@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,124 @@
1
+ import {
2
+ basePermanentErrorPatterns,
3
+ baseRetryableErrorPatterns,
4
+ classifyErrorWithPatterns,
5
+ } from '../errors';
6
+ import {
7
+ InvalidProviderModelError,
8
+ type BuildProviderCommandOptions,
9
+ type CliFeatureOverrides,
10
+ type CleanupMetadata,
11
+ type CommandSpec,
12
+ type ErrorClassification,
13
+ type LevelModelSpec,
14
+ type LevelOverrides,
15
+ type ModelCatalogEntry,
16
+ type ModelLevel,
17
+ type ProviderId,
18
+ type ProviderParserState,
19
+ type RedactionMetadata,
20
+ type ResolvedModelSpec,
21
+ type WarningMetadata,
22
+ } from '../types';
23
+
24
+ export function createParserState(provider: ProviderId): ProviderParserState {
25
+ return {
26
+ provider,
27
+ lastToolId: undefined,
28
+ };
29
+ }
30
+
31
+ export function commandSpec(input: {
32
+ readonly binary: string;
33
+ readonly args: readonly string[];
34
+ readonly env?: Readonly<Record<string, string>>;
35
+ readonly cwd?: string;
36
+ readonly cleanup?: readonly string[];
37
+ readonly cleanupMetadata?: readonly CleanupMetadata[];
38
+ readonly warnings?: readonly WarningMetadata[];
39
+ readonly redactions?: readonly RedactionMetadata[];
40
+ }): CommandSpec {
41
+ const spec = {
42
+ binary: input.binary,
43
+ args: input.args,
44
+ env: input.env ?? {},
45
+ cleanupMetadata: input.cleanupMetadata ?? [],
46
+ warnings: input.warnings ?? [],
47
+ redactions: input.redactions ?? [],
48
+ };
49
+ const specWithCwd = input.cwd === undefined ? spec : { ...spec, cwd: input.cwd };
50
+ if (input.cleanup === undefined) return specWithCwd;
51
+ return { ...specWithCwd, cleanup: input.cleanup };
52
+ }
53
+
54
+ export function warning(provider: ProviderId, code: string, message: string): WarningMetadata {
55
+ return { provider, code, message };
56
+ }
57
+
58
+ export function unsupportedSessionControlWarnings(
59
+ provider: ProviderId,
60
+ options: BuildProviderCommandOptions
61
+ ): WarningMetadata[] {
62
+ if (!options.resumeSessionId && !options.continueSession) return [];
63
+ return [
64
+ warning(
65
+ provider,
66
+ 'unsupported-session-control',
67
+ 'resume/continue is only supported for Claude CLI; ignoring.'
68
+ ),
69
+ ];
70
+ }
71
+
72
+ export function envRedactions(env: Readonly<Record<string, string>>): readonly RedactionMetadata[] {
73
+ return Object.keys(env).map((key) => ({ kind: 'env', key }));
74
+ }
75
+
76
+ interface ModelResolutionConfig {
77
+ readonly mapping: Readonly<Record<ModelLevel, LevelModelSpec>>;
78
+ readonly defaultLevel: ModelLevel;
79
+ readonly level: ModelLevel;
80
+ readonly overrides: LevelOverrides | undefined;
81
+ readonly validateModelId: (modelId: string | null | undefined) => string | null | undefined;
82
+ }
83
+
84
+ export function resolveModelSpecWithConfig(config: ModelResolutionConfig): ResolvedModelSpec {
85
+ const base = config.mapping[config.level] ?? config.mapping[config.defaultLevel];
86
+ const override = config.overrides?.[config.level];
87
+ const selectedModel = override?.model || base.model;
88
+ const validatedModel = config.validateModelId(selectedModel);
89
+ return {
90
+ level: config.level,
91
+ model: validatedModel ?? null,
92
+ reasoningEffort: override?.reasoningEffort || base.reasoningEffort,
93
+ };
94
+ }
95
+
96
+ export function validateModelIdFromCatalog(
97
+ provider: ProviderId,
98
+ catalog: Readonly<Record<string, ModelCatalogEntry>>,
99
+ modelId: string | null | undefined
100
+ ): string | null | undefined {
101
+ if (!modelId) return modelId;
102
+ if (catalog[modelId] !== undefined) return modelId;
103
+ throw new InvalidProviderModelError(
104
+ `Invalid model "${modelId}" for provider "${provider}". Use a model listed in provider settings/catalog.`
105
+ );
106
+ }
107
+
108
+ export function classifyBaseProviderError(
109
+ error: unknown,
110
+ retryablePatterns: readonly RegExp[],
111
+ permanentPatterns: readonly RegExp[]
112
+ ): ErrorClassification {
113
+ return classifyErrorWithPatterns(
114
+ error,
115
+ [...baseRetryableErrorPatterns(), ...retryablePatterns],
116
+ [...basePermanentErrorPatterns(), ...permanentPatterns]
117
+ );
118
+ }
119
+
120
+ export function optionFeatures(
121
+ options: BuildProviderCommandOptions | undefined
122
+ ): CliFeatureOverrides {
123
+ return options?.cliFeatures ?? {};
124
+ }
@@ -0,0 +1,243 @@
1
+ import { appendJsonSchemaPrompt } from '../schema';
2
+ import {
3
+ getOrStringFromKeys,
4
+ getOrStringFromKeysWithFallback,
5
+ getString,
6
+ isRecord,
7
+ tryParseJson,
8
+ } from '../json';
9
+ import {
10
+ type BuildProviderCommandOptions,
11
+ type CommandSpec,
12
+ type ErrorClassification,
13
+ type GeminiCliFeatures,
14
+ type LevelModelSpec,
15
+ type LevelOverrides,
16
+ type ModelCatalogEntry,
17
+ type ModelLevel,
18
+ type OutputEvent,
19
+ type ProviderAdapter,
20
+ type ProviderParserState,
21
+ type ResolvedModelSpec,
22
+ type WarningMetadata,
23
+ } from '../types';
24
+ import {
25
+ classifyBaseProviderError,
26
+ commandSpec,
27
+ createParserState,
28
+ optionFeatures,
29
+ resolveModelSpecWithConfig,
30
+ unsupportedSessionControlWarnings,
31
+ validateModelIdFromCatalog,
32
+ warning,
33
+ } from './common';
34
+
35
+ const MODEL_CATALOG: Readonly<Record<string, ModelCatalogEntry>> = {
36
+ 'gemini-2.5-pro': { rank: 3 },
37
+ 'gemini-2.0-flash': { rank: 1 },
38
+ };
39
+
40
+ const LEVEL_MAPPING: Readonly<Record<ModelLevel, LevelModelSpec>> = {
41
+ level1: { rank: 1, model: null },
42
+ level2: { rank: 2, model: null },
43
+ level3: { rank: 3, model: null },
44
+ };
45
+
46
+ function detectCliFeatures(helpText?: string | null): GeminiCliFeatures {
47
+ const help = helpText ?? '';
48
+ const unknown = !help;
49
+ return {
50
+ provider: 'gemini',
51
+ supportsStreamJson: unknown ? true : /--output-format\b/.test(help),
52
+ supportsAutoApprove: unknown ? true : /--yolo\b/.test(help),
53
+ supportsCwd: unknown ? true : /--cwd\b/.test(help),
54
+ supportsModel: unknown ? true : /\s-m\b/.test(help) || /--model\b/.test(help),
55
+ unknown,
56
+ };
57
+ }
58
+
59
+ function addGeminiOptionalArgs(args: string[], options: BuildProviderCommandOptions): void {
60
+ const features = optionFeatures(options);
61
+ if (
62
+ (options.outputFormat === 'stream-json' || options.outputFormat === 'json') &&
63
+ features.supportsStreamJson
64
+ ) {
65
+ args.push('--output-format', 'stream-json');
66
+ }
67
+
68
+ if (options.modelSpec?.model) {
69
+ args.push('-m', options.modelSpec.model);
70
+ }
71
+
72
+ if (options.cwd && features.supportsCwd) {
73
+ args.push('--cwd', options.cwd);
74
+ }
75
+
76
+ if (options.autoApprove && features.supportsAutoApprove) {
77
+ args.push('--yolo');
78
+ }
79
+ }
80
+
81
+ function collectGeminiWarnings(options: BuildProviderCommandOptions): WarningMetadata[] {
82
+ const features = optionFeatures(options);
83
+ const warnings: WarningMetadata[] = unsupportedSessionControlWarnings('gemini', options);
84
+ if (options.autoApprove && features.supportsAutoApprove === false) {
85
+ warnings.push(
86
+ warning(
87
+ 'gemini',
88
+ 'gemini-auto-approve',
89
+ 'Gemini CLI does not support --yolo; continuing without auto-approve.'
90
+ )
91
+ );
92
+ }
93
+ return warnings;
94
+ }
95
+
96
+ function buildCommand(context: string, options: BuildProviderCommandOptions = {}): CommandSpec {
97
+ const finalContext = options.jsonSchema
98
+ ? appendJsonSchemaPrompt(context, options.jsonSchema)
99
+ : context;
100
+ const args: string[] = ['-p', finalContext];
101
+ addGeminiOptionalArgs(args, options);
102
+
103
+ return commandSpec({
104
+ binary: 'gemini',
105
+ args,
106
+ env: {},
107
+ ...(options.cwd === undefined ? {} : { cwd: options.cwd }),
108
+ warnings: collectGeminiWarnings(options),
109
+ });
110
+ }
111
+
112
+ function normalizeMessageContent(content: unknown): string {
113
+ if (typeof content === 'string') return content;
114
+ if (Array.isArray(content)) {
115
+ return content
116
+ .map((item) => {
117
+ if (typeof item === 'string') return item;
118
+ if (isRecord(item)) return getString(item, 'text') ?? '';
119
+ return '';
120
+ })
121
+ .join('');
122
+ }
123
+ if (isRecord(content)) return getString(content, 'text') ?? '';
124
+ return '';
125
+ }
126
+
127
+ function parseMessageEvent(event: Record<string, unknown>): OutputEvent | null {
128
+ if (getString(event, 'role') !== 'assistant') return null;
129
+ const text = normalizeMessageContent(event.content);
130
+ return text ? { type: 'text', text } : null;
131
+ }
132
+
133
+ function parseToolUseEvent(
134
+ event: Record<string, unknown>,
135
+ state: ProviderParserState
136
+ ): OutputEvent {
137
+ const toolId = getOrStringFromKeysWithFallback(
138
+ event,
139
+ ['tool_call_id', 'tool_id', 'id'],
140
+ state.lastToolId
141
+ );
142
+ state.lastToolId = toolId;
143
+ return {
144
+ type: 'tool_call',
145
+ toolName: getOrStringFromKeys(event, ['tool_name', 'name']),
146
+ toolId,
147
+ input: event.parameters ?? event.input ?? {},
148
+ };
149
+ }
150
+
151
+ function parseToolResultEvent(
152
+ event: Record<string, unknown>,
153
+ state: ProviderParserState
154
+ ): OutputEvent {
155
+ const toolId = getOrStringFromKeysWithFallback(
156
+ event,
157
+ ['tool_call_id', 'tool_id', 'id'],
158
+ state.lastToolId
159
+ );
160
+ return {
161
+ type: 'tool_result',
162
+ toolId,
163
+ content: event.output ?? event.content ?? '',
164
+ isError: event.success === false,
165
+ };
166
+ }
167
+
168
+ function parseResultEvent(event: Record<string, unknown>): OutputEvent {
169
+ return {
170
+ type: 'result',
171
+ success: event.success !== false,
172
+ result: event.result || '',
173
+ error: event.success === false ? (getString(event, 'error') ?? 'Result failed') : null,
174
+ };
175
+ }
176
+
177
+ function parseEvent(line: string, state: ProviderParserState): OutputEvent | null {
178
+ const event = tryParseJson(line);
179
+ if (!isRecord(event)) return null;
180
+
181
+ switch (getString(event, 'type')) {
182
+ case 'init':
183
+ return null;
184
+ case 'message':
185
+ return parseMessageEvent(event);
186
+ case 'tool_use':
187
+ return parseToolUseEvent(event, state);
188
+ case 'tool_result':
189
+ return parseToolResultEvent(event, state);
190
+ case 'result':
191
+ return parseResultEvent(event);
192
+ default:
193
+ return null;
194
+ }
195
+ }
196
+
197
+ function resolveModelSpec(level: ModelLevel, overrides?: LevelOverrides): ResolvedModelSpec {
198
+ return resolveModelSpecWithConfig({
199
+ mapping: LEVEL_MAPPING,
200
+ defaultLevel: 'level2',
201
+ level,
202
+ overrides,
203
+ validateModelId,
204
+ });
205
+ }
206
+
207
+ function validateModelId(modelId: string | null | undefined): string | null | undefined {
208
+ return validateModelIdFromCatalog('gemini', MODEL_CATALOG, modelId);
209
+ }
210
+
211
+ function classifyError(error: unknown): ErrorClassification {
212
+ return classifyBaseProviderError(
213
+ error,
214
+ [
215
+ /\bRESOURCE_EXHAUSTED\b/i,
216
+ /\bUNAVAILABLE\b/i,
217
+ /\bDEADLINE_EXCEEDED\b/i,
218
+ /No capacity available/i,
219
+ /quota.?exceeded/i,
220
+ ],
221
+ [/\bINVALID_ARGUMENT\b/i, /\bPERMISSION_DENIED\b/i, /\bNOT_FOUND\b/i]
222
+ );
223
+ }
224
+
225
+ export const geminiAdapter: ProviderAdapter = {
226
+ id: 'gemini',
227
+ displayName: 'Gemini',
228
+ binary: 'gemini',
229
+ adapterVersion: '1',
230
+ credentialEnvKeys: ['GEMINI_API_KEY', 'GOOGLE_API_KEY'],
231
+ modelCatalog: MODEL_CATALOG,
232
+ levelMapping: LEVEL_MAPPING,
233
+ defaultLevel: 'level2',
234
+ defaultMaxLevel: 'level3',
235
+ defaultMinLevel: 'level1',
236
+ detectCliFeatures,
237
+ buildCommand,
238
+ parseEvent,
239
+ createParserState: () => createParserState('gemini'),
240
+ resolveModelSpec,
241
+ validateModelId,
242
+ classifyError,
243
+ };
@@ -0,0 +1,126 @@
1
+ import { stripTimestampPrefix } from '../log-prefix';
2
+ import type {
3
+ BuildProviderCommandOptions,
4
+ CommandSpec,
5
+ ErrorClassification,
6
+ KnownProviderName,
7
+ LevelOverrides,
8
+ ModelLevel,
9
+ OutputEvent,
10
+ ProviderAdapter,
11
+ ProviderId,
12
+ ResolvedModelSpec,
13
+ } from '../types';
14
+ import { claudeAdapter } from './claude';
15
+ export {
16
+ NO_MESSAGES_RETURNED,
17
+ STREAMING_MODE_ERROR,
18
+ detectProviderFatalError,
19
+ detectProviderStreamingModeError,
20
+ recoverProviderStructuredOutput,
21
+ supportsProviderStructuredOutputRecovery,
22
+ type StreamingModeError,
23
+ type StructuredOutputRecovery,
24
+ } from './claude-recovery';
25
+ import { codexAdapter } from './codex';
26
+ import { geminiAdapter } from './gemini';
27
+ import { opencodeAdapter } from './opencode';
28
+
29
+ const ADAPTERS: Readonly<Record<ProviderId, ProviderAdapter>> = {
30
+ claude: claudeAdapter,
31
+ codex: codexAdapter,
32
+ gemini: geminiAdapter,
33
+ opencode: opencodeAdapter,
34
+ };
35
+
36
+ const PROVIDER_IDS: readonly ProviderId[] = ['claude', 'codex', 'gemini', 'opencode'];
37
+
38
+ function isOutputEventArray(
39
+ event: OutputEvent | readonly OutputEvent[]
40
+ ): event is readonly OutputEvent[] {
41
+ return Array.isArray(event);
42
+ }
43
+
44
+ function normalizeProviderName(name: string): ProviderId | string {
45
+ const normalized = name.toLowerCase();
46
+ switch (normalized) {
47
+ case 'anthropic':
48
+ case 'claude':
49
+ return 'claude';
50
+ case 'openai':
51
+ case 'codex':
52
+ return 'codex';
53
+ case 'google':
54
+ case 'gemini':
55
+ return 'gemini';
56
+ case 'opencode':
57
+ return 'opencode';
58
+ default:
59
+ return name;
60
+ }
61
+ }
62
+
63
+ function adapterForProviderId(provider: ProviderId): ProviderAdapter {
64
+ return ADAPTERS[provider];
65
+ }
66
+
67
+ function isProviderId(name: string): name is ProviderId {
68
+ return name === 'claude' || name === 'codex' || name === 'gemini' || name === 'opencode';
69
+ }
70
+
71
+ export function getProviderAdapter(name: KnownProviderName | string): ProviderAdapter {
72
+ const normalized = normalizeProviderName(name || '');
73
+ if (isProviderId(normalized)) return adapterForProviderId(normalized);
74
+ throw new Error(`Unknown provider: ${name}. Valid: ${PROVIDER_IDS.join(', ')}`);
75
+ }
76
+
77
+ export function listProviderAdapters(): readonly ProviderId[] {
78
+ return PROVIDER_IDS;
79
+ }
80
+
81
+ export function buildProviderCommand(
82
+ providerName: KnownProviderName | string,
83
+ context: string,
84
+ options?: BuildProviderCommandOptions
85
+ ): CommandSpec {
86
+ return getProviderAdapter(providerName).buildCommand(context, options);
87
+ }
88
+
89
+ export function parseProviderChunk(
90
+ providerName: KnownProviderName | string,
91
+ chunk: string
92
+ ): readonly OutputEvent[] {
93
+ const adapter = getProviderAdapter(providerName || 'claude');
94
+ const state = adapter.createParserState();
95
+ const events: OutputEvent[] = [];
96
+ const lines = chunk.split('\n');
97
+
98
+ for (const line of lines) {
99
+ const content = stripTimestampPrefix(line);
100
+ if (!content) continue;
101
+ const event = adapter.parseEvent(content, state);
102
+ if (!event) continue;
103
+ if (isOutputEventArray(event)) {
104
+ events.push(...event);
105
+ } else {
106
+ events.push(event);
107
+ }
108
+ }
109
+
110
+ return events;
111
+ }
112
+
113
+ export function resolveModelSpec(
114
+ providerName: KnownProviderName | string,
115
+ level: ModelLevel,
116
+ overrides?: LevelOverrides
117
+ ): ResolvedModelSpec {
118
+ return getProviderAdapter(providerName).resolveModelSpec(level, overrides);
119
+ }
120
+
121
+ export function classifyProviderError(
122
+ providerName: KnownProviderName | string,
123
+ error: unknown
124
+ ): ErrorClassification {
125
+ return getProviderAdapter(providerName).classifyError(error);
126
+ }