titan-agent 5.6.0 → 5.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -65,7 +65,7 @@ const codexAdapter = {
65
65
  });
66
66
  child.stdin.write(ctx.task);
67
67
  child.stdin.end();
68
- child.on("close", (code, signal) => {
68
+ child.on("close", (code, _signal) => {
69
69
  clearTimeout(timer);
70
70
  const durationMs = Date.now() - startMs;
71
71
  let content = stdout.trim();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/agent/adapters/codex.ts"],"sourcesContent":["/**\n * TITAN — Codex CLI Adapter\n *\n * Spawns OpenAI Codex (`codex`) as a child process with `exec --json` mode.\n * Injects TITAN env vars for callback integration.\n */\nimport { spawn } from 'child_process';\nimport { existsSync } from 'fs';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport type { ExternalAdapter, AdapterContext, AdapterResult } from './base.js';\nimport logger from '../../utils/logger.js';\n\nconst COMPONENT = 'Adapter:Codex';\nconst MAX_OUTPUT = 4 * 1024 * 1024;\n\nfunction findCodexBinary(): string | null {\n const pathDirs = (process.env.PATH || '').split(':');\n for (const dir of pathDirs) {\n const p = join(dir, 'codex');\n if (existsSync(p)) return p;\n }\n const npmGlobal = join(homedir(), '.npm-global', 'bin', 'codex');\n if (existsSync(npmGlobal)) return npmGlobal;\n return null;\n}\n\nexport const codexAdapter: ExternalAdapter = {\n type: 'codex',\n displayName: 'Codex',\n\n async execute(ctx: AdapterContext): Promise<AdapterResult> {\n const binary = findCodexBinary();\n if (!binary) {\n return {\n content: 'Codex CLI not found. Install with: npm install -g @openai/codex',\n exitCode: 1, success: false, durationMs: 0, toolsUsed: [],\n };\n }\n\n const startMs = Date.now();\n const timeoutMs = ctx.timeoutMs || 300_000;\n\n const args = ['exec', '--json', '-'];\n\n const env: Record<string, string> = {\n ...process.env as Record<string, string>,\n TITAN_API_URL: ctx.titanApiUrl,\n TITAN_RUN_ID: ctx.titanRunId,\n TITAN_ISSUE_ID: ctx.titanIssueId,\n ...ctx.env,\n };\n\n logger.info(COMPONENT, `Spawning: ${binary} ${args.join(' ')} (timeout: ${timeoutMs}ms)`);\n\n return new Promise<AdapterResult>((resolve) => {\n let stdout = '';\n let stderr = '';\n let killed = false;\n\n const child = spawn(binary, args, {\n cwd: ctx.cwd || process.cwd(),\n env,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n const timer = setTimeout(() => {\n killed = true;\n child.kill('SIGTERM');\n setTimeout(() => { if (!child.killed) child.kill('SIGKILL'); }, 5000);\n }, timeoutMs);\n\n child.stdout.on('data', (chunk: Buffer) => {\n if (stdout.length < MAX_OUTPUT) stdout += chunk.toString();\n });\n child.stderr.on('data', (chunk: Buffer) => {\n if (stderr.length < MAX_OUTPUT) stderr += chunk.toString();\n });\n\n child.stdin.write(ctx.task);\n child.stdin.end();\n\n child.on('close', (code, signal) => {\n clearTimeout(timer);\n const durationMs = Date.now() - startMs;\n\n // Try to parse JSONL output for result\n let content = stdout.trim();\n try {\n const lines = content.split('\\n').filter(l => l.trim());\n const lastLine = lines[lines.length - 1];\n const parsed = JSON.parse(lastLine);\n if (parsed.result) content = parsed.result;\n } catch { /* use raw stdout */ }\n\n if (!content) content = stderr.trim() || (killed ? 'Execution timed out' : 'No output');\n\n logger.info(COMPONENT, `Completed in ${durationMs}ms — exit: ${code}`);\n\n resolve({\n content,\n exitCode: code,\n success: code === 0 && !killed,\n durationMs,\n toolsUsed: ['codex'],\n });\n });\n\n child.on('error', (err) => {\n clearTimeout(timer);\n resolve({\n content: `Failed to spawn Codex: ${err.message}`,\n exitCode: 1, success: false, durationMs: Date.now() - startMs, toolsUsed: [],\n });\n });\n });\n },\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/agent/adapters/codex.ts"],"sourcesContent":["/**\n * TITAN — Codex CLI Adapter\n *\n * Spawns OpenAI Codex (`codex`) as a child process with `exec --json` mode.\n * Injects TITAN env vars for callback integration.\n */\nimport { spawn } from 'child_process';\nimport { existsSync } from 'fs';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport type { ExternalAdapter, AdapterContext, AdapterResult } from './base.js';\nimport logger from '../../utils/logger.js';\n\nconst COMPONENT = 'Adapter:Codex';\nconst MAX_OUTPUT = 4 * 1024 * 1024;\n\nfunction findCodexBinary(): string | null {\n const pathDirs = (process.env.PATH || '').split(':');\n for (const dir of pathDirs) {\n const p = join(dir, 'codex');\n if (existsSync(p)) return p;\n }\n const npmGlobal = join(homedir(), '.npm-global', 'bin', 'codex');\n if (existsSync(npmGlobal)) return npmGlobal;\n return null;\n}\n\nexport const codexAdapter: ExternalAdapter = {\n type: 'codex',\n displayName: 'Codex',\n\n async execute(ctx: AdapterContext): Promise<AdapterResult> {\n const binary = findCodexBinary();\n if (!binary) {\n return {\n content: 'Codex CLI not found. Install with: npm install -g @openai/codex',\n exitCode: 1, success: false, durationMs: 0, toolsUsed: [],\n };\n }\n\n const startMs = Date.now();\n const timeoutMs = ctx.timeoutMs || 300_000;\n\n const args = ['exec', '--json', '-'];\n\n const env: Record<string, string> = {\n ...process.env as Record<string, string>,\n TITAN_API_URL: ctx.titanApiUrl,\n TITAN_RUN_ID: ctx.titanRunId,\n TITAN_ISSUE_ID: ctx.titanIssueId,\n ...ctx.env,\n };\n\n logger.info(COMPONENT, `Spawning: ${binary} ${args.join(' ')} (timeout: ${timeoutMs}ms)`);\n\n return new Promise<AdapterResult>((resolve) => {\n let stdout = '';\n let stderr = '';\n let killed = false;\n\n const child = spawn(binary, args, {\n cwd: ctx.cwd || process.cwd(),\n env,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n const timer = setTimeout(() => {\n killed = true;\n child.kill('SIGTERM');\n setTimeout(() => { if (!child.killed) child.kill('SIGKILL'); }, 5000);\n }, timeoutMs);\n\n child.stdout.on('data', (chunk: Buffer) => {\n if (stdout.length < MAX_OUTPUT) stdout += chunk.toString();\n });\n child.stderr.on('data', (chunk: Buffer) => {\n if (stderr.length < MAX_OUTPUT) stderr += chunk.toString();\n });\n\n child.stdin.write(ctx.task);\n child.stdin.end();\n\n child.on('close', (code, _signal) => {\n clearTimeout(timer);\n const durationMs = Date.now() - startMs;\n\n // Try to parse JSONL output for result\n let content = stdout.trim();\n try {\n const lines = content.split('\\n').filter(l => l.trim());\n const lastLine = lines[lines.length - 1];\n const parsed = JSON.parse(lastLine);\n if (parsed.result) content = parsed.result;\n } catch { /* use raw stdout */ }\n\n if (!content) content = stderr.trim() || (killed ? 'Execution timed out' : 'No output');\n\n logger.info(COMPONENT, `Completed in ${durationMs}ms — exit: ${code}`);\n\n resolve({\n content,\n exitCode: code,\n success: code === 0 && !killed,\n durationMs,\n toolsUsed: ['codex'],\n });\n });\n\n child.on('error', (err) => {\n clearTimeout(timer);\n resolve({\n content: `Failed to spawn Codex: ${err.message}`,\n exitCode: 1, success: false, durationMs: Date.now() - startMs, toolsUsed: [],\n });\n });\n });\n },\n};\n"],"mappings":";AAMA,SAAS,aAAa;AACtB,SAAS,kBAAkB;AAC3B,SAAS,eAAe;AACxB,SAAS,YAAY;AAErB,OAAO,YAAY;AAEnB,MAAM,YAAY;AAClB,MAAM,aAAa,IAAI,OAAO;AAE9B,SAAS,kBAAiC;AACtC,QAAM,YAAY,QAAQ,IAAI,QAAQ,IAAI,MAAM,GAAG;AACnD,aAAW,OAAO,UAAU;AACxB,UAAM,IAAI,KAAK,KAAK,OAAO;AAC3B,QAAI,WAAW,CAAC,EAAG,QAAO;AAAA,EAC9B;AACA,QAAM,YAAY,KAAK,QAAQ,GAAG,eAAe,OAAO,OAAO;AAC/D,MAAI,WAAW,SAAS,EAAG,QAAO;AAClC,SAAO;AACX;AAEO,MAAM,eAAgC;AAAA,EACzC,MAAM;AAAA,EACN,aAAa;AAAA,EAEb,MAAM,QAAQ,KAA6C;AACvD,UAAM,SAAS,gBAAgB;AAC/B,QAAI,CAAC,QAAQ;AACT,aAAO;AAAA,QACH,SAAS;AAAA,QACT,UAAU;AAAA,QAAG,SAAS;AAAA,QAAO,YAAY;AAAA,QAAG,WAAW,CAAC;AAAA,MAC5D;AAAA,IACJ;AAEA,UAAM,UAAU,KAAK,IAAI;AACzB,UAAM,YAAY,IAAI,aAAa;AAEnC,UAAM,OAAO,CAAC,QAAQ,UAAU,GAAG;AAEnC,UAAM,MAA8B;AAAA,MAChC,GAAG,QAAQ;AAAA,MACX,eAAe,IAAI;AAAA,MACnB,cAAc,IAAI;AAAA,MAClB,gBAAgB,IAAI;AAAA,MACpB,GAAG,IAAI;AAAA,IACX;AAEA,WAAO,KAAK,WAAW,aAAa,MAAM,IAAI,KAAK,KAAK,GAAG,CAAC,cAAc,SAAS,KAAK;AAExF,WAAO,IAAI,QAAuB,CAAC,YAAY;AAC3C,UAAI,SAAS;AACb,UAAI,SAAS;AACb,UAAI,SAAS;AAEb,YAAM,QAAQ,MAAM,QAAQ,MAAM;AAAA,QAC9B,KAAK,IAAI,OAAO,QAAQ,IAAI;AAAA,QAC5B;AAAA,QACA,OAAO,CAAC,QAAQ,QAAQ,MAAM;AAAA,MAClC,CAAC;AAED,YAAM,QAAQ,WAAW,MAAM;AAC3B,iBAAS;AACT,cAAM,KAAK,SAAS;AACpB,mBAAW,MAAM;AAAE,cAAI,CAAC,MAAM,OAAQ,OAAM,KAAK,SAAS;AAAA,QAAG,GAAG,GAAI;AAAA,MACxE,GAAG,SAAS;AAEZ,YAAM,OAAO,GAAG,QAAQ,CAAC,UAAkB;AACvC,YAAI,OAAO,SAAS,WAAY,WAAU,MAAM,SAAS;AAAA,MAC7D,CAAC;AACD,YAAM,OAAO,GAAG,QAAQ,CAAC,UAAkB;AACvC,YAAI,OAAO,SAAS,WAAY,WAAU,MAAM,SAAS;AAAA,MAC7D,CAAC;AAED,YAAM,MAAM,MAAM,IAAI,IAAI;AAC1B,YAAM,MAAM,IAAI;AAEhB,YAAM,GAAG,SAAS,CAAC,MAAM,YAAY;AACjC,qBAAa,KAAK;AAClB,cAAM,aAAa,KAAK,IAAI,IAAI;AAGhC,YAAI,UAAU,OAAO,KAAK;AAC1B,YAAI;AACA,gBAAM,QAAQ,QAAQ,MAAM,IAAI,EAAE,OAAO,OAAK,EAAE,KAAK,CAAC;AACtD,gBAAM,WAAW,MAAM,MAAM,SAAS,CAAC;AACvC,gBAAM,SAAS,KAAK,MAAM,QAAQ;AAClC,cAAI,OAAO,OAAQ,WAAU,OAAO;AAAA,QACxC,QAAQ;AAAA,QAAuB;AAE/B,YAAI,CAAC,QAAS,WAAU,OAAO,KAAK,MAAM,SAAS,wBAAwB;AAE3E,eAAO,KAAK,WAAW,gBAAgB,UAAU,mBAAc,IAAI,EAAE;AAErE,gBAAQ;AAAA,UACJ;AAAA,UACA,UAAU;AAAA,UACV,SAAS,SAAS,KAAK,CAAC;AAAA,UACxB;AAAA,UACA,WAAW,CAAC,OAAO;AAAA,QACvB,CAAC;AAAA,MACL,CAAC;AAED,YAAM,GAAG,SAAS,CAAC,QAAQ;AACvB,qBAAa,KAAK;AAClB,gBAAQ;AAAA,UACJ,SAAS,0BAA0B,IAAI,OAAO;AAAA,UAC9C,UAAU;AAAA,UAAG,SAAS;AAAA,UAAO,YAAY,KAAK,IAAI,IAAI;AAAA,UAAS,WAAW,CAAC;AAAA,QAC/E,CAAC;AAAA,MACL,CAAC;AAAA,IACL,CAAC;AAAA,EACL;AACJ;","names":[]}
@@ -80,7 +80,7 @@ function estimateRoundBudget(message, config) {
80
80
  }
81
81
  return Math.min(budget, hardCap);
82
82
  }
83
- function verifyTaskCompletion(message, toolsUsed, response) {
83
+ function verifyTaskCompletion(message, toolsUsed, _response) {
84
84
  const lower = message.toLowerCase();
85
85
  const verbMatch = /\b(edit|fix|change|modify|update|add|write|create|improve|rewrite|save|implement|patch)\b/i.test(lower);
86
86
  const hasFilePath = /[\w-]+\.(ts|tsx|js|jsx|py|md|json|yaml|yml|html|css|sh|txt|rs|go|java|cpp|c|h)\b|\bsrc\/|\bpath:|\/[a-z]+\//i.test(lower);