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
@@ -1,26 +1,21 @@
1
1
  /**
2
2
  * Coordination Handler — dispatches inbound coordination messages from the MAP hub.
3
3
  *
4
- * Task operations use generic MAP scope messages (task.created, task.assigned,
5
- * task.status) matching the wire format used by cc-swarm and opentasks.
6
- * Context sharing and messaging use agent-inbox (not MAP).
7
- * Workspace execution uses x-workspace/* notifications.
4
+ * Handles x-openhive/* JSON-RPC notifications for task assignment, status updates,
5
+ * context sharing, messaging, and workspace execution.
8
6
  *
9
7
  * @module map/coordination-handler
10
8
  */
11
9
 
12
- import { WORKSPACE_METHODS, WORKSPACE_METHODS_LEGACY } from "agent-workspace";
10
+ import type { AgentManager } from "../agent/agent-manager.js";
13
11
  import type { InboxAdapter, TasksAdapter } from "../adapters/types.js";
14
-
15
- /** MAP Message shape (subset of @multi-agent-protocol/sdk Message) */
16
- export interface MAPMessage {
17
- id: string;
18
- from: string;
19
- to: string | { scope: string };
20
- timestamp: string;
21
- payload?: Record<string, unknown>;
22
- meta?: Record<string, unknown>;
23
- }
12
+ import type {
13
+ CoordinationTaskAssign,
14
+ CoordinationTaskStatus,
15
+ CoordinationContextShare,
16
+ CoordinationMessage,
17
+ TrajectoryReporter,
18
+ } from "./types.js";
24
19
 
