agent-relay 2.3.4 → 2.3.6
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/src/cli/index.js +124 -7
- package/dist/src/cli/index.js.map +1 -1
- package/package.json +23 -26
- package/packages/acp-bridge/package.json +2 -2
- package/packages/bridge/package.json +7 -7
- package/packages/config/package.json +2 -2
- package/packages/continuity/package.json +2 -2
- package/packages/daemon/package.json +12 -12
- package/packages/hooks/package.json +4 -4
- package/packages/mcp/package.json +5 -5
- package/packages/memory/package.json +2 -2
- package/packages/policy/package.json +2 -2
- package/packages/protocol/package.json +1 -1
- package/packages/resiliency/package.json +1 -1
- package/packages/sdk/dist/index.d.ts +1 -29
- package/packages/sdk/dist/index.d.ts.map +1 -1
- package/packages/sdk/dist/index.js +1 -38
- package/packages/sdk/dist/index.js.map +1 -1
- package/packages/sdk/package.json +4 -25
- package/packages/sdk/src/index.ts +1 -69
- package/packages/sdk-py/README.md +56 -0
- package/packages/sdk-py/pyproject.toml +23 -0
- package/packages/sdk-py/src/agent_relay/__init__.py +27 -0
- package/packages/sdk-py/src/agent_relay/builder.py +367 -0
- package/packages/sdk-py/src/agent_relay/types.py +92 -0
- package/packages/sdk-py/tests/__init__.py +0 -0
- package/packages/sdk-py/tests/test_builder.py +101 -0
- package/packages/sdk-ts/dist/index.d.ts +1 -0
- package/packages/sdk-ts/dist/index.d.ts.map +1 -1
- package/packages/sdk-ts/dist/index.js +1 -0
- package/packages/sdk-ts/dist/index.js.map +1 -1
- package/packages/sdk-ts/dist/workflows/barrier.d.ts +72 -0
- package/packages/sdk-ts/dist/workflows/barrier.d.ts.map +1 -0
- package/packages/sdk-ts/dist/workflows/barrier.js +162 -0
- package/packages/sdk-ts/dist/workflows/barrier.js.map +1 -0
- package/packages/sdk-ts/dist/workflows/builder.d.ts +101 -0
- package/packages/sdk-ts/dist/workflows/builder.d.ts.map +1 -0
- package/packages/sdk-ts/dist/workflows/builder.js +179 -0
- package/packages/sdk-ts/dist/workflows/builder.js.map +1 -0
- package/packages/sdk-ts/dist/workflows/cli.d.ts +10 -0
- package/packages/sdk-ts/dist/workflows/cli.d.ts.map +1 -0
- package/packages/sdk-ts/dist/workflows/cli.js +82 -0
- package/packages/sdk-ts/dist/workflows/cli.js.map +1 -0
- package/packages/sdk-ts/dist/workflows/coordinator.d.ts +68 -0
- package/packages/sdk-ts/dist/workflows/coordinator.d.ts.map +1 -0
- package/packages/sdk-ts/dist/workflows/coordinator.js +353 -0
- package/packages/sdk-ts/dist/workflows/coordinator.js.map +1 -0
- package/packages/sdk-ts/dist/workflows/index.d.ts +10 -0
- package/packages/sdk-ts/dist/workflows/index.d.ts.map +1 -0
- package/packages/sdk-ts/dist/workflows/index.js +10 -0
- package/packages/sdk-ts/dist/workflows/index.js.map +1 -0
- package/packages/sdk-ts/dist/workflows/memory-db.d.ts +17 -0
- package/packages/sdk-ts/dist/workflows/memory-db.d.ts.map +1 -0
- package/packages/sdk-ts/dist/workflows/memory-db.js +33 -0
- package/packages/sdk-ts/dist/workflows/memory-db.js.map +1 -0
- package/packages/sdk-ts/dist/workflows/run.d.ts +31 -0
- package/packages/sdk-ts/dist/workflows/run.d.ts.map +1 -0
- package/packages/sdk-ts/dist/workflows/run.js +24 -0
- package/packages/sdk-ts/dist/workflows/run.js.map +1 -0
- package/packages/sdk-ts/dist/workflows/runner.d.ts +119 -0
- package/packages/sdk-ts/dist/workflows/runner.d.ts.map +1 -0
- package/packages/sdk-ts/dist/workflows/runner.js +650 -0
- package/packages/sdk-ts/dist/workflows/runner.js.map +1 -0
- package/packages/sdk-ts/dist/workflows/state.d.ts +77 -0
- package/packages/sdk-ts/dist/workflows/state.d.ts.map +1 -0
- package/packages/sdk-ts/dist/workflows/state.js +140 -0
- package/packages/sdk-ts/dist/workflows/state.js.map +1 -0
- package/packages/sdk-ts/dist/workflows/templates.d.ts +47 -0
- package/packages/sdk-ts/dist/workflows/templates.d.ts.map +1 -0
- package/packages/sdk-ts/dist/workflows/templates.js +395 -0
- package/packages/sdk-ts/dist/workflows/templates.js.map +1 -0
- package/packages/sdk-ts/dist/workflows/types.d.ts +126 -0
- package/packages/sdk-ts/dist/workflows/types.d.ts.map +1 -0
- package/packages/sdk-ts/dist/workflows/types.js +8 -0
- package/packages/sdk-ts/dist/workflows/types.js.map +1 -0
- package/packages/sdk-ts/package.json +8 -2
- package/packages/sdk-ts/src/__tests__/error-scenarios.test.ts +682 -0
- package/packages/sdk-ts/src/__tests__/swarm-coordinator.test.ts +416 -0
- package/packages/sdk-ts/src/__tests__/workflow-runner.test.ts +333 -0
- package/packages/sdk-ts/src/index.ts +1 -0
- package/packages/sdk-ts/src/workflows/README.md +450 -0
- package/packages/sdk-ts/src/workflows/barrier.ts +254 -0
- package/packages/sdk-ts/src/workflows/builder.ts +241 -0
- package/packages/sdk-ts/src/workflows/builtin-templates/bug-fix.yaml +75 -0
- package/packages/sdk-ts/src/workflows/builtin-templates/code-review.yaml +82 -0
- package/packages/sdk-ts/src/workflows/builtin-templates/documentation.yaml +70 -0
- package/packages/sdk-ts/src/workflows/builtin-templates/feature-dev.yaml +76 -0
- package/packages/sdk-ts/src/workflows/builtin-templates/refactor.yaml +82 -0
- package/packages/sdk-ts/src/workflows/builtin-templates/security-audit.yaml +84 -0
- package/packages/sdk-ts/src/workflows/cli.ts +93 -0
- package/packages/sdk-ts/src/workflows/coordinator.ts +520 -0
- package/packages/sdk-ts/src/workflows/index.ts +9 -0
- package/packages/sdk-ts/src/workflows/memory-db.ts +39 -0
- package/packages/sdk-ts/src/workflows/run.ts +47 -0
- package/packages/sdk-ts/src/workflows/runner.ts +873 -0
- package/packages/sdk-ts/src/workflows/schema.json +321 -0
- package/packages/sdk-ts/src/workflows/state.ts +279 -0
- package/packages/sdk-ts/src/workflows/templates.ts +544 -0
- package/packages/sdk-ts/src/workflows/types.ts +178 -0
- package/packages/sdk-ts/tsconfig.json +6 -1
- package/packages/spawner/package.json +1 -1
- package/packages/state/package.json +1 -1
- package/packages/storage/package.json +2 -2
- package/packages/telemetry/package.json +1 -1
- package/packages/trajectory/package.json +2 -2
- package/packages/user-directory/package.json +2 -2
- package/packages/utils/package.json +3 -3
- package/packages/wrapper/package.json +5 -6
- package/packages/api-types/.trajectories/active/traj_xbsvuzogscey.json +0 -15
- package/packages/api-types/.trajectories/index.json +0 -12
- package/packages/api-types/dist/index.d.ts +0 -21
- package/packages/api-types/dist/index.d.ts.map +0 -1
- package/packages/api-types/dist/index.js +0 -22
- package/packages/api-types/dist/index.js.map +0 -1
- package/packages/api-types/dist/schemas/agent.d.ts +0 -259
- package/packages/api-types/dist/schemas/agent.d.ts.map +0 -1
- package/packages/api-types/dist/schemas/agent.js +0 -102
- package/packages/api-types/dist/schemas/agent.js.map +0 -1
- package/packages/api-types/dist/schemas/api.d.ts +0 -290
- package/packages/api-types/dist/schemas/api.d.ts.map +0 -1
- package/packages/api-types/dist/schemas/api.js +0 -162
- package/packages/api-types/dist/schemas/api.js.map +0 -1
- package/packages/api-types/dist/schemas/decision.d.ts +0 -230
- package/packages/api-types/dist/schemas/decision.d.ts.map +0 -1
- package/packages/api-types/dist/schemas/decision.js +0 -104
- package/packages/api-types/dist/schemas/decision.js.map +0 -1
- package/packages/api-types/dist/schemas/fleet.d.ts +0 -615
- package/packages/api-types/dist/schemas/fleet.d.ts.map +0 -1
- package/packages/api-types/dist/schemas/fleet.js +0 -71
- package/packages/api-types/dist/schemas/fleet.js.map +0 -1
- package/packages/api-types/dist/schemas/history.d.ts +0 -180
- package/packages/api-types/dist/schemas/history.d.ts.map +0 -1
- package/packages/api-types/dist/schemas/history.js +0 -72
- package/packages/api-types/dist/schemas/history.js.map +0 -1
- package/packages/api-types/dist/schemas/index.d.ts +0 -14
- package/packages/api-types/dist/schemas/index.d.ts.map +0 -1
- package/packages/api-types/dist/schemas/index.js +0 -22
- package/packages/api-types/dist/schemas/index.js.map +0 -1
- package/packages/api-types/dist/schemas/message.d.ts +0 -456
- package/packages/api-types/dist/schemas/message.d.ts.map +0 -1
- package/packages/api-types/dist/schemas/message.js +0 -88
- package/packages/api-types/dist/schemas/message.js.map +0 -1
- package/packages/api-types/dist/schemas/session.d.ts +0 -60
- package/packages/api-types/dist/schemas/session.d.ts.map +0 -1
- package/packages/api-types/dist/schemas/session.js +0 -36
- package/packages/api-types/dist/schemas/session.js.map +0 -1
- package/packages/api-types/dist/schemas/task.d.ts +0 -111
- package/packages/api-types/dist/schemas/task.d.ts.map +0 -1
- package/packages/api-types/dist/schemas/task.js +0 -64
- package/packages/api-types/dist/schemas/task.js.map +0 -1
- package/packages/api-types/package.json +0 -61
- package/packages/api-types/scripts/generate-openapi.ts +0 -106
- package/packages/api-types/src/index.ts +0 -22
- package/packages/api-types/src/schemas/agent.test.ts +0 -164
- package/packages/api-types/src/schemas/agent.ts +0 -110
- package/packages/api-types/src/schemas/api.test.ts +0 -372
- package/packages/api-types/src/schemas/api.ts +0 -194
- package/packages/api-types/src/schemas/decision.test.ts +0 -324
- package/packages/api-types/src/schemas/decision.ts +0 -136
- package/packages/api-types/src/schemas/fleet.test.ts +0 -212
- package/packages/api-types/src/schemas/fleet.ts +0 -83
- package/packages/api-types/src/schemas/history.test.ts +0 -242
- package/packages/api-types/src/schemas/history.ts +0 -84
- package/packages/api-types/src/schemas/index.ts +0 -148
- package/packages/api-types/src/schemas/message.test.ts +0 -192
- package/packages/api-types/src/schemas/message.ts +0 -98
- package/packages/api-types/src/schemas/session.test.ts +0 -104
- package/packages/api-types/src/schemas/session.ts +0 -40
- package/packages/api-types/src/schemas/task.test.ts +0 -192
- package/packages/api-types/src/schemas/task.ts +0 -78
- package/packages/api-types/tsconfig.json +0 -19
- package/packages/api-types/vitest.config.ts +0 -9
- package/packages/benchmark/README.md +0 -200
- package/packages/benchmark/datasets/coding-tasks.yaml +0 -127
- package/packages/benchmark/datasets/coordination-tasks.yaml +0 -122
- package/packages/benchmark/datasets/quick-test.yaml +0 -20
- package/packages/benchmark/dist/benchmark.d.ts +0 -47
- package/packages/benchmark/dist/benchmark.d.ts.map +0 -1
- package/packages/benchmark/dist/benchmark.js +0 -224
- package/packages/benchmark/dist/benchmark.js.map +0 -1
- package/packages/benchmark/dist/cli.d.ts +0 -8
- package/packages/benchmark/dist/cli.d.ts.map +0 -1
- package/packages/benchmark/dist/cli.js +0 -185
- package/packages/benchmark/dist/cli.js.map +0 -1
- package/packages/benchmark/dist/harbor.d.ts +0 -53
- package/packages/benchmark/dist/harbor.d.ts.map +0 -1
- package/packages/benchmark/dist/harbor.js +0 -127
- package/packages/benchmark/dist/harbor.js.map +0 -1
- package/packages/benchmark/dist/index.d.ts +0 -48
- package/packages/benchmark/dist/index.d.ts.map +0 -1
- package/packages/benchmark/dist/index.js +0 -50
- package/packages/benchmark/dist/index.js.map +0 -1
- package/packages/benchmark/dist/runners/base.d.ts +0 -63
- package/packages/benchmark/dist/runners/base.d.ts.map +0 -1
- package/packages/benchmark/dist/runners/base.js +0 -156
- package/packages/benchmark/dist/runners/base.js.map +0 -1
- package/packages/benchmark/dist/runners/index.d.ts +0 -10
- package/packages/benchmark/dist/runners/index.d.ts.map +0 -1
- package/packages/benchmark/dist/runners/index.js +0 -10
- package/packages/benchmark/dist/runners/index.js.map +0 -1
- package/packages/benchmark/dist/runners/single.d.ts +0 -19
- package/packages/benchmark/dist/runners/single.d.ts.map +0 -1
- package/packages/benchmark/dist/runners/single.js +0 -111
- package/packages/benchmark/dist/runners/single.js.map +0 -1
- package/packages/benchmark/dist/runners/subagent.d.ts +0 -32
- package/packages/benchmark/dist/runners/subagent.d.ts.map +0 -1
- package/packages/benchmark/dist/runners/subagent.js +0 -212
- package/packages/benchmark/dist/runners/subagent.js.map +0 -1
- package/packages/benchmark/dist/runners/swarm.d.ts +0 -36
- package/packages/benchmark/dist/runners/swarm.d.ts.map +0 -1
- package/packages/benchmark/dist/runners/swarm.js +0 -273
- package/packages/benchmark/dist/runners/swarm.js.map +0 -1
- package/packages/benchmark/dist/types.d.ts +0 -178
- package/packages/benchmark/dist/types.d.ts.map +0 -1
- package/packages/benchmark/dist/types.js +0 -16
- package/packages/benchmark/dist/types.js.map +0 -1
- package/packages/benchmark/package.json +0 -80
- package/packages/benchmark/src/benchmark.ts +0 -298
- package/packages/benchmark/src/cli.ts +0 -240
- package/packages/benchmark/src/harbor.ts +0 -170
- package/packages/benchmark/src/index.ts +0 -73
- package/packages/benchmark/src/runners/base.ts +0 -205
- package/packages/benchmark/src/runners/index.ts +0 -10
- package/packages/benchmark/src/runners/single.ts +0 -121
- package/packages/benchmark/src/runners/subagent.ts +0 -240
- package/packages/benchmark/src/runners/swarm.ts +0 -326
- package/packages/benchmark/src/types.ts +0 -205
- package/packages/benchmark/tsconfig.json +0 -20
- package/packages/cli-tester/README.md +0 -277
- package/packages/cli-tester/dist/index.d.ts +0 -21
- package/packages/cli-tester/dist/index.d.ts.map +0 -1
- package/packages/cli-tester/dist/index.js +0 -21
- package/packages/cli-tester/dist/index.js.map +0 -1
- package/packages/cli-tester/dist/utils/credential-check.d.ts +0 -56
- package/packages/cli-tester/dist/utils/credential-check.d.ts.map +0 -1
- package/packages/cli-tester/dist/utils/credential-check.js +0 -230
- package/packages/cli-tester/dist/utils/credential-check.js.map +0 -1
- package/packages/cli-tester/dist/utils/socket-client.d.ts +0 -76
- package/packages/cli-tester/dist/utils/socket-client.d.ts.map +0 -1
- package/packages/cli-tester/dist/utils/socket-client.js +0 -153
- package/packages/cli-tester/dist/utils/socket-client.js.map +0 -1
- package/packages/cli-tester/docker/Dockerfile +0 -61
- package/packages/cli-tester/docker/docker-compose.yml +0 -71
- package/packages/cli-tester/docker/entrypoint.sh +0 -58
- package/packages/cli-tester/package.json +0 -32
- package/packages/cli-tester/scripts/clear-auth.sh +0 -101
- package/packages/cli-tester/scripts/inject-message.sh +0 -42
- package/packages/cli-tester/scripts/start.sh +0 -71
- package/packages/cli-tester/scripts/test-cli.sh +0 -56
- package/packages/cli-tester/scripts/test-full-spawn.sh +0 -238
- package/packages/cli-tester/scripts/test-registration.sh +0 -182
- package/packages/cli-tester/scripts/test-setup-flow.sh +0 -202
- package/packages/cli-tester/scripts/test-spawn.sh +0 -140
- package/packages/cli-tester/scripts/test-with-daemon.sh +0 -247
- package/packages/cli-tester/scripts/verify-auth.sh +0 -112
- package/packages/cli-tester/src/index.ts +0 -40
- package/packages/cli-tester/src/utils/credential-check.ts +0 -284
- package/packages/cli-tester/src/utils/socket-client.ts +0 -211
- package/packages/cli-tester/tests/credential-check.test.ts +0 -56
- package/packages/cli-tester/tsconfig.json +0 -11
- package/packages/sdk/dist/browser-client.d.ts +0 -212
- package/packages/sdk/dist/browser-client.d.ts.map +0 -1
- package/packages/sdk/dist/browser-client.js +0 -750
- package/packages/sdk/dist/browser-client.js.map +0 -1
- package/packages/sdk/dist/browser-framing.d.ts +0 -46
- package/packages/sdk/dist/browser-framing.d.ts.map +0 -1
- package/packages/sdk/dist/browser-framing.js +0 -122
- package/packages/sdk/dist/browser-framing.js.map +0 -1
- package/packages/sdk/dist/standalone.d.ts +0 -89
- package/packages/sdk/dist/standalone.d.ts.map +0 -1
- package/packages/sdk/dist/standalone.js +0 -131
- package/packages/sdk/dist/standalone.js.map +0 -1
- package/packages/sdk/dist/transports/index.d.ts +0 -92
- package/packages/sdk/dist/transports/index.d.ts.map +0 -1
- package/packages/sdk/dist/transports/index.js +0 -129
- package/packages/sdk/dist/transports/index.js.map +0 -1
- package/packages/sdk/dist/transports/socket-transport.d.ts +0 -30
- package/packages/sdk/dist/transports/socket-transport.d.ts.map +0 -1
- package/packages/sdk/dist/transports/socket-transport.js +0 -94
- package/packages/sdk/dist/transports/socket-transport.js.map +0 -1
- package/packages/sdk/dist/transports/types.d.ts +0 -69
- package/packages/sdk/dist/transports/types.d.ts.map +0 -1
- package/packages/sdk/dist/transports/types.js +0 -10
- package/packages/sdk/dist/transports/types.js.map +0 -1
- package/packages/sdk/dist/transports/websocket-transport.d.ts +0 -55
- package/packages/sdk/dist/transports/websocket-transport.d.ts.map +0 -1
- package/packages/sdk/dist/transports/websocket-transport.js +0 -180
- package/packages/sdk/dist/transports/websocket-transport.js.map +0 -1
- package/packages/sdk/src/browser-client.ts +0 -985
- package/packages/sdk/src/browser-framing.test.ts +0 -115
- package/packages/sdk/src/browser-framing.ts +0 -150
- package/packages/sdk/src/standalone.ts +0 -183
- package/packages/sdk/src/transports/index.ts +0 -197
- package/packages/sdk/src/transports/socket-transport.ts +0 -115
- package/packages/sdk/src/transports/types.ts +0 -77
- package/packages/sdk/src/transports/websocket-transport.ts +0 -245
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "RelayYamlConfig",
|
|
4
|
+
"title": "Relay YAML Configuration",
|
|
5
|
+
"description": "Schema for relay.yaml workflow configuration files",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["version", "name", "swarm", "agents"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"version": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "Configuration schema version"
|
|
13
|
+
},
|
|
14
|
+
"name": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"description": "Human-readable name for this relay configuration"
|
|
17
|
+
},
|
|
18
|
+
"description": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"description": "Optional description of the configuration"
|
|
21
|
+
},
|
|
22
|
+
"swarm": {
|
|
23
|
+
"$ref": "#/definitions/SwarmConfig"
|
|
24
|
+
},
|
|
25
|
+
"agents": {
|
|
26
|
+
"type": "array",
|
|
27
|
+
"items": {
|
|
28
|
+
"$ref": "#/definitions/AgentDefinition"
|
|
29
|
+
},
|
|
30
|
+
"minItems": 1
|
|
31
|
+
},
|
|
32
|
+
"workflows": {
|
|
33
|
+
"type": "array",
|
|
34
|
+
"items": {
|
|
35
|
+
"$ref": "#/definitions/WorkflowDefinition"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"coordination": {
|
|
39
|
+
"$ref": "#/definitions/CoordinationConfig"
|
|
40
|
+
},
|
|
41
|
+
"state": {
|
|
42
|
+
"$ref": "#/definitions/StateConfig"
|
|
43
|
+
},
|
|
44
|
+
"errorHandling": {
|
|
45
|
+
"$ref": "#/definitions/ErrorHandlingConfig"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"definitions": {
|
|
49
|
+
"SwarmConfig": {
|
|
50
|
+
"type": "object",
|
|
51
|
+
"required": ["pattern"],
|
|
52
|
+
"additionalProperties": false,
|
|
53
|
+
"properties": {
|
|
54
|
+
"pattern": {
|
|
55
|
+
"$ref": "#/definitions/SwarmPattern"
|
|
56
|
+
},
|
|
57
|
+
"maxConcurrency": {
|
|
58
|
+
"type": "integer",
|
|
59
|
+
"minimum": 1,
|
|
60
|
+
"description": "Maximum number of agents running concurrently"
|
|
61
|
+
},
|
|
62
|
+
"timeoutMs": {
|
|
63
|
+
"type": "integer",
|
|
64
|
+
"minimum": 0,
|
|
65
|
+
"description": "Global swarm timeout in milliseconds"
|
|
66
|
+
},
|
|
67
|
+
"channel": {
|
|
68
|
+
"type": "string",
|
|
69
|
+
"description": "Default relay channel for agent communication"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
"SwarmPattern": {
|
|
74
|
+
"type": "string",
|
|
75
|
+
"enum": [
|
|
76
|
+
"fan-out",
|
|
77
|
+
"pipeline",
|
|
78
|
+
"hub-spoke",
|
|
79
|
+
"consensus",
|
|
80
|
+
"mesh",
|
|
81
|
+
"handoff",
|
|
82
|
+
"cascade",
|
|
83
|
+
"dag",
|
|
84
|
+
"debate",
|
|
85
|
+
"hierarchical"
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
"AgentDefinition": {
|
|
89
|
+
"type": "object",
|
|
90
|
+
"required": ["name", "cli"],
|
|
91
|
+
"additionalProperties": false,
|
|
92
|
+
"properties": {
|
|
93
|
+
"name": {
|
|
94
|
+
"type": "string",
|
|
95
|
+
"description": "Unique agent name within the workflow"
|
|
96
|
+
},
|
|
97
|
+
"cli": {
|
|
98
|
+
"$ref": "#/definitions/AgentCli"
|
|
99
|
+
},
|
|
100
|
+
"role": {
|
|
101
|
+
"type": "string",
|
|
102
|
+
"description": "Agent role description"
|
|
103
|
+
},
|
|
104
|
+
"task": {
|
|
105
|
+
"type": "string",
|
|
106
|
+
"description": "Default task assigned to the agent"
|
|
107
|
+
},
|
|
108
|
+
"channels": {
|
|
109
|
+
"type": "array",
|
|
110
|
+
"items": { "type": "string" },
|
|
111
|
+
"description": "Relay channels the agent should join"
|
|
112
|
+
},
|
|
113
|
+
"constraints": {
|
|
114
|
+
"$ref": "#/definitions/AgentConstraints"
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"AgentCli": {
|
|
119
|
+
"type": "string",
|
|
120
|
+
"enum": ["claude", "codex", "gemini", "aider", "goose"]
|
|
121
|
+
},
|
|
122
|
+
"AgentConstraints": {
|
|
123
|
+
"type": "object",
|
|
124
|
+
"additionalProperties": false,
|
|
125
|
+
"properties": {
|
|
126
|
+
"maxTokens": {
|
|
127
|
+
"type": "integer",
|
|
128
|
+
"minimum": 1,
|
|
129
|
+
"description": "Maximum token budget for the agent"
|
|
130
|
+
},
|
|
131
|
+
"timeoutMs": {
|
|
132
|
+
"type": "integer",
|
|
133
|
+
"minimum": 0,
|
|
134
|
+
"description": "Per-agent timeout in milliseconds"
|
|
135
|
+
},
|
|
136
|
+
"retries": {
|
|
137
|
+
"type": "integer",
|
|
138
|
+
"minimum": 0,
|
|
139
|
+
"description": "Number of retry attempts on failure"
|
|
140
|
+
},
|
|
141
|
+
"model": {
|
|
142
|
+
"type": "string",
|
|
143
|
+
"description": "Model override for the agent"
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
"WorkflowDefinition": {
|
|
148
|
+
"type": "object",
|
|
149
|
+
"required": ["name", "steps"],
|
|
150
|
+
"additionalProperties": false,
|
|
151
|
+
"properties": {
|
|
152
|
+
"name": {
|
|
153
|
+
"type": "string",
|
|
154
|
+
"description": "Unique workflow name"
|
|
155
|
+
},
|
|
156
|
+
"description": {
|
|
157
|
+
"type": "string"
|
|
158
|
+
},
|
|
159
|
+
"steps": {
|
|
160
|
+
"type": "array",
|
|
161
|
+
"items": {
|
|
162
|
+
"$ref": "#/definitions/WorkflowStep"
|
|
163
|
+
},
|
|
164
|
+
"minItems": 1
|
|
165
|
+
},
|
|
166
|
+
"onError": {
|
|
167
|
+
"type": "string",
|
|
168
|
+
"enum": ["fail", "skip", "retry"],
|
|
169
|
+
"description": "Error handling strategy for this workflow"
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
"WorkflowStep": {
|
|
174
|
+
"type": "object",
|
|
175
|
+
"required": ["name", "agent", "task"],
|
|
176
|
+
"additionalProperties": false,
|
|
177
|
+
"properties": {
|
|
178
|
+
"name": {
|
|
179
|
+
"type": "string",
|
|
180
|
+
"description": "Unique step name within the workflow"
|
|
181
|
+
},
|
|
182
|
+
"agent": {
|
|
183
|
+
"type": "string",
|
|
184
|
+
"description": "Name of the agent to execute this step"
|
|
185
|
+
},
|
|
186
|
+
"task": {
|
|
187
|
+
"type": "string",
|
|
188
|
+
"description": "Task description for the agent"
|
|
189
|
+
},
|
|
190
|
+
"dependsOn": {
|
|
191
|
+
"type": "array",
|
|
192
|
+
"items": { "type": "string" },
|
|
193
|
+
"description": "Step names that must complete before this step runs"
|
|
194
|
+
},
|
|
195
|
+
"verification": {
|
|
196
|
+
"$ref": "#/definitions/VerificationCheck"
|
|
197
|
+
},
|
|
198
|
+
"timeoutMs": {
|
|
199
|
+
"type": "integer",
|
|
200
|
+
"minimum": 0
|
|
201
|
+
},
|
|
202
|
+
"retries": {
|
|
203
|
+
"type": "integer",
|
|
204
|
+
"minimum": 0
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
"VerificationCheck": {
|
|
209
|
+
"type": "object",
|
|
210
|
+
"required": ["type", "value"],
|
|
211
|
+
"additionalProperties": false,
|
|
212
|
+
"properties": {
|
|
213
|
+
"type": {
|
|
214
|
+
"type": "string",
|
|
215
|
+
"enum": ["output_contains", "exit_code", "file_exists", "custom"],
|
|
216
|
+
"description": "Type of verification to perform"
|
|
217
|
+
},
|
|
218
|
+
"value": {
|
|
219
|
+
"type": "string",
|
|
220
|
+
"description": "Expected value or expression for verification"
|
|
221
|
+
},
|
|
222
|
+
"description": {
|
|
223
|
+
"type": "string",
|
|
224
|
+
"description": "Human-readable description of what is being verified"
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
"CoordinationConfig": {
|
|
229
|
+
"type": "object",
|
|
230
|
+
"additionalProperties": false,
|
|
231
|
+
"properties": {
|
|
232
|
+
"barriers": {
|
|
233
|
+
"type": "array",
|
|
234
|
+
"items": {
|
|
235
|
+
"$ref": "#/definitions/Barrier"
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
"votingThreshold": {
|
|
239
|
+
"type": "number",
|
|
240
|
+
"minimum": 0,
|
|
241
|
+
"maximum": 1,
|
|
242
|
+
"description": "Fraction of agents required for voting (0-1)"
|
|
243
|
+
},
|
|
244
|
+
"consensusStrategy": {
|
|
245
|
+
"type": "string",
|
|
246
|
+
"enum": ["majority", "unanimous", "quorum"],
|
|
247
|
+
"description": "Strategy for reaching consensus among agents"
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
"Barrier": {
|
|
252
|
+
"type": "object",
|
|
253
|
+
"required": ["name", "waitFor"],
|
|
254
|
+
"additionalProperties": false,
|
|
255
|
+
"properties": {
|
|
256
|
+
"name": {
|
|
257
|
+
"type": "string",
|
|
258
|
+
"description": "Unique barrier name"
|
|
259
|
+
},
|
|
260
|
+
"waitFor": {
|
|
261
|
+
"type": "array",
|
|
262
|
+
"items": { "type": "string" },
|
|
263
|
+
"minItems": 1,
|
|
264
|
+
"description": "Agent or step names to wait for before proceeding"
|
|
265
|
+
},
|
|
266
|
+
"timeoutMs": {
|
|
267
|
+
"type": "integer",
|
|
268
|
+
"minimum": 0,
|
|
269
|
+
"description": "Timeout for the barrier in milliseconds"
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
"StateConfig": {
|
|
274
|
+
"type": "object",
|
|
275
|
+
"required": ["backend"],
|
|
276
|
+
"additionalProperties": false,
|
|
277
|
+
"properties": {
|
|
278
|
+
"backend": {
|
|
279
|
+
"type": "string",
|
|
280
|
+
"enum": ["memory", "redis", "database"],
|
|
281
|
+
"description": "State storage backend"
|
|
282
|
+
},
|
|
283
|
+
"ttlMs": {
|
|
284
|
+
"type": "integer",
|
|
285
|
+
"minimum": 0,
|
|
286
|
+
"description": "Time-to-live for state entries in milliseconds"
|
|
287
|
+
},
|
|
288
|
+
"namespace": {
|
|
289
|
+
"type": "string",
|
|
290
|
+
"description": "Namespace prefix for state keys"
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
"ErrorHandlingConfig": {
|
|
295
|
+
"type": "object",
|
|
296
|
+
"required": ["strategy"],
|
|
297
|
+
"additionalProperties": false,
|
|
298
|
+
"properties": {
|
|
299
|
+
"strategy": {
|
|
300
|
+
"type": "string",
|
|
301
|
+
"enum": ["fail-fast", "continue", "retry"],
|
|
302
|
+
"description": "Global error handling strategy"
|
|
303
|
+
},
|
|
304
|
+
"maxRetries": {
|
|
305
|
+
"type": "integer",
|
|
306
|
+
"minimum": 0,
|
|
307
|
+
"description": "Maximum number of retries"
|
|
308
|
+
},
|
|
309
|
+
"retryDelayMs": {
|
|
310
|
+
"type": "integer",
|
|
311
|
+
"minimum": 0,
|
|
312
|
+
"description": "Delay between retries in milliseconds"
|
|
313
|
+
},
|
|
314
|
+
"notifyChannel": {
|
|
315
|
+
"type": "string",
|
|
316
|
+
"description": "Relay channel to notify on errors"
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State Store — CRUD on swarm_state with optional consensus-gated writes.
|
|
3
|
+
*
|
|
4
|
+
* Provides a key-value store scoped to a workflow run and namespace.
|
|
5
|
+
* When consensus gating is enabled, writes require approval from a
|
|
6
|
+
* ConsensusEngine before being committed.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { randomBytes } from 'node:crypto';
|
|
10
|
+
import { EventEmitter } from 'node:events';
|
|
11
|
+
import type { DbClient } from './coordinator.js';
|
|
12
|
+
|
|
13
|
+
// ── Types ───────────────────────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
export interface StateEntry {
|
|
16
|
+
id: string;
|
|
17
|
+
runId: string;
|
|
18
|
+
namespace: string;
|
|
19
|
+
key: string;
|
|
20
|
+
value: unknown;
|
|
21
|
+
expiresAt: string | null;
|
|
22
|
+
createdAt: string;
|
|
23
|
+
updatedAt: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface StateStoreOptions {
|
|
27
|
+
/** Default namespace for keys. */
|
|
28
|
+
namespace?: string;
|
|
29
|
+
/** Default TTL in milliseconds for new entries. */
|
|
30
|
+
defaultTtlMs?: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface WriteOptions {
|
|
34
|
+
namespace?: string;
|
|
35
|
+
ttlMs?: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface ReadOptions {
|
|
39
|
+
namespace?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Callback invoked to gate a write. Return true to allow, false to reject. */
|
|
43
|
+
export type ConsensusGate = (
|
|
44
|
+
runId: string,
|
|
45
|
+
key: string,
|
|
46
|
+
value: unknown,
|
|
47
|
+
agent: string,
|
|
48
|
+
) => Promise<boolean>;
|
|
49
|
+
|
|
50
|
+
export interface StateStoreEvents {
|
|
51
|
+
'state:set': (entry: StateEntry) => void;
|
|
52
|
+
'state:deleted': (runId: string, key: string, namespace: string) => void;
|
|
53
|
+
'state:gated': (runId: string, key: string, agent: string) => void;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ── Store ───────────────────────────────────────────────────────────────────
|
|
57
|
+
|
|
58
|
+
export class StateStore extends EventEmitter {
|
|
59
|
+
private db: DbClient;
|
|
60
|
+
private defaultNamespace: string;
|
|
61
|
+
private defaultTtlMs: number | null;
|
|
62
|
+
private consensusGate: ConsensusGate | null = null;
|
|
63
|
+
|
|
64
|
+
constructor(db: DbClient, options: StateStoreOptions = {}) {
|
|
65
|
+
super();
|
|
66
|
+
this.db = db;
|
|
67
|
+
this.defaultNamespace = options.namespace ?? 'default';
|
|
68
|
+
this.defaultTtlMs = options.defaultTtlMs ?? null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ── Consensus gating ──────────────────────────────────────────────────
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Enable consensus-gated writes. When set, every `set()` call will
|
|
75
|
+
* invoke the gate function before persisting. If the gate returns false,
|
|
76
|
+
* the write is rejected.
|
|
77
|
+
*/
|
|
78
|
+
setConsensusGate(gate: ConsensusGate): void {
|
|
79
|
+
this.consensusGate = gate;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
clearConsensusGate(): void {
|
|
83
|
+
this.consensusGate = null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ── Write ─────────────────────────────────────────────────────────────
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Set a key-value pair. If consensus gating is enabled, the write is
|
|
90
|
+
* subject to approval.
|
|
91
|
+
*
|
|
92
|
+
* @param agent - The agent requesting the write (used for consensus gating).
|
|
93
|
+
*/
|
|
94
|
+
async set(
|
|
95
|
+
runId: string,
|
|
96
|
+
key: string,
|
|
97
|
+
value: unknown,
|
|
98
|
+
agent: string,
|
|
99
|
+
options: WriteOptions = {},
|
|
100
|
+
): Promise<StateEntry> {
|
|
101
|
+
// Consensus gate check.
|
|
102
|
+
if (this.consensusGate) {
|
|
103
|
+
const allowed = await this.consensusGate(runId, key, value, agent);
|
|
104
|
+
if (!allowed) {
|
|
105
|
+
this.emit('state:gated', runId, key, agent);
|
|
106
|
+
throw new Error(
|
|
107
|
+
`Write to "${key}" rejected by consensus gate for agent "${agent}"`,
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const namespace = options.namespace ?? this.defaultNamespace;
|
|
113
|
+
const ttlMs = options.ttlMs ?? this.defaultTtlMs;
|
|
114
|
+
const expiresAt = ttlMs ? new Date(Date.now() + ttlMs).toISOString() : null;
|
|
115
|
+
const id = `st_${Date.now()}_${randomBytes(4).toString('hex')}`;
|
|
116
|
+
const now = new Date().toISOString();
|
|
117
|
+
|
|
118
|
+
// Upsert: use the unique (run_id, namespace, key) constraint.
|
|
119
|
+
const { rows } = await this.db.query<StateEntry>(
|
|
120
|
+
`INSERT INTO swarm_state (id, run_id, namespace, key, value, expires_at, created_at, updated_at)
|
|
121
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $7)
|
|
122
|
+
ON CONFLICT (run_id, namespace, key)
|
|
123
|
+
DO UPDATE SET value = EXCLUDED.value, expires_at = EXCLUDED.expires_at, updated_at = EXCLUDED.updated_at
|
|
124
|
+
RETURNING *`,
|
|
125
|
+
[id, runId, namespace, key, JSON.stringify(value), expiresAt, now],
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
const entry = rows[0];
|
|
129
|
+
this.emit('state:set', entry);
|
|
130
|
+
return entry;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// ── Read ──────────────────────────────────────────────────────────────
|
|
134
|
+
|
|
135
|
+
async get(
|
|
136
|
+
runId: string,
|
|
137
|
+
key: string,
|
|
138
|
+
options: ReadOptions = {},
|
|
139
|
+
): Promise<unknown | null> {
|
|
140
|
+
const namespace = options.namespace ?? this.defaultNamespace;
|
|
141
|
+
|
|
142
|
+
const { rows } = await this.db.query<StateEntry>(
|
|
143
|
+
`SELECT * FROM swarm_state
|
|
144
|
+
WHERE run_id = $1 AND namespace = $2 AND key = $3
|
|
145
|
+
AND (expires_at IS NULL OR expires_at > now())`,
|
|
146
|
+
[runId, namespace, key],
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
if (rows.length === 0) return null;
|
|
150
|
+
return rows[0].value;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async getEntry(
|
|
154
|
+
runId: string,
|
|
155
|
+
key: string,
|
|
156
|
+
options: ReadOptions = {},
|
|
157
|
+
): Promise<StateEntry | null> {
|
|
158
|
+
const namespace = options.namespace ?? this.defaultNamespace;
|
|
159
|
+
|
|
160
|
+
const { rows } = await this.db.query<StateEntry>(
|
|
161
|
+
`SELECT * FROM swarm_state
|
|
162
|
+
WHERE run_id = $1 AND namespace = $2 AND key = $3
|
|
163
|
+
AND (expires_at IS NULL OR expires_at > now())`,
|
|
164
|
+
[runId, namespace, key],
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
return rows[0] ?? null;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async getAll(
|
|
171
|
+
runId: string,
|
|
172
|
+
options: ReadOptions = {},
|
|
173
|
+
): Promise<StateEntry[]> {
|
|
174
|
+
const namespace = options.namespace ?? this.defaultNamespace;
|
|
175
|
+
|
|
176
|
+
const { rows } = await this.db.query<StateEntry>(
|
|
177
|
+
`SELECT * FROM swarm_state
|
|
178
|
+
WHERE run_id = $1 AND namespace = $2
|
|
179
|
+
AND (expires_at IS NULL OR expires_at > now())
|
|
180
|
+
ORDER BY key ASC`,
|
|
181
|
+
[runId, namespace],
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
return rows;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async keys(
|
|
188
|
+
runId: string,
|
|
189
|
+
options: ReadOptions = {},
|
|
190
|
+
): Promise<string[]> {
|
|
191
|
+
const namespace = options.namespace ?? this.defaultNamespace;
|
|
192
|
+
|
|
193
|
+
const { rows } = await this.db.query<{ key: string }>(
|
|
194
|
+
`SELECT key FROM swarm_state
|
|
195
|
+
WHERE run_id = $1 AND namespace = $2
|
|
196
|
+
AND (expires_at IS NULL OR expires_at > now())
|
|
197
|
+
ORDER BY key ASC`,
|
|
198
|
+
[runId, namespace],
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
return rows.map((r) => r.key);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// ── Delete ────────────────────────────────────────────────────────────
|
|
205
|
+
|
|
206
|
+
async delete(
|
|
207
|
+
runId: string,
|
|
208
|
+
key: string,
|
|
209
|
+
options: ReadOptions = {},
|
|
210
|
+
): Promise<boolean> {
|
|
211
|
+
const namespace = options.namespace ?? this.defaultNamespace;
|
|
212
|
+
|
|
213
|
+
const { rows } = await this.db.query(
|
|
214
|
+
`DELETE FROM swarm_state WHERE run_id = $1 AND namespace = $2 AND key = $3 RETURNING id`,
|
|
215
|
+
[runId, namespace, key],
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
if (rows.length > 0) {
|
|
219
|
+
this.emit('state:deleted', runId, key, namespace);
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
async deleteAll(
|
|
227
|
+
runId: string,
|
|
228
|
+
options: ReadOptions = {},
|
|
229
|
+
): Promise<number> {
|
|
230
|
+
const namespace = options.namespace ?? this.defaultNamespace;
|
|
231
|
+
|
|
232
|
+
const { rows } = await this.db.query(
|
|
233
|
+
`DELETE FROM swarm_state WHERE run_id = $1 AND namespace = $2 RETURNING id`,
|
|
234
|
+
[runId, namespace],
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
return rows.length;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// ── Expiry cleanup ────────────────────────────────────────────────────
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Remove all expired entries for a run (or globally if runId is omitted).
|
|
244
|
+
* Returns the number of entries purged.
|
|
245
|
+
*/
|
|
246
|
+
async purgeExpired(runId?: string): Promise<number> {
|
|
247
|
+
if (runId) {
|
|
248
|
+
const { rows } = await this.db.query(
|
|
249
|
+
`DELETE FROM swarm_state WHERE run_id = $1 AND expires_at IS NOT NULL AND expires_at <= now() RETURNING id`,
|
|
250
|
+
[runId],
|
|
251
|
+
);
|
|
252
|
+
return rows.length;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const { rows } = await this.db.query(
|
|
256
|
+
`DELETE FROM swarm_state WHERE expires_at IS NOT NULL AND expires_at <= now() RETURNING id`,
|
|
257
|
+
[],
|
|
258
|
+
);
|
|
259
|
+
return rows.length;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// ── Snapshot ───────────────────────────────────────────────────────────
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Take a snapshot of all state for a run as a plain object.
|
|
266
|
+
* Useful for persisting into workflow_runs.state_snapshot.
|
|
267
|
+
*/
|
|
268
|
+
async snapshot(
|
|
269
|
+
runId: string,
|
|
270
|
+
options: ReadOptions = {},
|
|
271
|
+
): Promise<Record<string, unknown>> {
|
|
272
|
+
const entries = await this.getAll(runId, options);
|
|
273
|
+
const result: Record<string, unknown> = {};
|
|
274
|
+
for (const entry of entries) {
|
|
275
|
+
result[entry.key] = entry.value;
|
|
276
|
+
}
|
|
277
|
+
return result;
|
|
278
|
+
}
|
|
279
|
+
}
|