mirror of
https://github.com/murashit/codex-panel.git
synced 2026-07-22 06:57:10 +00:00
Unify runtime pending setting state
This commit is contained in:
parent
be7f504871
commit
76fd86175d
14 changed files with 138 additions and 122 deletions
|
|
@ -19,7 +19,12 @@ import type { DisplayItem } from "./display/types";
|
|||
import { upsertDisplayItem } from "./display/stream-updates";
|
||||
import type { PendingUserInput } from "./user-input/model";
|
||||
import { parseServiceTier, type RequestedServiceTier, type ServiceTier } from "../../app-server/service-tier";
|
||||
import { defaultRuntimeOverride, resetRuntimeOverride, setRuntimeOverride, type RuntimeOverride } from "../../runtime/state";
|
||||
import {
|
||||
resetRuntimeSettingToConfig,
|
||||
setPendingRuntimeSetting,
|
||||
unchangedRuntimeSetting,
|
||||
type PendingRuntimeSetting,
|
||||
} from "../../runtime/state";
|
||||
|
||||
export interface PendingTurnStart {
|
||||
anchorItemId: string;
|
||||
|
|
@ -56,11 +61,11 @@ export interface ChatState {
|
|||
activePermissionProfile: ActivePermissionProfile | null;
|
||||
activeThreadCreationCliVersion: string | null;
|
||||
appServerDiagnostics: AppServerDiagnostics;
|
||||
requestedModel: RuntimeOverride<string>;
|
||||
requestedReasoningEffort: RuntimeOverride<ReasoningEffort>;
|
||||
requestedApprovalsReviewer: ApprovalsReviewer | null;
|
||||
requestedCollaborationMode: ModeKind;
|
||||
requestedServiceTier: RequestedServiceTier | null;
|
||||
requestedModel: PendingRuntimeSetting<string>;
|
||||
requestedReasoningEffort: PendingRuntimeSetting<ReasoningEffort>;
|
||||
requestedApprovalsReviewer: PendingRuntimeSetting<ApprovalsReviewer>;
|
||||
selectedCollaborationMode: ModeKind;
|
||||
requestedServiceTier: PendingRuntimeSetting<RequestedServiceTier>;
|
||||
tokenUsage: ThreadTokenUsage | null;
|
||||
rateLimit: RateLimitSnapshot | null;
|
||||
displayItems: readonly DisplayItem[];
|
||||
|
|
@ -214,11 +219,11 @@ export function createChatState(): ChatState {
|
|||
activePermissionProfile: null,
|
||||
activeThreadCreationCliVersion: null,
|
||||
appServerDiagnostics: createAppServerDiagnostics(),
|
||||
requestedModel: defaultRuntimeOverride(),
|
||||
requestedReasoningEffort: defaultRuntimeOverride(),
|
||||
requestedApprovalsReviewer: null,
|
||||
requestedCollaborationMode: "default",
|
||||
requestedServiceTier: null,
|
||||
requestedModel: unchangedRuntimeSetting(),
|
||||
requestedReasoningEffort: unchangedRuntimeSetting(),
|
||||
requestedApprovalsReviewer: unchangedRuntimeSetting(),
|
||||
selectedCollaborationMode: "default",
|
||||
requestedServiceTier: unchangedRuntimeSetting(),
|
||||
tokenUsage: null,
|
||||
rateLimit: null,
|
||||
displayItems: [],
|
||||
|
|
@ -362,7 +367,7 @@ function reduceThreadState(state: ChatState, action: ThreadAction): ChatState {
|
|||
activeModel: action.model,
|
||||
activeReasoningEffort: action.reasoningEffort,
|
||||
activeCollaborationMode: action.collaborationMode,
|
||||
requestedCollaborationMode: action.collaborationMode,
|
||||
selectedCollaborationMode: action.collaborationMode,
|
||||
activeServiceTier: action.serviceTier,
|
||||
activeApprovalPolicy: action.approvalPolicy,
|
||||
activeApprovalsReviewer: action.approvalsReviewer,
|
||||
|
|
@ -526,21 +531,24 @@ function reduceUiState(state: ChatState, action: UiAction): ChatState {
|
|||
function reduceRuntimeState(state: ChatState, action: RuntimeAction): ChatState {
|
||||
switch (action.type) {
|
||||
case "runtime/requested-model-set":
|
||||
return patchChatState(state, { requestedModel: action.model === null ? resetRuntimeOverride() : setRuntimeOverride(action.model) });
|
||||
return patchChatState(state, {
|
||||
requestedModel: action.model === null ? resetRuntimeSettingToConfig() : setPendingRuntimeSetting(action.model),
|
||||
});
|
||||
case "runtime/requested-effort-set":
|
||||
return patchChatState(state, {
|
||||
requestedReasoningEffort: action.effort === null ? resetRuntimeOverride() : setRuntimeOverride(action.effort),
|
||||
requestedReasoningEffort: action.effort === null ? resetRuntimeSettingToConfig() : setPendingRuntimeSetting(action.effort),
|
||||
});
|
||||
case "runtime/requested-service-tier-set":
|
||||
return patchChatState(state, {
|
||||
requestedServiceTier: action.serviceTier,
|
||||
requestedServiceTier: action.serviceTier === null ? unchangedRuntimeSetting() : setPendingRuntimeSetting(action.serviceTier),
|
||||
});
|
||||
case "runtime/requested-approvals-reviewer-set":
|
||||
return patchChatState(state, {
|
||||
requestedApprovalsReviewer: action.approvalsReviewer,
|
||||
requestedApprovalsReviewer:
|
||||
action.approvalsReviewer === null ? unchangedRuntimeSetting() : setPendingRuntimeSetting(action.approvalsReviewer),
|
||||
});
|
||||
case "runtime/requested-collaboration-mode-set":
|
||||
return patchChatState(state, { requestedCollaborationMode: action.collaborationMode });
|
||||
return patchChatState(state, { selectedCollaborationMode: action.collaborationMode });
|
||||
case "runtime/pending-thread-settings-committed":
|
||||
return commitPendingThreadSettings(state, action.update);
|
||||
}
|
||||
|
|
@ -713,13 +721,18 @@ function setUserInputDraftState(state: ChatState, key: string, value: string): C
|
|||
|
||||
function commitPendingThreadSettings(state: ChatState, update: Omit<ThreadSettingsUpdateParams, "threadId">): ChatState {
|
||||
return patchChatState(state, {
|
||||
...("model" in update ? { activeModel: update.model ?? null, requestedModel: defaultRuntimeOverride<string>() } : {}),
|
||||
...("model" in update ? { activeModel: update.model ?? null, requestedModel: unchangedRuntimeSetting<string>() } : {}),
|
||||
...("effort" in update
|
||||
? { activeReasoningEffort: update.effort ?? null, requestedReasoningEffort: defaultRuntimeOverride<ReasoningEffort>() }
|
||||
? { activeReasoningEffort: update.effort ?? null, requestedReasoningEffort: unchangedRuntimeSetting<ReasoningEffort>() }
|
||||
: {}),
|
||||
...("serviceTier" in update
|
||||
? { activeServiceTier: parseServiceTier(update.serviceTier), requestedServiceTier: unchangedRuntimeSetting<RequestedServiceTier>() }
|
||||
: {}),
|
||||
...("serviceTier" in update ? { activeServiceTier: parseServiceTier(update.serviceTier), requestedServiceTier: null } : {}),
|
||||
...("approvalsReviewer" in update
|
||||
? { activeApprovalsReviewer: update.approvalsReviewer ?? null, requestedApprovalsReviewer: null }
|
||||
? {
|
||||
activeApprovalsReviewer: update.approvalsReviewer ?? null,
|
||||
requestedApprovalsReviewer: unchangedRuntimeSetting<ApprovalsReviewer>(),
|
||||
}
|
||||
: {}),
|
||||
...(update.collaborationMode ? { activeCollaborationMode: update.collaborationMode.mode } : {}),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,14 +2,9 @@ import { chatTurnBusy, type ChatState } from "./chat-state";
|
|||
import type { DisplayItem } from "./display/types";
|
||||
|
||||
export function implementPlanCandidateFromState(
|
||||
state: Pick<ChatState, "activeThreadId" | "turnLifecycle" | "composerDraft" | "requestedCollaborationMode" | "displayItems">,
|
||||
state: Pick<ChatState, "activeThreadId" | "turnLifecycle" | "composerDraft" | "selectedCollaborationMode" | "displayItems">,
|
||||
): DisplayItem | null {
|
||||
if (
|
||||
!state.activeThreadId ||
|
||||
chatTurnBusy(state) ||
|
||||
state.composerDraft.trim().length > 0 ||
|
||||
state.requestedCollaborationMode !== "plan"
|
||||
) {
|
||||
if (!state.activeThreadId || chatTurnBusy(state) || state.composerDraft.trim().length > 0 || state.selectedCollaborationMode !== "plan") {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ import {
|
|||
autoReviewActive,
|
||||
fastModeActive,
|
||||
fastServiceTierRequestValue,
|
||||
pendingRuntimeSettingPayload,
|
||||
requestedTurnRuntimeSettings,
|
||||
runtimeOverridePayload,
|
||||
type RuntimeSnapshot,
|
||||
} from "../../runtime/state";
|
||||
import { modelOverrideMessage, reasoningEffortOverrideMessage } from "../../runtime/settings";
|
||||
|
|
@ -89,7 +89,7 @@ export class ChatRuntimeSettingsController {
|
|||
}
|
||||
|
||||
async toggleCollaborationMode(): Promise<void> {
|
||||
const next = nextCollaborationMode(this.state.requestedCollaborationMode);
|
||||
const next = nextCollaborationMode(this.state.selectedCollaborationMode);
|
||||
await this.setCollaborationMode(next);
|
||||
}
|
||||
|
||||
|
|
@ -117,25 +117,28 @@ export class ChatRuntimeSettingsController {
|
|||
const snapshot = this.host.runtimeSnapshot();
|
||||
const turnSettings = requestedTurnRuntimeSettings(snapshot);
|
||||
|
||||
if (state.requestedModel.kind !== "default") {
|
||||
const model = runtimeOverridePayload(state.requestedModel);
|
||||
if (state.requestedModel.kind !== "unchanged") {
|
||||
const model = pendingRuntimeSettingPayload(state.requestedModel);
|
||||
if (model !== undefined) update.model = model;
|
||||
}
|
||||
if (state.requestedReasoningEffort.kind !== "default") {
|
||||
const effort = runtimeOverridePayload(state.requestedReasoningEffort);
|
||||
if (state.requestedReasoningEffort.kind !== "unchanged") {
|
||||
const effort = pendingRuntimeSettingPayload(state.requestedReasoningEffort);
|
||||
if (effort !== undefined) update.effort = effort;
|
||||
}
|
||||
if (state.requestedServiceTier !== null) {
|
||||
if (state.requestedServiceTier.kind === "set") {
|
||||
const serviceTier = requestedServiceTierRequestValue(
|
||||
state.requestedServiceTier,
|
||||
state.requestedServiceTier.value,
|
||||
fastServiceTierRequestValue(snapshot, readRuntimeConfig(state.effectiveConfig)),
|
||||
);
|
||||
if (serviceTier !== undefined) update.serviceTier = serviceTier;
|
||||
} else if (state.requestedServiceTier.kind === "resetToConfig") {
|
||||
update.serviceTier = null;
|
||||
}
|
||||
if (state.requestedApprovalsReviewer !== null) {
|
||||
update.approvalsReviewer = state.requestedApprovalsReviewer;
|
||||
if (state.requestedApprovalsReviewer.kind !== "unchanged") {
|
||||
const approvalsReviewer = pendingRuntimeSettingPayload(state.requestedApprovalsReviewer);
|
||||
if (approvalsReviewer !== undefined) update.approvalsReviewer = approvalsReviewer;
|
||||
}
|
||||
if (state.requestedCollaborationMode !== state.activeCollaborationMode) {
|
||||
if (state.selectedCollaborationMode !== state.activeCollaborationMode) {
|
||||
if (turnSettings.warning) {
|
||||
this.host.addSystemMessage(`${this.host.collaborationModeLabel()} mode is selected, but ${turnSettings.warning}`);
|
||||
} else if (turnSettings.collaborationMode) {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import {
|
|||
currentModel,
|
||||
currentReasoningEffort,
|
||||
fastModeActive,
|
||||
runtimeOverrideLabel,
|
||||
pendingRuntimeSettingLabel,
|
||||
runtimeSummaryLabel,
|
||||
serviceTierLabel,
|
||||
supportedReasoningEfforts,
|
||||
|
|
@ -81,7 +81,7 @@ export function runtimeSnapshotForChatState({ state }: RuntimeSnapshotInput): Ru
|
|||
requestedModel: state.requestedModel,
|
||||
requestedReasoningEffort: state.requestedReasoningEffort,
|
||||
requestedApprovalsReviewer: state.requestedApprovalsReviewer,
|
||||
requestedCollaborationMode: state.requestedCollaborationMode,
|
||||
selectedCollaborationMode: state.selectedCollaborationMode,
|
||||
requestedServiceTier: state.requestedServiceTier,
|
||||
tokenUsage: state.tokenUsage,
|
||||
rateLimit: state.rateLimit,
|
||||
|
|
@ -168,7 +168,7 @@ export function toolbarViewModel(input: ToolbarViewModelInput): ToolbarViewModel
|
|||
historyOpen,
|
||||
statusPanelOpen,
|
||||
runtimeOpen,
|
||||
planActive: state.requestedCollaborationMode === "plan",
|
||||
planActive: state.selectedCollaborationMode === "plan",
|
||||
autoReviewActive: autoReviewActive(snapshot, config),
|
||||
fastActive: fastModeActive(snapshot, config),
|
||||
runtimeSummary: runtimeSummaryLabel(model, effort),
|
||||
|
|
@ -230,7 +230,7 @@ export function modelStatusLines(state: ChatState, snapshot: RuntimeSnapshot, co
|
|||
const config = readRuntimeConfig(state.effectiveConfig);
|
||||
return [
|
||||
`Model: ${currentModel(snapshot, config) ?? "(Codex default)"}`,
|
||||
`Override: ${runtimeOverrideLabel(state.requestedModel)}`,
|
||||
`Override: ${pendingRuntimeSettingLabel(state.requestedModel)}`,
|
||||
`Provider: ${statusValue(config.modelProvider, "(Codex default)")}`,
|
||||
`Effort: ${currentReasoningEffort(snapshot, config) ?? "(Codex default)"}`,
|
||||
`Mode: ${collaborationModeLabel}`,
|
||||
|
|
@ -242,7 +242,7 @@ export function effortStatusLines(state: ChatState, snapshot: RuntimeSnapshot):
|
|||
const config = readRuntimeConfig(state.effectiveConfig);
|
||||
return [
|
||||
`Effort: ${currentReasoningEffort(snapshot, config) ?? "(Codex default)"}`,
|
||||
`Override: ${runtimeOverrideLabel(state.requestedReasoningEffort)}`,
|
||||
`Override: ${pendingRuntimeSettingLabel(state.requestedReasoningEffort)}`,
|
||||
`Supported: ${supportedReasoningEfforts(snapshot).join(", ")}`,
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ export function toolbarSlotSnapshot(state: ChatState, connected: boolean): ChatP
|
|||
state.activeApprovalPolicy,
|
||||
state.activeApprovalsReviewer,
|
||||
state.activePermissionProfile,
|
||||
state.requestedCollaborationMode,
|
||||
state.selectedCollaborationMode,
|
||||
state.requestedServiceTier,
|
||||
state.requestedApprovalsReviewer,
|
||||
state.requestedModel,
|
||||
|
|
@ -60,7 +60,7 @@ export function messagesSlotSnapshot(state: ChatState, pendingRequestsSignature:
|
|||
chatTurnBusy(state),
|
||||
state.messagesPinnedToBottom,
|
||||
state.composerDraft,
|
||||
state.requestedCollaborationMode,
|
||||
state.selectedCollaborationMode,
|
||||
displayItemsSignature(state.displayItems),
|
||||
turnDiffsSignature(state.turnDiffs),
|
||||
openDetailsSignature(state.openDetails),
|
||||
|
|
|
|||
|
|
@ -691,7 +691,7 @@ export class CodexChatView extends ItemView {
|
|||
}
|
||||
|
||||
private collaborationModeLabel(): string {
|
||||
return formatCollaborationModeLabel(this.state.requestedCollaborationMode);
|
||||
return formatCollaborationModeLabel(this.state.selectedCollaborationMode);
|
||||
}
|
||||
|
||||
private runtimeSnapshot(): RuntimeSnapshot {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import { findModelByIdOrName, supportedEffortsForModel } from "./model";
|
|||
import { compactModelLabel, compactReasoningEffortLabel } from "./settings";
|
||||
import { readRuntimeConfig, type RuntimeConfigProjection } from "./config";
|
||||
|
||||
export type RuntimeOverride<T> = { kind: "default" } | { kind: "set"; value: T } | { kind: "resetPending" };
|
||||
export type PendingRuntimeSetting<T> = { kind: "unchanged" } | { kind: "set"; value: T } | { kind: "resetToConfig" };
|
||||
|
||||
export interface RuntimeSnapshot {
|
||||
effectiveConfig: ConfigReadResponse | null;
|
||||
|
|
@ -33,11 +33,11 @@ export interface RuntimeSnapshot {
|
|||
activeApprovalPolicy: AskForApproval | null;
|
||||
activeApprovalsReviewer: ApprovalsReviewer | null;
|
||||
activePermissionProfile: ActivePermissionProfile | null;
|
||||
requestedModel: RuntimeOverride<string>;
|
||||
requestedReasoningEffort: RuntimeOverride<ReasoningEffort>;
|
||||
requestedApprovalsReviewer: ApprovalsReviewer | null;
|
||||
requestedCollaborationMode: ModeKind;
|
||||
requestedServiceTier: RequestedServiceTier | null;
|
||||
requestedModel: PendingRuntimeSetting<string>;
|
||||
requestedReasoningEffort: PendingRuntimeSetting<ReasoningEffort>;
|
||||
requestedApprovalsReviewer: PendingRuntimeSetting<ApprovalsReviewer>;
|
||||
selectedCollaborationMode: ModeKind;
|
||||
requestedServiceTier: PendingRuntimeSetting<RequestedServiceTier>;
|
||||
tokenUsage: ThreadTokenUsage | null;
|
||||
rateLimit: RateLimitSnapshot | null;
|
||||
hasThreadTurns: boolean;
|
||||
|
|
@ -53,8 +53,9 @@ export function currentServiceTier(
|
|||
snapshot: RuntimeSnapshot,
|
||||
config: RuntimeConfigProjection = readRuntimeConfig(snapshot.effectiveConfig),
|
||||
): string | null {
|
||||
if (snapshot.requestedServiceTier === "fast") return "fast";
|
||||
if (snapshot.requestedServiceTier === "off") return null;
|
||||
if (snapshot.requestedServiceTier.kind === "set" && snapshot.requestedServiceTier.value === "fast") return "fast";
|
||||
if (snapshot.requestedServiceTier.kind === "set" && snapshot.requestedServiceTier.value === "off") return null;
|
||||
if (snapshot.requestedServiceTier.kind === "resetToConfig") return config.serviceTier;
|
||||
return snapshot.activeServiceTier ?? config.serviceTier;
|
||||
}
|
||||
|
||||
|
|
@ -62,8 +63,11 @@ export function requestedOrConfiguredServiceTier(
|
|||
snapshot: RuntimeSnapshot,
|
||||
config: RuntimeConfigProjection = readRuntimeConfig(snapshot.effectiveConfig),
|
||||
): ServiceTierRequest {
|
||||
if (snapshot.requestedServiceTier !== null) {
|
||||
return requestedServiceTierRequestValue(snapshot.requestedServiceTier, fastServiceTierRequestValue(snapshot, config));
|
||||
if (snapshot.requestedServiceTier.kind === "set") {
|
||||
return requestedServiceTierRequestValue(snapshot.requestedServiceTier.value, fastServiceTierRequestValue(snapshot, config));
|
||||
}
|
||||
if (snapshot.requestedServiceTier.kind === "resetToConfig") {
|
||||
return null;
|
||||
}
|
||||
return configuredServiceTierRequestValue(config.serviceTier);
|
||||
}
|
||||
|
|
@ -74,7 +78,7 @@ export function currentModel(
|
|||
): string | null {
|
||||
const configModel = config.model;
|
||||
if (snapshot.requestedModel.kind === "set") return snapshot.requestedModel.value;
|
||||
if (snapshot.requestedModel.kind === "resetPending" && configModel) return configModel;
|
||||
if (snapshot.requestedModel.kind === "resetToConfig" && configModel) return configModel;
|
||||
return snapshot.activeModel ?? configModel;
|
||||
}
|
||||
|
||||
|
|
@ -83,7 +87,7 @@ export function currentReasoningEffort(
|
|||
config: RuntimeConfigProjection = readRuntimeConfig(snapshot.effectiveConfig),
|
||||
): ReasoningEffort | null {
|
||||
if (snapshot.requestedReasoningEffort.kind === "set") return snapshot.requestedReasoningEffort.value;
|
||||
if (snapshot.requestedReasoningEffort.kind === "resetPending") return config.reasoningEffort;
|
||||
if (snapshot.requestedReasoningEffort.kind === "resetToConfig") return config.reasoningEffort;
|
||||
return snapshot.activeReasoningEffort ?? config.reasoningEffort;
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +95,8 @@ export function currentApprovalsReviewer(
|
|||
snapshot: RuntimeSnapshot,
|
||||
config: RuntimeConfigProjection = readRuntimeConfig(snapshot.effectiveConfig),
|
||||
): ApprovalsReviewer | null {
|
||||
if (snapshot.requestedApprovalsReviewer !== null) return snapshot.requestedApprovalsReviewer;
|
||||
if (snapshot.requestedApprovalsReviewer.kind === "set") return snapshot.requestedApprovalsReviewer.value;
|
||||
if (snapshot.requestedApprovalsReviewer.kind === "resetToConfig") return config.approvalsReviewer;
|
||||
return snapshot.activeApprovalsReviewer ?? config.approvalsReviewer;
|
||||
}
|
||||
|
||||
|
|
@ -113,7 +118,7 @@ export function requestedTurnRuntimeSettings(snapshot: RuntimeSnapshot): TurnRun
|
|||
const model = currentModel(snapshot);
|
||||
const effort = currentReasoningEffort(snapshot);
|
||||
const collaborationMode = model
|
||||
? snapshot.requestedCollaborationMode === "plan"
|
||||
? snapshot.selectedCollaborationMode === "plan"
|
||||
? planCollaborationMode(model, effort)
|
||||
: defaultCollaborationMode(model, effort)
|
||||
: null;
|
||||
|
|
@ -152,7 +157,7 @@ export function fastModeLabel(
|
|||
snapshot: RuntimeSnapshot,
|
||||
config: RuntimeConfigProjection = readRuntimeConfig(snapshot.effectiveConfig),
|
||||
): string {
|
||||
if (snapshot.requestedServiceTier === "off") return "off";
|
||||
if (snapshot.requestedServiceTier.kind === "set" && snapshot.requestedServiceTier.value === "off") return "off";
|
||||
if (fastModeActive(snapshot, config)) return "on";
|
||||
const serviceTier = currentServiceTier(snapshot, config);
|
||||
return serviceTier ? "off" : "Codex default";
|
||||
|
|
@ -165,27 +170,27 @@ export function fastServiceTierRequestValue(
|
|||
return currentModelServiceTiers(snapshot, config).find((tier) => tier.name.trim().toLowerCase() === "fast")?.id ?? "fast";
|
||||
}
|
||||
|
||||
export function defaultRuntimeOverride<T>(): RuntimeOverride<T> {
|
||||
return { kind: "default" };
|
||||
export function unchangedRuntimeSetting<T>(): PendingRuntimeSetting<T> {
|
||||
return { kind: "unchanged" };
|
||||
}
|
||||
|
||||
export function setRuntimeOverride<T>(value: T): RuntimeOverride<T> {
|
||||
export function setPendingRuntimeSetting<T>(value: T): PendingRuntimeSetting<T> {
|
||||
return { kind: "set", value };
|
||||
}
|
||||
|
||||
export function resetRuntimeOverride<T>(): RuntimeOverride<T> {
|
||||
return { kind: "resetPending" };
|
||||
export function resetRuntimeSettingToConfig<T>(): PendingRuntimeSetting<T> {
|
||||
return { kind: "resetToConfig" };
|
||||
}
|
||||
|
||||
export function runtimeOverridePayload<T>(override: RuntimeOverride<T>): T | null | undefined {
|
||||
if (override.kind === "set") return override.value;
|
||||
if (override.kind === "resetPending") return null;
|
||||
export function pendingRuntimeSettingPayload<T>(setting: PendingRuntimeSetting<T>): T | null | undefined {
|
||||
if (setting.kind === "set") return setting.value;
|
||||
if (setting.kind === "resetToConfig") return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function runtimeOverrideLabel<T>(override: RuntimeOverride<T>): string {
|
||||
if (override.kind === "set") return String(override.value);
|
||||
if (override.kind === "resetPending") return "(reset to config)";
|
||||
export function pendingRuntimeSettingLabel<T>(setting: PendingRuntimeSetting<T>): string {
|
||||
if (setting.kind === "set") return String(setting.value);
|
||||
if (setting.kind === "resetToConfig") return "(reset to config)";
|
||||
return "(none)";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import {
|
|||
currentReasoningEffort,
|
||||
autoReviewActive,
|
||||
fastModeLabel,
|
||||
runtimeOverrideLabel,
|
||||
pendingRuntimeSettingLabel,
|
||||
serviceTierLabel,
|
||||
type RuntimeSnapshot,
|
||||
} from "./state";
|
||||
|
|
@ -122,25 +122,25 @@ export function effectiveConfigSections(snapshot: RuntimeSnapshot, vaultPath: st
|
|||
{ key: "effective model", value: currentModel(snapshot, config) ?? CODEX_DEFAULT_LABEL },
|
||||
{ key: "configured model", value: configuredModel(snapshot, config) ?? NOT_REPORTED_LABEL },
|
||||
{ key: "thread model", value: activeRuntimeValueLabel(snapshot.activeModel) },
|
||||
{ key: "requested model", value: runtimeOverrideLabel(snapshot.requestedModel) },
|
||||
{ key: "requested model", value: pendingRuntimeSettingLabel(snapshot.requestedModel) },
|
||||
{ key: "effective effort", value: currentReasoningEffort(snapshot, config) ?? CODEX_DEFAULT_LABEL },
|
||||
{ key: "configured effort", value: configuredReasoningEffort(snapshot, config) ?? NOT_REPORTED_LABEL },
|
||||
{ key: "thread effort", value: activeRuntimeValueLabel(snapshot.activeReasoningEffort) },
|
||||
{ key: "requested effort", value: runtimeOverrideLabel(snapshot.requestedReasoningEffort) },
|
||||
{ key: "requested effort", value: pendingRuntimeSettingLabel(snapshot.requestedReasoningEffort) },
|
||||
{ key: "reasoning summary", value: stringValue(config.reasoningSummary, CODEX_DEFAULT_LABEL) },
|
||||
{ key: "verbosity", value: stringValue(config.verbosity, CODEX_DEFAULT_LABEL) },
|
||||
{ key: "effective mode", value: snapshot.activeCollaborationMode === "plan" ? "Plan" : "Default" },
|
||||
{
|
||||
key: "requested mode",
|
||||
value:
|
||||
snapshot.requestedCollaborationMode === snapshot.activeCollaborationMode
|
||||
snapshot.selectedCollaborationMode === snapshot.activeCollaborationMode
|
||||
? "(none)"
|
||||
: modeLabel(snapshot.requestedCollaborationMode),
|
||||
: modeLabel(snapshot.selectedCollaborationMode),
|
||||
},
|
||||
{ key: "effective service tier", value: serviceTierLabel(snapshot, config) },
|
||||
{ key: "configured service tier", value: config.serviceTier ?? CODEX_DEFAULT_LABEL },
|
||||
{ key: "thread service tier", value: activeRuntimeValueLabel(snapshot.activeServiceTier) },
|
||||
{ key: "requested service tier", value: snapshot.requestedServiceTier ?? "(none)" },
|
||||
{ key: "requested service tier", value: pendingRuntimeSettingLabel(snapshot.requestedServiceTier) },
|
||||
{ key: "fast mode", value: fastModeLabel(snapshot, config) },
|
||||
{ key: "context window", value: tokenLimitLabel(config.modelContextWindow) },
|
||||
{ key: "auto compact limit", value: tokenLimitLabel(config.autoCompactTokenLimit) },
|
||||
|
|
@ -157,7 +157,7 @@ export function effectiveConfigSections(snapshot: RuntimeSnapshot, vaultPath: st
|
|||
{ key: "auto-review", value: autoReviewActive(snapshot, config) ? "on" : "off" },
|
||||
{ key: "configured reviewer", value: config.approvalsReviewer ?? CODEX_DEFAULT_LABEL },
|
||||
{ key: "thread reviewer", value: activeRuntimeValueLabel(snapshot.activeApprovalsReviewer) },
|
||||
{ key: "requested reviewer", value: snapshot.requestedApprovalsReviewer ?? "(none)" },
|
||||
{ key: "requested reviewer", value: pendingRuntimeSettingLabel(snapshot.requestedApprovalsReviewer) },
|
||||
{ key: "sandbox", value: stringValue(config.sandboxMode, CODEX_DEFAULT_LABEL) },
|
||||
{ key: "workspace network", value: stringValue(config.workspaceNetworkAccess, CODEX_DEFAULT_LABEL) },
|
||||
{ key: "writable roots", value: writableRootsLabel(config.writableRoots) },
|
||||
|
|
@ -191,7 +191,7 @@ function configuredReasoningEffort(snapshot: RuntimeSnapshot, config: RuntimeCon
|
|||
);
|
||||
}
|
||||
|
||||
function modeLabel(mode: RuntimeSnapshot["requestedCollaborationMode"]): string {
|
||||
function modeLabel(mode: RuntimeSnapshot["selectedCollaborationMode"]): string {
|
||||
return mode === "plan" ? "Plan" : "Default";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ describe("ChatAppServerController", () => {
|
|||
stateStore,
|
||||
vaultPath: "/vault",
|
||||
currentClient: () => client,
|
||||
runtimeSnapshot: () => ({ requestedServiceTier: null, effectiveConfig: null }) as never,
|
||||
runtimeSnapshot: () => ({ requestedServiceTier: { kind: "unchanged" }, effectiveConfig: null }) as never,
|
||||
forceMessagesToBottom: () => undefined,
|
||||
publishThreadList,
|
||||
publishAppServerMetadata: () => undefined,
|
||||
|
|
@ -68,7 +68,7 @@ describe("ChatAppServerController", () => {
|
|||
stateStore,
|
||||
vaultPath: "/vault",
|
||||
currentClient: () => client,
|
||||
runtimeSnapshot: () => ({ requestedServiceTier: null, effectiveConfig: null }) as never,
|
||||
runtimeSnapshot: () => ({ requestedServiceTier: { kind: "unchanged" }, effectiveConfig: null }) as never,
|
||||
forceMessagesToBottom: () => undefined,
|
||||
publishThreadList,
|
||||
publishAppServerMetadata: () => undefined,
|
||||
|
|
|
|||
|
|
@ -219,13 +219,13 @@ describe("chatReducer", () => {
|
|||
});
|
||||
|
||||
expect(next.activeModel).toBe("gpt-5.1");
|
||||
expect(next.requestedModel).toEqual({ kind: "default" });
|
||||
expect(next.requestedModel).toEqual({ kind: "unchanged" });
|
||||
expect(next.activeReasoningEffort).toBe("high");
|
||||
expect(next.requestedReasoningEffort).toEqual({ kind: "default" });
|
||||
expect(next.requestedReasoningEffort).toEqual({ kind: "unchanged" });
|
||||
expect(next.activeServiceTier).toBe("fast");
|
||||
expect(next.requestedServiceTier).toBeNull();
|
||||
expect(next.requestedServiceTier).toEqual({ kind: "unchanged" });
|
||||
expect(next.activeApprovalsReviewer).toBe("auto_review");
|
||||
expect(next.requestedApprovalsReviewer).toBeNull();
|
||||
expect(next.requestedApprovalsReviewer).toEqual({ kind: "unchanged" });
|
||||
expect(next.activeCollaborationMode).toBe("plan");
|
||||
});
|
||||
|
||||
|
|
@ -237,9 +237,9 @@ describe("chatReducer", () => {
|
|||
state = chatReducer(state, { type: "runtime/requested-service-tier-set", serviceTier: "fast" });
|
||||
state = chatReducer(state, { type: "runtime/requested-approvals-reviewer-set", approvalsReviewer: "auto_review" });
|
||||
|
||||
expect(state.requestedServiceTier).toBe("fast");
|
||||
expect(state.requestedServiceTier).toEqual({ kind: "set", value: "fast" });
|
||||
expect(state.activeServiceTier).toBe("flex");
|
||||
expect(state.requestedApprovalsReviewer).toBe("auto_review");
|
||||
expect(state.requestedApprovalsReviewer).toEqual({ kind: "set", value: "auto_review" });
|
||||
expect(state.activeApprovalsReviewer).toBe("user");
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ describe("PlanImplementationController", () => {
|
|||
await controller.implement(plan);
|
||||
|
||||
expect(host.ensureConnected).toHaveBeenCalledOnce();
|
||||
expect(stateStore.getState().requestedCollaborationMode).toBe("default");
|
||||
expect(stateStore.getState().selectedCollaborationMode).toBe("default");
|
||||
expect(stateStore.getState().runtimePicker).toBeNull();
|
||||
expect(host.sendTurnText).toHaveBeenCalledWith("Please implement this plan.");
|
||||
});
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ describe("ChatRuntimeSettingsController", () => {
|
|||
requestedModel: store.getState().requestedModel,
|
||||
requestedReasoningEffort: store.getState().requestedReasoningEffort,
|
||||
requestedApprovalsReviewer: store.getState().requestedApprovalsReviewer,
|
||||
requestedCollaborationMode: store.getState().requestedCollaborationMode,
|
||||
selectedCollaborationMode: store.getState().selectedCollaborationMode,
|
||||
requestedServiceTier: store.getState().requestedServiceTier,
|
||||
tokenUsage: store.getState().tokenUsage,
|
||||
rateLimit: store.getState().rateLimit,
|
||||
|
|
@ -42,7 +42,7 @@ describe("ChatRuntimeSettingsController", () => {
|
|||
await expect(controller.setRequestedModel("gpt-5.5")).resolves.toBe(true);
|
||||
|
||||
expect(client.updateThreadSettings).toHaveBeenCalledWith("thread", { model: "gpt-5.5" });
|
||||
expect(store.getState().requestedModel).toEqual({ kind: "default" });
|
||||
expect(store.getState().requestedModel).toEqual({ kind: "unchanged" });
|
||||
expect(store.getState().activeModel).toBe("gpt-5.5");
|
||||
expect(messages).toEqual([]);
|
||||
});
|
||||
|
|
@ -58,7 +58,7 @@ describe("ChatRuntimeSettingsController", () => {
|
|||
await controller.toggleFastMode();
|
||||
|
||||
expect(client.updateThreadSettings).toHaveBeenCalledWith("thread", { serviceTier: "fast" });
|
||||
expect(store.getState().requestedServiceTier).toBeNull();
|
||||
expect(store.getState().requestedServiceTier).toEqual({ kind: "unchanged" });
|
||||
expect(store.getState().activeServiceTier).toBe("fast");
|
||||
expect(messages).toEqual(["Fast mode on for subsequent turns."]);
|
||||
});
|
||||
|
|
@ -126,7 +126,7 @@ function runtimeControllerFixture(
|
|||
requestedModel: state.requestedModel,
|
||||
requestedReasoningEffort: state.requestedReasoningEffort,
|
||||
requestedApprovalsReviewer: state.requestedApprovalsReviewer,
|
||||
requestedCollaborationMode: state.requestedCollaborationMode,
|
||||
selectedCollaborationMode: state.selectedCollaborationMode,
|
||||
requestedServiceTier: state.requestedServiceTier,
|
||||
tokenUsage: state.tokenUsage,
|
||||
rateLimit: state.rateLimit,
|
||||
|
|
|
|||
|
|
@ -793,12 +793,12 @@ describe("message stream block identity and message actions", () => {
|
|||
activeThreadId: "thread",
|
||||
turnLifecycle: { kind: "idle" as const },
|
||||
composerDraft: "",
|
||||
requestedCollaborationMode: "plan" as const,
|
||||
selectedCollaborationMode: "plan" as const,
|
||||
displayItems: [firstPlan, { id: "a1", kind: "message", role: "assistant", text: "answer" } as const, secondPlan],
|
||||
};
|
||||
|
||||
expect(implementPlanCandidateFromState(baseState)).toBe(secondPlan);
|
||||
expect(implementPlanCandidateFromState({ ...baseState, requestedCollaborationMode: "default" })).toBeNull();
|
||||
expect(implementPlanCandidateFromState({ ...baseState, selectedCollaborationMode: "default" })).toBeNull();
|
||||
expect(implementPlanCandidateFromState({ ...baseState, composerDraft: "edit first" })).toBeNull();
|
||||
expect(implementPlanCandidateFromState({ ...baseState, turnLifecycle: { kind: "running", turnId: "turn-2" } })).toBeNull();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@ import {
|
|||
fastModeLabel,
|
||||
requestedOrConfiguredServiceTier,
|
||||
requestedTurnRuntimeSettings,
|
||||
resetRuntimeOverride,
|
||||
runtimeOverridePayload,
|
||||
setRuntimeOverride,
|
||||
resetRuntimeSettingToConfig,
|
||||
pendingRuntimeSettingPayload,
|
||||
setPendingRuntimeSetting,
|
||||
serviceTierLabel,
|
||||
type RuntimeSnapshot,
|
||||
} from "../../src/runtime/state";
|
||||
|
|
@ -111,8 +111,8 @@ describe("runtime settings", () => {
|
|||
|
||||
it("keeps runtime defaults, resets, and collaboration mode semantics distinct", () => {
|
||||
const snapshot = runtimeSnapshot({
|
||||
requestedModel: resetRuntimeOverride(),
|
||||
requestedReasoningEffort: resetRuntimeOverride(),
|
||||
requestedModel: resetRuntimeSettingToConfig(),
|
||||
requestedReasoningEffort: resetRuntimeSettingToConfig(),
|
||||
});
|
||||
|
||||
expect(currentModel(snapshot)).toBe("gpt-5.5");
|
||||
|
|
@ -123,27 +123,27 @@ describe("runtime settings", () => {
|
|||
settings: { model: "gpt-5.5", reasoning_effort: "high" },
|
||||
},
|
||||
});
|
||||
expect(runtimeOverridePayload(snapshot.requestedModel)).toBeNull();
|
||||
expect(runtimeOverridePayload(snapshot.requestedReasoningEffort)).toBeNull();
|
||||
expect(pendingRuntimeSettingPayload(snapshot.requestedModel)).toBeNull();
|
||||
expect(pendingRuntimeSettingPayload(snapshot.requestedReasoningEffort)).toBeNull();
|
||||
});
|
||||
|
||||
it("uses explicit runtime overrides as current values and settings payload values", () => {
|
||||
const snapshot = runtimeSnapshot({
|
||||
requestedModel: setRuntimeOverride("gpt-5.4"),
|
||||
requestedReasoningEffort: setRuntimeOverride("low"),
|
||||
requestedModel: setPendingRuntimeSetting("gpt-5.4"),
|
||||
requestedReasoningEffort: setPendingRuntimeSetting("low"),
|
||||
});
|
||||
|
||||
expect(currentModel(snapshot)).toBe("gpt-5.4");
|
||||
expect(currentReasoningEffort(snapshot)).toBe("low");
|
||||
expect(runtimeOverridePayload(snapshot.requestedModel)).toBe("gpt-5.4");
|
||||
expect(runtimeOverridePayload(snapshot.requestedReasoningEffort)).toBe("low");
|
||||
expect(pendingRuntimeSettingPayload(snapshot.requestedModel)).toBe("gpt-5.4");
|
||||
expect(pendingRuntimeSettingPayload(snapshot.requestedReasoningEffort)).toBe("low");
|
||||
});
|
||||
|
||||
it("resolves approval reviewer from requested, active, then effective config", () => {
|
||||
expect(
|
||||
currentApprovalsReviewer(
|
||||
runtimeSnapshot({
|
||||
requestedApprovalsReviewer: "user",
|
||||
requestedApprovalsReviewer: setPendingRuntimeSetting("user"),
|
||||
activeApprovalsReviewer: "auto_review",
|
||||
effectiveConfig: effectiveConfigFixture({ approvals_reviewer: "guardian_subagent" }),
|
||||
}),
|
||||
|
|
@ -187,7 +187,7 @@ describe("runtime settings", () => {
|
|||
|
||||
it("uses requested reviewer above active and configured reviewers", () => {
|
||||
const snapshot = runtimeSnapshot({
|
||||
requestedApprovalsReviewer: "user",
|
||||
requestedApprovalsReviewer: setPendingRuntimeSetting("user"),
|
||||
activeApprovalsReviewer: "user",
|
||||
effectiveConfig: effectiveConfigFixture({ approvals_reviewer: "auto_review" }),
|
||||
});
|
||||
|
|
@ -279,7 +279,7 @@ describe("runtime settings", () => {
|
|||
|
||||
it("uses requested service tier above active and configured service tiers", () => {
|
||||
const snapshot = runtimeSnapshot({
|
||||
requestedServiceTier: "off",
|
||||
requestedServiceTier: setPendingRuntimeSetting("off"),
|
||||
activeServiceTier: "flex",
|
||||
effectiveConfig: effectiveConfigFixture({ service_tier: "fast" }),
|
||||
});
|
||||
|
|
@ -289,7 +289,7 @@ describe("runtime settings", () => {
|
|||
});
|
||||
|
||||
it("resolves requested approval reviewer without adding it to turn runtime settings", () => {
|
||||
const snapshot = runtimeSnapshot({ requestedApprovalsReviewer: "auto_review" });
|
||||
const snapshot = runtimeSnapshot({ requestedApprovalsReviewer: setPendingRuntimeSetting("auto_review") });
|
||||
|
||||
expect(autoReviewActive(snapshot)).toBe(true);
|
||||
expect(currentApprovalsReviewer(snapshot)).toBe("auto_review");
|
||||
|
|
@ -321,8 +321,8 @@ describe("runtime settings", () => {
|
|||
activeModel: "gpt-5-active",
|
||||
activeReasoningEffort: "low",
|
||||
activeCollaborationMode: "plan",
|
||||
requestedCollaborationMode: "plan",
|
||||
requestedModel: setRuntimeOverride("gpt-5-pending"),
|
||||
selectedCollaborationMode: "plan",
|
||||
requestedModel: setPendingRuntimeSetting("gpt-5-pending"),
|
||||
}),
|
||||
"/vault",
|
||||
);
|
||||
|
|
@ -348,7 +348,7 @@ describe("runtime settings", () => {
|
|||
|
||||
const resetSections = effectiveConfigSections(
|
||||
runtimeSnapshot({
|
||||
requestedReasoningEffort: resetRuntimeOverride(),
|
||||
requestedReasoningEffort: resetRuntimeSettingToConfig(),
|
||||
}),
|
||||
"/vault",
|
||||
);
|
||||
|
|
@ -482,7 +482,7 @@ describe("runtime settings", () => {
|
|||
});
|
||||
|
||||
it("summarizes service tier and context meter state from one runtime snapshot", () => {
|
||||
const snapshot = runtimeSnapshot({ requestedServiceTier: "fast", activeThreadId: "thread" });
|
||||
const snapshot = runtimeSnapshot({ requestedServiceTier: setPendingRuntimeSetting("fast"), activeThreadId: "thread" });
|
||||
|
||||
expect(serviceTierLabel(snapshot)).toBe("fast");
|
||||
expect(fastModeLabel(snapshot)).toBe("on");
|
||||
|
|
@ -522,7 +522,7 @@ describe("runtime settings", () => {
|
|||
it("serializes explicit fast off as a null service tier request", () => {
|
||||
const snapshot = runtimeSnapshot({
|
||||
effectiveConfig: effectiveConfigFixture({ service_tier: "fast" }),
|
||||
requestedServiceTier: "off",
|
||||
requestedServiceTier: setPendingRuntimeSetting("off"),
|
||||
});
|
||||
|
||||
expect(serviceTierLabel(snapshot)).toBe("(Codex default)");
|
||||
|
|
@ -534,7 +534,7 @@ describe("runtime settings", () => {
|
|||
const model = modelFixture("gpt-5.5");
|
||||
model.serviceTiers = [{ id: "priority", name: "Fast", description: "1.5x speed, increased usage" }];
|
||||
const snapshot = runtimeSnapshot({
|
||||
requestedServiceTier: "fast",
|
||||
requestedServiceTier: setPendingRuntimeSetting("fast"),
|
||||
effectiveConfig: effectiveConfigFixture({ model: "gpt-5.5" }),
|
||||
availableModels: [model],
|
||||
});
|
||||
|
|
@ -654,11 +654,11 @@ function runtimeSnapshot(overrides: Partial<RuntimeSnapshot> = {}): RuntimeSnaps
|
|||
activeApprovalPolicy: null,
|
||||
activeApprovalsReviewer: null,
|
||||
activePermissionProfile: null,
|
||||
requestedModel: { kind: "default" },
|
||||
requestedReasoningEffort: { kind: "default" },
|
||||
requestedApprovalsReviewer: null,
|
||||
requestedCollaborationMode: "default",
|
||||
requestedServiceTier: null,
|
||||
requestedModel: { kind: "unchanged" },
|
||||
requestedReasoningEffort: { kind: "unchanged" },
|
||||
requestedApprovalsReviewer: { kind: "unchanged" },
|
||||
selectedCollaborationMode: "default",
|
||||
requestedServiceTier: { kind: "unchanged" },
|
||||
tokenUsage: null,
|
||||
rateLimit: null,
|
||||
hasThreadTurns: false,
|
||||
|
|
|
|||
Loading…
Reference in a new issue