@desplega.ai/agent-swarm 2.4.3 → 2.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{acp-adapter-1885dpr7.js → acp-adapter-thq04adh.js} +1 -2
- package/dist/{actions-pn76n32q.js → actions-j6ywh6x5.js} +17 -17
- package/dist/{amp-adapter-af84rx1d.js → amp-adapter-k8b5xmj8.js} +2 -2
- package/dist/{app-6sv8mhzm.js → app-rb7vc02s.js} +3 -3
- package/dist/{assistant-sc2tf825.js → assistant-ftta1zjf.js} +18 -18
- package/dist/{boot-reembed-y3m0ydzj.js → boot-reembed-srp6v6af.js} +1 -1
- package/dist/{boot-reembed-gvxjs2py.js → boot-reembed-xns7h5h9.js} +1 -1
- package/dist/{boot-scrub-sweep-1j9mk05f.js → boot-scrub-sweep-3qqrh2mz.js} +2 -2
- package/dist/{boot-seeds-37sp626b.js → boot-seeds-9ks8hce7.js} +4 -4
- package/dist/{claude-adapter-rp0jtnwr.js → claude-adapter-k5ksyres.js} +2 -2
- package/dist/{claude-managed-setup-rdt248k7.js → claude-managed-setup-n5a5eqks.js} +1 -1
- package/dist/{claude-sdk-session-53rcw5we.js → claude-sdk-session-2j3j4kwn.js} +2 -2
- package/dist/{cli-v87dr6e3.js → cli-1d70crsy.js} +1 -1
- package/dist/{cli-1ma335fz.js → cli-1ephgwnq.js} +2 -2
- package/dist/{cli-4yef8ghv.js → cli-2v045xyf.js} +3 -3
- package/dist/{cli-73ezfhha.js → cli-2y91wnbh.js} +10 -5
- package/dist/{cli-1eszr343.js → cli-2zqpkvtt.js} +1 -1
- package/dist/{cli-e4d78xsv.js → cli-37yb7307.js} +1 -1
- package/dist/{cli-8y99kfey.js → cli-3cgngyd8.js} +9 -9
- package/dist/{cli-wk28hzqn.js → cli-44159k28.js} +1 -1
- package/dist/{cli-qp2m4btv.js → cli-4dg55wsk.js} +2 -2
- package/dist/{cli-0dxxwfkt.js → cli-51y09c6p.js} +17 -14
- package/dist/{cli-aa3tb29r.js → cli-55qmbp6z.js} +1 -1
- package/dist/{cli-mzkwkbdy.js → cli-82d3nkc3.js} +1 -1
- package/dist/{cli-sds5zzs8.js → cli-9fhkkpj5.js} +78 -12
- package/dist/{cli-vq9gqarq.js → cli-amyhm3gj.js} +1 -1
- package/dist/{cli-bxrqvpg5.js → cli-b8k7epj1.js} +5 -5
- package/dist/{cli-8vverzf7.js → cli-ba8ne1es.js} +5 -0
- package/dist/{cli-58vwn100.js → cli-bnz0r3kc.js} +1 -1
- package/dist/{cli-6eyncg0y.js → cli-cynvc9fj.js} +34 -6
- package/dist/{cli-f0p0f6ja.js → cli-dqb4n629.js} +7 -7
- package/dist/{cli-pygdsgh8.js → cli-esxerzg7.js} +1 -1
- package/dist/{cli-dm8p2dpf.js → cli-gqvh8d8a.js} +6 -6
- package/dist/{cli-p0qerd2r.js → cli-hj3debgw.js} +1 -1
- package/dist/{cli-836ehxmt.js → cli-nc35pxb7.js} +2 -2
- package/dist/{cli-vcgscaan.js → cli-p20r8w42.js} +8 -6
- package/dist/{cli-1xsraagq.js → cli-pccfmtb5.js} +4 -4
- package/dist/{cli-s9rr4gr2.js → cli-q6r7t299.js} +1036 -298
- package/dist/{cli-tkf4x6ha.js → cli-qkhc5aqy.js} +11 -11
- package/dist/{cli-1n9gdg56.js → cli-t7cyef5g.js} +4 -4
- package/dist/{cli-038fga5k.js → cli-te6b5wvg.js} +148 -183
- package/dist/{cli-kgnkyabk.js → cli-v3yr2gbg.js} +109 -35
- package/dist/{cli-h0mgxann.js → cli-vdm20wej.js} +2 -2
- package/dist/{cli-zvbb4n0e.js → cli-vq97g1jq.js} +2 -2
- package/dist/{cli-gx0j2khs.js → cli-w6nadkh4.js} +3 -3
- package/dist/{cli-99jez72r.js → cli-w9etnnxk.js} +6 -1
- package/dist/{cli-npfe9t1s.js → cli-xc27fwzg.js} +2 -2
- package/dist/{cli-6aen3ezb.js → cli-xj0re5tm.js} +1 -1
- package/dist/{cli-aypbg9r2.js → cli-zrk6jxv8.js} +1 -1
- package/dist/{cli-1012xb7j.js → cli-zrwpctp4.js} +20 -20
- package/dist/cli.js +41 -16
- package/dist/{codex-adapter-2zrmab9b.js → codex-adapter-968xwfy7.js} +1 -1
- package/dist/{codex-session-runner-kbkz62vc.js → codex-session-runner-ht4z99fa.js} +1 -1
- package/dist/{commands-hd574th6.js → commands-pcymaeg9.js} +2 -2
- package/dist/{controller-pz5mcfg4.js → controller-fpjyk46r.js} +2 -2
- package/dist/{controllers-connect-5rgq2hfk.js → controllers-connect-mwzx1fh6.js} +18 -18
- package/dist/{cursor-adapter-mgaprq0j.js → cursor-adapter-cp4s2e2f.js} +1 -1
- package/dist/{db-h06dxp05.js → db-sgd12bt9.js} +3 -3
- package/dist/{db-6nf1207q.js → db-xsjg9jqq.js} +1 -1
- package/dist/{dispatcher-zthpy4m1.js → dispatcher-x0jfw2c9.js} +16 -16
- package/dist/{dsh-adapter-64dhw0j7.js → dsh-adapter-jrq7ma7h.js} +1 -1
- package/dist/{external-channel-x01t7ke6.js → external-channel-8njj4h3b.js} +2 -2
- package/dist/{grok-adapter-h21jv594.js → grok-adapter-kkr97v2f.js} +2 -3
- package/dist/handlers-0pvee9nw.js +39 -0
- package/dist/{heartbeat-zzfksckz.js → heartbeat-wd03zhn0.js} +19 -19
- package/dist/{hook-z4zhzj1f.js → hook-f0vghj42.js} +1 -1
- package/dist/{hook-3xfqhh2s.js → hook-xzj2ts2p.js} +1 -1
- package/dist/{http-q813tmya.js → http-4hwxv62p.js} +255 -117
- package/dist/{index-va3y63es.js → index-6srwvd5b.js} +1 -2
- package/dist/{index-220tk9bw.js → index-97q4xn03.js} +19 -10
- package/dist/{index-s98037v0.js → index-cbxkmfc5.js} +1 -2
- package/dist/{index-m0a4ydqj.js → index-gdh8jrdm.js} +16 -16
- package/dist/{index-wbbs14c5.js → index-hg0x2cdv.js} +16 -16
- package/dist/{index-d0g18bax.js → index-thm0y6a8.js} +19 -19
- package/dist/{index-x8xbyn1t.js → index-ww2vznkp.js} +1 -1
- package/dist/{keepalive-y5t1my7m.js → keepalive-hrh7xnr9.js} +3 -3
- package/dist/{lead-2xwtq66b.js → lead-ee8vazz2.js} +26 -27
- package/dist/{maintenance-ybfsaedv.js → maintenance-e8wnwnqx.js} +1 -1
- package/dist/{oauth-refresh-sweep-909jmn12.js → oauth-refresh-sweep-zm0yj4sj.js} +2 -2
- package/dist/{onboard-xn6fkkys.js → onboard-dtwcq603.js} +2 -2
- package/dist/{otel-impl-e6mn0z13.js → otel-impl-w3fbhpn0.js} +1 -1
- package/dist/{pricing-refresh-ygd362ep.js → pricing-refresh-j38dehfs.js} +3 -3
- package/dist/{rbac-roles-c9axvfnz.js → rbac-roles-ae8yttq4.js} +2 -2
- package/dist/{rbac-roles-mb470p4e.js → rbac-roles-ejxx9b35.js} +2 -2
- package/dist/{render-v2-g0306nh1.js → render-v2-n16n0phe.js} +3 -3
- package/dist/{resume-v315hnq6.js → resume-z0fgjc38.js} +5 -5
- package/dist/{session-access-2zg285a1.js → session-access-cv3mq6mc.js} +6 -4
- package/dist/{setup-a4mtf02k.js → setup-mafhj3yt.js} +1 -1
- package/dist/{work-objects-9fr0fgtn.js → work-objects-8b86mgjp.js} +19 -19
- package/dist/{worker-qae22jeb.js → worker-16s75hm5.js} +26 -27
- package/dist/worker-token-xf11yyds.js +136 -0
- package/openapi.json +295 -12
- package/package.json +4 -4
- package/src/apps/action-runner.ts +4 -0
- package/src/apps/catalog.generated.json +3 -0
- package/src/apps/page-validator.ts +8 -2
- package/src/be/migrations/232_agent_session_tokens.sql +41 -0
- package/src/be/seed-scripts/catalog/heartbeat-jev-gate.ts +10 -1
- package/src/be/swarm-config-guard.ts +16 -0
- package/src/be/users.ts +169 -12
- package/src/cli.tsx +24 -0
- package/src/commands/worker-token.ts +164 -0
- package/src/http/apps.ts +43 -5
- package/src/http/codex-oauth-keep-warm.ts +27 -9
- package/src/http/config.ts +5 -3
- package/src/http/core.ts +2 -0
- package/src/http/session-access.ts +51 -2
- package/src/http/sessions.ts +249 -10
- package/src/http/tasks.ts +4 -32
- package/src/providers/acp-adapter.ts +33 -13
- package/src/providers/acp-swarm-events.ts +1 -1
- package/src/providers/amp-adapter.ts +1 -1
- package/src/providers/codex-oauth/storage.ts +1 -1
- package/src/rbac/legacy-policy.ts +3 -1
- package/src/rbac/permissions.ts +4 -0
- package/src/tests/acp-adapter.test.ts +10 -23
- package/src/tests/acp-fake-agent.ts +36 -0
- package/src/tests/acp-swarm-events.test.ts +1 -1
- package/src/tests/agent-session-tokens.test.ts +452 -0
- package/src/tests/apps-action-parent-task.test.ts +295 -0
- package/src/tests/codex-oauth-keep-warm.test.ts +85 -1
- package/src/tests/config-session-auth.test.ts +14 -0
- package/src/tests/docs-index-footprint.test.js +2 -2
- package/src/tests/grok-adapter.test.ts +3 -3
- package/src/tests/heartbeat-jev-gate.test.ts +23 -0
- package/src/tests/migration-232-agent-session-tokens.test.ts +67 -0
- package/src/tests/rbac-engine.test.ts +1 -0
- package/src/tests/runtime-child-token-cleanup.test.ts +3 -3
- package/src/tests/script-connections.test.ts +2 -0
- package/src/tests/session-route-posture.test.ts +2 -0
- package/src/tests/worker-token-cli.test.ts +76 -0
- package/src/tests/workflow-executors.test.ts +4 -2
- package/src/tests/workflow-system-one-extraction.test.ts +805 -0
- package/src/types.ts +2 -1
- package/src/utils/request-auth-context.ts +2 -1
- package/src/workflows/definition.ts +7 -1
- package/src/workflows/engine.ts +18 -12
- package/src/workflows/executors/index.ts +1 -0
- package/src/workflows/executors/registry.ts +2 -0
- package/src/workflows/executors/system-one-decision.ts +56 -255
- package/src/workflows/executors/system-one-extract-wire.ts +57 -0
- package/src/workflows/executors/system-one-extraction.ts +830 -0
- package/src/workflows/executors/system-one-providers.ts +277 -110
- package/src/workflows/executors/system-one-transport.ts +264 -0
- package/templates/official/lead/HEARTBEAT.md +1 -1
- package/templates/skills/apps/SKILL.md +3 -1
- package/templates/skills/apps/content.md +3 -1
- package/templates/skills/heartbeat-runbook/content.md +3 -3
- package/dist/cli-v1sjhn52.js +0 -7
- package/dist/handlers-2qjw434w.js +0 -39
package/openapi.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"openapi": "3.1.0",
|
|
3
3
|
"info": {
|
|
4
4
|
"title": "Agent Swarm API",
|
|
5
|
-
"version": "2.4.
|
|
5
|
+
"version": "2.4.4",
|
|
6
6
|
"description": "Multi-agent orchestration API for Claude Code, Codex, and Gemini CLI. Enables task distribution, agent communication, and service discovery.\n\nMCP tools are documented separately in [MCP.md](./MCP.md)."
|
|
7
7
|
},
|
|
8
8
|
"servers": [
|
|
@@ -4680,7 +4680,7 @@
|
|
|
4680
4680
|
},
|
|
4681
4681
|
"type": {
|
|
4682
4682
|
"type": "string",
|
|
4683
|
-
"description": "Executor type: 'agent-task', 'script', 'swarm-script', 'raw-llm', 'system-one-decision', 'validate', 'property-match'"
|
|
4683
|
+
"description": "Executor type: 'agent-task', 'script', 'swarm-script', 'raw-llm', 'system-one-decision', 'system-one-extraction', 'validate', 'property-match'"
|
|
4684
4684
|
},
|
|
4685
4685
|
"label": {
|
|
4686
4686
|
"type": "string",
|
|
@@ -4689,7 +4689,7 @@
|
|
|
4689
4689
|
"config": {
|
|
4690
4690
|
"type": "object",
|
|
4691
4691
|
"additionalProperties": {},
|
|
4692
|
-
"description": "Executor-specific config. For agent-task: { template, outputSchema?, agentId?, routingReason?, routingNote?, tags?, priority?, dir?, vcsRepo?, model? }; configured agentId defaults routingReason to human_pinned. For script: { runtime, script, args?, timeout? }. For swarm-script: { scriptName, scope?, pinHash?, args?, fsMode?, timeoutMs? (1000-300000) }. For system-one-decision (typed decisions, Jev by default): { provider? ('typesafe' default | 'openrouter' | 'laya'; a literal, never a {{token}}), state, questions: { <id>: { type: 'noul'|'choice'|'score', instructions, criteria? } }, returns: { <id>: { type } }, model? (provider-specific; unset = the provider's default, and laya has none so it sends no model and picks its own checkpoint), timeoutMs?, maxRetries? (0-3), humanReview? { band: { min, max } (0-1, inclusive), approvers: { users?, roles?, policy }, title?, timeout?, notifications? } }; each provider needs its own global secret (TYPESAFE_API_KEY, OPENROUTER_API_KEY, or LAYA_API_KEY; laya also needs the global config LAYA_URL), and a save warns and a run fails before any node executes when one is missing; system-one-decision nodes must not set retry or validation.retry. With humanReview, an answer whose confidence is inside the band waits for a person (human-in-the-loop approval), and next must map ports { approved, rejected?, timeout? }. Agent-task templates and ordinary config values support {{interpolation}} from the node's inputs context, including trigger and declared upstream aliases. SECURITY: executable source for script/swarm-script nodes does not interpolate trigger.* or upstream node outputs; only input/workflow/swarm/run values are allowed in inline script source, and named swarm-script source is not workflow-interpolated. Pass dynamic values through config.args instead (inline script receives them as argv, with runtime: \"bash\" running bash -c <script> ...args so args[0] is $0 and args[1] is $1; swarm-script receives its args object). NOTE: config.outputSchema on agent-task nodes validates the AGENT's raw JSON output, while node-level outputSchema validates the EXECUTOR's return value ({taskId, taskOutput})."
|
|
4692
|
+
"description": "Executor-specific config. For agent-task: { template, outputSchema?, agentId?, routingReason?, routingNote?, tags?, priority?, dir?, vcsRepo?, model? }; configured agentId defaults routingReason to human_pinned. For script: { runtime, script, args?, timeout? }. For swarm-script: { scriptName, scope?, pinHash?, args?, fsMode?, timeoutMs? (1000-300000) }. For system-one-decision (typed decisions, Jev by default): { provider? ('typesafe' default | 'openrouter' | 'laya'; a literal, never a {{token}}), state, questions: { <id>: { type: 'noul'|'choice'|'score', instructions, criteria? } }, returns: { <id>: { type } }, model? (provider-specific; unset = the provider's default, and laya has none so it sends no model and picks its own checkpoint), timeoutMs?, maxRetries? (0-3), humanReview? { band: { min, max } (0-1, inclusive), approvers: { users?, roles?, policy }, title?, timeout?, notifications? } }; each provider needs its own global secret (TYPESAFE_API_KEY, OPENROUTER_API_KEY, or LAYA_API_KEY; laya also needs the global config LAYA_URL), and a save warns and a run fails before any node executes when one is missing; system-one-decision nodes must not set retry or validation.retry. With humanReview, an answer whose confidence is inside the band waits for a person (human-in-the-loop approval), and next must map ports { approved, rejected?, timeout? }. For system-one-extraction (typed extraction, Cloudflare Clairic by default): { provider? ('cloudflare'; a literal), state (text to read; may be empty when images are sent), fields: { <id>: { type: 'text'|'number'|'date'|'time'|'datetime'|'duration'|'list'|'estimate'|'forecast', instructions?, ...type options (number: unit?, integer?, decimals?; duration: unit? (seconds..years), integer?, decimals?; list: items ('text'|'number'|'date'); estimate: min, max, step?, scale?, unit?; forecast: min, max, horizon?, interval?, scale?, unit?; text/number/date/time/datetime/duration: null_threshold?) } }, images? (max 4 base64 data: URLs or { content_type, base64 }), referenceDate? (YYYY-MM-DD), model?, timeoutMs?, maxRetries? (0-3) }; output answers.<id> carries value (null when the input does not say), guess, p_null, confidence, span/spans, and for estimate/forecast median/p10/p90. Needs the global secret CLOUDFLARE_API_TOKEN (or CLOUDFLARE_API_KEY) and the global config CLOUDFLARE_ACCOUNT_ID; must not set retry or validation.retry. Agent-task templates and ordinary config values support {{interpolation}} from the node's inputs context, including trigger and declared upstream aliases. SECURITY: executable source for script/swarm-script nodes does not interpolate trigger.* or upstream node outputs; only input/workflow/swarm/run values are allowed in inline script source, and named swarm-script source is not workflow-interpolated. Pass dynamic values through config.args instead (inline script receives them as argv, with runtime: \"bash\" running bash -c <script> ...args so args[0] is $0 and args[1] is $1; swarm-script receives its args object). NOTE: config.outputSchema on agent-task nodes validates the AGENT's raw JSON output, while node-level outputSchema validates the EXECUTOR's return value ({taskId, taskOutput})."
|
|
4693
4693
|
},
|
|
4694
4694
|
"next": {
|
|
4695
4695
|
"anyOf": [
|
|
@@ -5131,7 +5131,7 @@
|
|
|
5131
5131
|
"properties": {
|
|
5132
5132
|
"type": {
|
|
5133
5133
|
"type": "string",
|
|
5134
|
-
"description": "Executor type: 'agent-task', 'script', 'swarm-script', 'raw-llm', 'system-one-decision', 'validate', 'property-match'"
|
|
5134
|
+
"description": "Executor type: 'agent-task', 'script', 'swarm-script', 'raw-llm', 'system-one-decision', 'system-one-extraction', 'validate', 'property-match'"
|
|
5135
5135
|
},
|
|
5136
5136
|
"label": {
|
|
5137
5137
|
"type": "string",
|
|
@@ -5140,7 +5140,7 @@
|
|
|
5140
5140
|
"config": {
|
|
5141
5141
|
"type": "object",
|
|
5142
5142
|
"additionalProperties": {},
|
|
5143
|
-
"description": "Executor-specific config. For agent-task: { template, outputSchema?, agentId?, routingReason?, routingNote?, tags?, priority?, dir?, vcsRepo?, model? }; configured agentId defaults routingReason to human_pinned. For script: { runtime, script, args?, timeout? }. For swarm-script: { scriptName, scope?, pinHash?, args?, fsMode?, timeoutMs? (1000-300000) }. For system-one-decision (typed decisions, Jev by default): { provider? ('typesafe' default | 'openrouter' | 'laya'; a literal, never a {{token}}), state, questions: { <id>: { type: 'noul'|'choice'|'score', instructions, criteria? } }, returns: { <id>: { type } }, model? (provider-specific; unset = the provider's default, and laya has none so it sends no model and picks its own checkpoint), timeoutMs?, maxRetries? (0-3), humanReview? { band: { min, max } (0-1, inclusive), approvers: { users?, roles?, policy }, title?, timeout?, notifications? } }; each provider needs its own global secret (TYPESAFE_API_KEY, OPENROUTER_API_KEY, or LAYA_API_KEY; laya also needs the global config LAYA_URL), and a save warns and a run fails before any node executes when one is missing; system-one-decision nodes must not set retry or validation.retry. With humanReview, an answer whose confidence is inside the band waits for a person (human-in-the-loop approval), and next must map ports { approved, rejected?, timeout? }. Agent-task templates and ordinary config values support {{interpolation}} from the node's inputs context, including trigger and declared upstream aliases. SECURITY: executable source for script/swarm-script nodes does not interpolate trigger.* or upstream node outputs; only input/workflow/swarm/run values are allowed in inline script source, and named swarm-script source is not workflow-interpolated. Pass dynamic values through config.args instead (inline script receives them as argv, with runtime: \"bash\" running bash -c <script> ...args so args[0] is $0 and args[1] is $1; swarm-script receives its args object). NOTE: config.outputSchema on agent-task nodes validates the AGENT's raw JSON output, while node-level outputSchema validates the EXECUTOR's return value ({taskId, taskOutput})."
|
|
5143
|
+
"description": "Executor-specific config. For agent-task: { template, outputSchema?, agentId?, routingReason?, routingNote?, tags?, priority?, dir?, vcsRepo?, model? }; configured agentId defaults routingReason to human_pinned. For script: { runtime, script, args?, timeout? }. For swarm-script: { scriptName, scope?, pinHash?, args?, fsMode?, timeoutMs? (1000-300000) }. For system-one-decision (typed decisions, Jev by default): { provider? ('typesafe' default | 'openrouter' | 'laya'; a literal, never a {{token}}), state, questions: { <id>: { type: 'noul'|'choice'|'score', instructions, criteria? } }, returns: { <id>: { type } }, model? (provider-specific; unset = the provider's default, and laya has none so it sends no model and picks its own checkpoint), timeoutMs?, maxRetries? (0-3), humanReview? { band: { min, max } (0-1, inclusive), approvers: { users?, roles?, policy }, title?, timeout?, notifications? } }; each provider needs its own global secret (TYPESAFE_API_KEY, OPENROUTER_API_KEY, or LAYA_API_KEY; laya also needs the global config LAYA_URL), and a save warns and a run fails before any node executes when one is missing; system-one-decision nodes must not set retry or validation.retry. With humanReview, an answer whose confidence is inside the band waits for a person (human-in-the-loop approval), and next must map ports { approved, rejected?, timeout? }. For system-one-extraction (typed extraction, Cloudflare Clairic by default): { provider? ('cloudflare'; a literal), state (text to read; may be empty when images are sent), fields: { <id>: { type: 'text'|'number'|'date'|'time'|'datetime'|'duration'|'list'|'estimate'|'forecast', instructions?, ...type options (number: unit?, integer?, decimals?; duration: unit? (seconds..years), integer?, decimals?; list: items ('text'|'number'|'date'); estimate: min, max, step?, scale?, unit?; forecast: min, max, horizon?, interval?, scale?, unit?; text/number/date/time/datetime/duration: null_threshold?) } }, images? (max 4 base64 data: URLs or { content_type, base64 }), referenceDate? (YYYY-MM-DD), model?, timeoutMs?, maxRetries? (0-3) }; output answers.<id> carries value (null when the input does not say), guess, p_null, confidence, span/spans, and for estimate/forecast median/p10/p90. Needs the global secret CLOUDFLARE_API_TOKEN (or CLOUDFLARE_API_KEY) and the global config CLOUDFLARE_ACCOUNT_ID; must not set retry or validation.retry. Agent-task templates and ordinary config values support {{interpolation}} from the node's inputs context, including trigger and declared upstream aliases. SECURITY: executable source for script/swarm-script nodes does not interpolate trigger.* or upstream node outputs; only input/workflow/swarm/run values are allowed in inline script source, and named swarm-script source is not workflow-interpolated. Pass dynamic values through config.args instead (inline script receives them as argv, with runtime: \"bash\" running bash -c <script> ...args so args[0] is $0 and args[1] is $1; swarm-script receives its args object). NOTE: config.outputSchema on agent-task nodes validates the AGENT's raw JSON output, while node-level outputSchema validates the EXECUTOR's return value ({taskId, taskOutput})."
|
|
5144
5144
|
},
|
|
5145
5145
|
"next": {
|
|
5146
5146
|
"anyOf": [
|
|
@@ -9751,6 +9751,10 @@
|
|
|
9751
9751
|
"input": {
|
|
9752
9752
|
"type": "object",
|
|
9753
9753
|
"additionalProperties": {}
|
|
9754
|
+
},
|
|
9755
|
+
"parentTaskId": {
|
|
9756
|
+
"type": "string",
|
|
9757
|
+
"minLength": 1
|
|
9754
9758
|
}
|
|
9755
9759
|
}
|
|
9756
9760
|
}
|
|
@@ -9938,7 +9942,7 @@
|
|
|
9938
9942
|
}
|
|
9939
9943
|
},
|
|
9940
9944
|
"400": {
|
|
9941
|
-
"description": "Invalid action input
|
|
9945
|
+
"description": "Invalid action input, stale script reference, or parentTaskId on a non-task action",
|
|
9942
9946
|
"content": {
|
|
9943
9947
|
"application/json": {
|
|
9944
9948
|
"schema": {
|
|
@@ -9958,7 +9962,7 @@
|
|
|
9958
9962
|
}
|
|
9959
9963
|
},
|
|
9960
9964
|
"404": {
|
|
9961
|
-
"description": "App or
|
|
9965
|
+
"description": "App, action, or parent task not found",
|
|
9962
9966
|
"content": {
|
|
9963
9967
|
"application/json": {
|
|
9964
9968
|
"schema": {
|
|
@@ -16632,7 +16636,7 @@
|
|
|
16632
16636
|
"/api/oauth/keep-warm/codex": {
|
|
16633
16637
|
"post": {
|
|
16634
16638
|
"summary": "Locked keep-warm refresh sweep across all Codex OAuth pool slots",
|
|
16635
|
-
"description": "Enumerates codex_oauth_* slots and refreshes any older than
|
|
16639
|
+
"description": "Enumerates codex_oauth_* slots and refreshes any older than CODEX_OAUTH_KEEP_WARM_MAX_AGE_HOURS (default 120 hours) through the same locked getValidCodexOAuth path used at task time. Skips slots with a codex-auth-watch bench marker (auth-failure bench or codex-auth-expiry-watch).",
|
|
16636
16640
|
"tags": [
|
|
16637
16641
|
"OAuth"
|
|
16638
16642
|
],
|
|
@@ -47902,7 +47906,7 @@
|
|
|
47902
47906
|
"/api/sessions/tokens": {
|
|
47903
47907
|
"post": {
|
|
47904
47908
|
"summary": "Mint an ephemeral task or runtime token",
|
|
47905
|
-
"description": "Operators can mint task or runtime tokens. Runtime tokens can mint task tokens for their own assigned tasks.
|
|
47909
|
+
"description": "Operators can mint task or runtime tokens. Runtime and agent tokens can mint task tokens for their own assigned tasks. A child token never outlives its parent and is revoked with it.",
|
|
47906
47910
|
"tags": [
|
|
47907
47911
|
"Sessions"
|
|
47908
47912
|
],
|
|
@@ -48001,7 +48005,7 @@
|
|
|
48001
48005
|
"/api/sessions/tokens/{tokenId}": {
|
|
48002
48006
|
"delete": {
|
|
48003
48007
|
"summary": "Revoke an ephemeral session token",
|
|
48004
|
-
"description": "Operators can revoke any ephemeral token.
|
|
48008
|
+
"description": "Operators can revoke any ephemeral token. Agent tokens, and runtime tokens when runtime pools are enabled, can revoke their own child task tokens. Repeated revocation has no effect.",
|
|
48005
48009
|
"tags": [
|
|
48006
48010
|
"Sessions"
|
|
48007
48011
|
],
|
|
@@ -48047,6 +48051,285 @@
|
|
|
48047
48051
|
}
|
|
48048
48052
|
}
|
|
48049
48053
|
},
|
|
48054
|
+
"/api/agents/{id}/token": {
|
|
48055
|
+
"post": {
|
|
48056
|
+
"operationId": "agents_mintWorkerToken",
|
|
48057
|
+
"summary": "Mint an agent-bound worker token",
|
|
48058
|
+
"description": "Returns the token once. A worker runs on it in place of the swarm API key and acts only as this agent. Creates the agent when it does not exist and `name` is given. Fails with 409 when the agent already holds an active token.",
|
|
48059
|
+
"tags": [
|
|
48060
|
+
"Sessions"
|
|
48061
|
+
],
|
|
48062
|
+
"security": [
|
|
48063
|
+
{
|
|
48064
|
+
"bearerAuth": []
|
|
48065
|
+
}
|
|
48066
|
+
],
|
|
48067
|
+
"parameters": [
|
|
48068
|
+
{
|
|
48069
|
+
"schema": {
|
|
48070
|
+
"type": "string",
|
|
48071
|
+
"minLength": 1
|
|
48072
|
+
},
|
|
48073
|
+
"required": true,
|
|
48074
|
+
"name": "id",
|
|
48075
|
+
"in": "path"
|
|
48076
|
+
}
|
|
48077
|
+
],
|
|
48078
|
+
"requestBody": {
|
|
48079
|
+
"content": {
|
|
48080
|
+
"application/json": {
|
|
48081
|
+
"schema": {
|
|
48082
|
+
"type": "object",
|
|
48083
|
+
"properties": {
|
|
48084
|
+
"name": {
|
|
48085
|
+
"type": "string",
|
|
48086
|
+
"minLength": 1
|
|
48087
|
+
},
|
|
48088
|
+
"ttlMs": {
|
|
48089
|
+
"type": "integer",
|
|
48090
|
+
"exclusiveMinimum": 0,
|
|
48091
|
+
"description": "Token lifetime in ms. Omit for the default (no expiry)."
|
|
48092
|
+
}
|
|
48093
|
+
},
|
|
48094
|
+
"additionalProperties": false
|
|
48095
|
+
}
|
|
48096
|
+
}
|
|
48097
|
+
}
|
|
48098
|
+
},
|
|
48099
|
+
"responses": {
|
|
48100
|
+
"200": {
|
|
48101
|
+
"description": "Minted worker token",
|
|
48102
|
+
"content": {
|
|
48103
|
+
"application/json": {
|
|
48104
|
+
"schema": {
|
|
48105
|
+
"type": "object",
|
|
48106
|
+
"properties": {
|
|
48107
|
+
"agentId": {
|
|
48108
|
+
"type": "string"
|
|
48109
|
+
},
|
|
48110
|
+
"tokenId": {
|
|
48111
|
+
"type": "string"
|
|
48112
|
+
},
|
|
48113
|
+
"plaintext": {
|
|
48114
|
+
"type": "string"
|
|
48115
|
+
},
|
|
48116
|
+
"expiresAt": {
|
|
48117
|
+
"type": [
|
|
48118
|
+
"string",
|
|
48119
|
+
"null"
|
|
48120
|
+
],
|
|
48121
|
+
"description": "null when the token does not expire"
|
|
48122
|
+
},
|
|
48123
|
+
"agentCreated": {
|
|
48124
|
+
"type": "boolean"
|
|
48125
|
+
}
|
|
48126
|
+
},
|
|
48127
|
+
"required": [
|
|
48128
|
+
"agentId",
|
|
48129
|
+
"tokenId",
|
|
48130
|
+
"plaintext",
|
|
48131
|
+
"expiresAt",
|
|
48132
|
+
"agentCreated"
|
|
48133
|
+
]
|
|
48134
|
+
}
|
|
48135
|
+
}
|
|
48136
|
+
}
|
|
48137
|
+
},
|
|
48138
|
+
"403": {
|
|
48139
|
+
"description": "Operator or user credentials required",
|
|
48140
|
+
"content": {
|
|
48141
|
+
"application/json": {
|
|
48142
|
+
"schema": {
|
|
48143
|
+
"$ref": "#/components/schemas/ErrorResponse"
|
|
48144
|
+
}
|
|
48145
|
+
}
|
|
48146
|
+
}
|
|
48147
|
+
},
|
|
48148
|
+
"404": {
|
|
48149
|
+
"description": "Agent not found and no name given",
|
|
48150
|
+
"content": {
|
|
48151
|
+
"application/json": {
|
|
48152
|
+
"schema": {
|
|
48153
|
+
"$ref": "#/components/schemas/ErrorResponse"
|
|
48154
|
+
}
|
|
48155
|
+
}
|
|
48156
|
+
}
|
|
48157
|
+
},
|
|
48158
|
+
"409": {
|
|
48159
|
+
"description": "Agent already holds an active token",
|
|
48160
|
+
"content": {
|
|
48161
|
+
"application/json": {
|
|
48162
|
+
"schema": {
|
|
48163
|
+
"$ref": "#/components/schemas/ErrorResponse"
|
|
48164
|
+
}
|
|
48165
|
+
}
|
|
48166
|
+
}
|
|
48167
|
+
}
|
|
48168
|
+
}
|
|
48169
|
+
},
|
|
48170
|
+
"delete": {
|
|
48171
|
+
"operationId": "agents_revokeWorkerToken",
|
|
48172
|
+
"summary": "Revoke an agent-bound worker token",
|
|
48173
|
+
"description": "Revokes every active worker token of the agent and the task tokens they minted. Open realtime connections on them close.",
|
|
48174
|
+
"tags": [
|
|
48175
|
+
"Sessions"
|
|
48176
|
+
],
|
|
48177
|
+
"security": [
|
|
48178
|
+
{
|
|
48179
|
+
"bearerAuth": []
|
|
48180
|
+
}
|
|
48181
|
+
],
|
|
48182
|
+
"parameters": [
|
|
48183
|
+
{
|
|
48184
|
+
"schema": {
|
|
48185
|
+
"type": "string",
|
|
48186
|
+
"minLength": 1
|
|
48187
|
+
},
|
|
48188
|
+
"required": true,
|
|
48189
|
+
"name": "id",
|
|
48190
|
+
"in": "path"
|
|
48191
|
+
}
|
|
48192
|
+
],
|
|
48193
|
+
"responses": {
|
|
48194
|
+
"200": {
|
|
48195
|
+
"description": "Number of worker tokens revoked (0 when none was active)",
|
|
48196
|
+
"content": {
|
|
48197
|
+
"application/json": {
|
|
48198
|
+
"schema": {
|
|
48199
|
+
"type": "object",
|
|
48200
|
+
"properties": {
|
|
48201
|
+
"revoked": {
|
|
48202
|
+
"type": "integer"
|
|
48203
|
+
}
|
|
48204
|
+
},
|
|
48205
|
+
"required": [
|
|
48206
|
+
"revoked"
|
|
48207
|
+
]
|
|
48208
|
+
}
|
|
48209
|
+
}
|
|
48210
|
+
}
|
|
48211
|
+
},
|
|
48212
|
+
"403": {
|
|
48213
|
+
"description": "Operator or user credentials required",
|
|
48214
|
+
"content": {
|
|
48215
|
+
"application/json": {
|
|
48216
|
+
"schema": {
|
|
48217
|
+
"$ref": "#/components/schemas/ErrorResponse"
|
|
48218
|
+
}
|
|
48219
|
+
}
|
|
48220
|
+
}
|
|
48221
|
+
}
|
|
48222
|
+
}
|
|
48223
|
+
}
|
|
48224
|
+
},
|
|
48225
|
+
"/api/agents/{id}/token/rotate": {
|
|
48226
|
+
"post": {
|
|
48227
|
+
"operationId": "agents_rotateWorkerToken",
|
|
48228
|
+
"summary": "Rotate an agent-bound worker token",
|
|
48229
|
+
"description": "Returns a new token once. The previous token keeps working for `graceSec` (default 300), then expires. Use revoke for a token that must stop now.",
|
|
48230
|
+
"tags": [
|
|
48231
|
+
"Sessions"
|
|
48232
|
+
],
|
|
48233
|
+
"security": [
|
|
48234
|
+
{
|
|
48235
|
+
"bearerAuth": []
|
|
48236
|
+
}
|
|
48237
|
+
],
|
|
48238
|
+
"parameters": [
|
|
48239
|
+
{
|
|
48240
|
+
"schema": {
|
|
48241
|
+
"type": "string",
|
|
48242
|
+
"minLength": 1
|
|
48243
|
+
},
|
|
48244
|
+
"required": true,
|
|
48245
|
+
"name": "id",
|
|
48246
|
+
"in": "path"
|
|
48247
|
+
}
|
|
48248
|
+
],
|
|
48249
|
+
"requestBody": {
|
|
48250
|
+
"content": {
|
|
48251
|
+
"application/json": {
|
|
48252
|
+
"schema": {
|
|
48253
|
+
"type": "object",
|
|
48254
|
+
"properties": {
|
|
48255
|
+
"graceSec": {
|
|
48256
|
+
"type": "integer",
|
|
48257
|
+
"minimum": 0,
|
|
48258
|
+
"maximum": 86400
|
|
48259
|
+
},
|
|
48260
|
+
"ttlMs": {
|
|
48261
|
+
"type": "integer",
|
|
48262
|
+
"exclusiveMinimum": 0,
|
|
48263
|
+
"description": "Token lifetime in ms. Omit for the default (no expiry)."
|
|
48264
|
+
}
|
|
48265
|
+
},
|
|
48266
|
+
"additionalProperties": false
|
|
48267
|
+
}
|
|
48268
|
+
}
|
|
48269
|
+
}
|
|
48270
|
+
},
|
|
48271
|
+
"responses": {
|
|
48272
|
+
"200": {
|
|
48273
|
+
"description": "New worker token",
|
|
48274
|
+
"content": {
|
|
48275
|
+
"application/json": {
|
|
48276
|
+
"schema": {
|
|
48277
|
+
"type": "object",
|
|
48278
|
+
"properties": {
|
|
48279
|
+
"agentId": {
|
|
48280
|
+
"type": "string"
|
|
48281
|
+
},
|
|
48282
|
+
"tokenId": {
|
|
48283
|
+
"type": "string"
|
|
48284
|
+
},
|
|
48285
|
+
"plaintext": {
|
|
48286
|
+
"type": "string"
|
|
48287
|
+
},
|
|
48288
|
+
"expiresAt": {
|
|
48289
|
+
"type": [
|
|
48290
|
+
"string",
|
|
48291
|
+
"null"
|
|
48292
|
+
],
|
|
48293
|
+
"description": "null when the token does not expire"
|
|
48294
|
+
},
|
|
48295
|
+
"previousExpiresAt": {
|
|
48296
|
+
"type": "string"
|
|
48297
|
+
}
|
|
48298
|
+
},
|
|
48299
|
+
"required": [
|
|
48300
|
+
"agentId",
|
|
48301
|
+
"tokenId",
|
|
48302
|
+
"plaintext",
|
|
48303
|
+
"expiresAt",
|
|
48304
|
+
"previousExpiresAt"
|
|
48305
|
+
]
|
|
48306
|
+
}
|
|
48307
|
+
}
|
|
48308
|
+
}
|
|
48309
|
+
},
|
|
48310
|
+
"403": {
|
|
48311
|
+
"description": "Operator or user credentials required",
|
|
48312
|
+
"content": {
|
|
48313
|
+
"application/json": {
|
|
48314
|
+
"schema": {
|
|
48315
|
+
"$ref": "#/components/schemas/ErrorResponse"
|
|
48316
|
+
}
|
|
48317
|
+
}
|
|
48318
|
+
}
|
|
48319
|
+
},
|
|
48320
|
+
"404": {
|
|
48321
|
+
"description": "Agent holds no active token",
|
|
48322
|
+
"content": {
|
|
48323
|
+
"application/json": {
|
|
48324
|
+
"schema": {
|
|
48325
|
+
"$ref": "#/components/schemas/ErrorResponse"
|
|
48326
|
+
}
|
|
48327
|
+
}
|
|
48328
|
+
}
|
|
48329
|
+
}
|
|
48330
|
+
}
|
|
48331
|
+
}
|
|
48332
|
+
},
|
|
48050
48333
|
"/api/sessions": {
|
|
48051
48334
|
"get": {
|
|
48052
48335
|
"summary": "List recent task sessions (root tasks + chain summary)",
|
|
@@ -60111,7 +60394,7 @@
|
|
|
60111
60394
|
"properties": {
|
|
60112
60395
|
"type": {
|
|
60113
60396
|
"type": "string",
|
|
60114
|
-
"description": "Executor type: 'agent-task', 'script', 'swarm-script', 'raw-llm', 'system-one-decision', 'validate', 'property-match'"
|
|
60397
|
+
"description": "Executor type: 'agent-task', 'script', 'swarm-script', 'raw-llm', 'system-one-decision', 'system-one-extraction', 'validate', 'property-match'"
|
|
60115
60398
|
},
|
|
60116
60399
|
"label": {
|
|
60117
60400
|
"type": "string",
|
|
@@ -60120,7 +60403,7 @@
|
|
|
60120
60403
|
"config": {
|
|
60121
60404
|
"type": "object",
|
|
60122
60405
|
"additionalProperties": {},
|
|
60123
|
-
"description": "Executor-specific config. For agent-task: { template, outputSchema?, agentId?, routingReason?, routingNote?, tags?, priority?, dir?, vcsRepo?, model? }; configured agentId defaults routingReason to human_pinned. For script: { runtime, script, args?, timeout? }. For swarm-script: { scriptName, scope?, pinHash?, args?, fsMode?, timeoutMs? (1000-300000) }. For system-one-decision (typed decisions, Jev by default): { provider? ('typesafe' default | 'openrouter' | 'laya'; a literal, never a {{token}}), state, questions: { <id>: { type: 'noul'|'choice'|'score', instructions, criteria? } }, returns: { <id>: { type } }, model? (provider-specific; unset = the provider's default, and laya has none so it sends no model and picks its own checkpoint), timeoutMs?, maxRetries? (0-3), humanReview? { band: { min, max } (0-1, inclusive), approvers: { users?, roles?, policy }, title?, timeout?, notifications? } }; each provider needs its own global secret (TYPESAFE_API_KEY, OPENROUTER_API_KEY, or LAYA_API_KEY; laya also needs the global config LAYA_URL), and a save warns and a run fails before any node executes when one is missing; system-one-decision nodes must not set retry or validation.retry. With humanReview, an answer whose confidence is inside the band waits for a person (human-in-the-loop approval), and next must map ports { approved, rejected?, timeout? }. Agent-task templates and ordinary config values support {{interpolation}} from the node's inputs context, including trigger and declared upstream aliases. SECURITY: executable source for script/swarm-script nodes does not interpolate trigger.* or upstream node outputs; only input/workflow/swarm/run values are allowed in inline script source, and named swarm-script source is not workflow-interpolated. Pass dynamic values through config.args instead (inline script receives them as argv, with runtime: \"bash\" running bash -c <script> ...args so args[0] is $0 and args[1] is $1; swarm-script receives its args object). NOTE: config.outputSchema on agent-task nodes validates the AGENT's raw JSON output, while node-level outputSchema validates the EXECUTOR's return value ({taskId, taskOutput})."
|
|
60406
|
+
"description": "Executor-specific config. For agent-task: { template, outputSchema?, agentId?, routingReason?, routingNote?, tags?, priority?, dir?, vcsRepo?, model? }; configured agentId defaults routingReason to human_pinned. For script: { runtime, script, args?, timeout? }. For swarm-script: { scriptName, scope?, pinHash?, args?, fsMode?, timeoutMs? (1000-300000) }. For system-one-decision (typed decisions, Jev by default): { provider? ('typesafe' default | 'openrouter' | 'laya'; a literal, never a {{token}}), state, questions: { <id>: { type: 'noul'|'choice'|'score', instructions, criteria? } }, returns: { <id>: { type } }, model? (provider-specific; unset = the provider's default, and laya has none so it sends no model and picks its own checkpoint), timeoutMs?, maxRetries? (0-3), humanReview? { band: { min, max } (0-1, inclusive), approvers: { users?, roles?, policy }, title?, timeout?, notifications? } }; each provider needs its own global secret (TYPESAFE_API_KEY, OPENROUTER_API_KEY, or LAYA_API_KEY; laya also needs the global config LAYA_URL), and a save warns and a run fails before any node executes when one is missing; system-one-decision nodes must not set retry or validation.retry. With humanReview, an answer whose confidence is inside the band waits for a person (human-in-the-loop approval), and next must map ports { approved, rejected?, timeout? }. For system-one-extraction (typed extraction, Cloudflare Clairic by default): { provider? ('cloudflare'; a literal), state (text to read; may be empty when images are sent), fields: { <id>: { type: 'text'|'number'|'date'|'time'|'datetime'|'duration'|'list'|'estimate'|'forecast', instructions?, ...type options (number: unit?, integer?, decimals?; duration: unit? (seconds..years), integer?, decimals?; list: items ('text'|'number'|'date'); estimate: min, max, step?, scale?, unit?; forecast: min, max, horizon?, interval?, scale?, unit?; text/number/date/time/datetime/duration: null_threshold?) } }, images? (max 4 base64 data: URLs or { content_type, base64 }), referenceDate? (YYYY-MM-DD), model?, timeoutMs?, maxRetries? (0-3) }; output answers.<id> carries value (null when the input does not say), guess, p_null, confidence, span/spans, and for estimate/forecast median/p10/p90. Needs the global secret CLOUDFLARE_API_TOKEN (or CLOUDFLARE_API_KEY) and the global config CLOUDFLARE_ACCOUNT_ID; must not set retry or validation.retry. Agent-task templates and ordinary config values support {{interpolation}} from the node's inputs context, including trigger and declared upstream aliases. SECURITY: executable source for script/swarm-script nodes does not interpolate trigger.* or upstream node outputs; only input/workflow/swarm/run values are allowed in inline script source, and named swarm-script source is not workflow-interpolated. Pass dynamic values through config.args instead (inline script receives them as argv, with runtime: \"bash\" running bash -c <script> ...args so args[0] is $0 and args[1] is $1; swarm-script receives its args object). NOTE: config.outputSchema on agent-task nodes validates the AGENT's raw JSON output, while node-level outputSchema validates the EXECUTOR's return value ({taskId, taskOutput})."
|
|
60124
60407
|
},
|
|
60125
60408
|
"next": {
|
|
60126
60409
|
"anyOf": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@desplega.ai/agent-swarm",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.4",
|
|
4
4
|
"description": "agent-swarm.dev — an open-source operating system for AI work: a lead agent breaks goals into tasks, routes them to specialized workers such as Claude Code or Codex, runs each worker in an isolated container, and preserves shared memory, tools, schedules, and review gates so delegated work compounds across sessions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent-swarm.dev",
|
|
@@ -179,8 +179,8 @@
|
|
|
179
179
|
"@desplega/model-catalog": "workspace:*",
|
|
180
180
|
"@desplega/model-routing": "workspace:*",
|
|
181
181
|
"@faker-js/faker": "^10.4.0",
|
|
182
|
-
"@opencode/plugin": "2.
|
|
183
|
-
"@opencode/sdk": "2.
|
|
182
|
+
"@opencode/plugin": "2.1.1",
|
|
183
|
+
"@opencode/sdk": "2.1.1",
|
|
184
184
|
"@oxlint/plugins": "1.78.0",
|
|
185
185
|
"@types/bun": "latest",
|
|
186
186
|
"dependency-cruiser": "^18.0.0",
|
|
@@ -198,7 +198,7 @@
|
|
|
198
198
|
"bun": ">=1.3.12"
|
|
199
199
|
},
|
|
200
200
|
"dependencies": {
|
|
201
|
-
"@agentclientprotocol/sdk": "
|
|
201
|
+
"@agentclientprotocol/sdk": "2.0.0",
|
|
202
202
|
"@ai-sdk/openai": "^3.0.41",
|
|
203
203
|
"@anthropic-ai/claude-agent-sdk": "0.3.304",
|
|
204
204
|
"@anthropic-ai/sdk": "^0.135.0",
|
|
@@ -24,12 +24,15 @@ export async function runAppAction({
|
|
|
24
24
|
app,
|
|
25
25
|
name,
|
|
26
26
|
input = {},
|
|
27
|
+
parentTaskId,
|
|
27
28
|
caller,
|
|
28
29
|
actor,
|
|
29
30
|
}: {
|
|
30
31
|
app: AppRecord;
|
|
31
32
|
name: string;
|
|
32
33
|
input?: Record<string, unknown>;
|
|
34
|
+
/** Task-kind actions only: chains the created task under an existing one. The HTTP route rejects it (400) for script and sync actions, which never read it. */
|
|
35
|
+
parentTaskId?: string;
|
|
33
36
|
caller: AppActionCaller;
|
|
34
37
|
actor: string;
|
|
35
38
|
}) {
|
|
@@ -136,6 +139,7 @@ export async function runAppAction({
|
|
|
136
139
|
// swarm-tasks source can pull them back via config.assetKey.
|
|
137
140
|
key: normalizeAssetKey(`shared/app:${app.id}/action:${name}/`),
|
|
138
141
|
...(actor.startsWith("user:") ? { requestedByUserId: actor.slice("user:".length) } : {}),
|
|
142
|
+
...(parentTaskId ? { parentTaskId } : {}),
|
|
139
143
|
},
|
|
140
144
|
{ origin: "app" },
|
|
141
145
|
);
|
|
@@ -149,7 +149,10 @@ function isActionSentinel(value: unknown): boolean {
|
|
|
149
149
|
if (!isPlainObject(value) || Object.keys(value).length !== 1) return false;
|
|
150
150
|
if (typeof value.$row === "string") return true;
|
|
151
151
|
if (value.$rowIndex === true) return true;
|
|
152
|
-
|
|
152
|
+
if (typeof value.$form === "string") return true;
|
|
153
|
+
// Chain-derived scope published by a component that runs a task chain —
|
|
154
|
+
// see `action-params.ts`'s `$chain` sentinel.
|
|
155
|
+
return typeof value.$chain === "string";
|
|
153
156
|
}
|
|
154
157
|
|
|
155
158
|
function appendPath(path: string, part: string | number): string {
|
|
@@ -220,7 +223,10 @@ function validateSchema(
|
|
|
220
223
|
? { issues: [], stateRefs: [] }
|
|
221
224
|
: {
|
|
222
225
|
issues: [
|
|
223
|
-
issue(
|
|
226
|
+
issue(
|
|
227
|
+
path,
|
|
228
|
+
"$row, $rowIndex, $form, and $chain bindings are only allowed in action params",
|
|
229
|
+
),
|
|
224
230
|
],
|
|
225
231
|
stateRefs: [],
|
|
226
232
|
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
PRAGMA defer_foreign_keys = ON;
|
|
2
|
+
|
|
3
|
+
-- Add agent-bound worker tokens: a fourth binding that names only the agent.
|
|
4
|
+
-- parentTokenId links a child task token to the agent token that minted it,
|
|
5
|
+
-- so revoking the agent token revokes its children.
|
|
6
|
+
CREATE TABLE session_tokens_new (
|
|
7
|
+
id TEXT PRIMARY KEY,
|
|
8
|
+
tokenHash TEXT NOT NULL UNIQUE,
|
|
9
|
+
tokenPreview TEXT NOT NULL,
|
|
10
|
+
agentId TEXT NOT NULL,
|
|
11
|
+
taskId TEXT,
|
|
12
|
+
runtimeId TEXT,
|
|
13
|
+
parentRuntimeId TEXT,
|
|
14
|
+
controllerId TEXT,
|
|
15
|
+
parentTokenId TEXT,
|
|
16
|
+
expiresAt TEXT NOT NULL,
|
|
17
|
+
revokedAt TEXT,
|
|
18
|
+
createdAt TEXT NOT NULL DEFAULT (datetime('now')),
|
|
19
|
+
lastUsedAt TEXT,
|
|
20
|
+
CHECK (
|
|
21
|
+
(taskId IS NOT NULL AND runtimeId IS NULL AND controllerId IS NULL
|
|
22
|
+
AND (parentRuntimeId IS NULL OR parentTokenId IS NULL))
|
|
23
|
+
OR (taskId IS NULL AND runtimeId IS NOT NULL AND parentRuntimeId IS NULL AND controllerId IS NULL AND parentTokenId IS NULL)
|
|
24
|
+
OR (controllerId IS NOT NULL AND taskId IS NULL AND runtimeId IS NULL AND parentRuntimeId IS NULL AND parentTokenId IS NULL)
|
|
25
|
+
OR (taskId IS NULL AND runtimeId IS NULL AND controllerId IS NULL AND parentRuntimeId IS NULL AND parentTokenId IS NULL)
|
|
26
|
+
)
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
INSERT INTO session_tokens_new
|
|
30
|
+
(id, tokenHash, tokenPreview, agentId, taskId, runtimeId, parentRuntimeId, controllerId,
|
|
31
|
+
expiresAt, revokedAt, createdAt, lastUsedAt)
|
|
32
|
+
SELECT id, tokenHash, tokenPreview, agentId, taskId, runtimeId, parentRuntimeId, controllerId,
|
|
33
|
+
expiresAt, revokedAt, createdAt, lastUsedAt
|
|
34
|
+
FROM session_tokens;
|
|
35
|
+
|
|
36
|
+
DROP TABLE session_tokens;
|
|
37
|
+
ALTER TABLE session_tokens_new RENAME TO session_tokens;
|
|
38
|
+
CREATE INDEX idx_session_tokens_agentId ON session_tokens(agentId);
|
|
39
|
+
CREATE INDEX idx_session_tokens_runtimeId ON session_tokens(runtimeId);
|
|
40
|
+
CREATE INDEX idx_session_tokens_parentRuntimeId ON session_tokens(parentRuntimeId);
|
|
41
|
+
CREATE INDEX idx_session_tokens_parentTokenId ON session_tokens(parentTokenId);
|
|
@@ -189,11 +189,20 @@ async function buildState(ctx: any, leadId: string, nowMs: number, timeZone: str
|
|
|
189
189
|
const mmdd = new Date(nowMs).toISOString().slice(5, 10);
|
|
190
190
|
const mmddLocal = stamp.slice(5, 10);
|
|
191
191
|
const due: string[] = [];
|
|
192
|
+
// An MM-DD counts only as a bare token: "release on 10-20" is due, while a
|
|
193
|
+
// re-verification stamp ("2026-10-20 ~10:45Z", a UUID piece) and a suffixed
|
|
194
|
+
// token ("10-20s") are not.
|
|
195
|
+
const mentionsMmdd = (s: string, tok: string) =>
|
|
196
|
+
new RegExp(`(?<![\\w-])${tok}(?![\\w-])`).test(s);
|
|
192
197
|
for (const line of String(lead[0]?.heartbeatMd ?? "").split("\n")) {
|
|
193
198
|
const l = line.trim();
|
|
194
199
|
if (!l) continue;
|
|
195
200
|
const del = /DELETE <?(\d\d-\d\d)>?/.exec(l);
|
|
196
|
-
if (
|
|
201
|
+
if (
|
|
202
|
+
mentionsMmdd(l, mmdd) ||
|
|
203
|
+
mentionsMmdd(l, mmddLocal) ||
|
|
204
|
+
(del?.[1] && del[1] <= mmddLocal)
|
|
205
|
+
) {
|
|
197
206
|
due.push(oneLine(l).slice(0, 200));
|
|
198
207
|
}
|
|
199
208
|
if (due.length >= 6) break;
|
|
@@ -149,6 +149,17 @@ export const DB_RETENTION_TUNING_BOUNDS = {
|
|
|
149
149
|
*/
|
|
150
150
|
export const APPS_JSON_COLUMN_MAX_BYTES_BOUNDS = { min: 1_024, max: 16_777_216 } as const;
|
|
151
151
|
|
|
152
|
+
/**
|
|
153
|
+
* Bounds for the Codex OAuth keep-warm age threshold
|
|
154
|
+
* (`CODEX_OAUTH_KEEP_WARM_MAX_AGE_HOURS`).
|
|
155
|
+
*
|
|
156
|
+
* `src/http/codex-oauth-keep-warm.ts` reads the knob against exactly these at
|
|
157
|
+
* call time and falls back to its default outside them. The 216 h (9 day)
|
|
158
|
+
* ceiling stays under the 9.5 day point where task-time near-expiry refresh
|
|
159
|
+
* takes over, so every accepted value still changes when a slot refreshes.
|
|
160
|
+
*/
|
|
161
|
+
export const CODEX_OAUTH_KEEP_WARM_MAX_AGE_HOURS_BOUNDS = { min: 1, max: 216 } as const;
|
|
162
|
+
|
|
152
163
|
/** Build `{ KEY: validator }` entries accepting only boolean literals. */
|
|
153
164
|
function booleanValidators(keys: string[]): Record<string, ConfigValidator> {
|
|
154
165
|
const message = (key: string) =>
|
|
@@ -542,6 +553,11 @@ const VALIDATED_KEYS: Record<string, ConfigValidator> = {
|
|
|
542
553
|
APPS_JSON_COLUMN_MAX_BYTES_BOUNDS.min,
|
|
543
554
|
APPS_JSON_COLUMN_MAX_BYTES_BOUNDS.max,
|
|
544
555
|
),
|
|
556
|
+
...boundedIntegerValidators(
|
|
557
|
+
["CODEX_OAUTH_KEEP_WARM_MAX_AGE_HOURS"],
|
|
558
|
+
CODEX_OAUTH_KEEP_WARM_MAX_AGE_HOURS_BOUNDS.min,
|
|
559
|
+
CODEX_OAUTH_KEEP_WARM_MAX_AGE_HOURS_BOUNDS.max,
|
|
560
|
+
),
|
|
545
561
|
...boundedIntegerValidators(
|
|
546
562
|
[
|
|
547
563
|
"SESSION_LOG_RETENTION_DAYS",
|