blob: 742e326bb22321d105d0774a2278438a29e37959 [file]
import assert from 'node:assert/strict';
import { describe, test } from 'node:test';
import {
decodeClientFrame,
decodeExternalSessionCatalogQueryResult,
decodeExternalSessionSourceQueryResult,
EXTERNAL_SESSION_PAGE_MAX_ITEMS,
HOST_OPERATION_SPECS,
RuntimeHostProtocolError,
} from '../protocol/index.js';
describe('external Session protocol', () => {
test('declares three bounded ready-only operations', () => {
assert.deepEqual(
Object.fromEntries(
(
[
'external-session.source.query',
'external-session.catalog.query',
'external-session.import',
] as const
).map((operation) => [
operation,
{
mode: HOST_OPERATION_SPECS[operation].mode,
availability: HOST_OPERATION_SPECS[operation].availability,
},
]),
),
{
'external-session.source.query': { mode: 'query', availability: 'ready' },
'external-session.catalog.query': { mode: 'query', availability: 'ready' },
'external-session.import': { mode: 'command', availability: 'ready' },
},
);
});
test('round-trips exact source, catalog, and import inputs', () => {
assert.deepEqual(
decodeClientFrame({
requestId: 'request-source',
operation: 'external-session.source.query',
input: {},
}),
{
requestId: 'request-source',
operation: 'external-session.source.query',
input: {},
},
);
assert.deepEqual(
decodeClientFrame({
requestId: 'request-list',
operation: 'external-session.catalog.query',
input: {
adapterId: 'codex',
includeArchived: true,
cwd: '/workspace',
cursor: '16',
},
}),
{
requestId: 'request-list',
operation: 'external-session.catalog.query',
input: {
adapterId: 'codex',
includeArchived: true,
cwd: '/workspace',
cursor: '16',
},
},
);
assert.deepEqual(
decodeClientFrame({
requestId: 'request-import',
operation: 'external-session.import',
input: { adapterId: 'codex', sourceSessionId: 'source-session-1' },
}),
{
requestId: 'request-import',
operation: 'external-session.import',
input: { adapterId: 'codex', sourceSessionId: 'source-session-1' },
},
);
});
test('rejects open-ended, malformed, and oversized frames', () => {
assert.throws(
() =>
decodeClientFrame({
requestId: 'request-extra',
operation: 'external-session.source.query',
input: { source: 'codex' },
}),
isProtocolError,
);
assert.throws(
() =>
decodeClientFrame({
requestId: 'request-cursor',
operation: 'external-session.catalog.query',
input: { adapterId: 'codex', cursor: '-1' },
}),
isProtocolError,
);
assert.throws(
() =>
decodeClientFrame({
requestId: 'request-id',
operation: 'external-session.import',
input: { adapterId: 'codex', sourceSessionId: 'bad\nsource' },
}),
isProtocolError,
);
assert.throws(
() =>
decodeExternalSessionCatalogQueryResult({
sessions: Array.from({ length: EXTERNAL_SESSION_PAGE_MAX_ITEMS + 1 }, (_, index) => ({
id: `source-${index}`,
name: `Session ${index}`,
cwd: '/workspace',
})),
nextCursor: null,
}),
isProtocolError,
);
assert.throws(
() => decodeExternalSessionSourceQueryResult({ adapterIds: ['codex'], extra: true }),
isProtocolError,
);
});
});
function isProtocolError(error: unknown): boolean {
return error instanceof RuntimeHostProtocolError && error.code === 'invalid_frame';
}