Skip to content

Commit a17d437

Browse files
authored
feat(status): show uptime in chat status
Show compact Gateway process and host system uptime in chat /status output.
1 parent 5a8ccb6 commit a17d437

6 files changed

Lines changed: 49 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Docs: https://docs.openclaw.ai
1111
### Changes
1212

1313
- Gateway/Windows: bind the default loopback gateway listener only to `127.0.0.1` on Windows so libuv's dual-stack `::1` behavior cannot wedge localhost HTTP requests. (#69701, fixes #69674) Thanks @SARAMALI15792.
14+
- Status: show compact Gateway process uptime and host system uptime in `/status`, making restart and host-lifetime checks visible from chat. Thanks @vincentkoc.
1415
- Contributor PRs: require external pull requests to include after-fix real behavior proof from a real OpenClaw setup, with terminal screenshots, console output, redacted runtime logs, linked artifacts, and copied live output treated as valid evidence while unit tests, mocks, lint, typechecks, snapshots, and CI remain supplemental only.
1516
- Plugins/migration: emit catalog-backed install hints when `plugins.entries` or `plugins.allow` references an official external plugin that is not installed, so upgraded configs point operators to `openclaw plugins install <spec>` instead of telling them to remove valid plugin config. (#77483) Thanks @hclsys.
1617
- OpenAI/Codex media: advertise Codex audio transcription in runtime and manifest metadata and route active Codex chat models to the OpenAI transcription default instead of sending chat model ids to audio transcription. Thanks @vincentkoc.

docs/cli/status.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Notes:
2626
- Session status output separates `Execution:` from `Runtime:`. `Execution` is the sandbox path (`direct`, `docker/*`), while `Runtime` tells you whether the session is using `OpenClaw Pi Default`, `OpenAI Codex`, a CLI backend, or an ACP backend such as `codex (acp/acpx)`. See [Agent runtimes](/concepts/agent-runtimes) for the provider/model/runtime distinction.
2727
- MiniMax's raw `usage_percent` / `usagePercent` fields are remaining quota, so OpenClaw inverts them before display; count-based fields win when present. `model_remains` responses prefer the chat-model entry, derive the window label from timestamps when needed, and include the model name in the plan label.
2828
- When the current session snapshot is sparse, `/status` can backfill token and cache counters from the most recent transcript usage log. Existing nonzero live values still win over transcript fallback values.
29+
- `/status` includes compact Gateway process uptime and host system uptime.
2930
- Transcript fallback can also recover the active runtime model label when the live session entry is missing it. If that transcript model differs from the selected model, status resolves the context window against the recovered runtime model instead of the selected one.
3031
- For prompt-size accounting, transcript fallback prefers the larger prompt-oriented total when session metadata is missing or smaller, so custom-provider sessions do not collapse to `0` token displays.
3132
- Output includes per-agent session stores when multiple agents are configured.

docs/tools/slash-commands.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ Current source-of-truth:
152152
- `/help` shows the short help summary.
153153
- `/commands` shows the generated command catalog.
154154
- `/tools [compact|verbose]` shows what the current agent can use right now.
155-
- `/status` shows execution/runtime status, including `Execution`/`Runtime` labels and provider usage/quota when available.
155+
- `/status` shows execution/runtime status, Gateway and system uptime, plus provider usage/quota when available.
156156
- `/diagnostics [note]` is the owner-only support-report flow for Gateway bugs and Codex harness runs. It asks for explicit exec approval every time before running `openclaw gateway diagnostics export --json`; do not approve diagnostics with an allow-all rule. After approval, it sends a pasteable report with the local bundle path, manifest summary, privacy notes, and relevant session ids. In group chats, the approval prompt and report go to the owner privately. When the active session uses the OpenAI Codex harness, the same approval also sends relevant Codex feedback to OpenAI servers and the completed reply lists the OpenClaw session ids, Codex thread ids, and `codex resume <thread-id>` commands. See [Diagnostics Export](/gateway/diagnostics).
157157
- `/crestodian <request>` runs the Crestodian setup and repair helper from an owner DM.
158158
- `/tasks` lists active/recent background tasks for the current session.

src/auto-reply/reply/commands-status.test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,37 @@ describe("buildStatusReply subagent summary", () => {
494494
});
495495
});
496496

