@wardby/cli 0.1.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 (412) hide show
  1. package/.env.example +131 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +2 -0
  4. package/README.md +282 -0
  5. package/bin/wardby.js +3 -0
  6. package/deploy/local/docker-compose.yml +19 -0
  7. package/dist/claude-coding-worker/driver.d.ts +70 -0
  8. package/dist/claude-coding-worker/driver.js +128 -0
  9. package/dist/claude-coding-worker/main.d.ts +2 -0
  10. package/dist/claude-coding-worker/main.js +41 -0
  11. package/dist/claude-coding-worker/sdk.d.ts +4 -0
  12. package/dist/claude-coding-worker/sdk.js +43 -0
  13. package/dist/claude-coding-worker/tool-relay.d.ts +1 -0
  14. package/dist/claude-coding-worker/tool-relay.js +9 -0
  15. package/dist/cli-help.d.ts +1 -0
  16. package/dist/cli-help.js +20 -0
  17. package/dist/cli.d.ts +18 -0
  18. package/dist/cli.js +629 -0
  19. package/dist/coding/observability.d.ts +59 -0
  20. package/dist/coding/observability.js +77 -0
  21. package/dist/coding/profile.d.ts +88 -0
  22. package/dist/coding/profile.js +137 -0
  23. package/dist/coding/protocol.d.ts +345 -0
  24. package/dist/coding/protocol.js +445 -0
  25. package/dist/coding/provider.d.ts +4 -0
  26. package/dist/coding/provider.js +18 -0
  27. package/dist/coding-proxy/main.d.ts +1 -0
  28. package/dist/coding-proxy/main.js +51 -0
  29. package/dist/coding-worker/artifact.d.ts +16 -0
  30. package/dist/coding-worker/artifact.js +37 -0
  31. package/dist/coding-worker/driver.d.ts +46 -0
  32. package/dist/coding-worker/driver.js +158 -0
  33. package/dist/coding-worker/errors.d.ts +1 -0
  34. package/dist/coding-worker/errors.js +23 -0
  35. package/dist/coding-worker/isolation-probe.d.ts +1 -0
  36. package/dist/coding-worker/isolation-probe.js +146 -0
  37. package/dist/coding-worker/keeper.d.ts +4 -0
  38. package/dist/coding-worker/keeper.js +29 -0
  39. package/dist/coding-worker/main.d.ts +2 -0
  40. package/dist/coding-worker/main.js +43 -0
  41. package/dist/coding-worker/sdk.d.ts +26 -0
  42. package/dist/coding-worker/sdk.js +28 -0
  43. package/dist/coding-worker/types.d.ts +64 -0
  44. package/dist/coding-worker/types.js +1 -0
  45. package/dist/config/providers.d.ts +158 -0
  46. package/dist/config/providers.js +162 -0
  47. package/dist/core/budget-groups.d.ts +72 -0
  48. package/dist/core/budget-groups.js +149 -0
  49. package/dist/core/budget.d.ts +63 -0
  50. package/dist/core/budget.js +69 -0
  51. package/dist/core/coding-queue.d.ts +32 -0
  52. package/dist/core/coding-queue.js +54 -0
  53. package/dist/core/cron.d.ts +31 -0
  54. package/dist/core/cron.js +43 -0
  55. package/dist/core/datastores.d.ts +41 -0
  56. package/dist/core/datastores.js +105 -0
  57. package/dist/core/db.d.ts +2 -0
  58. package/dist/core/db.js +2 -0
  59. package/dist/core/dispatch.d.ts +81 -0
  60. package/dist/core/dispatch.js +184 -0
  61. package/dist/core/engine-native.d.ts +29 -0
  62. package/dist/core/engine-native.js +259 -0
  63. package/dist/core/http-runtime.d.ts +7 -0
  64. package/dist/core/http-runtime.js +101 -0
  65. package/dist/core/lease.d.ts +13 -0
  66. package/dist/core/lease.js +22 -0
  67. package/dist/core/logger.d.ts +13 -0
  68. package/dist/core/logger.js +45 -0
  69. package/dist/core/memory-tools.d.ts +11 -0
  70. package/dist/core/memory-tools.js +122 -0
  71. package/dist/core/reconciler.d.ts +45 -0
  72. package/dist/core/reconciler.js +152 -0
  73. package/dist/core/runner.d.ts +87 -0
  74. package/dist/core/runner.js +529 -0
  75. package/dist/core/scheduler.d.ts +47 -0
  76. package/dist/core/scheduler.js +121 -0
  77. package/dist/core/secrets.d.ts +46 -0
  78. package/dist/core/secrets.js +100 -0
  79. package/dist/core/subagent-memory-tools.d.ts +18 -0
  80. package/dist/core/subagent-memory-tools.js +121 -0
  81. package/dist/core/timing.d.ts +7 -0
  82. package/dist/core/timing.js +7 -0
  83. package/dist/core/webhooks.d.ts +23 -0
  84. package/dist/core/webhooks.js +113 -0
  85. package/dist/env.d.ts +11 -0
  86. package/dist/env.js +13 -0
  87. package/dist/import/budgets.d.ts +16 -0
  88. package/dist/import/budgets.js +21 -0
  89. package/dist/import/bundle.d.ts +16 -0
  90. package/dist/import/bundle.js +61 -0
  91. package/dist/import/cli-args.d.ts +2 -0
  92. package/dist/import/cli-args.js +44 -0
  93. package/dist/import/create.d.ts +34 -0
  94. package/dist/import/create.js +363 -0
  95. package/dist/import/index.d.ts +25 -0
  96. package/dist/import/index.js +130 -0
  97. package/dist/import/model-gate.d.ts +1 -0
  98. package/dist/import/model-gate.js +3 -0
  99. package/dist/import/neutral-schema.d.ts +369 -0
  100. package/dist/import/neutral-schema.js +109 -0
  101. package/dist/import/preflight.d.ts +41 -0
  102. package/dist/import/preflight.js +71 -0
  103. package/dist/import/report.d.ts +5 -0
  104. package/dist/import/report.js +98 -0
  105. package/dist/import/tool-scan.d.ts +8 -0
  106. package/dist/import/tool-scan.js +20 -0
  107. package/dist/mcp/auth/ownership.d.ts +113 -0
  108. package/dist/mcp/auth/ownership.js +87 -0
  109. package/dist/mcp/auth/principal.d.ts +9 -0
  110. package/dist/mcp/auth/principal.js +9 -0
  111. package/dist/mcp/auth/resource-server.d.ts +47 -0
  112. package/dist/mcp/auth/resource-server.js +82 -0
  113. package/dist/mcp/auth/self-hosted/browser.d.ts +3 -0
  114. package/dist/mcp/auth/self-hosted/browser.js +273 -0
  115. package/dist/mcp/auth/self-hosted/cli.d.ts +2 -0
  116. package/dist/mcp/auth/self-hosted/cli.js +39 -0
  117. package/dist/mcp/auth/self-hosted/credentials.d.ts +58 -0
  118. package/dist/mcp/auth/self-hosted/credentials.js +106 -0
  119. package/dist/mcp/auth/self-hosted/rate-limit.d.ts +13 -0
  120. package/dist/mcp/auth/self-hosted/rate-limit.js +20 -0
  121. package/dist/mcp/auth/self-hosted/session.d.ts +36 -0
  122. package/dist/mcp/auth/self-hosted/session.js +110 -0
  123. package/dist/mcp/capabilities.d.ts +11 -0
  124. package/dist/mcp/capabilities.js +10 -0
  125. package/dist/mcp/context.d.ts +46 -0
  126. package/dist/mcp/context.js +1 -0
  127. package/dist/mcp/errors.d.ts +13 -0
  128. package/dist/mcp/errors.js +22 -0
  129. package/dist/mcp/index.d.ts +32 -0
  130. package/dist/mcp/index.js +187 -0
  131. package/dist/mcp/jsonrpc.d.ts +8 -0
  132. package/dist/mcp/jsonrpc.js +1 -0
  133. package/dist/mcp/server.d.ts +107 -0
  134. package/dist/mcp/server.js +203 -0
  135. package/dist/mcp/tasks/manager.d.ts +63 -0
  136. package/dist/mcp/tasks/manager.js +103 -0
  137. package/dist/mcp/tools/agents.d.ts +2 -0
  138. package/dist/mcp/tools/agents.js +375 -0
  139. package/dist/mcp/tools/budget-groups.d.ts +2 -0
  140. package/dist/mcp/tools/budget-groups.js +136 -0
  141. package/dist/mcp/tools/datastore.d.ts +2 -0
  142. package/dist/mcp/tools/datastore.js +217 -0
  143. package/dist/mcp/tools/memory.d.ts +3 -0
  144. package/dist/mcp/tools/memory.js +60 -0
  145. package/dist/mcp/tools/models.d.ts +8 -0
  146. package/dist/mcp/tools/models.js +15 -0
  147. package/dist/mcp/tools/runs.d.ts +2 -0
  148. package/dist/mcp/tools/runs.js +61 -0
  149. package/dist/mcp/tools/scheduling.d.ts +2 -0
  150. package/dist/mcp/tools/scheduling.js +48 -0
  151. package/dist/mcp/tools/secret-elicitation-form.d.ts +22 -0
  152. package/dist/mcp/tools/secret-elicitation-form.js +93 -0
  153. package/dist/mcp/tools/secret-elicitation-server.d.ts +5 -0
  154. package/dist/mcp/tools/secret-elicitation-server.js +57 -0
  155. package/dist/mcp/tools/secret-elicitation.d.ts +38 -0
  156. package/dist/mcp/tools/secret-elicitation.js +52 -0
  157. package/dist/mcp/tools/secrets.d.ts +13 -0
  158. package/dist/mcp/tools/secrets.js +124 -0
  159. package/dist/mcp/tools/subagents.d.ts +2 -0
  160. package/dist/mcp/tools/subagents.js +133 -0
  161. package/dist/mcp/tools/text-result.d.ts +6 -0
  162. package/dist/mcp/tools/text-result.js +3 -0
  163. package/dist/mcp/tools/tools.d.ts +2 -0
  164. package/dist/mcp/tools/tools.js +211 -0
  165. package/dist/mcp/tools/trigger.d.ts +2 -0
  166. package/dist/mcp/tools/trigger.js +120 -0
  167. package/dist/mcp/tools/webhooks.d.ts +2 -0
  168. package/dist/mcp/tools/webhooks.js +34 -0
  169. package/dist/mcp/transport/http-limits.d.ts +17 -0
  170. package/dist/mcp/transport/http-limits.js +92 -0
  171. package/dist/mcp/transport/stdio.d.ts +23 -0
  172. package/dist/mcp/transport/stdio.js +6 -0
  173. package/dist/mcp/transport/streamable-http.d.ts +34 -0
  174. package/dist/mcp/transport/streamable-http.js +158 -0
  175. package/dist/mcp/unattended-schedules.d.ts +15 -0
  176. package/dist/mcp/unattended-schedules.js +21 -0
  177. package/dist/mcp/webhooks/ingress.d.ts +17 -0
  178. package/dist/mcp/webhooks/ingress.js +33 -0
  179. package/dist/observability/config.d.ts +6 -0
  180. package/dist/observability/config.js +20 -0
  181. package/dist/observability/metrics-server.d.ts +11 -0
  182. package/dist/observability/metrics-server.js +47 -0
  183. package/dist/observability/metrics.d.ts +36 -0
  184. package/dist/observability/metrics.js +158 -0
  185. package/dist/providers/auth/authorization-server.d.ts +41 -0
  186. package/dist/providers/auth/authorization-server.js +1 -0
  187. package/dist/providers/auth/delegating.d.ts +44 -0
  188. package/dist/providers/auth/delegating.js +105 -0
  189. package/dist/providers/auth/index.d.ts +11 -0
  190. package/dist/providers/auth/index.js +20 -0
  191. package/dist/providers/auth/release-gate.d.ts +1 -0
  192. package/dist/providers/auth/release-gate.js +4 -0
  193. package/dist/providers/auth/self-hosted.d.ts +78 -0
  194. package/dist/providers/auth/self-hosted.js +377 -0
  195. package/dist/providers/auth/subject.d.ts +1 -0
  196. package/dist/providers/auth/subject.js +6 -0
  197. package/dist/providers/auth/types.d.ts +63 -0
  198. package/dist/providers/auth/types.js +22 -0
  199. package/dist/providers/coding-proxy/deny-port.d.ts +5 -0
  200. package/dist/providers/coding-proxy/deny-port.js +45 -0
  201. package/dist/providers/coding-proxy/environment-credentials.d.ts +7 -0
  202. package/dist/providers/coding-proxy/environment-credentials.js +16 -0
  203. package/dist/providers/coding-proxy/index.d.ts +7 -0
  204. package/dist/providers/coding-proxy/index.js +7 -0
  205. package/dist/providers/coding-proxy/memory-ledger.d.ts +17 -0
  206. package/dist/providers/coding-proxy/memory-ledger.js +103 -0
  207. package/dist/providers/coding-proxy/metering.d.ts +20 -0
  208. package/dist/providers/coding-proxy/metering.js +161 -0
  209. package/dist/providers/coding-proxy/prisma-ledger.d.ts +15 -0
  210. package/dist/providers/coding-proxy/prisma-ledger.js +213 -0
  211. package/dist/providers/coding-proxy/proxy.d.ts +75 -0
  212. package/dist/providers/coding-proxy/proxy.js +721 -0
  213. package/dist/providers/coding-proxy/runtime.d.ts +18 -0
  214. package/dist/providers/coding-proxy/runtime.js +39 -0
  215. package/dist/providers/coding-proxy/secure-fetch.d.ts +9 -0
  216. package/dist/providers/coding-proxy/secure-fetch.js +72 -0
  217. package/dist/providers/coding-proxy/server.d.ts +17 -0
  218. package/dist/providers/coding-proxy/server.js +139 -0
  219. package/dist/providers/coding-proxy/types.d.ts +99 -0
  220. package/dist/providers/coding-proxy/types.js +1 -0
  221. package/dist/providers/datastore/index.d.ts +2 -0
  222. package/dist/providers/datastore/index.js +2 -0
  223. package/dist/providers/datastore/postgres.d.ts +20 -0
  224. package/dist/providers/datastore/postgres.js +130 -0
  225. package/dist/providers/datastore/scoped.d.ts +10 -0
  226. package/dist/providers/datastore/scoped.js +46 -0
  227. package/dist/providers/datastore/types.d.ts +31 -0
  228. package/dist/providers/datastore/types.js +7 -0
  229. package/dist/providers/email/types.d.ts +46 -0
  230. package/dist/providers/email/types.js +8 -0
  231. package/dist/providers/engine/index.d.ts +1 -0
  232. package/dist/providers/engine/index.js +1 -0
  233. package/dist/providers/engine/types.d.ts +67 -0
  234. package/dist/providers/engine/types.js +16 -0
  235. package/dist/providers/executor/build.d.ts +6 -0
  236. package/dist/providers/executor/build.js +15 -0
  237. package/dist/providers/executor/composition.d.ts +14 -0
  238. package/dist/providers/executor/composition.js +123 -0
  239. package/dist/providers/executor/container.d.ts +184 -0
  240. package/dist/providers/executor/container.js +936 -0
  241. package/dist/providers/executor/dbos-status.d.ts +50 -0
  242. package/dist/providers/executor/dbos-status.js +64 -0
  243. package/dist/providers/executor/dbos.d.ts +53 -0
  244. package/dist/providers/executor/dbos.js +269 -0
  245. package/dist/providers/executor/in-process.d.ts +18 -0
  246. package/dist/providers/executor/in-process.js +38 -0
  247. package/dist/providers/executor/index.d.ts +8 -0
  248. package/dist/providers/executor/index.js +8 -0
  249. package/dist/providers/executor/routing.d.ts +48 -0
  250. package/dist/providers/executor/routing.js +70 -0
  251. package/dist/providers/executor/types.d.ts +55 -0
  252. package/dist/providers/executor/types.js +1 -0
  253. package/dist/providers/index.d.ts +43 -0
  254. package/dist/providers/index.js +18 -0
  255. package/dist/providers/jobs/docker-isolation.d.ts +166 -0
  256. package/dist/providers/jobs/docker-isolation.js +724 -0
  257. package/dist/providers/jobs/docker.d.ts +127 -0
  258. package/dist/providers/jobs/docker.js +1027 -0
  259. package/dist/providers/jobs/fake-kubernetes-api.d.ts +98 -0
  260. package/dist/providers/jobs/fake-kubernetes-api.js +142 -0
  261. package/dist/providers/jobs/fake.d.ts +23 -0
  262. package/dist/providers/jobs/fake.js +132 -0
  263. package/dist/providers/jobs/kubernetes-api.d.ts +60 -0
  264. package/dist/providers/jobs/kubernetes-api.js +20 -0
  265. package/dist/providers/jobs/kubernetes-client.d.ts +36 -0
  266. package/dist/providers/jobs/kubernetes-client.js +171 -0
  267. package/dist/providers/jobs/kubernetes-dry-run-fixture.d.ts +49 -0
  268. package/dist/providers/jobs/kubernetes-dry-run-fixture.js +141 -0
  269. package/dist/providers/jobs/kubernetes-isolation.d.ts +147 -0
  270. package/dist/providers/jobs/kubernetes-isolation.js +607 -0
  271. package/dist/providers/jobs/kubernetes-platform.d.ts +177 -0
  272. package/dist/providers/jobs/kubernetes-platform.js +280 -0
  273. package/dist/providers/jobs/kubernetes-preflight.d.ts +59 -0
  274. package/dist/providers/jobs/kubernetes-preflight.js +339 -0
  275. package/dist/providers/jobs/kubernetes-witness.d.ts +10 -0
  276. package/dist/providers/jobs/kubernetes-witness.js +193 -0
  277. package/dist/providers/jobs/kubernetes.d.ts +127 -0
  278. package/dist/providers/jobs/kubernetes.js +874 -0
  279. package/dist/providers/jobs/safe-extract.d.ts +9 -0
  280. package/dist/providers/jobs/safe-extract.js +325 -0
  281. package/dist/providers/jobs/types.d.ts +78 -0
  282. package/dist/providers/jobs/types.js +6 -0
  283. package/dist/providers/jobs/workspace-swap.d.ts +2 -0
  284. package/dist/providers/jobs/workspace-swap.js +47 -0
  285. package/dist/providers/llm/anthropic.d.ts +13 -0
  286. package/dist/providers/llm/anthropic.js +21 -0
  287. package/dist/providers/llm/bedrock.d.ts +19 -0
  288. package/dist/providers/llm/bedrock.js +33 -0
  289. package/dist/providers/llm/claude-messages.d.ts +106 -0
  290. package/dist/providers/llm/claude-messages.js +157 -0
  291. package/dist/providers/llm/claude-provider.d.ts +40 -0
  292. package/dist/providers/llm/claude-provider.js +31 -0
  293. package/dist/providers/llm/index.d.ts +10 -0
  294. package/dist/providers/llm/index.js +10 -0
  295. package/dist/providers/llm/openai.d.ts +23 -0
  296. package/dist/providers/llm/openai.js +156 -0
  297. package/dist/providers/llm/pricing-anthropic.d.ts +4 -0
  298. package/dist/providers/llm/pricing-anthropic.js +30 -0
  299. package/dist/providers/llm/pricing-bedrock-claude.d.ts +12 -0
  300. package/dist/providers/llm/pricing-bedrock-claude.js +37 -0
  301. package/dist/providers/llm/pricing-core.d.ts +26 -0
  302. package/dist/providers/llm/pricing-core.js +17 -0
  303. package/dist/providers/llm/pricing.d.ts +30 -0
  304. package/dist/providers/llm/pricing.js +74 -0
  305. package/dist/providers/llm/registration.d.ts +8 -0
  306. package/dist/providers/llm/registration.js +39 -0
  307. package/dist/providers/llm/routing.d.ts +25 -0
  308. package/dist/providers/llm/routing.js +32 -0
  309. package/dist/providers/llm/types.d.ts +85 -0
  310. package/dist/providers/llm/types.js +12 -0
  311. package/dist/providers/memory/index.d.ts +2 -0
  312. package/dist/providers/memory/index.js +2 -0
  313. package/dist/providers/memory/postgres.d.ts +20 -0
  314. package/dist/providers/memory/postgres.js +72 -0
  315. package/dist/providers/memory/types.d.ts +32 -0
  316. package/dist/providers/memory/types.js +17 -0
  317. package/dist/providers/secrets/app-key.d.ts +8 -0
  318. package/dist/providers/secrets/app-key.js +50 -0
  319. package/dist/providers/secrets/index.d.ts +10 -0
  320. package/dist/providers/secrets/index.js +13 -0
  321. package/dist/providers/secrets/transfer-envelope.d.ts +12 -0
  322. package/dist/providers/secrets/transfer-envelope.js +35 -0
  323. package/dist/providers/secrets/types.d.ts +18 -0
  324. package/dist/providers/secrets/types.js +12 -0
  325. package/dist/providers/storage/types.d.ts +18 -0
  326. package/dist/providers/storage/types.js +7 -0
  327. package/dist/providers/vcs/git.d.ts +105 -0
  328. package/dist/providers/vcs/git.js +710 -0
  329. package/dist/providers/vcs/github.d.ts +105 -0
  330. package/dist/providers/vcs/github.js +394 -0
  331. package/dist/providers/vcs/index.d.ts +6 -0
  332. package/dist/providers/vcs/index.js +26 -0
  333. package/dist/providers/vcs/types.d.ts +118 -0
  334. package/dist/providers/vcs/types.js +1 -0
  335. package/dist/sandbox/bounded-json.d.ts +2 -0
  336. package/dist/sandbox/bounded-json.js +36 -0
  337. package/dist/sandbox/bridge.d.ts +15 -0
  338. package/dist/sandbox/bridge.js +78 -0
  339. package/dist/sandbox/eval-core.d.ts +37 -0
  340. package/dist/sandbox/eval-core.js +159 -0
  341. package/dist/sandbox/fetch-policy.d.ts +24 -0
  342. package/dist/sandbox/fetch-policy.js +96 -0
  343. package/dist/sandbox/generated/zod-to-json-schema.bundle.js +5 -0
  344. package/dist/sandbox/generated/zod.bundle.js +1 -0
  345. package/dist/sandbox/host-functions.d.ts +29 -0
  346. package/dist/sandbox/host-functions.js +168 -0
  347. package/dist/sandbox/limits.d.ts +39 -0
  348. package/dist/sandbox/limits.js +39 -0
  349. package/dist/sandbox/parser-worker/__fixtures__/crash.d.ts +1 -0
  350. package/dist/sandbox/parser-worker/__fixtures__/crash.js +6 -0
  351. package/dist/sandbox/parser-worker/__fixtures__/echo.d.ts +1 -0
  352. package/dist/sandbox/parser-worker/__fixtures__/echo.js +5 -0
  353. package/dist/sandbox/parser-worker/__fixtures__/reject.d.ts +1 -0
  354. package/dist/sandbox/parser-worker/__fixtures__/reject.js +5 -0
  355. package/dist/sandbox/parser-worker/__fixtures__/spin-forever.d.ts +1 -0
  356. package/dist/sandbox/parser-worker/__fixtures__/spin-forever.js +11 -0
  357. package/dist/sandbox/parser-worker/pool.d.ts +13 -0
  358. package/dist/sandbox/parser-worker/pool.js +111 -0
  359. package/dist/sandbox/parser-worker/worker.d.ts +14 -0
  360. package/dist/sandbox/parser-worker/worker.js +63 -0
  361. package/dist/sandbox/pii-redaction.d.ts +1 -0
  362. package/dist/sandbox/pii-redaction.js +29 -0
  363. package/dist/sandbox/prelude.d.ts +26 -0
  364. package/dist/sandbox/prelude.js +408 -0
  365. package/dist/sandbox/quickjs-module.d.ts +13 -0
  366. package/dist/sandbox/quickjs-module.js +19 -0
  367. package/dist/sandbox/run-in-sandbox.d.ts +34 -0
  368. package/dist/sandbox/run-in-sandbox.js +53 -0
  369. package/dist/sandbox/safe-fetch.d.ts +26 -0
  370. package/dist/sandbox/safe-fetch.js +140 -0
  371. package/dist/sandbox/tool-capabilities.d.ts +66 -0
  372. package/dist/sandbox/tool-capabilities.js +103 -0
  373. package/dist/sandbox/zod-params.d.ts +22 -0
  374. package/dist/sandbox/zod-params.js +60 -0
  375. package/dist/serve.d.ts +14 -0
  376. package/dist/serve.js +54 -0
  377. package/dist/wardby-bin.d.ts +2 -0
  378. package/dist/wardby-bin.js +20 -0
  379. package/package.json +123 -0
  380. package/prisma/migrations/20260905000000_init/migration.sql +34 -0
  381. package/prisma/migrations/20260905010000_scheduler_durability/migration.sql +31 -0
  382. package/prisma/migrations/20260905020000_tools_multiturn/migration.sql +47 -0
  383. package/prisma/migrations/20260905030000_cache_tool_json_schema/migration.sql +13 -0
  384. package/prisma/migrations/20260906000000_mcp_phase4/migration.sql +115 -0
  385. package/prisma/migrations/20260906010000_run_final_text/migration.sql +7 -0
  386. package/prisma/migrations/20260906020000_run_turns/migration.sql +6 -0
  387. package/prisma/migrations/20260906030000_task_principal_id/migration.sql +5 -0
  388. package/prisma/migrations/20260906040000_secure_self_hosted_oauth/migration.sql +67 -0
  389. package/prisma/migrations/20260906050000_phase5_coding_agents/migration.sql +52 -0
  390. package/prisma/migrations/20260906060000_tool_capability_scoping/migration.sql +22 -0
  391. package/prisma/migrations/20260906070000_datastore_pii_flag/migration.sql +6 -0
  392. package/prisma/migrations/20260906080000_secret_elicitation_outcomes/migration.sql +13 -0
  393. package/prisma/migrations/20260907010000_coding_proxy_ledger/migration.sql +57 -0
  394. package/prisma/migrations/20260907020000_budget_groups/migration.sql +24 -0
  395. package/prisma/migrations/20260907030000_coding_webhook_task_override/migration.sql +4 -0
  396. package/prisma/migrations/20260908010000_run_execution_backend/migration.sql +2 -0
  397. package/prisma/migrations/20260908020000_coding_run_audit_metadata/migration.sql +7 -0
  398. package/prisma/migrations/20260910010000_agent_secret_bound_name/migration.sql +16 -0
  399. package/prisma/migrations/20260911010000_coding_worker_toolchains/migration.sql +5 -0
  400. package/prisma/migrations/20260912010000_coding_provider_contract/migration.sql +24 -0
  401. package/prisma/migrations/20260912020000_coding_proxy_protocol/migration.sql +10 -0
  402. package/prisma/migrations/20260912030000_agent_memory/migration.sql +18 -0
  403. package/prisma/migrations/20260912040000_named_shared_datastores/migration.sql +68 -0
  404. package/prisma/migrations/20260913000000_run_trigger_webhook/migration.sql +2 -0
  405. package/prisma/migrations/20260913010000_agent_sub_agent/migration.sql +32 -0
  406. package/prisma/migrations/20260913020000_run_task_override/migration.sql +5 -0
  407. package/prisma/migrations/20260913030000_coding_run_root/migration.sql +11 -0
  408. package/prisma/migrations/20260922010000_coding_run_queued_at/migration.sql +8 -0
  409. package/prisma/migrations/20260922020000_coding_workspace_disk/migration.sql +8 -0
  410. package/prisma/migrations/migration_lock.toml +3 -0
  411. package/prisma/schema.prisma +723 -0
  412. package/scripts/git-askpass.sh +11 -0
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Static price + tokenizer table for the budget guardrail.
3
+ *
4
+ * Sourced from OpenAI's public pricing page at write time. Deliberately
5
+ * static (no pricing API call) so `priceUsd` stays synchronous and
6
+ * network-free — the budget math must work offline and in tests. An unknown
7
+ * model throws rather than silently pricing at zero, so a misconfigured
8
+ * agent can never bypass the budget guardrail by accident.
9
+ *
10
+ * `encoding` is here too (not just price) because it drives which
11
+ * `gpt-tokenizer` BPE table `countTokens` uses — every gpt-4o-and-later
12
+ * model uses `o200k_base`, not the older `cl100k_base` gpt-tokenizer
13
+ * defaults to. Keeping both in one table means a model can't be priced
14
+ * without also being told which tokenizer estimates its input cost.
15
+ *
16
+ * `cachedInputPerMTok` / `cacheWritePerMTok` are optional: not every model's
17
+ * entry carries verified cache rates. When a model has cached or
18
+ * cache-write tokens but no rate for them, `priceUsd` falls back to the
19
+ * full (non-cached) input rate — the same fail-toward-overestimate
20
+ * direction as the unknown-model error, never fail-toward-underestimate.
21
+ */
22
+ import { computeCost } from "./pricing-core.js";
23
+ export { computeCost } from "./pricing-core.js";
24
+ /** Bump whenever a rate changes so durable reservations retain their original terms. */
25
+ export const PRICING_VERSION = "2026-09-06";
26
+ const PRICING = {
27
+ "gpt-4o": { encoding: "o200k_base", inputPerMTok: 2.5, cachedInputPerMTok: 1.25, outputPerMTok: 10.0 },
28
+ "gpt-4o-mini": { encoding: "o200k_base", inputPerMTok: 0.15, cachedInputPerMTok: 0.075, outputPerMTok: 0.6 },
29
+ "gpt-4.1": { encoding: "o200k_base", inputPerMTok: 2.0, cachedInputPerMTok: 0.5, outputPerMTok: 8.0 },
30
+ "gpt-4.1-mini": { encoding: "o200k_base", inputPerMTok: 0.4, cachedInputPerMTok: 0.1, outputPerMTok: 1.6 },
31
+ "gpt-4.1-nano": { encoding: "o200k_base", inputPerMTok: 0.1, cachedInputPerMTok: 0.025, outputPerMTok: 0.4 },
32
+ "gpt-6-astra": {
33
+ encoding: "o200k_base",
34
+ inputPerMTok: 10.0,
35
+ cachedInputPerMTok: 1.0,
36
+ cacheWritePerMTok: 12.5,
37
+ outputPerMTok: 50.0,
38
+ },
39
+ "gpt-5.6-sol": {
40
+ encoding: "o200k_base",
41
+ inputPerMTok: 4.0,
42
+ cachedInputPerMTok: 0.4,
43
+ cacheWritePerMTok: 5.0,
44
+ outputPerMTok: 20.0,
45
+ },
46
+ "gpt-5.6-terra": {
47
+ encoding: "o200k_base",
48
+ inputPerMTok: 2.0,
49
+ cachedInputPerMTok: 0.2,
50
+ cacheWritePerMTok: 2.5,
51
+ outputPerMTok: 12.0,
52
+ },
53
+ "gpt-5.6-luna": {
54
+ encoding: "o200k_base",
55
+ inputPerMTok: 0.2,
56
+ cachedInputPerMTok: 0.02,
57
+ cacheWritePerMTok: 0.25,
58
+ outputPerMTok: 1.2,
59
+ },
60
+ };
61
+ /** Looks up a model's pricing/tokenizer entry, or throws (fail closed). */
62
+ export function getModelPricing(model) {
63
+ const pricing = PRICING[model];
64
+ if (!pricing) {
65
+ throw new Error(`No pricing entry for model "${model}" — refusing to price at zero. ` + `Add it to src/providers/llm/pricing.ts.`);
66
+ }
67
+ return pricing;
68
+ }
69
+ export function supportedModels() {
70
+ return Object.keys(PRICING);
71
+ }
72
+ export function priceUsd(model, usage) {
73
+ return computeCost(getModelPricing(model), usage);
74
+ }
@@ -0,0 +1,8 @@
1
+ import type { LlmRegistration } from "./routing.js";
2
+ export type LlmRegistrationResult = {
3
+ kind: "registrations";
4
+ registrations: LlmRegistration[];
5
+ } | {
6
+ kind: "no-credentials";
7
+ };
8
+ export declare function resolveLlmRegistrations(env?: NodeJS.ProcessEnv): LlmRegistrationResult;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Enable-by-credential decision logic for the LLM seam: which adapters to
3
+ * wire into RoutingLlmProvider, given environment credentials.
4
+ *
5
+ * Pure — no `fail()`/`process.exit` — so the CLI's `buildLlmProvider()` can
6
+ * stay a thin wrapper that translates each outcome to `fail()`, while this
7
+ * branching (which adapters to register) is unit-testable on its own.
8
+ *
9
+ * All three adapters register additively, purely by credential presence —
10
+ * OpenAI, direct Anthropic, and Bedrock-Claude can all be active in one
11
+ * deployment at once. An agent's `model` field (routed by RoutingLlmProvider)
12
+ * picks which one handles its calls; there is no exclusive global mode.
13
+ */
14
+ import { OpenAiLlmProvider, openaiCredentialsPresent } from "./openai.js";
15
+ import { supportedModels as openaiSupportedModels } from "./pricing.js";
16
+ import { AnthropicLlmProvider, anthropicCredentialsPresent, anthropicSupportedModels } from "./anthropic.js";
17
+ import { BedrockClaudeLlmProvider, bedrockCredentialsPresent, bedrockClaudeSupportedModels } from "./bedrock.js";
18
+ export function resolveLlmRegistrations(env = process.env) {
19
+ const registrations = [];
20
+ if (openaiCredentialsPresent(env)) {
21
+ registrations.push({ provider: new OpenAiLlmProvider(env.OPENAI_API_KEY), models: openaiSupportedModels() });
22
+ }
23
+ if (anthropicCredentialsPresent(env)) {
24
+ registrations.push({
25
+ provider: new AnthropicLlmProvider(env.ANTHROPIC_API_KEY),
26
+ models: anthropicSupportedModels(),
27
+ });
28
+ }
29
+ if (bedrockCredentialsPresent(env)) {
30
+ registrations.push({
31
+ provider: new BedrockClaudeLlmProvider(env.BEDROCK_REGION ?? env.AWS_REGION),
32
+ models: bedrockClaudeSupportedModels(),
33
+ });
34
+ }
35
+ if (registrations.length === 0) {
36
+ return { kind: "no-credentials" };
37
+ }
38
+ return { kind: "registrations", registrations };
39
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Model->provider routing. Becomes the single ProviderRegistry.llm and
3
+ * dispatches each call to the adapter that owns `model`, so per-agent model
4
+ * selection (Agent.model) selects the provider too — GPT and Claude agents
5
+ * run in one deployment. Unknown model / duplicate registration fail closed.
6
+ */
7
+ import type { LlmMessage, LlmProvider, LlmRequest, LlmStreamEvent, LlmToolDef } from "./types.js";
8
+ export interface LlmRegistration {
9
+ provider: LlmProvider;
10
+ models: string[];
11
+ }
12
+ export declare class RoutingLlmProvider implements LlmProvider {
13
+ private readonly byModel;
14
+ constructor(registrations: LlmRegistration[]);
15
+ listModels(): string[];
16
+ private resolve;
17
+ stream(req: LlmRequest, signal?: AbortSignal): AsyncIterable<LlmStreamEvent>;
18
+ countTokens(model: string, messages: LlmMessage[], tools?: LlmToolDef[]): Promise<number>;
19
+ priceUsd(model: string, usage: {
20
+ inputTokens: number;
21
+ outputTokens: number;
22
+ cachedInputTokens?: number;
23
+ cacheWriteTokens?: number;
24
+ }): number;
25
+ }
@@ -0,0 +1,32 @@
1
+ export class RoutingLlmProvider {
2
+ byModel = new Map();
3
+ constructor(registrations) {
4
+ for (const reg of registrations) {
5
+ for (const model of reg.models) {
6
+ if (this.byModel.has(model)) {
7
+ throw new Error(`Model "${model}" is registered by more than one LLM provider — check the routing configuration.`);
8
+ }
9
+ this.byModel.set(model, reg.provider);
10
+ }
11
+ }
12
+ }
13
+ listModels() {
14
+ return [...this.byModel.keys()];
15
+ }
16
+ resolve(model) {
17
+ const provider = this.byModel.get(model);
18
+ if (!provider) {
19
+ throw new Error(`No LLM provider is registered for model "${model}". Known models: ${[...this.byModel.keys()].join(", ") || "(none)"}.`);
20
+ }
21
+ return provider;
22
+ }
23
+ stream(req, signal) {
24
+ return this.resolve(req.model).stream(req, signal);
25
+ }
26
+ countTokens(model, messages, tools) {
27
+ return this.resolve(model).countTokens(model, messages, tools);
28
+ }
29
+ priceUsd(model, usage) {
30
+ return this.resolve(model).priceUsd(model, usage);
31
+ }
32
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * LLM seam — streaming chat with tool-calling and usage accounting.
3
+ *
4
+ * The budget guardrail (wardby's differentiator) hangs off `countTokens`
5
+ * and `priceUsd`: the core estimates cost pre-flight and can stop a run
6
+ * *before* it incurs spend, not just report spend after the fact.
7
+ *
8
+ * Default adapter: OpenAiLlmProvider. Anthropic adapter: AnthropicLlmProvider.
9
+ * Selected per-agent by RoutingLlmProvider (Agent.model -> provider).
10
+ * Bedrock-hosted Claude is a reserved future adapter (shared claude-messages.ts core).
11
+ */
12
+ export interface LlmMessage {
13
+ role: "system" | "user" | "assistant" | "tool";
14
+ content: string;
15
+ /** Set on `role: "tool"` messages to correlate with the originating call. */
16
+ toolCallId?: string;
17
+ /** Optional tool/function name (for tool results or named messages). */
18
+ name?: string;
19
+ /**
20
+ * Set on an `role: "assistant"` message that made tool calls. Providers
21
+ * require the assistant message preceding tool-result messages to
22
+ * replay the calls it made — omitting this on a follow-up turn breaks
23
+ * the conversation, since the provider can no longer correlate the
24
+ * `role: "tool"` results that follow it.
25
+ */
26
+ toolCalls?: {
27
+ id: string;
28
+ name: string;
29
+ argsJson: string;
30
+ }[];
31
+ }
32
+ export interface LlmToolDef {
33
+ name: string;
34
+ description: string;
35
+ /** JSON Schema for the tool's parameters. */
36
+ parameters: Record<string, unknown>;
37
+ }
38
+ export interface LlmRequest {
39
+ model: string;
40
+ messages: LlmMessage[];
41
+ tools?: LlmToolDef[];
42
+ maxTokens?: number;
43
+ temperature?: number;
44
+ stopSequences?: string[];
45
+ }
46
+ export interface LlmUsage {
47
+ /** Total input tokens, including any served from cache. */
48
+ inputTokens: number;
49
+ outputTokens: number;
50
+ /** Subset of `inputTokens` served from a provider-side prompt cache, if reported. */
51
+ cachedInputTokens?: number;
52
+ /** Tokens billed for writing a new prompt-cache entry, if the provider charges for it. */
53
+ cacheWriteTokens?: number;
54
+ costUsd: number;
55
+ }
56
+ export type LlmStreamEvent = {
57
+ type: "text";
58
+ delta: string;
59
+ } | {
60
+ type: "tool_call";
61
+ id: string;
62
+ name: string;
63
+ argsJson: string;
64
+ } | {
65
+ type: "done";
66
+ stopReason: string;
67
+ usage: LlmUsage;
68
+ };
69
+ export interface LlmProvider {
70
+ stream(req: LlmRequest, signal?: AbortSignal): AsyncIterable<LlmStreamEvent>;
71
+ /**
72
+ * Pre-flight token count for budget enforcement. `tools`, when passed,
73
+ * must be counted too — a provider bills the serialized tool schemas as
74
+ * input tokens alongside the messages, so an estimate that ignores them
75
+ * under-counts by however large the attached tool roster is.
76
+ */
77
+ countTokens(model: string, messages: LlmMessage[], tools?: LlmToolDef[]): Promise<number>;
78
+ /** Deterministic price for a given token usage (no network call). */
79
+ priceUsd(model: string, usage: {
80
+ inputTokens: number;
81
+ outputTokens: number;
82
+ cachedInputTokens?: number;
83
+ cacheWriteTokens?: number;
84
+ }): number;
85
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * LLM seam — streaming chat with tool-calling and usage accounting.
3
+ *
4
+ * The budget guardrail (wardby's differentiator) hangs off `countTokens`
5
+ * and `priceUsd`: the core estimates cost pre-flight and can stop a run
6
+ * *before* it incurs spend, not just report spend after the fact.
7
+ *
8
+ * Default adapter: OpenAiLlmProvider. Anthropic adapter: AnthropicLlmProvider.
9
+ * Selected per-agent by RoutingLlmProvider (Agent.model -> provider).
10
+ * Bedrock-hosted Claude is a reserved future adapter (shared claude-messages.ts core).
11
+ */
12
+ export {};
@@ -0,0 +1,2 @@
1
+ export * from "./types.js";
2
+ export * from "./postgres.js";
@@ -0,0 +1,2 @@
1
+ export * from "./types.js";
2
+ export * from "./postgres.js";
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Postgres-backed default AgentMemory adapter, via the `AgentMemory` table.
3
+ * `content`/`contentTsv` are always written together in one raw statement
4
+ * (`contentTsv` is an `Unsupported("tsvector")` column — unreachable through
5
+ * Prisma Client, and deliberately not a Postgres GENERATED column; see
6
+ * schema.prisma). Every other operation goes through the normal Prisma
7
+ * Client since it never touches `contentTsv`.
8
+ */
9
+ import type { PrismaClient } from "@prisma/client";
10
+ import type { AgentMemorySearchHit, AgentMemoryStore } from "./types.js";
11
+ export type AgentMemoryDb = Pick<PrismaClient, "agentMemory" | "$executeRaw" | "$queryRaw">;
12
+ export declare class PostgresAgentMemory implements AgentMemoryStore {
13
+ private readonly db;
14
+ constructor(db: AgentMemoryDb);
15
+ get(agentId: string, key: string): Promise<string | undefined>;
16
+ set(agentId: string, key: string, content: string): Promise<void>;
17
+ list(agentId: string): Promise<string[]>;
18
+ search(agentId: string, query: string, limit?: number): Promise<AgentMemorySearchHit[]>;
19
+ delete(agentId: string, key: string): Promise<void>;
20
+ }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Postgres-backed default AgentMemory adapter, via the `AgentMemory` table.
3
+ * `content`/`contentTsv` are always written together in one raw statement
4
+ * (`contentTsv` is an `Unsupported("tsvector")` column — unreachable through
5
+ * Prisma Client, and deliberately not a Postgres GENERATED column; see
6
+ * schema.prisma). Every other operation goes through the normal Prisma
7
+ * Client since it never touches `contentTsv`.
8
+ */
9
+ import { MEMORY_CONTENT_MAX_BYTES, MEMORY_KEY_MAX_BYTES, MEMORY_MAX_KEYS_PER_AGENT, MEMORY_SEARCH_DEFAULT_LIMIT, MEMORY_SEARCH_MAX_LIMIT, } from "./types.js";
10
+ function checkKey(key) {
11
+ if (typeof key !== "string" || Buffer.byteLength(key) < 1 || Buffer.byteLength(key) > MEMORY_KEY_MAX_BYTES) {
12
+ throw new Error("memory_key_limit");
13
+ }
14
+ }
15
+ function checkContent(content) {
16
+ if (typeof content !== "string" || Buffer.byteLength(content) > MEMORY_CONTENT_MAX_BYTES) {
17
+ throw new Error("memory_content_limit");
18
+ }
19
+ }
20
+ export class PostgresAgentMemory {
21
+ db;
22
+ constructor(db) {
23
+ this.db = db;
24
+ }
25
+ async get(agentId, key) {
26
+ checkKey(key);
27
+ const row = await this.db.agentMemory.findUnique({
28
+ where: { agentId_key: { agentId, key } },
29
+ select: { content: true },
30
+ });
31
+ return row?.content;
32
+ }
33
+ async set(agentId, key, content) {
34
+ checkKey(key);
35
+ checkContent(content);
36
+ // Single atomic statement: the INSERT...SELECT's WHERE only yields a row
37
+ // (so the INSERT proceeds) when the agent is under its key cap, or the
38
+ // key already exists (in which case ON CONFLICT overwrites regardless of
39
+ // the cap) — overwriting an existing key never counts against the cap.
40
+ const affected = await this.db.$executeRaw `
41
+ INSERT INTO "AgentMemory" ("agentId", "key", "content", "contentTsv", "updatedAt")
42
+ SELECT ${agentId}, ${key}, ${content}, to_tsvector('english', ${content}), now()
43
+ WHERE (SELECT count(*) FROM "AgentMemory" WHERE "agentId" = ${agentId}) < ${MEMORY_MAX_KEYS_PER_AGENT}
44
+ OR EXISTS (SELECT 1 FROM "AgentMemory" WHERE "agentId" = ${agentId} AND "key" = ${key})
45
+ ON CONFLICT ("agentId", "key")
46
+ DO UPDATE SET "content" = EXCLUDED."content", "contentTsv" = EXCLUDED."contentTsv", "updatedAt" = now()
47
+ `;
48
+ if (affected === 0)
49
+ throw new Error("memory_limit_exceeded");
50
+ }
51
+ async list(agentId) {
52
+ const rows = await this.db.agentMemory.findMany({
53
+ where: { agentId },
54
+ select: { key: true },
55
+ orderBy: { key: "asc" },
56
+ });
57
+ return rows.map((r) => r.key);
58
+ }
59
+ async search(agentId, query, limit) {
60
+ const cappedLimit = Math.min(Math.max(1, limit ?? MEMORY_SEARCH_DEFAULT_LIMIT), MEMORY_SEARCH_MAX_LIMIT);
61
+ return this.db.$queryRaw `
62
+ SELECT "key", "content", ts_rank("contentTsv", plainto_tsquery('english', ${query}))::float8 AS rank
63
+ FROM "AgentMemory"
64
+ WHERE "agentId" = ${agentId} AND "contentTsv" @@ plainto_tsquery('english', ${query})
65
+ ORDER BY rank DESC
66
+ LIMIT ${cappedLimit}
67
+ `;
68
+ }
69
+ async delete(agentId, key) {
70
+ await this.db.agentMemory.deleteMany({ where: { agentId, key } });
71
+ }
72
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Agent memory seam — persistent, agent-controlled key/content notes,
3
+ * separate from the Datastore seam (`../datastore/types.ts`). Datastore is
4
+ * opaque per-tool JSON state a sandboxed tool body reads/writes; memory is
5
+ * curated free-text an agent reads/writes about itself, with its own
6
+ * built-in tools (`memory_get`/`memory_set`/`memory_list`/`memory_search`,
7
+ * see `../../core/memory-tools.ts`) rather than user-authored sandbox code.
8
+ */
9
+ /** A key must fit a reasonable identifier; content is free text up to MEMORY_CONTENT_MAX_BYTES. */
10
+ export declare const MEMORY_KEY_MAX_BYTES = 200;
11
+ /** Bounds one entry's content — generous for free-text notes, far below the sandbox bridge's 1MiB guard. */
12
+ export declare const MEMORY_CONTENT_MAX_BYTES: number;
13
+ /** Caps rows per agent so a runaway loop writing unique keys every turn can't grow the table unbounded. */
14
+ export declare const MEMORY_MAX_KEYS_PER_AGENT = 500;
15
+ /** Default/maximum result count for `search`. */
16
+ export declare const MEMORY_SEARCH_DEFAULT_LIMIT = 20;
17
+ export declare const MEMORY_SEARCH_MAX_LIMIT = 50;
18
+ export interface AgentMemorySearchHit {
19
+ key: string;
20
+ content: string;
21
+ rank: number;
22
+ }
23
+ export interface AgentMemoryStore {
24
+ get(agentId: string, key: string): Promise<string | undefined>;
25
+ /** Upserts `key`. Throws `memory_key_limit`/`memory_content_limit` over the byte bounds, or `memory_limit_exceeded` if a brand-new key would exceed MEMORY_MAX_KEYS_PER_AGENT (overwriting an existing key never counts against the cap). */
26
+ set(agentId: string, key: string, content: string): Promise<void>;
27
+ /** Lists keys only (not content), sorted, scoped to the agent. */
28
+ list(agentId: string): Promise<string[]>;
29
+ /** Full-text search over content via Postgres `ts_rank`, best matches first. */
30
+ search(agentId: string, query: string, limit?: number): Promise<AgentMemorySearchHit[]>;
31
+ delete(agentId: string, key: string): Promise<void>;
32
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Agent memory seam — persistent, agent-controlled key/content notes,
3
+ * separate from the Datastore seam (`../datastore/types.ts`). Datastore is
4
+ * opaque per-tool JSON state a sandboxed tool body reads/writes; memory is
5
+ * curated free-text an agent reads/writes about itself, with its own
6
+ * built-in tools (`memory_get`/`memory_set`/`memory_list`/`memory_search`,
7
+ * see `../../core/memory-tools.ts`) rather than user-authored sandbox code.
8
+ */
9
+ /** A key must fit a reasonable identifier; content is free text up to MEMORY_CONTENT_MAX_BYTES. */
10
+ export const MEMORY_KEY_MAX_BYTES = 200;
11
+ /** Bounds one entry's content — generous for free-text notes, far below the sandbox bridge's 1MiB guard. */
12
+ export const MEMORY_CONTENT_MAX_BYTES = 64 * 1024;
13
+ /** Caps rows per agent so a runaway loop writing unique keys every turn can't grow the table unbounded. */
14
+ export const MEMORY_MAX_KEYS_PER_AGENT = 500;
15
+ /** Default/maximum result count for `search`. */
16
+ export const MEMORY_SEARCH_DEFAULT_LIMIT = 20;
17
+ export const MEMORY_SEARCH_MAX_LIMIT = 50;
@@ -0,0 +1,8 @@
1
+ export declare class AppKeySecretCipher {
2
+ private readonly key;
3
+ private readonly id;
4
+ constructor(hexKey: string);
5
+ keyId(): string;
6
+ encrypt(plaintext: string): Promise<string>;
7
+ decrypt(blob: string): Promise<string>;
8
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * AES-256-GCM SecretCipher adapter, keyed by a single app-wide master key
3
+ * (SECRET_APP_KEY, 32 bytes hex). Ciphertext is a self-describing
4
+ * `iv:tag:ciphertext` base64url blob — random per-call IV (never reused),
5
+ * auth tag verified on decrypt so a tampered ciphertext throws rather than
6
+ * silently returning corrupted plaintext.
7
+ */
8
+ import { createCipheriv, createDecipheriv, createHash, randomBytes } from "node:crypto";
9
+ const ALGORITHM = "aes-256-gcm";
10
+ const KEY_BYTES = 32;
11
+ const IV_BYTES = 12;
12
+ function b64url(buf) {
13
+ return buf.toString("base64url");
14
+ }
15
+ export class AppKeySecretCipher {
16
+ key;
17
+ id;
18
+ constructor(hexKey) {
19
+ const key = Buffer.from(hexKey, "hex");
20
+ if (key.length !== KEY_BYTES) {
21
+ throw new Error(`SECRET_APP_KEY must be ${KEY_BYTES} bytes of hex (${KEY_BYTES * 2} hex chars); got ${key.length} bytes.`);
22
+ }
23
+ this.key = key;
24
+ this.id = `appkey:${createHash("sha256").update(key).digest("hex").slice(0, 8)}`;
25
+ }
26
+ keyId() {
27
+ return this.id;
28
+ }
29
+ async encrypt(plaintext) {
30
+ const iv = randomBytes(IV_BYTES);
31
+ const cipher = createCipheriv(ALGORITHM, this.key, iv);
32
+ const ciphertext = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
33
+ const tag = cipher.getAuthTag();
34
+ return `${b64url(iv)}:${b64url(tag)}:${b64url(ciphertext)}`;
35
+ }
36
+ async decrypt(blob) {
37
+ const parts = blob.split(":");
38
+ if (parts.length !== 3) {
39
+ throw new Error("Malformed ciphertext blob — expected iv:tag:ciphertext.");
40
+ }
41
+ const [ivPart, tagPart, ciphertextPart] = parts;
42
+ const iv = Buffer.from(ivPart, "base64url");
43
+ const tag = Buffer.from(tagPart, "base64url");
44
+ const ciphertext = Buffer.from(ciphertextPart, "base64url");
45
+ const decipher = createDecipheriv(ALGORITHM, this.key, iv);
46
+ decipher.setAuthTag(tag);
47
+ const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
48
+ return plaintext.toString("utf8");
49
+ }
50
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Secret-cipher selector — builds the adapter for the configured
3
+ * SECRET_CIPHER kind. `kms` is reserved (no adapter yet); selecting it
4
+ * fails closed with a clear error, mirroring how the config seam handles
5
+ * other not-yet-built kinds (e.g. bedrock in the LLM router).
6
+ */
7
+ import type { ProviderConfig } from "../../config/providers.js";
8
+ import type { SecretCipher } from "./types.js";
9
+ export { AppKeySecretCipher } from "./app-key.js";
10
+ export declare function buildSecretCipher(config: Pick<ProviderConfig, "secrets">, env?: NodeJS.ProcessEnv): SecretCipher;
@@ -0,0 +1,13 @@
1
+ import { loadSecretConfig } from "../../config/providers.js";
2
+ import { AppKeySecretCipher } from "./app-key.js";
3
+ export { AppKeySecretCipher } from "./app-key.js";
4
+ export function buildSecretCipher(config, env = process.env) {
5
+ if (config.secrets === "kms") {
6
+ throw new Error("SECRET_CIPHER=kms not implemented (reserved).");
7
+ }
8
+ const { appKey } = loadSecretConfig(env);
9
+ if (!appKey) {
10
+ throw new Error("SECRET_APP_KEY is not set — required by the app-key SecretCipher adapter.");
11
+ }
12
+ return new AppKeySecretCipher(appKey);
13
+ }
@@ -0,0 +1,12 @@
1
+ import { type KeyObject } from "node:crypto";
2
+ export interface TransferEnvelope {
3
+ v: number;
4
+ alg: string;
5
+ epk: string;
6
+ nonce: string;
7
+ ct: string;
8
+ tag: string;
9
+ }
10
+ export declare function loadTransferPrivateKey(pem: string): KeyObject;
11
+ export declare function transferKeyIdOf(privateKey: KeyObject): string;
12
+ export declare function decryptTransferEnvelope(env: TransferEnvelope, secretName: string, privateKey: KeyObject): string;
@@ -0,0 +1,35 @@
1
+ import { createPrivateKey, createPublicKey, diffieHellman, hkdfSync, createDecipheriv, createHash, } from "node:crypto";
2
+ const ALG = "x25519-hkdf-sha256-chacha20poly1305-v1";
3
+ const INFO = Buffer.from("wardby-secret-transfer-v1");
4
+ const SPKI_PREFIX = Buffer.from("302a300506032b656e032100", "hex"); // X25519 SPKI DER header
5
+ function rawFromSpki(key) {
6
+ return key.export({ type: "spki", format: "der" }).subarray(-32);
7
+ }
8
+ export function loadTransferPrivateKey(pem) {
9
+ const key = createPrivateKey(pem.trim());
10
+ if (key.asymmetricKeyType !== "x25519") {
11
+ throw new Error("transfer private key must be an X25519 PKCS8 private key");
12
+ }
13
+ return key;
14
+ }
15
+ export function transferKeyIdOf(privateKey) {
16
+ const pubRaw = rawFromSpki(createPublicKey(privateKey));
17
+ return createHash("sha256").update(pubRaw).digest("hex").slice(0, 16);
18
+ }
19
+ function publicFromRaw(raw) {
20
+ return createPublicKey({ key: Buffer.concat([SPKI_PREFIX, raw]), format: "der", type: "spki" });
21
+ }
22
+ export function decryptTransferEnvelope(env, secretName, privateKey) {
23
+ if (env.alg !== ALG)
24
+ throw new Error(`unsupported envelope alg: ${env.alg}`);
25
+ const epkRaw = Buffer.from(env.epk, "hex");
26
+ const shared = diffieHellman({ privateKey, publicKey: publicFromRaw(epkRaw) });
27
+ const recipientRaw = rawFromSpki(createPublicKey(privateKey));
28
+ const okm = Buffer.from(hkdfSync("sha256", shared, Buffer.concat([epkRaw, recipientRaw]), INFO, 32));
29
+ // Supplying the plaintext length satisfies Node's generic AEAD typing and
30
+ // keeps the authenticated-data call explicit for chacha20-poly1305.
31
+ const d = createDecipheriv("chacha20-poly1305", okm, Buffer.from(env.nonce, "hex"), { authTagLength: 16 });
32
+ d.setAAD(Buffer.from(secretName, "utf8"), { plaintextLength: Buffer.byteLength(env.ct, "hex") });
33
+ d.setAuthTag(Buffer.from(env.tag, "hex"));
34
+ return Buffer.concat([d.update(Buffer.from(env.ct, "hex")), d.final()]).toString("utf8");
35
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Secrets seam — encryption of secret values at rest.
3
+ *
4
+ * wardby uses its own key and its own ciphertext format, independent of any
5
+ * other system. `encrypt` returns a self-describing blob (algorithm + key id +
6
+ * IV + ciphertext) so values can be rotated and re-encrypted without ambiguity
7
+ * — this is what makes a one-time migration onto wardby clean.
8
+ *
9
+ * Default adapter: AppKeySecretCipher (AES-GCM with an app master key).
10
+ * Native adapter: KmsSecretCipher (envelope encryption via a KMS key).
11
+ */
12
+ export interface SecretCipher {
13
+ /** Identifier of the active key/version, for rotation and envelope reference. */
14
+ keyId(): string;
15
+ /** Encrypt to a self-describing blob (algorithm + keyId + IV + ciphertext). */
16
+ encrypt(plaintext: string): Promise<string>;
17
+ decrypt(ciphertext: string): Promise<string>;
18
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Secrets seam — encryption of secret values at rest.
3
+ *
4
+ * wardby uses its own key and its own ciphertext format, independent of any
5
+ * other system. `encrypt` returns a self-describing blob (algorithm + key id +
6
+ * IV + ciphertext) so values can be rotated and re-encrypted without ambiguity
7
+ * — this is what makes a one-time migration onto wardby clean.
8
+ *
9
+ * Default adapter: AppKeySecretCipher (AES-GCM with an app master key).
10
+ * Native adapter: KmsSecretCipher (envelope encryption via a KMS key).
11
+ */
12
+ export {};
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Storage seam — object/blob storage (email attachments, run artifacts).
3
+ *
4
+ * Default adapter: LocalBlobStore (filesystem).
5
+ * Native adapter: S3BlobStore (S3 or S3-compatible object storage).
6
+ */
7
+ export interface BlobStore {
8
+ put(key: string, body: Buffer, opts?: {
9
+ contentType?: string;
10
+ }): Promise<void>;
11
+ get(key: string): Promise<Buffer>;
12
+ delete(key: string): Promise<void>;
13
+ /** Pre-signed URL for direct client GET/PUT without proxying through the app. */
14
+ signedUrl(key: string, opts: {
15
+ expiresSec: number;
16
+ method: "GET" | "PUT";
17
+ }): Promise<string>;
18
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Storage seam — object/blob storage (email attachments, run artifacts).
3
+ *
4
+ * Default adapter: LocalBlobStore (filesystem).
5
+ * Native adapter: S3BlobStore (S3 or S3-compatible object storage).
6
+ */
7
+ export {};