@the-open-engine/zeroshot 5.4.0

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.
Files changed (295) hide show
  1. package/CHANGELOG.md +539 -0
  2. package/LICENSE +21 -0
  3. package/README.md +508 -0
  4. package/cli/commands/inspect-render.js +135 -0
  5. package/cli/commands/inspect.js +294 -0
  6. package/cli/commands/providers.js +149 -0
  7. package/cli/index.js +5431 -0
  8. package/cli/lib/first-run.js +211 -0
  9. package/cli/lib/update-checker.js +281 -0
  10. package/cli/message-formatter-utils.js +75 -0
  11. package/cli/message-formatters-normal.js +275 -0
  12. package/cli/message-formatters-watch.js +185 -0
  13. package/cluster-templates/base-templates/debug-workflow.json +422 -0
  14. package/cluster-templates/base-templates/full-workflow.json +727 -0
  15. package/cluster-templates/base-templates/heavy-validation.json +272 -0
  16. package/cluster-templates/base-templates/quick-validation.json +285 -0
  17. package/cluster-templates/base-templates/single-worker.json +71 -0
  18. package/cluster-templates/base-templates/worker-validator.json +230 -0
  19. package/cluster-templates/conductor-bootstrap.json +130 -0
  20. package/docker/zeroshot-cluster/Dockerfile +153 -0
  21. package/docker/zeroshot-cluster/pre-baked-deps.json +28 -0
  22. package/lib/agent-cli-provider/adapters/claude-parser.d.ts +3 -0
  23. package/lib/agent-cli-provider/adapters/claude-parser.d.ts.map +1 -0
  24. package/lib/agent-cli-provider/adapters/claude-parser.js +122 -0
  25. package/lib/agent-cli-provider/adapters/claude-parser.js.map +1 -0
  26. package/lib/agent-cli-provider/adapters/claude-recovery.d.ts +15 -0
  27. package/lib/agent-cli-provider/adapters/claude-recovery.d.ts.map +1 -0
  28. package/lib/agent-cli-provider/adapters/claude-recovery.js +165 -0
  29. package/lib/agent-cli-provider/adapters/claude-recovery.js.map +1 -0
  30. package/lib/agent-cli-provider/adapters/claude.d.ts +3 -0
  31. package/lib/agent-cli-provider/adapters/claude.d.ts.map +1 -0
  32. package/lib/agent-cli-provider/adapters/claude.js +181 -0
  33. package/lib/agent-cli-provider/adapters/claude.js.map +1 -0
  34. package/lib/agent-cli-provider/adapters/codex-parser.d.ts +3 -0
  35. package/lib/agent-cli-provider/adapters/codex-parser.d.ts.map +1 -0
  36. package/lib/agent-cli-provider/adapters/codex-parser.js +192 -0
  37. package/lib/agent-cli-provider/adapters/codex-parser.js.map +1 -0
  38. package/lib/agent-cli-provider/adapters/codex.d.ts +3 -0
  39. package/lib/agent-cli-provider/adapters/codex.d.ts.map +1 -0
  40. package/lib/agent-cli-provider/adapters/codex.js +151 -0
  41. package/lib/agent-cli-provider/adapters/codex.js.map +1 -0
  42. package/lib/agent-cli-provider/adapters/common.d.ts +28 -0
  43. package/lib/agent-cli-provider/adapters/common.d.ts.map +1 -0
  44. package/lib/agent-cli-provider/adapters/common.js +71 -0
  45. package/lib/agent-cli-provider/adapters/common.js.map +1 -0
  46. package/lib/agent-cli-provider/adapters/gemini.d.ts +3 -0
  47. package/lib/agent-cli-provider/adapters/gemini.d.ts.map +1 -0
  48. package/lib/agent-cli-provider/adapters/gemini.js +176 -0
  49. package/lib/agent-cli-provider/adapters/gemini.js.map +1 -0
  50. package/lib/agent-cli-provider/adapters/index.d.ts +9 -0
  51. package/lib/agent-cli-provider/adapters/index.d.ts.map +1 -0
  52. package/lib/agent-cli-provider/adapters/index.js +95 -0
  53. package/lib/agent-cli-provider/adapters/index.js.map +1 -0
  54. package/lib/agent-cli-provider/adapters/opencode.d.ts +3 -0
  55. package/lib/agent-cli-provider/adapters/opencode.d.ts.map +1 -0
  56. package/lib/agent-cli-provider/adapters/opencode.js +228 -0
  57. package/lib/agent-cli-provider/adapters/opencode.js.map +1 -0
  58. package/lib/agent-cli-provider/contract-actions.d.ts +5 -0
  59. package/lib/agent-cli-provider/contract-actions.d.ts.map +1 -0
  60. package/lib/agent-cli-provider/contract-actions.js +140 -0
  61. package/lib/agent-cli-provider/contract-actions.js.map +1 -0
  62. package/lib/agent-cli-provider/contract-env.d.ts +11 -0
  63. package/lib/agent-cli-provider/contract-env.d.ts.map +1 -0
  64. package/lib/agent-cli-provider/contract-env.js +113 -0
  65. package/lib/agent-cli-provider/contract-env.js.map +1 -0
  66. package/lib/agent-cli-provider/contract-envelope.d.ts +49 -0
  67. package/lib/agent-cli-provider/contract-envelope.d.ts.map +1 -0
  68. package/lib/agent-cli-provider/contract-envelope.js +52 -0
  69. package/lib/agent-cli-provider/contract-envelope.js.map +1 -0
  70. package/lib/agent-cli-provider/contract-errors.d.ts +22 -0
  71. package/lib/agent-cli-provider/contract-errors.d.ts.map +1 -0
  72. package/lib/agent-cli-provider/contract-errors.js +71 -0
  73. package/lib/agent-cli-provider/contract-errors.js.map +1 -0
  74. package/lib/agent-cli-provider/contract-fallback.d.ts +7 -0
  75. package/lib/agent-cli-provider/contract-fallback.d.ts.map +1 -0
  76. package/lib/agent-cli-provider/contract-fallback.js +102 -0
  77. package/lib/agent-cli-provider/contract-fallback.js.map +1 -0
  78. package/lib/agent-cli-provider/contract-invoke.d.ts +5 -0
  79. package/lib/agent-cli-provider/contract-invoke.d.ts.map +1 -0
  80. package/lib/agent-cli-provider/contract-invoke.js +89 -0
  81. package/lib/agent-cli-provider/contract-invoke.js.map +1 -0
  82. package/lib/agent-cli-provider/contract-options.d.ts +3 -0
  83. package/lib/agent-cli-provider/contract-options.d.ts.map +1 -0
  84. package/lib/agent-cli-provider/contract-options.js +140 -0
  85. package/lib/agent-cli-provider/contract-options.js.map +1 -0
  86. package/lib/agent-cli-provider/contract-parse.d.ts +15 -0
  87. package/lib/agent-cli-provider/contract-parse.d.ts.map +1 -0
  88. package/lib/agent-cli-provider/contract-parse.js +81 -0
  89. package/lib/agent-cli-provider/contract-parse.js.map +1 -0
  90. package/lib/agent-cli-provider/contract-support.d.ts +18 -0
  91. package/lib/agent-cli-provider/contract-support.d.ts.map +1 -0
  92. package/lib/agent-cli-provider/contract-support.js +154 -0
  93. package/lib/agent-cli-provider/contract-support.js.map +1 -0
  94. package/lib/agent-cli-provider/contract.d.ts +13 -0
  95. package/lib/agent-cli-provider/contract.d.ts.map +1 -0
  96. package/lib/agent-cli-provider/contract.js +30 -0
  97. package/lib/agent-cli-provider/contract.js.map +1 -0
  98. package/lib/agent-cli-provider/env-safety.d.ts +11 -0
  99. package/lib/agent-cli-provider/env-safety.d.ts.map +1 -0
  100. package/lib/agent-cli-provider/env-safety.js +83 -0
  101. package/lib/agent-cli-provider/env-safety.js.map +1 -0
  102. package/lib/agent-cli-provider/errors.d.ts +5 -0
  103. package/lib/agent-cli-provider/errors.d.ts.map +1 -0
  104. package/lib/agent-cli-provider/errors.js +115 -0
  105. package/lib/agent-cli-provider/errors.js.map +1 -0
  106. package/lib/agent-cli-provider/executable.d.ts +3 -0
  107. package/lib/agent-cli-provider/executable.d.ts.map +1 -0
  108. package/lib/agent-cli-provider/executable.js +24 -0
  109. package/lib/agent-cli-provider/executable.js.map +1 -0
  110. package/lib/agent-cli-provider/index.d.ts +8 -0
  111. package/lib/agent-cli-provider/index.d.ts.map +1 -0
  112. package/lib/agent-cli-provider/index.js +31 -0
  113. package/lib/agent-cli-provider/index.js.map +1 -0
  114. package/lib/agent-cli-provider/invoke-evidence.d.ts +4 -0
  115. package/lib/agent-cli-provider/invoke-evidence.d.ts.map +1 -0
  116. package/lib/agent-cli-provider/invoke-evidence.js +17 -0
  117. package/lib/agent-cli-provider/invoke-evidence.js.map +1 -0
  118. package/lib/agent-cli-provider/json.d.ts +16 -0
  119. package/lib/agent-cli-provider/json.d.ts.map +1 -0
  120. package/lib/agent-cli-provider/json.js +110 -0
  121. package/lib/agent-cli-provider/json.js.map +1 -0
  122. package/lib/agent-cli-provider/log-prefix.d.ts +2 -0
  123. package/lib/agent-cli-provider/log-prefix.d.ts.map +1 -0
  124. package/lib/agent-cli-provider/log-prefix.js +22 -0
  125. package/lib/agent-cli-provider/log-prefix.js.map +1 -0
  126. package/lib/agent-cli-provider/process-runner.d.ts +17 -0
  127. package/lib/agent-cli-provider/process-runner.d.ts.map +1 -0
  128. package/lib/agent-cli-provider/process-runner.js +89 -0
  129. package/lib/agent-cli-provider/process-runner.js.map +1 -0
  130. package/lib/agent-cli-provider/redaction.d.ts +9 -0
  131. package/lib/agent-cli-provider/redaction.d.ts.map +1 -0
  132. package/lib/agent-cli-provider/redaction.js +227 -0
  133. package/lib/agent-cli-provider/redaction.js.map +1 -0
  134. package/lib/agent-cli-provider/schema.d.ts +5 -0
  135. package/lib/agent-cli-provider/schema.d.ts.map +1 -0
  136. package/lib/agent-cli-provider/schema.js +136 -0
  137. package/lib/agent-cli-provider/schema.js.map +1 -0
  138. package/lib/agent-cli-provider/single-agent-runtime.d.ts +15 -0
  139. package/lib/agent-cli-provider/single-agent-runtime.d.ts.map +1 -0
  140. package/lib/agent-cli-provider/single-agent-runtime.js +228 -0
  141. package/lib/agent-cli-provider/single-agent-runtime.js.map +1 -0
  142. package/lib/agent-cli-provider/types.d.ts +194 -0
  143. package/lib/agent-cli-provider/types.d.ts.map +1 -0
  144. package/lib/agent-cli-provider/types.js +12 -0
  145. package/lib/agent-cli-provider/types.js.map +1 -0
  146. package/lib/completion.js +174 -0
  147. package/lib/detached-startup.js +220 -0
  148. package/lib/docker-config.js +220 -0
  149. package/lib/git-remote-utils.js +165 -0
  150. package/lib/id-detector.js +55 -0
  151. package/lib/provider-defaults.js +62 -0
  152. package/lib/provider-detection.js +59 -0
  153. package/lib/provider-names.js +57 -0
  154. package/lib/repo-settings.js +69 -0
  155. package/lib/settings/claude-auth.js +78 -0
  156. package/lib/settings.js +542 -0
  157. package/lib/start-cluster.js +321 -0
  158. package/lib/stream-json-parser.js +67 -0
  159. package/package.json +162 -0
  160. package/scripts/fix-node-pty-permissions.js +75 -0
  161. package/scripts/record-demo.sh +279 -0
  162. package/scripts/setup-merge-queue.sh +170 -0
  163. package/scripts/test-install.sh +40 -0
  164. package/scripts/validate-templates.js +107 -0
  165. package/src/agent/agent-config.js +266 -0
  166. package/src/agent/agent-context-builder.js +189 -0
  167. package/src/agent/agent-context-sections.js +338 -0
  168. package/src/agent/agent-context-sources.js +147 -0
  169. package/src/agent/agent-hook-executor.js +721 -0
  170. package/src/agent/agent-input-injector.js +141 -0
  171. package/src/agent/agent-lifecycle.js +982 -0
  172. package/src/agent/agent-quality-gate-schema.js +93 -0
  173. package/src/agent/agent-quality-gates-context.js +51 -0
  174. package/src/agent/agent-stuck-detector.js +256 -0
  175. package/src/agent/agent-task-executor.js +2028 -0
  176. package/src/agent/agent-trigger-evaluator.js +67 -0
  177. package/src/agent/context-metrics.js +160 -0
  178. package/src/agent/context-pack-builder.js +367 -0
  179. package/src/agent/context-replay-policy.js +51 -0
  180. package/src/agent/guidance-queue.js +77 -0
  181. package/src/agent/output-extraction.js +367 -0
  182. package/src/agent/output-reformatter.js +175 -0
  183. package/src/agent/pr-verification.js +653 -0
  184. package/src/agent/rate-limit-backoff.js +82 -0
  185. package/src/agent/schema-utils.js +146 -0
  186. package/src/agent/validation-platform.js +35 -0
  187. package/src/agent-cli-provider/adapters/claude-parser.ts +133 -0
  188. package/src/agent-cli-provider/adapters/claude-recovery.ts +203 -0
  189. package/src/agent-cli-provider/adapters/claude.ts +247 -0
  190. package/src/agent-cli-provider/adapters/codex-parser.ts +211 -0
  191. package/src/agent-cli-provider/adapters/codex.ts +217 -0
  192. package/src/agent-cli-provider/adapters/common.ts +124 -0
  193. package/src/agent-cli-provider/adapters/gemini.ts +243 -0
  194. package/src/agent-cli-provider/adapters/index.ts +126 -0
  195. package/src/agent-cli-provider/adapters/opencode.ts +286 -0
  196. package/src/agent-cli-provider/contract-actions.ts +150 -0
  197. package/src/agent-cli-provider/contract-env.ts +111 -0
  198. package/src/agent-cli-provider/contract-envelope.ts +110 -0
  199. package/src/agent-cli-provider/contract-errors.ts +66 -0
  200. package/src/agent-cli-provider/contract-fallback.ts +121 -0
  201. package/src/agent-cli-provider/contract-invoke.ts +104 -0
  202. package/src/agent-cli-provider/contract-options.ts +173 -0
  203. package/src/agent-cli-provider/contract-parse.ts +94 -0
  204. package/src/agent-cli-provider/contract-support.ts +167 -0
  205. package/src/agent-cli-provider/contract.ts +56 -0
  206. package/src/agent-cli-provider/env-safety.ts +82 -0
  207. package/src/agent-cli-provider/errors.ts +122 -0
  208. package/src/agent-cli-provider/executable.ts +24 -0
  209. package/src/agent-cli-provider/index.ts +83 -0
  210. package/src/agent-cli-provider/invoke-evidence.ts +18 -0
  211. package/src/agent-cli-provider/json.ts +114 -0
  212. package/src/agent-cli-provider/log-prefix.ts +20 -0
  213. package/src/agent-cli-provider/process-runner.ts +145 -0
  214. package/src/agent-cli-provider/redaction.ts +282 -0
  215. package/src/agent-cli-provider/schema.ts +115 -0
  216. package/src/agent-cli-provider/single-agent-runtime.ts +311 -0
  217. package/src/agent-cli-provider/types.ts +237 -0
  218. package/src/agent-wrapper.js +615 -0
  219. package/src/agents/git-pusher-template.js +705 -0
  220. package/src/attach/attach-client.js +438 -0
  221. package/src/attach/attach-server.js +543 -0
  222. package/src/attach/index.js +37 -0
  223. package/src/attach/protocol.js +220 -0
  224. package/src/attach/ring-buffer.js +121 -0
  225. package/src/attach/send-input.js +88 -0
  226. package/src/attach/socket-discovery.js +267 -0
  227. package/src/claude-task-runner.js +661 -0
  228. package/src/config-router.js +89 -0
  229. package/src/config-validator.js +2202 -0
  230. package/src/copy-worker.js +43 -0
  231. package/src/guidance-topics.js +10 -0
  232. package/src/input-helpers.js +65 -0
  233. package/src/isolation-manager.js +1734 -0
  234. package/src/issue-providers/README.md +305 -0
  235. package/src/issue-providers/azure-devops-provider.js +307 -0
  236. package/src/issue-providers/base-provider.js +232 -0
  237. package/src/issue-providers/github-provider.js +210 -0
  238. package/src/issue-providers/gitlab-provider.js +262 -0
  239. package/src/issue-providers/index.js +196 -0
  240. package/src/issue-providers/jira-provider.js +260 -0
  241. package/src/ledger.js +692 -0
  242. package/src/lib/gc.js +232 -0
  243. package/src/lib/safe-exec.js +88 -0
  244. package/src/logic-engine.js +201 -0
  245. package/src/message-buffer.js +81 -0
  246. package/src/message-bus-bridge.js +144 -0
  247. package/src/message-bus.js +256 -0
  248. package/src/name-generator.js +232 -0
  249. package/src/orchestrator.js +3924 -0
  250. package/src/preflight.js +712 -0
  251. package/src/process-metrics.js +608 -0
  252. package/src/providers/anthropic/index.js +3 -0
  253. package/src/providers/base-provider.js +355 -0
  254. package/src/providers/capabilities.js +60 -0
  255. package/src/providers/google/index.js +3 -0
  256. package/src/providers/index.js +293 -0
  257. package/src/providers/openai/index.js +3 -0
  258. package/src/providers/opencode/index.js +3 -0
  259. package/src/quality-gates.js +143 -0
  260. package/src/schemas/sub-cluster.js +208 -0
  261. package/src/state-snapshot.js +398 -0
  262. package/src/state-snapshotter.js +142 -0
  263. package/src/status-footer.js +1026 -0
  264. package/src/sub-cluster-wrapper.js +693 -0
  265. package/src/task-runner.js +30 -0
  266. package/src/template-resolver.js +425 -0
  267. package/src/template-validation/index.js +338 -0
  268. package/src/template-validation/simulate-consensus-gates.js +324 -0
  269. package/src/template-validation/simulate-random-topology.js +541 -0
  270. package/src/template-validation/simulate-two-stage-validation.js +270 -0
  271. package/src/worktree-claude-config.js +135 -0
  272. package/src/worktree-tooling-env.js +150 -0
  273. package/task-lib/attachable-watcher.js +381 -0
  274. package/task-lib/commands/clean.js +50 -0
  275. package/task-lib/commands/episodes.js +105 -0
  276. package/task-lib/commands/get-log-path.js +23 -0
  277. package/task-lib/commands/kill.js +32 -0
  278. package/task-lib/commands/list.js +105 -0
  279. package/task-lib/commands/logs.js +439 -0
  280. package/task-lib/commands/resume.js +42 -0
  281. package/task-lib/commands/run.js +57 -0
  282. package/task-lib/commands/schedule.js +105 -0
  283. package/task-lib/commands/scheduler-cmd.js +96 -0
  284. package/task-lib/commands/schedules.js +148 -0
  285. package/task-lib/commands/status.js +44 -0
  286. package/task-lib/commands/unschedule.js +16 -0
  287. package/task-lib/completion.js +9 -0
  288. package/task-lib/config.js +11 -0
  289. package/task-lib/name-generator.js +230 -0
  290. package/task-lib/package.json +3 -0
  291. package/task-lib/provider-helper-runtime.js +29 -0
  292. package/task-lib/runner.js +190 -0
  293. package/task-lib/scheduler.js +252 -0
  294. package/task-lib/store.js +529 -0
  295. package/task-lib/watcher.js +305 -0
