File size: 1,776 Bytes
68d7816
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { createUserMessage } from '#/llm/message';
import type { Plugin } from '#/plugin';

import type { ToolSelectState } from './state';
import { createSelectToolsTool } from './tool';

export const LOADABLE_TOOLS_REMINDER_KEY = 'loadable-tools';
export const DYNAMIC_TOOL_SCHEMA_REMINDER_KEY = 'dynamic-tool-schemas';

export interface ToolSelectPlugin extends Plugin {
  readonly name: 'tool-select';
}

export function createToolSelectPlugin(state: ToolSelectState): ToolSelectPlugin {
  return {
    name: 'tool-select',
    tools: () => [createSelectToolsTool(state)],
    connect(target) {
      if (target.kind !== 'agent') return;
      target.on('turn.started', (event) => {
        if (event.type !== 'turn.started') return;
        if (!state.enabled()) return;
        const announcement = state.announcement();
        if (announcement === undefined) return;
        target.remind(LOADABLE_TOOLS_REMINDER_KEY, createUserMessage(announcement));
      });
      const pushSchemas = () => {
        if (!state.enabled()) return;
        const tools = state.pendingSchemas();
        if (tools.length === 0) return;
        target.remind(DYNAMIC_TOOL_SCHEMA_REMINDER_KEY, { role: 'system', content: [], tools });
      };
      target.on('tool.done', pushSchemas);
      target.on('tool.failed', pushSchemas);
      target.on('turn.reminders_consumed', (event) => {
        if (event.type !== 'turn.reminders_consumed') return;
        for (const entry of event.reminders) {
          if (entry.meta?.key === LOADABLE_TOOLS_REMINDER_KEY) state.markAnnounced();
          if (entry.meta?.key === DYNAMIC_TOOL_SCHEMA_REMINDER_KEY) state.markSchemasLanded();
        }
      });
      target.on('context.reset', () => {
        state.reset();
      });
    },
  };
}