Resolve profile runtime config for toolbar

This commit is contained in:
murashit 2026-05-22 12:30:45 +09:00
parent c05364addf
commit d26f9f58a8
10 changed files with 379 additions and 28 deletions

View file

@ -170,7 +170,7 @@ export class AppServerClient {
}
readEffectiveConfig(cwd: string): Promise<ConfigReadResponse> {
return this.request("config/read", { cwd, includeLayers: false });
return this.request("config/read", { cwd, includeLayers: true });
}
listHooks(cwd: string): Promise<HooksListResponse> {

View file

@ -427,8 +427,13 @@ export class PanelController {
this.state.activeReasoningEffort = settings.effort ?? null;
this.state.activeCollaborationMode = settings.collaborationMode.mode;
this.state.requestedCollaborationMode = settings.collaborationMode.mode;
this.state.activeServiceTier = settings.serviceTier ?? null;
this.state.activeApprovalsReviewer = settings.approvalsReviewer ?? null;
const serviceTierOverride = this.state.activeServiceTierOverride || this.state.requestedServiceTier !== null;
const approvalsReviewerOverride = this.state.activeApprovalsReviewerOverride || this.state.requestedApprovalsReviewer !== null;
this.state.activeServiceTier = settings.serviceTier ?? (serviceTierOverride ? this.state.activeServiceTier : null);
this.state.activeServiceTierOverride = serviceTierOverride;
this.state.activeApprovalsReviewer =
settings.approvalsReviewer ?? (approvalsReviewerOverride ? this.state.activeApprovalsReviewer : null);
this.state.activeApprovalsReviewerOverride = approvalsReviewerOverride;
}
}

View file

