@chorus-aidlc/chorus-openclaw-plugin 0.5.3 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/connection-state.d.ts +35 -0
  2. package/dist/connection-state.d.ts.map +1 -0
  3. package/dist/connection-state.js +52 -0
  4. package/dist/connection-state.js.map +1 -0
  5. package/dist/control-handler.d.ts +73 -0
  6. package/dist/control-handler.d.ts.map +1 -0
  7. package/dist/control-handler.js +135 -0
  8. package/dist/control-handler.js.map +1 -0
  9. package/dist/daemon-client.d.ts +203 -0
  10. package/dist/daemon-client.d.ts.map +1 -0
  11. package/dist/daemon-client.js +469 -0
  12. package/dist/daemon-client.js.map +1 -0
  13. package/dist/daemon-rest-client.d.ts +86 -0
  14. package/dist/daemon-rest-client.d.ts.map +1 -0
  15. package/dist/daemon-rest-client.js +196 -0
  16. package/dist/daemon-rest-client.js.map +1 -0
  17. package/dist/event-router.d.ts +31 -6
  18. package/dist/event-router.d.ts.map +1 -1
  19. package/dist/event-router.js +58 -27
  20. package/dist/event-router.js.map +1 -1
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +106 -7
  23. package/dist/index.js.map +1 -1
  24. package/dist/lineage.d.ts +44 -0
  25. package/dist/lineage.d.ts.map +1 -0
  26. package/dist/lineage.js +116 -0
  27. package/dist/lineage.js.map +1 -0
  28. package/dist/mcp-registration.d.ts.map +1 -1
  29. package/dist/mcp-registration.js +5 -4
  30. package/dist/mcp-registration.js.map +1 -1
  31. package/dist/sse-listener.d.ts +34 -0
  32. package/dist/sse-listener.d.ts.map +1 -1
  33. package/dist/sse-listener.js +78 -4
  34. package/dist/sse-listener.js.map +1 -1
  35. package/dist/wake.d.ts +20 -0
  36. package/dist/wake.d.ts.map +1 -1
  37. package/dist/wake.js +56 -0
  38. package/dist/wake.js.map +1 -1
  39. package/package.json +1 -1
  40. package/skills/brainstorm/SKILL.md +1 -1
  41. package/skills/chorus/SKILL.md +37 -6
  42. package/skills/develop/SKILL.md +1 -1
  43. package/skills/idea/SKILL.md +18 -3
  44. package/skills/openspec-aware/SKILL.md +1 -1
  45. package/skills/proposal/SKILL.md +1 -1
  46. package/skills/proposal-reviewer/SKILL.md +1 -1
  47. package/skills/quick-dev/SKILL.md +1 -1
  48. package/skills/review/SKILL.md +1 -1
  49. package/skills/task-reviewer/SKILL.md +1 -1
  50. package/skills/yolo/SKILL.md +1 -1
  51. package/src/connection-state.ts +66 -0
  52. package/src/control-handler.ts +219 -0
  53. package/src/daemon-client.ts +622 -0
  54. package/src/daemon-rest-client.ts +312 -0
  55. package/src/event-router.ts +103 -33
  56. package/src/index.ts +113 -8
  57. package/src/lineage.ts +157 -0
  58. package/src/mcp-registration.ts +6 -19
  59. package/src/openclaw-sdk.d.ts +232 -1
  60. package/src/sse-listener.ts +117 -5
  61. package/src/wake.ts +69 -26
