@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.
- package/README.md +1 -1
- package/dist/acp-adapter-yzfxn8vj.js +23 -0
- package/dist/{actions-hp2h32dx.js → actions-qz3m692w.js} +24 -28
- package/dist/{amp-adapter-zfd7djyx.js → amp-adapter-j1xbmsqz.js} +7 -7
- package/dist/{app-w2d26h4f.js → app-43vrdmv8.js} +9 -10
- package/dist/{assistant-45pc4en7.js → assistant-ertffmka.js} +25 -29
- package/dist/{boot-reembed-k1q2s4fc.js → boot-reembed-998jtpdg.js} +12 -15
- package/dist/{boot-reembed-6rhcpsjf.js → boot-reembed-s7k7c6v2.js} +13 -15
- package/dist/boot-scrub-sweep-nepsk4t1.js +211 -0
- package/dist/{boot-seeds-ex93edx7.js → boot-seeds-vvzs1zhk.js} +12 -12
- package/dist/{claude-adapter-hcxd0szm.js → claude-adapter-2zvmekrp.js} +15 -17
- package/dist/{claude-managed-adapter-fz7xps2r.js → claude-managed-adapter-s49wbk8t.js} +5 -5
- package/dist/{claude-managed-setup-xx6f15h9.js → claude-managed-setup-cvhqq8qn.js} +4 -4
- package/dist/{claude-sdk-session-6nb9raem.js → claude-sdk-session-kkbxtw5q.js} +2624 -2606
- package/dist/{cli-etbrt8x1.js → cli-0nhdwxd5.js} +4 -4
- package/dist/{cli-jeefgppq.js → cli-0qjcsxgz.js} +7 -7
- package/dist/{cli-6behs2bt.js → cli-32bca7nr.js} +1 -1
- package/dist/{cli-gt8v96qx.js → cli-3ddybbbx.js} +4 -4
- package/dist/{acp-adapter-rxvek4ym.js → cli-3qn4r334.js} +317 -35
- package/dist/{cli-1d3w4xm3.js → cli-4r1sjfc4.js} +14 -6
- package/dist/{cli-691f2rxm.js → cli-66zh26sp.js} +68 -16
- package/dist/{cli-et8wdyqh.js → cli-68r1j4sg.js} +9 -9
- package/dist/{cli-xb7kyanp.js → cli-8kgvmkak.js} +3 -3
- package/dist/{cli-fdpkw8vk.js → cli-8t229cmr.js} +8 -8
- package/dist/{cli-gc54qc0p.js → cli-aqcey741.js} +1 -1
- package/dist/{cli-4q4cmr4t.js → cli-cpfmqz3n.js} +8 -8
- package/dist/{cli-a9bw0xxt.js → cli-df56tqdw.js} +997 -408
- package/dist/{cli-n7h1kqpf.js → cli-dmtrxqhg.js} +6 -1
- package/dist/{cli-xfb7333f.js → cli-dw2q9f7g.js} +5 -5
- package/dist/{cli-4drstbb9.js → cli-ecknp7p1.js} +81 -23
- package/dist/{cli-v0pvvhfq.js → cli-efnd2kce.js} +36 -1
- package/dist/{cli-1wetf34q.js → cli-f2n17zhp.js} +1 -1
- package/dist/{cli-2c8eky5y.js → cli-feh3dkah.js} +1 -1
- package/dist/cli-fn697bnt.js +126 -0
- package/dist/{cli-v5pr2fgt.js → cli-gt8azyet.js} +3 -3
- package/dist/{cli-dbszf3rw.js → cli-h3x613ze.js} +4 -4
- package/dist/{cli-nwhb8y2e.js → cli-hf5s9pgf.js} +1 -1
- package/dist/cli-j2jbr8af.js +516 -0
- package/dist/{cli-agjzafns.js → cli-jhm6hzjn.js} +593 -10
- package/dist/{cli-j0tmc908.js → cli-jvj6a0cv.js} +484 -477
- package/dist/{cli-xxz89c2n.js → cli-mb75wpxf.js} +1 -1
- package/dist/{cli-07s39g1n.js → cli-mv2520nm.js} +1 -1
- package/dist/{cli-v90vfwyb.js → cli-mwegs4af.js} +5 -5
- package/dist/{cli-bz1gbac9.js → cli-p4ztb80h.js} +2 -2
- package/dist/{cli-1wd1n2ya.js → cli-rfphkzh5.js} +1 -1
- package/dist/{cli-976r1zqx.js → cli-rggdq8wq.js} +5 -5
- package/dist/{cli-3ajw5v5v.js → cli-rsy933yz.js} +6 -6
- package/dist/{cli-yj790e19.js → cli-tadfgd0t.js} +8 -1
- package/dist/{cli-cn53e7vc.js → cli-ttbsse3f.js} +6 -1
- package/dist/{cli-dyqsrqcf.js → cli-v2a8x45d.js} +4 -4
- package/dist/{cli-wbvnn6tk.js → cli-v6vv7dy8.js} +91 -9
- package/dist/{cli-z2ap2c0c.js → cli-vzc73wet.js} +90 -55
- package/dist/cli-wt7ccy4r.js +2654 -0
- package/dist/{cli-4cn19jvn.js → cli-x7kpr72a.js} +3 -3
- package/dist/{cli-003785v9.js → cli-xvc3q9br.js} +1 -1
- package/dist/{cli-v0e7jpr5.js → cli-xvdgasgy.js} +13 -4
- package/dist/{cli-asqeg4ve.js → cli-y59h2pk9.js} +2 -2
- package/dist/{cli-0wn3ypqv.js → cli-yshaazs1.js} +14121 -3478
- package/dist/{cli-wg8yjqtw.js → cli-ysnyhws9.js} +16 -3
- package/dist/cli-zp67qg5x.js +92 -0
- package/dist/{cli-g3qgrzck.js → cli-zsh093hk.js} +71 -3
- package/dist/{cli-ma3zvh39.js → cli-zy7vwsne.js} +6066 -5829
- package/dist/cli.js +79 -26
- package/dist/{codex-adapter-pcxdn10v.js → codex-adapter-dw1wxqt8.js} +10 -10
- package/dist/{codex-hook-b1fb7c2k.js → codex-hook-d2rkvf39.js} +1 -1
- package/dist/{codex-login-059nm145.js → codex-login-terbdsqq.js} +2 -2
- package/dist/{codex-session-runner-xzwwddp8.js → codex-session-runner-3cgb8y1g.js} +10 -10
- package/dist/{commands-98at8mkn.js → commands-mhxam6z2.js} +9 -9
- package/dist/{cursor-adapter-dkg6qnkp.js → cursor-adapter-2qda3st7.js} +6 -6
- package/dist/{db-01g8wtvw.js → db-sjks418k.js} +11 -9
- package/dist/{devin-adapter-qmttt2fz.js → devin-adapter-bffjj5n4.js} +2 -2
- package/dist/{dispatcher-nn2k1wxd.js → dispatcher-1es759rn.js} +22 -26
- package/dist/{dsh-adapter-w4d4vwdq.js → dsh-adapter-bek4cyw9.js} +6 -6
- package/dist/{e2b-9e4g2hvt.js → e2b-nd50eccg.js} +1 -1
- package/dist/{event-bus-z7v2t26e.js → event-bus-vnfthafg.js} +2 -2
- package/dist/grok-adapter-ar9cw9jg.js +29 -0
- package/dist/{handlers-b0kqsbg8.js → handlers-1gkbhktr.js} +25 -29
- package/dist/{hook-sap7v1aj.js → hook-ds2zxq9v.js} +16 -18
- package/dist/{hook-pz50gqep.js → hook-vxa3tcsy.js} +10 -12
- package/dist/{http-ncr8rmd0.js → http-3h21z9md.js} +679 -227
- package/dist/{index-c4aqcyz1.js → index-9b65j1m5.js} +11 -11
- package/dist/{index-r46s01nq.js → index-bn6cy8ps.js} +22 -26
- package/dist/{index-38kqdt3e.js → index-dkfxpkmm.js} +23 -27
- package/dist/{index-630kj5vd.js → index-f8xnqrye.js} +55 -43
- package/dist/{index-fdk1t4d6.js → index-n0rxa4ca.js} +11962 -9900
- package/dist/{index-9nrj7797.js → index-n99fycq7.js} +22 -26
- package/dist/{keepalive-31613r2h.js → keepalive-3xspa9jw.js} +14 -11
- package/dist/{lead-mx59tr5s.js → lead-6qphc124.js} +43 -43
- package/dist/{maintenance-55ff39ca.js → maintenance-0teem1bb.js} +10 -12
- package/dist/{node-f0ykebbv.js → node-9sg7ajby.js} +25 -7
- package/dist/{oauth-refresh-sweep-anma954w.js → oauth-refresh-sweep-sh9q25xp.js} +13 -10
- package/dist/{onboard-b2fy8ftb.js → onboard-54qmnqxe.js} +4 -3
- package/dist/{opencode-adapter-p1s92tmy.js → opencode-adapter-wjfa2wvd.js} +6 -6
- package/dist/{otel-impl-9brvt7xv.js → otel-impl-ycqzp2a1.js} +2 -2
- package/dist/{pi-mono-adapter-kz4rrwvd.js → pi-mono-adapter-e77e9zst.js} +6 -6
- package/dist/{pricing-refresh-7w8mbmva.js → pricing-refresh-atnkngqs.js} +10 -10
- package/dist/{rbac-roles-ejp7qwvb.js → rbac-roles-9pjphh9q.js} +10 -10
- package/dist/{rbac-roles-nhk4r7bc.js → rbac-roles-j78wdksm.js} +10 -10
- package/dist/{render-v2-2gzt8skq.js → render-v2-pxjs49fx.js} +9 -10
- package/dist/{setup-5et8t412.js → setup-ymej0xtx.js} +2 -2
- package/dist/{work-objects-tb0er7qa.js → work-objects-3nh4ymzb.js} +26 -30
- package/dist/{worker-62cv075d.js → worker-qa9fkz5s.js} +43 -43
- package/dist/{x-vbxb31jr.js → x-ma4gnfgy.js} +2 -2
- package/openapi.json +457 -31
- package/package.json +14 -6
- package/plugin/commands/create-pr.md +7 -1
- package/plugin/pi-skills/create-pr/SKILL.md +7 -1
- package/src/agentmail/app.ts +5 -4
- package/src/be/automation-preflight.ts +11 -9
- package/src/be/boot-scrub-sweep.ts +302 -0
- package/src/be/connector-codes.ts +81 -0
- package/src/be/crypto/key-bootstrap.ts +1 -1
- package/src/be/db/approvals.ts +15 -1
- package/src/be/db/codex-oauth-device-flows.ts +40 -0
- package/src/be/db/config-secrets.ts +31 -0
- package/src/be/db/runtime.ts +4 -0
- package/src/be/db/script-runs.ts +15 -0
- package/src/be/db/tasks/write.ts +1 -1
- package/src/be/db-queries/mcp-oauth.ts +5 -0
- package/src/be/db-queries/oauth.ts +77 -0
- package/src/be/db.ts +162 -59
- package/src/be/events.ts +17 -1
- package/src/be/memory/index-content.ts +2 -2
- package/src/be/memory/providers/sqlite-store.ts +63 -11
- package/src/be/memory/types.ts +14 -0
- package/src/be/migrations/197_connector_codes.sql +23 -0
- package/src/be/migrations/198_permission_audit_guest.sql +33 -0
- package/src/be/migrations/200_backfill_auto_memory_expiry.sql +20 -0
- package/src/be/migrations/201_workflow_replay_columns.sql +10 -0
- package/src/be/migrations/202_codex_oauth_device_flows.sql +24 -0
- package/src/be/model-tier-resolution.ts +2 -1
- package/src/be/model-validation.ts +1 -1
- package/src/be/pricing-normalize.ts +3 -0
- package/src/be/rbac-audit.ts +2 -1
- package/src/be/scripts/db.ts +28 -4
- package/src/be/scripts/source-secrets.ts +37 -0
- package/src/be/scripts/typecheck.ts +23 -2
- package/src/be/scrub-json.ts +32 -0
- package/src/be/sealed-json.ts +59 -0
- package/src/be/secret-registry.ts +131 -0
- package/src/be/seed-pricing.ts +14 -0
- package/src/be/users.ts +7 -1
- package/src/be/workflow-replay.ts +77 -0
- package/src/cli.tsx +7 -0
- package/src/commands/provider-credentials.ts +46 -8
- package/src/commands/runner.ts +2 -10
- package/src/extensions/contract-types.generated.ts +1 -1
- package/src/github/app.ts +4 -4
- package/src/heartbeat/heartbeat.ts +20 -8
- package/src/hooks/pr-body-guard.ts +1 -1
- package/src/http/agents.ts +1 -0
- package/src/http/approval-requests.ts +1 -0
- package/src/http/apps.ts +3 -0
- package/src/http/auth.ts +4 -1
- package/src/http/codex-oauth-device.ts +8 -10
- package/src/http/codex-oauth-keep-warm.ts +2 -2
- package/src/http/config-values.ts +59 -0
- package/src/http/config.ts +5 -0
- package/src/http/db-query-bounded.ts +3 -0
- package/src/http/db-query-shared.ts +107 -15
- package/src/http/db-query.ts +10 -2
- package/src/http/extensions.ts +1 -0
- package/src/http/index.ts +23 -6
- package/src/http/integrations.ts +1 -38
- package/src/http/ip-rate-limit.ts +82 -0
- package/src/http/kv.ts +38 -4
- package/src/http/mcp-servers.ts +1 -0
- package/src/http/memory.ts +9 -0
- package/src/http/models-catalog.ts +2 -0
- package/src/http/operator-actor.ts +4 -0
- package/src/http/page-proxy.ts +22 -0
- package/src/http/pages.ts +4 -2
- package/src/http/realtime.ts +1 -1
- package/src/http/request-principal.ts +14 -1
- package/src/http/script-connections.ts +8 -0
- package/src/http/script-runs.ts +12 -4
- package/src/http/scripts.ts +15 -0
- package/src/http/session-cost-recompute.ts +3 -2
- package/src/http/tasks.ts +9 -0
- package/src/http/users.ts +226 -0
- package/src/http/workflows.ts +3 -2
- package/src/http.ts +1 -0
- package/src/integrations/kapso/client.ts +3 -1
- package/src/jira/app.ts +2 -2
- package/src/kv-view.ts +324 -0
- package/src/linear/app.ts +2 -2
- package/src/oauth/mcp-wrapper.ts +1 -1
- package/src/prompts/memories.ts +42 -1
- package/src/providers/acp-adapter.ts +85 -24
- package/src/providers/acp-target-catalog.ts +54 -1
- package/src/providers/acp-targets.ts +358 -4
- package/src/providers/amp-adapter.ts +1 -1
- package/src/providers/cursor-adapter.ts +1 -1
- package/src/providers/grok-adapter.ts +186 -0
- package/src/providers/index.ts +5 -1
- package/src/providers/pricing-sources.md +6 -0
- package/src/providers/reasoning-effort.ts +17 -1
- package/src/providers/types.ts +2 -1
- package/src/rbac/can.ts +4 -3
- package/src/rbac/legacy-policy.ts +3 -3
- package/src/rbac/types.ts +6 -0
- package/src/script-workflows/supervisor.ts +11 -2
- package/src/scripts-runtime/eval-harness.ts +2 -12
- package/src/scripts-runtime/executors/quickjs-bundle.ts +152 -0
- package/src/scripts-runtime/executors/quickjs-prelude.ts +285 -0
- package/src/scripts-runtime/executors/quickjs-runner.ts +580 -0
- package/src/scripts-runtime/executors/quickjs-worker.ts +81 -0
- package/src/scripts-runtime/executors/quickjs.ts +196 -0
- package/src/scripts-runtime/executors/registry.ts +2 -0
- package/src/scripts-runtime/executors/sourcemap.ts +79 -0
- package/src/scripts-runtime/script-error-hints.ts +14 -0
- package/src/scripts-runtime/swarm-sdk.ts +9 -2
- package/src/scripts-runtime/types/stdlib.d.ts +27 -8
- package/src/scripts-runtime/types/swarm-extension.d.ts +3 -0
- package/src/scripts-runtime/types/swarm-sdk.d.ts +27 -8
- package/src/server-user.ts +2 -20
- package/src/server.ts +3 -1
- package/src/slack/app.ts +4 -0
- package/src/slack/config.ts +3 -1
- package/src/slack/egress-scrub.ts +87 -0
- package/src/tests/acp-adapter.test.ts +191 -2
- package/src/tests/boot-scrub-sweep.test.ts +390 -0
- package/src/tests/budget-user-scope.test.ts +7 -21
- package/src/tests/check-pr-body.test.ts +149 -6
- package/src/tests/check-text-columns.test.ts +145 -0
- package/src/tests/claude-adapter-binary.test.ts +1 -1
- package/src/tests/claude-sdk-process.fixture.ts +13 -2
- package/src/tests/codex-oauth-device.test.ts +23 -37
- package/src/tests/codex-oauth-keep-warm.test.ts +29 -0
- package/src/tests/console-scrub.test.ts +141 -0
- package/src/tests/credential-check.test.ts +90 -0
- package/src/tests/db-query-denylist.test.ts +202 -0
- package/src/tests/db-task-read-contract.test.ts +1 -0
- package/src/tests/db-task-write-contract.test.ts +1 -0
- package/src/tests/docs-index-footprint.test.js +3 -3
- package/src/tests/entrypoint-acp-target-binary.test.ts +44 -1
- package/src/tests/events-scrub.test.ts +88 -0
- package/src/tests/explicit-model-validation.test.ts +81 -0
- package/src/tests/extensions-pre-task.test.ts +33 -1
- package/src/tests/fixtures/grok/acp-updates-recorded.jsonl +53 -0
- package/src/tests/fixtures/grok/prompt-response-meta.json +36 -0
- package/src/tests/fixtures/secret-corpus.ts +320 -0
- package/src/tests/grok-adapter.test.ts +647 -0
- package/src/tests/heartbeat-checklist.test.ts +44 -0
- package/src/tests/integration-disable-flags.test.ts +156 -0
- package/src/tests/kv-http.test.ts +34 -0
- package/src/tests/kv-tool.test.ts +274 -1
- package/src/tests/kv-view.test.ts +147 -0
- package/src/tests/mcp-user-route.test.ts +257 -15
- package/src/tests/memory-injection-outcome.test.ts +143 -0
- package/src/tests/model-tier-resolution.test.ts +76 -3
- package/src/tests/page-guest-session.test.ts +424 -0
- package/src/tests/page-proxy.test.ts +1 -1
- package/src/tests/page-viewer-auth.test.ts +22 -1
- package/src/tests/pr-body-leaks.test.ts +157 -2
- package/src/tests/preload.ts +10 -0
- package/src/tests/provider-registration.test.ts +3 -1
- package/src/tests/rbac-audit.test.ts +32 -0
- package/src/tests/rbac-mcp-admission-e2e.test.ts +4 -62
- package/src/tests/script-connections.test.ts +9 -0
- package/src/tests/script-executor-conformance.test.ts +3 -0
- package/src/tests/script-executor-quickjs.test.ts +442 -0
- package/src/tests/script-executor-registry.test.ts +6 -1
- package/src/tests/script-runs-http.test.ts +126 -1
- package/src/tests/script-runs-scrub.test.ts +275 -0
- package/src/tests/scripts-http.test.ts +82 -1
- package/src/tests/scripts-mcp-e2e.test.ts +42 -6
- package/src/tests/scripts-runtime.test.ts +37 -0
- package/src/tests/scrubbed-text-12e.test.ts +289 -0
- package/src/tests/sealed-key-guard.test.ts +166 -0
- package/src/tests/secret-canary-sweep.test.ts +958 -0
- package/src/tests/secret-registry.test.ts +355 -0
- package/src/tests/secret-rules.test.ts +230 -0
- package/src/tests/secret-scrubber.test.ts +317 -1
- package/src/tests/session-costs-golden.test.ts +17 -0
- package/src/tests/slack-egress-scrub.test.ts +216 -0
- package/src/tests/swarm-tool-result-gate.test.ts +143 -30
- package/src/tests/task-tools-ctx.test.ts +3 -0
- package/src/tests/user-token-routes.test.ts +342 -3
- package/src/tests/workflow-replay.test.ts +518 -0
- package/src/tests/workflow-scrub.test.ts +242 -0
- package/src/tests/workflow-system-one-decision-providers.test.ts +737 -0
- package/src/tools/db-query.ts +1 -1
- package/src/tools/inject-learning.ts +1 -1
- package/src/tools/kv/kv-get.ts +136 -6
- package/src/tools/send-task.ts +61 -17
- package/src/tools/utils.ts +186 -43
- package/src/tools/workflows/get-workflow-run.ts +3 -2
- package/src/types.ts +16 -1
- package/src/utils/console-scrub-install.ts +5 -0
- package/src/utils/console-scrub.ts +57 -0
- package/src/utils/credentials.ts +8 -0
- package/src/utils/page-session.ts +6 -2
- package/src/utils/pr-body-leaks.ts +149 -10
- package/src/utils/request-auth-context.ts +2 -0
- package/src/utils/secret-rules.generated.ts +2055 -0
- package/src/utils/secret-scrubber.ts +662 -36
- package/src/workflows/engine.ts +39 -4
- package/src/workflows/executors/notify.ts +6 -1
- package/src/workflows/executors/system-one-decision.ts +31 -12
- package/src/workflows/executors/system-one-openai-wire.ts +168 -0
- package/src/workflows/executors/system-one-providers.ts +112 -11
- package/src/workflows/executors/system-one-wire.ts +79 -0
- package/src/workflows/recovery.ts +10 -1
- package/src/workflows/resume.ts +62 -3
- package/src/workflows/retry-poller.ts +3 -0
- package/templates/ai-toolbox.manifest.json +2 -2
- package/templates/skills/agent-browser/SKILL.md +5 -5
- package/templates/skills/agent-browser/config.json +1 -1
- package/templates/skills/agent-browser/content.md +4 -4
- package/templates/skills/artifacts/content.md +17 -7
- package/templates/skills/jira-interaction/config.json +1 -1
- package/templates/skills/jira-interaction/content.md +56 -205
- package/templates/skills/linear-interaction/config.json +1 -1
- package/templates/skills/linear-interaction/content.md +31 -50
- package/templates/skills/pages/content.md +8 -4
- package/templates/skills/qa/content.md +2 -2
- package/templates/skills/workflow-iterate/content.md +4 -4
- package/tsconfig.json +3 -3
- package/dist/boot-scrub-logs-t8xg7wd7.js +0 -99
- package/dist/cli-0a7r5331.js +0 -168
- package/dist/cli-93rxw9yd.js +0 -951
- package/dist/cli-cvk6yzw5.js +0 -40
- package/dist/cli-dgnj0zcc.js +0 -40
- package/dist/cli-qt5wzq6v.js +0 -256
- package/dist/cli-v7fqehqd.js +0 -9281
- package/dist/cli-vbr859rz.js +0 -572
- 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.
|
|
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
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
32
|
+
## Making API calls
|
|
47
33
|
|
|
48
|
-
|
|
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
|
-
```
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
-
|
|
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
|
-
- **
|
|
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` →
|
|
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
|
|
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
|
|
466
|
-
|
|
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
|
|
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),
|
|
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): ``. 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` (
|
|
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
|
|
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 `
|
|
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 `
|
|
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
|
-
|
|
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
|
-
};
|
package/dist/cli-0a7r5331.js
DELETED
|
@@ -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 };
|