135 lines
3.9 KiB
JavaScript
Executable File
135 lines
3.9 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
const crypto = require('crypto');
|
|
const fs = require('fs');
|
|
const os = require('os');
|
|
const path = require('path');
|
|
|
|
function readStdin() {
|
|
return new Promise((resolve) => {
|
|
let data = '';
|
|
process.stdin.setEncoding('utf8');
|
|
process.stdin.on('data', (chunk) => { data += chunk; });
|
|
process.stdin.on('end', () => resolve(data));
|
|
});
|
|
}
|
|
|
|
function sleep(ms) {
|
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
}
|
|
|
|
(async function main() {
|
|
const args = process.argv.slice(2);
|
|
// cc-web can place `resume` after other `codex exec` options (e.g. --json, -s).
|
|
const isResume = args[0] === 'exec' && args.includes('resume');
|
|
const threadId = (() => {
|
|
if (!isResume) return `mock-${crypto.randomUUID()}`;
|
|
for (let i = args.length - 1; i >= 2; i--) {
|
|
const arg = args[i];
|
|
if (arg === '-' || String(arg).startsWith('-')) continue;
|
|
return arg;
|
|
}
|
|
return `mock-${crypto.randomUUID()}`;
|
|
})();
|
|
const input = (await readStdin()).trim();
|
|
const imageCount = args.filter((arg) => arg === '--image').length;
|
|
const statePath = path.join(os.tmpdir(), `cc-web-mock-codex-${threadId}.json`);
|
|
let state = {};
|
|
try {
|
|
state = JSON.parse(fs.readFileSync(statePath, 'utf8'));
|
|
} catch {}
|
|
|
|
process.stdout.write(`${JSON.stringify({ type: 'thread.started', thread_id: threadId })}\n`);
|
|
process.stdout.write(`${JSON.stringify({ type: 'turn.started' })}\n`);
|
|
|
|
if (/pwd/i.test(input)) {
|
|
process.stdout.write(`${JSON.stringify({
|
|
type: 'item.started',
|
|
item: {
|
|
id: 'item_cmd',
|
|
type: 'command_execution',
|
|
command: '/bin/bash -lc pwd',
|
|
aggregated_output: '',
|
|
exit_code: null,
|
|
status: 'in_progress',
|
|
},
|
|
})}\n`);
|
|
process.stdout.write(`${JSON.stringify({
|
|
type: 'item.completed',
|
|
item: {
|
|
id: 'item_cmd',
|
|
type: 'command_execution',
|
|
command: '/bin/bash -lc pwd',
|
|
aggregated_output: '/tmp/mock-codex\n',
|
|
exit_code: 0,
|
|
status: 'completed',
|
|
},
|
|
})}\n`);
|
|
}
|
|
|
|
if (input === '/compact') {
|
|
state.compacted = true;
|
|
fs.writeFileSync(statePath, JSON.stringify(state));
|
|
}
|
|
|
|
const isInitPrompt = input === '/init' || input.includes('You are running cc-web\'s /init for a Codex session.');
|
|
|
|
if (isInitPrompt) {
|
|
const agentsPath = path.join(process.cwd(), 'AGENTS.md');
|
|
fs.writeFileSync(agentsPath, '# AGENTS.md\n\nGenerated by mock Codex /init.\n');
|
|
}
|
|
|
|
if (input === 'trigger codex context limit' && !state.compacted) {
|
|
process.stdout.write(`${JSON.stringify({
|
|
type: 'turn.failed',
|
|
error: { message: 'Context window exceeded. Please use /compact and retry.' },
|
|
})}\n`);
|
|
process.exit(1);
|
|
}
|
|
|
|
if (input === 'trigger codex capacity retry' && !state.capacityRetried) {
|
|
state.capacityRetried = true;
|
|
fs.writeFileSync(statePath, JSON.stringify(state));
|
|
process.stdout.write(`${JSON.stringify({
|
|
type: 'turn.failed',
|
|
error: {
|
|
type: 'service_unavailable_error',
|
|
code: 'server_is_overloaded',
|
|
message: 'Our servers are currently overloaded. Please try again later.',
|
|
},
|
|
})}\n`);
|
|
process.exit(1);
|
|
}
|
|
|
|
if (input === 'slow cross-session prompt') {
|
|
await sleep(800);
|
|
}
|
|
if (input === 'very slow cross-session prompt') {
|
|
await sleep(2500);
|
|
}
|
|
|
|
const responseText = input === '/compact'
|
|
? 'Codex compact finished.'
|
|
: isInitPrompt
|
|
? 'Codex init finished.'
|
|
: `Codex mock handled (${imageCount} image): ${input}`;
|
|
|
|
process.stdout.write(`${JSON.stringify({
|
|
type: 'item.completed',
|
|
item: {
|
|
id: 'item_msg',
|
|
type: 'agent_message',
|
|
text: responseText,
|
|
},
|
|
})}\n`);
|
|
|
|
if (input === 'trigger codex context limit' && state.compacted) {
|
|
try { fs.unlinkSync(statePath); } catch {}
|
|
}
|
|
|
|
process.stdout.write(`${JSON.stringify({
|
|
type: 'turn.completed',
|
|
usage: { input_tokens: 10, cached_input_tokens: 2, output_tokens: 5 },
|
|
})}\n`);
|
|
})();
|