File size: 1,735 Bytes
4e23b01 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | import type { SystemMessage, UserMessage } from '#/llm/message';
import type { AgentEmitted } from '#/agent/machine';
import { createSystemEntry, createUserEntry, type SystemEntry, type UserEntry } from '#/agent/turn';
import type { ToolDefinition } from '#/tool/tool';
export interface AgentPluginTarget {
kind: 'agent';
on(type: AgentEmitted['type'], handler: (event: AgentEmitted) => void): unknown;
notify(message: UserMessage): void;
remind(key: string, message: UserMessage | SystemMessage): void;
}
export type PluginTarget = AgentPluginTarget;
export interface Plugin {
readonly name: string;
tools?(): readonly ToolDefinition[];
connect?(target: PluginTarget): void;
}
export function collectPluginTools(plugins: readonly Plugin[]): readonly ToolDefinition[] {
return plugins.flatMap((plugin) => plugin.tools?.() ?? []);
}
export interface AgentPluginSource {
on(type: AgentEmitted['type'], handler: (event: AgentEmitted) => void): unknown;
send(
event:
| { type: 'input.notify'; entry: UserEntry }
| { type: 'input.remind'; key: string; entry: SystemEntry | UserEntry },
): void;
}
export function connectPlugins(actor: AgentPluginSource, plugins: readonly Plugin[]): void {
const target: AgentPluginTarget = {
kind: 'agent',
on: (type, handler) => {
actor.on(type, handler);
},
notify: (message) => {
actor.send({ type: 'input.notify', entry: { message } });
},
remind: (key, message) => {
actor.send({
type: 'input.remind',
key,
entry: message.role === 'system' ? createSystemEntry(message) : createUserEntry(message),
});
},
};
for (const plugin of plugins) {
plugin.connect?.(target);
}
}
|