mirror of
https://github.com/hangwin/mcp-chrome.git
synced 2026-09-21 12:43:18 +08:00
feat: 完善codex支持
This commit is contained in:
@@ -46,34 +46,98 @@ export const CLAUDE_MODELS: ModelDefinition[] = [
|
||||
export const CLAUDE_DEFAULT_MODEL = 'claude-sonnet-4-5-20250929';
|
||||
|
||||
// ============================================================
|
||||
// Codex Models
|
||||
// Codex Models (aligned with other/cweb)
|
||||
// ============================================================
|
||||
|
||||
export const CODEX_MODELS: ModelDefinition[] = [
|
||||
{
|
||||
id: 'o3',
|
||||
name: 'o3',
|
||||
id: 'gpt-5',
|
||||
name: 'GPT-5',
|
||||
description: 'OpenAI flagship reasoning model',
|
||||
},
|
||||
{
|
||||
id: 'gpt-4.1',
|
||||
name: 'GPT-4.1',
|
||||
description: 'OpenAI GPT-4.1 model',
|
||||
},
|
||||
{
|
||||
id: 'o4-mini',
|
||||
name: 'o4 Mini',
|
||||
description: 'Fast and efficient model',
|
||||
},
|
||||
{
|
||||
id: 'claude-sonnet-4-5-20250929',
|
||||
name: 'Claude Sonnet 4.5 (via Codex)',
|
||||
description: 'Anthropic model via Codex',
|
||||
id: 'gpt-4o',
|
||||
name: 'GPT-4o',
|
||||
description: 'General-purpose model with multimodal support',
|
||||
supportsImages: true,
|
||||
},
|
||||
{
|
||||
id: 'gpt-4o-mini',
|
||||
name: 'GPT-4o Mini',
|
||||
description: 'Cost-efficient GPT-4o variant',
|
||||
supportsImages: true,
|
||||
},
|
||||
{
|
||||
id: 'o1-preview',
|
||||
name: 'o1 Preview',
|
||||
description: 'OpenAI o1 preview model focused on agent use-cases',
|
||||
},
|
||||
{
|
||||
id: 'o1-mini',
|
||||
name: 'o1 Mini',
|
||||
description: 'Lightweight o1 model for faster iterations',
|
||||
},
|
||||
{
|
||||
id: 'o3',
|
||||
name: 'o3',
|
||||
description: 'OpenAI o3 reasoning model',
|
||||
},
|
||||
{
|
||||
id: 'claude-3.5-sonnet',
|
||||
name: 'Claude 3.5 Sonnet (via Codex)',
|
||||
description: 'Anthropic Claude via Codex router',
|
||||
},
|
||||
{
|
||||
id: 'claude-3-haiku',
|
||||
name: 'Claude 3 Haiku (via Codex)',
|
||||
description: 'Anthropic Haiku model routed through Codex',
|
||||
},
|
||||
];
|
||||
|
||||
export const CODEX_DEFAULT_MODEL = 'o3';
|
||||
export const CODEX_DEFAULT_MODEL = 'gpt-5';
|
||||
|
||||
// Codex model alias normalization (aligned with other/cweb)
|
||||
const CODEX_ALIAS_MAP: Record<string, string> = {
|
||||
gpt5: 'gpt-5',
|
||||
gpt_5: 'gpt-5',
|
||||
'gpt-5.0': 'gpt-5',
|
||||
'gpt-4o-mini-high': 'gpt-4o-mini',
|
||||
'gpt-4o-mini-low': 'gpt-4o-mini',
|
||||
'claude-sonnet-3.5': 'claude-3.5-sonnet',
|
||||
'claude35-sonnet': 'claude-3.5-sonnet',
|
||||
};
|
||||
|
||||
const CODEX_KNOWN_IDS = new Set(CODEX_MODELS.map((model) => model.id));
|
||||
|
||||
/**
|
||||
* Normalize a Codex model ID, handling aliases and falling back to default.
|
||||
*/
|
||||
export function normalizeCodexModelId(model?: string | null): string {
|
||||
if (!model || typeof model !== 'string') {
|
||||
return CODEX_DEFAULT_MODEL;
|
||||
}
|
||||
|
||||
const trimmed = model.trim();
|
||||
if (!trimmed) {
|
||||
return CODEX_DEFAULT_MODEL;
|
||||
}
|
||||
|
||||
const lower = trimmed.toLowerCase();
|
||||
if (CODEX_ALIAS_MAP[lower]) {
|
||||
return CODEX_ALIAS_MAP[lower];
|
||||
}
|
||||
|
||||
if (CODEX_KNOWN_IDS.has(lower)) {
|
||||
return lower;
|
||||
}
|
||||
|
||||
// If the exact casing exists, allow it
|
||||
if (CODEX_KNOWN_IDS.has(trimmed)) {
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
return CODEX_DEFAULT_MODEL;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Cursor Models
|
||||
|
||||
@@ -271,6 +271,8 @@ export class AgentChatService {
|
||||
resumeClaudeSessionId: engineName === 'claude' ? resumeClaudeSessionId : undefined,
|
||||
// Pass useCcr flag for Claude Code Router support (ClaudeEngine only)
|
||||
useCcr: engineName === 'claude' ? projectUseCcr : undefined,
|
||||
// Pass Codex-specific configuration (CodexEngine only)
|
||||
codexConfig: engineName === 'codex' ? dbSession?.optionsConfig?.codexConfig : undefined,
|
||||
};
|
||||
|
||||
// Create abort controller for cancellation support
|
||||
|
||||
@@ -2,6 +2,11 @@ import { spawn } from 'node:child_process';
|
||||
import readline from 'node:readline';
|
||||
import path from 'node:path';
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import {
|
||||
CODEX_AUTO_INSTRUCTIONS,
|
||||
DEFAULT_CODEX_CONFIG,
|
||||
type CodexEngineConfig,
|
||||
} from 'chrome-mcp-shared';
|
||||
import type { AgentEngine, EngineExecutionContext, EngineInitOptions } from './types';
|
||||
import type { AgentMessage, RealtimeEvent } from '../types';
|
||||
import { AgentToolBridge } from '../tool-bridge';
|
||||
@@ -41,7 +46,16 @@ export class CodexEngine implements AgentEngine {
|
||||
private static readonly MAX_STDERR_LINES = 200;
|
||||
|
||||
async initializeAndRun(options: EngineInitOptions, ctx: EngineExecutionContext): Promise<void> {
|
||||
const { sessionId, instruction, model, projectRoot, requestId, signal, attachments } = options;
|
||||
const {
|
||||
sessionId,
|
||||
instruction,
|
||||
model,
|
||||
projectRoot,
|
||||
requestId,
|
||||
signal,
|
||||
attachments,
|
||||
codexConfig,
|
||||
} = options;
|
||||
const repoPath = this.resolveRepoPath(projectRoot);
|
||||
|
||||
// Check if already aborted
|
||||
@@ -54,6 +68,22 @@ export class CodexEngine implements AgentEngine {
|
||||
throw new Error('CodexEngine: instruction must not be empty');
|
||||
}
|
||||
|
||||
// Merge user config with defaults
|
||||
const resolvedConfig: CodexEngineConfig = {
|
||||
...DEFAULT_CODEX_CONFIG,
|
||||
...(codexConfig ?? {}),
|
||||
};
|
||||
|
||||
// Ensure autoInstructions has a value
|
||||
if (!resolvedConfig.autoInstructions?.trim()) {
|
||||
resolvedConfig.autoInstructions = CODEX_AUTO_INSTRUCTIONS;
|
||||
}
|
||||
|
||||
// Optionally append project context to the prompt
|
||||
const prompt = resolvedConfig.appendProjectContext
|
||||
? await this.appendProjectContext(normalizedInstruction, repoPath)
|
||||
: normalizedInstruction;
|
||||
|
||||
const executable = process.platform === 'win32' ? 'codex.cmd' : 'codex';
|
||||
const args: string[] = [
|
||||
'exec',
|
||||
@@ -66,6 +96,9 @@ export class CodexEngine implements AgentEngine {
|
||||
repoPath,
|
||||
];
|
||||
|
||||
// Add Codex configuration arguments
|
||||
args.push(...this.buildCodexConfigArgs(resolvedConfig));
|
||||
|
||||
if (model && model.trim()) {
|
||||
args.push('--model', model.trim());
|
||||
}
|
||||
@@ -86,7 +119,7 @@ export class CodexEngine implements AgentEngine {
|
||||
}
|
||||
}
|
||||
|
||||
args.push(normalizedInstruction);
|
||||
args.push(prompt);
|
||||
|
||||
// Use explicit Promise wrapping to ensure child process errors are properly rejected.
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
@@ -111,6 +144,8 @@ export class CodexEngine implements AgentEngine {
|
||||
let assistantMessageId: string | null = null;
|
||||
let assistantCreatedAt: string | null = null;
|
||||
const streamedToolHashes = new Set<string>();
|
||||
const activeCommands = new Map<string, { command?: string }>();
|
||||
const thinkingSegments: string[] = [];
|
||||
|
||||
/**
|
||||
* Cleanup and settle the promise (resolve or reject).
|
||||
@@ -188,9 +223,40 @@ export class CodexEngine implements AgentEngine {
|
||||
|
||||
rl = readline.createInterface({ input: child.stdout });
|
||||
|
||||
/**
|
||||
* Build the assistant message payload, combining thinking and agent content.
|
||||
*/
|
||||
const buildAssistantPayload = (): string => {
|
||||
const trimmedAssistant = assistantBuffer.trim();
|
||||
const thinkingContent = thinkingSegments
|
||||
.map((segment) => segment.trim())
|
||||
.filter((segment) => segment.length > 0)
|
||||
.map((segment) => `<thinking>${segment}</thinking>`)
|
||||
.join('\n\n');
|
||||
|
||||
const parts: string[] = [];
|
||||
if (thinkingContent) {
|
||||
parts.push(thinkingContent);
|
||||
}
|
||||
if (trimmedAssistant) {
|
||||
parts.push(trimmedAssistant);
|
||||
}
|
||||
return parts.join('\n\n').trim();
|
||||
};
|
||||
|
||||
/**
|
||||
* Reset assistant buffers after emitting a final message.
|
||||
*/
|
||||
const resetAssistantBuffers = (): void => {
|
||||
assistantBuffer = '';
|
||||
thinkingSegments.length = 0;
|
||||
assistantMessageId = null;
|
||||
assistantCreatedAt = null;
|
||||
};
|
||||
|
||||
// Helper: emit assistant message
|
||||
const emitAssistant = (isFinal: boolean): void => {
|
||||
const content = assistantBuffer.trim();
|
||||
const content = buildAssistantPayload();
|
||||
if (!content) return;
|
||||
|
||||
if (!assistantMessageId) {
|
||||
@@ -251,7 +317,9 @@ export class CodexEngine implements AgentEngine {
|
||||
|
||||
// Event handlers for specific item types
|
||||
const emitCommandStart = (item: Record<string, unknown>): void => {
|
||||
const id = this.pickFirstString(item.id) ?? randomUUID();
|
||||
const command = this.pickFirstString(item.command);
|
||||
activeCommands.set(id, { command });
|
||||
dispatchToolMessage(
|
||||
command ? `Running: ${command}` : 'Running command',
|
||||
{
|
||||
@@ -266,7 +334,12 @@ export class CodexEngine implements AgentEngine {
|
||||
};
|
||||
|
||||
const emitCommandResult = (item: Record<string, unknown>): void => {
|
||||
const command = this.pickFirstString(item.command);
|
||||
const id = this.pickFirstString(item.id);
|
||||
const tracked = id ? activeCommands.get(id) : undefined;
|
||||
if (id) {
|
||||
activeCommands.delete(id);
|
||||
}
|
||||
const command = this.pickFirstString(item.command) ?? tracked?.command;
|
||||
const output = this.pickFirstString(item.aggregated_output) ?? '';
|
||||
const exitCode = typeof item.exit_code === 'number' ? item.exit_code : undefined;
|
||||
const status = this.pickFirstString(item.status);
|
||||
@@ -347,12 +420,18 @@ export class CodexEngine implements AgentEngine {
|
||||
const record = delta as Record<string, unknown>;
|
||||
const type = this.pickFirstString(record.type);
|
||||
|
||||
if (type === 'agent_message' || type === 'reasoning') {
|
||||
if (type === 'agent_message') {
|
||||
const text = this.pickFirstString(record.text);
|
||||
if (text) {
|
||||
assistantBuffer += text;
|
||||
emitAssistant(false);
|
||||
}
|
||||
} else if (type === 'reasoning') {
|
||||
const text = this.pickFirstString(record.text);
|
||||
if (text) {
|
||||
thinkingSegments.push(text);
|
||||
emitAssistant(false);
|
||||
}
|
||||
} else if (type === 'todo_list') {
|
||||
emitTodoListUpdate(record, 'update');
|
||||
}
|
||||
@@ -377,12 +456,21 @@ export class CodexEngine implements AgentEngine {
|
||||
const text = this.pickFirstString(record.text);
|
||||
if (text) assistantBuffer = text;
|
||||
emitAssistant(true);
|
||||
resetAssistantBuffers();
|
||||
break;
|
||||
}
|
||||
case 'reasoning': {
|
||||
const text = this.pickFirstString(record.text);
|
||||
if (text) {
|
||||
thinkingSegments.push(text);
|
||||
emitAssistant(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
const text = this.pickFirstString(record.text);
|
||||
if (text) {
|
||||
assistantBuffer += text;
|
||||
thinkingSegments.push(text);
|
||||
emitAssistant(false);
|
||||
}
|
||||
break;
|
||||
@@ -411,12 +499,33 @@ export class CodexEngine implements AgentEngine {
|
||||
}, timeoutMs);
|
||||
timeoutHandle.unref?.();
|
||||
|
||||
// Cleanup timeout when child closes
|
||||
child.on('close', () => {
|
||||
// Cleanup timeout and handle abnormal exit
|
||||
child.on('close', (code: number | null, closeSignal: NodeJS.Signals | null) => {
|
||||
if (timeoutHandle) {
|
||||
clearTimeout(timeoutHandle);
|
||||
timeoutHandle = null;
|
||||
}
|
||||
|
||||
// If already timed out, settled, or completed normally, do nothing
|
||||
if (timedOut || settled || hasCompleted) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Build error detail from exit code and signal
|
||||
const detailParts: string[] = [];
|
||||
if (typeof code === 'number') {
|
||||
detailParts.push(`exit code ${code}`);
|
||||
}
|
||||
if (closeSignal) {
|
||||
detailParts.push(`signal ${closeSignal}`);
|
||||
}
|
||||
const detail = detailParts.length > 0 ? detailParts.join(', ') : 'unexpected shutdown';
|
||||
|
||||
// Emit final assistant message and mark as failed
|
||||
emitAssistant(true);
|
||||
resetAssistantBuffers();
|
||||
hasCompleted = true;
|
||||
finish(new Error(`CodexEngine: process terminated (${detail})`));
|
||||
});
|
||||
|
||||
// Main event processing loop (wrapped in IIFE to handle async properly)
|
||||
@@ -448,6 +557,9 @@ export class CodexEngine implements AgentEngine {
|
||||
case 'item.failed': {
|
||||
const item = (event as { item?: unknown }).item ?? null;
|
||||
handleItemCompleted(item);
|
||||
// Flush assistant message before throwing (aligned with other/cweb)
|
||||
emitAssistant(true);
|
||||
resetAssistantBuffers();
|
||||
const msg =
|
||||
(item &&
|
||||
typeof item === 'object' &&
|
||||
@@ -457,6 +569,9 @@ export class CodexEngine implements AgentEngine {
|
||||
throw new Error(msg);
|
||||
}
|
||||
case 'error': {
|
||||
// Flush assistant message before throwing (aligned with other/cweb)
|
||||
emitAssistant(true);
|
||||
resetAssistantBuffers();
|
||||
const msg =
|
||||
this.pickFirstString((event as { error?: unknown }).error) ||
|
||||
this.pickFirstString((event as { message?: unknown }).message) ||
|
||||
@@ -466,6 +581,8 @@ export class CodexEngine implements AgentEngine {
|
||||
throw new Error(msg);
|
||||
}
|
||||
case 'turn.completed':
|
||||
emitAssistant(true);
|
||||
resetAssistantBuffers();
|
||||
hasCompleted = true;
|
||||
break;
|
||||
default:
|
||||
@@ -482,6 +599,7 @@ export class CodexEngine implements AgentEngine {
|
||||
// Emit final assistant message if not already completed
|
||||
if (!hasCompleted) {
|
||||
emitAssistant(true);
|
||||
resetAssistantBuffers();
|
||||
hasCompleted = true;
|
||||
}
|
||||
|
||||
@@ -499,6 +617,61 @@ export class CodexEngine implements AgentEngine {
|
||||
return path.resolve(base);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append project context (file listing) to the prompt.
|
||||
* Aligned with other/cweb implementation.
|
||||
*/
|
||||
private async appendProjectContext(baseInstruction: string, repoPath: string): Promise<string> {
|
||||
try {
|
||||
const fs = await import('node:fs/promises');
|
||||
const entries = await fs.readdir(repoPath, { withFileTypes: true });
|
||||
const visible = entries
|
||||
.filter((entry) => !entry.name.startsWith('.git') && entry.name !== 'AGENTS.md')
|
||||
.map((entry) => entry.name);
|
||||
|
||||
if (visible.length === 0) {
|
||||
return `${baseInstruction}
|
||||
|
||||
<current_project_context>
|
||||
This is an empty project directory. Work directly in the current folder without creating extra subdirectories.
|
||||
</current_project_context>`;
|
||||
}
|
||||
|
||||
return `${baseInstruction}
|
||||
|
||||
<current_project_context>
|
||||
Current files in project directory: ${visible.sort().join(', ')}
|
||||
Work directly in the current directory. Do not create subdirectories unless specifically requested.
|
||||
</current_project_context>`;
|
||||
} catch (error) {
|
||||
console.warn('[CodexEngine] Failed to append project context:', error);
|
||||
return baseInstruction;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build Codex CLI configuration arguments from the resolved config.
|
||||
* Aligned with other/cweb implementation for feature parity.
|
||||
*/
|
||||
private buildCodexConfigArgs(config: CodexEngineConfig): string[] {
|
||||
const args: string[] = [];
|
||||
|
||||
const pushConfig = (key: string, value: string | number | boolean): void => {
|
||||
args.push('-c', `${key}=${String(value)}`);
|
||||
};
|
||||
|
||||
pushConfig('include_apply_patch_tool', config.includeApplyPatchTool);
|
||||
pushConfig('include_plan_tool', config.includePlanTool);
|
||||
pushConfig('tools.web_search_request', config.enableWebSearch);
|
||||
pushConfig('use_experimental_streamable_shell_tool', config.useStreamableShell);
|
||||
pushConfig('sandbox_mode', config.sandboxMode);
|
||||
pushConfig('max_turns', config.maxTurns);
|
||||
pushConfig('max_thinking_tokens', config.maxThinkingTokens);
|
||||
args.push('-c', `instructions=${JSON.stringify(config.autoInstructions)}`);
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an attachment to a temporary file and return its path.
|
||||
*/
|
||||
@@ -530,6 +703,17 @@ export class CodexEngine implements AgentEngine {
|
||||
if (globalPath) {
|
||||
extraPaths.push(globalPath);
|
||||
}
|
||||
// Enhanced Windows PATH handling (aligned with other/cweb)
|
||||
if (process.platform === 'win32') {
|
||||
const appData = process.env.APPDATA;
|
||||
const localApp = process.env.LOCALAPPDATA;
|
||||
if (appData) {
|
||||
extraPaths.push(path.join(appData, 'npm'));
|
||||
}
|
||||
if (localApp) {
|
||||
extraPaths.push(path.join(localApp, 'Programs', 'nodejs'));
|
||||
}
|
||||
}
|
||||
if (extraPaths.length > 0) {
|
||||
const currentPath = env.PATH || env.Path || '';
|
||||
env.PATH = [...extraPaths, currentPath].filter(Boolean).join(path.delimiter);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { AgentAttachment, RealtimeEvent } from '../types';
|
||||
import type { CodexEngineConfig } from 'chrome-mcp-shared';
|
||||
|
||||
export interface EngineInitOptions {
|
||||
sessionId: string;
|
||||
@@ -50,6 +51,11 @@ export interface EngineInitOptions {
|
||||
* Only applicable to ClaudeEngine; when true, CCR will be auto-detected.
|
||||
*/
|
||||
useCcr?: boolean;
|
||||
/**
|
||||
* Optional Codex-specific configuration overrides.
|
||||
* Only applicable to CodexEngine; merged with DEFAULT_CODEX_CONFIG.
|
||||
*/
|
||||
codexConfig?: Partial<CodexEngineConfig>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,6 +44,11 @@ export interface SessionOptionsConfig {
|
||||
enableFileCheckpointing?: boolean;
|
||||
sandbox?: Record<string, unknown>;
|
||||
env?: Record<string, string>;
|
||||
/**
|
||||
* Optional Codex-specific configuration overrides.
|
||||
* Only applicable when using CodexEngine.
|
||||
*/
|
||||
codexConfig?: Partial<import('chrome-mcp-shared').CodexEngineConfig>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -183,6 +183,11 @@ export interface AgentSessionOptionsConfig {
|
||||
enableFileCheckpointing?: boolean;
|
||||
sandbox?: Record<string, unknown>;
|
||||
env?: Record<string, string>;
|
||||
/**
|
||||
* Optional Codex-specific configuration overrides.
|
||||
* Only applicable when using CodexEngine.
|
||||
*/
|
||||
codexConfig?: Partial<CodexEngineConfig>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -268,3 +273,64 @@ export interface AgentStoredMessage {
|
||||
createdAt?: string;
|
||||
requestId?: string;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Codex Engine Configuration
|
||||
// ============================================================
|
||||
|
||||
/**
|
||||
* Sandbox mode for Codex CLI execution.
|
||||
*/
|
||||
export type CodexSandboxMode = 'read-only' | 'workspace-write' | 'danger-full-access';
|
||||
|
||||
/**
|
||||
* Configuration options for Codex Engine.
|
||||
* These can be overridden per-session via session settings.
|
||||
*/
|
||||
export interface CodexEngineConfig {
|
||||
/** Enable apply_patch tool for file modifications. Default: true */
|
||||
includeApplyPatchTool: boolean;
|
||||
/** Enable plan tool for task planning. Default: true */
|
||||
includePlanTool: boolean;
|
||||
/** Enable web search capability. Default: true */
|
||||
enableWebSearch: boolean;
|
||||
/** Use experimental streamable shell tool. Default: true */
|
||||
useStreamableShell: boolean;
|
||||
/** Sandbox mode for command execution. Default: 'danger-full-access' */
|
||||
sandboxMode: CodexSandboxMode;
|
||||
/** Maximum number of turns. Default: 20 */
|
||||
maxTurns: number;
|
||||
/** Maximum thinking tokens. Default: 4096 */
|
||||
maxThinkingTokens: number;
|
||||
/** Auto instructions for autonomous behavior. Default: AUTO_INSTRUCTIONS */
|
||||
autoInstructions: string;
|
||||
/** Append project context (file listing) to prompt. Default: true */
|
||||
appendProjectContext: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default auto instructions for Codex to act autonomously.
|
||||
* Aligned with other/cweb implementation.
|
||||
*/
|
||||
export const CODEX_AUTO_INSTRUCTIONS = `Act autonomously without asking for confirmations.
|
||||
Use apply_patch to create and modify files directly in the current working directory (do not create subdirectories unless the user explicitly requests it).
|
||||
Use exec_command to run, build, and test as needed.
|
||||
You have full permissions. Keep taking concrete actions until the task is complete.
|
||||
Respect the existing project structure when creating or modifying files.
|
||||
Prefer concise status updates over questions.`;
|
||||
|
||||
/**
|
||||
* Default configuration for Codex Engine.
|
||||
* Aligned with other/cweb implementation for feature parity.
|
||||
*/
|
||||
export const DEFAULT_CODEX_CONFIG: CodexEngineConfig = {
|
||||
includeApplyPatchTool: true,
|
||||
includePlanTool: true,
|
||||
enableWebSearch: true,
|
||||
useStreamableShell: true,
|
||||
sandboxMode: 'danger-full-access',
|
||||
maxTurns: 20,
|
||||
maxThinkingTokens: 4096,
|
||||
autoInstructions: CODEX_AUTO_INSTRUCTIONS,
|
||||
appendProjectContext: true,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user