openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
609 lines (608 loc) • 32.4 kB
JavaScript
import { l as asNonNegativeFiniteNumber } from "./number-coercion-CLj0HTDM.js";
import { c as normalizeOptionalLowercaseString, l as normalizeOptionalString, o as normalizeLowercaseStringOrEmpty } from "./string-coerce-CIXf7egm.js";
import { f as resolveAgentIdFromSessionKey } from "./session-key-BnWWjqNc.js";
import { c as resolveRuntimeServiceCommit, t as VERSION } from "./version-v1kuAkGj.js";
import { g as resolveConfiguredModelRef, i as buildModelAliasIndex, x as findModelInCatalog, y as resolveModelRefFromString } from "./model-selection-shared-BlLyx1r2.js";
import { n as DEFAULT_MODEL, r as DEFAULT_PROVIDER } from "./defaults-CdX9UGcX.js";
import { D as hasUserPinnedModelSelection, E as hasSessionAutoModelFallbackProvenance, T as hasSessionActiveAutoModelFallback } from "./agent-scope-DbtJyKUL.js";
import { d as sessionDeliveryChannel, f as sessionDeliveryOrigin } from "./delivery-context.shared-CXmRgetN.js";
import { c as resolveSessionPluginTraceLines, o as resolveFreshSessionTotalTokens, s as resolveSessionPluginStatusLines } from "./types-BHV0IaPK.js";
import { a as resolveMainSessionKey } from "./main-session-Br0F9dzh.js";
import { t as formatDurationCompact } from "./format-duration-CeDWULoS.js";
import { c as shouldPreferActiveRuntimeAliasAuthLabel, t as areRuntimeModelRefsEquivalent } from "./model-runtime-aliases-BJ2qM8I_.js";
import { o as resolveModelAuthMode } from "./model-auth-C48_DZ-I.js";
import "./model-selection-di2kjKCB.js";
import { o as formatFastModeStatusValue } from "./fast-mode-CCX0YiYh.js";
import { t as formatTokenCount } from "./token-format-D942KbWN.js";
import "./sessions-9nxpeTwt.js";
import { d as resolveSessionLifecycleTimestamps } from "./lifecycle-BaroCBMc.js";
import { t as resolveProjectedSessionContextTokens } from "./context-token-provenance-CAdnGN1p.js";
import { a as resolveModelCostConfig, r as formatUsd, t as estimateAggregateUsageCost } from "./usage-format-DhUP1uYp.js";
import { n as resolveSandboxRuntimeStatus } from "./runtime-status-6c8Jb1Kg.js";
import { t as resolveStatusTtsSnapshot } from "./status-config-wwgdsC-4.js";
import "./sandbox-A2KOznlu.js";
import { S as resolveOpenAITextVerbosity } from "./proxy-WJH2VPqG.js";
import { i as resolveExtraParams } from "./extra-params-UGKIp88L.js";
import { r as readRecentSessionUsageFromTranscript } from "./session-transcript-readers-CYDRQsH5.js";
import { c as resolveAuthoredModelContextTokens } from "./context-resolution-DlNIXncb.js";
import { a as resolveContextTokensForModel } from "./context-B0EuZFRZ.js";
import { t as resolveFastModeState } from "./fast-mode-CTXu8q8K.js";
import { n as resolveSelectedAndActiveModel, t as formatProviderModelRef } from "./model-runtime-BzIef07I.js";
import { t as resolveActiveFallbackState } from "./fallback-notice-state-CyRMuzrq.js";
import { n as resolveCronStyleNow } from "./current-time-Cwxy-JQb.js";
import { t as resolveChannelModelOverride } from "./model-overrides-DPMkS7yu.js";
import { n as findDecisionReason, s as summarizeDecisionReason } from "./runner.entries-B6FlBFiO.js";
import { t as resolveAgentRuntimeLabel } from "./agent-runtime-label-BA4eUY6k.js";
import { n as formatTimeAgo } from "./format-relative-DiD6ocfu.js";
//#region src/status/status-message.ts
function normalizeAuthMode(value) {
const normalized = normalizeOptionalLowercaseString(value);
if (!normalized) return;
if (normalized === "api-key" || normalized.startsWith("api-key ")) return "api-key";
if (normalized === "oauth" || normalized.startsWith("oauth ")) return "oauth";
if (normalized === "token" || normalized.startsWith("token ")) return "token";
if (normalized === "aws-sdk" || normalized.startsWith("aws-sdk ")) return "aws-sdk";
if (normalized === "native" || normalized.startsWith("native ")) return "native";
if (normalized === "mixed" || normalized.startsWith("mixed ")) return "mixed";
if (normalized === "unknown") return "unknown";
}
function resolveConfiguredTextVerbosity(params) {
const provider = params.provider?.trim();
const model = params.model?.trim();
if (!provider || !model || provider !== "openai") return;
return resolveOpenAITextVerbosity(resolveExtraParams({
cfg: params.config,
provider,
modelId: model,
agentId: params.agentId
}));
}
function resolveExecutionLabel(args) {
const sessionKey = args.sessionKey?.trim();
if (args.config && sessionKey) {
const runtimeStatus = resolveSandboxRuntimeStatus({
cfg: args.config,
sessionKey,
agentId: args.agentId
});
const sandboxMode = runtimeStatus.mode ?? "off";
if (sandboxMode === "off") return "direct";
return `${runtimeStatus.sandboxed ? "docker" : sessionKey ? "direct" : "unknown"}/${sandboxMode}`;
}
const sandboxMode = args.agent?.sandbox?.mode ?? "off";
if (sandboxMode === "off") return "direct";
return `${(() => {
if (!sessionKey) return false;
if (sandboxMode === "all") return true;
const sessionScope = args.sessionScope ?? "per-sender";
const mainKey = resolveMainSessionKey({ session: { scope: sessionScope } });
return sessionKey !== mainKey.trim();
})() ? "docker" : sessionKey ? "direct" : "unknown"}/${sandboxMode}`;
}
const formatTokens = (total, contextTokens) => {
const ctx = contextTokens ?? null;
if (total == null) return `?/${ctx ? formatTokenCount(ctx) : "?"}`;
const pct = ctx ? Math.min(999, Math.round(total / ctx * 100)) : null;
return `${formatTokenCount(total)}/${ctx ? formatTokenCount(ctx) : "?"}${pct !== null ? ` (${pct}%)` : ""}`;
};
const formatEstimatedContextBudgetTokens = (status, contextTokens) => {
if (!status || status.source !== "pre-prompt-estimate") return null;
const estimatedPromptTokens = typeof status.estimatedPromptTokens === "number" && Number.isFinite(status.estimatedPromptTokens) && status.estimatedPromptTokens >= 0 ? Math.floor(status.estimatedPromptTokens) : void 0;
if (estimatedPromptTokens === void 0) return null;
const ctx = typeof contextTokens === "number" && Number.isFinite(contextTokens) && contextTokens > 0 ? contextTokens : typeof status.contextTokenBudget === "number" && Number.isFinite(status.contextTokenBudget) && status.contextTokenBudget > 0 ? status.contextTokenBudget : void 0;
const pct = ctx ? Math.min(999, Math.round(estimatedPromptTokens / ctx * 100)) : null;
return `~${formatTokenCount(estimatedPromptTokens)}/${ctx ? formatTokenCount(ctx) : "?"}${pct !== null ? ` (${pct}% est)` : " (est)"}`;
};
const formatContextUsageShort = (total, contextTokens) => `Context ${formatTokens(total, contextTokens ?? null)}`;
const formatQueueDetails = (queue) => {
if (!queue) return "";
const depth = typeof queue.depth === "number" ? `depth ${queue.depth}` : null;
if (!queue.showDetails) return depth ? ` (${depth})` : "";
const detailParts = [];
if (depth) detailParts.push(depth);
if (typeof queue.debounceMs === "number") {
const ms = Math.max(0, Math.round(queue.debounceMs));
const label = ms >= 1e3 ? `${ms % 1e3 === 0 ? ms / 1e3 : (ms / 1e3).toFixed(1)}s` : `${ms}ms`;
detailParts.push(`debounce ${label}`);
}
if (typeof queue.cap === "number") detailParts.push(`cap ${queue.cap}`);
if (queue.dropPolicy) detailParts.push(`drop ${queue.dropPolicy}`);
return detailParts.length ? ` (${detailParts.join(" · ")})` : "";
};
const readUsageFromSessionLog = (sessionId, sessionEntry, agentId, sessionKey, storePath) => {
if (!sessionId) return;
try {
const resolvedAgentId = agentId ?? (sessionKey ? resolveAgentIdFromSessionKey(sessionKey) : void 0);
const snapshot = readRecentSessionUsageFromTranscript({
agentId: resolvedAgentId,
sessionEntry,
sessionId,
sessionKey,
storePath
}, 262144);
if (!snapshot) return;
const input = snapshot.inputTokens ?? 0;
const output = snapshot.outputTokens ?? 0;
const cacheRead = snapshot.cacheRead ?? 0;
const cacheWrite = snapshot.cacheWrite ?? 0;
const promptTokens = snapshot.totalTokens ?? input + cacheRead + cacheWrite;
const total = promptTokens + output;
if (promptTokens === 0 && total === 0) return;
const model = snapshot.modelProvider ? snapshot.model ? `${snapshot.modelProvider}/${snapshot.model}` : snapshot.modelProvider : snapshot.model;
return {
input,
output,
cacheRead,
cacheWrite,
promptTokens,
total,
totalTokensFresh: snapshot.totalTokensFresh === true,
model
};
} catch {
return;
}
};
const formatTokensPairValue = (input, output) => {
if (input == null && output == null) return null;
return `${typeof input === "number" ? formatTokenCount(input) : "?"} in / ${typeof output === "number" ? formatTokenCount(output) : "?"} out`;
};
const formatCacheHitValue = (input, cacheRead, cacheWrite) => {
if (!cacheRead && !cacheWrite) return null;
if ((typeof cacheRead !== "number" || cacheRead <= 0) && (typeof cacheWrite !== "number" || cacheWrite <= 0)) return null;
const cachedLabel = typeof cacheRead === "number" ? formatTokenCount(cacheRead) : "0";
const newLabel = typeof cacheWrite === "number" ? formatTokenCount(cacheWrite) : "0";
const totalInput = (typeof cacheRead === "number" ? cacheRead : 0) + (typeof cacheWrite === "number" ? cacheWrite : 0) + (typeof input === "number" ? input : 0);
return `${totalInput > 0 && typeof cacheRead === "number" ? Math.round(cacheRead / totalInput * 100) : 0}% hit · ${cachedLabel} cached, ${newLabel} new`;
};
const formatMediaUnderstandingLine = (decisions) => {
if (!decisions || decisions.length === 0) return null;
const parts = decisions.map((decision) => {
const count = decision.attachments.length;
const countLabel = count > 1 ? ` x${count}` : "";
if (decision.outcome === "success") {
const chosen = decision.attachments.find((entry) => entry.chosen)?.chosen;
const provider = chosen?.provider?.trim();
const model = chosen?.model?.trim();
const modelLabel = provider ? model && model !== provider ? `${provider}/${model}` : provider : null;
const backendLabel = chosen?.observedBackend ? ` observed=${chosen.observedBackend}` : chosen?.requestedBackend ? ` requested=${chosen.requestedBackend}` : "";
return `${decision.capability}${countLabel} ok${modelLabel ? ` (${modelLabel}${backendLabel})` : ""}`;
}
if (decision.outcome === "no-attachment") return `${decision.capability} none`;
if (decision.outcome === "disabled") return `${decision.capability} off`;
if (decision.outcome === "scope-deny") return `${decision.capability} denied`;
if (decision.outcome === "skipped") {
const reason = findDecisionReason(decision);
const shortReason = summarizeDecisionReason(reason);
return `${decision.capability} skipped${shortReason ? ` (${shortReason})` : ""}`;
}
if (decision.outcome === "failed") {
const reason = findDecisionReason(decision, "failed");
const shortReason = summarizeDecisionReason(reason);
return `${decision.capability} failed${shortReason ? ` (${shortReason})` : ""}`;
}
return null;
}).filter((part) => part != null);
if (parts.length === 0) return null;
if (parts.every((part) => part.endsWith(" none"))) return null;
return `📎 Media: ${parts.join(" · ")}`;
};
const formatVoiceModeLine = (config, sessionEntry, agentId) => {
if (!config) return null;
const snapshot = resolveStatusTtsSnapshot({
cfg: config,
sessionAuto: sessionEntry?.ttsAuto,
agentId
});
if (!snapshot) return null;
const parts = [`🔊 Voice: ${snapshot.autoMode}`, `provider=${snapshot.provider}`];
if (snapshot.persona) parts.push(`persona=${snapshot.persona}`);
if (snapshot.displayName) parts.push(`name=${snapshot.displayName}`);
if (snapshot.model) parts.push(`model=${snapshot.model}`);
if (snapshot.voice) parts.push(`voice=${snapshot.voice}`);
if (snapshot.baseUrl) parts.push(snapshot.customBaseUrl ? `endpoint=custom(${snapshot.baseUrl})` : `endpoint=${snapshot.baseUrl}`);
parts.push(`limit=${snapshot.maxLength}`, `summary=${snapshot.summarize ? "on" : "off"}`);
return parts.join(" · ");
};
function resolveChannelModelNote(params) {
if (!params.config || !params.entry) return;
if (normalizeOptionalString(params.entry.modelOverride) || normalizeOptionalString(params.entry.providerOverride)) return;
const channelOverride = resolveChannelModelOverride({
cfg: params.config,
channel: sessionDeliveryChannel(params.entry),
groupId: params.entry.groupId,
groupChatType: params.entry.chatType ?? sessionDeliveryOrigin(params.entry)?.chatType,
groupChannel: params.entry.groupChannel,
groupSubject: params.entry.subject,
parentSessionKey: params.parentSessionKey,
directUserIds: [
sessionDeliveryOrigin(params.entry)?.nativeDirectUserId,
sessionDeliveryOrigin(params.entry)?.from,
sessionDeliveryOrigin(params.entry)?.to
]
});
if (!channelOverride) return;
const aliasIndex = buildModelAliasIndex({
cfg: params.config,
defaultProvider: DEFAULT_PROVIDER,
allowPluginNormalization: false
});
const resolvedOverride = resolveModelRefFromString({
raw: channelOverride.model,
defaultProvider: DEFAULT_PROVIDER,
aliasIndex,
allowPluginNormalization: false
});
if (!resolvedOverride) return;
if (resolvedOverride.ref.provider !== params.selectedProvider || resolvedOverride.ref.model !== params.selectedModel) return;
return "channel override";
}
function buildStatusMessage(args) {
return buildStatusMessageParts(args).text;
}
function buildStatusMessageParts(args) {
const now = args.now ?? Date.now();
const cronNow = args.config ? resolveCronStyleNow(args.config, now) : void 0;
const timeLine = args.timeLine ?? cronNow?.timeLine;
const uptimeLine = args.uptimeValue ? `⏱️ Uptime: ${args.uptimeValue}` : void 0;
const entry = args.sessionEntry;
const selectionConfig = { agents: { defaults: args.agent ?? {} } };
const contextConfig = args.config ? {
...args.config,
agents: {
...args.config.agents,
defaults: {
...args.config.agents?.defaults,
...args.agent
}
}
} : { agents: { defaults: args.agent ?? {} } };
const resolved = resolveConfiguredModelRef({
cfg: selectionConfig,
defaultProvider: DEFAULT_PROVIDER,
defaultModel: DEFAULT_MODEL,
allowPluginNormalization: false
});
const selectedProvider = entry?.providerOverride ?? resolved.provider ?? "openai";
const selectedModel = entry?.modelOverride ?? resolved.model ?? "gpt-5.6-sol";
const parseSelectedProvider = Boolean(entry?.modelOverride?.trim() && !entry?.providerOverride?.trim());
const modelRefs = resolveSelectedAndActiveModel({
selectedProvider,
selectedModel,
sessionEntry: entry,
parseSelectedProvider
});
const selectedLookupProvider = modelRefs.selected.provider || selectedProvider;
const selectedLookupModel = modelRefs.selected.model || selectedModel;
const initialFallbackState = resolveActiveFallbackState({
selectedModelRef: modelRefs.selected.label || "unknown",
activeModelRef: modelRefs.active.label || "unknown",
config: args.config,
state: entry
});
let activeProvider = modelRefs.active.provider;
let activeModel = modelRefs.active.model;
let contextLookupProvider = activeProvider;
let contextLookupModel = activeModel;
const runtimeModelRaw = normalizeOptionalString(entry?.model) ?? "";
const runtimeProviderRaw = normalizeOptionalString(entry?.modelProvider) ?? "";
if (runtimeModelRaw && !runtimeProviderRaw && runtimeModelRaw.includes("/")) {
const slashIndex = runtimeModelRaw.indexOf("/");
const embeddedProvider = normalizeOptionalLowercaseString(runtimeModelRaw.slice(0, slashIndex)) ?? "";
const fallbackMatchesRuntimeModel = initialFallbackState.active && normalizeLowercaseStringOrEmpty(runtimeModelRaw) === normalizeLowercaseStringOrEmpty(normalizeOptionalString(entry?.fallbackNotice?.activeModel ?? "") ?? "");
const runtimeMatchesSelectedModel = normalizeLowercaseStringOrEmpty(runtimeModelRaw) === normalizeLowercaseStringOrEmpty(modelRefs.selected.label || "unknown");
if ((fallbackMatchesRuntimeModel || runtimeMatchesSelectedModel) && embeddedProvider === normalizeLowercaseStringOrEmpty(activeProvider)) {
contextLookupProvider = activeProvider;
contextLookupModel = activeModel;
} else {
contextLookupProvider = void 0;
contextLookupModel = runtimeModelRaw;
}
}
let inputTokens = entry?.inputTokens;
let outputTokens = entry?.outputTokens;
let cacheRead = entry?.cacheRead;
let cacheWrite = entry?.cacheWrite;
const freshTotalTokens = resolveFreshSessionTotalTokens(entry);
const allowTranscriptContextUsage = entry?.totalTokensFresh !== false && freshTotalTokens === void 0;
let totalTokens = freshTotalTokens;
if (args.includeTranscriptUsage) {
const logUsage = readUsageFromSessionLog(entry?.sessionId, entry, args.agentId, args.sessionKey, args.sessionStorePath);
if (logUsage) {
const candidate = logUsage.totalTokensFresh ? logUsage.promptTokens || logUsage.total : void 0;
if (allowTranscriptContextUsage && candidate !== void 0 && candidate > 0 && (!totalTokens || totalTokens === 0 || candidate > totalTokens)) totalTokens = candidate;
if (!entry?.model && logUsage.model) {
const slashIndex = logUsage.model.indexOf("/");
if (slashIndex > 0) {
const provider = logUsage.model.slice(0, slashIndex).trim();
const model = logUsage.model.slice(slashIndex + 1).trim();
if (provider && model) {
const catalogEntry = findModelInCatalog(args.thinkingCatalog ?? [], provider, model);
activeProvider = provider;
activeModel = model;
contextLookupProvider = catalogEntry ? provider : void 0;
contextLookupModel = catalogEntry ? model : logUsage.model;
}
} else {
activeModel = logUsage.model;
contextLookupProvider = activeProvider;
contextLookupModel = logUsage.model;
}
}
if (!inputTokens || inputTokens === 0) inputTokens = logUsage.input;
if (!outputTokens || outputTokens === 0) outputTokens = logUsage.output;
if (typeof cacheRead !== "number" || cacheRead <= 0) cacheRead = logUsage.cacheRead;
if (typeof cacheWrite !== "number" || cacheWrite <= 0) cacheWrite = logUsage.cacheWrite;
}
}
const activeModelLabel = formatProviderModelRef(activeProvider, activeModel) || "unknown";
const runtimeDiffersFromSelected = activeModelLabel !== (modelRefs.selected.label || "unknown");
const runtimeAliasModelEquivalent = areRuntimeModelRefsEquivalent(modelRefs.selected.label || "unknown", activeModelLabel, { config: args.config });
const activeModelProvider = runtimeAliasModelEquivalent ? selectedLookupProvider : contextLookupProvider;
const selectedContextTokens = resolveContextTokensForModel({
cfg: contextConfig,
provider: selectedLookupProvider,
model: selectedLookupModel,
modelContextWindow: args.selectedContextWindow,
modelContextTokens: args.selectedContextTokens,
allowAsyncLoad: false
});
const activeCatalogEntry = contextLookupProvider ? findModelInCatalog(args.thinkingCatalog ?? [], contextLookupProvider, contextLookupModel) : void 0;
const activeModelMatchesPreparedIdentity = normalizeLowercaseStringOrEmpty(contextLookupProvider) === normalizeLowercaseStringOrEmpty(modelRefs.active.provider) && normalizeLowercaseStringOrEmpty(contextLookupModel) === normalizeLowercaseStringOrEmpty(modelRefs.active.model);
const activeContextProvider = contextLookupProvider && normalizeLowercaseStringOrEmpty(contextLookupProvider) === normalizeLowercaseStringOrEmpty(modelRefs.active.provider) ? args.runtimeContextProvider ?? contextLookupProvider : contextLookupProvider;
const activeContextTokens = resolveContextTokensForModel({
cfg: contextConfig,
...activeContextProvider ? { provider: activeContextProvider } : {},
modelProvider: contextLookupProvider,
model: contextLookupModel,
modelContextWindow: activeCatalogEntry?.contextWindow,
modelContextTokens: activeCatalogEntry?.contextTokens ?? (activeCatalogEntry || activeModelMatchesPreparedIdentity ? args.runtimeContextTokens : void 0),
allowAsyncLoad: false
});
const channelModelNote = resolveChannelModelNote({
config: args.config,
entry,
selectedProvider: selectedLookupProvider,
selectedModel: selectedLookupModel,
parentSessionKey: args.parentSessionKey
});
const projectedActiveContextTokens = resolveProjectedSessionContextTokens({
entry,
provider: contextLookupProvider,
model: contextLookupModel,
agentHarnessId: args.resolvedHarness,
resolvedContextTokens: activeContextTokens,
authoredContextTokens: resolveAuthoredModelContextTokens({
cfg: contextConfig,
provider: contextLookupProvider,
modelProvider: activeModelProvider,
model: contextLookupModel
})
});
const runtimeSnapshotHasFallbackProvenance = initialFallbackState.active || hasSessionAutoModelFallbackProvenance(entry) || runtimeAliasModelEquivalent;
const contextTokens = entry?.modelSelectionLocked !== true && runtimeDiffersFromSelected && !runtimeSnapshotHasFallbackProvenance ? selectedContextTokens ?? 2e5 : projectedActiveContextTokens ?? 2e5;
const thinkLevel = args.resolvedThink ?? args.sessionEntry?.thinkingLevel ?? args.agent?.thinkingDefault ?? "off";
const verboseLevel = args.resolvedVerbose ?? args.sessionEntry?.verboseLevel ?? args.agent?.verboseDefault ?? "off";
const fastMode = args.resolvedFast ?? args.sessionEntry?.fastMode ?? false;
const fastModeState = resolveFastModeState({
cfg: args.config,
provider: activeProvider,
model: activeModel,
agentId: args.agentId,
sessionEntry: args.sessionEntry
});
const reasoningLevel = args.resolvedReasoning ?? args.sessionEntry?.reasoningLevel ?? args.agent?.reasoningDefault ?? "off";
const elevatedLevel = args.resolvedElevated ?? args.sessionEntry?.elevatedLevel ?? args.agent?.elevatedDefault ?? "on";
const execution = { label: resolveExecutionLabel(args) };
const agentRuntimeLabel = resolveAgentRuntimeLabel({
config: args.config,
sessionEntry: args.sessionEntry,
resolvedHarness: args.resolvedHarness,
fallbackProvider: activeProvider
});
const updatedAt = entry?.updatedAt;
const sessionStartedAt = resolveSessionLifecycleTimestamps({
entry,
agentId: args.agentId,
sessionKey: args.sessionKey,
storePath: args.sessionStorePath
}).sessionStartedAt;
const sessionDuration = typeof sessionStartedAt === "number" ? formatDurationCompact(now - sessionStartedAt, { spaced: true }) : void 0;
const sessionValue = [
args.sessionKey ?? "unknown",
sessionDuration ? `duration ${sessionDuration}` : null,
typeof updatedAt === "number" ? `updated ${formatTimeAgo(now - updatedAt)}` : "no activity"
].filter(Boolean).join(" • ");
const groupActivationValue = entry?.chatType === "group" || entry?.chatType === "channel" || Boolean(args.sessionKey?.includes(":group:")) || Boolean(args.sessionKey?.includes(":channel:")) ? args.groupActivation ?? entry?.groupActivation ?? "mention" : void 0;
const contextUsageLabel = totalTokens == null || totalTokens === 0 ? formatEstimatedContextBudgetTokens(entry?.contextBudgetStatus, contextTokens) ?? formatTokens(totalTokens, contextTokens ?? null) : formatTokens(totalTokens, contextTokens ?? null);
const queueMode = args.queue?.mode ?? "unknown";
const queueDetails = formatQueueDetails(args.queue);
const verboseLabel = verboseLevel === "full" ? "verbose:full" : verboseLevel === "on" ? "verbose" : null;
const traceLevel = entry?.traceLevel === "raw" ? "raw" : entry?.traceLevel === "on" ? "on" : "off";
const traceLabel = traceLevel === "raw" ? "trace:raw" : traceLevel === "on" ? "trace" : null;
const pluginStatusLines = verboseLevel !== "off" ? resolveSessionPluginStatusLines(entry) : [];
const pluginTraceLines = traceLevel === "on" || traceLevel === "raw" ? resolveSessionPluginTraceLines(entry) : [];
const pluginStatusLine = pluginStatusLines.length > 0 || pluginTraceLines.length > 0 ? [...pluginStatusLines, ...pluginTraceLines].join(" · ") : null;
const elevatedLabel = elevatedLevel && elevatedLevel !== "off" ? elevatedLevel === "on" ? "elevated" : `elevated:${elevatedLevel}` : null;
const textVerbosity = resolveConfiguredTextVerbosity({
config: args.config,
agentId: args.agentId,
provider: activeProvider,
model: activeModel
});
const fastModeValue = formatFastModeStatusValue({
mode: fastMode,
fastAutoOnSeconds: fastModeState.fastAutoOnSeconds
});
const optionFlagsValue = [
verboseLabel,
traceLabel,
elevatedLabel
].filter(Boolean).join(" · ");
const modesValue = [
`think ${thinkLevel}`,
`fast ${fastModeValue}`,
textVerbosity ? `text ${textVerbosity}` : null,
reasoningLevel !== "off" ? `reasoning ${reasoningLevel}` : null,
optionFlagsValue || null
].filter(Boolean).join(" · ");
const selectedModelLabel = modelRefs.selected.label || "unknown";
const selectedAuthMode = normalizeAuthMode(args.modelAuth) ?? resolveModelAuthMode(selectedLookupProvider, args.config);
const rawSelectedAuthLabelValue = selectedAuthMode && selectedAuthMode !== "unknown" ? args.modelAuth ?? selectedAuthMode : void 0;
const activeAuthMode = normalizeAuthMode(args.activeModelAuth) ?? resolveModelAuthMode(activeProvider, args.config);
const activeAuthLabelValue = activeAuthMode && activeAuthMode !== "unknown" ? args.activeModelAuth ?? activeAuthMode : void 0;
const selectedAuthLabelValue = shouldPreferActiveRuntimeAliasAuthLabel({
runtimeAliasModelEquivalent,
selectedAuthLabel: rawSelectedAuthLabelValue,
activeAuthLabel: activeAuthLabelValue
}) ? activeAuthLabelValue : rawSelectedAuthLabelValue ?? (runtimeAliasModelEquivalent ? activeAuthLabelValue : void 0);
const fallbackState = resolveActiveFallbackState({
selectedModelRef: selectedModelLabel,
activeModelRef: activeModelLabel,
config: args.config,
state: entry
});
const hasUsage = typeof inputTokens === "number" || typeof outputTokens === "number" || typeof cacheRead === "number" || typeof cacheWrite === "number";
const costConfig = hasUsage ? resolveModelCostConfig({
provider: activeProvider,
model: activeModel,
config: args.config,
allowPluginNormalization: false
}) : void 0;
const cost = asNonNegativeFiniteNumber(entry?.estimatedCostUsd) ?? (hasUsage ? estimateAggregateUsageCost({
usage: {
input: inputTokens ?? void 0,
output: outputTokens ?? void 0,
cacheRead: cacheRead ?? void 0,
cacheWrite: cacheWrite ?? void 0
},
cost: costConfig
}) : void 0);
const costLabel = formatUsd(cost);
const modelNote = channelModelNote ? ` · ${channelModelNote}` : "";
const configuredDefaultModelLabel = normalizeOptionalString(args.configuredDefaultModelLabel);
const sessionHasPersistedModelSelection = hasUserPinnedModelSelection(entry);
const sessionHasAutoFallback = hasSessionActiveAutoModelFallback(entry);
const overrideLabel = (sessionHasPersistedModelSelection || sessionHasAutoFallback) && configuredDefaultModelLabel && selectedModelLabel !== configuredDefaultModelLabel && !areRuntimeModelRefsEquivalent(selectedModelLabel, configuredDefaultModelLabel, { config: args.config }) ? sessionHasPersistedModelSelection ? ` · pinned session; config primary ${configuredDefaultModelLabel} · clear /model default` : ` · auto fallback; config primary ${configuredDefaultModelLabel} · check provider` : "";
const liveSwitchNote = entry?.liveModelSwitchPending ? " · ⏳ live switch pending" : "";
const modelLines = [`🧠 Model: ${selectedModelLabel}${modelNote}${overrideLabel}${liveSwitchNote}`];
const configuredFallbacks = (() => {
const modelConfig = args.agent?.model;
if (typeof modelConfig === "object" && modelConfig && Array.isArray(modelConfig.fallbacks)) return sessionHasPersistedModelSelection ? void 0 : modelConfig.fallbacks;
})();
const configuredFallbacksLine = configuredFallbacks?.length ? `🔄 Fallbacks: ${configuredFallbacks.join(", ")}` : null;
const showFallbackAuth = activeAuthLabelValue && activeAuthLabelValue !== selectedAuthLabelValue;
const fallbackValue = fallbackState.active ? `${activeModelLabel}${showFallbackAuth ? ` · 🔑 ${activeAuthLabelValue}` : ""} (${fallbackState.reason ?? "selected model unavailable"})` : null;
const fallbackLine = fallbackValue ? `↪️ Fallback: ${fallbackValue}` : null;
const commit = resolveRuntimeServiceCommit();
const versionLine = `🦞 OpenClaw ${VERSION}${commit ? ` (${commit})` : ""}`;
const tokensValue = formatTokensPairValue(inputTokens, outputTokens);
const usagePair = tokensValue ? `🧮 Tokens: ${tokensValue}` : null;
const cacheValue = formatCacheHitValue(inputTokens, cacheRead, cacheWrite);
const cacheLine = cacheValue ? `🗄️ Cache: ${cacheValue}` : null;
const costLine = costLabel ? `💵 Cost: ${costLabel}` : null;
const queueHasSignal = (args.queue?.depth ?? 0) > 0 || args.queue?.showDetails === true;
const compactionCount = entry?.compactionCount ?? 0;
const contextPct = typeof totalTokens === "number" && totalTokens > 0 && contextTokens > 0 ? Math.min(999, Math.round(totalTokens / contextTokens * 100)) : null;
const contextMeter = contextPct !== null ? (() => {
const filled = Math.min(10, Math.max(0, Math.round(contextPct / 10)));
return `${"▰".repeat(filled)}${"▱".repeat(10 - filled)} `;
})() : "";
const mediaLine = formatMediaUnderstandingLine(args.mediaDecisions);
const voiceLine = formatVoiceModeLine(args.config, args.sessionEntry, args.agentId);
const text = [
[
versionLine,
timeLine,
uptimeLine
],
[
...modelLines,
selectedAuthLabelValue ? `🔑 Auth: ${selectedAuthLabelValue}` : null,
configuredFallbacksLine,
fallbackLine
],
[
usagePair,
costLine,
cacheLine,
`📚 Context: ${contextUsageLabel}`,
compactionCount > 0 ? `🧹 Compactions: ${compactionCount}` : null,
mediaLine,
args.usageLine
],
[
`🧵 Session: ${sessionValue}`,
args.subagentsLine,
args.taskLine
],
[
`⚙️ Execution: ${execution.label}`,
`🤖 Runtime: ${agentRuntimeLabel}`,
modesValue ? `🎛️ Modes: ${modesValue}` : null,
groupActivationValue ? `👥 Activation: ${groupActivationValue}` : null,
`🪢 Queue: ${queueMode}${queueHasSignal ? queueDetails : ""}`
],
[
args.channelFeatureLine,
args.pluginHealthLine,
pluginStatusLine ? `🧩 ${pluginStatusLine}` : null,
voiceLine
]
].map((section) => section.filter((line) => Boolean(line)).join("\n")).filter(Boolean).join("\n\n");
const statusRows = [];
const pushStatusRow = (label, value) => {
const cell = typeof value === "number" ? String(value) : value?.trim() ?? "";
if (cell) statusRows.push([label, cell]);
};
pushStatusRow("🧠 Model", `${selectedModelLabel}${modelNote}${overrideLabel}${liveSwitchNote}`);
pushStatusRow("🔑 Auth", selectedAuthLabelValue);
pushStatusRow("🔄 Fallbacks", configuredFallbacks?.join(", "));
pushStatusRow("↪️ Fallback", fallbackValue);
pushStatusRow("🧮 Tokens", tokensValue);
pushStatusRow("💵 Cost", costLabel);
pushStatusRow("🗄️ Cache", cacheValue);
pushStatusRow("📚 Context", `${contextMeter}${contextUsageLabel}`);
pushStatusRow("🧹 Compactions", compactionCount > 0 ? compactionCount : null);
pushStatusRow("🧵 Session", sessionValue);
pushStatusRow("⚙️ Execution", execution.label);
pushStatusRow("Runtime", agentRuntimeLabel);
pushStatusRow("🎛️ Modes", modesValue);
pushStatusRow("👥 Activation", groupActivationValue);
pushStatusRow("🪢 Queue", queueHasSignal ? `${queueMode}${queueDetails}` : queueMode);
const contextBlock = (value) => value?.trim() ? [{
type: "context",
text: value
}] : [];
const clockUptimeValue = [cronNow ? `${cronNow.formattedTime} (${cronNow.userTimezone})` : args.timeLine, args.uptimeValue ? `⏱️ ${args.uptimeValue}` : null].filter(Boolean).join(" · ");
const contextPressureLine = contextPct !== null && contextPct >= 80 ? `⚠️ Context ${contextPct}% full` : null;
return {
text,
presentation: {
title: versionLine,
blocks: [
...contextBlock(clockUptimeValue),
{
type: "table",
caption: "Session status",
headers: ["Item", "Value"],
rows: statusRows,
rowHeaderColumnIndex: 0
},
...contextPressureLine ? [{
type: "text",
text: contextPressureLine
}] : [],
...contextBlock(mediaLine),
...contextBlock(args.usageLine),
...contextBlock(args.subagentsLine),
...contextBlock(args.taskLine),
...contextBlock(args.pluginHealthLine),
...contextBlock(pluginStatusLine ? `🧩 ${pluginStatusLine}` : null),
...contextBlock(voiceLine)
]
}
};
}
//#endregion
export { buildStatusMessageParts as n, formatContextUsageShort as r, buildStatusMessage as t };