@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,425 @@
1
+ /**
2
+ * TemplateResolver - Resolves parameterized cluster templates
3
+ *
4
+ * Takes a base template with {{param}} placeholders and resolves them
5
+ * with provided parameter values. Pure data transformation, no magic.
6
+ *
7
+ * Resolution rules:
8
+ * 1. Load base template JSON
9
+ * 2. Deep clone
10
+ * 3. Walk all values, replace {{param}} with params[param]
11
+ * 4. Handle conditional agents via "condition" field
12
+ * 5. Fail hard if any {{param}} remains unresolved
13
+ */
14
+
15
+ const fs = require('fs');
16
+ const path = require('path');
17
+
18
+ const COMPARISON_OPERATORS = ['==', '!=', '<=', '>=', '<', '>'];
19
+
20
+ function isIdentifierChar(char) {
21
+ if (!char) return false;
22
+ const code = char.charCodeAt(0);
23
+ return (
24
+ (code >= 48 && code <= 57) ||
25
+ (code >= 65 && code <= 90) ||
26
+ (code >= 97 && code <= 122) ||
27
+ code === 95
28
+ );
29
+ }
30
+
31
+ function replaceBareIdentifier(source, name, replacement) {
32
+ let result = '';
33
+ let cursor = 0;
34
+
35
+ while (cursor < source.length) {
36
+ const index = source.indexOf(name, cursor);
37
+ if (index === -1) {
38
+ return result + source.slice(cursor);
39
+ }
40
+
41
+ const before = source[index - 1];
42
+ const after = source[index + name.length];
43
+ const replace = !isIdentifierChar(before) && !isIdentifierChar(after);
44
+ result += source.slice(cursor, index);
45
+ result += replace ? replacement : name;
46
+ cursor = index + name.length;
47
+ }
48
+
49
+ return result;
50
+ }
51
+
52
+ function formatConditionValue(value) {
53
+ if (value === undefined) return 'undefined';
54
+ if (typeof value === 'string') return JSON.stringify(value);
55
+ return String(value);
56
+ }
57
+
58
+ function parseNumberLiteral(value) {
59
+ if (!value) return null;
60
+ const unsigned = value[0] === '-' ? value.slice(1) : value;
61
+ const parts = unsigned.split('.');
62
+ if (parts.length > 2 || parts.some((part) => part.length === 0)) return null;
63
+ const numeric = parts.every((part) =>
64
+ [...part].every((char) => {
65
+ const code = char.charCodeAt(0);
66
+ return code >= 48 && code <= 57;
67
+ })
68
+ );
69
+ return numeric ? Number(value) : null;
70
+ }
71
+
72
+ function compareValues(left, operator, right) {
73
+ switch (operator) {
74
+ case '==':
75
+ return left === right;
76
+ case '!=':
77
+ return left !== right;
78
+ case '<':
79
+ return left < right;
80
+ case '>':
81
+ return left > right;
82
+ case '<=':
83
+ return left <= right;
84
+ case '>=':
85
+ return left >= right;
86
+ default:
87
+ throw new Error(`Unsupported comparison operator: ${operator}`);
88
+ }
89
+ }
90
+
91
+ class TemplateResolver {
92
+ /**
93
+ * @param {string} templatesDir
94
+ */
95
+ constructor(templatesDir) {
96
+ this.templatesDir = templatesDir;
97
+ this.baseTemplatesDir = path.join(templatesDir, 'base-templates');
98
+ }
99
+
100
+ /**
101
+ * Resolve a template with parameters
102
+ * @param {string} baseName - Name of base template (without .json)
103
+ * @param {Object} params - Parameter values to substitute
104
+ * @returns {Object} Resolved cluster config
105
+ */
106
+ resolve(baseName, params) {
107
+ // Load base template
108
+ const templatePath = path.join(this.baseTemplatesDir, `${baseName}.json`);
109
+ if (!fs.existsSync(templatePath)) {
110
+ throw new Error(`Base template not found: ${baseName} (looked in ${templatePath})`);
111
+ }
112
+
113
+ const templateJson = fs.readFileSync(templatePath, 'utf8');
114
+ const template = JSON.parse(templateJson);
115
+
116
+ return this.resolveTemplate(template, params);
117
+ }
118
+
119
+ /**
120
+ * Resolve an already-loaded parameterized template object.
121
+ * @param {Object} template
122
+ * @param {Object} params
123
+ * @returns {Object} Resolved cluster config
124
+ */
125
+ resolveTemplate(template, params = {}) {
126
+ // Validate required params
127
+ this._validateParams(template, params);
128
+
129
+ // Apply defaults for missing params (e.g., timeout: 0)
130
+ const paramsWithDefaults = this._applyDefaults(template, params);
131
+
132
+ // Deep clone and resolve
133
+ const resolved = this._resolveObject(JSON.parse(JSON.stringify(template)), paramsWithDefaults);
134
+
135
+ // Filter out conditional agents that don't meet their condition
136
+ if (resolved.agents) {
137
+ resolved.agents = resolved.agents.filter((/** @type {any} */ agent) => {
138
+ if (!agent.condition) return true;
139
+ const conditionMet = this._evaluateCondition(agent.condition, paramsWithDefaults);
140
+ delete agent.condition; // Remove condition field from final output
141
+ return conditionMet;
142
+ });
143
+ }
144
+
145
+ // Verify no unresolved placeholders remain
146
+ this._verifyResolved(resolved);
147
+
148
+ // Remove params schema from output (it's metadata, not config)
149
+ delete resolved.params;
150
+
151
+ return resolved;
152
+ }
153
+
154
+ /**
155
+ * Validate that required params are provided
156
+ * @private
157
+ * @param {any} template
158
+ * @param {any} params
159
+ */
160
+ _validateParams(template, params) {
161
+ if (!template.params) return;
162
+
163
+ const missing = [];
164
+ for (const [name, schema] of Object.entries(template.params)) {
165
+ if (params[name] === undefined && schema.default === undefined) {
166
+ missing.push(name);
167
+ }
168
+ }
169
+
170
+ if (missing.length > 0) {
171
+ throw new Error(`Missing required params: ${missing.join(', ')}`);
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Apply template defaults for any missing params
177
+ * @private
178
+ * @param {any} template
179
+ * @param {any} params
180
+ * @returns {any} params with defaults applied
181
+ */
182
+ _applyDefaults(template, params) {
183
+ if (!template.params) return params;
184
+
185
+ const result = { ...params };
186
+ for (const [name, schema] of Object.entries(template.params)) {
187
+ if (result[name] === undefined && schema.default !== undefined) {
188
+ result[name] = schema.default;
189
+ }
190
+ }
191
+ return result;
192
+ }
193
+
194
+ /**
195
+ * Recursively resolve placeholders in an object
196
+ * @private
197
+ * @param {any} obj
198
+ * @param {any} params
199
+ * @returns {any}
200
+ */
201
+ _resolveObject(obj, params) {
202
+ if (obj === null || obj === undefined) {
203
+ return obj;
204
+ }
205
+
206
+ if (typeof obj === 'string') {
207
+ return this._resolveString(obj, params);
208
+ }
209
+
210
+ if (Array.isArray(obj)) {
211
+ return obj.map((item) => this._resolveObject(item, params));
212
+ }
213
+
214
+ if (typeof obj === 'object') {
215
+ /** @type {any} */
216
+ const result = {};
217
+ for (const [key, value] of Object.entries(obj)) {
218
+ result[key] = this._resolveObject(value, params);
219
+ }
220
+ return result;
221
+ }
222
+
223
+ return obj;
224
+ }
225
+
226
+ /**
227
+ * Resolve placeholders in a string
228
+ * Supports: {{param}} and {{#if condition}}...{{/if}}
229
+ * @private
230
+ * @param {any} str
231
+ * @param {any} params
232
+ * @returns {any}
233
+ */
234
+ _resolveString(str, params) {
235
+ // Handle simple {{param}} substitutions
236
+ let result = str.replace(
237
+ /\{\{(\w+)\}\}/g,
238
+ (/** @type {any} */ _match, /** @type {any} */ paramName) => {
239
+ if (params[paramName] !== undefined) {
240
+ return params[paramName];
241
+ }
242
+ // Return match unchanged if param not found (will be caught by verify)
243
+ return _match;
244
+ }
245
+ );
246
+
247
+ // Handle {{#if condition}}...{{/if}} blocks
248
+ result = result.replace(
249
+ /\{\{#if\s+([^}]+)\}\}([\s\S]*?)\{\{\/if\}\}/g,
250
+ (/** @type {any} */ _match, /** @type {any} */ condition, /** @type {any} */ content) => {
251
+ const conditionMet = this._evaluateCondition(condition, params);
252
+ return conditionMet ? content : '';
253
+ }
254
+ );
255
+
256
+ // Clean up multiple newlines from removed conditionals
257
+ result = result.replace(/\n{3,}/g, '\n\n');
258
+
259
+ return result;
260
+ }
261
+
262
+ /**
263
+ * Evaluate a simple condition expression
264
+ * Supports: param == 'value', param != 'value', {{param}} >= N
265
+ * @private
266
+ * @param {any} condition
267
+ * @param {any} params
268
+ * @returns {boolean}
269
+ */
270
+ _evaluateCondition(condition, params) {
271
+ // Replace {{param}} with actual values first
272
+ let expr = condition.trim();
273
+
274
+ // Replace {{param}} placeholders
275
+ expr = expr.replace(
276
+ /\{\{(\w+)\}\}/g,
277
+ (/** @type {any} */ _match, /** @type {any} */ paramName) => {
278
+ return formatConditionValue(params[paramName]);
279
+ }
280
+ );
281
+
282
+ // Replace bare param names
283
+ for (const [name, value] of Object.entries(params)) {
284
+ expr = replaceBareIdentifier(expr, name, formatConditionValue(value));
285
+ }
286
+
287
+ try {
288
+ // Parse and evaluate simple comparison expressions without eval
289
+ return this._evaluateSimpleExpression(expr);
290
+ } catch {
291
+ console.error(`Failed to evaluate condition: ${condition} (resolved: ${expr})`);
292
+ return false;
293
+ }
294
+ }
295
+
296
+ /**
297
+ * Evaluate simple comparison expressions without eval
298
+ * Supports: ==, !=, <, >, <=, >=, &&, ||
299
+ * @private
300
+ * @param {string} expr
301
+ * @returns {boolean}
302
+ */
303
+ _evaluateSimpleExpression(expr) {
304
+ // Handle logical operators (&&, ||) by splitting and recursing
305
+ if (expr.includes('||')) {
306
+ return expr.split('||').some((part) => this._evaluateSimpleExpression(part.trim()));
307
+ }
308
+ if (expr.includes('&&')) {
309
+ return expr.split('&&').every((part) => this._evaluateSimpleExpression(part.trim()));
310
+ }
311
+
312
+ for (const op of COMPARISON_OPERATORS) {
313
+ if (expr.includes(op)) {
314
+ const [left, right] = expr.split(op).map((s) => s.trim());
315
+ return compareValues(this._parseValue(left), op, this._parseValue(right));
316
+ }
317
+ }
318
+
319
+ // If no operator found, treat as boolean literal or truthy value
320
+ return this._parseValue(expr) ? true : false;
321
+ }
322
+
323
+ /**
324
+ * Parse a value from string (number, boolean, string literal)
325
+ * @private
326
+ * @param {string} str
327
+ * @returns {any}
328
+ */
329
+ _parseValue(str) {
330
+ const trimmed = str.trim();
331
+
332
+ // String literals (single or double quotes)
333
+ if (
334
+ (trimmed.startsWith('"') && trimmed.endsWith('"')) ||
335
+ (trimmed.startsWith("'") && trimmed.endsWith("'"))
336
+ ) {
337
+ return trimmed.slice(1, -1);
338
+ }
339
+
340
+ // Boolean literals
341
+ if (trimmed === 'true') return true;
342
+ if (trimmed === 'false') return false;
343
+ if (trimmed === 'undefined' || trimmed === 'null') return undefined;
344
+
345
+ const numericValue = parseNumberLiteral(trimmed);
346
+ if (numericValue !== null) return numericValue;
347
+
348
+ // Return as-is for other cases
349
+ return trimmed;
350
+ }
351
+
352
+ /**
353
+ * Verify no unresolved placeholders remain
354
+ * @private
355
+ * @param {any} obj
356
+ */
357
+ _verifyResolved(obj) {
358
+ const unresolved = this._findUnresolved(obj);
359
+ if (unresolved.length > 0) {
360
+ throw new Error(`Unresolved template placeholders: ${unresolved.join(', ')}`);
361
+ }
362
+ }
363
+
364
+ /**
365
+ * Find all unresolved {{param}} placeholders
366
+ * @private
367
+ * @param {any} obj
368
+ * @param {string} pathPrefix
369
+ * @returns {string[]}
370
+ */
371
+ _findUnresolved(obj, pathPrefix = '') {
372
+ const unresolved = [];
373
+
374
+ if (typeof obj === 'string') {
375
+ const matches = obj.match(/\{\{(\w+)\}\}/g);
376
+ if (matches) {
377
+ unresolved.push(...matches.map((m) => `${pathPrefix}: ${m}`));
378
+ }
379
+ } else if (Array.isArray(obj)) {
380
+ obj.forEach((item, i) => {
381
+ unresolved.push(...this._findUnresolved(item, `${pathPrefix}[${i}]`));
382
+ });
383
+ } else if (obj && typeof obj === 'object') {
384
+ for (const [key, value] of Object.entries(obj)) {
385
+ unresolved.push(...this._findUnresolved(value, `${pathPrefix}.${key}`));
386
+ }
387
+ }
388
+
389
+ return unresolved;
390
+ }
391
+
392
+ /**
393
+ * List available base templates
394
+ * @returns {string[]}
395
+ */
396
+ listTemplates() {
397
+ if (!fs.existsSync(this.baseTemplatesDir)) {
398
+ return [];
399
+ }
400
+ return fs
401
+ .readdirSync(this.baseTemplatesDir)
402
+ .filter((f) => f.endsWith('.json'))
403
+ .map((f) => f.replace('.json', ''));
404
+ }
405
+
406
+ /**
407
+ * Get template metadata (name, description, params)
408
+ * @param {any} baseName
409
+ * @returns {any}
410
+ */
411
+ getTemplateInfo(baseName) {
412
+ const templatePath = path.join(this.baseTemplatesDir, `${baseName}.json`);
413
+ if (!fs.existsSync(templatePath)) {
414
+ return null;
415
+ }
416
+ const template = JSON.parse(fs.readFileSync(templatePath, 'utf8'));
417
+ return {
418
+ name: template.name,
419
+ description: template.description,
420
+ params: template.params || {},
421
+ };
422
+ }
423
+ }
424
+
425
+ module.exports = TemplateResolver;