497+
it("shows gateway and system uptime in /status output", async () => {
498+
vi.spyOn(process, "uptime").mockReturnValue(2 * 60 * 60 + 5 * 60);
499+
vi.spyOn(os, "uptime").mockReturnValue(4 * 24 * 60 * 60 + 3 * 60 * 60);
500+
501+
const text = await buildStatusText({
502+
cfg: baseCfg,
503+
sessionEntry: {
504+
sessionId: "sess-status-uptime",
505+
updatedAt: 0,
506+
contextTokens: 32_000,
507+
},
508+
sessionKey: "agent:main:main",
509+
parentSessionKey: "agent:main:main",
510+
sessionScope: "per-sender",
511+
statusChannel: "mobilechat",
512+
provider: "anthropic",
513+
model: "claude-opus-4-5",
514+
contextTokens: 32_000,
515+
resolvedFastMode: false,
516+
resolvedVerboseLevel: "off",
517+
resolvedReasoningLevel: "off",
518+
resolveDefaultThinkingLevel: async () => undefined,
519+
isGroup: false,
520+
defaultGroupActivation: () => "mention",
521+
modelAuthOverride: "api-key",
522+
activeModelAuthOverride: "api-key",
523+
});
524+
525+
expect(normalizeTestText(text)).toContain("Uptime: gateway 2h 5m · system 4d 3h");
526+
});
527+
497528
it("shows the effective non-PI embedded harness in /status", async () => {
498529
registerStatusCodexHarness();
499530

src/status/status-message.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ export type StatusArgs = {
9797
activeModelAuth?: string;
9898
usageLine?: string;
9999
timeLine?: string;
100+
uptimeLine?: string;
100101
queue?: QueueStatus;
101102
mediaDecisions?: ReadonlyArray<MediaUnderstandingDecision>;
102103
subagentsLine?: string;
@@ -961,6 +962,7 @@ export function buildStatusMessage(args: StatusArgs): string {
961962
return [
962963
versionLine,
963964
args.timeLine,
965+
args.uptimeLine,
964966
modelLine,
965967
configuredFallbacksLine,
966968
fallbackLine,

src/status/status-text.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import os from "node:os";
12
import {
23
resolveAgentConfig,
34
resolveAgentDir,
@@ -18,6 +19,7 @@ import type { ThinkLevel } from "../auto-reply/thinking.js";
1819
import { toAgentModelListLike } from "../config/model-input.js";
1920
import type { SessionEntry } from "../config/sessions.js";
2021
import type { OpenClawConfig } from "../config/types.openclaw.js";
22+
import { formatDurationCompact } from "../infra/format-time/format-duration.ts";
2123
import {
2224
formatUsageWindowSummary,
2325
loadProviderUsageSummary,
@@ -156,6 +158,16 @@ function formatAgentTaskCountsLine(agentId: string): string | undefined {
156158
return `📌 Tasks: ${snapshot.activeCount} active · ${snapshot.totalCount} total · agent-local`;
157159
}
158160

161+
function formatStatusUptimeDuration(ms: number): string {
162+
return formatDurationCompact(ms, { spaced: true }) ?? "0s";
163+
}
164+
165+
export function buildStatusUptimeLine(): string {
166+
const gatewayUptimeMs = Math.max(0, Math.round(process.uptime() * 1000));
167+
const systemUptimeMs = Math.max(0, Math.round(os.uptime() * 1000));
168+
return `⏱️ Uptime: gateway ${formatStatusUptimeDuration(gatewayUptimeMs)} · system ${formatStatusUptimeDuration(systemUptimeMs)}`;
169+
}
170+
159171
export async function buildStatusText(params: BuildStatusTextParams): Promise<string> {
160172
const {
161173
cfg,
@@ -365,6 +377,7 @@ export async function buildStatusText(params: BuildStatusTextParams): Promise<st
365377
resolvedElevated: resolvedElevatedLevel,
366378
modelAuth: selectedModelAuth,
367379
activeModelAuth,
380+
uptimeLine: buildStatusUptimeLine(),
368381
usageLine: usageLine ?? undefined,
369382
queue: {
370383
mode: queueSettings.mode,

0 commit comments

Comments
 (0)