@desplega.ai/agent-swarm 2.5.4 → 2.7.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 +4 -2
- package/dist/{acp-adapter-ek38cwsv.js → acp-adapter-ma1js5n7.js} +9 -9
- package/dist/{actions-92mepq03.js → actions-1vhmtvg9.js} +21 -21
- package/dist/{amp-adapter-9gaxg015.js → amp-adapter-sxqqvmdk.js} +4 -4
- package/dist/{app-ctn8gsgx.js → app-mwx1d5a9.js} +3 -3
- package/dist/{assistant-zyr5kz47.js → assistant-yx1p6g82.js} +30 -26
- package/dist/{boot-reembed-w75maga2.js → boot-reembed-5h37a2c2.js} +1 -1
- package/dist/{boot-reembed-dwzfttdr.js → boot-reembed-7h78vmvv.js} +2 -1
- package/dist/{boot-scrub-sweep-e9kq43kf.js → boot-scrub-sweep-8mawd4gw.js} +4 -4
- package/dist/{boot-seeds-x28v3fhb.js → boot-seeds-ca84dhnn.js} +4 -4
- package/dist/{claude-adapter-f0afqnne.js → claude-adapter-wqt4hfkq.js} +9 -9
- package/dist/{claude-managed-adapter-x81a7r65.js → claude-managed-adapter-6fjqtr2z.js} +2 -2
- package/dist/{claude-managed-setup-bqzwjd9x.js → claude-managed-setup-rqv98sea.js} +10 -3
- package/dist/{claude-sdk-session-7b7whkaq.js → claude-sdk-session-f29f3b2x.js} +11 -11
- package/dist/{cli-sxgtf5fw.js → cli-07q03xm2.js} +1 -1
- package/dist/{cli-kxpfx2xr.js → cli-0z1xjzwa.js} +2 -2
- package/dist/{cli-g9vd9ece.js → cli-1hhbzkbb.js} +14 -16
- package/dist/{cli-qqzmjxkf.js → cli-1m9x8dr5.js} +11 -6
- package/dist/{cli-jbnn4vxb.js → cli-2pvzmas1.js} +3 -3
- package/dist/{cli-x77gen2p.js → cli-2y7v133v.js} +7 -7
- package/dist/{cli-dew6x255.js → cli-39aet655.js} +2 -2
- package/dist/{cli-g1cw7xtt.js → cli-39rrw8yp.js} +1 -1
- package/dist/{cli-jb30dzvk.js → cli-48gxjmcz.js} +530 -190
- package/dist/{cli-pzatvw94.js → cli-54sj64fc.js} +2 -2
- package/dist/{cli-bvpgr9ny.js → cli-60sty27p.js} +5 -5
- package/dist/{cli-asq5ydm4.js → cli-6a9qfa8b.js} +411 -69
- package/dist/{cli-277c31dw.js → cli-6mgdba42.js} +225 -3
- package/dist/{cli-19202kew.js → cli-6srv653c.js} +5 -5
- package/dist/{cli-n4c8e3s5.js → cli-708wdy32.js} +1 -1
- package/dist/{cli-pasyvjmm.js → cli-737pyqxr.js} +1 -1
- package/dist/{cli-6x9ma5w5.js → cli-803188pb.js} +1 -1
- package/dist/{cli-hh5we352.js → cli-86ehn4s5.js} +7 -7
- package/dist/{cli-9s05422w.js → cli-8mbc9za9.js} +1 -1
- package/dist/{cli-ff1tm9n9.js → cli-8wmj18cz.js} +1 -1
- package/dist/{cli-1r5ad7j5.js → cli-9gsm2rzp.js} +12 -12
- package/dist/{cli-mz9afxxf.js → cli-9pshx6rd.js} +17 -3
- package/dist/{cli-s682zgqz.js → cli-a6ds2epe.js} +1 -1
- package/dist/{cli-6a1xg1p7.js → cli-a89zdqz9.js} +2 -2
- package/dist/{cli-03vpq45j.js → cli-ay40dnj3.js} +2 -2
- package/dist/{cli-tsma7p8v.js → cli-aypd09nf.js} +2 -2
- package/dist/{cli-ethgy7ha.js → cli-b3yzyc57.js} +2 -2
- package/dist/{cli-bn0rewsy.js → cli-c081bj3b.js} +2 -2
- package/dist/{cli-mmhj8vd7.js → cli-c668vvcf.js} +11 -2
- package/dist/{cli-sbwsxvtd.js → cli-d20qvpr2.js} +2 -2
- package/dist/{cli-c952c7ac.js → cli-e1595bgx.js} +3 -3
- package/dist/{cli-621ce7kw.js → cli-f12mr20z.js} +3 -3
- package/dist/{cli-dqygeeh5.js → cli-f1e0ptjj.js} +10 -1
- package/dist/{cli-xzfq4at3.js → cli-f4dbh7a5.js} +16 -12
- package/dist/{cli-ha9rmwgq.js → cli-fb8m699c.js} +2 -2
- package/dist/{cli-5bnsc0e1.js → cli-gsfk58nw.js} +5 -5
- package/dist/cli-gt4h8cxw.js +895 -0
- package/dist/{cli-nwyw3zhg.js → cli-gxee0bqa.js} +1 -1
- package/dist/{cli-25n3mv5d.js → cli-h5jeg46p.js} +6 -6
- package/dist/{cli-gn5af0x5.js → cli-he9gbdx0.js} +62 -12
- package/dist/{cli-gbfxp48k.js → cli-j0ppywdr.js} +42 -35
- package/dist/{cli-k4tjsdx9.js → cli-j3y0x2n4.js} +277 -199
- package/dist/{cli-7p4jxgtt.js → cli-j9bpmykh.js} +75 -27
- package/dist/{cli-dabehxhp.js → cli-kt907da6.js} +1 -1
- package/dist/{cli-wx2nj19m.js → cli-kv7sbc2c.js} +6 -6
- package/dist/{cli-abs8ndtr.js → cli-m30k9777.js} +26 -26
- package/dist/{cli-cz5nmdxt.js → cli-m5e802r7.js} +2 -2
- package/dist/{cli-0shx9j93.js → cli-pfk92eqz.js} +2 -2
- package/dist/{cli-xtrz6bzs.js → cli-ptfq202x.js} +5 -3
- package/dist/{cli-6n8axjv1.js → cli-qj442fws.js} +2 -2
- package/dist/{cli-c61mbdds.js → cli-rd5m70gj.js} +4 -4
- package/dist/{cli-eftzyh9y.js → cli-s09j9vp5.js} +2 -2
- package/dist/{cli-m4ecdxvz.js → cli-s0mgx214.js} +7 -7
- package/dist/{cli-wghjkr0e.js → cli-sgqm2582.js} +10 -7
- package/dist/{cli-2655k16q.js → cli-sjctjr48.js} +2 -2
- package/dist/{cli-nzfnt2gs.js → cli-tf1n0r0b.js} +1 -1
- package/dist/{cli-x0f2v69c.js → cli-twctnkng.js} +12 -7
- package/dist/{cli-j6rktc91.js → cli-v6shg7na.js} +1 -1
- package/dist/{cli-gx4rm0qx.js → cli-vz78s5wm.js} +1 -1
- package/dist/{cli-gwhjmh8g.js → cli-wqr7cea4.js} +5 -5
- package/dist/{cli-e42vss7b.js → cli-x37r7qwf.js} +16 -8
- package/dist/{cli-4b2z6n0m.js → cli-yd2nreqw.js} +17 -8
- package/dist/{cli-64mh9mf3.js → cli-ymjpkxgn.js} +69 -17
- package/dist/{cli-5kqnemen.js → cli-yvy48785.js} +1 -1
- package/dist/{cli-9j129brq.js → cli-yxbsmx56.js} +6 -6
- package/dist/cli.js +22 -20
- package/dist/{codex-adapter-wch12q99.js → codex-adapter-zk59x2zh.js} +7 -7
- package/dist/{codex-hook-brpnycn5.js → codex-hook-xyjhvxwd.js} +1 -1
- package/dist/{codex-login-rn7c5gxt.js → codex-login-8cg0vhf2.js} +1 -1
- package/dist/{codex-session-runner-41pfcr95.js → codex-session-runner-kh6s4j3n.js} +8 -8
- package/dist/{commands-9849dkj6.js → commands-68et1qv2.js} +2 -2
- package/dist/{controller-ja0sd95p.js → controller-fyrbnzg4.js} +4 -4
- package/dist/{controllers-connect-xp05dj6x.js → controllers-connect-nep9h2xv.js} +23 -23
- package/dist/{cursor-adapter-623qxqew.js → cursor-adapter-yss3pg7t.js} +2 -2
- package/dist/{db-w759qmx0.js → db-28gjyvxj.js} +4 -2
- package/dist/{db-47vj40dy.js → db-8ftwvzba.js} +3 -3
- package/dist/{devin-adapter-4ycy4vrf.js → devin-adapter-byen2cxt.js} +1 -1
- package/dist/{dispatcher-7b8e4z2j.js → dispatcher-hayexmkr.js} +20 -20
- package/dist/{docker-s84hjs91.js → docker-fdzyewpz.js} +2 -2
- package/dist/{dsh-adapter-2ezw3xea.js → dsh-adapter-46wawff9.js} +2 -2
- package/dist/{e2b-9gkdhm3c.js → e2b-222hsajc.js} +2 -2
- package/dist/{e2b-cjtf8k1z.js → e2b-fn3zacvt.js} +2 -2
- package/dist/{easter-egg-3d-e4qv8dxj.js → easter-egg-3d-8d1e0h4m.js} +1 -1
- package/dist/{event-bus-3z78ep5n.js → event-bus-pghg8hqy.js} +1 -1
- package/dist/{execute-0xpz8950.js → execute-cjrfxfnm.js} +1 -1
- package/dist/{external-channel-e2s028da.js → external-channel-xbmxcg09.js} +2 -2
- package/dist/{grok-adapter-ys7gaqee.js → grok-adapter-ag4wks2a.js} +10 -10
- package/dist/handlers-tzmevqb5.js +41 -0
- package/dist/{heartbeat-w3mntghj.js → heartbeat-psfvcgwp.js} +23 -23
- package/dist/{hook-g7kvv6x9.js → hook-8pz04697.js} +6 -6
- package/dist/{hook-3jjywnpb.js → hook-cyq4mryn.js} +8 -8
- package/dist/{http-tkp7d4kb.js → http-haj1nd6k.js} +921 -169
- package/dist/{index-q7m26kvs.js → index-jwt2bj6f.js} +265 -97
- package/dist/{index-3n8m9ea2.js → index-q52f47pe.js} +1 -1
- package/dist/{index-31ceyf42.js → index-syvhnvtw.js} +1 -1
- package/dist/index-y1ajx04a.js +43 -0
- package/dist/{index-1ef1myq2.js → index-z5h22pes.js} +20 -20
- package/dist/{index-xdaahthb.js → index-zyq8ct52.js} +20 -20
- package/dist/{keepalive-v4ta8wgg.js → keepalive-xdvsamvj.js} +4 -4
- package/dist/lead-hqg57kdp.js +79 -0
- package/dist/{maintenance-84n1ex21.js → maintenance-4y2xzh3a.js} +1 -1
- package/dist/{oauth-refresh-sweep-vjnnandw.js → oauth-refresh-sweep-jd4r7zbs.js} +9 -4
- package/dist/{onboard-sfmpe4np.js → onboard-18447q9q.js} +6 -6
- package/dist/{opencode-adapter-jmpst4q4.js → opencode-adapter-26b2frdf.js} +7 -7
- package/dist/{otel-impl-v6cc0zve.js → otel-impl-f9tgr8yw.js} +2 -2
- package/dist/{pi-mono-adapter-fk8fkcf6.js → pi-mono-adapter-qn6qbga1.js} +38 -17
- package/dist/{pricing-refresh-fsk1e1zc.js → pricing-refresh-dw2tgb53.js} +3 -3
- package/dist/{rbac-roles-prmkdnkw.js → rbac-roles-aygm2760.js} +2 -2
- package/dist/{rbac-roles-zxmxqa39.js → rbac-roles-s4nwj2m3.js} +1 -1
- package/dist/render-v2-yfvdfr0x.js +16 -0
- package/dist/{resume-frdtgfa0.js → resume-1bmvjbf3.js} +9 -9
- package/dist/{runtime-bt5pkpm1.js → runtime-f7tpzedy.js} +1 -1
- package/dist/{session-access-fpez4y5q.js → session-access-r5garej6.js} +4 -4
- package/dist/session-source-backfill-424wzv0r.js +110 -0
- package/dist/{setup-mq6m3m8q.js → setup-8tygvxkq.js} +1 -1
- package/dist/{virtual-modules-mnfbh5mr.js → virtual-modules-xsw323b3.js} +2 -2
- package/dist/{work-objects-kfahhjsq.js → work-objects-ggnghpgf.js} +23 -23
- package/dist/worker-sqjd1nqf.js +79 -0
- package/dist/{x-pbpezr0s.js → x-wxrzvzx8.js} +2 -2
- package/openapi.json +1324 -14
- package/package.json +5 -3
- package/src/assets/source-key.ts +95 -0
- package/src/be/automation-preflight.ts +2 -0
- package/src/be/db/api-keys.ts +89 -0
- package/src/be/db/session-labels.ts +28 -0
- package/src/be/db/session-moves.ts +5 -6
- package/src/be/db/session-tree.ts +153 -14
- package/src/be/db/tasks/read.ts +11 -0
- package/src/be/db/tasks/write.ts +6 -1
- package/src/be/db/workflow-runs.ts +219 -6
- package/src/be/db-retention.ts +61 -6
- package/src/be/db.ts +135 -132
- package/src/be/memory/providers/openai-embedding.ts +5 -1
- package/src/be/memory/task-learning.ts +155 -0
- package/src/be/migrations/244_api_key_validation.sql +4 -0
- package/src/be/migrations/245_script_executor.sql +3 -0
- package/src/be/oauth-refresh-sweep.ts +2 -1
- package/src/be/onboarding.ts +4 -0
- package/src/be/scripts/boot-reembed.ts +2 -0
- package/src/be/scripts/db.ts +14 -4
- package/src/be/scripts/embeddings.ts +2 -0
- package/src/be/scripts/run-saved.ts +1 -0
- package/src/be/scripts/typecheck.ts +10 -4
- package/src/be/seed-skills/index.ts +7 -0
- package/src/be/session-source-backfill.ts +163 -0
- package/src/be/swarm-config-guard.ts +1 -0
- package/src/comb/review-batch.ts +28 -1
- package/src/comb/templates.ts +7 -2
- package/src/commands/claude-managed-setup.ts +7 -1
- package/src/commands/credential-refresh.ts +76 -1
- package/src/commands/credential-wait.ts +2 -2
- package/src/commands/onboard/compose-generator.ts +5 -3
- package/src/commands/provider-credentials.ts +212 -171
- package/src/commands/runner.ts +25 -4
- package/src/extensions/apply-task-create.ts +8 -1
- package/src/extensions/contract-types.generated.ts +1 -1
- package/src/extensions/contract.ts +5 -0
- package/src/heartbeat/heartbeat.ts +14 -1
- package/src/heartbeat/script-runner-probe.ts +47 -0
- package/src/http/all-routes.ts +2 -0
- package/src/http/api-keys.ts +77 -9
- package/src/http/assets.ts +15 -0
- package/src/http/codex-oauth-accounts.ts +191 -0
- package/src/http/comb.ts +15 -2
- package/src/http/config.ts +1 -1
- package/src/http/core.ts +6 -0
- package/src/http/fleet-benchmark.ts +5 -2
- package/src/http/idempotency-key.ts +1 -1
- package/src/http/index.ts +14 -3
- package/src/http/integrations.ts +5 -1
- package/src/http/kv.ts +8 -3
- package/src/http/onboarding.ts +6 -1
- package/src/http/pages-public.ts +38 -5
- package/src/http/pool-keys.ts +354 -0
- package/src/http/scripts.ts +27 -0
- package/src/http/sessions.ts +37 -12
- package/src/http/stats.ts +1 -0
- package/src/http/status.ts +26 -12
- package/src/http/tasks.ts +3 -0
- package/src/http/used-by.ts +7 -2
- package/src/http/workflows.ts +88 -9
- package/src/http/x.ts +5 -0
- package/src/integrations/chat-sdk/inbound.ts +27 -0
- package/src/kv-reserved-namespaces.ts +19 -0
- package/src/prompts/base-prompt.ts +21 -1
- package/src/prompts/session-templates.ts +17 -3
- package/src/providers/acp-targets.ts +1 -1
- package/src/providers/amp-adapter.ts +1 -1
- package/src/providers/claude-adapter.ts +5 -1
- package/src/providers/claude-managed-adapter.ts +16 -9
- package/src/providers/codex-adapter.ts +71 -11
- package/src/providers/dsh-adapter.ts +1 -1
- package/src/providers/pi-mono-adapter.ts +41 -11
- package/src/scheduler/scheduler.ts +5 -3
- package/src/scripts-runtime/eval-harness.ts +8 -1
- package/src/scripts-runtime/executors/native.ts +22 -16
- package/src/scripts-runtime/executors/quickjs-prelude.ts +103 -1
- package/src/scripts-runtime/executors/quickjs-runner.ts +2 -1
- package/src/scripts-runtime/executors/quickjs.ts +7 -0
- package/src/scripts-runtime/executors/registry.ts +32 -0
- package/src/scripts-runtime/executors/types.ts +7 -0
- package/src/scripts-runtime/host-validated-args.ts +133 -0
- package/src/scripts-runtime/loader.ts +30 -3
- package/src/scripts-runtime/swarm-sdk.ts +16 -3
- package/src/scripts-runtime/types/stdlib.d.ts +10 -2
- package/src/scripts-runtime/types/swarm-extension.d.ts +17 -8
- package/src/scripts-runtime/types/swarm-sdk.d.ts +10 -2
- package/src/slack/assistant.ts +7 -0
- package/src/slack/channel-labels.ts +74 -0
- package/src/slack/handlers.ts +8 -0
- package/src/slack/inbound-files.ts +5 -2
- package/src/slack/thread-buffer.ts +4 -0
- package/src/tasks/sibling-awareness.ts +12 -3
- package/src/telemetry-context.ts +5 -6
- package/src/telemetry-identity.ts +3 -3
- package/src/tests/api-key-status-by-suffix.test.ts +242 -0
- package/src/tests/api-keys-validation.test.ts +170 -0
- package/src/tests/base-prompt.test.ts +70 -2
- package/src/tests/claude-managed-adapter.test.ts +46 -0
- package/src/tests/claude-routes-e2e.test.ts +7 -2
- package/src/tests/codex-credential-pools.test.ts +120 -0
- package/src/tests/codex-gateway-route.test.ts +165 -0
- package/src/tests/codex-oauth-accounts.test.ts +357 -0
- package/src/tests/comb-review-batch.test.ts +63 -2
- package/src/tests/community-linear-delivery-loop.test.ts +2099 -0
- package/src/tests/config-pool-keys.test.ts +533 -0
- package/src/tests/credential-check.test.ts +294 -4
- package/src/tests/credential-refresh.test.ts +172 -1
- package/src/tests/db-retention.test.ts +9 -3
- package/src/tests/db-task-read-contract.test.ts +1 -0
- package/src/tests/db-task-write-contract.test.ts +1 -3
- package/src/tests/docs-index-footprint.test.js +3 -3
- package/src/tests/docs-index.test.ts +135 -0
- package/src/tests/dsh-adapter.test.ts +1 -1
- package/src/tests/extensions-pre-task.test.ts +53 -1
- package/src/tests/fetch-resolved-env.test.ts +16 -2
- package/src/tests/fixtures/extensions/record-task-create/hooks.ts +9 -0
- package/src/tests/fixtures/extensions/record-task-create/manifest.json +7 -0
- package/src/tests/fleet-benchmark.test.ts +8 -0
- package/src/tests/get-workflow-run-tool.test.ts +98 -0
- package/src/tests/heartbeat-checklist.test.ts +89 -0
- package/src/tests/heartbeat-script-runner-probe.test.ts +83 -0
- package/src/tests/integrations-http.test.ts +32 -2
- package/src/tests/internal-ai/complete-structured.test.ts +37 -1
- package/src/tests/internal-ai/credentials.test.ts +23 -0
- package/src/tests/kv-http.test.ts +32 -0
- package/src/tests/kv-tool.test.ts +25 -0
- package/src/tests/multi-runtime-registration.test.ts +12 -12
- package/src/tests/oauth-refresh-sweep.test.ts +34 -1
- package/src/tests/onboard-compose.test.ts +20 -0
- package/src/tests/onboarding.test.ts +108 -1
- package/src/tests/openai-embedding-credentials.test.ts +35 -0
- package/src/tests/opencode-adapter.test.ts +2 -1
- package/src/tests/openrouter-attribution-call-sites.test.ts +2 -2
- package/src/tests/org-website.test.ts +36 -0
- package/src/tests/pages-frame-ancestors.test.ts +162 -0
- package/src/tests/pi-codemode.test.ts +2 -1
- package/src/tests/pi-mono-adapter.test.ts +54 -0
- package/src/tests/pi-native-mcp.test.ts +13 -1
- package/src/tests/pi-tool-exposure.test.ts +8 -8
- package/src/tests/probe-tool-schema-tokens.test.ts +144 -0
- package/src/tests/prompt-template-session.test.ts +4 -3
- package/src/tests/provider-key-probes.test.ts +181 -0
- package/src/tests/rbac-e2e-helpers.test.ts +88 -1
- package/src/tests/rbac-e2e-helpers.ts +36 -11
- package/src/tests/request-composition-derive.test.ts +329 -0
- package/src/tests/script-connections.test.ts +4 -0
- package/src/tests/script-executor-conformance.test.ts +36 -1
- package/src/tests/script-executor-quickjs-pool.test.ts +50 -0
- package/src/tests/script-executor-quickjs.test.ts +140 -0
- package/src/tests/script-host-validated-args-native.test.ts +196 -0
- package/src/tests/script-per-script-executor.test.ts +415 -0
- package/src/tests/script-runs-retention.test.ts +212 -0
- package/src/tests/scripts-external-api.test.ts +45 -0
- package/src/tests/sdk-allowlist.test.ts +42 -2
- package/src/tests/self-improvement.test.ts +4 -4
- package/src/tests/session-source-backfill.test.ts +429 -0
- package/src/tests/session-source-keys.test.ts +236 -0
- package/src/tests/session-source-labels.test.ts +419 -0
- package/src/tests/sessions-detail-batch.test.ts +2 -0
- package/src/tests/sessions-move.test.ts +131 -0
- package/src/tests/sessions-tree.test.ts +299 -2
- package/src/tests/slack-inbound-files.test.ts +103 -23
- package/src/tests/status.test.ts +101 -18
- package/src/tests/store-progress-learning.test.ts +288 -0
- package/src/tests/tasks-workflow-run-filter.test.ts +146 -0
- package/src/tests/test-net.ts +31 -0
- package/src/tests/transcription.test.ts +8 -0
- package/src/tests/ui-logs-parser.test.ts +180 -0
- package/src/tests/used-by-route.test.ts +11 -0
- package/src/tests/workflow-cascade-cancel.test.ts +172 -0
- package/src/tests/workflow-engine-v2.test.ts +116 -1
- package/src/tests/workflow-http-v2.test.ts +131 -0
- package/src/tests/workflow-mcp-trigger-schema.test.ts +209 -0
- package/src/tests/workflow-run-finished-event.test.ts +263 -0
- package/src/tests/workflow-step-order.test.ts +92 -0
- package/src/tests/workflow-sub-workflow.test.ts +30 -0
- package/src/tests/workflow-swarm-script.test.ts +34 -0
- package/src/tools/get-tasks.ts +8 -0
- package/src/tools/kv/kv-read-auth.ts +4 -2
- package/src/tools/script-common.ts +1 -0
- package/src/tools/script-run.ts +7 -0
- package/src/tools/script-upsert.ts +7 -0
- package/src/tools/store-progress.ts +67 -1
- package/src/tools/task-action.ts +1 -1
- package/src/tools/workflows/get-workflow-run.ts +14 -4
- package/src/tools/workflows/trigger-workflow.ts +104 -10
- package/src/types.ts +36 -1
- package/src/utils/company-profile.ts +51 -1
- package/src/utils/credentials.ts +10 -4
- package/src/utils/internal-ai/complete-structured.ts +5 -0
- package/src/utils/internal-ai/credentials.ts +4 -3
- package/src/utils/provider-key-probes.ts +328 -0
- package/src/utils/transcription.ts +4 -1
- package/src/workflows/engine.ts +18 -16
- package/src/workflows/executors/sub-workflow.ts +8 -1
- package/src/workflows/executors/swarm-script.ts +5 -0
- package/src/workflows/foreach-driver.ts +5 -11
- package/src/workflows/node-timeout.ts +30 -0
- package/templates/ai-toolbox.manifest.json +2 -2
- package/templates/community/linear-delivery-loop/PLAYBOOK.md +323 -0
- package/templates/community/linear-delivery-loop/README.md +38 -0
- package/templates/community/linear-delivery-loop/config.example.json +31 -0
- package/templates/community/linear-delivery-loop/lead-prompt.md +34 -0
- package/templates/community/linear-delivery-loop/schedule.json +10 -0
- package/templates/community/linear-delivery-loop/scripts/linear-delivery-setup.ts +148 -0
- package/templates/community/linear-delivery-loop/scripts/linear-delivery-tick.ts +1781 -0
- package/templates/skills/researching/content.md +2 -0
- package/templates/skills/swarm-docs/config.json +14 -0
- package/templates/skills/swarm-docs/content.md +144 -0
- package/templates/skills/swarm-scripts/SKILL.md +1 -0
- package/templates/skills/swarm-scripts/content.md +1 -0
- package/dist/cli-7421jzsw.js +0 -84
- package/dist/cli-e45e4m6b.js +0 -413
- package/dist/cli-zw88zjba.js +0 -307
- package/dist/handlers-wy1dr6ja.js +0 -41
- package/dist/index-nmm79qgr.js +0 -43
- package/dist/lead-sawnyqxk.js +0 -79
- package/dist/render-v2-pjwxvnkw.js +0 -12
- package/dist/worker-v5e5rxj3.js +0 -79
|
@@ -150,6 +150,8 @@ import {
|
|
|
150
150
|
TelegramBotApiError,
|
|
151
151
|
callTelegramBotApi,
|
|
152
152
|
isTrustedTeamsServiceUrl,
|
|
153
|
+
getSessionLabels,
|
|
154
|
+
rememberSessionLabel,
|
|
153
155
|
isChatSdkStopping,
|
|
154
156
|
startChatSdk,
|
|
155
157
|
getChatInstance,
|
|
@@ -176,6 +178,7 @@ import {
|
|
|
176
178
|
extractAndVerifyCookie,
|
|
177
179
|
pageSessionSetCookies,
|
|
178
180
|
resolveHttpRequestAuth,
|
|
181
|
+
getDeploymentEnvValue,
|
|
179
182
|
loadGlobalConfigsIntoEnv,
|
|
180
183
|
reloadGlobalConfigsAndIntegrations,
|
|
181
184
|
scheduleIntegrationsReload,
|
|
@@ -227,6 +230,7 @@ import {
|
|
|
227
230
|
getTasksOutputSchema,
|
|
228
231
|
getTasksHandler,
|
|
229
232
|
reservedNamespaceError,
|
|
233
|
+
privateNamespaceError,
|
|
230
234
|
reservedRoomKeyError,
|
|
231
235
|
updateMcpServerChecked,
|
|
232
236
|
updateTouchesStdioExecution,
|
|
@@ -284,22 +288,31 @@ import {
|
|
|
284
288
|
emitBudgetRefusalSideEffects,
|
|
285
289
|
workflowModelErrors,
|
|
286
290
|
patchWorkflowDefinition,
|
|
291
|
+
idempotencyKeyHeader,
|
|
292
|
+
readIdempotencyKey,
|
|
293
|
+
replayAcceptedOperation,
|
|
287
294
|
resolveScriptsOnlyMode,
|
|
288
295
|
ALL_CAPABILITIES,
|
|
289
296
|
hasCapability,
|
|
290
297
|
getEnabledCapabilities,
|
|
291
298
|
createServer
|
|
292
|
-
} from "./cli-
|
|
299
|
+
} from "./cli-6a9qfa8b.js";
|
|
293
300
|
import {
|
|
294
301
|
chatThreadOfContextKey,
|
|
295
302
|
agentContextKey,
|
|
296
303
|
pageContextKey,
|
|
297
304
|
init_context_key,
|
|
305
|
+
sourceOfKey,
|
|
306
|
+
SOURCE_GROUPS_READ_ONLY,
|
|
307
|
+
sourceMoveError,
|
|
308
|
+
init_source_key,
|
|
298
309
|
init_catalog,
|
|
299
310
|
catalog_default,
|
|
300
311
|
COMPANY_TEAM_SIZES,
|
|
301
312
|
COMPANY_USE_CASES,
|
|
302
313
|
USER_FUNCTIONS,
|
|
314
|
+
reportedUseCase,
|
|
315
|
+
reportedUserFunction,
|
|
303
316
|
init_company_profile,
|
|
304
317
|
TELEMETRY_PROXY_ORIGIN,
|
|
305
318
|
normalizeOrgWebsite,
|
|
@@ -347,6 +360,7 @@ import {
|
|
|
347
360
|
resolveTriggerSurface,
|
|
348
361
|
emitTaskTelemetry,
|
|
349
362
|
init_telemetry_trigger,
|
|
363
|
+
CODEX_AUTH_FAILURE_BENCH_THRESHOLD,
|
|
350
364
|
CODEX_AUTH_WATCH_NAMESPACE,
|
|
351
365
|
codexAuthBenchMarkerKey,
|
|
352
366
|
init_codex_auth_failure,
|
|
@@ -410,6 +424,7 @@ import {
|
|
|
410
424
|
listPrefixRoots,
|
|
411
425
|
listSharedPrefixRoots,
|
|
412
426
|
init_session_moves,
|
|
427
|
+
getSessionGroupKey,
|
|
413
428
|
getSessionReadState,
|
|
414
429
|
getSessionTree,
|
|
415
430
|
triageSessionList,
|
|
@@ -442,10 +457,14 @@ import {
|
|
|
442
457
|
updateTaskProgress2,
|
|
443
458
|
IdempotencyKeyTakenError,
|
|
444
459
|
workflowRequestFingerprint,
|
|
445
|
-
findAcceptedWorkflowOperation,
|
|
446
460
|
assertWorkflowIdempotencyKeyUnused,
|
|
447
461
|
recordAcceptedWorkflowOperation,
|
|
448
462
|
init_workflow_idempotency,
|
|
463
|
+
getWorkflowRunSummary,
|
|
464
|
+
getWorkflowRunStepsSlimByRunId,
|
|
465
|
+
WORKFLOW_RUN_TREE_MAX_DEPTH,
|
|
466
|
+
WorkflowRunTreeError,
|
|
467
|
+
getWorkflowRunTree,
|
|
449
468
|
getWorkflowRunParent,
|
|
450
469
|
init_workflow_runs,
|
|
451
470
|
CHAT_SDK_ADAPTER_NAMES,
|
|
@@ -537,6 +556,9 @@ import {
|
|
|
537
556
|
init_steering,
|
|
538
557
|
refreshActiveSessionOnActivity2,
|
|
539
558
|
recordKeySeatMismatch2,
|
|
559
|
+
recordKeyValidation2,
|
|
560
|
+
retirePoolKeyStatus,
|
|
561
|
+
init_api_keys,
|
|
540
562
|
getScriptRunExecutionArgs2,
|
|
541
563
|
updateTaskVcs2,
|
|
542
564
|
upsertAssetKeyMapping2,
|
|
@@ -743,7 +765,7 @@ import {
|
|
|
743
765
|
countScriptRunJournalSteps2,
|
|
744
766
|
countScriptRunJournalAgentTaskSteps2,
|
|
745
767
|
init_db3
|
|
746
|
-
} from "./cli-
|
|
768
|
+
} from "./cli-48gxjmcz.js";
|
|
747
769
|
import {
|
|
748
770
|
PRIMARY_ROLE_NAMES2,
|
|
749
771
|
getUserGrant2,
|
|
@@ -754,26 +776,26 @@ import {
|
|
|
754
776
|
assertNotLastAdmin2,
|
|
755
777
|
setUserRoles2,
|
|
756
778
|
init_rbac_roles
|
|
757
|
-
} from "./cli-
|
|
758
|
-
import"./cli-
|
|
779
|
+
} from "./cli-8wmj18cz.js";
|
|
780
|
+
import"./cli-rd5m70gj.js";
|
|
759
781
|
import {
|
|
760
782
|
normalizeModelKey
|
|
761
|
-
} from "./cli-
|
|
783
|
+
} from "./cli-d20qvpr2.js";
|
|
762
784
|
import {
|
|
763
785
|
upsertModelCatalogOverlay,
|
|
764
786
|
deleteModelCatalogOverlay,
|
|
765
787
|
loadModelsCatalog,
|
|
766
788
|
requestModelCatalogRefresh2
|
|
767
|
-
} from "./cli-
|
|
789
|
+
} from "./cli-60sty27p.js";
|
|
768
790
|
import {
|
|
769
791
|
AMP_ESTIMATE_MODELS,
|
|
770
792
|
ampBillsCacheWrites,
|
|
771
793
|
resolveAmpModel
|
|
772
|
-
} from "./cli-
|
|
794
|
+
} from "./cli-8mbc9za9.js";
|
|
773
795
|
import {
|
|
774
796
|
workflowEventBus2,
|
|
775
797
|
init_event_bus
|
|
776
|
-
} from "./cli-
|
|
798
|
+
} from "./cli-kt907da6.js";
|
|
777
799
|
import {
|
|
778
800
|
automationIntegrationFixUrl,
|
|
779
801
|
preflightAutomation,
|
|
@@ -809,7 +831,7 @@ import {
|
|
|
809
831
|
generateEdges,
|
|
810
832
|
definitionNodeIds,
|
|
811
833
|
validateDefinition
|
|
812
|
-
} from "./cli-
|
|
834
|
+
} from "./cli-j0ppywdr.js";
|
|
813
835
|
import {
|
|
814
836
|
require_dist2,
|
|
815
837
|
isInvalidClientError,
|
|
@@ -869,8 +891,10 @@ import {
|
|
|
869
891
|
buildSandboxedCommand,
|
|
870
892
|
sandboxSpawnEnv,
|
|
871
893
|
readStreamCapped,
|
|
894
|
+
isExecutorAllowedByDeployment,
|
|
872
895
|
MIN_SCRIPT_WALL_CLOCK_MS,
|
|
873
896
|
MAX_SCRIPT_WALL_CLOCK_MS,
|
|
897
|
+
HOST_VALIDATED_ARGS,
|
|
874
898
|
require_typescript2,
|
|
875
899
|
checkImportAllowlist,
|
|
876
900
|
runScriptWithRunCredential,
|
|
@@ -889,14 +913,14 @@ import {
|
|
|
889
913
|
typecheckWithAmbient,
|
|
890
914
|
typecheckScript,
|
|
891
915
|
parseSkillContent
|
|
892
|
-
} from "./cli-
|
|
916
|
+
} from "./cli-j9bpmykh.js";
|
|
893
917
|
import {
|
|
894
918
|
buildAuthorizationUrl,
|
|
895
919
|
exchangeAuthorizationCode,
|
|
896
920
|
oauthAppRowToProviderConfig,
|
|
897
921
|
forceRefreshAuthorizationOrThrow,
|
|
898
922
|
forceRefreshTokenOrThrow
|
|
899
|
-
} from "./cli-
|
|
923
|
+
} from "./cli-aypd09nf.js";
|
|
900
924
|
import {
|
|
901
925
|
signalProcessGroup,
|
|
902
926
|
detachedProcessGroup,
|
|
@@ -924,27 +948,31 @@ import {
|
|
|
924
948
|
getTaskCitationsForTasks,
|
|
925
949
|
initialize,
|
|
926
950
|
ensure,
|
|
951
|
+
callSlackWithRetry2,
|
|
952
|
+
slackErrorCode2,
|
|
927
953
|
getSlackApp2,
|
|
928
954
|
startSlackApp2,
|
|
929
955
|
stopSlackApp2
|
|
930
|
-
} from "./cli-
|
|
931
|
-
import"./cli-
|
|
932
|
-
import"./cli-
|
|
956
|
+
} from "./cli-m30k9777.js";
|
|
957
|
+
import"./cli-s09j9vp5.js";
|
|
958
|
+
import"./cli-1m9x8dr5.js";
|
|
933
959
|
import {
|
|
934
960
|
_fetchHolder,
|
|
935
961
|
CLIENT_ID,
|
|
962
|
+
decodeJwt,
|
|
936
963
|
exchangeAuthorizationCode2,
|
|
937
964
|
getAccountId,
|
|
965
|
+
extractChatgptPlanType,
|
|
938
966
|
deriveCodexKeySuffix,
|
|
939
967
|
MAX_CODEX_OAUTH_SLOT,
|
|
940
968
|
codexOAuthKeyForSlot,
|
|
941
969
|
loadAllCodexOAuthSlots,
|
|
942
970
|
getValidCodexOAuth
|
|
943
|
-
} from "./cli-
|
|
971
|
+
} from "./cli-0z1xjzwa.js";
|
|
944
972
|
import {
|
|
945
973
|
retryFailedRun2,
|
|
946
974
|
cancelWorkflowRun2
|
|
947
|
-
} from "./cli-
|
|
975
|
+
} from "./cli-twctnkng.js";
|
|
948
976
|
import {
|
|
949
977
|
duplicateGuardedQueryKey,
|
|
950
978
|
warnIfCorsAllowsAnyOrigin,
|
|
@@ -989,7 +1017,7 @@ import {
|
|
|
989
1017
|
bodyListTask,
|
|
990
1018
|
describeRequestRoute,
|
|
991
1019
|
route
|
|
992
|
-
} from "./cli-
|
|
1020
|
+
} from "./cli-wqr7cea4.js";
|
|
993
1021
|
import {
|
|
994
1022
|
FilesError,
|
|
995
1023
|
normalizeFilesError,
|
|
@@ -1017,13 +1045,13 @@ import {
|
|
|
1017
1045
|
resolvePoolDelivery2,
|
|
1018
1046
|
createPoolAgent2,
|
|
1019
1047
|
init_db
|
|
1020
|
-
} from "./cli-
|
|
1048
|
+
} from "./cli-6srv653c.js";
|
|
1021
1049
|
import {
|
|
1022
1050
|
RATING_MODEL_MAX_LENGTH,
|
|
1023
1051
|
REFERENCES_SOURCE_MAX_LENGTH,
|
|
1024
1052
|
sanitizeReferencesSource
|
|
1025
1053
|
} from "./cli-3h26v7yj.js";
|
|
1026
|
-
import"./cli-
|
|
1054
|
+
import"./cli-737pyqxr.js";
|
|
1027
1055
|
import {
|
|
1028
1056
|
startPoolRouting,
|
|
1029
1057
|
stopPoolRouting,
|
|
@@ -1033,8 +1061,8 @@ import {
|
|
|
1033
1061
|
checkHeartbeatChecklist2,
|
|
1034
1062
|
runHeartbeatSweep2,
|
|
1035
1063
|
stopHeartbeat2
|
|
1036
|
-
} from "./cli-
|
|
1037
|
-
import"./cli-
|
|
1064
|
+
} from "./cli-he9gbdx0.js";
|
|
1065
|
+
import"./cli-qj442fws.js";
|
|
1038
1066
|
import {
|
|
1039
1067
|
import_websocket,
|
|
1040
1068
|
import_websocket_server
|
|
@@ -1043,18 +1071,18 @@ import {
|
|
|
1043
1071
|
runtimeSupervisorStatus,
|
|
1044
1072
|
startRuntimeSupervisor,
|
|
1045
1073
|
stopRuntimeSupervisor
|
|
1046
|
-
} from "./cli-
|
|
1074
|
+
} from "./cli-9gsm2rzp.js";
|
|
1047
1075
|
import"./cli-ns59dc6r.js";
|
|
1048
1076
|
import {
|
|
1049
1077
|
ACP_TARGET_IDS
|
|
1050
|
-
} from "./cli-
|
|
1078
|
+
} from "./cli-yvy48785.js";
|
|
1051
1079
|
import {
|
|
1052
1080
|
reasoningCapability,
|
|
1053
1081
|
supportedReasoningLevels
|
|
1054
|
-
} from "./cli-
|
|
1082
|
+
} from "./cli-c081bj3b.js";
|
|
1055
1083
|
import {
|
|
1056
1084
|
MAX_RATE_LIMIT_RESET_MS
|
|
1057
|
-
} from "./cli-
|
|
1085
|
+
} from "./cli-vz78s5wm.js";
|
|
1058
1086
|
import {
|
|
1059
1087
|
isLeadChannelMonitoringEnabled,
|
|
1060
1088
|
ORG_IDENTITY_KEYS,
|
|
@@ -1062,12 +1090,13 @@ import {
|
|
|
1062
1090
|
SIMILARITY_THRESHOLD,
|
|
1063
1091
|
memoryRelevance,
|
|
1064
1092
|
isUnknownModelError,
|
|
1093
|
+
checkProviderPoolKey,
|
|
1065
1094
|
writeSkillsToFilesystem
|
|
1066
|
-
} from "./cli-
|
|
1095
|
+
} from "./cli-6mgdba42.js";
|
|
1067
1096
|
import {
|
|
1068
1097
|
inviteEmailToSharedOrg,
|
|
1069
1098
|
ensureAgentFsCredentialsForAgent
|
|
1070
|
-
} from "./cli-
|
|
1099
|
+
} from "./cli-b3yzyc57.js";
|
|
1071
1100
|
import {
|
|
1072
1101
|
Anthropic
|
|
1073
1102
|
} from "./cli-rr7zx19j.js";
|
|
@@ -1107,7 +1136,7 @@ import {
|
|
|
1107
1136
|
revokeAgentTokens,
|
|
1108
1137
|
fingerprintApiKey,
|
|
1109
1138
|
init_users
|
|
1110
|
-
} from "./cli-
|
|
1139
|
+
} from "./cli-a89zdqz9.js";
|
|
1111
1140
|
import"./cli-v41kn3cd.js";
|
|
1112
1141
|
import"./cli-wgtk7xxr.js";
|
|
1113
1142
|
import"./cli-1f0gp9vz.js";
|
|
@@ -1235,10 +1264,12 @@ import {
|
|
|
1235
1264
|
ScriptRunListItemSchema,
|
|
1236
1265
|
ScriptRunJournalEntrySchema,
|
|
1237
1266
|
WorkflowRunStepSchema,
|
|
1267
|
+
WorkflowRunStepSlimSchema,
|
|
1238
1268
|
PromptTemplateSchema,
|
|
1239
1269
|
PromptTemplateHistorySchema,
|
|
1240
1270
|
ScriptScopeSchema,
|
|
1241
1271
|
ScriptFsModeSchema,
|
|
1272
|
+
ScriptExecutorNameSchema,
|
|
1242
1273
|
ScriptRecordSchema,
|
|
1243
1274
|
ScriptVersionRecordSchema,
|
|
1244
1275
|
ExtensionManifestSchema,
|
|
@@ -1271,31 +1302,35 @@ import {
|
|
|
1271
1302
|
KvKeySchema,
|
|
1272
1303
|
KvEntrySchema,
|
|
1273
1304
|
init_types
|
|
1274
|
-
} from "./cli-
|
|
1305
|
+
} from "./cli-9pshx6rd.js";
|
|
1275
1306
|
import {
|
|
1276
1307
|
IDENTITY_FIELD_BUDGETS,
|
|
1277
1308
|
IdentityFieldBudgetError,
|
|
1278
1309
|
init_identity_field_budget
|
|
1279
|
-
} from "./cli-
|
|
1280
|
-
import {
|
|
1281
|
-
getSlackConfiguration,
|
|
1282
|
-
init_config
|
|
1283
|
-
} from "./cli-qeaq3j6t.js";
|
|
1310
|
+
} from "./cli-x37r7qwf.js";
|
|
1284
1311
|
import {
|
|
1285
1312
|
isSteeringEnabled2,
|
|
1286
1313
|
init_steering_enabled
|
|
1287
1314
|
} from "./cli-4sydckyj.js";
|
|
1288
1315
|
import {
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
} from "./cli-7421jzsw.js";
|
|
1316
|
+
getSlackConfiguration,
|
|
1317
|
+
init_config
|
|
1318
|
+
} from "./cli-qeaq3j6t.js";
|
|
1293
1319
|
import {
|
|
1294
1320
|
SUBSCRIPTION_PLANS_CHECKED_AT,
|
|
1295
1321
|
SUBSCRIPTION_PLANS,
|
|
1296
1322
|
isSubscriptionPlanId,
|
|
1297
1323
|
init_subscription_plans
|
|
1298
1324
|
} from "./cli-7akn6ze9.js";
|
|
1325
|
+
import {
|
|
1326
|
+
MODEL_SCOPED_WINDOWS,
|
|
1327
|
+
activeModelBlocks,
|
|
1328
|
+
init_model_rate_limit_windows,
|
|
1329
|
+
CREDENTIAL_POOL_VARS,
|
|
1330
|
+
splitCredentialPool,
|
|
1331
|
+
selectCredential,
|
|
1332
|
+
init_credentials
|
|
1333
|
+
} from "./cli-gt4h8cxw.js";
|
|
1299
1334
|
import {
|
|
1300
1335
|
getOpenRouterAttributionHeaders,
|
|
1301
1336
|
init_openrouter_base_url
|
|
@@ -1309,7 +1344,7 @@ import {
|
|
|
1309
1344
|
resolveTemplate,
|
|
1310
1345
|
init_resolver,
|
|
1311
1346
|
init_session_templates
|
|
1312
|
-
} from "./cli-
|
|
1347
|
+
} from "./cli-f1e0ptjj.js";
|
|
1313
1348
|
import {
|
|
1314
1349
|
init_zod
|
|
1315
1350
|
} from "./cli-4chz1hye.js";
|
|
@@ -1344,7 +1379,7 @@ import {
|
|
|
1344
1379
|
import {
|
|
1345
1380
|
init_package,
|
|
1346
1381
|
package_default
|
|
1347
|
-
} from "./cli-
|
|
1382
|
+
} from "./cli-ptfq202x.js";
|
|
1348
1383
|
import {
|
|
1349
1384
|
realtimeBus,
|
|
1350
1385
|
init_bus
|
|
@@ -1372,12 +1407,15 @@ import {
|
|
|
1372
1407
|
findSecretsIn,
|
|
1373
1408
|
scrubObject,
|
|
1374
1409
|
registerVolatileSecret,
|
|
1410
|
+
registerEnvSecrets,
|
|
1375
1411
|
init_secret_scrubber
|
|
1376
|
-
} from "./cli-
|
|
1412
|
+
} from "./cli-708wdy32.js";
|
|
1377
1413
|
import {
|
|
1378
1414
|
isAlias,
|
|
1415
|
+
baseUrlEnvVar,
|
|
1416
|
+
providerForKeyVar,
|
|
1379
1417
|
init_src2
|
|
1380
|
-
} from "./cli-
|
|
1418
|
+
} from "./cli-gxee0bqa.js";
|
|
1381
1419
|
import {
|
|
1382
1420
|
__toESM
|
|
1383
1421
|
} from "./cli-242037k3.js";
|
|
@@ -1435,6 +1473,7 @@ init_db3();
|
|
|
1435
1473
|
|
|
1436
1474
|
// src/be/db-retention.ts
|
|
1437
1475
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
1476
|
+
init_types();
|
|
1438
1477
|
init_env_flag();
|
|
1439
1478
|
init_secret_scrubber();
|
|
1440
1479
|
init_db3();
|
|
@@ -1479,6 +1518,19 @@ var DB_RETENTION_TABLES = [
|
|
|
1479
1518
|
metricsKey: "contextVersions",
|
|
1480
1519
|
initialBatchSize: 50,
|
|
1481
1520
|
maxBatchSize: 100
|
|
1521
|
+
},
|
|
1522
|
+
{
|
|
1523
|
+
table: "script_runs",
|
|
1524
|
+
policy: "age",
|
|
1525
|
+
timeColumn: "startedAt",
|
|
1526
|
+
cutoffFormat: "sqliteDatetime",
|
|
1527
|
+
statusColumn: "status",
|
|
1528
|
+
terminalStatuses: TERMINAL_SCRIPT_RUN_STATUSES,
|
|
1529
|
+
keepWhenSet: "idempotencyKey",
|
|
1530
|
+
envKey: "SCRIPT_RUNS_RETENTION_DAYS",
|
|
1531
|
+
metricsKey: "scriptRuns",
|
|
1532
|
+
initialBatchSize: 100,
|
|
1533
|
+
maxBatchSize: 500
|
|
1482
1534
|
}
|
|
1483
1535
|
];
|
|
1484
1536
|
|
|
@@ -1612,13 +1664,26 @@ function sweepStatements(table, value, now) {
|
|
|
1612
1664
|
params: [value]
|
|
1613
1665
|
};
|
|
1614
1666
|
}
|
|
1615
|
-
const
|
|
1667
|
+
const iso = new Date(now.getTime() - value * DAY_MS).toISOString();
|
|
1668
|
+
const cutoff = "cutoffFormat" in table ? `${iso.slice(0, 10)} ${iso.slice(11, 19)}` : iso;
|
|
1669
|
+
const conditions = [];
|
|
1670
|
+
const params = [];
|
|
1671
|
+
if ("terminalStatuses" in table) {
|
|
1672
|
+
conditions.push(`${table.statusColumn} IN (${table.terminalStatuses.map(() => "?").join(", ")})`);
|
|
1673
|
+
params.push(...table.terminalStatuses);
|
|
1674
|
+
}
|
|
1675
|
+
conditions.push(`${table.timeColumn} < ?`);
|
|
1676
|
+
params.push(cutoff);
|
|
1677
|
+
if ("keepWhenSet" in table) {
|
|
1678
|
+
conditions.push(`rowid NOT IN (SELECT rowid FROM ${table.table} WHERE ${table.keepWhenSet} IS NOT NULL)`);
|
|
1679
|
+
}
|
|
1680
|
+
const where = conditions.join(" AND ");
|
|
1616
1681
|
return {
|
|
1617
|
-
backlogSql: `SELECT COUNT(*) AS n FROM ${table.table} WHERE ${
|
|
1682
|
+
backlogSql: `SELECT COUNT(*) AS n FROM ${table.table} WHERE ${where}`,
|
|
1618
1683
|
deleteSql: `DELETE FROM ${table.table} WHERE rowid IN (
|
|
1619
|
-
SELECT rowid FROM ${table.table} WHERE ${
|
|
1684
|
+
SELECT rowid FROM ${table.table} WHERE ${where} ORDER BY ${table.timeColumn} LIMIT ?
|
|
1620
1685
|
)`,
|
|
1621
|
-
params
|
|
1686
|
+
params
|
|
1622
1687
|
};
|
|
1623
1688
|
}
|
|
1624
1689
|
function dryRunEnabled(env = process.env) {
|
|
@@ -5455,6 +5520,33 @@ var reportRateLimit = route({
|
|
|
5455
5520
|
},
|
|
5456
5521
|
auth: { apiKey: true }
|
|
5457
5522
|
});
|
|
5523
|
+
var reportValidation = route({
|
|
5524
|
+
method: "post",
|
|
5525
|
+
path: "/api/keys/report-validation",
|
|
5526
|
+
pattern: ["api", "keys", "report-validation"],
|
|
5527
|
+
summary: "Record live validation results for a credential pool",
|
|
5528
|
+
tags: ["API Keys"],
|
|
5529
|
+
body: object2({
|
|
5530
|
+
keyType: string2(),
|
|
5531
|
+
keys: array2(object2({
|
|
5532
|
+
keyIndex: number2().int().min(0),
|
|
5533
|
+
keySuffix: string2().min(1).max(10),
|
|
5534
|
+
ok: boolean(),
|
|
5535
|
+
httpStatus: number2().int().optional()
|
|
5536
|
+
})).min(1).max(100),
|
|
5537
|
+
scope: string2().optional(),
|
|
5538
|
+
scopeId: string2().optional()
|
|
5539
|
+
}),
|
|
5540
|
+
responses: {
|
|
5541
|
+
200: { description: "Validation recorded", schema: successMessageSchema },
|
|
5542
|
+
400: { description: "Validation error" },
|
|
5543
|
+
401: { description: "Unauthorized" }
|
|
5544
|
+
},
|
|
5545
|
+
auth: { apiKey: true },
|
|
5546
|
+
rbac: {
|
|
5547
|
+
ungated: "worker credential telemetry, same posture as POST /api/keys/report-rate-limit"
|
|
5548
|
+
}
|
|
5549
|
+
});
|
|
5458
5550
|
var reportAuthFailure = route({
|
|
5459
5551
|
method: "post",
|
|
5460
5552
|
path: "/api/keys/report-auth-failure",
|
|
@@ -5564,7 +5656,11 @@ var getAvailable = route({
|
|
|
5564
5656
|
totalKeys: exports_coerce.number().int().min(1),
|
|
5565
5657
|
scope: string2().optional(),
|
|
5566
5658
|
scopeId: string2().optional(),
|
|
5567
|
-
model: _enum2(["fable", "opus", "sonnet", "haiku"]).optional()
|
|
5659
|
+
model: _enum2(["fable", "opus", "sonnet", "haiku"]).optional(),
|
|
5660
|
+
keySuffixes: string2().transform((value) => value.split(",")).optional()
|
|
5661
|
+
}).refine((query) => !query.keySuffixes || query.keySuffixes.length === query.totalKeys, {
|
|
5662
|
+
message: "keySuffixes must list exactly totalKeys suffixes",
|
|
5663
|
+
path: ["keySuffixes"]
|
|
5568
5664
|
}),
|
|
5569
5665
|
responses: {
|
|
5570
5666
|
200: {
|
|
@@ -5572,6 +5668,7 @@ var getAvailable = route({
|
|
|
5572
5668
|
schema: object2({
|
|
5573
5669
|
success: literal2(true),
|
|
5574
5670
|
availableIndices: array2(number2().int()),
|
|
5671
|
+
rejectedIndices: array2(number2().int()).optional(),
|
|
5575
5672
|
totalKeys: number2().int(),
|
|
5576
5673
|
modelBlockedIndices: array2(number2().int()).optional(),
|
|
5577
5674
|
earliestModelResetAt: string2().nullable().optional(),
|
|
@@ -5606,6 +5703,8 @@ var ApiKeyStatusSchema = object2({
|
|
|
5606
5703
|
lastSeatMismatchModel: string2().nullable(),
|
|
5607
5704
|
consecutiveAuthFailures: number2().int(),
|
|
5608
5705
|
lastAuthFailureAt: string2().nullable(),
|
|
5706
|
+
lastValidationError: string2().nullable(),
|
|
5707
|
+
lastValidationFailedAt: string2().nullable(),
|
|
5609
5708
|
modelLimits: array2(object2({
|
|
5610
5709
|
model: string2(),
|
|
5611
5710
|
window: string2(),
|
|
@@ -5828,6 +5927,19 @@ async function handleApiKeys(req, res, pathSegments, queryParams) {
|
|
|
5828
5927
|
}
|
|
5829
5928
|
return true;
|
|
5830
5929
|
}
|
|
5930
|
+
if (reportValidation.match(req.method, pathSegments)) {
|
|
5931
|
+
const parsed = await reportValidation.parse(req, res, pathSegments, queryParams);
|
|
5932
|
+
if (!parsed)
|
|
5933
|
+
return true;
|
|
5934
|
+
const { keyType, keys, scope, scopeId } = parsed.body;
|
|
5935
|
+
try {
|
|
5936
|
+
await recordKeyValidation2(keyType, keys, scope, scopeId ?? null);
|
|
5937
|
+
reportValidation.respond(res, 200, { success: true, message: "Key validation recorded" });
|
|
5938
|
+
} catch (err) {
|
|
5939
|
+
jsonError(res, err instanceof Error ? err.message : "Failed to record key validation", 500);
|
|
5940
|
+
}
|
|
5941
|
+
return true;
|
|
5942
|
+
}
|
|
5831
5943
|
if (reportAuthFailure.match(req.method, pathSegments)) {
|
|
5832
5944
|
const parsed = await reportAuthFailure.parse(req, res, pathSegments, queryParams);
|
|
5833
5945
|
if (!parsed)
|
|
@@ -5883,12 +5995,13 @@ async function handleApiKeys(req, res, pathSegments, queryParams) {
|
|
|
5883
5995
|
const parsed = await getAvailable.parse(req, res, pathSegments, queryParams);
|
|
5884
5996
|
if (!parsed)
|
|
5885
5997
|
return true;
|
|
5886
|
-
const { keyType, totalKeys, scope, scopeId, model } = parsed.query;
|
|
5998
|
+
const { keyType, totalKeys, scope, scopeId, model, keySuffixes } = parsed.query;
|
|
5887
5999
|
try {
|
|
5888
|
-
const result = await getAvailableKeyIndices2(keyType, totalKeys, scope, scopeId ?? null, model);
|
|
6000
|
+
const result = await getAvailableKeyIndices2(keyType, totalKeys, scope, scopeId ?? null, model, keySuffixes);
|
|
5889
6001
|
getAvailable.respond(res, 200, {
|
|
5890
6002
|
success: true,
|
|
5891
6003
|
availableIndices: result.availableIndices,
|
|
6004
|
+
rejectedIndices: result.rejectedIndices,
|
|
5892
6005
|
totalKeys,
|
|
5893
6006
|
authFailureFence: result.authFailureFence,
|
|
5894
6007
|
...model !== undefined ? {
|
|
@@ -6160,7 +6273,11 @@ async function handleUsedBy(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
6160
6273
|
org_website: orgWebsite,
|
|
6161
6274
|
...orgDomain ? { org_domain: orgDomain } : {},
|
|
6162
6275
|
granted,
|
|
6163
|
-
...granted ? {
|
|
6276
|
+
...granted ? {
|
|
6277
|
+
contact_email: contactEmail,
|
|
6278
|
+
contact_function: reportedUserFunction(contactFunction),
|
|
6279
|
+
quote
|
|
6280
|
+
} : {},
|
|
6164
6281
|
changed_at: changedAt
|
|
6165
6282
|
}),
|
|
6166
6283
|
signal: AbortSignal.timeout(TIMEOUT_MS)
|
|
@@ -7568,6 +7685,8 @@ async function approvalQuorumMet(approvers, votes) {
|
|
|
7568
7685
|
|
|
7569
7686
|
// src/http/assets.ts
|
|
7570
7687
|
init_zod();
|
|
7688
|
+
init_key();
|
|
7689
|
+
init_source_key();
|
|
7571
7690
|
init_asset_key_audit();
|
|
7572
7691
|
init_db3();
|
|
7573
7692
|
init_db2();
|
|
@@ -7827,6 +7946,16 @@ async function handleAssets(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
7827
7946
|
jsonError(res, await canReadSession2(req, myAgentId, task.id) ? "You can view this session but not move it." : SESSION_READ_DENIED2, 403);
|
|
7828
7947
|
return true;
|
|
7829
7948
|
}
|
|
7949
|
+
const destination = normalizeAssetKey(parsed.body.key);
|
|
7950
|
+
if (sourceOfKey(destination)) {
|
|
7951
|
+
const rootId = task.parentTaskId ? (await getSessionRoot(task.id))?.id : task.id;
|
|
7952
|
+
const root = rootId === task.id ? task : rootId ? await getTaskById2(rootId) : null;
|
|
7953
|
+
const sourceError = sourceMoveError(destination, root ?? { id: task.id });
|
|
7954
|
+
if (sourceError) {
|
|
7955
|
+
jsonError(res, sourceError, 400);
|
|
7956
|
+
return true;
|
|
7957
|
+
}
|
|
7958
|
+
}
|
|
7830
7959
|
const tasks = parsed.body.cascade ? await getRootTaskChain2(task.id) : [task];
|
|
7831
7960
|
for (const target of tasks) {
|
|
7832
7961
|
if (!await canMutateTaskNamespace(target, myAgentId, req)) {
|
|
@@ -8052,6 +8181,165 @@ async function handleBudgets(req, res, pathSegments, queryParams, _myAgentId) {
|
|
|
8052
8181
|
return false;
|
|
8053
8182
|
}
|
|
8054
8183
|
|
|
8184
|
+
// src/http/codex-oauth-accounts.ts
|
|
8185
|
+
init_zod();
|
|
8186
|
+
init_crypto();
|
|
8187
|
+
init_db3();
|
|
8188
|
+
init_api_keys();
|
|
8189
|
+
init_codex_auth_failure();
|
|
8190
|
+
var CodexAccountSchema = object2({
|
|
8191
|
+
slot: number2().int().min(0),
|
|
8192
|
+
configKey: string2(),
|
|
8193
|
+
legacy: boolean(),
|
|
8194
|
+
suffix: string2().nullable(),
|
|
8195
|
+
plan: string2().nullable(),
|
|
8196
|
+
email: string2().nullable(),
|
|
8197
|
+
status: _enum2(["ok", "needs_login", "unchecked"])
|
|
8198
|
+
});
|
|
8199
|
+
var CodexAccountsResponseSchema = object2({ accounts: array2(CodexAccountSchema) });
|
|
8200
|
+
var listAccounts = route({
|
|
8201
|
+
method: "get",
|
|
8202
|
+
path: "/api/codex-oauth/accounts",
|
|
8203
|
+
pattern: ["api", "codex-oauth", "accounts"],
|
|
8204
|
+
summary: "List stored Codex ChatGPT accounts",
|
|
8205
|
+
tags: ["Codex OAuth"],
|
|
8206
|
+
responses: {
|
|
8207
|
+
200: { description: "Stored account metadata", schema: CodexAccountsResponseSchema },
|
|
8208
|
+
403: { description: "Caller cannot read all secrets" }
|
|
8209
|
+
}
|
|
8210
|
+
});
|
|
8211
|
+
var deleteAccount = route({
|
|
8212
|
+
method: "delete",
|
|
8213
|
+
path: "/api/codex-oauth/accounts/{slot}",
|
|
8214
|
+
pattern: ["api", "codex-oauth", "accounts", null],
|
|
8215
|
+
summary: "Remove a stored Codex ChatGPT account",
|
|
8216
|
+
tags: ["Codex OAuth"],
|
|
8217
|
+
rbac: { permission: "config.delete.any" },
|
|
8218
|
+
params: object2({ slot: exports_coerce.number().int().min(0).max(MAX_CODEX_OAUTH_SLOT) }),
|
|
8219
|
+
responses: {
|
|
8220
|
+
200: { description: "Remaining accounts", schema: CodexAccountsResponseSchema },
|
|
8221
|
+
403: { description: "Config administration and permission to read all secrets required" },
|
|
8222
|
+
404: { description: "Account slot does not exist" }
|
|
8223
|
+
}
|
|
8224
|
+
});
|
|
8225
|
+
async function accountRows() {
|
|
8226
|
+
const rows = await getDbClient2().query("SELECT key, value, encrypted FROM swarm_config WHERE scope = 'global' AND (key = 'codex_oauth' OR key GLOB 'codex_oauth_[0-9]*')");
|
|
8227
|
+
const hasSlotZero = rows.some((row) => row.key === "codex_oauth_0");
|
|
8228
|
+
return rows.flatMap((row) => {
|
|
8229
|
+
if (row.key === "codex_oauth") {
|
|
8230
|
+
return hasSlotZero ? [] : [{ ...row, slot: 0, legacy: true }];
|
|
8231
|
+
}
|
|
8232
|
+
const match = /^codex_oauth_(0|[1-9]\d*)$/.exec(row.key);
|
|
8233
|
+
if (!match)
|
|
8234
|
+
return [];
|
|
8235
|
+
const slot = Number(match[1]);
|
|
8236
|
+
return slot <= MAX_CODEX_OAUTH_SLOT ? [{ ...row, slot, legacy: false }] : [];
|
|
8237
|
+
}).sort((a, b) => a.slot - b.slot);
|
|
8238
|
+
}
|
|
8239
|
+
var AccountCredentialsSchema = object2({
|
|
8240
|
+
access: string2().min(1),
|
|
8241
|
+
refresh: string2().min(1),
|
|
8242
|
+
expires: number2().finite(),
|
|
8243
|
+
accountId: string2().min(1)
|
|
8244
|
+
});
|
|
8245
|
+
function readCredentials(row) {
|
|
8246
|
+
try {
|
|
8247
|
+
const value = row.encrypted ? decryptSecret(row.value, getEncryptionKey()) : row.value;
|
|
8248
|
+
return AccountCredentialsSchema.parse(JSON.parse(value));
|
|
8249
|
+
} catch {
|
|
8250
|
+
return null;
|
|
8251
|
+
}
|
|
8252
|
+
}
|
|
8253
|
+
function accountSuffix(row) {
|
|
8254
|
+
const credentials = readCredentials(row);
|
|
8255
|
+
return credentials ? deriveCodexKeySuffix(credentials.access, credentials.accountId) : null;
|
|
8256
|
+
}
|
|
8257
|
+
async function accountsResponse() {
|
|
8258
|
+
const rows = await accountRows();
|
|
8259
|
+
const statuses = await getKeyStatuses2("CODEX_OAUTH", "global", null);
|
|
8260
|
+
const accounts = [];
|
|
8261
|
+
for (const row of rows) {
|
|
8262
|
+
const account = {
|
|
8263
|
+
slot: row.slot,
|
|
8264
|
+
configKey: row.key,
|
|
8265
|
+
legacy: row.legacy,
|
|
8266
|
+
suffix: null,
|
|
8267
|
+
plan: null,
|
|
8268
|
+
email: null,
|
|
8269
|
+
status: "needs_login"
|
|
8270
|
+
};
|
|
8271
|
+
const credentials = readCredentials(row);
|
|
8272
|
+
if (!credentials) {
|
|
8273
|
+
accounts.push(account);
|
|
8274
|
+
continue;
|
|
8275
|
+
}
|
|
8276
|
+
account.suffix = deriveCodexKeySuffix(credentials.access, credentials.accountId);
|
|
8277
|
+
account.plan = extractChatgptPlanType(credentials.access);
|
|
8278
|
+
const profile = decodeJwt(credentials.access)?.["https://api.openai.com/profile"];
|
|
8279
|
+
if (profile && typeof profile === "object" && "email" in profile) {
|
|
8280
|
+
account.email = typeof profile.email === "string" && profile.email ? profile.email : null;
|
|
8281
|
+
}
|
|
8282
|
+
const status = statuses.find((entry) => entry.keySuffix === account.suffix);
|
|
8283
|
+
const marker = await getKv2(CODEX_AUTH_WATCH_NAMESPACE, codexAuthBenchMarkerKey(account.suffix));
|
|
8284
|
+
const statusBenched = status && status.consecutiveAuthFailures >= CODEX_AUTH_FAILURE_BENCH_THRESHOLD && status.status === "rate_limited";
|
|
8285
|
+
account.status = marker || statusBenched ? "needs_login" : status ? "ok" : "unchecked";
|
|
8286
|
+
accounts.push(account);
|
|
8287
|
+
}
|
|
8288
|
+
return { accounts };
|
|
8289
|
+
}
|
|
8290
|
+
async function ensureSecretRead(req, res) {
|
|
8291
|
+
if (await requestSecretReadScope(req) === "all")
|
|
8292
|
+
return true;
|
|
8293
|
+
jsonError(res, "Reading Codex accounts requires access to all secrets", 403);
|
|
8294
|
+
return false;
|
|
8295
|
+
}
|
|
8296
|
+
async function handleCodexOAuthAccounts(req, res, pathSegments, queryParams) {
|
|
8297
|
+
if (listAccounts.match(req.method, pathSegments)) {
|
|
8298
|
+
const parsed = await listAccounts.parse(req, res, pathSegments, queryParams);
|
|
8299
|
+
if (!parsed)
|
|
8300
|
+
return true;
|
|
8301
|
+
if (!await ensureSecretRead(req, res))
|
|
8302
|
+
return true;
|
|
8303
|
+
listAccounts.respond(res, 200, await accountsResponse());
|
|
8304
|
+
return true;
|
|
8305
|
+
}
|
|
8306
|
+
if (deleteAccount.match(req.method, pathSegments)) {
|
|
8307
|
+
const parsed = await deleteAccount.parse(req, res, pathSegments, queryParams);
|
|
8308
|
+
if (!parsed)
|
|
8309
|
+
return true;
|
|
8310
|
+
if (!await ensureConfigAdmin(req, res, "config.delete.any"))
|
|
8311
|
+
return true;
|
|
8312
|
+
if (!await ensureSecretRead(req, res))
|
|
8313
|
+
return true;
|
|
8314
|
+
const deletedKey = await getDbClient2().transaction(async () => {
|
|
8315
|
+
const rows = await accountRows();
|
|
8316
|
+
const account = rows.find((row) => row.slot === parsed.params.slot);
|
|
8317
|
+
if (!account || !await deleteSwarmConfigByKey2("global", null, account.key))
|
|
8318
|
+
return null;
|
|
8319
|
+
const suffix = accountSuffix(account);
|
|
8320
|
+
if (suffix) {
|
|
8321
|
+
const remaining = rows.flatMap((row) => {
|
|
8322
|
+
const keySuffix = row === account ? null : accountSuffix(row);
|
|
8323
|
+
return keySuffix ? [{ keySuffix, keyIndex: row.slot }] : [];
|
|
8324
|
+
});
|
|
8325
|
+
await retirePoolKeyStatus("CODEX_OAUTH", suffix, remaining);
|
|
8326
|
+
if (!remaining.some((row) => row.keySuffix === suffix)) {
|
|
8327
|
+
await deleteKv2(CODEX_AUTH_WATCH_NAMESPACE, codexAuthBenchMarkerKey(suffix));
|
|
8328
|
+
}
|
|
8329
|
+
}
|
|
8330
|
+
return account.key;
|
|
8331
|
+
});
|
|
8332
|
+
if (deletedKey === null) {
|
|
8333
|
+
jsonError(res, "Codex account slot does not exist", 404);
|
|
8334
|
+
return true;
|
|
8335
|
+
}
|
|
8336
|
+
await runConfigWriteSideEffects("global", deletedKey, "");
|
|
8337
|
+
deleteAccount.respond(res, 200, await accountsResponse());
|
|
8338
|
+
return true;
|
|
8339
|
+
}
|
|
8340
|
+
return false;
|
|
8341
|
+
}
|
|
8342
|
+
|
|
8055
8343
|
// src/http/codex-oauth-device.ts
|
|
8056
8344
|
init_zod();
|
|
8057
8345
|
init_crypto();
|
|
@@ -8192,7 +8480,9 @@ var OnboardingSignalsSchema = object2({
|
|
|
8192
8480
|
provider: ProviderNameSchema,
|
|
8193
8481
|
state: _enum2(["unverified", "configured", "verified"]),
|
|
8194
8482
|
workers: number2().int().nonnegative(),
|
|
8195
|
-
verifiedWorkers: number2().int().nonnegative()
|
|
8483
|
+
verifiedWorkers: number2().int().nonnegative(),
|
|
8484
|
+
error: string2().nullable(),
|
|
8485
|
+
warning: string2().nullable()
|
|
8196
8486
|
})),
|
|
8197
8487
|
embeddings: object2({
|
|
8198
8488
|
configured: boolean(),
|
|
@@ -9117,6 +9407,7 @@ function sentTaskId(thread, replies, serviceUserId) {
|
|
|
9117
9407
|
// src/comb/review-batch.ts
|
|
9118
9408
|
init_templates();
|
|
9119
9409
|
var REVIEW_BATCH_MAX = 50;
|
|
9410
|
+
var REVIEW_NOTE_MAX = 4000;
|
|
9120
9411
|
var REVIEW_BATCH_READ_CONCURRENCY = 5;
|
|
9121
9412
|
var SENT_KV_NAMESPACE = "comb:sent";
|
|
9122
9413
|
var PENDING_CLAIM_MS = 5 * 60000;
|
|
@@ -9147,6 +9438,9 @@ async function sendReviewBatch(input, deps = {}) {
|
|
|
9147
9438
|
if (ids.length === 0 || ids.length > REVIEW_BATCH_MAX) {
|
|
9148
9439
|
throw new ReviewBatchError(400, `Send between 1 and ${REVIEW_BATCH_MAX} comments`);
|
|
9149
9440
|
}
|
|
9441
|
+
if ((input.note?.length ?? 0) > REVIEW_NOTE_MAX) {
|
|
9442
|
+
throw new ReviewBatchError(400, `The note is longer than ${REVIEW_NOTE_MAX} characters`);
|
|
9443
|
+
}
|
|
9150
9444
|
const agentFs = combAgentFs();
|
|
9151
9445
|
if (!agentFs)
|
|
9152
9446
|
throw new ReviewBatchError(503, "agent-fs is not set up for this swarm");
|
|
@@ -9180,6 +9474,7 @@ async function sendReviewBatch(input, deps = {}) {
|
|
|
9180
9474
|
}
|
|
9181
9475
|
const wonIds = won.map((read) => read.id);
|
|
9182
9476
|
let taskId = null;
|
|
9477
|
+
let leadState = "none";
|
|
9183
9478
|
if (won.length > 0) {
|
|
9184
9479
|
try {
|
|
9185
9480
|
const text = await renderTaskText(input, won);
|
|
@@ -9190,6 +9485,7 @@ async function sendReviewBatch(input, deps = {}) {
|
|
|
9190
9485
|
]);
|
|
9191
9486
|
}
|
|
9192
9487
|
const lead = await getLeadAgent2();
|
|
9488
|
+
leadState = !lead ? "none" : lead.status === "offline" ? "offline" : "online";
|
|
9193
9489
|
const task = await createTask(text, {
|
|
9194
9490
|
agentId: lead?.id ?? "",
|
|
9195
9491
|
routingReason: lead ? "skill" : undefined,
|
|
@@ -9226,7 +9522,7 @@ async function sendReviewBatch(input, deps = {}) {
|
|
|
9226
9522
|
if (taskId === null && repaired.length === 0) {
|
|
9227
9523
|
throw new ReviewBatchError(409, "Nothing to send", skipped);
|
|
9228
9524
|
}
|
|
9229
|
-
return { taskId, sent: wonIds, skipped, repaired };
|
|
9525
|
+
return taskId === null ? { taskId, sent: wonIds, skipped, repaired } : { taskId, sent: wonIds, skipped, repaired, lead: leadState };
|
|
9230
9526
|
}
|
|
9231
9527
|
async function mapLimited(items, limit, fn) {
|
|
9232
9528
|
const results = new Array(items.length);
|
|
@@ -9371,6 +9667,7 @@ async function renderTaskText(input, reads) {
|
|
|
9371
9667
|
requested_by: await requesterLabel(input.requestedByUserId),
|
|
9372
9668
|
org_id: input.orgId,
|
|
9373
9669
|
drive_id: input.driveId,
|
|
9670
|
+
note_block: noteBlock(input.note),
|
|
9374
9671
|
comments_block: blocks.join(`
|
|
9375
9672
|
`)
|
|
9376
9673
|
});
|
|
@@ -9385,6 +9682,13 @@ function lineRange(comment) {
|
|
|
9385
9682
|
const end = comment.lineEnd ?? comment.lineStart;
|
|
9386
9683
|
return end === comment.lineStart ? `line ${comment.lineStart}` : `lines ${comment.lineStart}-${end}`;
|
|
9387
9684
|
}
|
|
9685
|
+
function noteBlock(note) {
|
|
9686
|
+
const text = note?.trim();
|
|
9687
|
+
return text ? `
|
|
9688
|
+
Note from the sender, about all the comments:
|
|
9689
|
+
${fenced(text)}
|
|
9690
|
+
` : "";
|
|
9691
|
+
}
|
|
9388
9692
|
function fenced(text) {
|
|
9389
9693
|
const longest = (text.match(/`+/g) ?? []).reduce((max, run) => Math.max(max, run.length), 0);
|
|
9390
9694
|
const fence = "`".repeat(Math.max(3, longest + 1));
|
|
@@ -9425,7 +9729,8 @@ var resultSchema = object2({
|
|
|
9425
9729
|
taskId: string2().nullable(),
|
|
9426
9730
|
sent: array2(string2()),
|
|
9427
9731
|
skipped: array2(skippedSchema),
|
|
9428
|
-
repaired: array2(object2({ id: string2(), taskId: string2() }))
|
|
9732
|
+
repaired: array2(object2({ id: string2(), taskId: string2() })),
|
|
9733
|
+
lead: _enum2(["online", "offline", "none"]).optional()
|
|
9429
9734
|
});
|
|
9430
9735
|
var batchErrorSchema = object2({ error: string2(), skipped: array2(skippedSchema) });
|
|
9431
9736
|
function isDrivePath(path) {
|
|
@@ -9436,13 +9741,14 @@ var reviewBatchRoute = route({
|
|
|
9436
9741
|
path: "/api/comb/review-batches",
|
|
9437
9742
|
pattern: ["api", "comb", "review-batches"],
|
|
9438
9743
|
summary: "Send agent-fs comments to the swarm as one lead task",
|
|
9439
|
-
description: "Comb's 'Send to swarm'. The server reads each comment again from agent-fs with its bootstrap key, skips replies, resolved comments, and comments already sent, and creates ONE task for the lead. Each sent comment gets a `[comb:sent task=<id>]` reply from the swarm service account. A comment is sent at most once. When an earlier send lost its reply, the batch posts that reply again (`repaired`). Answers 404 while COMB_ENABLED is off.",
|
|
9744
|
+
description: "Comb's 'Send to swarm'. The server reads each comment again from agent-fs with its bootstrap key, skips replies, resolved comments, and comments already sent, and creates ONE task for the lead. Each sent comment gets a `[comb:sent task=<id>]` reply from the swarm service account. A comment is sent at most once. An optional `note` from the sender goes into the task text. When an earlier send lost its reply, the batch posts that reply again (`repaired`). Answers 404 while COMB_ENABLED is off.",
|
|
9440
9745
|
tags: ["Comb"],
|
|
9441
9746
|
body: object2({
|
|
9442
9747
|
orgId: string2().min(1),
|
|
9443
9748
|
driveId: string2().min(1),
|
|
9444
9749
|
commentIds: array2(uuid()).min(1).max(REVIEW_BATCH_MAX),
|
|
9445
|
-
scopePath: string2().min(1).max(1024).refine(isDrivePath, "scopePath must start with '/' and have no '.' or '..' segment")
|
|
9750
|
+
scopePath: string2().min(1).max(1024).refine(isDrivePath, "scopePath must start with '/' and have no '.' or '..' segment"),
|
|
9751
|
+
note: string2().max(REVIEW_NOTE_MAX).optional()
|
|
9446
9752
|
}),
|
|
9447
9753
|
responses: {
|
|
9448
9754
|
200: {
|
|
@@ -9832,16 +10138,16 @@ declare module "swarm-extension" {
|
|
|
9832
10138
|
| "schedule"
|
|
9833
10139
|
| "slack"
|
|
9834
10140
|
| "agentmail"
|
|
9835
|
-
| "mcp"
|
|
9836
|
-
| "api"
|
|
9837
|
-
| "ui"
|
|
9838
10141
|
| "github"
|
|
9839
10142
|
| "gitlab"
|
|
9840
10143
|
| "azure-devops"
|
|
9841
10144
|
| "bitbucket"
|
|
9842
|
-
| "system"
|
|
9843
10145
|
| "linear"
|
|
9844
10146
|
| "jira"
|
|
10147
|
+
| "mcp"
|
|
10148
|
+
| "api"
|
|
10149
|
+
| "ui"
|
|
10150
|
+
| "system"
|
|
9845
10151
|
| "comb"
|
|
9846
10152
|
| "chat"
|
|
9847
10153
|
| undefined;
|
|
@@ -9950,16 +10256,16 @@ declare module "swarm-extension" {
|
|
|
9950
10256
|
| "schedule"
|
|
9951
10257
|
| "slack"
|
|
9952
10258
|
| "agentmail"
|
|
9953
|
-
| "mcp"
|
|
9954
|
-
| "api"
|
|
9955
|
-
| "ui"
|
|
9956
10259
|
| "github"
|
|
9957
10260
|
| "gitlab"
|
|
9958
10261
|
| "azure-devops"
|
|
9959
10262
|
| "bitbucket"
|
|
9960
|
-
| "system"
|
|
9961
10263
|
| "linear"
|
|
9962
10264
|
| "jira"
|
|
10265
|
+
| "mcp"
|
|
10266
|
+
| "api"
|
|
10267
|
+
| "ui"
|
|
10268
|
+
| "system"
|
|
9963
10269
|
| "comb"
|
|
9964
10270
|
| "chat";
|
|
9965
10271
|
tags: string[];
|
|
@@ -10224,6 +10530,15 @@ declare module "swarm-extension" {
|
|
|
10224
10530
|
description: string;
|
|
10225
10531
|
origin: TaskCreateOrigin;
|
|
10226
10532
|
requestInfo?: RequestInfo;
|
|
10533
|
+
/** Slack ingress metadata; not persisted or writable through modify. */
|
|
10534
|
+
slack?: {
|
|
10535
|
+
trigger: "mention" | "thread-buffer";
|
|
10536
|
+
messages: {
|
|
10537
|
+
ts: string;
|
|
10538
|
+
userId: string;
|
|
10539
|
+
text: string;
|
|
10540
|
+
}[];
|
|
10541
|
+
};
|
|
10227
10542
|
}
|
|
10228
10543
|
/** A pre.task.create hook blocked a task before it was created. */
|
|
10229
10544
|
export interface TaskBlockedEvent {
|
|
@@ -13653,6 +13968,7 @@ async function buildFleetBenchmarkResponse(now = new Date) {
|
|
|
13653
13968
|
const team = _enum2(COMPANY_TEAM_SIZES).safeParse(teamSize);
|
|
13654
13969
|
const use = _enum2(COMPANY_USE_CASES).safeParse(useCase);
|
|
13655
13970
|
const peerGroup = normalizeOrgWebsite(website) && team.success && use.success ? { teamSize: team.data, useCase: use.data } : null;
|
|
13971
|
+
const proxyPeerGroup = peerGroup && reportedUseCase(peerGroup.useCase) ? peerGroup : null;
|
|
13656
13972
|
const empty = {
|
|
13657
13973
|
level: peerGroup ? "full" : "basic",
|
|
13658
13974
|
peerGroup: null,
|
|
@@ -13679,7 +13995,7 @@ async function buildFleetBenchmarkResponse(now = new Date) {
|
|
|
13679
13995
|
return { ...empty, state: "telemetry_off", local };
|
|
13680
13996
|
if (finishedTasks < FLEET_MIN_FINISHED_TASKS)
|
|
13681
13997
|
return { ...empty, state: "not_enough_tasks", local };
|
|
13682
|
-
const fleet = await fleetBenchmarks(now.getTime(),
|
|
13998
|
+
const fleet = await fleetBenchmarks(now.getTime(), proxyPeerGroup);
|
|
13683
13999
|
const responsePeerGroup = peerGroup && fleet?.peer_group ? {
|
|
13684
14000
|
teamSize: fleet.peer_group.team_size,
|
|
13685
14001
|
useCase: fleet.peer_group.use_case,
|
|
@@ -14736,6 +15052,9 @@ function buildSlackManifest(name) {
|
|
|
14736
15052
|
return manifest;
|
|
14737
15053
|
}
|
|
14738
15054
|
|
|
15055
|
+
// src/http/integrations.ts
|
|
15056
|
+
init_credentials();
|
|
15057
|
+
|
|
14739
15058
|
// src/http/config-values.ts
|
|
14740
15059
|
init_db3();
|
|
14741
15060
|
async function resolveConfigValue(key) {
|
|
@@ -14910,7 +15229,7 @@ function createIntegrationsHandler(deps = {}) {
|
|
|
14910
15229
|
return true;
|
|
14911
15230
|
}
|
|
14912
15231
|
try {
|
|
14913
|
-
const client = buildClient(apiKey);
|
|
15232
|
+
const client = buildClient(selectCredential(apiKey, undefined, "ANTHROPIC_API_KEY").selected);
|
|
14914
15233
|
const agent = await client.beta.agents.retrieve(agentId);
|
|
14915
15234
|
const modelId = typeof agent.model === "string" ? agent.model : agent.model?.id ?? null;
|
|
14916
15235
|
claudeManagedTestRoute.respond(res, 200, {
|
|
@@ -15187,8 +15506,8 @@ function authorizeWrite(namespace, ctx) {
|
|
|
15187
15506
|
return null;
|
|
15188
15507
|
}
|
|
15189
15508
|
function authorizeRead(namespace, ctx) {
|
|
15190
|
-
const
|
|
15191
|
-
return
|
|
15509
|
+
const readErr = privateNamespaceError(namespace) ?? mcpOverflowAuthError(namespace, ctx.callerAgentId);
|
|
15510
|
+
return readErr ? { status: 403, message: readErr } : null;
|
|
15192
15511
|
}
|
|
15193
15512
|
function encodeValueOrError(res, value, valueType) {
|
|
15194
15513
|
try {
|
|
@@ -21590,6 +21909,7 @@ init_db3();
|
|
|
21590
21909
|
init_memory();
|
|
21591
21910
|
init_constants();
|
|
21592
21911
|
init_types();
|
|
21912
|
+
init_credentials();
|
|
21593
21913
|
init_openrouter_base_url();
|
|
21594
21914
|
|
|
21595
21915
|
// src/http/status.ts
|
|
@@ -21658,6 +21978,7 @@ var StatusIdentitySchema = object2({
|
|
|
21658
21978
|
var StatusActivitySchema = object2({
|
|
21659
21979
|
agents_online: number2().int().nonnegative(),
|
|
21660
21980
|
leads_online: number2().int().nonnegative(),
|
|
21981
|
+
leads_ready: number2().int().nonnegative(),
|
|
21661
21982
|
recent_tasks_count: number2().int().nonnegative()
|
|
21662
21983
|
});
|
|
21663
21984
|
var StatusCombSchema = object2({
|
|
@@ -22038,7 +22359,7 @@ async function buildSetup(automationSetup) {
|
|
|
22038
22359
|
await firstTaskMilestone()
|
|
22039
22360
|
];
|
|
22040
22361
|
}
|
|
22041
|
-
function computeHealth(setup) {
|
|
22362
|
+
function computeHealth(setup, readyLeads) {
|
|
22042
22363
|
const byId = new Map(setup.map((m) => [m.id, m]));
|
|
22043
22364
|
const harness = byId.get("harness");
|
|
22044
22365
|
const workers = byId.get("workers");
|
|
@@ -22046,6 +22367,8 @@ function computeHealth(setup) {
|
|
|
22046
22367
|
return "broken";
|
|
22047
22368
|
if (!workers || workers.state === "unverified")
|
|
22048
22369
|
return "broken";
|
|
22370
|
+
if (readyLeads === 0)
|
|
22371
|
+
return "degraded";
|
|
22049
22372
|
if (harness.state === "configured")
|
|
22050
22373
|
return "degraded";
|
|
22051
22374
|
for (const id of ["slack", "github", "linear", "jira"]) {
|
|
@@ -22063,12 +22386,13 @@ async function buildStatusPayload() {
|
|
|
22063
22386
|
const toStatus = ({ failureReason: _, ...status }) => status;
|
|
22064
22387
|
const automations = automationInputs.map((automation) => toStatus(preflightAutomation(automation, automationSetup))).sort((a, b) => a.name.localeCompare(b.name) || a.kind.localeCompare(b.kind));
|
|
22065
22388
|
const activity = await getInstanceActivity2();
|
|
22389
|
+
const readyLeads = (await getReadyAgentCounts2()).leads;
|
|
22066
22390
|
const instance = await getInstanceFeedbackSignals();
|
|
22067
22391
|
return {
|
|
22068
22392
|
runtime_pools: { enabled: isRuntimePoolsEnabled(), supervisor: runtimeSupervisorStatus() },
|
|
22069
22393
|
identity: buildIdentity(),
|
|
22070
22394
|
setup,
|
|
22071
|
-
activity,
|
|
22395
|
+
activity: { ...activity, leads_ready: readyLeads },
|
|
22072
22396
|
agent_fs: {
|
|
22073
22397
|
configured: !!process.env.AGENT_FS_API_URL,
|
|
22074
22398
|
base_url: process.env.AGENT_FS_API_URL ?? null,
|
|
@@ -22076,7 +22400,7 @@ async function buildStatusPayload() {
|
|
|
22076
22400
|
comb: getCombStatus(await combServiceUserId)
|
|
22077
22401
|
},
|
|
22078
22402
|
automations,
|
|
22079
|
-
health: computeHealth(setup),
|
|
22403
|
+
health: computeHealth(setup, readyLeads),
|
|
22080
22404
|
telemetry: { enabled: isTelemetryEnabled() },
|
|
22081
22405
|
instance
|
|
22082
22406
|
};
|
|
@@ -22111,7 +22435,7 @@ var getStatus = route({
|
|
|
22111
22435
|
path: "/status",
|
|
22112
22436
|
pattern: ["status"],
|
|
22113
22437
|
summary: "Identity + setup readiness + live activity for the swarm dashboard",
|
|
22114
|
-
description: "Single source of truth consumed by the UI home page. Identity comes from SWARM_* envs; setup milestones each emit `unverified | configured | verified`; automations report `running | needs_setup` from the same runtime preflight used at dispatch; activity counts agents alive in the last 5 min and tasks created in the last 24h; agent_fs reports whether AGENT_FS_API_URL is set, plus the Comb settings (COMB_ENABLED, the browser-facing agent-fs URL, the shared org and drive ids, and the agent-fs user id of the swarm service account); telemetry reports the effective ANONYMIZED_TELEMETRY opt-out state.",
|
|
22438
|
+
description: "Single source of truth consumed by the UI home page. Identity comes from SWARM_* envs; setup milestones each emit `unverified | configured | verified`; automations report `running | needs_setup` from the same runtime preflight used at dispatch; activity counts agents alive in the last 5 min, leads that can take work (status idle or busy), and tasks created in the last 24h; agent_fs reports whether AGENT_FS_API_URL is set, plus the Comb settings (COMB_ENABLED, the browser-facing agent-fs URL, the shared org and drive ids, and the agent-fs user id of the swarm service account); telemetry reports the effective ANONYMIZED_TELEMETRY opt-out state.",
|
|
22115
22439
|
tags: ["Status"],
|
|
22116
22440
|
responses: {
|
|
22117
22441
|
200: { description: "Status payload", schema: StatusResponseSchema },
|
|
@@ -22184,11 +22508,14 @@ async function buildSignals(state) {
|
|
|
22184
22508
|
if (!provider.success)
|
|
22185
22509
|
continue;
|
|
22186
22510
|
const rollup = await rollupCredStatusForProvider(provider.data);
|
|
22511
|
+
const live = rollup.latestLiveTest;
|
|
22187
22512
|
providers.push({
|
|
22188
22513
|
provider: provider.data,
|
|
22189
22514
|
state: rollup.state,
|
|
22190
22515
|
workers: rollup.workers,
|
|
22191
|
-
verifiedWorkers: rollup.verifiedWorkers
|
|
22516
|
+
verifiedWorkers: rollup.verifiedWorkers,
|
|
22517
|
+
error: live && !live.ok ? live.error ?? null : null,
|
|
22518
|
+
warning: live?.ok ? live.warning ?? null : null
|
|
22192
22519
|
});
|
|
22193
22520
|
}
|
|
22194
22521
|
const integrations = await getAutomationSetupStates();
|
|
@@ -22334,7 +22661,7 @@ async function handleMemoryProbe(body) {
|
|
|
22334
22661
|
const canReuseKey = reuseHost === undefined || endpoint.hostname === reuseHost;
|
|
22335
22662
|
const reusedKey = !explicitKey && body.reuseKey && canReuseKey ? process.env[body.reuseKey] : undefined;
|
|
22336
22663
|
const implicitKey = body.preset === "existing" ? process.env.EMBEDDING_API_KEY ?? process.env.OPENAI_API_KEY : undefined;
|
|
22337
|
-
const apiKey = explicitKey ?? reusedKey ?? implicitKey;
|
|
22664
|
+
const apiKey = splitCredentialPool(explicitKey ?? reusedKey ?? implicitKey ?? "")[0];
|
|
22338
22665
|
if (!apiKey) {
|
|
22339
22666
|
return {
|
|
22340
22667
|
ok: false,
|
|
@@ -22794,6 +23121,7 @@ var listTasks = route({
|
|
|
22794
23121
|
status: string2().optional(),
|
|
22795
23122
|
agentId: string2().optional(),
|
|
22796
23123
|
scheduleId: string2().optional(),
|
|
23124
|
+
workflowRunId: string2().uuid().optional(),
|
|
22797
23125
|
key: AssetKeySchema.optional(),
|
|
22798
23126
|
keyPrefix: AssetKeySchema.optional(),
|
|
22799
23127
|
search: string2().optional(),
|
|
@@ -23396,6 +23724,7 @@ async function handleTasks(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
23396
23724
|
status,
|
|
23397
23725
|
agentId: parsed.query.agentId || undefined,
|
|
23398
23726
|
scheduleId: parsed.query.scheduleId || undefined,
|
|
23727
|
+
workflowRunId: parsed.query.workflowRunId,
|
|
23399
23728
|
key: parsed.query.key,
|
|
23400
23729
|
keyPrefix: parsed.query.keyPrefix,
|
|
23401
23730
|
search: parsed.query.search || undefined,
|
|
@@ -26520,7 +26849,26 @@ var LOCAL_PAGE_APP_URL = "http://localhost:5274";
|
|
|
26520
26849
|
function getAppBaseUrl2() {
|
|
26521
26850
|
return getAppUrl(LOCAL_PAGE_APP_URL);
|
|
26522
26851
|
}
|
|
26523
|
-
|
|
26852
|
+
var FRAME_ANCESTOR_SOURCE_RE = /^(?:https?:\/\/)?(?:\*\.)?[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)*(?::(?:\d{1,5}|\*))?$/i;
|
|
26853
|
+
var cachedFrameAncestors = null;
|
|
26854
|
+
function getPageFrameAncestors() {
|
|
26855
|
+
const raw = process.env.PAGES_FRAME_ANCESTORS ?? "";
|
|
26856
|
+
if (cachedFrameAncestors?.raw === raw)
|
|
26857
|
+
return cachedFrameAncestors.origins;
|
|
26858
|
+
const origins = [];
|
|
26859
|
+
for (const entry of raw.split(/[\s,]+/)) {
|
|
26860
|
+
const value = entry.replace(/\/+$/, "");
|
|
26861
|
+
if (!value)
|
|
26862
|
+
continue;
|
|
26863
|
+
if (FRAME_ANCESTOR_SOURCE_RE.test(value))
|
|
26864
|
+
origins.push(value);
|
|
26865
|
+
else
|
|
26866
|
+
console.warn(`[pages] ignoring invalid PAGES_FRAME_ANCESTORS entry: ${entry}`);
|
|
26867
|
+
}
|
|
26868
|
+
cachedFrameAncestors = { raw, origins };
|
|
26869
|
+
return origins;
|
|
26870
|
+
}
|
|
26871
|
+
function buildCsp(page) {
|
|
26524
26872
|
const configured = getConfiguredAppUrls();
|
|
26525
26873
|
const devFallbacks = getNodeEnv() === "production" ? [] : [
|
|
26526
26874
|
"http://localhost:5274",
|
|
@@ -26530,7 +26878,8 @@ function buildCsp() {
|
|
|
26530
26878
|
"https://*.localhost",
|
|
26531
26879
|
"http://*.localhost"
|
|
26532
26880
|
];
|
|
26533
|
-
const
|
|
26881
|
+
const embedders = page.authMode === "public" ? getPageFrameAncestors() : [];
|
|
26882
|
+
const ancestors = Array.from(new Set([...configured, ...devFallbacks, ...embedders]));
|
|
26534
26883
|
return [
|
|
26535
26884
|
"default-src 'self'",
|
|
26536
26885
|
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.tailwindcss.com https://cdn.jsdelivr.net https://unpkg.com",
|
|
@@ -26696,7 +27045,7 @@ async function handlePagesPublic(req, res, pathSegments, queryParams) {
|
|
|
26696
27045
|
const headers = {
|
|
26697
27046
|
"Content-Type": "text/html; charset=utf-8",
|
|
26698
27047
|
"Cache-Control": "no-store",
|
|
26699
|
-
"Content-Security-Policy": buildCsp(),
|
|
27048
|
+
"Content-Security-Policy": buildCsp(page),
|
|
26700
27049
|
"X-Content-Type-Options": "nosniff"
|
|
26701
27050
|
};
|
|
26702
27051
|
if (inlineSetCookie.length > 0)
|
|
@@ -26720,7 +27069,7 @@ async function handlePagesPublic(req, res, pathSegments, queryParams) {
|
|
|
26720
27069
|
const headers = {
|
|
26721
27070
|
"Content-Type": "text/html; charset=utf-8",
|
|
26722
27071
|
"Cache-Control": "no-store",
|
|
26723
|
-
"Content-Security-Policy": buildCsp(),
|
|
27072
|
+
"Content-Security-Policy": buildCsp(page),
|
|
26724
27073
|
"X-Content-Type-Options": "nosniff"
|
|
26725
27074
|
};
|
|
26726
27075
|
if (inlineSetCookie.length > 0)
|
|
@@ -27302,6 +27651,298 @@ async function handlePoll(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
27302
27651
|
return false;
|
|
27303
27652
|
}
|
|
27304
27653
|
|
|
27654
|
+
// src/http/pool-keys.ts
|
|
27655
|
+
init_src2();
|
|
27656
|
+
init_zod();
|
|
27657
|
+
init_db3();
|
|
27658
|
+
init_api_keys();
|
|
27659
|
+
init_swarm_config_guard();
|
|
27660
|
+
init_credentials();
|
|
27661
|
+
init_secret_scrubber();
|
|
27662
|
+
var PoolKeyStatusSchema = _enum2(["ok", "rejected", "rate_limited", "unchecked"]);
|
|
27663
|
+
var PoolKeySchema = object2({
|
|
27664
|
+
index: number2().int().min(0),
|
|
27665
|
+
suffix: string2(),
|
|
27666
|
+
status: PoolKeyStatusSchema,
|
|
27667
|
+
error: string2().nullable(),
|
|
27668
|
+
checkedAt: string2().nullable(),
|
|
27669
|
+
rateLimitedUntil: string2().nullable()
|
|
27670
|
+
});
|
|
27671
|
+
var PoolKeysResponseSchema = object2({
|
|
27672
|
+
key: string2(),
|
|
27673
|
+
source: _enum2(["stored", "env", "none"]),
|
|
27674
|
+
readOnly: boolean(),
|
|
27675
|
+
keys: array2(PoolKeySchema)
|
|
27676
|
+
});
|
|
27677
|
+
var PoolKeyCheckResultSchema = _enum2(["verified", "rejected", "not_tested"]);
|
|
27678
|
+
var PoolKeyCheckSchema = object2({
|
|
27679
|
+
suffix: string2(),
|
|
27680
|
+
result: PoolKeyCheckResultSchema,
|
|
27681
|
+
httpStatus: number2().nullable(),
|
|
27682
|
+
error: string2().nullable()
|
|
27683
|
+
});
|
|
27684
|
+
var poolVar = string2().refine((key) => key !== "CODEX_OAUTH" && CREDENTIAL_POOL_VARS.includes(key), "Choose a credential pool variable.");
|
|
27685
|
+
var getPoolKeys = route({
|
|
27686
|
+
method: "get",
|
|
27687
|
+
path: "/api/config/pool-keys",
|
|
27688
|
+
pattern: ["api", "config", "pool-keys"],
|
|
27689
|
+
summary: "List credential pool suffixes and status",
|
|
27690
|
+
tags: ["Config"],
|
|
27691
|
+
query: object2({ key: poolVar }),
|
|
27692
|
+
responses: {
|
|
27693
|
+
200: { description: "Credential pool", schema: PoolKeysResponseSchema },
|
|
27694
|
+
400: { description: "Invalid pool variable" },
|
|
27695
|
+
403: { description: "Secret read permission required" }
|
|
27696
|
+
}
|
|
27697
|
+
});
|
|
27698
|
+
var addPoolKeys = route({
|
|
27699
|
+
method: "post",
|
|
27700
|
+
path: "/api/config/pool-keys",
|
|
27701
|
+
pattern: ["api", "config", "pool-keys"],
|
|
27702
|
+
summary: "Test and append keys to a credential pool",
|
|
27703
|
+
tags: ["Config"],
|
|
27704
|
+
rbac: { permission: "config.write.any" },
|
|
27705
|
+
body: object2({
|
|
27706
|
+
key: poolVar,
|
|
27707
|
+
value: string2(),
|
|
27708
|
+
baseUrl: string2().nullable().optional().describe("Base URL for the check only. Null tests the provider default. Omit to use the stored URL.")
|
|
27709
|
+
}),
|
|
27710
|
+
responses: {
|
|
27711
|
+
200: {
|
|
27712
|
+
description: "Updated credential pool and checks",
|
|
27713
|
+
schema: PoolKeysResponseSchema.extend({ checks: array2(PoolKeyCheckSchema) })
|
|
27714
|
+
},
|
|
27715
|
+
400: { description: "Invalid key" },
|
|
27716
|
+
403: { description: "Config administration and permission to read all secrets required" },
|
|
27717
|
+
409: { description: "Duplicate key or deployment env pool" },
|
|
27718
|
+
422: {
|
|
27719
|
+
description: "Provider rejected a key. Nothing was saved.",
|
|
27720
|
+
schema: object2({ error: string2(), checks: array2(PoolKeyCheckSchema) })
|
|
27721
|
+
}
|
|
27722
|
+
}
|
|
27723
|
+
});
|
|
27724
|
+
var deletePoolKey = route({
|
|
27725
|
+
method: "delete",
|
|
27726
|
+
path: "/api/config/pool-keys",
|
|
27727
|
+
pattern: ["api", "config", "pool-keys"],
|
|
27728
|
+
summary: "Remove one credential pool member",
|
|
27729
|
+
tags: ["Config"],
|
|
27730
|
+
rbac: { permission: "config.delete.any" },
|
|
27731
|
+
query: object2({
|
|
27732
|
+
key: poolVar,
|
|
27733
|
+
index: exports_coerce.number().int().min(0),
|
|
27734
|
+
suffix: string2().min(1).max(5)
|
|
27735
|
+
}),
|
|
27736
|
+
responses: {
|
|
27737
|
+
200: { description: "Updated credential pool", schema: PoolKeysResponseSchema },
|
|
27738
|
+
400: { description: "Invalid pool member" },
|
|
27739
|
+
403: { description: "Config administration and permission to read all secrets required" },
|
|
27740
|
+
409: { description: "The pool changed or comes from the deployment env" }
|
|
27741
|
+
}
|
|
27742
|
+
});
|
|
27743
|
+
var ENV_POOL_ERROR = "These keys come from the deployment env. Change them there.";
|
|
27744
|
+
async function readPool(key) {
|
|
27745
|
+
const [row] = await getSwarmConfigs2({ scope: "global", key });
|
|
27746
|
+
const envValue = getDeploymentEnvValue(key);
|
|
27747
|
+
const source = row ? "stored" : envValue ? "env" : "none";
|
|
27748
|
+
const value = row?.value ?? envValue ?? "";
|
|
27749
|
+
registerEnvSecrets({ [key]: value });
|
|
27750
|
+
return { row, source, members: splitCredentialPool(value) };
|
|
27751
|
+
}
|
|
27752
|
+
async function poolResponse(key) {
|
|
27753
|
+
const pool = await readPool(key);
|
|
27754
|
+
const statuses = await getKeyStatuses2(key, "global", null);
|
|
27755
|
+
return {
|
|
27756
|
+
key,
|
|
27757
|
+
source: pool.source,
|
|
27758
|
+
readOnly: pool.source === "env",
|
|
27759
|
+
keys: pool.members.map((member, index) => {
|
|
27760
|
+
const suffix = member.slice(-5);
|
|
27761
|
+
const row = statuses.find((status) => status.keySuffix === suffix);
|
|
27762
|
+
const rejected = !!row?.lastValidationFailedAt;
|
|
27763
|
+
const limited = row?.status === "rate_limited" && !!row.rateLimitedUntil && Date.parse(row.rateLimitedUntil) > Date.now();
|
|
27764
|
+
return {
|
|
27765
|
+
index,
|
|
27766
|
+
suffix,
|
|
27767
|
+
status: rejected ? "rejected" : limited ? "rate_limited" : row ? "ok" : "unchecked",
|
|
27768
|
+
error: rejected ? scrubSecrets(row?.lastValidationError) || null : null,
|
|
27769
|
+
checkedAt: rejected ? row.lastValidationFailedAt : row?.updatedAt ?? null,
|
|
27770
|
+
rateLimitedUntil: row?.rateLimitedUntil ?? null
|
|
27771
|
+
};
|
|
27772
|
+
})
|
|
27773
|
+
};
|
|
27774
|
+
}
|
|
27775
|
+
function duplicateError(members, additions) {
|
|
27776
|
+
const seen = new Set(members);
|
|
27777
|
+
for (const member of additions) {
|
|
27778
|
+
if (seen.has(member))
|
|
27779
|
+
return `The key ending ${member.slice(-5)} is already in the pool.`;
|
|
27780
|
+
seen.add(member);
|
|
27781
|
+
}
|
|
27782
|
+
return null;
|
|
27783
|
+
}
|
|
27784
|
+
async function savePool(key, members, row) {
|
|
27785
|
+
const value = members.join(",");
|
|
27786
|
+
const validationError = validateConfigEntry({
|
|
27787
|
+
scope: "global",
|
|
27788
|
+
key,
|
|
27789
|
+
value,
|
|
27790
|
+
exportToEnv: row?.exportToEnv
|
|
27791
|
+
});
|
|
27792
|
+
if (validationError)
|
|
27793
|
+
return validationError;
|
|
27794
|
+
await upsertSwarmConfigWithPolicyMirror({
|
|
27795
|
+
scope: "global",
|
|
27796
|
+
key,
|
|
27797
|
+
value,
|
|
27798
|
+
isSecret: true,
|
|
27799
|
+
description: row?.description ?? null,
|
|
27800
|
+
envPath: row?.envPath ?? null,
|
|
27801
|
+
exportToEnv: row?.exportToEnv
|
|
27802
|
+
});
|
|
27803
|
+
return null;
|
|
27804
|
+
}
|
|
27805
|
+
async function ensureSecretRead2(req, res) {
|
|
27806
|
+
if (await requestSecretReadScope(req) === "all")
|
|
27807
|
+
return true;
|
|
27808
|
+
jsonError(res, "Reading credential pools requires permission to read all secrets.", 403);
|
|
27809
|
+
return false;
|
|
27810
|
+
}
|
|
27811
|
+
async function handlePoolKeys(req, res, pathSegments, queryParams) {
|
|
27812
|
+
if (getPoolKeys.match(req.method, pathSegments)) {
|
|
27813
|
+
const parsed = await getPoolKeys.parse(req, res, pathSegments, queryParams);
|
|
27814
|
+
if (!parsed)
|
|
27815
|
+
return true;
|
|
27816
|
+
if (!await ensureSecretRead2(req, res))
|
|
27817
|
+
return true;
|
|
27818
|
+
getPoolKeys.respond(res, 200, await poolResponse(parsed.query.key));
|
|
27819
|
+
return true;
|
|
27820
|
+
}
|
|
27821
|
+
if (addPoolKeys.match(req.method, pathSegments)) {
|
|
27822
|
+
const parsed = await addPoolKeys.parse(req, res, pathSegments, queryParams);
|
|
27823
|
+
if (!parsed)
|
|
27824
|
+
return true;
|
|
27825
|
+
if (!await ensureConfigAdmin(req, res, "config.write.any"))
|
|
27826
|
+
return true;
|
|
27827
|
+
if (!await ensureSecretRead2(req, res))
|
|
27828
|
+
return true;
|
|
27829
|
+
const { key, value, baseUrl } = parsed.body;
|
|
27830
|
+
const additions = value.split(",").map((part) => part.trim()).filter(Boolean);
|
|
27831
|
+
if (!additions.length) {
|
|
27832
|
+
jsonError(res, "Enter a key.", 400);
|
|
27833
|
+
return true;
|
|
27834
|
+
}
|
|
27835
|
+
if (additions.some((part) => /\s/.test(part))) {
|
|
27836
|
+
jsonError(res, "A key cannot contain spaces or line breaks.", 400);
|
|
27837
|
+
return true;
|
|
27838
|
+
}
|
|
27839
|
+
registerEnvSecrets({ [key]: additions.join(",") });
|
|
27840
|
+
const initial = await readPool(key);
|
|
27841
|
+
if (initial.source === "env") {
|
|
27842
|
+
jsonError(res, ENV_POOL_ERROR, 409);
|
|
27843
|
+
return true;
|
|
27844
|
+
}
|
|
27845
|
+
const duplicate = duplicateError(initial.members, additions);
|
|
27846
|
+
if (duplicate) {
|
|
27847
|
+
jsonError(res, scrubSecrets(duplicate), 409);
|
|
27848
|
+
return true;
|
|
27849
|
+
}
|
|
27850
|
+
const env = { ...process.env };
|
|
27851
|
+
const provider = providerForKeyVar(key);
|
|
27852
|
+
const baseUrlKey = key === "OPENROUTER_API_KEY" ? "OPENROUTER_BASE_URL" : provider ? baseUrlEnvVar(provider) : undefined;
|
|
27853
|
+
if (baseUrlKey && baseUrl !== undefined) {
|
|
27854
|
+
env[baseUrlKey] = baseUrl ?? "";
|
|
27855
|
+
} else if (baseUrlKey) {
|
|
27856
|
+
const [row] = await getSwarmConfigs2({ scope: "global", key: baseUrlKey });
|
|
27857
|
+
if (row)
|
|
27858
|
+
env[baseUrlKey] = row.value;
|
|
27859
|
+
}
|
|
27860
|
+
const checks = await Promise.all(additions.map(async (member) => {
|
|
27861
|
+
try {
|
|
27862
|
+
const probe = await checkProviderPoolKey(key, member, env);
|
|
27863
|
+
return {
|
|
27864
|
+
suffix: member.slice(-5),
|
|
27865
|
+
result: probe.skipped ? "not_tested" : probe.ok ? "verified" : probe.httpStatus === 401 ? "rejected" : "not_tested",
|
|
27866
|
+
httpStatus: probe.httpStatus ?? null,
|
|
27867
|
+
error: scrubSecrets(probe.error?.replaceAll(member, "[REDACTED]")) || null
|
|
27868
|
+
};
|
|
27869
|
+
} catch {
|
|
27870
|
+
return {
|
|
27871
|
+
suffix: member.slice(-5),
|
|
27872
|
+
result: "not_tested",
|
|
27873
|
+
httpStatus: null,
|
|
27874
|
+
error: "The provider check did not complete."
|
|
27875
|
+
};
|
|
27876
|
+
}
|
|
27877
|
+
}));
|
|
27878
|
+
const rejected = checks.find((check) => check.result === "rejected");
|
|
27879
|
+
if (rejected) {
|
|
27880
|
+
addPoolKeys.respond(res, 422, {
|
|
27881
|
+
error: scrubSecrets(`The key ending ${rejected.suffix} was rejected (HTTP 401). Nothing was saved.`),
|
|
27882
|
+
checks
|
|
27883
|
+
});
|
|
27884
|
+
return true;
|
|
27885
|
+
}
|
|
27886
|
+
const result = await getDbClient2().transaction(async () => {
|
|
27887
|
+
const current = await readPool(key);
|
|
27888
|
+
if (current.source === "env")
|
|
27889
|
+
return { error: ENV_POOL_ERROR, status: 409 };
|
|
27890
|
+
const duplicate = duplicateError(current.members, additions);
|
|
27891
|
+
if (duplicate)
|
|
27892
|
+
return { error: duplicate, status: 409 };
|
|
27893
|
+
const members = [...current.members, ...additions];
|
|
27894
|
+
const error = await savePool(key, members, current.row);
|
|
27895
|
+
if (error)
|
|
27896
|
+
return { error, status: 400 };
|
|
27897
|
+
await recordKeyValidation2(key, checks.flatMap((check, index) => check.result === "verified" ? [{ keyIndex: current.members.length + index, keySuffix: check.suffix, ok: true }] : []), "global", null, { retireAbsent: false });
|
|
27898
|
+
return { value: members.join(",") };
|
|
27899
|
+
});
|
|
27900
|
+
if ("error" in result) {
|
|
27901
|
+
jsonError(res, scrubSecrets(result.error), result.status);
|
|
27902
|
+
return true;
|
|
27903
|
+
}
|
|
27904
|
+
await runConfigWriteSideEffects("global", key, result.value);
|
|
27905
|
+
addPoolKeys.respond(res, 200, { ...await poolResponse(key), checks });
|
|
27906
|
+
return true;
|
|
27907
|
+
}
|
|
27908
|
+
if (deletePoolKey.match(req.method, pathSegments)) {
|
|
27909
|
+
const parsed = await deletePoolKey.parse(req, res, pathSegments, queryParams);
|
|
27910
|
+
if (!parsed)
|
|
27911
|
+
return true;
|
|
27912
|
+
if (!await ensureConfigAdmin(req, res, "config.delete.any"))
|
|
27913
|
+
return true;
|
|
27914
|
+
if (!await ensureSecretRead2(req, res))
|
|
27915
|
+
return true;
|
|
27916
|
+
const { key, index, suffix } = parsed.query;
|
|
27917
|
+
const result = await getDbClient2().transaction(async () => {
|
|
27918
|
+
const current = await readPool(key);
|
|
27919
|
+
if (current.source === "env")
|
|
27920
|
+
return { error: ENV_POOL_ERROR, status: 409 };
|
|
27921
|
+
if (!current.members[index] || current.members[index].slice(-5) !== suffix) {
|
|
27922
|
+
return { error: "The key list changed. Reload it and try again.", status: 409 };
|
|
27923
|
+
}
|
|
27924
|
+
const members = current.members.filter((_, position) => position !== index);
|
|
27925
|
+
if (members.length) {
|
|
27926
|
+
const error = await savePool(key, members, current.row);
|
|
27927
|
+
if (error)
|
|
27928
|
+
return { error, status: 400 };
|
|
27929
|
+
} else {
|
|
27930
|
+
await deleteSwarmConfigByKey2("global", null, key);
|
|
27931
|
+
}
|
|
27932
|
+
await retirePoolKeyStatus(key, suffix, members.map((member, keyIndex) => ({ keySuffix: member.slice(-5), keyIndex })));
|
|
27933
|
+
return { value: members.join(",") };
|
|
27934
|
+
});
|
|
27935
|
+
if ("error" in result) {
|
|
27936
|
+
jsonError(res, scrubSecrets(result.error), result.status);
|
|
27937
|
+
return true;
|
|
27938
|
+
}
|
|
27939
|
+
await runConfigWriteSideEffects("global", key, result.value);
|
|
27940
|
+
deletePoolKey.respond(res, 200, await poolResponse(key));
|
|
27941
|
+
return true;
|
|
27942
|
+
}
|
|
27943
|
+
return false;
|
|
27944
|
+
}
|
|
27945
|
+
|
|
27305
27946
|
// src/http/pricing.ts
|
|
27306
27947
|
init_zod();
|
|
27307
27948
|
init_db3();
|
|
@@ -32240,7 +32881,8 @@ var upsertBodySchema = object2({
|
|
|
32240
32881
|
description: string2().default(""),
|
|
32241
32882
|
intent: string2().default(""),
|
|
32242
32883
|
scope: ScriptScopeSchema.default("agent"),
|
|
32243
|
-
fsMode: ScriptFsModeSchema.default("none")
|
|
32884
|
+
fsMode: ScriptFsModeSchema.default("none"),
|
|
32885
|
+
executor: ScriptExecutorNameSchema.nullable().optional()
|
|
32244
32886
|
});
|
|
32245
32887
|
var runBodySchema = object2({
|
|
32246
32888
|
name: scriptNameSchema.optional(),
|
|
@@ -32249,6 +32891,7 @@ var runBodySchema = object2({
|
|
|
32249
32891
|
intent: string2().default(""),
|
|
32250
32892
|
scope: ScriptScopeSchema.optional(),
|
|
32251
32893
|
fsMode: ScriptFsModeSchema.default("none"),
|
|
32894
|
+
executor: ScriptExecutorNameSchema.nullable().optional(),
|
|
32252
32895
|
idempotencyKey: string2().max(200).optional()
|
|
32253
32896
|
}).refine((body) => Boolean(body.name) !== Boolean(body.source), {
|
|
32254
32897
|
message: "Provide exactly one of name or source"
|
|
@@ -32697,6 +33340,10 @@ async function handleScripts(req, res, pathSegments, queryParams, agentId) {
|
|
|
32697
33340
|
return true;
|
|
32698
33341
|
}
|
|
32699
33342
|
}
|
|
33343
|
+
if (parsed.body.executor && !isExecutorAllowedByDeployment(parsed.body.executor)) {
|
|
33344
|
+
jsonError(res, 'Executor "native" is not permitted when deployment SCRIPT_EXECUTOR="quickjs"', 400);
|
|
33345
|
+
return true;
|
|
33346
|
+
}
|
|
32700
33347
|
const secretRefusal = refuseSourceWithSecrets(parsed.body.source);
|
|
32701
33348
|
if (secretRefusal) {
|
|
32702
33349
|
json(res, secretRefusal, 400);
|
|
@@ -32724,6 +33371,7 @@ async function handleScripts(req, res, pathSegments, queryParams, agentId) {
|
|
|
32724
33371
|
signatureJson: signatureJsonFor(parsed.body.source),
|
|
32725
33372
|
argsJsonSchema,
|
|
32726
33373
|
fsMode: parsed.body.fsMode,
|
|
33374
|
+
executor: parsed.body.executor,
|
|
32727
33375
|
agentId: agent.id,
|
|
32728
33376
|
isScratch: false,
|
|
32729
33377
|
typeChecked: true,
|
|
@@ -32761,6 +33409,7 @@ async function handleScripts(req, res, pathSegments, queryParams, agentId) {
|
|
|
32761
33409
|
}
|
|
32762
33410
|
let source = parsed.body.source;
|
|
32763
33411
|
let fsMode = parsed.body.fsMode;
|
|
33412
|
+
let executor = parsed.body.executor ?? null;
|
|
32764
33413
|
let namedScript = null;
|
|
32765
33414
|
if (parsed.body.name) {
|
|
32766
33415
|
const script = await resolveScript(parsed.body.name, agent.id, parsed.body.scope);
|
|
@@ -32771,11 +33420,16 @@ async function handleScripts(req, res, pathSegments, queryParams, agentId) {
|
|
|
32771
33420
|
namedScript = script;
|
|
32772
33421
|
source = script.source;
|
|
32773
33422
|
fsMode = script.fsMode;
|
|
33423
|
+
executor = parsed.body.executor !== undefined ? parsed.body.executor : script.executor;
|
|
32774
33424
|
}
|
|
32775
33425
|
if (fsMode === "workspace-rw") {
|
|
32776
33426
|
jsonError(res, "workspace-rw scripts are not supported by /api/scripts/run in v1", 501);
|
|
32777
33427
|
return true;
|
|
32778
33428
|
}
|
|
33429
|
+
if (executor && !isExecutorAllowedByDeployment(executor)) {
|
|
33430
|
+
jsonError(res, 'Executor "native" is not permitted when deployment SCRIPT_EXECUTOR="quickjs"', 400);
|
|
33431
|
+
return true;
|
|
33432
|
+
}
|
|
32779
33433
|
const startedAt = new Date().toISOString();
|
|
32780
33434
|
const runStartTouch = namedScript?.isScratch ? await touchScratchScriptLastUsed(namedScript.id) : null;
|
|
32781
33435
|
const credentials = await buildScriptCredentialBindingsWithFailures({ agentId: agent.id });
|
|
@@ -32783,6 +33437,7 @@ async function handleScripts(req, res, pathSegments, queryParams, agentId) {
|
|
|
32783
33437
|
source,
|
|
32784
33438
|
args: parsed.body.args,
|
|
32785
33439
|
fsMode,
|
|
33440
|
+
executor,
|
|
32786
33441
|
agentId: agent.id,
|
|
32787
33442
|
runtimeInstanceId,
|
|
32788
33443
|
egressSecrets: credentials.egressSecrets,
|
|
@@ -32911,6 +33566,7 @@ async function handleScripts(req, res, pathSegments, queryParams, agentId) {
|
|
|
32911
33566
|
isScratch: script.isScratch,
|
|
32912
33567
|
typeChecked: script.typeChecked,
|
|
32913
33568
|
fsMode: script.fsMode,
|
|
33569
|
+
executor: script.executor,
|
|
32914
33570
|
createdByAgentId: script.createdByAgentId,
|
|
32915
33571
|
createdAt: script.createdAt,
|
|
32916
33572
|
updatedAt: script.updatedAt
|
|
@@ -33672,6 +34328,7 @@ async function handleSessionData(req, res, pathSegments, queryParams, myAgentId)
|
|
|
33672
34328
|
// src/http/sessions.ts
|
|
33673
34329
|
init_zod();
|
|
33674
34330
|
init_key();
|
|
34331
|
+
init_source_key();
|
|
33675
34332
|
init_db3();
|
|
33676
34333
|
init_session_moves();
|
|
33677
34334
|
init_session_tree();
|
|
@@ -33680,6 +34337,74 @@ init_steering();
|
|
|
33680
34337
|
init_users();
|
|
33681
34338
|
init_rbac();
|
|
33682
34339
|
init_bus();
|
|
34340
|
+
|
|
34341
|
+
// src/slack/channel-labels.ts
|
|
34342
|
+
var LABEL_TTL_MS = 24 * 60 * 60 * 1000;
|
|
34343
|
+
var FAILURE_TTL_MS = 10 * 60 * 1000;
|
|
34344
|
+
var FAILURE_CACHE_MAX = 500;
|
|
34345
|
+
var LOOKUP_QUEUE_MAX = 50;
|
|
34346
|
+
var inFlight2 = new Set;
|
|
34347
|
+
var failedUntil = new Map;
|
|
34348
|
+
var pending = Promise.resolve();
|
|
34349
|
+
async function channelLabel(client, id) {
|
|
34350
|
+
const result = await callSlackWithRetry2(client, "conversations.info", {
|
|
34351
|
+
channel: id.toUpperCase()
|
|
34352
|
+
});
|
|
34353
|
+
const channel = result.channel;
|
|
34354
|
+
if (result.ok === false || !channel)
|
|
34355
|
+
throw new Error("Channel lookup failed");
|
|
34356
|
+
if (channel.is_mpim)
|
|
34357
|
+
return "Group DM";
|
|
34358
|
+
if (channel.is_im && channel.user) {
|
|
34359
|
+
const result = await callSlackWithRetry2(client, "users.info", { user: channel.user });
|
|
34360
|
+
const user = result.user;
|
|
34361
|
+
const name = user?.profile?.display_name || user?.real_name || user?.profile?.real_name;
|
|
34362
|
+
if (result.ok !== false && name)
|
|
34363
|
+
return `DM · ${name}`;
|
|
34364
|
+
} else if (channel.name) {
|
|
34365
|
+
return `#${channel.name}`;
|
|
34366
|
+
}
|
|
34367
|
+
throw new Error("Channel label unavailable");
|
|
34368
|
+
}
|
|
34369
|
+
var CHANNEL_GROUP_KEY = /^shared\/slack\/([^/]+)\/$/;
|
|
34370
|
+
function warmSlackChannelLabels(groupKeys) {
|
|
34371
|
+
const client = getSlackApp2()?.client;
|
|
34372
|
+
if (!client)
|
|
34373
|
+
return;
|
|
34374
|
+
for (const groupKey of groupKeys) {
|
|
34375
|
+
const id = CHANNEL_GROUP_KEY.exec(groupKey)?.[1];
|
|
34376
|
+
if (!id)
|
|
34377
|
+
continue;
|
|
34378
|
+
if (inFlight2.has(id) || (failedUntil.get(id) ?? 0) > Date.now())
|
|
34379
|
+
continue;
|
|
34380
|
+
failedUntil.delete(id);
|
|
34381
|
+
if (inFlight2.size >= LOOKUP_QUEUE_MAX)
|
|
34382
|
+
continue;
|
|
34383
|
+
if (failedUntil.size + inFlight2.size >= FAILURE_CACHE_MAX) {
|
|
34384
|
+
const now = Date.now();
|
|
34385
|
+
for (const [failedId, until] of failedUntil) {
|
|
34386
|
+
if (until <= now)
|
|
34387
|
+
failedUntil.delete(failedId);
|
|
34388
|
+
}
|
|
34389
|
+
if (failedUntil.size + inFlight2.size >= FAILURE_CACHE_MAX)
|
|
34390
|
+
continue;
|
|
34391
|
+
}
|
|
34392
|
+
inFlight2.add(id);
|
|
34393
|
+
pending = pending.then(async () => {
|
|
34394
|
+
try {
|
|
34395
|
+
const label = await channelLabel(client, id);
|
|
34396
|
+
await rememberSessionLabel(groupKey, label, LABEL_TTL_MS);
|
|
34397
|
+
} catch (error) {
|
|
34398
|
+
failedUntil.set(id, Date.now() + FAILURE_TTL_MS);
|
|
34399
|
+
console.warn(`[Slack] Could not cache a session channel label: ${slackErrorCode2(error) ?? "unknown error"}`);
|
|
34400
|
+
} finally {
|
|
34401
|
+
inFlight2.delete(id);
|
|
34402
|
+
}
|
|
34403
|
+
});
|
|
34404
|
+
}
|
|
34405
|
+
}
|
|
34406
|
+
|
|
34407
|
+
// src/http/sessions.ts
|
|
33683
34408
|
init_types();
|
|
33684
34409
|
init_request_auth_context();
|
|
33685
34410
|
init_runtime_pools_flag();
|
|
@@ -33742,6 +34467,7 @@ var SessionTreeGroupSchema = SessionSectionCountsSchema.extend({
|
|
|
33742
34467
|
lastActivityAt: string2()
|
|
33743
34468
|
});
|
|
33744
34469
|
var SessionTreeResponseSchema = object2({
|
|
34470
|
+
labels: record2(string2(), string2()).optional(),
|
|
33745
34471
|
groups: array2(SessionTreeGroupSchema),
|
|
33746
34472
|
inbox: SessionSectionCountsSchema,
|
|
33747
34473
|
later: SessionSectionCountsSchema,
|
|
@@ -34179,6 +34905,9 @@ async function checkSessionMove(rootTaskId, actor, req, myAgentId, options = {})
|
|
|
34179
34905
|
}
|
|
34180
34906
|
if (root.parentTaskId)
|
|
34181
34907
|
return { reason: "Task is not a session root" };
|
|
34908
|
+
const sourceError = sourceMoveError(options.destination ?? null, root);
|
|
34909
|
+
if (sourceError)
|
|
34910
|
+
return { reason: sourceError };
|
|
34182
34911
|
const tasks = await getRootTaskChain2(root.id);
|
|
34183
34912
|
for (const task of tasks) {
|
|
34184
34913
|
if (!await canMutateTaskNamespace(task, myAgentId, req)) {
|
|
@@ -34203,6 +34932,7 @@ var getSession = route({
|
|
|
34203
34932
|
chain: array2(TaskWithSteeringSchema),
|
|
34204
34933
|
access: SessionAccessSchema,
|
|
34205
34934
|
owner: SessionOwnerSchema.nullable(),
|
|
34935
|
+
groupKey: string2(),
|
|
34206
34936
|
approvals: array2(SessionApprovalSchema).optional(),
|
|
34207
34937
|
readState: _enum2(["unread", "read", "later", "done"]).optional(),
|
|
34208
34938
|
lastActivityAt: string2().optional()
|
|
@@ -34389,11 +35119,15 @@ async function handleSessions(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
34389
35119
|
if (!parsed)
|
|
34390
35120
|
return true;
|
|
34391
35121
|
const actor = await resolveSessionActor2(req, myAgentId);
|
|
34392
|
-
|
|
35122
|
+
const tree = await getSessionTree(actor, undefined, {
|
|
34393
35123
|
mine: parsed.query.show !== "all",
|
|
34394
35124
|
hideSource: parsed.query.hideSource,
|
|
34395
35125
|
showSource: parsed.query.showSource
|
|
34396
|
-
})
|
|
35126
|
+
});
|
|
35127
|
+
const { sourceGroups, slackChannels, threadLabels, ...counts } = tree;
|
|
35128
|
+
const labels = { ...threadLabels, ...await getSessionLabels(sourceGroups) };
|
|
35129
|
+
warmSlackChannelLabels(slackChannels.map((id) => `shared/slack/${id}/`).filter((key) => labels[key] === undefined));
|
|
35130
|
+
sessionTree.respond(res, 200, { ...counts, labels });
|
|
34397
35131
|
return true;
|
|
34398
35132
|
}
|
|
34399
35133
|
if (triageSessionListRoute.match(req.method, pathSegments)) {
|
|
@@ -34418,7 +35152,9 @@ async function handleSessions(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
34418
35152
|
const skipped = [];
|
|
34419
35153
|
const moves = [];
|
|
34420
35154
|
for (const rootId of new Set(parsed.body.rootTaskIds)) {
|
|
34421
|
-
const checked = await checkSessionMove(rootId, actor, req, myAgentId
|
|
35155
|
+
const checked = await checkSessionMove(rootId, actor, req, myAgentId, {
|
|
35156
|
+
destination: key
|
|
35157
|
+
});
|
|
34422
35158
|
if ("reason" in checked) {
|
|
34423
35159
|
skipped.push({ rootTaskId: rootId, reason: checked.reason });
|
|
34424
35160
|
} else {
|
|
@@ -34439,6 +35175,10 @@ async function handleSessions(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
34439
35175
|
if (!parsed)
|
|
34440
35176
|
return true;
|
|
34441
35177
|
const from = normalizeAssetKey(parsed.body.from);
|
|
35178
|
+
if (sourceOfKey(from) || parsed.body.to && sourceOfKey(normalizeAssetKey(parsed.body.to))) {
|
|
35179
|
+
jsonError(res, SOURCE_GROUPS_READ_ONLY, 400);
|
|
35180
|
+
return true;
|
|
35181
|
+
}
|
|
34442
35182
|
if (parseAssetKey(from).relativeSegments.length === 0) {
|
|
34443
35183
|
jsonError(res, "Cannot move a namespace root", 400);
|
|
34444
35184
|
return true;
|
|
@@ -34478,7 +35218,8 @@ async function handleSessions(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
34478
35218
|
continue;
|
|
34479
35219
|
}
|
|
34480
35220
|
const checked = await checkSessionMove(root.id, actor, req, myAgentId, {
|
|
34481
|
-
ownerOnly: true
|
|
35221
|
+
ownerOnly: true,
|
|
35222
|
+
destination: nextKey
|
|
34482
35223
|
});
|
|
34483
35224
|
if ("reason" in checked) {
|
|
34484
35225
|
skipped.push({ rootTaskId: root.id, reason: checked.reason });
|
|
@@ -34522,11 +35263,12 @@ async function handleSessions(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
34522
35263
|
} : null;
|
|
34523
35264
|
const chain = await getRootTaskChain2(parsed.params.rootTaskId);
|
|
34524
35265
|
const tasks = [root, ...chain];
|
|
34525
|
-
const [steering, citations, approvals, read] = await Promise.all([
|
|
35266
|
+
const [steering, citations, approvals, read, groupKey] = await Promise.all([
|
|
34526
35267
|
getTaskSteeringFieldsForTasks(tasks),
|
|
34527
35268
|
getTaskCitationsForTasks(tasks.map((task) => task.id)),
|
|
34528
35269
|
getPendingApprovalsForTasks2(tasks.map((task) => task.id)),
|
|
34529
|
-
actor.kind === "user" && actor.userId ? getSessionReadState(sessionRoot.id, actor.userId) : Promise.resolve(null)
|
|
35270
|
+
actor.kind === "user" && actor.userId ? getSessionReadState(sessionRoot.id, actor.userId) : Promise.resolve(null),
|
|
35271
|
+
getSessionGroupKey(root)
|
|
34530
35272
|
]);
|
|
34531
35273
|
const decorate = (task) => ({
|
|
34532
35274
|
...task,
|
|
@@ -34538,6 +35280,7 @@ async function handleSessions(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
34538
35280
|
chain: chain.map(decorate),
|
|
34539
35281
|
access,
|
|
34540
35282
|
owner,
|
|
35283
|
+
groupKey,
|
|
34541
35284
|
...approvals.length ? { approvals } : {},
|
|
34542
35285
|
...read ?? {}
|
|
34543
35286
|
});
|
|
@@ -35926,7 +36669,8 @@ var SwarmMetricsSchema = object2({
|
|
|
35926
36669
|
sessionLogs: RetentionTableStatsSchema.optional(),
|
|
35927
36670
|
agentLog: RetentionTableStatsSchema.optional(),
|
|
35928
36671
|
events: RetentionTableStatsSchema.optional(),
|
|
35929
|
-
contextVersions: RetentionTableStatsSchema.optional()
|
|
36672
|
+
contextVersions: RetentionTableStatsSchema.optional(),
|
|
36673
|
+
scriptRuns: RetentionTableStatsSchema.optional()
|
|
35930
36674
|
})
|
|
35931
36675
|
});
|
|
35932
36676
|
var ConcurrentContextSchema = object2({
|
|
@@ -39306,63 +40050,6 @@ init_db3();
|
|
|
39306
40050
|
init_workflow_idempotency();
|
|
39307
40051
|
init_workflow_runs();
|
|
39308
40052
|
init_types();
|
|
39309
|
-
|
|
39310
|
-
// src/http/idempotency-key.ts
|
|
39311
|
-
init_zod();
|
|
39312
|
-
init_workflow_idempotency();
|
|
39313
|
-
init_request_auth_context();
|
|
39314
|
-
var IDEMPOTENCY_KEY_PATTERN = /^[\x21-\x7E]{1,255}$/;
|
|
39315
|
-
var IDEMPOTENT_REPLAYED_HEADER = "Idempotent-Replayed";
|
|
39316
|
-
var idempotencyKeyHeader = (accepted) => object2({
|
|
39317
|
-
"Idempotency-Key": string2().regex(IDEMPOTENCY_KEY_PATTERN).optional().describe("Optional client-generated key, 1-255 visible ASCII characters (a UUID works). " + `The first request the server accepts under a key ${accepted}; a retry with the same key ` + "and an equivalent body gets that request's status and body back (with " + `\`${IDEMPOTENT_REPLAYED_HEADER}: true\`) and changes nothing. The key is scoped to the ` + "caller's identity and this operation; it is not a credential. The same key with a " + "different body is a 409. A request rejected before it is accepted (validation, auth, " + "not found, disabled) does not use up the key. Accepted keys do not expire.")
|
|
39318
|
-
});
|
|
39319
|
-
function idempotencyPrincipal(req, myAgentId) {
|
|
39320
|
-
const auth = getRequestAuth(req);
|
|
39321
|
-
switch (auth?.kind) {
|
|
39322
|
-
case "user":
|
|
39323
|
-
return `user:${auth.userId}`;
|
|
39324
|
-
case "agent":
|
|
39325
|
-
return `agent:${auth.agentId}`;
|
|
39326
|
-
case "controller":
|
|
39327
|
-
return `controller:${auth.controllerId}`;
|
|
39328
|
-
case "guest":
|
|
39329
|
-
return null;
|
|
39330
|
-
default:
|
|
39331
|
-
return myAgentId ? `agent:${myAgentId}` : "operator";
|
|
39332
|
-
}
|
|
39333
|
-
}
|
|
39334
|
-
function readIdempotencyKey(req, res, myAgentId) {
|
|
39335
|
-
const raw = req.headers["idempotency-key"];
|
|
39336
|
-
if (raw === undefined)
|
|
39337
|
-
return;
|
|
39338
|
-
const key = Array.isArray(raw) ? raw.join(", ") : raw;
|
|
39339
|
-
if (!IDEMPOTENCY_KEY_PATTERN.test(key)) {
|
|
39340
|
-
jsonError(res, "Idempotency-Key must be 1-255 visible ASCII characters", 400);
|
|
39341
|
-
return null;
|
|
39342
|
-
}
|
|
39343
|
-
const principal = idempotencyPrincipal(req, myAgentId);
|
|
39344
|
-
if (!principal) {
|
|
39345
|
-
jsonError(res, "Idempotency-Key needs an identified caller", 400);
|
|
39346
|
-
return null;
|
|
39347
|
-
}
|
|
39348
|
-
return { principal, key };
|
|
39349
|
-
}
|
|
39350
|
-
async function replayAcceptedOperation(res, claim, send) {
|
|
39351
|
-
const accepted = await findAcceptedWorkflowOperation(claim);
|
|
39352
|
-
if (!accepted)
|
|
39353
|
-
return false;
|
|
39354
|
-
if (accepted.fingerprint !== claim.fingerprint) {
|
|
39355
|
-
jsonError(res, "Idempotency-Key was already used for a different request", 409);
|
|
39356
|
-
} else if (accepted.resourceDeletedAt !== null) {
|
|
39357
|
-
jsonError(res, "The workflow this Idempotency-Key created or triggered was deleted; send a new key to start over", 410);
|
|
39358
|
-
} else {
|
|
39359
|
-
res.setHeader(IDEMPOTENT_REPLAYED_HEADER, "true");
|
|
39360
|
-
send(accepted.body);
|
|
39361
|
-
}
|
|
39362
|
-
return true;
|
|
39363
|
-
}
|
|
39364
|
-
|
|
39365
|
-
// src/http/workflows.ts
|
|
39366
40053
|
var WorkflowWithFavoriteSchema = WorkflowSchema.extend({ favorite: boolean() });
|
|
39367
40054
|
var WorkflowSaveResponseSchema = WorkflowSchema.extend({
|
|
39368
40055
|
warnings: array2(string2()).optional()
|
|
@@ -39391,6 +40078,11 @@ var WorkflowRunPageSchema = object2({
|
|
|
39391
40078
|
nextOffset: number2().int().optional()
|
|
39392
40079
|
})
|
|
39393
40080
|
});
|
|
40081
|
+
var WorkflowRunTreeSchema = object2({
|
|
40082
|
+
rootRunId: string2(),
|
|
40083
|
+
runs: array2(WorkflowRunSummarySchema),
|
|
40084
|
+
hasOpenWork: boolean()
|
|
40085
|
+
});
|
|
39394
40086
|
var SuccessResponseSchema = object2({ success: literal2(true) });
|
|
39395
40087
|
async function withSaveWarnings(workflow) {
|
|
39396
40088
|
const warnings = await workflowSaveWarnings(workflow.definition, getExecutorRegistry2());
|
|
@@ -39551,6 +40243,9 @@ var triggerWorkflowRoute = route({
|
|
|
39551
40243
|
description: "With an `Idempotency-Key`, a retry returns the accepted run's `runId` and `skipped` without starting, resuming or waiting for anything, even after the workflow was disabled or edited and whatever state the run is in now.",
|
|
39552
40244
|
tags: ["Workflows"],
|
|
39553
40245
|
params: object2({ id: string2() }),
|
|
40246
|
+
query: object2({
|
|
40247
|
+
wait: _enum2(["true", "false"]).optional().describe("Default true: respond after the run's instant steps ran, when it finishes or parks at its first async step. " + "false: respond as soon as the run is committed and walk it in the background.")
|
|
40248
|
+
}),
|
|
39554
40249
|
headers: idempotencyKeyHeader("starts one run"),
|
|
39555
40250
|
responses: {
|
|
39556
40251
|
201: {
|
|
@@ -39605,20 +40300,45 @@ var getWorkflowRunRoute = route({
|
|
|
39605
40300
|
path: "/api/workflow-runs/{id}",
|
|
39606
40301
|
pattern: ["api", "workflow-runs", null],
|
|
39607
40302
|
summary: "Get a workflow run with steps (includes retry columns)",
|
|
40303
|
+
description: "Returns the run with its `context` and every step with its `input` by default. A step's `input` is a snapshot of the context when the step started, so in runs with loops (polling, `wait`, iterations) the response grows with steps × context size. Pass `fields=slim` to drop `run.context` and `steps[].input`; outputs, errors, diagnostics, retry fields and `parent` stay.",
|
|
39608
40304
|
tags: ["Workflows"],
|
|
39609
40305
|
params: object2({ id: string2() }),
|
|
40306
|
+
query: object2({
|
|
40307
|
+
fields: _enum2(["full", "slim"]).optional()
|
|
40308
|
+
}),
|
|
39610
40309
|
responses: {
|
|
39611
40310
|
200: {
|
|
39612
40311
|
description: "Workflow run details with steps including retry info",
|
|
39613
|
-
schema:
|
|
39614
|
-
|
|
39615
|
-
|
|
39616
|
-
|
|
39617
|
-
|
|
40312
|
+
schema: union2([
|
|
40313
|
+
object2({
|
|
40314
|
+
run: WorkflowRunSchema,
|
|
40315
|
+
steps: array2(WorkflowRunStepSchema),
|
|
40316
|
+
parent: WorkflowRunParentSchema.optional()
|
|
40317
|
+
}),
|
|
40318
|
+
object2({
|
|
40319
|
+
run: WorkflowRunSummarySchema,
|
|
40320
|
+
steps: array2(WorkflowRunStepSlimSchema),
|
|
40321
|
+
parent: WorkflowRunParentSchema.optional()
|
|
40322
|
+
})
|
|
40323
|
+
])
|
|
39618
40324
|
},
|
|
39619
40325
|
404: { description: "Run not found" }
|
|
39620
40326
|
}
|
|
39621
40327
|
});
|
|
40328
|
+
var getWorkflowRunTreeRoute = route({
|
|
40329
|
+
method: "get",
|
|
40330
|
+
path: "/api/workflow-runs/{id}/tree",
|
|
40331
|
+
pattern: ["api", "workflow-runs", null, "tree"],
|
|
40332
|
+
summary: "Get a workflow run and every sub-workflow run below it",
|
|
40333
|
+
description: `Follows stored parent links (\`parentStepId\` → step → run) through every attempt of every step, terminal runs included. \`runs\` holds list rows without \`context\`, root first. \`hasOpenWork\` is true while any run in the tree is live, has a pending, running or waiting step, a queued retry, an open task or a pending approval; after a cancel it turns false once the tree has settled. Both come from one read snapshot. The tree is not paginated. Links that form a cycle or nest deeper than ${WORKFLOW_RUN_TREE_MAX_DEPTH} levels return 409.`,
|
|
40334
|
+
tags: ["Workflows"],
|
|
40335
|
+
params: object2({ id: string2() }),
|
|
40336
|
+
responses: {
|
|
40337
|
+
200: { description: "The run tree", schema: WorkflowRunTreeSchema },
|
|
40338
|
+
404: { description: "Run not found" },
|
|
40339
|
+
409: { description: "Stored parent links form a cycle or nest past the depth bound" }
|
|
40340
|
+
}
|
|
40341
|
+
});
|
|
39622
40342
|
var retryWorkflowRunRoute = route({
|
|
39623
40343
|
method: "post",
|
|
39624
40344
|
path: "/api/workflow-runs/{id}/retry",
|
|
@@ -40124,6 +40844,7 @@ async function handleWorkflows(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
40124
40844
|
runId = await startWorkflowExecution2(workflow, body, getExecutorRegistry2(), {
|
|
40125
40845
|
triggerType: "api",
|
|
40126
40846
|
requestedByUserId: await resolveHttpAuditUserId(req, myAgentId) ?? undefined,
|
|
40847
|
+
detach: parsed.query.wait === "false",
|
|
40127
40848
|
accept: claim ? async (run) => {
|
|
40128
40849
|
const response = { runId: run.runId, skipped: run.skipped };
|
|
40129
40850
|
await recordAcceptedWorkflowOperation(claim, {
|
|
@@ -40171,17 +40892,39 @@ async function handleWorkflows(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
40171
40892
|
const parsed = await getWorkflowRunRoute.parse(req, res, pathSegments, queryParams);
|
|
40172
40893
|
if (!parsed)
|
|
40173
40894
|
return true;
|
|
40174
|
-
const
|
|
40895
|
+
const slim = parsed.query.fields === "slim";
|
|
40896
|
+
const run = slim ? await getWorkflowRunSummary(parsed.params.id) : await getWorkflowRun2(parsed.params.id, "display");
|
|
40175
40897
|
if (!run) {
|
|
40176
40898
|
res.writeHead(404);
|
|
40177
40899
|
res.end();
|
|
40178
40900
|
return true;
|
|
40179
40901
|
}
|
|
40180
|
-
const steps = await getWorkflowRunStepsByRunId2(parsed.params.id, "display");
|
|
40902
|
+
const steps = slim ? await getWorkflowRunStepsSlimByRunId(parsed.params.id) : await getWorkflowRunStepsByRunId2(parsed.params.id, "display");
|
|
40181
40903
|
const parent = run.parentStepId ? await getWorkflowRunParent(run.parentStepId) : null;
|
|
40182
40904
|
getWorkflowRunRoute.respond(res, 200, { run, steps, ...parent ? { parent } : {} });
|
|
40183
40905
|
return true;
|
|
40184
40906
|
}
|
|
40907
|
+
if (getWorkflowRunTreeRoute.match(req.method, pathSegments)) {
|
|
40908
|
+
const parsed = await getWorkflowRunTreeRoute.parse(req, res, pathSegments, queryParams);
|
|
40909
|
+
if (!parsed)
|
|
40910
|
+
return true;
|
|
40911
|
+
let tree;
|
|
40912
|
+
try {
|
|
40913
|
+
tree = await getWorkflowRunTree(parsed.params.id);
|
|
40914
|
+
} catch (err) {
|
|
40915
|
+
if (!(err instanceof WorkflowRunTreeError))
|
|
40916
|
+
throw err;
|
|
40917
|
+
jsonError(res, err.message, 409);
|
|
40918
|
+
return true;
|
|
40919
|
+
}
|
|
40920
|
+
if (!tree) {
|
|
40921
|
+
res.writeHead(404);
|
|
40922
|
+
res.end();
|
|
40923
|
+
return true;
|
|
40924
|
+
}
|
|
40925
|
+
getWorkflowRunTreeRoute.respond(res, 200, tree);
|
|
40926
|
+
return true;
|
|
40927
|
+
}
|
|
40185
40928
|
if (retryWorkflowRunRoute.match(req.method, pathSegments)) {
|
|
40186
40929
|
const parsed = await retryWorkflowRunRoute.parse(req, res, pathSegments, queryParams);
|
|
40187
40930
|
if (!parsed)
|
|
@@ -40346,6 +41089,7 @@ async function handleX(req, res, pathSegments) {
|
|
|
40346
41089
|
jsonError(res, "workspace-rw scripts are not supported", 501);
|
|
40347
41090
|
return true;
|
|
40348
41091
|
}
|
|
41092
|
+
let hostValidatedArgs = false;
|
|
40349
41093
|
if (script.argsJsonSchema) {
|
|
40350
41094
|
try {
|
|
40351
41095
|
const schema = JSON.parse(script.argsJsonSchema);
|
|
@@ -40359,6 +41103,7 @@ async function handleX(req, res, pathSegments) {
|
|
|
40359
41103
|
});
|
|
40360
41104
|
return true;
|
|
40361
41105
|
}
|
|
41106
|
+
hostValidatedArgs = true;
|
|
40362
41107
|
} catch {}
|
|
40363
41108
|
}
|
|
40364
41109
|
const timeoutMs = resolveTimeoutMs(req);
|
|
@@ -40370,7 +41115,9 @@ async function handleX(req, res, pathSegments) {
|
|
|
40370
41115
|
const output = await runScriptWithRunCredential({
|
|
40371
41116
|
source: script.source,
|
|
40372
41117
|
args: args ?? null,
|
|
41118
|
+
[HOST_VALIDATED_ARGS]: hostValidatedArgs,
|
|
40373
41119
|
fsMode: "none",
|
|
41120
|
+
executor: script.executor,
|
|
40374
41121
|
agentId: endpoint.agentId,
|
|
40375
41122
|
timeoutMs,
|
|
40376
41123
|
egressSecrets: credentials.egressSecrets,
|
|
@@ -40536,6 +41283,7 @@ var httpServer = createHttpServer(async (req, res) => {
|
|
|
40536
41283
|
() => handleStatus(req, res, pathSegments, queryParams),
|
|
40537
41284
|
() => handleOnboarding(req, res, pathSegments, queryParams),
|
|
40538
41285
|
() => handleCodexOAuthDevice(req, res, pathSegments, queryParams),
|
|
41286
|
+
() => handleCodexOAuthAccounts(req, res, pathSegments, queryParams),
|
|
40539
41287
|
() => handleActiveSessions(req, res, pathSegments, queryParams, myAgentId),
|
|
40540
41288
|
() => handlePricing(req, res, pathSegments, queryParams, myAgentId),
|
|
40541
41289
|
() => handleSchedules(req, res, pathSegments, queryParams, myAgentId),
|
|
@@ -40543,6 +41291,7 @@ var httpServer = createHttpServer(async (req, res) => {
|
|
|
40543
41291
|
() => handleWorkflowEvents(req, res, pathSegments, queryParams),
|
|
40544
41292
|
() => handleApprovalRequests(req, res, pathSegments, queryParams),
|
|
40545
41293
|
() => handleApps(req, res, pathSegments, queryParams, myAgentId),
|
|
41294
|
+
() => handlePoolKeys(req, res, pathSegments, queryParams),
|
|
40546
41295
|
() => handleConfig(req, res, pathSegments, queryParams),
|
|
40547
41296
|
() => handleFs(req, res, pathSegments, queryParams, myAgentId),
|
|
40548
41297
|
() => handleComb(req, res, pathSegments, queryParams, myAgentId),
|
|
@@ -40619,7 +41368,7 @@ var httpServer = createHttpServer(async (req, res) => {
|
|
|
40619
41368
|
});
|
|
40620
41369
|
});
|
|
40621
41370
|
var detachRealtime = attachRealtimeTransport(httpServer);
|
|
40622
|
-
var { attachControllerTransport } = await import("./controllers-connect-
|
|
41371
|
+
var { attachControllerTransport } = await import("./controllers-connect-nep9h2xv.js");
|
|
40623
41372
|
var detachControllers = attachControllerTransport(httpServer);
|
|
40624
41373
|
var stopWorkerNudges = startWorkerNudgeListener();
|
|
40625
41374
|
var stopRoomDeletion = realtimeBus.subscribe("room:namespace-deleted", (namespace) => {
|
|
@@ -40648,7 +41397,7 @@ async function shutdown() {
|
|
|
40648
41397
|
sessionsProcessed: getServerSessionsProcessed()
|
|
40649
41398
|
});
|
|
40650
41399
|
if (hasCapability("scheduling")) {
|
|
40651
|
-
const { stopScheduler } = await import("./index-
|
|
41400
|
+
const { stopScheduler } = await import("./index-zyq8ct52.js");
|
|
40652
41401
|
stopScheduler();
|
|
40653
41402
|
}
|
|
40654
41403
|
stopHeartbeat2();
|
|
@@ -40659,8 +41408,8 @@ async function shutdown() {
|
|
|
40659
41408
|
await stopScriptRunSupervisor();
|
|
40660
41409
|
await stopSlackApp2();
|
|
40661
41410
|
await stopChatSdk();
|
|
40662
|
-
if (
|
|
40663
|
-
const { stopOAuthKeepalive } = await import("./keepalive-
|
|
41411
|
+
if (!isEnvFlagEnabled("OAUTH_KEEPALIVE_DISABLE", false)) {
|
|
41412
|
+
const { stopOAuthKeepalive } = await import("./keepalive-xdvsamvj.js");
|
|
40664
41413
|
await stopOAuthKeepalive();
|
|
40665
41414
|
}
|
|
40666
41415
|
stopOAuthPendingGc();
|
|
@@ -40740,21 +41489,21 @@ try {
|
|
|
40740
41489
|
console.warn("[startup] CAPABILITIES upgrade seed failed (non-fatal):", err);
|
|
40741
41490
|
}
|
|
40742
41491
|
try {
|
|
40743
|
-
const { ensurePricingSeeded } = await import("./boot-seeds-
|
|
41492
|
+
const { ensurePricingSeeded } = await import("./boot-seeds-ca84dhnn.js");
|
|
40744
41493
|
ensurePricingSeeded();
|
|
40745
|
-
const { startPricingRefreshLoop } = await import("./pricing-refresh-
|
|
41494
|
+
const { startPricingRefreshLoop } = await import("./pricing-refresh-dw2tgb53.js");
|
|
40746
41495
|
startPricingRefreshLoop();
|
|
40747
41496
|
} catch (err) {
|
|
40748
41497
|
console.error("[startup] Failed to seed pricing rows:", err);
|
|
40749
41498
|
}
|
|
40750
41499
|
try {
|
|
40751
|
-
const { ensureModelProfilesSeeded } = await import("./boot-seeds-
|
|
41500
|
+
const { ensureModelProfilesSeeded } = await import("./boot-seeds-ca84dhnn.js");
|
|
40752
41501
|
await ensureModelProfilesSeeded();
|
|
40753
41502
|
} catch (err) {
|
|
40754
41503
|
console.error("[startup] Failed to seed model profiles:", err);
|
|
40755
41504
|
}
|
|
40756
41505
|
try {
|
|
40757
|
-
const { ensureRbacSeeded } = await import("./boot-seeds-
|
|
41506
|
+
const { ensureRbacSeeded } = await import("./boot-seeds-ca84dhnn.js");
|
|
40758
41507
|
ensureRbacSeeded();
|
|
40759
41508
|
} catch (err) {
|
|
40760
41509
|
console.error("[startup] Failed to sync RBAC seed rows:", err);
|
|
@@ -40762,7 +41511,7 @@ try {
|
|
|
40762
41511
|
throw err;
|
|
40763
41512
|
}
|
|
40764
41513
|
try {
|
|
40765
|
-
const { runAllSeeders } = await import("./index-
|
|
41514
|
+
const { runAllSeeders } = await import("./index-jwt2bj6f.js");
|
|
40766
41515
|
await runAllSeeders({ scriptEmbeddingMode: "skip" });
|
|
40767
41516
|
} catch (err) {
|
|
40768
41517
|
console.error("[startup] Failed to seed built-in entities:", err);
|
|
@@ -40825,41 +41574,44 @@ httpServer.listen(port, async () => {
|
|
|
40825
41574
|
await initWorkflows2();
|
|
40826
41575
|
await startScriptRunSupervisor(getMcpBaseUrl());
|
|
40827
41576
|
if (hasCapability("scheduling")) {
|
|
40828
|
-
const { startScheduler } = await import("./index-
|
|
40829
|
-
const { getExecutorRegistry } = await import("./index-
|
|
41577
|
+
const { startScheduler } = await import("./index-zyq8ct52.js");
|
|
41578
|
+
const { getExecutorRegistry } = await import("./index-z5h22pes.js");
|
|
40830
41579
|
const intervalMs = Number(process.env.SCHEDULER_INTERVAL_MS) || 1e4;
|
|
40831
41580
|
startScheduler(getExecutorRegistry(), intervalMs, {
|
|
40832
41581
|
runId: globalState.__runId
|
|
40833
41582
|
});
|
|
40834
41583
|
}
|
|
40835
41584
|
if (!isEnvFlagEnabled("HEARTBEAT_DISABLE", false)) {
|
|
40836
|
-
const { startHeartbeat } = await import("./index-
|
|
41585
|
+
const { startHeartbeat } = await import("./index-y1ajx04a.js");
|
|
40837
41586
|
const heartbeatMs = Number(process.env.HEARTBEAT_INTERVAL_MS) || 90000;
|
|
40838
41587
|
startHeartbeat(heartbeatMs);
|
|
40839
41588
|
}
|
|
40840
41589
|
startPoolRouting();
|
|
40841
41590
|
startRuntimeSupervisor();
|
|
40842
|
-
if (
|
|
40843
|
-
const { startOAuthKeepalive } = await import("./keepalive-
|
|
41591
|
+
if (!isEnvFlagEnabled("OAUTH_KEEPALIVE_DISABLE", false)) {
|
|
41592
|
+
const { startOAuthKeepalive } = await import("./keepalive-xdvsamvj.js");
|
|
40844
41593
|
startOAuthKeepalive();
|
|
40845
41594
|
}
|
|
40846
|
-
if (
|
|
40847
|
-
const { startOAuthRefreshSweep } = await import("./oauth-refresh-sweep-
|
|
41595
|
+
if (!isEnvFlagEnabled("OAUTH_REFRESH_SWEEP_DISABLE", false)) {
|
|
41596
|
+
const { startOAuthRefreshSweep } = await import("./oauth-refresh-sweep-jd4r7zbs.js");
|
|
40848
41597
|
startOAuthRefreshSweep();
|
|
40849
41598
|
}
|
|
40850
41599
|
startOAuthPendingGc();
|
|
40851
41600
|
await startMemoryGc();
|
|
40852
41601
|
await startDbRetention();
|
|
40853
41602
|
startHumanFreeDrain();
|
|
40854
|
-
import("./boot-reembed-
|
|
41603
|
+
import("./boot-reembed-5h37a2c2.js").then(({ runBootReembed }) => runBootReembed()).catch((err) => {
|
|
40855
41604
|
console.error("[boot-reembed] startup backfill failed (non-fatal):", err);
|
|
40856
41605
|
});
|
|
40857
|
-
import("./boot-reembed-
|
|
41606
|
+
import("./boot-reembed-7h78vmvv.js").then(({ runBootReembedScripts }) => runBootReembedScripts()).catch((err) => {
|
|
40858
41607
|
console.error("[boot-reembed-scripts] startup backfill failed (non-fatal):", err);
|
|
40859
41608
|
});
|
|
40860
|
-
import("./boot-scrub-sweep-
|
|
41609
|
+
import("./boot-scrub-sweep-8mawd4gw.js").then(({ runBootScrubSweep }) => runBootScrubSweep()).catch((err) => {
|
|
40861
41610
|
console.error("[boot-scrub-sweep] startup scrub failed (non-fatal):", err);
|
|
40862
41611
|
});
|
|
41612
|
+
import("./session-source-backfill-424wzv0r.js").then(({ runSessionSourceBackfill }) => runSessionSourceBackfill()).catch((err) => {
|
|
41613
|
+
console.error("[session-source-backfill] startup run failed (non-fatal):", err);
|
|
41614
|
+
});
|
|
40863
41615
|
}).on("error", (err) => {
|
|
40864
41616
|
console.error("HTTP Server Error:", err);
|
|
40865
41617
|
});
|