@almyty/acp-server 1.0.10 → 1.0.12
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.
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,81 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { mapStreamEvent, buildPlanFromPipeline, isTerminalEvent, extractFinalOutput } from '../events.js';
|
|
3
|
-
describe('mapStreamEvent', () => {
|
|
4
|
-
it('maps node.started to tool_call with running status', () => {
|
|
5
|
-
const results = mapStreamEvent({ event: 'node.started', data: { nodeId: 'n1', nodeType: 'tool_call', name: 'get_users' } });
|
|
6
|
-
expect(results.length).toBeGreaterThan(0);
|
|
7
|
-
const tc = results.find(r => r.type === 'tool_call');
|
|
8
|
-
expect(tc).toBeDefined();
|
|
9
|
-
expect(tc.status).toBe('running');
|
|
10
|
-
});
|
|
11
|
-
it('maps node.completed to tool_call_update', () => {
|
|
12
|
-
const results = mapStreamEvent({ event: 'node.completed', data: { nodeId: 'n1', output: { users: [] } } });
|
|
13
|
-
expect(results.length).toBeGreaterThan(0);
|
|
14
|
-
const update = results.find(r => r.type === 'tool_call_update');
|
|
15
|
-
expect(update).toBeDefined();
|
|
16
|
-
expect(update.status).toBe('completed');
|
|
17
|
-
});
|
|
18
|
-
it('maps node.error to tool_call_update with error', () => {
|
|
19
|
-
const results = mapStreamEvent({ event: 'node.error', data: { nodeId: 'n1', error: 'timeout' } });
|
|
20
|
-
expect(results.length).toBeGreaterThan(0);
|
|
21
|
-
const update = results.find(r => r.type === 'tool_call_update');
|
|
22
|
-
expect(update).toBeDefined();
|
|
23
|
-
expect(update.status).toBe('error');
|
|
24
|
-
});
|
|
25
|
-
it('maps text events to agent_message_chunk', () => {
|
|
26
|
-
for (const event of ['text', 'message', 'chunk', 'token']) {
|
|
27
|
-
const results = mapStreamEvent({ event, data: { text: 'hello' } });
|
|
28
|
-
expect(results.length).toBeGreaterThan(0);
|
|
29
|
-
expect(results[0].type).toBe('agent_message_chunk');
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
it('maps thinking events to agent_thought_chunk', () => {
|
|
33
|
-
const results = mapStreamEvent({ event: 'thinking', data: { text: 'hmm' } });
|
|
34
|
-
expect(results.length).toBeGreaterThan(0);
|
|
35
|
-
expect(results[0].type).toBe('agent_thought_chunk');
|
|
36
|
-
});
|
|
37
|
-
it('returns empty array for unknown events', () => {
|
|
38
|
-
expect(mapStreamEvent({ event: 'unknown_xyz', data: {} })).toHaveLength(0);
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
describe('buildPlanFromPipeline', () => {
|
|
42
|
-
it('converts pipeline nodes to plan entries (filters input/output)', () => {
|
|
43
|
-
const nodes = [
|
|
44
|
-
{ id: 'n1', type: 'input', data: {} },
|
|
45
|
-
{ id: 'n2', type: 'llm_call', data: {} },
|
|
46
|
-
{ id: 'n3', type: 'tool_call', data: { toolName: 'fetch' } },
|
|
47
|
-
{ id: 'n4', type: 'output', data: {} },
|
|
48
|
-
];
|
|
49
|
-
const plan = buildPlanFromPipeline(nodes);
|
|
50
|
-
expect(plan.type).toBe('plan');
|
|
51
|
-
// input + output filtered out, llm_call + tool_call remain
|
|
52
|
-
expect(plan.entries.length).toBe(2);
|
|
53
|
-
});
|
|
54
|
-
it('returns empty plan for empty pipeline', () => {
|
|
55
|
-
const plan = buildPlanFromPipeline([]);
|
|
56
|
-
expect(plan.entries).toHaveLength(0);
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
describe('isTerminalEvent', () => {
|
|
60
|
-
it('recognizes terminal events', () => {
|
|
61
|
-
expect(isTerminalEvent({ event: 'execution.completed', data: {} })).toBe(true);
|
|
62
|
-
expect(isTerminalEvent({ event: 'execution.error', data: {} })).toBe(true);
|
|
63
|
-
expect(isTerminalEvent({ event: 'run.completed', data: {} })).toBe(true);
|
|
64
|
-
});
|
|
65
|
-
it('rejects non-terminal events', () => {
|
|
66
|
-
expect(isTerminalEvent({ event: 'text', data: {} })).toBe(false);
|
|
67
|
-
expect(isTerminalEvent({ event: 'node.started', data: {} })).toBe(false);
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
describe('extractFinalOutput', () => {
|
|
71
|
-
it('extracts text from output', () => {
|
|
72
|
-
expect(extractFinalOutput({ event: 'execution.completed', data: { output: 'result' } })).toBe('result');
|
|
73
|
-
});
|
|
74
|
-
it('stringifies object output', () => {
|
|
75
|
-
const result = extractFinalOutput({ event: 'execution.completed', data: { output: { key: 'val' } } });
|
|
76
|
-
expect(result).toContain('key');
|
|
77
|
-
});
|
|
78
|
-
it('returns undefined for missing output', () => {
|
|
79
|
-
expect(extractFinalOutput({ event: 'execution.completed', data: {} })).toBeUndefined();
|
|
80
|
-
});
|
|
81
|
-
});
|
|
1
|
+
"use strict";
|
package/dist/agent.js
CHANGED
|
@@ -260,7 +260,6 @@ export class AlmytyAcpAgent {
|
|
|
260
260
|
if (event.event === 'execution.error' || event.event === 'run.error') {
|
|
261
261
|
return {
|
|
262
262
|
stopReason: 'end_turn',
|
|
263
|
-
content: [{ type: 'text', text: collectedText.join('') || 'Execution failed.' }],
|
|
264
263
|
};
|
|
265
264
|
}
|
|
266
265
|
}
|
|
@@ -281,14 +280,12 @@ export class AlmytyAcpAgent {
|
|
|
281
280
|
});
|
|
282
281
|
return {
|
|
283
282
|
stopReason: 'end_turn',
|
|
284
|
-
content: [{ type: 'text', text }],
|
|
285
283
|
};
|
|
286
284
|
}
|
|
287
285
|
catch (invokeErr) {
|
|
288
286
|
const errMsg = invokeErr instanceof Error ? invokeErr.message : String(invokeErr);
|
|
289
287
|
return {
|
|
290
288
|
stopReason: 'end_turn',
|
|
291
|
-
content: [{ type: 'text', text: `Error: ${errMsg}` }],
|
|
292
289
|
};
|
|
293
290
|
}
|
|
294
291
|
}
|
|
@@ -420,7 +417,6 @@ export class AlmytyAcpAgent {
|
|
|
420
417
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
421
418
|
return {
|
|
422
419
|
stopReason: 'end_turn',
|
|
423
|
-
content: [{ type: 'text', text: `Error: ${errMsg}` }],
|
|
424
420
|
};
|
|
425
421
|
}
|
|
426
422
|
}
|
|
@@ -490,9 +486,24 @@ export class AlmytyAcpAgent {
|
|
|
490
486
|
});
|
|
491
487
|
}
|
|
492
488
|
sendSessionUpdate(sessionId, update) {
|
|
489
|
+
// Transform internal format to ACP spec format:
|
|
490
|
+
// - "type" -> "sessionUpdate"
|
|
491
|
+
// - text content wrapped in { type: 'text', text }
|
|
492
|
+
const specUpdate = { ...update };
|
|
493
|
+
if ('type' in specUpdate) {
|
|
494
|
+
specUpdate.sessionUpdate = specUpdate.type;
|
|
495
|
+
delete specUpdate.type;
|
|
496
|
+
}
|
|
497
|
+
// Wrap bare text in content object for message/thought chunks
|
|
498
|
+
if (specUpdate.sessionUpdate === 'agent_message_chunk' || specUpdate.sessionUpdate === 'agent_thought_chunk') {
|
|
499
|
+
if ('text' in specUpdate && !('content' in specUpdate)) {
|
|
500
|
+
specUpdate.content = { type: 'text', text: specUpdate.text };
|
|
501
|
+
delete specUpdate.text;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
493
504
|
this.sendNotification('session/update', {
|
|
494
505
|
sessionId,
|
|
495
|
-
update,
|
|
506
|
+
update: specUpdate,
|
|
496
507
|
});
|
|
497
508
|
}
|
|
498
509
|
/**
|