@@ -0,0 +1,247 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { getString, isRecord, stringifyJson } from '../json';
5
+ import {
6
+ type BuildProviderCommandOptions,
7
+ type ClaudeCliFeatures,
8
+ type CommandSpec,
9
+ type ErrorClassification,
10
+ InvalidProviderModelError,
11
+ type LevelModelSpec,
12
+ type LevelOverrides,
13
+ type ModelCatalogEntry,
14
+ type ModelLevel,
15
+ type ProviderAdapter,
16
+ type ResolvedModelSpec,
17
+ type WarningMetadata,
18
+ } from '../types';
19
+ import {
20
+ classifyBaseProviderError,
21
+ commandSpec,
22
+ createParserState,
23
+ envRedactions,
24
+ optionFeatures,
25
+ resolveModelSpecWithConfig,
26
+ validateModelIdFromCatalog,
27
+ warning,
28
+ } from './common';
29
+ import { parseClaudeEvent } from './claude-parser';
30
+
31
+ const MODEL_CATALOG: Readonly<Record<string, ModelCatalogEntry>> = {
32
+ haiku: { rank: 1 },
33
+ sonnet: { rank: 2 },
34
+ opus: { rank: 3 },
35
+ };
36
+
37
+ const LEVEL_MAPPING: Readonly<Record<ModelLevel, LevelModelSpec>> = {
38
+ level1: { rank: 1, model: 'haiku' },
39
+ level2: { rank: 2, model: 'sonnet' },
40
+ level3: { rank: 3, model: 'opus' },
41
+ };
42
+
43
+ function detectCliFeatures(helpText?: string | null): ClaudeCliFeatures {
44
+ const help = helpText ?? '';
45
+ const unknown = !help;
46
+ return {
47
+ provider: 'claude',
48
+ supportsOutputFormat: unknown ? true : /--output-format/.test(help),
49
+ supportsStreamJson: unknown ? true : /stream-json/.test(help),
50
+ supportsJsonSchema: unknown ? true : /--json-schema/.test(help),
51
+ supportsAutoApprove: unknown ? true : /--dangerously-skip-permissions/.test(help),
52
+ supportsIncludePartials: unknown ? true : /--include-partial-messages/.test(help),
53
+ supportsVerbose: unknown ? true : /--verbose/.test(help),
54
+ supportsModel: unknown ? true : /--model/.test(help),
55
+ unknown,
56
+ };
57
+ }
58
+
59
+ function addOutputArgs(args: string[], options: BuildProviderCommandOptions): void {
60
+ const features = optionFeatures(options);
61
+ if (options.outputFormat && features.supportsOutputFormat !== false) {
62
+ args.push('--output-format', options.outputFormat);
63
+ }
64
+ if (options.outputFormat === 'stream-json') {
65
+ if (features.supportsVerbose !== false) args.push('--verbose');
66
+ if (features.supportsIncludePartials !== false) args.push('--include-partial-messages');
67
+ }
68
+ }
69
+
70
+ function addSchemaArgs(args: string[], options: BuildProviderCommandOptions): void {
71
+ const features = optionFeatures(options);
72
+ if (
73
+ options.jsonSchema &&
74
+ options.outputFormat === 'json' &&
75
+ features.supportsJsonSchema !== false
76
+ ) {
77
+ args.push(
78
+ '--json-schema',
79
+ typeof options.jsonSchema === 'string'
80
+ ? options.jsonSchema
81
+ : stringifyJson(options.jsonSchema)
82
+ );
83
+ }
84
+ }
85
+
86
+ function addModelArgs(args: string[], options: BuildProviderCommandOptions): void {
87
+ const features = optionFeatures(options);
88
+ if (options.modelSpec?.model && features.supportsModel !== false) {
89
+ args.push('--model', options.modelSpec.model);
90
+ }
91
+ }
92
+
93
+ function addAutoApproveArgs(args: string[], options: BuildProviderCommandOptions): void {
94
+ const features = optionFeatures(options);
95
+ if (options.autoApprove && features.supportsAutoApprove !== false) {
96
+ args.push('--dangerously-skip-permissions');
97
+ }
98
+ }
99
+
100
+ function addSessionArgs(args: string[], options: BuildProviderCommandOptions): void {
101
+ if (options.resumeSessionId) {
102
+ args.push('--resume', options.resumeSessionId);
103
+ return;
104
+ }
105
+ if (options.continueSession) {
106
+ args.push('--continue');
107
+ }
108
+ }
109
+
110
+ function readConfiguredClaudeCommand(): string {
111
+ if (process.env.ZEROSHOT_CLAUDE_COMMAND?.trim()) {
112
+ return process.env.ZEROSHOT_CLAUDE_COMMAND;
113
+ }
114
+
115
+ const settingsPath =
116
+ process.env.ZEROSHOT_SETTINGS_FILE || join(homedir(), '.zeroshot', 'settings.json');
117
+ if (!existsSync(settingsPath)) return 'claude';
118
+
119
+ try {
120
+ const settings: unknown = JSON.parse(readFileSync(settingsPath, 'utf8'));
121
+ const configured = isRecord(settings) ? getString(settings, 'claudeCommand') : null;
122
+ if (configured?.trim()) return configured;
123
+ } catch {
124
+ return 'claude';
125
+ }
126
+
127
+ return 'claude';
128
+ }
129
+
130
+ function resolveClaudeCommand(): { readonly command: string; readonly args: readonly string[] } {
131
+ const parts = readConfiguredClaudeCommand().trim().split(/\s+/);
132
+ return {
133
+ command: parts[0] ?? 'claude',
134
+ args: parts.slice(1),
135
+ };
136
+ }
137
+
138
+ function collectWarnings(options: BuildProviderCommandOptions): WarningMetadata[] {
139
+ const features = optionFeatures(options);
140
+ const warnings: WarningMetadata[] = [];
141
+ if (options.jsonSchema && options.outputFormat !== 'json' && !options.strictSchema) {
142
+ warnings.push(
143
+ warning(
144
+ 'claude',
145
+ 'claude-jsonschema-stream',
146
+ 'jsonSchema requested with stream output; schema enforcement will be post-validated.'
147
+ )
148
+ );
149
+ }
150
+ if (
151
+ options.jsonSchema &&
152
+ options.outputFormat === 'json' &&
153
+ features.supportsJsonSchema === false
154
+ ) {
155
+ warnings.push(
156
+ warning(
157
+ 'claude',
158
+ 'claude-jsonschema-flag',
159
+ 'Claude CLI does not support --json-schema; skipping schema flag.'
160
+ )
161
+ );
162
+ }
163
+ if (options.autoApprove && features.supportsAutoApprove === false) {
164
+ warnings.push(
165
+ warning(
166
+ 'claude',
167
+ 'claude-auto-approve',
168
+ 'Claude CLI does not support --dangerously-skip-permissions; continuing without auto-approve.'
169
+ )
170
+ );
171
+ }
172
+ return warnings;
173
+ }
174
+
175
+ function buildCommand(context: string, options: BuildProviderCommandOptions = {}): CommandSpec {
176
+ const { command, args: commandPrefix } = resolveClaudeCommand();
177
+ const args: string[] = [...commandPrefix, '--print', '--input-format', 'text'];
178
+ const authEnv = options.authEnv ?? {};
179
+
180
+ addOutputArgs(args, options);
181
+ addSchemaArgs(args, options);
182
+ addModelArgs(args, options);
183
+ addAutoApproveArgs(args, options);
184
+ addSessionArgs(args, options);
185
+
186
+ args.push(context);
187
+
188
+ return commandSpec({
189
+ binary: command,
190
+ args,
191
+ env: authEnv,
192
+ ...(options.cwd === undefined ? {} : { cwd: options.cwd }),
193
+ warnings: collectWarnings(options),
194
+ redactions: envRedactions(authEnv),
195
+ });
196
+ }
197
+
198
+ function resolveModelSpec(level: ModelLevel, overrides?: LevelOverrides): ResolvedModelSpec {
199
+ return resolveModelSpecWithConfig({
200
+ mapping: LEVEL_MAPPING,
201
+ defaultLevel: 'level2',
202
+ level,
203
+ overrides,
204
+ validateModelId,
205
+ });
206
+ }
207
+
208
+ function validateModelId(modelId: string | null | undefined): string | null | undefined {
209
+ try {
210
+ return validateModelIdFromCatalog('claude', MODEL_CATALOG, modelId);
211
+ } catch (error) {
212
+ if (modelId && (modelId === 'opus-4.6' || modelId === 'claude-opus-4-6')) {
213
+ throw new InvalidProviderModelError(
214
+ `Invalid model "${modelId}" for provider "claude". Use canonical model ids: haiku, sonnet, opus.`
215
+ );
216
+ }
217
+ throw error;
218
+ }
219
+ }
220
+
221
+ function classifyError(error: unknown): ErrorClassification {
222
+ return classifyBaseProviderError(
223
+ error,
224
+ [/no messages returned/i, /\boverloaded\b/i, /\brate[_ -]?limit\b/i],
225
+ [/invalid_request_error/i, /model_not_available/i]
226
+ );
227
+ }
228
+
229
+ export const claudeAdapter: ProviderAdapter = {
230
+ id: 'claude',
231
+ displayName: 'Claude',
232
+ binary: 'claude',
233
+ adapterVersion: '1',
234
+ credentialEnvKeys: ['ANTHROPIC_API_KEY', 'CLAUDE_API_KEY'],
235
+ modelCatalog: MODEL_CATALOG,
236
+ levelMapping: LEVEL_MAPPING,
237
+ defaultLevel: 'level2',
238
+ defaultMaxLevel: 'level3',
239
+ defaultMinLevel: 'level1',
240
+ detectCliFeatures,
241
+ buildCommand,
242
+ parseEvent: parseClaudeEvent,
243
+ createParserState: () => createParserState('claude'),
244
+ resolveModelSpec,
245
+ validateModelId,
246
+ classifyError,
247
+ };
@@ -0,0 +1,211 @@
1
+ import {
2
+ getNumber,
3
+ getOptionalString,
4
+ getOrStringFromKeys,
5
+ getRecord,
6
+ getString,
7
+ isRecord,
8
+ parseJson,
9
+ tryParseJson,
10
+ } from '../json';
11
+ import type { OutputEvent, ProviderParseResult } from '../types';
12
+
13
+ function safeJsonParse(value: string, fallback: unknown): unknown {
14
+ try {
15
+ return parseJson(value);
16
+ } catch {
17
+ return fallback;
18
+ }
19
+ }
20
+
21
+ function parseAssistantMessage(item: Record<string, unknown>): OutputEvent[] {
22
+ const rawContent = item.content;
23
+ const content = Array.isArray(rawContent) ? rawContent : [{ type: 'text', text: rawContent }];
24
+ const records = content.filter(isRecord);
25
+ const text = records
26
+ .filter((contentItem) => getString(contentItem, 'type') === 'text')
27
+ .map((contentItem) => getString(contentItem, 'text') ?? '')
28
+ .join('');
29
+ const thinking = records
30
+ .filter((contentItem) => {
31
+ const type = getString(contentItem, 'type');
32
+ return type === 'thinking' || type === 'reasoning';
33
+ })
34
+ .map((contentItem) => getString(contentItem, 'text') ?? '')
35
+ .join('');
36
+
37
+ const events: OutputEvent[] = [];
38
+ if (text) events.push({ type: 'text', text });
39
+ if (thinking) events.push({ type: 'thinking', text: thinking });
40
+ return events;
41
+ }
42
+
43
+ function parseFunctionCall(item: Record<string, unknown>): OutputEvent {
44
+ const argumentValue = item.arguments;
45
+ const input =
46
+ typeof argumentValue === 'string' ? safeJsonParse(argumentValue, {}) : (argumentValue ?? {});
47
+ return {
48
+ type: 'tool_call',
49
+ toolName: getOptionalString(item, 'name'),
50
+ toolId: getOrStringFromKeys(item, ['call_id', 'id', 'tool_call_id', 'tool_id']),
51
+ input,
52
+ };
53
+ }
54
+
55
+ function parseFunctionCallOutput(item: Record<string, unknown>): OutputEvent {
56
+ return {
57
+ type: 'tool_result',
58
+ toolId: getOrStringFromKeys(item, ['call_id', 'id', 'tool_call_id', 'tool_id']),
59
+ content: item.output ?? item.result ?? item.content ?? '',
60
+ isError: Boolean(item.error),
61
+ };
62
+ }
63
+
64
+ function commandFromItem(item: Record<string, unknown>): string | null {
65
+ const input = getRecord(item, 'input');
66
+ if (input !== null) {
67
+ return (
68
+ getString(item, 'command') ??
69
+ getString(item, 'cmd') ??
70
+ getString(input, 'command') ??
71
+ getString(input, 'cmd')
72
+ );
73
+ }
74
+ return getString(item, 'command') ?? getString(item, 'cmd');
75
+ }
76
+
77
+ function commandExecutionResultIsError(item: Record<string, unknown>): boolean {
78
+ const exitCode = getNumber(item, 'exit_code') ?? getNumber(item, 'exitCode');
79
+ if (exitCode !== null) return exitCode !== 0;
80
+ return Boolean(item.error);
81
+ }
82
+
83
+ function parseCommandExecutionItem(
84
+ item: Record<string, unknown>,
85
+ phase: 'started' | 'completed'
86
+ ): OutputEvent {
87
+ const command = commandFromItem(item);
88
+ const toolId = getOptionalString(item, 'id');
89
+
90
+ if (phase === 'started') {
91
+ return {
92
+ type: 'tool_call',
93
+ toolName: 'Bash',
94
+ toolId,
95
+ input: command ? { command } : {},
96
+ };
97
+ }
98
+
99
+ return {
100
+ type: 'tool_result',
101
+ toolId,
102
+ content: item.aggregated_output ?? item.output ?? item.result ?? '',
103
+ isError: commandExecutionResultIsError(item),
104
+ };
105
+ }
106
+
107
+ function parseReasoningItem(item: Record<string, unknown>): OutputEvent | null {
108
+ const text = getString(item, 'text') ?? getString(item, 'content') ?? '';
109
+ return text ? { type: 'thinking', text } : null;
110
+ }
111
+
112
+ function normalizeItemEvents(events: OutputEvent[]): ProviderParseResult {
113
+ if (events.length === 1) return events[0] ?? null;
114
+ if (events.length > 1) return events;
115
+ return null;
116
+ }
117
+
118
+ function phaseForEventType(eventType: string): 'started' | 'completed' | null {
119
+ if (eventType === 'item.started') return 'started';
120
+ if (eventType === 'item.completed') return 'completed';
121
+ return null;
122
+ }
123
+
124
+ function pushMaybe(events: OutputEvent[], event: OutputEvent | null): void {
125
+ if (event !== null) events.push(event);
126
+ }
127
+
128
+ function parseItem(item: Record<string, unknown>, eventType: string): ProviderParseResult {
129
+ const events: OutputEvent[] = [];
130
+ const itemType = getString(item, 'type');
131
+ const phase = phaseForEventType(eventType);
132
+
133
+ if (itemType === 'message' && getString(item, 'role') === 'assistant') {
134
+ events.push(...parseAssistantMessage(item));
135
+ }
136
+ if (itemType === 'agent_message') {
137
+ const text = getString(item, 'text');
138
+ if (text) events.push({ type: 'text', text });
139
+ }
140
+ if (itemType === 'reasoning') pushMaybe(events, parseReasoningItem(item));
141
+ if (itemType === 'command_execution' && phase !== null) {
142
+ events.push(parseCommandExecutionItem(item, phase));
143
+ }
144
+ if (itemType === 'function_call') events.push(parseFunctionCall(item));
145
+ if (itemType === 'function_call_output') events.push(parseFunctionCallOutput(item));
146
+
147
+ return normalizeItemEvents(events);
148
+ }
149
+
150
+ function parseErrorEvent(event: Record<string, unknown>): OutputEvent {
151
+ const error = getRecord(event, 'error');
152
+ return {
153
+ type: 'result',
154
+ success: false,
155
+ error: error
156
+ ? (getString(error, 'message') ?? getString(event, 'message') ?? event.error ?? 'Error')
157
+ : (getString(event, 'message') ?? event.error ?? 'Error'),
158
+ };
159
+ }
160
+
161
+ function parseTurnCompleted(event: Record<string, unknown>): OutputEvent {
162
+ const response = getRecord(event, 'response');
163
+ const usage = getRecord(event, 'usage') ?? (response ? getRecord(response, 'usage') : null) ?? {};
164
+ return {
165
+ type: 'result',
166
+ success: true,
167
+ inputTokens: getNumber(usage, 'input_tokens') ?? 0,
168
+ outputTokens: getNumber(usage, 'output_tokens') ?? 0,
169
+ };
170
+ }
171
+
172
+ function parseTurnFailed(event: Record<string, unknown>): OutputEvent {
173
+ const error = getRecord(event, 'error');
174
+ return {
175
+ type: 'result',
176
+ success: false,
177
+ error: error
178
+ ? (getString(error, 'message') ?? event.error ?? 'Turn failed')
179
+ : (event.error ?? 'Turn failed'),
180
+ };
181
+ }
182
+
183
+ function parseStartedItem(event: Record<string, unknown>): ProviderParseResult {
184
+ const item = getRecord(event, 'item');
185
+ if (item === null || getString(item, 'type') !== 'command_execution') return null;
186
+ return parseItem(item, 'item.started');
187
+ }
188
+
189
+ function parseCreatedOrCompletedItem(
190
+ event: Record<string, unknown>,
191
+ type: string
192
+ ): ProviderParseResult {
193
+ const item = getRecord(event, 'item');
194
+ return item === null ? null : parseItem(item, type);
195
+ }
196
+
197
+ export function parseCodexEvent(line: string): ProviderParseResult {
198
+ const event = tryParseJson(line);
199
+ if (!isRecord(event)) return null;
200
+
201
+ const type = getString(event, 'type');
202
+ if (type === 'error') return parseErrorEvent(event);
203
+ if (type === 'thread.started' || type === 'turn.started') return null;
204
+ if (type === 'item.started') return parseStartedItem(event);
205
+ if (type === 'item.created' || type === 'item.completed') {
206
+ return parseCreatedOrCompletedItem(event, type);
207
+ }
208
+ if (type === 'turn.completed') return parseTurnCompleted(event);
209
+ if (type === 'turn.failed') return parseTurnFailed(event);
210
+ return null;
211
+ }
@@ -0,0 +1,217 @@
1
+ import { appendJsonSchemaPrompt, writeStrictOutputSchemaFile } from '../schema';
2
+ import {
3
+ type BuildProviderCommandOptions,
4
+ type CodexCliFeatures,
5
+ type CommandSpec,
6
+ type ErrorClassification,
7
+ type LevelModelSpec,
8
+ type LevelOverrides,
9
+ type ModelCatalogEntry,
10
+ type ModelLevel,
11
+ type ProviderAdapter,
12
+ type ResolvedModelSpec,
13
+ type WarningMetadata,
14
+ } from '../types';
15
+ import {
16
+ classifyBaseProviderError,
17
+ commandSpec,
18
+ createParserState,
19
+ optionFeatures,
20
+ resolveModelSpecWithConfig,
21
+ unsupportedSessionControlWarnings,
22
+ validateModelIdFromCatalog,
23
+ warning,
24
+ } from './common';
25
+ import { parseCodexEvent } from './codex-parser';
26
+
27
+ const MODEL_CATALOG: Readonly<Record<string, ModelCatalogEntry>> = {
28
+ 'gpt-5.4': { rank: 2 },
29
+ 'gpt-5.5': { rank: 3 },
30
+ };
31
+
32
+ const LEVEL_MAPPING: Readonly<Record<ModelLevel, LevelModelSpec>> = {
33
+ level1: { rank: 1, model: 'gpt-5.4', reasoningEffort: 'medium' },
34
+ level2: { rank: 2, model: 'gpt-5.4', reasoningEffort: 'high' },
35
+ level3: { rank: 3, model: 'gpt-5.4', reasoningEffort: 'xhigh' },
36
+ };
37
+
38
+ function supports(help: string, pattern: RegExp): boolean {
39
+ return help ? pattern.test(help) : true;
40
+ }
41
+
42
+ function detectCliFeatures(helpText?: string | null): CodexCliFeatures {
43
+ const help = helpText ?? '';
44
+ const unknown = !help;
45
+ return {
46
+ provider: 'codex',
47
+ supportsJson: supports(help, /--json\b/),
48
+ supportsOutputSchema: supports(help, /--output-schema\b/),
49
+ supportsAutoApprove: supports(help, /--dangerously-bypass-approvals-and-sandbox\b/),
50
+ supportsCwd: supports(help, /\s-C\b/) || supports(help, /--cwd\b/),
51
+ supportsConfigOverride: supports(help, /--config\b/),
52
+ supportsModel: supports(help, /\s-m\b/) || supports(help, /--model\b/),
53
+ supportsSkipGitRepoCheck: supports(help, /--skip-git-repo-check\b/),
54
+ unknown,
55
+ };
56
+ }
57
+
58
+ function addOutputArgs(args: string[], options: BuildProviderCommandOptions): void {
59
+ const features = optionFeatures(options);
60
+ if (
61
+ (options.outputFormat === 'stream-json' || options.outputFormat === 'json') &&
62
+ features.supportsJson
63
+ ) {
64
+ args.push('--json');
65
+ }
66
+ }
67
+
68
+ function addModelArgs(args: string[], options: BuildProviderCommandOptions): void {
69
+ const features = optionFeatures(options);
70
+ if (options.modelSpec?.model) {
71
+ args.push('-m', options.modelSpec.model);
72
+ }
73
+ if (options.modelSpec?.reasoningEffort && features.supportsConfigOverride) {
74
+ args.push('--config', `model_reasoning_effort="${options.modelSpec.reasoningEffort}"`);
75
+ }
76
+ }
77
+
78
+ function addCwdArgs(args: string[], options: BuildProviderCommandOptions): void {
79
+ const features = optionFeatures(options);
80
+ if (options.cwd && features.supportsCwd) {
81
+ args.push('-C', options.cwd);
82
+ }
83
+ }
84
+
85
+ function addAutoApproveArgs(args: string[], options: BuildProviderCommandOptions): void {
86
+ const features = optionFeatures(options);
87
+ if (options.autoApprove && features.supportsAutoApprove) {
88
+ args.push('--dangerously-bypass-approvals-and-sandbox');
89
+ }
90
+ }
91
+
92
+ function addSkipGitArgs(args: string[], options: BuildProviderCommandOptions): void {
93
+ const features = optionFeatures(options);
94
+ if (features.supportsSkipGitRepoCheck !== false) {
95
+ args.push('--skip-git-repo-check');
96
+ }
97
+ }
98
+
99
+ function applySchemaArgs(
100
+ args: string[],
101
+ cleanup: string[],
102
+ context: string,
103
+ options: BuildProviderCommandOptions
104
+ ): string {
105
+ const features = optionFeatures(options);
106
+ if (options.jsonSchema && features.supportsOutputSchema) {
107
+ const schemaFile = writeStrictOutputSchemaFile(options.jsonSchema);
108
+ cleanup.push(schemaFile);
109
+ args.push('--output-schema', schemaFile);
110
+ return context;
111
+ }
112
+ return options.jsonSchema ? appendJsonSchemaPrompt(context, options.jsonSchema) : context;
113
+ }
114
+
115
+ function collectWarnings(options: BuildProviderCommandOptions): WarningMetadata[] {
116
+ const features = optionFeatures(options);
117
+ const warnings: WarningMetadata[] = unsupportedSessionControlWarnings('codex', options);
118
+ if (options.autoApprove && features.supportsAutoApprove === false) {
119
+ warnings.push(
120
+ warning(
121
+ 'codex',
122
+ 'codex-auto-approve',
123
+ 'Codex CLI does not support auto-approve; continuing without bypass flag.'
124
+ )
125
+ );
126
+ }
127
+ if (options.jsonSchema && features.supportsOutputSchema === false) {
128
+ warnings.push(
129
+ warning(
130
+ 'codex',
131
+ 'codex-jsonschema',
132
+ 'Codex CLI does not support --output-schema; skipping schema flag.'
133
+ )
134
+ );
135
+ }
136
+ if (options.modelSpec?.reasoningEffort && features.supportsConfigOverride === false) {
137
+ warnings.push(
138
+ warning(
139
+ 'codex',
140
+ 'codex-reasoning',
141
+ 'Codex CLI does not support --config overrides; skipping reasoningEffort.'
142
+ )
143
+ );
144
+ }
145
+ return warnings;
146
+ }
147
+
148
+ function buildCommand(context: string, options: BuildProviderCommandOptions = {}): CommandSpec {
149
+ const args: string[] = ['exec'];
150
+ const cleanup: string[] = [];
151
+
152
+ addOutputArgs(args, options);
153
+ addModelArgs(args, options);
154
+ addCwdArgs(args, options);
155
+ addAutoApproveArgs(args, options);
156
+ addSkipGitArgs(args, options);
157
+ const finalContext = applySchemaArgs(args, cleanup, context, options);
158
+
159
+ args.push(finalContext);
160
+
161
+ return commandSpec({
162
+ binary: 'codex',
163
+ args,
164
+ env: {},
165
+ ...(options.cwd === undefined ? {} : { cwd: options.cwd }),
166
+ cleanup,
167
+ cleanupMetadata: cleanup.map((schemaFile) => ({
168
+ kind: 'temp-file',
169
+ provider: 'codex',
170
+ path: schemaFile,
171
+ reason: 'output-schema',
172
+ })),
173
+ warnings: collectWarnings(options),
174
+ });
175
+ }
176
+
177
+ function resolveModelSpec(level: ModelLevel, overrides?: LevelOverrides): ResolvedModelSpec {
178
+ return resolveModelSpecWithConfig({
179
+ mapping: LEVEL_MAPPING,
180
+ defaultLevel: 'level2',
181
+ level,
182
+ overrides,
183
+ validateModelId,
184
+ });
185
+ }
186
+
187
+ function validateModelId(modelId: string | null | undefined): string | null | undefined {
188
+ return validateModelIdFromCatalog('codex', MODEL_CATALOG, modelId);
189
+ }
190
+
191
+ function classifyError(error: unknown): ErrorClassification {
192
+ return classifyBaseProviderError(
193
+ error,
194
+ [/rate_limit_exceeded/i, /\bserver_error\b/i, /\bservice_unavailable\b/i],
195
+ [/\binsufficient_quota\b/i, /\bmodel_not_found\b/i, /\bcontext_length_exceeded\b/i]
196
+ );
197
+ }
198
+
199
+ export const codexAdapter: ProviderAdapter = {
200
+ id: 'codex',
201
+ displayName: 'Codex',
202
+ binary: 'codex',
203
+ adapterVersion: '1',
204
+ credentialEnvKeys: ['OPENAI_API_KEY', 'CODEX_API_KEY'],
205
+ modelCatalog: MODEL_CATALOG,
206
+ levelMapping: LEVEL_MAPPING,
207
+ defaultLevel: 'level2',
208
+ defaultMaxLevel: 'level3',
209
+ defaultMinLevel: 'level1',
210
+ detectCliFeatures,
211
+ buildCommand,
212
+ parseEvent: parseCodexEvent,
213
+ createParserState: () => createParserState('codex'),
214
+ resolveModelSpec,
215
+ validateModelId,
216
+ classifyError,
217
+ };