@desplega.ai/agent-swarm 1.158.0 → 1.160.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{acp-adapter-xaq4n6pc.js → acp-adapter-2mjwcsfh.js} +124 -27
- package/dist/{actions-p9hz5yat.js → actions-e43rxskr.js} +35 -30
- package/dist/{anthropic-messages-51pz26qe.js → anthropic-messages-5qx80j9k.js} +106 -16
- package/dist/{app-g26wdcz6.js → app-mc7xfagn.js} +12 -10
- package/dist/{assistant-wydfqkb3.js → assistant-sedkzv3b.js} +42 -31
- package/dist/{azure-openai-responses-8gksqtmz.js → azure-openai-responses-nfb21z9a.js} +13 -14
- package/dist/{boot-reembed-se8zmdcp.js → boot-reembed-cqz9swn5.js} +13 -12
- package/dist/{boot-reembed-g5ckg9yb.js → boot-reembed-m3656j2n.js} +14 -13
- package/dist/{boot-scrub-logs-wfxqan61.js → boot-scrub-logs-xbxf5d7w.js} +11 -9
- package/dist/boot-seeds-gsetbs5y.js +28 -0
- package/dist/{claude-adapter-tv2x4f36.js → claude-adapter-dc6289mc.js} +28 -23
- package/dist/{claude-managed-adapter-41b2s7fd.js → claude-managed-adapter-naaw51me.js} +4 -3
- package/dist/{claude-managed-setup-60g8aazx.js → claude-managed-setup-eacvchx0.js} +12 -3
- package/dist/claude-sdk-session-bqp2xvym.js +29722 -0
- package/dist/{cli-987hg0aa.js → cli-0jwe9034.js} +2 -2
- package/dist/{cli-vj6h9kc2.js → cli-0m7wct0d.js} +59 -1
- package/dist/{cli-c07r9a2m.js → cli-0q3avq3s.js} +12 -11
- package/dist/{cli-19jenss3.js → cli-0wgxmwf6.js} +31 -10
- package/dist/cli-0x01kwrd.js +491 -0
- package/dist/cli-0xqde53b.js +176 -0
- package/dist/cli-10nhj6xq.js +8355 -0
- package/dist/{cli-tt9k8r35.js → cli-12tszpk9.js} +479 -910
- package/dist/{cli-5b6b62tz.js → cli-13hw4z91.js} +1 -1
- package/dist/{cli-cqt19wg6.js → cli-1a2j50m0.js} +11 -2
- package/dist/{cli-xberxa1r.js → cli-25fcq4b4.js} +2 -2
- package/dist/{cli-npssxgaz.js → cli-2pdaysab.js} +52 -2
- package/dist/cli-3qhyh31j.js +166 -0
- package/dist/cli-447dt1h3.js +3828 -0
- package/dist/cli-4derpgyk.js +115 -0
- package/dist/{cli-00w2c66p.js → cli-523679eh.js} +13 -2
- package/dist/{cli-y95wp3tg.js → cli-58e8yr0d.js} +1 -1
- package/dist/{cli-24k806sc.js → cli-5nbmpy8w.js} +3 -3
- package/dist/{cli-53sz8gkz.js → cli-6cs6wzxt.js} +1 -1
- package/dist/cli-741yb0xx.js +1027 -0
- package/dist/cli-74h9hscv.js +69 -0
- package/dist/cli-7cxw8b60.js +14910 -0
- package/dist/{cli-xhaeg2nc.js → cli-7e398j1h.js} +1 -1
- package/dist/cli-7kyk9jr3.js +22 -0
- package/dist/cli-89s4ngw3.js +183 -0
- package/dist/{cli-9b13ggd1.js → cli-89v6kyq7.js} +1 -0
- package/dist/{cli-ftfvggzx.js → cli-9hsgwz4w.js} +1045 -581
- package/dist/{cli-rqz8qbw7.js → cli-a8dvhzrt.js} +59 -20
- package/dist/{cli-j57qkrpq.js → cli-azhgzetg.js} +395 -56
- package/dist/cli-br0qdrnp.js +2150 -0
- package/dist/{cli-rj19hc34.js → cli-btfv8y88.js} +1 -1
- package/dist/{cli-8qmme6vd.js → cli-c8a36vcc.js} +2 -2
- package/dist/cli-cpvsaqsw.js +333 -0
- package/dist/cli-d5czme6m.js +17805 -0
- package/dist/{cli-h38x0qhg.js → cli-et8m9xsv.js} +4 -3
- package/dist/{cli-x24pshtq.js → cli-evvtk35y.js} +6 -6
- package/dist/{cli-7s3syk22.js → cli-f8gy6r2r.js} +5 -5
- package/dist/{cli-zt1227k1.js → cli-fkqhbg8g.js} +5 -3
- package/dist/{cli-9httdpyq.js → cli-g2whhdrf.js} +1 -1
- package/dist/cli-gt4hxb8p.js +99 -0
- package/dist/{cli-s8eet254.js → cli-jajnsm8q.js} +37184 -53838
- package/dist/{cli-7gtvvpbh.js → cli-jayjpjmb.js} +21 -12
- package/dist/{cli-68w09sjw.js → cli-jyk0ynw2.js} +27 -89
- package/dist/{cli-aehm1rbq.js → cli-jz4w45qt.js} +1152 -61
- package/dist/cli-kmcpfwn2.js +333856 -0
- package/dist/{cli-4198qc9v.js → cli-ktmyrtpn.js} +19 -3
- package/dist/{cli-j55n64b6.js → cli-mfe5btp9.js} +505 -189
- package/dist/{cli-q67y4wzm.js → cli-phsaj4xq.js} +24 -2
- package/dist/{cli-1hkrch3k.js → cli-pm1rst0h.js} +46 -7
- package/dist/{cli-pw9rj5t9.js → cli-pqetb83f.js} +1 -176
- package/dist/{cli-ggm92wcn.js → cli-ptr8h7kp.js} +20 -1
- package/dist/{cli-s8s499xy.js → cli-qbksc292.js} +3 -2
- package/dist/{cli-47m6dkd3.js → cli-qydf22qq.js} +597 -346
- package/dist/{cli-3gmcwfyx.js → cli-r1mxd1xh.js} +13 -6
- package/dist/cli-rb9m6rpe.js +4980 -0
- package/dist/cli-rykfmgwg.js +102 -0
- package/dist/{cli-5d10vd2m.js → cli-shkxm1vn.js} +6 -5
- package/dist/{cli-eetrvv91.js → cli-t3p77qk1.js} +1 -1
- package/dist/cli-tfky2838.js +756 -0
- package/dist/{cli-g8djp6qe.js → cli-tmqt7dpj.js} +40 -0
- package/dist/{cli-fgqxwrpv.js → cli-tpq83z89.js} +1631 -127
- package/dist/cli-trc24wk2.js +143 -0
- package/dist/{cli-aky8tctm.js → cli-tzx2ke1v.js} +3 -3
- package/dist/cli-v7fn5gms.js +1425 -0
- package/dist/{cli-wscdvcqz.js → cli-vctdqs5h.js} +1 -1
- package/dist/{cli-cw9zck8j.js → cli-xjcywfsf.js} +8 -4
- package/dist/{cli-k0g1sjzm.js → cli-ybgv4kw2.js} +18 -11
- package/dist/{cli-rjehvrts.js → cli-ydmcgve1.js} +8 -8
- package/dist/{cli-vhjwh6cz.js → cli-ygwm91nt.js} +1 -1
- package/dist/{cli-mcnhgnn1.js → cli-ykk5jaax.js} +184 -26
- package/dist/{cli-de1396j2.js → cli-ywybs5as.js} +7 -1
- package/dist/cli-zpep9q5e.js +491 -0
- package/dist/cli.js +41 -32
- package/dist/cloudflare-workers-ai-system-one-k6fbxw9d.js +46 -0
- package/dist/{codex-adapter-cnm8wk11.js → codex-adapter-nmxcatww.js} +26 -17
- package/dist/{codex-hook-9hptmdhj.js → codex-hook-20me6byw.js} +2 -2
- package/dist/{codex-login-x3jk4etn.js → codex-login-w6fz4xbz.js} +50 -5
- package/dist/{codex-session-runner-gfg547zj.js → codex-session-runner-90aa80ev.js} +24 -17
- package/dist/{commands-e3bn0p75.js → commands-8wcq1kn7.js} +11 -9
- package/dist/{db-03v9kzr2.js → db-j40kc4se.js} +25 -11
- package/dist/{devin-adapter-8vgkwh29.js → devin-adapter-dpsv6hd9.js} +1 -1
- package/dist/{dispatcher-nrmg8yht.js → dispatcher-4zqy768d.js} +34 -29
- package/dist/{dsh-adapter-k03nfqa6.js → dsh-adapter-mpnzgztj.js} +3 -3
- package/dist/{e2b-93x1k0j5.js → e2b-ez07znam.js} +4 -3
- package/dist/execute-6e7qeyk4.js +1017 -0
- package/dist/{google-generative-ai-bxmv50nc.js → google-generative-ai-k6n5nbpp.js} +6 -5
- package/dist/{google-vertex-809af514.js → google-vertex-44xxtcvp.js} +6 -5
- package/dist/{handlers-aqcedbyb.js → handlers-kjdce1w5.js} +37 -32
- package/dist/{hook-ybvmrmhq.js → hook-czx13n12.js} +19 -15
- package/dist/{hook-7vkskkre.js → hook-r2t4bqfg.js} +18 -14
- package/dist/{http-2eqa8t24.js → http-3bbb19be.js} +900 -145
- package/dist/{index-f6cryxwe.js → index-4a5njnm1.js} +2 -59
- package/dist/{index-x71bvq0p.js → index-668me3f0.js} +35 -30
- package/dist/{index-c6zsv1bd.js → index-7aj368tw.js} +13 -12
- package/dist/{index-1yks3qcr.js → index-fg0dsp6c.js} +34 -29
- package/dist/{index-chgdkq36.js → index-kkv84jq9.js} +34 -29
- package/dist/{index-a3vn96n8.js → index-zg7vp46x.js} +198 -54
- package/dist/{keepalive-vtkf5n99.js → keepalive-yra8dy57.js} +13 -11
- package/dist/{lead-h3sp357x.js → lead-va0pad2c.js} +54 -49
- package/dist/llama-cpp-classify-tgj35k8d.js +335 -0
- package/dist/{maintenance-jzeqtk3q.js → maintenance-hqewtmyg.js} +14 -13
- package/dist/{mistral-conversations-zx0kn554.js → mistral-conversations-pc3ntnxt.js} +14 -17
- package/dist/{oauth-refresh-sweep-qp3dzmdp.js → oauth-refresh-sweep-7rdt1m9n.js} +12 -10
- package/dist/{onboard-tmsp0qbz.js → onboard-j6ms6d0x.js} +6 -5
- package/dist/{openai-codex-responses-4vjqzvjp.js → openai-codex-responses-bbancrr0.js} +21 -8
- package/dist/{openai-completions-9hjrqbw8.js → openai-completions-jpaj5g2b.js} +9 -12
- package/dist/{openai-responses-7b1pn0xt.js → openai-responses-200k1wx4.js} +23 -18
- package/dist/{opencode-adapter-x6x2da1z.js → opencode-adapter-89rabkw2.js} +8 -7
- package/dist/{openrouter-images-9f9ek4rw.js → openrouter-images-8yx3487g.js} +5 -7
- package/dist/{otel-impl-9mz73q65.js → otel-impl-a792rjz0.js} +1 -1
- package/dist/{pi-messages-txpjj39q.js → pi-messages-vxdt8v7j.js} +2 -1
- package/dist/{pi-mono-adapter-m6dvv0dz.js → pi-mono-adapter-g7qzvr3v.js} +295 -70
- package/dist/pricing-refresh-wx0tp7cb.js +39 -0
- package/dist/quickjs-r1pq2107.wasm +0 -0
- package/dist/{rbac-roles-c9wqz83x.js → rbac-roles-8tzawacv.js} +12 -10
- package/dist/{render-v2-gryrh9h8.js → render-v2-mm7zswb8.js} +12 -10
- package/dist/runtime-zyssgse0.js +24 -0
- package/dist/{setup-q9720bt6.js → setup-8y70ys6t.js} +6 -5
- package/dist/typesafe-system-one-2ef30pec.js +27 -0
- package/dist/{virtual-modules-3htpgn8x.js → virtual-modules-6nmk7h3n.js} +22 -13
- package/dist/{work-objects-b76x7deb.js → work-objects-fg6xkb0n.js} +37 -32
- package/dist/{worker-6vrxbv41.js → worker-wmwhxsph.js} +54 -49
- package/openapi.json +1314 -91
- package/package.json +12 -11
- package/src/be/db/agents.ts +20 -0
- package/src/be/db/api-keys.ts +70 -0
- package/src/be/db/tasks/human-free.ts +442 -0
- package/src/be/db/tasks/read.ts +56 -1
- package/src/be/db/tasks/write.ts +107 -11
- package/src/be/db.ts +274 -188
- package/src/be/harness-model-support.ts +182 -0
- package/src/be/human-free-drain.ts +67 -0
- package/src/be/memory/providers/sqlite-store.ts +51 -15
- package/src/be/migrations/182_task_human_free_flag.sql +63 -0
- package/src/be/migrations/183_human_free_reclassify_queue.sql +25 -0
- package/src/be/migrations/184_model_catalog.sql +120 -0
- package/src/be/migrations/185_api_key_auth_failures.sql +6 -0
- package/src/be/migrations/186_api_key_seat_mismatch.sql +8 -0
- package/src/be/model-catalog-store.ts +644 -0
- package/src/be/model-tier-keys.ts +46 -0
- package/src/be/model-tier-resolution.ts +534 -0
- package/src/be/model-validation.ts +188 -0
- package/src/be/models-catalog.ts +61 -7
- package/src/be/modelsdev-cache.json +82 -0
- package/src/be/modelsdev-cache.ts +2 -0
- package/src/be/pricing-refresh.ts +154 -12
- package/src/be/scripts/typecheck.ts +15 -0
- package/src/be/seed/runner.ts +18 -12
- package/src/be/seed/types.ts +1 -0
- package/src/be/seed-scripts/catalog/task-failure-audit.ts +61 -9
- package/src/be/swarm-config-guard.ts +8 -0
- package/src/cli.tsx +10 -0
- package/src/commands/claude-managed-setup.ts +3 -1
- package/src/commands/codex-login.ts +67 -0
- package/src/commands/credential-outcome-report.ts +191 -0
- package/src/commands/rate-limit-outcome.ts +34 -4
- package/src/commands/runner.ts +357 -186
- package/src/commands/seat-mismatch-report.ts +46 -0
- package/src/extensions/apply-task-create.ts +27 -1
- package/src/extensions/contract-types.generated.ts +1 -1
- package/src/heartbeat/heartbeat.ts +79 -17
- package/src/heartbeat/templates.ts +2 -2
- package/src/http/agents.ts +62 -1
- package/src/http/api-keys.ts +140 -2
- package/src/http/codex-oauth-keep-warm.ts +3 -5
- package/src/http/index.ts +8 -0
- package/src/http/memory.ts +12 -5
- package/src/http/models-catalog.ts +357 -8
- package/src/http/poll.ts +54 -3
- package/src/http/schedules.ts +51 -6
- package/src/http/script-runs.ts +12 -0
- package/src/http/session-data.ts +2 -5
- package/src/http/stats.ts +6 -8
- package/src/http/status.ts +15 -1
- package/src/http/tasks.ts +90 -7
- package/src/http/usage-cache.ts +56 -15
- package/src/http/workflows.ts +46 -8
- package/src/mcp-client/http-client.ts +5 -0
- package/src/memory/recall-query.ts +74 -0
- package/src/prompts/base-prompt.ts +15 -4
- package/src/prompts/session-templates.ts +23 -1
- package/src/providers/acp-adapter.ts +1 -0
- package/src/providers/claude-adapter.ts +14 -5
- package/src/providers/claude-managed-adapter.ts +1 -0
- package/src/providers/claude-managed-models.ts +47 -161
- package/src/providers/claude-sdk-session.ts +3 -1
- package/src/providers/codex-adapter.ts +14 -14
- package/src/providers/codex-models.ts +65 -198
- package/src/providers/devin-adapter.ts +1 -0
- package/src/providers/dsh-adapter.ts +2 -1
- package/src/providers/harness-version.ts +83 -7
- package/src/providers/opencode-adapter.ts +53 -1
- package/src/providers/pi-binary-root/src/extensions/codemode/worker.ts +11 -0
- package/src/providers/pi-codemode-runtime.ts +17 -0
- package/src/providers/pi-mono-adapter.ts +361 -83
- package/src/providers/pi-mono-extension.ts +16 -1
- package/src/providers/reasoning-effort.ts +44 -140
- package/src/providers/types.ts +8 -0
- package/src/rbac/legacy-policy.ts +43 -0
- package/src/rbac/permissions.ts +15 -0
- package/src/scripts-runtime/sdk-allowlist.ts +4 -0
- package/src/scripts-runtime/types/stdlib.d.ts +15 -0
- package/src/scripts-runtime/types/swarm-extension.d.ts +3 -0
- package/src/scripts-runtime/types/swarm-sdk.d.ts +15 -0
- package/src/server.ts +6 -0
- package/src/slack/assistant.ts +13 -0
- package/src/slack/message-text.ts +56 -2
- package/src/slack/render-v2.ts +87 -37
- package/src/slack/session-status.ts +541 -0
- package/src/slack/thread-buffer.ts +10 -2
- package/src/tasks/sibling-awareness.ts +3 -2
- package/src/telemetry.ts +5 -4
- package/src/templates.d.ts +6 -0
- package/src/tests/agents-list-model-display.test.ts +4 -6
- package/src/tests/api-key-auth-failure-route.test.ts +142 -0
- package/src/tests/api-key-tracking.test.ts +368 -1
- package/src/tests/base-prompt.test.ts +43 -2
- package/src/tests/claude-adapter.test.ts +68 -0
- package/src/tests/claude-managed-adapter.test.ts +12 -18
- package/src/tests/codex-adapter.test.ts +2 -1
- package/src/tests/codex-auth-failure.test.ts +52 -0
- package/src/tests/codex-gpt6-release.test.ts +66 -5
- package/src/tests/codex-login.test.ts +116 -0
- package/src/tests/context-window.test.ts +7 -5
- package/src/tests/credential-exhaustion-policy.test.ts +118 -3
- package/src/tests/credential-outcome-report.test.ts +171 -0
- package/src/tests/credential-status-api.test.ts +103 -2
- package/src/tests/db-extraction-contract.test.ts +1 -0
- package/src/tests/db-task-read-contract.test.ts +10 -1
- package/src/tests/db-task-write-contract.test.ts +535 -2
- package/src/tests/docs-index-footprint.test.js +3 -3
- package/src/tests/dokploy-deploy.test.ts +315 -0
- package/src/tests/dsh-adapter.test.ts +1 -1
- package/src/tests/explicit-model-validation.test.ts +583 -0
- package/src/tests/extensions-pre-task.test.ts +73 -0
- package/src/tests/fetch-resolved-env.test.ts +46 -0
- package/src/tests/hang-watchdog-worker.ts +47 -0
- package/src/tests/hang-watchdog.test.ts +45 -0
- package/src/tests/hang-watchdog.ts +30 -0
- package/src/tests/harness-model-guard.test.ts +123 -0
- package/src/tests/harness-model-support.test.ts +374 -0
- package/src/tests/harness-version.test.ts +70 -3
- package/src/tests/heartbeat-checklist-config.test.ts +71 -0
- package/src/tests/heartbeat-checklist.test.ts +4 -2
- package/src/tests/heartbeat-orphan-resume.test.ts +48 -0
- package/src/tests/http-task-write-ownership.test.ts +172 -0
- package/src/tests/human-free-flag.test.ts +279 -0
- package/src/tests/human-free-oracle.ts +57 -0
- package/src/tests/human-free-reclassify.test.ts +669 -0
- package/src/tests/memory-fts-populate.test.ts +139 -0
- package/src/tests/memory-http-recall-gating.test.ts +125 -1
- package/src/tests/migration-046-budgets.test.ts +3 -3
- package/src/tests/model-catalog-migration.test.ts +134 -0
- package/src/tests/model-catalog-table.test.ts +249 -0
- package/src/tests/model-catalog-write-access.test.ts +387 -0
- package/src/tests/model-rate-limit-windows.test.ts +19 -0
- package/src/tests/model-tier-resolution.test.ts +611 -0
- package/src/tests/models-catalog.test.ts +1 -1
- package/src/tests/multi-runtime-enabled-stats.test.ts +65 -1
- package/src/tests/opencode-adapter.test.ts +157 -2
- package/src/tests/package-publish.test.ts +137 -36
- package/src/tests/pi-codemode.test.ts +246 -0
- package/src/tests/pi-mono-adapter.test.ts +3 -0
- package/src/tests/pi-native-mcp.test.ts +193 -0
- package/src/tests/pi-tool-exposure.test.ts +374 -0
- package/src/tests/preload.ts +3 -0
- package/src/tests/pricing-routes.test.ts +2 -2
- package/src/tests/prompt-template-session.test.ts +5 -3
- package/src/tests/rate-limit-event.test.ts +65 -0
- package/src/tests/rate-limit-outcome.test.ts +90 -0
- package/src/tests/rbac-engine.test.ts +77 -3
- package/src/tests/reasoning-effort.test.ts +109 -0
- package/src/tests/refresh-modelsdev-carryforward.test.ts +5 -5
- package/src/tests/runner-key-completion-outcome.test.ts +112 -0
- package/src/tests/runner-key-outcome-late-reset.test.ts +224 -0
- package/src/tests/runner-registration-retry.test.ts +149 -0
- package/src/tests/runtime-model-catalog.test.ts +86 -0
- package/src/tests/script-connections.test.ts +9 -0
- package/src/tests/seat-mismatch-report.test.ts +85 -0
- package/src/tests/seed-scripts.test.ts +138 -0
- package/src/tests/seed.test.ts +25 -0
- package/src/tests/session-costs.test.ts +14 -11
- package/src/tests/slack-message-text.test.ts +101 -0
- package/src/tests/slack-render-v2.test.ts +96 -0
- package/src/tests/slack-session-status.test.ts +626 -0
- package/src/tests/slack-thread-buffer-context.test.ts +93 -0
- package/src/tests/status.test.ts +29 -0
- package/src/tests/steering-promotion.test.ts +51 -0
- package/src/tests/store-progress-ownership.test.ts +136 -0
- package/src/tests/subscription-plans.test.ts +28 -0
- package/src/tests/task-cascade-fail.test.ts +148 -2
- package/src/tests/task-citations.test.ts +3 -2
- package/src/tests/tool-annotations.test.ts +1 -1
- package/src/tests/usage-cache.test.ts +166 -0
- package/src/tests/workflow-agent-task.test.ts +30 -0
- package/src/tests/workflow-executors.test.ts +5 -2
- package/src/tests/workflow-system-one-decision-review.test.ts +1021 -0
- package/src/tests/workflow-system-one-decision-save-warnings.test.ts +365 -0
- package/src/tests/workflow-system-one-decision.test.ts +2063 -0
- package/src/tests/workflow-triggers-v2.test.ts +320 -0
- package/src/tools/model-catalog/index.ts +137 -0
- package/src/tools/schedules/create-schedule.ts +17 -2
- package/src/tools/schedules/patch-schedule.ts +31 -1
- package/src/tools/schedules/update-schedule.ts +31 -1
- package/src/tools/send-task.ts +18 -1
- package/src/tools/store-progress.ts +49 -4
- package/src/tools/task-action.ts +14 -1
- package/src/tools/tool-config.ts +3 -1
- package/src/tools/workflows/create-workflow.ts +17 -4
- package/src/tools/workflows/patch-workflow-node.ts +17 -7
- package/src/tools/workflows/patch-workflow.ts +9 -2
- package/src/tools/workflows/update-workflow.ts +17 -4
- package/src/types.ts +41 -1
- package/src/utils/codex-auth-failure.ts +34 -0
- package/src/utils/context-window.ts +47 -53
- package/src/utils/credentials.ts +72 -30
- package/src/utils/error-tracker.ts +80 -0
- package/src/utils/harness-cli-version.ts +115 -0
- package/src/utils/harness-model-error.ts +33 -0
- package/src/utils/model-rate-limit-windows.ts +12 -0
- package/src/utils/runtime-model-catalog.ts +152 -0
- package/src/utils/spawn-model-guard.ts +43 -0
- package/src/utils/subscription-plans.ts +22 -0
- package/src/workflows/approval-resolution.ts +39 -0
- package/src/workflows/definition.ts +7 -0
- package/src/workflows/engine.ts +69 -1
- package/src/workflows/executors/agent-task.ts +16 -6
- package/src/workflows/executors/base.ts +53 -0
- package/src/workflows/executors/human-in-the-loop.ts +8 -8
- package/src/workflows/executors/index.ts +1 -0
- package/src/workflows/executors/registry.ts +2 -0
- package/src/workflows/executors/system-one-decision.ts +1232 -0
- package/src/workflows/executors/system-one-providers.ts +301 -0
- package/src/workflows/executors/workflow-llm.ts +13 -1
- package/src/workflows/model-validation.ts +45 -0
- package/src/workflows/patch-definition.ts +5 -0
- package/src/workflows/readiness.ts +86 -0
- package/src/workflows/recovery.ts +12 -12
- package/src/workflows/resume.ts +23 -9
- package/src/workflows/triggers.ts +85 -0
- package/templates/schedules/daily-blocker-digest/content.md +4 -5
- package/templates/skills/agent-browser/SKILL.md +6 -5
- package/templates/skills/agent-browser/content.md +6 -5
- package/templates/skills/heartbeat-runbook/config.json +1 -1
- package/templates/skills/heartbeat-runbook/content.md +2 -2
- package/templates/skills/swarm-scripts/SKILL.md +1 -1
- package/templates/skills/swarm-scripts/content.md +1 -1
- package/templates/skills/workflow-iterate/content.md +82 -1
- package/templates/workflows/claude-code-changelog-watch/content.md +2 -0
- package/templates/workflows/pr-review-status-sweep/content.md +2 -0
- package/dist/boot-seeds-s3q01xj3.js +0 -26
- package/dist/claude-sdk-session-t442qz6f.js +0 -39108
- package/dist/cli-0xjkj1j7.js +0 -61
- package/dist/cli-20cj37vt.js +0 -335561
- package/dist/cli-2djtr51b.js +0 -48
- package/dist/cli-65hjmev5.js +0 -1141
- package/dist/cli-aw1jwp1r.js +0 -14075
- package/dist/cli-h967nb6r.js +0 -6603
- package/dist/cli-vapyk8sw.js +0 -20
- package/dist/cli-ws6rqycm.js +0 -247
- package/dist/pricing-refresh-v1cbr9te.js +0 -27
- package/src/providers/modelsdev-reasoning.json +0 -6453
- package/dist/{index-f24115ge.js → index-2wsdsnmm.js} +3 -3
|
@@ -9,9 +9,17 @@ import {
|
|
|
9
9
|
import {
|
|
10
10
|
getApiKey
|
|
11
11
|
} from "./cli-f14fvzag.js";
|
|
12
|
+
import {
|
|
13
|
+
DEFAULT_MODEL,
|
|
14
|
+
resolveCredential
|
|
15
|
+
} from "./cli-12tszpk9.js";
|
|
16
|
+
import {
|
|
17
|
+
DEFAULT_OPENROUTER_BASE_URL,
|
|
18
|
+
getOpenRouterBaseUrl
|
|
19
|
+
} from "./cli-3dpj7atn.js";
|
|
12
20
|
import {
|
|
13
21
|
embedScript
|
|
14
|
-
} from "./cli-
|
|
22
|
+
} from "./cli-0jwe9034.js";
|
|
15
23
|
import {
|
|
16
24
|
calculatePKCECodeChallenge,
|
|
17
25
|
ensureAuthorizationTokenOrThrow,
|
|
@@ -23,11 +31,17 @@ import {
|
|
|
23
31
|
oauthAppRowToProviderConfig,
|
|
24
32
|
updateAuthorizationTokens,
|
|
25
33
|
upsertAuthorization
|
|
26
|
-
} from "./cli-
|
|
34
|
+
} from "./cli-6cs6wzxt.js";
|
|
35
|
+
import {
|
|
36
|
+
getSlackApp
|
|
37
|
+
} from "./cli-azhgzetg.js";
|
|
27
38
|
import {
|
|
28
39
|
CredentialBroker,
|
|
29
40
|
DEFAULT_CREDENTIAL_BINDINGS,
|
|
41
|
+
claimApprovalCancellationNotification,
|
|
42
|
+
completeApprovalCancellationNotificationClaim,
|
|
30
43
|
computeContentHash,
|
|
44
|
+
createTaskExtended,
|
|
31
45
|
decryptSecret,
|
|
32
46
|
encryptSecret,
|
|
33
47
|
getDb,
|
|
@@ -36,18 +50,30 @@ import {
|
|
|
36
50
|
getLeadAgent,
|
|
37
51
|
getMcpServerById,
|
|
38
52
|
getResolvedConfig,
|
|
53
|
+
getTaskById,
|
|
39
54
|
init_credential_broker,
|
|
40
55
|
init_crypto,
|
|
41
56
|
init_date_utils,
|
|
42
57
|
init_db,
|
|
43
58
|
normalizeDateRequired,
|
|
44
59
|
placeholderForConfigKey,
|
|
60
|
+
releaseApprovalCancellationNotificationClaim,
|
|
45
61
|
upsertSwarmConfig
|
|
46
|
-
} from "./cli-
|
|
62
|
+
} from "./cli-qydf22qq.js";
|
|
47
63
|
import {
|
|
64
|
+
TERMINAL_TASK_STATUSES,
|
|
48
65
|
defaultAssetKey,
|
|
49
|
-
init_key
|
|
50
|
-
|
|
66
|
+
init_key,
|
|
67
|
+
init_types
|
|
68
|
+
} from "./cli-ktmyrtpn.js";
|
|
69
|
+
import {
|
|
70
|
+
init_resolver,
|
|
71
|
+
resolveTemplate
|
|
72
|
+
} from "./cli-ptr8h7kp.js";
|
|
73
|
+
import {
|
|
74
|
+
getAppUrl,
|
|
75
|
+
init_constants
|
|
76
|
+
} from "./cli-dv6cdjs2.js";
|
|
51
77
|
import {
|
|
52
78
|
init_env_flag,
|
|
53
79
|
isEnvFlagEnabled
|
|
@@ -351,8 +377,8 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
351
377
|
}
|
|
352
378
|
|
|
353
379
|
class InvalidUnitError extends LuxonError {
|
|
354
|
-
constructor(
|
|
355
|
-
super(`Invalid unit ${
|
|
380
|
+
constructor(unit2) {
|
|
381
|
+
super(`Invalid unit ${unit2}`);
|
|
356
382
|
}
|
|
357
383
|
}
|
|
358
384
|
|
|
@@ -981,16 +1007,16 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
981
1007
|
this.rtf = getCachedRTF(intl, opts);
|
|
982
1008
|
}
|
|
983
1009
|
}
|
|
984
|
-
format(count,
|
|
1010
|
+
format(count, unit2) {
|
|
985
1011
|
if (this.rtf) {
|
|
986
|
-
return this.rtf.format(count,
|
|
1012
|
+
return this.rtf.format(count, unit2);
|
|
987
1013
|
} else {
|
|
988
|
-
return formatRelativeTime(
|
|
1014
|
+
return formatRelativeTime(unit2, count, this.opts.numeric, this.opts.style !== "long");
|
|
989
1015
|
}
|
|
990
1016
|
}
|
|
991
|
-
formatToParts(count,
|
|
1017
|
+
formatToParts(count, unit2) {
|
|
992
1018
|
if (this.rtf) {
|
|
993
|
-
return this.rtf.formatToParts(count,
|
|
1019
|
+
return this.rtf.formatToParts(count, unit2);
|
|
994
1020
|
} else {
|
|
995
1021
|
return [];
|
|
996
1022
|
}
|
|
@@ -1459,8 +1485,8 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
1459
1485
|
}
|
|
1460
1486
|
var nonLeapLadder = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
|
|
1461
1487
|
var leapLadder = [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335];
|
|
1462
|
-
function unitOutOfRange(
|
|
1463
|
-
return new Invalid("unit out of range", `you specified ${value} (of type ${typeof value}) as a ${
|
|
1488
|
+
function unitOutOfRange(unit2, value) {
|
|
1489
|
+
return new Invalid("unit out of range", `you specified ${value} (of type ${typeof value}) as a ${unit2}, which is invalid`);
|
|
1464
1490
|
}
|
|
1465
1491
|
function dayOfWeek(year, month, day) {
|
|
1466
1492
|
const d = new Date(Date.UTC(year, month - 1, day));
|
|
@@ -1928,7 +1954,7 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
1928
1954
|
function eraForDateTime(dt, length) {
|
|
1929
1955
|
return eras(length)[dt.year < 0 ? 0 : 1];
|
|
1930
1956
|
}
|
|
1931
|
-
function formatRelativeTime(
|
|
1957
|
+
function formatRelativeTime(unit2, count, numeric = "always", narrow = false) {
|
|
1932
1958
|
const units = {
|
|
1933
1959
|
years: ["year", "yr."],
|
|
1934
1960
|
quarters: ["quarter", "qtr."],
|
|
@@ -1939,19 +1965,19 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
1939
1965
|
minutes: ["minute", "min."],
|
|
1940
1966
|
seconds: ["second", "sec."]
|
|
1941
1967
|
};
|
|
1942
|
-
const lastable = ["hours", "minutes", "seconds"].indexOf(
|
|
1968
|
+
const lastable = ["hours", "minutes", "seconds"].indexOf(unit2) === -1;
|
|
1943
1969
|
if (numeric === "auto" && lastable) {
|
|
1944
|
-
const isDay =
|
|
1970
|
+
const isDay = unit2 === "days";
|
|
1945
1971
|
switch (count) {
|
|
1946
1972
|
case 1:
|
|
1947
|
-
return isDay ? "tomorrow" : `next ${units[
|
|
1973
|
+
return isDay ? "tomorrow" : `next ${units[unit2][0]}`;
|
|
1948
1974
|
case -1:
|
|
1949
|
-
return isDay ? "yesterday" : `last ${units[
|
|
1975
|
+
return isDay ? "yesterday" : `last ${units[unit2][0]}`;
|
|
1950
1976
|
case 0:
|
|
1951
|
-
return isDay ? "today" : `this ${units[
|
|
1977
|
+
return isDay ? "today" : `this ${units[unit2][0]}`;
|
|
1952
1978
|
}
|
|
1953
1979
|
}
|
|
1954
|
-
const isInPast = Object.is(count, -0) || count < 0, fmtValue = Math.abs(count), singular = fmtValue === 1, lilUnits = units[
|
|
1980
|
+
const isInPast = Object.is(count, -0) || count < 0, fmtValue = Math.abs(count), singular = fmtValue === 1, lilUnits = units[unit2], fmtUnit = narrow ? singular ? lilUnits[1] : lilUnits[2] || lilUnits[1] : singular ? units[unit2][0] : unit2;
|
|
1955
1981
|
return isInPast ? `${fmtValue} ${fmtUnit} ago` : `in ${fmtValue} ${fmtUnit}`;
|
|
1956
1982
|
}
|
|
1957
1983
|
function stringifyTokens(splits, tokenToString) {
|
|
@@ -2612,9 +2638,9 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
2612
2638
|
function durationToMillis(matrix, vals) {
|
|
2613
2639
|
var _vals$milliseconds;
|
|
2614
2640
|
let sum = (_vals$milliseconds = vals.milliseconds) != null ? _vals$milliseconds : 0;
|
|
2615
|
-
for (const
|
|
2616
|
-
if (vals[
|
|
2617
|
-
sum += vals[
|
|
2641
|
+
for (const unit2 of reverseUnits.slice(1)) {
|
|
2642
|
+
if (vals[unit2]) {
|
|
2643
|
+
sum += vals[unit2] * matrix[unit2]["milliseconds"];
|
|
2618
2644
|
}
|
|
2619
2645
|
}
|
|
2620
2646
|
return sum;
|
|
@@ -2728,7 +2754,7 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
2728
2754
|
});
|
|
2729
2755
|
}
|
|
2730
2756
|
}
|
|
2731
|
-
static normalizeUnit(
|
|
2757
|
+
static normalizeUnit(unit2) {
|
|
2732
2758
|
const normalized = {
|
|
2733
2759
|
year: "years",
|
|
2734
2760
|
years: "years",
|
|
@@ -2748,9 +2774,9 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
2748
2774
|
seconds: "seconds",
|
|
2749
2775
|
millisecond: "milliseconds",
|
|
2750
2776
|
milliseconds: "milliseconds"
|
|
2751
|
-
}[
|
|
2777
|
+
}[unit2 ? unit2.toLowerCase() : unit2];
|
|
2752
2778
|
if (!normalized)
|
|
2753
|
-
throw new InvalidUnitError(
|
|
2779
|
+
throw new InvalidUnitError(unit2);
|
|
2754
2780
|
return normalized;
|
|
2755
2781
|
}
|
|
2756
2782
|
static isDuration(o) {
|
|
@@ -2773,8 +2799,8 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
2773
2799
|
if (!this.isValid)
|
|
2774
2800
|
return INVALID$2;
|
|
2775
2801
|
const showZeros = opts.showZeros !== false;
|
|
2776
|
-
const l2 = orderedUnits$1.map((
|
|
2777
|
-
const val = this.values[
|
|
2802
|
+
const l2 = orderedUnits$1.map((unit2) => {
|
|
2803
|
+
const val = this.values[unit2];
|
|
2778
2804
|
if (isUndefined(val) || val === 0 && !showZeros) {
|
|
2779
2805
|
return null;
|
|
2780
2806
|
}
|
|
@@ -2782,7 +2808,7 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
2782
2808
|
style: "unit",
|
|
2783
2809
|
unitDisplay: "long",
|
|
2784
2810
|
...opts,
|
|
2785
|
-
unit:
|
|
2811
|
+
unit: unit2.slice(0, -1)
|
|
2786
2812
|
}).format(val);
|
|
2787
2813
|
}).filter((n2) => n2);
|
|
2788
2814
|
return this.loc.listFormatter({
|
|
@@ -2892,8 +2918,8 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
2892
2918
|
values: result
|
|
2893
2919
|
}, true);
|
|
2894
2920
|
}
|
|
2895
|
-
get(
|
|
2896
|
-
return this[Duration.normalizeUnit(
|
|
2921
|
+
get(unit2) {
|
|
2922
|
+
return this[Duration.normalizeUnit(unit2)];
|
|
2897
2923
|
}
|
|
2898
2924
|
set(values) {
|
|
2899
2925
|
if (!this.isValid)
|
|
@@ -2923,8 +2949,8 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
2923
2949
|
};
|
|
2924
2950
|
return clone$1(this, opts);
|
|
2925
2951
|
}
|
|
2926
|
-
as(
|
|
2927
|
-
return this.isValid ? this.shiftTo(
|
|
2952
|
+
as(unit2) {
|
|
2953
|
+
return this.isValid ? this.shiftTo(unit2).get(unit2) : NaN;
|
|
2928
2954
|
}
|
|
2929
2955
|
normalize() {
|
|
2930
2956
|
if (!this.isValid)
|
|
@@ -3168,13 +3194,13 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
3168
3194
|
get invalidExplanation() {
|
|
3169
3195
|
return this.invalid ? this.invalid.explanation : null;
|
|
3170
3196
|
}
|
|
3171
|
-
length(
|
|
3172
|
-
return this.isValid ? this.toDuration(...[
|
|
3197
|
+
length(unit2 = "milliseconds") {
|
|
3198
|
+
return this.isValid ? this.toDuration(...[unit2]).get(unit2) : NaN;
|
|
3173
3199
|
}
|
|
3174
|
-
count(
|
|
3200
|
+
count(unit2 = "milliseconds", opts) {
|
|
3175
3201
|
if (!this.isValid)
|
|
3176
3202
|
return NaN;
|
|
3177
|
-
const start = this.start.startOf(
|
|
3203
|
+
const start = this.start.startOf(unit2, opts);
|
|
3178
3204
|
let end;
|
|
3179
3205
|
if (opts != null && opts.useLocaleWeeks) {
|
|
3180
3206
|
end = this.end.reconfigure({
|
|
@@ -3183,11 +3209,11 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
3183
3209
|
} else {
|
|
3184
3210
|
end = this.end;
|
|
3185
3211
|
}
|
|
3186
|
-
end = end.startOf(
|
|
3187
|
-
return Math.floor(end.diff(start,
|
|
3212
|
+
end = end.startOf(unit2, opts);
|
|
3213
|
+
return Math.floor(end.diff(start, unit2).get(unit2)) + (end.valueOf() !== this.end.valueOf());
|
|
3188
3214
|
}
|
|
3189
|
-
hasSame(
|
|
3190
|
-
return this.isValid ? this.isEmpty() || this.e.minus(1).hasSame(this.s,
|
|
3215
|
+
hasSame(unit2) {
|
|
3216
|
+
return this.isValid ? this.isEmpty() || this.e.minus(1).hasSame(this.s, unit2) : false;
|
|
3191
3217
|
}
|
|
3192
3218
|
isEmpty() {
|
|
3193
3219
|
return this.s.valueOf() === this.e.valueOf();
|
|
@@ -3370,11 +3396,11 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
3370
3396
|
return INVALID$1;
|
|
3371
3397
|
return `${this.s.toFormat(dateFormat)}${separator}${this.e.toFormat(dateFormat)}`;
|
|
3372
3398
|
}
|
|
3373
|
-
toDuration(
|
|
3399
|
+
toDuration(unit2, opts) {
|
|
3374
3400
|
if (!this.isValid) {
|
|
3375
3401
|
return Duration.invalid(this.invalidReason);
|
|
3376
3402
|
}
|
|
3377
|
-
return this.e.diff(this.s,
|
|
3403
|
+
return this.e.diff(this.s, unit2, opts);
|
|
3378
3404
|
}
|
|
3379
3405
|
mapEndpoints(mapFn) {
|
|
3380
3406
|
return Interval.fromDateTimes(mapFn(this.s), mapFn(this.e));
|
|
@@ -3475,17 +3501,17 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
3475
3501
|
const results = {};
|
|
3476
3502
|
const earlier = cursor;
|
|
3477
3503
|
let lowestOrder, highWater;
|
|
3478
|
-
for (const [
|
|
3479
|
-
if (units.indexOf(
|
|
3480
|
-
lowestOrder =
|
|
3481
|
-
results[
|
|
3504
|
+
for (const [unit2, differ] of differs) {
|
|
3505
|
+
if (units.indexOf(unit2) >= 0) {
|
|
3506
|
+
lowestOrder = unit2;
|
|
3507
|
+
results[unit2] = differ(cursor, later);
|
|
3482
3508
|
highWater = earlier.plus(results);
|
|
3483
3509
|
if (highWater > later) {
|
|
3484
|
-
results[
|
|
3510
|
+
results[unit2]--;
|
|
3485
3511
|
cursor = earlier.plus(results);
|
|
3486
3512
|
if (cursor > later) {
|
|
3487
3513
|
highWater = cursor;
|
|
3488
|
-
results[
|
|
3514
|
+
results[unit2]--;
|
|
3489
3515
|
cursor = earlier.plus(results);
|
|
3490
3516
|
}
|
|
3491
3517
|
} else {
|
|
@@ -3670,11 +3696,11 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
3670
3696
|
return literal2(t);
|
|
3671
3697
|
}
|
|
3672
3698
|
};
|
|
3673
|
-
const
|
|
3699
|
+
const unit2 = unitate(token) || {
|
|
3674
3700
|
invalidReason: MISSING_FTP
|
|
3675
3701
|
};
|
|
3676
|
-
|
|
3677
|
-
return
|
|
3702
|
+
unit2.token = token;
|
|
3703
|
+
return unit2;
|
|
3678
3704
|
}
|
|
3679
3705
|
var partTypeStyleToTokenVal = {
|
|
3680
3706
|
year: {
|
|
@@ -4152,7 +4178,7 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
4152
4178
|
var orderedUnits = ["year", "month", "day", "hour", "minute", "second", "millisecond"];
|
|
4153
4179
|
var orderedWeekUnits = ["weekYear", "weekNumber", "weekday", "hour", "minute", "second", "millisecond"];
|
|
4154
4180
|
var orderedOrdinalUnits = ["year", "ordinal", "hour", "minute", "second", "millisecond"];
|
|
4155
|
-
function normalizeUnit(
|
|
4181
|
+
function normalizeUnit(unit2) {
|
|
4156
4182
|
const normalized = {
|
|
4157
4183
|
year: "year",
|
|
4158
4184
|
years: "year",
|
|
@@ -4178,13 +4204,13 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
4178
4204
|
weekyear: "weekYear",
|
|
4179
4205
|
weekyears: "weekYear",
|
|
4180
4206
|
ordinal: "ordinal"
|
|
4181
|
-
}[
|
|
4207
|
+
}[unit2.toLowerCase()];
|
|
4182
4208
|
if (!normalized)
|
|
4183
|
-
throw new InvalidUnitError(
|
|
4209
|
+
throw new InvalidUnitError(unit2);
|
|
4184
4210
|
return normalized;
|
|
4185
4211
|
}
|
|
4186
|
-
function normalizeUnitWithLocalWeeks(
|
|
4187
|
-
switch (
|
|
4212
|
+
function normalizeUnitWithLocalWeeks(unit2) {
|
|
4213
|
+
switch (unit2.toLowerCase()) {
|
|
4188
4214
|
case "localweekday":
|
|
4189
4215
|
case "localweekdays":
|
|
4190
4216
|
return "localWeekday";
|
|
@@ -4195,7 +4221,7 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
4195
4221
|
case "localweekyears":
|
|
4196
4222
|
return "localWeekYear";
|
|
4197
4223
|
default:
|
|
4198
|
-
return normalizeUnit(
|
|
4224
|
+
return normalizeUnit(unit2);
|
|
4199
4225
|
}
|
|
4200
4226
|
}
|
|
4201
4227
|
function guessOffsetForZone(zone) {
|
|
@@ -4243,27 +4269,27 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
4243
4269
|
});
|
|
4244
4270
|
}
|
|
4245
4271
|
function diffRelative(start, end, opts) {
|
|
4246
|
-
const round = isUndefined(opts.round) ? true : opts.round, rounding = isUndefined(opts.rounding) ? "trunc" : opts.rounding, format = (c,
|
|
4272
|
+
const round = isUndefined(opts.round) ? true : opts.round, rounding = isUndefined(opts.rounding) ? "trunc" : opts.rounding, format = (c, unit2) => {
|
|
4247
4273
|
c = roundTo(c, round || opts.calendary ? 0 : 2, opts.calendary ? "round" : rounding);
|
|
4248
4274
|
const formatter = end.loc.clone(opts).relFormatter(opts);
|
|
4249
|
-
return formatter.format(c,
|
|
4250
|
-
}, differ = (
|
|
4275
|
+
return formatter.format(c, unit2);
|
|
4276
|
+
}, differ = (unit2) => {
|
|
4251
4277
|
if (opts.calendary) {
|
|
4252
|
-
if (!end.hasSame(start,
|
|
4253
|
-
return end.startOf(
|
|
4278
|
+
if (!end.hasSame(start, unit2)) {
|
|
4279
|
+
return end.startOf(unit2).diff(start.startOf(unit2), unit2).get(unit2);
|
|
4254
4280
|
} else
|
|
4255
4281
|
return 0;
|
|
4256
4282
|
} else {
|
|
4257
|
-
return end.diff(start,
|
|
4283
|
+
return end.diff(start, unit2).get(unit2);
|
|
4258
4284
|
}
|
|
4259
4285
|
};
|
|
4260
4286
|
if (opts.unit) {
|
|
4261
4287
|
return format(differ(opts.unit), opts.unit);
|
|
4262
4288
|
}
|
|
4263
|
-
for (const
|
|
4264
|
-
const count = differ(
|
|
4289
|
+
for (const unit2 of opts.units) {
|
|
4290
|
+
const count = differ(unit2);
|
|
4265
4291
|
if (Math.abs(count) >= 1) {
|
|
4266
|
-
return format(count,
|
|
4292
|
+
return format(count, unit2);
|
|
4267
4293
|
}
|
|
4268
4294
|
}
|
|
4269
4295
|
return format(start > end ? -0 : 0, opts.units[opts.units.length - 1]);
|
|
@@ -4502,8 +4528,8 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
4502
4528
|
zoneOffsetTs = undefined;
|
|
4503
4529
|
zoneOffsetGuessCache.clear();
|
|
4504
4530
|
}
|
|
4505
|
-
get(
|
|
4506
|
-
return this[
|
|
4531
|
+
get(unit2) {
|
|
4532
|
+
return this[unit2];
|
|
4507
4533
|
}
|
|
4508
4534
|
get isValid() {
|
|
4509
4535
|
return this.invalid === null;
|
|
@@ -4789,12 +4815,12 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
4789
4815
|
const dur = Duration.fromDurationLike(duration).negate();
|
|
4790
4816
|
return clone(this, adjustTime(this, dur));
|
|
4791
4817
|
}
|
|
4792
|
-
startOf(
|
|
4818
|
+
startOf(unit2, {
|
|
4793
4819
|
useLocaleWeeks = false
|
|
4794
4820
|
} = {}) {
|
|
4795
4821
|
if (!this.isValid)
|
|
4796
4822
|
return this;
|
|
4797
|
-
const o = {}, normalizedUnit = Duration.normalizeUnit(
|
|
4823
|
+
const o = {}, normalizedUnit = Duration.normalizeUnit(unit2);
|
|
4798
4824
|
switch (normalizedUnit) {
|
|
4799
4825
|
case "years":
|
|
4800
4826
|
o.month = 1;
|
|
@@ -4832,10 +4858,10 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
4832
4858
|
}
|
|
4833
4859
|
return this.set(o);
|
|
4834
4860
|
}
|
|
4835
|
-
endOf(
|
|
4861
|
+
endOf(unit2, opts) {
|
|
4836
4862
|
return this.isValid ? this.plus({
|
|
4837
|
-
[
|
|
4838
|
-
}).startOf(
|
|
4863
|
+
[unit2]: 1
|
|
4864
|
+
}).startOf(unit2, opts).minus(1) : this;
|
|
4839
4865
|
}
|
|
4840
4866
|
toFormat(fmt, opts = {}) {
|
|
4841
4867
|
return this.isValid ? Formatter.create(this.loc.redefaultToEN(opts)).formatDateTimeFromString(this, fmt) : INVALID;
|
|
@@ -4973,7 +4999,7 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
4973
4999
|
toJSDate() {
|
|
4974
5000
|
return new Date(this.isValid ? this.ts : NaN);
|
|
4975
5001
|
}
|
|
4976
|
-
diff(otherDateTime,
|
|
5002
|
+
diff(otherDateTime, unit2 = "milliseconds", opts = {}) {
|
|
4977
5003
|
if (!this.isValid || !otherDateTime.isValid) {
|
|
4978
5004
|
return Duration.invalid("created by diffing an invalid DateTime");
|
|
4979
5005
|
}
|
|
@@ -4982,23 +5008,23 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
4982
5008
|
numberingSystem: this.numberingSystem,
|
|
4983
5009
|
...opts
|
|
4984
5010
|
};
|
|
4985
|
-
const units = maybeArray(
|
|
5011
|
+
const units = maybeArray(unit2).map(Duration.normalizeUnit), otherIsLater = otherDateTime.valueOf() > this.valueOf(), earlier = otherIsLater ? this : otherDateTime, later = otherIsLater ? otherDateTime : this, diffed = diff(earlier, later, units, durOpts);
|
|
4986
5012
|
return otherIsLater ? diffed.negate() : diffed;
|
|
4987
5013
|
}
|
|
4988
|
-
diffNow(
|
|
4989
|
-
return this.diff(DateTime.now(),
|
|
5014
|
+
diffNow(unit2 = "milliseconds", opts = {}) {
|
|
5015
|
+
return this.diff(DateTime.now(), unit2, opts);
|
|
4990
5016
|
}
|
|
4991
5017
|
until(otherDateTime) {
|
|
4992
5018
|
return this.isValid ? Interval.fromDateTimes(this, otherDateTime) : this;
|
|
4993
5019
|
}
|
|
4994
|
-
hasSame(otherDateTime,
|
|
5020
|
+
hasSame(otherDateTime, unit2, opts) {
|
|
4995
5021
|
if (!this.isValid)
|
|
4996
5022
|
return false;
|
|
4997
5023
|
const inputMs = otherDateTime.valueOf();
|
|
4998
5024
|
const adjustedToZone = this.setZone(otherDateTime.zone, {
|
|
4999
5025
|
keepLocalTime: true
|
|
5000
5026
|
});
|
|
5001
|
-
return adjustedToZone.startOf(
|
|
5027
|
+
return adjustedToZone.startOf(unit2, opts) <= inputMs && inputMs <= adjustedToZone.endOf(unit2, opts);
|
|
5002
5028
|
}
|
|
5003
5029
|
equals(other) {
|
|
5004
5030
|
return this.isValid && other.isValid && this.valueOf() === other.valueOf() && this.zone.equals(other.zone) && this.loc.equals(other.loc);
|
|
@@ -5010,16 +5036,16 @@ var require_luxon = __commonJS(function(exports) {
|
|
|
5010
5036
|
zone: this.zone
|
|
5011
5037
|
}), padding = options.padding ? this < base ? -options.padding : options.padding : 0;
|
|
5012
5038
|
let units = ["years", "months", "days", "hours", "minutes", "seconds"];
|
|
5013
|
-
let
|
|
5039
|
+
let unit2 = options.unit;
|
|
5014
5040
|
if (Array.isArray(options.unit)) {
|
|
5015
5041
|
units = options.unit;
|
|
5016
|
-
|
|
5042
|
+
unit2 = undefined;
|
|
5017
5043
|
}
|
|
5018
5044
|
return diffRelative(base, this.plus(padding), {
|
|
5019
5045
|
...options,
|
|
5020
5046
|
numeric: "always",
|
|
5021
5047
|
units,
|
|
5022
|
-
unit
|
|
5048
|
+
unit: unit2
|
|
5023
5049
|
});
|
|
5024
5050
|
}
|
|
5025
5051
|
toRelativeCalendar(options = {}) {
|
|
@@ -5309,19 +5335,19 @@ var require_CronDate = __commonJS(function(exports) {
|
|
|
5309
5335
|
subtractSecond() {
|
|
5310
5336
|
this.#date = this.#date.minus({ seconds: 1 });
|
|
5311
5337
|
}
|
|
5312
|
-
addUnit(
|
|
5313
|
-
this.#verbMap.add[
|
|
5338
|
+
addUnit(unit2) {
|
|
5339
|
+
this.#verbMap.add[unit2]();
|
|
5314
5340
|
}
|
|
5315
|
-
subtractUnit(
|
|
5316
|
-
this.#verbMap.subtract[
|
|
5341
|
+
subtractUnit(unit2) {
|
|
5342
|
+
this.#verbMap.subtract[unit2]();
|
|
5317
5343
|
}
|
|
5318
|
-
invokeDateOperation(verb,
|
|
5344
|
+
invokeDateOperation(verb, unit2) {
|
|
5319
5345
|
if (verb === DateMathOp.Add) {
|
|
5320
|
-
this.addUnit(
|
|
5346
|
+
this.addUnit(unit2);
|
|
5321
5347
|
return;
|
|
5322
5348
|
}
|
|
5323
5349
|
if (verb === DateMathOp.Subtract) {
|
|
5324
|
-
this.subtractUnit(
|
|
5350
|
+
this.subtractUnit(unit2);
|
|
5325
5351
|
return;
|
|
5326
5352
|
}
|
|
5327
5353
|
throw new Error(`Invalid verb: ${verb}`);
|
|
@@ -5430,13 +5456,13 @@ var require_CronDate = __commonJS(function(exports) {
|
|
|
5430
5456
|
}
|
|
5431
5457
|
return day > lastDay - 7;
|
|
5432
5458
|
}
|
|
5433
|
-
applyDateOperation(op,
|
|
5434
|
-
if (
|
|
5435
|
-
this.invokeDateOperation(op,
|
|
5459
|
+
applyDateOperation(op, unit2, hoursLength) {
|
|
5460
|
+
if (unit2 === TimeUnit.Month || unit2 === TimeUnit.Day) {
|
|
5461
|
+
this.invokeDateOperation(op, unit2);
|
|
5436
5462
|
return;
|
|
5437
5463
|
}
|
|
5438
5464
|
const previousHour = this.getHours();
|
|
5439
|
-
this.invokeDateOperation(op,
|
|
5465
|
+
this.invokeDateOperation(op, unit2);
|
|
5440
5466
|
const currentHour = this.getHours();
|
|
5441
5467
|
const diff = currentHour - previousHour;
|
|
5442
5468
|
if (diff === 2) {
|
|
@@ -10312,17 +10338,17 @@ var require_typescript = __commonJS(function(exports, module) {
|
|
|
10312
10338
|
}
|
|
10313
10339
|
return true;
|
|
10314
10340
|
}
|
|
10315
|
-
function
|
|
10341
|
+
function fail2(message, stackCrawlMark) {
|
|
10316
10342
|
debugger;
|
|
10317
10343
|
const e = new Error(message ? `Debug Failure. ${message}` : "Debug Failure.");
|
|
10318
10344
|
if (Error.captureStackTrace) {
|
|
10319
|
-
Error.captureStackTrace(e, stackCrawlMark ||
|
|
10345
|
+
Error.captureStackTrace(e, stackCrawlMark || fail2);
|
|
10320
10346
|
}
|
|
10321
10347
|
throw e;
|
|
10322
10348
|
}
|
|
10323
|
-
Debug2.fail =
|
|
10349
|
+
Debug2.fail = fail2;
|
|
10324
10350
|
function failBadSyntaxKind(node, message, stackCrawlMark) {
|
|
10325
|
-
return
|
|
10351
|
+
return fail2(`${message || "Unexpected node."}\r
|
|
10326
10352
|
Node ${formatSyntaxKind(node.kind)} was unexpected.`, stackCrawlMark || failBadSyntaxKind);
|
|
10327
10353
|
}
|
|
10328
10354
|
Debug2.failBadSyntaxKind = failBadSyntaxKind;
|
|
@@ -10333,38 +10359,38 @@ Node ${formatSyntaxKind(node.kind)} was unexpected.`, stackCrawlMark || failBadS
|
|
|
10333
10359
|
message += `\r
|
|
10334
10360
|
Verbose Debug Information: ` + (typeof verboseDebugInfo === "string" ? verboseDebugInfo : verboseDebugInfo());
|
|
10335
10361
|
}
|
|
10336
|
-
|
|
10362
|
+
fail2(message, stackCrawlMark || assert);
|
|
10337
10363
|
}
|
|
10338
10364
|
}
|
|
10339
10365
|
Debug2.assert = assert;
|
|
10340
10366
|
function assertEqual(a, b, msg, msg2, stackCrawlMark) {
|
|
10341
10367
|
if (a !== b) {
|
|
10342
10368
|
const message = msg ? msg2 ? `${msg} ${msg2}` : msg : "";
|
|
10343
|
-
|
|
10369
|
+
fail2(`Expected ${a} === ${b}. ${message}`, stackCrawlMark || assertEqual);
|
|
10344
10370
|
}
|
|
10345
10371
|
}
|
|
10346
10372
|
Debug2.assertEqual = assertEqual;
|
|
10347
10373
|
function assertLessThan(a, b, msg, stackCrawlMark) {
|
|
10348
10374
|
if (a >= b) {
|
|
10349
|
-
|
|
10375
|
+
fail2(`Expected ${a} < ${b}. ${msg || ""}`, stackCrawlMark || assertLessThan);
|
|
10350
10376
|
}
|
|
10351
10377
|
}
|
|
10352
10378
|
Debug2.assertLessThan = assertLessThan;
|
|
10353
10379
|
function assertLessThanOrEqual(a, b, stackCrawlMark) {
|
|
10354
10380
|
if (a > b) {
|
|
10355
|
-
|
|
10381
|
+
fail2(`Expected ${a} <= ${b}`, stackCrawlMark || assertLessThanOrEqual);
|
|
10356
10382
|
}
|
|
10357
10383
|
}
|
|
10358
10384
|
Debug2.assertLessThanOrEqual = assertLessThanOrEqual;
|
|
10359
10385
|
function assertGreaterThanOrEqual(a, b, stackCrawlMark) {
|
|
10360
10386
|
if (a < b) {
|
|
10361
|
-
|
|
10387
|
+
fail2(`Expected ${a} >= ${b}`, stackCrawlMark || assertGreaterThanOrEqual);
|
|
10362
10388
|
}
|
|
10363
10389
|
}
|
|
10364
10390
|
Debug2.assertGreaterThanOrEqual = assertGreaterThanOrEqual;
|
|
10365
10391
|
function assertIsDefined(value, message, stackCrawlMark) {
|
|
10366
10392
|
if (value === undefined || value === null) {
|
|
10367
|
-
|
|
10393
|
+
fail2(message, stackCrawlMark || assertIsDefined);
|
|
10368
10394
|
}
|
|
10369
10395
|
}
|
|
10370
10396
|
Debug2.assertIsDefined = assertIsDefined;
|
|
@@ -10386,7 +10412,7 @@ Verbose Debug Information: ` + (typeof verboseDebugInfo === "string" ? verboseDe
|
|
|
10386
10412
|
Debug2.checkEachDefined = checkEachDefined;
|
|
10387
10413
|
function assertNever(member, message = "Illegal value:", stackCrawlMark) {
|
|
10388
10414
|
const detail = typeof member === "object" && hasProperty(member, "kind") && hasProperty(member, "pos") ? "SyntaxKind: " + formatSyntaxKind(member.kind) : JSON.stringify(member);
|
|
10389
|
-
return
|
|
10415
|
+
return fail2(`${message} ${detail}`, stackCrawlMark || assertNever);
|
|
10390
10416
|
}
|
|
10391
10417
|
Debug2.assertNever = assertNever;
|
|
10392
10418
|
function assertEachNode(nodes, test, message, stackCrawlMark) {
|
|
@@ -115317,30 +115343,30 @@ ${lanes.join(`
|
|
|
115317
115343
|
function getSourceFileFromReference(referencingFile, ref) {
|
|
115318
115344
|
return getSourceFileFromReferenceWorker(resolveTripleslashReference(ref.fileName, referencingFile.fileName), getSourceFile);
|
|
115319
115345
|
}
|
|
115320
|
-
function getSourceFileFromReferenceWorker(fileName, getSourceFile2,
|
|
115346
|
+
function getSourceFileFromReferenceWorker(fileName, getSourceFile2, fail2, reason) {
|
|
115321
115347
|
if (hasExtension(fileName)) {
|
|
115322
115348
|
const canonicalFileName = host.getCanonicalFileName(fileName);
|
|
115323
115349
|
if (!options.allowNonTsExtensions && !forEach(flatten(supportedExtensionsWithJsonIfResolveJsonModule), (extension) => fileExtensionIs(canonicalFileName, extension))) {
|
|
115324
|
-
if (
|
|
115350
|
+
if (fail2) {
|
|
115325
115351
|
if (hasJSFileExtension(canonicalFileName)) {
|
|
115326
|
-
|
|
115352
|
+
fail2(Diagnostics.File_0_is_a_JavaScript_file_Did_you_mean_to_enable_the_allowJs_option, fileName);
|
|
115327
115353
|
} else {
|
|
115328
|
-
|
|
115354
|
+
fail2(Diagnostics.File_0_has_an_unsupported_extension_The_only_supported_extensions_are_1, fileName, "'" + flatten(supportedExtensions).join("', '") + "'");
|
|
115329
115355
|
}
|
|
115330
115356
|
}
|
|
115331
115357
|
return;
|
|
115332
115358
|
}
|
|
115333
115359
|
const sourceFile = getSourceFile2(fileName);
|
|
115334
|
-
if (
|
|
115360
|
+
if (fail2) {
|
|
115335
115361
|
if (!sourceFile) {
|
|
115336
115362
|
const redirect = getRedirectFromSourceFile(fileName);
|
|
115337
115363
|
if (redirect == null ? undefined : redirect.outputDts) {
|
|
115338
|
-
|
|
115364
|
+
fail2(Diagnostics.Output_file_0_has_not_been_built_from_source_file_1, redirect.outputDts, fileName);
|
|
115339
115365
|
} else {
|
|
115340
|
-
|
|
115366
|
+
fail2(Diagnostics.File_0_not_found, fileName);
|
|
115341
115367
|
}
|
|
115342
115368
|
} else if (isReferencedFile(reason) && canonicalFileName === host.getCanonicalFileName(getSourceFileByPath(reason.file).fileName)) {
|
|
115343
|
-
|
|
115369
|
+
fail2(Diagnostics.A_file_cannot_have_a_reference_to_itself);
|
|
115344
115370
|
}
|
|
115345
115371
|
}
|
|
115346
115372
|
return sourceFile;
|
|
@@ -115348,13 +115374,13 @@ ${lanes.join(`
|
|
|
115348
115374
|
const sourceFileNoExtension = options.allowNonTsExtensions && getSourceFile2(fileName);
|
|
115349
115375
|
if (sourceFileNoExtension)
|
|
115350
115376
|
return sourceFileNoExtension;
|
|
115351
|
-
if (
|
|
115352
|
-
|
|
115377
|
+
if (fail2 && options.allowNonTsExtensions) {
|
|
115378
|
+
fail2(Diagnostics.File_0_not_found, fileName);
|
|
115353
115379
|
return;
|
|
115354
115380
|
}
|
|
115355
115381
|
const sourceFileWithAddedExtension = forEach(supportedExtensions[0], (extension) => getSourceFile2(fileName + extension));
|
|
115356
|
-
if (
|
|
115357
|
-
|
|
115382
|
+
if (fail2 && !sourceFileWithAddedExtension)
|
|
115383
|
+
fail2(Diagnostics.Could_not_resolve_the_path_0_with_the_extensions_Colon_1, fileName, "'" + flatten(supportedExtensions).join("', '") + "'");
|
|
115358
115384
|
return sourceFileWithAddedExtension;
|
|
115359
115385
|
}
|
|
115360
115386
|
}
|
|
@@ -175175,6 +175201,1468 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
|
|
|
175175
175201
|
} });
|
|
175176
175202
|
});
|
|
175177
175203
|
|
|
175204
|
+
// src/workflows/executors/system-one-decision.ts
|
|
175205
|
+
init_zod();
|
|
175206
|
+
init_secret_scrubber();
|
|
175207
|
+
|
|
175208
|
+
// src/workflows/executors/base.ts
|
|
175209
|
+
class BaseExecutor {
|
|
175210
|
+
deps;
|
|
175211
|
+
retryPolicy;
|
|
175212
|
+
constructor(deps) {
|
|
175213
|
+
this.deps = deps;
|
|
175214
|
+
}
|
|
175215
|
+
async checkReadiness(_nodes) {
|
|
175216
|
+
return [];
|
|
175217
|
+
}
|
|
175218
|
+
resolveApproval(_parkedOutput, _approval) {
|
|
175219
|
+
return null;
|
|
175220
|
+
}
|
|
175221
|
+
async run(input) {
|
|
175222
|
+
const configResult = this.configSchema.safeParse(input.config);
|
|
175223
|
+
if (!configResult.success) {
|
|
175224
|
+
return {
|
|
175225
|
+
status: "failed",
|
|
175226
|
+
error: `Input validation failed: ${configResult.error.message}`
|
|
175227
|
+
};
|
|
175228
|
+
}
|
|
175229
|
+
let result;
|
|
175230
|
+
try {
|
|
175231
|
+
result = await this.execute(configResult.data, input.context, input.meta);
|
|
175232
|
+
} catch (err) {
|
|
175233
|
+
return {
|
|
175234
|
+
status: "failed",
|
|
175235
|
+
error: `Executor threw: ${err instanceof Error ? err.message : String(err)}`
|
|
175236
|
+
};
|
|
175237
|
+
}
|
|
175238
|
+
if (result.status === "success" && result.output !== undefined) {
|
|
175239
|
+
const outputResult = this.outputSchema.safeParse(result.output);
|
|
175240
|
+
if (!outputResult.success) {
|
|
175241
|
+
return {
|
|
175242
|
+
status: "failed",
|
|
175243
|
+
error: `Output validation failed: ${outputResult.error.message}`
|
|
175244
|
+
};
|
|
175245
|
+
}
|
|
175246
|
+
}
|
|
175247
|
+
return result;
|
|
175248
|
+
}
|
|
175249
|
+
}
|
|
175250
|
+
|
|
175251
|
+
// src/workflows/executors/human-in-the-loop.ts
|
|
175252
|
+
init_zod();
|
|
175253
|
+
init_constants();
|
|
175254
|
+
init_secret_scrubber();
|
|
175255
|
+
|
|
175256
|
+
// src/workflows/approval-notifications.ts
|
|
175257
|
+
init_db();
|
|
175258
|
+
init_resolver();
|
|
175259
|
+
init_types();
|
|
175260
|
+
init_secret_scrubber();
|
|
175261
|
+
async function postApprovalCancellationUpdates(approvals, reason, client = getSlackApp()?.client) {
|
|
175262
|
+
if (!client)
|
|
175263
|
+
return;
|
|
175264
|
+
const text = `This approval is no longer actionable: ${reason}`;
|
|
175265
|
+
for (const approval of approvals) {
|
|
175266
|
+
const channels = approval.notificationChannels;
|
|
175267
|
+
const slackThreads = (channels ?? []).filter((notification) => notification.channel === "slack" && notification.messageTs);
|
|
175268
|
+
if (slackThreads.length === 0)
|
|
175269
|
+
continue;
|
|
175270
|
+
for (const notification of slackThreads) {
|
|
175271
|
+
if (notification.channel !== "slack" || !notification.messageTs)
|
|
175272
|
+
continue;
|
|
175273
|
+
const notificationKey = `${notification.target}:${notification.messageTs}`;
|
|
175274
|
+
const claim = await claimApprovalCancellationNotification(approval.id, notificationKey);
|
|
175275
|
+
if (!claim)
|
|
175276
|
+
continue;
|
|
175277
|
+
try {
|
|
175278
|
+
await client.chat.postMessage({
|
|
175279
|
+
channel: notification.target,
|
|
175280
|
+
thread_ts: notification.messageTs,
|
|
175281
|
+
text,
|
|
175282
|
+
unfurl_links: false,
|
|
175283
|
+
unfurl_media: false
|
|
175284
|
+
});
|
|
175285
|
+
await completeApprovalCancellationNotificationClaim(approval.id, notificationKey, claim.leaseToken);
|
|
175286
|
+
} catch (error) {
|
|
175287
|
+
await releaseApprovalCancellationNotificationClaim(approval.id, notificationKey, claim.leaseToken);
|
|
175288
|
+
console.error(`[HITL] Failed to post cancellation update for approval ${approval.id}:`, scrubSecrets(error instanceof Error ? error.message : String(error)));
|
|
175289
|
+
}
|
|
175290
|
+
}
|
|
175291
|
+
}
|
|
175292
|
+
}
|
|
175293
|
+
async function createApprovalFollowUpTask(request, templateEventType) {
|
|
175294
|
+
if (request.workflowRunId || !request.sourceTaskId)
|
|
175295
|
+
return false;
|
|
175296
|
+
const sourceTask = await getTaskById(request.sourceTaskId);
|
|
175297
|
+
if (!sourceTask)
|
|
175298
|
+
return false;
|
|
175299
|
+
if (templateEventType === "hitl.timeout" && TERMINAL_TASK_STATUSES.includes(sourceTask.status)) {
|
|
175300
|
+
return false;
|
|
175301
|
+
}
|
|
175302
|
+
const { text: taskText } = templateEventType === "hitl.follow_up" ? resolveTemplate("hitl.follow_up", {
|
|
175303
|
+
request_id: request.id,
|
|
175304
|
+
title: request.title,
|
|
175305
|
+
status: request.status,
|
|
175306
|
+
responses: formatResponses(request.questions, request.responses ?? {})
|
|
175307
|
+
}) : resolveTemplate("hitl.timeout", {
|
|
175308
|
+
request_id: request.id,
|
|
175309
|
+
title: request.title,
|
|
175310
|
+
expires_at: request.expiresAt ?? "",
|
|
175311
|
+
reason: request.resolutionReason ?? ""
|
|
175312
|
+
});
|
|
175313
|
+
await createTaskExtended(taskText, {
|
|
175314
|
+
agentId: sourceTask.agentId,
|
|
175315
|
+
routingReason: sourceTask.agentId ? "continuity" : undefined,
|
|
175316
|
+
routingSource: sourceTask.agentId ? "engine_default" : undefined,
|
|
175317
|
+
parentTaskId: request.sourceTaskId,
|
|
175318
|
+
source: "system",
|
|
175319
|
+
taskType: "hitl-follow-up",
|
|
175320
|
+
tags: ["hitl", "follow-up"],
|
|
175321
|
+
slackChannelId: sourceTask.slackChannelId ?? undefined,
|
|
175322
|
+
slackThreadTs: sourceTask.slackThreadTs ?? undefined,
|
|
175323
|
+
slackUserId: sourceTask.slackUserId ?? undefined
|
|
175324
|
+
});
|
|
175325
|
+
return true;
|
|
175326
|
+
}
|
|
175327
|
+
function formatResponses(questions, responses) {
|
|
175328
|
+
return questions.map((q) => {
|
|
175329
|
+
const answer = responses[q.id];
|
|
175330
|
+
let answerText;
|
|
175331
|
+
if (answer == null) {
|
|
175332
|
+
answerText = "(no answer)";
|
|
175333
|
+
} else if (q.type === "approval") {
|
|
175334
|
+
const a = answer;
|
|
175335
|
+
answerText = a.approved ? "Approved" : "Rejected";
|
|
175336
|
+
if (a.comment)
|
|
175337
|
+
answerText += ` — ${a.comment}`;
|
|
175338
|
+
} else if (typeof answer === "object") {
|
|
175339
|
+
answerText = JSON.stringify(answer);
|
|
175340
|
+
} else {
|
|
175341
|
+
answerText = String(answer);
|
|
175342
|
+
}
|
|
175343
|
+
return `- ${q.label}: ${answerText}`;
|
|
175344
|
+
}).join(`
|
|
175345
|
+
`);
|
|
175346
|
+
}
|
|
175347
|
+
|
|
175348
|
+
// src/workflows/executors/human-in-the-loop.ts
|
|
175349
|
+
var SelectOptionSchema = exports_external.object({
|
|
175350
|
+
value: exports_external.string(),
|
|
175351
|
+
label: exports_external.string(),
|
|
175352
|
+
description: exports_external.string().optional()
|
|
175353
|
+
});
|
|
175354
|
+
var QuestionSchema = exports_external.discriminatedUnion("type", [
|
|
175355
|
+
exports_external.object({
|
|
175356
|
+
id: exports_external.string(),
|
|
175357
|
+
type: exports_external.literal("approval"),
|
|
175358
|
+
label: exports_external.string(),
|
|
175359
|
+
required: exports_external.boolean().default(true),
|
|
175360
|
+
description: exports_external.string().optional()
|
|
175361
|
+
}),
|
|
175362
|
+
exports_external.object({
|
|
175363
|
+
id: exports_external.string(),
|
|
175364
|
+
type: exports_external.literal("text"),
|
|
175365
|
+
label: exports_external.string(),
|
|
175366
|
+
required: exports_external.boolean().default(true),
|
|
175367
|
+
description: exports_external.string().optional(),
|
|
175368
|
+
placeholder: exports_external.string().optional(),
|
|
175369
|
+
multiline: exports_external.boolean().optional()
|
|
175370
|
+
}),
|
|
175371
|
+
exports_external.object({
|
|
175372
|
+
id: exports_external.string(),
|
|
175373
|
+
type: exports_external.literal("single-select"),
|
|
175374
|
+
label: exports_external.string(),
|
|
175375
|
+
required: exports_external.boolean().default(true),
|
|
175376
|
+
description: exports_external.string().optional(),
|
|
175377
|
+
options: exports_external.array(SelectOptionSchema)
|
|
175378
|
+
}),
|
|
175379
|
+
exports_external.object({
|
|
175380
|
+
id: exports_external.string(),
|
|
175381
|
+
type: exports_external.literal("multi-select"),
|
|
175382
|
+
label: exports_external.string(),
|
|
175383
|
+
required: exports_external.boolean().default(true),
|
|
175384
|
+
description: exports_external.string().optional(),
|
|
175385
|
+
options: exports_external.array(SelectOptionSchema),
|
|
175386
|
+
minSelections: exports_external.number().int().min(0).optional(),
|
|
175387
|
+
maxSelections: exports_external.number().int().min(1).optional()
|
|
175388
|
+
}),
|
|
175389
|
+
exports_external.object({
|
|
175390
|
+
id: exports_external.string(),
|
|
175391
|
+
type: exports_external.literal("boolean"),
|
|
175392
|
+
label: exports_external.string(),
|
|
175393
|
+
required: exports_external.boolean().default(true),
|
|
175394
|
+
description: exports_external.string().optional(),
|
|
175395
|
+
defaultValue: exports_external.boolean().optional()
|
|
175396
|
+
})
|
|
175397
|
+
]);
|
|
175398
|
+
var ApproverConfigSchema = exports_external.object({
|
|
175399
|
+
users: exports_external.array(exports_external.string()).optional(),
|
|
175400
|
+
roles: exports_external.array(exports_external.string()).optional(),
|
|
175401
|
+
policy: exports_external.union([exports_external.literal("any"), exports_external.literal("all"), exports_external.object({ min: exports_external.number().int().min(1) })])
|
|
175402
|
+
});
|
|
175403
|
+
var NotificationConfigSchema = exports_external.object({
|
|
175404
|
+
channel: exports_external.enum(["slack", "email"]),
|
|
175405
|
+
target: exports_external.string()
|
|
175406
|
+
});
|
|
175407
|
+
var HITLTimeoutSchema = exports_external.object({
|
|
175408
|
+
seconds: exports_external.number().int().min(1),
|
|
175409
|
+
action: exports_external.literal("reject")
|
|
175410
|
+
});
|
|
175411
|
+
var DYNAMIC_QUESTIONS_TOKEN_RE = /^\{\{[^}]+\}\}$/;
|
|
175412
|
+
var MAX_HITL_QUESTIONS = 100;
|
|
175413
|
+
var SLACK_SECTION_TEXT_LIMIT = 3000;
|
|
175414
|
+
var MAX_REPORTED_ISSUES = 5;
|
|
175415
|
+
var HITLConfigSchema = exports_external.object({
|
|
175416
|
+
title: exports_external.string(),
|
|
175417
|
+
questions: exports_external.union([
|
|
175418
|
+
exports_external.array(QuestionSchema).min(1),
|
|
175419
|
+
exports_external.string().regex(DYNAMIC_QUESTIONS_TOKEN_RE, "questions must be an array or one exact {{interpolation}} token")
|
|
175420
|
+
]),
|
|
175421
|
+
approvers: ApproverConfigSchema,
|
|
175422
|
+
timeout: HITLTimeoutSchema.optional(),
|
|
175423
|
+
notifications: exports_external.array(NotificationConfigSchema).optional()
|
|
175424
|
+
});
|
|
175425
|
+
var HITLOutputSchema = exports_external.object({
|
|
175426
|
+
requestId: exports_external.string().uuid(),
|
|
175427
|
+
status: exports_external.string(),
|
|
175428
|
+
responses: exports_external.record(exports_external.string(), exports_external.unknown()).nullable()
|
|
175429
|
+
});
|
|
175430
|
+
function resolveHitlQuestions(value) {
|
|
175431
|
+
const fail = (reason) => ({
|
|
175432
|
+
ok: false,
|
|
175433
|
+
error: `human-in-the-loop questions ${reason}`
|
|
175434
|
+
});
|
|
175435
|
+
if (typeof value === "string") {
|
|
175436
|
+
return fail(value.trim() === "" ? "resolved to an empty value: the {{token}} did not resolve (check the node's inputs mapping and the upstream output)" : "resolved to a string; they must resolve to an array of question objects (use one exact {{token}} pointing at an array)");
|
|
175437
|
+
}
|
|
175438
|
+
if (!Array.isArray(value)) {
|
|
175439
|
+
return fail(`must resolve to an array of question objects, got ${value === null ? "null" : typeof value}`);
|
|
175440
|
+
}
|
|
175441
|
+
if (value.length === 0) {
|
|
175442
|
+
return fail("resolved to an empty array; refusing to create an approval card with no questions");
|
|
175443
|
+
}
|
|
175444
|
+
if (value.length > MAX_HITL_QUESTIONS) {
|
|
175445
|
+
return fail(`resolved to ${value.length} questions, over the limit of ${MAX_HITL_QUESTIONS} per card; split or group them upstream`);
|
|
175446
|
+
}
|
|
175447
|
+
const issues = [];
|
|
175448
|
+
const questions = [];
|
|
175449
|
+
const seenIds = new Set;
|
|
175450
|
+
value.forEach((raw, index) => {
|
|
175451
|
+
const parsed = QuestionSchema.safeParse(raw);
|
|
175452
|
+
if (!parsed.success) {
|
|
175453
|
+
for (const issue of parsed.error.issues) {
|
|
175454
|
+
const path = issue.path.length > 0 ? `.${issue.path.map(String).join(".")}` : "";
|
|
175455
|
+
issues.push(`[${index}]${path}: ${issue.message}`);
|
|
175456
|
+
}
|
|
175457
|
+
return;
|
|
175458
|
+
}
|
|
175459
|
+
const question = parsed.data;
|
|
175460
|
+
if (question.id.trim() === "") {
|
|
175461
|
+
issues.push(`[${index}].id: must be a non-empty string`);
|
|
175462
|
+
} else if (seenIds.has(question.id)) {
|
|
175463
|
+
issues.push(`[${index}].id: duplicate id "${question.id}" (responses are keyed by id)`);
|
|
175464
|
+
}
|
|
175465
|
+
seenIds.add(question.id);
|
|
175466
|
+
if ((question.type === "single-select" || question.type === "multi-select") && question.options.length === 0) {
|
|
175467
|
+
issues.push(`[${index}].options: a ${question.type} question needs at least one option`);
|
|
175468
|
+
}
|
|
175469
|
+
questions.push(question);
|
|
175470
|
+
});
|
|
175471
|
+
if (issues.length > 0) {
|
|
175472
|
+
const shown = issues.slice(0, MAX_REPORTED_ISSUES).join("; ");
|
|
175473
|
+
const more = issues.length > MAX_REPORTED_ISSUES ? `; and ${issues.length - MAX_REPORTED_ISSUES} more issue(s)` : "";
|
|
175474
|
+
return fail(`are invalid: ${shown}${more}`);
|
|
175475
|
+
}
|
|
175476
|
+
return { ok: true, questions };
|
|
175477
|
+
}
|
|
175478
|
+
function escapeSlackMrkdwn(text) {
|
|
175479
|
+
return text.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
175480
|
+
}
|
|
175481
|
+
function buildSlackQuestionsSummary(questions, timeoutText = "") {
|
|
175482
|
+
const header = `*Questions:*
|
|
175483
|
+
`;
|
|
175484
|
+
const lines = questions.map((q) => `• ${escapeSlackMrkdwn(q.label.replace(/\s+/g, " ").trim())}`);
|
|
175485
|
+
const fits = (shown, omitted) => {
|
|
175486
|
+
const tail = omitted > 0 ? `
|
|
175487
|
+
_…and ${omitted} more. Answer all of them on the dashboard._` : "";
|
|
175488
|
+
const text = `${header}${shown.join(`
|
|
175489
|
+
`)}${tail}${timeoutText}`;
|
|
175490
|
+
return text.length <= SLACK_SECTION_TEXT_LIMIT ? text : null;
|
|
175491
|
+
};
|
|
175492
|
+
const full = fits(lines, 0);
|
|
175493
|
+
if (full)
|
|
175494
|
+
return full;
|
|
175495
|
+
for (let count = lines.length - 1;count >= 0; count--) {
|
|
175496
|
+
const text = fits(lines.slice(0, count), lines.length - count);
|
|
175497
|
+
if (text)
|
|
175498
|
+
return text;
|
|
175499
|
+
}
|
|
175500
|
+
return `${header}_${questions.length} questions. Answer them on the dashboard._`;
|
|
175501
|
+
}
|
|
175502
|
+
|
|
175503
|
+
class HumanInTheLoopExecutor extends BaseExecutor {
|
|
175504
|
+
type = "human-in-the-loop";
|
|
175505
|
+
mode = "async";
|
|
175506
|
+
configSchema = HITLConfigSchema;
|
|
175507
|
+
outputSchema = HITLOutputSchema;
|
|
175508
|
+
async run(input) {
|
|
175509
|
+
const resolved = resolveHitlQuestions(input.config?.questions);
|
|
175510
|
+
if (!resolved.ok)
|
|
175511
|
+
return { status: "failed", error: resolved.error };
|
|
175512
|
+
return super.run({ ...input, config: { ...input.config, questions: resolved.questions } });
|
|
175513
|
+
}
|
|
175514
|
+
async execute(config, _context, meta) {
|
|
175515
|
+
const { db } = this.deps;
|
|
175516
|
+
const existing = await db.getApprovalRequestByStepId(meta.stepId);
|
|
175517
|
+
if (existing) {
|
|
175518
|
+
if (existing.status !== "pending") {
|
|
175519
|
+
if (existing.status === "cancelled") {
|
|
175520
|
+
return {
|
|
175521
|
+
status: "failed",
|
|
175522
|
+
error: `Approval request was cancelled: ${existing.resolutionReason ?? "workflow run cancelled"}`
|
|
175523
|
+
};
|
|
175524
|
+
}
|
|
175525
|
+
const nextPort = existing.status === "timeout" ? "timeout" : existing.status === "rejected" ? "rejected" : "approved";
|
|
175526
|
+
return {
|
|
175527
|
+
status: "success",
|
|
175528
|
+
output: {
|
|
175529
|
+
requestId: existing.id,
|
|
175530
|
+
status: existing.status,
|
|
175531
|
+
responses: existing.responses
|
|
175532
|
+
},
|
|
175533
|
+
nextPort
|
|
175534
|
+
};
|
|
175535
|
+
}
|
|
175536
|
+
return {
|
|
175537
|
+
status: "success",
|
|
175538
|
+
async: true,
|
|
175539
|
+
waitFor: "approval.resolved",
|
|
175540
|
+
correlationId: existing.id
|
|
175541
|
+
};
|
|
175542
|
+
}
|
|
175543
|
+
if (!Array.isArray(config.questions)) {
|
|
175544
|
+
return { status: "failed", error: "human-in-the-loop questions did not resolve to an array" };
|
|
175545
|
+
}
|
|
175546
|
+
const requestId = crypto.randomUUID();
|
|
175547
|
+
const created = await db.createApprovalRequest({
|
|
175548
|
+
id: requestId,
|
|
175549
|
+
title: config.title,
|
|
175550
|
+
questions: config.questions,
|
|
175551
|
+
approvers: config.approvers,
|
|
175552
|
+
workflowRunId: meta.runId,
|
|
175553
|
+
workflowRunStepId: meta.stepId,
|
|
175554
|
+
timeoutSeconds: config.timeout?.seconds,
|
|
175555
|
+
notificationChannels: config.notifications,
|
|
175556
|
+
createdBy: meta.requestedByUserId,
|
|
175557
|
+
requireActionableWorkflow: true
|
|
175558
|
+
});
|
|
175559
|
+
if (created.status === "cancelled") {
|
|
175560
|
+
return {
|
|
175561
|
+
status: "success",
|
|
175562
|
+
async: true,
|
|
175563
|
+
waitFor: "approval.resolved",
|
|
175564
|
+
correlationId: requestId
|
|
175565
|
+
};
|
|
175566
|
+
}
|
|
175567
|
+
if (config.notifications?.length) {
|
|
175568
|
+
this.dispatchNotifications(requestId, config, db).catch((err) => {
|
|
175569
|
+
console.error("[HITL] Unexpected error dispatching notifications:", scrubSecrets(err instanceof Error ? err.message : String(err)));
|
|
175570
|
+
});
|
|
175571
|
+
}
|
|
175572
|
+
return {
|
|
175573
|
+
status: "success",
|
|
175574
|
+
async: true,
|
|
175575
|
+
waitFor: "approval.resolved",
|
|
175576
|
+
correlationId: requestId
|
|
175577
|
+
};
|
|
175578
|
+
}
|
|
175579
|
+
async dispatchNotifications(requestId, config, db) {
|
|
175580
|
+
if (!config.notifications?.length)
|
|
175581
|
+
return;
|
|
175582
|
+
const approvalUrl = `${getAppUrl()}/approval-requests/${requestId}`;
|
|
175583
|
+
const updatedChannels = [...config.notifications];
|
|
175584
|
+
let updated = false;
|
|
175585
|
+
for (let i = 0;i < config.notifications.length; i++) {
|
|
175586
|
+
const notification = config.notifications[i];
|
|
175587
|
+
if (notification.channel === "email") {
|
|
175588
|
+
console.warn(`[HITL] Email notifications not yet supported (target: ${notification.target})`);
|
|
175589
|
+
continue;
|
|
175590
|
+
}
|
|
175591
|
+
if (notification.channel === "slack") {
|
|
175592
|
+
try {
|
|
175593
|
+
const { getSlackApp: getSlackApp2 } = await import("./app-mc7xfagn.js");
|
|
175594
|
+
const slackApp = getSlackApp2();
|
|
175595
|
+
if (!slackApp) {
|
|
175596
|
+
console.warn("[HITL] Slack not initialized — cannot send notification");
|
|
175597
|
+
continue;
|
|
175598
|
+
}
|
|
175599
|
+
const questions = Array.isArray(config.questions) ? config.questions : [];
|
|
175600
|
+
const questionsText = buildSlackQuestionsSummary(questions);
|
|
175601
|
+
const timeoutCaption = config.timeout ? [
|
|
175602
|
+
{
|
|
175603
|
+
type: "context",
|
|
175604
|
+
elements: [
|
|
175605
|
+
{
|
|
175606
|
+
type: "mrkdwn",
|
|
175607
|
+
text: `⏱ Timeout: ${formatTimeout(config.timeout.seconds)} — times out if not responded`
|
|
175608
|
+
}
|
|
175609
|
+
]
|
|
175610
|
+
}
|
|
175611
|
+
] : [];
|
|
175612
|
+
const blocks = [
|
|
175613
|
+
{
|
|
175614
|
+
type: "section",
|
|
175615
|
+
text: {
|
|
175616
|
+
type: "mrkdwn",
|
|
175617
|
+
text: `\uD83D\uDD14 *Approval Required: ${config.title}*`
|
|
175618
|
+
}
|
|
175619
|
+
},
|
|
175620
|
+
{
|
|
175621
|
+
type: "section",
|
|
175622
|
+
text: {
|
|
175623
|
+
type: "mrkdwn",
|
|
175624
|
+
text: questionsText
|
|
175625
|
+
}
|
|
175626
|
+
},
|
|
175627
|
+
{
|
|
175628
|
+
type: "actions",
|
|
175629
|
+
elements: [
|
|
175630
|
+
{
|
|
175631
|
+
type: "button",
|
|
175632
|
+
text: { type: "plain_text", text: "Review & Respond" },
|
|
175633
|
+
url: approvalUrl,
|
|
175634
|
+
style: "primary"
|
|
175635
|
+
}
|
|
175636
|
+
]
|
|
175637
|
+
},
|
|
175638
|
+
...timeoutCaption
|
|
175639
|
+
];
|
|
175640
|
+
const result = await slackApp.client.chat.postMessage({
|
|
175641
|
+
channel: notification.target,
|
|
175642
|
+
text: `Approval Required: ${config.title} — ${approvalUrl}`,
|
|
175643
|
+
unfurl_links: false,
|
|
175644
|
+
unfurl_media: false,
|
|
175645
|
+
blocks
|
|
175646
|
+
});
|
|
175647
|
+
if (result.ts) {
|
|
175648
|
+
updatedChannels[i] = { ...notification, messageTs: result.ts };
|
|
175649
|
+
updated = true;
|
|
175650
|
+
}
|
|
175651
|
+
console.log(`[HITL] Slack notification sent to ${notification.target} for request ${requestId}`);
|
|
175652
|
+
} catch (err) {
|
|
175653
|
+
console.error(`[HITL] Failed to send Slack notification to ${notification.target}:`, scrubSecrets(err instanceof Error ? err.message : String(err)));
|
|
175654
|
+
}
|
|
175655
|
+
}
|
|
175656
|
+
}
|
|
175657
|
+
if (updated) {
|
|
175658
|
+
try {
|
|
175659
|
+
await db.updateApprovalRequestNotifications(requestId, updatedChannels);
|
|
175660
|
+
const latest = await db.getApprovalRequestById(requestId);
|
|
175661
|
+
if (latest?.status === "cancelled") {
|
|
175662
|
+
await postApprovalCancellationUpdates([latest], latest.resolutionReason ?? "Workflow run cancelled");
|
|
175663
|
+
}
|
|
175664
|
+
} catch (err) {
|
|
175665
|
+
console.error("[HITL] Failed to update notification channels in DB:", scrubSecrets(err instanceof Error ? err.message : String(err)));
|
|
175666
|
+
}
|
|
175667
|
+
}
|
|
175668
|
+
}
|
|
175669
|
+
}
|
|
175670
|
+
function formatTimeout(seconds) {
|
|
175671
|
+
if (seconds < 60)
|
|
175672
|
+
return `${seconds}s`;
|
|
175673
|
+
if (seconds < 3600)
|
|
175674
|
+
return `${Math.round(seconds / 60)}m`;
|
|
175675
|
+
const hours = Math.floor(seconds / 3600);
|
|
175676
|
+
const mins = Math.round(seconds % 3600 / 60);
|
|
175677
|
+
return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;
|
|
175678
|
+
}
|
|
175679
|
+
|
|
175680
|
+
// src/workflows/executors/workflow-llm.ts
|
|
175681
|
+
async function resolveWorkflowLlmConfig(requestedModel, env = process.env, options = {}) {
|
|
175682
|
+
const credential = await resolveCredential({ env });
|
|
175683
|
+
if (!credential) {
|
|
175684
|
+
throw new Error("No workflow LLM credential found. Set OPENROUTER_API_KEY or OPENAI_API_KEY.");
|
|
175685
|
+
}
|
|
175686
|
+
if (options.requireKind && credential.kind !== options.requireKind) {
|
|
175687
|
+
throw new Error(`No ${options.requireKind} credential found for this workflow LLM call.`);
|
|
175688
|
+
}
|
|
175689
|
+
if (credential.kind !== "openrouter" && credential.kind !== "openai") {
|
|
175690
|
+
throw new Error(`Workflow LLM nodes do not support the resolved ${credential.kind} credential yet. Set OPENROUTER_API_KEY or OPENAI_API_KEY.`);
|
|
175691
|
+
}
|
|
175692
|
+
const providerPrefix = `${credential.kind}/`;
|
|
175693
|
+
const model = requestedModel ?? DEFAULT_MODEL[credential.kind];
|
|
175694
|
+
return {
|
|
175695
|
+
apiKey: credential.apiKey,
|
|
175696
|
+
baseURL: credential.kind === "openrouter" ? getOpenRouterBaseUrl(env) : undefined,
|
|
175697
|
+
model: model.startsWith(providerPrefix) ? model.slice(providerPrefix.length) : model
|
|
175698
|
+
};
|
|
175699
|
+
}
|
|
175700
|
+
|
|
175701
|
+
// src/workflows/executors/system-one-providers.ts
|
|
175702
|
+
var TYPESAFE_KEY = "TYPESAFE_API_KEY";
|
|
175703
|
+
var OPENROUTER_KEY = "OPENROUTER_API_KEY";
|
|
175704
|
+
var LAYA_KEY = "LAYA_API_KEY";
|
|
175705
|
+
var LAYA_URL_KEY = "LAYA_URL";
|
|
175706
|
+
async function readGlobalConfig(db, key) {
|
|
175707
|
+
const rows = await db.getSwarmConfigs({ scope: "global", key });
|
|
175708
|
+
return rows.find((row) => row.scope === "global" && row.key === key)?.value;
|
|
175709
|
+
}
|
|
175710
|
+
var SYSTEM_ONE_PROVIDERS = {
|
|
175711
|
+
typesafe: {
|
|
175712
|
+
label: "TypeSafe",
|
|
175713
|
+
keyName: TYPESAFE_KEY,
|
|
175714
|
+
endpoint: "https://api.typesafe.ai/v1/systemone",
|
|
175715
|
+
defaultModel: "jev-latest",
|
|
175716
|
+
confidenceField: "confidence",
|
|
175717
|
+
readKey: ({ db }) => readGlobalConfig(db, TYPESAFE_KEY)
|
|
175718
|
+
},
|
|
175719
|
+
openrouter: {
|
|
175720
|
+
label: "OpenRouter",
|
|
175721
|
+
keyName: OPENROUTER_KEY,
|
|
175722
|
+
endpoint: "https://openrouter.ai/api/alpha/decisions",
|
|
175723
|
+
defaultModel: "~typesafe/jev-latest",
|
|
175724
|
+
confidenceField: "confidence",
|
|
175725
|
+
deploymentProblem(env) {
|
|
175726
|
+
return getOpenRouterBaseUrl(env) === DEFAULT_OPENROUTER_BASE_URL ? null : 'OPENROUTER_BASE_URL points at a gateway. SystemOne provider "openrouter" calls openrouter.ai directly and is not supported through a gateway; unset OPENROUTER_BASE_URL or use provider "typesafe".';
|
|
175727
|
+
},
|
|
175728
|
+
async readKey({ env }) {
|
|
175729
|
+
try {
|
|
175730
|
+
return (await resolveWorkflowLlmConfig(undefined, env, { requireKind: "openrouter" })).apiKey;
|
|
175731
|
+
} catch {
|
|
175732
|
+
return null;
|
|
175733
|
+
}
|
|
175734
|
+
}
|
|
175735
|
+
},
|
|
175736
|
+
laya: {
|
|
175737
|
+
label: "laya",
|
|
175738
|
+
keyName: LAYA_KEY,
|
|
175739
|
+
endpoint: { configKey: LAYA_URL_KEY, path: "/v1/systemone" },
|
|
175740
|
+
confidenceField: "answer_confidence",
|
|
175741
|
+
readKey: ({ db }) => readGlobalConfig(db, LAYA_KEY)
|
|
175742
|
+
}
|
|
175743
|
+
};
|
|
175744
|
+
var SYSTEM_ONE_PROVIDER_IDS = Object.keys(SYSTEM_ONE_PROVIDERS);
|
|
175745
|
+
var SYSTEM_ONE_DEFAULT_PROVIDER = "typesafe";
|
|
175746
|
+
function isSystemOneProviderId(value) {
|
|
175747
|
+
return typeof value === "string" && Object.hasOwn(SYSTEM_ONE_PROVIDERS, value);
|
|
175748
|
+
}
|
|
175749
|
+
function systemOneProviderOf(config) {
|
|
175750
|
+
if (config.provider === undefined)
|
|
175751
|
+
return SYSTEM_ONE_DEFAULT_PROVIDER;
|
|
175752
|
+
return isSystemOneProviderId(config.provider) ? config.provider : undefined;
|
|
175753
|
+
}
|
|
175754
|
+
var SET_IT = (keyName) => `Set ${keyName} as a global secret on the Secrets page (Settings > Secrets).`;
|
|
175755
|
+
var SET_URL = (configKey) => `Set ${configKey} as a global config value (set-config with scope global).`;
|
|
175756
|
+
function systemOneKeyMissingMessage(id) {
|
|
175757
|
+
const { label, keyName } = SYSTEM_ONE_PROVIDERS[id];
|
|
175758
|
+
return `${keyName} is not configured. SystemOne provider "${id}" needs a working ${label} API key. ${SET_IT(keyName)}`;
|
|
175759
|
+
}
|
|
175760
|
+
function systemOneKeyUnreadableMessage(id) {
|
|
175761
|
+
return `Could not read ${SYSTEM_ONE_PROVIDERS[id].keyName} from swarm config`;
|
|
175762
|
+
}
|
|
175763
|
+
function systemOneKeyMalformedMessage(id) {
|
|
175764
|
+
return `${SYSTEM_ONE_PROVIDERS[id].keyName} is not a valid bearer token value. ${SET_IT(SYSTEM_ONE_PROVIDERS[id].keyName)}`;
|
|
175765
|
+
}
|
|
175766
|
+
function systemOneKeyRejectedMessage(id, status, code) {
|
|
175767
|
+
const { label, keyName } = SYSTEM_ONE_PROVIDERS[id];
|
|
175768
|
+
const detail = code ? ` (${code})` : "";
|
|
175769
|
+
return `${keyName} was rejected by ${label} (HTTP ${status}${detail}). ` + `The key is invalid, revoked, or lacks access to the model. Replace it on the Secrets page (Settings > Secrets). No decision was made.`;
|
|
175770
|
+
}
|
|
175771
|
+
function urlKeyOf(provider) {
|
|
175772
|
+
return typeof provider.endpoint === "string" ? null : provider.endpoint.configKey;
|
|
175773
|
+
}
|
|
175774
|
+
function systemOneUrlMissingMessage(id) {
|
|
175775
|
+
const provider = SYSTEM_ONE_PROVIDERS[id];
|
|
175776
|
+
const configKey = urlKeyOf(provider) ?? "";
|
|
175777
|
+
return `${configKey} is not configured. SystemOne provider "${id}" needs the URL of a ${provider.label} server. ${SET_URL(configKey)}`;
|
|
175778
|
+
}
|
|
175779
|
+
function systemOneUrlUnreadableMessage(id) {
|
|
175780
|
+
return `Could not read ${urlKeyOf(SYSTEM_ONE_PROVIDERS[id]) ?? ""} from swarm config`;
|
|
175781
|
+
}
|
|
175782
|
+
function systemOneUrlInvalidMessage(id) {
|
|
175783
|
+
const provider = SYSTEM_ONE_PROVIDERS[id];
|
|
175784
|
+
const configKey = urlKeyOf(provider) ?? "";
|
|
175785
|
+
return `${configKey} is not a usable ${provider.label} server URL. It must be an https URL (http only for localhost) with no credentials, query, or fragment. ${SET_URL(configKey)}`;
|
|
175786
|
+
}
|
|
175787
|
+
function hasWhitespaceOrControl(value) {
|
|
175788
|
+
for (const char of value) {
|
|
175789
|
+
const code = char.charCodeAt(0);
|
|
175790
|
+
if (code <= 32 || code === 127)
|
|
175791
|
+
return true;
|
|
175792
|
+
}
|
|
175793
|
+
return false;
|
|
175794
|
+
}
|
|
175795
|
+
var LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1", "[::1]"]);
|
|
175796
|
+
function systemOneEndpointFromBase(base, path) {
|
|
175797
|
+
let url;
|
|
175798
|
+
try {
|
|
175799
|
+
url = new URL(base.trim());
|
|
175800
|
+
} catch {
|
|
175801
|
+
return null;
|
|
175802
|
+
}
|
|
175803
|
+
const secure = url.protocol === "https:";
|
|
175804
|
+
const loopback = url.protocol === "http:" && LOOPBACK_HOSTS.has(url.hostname);
|
|
175805
|
+
if (!secure && !loopback)
|
|
175806
|
+
return null;
|
|
175807
|
+
if (url.username || url.password || url.search || url.hash)
|
|
175808
|
+
return null;
|
|
175809
|
+
return `${url.origin}${url.pathname.replace(/\/+$/, "")}${path}`;
|
|
175810
|
+
}
|
|
175811
|
+
async function resolveSystemOneTarget(id, ctx, overrides = {}) {
|
|
175812
|
+
const provider = SYSTEM_ONE_PROVIDERS[id];
|
|
175813
|
+
const deploymentProblem = provider.deploymentProblem?.(ctx.env);
|
|
175814
|
+
if (deploymentProblem)
|
|
175815
|
+
return { ok: false, error: deploymentProblem };
|
|
175816
|
+
const errors = [];
|
|
175817
|
+
let endpoint;
|
|
175818
|
+
if (typeof provider.endpoint === "string") {
|
|
175819
|
+
endpoint = provider.endpoint;
|
|
175820
|
+
} else {
|
|
175821
|
+
const { configKey, path } = provider.endpoint;
|
|
175822
|
+
let base;
|
|
175823
|
+
let readable = true;
|
|
175824
|
+
try {
|
|
175825
|
+
base = await (overrides.serverUrl ? overrides.serverUrl(id) : readGlobalConfig(ctx.db, configKey));
|
|
175826
|
+
} catch {
|
|
175827
|
+
readable = false;
|
|
175828
|
+
errors.push(systemOneUrlUnreadableMessage(id));
|
|
175829
|
+
}
|
|
175830
|
+
if (readable) {
|
|
175831
|
+
if (!base || base.trim() === "") {
|
|
175832
|
+
errors.push(systemOneUrlMissingMessage(id));
|
|
175833
|
+
} else {
|
|
175834
|
+
const resolved = systemOneEndpointFromBase(base, path);
|
|
175835
|
+
if (resolved)
|
|
175836
|
+
endpoint = resolved;
|
|
175837
|
+
else
|
|
175838
|
+
errors.push(systemOneUrlInvalidMessage(id));
|
|
175839
|
+
}
|
|
175840
|
+
}
|
|
175841
|
+
}
|
|
175842
|
+
let apiKey;
|
|
175843
|
+
let keyProblem;
|
|
175844
|
+
try {
|
|
175845
|
+
apiKey = await (overrides.apiKey ? overrides.apiKey(id) : provider.readKey(ctx));
|
|
175846
|
+
} catch {
|
|
175847
|
+
keyProblem = systemOneKeyUnreadableMessage(id);
|
|
175848
|
+
}
|
|
175849
|
+
if (!keyProblem) {
|
|
175850
|
+
if (!apiKey || apiKey.trim() === "")
|
|
175851
|
+
keyProblem = systemOneKeyMissingMessage(id);
|
|
175852
|
+
else if (hasWhitespaceOrControl(apiKey))
|
|
175853
|
+
keyProblem = systemOneKeyMalformedMessage(id);
|
|
175854
|
+
}
|
|
175855
|
+
if (keyProblem)
|
|
175856
|
+
errors.push(keyProblem);
|
|
175857
|
+
if (errors.length > 0 || !endpoint || !apiKey)
|
|
175858
|
+
return { ok: false, error: errors.join(" ") };
|
|
175859
|
+
return { ok: true, apiKey, endpoint };
|
|
175860
|
+
}
|
|
175861
|
+
|
|
175862
|
+
// src/workflows/executors/system-one-decision.ts
|
|
175863
|
+
var SYSTEM_ONE_DECISION_NODE_TYPE = "system-one-decision";
|
|
175864
|
+
var SYSTEM_ONE_ENDPOINT = SYSTEM_ONE_PROVIDERS.typesafe.endpoint;
|
|
175865
|
+
var SYSTEM_ONE_API_KEY_CONFIG_KEY = SYSTEM_ONE_PROVIDERS.typesafe.keyName;
|
|
175866
|
+
var SYSTEM_ONE_DEFAULT_TIMEOUT_MS = 30000;
|
|
175867
|
+
var SYSTEM_ONE_MIN_TIMEOUT_MS = 1000;
|
|
175868
|
+
var SYSTEM_ONE_MAX_TIMEOUT_MS = 300000;
|
|
175869
|
+
var SYSTEM_ONE_DEFAULT_MAX_RETRIES = 2;
|
|
175870
|
+
var SYSTEM_ONE_MAX_RETRIES_LIMIT = 3;
|
|
175871
|
+
var CHOICE_MIN_OPTIONS = 2;
|
|
175872
|
+
var CHOICE_MAX_OPTIONS = 255;
|
|
175873
|
+
var SCORE_MIN_LEVELS = 2;
|
|
175874
|
+
var SCORE_MAX_LEVELS = 10;
|
|
175875
|
+
var DEADLINE_MARGIN_MS = 250;
|
|
175876
|
+
var BACKOFF_BASE_MS = 500;
|
|
175877
|
+
var BACKOFF_CAP_MS = 8000;
|
|
175878
|
+
var DISTRIBUTION_TOLERANCE = 0.02;
|
|
175879
|
+
var MAX_RESPONSE_CHARS = 1048576;
|
|
175880
|
+
var MAX_ERROR_BODY_CHARS = 65536;
|
|
175881
|
+
var REVIEW_PORTS = ["approved", "rejected", "timeout"];
|
|
175882
|
+
var ENGINE_RETRY_DEFAULT = 3;
|
|
175883
|
+
var SystemOneEntrySchema = exports_external.union([
|
|
175884
|
+
exports_external.string(),
|
|
175885
|
+
exports_external.null(),
|
|
175886
|
+
exports_external.array(exports_external.unknown()),
|
|
175887
|
+
exports_external.record(exports_external.string(), exports_external.unknown())
|
|
175888
|
+
]);
|
|
175889
|
+
var SystemOneInstructionsSchema = SystemOneEntrySchema.refine((value) => value !== null && !(typeof value === "string" && value.trim() === ""), { message: "instructions must not be null or blank" });
|
|
175890
|
+
var SystemOneStateSchema = exports_external.union([
|
|
175891
|
+
exports_external.string().min(1, "state must not be empty"),
|
|
175892
|
+
exports_external.array(exports_external.string()).min(1, "state must not be an empty array"),
|
|
175893
|
+
exports_external.record(exports_external.string(), exports_external.unknown())
|
|
175894
|
+
]);
|
|
175895
|
+
var NoulQuestionSchema = exports_external.strictObject({
|
|
175896
|
+
type: exports_external.literal("noul"),
|
|
175897
|
+
instructions: SystemOneInstructionsSchema,
|
|
175898
|
+
criteria: exports_external.strictObject({ true: SystemOneEntrySchema.optional(), false: SystemOneEntrySchema.optional() }).refine((criteria) => criteria.true !== undefined || criteria.false !== undefined, {
|
|
175899
|
+
message: "noul criteria must describe at least one of true / false"
|
|
175900
|
+
}).optional()
|
|
175901
|
+
});
|
|
175902
|
+
var ChoiceQuestionSchema = exports_external.strictObject({
|
|
175903
|
+
type: exports_external.literal("choice"),
|
|
175904
|
+
instructions: SystemOneInstructionsSchema,
|
|
175905
|
+
criteria: exports_external.record(exports_external.string().min(1), SystemOneEntrySchema).refine((criteria) => {
|
|
175906
|
+
const count = Object.keys(criteria).length;
|
|
175907
|
+
return count >= CHOICE_MIN_OPTIONS && count <= CHOICE_MAX_OPTIONS;
|
|
175908
|
+
}, {
|
|
175909
|
+
message: `choice criteria must define ${CHOICE_MIN_OPTIONS}-${CHOICE_MAX_OPTIONS} options`
|
|
175910
|
+
})
|
|
175911
|
+
});
|
|
175912
|
+
var ScoreQuestionSchema = exports_external.strictObject({
|
|
175913
|
+
type: exports_external.literal("score"),
|
|
175914
|
+
instructions: SystemOneInstructionsSchema,
|
|
175915
|
+
criteria: exports_external.array(SystemOneEntrySchema).min(SCORE_MIN_LEVELS).max(SCORE_MAX_LEVELS)
|
|
175916
|
+
});
|
|
175917
|
+
var SystemOneQuestionSchema = exports_external.discriminatedUnion("type", [
|
|
175918
|
+
NoulQuestionSchema,
|
|
175919
|
+
ChoiceQuestionSchema,
|
|
175920
|
+
ScoreQuestionSchema
|
|
175921
|
+
]);
|
|
175922
|
+
var Unit = exports_external.number().min(0).max(1);
|
|
175923
|
+
var QUESTION_ID_RE = /^[A-Za-z_][A-Za-z0-9_-]*$/;
|
|
175924
|
+
var RESERVED_QUESTION_IDS = new Set([
|
|
175925
|
+
...Object.getOwnPropertyNames(Object.prototype),
|
|
175926
|
+
"prototype"
|
|
175927
|
+
]);
|
|
175928
|
+
var SystemOnePrimitiveTypeSchema = exports_external.enum(["noul", "choice", "score"]);
|
|
175929
|
+
var HumanReviewSchema = exports_external.strictObject({
|
|
175930
|
+
band: exports_external.strictObject({ min: Unit, max: Unit }).refine((band) => band.min <= band.max, { message: "band.min must not exceed band.max" }),
|
|
175931
|
+
approvers: ApproverConfigSchema,
|
|
175932
|
+
title: exports_external.string().min(1).optional(),
|
|
175933
|
+
timeout: HITLTimeoutSchema.optional(),
|
|
175934
|
+
notifications: exports_external.array(NotificationConfigSchema).optional()
|
|
175935
|
+
});
|
|
175936
|
+
var SystemOneDecisionConfigSchema = exports_external.strictObject({
|
|
175937
|
+
provider: exports_external.enum(SYSTEM_ONE_PROVIDER_IDS).default(SYSTEM_ONE_DEFAULT_PROVIDER),
|
|
175938
|
+
model: exports_external.string().min(1).optional(),
|
|
175939
|
+
state: SystemOneStateSchema,
|
|
175940
|
+
timeoutMs: exports_external.number().int().min(SYSTEM_ONE_MIN_TIMEOUT_MS).max(SYSTEM_ONE_MAX_TIMEOUT_MS).default(SYSTEM_ONE_DEFAULT_TIMEOUT_MS),
|
|
175941
|
+
maxRetries: exports_external.number().int().min(0).max(SYSTEM_ONE_MAX_RETRIES_LIMIT).default(SYSTEM_ONE_DEFAULT_MAX_RETRIES),
|
|
175942
|
+
questions: exports_external.record(exports_external.string().regex(QUESTION_ID_RE, "question ids must start with a letter or underscore and use only letters, digits, _ or -"), SystemOneQuestionSchema),
|
|
175943
|
+
returns: exports_external.record(exports_external.string(), exports_external.strictObject({ type: SystemOnePrimitiveTypeSchema })),
|
|
175944
|
+
humanReview: HumanReviewSchema.optional()
|
|
175945
|
+
}).superRefine((config, ctx) => {
|
|
175946
|
+
const questionIds = Object.keys(config.questions);
|
|
175947
|
+
if (questionIds.length === 0) {
|
|
175948
|
+
ctx.addIssue({
|
|
175949
|
+
code: "custom",
|
|
175950
|
+
path: ["questions"],
|
|
175951
|
+
message: "system-one-decision needs at least one question"
|
|
175952
|
+
});
|
|
175953
|
+
}
|
|
175954
|
+
for (const id of questionIds) {
|
|
175955
|
+
if (RESERVED_QUESTION_IDS.has(id)) {
|
|
175956
|
+
ctx.addIssue({
|
|
175957
|
+
code: "custom",
|
|
175958
|
+
path: ["questions", id],
|
|
175959
|
+
message: `"${id}" is reserved and cannot be a question id`
|
|
175960
|
+
});
|
|
175961
|
+
}
|
|
175962
|
+
const declared = Object.hasOwn(config.returns, id) ? config.returns[id] : undefined;
|
|
175963
|
+
if (!declared) {
|
|
175964
|
+
ctx.addIssue({
|
|
175965
|
+
code: "custom",
|
|
175966
|
+
path: ["returns"],
|
|
175967
|
+
message: `returns must declare question "${id}"`
|
|
175968
|
+
});
|
|
175969
|
+
} else if (declared.type !== config.questions[id]?.type) {
|
|
175970
|
+
ctx.addIssue({
|
|
175971
|
+
code: "custom",
|
|
175972
|
+
path: ["returns", id, "type"],
|
|
175973
|
+
message: `returns.${id}.type is "${declared.type}" but question "${id}" is "${config.questions[id]?.type}"`
|
|
175974
|
+
});
|
|
175975
|
+
}
|
|
175976
|
+
}
|
|
175977
|
+
for (const id of Object.keys(config.returns)) {
|
|
175978
|
+
if (!Object.hasOwn(config.questions, id)) {
|
|
175979
|
+
ctx.addIssue({
|
|
175980
|
+
code: "custom",
|
|
175981
|
+
path: ["returns", id],
|
|
175982
|
+
message: `returns declares "${id}" but no question has that id`
|
|
175983
|
+
});
|
|
175984
|
+
}
|
|
175985
|
+
}
|
|
175986
|
+
});
|
|
175987
|
+
var NoulAnswerSchema = exports_external.strictObject({ type: exports_external.literal("noul"), noul: Unit });
|
|
175988
|
+
var ChoiceAnswerSchema = exports_external.strictObject({
|
|
175989
|
+
type: exports_external.literal("choice"),
|
|
175990
|
+
choice: exports_external.string(),
|
|
175991
|
+
probabilities: exports_external.record(exports_external.string(), Unit),
|
|
175992
|
+
confidence: Unit
|
|
175993
|
+
});
|
|
175994
|
+
var ScoreAnswerSchema = exports_external.strictObject({
|
|
175995
|
+
type: exports_external.literal("score"),
|
|
175996
|
+
score: exports_external.number(),
|
|
175997
|
+
legend: exports_external.record(exports_external.string(), SystemOneEntrySchema),
|
|
175998
|
+
probabilities: exports_external.record(exports_external.string(), Unit),
|
|
175999
|
+
confidence: Unit
|
|
176000
|
+
});
|
|
176001
|
+
var SystemOneAnswerSchema = exports_external.discriminatedUnion("type", [
|
|
176002
|
+
NoulAnswerSchema,
|
|
176003
|
+
ChoiceAnswerSchema,
|
|
176004
|
+
ScoreAnswerSchema
|
|
176005
|
+
]);
|
|
176006
|
+
var ReviewQuestionSchema = exports_external.strictObject({
|
|
176007
|
+
confidence: Unit,
|
|
176008
|
+
inBand: exports_external.boolean(),
|
|
176009
|
+
decidedBy: exports_external.enum(["model", "human"]),
|
|
176010
|
+
modelAnswer: exports_external.union([exports_external.string(), exports_external.number()]).optional()
|
|
176011
|
+
});
|
|
176012
|
+
var ReviewSchema = exports_external.strictObject({
|
|
176013
|
+
status: exports_external.enum(["not_required", "pending", "approved", "rejected", "timeout"]),
|
|
176014
|
+
approvalRequestId: exports_external.string().optional(),
|
|
176015
|
+
reason: exports_external.string().optional(),
|
|
176016
|
+
questions: exports_external.record(exports_external.string(), ReviewQuestionSchema)
|
|
176017
|
+
});
|
|
176018
|
+
var SystemOneDecisionOutputSchema = exports_external.object({
|
|
176019
|
+
model: exports_external.string().min(1),
|
|
176020
|
+
answers: exports_external.record(exports_external.string(), SystemOneAnswerSchema),
|
|
176021
|
+
usage: exports_external.object({
|
|
176022
|
+
input_tokens: exports_external.number().int().min(0),
|
|
176023
|
+
output_tokens: exports_external.number().int().min(0)
|
|
176024
|
+
}),
|
|
176025
|
+
requestId: exports_external.string().optional(),
|
|
176026
|
+
routing: exports_external.strictObject({ model: exports_external.string().min(1) }).optional(),
|
|
176027
|
+
review: ReviewSchema.optional()
|
|
176028
|
+
});
|
|
176029
|
+
function systemOneRetryViolations(node) {
|
|
176030
|
+
if (node.type !== SYSTEM_ONE_DECISION_NODE_TYPE)
|
|
176031
|
+
return [];
|
|
176032
|
+
const violations = [];
|
|
176033
|
+
const attempts = (retry) => retry ? retry.maxRetries ?? ENGINE_RETRY_DEFAULT : 0;
|
|
176034
|
+
if (attempts(node.retry) > 0) {
|
|
176035
|
+
violations.push(`Node "${node.id}" (system-one-decision) must not set retry.maxRetries > 0: the system-one-decision executor retries transient transport errors itself (config.maxRetries), and engine retries would re-send rejected requests`);
|
|
176036
|
+
}
|
|
176037
|
+
if (attempts(node.validation?.retry) > 0) {
|
|
176038
|
+
violations.push(`Node "${node.id}" (system-one-decision) must not set validation.retry.maxRetries > 0: a validation-driven retry would send another paid request`);
|
|
176039
|
+
}
|
|
176040
|
+
return violations;
|
|
176041
|
+
}
|
|
176042
|
+
function systemOneStaticShapeViolations(node) {
|
|
176043
|
+
if (node.type !== SYSTEM_ONE_DECISION_NODE_TYPE)
|
|
176044
|
+
return [];
|
|
176045
|
+
const violations = [];
|
|
176046
|
+
for (const field of ["questions", "returns"]) {
|
|
176047
|
+
const value = node.config[field];
|
|
176048
|
+
if (value !== undefined && (typeof value !== "object" || value === null || Array.isArray(value))) {
|
|
176049
|
+
violations.push(`Node "${node.id}" (system-one-decision) config.${field} must be an object: question ids and return types are static, only state and descriptions may use {{tokens}}`);
|
|
176050
|
+
}
|
|
176051
|
+
}
|
|
176052
|
+
const provider = node.config.provider;
|
|
176053
|
+
if (typeof provider === "string" && provider.includes("{{")) {
|
|
176054
|
+
violations.push(`Node "${node.id}" (system-one-decision) config.provider must be a literal (${SYSTEM_ONE_PROVIDER_IDS.join(", ")}), not a {{token}}: the provider decides which credential is checked before the run starts`);
|
|
176055
|
+
}
|
|
176056
|
+
if (isRecord(node.config.humanReview) && node.next != null) {
|
|
176057
|
+
if (typeof node.next === "string" || Array.isArray(node.next)) {
|
|
176058
|
+
violations.push(`Node "${node.id}" (system-one-decision) sets humanReview, so next must map output ports (${REVIEW_PORTS.join(", ")}): a single or list next would run the same successors after a rejection or a timeout`);
|
|
176059
|
+
} else {
|
|
176060
|
+
const ports = Object.keys(node.next);
|
|
176061
|
+
const unknown2 = ports.filter((port) => !REVIEW_PORTS.includes(port));
|
|
176062
|
+
if (unknown2.length > 0) {
|
|
176063
|
+
violations.push(`Node "${node.id}" (system-one-decision) sets humanReview, so next ports must be ${REVIEW_PORTS.join(", ")}; got ${unknown2.map((port) => `"${port}"`).join(", ")}`);
|
|
176064
|
+
}
|
|
176065
|
+
if (!ports.includes("approved")) {
|
|
176066
|
+
violations.push(`Node "${node.id}" (system-one-decision) sets humanReview, so next must define the "approved" port: it carries every answer that is accepted, by the model or by a person`);
|
|
176067
|
+
}
|
|
176068
|
+
}
|
|
176069
|
+
}
|
|
176070
|
+
return violations;
|
|
176071
|
+
}
|
|
176072
|
+
function systemOneUnresolvedError(nodeId, tokens) {
|
|
176073
|
+
const rendered = [...new Set(tokens)].map((token) => `{{${token}}}`).join(", ");
|
|
176074
|
+
return `SystemOne Decision node "${nodeId}" has unresolved interpolation token(s): ${rendered}. ` + "No request was sent. Declare the value in the node's inputs mapping or fix the path.";
|
|
176075
|
+
}
|
|
176076
|
+
|
|
176077
|
+
class SystemOneContractError extends Error {
|
|
176078
|
+
}
|
|
176079
|
+
function fail(message) {
|
|
176080
|
+
throw new SystemOneContractError(message);
|
|
176081
|
+
}
|
|
176082
|
+
function isRecord(value) {
|
|
176083
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
176084
|
+
}
|
|
176085
|
+
function unit(value, what) {
|
|
176086
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0 || value > 1) {
|
|
176087
|
+
fail(`${what} must be a finite number between 0 and 1`);
|
|
176088
|
+
}
|
|
176089
|
+
return value;
|
|
176090
|
+
}
|
|
176091
|
+
function distribution(value, keys, what) {
|
|
176092
|
+
if (!isRecord(value))
|
|
176093
|
+
fail(`${what} must be an object`);
|
|
176094
|
+
const actual = Object.keys(value);
|
|
176095
|
+
const missing = keys.filter((key) => !Object.hasOwn(value, key));
|
|
176096
|
+
const extra = actual.filter((key) => !keys.includes(key));
|
|
176097
|
+
if (missing.length > 0 || extra.length > 0) {
|
|
176098
|
+
fail(`${what} keys must be exactly the declared ${keys.length} option(s)` + (missing.length > 0 ? `; missing ${missing.length}` : "") + (extra.length > 0 ? `; ${extra.length} unexpected` : ""));
|
|
176099
|
+
}
|
|
176100
|
+
const out = {};
|
|
176101
|
+
let sum = 0;
|
|
176102
|
+
for (const key of keys) {
|
|
176103
|
+
const p = unit(value[key], `${what}["${key}"]`);
|
|
176104
|
+
out[key] = p;
|
|
176105
|
+
sum += p;
|
|
176106
|
+
}
|
|
176107
|
+
if (Math.abs(sum - 1) > DISTRIBUTION_TOLERANCE) {
|
|
176108
|
+
fail(`${what} must sum to 1 (within ${DISTRIBUTION_TOLERANCE})`);
|
|
176109
|
+
}
|
|
176110
|
+
return out;
|
|
176111
|
+
}
|
|
176112
|
+
function validateAnswer(id, question, raw, confidenceField) {
|
|
176113
|
+
const at = `answer "${id}"`;
|
|
176114
|
+
if (!isRecord(raw))
|
|
176115
|
+
fail(`${at} must be an object`);
|
|
176116
|
+
if (raw.type !== question.type) {
|
|
176117
|
+
fail(`${at} has type ${JSON.stringify(raw.type)} but the question declares "${question.type}"`);
|
|
176118
|
+
}
|
|
176119
|
+
switch (question.type) {
|
|
176120
|
+
case "noul":
|
|
176121
|
+
return { type: "noul", noul: unit(raw.noul, `${at}.noul`) };
|
|
176122
|
+
case "choice": {
|
|
176123
|
+
const options = Object.keys(question.criteria);
|
|
176124
|
+
if (typeof raw.choice !== "string" || !Object.hasOwn(question.criteria, raw.choice)) {
|
|
176125
|
+
fail(`${at}.choice is not one of the declared options`);
|
|
176126
|
+
}
|
|
176127
|
+
return {
|
|
176128
|
+
type: "choice",
|
|
176129
|
+
choice: raw.choice,
|
|
176130
|
+
probabilities: distribution(raw.probabilities, options, `${at}.probabilities`),
|
|
176131
|
+
confidence: unit(raw[confidenceField], `${at}.${confidenceField}`)
|
|
176132
|
+
};
|
|
176133
|
+
}
|
|
176134
|
+
case "score": {
|
|
176135
|
+
const indices = question.criteria.map((_, index) => String(index));
|
|
176136
|
+
const top = indices.length - 1;
|
|
176137
|
+
if (typeof raw.score !== "number" || !Number.isFinite(raw.score) || raw.score < 0 || raw.score > top) {
|
|
176138
|
+
fail(`${at}.score must be a finite number between 0 and ${top}`);
|
|
176139
|
+
}
|
|
176140
|
+
if (!isRecord(raw.legend))
|
|
176141
|
+
fail(`${at}.legend must be an object`);
|
|
176142
|
+
const legend = {};
|
|
176143
|
+
for (const key of indices) {
|
|
176144
|
+
if (!Object.hasOwn(raw.legend, key))
|
|
176145
|
+
fail(`${at}.legend is missing level ${key}`);
|
|
176146
|
+
const entry = SystemOneEntrySchema.safeParse(raw.legend[key]);
|
|
176147
|
+
if (!entry.success)
|
|
176148
|
+
fail(`${at}.legend["${key}"] must be a string, object, array, or null`);
|
|
176149
|
+
legend[key] = entry.data;
|
|
176150
|
+
}
|
|
176151
|
+
return {
|
|
176152
|
+
type: "score",
|
|
176153
|
+
score: raw.score,
|
|
176154
|
+
legend,
|
|
176155
|
+
probabilities: distribution(raw.probabilities, indices, `${at}.probabilities`),
|
|
176156
|
+
confidence: unit(raw[confidenceField], `${at}.${confidenceField}`)
|
|
176157
|
+
};
|
|
176158
|
+
}
|
|
176159
|
+
}
|
|
176160
|
+
}
|
|
176161
|
+
var MAX_ROUTING_MODEL_CHARS = 128;
|
|
176162
|
+
function readRoutingModel(routing) {
|
|
176163
|
+
if (!isRecord(routing))
|
|
176164
|
+
return;
|
|
176165
|
+
const { model } = routing;
|
|
176166
|
+
return typeof model === "string" && model !== "" && model.length <= MAX_ROUTING_MODEL_CHARS ? model : undefined;
|
|
176167
|
+
}
|
|
176168
|
+
function validateSystemOneResponse(questions, body, requestId, confidenceField = "confidence") {
|
|
176169
|
+
if (!isRecord(body))
|
|
176170
|
+
fail("response body must be a JSON object");
|
|
176171
|
+
if (typeof body.model !== "string" || body.model === "") {
|
|
176172
|
+
fail("response is missing the model that produced the answers");
|
|
176173
|
+
}
|
|
176174
|
+
if (!isRecord(body.answers))
|
|
176175
|
+
fail("response is missing the answers object");
|
|
176176
|
+
const usage = exports_external.object({ input_tokens: exports_external.number().int().min(0), output_tokens: exports_external.number().int().min(0) }).safeParse(body.usage);
|
|
176177
|
+
if (!usage.success)
|
|
176178
|
+
fail("response usage must report non-negative integer input_tokens and output_tokens");
|
|
176179
|
+
const declared = Object.keys(questions);
|
|
176180
|
+
const unexpected = Object.keys(body.answers).filter((id) => !Object.hasOwn(questions, id));
|
|
176181
|
+
if (unexpected.length > 0)
|
|
176182
|
+
fail(`response contains ${unexpected.length} answer(s) for undeclared questions`);
|
|
176183
|
+
const answers = {};
|
|
176184
|
+
for (const id of declared) {
|
|
176185
|
+
if (!Object.hasOwn(body.answers, id))
|
|
176186
|
+
fail(`response is missing the answer for question "${id}"`);
|
|
176187
|
+
const question = questions[id];
|
|
176188
|
+
if (!question)
|
|
176189
|
+
fail(`question "${id}" is not defined`);
|
|
176190
|
+
answers[id] = validateAnswer(id, question, body.answers[id], confidenceField);
|
|
176191
|
+
}
|
|
176192
|
+
if (declared.length === 0)
|
|
176193
|
+
fail("a system-one-decision call needs at least one question");
|
|
176194
|
+
const routingModel = readRoutingModel(body.routing);
|
|
176195
|
+
return {
|
|
176196
|
+
model: body.model,
|
|
176197
|
+
answers,
|
|
176198
|
+
usage: usage.data,
|
|
176199
|
+
...requestId ? { requestId } : {},
|
|
176200
|
+
...routingModel ? { routing: { model: routingModel } } : {}
|
|
176201
|
+
};
|
|
176202
|
+
}
|
|
176203
|
+
var REVIEW_CONFIRM_ID = "$confirm";
|
|
176204
|
+
var REVIEW_STATE_CHARS = 2000;
|
|
176205
|
+
var REVIEW_LABEL_CHARS = 160;
|
|
176206
|
+
var REVIEW_OPTION_CHARS = 200;
|
|
176207
|
+
var round6 = (value) => Math.round(value * 1e6) / 1e6;
|
|
176208
|
+
function answerConfidence(answer) {
|
|
176209
|
+
return answer.type === "noul" ? round6(Math.max(answer.noul, 1 - answer.noul)) : answer.confidence;
|
|
176210
|
+
}
|
|
176211
|
+
function clip(text, max) {
|
|
176212
|
+
return text.length > max ? `${text.slice(0, max - 1)}…` : text;
|
|
176213
|
+
}
|
|
176214
|
+
function showEntry(entry, max) {
|
|
176215
|
+
return clip(typeof entry === "string" ? entry : JSON.stringify(entry) ?? "", max);
|
|
176216
|
+
}
|
|
176217
|
+
function modelAnswerOf(answer) {
|
|
176218
|
+
return answer.type === "choice" ? answer.choice : answer.type === "score" ? answer.score : answer.noul;
|
|
176219
|
+
}
|
|
176220
|
+
function buildReviewCard(nodeId, config, review, parked) {
|
|
176221
|
+
const state = scrubSecrets(typeof config.state === "string" ? config.state : JSON.stringify(config.state) ?? "");
|
|
176222
|
+
const questions = [
|
|
176223
|
+
{
|
|
176224
|
+
id: REVIEW_CONFIRM_ID,
|
|
176225
|
+
type: "approval",
|
|
176226
|
+
label: "Accept these answers and continue?",
|
|
176227
|
+
required: true,
|
|
176228
|
+
description: `Model ${parked.model}. Input: ${clip(state, REVIEW_STATE_CHARS)}`
|
|
176229
|
+
}
|
|
176230
|
+
];
|
|
176231
|
+
for (const [id, info] of Object.entries(parked.review?.questions ?? {})) {
|
|
176232
|
+
if (!info.inBand)
|
|
176233
|
+
continue;
|
|
176234
|
+
const question = config.questions[id];
|
|
176235
|
+
const answer = parked.answers[id];
|
|
176236
|
+
if (!question || !answer)
|
|
176237
|
+
continue;
|
|
176238
|
+
const label = `${id}: ${showEntry(question.instructions, REVIEW_LABEL_CHARS)}`;
|
|
176239
|
+
const said = `The model answered ${JSON.stringify(modelAnswerOf(answer))} at confidence ${info.confidence}.`;
|
|
176240
|
+
if (question.type === "choice" && answer.type === "choice") {
|
|
176241
|
+
questions.push({
|
|
176242
|
+
id,
|
|
176243
|
+
type: "single-select",
|
|
176244
|
+
label,
|
|
176245
|
+
required: false,
|
|
176246
|
+
description: `${said} Leave empty to confirm it, or pick another option.`,
|
|
176247
|
+
options: Object.entries(question.criteria).map(([value, entry]) => ({
|
|
176248
|
+
value,
|
|
176249
|
+
label: value,
|
|
176250
|
+
...typeof entry === "string" && entry ? { description: clip(entry, REVIEW_OPTION_CHARS) } : {}
|
|
176251
|
+
}))
|
|
176252
|
+
});
|
|
176253
|
+
} else if (question.type === "score" && answer.type === "score") {
|
|
176254
|
+
questions.push({
|
|
176255
|
+
id,
|
|
176256
|
+
type: "single-select",
|
|
176257
|
+
label,
|
|
176258
|
+
required: false,
|
|
176259
|
+
description: `${said} Leave empty to confirm it, or pick a level.`,
|
|
176260
|
+
options: question.criteria.map((entry, level) => ({
|
|
176261
|
+
value: String(level),
|
|
176262
|
+
label: `${level}: ${showEntry(entry, REVIEW_OPTION_CHARS)}`
|
|
176263
|
+
}))
|
|
176264
|
+
});
|
|
176265
|
+
} else if (question.type === "noul" && answer.type === "noul") {
|
|
176266
|
+
questions.push({
|
|
176267
|
+
id,
|
|
176268
|
+
type: "boolean",
|
|
176269
|
+
label,
|
|
176270
|
+
required: false,
|
|
176271
|
+
defaultValue: answer.noul >= 0.5,
|
|
176272
|
+
description: `${said} The switch starts on the side the model took.`
|
|
176273
|
+
});
|
|
176274
|
+
}
|
|
176275
|
+
}
|
|
176276
|
+
return {
|
|
176277
|
+
title: review.title ?? `Review decision: ${nodeId}`,
|
|
176278
|
+
questions,
|
|
176279
|
+
approvers: review.approvers,
|
|
176280
|
+
...review.timeout ? { timeout: review.timeout } : {},
|
|
176281
|
+
...review.notifications ? { notifications: review.notifications } : {}
|
|
176282
|
+
};
|
|
176283
|
+
}
|
|
176284
|
+
function readHumanAnswer(answer, response) {
|
|
176285
|
+
if (response === undefined || response === null || response === "")
|
|
176286
|
+
return { kind: "confirm" };
|
|
176287
|
+
switch (answer.type) {
|
|
176288
|
+
case "choice":
|
|
176289
|
+
if (typeof response !== "string" || !Object.hasOwn(answer.probabilities, response)) {
|
|
176290
|
+
return { kind: "invalid" };
|
|
176291
|
+
}
|
|
176292
|
+
return response === answer.choice ? { kind: "confirm" } : { kind: "override", answer: { ...answer, choice: response } };
|
|
176293
|
+
case "score": {
|
|
176294
|
+
if (typeof response !== "string" || !Object.hasOwn(answer.legend, response)) {
|
|
176295
|
+
return { kind: "invalid" };
|
|
176296
|
+
}
|
|
176297
|
+
const level = Number(response);
|
|
176298
|
+
return level === answer.score ? { kind: "confirm" } : { kind: "override", answer: { ...answer, score: level } };
|
|
176299
|
+
}
|
|
176300
|
+
case "noul":
|
|
176301
|
+
if (typeof response !== "boolean")
|
|
176302
|
+
return { kind: "invalid" };
|
|
176303
|
+
return response === answer.noul >= 0.5 ? { kind: "confirm" } : { kind: "override", answer: { ...answer, noul: response ? 1 : 0 } };
|
|
176304
|
+
}
|
|
176305
|
+
}
|
|
176306
|
+
function resolveReviewedDecision(parkedOutput, approval) {
|
|
176307
|
+
const parked = SystemOneDecisionOutputSchema.safeParse(parkedOutput);
|
|
176308
|
+
if (!parked.success || parked.data.review?.status !== "pending")
|
|
176309
|
+
return null;
|
|
176310
|
+
const decision = parked.data;
|
|
176311
|
+
const parkedQuestions = decision.review?.questions ?? {};
|
|
176312
|
+
const finish = (status, answers2, questions2, reason) => ({
|
|
176313
|
+
output: {
|
|
176314
|
+
...decision,
|
|
176315
|
+
answers: answers2,
|
|
176316
|
+
review: {
|
|
176317
|
+
status,
|
|
176318
|
+
approvalRequestId: approval.requestId,
|
|
176319
|
+
...reason ? { reason } : {},
|
|
176320
|
+
questions: questions2
|
|
176321
|
+
}
|
|
176322
|
+
},
|
|
176323
|
+
nextPort: status
|
|
176324
|
+
});
|
|
176325
|
+
if (approval.status !== "approved") {
|
|
176326
|
+
return finish(approval.status, decision.answers, parkedQuestions);
|
|
176327
|
+
}
|
|
176328
|
+
const answers = { ...decision.answers };
|
|
176329
|
+
const questions = { ...parkedQuestions };
|
|
176330
|
+
for (const [id, info] of Object.entries(parkedQuestions)) {
|
|
176331
|
+
const modelAnswer = decision.answers[id];
|
|
176332
|
+
if (!info.inBand || !modelAnswer)
|
|
176333
|
+
continue;
|
|
176334
|
+
const human = readHumanAnswer(modelAnswer, approval.responses?.[id]);
|
|
176335
|
+
if (human.kind === "invalid") {
|
|
176336
|
+
return finish("rejected", decision.answers, parkedQuestions, `The response for "${id}" is not one of its options`);
|
|
176337
|
+
}
|
|
176338
|
+
if (human.kind === "override")
|
|
176339
|
+
answers[id] = human.answer;
|
|
176340
|
+
questions[id] = { ...info, decidedBy: "human", modelAnswer: modelAnswerOf(modelAnswer) };
|
|
176341
|
+
}
|
|
176342
|
+
return finish("approved", answers, questions);
|
|
176343
|
+
}
|
|
176344
|
+
var REQUEST_ID_RE = /^[A-Za-z0-9._:-]{1,128}$/;
|
|
176345
|
+
var ERROR_CODE_RE = /^[A-Za-z0-9._:-]{1,64}$/;
|
|
176346
|
+
function readRequestId(headers) {
|
|
176347
|
+
const value = headers.get("x-request-id") ?? headers.get("request-id");
|
|
176348
|
+
return value && REQUEST_ID_RE.test(value) ? value : undefined;
|
|
176349
|
+
}
|
|
176350
|
+
function parseRetryAfter(value, now) {
|
|
176351
|
+
if (!value)
|
|
176352
|
+
return;
|
|
176353
|
+
const trimmed = value.trim();
|
|
176354
|
+
if (/^\d+(\.\d+)?$/.test(trimmed))
|
|
176355
|
+
return Math.round(Number(trimmed) * 1000);
|
|
176356
|
+
const at = Date.parse(trimmed);
|
|
176357
|
+
return Number.isNaN(at) ? undefined : Math.max(0, at - now);
|
|
176358
|
+
}
|
|
176359
|
+
function readErrorCode(text) {
|
|
176360
|
+
if (text.length === 0 || text.length > MAX_ERROR_BODY_CHARS)
|
|
176361
|
+
return;
|
|
176362
|
+
let parsed;
|
|
176363
|
+
try {
|
|
176364
|
+
parsed = JSON.parse(text);
|
|
176365
|
+
} catch {
|
|
176366
|
+
return;
|
|
176367
|
+
}
|
|
176368
|
+
if (!isRecord(parsed))
|
|
176369
|
+
return;
|
|
176370
|
+
const nested = isRecord(parsed.error) ? parsed.error : undefined;
|
|
176371
|
+
const detail = isRecord(parsed.detail) ? parsed.detail : undefined;
|
|
176372
|
+
for (const candidate of [
|
|
176373
|
+
nested?.code,
|
|
176374
|
+
nested?.type,
|
|
176375
|
+
detail?.error_type,
|
|
176376
|
+
parsed.code,
|
|
176377
|
+
parsed.type
|
|
176378
|
+
]) {
|
|
176379
|
+
if (typeof candidate === "string" && ERROR_CODE_RE.test(candidate))
|
|
176380
|
+
return candidate;
|
|
176381
|
+
}
|
|
176382
|
+
return;
|
|
176383
|
+
}
|
|
176384
|
+
function defaultSleep(ms, signal) {
|
|
176385
|
+
return new Promise((resolve) => {
|
|
176386
|
+
if (signal.aborted)
|
|
176387
|
+
return resolve();
|
|
176388
|
+
const timer = setTimeout(done, ms);
|
|
176389
|
+
function done() {
|
|
176390
|
+
clearTimeout(timer);
|
|
176391
|
+
signal.removeEventListener("abort", done);
|
|
176392
|
+
resolve();
|
|
176393
|
+
}
|
|
176394
|
+
signal.addEventListener("abort", done, { once: true });
|
|
176395
|
+
});
|
|
176396
|
+
}
|
|
176397
|
+
|
|
176398
|
+
class SystemOneDecisionExecutor extends BaseExecutor {
|
|
176399
|
+
options;
|
|
176400
|
+
type = SYSTEM_ONE_DECISION_NODE_TYPE;
|
|
176401
|
+
mode = "async";
|
|
176402
|
+
configSchema = SystemOneDecisionConfigSchema;
|
|
176403
|
+
outputSchema = SystemOneDecisionOutputSchema;
|
|
176404
|
+
constructor(deps, options = {}) {
|
|
176405
|
+
super(deps);
|
|
176406
|
+
this.options = options;
|
|
176407
|
+
}
|
|
176408
|
+
providerContext() {
|
|
176409
|
+
return { db: this.deps.db, env: this.options.env ?? process.env };
|
|
176410
|
+
}
|
|
176411
|
+
resolveTarget(id) {
|
|
176412
|
+
return resolveSystemOneTarget(id, this.providerContext(), {
|
|
176413
|
+
apiKey: this.options.getApiKey,
|
|
176414
|
+
serverUrl: this.options.getServerUrl
|
|
176415
|
+
});
|
|
176416
|
+
}
|
|
176417
|
+
async checkReadiness(nodes) {
|
|
176418
|
+
const nodeIdsByProvider = new Map;
|
|
176419
|
+
for (const node of nodes) {
|
|
176420
|
+
const id = systemOneProviderOf(node.config);
|
|
176421
|
+
if (id)
|
|
176422
|
+
nodeIdsByProvider.set(id, [...nodeIdsByProvider.get(id) ?? [], node.id]);
|
|
176423
|
+
}
|
|
176424
|
+
const problems = [];
|
|
176425
|
+
for (const [id, nodeIds] of nodeIdsByProvider) {
|
|
176426
|
+
const target = await this.resolveTarget(id);
|
|
176427
|
+
if (!target.ok)
|
|
176428
|
+
problems.push({ nodeIds, message: target.error });
|
|
176429
|
+
}
|
|
176430
|
+
return problems;
|
|
176431
|
+
}
|
|
176432
|
+
async execute(config, context, meta) {
|
|
176433
|
+
if (config.humanReview) {
|
|
176434
|
+
const existing = await this.deps.db.getApprovalRequestByStepId(meta.stepId);
|
|
176435
|
+
if (existing) {
|
|
176436
|
+
return this.handOffToReviewer(config, await this.readParked(meta.stepId), context, meta);
|
|
176437
|
+
}
|
|
176438
|
+
}
|
|
176439
|
+
const providerId = config.provider;
|
|
176440
|
+
const provider = SYSTEM_ONE_PROVIDERS[providerId];
|
|
176441
|
+
const target = await this.resolveTarget(providerId);
|
|
176442
|
+
if (!target.ok)
|
|
176443
|
+
return { status: "failed", error: target.error };
|
|
176444
|
+
const { apiKey, endpoint } = target;
|
|
176445
|
+
const model = config.model ?? provider.defaultModel;
|
|
176446
|
+
const body = JSON.stringify({
|
|
176447
|
+
state: config.state,
|
|
176448
|
+
...model === undefined ? {} : { model },
|
|
176449
|
+
questions: config.questions
|
|
176450
|
+
});
|
|
176451
|
+
const scrub = (message) => message.split(apiKey).join("[REDACTED]");
|
|
176452
|
+
const sent = await this.send(providerId, endpoint, apiKey, body, config.timeoutMs, config.maxRetries);
|
|
176453
|
+
if (!sent.ok)
|
|
176454
|
+
return { status: "failed", error: scrub(sent.error) };
|
|
176455
|
+
let parsed;
|
|
176456
|
+
try {
|
|
176457
|
+
parsed = JSON.parse(sent.text);
|
|
176458
|
+
} catch {
|
|
176459
|
+
return { status: "failed", error: "SystemOne response was not valid JSON" };
|
|
176460
|
+
}
|
|
176461
|
+
let decision;
|
|
176462
|
+
try {
|
|
176463
|
+
decision = validateSystemOneResponse(config.questions, parsed, sent.requestId, provider.confidenceField);
|
|
176464
|
+
} catch (err) {
|
|
176465
|
+
if (err instanceof SystemOneContractError) {
|
|
176466
|
+
return {
|
|
176467
|
+
status: "failed",
|
|
176468
|
+
error: scrub(`SystemOne response failed validation: ${err.message}`)
|
|
176469
|
+
};
|
|
176470
|
+
}
|
|
176471
|
+
throw err;
|
|
176472
|
+
}
|
|
176473
|
+
if (!config.humanReview)
|
|
176474
|
+
return { status: "success", output: decision };
|
|
176475
|
+
return this.reviewDecision(config, config.humanReview, decision, context, meta);
|
|
176476
|
+
}
|
|
176477
|
+
async reviewDecision(config, review, decision, context, meta) {
|
|
176478
|
+
const questions = {};
|
|
176479
|
+
for (const [id, answer] of Object.entries(decision.answers)) {
|
|
176480
|
+
const confidence = answerConfidence(answer);
|
|
176481
|
+
questions[id] = {
|
|
176482
|
+
confidence,
|
|
176483
|
+
inBand: confidence >= review.band.min && confidence <= review.band.max,
|
|
176484
|
+
decidedBy: "model"
|
|
176485
|
+
};
|
|
176486
|
+
}
|
|
176487
|
+
if (!Object.values(questions).some((question) => question.inBand)) {
|
|
176488
|
+
return {
|
|
176489
|
+
status: "success",
|
|
176490
|
+
output: { ...decision, review: { status: "not_required", questions } },
|
|
176491
|
+
nextPort: "approved"
|
|
176492
|
+
};
|
|
176493
|
+
}
|
|
176494
|
+
const parked = {
|
|
176495
|
+
...decision,
|
|
176496
|
+
review: { status: "pending", questions }
|
|
176497
|
+
};
|
|
176498
|
+
await this.deps.db.updateWorkflowRunStep(meta.stepId, { output: parked });
|
|
176499
|
+
return this.handOffToReviewer(config, parked, context, meta);
|
|
176500
|
+
}
|
|
176501
|
+
async readParked(stepId) {
|
|
176502
|
+
const step = await this.deps.db.getWorkflowRunStep(stepId);
|
|
176503
|
+
const parked = SystemOneDecisionOutputSchema.safeParse(step?.output);
|
|
176504
|
+
return parked.success && parked.data.review?.status === "pending" ? parked.data : null;
|
|
176505
|
+
}
|
|
176506
|
+
async handOffToReviewer(config, parked, context, meta) {
|
|
176507
|
+
if (!parked || !config.humanReview) {
|
|
176508
|
+
return {
|
|
176509
|
+
status: "failed",
|
|
176510
|
+
error: "The decision this step parked with is missing, so its approval cannot be resumed. Run the node again."
|
|
176511
|
+
};
|
|
176512
|
+
}
|
|
176513
|
+
const result = await new HumanInTheLoopExecutor(this.deps).run({
|
|
176514
|
+
config: buildReviewCard(meta.nodeId, config, config.humanReview, parked),
|
|
176515
|
+
context,
|
|
176516
|
+
meta
|
|
176517
|
+
});
|
|
176518
|
+
if (result.status === "failed")
|
|
176519
|
+
return { status: "failed", error: result.error };
|
|
176520
|
+
if ("async" in result)
|
|
176521
|
+
return result;
|
|
176522
|
+
const answered = result.output;
|
|
176523
|
+
const outcome = answered ? this.resolveApproval(parked, {
|
|
176524
|
+
requestId: answered.requestId,
|
|
176525
|
+
status: answered.status,
|
|
176526
|
+
responses: answered.responses
|
|
176527
|
+
}) : null;
|
|
176528
|
+
if (!outcome) {
|
|
176529
|
+
return {
|
|
176530
|
+
status: "failed",
|
|
176531
|
+
error: "The approval was answered but its result could not be applied"
|
|
176532
|
+
};
|
|
176533
|
+
}
|
|
176534
|
+
return {
|
|
176535
|
+
status: "success",
|
|
176536
|
+
output: outcome.output,
|
|
176537
|
+
nextPort: outcome.nextPort
|
|
176538
|
+
};
|
|
176539
|
+
}
|
|
176540
|
+
resolveApproval(parkedOutput, approval) {
|
|
176541
|
+
return resolveReviewedDecision(parkedOutput, approval);
|
|
176542
|
+
}
|
|
176543
|
+
async send(providerId, endpoint, apiKey, body, timeoutMs, maxRetries) {
|
|
176544
|
+
const doFetch = this.options.fetch ?? fetch;
|
|
176545
|
+
const sleep = this.options.sleep ?? defaultSleep;
|
|
176546
|
+
const now = this.options.now ?? Date.now;
|
|
176547
|
+
const random = this.options.random ?? Math.random;
|
|
176548
|
+
const deadlineAt = now() + timeoutMs - DEADLINE_MARGIN_MS;
|
|
176549
|
+
const controller = new AbortController;
|
|
176550
|
+
const timer = setTimeout(() => controller.abort(), Math.max(0, deadlineAt - now()));
|
|
176551
|
+
const timedOut = () => ({
|
|
176552
|
+
ok: false,
|
|
176553
|
+
error: `SystemOne request exceeded its ${timeoutMs}ms time budget`
|
|
176554
|
+
});
|
|
176555
|
+
try {
|
|
176556
|
+
for (let attempt = 0;; attempt++) {
|
|
176557
|
+
const result = await this.attemptOnce(doFetch, providerId, endpoint, apiKey, body, controller.signal, now);
|
|
176558
|
+
if (result.kind === "ok") {
|
|
176559
|
+
return { ok: true, text: result.text, requestId: result.requestId };
|
|
176560
|
+
}
|
|
176561
|
+
if (result.kind === "timeout" || controller.signal.aborted)
|
|
176562
|
+
return timedOut();
|
|
176563
|
+
const attempts = attempt + 1;
|
|
176564
|
+
const suffix = attempts > 1 ? ` after ${attempts} attempts` : "";
|
|
176565
|
+
if (!result.retryable || attempt >= maxRetries) {
|
|
176566
|
+
return { ok: false, error: `${result.message}${suffix}` };
|
|
176567
|
+
}
|
|
176568
|
+
const backoff = Math.min(BACKOFF_CAP_MS, BACKOFF_BASE_MS * 2 ** attempt);
|
|
176569
|
+
const delay = result.retryAfterMs ?? Math.round(backoff * (0.5 + random() * 0.5));
|
|
176570
|
+
if (delay >= deadlineAt - now()) {
|
|
176571
|
+
return {
|
|
176572
|
+
ok: false,
|
|
176573
|
+
error: `${result.message}${suffix}; the ${delay}ms retry delay does not fit the ${timeoutMs}ms time budget`
|
|
176574
|
+
};
|
|
176575
|
+
}
|
|
176576
|
+
await sleep(delay, controller.signal);
|
|
176577
|
+
if (controller.signal.aborted)
|
|
176578
|
+
return timedOut();
|
|
176579
|
+
}
|
|
176580
|
+
} finally {
|
|
176581
|
+
clearTimeout(timer);
|
|
176582
|
+
}
|
|
176583
|
+
}
|
|
176584
|
+
async attemptOnce(doFetch, providerId, endpoint, apiKey, body, signal, now) {
|
|
176585
|
+
let res;
|
|
176586
|
+
try {
|
|
176587
|
+
res = await doFetch(endpoint, {
|
|
176588
|
+
method: "POST",
|
|
176589
|
+
headers: {
|
|
176590
|
+
"content-type": "application/json",
|
|
176591
|
+
accept: "application/json",
|
|
176592
|
+
authorization: `Bearer ${apiKey}`
|
|
176593
|
+
},
|
|
176594
|
+
body,
|
|
176595
|
+
redirect: "manual",
|
|
176596
|
+
signal
|
|
176597
|
+
});
|
|
176598
|
+
} catch (err) {
|
|
176599
|
+
if (signal.aborted)
|
|
176600
|
+
return { kind: "timeout" };
|
|
176601
|
+
const code2 = err?.code;
|
|
176602
|
+
const detail2 = typeof code2 === "string" && /^[A-Z0-9_]{3,40}$/.test(code2) ? ` (${code2})` : "";
|
|
176603
|
+
return {
|
|
176604
|
+
kind: "fail",
|
|
176605
|
+
message: `SystemOne request failed: network error${detail2}`,
|
|
176606
|
+
retryable: true
|
|
176607
|
+
};
|
|
176608
|
+
}
|
|
176609
|
+
const requestId = readRequestId(res.headers);
|
|
176610
|
+
const withId = (message) => requestId ? `${message} [request ${requestId}]` : message;
|
|
176611
|
+
if (res.status >= 200 && res.status < 300) {
|
|
176612
|
+
let text;
|
|
176613
|
+
try {
|
|
176614
|
+
text = await res.text();
|
|
176615
|
+
} catch {
|
|
176616
|
+
if (signal.aborted)
|
|
176617
|
+
return { kind: "timeout" };
|
|
176618
|
+
return {
|
|
176619
|
+
kind: "fail",
|
|
176620
|
+
message: withId("SystemOne response body could not be read"),
|
|
176621
|
+
retryable: true
|
|
176622
|
+
};
|
|
176623
|
+
}
|
|
176624
|
+
if (text.length > MAX_RESPONSE_CHARS) {
|
|
176625
|
+
return {
|
|
176626
|
+
kind: "fail",
|
|
176627
|
+
message: withId("SystemOne response exceeded the size limit"),
|
|
176628
|
+
retryable: false
|
|
176629
|
+
};
|
|
176630
|
+
}
|
|
176631
|
+
return { kind: "ok", text, requestId };
|
|
176632
|
+
}
|
|
176633
|
+
if (res.status >= 300 && res.status < 400) {
|
|
176634
|
+
return {
|
|
176635
|
+
kind: "fail",
|
|
176636
|
+
message: withId(`SystemOne request was redirected (HTTP ${res.status}); redirects are refused`),
|
|
176637
|
+
retryable: false
|
|
176638
|
+
};
|
|
176639
|
+
}
|
|
176640
|
+
let errorText = "";
|
|
176641
|
+
try {
|
|
176642
|
+
errorText = await res.text();
|
|
176643
|
+
} catch {
|
|
176644
|
+
if (signal.aborted)
|
|
176645
|
+
return { kind: "timeout" };
|
|
176646
|
+
}
|
|
176647
|
+
const code = readErrorCode(errorText);
|
|
176648
|
+
if (res.status === 401 || res.status === 403) {
|
|
176649
|
+
return {
|
|
176650
|
+
kind: "fail",
|
|
176651
|
+
message: withId(systemOneKeyRejectedMessage(providerId, res.status, code)),
|
|
176652
|
+
retryable: false
|
|
176653
|
+
};
|
|
176654
|
+
}
|
|
176655
|
+
const detail = code ? ` (${code})` : "";
|
|
176656
|
+
const retryable = res.status === 408 || res.status === 429 || res.status >= 500;
|
|
176657
|
+
return {
|
|
176658
|
+
kind: "fail",
|
|
176659
|
+
message: withId(`SystemOne API returned HTTP ${res.status}${detail}`),
|
|
176660
|
+
retryable,
|
|
176661
|
+
retryAfterMs: retryable ? parseRetryAfter(res.headers.get("retry-after"), now()) : undefined
|
|
176662
|
+
};
|
|
176663
|
+
}
|
|
176664
|
+
}
|
|
176665
|
+
|
|
175178
176666
|
// src/workflows/definition.ts
|
|
175179
176667
|
function getNextTargets(next) {
|
|
175180
176668
|
if (typeof next === "string")
|
|
@@ -175307,6 +176795,7 @@ function validateDefinition(def, registry, options = {}) {
|
|
|
175307
176795
|
if (node.type === "human-in-the-loop" && typeof node.config.questions === "string" && !/^\{\{[^}]+\}\}$/.test(node.config.questions.trim())) {
|
|
175308
176796
|
errors.push(`Node "${node.id}" human-in-the-loop config.questions must be an array or one exact {{interpolation}} token`);
|
|
175309
176797
|
}
|
|
176798
|
+
errors.push(...systemOneStaticShapeViolations(node), ...systemOneRetryViolations(node));
|
|
175310
176799
|
if (node.type === "foreach") {
|
|
175311
176800
|
validateForeachNode(node, errors);
|
|
175312
176801
|
if (node.id.includes("#")) {
|
|
@@ -182044,25 +183533,25 @@ init_db();
|
|
|
182044
183533
|
|
|
182045
183534
|
// src/apps/format-upgrades.ts
|
|
182046
183535
|
var CURRENT_APP_SCHEMA_VERSION = 1;
|
|
182047
|
-
function
|
|
183536
|
+
function isRecord2(value) {
|
|
182048
183537
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
182049
183538
|
}
|
|
182050
183539
|
function upgradeFrom0(raw) {
|
|
182051
183540
|
const upgraded = { ...raw };
|
|
182052
|
-
if (
|
|
183541
|
+
if (isRecord2(upgraded.page) && !Object.hasOwn(upgraded, "pages")) {
|
|
182053
183542
|
upgraded.pages = { main: upgraded.page };
|
|
182054
183543
|
upgraded.defaultPage = "main";
|
|
182055
183544
|
}
|
|
182056
183545
|
delete upgraded.page;
|
|
182057
|
-
if (
|
|
183546
|
+
if (isRecord2(upgraded.models)) {
|
|
182058
183547
|
upgraded.models = Object.fromEntries(Object.entries(upgraded.models).map(([modelName, model]) => {
|
|
182059
|
-
if (!
|
|
183548
|
+
if (!isRecord2(model))
|
|
182060
183549
|
return [modelName, model];
|
|
182061
183550
|
const upgradedModel = { ...model };
|
|
182062
183551
|
delete upgradedModel.sources;
|
|
182063
|
-
if (
|
|
183552
|
+
if (isRecord2(upgradedModel.columns)) {
|
|
182064
183553
|
upgradedModel.columns = Object.fromEntries(Object.entries(upgradedModel.columns).map(([columnName, column]) => {
|
|
182065
|
-
if (!
|
|
183554
|
+
if (!isRecord2(column))
|
|
182066
183555
|
return [columnName, column];
|
|
182067
183556
|
const upgradedColumn = { ...column };
|
|
182068
183557
|
delete upgradedColumn.source;
|
|
@@ -182077,13 +183566,13 @@ function upgradeFrom0(raw) {
|
|
|
182077
183566
|
}
|
|
182078
183567
|
var APP_FORMAT_UPGRADES = [{ from: 0, to: 1, upgrade: upgradeFrom0 }];
|
|
182079
183568
|
function schemaVersionOf(raw) {
|
|
182080
|
-
if (!
|
|
183569
|
+
if (!isRecord2(raw) || typeof raw.schemaVersion !== "number" || !Number.isInteger(raw.schemaVersion)) {
|
|
182081
183570
|
return 0;
|
|
182082
183571
|
}
|
|
182083
183572
|
return raw.schemaVersion;
|
|
182084
183573
|
}
|
|
182085
183574
|
function upgradeAppDefinition(raw) {
|
|
182086
|
-
if (!
|
|
183575
|
+
if (!isRecord2(raw))
|
|
182087
183576
|
return raw;
|
|
182088
183577
|
let upgraded = raw;
|
|
182089
183578
|
let version = schemaVersionOf(upgraded);
|
|
@@ -182667,6 +184156,21 @@ export interface SwarmSdk {
|
|
|
182667
184156
|
config_set(args: { key: string; value: unknown; scope?: "global" | "agent" | "repo"; scopeId?: string; isSecret?: boolean }): Promise<unknown>;
|
|
182668
184157
|
config_delete(args: { id: string }): Promise<unknown>;
|
|
182669
184158
|
|
|
184159
|
+
// --- write: model catalog ---
|
|
184160
|
+
modelCatalog_refresh(args?: { force?: boolean }): Promise<unknown>;
|
|
184161
|
+
modelCatalog_overlayUpsert(args: {
|
|
184162
|
+
provider: string;
|
|
184163
|
+
modelId: string;
|
|
184164
|
+
name?: string;
|
|
184165
|
+
releaseDate?: string;
|
|
184166
|
+
contextWindow?: number;
|
|
184167
|
+
maxOutput?: number;
|
|
184168
|
+
reasoningOptions?: Array<{ type: string; values?: string[] }>;
|
|
184169
|
+
pricing?: { input?: number; output?: number; cache_read?: number; cache_write?: number };
|
|
184170
|
+
reason: string;
|
|
184171
|
+
verifiedBy?: string;
|
|
184172
|
+
}): Promise<unknown>;
|
|
184173
|
+
|
|
182670
184174
|
// --- write: slack ---
|
|
182671
184175
|
slack_post(args: { channelId: string; message: string; blocks?: unknown }): Promise<unknown>;
|
|
182672
184176
|
slack_reply(args: { channelId?: string; threadTs?: string; message: string; taskId?: string; blocks?: unknown }): Promise<unknown>;
|
|
@@ -183405,4 +184909,4 @@ void _scriptMain;
|
|
|
183405
184909
|
});
|
|
183406
184910
|
}
|
|
183407
184911
|
|
|
183408
|
-
export { require_dist, isInvalidClientError, assertUrlSafe, publicEndpointSsrfOptions, discoverProtectedResourceMetadata, discoverAuthorizationServerMetadata, normalizeTokenEndpointAuthMethod, resolveAdvertisedTokenEndpointAuthMethod, authMethodForStoredClient, selectDcrTokenEndpointAuthMethod, registerClient, buildAuthorizeUrl, exchangeCodeForTokens, refreshMcpToken, revokeMcpToken, computeExpiresAt, getMcpOAuthToken, findReusableMcpOAuthClient, invalidateMcpOAuthClient, upsertMcpOAuthToken, applyMcpOAuthRefresh, markMcpOAuthTokenStatus, deleteMcpOAuthToken, insertMcpOAuthPending, consumeMcpOAuthPending, gcMcpOAuthPending, setMcpServerAuthMethod, ensureMcpToken, callMcpServerTool, listVendoredOpenapiEntries, ConnectionAuthInputSchema, connectionAuthSummary, listRelationalCredentialBindings, getCredentialBindingById, findCredentialBindingByIdentity, upsertCredentialBinding, disableCredentialBinding, listScriptConnections, listScriptConnectionsAsync, getScriptConnectionById, ScriptConnectionConflictError, connectionAuthInputFromFlat, upsertScriptConnection, refreshScriptConnection, setScriptConnectionEnabled, getScriptApiConnectionDescriptors, getScriptMcpConnectionDescriptors, getScriptApiTypes, getScriptMcpTypes, oauthAppToProviderConfig, getOAuthProviderConfig, getOAuthBindingTokenStatus, buildScriptCredentialBindingsWithFailures, buildScriptCredentialBindings, upsertScriptByName, getScript, getScriptById, getScriptVersion, listScripts, listScriptVersions, deleteScript, touchScratchScriptLastUsed, restoreScratchScriptLastUsedIfUnchanged, createScriptApi, listScriptApisForScript, getScriptApiById, getScriptApiSecret, updateScriptApi, rotateScriptApiSecret, deleteScriptApi, recordScriptApiUsage, buildSandboxedCommand, sandboxSpawnEnv, createCappedStreamState, snapshotCapped, readStreamCapped, writeBareImportShim, MIN_SCRIPT_WALL_CLOCK_MS, SCRIPT_LONG_TIMEOUT_HINT_MS, MAX_SCRIPT_WALL_CLOCK_MS, DEFAULT_SCRIPT_RESOURCES, require_typescript, checkImportAllowlist, validateScriptImports, runScript, getNextTargets, generateEdges, findEntryNodes, resolveValidationPort, getSuccessors, definitionNodeIds, validateDefinition, applyDefinitionPatch, extractScriptSignature, extractArgsJsonSchema, getSavedScriptOwnerAgentId, runSavedScriptAsAgent, resolveSyncRunAs, AppNameSchema, ColumnKindSchema, isIso8601Date, SYSTEM_COLUMN_KINDS, SORTABLE_SYSTEM_DATE_COLUMNS, AppElementsSchema, AppDefinitionSchema, collectScriptReferences, parseAppDefinition, applyAppDefinitionPatch, upgradeAppDefinition, decodeAppDefinition, appDefinitionNeedsRepair, createApp, getApp, listApps, listAppRecords, updateApp, deleteApp, getScriptAppTypes, SCRIPT_SDK_TYPES, scriptSdkTypesWithGeneratedApis, SCRIPT_STDLIB_MODULE_TYPES, scriptStdlibTypesWithGeneratedApis, typecheckWithAmbient, typecheckScript };
|
|
184912
|
+
export { require_dist, isInvalidClientError, assertUrlSafe, publicEndpointSsrfOptions, discoverProtectedResourceMetadata, discoverAuthorizationServerMetadata, normalizeTokenEndpointAuthMethod, resolveAdvertisedTokenEndpointAuthMethod, authMethodForStoredClient, selectDcrTokenEndpointAuthMethod, registerClient, buildAuthorizeUrl, exchangeCodeForTokens, refreshMcpToken, revokeMcpToken, computeExpiresAt, getMcpOAuthToken, findReusableMcpOAuthClient, invalidateMcpOAuthClient, upsertMcpOAuthToken, applyMcpOAuthRefresh, markMcpOAuthTokenStatus, deleteMcpOAuthToken, insertMcpOAuthPending, consumeMcpOAuthPending, gcMcpOAuthPending, setMcpServerAuthMethod, ensureMcpToken, callMcpServerTool, listVendoredOpenapiEntries, ConnectionAuthInputSchema, connectionAuthSummary, listRelationalCredentialBindings, getCredentialBindingById, findCredentialBindingByIdentity, upsertCredentialBinding, disableCredentialBinding, listScriptConnections, listScriptConnectionsAsync, getScriptConnectionById, ScriptConnectionConflictError, connectionAuthInputFromFlat, upsertScriptConnection, refreshScriptConnection, setScriptConnectionEnabled, getScriptApiConnectionDescriptors, getScriptMcpConnectionDescriptors, getScriptApiTypes, getScriptMcpTypes, oauthAppToProviderConfig, getOAuthProviderConfig, getOAuthBindingTokenStatus, buildScriptCredentialBindingsWithFailures, buildScriptCredentialBindings, upsertScriptByName, getScript, getScriptById, getScriptVersion, listScripts, listScriptVersions, deleteScript, touchScratchScriptLastUsed, restoreScratchScriptLastUsedIfUnchanged, createScriptApi, listScriptApisForScript, getScriptApiById, getScriptApiSecret, updateScriptApi, rotateScriptApiSecret, deleteScriptApi, recordScriptApiUsage, buildSandboxedCommand, sandboxSpawnEnv, createCappedStreamState, snapshotCapped, readStreamCapped, writeBareImportShim, MIN_SCRIPT_WALL_CLOCK_MS, SCRIPT_LONG_TIMEOUT_HINT_MS, MAX_SCRIPT_WALL_CLOCK_MS, DEFAULT_SCRIPT_RESOURCES, require_typescript, checkImportAllowlist, validateScriptImports, runScript, BaseExecutor, postApprovalCancellationUpdates, createApprovalFollowUpTask, HumanInTheLoopExecutor, resolveWorkflowLlmConfig, SYSTEM_ONE_DECISION_NODE_TYPE, systemOneRetryViolations, systemOneUnresolvedError, SystemOneDecisionExecutor, getNextTargets, generateEdges, findEntryNodes, resolveValidationPort, getSuccessors, definitionNodeIds, validateDefinition, applyDefinitionPatch, extractScriptSignature, extractArgsJsonSchema, getSavedScriptOwnerAgentId, runSavedScriptAsAgent, resolveSyncRunAs, AppNameSchema, ColumnKindSchema, isIso8601Date, SYSTEM_COLUMN_KINDS, SORTABLE_SYSTEM_DATE_COLUMNS, AppElementsSchema, AppDefinitionSchema, collectScriptReferences, parseAppDefinition, applyAppDefinitionPatch, upgradeAppDefinition, decodeAppDefinition, appDefinitionNeedsRepair, createApp, getApp, listApps, listAppRecords, updateApp, deleteApp, getScriptAppTypes, SCRIPT_SDK_TYPES, scriptSdkTypesWithGeneratedApis, SCRIPT_STDLIB_MODULE_TYPES, scriptStdlibTypesWithGeneratedApis, typecheckWithAmbient, typecheckScript };
|