@@ -0,0 +1,196 @@
1
+ // packages/openclaw-plugin/src/daemon-rest-client.ts
2
+ // TypeScript mirror of the shared, host-agnostic pure-REST client for the Chorus
3
+ // daemon → server reporting surface (`/api/daemon/*`).
4
+ //
5
+ // WHY A MIRROR (not an import): the single-source-of-truth implementation is
6
+ // `cli/daemon-rest-client.mjs`, consumed verbatim by the chorus CLI daemon. The
7
+ // OpenClaw plugin, however, is a SEPARATELY-PUBLISHED npm package
8
+ // (`@chorus-aidlc/chorus-openclaw-plugin`, `files: ["src", "dist", ...]`) whose
9
+ // TS build has `rootDir: "src"`. Importing a file under `cli/` (outside both the
10
+ // package boundary AND rootDir) is rejected by `tsc` and would not be present in
11
+ // the published tarball. So we mirror the EXACT same factory + payload shapes here
12
+ // — this is NOT a fork of the wire contract: every payload below is byte-for-byte
13
+ // the shape `cli/daemon-rest-client.mjs` sends (and the server already accepts).
14
+ // The two files are kept in lock-step by the spec's "single source of truth for
15
+ // the payload shapes" requirement; a drift would be caught by T5 (live e2e).
16
+ //
17
+ // The five operations and their EXACT server payload shapes (verified against
18
+ // cli/daemon-rest-client.mjs + src/app/api/daemon/*/route.ts — server unchanged):
19
+ // turnAdvance → POST /api/daemon/turn-advance
20
+ // { connectionUuid, sessionId, status, entityType?, entityUuid? }
21
+ // transcript → POST /api/daemon/transcript
22
+ // { sessionId, messages: [{ role, text }] }
23
+ // executionState → POST /api/daemon/execution-state
24
+ // { connectionUuid, executions: [{ entityType, entityUuid,
25
+ // rootIdeaUuid|null, status,
26
+ // startedAt|null }] }
27
+ // reportInterrupt → POST /api/daemon/report-interrupt
28
+ // { connectionUuid, entityType, entityUuid, reason }
29
+ // readPendingTurns → GET /api/daemon/pending-turns?connectionUuid=…
30
+ // → { turns: [{ turnUuid, sessionId, directIdeaUuid, trigger,
31
+ // promptText }] }
32
+ //
33
+ // HARD CONSTRAINTS (identical to the CLI client):
34
+ // • ZERO daemon-host coupling — no child_process, no OpenClaw SDK import. Its only
35
+ // outbound effect is HTTP via the injected `fetchImpl` (global fetch on Node 18+).
36
+ // Adds NO new npm dependency (CLAUDE.md pitfall #9).
37
+ // • Bearer-only auth: every request carries `Authorization: Bearer <apiKey>`.
38
+ // • NO SILENT ERRORS (project policy): a network error, a non-2xx response, or a
39
+ // bad/empty body is LOGGED WITH ITS CAUSE and SURFACED via a structured result —
40
+ // never swallowed into a silent success.
41
+ // • A failed report NEVER rejects: every method RESOLVES with `{ ok: false, ... }`
42
+ // so a fire-and-forget caller can `await` it safely.
43
+ const NOOP_LOGGER = { info() { }, warn() { }, error() { } };
44
+ /**
45
+ * Build the shared daemon REST client. Inputs are entirely host-agnostic, which is
46
+ * exactly why the same surface serves both daemon hosts.
47
+ */
48
+ export function createDaemonRestClient(opts) {
49
+ const url = opts.url.replace(/\/$/, "");
50
+ const apiKey = opts.apiKey;
51
+ const getConnectionUuid = opts.getConnectionUuid ?? (() => null);
52
+ const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
53
+ const logger = opts.logger ?? NOOP_LOGGER;
54
+ const jsonHeaders = {
55
+ Authorization: `Bearer ${apiKey}`,
56
+ "Content-Type": "application/json",
57
+ Accept: "application/json",
58
+ };
59
+ /**
60
+ * Issue one daemon report. Owns the transport + the no-silent-errors contract
61
+ * IDENTICAL across all four POST endpoints; only the `op` label and the path
62
+ * differ. Never throws — returns a structured {@link DaemonRestResult}.
63
+ */
64
+ async function post(op, path, body, successLog, context = "") {
65
+ let response;
66
+ try {
67
+ response = await fetchImpl(`${url}${path}`, {
68
+ method: "POST",
69
+ headers: jsonHeaders,
70
+ body: JSON.stringify(body),
71
+ });
72
+ }
73
+ catch (err) {
74
+ // Network-level failure (DNS, connection refused, abort, …). Surface WITH cause.
75
+ const error = `${op} request failed${context}: ${err}`;
76
+ logger.warn(`[Chorus] ${error}`);
77
+ return { ok: false, status: null, error };
78
+ }
79
+ if (!response.ok) {
80
+ // Non-2xx. Surface WITH the status so a 4xx/5xx is debuggable.
81
+ const error = `${op} returned ${response.status}${context}`;
82
+ logger.warn(`[Chorus] ${error}`);
83
+ return { ok: false, status: response.status, error };
84
+ }
85
+ if (successLog)
86
+ logger.info(`[Chorus] ${successLog}`);
87
+ return { ok: true, status: response.status };
88
+ }
89
+ return {
90
+ /**
91
+ * POST /api/daemon/turn-advance — advance a wake's DaemonSessionTurn lifecycle.
92
+ * The server resolves the turn by the session BUSINESS KEY (`sessionId`); the
93
+ * optional `entityType`/`entityUuid` stamp the weak executionUuid link. Requires
94
+ * the connectionUuid.
95
+ */
96
+ async turnAdvance({ sessionId, status, entityType, entityUuid }) {
97
+ const connectionUuid = getConnectionUuid();
98
+ if (!connectionUuid) {
99
+ const error = `cannot advance turn for session ${sessionId} → ${status} — no connection uuid yet`;
100
+ logger.warn(`[Chorus] ${error}`);
101
+ return { ok: false, status: null, error, skipped: true };
102
+ }
103
+ const body = {
104
+ connectionUuid,
105
+ sessionId,
106
+ status,
107
+ // Only sent when BOTH are present, so the server never gets a partial linkage.
108
+ ...(entityType && entityUuid ? { entityType, entityUuid } : {}),
109
+ };
110
+ return post("turn-advance", "/api/daemon/turn-advance", body, `advanced turn for session ${sessionId} → ${status}`);
111
+ },
112
+ /**
113
+ * POST /api/daemon/transcript — append finalized user/assistant text to the
114
+ * current turn, targeted by the session BUSINESS KEY. The caller owns the content
115
+ * filter (only `{ role, text }`) and any batching. No connectionUuid needed.
116
+ */
117
+ async transcript({ sessionId, messages }) {
118
+ return post("transcript upload", "/api/daemon/transcript", { sessionId, messages }, `transcript uploaded (${messages.length} msg) for session ${sessionId}`);
119
+ },
120
+ /**
121
+ * POST /api/daemon/execution-state — publish the connection's running/queued
122
+ * execution snapshot (caller supplies the already-built `executions` array).
123
+ * Requires the connectionUuid; a null uuid is a normal early state (silent skip).
124
+ */
125
+ async executionState({ executions }) {
126
+ const connectionUuid = getConnectionUuid();
127
+ if (!connectionUuid) {
128
+ return { ok: false, status: null, skipped: true };
129
+ }
130
+ return post("execution-state upload", "/api/daemon/execution-state", { connectionUuid, executions }, `execution-state uploaded (${executions.length} active)`);
131
+ },
132
+ /**
133
+ * POST /api/daemon/report-interrupt — record a wake's `interrupted` outcome
134
+ * (reason = "user" | "crash") on the execution row keyed by connection + entity.
135
+ */
136
+ async reportInterrupt({ entityType, entityUuid, reason }) {
137
+ const connectionUuid = getConnectionUuid();
138
+ if (!connectionUuid) {
139
+ const error = `cannot report interrupt for ${entityType}:${entityUuid} — no connection uuid yet`;
140
+ logger.warn(`[Chorus] ${error}`);
141
+ return { ok: false, status: null, error, skipped: true };
142
+ }
143
+ return post("report-interrupt", "/api/daemon/report-interrupt", { connectionUuid, entityType, entityUuid, reason }, `reported ${entityType}:${entityUuid} interrupted (reason=${reason})`, ` for ${entityType}:${entityUuid}`);
144
+ },
145
+ /**
146
+ * GET /api/daemon/pending-turns?connectionUuid=… — read this connection's
147
+ * unstarted (pending) turns. Returns the parsed `{ turns: [...] }` data on
148
+ * success; a network error / non-2xx / bad body / missing array is logged with
149
+ * cause and surfaced as a failure result — never a silent empty success.
150
+ */
151
+ async readPendingTurns() {
152
+ const connectionUuid = getConnectionUuid();
153
+ if (!connectionUuid) {
154
+ return { ok: false, status: null, skipped: true };
155
+ }
156
+ const endpoint = `${url}/api/daemon/pending-turns?connectionUuid=${encodeURIComponent(connectionUuid)}`;
157
+ let response;
158
+ try {
159
+ response = await fetchImpl(endpoint, {
160
+ headers: { Authorization: `Bearer ${apiKey}`, Accept: "application/json" },
161
+ });
162
+ }
163
+ catch (err) {
164
+ const error = `pending-turns backfill request failed: ${err}`;
165
+ logger.warn(`[Chorus] ${error}`);
166
+ return { ok: false, status: null, error };
167
+ }
168
+ if (!response.ok) {
169
+ const error = `pending-turns backfill returned ${response.status}`;
170
+ logger.warn(`[Chorus] ${error}`);
171
+ return { ok: false, status: response.status, error };
172
+ }
173
+ let parsed;
174
+ try {
175
+ parsed = await response.json();
176
+ }
177
+ catch (err) {
178
+ const error = `pending-turns backfill: bad JSON: ${err}`;
179
+ logger.warn(`[Chorus] ${error}`);
180
+ return { ok: false, status: response.status, error };
181
+ }
182
+ // API envelope: { success: true, data: { turns: [...] } }.
183
+ const data = parsed && typeof parsed === "object"
184
+ ? parsed.data
185
+ : undefined;
186
+ const turns = data && typeof data === "object" ? data.turns : undefined;
187
+ if (!Array.isArray(turns)) {
188
+ const error = "pending-turns backfill: no turns array in response";
189
+ logger.warn(`[Chorus] ${error}`);
190
+ return { ok: false, status: response.status, error };
191
+ }
192
+ return { ok: true, status: response.status, data: { turns: turns } };
193
+ },
194
+ };
195
+ }
196
+ //# sourceMappingURL=daemon-rest-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-rest-client.js","sourceRoot":"","sources":["../src/daemon-rest-client.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,iFAAiF;AACjF,uDAAuD;AACvD,EAAE;AACF,6EAA6E;AAC7E,gFAAgF;AAChF,kEAAkE;AAClE,gFAAgF;AAChF,iFAAiF;AACjF,iFAAiF;AACjF,mFAAmF;AACnF,kFAAkF;AAClF,iFAAiF;AACjF,gFAAgF;AAChF,6EAA6E;AAC7E,EAAE;AACF,8EAA8E;AAC9E,kFAAkF;AAClF,qDAAqD;AACrD,uFAAuF;AACvF,mDAAmD;AACnD,iEAAiE;AACjE,wDAAwD;AACxD,gFAAgF;AAChF,mFAAmF;AACnF,4EAA4E;AAC5E,yDAAyD;AACzD,0EAA0E;AAC1E,uEAAuE;AACvE,mFAAmF;AACnF,qDAAqD;AACrD,EAAE;AACF,kDAAkD;AAClD,qFAAqF;AACrF,uFAAuF;AACvF,yDAAyD;AACzD,gFAAgF;AAChF,mFAAmF;AACnF,qFAAqF;AACrF,6CAA6C;AAC7C,qFAAqF;AACrF,yDAAyD;AAQzD,MAAM,WAAW,GAAqB,EAAE,IAAI,KAAI,CAAC,EAAE,IAAI,KAAI,CAAC,EAAE,KAAK,KAAI,CAAC,EAAE,CAAC;AA+E3E;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAmC;IACxE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC3B,MAAM,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IACjE,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,UAAU,CAAC,KAAK,CAAC;IACrD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,WAAW,CAAC;IAE1C,MAAM,WAAW,GAAG;QAClB,aAAa,EAAE,UAAU,MAAM,EAAE;QACjC,cAAc,EAAE,kBAAkB;QAClC,MAAM,EAAE,kBAAkB;KAC3B,CAAC;IAEF;;;;OAIG;IACH,KAAK,UAAU,IAAI,CACjB,EAAU,EACV,IAAY,EACZ,IAAa,EACb,UAAmB,EACnB,OAAO,GAAG,EAAE;QAEZ,IAAI,QAAkB,CAAC;QACvB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,GAAG,GAAG,IAAI,EAAE,EAAE;gBAC1C,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,WAAW;gBACpB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aAC3B,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,iFAAiF;YACjF,MAAM,KAAK,GAAG,GAAG,EAAE,kBAAkB,OAAO,KAAK,GAAG,EAAE,CAAC;YACvD,MAAM,CAAC,IAAI,CAAC,YAAY,KAAK,EAAE,CAAC,CAAC;YACjC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QAC5C,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,+DAA+D;YAC/D,MAAM,KAAK,GAAG,GAAG,EAAE,aAAa,QAAQ,CAAC,MAAM,GAAG,OAAO,EAAE,CAAC;YAC5D,MAAM,CAAC,IAAI,CAAC,YAAY,KAAK,EAAE,CAAC,CAAC;YACjC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;QACvD,CAAC;QACD,IAAI,UAAU;YAAE,MAAM,CAAC,IAAI,CAAC,YAAY,UAAU,EAAE,CAAC,CAAC;QACtD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;IAC/C,CAAC;IAED,OAAO;QACL;;;;;WAKG;QACH,KAAK,CAAC,WAAW,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE;YAC7D,MAAM,cAAc,GAAG,iBAAiB,EAAE,CAAC;YAC3C,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,MAAM,KAAK,GAAG,mCAAmC,SAAS,MAAM,MAAM,2BAA2B,CAAC;gBAClG,MAAM,CAAC,IAAI,CAAC,YAAY,KAAK,EAAE,CAAC,CAAC;gBACjC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC3D,CAAC;YACD,MAAM,IAAI,GAAG;gBACX,cAAc;gBACd,SAAS;gBACT,MAAM;gBACN,+EAA+E;gBAC/E,GAAG,CAAC,UAAU,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAChE,CAAC;YACF,OAAO,IAAI,CACT,cAAc,EACd,0BAA0B,EAC1B,IAAI,EACJ,6BAA6B,SAAS,MAAM,MAAM,EAAE,CACrD,CAAC;QACJ,CAAC;QAED;;;;WAIG;QACH,KAAK,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE;YACtC,OAAO,IAAI,CACT,mBAAmB,EACnB,wBAAwB,EACxB,EAAE,SAAS,EAAE,QAAQ,EAAE,EACvB,wBAAwB,QAAQ,CAAC,MAAM,qBAAqB,SAAS,EAAE,CACxE,CAAC;QACJ,CAAC;QAED;;;;WAIG;QACH,KAAK,CAAC,cAAc,CAAC,EAAE,UAAU,EAAE;YACjC,MAAM,cAAc,GAAG,iBAAiB,EAAE,CAAC;YAC3C,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YACpD,CAAC;YACD,OAAO,IAAI,CACT,wBAAwB,EACxB,6BAA6B,EAC7B,EAAE,cAAc,EAAE,UAAU,EAAE,EAC9B,6BAA6B,UAAU,CAAC,MAAM,UAAU,CACzD,CAAC;QACJ,CAAC;QAED;;;WAGG;QACH,KAAK,CAAC,eAAe,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE;YACtD,MAAM,cAAc,GAAG,iBAAiB,EAAE,CAAC;YAC3C,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,MAAM,KAAK,GAAG,+BAA+B,UAAU,IAAI,UAAU,2BAA2B,CAAC;gBACjG,MAAM,CAAC,IAAI,CAAC,YAAY,KAAK,EAAE,CAAC,CAAC;gBACjC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC3D,CAAC;YACD,OAAO,IAAI,CACT,kBAAkB,EAClB,8BAA8B,EAC9B,EAAE,cAAc,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,EAClD,YAAY,UAAU,IAAI,UAAU,wBAAwB,MAAM,GAAG,EACrE,QAAQ,UAAU,IAAI,UAAU,EAAE,CACnC,CAAC;QACJ,CAAC;QAED;;;;;WAKG;QACH,KAAK,CAAC,gBAAgB;YACpB,MAAM,cAAc,GAAG,iBAAiB,EAAE,CAAC;YAC3C,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YACpD,CAAC;YACD,MAAM,QAAQ,GAAG,GAAG,GAAG,4CAA4C,kBAAkB,CAAC,cAAc,CAAC,EAAE,CAAC;YACxG,IAAI,QAAkB,CAAC;YACvB,IAAI,CAAC;gBACH,QAAQ,GAAG,MAAM,SAAS,CAAC,QAAQ,EAAE;oBACnC,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,MAAM,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;iBAC3E,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,KAAK,GAAG,0CAA0C,GAAG,EAAE,CAAC;gBAC9D,MAAM,CAAC,IAAI,CAAC,YAAY,KAAK,EAAE,CAAC,CAAC;gBACjC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;YAC5C,CAAC;YACD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,KAAK,GAAG,mCAAmC,QAAQ,CAAC,MAAM,EAAE,CAAC;gBACnE,MAAM,CAAC,IAAI,CAAC,YAAY,KAAK,EAAE,CAAC,CAAC;gBACjC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;YACvD,CAAC;YACD,IAAI,MAAe,CAAC;YACpB,IAAI,CAAC;gBACH,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACjC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,KAAK,GAAG,qCAAqC,GAAG,EAAE,CAAC;gBACzD,MAAM,CAAC,IAAI,CAAC,YAAY,KAAK,EAAE,CAAC,CAAC;gBACjC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;YACvD,CAAC;YACD,2DAA2D;YAC3D,MAAM,IAAI,GACR,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;gBAClC,CAAC,CAAE,MAA6B,CAAC,IAAI;gBACrC,CAAC,CAAC,SAAS,CAAC;YAChB,MAAM,KAAK,GACT,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAE,IAA4B,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;YACrF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC1B,MAAM,KAAK,GAAG,oDAAoD,CAAC;gBACnE,MAAM,CAAC,IAAI,CAAC,YAAY,KAAK,EAAE,CAAC,CAAC;gBACjC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;YACvD,CAAC;YACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,KAA4B,EAAE,EAAE,CAAC;QAC9F,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -1,19 +1,43 @@
1
1
  import type { ChorusMcpClient } from "./mcp-client.js";
