@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,615 @@
1
+ // @ts-nocheck
2
+ /**
3
+ * AgentWrapper - Manages agent lifecycle and claude-zeroshots execution
4
+ *
5
+ * Provides:
6
+ * - Agent state machine (idle -> evaluating -> building context -> executing -> idle)
7
+ * - Trigger evaluation via LogicEngine
8
+ * - Context building from ledger
9
+ * - claude-zeroshots spawning and monitoring
10
+ * - Hook execution (onStart, onComplete, onError)
11
+ */
12
+
13
+ const LogicEngine = require('./logic-engine');
14
+ const { validateAgentConfig } = require('./agent/agent-config');
15
+ const { loadSettings, validateModelAgainstMax, VALID_MODELS } = require('../lib/settings');
16
+ const { normalizeProviderName } = require('../lib/provider-names');
17
+ const { getProvider } = require('./providers');
18
+ const { buildContext } = require('./agent/agent-context-builder');
19
+ const { collectQueuedGuidance } = require('./agent/guidance-queue');
20
+ const { findMatchingTrigger, evaluateTrigger } = require('./agent/agent-trigger-evaluator');
21
+ const { executeHook } = require('./agent/agent-hook-executor');
22
+ const { injectInput: injectAgentInput } = require('./agent/agent-input-injector');
23
+ const {
24
+ spawnClaudeTask,
25
+ followClaudeTaskLogs,
26
+ waitForTaskReady,
27
+ spawnClaudeTaskIsolated,
28
+ getClaudeTasksPath,
29
+ parseResultOutput,
30
+ killTask,
31
+ } = require('./agent/agent-task-executor');
32
+ const {
33
+ start: lifecycleStart,
34
+ stop: lifecycleStop,
35
+ handleMessage: lifecycleHandleMessage,
36
+ executeTriggerAction: lifecycleExecuteTriggerAction,
37
+ executeTask: lifecycleExecuteTask,
38
+ startLivenessCheck: lifecycleStartLivenessCheck,
39
+ stopLivenessCheck: lifecycleStopLivenessCheck,
40
+ } = require('./agent/agent-lifecycle');
41
+
42
+ class AgentWrapper {
43
+ /**
44
+ * @param {any} config - Agent configuration
45
+ * @param {any} messageBus - Message bus instance
46
+ * @param {any} cluster - Cluster instance
47
+ * @param {any} options - Options
48
+ */
49
+ constructor(config, messageBus, cluster, options = {}) {
50
+ // Validate and normalize configuration
51
+ const normalizedConfig = validateAgentConfig(config, options);
52
+
53
+ this.id = normalizedConfig.id;
54
+ this.role = normalizedConfig.role;
55
+ this.modelConfig = normalizedConfig.modelConfig;
56
+ this.config = normalizedConfig;
57
+ this.messageBus = messageBus;
58
+ this.cluster = cluster;
59
+ this.logicEngine = new LogicEngine(messageBus, cluster);
60
+
61
+ this.state = 'idle';
62
+ this.iteration = 0;
63
+ this.maxIterations = normalizedConfig.maxIterations;
64
+ this.timeout = normalizedConfig.timeout;
65
+ /** @type {any} */
66
+ this.currentTask = null;
67
+ /** @type {string | null} */
68
+ this.currentTaskId = null; // Track spawned task ID for resume capability
69
+ /** @type {number | null} */
70
+ this.processPid = null; // Track process PID for resource monitoring
71
+ this.running = false;
72
+ /** @type {Function | null} */
73
+ this.unsubscribe = null;
74
+ /** @type {number | null} */
75
+ this.lastTaskEndTime = null; // Track when last task completed (for context filtering)
76
+ /** @type {number | null} */
77
+ this.lastAgentStartTime = null; // Track when agent last began executing (for context filtering)
78
+ /** @type {number | null} */
79
+ this.lastGuidanceAppliedAt = null; // Track last queued guidance applied to prompt
80
+
81
+ // LIVENESS DETECTION - Track output freshness to detect stuck agents
82
+ /** @type {number | null} */
83
+ this.lastOutputTime = null; // Timestamp of last output received
84
+ /** @type {NodeJS.Timeout | null} */
85
+ this.livenessCheckInterval = null; // Interval for health checks
86
+ this.staleDuration = normalizedConfig.staleDuration;
87
+ this.enableLivenessCheck = normalizedConfig.enableLivenessCheck;
88
+
89
+ // MOCK SUPPORT - Inject mock spawn function for testing
90
+ // When set, _spawnClaudeTask uses this instead of real ct CLI
91
+ // Priority: options.mockSpawnFn (legacy) > options.taskRunner (new DI pattern)
92
+ if (options.mockSpawnFn) {
93
+ this.mockSpawnFn = options.mockSpawnFn;
94
+ } else if (options.taskRunner) {
95
+ // TaskRunner DI - create mockSpawnFn wrapper
96
+ const taskRunner = options.taskRunner;
97
+ this.mockSpawnFn = (args, { context }) => {
98
+ const spec = this._resolveModelSpec();
99
+ return taskRunner.run(context, {
100
+ agentId: this.id,
101
+ model: this._selectModel(),
102
+ modelSpec: spec,
103
+ provider: this._resolveProvider(),
104
+ cwd: this.config.cwd || process.cwd(),
105
+ worktreePath: this.worktree?.path || null,
106
+ });
107
+ };
108
+ } else {
109
+ this.mockSpawnFn = null;
110
+ }
111
+
112
+ this.testMode = options.testMode || false;
113
+ this.quiet = options.quiet || false;
114
+
115
+ // ISOLATION SUPPORT - Run tasks inside Docker container
116
+ this.isolation = options.isolation || null;
117
+
118
+ // WORKTREE SUPPORT - Run tasks in git worktree (lightweight isolation without Docker)
119
+ this.worktree = options.worktree || null;
120
+ }
121
+
122
+ /**
123
+ * Log message (respects quiet mode)
124
+ * @private
125
+ */
126
+ _log(...args) {
127
+ if (!this.quiet) {
128
+ console.log(...args);
129
+ }
130
+ }
131
+
132
+ _resolveProvider() {
133
+ const settings = loadSettings();
134
+ const clusterConfig = this.cluster?.config || {};
135
+
136
+ const resolved =
137
+ clusterConfig.forceProvider ||
138
+ this.config.provider ||
139
+ clusterConfig.defaultProvider ||
140
+ settings.defaultProvider ||
141
+ 'claude';
142
+
143
+ return normalizeProviderName(resolved) || 'claude';
144
+ }
145
+
146
+ _resolveModelSpec() {
147
+ const settings = loadSettings();
148
+ const providerName = this._resolveProvider();
149
+ const provider = getProvider(providerName);
150
+ const clusterConfig = this.cluster?.config || {};
151
+ const providerSettings = settings.providerSettings?.[providerName] || {};
152
+ const levelOverrides = providerSettings.levelOverrides || {};
153
+ const minLevel = providerSettings.minLevel;
154
+ const maxLevel = providerSettings.maxLevel;
155
+ const forcedLevel =
156
+ clusterConfig.forceProvider === providerName ? clusterConfig.forceLevel : null;
157
+
158
+ const applyReasoningOverride = (spec, override) => {
159
+ if (!override) return spec;
160
+ return { ...spec, reasoningEffort: override };
161
+ };
162
+
163
+ if (this.modelConfig.type === 'rules') {
164
+ for (const rule of this.modelConfig.rules) {
165
+ if (this._matchesIterationRange(rule.iterations)) {
166
+ if (rule.model) {
167
+ provider.validateModelId(rule.model);
168
+ return {
169
+ level: 'custom',
170
+ model: rule.model,
171
+ reasoningEffort: rule.reasoningEffort || this.config.reasoningEffort,
172
+ };
173
+ }
174
+ if (rule.modelLevel) {
175
+ const level = provider.validateLevel(rule.modelLevel, minLevel, maxLevel);
176
+ const spec = provider.resolveModelSpec(level, levelOverrides);
177
+ return applyReasoningOverride(
178
+ { ...spec, level },
179
+ rule.reasoningEffort || this.config.reasoningEffort
180
+ );
181
+ }
182
+ }
183
+ }
184
+
185
+ throw new Error(
186
+ `Agent ${this.id}: No model rule matched iteration ${this.iteration}. ` +
187
+ `Add a catch-all rule like { "iterations": "all", "modelLevel": "level2" }`
188
+ );
189
+ }
190
+
191
+ if (this.modelConfig.model) {
192
+ provider.validateModelId(this.modelConfig.model);
193
+ return {
194
+ level: 'custom',
195
+ model: this.modelConfig.model,
196
+ reasoningEffort: this.config.reasoningEffort,
197
+ };
198
+ }
199
+
200
+ if (forcedLevel) {
201
+ const level = provider.validateLevel(forcedLevel, minLevel, maxLevel);
202
+ const spec = provider.resolveModelSpec(level, levelOverrides);
203
+ return applyReasoningOverride({ ...spec, level }, this.config.reasoningEffort);
204
+ }
205
+
206
+ if (this.modelConfig.modelLevel) {
207
+ const level = provider.validateLevel(this.modelConfig.modelLevel, minLevel, maxLevel);
208
+ const spec = provider.resolveModelSpec(level, levelOverrides);
209
+ return applyReasoningOverride({ ...spec, level }, this.config.reasoningEffort);
210
+ }
211
+
212
+ const defaultLevel = providerSettings.defaultLevel || provider.getDefaultLevel();
213
+ const level = provider.validateLevel(defaultLevel, minLevel, maxLevel);
214
+ const spec = provider.resolveModelSpec(level, levelOverrides);
215
+ return applyReasoningOverride({ ...spec, level }, this.config.reasoningEffort);
216
+ }
217
+
218
+ /**
219
+ * Publish a message to the message bus, always including sender_model
220
+ * @private
221
+ */
222
+ _publish(message) {
223
+ this.messageBus.publish({
224
+ ...message,
225
+ cluster_id: this.cluster.id,
226
+ sender: this.id,
227
+ sender_model: this._selectModel(),
228
+ sender_provider: this._resolveProvider(),
229
+ });
230
+ }
231
+
232
+ /**
233
+ * Publish agent lifecycle event to message bus (visible in zeroshot logs)
234
+ * @private
235
+ */
236
+ _publishLifecycle(event, details = {}) {
237
+ this._publish({
238
+ topic: 'AGENT_LIFECYCLE',
239
+ receiver: 'system',
240
+ content: {
241
+ text: `${this.id}: ${event}`,
242
+ data: {
243
+ event,
244
+ agent: this.id,
245
+ role: this.role,
246
+ state: this.state,
247
+ model: this._selectModel(),
248
+ provider: this._resolveProvider(),
249
+ ...details,
250
+ },
251
+ },
252
+ });
253
+ }
254
+
255
+ /**
256
+ * Select model based on current iteration and agent config
257
+ * Enforces legacy maxModel/minModel aliases for Claude compatibility
258
+ * @returns {string|null}
259
+ * @private
260
+ */
261
+ _selectModel() {
262
+ const spec = this._resolveModelSpec();
263
+ const settings = loadSettings();
264
+ const maxModel = settings.maxModel;
265
+ const minModel = settings.minModel || null;
266
+
267
+ if (spec.model && maxModel && VALID_MODELS.includes(spec.model)) {
268
+ return validateModelAgainstMax(spec.model, maxModel, minModel);
269
+ }
270
+
271
+ return spec.model || null;
272
+ }
273
+
274
+ /**
275
+ * Check if current iteration matches the range pattern
276
+ * @param {string} pattern - e.g., "1", "1-3", "5+", "all"
277
+ * @returns {boolean}
278
+ * @private
279
+ */
280
+ _matchesIterationRange(pattern) {
281
+ if (pattern === 'all') return true;
282
+
283
+ const current = this.iteration;
284
+
285
+ // Exact match: "3"
286
+ if (/^\d+$/.test(pattern)) {
287
+ return current === parseInt(pattern);
288
+ }
289
+
290
+ // Range: "1-3"
291
+ const rangeMatch = pattern.match(/^(\d+)-(\d+)$/);
292
+ if (rangeMatch) {
293
+ const [, start, end] = rangeMatch;
294
+ return current >= parseInt(start) && current <= parseInt(end);
295
+ }
296
+
297
+ // Open-ended: "5+"
298
+ const openMatch = pattern.match(/^(\d+)\+$/);
299
+ if (openMatch) {
300
+ const [, start] = openMatch;
301
+ return current >= parseInt(start);
302
+ }
303
+
304
+ throw new Error(
305
+ `Agent ${this.id}: Invalid iteration pattern '${pattern}'. ` +
306
+ `Valid formats: "1", "1-3", "5+", "all"`
307
+ );
308
+ }
309
+
310
+ /**
311
+ * Select prompt based on current iteration and agent config
312
+ * @returns {string|null} System prompt string, or null if no prompt configured
313
+ * @private
314
+ */
315
+ _selectPrompt() {
316
+ const promptConfig = this.config.promptConfig;
317
+
318
+ // No prompt configured
319
+ if (!promptConfig) {
320
+ return null;
321
+ }
322
+
323
+ // Backward compatibility: static prompt
324
+ if (promptConfig.type === 'static') {
325
+ return promptConfig.system;
326
+ }
327
+
328
+ // Dynamic rules: evaluate based on iteration
329
+ for (const rule of promptConfig.rules) {
330
+ if (this._matchesIterationRange(rule.match)) {
331
+ return rule.system;
332
+ }
333
+ }
334
+
335
+ // No match: fail fast
336
+ throw new Error(
337
+ `Agent ${this.id}: No prompt rule matched iteration ${this.iteration}. ` +
338
+ `Add a catch-all rule like { "match": "all", "system": "..." }`
339
+ );
340
+ }
341
+
342
+ /**
343
+ * Start the agent (begin listening for triggers)
344
+ */
345
+ start() {
346
+ return lifecycleStart(this);
347
+ }
348
+
349
+ /**
350
+ * Stop the agent
351
+ */
352
+ stop() {
353
+ return lifecycleStop(this);
354
+ }
355
+
356
+ /**
357
+ * Handle incoming message
358
+ * @private
359
+ */
360
+ _handleMessage(message) {
361
+ return lifecycleHandleMessage(this, message);
362
+ }
363
+
364
+ /**
365
+ * Find trigger matching the message topic
366
+ * @private
367
+ */
368
+ _findMatchingTrigger(message) {
369
+ return findMatchingTrigger({
370
+ triggers: this.config.triggers,
371
+ message,
372
+ });
373
+ }
374
+
375
+ /**
376
+ * Evaluate trigger logic
377
+ * @private
378
+ */
379
+ _evaluateTrigger(trigger, message) {
380
+ const agent = {
381
+ id: this.id,
382
+ role: this.role,
383
+ iteration: this.iteration,
384
+ cluster_id: this.cluster.id,
385
+ requiredQualityGates: this.config?.requiredQualityGates || [],
386
+ };
387
+
388
+ return evaluateTrigger({
389
+ trigger,
390
+ message,
391
+ agent,
392
+ logicEngine: this.logicEngine,
393
+ });
394
+ }
395
+
396
+ /**
397
+ * Execute trigger action
398
+ * @private
399
+ */
400
+ _executeTriggerAction(trigger, message) {
401
+ return lifecycleExecuteTriggerAction(this, trigger, message);
402
+ }
403
+
404
+ /**
405
+ * Execute claude-zeroshots with built context
406
+ * Retries disabled by default. Set agent config `maxRetries` to enable (e.g., 3).
407
+ * @private
408
+ */
409
+ _executeTask(triggeringMessage) {
410
+ return lifecycleExecuteTask(this, triggeringMessage);
411
+ }
412
+
413
+ /**
414
+ * Build context from ledger based on contextStrategy
415
+ * @private
416
+ */
417
+ _buildContext(triggeringMessage) {
418
+ const previousAgentStart = this.lastAgentStartTime;
419
+ const queuedGuidance = collectQueuedGuidance({
420
+ messageBus: this.messageBus,
421
+ clusterId: this.cluster.id,
422
+ agentId: this.id,
423
+ lastDeliveredAt: this.lastGuidanceAppliedAt,
424
+ });
425
+ const context = buildContext({
426
+ id: this.id,
427
+ role: this.role,
428
+ iteration: this.iteration,
429
+ config: this.config,
430
+ messageBus: this.messageBus,
431
+ cluster: this.cluster,
432
+ lastTaskEndTime: this.lastTaskEndTime,
433
+ lastAgentStartTime: previousAgentStart,
434
+ triggeringMessage,
435
+ selectedPrompt: this._selectPrompt(),
436
+ queuedGuidance: queuedGuidance.guidanceBlock,
437
+ // Pass isolation state for conditional git restriction
438
+ worktree: this.worktree,
439
+ isolation: this.isolation,
440
+ });
441
+
442
+ // Record when this iteration started so future "since: last_agent_start" filters work.
443
+ const latestMessage = this.messageBus.findLast({ cluster_id: this.cluster.id });
444
+ const latestTimestamp = latestMessage?.timestamp;
445
+ const now = Date.now();
446
+ this.lastAgentStartTime =
447
+ typeof latestTimestamp === 'number' ? Math.max(now, latestTimestamp + 1) : now;
448
+
449
+ if (queuedGuidance.latestTimestamp !== null) {
450
+ this.lastGuidanceAppliedAt = queuedGuidance.latestTimestamp;
451
+ }
452
+
453
+ return context;
454
+ }
455
+
456
+ /**
457
+ * Spawn claude-zeroshots process and stream output via message bus
458
+ * @private
459
+ */
460
+ _spawnClaudeTask(context) {
461
+ return spawnClaudeTask(this, context);
462
+ }
463
+
464
+ /**
465
+ * Wait for task to be registered in ct storage
466
+ * @private
467
+ */
468
+ _waitForTaskReady(taskId, maxRetries = 10, delayMs = 200) {
469
+ return waitForTaskReady(this, taskId, maxRetries, delayMs);
470
+ }
471
+
472
+ /**
473
+ * Follow claude-zeroshots logs until completion, streaming to message bus
474
+ * Reads log file directly for reliable streaming
475
+ * @private
476
+ */
477
+ _followClaudeTaskLogs(taskId) {
478
+ return followClaudeTaskLogs(this, taskId);
479
+ }
480
+
481
+ /**
482
+ * Get path to claude-zeroshots executable
483
+ * @private
484
+ */
485
+ _getClaudeTasksPath() {
486
+ return getClaudeTasksPath();
487
+ }
488
+
489
+ /**
490
+ * Spawn claude-zeroshots inside Docker container (isolation mode)
491
+ * Runs Claude CLI inside the container for full isolation
492
+ * @private
493
+ */
494
+ _spawnClaudeTaskIsolated(context) {
495
+ return spawnClaudeTaskIsolated(this, context);
496
+ }
497
+
498
+ /**
499
+ * Kill current task
500
+ * @private
501
+ */
502
+ _killTask() {
503
+ return killTask(this);
504
+ }
505
+
506
+ /**
507
+ * Execute a hook
508
+ * THROWS on failure - no silent errors
509
+ * @private
510
+ */
511
+ _executeHook(hookName, context) {
512
+ const hook = this.config.hooks?.[hookName];
513
+ return executeHook({
514
+ hook,
515
+ agent: this,
516
+ message: context.triggeringMessage,
517
+ result: context.result,
518
+ messageBus: this.messageBus,
519
+ cluster: this.cluster,
520
+ orchestrator: this.orchestrator,
521
+ });
522
+ }
523
+
524
+ /**
525
+ * Parse agent output to extract structured result data
526
+ * GENERIC - returns whatever structured output the agent provides
527
+ * Works with any agent schema (planner, validator, worker, etc.)
528
+ * Falls back to reformatting if extraction fails
529
+ * @private
530
+ */
531
+ _parseResultOutput(output) {
532
+ return parseResultOutput(this, output);
533
+ }
534
+
535
+ /**
536
+ * Resume agent task with context from previous failure
537
+ * Called by Orchestrator.resume() to continue where we left off
538
+ * @param {String} resumeContext - Context describing what to resume
539
+ */
540
+ async resume(resumeContext) {
541
+ if (!this.running) {
542
+ throw new Error(`Agent ${this.id} is not running. Start it first.`);
543
+ }
544
+
545
+ if (this.state !== 'idle') {
546
+ throw new Error(`Agent ${this.id} is busy (state: ${this.state}). Wait for current task.`);
547
+ }
548
+
549
+ this._log(`[${this.id}] Resuming task...`);
550
+
551
+ // Create a synthetic triggering message for resume
552
+ const triggeringMessage = {
553
+ cluster_id: this.cluster.id,
554
+ topic: 'AGENT_RESUME',
555
+ sender: 'system',
556
+ content: {
557
+ text: resumeContext,
558
+ },
559
+ };
560
+
561
+ // Execute the task with resume context
562
+ await this._executeTask(triggeringMessage);
563
+ }
564
+
565
+ /**
566
+ * Inject live input into a running agent task when possible
567
+ * @param {string} text
568
+ * @param {object} [options]
569
+ * @returns {Promise<{status: string, reason?: string|null, method?: string|null, taskId?: string|null}>}
570
+ */
571
+ injectInput(text, options = {}) {
572
+ return injectAgentInput(this, text, options);
573
+ }
574
+
575
+ /**
576
+ * Get current agent state
577
+ */
578
+ getState() {
579
+ const modelSpec = this._resolveModelSpec();
580
+ const hasLiveOrTrackedTask =
581
+ this.state === 'executing_task' && (!!this.currentTask || !!this.currentTaskId);
582
+ return {
583
+ id: this.id,
584
+ role: this.role,
585
+ model: this._selectModel(),
586
+ provider: this._resolveProvider(),
587
+ modelSpec,
588
+ state: this.state,
589
+ iteration: this.iteration,
590
+ maxIterations: this.maxIterations,
591
+ currentTask: hasLiveOrTrackedTask,
592
+ currentTaskId: this.currentTaskId,
593
+ pid: this.processPid,
594
+ };
595
+ }
596
+
597
+ /**
598
+ * Start monitoring agent output liveness
599
+ * Detects when agent produces no output for configured staleDuration
600
+ * @private
601
+ */
602
+ _startLivenessCheck() {
603
+ return lifecycleStartLivenessCheck(this);
604
+ }
605
+
606
+ /**
607
+ * Stop liveness monitoring
608
+ * @private
609
+ */
610
+ _stopLivenessCheck() {
611
+ return lifecycleStopLivenessCheck(this);
612
+ }
613
+ }
614
+
615
+ module.exports = AgentWrapper;