@ -48,7 +48,9 @@ export class PanelSessionController {
this.host.state.activeModel = response.model ?? null;
this.host.state.activeReasoningEffort = response.reasoningEffort ?? null;
this.host.state.activeServiceTier = response.serviceTier ?? null;
this.host.state.activeServiceTierOverride = false;
this.host.state.activeApprovalsReviewer = response.approvalsReviewer ?? null;
this.host.state.activeApprovalsReviewerOverride = false;
this.host.state.activeThreadCliVersion = response.thread.cliVersion ?? null;
this.host.state.tokenUsage = null;
this.host.state.historyCursor = null;

View file

@ -33,7 +33,9 @@ export interface PanelState {
activeReasoningEffort: ReasoningEffort | null;
activeCollaborationMode: ModeKind;
activeServiceTier: string | null;
activeServiceTierOverride: boolean;
activeApprovalsReviewer: ApprovalsReviewer | null;
activeApprovalsReviewerOverride: boolean;
activeThreadCliVersion: string | null;
appServerDiagnostics: AppServerDiagnostics;
requestedModel: RuntimeOverride<string>;
@ -78,7 +80,9 @@ export function createPanelState(): PanelState {
activeReasoningEffort: null,
activeCollaborationMode: "default",
activeServiceTier: null,
activeServiceTierOverride: false,
activeApprovalsReviewer: null,
activeApprovalsReviewerOverride: false,
activeThreadCliVersion: null,
appServerDiagnostics: createAppServerDiagnostics(),
requestedModel: defaultRuntimeOverride(),
@ -128,7 +132,9 @@ export function clearActiveThreadState(state: PanelState): void {
state.activeReasoningEffort = null;
state.activeCollaborationMode = "default";
state.activeServiceTier = null;
state.activeServiceTierOverride = false;
state.activeApprovalsReviewer = null;
state.activeApprovalsReviewerOverride = false;
state.activeThreadCliVersion = null;
state.tokenUsage = null;
state.historyCursor = null;
@ -145,7 +151,9 @@ export function clearConnectionScopedState(state: PanelState): void {
state.activeReasoningEffort = null;
state.activeCollaborationMode = "default";
state.activeServiceTier = null;
state.activeServiceTierOverride = false;
state.activeApprovalsReviewer = null;
state.activeApprovalsReviewerOverride = false;
state.activeThreadCliVersion = null;
state.rateLimit = null;
state.listedThreads = [];

View file

@ -32,6 +32,7 @@ import {
currentServiceTier,
defaultRuntimeOverride,
requestedTurnRuntimeSettings,
resolvedConfigValue,
resetRuntimeOverride,
runtimeOverridePayload,
runtimeOverrideLabel,
@ -329,7 +330,9 @@ export class CodexPanelView extends ItemView {
this.state.activeModel = response.model ?? null;
this.state.activeReasoningEffort = response.reasoningEffort ?? null;
this.state.activeServiceTier = response.serviceTier ?? null;
this.state.activeServiceTierOverride = false;
this.state.activeApprovalsReviewer = response.approvalsReviewer ?? null;
this.state.activeApprovalsReviewerOverride = false;
this.state.activeThreadCliVersion = response.thread.cliVersion ?? null;
this.state.tokenUsage = null;
this.state.displayItems = [];
@ -631,10 +634,12 @@ export class CodexPanelView extends ItemView {
}
if ("serviceTier" in update) {
this.state.activeServiceTier = this.state.requestedServiceTier === "standard" ? "standard" : (update.serviceTier ?? null);
this.state.activeServiceTierOverride = true;
this.state.requestedServiceTier = null;
}
if ("approvalsReviewer" in update) {
this.state.activeApprovalsReviewer = update.approvalsReviewer ?? null;
this.state.activeApprovalsReviewerOverride = true;
this.state.requestedApprovalsReviewer = null;
}
if (update.collaborationMode) {
@ -647,6 +652,7 @@ export class CodexPanelView extends ItemView {
const next: ServiceTier = current === "fast" ? "standard" : "fast";
this.state.requestedServiceTier = next;
this.state.activeServiceTier = next;
this.state.activeServiceTierOverride = true;
this.state.runtimePicker = null;
if (!(await this.applyPendingThreadSettings())) return;
this.addSystemMessage(next === "fast" ? "Fast mode on for subsequent turns." : "Fast mode off for subsequent turns.");
@ -666,6 +672,7 @@ export class CodexPanelView extends ItemView {
: "auto_review";
this.state.requestedApprovalsReviewer = next;
this.state.activeApprovalsReviewer = next;
this.state.activeApprovalsReviewerOverride = true;
this.state.runtimePicker = null;
if (!(await this.applyPendingThreadSettings())) return;
this.addSystemMessage(next === "auto_review" ? "Auto-review on for subsequent turns." : "Auto-review off for subsequent turns.");
@ -1009,7 +1016,7 @@ export class CodexPanelView extends ItemView {
return [
`Model: ${currentModel(snapshot, config) ?? "(from default)"}`,
`Override: ${runtimeOverrideLabel(this.state.requestedModel)}`,
`Provider: ${statusValue(config.model_provider, "(from default)")}`,
`Provider: ${statusValue(resolvedConfigValue(config, "model_provider"), "(from default)")}`,
`Effort: ${currentReasoningEffort(snapshot, config) ?? "(from default)"}`,
`Mode: ${this.collaborationModeLabel()}`,
`Service tier: ${serviceTierLabel(snapshot, config)}`,
@ -1067,7 +1074,9 @@ export class CodexPanelView extends ItemView {
activeReasoningEffort: this.state.activeReasoningEffort,
activeCollaborationMode: this.state.activeCollaborationMode,
activeServiceTier: this.state.activeServiceTier,
activeServiceTierOverride: this.state.activeServiceTierOverride,
activeApprovalsReviewer: this.state.activeApprovalsReviewer,
activeApprovalsReviewerOverride: this.state.activeApprovalsReviewerOverride,
requestedModel: this.state.requestedModel,
requestedReasoningEffort: this.state.requestedReasoningEffort,
requestedApprovalsReviewer: this.state.requestedApprovalsReviewer,

View file

@ -21,7 +21,9 @@ export interface RuntimeSnapshot {
activeReasoningEffort: ReasoningEffort | null;
activeCollaborationMode: ModeKind;
activeServiceTier: string | null;
activeServiceTierOverride: boolean;
activeApprovalsReviewer: ApprovalsReviewer | null;
activeApprovalsReviewerOverride: boolean;
requestedModel: RuntimeOverride<string>;
requestedReasoningEffort: RuntimeOverride<ReasoningEffort>;
requestedApprovalsReviewer: ApprovalsReviewer | null;
@ -39,16 +41,26 @@ export interface TurnRuntimeSettings {
}
export function configRecord(effectiveConfig: ConfigReadResponse | null): Record<string, unknown> {
return asRecord(effectiveConfig?.config);
return fillMissingConfigValues(asRecord(effectiveConfig?.config), effectiveConfig?.layers ?? null);
}
export function selectedProfileConfig(config: Record<string, unknown>): Record<string, unknown> {
const profileName = typeof config.profile === "string" && config.profile.length > 0 ? config.profile : null;
return profileName ? asRecord(asRecord(config.profiles)[profileName]) : {};
}
export function resolvedConfigValue(config: Record<string, unknown>, key: string): unknown {
const profileValue = selectedProfileConfig(config)[key];
return profileValue === undefined || profileValue === null ? config[key] : profileValue;
}
export function currentServiceTier(snapshot: RuntimeSnapshot, config = configRecord(snapshot.effectiveConfig)): string | null {
return (
snapshot.requestedServiceTier ??
parseServiceTier(snapshot.activeServiceTier) ??
snapshot.activeServiceTier ??
configuredServiceTier(config)
);
const active = parseServiceTier(snapshot.activeServiceTier) ?? snapshot.activeServiceTier;
const configured = configuredServiceTier(config);
if (snapshot.requestedServiceTier !== null) return snapshot.requestedServiceTier;
if (snapshot.activeServiceTierOverride) return active ?? configured;
if (configured && (active === null || active === "standard")) return configured;
return active ?? configured;
}
export function requestedOrConfiguredServiceTier(
@ -59,7 +71,7 @@ export function requestedOrConfiguredServiceTier(
}
export function currentModel(snapshot: RuntimeSnapshot, config = configRecord(snapshot.effectiveConfig)): string | null {
const model = config.model;
const model = resolvedConfigValue(config, "model");
const configModel = typeof model === "string" && model.length > 0 ? model : null;
if (snapshot.requestedModel.kind === "set") return snapshot.requestedModel.value;
if (snapshot.requestedModel.kind === "resetPending" && configModel) return configModel;
@ -68,7 +80,7 @@ export function currentModel(snapshot: RuntimeSnapshot, config = configRecord(sn
export function currentReasoningEffort(snapshot: RuntimeSnapshot, config = configRecord(snapshot.effectiveConfig)): ReasoningEffort | null {
if (snapshot.requestedReasoningEffort.kind === "set") return snapshot.requestedReasoningEffort.value;
const effort = config.model_reasoning_effort;
const effort = resolvedConfigValue(config, "model_reasoning_effort");
if (snapshot.requestedReasoningEffort.kind === "resetPending") return isReasoningEffort(effort) ? effort : null;
return snapshot.activeReasoningEffort ?? (isReasoningEffort(effort) ? effort : null);
}
@ -77,12 +89,20 @@ export function currentApprovalsReviewer(
snapshot: RuntimeSnapshot,
config = configRecord(snapshot.effectiveConfig),
): ApprovalsReviewer | null {
const configured = config.approvals_reviewer;
return snapshot.requestedApprovalsReviewer ?? snapshot.activeApprovalsReviewer ?? (isApprovalsReviewer(configured) ? configured : null);
const configured = configuredApprovalsReviewer(config);
if (snapshot.requestedApprovalsReviewer !== null) return snapshot.requestedApprovalsReviewer;
if (snapshot.activeApprovalsReviewerOverride) return snapshot.activeApprovalsReviewer ?? configured;
if (configured && (!snapshot.activeApprovalsReviewer || snapshot.activeApprovalsReviewer === "user")) return configured;
return snapshot.activeApprovalsReviewer ?? configured;
}
export function autoReviewActive(snapshot: RuntimeSnapshot, config = configRecord(snapshot.effectiveConfig)): boolean {
return currentApprovalsReviewer(snapshot, config) === "auto_review";
return isAutoReviewReviewer(currentApprovalsReviewer(snapshot, config));
}
export function configuredApprovalsReviewer(config: Record<string, unknown>): ApprovalsReviewer | null {
const value = resolvedConfigValue(config, "approvals_reviewer");
return isApprovalsReviewer(value) ? value : null;
}
export function requestedTurnRuntimeSettings(snapshot: RuntimeSnapshot): TurnRuntimeSettings {
@ -146,14 +166,43 @@ export function runtimeOverrideLabel<T>(override: RuntimeOverride<T>): string {
return "(none)";
}
function configuredServiceTier(config: Record<string, unknown>): ServiceTier | null {
return parseServiceTier(config.service_tier);
export function configuredServiceTier(config: Record<string, unknown>): ServiceTier | null {
return parseServiceTier(resolvedConfigValue(config, "service_tier"));
}
function isApprovalsReviewer(value: unknown): value is ApprovalsReviewer {
return value === "user" || value === "auto_review" || value === "guardian_subagent";
}
function isAutoReviewReviewer(value: ApprovalsReviewer | null): boolean {
return value === "auto_review" || value === "guardian_subagent";
}
function asRecord(value: unknown): Record<string, unknown> {
return value && typeof value === "object" ? (value as Record<string, unknown>) : {};
}
function fillMissingConfigValues(config: Record<string, unknown>, layers: ConfigReadResponse["layers"]): Record<string, unknown> {
if (!layers || layers.length === 0) return config;
const fallback = rawLayerConfigRecord(layers);
if (Object.keys(fallback).length === 0) return config;
const merged = { ...config };
for (const [key, value] of Object.entries(fallback)) {
if (merged[key] === undefined || merged[key] === null) {
merged[key] = value;
}
}
return merged;
}
function rawLayerConfigRecord(layers: NonNullable<ConfigReadResponse["layers"]>): Record<string, unknown> {
const merged: Record<string, unknown> = {};
for (const layer of layers) {
const config = asRecord(layer.config);
for (const [key, value] of Object.entries(config)) {
if (value !== undefined && value !== null) merged[key] = value;
}
}
return merged;
}

View file

@ -4,9 +4,14 @@ import { jsonPreview } from "../utils";
import { sortedAvailableModels } from "./model";
import {
configRecord,
configuredApprovalsReviewer,
configuredServiceTier,
currentApprovalsReviewer,
currentModel,
currentReasoningEffort,
autoReviewActive,
fastModeLabel,
resolvedConfigValue,
runtimeOverrideLabel,
serviceTierLabel,
type RuntimeSnapshot,
@ -102,7 +107,7 @@ export function rateLimitSummary(snapshot: RuntimeSnapshot, nowMs = Date.now()):
export function effectiveConfigSections(snapshot: RuntimeSnapshot, vaultPath: string): EffectiveConfigSection[] {
const config = configRecord(snapshot.effectiveConfig);
const features = asRecord(config.features);
const tools = asRecord(config.tools);
const tools = asRecord(resolvedConfigValue(config, "tools"));
const workspaceWrite = asRecord(config.sandbox_workspace_write);
return [
{
@ -110,7 +115,7 @@ export function effectiveConfigSections(snapshot: RuntimeSnapshot, vaultPath: st
rows: [
{ key: "cwd", value: vaultPath },
{ key: "profile", value: stringValue(config.profile, "(default)") },
{ key: "model provider", value: stringValue(config.model_provider, "(from default)") },
{ key: "model provider", value: stringValue(resolvedConfigValue(config, "model_provider"), "(from default)") },
],
},
{
@ -122,8 +127,8 @@ export function effectiveConfigSections(snapshot: RuntimeSnapshot, vaultPath: st
{ key: "effort", value: currentReasoningEffort(snapshot, config) ?? "(from default)" },
{ key: "config effort", value: configuredReasoningEffort(snapshot, config) ?? "(not reported)" },
{ key: "effort change", value: runtimeOverrideLabel(snapshot.requestedReasoningEffort) },
{ key: "reasoning summary", value: stringValue(config.model_reasoning_summary, "(from default)") },
{ key: "verbosity", value: stringValue(config.model_verbosity, "(from default)") },
{ key: "reasoning summary", value: stringValue(resolvedConfigValue(config, "model_reasoning_summary"), "(from default)") },
{ key: "verbosity", value: stringValue(resolvedConfigValue(config, "model_verbosity"), "(from default)") },
{ key: "mode", value: snapshot.activeCollaborationMode === "plan" ? "Plan" : "Default" },
{
key: "mode change",
@ -133,6 +138,8 @@ export function effectiveConfigSections(snapshot: RuntimeSnapshot, vaultPath: st
: modeLabel(snapshot.requestedCollaborationMode),
},
{ key: "service tier", value: serviceTierLabel(snapshot, config) },
{ key: "config service tier", value: configuredServiceTier(config) ?? "(not reported)" },
{ key: "active service tier", value: activeRuntimeValueLabel(snapshot.activeServiceTier, snapshot.activeServiceTierOverride) },
{ key: "fast mode", value: fastModeLabel(snapshot, config) },
{ key: "context window", value: tokenLimitLabel(config.model_context_window) },
{ key: "auto compact limit", value: tokenLimitLabel(config.model_auto_compact_token_limit) },
@ -141,12 +148,18 @@ export function effectiveConfigSections(snapshot: RuntimeSnapshot, vaultPath: st
{
title: "Policy",
rows: [
{ key: "approval", value: stringValue(config.approval_policy, "(from default)") },
{ key: "reviewer", value: stringValue(config.approvals_reviewer, "(from default)") },
{ key: "approval", value: stringValue(resolvedConfigValue(config, "approval_policy"), "(from default)") },
{ key: "reviewer", value: currentApprovalsReviewer(snapshot, config) ?? "(not reported)" },
{ key: "auto-review", value: autoReviewActive(snapshot, config) ? "on" : "off" },
{ key: "config reviewer", value: configuredApprovalsReviewer(config) ?? "(from default)" },
{
key: "active reviewer",
value: activeRuntimeValueLabel(snapshot.activeApprovalsReviewer, snapshot.activeApprovalsReviewerOverride),
},
{ key: "sandbox", value: stringValue(config.sandbox_mode, "(from default)") },
{ key: "workspace network", value: stringValue(workspaceWrite.network_access, "(from default)") },
{ key: "writable roots", value: writableRootsLabel(workspaceWrite.writable_roots) },
{ key: "web search", value: stringValue(config.web_search, "(from default)") },
{ key: "web search", value: stringValue(resolvedConfigValue(config, "web_search"), "(from default)") },
],
},
{
@ -166,13 +179,15 @@ function contextUsageTokens(usage: ThreadTokenUsage): number {
}
function configuredModel(snapshot: RuntimeSnapshot, config: Record<string, unknown>): string | null {
if (typeof config.model === "string" && config.model.length > 0) return config.model;
const model = resolvedConfigValue(config, "model");
if (typeof model === "string" && model.length > 0) return model;
return sortedAvailableModels(snapshot.availableModels).find((model) => model.isDefault)?.model ?? null;
}
function configuredReasoningEffort(snapshot: RuntimeSnapshot, config: Record<string, unknown>): string | null {
if (typeof config.model_reasoning_effort === "string" && config.model_reasoning_effort.length > 0) {
return config.model_reasoning_effort;
const effort = resolvedConfigValue(config, "model_reasoning_effort");
if (typeof effort === "string" && effort.length > 0) {
return effort;
}
const model = configuredModel(snapshot, config);
return (
@ -184,6 +199,10 @@ function modeLabel(mode: RuntimeSnapshot["requestedCollaborationMode"]): string
return mode === "plan" ? "Plan" : "Default";
}
function activeRuntimeValueLabel(value: string | null, override: boolean): string {
return `${value ?? "(not reported)"}${override ? " (override)" : ""}`;
}
function rateLimitWindowSummary(
fallbackLabel: string,
window: RateLimitWindow | null,

View file

@ -377,6 +377,19 @@ describe("AppServerClient", () => {
await update;
});
it("requests effective config with raw layers for display fallbacks", async () => {
const { client, transport } = await connectedClient();
const reading = client.readEffectiveConfig("/vault");
expect(transport.sent[2]).toMatchObject({
id: 2,
method: "config/read",
params: { cwd: "/vault", includeLayers: true },
});
transport.emitLine({ id: 2, result: { config: {}, origins: {}, layers: [] } });
await reading;
});
it("sends model list request payloads", async () => {
const { client, transport } = await connectedClient();

View file

@ -1029,6 +1029,41 @@ describe("PanelController", () => {
expect(state.displayItems).toEqual([]);
});
it("preserves explicit standard service tier when settings notifications report null", () => {
const state = createPanelState();
state.activeThreadId = "thread-active";
state.activeServiceTier = "standard";
state.activeServiceTierOverride = true;
const controller = controllerForState(state);
controller.handleNotification({
method: "thread/settings/updated",
params: {
threadId: "thread-active",
threadSettings: {
cwd: "/workspace/active",
approvalPolicy: "on-request",
approvalsReviewer: "user",
sandboxPolicy: { type: "readOnly", networkAccess: false },
activePermissionProfile: null,
model: "gpt-5.5",
modelProvider: "openai",
serviceTier: null,
effort: "high",
summary: null,
collaborationMode: {
mode: "default",
settings: { model: "gpt-5.5", reasoning_effort: "high", developer_instructions: null },
},
personality: null,
},
},
} satisfies Extract<ServerNotification, { method: "thread/settings/updated" }>);
expect(state.activeServiceTier).toBe("standard");
expect(state.activeServiceTierOverride).toBe(true);
});
it("keeps goal notifications out of the message stream", () => {
const state = createPanelState();
state.activeThreadId = "thread-active";

View file

@ -11,6 +11,7 @@ import {
} from "../../src/runtime/settings";
import {
autoReviewActive,
configRecord,
currentApprovalsReviewer,
currentModel,
currentReasoningEffort,
@ -119,6 +120,128 @@ describe("runtime settings", () => {
).toBe("guardian_subagent");
});
it("lets config auto-review beat an implicit initial user reviewer", () => {
const snapshot = runtimeSnapshot({
activeApprovalsReviewer: "user",
activeApprovalsReviewerOverride: false,
effectiveConfig: { config: { approvals_reviewer: "auto_review" } } as unknown as RuntimeSnapshot["effectiveConfig"],
});
expect(currentApprovalsReviewer(snapshot)).toBe("auto_review");
expect(autoReviewActive(snapshot)).toBe(true);
});
it("uses raw config layers when typed config omits approval reviewer", () => {
const config = configRecord({
config: {
approvals_reviewer: null,
},
layers: [
{
name: { type: "user", file: "/home/me/.codex/config.toml", profile: null },
version: "1",
config: { approvals_reviewer: "auto_review" },
disabledReason: null,
},
],
} as unknown as RuntimeSnapshot["effectiveConfig"]);
const snapshot = runtimeSnapshot({
activeApprovalsReviewer: "user",
activeApprovalsReviewerOverride: false,
effectiveConfig: { config } as unknown as RuntimeSnapshot["effectiveConfig"],
});
expect(config.approvals_reviewer).toBe("auto_review");
expect(autoReviewActive(snapshot, config)).toBe(true);
});
it("treats guardian subagent reviewer as active auto-review", () => {
const snapshot = runtimeSnapshot({
activeApprovalsReviewer: "guardian_subagent",
activeApprovalsReviewerOverride: false,
});
expect(currentApprovalsReviewer(snapshot)).toBe("guardian_subagent");
expect(autoReviewActive(snapshot)).toBe(true);
});
it("keeps an explicit user reviewer override above config auto-review", () => {
const snapshot = runtimeSnapshot({
activeApprovalsReviewer: "user",
activeApprovalsReviewerOverride: true,
effectiveConfig: { config: { approvals_reviewer: "auto_review" } } as unknown as RuntimeSnapshot["effectiveConfig"],
});
expect(currentApprovalsReviewer(snapshot)).toBe("user");
expect(autoReviewActive(snapshot)).toBe(false);
});
it("resolves approval reviewer from the selected config profile", () => {
const snapshot = runtimeSnapshot({
effectiveConfig: {
config: {
approvals_reviewer: "user",
profile: "auto",
profiles: {
auto: { approvals_reviewer: "auto_review" },
},
},
} as unknown as RuntimeSnapshot["effectiveConfig"],
});
expect(currentApprovalsReviewer(snapshot)).toBe("auto_review");
expect(autoReviewActive(snapshot)).toBe(true);
});
it("resolves model, effort, and fast mode from the selected config profile", () => {
const snapshot = runtimeSnapshot({
effectiveConfig: {
config: {
model: "gpt-root",
model_reasoning_effort: "low",
service_tier: "standard",
profile: "fast-profile",
profiles: {
"fast-profile": {
model: "gpt-profile",
model_reasoning_effort: "high",
service_tier: "fast",
},
},
},
} as unknown as RuntimeSnapshot["effectiveConfig"],
});
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");
});
it("lets config fast mode beat an implicit initial standard service tier", () => {
const snapshot = runtimeSnapshot({
activeServiceTier: "standard",
activeServiceTierOverride: false,
effectiveConfig: { config: { service_tier: "fast" } } as unknown as RuntimeSnapshot["effectiveConfig"],
});
expect(currentServiceTier(snapshot)).toBe("fast");
expect(fastModeLabel(snapshot)).toBe("on");
});
it("keeps an explicit standard service tier override above config fast mode", () => {
const snapshot = runtimeSnapshot({
activeServiceTier: "standard",
activeServiceTierOverride: true,
effectiveConfig: { config: { service_tier: "fast" } } as unknown as RuntimeSnapshot["effectiveConfig"],
});
expect(currentServiceTier(snapshot)).toBe("standard");
expect(fastModeLabel(snapshot)).toBe("off");
});
it("resolves requested approval reviewer without adding it to turn runtime settings", () => {
const snapshot = runtimeSnapshot({ requestedApprovalsReviewer: "auto_review" });
@ -170,6 +293,8 @@ describe("runtime settings", () => {
"effort change": "(none)",
mode: "Plan",
"mode change": "(none)",
"config service tier": "standard",
"active service tier": "(not reported)",
});
const resetSections = effectiveConfigSections(
@ -184,6 +309,90 @@ describe("runtime settings", () => {
expect(resetRuntimeRows["effort change"]).toBe("(reset to config)");
});
it("shows selected profile runtime and policy values in status details", () => {
const sections = effectiveConfigSections(
runtimeSnapshot({
effectiveConfig: {
config: {
model: "gpt-root",
model_provider: "root-provider",
model_reasoning_effort: "low",
model_reasoning_summary: "auto",
model_verbosity: "low",
approval_policy: "on-request",
web_search: "disabled",
service_tier: "standard",
profile: "auto",
profiles: {
auto: {
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",
},
},
},
} as unknown as RuntimeSnapshot["effectiveConfig"],
}),
"/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("profile-provider");
expect(runtimeRows).toMatchObject({
model: "gpt-profile",
"config model": "gpt-profile",
effort: "high",
"config effort": "high",
"reasoning summary": "detailed",
verbosity: "high",
"service tier": "fast",
"config service tier": "fast",
"active service tier": "(not reported)",
"fast mode": "on",
});
expect(policyRows.approval).toBe("never");
expect(policyRows.reviewer).toBe("auto_review");
expect(policyRows["auto-review"]).toBe("on");
expect(policyRows["config reviewer"]).toBe("auto_review");
expect(policyRows["active reviewer"]).toBe("(not reported)");
expect(policyRows["web search"]).toBe("live");
});
it("shows active and configured reviewer inputs in status details", () => {
const sections = effectiveConfigSections(
runtimeSnapshot({
activeApprovalsReviewer: "guardian_subagent",
activeApprovalsReviewerOverride: false,
effectiveConfig: { config: { approvals_reviewer: "auto_review" } } as unknown as RuntimeSnapshot["effectiveConfig"],
}),
"/vault",
);
const policyRows = Object.fromEntries(
sections.find((section) => section.title === "Policy")?.rows.map((row) => [row.key, row.value]) ?? [],
);
expect(policyRows).toMatchObject({
reviewer: "guardian_subagent",
"auto-review": "on",
"config reviewer": "auto_review",
"active reviewer": "guardian_subagent",
});
});
it("summarizes service tier and context meter state from one runtime snapshot", () => {
const snapshot = runtimeSnapshot({ requestedServiceTier: "fast", activeThreadId: "thread" });
@ -324,7 +533,9 @@ function runtimeSnapshot(overrides: Partial<RuntimeSnapshot> = {}): RuntimeSnaps
activeReasoningEffort: null,
activeCollaborationMode: "default",
activeServiceTier: null,
activeServiceTierOverride: false,
activeApprovalsReviewer: null,
activeApprovalsReviewerOverride: false,
requestedModel: { kind: "default" },
requestedReasoningEffort: { kind: "default" },
requestedApprovalsReviewer: null,