Bind local handlers by validated command
The policy implementation follows.
ts
export function bindInteraction<
Value extends object,
Parsed,
Args extends unknown[],
Id extends string,
Context,
Output,
>(
protocol: {
readonly commands: Pick<InteractionProtocol<Value, Parsed, Args, Id>['commands'], 'manifest'>;
receive(value: Value, ...args: Args): { id: Id; result: Parsed };
},
handlers: InteractionHandlers<Id, Parsed, Context, Output>,
) {
const catalog = Object.freeze(
protocol.commands.manifest().map((command) =>
Object.freeze({
id: command.id,
category: command.category,
description: command.description,
terminal: command.terminal,
modes: command.modes && Object.freeze([...command.modes]),
}),
),
);
const receive = protocol.receive.bind(protocol);
const ids = new Set(catalog.map((command) => command.id));
breakWhile(
[
{
occur: () =>
catalog.some(
(command) =>
typeof handlers[command.id as Id] !== 'function' ||
(!Object.hasOwn(handlers, command.id) &&
(command.id === 'constructor' ||
handlers[command.id as Id] === Reflect.get(Object.prototype, command.id))),
),
error: 'Missing interaction handler',
tags: ['missing-handler'],
},
{
occur: () => Object.keys(handlers).some((id) => !ids.has(id)),
error: 'Unregistered interaction handler',
tags: ['unknown-handler'],
},
],
['agent-core', 'interaction-registration'],
);
const registered = Object.freeze(
Object.fromEntries(catalog.map(({ id }) => [id, handlers[id as Id].bind(handlers)])) as Record<
Id,
(value: Parsed, context: Context) => Output
>,
);
return Object.freeze({
catalog,
dispatch(value: Value, context: Context, ...args: Args): Output {
// Select from the validated wire value, never from a formatter's unconstrained output.
const { id, result } = receive(value, ...args);
return registered[id](result, context);
},
});
}