@desplega.ai/agent-swarm 1.164.1 → 1.166.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 (328) hide show
  1. package/README.md +1 -1
  2. package/dist/acp-adapter-yzfxn8vj.js +23 -0
  3. package/dist/{actions-hp2h32dx.js → actions-qz3m692w.js} +24 -28
  4. package/dist/{amp-adapter-zfd7djyx.js → amp-adapter-j1xbmsqz.js} +7 -7
  5. package/dist/{app-w2d26h4f.js → app-43vrdmv8.js} +9 -10
  6. package/dist/{assistant-45pc4en7.js → assistant-ertffmka.js} +25 -29
  7. package/dist/{boot-reembed-k1q2s4fc.js → boot-reembed-998jtpdg.js} +12 -15
  8. package/dist/{boot-reembed-6rhcpsjf.js → boot-reembed-s7k7c6v2.js} +13 -15
  9. package/dist/boot-scrub-sweep-nepsk4t1.js +211 -0
  10. package/dist/{boot-seeds-ex93edx7.js → boot-seeds-vvzs1zhk.js} +12 -12
  11. package/dist/{claude-adapter-hcxd0szm.js → claude-adapter-2zvmekrp.js} +15 -17
  12. package/dist/{claude-managed-adapter-fz7xps2r.js → claude-managed-adapter-s49wbk8t.js} +5 -5
  13. package/dist/{claude-managed-setup-xx6f15h9.js → claude-managed-setup-cvhqq8qn.js} +4 -4
  14. package/dist/{claude-sdk-session-6nb9raem.js → claude-sdk-session-kkbxtw5q.js} +2624 -2606
  15. package/dist/{cli-etbrt8x1.js → cli-0nhdwxd5.js} +4 -4
  16. package/dist/{cli-jeefgppq.js → cli-0qjcsxgz.js} +7 -7
  17. package/dist/{cli-6behs2bt.js → cli-32bca7nr.js} +1 -1
  18. package/dist/{cli-gt8v96qx.js → cli-3ddybbbx.js} +4 -4
  19. package/dist/{acp-adapter-rxvek4ym.js → cli-3qn4r334.js} +317 -35
  20. package/dist/{cli-1d3w4xm3.js → cli-4r1sjfc4.js} +14 -6
  21. package/dist/{cli-691f2rxm.js → cli-66zh26sp.js} +68 -16
  22. package/dist/{cli-et8wdyqh.js → cli-68r1j4sg.js} +9 -9
  23. package/dist/{cli-xb7kyanp.js → cli-8kgvmkak.js} +3 -3
  24. package/dist/{cli-fdpkw8vk.js → cli-8t229cmr.js} +8 -8
  25. package/dist/{cli-gc54qc0p.js → cli-aqcey741.js} +1 -1
  26. package/dist/{cli-4q4cmr4t.js → cli-cpfmqz3n.js} +8 -8
  27. package/dist/{cli-a9bw0xxt.js → cli-df56tqdw.js} +997 -408
  28. package/dist/{cli-n7h1kqpf.js → cli-dmtrxqhg.js} +6 -1
  29. package/dist/{cli-xfb7333f.js → cli-dw2q9f7g.js} +5 -5
  30. package/dist/{cli-4drstbb9.js → cli-ecknp7p1.js} +81 -23
  31. package/dist/{cli-v0pvvhfq.js → cli-efnd2kce.js} +36 -1
  32. package/dist/{cli-1wetf34q.js → cli-f2n17zhp.js} +1 -1
  33. package/dist/{cli-2c8eky5y.js → cli-feh3dkah.js} +1 -1
  34. package/dist/cli-fn697bnt.js +126 -0
  35. package/dist/{cli-v5pr2fgt.js → cli-gt8azyet.js} +3 -3
  36. package/dist/{cli-dbszf3rw.js → cli-h3x613ze.js} +4 -4
  37. package/dist/{cli-nwhb8y2e.js → cli-hf5s9pgf.js} +1 -1
  38. package/dist/cli-j2jbr8af.js +516 -0
  39. package/dist/{cli-agjzafns.js → cli-jhm6hzjn.js} +593 -10
  40. package/dist/{cli-j0tmc908.js → cli-jvj6a0cv.js} +484 -477
  41. package/dist/{cli-xxz89c2n.js → cli-mb75wpxf.js} +1 -1
  42. package/dist/{cli-07s39g1n.js → cli-mv2520nm.js} +1 -1
  43. package/dist/{cli-v90vfwyb.js → cli-mwegs4af.js} +5 -5
  44. package/dist/{cli-bz1gbac9.js → cli-p4ztb80h.js} +2 -2
  45. package/dist/{cli-1wd1n2ya.js → cli-rfphkzh5.js} +1 -1
  46. package/dist/{cli-976r1zqx.js → cli-rggdq8wq.js} +5 -5
  47. package/dist/{cli-3ajw5v5v.js → cli-rsy933yz.js} +6 -6
  48. package/dist/{cli-yj790e19.js → cli-tadfgd0t.js} +8 -1
  49. package/dist/{cli-cn53e7vc.js → cli-ttbsse3f.js} +6 -1
  50. package/dist/{cli-dyqsrqcf.js → cli-v2a8x45d.js} +4 -4
  51. package/dist/{cli-wbvnn6tk.js → cli-v6vv7dy8.js} +91 -9
  52. package/dist/{cli-z2ap2c0c.js → cli-vzc73wet.js} +90 -55
  53. package/dist/cli-wt7ccy4r.js +2654 -0
  54. package/dist/{cli-4cn19jvn.js → cli-x7kpr72a.js} +3 -3
  55. package/dist/{cli-003785v9.js → cli-xvc3q9br.js} +1 -1
  56. package/dist/{cli-v0e7jpr5.js → cli-xvdgasgy.js} +13 -4
  57. package/dist/{cli-asqeg4ve.js → cli-y59h2pk9.js} +2 -2
  58. package/dist/{cli-0wn3ypqv.js → cli-yshaazs1.js} +14121 -3478
  59. package/dist/{cli-wg8yjqtw.js → cli-ysnyhws9.js} +16 -3
  60. package/dist/cli-zp67qg5x.js +92 -0
  61. package/dist/{cli-g3qgrzck.js → cli-zsh093hk.js} +71 -3
  62. package/dist/{cli-ma3zvh39.js → cli-zy7vwsne.js} +6066 -5829
  63. package/dist/cli.js +79 -26
  64. package/dist/{codex-adapter-pcxdn10v.js → codex-adapter-dw1wxqt8.js} +10 -10
  65. package/dist/{codex-hook-b1fb7c2k.js → codex-hook-d2rkvf39.js} +1 -1
  66. package/dist/{codex-login-059nm145.js → codex-login-terbdsqq.js} +2 -2
  67. package/dist/{codex-session-runner-xzwwddp8.js → codex-session-runner-3cgb8y1g.js} +10 -10
  68. package/dist/{commands-98at8mkn.js → commands-mhxam6z2.js} +9 -9
  69. package/dist/{cursor-adapter-dkg6qnkp.js → cursor-adapter-2qda3st7.js} +6 -6
  70. package/dist/{db-01g8wtvw.js → db-sjks418k.js} +11 -9
  71. package/dist/{devin-adapter-qmttt2fz.js → devin-adapter-bffjj5n4.js} +2 -2
  72. package/dist/{dispatcher-nn2k1wxd.js → dispatcher-1es759rn.js} +22 -26
  73. package/dist/{dsh-adapter-w4d4vwdq.js → dsh-adapter-bek4cyw9.js} +6 -6
  74. package/dist/{e2b-9e4g2hvt.js → e2b-nd50eccg.js} +1 -1
  75. package/dist/{event-bus-z7v2t26e.js → event-bus-vnfthafg.js} +2 -2
  76. package/dist/grok-adapter-ar9cw9jg.js +29 -0
  77. package/dist/{handlers-b0kqsbg8.js → handlers-1gkbhktr.js} +25 -29
  78. package/dist/{hook-sap7v1aj.js → hook-ds2zxq9v.js} +16 -18
  79. package/dist/{hook-pz50gqep.js → hook-vxa3tcsy.js} +10 -12
  80. package/dist/{http-ncr8rmd0.js → http-3h21z9md.js} +679 -227
  81. package/dist/{index-c4aqcyz1.js → index-9b65j1m5.js} +11 -11
  82. package/dist/{index-r46s01nq.js → index-bn6cy8ps.js} +22 -26
  83. package/dist/{index-38kqdt3e.js → index-dkfxpkmm.js} +23 -27
  84. package/dist/{index-630kj5vd.js → index-f8xnqrye.js} +55 -43
  85. package/dist/{index-fdk1t4d6.js → index-n0rxa4ca.js} +11962 -9900
  86. package/dist/{index-9nrj7797.js → index-n99fycq7.js} +22 -26
  87. package/dist/{keepalive-31613r2h.js → keepalive-3xspa9jw.js} +14 -11
  88. package/dist/{lead-mx59tr5s.js → lead-6qphc124.js} +43 -43
  89. package/dist/{maintenance-55ff39ca.js → maintenance-0teem1bb.js} +10 -12
  90. package/dist/{node-f0ykebbv.js → node-9sg7ajby.js} +25 -7
  91. package/dist/{oauth-refresh-sweep-anma954w.js → oauth-refresh-sweep-sh9q25xp.js} +13 -10
  92. package/dist/{onboard-b2fy8ftb.js → onboard-54qmnqxe.js} +4 -3
  93. package/dist/{opencode-adapter-p1s92tmy.js → opencode-adapter-wjfa2wvd.js} +6 -6
  94. package/dist/{otel-impl-9brvt7xv.js → otel-impl-ycqzp2a1.js} +2 -2
  95. package/dist/{pi-mono-adapter-kz4rrwvd.js → pi-mono-adapter-e77e9zst.js} +6 -6
  96. package/dist/{pricing-refresh-7w8mbmva.js → pricing-refresh-atnkngqs.js} +10 -10
  97. package/dist/{rbac-roles-ejp7qwvb.js → rbac-roles-9pjphh9q.js} +10 -10
  98. package/dist/{rbac-roles-nhk4r7bc.js → rbac-roles-j78wdksm.js} +10 -10
  99. package/dist/{render-v2-2gzt8skq.js → render-v2-pxjs49fx.js} +9 -10
  100. package/dist/{setup-5et8t412.js → setup-ymej0xtx.js} +2 -2
  101. package/dist/{work-objects-tb0er7qa.js → work-objects-3nh4ymzb.js} +26 -30
  102. package/dist/{worker-62cv075d.js → worker-qa9fkz5s.js} +43 -43
  103. package/dist/{x-vbxb31jr.js → x-ma4gnfgy.js} +2 -2
  104. package/openapi.json +457 -31
  105. package/package.json +14 -6
  106. package/plugin/commands/create-pr.md +7 -1
  107. package/plugin/pi-skills/create-pr/SKILL.md +7 -1
  108. package/src/agentmail/app.ts +5 -4
  109. package/src/be/automation-preflight.ts +11 -9
  110. package/src/be/boot-scrub-sweep.ts +302 -0
  111. package/src/be/connector-codes.ts +81 -0
  112. package/src/be/crypto/key-bootstrap.ts +1 -1
  113. package/src/be/db/approvals.ts +15 -1
  114. package/src/be/db/codex-oauth-device-flows.ts +40 -0
  115. package/src/be/db/config-secrets.ts +31 -0
  116. package/src/be/db/runtime.ts +4 -0
  117. package/src/be/db/script-runs.ts +15 -0
  118. package/src/be/db/tasks/write.ts +1 -1
  119. package/src/be/db-queries/mcp-oauth.ts +5 -0
  120. package/src/be/db-queries/oauth.ts +77 -0
  121. package/src/be/db.ts +162 -59
  122. package/src/be/events.ts +17 -1
  123. package/src/be/memory/index-content.ts +2 -2
  124. package/src/be/memory/providers/sqlite-store.ts +63 -11
  125. package/src/be/memory/types.ts +14 -0
  126. package/src/be/migrations/197_connector_codes.sql +23 -0
  127. package/src/be/migrations/198_permission_audit_guest.sql +33 -0
  128. package/src/be/migrations/200_backfill_auto_memory_expiry.sql +20 -0
  129. package/src/be/migrations/201_workflow_replay_columns.sql +10 -0
  130. package/src/be/migrations/202_codex_oauth_device_flows.sql +24 -0
  131. package/src/be/model-tier-resolution.ts +2 -1
  132. package/src/be/model-validation.ts +1 -1
  133. package/src/be/pricing-normalize.ts +3 -0
  134. package/src/be/rbac-audit.ts +2 -1
  135. package/src/be/scripts/db.ts +28 -4
  136. package/src/be/scripts/source-secrets.ts +37 -0
  137. package/src/be/scripts/typecheck.ts +23 -2
  138. package/src/be/scrub-json.ts +32 -0
  139. package/src/be/sealed-json.ts +59 -0
  140. package/src/be/secret-registry.ts +131 -0
  141. package/src/be/seed-pricing.ts +14 -0
  142. package/src/be/users.ts +7 -1
  143. package/src/be/workflow-replay.ts +77 -0
  144. package/src/cli.tsx +7 -0
  145. package/src/commands/provider-credentials.ts +46 -8
  146. package/src/commands/runner.ts +2 -10
  147. package/src/extensions/contract-types.generated.ts +1 -1
  148. package/src/github/app.ts +4 -4
  149. package/src/heartbeat/heartbeat.ts +20 -8
  150. package/src/hooks/pr-body-guard.ts +1 -1
  151. package/src/http/agents.ts +1 -0
  152. package/src/http/approval-requests.ts +1 -0
  153. package/src/http/apps.ts +3 -0
  154. package/src/http/auth.ts +4 -1
  155. package/src/http/codex-oauth-device.ts +8 -10
  156. package/src/http/codex-oauth-keep-warm.ts +2 -2
  157. package/src/http/config-values.ts +59 -0
  158. package/src/http/config.ts +5 -0
  159. package/src/http/db-query-bounded.ts +3 -0
  160. package/src/http/db-query-shared.ts +107 -15
  161. package/src/http/db-query.ts +10 -2
  162. package/src/http/extensions.ts +1 -0
  163. package/src/http/index.ts +23 -6
  164. package/src/http/integrations.ts +1 -38
  165. package/src/http/ip-rate-limit.ts +82 -0
  166. package/src/http/kv.ts +38 -4
  167. package/src/http/mcp-servers.ts +1 -0
  168. package/src/http/memory.ts +9 -0
  169. package/src/http/models-catalog.ts +2 -0
  170. package/src/http/operator-actor.ts +4 -0
  171. package/src/http/page-proxy.ts +22 -0
  172. package/src/http/pages.ts +4 -2
  173. package/src/http/realtime.ts +1 -1
  174. package/src/http/request-principal.ts +14 -1
  175. package/src/http/script-connections.ts +8 -0
  176. package/src/http/script-runs.ts +12 -4
  177. package/src/http/scripts.ts +15 -0
  178. package/src/http/session-cost-recompute.ts +3 -2
  179. package/src/http/tasks.ts +9 -0
  180. package/src/http/users.ts +226 -0
  181. package/src/http/workflows.ts +3 -2
  182. package/src/http.ts +1 -0
  183. package/src/integrations/kapso/client.ts +3 -1
  184. package/src/jira/app.ts +2 -2
  185. package/src/kv-view.ts +324 -0
  186. package/src/linear/app.ts +2 -2
  187. package/src/oauth/mcp-wrapper.ts +1 -1
  188. package/src/prompts/memories.ts +42 -1
  189. package/src/providers/acp-adapter.ts +85 -24
  190. package/src/providers/acp-target-catalog.ts +54 -1
  191. package/src/providers/acp-targets.ts +358 -4
  192. package/src/providers/amp-adapter.ts +1 -1
  193. package/src/providers/cursor-adapter.ts +1 -1
  194. package/src/providers/grok-adapter.ts +186 -0
  195. package/src/providers/index.ts +5 -1
  196. package/src/providers/pricing-sources.md +6 -0
  197. package/src/providers/reasoning-effort.ts +17 -1
  198. package/src/providers/types.ts +2 -1
  199. package/src/rbac/can.ts +4 -3
  200. package/src/rbac/legacy-policy.ts +3 -3
  201. package/src/rbac/types.ts +6 -0
  202. package/src/script-workflows/supervisor.ts +11 -2
  203. package/src/scripts-runtime/eval-harness.ts +2 -12
  204. package/src/scripts-runtime/executors/quickjs-bundle.ts +152 -0
  205. package/src/scripts-runtime/executors/quickjs-prelude.ts +285 -0
  206. package/src/scripts-runtime/executors/quickjs-runner.ts +580 -0
  207. package/src/scripts-runtime/executors/quickjs-worker.ts +81 -0
  208. package/src/scripts-runtime/executors/quickjs.ts +196 -0
  209. package/src/scripts-runtime/executors/registry.ts +2 -0
  210. package/src/scripts-runtime/executors/sourcemap.ts +79 -0
  211. package/src/scripts-runtime/script-error-hints.ts +14 -0
  212. package/src/scripts-runtime/swarm-sdk.ts +9 -2
  213. package/src/scripts-runtime/types/stdlib.d.ts +27 -8
  214. package/src/scripts-runtime/types/swarm-extension.d.ts +3 -0
  215. package/src/scripts-runtime/types/swarm-sdk.d.ts +27 -8
  216. package/src/server-user.ts +2 -20
  217. package/src/server.ts +3 -1
  218. package/src/slack/app.ts +4 -0
  219. package/src/slack/config.ts +3 -1
  220. package/src/slack/egress-scrub.ts +87 -0
  221. package/src/tests/acp-adapter.test.ts +191 -2
  222. package/src/tests/boot-scrub-sweep.test.ts +390 -0
  223. package/src/tests/budget-user-scope.test.ts +7 -21
  224. package/src/tests/check-pr-body.test.ts +149 -6
  225. package/src/tests/check-text-columns.test.ts +145 -0
  226. package/src/tests/claude-adapter-binary.test.ts +1 -1
  227. package/src/tests/claude-sdk-process.fixture.ts +13 -2
  228. package/src/tests/codex-oauth-device.test.ts +23 -37
  229. package/src/tests/codex-oauth-keep-warm.test.ts +29 -0
  230. package/src/tests/console-scrub.test.ts +141 -0
  231. package/src/tests/credential-check.test.ts +90 -0
  232. package/src/tests/db-query-denylist.test.ts +202 -0
  233. package/src/tests/db-task-read-contract.test.ts +1 -0
  234. package/src/tests/db-task-write-contract.test.ts +1 -0
  235. package/src/tests/docs-index-footprint.test.js +3 -3
  236. package/src/tests/entrypoint-acp-target-binary.test.ts +44 -1
  237. package/src/tests/events-scrub.test.ts +88 -0
  238. package/src/tests/explicit-model-validation.test.ts +81 -0
  239. package/src/tests/extensions-pre-task.test.ts +33 -1
  240. package/src/tests/fixtures/grok/acp-updates-recorded.jsonl +53 -0
  241. package/src/tests/fixtures/grok/prompt-response-meta.json +36 -0
  242. package/src/tests/fixtures/secret-corpus.ts +320 -0
  243. package/src/tests/grok-adapter.test.ts +647 -0
  244. package/src/tests/heartbeat-checklist.test.ts +44 -0
  245. package/src/tests/integration-disable-flags.test.ts +156 -0
  246. package/src/tests/kv-http.test.ts +34 -0
  247. package/src/tests/kv-tool.test.ts +274 -1
  248. package/src/tests/kv-view.test.ts +147 -0
  249. package/src/tests/mcp-user-route.test.ts +257 -15
  250. package/src/tests/memory-injection-outcome.test.ts +143 -0
  251. package/src/tests/model-tier-resolution.test.ts +76 -3
  252. package/src/tests/page-guest-session.test.ts +424 -0
  253. package/src/tests/page-proxy.test.ts +1 -1
  254. package/src/tests/page-viewer-auth.test.ts +22 -1
  255. package/src/tests/pr-body-leaks.test.ts +157 -2
  256. package/src/tests/preload.ts +10 -0
  257. package/src/tests/provider-registration.test.ts +3 -1
  258. package/src/tests/rbac-audit.test.ts +32 -0
  259. package/src/tests/rbac-mcp-admission-e2e.test.ts +4 -62
  260. package/src/tests/script-connections.test.ts +9 -0
  261. package/src/tests/script-executor-conformance.test.ts +3 -0
  262. package/src/tests/script-executor-quickjs.test.ts +442 -0
  263. package/src/tests/script-executor-registry.test.ts +6 -1
  264. package/src/tests/script-runs-http.test.ts +126 -1
  265. package/src/tests/script-runs-scrub.test.ts +275 -0
  266. package/src/tests/scripts-http.test.ts +82 -1
  267. package/src/tests/scripts-mcp-e2e.test.ts +42 -6
  268. package/src/tests/scripts-runtime.test.ts +37 -0
  269. package/src/tests/scrubbed-text-12e.test.ts +289 -0
  270. package/src/tests/sealed-key-guard.test.ts +166 -0
  271. package/src/tests/secret-canary-sweep.test.ts +958 -0
  272. package/src/tests/secret-registry.test.ts +355 -0
  273. package/src/tests/secret-rules.test.ts +230 -0
  274. package/src/tests/secret-scrubber.test.ts +317 -1
  275. package/src/tests/session-costs-golden.test.ts +17 -0
  276. package/src/tests/slack-egress-scrub.test.ts +216 -0
  277. package/src/tests/swarm-tool-result-gate.test.ts +143 -30
  278. package/src/tests/task-tools-ctx.test.ts +3 -0
  279. package/src/tests/user-token-routes.test.ts +342 -3
  280. package/src/tests/workflow-replay.test.ts +518 -0
  281. package/src/tests/workflow-scrub.test.ts +242 -0
  282. package/src/tests/workflow-system-one-decision-providers.test.ts +737 -0
  283. package/src/tools/db-query.ts +1 -1
  284. package/src/tools/inject-learning.ts +1 -1
  285. package/src/tools/kv/kv-get.ts +136 -6
  286. package/src/tools/send-task.ts +61 -17
  287. package/src/tools/utils.ts +186 -43
  288. package/src/tools/workflows/get-workflow-run.ts +3 -2
  289. package/src/types.ts +16 -1
  290. package/src/utils/console-scrub-install.ts +5 -0
  291. package/src/utils/console-scrub.ts +57 -0
  292. package/src/utils/credentials.ts +8 -0
  293. package/src/utils/page-session.ts +6 -2
  294. package/src/utils/pr-body-leaks.ts +149 -10
  295. package/src/utils/request-auth-context.ts +2 -0
  296. package/src/utils/secret-rules.generated.ts +2055 -0
  297. package/src/utils/secret-scrubber.ts +662 -36
  298. package/src/workflows/engine.ts +39 -4
  299. package/src/workflows/executors/notify.ts +6 -1
  300. package/src/workflows/executors/system-one-decision.ts +31 -12
  301. package/src/workflows/executors/system-one-openai-wire.ts +168 -0
  302. package/src/workflows/executors/system-one-providers.ts +112 -11
  303. package/src/workflows/executors/system-one-wire.ts +79 -0
  304. package/src/workflows/recovery.ts +10 -1
  305. package/src/workflows/resume.ts +62 -3
  306. package/src/workflows/retry-poller.ts +3 -0
  307. package/templates/ai-toolbox.manifest.json +2 -2
  308. package/templates/skills/agent-browser/SKILL.md +5 -5
  309. package/templates/skills/agent-browser/config.json +1 -1
  310. package/templates/skills/agent-browser/content.md +4 -4
  311. package/templates/skills/artifacts/content.md +17 -7
  312. package/templates/skills/jira-interaction/config.json +1 -1
  313. package/templates/skills/jira-interaction/content.md +56 -205
  314. package/templates/skills/linear-interaction/config.json +1 -1
  315. package/templates/skills/linear-interaction/content.md +31 -50
  316. package/templates/skills/pages/content.md +8 -4
  317. package/templates/skills/qa/content.md +2 -2
  318. package/templates/skills/workflow-iterate/content.md +4 -4
  319. package/tsconfig.json +3 -3
  320. package/dist/boot-scrub-logs-t8xg7wd7.js +0 -99
  321. package/dist/cli-0a7r5331.js +0 -168
  322. package/dist/cli-93rxw9yd.js +0 -951
  323. package/dist/cli-cvk6yzw5.js +0 -40
  324. package/dist/cli-dgnj0zcc.js +0 -40
  325. package/dist/cli-qt5wzq6v.js +0 -256
  326. package/dist/cli-v7fqehqd.js +0 -9281
  327. package/dist/cli-vbr859rz.js +0 -572
  328. package/src/be/boot-scrub-logs.ts +0 -132
