@mclawnet/swarm 0.1.4 → 0.1.5
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__/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 +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -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/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
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { InboxStore } from "./inbox-store.js";
|
|
2
|
+
import { createLogger } from "@mclawnet/logger";
|
|
3
|
+
const log = createLogger({ module: "swarm/inbox-relay" });
|
|
4
|
+
/**
|
|
5
|
+
* Escape a string for safe inclusion as an XML/HTML attribute value
|
|
6
|
+
* (between double quotes). Order matters: `&` must be replaced first.
|
|
7
|
+
*/
|
|
8
|
+
function escapeXmlAttr(s) {
|
|
9
|
+
return s
|
|
10
|
+
.replace(/&/g, "&")
|
|
11
|
+
.replace(/</g, "<")
|
|
12
|
+
.replace(/>/g, ">")
|
|
13
|
+
.replace(/"/g, """);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Escape body text so embedded `</message>` / `</info_for_agent>` cannot
|
|
17
|
+
* close the wrapping envelope. Only `<` and `&` need escaping for that.
|
|
18
|
+
*/
|
|
19
|
+
function escapeXmlText(s) {
|
|
20
|
+
return s.replace(/&/g, "&").replace(/</g, "<");
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Wrap a batch of inbox messages into a single <info_for_agent> envelope.
|
|
24
|
+
* Host→agent direction; message body is free-form text per design §6.
|
|
25
|
+
*/
|
|
26
|
+
function wrapAgentBlock(msgs) {
|
|
27
|
+
const body = msgs
|
|
28
|
+
.map((m) => {
|
|
29
|
+
const taskAttr = m.taskId ? ` taskId="${escapeXmlAttr(m.taskId)}"` : "";
|
|
30
|
+
return `<message from="${escapeXmlAttr(m.from)}" type="${escapeXmlAttr(m.type)}"${taskAttr} id="${escapeXmlAttr(m.id)}">\n${escapeXmlText(m.data)}\n</message>`;
|
|
31
|
+
})
|
|
32
|
+
.join("\n");
|
|
33
|
+
return `\n<info_for_agent>\n${body}\n</info_for_agent>\n`;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* InboxRelay: pushes inbox messages to the target agent.
|
|
37
|
+
*
|
|
38
|
+
* Task 7: 4 gates implemented in runDeliver (liveness, lifecycle, single-flight,
|
|
39
|
+
* pending-echo). Single-flight gate sits in deliver(); the other three live
|
|
40
|
+
* inside runDeliver().
|
|
41
|
+
*
|
|
42
|
+
* Task 8 will fill in onAgentTurnSettled() to flush pendingEchoes and
|
|
43
|
+
* markDelivered() in the InboxStore.
|
|
44
|
+
*/
|
|
45
|
+
export class InboxRelay {
|
|
46
|
+
sessionAdapter;
|
|
47
|
+
getSwarm;
|
|
48
|
+
messageInterceptor;
|
|
49
|
+
home;
|
|
50
|
+
inFlight = new Map();
|
|
51
|
+
// key → set of messageIds already pushed but awaiting turn-settled ack.
|
|
52
|
+
pendingEchoes = new Map();
|
|
53
|
+
constructor(sessionAdapter, getSwarm, messageInterceptor,
|
|
54
|
+
// Optional override for the user-home root (no `.clawnet` suffix).
|
|
55
|
+
// Threaded down to InboxStore so tests pinned to a tmpdir don't fall
|
|
56
|
+
// through to `homedir()` and write inbox files into the real `~/.clawnet`.
|
|
57
|
+
home) {
|
|
58
|
+
this.sessionAdapter = sessionAdapter;
|
|
59
|
+
this.getSwarm = getSwarm;
|
|
60
|
+
this.messageInterceptor = messageInterceptor;
|
|
61
|
+
this.home = home;
|
|
62
|
+
}
|
|
63
|
+
key(swarmId, instanceId) {
|
|
64
|
+
return `${swarmId}::${instanceId}`;
|
|
65
|
+
}
|
|
66
|
+
async deliver(swarmId, instanceId) {
|
|
67
|
+
const k = this.key(swarmId, instanceId);
|
|
68
|
+
const cur = this.inFlight.get(k);
|
|
69
|
+
if (cur)
|
|
70
|
+
return cur;
|
|
71
|
+
const p = this.runDeliver(swarmId, instanceId).finally(() => {
|
|
72
|
+
this.inFlight.delete(k);
|
|
73
|
+
});
|
|
74
|
+
this.inFlight.set(k, p);
|
|
75
|
+
return p;
|
|
76
|
+
}
|
|
77
|
+
async runDeliver(swarmId, instanceId) {
|
|
78
|
+
// Gate 1: liveness — swarm and role must exist with a workDir.
|
|
79
|
+
const swarm = this.getSwarm(swarmId);
|
|
80
|
+
if (!swarm || !swarm.workDir)
|
|
81
|
+
return;
|
|
82
|
+
const role = swarm.roles.get(instanceId);
|
|
83
|
+
if (!role)
|
|
84
|
+
return;
|
|
85
|
+
// Gate 2: lifecycle — skip agents that are still spawning or already stopped.
|
|
86
|
+
if (role.status === "spawning" || role.status === "stopped")
|
|
87
|
+
return;
|
|
88
|
+
// Read undelivered inbox.
|
|
89
|
+
const store = new InboxStore(swarm.workDir, swarmId, this.home);
|
|
90
|
+
const undelivered = await store.readUndelivered(instanceId);
|
|
91
|
+
if (undelivered.length === 0)
|
|
92
|
+
return;
|
|
93
|
+
// Interceptor pass — give the coordinator a chance to consume system
|
|
94
|
+
// envelopes (plan_review_result etc.) before they reach the LLM. A
|
|
95
|
+
// consumed message is filtered out of the LLM payload AND marked
|
|
96
|
+
// delivered so it does not re-fire on subsequent passes. Throwing
|
|
97
|
+
// interceptors are demoted to no-ops (fail open: message still flows).
|
|
98
|
+
const consumedIds = [];
|
|
99
|
+
const survived = [];
|
|
100
|
+
for (const m of undelivered) {
|
|
101
|
+
let consumed = false;
|
|
102
|
+
if (this.messageInterceptor) {
|
|
103
|
+
try {
|
|
104
|
+
consumed = await this.messageInterceptor(swarmId, instanceId, m);
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
log.warn({ err, swarmId, instanceId, msgId: m.id, msgType: m.type }, "messageInterceptor threw — falling back to default delivery");
|
|
108
|
+
consumed = false;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (consumed)
|
|
112
|
+
consumedIds.push(m.id);
|
|
113
|
+
else
|
|
114
|
+
survived.push(m);
|
|
115
|
+
}
|
|
116
|
+
// Persist consumption so consumed messages don't re-fire next pass.
|
|
117
|
+
if (consumedIds.length > 0) {
|
|
118
|
+
try {
|
|
119
|
+
await store.markDelivered(instanceId, consumedIds);
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
log.warn({ err, swarmId, instanceId, count: consumedIds.length }, "markDelivered for consumed messages failed (best-effort)");
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (survived.length === 0)
|
|
126
|
+
return;
|
|
127
|
+
// Gate 3: pending-echo — drop messages already pushed but not yet ack'd.
|
|
128
|
+
const k = this.key(swarmId, instanceId);
|
|
129
|
+
const pending = this.pendingEchoes.get(k) ?? new Set();
|
|
130
|
+
const toPush = survived.filter((m) => !pending.has(m.id));
|
|
131
|
+
if (toPush.length === 0)
|
|
132
|
+
return;
|
|
133
|
+
// Push as a single <info_for_agent> envelope.
|
|
134
|
+
const payload = wrapAgentBlock(toPush);
|
|
135
|
+
this.sessionAdapter.sendInput(role.roleSessionId, payload);
|
|
136
|
+
for (const m of toPush)
|
|
137
|
+
pending.add(m.id);
|
|
138
|
+
this.pendingEchoes.set(k, pending);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Called when the host receives a `result` event signalling the agent
|
|
142
|
+
* finished a turn. Marks all messages currently in pendingEchoes as
|
|
143
|
+
* `delivered=true` in the InboxStore, clears the pending set, then triggers
|
|
144
|
+
* another deliver pass to flush any messages that arrived during the turn.
|
|
145
|
+
*
|
|
146
|
+
* Order: delete-before-mark — protects against (a) the next runDeliver
|
|
147
|
+
* stealing entries from pendingEchoes mid-flight, and (b) markDelivered
|
|
148
|
+
* throwing leaving stale ids in pendingEchoes (the inbox stays
|
|
149
|
+
* delivered=false so the next deliver re-pushes; markDelivered is idempotent).
|
|
150
|
+
*/
|
|
151
|
+
async onAgentTurnSettled(swarmId, instanceId) {
|
|
152
|
+
const k = this.key(swarmId, instanceId);
|
|
153
|
+
const pending = this.pendingEchoes.get(k);
|
|
154
|
+
if (!pending || pending.size === 0)
|
|
155
|
+
return;
|
|
156
|
+
const swarm = this.getSwarm(swarmId);
|
|
157
|
+
if (!swarm?.workDir) {
|
|
158
|
+
this.pendingEchoes.delete(k);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const ids = [...pending];
|
|
162
|
+
this.pendingEchoes.delete(k);
|
|
163
|
+
const store = new InboxStore(swarm.workDir, swarmId, this.home);
|
|
164
|
+
await store.markDelivered(instanceId, ids);
|
|
165
|
+
void this.deliver(swarmId, instanceId);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=inbox-relay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox-relay.js","sourceRoot":"","sources":["../src/inbox-relay.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface InboxMessage {
|
|
2
|
+
id: string;
|
|
3
|
+
from: string;
|
|
4
|
+
type: string;
|
|
5
|
+
data: string;
|
|
6
|
+
taskId?: string;
|
|
7
|
+
timestamp: number;
|
|
8
|
+
delivered: boolean;
|
|
9
|
+
deliveredAt?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare class InboxStore {
|
|
12
|
+
private workDir;
|
|
13
|
+
private swarmId;
|
|
14
|
+
private homeOverride?;
|
|
15
|
+
constructor(workDir: string, swarmId: string, homeOverride?: string | undefined);
|
|
16
|
+
private home;
|
|
17
|
+
private inboxesDir;
|
|
18
|
+
private validateInstanceId;
|
|
19
|
+
inboxFile(instanceId: string): string;
|
|
20
|
+
readAll(instanceId: string): Promise<InboxMessage[]>;
|
|
21
|
+
append(instanceId: string, msg: InboxMessage): Promise<void>;
|
|
22
|
+
readUndelivered(instanceId: string): Promise<InboxMessage[]>;
|
|
23
|
+
markDelivered(instanceId: string, ids: string[]): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=inbox-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox-store.d.ts","sourceRoot":"","sources":["../src/inbox-store.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,UAAU;IAQnB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,YAAY,CAAC;gBAFb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,MAAM,YAAA;IAG/B,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,kBAAkB;IAM1B,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAK/B,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAUpD,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAe5D,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAI5D,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAoBtE"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { readFileSync, existsSync, writeFileSync, mkdirSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { projectRoot } from "@mclawnet/task";
|
|
5
|
+
import lockfile from "proper-lockfile";
|
|
6
|
+
const LOCK_OPTS = {
|
|
7
|
+
realpath: false,
|
|
8
|
+
retries: { retries: 50, minTimeout: 20, maxTimeout: 200 },
|
|
9
|
+
};
|
|
10
|
+
export class InboxStore {
|
|
11
|
+
workDir;
|
|
12
|
+
swarmId;
|
|
13
|
+
homeOverride;
|
|
14
|
+
// `home` is the user-home root (no `.clawnet` suffix). projectRoot() adds
|
|
15
|
+
// `.clawnet/projects/...` itself. When omitted we honour CLAWNET_HOME first,
|
|
16
|
+
// then fall back to the OS home — matches TaskStore for symmetry. Callers
|
|
17
|
+
// that already plumb a `rootDir` through ToolContext should pass it here so
|
|
18
|
+
// their writes land inside the test harness's tempdir instead of the real
|
|
19
|
+
// `~/.clawnet/projects/...`.
|
|
20
|
+
constructor(workDir, swarmId, homeOverride) {
|
|
21
|
+
this.workDir = workDir;
|
|
22
|
+
this.swarmId = swarmId;
|
|
23
|
+
this.homeOverride = homeOverride;
|
|
24
|
+
}
|
|
25
|
+
home() {
|
|
26
|
+
return this.homeOverride ?? process.env.CLAWNET_HOME ?? homedir();
|
|
27
|
+
}
|
|
28
|
+
inboxesDir() {
|
|
29
|
+
return join(projectRoot(this.workDir, this.home()), "swarms", this.swarmId, "inboxes");
|
|
30
|
+
}
|
|
31
|
+
validateInstanceId(id) {
|
|
32
|
+
if (!id || /[\\/]|\.\./.test(id) || id.includes("\0")) {
|
|
33
|
+
throw new Error(`InboxStore: invalid instanceId: ${JSON.stringify(id)}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
inboxFile(instanceId) {
|
|
37
|
+
this.validateInstanceId(instanceId);
|
|
38
|
+
return join(this.inboxesDir(), `${instanceId}.json`);
|
|
39
|
+
}
|
|
40
|
+
async readAll(instanceId) {
|
|
41
|
+
const fp = this.inboxFile(instanceId);
|
|
42
|
+
if (!existsSync(fp))
|
|
43
|
+
return [];
|
|
44
|
+
try {
|
|
45
|
+
return JSON.parse(readFileSync(fp, "utf-8"));
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async append(instanceId, msg) {
|
|
52
|
+
mkdirSync(this.inboxesDir(), { recursive: true });
|
|
53
|
+
const fp = this.inboxFile(instanceId);
|
|
54
|
+
if (!existsSync(fp))
|
|
55
|
+
writeFileSync(fp, "[]");
|
|
56
|
+
const release = await lockfile.lock(fp, LOCK_OPTS);
|
|
57
|
+
try {
|
|
58
|
+
const cur = JSON.parse(readFileSync(fp, "utf-8"));
|
|
59
|
+
if (cur.some(m => m.id === msg.id))
|
|
60
|
+
return;
|
|
61
|
+
cur.push(msg);
|
|
62
|
+
writeFileSync(fp, JSON.stringify(cur, null, 2));
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
await release();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async readUndelivered(instanceId) {
|
|
69
|
+
return (await this.readAll(instanceId)).filter(m => !m.delivered);
|
|
70
|
+
}
|
|
71
|
+
async markDelivered(instanceId, ids) {
|
|
72
|
+
if (ids.length === 0)
|
|
73
|
+
return;
|
|
74
|
+
const fp = this.inboxFile(instanceId);
|
|
75
|
+
if (!existsSync(fp))
|
|
76
|
+
return;
|
|
77
|
+
const release = await lockfile.lock(fp, LOCK_OPTS);
|
|
78
|
+
try {
|
|
79
|
+
const cur = JSON.parse(readFileSync(fp, "utf-8"));
|
|
80
|
+
const set = new Set(ids);
|
|
81
|
+
const now = Date.now();
|
|
82
|
+
for (const m of cur) {
|
|
83
|
+
if (set.has(m.id) && !m.delivered) {
|
|
84
|
+
m.delivered = true;
|
|
85
|
+
m.deliveredAt = now;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
writeFileSync(fp, JSON.stringify(cur, null, 2));
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
await release();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=inbox-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox-store.js","sourceRoot":"","sources":["../src/inbox-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface InboxRelayLike {
|
|
2
|
+
deliver(swarmId: string, instanceId: string): Promise<void> | void;
|
|
3
|
+
}
|
|
4
|
+
export declare class InboxWatcher {
|
|
5
|
+
private relay;
|
|
6
|
+
private swarms;
|
|
7
|
+
constructor(relay: InboxRelayLike);
|
|
8
|
+
watch(swarmId: string, workDir: string): void;
|
|
9
|
+
unwatch(swarmId: string): void;
|
|
10
|
+
close(): void;
|
|
11
|
+
private schedule;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=inbox-watcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox-watcher.d.ts","sourceRoot":"","sources":["../src/inbox-watcher.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACpE;AAiBD,qBAAa,YAAY;IAGX,OAAO,CAAC,KAAK;IAFzB,OAAO,CAAC,MAAM,CAAiC;gBAE3B,KAAK,EAAE,cAAc;IAEzC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IA6B7C,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAS9B,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,QAAQ;CAWjB"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { mkdirSync, watch } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { createLogger } from "@mclawnet/logger";
|
|
5
|
+
import { projectRoot as taskProjectRoot } from "@mclawnet/task";
|
|
6
|
+
const log = createLogger({ module: "swarm/inbox-watcher" });
|
|
7
|
+
const DEBOUNCE_MS = 50;
|
|
8
|
+
const VALID_ID_RE = /^[A-Za-z0-9_.-]+$/;
|
|
9
|
+
// Use the canonical layout from @mclawnet/task so the watcher observes the
|
|
10
|
+
// same directory the InboxStore writes into. Previously this used a local
|
|
11
|
+
// `join(home, "projects", ...)` (missing `.clawnet`), which silently created
|
|
12
|
+
// phantom dirs at ~/projects/... while real inboxes lived at ~/.clawnet/...,
|
|
13
|
+
// so fs.watch never fired and task_assigned messages stayed delivered:false.
|
|
14
|
+
function projectRoot(workDir) {
|
|
15
|
+
const home = process.env.CLAWNET_HOME ?? homedir();
|
|
16
|
+
return taskProjectRoot(workDir, home);
|
|
17
|
+
}
|
|
18
|
+
export class InboxWatcher {
|
|
19
|
+
relay;
|
|
20
|
+
swarms = new Map();
|
|
21
|
+
constructor(relay) {
|
|
22
|
+
this.relay = relay;
|
|
23
|
+
}
|
|
24
|
+
watch(swarmId, workDir) {
|
|
25
|
+
if (this.swarms.has(swarmId))
|
|
26
|
+
return;
|
|
27
|
+
const dir = join(projectRoot(workDir), "swarms", swarmId, "inboxes");
|
|
28
|
+
try {
|
|
29
|
+
mkdirSync(dir, { recursive: true });
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
log.warn({ err, swarmId, dir }, "inbox-watcher: mkdir failed");
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
let fsw;
|
|
36
|
+
try {
|
|
37
|
+
fsw = watch(dir, { persistent: false }, (_evt, filename) => {
|
|
38
|
+
if (!filename)
|
|
39
|
+
return;
|
|
40
|
+
const name = String(filename);
|
|
41
|
+
if (!name.endsWith(".json"))
|
|
42
|
+
return;
|
|
43
|
+
const id = name.slice(0, -".json".length);
|
|
44
|
+
if (!VALID_ID_RE.test(id))
|
|
45
|
+
return;
|
|
46
|
+
this.schedule(swarmId, id);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
log.warn({ err, swarmId, dir }, "inbox-watcher: fs.watch failed");
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
fsw.on("error", (err) => {
|
|
54
|
+
log.warn({ err, swarmId }, "inbox-watcher: fs.watch error");
|
|
55
|
+
});
|
|
56
|
+
this.swarms.set(swarmId, { watcher: fsw, timers: new Map() });
|
|
57
|
+
}
|
|
58
|
+
unwatch(swarmId) {
|
|
59
|
+
const entry = this.swarms.get(swarmId);
|
|
60
|
+
if (!entry)
|
|
61
|
+
return;
|
|
62
|
+
for (const t of entry.timers.values())
|
|
63
|
+
clearTimeout(t);
|
|
64
|
+
entry.timers.clear();
|
|
65
|
+
try {
|
|
66
|
+
entry.watcher.close();
|
|
67
|
+
}
|
|
68
|
+
catch { /* ignore */ }
|
|
69
|
+
this.swarms.delete(swarmId);
|
|
70
|
+
}
|
|
71
|
+
close() {
|
|
72
|
+
for (const swarmId of [...this.swarms.keys()])
|
|
73
|
+
this.unwatch(swarmId);
|
|
74
|
+
}
|
|
75
|
+
schedule(swarmId, instanceId) {
|
|
76
|
+
const entry = this.swarms.get(swarmId);
|
|
77
|
+
if (!entry)
|
|
78
|
+
return;
|
|
79
|
+
const existing = entry.timers.get(instanceId);
|
|
80
|
+
if (existing)
|
|
81
|
+
clearTimeout(existing);
|
|
82
|
+
const timer = setTimeout(() => {
|
|
83
|
+
entry.timers.delete(instanceId);
|
|
84
|
+
Promise.resolve(this.relay.deliver(swarmId, instanceId)).catch(() => { });
|
|
85
|
+
}, DEBOUNCE_MS);
|
|
86
|
+
entry.timers.set(instanceId, timer);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=inbox-watcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox-watcher.js","sourceRoot":"","sources":["../src/inbox-watcher.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
export { SwarmCoordinator } from "./swarm-coordinator.js";
|
|
2
|
-
export { LocalMessageRouter } from "./message-router.js";
|
|
3
|
-
export type { MessageRouter } from "./message-router.js";
|
|
4
|
-
export { parseSwarmActions } from "./action-parser.js";
|
|
5
2
|
export { initRoles, loadRole, listRoles, buildRolePrompt, parseRoleFile } from "./roles/role-loader.js";
|
|
6
3
|
export { saveSwarmSnapshot, loadSwarmSnapshot, deleteSwarmSnapshot, appendMessageLog, readMessageLog, listRecoverableSwarmIds, } from "./persistence.js";
|
|
7
4
|
export type { SwarmSnapshot } from "./persistence.js";
|
|
8
5
|
export { runRetrospective } from "./retrospective.js";
|
|
9
6
|
export type { RetrospectiveResult, RoleEvaluation } from "./retrospective.js";
|
|
10
7
|
export { listRecoverableSwarms, recoverSwarm } from "./recovery.js";
|
|
8
|
+
export { InboxStore } from "./inbox-store.js";
|
|
9
|
+
export type { InboxMessage } from "./inbox-store.js";
|
|
10
|
+
export { InboxRelay } from "./inbox-relay.js";
|
|
11
|
+
export { InboxWatcher, type InboxRelayLike as InboxWatcherRelayLike } from "./inbox-watcher.js";
|
|
11
12
|
export type { SessionAdapter, HubAdapter, SwarmInstance, RoleInstance, SwarmAction, SwarmMessage, SwarmCreateOptions, RouteEndpoint, SwarmStatus, PlanStatus, } from "./types.js";
|
|
12
13
|
export type { RoleDefinition, DelegationMap, DelegationEntry } from "./roles/types.js";
|
|
13
14
|
export { initTemplates, listTemplates, loadTemplate } from "./templates/template-loader.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACxG,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,uBAAuB,GACxB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,KAAK,cAAc,IAAI,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEhG,YAAY,EACV,cAAc,EACd,UAAU,EACV,aAAa,EACb,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACb,WAAW,EACX,UAAU,GACX,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEvF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC5F,YAAY,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
// @mclawnet/swarm — Swarm coordination, message routing, and role management
|
|
2
2
|
export { SwarmCoordinator } from "./swarm-coordinator.js";
|
|
3
|
-
export { LocalMessageRouter } from "./message-router.js";
|
|
4
|
-
export { parseSwarmActions } from "./action-parser.js";
|
|
5
3
|
export { initRoles, loadRole, listRoles, buildRolePrompt, parseRoleFile } from "./roles/role-loader.js";
|
|
6
4
|
export { saveSwarmSnapshot, loadSwarmSnapshot, deleteSwarmSnapshot, appendMessageLog, readMessageLog, listRecoverableSwarmIds, } from "./persistence.js";
|
|
7
5
|
export { runRetrospective } from "./retrospective.js";
|
|
8
6
|
export { listRecoverableSwarms, recoverSwarm } from "./recovery.js";
|
|
7
|
+
export { InboxStore } from "./inbox-store.js";
|
|
8
|
+
export { InboxRelay } from "./inbox-relay.js";
|
|
9
|
+
export { InboxWatcher } from "./inbox-watcher.js";
|
|
9
10
|
export { initTemplates, listTemplates, loadTemplate } from "./templates/template-loader.js";
|
|
10
11
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAE7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAE7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACxG,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,uBAAuB,GACxB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAgD,MAAM,oBAAoB,CAAC;AAiBhG,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC"}
|
package/dist/persistence.d.ts
CHANGED
|
@@ -3,22 +3,36 @@ export interface SwarmSnapshot {
|
|
|
3
3
|
id: string;
|
|
4
4
|
hubSessionId: string;
|
|
5
5
|
workDir?: string;
|
|
6
|
+
teamName: string;
|
|
6
7
|
roles: Array<{
|
|
7
8
|
instanceId: string;
|
|
8
9
|
roleName: string;
|
|
9
10
|
status: string;
|
|
10
11
|
currentTask?: string;
|
|
12
|
+
claudeSessionId?: string;
|
|
13
|
+
type?: "queen" | "worker";
|
|
11
14
|
}>;
|
|
12
15
|
plan: unknown;
|
|
13
16
|
nextInstanceSeq: Record<string, number>;
|
|
14
17
|
savedAt: number;
|
|
15
18
|
status?: SwarmStatus;
|
|
16
19
|
planStatus?: PlanStatus;
|
|
20
|
+
partialRecover?: boolean;
|
|
17
21
|
}
|
|
18
22
|
export declare function saveSwarmSnapshot(swarm: SwarmInstance): void;
|
|
19
|
-
export declare function loadSwarmSnapshot(swarmId: string): SwarmSnapshot | null;
|
|
20
|
-
export declare function deleteSwarmSnapshot(swarmId: string): void;
|
|
21
|
-
export declare function readMessageLog(swarmId: string): object[];
|
|
22
|
-
export declare function appendMessageLog(swarmId: string, entry: object): void;
|
|
23
|
-
|
|
23
|
+
export declare function loadSwarmSnapshot(workDir: string, swarmId: string): SwarmSnapshot | null;
|
|
24
|
+
export declare function deleteSwarmSnapshot(workDir: string, swarmId: string): void;
|
|
25
|
+
export declare function readMessageLog(workDir: string, swarmId: string): object[];
|
|
26
|
+
export declare function appendMessageLog(workDir: string, swarmId: string, entry: object): void;
|
|
27
|
+
/**
|
|
28
|
+
* List recoverable swarms across all per-project roots. The authoritative
|
|
29
|
+
* `workDir` is read from each snapshot's `workDir` field (snapshots written
|
|
30
|
+
* since 0.1.6 always include it). Falling back on the encoded directory
|
|
31
|
+
* name is lossy for paths whose segments contain `-`, so we deliberately
|
|
32
|
+
* skip entries whose snapshot can't be parsed or doesn't carry `workDir`.
|
|
33
|
+
*/
|
|
34
|
+
export declare function listRecoverableSwarmIds(): Array<{
|
|
35
|
+
workDir: string;
|
|
36
|
+
swarmId: string;
|
|
37
|
+
}>;
|
|
24
38
|
//# sourceMappingURL=persistence.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../src/persistence.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../src/persistence.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAgBzE,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;QACX,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;KAC3B,CAAC,CAAC;IACH,IAAI,EAAE,OAAO,CAAC;IACd,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CA2C5D;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAgBxF;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAK1E;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAkBzE;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAItF;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,IAAI,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAyCrF"}
|