Pinned pi SDK 0.85.1 bridge, Python supervisor, artifact exporter, scripted backend peer, image checks and boundary checks under agent/**. Review findings F1-F3 are recorded in docs/implementation/PI_AGENT_REVIEW.md.
86 lines
5.3 KiB
TypeScript
86 lines
5.3 KiB
TypeScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { PassThrough, Writable } from 'node:stream';
|
|
import { NDJsonFrameParser, StreamMessageWriter, sanitizeError } from '../framing.js';
|
|
import { envelope } from '../validation.js';
|
|
|
|
async function parse(chunks: Buffer[], max = 1024) {
|
|
const input = new PassThrough(); const parser = new NDJsonFrameParser(max);
|
|
input.pipe(parser);
|
|
const result = (async () => { const frames = []; for await (const frame of parser) frames.push(frame); return frames; })();
|
|
for (const c of chunks) input.write(c); input.end();
|
|
return result;
|
|
}
|
|
test('fragmented and coalesced UTF-8 frames, escaping', async () => {
|
|
const a = { v: 1, type: 'collection_ready', id: 'b_1', reply_to: 'a_1', payload: {} };
|
|
const b = { text: '雪 🐈 \\ " \n' };
|
|
const wire = Buffer.from(JSON.stringify(a) + '\n' + JSON.stringify(b) + '\n');
|
|
assert.deepEqual(await parse([...wire].map(x => Buffer.from([x]))), [a, b]);
|
|
assert.deepEqual(await parse([wire]), [a, b]);
|
|
});
|
|
test('invalid UTF-8, empty, malformed, oversized and truncated lines fail', async () => {
|
|
for (const bytes of [Buffer.from('\n'), Buffer.from('{\n'), Buffer.from('{"x":"\xff"}\n', 'latin1'), Buffer.alloc(65, 65), Buffer.from('{}')]) {
|
|
await assert.rejects(parse([bytes], 64));
|
|
}
|
|
assert.deepEqual(await parse([Buffer.from('{}\n')], 2), [{}]);
|
|
});
|
|
test('envelopes reject extra fields, wrong IDs and wrong versions', () => {
|
|
const a = { v: 1, type: 'collection_ready', id: 'b_1', reply_to: 'a_1', payload: {} };
|
|
envelope(a);
|
|
for (const b of [{ ...a, extra: true }, { ...a, v: 2 }, { ...a, id: 'a_1' }, { ...a, payload: { extra: true } }, { ...a, reply_to: 'invalid/path' }]) assert.throws(() => envelope(b));
|
|
});
|
|
test('serialized concurrent writes await slow callbacks and preserve order', async () => {
|
|
const lines: string[] = [];
|
|
const stream = new Writable({ highWaterMark: 1, write(chunk, _encoding, cb) { setTimeout(() => { lines.push(chunk.toString()); cb(); }, 5); } });
|
|
const writer = new StreamMessageWriter(stream);
|
|
await Promise.all(Array.from({ length: 8 }, (_, i) => writer.write({ v: 1, type: 'x', id: `a_${i}`, payload: {} })));
|
|
assert.deepEqual(lines.map(x => JSON.parse(x).id), Array.from({ length: 8 }, (_, i) => `a_${i}`));
|
|
});
|
|
test('terminal diagnostics never echo arbitrary exception content', () => {
|
|
assert(!JSON.stringify(sanitizeError('invalid_input', new Error('SECRET_PROMPT'))).includes('SECRET'));
|
|
assert.equal(sanitizeError('SECRET_CODE', 'SECRET_BODY').code, 'execution_failed');
|
|
});
|
|
|
|
test('fragment serializer preserves escaping and surrogate pairs across chunks', async () => {
|
|
const { jsonPieces, jsonBytes } = await import('../json.js');
|
|
const value = { text: 'x'.repeat(16383) + '🐈\u0001\n"\\', nested: [{ unicode: '雪' }, null, true, 3] };
|
|
const encoded = [...jsonPieces(value)].join('');
|
|
assert.equal(encoded, JSON.stringify(value));
|
|
assert.deepEqual(JSON.parse(encoded), value);
|
|
assert.equal(jsonBytes(value), Buffer.byteLength(encoded));
|
|
assert(jsonBytes(value, 32) > 32);
|
|
});
|
|
|
|
test('terminal write replaces backlog only after the active large NDJSON frame', async () => {
|
|
const chunks: string[] = []; let started!: () => void;
|
|
const first = new Promise<void>(resolve => started = resolve);
|
|
const stream = new Writable({ highWaterMark: 1, write(chunk, _encoding, cb) {
|
|
chunks.push(chunk.toString()); started(); setTimeout(cb, 8);
|
|
} });
|
|
const writer = new StreamMessageWriter(stream);
|
|
const large = { v: 1, type: 'collection_start', id: 'a_1', payload: { markdown: '雪'.repeat(100000), warnings: [] } };
|
|
const active = writer.write(large);
|
|
const queued = writer.write({ v: 1, type: 'artifact_begin', id: 'a_2', payload: {} });
|
|
const cancelled = assert.rejects(queued, /cancelled/);
|
|
await first;
|
|
const terminal = writer.writeTerminal({ v: 1, type: 'error', id: 'a_3', payload: sanitizeError('query_timeout') });
|
|
await Promise.all([active, cancelled, terminal, writer.close()]);
|
|
assert.deepEqual(chunks.join('').trimEnd().split('\n').map(line => JSON.parse(line)), [large, { v: 1, type: 'error', id: 'a_3', payload: sanitizeError('query_timeout') }]);
|
|
await assert.rejects(writer.write(large), /closed/);
|
|
});
|
|
test('a started terminal frame cannot be followed by another terminal message', async () => {
|
|
let release!: () => void; const chunks: string[] = [];
|
|
const stream = new Writable({ write(chunk, _encoding, cb) { chunks.push(chunk.toString()); release = () => cb(); } });
|
|
const writer = new StreamMessageWriter(stream);
|
|
const complete = writer.write({ v: 1, type: 'complete', id: 'a_1', payload: { accepted_transfer_count: 0 } });
|
|
await assert.rejects(writer.writeTerminal({ v: 1, type: 'error', id: 'a_2', payload: sanitizeError('query_timeout') }), /already started/);
|
|
release(); await complete; await writer.close();
|
|
assert.equal(chunks.join('').trimEnd().split('\n').length, 1);
|
|
});
|
|
test('broken output rejects active and queued frames and reports failed drain', async () => {
|
|
const stream = new Writable({ write(_chunk, _encoding, cb) { setTimeout(() => cb(new Error('DUMMY_PRIVATE_ERROR')), 5); } });
|
|
const writer = new StreamMessageWriter(stream);
|
|
await Promise.all([1, 2].map(i => assert.rejects(writer.write({ v: 1, type: 'x', id: `a_${i}`, payload: {} }), /Output stream failed/)));
|
|
await assert.rejects(writer.close(), /Output stream failed/);
|
|
});
|