@roj-ai/sdk 0.1.13 → 0.1.15
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/bootstrap.d.ts +13 -0
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +3 -1
- package/dist/bootstrap.js.map +1 -1
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -0
- package/dist/config.js.map +1 -1
- package/dist/core/agents/agent.d.ts +25 -1
- package/dist/core/agents/agent.d.ts.map +1 -1
- package/dist/core/agents/agent.js +117 -21
- package/dist/core/agents/agent.js.map +1 -1
- package/dist/core/agents/config.d.ts +7 -0
- package/dist/core/agents/config.d.ts.map +1 -1
- package/dist/core/agents/context.d.ts +10 -0
- package/dist/core/agents/context.d.ts.map +1 -1
- package/dist/core/agents/state.d.ts +11 -3
- package/dist/core/agents/state.d.ts.map +1 -1
- package/dist/core/agents/state.js.map +1 -1
- package/dist/core/file-store/file-store.d.ts +5 -1
- package/dist/core/file-store/file-store.d.ts.map +1 -1
- package/dist/core/file-store/file-store.js +31 -21
- package/dist/core/file-store/file-store.js.map +1 -1
- package/dist/core/image/vips-resizer.test.js +26 -14
- package/dist/core/image/vips-resizer.test.js.map +1 -1
- package/dist/core/llm/anthropic.d.ts.map +1 -1
- package/dist/core/llm/anthropic.js +11 -8
- package/dist/core/llm/anthropic.js.map +1 -1
- package/dist/core/llm/cache-breakpoints.d.ts +5 -1
- package/dist/core/llm/cache-breakpoints.d.ts.map +1 -1
- package/dist/core/llm/cache-breakpoints.js +10 -5
- package/dist/core/llm/cache-breakpoints.js.map +1 -1
- package/dist/core/sessions/session.d.ts.map +1 -1
- package/dist/core/sessions/session.js +10 -0
- package/dist/core/sessions/session.js.map +1 -1
- package/dist/core/sessions/session.test.js +5 -0
- package/dist/core/sessions/session.test.js.map +1 -1
- package/dist/core/sessions/state.d.ts.map +1 -1
- package/dist/core/sessions/state.js +5 -1
- package/dist/core/sessions/state.js.map +1 -1
- package/dist/core/tools/executor.test.js +1 -0
- package/dist/core/tools/executor.test.js.map +1 -1
- package/dist/lib/utils/concurrency.d.ts +25 -0
- package/dist/lib/utils/concurrency.d.ts.map +1 -0
- package/dist/lib/utils/concurrency.js +69 -0
- package/dist/lib/utils/concurrency.js.map +1 -0
- package/dist/lib/utils/concurrency.test.d.ts +2 -0
- package/dist/lib/utils/concurrency.test.d.ts.map +1 -0
- package/dist/lib/utils/concurrency.test.js +135 -0
- package/dist/lib/utils/concurrency.test.js.map +1 -0
- package/dist/plugins/agent-status/plugin.d.ts.map +1 -1
- package/dist/plugins/agent-status/plugin.js +18 -26
- package/dist/plugins/agent-status/plugin.js.map +1 -1
- package/dist/plugins/context-compact/compaction-live.test.d.ts +17 -0
- package/dist/plugins/context-compact/compaction-live.test.d.ts.map +1 -0
- package/dist/plugins/context-compact/compaction-live.test.js +177 -0
- package/dist/plugins/context-compact/compaction-live.test.js.map +1 -0
- package/dist/plugins/context-compact/context-compact.integration.test.js +123 -3
- package/dist/plugins/context-compact/context-compact.integration.test.js.map +1 -1
- package/dist/plugins/context-compact/context-compactor.d.ts +47 -17
- package/dist/plugins/context-compact/context-compactor.d.ts.map +1 -1
- package/dist/plugins/context-compact/context-compactor.js +60 -36
- package/dist/plugins/context-compact/context-compactor.js.map +1 -1
- package/dist/plugins/context-compact/context-compactor.test.js +69 -103
- package/dist/plugins/context-compact/context-compactor.test.js.map +1 -1
- package/dist/plugins/context-compact/plugin.d.ts +9 -2
- package/dist/plugins/context-compact/plugin.d.ts.map +1 -1
- package/dist/plugins/context-compact/plugin.js +8 -4
- package/dist/plugins/context-compact/plugin.js.map +1 -1
- package/dist/plugins/filesystem/filesystem.integration.test.js +36 -0
- package/dist/plugins/filesystem/filesystem.integration.test.js.map +1 -1
- package/dist/plugins/filesystem/plugin.d.ts.map +1 -1
- package/dist/plugins/filesystem/plugin.js +8 -6
- package/dist/plugins/filesystem/plugin.js.map +1 -1
- package/dist/plugins/mailbox/mailbox.integration.test.js +9 -16
- package/dist/plugins/mailbox/mailbox.integration.test.js.map +1 -1
- package/dist/plugins/resources/plugin.d.ts.map +1 -1
- package/dist/plugins/resources/plugin.js +4 -1
- package/dist/plugins/resources/plugin.js.map +1 -1
- package/dist/plugins/uploads/plugin.d.ts +12 -0
- package/dist/plugins/uploads/plugin.d.ts.map +1 -1
- package/dist/plugins/uploads/plugin.js +188 -44
- package/dist/plugins/uploads/plugin.js.map +1 -1
- package/dist/plugins/uploads/preprocessors/image-classifier.d.ts +9 -0
- package/dist/plugins/uploads/preprocessors/image-classifier.d.ts.map +1 -1
- package/dist/plugins/uploads/preprocessors/image-classifier.js +4 -1
- package/dist/plugins/uploads/preprocessors/image-classifier.js.map +1 -1
- package/dist/plugins/uploads/preprocessors/image-classifier.test.d.ts +2 -0
- package/dist/plugins/uploads/preprocessors/image-classifier.test.d.ts.map +1 -0
- package/dist/plugins/uploads/preprocessors/image-classifier.test.js +113 -0
- package/dist/plugins/uploads/preprocessors/image-classifier.test.js.map +1 -0
- package/dist/plugins/uploads/preprocessors/markitdown-preprocessor.d.ts.map +1 -1
- package/dist/plugins/uploads/preprocessors/markitdown-preprocessor.js +8 -7
- package/dist/plugins/uploads/preprocessors/markitdown-preprocessor.js.map +1 -1
- package/dist/plugins/uploads/preprocessors/zip-preprocessor.d.ts.map +1 -1
- package/dist/plugins/uploads/preprocessors/zip-preprocessor.js +35 -15
- package/dist/plugins/uploads/preprocessors/zip-preprocessor.js.map +1 -1
- package/dist/plugins/uploads/state.d.ts +1 -0
- package/dist/plugins/uploads/state.d.ts.map +1 -1
- package/dist/plugins/uploads/state.js +1 -1
- package/dist/plugins/uploads/state.js.map +1 -1
- package/dist/plugins/uploads/uploads.integration.test.js +97 -0
- package/dist/plugins/uploads/uploads.integration.test.js.map +1 -1
- package/dist/plugins/user-chat/plugin.d.ts +2 -0
- package/dist/plugins/user-chat/plugin.d.ts.map +1 -1
- package/dist/plugins/user-chat/plugin.js +47 -3
- package/dist/plugins/user-chat/plugin.js.map +1 -1
- package/dist/plugins/user-chat/schema.d.ts +10 -0
- package/dist/plugins/user-chat/schema.d.ts.map +1 -1
- package/dist/plugins/user-chat/schema.js +1 -0
- package/dist/plugins/user-chat/schema.js.map +1 -1
- package/dist/plugins/user-chat/user-chat.integration.test.js +86 -0
- package/dist/plugins/user-chat/user-chat.integration.test.js.map +1 -1
- package/dist/transport/http/routes/upload.d.ts.map +1 -1
- package/dist/transport/http/routes/upload.js +60 -0
- package/dist/transport/http/routes/upload.js.map +1 -1
- package/package.json +2 -2
- package/src/bootstrap.ts +3 -1
- package/src/config.ts +6 -0
- package/src/core/agents/agent.ts +134 -20
- package/src/core/agents/config.ts +7 -0
- package/src/core/agents/context.ts +11 -0
- package/src/core/agents/state.ts +11 -4
- package/src/core/file-store/file-store.ts +38 -18
- package/src/core/image/vips-resizer.test.ts +26 -15
- package/src/core/llm/anthropic.ts +19 -12
- package/src/core/llm/cache-breakpoints.ts +15 -6
- package/src/core/sessions/session.test.ts +6 -0
- package/src/core/sessions/session.ts +12 -0
- package/src/core/sessions/state.ts +5 -1
- package/src/core/tools/executor.test.ts +1 -0
- package/src/lib/utils/concurrency.test.ts +169 -0
- package/src/lib/utils/concurrency.ts +72 -0
- package/src/plugins/agent-status/plugin.ts +18 -25
- package/src/plugins/context-compact/compaction-live.test.ts +221 -0
- package/src/plugins/context-compact/context-compact.integration.test.ts +135 -3
- package/src/plugins/context-compact/context-compactor.test.ts +71 -110
- package/src/plugins/context-compact/context-compactor.ts +88 -43
- package/src/plugins/context-compact/plugin.ts +19 -10
- package/src/plugins/filesystem/filesystem.integration.test.ts +44 -0
- package/src/plugins/filesystem/plugin.ts +8 -6
- package/src/plugins/mailbox/mailbox.integration.test.ts +12 -18
- package/src/plugins/resources/plugin.ts +4 -1
- package/src/plugins/uploads/plugin.ts +212 -47
- package/src/plugins/uploads/preprocessors/image-classifier.test.ts +142 -0
- package/src/plugins/uploads/preprocessors/image-classifier.ts +13 -1
- package/src/plugins/uploads/preprocessors/markitdown-preprocessor.ts +8 -8
- package/src/plugins/uploads/preprocessors/zip-preprocessor.ts +37 -17
- package/src/plugins/uploads/state.ts +1 -1
- package/src/plugins/uploads/uploads.integration.test.ts +123 -0
- package/src/plugins/user-chat/plugin.ts +60 -3
- package/src/plugins/user-chat/schema.ts +10 -1
- package/src/plugins/user-chat/user-chat.integration.test.ts +99 -0
- package/src/transport/http/routes/upload.ts +87 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"concurrency.test.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/concurrency.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { describe, expect, it } from 'bun:test';
|
|
2
|
+
import { mapWithConcurrency, Semaphore } from './concurrency.js';
|
|
3
|
+
function defer() {
|
|
4
|
+
let resolve;
|
|
5
|
+
let reject;
|
|
6
|
+
const promise = new Promise((res, rej) => {
|
|
7
|
+
resolve = res;
|
|
8
|
+
reject = rej;
|
|
9
|
+
});
|
|
10
|
+
return { promise, resolve, reject };
|
|
11
|
+
}
|
|
12
|
+
describe('mapWithConcurrency', () => {
|
|
13
|
+
it('preserves input order regardless of completion order', async () => {
|
|
14
|
+
const delays = [50, 10, 30, 5, 20];
|
|
15
|
+
const results = await mapWithConcurrency(delays, 3, async (ms, i) => {
|
|
16
|
+
await new Promise(r => setTimeout(r, ms));
|
|
17
|
+
return `${i}:${ms}`;
|
|
18
|
+
});
|
|
19
|
+
expect(results).toEqual(['0:50', '1:10', '2:30', '3:5', '4:20']);
|
|
20
|
+
});
|
|
21
|
+
it('does not exceed the concurrency limit', async () => {
|
|
22
|
+
let active = 0;
|
|
23
|
+
let peak = 0;
|
|
24
|
+
const items = Array.from({ length: 20 }, (_, i) => i);
|
|
25
|
+
await mapWithConcurrency(items, 4, async () => {
|
|
26
|
+
active++;
|
|
27
|
+
peak = Math.max(peak, active);
|
|
28
|
+
await new Promise(r => setTimeout(r, 5));
|
|
29
|
+
active--;
|
|
30
|
+
});
|
|
31
|
+
expect(peak).toBeLessThanOrEqual(4);
|
|
32
|
+
expect(peak).toBe(4);
|
|
33
|
+
});
|
|
34
|
+
it('handles empty input without spawning workers', async () => {
|
|
35
|
+
let calls = 0;
|
|
36
|
+
const results = await mapWithConcurrency([], 5, async () => {
|
|
37
|
+
calls++;
|
|
38
|
+
return 1;
|
|
39
|
+
});
|
|
40
|
+
expect(results).toEqual([]);
|
|
41
|
+
expect(calls).toBe(0);
|
|
42
|
+
});
|
|
43
|
+
it('caps worker count at item count when concurrency > items', async () => {
|
|
44
|
+
let active = 0;
|
|
45
|
+
let peak = 0;
|
|
46
|
+
const items = [1, 2];
|
|
47
|
+
await mapWithConcurrency(items, 10, async () => {
|
|
48
|
+
active++;
|
|
49
|
+
peak = Math.max(peak, active);
|
|
50
|
+
await new Promise(r => setTimeout(r, 5));
|
|
51
|
+
active--;
|
|
52
|
+
});
|
|
53
|
+
expect(peak).toBe(2);
|
|
54
|
+
});
|
|
55
|
+
it('propagates errors thrown by the worker fn', async () => {
|
|
56
|
+
await expect(mapWithConcurrency([1, 2, 3], 2, async (n) => {
|
|
57
|
+
if (n === 2)
|
|
58
|
+
throw new Error('boom');
|
|
59
|
+
return n;
|
|
60
|
+
})).rejects.toThrow('boom');
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
describe('Semaphore', () => {
|
|
64
|
+
it('rejects invalid limits', () => {
|
|
65
|
+
expect(() => new Semaphore(0)).toThrow();
|
|
66
|
+
expect(() => new Semaphore(-1)).toThrow();
|
|
67
|
+
expect(() => new Semaphore(1.5)).toThrow();
|
|
68
|
+
});
|
|
69
|
+
it('caps concurrent executions at limit', async () => {
|
|
70
|
+
const gate = new Semaphore(3);
|
|
71
|
+
let active = 0;
|
|
72
|
+
let peak = 0;
|
|
73
|
+
const tasks = Array.from({ length: 12 }, () => gate.run(async () => {
|
|
74
|
+
active++;
|
|
75
|
+
peak = Math.max(peak, active);
|
|
76
|
+
await new Promise(r => setTimeout(r, 10));
|
|
77
|
+
active--;
|
|
78
|
+
}));
|
|
79
|
+
await Promise.all(tasks);
|
|
80
|
+
expect(peak).toBe(3);
|
|
81
|
+
expect(active).toBe(0);
|
|
82
|
+
});
|
|
83
|
+
it('admits waiters in FIFO order', async () => {
|
|
84
|
+
const gate = new Semaphore(1);
|
|
85
|
+
const order = [];
|
|
86
|
+
const blocker = defer();
|
|
87
|
+
// Hold the only slot
|
|
88
|
+
const held = gate.run(async () => {
|
|
89
|
+
await blocker.promise;
|
|
90
|
+
});
|
|
91
|
+
// Queue three waiters in known order, with their own blockers so the test
|
|
92
|
+
// can observe entry order without relying on real timers.
|
|
93
|
+
const gates = [defer(), defer(), defer()];
|
|
94
|
+
const queued = gates.map((g, i) => gate.run(async () => {
|
|
95
|
+
order.push(i);
|
|
96
|
+
await g.promise;
|
|
97
|
+
}));
|
|
98
|
+
// Yield so all three are queued.
|
|
99
|
+
await new Promise(r => setTimeout(r, 0));
|
|
100
|
+
expect(order).toEqual([]);
|
|
101
|
+
// Release the holder; waiter 0 should run first.
|
|
102
|
+
blocker.resolve();
|
|
103
|
+
await new Promise(r => setTimeout(r, 0));
|
|
104
|
+
expect(order).toEqual([0]);
|
|
105
|
+
gates[0].resolve();
|
|
106
|
+
await new Promise(r => setTimeout(r, 0));
|
|
107
|
+
expect(order).toEqual([0, 1]);
|
|
108
|
+
gates[1].resolve();
|
|
109
|
+
await new Promise(r => setTimeout(r, 0));
|
|
110
|
+
expect(order).toEqual([0, 1, 2]);
|
|
111
|
+
gates[2].resolve();
|
|
112
|
+
await Promise.all([held, ...queued]);
|
|
113
|
+
});
|
|
114
|
+
it('releases the slot when the body throws', async () => {
|
|
115
|
+
const gate = new Semaphore(1);
|
|
116
|
+
await expect(gate.run(async () => {
|
|
117
|
+
throw new Error('boom');
|
|
118
|
+
})).rejects.toThrow('boom');
|
|
119
|
+
// Slot must be free again — this would deadlock otherwise.
|
|
120
|
+
const result = await gate.run(async () => 42);
|
|
121
|
+
expect(result).toBe(42);
|
|
122
|
+
});
|
|
123
|
+
it('serializes work under limit=1', async () => {
|
|
124
|
+
const gate = new Semaphore(1);
|
|
125
|
+
const events = [];
|
|
126
|
+
const tasks = [0, 1, 2].map(i => gate.run(async () => {
|
|
127
|
+
events.push(`start:${i}`);
|
|
128
|
+
await new Promise(r => setTimeout(r, 5));
|
|
129
|
+
events.push(`end:${i}`);
|
|
130
|
+
}));
|
|
131
|
+
await Promise.all(tasks);
|
|
132
|
+
expect(events).toEqual(['start:0', 'end:0', 'start:1', 'end:1', 'start:2', 'end:2']);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
//# sourceMappingURL=concurrency.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"concurrency.test.js","sourceRoot":"","sources":["../../../src/lib/utils/concurrency.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/plugins/agent-status/plugin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,eAAO,MAAM,iBAAiB,
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/plugins/agent-status/plugin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,eAAO,MAAM,iBAAiB,wFAyDrB,CAAA"}
|
|
@@ -36,41 +36,33 @@ export const agentStatusPlugin = definePlugin('agent-status')
|
|
|
36
36
|
sessionId: ctx.sessionId,
|
|
37
37
|
agentId: ctx.agentId,
|
|
38
38
|
status: 'thinking',
|
|
39
|
+
definitionName: ctx.agentState.definitionName,
|
|
39
40
|
timestamp: Date.now(),
|
|
40
41
|
});
|
|
41
42
|
}
|
|
42
43
|
return null;
|
|
43
44
|
})
|
|
44
45
|
.hook('onComplete', async (ctx) => {
|
|
45
|
-
|
|
46
|
-
ctx.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
ctx.notify('agentStatus', {
|
|
56
|
-
sessionId: ctx.sessionId,
|
|
57
|
-
agentId: ctx.agentId,
|
|
58
|
-
status: 'idle',
|
|
59
|
-
timestamp: Date.now(),
|
|
60
|
-
});
|
|
61
|
-
}
|
|
46
|
+
ctx.notify('agentStatus', {
|
|
47
|
+
sessionId: ctx.sessionId,
|
|
48
|
+
agentId: ctx.agentId,
|
|
49
|
+
status: 'idle',
|
|
50
|
+
definitionName: ctx.agentState.definitionName,
|
|
51
|
+
timestamp: Date.now(),
|
|
52
|
+
});
|
|
62
53
|
return null;
|
|
63
54
|
})
|
|
64
55
|
.hook('onError', async (ctx) => {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
56
|
+
// Emit idle for both entry and sub-agents — without this the client's
|
|
57
|
+
// `activeAgents` map keeps the agent flagged thinking until reconnect,
|
|
58
|
+
// since the session-store no longer clears it on chat_message/ask_user.
|
|
59
|
+
ctx.notify('agentStatus', {
|
|
60
|
+
sessionId: ctx.sessionId,
|
|
61
|
+
agentId: ctx.agentId,
|
|
62
|
+
status: 'idle',
|
|
63
|
+
definitionName: ctx.agentState.definitionName,
|
|
64
|
+
timestamp: Date.now(),
|
|
65
|
+
});
|
|
74
66
|
return null;
|
|
75
67
|
})
|
|
76
68
|
.build();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../../src/plugins/agent-status/plugin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,CAAC,MAAM,QAAQ,CAAA;AACtB,OAAO,EAAE,aAAa,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAA;AAClF,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAE3D,MAAM,CAAC,MAAM,iBAAiB,GAAG,YAAY,CAAC,cAAc,CAAC;KAC3D,YAAY,CAAC,aAAa,EAAE;IAC5B,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QAChB,SAAS,EAAE,eAAe;QAC1B,OAAO,EAAE,aAAa;QACtB,MAAM,EAAE,yBAAyB;QACjC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QACrC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;KACrB,CAAC;CACF,CAAC;KACD,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;IAC9B,IAAI,GAAG,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QAC3B,GAAG,CAAC,MAAM,CAAC,aAAa,EAAE;YACzB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,MAAM,EAAE,UAAU;YAClB,cAAc,EAAE,GAAG,CAAC,UAAU,CAAC,cAAc;YAC7C,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACrB,CAAC,CAAA;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACZ,CAAC,CAAC;KACD,IAAI,CAAC,iBAAiB,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;IACtC,IAAI,GAAG,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QAC3B,GAAG,CAAC,MAAM,CAAC,aAAa,EAAE;YACzB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,MAAM,EAAE,UAAU;YAClB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACrB,CAAC,CAAA;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACZ,CAAC,CAAC;KACD,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;IACjC,
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../../src/plugins/agent-status/plugin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,CAAC,MAAM,QAAQ,CAAA;AACtB,OAAO,EAAE,aAAa,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAA;AAClF,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAE3D,MAAM,CAAC,MAAM,iBAAiB,GAAG,YAAY,CAAC,cAAc,CAAC;KAC3D,YAAY,CAAC,aAAa,EAAE;IAC5B,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QAChB,SAAS,EAAE,eAAe;QAC1B,OAAO,EAAE,aAAa;QACtB,MAAM,EAAE,yBAAyB;QACjC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QACrC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;KACrB,CAAC;CACF,CAAC;KACD,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;IAC9B,IAAI,GAAG,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QAC3B,GAAG,CAAC,MAAM,CAAC,aAAa,EAAE;YACzB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,MAAM,EAAE,UAAU;YAClB,cAAc,EAAE,GAAG,CAAC,UAAU,CAAC,cAAc;YAC7C,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACrB,CAAC,CAAA;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACZ,CAAC,CAAC;KACD,IAAI,CAAC,iBAAiB,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;IACtC,IAAI,GAAG,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QAC3B,GAAG,CAAC,MAAM,CAAC,aAAa,EAAE;YACzB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,MAAM,EAAE,UAAU;YAClB,cAAc,EAAE,GAAG,CAAC,UAAU,CAAC,cAAc;YAC7C,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACrB,CAAC,CAAA;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACZ,CAAC,CAAC;KACD,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;IACjC,GAAG,CAAC,MAAM,CAAC,aAAa,EAAE;QACzB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,MAAM,EAAE,MAAM;QACd,cAAc,EAAE,GAAG,CAAC,UAAU,CAAC,cAAc;QAC7C,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACrB,CAAC,CAAA;IACF,OAAO,IAAI,CAAA;AACZ,CAAC,CAAC;KACD,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;IAC9B,sEAAsE;IACtE,uEAAuE;IACvE,wEAAwE;IACxE,GAAG,CAAC,MAAM,CAAC,aAAa,EAAE;QACzB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,MAAM,EAAE,MAAM;QACd,cAAc,EAAE,GAAG,CAAC,UAAU,CAAC,cAAc;QAC7C,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACrB,CAAC,CAAA;IACF,OAAO,IAAI,CAAA;AACZ,CAAC,CAAC;KACD,KAAK,EAAE,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live compaction tests against the real Anthropic API.
|
|
3
|
+
*
|
|
4
|
+
* Opt-in: run with `LIVE_TESTS=1 ANTHROPIC_API_KEY=…`. Skipped otherwise so the
|
|
5
|
+
* default `bun test` run stays hermetic.
|
|
6
|
+
*
|
|
7
|
+
* These cover the two real-API claims of the context-compact rewrite (5c27ab7):
|
|
8
|
+
* 1. The auxiliary-inference call (used by `ContextCompactor`) reuses the
|
|
9
|
+
* agent's warm prompt cache — only the trailing instruction + output are
|
|
10
|
+
* paid for, not the whole conversation a second time.
|
|
11
|
+
* 2. `DEFAULT_SUMMARY_INSTRUCTION` actually elicits a plain-text summary from
|
|
12
|
+
* a real Sonnet/Haiku-class model (no tool calls, non-empty content), so
|
|
13
|
+
* the end-to-end `ContextCompactor.compact()` path produces a usable
|
|
14
|
+
* `[CONVERSATION SUMMARY]` block.
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=compaction-live.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compaction-live.test.d.ts","sourceRoot":"","sources":["../../../src/plugins/context-compact/compaction-live.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live compaction tests against the real Anthropic API.
|
|
3
|
+
*
|
|
4
|
+
* Opt-in: run with `LIVE_TESTS=1 ANTHROPIC_API_KEY=…`. Skipped otherwise so the
|
|
5
|
+
* default `bun test` run stays hermetic.
|
|
6
|
+
*
|
|
7
|
+
* These cover the two real-API claims of the context-compact rewrite (5c27ab7):
|
|
8
|
+
* 1. The auxiliary-inference call (used by `ContextCompactor`) reuses the
|
|
9
|
+
* agent's warm prompt cache — only the trailing instruction + output are
|
|
10
|
+
* paid for, not the whole conversation a second time.
|
|
11
|
+
* 2. `DEFAULT_SUMMARY_INSTRUCTION` actually elicits a plain-text summary from
|
|
12
|
+
* a real Sonnet/Haiku-class model (no tool calls, non-empty content), so
|
|
13
|
+
* the end-to-end `ContextCompactor.compact()` path produces a usable
|
|
14
|
+
* `[CONVERSATION SUMMARY]` block.
|
|
15
|
+
*/
|
|
16
|
+
import { describe, expect, test } from 'bun:test';
|
|
17
|
+
import { generateTestAgentId } from '../../core/agents/schema.js';
|
|
18
|
+
import { AnthropicProvider } from '../../core/llm/anthropic.js';
|
|
19
|
+
import { applyCacheBreakpoint } from '../../core/llm/cache-breakpoints.js';
|
|
20
|
+
import { ModelId } from '../../core/llm/schema.js';
|
|
21
|
+
import { generateSessionId } from '../../core/sessions/schema.js';
|
|
22
|
+
import { silentLogger } from '../../lib/logger/logger.js';
|
|
23
|
+
import { ContextCompactor, DEFAULT_SUMMARY_INSTRUCTION, } from './context-compactor.js';
|
|
24
|
+
const liveEnabled = process.env.LIVE_TESTS === '1';
|
|
25
|
+
const anthropicApiKey = liveEnabled ? process.env.ANTHROPIC_API_KEY : undefined;
|
|
26
|
+
const describeLive = (name, apiKey, fn) => {
|
|
27
|
+
if (!apiKey) {
|
|
28
|
+
describe.skip(`${name} (skipped — API key missing)`, fn);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
describe(name, fn);
|
|
32
|
+
};
|
|
33
|
+
const noopImageProcessor = {
|
|
34
|
+
resolveContent: async (content) => content,
|
|
35
|
+
};
|
|
36
|
+
const MODEL = ModelId('claude-haiku-4-5-20251001');
|
|
37
|
+
/**
|
|
38
|
+
* Padded system prompt so the cacheable prefix comfortably exceeds Anthropic's
|
|
39
|
+
* 1024-token minimum for Haiku. Deterministic content so identical calls reuse
|
|
40
|
+
* the exact same prefix.
|
|
41
|
+
*/
|
|
42
|
+
const LARGE_SYSTEM_PROMPT = [
|
|
43
|
+
'You are a meticulous assistant helping a developer review a long conversation.',
|
|
44
|
+
'Always respond concisely and accurately. Never speculate beyond the data.',
|
|
45
|
+
'Follow these rules strictly:',
|
|
46
|
+
...Array.from({ length: 120 }, (_, i) => `- Rule ${i + 1}: When asked about topic ${i + 1}, prefer factual sources and decline to speculate.`),
|
|
47
|
+
'End of instructions.',
|
|
48
|
+
].join('\n');
|
|
49
|
+
/**
|
|
50
|
+
* Deterministic multi-turn history padded well past 1024 tokens so cache writes
|
|
51
|
+
* and reads are unambiguous. Includes both user and assistant messages, which
|
|
52
|
+
* is the shape an inline-compaction call sees in practice.
|
|
53
|
+
*/
|
|
54
|
+
function buildLongHistory() {
|
|
55
|
+
const history = [];
|
|
56
|
+
for (let i = 0; i < 8; i++) {
|
|
57
|
+
history.push({
|
|
58
|
+
role: 'user',
|
|
59
|
+
content: `Turn ${i + 1} user: please analyze topic ${i + 1}. `
|
|
60
|
+
+ 'context detail '.repeat(30),
|
|
61
|
+
});
|
|
62
|
+
history.push({
|
|
63
|
+
role: 'assistant',
|
|
64
|
+
content: `Turn ${i + 1} assistant: here is my analysis of topic ${i + 1}. `
|
|
65
|
+
+ 'analysis detail '.repeat(30),
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return history;
|
|
69
|
+
}
|
|
70
|
+
describeLive('context-compact live: auxiliary inference cache reuse', anthropicApiKey, () => {
|
|
71
|
+
test('priming inference then auxiliary summary call hits the prompt cache', async () => {
|
|
72
|
+
const provider = new AnthropicProvider({
|
|
73
|
+
apiKey: anthropicApiKey,
|
|
74
|
+
imageProcessor: noopImageProcessor,
|
|
75
|
+
defaultModel: 'claude-haiku-4-5-20251001',
|
|
76
|
+
});
|
|
77
|
+
const history = buildLongHistory();
|
|
78
|
+
// Call 1: regular inference, breakpoint on the last history message.
|
|
79
|
+
// Mirrors what an Agent.advance() turn does just before requesting a
|
|
80
|
+
// compaction summary.
|
|
81
|
+
const primeMessages = applyCacheBreakpoint(history, 0, '1h');
|
|
82
|
+
const prime = await provider.inference({
|
|
83
|
+
model: MODEL,
|
|
84
|
+
systemPrompt: LARGE_SYSTEM_PROMPT,
|
|
85
|
+
messages: primeMessages,
|
|
86
|
+
});
|
|
87
|
+
if (!prime.ok) {
|
|
88
|
+
if (prime.error.message?.includes('credit balance')) {
|
|
89
|
+
console.warn('⚠️ Live compaction cache test skipped: credit balance too low');
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
throw new Error(`prime call failed: ${JSON.stringify(prime.error)}`);
|
|
93
|
+
}
|
|
94
|
+
expect(prime.value.metrics.promptTokens).toBeGreaterThan(1024);
|
|
95
|
+
// Call 2: simulate Agent.runAuxiliaryInference — append the summary
|
|
96
|
+
// instruction as a trailing user message and place the breakpoint at
|
|
97
|
+
// the same position as the prime call (last history message), so the
|
|
98
|
+
// whole prefix lands as a cache read.
|
|
99
|
+
const summaryInstruction = { role: 'user', content: DEFAULT_SUMMARY_INSTRUCTION };
|
|
100
|
+
const auxMessages = applyCacheBreakpoint([...history, summaryInstruction], 1, '1h');
|
|
101
|
+
const aux = await provider.inference({
|
|
102
|
+
model: MODEL,
|
|
103
|
+
systemPrompt: LARGE_SYSTEM_PROMPT,
|
|
104
|
+
messages: auxMessages,
|
|
105
|
+
});
|
|
106
|
+
if (!aux.ok)
|
|
107
|
+
throw new Error(`auxiliary call failed: ${JSON.stringify(aux.error)}`);
|
|
108
|
+
// Core claim: the auxiliary call served the prefix from cache (otherwise
|
|
109
|
+
// we'd re-upload the entire conversation just to get a summary).
|
|
110
|
+
expect(aux.value.metrics.cachedTokens ?? 0).toBeGreaterThan(1024);
|
|
111
|
+
// Sonnet/Haiku reliably emit plain text under DEFAULT_SUMMARY_INSTRUCTION.
|
|
112
|
+
// If this regresses, the prompt is no longer fit for purpose.
|
|
113
|
+
expect(aux.value.toolCalls).toHaveLength(0);
|
|
114
|
+
expect(aux.value.finishReason).toBe('stop');
|
|
115
|
+
expect(aux.value.content ?? '').not.toBe('');
|
|
116
|
+
}, 60_000);
|
|
117
|
+
});
|
|
118
|
+
describeLive('context-compact live: end-to-end compactor', anthropicApiKey, () => {
|
|
119
|
+
test('ContextCompactor.compact() produces a real summary from a real model', async () => {
|
|
120
|
+
const provider = new AnthropicProvider({
|
|
121
|
+
apiKey: anthropicApiKey,
|
|
122
|
+
imageProcessor: noopImageProcessor,
|
|
123
|
+
defaultModel: 'claude-haiku-4-5-20251001',
|
|
124
|
+
});
|
|
125
|
+
const history = buildLongHistory();
|
|
126
|
+
// Wraps the provider exactly the way AgentContext.runAuxiliaryInference
|
|
127
|
+
// does: full prefix + extraMessages, breakpoint pinned to the last
|
|
128
|
+
// pre-extraMessages position so the agent's cache is reused.
|
|
129
|
+
const auxCalls = [];
|
|
130
|
+
const runInference = async (extraMessages) => {
|
|
131
|
+
const messages = applyCacheBreakpoint([...history, ...extraMessages], extraMessages.length, '1h');
|
|
132
|
+
const result = await provider.inference({
|
|
133
|
+
model: MODEL,
|
|
134
|
+
systemPrompt: LARGE_SYSTEM_PROMPT,
|
|
135
|
+
messages,
|
|
136
|
+
});
|
|
137
|
+
if (result.ok)
|
|
138
|
+
auxCalls.push(result.value);
|
|
139
|
+
return result;
|
|
140
|
+
};
|
|
141
|
+
// Prime the cache with one regular inference first, otherwise the
|
|
142
|
+
// auxiliary call would pay full write cost — same as a real session
|
|
143
|
+
// where compaction always runs after at least one normal turn.
|
|
144
|
+
const prime = await provider.inference({
|
|
145
|
+
model: MODEL,
|
|
146
|
+
systemPrompt: LARGE_SYSTEM_PROMPT,
|
|
147
|
+
messages: applyCacheBreakpoint(history, 0, '1h'),
|
|
148
|
+
});
|
|
149
|
+
if (!prime.ok) {
|
|
150
|
+
if (prime.error.message?.includes('credit balance')) {
|
|
151
|
+
console.warn('⚠️ Live compaction end-to-end test skipped: credit balance too low');
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
throw new Error(`prime call failed: ${JSON.stringify(prime.error)}`);
|
|
155
|
+
}
|
|
156
|
+
const compactor = new ContextCompactor(silentLogger, {
|
|
157
|
+
// Force compaction regardless of estimator vs actual tokens.
|
|
158
|
+
maxTokens: 10,
|
|
159
|
+
keepRecentMessages: 2,
|
|
160
|
+
});
|
|
161
|
+
const result = await compactor.compact(generateSessionId(), generateTestAgentId(), history, runInference);
|
|
162
|
+
expect(result.ok).toBe(true);
|
|
163
|
+
if (!result.ok)
|
|
164
|
+
return;
|
|
165
|
+
expect(result.value.messagesRemoved).toBeGreaterThan(0);
|
|
166
|
+
expect(result.value.summary.trim().length).toBeGreaterThan(0);
|
|
167
|
+
// keepRecentMessages=2 → summary message + 2 kept = 3 total
|
|
168
|
+
expect(result.value.compactedMessages).toHaveLength(3);
|
|
169
|
+
expect(result.value.compactedMessages[0].role).toBe('user');
|
|
170
|
+
expect(result.value.compactedMessages[0].content).toContain('[CONVERSATION SUMMARY]');
|
|
171
|
+
// The auxiliary inference under the compactor should have served the
|
|
172
|
+
// prefix from cache (priming call wrote it).
|
|
173
|
+
expect(auxCalls).toHaveLength(1);
|
|
174
|
+
expect(auxCalls[0].metrics.cachedTokens ?? 0).toBeGreaterThan(1024);
|
|
175
|
+
}, 60_000);
|
|
176
|
+
});
|
|
177
|
+
//# sourceMappingURL=compaction-live.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compaction-live.test.js","sourceRoot":"","sources":["../../../src/plugins/context-compact/compaction-live.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
import { describe, expect, it } from 'bun:test';
|
|
2
|
+
import z from 'zod/v4';
|
|
2
3
|
import { contextEvents } from '../../core/context/state.js';
|
|
3
4
|
import { MockLLMProvider } from '../../core/llm/mock.js';
|
|
4
5
|
import { ModelId } from '../../core/llm/schema.js';
|
|
6
|
+
import { createTool } from '../../core/tools/definition.js';
|
|
7
|
+
import { ToolCallId } from '../../core/tools/schema.js';
|
|
5
8
|
import { createTestPreset, TestHarness } from '../../testing/index.js';
|
|
6
9
|
import { contextCompactPlugin } from './index.js';
|
|
10
|
+
/**
|
|
11
|
+
* Inline compaction sends the agent's regular systemPrompt and full conversation
|
|
12
|
+
* to the LLM, with a trailing user message containing the summarization
|
|
13
|
+
* instruction. We detect compaction calls by looking at that trailing message.
|
|
14
|
+
*/
|
|
15
|
+
function isSummarizationRequest(request) {
|
|
16
|
+
const last = request.messages[request.messages.length - 1];
|
|
17
|
+
if (!last || last.role !== 'user')
|
|
18
|
+
return false;
|
|
19
|
+
const content = typeof last.content === 'string' ? last.content : JSON.stringify(last.content);
|
|
20
|
+
return content.includes('[CONTEXT COMPACTION REQUEST]');
|
|
21
|
+
}
|
|
7
22
|
// ============================================================================
|
|
8
23
|
// Helpers
|
|
9
24
|
// ============================================================================
|
|
@@ -44,7 +59,7 @@ describe('context-compact plugin', () => {
|
|
|
44
59
|
presets: [createCompactPreset(10)],
|
|
45
60
|
mockHandler: (request) => {
|
|
46
61
|
// Compaction requests use CONTEXT_SUMMARY_PROMPT which contains "summarizer".
|
|
47
|
-
if (
|
|
62
|
+
if (isSummarizationRequest(request)) {
|
|
48
63
|
return {
|
|
49
64
|
content: 'Summary of conversation so far.',
|
|
50
65
|
toolCalls: [],
|
|
@@ -100,7 +115,7 @@ describe('context-compact plugin', () => {
|
|
|
100
115
|
mockHandler: (request) => {
|
|
101
116
|
inferenceCallCount++;
|
|
102
117
|
// Summarization requests (from context-compact plugin)
|
|
103
|
-
if (
|
|
118
|
+
if (isSummarizationRequest(request)) {
|
|
104
119
|
return {
|
|
105
120
|
content: 'Conversation summary.',
|
|
106
121
|
toolCalls: [],
|
|
@@ -132,6 +147,111 @@ describe('context-compact plugin', () => {
|
|
|
132
147
|
});
|
|
133
148
|
});
|
|
134
149
|
// =========================================================================
|
|
150
|
+
// Pending tool results regression
|
|
151
|
+
// =========================================================================
|
|
152
|
+
describe('pending tool results', () => {
|
|
153
|
+
it('aux inference after a tool turn includes the tool_result before the summary instruction', async () => {
|
|
154
|
+
// Regression for the bug where context-compact's auxiliary inference call
|
|
155
|
+
// runs at a moment where `conversationHistory` ends with an assistant
|
|
156
|
+
// `tool_use` block but the corresponding tool_result is still in
|
|
157
|
+
// `pendingToolResults` (not yet committed to history). Sending
|
|
158
|
+
// `[..., assistant(tool_use), user(summary)]` to Anthropic 400s with
|
|
159
|
+
// "tool_use blocks must be followed by tool_result blocks".
|
|
160
|
+
const myTool = createTool({
|
|
161
|
+
name: 'my_tool',
|
|
162
|
+
description: 'returns a fixed value',
|
|
163
|
+
input: z.object({}),
|
|
164
|
+
execute: async () => ({ ok: true, value: 'tool result content' }),
|
|
165
|
+
});
|
|
166
|
+
const preset = {
|
|
167
|
+
id: 'test',
|
|
168
|
+
name: 'Tool Compaction Test',
|
|
169
|
+
orchestrator: {
|
|
170
|
+
system: 'You are a test agent.',
|
|
171
|
+
model: ModelId('mock'),
|
|
172
|
+
tools: [myTool],
|
|
173
|
+
agents: [],
|
|
174
|
+
debounceMs: 0,
|
|
175
|
+
},
|
|
176
|
+
agents: [],
|
|
177
|
+
plugins: [
|
|
178
|
+
contextCompactPlugin.configure({
|
|
179
|
+
compaction: {
|
|
180
|
+
model: ModelId('mock'),
|
|
181
|
+
maxTokens: 10,
|
|
182
|
+
// 1 so that after the tool turn, [user, assistant(tool_use)]
|
|
183
|
+
// splits into toCompact=[user], toKeep=[assistant(tool_use)] —
|
|
184
|
+
// the aux call actually runs and gets the buggy prefix.
|
|
185
|
+
keepRecentMessages: 1,
|
|
186
|
+
},
|
|
187
|
+
}),
|
|
188
|
+
],
|
|
189
|
+
};
|
|
190
|
+
let capturedAuxRequest;
|
|
191
|
+
const harness = new TestHarness({
|
|
192
|
+
systemPlugins: [contextCompactPlugin],
|
|
193
|
+
presets: [preset],
|
|
194
|
+
mockHandler: (request) => {
|
|
195
|
+
if (isSummarizationRequest(request)) {
|
|
196
|
+
capturedAuxRequest = request;
|
|
197
|
+
return {
|
|
198
|
+
content: 'Summary of conversation.',
|
|
199
|
+
toolCalls: [],
|
|
200
|
+
finishReason: 'stop',
|
|
201
|
+
metrics: MockLLMProvider.defaultMetrics(),
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
// First inference (no tool messages in history yet) → emit a tool call.
|
|
205
|
+
const hasToolMessages = request.messages.some((m) => m.role === 'tool');
|
|
206
|
+
if (!hasToolMessages) {
|
|
207
|
+
return {
|
|
208
|
+
content: '',
|
|
209
|
+
toolCalls: [{ id: ToolCallId('tc1'), name: 'my_tool', input: {} }],
|
|
210
|
+
finishReason: 'tool_calls',
|
|
211
|
+
metrics: MockLLMProvider.defaultMetrics(),
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
return {
|
|
215
|
+
content: 'Done.',
|
|
216
|
+
toolCalls: [],
|
|
217
|
+
finishReason: 'stop',
|
|
218
|
+
metrics: MockLLMProvider.defaultMetrics(),
|
|
219
|
+
};
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
const session = await harness.createSession('test');
|
|
223
|
+
await session.sendAndWaitForIdle('Please call my_tool');
|
|
224
|
+
expect(capturedAuxRequest).toBeDefined();
|
|
225
|
+
// Every assistant message with toolCalls must be followed by a contiguous
|
|
226
|
+
// run of tool messages covering each tool_use id before any further
|
|
227
|
+
// user/assistant message. This mirrors Anthropic's API contract.
|
|
228
|
+
const msgs = capturedAuxRequest.messages;
|
|
229
|
+
for (let i = 0; i < msgs.length; i++) {
|
|
230
|
+
const m = msgs[i];
|
|
231
|
+
if (m.role !== 'assistant' || !m.toolCalls?.length)
|
|
232
|
+
continue;
|
|
233
|
+
const expected = new Set(m.toolCalls.map((tc) => tc.id));
|
|
234
|
+
const seen = new Set();
|
|
235
|
+
for (let j = i + 1; j < msgs.length; j++) {
|
|
236
|
+
const next = msgs[j];
|
|
237
|
+
if (next.role !== 'tool')
|
|
238
|
+
break;
|
|
239
|
+
seen.add(next.toolCallId);
|
|
240
|
+
}
|
|
241
|
+
for (const id of expected) {
|
|
242
|
+
expect(seen.has(id)).toBe(true);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// Compaction must have actually succeeded — pre-fix it would Err-out
|
|
246
|
+
// in production (mock accepts it but the assertion above already
|
|
247
|
+
// catches the malformed-prefix case).
|
|
248
|
+
const compactedEvents = await session.getEventsByType(contextEvents, 'context_compacted');
|
|
249
|
+
const actualCompactions = compactedEvents.filter((e) => e.messagesRemoved > 0);
|
|
250
|
+
expect(actualCompactions.length).toBeGreaterThanOrEqual(1);
|
|
251
|
+
await harness.shutdown();
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
// =========================================================================
|
|
135
255
|
// Compaction failure
|
|
136
256
|
// =========================================================================
|
|
137
257
|
describe('compaction failure', () => {
|
|
@@ -142,7 +262,7 @@ describe('context-compact plugin', () => {
|
|
|
142
262
|
mockHandler: (request) => {
|
|
143
263
|
// Summarization requests — throw to simulate LLM failure.
|
|
144
264
|
// MockLLMProvider only returns Err() when the handler throws.
|
|
145
|
-
if (
|
|
265
|
+
if (isSummarizationRequest(request)) {
|
|
146
266
|
throw { type: 'server_error', message: 'LLM summarization failed' };
|
|
147
267
|
}
|
|
148
268
|
// Regular inference
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-compact.integration.test.js","sourceRoot":"","sources":["../../../src/plugins/context-compact/context-compact.integration.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,UAAU,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"context-compact.integration.test.js","sourceRoot":"","sources":["../../../src/plugins/context-compact/context-compact.integration.test.ts"],"names":[],"mappings":"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"}
|