macro-agent 0.1.5 → 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.
Files changed (33) hide show
  1. package/.claude/settings.json +128 -1
  2. package/.sessionlog/settings.json +4 -0
  3. package/CLAUDE.md +125 -10
  4. package/README.md +93 -31
  5. package/dist/boot-v2-DMTHPQ4i.d.ts +2672 -0
  6. package/dist/cognitive/workspace-handler.d.ts +17 -9
  7. package/dist/cognitive/workspace-handler.d.ts.map +1 -1
  8. package/dist/cognitive/workspace-handler.js +10 -11
  9. package/dist/cognitive/workspace-handler.js.map +1 -1
  10. package/dist/map/coordination-handler.d.ts +7 -23
  11. package/dist/map/coordination-handler.d.ts.map +1 -1
  12. package/dist/map/coordination-handler.js +124 -100
  13. package/dist/map/coordination-handler.js.map +1 -1
  14. package/dist/map/sidecar.d.ts.map +1 -1
  15. package/dist/map/sidecar.js +7 -15
  16. package/dist/map/sidecar.js.map +1 -1
  17. package/dist/map/trajectory-reporter.d.ts +4 -9
  18. package/dist/map/trajectory-reporter.d.ts.map +1 -1
  19. package/dist/map/trajectory-reporter.js +15 -129
  20. package/dist/map/trajectory-reporter.js.map +1 -1
  21. package/dist/map/types.d.ts +37 -0
  22. package/dist/map/types.d.ts.map +1 -1
  23. package/package.json +1 -2
  24. package/src/__tests__/e2e/cognitive-workspace.e2e.test.ts +1 -1
  25. package/src/cognitive/__tests__/workspace-handler.test.ts +2 -10
  26. package/src/cognitive/workspace-handler.ts +18 -15
  27. package/src/map/__tests__/trajectory-reporter.test.ts +2 -254
  28. package/src/map/coordination-handler.ts +137 -120
  29. package/src/map/sidecar.ts +7 -20
  30. package/src/map/trajectory-reporter.ts +16 -154
  31. package/src/map/types.ts +40 -2
  32. package/src/__tests__/e2e/trajectory-content.e2e.test.ts +0 -708
  33. package/src/map/__tests__/coordination-handler.test.ts +0 -598
@@ -2,153 +2,39 @@
2
2
  * Trajectory Reporter — builds and reports trajectory checkpoints to the MAP hub.
3
3
  *
4
4
  * Sends checkpoints via the `trajectory/checkpoint` JSON-RPC extension.
5
- * Handles inbound `trajectory/content.request` notifications by serving
6
- * session transcripts via sessionlog's SessionStore and CheckpointStore.
7
- * Supports all agent types (Claude Code, Codex, Gemini, etc.) through
8
- * sessionlog's adapter system.
5
+ * Also handles inbound `trajectory/content.request` notifications by serving
6
+ * session transcript data.
9
7
  *
10
8
  * @module map/trajectory-reporter
11
9
  */
