feat(agent): add Matrix native runtime provider (#744)
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful

This commit was merged in pull request #744.
This commit is contained in:
2026-07-13 15:29:37 +00:00
parent c6e3cfbd95
commit 6345dbfcf2
7 changed files with 1231 additions and 0 deletions

View File

@@ -0,0 +1,153 @@
import { describe, expect, it, vi } from 'vitest';
import type { RuntimeScope, RuntimeStreamEvent } from '@mosaicstack/types';
import {
type MatrixRuntimeSession,
type MatrixRuntimeTransport,
MatrixNativeRuntimeProvider,
type MatrixReadAuthority,
type MatrixWriteAuthority,
} from './matrix-native-runtime-provider.js';
const scope: RuntimeScope = {
actorId: 'operator-1',
tenantId: 'tenant-a',
channelId: 'matrix-control',
correlationId: 'corr-1',
};
const session: MatrixRuntimeSession = {
id: 'native-1',
runtimeId: '@worker:example.test',
state: 'active',
createdAt: '2026-07-13T00:00:00.000Z',
updatedAt: '2026-07-13T00:00:00.000Z',
};
function transport(): MatrixRuntimeTransport {
return {
health: vi.fn(async () => ({
status: 'healthy' as const,
checkedAt: '2026-07-13T00:00:00.000Z',
})),
listSessions: vi.fn(async () => [session]),
verifySession: vi.fn(async (sessionId) => {
if (sessionId !== session.id) throw new Error('unexpected session');
return session;
}),
stream: vi.fn(async function* (): AsyncIterable<RuntimeStreamEvent> {
yield {
type: 'message.delta',
sessionId: 'native-1',
cursor: 'cursor-1',
occurredAt: '2026-07-13T00:00:00.000Z',
content: 'hello',
};
}),
send: vi.fn(async () => undefined),
terminate: vi.fn(async () => undefined),
};
}
function readAuthority(): MatrixReadAuthority {
return { canRead: vi.fn(async () => true) };
}
function writeAuthority(): MatrixWriteAuthority {
return {
canWrite: vi.fn(async () => true),
assertAuthorized: vi.fn(async () => undefined),
};
}
describe('MatrixNativeRuntimeProvider contract boundary', (): void => {
it('advertises the concrete Matrix operations and returns only normalized sessions', async (): Promise<void> => {
const provider = new MatrixNativeRuntimeProvider({
transport: transport(),
readAuthority: readAuthority(),
});
await expect(provider.capabilities(scope)).resolves.toEqual({
supported: [
'session.list',
'session.tree',
'session.stream',
'session.send',
'session.attach',
'session.terminate',
],
});
await expect(provider.listSessions(scope)).resolves.toEqual([
expect.objectContaining({ id: 'native-1', providerId: 'runtime.matrix' }),
]);
});
it('binds read attachments to immutable scope and rejects control mode before transport access', async (): Promise<void> => {
const matrix = transport();
const provider = new MatrixNativeRuntimeProvider({
transport: matrix,
readAuthority: readAuthority(),
attachmentIdFactory: () => 'attachment-1',
now: () => new Date('2026-07-13T00:00:00.000Z'),
});
await expect(provider.attach('native-1', 'control', scope)).rejects.toMatchObject({
code: 'forbidden',
});
expect(matrix.verifySession).not.toHaveBeenCalled();
await provider.attach('native-1', 'read', scope);
await expect(
provider.detach('attachment-1', { ...scope, tenantId: 'other' }),
).rejects.toMatchObject({
code: 'forbidden',
});
});
it('validates messages and applies exact Matrix authority after bound-session verification', async (): Promise<void> => {
const matrix = transport();
const writes = writeAuthority();
const provider = new MatrixNativeRuntimeProvider({
transport: matrix,
readAuthority: readAuthority(),
writeAuthority: writes,
});
await expect(
provider.sendMessage('native-1', { content: '', idempotencyKey: 'msg-1' }, scope),
).rejects.toMatchObject({
code: 'invalid_request',
});
expect(matrix.verifySession).not.toHaveBeenCalled();
await provider.sendMessage('native-1', { content: 'hello', idempotencyKey: 'msg-1' }, scope);
expect(writes.assertAuthorized).toHaveBeenCalledWith({
operation: 'session.send',
sessionId: 'native-1',
scope,
});
expect(matrix.send).toHaveBeenCalledWith(
'native-1',
{ content: 'hello', idempotencyKey: 'msg-1' },
scope,
);
});
it('streams only after exact read authorization', async (): Promise<void> => {
const matrix = transport();
const provider = new MatrixNativeRuntimeProvider({
transport: matrix,
readAuthority: readAuthority(),
});
await expect(collect(provider.streamSession('native-1', 'cursor-0', scope))).resolves.toEqual([
expect.objectContaining({ type: 'message.delta', sessionId: 'native-1' }),
]);
expect(matrix.stream).toHaveBeenCalledWith('native-1', 'cursor-0', scope);
});
});
async function collect(stream: AsyncIterable<RuntimeStreamEvent>): Promise<RuntimeStreamEvent[]> {
const values: RuntimeStreamEvent[] = [];
for await (const value of stream) values.push(value);
return values;
}