Download packages/agent-core-v2/src/agent/toolSelect/dynamicTools.ts from SaylorTwift/kimi-code: direct link, hf CLI and curl.
- Browser
- Download file 3.36 kB
-
https://huggingface.co/SaylorTwift/kimi-code/resolve/main/packages/agent-core-v2/src/agent/toolSelect/dynamicTools.ts
- Command line
-
hf download hf://SaylorTwift/kimi-code/packages/agent-core-v2/src/agent/toolSelect/dynamicTools.ts
-
curl -L -o dynamicTools.ts https://huggingface.co/SaylorTwift/kimi-code/resolve/main/packages/agent-core-v2/src/agent/toolSelect/dynamicTools.ts
3.36 kB
| import type { ContextMessage } from '#/agent/contextMemory/types'; | |
| export const DYNAMIC_TOOL_SCHEMA_VARIANT = 'dynamic_tool_schema'; | |
| export const LOADABLE_TOOLS_VARIANT = 'loadable-tools'; | |
| export function isDynamicToolSchemaMessage(message: ContextMessage): boolean { | |
| return message.tools !== undefined && message.tools.length > 0; | |
| } | |
| export function isLoadableToolsAnnouncement(message: ContextMessage): boolean { | |
| const origin = message.origin; | |
| if (origin?.kind === 'injection') return origin.variant === LOADABLE_TOOLS_VARIANT; | |
| return origin?.kind === 'system_trigger' && origin.name === LOADABLE_TOOLS_VARIANT; | |
| } | |
| export function stripDynamicToolContext( | |
| history: readonly ContextMessage[], | |
| ): readonly ContextMessage[] { | |
| if (!history.some((m) => isDynamicToolSchemaMessage(m) || isLoadableToolsAnnouncement(m))) { | |
| return history; | |
| } | |
| const out: ContextMessage[] = []; | |
| for (const message of history) { | |
| if (isLoadableToolsAnnouncement(message)) continue; | |
| if (isDynamicToolSchemaMessage(message)) { | |
| const { tools: _tools, ...rest } = message; | |
| void _tools; | |
| if (rest.content.length === 0 && rest.toolCalls.length === 0) continue; | |
| out.push(rest); | |
| continue; | |
| } | |
| out.push(message); | |
| } | |
| return out; | |
| } | |
| export function collectLoadedDynamicToolNames( | |
| history: readonly ContextMessage[], | |
| ): Set<string> { | |
| const names = new Set<string>(); | |
| for (const message of history) { | |
| if (message.tools === undefined) continue; | |
| for (const tool of message.tools) { | |
| names.add(tool.name); | |
| } | |
| } | |
| return names; | |
| } | |
| const TOOLS_ADDED_BLOCK = /<tools_added>\n?([\s\S]*?)\n?<\/tools_added>/g; | |
| const TOOLS_REMOVED_BLOCK = /<tools_removed>\n?([\s\S]*?)\n?<\/tools_removed>/g; | |
| export function foldAnnouncedToolNames(history: readonly ContextMessage[]): Set<string> { | |
| const announced = new Set<string>(); | |
| for (const message of history) { | |
| if (!isLoadableToolsAnnouncement(message)) continue; | |
| const text = message.content | |
| .map((part) => (part.type === 'text' ? part.text : '')) | |
| .join(''); | |
| for (const name of matchToolNameBlocks(text, TOOLS_REMOVED_BLOCK)) { | |
| announced.delete(name); | |
| } | |
| for (const name of matchToolNameBlocks(text, TOOLS_ADDED_BLOCK)) { | |
| announced.add(name); | |
| } | |
| } | |
| return announced; | |
| } | |
| function matchToolNameBlocks(text: string, pattern: RegExp): string[] { | |
| const names: string[] = []; | |
| pattern.lastIndex = 0; | |
| for (const match of text.matchAll(pattern)) { | |
| const body = match[1] ?? ''; | |
| for (const line of body.split('\n')) { | |
| const name = line.trim(); | |
| if (name.length > 0) names.push(name); | |
| } | |
| } | |
| return names; | |
| } | |
| export function renderLoadableToolsAnnouncement( | |
| added: readonly string[], | |
| removed: readonly string[], | |
| ): string { | |
| const sections: string[] = []; | |
| if (added.length > 0) { | |
| sections.push(`<tools_added>\n${added.join('\n')}\n</tools_added>`); | |
| } | |
| if (removed.length > 0) { | |
| sections.push(`<tools_removed>\n${removed.join('\n')}\n</tools_removed>`); | |
| } | |
| sections.push( | |
| 'Use the select_tools tool with exact names to load full tool definitions before calling them. ' + | |
| 'Names listed as removed are no longer loadable — do not select them. ' + | |
| 'Fold all announcements in this conversation in order to get the current list.', | |
| ); | |
| return sections.join('\n\n'); | |
| } | |