@mclawnet/swarm 0.1.4 → 0.1.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 +118 -0
- package/dist/__tests__/action-parser.test.js +29 -82
- package/dist/__tests__/action-parser.test.js.map +1 -1
- package/dist/__tests__/coordinator-create-tx.test.d.ts +2 -0
- package/dist/__tests__/coordinator-create-tx.test.d.ts.map +1 -0
- package/dist/__tests__/coordinator-create-tx.test.js +114 -0
- package/dist/__tests__/coordinator-create-tx.test.js.map +1 -0
- package/dist/__tests__/coordinator-inbox-migration.test.d.ts +2 -0
- package/dist/__tests__/coordinator-inbox-migration.test.d.ts.map +1 -0
- package/dist/__tests__/coordinator-inbox-migration.test.js +56 -0
- package/dist/__tests__/coordinator-inbox-migration.test.js.map +1 -0
- package/dist/__tests__/inbox-integration.test.d.ts +2 -0
- package/dist/__tests__/inbox-integration.test.d.ts.map +1 -0
- package/dist/__tests__/inbox-integration.test.js +120 -0
- package/dist/__tests__/inbox-integration.test.js.map +1 -0
- package/dist/__tests__/inbox-persistence-recovery.test.d.ts +2 -0
- package/dist/__tests__/inbox-persistence-recovery.test.d.ts.map +1 -0
- package/dist/__tests__/inbox-persistence-recovery.test.js +139 -0
- package/dist/__tests__/inbox-persistence-recovery.test.js.map +1 -0
- package/dist/__tests__/inbox-relay-interceptor.test.d.ts +2 -0
- package/dist/__tests__/inbox-relay-interceptor.test.d.ts.map +1 -0
- package/dist/__tests__/inbox-relay-interceptor.test.js +156 -0
- package/dist/__tests__/inbox-relay-interceptor.test.js.map +1 -0
- package/dist/__tests__/inbox-relay.test.d.ts +2 -0
- package/dist/__tests__/inbox-relay.test.d.ts.map +1 -0
- package/dist/__tests__/inbox-relay.test.js +318 -0
- package/dist/__tests__/inbox-relay.test.js.map +1 -0
- package/dist/__tests__/inbox-store.test.d.ts +2 -0
- package/dist/__tests__/inbox-store.test.d.ts.map +1 -0
- package/dist/__tests__/inbox-store.test.js +129 -0
- package/dist/__tests__/inbox-store.test.js.map +1 -0
- package/dist/__tests__/inbox-watcher.test.d.ts +2 -0
- package/dist/__tests__/inbox-watcher.test.d.ts.map +1 -0
- package/dist/__tests__/inbox-watcher.test.js +104 -0
- package/dist/__tests__/inbox-watcher.test.js.map +1 -0
- package/dist/__tests__/persistence-path.test.d.ts +2 -0
- package/dist/__tests__/persistence-path.test.d.ts.map +1 -0
- package/dist/__tests__/persistence-path.test.js +79 -0
- package/dist/__tests__/persistence-path.test.js.map +1 -0
- package/dist/__tests__/persistence-robust.test.d.ts +2 -0
- package/dist/__tests__/persistence-robust.test.d.ts.map +1 -0
- package/dist/__tests__/persistence-robust.test.js +125 -0
- package/dist/__tests__/persistence-robust.test.js.map +1 -0
- package/dist/__tests__/persistence.test.d.ts +2 -0
- package/dist/__tests__/persistence.test.d.ts.map +1 -0
- package/dist/__tests__/persistence.test.js +105 -0
- package/dist/__tests__/persistence.test.js.map +1 -0
- package/dist/__tests__/phase4-5-e2e.test.d.ts +2 -0
- package/dist/__tests__/phase4-5-e2e.test.d.ts.map +1 -0
- package/dist/__tests__/phase4-5-e2e.test.js +203 -0
- package/dist/__tests__/phase4-5-e2e.test.js.map +1 -0
- package/dist/__tests__/phase6-7-e2e.test.d.ts +2 -0
- package/dist/__tests__/phase6-7-e2e.test.d.ts.map +1 -0
- package/dist/__tests__/phase6-7-e2e.test.js +93 -0
- package/dist/__tests__/phase6-7-e2e.test.js.map +1 -0
- package/dist/__tests__/project-files.test.d.ts +2 -0
- package/dist/__tests__/project-files.test.d.ts.map +1 -0
- package/dist/__tests__/project-files.test.js +143 -0
- package/dist/__tests__/project-files.test.js.map +1 -0
- package/dist/__tests__/projects-fs.test.d.ts +2 -0
- package/dist/__tests__/projects-fs.test.d.ts.map +1 -0
- package/dist/__tests__/projects-fs.test.js +107 -0
- package/dist/__tests__/projects-fs.test.js.map +1 -0
- package/dist/__tests__/recovery-cross-project.test.d.ts +2 -0
- package/dist/__tests__/recovery-cross-project.test.d.ts.map +1 -0
- package/dist/__tests__/recovery-cross-project.test.js +87 -0
- package/dist/__tests__/recovery-cross-project.test.js.map +1 -0
- package/dist/__tests__/recovery-forwards-to-coordinator.test.d.ts +2 -0
- package/dist/__tests__/recovery-forwards-to-coordinator.test.d.ts.map +1 -0
- package/dist/__tests__/recovery-forwards-to-coordinator.test.js +59 -0
- package/dist/__tests__/recovery-forwards-to-coordinator.test.js.map +1 -0
- package/dist/__tests__/recovery-resume.test.d.ts +2 -0
- package/dist/__tests__/recovery-resume.test.d.ts.map +1 -0
- package/dist/__tests__/recovery-resume.test.js +132 -0
- package/dist/__tests__/recovery-resume.test.js.map +1 -0
- package/dist/__tests__/retrospective.test.js +1 -0
- package/dist/__tests__/retrospective.test.js.map +1 -1
- package/dist/__tests__/role-loader-preamble-all.test.d.ts +2 -0
- package/dist/__tests__/role-loader-preamble-all.test.d.ts.map +1 -0
- package/dist/__tests__/role-loader-preamble-all.test.js +38 -0
- package/dist/__tests__/role-loader-preamble-all.test.js.map +1 -0
- package/dist/__tests__/role-loader-tools.test.d.ts +2 -0
- package/dist/__tests__/role-loader-tools.test.d.ts.map +1 -0
- package/dist/__tests__/role-loader-tools.test.js +39 -0
- package/dist/__tests__/role-loader-tools.test.js.map +1 -0
- package/dist/__tests__/role-loader.test.js +116 -1
- package/dist/__tests__/role-loader.test.js.map +1 -1
- package/dist/__tests__/role-prompt-no-legacy-protocol.test.d.ts +2 -0
- package/dist/__tests__/role-prompt-no-legacy-protocol.test.d.ts.map +1 -0
- package/dist/__tests__/role-prompt-no-legacy-protocol.test.js +37 -0
- package/dist/__tests__/role-prompt-no-legacy-protocol.test.js.map +1 -0
- package/dist/__tests__/role-tools.test.d.ts +2 -0
- package/dist/__tests__/role-tools.test.d.ts.map +1 -0
- package/dist/__tests__/role-tools.test.js +80 -0
- package/dist/__tests__/role-tools.test.js.map +1 -0
- package/dist/__tests__/spawn-role-injects-briefings.test.d.ts +2 -0
- package/dist/__tests__/spawn-role-injects-briefings.test.d.ts.map +1 -0
- package/dist/__tests__/spawn-role-injects-briefings.test.js +182 -0
- package/dist/__tests__/spawn-role-injects-briefings.test.js.map +1 -0
- package/dist/__tests__/spawn-role-tool-policy.test.d.ts +2 -0
- package/dist/__tests__/spawn-role-tool-policy.test.d.ts.map +1 -0
- package/dist/__tests__/spawn-role-tool-policy.test.js +96 -0
- package/dist/__tests__/spawn-role-tool-policy.test.js.map +1 -0
- package/dist/__tests__/swarm-coordinator-inbox-watcher.test.d.ts +2 -0
- package/dist/__tests__/swarm-coordinator-inbox-watcher.test.d.ts.map +1 -0
- package/dist/__tests__/swarm-coordinator-inbox-watcher.test.js +61 -0
- package/dist/__tests__/swarm-coordinator-inbox-watcher.test.js.map +1 -0
- package/dist/__tests__/swarm-coordinator-inbox.test.d.ts +2 -0
- package/dist/__tests__/swarm-coordinator-inbox.test.d.ts.map +1 -0
- package/dist/__tests__/swarm-coordinator-inbox.test.js +182 -0
- package/dist/__tests__/swarm-coordinator-inbox.test.js.map +1 -0
- package/dist/__tests__/swarm-coordinator-init.test.js +36 -8
- package/dist/__tests__/swarm-coordinator-init.test.js.map +1 -1
- package/dist/__tests__/swarm-coordinator-legacy-plan-review-warn.test.d.ts +2 -0
- package/dist/__tests__/swarm-coordinator-legacy-plan-review-warn.test.d.ts.map +1 -0
- package/dist/__tests__/swarm-coordinator-legacy-plan-review-warn.test.js +113 -0
- package/dist/__tests__/swarm-coordinator-legacy-plan-review-warn.test.js.map +1 -0
- package/dist/__tests__/swarm-coordinator-plan-review-intercept.test.d.ts +2 -0
- package/dist/__tests__/swarm-coordinator-plan-review-intercept.test.d.ts.map +1 -0
- package/dist/__tests__/swarm-coordinator-plan-review-intercept.test.js +465 -0
- package/dist/__tests__/swarm-coordinator-plan-review-intercept.test.js.map +1 -0
- package/dist/__tests__/swarm-coordinator-plan-review-recovery.test.d.ts +2 -0
- package/dist/__tests__/swarm-coordinator-plan-review-recovery.test.d.ts.map +1 -0
- package/dist/__tests__/swarm-coordinator-plan-review-recovery.test.js +284 -0
- package/dist/__tests__/swarm-coordinator-plan-review-recovery.test.js.map +1 -0
- package/dist/__tests__/swarm-coordinator-plan-review.test.d.ts +2 -0
- package/dist/__tests__/swarm-coordinator-plan-review.test.d.ts.map +1 -0
- package/dist/__tests__/swarm-coordinator-plan-review.test.js +294 -0
- package/dist/__tests__/swarm-coordinator-plan-review.test.js.map +1 -0
- package/dist/__tests__/swarm-coordinator-resume.test.d.ts +2 -0
- package/dist/__tests__/swarm-coordinator-resume.test.d.ts.map +1 -0
- package/dist/__tests__/swarm-coordinator-resume.test.js +93 -0
- package/dist/__tests__/swarm-coordinator-resume.test.js.map +1 -0
- package/dist/__tests__/swarm-coordinator-roleId.test.js +2 -2
- package/dist/__tests__/swarm-coordinator-roleId.test.js.map +1 -1
- package/dist/__tests__/swarm-destroy-detach.test.d.ts +2 -0
- package/dist/__tests__/swarm-destroy-detach.test.d.ts.map +1 -0
- package/dist/__tests__/swarm-destroy-detach.test.js +135 -0
- package/dist/__tests__/swarm-destroy-detach.test.js.map +1 -0
- package/dist/action-parser.d.ts +0 -9
- package/dist/action-parser.d.ts.map +1 -1
- package/dist/action-parser.js +0 -114
- package/dist/action-parser.js.map +1 -1
- package/dist/inbox-relay.d.ts +50 -0
- package/dist/inbox-relay.d.ts.map +1 -0
- package/dist/inbox-relay.js +168 -0
- package/dist/inbox-relay.js.map +1 -0
- package/dist/inbox-store.d.ts +25 -0
- package/dist/inbox-store.d.ts.map +1 -0
- package/dist/inbox-store.js +95 -0
- package/dist/inbox-store.js.map +1 -0
- package/dist/inbox-watcher.d.ts +13 -0
- package/dist/inbox-watcher.d.ts.map +1 -0
- package/dist/inbox-watcher.js +89 -0
- package/dist/inbox-watcher.js.map +1 -0
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/persistence.d.ts +19 -5
- package/dist/persistence.d.ts.map +1 -1
- package/dist/persistence.js +97 -22
- package/dist/persistence.js.map +1 -1
- package/dist/project-files.d.ts +60 -0
- package/dist/project-files.d.ts.map +1 -0
- package/dist/project-files.js +214 -0
- package/dist/project-files.js.map +1 -0
- package/dist/projects-fs.d.ts +28 -0
- package/dist/projects-fs.d.ts.map +1 -0
- package/dist/projects-fs.js +111 -0
- package/dist/projects-fs.js.map +1 -0
- package/dist/recovery.d.ts +12 -0
- package/dist/recovery.d.ts.map +1 -1
- package/dist/recovery.js +14 -19
- package/dist/recovery.js.map +1 -1
- package/dist/roles/role-loader.d.ts +28 -1
- package/dist/roles/role-loader.d.ts.map +1 -1
- package/dist/roles/role-loader.js +73 -1
- package/dist/roles/role-loader.js.map +1 -1
- package/dist/roles/role-tools.d.ts +16 -0
- package/dist/roles/role-tools.d.ts.map +1 -0
- package/dist/roles/role-tools.js +25 -0
- package/dist/roles/role-tools.js.map +1 -0
- package/dist/roles/types.d.ts +4 -0
- package/dist/roles/types.d.ts.map +1 -1
- package/dist/swarm-coordinator.d.ts +176 -12
- package/dist/swarm-coordinator.d.ts.map +1 -1
- package/dist/swarm-coordinator.js +863 -370
- package/dist/swarm-coordinator.js.map +1 -1
- package/dist/types.d.ts +26 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +9 -6
- package/roles/analyst-livermore.md +6 -30
- package/roles/designer-rams.md +2 -30
- package/roles/dev-torvalds.md +8 -44
- package/roles/developer.md +5 -21
- package/roles/director-jia.md +20 -49
- package/roles/editor-boyong.md +8 -40
- package/roles/macro-dalio.md +6 -30
- package/roles/planner-maoni.md +24 -53
- package/roles/pm-jobs.md +20 -71
- package/roles/preset-analyst-simons.md +2 -18
- package/roles/preset-architect-knuth.md +2 -18
- package/roles/preset-designer-norman.md +2 -18
- package/roles/preset-designer.md +2 -18
- package/roles/preset-dev-carmack.md +2 -18
- package/roles/preset-dev-gosling.md +2 -18
- package/roles/preset-developer.md +7 -23
- package/roles/preset-manager-grove.md +2 -18
- package/roles/preset-manager-musk.md +2 -18
- package/roles/preset-pm.md +7 -34
- package/roles/preset-researcher-feynman.md +2 -18
- package/roles/preset-reviewer.md +5 -21
- package/roles/preset-strategist-buffett.md +2 -18
- package/roles/preset-strategist-munger.md +2 -18
- package/roles/preset-strategist-sunzi.md +2 -18
- package/roles/preset-tester-beck.md +2 -18
- package/roles/preset-tester.md +5 -21
- package/roles/preset-writer-orwell.md +2 -18
- package/roles/preset-writer.md +2 -18
- package/roles/quant-simons.md +5 -32
- package/roles/queen.md +25 -41
- package/roles/reviewer-martin.md +11 -37
- package/roles/reviewer.md +20 -21
- package/roles/rhythm-tangsan.md +5 -29
- package/roles/risk-taleb.md +4 -32
- package/roles/script-shitiesheng.md +8 -31
- package/roles/storyboard-xuke.md +9 -29
- package/roles/strategist-soros.md +16 -73
- package/roles/tester-beck.md +4 -40
- package/roles/tester.md +5 -21
- package/roles/trader-jones.md +4 -32
- package/roles/vfx-guchangwei.md +8 -27
- package/roles/writer-zhouzi.md +7 -39
- package/templates/dev-team-pro.md +4 -1
- package/templates/dev-team.md +3 -1
- package/templates/minimal.md +2 -1
- package/templates/trading-team.md +6 -1
- package/templates/video-team.md +4 -1
- package/templates/writing-team.md +4 -1
package/README.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# @mclawnet/swarm
|
|
2
|
+
|
|
3
|
+
Swarm coordination, message routing, and role management. Phase 2 adds an
|
|
4
|
+
**Inbox layer** (`InboxStore` + `InboxRelay`) on top of the existing
|
|
5
|
+
`SwarmCoordinator`, giving the host a push-based path for delivering
|
|
6
|
+
messages to agent sessions.
|
|
7
|
+
|
|
8
|
+
## BREAKING CHANGE — persistence path migrated
|
|
9
|
+
|
|
10
|
+
Swarm state has moved under the per-project directory shared with
|
|
11
|
+
`@mclawnet/task`:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
OLD: ~/.clawnet/swarms/<swarmId>/...
|
|
15
|
+
NEW: ~/.clawnet/projects/<encoded-cwd>/swarms/<swarmId>/...
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
There is **no backward-compatibility shim**. Snapshots, message logs, and
|
|
19
|
+
inbox files written by 0.1.4 and earlier will not be picked up by 0.1.5+.
|
|
20
|
+
Any in-flight swarms should be drained before upgrading.
|
|
21
|
+
|
|
22
|
+
`<encoded-cwd>` is computed by `encodeCwd()` from `@mclawnet/task` (absolute
|
|
23
|
+
path with `/` replaced by `-`).
|
|
24
|
+
|
|
25
|
+
## Modules
|
|
26
|
+
|
|
27
|
+
### Coordinator (existing)
|
|
28
|
+
|
|
29
|
+
`SwarmCoordinator`, action parsing, role/template
|
|
30
|
+
loading, persistence, and recovery — see exports in `src/index.ts`.
|
|
31
|
+
Inter-role messaging is delivered via `InboxStore` + `InboxRelay` (see below).
|
|
32
|
+
|
|
33
|
+
### Inbox (new)
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
interface InboxMessage {
|
|
37
|
+
id: string;
|
|
38
|
+
from: string;
|
|
39
|
+
type: string;
|
|
40
|
+
data: string;
|
|
41
|
+
taskId?: string;
|
|
42
|
+
timestamp: number;
|
|
43
|
+
delivered: boolean;
|
|
44
|
+
deliveredAt?: number;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
class InboxStore {
|
|
48
|
+
constructor(workDir: string, swarmId: string);
|
|
49
|
+
append(instanceId: string, msg: InboxMessage): Promise<void>;
|
|
50
|
+
readAll(instanceId: string): Promise<InboxMessage[]>;
|
|
51
|
+
readUndelivered(instanceId: string): Promise<InboxMessage[]>;
|
|
52
|
+
markDelivered(instanceId: string, ids: string[]): Promise<void>;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
class InboxRelay {
|
|
56
|
+
constructor(
|
|
57
|
+
sessionAdapter: SessionAdapter,
|
|
58
|
+
getSwarm: (swarmId: string) => SwarmInstance | undefined,
|
|
59
|
+
);
|
|
60
|
+
deliver(swarmId: string, instanceId: string): Promise<void>;
|
|
61
|
+
onAgentTurnSettled(swarmId: string, instanceId: string): Promise<void>;
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`InboxStore` writes one JSON file per recipient under
|
|
66
|
+
`~/.clawnet/projects/<encoded-cwd>/swarms/<swarmId>/inboxes/<instanceId>.json`,
|
|
67
|
+
guarded by `proper-lockfile` for concurrent appenders.
|
|
68
|
+
|
|
69
|
+
`InboxRelay` is the push side. It wraps undelivered messages in a single
|
|
70
|
+
`<info_for_agent>` envelope and feeds them to the session through
|
|
71
|
+
`SessionAdapter.sendInput`. Four gates guard the push:
|
|
72
|
+
|
|
73
|
+
1. **single-flight** — at most one in-flight `deliver()` per `(swarmId, instanceId)`.
|
|
74
|
+
2. **liveness** — swarm and role must exist with a `workDir`.
|
|
75
|
+
3. **lifecycle** — agents in `spawning` or `stopped` are skipped.
|
|
76
|
+
4. **pending-echo** — messages already pushed but not yet ack'd by a turn
|
|
77
|
+
completion are not re-pushed.
|
|
78
|
+
|
|
79
|
+
`onAgentTurnSettled()` is called when the host sees a `result` event for a
|
|
80
|
+
turn; it marks pending messages `delivered=true` and triggers another
|
|
81
|
+
deliver pass to flush messages that arrived mid-turn.
|
|
82
|
+
|
|
83
|
+
## Wiring points
|
|
84
|
+
|
|
85
|
+
The host connects the relay to the coordinator at three places:
|
|
86
|
+
|
|
87
|
+
- **spawn** — after `SwarmCoordinator` creates a role and the session is
|
|
88
|
+
ready, call `relay.deliver(swarmId, instanceId)` to flush any inbox
|
|
89
|
+
messages buffered before the agent existed.
|
|
90
|
+
- **resume** — on snapshot recovery, call `deliver()` for each restored role
|
|
91
|
+
so agents receive what queued up while offline.
|
|
92
|
+
- **turn-complete** — on the session adapter's turn-settled signal, call
|
|
93
|
+
`relay.onAgentTurnSettled(swarmId, instanceId)`.
|
|
94
|
+
|
|
95
|
+
Producers append to the inbox via `InboxStore.append()` (e.g. router
|
|
96
|
+
fan-out, task notifications); the relay handles delivery semantics.
|
|
97
|
+
|
|
98
|
+
## Example
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
import { InboxStore, InboxRelay } from "@mclawnet/swarm";
|
|
102
|
+
|
|
103
|
+
const store = new InboxStore(process.cwd(), swarmId);
|
|
104
|
+
await store.append("worker-1", {
|
|
105
|
+
id: crypto.randomUUID(),
|
|
106
|
+
from: "host",
|
|
107
|
+
type: "task-assigned",
|
|
108
|
+
data: "please pick up TASK-42",
|
|
109
|
+
taskId: "TASK-42",
|
|
110
|
+
timestamp: Date.now(),
|
|
111
|
+
delivered: false,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const relay = new InboxRelay(sessionAdapter, (id) => coordinator.get(id));
|
|
115
|
+
await relay.deliver(swarmId, "worker-1");
|
|
116
|
+
// later, when the agent's turn completes:
|
|
117
|
+
await relay.onAgentTurnSettled(swarmId, "worker-1");
|
|
118
|
+
```
|
|
@@ -1,91 +1,38 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
describe("
|
|
4
|
-
it("should parse
|
|
5
|
-
const text =
|
|
6
|
-
\`\`\`
|
|
7
|
-
{"
|
|
2
|
+
import { parsePlanFromText } from "../action-parser.js";
|
|
3
|
+
describe("parsePlanFromText", () => {
|
|
4
|
+
it("should parse plan from ```json code block", () => {
|
|
5
|
+
const text = `Queen 给出方案:
|
|
6
|
+
\`\`\`json
|
|
7
|
+
{"plan":{"goal":"实现登录","tasks":[{"id":"t1","desc":"写表单"}]}}
|
|
8
8
|
\`\`\`
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
expect(
|
|
12
|
-
expect(
|
|
13
|
-
expect(
|
|
14
|
-
expect(cleanText).toContain("一些文字");
|
|
15
|
-
expect(cleanText).toContain("后续文字");
|
|
9
|
+
请审核`;
|
|
10
|
+
const plan = parsePlanFromText(text);
|
|
11
|
+
expect(plan).not.toBeNull();
|
|
12
|
+
expect(plan.goal).toBe("实现登录");
|
|
13
|
+
expect(plan.tasks).toHaveLength(1);
|
|
16
14
|
});
|
|
17
|
-
it("should parse
|
|
18
|
-
const text =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
expect(actions).toHaveLength(1);
|
|
23
|
-
expect(actions[0]).toMatchObject({ action: "send", to: "dev-0" });
|
|
24
|
-
expect(actions[0].data).toContain("```typescript");
|
|
25
|
-
expect(actions[0].data).toContain("const x = 1;");
|
|
15
|
+
it("should parse inline JSON containing plan key", () => {
|
|
16
|
+
const text = `这里直接给出 {"plan":{"goal":"x","tasks":[]}} 内联 JSON`;
|
|
17
|
+
const plan = parsePlanFromText(text);
|
|
18
|
+
expect(plan).not.toBeNull();
|
|
19
|
+
expect(plan.goal).toBe("x");
|
|
26
20
|
});
|
|
27
|
-
it("should
|
|
28
|
-
|
|
29
|
-
{"action":"send","to":"dev-0","type":"task","data":"任务1"}
|
|
30
|
-
\`\`\`
|
|
31
|
-
中间文字
|
|
32
|
-
\`\`\`swarm
|
|
33
|
-
{"action":"report","status":"completed","output":"完成"}
|
|
34
|
-
\`\`\``;
|
|
35
|
-
const { actions, cleanText } = parseSwarmActions(text);
|
|
36
|
-
expect(actions).toHaveLength(2);
|
|
37
|
-
expect(actions[0]).toMatchObject({ action: "send" });
|
|
38
|
-
expect(actions[1]).toMatchObject({ action: "report", status: "completed" });
|
|
39
|
-
expect(cleanText).toContain("中间文字");
|
|
40
|
-
expect(cleanText).not.toContain("```swarm");
|
|
41
|
-
});
|
|
42
|
-
it("should skip malformed JSON", () => {
|
|
43
|
-
const text = `\`\`\`swarm
|
|
44
|
-
{"action":"send","to":"dev-0"
|
|
45
|
-
\`\`\``;
|
|
46
|
-
const { actions } = parseSwarmActions(text);
|
|
47
|
-
expect(actions).toHaveLength(0);
|
|
48
|
-
});
|
|
49
|
-
it("should skip JSON without action field", () => {
|
|
50
|
-
const text = `\`\`\`swarm
|
|
51
|
-
{"foo":"bar"}
|
|
52
|
-
\`\`\``;
|
|
53
|
-
const { actions } = parseSwarmActions(text);
|
|
54
|
-
expect(actions).toHaveLength(0);
|
|
55
|
-
});
|
|
56
|
-
it("should handle nested braces in data field", () => {
|
|
57
|
-
const text = `\`\`\`swarm
|
|
58
|
-
{"action":"send","to":"dev-0","type":"task","data":"{\\"nested\\":{\\"deep\\":true}}"}
|
|
59
|
-
\`\`\``;
|
|
60
|
-
const { actions } = parseSwarmActions(text);
|
|
61
|
-
expect(actions).toHaveLength(1);
|
|
62
|
-
expect(actions[0].data).toBe('{"nested":{"deep":true}}');
|
|
21
|
+
it("should return null when there is no plan", () => {
|
|
22
|
+
expect(parsePlanFromText("普通文字,不含 plan")).toBeNull();
|
|
63
23
|
});
|
|
64
|
-
it("should return
|
|
65
|
-
const text = "
|
|
66
|
-
|
|
67
|
-
expect(actions).toHaveLength(0);
|
|
68
|
-
expect(cleanText).toBe(text);
|
|
24
|
+
it("should return null for malformed JSON", () => {
|
|
25
|
+
const text = "```json\n{\"plan\": { broken }\n```";
|
|
26
|
+
expect(parsePlanFromText(text)).toBeNull();
|
|
69
27
|
});
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
expect(
|
|
78
|
-
expect(cleanText).not.toContain('"action"');
|
|
79
|
-
expect(cleanText).toContain("前文");
|
|
80
|
-
expect(cleanText).toContain("后文");
|
|
81
|
-
});
|
|
82
|
-
it("should handle escaped quotes in data field", () => {
|
|
83
|
-
const text = `\`\`\`swarm
|
|
84
|
-
{"action":"send","to":"dev-0","type":"task","data":"他说:\\"你好\\""}
|
|
85
|
-
\`\`\``;
|
|
86
|
-
const { actions } = parseSwarmActions(text);
|
|
87
|
-
expect(actions).toHaveLength(1);
|
|
88
|
-
expect(actions[0].data).toBe('他说:"你好"');
|
|
28
|
+
});
|
|
29
|
+
describe("action-parser exports (hard cut)", () => {
|
|
30
|
+
it("should not export parseSwarmActions / extractSwarmJsonBlocks / tryExtractPlan", async () => {
|
|
31
|
+
const mod = await import("../action-parser.js");
|
|
32
|
+
expect("parseSwarmActions" in mod).toBe(false);
|
|
33
|
+
expect("extractSwarmJsonBlocks" in mod).toBe(false);
|
|
34
|
+
expect("tryExtractPlan" in mod).toBe(false);
|
|
35
|
+
expect("parsePlanFromText" in mod).toBe(true);
|
|
89
36
|
});
|
|
90
37
|
});
|
|
91
38
|
//# sourceMappingURL=action-parser.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-parser.test.js","sourceRoot":"","sources":["../../src/__tests__/action-parser.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"action-parser.test.js","sourceRoot":"","sources":["../../src/__tests__/action-parser.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,IAAI,GAAG;;;;IAIb,CAAC;QACD,MAAM,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAQ,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC/B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,IAAI,GAAG,iDAAiD,CAAC;QAC/D,MAAM,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAQ,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,IAAI,GAAG,qCAAqC,CAAC;QACnD,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC7C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;IAChD,EAAE,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;QAC7F,MAAM,GAAG,GAA4B,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;QACzE,MAAM,CAAC,mBAAmB,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/C,MAAM,CAAC,wBAAwB,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpD,MAAM,CAAC,gBAAgB,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5C,MAAM,CAAC,mBAAmB,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordinator-create-tx.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/coordinator-create-tx.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
const { warnFn } = vi.hoisted(() => ({ warnFn: vi.fn() }));
|
|
3
|
+
vi.mock("@mclawnet/logger", () => ({
|
|
4
|
+
createLogger: () => ({ info: vi.fn(), warn: warnFn, error: vi.fn(), debug: vi.fn() }),
|
|
5
|
+
}));
|
|
6
|
+
vi.mock("../retrospective.js", () => ({ runRetrospective: vi.fn() }));
|
|
7
|
+
import { mkdtempSync, rmSync, existsSync, mkdirSync, writeFileSync, readFileSync } from "node:fs";
|
|
8
|
+
import { tmpdir } from "node:os";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
// keep persistence real so we can observe snapshot cleanup
|
|
11
|
+
import { SwarmCoordinator } from "../swarm-coordinator.js";
|
|
12
|
+
import { projectRoot } from "@mclawnet/task";
|
|
13
|
+
let tempHome;
|
|
14
|
+
let workDir;
|
|
15
|
+
let prevHome;
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
tempHome = mkdtempSync(join(tmpdir(), "create-tx-"));
|
|
18
|
+
workDir = mkdtempSync(join(tmpdir(), "create-tx-work-"));
|
|
19
|
+
prevHome = process.env.CLAWNET_HOME;
|
|
20
|
+
process.env.CLAWNET_HOME = tempHome;
|
|
21
|
+
warnFn.mockClear();
|
|
22
|
+
});
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
if (prevHome === undefined)
|
|
25
|
+
delete process.env.CLAWNET_HOME;
|
|
26
|
+
else
|
|
27
|
+
process.env.CLAWNET_HOME = prevHome;
|
|
28
|
+
rmSync(tempHome, { recursive: true, force: true });
|
|
29
|
+
rmSync(workDir, { recursive: true, force: true });
|
|
30
|
+
});
|
|
31
|
+
function makeCoordinator(opts) {
|
|
32
|
+
let openCount = 0;
|
|
33
|
+
const sessionAdapter = {
|
|
34
|
+
createSession: vi.fn(async (options) => {
|
|
35
|
+
openCount++;
|
|
36
|
+
if (opts.failAtRole && openCount === opts.failAtRole) {
|
|
37
|
+
throw new Error(`simulated openSession failure on call ${openCount}`);
|
|
38
|
+
}
|
|
39
|
+
return options.sessionId;
|
|
40
|
+
}),
|
|
41
|
+
closeSession: vi.fn(async (id) => { opts.closed.push(id); }),
|
|
42
|
+
sendInput: vi.fn(),
|
|
43
|
+
};
|
|
44
|
+
const hub = { send: vi.fn() };
|
|
45
|
+
return new SwarmCoordinator(sessionAdapter, hub);
|
|
46
|
+
}
|
|
47
|
+
describe("SwarmCoordinator.create — transactional cleanup", () => {
|
|
48
|
+
it("on spawnRole failure, retry with same swarmId succeeds (state was cleaned up)", async () => {
|
|
49
|
+
const closed = [];
|
|
50
|
+
const coord1 = makeCoordinator({ failAtRole: 1, closed });
|
|
51
|
+
await expect(coord1.create("swarm-tx-1", {
|
|
52
|
+
workDir,
|
|
53
|
+
roles: [{ roleName: "queen", eager: true }],
|
|
54
|
+
task: "hello",
|
|
55
|
+
})).rejects.toThrow(/simulated openSession failure/);
|
|
56
|
+
// Memory registry is empty — same id can be reused
|
|
57
|
+
expect(coord1.hasSwarm("swarm-tx-1")).toBe(false);
|
|
58
|
+
// No persisted recovery.json left behind
|
|
59
|
+
const recoveryPath = join(projectRoot(workDir, tempHome), "swarms", "swarm-tx-1", "recovery.json");
|
|
60
|
+
expect(existsSync(recoveryPath)).toBe(false);
|
|
61
|
+
// Retry must NOT throw "already exists"
|
|
62
|
+
const closed2 = [];
|
|
63
|
+
const coord2 = makeCoordinator({ closed: closed2 }); // no failure this time
|
|
64
|
+
await expect(coord2.create("swarm-tx-1", {
|
|
65
|
+
workDir,
|
|
66
|
+
roles: [{ roleName: "queen", eager: true }],
|
|
67
|
+
task: "hello",
|
|
68
|
+
})).resolves.toBeUndefined();
|
|
69
|
+
});
|
|
70
|
+
it("on spawnRole failure mid-loop, all previously opened sessions are closed and timer cleared", async () => {
|
|
71
|
+
const closed = [];
|
|
72
|
+
// Two roles requested; fail on the SECOND openSession
|
|
73
|
+
const coord = makeCoordinator({ failAtRole: 2, closed });
|
|
74
|
+
await expect(coord.create("swarm-tx-2", {
|
|
75
|
+
workDir,
|
|
76
|
+
roles: [
|
|
77
|
+
{ roleName: "queen", eager: true },
|
|
78
|
+
{ roleName: "developer", eager: true },
|
|
79
|
+
],
|
|
80
|
+
task: "hello",
|
|
81
|
+
})).rejects.toThrow(/simulated openSession failure on call 2/);
|
|
82
|
+
// The successfully-opened first role's session must have been closed.
|
|
83
|
+
expect(closed.length).toBeGreaterThanOrEqual(1);
|
|
84
|
+
// No swarm in the map → its checkTimer cannot fire.
|
|
85
|
+
expect(coord.hasSwarm("swarm-tx-2")).toBe(false);
|
|
86
|
+
// Cleanup is logged for visibility (operators want to see this).
|
|
87
|
+
const cleanupLogged = warnFn.mock.calls.some(([ctx, msg]) => {
|
|
88
|
+
const ctxStr = JSON.stringify(ctx ?? {});
|
|
89
|
+
return ctxStr.includes("swarm-tx-2") &&
|
|
90
|
+
/partial.*create|cleanup|rollback/i.test(String(msg ?? ""));
|
|
91
|
+
});
|
|
92
|
+
expect(cleanupLogged).toBe(true);
|
|
93
|
+
});
|
|
94
|
+
it("on spawnRole failure, a pre-existing recovery.json from a prior run is preserved", async () => {
|
|
95
|
+
// Simulate the continuation / restart-after-crash path: recovery.json
|
|
96
|
+
// already exists on disk before create() runs.
|
|
97
|
+
const swarmDir = join(projectRoot(workDir, tempHome), "swarms", "swarm-tx-3");
|
|
98
|
+
mkdirSync(swarmDir, { recursive: true });
|
|
99
|
+
const recoveryPath = join(swarmDir, "recovery.json");
|
|
100
|
+
const priorContent = JSON.stringify({ id: "swarm-tx-3", marker: "PRIOR" });
|
|
101
|
+
writeFileSync(recoveryPath, priorContent);
|
|
102
|
+
const closed = [];
|
|
103
|
+
const coord = makeCoordinator({ failAtRole: 1, closed });
|
|
104
|
+
await expect(coord.create("swarm-tx-3", {
|
|
105
|
+
workDir,
|
|
106
|
+
roles: [{ roleName: "queen", eager: true }],
|
|
107
|
+
task: "hello",
|
|
108
|
+
})).rejects.toThrow(/simulated openSession failure/);
|
|
109
|
+
// The prior snapshot must NOT be deleted by cleanup.
|
|
110
|
+
expect(existsSync(recoveryPath)).toBe(true);
|
|
111
|
+
expect(readFileSync(recoveryPath, "utf-8")).toBe(priorContent);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
//# sourceMappingURL=coordinator-create-tx.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordinator-create-tx.test.js","sourceRoot":"","sources":["../../src/__tests__/coordinator-create-tx.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordinator-inbox-migration.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/coordinator-inbox-migration.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { mkdtempSync, rmSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
vi.mock("@mclawnet/logger", () => ({
|
|
6
|
+
createLogger: () => ({ info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() }),
|
|
7
|
+
}));
|
|
8
|
+
vi.mock("../persistence.js", () => ({
|
|
9
|
+
saveSwarmSnapshot: vi.fn(),
|
|
10
|
+
deleteSwarmSnapshot: vi.fn(),
|
|
11
|
+
appendMessageLog: vi.fn(),
|
|
12
|
+
loadSwarmSnapshot: vi.fn(),
|
|
13
|
+
readMessageLog: vi.fn(() => []),
|
|
14
|
+
}));
|
|
15
|
+
vi.mock("../retrospective.js", () => ({
|
|
16
|
+
runRetrospective: vi.fn(async () => ({})),
|
|
17
|
+
}));
|
|
18
|
+
import { SwarmCoordinator } from "../swarm-coordinator.js";
|
|
19
|
+
import { InboxStore } from "../inbox-store.js";
|
|
20
|
+
let HOME;
|
|
21
|
+
let WORK;
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
HOME = mkdtempSync(join(tmpdir(), "coord-mig-home-"));
|
|
24
|
+
WORK = mkdtempSync(join(tmpdir(), "coord-mig-work-"));
|
|
25
|
+
process.env.CLAWNET_HOME = HOME;
|
|
26
|
+
});
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
rmSync(HOME, { recursive: true, force: true });
|
|
29
|
+
rmSync(WORK, { recursive: true, force: true });
|
|
30
|
+
delete process.env.CLAWNET_HOME;
|
|
31
|
+
});
|
|
32
|
+
describe("Task 6 — coordinator routes through InboxStore", () => {
|
|
33
|
+
it("handleUserMessage writes the user task into the queen's inbox file", async () => {
|
|
34
|
+
const sessionAdapter = {
|
|
35
|
+
createSession: vi.fn(async (o) => `proc-${o.sessionId}`),
|
|
36
|
+
sendInput: vi.fn(),
|
|
37
|
+
closeSession: vi.fn(async () => { }),
|
|
38
|
+
};
|
|
39
|
+
const hub = { send: vi.fn() };
|
|
40
|
+
const coordinator = new SwarmCoordinator(sessionAdapter, hub);
|
|
41
|
+
const swarmId = "sw-mig-1";
|
|
42
|
+
await coordinator.create(swarmId, {
|
|
43
|
+
workDir: WORK,
|
|
44
|
+
roles: [{ roleName: "queen", count: 1, eager: true }],
|
|
45
|
+
});
|
|
46
|
+
await coordinator.handleUserMessage(swarmId, "make me a sandwich");
|
|
47
|
+
// Allow the fire-and-forget deliver in handleUserMessage to settle.
|
|
48
|
+
await new Promise((r) => setTimeout(r, 30));
|
|
49
|
+
const store = new InboxStore(WORK, swarmId);
|
|
50
|
+
const all = await store.readAll("queen-0");
|
|
51
|
+
const userMsg = all.find((m) => m.from === "user" && m.data === "make me a sandwich");
|
|
52
|
+
expect(userMsg).toBeDefined();
|
|
53
|
+
expect(userMsg.type).toBe("task");
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
//# sourceMappingURL=coordinator-inbox-migration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordinator-inbox-migration.test.js","sourceRoot":"","sources":["../../src/__tests__/coordinator-inbox-migration.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox-integration.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/inbox-integration.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { mkdtempSync, rmSync, readFileSync, existsSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
// Mock logger
|
|
6
|
+
vi.mock("@mclawnet/logger", () => ({
|
|
7
|
+
createLogger: () => ({
|
|
8
|
+
info: vi.fn(),
|
|
9
|
+
warn: vi.fn(),
|
|
10
|
+
error: vi.fn(),
|
|
11
|
+
debug: vi.fn(),
|
|
12
|
+
}),
|
|
13
|
+
}));
|
|
14
|
+
// Mock persistence
|
|
15
|
+
vi.mock("../persistence.js", () => ({
|
|
16
|
+
saveSwarmSnapshot: vi.fn(),
|
|
17
|
+
deleteSwarmSnapshot: vi.fn(),
|
|
18
|
+
appendMessageLog: vi.fn(),
|
|
19
|
+
loadSwarmSnapshot: vi.fn(),
|
|
20
|
+
readMessageLog: vi.fn(() => []),
|
|
21
|
+
}));
|
|
22
|
+
vi.mock("../retrospective.js", () => ({
|
|
23
|
+
runRetrospective: vi.fn(async () => ({})),
|
|
24
|
+
}));
|
|
25
|
+
import { SwarmCoordinator, InboxStore, InboxRelay, } from "../index.js";
|
|
26
|
+
function createMockSessionAdapter() {
|
|
27
|
+
const inputs = [];
|
|
28
|
+
const adapter = {
|
|
29
|
+
_inputs: inputs,
|
|
30
|
+
createSession: vi.fn(async (options) => `proc-${options.sessionId}`),
|
|
31
|
+
sendInput: vi.fn((sessionId, input) => {
|
|
32
|
+
inputs.push({ sessionId, input });
|
|
33
|
+
}),
|
|
34
|
+
closeSession: vi.fn(async () => { }),
|
|
35
|
+
};
|
|
36
|
+
return adapter;
|
|
37
|
+
}
|
|
38
|
+
function createMockHubAdapter() {
|
|
39
|
+
const adapter = { send: vi.fn() };
|
|
40
|
+
return adapter;
|
|
41
|
+
}
|
|
42
|
+
const baseMsg = {
|
|
43
|
+
from: "queen",
|
|
44
|
+
type: "task",
|
|
45
|
+
data: "implement feature X",
|
|
46
|
+
timestamp: 1,
|
|
47
|
+
delivered: false,
|
|
48
|
+
};
|
|
49
|
+
let HOME;
|
|
50
|
+
let WORK;
|
|
51
|
+
beforeEach(() => {
|
|
52
|
+
HOME = mkdtempSync(join(tmpdir(), "swarm-inbox-int-"));
|
|
53
|
+
WORK = mkdtempSync(join(tmpdir(), "swarm-inbox-int-work-"));
|
|
54
|
+
process.env.CLAWNET_HOME = HOME;
|
|
55
|
+
});
|
|
56
|
+
afterEach(() => {
|
|
57
|
+
rmSync(HOME, { recursive: true, force: true });
|
|
58
|
+
rmSync(WORK, { recursive: true, force: true });
|
|
59
|
+
delete process.env.CLAWNET_HOME;
|
|
60
|
+
});
|
|
61
|
+
describe("Inbox end-to-end integration", () => {
|
|
62
|
+
it("re-exports InboxStore, InboxRelay, and InboxMessage type from package index", () => {
|
|
63
|
+
expect(typeof InboxStore).toBe("function");
|
|
64
|
+
expect(typeof InboxRelay).toBe("function");
|
|
65
|
+
// InboxMessage is a type-only export — verified at compile time.
|
|
66
|
+
const msg = { ...baseMsg, id: "x" };
|
|
67
|
+
expect(msg.id).toBe("x");
|
|
68
|
+
});
|
|
69
|
+
it("delivers inbox message via inboxRelay.deliver and marks it delivered after turn-complete", async () => {
|
|
70
|
+
const sessionAdapter = createMockSessionAdapter();
|
|
71
|
+
const hubAdapter = createMockHubAdapter();
|
|
72
|
+
const coordinator = new SwarmCoordinator(sessionAdapter, hubAdapter);
|
|
73
|
+
const swarmId = "sw-int-1";
|
|
74
|
+
// Spec: pre-populate the developer's inbox BEFORE create() is fine, but
|
|
75
|
+
// the spec also mentions "directly use coordinator.inboxRelay.deliver(...)".
|
|
76
|
+
// We do both: create the swarm, then append to dev-0's inbox, then call
|
|
77
|
+
// inboxRelay.deliver directly.
|
|
78
|
+
await coordinator.create(swarmId, {
|
|
79
|
+
workDir: WORK,
|
|
80
|
+
roles: [
|
|
81
|
+
{ roleName: "queen", count: 1, eager: true },
|
|
82
|
+
{ roleName: "developer", count: 1, eager: true },
|
|
83
|
+
],
|
|
84
|
+
task: "Outer task",
|
|
85
|
+
});
|
|
86
|
+
// Wait for spawn-time deliver passes to settle.
|
|
87
|
+
await new Promise((r) => setTimeout(r, 30));
|
|
88
|
+
// Append a fresh inbox message addressed to dev-0.
|
|
89
|
+
const store = new InboxStore(WORK, swarmId);
|
|
90
|
+
await store.append("dev-0", { ...baseMsg, id: "int-msg-1", data: "do the thing" });
|
|
91
|
+
// Directly trigger delivery via the public relay.
|
|
92
|
+
expect(coordinator.inboxRelay).toBeInstanceOf(InboxRelay);
|
|
93
|
+
await coordinator.inboxRelay.deliver(swarmId, "dev-0");
|
|
94
|
+
// sendInput should have been called with the wrapped envelope to dev-0.
|
|
95
|
+
const devInputs = sessionAdapter._inputs.filter((i) => i.sessionId === `${swarmId}::dev-0` && i.input.includes("<info_for_agent>"));
|
|
96
|
+
expect(devInputs.length).toBeGreaterThanOrEqual(1);
|
|
97
|
+
const lastDev = devInputs[devInputs.length - 1];
|
|
98
|
+
expect(lastDev.input).toEqual(expect.stringContaining("<info_for_agent>"));
|
|
99
|
+
expect(lastDev.input).toEqual(expect.stringMatching(/<message [^>]*id="int-msg-1"/));
|
|
100
|
+
expect(lastDev.input).toContain("do the thing");
|
|
101
|
+
// The message is still pendingEcho — not yet marked delivered.
|
|
102
|
+
let all = await store.readAll("dev-0");
|
|
103
|
+
let m = all.find((x) => x.id === "int-msg-1");
|
|
104
|
+
expect(m.delivered).toBe(false);
|
|
105
|
+
// Trigger turn-complete, which should call onAgentTurnSettled and mark delivered.
|
|
106
|
+
const handled = coordinator.handleRoleTurnComplete(`${swarmId}::dev-0`, {});
|
|
107
|
+
expect(handled).toBe(true);
|
|
108
|
+
// Wait for the async markDelivered.
|
|
109
|
+
await new Promise((r) => setTimeout(r, 80));
|
|
110
|
+
// Read the inbox file directly and assert delivered flag + deliveredAt.
|
|
111
|
+
const inboxFile = store.inboxFile("dev-0");
|
|
112
|
+
expect(existsSync(inboxFile)).toBe(true);
|
|
113
|
+
const raw = JSON.parse(readFileSync(inboxFile, "utf-8"));
|
|
114
|
+
const persisted = raw.find((x) => x.id === "int-msg-1");
|
|
115
|
+
expect(persisted.delivered).toBe(true);
|
|
116
|
+
expect(typeof persisted.deliveredAt).toBe("number");
|
|
117
|
+
expect(persisted.deliveredAt).toBeGreaterThan(0);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
//# sourceMappingURL=inbox-integration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox-integration.test.js","sourceRoot":"","sources":["../../src/__tests__/inbox-integration.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox-persistence-recovery.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/inbox-persistence-recovery.test.ts"],"names":[],"mappings":""}
|