(options: AgentCoreOptions)
| 25 | } |
| 26 | |
| 27 | export async function runAgentCore(options: AgentCoreOptions): Promise<AgentCoreResult> { |
| 28 | const { |
| 29 | piModel, |
| 30 | apiKey, |
| 31 | systemPrompt, |
| 32 | tools, |
| 33 | history, |
| 34 | userMessage, |
| 35 | maxToolRounds = DEFAULT_MAX_TOOL_ROUNDS, |
| 36 | abortSignal, |
| 37 | steerMessage = 'Please provide your final answer based on the information gathered.', |
| 38 | onEvent, |
| 39 | onConvertToLlm, |
| 40 | onDebugContext, |
| 41 | } = options |
| 42 | |
| 43 | // 确保 cl100k rank 表已加载,压缩/预处理路径使用精确 token 计数 |
| 44 | await initTokenizer() |
| 45 | |
| 46 | const resolvedStreamFn = (options.streamFn ?? defaultStreamSimple) as typeof defaultStreamSimple |
| 47 | |
| 48 | const totalUsage: AgentTokenUsage = { |
| 49 | promptTokens: 0, |
| 50 | completionTokens: 0, |
| 51 | totalTokens: 0, |
| 52 | cacheReadTokens: 0, |
| 53 | cacheWriteTokens: 0, |
| 54 | } |
| 55 | const toolsUsed: string[] = [] |
| 56 | let toolRounds = 0 |
| 57 | |
| 58 | const addPiUsage = (usage?: PiUsage) => { |
| 59 | if (!usage) return |
| 60 | totalUsage.promptTokens += usage.input || 0 |
| 61 | totalUsage.completionTokens += usage.output || 0 |
| 62 | totalUsage.totalTokens += usage.totalTokens || usage.input + usage.output || 0 |
| 63 | totalUsage.cacheReadTokens += usage.cacheRead || 0 |
| 64 | totalUsage.cacheWriteTokens += usage.cacheWrite || 0 |
| 65 | } |
| 66 | |
| 67 | if (abortSignal?.aborted) { |
| 68 | return { usage: totalUsage, finalMessages: [], toolsUsed: [], toolRounds: 0 } |
| 69 | } |
| 70 | |
| 71 | // Resolve thinkingLevel for pi-agent-core: |
| 72 | // - 'default'/undefined → strip reasoning from piModel so pi-ai sends a plain request |
| 73 | // with NO reasoning params at all (model uses its native default behavior). |
| 74 | // - 'off' → pi-ai sends disable signals (thinking:{type:'disabled'} / enable_thinking:false) |
| 75 | // - 'auto' → for thinkingFormat models or effort-based models with thinkingLevelMap, |
| 76 | // use 'high' to enable; others no params. |
| 77 | // Note: pi-ai's clampThinkingLevel only covers EXTENDED_THINKING_LEVELS (no 'auto'), |
| 78 | // so 'auto' cannot be forwarded verbatim for effort-based models like Kimi/Doubao. |
| 79 | // Returning 'high' ensures reasoning is at least enabled. |
| 80 | // - Other levels → clamp to what pi-agent-core accepts. |
| 81 | const isDefault = !options.thinkingLevel || options.thinkingLevel === 'default' |
| 82 | const effectiveModel = isDefault |
| 83 | ? { ...piModel, reasoning: false, compat: undefined, thinkingLevelMap: undefined } |
| 84 | : piModel |
no test coverage detected