12
- /**
13
- * Resolve transcript content for a checkpoint ID using sessionlog.
14
- *
15
- * Two-source strategy (matching cc-swarm):
16
- * 1. Live session — use sessionlog's SessionStore to find a session
17
- * matching the checkpoint ID, then read its transcript from disk.
18
- * 2. Committed checkpoint — use sessionlog's CheckpointStore to read
19
- * content from the git history.
20
- *
21
- * Returns null if no content is found or sessionlog is unavailable.
22
- */
23
- async function resolveContent(checkpointId, sessionDirs) {
24
- let sessionlog = null;
25
- try {
26
- sessionlog = await import("sessionlog");
27
- }
28
- catch {
29
- return null; // sessionlog not available
30
- }
31
- const { readFileSync, existsSync } = await import("node:fs");
32
- // Derive the session ID from checkpoint ID (e.g., "sess-abc-step3" → "sess-abc")
33
- const sessionId = checkpointId.replace(/-step\d+$/, "");
34
- // ── 1. Live session lookup via SessionStore ────────────────────────────
35
- for (const sessionsDir of sessionDirs) {
36
- if (!existsSync(sessionsDir))
37
- continue;
38
- try {
39
- const store = sessionlog.createSessionStore(undefined, sessionsDir);
40
- // Try loading by derived session ID first, then by raw checkpoint ID
41
- let state = await store.load(sessionId);
42
- if (!state)
43
- state = await store.load(checkpointId);
44
- // If not found by ID, scan all sessions for checkpoint match
45
- if (!state) {
46
- const allSessions = await store.list();
47
- state = allSessions.find((s) => s.lastCheckpointID === checkpointId ||
48
- (s.turnCheckpointIDs || []).includes(checkpointId)) ?? null;
49
- }
50
- if (!state?.transcriptPath || !existsSync(state.transcriptPath))
51
- continue;
52
- const transcript = readFileSync(state.transcriptPath, "utf-8");
53
- // Use sessionlog's prompt extraction if the agent has a TranscriptAnalyzer,
54
- // otherwise fall back to the prompts stored in state
55
- let prompts = "";
56
- if (state.firstPrompt) {
57
- // Collect from promptAttributions if available, otherwise use firstPrompt
58
- const attrs = state.promptAttributions;
59
- if (attrs && attrs.length > 0) {
60
- prompts = attrs.map((a) => a.prompt).join("\n---\n");
61
- }
62
- else {
63
- prompts = state.firstPrompt;
64
- }
65
- }
66
- return {
67
- transcript,
68
- prompts,
69
- metadata: {
70
- sessionID: state.sessionID,
71
- phase: state.phase,
72
- agentType: state.agentType,
73
- stepCount: state.stepCount || 0,
74
- filesTouched: state.filesTouched || [],
75
- tokenUsage: state.tokenUsage || {},
76
- startedAt: state.startedAt,
77
- endedAt: state.endedAt,
78
- source: "live",
79
- },
80
- context: `Session ${state.sessionID} (${state.phase})`,
81
- };
82
- }
83
- catch {
84
- continue;
85
- }
86
- }
87
- // ── 2. Committed checkpoint via CheckpointStore ────────────────────────
88
- try {
89
- if (sessionlog.createCheckpointStore) {
90
- const store = sessionlog.createCheckpointStore();
91
- const content = await store.readSessionContent(checkpointId, 0);
92
- if (content) {
93
- return {
94
- transcript: content.transcript,
95
- prompts: content.prompts,
96
- metadata: { ...content.metadata, source: "committed" },
97
- context: content.context,
98
- };
99
- }
100
- }
101
- }
102
- catch {
103
- // Checkpoint not found or store unavailable
104
- }
105
- return null;
106
- }
107
10
  /**
108
11
  * Create a trajectory reporter that sends checkpoints to the MAP hub
109
- * and serves session transcript content on demand via sessionlog.
12
+ * and serves content on demand.
110
13
  */
