import type { CompactToolsOptions, ToolPlan } from './types.ts'; const DEFAULT_HEADER = `# Wire format Use toolName key=value instead of JSON tools. Examples: getWeather location=Austin units=metric bookMeeting title="Review" date=2026-05-15 duration=60 attendees=["a@c.com"] room=A Values: bare if safe (text=hello), "quotes" if spaces, 'quotes' if inner ", numbers/booleans unquoted, arrays as ["a","b"], nested as parent.child=val. tools use {"key":"val"} inside the call. Only is parsed — no native JSON tool calls.`; export function buildSystemPrompt(plans: ToolPlan[], options: CompactToolsOptions): string { const header = options.manualHeader ?? getDefaultHeader(options.syntax ?? 'wire'); if (plans.length === 0) return header; const lines = plans.map(p => `- ${p.signature}`).join('\n'); return `${header}\n\n## Available tools\n\n${lines}`; } function getDefaultHeader(syntax: 'wire' | 'json'): string { return DEFAULT_HEADER; } /** * Inject the generated system prompt into the existing prompt: * - Concatenate to existing leading `system` message, or * - Insert a new `system` message at first/last per `placement`. */ export function injectSystemPrompt( prompt: M[], toolManual: string, placement: 'first' | 'last', ): M[] { const out = prompt.slice(); // Concatenate into the first existing `system` message if present. for (let i = 0; i < out.length; i++) { const m = out[i] as M; if (m.role === 'system' && typeof m.content === 'string') { const merged = placement === 'first' ? `${toolManual}\n\n${m.content}` : `${m.content}\n\n${toolManual}`; out[i] = { ...m, content: merged } as M; return out; } } // No system message: insert one. const sysMsg = { role: 'system', content: toolManual } as unknown as M; if (placement === 'first') return [sysMsg, ...out]; return [...out, sysMsg]; }