mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-30 11:01:18 +00:00
* feat(codex): add native session supervision * fix(codex): harden supervision integration * fix(codex): preserve locked harness ownership * fix(codex): fence native session archive * fix(codex): revalidate archive binding ownership * feat(codex): integrate supervision runtime * feat(sessions): preserve harness-owned execution * feat(sessions): persist harness ownership invariants * feat(gateway): enforce harness-owned sessions * feat(setup): enable detected Codex supervision * feat(mac): expose supervised Codex sessions * feat(ui): make Codex sessions actionable * docs(codex): document session supervision * test(codex): cover integration ownership * chore(i18n): refresh supervision inventories * fix(setup): finalize Codex activation atomically * test(codex): narrow binding store update * fix(sessions): preserve legacy model locks * test(macos): serialize Codex catalog fixtures * fix(sessions): preserve legacy lock admission * chore(i18n): reconcile supervision metadata * test(sessions): mark legacy lock fixture * fix(macos): drain final Codex catalog frame * docs: leave supervision note to release * style(macos): satisfy Codex catalog type length * chore: record session accessor seam owners * fix(macos): honor configured Codex supervision * fix(codex): preserve harness-owned model locks * fix(codex): satisfy supervision lint gates * chore(i18n): refresh native supervision inventory * fix(codex): align supervision validation contracts * fix(codex): close supervision boundary gaps * fix(codex): preserve supervision activation contracts * fix(codex): dispose standalone supervision runtime * fix(codex): pin supervised source connection * fix(plugins): bind delegated runs to exact session target * fix(codex): scope supervised sessions to configured agents * fix(codex): fingerprint effective supervision home * fix(codex): normalize supervision plugin policy * fix(codex): keep supervised bindings stable across upgrades * fix(codex): guard all supervised binding connections * fix(codex): preserve catalog filters and pending CAS identity * fix(codex): preserve supervision identity for diagnostics * fix(codex): bind uncertain commits to supervision connection * fix(codex): satisfy supervision type boundaries * fix(macos): reconcile current main validation * fix(codex): handle absent runtime config in supervision * fix(doctor): own local audio acceleration check * fix(codex): satisfy integration lint gates * fix(codex): satisfy lifecycle safety guards
382 lines
10 KiB
TypeScript
382 lines
10 KiB
TypeScript
// Status summary runtime tests cover model context-token resolution.
|
|
import { describe, expect, it } from "vitest";
|
|
import { statusSummaryRuntime } from "./status.summary.runtime.js";
|
|
|
|
describe("statusSummaryRuntime.resolveContextTokensForModel", () => {
|
|
it("does not match provider context window overrides across provider id variants", () => {
|
|
const contextTokens = statusSummaryRuntime.resolveContextTokensForModel({
|
|
cfg: {
|
|
models: {
|
|
providers: {
|
|
"z.ai": {
|
|
models: [{ id: "glm-4.7", contextWindow: 123_456 }],
|
|
},
|
|
},
|
|
},
|
|
} as never,
|
|
provider: "z-ai",
|
|
model: "glm-4.7",
|
|
fallbackContextTokens: 999,
|
|
});
|
|
|
|
expect(contextTokens).toBe(999);
|
|
});
|
|
|
|
it("prefers per-model contextTokens over contextWindow", () => {
|
|
const contextTokens = statusSummaryRuntime.resolveContextTokensForModel({
|
|
cfg: {
|
|
models: {
|
|
providers: {
|
|
openai: {
|
|
models: [{ id: "gpt-5.4", contextWindow: 1_050_000, contextTokens: 272_000 }],
|
|
},
|
|
},
|
|
},
|
|
} as never,
|
|
provider: "openai",
|
|
model: "gpt-5.4",
|
|
fallbackContextTokens: 999,
|
|
});
|
|
|
|
expect(contextTokens).toBe(272_000);
|
|
});
|
|
|
|
it("caps an oversized override without raising a lower override", () => {
|
|
const cfg = {
|
|
models: {
|
|
providers: {
|
|
openai: {
|
|
models: [{ id: "gpt-5.5", contextWindow: 272_000 }],
|
|
},
|
|
},
|
|
},
|
|
} as never;
|
|
const resolveOverride = (contextTokensOverride: number) =>
|
|
statusSummaryRuntime.resolveContextTokensForModel({
|
|
cfg,
|
|
provider: "openai",
|
|
model: "gpt-5.5",
|
|
contextTokensOverride,
|
|
fallbackContextTokens: 999,
|
|
});
|
|
|
|
expect(resolveOverride(1_000_000)).toBe(272_000);
|
|
expect(resolveOverride(128_000)).toBe(128_000);
|
|
});
|
|
|
|
it("caps cold-cache overrides with prepared static catalog metadata", () => {
|
|
expect(
|
|
statusSummaryRuntime.resolveContextTokensForModel({
|
|
cfg: {},
|
|
provider: "openai",
|
|
model: "gpt-5.5",
|
|
modelContextWindow: 1_000_000,
|
|
modelContextTokens: 272_000,
|
|
contextTokensOverride: 1_000_000,
|
|
fallbackContextTokens: 200_000,
|
|
}),
|
|
).toBe(272_000);
|
|
});
|
|
|
|
it("combines configured native windows with lower prepared runtime caps", () => {
|
|
expect(
|
|
statusSummaryRuntime.resolveContextTokensForModel({
|
|
cfg: {
|
|
models: {
|
|
providers: {
|
|
openai: {
|
|
models: [{ id: "gpt-5.5", contextWindow: 1_000_000 }],
|
|
},
|
|
},
|
|
},
|
|
} as never,
|
|
provider: "openai",
|
|
model: "gpt-5.5",
|
|
modelContextTokens: 272_000,
|
|
contextTokensOverride: 1_000_000,
|
|
}),
|
|
).toBe(272_000);
|
|
});
|
|
|
|
it("matches self-prefixed configured ids through provider ownership", () => {
|
|
expect(
|
|
statusSummaryRuntime.resolveContextTokensForModel({
|
|
cfg: {
|
|
models: {
|
|
providers: {
|
|
"google-gemini-cli": {
|
|
models: [
|
|
{
|
|
id: "google-gemini-cli/gemini-3.1-pro-preview",
|
|
contextTokens: 1_000_000,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
},
|
|
} as never,
|
|
provider: "google-gemini-cli",
|
|
model: "gemini-3.1-pro-preview",
|
|
contextTokensOverride: 2_000_000,
|
|
}),
|
|
).toBe(1_000_000);
|
|
});
|
|
|
|
it("uses provider defaults and fixed Anthropic windows when capping overrides", () => {
|
|
expect(
|
|
statusSummaryRuntime.resolveContextTokensForModel({
|
|
cfg: {
|
|
models: {
|
|
providers: {
|
|
ollama: {
|
|
contextWindow: 32_000,
|
|
models: [{ id: "qwen3.5:9b" }],
|
|
},
|
|
},
|
|
},
|
|
} as never,
|
|
provider: "ollama",
|
|
model: "qwen3.5:9b",
|
|
contextTokensOverride: 100_000,
|
|
}),
|
|
).toBe(32_000);
|
|
|
|
expect(
|
|
statusSummaryRuntime.resolveContextTokensForModel({
|
|
cfg: {
|
|
models: {
|
|
providers: {
|
|
anthropic: {
|
|
models: [{ id: "claude-sonnet-4-6", contextWindow: 200_000 }],
|
|
},
|
|
},
|
|
},
|
|
} as never,
|
|
sourceCfg: {},
|
|
provider: "anthropic",
|
|
model: "claude-sonnet-4-6",
|
|
contextTokensOverride: 1_200_000,
|
|
}),
|
|
).toBe(1_048_576);
|
|
});
|
|
|
|
it.each([
|
|
{ contextTokens: 200_000, expected: 200_000 },
|
|
{ contextTokens: 2_000_000, expected: 1_048_576 },
|
|
])(
|
|
"bounds Anthropic contextTokens=$contextTokens by the fixed native window",
|
|
({ contextTokens, expected }) => {
|
|
expect(
|
|
statusSummaryRuntime.resolveContextTokensForModel({
|
|
cfg: {
|
|
models: {
|
|
providers: {
|
|
anthropic: {
|
|
models: [
|
|
{
|
|
id: "claude-sonnet-4-6",
|
|
contextWindow: 1_048_576,
|
|
contextTokens,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
},
|
|
} as never,
|
|
provider: "anthropic",
|
|
model: "claude-sonnet-4-6",
|
|
contextTokensOverride: 1_200_000,
|
|
}),
|
|
).toBe(expected);
|
|
},
|
|
);
|
|
});
|
|
|
|
describe("statusSummaryRuntime.classifySessionKey", () => {
|
|
it("classifies cron history sessions distinctly", () => {
|
|
expect(statusSummaryRuntime.classifySessionKey("agent:main:cron:daily-digest")).toBe("cron");
|
|
expect(
|
|
statusSummaryRuntime.classifySessionKey("agent:avery:cron:daily-digest:run:abc123"),
|
|
).toBe("cron");
|
|
});
|
|
});
|
|
|
|
describe("statusSummaryRuntime.resolveSessionRuntimeLabel", () => {
|
|
it("uses the shared /status runtime label for the implicit OpenAI Codex route", () => {
|
|
expect(
|
|
statusSummaryRuntime.resolveSessionRuntimeLabel({
|
|
cfg: {} as never,
|
|
entry: {
|
|
sessionId: "session-1",
|
|
updatedAt: 0,
|
|
},
|
|
provider: "openai",
|
|
model: "gpt-5.5",
|
|
sessionKey: "agent:main:main",
|
|
}),
|
|
).toBe("OpenAI Codex");
|
|
});
|
|
|
|
it("preserves configured default model CLI runtimes", () => {
|
|
expect(
|
|
statusSummaryRuntime.resolveSessionRuntimeLabel({
|
|
cfg: {
|
|
agents: {
|
|
defaults: {
|
|
models: {
|
|
"anthropic/claude-sonnet-4-6": { agentRuntime: { id: "claude-cli" } },
|
|
},
|
|
},
|
|
},
|
|
} as never,
|
|
entry: {
|
|
sessionId: "session-1",
|
|
updatedAt: 0,
|
|
},
|
|
provider: "anthropic",
|
|
model: "claude-sonnet-4-6",
|
|
sessionKey: "agent:main:main",
|
|
}),
|
|
).toBe("Claude CLI");
|
|
});
|
|
|
|
it("preserves configured agent model runtimes before harness selection", () => {
|
|
expect(
|
|
statusSummaryRuntime.resolveSessionRuntimeLabel({
|
|
cfg: {
|
|
agents: {
|
|
defaults: {
|
|
models: {
|
|
"openai/gpt-5.5": { agentRuntime: { id: "openclaw" } },
|
|
},
|
|
},
|
|
list: [
|
|
{
|
|
id: "research",
|
|
models: {
|
|
"openai/gpt-5.5": { agentRuntime: { id: "codex" } },
|
|
},
|
|
},
|
|
],
|
|
},
|
|
} as never,
|
|
entry: {
|
|
sessionId: "session-1",
|
|
updatedAt: 0,
|
|
},
|
|
provider: "openai",
|
|
model: "gpt-5.5",
|
|
agentId: "research",
|
|
sessionKey: "agent:research:main",
|
|
}),
|
|
).toBe("OpenAI Codex");
|
|
});
|
|
|
|
it("reports the owning Codex harness for a locked session with stale OpenClaw metadata", () => {
|
|
expect(
|
|
statusSummaryRuntime.resolveSessionRuntimeLabel({
|
|
cfg: {
|
|
agents: {
|
|
defaults: {
|
|
models: {
|
|
"openai/gpt-5.5": { agentRuntime: { id: "openclaw" } },
|
|
},
|
|
},
|
|
},
|
|
} as never,
|
|
entry: {
|
|
sessionId: "locked-codex-session",
|
|
updatedAt: 0,
|
|
agentHarnessId: "codex",
|
|
agentRuntimeOverride: "openclaw",
|
|
modelSelectionLocked: true,
|
|
},
|
|
provider: "openai",
|
|
model: "gpt-5.5",
|
|
sessionKey: "agent:main:main",
|
|
}),
|
|
).toBe("OpenAI Codex");
|
|
});
|
|
});
|
|
|
|
describe("statusSummaryRuntime.resolveSessionModelRef", () => {
|
|
const cfg = {
|
|
agents: {
|
|
defaults: {
|
|
model: { primary: "anthropic/claude-sonnet-4-6" },
|
|
},
|
|
},
|
|
} as never;
|
|
|
|
it("preserves explicit runtime providers for vendor-prefixed model ids", () => {
|
|
expect(
|
|
statusSummaryRuntime.resolveSessionModelRef(cfg, {
|
|
modelProvider: "openrouter",
|
|
model: "anthropic/claude-haiku-4.5",
|
|
}),
|
|
).toEqual({
|
|
provider: "openrouter",
|
|
model: "anthropic/claude-haiku-4.5",
|
|
});
|
|
});
|
|
|
|
it("splits legacy combined overrides when provider is missing", () => {
|
|
expect(
|
|
statusSummaryRuntime.resolveSessionModelRef(cfg, {
|
|
modelOverride: "ollama-beelink2/qwen2.5-coder:7b",
|
|
}),
|
|
).toEqual({
|
|
provider: "ollama-beelink2",
|
|
model: "qwen2.5-coder:7b",
|
|
});
|
|
});
|
|
|
|
it("uses the configured default provider for providerless runtime models", () => {
|
|
expect(
|
|
statusSummaryRuntime.resolveSessionModelRef(
|
|
{
|
|
agents: {
|
|
defaults: {
|
|
model: { primary: "openai/gpt-5.5" },
|
|
},
|
|
},
|
|
} as never,
|
|
{
|
|
model: "gpt-5.5",
|
|
},
|
|
),
|
|
).toEqual({
|
|
provider: "openai",
|
|
model: "gpt-5.5",
|
|
});
|
|
});
|
|
|
|
it("prefers explicit overrides ahead of fallback runtime fields", () => {
|
|
expect(
|
|
statusSummaryRuntime.resolveSessionModelRef(cfg, {
|
|
providerOverride: "openai",
|
|
modelOverride: "gpt-5.4",
|
|
modelProvider: "amazon-bedrock",
|
|
model: "minimax.minimax-m2.5",
|
|
}),
|
|
).toEqual({
|
|
provider: "openai",
|
|
model: "gpt-5.4",
|
|
});
|
|
});
|
|
|
|
it("falls back to configured defaults when persisted session model fields are malformed", () => {
|
|
expect(
|
|
statusSummaryRuntime.resolveSessionModelRef(cfg, {
|
|
modelProvider: { provider: "openai" },
|
|
model: false,
|
|
providerOverride: ["anthropic"],
|
|
modelOverride: 123,
|
|
} as never),
|
|
).toEqual({
|
|
provider: "anthropic",
|
|
model: "claude-sonnet-4-6",
|
|
});
|
|
});
|
|
});
|