mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
Merged via /review-pr -> /prepare-pr -> /merge-pr.
Prepared head SHA: 7533b85156
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: shakkernerd <165377636+shakkernerd@users.noreply.github.com>
Reviewed-by: @shakkernerd
149 lines
4.9 KiB
TypeScript
149 lines
4.9 KiB
TypeScript
import { DEFAULT_MODEL, DEFAULT_PROVIDER } from "../agents/defaults.js";
|
|
import { resolveConfiguredModelRef } from "../agents/model-selection.js";
|
|
import type { SessionEntry } from "../config/sessions.js";
|
|
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
|
import { resolveSessionModelRef } from "../gateway/session-utils.js";
|
|
import { formatTimeAgo } from "../infra/format-time/format-relative.ts";
|
|
import { parseAgentSessionKey } from "../routing/session-key.js";
|
|
import { theme } from "../terminal/theme.js";
|
|
|
|
export type SessionDisplayRow = {
|
|
key: string;
|
|
updatedAt: number | null;
|
|
ageMs: number | null;
|
|
sessionId?: string;
|
|
systemSent?: boolean;
|
|
abortedLastRun?: boolean;
|
|
thinkingLevel?: string;
|
|
verboseLevel?: string;
|
|
reasoningLevel?: string;
|
|
elevatedLevel?: string;
|
|
responseUsage?: string;
|
|
groupActivation?: string;
|
|
inputTokens?: number;
|
|
outputTokens?: number;
|
|
totalTokens?: number;
|
|
totalTokensFresh?: boolean;
|
|
model?: string;
|
|
modelProvider?: string;
|
|
providerOverride?: string;
|
|
modelOverride?: string;
|
|
contextTokens?: number;
|
|
};
|
|
|
|
export type SessionDisplayDefaults = {
|
|
model: string;
|
|
};
|
|
|
|
export const SESSION_KEY_PAD = 26;
|
|
export const SESSION_AGE_PAD = 9;
|
|
export const SESSION_MODEL_PAD = 14;
|
|
|
|
export function toSessionDisplayRows(store: Record<string, SessionEntry>): SessionDisplayRow[] {
|
|
return Object.entries(store)
|
|
.map(([key, entry]) => {
|
|
const updatedAt = entry?.updatedAt ?? null;
|
|
return {
|
|
key,
|
|
updatedAt,
|
|
ageMs: updatedAt ? Date.now() - updatedAt : null,
|
|
sessionId: entry?.sessionId,
|
|
systemSent: entry?.systemSent,
|
|
abortedLastRun: entry?.abortedLastRun,
|
|
thinkingLevel: entry?.thinkingLevel,
|
|
verboseLevel: entry?.verboseLevel,
|
|
reasoningLevel: entry?.reasoningLevel,
|
|
elevatedLevel: entry?.elevatedLevel,
|
|
responseUsage: entry?.responseUsage,
|
|
groupActivation: entry?.groupActivation,
|
|
inputTokens: entry?.inputTokens,
|
|
outputTokens: entry?.outputTokens,
|
|
totalTokens: entry?.totalTokens,
|
|
totalTokensFresh: entry?.totalTokensFresh,
|
|
model: entry?.model,
|
|
modelProvider: entry?.modelProvider,
|
|
providerOverride: entry?.providerOverride,
|
|
modelOverride: entry?.modelOverride,
|
|
contextTokens: entry?.contextTokens,
|
|
} satisfies SessionDisplayRow;
|
|
})
|
|
.toSorted((a, b) => (b.updatedAt ?? 0) - (a.updatedAt ?? 0));
|
|
}
|
|
|
|
export function resolveSessionDisplayDefaults(cfg: OpenClawConfig): SessionDisplayDefaults {
|
|
const resolved = resolveConfiguredModelRef({
|
|
cfg,
|
|
defaultProvider: DEFAULT_PROVIDER,
|
|
defaultModel: DEFAULT_MODEL,
|
|
});
|
|
return {
|
|
model: resolved.model ?? DEFAULT_MODEL,
|
|
};
|
|
}
|
|
|
|
export function resolveSessionDisplayModel(
|
|
cfg: OpenClawConfig,
|
|
row: Pick<
|
|
SessionDisplayRow,
|
|
"key" | "model" | "modelProvider" | "modelOverride" | "providerOverride"
|
|
>,
|
|
defaults: SessionDisplayDefaults,
|
|
): string {
|
|
const resolved = resolveSessionModelRef(cfg, row, parseAgentSessionKey(row.key)?.agentId);
|
|
return resolved.model ?? defaults.model;
|
|
}
|
|
|
|
function truncateSessionKey(key: string): string {
|
|
if (key.length <= SESSION_KEY_PAD) {
|
|
return key;
|
|
}
|
|
const head = Math.max(4, SESSION_KEY_PAD - 10);
|
|
return `${key.slice(0, head)}...${key.slice(-6)}`;
|
|
}
|
|
|
|
export function formatSessionKeyCell(key: string, rich: boolean): string {
|
|
const label = truncateSessionKey(key).padEnd(SESSION_KEY_PAD);
|
|
return rich ? theme.accent(label) : label;
|
|
}
|
|
|
|
export function formatSessionAgeCell(updatedAt: number | null | undefined, rich: boolean): string {
|
|
const ageLabel = updatedAt ? formatTimeAgo(Date.now() - updatedAt) : "unknown";
|
|
const padded = ageLabel.padEnd(SESSION_AGE_PAD);
|
|
return rich ? theme.muted(padded) : padded;
|
|
}
|
|
|
|
export function formatSessionModelCell(model: string | null | undefined, rich: boolean): string {
|
|
const label = (model ?? "unknown").padEnd(SESSION_MODEL_PAD);
|
|
return rich ? theme.info(label) : label;
|
|
}
|
|
|
|
export function formatSessionFlagsCell(
|
|
row: Pick<
|
|
SessionDisplayRow,
|
|
| "thinkingLevel"
|
|
| "verboseLevel"
|
|
| "reasoningLevel"
|
|
| "elevatedLevel"
|
|
| "responseUsage"
|
|
| "groupActivation"
|
|
| "systemSent"
|
|
| "abortedLastRun"
|
|
| "sessionId"
|
|
>,
|
|
rich: boolean,
|
|
): string {
|
|
const flags = [
|
|
row.thinkingLevel ? `think:${row.thinkingLevel}` : null,
|
|
row.verboseLevel ? `verbose:${row.verboseLevel}` : null,
|
|
row.reasoningLevel ? `reasoning:${row.reasoningLevel}` : null,
|
|
row.elevatedLevel ? `elev:${row.elevatedLevel}` : null,
|
|
row.responseUsage ? `usage:${row.responseUsage}` : null,
|
|
row.groupActivation ? `activation:${row.groupActivation}` : null,
|
|
row.systemSent ? "system" : null,
|
|
row.abortedLastRun ? "aborted" : null,
|
|
row.sessionId ? `id:${row.sessionId}` : null,
|
|
].filter(Boolean);
|
|
const label = flags.join(" ");
|
|
return label.length === 0 ? "" : rich ? theme.muted(label) : label;
|
|
}
|