@kiturone/kapibala 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +11 -0
- package/dist/index.cjs +1940 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +636 -0
- package/dist/index.d.ts +636 -0
- package/dist/index.js +1872 -0
- package/dist/index.js.map +1 -0
- package/package.json +39 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types/index.ts","../src/errors/index.ts","../src/security/sandbox.ts","../src/tools/index.ts","../src/tools/registry.ts","../src/tools/builtin/fs.ts","../src/hooks/registry.ts","../src/executor/index.ts","../src/models/router.ts","../src/models/openai-compatible/sse.ts","../src/models/openai-compatible/index.ts","../src/store/jsonl.ts","../src/prompt/index.ts","../src/loop/index.ts","../src/session/index.ts"],"sourcesContent":["/**\n * Canonical Message & Event Types for Kapibala\n */\n\nexport type ContentBlock =\n | TextBlock\n | ToolUseBlock\n | ToolResultBlock\n | ThinkingBlock\n | RedactedThinkingBlock;\n\nexport interface TextBlock {\n type: 'text';\n text: string;\n}\n\nexport interface ToolUseBlock {\n type: 'tool_use';\n id: string;\n name: string;\n input: Record<string, unknown>;\n}\n\nexport interface ToolResultBlock {\n type: 'tool_result';\n toolUseId: string;\n content: string;\n isError?: boolean;\n /** 单次工具调用总耗时,包含 tool hooks 与实际执行。 */\n durationMs?: number;\n}\n\nexport interface ThinkingBlock {\n type: 'thinking';\n thinking: string;\n signature?: string;\n}\n\nexport interface RedactedThinkingBlock {\n type: 'redacted_thinking';\n data: string;\n}\n\nexport interface Usage {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n}\n\nexport type MessageRole = 'user' | 'assistant' | 'system' | 'tool';\n\nexport interface CanonicalMessage {\n role: MessageRole;\n content: ContentBlock[];\n timestamp?: number;\n}\n\nexport function isTextBlock(block: ContentBlock): block is TextBlock {\n return block.type === 'text';\n}\n\nexport function isToolUseBlock(block: ContentBlock): block is ToolUseBlock {\n return block.type === 'tool_use';\n}\n\nexport function isToolResultBlock(block: ContentBlock): block is ToolResultBlock {\n return block.type === 'tool_result';\n}\n\nexport function isThinkingBlock(block: ContentBlock): block is ThinkingBlock {\n return block.type === 'thinking';\n}\n\nexport interface TurnMetrics {\n turn: number;\n startTime: number;\n endTime: number;\n totalDurationMs: number;\n ttftMs?: number; // 首 token 耗时 Time To First Token\n modelDurationMs: number;\n toolDurationMs: number;\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n toolCallsCount: number;\n}\n\nexport interface RunMetrics {\n startTime: number;\n endTime: number;\n totalDurationMs: number;\n modelDurationMs: number;\n toolDurationMs: number;\n ttftMs?: number;\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n turns: number;\n toolCalls: number;\n status: 'completed' | 'failed' | 'aborted';\n /** 最近一次内部模型请求占用的上下文;不使用 run 累计 promptTokens。 */\n contextUsage?: ContextUsage;\n}\n\nexport interface ContextUsage {\n usedTokens?: number;\n limitTokens: number;\n percent?: number;\n estimatedLimit: boolean;\n}\n\nexport type StepLogStage =\n | 'model_request_start'\n | 'first_token'\n | 'model_stream_finish'\n | 'tool_execution_start'\n | 'tool_execution_finish'\n | 'turn_finish';\n\nexport interface StepLogEntry {\n timestamp: number;\n turn: number;\n stage: StepLogStage;\n message: string;\n durationMs?: number;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * AgentSession 面向宿主输出的统一进程内事件契约。\n *\n * 事件只描述 Agent 语义,不携带终端颜色、组件状态或具体 UI 类型,因此 CLI、TUI、\n * GUI 和 SDK 可以消费同一条事件流。跨进程或网络传输需要由宿主转换为独立的 wire DTO,\n * 不应直接把本类型当作长期兼容的网络协议。\n */\nexport type SessionEvent =\n | { type: 'turn_start'; turn: number }\n | { type: 'step_log'; log: StepLogEntry }\n | { type: 'text_delta'; text: string }\n | { type: 'thinking_delta'; thinking: string }\n | { type: 'tool_start'; id: string; name: string; input: Record<string, unknown> }\n | {\n type: 'tool_finish';\n id: string;\n name: string;\n result: string;\n isError: boolean;\n durationMs?: number;\n }\n /**\n * 工具结果已完成 canonical 装配并写入历史。\n * 消费方(SessionStore)据此落盘 —— 见设计文档 §4.4「tool:after 落一条 tool_result message」。\n * 该事件在熔断/中断判定之前派发,保证任何终止路径下历史结构都合法(§4.3)。\n */\n | { type: 'tool_messages'; messages: CanonicalMessage[] }\n | {\n type: 'message_stop';\n message: CanonicalMessage;\n usage?: Usage;\n ttftMs?: number;\n durationMs?: number;\n }\n | { type: 'turn_finish'; turn: number; usage?: Usage; metrics: TurnMetrics }\n | { type: 'run_finish'; metrics: RunMetrics }\n | { type: 'error'; error: Error };\n\n// 底层 Provider 吐出的原始事件流\nexport type ModelEvent =\n | { type: 'text_delta'; text: string }\n | { type: 'thinking_delta'; thinking: string }\n | { type: 'tool_call_start'; id: string; name: string }\n | { type: 'tool_call_delta'; id: string; argumentChunk: string }\n | {\n type: 'tool_call_finish';\n id: string;\n name: string;\n input: Record<string, unknown>;\n /** 参数 JSON 解析失败时置位,input 退化为 { _raw: '<原始字符串>' },便于上游诊断而非静默吞错 */\n parseError?: boolean;\n }\n | { type: 'message_stop'; usage?: Usage; ttftMs?: number; durationMs?: number };\n\nexport interface ToolDefinition {\n name: string;\n description: string;\n parameters: Record<string, unknown>; // JSON Schema\n}\n\nexport interface ModelRequest {\n systemPrompt?: string;\n messages: CanonicalMessage[];\n tools?: ToolDefinition[];\n signal?: AbortSignal;\n temperature?: number;\n maxTokens?: number;\n}\n","/**\n * Error Taxonomy for Kapibala Agent Harness\n */\n\nexport class KapibalaError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'KapibalaError';\n }\n}\n\nexport class ModelError extends KapibalaError {\n readonly status?: number;\n readonly retryable: boolean;\n\n constructor(message: string, options?: { status?: number; retryable?: boolean }) {\n super(message);\n this.name = 'ModelError';\n this.status = options?.status;\n this.retryable =\n options?.retryable ??\n (options?.status ? [429, 500, 502, 503, 504, 529].includes(options.status) : false);\n }\n}\n\nexport class TransportError extends KapibalaError {\n readonly retryable: boolean;\n\n constructor(message: string, retryable = true) {\n super(message);\n this.name = 'TransportError';\n this.retryable = retryable;\n }\n}\n\nexport class ToolError extends KapibalaError {\n constructor(message: string) {\n super(message);\n this.name = 'ToolError';\n }\n}\n\nexport class ToolNotFound extends KapibalaError {\n readonly toolName: string;\n readonly availableTools: string[];\n\n constructor(toolName: string, availableTools: string[] = []) {\n super(`Tool '${toolName}' not found. Available tools: ${availableTools.join(', ') || 'none'}`);\n this.name = 'ToolNotFound';\n this.toolName = toolName;\n this.availableTools = availableTools;\n }\n}\n\nexport class AbortError extends KapibalaError {\n constructor(message = 'Execution aborted by user') {\n super(message);\n this.name = 'AbortError';\n }\n}\n\nexport class FatalError extends KapibalaError {\n constructor(message: string) {\n super(message);\n this.name = 'FatalError';\n }\n}\n\nexport class SessionBusyError extends KapibalaError {\n constructor(operation: string) {\n super(`Session is already running; cannot ${operation}`);\n this.name = 'SessionBusyError';\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { ToolError } from '../errors/index.js';\n\nexport interface SandboxConfig {\n rootDir: string;\n /**\n * v0.0.1 恒为严格模式:任何解析后落在 rootDir 之外的物理路径一律拒绝,\n * 不存在 fail-open 开关。该字段为 v0.0.2 权限引擎预留,当前不改变校验行为。\n */\n allowSymlinks?: boolean;\n}\n\nfunction tryRealpath(target: string): string | undefined {\n try {\n return fs.realpathSync(target);\n } catch {\n return undefined;\n }\n}\n\nexport class PathSandbox {\n readonly rootDir: string;\n readonly allowSymlinks: boolean;\n private cachedRealRootDir?: string;\n\n constructor(config: SandboxConfig) {\n this.rootDir = path.resolve(config.rootDir);\n this.allowSymlinks = config.allowSymlinks ?? false;\n }\n\n /**\n * rootDir 的物理路径。rootDir 自身可能是一个符号链接(如 macOS 的 /var → /private/var),\n * 必须先归一化,否则物理路径与 rootDir 比较时会产生误判。\n */\n private get realRootDir(): string {\n if (this.cachedRealRootDir === undefined) {\n this.cachedRealRootDir = tryRealpath(this.rootDir) ?? this.rootDir;\n }\n return this.cachedRealRootDir;\n }\n\n /**\n * 检查并解析安全路径\n * 1. 解析相对路径为相对于 rootDir 的绝对路径\n * 2. 词法检查:`..` 归一化后必须仍在 rootDir 内\n * 3. 物理检查:解析符号链接后的真实路径必须仍在 rootDir 内\n */\n resolveSafePath(targetPath: string): string {\n if (!targetPath || typeof targetPath !== 'string') {\n throw new ToolError('Invalid path: path must be a non-empty string');\n }\n\n // 处理绝对路径或相对路径\n const resolvedPath = path.isAbsolute(targetPath)\n ? path.resolve(targetPath)\n : path.resolve(this.rootDir, targetPath);\n\n // 词法检查:规范化相对路径判定\n const relative = path.relative(this.rootDir, resolvedPath);\n if (relative.startsWith('..') || path.isAbsolute(relative)) {\n throw new ToolError(\n `Access denied: path '${targetPath}' escapes root directory '${this.rootDir}'`,\n );\n }\n\n // 物理检查:必须对\"目标尚不存在\"的路径同样生效\n const physicalPath = this.toPhysicalPath(resolvedPath);\n const physicalRelative = path.relative(this.realRootDir, physicalPath);\n if (physicalRelative.startsWith('..') || path.isAbsolute(physicalRelative)) {\n throw new ToolError(\n `Access denied: path '${targetPath}' resolves outside root directory '${this.rootDir}' (via symlink)`,\n );\n }\n\n return resolvedPath;\n }\n\n /**\n * 把词法路径映射为物理路径。\n *\n * 关键点在于**向上回溯到最近一个真实存在的祖先**再取 realpath,然后把尚未存在的尾段拼回去:\n * - 目标已存在 → 直接 realpath,符号链接立刻被展开;\n * - 目标不存在(典型场景:write_file 新建文件) → 若只看目标本身,所有校验都会被跳过,\n * 于是 `write_file('linkDir/new.txt')` 可以借道指向外部的 linkDir 越界写入。\n * 回溯到 linkDir 取 realpath 即可识破这种穿透。\n */\n private toPhysicalPath(resolvedPath: string): string {\n const pendingSegments: string[] = [];\n let probe = resolvedPath;\n\n while (true) {\n let stat: fs.Stats | undefined;\n try {\n stat = fs.lstatSync(probe);\n } catch {\n stat = undefined;\n }\n\n if (stat) {\n // 用 realpath 展开符号链接;悬挂符号链接(目标不存在)会在这里失败,\n // 而 writeFileSync 这类调用会顺着它在外部落盘,因此必须直接拒绝。\n const real = tryRealpath(probe);\n if (real === undefined) {\n throw new ToolError(\n `Access denied: cannot resolve real path for '${resolvedPath}' (broken or unresolvable symlink)`,\n );\n }\n return pendingSegments.length > 0 ? path.join(real, ...pendingSegments) : real;\n }\n\n const parent = path.dirname(probe);\n if (parent === probe) {\n // 已回溯到文件系统根仍不存在,退化为词法路径(由上层词法检查兜底)\n return resolvedPath;\n }\n pendingSegments.unshift(path.basename(probe));\n probe = parent;\n }\n }\n}\n","import type { ToolDefinition } from '../types/index.js';\nexport type { ToolDefinition };\n\nexport type Capability =\n | 'fs:read'\n | 'fs:write'\n | 'exec'\n | 'net:outbound'\n | 'env:read'\n | 'agent:spawn';\n\nexport interface ToolMetadata {\n source?: string;\n dangerous?: boolean;\n /** 所需能力的声明;v0.0.1 不据此授权,v0.0.2 的执行前权限决策才会消费。 */\n permissions?: Capability[];\n}\n\nexport interface ToolContext {\n rootDir: string;\n signal?: AbortSignal;\n logger?: (message: string) => void;\n}\n\nexport interface Tool<TInput = Record<string, unknown>, TOutput = unknown> {\n readonly name: string;\n readonly description: string;\n readonly parameters: Record<string, unknown>; // JSON Schema\n readonly metadata?: ToolMetadata;\n execute(input: TInput, ctx: ToolContext): Promise<TOutput>;\n}\n\nexport function defineTool<TInput = Record<string, unknown>, TOutput = unknown>(\n tool: Tool<TInput, TOutput>,\n): Tool<TInput, TOutput> {\n return tool;\n}\n\nexport function toToolDefinition(tool: Tool): ToolDefinition {\n return {\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters,\n };\n}\n","import { ToolNotFound } from '../errors/index.js';\nimport type { Tool, ToolDefinition } from './index.js';\nimport { toToolDefinition } from './index.js';\n\nexport type ConflictPolicy = 'error' | 'prefer-builtin' | 'prefer-last';\n\nexport class ToolRegistry {\n private readonly tools = new Map<string, Tool>();\n private readonly toolSources = new Map<string, string>(); // toolName -> source\n private readonly conflictPolicy: ConflictPolicy;\n\n constructor(options?: { conflictPolicy?: ConflictPolicy }) {\n this.conflictPolicy = options?.conflictPolicy ?? 'error';\n }\n\n register(tool: Tool, opts?: { source?: string }): void {\n const source = opts?.source ?? tool.metadata?.source ?? 'builtin';\n const existing = this.tools.get(tool.name);\n\n if (existing) {\n if (this.conflictPolicy === 'error') {\n throw new Error(\n `Tool name conflict: '${tool.name}' is already registered by '${this.toolSources.get(tool.name)}'`,\n );\n }\n if (\n this.conflictPolicy === 'prefer-builtin' &&\n this.toolSources.get(tool.name) === 'builtin'\n ) {\n return; // 保留内置\n }\n // prefer-last 直接覆盖\n }\n\n this.tools.set(tool.name, tool);\n this.toolSources.set(tool.name, source);\n }\n\n registerSource(source: string, tools: Tool[]): void {\n for (const tool of tools) {\n this.register(tool, { source });\n }\n }\n\n unregisterSource(source: string): void {\n for (const [name, s] of this.toolSources.entries()) {\n if (s === source) {\n this.tools.delete(name);\n this.toolSources.delete(name);\n }\n }\n }\n\n get(name: string): Tool | undefined {\n return this.tools.get(name);\n }\n\n resolve(name: string): Tool {\n const tool = this.tools.get(name);\n if (!tool) {\n throw new ToolNotFound(name, Array.from(this.tools.keys()));\n }\n return tool;\n }\n\n list(): Tool[] {\n return Array.from(this.tools.values());\n }\n\n definitions(): ToolDefinition[] {\n return this.list().map(toToolDefinition);\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { AbortError, ToolError } from '../../errors/index.js';\nimport { PathSandbox } from '../../security/sandbox.js';\nimport { defineTool } from '../index.js';\n\n// PathSandbox 会缓存 rootDir 的 realpath,按 rootDir 复用实例避免每次调用重建缓存\nconst sandboxCache = new Map<string, PathSandbox>();\n\nfunction getSandbox(rootDir: string): PathSandbox {\n let sandbox = sandboxCache.get(rootDir);\n if (!sandbox) {\n sandbox = new PathSandbox({ rootDir });\n sandboxCache.set(rootDir, sandbox);\n }\n return sandbox;\n}\n\n// 1. read_file\nexport const readFileTool = defineTool({\n name: 'read_file',\n description: 'Read the text contents of a file at the specified path.',\n metadata: {\n source: 'builtin',\n permissions: ['fs:read'],\n },\n parameters: {\n type: 'object',\n properties: {\n path: {\n type: 'string',\n description: 'The path of the file to read (relative to workspace or absolute).',\n },\n startLine: {\n type: 'integer',\n description: 'Optional 1-based start line to read from.',\n },\n endLine: {\n type: 'integer',\n description: 'Optional 1-based end line to read to (inclusive).',\n },\n },\n required: ['path'],\n },\n async execute(input: { path: string; startLine?: number; endLine?: number }, ctx) {\n const sandbox = getSandbox(ctx.rootDir);\n const safePath = sandbox.resolveSafePath(input.path);\n\n if (!fs.existsSync(safePath)) {\n throw new ToolError(`File not found: ${input.path}`);\n }\n\n const stat = fs.statSync(safePath);\n if (stat.isDirectory()) {\n throw new ToolError(`Target path is a directory, not a file: ${input.path}`);\n }\n\n // 大小上限:避免把超大文件整段读进模型上下文撑爆 token\n const maxReadBytes = 512 * 1024;\n const hasLineRange = input.startLine !== undefined || input.endLine !== undefined;\n if (stat.size > maxReadBytes && !hasLineRange) {\n throw new ToolError(\n `File too large to read in one call: ${input.path} (${stat.size} bytes > ${maxReadBytes}). Use startLine/endLine to read in chunks, or narrow the file first.`,\n );\n }\n\n // 二进制嗅探:首 8KB 出现 NUL 字节基本可判定为二进制文件,避免乱码进入上下文\n const prefixSize = Math.min(stat.size, 8192);\n const prefix = Buffer.alloc(prefixSize);\n const fileDescriptor = fs.openSync(safePath, 'r');\n try {\n fs.readSync(fileDescriptor, prefix, 0, prefixSize, 0);\n } finally {\n fs.closeSync(fileDescriptor);\n }\n if (prefix.includes(0)) {\n throw new ToolError(`Cannot read binary file: ${input.path}`);\n }\n\n if (hasLineRange) {\n return readFileLineRange(\n safePath,\n Math.max(1, input.startLine ?? 1),\n input.endLine,\n maxReadBytes,\n );\n }\n\n return fs.readFileSync(safePath, 'utf-8');\n },\n});\n\n/**\n * 流式读取指定的 1-based 闭区间,避免为了少量目标行把整个大文件载入内存。\n * 返回片段仍受 maxReadBytes 限制,防止调用方用超大行区间绕过全文读取上限。\n */\nasync function readFileLineRange(\n filePath: string,\n startLine: number,\n endLine: number | undefined,\n maxReadBytes: number,\n): Promise<string> {\n if (endLine !== undefined && endLine < startLine) return '';\n\n const selectedLines: string[] = [];\n let selectedBytes = 0;\n let currentLine = 1;\n let pending = '';\n let reachedEnd = false;\n const stream = fs.createReadStream(filePath, { encoding: 'utf-8' });\n\n const selectLine = (line: string): void => {\n if (currentLine >= startLine && (endLine === undefined || currentLine <= endLine)) {\n const addedBytes = Buffer.byteLength(line, 'utf-8') + (selectedLines.length > 0 ? 1 : 0);\n if (selectedBytes + addedBytes > maxReadBytes) {\n throw new ToolError(\n `Requested line range exceeds ${maxReadBytes} bytes. Use a narrower startLine/endLine range.`,\n );\n }\n selectedLines.push(line);\n selectedBytes += addedBytes;\n }\n if (Buffer.byteLength(line, 'utf-8') > maxReadBytes) {\n throw new ToolError(`File line exceeds ${maxReadBytes} byte limit`);\n }\n currentLine++;\n reachedEnd = endLine !== undefined && currentLine > endLine;\n };\n\n try {\n for await (const chunk of stream) {\n pending += chunk;\n let newlineIndex = pending.indexOf('\\n');\n while (newlineIndex >= 0) {\n selectLine(pending.slice(0, newlineIndex));\n pending = pending.slice(newlineIndex + 1);\n if (reachedEnd) break;\n newlineIndex = pending.indexOf('\\n');\n }\n if (Buffer.byteLength(pending, 'utf-8') > maxReadBytes) {\n throw new ToolError(`File line exceeds ${maxReadBytes} byte limit`);\n }\n if (reachedEnd) break;\n }\n if (!reachedEnd) selectLine(pending);\n } finally {\n stream.destroy();\n }\n\n return selectedLines.join('\\n');\n}\n\n// 2. write_file\nexport const writeFileTool = defineTool({\n name: 'write_file',\n description: 'Create a new file or overwrite an existing file with new content.',\n metadata: {\n source: 'builtin',\n permissions: ['fs:write'],\n },\n parameters: {\n type: 'object',\n properties: {\n path: {\n type: 'string',\n description: 'The path of the file to write to.',\n },\n content: {\n type: 'string',\n description: 'The full text content to write into the file.',\n },\n },\n required: ['path', 'content'],\n },\n async execute(input: { path: string; content: string }, ctx) {\n const sandbox = getSandbox(ctx.rootDir);\n const safePath = sandbox.resolveSafePath(input.path);\n\n const dir = path.dirname(safePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n fs.writeFileSync(safePath, input.content, 'utf-8');\n return `Successfully wrote ${Buffer.byteLength(input.content, 'utf-8')} bytes to ${input.path}`;\n },\n});\n\n// 3. edit_file\nexport const editFileTool = defineTool({\n name: 'edit_file',\n description: 'Perform an exact string replacement in a file.',\n metadata: {\n source: 'builtin',\n permissions: ['fs:write'],\n },\n parameters: {\n type: 'object',\n properties: {\n path: {\n type: 'string',\n description: 'The path of the file to edit.',\n },\n targetContent: {\n type: 'string',\n description: 'The exact string snippet in the file to be replaced.',\n },\n replacementContent: {\n type: 'string',\n description: 'The new replacement content to put in place of targetContent.',\n },\n },\n required: ['path', 'targetContent', 'replacementContent'],\n },\n async execute(input: { path: string; targetContent: string; replacementContent: string }, ctx) {\n const sandbox = getSandbox(ctx.rootDir);\n const safePath = sandbox.resolveSafePath(input.path);\n\n if (!fs.existsSync(safePath)) {\n throw new ToolError(`File not found: ${input.path}`);\n }\n\n if (!input.targetContent) {\n throw new ToolError('Target content must not be empty');\n }\n\n const content = fs.readFileSync(safePath, 'utf-8');\n if (!content.includes(input.targetContent)) {\n throw new ToolError(\n `Target content not found in ${input.path}. Ensure exact indentation and characters.`,\n );\n }\n\n // 统计出现次数,若出现多次则要求精确\n const occurrences = content.split(input.targetContent).length - 1;\n if (occurrences > 1) {\n throw new ToolError(\n `Target content occurs ${occurrences} times in ${input.path}. Please provide more surrounding context to match uniquely.`,\n );\n }\n\n // 必须用函数形式提供 replacement:字符串形式会把 $& / $` / $' / $$ 当特殊模式展开,\n // 导致写入内容被静默污染(例如替换目标里写 '$$' 会变成 '$')。\n const newContent = content.replace(input.targetContent, () => input.replacementContent);\n fs.writeFileSync(safePath, newContent, 'utf-8');\n return `Successfully replaced target content in ${input.path}`;\n },\n});\n\n// 4. glob\nexport const globTool = defineTool({\n name: 'glob',\n description: 'Search for files matching a pattern within a directory.',\n metadata: {\n source: 'builtin',\n permissions: ['fs:read'],\n },\n parameters: {\n type: 'object',\n properties: {\n pattern: {\n type: 'string',\n description: 'A glob pattern or filename prefix/suffix to match (e.g. \"*.ts\", \"src/**\").',\n },\n subDirectory: {\n type: 'string',\n description: 'Optional sub-directory to restrict search within.',\n },\n },\n required: ['pattern'],\n },\n async execute(input: { pattern: string; subDirectory?: string }, ctx) {\n const sandbox = getSandbox(ctx.rootDir);\n const searchRoot = input.subDirectory\n ? sandbox.resolveSafePath(input.subDirectory)\n : ctx.rootDir;\n\n if (!fs.existsSync(searchRoot)) {\n throw new ToolError(`Directory not found: ${input.subDirectory ?? '.'}`);\n }\n\n const results: string[] = [];\n const maxResults = 100;\n\n function walk(currentDir: string) {\n if (results.length >= maxResults) return;\n const entries = fs.readdirSync(currentDir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.name === 'node_modules' || entry.name === '.git' || entry.name === 'dist') {\n continue;\n }\n const fullPath = path.join(currentDir, entry.name);\n const relPath = path.relative(ctx.rootDir, fullPath).replace(/\\\\/g, '/');\n\n if (entry.isDirectory()) {\n walk(fullPath);\n } else {\n // 简易 glob 模式匹配\n if (simpleMatch(entry.name, input.pattern) || simpleMatch(relPath, input.pattern)) {\n results.push(relPath);\n if (results.length >= maxResults) return;\n }\n }\n }\n }\n\n walk(searchRoot);\n return results.length > 0 ? results.join('\\n') : 'No matching files found.';\n },\n});\n\n// 5. grep\nexport const grepTool = defineTool({\n name: 'grep',\n description: 'Search for case-insensitive literal text in files within workspace.',\n metadata: {\n source: 'builtin',\n permissions: ['fs:read'],\n },\n parameters: {\n type: 'object',\n properties: {\n pattern: {\n type: 'string',\n description:\n 'Literal text to search for. Regular-expression characters have no special meaning.',\n },\n path: {\n type: 'string',\n description: 'File or directory path to search within.',\n },\n },\n required: ['pattern'],\n },\n async execute(input: { pattern: string; path?: string }, ctx) {\n if (ctx.signal?.aborted) throw new AbortError();\n const sandbox = getSandbox(ctx.rootDir);\n const target = input.path ? sandbox.resolveSafePath(input.path) : ctx.rootDir;\n\n if (!fs.existsSync(target)) {\n throw new ToolError(`Path not found: ${input.path ?? '.'}`);\n }\n\n if (!input.pattern.trim()) throw new ToolError('Search pattern must not be empty');\n const needle = input.pattern.toLowerCase();\n const matches: string[] = [];\n const maxMatches = 50;\n let outputBytes = 0;\n\n async function searchFile(filePath: string): Promise<void> {\n if (matches.length >= maxMatches) return;\n const maxLineBytes = 512 * 1024;\n const maxOutputBytes = 512 * 1024;\n const stream = fs.createReadStream(filePath, { encoding: 'utf-8' });\n const relPath = path.relative(ctx.rootDir, filePath).replace(/\\\\/g, '/');\n let lineNumber = 0;\n let pending = '';\n let skippingLongLine = false;\n\n const inspectLine = (line: string): void => {\n lineNumber++;\n if (skippingLongLine || Buffer.byteLength(line, 'utf-8') > maxLineBytes) {\n skippingLongLine = false;\n if (line.toLowerCase().includes(needle)) {\n throw new ToolError(`Search line exceeds ${maxLineBytes} byte limit`);\n }\n return;\n }\n if (!line.toLowerCase().includes(needle)) return;\n const match = `${relPath}:${lineNumber}: ${line.trim()}`;\n const bytes = Buffer.byteLength(match, 'utf-8') + (matches.length > 0 ? 1 : 0);\n if (outputBytes + bytes > maxOutputBytes) {\n throw new ToolError(`Search results exceed ${maxOutputBytes} byte limit`);\n }\n matches.push(match);\n outputBytes += bytes;\n };\n\n try {\n for await (const chunk of stream) {\n if (ctx.signal?.aborted) throw new AbortError();\n pending += chunk;\n let newlineIndex = pending.indexOf('\\n');\n while (newlineIndex >= 0) {\n inspectLine(pending.slice(0, newlineIndex).replace(/\\r$/, ''));\n pending = pending.slice(newlineIndex + 1);\n if (matches.length >= maxMatches) return;\n newlineIndex = pending.indexOf('\\n');\n }\n if (Buffer.byteLength(pending, 'utf-8') > maxLineBytes) {\n if (pending.toLowerCase().includes(needle)) {\n throw new ToolError(`Search line exceeds ${maxLineBytes} byte limit`);\n }\n skippingLongLine = true;\n pending = needle.length > 1 ? pending.slice(1 - needle.length) : '';\n }\n }\n if (pending.length > 0) inspectLine(pending.replace(/\\r$/, ''));\n } catch (error: unknown) {\n if (error instanceof AbortError || error instanceof ToolError) throw error;\n // 无法读取的文件不阻断其它搜索结果。\n } finally {\n stream.destroy();\n }\n }\n async function walk(dirPath: string): Promise<void> {\n if (matches.length >= maxMatches) return;\n const entries = fs.readdirSync(dirPath, { withFileTypes: true });\n for (const entry of entries) {\n if (ctx.signal?.aborted) throw new AbortError();\n if (entry.name === 'node_modules' || entry.name === '.git' || entry.name === 'dist') {\n continue;\n }\n if (entry.isSymbolicLink()) continue;\n const fullPath = path.join(dirPath, entry.name);\n if (entry.isDirectory()) {\n await walk(fullPath);\n } else {\n await searchFile(fullPath);\n }\n if (matches.length >= maxMatches) return;\n }\n }\n\n const stat = fs.statSync(target);\n if (stat.isFile()) {\n await searchFile(target);\n } else {\n await walk(target);\n }\n\n return matches.length > 0 ? matches.join('\\n') : 'No matches found.';\n },\n});\n\nfunction simpleMatch(str: string, pattern: string): boolean {\n if (pattern === '*' || pattern === '**') return true;\n // 单趟替换,同时完成特殊字符转义与通配符展开:\n // 1. 避免 pattern 里的 ( + [ 等字符炸出非法正则或意外语义;\n // 2. 通配符是纯字面匹配,不存在回溯放大,天然规避 ReDoS。\n const escaped = pattern.replace(/[.+?^${}()|[\\]\\\\]|\\*{1,2}/g, (match) =>\n match === '**' ? '.*' : match === '*' ? '[^/]*' : `\\\\${match}`,\n );\n return new RegExp(`^${escaped}$`, 'i').test(str);\n}\n\nexport const builtinTools = [readFileTool, writeFileTool, editFileTool, globTool, grepTool];\n","import type { HookContext, HookHandlers, HookPoint } from './index.js';\n\nexport class HookRegistry {\n private readonly hooks: { [K in HookPoint]?: Array<NonNullable<HookHandlers[K]>> } = {};\n\n on<K extends HookPoint>(point: K, handler: NonNullable<HookHandlers[K]>): void {\n if (!this.hooks[point]) {\n this.hooks[point] = [];\n }\n (this.hooks[point] as any[]).push(handler);\n }\n\n get<K extends HookPoint>(point: K): Array<NonNullable<HookHandlers[K]>> {\n return (this.hooks[point] as any[]) ?? [];\n }\n\n async emit<K extends 'session:start' | 'session:end' | 'model:after' | 'tool:after' | 'error'>(\n point: K,\n ctx: HookContext,\n ...args: any[]\n ): Promise<void> {\n const handlers = this.get(point);\n for (const handler of handlers) {\n await (handler as (...emitArgs: any[]) => void | Promise<void>)(ctx, ...args);\n }\n }\n}\n","import { ToolError } from '../errors/index.js';\nimport type { HookRegistry } from '../hooks/registry.js';\nimport type { ToolContext } from '../tools/index.js';\nimport type { ToolRegistry } from '../tools/registry.js';\nimport type { ToolResultBlock, ToolUseBlock } from '../types/index.js';\n\nexport interface ExecutorOptions {\n tools: ToolRegistry;\n hooks: HookRegistry;\n rootDir: string;\n signal?: AbortSignal;\n logger?: (msg: string) => void;\n /** 单次工具执行超时(毫秒)。异步挂起的工具超时后返回 isError 结果,避免永久卡死会话循环 */\n toolTimeoutMs?: number;\n}\n\nconst DEFAULT_TOOL_TIMEOUT_MS = 120_000;\n\nexport class ToolExecutor {\n private readonly tools: ToolRegistry;\n private readonly hooks: HookRegistry;\n private readonly rootDir: string;\n private readonly signal?: AbortSignal;\n private readonly logger?: (msg: string) => void;\n private readonly toolTimeoutMs: number;\n\n constructor(options: ExecutorOptions) {\n this.tools = options.tools;\n this.hooks = options.hooks;\n this.rootDir = options.rootDir;\n this.signal = options.signal;\n this.logger = options.logger;\n this.toolTimeoutMs = options.toolTimeoutMs ?? DEFAULT_TOOL_TIMEOUT_MS;\n }\n\n async runAll(calls: ToolUseBlock[]): Promise<ToolResultBlock[]> {\n const results: ToolResultBlock[] = [];\n for (const call of calls) {\n if (this.signal?.aborted) {\n results.push({\n type: 'tool_result',\n toolUseId: call.id,\n content: 'Tool execution aborted',\n isError: true,\n });\n continue;\n }\n results.push(await this.executeOne(call));\n }\n return results;\n }\n\n async executeOne(call: ToolUseBlock): Promise<ToolResultBlock> {\n const startedAt = Date.now();\n const hookCtx = { signal: this.signal, logger: this.logger };\n let currentInput = call.input;\n\n // 1. 触发 tool:before hooks\n const beforeHooks = this.hooks.get('tool:before');\n for (const hook of beforeHooks) {\n const decision = await hook(hookCtx, { id: call.id, name: call.name, input: currentInput });\n if (decision.action === 'skip') {\n return {\n type: 'tool_result',\n toolUseId: call.id,\n content: decision.result,\n isError: decision.isError ?? false,\n durationMs: Math.max(0, Date.now() - startedAt),\n };\n }\n if (decision.action === 'modify') {\n currentInput = decision.input;\n }\n }\n\n // 2. 解析与执行工具\n let outputStr: string;\n let isError = false;\n\n try {\n const tool = this.tools.resolve(call.name);\n const executionController = new AbortController();\n const abortFromSession = () => executionController.abort();\n if (this.signal?.aborted) {\n executionController.abort();\n } else {\n this.signal?.addEventListener('abort', abortFromSession, { once: true });\n }\n const toolCtx: ToolContext = {\n rootDir: this.rootDir,\n signal: executionController.signal,\n logger: this.logger,\n };\n\n try {\n const rawResult = await this.withTimeout(\n tool.execute(currentInput, toolCtx),\n call.name,\n executionController,\n );\n outputStr = typeof rawResult === 'string' ? rawResult : JSON.stringify(rawResult, null, 2);\n } finally {\n this.signal?.removeEventListener('abort', abortFromSession);\n }\n } catch (err: unknown) {\n isError = true;\n outputStr = err instanceof Error ? err.message : String(err);\n }\n\n const resultBlock: ToolResultBlock = {\n type: 'tool_result',\n toolUseId: call.id,\n content: outputStr,\n isError,\n };\n\n // 3. 触发 tool:after hooks\n const afterHooks = this.hooks.get('tool:after');\n for (const hook of afterHooks) {\n await hook(\n hookCtx,\n { id: call.id, name: call.name, input: currentInput },\n { output: outputStr, isError },\n );\n }\n\n resultBlock.durationMs = Math.max(0, Date.now() - startedAt);\n\n return resultBlock;\n }\n\n /**\n * 给工具执行加超时护栏:Promise.race 在超时后reject,循环拿到 isError 结果继续运转,\n * 不会因某个异步工具(如未来接入的网络/exec 工具)挂起而永久卡死。\n *\n * 局限:同步 CPU 密集型实现会阻塞事件循环,timer 同样无法触发;\n * 因此内置工具仍需避免执行用户可控的同步高复杂度计算。\n */\n private withTimeout<T>(\n promise: Promise<T>,\n toolName: string,\n executionController: AbortController,\n ): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n const error = new ToolError(`Tool '${toolName}' timed out after ${this.toolTimeoutMs}ms`);\n reject(error);\n executionController.abort(error);\n }, this.toolTimeoutMs);\n });\n return Promise.race([promise, timeout]).finally(() => clearTimeout(timer));\n }\n}\n","import type { ModelProvider } from './index.js';\n\nexport type ModelRole = 'default' | 'planning' | 'execution' | 'summary' | 'fast';\n\nexport type ContextWindowValue = number | `${number}${'K' | 'k' | 'M' | 'm'}`;\n\nexport interface ResolvedContextWindow {\n tokens: number;\n /** true 表示模型未声明窗口,当前值来自 Kapibala 的默认估算。 */\n estimated: boolean;\n}\n\nexport const DEFAULT_CONTEXT_WINDOW_TOKENS = 1_000_000;\n\n/**\n * 将模型上下文窗口统一解析为整数 Token 数。\n *\n * 配置允许直接填写整数,或使用十进制 K/M 简写;未填写时返回默认 1M,并标记为估算值。\n */\nexport function resolveContextWindow(value?: ContextWindowValue): ResolvedContextWindow {\n if (value === undefined) {\n return { tokens: DEFAULT_CONTEXT_WINDOW_TOKENS, estimated: true };\n }\n\n let tokens: number;\n if (typeof value === 'number') {\n tokens = value;\n } else {\n const match = /^([0-9]+(?:\\.[0-9]+)?)([km])$/i.exec(value.trim());\n const unit = match?.[2]?.toLowerCase();\n const fractionDigits = match?.[1]?.split('.')[1]?.length ?? 0;\n const maxFractionDigits = unit === 'm' ? 6 : 3;\n if (!match || fractionDigits > maxFractionDigits) {\n throw new RangeError(\n `Invalid contextWindow '${value}': expected a positive integer or K/M value`,\n );\n }\n const multiplier = unit === 'm' ? 1_000_000 : 1_000;\n tokens = Number(match[1]) * multiplier;\n }\n\n if (!Number.isSafeInteger(tokens) || tokens <= 0) {\n throw new RangeError(\n `Invalid contextWindow '${value}': token count must be a positive integer`,\n );\n }\n\n return { tokens, estimated: false };\n}\n\nexport interface ModelProfile {\n id: string;\n name: string;\n provider: 'openai-compatible';\n baseURL: string;\n apiKeyEnv: string;\n apiKey?: string;\n modelName: string;\n contextWindow?: ContextWindowValue;\n supportsThinking?: boolean;\n}\n\nexport interface ModelRouter {\n resolve(role?: ModelRole): ModelProvider;\n getProfile(role?: ModelRole): ModelProfile;\n}\n\nexport class SimpleModelRouter implements ModelRouter {\n private readonly providers = new Map<ModelRole, ModelProvider>();\n private readonly profiles = new Map<ModelRole, ModelProfile>();\n private defaultRole: ModelRole = 'default';\n\n constructor(defaultProfile: ModelProfile, defaultProvider: ModelProvider) {\n this.setRole('default', defaultProfile, defaultProvider);\n }\n\n setRole(role: ModelRole, profile: ModelProfile, provider: ModelProvider): void {\n this.profiles.set(role, profile);\n this.providers.set(role, provider);\n }\n\n resolve(role: ModelRole = 'default'): ModelProvider {\n return this.providers.get(role) ?? this.providers.get('default')!;\n }\n\n getProfile(role: ModelRole = 'default'): ModelProfile {\n return this.profiles.get(role) ?? this.profiles.get('default')!;\n }\n}\n","/**\n * Lightweight Server-Sent Events (SSE) stream parser for Node.js fetch\n */\n\nexport async function* parseSSEStream(stream: ReadableStream<Uint8Array>): AsyncIterable<string> {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(/\\r?\\n/);\n buffer = lines.pop() ?? ''; // 保持最后一个未完成行\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(':')) {\n continue; // 心跳或注释\n }\n\n if (trimmed.startsWith('data:')) {\n const dataContent = trimmed.slice(5).trim();\n if (dataContent === '[DONE]') {\n return;\n }\n yield dataContent;\n }\n }\n }\n\n if (buffer.trim().startsWith('data:')) {\n const dataContent = buffer.trim().slice(5).trim();\n if (dataContent !== '[DONE]') {\n yield dataContent;\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n","import { ModelError } from '../../errors/index.js';\nimport type {\n CanonicalMessage,\n ContentBlock,\n ModelEvent,\n ModelRequest,\n ToolDefinition,\n ToolResultBlock,\n Usage,\n} from '../../types/index.js';\nimport type { ModelProvider } from '../index.js';\nimport { parseSSEStream } from './sse.js';\n\nexport interface OpenAIProviderOptions {\n baseURL: string;\n apiKey: string;\n modelName: string;\n supportsThinking?: boolean;\n /** 建立 HTTP 连接(收到响应头)的超时毫秒数;仅约束建连阶段,不限制流式读取总时长 */\n connectTimeoutMs?: number;\n}\n\nconst DEFAULT_CONNECT_TIMEOUT_MS = 60_000;\n\ninterface WireToolCall {\n id: string;\n type: 'function';\n function: {\n name: string;\n arguments: string;\n };\n}\n\ninterface WireMessage {\n role: 'system' | 'user' | 'assistant' | 'tool';\n content?: string | null;\n tool_call_id?: string;\n tool_calls?: WireToolCall[];\n}\n\nexport class OpenAICompatibleProvider implements ModelProvider {\n readonly name = 'openai-compatible';\n readonly baseURL: string;\n readonly apiKey: string;\n readonly modelName: string;\n readonly supportsThinking: boolean;\n readonly connectTimeoutMs: number;\n\n constructor(options: OpenAIProviderOptions) {\n this.baseURL = options.baseURL.replace(/\\/+$/, '');\n this.apiKey = options.apiKey;\n this.modelName = options.modelName;\n this.supportsThinking = options.supportsThinking ?? false;\n this.connectTimeoutMs = options.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS;\n }\n\n async *create(req: ModelRequest): AsyncIterable<ModelEvent> {\n const url = `${this.baseURL}/chat/completions`;\n const wireMessages = this.translateMessagesToWire(req.messages, req.systemPrompt);\n\n const wireTools =\n req.tools && req.tools.length > 0\n ? req.tools.map((t) => ({\n type: 'function' as const,\n function: {\n name: t.name,\n description: t.description,\n parameters: t.parameters,\n },\n }))\n : undefined;\n\n const payload: Record<string, unknown> = {\n model: this.modelName,\n messages: wireMessages,\n stream: true,\n stream_options: { include_usage: true },\n temperature: req.temperature ?? 0.7,\n };\n\n if (wireTools) {\n payload.tools = wireTools;\n }\n if (req.maxTokens) {\n payload.max_tokens = req.maxTokens;\n }\n\n let response: Response;\n // 建连超时护栏:服务端无响应时不能永久挂起(流式读取阶段不受此限制)。\n // 手动组合外层 signal 与超时 signal,避免依赖 Node 20.3+ 的 AbortSignal.any。\n const timeoutController = new AbortController();\n const timeoutTimer = setTimeout(() => timeoutController.abort(), this.connectTimeoutMs);\n const onOuterAbort = () => timeoutController.abort();\n if (req.signal?.aborted) {\n timeoutController.abort();\n } else {\n req.signal?.addEventListener('abort', onOuterAbort, { once: true });\n }\n\n try {\n try {\n response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(payload),\n signal: timeoutController.signal,\n });\n } catch (err: unknown) {\n if (req.signal?.aborted) {\n throw err;\n }\n if (timeoutController.signal.aborted) {\n throw new ModelError(`Connection to ${url} timed out after ${this.connectTimeoutMs}ms`, {\n status: 408,\n retryable: true,\n });\n }\n throw new ModelError(`Failed to connect to ${url}: ${(err as Error).message}`);\n } finally {\n // 只停止建连计时;外层 signal 的联动必须保留到响应流消费结束。\n clearTimeout(timeoutTimer);\n }\n\n if (!response.ok) {\n const errorText = await response.text();\n let errorMsg = `API request failed with status ${response.status}: ${response.statusText}`;\n try {\n const errorJson = JSON.parse(errorText);\n if (errorJson.error?.message) {\n errorMsg = errorJson.error.message;\n }\n } catch {\n if (errorText) errorMsg += ` - ${errorText.slice(0, 300)}`;\n }\n throw new ModelError(errorMsg, { status: response.status });\n }\n\n if (!response.body) {\n throw new ModelError('Response body is null');\n }\n\n // 状态机收集分片 tool_calls\n const pendingToolCalls = new Map<\n number,\n { id: string; name: string; argumentChunks: string[] }\n >();\n let usage: Usage | undefined;\n const requestStartTime = Date.now();\n let ttftMs: number | undefined;\n\n for await (const chunk of parseSSEStream(response.body)) {\n if (req.signal?.aborted) return;\n if (!chunk) continue;\n\n let json: any;\n try {\n json = JSON.parse(chunk);\n } catch {\n continue;\n }\n\n if (json.error) {\n const message =\n typeof json.error.message === 'string' ? json.error.message : 'Model API stream error';\n const details = [json.error.type, json.error.code]\n .filter((value) => typeof value === 'string' && value.length > 0)\n .join(', ');\n throw new ModelError(details ? `${message} (${details})` : message);\n }\n\n if (json.usage) {\n usage = {\n promptTokens: json.usage.prompt_tokens ?? 0,\n completionTokens: json.usage.completion_tokens ?? 0,\n totalTokens: json.usage.total_tokens ?? 0,\n };\n }\n\n const choice = json.choices?.[0];\n if (!choice) continue;\n\n const delta = choice.delta;\n if (!delta) continue;\n\n if (\n (delta.content ||\n delta.reasoning_content ||\n (delta.tool_calls && delta.tool_calls.length > 0)) &&\n ttftMs === undefined\n ) {\n ttftMs = Date.now() - requestStartTime;\n }\n\n // 1. 普通文本增量\n if (delta.content) {\n yield { type: 'text_delta', text: delta.content };\n }\n\n // 2. 深度思考增量 (DeepSeek reasoning_content)\n if (delta.reasoning_content) {\n yield { type: 'thinking_delta', thinking: delta.reasoning_content };\n }\n\n // 3. 工具调用增量\n if (delta.tool_calls && Array.isArray(delta.tool_calls)) {\n for (const tc of delta.tool_calls) {\n const index = tc.index ?? 0;\n let entry = pendingToolCalls.get(index);\n if (!entry) {\n entry = {\n id: tc.id ?? `call_${Date.now()}_${index}`,\n name: tc.function?.name ?? '',\n argumentChunks: [],\n };\n pendingToolCalls.set(index, entry);\n yield { type: 'tool_call_start', id: entry.id, name: entry.name };\n }\n\n if (tc.function?.name && !entry.name) {\n entry.name = tc.function.name;\n }\n\n if (tc.function?.arguments) {\n entry.argumentChunks.push(tc.function.arguments);\n yield {\n type: 'tool_call_delta',\n id: entry.id,\n argumentChunk: tc.function.arguments,\n };\n }\n }\n }\n }\n\n // 触发所有已收集完整的 tool_calls\n for (const [, tc] of pendingToolCalls.entries()) {\n const fullArgs = tc.argumentChunks.join('');\n let parsedInput: Record<string, unknown> = {};\n let parseError: boolean | undefined;\n try {\n parsedInput = fullArgs.trim() ? JSON.parse(fullArgs) : {};\n } catch {\n // 解析失败不静默吞掉:input 退化为 _raw 并显式标记,工具端报错时可定位根因\n parsedInput = { _raw: fullArgs };\n parseError = true;\n }\n\n yield {\n type: 'tool_call_finish',\n id: tc.id,\n name: tc.name,\n input: parsedInput,\n parseError,\n };\n }\n\n const durationMs = Date.now() - requestStartTime;\n yield { type: 'message_stop', usage, ttftMs, durationMs };\n } finally {\n req.signal?.removeEventListener('abort', onOuterAbort);\n }\n }\n\n assembleToolResults(results: ToolResultBlock[]): CanonicalMessage[] {\n return results.map((r) => ({\n role: 'tool' as const,\n content: [r],\n timestamp: Date.now(),\n }));\n }\n\n private translateMessagesToWire(\n messages: CanonicalMessage[],\n systemPrompt?: string,\n ): WireMessage[] {\n const wire: WireMessage[] = [];\n\n if (systemPrompt?.trim()) {\n wire.push({ role: 'system', content: systemPrompt.trim() });\n }\n\n for (const msg of messages) {\n if (msg.role === 'system') {\n const text = msg.content\n .filter((b): b is { type: 'text'; text: string } => b.type === 'text')\n .map((b) => b.text)\n .join('\\n');\n if (text) wire.push({ role: 'system', content: text });\n } else if (msg.role === 'user') {\n const text = msg.content\n .filter((b): b is { type: 'text'; text: string } => b.type === 'text')\n .map((b) => b.text)\n .join('\\n');\n const previous = wire[wire.length - 1];\n if (previous?.role === 'user' && typeof previous.content === 'string') {\n previous.content = [previous.content, text].filter(Boolean).join('\\n\\n');\n } else {\n wire.push({ role: 'user', content: text });\n }\n } else if (msg.role === 'assistant') {\n const text = msg.content\n .filter((b): b is { type: 'text'; text: string } => b.type === 'text')\n .map((b) => b.text)\n .join('\\n');\n\n const toolCalls: WireToolCall[] = [];\n for (const block of msg.content) {\n if (block.type === 'tool_use') {\n toolCalls.push({\n id: block.id,\n type: 'function',\n function: {\n name: block.name,\n arguments: JSON.stringify(block.input),\n },\n });\n }\n }\n\n // 失败轮次或中断可能留下空 assistant;不要把它发给要求严格消息序列的端点。\n if (!text && toolCalls.length === 0) continue;\n\n wire.push({\n role: 'assistant',\n content: text || null,\n tool_calls: toolCalls.length > 0 ? toolCalls : undefined,\n });\n } else if (msg.role === 'tool') {\n for (const block of msg.content) {\n if (block.type === 'tool_result') {\n wire.push({\n role: 'tool',\n tool_call_id: block.toolUseId,\n content: block.content,\n });\n }\n }\n }\n }\n\n return wire;\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport {\n type CanonicalMessage,\n type ToolResultBlock,\n type ToolUseBlock,\n isToolResultBlock,\n isToolUseBlock,\n} from '../types/index.js';\nimport type { MessageStore } from './index.js';\n\nexport class JSONLMessageStore implements MessageStore {\n readonly filePath: string;\n\n constructor(filePath: string) {\n this.filePath = path.resolve(filePath);\n const dir = path.dirname(this.filePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n }\n\n async append(message: CanonicalMessage): Promise<void> {\n const record = {\n ts: message.timestamp ?? Date.now(),\n role: message.role,\n content: message.content,\n };\n fs.appendFileSync(this.filePath, `${JSON.stringify(record)}\\n`, 'utf-8');\n }\n\n async load(): Promise<CanonicalMessage[]> {\n if (!fs.existsSync(this.filePath)) {\n return [];\n }\n\n const content = fs.readFileSync(this.filePath, 'utf-8');\n const lines = content.split('\\n');\n const messages: CanonicalMessage[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n const record = JSON.parse(trimmed);\n if (record.role && record.content) {\n messages.push({\n role: record.role,\n content: record.content,\n timestamp: record.ts,\n });\n }\n } catch {\n // 遇到半截脏行忽略,实现容错恢复\n }\n }\n\n // 崩溃自愈:检查历史末尾是否存在悬挂的 tool_use\n this.healDanglingToolCalls(messages);\n\n return messages;\n }\n\n async clear(): Promise<void> {\n if (fs.existsSync(this.filePath)) {\n fs.unlinkSync(this.filePath);\n }\n }\n\n /**\n * 历史自愈(设计文档 §4.4):逐条扫描 assistant 的 tool_use,\n * 若其后的 tool 消息未完整覆盖这些 tool_use,就地补一条 is_error 的 tool_result。\n *\n * 之所以做**全历史扫描**而非只看末条:崩溃可能发生在任意一轮工具执行中途,\n * 悬挂的 tool_use 未必位于历史末尾(例如中断后用户又继续提了问)。\n * 只看末条会漏掉夹在中间的悬挂,下一次请求仍会因上下文非法而 400。\n */\n private healDanglingToolCalls(messages: CanonicalMessage[]): void {\n const healed: CanonicalMessage[] = [];\n let pending = new Map<string, ToolUseBlock>();\n\n const closePending = () => {\n if (pending.size === 0) return;\n healed.push({\n role: 'tool',\n content: Array.from(pending.values()).map(\n (toolUse: ToolUseBlock): ToolResultBlock => ({\n type: 'tool_result',\n toolUseId: toolUse.id,\n content: 'Tool execution was interrupted or crashed in previous session',\n isError: true,\n }),\n ),\n timestamp: Date.now(),\n });\n pending = new Map();\n };\n\n for (const msg of messages) {\n if (msg.role === 'tool') {\n // 结果只允许满足紧邻 assistant 打开的调用集合;迟到、重复和孤儿结果全部剔除。\n const valid = msg.content.filter((block): block is ToolResultBlock => {\n if (!isToolResultBlock(block) || !pending.has(block.toolUseId)) return false;\n pending.delete(block.toolUseId);\n return true;\n });\n if (valid.length === 0) continue;\n healed.push(valid.length === msg.content.length ? msg : { ...msg, content: valid });\n continue;\n }\n\n // 任何非 tool 消息都结束上一组调用;先补齐缺失结果,再接收新消息。\n closePending();\n healed.push(msg);\n if (msg.role !== 'assistant') continue;\n\n const toolUses = msg.content.filter(isToolUseBlock);\n if (toolUses.length === 0) continue;\n pending = new Map(toolUses.map((toolUse) => [toolUse.id, toolUse]));\n }\n\n closePending();\n\n messages.length = 0;\n messages.push(...healed);\n }\n}\n","import os from 'node:os';\nimport type { ToolRegistry } from '../tools/registry.js';\n\nexport interface PromptAssemblerOptions {\n tools?: ToolRegistry;\n rootDir: string;\n agentName?: string;\n customInstructions?: string;\n}\n\nexport class PromptAssembler {\n private readonly tools?: ToolRegistry;\n private readonly rootDir: string;\n private readonly agentName: string;\n private readonly customInstructions?: string;\n\n constructor(options: PromptAssemblerOptions) {\n this.tools = options.tools;\n this.rootDir = options.rootDir;\n this.agentName = options.agentName ?? 'Kapibala';\n this.customInstructions = options.customInstructions;\n }\n\n assemble(): string {\n const sections: string[] = [];\n\n // L1: 行为层\n sections.push(this.getL1Behavior());\n\n // L2: 工具清单层\n if (this.tools) {\n sections.push(this.getL2Tools());\n }\n\n // L3: 环境层\n sections.push(this.getL3Environment());\n\n // 自定义提示词\n if (this.customInstructions?.trim()) {\n sections.push(this.customInstructions.trim());\n }\n\n return sections.filter(Boolean).join('\\n\\n---\\n\\n');\n }\n\n private getL1Behavior(): string {\n return `You are ${this.agentName}, an intelligent and dependable AI software engineering assistant.\nYour goal is to solve tasks efficiently and accurately by reasoning step-by-step and calling available tools when needed.\nFollow these key behavioral rules:\n1. Ground your answers in reality by inspecting files before making assumptions.\n2. When calling tools, ensure parameters conform strictly to the schema.\n3. When the user provides an exact file path, read it directly instead of searching for it first.\n4. Do not broaden a successful exact lookup with wildcard searches or duplicate read-only calls.\n5. Stop calling tools once you have enough evidence to answer the user's request.\n6. If a tool call fails, analyze the error before self-correcting. Do not repeat an identical failed tool call.\n7. Keep answers concise, clear, and focused on user requirements. Do not add unrelated analysis unless requested.`;\n }\n\n private getL2Tools(): string {\n if (!this.tools) return '';\n const tools = this.tools.list();\n if (tools.length === 0) return '';\n\n const lines: string[] = ['# Available Tools:'];\n for (const tool of tools) {\n lines.push(`- **${tool.name}**: ${tool.description}`);\n }\n return lines.join('\\n');\n }\n\n private getL3Environment(): string {\n const now = new Date().toISOString();\n const platform = os.platform();\n return `# Environment Context:\n- Current Working Directory (Workspace Root): ${this.rootDir}\n- Operating System: ${platform}\n- Current Date/Time: ${now}`;\n }\n}\n","import { AbortError } from '../errors/index.js';\nimport type { ToolExecutor } from '../executor/index.js';\nimport type { HookRegistry } from '../hooks/registry.js';\nimport type { ModelProvider } from '../models/index.js';\nimport type { ToolRegistry } from '../tools/registry.js';\nimport type {\n CanonicalMessage,\n ContentBlock,\n ModelRequest,\n SessionEvent,\n ToolUseBlock,\n TurnMetrics,\n Usage,\n} from '../types/index.js';\n\nexport interface AgentLoopOptions {\n provider: ModelProvider;\n executor: ToolExecutor;\n tools: ToolRegistry;\n hooks: HookRegistry;\n systemPrompt?: string;\n maxSteps?: number;\n maxConsecutiveErrors?: number;\n signal?: AbortSignal;\n}\n\nexport class AgentLoop {\n private readonly provider: ModelProvider;\n private readonly executor: ToolExecutor;\n private readonly tools: ToolRegistry;\n private readonly hooks: HookRegistry;\n private readonly systemPrompt?: string;\n private readonly maxSteps: number;\n private readonly maxConsecutiveErrors: number;\n private readonly signal?: AbortSignal;\n\n constructor(options: AgentLoopOptions) {\n this.provider = options.provider;\n this.executor = options.executor;\n this.tools = options.tools;\n this.hooks = options.hooks;\n this.systemPrompt = options.systemPrompt;\n this.maxSteps = options.maxSteps ?? 20;\n this.maxConsecutiveErrors = options.maxConsecutiveErrors ?? 3;\n this.signal = options.signal;\n }\n\n async *run(history: CanonicalMessage[]): AsyncIterable<SessionEvent> {\n let step = 0;\n let consecutiveErrors = 0;\n // 标记循环是否已\"有结论\"地结束(正常回答/熔断/模型错误)。\n // while 条件自然退出 = 每一轮都以工具调用收尾直到步数耗尽,需要显式告知消费方。\n let completed = false;\n\n while (step < this.maxSteps) {\n step++;\n const turnStartTime = Date.now();\n yield { type: 'turn_start', turn: step };\n\n if (this.signal?.aborted) {\n throw new AbortError();\n }\n\n // 1. 构建请求\n let request: ModelRequest = {\n systemPrompt: this.systemPrompt,\n messages: history,\n tools: this.tools.definitions(),\n signal: this.signal,\n };\n\n // 触发 model:before hooks\n const beforeModelHooks = this.hooks.get('model:before');\n const hookCtx = { signal: this.signal };\n for (const hook of beforeModelHooks) {\n request = await hook(hookCtx, request);\n }\n\n yield {\n type: 'step_log',\n log: {\n timestamp: Date.now(),\n turn: step,\n stage: 'model_request_start',\n message: `Sending request to model with ${request.messages.length} messages and ${request.tools?.length ?? 0} tools`,\n },\n };\n\n // 2. 请求模型并流式组装 Assistant 消息\n let accumulatedText = '';\n let accumulatedThinking = '';\n const toolCalls: ToolUseBlock[] = [];\n let turnUsage: Usage | undefined;\n let turnTtftMs: number | undefined;\n const modelStartTime = Date.now();\n let firstTokenReceived = false;\n\n // 统一的 TurnMetrics 构造:保证错误/熔断/正常三条路径的指标结构一致\n const buildMetrics = (\n modelDurationMs: number,\n toolDurationMs: number,\n toolCallsCount: number,\n ): TurnMetrics => {\n const endTime = Date.now();\n return {\n turn: step,\n startTime: turnStartTime,\n endTime,\n totalDurationMs: endTime - turnStartTime,\n ttftMs: turnTtftMs,\n modelDurationMs,\n toolDurationMs,\n promptTokens: turnUsage?.promptTokens ?? 0,\n completionTokens: turnUsage?.completionTokens ?? 0,\n totalTokens: turnUsage?.totalTokens ?? 0,\n toolCallsCount,\n };\n };\n\n try {\n for await (const event of this.provider.create(request)) {\n if (this.signal?.aborted) throw new AbortError();\n\n if (\n !firstTokenReceived &&\n (event.type === 'text_delta' ||\n event.type === 'thinking_delta' ||\n event.type === 'tool_call_start')\n ) {\n firstTokenReceived = true;\n turnTtftMs = Date.now() - modelStartTime;\n yield {\n type: 'step_log',\n log: {\n timestamp: Date.now(),\n turn: step,\n stage: 'first_token',\n message: `First token received (TTFT: ${turnTtftMs}ms)`,\n durationMs: turnTtftMs,\n },\n };\n }\n\n if (event.type === 'text_delta') {\n accumulatedText += event.text;\n yield { type: 'text_delta', text: event.text };\n } else if (event.type === 'thinking_delta') {\n accumulatedThinking += event.thinking;\n yield { type: 'thinking_delta', thinking: event.thinking };\n } else if (event.type === 'tool_call_finish') {\n const toolUse: ToolUseBlock = {\n type: 'tool_use',\n id: event.id,\n name: event.name,\n input: event.input,\n };\n toolCalls.push(toolUse);\n } else if (event.type === 'message_stop') {\n turnUsage = event.usage;\n if (event.ttftMs && turnTtftMs === undefined) {\n turnTtftMs = event.ttftMs;\n }\n }\n }\n } catch (err: unknown) {\n if (err instanceof AbortError || this.signal?.aborted) {\n throw new AbortError();\n }\n const modelError = err instanceof Error ? err : new Error(String(err));\n await this.hooks.emit('error', hookCtx, modelError);\n yield { type: 'error', error: modelError };\n // 与熔断路径保持一致:turn_start 必须有配对的 turn_finish,消费方(如指标统计)才能正确收口\n yield {\n type: 'turn_finish',\n turn: step,\n metrics: buildMetrics(Date.now() - modelStartTime, 0, 0),\n };\n completed = true;\n break;\n }\n\n const modelDurationMs = Date.now() - modelStartTime;\n\n yield {\n type: 'step_log',\n log: {\n timestamp: Date.now(),\n turn: step,\n stage: 'model_stream_finish',\n message: `Model streaming completed in ${modelDurationMs}ms (prompt: ${turnUsage?.promptTokens ?? 0}, completion: ${turnUsage?.completionTokens ?? 0})`,\n durationMs: modelDurationMs,\n metadata: { usage: turnUsage, ttftMs: turnTtftMs },\n },\n };\n\n // 3. 构建完整的 Canonical Assistant Message\n const contentBlocks: ContentBlock[] = [];\n if (accumulatedThinking) {\n contentBlocks.push({ type: 'thinking', thinking: accumulatedThinking });\n }\n if (accumulatedText) {\n contentBlocks.push({ type: 'text', text: accumulatedText });\n }\n for (const tc of toolCalls) {\n contentBlocks.push(tc);\n }\n\n const assistantMessage: CanonicalMessage = {\n role: 'assistant',\n content: contentBlocks,\n timestamp: Date.now(),\n };\n\n // 触发 model:after hooks\n await this.hooks.emit('model:after', hookCtx, { message: assistantMessage });\n\n // 4. 判断是否需要调用工具\n if (toolCalls.length === 0) {\n history.push(assistantMessage);\n yield {\n type: 'message_stop',\n message: assistantMessage,\n usage: turnUsage,\n ttftMs: turnTtftMs,\n durationMs: modelDurationMs,\n };\n\n const metrics = buildMetrics(modelDurationMs, 0, 0);\n\n yield {\n type: 'step_log',\n log: {\n timestamp: metrics.endTime,\n turn: step,\n stage: 'turn_finish',\n message: `Turn ${step} finished in ${metrics.totalDurationMs}ms (TTFT: ${metrics.ttftMs ?? 0}ms, Tokens: ${metrics.totalTokens})`,\n durationMs: metrics.totalDurationMs,\n metadata: { metrics },\n },\n };\n\n yield { type: 'turn_finish', turn: step, usage: turnUsage, metrics };\n completed = true;\n break; // 没有工具调用,正常回答完毕,结束本轮交互\n }\n\n // 5. 调度工具执行\n yield {\n type: 'step_log',\n log: {\n timestamp: Date.now(),\n turn: step,\n stage: 'tool_execution_start',\n message: `Executing ${toolCalls.length} tool(s): ${toolCalls.map((c) => c.name).join(', ')}`,\n },\n };\n\n for (const call of toolCalls) {\n yield { type: 'tool_start', id: call.id, name: call.name, input: call.input };\n }\n\n const toolStartTime = Date.now();\n const toolResults = await this.executor.runAll(toolCalls);\n const toolDurationMs = Date.now() - toolStartTime;\n\n const hasError = toolResults.some((result) => result.isError);\n const metrics = buildMetrics(modelDurationMs, toolDurationMs, toolCalls.length);\n\n // 6. 工具结果回填历史 + 派发落盘事件\n // assistant 与所有 tool_result 在同一个同步临界段进入历史,并且发生在下一次 yield 前。\n // 因此直接消费 AgentLoop 的调用方即使在任意对外事件后停止,也看不到半闭合历史。\n // 熔断只决定「是否继续循环」,不改变历史的合法性(设计文档 §4.3 / §4.4)。\n const toolMessages = this.provider.assembleToolResults(toolResults);\n history.push(assistantMessage, ...toolMessages);\n\n yield {\n type: 'message_stop',\n message: assistantMessage,\n usage: turnUsage,\n ttftMs: turnTtftMs,\n durationMs: modelDurationMs,\n };\n\n for (const res of toolResults) {\n const matchingCall = toolCalls.find((c) => c.id === res.toolUseId);\n yield {\n type: 'tool_finish',\n id: res.toolUseId,\n name: matchingCall?.name ?? 'unknown',\n result: res.content,\n isError: res.isError ?? false,\n durationMs: res.durationMs,\n };\n }\n\n yield {\n type: 'step_log',\n log: {\n timestamp: Date.now(),\n turn: step,\n stage: 'tool_execution_finish',\n message: `Tools execution finished in ${toolDurationMs}ms (${hasError ? 'with errors' : 'success'})`,\n durationMs: toolDurationMs,\n },\n };\n\n yield { type: 'tool_messages', messages: toolMessages };\n\n if (hasError) {\n consecutiveErrors++;\n if (consecutiveErrors >= this.maxConsecutiveErrors) {\n const breakerError = new Error(\n `Circuit breaker triggered: ${consecutiveErrors} consecutive tool failures`,\n );\n await this.hooks.emit('error', hookCtx, breakerError);\n yield { type: 'error', error: breakerError };\n yield { type: 'turn_finish', turn: step, usage: turnUsage, metrics };\n completed = true;\n break;\n }\n } else {\n consecutiveErrors = 0;\n }\n\n yield {\n type: 'step_log',\n log: {\n timestamp: metrics.endTime,\n turn: step,\n stage: 'turn_finish',\n message: `Turn ${step} completed in ${metrics.totalDurationMs}ms (tool duration: ${toolDurationMs}ms). Continuing loop.`,\n durationMs: metrics.totalDurationMs,\n metadata: { metrics },\n },\n };\n\n yield { type: 'turn_finish', turn: step, usage: turnUsage, metrics };\n }\n\n // 步数耗尽:显式告知消费方\"未产出最终回答\",否则用户只会看到 tool_finish 就回到提示符。\n if (!completed) {\n yield {\n type: 'error',\n error: new Error(\n `Reached max steps limit (${this.maxSteps}); loop terminated before a final answer was produced`,\n ),\n };\n }\n }\n}\n","import { AbortError, SessionBusyError } from '../errors/index.js';\nimport { ToolExecutor } from '../executor/index.js';\nimport { HookRegistry } from '../hooks/registry.js';\nimport { AgentLoop } from '../loop/index.js';\nimport type { ModelProfile, ModelProvider, ModelRole } from '../models/index.js';\nimport { SimpleModelRouter, resolveContextWindow } from '../models/router.js';\nimport type { AgentPlugin } from '../plugin/index.js';\nimport { PromptAssembler } from '../prompt/index.js';\nimport type { MessageStore } from '../store/index.js';\nimport { ToolRegistry } from '../tools/registry.js';\nimport type {\n CanonicalMessage,\n ContextUsage,\n RunMetrics,\n SessionEvent,\n TurnMetrics,\n Usage,\n} from '../types/index.js';\n\nexport interface SessionConfig {\n defaultProfile: ModelProfile;\n defaultProvider: ModelProvider;\n store?: MessageStore;\n rootDir?: string;\n systemPrompt?: string;\n maxSteps?: number;\n logger?: (msg: string) => void;\n}\n\nexport interface SessionStats {\n totalTurns: number;\n totalTokens: Usage;\n activeModel: string;\n loadedToolsCount: number;\n lastMetrics?: TurnMetrics;\n lastRunMetrics?: RunMetrics;\n contextUsage: ContextUsage;\n}\n\nexport class AgentSession {\n readonly rootDir: string;\n readonly tools: ToolRegistry;\n readonly hooks: HookRegistry;\n private readonly router: SimpleModelRouter;\n private readonly store?: MessageStore;\n private readonly customSystemPrompt?: string;\n private readonly maxSteps: number;\n private readonly logger?: (msg: string) => void;\n\n private history: CanonicalMessage[] = [];\n private totalTurns = 0;\n private usageStats: Usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };\n private lastMetrics?: TurnMetrics;\n private lastRunMetrics?: RunMetrics;\n private initialized = false;\n private destroyed = false;\n private activeRun = false;\n private readonly plugins: AgentPlugin[] = [];\n\n constructor(config: SessionConfig) {\n resolveContextWindow(config.defaultProfile.contextWindow);\n this.rootDir = config.rootDir ?? process.cwd();\n this.tools = new ToolRegistry();\n this.hooks = new HookRegistry();\n this.router = new SimpleModelRouter(config.defaultProfile, config.defaultProvider);\n this.store = config.store;\n this.customSystemPrompt = config.systemPrompt;\n this.maxSteps = config.maxSteps ?? 20;\n this.logger = config.logger;\n }\n\n async init(): Promise<void> {\n if (this.initialized) return;\n if (this.store) {\n this.history = await this.store.load();\n }\n await this.hooks.emit('session:start', { logger: this.logger });\n this.initialized = true;\n }\n\n async use(plugin: AgentPlugin): Promise<void> {\n if (this.destroyed) {\n throw new Error(`Cannot mount plugin '${plugin.name}': session already destroyed`);\n }\n this.assertIdle(`mount plugin '${plugin.name}'`);\n await plugin.setup({\n tools: this.tools,\n hooks: this.hooks,\n rootDir: this.rootDir,\n logger: this.logger,\n });\n this.plugins.push(plugin);\n }\n\n switchModel(profile: ModelProfile, role: ModelRole = 'default', provider?: ModelProvider): void {\n this.assertIdle('switch models');\n resolveContextWindow(profile.contextWindow);\n if (!provider) {\n // 默认使用当前角色的 provider\n provider = this.router.resolve(role);\n }\n this.router.setRole(role, profile, provider);\n this.logger?.(`Switched model for role [${role}] to ${profile.name} (${profile.modelName})`);\n }\n\n getActiveProfile(role: ModelRole = 'default'): ModelProfile {\n return this.router.getProfile(role);\n }\n\n getHistory(): CanonicalMessage[] {\n return [...this.history];\n }\n\n getStats(): SessionStats {\n return {\n totalTurns: this.totalTurns,\n totalTokens: { ...this.usageStats },\n activeModel: this.router.getProfile('default').name,\n loadedToolsCount: this.tools.list().length,\n lastMetrics: this.lastMetrics,\n lastRunMetrics: this.lastRunMetrics,\n contextUsage: this.lastRunMetrics?.contextUsage ?? this.createContextUsage(),\n };\n }\n\n getLastMetrics(): TurnMetrics | undefined {\n return this.lastMetrics;\n }\n\n getLastRunMetrics(): RunMetrics | undefined {\n return this.lastRunMetrics;\n }\n\n async reset(): Promise<void> {\n this.assertIdle('reset session');\n this.history = [];\n this.totalTurns = 0;\n this.usageStats = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };\n this.lastMetrics = undefined;\n this.lastRunMetrics = undefined;\n if (this.store) {\n await this.store.clear();\n }\n this.logger?.('Session context cleared');\n }\n\n /**\n * 执行一次用户输入,并以宿主无关的语义事件流返回全过程。\n *\n * Core 不负责终端或图形界面渲染;CLI、TUI、GUI 与其它宿主应消费同一组\n * {@link SessionEvent},分别完成展示、交互和中止控制。\n *\n * @param userInput 用户本轮输入。\n * @param options 可选的中止信号。\n * @returns 文本、思考、工具、指标和错误等结构化事件的异步流。\n * @throws {SessionBusyError} 当前会话已有正在执行的 run 时抛出。\n */\n async *run(userInput: string, options?: { signal?: AbortSignal }): AsyncIterable<SessionEvent> {\n this.assertIdle('start another run');\n resolveContextWindow(this.router.getProfile('default').contextWindow);\n this.activeRun = true;\n const runStartTime = Date.now();\n const aggregate = {\n modelDurationMs: 0,\n toolDurationMs: 0,\n promptTokens: 0,\n completionTokens: 0,\n totalTokens: 0,\n turns: 0,\n toolCalls: 0,\n ttftMs: undefined as number | undefined,\n };\n let lastPromptTokens: number | undefined;\n let runStatus: RunMetrics['status'] = 'completed';\n let runFinalized = false;\n\n const finalizeRun = (status: RunMetrics['status']): RunMetrics => {\n const endTime = Date.now();\n return {\n startTime: runStartTime,\n endTime,\n totalDurationMs: endTime - runStartTime,\n ...aggregate,\n status,\n contextUsage: this.createContextUsage(lastPromptTokens),\n };\n };\n\n try {\n if (!this.initialized) {\n await this.init();\n }\n\n this.totalTurns++;\n\n // 1. 组装并记录 User 消息\n const userMessage: CanonicalMessage = {\n role: 'user',\n content: [{ type: 'text', text: userInput }],\n timestamp: Date.now(),\n };\n\n this.history.push(userMessage);\n if (this.store) {\n await this.store.append(userMessage);\n }\n\n // 2. 组装分层 System Prompt\n const promptAssembler = new PromptAssembler({\n tools: this.tools,\n rootDir: this.rootDir,\n customInstructions: this.customSystemPrompt,\n });\n const assembledSystemPrompt = promptAssembler.assemble();\n\n // 3. 构建执行器与 Loop\n const executor = new ToolExecutor({\n tools: this.tools,\n hooks: this.hooks,\n rootDir: this.rootDir,\n signal: options?.signal,\n logger: this.logger,\n });\n\n const loop = new AgentLoop({\n provider: this.router.resolve('default'),\n executor,\n tools: this.tools,\n hooks: this.hooks,\n systemPrompt: assembledSystemPrompt,\n maxSteps: this.maxSteps,\n signal: options?.signal,\n });\n\n // 4. 执行循环并落盘。含 tool_use 的完成事件先缓冲,直到 tool_result 已进入历史并落盘,\n // 外部消费者因此无法在历史半闭合时终止迭代。\n let pendingAssistant: Extract<SessionEvent, { type: 'message_stop' }> | undefined;\n let pendingEvents: SessionEvent[] = [];\n let pendingClosedInMemory = false;\n let pendingAssistantPersisted = false;\n let pendingPersistenceStarted = false;\n let pendingToolMessages: CanonicalMessage[] = [];\n\n try {\n for await (const event of loop.run(this.history)) {\n if (event.type === 'step_log') {\n this.logger?.(`[Turn ${event.log.turn} | ${event.log.stage}] ${event.log.message}`);\n }\n if (event.type === 'turn_finish') {\n this.lastMetrics = event.metrics;\n aggregate.modelDurationMs += event.metrics.modelDurationMs;\n aggregate.toolDurationMs += event.metrics.toolDurationMs;\n aggregate.promptTokens += event.metrics.promptTokens;\n aggregate.completionTokens += event.metrics.completionTokens;\n aggregate.totalTokens += event.metrics.totalTokens;\n lastPromptTokens = event.usage?.promptTokens;\n aggregate.turns++;\n aggregate.toolCalls += event.metrics.toolCallsCount;\n aggregate.ttftMs ??= event.metrics.ttftMs;\n }\n if (event.type === 'error') {\n runStatus = 'failed';\n }\n\n if (\n event.type === 'message_stop' &&\n event.message.content.some((block) => block.type === 'tool_use')\n ) {\n pendingAssistant = event;\n pendingEvents = [event];\n pendingToolMessages = this.findClosedToolMessages(event);\n pendingClosedInMemory = pendingToolMessages.length > 0;\n pendingAssistantPersisted = false;\n pendingPersistenceStarted = false;\n continue;\n }\n\n if (pendingAssistant) {\n pendingEvents.push(event);\n if (event.type !== 'tool_messages') continue;\n\n pendingClosedInMemory = true;\n pendingToolMessages = event.messages;\n pendingPersistenceStarted = true;\n await this.persistAssistant(pendingAssistant);\n pendingAssistantPersisted = true;\n await this.persistToolMessages(event.messages);\n\n const releasable = pendingEvents;\n pendingAssistant = undefined;\n pendingEvents = [];\n for (const buffered of releasable) yield buffered;\n continue;\n }\n\n if (event.type === 'message_stop') {\n await this.persistAssistant(event);\n } else if (event.type === 'tool_messages') {\n await this.persistToolMessages(event.messages);\n }\n yield event;\n }\n } catch (error: unknown) {\n if (pendingAssistant && !pendingPersistenceStarted) {\n const interruptedMessages = pendingClosedInMemory\n ? pendingToolMessages\n : this.closeInterruptedToolCalls(pendingAssistant, error);\n if (!pendingAssistantPersisted) {\n await this.persistAssistant(pendingAssistant);\n }\n await this.persistToolMessages(interruptedMessages);\n\n for (const buffered of pendingEvents) yield buffered;\n yield { type: 'tool_messages', messages: interruptedMessages };\n }\n throw error;\n }\n const metrics = finalizeRun(runStatus);\n this.lastRunMetrics = metrics;\n runFinalized = true;\n yield { type: 'run_finish', metrics };\n } catch (error: unknown) {\n const status: RunMetrics['status'] =\n error instanceof AbortError || options?.signal?.aborted ? 'aborted' : 'failed';\n const metrics = finalizeRun(status);\n this.lastRunMetrics = metrics;\n runFinalized = true;\n yield { type: 'run_finish', metrics };\n throw error;\n } finally {\n this.activeRun = false;\n if (!runFinalized) {\n this.lastRunMetrics = finalizeRun('aborted');\n }\n }\n }\n\n async destroy(): Promise<void> {\n if (this.destroyed) return;\n this.assertIdle('destroy session');\n this.destroyed = true;\n\n // 先逐个回收插件资源(MCP 连接、子进程、文件句柄),再派发 session:end\n for (const plugin of this.plugins) {\n try {\n await plugin.teardown?.();\n } catch (err: unknown) {\n this.logger?.(`Plugin '${plugin.name}' teardown failed: ${(err as Error).message}`);\n }\n }\n this.plugins.length = 0;\n\n await this.hooks.emit('session:end', { logger: this.logger });\n }\n\n private assertIdle(operation: string): void {\n if (this.activeRun) throw new SessionBusyError(operation);\n }\n\n /**\n * 计算最近一次内部模型请求的上下文占用。\n * run 累计 promptTokens 会重复计算每一步都重发的历史,不能用于窗口占用率。\n */\n private createContextUsage(usedTokens?: number): ContextUsage {\n const contextWindow = resolveContextWindow(this.router.getProfile('default').contextWindow);\n return {\n usedTokens,\n limitTokens: contextWindow.tokens,\n percent: usedTokens === undefined ? undefined : (usedTokens / contextWindow.tokens) * 100,\n estimatedLimit: contextWindow.estimated,\n };\n }\n\n private async persistAssistant(\n event: Extract<SessionEvent, { type: 'message_stop' }>,\n ): Promise<void> {\n if (this.store) await this.store.append(event.message);\n if (event.usage) {\n this.usageStats.promptTokens += event.usage.promptTokens;\n this.usageStats.completionTokens += event.usage.completionTokens;\n this.usageStats.totalTokens += event.usage.totalTokens;\n }\n }\n\n private async persistToolMessages(messages: CanonicalMessage[]): Promise<void> {\n if (!this.store) return;\n for (const message of messages) await this.store.append(message);\n }\n\n private closeInterruptedToolCalls(\n assistantEvent: Extract<SessionEvent, { type: 'message_stop' }>,\n error: unknown,\n ): CanonicalMessage[] {\n const message: CanonicalMessage = {\n role: 'tool',\n content: assistantEvent.message.content\n .filter((block) => block.type === 'tool_use')\n .map((toolUse) => ({\n type: 'tool_result' as const,\n toolUseId: toolUse.id,\n content: `Tool execution interrupted before completion: ${error instanceof Error ? error.message : String(error)}`,\n isError: true,\n })),\n timestamp: Date.now(),\n };\n this.history.push(message);\n return [message];\n }\n\n private findClosedToolMessages(\n assistantEvent: Extract<SessionEvent, { type: 'message_stop' }>,\n ): CanonicalMessage[] {\n const assistantIndex = this.history.lastIndexOf(assistantEvent.message);\n if (assistantIndex < 0) return [];\n\n const expected = new Set(\n assistantEvent.message.content\n .filter((block) => block.type === 'tool_use')\n .map((toolUse) => toolUse.id),\n );\n const messages: CanonicalMessage[] = [];\n for (let index = assistantIndex + 1; index < this.history.length; index++) {\n const message = this.history[index]!;\n if (message.role !== 'tool') break;\n messages.push(message);\n for (const block of message.content) {\n if (block.type === 'tool_result') expected.delete(block.toolUseId);\n }\n }\n return expected.size === 0 ? messages : [];\n }\n}\n"],"mappings":"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","names":["fs","path","fs","path","fs","path","path","fs","modelDurationMs","toolDurationMs","metrics"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kiturone/kapibala",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Headless core engine and abstractions for the Kapibala agent harness",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "tedburner",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/tedburner/kapibala.git",
|
|
10
|
+
"directory": "packages/core"
|
|
11
|
+
},
|
|
12
|
+
"type": "module",
|
|
13
|
+
"main": "./dist/index.cjs",
|
|
14
|
+
"module": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"import": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"default": "./dist/index.js"
|
|
21
|
+
},
|
|
22
|
+
"require": {
|
|
23
|
+
"types": "./dist/index.d.cts",
|
|
24
|
+
"default": "./dist/index.cjs"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist"
|
|
30
|
+
],
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"tsup": "^8.3.6",
|
|
33
|
+
"typescript": "^5.7.3"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsup",
|
|
37
|
+
"dev": "tsup --watch"
|
|
38
|
+
}
|
|
39
|
+
}
|