This commit is contained in:
quotentiroler
2026-02-08 03:48:36 -08:00
parent 27d135008c
commit aa2783a4f8
34 changed files with 59 additions and 61 deletions

View File

@@ -1,5 +1,6 @@
import type { AgentTool } from "@mariozechner/pi-agent-core";
import { Type } from "@sinclair/typebox";
import { formatDurationCompact } from "../infra/format-time/format-duration.ts";
import {
deleteSession,
drainSession,
@@ -10,7 +11,6 @@ import {
markExited,
setJobTtlMs,
} from "./bash-process-registry.js";
import { formatDurationCompact } from "../infra/format-duration.ts";
import {
deriveSessionName,
killSession,

View File

@@ -9,6 +9,7 @@ import {
resolveStorePath,
} from "../config/sessions.js";
import { callGateway } from "../gateway/call.js";
import { formatDurationCompact } from "../infra/format-time/format-duration.ts";
import { normalizeMainKey } from "../routing/session-key.js";
import { defaultRuntime } from "../runtime.js";
import {
@@ -22,7 +23,6 @@ import {
queueEmbeddedPiMessage,
waitForEmbeddedPiRunEnd,
} from "./pi-embedded.js";
import { formatDurationCompact } from "../infra/format-duration.ts";
import { type AnnounceQueueItem, enqueueAnnounce } from "./subagent-announce-queue.js";
import { readLatestAssistantReply } from "./tools/agent-step.js";

View File

@@ -6,8 +6,8 @@ import {
resolveTimezone,
formatUtcTimestamp,
formatZonedTimestamp,
} from "../infra/format-datetime.ts";
import { formatTimeAgo } from "../infra/format-relative.ts";
} from "../infra/format-time/format-datetime.ts";
import { formatTimeAgo } from "../infra/format-time/format-relative.ts";
export type AgentEnvelopeParams = {
channel: string;

View File

@@ -14,17 +14,13 @@ import {
import { loadSessionStore, resolveStorePath, updateSessionStore } from "../../config/sessions.js";
import { callGateway } from "../../gateway/call.js";
import { logVerbose } from "../../globals.js";
import { formatDurationCompact } from "../../infra/format-time/format-duration.ts";
import { formatTimeAgo } from "../../infra/format-time/format-relative.ts";
import { parseAgentSessionKey } from "../../routing/session-key.js";
import { INTERNAL_MESSAGE_CHANNEL } from "../../utils/message-channel.js";
import { stopSubagentsForRequester } from "./abort.js";
import { clearSessionQueues } from "./queue.js";
import {
formatRunLabel,
formatRunStatus,
sortSubagentRuns,
} from "./subagents-utils.js";
import { formatDurationCompact } from "../../infra/format-duration.ts";
import { formatTimeAgo } from "../../infra/format-relative.ts";
import { formatRunLabel, formatRunStatus, sortSubagentRuns } from "./subagents-utils.js";
type SubagentTargetResolution = {
entry?: SubagentRunRecord;

View File

@@ -9,7 +9,7 @@ import {
resolveTimezone,
formatUtcTimestamp,
formatZonedTimestamp,
} from "../../infra/format-datetime.ts";
} from "../../infra/format-time/format-datetime.ts";
import { getRemoteSkillEligibility } from "../../infra/skills-remote.js";
import { drainSystemEventEntries } from "../../infra/system-events.js";
@@ -78,9 +78,7 @@ export async function prependSystemEvents(params: {
if (zone.mode === "local") {
return formatZonedTimestamp(date, { seconds: true }) ?? "unknown-time";
}
return (
formatZonedTimestamp(date, { timeZone: zone.timeZone, seconds: true }) ?? "unknown-time"
);
return formatZonedTimestamp(date, { timeZone: zone.timeZone, seconds: true }) ?? "unknown-time";
};
const systemLines: string[] = [];

View File

@@ -1,6 +1,6 @@
import { describe, expect, it } from "vitest";
import type { SubagentRunRecord } from "../../agents/subagent-registry.js";
import { formatDurationCompact } from "../../infra/format-duration.js";
import { formatDurationCompact } from "../../infra/format-time/format-duration.js";
import {
formatRunLabel,
formatRunStatus,

View File

@@ -10,13 +10,13 @@ import { resolveModelAuthMode } from "../agents/model-auth.js";
import { resolveConfiguredModelRef } from "../agents/model-selection.js";
import { resolveSandboxRuntimeStatus } from "../agents/sandbox.js";
import { derivePromptTokens, normalizeUsage, type UsageLike } from "../agents/usage.js";
import { formatTimeAgo } from "../infra/format-relative.ts";
import {
resolveMainSessionKey,
resolveSessionFilePath,
type SessionEntry,
type SessionScope,
} from "../config/sessions.js";
import { formatTimeAgo } from "../infra/format-time/format-relative.ts";
import { resolveCommitHash } from "../infra/git-commit.js";
import { listPluginCommands } from "../plugins/commands.js";
import {
@@ -135,7 +135,6 @@ export const formatContextUsageShort = (
contextTokens: number | null | undefined,
) => `Context ${formatTokens(total, contextTokens ?? null)}`;
const formatQueueDetails = (queue?: QueueStatus) => {
if (!queue) {
return "";

View File

@@ -2,7 +2,7 @@ import type { CronJob, CronSchedule } from "../../cron/types.js";
import type { GatewayRpcOpts } from "../gateway-rpc.js";
import { listChannelPlugins } from "../../channels/plugins/index.js";
import { parseAbsoluteTimeMs } from "../../cron/parse.js";
import { formatDurationHuman } from "../../infra/format-duration.ts";
import { formatDurationHuman } from "../../infra/format-time/format-duration.ts";
import { defaultRuntime } from "../../runtime.js";
import { colorize, isRich, theme } from "../../terminal/theme.js";
import { callGatewayFromCli } from "../gateway-rpc.js";

View File

@@ -1,6 +1,6 @@
import type { Command } from "commander";
import { callGateway } from "../gateway/call.js";
import { formatTimeAgo } from "../infra/format-relative.ts";
import { formatTimeAgo } from "../infra/format-time/format-relative.ts";
import { defaultRuntime } from "../runtime.js";
import { renderTable } from "../terminal/table.js";
import { theme } from "../terminal/theme.js";

View File

@@ -8,7 +8,7 @@ import {
type ExecApprovalsAgent,
type ExecApprovalsFile,
} from "../infra/exec-approvals.js";
import { formatTimeAgo } from "../infra/format-relative.ts";
import { formatTimeAgo } from "../infra/format-time/format-relative.ts";
import { defaultRuntime } from "../runtime.js";
import { formatDocsLink } from "../terminal/links.js";
import { renderTable } from "../terminal/table.js";
@@ -32,8 +32,6 @@ type ExecApprovalsCliOpts = NodesRpcOpts & {
agent?: string;
};
async function readStdin(): Promise<string> {
const chunks: Buffer[] = [];
for await (const chunk of process.stdin) {

View File

@@ -1,10 +1,10 @@
import type { Command } from "commander";
import type { NodesRpcOpts } from "./types.js";
import { formatTimeAgo } from "../../infra/format-time/format-relative.ts";
import { defaultRuntime } from "../../runtime.js";
import { renderTable } from "../../terminal/table.js";
import { getNodesTheme, runNodesCommand } from "./cli-utils.js";
import { parsePairingList } from "./format.js";
import { formatTimeAgo } from "../../infra/format-relative.ts";
import { callGatewayCli, nodesCallOpts, resolveNodeId } from "./rpc.js";
export function registerNodesPairingCommands(nodes: Command) {
@@ -33,9 +33,7 @@ export function registerNodesPairingCommands(nodes: Command) {
Node: r.displayName?.trim() ? r.displayName.trim() : r.nodeId,
IP: r.remoteIp ?? "",
Requested:
typeof r.ts === "number"
? formatTimeAgo(Math.max(0, now - r.ts))
: muted("unknown"),
typeof r.ts === "number" ? formatTimeAgo(Math.max(0, now - r.ts)) : muted("unknown"),
Repair: r.isRepair ? warn("yes") : "",
}));
defaultRuntime.log(heading("Pending"));

View File

@@ -1,12 +1,12 @@
import type { Command } from "commander";
import type { NodesRpcOpts } from "./types.js";
import { formatTimeAgo } from "../../infra/format-time/format-relative.ts";
import { defaultRuntime } from "../../runtime.js";
import { renderTable } from "../../terminal/table.js";
import { shortenHomeInString } from "../../utils.js";
import { parseDurationMs } from "../parse-duration.js";
import { getNodesTheme, runNodesCommand } from "./cli-utils.js";
import { formatPermissions, parseNodeList, parsePairingList } from "./format.js";
import { formatTimeAgo } from "../../infra/format-relative.ts";
import { callGatewayCli, nodesCallOpts, resolveNodeId } from "./rpc.js";
function formatVersionLabel(raw: string) {
@@ -398,7 +398,7 @@ export function registerNodesStatusCommands(nodes: Command) {
IP: n.remoteIp ?? "",
LastConnect:
typeof lastConnectedAtMs === "number"
? formatTimeAgo(Math.max(0, now - lastConnectedAtMs))
? formatTimeAgo(Math.max(0, now - lastConnectedAtMs))
: muted("unknown"),
};
});

View File

@@ -16,6 +16,7 @@ import {
} from "../commands/status.update.js";
import { readConfigFileSnapshot, writeConfigFile } from "../config/config.js";
import { resolveStateDir } from "../config/paths.js";
import { formatDurationPrecise } from "../infra/format-time/format-duration.ts";
import { resolveOpenClawPackageRoot } from "../infra/openclaw-root.js";
import { trimLogTail } from "../infra/restart-sentinel.js";
import { parseSemver } from "../infra/runtime-guard.js";
@@ -48,7 +49,6 @@ import {
type UpdateStepResult,
type UpdateStepProgress,
} from "../infra/update-runner.js";
import { formatDurationPrecise } from "../infra/format-duration.ts";
import { syncPluginsForUpdateChannel, updateNpmInstalledPlugins } from "../plugins/update.js";
import { runCommandWithTimeout } from "../process/exec.js";
import { defaultRuntime } from "../runtime.js";

View File

@@ -5,8 +5,8 @@ import { formatCliCommand } from "../../cli/command-format.js";
import { withProgress } from "../../cli/progress.js";
import { type OpenClawConfig, readConfigFileSnapshot } from "../../config/config.js";
import { callGateway } from "../../gateway/call.js";
import { formatTimeAgo } from "../../infra/format-relative.ts";
import { collectChannelStatusIssues } from "../../infra/channels-status-issues.js";
import { formatTimeAgo } from "../../infra/format-time/format-relative.ts";
import { defaultRuntime, type RuntimeEnv } from "../../runtime.js";
import { formatDocsLink } from "../../terminal/links.js";
import { theme } from "../../terminal/theme.js";

View File

@@ -5,12 +5,8 @@
import type { SandboxBrowserInfo, SandboxContainerInfo } from "../agents/sandbox.js";
import type { RuntimeEnv } from "../runtime.js";
import { formatCliCommand } from "../cli/command-format.js";
import { formatDurationCompact } from "../infra/format-duration.ts";
import {
formatImageMatch,
formatSimpleStatus,
formatStatus,
} from "./sandbox-formatters.js";
import { formatDurationCompact } from "../infra/format-time/format-duration.ts";
import { formatImageMatch, formatSimpleStatus, formatStatus } from "./sandbox-formatters.js";
type DisplayConfig<T> = {
emptyMessage: string;
@@ -40,8 +36,12 @@ export function displayContainers(containers: SandboxContainerInfo[], runtime: R
rt.log(` ${container.containerName}`);
rt.log(` Status: ${formatStatus(container.running)}`);
rt.log(` Image: ${container.image} ${formatImageMatch(container.imageMatch)}`);
rt.log(` Age: ${(formatDurationCompact(Date.now() - container.createdAtMs, { spaced: true }) ?? "0s")}`);
rt.log(` Idle: ${(formatDurationCompact(Date.now() - container.lastUsedAtMs, { spaced: true }) ?? "0s")}`);
rt.log(
` Age: ${formatDurationCompact(Date.now() - container.createdAtMs, { spaced: true }) ?? "0s"}`,
);
rt.log(
` Idle: ${formatDurationCompact(Date.now() - container.lastUsedAtMs, { spaced: true }) ?? "0s"}`,
);
rt.log(` Session: ${container.sessionKey}`);
rt.log("");
},
@@ -64,8 +64,12 @@ export function displayBrowsers(browsers: SandboxBrowserInfo[], runtime: Runtime
if (browser.noVncPort) {
rt.log(` noVNC: ${browser.noVncPort}`);
}
rt.log(` Age: ${(formatDurationCompact(Date.now() - browser.createdAtMs, { spaced: true }) ?? "0s")}`);
rt.log(` Idle: ${(formatDurationCompact(Date.now() - browser.lastUsedAtMs, { spaced: true }) ?? "0s")}`);
rt.log(
` Age: ${formatDurationCompact(Date.now() - browser.createdAtMs, { spaced: true }) ?? "0s"}`,
);
rt.log(
` Idle: ${formatDurationCompact(Date.now() - browser.lastUsedAtMs, { spaced: true }) ?? "0s"}`,
);
rt.log(` Session: ${browser.sessionKey}`);
rt.log("");
},

View File

@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import { formatDurationCompact } from "../infra/format-duration.js";
import { formatDurationCompact } from "../infra/format-time/format-duration.js";
import {
countMismatches,
countRunning,

View File

@@ -5,7 +5,7 @@ import { resolveConfiguredModelRef } from "../agents/model-selection.js";
import { loadConfig } from "../config/config.js";
import { loadSessionStore, resolveStorePath, type SessionEntry } from "../config/sessions.js";
import { info } from "../globals.js";
import { formatTimeAgo } from "../infra/format-relative.ts";
import { formatTimeAgo } from "../infra/format-time/format-relative.ts";
import { isRich, theme } from "../terminal/theme.js";
type SessionRow = {

View File

@@ -1,5 +1,5 @@
export { formatTimeAgo } from "../../infra/format-relative.ts";
export { formatDurationPrecise } from "../../infra/format-duration.ts";
export { formatTimeAgo } from "../../infra/format-time/format-relative.ts";
export { formatDurationPrecise } from "../../infra/format-time/format-duration.ts";
export function formatGatewayAuthUsed(
auth: {

View File

@@ -5,6 +5,7 @@ import { withProgress } from "../cli/progress.js";
import { resolveGatewayPort } from "../config/config.js";
import { buildGatewayConnectionDetails, callGateway } from "../gateway/call.js";
import { info } from "../globals.js";
import { formatTimeAgo } from "../infra/format-time/format-relative.ts";
import { formatUsageReportLines, loadProviderUsageSummary } from "../infra/provider-usage.js";
import {
formatUpdateChannelLabel,
@@ -31,7 +32,6 @@ import {
formatTokensCompact,
shortenText,
} from "./status.format.js";
import { formatTimeAgo } from "../infra/format-relative.ts";
import { resolveGatewayProbeAuth } from "./status.gateway-probe.js";
import { scanStatus } from "./status.scan.js";
import {

View File

@@ -1,5 +1,5 @@
import type { SessionStatus } from "./status.types.js";
import { formatDurationPrecise } from "../infra/format-duration.ts";
import { formatDurationPrecise } from "../infra/format-time/format-duration.ts";
export const formatKTokens = (value: number) =>
`${(value / 1000).toFixed(value >= 10_000 ? 0 : 1)}k`;

View File

@@ -7,7 +7,7 @@ import {
PresenceUpdateListener,
} from "@buape/carbon";
import { danger } from "../../globals.js";
import { formatDurationSeconds } from "../../infra/format-duration.ts";
import { formatDurationSeconds } from "../../infra/format-time/format-duration.ts";
import { enqueueSystemEvent } from "../../infra/system-events.js";
import { createSubsystemLogger } from "../../logging/subsystem.js";
import { resolveAgentRoute } from "../../routing/resolve-route.js";

View File

@@ -1,5 +1,5 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { formatZonedTimestamp } from "../../infra/format-datetime.js";
import { formatZonedTimestamp } from "../../infra/format-time/format-datetime.js";
import { injectTimestamp, timestampOptsFromConfig } from "./agent-timestamp.js";
describe("injectTimestamp", () => {

View File

@@ -1,6 +1,6 @@
import type { OpenClawConfig } from "../../config/types.js";
import { resolveUserTimezone } from "../../agents/date-time.js";
import { formatZonedTimestamp } from "../../infra/format-datetime.ts";
import { formatZonedTimestamp } from "../../infra/format-time/format-datetime.ts";
/**
* Cron jobs inject "Current time: ..." into their messages.

View File

@@ -1,9 +1,9 @@
import type { ChannelAccountSnapshot, ChannelPlugin } from "../channels/plugins/types.js";
import { listChannelPlugins } from "../channels/plugins/index.js";
import { type OpenClawConfig, loadConfig } from "../config/config.js";
import { formatTimeAgo } from "./format-relative.ts";
import { DEFAULT_ACCOUNT_ID } from "../routing/session-key.js";
import { theme } from "../terminal/theme.js";
import { formatTimeAgo } from "./format-time/format-relative.ts";
export type ChannelSummaryOptions = {
colorize?: boolean;

View File

@@ -5,7 +5,7 @@ import { resolveAgentMaxConcurrent } from "../config/agent-limits.js";
import { loadConfig } from "../config/config.js";
import { computeBackoff, sleepWithAbort } from "../infra/backoff.js";
import { formatErrorMessage } from "../infra/errors.js";
import { formatDurationPrecise } from "../infra/format-duration.ts";
import { formatDurationPrecise } from "../infra/format-time/format-duration.ts";
import { registerUnhandledRejectionHandler } from "../infra/unhandled-rejections.js";
import { resolveTelegramAccount } from "./accounts.js";
import { resolveTelegramAllowedUpdates } from "./allowed-updates.js";

View File

@@ -14,8 +14,8 @@ import {
normalizeUsageDisplay,
resolveResponseUsageMode,
} from "../auto-reply/thinking.js";
import { formatRelativeTimestamp } from "../infra/format-time/format-relative.ts";
import { normalizeAgentId } from "../routing/session-key.js";
import { formatRelativeTimestamp } from "../infra/format-relative.ts";
import { helpText, parseCommand } from "./commands.js";
import {
createFilterableSelectList,
@@ -158,7 +158,9 @@ export function createCommandHandlers(context: CommandHandlerContext) {
// Avoid redundant "title (key)" when title matches key
const label = title && title !== formattedKey ? `${title} (${formattedKey})` : formattedKey;
// Build description: time + message preview
const timePart = session.updatedAt ? formatRelativeTimestamp(session.updatedAt, { dateFallback: true, fallback: "" }) : "";
const timePart = session.updatedAt
? formatRelativeTimestamp(session.updatedAt, { dateFallback: true, fallback: "" })
: "";
const preview = session.lastMessagePreview?.replace(/\s+/g, " ").trim();
const description =
timePart && preview ? `${timePart} · ${preview}` : (preview ?? timePart);

View File

@@ -1,5 +1,5 @@
import type { GatewayStatusSummary } from "./tui-types.js";
import { formatTimeAgo } from "../infra/format-relative.ts";
import { formatTimeAgo } from "../infra/format-time/format-relative.ts";
import { formatTokenCount } from "../utils/usage-format.js";
import { formatContextUsageLine } from "./tui-formatters.js";

View File

@@ -1,4 +1,4 @@
import { formatRelativeTimestamp } from "../infra/format-relative.ts";
import { formatRelativeTimestamp } from "../infra/format-time/format-relative.ts";
/** Delegates to centralized formatRelativeTimestamp with date fallback for >7d. */
export function formatRelativeTime(timestamp: number): string {

View File

@@ -7,7 +7,7 @@ import { formatCliCommand } from "../../cli/command-format.js";
import { waitForever } from "../../cli/wait.js";
import { loadConfig } from "../../config/config.js";
import { logVerbose } from "../../globals.js";
import { formatDurationPrecise } from "../../infra/format-duration.ts";
import { formatDurationPrecise } from "../../infra/format-time/format-duration.ts";
import { enqueueSystemEvent } from "../../infra/system-events.js";
import { registerUnhandledRejectionHandler } from "../../infra/unhandled-rejections.js";
import { getChildLogger } from "../../logging.js";

View File

@@ -1,5 +1,5 @@
import { formatDurationHuman } from "../../../src/infra/format-duration.ts";
import { formatRelativeTimestamp } from "../../../src/infra/format-relative.ts";
import { formatDurationHuman } from "../../../src/infra/format-time/format-duration.ts";
import { formatRelativeTimestamp } from "../../../src/infra/format-time/format-relative.ts";
import { stripReasoningTagsFromText } from "../../../src/shared/text/reasoning-tags.js";
export { formatRelativeTimestamp, formatDurationHuman };

View File

@@ -1,5 +1,5 @@
import { html, svg, nothing } from "lit";
import { formatDurationCompact } from "../../../../src/infra/format-duration.ts";
import { formatDurationCompact } from "../../../../src/infra/format-time/format-duration.ts";
import { extractQueryTerms, filterSessionsByQuery, parseToolSummary } from "../usage-helpers.ts";
// Inline styles for usage view (app uses light DOM, so static styles don't work)
@@ -3438,7 +3438,10 @@ function renderUsageInsights(
stats.throughputCostPerMin !== undefined
? `${formatCost(stats.throughputCostPerMin, 4)} / min`
: "—";
const avgDurationLabel = stats.durationCount > 0 ? (formatDurationCompact(stats.avgDurationMs, { spaced: true }) ?? "—") : "—";
const avgDurationLabel =
stats.durationCount > 0
? (formatDurationCompact(stats.avgDurationMs, { spaced: true }) ?? "—")
: "—";
const cacheHint = "Cache hit rate = cache read / (input + cache read). Higher is better.";
const errorHint = "Error rate = errors / total messages. Lower is better.";
const throughputHint = "Throughput shows tokens per minute over active time. Higher is better.";