src/vs/platform/agentHost/node/codex/codexSessionConfigKeys.ts
197 LOC · 197 covered · 0 uncovered · 37 ranges · 25 concepts · 11 introducers · 13 tests
File neighbourhood
The centred file is linked to every concept that introduces one of its ranges, every test that runs code from the file, and the gray connector concepts standing between those tests and the file's own introducer concepts. Undirected links join concepts to every file where they introduce source and concepts to the tests they introduce; arrows show specialization between the displayed concepts and bridge only concepts omitted from this view. Concept colors match the source ranges below; connector concepts have no source color and are shown in gray.
Focused file, its introducer and connector concepts, their introduced files, and tests that run code from the file
In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the related-file, concept, and source links on this page.
Graph controls are ready.
Interactive rendering requires JavaScript and WebGL. Use the related-file, concept, and source links on this page while the interactive map is unavailable.
/*---------------------------------------------------------------------------------------------
codexAgent.ts ×158
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import type { ReasoningEffort } from './protocol/generated/ReasoningEffort.js';
import type { ReasoningSummary } from './protocol/generated/ReasoningSummary.js';
import type { Personality } from './protocol/generated/Personality.js';
import type { WebSearchMode } from './protocol/generated/WebSearchMode.js';
import type { ModeKind } from './protocol/generated/ModeKind.js';
import type { SandboxMode } from './protocol/generated/v2/SandboxMode.js';
import { CodexSessionConfigKey, CODEX_DEFAULT_PERMISSIONS_PRESET, narrowCodexPermissionsPreset, presetForResolvedPermissions, resolveCodexPermissionsPreset, type CodexApprovalPolicy, type ICodexResolvedPermissions } from '../../common/codexSessionConfigKeys.js';
// Re-export the shared, protocol-free config-key surface so node callers can
// keep importing everything from this module.
export { CodexSessionConfigKey, resolveCodexPermissionsPreset, presetForResolvedPermissions, narrowCodexPermissionsPreset, CODEX_PERMISSIONS_PRESETS, CODEX_DEFAULT_PERMISSIONS_PRESET } from '../../common/codexSessionConfigKeys.js';
export type { CodexApprovalPolicy, CodexPermissionsPreset, CodexSandboxMode, CodexApprovalsReviewer, ICodexResolvedPermissions } from '../../common/codexSessionConfigKeys.js';
export function narrowApprovalPolicy(value: unknown): CodexApprovalPolicy | undefined {
case 'never':
case 'on-request':
case 'on-failure':
case 'untrusted':
}
export function narrowSandboxMode(value: unknown): SandboxMode | undefined {
case 'read-only':
case 'workspace-write':
case 'danger-full-access':
}
/**
* Resolve the Codex security axes (approval policy, sandbox, approvals
* reviewer) for a session's stored config values.
*
* The user-facing {@link CodexSessionConfigKey.PermissionsPreset} is the source
* of truth; when present it expands into all three axes. For backward
* compatibility (older sessions / programmatic config) we fall back to the
* individual {@link CodexSessionConfigKey.ApprovalPolicy} /
* {@link CodexSessionConfigKey.SandboxMode} keys with a `user` reviewer.
*/
export function resolveCodexPermissions(
defaults: { approvalPolicy: CodexApprovalPolicy; sandboxMode: SandboxMode },
): ICodexResolvedPermissions {
const preset = narrowCodexPermissionsPreset(values?.[CodexSessionConfigKey.PermissionsPreset]);
if (preset) {
}
approvalPolicy: narrowApprovalPolicy(values?.[CodexSessionConfigKey.ApprovalPolicy]) ?? defaults.approvalPolicy,
sandboxMode: narrowSandboxMode(values?.[CodexSessionConfigKey.SandboxMode]) ?? defaults.sandboxMode,
approvalsReviewer: 'user',
};
}
/**
* Decide how a restored session's three permission keys (`permissionsPreset`,
* `approvalPolicy`, `sandboxMode`) should be represented, given its raw
* persisted config values.
*
* This exists to prevent a silent privilege escalation on restore: a legacy
* session that persisted only the individual axes (for example
* `sandboxMode = 'read-only'`) and never chose a preset must not have a
* materialized `permissionsPreset = 'default'` inserted on top of it, because
* {@link resolveCodexPermissions} checks the preset first and would resume the
* session as `workspace-write`.
*
* The returned object contains ONLY the permission keys that should be present
* afterwards, so callers should drop all three permission keys before applying
* it:
* - an explicitly chosen preset is kept as-is;
* - legacy axes that map exactly onto a preset are migrated to that preset
* (single source of truth) and the raw axes dropped;
* - legacy axes with a `workspace-write` or `danger-full-access` sandbox that
* do NOT map exactly onto a preset are snapped to the preset whose sandbox
* matches (`default` / `full-access`). This keeps the resolved axes in sync
* with the preset the "Approvals" chip displays, so a legacy
* `approvalPolicy = 'never'` + `workspace-write` session resolves to the
* `default` preset's `on-request` policy (and actually prompts) instead of
* silently running without approval while the chip claims "Default
* Permissions". Snapping never grants more sandbox access than the legacy
* value already had;
* - legacy axes with a `read-only` sandbox (which no preset expands to, and
* which is more locked-down than any preset) are preserved verbatim and no
* preset is surfaced, so restore never silently escalates them to
* `workspace-write`.
*/
export function migrateCodexPermissionValues(
defaults: { approvalPolicy: CodexApprovalPolicy; sandboxMode: SandboxMode },
): Record<string, string> {
const explicitPreset = narrowCodexPermissionsPreset(config?.[CodexSessionConfigKey.PermissionsPreset]);
if (explicitPreset) {
return { [CodexSessionConfigKey.PermissionsPreset]: explicitPreset };
codexSessionConfigKeys.ts ×1
}
const equivalentPreset = presetForResolvedPermissions(resolved);
if (equivalentPreset) {
return { [CodexSessionConfigKey.PermissionsPreset]: equivalentPreset };
}
// `read-only` is more locked-down than any preset's sandbox and cannot be
codexSessionConfigKeys.ts ×1
// represented by one, so preserve the raw axes — surfacing a preset here
// would silently escalate the session to `workspace-write` on restore.
if (resolved.sandboxMode === 'read-only') {
return {
[CodexSessionConfigKey.ApprovalPolicy]: resolved.approvalPolicy,
[CodexSessionConfigKey.SandboxMode]: resolved.sandboxMode,
};
}
// Otherwise snap onto the preset whose sandbox matches so the displayed chip
codexSessionConfigKeys.ts ×1
// and the resolved axes stay consistent (`danger-full-access` → Full Access,
// any other non-exact `workspace-write` combo → Default Permissions).
return {
[CodexSessionConfigKey.PermissionsPreset]: resolved.sandboxMode === 'danger-full-access'
? 'full-access'
: CODEX_DEFAULT_PERMISSIONS_PRESET,
}
export function narrowAdditionalDirectories(value: unknown): readonly string[] | undefined {
return undefined;
}
return value.filter((entry): entry is string => typeof entry === 'string' && entry.length > 0);
}
export function narrowBoolean(value: unknown): boolean | undefined {
}
export function narrowWebSearchMode(value: unknown): WebSearchMode | undefined {
case 'disabled':
case 'cached':
case 'live':
return value;
default:
return undefined;
}
}
export function narrowReasoningEffort(value: unknown): ReasoningEffort | undefined {
case 'none':
case 'minimal':
case 'low':
case 'medium':
case 'high':
case 'xhigh':
return value;
default:
return undefined;
}
}
export function narrowPersonality(value: unknown): Personality | undefined {
case 'none':
case 'friendly':
case 'pragmatic':
return value;
default:
return undefined;
}
}
export function narrowReasoningSummary(value: unknown): ReasoningSummary | undefined {
case 'auto':
case 'concise':
case 'detailed':
case 'none':
return value;
default:
return undefined;
}
}
/**
* Map the platform-generic {@link SessionMode} (Agent Mode) to codex's native
* collaboration {@link ModeKind}: VS Code "Plan" → codex `plan`, "Interactive"
* → codex `default`.
*/
export function collaborationModeKind(value: unknown): ModeKind {
}