@@ -5,7 +5,7 @@
5
5
  "slug": "linear-interaction",
6
6
  "title": "Linear Interaction",
7
7
  "description": "Create issues, update status, and post comments in Linear with explicit project placeholders.",
8
- "version": "1.0.0",
8
+ "version": "1.0.1",
9
9
  "category": "skills",
10
10
  "placeholders": [
11
11
  "LINEAR_PROJECT_ID"
@@ -1,16 +1,5 @@
1
1
  # Linear Interaction (Outbound Push)
2
2
 
3
- **Before attempting any API call below, check if the token has been renewed:**
4
- ```bash
5
- # Use db-query MCP tool
6
- db-query: SELECT accessToken, expiresAt FROM oauth_tokens WHERE provider = 'linear'
7
- ```
8
- If `expiresAt` is in the past, do NOT attempt the API calls — just report the needed update in your task output.
9
-
10
- To re-authorize, use your swarm API base URL with `/api/trackers/linear/authorize` (potentially needing to remove the app and re-auth). Only mention this if you can confirm the token is expired or not present.
11
-
12
- ---
13
-
14
3
  ## Critical Context
15
4
 
16
5
  The swarm's Linear integration is **inbound-only**: Linear → swarm. This means:
@@ -26,34 +15,43 @@ The available MCP tracker tools (`tracker-link-task`, `tracker-link-epic`, `trac
26
15
  - **Standard PR workflow:** Transition to **In Review** on PR open, **Done** after merge. If the ticket is still "In Progress" 30 min after the PR merges, you're late.
27
16
  - **Blocked:** If a ticket is stuck on a dependency, add a comment linking the blocker — don't leave it silent.
28
17
 
29
- ## Authentication
18
+ ## Authentication: script credential binding
30
19
 
31
- The OAuth token is stored in the swarm database (`oauth_tokens` table, provider = 'linear').
20
+ Use the `swarm-scripts` skill and `script-run` (`args` first, `ctx` second) for every authenticated request. The API server resolves an OAuth authorization, refreshes it when needed, and substitutes `[REDACTED:LINEAR_OAUTH_ACCESS_TOKEN]` in the request header only for the binding's allowed hosts. Never read credential tables, request a raw token from Lead, or copy a token into source, arguments, environment variables, logs, or task output.
32
21
 
33
- **To get the token:**
34
- ```bash
35
- # Use db-query MCP tool
36
- db-query: SELECT accessToken FROM oauth_tokens WHERE provider = 'linear'
37
- ```
22
+ Try the conventional binding key `LINEAR_OAUTH_ACCESS_TOKEN` first, using `Authorization: Bearer [REDACTED:LINEAR_OAUTH_ACCESS_TOKEN]` for `api.linear.app`. Do not ask Lead before the first try. `credential-bindings` is lead-only; workers cannot list bindings.
23
+
24
+ On HTTP 401 with the conventional key, report the missing binding or authorization to Lead as a blocker. The fetch wrapper in `src/scripts-runtime/credential-broker/fetch-patch.ts` drops any header with an unresolved `[REDACTED:` placeholder, so a missing binding sends an unauthenticated request that yields 401, never a credential leak.
25
+
26
+ Lead uses `credential-bindings` action `list` to check the binding. If missing, Lead registers/authorizes the provider and creates a binding visible to the agent with `configKey: "LINEAR_OAUTH_ACCESS_TOKEN"`, `authKind: "oauth"`, `oauthAuthorizationId`, `allowedHosts: ["api.linear.app"]`, and `headerTemplate: "Authorization: Bearer [REDACTED:LINEAR_OAUTH_ACCESS_TOKEN]"`.
38
27
 
39
- > **Worker agents (non-lead):** If you are a non-lead agent and cannot access the Linear token via `db-query`, message the lead agent in the task and request the token. Do not complete the task without updating Linear.
28
+ An expiring authorization is refreshed server-side; a refresh failure, revoked/missing authorization, or persistent 401 needs Lead/user re-authorization through `credential-bindings` action `oauth-authorize-url`. Do not query expiry/token columns or loop on 401s.
40
29
 
41
- **Token details:**
42
- - Scopes: `app:assignable app:mentionable comments:create issues:create read write`
43
- - Tokens expire — check `expiresAt` column. If expired, the user needs to re-authorize via the OAuth flow.
44
- - API endpoint: `https://api.linear.app/graphql`
30
+ Supported implementation: `src/be/script-credential-broker.ts` loads scoped relational bindings and calls `resolveOAuthBindingToken` from `src/be/oauth-credential-bindings.ts`. The scripts runtime substitutes placeholders at egress for allowed hosts.
45
31
 
46
- ## Making API Calls
32
+ ## Making API calls
47
33
 
48
- All Linear API calls use GraphQL via POST to `https://api.linear.app/graphql`.
34
+ Allowed host: `api.linear.app`. Send GraphQL queries and mutations with `script-run`; the common operations below supply the `query` and optional `variables`:
49
35
 
50
- ```bash
51
- curl -s -X POST https://api.linear.app/graphql \
52
- -H "Content-Type: application/json" \
53
- -H "Authorization: Bearer <ACCESS_TOKEN>" \
54
- -d '{"query": "<GRAPHQL_QUERY>"}'
36
+ ```typescript
37
+ export default async function (args, ctx) {
38
+ const response = await fetch("https://api.linear.app/graphql", {
39
+ method: "POST",
40
+ headers: {
41
+ "Content-Type": "application/json",
42
+ Authorization: "Bearer [REDACTED:LINEAR_OAUTH_ACCESS_TOKEN]",
43
+ },
44
+ body: JSON.stringify({ query: args.query, variables: args.variables ?? {} }),
45
+ });
46
+ if (!response.ok) throw new Error(`Linear HTTP ${response.status}`);
47
+ const result = await response.json();
48
+ if (result.errors?.length) throw new Error(JSON.stringify(result.errors));
49
+ return result.data;
50
+ }
55
51
  ```
56
52
 
53
+ Return only the issue fields needed for the task; never return request headers or credentials.
54
+
57
55
  ## Agent Interaction API — `action` vs `thought`
58
56
 
59
57
  Linear's **Agent Interaction API** (different from issue mutations above) supports two activity payload kinds. Use this section whenever emitting `agentActivityCreate` mutations.
@@ -191,30 +189,13 @@ query {
191
189
 
192
190
  This is the most common scenario — completing a Linear-sourced swarm task and updating the ticket:
193
191
 
194
- ```bash
195
- # 1. Get the token
196
- TOKEN=$(db-query result from oauth_tokens)
197
-
198
- # 2. Get issue details and team states
199
- curl -s -X POST https://api.linear.app/graphql \
200
- -H "Content-Type: application/json" \
201
- -H "Authorization: Bearer $TOKEN" \
202
- -d '{"query": "{ issue(id: \"DES-12\") { id team { states { nodes { id name type } } } } }"}'
203
-
204
- # 3. Find the "Done" state UUID from the response (type: "completed")
205
-
206
- # 4. Update the issue
207
- curl -s -X POST https://api.linear.app/graphql \
208
- -H "Content-Type: application/json" \
209
- -H "Authorization: Bearer $TOKEN" \
210
- -d '{"query": "mutation { issueUpdate(id: \"<ISSUE-UUID>\", input: { stateId: \"<DONE-STATE-UUID>\" }) { success issue { identifier state { name } } } }"}'
211
- ```
192
+ Run the query in operation 1 through the script above to get the issue UUID and team states. Select the state whose `type` is `completed`, then run `issueUpdate` with that state UUID through the same script. Check GraphQL errors and mutation `success` before reporting the ticket updated.
212
193
 
213
194
  ## Important Notes
214
195
 
215
196
  - **Always update Linear when completing Linear-sourced tasks.** The user expects the ticket to reflect the swarm's work. Marking only the swarm task as complete is insufficient. Do not complete only the swarm task — failing to update Linear breaks the sync and wastes resources.
216
197
  - **Transition timing:** see the "When to Transition" section above. Direct-to-main work transitions on ship, not on merge.
217
- - **Token expiry:** Check `expiresAt` before making calls. If expired, notify the user — they need to re-authorize.
198
+ - **Authorization failures:** Report refresh failures or persistent 401s to Lead/user for re-authorization; the server handles normal expiry.
218
199
  - **Rate limits:** Linear has rate limits. For bulk operations, add small delays between calls.
219
200
  - **Issue identifiers vs UUIDs:** The human-readable identifier (e.g., "DES-12") works for queries but the `issueUpdate` mutation requires the actual UUID. Always fetch the UUID first via a query.
220
201
  - **Markdown support:** Linear supports markdown in descriptions and comments.
@@ -222,7 +203,7 @@ curl -s -X POST https://api.linear.app/graphql \
222
203
  ## Error Handling
223
204
 
224
205
  Common errors:
225
- - `401 Unauthorized` → Token expired or invalid, needs re-auth
206
+ - `401 Unauthorized` → Report the missing binding or authorization to Lead as a blocker; Lead checks provisioning or re-authorization
226
207
  - `Forbidden` → Token doesn't have required scope
227
208
  - `Entity not found` → Wrong issue ID/identifier
228
209
  - `"parameter must not be empty"` (or similar on Agent Interaction API) → You sent an `action` activity without a `parameter` — convert to `thought` or fill in a real noun. See "Agent Interaction API — action vs thought" above.
@@ -454,7 +454,9 @@ with a custom `swarm.call` action handler. Action shape:
454
454
  `swarm.call` dispatches through the SPA's bearer (for `app_url` loads) or
455
455
  the page-session cookie (for direct `api_url` loads). The endpoint must be
456
456
  a valid swarm API path. User-token sessions retain user authorization.
457
- Operator and password sessions retain deployment-level API access.
457
+ Operator-launched sessions retain deployment-level API access. Password
458
+ sessions are guests: they reach only their own page record and KV, so
459
+ `swarm.call` to any other endpoint returns 403.
458
460
 
459
461
  See the `@json-render/core` docs for the supported node types (`text`,
460
462
  `button`, `input`, `card`, etc.).
@@ -462,8 +464,9 @@ See the `@json-render/core` docs for the supported node types (`text`,
462
464
  ## Security & Blast Radius
463
465
 
464
466
  - User-token launches retain the signed viewer identity and its API permissions.
465
- - Operator and password sessions are guests with deployment-level API access.
466
- They do not inherit the page author's agent identity. Review actions before sharing these pages.
467
+ - Operator launches keep deployment-level API access. They do not inherit the page author's agent identity.
468
+ - Password sessions are guests. Through the proxy they reach only `GET pages/<own id>` (without
469
+ `passwordHash`) and the page's own KV. Every other route returns 403, and every RBAC verb denies a guest.
467
470
  - Browser SDK memory operations use the page owner's agent scope through verified page execution context.
468
471
  Viewer authentication, permissions, and audit identity remain separate from this resource scope.
469
472
  - Treat agent-generated HTML / JSON like trusted code — the agent already
@@ -473,7 +476,8 @@ See the `@json-render/core` docs for the supported node types (`text`,
473
476
  - HTML pages render inside a sandboxed iframe with
474
477
  `sandbox="allow-scripts allow-forms allow-same-origin"`. This limits
475
478
  some attack surface (no top-level navigation, no pointer-lock) but the
476
- page still has full access to the SwarmSDK if cookies are present.
479
+ page still has the SwarmSDK access of its session: full for user and
480
+ operator sessions, page record and KV only for password guests.
477
481
  - All page bodies pass through `scrubSecrets` at the egress boundary
478
482
  (`/p/:id`, `/p/:id.json`, listing endpoint) — accidental secrets in
479
483
  the body get masked at serve time, not at write time. Don't rely on
@@ -94,7 +94,7 @@ Write all test cases into the QA document's `## Test Cases` section.
94
94
  2. `agent-browser snapshot -i` to read the page state and its `@eN` refs
95
95
  3. Act on refs (`click @eN`, `fill @eN "text"`, `type`, `press`) and re-snapshot after every navigation or state change; refs are only valid for the snapshot that produced them
96
96
  4. `agent-browser screenshot /tmp/<name>.png` for evidence, then `agent-browser close`
97
- 5. To share a screenshot outside the machine, upload it to agent-fs with `agent-fs write <path> --file /tmp/<name>.png -m "<what it shows>"` (binary-safe; `--content` mangles PNGs), then `agent-fs signed-url <path> --json` and embed the URL as `![caption](<url>)`. If agent-fs is not configured, report the local path and say the upload was skipped
97
+ 5. To share a screenshot outside the machine, upload it to agent-fs with `agent-fs write <path> --file /tmp/<name>.png -m "<what it shows>"` (binary-safe; `--content` mangles PNGs), keep it there as the original, and embed it in a PR or GitHub comment as a GitHub user attachment (`github-attach` skill): `![caption](https://github.com/user-attachments/assets/<uuid>)`. Use `agent-fs share-create <path>` for Slack or Linear. If agent-fs is not configured, report the local path and say the upload was skipped
98
98
 
99
99
  **For manual testing**:
100
100
  1. Present each test case's steps to the user
@@ -117,7 +117,7 @@ For each test case, record the actual result and pass/fail status.
117
117
  ### Step 4: Capture Evidence
118
118
 
119
119
  Gather evidence for the QA report:
120
- - **Screenshots**: Via `agent-browser screenshot` (uploaded to agent-fs with a signed URL when they must be shared) or user-provided
120
+ - **Screenshots**: Via `agent-browser screenshot` (kept on agent-fs; GitHub user attachments in a PR, `share-create` links elsewhere) or user-provided
121
121
  - **Videos**: Session recording URLs (Loom, etc.)
122
122
  - **Logs**: Console output, error messages, relevant log lines
123
123
  - **External links**: Sentry issues, CI/CD runs, Grafana dashboards, PR URLs
@@ -108,8 +108,8 @@ Use these shapes as a starting point, then confirm them against the current exec
108
108
 
109
109
  **Before you add the first `system-one-decision` node to a workflow, confirm its key works.** A node with no working key fails its whole run, and a save only warns. Do these in order and stop at the first failure:
110
110
 
111
- 1. Pick the provider. `typesafe` (the default) needs the global secret `TYPESAFE_API_KEY`. `openrouter` needs `OPENROUTER_API_KEY`. `laya` needs the global secret `LAYA_API_KEY` and the global config `LAYA_URL`, the base URL of its server. Use the provider the requester named. If they named none, use `typesafe`. If its key is missing but another provider's key exists, ask which to use rather than switching, because the accounts bill separately.
112
- 2. Check the key is set: `get-config` with `key` set to that name and no `includeSecrets`. A masked value (`********`) means a value exists. No entry means it is missing. Never pass `includeSecrets`, and never read the value. For `laya`, check `LAYA_URL` the same way; it is not secret, so its value shows.
111
+ 1. Pick the provider. `typesafe` (the default) needs the global secret `TYPESAFE_API_KEY`. `openrouter` needs `OPENROUTER_API_KEY`. `laya` needs the global secret `LAYA_API_KEY` and the global config `LAYA_URL`, the base URL of its server. `openai` needs `OPENAI_DECISIONS_API_KEY` (never `OPENAI_API_KEY`). `cloudflare` needs the global secret `CLOUDFLARE_API_TOKEN` and the global config `CLOUDFLARE_ACCOUNT_ID`. Use the provider the requester named. If they named none, use `typesafe`. If its key is missing but another provider's key exists, ask which to use rather than switching, because the accounts bill separately.
112
+ 2. Check the key is set: `get-config` with `key` set to that name and no `includeSecrets`. A masked value (`********`) means a value exists. No entry means it is missing. Never pass `includeSecrets`, and never read the value. For `laya`, check `LAYA_URL` the same way, and for `cloudflare`, `CLOUDFLARE_ACCOUNT_ID`; neither is secret, so the value shows.
113
113
  3. Confirm it works with one cheap call. Create a throwaway one-node workflow, trigger it, read the run, then `delete-workflow` it:
114
114
 
115
115
  ```json
@@ -162,7 +162,7 @@ Afterwards, a `warnings` entry on `create-workflow` or a patch tool means the ke
162
162
  }
163
163
  ```
164
164
 
165
- - `provider` is `typesafe` (default), `openrouter`, or `laya`, and must be a literal, not a `{{token}}`. `model` is that provider's own id (`jev-1.13.0` on `typesafe`, `typesafe/jev-1.13` on `openrouter`, a checkpoint name such as `multilingual` on `laya`); leave it unset for the provider's default. `laya` has no default and sends no `model`, because it silently ignores one it does not know: leave it unset unless you mean a specific checkpoint. All three take the same request and return the same answers. There is no fallback between them. Never use OpenRouter's `typesafe/jev-router`, which is a chat router that hands the request to another model.
165
+ - `provider` is `typesafe` (default), `openrouter`, `laya`, `openai`, or `cloudflare`, and must be a literal, not a `{{token}}`. `model` is that provider's own id (`jev-1.13.0` on `typesafe`, `typesafe/jev-1.13` on `openrouter`, a checkpoint name such as `multilingual` on `laya`); `gpt-6-luna` on `openai`, `clef` (default) or `clef-flash` on `cloudflare`, which accepts no other id; leave it unset for the provider's default. `laya` has no default and sends no `model`, because it silently ignores one it does not know: leave it unset unless you mean a specific checkpoint. Every provider returns the same output; `openai` gets a translated request, and an OpenAI refusal of any question fails the step. `cloudflare` takes at most 64 questions. There is no fallback between them. Never use OpenRouter's `typesafe/jev-router`, which is a chat router that hands the request to another model.
166
166
  - `state` is required: text, a string array, or a JSON object. An exact `{{token}}` keeps the upstream JSON type. Every question in one call shares the state and cannot see the other answers, so a dependent judgment needs its own node.
167
167
  - Each question is `noul` (probability that a claim is true; optional `criteria: { true, false }`), `choice` (2 to 255 options; `criteria: { option: description }`), or `score` (2 to 10 ordered levels; `criteria: [level, ...]`).
168
168
  - `returns` repeats every question id and its type. A mismatch is rejected when the workflow is saved.
@@ -171,7 +171,7 @@ Afterwards, a `warnings` entry on `create-workflow` or a patch tool means the ke
171
171
  - `humanReview: { band: { min, max }, approvers, title?, timeout?, notifications? }` sends an answer to a person when `min <= confidence <= max` (0 to 1, both ends inside). It raises a `human-in-the-loop` approval (same approvers, timeout, notifications, `waiting` run state), so use the same `approvers` shape. `choice` and `score` are tested on their `confidence` (on `laya` that is its `answer_confidence`, the top probability); a `noul` on `max(noul, 1 - noul)`. Any answer in the band makes the run wait. `next` must then be a port map: `approved` (required, every accepted answer), and optionally `rejected` and `timeout`; a string or list `next` is refused. The output stays `{ model, answers, usage }` on every path, plus `review` (`status`, and per question `confidence`, `inBand`, `decidedBy`). A person's answer replaces the model's in `answers`; `probabilities` and `confidence` stay the model's.
172
172
  - On `laya`, ask `choice` questions, not `noul`, until a `noul` question is checked against known inputs. On laya-server 0.1.0 a `noul` sentiment question returned close to 0 even for clearly positive text, while the same judgment as a `choice` answered correctly. This is how the model answered, not a node rule. After a run, read `<node-id>.routing.model` to see which laya checkpoint answered. A complete laya workflow (manual trigger with `{"text": "..."}`, one `choice` question, a review band, and a `property-match` branch on `<node-id>.answers.<question>.choice`) is in `docs-site/content/docs/(documentation)/concepts/workflows.mdx`, section "Example: a laya decision end to end".
173
173
  - Do not set `retry` or `validation.retry` on a `system-one-decision` node. It retries connection errors, 408, 429, and 5xx itself (`config.maxRetries`, 0 to 3, default 2) inside `config.timeoutMs` (default 30000). A 401, a 422, or an answer that fails validation ends after one attempt.
174
- - The node reads its provider's key (`TYPESAFE_API_KEY`, `OPENROUTER_API_KEY`, or `LAYA_API_KEY`, and for `laya` the server URL `LAYA_URL`) server-side. The key never appears in the definition, the step output, or an error. A run whose key or `LAYA_URL` is missing fails before any node executes, and a 401 or 403 fails the step as `<KEY> was rejected`. An unresolved `{{token}}` fails the step before any request.
174
+ - The node reads its provider's key (`TYPESAFE_API_KEY`, `OPENROUTER_API_KEY`, `LAYA_API_KEY`, `OPENAI_DECISIONS_API_KEY`, or `CLOUDFLARE_API_TOKEN`, plus `LAYA_URL` for `laya` and `CLOUDFLARE_ACCOUNT_ID` for `cloudflare`) server-side. The key never appears in the definition, the step output, or an error. A run whose key or `LAYA_URL` is missing fails before any node executes, and a 401 or 403 fails the step as `<KEY> was rejected`. An unresolved `{{token}}` fails the step before any request.
175
175
 
176
176
  ### `swarm-script`
177
177
 
package/tsconfig.json CHANGED
@@ -13,10 +13,10 @@
13
13
  "moduleResolution": "bundler",
14
14
  "allowImportingTsExtensions": true,
15
15
 
16
- // Path aliases
17
- "baseUrl": ".",
16
+ // Path aliases. No `baseUrl`: TS 7 (tsgo) removed it, and relative
17
+ // `paths` resolve against this file in both TS 5 and TS 7.
18
18
  "paths": {
19
- "@/*": ["src/*"]
19
+ "@/*": ["./src/*"]
20
20
  },
21
21
  "verbatimModuleSyntax": true,
22
22
  "noEmit": true,
@@ -1,99 +0,0 @@
1
- import {
2
- getDbClient,
3
- init_db
4
- } from "./cli-0wn3ypqv.js";
5
- import"./cli-v0e7jpr5.js";
6
- import"./cli-3qhyh31j.js";
7
- import"./cli-vbr859rz.js";
8
- import"./cli-n7h1kqpf.js";
9
- import"./cli-7mm2r1kp.js";
10
- import"./cli-g5erf0zt.js";
11
- import"./cli-yj790e19.js";
12
- import"./cli-ywybs5as.js";
13
- import"./cli-gd4favx9.js";
14
- import"./cli-agamgm0p.js";
15
- import"./cli-5c2j5yvx.js";
16
- import"./cli-1a2j50m0.js";
17
- import"./cli-f9w1semm.js";
18
- import"./cli-ej6gbxfb.js";
19
- import"./cli-g3qgrzck.js";
20
- import"./cli-sd0mxa3c.js";
21
- import"./cli-w5e1d1vv.js";
22
- import"./cli-1d3w4xm3.js";
23
- import"./cli-zf8jjwex.js";
24
- import {
25
- init_secret_scrubber,
26
- scrubSecrets
27
- } from "./cli-qt5wzq6v.js";
28
- import"./cli-bc05qbss.js";
29
-
30
- // src/be/boot-scrub-logs.ts
31
- init_secret_scrubber();
32
- init_db();
33
- var SCRUB_KEY = "boot-scrub-logs-v2";
34
- var CURSOR_KEY = "boot-scrub-logs-v2-cursor";
35
- var BATCH_SIZE = 200;
36
- var yieldTick = () => new Promise((r) => setTimeout(r, 5));
37
- async function runBootScrubLogs() {
38
- const done = await getDbClient().get("SELECT key FROM seed_state WHERE kind = ? AND key = ?", ["maintenance", SCRUB_KEY]);
39
- if (done)
40
- return;
41
- const savedCursor = (await getDbClient().get("SELECT seededHash FROM seed_state WHERE kind = ? AND key = ?", ["maintenance", CURSOR_KEY]))?.seededHash ?? "";
42
- const lastProcessedId = savedCursor || "";
43
- const totalRemaining = (await getDbClient().get(`SELECT COUNT(*) as count FROM session_logs
44
- WHERE id > ?
45
- AND (content LIKE '%lin!_oauth!_%' ESCAPE '!'
46
- OR content LIKE '%lin!_api!_%' ESCAPE '!'
47
- OR content LIKE '%npm!_%' ESCAPE '!'
48
- OR content LIKE '%ATATT%')`, [lastProcessedId]))?.count ?? 0;
49
- if (totalRemaining === 0) {
50
- await markDone();
51
- return;
52
- }
53
- console.log(`[boot-scrub-logs] starting: ${totalRemaining} candidate rows remaining` + (lastProcessedId ? ` (resuming from cursor ${lastProcessedId.slice(0, 8)}…)` : ""));
54
- const saveCursorSql = `INSERT INTO seed_state (kind, key, seededHash, seededAt)
55
- VALUES ('maintenance', '${CURSOR_KEY}', ?, datetime('now'))
56
- ON CONFLICT (kind, key) DO UPDATE SET seededHash = ?, seededAt = datetime('now')`;
57
- let scrubbed = 0;
58
- let scanned = 0;
59
- let cursor = lastProcessedId;
60
- for (;; ) {
61
- const rows = await getDbClient().query(`SELECT id, content FROM session_logs
62
- WHERE id > ?
63
- AND (content LIKE '%lin!_oauth!_%' ESCAPE '!'
64
- OR content LIKE '%lin!_api!_%' ESCAPE '!'
65
- OR content LIKE '%npm!_%' ESCAPE '!'
66
- OR content LIKE '%ATATT%')
67
- ORDER BY id ASC
68
- LIMIT ${BATCH_SIZE}`, [cursor]);
69
- if (rows.length === 0)
70
- break;
71
- const batchLastId = rows[rows.length - 1].id;
72
- await getDbClient().transaction(async (tx) => {
73
- for (const row of rows) {
74
- const cleaned = scrubSecrets(row.content);
75
- if (cleaned !== row.content) {
76
- await tx.run("UPDATE session_logs SET content = ? WHERE id = ?", [cleaned, row.id]);
77
- scrubbed++;
78
- }
79
- }
80
- await tx.run(saveCursorSql, [batchLastId, batchLastId]);
81
- });
82
- scanned += rows.length;
83
- cursor = batchLastId;
84
- await yieldTick();
85
- }
86
- await markDone();
87
- await getDbClient().run("DELETE FROM seed_state WHERE kind = 'maintenance' AND key = ?", [
88
- CURSOR_KEY
89
- ]);
90
- console.log(`[boot-scrub-logs] complete: scanned=${scanned} scrubbed=${scrubbed}`);
91
- }
92
- async function markDone() {
93
- await getDbClient().run(`INSERT INTO seed_state (kind, key, seededHash, seededAt)
94
- VALUES ('maintenance', ?, 'done', datetime('now'))
95
- ON CONFLICT (kind, key) DO UPDATE SET seededHash = 'done', seededAt = datetime('now')`, [SCRUB_KEY]);
96
- }
97
- export {
98
- runBootScrubLogs
99
- };
@@ -1,168 +0,0 @@
1
- import {
2
- cosineSimilarity,
3
- deserializeEmbedding,
4
- getEmbeddingProvider,
5
- init_embedding,
6
- serializeEmbedding
7
- } from "./cli-v7fqehqd.js";
8
- import {
9
- getDbClient,
10
- init_db
11
- } from "./cli-0wn3ypqv.js";
12
- import {
13
- init_secret_scrubber,
14
- scrubSecrets
15
- } from "./cli-qt5wzq6v.js";
16
-
17
- // src/be/scripts/embeddings.ts
18
- init_secret_scrubber();
19
- init_db();
20
- init_embedding();
21
- var providerOverride = null;
22
- function embeddingProvider() {
23
- return providerOverride ?? getEmbeddingProvider();
24
- }
25
- function scriptEmbeddingText(script) {
26
- return scrubSecrets([script.description, script.intent, script.signatureJson].join(`
27
- `));
28
- }
29
- function rowToScript(row) {
30
- return {
31
- id: row.id,
32
- name: row.name,
33
- scope: row.scope,
34
- scopeId: row.scopeId ?? null,
35
- source: row.source,
36
- description: row.description,
37
- intent: row.intent,
38
- signatureJson: row.signatureJson,
39
- argsJsonSchema: row.argsJsonSchema ?? null,
40
- contentHash: row.contentHash,
41
- version: row.version,
42
- isScratch: row.isScratch === 1,
43
- typeChecked: row.typeChecked === 1,
44
- fsMode: row.fsMode,
45
- createdByAgentId: row.createdByAgentId ?? null,
46
- createdAt: row.createdAt,
47
- updatedAt: row.updatedAt
48
- };
49
- }
50
- async function embedScript(script) {
51
- const text = scriptEmbeddingText(script);
52
- const provider = embeddingProvider();
53
- const embedding = await provider.embed(text);
54
- if (!embedding)
55
- return;
56
- if (embedding.length !== provider.dimensions) {
57
- console.error(`[script-embed] dimension mismatch for "${script.name}": expected=${provider.dimensions} got=${embedding.length}, skipping`);
58
- return;
59
- }
60
- await getDbClient().run(`INSERT INTO script_embeddings (
61
- scriptId, embedding, embeddingModel, embeddedText, embeddedAt
62
- )
63
- VALUES (?, ?, ?, ?, ?)
64
- ON CONFLICT(scriptId) DO UPDATE SET
65
- embedding = excluded.embedding,
66
- embeddingModel = excluded.embeddingModel,
67
- embeddedText = excluded.embeddedText,
68
- embeddedAt = excluded.embeddedAt`, [script.id, serializeEmbedding(embedding), provider.name, text, new Date().toISOString()]);
69
- }
70
- async function candidateRows(scope, scopeId) {
71
- const params = [];
72
- let where = "s.isScratch = 0";
73
- if (scope === "global") {
74
- where += " AND s.scope = 'global' AND s.scopeId IS NULL";
75
- } else if (scope === "agent") {
76
- where += " AND s.scope = 'agent' AND s.scopeId = ?";
77
- params.push(scopeId ?? "");
78
- } else if (scopeId) {
79
- where += " AND ((s.scope = 'agent' AND s.scopeId = ?) OR (s.scope = 'global' AND s.scopeId IS NULL))";
80
- params.push(scopeId);
81
- } else {
82
- where += " AND s.scope = 'global' AND s.scopeId IS NULL";
83
- }
84
- return getDbClient().query(`SELECT
85
- s.*,
86
- e.scriptId,
87
- e.embedding,
88
- e.embeddingModel,
89
- e.embeddedText,
90
- e.embeddedAt
91
- FROM script_embeddings e
92
- JOIN scripts s ON s.id = e.scriptId
93
- WHERE ${where}`, params);
94
- }
95
- async function scriptRows(scope, scopeId) {
96
- const params = [];
97
- let where = "isScratch = 0";
98
- if (scope === "global") {
99
- where += " AND scope = 'global' AND scopeId IS NULL";
100
- } else if (scope === "agent") {
101
- where += " AND scope = 'agent' AND scopeId = ?";
102
- params.push(scopeId ?? "");
103
- } else if (scopeId) {
104
- where += " AND ((scope = 'agent' AND scopeId = ?) OR (scope = 'global' AND scopeId IS NULL))";
105
- params.push(scopeId);
106
- } else {
107
- where += " AND scope = 'global' AND scopeId IS NULL";
108
- }
109
- return getDbClient().query(`SELECT *, NULL as scriptId, NULL as embedding, NULL as embeddingModel, NULL as embeddedText, NULL as embeddedAt FROM scripts WHERE ${where}`, params);
110
- }
111
- function nameMatchBonus(script, query) {
112
- const trimmed = query.trim().toLowerCase();
113
- if (!trimmed)
114
- return 0;
115
- return script.name.toLowerCase().includes(trimmed) ? 1 : 0;
116
- }
117
- async function lexicalFallback(args) {
118
- const query = args.query.trim().toLowerCase();
119
- return (await scriptRows(args.scope, args.scopeId)).map(rowToScript).filter((script) => {
120
- if (!query)
121
- return true;
122
- return [script.name, script.description, script.intent].join(`
123
- `).toLowerCase().includes(query);
124
- }).map((script) => {
125
- const bonus = nameMatchBonus(script, args.query);
126
- return {
127
- script,
128
- score: bonus || 0.5,
129
- semanticScore: 0,
130
- nameMatchBonus: bonus
131
- };
132
- }).sort((a, b) => b.score - a.score).slice(0, args.limit ?? 10);
133
- }
134
- async function searchScripts(args) {
135
- const provider = embeddingProvider();
136
- const queryEmbedding = await provider.embed(args.query);
137
- if (!queryEmbedding)
138
- return lexicalFallback(args);
139
- const candidates = await candidateRows(args.scope, args.scopeId);
140
- if (candidates.length === 0)
141
- return lexicalFallback(args);
142
- const results = [];
143
- for (const row of candidates) {
144
- const stored = deserializeEmbedding(row.embedding);
145
- if (stored.length !== queryEmbedding.length)
146
- continue;
147
- const script = rowToScript(row);
148
- const semanticScore = cosineSimilarity(queryEmbedding, stored);
149
- const bonus = nameMatchBonus(script, args.query);
150
- results.push({
151
- script,
152
- score: 0.7 * semanticScore + 0.3 * bonus,
153
- semanticScore,
154
- nameMatchBonus: bonus
155
- });
156
- }
157
- if (results.length === 0)
158
- return lexicalFallback(args);
159
- return results.sort((a, b) => b.score - a.score).slice(0, args.limit ?? 10);
160
- }
161
- async function reembedAllScripts() {
162
- const rows = await getDbClient().query("SELECT *, NULL as scriptId, NULL as embedding, NULL as embeddingModel, NULL as embeddedText, NULL as embeddedAt FROM scripts WHERE isScratch = 0 ORDER BY updatedAt ASC");
163
- for (const row of rows) {
164
- await embedScript(rowToScript(row));
165
- }
166
- }
167
-
168
- export { embeddingProvider, embedScript, searchScripts, reembedAllScripts };