@desplega.ai/agent-swarm 1.165.0 → 1.167.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/dist/acp-adapter-zpvy6321.js +34 -0
- package/dist/{actions-jna0b3wm.js → actions-fq2zrwtf.js} +30 -34
- package/dist/{amp-adapter-0eve81pz.js → amp-adapter-5gbk7501.js} +7 -7
- package/dist/{anthropic-messages-hst62ws9.js → anthropic-messages-13yn502s.js} +4 -4
- package/dist/{app-75hm5cfa.js → app-nctetn1e.js} +11 -11
- package/dist/{assistant-yzd51j33.js → assistant-0aq8gjvj.js} +31 -35
- package/dist/{azure-openai-responses-mh8tvf78.js → azure-openai-responses-9st34pfz.js} +5 -5
- package/dist/{boot-reembed-z158xq32.js → boot-reembed-1ze5853n.js} +14 -16
- package/dist/{boot-reembed-2ex2mcsh.js → boot-reembed-fmp5ww69.js} +15 -16
- package/dist/boot-scrub-sweep-cbp8xd4e.js +212 -0
- package/dist/{boot-seeds-2bmnh18p.js → boot-seeds-22tx8a53.js} +13 -12
- package/dist/{claude-adapter-jbj1mycz.js → claude-adapter-0jhgeh1d.js} +25 -25
- package/dist/{claude-managed-adapter-17ggz09t.js → claude-managed-adapter-tzwxy803.js} +5 -5
- package/dist/{claude-managed-setup-ptm1nzm2.js → claude-managed-setup-nrhfx5b0.js} +5 -5
- package/dist/{claude-sdk-session-9re1g7r2.js → claude-sdk-session-wh77rh83.js} +2632 -2614
- package/dist/{cli-zsh093hk.js → cli-014vns2y.js} +63 -1
- package/dist/{cli-qvfk83fy.js → cli-13xwcqvj.js} +2 -2
- package/dist/{cli-8gpbwy09.js → cli-1yrcfa5s.js} +5 -5
- package/dist/{cli-xtgtyafv.js → cli-577bxkf6.js} +212 -451
- package/dist/{cli-ma3zvh39.js → cli-5qkcdv8c.js} +6118 -5874
- package/dist/{cli-cwxhbf43.js → cli-5t5my0h8.js} +85 -2
- package/dist/{cli-zvckv750.js → cli-69egj654.js} +2 -2
- package/dist/{cli-9xb89xca.js → cli-6bpvv8h4.js} +9 -9
- package/dist/{cli-90v942q1.js → cli-6qxmjpem.js} +8 -8
- package/dist/{cli-9866bd07.js → cli-6vfz44sr.js} +1 -1
- package/dist/{cli-32bca7nr.js → cli-7avy4v8w.js} +1 -1
- package/dist/{cli-xb3c6aat.js → cli-7mhy3ths.js} +21 -18
- package/dist/{cli-q38n4bq0.js → cli-95zs84qw.js} +3 -3
- package/dist/cli-a35hzdve.js +33 -0
- package/dist/{cli-x3x0qwky.js → cli-bxqez1p0.js} +51 -23
- package/dist/{cli-prt9emct.js → cli-c2tpw9ck.js} +3 -3
- package/dist/{cli-0n4fasz0.js → cli-c8r99akr.js} +16 -16
- package/dist/{cli-5anb0ev3.js → cli-cexctgn5.js} +89 -26
- package/dist/{cli-bns5c8k9.js → cli-cf2vgn9d.js} +105 -91
- package/dist/{cli-ng97fjq7.js → cli-cmxkbzzs.js} +33 -7
- package/dist/{cli-nexwh8zg.js → cli-g7k7zbcz.js} +12 -5
- package/dist/{cli-mmzwwptd.js → cli-hf5s9pgf.js} +1 -1
- package/dist/{cli-nvvfd8bq.js → cli-jbzbr36n.js} +4091 -3793
- package/dist/{cli-zn2v3t8v.js → cli-jvmtxqtc.js} +27 -15
- package/dist/{cli-pkke6geq.js → cli-km4x66j0.js} +83 -65
- package/dist/cli-kw0jcfje.js +516 -0
- package/dist/{cli-28smfvbn.js → cli-m7vmeepg.js} +32 -19
- package/dist/{cli-hpryr6em.js → cli-mb75wpxf.js} +1 -1
- package/dist/{cli-qdv8kgz7.js → cli-mkdsy1nq.js} +14018 -3333
- package/dist/{cli-b0f70z24.js → cli-mn8qkd8v.js} +1 -1
- package/dist/{cli-420bdgw0.js → cli-mv2520nm.js} +1 -1
- package/dist/{cli-n9ehc28t.js → cli-mxry91sa.js} +31 -10
- package/dist/{cli-wfajtmf7.js → cli-mxvnnv5q.js} +596 -13
- package/dist/cli-nkqjj42q.js +104 -0
- package/dist/{cli-e7t4snpa.js → cli-p8rt8spp.js} +5 -5
- package/dist/{cli-gh5yqzpe.js → cli-pkj1w46r.js} +12 -7
- package/dist/cli-q1vnz8wv.js +96 -0
- package/dist/{cli-fj86xr3c.js → cli-qd97v6z2.js} +2 -2
- package/dist/{cli-ba66wyhy.js → cli-qzmzwegq.js} +60 -20
- package/dist/{cli-5b2fjjzh.js → cli-r7eeddkq.js} +14 -9
- package/dist/{cli-8ssjez7e.js → cli-rhy7z1rp.js} +22 -11
- package/dist/{cli-4mevd1hf.js → cli-s9y81s7j.js} +5 -5
- package/dist/{cli-59jn5twa.js → cli-tc5zec7v.js} +7 -7
- package/dist/{cli-ttbsse3f.js → cli-tmhsxhb8.js} +1 -1
- package/dist/{cli-k6xx3pve.js → cli-tx2zvn23.js} +4 -4
- package/dist/{cli-pjxnr1jn.js → cli-ty4bzkqr.js} +5 -5
- package/dist/{cli-nfygw434.js → cli-v1pwxreq.js} +55 -52
- package/dist/{cli-ftry7975.js → cli-v1w7pbd8.js} +3 -2
- package/dist/{cli-10zmp1p7.js → cli-vr5avem2.js} +27 -32
- package/dist/{cli-bzr0ftht.js → cli-wnb9b2g3.js} +19 -0
- package/dist/cli-wt7ccy4r.js +2654 -0
- package/dist/{cli-50eg13rj.js → cli-wydz3feg.js} +549 -321
- package/dist/{cli-krqm5f11.js → cli-xezn9nkh.js} +16 -13
- package/dist/{cli-8kt0bmgx.js → cli-xf713zz0.js} +2 -2
- package/dist/{cli-x7afk5wm.js → cli-xvc3q9br.js} +1 -1
- package/dist/{cli-9s3h836g.js → cli-xvdgasgy.js} +1 -1
- package/dist/{cli-j0pdrmwg.js → cli-y0kjpfm9.js} +3 -3
- package/dist/{cli-6zcfw0x7.js → cli-y195hv1a.js} +1 -1
- package/dist/{cli-amwhs8h2.js → cli-ykt8f7va.js} +22 -9
- package/dist/{cli-1kzfvd1z.js → cli-ymmc1zxg.js} +15 -11
- package/dist/{cli-xnzrzets.js → cli-ypgba1a8.js} +2 -2
- package/dist/{cli-bdv39kgj.js → cli-z1dqhc9y.js} +31 -20
- package/dist/{cli-fw6vdcq5.js → cli-zp67qg5x.js} +34 -1
- package/dist/{cli-qbksc292.js → cli-zy39d433.js} +2 -0
- package/dist/cli.js +36 -32
- package/dist/{cloudflare-workers-ai-system-one-tt484t61.js → cloudflare-workers-ai-system-one-sta45jf9.js} +7 -5
- package/dist/{codex-adapter-3qnxshje.js → codex-adapter-cgesnjkr.js} +20 -20
- package/dist/{codex-login-brkxhhdg.js → codex-login-g1cyt5zm.js} +2 -2
- package/dist/{codex-session-runner-612wnapp.js → codex-session-runner-8kd7ddhr.js} +20 -20
- package/dist/{commands-2ybfcxkj.js → commands-h6zaaxym.js} +11 -10
- package/dist/{cursor-adapter-p3jgdehv.js → cursor-adapter-v8mm6bp5.js} +7 -7
- package/dist/{db-f4ans0jj.js → db-qg3myn53.js} +13 -10
- package/dist/{devin-adapter-dhzt01ff.js → devin-adapter-bffjj5n4.js} +2 -2
- package/dist/{dispatcher-pk182apd.js → dispatcher-7vnwj9qw.js} +28 -32
- package/dist/{dsh-adapter-7twaeps1.js → dsh-adapter-tz6hfp5r.js} +7 -7
- package/dist/{e2b-y8t3jzyz.js → e2b-nd50eccg.js} +1 -1
- package/dist/{easter-egg-3d-mtpnw06s.js → easter-egg-3d-66zxervv.js} +2 -2
- package/dist/{event-bus-w7ac4n3c.js → event-bus-vnfthafg.js} +2 -2
- package/dist/{execute-s4ccjq3n.js → execute-h4jgevyw.js} +61 -11
- package/dist/{google-generative-ai-d6nphg3q.js → google-generative-ai-b8zxrpax.js} +5 -5
- package/dist/{google-vertex-cpshkref.js → google-vertex-nrdd697t.js} +5 -5
- package/dist/grok-adapter-jdt2dz2s.js +39 -0
- package/dist/{handlers-g2wnr4t9.js → handlers-2qtkpncr.js} +31 -35
- package/dist/{hook-f7jt9vnm.js → hook-51yfcgsv.js} +48 -39
- package/dist/{hook-bbdpnkb4.js → hook-qnbdgwvd.js} +15 -17
- package/dist/{http-w40q4w94.js → http-jsmtag08.js} +536 -231
- package/dist/{index-056j5kzn.js → index-2t9kesn1.js} +13 -12
- package/dist/{index-cj1r9q83.js → index-bt8wkv1w.js} +29 -33
- package/dist/{index-7n70jwbb.js → index-cx1sb9bq.js} +42 -35
- package/dist/{index-9bfssf54.js → index-ekywyv2v.js} +28 -32
- package/dist/{index-fdk1t4d6.js → index-n0rxa4ca.js} +11962 -9900
- package/dist/{index-k8xc083e.js → index-t4g06w93.js} +28 -32
- package/dist/{keepalive-1tj10tf4.js → keepalive-4aezx4bj.js} +16 -12
- package/dist/{lead-st0bg7v4.js → lead-r44bkpm5.js} +52 -56
- package/dist/{llama-cpp-classify-tgj35k8d.js → llama-cpp-classify-6erb7wwv.js} +3 -1
- package/dist/{maintenance-nz71zats.js → maintenance-grz5jrzh.js} +12 -13
- package/dist/{mistral-conversations-8445ddjn.js → mistral-conversations-059y51zt.js} +4 -4
- package/dist/{node-f0ykebbv.js → node-qm9eb6z0.js} +25 -7
- package/dist/{oauth-refresh-sweep-aefzwvvq.js → oauth-refresh-sweep-wm4ctjfj.js} +15 -11
- package/dist/{onboard-kgpr9mbn.js → onboard-v60zgqf0.js} +2 -2
- package/dist/{openai-codex-responses-9ynm88zy.js → openai-codex-responses-jzxkta9b.js} +8 -7
- package/dist/{openai-completions-nhqwjmaw.js → openai-completions-663yncfq.js} +4 -4
- package/dist/openai-decisions-vj9nkpf8.js +162 -0
- package/dist/{openai-responses-xx1c4kgm.js → openai-responses-m3g43rrt.js} +5 -5
- package/dist/{opencode-adapter-0c8e70dk.js → opencode-adapter-yjyqynzf.js} +8 -8
- package/dist/{openrouter-images-8yx3487g.js → openrouter-images-kr60n6b9.js} +1 -1
- package/dist/{otel-impl-x8zp4y5a.js → otel-impl-ghh4dyf8.js} +2 -2
- package/dist/{pi-messages-vxdt8v7j.js → pi-messages-xszk613n.js} +1 -1
- package/dist/{pi-mono-adapter-t280ah5c.js → pi-mono-adapter-0eg8kw2c.js} +69 -52
- package/dist/{pricing-refresh-9e0q7cwk.js → pricing-refresh-mjrqvnvw.js} +12 -11
- package/dist/{rbac-roles-790j3ga8.js → rbac-roles-axv4d74x.js} +11 -10
- package/dist/{rbac-roles-kcp6zge2.js → rbac-roles-fd5tskj9.js} +11 -10
- package/dist/{render-v2-tch4nefj.js → render-v2-k50j33qd.js} +11 -11
- package/dist/{runtime-v2t1r79e.js → runtime-h9ha1mq6.js} +4 -4
- package/dist/{setup-rcm303ns.js → setup-4syh0pd2.js} +2 -2
- package/dist/{typesafe-system-one-datfr82p.js → typesafe-system-one-e988vty7.js} +7 -5
- package/dist/{virtual-modules-wm8mxdxx.js → virtual-modules-ftr9kwe8.js} +11 -11
- package/dist/{work-objects-ctg7t70w.js → work-objects-jcdbg8rr.js} +32 -36
- package/dist/{worker-5dp0xm55.js → worker-x8j8c9sx.js} +52 -56
- package/dist/{x-v3yw66zs.js → x-ma4gnfgy.js} +2 -2
- package/openapi.json +5 -2
- package/package.json +15 -11
- package/src/be/automation-preflight.ts +9 -4
- package/src/be/boot-scrub-sweep.ts +302 -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/openai-embedding.ts +7 -2
- package/src/be/memory/providers/sqlite-store.ts +63 -11
- package/src/be/memory/raters/llm-summarizer.ts +7 -2
- package/src/be/memory/types.ts +14 -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/modelsdev-cache.json +61 -0
- package/src/be/scripts/db.ts +28 -4
- package/src/be/scripts/source-secrets.ts +37 -0
- 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 +84 -53
- package/src/be/swarm-config-guard.ts +13 -0
- package/src/be/workflow-replay.ts +77 -0
- package/src/commands/provider-credentials.ts +28 -5
- package/src/commands/runner.ts +7 -12
- package/src/heartbeat/heartbeat.ts +91 -19
- package/src/hooks/hook.ts +72 -27
- package/src/http/codex-oauth-device.ts +8 -10
- 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/index.ts +23 -6
- package/src/http/mcp.ts +5 -0
- package/src/http/onboarding.ts +2 -0
- package/src/http/script-runs.ts +9 -1
- package/src/http/scripts.ts +15 -0
- package/src/http/workflows.ts +3 -2
- package/src/oauth/mcp-wrapper.ts +1 -1
- package/src/providers/acp-adapter.ts +25 -11
- package/src/providers/acp-target-catalog.ts +35 -1
- package/src/providers/acp-targets.ts +78 -7
- package/src/providers/amp-adapter.ts +1 -1
- package/src/providers/claude-adapter.ts +26 -0
- package/src/providers/codex-adapter.ts +30 -3
- package/src/providers/codex-oauth/auth-json.ts +21 -4
- package/src/providers/codex-oauth/types.ts +2 -0
- package/src/providers/cursor-adapter.ts +1 -1
- package/src/providers/dsh-adapter.ts +10 -1
- package/src/providers/grok-adapter.ts +18 -2
- package/src/providers/opencode-adapter.ts +21 -5
- package/src/providers/pi-mono-extension.ts +56 -25
- package/src/providers/pricing-sources.md +2 -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/server.ts +66 -4
- package/src/tests/acp-adapter.test.ts +277 -12
- package/src/tests/boot-scrub-sweep.test.ts +390 -0
- package/src/tests/check-text-columns.test.ts +145 -0
- package/src/tests/ci-unit-test-report.test.ts +73 -0
- package/src/tests/claude-default-route.test.ts +75 -0
- package/src/tests/claude-hook-output.test.ts +233 -0
- package/src/tests/claude-sdk-process.fixture.ts +13 -2
- package/src/tests/codex-adapter-pool-auth-revalidate.test.ts +4 -2
- package/src/tests/codex-adapter.test.ts +166 -26
- package/src/tests/codex-oauth-auth-timestamps.test.ts +76 -0
- package/src/tests/codex-oauth-device.test.ts +23 -37
- package/src/tests/codex-oauth.test.ts +4 -1
- package/src/tests/context-window.test.ts +2 -2
- package/src/tests/credential-check.test.ts +51 -1
- 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/dsh-adapter.test.ts +23 -1
- package/src/tests/enabled-tools.test.ts +269 -0
- package/src/tests/entrypoint-acp-target-binary.test.ts +31 -1
- package/src/tests/entrypoint-codex-oauth-seed.test.ts +12 -0
- package/src/tests/events-scrub.test.ts +88 -0
- package/src/tests/fixtures/secret-corpus.ts +320 -0
- package/src/tests/grok-adapter.test.ts +13 -0
- package/src/tests/haiku-5-5-pricing.test.ts +38 -0
- package/src/tests/heartbeat-checklist.test.ts +158 -1
- package/src/tests/onboarding.test.ts +44 -0
- package/src/tests/opencode-adapter.test.ts +66 -3
- package/src/tests/opencode-plugin.test.ts +37 -0
- package/src/tests/openrouter-attribution-call-sites.test.ts +204 -0
- package/src/tests/openrouter-base-url.test.ts +30 -39
- package/src/tests/pi-mono-extension.test.ts +161 -2
- package/src/tests/pricing-refresh.test.ts +70 -1
- package/src/tests/reasoning-effort.test.ts +3 -1
- package/src/tests/script-connections.test.ts +5 -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 +88 -1
- package/src/tests/script-runs-scrub.test.ts +275 -0
- package/src/tests/scripts-http.test.ts +82 -1
- 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 +3 -2
- package/src/tests/telemetry-trigger.test.ts +12 -1
- package/src/tests/workflow-llm.test.ts +14 -0
- 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 +33 -0
- package/src/tools/db-query.ts +1 -1
- package/src/tools/inject-learning.ts +1 -1
- package/src/tools/request-human-input.ts +7 -2
- package/src/tools/workflows/get-workflow-run.ts +3 -2
- package/src/types.ts +1 -1
- package/src/utils/enabled-tools.ts +27 -0
- package/src/utils/internal-ai/complete-structured.ts +11 -3
- package/src/utils/openrouter-base-url.ts +23 -0
- package/src/utils/secret-rules.generated.ts +2055 -0
- package/src/utils/secret-scrubber.ts +363 -29
- package/src/workflows/engine.ts +39 -4
- package/src/workflows/executors/raw-llm.ts +1 -0
- package/src/workflows/executors/system-one-decision.ts +2 -0
- package/src/workflows/executors/validate.ts +1 -0
- package/src/workflows/executors/workflow-llm.ts +9 -2
- package/src/workflows/recovery.ts +10 -1
- package/src/workflows/resume.ts +62 -3
- package/src/workflows/retry-poller.ts +3 -0
- package/templates/skills/agent-browser/SKILL.md +2 -0
- package/templates/skills/agent-browser/content.md +2 -0
- package/templates/skills/code-quality/content.md +1 -0
- package/templates/skills/heartbeat-runbook/content.md +1 -1
- package/templates/skills/work-on-task/SKILL.md +4 -0
- package/templates/skills/work-on-task/content.md +4 -0
- package/templates/skills/workflow-iterate/content.md +9 -0
- package/dist/acp-adapter-w6zws6me.js +0 -23
- package/dist/boot-scrub-logs-246yn076.js +0 -99
- package/dist/cli-3a4m1aws.js +0 -572
- package/dist/cli-3dpj7atn.js +0 -11
- package/dist/cli-a87b04k8.js +0 -951
- package/dist/cli-cvk6yzw5.js +0 -40
- package/dist/cli-gvcgmx69.js +0 -183
- package/dist/cli-h1spv8v4.js +0 -427
- package/dist/cli-jqt9hrnz.js +0 -168
- package/dist/cli-yhmwmv0g.js +0 -9281
- package/dist/grok-adapter-yt9pab3k.js +0 -29
- package/src/be/boot-scrub-logs.ts +0 -132
- package/dist/{codex-hook-d2rkvf39.js → codex-hook-15dgc4cb.js} +1 -1
package/src/be/db.ts
CHANGED
|
@@ -149,7 +149,7 @@ import { activeModelBlock, type ModelFamily } from "../utils/model-rate-limit-wi
|
|
|
149
149
|
import { getCurrentRequestUserId } from "../utils/request-auth-context";
|
|
150
150
|
import {
|
|
151
151
|
registerSensitiveKeyName,
|
|
152
|
-
|
|
152
|
+
type ScrubbedText,
|
|
153
153
|
scrubSecrets,
|
|
154
154
|
} from "../utils/secret-scrubber";
|
|
155
155
|
import {
|
|
@@ -178,6 +178,7 @@ import {
|
|
|
178
178
|
type ApprovalRequestListFilters,
|
|
179
179
|
type ApprovalVote,
|
|
180
180
|
approvalRequestListClause,
|
|
181
|
+
scrubApprovalVotesJson,
|
|
181
182
|
} from "./db/approvals";
|
|
182
183
|
import {
|
|
183
184
|
computeContentHash,
|
|
@@ -197,9 +198,13 @@ import {
|
|
|
197
198
|
rowToAgentTaskSummary,
|
|
198
199
|
} from "./db/tasks/read";
|
|
199
200
|
import { configureTaskWriteDependencies, failTask } from "./db/tasks/write";
|
|
201
|
+
import { scrubJsonValue } from "./scrub-json";
|
|
202
|
+
import { openSealedJson, sealedJsonForDisplay, sealJson } from "./sealed-json";
|
|
203
|
+
import { configSecretName, registerStoredSecret } from "./secret-registry";
|
|
200
204
|
import { promotePendingSteeringForTask } from "./steering";
|
|
201
205
|
import { isInternalConfigKey, isReservedConfigKey, reservedKeyError } from "./swarm-config-guard";
|
|
202
206
|
import { emitTaskStarted } from "./task-lifecycle-events";
|
|
207
|
+
import { defineWorkflowPayload, type WorkflowPayloadView } from "./workflow-replay";
|
|
203
208
|
|
|
204
209
|
export {
|
|
205
210
|
refreshActiveSessionOnActivity,
|
|
@@ -257,6 +262,7 @@ export {
|
|
|
257
262
|
getContextVersionHistory,
|
|
258
263
|
getLatestContextVersion,
|
|
259
264
|
} from "./db/context-versions";
|
|
265
|
+
export { getScriptRunExecutionArgs } from "./db/script-runs";
|
|
260
266
|
|
|
261
267
|
configureAgentDependencies({
|
|
262
268
|
createLogEntry: (entry) => createLogEntry(entry),
|
|
@@ -2182,7 +2188,7 @@ export async function createLogEntry(entry: {
|
|
|
2182
2188
|
entry.eventType,
|
|
2183
2189
|
entry.agentId ?? null,
|
|
2184
2190
|
entry.taskId ?? null,
|
|
2185
|
-
entry.oldValue
|
|
2191
|
+
entry.oldValue ? scrubSecrets(entry.oldValue) : null,
|
|
2186
2192
|
entry.newValue ? scrubSecrets(entry.newValue) : null,
|
|
2187
2193
|
metaJson ? scrubSecrets(metaJson) : null,
|
|
2188
2194
|
],
|
|
@@ -2811,7 +2817,8 @@ export async function createTaskExtended(
|
|
|
2811
2817
|
assetKey,
|
|
2812
2818
|
options?.agentId ?? null,
|
|
2813
2819
|
options?.creatorAgentId ?? null,
|
|
2814
|
-
task
|
|
2820
|
+
// Free text from every task source; scrub at the single INSERT.
|
|
2821
|
+
scrubSecrets(task),
|
|
2815
2822
|
status,
|
|
2816
2823
|
options?.source ?? "mcp",
|
|
2817
2824
|
options?.routingReason ?? null,
|
|
@@ -3883,7 +3890,11 @@ export async function postMessage(
|
|
|
3883
3890
|
|
|
3884
3891
|
// Detect /task prefix - only create tasks when explicitly requested
|
|
3885
3892
|
const isTaskMessage = content.trimStart().startsWith("/task ");
|
|
3886
|
-
|
|
3893
|
+
// Scrubbed once here: the row, the task description built from it and the
|
|
3894
|
+
// appended task-link UPDATE below all derive from this value.
|
|
3895
|
+
const messageContent = scrubSecrets(
|
|
3896
|
+
isTaskMessage ? content.replace(/^\s*\/task\s+/, "") : content,
|
|
3897
|
+
);
|
|
3887
3898
|
|
|
3888
3899
|
const row = await getDbClient().get<ChannelMessageRow>(
|
|
3889
3900
|
`INSERT INTO channel_messages (id, channelId, agentId, content, replyToId, mentions, createdAt)
|
|
@@ -4597,7 +4608,7 @@ export async function createSessionLogs(logs: {
|
|
|
4597
4608
|
lines: string[];
|
|
4598
4609
|
}): Promise<void> {
|
|
4599
4610
|
// Bounded batches, one short transaction each (reference shape:
|
|
4600
|
-
// src/be/boot-scrub-
|
|
4611
|
+
// src/be/boot-scrub-sweep.ts): worker log batches have unbounded line
|
|
4601
4612
|
// counts, and a single transaction across thousands of scrub+INSERT
|
|
4602
4613
|
// iterations would hold the global write lock — and the event loop — for
|
|
4603
4614
|
// the whole sweep. The regex scrub runs outside the transaction so only
|
|
@@ -5552,12 +5563,12 @@ export async function createInboxMessage(
|
|
|
5552
5563
|
[
|
|
5553
5564
|
id,
|
|
5554
5565
|
agentId,
|
|
5555
|
-
content,
|
|
5566
|
+
scrubSecrets(content),
|
|
5556
5567
|
options?.source ?? "slack",
|
|
5557
5568
|
options?.slackChannelId ?? null,
|
|
5558
5569
|
options?.slackThreadTs ?? null,
|
|
5559
5570
|
options?.slackUserId ?? null,
|
|
5560
|
-
options?.matchedText
|
|
5571
|
+
options?.matchedText == null ? null : scrubSecrets(options.matchedText),
|
|
5561
5572
|
now,
|
|
5562
5573
|
now,
|
|
5563
5574
|
],
|
|
@@ -5633,7 +5644,7 @@ export async function markInboxMessageResponded(
|
|
|
5633
5644
|
const now = new Date().toISOString();
|
|
5634
5645
|
const row = await getDbClient().get<InboxMessageRow>(
|
|
5635
5646
|
"UPDATE inbox_messages SET status = 'responded', responseText = ?, lastUpdatedAt = ? WHERE id = ? AND status IN ('unread', 'processing') RETURNING *",
|
|
5636
|
-
[responseText, now, id],
|
|
5647
|
+
[scrubSecrets(responseText), now, id],
|
|
5637
5648
|
);
|
|
5638
5649
|
return row ? rowToInboxMessage(row) : null;
|
|
5639
5650
|
}
|
|
@@ -6030,10 +6041,10 @@ export async function createScheduledTask(data: CreateScheduledTaskData): Promis
|
|
|
6030
6041
|
id,
|
|
6031
6042
|
normalizeAssetKey(data.key ?? defaultAssetKey("schedule", id)),
|
|
6032
6043
|
data.name,
|
|
6033
|
-
data.description
|
|
6044
|
+
data.description == null ? null : scrubSecrets(data.description),
|
|
6034
6045
|
data.cronExpression ?? null,
|
|
6035
6046
|
data.intervalMs ?? null,
|
|
6036
|
-
data.taskTemplate
|
|
6047
|
+
data.taskTemplate == null ? null : scrubSecrets(data.taskTemplate),
|
|
6037
6048
|
data.taskType ?? null,
|
|
6038
6049
|
JSON.stringify(data.tags ?? []),
|
|
6039
6050
|
data.priority ?? 50,
|
|
@@ -6116,7 +6127,7 @@ export async function updateScheduledTask(
|
|
|
6116
6127
|
}
|
|
6117
6128
|
if (data.description !== undefined) {
|
|
6118
6129
|
updates.push("description = ?");
|
|
6119
|
-
params.push(data.description);
|
|
6130
|
+
params.push(data.description == null ? null : scrubSecrets(data.description));
|
|
6120
6131
|
}
|
|
6121
6132
|
if (data.cronExpression !== undefined) {
|
|
6122
6133
|
updates.push("cronExpression = ?");
|
|
@@ -6128,7 +6139,7 @@ export async function updateScheduledTask(
|
|
|
6128
6139
|
}
|
|
6129
6140
|
if (data.taskTemplate !== undefined) {
|
|
6130
6141
|
updates.push("taskTemplate = ?");
|
|
6131
|
-
params.push(data.taskTemplate);
|
|
6142
|
+
params.push(data.taskTemplate == null ? null : scrubSecrets(data.taskTemplate));
|
|
6132
6143
|
}
|
|
6133
6144
|
if (data.taskType !== undefined) {
|
|
6134
6145
|
updates.push("taskType = ?");
|
|
@@ -6172,7 +6183,7 @@ export async function updateScheduledTask(
|
|
|
6172
6183
|
}
|
|
6173
6184
|
if (data.lastErrorMessage !== undefined) {
|
|
6174
6185
|
updates.push("lastErrorMessage = ?");
|
|
6175
|
-
params.push(data.lastErrorMessage);
|
|
6186
|
+
params.push(data.lastErrorMessage == null ? null : scrubSecrets(data.lastErrorMessage));
|
|
6176
6187
|
}
|
|
6177
6188
|
if (data.model !== undefined) {
|
|
6178
6189
|
updates.push("model = ?");
|
|
@@ -6614,7 +6625,7 @@ export async function upsertSwarmConfig(data: {
|
|
|
6614
6625
|
}
|
|
6615
6626
|
|
|
6616
6627
|
if (config.isSecret) {
|
|
6617
|
-
|
|
6628
|
+
registerStoredSecret(config.value, configSecretName(config.key));
|
|
6618
6629
|
registerSensitiveKeyName(config.key);
|
|
6619
6630
|
}
|
|
6620
6631
|
|
|
@@ -7655,6 +7666,8 @@ type WorkflowRunRow = {
|
|
|
7655
7666
|
triggerData: string | null;
|
|
7656
7667
|
/** Absent from list rows: see `WORKFLOW_RUN_SUMMARY_COLUMNS`. */
|
|
7657
7668
|
context?: string | null;
|
|
7669
|
+
/** Sealed exact `context` (migration 201). Absent from list rows. */
|
|
7670
|
+
context_replay?: string | null;
|
|
7658
7671
|
error: string | null;
|
|
7659
7672
|
created_by: string | null;
|
|
7660
7673
|
startedAt: string;
|
|
@@ -7662,19 +7675,28 @@ type WorkflowRunRow = {
|
|
|
7662
7675
|
finishedAt: string | null;
|
|
7663
7676
|
};
|
|
7664
7677
|
|
|
7665
|
-
|
|
7666
|
-
|
|
7678
|
+
/**
|
|
7679
|
+
* `view` picks the `context` copy: `replay` (default) is the exact sealed value
|
|
7680
|
+
* the engine resumes from; `display` is the scrubbed column for API, MCP and UI
|
|
7681
|
+
* responses. See `src/be/workflow-replay.ts`.
|
|
7682
|
+
*/
|
|
7683
|
+
function rowToWorkflowRun(row: WorkflowRunRow, view: WorkflowPayloadView = "replay"): WorkflowRun {
|
|
7684
|
+
const run: WorkflowRun = {
|
|
7667
7685
|
id: row.id,
|
|
7668
7686
|
workflowId: row.workflowId,
|
|
7669
7687
|
status: row.status as WorkflowRunStatus,
|
|
7670
7688
|
triggerData: row.triggerData ? JSON.parse(row.triggerData) : undefined,
|
|
7671
|
-
context:
|
|
7689
|
+
context: undefined,
|
|
7672
7690
|
error: row.error ?? undefined,
|
|
7673
7691
|
createdBy: row.created_by ?? undefined,
|
|
7674
7692
|
startedAt: normalizeDateRequired(row.startedAt),
|
|
7675
7693
|
lastUpdatedAt: normalizeDateRequired(row.lastUpdatedAt),
|
|
7676
7694
|
finishedAt: normalizeDate(row.finishedAt) ?? undefined,
|
|
7677
7695
|
};
|
|
7696
|
+
return defineWorkflowPayload(run, "context", row.context, row.context_replay, view, {
|
|
7697
|
+
runId: row.id,
|
|
7698
|
+
target: "its context",
|
|
7699
|
+
});
|
|
7678
7700
|
}
|
|
7679
7701
|
|
|
7680
7702
|
export async function createWorkflowRun(data: {
|
|
@@ -7692,7 +7714,7 @@ export async function createWorkflowRun(data: {
|
|
|
7692
7714
|
data.workflowId,
|
|
7693
7715
|
data.triggerType ?? "manual",
|
|
7694
7716
|
now,
|
|
7695
|
-
data.triggerData ?
|
|
7717
|
+
data.triggerData ? scrubJsonValue(data.triggerData) : null,
|
|
7696
7718
|
data.createdBy ?? null,
|
|
7697
7719
|
],
|
|
7698
7720
|
);
|
|
@@ -7700,11 +7722,14 @@ export async function createWorkflowRun(data: {
|
|
|
7700
7722
|
return rowToWorkflowRun(row);
|
|
7701
7723
|
}
|
|
7702
7724
|
|
|
7703
|
-
export async function getWorkflowRun(
|
|
7725
|
+
export async function getWorkflowRun(
|
|
7726
|
+
id: string,
|
|
7727
|
+
view: WorkflowPayloadView = "replay",
|
|
7728
|
+
): Promise<WorkflowRun | null> {
|
|
7704
7729
|
const row = await getDbClient().get<WorkflowRunRow>("SELECT * FROM workflow_runs WHERE id = ?", [
|
|
7705
7730
|
id,
|
|
7706
7731
|
]);
|
|
7707
|
-
return row ? rowToWorkflowRun(row) : null;
|
|
7732
|
+
return row ? rowToWorkflowRun(row, view) : null;
|
|
7708
7733
|
}
|
|
7709
7734
|
|
|
7710
7735
|
function emitWorkflowTerminalTelemetry(run: WorkflowRun): void {
|
|
@@ -7746,12 +7771,15 @@ export async function updateWorkflowRun(
|
|
|
7746
7771
|
params.push(data.status);
|
|
7747
7772
|
}
|
|
7748
7773
|
if (data.context !== undefined) {
|
|
7749
|
-
|
|
7750
|
-
|
|
7774
|
+
// Resume/retry/recovery rebuild the live ctx (resolved `secret.*` inputs
|
|
7775
|
+
// included, which are never re-resolved) from the sealed exact copy; the
|
|
7776
|
+
// scrubbed column serves display and SQL filters.
|
|
7777
|
+
updates.push("context = ?", "context_replay = ?");
|
|
7778
|
+
params.push(scrubJsonValue(data.context), sealJson(data.context));
|
|
7751
7779
|
}
|
|
7752
7780
|
if (data.error !== undefined) {
|
|
7753
7781
|
updates.push("error = ?");
|
|
7754
|
-
params.push(data.error);
|
|
7782
|
+
params.push(data.error === null ? null : scrubSecrets(data.error));
|
|
7755
7783
|
}
|
|
7756
7784
|
if (data.finishedAt !== undefined) {
|
|
7757
7785
|
updates.push("finishedAt = ?");
|
|
@@ -7833,7 +7861,8 @@ export async function listWorkflowRuns(
|
|
|
7833
7861
|
ORDER BY startedAt DESC, id DESC${pagination}`,
|
|
7834
7862
|
params,
|
|
7835
7863
|
);
|
|
7836
|
-
|
|
7864
|
+
// List rows are display-only (runs API, list-workflow-runs tool).
|
|
7865
|
+
return rows.map((row) => rowToWorkflowRun(row, "display"));
|
|
7837
7866
|
}
|
|
7838
7867
|
|
|
7839
7868
|
export async function countWorkflowRuns(
|
|
@@ -7886,6 +7915,8 @@ type WorkflowRunStepRow = {
|
|
|
7886
7915
|
status: string;
|
|
7887
7916
|
input: string | null;
|
|
7888
7917
|
output: string | null;
|
|
7918
|
+
/** Sealed exact `output` (migration 201). */
|
|
7919
|
+
output_replay: string | null;
|
|
7889
7920
|
error: string | null;
|
|
7890
7921
|
startedAt: string;
|
|
7891
7922
|
finishedAt: string | null;
|
|
@@ -7897,15 +7928,19 @@ type WorkflowRunStepRow = {
|
|
|
7897
7928
|
nextPort: string | null;
|
|
7898
7929
|
};
|
|
7899
7930
|
|
|
7900
|
-
|
|
7901
|
-
|
|
7931
|
+
/** `view` picks the `output` copy, as in `rowToWorkflowRun`. */
|
|
7932
|
+
function rowToWorkflowRunStep(
|
|
7933
|
+
row: WorkflowRunStepRow,
|
|
7934
|
+
view: WorkflowPayloadView = "replay",
|
|
7935
|
+
): WorkflowRunStep {
|
|
7936
|
+
const step: WorkflowRunStep = {
|
|
7902
7937
|
id: row.id,
|
|
7903
7938
|
runId: row.runId,
|
|
7904
7939
|
nodeId: row.nodeId,
|
|
7905
7940
|
nodeType: row.nodeType,
|
|
7906
7941
|
status: row.status as WorkflowRunStepStatus,
|
|
7907
7942
|
input: row.input ? JSON.parse(row.input) : undefined,
|
|
7908
|
-
output:
|
|
7943
|
+
output: undefined,
|
|
7909
7944
|
error: row.error ?? undefined,
|
|
7910
7945
|
startedAt: normalizeDateRequired(row.startedAt),
|
|
7911
7946
|
finishedAt: normalizeDate(row.finishedAt) ?? undefined,
|
|
@@ -7916,6 +7951,10 @@ function rowToWorkflowRunStep(row: WorkflowRunStepRow): WorkflowRunStep {
|
|
|
7916
7951
|
diagnostics: row.diagnostics ?? undefined,
|
|
7917
7952
|
nextPort: row.nextPort ?? undefined,
|
|
7918
7953
|
};
|
|
7954
|
+
return defineWorkflowPayload(step, "output", row.output, row.output_replay, view, {
|
|
7955
|
+
runId: row.runId,
|
|
7956
|
+
target: `the output of step ${row.id} (node ${row.nodeId})`,
|
|
7957
|
+
});
|
|
7919
7958
|
}
|
|
7920
7959
|
|
|
7921
7960
|
export async function createWorkflowRunStep(data: {
|
|
@@ -7936,7 +7975,7 @@ export async function createWorkflowRunStep(data: {
|
|
|
7936
7975
|
data.nodeId,
|
|
7937
7976
|
data.nodeType,
|
|
7938
7977
|
now,
|
|
7939
|
-
data.input ?
|
|
7978
|
+
data.input ? scrubJsonValue(data.input) : null,
|
|
7940
7979
|
data.idempotencyKey ?? null,
|
|
7941
7980
|
],
|
|
7942
7981
|
);
|
|
@@ -7974,12 +8013,14 @@ export async function updateWorkflowRunStep(
|
|
|
7974
8013
|
params.push(data.status);
|
|
7975
8014
|
}
|
|
7976
8015
|
if (data.output !== undefined) {
|
|
7977
|
-
|
|
7978
|
-
|
|
8016
|
+
// Scrubbed for display; dedup, convergence and recovery replay the sealed
|
|
8017
|
+
// exact copy into downstream nodes.
|
|
8018
|
+
updates.push("output = ?", "output_replay = ?");
|
|
8019
|
+
params.push(scrubJsonValue(data.output), sealJson(data.output));
|
|
7979
8020
|
}
|
|
7980
8021
|
if (data.error !== undefined) {
|
|
7981
8022
|
updates.push("error = ?");
|
|
7982
|
-
params.push(data.error);
|
|
8023
|
+
params.push(data.error === null ? null : scrubSecrets(data.error));
|
|
7983
8024
|
}
|
|
7984
8025
|
if (data.finishedAt !== undefined) {
|
|
7985
8026
|
updates.push("finishedAt = ?");
|
|
@@ -8003,7 +8044,7 @@ export async function updateWorkflowRunStep(
|
|
|
8003
8044
|
}
|
|
8004
8045
|
if (data.diagnostics !== undefined) {
|
|
8005
8046
|
updates.push("diagnostics = ?");
|
|
8006
|
-
params.push(data.diagnostics);
|
|
8047
|
+
params.push(scrubSecrets(data.diagnostics));
|
|
8007
8048
|
}
|
|
8008
8049
|
if (data.nextPort !== undefined) {
|
|
8009
8050
|
updates.push("nextPort = ?");
|
|
@@ -8024,12 +8065,15 @@ export async function updateWorkflowRunStep(
|
|
|
8024
8065
|
return row ? rowToWorkflowRunStep(row) : null;
|
|
8025
8066
|
}
|
|
8026
8067
|
|
|
8027
|
-
export async function getWorkflowRunStepsByRunId(
|
|
8068
|
+
export async function getWorkflowRunStepsByRunId(
|
|
8069
|
+
runId: string,
|
|
8070
|
+
view: WorkflowPayloadView = "replay",
|
|
8071
|
+
): Promise<WorkflowRunStep[]> {
|
|
8028
8072
|
const rows = await getDbClient().query<WorkflowRunStepRow>(
|
|
8029
8073
|
"SELECT * FROM workflow_run_steps WHERE runId = ? ORDER BY startedAt ASC",
|
|
8030
8074
|
[runId],
|
|
8031
8075
|
);
|
|
8032
|
-
return rows.map(rowToWorkflowRunStep);
|
|
8076
|
+
return rows.map((row) => rowToWorkflowRunStep(row, view));
|
|
8033
8077
|
}
|
|
8034
8078
|
|
|
8035
8079
|
// --- Stuck Workflow Run Recovery ---
|
|
@@ -8097,7 +8141,7 @@ export async function getRetryableSteps(): Promise<WorkflowRunStep[]> {
|
|
|
8097
8141
|
ORDER BY s.nextRetryAt ASC`,
|
|
8098
8142
|
[now],
|
|
8099
8143
|
);
|
|
8100
|
-
return rows.map(rowToWorkflowRunStep);
|
|
8144
|
+
return rows.map((row) => rowToWorkflowRunStep(row));
|
|
8101
8145
|
}
|
|
8102
8146
|
|
|
8103
8147
|
export async function getCompletedStepNodeIds(runId: string): Promise<string[]> {
|
|
@@ -9526,7 +9570,8 @@ function rowToApprovalRequest(row: ApprovalRequestRow): ApprovalRequest {
|
|
|
9526
9570
|
sourceTaskId: row.sourceTaskId,
|
|
9527
9571
|
approvers: JSON.parse(row.approvers),
|
|
9528
9572
|
status: row.status as ApprovalRequest["status"],
|
|
9529
|
-
|
|
9573
|
+
// Sealed at rest: workflow recovery and HITL resume read the exact answer.
|
|
9574
|
+
responses: row.responses ? openSealedJson(row.responses) : null,
|
|
9530
9575
|
approvals: row.approvals ? JSON.parse(row.approvals) : null,
|
|
9531
9576
|
resolvedBy: row.resolvedBy,
|
|
9532
9577
|
resolvedAt: normalizeDate(row.resolvedAt),
|
|
@@ -9582,14 +9627,14 @@ export async function createApprovalRequest(data: {
|
|
|
9582
9627
|
RETURNING *`,
|
|
9583
9628
|
[
|
|
9584
9629
|
data.id,
|
|
9585
|
-
data.title,
|
|
9586
|
-
|
|
9630
|
+
scrubSecrets(data.title),
|
|
9631
|
+
scrubJsonValue(data.questions),
|
|
9587
9632
|
data.workflowRunId ?? null,
|
|
9588
9633
|
data.workflowRunStepId ?? null,
|
|
9589
9634
|
data.sourceTaskId ?? null,
|
|
9590
9635
|
JSON.stringify(data.approvers),
|
|
9591
9636
|
status,
|
|
9592
|
-
resolutionReason,
|
|
9637
|
+
resolutionReason == null ? null : scrubSecrets(resolutionReason),
|
|
9593
9638
|
status === "cancelled" ? now : null,
|
|
9594
9639
|
data.timeoutSeconds ?? null,
|
|
9595
9640
|
expiresAt,
|
|
@@ -9651,10 +9696,12 @@ export async function resolveApprovalRequest(
|
|
|
9651
9696
|
RETURNING *`,
|
|
9652
9697
|
[
|
|
9653
9698
|
data.status,
|
|
9654
|
-
|
|
9655
|
-
|
|
9699
|
+
// Sealed, not scrubbed: recovery resumes the workflow from this answer,
|
|
9700
|
+
// so it must stay byte-exact. Votes are diagnostic and get redacted.
|
|
9701
|
+
data.responses ? sealJson(data.responses) : null,
|
|
9702
|
+
data.approvals ? scrubApprovalVotesJson(data.approvals) : null,
|
|
9656
9703
|
data.resolvedBy ?? null,
|
|
9657
|
-
data.resolutionReason
|
|
9704
|
+
data.resolutionReason == null ? null : scrubSecrets(data.resolutionReason),
|
|
9658
9705
|
now,
|
|
9659
9706
|
now,
|
|
9660
9707
|
id,
|
|
@@ -9675,7 +9722,7 @@ export async function cancelApprovalRequestById(
|
|
|
9675
9722
|
SET status = 'cancelled', resolutionReason = ?, resolvedBy = ?, resolvedAt = ?, updatedAt = ?
|
|
9676
9723
|
WHERE id = ? AND status = 'pending'
|
|
9677
9724
|
RETURNING *`,
|
|
9678
|
-
[data.reason, data.resolvedBy, now, now, id],
|
|
9725
|
+
[scrubSecrets(data.reason), data.resolvedBy, now, now, id],
|
|
9679
9726
|
);
|
|
9680
9727
|
return row ? rowToApprovalRequest(row) : null;
|
|
9681
9728
|
}
|
|
@@ -9690,7 +9737,7 @@ export async function cancelPendingApprovalRequestsForRun(
|
|
|
9690
9737
|
SET status = 'cancelled', resolutionReason = ?, resolvedAt = ?, updatedAt = ?
|
|
9691
9738
|
WHERE workflowRunId = ? AND status = 'pending'
|
|
9692
9739
|
RETURNING *`,
|
|
9693
|
-
[reason, now, now, workflowRunId],
|
|
9740
|
+
[scrubSecrets(reason), now, now, workflowRunId],
|
|
9694
9741
|
);
|
|
9695
9742
|
return rows.map(rowToApprovalRequest);
|
|
9696
9743
|
}
|
|
@@ -9838,7 +9885,7 @@ export interface StuckApprovalRun {
|
|
|
9838
9885
|
}
|
|
9839
9886
|
|
|
9840
9887
|
export async function getStuckApprovalRuns(): Promise<StuckApprovalRun[]> {
|
|
9841
|
-
|
|
9888
|
+
const rows = await getDbClient().query<StuckApprovalRun>(
|
|
9842
9889
|
`SELECT
|
|
9843
9890
|
wr.id as runId,
|
|
9844
9891
|
wrs.id as stepId,
|
|
@@ -9855,6 +9902,11 @@ export async function getStuckApprovalRuns(): Promise<StuckApprovalRun[]> {
|
|
|
9855
9902
|
AND (ar.status IN ('approved', 'rejected', 'timeout')
|
|
9856
9903
|
OR (ar.status = 'pending' AND ar.expiresAt IS NOT NULL AND ar.expiresAt < strftime('%Y-%m-%dT%H:%M:%fZ', 'now')))`,
|
|
9857
9904
|
);
|
|
9905
|
+
return rows.map((row) => ({
|
|
9906
|
+
...row,
|
|
9907
|
+
approvalResponses:
|
|
9908
|
+
row.approvalResponses === null ? null : JSON.stringify(openSealedJson(row.approvalResponses)),
|
|
9909
|
+
}));
|
|
9858
9910
|
}
|
|
9859
9911
|
|
|
9860
9912
|
export async function getApprovalRequestByStepId(stepId: string): Promise<ApprovalRequest | null> {
|
|
@@ -12259,6 +12311,33 @@ export async function deleteUser(id: string, replacementUserId?: string): Promis
|
|
|
12259
12311
|
// Workflow context is persisted JSON rather than a relational column, but
|
|
12260
12312
|
// it exposes the same requester identity to downstream interpolation. Keep
|
|
12261
12313
|
// it consistent with workflow_runs.created_by inside this transaction.
|
|
12314
|
+
// The sealed replay copy is what a resume reads, so rewrite it first, while
|
|
12315
|
+
// the scrubbed column still matches the filter.
|
|
12316
|
+
const sealedContexts = await tx.query<{ id: string; context_replay: string }>(
|
|
12317
|
+
`SELECT id, context_replay FROM workflow_runs
|
|
12318
|
+
WHERE context_replay IS NOT NULL
|
|
12319
|
+
AND json_valid(context)
|
|
12320
|
+
AND json_extract(context, '$.swarm.requestedByUserId') = ?`,
|
|
12321
|
+
[id],
|
|
12322
|
+
);
|
|
12323
|
+
for (const row of sealedContexts) {
|
|
12324
|
+
let context: Record<string, unknown>;
|
|
12325
|
+
try {
|
|
12326
|
+
context = openSealedJson(row.context_replay) as Record<string, unknown>;
|
|
12327
|
+
} catch {
|
|
12328
|
+
// Unreadable replay state fails the run on resume
|
|
12329
|
+
// (WorkflowReplayStateError), so the stale id is never replayed.
|
|
12330
|
+
continue;
|
|
12331
|
+
}
|
|
12332
|
+
const swarm = { ...(context.swarm as Record<string, unknown> | undefined) };
|
|
12333
|
+
if (swarm.requestedByUserId !== id) continue;
|
|
12334
|
+
if (replacementUserId) swarm.requestedByUserId = replacementUserId;
|
|
12335
|
+
else delete swarm.requestedByUserId;
|
|
12336
|
+
await tx.run("UPDATE workflow_runs SET context_replay = ? WHERE id = ?", [
|
|
12337
|
+
sealJson({ ...context, swarm }),
|
|
12338
|
+
row.id,
|
|
12339
|
+
]);
|
|
12340
|
+
}
|
|
12262
12341
|
if (replacementUserId) {
|
|
12263
12342
|
await tx.run(
|
|
12264
12343
|
`UPDATE workflow_runs
|
|
@@ -13833,7 +13912,9 @@ function rowToScriptRun(row: ScriptRunRow): ScriptRun {
|
|
|
13833
13912
|
agentId: row.agentId,
|
|
13834
13913
|
scriptName: row.scriptName ?? undefined,
|
|
13835
13914
|
source: row.source,
|
|
13836
|
-
args
|
|
13915
|
+
// Durable-run args are sealed replay state; callers get the redacted view.
|
|
13916
|
+
// The supervisor reads the exact value via getScriptRunExecutionArgs.
|
|
13917
|
+
args: sealedJsonForDisplay(row.args),
|
|
13837
13918
|
kind: row.kind as ScriptRunKind,
|
|
13838
13919
|
status: row.status as ScriptRunStatus,
|
|
13839
13920
|
pid: row.pid ?? undefined,
|
|
@@ -13894,7 +13975,10 @@ export async function createScriptRun(data: {
|
|
|
13894
13975
|
data.agentId,
|
|
13895
13976
|
data.scriptName ?? null,
|
|
13896
13977
|
data.source,
|
|
13897
|
-
|
|
13978
|
+
// Sealed, not scrubbed: this is the run's execution input. The supervisor
|
|
13979
|
+
// launches (and relaunches after a restart or pause) from it, so a
|
|
13980
|
+
// redacted value would change what the script receives.
|
|
13981
|
+
sealJson(data.args ?? null),
|
|
13898
13982
|
data.idempotencyKey ?? null,
|
|
13899
13983
|
data.requestedByUserId ?? null,
|
|
13900
13984
|
data.createdBy ?? null,
|
|
@@ -13916,7 +14000,7 @@ export async function recordInlineScriptRun(data: {
|
|
|
13916
14000
|
scriptName?: string;
|
|
13917
14001
|
status: "completed" | "failed";
|
|
13918
14002
|
output?: unknown;
|
|
13919
|
-
error?:
|
|
14003
|
+
error?: ScrubbedText;
|
|
13920
14004
|
startedAt: string;
|
|
13921
14005
|
finishedAt: string;
|
|
13922
14006
|
requestedByUserId?: string;
|
|
@@ -13924,6 +14008,10 @@ export async function recordInlineScriptRun(data: {
|
|
|
13924
14008
|
/** Set when this run originated from an external API endpoint (POST /api/x/script/<id>). */
|
|
13925
14009
|
apiEndpointId?: string | null;
|
|
13926
14010
|
}): Promise<ScriptRun> {
|
|
14011
|
+
// The run already executed, so args and output are a record, not an input:
|
|
14012
|
+
// redact them here so every caller is covered.
|
|
14013
|
+
const args = scrubJsonValue(data.args ?? null);
|
|
14014
|
+
const output = data.output === undefined ? null : scrubJsonValue(data.output);
|
|
13927
14015
|
const row = await getDbClient().get<ScriptRunRow>(
|
|
13928
14016
|
`INSERT INTO script_runs
|
|
13929
14017
|
(id, agentId, scriptName, source, args, kind, status, output, error,
|
|
@@ -13935,9 +14023,9 @@ export async function recordInlineScriptRun(data: {
|
|
|
13935
14023
|
data.agentId,
|
|
13936
14024
|
data.scriptName ?? null,
|
|
13937
14025
|
data.source,
|
|
13938
|
-
|
|
14026
|
+
args,
|
|
13939
14027
|
data.status,
|
|
13940
|
-
|
|
14028
|
+
output,
|
|
13941
14029
|
data.error ?? null,
|
|
13942
14030
|
data.startedAt,
|
|
13943
14031
|
data.finishedAt,
|
|
@@ -14076,13 +14164,16 @@ function scriptRunUpdateSets(patch: ScriptRunPatch): {
|
|
|
14076
14164
|
sets.push("finishedAt = ?");
|
|
14077
14165
|
vals.push(patch.finishedAt);
|
|
14078
14166
|
}
|
|
14167
|
+
// Every script_runs UPDATE builds its SET list here, so this is the
|
|
14168
|
+
// chokepoint for the output and error columns. Output is a record of the
|
|
14169
|
+
// finished run (nothing re-reads it as input), so redaction is safe.
|
|
14079
14170
|
if ("output" in patch) {
|
|
14080
14171
|
sets.push("output = ?");
|
|
14081
|
-
vals.push(patch.output === undefined ? null :
|
|
14172
|
+
vals.push(patch.output === undefined ? null : scrubJsonValue(patch.output));
|
|
14082
14173
|
}
|
|
14083
14174
|
if (patch.error !== undefined) {
|
|
14084
14175
|
sets.push("error = ?");
|
|
14085
|
-
vals.push(patch.error);
|
|
14176
|
+
vals.push(patch.error === null ? null : scrubSecrets(patch.error));
|
|
14086
14177
|
}
|
|
14087
14178
|
if (patch.lastHeartbeatAt !== undefined) {
|
|
14088
14179
|
sets.push("last_heartbeat_at = ?");
|
|
@@ -14177,7 +14268,11 @@ type ScriptRunJournalRow = {
|
|
|
14177
14268
|
updated_by: string | null;
|
|
14178
14269
|
};
|
|
14179
14270
|
|
|
14180
|
-
function rowToScriptRunJournalEntry(
|
|
14271
|
+
function rowToScriptRunJournalEntry(
|
|
14272
|
+
row: ScriptRunJournalRow,
|
|
14273
|
+
view: "display" | "replay" = "display",
|
|
14274
|
+
): ScriptRunJournalEntry {
|
|
14275
|
+
const open = view === "replay" ? openSealedJson : sealedJsonForDisplay;
|
|
14181
14276
|
return {
|
|
14182
14277
|
id: row.id,
|
|
14183
14278
|
runId: row.runId,
|
|
@@ -14185,7 +14280,7 @@ function rowToScriptRunJournalEntry(row: ScriptRunJournalRow): ScriptRunJournalE
|
|
|
14185
14280
|
stepType: row.stepType,
|
|
14186
14281
|
config: JSON.parse(row.config),
|
|
14187
14282
|
status: row.status as "completed" | "failed",
|
|
14188
|
-
result:
|
|
14283
|
+
result: row.result === null ? undefined : open(row.result),
|
|
14189
14284
|
error: row.error ?? undefined,
|
|
14190
14285
|
startedAt: row.startedAt,
|
|
14191
14286
|
completedAt: row.completedAt ?? undefined,
|
|
@@ -14193,6 +14288,10 @@ function rowToScriptRunJournalEntry(row: ScriptRunJournalRow): ScriptRunJournalE
|
|
|
14193
14288
|
};
|
|
14194
14289
|
}
|
|
14195
14290
|
|
|
14291
|
+
/**
|
|
14292
|
+
* One journal step with its exact `result`, for the harness replay route only.
|
|
14293
|
+
* Everything that shows a journal to a person uses listScriptRunJournalSteps.
|
|
14294
|
+
*/
|
|
14196
14295
|
export async function getScriptRunJournalStep(
|
|
14197
14296
|
runId: string,
|
|
14198
14297
|
stepKey: string,
|
|
@@ -14201,7 +14300,7 @@ export async function getScriptRunJournalStep(
|
|
|
14201
14300
|
"SELECT * FROM script_run_journal WHERE runId = ? AND stepKey = ?",
|
|
14202
14301
|
[runId, stepKey],
|
|
14203
14302
|
);
|
|
14204
|
-
return row ? rowToScriptRunJournalEntry(row) : null;
|
|
14303
|
+
return row ? rowToScriptRunJournalEntry(row, "replay") : null;
|
|
14205
14304
|
}
|
|
14206
14305
|
|
|
14207
14306
|
export async function upsertScriptRunJournalStep(data: {
|
|
@@ -14211,9 +14310,13 @@ export async function upsertScriptRunJournalStep(data: {
|
|
|
14211
14310
|
config: unknown;
|
|
14212
14311
|
status: "completed" | "failed";
|
|
14213
14312
|
result?: unknown;
|
|
14214
|
-
error?:
|
|
14313
|
+
error?: ScrubbedText;
|
|
14215
14314
|
durationMs?: number;
|
|
14216
14315
|
}): Promise<void> {
|
|
14316
|
+
// `config` is diagnostic only (the step GET never returns it), so it is
|
|
14317
|
+
// redacted. `result` is sealed instead: the harness replays it verbatim as
|
|
14318
|
+
// the step's return value on resume, so redaction would change what later
|
|
14319
|
+
// steps see.
|
|
14217
14320
|
await getDbClient().run(
|
|
14218
14321
|
`INSERT OR IGNORE INTO script_run_journal
|
|
14219
14322
|
(id, runId, stepKey, stepType, config, status, result, error, durationMs, completedAt)
|
|
@@ -14223,9 +14326,9 @@ export async function upsertScriptRunJournalStep(data: {
|
|
|
14223
14326
|
data.runId,
|
|
14224
14327
|
data.stepKey,
|
|
14225
14328
|
data.stepType,
|
|
14226
|
-
|
|
14329
|
+
scrubJsonValue(data.config ?? {}),
|
|
14227
14330
|
data.status,
|
|
14228
|
-
data.result !== undefined ?
|
|
14331
|
+
data.result !== undefined ? sealJson(data.result) : null,
|
|
14229
14332
|
data.error ?? null,
|
|
14230
14333
|
data.durationMs ?? null,
|
|
14231
14334
|
],
|
|
@@ -14237,7 +14340,7 @@ export async function listScriptRunJournalSteps(runId: string): Promise<ScriptRu
|
|
|
14237
14340
|
"SELECT * FROM script_run_journal WHERE runId = ? ORDER BY startedAt ASC",
|
|
14238
14341
|
[runId],
|
|
14239
14342
|
);
|
|
14240
|
-
return rows.map(rowToScriptRunJournalEntry);
|
|
14343
|
+
return rows.map((row) => rowToScriptRunJournalEntry(row));
|
|
14241
14344
|
}
|
|
14242
14345
|
|
|
14243
14346
|
export async function countScriptRunJournalSteps(runId: string): Promise<number> {
|
package/src/be/events.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { EventCategory, EventName, EventSource, EventStatus, SwarmEvent } from "../types";
|
|
2
|
+
import { type ScrubbedText, scrubObject, scrubSecrets } from "../utils/secret-scrubber";
|
|
2
3
|
import { getDbClient } from "./db";
|
|
3
4
|
import type { DbExecutor } from "./db-client";
|
|
5
|
+
import { breaksJsonValidity } from "./scrub-json";
|
|
4
6
|
import { recordSkillInvocation } from "./skill-invocations";
|
|
5
7
|
|
|
6
8
|
// -- Events --
|
|
@@ -59,6 +61,20 @@ export interface CreateEventInput {
|
|
|
59
61
|
data?: Record<string, unknown>;
|
|
60
62
|
}
|
|
61
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Serialize an event payload for `events.data` with secrets redacted. Scrubs
|
|
66
|
+
* the serialized string; if a redaction breaks JSON validity (e.g. a marker
|
|
67
|
+
* swallowed a closing quote), falls back to scrubbing each leaf string so the
|
|
68
|
+
* column always parses for `rowToSwarmEvent`.
|
|
69
|
+
*/
|
|
70
|
+
function serializeEventData(data: Record<string, unknown>): ScrubbedText {
|
|
71
|
+
const raw = JSON.stringify(data);
|
|
72
|
+
const scrubbed = scrubSecrets(raw);
|
|
73
|
+
if (!breaksJsonValidity(raw, scrubbed)) return scrubbed;
|
|
74
|
+
// Every leaf string went through scrubSecrets, so the brand holds.
|
|
75
|
+
return JSON.stringify(scrubObject(data)) as ScrubbedText;
|
|
76
|
+
}
|
|
77
|
+
|
|
62
78
|
async function insertEvent(db: DbExecutor, id: string, input: CreateEventInput): Promise<void> {
|
|
63
79
|
await db.run(INSERT_EVENT_SQL, [
|
|
64
80
|
id,
|
|
@@ -72,7 +88,7 @@ async function insertEvent(db: DbExecutor, id: string, input: CreateEventInput):
|
|
|
72
88
|
input.parentEventId ?? null,
|
|
73
89
|
input.numericValue ?? null,
|
|
74
90
|
input.durationMs ?? null,
|
|
75
|
-
input.data ?
|
|
91
|
+
input.data ? serializeEventData(input.data) : null,
|
|
76
92
|
]);
|
|
77
93
|
// `skill.invoke` also feeds the per-skill counter and invocation history.
|
|
78
94
|
await recordSkillInvocation(db, input, id);
|
|
@@ -90,7 +90,7 @@ export async function indexMemoryContent(
|
|
|
90
90
|
intent: "re-index memory source path",
|
|
91
91
|
changedByAgentId: agentId,
|
|
92
92
|
});
|
|
93
|
-
const embedding = await provider.embed(
|
|
93
|
+
const embedding = await provider.embed(result.memory.content);
|
|
94
94
|
if (embedding) await store.updateEmbedding(result.memory.id, embedding, provider.name);
|
|
95
95
|
try {
|
|
96
96
|
// Re-index of an existing memory: prune stale content-derived links.
|
|
@@ -143,7 +143,7 @@ export async function indexMemoryContent(
|
|
|
143
143
|
// Async batch embed (fire and forget)
|
|
144
144
|
(async () => {
|
|
145
145
|
try {
|
|
146
|
-
const embeddings = await provider.embedBatch(
|
|
146
|
+
const embeddings = await provider.embedBatch(memories.map((m) => m.content));
|
|
147
147
|
for (let i = 0; i < embeddings.length; i++) {
|
|
148
148
|
if (embeddings[i]) {
|
|
149
149
|
await store.updateEmbedding(memories[i]!.id, embeddings[i]!, provider.name);
|