2
2
  import type { SseNotificationEvent } from "./sse-listener.js";
3
+ import type { LineageResolver } from "./lineage.js";
4
+ /**
5
+ * Per-wake attribution the router resolves and threads to the wake. Carries the
6
+ * reportable resource (`entityType`/`entityUuid`) and the lineage ids (the two-id
7
+ * contract: `directIdeaUuid` = session anchor, `rootIdeaUuid` = snapshot attribution).
8
+ * All optional so a host wired WITHOUT the daemon client (no lineage) still wakes —
9
+ * the daemon-reporting fields are simply absent and the run is a plain wake.
10
+ */
11
+ export interface WakeAttribution {
12
+ entityType?: string | null;
13
+ entityUuid?: string | null;
14
+ directIdeaUuid?: string | null;
15
+ rootIdeaUuid?: string | null;
16
+ }
3
17
  /**
4
18
  * Wake callback injected by the entry. Runs an embedded agent turn on the main
5
- * agent's session with `message` as the prompt (see `wake.ts` createWake,
6
- * which calls `api.runtime.agent.runEmbeddedAgent`).
19
+ * agent's session with `message` as the prompt (see `wake.ts` / daemon-client.ts,
20
+ * which call `api.runtime.agent.runEmbeddedAgent`).
7
21
  *
8
22
  * `contextKey` identifies the originating Chorus action+entity (e.g.
9
- * `chorus:mentioned:<uuid>`); it is used for the run id / logging. The wake
10
- * resolves the main agent session + model and DROPS (logs + returns) when it
11
- * cannot run it never throws, so the SSE service stays alive.
23
+ * `chorus:mentioned:<uuid>`); it is used for the run id / logging. `attribution`
24
+ * (when present) lets the daemon client report turn-advance / execution-state /
25
+ * interrupt for the wake and anchor the session on the business key. The wake
26
+ * resolves the main agent session + model and DROPS (logs + returns) when it cannot
27
+ * run — it never throws, so the SSE service stays alive.
12
28
  */
