@animalabs/agent-framework 0.7.0 → 0.7.3

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 (58) hide show
  1. package/dist/src/code-execution/index.d.ts +14 -0
  2. package/dist/src/code-execution/index.d.ts.map +1 -0
  3. package/dist/src/code-execution/index.js +13 -0
  4. package/dist/src/code-execution/index.js.map +1 -0
  5. package/dist/src/code-execution/py-runner.d.ts +96 -0
  6. package/dist/src/code-execution/py-runner.d.ts.map +1 -0
  7. package/dist/src/code-execution/py-runner.js +371 -0
  8. package/dist/src/code-execution/py-runner.js.map +1 -0
  9. package/dist/src/code-execution/runtime-py.d.ts +32 -0
  10. package/dist/src/code-execution/runtime-py.d.ts.map +1 -0
  11. package/dist/src/code-execution/runtime-py.js +265 -0
  12. package/dist/src/code-execution/runtime-py.js.map +1 -0
  13. package/dist/src/code-execution/tool-definition.d.ts +16 -0
  14. package/dist/src/code-execution/tool-definition.d.ts.map +1 -0
  15. package/dist/src/code-execution/tool-definition.js +47 -0
  16. package/dist/src/code-execution/tool-definition.js.map +1 -0
  17. package/dist/src/framework.d.ts +43 -1
  18. package/dist/src/framework.d.ts.map +1 -1
  19. package/dist/src/framework.js +274 -26
  20. package/dist/src/framework.js.map +1 -1
  21. package/dist/src/index.d.ts +2 -0
  22. package/dist/src/index.d.ts.map +1 -1
  23. package/dist/src/index.js +4 -0
  24. package/dist/src/index.js.map +1 -1
  25. package/dist/src/mcpl/channel-registry.d.ts +12 -0
  26. package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
  27. package/dist/src/mcpl/channel-registry.js +45 -0
  28. package/dist/src/mcpl/channel-registry.js.map +1 -1
  29. package/dist/src/mcpl/prose-grammar.d.ts +24 -0
  30. package/dist/src/mcpl/prose-grammar.d.ts.map +1 -0
  31. package/dist/src/mcpl/prose-grammar.js +33 -0
  32. package/dist/src/mcpl/prose-grammar.js.map +1 -0
  33. package/dist/src/mcpl/prose-stream-router.d.ts +58 -0
  34. package/dist/src/mcpl/prose-stream-router.d.ts.map +1 -0
  35. package/dist/src/mcpl/prose-stream-router.js +168 -0
  36. package/dist/src/mcpl/prose-stream-router.js.map +1 -0
  37. package/dist/src/types/framework.d.ts +33 -0
  38. package/dist/src/types/framework.d.ts.map +1 -1
  39. package/dist/test/code-execution.test.d.ts +11 -0
  40. package/dist/test/code-execution.test.d.ts.map +1 -0
  41. package/dist/test/code-execution.test.js +423 -0
  42. package/dist/test/code-execution.test.js.map +1 -0
  43. package/dist/test/prose-stream-router.test.d.ts +2 -0
  44. package/dist/test/prose-stream-router.test.d.ts.map +1 -0
  45. package/dist/test/prose-stream-router.test.js +87 -0
  46. package/dist/test/prose-stream-router.test.js.map +1 -0
  47. package/dist/tsconfig.tsbuildinfo +1 -1
  48. package/package.json +1 -1
  49. package/src/code-execution/index.ts +19 -0
  50. package/src/code-execution/py-runner.ts +439 -0
  51. package/src/code-execution/runtime-py.ts +265 -0
  52. package/src/code-execution/tool-definition.ts +54 -0
  53. package/src/framework.ts +307 -28
  54. package/src/index.ts +17 -0
  55. package/src/mcpl/channel-registry.ts +53 -0
  56. package/src/mcpl/prose-grammar.ts +40 -0
  57. package/src/mcpl/prose-stream-router.ts +161 -0
  58. package/src/types/framework.ts +35 -0
