murashit_codex-panel/tests/runtime/runtime-settings.test.ts

749 lines
27 KiB
TypeScript
Raw Normal View History

2026-05-12 15:05:56 +00:00
import { describe, expect, it } from "vitest";
2026-05-22 23:37:26 +00:00
import type { ConfigReadResponse } from "../../src/generated/app-server/v2/ConfigReadResponse";
import type { Model } from "../../src/generated/app-server/v2/Model";
import type { Thread } from "../../src/generated/app-server/v2/Thread";
import { createAppServerDiagnostics } from "../../src/app-server/compatibility";
2026-05-12 15:05:56 +00:00
import {
compactModelLabel,
compactReasoningEffortLabel,
modelOverrideMessage,
parseModelOverride,
parseReasoningEffortOverride,
reasoningEffortOverrideMessage,
} from "../../src/runtime/settings";
2026-05-12 15:05:56 +00:00
import {
2026-05-21 15:02:32 +00:00
autoReviewActive,
currentApprovalsReviewer,
2026-05-12 15:05:56 +00:00
currentModel,
currentReasoningEffort,
currentServiceTier,
2026-05-29 00:44:25 +00:00
fastModeActive,
fastServiceTierRequestValue,
2026-05-12 15:05:56 +00:00
fastModeLabel,
requestedOrConfiguredServiceTier,
requestedTurnRuntimeSettings,
2026-06-01 02:07:59 +00:00
resetRuntimeSettingToConfig,
pendingRuntimeSettingPayload,
setPendingRuntimeSetting,
2026-05-12 15:05:56 +00:00
serviceTierLabel,
type RuntimeSnapshot,
} from "../../src/runtime/state";
import { readRuntimeConfig } from "../../src/runtime/config";
import { contextSummary, effectiveConfigSections, rateLimitSummary } from "../../src/runtime/view";
import {
applySharedAppServerMetadata,
applySharedModels,
applySharedThreadList,
cachedSharedAppServerMetadata,
cachedSharedThreadList,
createSharedAppServerState,
} from "../../src/runtime/shared-app-server-state";
2026-05-12 15:05:56 +00:00
describe("runtime settings", () => {
it("parses model overrides", () => {
expect(parseModelOverride("gpt-5.5")).toBe("gpt-5.5");
expect(parseModelOverride(" default ")).toBeNull();
expect(parseModelOverride("")).toBeUndefined();
});
it("keeps shared app-server cache snapshots detached from caller-owned arrays", () => {
const sourceThreads = [threadFixture("thread-1")];
const threadState = applySharedThreadList(createSharedAppServerState(), sourceThreads);
sourceThreads.push(threadFixture("thread-2"));
const cachedThreads = cachedSharedThreadList(threadState);
expect(cachedThreads?.map((thread) => thread.id)).toEqual(["thread-1"]);
const mutableCachedThreads = cachedThreads as Thread[];
mutableCachedThreads.push(threadFixture("thread-3"));
expect(cachedSharedThreadList(threadState)?.map((thread) => thread.id)).toEqual(["thread-1"]);
const sourceModels = [modelFixture("gpt-5.5")];
const modelState = applySharedModels(createSharedAppServerState(), sourceModels);
sourceModels.push(modelFixture("gpt-5.6"));
expect(modelState.availableModels.map((model) => model.model)).toEqual(["gpt-5.5"]);
const metadataState = applySharedAppServerMetadata(createSharedAppServerState(), {
effectiveConfig: null,
availableModels: sourceModels,
availableSkills: [{ name: "skill", description: "", path: "/tmp/skill", scope: "repo", enabled: true }],
rateLimit: null,
appServerDiagnostics: {
...createAppServerDiagnostics(),
mcpServers: [{ name: "server", startupStatus: "ready", authStatus: null, toolCount: 1, message: null }],
},
});
sourceModels.push(modelFixture("gpt-5.7"));
const cachedMetadata = cachedSharedAppServerMetadata(metadataState);
expect(cachedMetadata?.availableModels.map((model) => model.model)).toEqual(["gpt-5.5", "gpt-5.6"]);
});
2026-05-12 15:05:56 +00:00
it("parses reasoning effort overrides", () => {
expect(parseReasoningEffortOverride("high")).toBe("high");
expect(parseReasoningEffortOverride("default")).toBeNull();
expect(parseReasoningEffortOverride("extreme")).toBeUndefined();
});
it("formats runtime override messages", () => {
expect(modelOverrideMessage("gpt-5.5")).toBe("Model set to gpt-5.5 for subsequent turns.");
expect(modelOverrideMessage(null)).toBe("Model reset to default for subsequent turns.");
expect(reasoningEffortOverrideMessage("low")).toBe("Reasoning effort set to low for subsequent turns.");
expect(reasoningEffortOverrideMessage(null)).toBe("Reasoning effort reset to default for subsequent turns.");
2026-05-12 15:05:56 +00:00
});
it("formats compact runtime labels", () => {
expect(compactModelLabel("gpt-5.5")).toBe("5.5");
expect(compactModelLabel("custom-model")).toBe("custom-model");
expect(compactModelLabel(null)).toBe("default");
expect(compactReasoningEffortLabel("minimal")).toBe("min");
expect(compactReasoningEffortLabel("high")).toBe("high");
expect(compactReasoningEffortLabel(null)).toBe("default");
});
it("keeps runtime defaults, resets, and collaboration mode semantics distinct", () => {
2026-05-12 15:05:56 +00:00
const snapshot = runtimeSnapshot({
2026-06-01 02:07:59 +00:00
requestedModel: resetRuntimeSettingToConfig(),
requestedReasoningEffort: resetRuntimeSettingToConfig(),
2026-05-12 15:05:56 +00:00
});
expect(currentModel(snapshot)).toBe("gpt-5.5");
expect(currentReasoningEffort(snapshot)).toBe("high");
expect(requestedTurnRuntimeSettings(snapshot)).toMatchObject({
collaborationMode: {
mode: "default",
settings: { model: "gpt-5.5", reasoning_effort: "high" },
},
});
2026-06-01 02:07:59 +00:00
expect(pendingRuntimeSettingPayload(snapshot.requestedModel)).toBeNull();
expect(pendingRuntimeSettingPayload(snapshot.requestedReasoningEffort)).toBeNull();
2026-05-12 15:05:56 +00:00
});
it("uses explicit runtime overrides as current values and settings payload values", () => {
2026-05-12 15:05:56 +00:00
const snapshot = runtimeSnapshot({
2026-06-01 02:07:59 +00:00
requestedModel: setPendingRuntimeSetting("gpt-5.4"),
requestedReasoningEffort: setPendingRuntimeSetting("low"),
2026-05-12 15:05:56 +00:00
});
expect(currentModel(snapshot)).toBe("gpt-5.4");
expect(currentReasoningEffort(snapshot)).toBe("low");
2026-06-01 02:07:59 +00:00
expect(pendingRuntimeSettingPayload(snapshot.requestedModel)).toBe("gpt-5.4");
expect(pendingRuntimeSettingPayload(snapshot.requestedReasoningEffort)).toBe("low");
2026-05-12 15:05:56 +00:00
});
2026-05-21 15:02:32 +00:00
it("resolves approval reviewer from requested, active, then effective config", () => {
expect(
currentApprovalsReviewer(
runtimeSnapshot({
2026-06-01 02:07:59 +00:00
requestedApprovalsReviewer: setPendingRuntimeSetting("user"),
2026-05-21 15:02:32 +00:00
activeApprovalsReviewer: "auto_review",
2026-05-22 23:37:26 +00:00
effectiveConfig: effectiveConfigFixture({ approvals_reviewer: "guardian_subagent" }),
2026-05-21 15:02:32 +00:00
}),
),
).toBe("user");
expect(
currentApprovalsReviewer(
runtimeSnapshot({
activeApprovalsReviewer: "auto_review",
2026-05-22 23:37:26 +00:00
effectiveConfig: effectiveConfigFixture({ approvals_reviewer: "guardian_subagent" }),
2026-05-21 15:02:32 +00:00
}),
),
).toBe("auto_review");
expect(
currentApprovalsReviewer(
runtimeSnapshot({
2026-05-22 23:37:26 +00:00
effectiveConfig: effectiveConfigFixture({ approvals_reviewer: "guardian_subagent" }),
2026-05-21 15:02:32 +00:00
}),
),
).toBe("guardian_subagent");
});
2026-05-22 21:01:07 +00:00
it("uses the active reviewer before configured reviewer", () => {
const snapshot = runtimeSnapshot({
activeApprovalsReviewer: "user",
2026-05-22 23:37:26 +00:00
effectiveConfig: effectiveConfigFixture({ approvals_reviewer: "auto_review" }),
});
2026-05-22 21:01:07 +00:00
expect(currentApprovalsReviewer(snapshot)).toBe("user");
expect(autoReviewActive(snapshot)).toBe(false);
});
it("treats guardian subagent reviewer as active auto-review", () => {
const snapshot = runtimeSnapshot({
activeApprovalsReviewer: "guardian_subagent",
});
expect(currentApprovalsReviewer(snapshot)).toBe("guardian_subagent");
expect(autoReviewActive(snapshot)).toBe(true);
});
2026-05-22 21:01:07 +00:00
it("uses requested reviewer above active and configured reviewers", () => {
const snapshot = runtimeSnapshot({
2026-06-01 02:07:59 +00:00
requestedApprovalsReviewer: setPendingRuntimeSetting("user"),
activeApprovalsReviewer: "user",
2026-05-22 23:37:26 +00:00
effectiveConfig: effectiveConfigFixture({ approvals_reviewer: "auto_review" }),
});
expect(currentApprovalsReviewer(snapshot)).toBe("user");
expect(autoReviewActive(snapshot)).toBe(false);
});
it("uses effective approval reviewer values and reports selected profile metadata", () => {
const effectiveConfig = effectiveConfigFixture({ approvals_reviewer: "auto_review" }, [
configLayer({}, null),
configLayer({ approvals_reviewer: "auto_review" }, "auto"),
]);
const snapshot = runtimeSnapshot({
effectiveConfig,
});
expect(readRuntimeConfig(effectiveConfig).profile).toBe("auto");
expect(currentApprovalsReviewer(snapshot)).toBe("auto_review");
expect(autoReviewActive(snapshot)).toBe(true);
});
it("uses effective model, effort, and fast mode config values", () => {
const snapshot = runtimeSnapshot({
effectiveConfig: effectiveConfigFixture(
{
model: "gpt-profile",
model_reasoning_effort: "high",
service_tier: "fast",
},
[
configLayer({}, null),
configLayer({ model: "gpt-profile", model_reasoning_effort: "high", service_tier: "fast" }, "fast-profile"),
],
),
});
expect(currentModel(snapshot)).toBe("gpt-profile");
expect(currentReasoningEffort(snapshot)).toBe("high");
expect(currentServiceTier(snapshot)).toBe("fast");
expect(serviceTierLabel(snapshot)).toBe("fast");
expect(fastModeLabel(snapshot)).toBe("on");
expect(requestedOrConfiguredServiceTier(snapshot)).toBe("fast");
});
2026-05-22 21:01:07 +00:00
it("uses active service tier before configured service tier", () => {
const snapshot = runtimeSnapshot({
2026-05-28 09:16:54 +00:00
activeServiceTier: "flex",
2026-05-22 23:37:26 +00:00
effectiveConfig: effectiveConfigFixture({ service_tier: "fast" }),
});
2026-05-28 09:16:54 +00:00
expect(currentServiceTier(snapshot)).toBe("flex");
2026-05-22 21:01:07 +00:00
expect(fastModeLabel(snapshot)).toBe("off");
});
2026-05-29 00:44:25 +00:00
it("treats the catalog Fast service tier id as fast mode while preserving the id", () => {
const model = modelFixture("gpt-5.5");
// This mirrors Codex app-server 0.134.0 model/list: Fast is named "Fast" but its id is "priority".
model.serviceTiers = [{ id: "priority", name: "Fast", description: "1.5x speed, increased usage" }];
const snapshot = runtimeSnapshot({
activeModel: "gpt-5.5",
activeServiceTier: "priority",
effectiveConfig: effectiveConfigFixture({ model: "gpt-5.5" }),
availableModels: [model],
});
expect(currentServiceTier(snapshot)).toBe("priority");
expect(serviceTierLabel(snapshot)).toBe("priority");
expect(fastModeActive(snapshot)).toBe(true);
expect(fastModeLabel(snapshot)).toBe("on");
expect(fastServiceTierRequestValue(snapshot)).toBe("priority");
});
it("treats the Codex 0.134.0 reported default tier after clearing Fast as fast mode off", () => {
const model = modelFixture("gpt-5.5");
model.serviceTiers = [{ id: "priority", name: "Fast", description: "1.5x speed, increased usage" }];
const snapshot = runtimeSnapshot({
activeModel: "gpt-5.5",
activeServiceTier: "default",
effectiveConfig: effectiveConfigFixture({ model: "gpt-5.5" }),
availableModels: [model],
});
expect(currentServiceTier(snapshot)).toBe("default");
expect(serviceTierLabel(snapshot)).toBe("default");
expect(fastModeActive(snapshot)).toBe(false);
expect(fastModeLabel(snapshot)).toBe("off");
});
2026-05-22 21:01:07 +00:00
it("uses requested service tier above active and configured service tiers", () => {
const snapshot = runtimeSnapshot({
2026-06-01 02:07:59 +00:00
requestedServiceTier: setPendingRuntimeSetting("off"),
2026-05-28 09:16:54 +00:00
activeServiceTier: "flex",
2026-05-22 23:37:26 +00:00
effectiveConfig: effectiveConfigFixture({ service_tier: "fast" }),
});
2026-05-28 09:16:54 +00:00
expect(currentServiceTier(snapshot)).toBeNull();
expect(fastModeLabel(snapshot)).toBe("off");
});
it("resolves requested approval reviewer without adding it to turn runtime settings", () => {
2026-06-01 02:07:59 +00:00
const snapshot = runtimeSnapshot({ requestedApprovalsReviewer: setPendingRuntimeSetting("auto_review") });
2026-05-21 15:02:32 +00:00
expect(autoReviewActive(snapshot)).toBe(true);
expect(currentApprovalsReviewer(snapshot)).toBe("auto_review");
expect(requestedTurnRuntimeSettings(snapshot)).not.toHaveProperty("approvalsReviewer");
2026-05-21 15:02:32 +00:00
});
it("treats active thread runtime as display state without persisting it into turn overrides", () => {
const snapshot = runtimeSnapshot({
activeModel: "gpt-5-active",
activeServiceTier: "fast",
2026-05-22 23:37:26 +00:00
effectiveConfig: effectiveConfigFixture({}),
});
expect(currentModel(snapshot)).toBe("gpt-5-active");
expect(currentServiceTier(snapshot)).toBe("fast");
expect(requestedTurnRuntimeSettings(snapshot)).toMatchObject({
collaborationMode: {
mode: "default",
settings: { model: "gpt-5-active" },
},
});
expect(requestedTurnRuntimeSettings(snapshot)).not.toHaveProperty("model");
expect(requestedTurnRuntimeSettings(snapshot)).not.toHaveProperty("effort");
});
it("separates effective runtime, config defaults, and pending changes in status details", () => {
const sections = effectiveConfigSections(
runtimeSnapshot({
activeModel: "gpt-5-active",
activeReasoningEffort: "low",
activeCollaborationMode: "plan",
2026-06-01 02:07:59 +00:00
selectedCollaborationMode: "plan",
requestedModel: setPendingRuntimeSetting("gpt-5-pending"),
}),
"/vault",
);
const runtimeRows = Object.fromEntries(
sections.find((section) => section.title === "Runtime")?.rows.map((row) => [row.key, row.value]) ?? [],
);
expect(runtimeRows).toMatchObject({
"effective model": "gpt-5-pending",
"configured model": "gpt-5.5",
"thread model": "gpt-5-active",
"requested model": "gpt-5-pending",
"effective effort": "low",
"configured effort": "high",
"thread effort": "low",
"requested effort": "(none)",
"effective mode": "Plan",
"requested mode": "(none)",
2026-05-28 09:16:54 +00:00
"configured service tier": "flex",
"thread service tier": "(not reported)",
"requested service tier": "(none)",
});
const resetSections = effectiveConfigSections(
runtimeSnapshot({
2026-06-01 02:07:59 +00:00
requestedReasoningEffort: resetRuntimeSettingToConfig(),
}),
"/vault",
);
const resetRuntimeRows = Object.fromEntries(
resetSections.find((section) => section.title === "Runtime")?.rows.map((row) => [row.key, row.value]) ?? [],
);
expect(resetRuntimeRows["requested effort"]).toBe("(reset to config)");
});
it("labels unset config values as Codex defaults when no concrete value is reported", () => {
const sections = effectiveConfigSections(
runtimeSnapshot({
effectiveConfig: effectiveConfigFixture({}),
}),
"/vault",
);
const scopeRows = Object.fromEntries(
sections.find((section) => section.title === "Scope")?.rows.map((row) => [row.key, row.value]) ?? [],
);
const runtimeRows = Object.fromEntries(
sections.find((section) => section.title === "Runtime")?.rows.map((row) => [row.key, row.value]) ?? [],
);
const policyRows = Object.fromEntries(
sections.find((section) => section.title === "Policy")?.rows.map((row) => [row.key, row.value]) ?? [],
);
expect(scopeRows["model provider"]).toBe("(Codex default)");
expect(runtimeRows).toMatchObject({
"effective model": "(Codex default)",
"configured model": "(not reported)",
"thread model": "(not reported)",
"requested model": "(none)",
"configured service tier": "(Codex default)",
"thread service tier": "(not reported)",
"requested service tier": "(none)",
"fast mode": "Codex default",
});
expect(policyRows).toMatchObject({
2026-05-28 09:29:21 +00:00
"effective approval": "(Codex default)",
"configured approval": "(Codex default)",
"thread approval": "(not reported)",
"active permissions": "(not reported)",
"configured reviewer": "(Codex default)",
sandbox: "(Codex default)",
"web search": "(Codex default)",
});
});
it("shows effective profile runtime and policy values in status details", () => {
const profileConfig = {
model: "gpt-profile",
model_provider: "profile-provider",
model_reasoning_effort: "high",
model_reasoning_summary: "detailed",
model_verbosity: "high",
approval_policy: "never",
approvals_reviewer: "auto_review",
web_search: "live",
service_tier: "fast",
};
const sections = effectiveConfigSections(
runtimeSnapshot({
effectiveConfig: effectiveConfigFixture(profileConfig, [configLayer({}, null), configLayer(profileConfig, "auto")]),
}),
"/vault",
);
const scopeRows = Object.fromEntries(
sections.find((section) => section.title === "Scope")?.rows.map((row) => [row.key, row.value]) ?? [],
);
const runtimeRows = Object.fromEntries(
sections.find((section) => section.title === "Runtime")?.rows.map((row) => [row.key, row.value]) ?? [],
);
const policyRows = Object.fromEntries(
sections.find((section) => section.title === "Policy")?.rows.map((row) => [row.key, row.value]) ?? [],
);
expect(scopeRows["profile"]).toBe("auto");
expect(scopeRows["model provider"]).toBe("profile-provider");
expect(runtimeRows).toMatchObject({
"effective model": "gpt-profile",
"configured model": "gpt-profile",
"thread model": "(not reported)",
"requested model": "(none)",
"effective effort": "high",
"configured effort": "high",
"thread effort": "(not reported)",
"requested effort": "(none)",
"reasoning summary": "detailed",
verbosity: "high",
"effective service tier": "fast",
"configured service tier": "fast",
"thread service tier": "(not reported)",
"requested service tier": "(none)",
"fast mode": "on",
});
2026-05-28 09:29:21 +00:00
expect(policyRows["effective approval"]).toBe("never");
expect(policyRows["configured approval"]).toBe("never");
expect(policyRows["thread approval"]).toBe("(not reported)");
expect(policyRows["active permissions"]).toBe("(not reported)");
expect(policyRows["effective reviewer"]).toBe("auto_review");
expect(policyRows["auto-review"]).toBe("on");
expect(policyRows["configured reviewer"]).toBe("auto_review");
expect(policyRows["thread reviewer"]).toBe("(not reported)");
expect(policyRows["requested reviewer"]).toBe("(none)");
expect(policyRows["web search"]).toBe("live");
});
it("shows active and configured reviewer inputs in status details", () => {
const sections = effectiveConfigSections(
runtimeSnapshot({
activeApprovalsReviewer: "guardian_subagent",
2026-05-28 09:29:21 +00:00
activeApprovalPolicy: "never",
activePermissionProfile: { id: ":workspace", extends: ":default" },
2026-05-22 23:37:26 +00:00
effectiveConfig: effectiveConfigFixture({ approvals_reviewer: "auto_review" }),
}),
"/vault",
);
const policyRows = Object.fromEntries(
sections.find((section) => section.title === "Policy")?.rows.map((row) => [row.key, row.value]) ?? [],
);
expect(policyRows).toMatchObject({
2026-05-28 09:29:21 +00:00
"effective approval": "never",
"thread approval": "never",
"active permissions": ":workspace extends :default",
"effective reviewer": "guardian_subagent",
"auto-review": "on",
"configured reviewer": "auto_review",
"thread reviewer": "guardian_subagent",
});
});
2026-05-12 15:05:56 +00:00
it("summarizes service tier and context meter state from one runtime snapshot", () => {
2026-06-01 02:07:59 +00:00
const snapshot = runtimeSnapshot({ requestedServiceTier: setPendingRuntimeSetting("fast"), activeThreadId: "thread" });
2026-05-12 15:05:56 +00:00
expect(serviceTierLabel(snapshot)).toBe("fast");
expect(fastModeLabel(snapshot)).toBe("on");
expect(contextSummary(snapshot)).toMatchObject({
label: "Context 0%",
2026-05-25 02:48:22 +00:00
title: "Context: 0 / 100,000 (0%). No turns in this thread yet.",
2026-05-12 15:05:56 +00:00
percent: 0,
level: "ok",
});
2026-05-25 02:48:22 +00:00
expect(
contextSummary(
runtimeSnapshot({
activeThreadId: "thread",
tokenUsage: {
last: { inputTokens: 1000, cachedInputTokens: 0, outputTokens: 200, reasoningOutputTokens: 50, totalTokens: 1250 },
total: { inputTokens: 2000, cachedInputTokens: 0, outputTokens: 500, reasoningOutputTokens: 100, totalTokens: 2600 },
modelContextWindow: 100_000,
},
}),
),
).toMatchObject({
title: "Context: 1,000 / 100,000 (1%). Last request: 1,000 input, 200 output, 50 reasoning. Total: 2,600 tokens.",
});
2026-05-12 15:05:56 +00:00
expect(
contextSummary(
runtimeSnapshot({
activeThreadId: "thread",
2026-05-26 00:54:45 +00:00
hasThreadTurns: true,
2026-05-12 15:05:56 +00:00
}),
),
).toMatchObject({
label: "Context unknown",
percent: null,
});
});
it("serializes explicit fast off as a null service tier request", () => {
const snapshot = runtimeSnapshot({
2026-05-22 23:37:26 +00:00
effectiveConfig: effectiveConfigFixture({ service_tier: "fast" }),
2026-06-01 02:07:59 +00:00
requestedServiceTier: setPendingRuntimeSetting("off"),
2026-05-12 15:05:56 +00:00
});
2026-05-28 09:16:54 +00:00
expect(serviceTierLabel(snapshot)).toBe("(Codex default)");
2026-05-12 15:05:56 +00:00
expect(fastModeLabel(snapshot)).toBe("off");
expect(requestedOrConfiguredServiceTier(snapshot)).toBeNull();
});
2026-05-29 00:44:25 +00:00
it("serializes requested fast mode using the catalog Fast service tier id", () => {
const model = modelFixture("gpt-5.5");
model.serviceTiers = [{ id: "priority", name: "Fast", description: "1.5x speed, increased usage" }];
const snapshot = runtimeSnapshot({
2026-06-01 02:07:59 +00:00
requestedServiceTier: setPendingRuntimeSetting("fast"),
2026-05-29 00:44:25 +00:00
effectiveConfig: effectiveConfigFixture({ model: "gpt-5.5" }),
availableModels: [model],
});
expect(fastModeLabel(snapshot)).toBe("on");
expect(requestedOrConfiguredServiceTier(snapshot)).toBe("priority");
});
2026-05-12 15:05:56 +00:00
it("omits service tier when neither config nor override selects one", () => {
2026-05-22 23:37:26 +00:00
expect(requestedOrConfiguredServiceTier(runtimeSnapshot({ effectiveConfig: effectiveConfigFixture({}) }))).toBeUndefined();
2026-05-12 15:05:56 +00:00
});
2026-05-28 09:16:54 +00:00
it("passes through configured non-fast service tier ids", () => {
const snapshot = runtimeSnapshot({ effectiveConfig: effectiveConfigFixture({ service_tier: "flex" }) });
expect(serviceTierLabel(snapshot)).toBe("flex");
expect(fastModeLabel(snapshot)).toBe("off");
expect(requestedOrConfiguredServiceTier(snapshot)).toBe("flex");
});
2026-05-12 15:05:56 +00:00
it("summarizes Codex usage limits independently from context usage", () => {
expect(
rateLimitSummary(
runtimeSnapshot({
rateLimit: {
limitId: "codex",
limitName: "Codex",
primary: { usedPercent: 72.4, windowDurationMins: 300, resetsAt: 1_800_000_000 },
secondary: null,
credits: null,
2026-06-04 02:54:53 +00:00
individualLimit: null,
2026-05-12 15:05:56 +00:00
planType: null,
rateLimitReachedType: null,
},
}),
1_799_991_600_000,
),
).toMatchObject({
2026-06-04 03:15:31 +00:00
rows: [{ label: "5h", value: "72%", resetLabel: "reset in 2h 20m", percent: 72, meterDivisions: 5 }],
2026-05-12 15:05:56 +00:00
level: "warn",
});
expect(
rateLimitSummary(
runtimeSnapshot({
rateLimit: {
limitId: "codex",
limitName: null,
primary: { usedPercent: 95, windowDurationMins: null, resetsAt: null },
secondary: null,
credits: null,
2026-06-04 02:54:53 +00:00
individualLimit: null,
2026-05-12 15:05:56 +00:00
planType: null,
rateLimitReachedType: "rate_limit_reached",
},
}),
),
).toMatchObject({
rows: [{ percent: 95, resetLabel: null }],
level: "danger",
});
expect(
rateLimitSummary(
runtimeSnapshot({
rateLimit: {
limitId: "codex",
limitName: "Codex",
primary: { usedPercent: 15, windowDurationMins: 300, resetsAt: null },
secondary: { usedPercent: 38, windowDurationMins: 10_080, resetsAt: null },
credits: null,
2026-06-04 02:54:53 +00:00
individualLimit: null,
2026-05-12 15:05:56 +00:00
planType: null,
rateLimitReachedType: null,
},
}),
),
).toMatchObject({
rows: [
2026-06-04 03:15:31 +00:00
{ label: "5h", value: "15%", meterDivisions: 5 },
{ label: "1w", value: "38%", meterDivisions: 7 },
2026-05-12 15:05:56 +00:00
],
level: "ok",
});
expect(
rateLimitSummary(
runtimeSnapshot({
rateLimit: {
limitId: "codex",
limitName: "Codex",
primary: { usedPercent: 10, windowDurationMins: 300, resetsAt: 1_800_000_000 },
secondary: null,
credits: null,
2026-06-04 02:54:53 +00:00
individualLimit: null,
2026-05-12 15:05:56 +00:00
planType: null,
rateLimitReachedType: null,
},
}),
1_800_000_001_000,
),
).toMatchObject({
rows: [{ resetLabel: "reset due" }],
});
2026-06-04 02:54:53 +00:00
expect(
rateLimitSummary(
runtimeSnapshot({
rateLimit: {
limitId: "codex",
limitName: "Codex",
primary: null,
secondary: null,
credits: null,
individualLimit: { limit: "$100", used: "$72", remainingPercent: 28, resetsAt: 1_800_000_000 },
planType: null,
rateLimitReachedType: null,
},
}),
1_799_991_600_000,
),
).toMatchObject({
2026-06-04 03:15:31 +00:00
rows: [{ label: "monthly", value: "$72 / $100", resetLabel: "reset in 2h 20m", percent: 72, meterDivisions: null }],
2026-06-04 02:54:53 +00:00
level: "warn",
});
2026-05-12 15:05:56 +00:00
});
});
function runtimeSnapshot(overrides: Partial<RuntimeSnapshot> = {}): RuntimeSnapshot {
return {
2026-05-22 23:37:26 +00:00
effectiveConfig: effectiveConfigFixture({
model: "gpt-5.5",
model_reasoning_effort: "high",
2026-05-28 09:16:54 +00:00
service_tier: "flex",
2026-05-22 23:37:26 +00:00
model_context_window: 100_000,
}),
2026-05-12 15:05:56 +00:00
activeThreadId: null,
activeModel: null,
activeReasoningEffort: null,
activeCollaborationMode: "default",
2026-05-12 15:05:56 +00:00
activeServiceTier: null,
2026-05-28 09:29:21 +00:00
activeApprovalPolicy: null,
2026-05-21 15:02:32 +00:00
activeApprovalsReviewer: null,
2026-05-28 09:29:21 +00:00
activePermissionProfile: null,
2026-06-01 02:07:59 +00:00
requestedModel: { kind: "unchanged" },
requestedReasoningEffort: { kind: "unchanged" },
requestedApprovalsReviewer: { kind: "unchanged" },
selectedCollaborationMode: "default",
requestedServiceTier: { kind: "unchanged" },
2026-05-12 15:05:56 +00:00
tokenUsage: null,
rateLimit: null,
2026-05-26 00:54:45 +00:00
hasThreadTurns: false,
2026-05-12 15:05:56 +00:00
availableModels: [],
...overrides,
};
}
2026-05-22 23:37:26 +00:00
function effectiveConfigFixture(config: Record<string, unknown>, layers: ConfigReadResponse["layers"] = null): ConfigReadResponse {
return {
config: config as ConfigReadResponse["config"],
origins: {},
layers,
};
}
function configLayer(config: Record<string, unknown>, profile: string | null): NonNullable<ConfigReadResponse["layers"]>[number] {
return {
name: { type: "user", file: "/home/me/.codex/config.toml", profile },
version: "1",
config: config as NonNullable<ConfigReadResponse["layers"]>[number]["config"],
disabledReason: null,
};
}
function threadFixture(id: string): Thread {
return {
id,
sessionId: "session",
forkedFromId: null,
2026-06-04 02:54:53 +00:00
parentThreadId: null,
preview: "",
ephemeral: false,
modelProvider: "openai",
createdAt: 1,
updatedAt: 1,
status: { type: "idle" },
path: null,
cwd: "/vault",
cliVersion: "0.0.0",
source: "appServer",
threadSource: null,
agentNickname: null,
agentRole: null,
gitInfo: null,
name: null,
turns: [],
};
}
function modelFixture(model: string): Model {
return {
id: model,
model,
upgrade: null,
upgradeInfo: null,
availabilityNux: null,
displayName: model,
description: "",
hidden: false,
supportedReasoningEfforts: [],
defaultReasoningEffort: "medium",
inputModalities: [],
supportsPersonality: false,
additionalSpeedTiers: [],
serviceTiers: [],
defaultServiceTier: null,
isDefault: false,
};
}