13
- export type ChorusWakeFn = (message: string, contextKey: string) => void;
29
+ export type ChorusWakeFn = (message: string, contextKey: string, attribution?: WakeAttribution) => void;
14
30
  export interface ChorusEventRouterOptions {
15
31
  mcpClient: ChorusMcpClient;
16
32
  wake: ChorusWakeFn;
33
+ /**
34
+ * Optional lineage resolver (daemon parity). When present, the router resolves each
35
+ * notification's `{ rootIdeaUuid, directIdeaUuid }` via the root-idea REST endpoint
36
+ * before waking, so the daemon client can anchor the session on the direct idea and
37
+ * report the root idea in its execution snapshot. When absent (a host with no daemon
38
+ * reporting), wakes carry only the entity fields the notification already provides.
39
+ */
40
+ lineage?: LineageResolver;
17
41
  logger: {
18
42
  info: (msg: string) => void;
19
43
  warn: (msg: string) => void;
@@ -23,6 +47,7 @@ export interface ChorusEventRouterOptions {
23
47
  export declare class ChorusEventRouter {
24
48
  private readonly mcpClient;
25
49
  private readonly wake;
50
+ private readonly lineage?;
26
51
  private readonly logger;
27
52
  constructor(opts: ChorusEventRouterOptions);
28
53
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"event-router.d.ts","sourceRoot":"","sources":["../src/event-router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAE9D;;;;;;;;;GASG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;AAEzE,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,eAAe,CAAC;IAC3B,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,EAAE;QAAE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;QAAC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;QAAC,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;CACpG;AAmBD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkB;IAC5C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAe;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;gBAEhD,IAAI,EAAE,wBAAwB;IAM1C;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI;IAsB3C;;;;OAIG;IACH,OAAO,CAAC,aAAa;YAIP,aAAa;IA4D3B;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAO5B,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,0BAA0B;IAOlC,OAAO,CAAC,sBAAsB;IAY9B,OAAO,CAAC,sBAAsB;IAY9B,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,yBAAyB;CAalC"}
1
+ {"version":3,"file":"event-router.d.ts","sourceRoot":"","sources":["../src/event-router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,YAAY,GAAG,CACzB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,WAAW,CAAC,EAAE,eAAe,KAC1B,IAAI,CAAC;AAEV,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,eAAe,CAAC;IAC3B,IAAI,EAAE,YAAY,CAAC;IACnB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,MAAM,EAAE;QAAE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;QAAC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;QAAC,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;CACpG;AAmBD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkB;IAC5C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAe;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAkB;IAC3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;gBAEhD,IAAI,EAAE,wBAAwB;IAO1C;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI;IAgC3C;;;;OAIG;IACH,OAAO,CAAC,aAAa;YAIP,aAAa;IAgF3B;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAO5B,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,0BAA0B;IAQlC,OAAO,CAAC,sBAAsB;IAa9B,OAAO,CAAC,sBAAsB;IAa9B,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,yBAAyB;CAclC"}
@@ -1,10 +1,12 @@
1
1
  export class ChorusEventRouter {
2
2
  mcpClient;
3
3
  wake;
4
+ lineage;
4
5
  logger;
5
6
  constructor(opts) {
6
7
  this.mcpClient = opts.mcpClient;
7
8
  this.wake = opts.wake;
9
+ this.lineage = opts.lineage;
8
10
  this.logger = opts.logger;
9
11
  }
10
12
  /**
@@ -12,6 +14,15 @@ export class ChorusEventRouter {
12
14
  * Never throws — all errors are caught and logged internally.
13
15
  */
14
16
  dispatch(event) {
17
+ // The bidirectional daemon events `connection_registered` and `control` are
18
+ // forked upstream by the SSE listener (onConnectionId / onControl) and never
19
+ // reach the wake path. If one ever does arrive here (defense-in-depth), drop
20
+ // it SILENTLY — it is a known, handled-elsewhere event, NOT an unhandled one,
21
+ // so logging it as "ignored" would be misleading noise (and the spec requires
22
+ // connection_registered never be logged as ignored).
23
+ if (event.type === "connection_registered" || event.type === "control") {
24
+ return;
25
+ }
15
26
  // Only handle new_notification events (ignore count_update, etc.)
16
27
  if (event.type !== "new_notification") {
17
28
  this.logger.info(`SSE event type "${event.type}" ignored`);
@@ -55,35 +66,55 @@ export class ChorusEventRouter {
55
66
  this.logger.warn(`Notification ${notificationUuid} not found in unread list`);
56
67
  return;
57
68
  }
69
+ // Resolve the wake attribution ONCE per notification (daemon parity). The lineage
70
+ // resolver returns { rootIdeaUuid, directIdeaUuid } via the root-idea REST endpoint;
71
+ // both null when there's no idea ancestor or no resolver is wired. The entity
72
+ // fields always come straight off the notification. This threads through to the
73
+ // daemon client so it reports/anchors against the right session + resource.
74
+ let attribution = {
75
+ entityType: notification.entityType,
76
+ entityUuid: notification.entityUuid,
77
+ };
78
+ if (this.lineage) {
79
+ try {
80
+ const { rootIdeaUuid, directIdeaUuid } = await this.lineage.resolve(notification);
81
+ attribution = { ...attribution, rootIdeaUuid, directIdeaUuid };
82
+ }
83
+ catch (err) {
84
+ // A lineage failure must not lose the wake — fall back to the entity-only
85
+ // attribution (the daemon client then anchors on the entity uuid). Logged.
86
+ this.logger.warn(`Lineage resolve failed for ${notification.entityType}:${notification.entityUuid}: ${err}`);
87
+ }
88
+ }
58
89
  // Route based on action (which corresponds to notificationType)
59
90
  try {
60
91
  switch (notification.action) {
61
92
  case "task_assigned":
62
- this.handleTaskAssigned(notification);
93
+ this.handleTaskAssigned(notification, attribution);
63
94
  break;
64
95
  case "mentioned":
65
- this.handleMentioned(notification);
96
+ this.handleMentioned(notification, attribution);
66
97
  break;
67
98
  case "elaboration_requested":
68
- this.handleElaborationRequested(notification);
99
+ this.handleElaborationRequested(notification, attribution);
69
100
  break;
70
101
  case "elaboration_answered":
71
- this.handleElaborationAnswered(notification);
102
+ this.handleElaborationAnswered(notification, attribution);
72
103
  break;
73
104
  case "proposal_rejected":
74
- this.handleProposalRejected(notification);
105
+ this.handleProposalRejected(notification, attribution);
75
106
  break;
76
107
  case "proposal_approved":
77
- this.handleProposalApproved(notification);
108
+ this.handleProposalApproved(notification, attribution);
78
109
  break;
79
110
  case "idea_claimed":
80
- this.handleIdeaClaimed(notification);
111
+ this.handleIdeaClaimed(notification, attribution);
81
112
  break;
82
113
  case "task_verified":
83
- this.handleTaskVerified(notification);
114
+ this.handleTaskVerified(notification, attribution);
84
115
  break;
85
116
  case "task_reopened":
86
- this.handleTaskReopened(notification);
117
+ this.handleTaskReopened(notification, attribution);
87
118
  break;
88
119
  default:
89
120
  this.logger.info(`Unhandled notification action: "${notification.action}"`);
@@ -102,56 +133,56 @@ export class ChorusEventRouter {
102
133
  return (`After completing your work, post a comment on this ${entityType} using chorus_add_comment with @mention:\n` +
103
134
  `Use this exact mention format: @[${n.actorName}](${n.actorType}:${n.actorUuid})`);
104
135
  }
105
- handleTaskAssigned(n) {
136
+ handleTaskAssigned(n, attr) {
106
137
  const mentionGuidance = this.buildMentionGuidance(n, "task");
107
- this.wake(`[Chorus] Task assigned: ${n.entityTitle}. Task UUID: ${n.entityUuid}, Project UUID: ${n.projectUuid}. Use chorus_get_task to review the task, then chorus_claim_task to start work.\n${mentionGuidance}`, this.contextKeyFor("task_assigned", n.entityUuid));
138
+ this.wake(`[Chorus] Task assigned: ${n.entityTitle}. Task UUID: ${n.entityUuid}, Project UUID: ${n.projectUuid}. Use chorus_get_task to review the task, then chorus_claim_task to start work.\n${mentionGuidance}`, this.contextKeyFor("task_assigned", n.entityUuid), attr);
108
139
  }
109
- handleMentioned(n) {
140
+ handleMentioned(n, attr) {
110
141
  const mentionGuidance = this.buildMentionGuidance(n, n.entityType);
111
142
  this.wake(`[Chorus] You were @mentioned in ${n.entityType} '${n.entityTitle}' (entityType: ${n.entityType}, entityUuid: ${n.entityUuid}, projectUuid: ${n.projectUuid}): ${n.message}\n` +
112
143
  `Review the ${n.entityType} content and use chorus_get_comments (targetType: "${n.entityType}", targetUuid: "${n.entityUuid}") to see the full conversation, then respond.\n` +
113
- mentionGuidance, this.contextKeyFor("mentioned", n.entityUuid));
144
+ mentionGuidance, this.contextKeyFor("mentioned", n.entityUuid), attr);
114
145
  }
115
- handleElaborationRequested(n) {
116
- this.wake(`[Chorus] Elaboration requested for idea '${n.entityTitle}' (ideaUuid: ${n.entityUuid}, projectUuid: ${n.projectUuid}). Use chorus_get_elaboration to review questions.`, this.contextKeyFor("elaboration_requested", n.entityUuid));
146
+ handleElaborationRequested(n, attr) {
147
+ this.wake(`[Chorus] Elaboration requested for idea '${n.entityTitle}' (ideaUuid: ${n.entityUuid}, projectUuid: ${n.projectUuid}). Use chorus_get_elaboration to review questions.`, this.contextKeyFor("elaboration_requested", n.entityUuid), attr);
117
148
  }
118
- handleProposalRejected(n) {
149
+ handleProposalRejected(n, attr) {
119
150
  const mentionGuidance = this.buildMentionGuidance(n, "proposal");
120
151
  this.wake(`[Chorus] Proposal '${n.entityTitle}' was REJECTED (proposalUuid: ${n.entityUuid}, projectUuid: ${n.projectUuid}). Review note: "${n.message}". ` +
121
152
  `Use chorus_get_proposal to review the proposal, then fix issues with chorus_update_task_draft / chorus_update_document_draft. ` +
122
153
  `After fixing, call chorus_validate_proposal then chorus_submit_proposal to resubmit.\n` +
123
- mentionGuidance, this.contextKeyFor("proposal_rejected", n.entityUuid));
154
+ mentionGuidance, this.contextKeyFor("proposal_rejected", n.entityUuid), attr);
124
155
  }
125
- handleProposalApproved(n) {
156
+ handleProposalApproved(n, attr) {
126
157
  const mentionGuidance = this.buildMentionGuidance(n, "proposal");
127
158
  const reviewInfo = n.message.includes("Note: ") ? ` Review note: "${n.message.split("Note: ").pop()}"` : "";
128
159
  this.wake(`[Chorus] Proposal '${n.entityTitle}' was APPROVED (proposalUuid: ${n.entityUuid}, projectUuid: ${n.projectUuid})!${reviewInfo} Documents and tasks have been created. ` +
129
160
  `Use chorus_get_available_tasks with projectUuid: "${n.projectUuid}" to see the new tasks ready for work.\n` +
130
- mentionGuidance, this.contextKeyFor("proposal_approved", n.entityUuid));
161
+ mentionGuidance, this.contextKeyFor("proposal_approved", n.entityUuid), attr);
131
162
  }
132
- handleIdeaClaimed(n) {
163
+ handleIdeaClaimed(n, attr) {
133
164
  const mentionGuidance = this.buildMentionGuidance(n, "idea");
134
165
  this.wake(`[Chorus] Idea '${n.entityTitle}' has been assigned to you (ideaUuid: ${n.entityUuid}, projectUuid: ${n.projectUuid}). ` +
135
166
  `Use chorus_get_idea to review the idea, then chorus_claim_idea to start elaboration.\n` +
136
- mentionGuidance, this.contextKeyFor("idea_claimed", n.entityUuid));
167
+ mentionGuidance, this.contextKeyFor("idea_claimed", n.entityUuid), attr);
137
168
  }
138
- handleTaskVerified(n) {
169
+ handleTaskVerified(n, attr) {
139
170
  this.wake(`[Chorus] Task '${n.entityTitle}' has been verified and is now done (taskUuid: ${n.entityUuid}, projectUuid: ${n.projectUuid}). ` +
140
- `Check if this unblocks other tasks: use chorus_get_unblocked_tasks with projectUuid "${n.projectUuid}" to find tasks that are now ready to start.`, this.contextKeyFor("task_verified", n.entityUuid));
171
+ `Check if this unblocks other tasks: use chorus_get_unblocked_tasks with projectUuid "${n.projectUuid}" to find tasks that are now ready to start.`, this.contextKeyFor("task_verified", n.entityUuid), attr);
141
172
  }
142
- handleTaskReopened(n) {
173
+ handleTaskReopened(n, attr) {
143
174
  const mentionGuidance = this.buildMentionGuidance(n, "task");
144
175
  this.wake(`[Chorus] Task '${n.entityTitle}' has been reopened and needs rework (taskUuid: ${n.entityUuid}, projectUuid: ${n.projectUuid}). ` +
145
- `Use chorus_get_task to review the task and chorus_get_comments to see verification feedback, then fix the issues.\n${mentionGuidance}`, this.contextKeyFor("task_reopened", n.entityUuid));
176
+ `Use chorus_get_task to review the task and chorus_get_comments to see verification feedback, then fix the issues.\n${mentionGuidance}`, this.contextKeyFor("task_reopened", n.entityUuid), attr);
146
177
  }
147
- handleElaborationAnswered(n) {
178
+ handleElaborationAnswered(n, attr) {
148
179
  const mentionGuidance = this.buildMentionGuidance(n, "idea");
149
180
  this.wake(`[Chorus] Elaboration answers submitted for idea '${n.entityTitle}' (ideaUuid: ${n.entityUuid}, projectUuid: ${n.projectUuid}). ` +
150
181
  `Review the answers with chorus_get_elaboration, then either:\n` +
151
182
  `- Call chorus_validate_elaboration with empty issues [] to resolve and proceed to proposal creation\n` +
152
183
  `- Call chorus_validate_elaboration with issues + followUpQuestions for another round\n\n` +
153
184
  `After reviewing, @mention the answerer to ask if they have any further questions before you proceed.\n` +
154
- mentionGuidance, this.contextKeyFor("elaboration_answered", n.entityUuid));
185
+ mentionGuidance, this.contextKeyFor("elaboration_answered", n.entityUuid), attr);
155
186
  }
156
187
  }
157
188
  //# sourceMappingURL=event-router.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"event-router.js","sourceRoot":"","sources":["../src/event-router.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"event-router.js","sourceRoot":"","sources":["../src/event-router.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAiCA,wBAuFG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAuCA,wBA0LG"}
package/dist/index.js CHANGED
@@ -4,8 +4,13 @@ import { ensureChorusMcpServer } from "./mcp-registration.js";
4
4
  import { ChorusMcpClient } from "./mcp-client.js";
5
5
  import { ChorusSseListener } from "./sse-listener.js";
6
6
  import { ChorusEventRouter } from "./event-router.js";
7
- import { createWake } from "./wake.js";
7
+ import { resolveWakeRunContext } from "./wake.js";
8
8
  import { registerChorusCommands } from "./commands.js";
9
+ import { ConnectionState } from "./connection-state.js";
10
+ import { createControlHandler } from "./control-handler.js";
11
+ import { createDaemonRestClient } from "./daemon-rest-client.js";
12
+ import { LineageResolver } from "./lineage.js";
13
+ import { OpenClawDaemonClient } from "./daemon-client.js";
9
14
  /**
10
15
  * JSON-Schema config contract for the Chorus plugin.
11
16
  *
@@ -57,15 +62,92 @@ export default definePluginEntry({
57
62
  // 4. Slim MCP client for the plugin's own synchronous calls (checkin,
58
63
  // assignments, notifications back-fill).
59
64
  const mcpClient = new ChorusMcpClient({ chorusUrl, apiKey, logger });
60
- // 5. Event router. Wakes the agent in-process by running an embedded agent
61
- // turn via `api.runtime.agent.runEmbeddedAgent` (see wake.ts). `createWake`
62
- // resolves the main agent session + configured model on each wake and
63
- // gracefully DROPS (logs + returns) when it cannot run it never throws,
64
- // so the SSE service stays alive even on a host that exposes no session.
65
+ // 4b. Connection identity + reverse control channel + daemon reporting (parity).
66
+ // `connectionState` holds the DaemonConnection uuid the server reports
67
+ // post-handshake (captured by the listener's onConnectionId); it is the
68
+ // single source of truth for "which connection am I", read by the control
69
+ // handler's double-check AND the daemon REST reporter (lazily, so order
70
+ // doesn't matter — both predate the handshake).
71
+ const connectionState = new ConnectionState();
72
+ // The shared pure-REST daemon client owns the `/api/daemon/*` payload shapes
73
+ // (turn-advance / transcript / execution-state / report-interrupt /
74
+ // pending-turns). It reads the connectionUuid lazily from connectionState.
75
+ const restClient = createDaemonRestClient({
76
+ url: chorusUrl,
77
+ apiKey,
78
+ getConnectionUuid: () => connectionState.getConnectionUuid(),
79
+ logger,
80
+ });
81
+ // Lineage resolver: per-notification { rootIdeaUuid, directIdeaUuid } via the
82
+ // root-idea REST endpoint, so the daemon client anchors the session on the
83
+ // DIRECT idea (resume/deliver_turn continuity) and reports the ROOT idea in
84
+ // its execution snapshot (the two-id contract).
85
+ const lineage = new LineageResolver({ url: chorusUrl, apiKey, logger });
86
+ // The in-process daemon client wraps runEmbeddedAgent with full reporting,
87
+ // the AbortController registry (real mid-run interrupt), the execution
88
+ // snapshot source, deterministic session-key mapping, and the at-most-once
89
+ // pending-turns backfill. `resolveRunContext` is the ONE place that reaches
90
+ // into api.config/api.runtime (kept out of the client so it stays testable).
91
+ // `redispatch` resolves lineage for a synthetic resume so it continues the
92
+ // SAME session, then runs the wake; a delivered turn already carries its ids.
93
+ let daemonClient;
94
+ const redispatch = (req) => {
95
+ void (async () => {
96
+ let enriched = req;
97
+ // A resume only knows the entity — resolve its lineage so the wake anchors on
98
+ // the same business key (direct idea) the original run used. A delivered turn
99
+ // already carries directIdeaUuid, so we skip the round-trip when present.
100
+ if (req.directIdeaUuid == null && req.entityType && req.entityUuid) {
101
+ try {
102
+ const { rootIdeaUuid, directIdeaUuid } = await lineage.resolve({
103
+ entityType: req.entityType,
104
+ entityUuid: req.entityUuid,
105
+ });
106
+ enriched = { ...req, rootIdeaUuid, directIdeaUuid };
107
+ }
108
+ catch (err) {
109
+ logger.warn(`[Chorus] resume lineage resolve failed: ${err}`);
110
+ }
111
+ }
112
+ await daemonClient.runWake(enriched);
113
+ })();
114
+ };
115
+ daemonClient = new OpenClawDaemonClient({
116
+ restClient,
117
+ resolveRunContext: () => resolveWakeRunContext(api, logger),
118
+ redispatch,
119
+ // Build the prompt for a delivered human_instruction turn. The free-text body
120
+ // lives only on the turn (promptText); fall back to a generic nudge if absent.
121
+ buildTurnPrompt: (turn) => turn.promptText && turn.promptText.trim()
122
+ ? `[Chorus] A human sent you an instruction in this conversation:\n\n${turn.promptText}`
123
+ : `[Chorus] A human sent you a new instruction in this conversation (session ${turn.sessionId}). Review the latest comments and respond.`,
124
+ logger,
125
+ });
126
+ // The control handler ROUTES verified control commands to the daemon client's
127
+ // behavior hooks (real abort / resume re-dispatch / pending-turns sweep),
128
+ // after its own double-check (own connection + held entity).
129
+ const controlHooks = daemonClient.controlHooks;
130
+ const onControl = createControlHandler({ connectionState, hooks: controlHooks, logger });
131
+ // 5. Event router. Wakes the agent in-process by running an embedded agent turn
132
+ // via the daemon client (which calls api.runtime.agent.runEmbeddedAgent and
133
+ // reports lifecycle/transcript). The router resolves each notification's
134
+ // lineage, then the daemon client's runWake gracefully DROPS (logs + returns)
135
+ // when it cannot run — it never throws, so the SSE service stays alive.
136
+ const wakeFn = (message, contextKey, attribution) => {
137
+ void daemonClient.runWake({
138
+ prompt: message,
139
+ contextKey,
140
+ entityType: attribution?.entityType,
141
+ entityUuid: attribution?.entityUuid,
142
+ directIdeaUuid: attribution?.directIdeaUuid,
143
+ rootIdeaUuid: attribution?.rootIdeaUuid,
144
+ });
145
+ };
65
146
  const eventRouter = new ChorusEventRouter({
66
147
  mcpClient,
67
148
  logger,
68
- wake: createWake(api, logger),
149
+ lineage,
150
+ wake: wakeFn,
69
151
  });
70
152
  // 6. Background SSE service. The SSE socket opens only inside start(), which
71
153
  // the host calls in full mode — keeping the heavy socket gated.
@@ -78,7 +160,23 @@ export default definePluginEntry({
78
160
  apiKey,
79
161
  logger,
80
162
  onEvent: (event) => eventRouter.dispatch(event),
163
+ // Capture (and refresh on reconnect) the DaemonConnection identity the
164
+ // server reports post-handshake. NOT a wake — forked by the listener.
165
+ onConnectionId: (connectionUuid) => {
166
+ connectionState.setConnectionUuid(connectionUuid);
167
+ logger.info(`[Chorus] registered as daemon connection ${connectionUuid}`);
168
+ },
169
+ // Reverse control channel. The handler does the double-check and routes
170
+ // to the behavior hooks — NEVER the wake path.
171
+ onControl,
81
172
  onReconnect: async () => {
173
+ // (1) Notification backfill — re-pull unread notifications missed during
174
+ // the gap (autonomous wakes). (2) Pending-turns backfill — re-derive
175
+ // this connection's unstarted human_instruction turns from the turn
176
+ // table and run each (the lost-deliver_turn-ping safety net). The two
177
+ // share the daemon client's seen-set so a turn is run at most once
178
+ // across live delivery + backfill. Each swallows its own errors so one
179
+ // failing source never aborts the other.
82
180
  try {
83
181
  const result = (await mcpClient.callTool("chorus_get_notifications", {
84
182
  status: "unread",
@@ -92,6 +190,7 @@ export default definePluginEntry({
92
190
  catch (err) {
93
191
  logger.warn(`Failed to back-fill notifications: ${err}`);
94
192
  }
193
+ await daemonClient.onReconnect();
95
194
  },
96
195
  });
97
196
  await sseListener.connect();