@desplega.ai/agent-swarm 1.165.0 → 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/dist/{acp-adapter-w6zws6me.js → acp-adapter-yzfxn8vj.js} +4 -4
- package/dist/{actions-jna0b3wm.js → actions-qz3m692w.js} +20 -24
- package/dist/{amp-adapter-0eve81pz.js → amp-adapter-j1xbmsqz.js} +4 -4
- package/dist/{app-75hm5cfa.js → app-43vrdmv8.js} +6 -7
- package/dist/{assistant-yzd51j33.js → assistant-ertffmka.js} +21 -25
- package/dist/{boot-reembed-z158xq32.js → boot-reembed-998jtpdg.js} +9 -12
- package/dist/{boot-reembed-2ex2mcsh.js → boot-reembed-s7k7c6v2.js} +10 -12
- package/dist/boot-scrub-sweep-nepsk4t1.js +211 -0
- package/dist/{boot-seeds-2bmnh18p.js → boot-seeds-vvzs1zhk.js} +8 -8
- package/dist/{claude-adapter-jbj1mycz.js → claude-adapter-2zvmekrp.js} +9 -11
- package/dist/{claude-managed-adapter-17ggz09t.js → claude-managed-adapter-s49wbk8t.js} +3 -3
- package/dist/{claude-managed-setup-ptm1nzm2.js → claude-managed-setup-cvhqq8qn.js} +4 -4
- package/dist/{claude-sdk-session-9re1g7r2.js → claude-sdk-session-kkbxtw5q.js} +2618 -2600
- package/dist/{cli-k6xx3pve.js → cli-0nhdwxd5.js} +4 -4
- package/dist/{cli-n9ehc28t.js → cli-0qjcsxgz.js} +4 -4
- package/dist/{cli-zn2v3t8v.js → cli-3ddybbbx.js} +1 -1
- package/dist/{cli-5anb0ev3.js → cli-3qn4r334.js} +71 -14
- package/dist/{cli-1kzfvd1z.js → cli-4r1sjfc4.js} +9 -5
- package/dist/{cli-ba66wyhy.js → cli-66zh26sp.js} +6 -6
- package/dist/{cli-9xb89xca.js → cli-68r1j4sg.js} +6 -6
- package/dist/{cli-xnzrzets.js → cli-8kgvmkak.js} +2 -2
- package/dist/{cli-28smfvbn.js → cli-8t229cmr.js} +5 -5
- package/dist/{cli-9866bd07.js → cli-aqcey741.js} +1 -1
- package/dist/{cli-90v942q1.js → cli-cpfmqz3n.js} +8 -8
- package/dist/{cli-50eg13rj.js → cli-df56tqdw.js} +459 -282
- package/dist/{cli-8gpbwy09.js → cli-dw2q9f7g.js} +5 -5
- package/dist/{cli-0n4fasz0.js → cli-ecknp7p1.js} +15 -15
- package/dist/{cli-xb3c6aat.js → cli-f2n17zhp.js} +1 -1
- package/dist/{cli-ftry7975.js → cli-feh3dkah.js} +1 -1
- package/dist/{cli-amwhs8h2.js → cli-fn697bnt.js} +2 -2
- package/dist/{cli-prt9emct.js → cli-gt8azyet.js} +3 -3
- package/dist/{cli-59jn5twa.js → cli-h3x613ze.js} +2 -2
- package/dist/{cli-mmzwwptd.js → cli-hf5s9pgf.js} +1 -1
- package/dist/cli-j2jbr8af.js +516 -0
- package/dist/{cli-wfajtmf7.js → cli-jhm6hzjn.js} +593 -10
- package/dist/{cli-xtgtyafv.js → cli-jvj6a0cv.js} +190 -439
- package/dist/{cli-hpryr6em.js → cli-mb75wpxf.js} +1 -1
- package/dist/{cli-420bdgw0.js → cli-mv2520nm.js} +1 -1
- package/dist/{cli-pjxnr1jn.js → cli-mwegs4af.js} +3 -3
- package/dist/{cli-5b2fjjzh.js → cli-p4ztb80h.js} +2 -2
- package/dist/{cli-e7t4snpa.js → cli-rggdq8wq.js} +4 -4
- package/dist/{cli-bdv39kgj.js → cli-rsy933yz.js} +5 -5
- package/dist/{cli-gh5yqzpe.js → cli-v2a8x45d.js} +2 -2
- package/dist/{cli-bns5c8k9.js → cli-vzc73wet.js} +43 -47
- package/dist/cli-wt7ccy4r.js +2654 -0
- package/dist/{cli-j0pdrmwg.js → cli-x7kpr72a.js} +3 -3
- package/dist/{cli-x7afk5wm.js → cli-xvc3q9br.js} +1 -1
- package/dist/{cli-9s3h836g.js → cli-xvdgasgy.js} +1 -1
- package/dist/{cli-zvckv750.js → cli-y59h2pk9.js} +2 -2
- package/dist/{cli-qdv8kgz7.js → cli-yshaazs1.js} +13884 -3241
- package/dist/{cli-nfygw434.js → cli-ysnyhws9.js} +2 -2
- package/dist/{cli-fw6vdcq5.js → cli-zp67qg5x.js} +34 -1
- package/dist/{cli-ma3zvh39.js → cli-zy7vwsne.js} +6066 -5829
- package/dist/cli.js +24 -20
- package/dist/{codex-adapter-3qnxshje.js → codex-adapter-dw1wxqt8.js} +7 -7
- package/dist/{codex-login-brkxhhdg.js → codex-login-terbdsqq.js} +2 -2
- package/dist/{codex-session-runner-612wnapp.js → codex-session-runner-3cgb8y1g.js} +7 -7
- package/dist/{commands-2ybfcxkj.js → commands-mhxam6z2.js} +6 -6
- package/dist/{cursor-adapter-p3jgdehv.js → cursor-adapter-2qda3st7.js} +3 -3
- package/dist/{db-f4ans0jj.js → db-sjks418k.js} +8 -6
- package/dist/{devin-adapter-dhzt01ff.js → devin-adapter-bffjj5n4.js} +2 -2
- package/dist/{dispatcher-pk182apd.js → dispatcher-1es759rn.js} +18 -22
- package/dist/{dsh-adapter-7twaeps1.js → dsh-adapter-bek4cyw9.js} +3 -3
- package/dist/{e2b-y8t3jzyz.js → e2b-nd50eccg.js} +1 -1
- package/dist/{event-bus-w7ac4n3c.js → event-bus-vnfthafg.js} +2 -2
- package/dist/{grok-adapter-yt9pab3k.js → grok-adapter-ar9cw9jg.js} +5 -5
- package/dist/{handlers-g2wnr4t9.js → handlers-1gkbhktr.js} +21 -25
- package/dist/{hook-f7jt9vnm.js → hook-ds2zxq9v.js} +14 -16
- package/dist/{hook-bbdpnkb4.js → hook-vxa3tcsy.js} +8 -10
- package/dist/{http-w40q4w94.js → http-3h21z9md.js} +247 -164
- package/dist/{index-056j5kzn.js → index-9b65j1m5.js} +8 -8
- package/dist/{index-9bfssf54.js → index-bn6cy8ps.js} +18 -22
- package/dist/{index-cj1r9q83.js → index-dkfxpkmm.js} +19 -23
- package/dist/{index-7n70jwbb.js → index-f8xnqrye.js} +19 -21
- package/dist/{index-fdk1t4d6.js → index-n0rxa4ca.js} +11962 -9900
- package/dist/{index-k8xc083e.js → index-n99fycq7.js} +18 -22
- package/dist/{keepalive-1tj10tf4.js → keepalive-3xspa9jw.js} +11 -8
- package/dist/{lead-st0bg7v4.js → lead-6qphc124.js} +34 -38
- package/dist/{maintenance-nz71zats.js → maintenance-0teem1bb.js} +7 -9
- package/dist/{node-f0ykebbv.js → node-9sg7ajby.js} +25 -7
- package/dist/{oauth-refresh-sweep-aefzwvvq.js → oauth-refresh-sweep-sh9q25xp.js} +10 -7
- package/dist/{onboard-kgpr9mbn.js → onboard-54qmnqxe.js} +2 -2
- package/dist/{opencode-adapter-0c8e70dk.js → opencode-adapter-wjfa2wvd.js} +2 -2
- package/dist/{otel-impl-x8zp4y5a.js → otel-impl-ycqzp2a1.js} +2 -2
- package/dist/{pi-mono-adapter-t280ah5c.js → pi-mono-adapter-e77e9zst.js} +4 -4
- package/dist/{pricing-refresh-9e0q7cwk.js → pricing-refresh-atnkngqs.js} +7 -7
- package/dist/{rbac-roles-kcp6zge2.js → rbac-roles-9pjphh9q.js} +6 -6
- package/dist/{rbac-roles-790j3ga8.js → rbac-roles-j78wdksm.js} +6 -6
- package/dist/{render-v2-tch4nefj.js → render-v2-pxjs49fx.js} +6 -7
- package/dist/{setup-rcm303ns.js → setup-ymej0xtx.js} +2 -2
- package/dist/{work-objects-ctg7t70w.js → work-objects-3nh4ymzb.js} +22 -26
- package/dist/{worker-5dp0xm55.js → worker-qa9fkz5s.js} +34 -38
- package/dist/{x-v3yw66zs.js → x-ma4gnfgy.js} +2 -2
- package/openapi.json +5 -2
- package/package.json +9 -5
- 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/sqlite-store.ts +63 -11
- 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/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/workflow-replay.ts +77 -0
- 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/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 +69 -3
- package/src/providers/amp-adapter.ts +1 -1
- package/src/providers/cursor-adapter.ts +1 -1
- 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 +3 -1
- package/src/tests/acp-adapter.test.ts +127 -2
- package/src/tests/boot-scrub-sweep.test.ts +390 -0
- package/src/tests/check-text-columns.test.ts +145 -0
- package/src/tests/claude-sdk-process.fixture.ts +13 -2
- package/src/tests/codex-oauth-device.test.ts +23 -37
- 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/entrypoint-acp-target-binary.test.ts +31 -1
- package/src/tests/events-scrub.test.ts +88 -0
- package/src/tests/fixtures/secret-corpus.ts +320 -0
- 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/workflow-replay.test.ts +518 -0
- package/src/tests/workflow-scrub.test.ts +242 -0
- package/src/tools/db-query.ts +1 -1
- package/src/tools/inject-learning.ts +1 -1
- package/src/tools/workflows/get-workflow-run.ts +3 -2
- package/src/types.ts +1 -1
- 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/recovery.ts +10 -1
- package/src/workflows/resume.ts +62 -3
- package/src/workflows/retry-poller.ts +3 -0
- package/dist/boot-scrub-logs-246yn076.js +0 -99
- package/dist/cli-3a4m1aws.js +0 -572
- package/dist/cli-a87b04k8.js +0 -951
- package/dist/cli-cvk6yzw5.js +0 -40
- package/dist/cli-h1spv8v4.js +0 -427
- package/dist/cli-jqt9hrnz.js +0 -168
- package/dist/cli-yhmwmv0g.js +0 -9281
- package/src/be/boot-scrub-logs.ts +0 -132
|
@@ -1,31 +1,28 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isUserAllowed
|
|
3
|
-
} from "./cli-
|
|
4
|
-
import"./cli-
|
|
5
|
-
import"./cli-
|
|
6
|
-
import"./cli-
|
|
7
|
-
import"./cli-
|
|
8
|
-
import"./cli-
|
|
3
|
+
} from "./cli-cpfmqz3n.js";
|
|
4
|
+
import"./cli-dw2q9f7g.js";
|
|
5
|
+
import"./cli-x7kpr72a.js";
|
|
6
|
+
import"./cli-df56tqdw.js";
|
|
7
|
+
import"./cli-xvc3q9br.js";
|
|
8
|
+
import"./cli-mv2520nm.js";
|
|
9
9
|
import"./cli-w0bwte75.js";
|
|
10
10
|
import"./cli-re8z5p8p.js";
|
|
11
|
-
import"./cli-
|
|
12
|
-
import"./cli-
|
|
13
|
-
import"./cli-
|
|
14
|
-
import"./cli-
|
|
11
|
+
import"./cli-0nhdwxd5.js";
|
|
12
|
+
import"./cli-rggdq8wq.js";
|
|
13
|
+
import"./cli-ysnyhws9.js";
|
|
14
|
+
import"./cli-jvj6a0cv.js";
|
|
15
15
|
import"./cli-epan13p1.js";
|
|
16
16
|
import"./cli-f14fvzag.js";
|
|
17
17
|
import"./cli-zt3w1cn1.js";
|
|
18
|
-
import"./cli-
|
|
19
|
-
import"./cli-
|
|
18
|
+
import"./cli-f2n17zhp.js";
|
|
19
|
+
import"./cli-feh3dkah.js";
|
|
20
20
|
import"./cli-3dpj7atn.js";
|
|
21
21
|
import"./cli-2x0e561b.js";
|
|
22
22
|
import"./cli-pkke6geq.js";
|
|
23
23
|
import"./cli-rb9m6rpe.js";
|
|
24
24
|
import"./cli-mzfth0bp.js";
|
|
25
|
-
import"./cli-
|
|
26
|
-
import"./cli-yhmwmv0g.js";
|
|
27
|
-
import"./cli-wfajtmf7.js";
|
|
28
|
-
import"./cli-a87b04k8.js";
|
|
25
|
+
import"./cli-j2jbr8af.js";
|
|
29
26
|
import"./cli-fad8m16k.js";
|
|
30
27
|
import"./cli-bsakbbkm.js";
|
|
31
28
|
import"./cli-zxg80zs9.js";
|
|
@@ -34,10 +31,9 @@ import"./cli-ydt3zkwv.js";
|
|
|
34
31
|
import {
|
|
35
32
|
getTaskUrl,
|
|
36
33
|
slackTaskOutput
|
|
37
|
-
} from "./cli-
|
|
34
|
+
} from "./cli-ecknp7p1.js";
|
|
38
35
|
import"./cli-q51yprfq.js";
|
|
39
36
|
import"./cli-3er6gcsn.js";
|
|
40
|
-
import"./cli-cvk6yzw5.js";
|
|
41
37
|
import"./cli-yatxqynm.js";
|
|
42
38
|
import"./cli-b0f70z24.js";
|
|
43
39
|
import"./cli-nexwh8zg.js";
|
|
@@ -46,16 +42,16 @@ import"./cli-1m2e086m.js";
|
|
|
46
42
|
import"./cli-bzr0ftht.js";
|
|
47
43
|
import"./cli-bd957dgb.js";
|
|
48
44
|
import"./cli-pzxba7gw.js";
|
|
49
|
-
import"./cli-
|
|
45
|
+
import"./cli-8kgvmkak.js";
|
|
50
46
|
import"./cli-rfphkzh5.js";
|
|
51
47
|
import {
|
|
52
48
|
getAgentById,
|
|
53
49
|
getTaskById,
|
|
54
|
-
init_db
|
|
55
|
-
} from "./cli-
|
|
56
|
-
import"./cli-
|
|
50
|
+
init_db1 as init_db
|
|
51
|
+
} from "./cli-yshaazs1.js";
|
|
52
|
+
import"./cli-xvdgasgy.js";
|
|
57
53
|
import"./cli-3qhyh31j.js";
|
|
58
|
-
import"./cli-
|
|
54
|
+
import"./cli-jhm6hzjn.js";
|
|
59
55
|
import"./cli-7mm2r1kp.js";
|
|
60
56
|
import"./cli-g5erf0zt.js";
|
|
61
57
|
import"./cli-dmtrxqhg.js";
|
|
@@ -73,10 +69,10 @@ import {
|
|
|
73
69
|
import"./cli-zsh093hk.js";
|
|
74
70
|
import"./cli-sd0mxa3c.js";
|
|
75
71
|
import"./cli-w5e1d1vv.js";
|
|
76
|
-
import"./cli-
|
|
77
|
-
import"./cli-
|
|
72
|
+
import"./cli-4r1sjfc4.js";
|
|
73
|
+
import"./cli-mb75wpxf.js";
|
|
78
74
|
import"./cli-zf8jjwex.js";
|
|
79
|
-
import"./cli-
|
|
75
|
+
import"./cli-wt7ccy4r.js";
|
|
80
76
|
import"./cli-bc05qbss.js";
|
|
81
77
|
|
|
82
78
|
// src/slack/work-objects.ts
|
|
@@ -1,73 +1,69 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runAgent
|
|
3
|
-
} from "./cli-
|
|
3
|
+
} from "./cli-vzc73wet.js";
|
|
4
4
|
import"./cli-9q3wt23f.js";
|
|
5
|
-
import"./cli-
|
|
6
|
-
import"./cli-
|
|
7
|
-
import"./cli-
|
|
8
|
-
import"./cli-
|
|
9
|
-
import"./cli-
|
|
5
|
+
import"./cli-68r1j4sg.js";
|
|
6
|
+
import"./cli-fn697bnt.js";
|
|
7
|
+
import"./cli-3qn4r334.js";
|
|
8
|
+
import"./cli-8t229cmr.js";
|
|
9
|
+
import"./cli-h3x613ze.js";
|
|
10
10
|
import"./cli-hsxj0yar.js";
|
|
11
|
-
import"./cli-
|
|
12
|
-
import"./cli-
|
|
13
|
-
import"./cli-
|
|
14
|
-
import"./cli-
|
|
11
|
+
import"./cli-hf5s9pgf.js";
|
|
12
|
+
import"./cli-3ddybbbx.js";
|
|
13
|
+
import"./cli-v2a8x45d.js";
|
|
14
|
+
import"./cli-mwegs4af.js";
|
|
15
15
|
import"./cli-9k7mqz00.js";
|
|
16
16
|
import"./cli-gt4hxb8p.js";
|
|
17
|
-
import"./cli-
|
|
18
|
-
import"./cli-
|
|
19
|
-
import"./cli-
|
|
17
|
+
import"./cli-0qjcsxgz.js";
|
|
18
|
+
import"./cli-rsy933yz.js";
|
|
19
|
+
import"./cli-y59h2pk9.js";
|
|
20
20
|
import"./cli-v6vv7dy8.js";
|
|
21
21
|
import"./cli-q2j38vre.js";
|
|
22
22
|
import"./cli-zm7njwzd.js";
|
|
23
23
|
import"./cli-ptcz1cqy.js";
|
|
24
24
|
import"./cli-32bca7nr.js";
|
|
25
|
-
import"./cli-
|
|
25
|
+
import"./cli-p4ztb80h.js";
|
|
26
26
|
import"./cli-hp1n6zq3.js";
|
|
27
27
|
import"./cli-tng3131n.js";
|
|
28
28
|
import"./cli-5bfdm1ah.js";
|
|
29
29
|
import"./cli-efnd2kce.js";
|
|
30
|
-
import"./cli-
|
|
30
|
+
import"./cli-zp67qg5x.js";
|
|
31
31
|
import"./cli-bqjfjex4.js";
|
|
32
32
|
import"./cli-eree7rnv.js";
|
|
33
33
|
import"./cli-2pdaysab.js";
|
|
34
34
|
import"./cli-ttbsse3f.js";
|
|
35
|
-
import"./cli-
|
|
35
|
+
import"./cli-zy7vwsne.js";
|
|
36
36
|
import"./cli-dpvkp2et.js";
|
|
37
37
|
import {
|
|
38
38
|
getEnabledCapabilities
|
|
39
|
-
} from "./cli-
|
|
40
|
-
import"./cli-
|
|
41
|
-
import"./cli-
|
|
39
|
+
} from "./cli-df56tqdw.js";
|
|
40
|
+
import"./cli-xvc3q9br.js";
|
|
41
|
+
import"./cli-mv2520nm.js";
|
|
42
42
|
import"./cli-w0bwte75.js";
|
|
43
43
|
import"./cli-re8z5p8p.js";
|
|
44
|
-
import"./cli-
|
|
45
|
-
import"./cli-
|
|
46
|
-
import"./cli-
|
|
47
|
-
import"./cli-
|
|
44
|
+
import"./cli-0nhdwxd5.js";
|
|
45
|
+
import"./cli-rggdq8wq.js";
|
|
46
|
+
import"./cli-ysnyhws9.js";
|
|
47
|
+
import"./cli-jvj6a0cv.js";
|
|
48
48
|
import"./cli-epan13p1.js";
|
|
49
49
|
import"./cli-f14fvzag.js";
|
|
50
50
|
import"./cli-zt3w1cn1.js";
|
|
51
|
-
import"./cli-
|
|
52
|
-
import"./cli-
|
|
51
|
+
import"./cli-f2n17zhp.js";
|
|
52
|
+
import"./cli-feh3dkah.js";
|
|
53
53
|
import"./cli-3dpj7atn.js";
|
|
54
54
|
import"./cli-2x0e561b.js";
|
|
55
55
|
import"./cli-pkke6geq.js";
|
|
56
56
|
import"./cli-rb9m6rpe.js";
|
|
57
57
|
import"./cli-mzfth0bp.js";
|
|
58
|
-
import"./cli-
|
|
59
|
-
import"./cli-yhmwmv0g.js";
|
|
60
|
-
import"./cli-wfajtmf7.js";
|
|
61
|
-
import"./cli-a87b04k8.js";
|
|
58
|
+
import"./cli-j2jbr8af.js";
|
|
62
59
|
import"./cli-fad8m16k.js";
|
|
63
60
|
import"./cli-bsakbbkm.js";
|
|
64
61
|
import"./cli-zxg80zs9.js";
|
|
65
62
|
import"./cli-51tf7ac3.js";
|
|
66
63
|
import"./cli-ydt3zkwv.js";
|
|
67
|
-
import"./cli-
|
|
64
|
+
import"./cli-ecknp7p1.js";
|
|
68
65
|
import"./cli-q51yprfq.js";
|
|
69
66
|
import"./cli-3er6gcsn.js";
|
|
70
|
-
import"./cli-cvk6yzw5.js";
|
|
71
67
|
import"./cli-yatxqynm.js";
|
|
72
68
|
import"./cli-b0f70z24.js";
|
|
73
69
|
import"./cli-nexwh8zg.js";
|
|
@@ -76,12 +72,12 @@ import"./cli-1m2e086m.js";
|
|
|
76
72
|
import"./cli-bzr0ftht.js";
|
|
77
73
|
import"./cli-bd957dgb.js";
|
|
78
74
|
import"./cli-pzxba7gw.js";
|
|
79
|
-
import"./cli-
|
|
75
|
+
import"./cli-8kgvmkak.js";
|
|
80
76
|
import"./cli-rfphkzh5.js";
|
|
81
|
-
import"./cli-
|
|
82
|
-
import"./cli-
|
|
77
|
+
import"./cli-yshaazs1.js";
|
|
78
|
+
import"./cli-xvdgasgy.js";
|
|
83
79
|
import"./cli-3qhyh31j.js";
|
|
84
|
-
import"./cli-
|
|
80
|
+
import"./cli-jhm6hzjn.js";
|
|
85
81
|
import"./cli-7mm2r1kp.js";
|
|
86
82
|
import"./cli-g5erf0zt.js";
|
|
87
83
|
import"./cli-dmtrxqhg.js";
|
|
@@ -96,10 +92,10 @@ import"./cli-ej6gbxfb.js";
|
|
|
96
92
|
import"./cli-zsh093hk.js";
|
|
97
93
|
import"./cli-sd0mxa3c.js";
|
|
98
94
|
import"./cli-w5e1d1vv.js";
|
|
99
|
-
import"./cli-
|
|
100
|
-
import"./cli-
|
|
95
|
+
import"./cli-4r1sjfc4.js";
|
|
96
|
+
import"./cli-mb75wpxf.js";
|
|
101
97
|
import"./cli-zf8jjwex.js";
|
|
102
|
-
import"./cli-
|
|
98
|
+
import"./cli-wt7ccy4r.js";
|
|
103
99
|
import"./cli-knd276ed.js";
|
|
104
100
|
import"./cli-bc05qbss.js";
|
|
105
101
|
|
|
@@ -3,11 +3,11 @@ import {
|
|
|
3
3
|
executeComposioRequest,
|
|
4
4
|
formatComposioResultForCli,
|
|
5
5
|
parseComposioArgs
|
|
6
|
-
} from "./cli-
|
|
6
|
+
} from "./cli-xvc3q9br.js";
|
|
7
7
|
import {
|
|
8
8
|
init_secret_scrubber,
|
|
9
9
|
scrubSecrets
|
|
10
|
-
} from "./cli-
|
|
10
|
+
} from "./cli-wt7ccy4r.js";
|
|
11
11
|
import"./cli-bc05qbss.js";
|
|
12
12
|
|
|
13
13
|
// src/commands/x.ts
|
package/openapi.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"openapi": "3.1.0",
|
|
3
3
|
"info": {
|
|
4
4
|
"title": "Agent Swarm API",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.166.0",
|
|
6
6
|
"description": "Multi-agent orchestration API for Claude Code, Codex, and Gemini CLI. Enables task distribution, agent communication, and service discovery.\n\nMCP tools are documented separately in [MCP.md](./MCP.md)."
|
|
7
7
|
},
|
|
8
8
|
"servers": [
|
|
@@ -755,6 +755,8 @@
|
|
|
755
755
|
"type": "string",
|
|
756
756
|
"enum": [
|
|
757
757
|
"opencode",
|
|
758
|
+
"gemini",
|
|
759
|
+
"copilot",
|
|
758
760
|
"custom"
|
|
759
761
|
]
|
|
760
762
|
},
|
|
@@ -9638,7 +9640,7 @@
|
|
|
9638
9640
|
}
|
|
9639
9641
|
},
|
|
9640
9642
|
"400": {
|
|
9641
|
-
"description": "Invalid or disallowed SQL",
|
|
9643
|
+
"description": "Invalid or disallowed SQL, including queries that read credential tables",
|
|
9642
9644
|
"content": {
|
|
9643
9645
|
"application/json": {
|
|
9644
9646
|
"schema": {
|
|
@@ -10286,6 +10288,7 @@
|
|
|
10286
10288
|
"enum": [
|
|
10287
10289
|
"opencode",
|
|
10288
10290
|
"gemini",
|
|
10291
|
+
"copilot",
|
|
10289
10292
|
"custom"
|
|
10290
10293
|
]
|
|
10291
10294
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@desplega.ai/agent-swarm",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.166.0",
|
|
4
4
|
"description": "agent-swarm.dev — an open-source operating system for AI work: a lead agent breaks goals into tasks, routes them to specialized workers such as Claude Code or Codex, runs each worker in an isolated container, and preserves shared memory, tools, schedules, and review gates so delegated work compounds across sessions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent-swarm.dev",
|
|
@@ -95,6 +95,8 @@
|
|
|
95
95
|
"check:extension-schema": "bun scripts/build-extension-manifest-schema.ts --check",
|
|
96
96
|
"build:extension-catalog": "bun scripts/build-extension-catalog.ts",
|
|
97
97
|
"check:extension-catalog": "bun scripts/build-extension-catalog.ts --check",
|
|
98
|
+
"build:secret-rules": "bun scripts/gen-secret-rules.ts",
|
|
99
|
+
"check:secret-rules": "bun scripts/gen-secret-rules.ts --check",
|
|
98
100
|
"build:cli": "bun run scripts/build-cli.ts",
|
|
99
101
|
"mono:build": "turbo run build",
|
|
100
102
|
"mono:test": "turbo run test",
|
|
@@ -200,20 +202,21 @@
|
|
|
200
202
|
"dependencies": {
|
|
201
203
|
"@agentclientprotocol/sdk": "1.7.0",
|
|
202
204
|
"@ai-sdk/openai": "^3.0.41",
|
|
203
|
-
"@anthropic-ai/claude-agent-sdk": "0.3.
|
|
204
|
-
"@anthropic-ai/sdk": "^0.
|
|
205
|
+
"@anthropic-ai/claude-agent-sdk": "0.3.293",
|
|
206
|
+
"@anthropic-ai/sdk": "^0.132.0",
|
|
205
207
|
"@asteasolutions/zod-to-openapi": "^8.0.0",
|
|
206
208
|
"@aws-sdk/client-bedrock": "3.1048.0",
|
|
207
|
-
"@cursor/sdk": "1.0.
|
|
209
|
+
"@cursor/sdk": "1.0.37",
|
|
208
210
|
"@desplega.ai/business-use": "^0.4.2",
|
|
209
211
|
"@desplega.ai/localtunnel": "^2.2.0",
|
|
210
212
|
"@earendil-works/pi-agent-core": "^1.0.4",
|
|
211
213
|
"@earendil-works/pi-ai": "^1.0.4",
|
|
212
214
|
"@earendil-works/pi-coding-agent": "^1.0.4",
|
|
213
215
|
"@inkjs/ui": "^2.0.0",
|
|
216
|
+
"@jitl/quickjs-singlefile-mjs-release-sync": "0.32.0",
|
|
214
217
|
"@linear/sdk": "^77.0.0",
|
|
215
218
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
216
|
-
"@openai/codex": "0.
|
|
219
|
+
"@openai/codex": "0.161.0",
|
|
217
220
|
"@opencode-ai/sdk": "^1.18.35",
|
|
218
221
|
"@openfort/openfort-node": "^0.9.1",
|
|
219
222
|
"@opentelemetry/api": "^1.9.1",
|
|
@@ -237,6 +240,7 @@
|
|
|
237
240
|
"ink": "^6.5.1",
|
|
238
241
|
"oauth4webapi": "^3.8.5",
|
|
239
242
|
"openai": "^6.22.0",
|
|
243
|
+
"quickjs-emscripten-core": "0.32.0",
|
|
240
244
|
"react": "19.2.3",
|
|
241
245
|
"react-devtools-core": "^7.0.1",
|
|
242
246
|
"sqlite-vec": "^0.1.9",
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { AutomationIntegrationId, ScheduledTask, Workflow } from "@/types";
|
|
2
2
|
import { getSlackConfiguration, isSlackConfigured } from "../slack/config";
|
|
3
3
|
import { isEnvFlagEnabled } from "../utils/env-flag";
|
|
4
|
+
import { scrubSecrets } from "../utils/secret-scrubber";
|
|
4
5
|
import { getDbClient } from "./db";
|
|
5
6
|
import { getOAuthApp, getOAuthTokens } from "./db-queries/oauth";
|
|
7
|
+
import { scrubJsonValue } from "./scrub-json";
|
|
6
8
|
|
|
7
9
|
export type AutomationKind = "schedule" | "workflow";
|
|
8
10
|
export type AutomationState = "running" | "needs_setup";
|
|
@@ -349,6 +351,9 @@ export async function recordSchedulePreflightFailure(
|
|
|
349
351
|
failureReason: string,
|
|
350
352
|
now: Date = new Date(),
|
|
351
353
|
): Promise<boolean> {
|
|
354
|
+
// Scrub before the same-day dedup compare: the stored message is scrubbed,
|
|
355
|
+
// so a raw reason would never match it and the dedup would stop working.
|
|
356
|
+
const message = scrubSecrets(failureReason);
|
|
352
357
|
return await getDbClient().transaction(async (tx) => {
|
|
353
358
|
const row = await tx.get<{ lastErrorAt: string | null; lastErrorMessage: string | null }>(
|
|
354
359
|
"SELECT lastErrorAt, lastErrorMessage FROM scheduled_tasks WHERE id = ?",
|
|
@@ -356,7 +361,7 @@ export async function recordSchedulePreflightFailure(
|
|
|
356
361
|
);
|
|
357
362
|
if (!row) return false;
|
|
358
363
|
if (
|
|
359
|
-
row.lastErrorMessage ===
|
|
364
|
+
row.lastErrorMessage === message &&
|
|
360
365
|
row.lastErrorAt?.slice(0, 10) === now.toISOString().slice(0, 10)
|
|
361
366
|
) {
|
|
362
367
|
return false;
|
|
@@ -365,7 +370,7 @@ export async function recordSchedulePreflightFailure(
|
|
|
365
370
|
`UPDATE scheduled_tasks
|
|
366
371
|
SET lastErrorAt = ?, lastErrorMessage = ?, lastUpdatedAt = ?
|
|
367
372
|
WHERE id = ?`,
|
|
368
|
-
[now.toISOString(),
|
|
373
|
+
[now.toISOString(), message, now.toISOString(), scheduleId],
|
|
369
374
|
);
|
|
370
375
|
return true;
|
|
371
376
|
});
|
|
@@ -404,8 +409,8 @@ export async function recordWorkflowPreflightFailure(input: {
|
|
|
404
409
|
runId,
|
|
405
410
|
input.workflowId,
|
|
406
411
|
input.triggerType,
|
|
407
|
-
input.triggerData === undefined ? null :
|
|
408
|
-
input.failureReason,
|
|
412
|
+
input.triggerData === undefined ? null : scrubJsonValue(input.triggerData),
|
|
413
|
+
scrubSecrets(input.failureReason),
|
|
409
414
|
input.createdBy ?? null,
|
|
410
415
|
timestamp,
|
|
411
416
|
timestamp,
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Versioned boot retro-sweep: re-scrub stored free-text columns whenever the
|
|
3
|
+
* redaction rules change.
|
|
4
|
+
*
|
|
5
|
+
* Rows written before a scrubber rule existed keep the secret it would now
|
|
6
|
+
* catch. This sweep re-runs `scrubSecrets` over every target column once per
|
|
7
|
+
* `SCRUBBER_RULES_VERSION` and redacts matching rows IN PLACE (irreversible;
|
|
8
|
+
* a redaction, not a deletion). The done marker is
|
|
9
|
+
* `seed_state(kind='maintenance', key='boot-scrub-v<N>')`, so bumping the
|
|
10
|
+
* version re-runs it on the next boot.
|
|
11
|
+
*
|
|
12
|
+
* Restart-safe: each target keeps an id cursor in seed_state
|
|
13
|
+
* (`boot-scrub-v<N>:<table>:cursor`), saved in the same transaction as the
|
|
14
|
+
* batch's writes, so a restart resumes after the last committed batch.
|
|
15
|
+
*
|
|
16
|
+
* Non-blocking: the regexes run OUTSIDE the write lock. Each batch is read,
|
|
17
|
+
* scrubbed in JS, and only the changed rows plus the cursor go into one short
|
|
18
|
+
* transaction. Every UPDATE is compare-and-set on the value that was read, so
|
|
19
|
+
* a row a concurrent writer moved in between is skipped, never clobbered. The
|
|
20
|
+
* loop yields between batches so /health and probes stay responsive.
|
|
21
|
+
*
|
|
22
|
+
* Replay state: `workflow_run_steps.output` and `workflow_runs.context` are
|
|
23
|
+
* also replayed by resume and recovery. A row written before the sealed
|
|
24
|
+
* `*_replay` columns existed has only the plain value, so before redacting it
|
|
25
|
+
* the sweep seals the original into the empty replay column (same CAS write).
|
|
26
|
+
*
|
|
27
|
+
* Logs counts only, never content.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
import { contentSha256 } from "@/commands/profile-sync";
|
|
31
|
+
import { SCRUBBER_RULES_VERSION, scrubSecrets } from "../utils/secret-scrubber";
|
|
32
|
+
import { getDbClient } from "./db";
|
|
33
|
+
import type { DbExecutor, DbParam } from "./db-client";
|
|
34
|
+
import { getMemoryStore } from "./memory";
|
|
35
|
+
import type { MemoryScrubFields } from "./memory/types";
|
|
36
|
+
import { breaksJsonValidity } from "./scrub-json";
|
|
37
|
+
import { sealJson } from "./sealed-json";
|
|
38
|
+
|
|
39
|
+
const DEFAULT_BATCH_SIZE = 200;
|
|
40
|
+
|
|
41
|
+
/** Yield to the event loop so probes can respond. */
|
|
42
|
+
const yieldTick = () => new Promise<void>((r) => setTimeout(r, 5));
|
|
43
|
+
|
|
44
|
+
type SweepTarget = {
|
|
45
|
+
table: string;
|
|
46
|
+
columns: string[];
|
|
47
|
+
/** Recompute `hashColumn = sha256(sourceColumn)` when the source changes. */
|
|
48
|
+
hash?: { column: string; of: string };
|
|
49
|
+
/** Route writes through the memory store (FTS sync + embedding reset). */
|
|
50
|
+
memory?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* `column -> sealed replay column`. When the sweep redacts `column` and the
|
|
53
|
+
* replay column is NULL, it seals the original there first.
|
|
54
|
+
*/
|
|
55
|
+
replay?: Record<string, string>;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/** Swept in this order. Every table has a TEXT `id` primary key. */
|
|
59
|
+
export const BOOT_SCRUB_TARGETS: readonly SweepTarget[] = [
|
|
60
|
+
{ table: "session_logs", columns: ["content"] },
|
|
61
|
+
{ table: "agent_tasks", columns: ["task", "output", "failureReason", "progress"] },
|
|
62
|
+
{ table: "agent_memory", columns: ["name", "content", "summary"], memory: true },
|
|
63
|
+
{
|
|
64
|
+
table: "agent_memory_version",
|
|
65
|
+
columns: ["content"],
|
|
66
|
+
hash: { column: "contentHash", of: "content" },
|
|
67
|
+
},
|
|
68
|
+
{ table: "events", columns: ["data"] },
|
|
69
|
+
{
|
|
70
|
+
table: "workflow_run_steps",
|
|
71
|
+
columns: ["input", "output", "error", "diagnostics"],
|
|
72
|
+
replay: { output: "output_replay" },
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
table: "workflow_runs",
|
|
76
|
+
columns: ["triggerData", "context", "error"],
|
|
77
|
+
replay: { context: "context_replay" },
|
|
78
|
+
},
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
export type BootScrubTableStats = {
|
|
82
|
+
table: string;
|
|
83
|
+
scanned: number;
|
|
84
|
+
changed: number;
|
|
85
|
+
skippedInvalidJson: number;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export type BootScrubSweepOptions = {
|
|
89
|
+
/** Rules version to key on. Defaults to `SCRUBBER_RULES_VERSION` (tests inject). */
|
|
90
|
+
version?: number;
|
|
91
|
+
batchSize?: number;
|
|
92
|
+
/** Scrub function. Defaults to `scrubSecrets` (tests inject to force edge cases). */
|
|
93
|
+
scrub?: (text: string) => string;
|
|
94
|
+
/**
|
|
95
|
+
* Test hook, called after each batch commits with the ids it scanned. A
|
|
96
|
+
* throw aborts the run with the cursor already saved.
|
|
97
|
+
*/
|
|
98
|
+
afterBatch?: (info: { table: string; ids: string[] }) => void | Promise<void>;
|
|
99
|
+
/** Re-embed redacted memory rows after the sweep. Default true. */
|
|
100
|
+
reembed?: boolean;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export function bootScrubDoneKey(version: number): string {
|
|
104
|
+
return `boot-scrub-v${version}`;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function bootScrubCursorKey(version: number, table: string): string {
|
|
108
|
+
return `boot-scrub-v${version}:${table}:cursor`;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Run the sweep for the current rules version. Returns per-table stats, or
|
|
113
|
+
* null when this version was already swept.
|
|
114
|
+
*/
|
|
115
|
+
export async function runBootScrubSweep(
|
|
116
|
+
opts: BootScrubSweepOptions = {},
|
|
117
|
+
): Promise<BootScrubTableStats[] | null> {
|
|
118
|
+
const version = opts.version ?? SCRUBBER_RULES_VERSION;
|
|
119
|
+
const doneKey = bootScrubDoneKey(version);
|
|
120
|
+
const done = await getDbClient().get<{ key: string }>(
|
|
121
|
+
"SELECT key FROM seed_state WHERE kind = 'maintenance' AND key = ?",
|
|
122
|
+
[doneKey],
|
|
123
|
+
);
|
|
124
|
+
if (done) return null;
|
|
125
|
+
|
|
126
|
+
const tag = `boot-scrub-v${version}`;
|
|
127
|
+
console.log(`[${tag}] starting`);
|
|
128
|
+
|
|
129
|
+
const stats: BootScrubTableStats[] = [];
|
|
130
|
+
for (const target of BOOT_SCRUB_TARGETS) {
|
|
131
|
+
const tableStats = await sweepTarget(target, version, opts);
|
|
132
|
+
stats.push(tableStats);
|
|
133
|
+
console.log(
|
|
134
|
+
`${tag}: ${target.table} scanned=${tableStats.scanned} changed=${tableStats.changed} skipped_invalid_json=${tableStats.skippedInvalidJson}`,
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
await getDbClient().transaction(async (tx) => {
|
|
139
|
+
await tx.run(
|
|
140
|
+
`INSERT INTO seed_state (kind, key, seededHash, seededAt)
|
|
141
|
+
VALUES ('maintenance', ?, 'done', datetime('now'))
|
|
142
|
+
ON CONFLICT (kind, key) DO UPDATE SET seededHash = 'done', seededAt = datetime('now')`,
|
|
143
|
+
[doneKey],
|
|
144
|
+
);
|
|
145
|
+
await tx.run("DELETE FROM seed_state WHERE kind = 'maintenance' AND key LIKE ? ESCAPE '!'", [
|
|
146
|
+
`${doneKey.replace(/[!%_]/g, "!$&")}:%:cursor`,
|
|
147
|
+
]);
|
|
148
|
+
});
|
|
149
|
+
console.log(`[${tag}] complete`);
|
|
150
|
+
|
|
151
|
+
const memoryChanged = stats.find((s) => s.table === "agent_memory")?.changed ?? 0;
|
|
152
|
+
if (memoryChanged > 0 && opts.reembed !== false) {
|
|
153
|
+
// Redacted memory rows lost their embedding; regenerate from scrubbed text.
|
|
154
|
+
const { runBootReembed } = await import("./memory/boot-reembed");
|
|
155
|
+
await runBootReembed();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return stats;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async function sweepTarget(
|
|
162
|
+
target: SweepTarget,
|
|
163
|
+
version: number,
|
|
164
|
+
opts: BootScrubSweepOptions,
|
|
165
|
+
): Promise<BootScrubTableStats> {
|
|
166
|
+
const client = getDbClient();
|
|
167
|
+
const scrub = opts.scrub ?? scrubSecrets;
|
|
168
|
+
const batchSize = opts.batchSize ?? DEFAULT_BATCH_SIZE;
|
|
169
|
+
const cursorKey = bootScrubCursorKey(version, target.table);
|
|
170
|
+
const stats: BootScrubTableStats = {
|
|
171
|
+
table: target.table,
|
|
172
|
+
scanned: 0,
|
|
173
|
+
changed: 0,
|
|
174
|
+
skippedInvalidJson: 0,
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
let cursor =
|
|
178
|
+
(
|
|
179
|
+
await client.get<{ seededHash: string }>(
|
|
180
|
+
"SELECT seededHash FROM seed_state WHERE kind = 'maintenance' AND key = ?",
|
|
181
|
+
[cursorKey],
|
|
182
|
+
)
|
|
183
|
+
)?.seededHash ?? "";
|
|
184
|
+
|
|
185
|
+
const selectCols = [
|
|
186
|
+
"id",
|
|
187
|
+
...target.columns,
|
|
188
|
+
...(target.hash && !target.columns.includes(target.hash.column) ? [target.hash.column] : []),
|
|
189
|
+
...Object.values(target.replay ?? {}),
|
|
190
|
+
];
|
|
191
|
+
|
|
192
|
+
for (;;) {
|
|
193
|
+
const rows = await client.query<Record<string, string | null>>(
|
|
194
|
+
`SELECT ${selectCols.join(", ")} FROM ${target.table}
|
|
195
|
+
WHERE id > ? ORDER BY id ASC LIMIT ?`,
|
|
196
|
+
[cursor, batchSize],
|
|
197
|
+
);
|
|
198
|
+
if (rows.length === 0) break;
|
|
199
|
+
|
|
200
|
+
// Scrub outside the transaction: regexes never run under the write lock.
|
|
201
|
+
const pending: {
|
|
202
|
+
id: string;
|
|
203
|
+
before: Record<string, string | null>;
|
|
204
|
+
after: Record<string, string | null>;
|
|
205
|
+
}[] = [];
|
|
206
|
+
for (const row of rows) {
|
|
207
|
+
const after: Record<string, string | null> = {};
|
|
208
|
+
let differs = false;
|
|
209
|
+
let breaksJson = false;
|
|
210
|
+
for (const col of target.columns) {
|
|
211
|
+
const value = row[col];
|
|
212
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
213
|
+
after[col] = value ?? null;
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
const cleaned = scrub(value);
|
|
217
|
+
after[col] = cleaned;
|
|
218
|
+
if (cleaned !== value) {
|
|
219
|
+
differs = true;
|
|
220
|
+
if (breaksJsonValidity(value, cleaned)) breaksJson = true;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (!differs) continue;
|
|
224
|
+
if (breaksJson) {
|
|
225
|
+
stats.skippedInvalidJson++;
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
for (const [col, replayCol] of Object.entries(target.replay ?? {})) {
|
|
229
|
+
const value = row[col];
|
|
230
|
+
if (after[col] === value || typeof value !== "string" || row[replayCol] != null) continue;
|
|
231
|
+
try {
|
|
232
|
+
after[replayCol] = sealJson(JSON.parse(value));
|
|
233
|
+
} catch {
|
|
234
|
+
// Not JSON, so nothing replays it.
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
pending.push({ id: row.id as string, before: row, after });
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const batchLastId = rows[rows.length - 1]!.id as string;
|
|
241
|
+
await client.transaction(async (tx) => {
|
|
242
|
+
for (const { id, before, after } of pending) {
|
|
243
|
+
const wrote = target.memory
|
|
244
|
+
? await rewriteMemoryRow(id, before, after)
|
|
245
|
+
: await rewriteRow(tx, target, id, before, after);
|
|
246
|
+
if (wrote) stats.changed++;
|
|
247
|
+
}
|
|
248
|
+
await tx.run(
|
|
249
|
+
`INSERT INTO seed_state (kind, key, seededHash, seededAt)
|
|
250
|
+
VALUES ('maintenance', ?, ?, datetime('now'))
|
|
251
|
+
ON CONFLICT (kind, key) DO UPDATE SET seededHash = excluded.seededHash, seededAt = datetime('now')`,
|
|
252
|
+
[cursorKey, batchLastId],
|
|
253
|
+
);
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
stats.scanned += rows.length;
|
|
257
|
+
cursor = batchLastId;
|
|
258
|
+
await opts.afterBatch?.({ table: target.table, ids: rows.map((r) => r.id as string) });
|
|
259
|
+
await yieldTick();
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return stats;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
async function rewriteRow(
|
|
266
|
+
tx: DbExecutor,
|
|
267
|
+
target: SweepTarget,
|
|
268
|
+
id: string,
|
|
269
|
+
before: Record<string, string | null>,
|
|
270
|
+
after: Record<string, string | null>,
|
|
271
|
+
): Promise<boolean> {
|
|
272
|
+
const changedCols = target.columns.filter((c) => after[c] !== before[c]);
|
|
273
|
+
// Replay columns the sweep fills: only while still NULL (guarded below).
|
|
274
|
+
const sealedCols = Object.values(target.replay ?? {}).filter((c) => after[c] !== undefined);
|
|
275
|
+
const sets = [...changedCols, ...sealedCols].map((c) => `${c} = ?`);
|
|
276
|
+
const params: DbParam[] = [...changedCols, ...sealedCols].map((c) => after[c] ?? null);
|
|
277
|
+
if (target.hash && changedCols.includes(target.hash.of)) {
|
|
278
|
+
sets.push(`${target.hash.column} = ?`);
|
|
279
|
+
params.push(contentSha256(after[target.hash.of] ?? ""));
|
|
280
|
+
}
|
|
281
|
+
// Compare-and-set on every changed column.
|
|
282
|
+
const guards = [...changedCols.map((c) => `${c} IS ?`), ...sealedCols.map((c) => `${c} IS NULL`)];
|
|
283
|
+
params.push(id, ...changedCols.map((c) => before[c] ?? null));
|
|
284
|
+
const result = await tx.run(
|
|
285
|
+
`UPDATE ${target.table} SET ${sets.join(", ")} WHERE id = ? AND ${guards.join(" AND ")}`,
|
|
286
|
+
params,
|
|
287
|
+
);
|
|
288
|
+
return result.changes > 0;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
async function rewriteMemoryRow(
|
|
292
|
+
id: string,
|
|
293
|
+
before: Record<string, string | null>,
|
|
294
|
+
after: Record<string, string | null>,
|
|
295
|
+
): Promise<boolean> {
|
|
296
|
+
const pick = (r: Record<string, string | null>): MemoryScrubFields => ({
|
|
297
|
+
name: r.name ?? "",
|
|
298
|
+
content: r.content ?? "",
|
|
299
|
+
summary: r.summary ?? null,
|
|
300
|
+
});
|
|
301
|
+
return getMemoryStore().rewriteForScrub(id, pick(before), pick(after));
|
|
302
|
+
}
|