@waratahlabs/canopy 0.5.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 (319) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +323 -0
  3. package/SKILL.md +97 -0
  4. package/demo/data/openclaw-demo.tc.json +397 -0
  5. package/demo/data/openclaw-nemoclaw-demo.tc.json +475 -0
  6. package/demo/index.html +556 -0
  7. package/dist/adapters/a2a.d.ts +82 -0
  8. package/dist/adapters/a2a.d.ts.map +1 -0
  9. package/dist/adapters/a2a.js +215 -0
  10. package/dist/adapters/a2a.js.map +1 -0
  11. package/dist/adapters/a2a.test.d.ts +2 -0
  12. package/dist/adapters/a2a.test.d.ts.map +1 -0
  13. package/dist/adapters/a2a.test.js +196 -0
  14. package/dist/adapters/a2a.test.js.map +1 -0
  15. package/dist/adapters/langfuse.d.ts +28 -0
  16. package/dist/adapters/langfuse.d.ts.map +1 -0
  17. package/dist/adapters/langfuse.js +192 -0
  18. package/dist/adapters/langfuse.js.map +1 -0
  19. package/dist/adapters/n8n.d.ts +4 -0
  20. package/dist/adapters/n8n.d.ts.map +1 -0
  21. package/dist/adapters/n8n.js +89 -0
  22. package/dist/adapters/n8n.js.map +1 -0
  23. package/dist/adapters/openclaw.d.ts +58 -0
  24. package/dist/adapters/openclaw.d.ts.map +1 -0
  25. package/dist/adapters/openclaw.js +275 -0
  26. package/dist/adapters/openclaw.js.map +1 -0
  27. package/dist/adapters/types.d.ts +33 -0
  28. package/dist/adapters/types.d.ts.map +1 -0
  29. package/dist/adapters/types.js +2 -0
  30. package/dist/adapters/types.js.map +1 -0
  31. package/dist/aivss/atlas/coverage-matrix.d.ts +12 -0
  32. package/dist/aivss/atlas/coverage-matrix.d.ts.map +1 -0
  33. package/dist/aivss/atlas/coverage-matrix.js +272 -0
  34. package/dist/aivss/atlas/coverage-matrix.js.map +1 -0
  35. package/dist/aivss/atlas/loader.d.ts +28 -0
  36. package/dist/aivss/atlas/loader.d.ts.map +1 -0
  37. package/dist/aivss/atlas/loader.js +126 -0
  38. package/dist/aivss/atlas/loader.js.map +1 -0
  39. package/dist/aivss/atlas/loader.test.d.ts +11 -0
  40. package/dist/aivss/atlas/loader.test.d.ts.map +1 -0
  41. package/dist/aivss/atlas/loader.test.js +111 -0
  42. package/dist/aivss/atlas/loader.test.js.map +1 -0
  43. package/dist/aivss/atlas/resolve-path.d.ts +34 -0
  44. package/dist/aivss/atlas/resolve-path.d.ts.map +1 -0
  45. package/dist/aivss/atlas/resolve-path.js +58 -0
  46. package/dist/aivss/atlas/resolve-path.js.map +1 -0
  47. package/dist/aivss/batch/batch-builder.d.ts +11 -0
  48. package/dist/aivss/batch/batch-builder.d.ts.map +1 -0
  49. package/dist/aivss/batch/batch-builder.js +75 -0
  50. package/dist/aivss/batch/batch-builder.js.map +1 -0
  51. package/dist/aivss/index.d.ts +21 -0
  52. package/dist/aivss/index.d.ts.map +1 -0
  53. package/dist/aivss/index.js +19 -0
  54. package/dist/aivss/index.js.map +1 -0
  55. package/dist/aivss/knowledge-base/kb-client.d.ts +9 -0
  56. package/dist/aivss/knowledge-base/kb-client.d.ts.map +1 -0
  57. package/dist/aivss/knowledge-base/kb-client.js +139 -0
  58. package/dist/aivss/knowledge-base/kb-client.js.map +1 -0
  59. package/dist/aivss/knowledge-base/kb-types.d.ts +21 -0
  60. package/dist/aivss/knowledge-base/kb-types.d.ts.map +1 -0
  61. package/dist/aivss/knowledge-base/kb-types.js +2 -0
  62. package/dist/aivss/knowledge-base/kb-types.js.map +1 -0
  63. package/dist/aivss/knowledge-base/search-builder.d.ts +7 -0
  64. package/dist/aivss/knowledge-base/search-builder.d.ts.map +1 -0
  65. package/dist/aivss/knowledge-base/search-builder.js +119 -0
  66. package/dist/aivss/knowledge-base/search-builder.js.map +1 -0
  67. package/dist/aivss/metrics/aa.d.ts +3 -0
  68. package/dist/aivss/metrics/aa.d.ts.map +1 -0
  69. package/dist/aivss/metrics/aa.js +26 -0
  70. package/dist/aivss/metrics/aa.js.map +1 -0
  71. package/dist/aivss/metrics/ad.d.ts +3 -0
  72. package/dist/aivss/metrics/ad.d.ts.map +1 -0
  73. package/dist/aivss/metrics/ad.js +30 -0
  74. package/dist/aivss/metrics/ad.js.map +1 -0
  75. package/dist/aivss/metrics/cs.d.ts +3 -0
  76. package/dist/aivss/metrics/cs.d.ts.map +1 -0
  77. package/dist/aivss/metrics/cs.js +50 -0
  78. package/dist/aivss/metrics/cs.js.map +1 -0
  79. package/dist/aivss/metrics/dc.d.ts +3 -0
  80. package/dist/aivss/metrics/dc.d.ts.map +1 -0
  81. package/dist/aivss/metrics/dc.js +30 -0
  82. package/dist/aivss/metrics/dc.js.map +1 -0
  83. package/dist/aivss/metrics/ds.d.ts +3 -0
  84. package/dist/aivss/metrics/ds.d.ts.map +1 -0
  85. package/dist/aivss/metrics/ds.js +26 -0
  86. package/dist/aivss/metrics/ds.js.map +1 -0
  87. package/dist/aivss/metrics/ei.d.ts +3 -0
  88. package/dist/aivss/metrics/ei.d.ts.map +1 -0
  89. package/dist/aivss/metrics/ei.js +30 -0
  90. package/dist/aivss/metrics/ei.js.map +1 -0
  91. package/dist/aivss/metrics/gv.d.ts +3 -0
  92. package/dist/aivss/metrics/gv.d.ts.map +1 -0
  93. package/dist/aivss/metrics/gv.js +34 -0
  94. package/dist/aivss/metrics/gv.js.map +1 -0
  95. package/dist/aivss/metrics/ll.d.ts +3 -0
  96. package/dist/aivss/metrics/ll.d.ts.map +1 -0
  97. package/dist/aivss/metrics/ll.js +30 -0
  98. package/dist/aivss/metrics/ll.js.map +1 -0
  99. package/dist/aivss/metrics/mr.d.ts +3 -0
  100. package/dist/aivss/metrics/mr.d.ts.map +1 -0
  101. package/dist/aivss/metrics/mr.js +26 -0
  102. package/dist/aivss/metrics/mr.js.map +1 -0
  103. package/dist/aivss/metrics/shared.d.ts +22 -0
  104. package/dist/aivss/metrics/shared.d.ts.map +1 -0
  105. package/dist/aivss/metrics/shared.js +70 -0
  106. package/dist/aivss/metrics/shared.js.map +1 -0
  107. package/dist/aivss/prompts/base-system-prompt.d.ts +2 -0
  108. package/dist/aivss/prompts/base-system-prompt.d.ts.map +1 -0
  109. package/dist/aivss/prompts/base-system-prompt.js +31 -0
  110. package/dist/aivss/prompts/base-system-prompt.js.map +1 -0
  111. package/dist/aivss/prompts/prompt-composer.d.ts +13 -0
  112. package/dist/aivss/prompts/prompt-composer.d.ts.map +1 -0
  113. package/dist/aivss/prompts/prompt-composer.js +21 -0
  114. package/dist/aivss/prompts/prompt-composer.js.map +1 -0
  115. package/dist/aivss/scoring/a2a-corpus.test.d.ts +28 -0
  116. package/dist/aivss/scoring/a2a-corpus.test.d.ts.map +1 -0
  117. package/dist/aivss/scoring/a2a-corpus.test.js +109 -0
  118. package/dist/aivss/scoring/a2a-corpus.test.js.map +1 -0
  119. package/dist/aivss/scoring/determinism.test.d.ts +16 -0
  120. package/dist/aivss/scoring/determinism.test.d.ts.map +1 -0
  121. package/dist/aivss/scoring/determinism.test.js +169 -0
  122. package/dist/aivss/scoring/determinism.test.js.map +1 -0
  123. package/dist/aivss/scoring/heuristic-scorer.d.ts +21 -0
  124. package/dist/aivss/scoring/heuristic-scorer.d.ts.map +1 -0
  125. package/dist/aivss/scoring/heuristic-scorer.js +299 -0
  126. package/dist/aivss/scoring/heuristic-scorer.js.map +1 -0
  127. package/dist/aivss/scoring/heuristic-scorer.test.d.ts +8 -0
  128. package/dist/aivss/scoring/heuristic-scorer.test.d.ts.map +1 -0
  129. package/dist/aivss/scoring/heuristic-scorer.test.js +150 -0
  130. package/dist/aivss/scoring/heuristic-scorer.test.js.map +1 -0
  131. package/dist/aivss/scoring/scoring-mode.d.ts +48 -0
  132. package/dist/aivss/scoring/scoring-mode.d.ts.map +1 -0
  133. package/dist/aivss/scoring/scoring-mode.js +64 -0
  134. package/dist/aivss/scoring/scoring-mode.js.map +1 -0
  135. package/dist/aivss/scoring/v4-engine.d.ts +15 -0
  136. package/dist/aivss/scoring/v4-engine.d.ts.map +1 -0
  137. package/dist/aivss/scoring/v4-engine.js +84 -0
  138. package/dist/aivss/scoring/v4-engine.js.map +1 -0
  139. package/dist/aivss/scoring/v4-engine.test.d.ts +16 -0
  140. package/dist/aivss/scoring/v4-engine.test.d.ts.map +1 -0
  141. package/dist/aivss/scoring/v4-engine.test.js +156 -0
  142. package/dist/aivss/scoring/v4-engine.test.js.map +1 -0
  143. package/dist/aivss/types.d.ts +92 -0
  144. package/dist/aivss/types.d.ts.map +1 -0
  145. package/dist/aivss/types.js +25 -0
  146. package/dist/aivss/types.js.map +1 -0
  147. package/dist/baseline/baseline.test.d.ts +2 -0
  148. package/dist/baseline/baseline.test.d.ts.map +1 -0
  149. package/dist/baseline/baseline.test.js +219 -0
  150. package/dist/baseline/baseline.test.js.map +1 -0
  151. package/dist/baseline/diff.d.ts +42 -0
  152. package/dist/baseline/diff.d.ts.map +1 -0
  153. package/dist/baseline/diff.js +124 -0
  154. package/dist/baseline/diff.js.map +1 -0
  155. package/dist/baseline/store.d.ts +51 -0
  156. package/dist/baseline/store.d.ts.map +1 -0
  157. package/dist/baseline/store.js +92 -0
  158. package/dist/baseline/store.js.map +1 -0
  159. package/dist/batch/anthropic-batch-runner.d.ts +50 -0
  160. package/dist/batch/anthropic-batch-runner.d.ts.map +1 -0
  161. package/dist/batch/anthropic-batch-runner.js +91 -0
  162. package/dist/batch/anthropic-batch-runner.js.map +1 -0
  163. package/dist/batch/bedrock-batch-runner.d.ts +90 -0
  164. package/dist/batch/bedrock-batch-runner.d.ts.map +1 -0
  165. package/dist/batch/bedrock-batch-runner.js +199 -0
  166. package/dist/batch/bedrock-batch-runner.js.map +1 -0
  167. package/dist/batch/providers/anthropic.d.ts +55 -0
  168. package/dist/batch/providers/anthropic.d.ts.map +1 -0
  169. package/dist/batch/providers/anthropic.js +103 -0
  170. package/dist/batch/providers/anthropic.js.map +1 -0
  171. package/dist/batch/providers/bedrock.d.ts +31 -0
  172. package/dist/batch/providers/bedrock.d.ts.map +1 -0
  173. package/dist/batch/providers/bedrock.js +42 -0
  174. package/dist/batch/providers/bedrock.js.map +1 -0
  175. package/dist/batch/providers/harness.d.ts +36 -0
  176. package/dist/batch/providers/harness.d.ts.map +1 -0
  177. package/dist/batch/providers/harness.js +65 -0
  178. package/dist/batch/providers/harness.js.map +1 -0
  179. package/dist/batch/providers/harness.test.d.ts +7 -0
  180. package/dist/batch/providers/harness.test.d.ts.map +1 -0
  181. package/dist/batch/providers/harness.test.js +84 -0
  182. package/dist/batch/providers/harness.test.js.map +1 -0
  183. package/dist/batch/providers/index.d.ts +82 -0
  184. package/dist/batch/providers/index.d.ts.map +1 -0
  185. package/dist/batch/providers/index.js +82 -0
  186. package/dist/batch/providers/index.js.map +1 -0
  187. package/dist/batch/providers/ollama.d.ts +68 -0
  188. package/dist/batch/providers/ollama.d.ts.map +1 -0
  189. package/dist/batch/providers/ollama.js +108 -0
  190. package/dist/batch/providers/ollama.js.map +1 -0
  191. package/dist/batch/response-parser.d.ts +45 -0
  192. package/dist/batch/response-parser.d.ts.map +1 -0
  193. package/dist/batch/response-parser.js +161 -0
  194. package/dist/batch/response-parser.js.map +1 -0
  195. package/dist/batch/types.d.ts +87 -0
  196. package/dist/batch/types.d.ts.map +1 -0
  197. package/dist/batch/types.js +8 -0
  198. package/dist/batch/types.js.map +1 -0
  199. package/dist/cli.d.ts +15 -0
  200. package/dist/cli.d.ts.map +1 -0
  201. package/dist/cli.js +1037 -0
  202. package/dist/cli.js.map +1 -0
  203. package/dist/examples/a2a-assessment.d.ts +20 -0
  204. package/dist/examples/a2a-assessment.d.ts.map +1 -0
  205. package/dist/examples/a2a-assessment.js +115 -0
  206. package/dist/examples/a2a-assessment.js.map +1 -0
  207. package/dist/examples/batch-assessment.d.ts +18 -0
  208. package/dist/examples/batch-assessment.d.ts.map +1 -0
  209. package/dist/examples/batch-assessment.js +112 -0
  210. package/dist/examples/batch-assessment.js.map +1 -0
  211. package/dist/examples/batch-submission-flow.d.ts +2 -0
  212. package/dist/examples/batch-submission-flow.d.ts.map +1 -0
  213. package/dist/examples/batch-submission-flow.js +279 -0
  214. package/dist/examples/batch-submission-flow.js.map +1 -0
  215. package/dist/examples/demo-agent-definition.json +58 -0
  216. package/dist/examples/langfuse-assessment.d.ts +2 -0
  217. package/dist/examples/langfuse-assessment.d.ts.map +1 -0
  218. package/dist/examples/langfuse-assessment.js +46 -0
  219. package/dist/examples/langfuse-assessment.js.map +1 -0
  220. package/dist/examples/model-eval.d.ts +25 -0
  221. package/dist/examples/model-eval.d.ts.map +1 -0
  222. package/dist/examples/model-eval.js +94 -0
  223. package/dist/examples/model-eval.js.map +1 -0
  224. package/dist/examples/openclaw-assessment.d.ts +17 -0
  225. package/dist/examples/openclaw-assessment.d.ts.map +1 -0
  226. package/dist/examples/openclaw-assessment.js +79 -0
  227. package/dist/examples/openclaw-assessment.js.map +1 -0
  228. package/dist/examples/simple-assessment.d.ts +2 -0
  229. package/dist/examples/simple-assessment.d.ts.map +1 -0
  230. package/dist/examples/simple-assessment.js +146 -0
  231. package/dist/examples/simple-assessment.js.map +1 -0
  232. package/dist/examples/threat-model-demo.d.ts +2 -0
  233. package/dist/examples/threat-model-demo.d.ts.map +1 -0
  234. package/dist/examples/threat-model-demo.js +103 -0
  235. package/dist/examples/threat-model-demo.js.map +1 -0
  236. package/dist/index.d.ts +60 -0
  237. package/dist/index.d.ts.map +1 -0
  238. package/dist/index.js +155 -0
  239. package/dist/index.js.map +1 -0
  240. package/dist/output/likec4-generator.d.ts +43 -0
  241. package/dist/output/likec4-generator.d.ts.map +1 -0
  242. package/dist/output/likec4-generator.js +287 -0
  243. package/dist/output/likec4-generator.js.map +1 -0
  244. package/dist/output/slot-filler.d.ts +6 -0
  245. package/dist/output/slot-filler.d.ts.map +1 -0
  246. package/dist/output/slot-filler.js +71 -0
  247. package/dist/output/slot-filler.js.map +1 -0
  248. package/dist/output/tc-assembler.d.ts +30 -0
  249. package/dist/output/tc-assembler.d.ts.map +1 -0
  250. package/dist/output/tc-assembler.js +227 -0
  251. package/dist/output/tc-assembler.js.map +1 -0
  252. package/dist/output/tc-types.d.ts +41 -0
  253. package/dist/output/tc-types.d.ts.map +1 -0
  254. package/dist/output/tc-types.js +5 -0
  255. package/dist/output/tc-types.js.map +1 -0
  256. package/dist/output/tc-validator.test.d.ts +9 -0
  257. package/dist/output/tc-validator.test.d.ts.map +1 -0
  258. package/dist/output/tc-validator.test.js +194 -0
  259. package/dist/output/tc-validator.test.js.map +1 -0
  260. package/dist/providers/anthropic.d.ts +9 -0
  261. package/dist/providers/anthropic.d.ts.map +1 -0
  262. package/dist/providers/anthropic.js +30 -0
  263. package/dist/providers/anthropic.js.map +1 -0
  264. package/dist/providers/bedrock.d.ts +9 -0
  265. package/dist/providers/bedrock.d.ts.map +1 -0
  266. package/dist/providers/bedrock.js +38 -0
  267. package/dist/providers/bedrock.js.map +1 -0
  268. package/dist/providers/index.d.ts +6 -0
  269. package/dist/providers/index.d.ts.map +1 -0
  270. package/dist/providers/index.js +14 -0
  271. package/dist/providers/index.js.map +1 -0
  272. package/dist/providers/types.d.ts +12 -0
  273. package/dist/providers/types.d.ts.map +1 -0
  274. package/dist/providers/types.js +5 -0
  275. package/dist/providers/types.js.map +1 -0
  276. package/dist/references/acsc-risks.d.ts +18 -0
  277. package/dist/references/acsc-risks.d.ts.map +1 -0
  278. package/dist/references/acsc-risks.js +232 -0
  279. package/dist/references/acsc-risks.js.map +1 -0
  280. package/dist/references/aicm.d.ts +41 -0
  281. package/dist/references/aicm.d.ts.map +1 -0
  282. package/dist/references/aicm.js +447 -0
  283. package/dist/references/aicm.js.map +1 -0
  284. package/dist/references/dstg-meaid.d.ts +59 -0
  285. package/dist/references/dstg-meaid.d.ts.map +1 -0
  286. package/dist/references/dstg-meaid.js +352 -0
  287. package/dist/references/dstg-meaid.js.map +1 -0
  288. package/dist/references/index.d.ts +20 -0
  289. package/dist/references/index.d.ts.map +1 -0
  290. package/dist/references/index.js +31 -0
  291. package/dist/references/index.js.map +1 -0
  292. package/dist/references/nemoclaw.d.ts +48 -0
  293. package/dist/references/nemoclaw.d.ts.map +1 -0
  294. package/dist/references/nemoclaw.js +140 -0
  295. package/dist/references/nemoclaw.js.map +1 -0
  296. package/dist/references/nist-ai-rmf.d.ts +31 -0
  297. package/dist/references/nist-ai-rmf.d.ts.map +1 -0
  298. package/dist/references/nist-ai-rmf.js +627 -0
  299. package/dist/references/nist-ai-rmf.js.map +1 -0
  300. package/dist/references/owasp-agentic-top10.d.ts +50 -0
  301. package/dist/references/owasp-agentic-top10.d.ts.map +1 -0
  302. package/dist/references/owasp-agentic-top10.js +202 -0
  303. package/dist/references/owasp-agentic-top10.js.map +1 -0
  304. package/dist/references/registry-parity.test.d.ts +17 -0
  305. package/dist/references/registry-parity.test.d.ts.map +1 -0
  306. package/dist/references/registry-parity.test.js +87 -0
  307. package/dist/references/registry-parity.test.js.map +1 -0
  308. package/dist/references/registry.d.ts +90 -0
  309. package/dist/references/registry.d.ts.map +1 -0
  310. package/dist/references/registry.js +29 -0
  311. package/dist/references/registry.js.map +1 -0
  312. package/dist/tools/model-eval.d.ts +97 -0
  313. package/dist/tools/model-eval.d.ts.map +1 -0
  314. package/dist/tools/model-eval.js +307 -0
  315. package/dist/tools/model-eval.js.map +1 -0
  316. package/package.json +105 -0
  317. package/schemas/threat-composer-v1.schema.json +966 -0
  318. package/vendor/atlas-release/ATLAS-2026.07.yaml +17877 -0
  319. package/vendor/atlas-release/README.md +41 -0
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Anthropic Messages Batches BatchProvider implementation.
3
+ *
4
+ * Uses the Anthropic Messages Batches API to run all AIVSS metric assessments
5
+ * asynchronously. Reuses the existing `buildBatchRequests()` prompt builder
6
+ * (already Anthropic-formatted) and submits via `beta.messages.batches`.
7
+ *
8
+ * Batches typically complete in minutes to hours. This provider polls at
9
+ * configurable intervals (default 60s) until `processing_status === "ended"`.
10
+ *
11
+ * Reference: https://docs.anthropic.com/en/docs/build-with-claude/message-batches
12
+ *
13
+ * @example
14
+ * const provider = createBatchProvider({
15
+ * type: "anthropic",
16
+ * model: "claude-haiku-4-5-20251001",
17
+ * });
18
+ * const result = await assessWorkflow({ ..., batchProvider: provider });
19
+ */
20
+ import Anthropic from "@anthropic-ai/sdk";
21
+ import { buildBatchRequests } from "../../aivss/batch/batch-builder.js";
22
+ import { parseMetricResponse } from "../response-parser.js";
23
+ // ── Provider ─────────────────────────────────────────────────────────────────
24
+ export class AnthropicBatchProvider {
25
+ constructor(config = {}) {
26
+ this.name = "anthropic-batch";
27
+ this.model = config.model ?? "claude-haiku-4-5-20251001";
28
+ this.maxTokens = config.maxTokens ?? 2048;
29
+ this.pollIntervalMs = config.pollIntervalMs ?? 60000;
30
+ this.timeoutMs = config.timeoutMs ?? 24 * 60 * 60 * 1000;
31
+ this.client = new Anthropic({ apiKey: config.apiKey });
32
+ }
33
+ async runBatch(agents, options) {
34
+ const maxTokens = options.maxTokens ?? this.maxTokens;
35
+ const temperature = options.temperature ?? 0;
36
+ // 1. Build Anthropic-formatted batch requests
37
+ const requests = await buildBatchRequests({
38
+ agents,
39
+ useKnowledgeBase: false,
40
+ model: this.model,
41
+ maxTokens,
42
+ temperature,
43
+ });
44
+ if (requests.length === 0) {
45
+ throw new Error("AnthropicBatchProvider: buildBatchRequests returned 0 requests");
46
+ }
47
+ // 2. Submit batch
48
+ const batch = await this.client.beta.messages.batches.create({
49
+ requests: requests.map((req) => ({
50
+ custom_id: req.custom_id,
51
+ params: {
52
+ model: this.model,
53
+ max_tokens: maxTokens,
54
+ temperature,
55
+ system: req.params.system,
56
+ messages: req.params.messages,
57
+ },
58
+ })),
59
+ });
60
+ options.onProgress?.(`Submitted — batch ${batch.id} (${requests.length} requests)`);
61
+ // 3. Poll until ended
62
+ const batchId = batch.id;
63
+ const deadline = Date.now() + this.timeoutMs;
64
+ while (Date.now() < deadline) {
65
+ await sleep(this.pollIntervalMs);
66
+ const status = await this.client.beta.messages.batches.retrieve(batchId);
67
+ options.onProgress?.(`${status.processing_status} — ${status.request_counts.processing} processing, ${status.request_counts.succeeded} succeeded`);
68
+ if (status.processing_status === "ended")
69
+ break;
70
+ }
71
+ // Verify completion
72
+ const finalStatus = await this.client.beta.messages.batches.retrieve(batchId);
73
+ if (finalStatus.processing_status !== "ended") {
74
+ throw new Error(`Anthropic batch ${batchId} did not complete within ${this.timeoutMs / 1000}s timeout`);
75
+ }
76
+ // 4. Stream results and parse
77
+ const responses = [];
78
+ for await (const result of await this.client.beta.messages.batches.results(batchId)) {
79
+ if (result.result.type === "succeeded") {
80
+ const content = result.result.message.content[0];
81
+ const text = content?.type === "text" ? content.text : "";
82
+ responses.push(parseMetricResponse(result.custom_id, text));
83
+ }
84
+ else {
85
+ // errored or canceled — degrade gracefully
86
+ const parts = result.custom_id.split("-");
87
+ const rawMetric = parts[parts.length - 1] ?? "CS";
88
+ responses.push({
89
+ metricCode: rawMetric,
90
+ subCategoryScores: {},
91
+ findings: [`[batch-error] ${result.result.type} for ${result.custom_id}`],
92
+ deploymentBlocker: false,
93
+ atlasTechniques: [],
94
+ });
95
+ }
96
+ }
97
+ return responses;
98
+ }
99
+ }
100
+ function sleep(ms) {
101
+ return new Promise((resolve) => setTimeout(resolve, ms));
102
+ }
103
+ //# sourceMappingURL=anthropic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../../src/batch/providers/anthropic.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Bedrock BatchProvider implementation.
3
+ *
4
+ * Uses Amazon Bedrock Batch Inference with Nova 2 Lite (cross-region profile)
5
+ * to run all AIVSS metric assessments in a single job submission.
6
+ *
7
+ * Required IAM permissions on roleArn:
8
+ * - bedrock:CreateModelInvocationJob
9
+ * - bedrock:GetModelInvocationJob
10
+ * - s3:PutObject on s3Bucket/{s3Prefix}/input/*
11
+ * - s3:GetObject on s3Bucket/{s3Prefix}/output/*
12
+ * - s3:ListBucket on s3Bucket
13
+ *
14
+ * @example
15
+ * const provider = createBatchProvider({
16
+ * type: "bedrock",
17
+ * s3Bucket: "my-canopy-bucket",
18
+ * roleArn: "arn:aws:iam::123456789012:role/CanopyBatchRole",
19
+ * });
20
+ * const result = await assessWorkflow({ ..., batchProvider: provider });
21
+ */
22
+ import type { BedrockBatchConfig } from "../types.js";
23
+ import type { BatchProvider, BatchProviderOptions } from "../types.js";
24
+ import type { AgentDefinition, MetricAssessmentResponse } from "../../aivss/types.js";
25
+ export declare class BedrockBatchProvider implements BatchProvider {
26
+ private readonly config;
27
+ readonly name = "bedrock-batch";
28
+ constructor(config: BedrockBatchConfig);
29
+ runBatch(agents: AgentDefinition[], options: BatchProviderOptions): Promise<MetricAssessmentResponse[]>;
30
+ }
31
+ //# sourceMappingURL=bedrock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bedrock.d.ts","sourceRoot":"","sources":["../../../src/batch/providers/bedrock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,KAAK,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAEtF,qBAAa,oBAAqB,YAAW,aAAa;IAG5C,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,QAAQ,CAAC,IAAI,mBAAmB;gBAEH,MAAM,EAAE,kBAAkB;IAEjD,QAAQ,CACZ,MAAM,EAAE,eAAe,EAAE,EACzB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,wBAAwB,EAAE,CAAC;CAcvC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Bedrock BatchProvider implementation.
3
+ *
4
+ * Uses Amazon Bedrock Batch Inference with Nova 2 Lite (cross-region profile)
5
+ * to run all AIVSS metric assessments in a single job submission.
6
+ *
7
+ * Required IAM permissions on roleArn:
8
+ * - bedrock:CreateModelInvocationJob
9
+ * - bedrock:GetModelInvocationJob
10
+ * - s3:PutObject on s3Bucket/{s3Prefix}/input/*
11
+ * - s3:GetObject on s3Bucket/{s3Prefix}/output/*
12
+ * - s3:ListBucket on s3Bucket
13
+ *
14
+ * @example
15
+ * const provider = createBatchProvider({
16
+ * type: "bedrock",
17
+ * s3Bucket: "my-canopy-bucket",
18
+ * roleArn: "arn:aws:iam::123456789012:role/CanopyBatchRole",
19
+ * });
20
+ * const result = await assessWorkflow({ ..., batchProvider: provider });
21
+ */
22
+ import { runBedrockBatch } from "../bedrock-batch-runner.js";
23
+ export class BedrockBatchProvider {
24
+ constructor(config) {
25
+ this.config = config;
26
+ this.name = "bedrock-batch";
27
+ }
28
+ async runBatch(agents, options) {
29
+ const result = await runBedrockBatch({
30
+ agents,
31
+ config: {
32
+ ...this.config,
33
+ maxTokens: options.maxTokens ?? this.config.maxTokens,
34
+ },
35
+ onProgress: options.onProgress
36
+ ? (status, jobArn) => options.onProgress(`${status} — ${jobArn}`)
37
+ : undefined,
38
+ });
39
+ return result.responses;
40
+ }
41
+ }
42
+ //# sourceMappingURL=bedrock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bedrock.js","sourceRoot":"","sources":["../../../src/batch/providers/bedrock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAK7D,MAAM,OAAO,oBAAoB;IAG/B,YAA6B,MAA0B;QAA1B,WAAM,GAAN,MAAM,CAAoB;QAF9C,SAAI,GAAG,eAAe,CAAC;IAE0B,CAAC;IAE3D,KAAK,CAAC,QAAQ,CACZ,MAAyB,EACzB,OAA6B;QAE7B,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC;YACnC,MAAM;YACN,MAAM,EAAE;gBACN,GAAG,IAAI,CAAC,MAAM;gBACd,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS;aACtD;YACD,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC5B,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,UAAW,CAAC,GAAG,MAAM,MAAM,MAAM,EAAE,CAAC;gBAClE,CAAC,CAAC,SAAS;SACd,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC,SAAS,CAAC;IAC1B,CAAC;CACF"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * HarnessBatchProvider — lets an LLM coding agent (Claude Code, or any other
3
+ * agent driving a shell) BE the inference engine, with no API key, no SDK,
4
+ * and no subprocess spawn back out to a model.
5
+ *
6
+ * Canopy writes the per-agent/per-metric assessment prompts to a JSON file.
7
+ * The calling agent reads that file, reasons about each prompt using its own
8
+ * in-context model (the same turn it's already running in — no extra call of
9
+ * any kind), and writes its answers to a second JSON file. Canopy is re-run
10
+ * and picks the answers up from there. Two runs, one round-trip, zero network
11
+ * calls Canopy itself has to authenticate.
12
+ *
13
+ * This is the intended way to run Canopy from inside any coding harness: the
14
+ * harness's own model does the assessment reasoning directly, rather than
15
+ * Canopy shelling out to a model API or CLI on its own.
16
+ */
17
+ import type { AgentDefinition, MetricAssessmentResponse } from "../../aivss/types.js";
18
+ import type { BatchProvider, BatchProviderOptions } from "../types.js";
19
+ export interface HarnessBatchConfig {
20
+ /** Where Canopy writes the batch of assessment prompts (BatchRequest[] JSON). */
21
+ requestsPath: string;
22
+ /**
23
+ * Where Canopy looks for the calling agent's filled-in answers:
24
+ * an array of { custom_id: string; text: string }, one per request in
25
+ * requestsPath, where `text` is the raw completion the agent would have
26
+ * gotten back from a model for that request's system+user prompt.
27
+ */
28
+ responsesPath: string;
29
+ }
30
+ export declare class HarnessBatchProvider implements BatchProvider {
31
+ private readonly config;
32
+ readonly name = "harness-file-exchange";
33
+ constructor(config: HarnessBatchConfig);
34
+ runBatch(agents: AgentDefinition[], _options: BatchProviderOptions): Promise<MetricAssessmentResponse[]>;
35
+ }
36
+ //# sourceMappingURL=harness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../../src/batch/providers/harness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,OAAO,KAAK,EAAE,eAAe,EAAgB,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AACpG,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEvE,MAAM,WAAW,kBAAkB;IACjC,iFAAiF;IACjF,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,aAAa,EAAE,MAAM,CAAC;CACvB;AAOD,qBAAa,oBAAqB,YAAW,aAAa;IAG5C,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,QAAQ,CAAC,IAAI,2BAA2B;gBAEX,MAAM,EAAE,kBAAkB;IAEjD,QAAQ,CACZ,MAAM,EAAE,eAAe,EAAE,EACzB,QAAQ,EAAE,oBAAoB,GAC7B,OAAO,CAAC,wBAAwB,EAAE,CAAC;CA8CvC"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * HarnessBatchProvider — lets an LLM coding agent (Claude Code, or any other
3
+ * agent driving a shell) BE the inference engine, with no API key, no SDK,
4
+ * and no subprocess spawn back out to a model.
5
+ *
6
+ * Canopy writes the per-agent/per-metric assessment prompts to a JSON file.
7
+ * The calling agent reads that file, reasons about each prompt using its own
8
+ * in-context model (the same turn it's already running in — no extra call of
9
+ * any kind), and writes its answers to a second JSON file. Canopy is re-run
10
+ * and picks the answers up from there. Two runs, one round-trip, zero network
11
+ * calls Canopy itself has to authenticate.
12
+ *
13
+ * This is the intended way to run Canopy from inside any coding harness: the
14
+ * harness's own model does the assessment reasoning directly, rather than
15
+ * Canopy shelling out to a model API or CLI on its own.
16
+ */
17
+ import * as fs from "node:fs";
18
+ import * as path from "node:path";
19
+ import { buildBatchRequests } from "../../aivss/batch/batch-builder.js";
20
+ import { parseMetricResponse } from "../response-parser.js";
21
+ export class HarnessBatchProvider {
22
+ constructor(config) {
23
+ this.config = config;
24
+ this.name = "harness-file-exchange";
25
+ }
26
+ async runBatch(agents, _options) {
27
+ const requests = await buildBatchRequests({
28
+ agents,
29
+ useKnowledgeBase: false,
30
+ });
31
+ fs.mkdirSync(path.dirname(path.resolve(this.config.requestsPath)), { recursive: true });
32
+ fs.writeFileSync(this.config.requestsPath, JSON.stringify(requests, null, 2));
33
+ if (!fs.existsSync(this.config.responsesPath)) {
34
+ throw new Error(`HarnessBatchProvider: wrote ${requests.length} assessment prompts to ` +
35
+ `${this.config.requestsPath}. No responses file found at ${this.config.responsesPath} yet.\n\n` +
36
+ `To continue: read ${this.config.requestsPath} (an array of ` +
37
+ `{ custom_id, params: { system, messages } }), answer each prompt directly ` +
38
+ `using your own reasoning — no API call needed — and write your answers to ` +
39
+ `${this.config.responsesPath} as an array of { custom_id, text }, where ` +
40
+ `"text" is exactly what a model would have returned for that request's ` +
41
+ `system+user prompt (the JSON schema described in each prompt). Then re-run.`);
42
+ }
43
+ const raw = fs.readFileSync(this.config.responsesPath, "utf8");
44
+ let responses;
45
+ try {
46
+ responses = JSON.parse(raw);
47
+ }
48
+ catch (err) {
49
+ const msg = err instanceof Error ? err.message : String(err);
50
+ throw new Error(`HarnessBatchProvider: ${this.config.responsesPath} is not valid JSON: ${msg}`);
51
+ }
52
+ if (!Array.isArray(responses)) {
53
+ throw new Error(`HarnessBatchProvider: ${this.config.responsesPath} must be a JSON array of { custom_id, text }`);
54
+ }
55
+ const byId = new Map(responses.map((r) => [r.custom_id, r.text]));
56
+ const missing = requests.filter((r) => !byId.has(r.custom_id));
57
+ if (missing.length > 0) {
58
+ throw new Error(`HarnessBatchProvider: ${this.config.responsesPath} is missing answers for ` +
59
+ `${missing.length} of ${requests.length} prompts (e.g. ${missing[0].custom_id}). ` +
60
+ `Every custom_id in ${this.config.requestsPath} needs a matching entry.`);
61
+ }
62
+ return requests.map((r) => parseMetricResponse(r.custom_id, byId.get(r.custom_id)));
63
+ }
64
+ }
65
+ //# sourceMappingURL=harness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness.js","sourceRoot":"","sources":["../../../src/batch/providers/harness.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Unit tests for HarnessBatchProvider — the no-API-key batch provider where
3
+ * an LLM coding agent answers the assessment prompts directly instead of
4
+ * Canopy calling out to a model itself.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=harness.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness.test.d.ts","sourceRoot":"","sources":["../../../src/batch/providers/harness.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Unit tests for HarnessBatchProvider — the no-API-key batch provider where
3
+ * an LLM coding agent answers the assessment prompts directly instead of
4
+ * Canopy calling out to a model itself.
5
+ */
6
+ import { describe, it, expect, afterEach } from "bun:test";
7
+ import * as fs from "node:fs";
8
+ import * as os from "node:os";
9
+ import * as path from "node:path";
10
+ import { HarnessBatchProvider } from "./harness";
11
+ function makeAgent() {
12
+ return {
13
+ id: "test-agent",
14
+ name: "Test Agent",
15
+ model: "test-model",
16
+ systemPrompt: "You are a test agent.",
17
+ tools: [],
18
+ permissions: [],
19
+ deploymentContext: "General",
20
+ modelComplexity: "Simple",
21
+ mitigationMultiplier: 1.0,
22
+ finetuned: false,
23
+ dependencies: [],
24
+ secretManagement: "vault, 24h TTL rotation",
25
+ deployment: "Docker container",
26
+ dataSources: [],
27
+ externalApiCount: 0,
28
+ autonomyLevel: "semi-autonomous",
29
+ objectives: [],
30
+ };
31
+ }
32
+ let tmpDir;
33
+ afterEach(() => {
34
+ if (tmpDir && fs.existsSync(tmpDir))
35
+ fs.rmSync(tmpDir, { recursive: true, force: true });
36
+ });
37
+ describe("HarnessBatchProvider", () => {
38
+ it("writes prompts and throws with next-step instructions when no responses file exists", async () => {
39
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "canopy-harness-test-"));
40
+ const requestsPath = path.join(tmpDir, "requests.json");
41
+ const responsesPath = path.join(tmpDir, "responses.json");
42
+ const provider = new HarnessBatchProvider({ requestsPath, responsesPath });
43
+ await expect(provider.runBatch([makeAgent()], {})).rejects.toThrow(/No responses file found/);
44
+ expect(fs.existsSync(requestsPath)).toBe(true);
45
+ const requests = JSON.parse(fs.readFileSync(requestsPath, "utf8"));
46
+ expect(Array.isArray(requests)).toBe(true);
47
+ expect(requests.length).toBe(9); // one per AIVSS metric
48
+ expect(requests[0]).toHaveProperty("custom_id");
49
+ expect(requests[0].params).toHaveProperty("system");
50
+ expect(requests[0].params.messages[0]).toHaveProperty("content");
51
+ });
52
+ it("throws naming the missing custom_id when responses are incomplete", async () => {
53
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "canopy-harness-test-"));
54
+ const requestsPath = path.join(tmpDir, "requests.json");
55
+ const responsesPath = path.join(tmpDir, "responses.json");
56
+ const provider = new HarnessBatchProvider({ requestsPath, responsesPath });
57
+ await expect(provider.runBatch([makeAgent()], {})).rejects.toThrow();
58
+ fs.writeFileSync(responsesPath, JSON.stringify([{ custom_id: "test-agent-MR", text: "{}" }]));
59
+ await expect(provider.runBatch([makeAgent()], {})).rejects.toThrow(/missing answers for 8 of 9/);
60
+ });
61
+ it("parses a complete responses file into MetricAssessmentResponse[] with no API call", async () => {
62
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "canopy-harness-test-"));
63
+ const requestsPath = path.join(tmpDir, "requests.json");
64
+ const responsesPath = path.join(tmpDir, "responses.json");
65
+ const provider = new HarnessBatchProvider({ requestsPath, responsesPath });
66
+ await expect(provider.runBatch([makeAgent()], {})).rejects.toThrow();
67
+ const requests = JSON.parse(fs.readFileSync(requestsPath, "utf8"));
68
+ const responses = requests.map((r) => ({
69
+ custom_id: r.custom_id,
70
+ text: JSON.stringify({
71
+ metricCode: r.custom_id.split("-").pop(),
72
+ subCategoryScores: { "Test Sub-Category": "High" },
73
+ findings: ["a finding"],
74
+ deploymentBlocker: false,
75
+ }),
76
+ }));
77
+ fs.writeFileSync(responsesPath, JSON.stringify(responses));
78
+ const result = await provider.runBatch([makeAgent()], {});
79
+ expect(result.length).toBe(9);
80
+ expect(result.every((r) => r.agentId === "test-agent")).toBe(true);
81
+ expect(result.some((r) => r.subCategoryScores["Test Sub-Category"] === "High")).toBe(true);
82
+ });
83
+ });
84
+ //# sourceMappingURL=harness.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness.test.js","sourceRoot":"","sources":["../../../src/batch/providers/harness.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * BatchProvider factory.
3
+ *
4
+ * Mirrors `createProvider()` in `src/providers/index.ts`. Pass a config object
5
+ * with `type` set to the desired backend; all other fields are provider-specific.
6
+ *
7
+ * @example
8
+ * // Bedrock (live)
9
+ * const provider = createBatchProvider({
10
+ * type: "bedrock",
11
+ * s3Bucket: "my-canopy-bucket",
12
+ * roleArn: "arn:aws:iam::123456789012:role/CanopyBatchRole",
13
+ * });
14
+ *
15
+ * // Anthropic (stub — API submission pending)
16
+ * const provider = createBatchProvider({
17
+ * type: "anthropic",
18
+ * model: "claude-haiku-4-5-20251001",
19
+ * });
20
+ *
21
+ * // Harness — no API key, the calling LLM coding agent answers the prompts
22
+ * const provider = createBatchProvider({
23
+ * type: "harness",
24
+ * requestsPath: "output/batch-requests.json",
25
+ * responsesPath: "output/batch-responses.json",
26
+ * });
27
+ *
28
+ * // BYO provider
29
+ * const provider: BatchProvider = {
30
+ * name: "my-provider",
31
+ * runBatch: async (agents, opts) => { ... },
32
+ * };
33
+ */
34
+ import { type AnthropicBatchConfig } from "./anthropic.js";
35
+ import { type OllamaBatchConfig } from "./ollama.js";
36
+ import { type HarnessBatchConfig } from "./harness.js";
37
+ import type { BedrockBatchConfig, BatchProvider } from "../types.js";
38
+ export type { BatchProvider } from "../types.js";
39
+ export { BedrockBatchProvider } from "./bedrock.js";
40
+ export { AnthropicBatchProvider } from "./anthropic.js";
41
+ export { OllamaBatchProvider } from "./ollama.js";
42
+ export { HarnessBatchProvider } from "./harness.js";
43
+ export type { AnthropicBatchConfig } from "./anthropic.js";
44
+ export type { OllamaBatchConfig } from "./ollama.js";
45
+ export type { HarnessBatchConfig } from "./harness.js";
46
+ export type BedrockBatchProviderConfig = BedrockBatchConfig & {
47
+ type: "bedrock";
48
+ };
49
+ export type AnthropicBatchProviderConfig = AnthropicBatchConfig & {
50
+ type: "anthropic";
51
+ };
52
+ export type OllamaBatchProviderConfig = OllamaBatchConfig & {
53
+ type: "ollama";
54
+ };
55
+ export type HarnessBatchProviderConfig = HarnessBatchConfig & {
56
+ type: "harness";
57
+ };
58
+ export type BatchProviderConfig = BedrockBatchProviderConfig | AnthropicBatchProviderConfig | OllamaBatchProviderConfig | HarnessBatchProviderConfig;
59
+ /**
60
+ * Create a BatchProvider from a config object.
61
+ *
62
+ * @param config Discriminated union with `type: "bedrock" | "anthropic" | "ollama" | "harness"`.
63
+ * @returns A BatchProvider ready to pass to `assessWorkflow()`.
64
+ *
65
+ * @example
66
+ * // Bedrock (AWS)
67
+ * createBatchProvider({ type: "bedrock", s3Bucket: "...", roleArn: "..." })
68
+ *
69
+ * // Anthropic Messages Batches (stub — pending API wiring)
70
+ * createBatchProvider({ type: "anthropic", model: "claude-haiku-4-5-20251001" })
71
+ *
72
+ * // Ollama local
73
+ * createBatchProvider({ type: "ollama", model: "llama3.2" })
74
+ *
75
+ * // Ollama cloud
76
+ * createBatchProvider({ type: "ollama", model: "llama3.2", baseUrl: "https://ollama.com/api", apiKey: "..." })
77
+ *
78
+ * // Harness — the calling LLM coding agent fills the prompts itself, no API key
79
+ * createBatchProvider({ type: "harness", requestsPath: "...", responsesPath: "..." })
80
+ */
81
+ export declare function createBatchProvider(config: BatchProviderConfig): BatchProvider;
82
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/batch/providers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAGH,OAAO,EAA0B,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACnF,OAAO,EAAuB,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAwB,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAC7E,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAErE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,YAAY,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC3D,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,YAAY,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAIvD,MAAM,MAAM,0BAA0B,GAAG,kBAAkB,GAAG;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAClF,MAAM,MAAM,4BAA4B,GAAG,oBAAoB,GAAG;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC;AACxF,MAAM,MAAM,yBAAyB,GAAG,iBAAiB,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAC/E,MAAM,MAAM,0BAA0B,GAAG,kBAAkB,GAAG;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAElF,MAAM,MAAM,mBAAmB,GAC3B,0BAA0B,GAC1B,4BAA4B,GAC5B,yBAAyB,GACzB,0BAA0B,CAAC;AAI/B;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,aAAa,CAgB9E"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * BatchProvider factory.
3
+ *
4
+ * Mirrors `createProvider()` in `src/providers/index.ts`. Pass a config object
5
+ * with `type` set to the desired backend; all other fields are provider-specific.
6
+ *
7
+ * @example
8
+ * // Bedrock (live)
9
+ * const provider = createBatchProvider({
10
+ * type: "bedrock",
11
+ * s3Bucket: "my-canopy-bucket",
12
+ * roleArn: "arn:aws:iam::123456789012:role/CanopyBatchRole",
13
+ * });
14
+ *
15
+ * // Anthropic (stub — API submission pending)
16
+ * const provider = createBatchProvider({
17
+ * type: "anthropic",
18
+ * model: "claude-haiku-4-5-20251001",
19
+ * });
20
+ *
21
+ * // Harness — no API key, the calling LLM coding agent answers the prompts
22
+ * const provider = createBatchProvider({
23
+ * type: "harness",
24
+ * requestsPath: "output/batch-requests.json",
25
+ * responsesPath: "output/batch-responses.json",
26
+ * });
27
+ *
28
+ * // BYO provider
29
+ * const provider: BatchProvider = {
30
+ * name: "my-provider",
31
+ * runBatch: async (agents, opts) => { ... },
32
+ * };
33
+ */
34
+ import { BedrockBatchProvider } from "./bedrock.js";
35
+ import { AnthropicBatchProvider } from "./anthropic.js";
36
+ import { OllamaBatchProvider } from "./ollama.js";
37
+ import { HarnessBatchProvider } from "./harness.js";
38
+ export { BedrockBatchProvider } from "./bedrock.js";
39
+ export { AnthropicBatchProvider } from "./anthropic.js";
40
+ export { OllamaBatchProvider } from "./ollama.js";
41
+ export { HarnessBatchProvider } from "./harness.js";
42
+ // ── Factory ──────────────────────────────────────────────────────────────────
43
+ /**
44
+ * Create a BatchProvider from a config object.
45
+ *
46
+ * @param config Discriminated union with `type: "bedrock" | "anthropic" | "ollama" | "harness"`.
47
+ * @returns A BatchProvider ready to pass to `assessWorkflow()`.
48
+ *
49
+ * @example
50
+ * // Bedrock (AWS)
51
+ * createBatchProvider({ type: "bedrock", s3Bucket: "...", roleArn: "..." })
52
+ *
53
+ * // Anthropic Messages Batches (stub — pending API wiring)
54
+ * createBatchProvider({ type: "anthropic", model: "claude-haiku-4-5-20251001" })
55
+ *
56
+ * // Ollama local
57
+ * createBatchProvider({ type: "ollama", model: "llama3.2" })
58
+ *
59
+ * // Ollama cloud
60
+ * createBatchProvider({ type: "ollama", model: "llama3.2", baseUrl: "https://ollama.com/api", apiKey: "..." })
61
+ *
62
+ * // Harness — the calling LLM coding agent fills the prompts itself, no API key
63
+ * createBatchProvider({ type: "harness", requestsPath: "...", responsesPath: "..." })
64
+ */
65
+ export function createBatchProvider(config) {
66
+ const { type, ...rest } = config;
67
+ switch (type) {
68
+ case "bedrock":
69
+ return new BedrockBatchProvider(rest);
70
+ case "anthropic":
71
+ return new AnthropicBatchProvider(rest);
72
+ case "ollama":
73
+ return new OllamaBatchProvider(rest);
74
+ case "harness":
75
+ return new HarnessBatchProvider(rest);
76
+ default: {
77
+ const exhaustive = type;
78
+ throw new Error(`createBatchProvider: unknown provider type "${exhaustive}"`);
79
+ }
80
+ }
81
+ }
82
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/batch/providers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAA6B,MAAM,gBAAgB,CAAC;AACnF,OAAO,EAAE,mBAAmB,EAA0B,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAA2B,MAAM,cAAc,CAAC;AAI7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAkBpD,gFAAgF;AAEhF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAA2B;IAC7D,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC;IACjC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,SAAS;YACZ,OAAO,IAAI,oBAAoB,CAAC,IAA0B,CAAC,CAAC;QAC9D,KAAK,WAAW;YACd,OAAO,IAAI,sBAAsB,CAAC,IAA4B,CAAC,CAAC;QAClE,KAAK,QAAQ;YACX,OAAO,IAAI,mBAAmB,CAAC,IAAyB,CAAC,CAAC;QAC5D,KAAK,SAAS;YACZ,OAAO,IAAI,oBAAoB,CAAC,IAA0B,CAAC,CAAC;QAC9D,OAAO,CAAC,CAAC,CAAC;YACR,MAAM,UAAU,GAAU,IAAI,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,+CAA+C,UAAoB,GAAG,CAAC,CAAC;QAC1F,CAAC;IACH,CAAC;AACH,CAAC"}