111
14
  export function createTrajectoryReporter(connection, config) {
112
15
  // Cache the resource_id from the first checkpoint response
113
16
  // so subsequent calls reuse it (avoids creating duplicate session resources)
114
17
  let cachedResourceId;
115
- // Build session directory search list
116
- const defaultDirs = [];
117
- try {
118
- const cwd = process.cwd();
119
- defaultDirs.push(`${cwd}/.git/sessionlog-sessions`, `${cwd}/.swarm/sessionlog/sessions`);
120
- }
121
- catch {
122
- // Can't resolve paths — will use config dirs only
123
- }
124
- const sessionDirs = [...(config.sessionDirs ?? []), ...defaultDirs];
125
18
  // Handler for inbound content requests
126
19
  const contentHandler = async (params) => {
127
20
  const req = params;
128
21
  if (!req?.request_id)
129
22
  return;
130
23
  try {
131
- const content = await resolveContent(req.checkpoint_id, sessionDirs);
132
- if (content) {
133
- await connection.sendNotification("trajectory/content.response", {
134
- request_id: req.request_id,
135
- transcript: content.transcript,
136
- metadata: content.metadata,
137
- prompts: content.prompts,
138
- context: content.context,
139
- });
140
- }
141
- else {
142
- await connection.sendNotification("trajectory/content.response", {
143
- request_id: req.request_id,
144
- transcript: "",
145
- metadata: { source: "macro-agent" },
146
- prompts: "",
147
- context: "",
148
- });
149
- }
24
+ // Respond with what we have — macro-agent doesn't store full transcripts
25
+ // like sessionlog does, so we send a minimal response.
26
+ // Future: integrate with ACP session history for richer content.
27
+ await connection.sendNotification("trajectory/content.response", {
28
+ request_id: req.request_id,
29
+ transcript: null,
30
+ metadata: {
31
+ source: "macro-agent",
32
+ note: "Full transcript serving not yet implemented",
33
+ },
34
+ });
150
35
  }
151
36
  catch {
37
+ // Best effort
152
38
  try {
153
39
  await connection.sendNotification("trajectory/content.response", {
154
40
  request_id: req.request_id,
@@ -1 +1 @@
1
- {"version":3,"file":"trajectory-reporter.js","sourceRoot":"","sources":["../../src/map/trajectory-reporter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"trajectory-reporter.js","sourceRoot":"","sources":["../../src/map/trajectory-reporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA4BH;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CACtC,UAAgC,EAChC,MAAqD;IAErD,2DAA2D;IAC3D,6EAA6E;IAC7E,IAAI,gBAAoC,CAAC;IAEzC,uCAAuC;IACvC,MAAM,cAAc,GAAG,KAAK,EAAE,MAAe,EAAiB,EAAE;QAC9D,MAAM,GAAG,GAAG,MAAkC,CAAC;QAC/C,IAAI,CAAC,GAAG,EAAE,UAAU;YAAE,OAAO;QAE7B,IAAI,CAAC;YACH,yEAAyE;YACzE,uDAAuD;YACvD,iEAAiE;YACjE,MAAM,UAAU,CAAC,gBAAgB,CAAC,6BAA6B,EAAE;gBAC/D,UAAU,EAAE,GAAG,CAAC,UAAU;gBAC1B,UAAU,EAAE,IAAI;gBAChB,QAAQ,EAAE;oBACR,MAAM,EAAE,aAAa;oBACrB,IAAI,EAAE,6CAA6C;iBACpD;aACF,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,cAAc;YACd,IAAI,CAAC;gBACH,MAAM,UAAU,CAAC,gBAAgB,CAAC,6BAA6B,EAAE;oBAC/D,UAAU,EAAE,GAAG,CAAC,UAAU;oBAC1B,KAAK,EAAE,wBAAwB;iBAChC,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,oCAAoC;YACtC,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IAEF,mCAAmC;IACnC,UAAU,CAAC,cAAc,CAAC,4BAA4B,EAAE,cAAc,CAAC,CAAC;IAExE,OAAO;QACL,KAAK,CAAC,gBAAgB,CACpB,UAAuC;YAEvC,IAAI,CAAC,UAAU,CAAC,WAAW;gBAAE,OAAO,IAAI,CAAC;YACzC,IAAI,MAAM,CAAC,mBAAmB,KAAK,KAAK;gBAAE,OAAO,IAAI,CAAC;YAEtD,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,aAAa,CAG3C,uBAAuB,EAAE;oBACzB,UAAU;oBACV,WAAW,EAAE,gBAAgB;iBAC9B,CAAC,CAAC;gBAEH,6CAA6C;gBAC7C,IAAI,MAAM,EAAE,WAAW,EAAE,CAAC;oBACxB,gBAAgB,GAAG,MAAM,CAAC,WAAW,CAAC;gBACxC,CAAC;gBAED,OAAO,MAAM,CAAC;YAChB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,kDAAkD;gBAClD,IAAI,CAAC;oBACH,MAAM,UAAU,CAAC,gBAAgB,CAAC,uBAAuB,EAAE;wBACzD,UAAU;qBACX,CAAC,CAAC;gBACL,CAAC;gBAAC,MAAM,CAAC;oBACP,6CAA6C;gBAC/C,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,IAAI;YACF,UAAU,CAAC,eAAe,CACxB,4BAA4B,EAC5B,cAAc,CACf,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -103,6 +103,43 @@ export interface TrajectoryContentRequest {
103
103
  request_id: string;
104
104
  checkpoint_id: string;
105
105
  }
106
+ /** Inbound task assignment from hub */
107
+ export interface CoordinationTaskAssign {
108
+ title: string;
109
+ description?: string;
110
+ assigned_to?: string;
111
+ assigned_by: string;
112
+ priority?: string;
113
+ context?: Record<string, unknown>;
114
+ deadline?: string;
115
+ }
116
+ /** Inbound task status update from hub */
117
+ export interface CoordinationTaskStatus {
118
+ task_id: string;
119
+ status: string;
120
+ progress?: number;
121
+ result?: unknown;
122
+ error?: string;
123
+ }
124
+ /** Inbound context share from hub */
125
+ export interface CoordinationContextShare {
126
+ hive_id?: string;
127
+ source_swarm_id: string;
128
+ context_type: string;
129
+ data: unknown;
130
+ target_swarm_ids?: string[];
131
+ ttl_seconds?: number;
132
+ }
133
+ /** Inbound message from hub */
134
+ export interface CoordinationMessage {
135
+ hive_id?: string;
136
+ from_swarm_id: string;
137
+ to_swarm_id: string;
138
+ content_type: string;
139
+ content: unknown;
140
+ reply_to?: string;
141
+ metadata?: Record<string, unknown>;
142
+ }
106
143
  /** Task bridge interface for emitting task events to MAP */
107
144
  export interface TaskBridge {
108
145
  taskCreated(task: {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/map/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/map/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "macro-agent",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Interact with multiple agents as if they were a single agent.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -53,7 +53,6 @@
53
53
  "@sudocode-ai/claude-code-acp": "^0.13.9",
54
54
  "acp-factory": "^0.1.12",
55
55
  "agent-inbox": "^0.1.8",
56
- "agent-workspace": "^0.1.5",
57
56
  "better-sqlite3": "^12.5.0",
58
57
  "chalk": "^5.6.2",
59
58
  "commander": "^14.0.2",
@@ -149,7 +149,7 @@ describe("Cognitive Workspace E2E", () => {
149
149
  expect(sentMessages.length).toBe(1);
150
150
  const result = sentMessages[0] as any;
151
151
  expect(result.jsonrpc).toBe("2.0");
152
- expect(result.method).toBe("x-workspace/task.result");
152
+ expect(result.method).toBe("x-openhive/learning.workspace.result");
153
153
  expect(result.params.request_id).toBe("e2e-001");
154
154
  expect(result.params.duration_ms).toBeGreaterThanOrEqual(0);
155
155
  // Success or failure depends on whether mocked agent wrote output
@@ -52,15 +52,7 @@ function createMockBackend(session?: CognitiveAgentSession): MacroAgentBackend {
52
52
  }
53
53
 
54
54
  describe("isWorkspaceExecuteMessage", () => {
55
- it("should return true for x-workspace/task.execute", () => {
56
- expect(
57
- isWorkspaceExecuteMessage({
58
- method: "x-workspace/task.execute",
59
- }),
60
- ).toBe(true);
61
- });
62
-
63
- it("should return true for legacy x-openhive/learning.workspace.execute", () => {
55
+ it("should return true for workspace.execute messages", () => {
64
56
  expect(
65
57
  isWorkspaceExecuteMessage({
66
58
  method: "x-openhive/learning.workspace.execute",
@@ -119,7 +111,7 @@ describe("handleWorkspaceExecute", () => {
119
111
  expect(sentMessages.length).toBe(1);
120
112
  const result = sentMessages[0] as any;
121
113
  expect(result.jsonrpc).toBe("2.0");
122
- expect(result.method).toBe("x-workspace/task.result");
114
+ expect(result.method).toBe("x-openhive/learning.workspace.result");
123
115
  expect(result.params.request_id).toBe("req-001");
124
116
  expect(result.params.success).toBe(true);
125
117
  expect(result.params.duration_ms).toBeGreaterThanOrEqual(0);
@@ -1,22 +1,20 @@
1
1
  /**
2
2
  * Workspace Execution Handler
3
3
  *
4
- * Bridge between workspace task execution MAP messages and
4
+ * Bridge between OpenHive's workspace.execute MAP messages and
5
5
  * macro-agent's MacroAgentBackend. Receives workspace tasks from
6
- * a hub, spawns analyst agents, and sends results back.
6
+ * OpenHive, spawns analyst agents, and sends results back.
7
7
  *
8
8
  * Registered as a MAP notification handler on the swarm's inbound
9
- * WebSocket connection to the hub.
9
+ * WebSocket connection to the OpenHive hub.
10
10
  *
11
- * Protocol (defined by agent-workspace):
12
- * Hub → Swarm: x-workspace/task.execute
11
+ * Protocol:
12
+ * Hive → Swarm: x-openhive/learning.workspace.execute
13
13
  * { request_id, prompt, cwd, system_context, timeout }
14
- * Swarm → Hub: x-workspace/task.result
14
+ * Swarm → Hive: x-openhive/learning.workspace.result
15
15
  * { request_id, success, output, structured, duration_ms }
16
16
  */
17
17
 
18
- import { WORKSPACE_METHODS, WORKSPACE_METHODS_LEGACY } from "agent-workspace";
19
- import type { WorkspaceExecuteParams, WorkspaceResultParams } from "agent-workspace";
20
18
  import type { MacroAgentBackend } from "./macro-agent-backend.js";
21
19
  import type { CognitiveAgentSpawnConfig } from "./types.js";
22
20
 
@@ -26,8 +24,13 @@ export interface WorkspaceHandlerDeps {
26
24
  sendToHub: (message: object) => void;
27
25
  }
28
26
 
29
- // Re-export the protocol type for consumers
30
- export type { WorkspaceExecuteParams } from "agent-workspace";
27
+ export interface WorkspaceExecuteParams {
28
+ request_id: string;
29
+ prompt: string;
30
+ cwd: string;
31
+ system_context?: string;
32
+ timeout?: number;
33
+ }
31
34
 
32
35
  /**
33
36
  * Handle an incoming workspace.execute request from OpenHive.
@@ -76,7 +79,7 @@ export async function handleWorkspaceExecute(
76
79
  await backend.terminate(session.id).catch(() => {});
77
80
  sendToHub({
78
81
  jsonrpc: "2.0",
79
- method: WORKSPACE_METHODS.RESULT,
82
+ method: "x-openhive/learning.workspace.result",
80
83
  params: {
81
84
  request_id,
82
85
  success: false,
@@ -125,7 +128,7 @@ export async function handleWorkspaceExecute(
125
128
 
126
129
  sendToHub({
127
130
  jsonrpc: "2.0",
128
- method: WORKSPACE_METHODS.RESULT,
131
+ method: "x-openhive/learning.workspace.result",
129
132
  params: {
130
133
  request_id,
131
134
  success: finalSession.state === "completed",
@@ -138,7 +141,7 @@ export async function handleWorkspaceExecute(
138
141
  } catch (err) {
139
142
  sendToHub({
140
143
  jsonrpc: "2.0",
141
- method: WORKSPACE_METHODS.RESULT,
144
+ method: "x-openhive/learning.workspace.result",
142
145
  params: {
143
146
  request_id,
144
147
  success: false,
@@ -155,6 +158,6 @@ export async function handleWorkspaceExecute(
155
158
  */
156
159
  export function isWorkspaceExecuteMessage(
157
160
  msg: { method?: string },
158
- ): boolean {
159
- return msg.method === WORKSPACE_METHODS.EXECUTE || msg.method === WORKSPACE_METHODS_LEGACY.EXECUTE;
161
+ ): msg is { method: "x-openhive/learning.workspace.execute"; params: WorkspaceExecuteParams } {
162
+ return msg.method === "x-openhive/learning.workspace.execute";
160
163
  }
@@ -1,11 +1,8 @@
1
1
  /**
2
- * Tests for Trajectory Reporter — checkpoint reporting & content serving.
2
+ * Tests for Trajectory Reporter — checkpoint building & reporting.
3
3
  */
4
4
 
5
- import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
6
- import * as fs from "node:fs";
7
- import * as path from "node:path";
8
- import * as os from "node:os";
5
+ import { describe, it, expect, beforeEach, vi } from "vitest";
9
6
  import {
10
7
  createTrajectoryReporter,
11
8
  type TrajectoryConnection,
@@ -174,252 +171,3 @@ describe("TrajectoryReporter", () => {
174
171
  );
175
172
  });
176
173
  });
177
-
178
- // =============================================================================
179
- // Tests — Content Serving via sessionlog
180
- // =============================================================================
181
-
182
- describe("TrajectoryReporter — content serving", () => {
183
- let conn: ReturnType<typeof mockConnection>;
184
- let tmpDir: string;
185
-
186
- beforeEach(() => {
187
- conn = mockConnection();
188
- tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "trajectory-content-test-"));
189
- });
190
-
191
- afterEach(() => {
192
- fs.rmSync(tmpDir, { recursive: true, force: true });
193
- });
194
-
195
- /** Write a sessionlog-compatible flat state file: <sessionsDir>/<sessionId>.json */
196
- function writeSessionState(
197
- sessionsDir: string,
198
- sessionId: string,
199
- state: Record<string, unknown>,
200
- transcript?: string,
201
- ): string {
202
- fs.mkdirSync(sessionsDir, { recursive: true });
203
-
204
- const transcriptPath = path.join(sessionsDir, `${sessionId}.jsonl`);
205
- if (transcript) {
206
- fs.writeFileSync(transcriptPath, transcript);
207
- }
208
-
209
- fs.writeFileSync(
210
- path.join(sessionsDir, `${sessionId}.json`),
211
- JSON.stringify({
212
- sessionID: sessionId,
213
- phase: "active",
214
- baseCommit: "abc123",
215
- startedAt: new Date().toISOString(),
216
- agentType: "claude",
217
- transcriptPath: transcript ? transcriptPath : undefined,
218
- ...state,
219
- }),
220
- );
221
-
222
- return transcriptPath;
223
- }
224
-
225
- it("serves transcript from live session matching session ID", async () => {
226
- const sessionsDir = path.join(tmpDir, "sessions");
227
- const transcript = [
228
- JSON.stringify({ type: "user", message: "Fix the bug" }),
229
- JSON.stringify({ type: "assistant", message: "I'll look into it" }),
230
- ].join("\n");
231
-
232
- writeSessionState(sessionsDir, "sess-abc", {
233
- stepCount: 3,
234
- filesTouched: ["src/main.ts"],
235
- firstPrompt: "Fix the bug",
236
- }, transcript);
237
-
238
- createTrajectoryReporter(conn, {
239
- trajectorySyncLevel: "full",
240
- sessionDirs: [sessionsDir],
241
- });
242
-
243
- const handler = conn.onNotification.mock.calls[0][1];
244
- await handler({ request_id: "req-1", checkpoint_id: "sess-abc-step2" });
245
-
246
- expect(conn.sendNotification).toHaveBeenCalledWith(
247
- "trajectory/content.response",
248
- expect.objectContaining({
249
- request_id: "req-1",
250
- transcript: expect.stringContaining("Fix the bug"),
251
- prompts: "Fix the bug",
252
- metadata: expect.objectContaining({
253
- sessionID: "sess-abc",
254
- source: "live",
255
- }),
256
- }),
257
- );
258
- });
259
-
260
- it("serves transcript matching checkpoint ID in turnCheckpointIDs", async () => {
261
- const sessionsDir = path.join(tmpDir, "sessions");
262
- const transcript = JSON.stringify({ type: "user", message: "Deploy it" }) + "\n";
263
-
264
- writeSessionState(sessionsDir, "sess-xyz", {
265
- turnCheckpointIDs: ["sess-xyz-step1", "sess-xyz-step2"],
266
- firstPrompt: "Deploy it",
267
- }, transcript);
268
-
269
- createTrajectoryReporter(conn, {
270
- trajectorySyncLevel: "full",
271
- sessionDirs: [sessionsDir],
272
- });
273
-
274
- const handler = conn.onNotification.mock.calls[0][1];
275
- await handler({ request_id: "req-2", checkpoint_id: "sess-xyz-step2" });
276
-
277
- expect(conn.sendNotification).toHaveBeenCalledWith(
278
- "trajectory/content.response",
279
- expect.objectContaining({
280
- request_id: "req-2",
281
- transcript: expect.stringContaining("Deploy it"),
282
- }),
283
- );
284
- });
285
-
286
- it("uses promptAttributions for multi-prompt sessions", async () => {
287
- const sessionsDir = path.join(tmpDir, "sessions");
288
- const transcript = JSON.stringify({ type: "user", message: "First" }) + "\n"
289
- + JSON.stringify({ type: "user", message: "Second" }) + "\n";
290
-
291
- writeSessionState(sessionsDir, "sess-multi", {
292
- firstPrompt: "First",
293
- promptAttributions: [
294
- { prompt: "First", timestamp: "2026-01-01T00:00:00Z", agentLines: 10 },
295
- { prompt: "Second", timestamp: "2026-01-01T00:01:00Z", agentLines: 5 },
296
- ],
297
- }, transcript);
298
-
299
- createTrajectoryReporter(conn, {
300
- trajectorySyncLevel: "full",
301
- sessionDirs: [sessionsDir],
302
- });
303
-
304
- const handler = conn.onNotification.mock.calls[0][1];
305
- await handler({ request_id: "req-3", checkpoint_id: "sess-multi-step1" });
306
-
307
- expect(conn.sendNotification).toHaveBeenCalledWith(
308
- "trajectory/content.response",
309
- expect.objectContaining({
310
- prompts: "First\n---\nSecond",
311
- }),
312
- );
313
- });
314
-
315
- it("returns empty response when no session found", async () => {
316
- createTrajectoryReporter(conn, {
317
- trajectorySyncLevel: "full",
318
- sessionDirs: [path.join(tmpDir, "nonexistent")],
319
- });
320
-
321
- const handler = conn.onNotification.mock.calls[0][1];
322
- await handler({ request_id: "req-4", checkpoint_id: "unknown-session-step1" });
323
-
324
- expect(conn.sendNotification).toHaveBeenCalledWith(
325
- "trajectory/content.response",
326
- expect.objectContaining({
327
- request_id: "req-4",
328
- transcript: "",
329
- metadata: expect.objectContaining({ source: "macro-agent" }),
330
- }),
331
- );
332
- });
333
-
334
- it("serves transcripts from ended sessions (content is still valid)", async () => {
335
- const sessionsDir = path.join(tmpDir, "sessions");
336
- const transcript = JSON.stringify({ type: "user", message: "Old session" }) + "\n";
337
-
338
- writeSessionState(sessionsDir, "sess-ended", {
339
- phase: "ended",
340
- }, transcript);
341
-
342
- createTrajectoryReporter(conn, {
343
- trajectorySyncLevel: "full",
344
- sessionDirs: [sessionsDir],
345
- });
346
-
347
- const handler = conn.onNotification.mock.calls[0][1];
348
- await handler({ request_id: "req-5", checkpoint_id: "sess-ended-step1" });
349
-
350
- expect(conn.sendNotification).toHaveBeenCalledWith(
351
- "trajectory/content.response",
352
- expect.objectContaining({
353
- request_id: "req-5",
354
- transcript: expect.stringContaining("Old session"),
355
- }),
356
- );
357
- });
358
-
359
- it("skips sessions with missing transcript path", async () => {
360
- const sessionsDir = path.join(tmpDir, "sessions");
361
-
362
- // Write state without transcript file
363
- writeSessionState(sessionsDir, "sess-no-file", {});
364
-
365
- createTrajectoryReporter(conn, {
366
- trajectorySyncLevel: "full",
367
- sessionDirs: [sessionsDir],
368
- });
369
-
370
- const handler = conn.onNotification.mock.calls[0][1];
371
- await handler({ request_id: "req-6", checkpoint_id: "sess-no-file-step1" });
372
-
373
- const call = conn.sendNotification.mock.calls[0];
374
- expect(call[1]).toHaveProperty("transcript", "");
375
- });
376
-
377
- it("sends error response when content handler throws", async () => {
378
- conn.sendNotification
379
- .mockRejectedValueOnce(new Error("network"))
380
- .mockResolvedValueOnce(undefined);
381
-
382
- createTrajectoryReporter(conn, {
383
- trajectorySyncLevel: "full",
384
- sessionDirs: [path.join(tmpDir, "nonexistent")],
385
- });
386
-
387
- const handler = conn.onNotification.mock.calls[0][1];
388
- await handler({ request_id: "req-7", checkpoint_id: "any" });
389
-
390
- // First call fails, second call sends error response
391
- expect(conn.sendNotification).toHaveBeenCalledTimes(2);
392
- expect(conn.sendNotification).toHaveBeenLastCalledWith(
393
- "trajectory/content.response",
394
- expect.objectContaining({
395
- request_id: "req-7",
396
- error: "Content serving failed",
397
- }),
398
- );
399
- });
400
-
401
- it("searches multiple session directories", async () => {
402
- const dir1 = path.join(tmpDir, "dir1");
403
- const dir2 = path.join(tmpDir, "dir2");
404
- const transcript = JSON.stringify({ type: "user", message: "Found in dir2" }) + "\n";
405
-
406
- // Only dir2 has the session
407
- fs.mkdirSync(dir1, { recursive: true });
408
- writeSessionState(dir2, "sess-multi-dir", {}, transcript);
409
-
410
- createTrajectoryReporter(conn, {
411
- trajectorySyncLevel: "full",
412
- sessionDirs: [dir1, dir2],
413
- });
414
-
415
- const handler = conn.onNotification.mock.calls[0][1];
416
- await handler({ request_id: "req-8", checkpoint_id: "sess-multi-dir-step1" });
417
-
418
- expect(conn.sendNotification).toHaveBeenCalledWith(
419
- "trajectory/content.response",
420
- expect.objectContaining({
421
- transcript: expect.stringContaining("Found in dir2"),
422
- }),
423
- );
424
- });
425
- });