25
20
  export interface CoordinationConnection {
26
21
  onNotification(
@@ -32,15 +27,14 @@ export interface CoordinationConnection {
32
27
  handler: (params: unknown) => void | Promise<void>,
33
28
  ): void;
34
29
  sendNotification(method: string, params: unknown): Promise<void>;
35
- onMessage(handler: (message: MAPMessage) => void | Promise<void>): void;
36
- offMessage(handler: (message: MAPMessage) => void | Promise<void>): void;
37
30
  }
38
31
 
39
32
  export interface CoordinationDeps {
40
33
  connection: CoordinationConnection;
41
- /** Used by task handlers to notify assignees */
34
+ agentManager: AgentManager;
42
35
  inboxAdapter: InboxAdapter;
43
36
  tasksAdapter: TasksAdapter;
37
+ trajectoryReporter?: TrajectoryReporter;
44
38
  /** Workspace handler from cognitive module (if available) */
45
39
  workspaceHandler?: {
46
40
  handleWorkspaceExecute(params: unknown): Promise<void>;
@@ -48,138 +42,164 @@ export interface CoordinationDeps {
48
42
  };
49
43
  }
50
44
 
51
- /** Notification method constants (workspace only — task/context/message use MAP messages) */
45
+ /** Coordination method constants */
52
46
  const METHODS = {
53
- WORKSPACE_EXECUTE: WORKSPACE_METHODS.EXECUTE,
54
- WORKSPACE_EXECUTE_LEGACY: WORKSPACE_METHODS_LEGACY.EXECUTE,
47
+ TASK_ASSIGN: "x-openhive/task.assign",
48
+ TASK_STATUS: "x-openhive/task.status",
49
+ CONTEXT_SHARE: "x-openhive/context.share",
50
+ MESSAGE_SEND: "x-openhive/message.send",
51
+ WORKSPACE_EXECUTE: "x-openhive/learning.workspace.execute",
55
52
  } as const;
56
53
 
57
54
  /**
58
- * Register coordination handlers on the MAP connection.
59
- *
60
- * Task operations are handled via MAP scope messages (onMessage).
61
- * Context sharing and messaging are handled by agent-inbox (not here).
62
- * Workspace execution uses x-workspace/* notifications.
55
+ * Register coordination notification handlers on the MAP connection.
63
56
  * Returns a cleanup function that removes all handlers.
64
57
  */
65
58
  export function setupCoordinationHandlers(
66
59
  deps: CoordinationDeps,
67
60
  ): () => void {
68
- const { connection, inboxAdapter, tasksAdapter } = deps;
69
- const notificationHandlers: Array<{ method: string; handler: (params: unknown) => void | Promise<void> }> = [];
61
+ const { connection, agentManager, inboxAdapter, tasksAdapter } = deps;
62
+ const handlers: Array<{ method: string; handler: (params: unknown) => void | Promise<void> }> = [];
70
63
 
71
64
  const register = (
72
65
  method: string,
73
66
  handler: (params: unknown) => void | Promise<void>,
74
67
  ): void => {
75
68
  connection.onNotification(method, handler);
76
- notificationHandlers.push({ method, handler });
69
+ handlers.push({ method, handler });
77
70
  };
78
71
 
79
- // =========================================================================
80
- // Task operations generic MAP scope messages
81
- // Wire format matches cc-swarm / opentasks MAP Event Bridge:
82
- // { type: "task.created", task: { id, title, status, assignee } }
83
- // { type: "task.assigned", taskId, assignee }
84
- // { type: "task.status", taskId, previous, current }
85
- // =========================================================================
86
-
87
- const messageHandler = async (message: MAPMessage): Promise<void> => {
88
- const payload = message.payload;
89
- if (!payload || typeof payload.type !== "string") return;
90
-
91
- // Skip messages we originated (echo prevention)
92
- const origin = payload._origin as string | undefined;
93
- if (origin === "macro-agent") return;
72
+ // --- Task Assignment ---
73
+ register(METHODS.TASK_ASSIGN, async (params: unknown) => {
74
+ const p = params as CoordinationTaskAssign;
75
+ if (!p?.title) return;
94
76
 
95
77
  try {
96
- switch (payload.type) {
97
- case "task.created": {
98
- const task = payload.task as
99
- | { id?: string; title?: string; status?: string; assignee?: string }
100
- | undefined;
101
- if (!task?.title) return;
102
-
103
- const taskId = await tasksAdapter.createTask({
104
- title: task.title,
105
- content: (task as Record<string, unknown>).description as string | undefined,
106
- assignee: task.assignee,
78
+ // Create task in opentasks
79
+ const taskId = await tasksAdapter.createTask({
80
+ title: p.title,
81
+ content: p.description,
82
+ assignee: p.assigned_to,
83
+ priority: p.priority === "critical" ? 1 : p.priority === "high" ? 2 : p.priority === "low" ? 4 : 3,
84
+ });
85
+
86
+ // Optionally spawn an agent to work on the task
87
+ if (p.assigned_to) {
88
+ try {
89
+ await inboxAdapter.send("system", p.assigned_to, {
90
+ type: "event",
91
+ event: "TASK_ASSIGNED",
92
+ data: { taskId, title: p.title, description: p.description },
107
93
  });
108
-
109
- if (task.assignee) {
110
- await inboxAdapter
111
- .send("system", task.assignee, {
112
- type: "event",
113
- event: "TASK_ASSIGNED",
114
- data: { taskId, title: task.title },
115
- })
116
- .catch(() => {});
117
- }
118
- break;
94
+ } catch {
95
+ // Agent may not exist locally — that's fine
119
96
  }
97
+ }
98
+ } catch (err) {
99
+ console.warn(
100
+ `[map-sidecar] Failed to handle task.assign: ${(err as Error).message}`,
101
+ );
102
+ }
103
+ });
120
104
 
121
- case "task.assigned": {
122
- const taskId = payload.taskId as string | undefined;
123
- const assignee = payload.assignee as string | undefined;
124
- if (!taskId || !assignee) return;
125
-
126
- await tasksAdapter.assignTask(taskId, assignee);
127
-
128
- await inboxAdapter
129
- .send("system", assignee, {
130
- type: "event",
131
- event: "TASK_ASSIGNED",
132
- data: { taskId },
133
- })
134
- .catch(() => {});
135
- break;
136
- }
105
+ // --- Task Status ---
106
+ register(METHODS.TASK_STATUS, async (params: unknown) => {
107
+ const p = params as CoordinationTaskStatus;
108
+ if (!p?.task_id || !p?.status) return;
137
109
 
138
- case "task.status": {
139
- const taskId = payload.taskId as string | undefined;
140
- const current = payload.current as string | undefined;
141
- if (!taskId || !current) return;
142
-
143
- const actionMap: Record<string, string> = {
144
- in_progress: "start",
145
- completed: "complete",
146
- closed: "complete",
147
- failed: "fail",
148
- blocked: "block",
149
- open: "reopen",
150
- };
151
- const action = actionMap[current];
152
- if (action) {
153
- await tasksAdapter.transitionTask(taskId, action as any);
154
- }
155
- break;
156
- }
110
+ try {
111
+ const actionMap: Record<string, string> = {
112
+ in_progress: "start",
113
+ completed: "complete",
114
+ closed: "complete",
115
+ failed: "fail",
116
+ blocked: "block",
117
+ open: "reopen",
118
+ };
119
+ const action = actionMap[p.status];
120
+ if (action) {
121
+ await tasksAdapter.transitionTask(p.task_id, action as any);
122
+ }
123
+ } catch (err) {
124
+ console.warn(
125
+ `[map-sidecar] Failed to handle task.status: ${(err as Error).message}`,
126
+ );
127
+ }
128
+ });
157
129
 
158
- // Context sharing and messaging are handled by agent-inbox directly
159
- // (not through MAP scope messages). See InboxAdapter for broadcast
160
- // scope delivery and agent-to-agent messaging.
130
+ // --- Context Share ---
131
+ register(METHODS.CONTEXT_SHARE, async (params: unknown) => {
132
+ const p = params as CoordinationContextShare;
133
+ if (!p?.context_type || !p?.data) return;
161
134
 
162
- // Ignore other message types (e.g., task.completed is informational)
163
- default:
164
- break;
135
+ try {
136
+ // Deliver context to all running agents via inbox
137
+ const agents = agentManager.list()
138
+ .filter((a: any) => a.state === "running");
139
+ for (const agent of agents) {
140
+ await inboxAdapter
141
+ .send("system", agent.id, {
142
+ type: "event",
143
+ event: "CONTEXT_SHARED",
144
+ data: {
145
+ context_type: p.context_type,
146
+ data: p.data,
147
+ source: p.source_swarm_id,
148
+ },
149
+ })
150
+ .catch(() => {});
165
151
  }
166
152
  } catch (err) {
167
153
  console.warn(
168
- `[map-sidecar] Failed to handle ${payload.type}: ${(err as Error).message}`,
154
+ `[map-sidecar] Failed to handle context.share: ${(err as Error).message}`,
169
155
  );
170
156
  }
171
- };
157
+ });
172
158
 
173
- connection.onMessage(messageHandler);
159
+ // --- Message Send ---
160
+ register(METHODS.MESSAGE_SEND, async (params: unknown) => {
161
+ const p = params as CoordinationMessage;
162
+ if (!p?.content) return;
174
163
 
175
- // =========================================================================
176
- // Workspace JSON-RPC notifications (x-workspace protocol)
177
- // =========================================================================
164
+ try {
165
+ const agents = agentManager.list()
166
+ .filter((a: any) => a.state === "running");
167
+ if (agents.length === 0) return;
168
+
169
+ // Route to the best target:
170
+ // 1. If to_swarm_id matches a local agent ID, send directly
171
+ // 2. If metadata has a target_agent hint, use it
172
+ // 3. Otherwise, send to the coordinator/head manager (parentless agent)
173
+ // 4. Fallback: first running agent
174
+ const targetId = p.to_swarm_id;
175
+ const directTarget = targetId
176
+ ? agents.find((a: any) => a.id === targetId)
177
+ : undefined;
178
+ const coordinator = agents.find((a: any) => !a.parent);
179
+ const target = directTarget ?? coordinator ?? agents[0];
180
+
181
+ await inboxAdapter.send("system", target.id, {
182
+ type: "event",
183
+ event: "EXTERNAL_MESSAGE",
184
+ data: {
185
+ from: p.from_swarm_id,
186
+ content_type: p.content_type,
187
+ content: p.content,
188
+ reply_to: p.reply_to,
189
+ metadata: p.metadata,
190
+ },
191
+ });
192
+ } catch (err) {
193
+ console.warn(
194
+ `[map-sidecar] Failed to handle message.send: ${(err as Error).message}`,
195
+ );
196
+ }
197
+ });
178
198
 
179
199
  // --- Workspace Execute (delegate to cognitive module) ---
180
200
  if (deps.workspaceHandler) {
181
201
  const wh = deps.workspaceHandler;
182
- const workspaceHandler = async (params: unknown) => {
202
+ register(METHODS.WORKSPACE_EXECUTE, async (params: unknown) => {
183
203
  try {
184
204
  await wh.handleWorkspaceExecute(params);
185
205
  } catch (err) {
@@ -187,17 +207,14 @@ export function setupCoordinationHandlers(
187
207
  `[map-sidecar] Failed to handle workspace.execute: ${(err as Error).message}`,
188
208
  );
189
209
  }
190
- };
191
- register(METHODS.WORKSPACE_EXECUTE, workspaceHandler);
192
- register(METHODS.WORKSPACE_EXECUTE_LEGACY, workspaceHandler);
210
+ });
193
211
  }
194
212
 
195
213
  // Return cleanup function
196
214
  return () => {
197
- connection.offMessage(messageHandler);
198
- for (const { method, handler } of notificationHandlers) {
215
+ for (const { method, handler } of handlers) {
199
216
  connection.offNotification(method, handler);
200
217
  }
201
- notificationHandlers.length = 0;
218
+ handlers.length = 0;
202
219
  };
203
220
  }
@@ -107,6 +107,10 @@ export function createMAPSidecar(
107
107
  role: "sidecar",
108
108
  scopes: [scope],
109
109
  capabilities: {
110
+ messaging: { canSend: true, canReceive: true },
111
+ mail: { canCreate: true, canJoin: true, canViewHistory: true },
112
+ protocols: ['acp'],
113
+ acp: { version: '2024-10-07' },
110
114
  trajectory: { canReport: true, canServeContent: false },
111
115
  tasks: {
112
116
  canCreate: true,
@@ -253,31 +257,14 @@ export function createMAPSidecar(
253
257
  const { createTrajectoryReporter } = await import("./trajectory-reporter.js");
254
258
  trajectoryReporter = createTrajectoryReporter(connection, config);
255
259
 
256
- // 4. Workspace Handler (for x-workspace/task.execute)
257
- const { MacroAgentBackend } = await import("../cognitive/macro-agent-backend.js");
258
- const { handleWorkspaceExecute, isWorkspaceExecuteMessage } = await import("../cognitive/workspace-handler.js");
259
- const workspaceBackend = new MacroAgentBackend(agentManager, {});
260
- const sendToHub = (msg: { method?: string; params?: unknown }) => {
261
- if (msg.method && msg.params) {
262
- connection.sendNotification(msg.method, msg.params as Record<string, unknown>);
263
- }
264
- };
265
- const workspaceHandler = {
266
- handleWorkspaceExecute: (params: unknown) =>
267
- handleWorkspaceExecute(
268
- { backend: workspaceBackend, sendToHub },
269
- params as import("agent-workspace").WorkspaceExecuteParams,
270
- ),
271
- isWorkspaceExecuteMessage,
272
- };
273
-
274
- // 5. Coordination Handler
260
+ // 4. Coordination Handler
275
261
  const { setupCoordinationHandlers } = await import("./coordination-handler.js");
276
262
  coordinationCleanup = setupCoordinationHandlers({
277
263
  connection,
264
+ agentManager,
278
265
  inboxAdapter,
279
266
  tasksAdapter,
280
- workspaceHandler,
267
+ trajectoryReporter,
281
268
  });
282
269
  }
283
270
 
@@ -2,10 +2,8 @@
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
  */
@@ -36,173 +34,37 @@ export interface TrajectoryConnection {
36
34
  get isConnected(): boolean;
37
35
  }
38
36
 
39
- /**
40
- * Resolve transcript content for a checkpoint ID using sessionlog.
41
- *
42
- * Two-source strategy (matching cc-swarm):
43
- * 1. Live session — use sessionlog's SessionStore to find a session
44
- * matching the checkpoint ID, then read its transcript from disk.
45
- * 2. Committed checkpoint — use sessionlog's CheckpointStore to read
46
- * content from the git history.
47
- *
48
- * Returns null if no content is found or sessionlog is unavailable.
49
- */
50
- async function resolveContent(
51
- checkpointId: string,
52
- sessionDirs: string[],
53
- ): Promise<{
54
- transcript: string;
55
- metadata: Record<string, unknown>;
56
- prompts: string;
57
- context: string;
58
- } | null> {
59
- let sessionlog: typeof import("sessionlog") | null = null;
60
- try {
61
- sessionlog = await import("sessionlog");
62
- } catch {
63
- return null; // sessionlog not available
64
- }
65
-
66
- const { readFileSync, existsSync } = await import("node:fs");
67
-
68
- // Derive the session ID from checkpoint ID (e.g., "sess-abc-step3" → "sess-abc")
69
- const sessionId = checkpointId.replace(/-step\d+$/, "");
70
-
71
- // ── 1. Live session lookup via SessionStore ────────────────────────────
72
- for (const sessionsDir of sessionDirs) {
73
- if (!existsSync(sessionsDir)) continue;
74
-
75
- try {
76
- const store = sessionlog.createSessionStore(undefined, sessionsDir);
77
- // Try loading by derived session ID first, then by raw checkpoint ID
78
- let state = await store.load(sessionId);
79
- if (!state) state = await store.load(checkpointId);
80
-
81
- // If not found by ID, scan all sessions for checkpoint match
82
- if (!state) {
83
- const allSessions = await store.list();
84
- state = allSessions.find((s) =>
85
- s.lastCheckpointID === checkpointId ||
86
- (s.turnCheckpointIDs || []).includes(checkpointId),
87
- ) ?? null;
88
- }
89
-
90
- if (!state?.transcriptPath || !existsSync(state.transcriptPath)) continue;
91
-
92
- const transcript = readFileSync(state.transcriptPath, "utf-8");
93
-
94
- // Use sessionlog's prompt extraction if the agent has a TranscriptAnalyzer,
95
- // otherwise fall back to the prompts stored in state
96
- let prompts = "";
97
- if (state.firstPrompt) {
98
- // Collect from promptAttributions if available, otherwise use firstPrompt
99
- const attrs = state.promptAttributions;
100
- if (attrs && attrs.length > 0) {
101
- prompts = attrs.map((a) => a.prompt).join("\n---\n");
102
- } else {
103
- prompts = state.firstPrompt;
104
- }
105
- }
106
-
107
- return {
108
- transcript,
109
- prompts,
110
- metadata: {
111
- sessionID: state.sessionID,
112
- phase: state.phase,
113
- agentType: state.agentType,
114
- stepCount: state.stepCount || 0,
115
- filesTouched: state.filesTouched || [],
116
- tokenUsage: state.tokenUsage || {},
117
- startedAt: state.startedAt,
118
- endedAt: state.endedAt,
119
- source: "live",
120
- },
121
- context: `Session ${state.sessionID} (${state.phase})`,
122
- };
123
- } catch {
124
- continue;
125
- }
126
- }
127
-
128
- // ── 2. Committed checkpoint via CheckpointStore ────────────────────────
129
- try {
130
- if (sessionlog.createCheckpointStore) {
131
- const store = sessionlog.createCheckpointStore();
132
- const content = await store.readSessionContent(checkpointId, 0);
133
- if (content) {
134
- return {
135
- transcript: content.transcript,
136
- prompts: content.prompts,
137
- metadata: { ...content.metadata, source: "committed" },
138
- context: content.context,
139
- };
140
- }
141
- }
142
- } catch {
143
- // Checkpoint not found or store unavailable
144
- }
145
-
146
- return null;
147
- }
148
-
149
37
  /**
150
38
  * Create a trajectory reporter that sends checkpoints to the MAP hub
151
- * and serves session transcript content on demand via sessionlog.
39
+ * and serves content on demand.
152
40
  */
153
41
  export function createTrajectoryReporter(
154
42
  connection: TrajectoryConnection,
155
- config: Pick<MAPSidecarConfig, "trajectorySyncLevel"> & {
156
- /** Additional session directories to search for transcripts */
157
- sessionDirs?: string[];
158
- },
43
+ config: Pick<MAPSidecarConfig, "trajectorySyncLevel">,
159
44
  ): TrajectoryReporter {
160
45
  // Cache the resource_id from the first checkpoint response
161
46
  // so subsequent calls reuse it (avoids creating duplicate session resources)
162
47
  let cachedResourceId: string | undefined;
163
48
 
164
- // Build session directory search list
165
- const defaultDirs: string[] = [];
166
- try {
167
- const cwd = process.cwd();
168
- defaultDirs.push(
169
- `${cwd}/.git/sessionlog-sessions`,
170
- `${cwd}/.swarm/sessionlog/sessions`,
171
- );
172
- } catch {
173
- // Can't resolve paths — will use config dirs only
174
- }
175
- const sessionDirs = [...(config.sessionDirs ?? []), ...defaultDirs];
176
-
177
49
  // Handler for inbound content requests
178
50
  const contentHandler = async (params: unknown): Promise<void> => {
179
51
  const req = params as TrajectoryContentRequest;
180
52
  if (!req?.request_id) return;
181
53
 
182
54
  try {
183
- const content = await resolveContent(
184
- req.checkpoint_id,
185
- sessionDirs,
186
- );
187
-
188
- if (content) {
189
- await connection.sendNotification("trajectory/content.response", {
190
- request_id: req.request_id,
191
- transcript: content.transcript,
192
- metadata: content.metadata,
193
- prompts: content.prompts,
194
- context: content.context,
195
- });
196
- } else {
197
- await connection.sendNotification("trajectory/content.response", {
198
- request_id: req.request_id,
199
- transcript: "",
200
- metadata: { source: "macro-agent" },
201
- prompts: "",
202
- context: "",
203
- });
204
- }
55
+ // Respond with what we have — macro-agent doesn't store full transcripts
56
+ // like sessionlog does, so we send a minimal response.
57
+ // Future: integrate with ACP session history for richer content.
58
+ await connection.sendNotification("trajectory/content.response", {
59
+ request_id: req.request_id,
60
+ transcript: null,
61
+ metadata: {
62
+ source: "macro-agent",
63
+ note: "Full transcript serving not yet implemented",
64
+ },
65
+ });
205
66
  } catch {
67
+ // Best effort
206
68
  try {
207
69
  await connection.sendNotification("trajectory/content.response", {
208
70
  request_id: req.request_id,
package/src/map/types.ts CHANGED
@@ -145,8 +145,46 @@ export interface TrajectoryContentRequest {
145
145
  // Coordination Wire Format
146
146
  // =============================================================================
147
147
 
148
- // Coordination uses generic MAP scope messages — see coordination-handler.ts.
149
- // Wire format types are inlined there; no custom types needed here.
148
+ /** Inbound task assignment from hub */
149
+ export interface CoordinationTaskAssign {
150
+ title: string;
151
+ description?: string;
152
+ assigned_to?: string;
153
+ assigned_by: string;
154
+ priority?: string;
155
+ context?: Record<string, unknown>;
156
+ deadline?: string;
157
+ }
158
+
159
+ /** Inbound task status update from hub */
160
+ export interface CoordinationTaskStatus {
161
+ task_id: string;
162
+ status: string;
163
+ progress?: number;
164
+ result?: unknown;
165
+ error?: string;
166
+ }
167
+
168
+ /** Inbound context share from hub */
169
+ export interface CoordinationContextShare {
170
+ hive_id?: string;
171
+ source_swarm_id: string;
172
+ context_type: string;
173
+ data: unknown;
174
+ target_swarm_ids?: string[];
175
+ ttl_seconds?: number;
176
+ }
177
+
178
+ /** Inbound message from hub */
179
+ export interface CoordinationMessage {
180
+ hive_id?: string;
181
+ from_swarm_id: string;
182
+ to_swarm_id: string;
183
+ content_type: string;
184
+ content: unknown;
185
+ reply_to?: string;
186
+ metadata?: Record<string, unknown>;
187
+ }
150
188
 
151
189
  // =============================================================================
152
190
  // Internal Bridge Types