@@ -0,0 +1,423 @@
1
+ /**
2
+ * Client-side programmatic tool calling (code_execution) tests.
3
+ *
4
+ * PyRunner tests spawn a REAL python3 subprocess — the protocol, top-level
5
+ * await, tool-function injection, timeout, and deadline behavior are all
6
+ * exercised end-to-end. Framework tests drive a full agent turn through the
7
+ * MockMembrane and assert the load-bearing invariant: inner tool results
8
+ * reach the running script but never the model-facing tool_result.
9
+ */
10
+ import { describe, it } from 'node:test';
11
+ import assert from 'node:assert';
12
+ import { mkdtempSync, rmSync } from 'node:fs';
13
+ import { tmpdir } from 'node:os';
14
+ import { join } from 'node:path';
15
+ import { AgentFramework, PyRunner, buildInjectedTools } from '../src/index.js';
16
+ import { createMockResponse, MockMembrane } from './helpers/mock-membrane.js';
17
+ const ECHO_TOOLS = [
18
+ { pyName: 'test__echo', toolName: 'test--echo' },
19
+ ];
20
+ describe('buildInjectedTools', () => {
21
+ it('sanitizes -- to __ and keeps valid identifiers', () => {
22
+ const injected = buildInjectedTools(['mcpl--discord--send_message', 'think']);
23
+ assert.deepStrictEqual(injected, [
24
+ { pyName: 'mcpl__discord__send_message', toolName: 'mcpl--discord--send_message' },
25
+ { pyName: 'think', toolName: 'think' },
26
+ ]);
27
+ });
28
+ it('sanitizes single hyphens inside segments (live fleet names)', () => {
29
+ // Found on the first Mica canary run: module/server ids with single
30
+ // hyphens were skipped entirely. They must inject.
31
+ const injected = buildInjectedTools([
32
+ 'mcpl-admin--mcpl_deploy',
33
+ 'mcpl--dog-events--dog_events_status',
34
+ 'channel-mode--set_channel_mode',
35
+ ]);
36
+ assert.deepStrictEqual(injected, [
37
+ { pyName: 'mcpl_admin__mcpl_deploy', toolName: 'mcpl-admin--mcpl_deploy' },
38
+ { pyName: 'mcpl__dog_events__dog_events_status', toolName: 'mcpl--dog-events--dog_events_status' },
39
+ { pyName: 'channel_mode__set_channel_mode', toolName: 'channel-mode--set_channel_mode' },
40
+ ]);
41
+ });
42
+ it('prefixes a leading digit', () => {
43
+ const injected = buildInjectedTools(['3d-tools--render']);
44
+ assert.deepStrictEqual(injected, [{ pyName: '_3d_tools__render', toolName: '3d-tools--render' }]);
45
+ });
46
+ it('skips colliding sanitized names loudly (first wins)', () => {
47
+ const logs = [];
48
+ const injected = buildInjectedTools(['a--b', 'a__b'], (m) => logs.push(m));
49
+ assert.deepStrictEqual(injected, [{ pyName: 'a__b', toolName: 'a--b' }]);
50
+ assert.strictEqual(logs.length, 1);
51
+ assert.match(logs[0], /collides/);
52
+ });
53
+ });
54
+ describe('PyRunner (real python3)', () => {
55
+ it('runs a script and returns stdout', async () => {
56
+ const runner = new PyRunner({ onToolCall: async () => '' });
57
+ try {
58
+ const result = await runner.exec('print("hello from python")', []);
59
+ assert.strictEqual(result.returnCode, 0);
60
+ assert.match(result.stdout, /hello from python/);
61
+ assert.strictEqual(result.stderr, '');
62
+ }
63
+ finally {
64
+ runner.dispose();
65
+ }
66
+ });
67
+ it('round-trips a tool call as an awaited async function', async () => {
68
+ const calls = [];
69
+ const runner = new PyRunner({
70
+ onToolCall: async (name, args) => {
71
+ calls.push({ name, args });
72
+ return JSON.stringify({ echoed: args });
73
+ },
74
+ });
75
+ try {
76
+ const result = await runner.exec([
77
+ 'import json',
78
+ 'r = json.loads(await test__echo({"message": "alpha"}))',
79
+ 'print("echoed:", r["echoed"]["message"])',
80
+ ].join('\n'), ECHO_TOOLS);
81
+ assert.strictEqual(result.returnCode, 0, result.stderr);
82
+ assert.match(result.stdout, /echoed: alpha/);
83
+ assert.deepStrictEqual(calls, [{ name: 'test--echo', args: { message: 'alpha' } }]);
84
+ }
85
+ finally {
86
+ runner.dispose();
87
+ }
88
+ });
89
+ it('supports the exact-name tools[...] escape hatch', async () => {
90
+ const runner = new PyRunner({
91
+ onToolCall: async (_name, args) => `got:${String(args.v)}`,
92
+ });
93
+ try {
94
+ const result = await runner.exec('print(await tools["test--echo"]({"v": 7}))', ECHO_TOOLS);
95
+ assert.strictEqual(result.returnCode, 0, result.stderr);
96
+ assert.match(result.stdout, /got:7/);
97
+ }
98
+ finally {
99
+ runner.dispose();
100
+ }
101
+ });
102
+ it('runs parallel tool calls via asyncio.gather', async () => {
103
+ let inFlight = 0;
104
+ let maxInFlight = 0;
105
+ const runner = new PyRunner({
106
+ onToolCall: async (_name, args) => {
107
+ inFlight++;
108
+ maxInFlight = Math.max(maxInFlight, inFlight);
109
+ await new Promise((r) => setTimeout(r, 150));
110
+ inFlight--;
111
+ return String(args.i);
112
+ },
113
+ });
114
+ try {
115
+ const result = await runner.exec([
116
+ 'import asyncio',
117
+ 'results = await asyncio.gather(*(test__echo({"i": i}) for i in range(3)))',
118
+ 'print(",".join(results))',
119
+ ].join('\n'), ECHO_TOOLS);
120
+ assert.strictEqual(result.returnCode, 0, result.stderr);
121
+ assert.match(result.stdout, /0,1,2/);
122
+ assert.ok(maxInFlight >= 2, `expected parallel dispatch, max in flight was ${maxInFlight}`);
123
+ }
124
+ finally {
125
+ runner.dispose();
126
+ }
127
+ });
128
+ it('persists interpreter state across execs (container-reuse semantics)', async () => {
129
+ const runner = new PyRunner({ onToolCall: async () => '' });
130
+ try {
131
+ const first = await runner.exec('x = 41', []);
132
+ assert.strictEqual(first.returnCode, 0, first.stderr);
133
+ const second = await runner.exec('print(x + 1)', []);
134
+ assert.strictEqual(second.returnCode, 0, second.stderr);
135
+ assert.match(second.stdout, /42/);
136
+ }
137
+ finally {
138
+ runner.dispose();
139
+ }
140
+ });
141
+ it('reports script exceptions as a traceback with return_code 1', async () => {
142
+ const runner = new PyRunner({ onToolCall: async () => '' });
143
+ try {
144
+ const result = await runner.exec('raise ValueError("boom")', []);
145
+ assert.strictEqual(result.returnCode, 1);
146
+ assert.match(result.stderr, /ValueError: boom/);
147
+ assert.match(result.stderr, /Traceback/);
148
+ }
149
+ finally {
150
+ runner.dispose();
151
+ }
152
+ });
153
+ it('delivers tool errors as plain strings the script can handle', async () => {
154
+ const runner = new PyRunner({
155
+ onToolCall: async () => 'Error: Query timeout - table lock exceeded',
156
+ });
157
+ try {
158
+ const result = await runner.exec([
159
+ 'r = await test__echo({})',
160
+ 'if r.startswith("Error:"):',
161
+ ' print("handled:", r)',
162
+ ].join('\n'), ECHO_TOOLS);
163
+ assert.strictEqual(result.returnCode, 0, result.stderr);
164
+ assert.match(result.stdout, /handled: Error: Query timeout/);
165
+ }
166
+ finally {
167
+ runner.dispose();
168
+ }
169
+ });
170
+ it('raises TimeoutError inside the script when a tool call gets no response', async () => {
171
+ const runner = new PyRunner({
172
+ toolCallTimeoutMs: 1000,
173
+ onToolCall: () => new Promise((resolve) => setTimeout(() => resolve('late'), 5000)),
174
+ });
175
+ try {
176
+ const result = await runner.exec('await test__echo({})', ECHO_TOOLS);
177
+ assert.strictEqual(result.returnCode, 1);
178
+ assert.match(result.stderr, /TimeoutError: Calling tool \['test--echo'\] timed out/);
179
+ }
180
+ finally {
181
+ runner.dispose();
182
+ }
183
+ });
184
+ it('cancels a script that exceeds the deadline', async () => {
185
+ const runner = new PyRunner({
186
+ scriptTimeoutMs: 1000,
187
+ onToolCall: async () => '',
188
+ });
189
+ try {
190
+ const started = Date.now();
191
+ const result = await runner.exec('import asyncio\nawait asyncio.sleep(60)', []);
192
+ assert.strictEqual(result.returnCode, 1);
193
+ assert.match(result.stderr, /cancelled by host/);
194
+ assert.ok(Date.now() - started < 15_000, 'deadline cancel took too long');
195
+ }
196
+ finally {
197
+ runner.dispose();
198
+ }
199
+ });
200
+ it('abort() settles a running script and reclaims the interpreter', async () => {
201
+ const runner = new PyRunner({ onToolCall: async () => '' });
202
+ try {
203
+ const pending = runner.exec('import asyncio\nawait asyncio.sleep(60)', []);
204
+ // Let the exec actually start before aborting.
205
+ await new Promise((r) => setTimeout(r, 500));
206
+ assert.strictEqual(runner.busy, true);
207
+ runner.abort('test abort');
208
+ const result = await pending;
209
+ assert.strictEqual(result.aborted, true);
210
+ assert.match(result.stderr, /aborted by host: test abort/);
211
+ // Runner remains usable after reclaim (fresh interpreter, state gone).
212
+ const after = await runner.exec('print("alive")', []);
213
+ assert.strictEqual(after.returnCode, 0, after.stderr);
214
+ assert.match(after.stdout, /alive/);
215
+ }
216
+ finally {
217
+ runner.dispose();
218
+ }
219
+ });
220
+ it('rejects concurrent execs on one runner', async () => {
221
+ const runner = new PyRunner({ onToolCall: async () => '' });
222
+ try {
223
+ const first = runner.exec('import asyncio\nawait asyncio.sleep(2)', []);
224
+ await new Promise((r) => setTimeout(r, 300));
225
+ const second = await runner.exec('print("nope")', []);
226
+ assert.strictEqual(second.returnCode, 1);
227
+ assert.match(second.stderr, /already running/);
228
+ runner.abort('cleanup');
229
+ await first;
230
+ }
231
+ finally {
232
+ runner.dispose();
233
+ }
234
+ });
235
+ it('fails gracefully when the python binary is missing', async () => {
236
+ const runner = new PyRunner({
237
+ pythonPath: '/definitely/not/a/python',
238
+ onToolCall: async () => '',
239
+ });
240
+ try {
241
+ const result = await runner.exec('print(1)', []);
242
+ assert.strictEqual(result.returnCode, 1);
243
+ assert.match(result.stderr, /Failed to start python runtime|exited before becoming ready/);
244
+ }
245
+ finally {
246
+ runner.dispose();
247
+ }
248
+ });
249
+ });
250
+ // ---------------------------------------------------------------------------
251
+ // Framework integration
252
+ // ---------------------------------------------------------------------------
253
+ class ScriptToolModule {
254
+ name = 'test';
255
+ calls = [];
256
+ async start(_ctx) { }
257
+ async stop() { }
258
+ getTools() {
259
+ return [
260
+ {
261
+ name: 'echo',
262
+ description: 'Echo input. Returns JSON: {"echoed": <input>}.',
263
+ inputSchema: { type: 'object', properties: { message: { type: 'string' } } },
264
+ },
265
+ {
266
+ name: 'finish',
267
+ description: 'End the turn.',
268
+ inputSchema: { type: 'object', properties: {} },
269
+ },
270
+ ];
271
+ }
272
+ async handleToolCall(call) {
273
+ this.calls.push(call);
274
+ const baseName = call.name.includes('--')
275
+ ? call.name.slice(call.name.lastIndexOf('--') + 2)
276
+ : call.name;
277
+ if (baseName === 'finish') {
278
+ return { success: true, data: { finished: true }, endTurn: true };
279
+ }
280
+ return { success: true, data: { echoed: call.input } };
281
+ }
282
+ async onProcess(_event, _state) {
283
+ return {};
284
+ }
285
+ }
286
+ function tempStorePath(prefix) {
287
+ const tempDir = mkdtempSync(join(tmpdir(), prefix));
288
+ return { tempDir, storePath: join(tempDir, 'store.chronicle') };
289
+ }
290
+ async function createFrameworkWithCodeExecution(storePath, membrane, module) {
291
+ return AgentFramework.create({
292
+ storePath,
293
+ membrane: membrane.asMembrane(),
294
+ agents: [],
295
+ modules: [module],
296
+ syncIntervalMs: 0,
297
+ codeExecution: { enabled: true },
298
+ });
299
+ }
300
+ describe('framework code_execution integration (real python3)', () => {
301
+ it('synthesizes the tool only when enabled', async () => {
302
+ const { tempDir, storePath } = tempStorePath('pytc-tools-');
303
+ const membrane = new MockMembrane();
304
+ const framework = await AgentFramework.create({
305
+ storePath,
306
+ membrane: membrane.asMembrane(),
307
+ agents: [],
308
+ modules: [new ScriptToolModule()],
309
+ syncIntervalMs: 0,
310
+ });
311
+ try {
312
+ assert.ok(!framework.getAllTools().some((t) => t.name === 'code_execution'));
313
+ }
314
+ finally {
315
+ await framework.stop();
316
+ rmSync(tempDir, { recursive: true, force: true });
317
+ }
318
+ const { tempDir: tempDir2, storePath: storePath2 } = tempStorePath('pytc-tools2-');
319
+ const membrane2 = new MockMembrane();
320
+ const framework2 = await createFrameworkWithCodeExecution(storePath2, membrane2, new ScriptToolModule());
321
+ try {
322
+ const tool = framework2.getAllTools().find((t) => t.name === 'code_execution');
323
+ assert.ok(tool, 'code_execution tool should be synthesized');
324
+ assert.match(tool.description, /async Python function/);
325
+ assert.match(tool.description, /__/);
326
+ }
327
+ finally {
328
+ await framework2.stop();
329
+ rmSync(tempDir2, { recursive: true, force: true });
330
+ }
331
+ });
332
+ it('runs a script that calls module tools; intermediates never reach the model', async () => {
333
+ const { tempDir, storePath } = tempStorePath('pytc-run-');
334
+ const membrane = new MockMembrane();
335
+ const module = new ScriptToolModule();
336
+ const code = [
337
+ 'import json',
338
+ 'names = []',
339
+ 'for m in ["alpha", "beta"]:',
340
+ ' r = json.loads(await test__echo({"message": m}))',
341
+ ' names.append(r["echoed"]["message"].upper())',
342
+ 'print("summary:", "+".join(names))',
343
+ ].join('\n');
344
+ membrane.pushResponse(createMockResponse([
345
+ { type: 'text', text: 'Let me fan out.' },
346
+ { type: 'tool_use', id: 'call_ce_1', name: 'code_execution', input: { code } },
347
+ ], 'tool_use'));
348
+ membrane.pushResponse(createMockResponse([
349
+ { type: 'text', text: 'Final answer.' },
350
+ ]));
351
+ const framework = await createFrameworkWithCodeExecution(storePath, membrane, module);
352
+ try {
353
+ const created = await framework.createEphemeralAgent({
354
+ name: 'worker',
355
+ model: 'test-model',
356
+ systemPrompt: 'Do the task.',
357
+ allowedTools: 'all',
358
+ });
359
+ created.contextManager.addMessage('user', [{ type: 'text', text: 'Go.' }]);
360
+ const promise = framework.runEphemeralToCompletion(created.agent, created.contextManager);
361
+ framework.start();
362
+ const result = await promise;
363
+ assert.strictEqual(result.speech, 'Final answer.');
364
+ // The module saw both inner calls, dispatched with pytc- IDs (waiter
365
+ // path), not the model's call ID.
366
+ const echoCalls = module.calls.filter((c) => c.name.endsWith('--echo') || c.name === 'echo');
367
+ assert.strictEqual(echoCalls.length, 2);
368
+ for (const call of echoCalls) {
369
+ assert.match(String(call.id), /^pytc-/);
370
+ }
371
+ // The model-facing tool_result carries the script's stdout...
372
+ const stream = membrane.lastStream;
373
+ assert.strictEqual(stream.receivedToolResults.length, 1);
374
+ const wireResult = stream.receivedToolResults[0][0];
375
+ assert.strictEqual(wireResult.toolUseId, 'call_ce_1');
376
+ assert.match(wireResult.content, /summary: ALPHA\+BETA/);
377
+ assert.match(wireResult.content, /"return_code":\s*0/);
378
+ // ...and NOT the intermediate tool results.
379
+ assert.ok(!wireResult.content.includes('"echoed"'), 'intermediate tool results must not reach the model-facing result');
380
+ }
381
+ finally {
382
+ await framework.stop();
383
+ rmSync(tempDir, { recursive: true, force: true });
384
+ }
385
+ });
386
+ it('defers endTurn from inner calls to the code_execution result', async () => {
387
+ const { tempDir, storePath } = tempStorePath('pytc-endturn-');
388
+ const membrane = new MockMembrane();
389
+ const module = new ScriptToolModule();
390
+ const code = [
391
+ 'r = await test__finish({})',
392
+ 'print("after finish:", r)',
393
+ ].join('\n');
394
+ membrane.pushResponse(createMockResponse([
395
+ { type: 'text', text: 'Finishing via script.' },
396
+ { type: 'tool_use', id: 'call_ce_2', name: 'code_execution', input: { code } },
397
+ ], 'tool_use'));
398
+ // No further response: endTurn must settle the turn without another round.
399
+ const framework = await createFrameworkWithCodeExecution(storePath, membrane, module);
400
+ try {
401
+ const created = await framework.createEphemeralAgent({
402
+ name: 'finisher',
403
+ model: 'test-model',
404
+ systemPrompt: 'Finish.',
405
+ allowedTools: 'all',
406
+ });
407
+ created.contextManager.addMessage('user', [{ type: 'text', text: 'Wrap up.' }]);
408
+ const promise = framework.runEphemeralToCompletion(created.agent, created.contextManager);
409
+ framework.start();
410
+ const result = await promise;
411
+ // The script ran to completion (endTurn was deferred, not applied
412
+ // mid-script), and the turn then ended without another model round.
413
+ const finishCalls = module.calls.filter((c) => c.name.endsWith('--finish') || c.name === 'finish');
414
+ assert.strictEqual(finishCalls.length, 1);
415
+ assert.strictEqual(result.toolCallsCount, 1); // one model-visible call: code_execution
416
+ }
417
+ finally {
418
+ await framework.stop();
419
+ rmSync(tempDir, { recursive: true, force: true });
420
+ }
421
+ });
422
+ });
423
+ //# sourceMappingURL=code-execution.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-execution.test.js","sourceRoot":"","sources":["../../test/code-execution.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=prose-stream-router.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prose-stream-router.test.d.ts","sourceRoot":"","sources":["../../test/prose-stream-router.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,87 @@
1
+ // ProseStreamRouter: streamed routing must agree with the delivery path's
2
+ // grammar (prose-grammar.parseProsePrefix + the envelope splitter) regardless
3
+ // of how the token stream is chopped. The last test is the property that
4
+ // matters most: char-by-char feeding ≡ one-shot feeding.
5
+ import { test } from 'node:test';
6
+ import assert from 'node:assert/strict';
7
+ import { ProseStreamRouter } from '../src/mcpl/prose-stream-router.js';
8
+ const RESOLVE = {
9
+ '#general': 'discord:g:100',
10
+ '#ops': 'discord:g:200',
11
+ '@sol': 'discord:dm:300',
12
+ };
13
+ function explicit() {
14
+ return new ProseStreamRouter({
15
+ mode: 'explicit',
16
+ initialTarget: null,
17
+ resolve: (spec) => RESOLVE[spec] ?? null,
18
+ });
19
+ }
20
+ function run(r, text, chunk = text.length) {
21
+ const out = [];
22
+ for (let i = 0; i < text.length; i += chunk)
23
+ out.push(...r.feed(text.slice(i, i + chunk)));
24
+ out.push(...r.finish());
25
+ return out;
26
+ }
27
+ function textFor(deltas, ch) {
28
+ return deltas.filter((d) => d.channelId === ch).map((d) => d.delta).join('');
29
+ }
30
+ test('locus mode: pure passthrough, >> lines are plain text', () => {
31
+ const r = new ProseStreamRouter({ mode: 'locus', initialTarget: 'discord:g:100', resolve: () => null });
32
+ const out = run(r, 'hello\n>>#ops not a prefix here\nbye');
33
+ assert.equal(textFor(out, 'discord:g:100'), 'hello\n>>#ops not a prefix here\nbye');
34
+ });
35
+ test('explicit: unprefixed leading text is suppressed (delivery would bounce it)', () => {
36
+ const out = run(explicit(), 'no destination yet\n>>#general now routed');
37
+ assert.equal(textFor(out, 'discord:g:100'), 'now routed');
38
+ assert.equal(out.every((d) => !d.delta.includes('no destination')), true);
39
+ });
40
+ test('explicit: multi-envelope switching, prefixes swallowed', () => {
41
+ const out = run(explicit(), '>>#general hello there\nstill general\n>>#ops aside for ops\n>>@sol dm line');
42
+ assert.equal(textFor(out, 'discord:g:100'), 'hello there\nstill general\n');
43
+ assert.equal(textFor(out, 'discord:g:200'), 'aside for ops\n');
44
+ assert.equal(textFor(out, 'discord:dm:300'), 'dm line');
45
+ });
46
+ test('quoted `>> arrow` and lone `>` stay body text', () => {
47
+ const out = run(explicit(), '>>#general look:\n>> quoted arrow\n> markdown quote\ndone');
48
+ assert.equal(textFor(out, 'discord:g:100'), 'look:\n>> quoted arrow\n> markdown quote\ndone');
49
+ });
50
+ test('skip_reply suppresses; later envelope resumes', () => {
51
+ const out = run(explicit(), '>>skip_reply private thought\n>>#ops public line');
52
+ assert.equal(out.every((d) => !d.delta.includes('private')), true);
53
+ assert.equal(textFor(out, 'discord:g:200'), 'public line');
54
+ });
55
+ test('unresolvable target suppresses that envelope only', () => {
56
+ const out = run(explicit(), '>>#nonexistent to nowhere\n>>#general to somewhere');
57
+ assert.equal(out.every((d) => !d.delta.includes('nowhere')), true);
58
+ assert.equal(textFor(out, 'discord:g:100'), 'to somewhere');
59
+ });
60
+ test('` !` continuation modifier is swallowed; `!` as body survives', () => {
61
+ const out = run(explicit(), '>>#general ! next turn continues\n>>#ops !bang body');
62
+ assert.equal(textFor(out, 'discord:g:100'), 'next turn continues\n');
63
+ // grammar: `([ \t]+!)?` — the first ! after whitespace is the modifier,
64
+ // remainder is body (matches parseProsePrefix on ">>#ops !bang body").
65
+ assert.equal(textFor(out, 'discord:g:200'), 'bang body');
66
+ });
67
+ test('prefix on its own line routes the following lines', () => {
68
+ const out = run(explicit(), '>>#general\nbody on next line\nand more');
69
+ assert.equal(textFor(out, 'discord:g:100'), 'body on next line\nand more');
70
+ });
71
+ test('byChannel accumulates exactly the emitted text', () => {
72
+ const r = explicit();
73
+ run(r, '>>#general one\n>>#ops two');
74
+ assert.equal(r.byChannel().get('discord:g:100'), 'one\n');
75
+ assert.equal(r.byChannel().get('discord:g:200'), 'two');
76
+ });
77
+ test('PROPERTY: char-by-char ≡ one-shot, across every chunk size', () => {
78
+ const text = 'lead-in ignored\n>>#general alpha\nbeta > gamma\n>> not a prefix\n>>#ops ! delta\n>>skip_reply hidden\n>>#general {{unsent}} tail';
79
+ const oneShot = run(explicit(), text);
80
+ for (const size of [1, 2, 3, 5, 7, 11]) {
81
+ const chunked = run(explicit(), text, size);
82
+ for (const ch of Object.values(RESOLVE)) {
83
+ assert.equal(textFor(chunked, ch), textFor(oneShot, ch));
84
+ }
85
+ }
86
+ });
87
+ //# sourceMappingURL=prose-stream-router.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prose-stream-router.test.js","sourceRoot":"","sources":["../../test/prose-stream-router.test.ts"],"names":[],"mappings":"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"}