macro-agent 0.0.16 → 0.1.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.
- package/dist/acp/macro-agent.d.ts +2 -0
- package/dist/acp/macro-agent.d.ts.map +1 -1
- package/dist/acp/macro-agent.js +52 -20
- package/dist/acp/macro-agent.js.map +1 -1
- package/dist/agent/agent-manager.d.ts.map +1 -1
- package/dist/agent/agent-manager.js +23 -5
- package/dist/agent/agent-manager.js.map +1 -1
- package/dist/map/adapter/acp-over-map.d.ts +16 -0
- package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
- package/dist/map/adapter/acp-over-map.js +242 -24
- package/dist/map/adapter/acp-over-map.js.map +1 -1
- package/dist/map/adapter/map-adapter.d.ts +1 -0
- package/dist/map/adapter/map-adapter.d.ts.map +1 -1
- package/dist/map/adapter/map-adapter.js +57 -8
- package/dist/map/adapter/map-adapter.js.map +1 -1
- package/dist/store/event-store.d.ts +5 -0
- package/dist/store/event-store.d.ts.map +1 -1
- package/dist/store/event-store.js +126 -53
- package/dist/store/event-store.js.map +1 -1
- package/dist/store/instance.d.ts +0 -2
- package/dist/store/instance.d.ts.map +1 -1
- package/dist/store/instance.js +1 -24
- package/dist/store/instance.js.map +1 -1
- package/dist/store/types/agents.d.ts +5 -0
- package/dist/store/types/agents.d.ts.map +1 -1
- package/package.json +3 -3
- package/references/acp-factory-ref/package-lock.json +2 -2
- package/references/acp-factory-ref/package.json +2 -2
- package/references/claude-code-acp/package-lock.json +2 -2
- package/references/claude-code-acp/package.json +1 -1
- package/references/claude-code-acp/src/acp-agent.ts +3 -6
- package/src/acp/__tests__/history.test.ts +8 -4
- package/src/acp/macro-agent.ts +60 -26
- package/src/agent/__tests__/agent-manager.test.ts +4 -6
- package/src/agent/agent-manager.ts +24 -5
- package/src/map/adapter/__tests__/acp-over-map-cancel.test.ts +802 -0
- package/src/map/adapter/__tests__/acp-over-map-history.test.ts +1123 -0
- package/src/map/adapter/__tests__/acp-over-map-persistence.e2e.test.ts +440 -0
- package/src/map/adapter/acp-over-map.ts +282 -25
- package/src/map/adapter/map-adapter.ts +79 -9
- package/src/store/__tests__/event-store.test.ts +44 -12
- package/src/store/__tests__/instance.test.ts +5 -7
- package/src/store/event-store.ts +157 -57
- package/src/store/instance.ts +1 -29
- package/src/store/types/agents.ts +1 -0
package/src/acp/macro-agent.ts
CHANGED
|
@@ -75,6 +75,22 @@ import type { RoleRegistry, Capability } from "../roles/types.js";
|
|
|
75
75
|
import { AGENT_CAPABILITIES } from "../roles/capabilities.js";
|
|
76
76
|
import { DefaultRoleRegistry } from "../roles/registry.js";
|
|
77
77
|
|
|
78
|
+
// ─────────────────────────────────────────────────────────────────
|
|
79
|
+
// Helpers
|
|
80
|
+
// ─────────────────────────────────────────────────────────────────
|
|
81
|
+
|
|
82
|
+
/** Extract a plain-text output string from `rawOutput` (string | ContentBlock[] | undefined). */
|
|
83
|
+
function extractToolOutput(rawOutput: unknown): string | undefined {
|
|
84
|
+
if (typeof rawOutput === "string") return rawOutput;
|
|
85
|
+
if (Array.isArray(rawOutput)) {
|
|
86
|
+
return rawOutput
|
|
87
|
+
.filter((item: any) => item.type === "text" && typeof item.text === "string")
|
|
88
|
+
.map((item: any) => item.text as string)
|
|
89
|
+
.join("\n") || undefined;
|
|
90
|
+
}
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
|
|
78
94
|
// ─────────────────────────────────────────────────────────────────
|
|
79
95
|
// Protocol Constants
|
|
80
96
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -157,7 +173,13 @@ export class MacroAgent implements Agent {
|
|
|
157
173
|
/** Accumulates assistant response parts during prompt streaming for history persistence */
|
|
158
174
|
private promptBuffers: Map<
|
|
159
175
|
ACPSessionId,
|
|
160
|
-
{
|
|
176
|
+
{ parts: Array<{ type: "text"; text: string } | ({ type: "tool" } & Record<string, unknown>)> }
|
|
177
|
+
> = new Map();
|
|
178
|
+
|
|
179
|
+
/** Caches tool info (title, name, input) from initial tool_call events per session */
|
|
180
|
+
private toolInfoCaches: Map<
|
|
181
|
+
ACPSessionId,
|
|
182
|
+
Map<string, { title?: string; name?: string; input?: unknown }>
|
|
161
183
|
> = new Map();
|
|
162
184
|
|
|
163
185
|
constructor(connection: AgentSideConnection, config: MacroAgentConfig) {
|
|
@@ -360,8 +382,9 @@ export class MacroAgent implements Agent {
|
|
|
360
382
|
// Mark session as processing (for health monitoring)
|
|
361
383
|
this.sessionMapper.setProcessing(acpSessionId, true);
|
|
362
384
|
|
|
363
|
-
// Initialize prompt buffer for history accumulation
|
|
364
|
-
this.promptBuffers.set(acpSessionId, {
|
|
385
|
+
// Initialize prompt buffer and tool info cache for history accumulation
|
|
386
|
+
this.promptBuffers.set(acpSessionId, { parts: [] });
|
|
387
|
+
this.toolInfoCaches.set(acpSessionId, new Map());
|
|
365
388
|
|
|
366
389
|
try {
|
|
367
390
|
// Stream responses from the agent
|
|
@@ -1396,7 +1419,7 @@ export class MacroAgent implements Agent {
|
|
|
1396
1419
|
console.log(`[MacroAgent] Forwarding ${updateType}`);
|
|
1397
1420
|
}
|
|
1398
1421
|
|
|
1399
|
-
// Accumulate content for history persistence
|
|
1422
|
+
// Accumulate content for history persistence (preserving text/tool interleaving order)
|
|
1400
1423
|
const buffer = this.promptBuffers.get(acpSessionId);
|
|
1401
1424
|
if (buffer) {
|
|
1402
1425
|
if (updateType === "agent_message_chunk") {
|
|
@@ -1404,23 +1427,42 @@ export class MacroAgent implements Agent {
|
|
|
1404
1427
|
| { type?: string; text?: string }
|
|
1405
1428
|
| undefined;
|
|
1406
1429
|
if (content?.text) {
|
|
1407
|
-
buffer.
|
|
1430
|
+
const last = buffer.parts[buffer.parts.length - 1];
|
|
1431
|
+
if (last && last.type === "text") {
|
|
1432
|
+
last.text += content.text;
|
|
1433
|
+
} else {
|
|
1434
|
+
buffer.parts.push({ type: "text", text: content.text });
|
|
1435
|
+
}
|
|
1408
1436
|
}
|
|
1409
1437
|
} else if (
|
|
1410
1438
|
updateType === "tool_call" ||
|
|
1411
1439
|
updateType === "tool_call_update"
|
|
1412
1440
|
) {
|
|
1441
|
+
const toolCallId = sessionUpdate.toolCallId as string | undefined;
|
|
1413
1442
|
const status = sessionUpdate.status as string | undefined;
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
title: sessionUpdate.title,
|
|
1421
|
-
|
|
1443
|
+
const meta = sessionUpdate._meta as { claudeCode?: { toolName?: string } } | undefined;
|
|
1444
|
+
const toolInfoCache = this.toolInfoCaches.get(acpSessionId);
|
|
1445
|
+
|
|
1446
|
+
// Cache tool info from initial tool_call events
|
|
1447
|
+
if (updateType === "tool_call" && toolCallId && toolInfoCache) {
|
|
1448
|
+
toolInfoCache.set(toolCallId, {
|
|
1449
|
+
title: sessionUpdate.title as string | undefined,
|
|
1450
|
+
name: meta?.claudeCode?.toolName,
|
|
1422
1451
|
input: sessionUpdate.rawInput,
|
|
1423
|
-
|
|
1452
|
+
});
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
if (status === "completed" || status === "failed") {
|
|
1456
|
+
// Merge cached info for tool_call_update events that lack title/input
|
|
1457
|
+
const cached = toolCallId ? toolInfoCache?.get(toolCallId) : undefined;
|
|
1458
|
+
buffer.parts.push({
|
|
1459
|
+
type: "tool",
|
|
1460
|
+
toolCallId,
|
|
1461
|
+
title: sessionUpdate.title ?? cached?.title,
|
|
1462
|
+
name: meta?.claudeCode?.toolName ?? cached?.name,
|
|
1463
|
+
status: sessionUpdate.status,
|
|
1464
|
+
input: sessionUpdate.rawInput ?? cached?.input,
|
|
1465
|
+
output: extractToolOutput(sessionUpdate.rawOutput),
|
|
1424
1466
|
});
|
|
1425
1467
|
}
|
|
1426
1468
|
}
|
|
@@ -1627,17 +1669,8 @@ export class MacroAgent implements Agent {
|
|
|
1627
1669
|
});
|
|
1628
1670
|
}
|
|
1629
1671
|
|
|
1630
|
-
// Record assistant turn with accumulated content
|
|
1631
|
-
const
|
|
1632
|
-
const parts: unknown[] = [];
|
|
1633
|
-
|
|
1634
|
-
if (assistantText) {
|
|
1635
|
-
parts.push({ type: "text", text: assistantText });
|
|
1636
|
-
}
|
|
1637
|
-
|
|
1638
|
-
for (const tool of buffer.toolCalls) {
|
|
1639
|
-
parts.push({ type: "tool", ...tool });
|
|
1640
|
-
}
|
|
1672
|
+
// Record assistant turn with accumulated content (parts already in order)
|
|
1673
|
+
const parts = buffer.parts;
|
|
1641
1674
|
|
|
1642
1675
|
if (parts.length > 0) {
|
|
1643
1676
|
this.eventStore.emit({
|
|
@@ -1661,8 +1694,9 @@ export class MacroAgent implements Agent {
|
|
|
1661
1694
|
error instanceof Error ? error.message : String(error),
|
|
1662
1695
|
);
|
|
1663
1696
|
} finally {
|
|
1664
|
-
// Clean up the buffer
|
|
1697
|
+
// Clean up the buffer and tool info cache
|
|
1665
1698
|
this.promptBuffers.delete(acpSessionId);
|
|
1699
|
+
this.toolInfoCaches.delete(acpSessionId);
|
|
1666
1700
|
}
|
|
1667
1701
|
}
|
|
1668
1702
|
|
|
@@ -720,7 +720,7 @@ describe("AgentManager Integration (with mocked acp-factory)", () => {
|
|
|
720
720
|
);
|
|
721
721
|
});
|
|
722
722
|
|
|
723
|
-
it("should
|
|
723
|
+
it("should create new session if provider_session_id is not set", async () => {
|
|
724
724
|
// Create agent directly without provider_session_id
|
|
725
725
|
const agentId = "agent_no_provider";
|
|
726
726
|
const sessionId = "session_no_provider";
|
|
@@ -744,11 +744,9 @@ describe("AgentManager Integration (with mocked acp-factory)", () => {
|
|
|
744
744
|
|
|
745
745
|
await agentManager.resume(agentId);
|
|
746
746
|
|
|
747
|
-
// Should
|
|
748
|
-
expect(mockHandle.
|
|
749
|
-
|
|
750
|
-
"/tmp",
|
|
751
|
-
);
|
|
747
|
+
// Should create a new session instead of loading with invalid macro-agent session_id
|
|
748
|
+
expect(mockHandle.createSession).toHaveBeenCalledWith("/tmp");
|
|
749
|
+
expect(mockHandle.loadSession).not.toHaveBeenCalled();
|
|
752
750
|
});
|
|
753
751
|
});
|
|
754
752
|
|
|
@@ -901,16 +901,34 @@ export function createAgentManager(
|
|
|
901
901
|
);
|
|
902
902
|
}
|
|
903
903
|
|
|
904
|
-
// Spawn new process
|
|
904
|
+
// Spawn new process
|
|
905
905
|
const handle = await AgentFactory.spawn(defaultAgentType, {
|
|
906
906
|
permissionMode: defaultPermissionMode,
|
|
907
907
|
});
|
|
908
908
|
|
|
909
|
-
// Load the existing session using the provider's session ID (e.g., Claude Code UUID)
|
|
910
|
-
// Falls back to macro-agent session_id for backwards compatibility
|
|
911
|
-
const loadSessionId = agent.provider_session_id ?? agent.session_id;
|
|
912
909
|
const agentCwd = agent.cwd ?? defaultCwd;
|
|
913
|
-
|
|
910
|
+
let session;
|
|
911
|
+
|
|
912
|
+
if (agent.provider_session_id) {
|
|
913
|
+
// Load existing session using the provider's session ID (e.g., Claude Code UUID)
|
|
914
|
+
session = await handle.loadSession(agent.provider_session_id, agentCwd);
|
|
915
|
+
} else {
|
|
916
|
+
// No provider session ID available (agent predates this feature or wasn't persisted).
|
|
917
|
+
// Create a new session instead of loading with the macro-agent session_id
|
|
918
|
+
// which is not a valid provider session ID (e.g., Claude Code expects UUIDs).
|
|
919
|
+
session = await handle.createSession(agentCwd);
|
|
920
|
+
|
|
921
|
+
// Store the provider session ID for future resumes
|
|
922
|
+
eventStore.emit({
|
|
923
|
+
type: "status",
|
|
924
|
+
source: { agent_id: agentId },
|
|
925
|
+
payload: {
|
|
926
|
+
status_type: "started",
|
|
927
|
+
summary: "Agent session created (no provider session to resume)",
|
|
928
|
+
provider_session_id: session.id,
|
|
929
|
+
},
|
|
930
|
+
});
|
|
931
|
+
}
|
|
914
932
|
|
|
915
933
|
// Track active session
|
|
916
934
|
const activeSession: ActiveSession = {
|
|
@@ -929,6 +947,7 @@ export function createAgentManager(
|
|
|
929
947
|
payload: {
|
|
930
948
|
status_type: "started",
|
|
931
949
|
summary: "Agent session resumed",
|
|
950
|
+
provider_session_id: session.id,
|
|
932
951
|
},
|
|
933
952
|
});
|
|
934
953
|
|