@24klynx/tools 0.1.0 → 0.1.4

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["e","descriptor","handler","descriptor","handler","descriptor","handler","countOccurrences","descriptor","handler","descriptor","handler","descriptor","cache","CACHE_TTL_MS","handler","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","SECRET_PATTERNS","handler","descriptor","handler","descriptor","handler","handleStatus","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","handler","STORAGE_DIR","STORAGE_FILE","init","persist","descriptor","handler","handleList","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","descriptor","descriptor","readFileDesc","readFileHandler","writeFileDesc","writeFileHandler","editFileDesc","editFileHandler","globDesc","globHandler","grepDesc","grepHandler","webFetchDesc","webFetchHandler","webSearchDesc","webSearchHandler","todoWriteDesc","todoWriteHandler","powershellDesc","powershellHandler","notebookEditDesc","notebookEditHandler","secretScanDesc","secretScanHandler","lspDesc","lspHandler","replDesc","replHandler","agentDesc","agentHandler","taskDesc","taskHandler","teamCreateDesc","teamCreateHandler","teamDeleteDesc","teamDeleteHandler","verifyPlanDesc","verifyPlanHandler","remoteTriggerDesc","remoteTriggerHandler","scheduleCronDesc","scheduleCronHandler","workflowDesc","workflowHandler","tungstenDesc","tungstenHandler","enterPlanModeDesc","enterPlanModeHandler","exitPlanModeDesc","exitPlanModeHandler","enterWorktreeDesc","enterWorktreeHandler","exitWorktreeDesc","exitWorktreeHandler","configToolDesc","configToolHandler","askUserDesc","askUserHandler","briefDesc","briefHandler","syntheticOutputDesc","syntheticOutputHandler","sleepDesc","sleepHandler","_compiled","compiledRules"],"sources":["../src/availability.ts","../src/registry.ts","../src/builtin/files/read-file.ts","../src/builtin/files/write-file.ts","../src/builtin/files/edit-file.ts","../src/builtin/files/glob.ts","../src/builtin/files/grep.ts","../src/builtin/files/web-fetch.ts","../src/builtin/files/web-search.ts","../src/builtin/files/todo-write.ts","../src/builtin/files/powershell.ts","../src/builtin/files/notebook-edit.ts","../src/builtin/files/secret-scan.ts","../src/builtin/files/lsp.ts","../src/builtin/files/repl.ts","../src/builtin/agent/agent.ts","../src/builtin/agent/task.ts","../src/builtin/agent/team-create.ts","../src/builtin/agent/team-delete.ts","../src/builtin/agent/verify-plan.ts","../src/builtin/agent/remote-trigger.ts","../src/builtin/agent/schedule-cron.ts","../src/builtin/agent/workflow.ts","../src/builtin/agent/tungsten.ts","../src/builtin/mode/enter-plan-mode.ts","../src/builtin/mode/exit-plan-mode.ts","../src/builtin/mode/enter-worktree.ts","../src/builtin/mode/exit-worktree.ts","../src/builtin/mode/config-tool.ts","../src/builtin/interact/ask-user-question.ts","../src/builtin/interact/brief.ts","../src/builtin/interact/synthetic-output.ts","../src/builtin/interact/sleep.ts","../src/builtin/memory/memory-write.ts","../src/builtin/mcp/mcp-auth.ts","../src/builtin/interact/send-message.ts","../src/builtin/index.ts","../src/planner.ts","../src/safety/sensitive.ts","../src/safety.ts","../src/safety/sanitize.ts","../src/safety/path-check.ts","../src/safety/trusted-cmd.ts","../src/safety/blocked-cmd.ts","../src/safety/redact.ts"],"sourcesContent":["/**\n * Availability expression evaluator.\n *\n * Each {@link AvailabilityExpr} is a pure expression tree.\n * The evaluator walks the tree against an {@link EvalContext} that\n * provides the runtime environment state.\n */\n\nimport type { AvailabilityExpr } from \"./types.js\";\n\n// ── Evaluation context ─────────────────────────────\n\n/**\n * Snapshot of the runtime environment passed to the availability evaluator.\n * Updated each turn before `buildToolPlan()` runs.\n */\nexport interface EvalContext {\n /** Current platform (\"windows\" | \"linux\"). */\n platform: \"windows\" | \"linux\";\n /** Current permission mode (from the session). */\n sessionMode: string;\n /** Enabled feature flags. */\n flags: Set<string>;\n /** Settings/configuration values keyed by dot‑path. */\n settings: Record<string, unknown>;\n /** Environment variable overrides. */\n env: Record<string, string>;\n /** Connected MCP server names. */\n connectedMcpServers: Set<string>;\n /** Loaded plugin ids. */\n loadedPlugins: Set<string>;\n}\n\n// ── Leaf evaluators ──────────────────────────────\n\ntype EvalResult = { available: boolean; reason?: string };\ntype EvalFn = (expr: AvailabilityExpr, ctx: EvalContext) => EvalResult;\n\nfunction evalAlways(): EvalResult {\n return { available: true };\n}\n\nfunction evalNever(expr: AvailabilityExpr): EvalResult {\n return { available: false, reason: (expr as { reason: string }).reason };\n}\n\nfunction evalEnv(expr: AvailabilityExpr, ctx: EvalContext): EvalResult {\n const e = expr as { key: string; equals: string };\n return { available: ctx.env[e.key] === e.equals };\n}\n\nfunction evalSetting(expr: AvailabilityExpr, ctx: EvalContext): EvalResult {\n const e = expr as { path: string; equals: unknown };\n return { available: getSetting(ctx.settings, e.path) === e.equals };\n}\n\nfunction evalFlag(expr: AvailabilityExpr, ctx: EvalContext): EvalResult {\n return { available: ctx.flags.has((expr as { flag: string }).flag) };\n}\n\nfunction evalPlatform(expr: AvailabilityExpr, ctx: EvalContext): EvalResult {\n return { available: ctx.platform === (expr as { platform: string }).platform };\n}\n\nfunction evalMcpConnected(expr: AvailabilityExpr, ctx: EvalContext): EvalResult {\n return { available: ctx.connectedMcpServers.has((expr as { serverName: string }).serverName) };\n}\n\nfunction evalHasPlugin(expr: AvailabilityExpr, ctx: EvalContext): EvalResult {\n return { available: ctx.loadedPlugins.has((expr as { pluginId: string }).pluginId) };\n}\n\nfunction evalSessionMode(expr: AvailabilityExpr, ctx: EvalContext): EvalResult {\n return { available: ctx.sessionMode === (expr as { mode: string }).mode };\n}\n\nfunction evalAll(expr: AvailabilityExpr, ctx: EvalContext): EvalResult {\n const e = expr as { exprs: AvailabilityExpr[] };\n for (const sub of e.exprs) {\n const result = evaluateAvailability(sub, ctx);\n if (!result.available) return result;\n }\n return { available: true };\n}\n\nfunction evalAny(expr: AvailabilityExpr, ctx: EvalContext): EvalResult {\n const e = expr as { exprs: AvailabilityExpr[] };\n const reasons: string[] = [];\n for (const sub of e.exprs) {\n const result = evaluateAvailability(sub, ctx);\n if (result.available) return { available: true };\n if (result.reason) reasons.push(result.reason);\n }\n return {\n available: false,\n reason: reasons.length > 0 ? reasons.join(\"; \") : \"no condition matched\",\n };\n}\n\nfunction evalNot(expr: AvailabilityExpr, ctx: EvalContext): EvalResult {\n const e = expr as { expr: AvailabilityExpr };\n const inner = evaluateAvailability(e.expr, ctx);\n return {\n available: !inner.available,\n reason: inner.available ? undefined : inner.reason,\n };\n}\n\nconst LEAF_EVALUATORS: Record<string, EvalFn> = {\n always: evalAlways,\n never: evalNever,\n env: evalEnv,\n setting: evalSetting,\n flag: evalFlag,\n platform: evalPlatform,\n mcp_connected: evalMcpConnected,\n has_plugin: evalHasPlugin,\n session_mode: evalSessionMode,\n all: evalAll,\n any: evalAny,\n not: evalNot,\n};\n\n// ── Public API ─────────────────────────────────────\n\n/**\n * Evaluate an availability expression against the current context.\n *\n * Returns `{ available: true }` or `{ available: false, reason: string }`.\n *\n * ```ts\n * const result = evaluateAvailability(expr, ctx);\n * if (!result.available) {\n * console.log(`Tool hidden because: ${result.reason}`);\n * }\n * ```\n */\nexport function evaluateAvailability(\n expr: AvailabilityExpr,\n ctx: EvalContext,\n): { available: boolean; reason?: string } {\n const evaluator = LEAF_EVALUATORS[expr.type];\n if (evaluator) {\n return evaluator(expr, ctx);\n }\n return {\n available: false,\n reason: `unknown expression type: ${expr.type}`,\n };\n}\n\n// ── Helpers ────────────────────────────────────────\n\n/** Navigate a dot‑path into a settings object. */\nfunction getSetting(settings: Record<string, unknown>, path: string): unknown {\n const parts = path.split(\".\");\n let current: unknown = settings;\n for (const part of parts) {\n if (current === null || current === undefined) return undefined;\n if (typeof current !== \"object\") return undefined;\n current = (current as Record<string, unknown>)[part];\n }\n return current;\n}\n","/**\n * ToolRegistry — central registration and lookup for all tools.\n *\n * Tools are registered by plugins during startup and the registry stays\n * immutable for the session lifetime. Lookups are O(1) by name and O(1)\n * by executor key.\n */\n\nimport { ToolError } from \"@lynx/core\";\nimport type { ToolDescriptor, ToolHandler, ToolExecutorRef } from \"./types.js\";\n\n// ── Public API ─────────────────────────────────────\n\n/**\n * In‑memory registry of all registered tools and their handlers.\n *\n * Create one instance per process in the bootstrap phase.\n */\nexport interface ToolRegistry {\n /** Register a tool descriptor and its handler. */\n register(descriptor: ToolDescriptor, handler: ToolHandler): void;\n\n /** Look up a descriptor by name. Returns undefined if not found. */\n resolve(name: string): ToolDescriptor | undefined;\n\n /** Look up a handler by executor key. Throws if not registered. */\n resolveExecutor(descriptor: ToolDescriptor): ToolHandler;\n\n /** Return every registered descriptor. */\n listAll(): ToolDescriptor[];\n\n /** Return the total number of registered tools. */\n count(): number;\n}\n\n/**\n * Create a new empty ToolRegistry.\n */\nexport function createToolRegistry(): ToolRegistry {\n const descriptors = new Map<string, ToolDescriptor>();\n // A single handler may serve multiple descriptors (e.g. bash → bash handler)\n const handlers = new Map<ToolExecutorRef, ToolHandler>();\n\n const registry: ToolRegistry = {\n register(descriptor: ToolDescriptor, handler: ToolHandler): void {\n if (descriptors.has(descriptor.name)) {\n throw new ToolError(`Tool \"${descriptor.name}\" is already registered`, {\n recoverable: false,\n retryable: false,\n userVisible: false,\n diagnosticHint: \"tool_duplicate_name\",\n });\n }\n\n descriptors.set(descriptor.name, descriptor);\n\n if (!handlers.has(descriptor.executor)) {\n handlers.set(descriptor.executor, handler);\n }\n },\n\n resolve(name: string): ToolDescriptor | undefined {\n return descriptors.get(name);\n },\n\n resolveExecutor(descriptor: ToolDescriptor): ToolHandler {\n const handler = handlers.get(descriptor.executor);\n if (!handler) {\n throw new ToolError(\n `No handler registered for executor \"${descriptor.executor}\" (tool: \"${descriptor.name}\")`,\n {\n recoverable: false,\n retryable: false,\n userVisible: false,\n diagnosticHint: \"tool_missing_handler\",\n },\n );\n }\n return handler;\n },\n\n listAll(): ToolDescriptor[] {\n return [...descriptors.values()];\n },\n\n count(): number {\n return descriptors.size;\n },\n };\n\n return registry;\n}\n","/**\n * read_file — Read file contents from the filesystem.\n *\n * Limits: 2000 lines per call, binary files return MIME + base64.\n */\nimport { readFile, stat } from \"node:fs/promises\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"read_file\",\n description:\n \"读取文件内容。支持 offset/limit 分页。二进制和图片文件以 base64 编码数据加 MIME 类型返回。\",\n inputSchema: {\n type: \"object\",\n properties: {\n file_path: { type: \"string\", description: \"要读取的文件绝对路径\" },\n offset: { type: \"integer\", description: \"起始行号(从 1 开始)\" },\n limit: { type: \"integer\", description: \"最多读取行数\" },\n },\n required: [\"file_path\"],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:read_file\",\n owner: \"core\",\n};\n\nconst MAX_LINES = 2000;\nconst TEXT_EXTENSIONS = new Set([\n \".ts\",\n \".tsx\",\n \".js\",\n \".jsx\",\n \".json\",\n \".md\",\n \".txt\",\n \".yml\",\n \".yaml\",\n \".css\",\n \".html\",\n \".xml\",\n \".svg\",\n \".py\",\n \".rs\",\n \".go\",\n \".java\",\n \".sh\",\n \".bash\",\n \".zsh\",\n \".fish\",\n \".toml\",\n \".ini\",\n \".cfg\",\n \".env\",\n \".gitignore\",\n \".editorconfig\",\n \".c\",\n \".h\",\n \".cpp\",\n \".hpp\",\n \".rb\",\n \".php\",\n \".sql\",\n \".graphql\",\n \".proto\",\n \".vue\",\n \".svelte\",\n \".astro\",\n]);\n\nfunction isTextExtension(filePath: string): boolean {\n const ext = filePath.slice(filePath.lastIndexOf(\".\")).toLowerCase();\n return TEXT_EXTENSIONS.has(ext);\n}\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { file_path, offset, limit } = invocation.payload as {\n file_path: string;\n offset?: number;\n limit?: number;\n };\n\n const startTime = Date.now();\n\n // Check abort before I/O\n if (signal.aborted) {\n return {\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n const fileStat = await stat(file_path);\n\n if (!fileStat.isFile()) {\n return {\n success: false,\n content: `不是文件: ${file_path}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (fileStat.size > 10 * 1024 * 1024) {\n return {\n success: false,\n content: `文件过大 (${(fileStat.size / 1024 / 1024).toFixed(1)}MB)。请使用 offset/limit 分段读取。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (!isTextExtension(file_path)) {\n // Binary file — return MIME + base64\n const buf = await readFile(file_path);\n const mime = guessMime(file_path);\n const b64 = buf.toString(\"base64\");\n const truncated = b64.length > 50000;\n return {\n success: true,\n content: `[${mime}] base64 数据 (${buf.length} 字节):\\n${truncated ? b64.slice(0, 49997) + \"...\" : b64}`,\n metadata: { durationMs: Date.now() - startTime, truncated },\n };\n }\n\n const raw = await readFile(file_path, \"utf-8\");\n const lines = raw.split(\"\\n\");\n const startLine = (offset ?? 1) - 1;\n const endLine = limit ? startLine + limit : startLine + MAX_LINES;\n const slice = lines.slice(startLine, endLine);\n\n const truncated = endLine < lines.length;\n let content = slice.join(\"\\n\");\n\n if (truncated) {\n content += `\\n\\n[已截断 — 剩余 ${lines.length - endLine} 行。使用 offset=${endLine + 1} 继续读取。]`;\n }\n\n return {\n success: true,\n content,\n metadata: {\n durationMs: Date.now() - startTime,\n truncated,\n truncatedAt: truncated ? endLine : undefined,\n },\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return {\n success: false,\n content: `文件未找到: ${file_path}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n if ((err as NodeJS.ErrnoException).code === \"EACCES\") {\n return {\n success: false,\n content: `权限不足: ${file_path}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n return {\n success: false,\n content: `读取文件失败: ${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n },\n};\n\nfunction guessMime(filePath: string): string {\n const ext = filePath.slice(filePath.lastIndexOf(\".\")).toLowerCase();\n const map: Record<string, string> = {\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".svg\": \"image/svg+xml\",\n \".webp\": \"image/webp\",\n \".pdf\": \"application/pdf\",\n \".zip\": \"application/zip\",\n \".gz\": \"application/gzip\",\n \".mp3\": \"audio/mpeg\",\n \".wav\": \"audio/wav\",\n \".mp4\": \"video/mp4\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n \".ttf\": \"font/ttf\",\n \".ico\": \"image/x-icon\",\n \".bin\": \"application/octet-stream\",\n };\n return map[ext] ?? \"application/octet-stream\";\n}\n","/**\n * write_file — Create or overwrite a file with content.\n *\n * Creates parent directories automatically. Overwrites existing files\n * without asking (permission pipeline handles safety).\n */\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"write_file\",\n description: \"创建新文件或完全覆盖已有文件。父目录不存在时会自动创建。\",\n inputSchema: {\n type: \"object\",\n properties: {\n file_path: { type: \"string\", description: \"要写入的文件绝对路径\" },\n content: { type: \"string\", description: \"要写入文件的内容\" },\n },\n required: [\"file_path\", \"content\"],\n },\n kind: \"WritesFiles\",\n safety: \"WorkspaceSafe\",\n availability: { type: \"always\" },\n executor: \"core:write_file\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { file_path, content } = invocation.payload as {\n file_path: string;\n content: string;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n await mkdir(dirname(file_path), { recursive: true });\n await writeFile(file_path, content, \"utf-8\");\n\n return {\n success: true,\n content: `已写入 ${content.length} 字节到 ${file_path}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `写入文件失败: ${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n },\n};\n","/**\n * edit_file — Exact string replacement in an existing file.\n *\n * `old_string` must match EXACTLY once in the file (or use replace_all).\n * This is the primary editing tool — LLMs should use it instead of write_file\n * for targeted changes.\n */\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"edit_file\",\n description:\n \"在文件中执行精确字符串替换。old_string 必须在文件中精确匹配(包括空格和缩进),\" +\n \"除非设置 replace_all 为 true。\",\n inputSchema: {\n type: \"object\",\n properties: {\n file_path: { type: \"string\", description: \"要编辑的文件绝对路径\" },\n old_string: {\n type: \"string\",\n description: \"要替换的精确文本 — 必须唯一匹配\",\n },\n new_string: { type: \"string\", description: \"替换后的新文本\" },\n replace_all: {\n type: \"boolean\",\n description: \"替换所有匹配项(而非仅第一个)\",\n },\n },\n required: [\"file_path\", \"old_string\", \"new_string\"],\n },\n kind: \"WritesFiles\",\n safety: \"WorkspaceSafe\",\n availability: { type: \"always\" },\n executor: \"core:edit_file\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { file_path, old_string, new_string, replace_all } = invocation.payload as {\n file_path: string;\n old_string: string;\n new_string: string;\n replace_all?: boolean;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (old_string === new_string) {\n return {\n success: false,\n content: \"old_string 与 new_string 相同 — 未做任何更改\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n const original = await readFile(file_path, \"utf-8\");\n\n const count = countOccurrences(original, old_string);\n if (count === 0) {\n return {\n success: false,\n content: `在 ${file_path} 中未找到 old_string。请确认文本精确匹配(包括缩进和空格)。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (count > 1 && !replace_all) {\n return {\n success: false,\n content: `old_string 在 ${file_path} 中出现了 ${count} 次。请设置 replace_all: true 替换所有匹配项,或提供更多上下文使匹配唯一。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const updated = replace_all\n ? original.replaceAll(old_string, new_string)\n : original.replace(old_string, new_string);\n\n await writeFile(file_path, updated, \"utf-8\");\n\n const changed = replace_all ? count : 1;\n return {\n success: true,\n content: `已在 ${file_path} 中替换 ${changed} 处`,\n metadata: { durationMs: Date.now() - startTime },\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return {\n success: false,\n content: `文件未找到: ${file_path}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n return {\n success: false,\n content: `编辑文件失败: ${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n },\n};\n\nfunction countOccurrences(haystack: string, needle: string): number {\n if (needle.length === 0) return 0;\n let count = 0;\n let pos = 0;\n while ((pos = haystack.indexOf(needle, pos)) !== -1) {\n count++;\n pos += needle.length;\n }\n return count;\n}\n","/**\n * glob — Fast file pattern matching.\n *\n * Returns sorted absolute paths. Default excludes: node_modules, .git, dist, build.\n */\nimport { readdir } from \"node:fs/promises\";\nimport { join, relative, resolve } from \"node:path\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"glob\",\n description: \"用 glob 模式匹配文件。返回排序后的绝对路径。\" + \"支持 ** 递归匹配、* 通配符。\",\n inputSchema: {\n type: \"object\",\n properties: {\n pattern: {\n type: \"string\",\n description: '要匹配的 glob 模式(如 \"**/*.ts\" 或 \"src/**/*.test.ts\")',\n },\n path: { type: \"string\", description: \"搜索的根目录(默认为当前工作目录)\" },\n },\n required: [\"pattern\"],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:glob\",\n owner: \"core\",\n};\n\nconst DEFAULT_EXCLUDE = new Set([\n \"node_modules\",\n \".git\",\n \"dist\",\n \"build\",\n \".next\",\n \"coverage\",\n \"__pycache__\",\n \".venv\",\n \"venv\",\n]);\nconst MAX_RESULTS = 10000;\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { pattern, path: rootPath } = invocation.payload as {\n pattern: string;\n path?: string;\n };\n\n const startTime = Date.now();\n const base = rootPath ? resolve(rootPath) : process.cwd();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n const results: string[] = [];\n await walk({ dir: base, pattern, base, results, signal, maxResults: MAX_RESULTS });\n\n const truncated = results.length >= MAX_RESULTS;\n let content = results.sort().join(\"\\n\");\n if (truncated) {\n content += `\\n\\n[已截断 — ${results.length}+ 条结果。请缩小匹配范围。]`;\n }\n\n return {\n success: true,\n content: content || \"(无匹配)\",\n metadata: { durationMs: Date.now() - startTime, truncated },\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `文件匹配失败: ${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n },\n};\n\n/** Options for the recursive {@link walk} function. */\ninterface WalkOptions {\n dir: string;\n pattern: string;\n base: string;\n results: string[];\n signal: AbortSignal;\n maxResults: number;\n}\n\nasync function walk(opts: WalkOptions): Promise<void> {\n if (opts.results.length >= opts.maxResults || opts.signal.aborted) return;\n\n let entries;\n try {\n entries = await readdir(opts.dir, { withFileTypes: true });\n } catch {\n return; // Permission denied, etc. — skip silently\n }\n\n for (const entry of entries) {\n if (opts.results.length >= opts.maxResults || opts.signal.aborted) break;\n if (DEFAULT_EXCLUDE.has(entry.name) || entry.name.startsWith(\".\")) continue;\n\n const full = join(opts.dir, entry.name);\n\n if (entry.isDirectory()) {\n await walk({ ...opts, dir: full });\n } else if (entry.isFile()) {\n const rel = relative(opts.base, full).replace(/\\\\/g, \"/\");\n if (matchGlob(rel, opts.pattern)) {\n opts.results.push(full);\n }\n }\n }\n}\n\nfunction matchGlob(filepath: string, pattern: string): boolean {\n // Simple glob matching: **, *, and literal segments\n const patParts = pattern.replace(/\\\\/g, \"/\").split(\"/\");\n const fpParts = filepath.split(\"/\");\n\n let pi = 0;\n let fi = 0;\n\n while (pi < patParts.length && fi < fpParts.length) {\n const pp = patParts[pi];\n const fp = fpParts[fi];\n\n if (pp === \"**\") {\n // ** matches zero or more path segments\n if (pi === patParts.length - 1) return true; // trailing ** matches everything\n pi++;\n // Try matching the rest at current and subsequent positions\n const restPat = patParts.slice(pi);\n for (let k = fi; k < fpParts.length; k++) {\n if (matchRest(fpParts.slice(k), restPat)) return true;\n }\n return false;\n }\n\n if (!matchSegment(fp, pp)) return false;\n pi++;\n fi++;\n }\n\n // Both exhausted → match\n return pi === patParts.length && fi === fpParts.length;\n}\n\nfunction matchRest(fpParts: string[], patParts: string[]): boolean {\n if (patParts.length === 0) return fpParts.length === 0;\n if (fpParts.length === 0) return patParts.every((p) => p === \"**\");\n if (patParts[0] === \"**\") return matchGlob(fpParts.join(\"/\"), patParts.join(\"/\"));\n if (!matchSegment(fpParts[0], patParts[0])) return false;\n return matchRest(fpParts.slice(1), patParts.slice(1));\n}\n\nfunction matchSegment(name: string, seg: string): boolean {\n if (seg === \"*\") return !name.includes(\"/\");\n // Convert glob segment to regex\n const regex = new RegExp(\n \"^\" +\n seg\n .replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n .replace(/\\*/g, \"[^/]*\")\n .replace(/\\?/g, \"[^/]\") +\n \"$\",\n );\n return regex.test(name);\n}\n","/**\n * grep — Regular expression content search (ripgrep-backed).\n *\n * Falls back to a pure-JS implementation when rg is not available.\n * Default head_limit=250 to prevent overwhelming output.\n */\nimport { type ChildProcess, execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nconst _execFileAsync = promisify(execFile);\n\n/** Options for {@link buildRgArgs}. */\ninterface BuildRgArgsOptions {\n pattern: string;\n path?: string;\n glob?: string;\n outputMode?: string;\n showLineNum?: boolean;\n caseInsensitive?: boolean;\n context?: number;\n}\n\n/** Collected output from a ripgrep stream. */\ninterface RgCollectedOutput {\n lines: string[];\n byteTruncated: boolean;\n}\n\nexport const descriptor: ToolDescriptor = {\n name: \"grep\",\n description: \"使用正则表达式搜索文件内容。\" + \"返回匹配行及可选的上下文。优先使用 ripgrep。\",\n inputSchema: {\n type: \"object\",\n properties: {\n pattern: { type: \"string\", description: \"要搜索的正则表达式\" },\n path: { type: \"string\", description: \"搜索的文件或目录(默认为当前工作目录)\" },\n glob: { type: \"string\", description: '用于过滤文件的 glob 模式(如 \"*.ts\")' },\n output_mode: {\n type: \"string\",\n enum: [\"content\", \"files_with_matches\", \"count\"],\n description:\n \"输出模式: content 显示匹配行, files_with_matches 显示文件路径, count 显示匹配计数\",\n },\n \"-n\": { type: \"boolean\", description: \"显示行号\" },\n \"-i\": { type: \"boolean\", description: \"忽略大小写\" },\n \"-C\": {\n type: \"integer\",\n description: \"匹配前后各显示的行数(上下文行数)\",\n },\n head_limit: { type: \"integer\", description: \"最大输出行数(默认: 250)\" },\n },\n required: [\"pattern\"],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:grep\",\n owner: \"core\",\n};\n\nconst DEFAULT_HEAD_LIMIT = 250;\nconst MAX_LINE_LENGTH = 1000;\nconst MAX_TOTAL_BYTES = 50_000;\n\n/**\n * Stream stdout from a ripgrep child process, collecting lines with\n * per-line length and total-byte limits enforced inline.\n */\nfunction collectRgLines(child: ChildProcess, limit: number): Promise<RgCollectedOutput> {\n return new Promise((resolve, reject) => {\n const collected: string[] = [];\n let lineCount = 0;\n let totalBytes = 0;\n let byteTruncated = false;\n\n const killIfAlive = () => {\n if (!child.killed) child.kill();\n };\n\n if (child.stdout) {\n let buffer = \"\";\n child.stdout.on(\"data\", (chunk: Buffer) => {\n buffer += chunk.toString(\"utf-8\");\n const rawLines = buffer.split(\"\\n\");\n buffer = rawLines.pop() ?? \"\";\n\n for (const raw of rawLines) {\n if (lineCount >= limit) {\n killIfAlive();\n break;\n }\n\n let l = raw;\n if (l.length > MAX_LINE_LENGTH) {\n l = l.slice(0, MAX_LINE_LENGTH) + \" [已截断]\";\n }\n\n const lineBytes = Buffer.byteLength(l, \"utf-8\") + 1;\n if (totalBytes + lineBytes > MAX_TOTAL_BYTES) {\n byteTruncated = true;\n killIfAlive();\n break;\n }\n\n collected.push(l);\n lineCount++;\n totalBytes += lineBytes;\n }\n });\n }\n\n child.on(\"close\", () => resolve({ lines: collected, byteTruncated }));\n child.on(\"error\", reject);\n });\n}\n\n/**\n * Build the final {@link ToolResult} from collected grep output.\n */\nfunction buildGrepResult(\n collected: string[],\n limit: number,\n byteTruncated: boolean,\n startTime: number,\n): ToolResult {\n const lineCount = collected.length;\n const truncated = lineCount >= limit || byteTruncated;\n const output = collected.join(\"\\n\");\n\n if (output.length === 0 && !truncated) {\n return {\n success: true,\n content: \"(无匹配)\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const suffix = truncated\n ? byteTruncated\n ? `\\n\\n[已截断 — 输出超过 ${MAX_TOTAL_BYTES} 字节。请缩小搜索范围。]`\n : `\\n\\n[已截断 — 达到 ${limit} 行限制。请缩小搜索范围。]`\n : \"\";\n\n return {\n success: true,\n content: output + suffix,\n metadata: {\n durationMs: Date.now() - startTime,\n truncated,\n truncatedAt: truncated ? limit : undefined,\n },\n };\n}\n\n/**\n * Classify an error thrown during ripgrep execution and return the\n * appropriate {@link ToolResult}, or `null` if the caller should\n * fall through to the JS fallback.\n */\nfunction classifyRgError(\n err: unknown,\n signal: AbortSignal | undefined,\n startTime: number,\n): ToolResult | null {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return null; // rg not installed — fall through\n }\n if ((err as { killed?: boolean }).killed) {\n return {\n success: false,\n content: \"搜索超时(30 秒)\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n if (signal?.aborted) {\n return {\n success: false,\n content: \"Operation cancelled\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n // rg exit code 1 = no matches (not an error)\n const stderr = (err as { stderr?: string }).stderr;\n if (stderr) {\n return {\n success: false,\n content: `grep 错误: ${stderr.slice(0, 500)}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n return {\n success: true,\n content: \"(no matches)\",\n metadata: { durationMs: Date.now() - startTime },\n };\n}\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const {\n pattern,\n path,\n glob,\n output_mode,\n \"-n\": showLineNum,\n \"-i\": caseInsensitive,\n \"-C\": context,\n head_limit,\n } = invocation.payload as {\n pattern: string;\n path?: string;\n glob?: string;\n output_mode?: \"content\" | \"files_with_matches\" | \"count\";\n \"-n\"?: boolean;\n \"-i\"?: boolean;\n \"-C\"?: number;\n head_limit?: number;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const limit = head_limit ?? DEFAULT_HEAD_LIMIT;\n\n // Try ripgrep first\n try {\n const args = buildRgArgs({\n pattern,\n path,\n glob,\n outputMode: output_mode,\n showLineNum,\n caseInsensitive,\n context,\n });\n const child = execFile(\"rg\", args, {\n cwd: process.cwd(),\n timeout: 30_000,\n maxBuffer: 10 * 1024 * 1024,\n signal,\n });\n\n const { lines, byteTruncated } = await collectRgLines(child, limit);\n return buildGrepResult(lines, limit, byteTruncated, startTime);\n } catch (err) {\n const classified = classifyRgError(err, signal, startTime);\n if (classified !== null) return classified;\n // ENOENT — fall through to JS fallback\n }\n\n // Fallback: ripgrep not available\n return {\n success: false,\n content:\n \"ripgrep (rg) 未安装。请安装 ripgrep 以支持 grep 功能: https://github.com/BurntSushi/ripgrep\",\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n\nfunction buildRgArgs(opts: BuildRgArgsOptions): string[] {\n const args: string[] = [\"--no-heading\", \"--color=never\"];\n\n if (opts.showLineNum !== false) args.push(\"--line-number\"); // default on\n if (opts.caseInsensitive) args.push(\"--ignore-case\");\n if (opts.context !== undefined) args.push(\"-C\", String(opts.context));\n if (opts.glob) args.push(\"--glob\", opts.glob);\n\n switch (opts.outputMode) {\n case \"files_with_matches\":\n args.push(\"-l\");\n break;\n case \"count\":\n args.push(\"--count\");\n break;\n default:\n break; // content mode\n }\n\n args.push(\"--\", opts.pattern);\n if (opts.path) args.push(opts.path);\n\n return args;\n}\n","/**\n * web_fetch — Fetch URL content and return it as plain text.\n *\n * HTTP → HTTPS upgrade. Cross-host redirects are returned to the caller.\n * Results cached for 15 minutes per URL.\n * HTML content is converted to plain text (tags stripped, entities decoded).\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\n// ── URL Allowlist ──────────────────────────────────────\n\n/** 约 50 个常用安全域名 */\nconst ALLOWED_DOMAINS = new Set([\n \"github.com\",\n \"gitlab.com\",\n \"npmjs.com\",\n \"pypi.org\",\n \"crates.io\",\n \"docs.rs\",\n \"stackoverflow.com\",\n \"wikipedia.org\",\n \"nodejs.org\",\n \"typescriptlang.org\",\n \"developer.mozilla.org\",\n \"anthropic.com\",\n \"openai.com\",\n \"googleapis.com\",\n \"eslint.org\",\n \"prettier.io\",\n \"jestjs.io\",\n \"vitest.dev\",\n \"playwright.dev\",\n \"docker.com\",\n \"kubernetes.io\",\n \"terraform.io\",\n \"redis.io\",\n \"postgresql.org\",\n \"mysql.com\",\n \"mongodb.com\",\n \"sqlite.org\",\n \"rust-lang.org\",\n \"golang.org\",\n \"python.org\",\n \"ruby-lang.org\",\n \"php.net\",\n \"java.com\",\n \"kernel.org\",\n \"archlinux.org\",\n \"ubuntu.com\",\n \"debian.org\",\n \"redhat.com\",\n \"aws.amazon.com\",\n \"cloud.google.com\",\n \"azure.microsoft.com\",\n \"reactjs.org\",\n \"vuejs.org\",\n \"angular.io\",\n \"svelte.dev\",\n \"nextjs.org\",\n \"nuxt.com\",\n \"tailwindcss.com\",\n \"vitejs.dev\",\n \"webpack.js.org\",\n \"babeljs.io\",\n]);\n\n/** 禁止访问的域名(本地、云元数据端点等) */\nconst BLOCKED_DOMAINS = new Set([\n \"localhost\",\n \"127.0.0.1\",\n \"0.0.0.0\",\n \"::1\",\n \"metadata.google.internal\",\n \"169.254.169.254\",\n]);\n\n/** IPv4 地址正则 */\nconst IPV4_RE = /^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/;\n\n/**\n * 检查 URL 是否在允许访问的范围内。\n *\n * 规则(按优先级):\n * 1. URL 解析失败 → 拒绝\n * 2. IP 地址 → 拒绝\n * 3. 被阻止的域名 → 拒绝\n * 4. .local / .internal TLD → 拒绝\n * 5. URL 中包含 userinfo(username:password@host)→ 拒绝\n * 6. 域名在允许列表中(去除 www. 前缀后匹配,支持子域名通配)→ 允许\n * 7. 默认 → 拒绝\n */\nexport function isUrlAllowed(url: string): { allowed: boolean; reason: string } {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n return { allowed: false, reason: `URL 解析失败: ${url}` };\n }\n\n const host = parsed.hostname.toLowerCase();\n\n // 阻止 IP 地址\n if (IPV4_RE.test(host) || host === \"::1\") {\n return { allowed: false, reason: `不允许访问 IP 地址: ${host}` };\n }\n\n // 阻止被禁域名\n if (BLOCKED_DOMAINS.has(host)) {\n return { allowed: false, reason: `不允许访问该域名: ${host}` };\n }\n\n // 阻止 .local 和 .internal TLD\n if (host.endsWith(\".local\") || host.endsWith(\".internal\")) {\n return { allowed: false, reason: `不允许访问本地/内部域名: ${host}` };\n }\n\n // 阻止 URL 中包含 userinfo\n if (parsed.username || parsed.password) {\n return { allowed: false, reason: \"URL 中包含认证信息(username:password),已拒绝\" };\n }\n\n // 检查允许列表(去除 www. 前缀后匹配)\n const strippedHost = host.startsWith(\"www.\") ? host.slice(4) : host;\n if (ALLOWED_DOMAINS.has(strippedHost)) {\n return { allowed: true, reason: \"\" };\n }\n\n // 子域名通配:检查父域名是否在允许列表中\n const parts = strippedHost.split(\".\");\n for (let i = 1; i < parts.length; i++) {\n const parentDomain = parts.slice(i).join(\".\");\n if (ALLOWED_DOMAINS.has(parentDomain)) {\n return { allowed: true, reason: \"\" };\n }\n }\n\n return {\n allowed: false,\n reason: `域名 \"${host}\" 不在允许列表中。如需访问请联系用户确认。`,\n };\n}\n\nexport const descriptor: ToolDescriptor = {\n name: \"web_fetch\",\n description:\n \"从 URL 获取内容并以文本形式返回。\" +\n \"HTTP 自动升级为 HTTPS。跨域重定向会返回给调用方而非自动跟随。\" +\n \"每个 URL 的结果缓存 15 分钟。HTML 内容会转换为纯文本。\",\n inputSchema: {\n type: \"object\",\n properties: {\n url: { type: \"string\", format: \"uri\", description: \"要获取内容的 URL\" },\n maxChars: {\n type: \"integer\",\n description: \"返回的最大字符数(默认: 50000)\",\n },\n },\n required: [\"url\"],\n },\n kind: \"Network\",\n safety: \"RequiresApproval\",\n availability: { type: \"always\" },\n executor: \"core:web_fetch\",\n owner: \"core\",\n};\n\n// Simple in-memory cache: url → { content, timestamp }\nconst cache = new Map<string, { content: string; ts: number }>();\nconst CACHE_TTL_MS = 15 * 60 * 1000; // 15 minutes\n\n/**\n * Strip HTML tags and decode entities to produce readable plain text.\n *\n * Handles the most common HTML entities and normalizes whitespace.\n * Not a full HTML parser — just enough to extract readable content from\n * typical web pages.\n */\nfunction htmlToText(html: string): string {\n let text = html\n // Remove script and style elements with their contents\n .replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, \"\")\n .replace(/<style\\b[^<]*(?:(?!<\\/style>)<[^<]*)*<\\/style>/gi, \"\")\n // Replace block-level tags with newlines\n .replace(\n /<\\/(?:div|p|h[1-6]|li|tr|article|section|header|footer|nav|aside|main|table|thead|tbody|tfoot|form|fieldset|pre|blockquote|dl|dt|dd|hr|br)[^>]*>/gi,\n \"\\n\",\n )\n .replace(/<(?:br|hr)[^>]*\\/?>/gi, \"\\n\")\n // Remove remaining HTML tags\n .replace(/<[^>]*>/g, \"\")\n // Decode common HTML entities\n .replace(/&amp;/g, \"&\")\n .replace(/&lt;/g, \"<\")\n .replace(/&gt;/g, \">\")\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\")\n .replace(/&nbsp;/g, \" \")\n .replace(/&#x27;/g, \"'\")\n .replace(/&#x2F;/g, \"/\")\n .replace(/&#(\\d+);/g, (_m, code) => String.fromCodePoint(Number.parseInt(code, 10)))\n .replace(/&#[xX]([0-9a-fA-F]+);/g, (_m, hex) => String.fromCodePoint(Number.parseInt(hex, 16)))\n // Collapse whitespace\n .replace(/[ \\t]+/g, \" \")\n .replace(/\\n{3,}/g, \"\\n\\n\")\n .trim();\n\n return text;\n}\n\n/**\n * Extract readable text from raw response body based on Content-Type.\n *\n * HTML responses are converted to plain text. Non‑HTML responses are\n * returned as‑is.\n */\nfunction extractContent(raw: string, contentType?: string): string {\n const isHtml = contentType\n ? contentType.includes(\"text/html\") || contentType.includes(\"application/xhtml\")\n : raw.trim().startsWith(\"<\") || raw.includes(\"<html\");\n\n return isHtml ? htmlToText(raw) : raw;\n}\n\n/**\n * Trim text to the specified character limit, preserving the beginning\n * (most important content is usually at the top of a page).\n */\nfunction trimToLimit(text: string, limit: number): string {\n if (text.length <= limit) return text;\n return text.slice(0, limit);\n}\n\n/** Set of HTTP redirect status codes. */\nconst REDIRECT_CODES = new Set([301, 302, 307, 308]);\n\n/**\n * Validate and normalize a URL for fetching.\n *\n * Upgrades HTTP to HTTPS. Returns the normalized URL or an error result.\n */\nfunction validateUrl(\n rawUrl: string,\n startTime: number,\n): { ok: true; url: string } | { ok: false; error: ToolResult } {\n let normalized = rawUrl;\n if (normalized.startsWith(\"http://\")) {\n normalized = normalized.replace(\"http://\", \"https://\");\n }\n if (!normalized.startsWith(\"https://\")) {\n return {\n ok: false,\n error: {\n success: false,\n content: `无效的 URL: ${rawUrl}。必须使用 http:// 或 https://。`,\n metadata: { durationMs: Date.now() - startTime },\n },\n };\n }\n return { ok: true, url: normalized };\n}\n\n/** Options for {@link handleFetchRedirect}. */\ninterface FetchRedirectOptions {\n fetchUrl: string;\n originalUrl: string;\n resp: Response;\n controller: AbortController;\n charLimit: number;\n startTime: number;\n}\n\n/**\n * Handle an HTTP redirect response.\n *\n * For cross-host redirects, returns a message instructing the caller to\n * re-issue the request. For same-host redirects, follows the redirect\n * and returns the fetched content.\n */\nasync function handleFetchRedirect(opts: FetchRedirectOptions): Promise<ToolResult> {\n const location = opts.resp.headers.get(\"location\") || \"\";\n try {\n const redirectHost = new URL(location).host;\n const originalHost = new URL(opts.fetchUrl).host;\n if (redirectHost !== originalHost) {\n return {\n success: true,\n content: `重定向至: ${location}\\n\\n检测到跨域重定向。请使用重定向后的 URL 重新调用 web_fetch。`,\n metadata: { durationMs: Date.now() - opts.startTime },\n };\n }\n // Same-host redirect — follow it\n const followResp = await fetch(location, {\n signal: opts.controller.signal,\n headers: { \"User-Agent\": \"Lynx/1.0\" },\n });\n const raw = await followResp.text();\n const extracted = extractContent(raw, opts.resp.headers.get(\"content-type\") ?? undefined);\n cache.set(opts.originalUrl, { content: extracted, ts: Date.now() });\n const output = trimToLimit(extracted, opts.charLimit);\n return {\n success: true,\n content: output + (extracted.length > opts.charLimit ? \"\\n\\n[内容已截断]\" : \"\"),\n metadata: {\n durationMs: Date.now() - opts.startTime,\n truncated: extracted.length > opts.charLimit,\n },\n };\n } catch {\n return {\n success: true,\n content: `重定向至: ${location}`,\n metadata: { durationMs: Date.now() - opts.startTime },\n };\n }\n}\n\n/**\n * Build an error ToolResult from a fetch exception.\n */\nfunction buildFetchError(err: unknown, startTime: number): ToolResult {\n if ((err as { name?: string }).name === \"AbortError\") {\n return {\n success: false,\n content: \"获取已中止\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `获取失败: ${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n}\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { url, maxChars } = invocation.payload as { url: string; maxChars?: number };\n const charLimit = maxChars ?? 50_000;\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const validated = validateUrl(url, startTime);\n if (!validated.ok) return validated.error;\n const fetchUrl = validated.url;\n\n // Check URL allowlist\n const urlCheck = isUrlAllowed(fetchUrl);\n if (!urlCheck.allowed) {\n return {\n success: false,\n content: urlCheck.reason,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n // Check cache\n const cached = cache.get(fetchUrl);\n if (cached && Date.now() - cached.ts < CACHE_TTL_MS) {\n const content = trimToLimit(cached.content, charLimit);\n return {\n success: true,\n content: `[缓存于 ${Math.round((Date.now() - cached.ts) / 1000)} 秒前]\\n\\n${content}`,\n metadata: {\n durationMs: Date.now() - startTime,\n truncated: cached.content.length > charLimit,\n },\n };\n }\n\n try {\n const controller = new AbortController();\n signal.addEventListener(\"abort\", () => controller.abort(), { once: true });\n\n const resp = await fetch(fetchUrl, {\n signal: controller.signal,\n redirect: \"manual\",\n headers: { \"User-Agent\": \"Lynx/1.0\" },\n });\n\n if (REDIRECT_CODES.has(resp.status)) {\n return await handleFetchRedirect({\n fetchUrl,\n originalUrl: url,\n resp,\n controller,\n charLimit,\n startTime,\n });\n }\n\n if (!resp.ok) {\n return {\n success: false,\n content: `HTTP 错误 ${resp.status}: ${resp.statusText}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const raw = await resp.text();\n const contentType = resp.headers.get(\"content-type\") ?? undefined;\n const extracted = extractContent(raw, contentType);\n cache.set(url, { content: extracted, ts: Date.now() });\n\n const output = trimToLimit(extracted, charLimit);\n return {\n success: true,\n content: `已获取 ${fetchUrl} (${contentType || \"未知类型\"}):\\n\\n${output}${extracted.length > charLimit ? \"\\n\\n[内容已截断]\" : \"\"}`,\n metadata: { durationMs: Date.now() - startTime, truncated: extracted.length > charLimit },\n };\n } catch (err) {\n return buildFetchError(err, startTime);\n }\n },\n};\n","/**\n * web_search — Search the web via DuckDuckGo HTML search.\n *\n * Returns results with title, URL, and snippet. Supports domain filtering.\n * Uses DuckDuckGo's HTML endpoint (no API key required). Results cached\n * for 15 minutes per query.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\nimport { isUrlAllowed } from \"./web-fetch.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"web_search\",\n description: \"搜索网页并返回包含标题、URL 和摘要的结果。\" + \"支持域名白名单和黑名单过滤。\",\n inputSchema: {\n type: \"object\",\n properties: {\n query: { type: \"string\", description: \"搜索关键词\" },\n allowed_domains: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"只包含来自这些域名的结果\",\n },\n blocked_domains: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"排除来自这些域名的结果\",\n },\n },\n required: [\"query\"],\n },\n kind: \"Network\",\n safety: \"RequiresApproval\",\n availability: { type: \"always\" },\n executor: \"core:web_search\",\n owner: \"core\",\n};\n\n/** A single search result extracted from DuckDuckGo HTML. */\ninterface SearchResult {\n title: string;\n url: string;\n snippet: string;\n}\n\n/** In-memory cache: query → { results, timestamp } */\nconst cache = new Map<string, { results: SearchResult[]; ts: number }>();\nconst CACHE_TTL_MS = 15 * 60 * 1000; // 15 minutes\n\n/**\n * Build an error ToolResult from a fetch exception.\n */\nfunction buildSearchError(err: unknown, startTime: number): ToolResult {\n if ((err as { name?: string }).name === \"AbortError\") {\n return {\n success: false,\n content: \"搜索已中止\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `搜索失败: ${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n}\n\n/**\n * Parse DuckDuckGo HTML search results page into structured results.\n *\n * Extracts title, URL, and snippet from the HTML using regex patterns\n * matching DuckDuckGo's HTML-only result page markup.\n */\nfunction parseDdgHtml(html: string): SearchResult[] {\n const results: SearchResult[] = [];\n\n // DuckDuckGo HTML results use <a class=\"result__a\" href=\"...\"> for titles\n // and <a class=\"result__snippet\"> for snippets\n const linkRegex = /<a[^>]*class=\"result__a\"[^>]*href=\"([^\"]*)\"[^>]*>([\\s\\S]*?)<\\/a>/gi;\n const snippetRegex = /<a[^>]*class=\"result__snippet\"[^>]*>([\\s\\S]*?)<\\/a>/gi;\n\n // Collect all title/URL pairs and snippets separately, then pair them\n const links: Array<{ title: string; url: string }> = [];\n let linkMatch: RegExpExecArray | null;\n while ((linkMatch = linkRegex.exec(html)) !== null) {\n const url = linkMatch[1];\n const title = linkMatch[2].replace(/<[^>]*>/g, \"\").trim();\n if (url && title && !url.startsWith(\"//duckduckgo.com\")) {\n links.push({ title, url });\n }\n }\n\n const snippets: string[] = [];\n let snippetMatch: RegExpExecArray | null;\n while ((snippetMatch = snippetRegex.exec(html)) !== null) {\n const text = snippetMatch[1].replace(/<[^>]*>/g, \"\").trim();\n if (text) snippets.push(text);\n }\n\n // Pair links with snippets (they appear in order)\n const count = Math.min(links.length, snippets.length);\n for (let i = 0; i < count; i++) {\n results.push({\n title: links[i].title,\n url: links[i].url,\n snippet: snippets[i],\n });\n }\n\n return results;\n}\n\n/**\n * Filter search results by allowed/blocked domains.\n */\nfunction filterByDomain(\n results: SearchResult[],\n allowed?: string[],\n blocked?: string[],\n): SearchResult[] {\n let filtered = results;\n\n if (allowed && allowed.length > 0) {\n const allowedLower = allowed.map((d) => d.toLowerCase());\n filtered = filtered.filter((r) => {\n try {\n const host = new URL(r.url).host.toLowerCase();\n return allowedLower.some((d) => host.includes(d));\n } catch {\n return false;\n }\n });\n }\n\n if (blocked && blocked.length > 0) {\n const blockedLower = blocked.map((d) => d.toLowerCase());\n filtered = filtered.filter((r) => {\n try {\n const host = new URL(r.url).host.toLowerCase();\n return !blockedLower.some((d) => host.includes(d));\n } catch {\n return true;\n }\n });\n }\n\n return filtered;\n}\n\n/**\n * Format search results into a readable text block.\n */\nfunction formatResults(results: SearchResult[], query: string): string {\n if (results.length === 0) {\n return `未找到与 \"${query}\" 相关的结果。`;\n }\n return results\n .map((r, i) => `${i + 1}. **${r.title}**\\n ${r.url}\\n ${r.snippet}`)\n .join(\"\\n\\n\");\n}\n\n/** Generate a cache key from the query and domain filters. */\nfunction cacheKey(query: string, allowed?: string[], blocked?: string[]): string {\n const parts = [query];\n if (allowed?.length) parts.push(\"allow:\" + allowed.sort().join(\",\"));\n if (blocked?.length) parts.push(\"block:\" + blocked.sort().join(\",\"));\n return parts.join(\"|\");\n}\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { query, allowed_domains, blocked_domains } = invocation.payload as {\n query: string;\n allowed_domains?: string[];\n blocked_domains?: string[];\n };\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (!query || query.trim().length === 0) {\n return {\n success: false,\n content: \"请输入搜索关键词.\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const key = cacheKey(query.trim(), allowed_domains, blocked_domains);\n\n // Check cache\n const cached = cache.get(key);\n if (cached && Date.now() - cached.ts < CACHE_TTL_MS) {\n const age = Math.round((Date.now() - cached.ts) / 1000);\n const content = `[缓存于 ${age} 秒前]\\n\\n${formatResults(cached.results, query)}`;\n return {\n success: true,\n content,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n const controller = new AbortController();\n signal.addEventListener(\"abort\", () => controller.abort(), { once: true });\n\n const searchUrl = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(query.trim())}`;\n\n // Check URL allowlist\n const urlCheck = isUrlAllowed(searchUrl);\n if (!urlCheck.allowed) {\n return {\n success: false,\n content: urlCheck.reason,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const resp = await fetch(searchUrl, {\n signal: controller.signal,\n headers: {\n \"User-Agent\": \"Lynx/1.0\",\n Accept: \"text/html\",\n },\n });\n\n if (!resp.ok) {\n return {\n success: false,\n content: `搜索请求失败: HTTP ${resp.status} ${resp.statusText}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const html = await resp.text();\n const allResults = parseDdgHtml(html);\n const filtered = filterByDomain(allResults, allowed_domains, blocked_domains);\n\n // Cache the full results (pre-filter) for reuse with different domain filters\n cache.set(key, { results: filtered, ts: Date.now() });\n\n const content = formatResults(filtered, query);\n return {\n success: true,\n content,\n metadata: {\n durationMs: Date.now() - startTime,\n truncated: filtered.length < allResults.length,\n },\n };\n } catch (err) {\n return buildSearchError(err, startTime);\n }\n },\n};\n","/**\n * todo_write — Create or update the task list.\n *\n * Each call REPLACES the entire list (not incremental).\n * Status: pending → in_progress → completed.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"todo_write\",\n description:\n \"创建和更新任务列表以跟踪进度。\" +\n \"每次调用会替换整个列表。每项任务必须包含 content、status 和 activeForm。\",\n inputSchema: {\n type: \"object\",\n properties: {\n todos: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n content: { type: \"string\", description: \"任务描述\" },\n status: {\n type: \"string\",\n enum: [\"pending\", \"in_progress\", \"completed\"],\n description: \"任务当前状态\",\n },\n activeForm: {\n type: \"string\",\n description: \"任务进行中时显示的现在时标签\",\n },\n },\n required: [\"content\", \"status\", \"activeForm\"],\n },\n description: \"完整的任务列表(替换已有列表)\",\n },\n },\n required: [\"todos\"],\n },\n kind: \"WritesFiles\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:todo_write\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, _signal): Promise<ToolResult> {\n const { todos } = invocation.payload as {\n todos: Array<{\n content: string;\n status: \"pending\" | \"in_progress\" | \"completed\";\n activeForm: string;\n }>;\n };\n\n const startTime = Date.now();\n\n // Validate\n if (!Array.isArray(todos)) {\n return {\n success: false,\n content: \"todos 必须是一个数组\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const statusCounts = { pending: 0, in_progress: 0, completed: 0 };\n for (const todo of todos) {\n if (!todo.content || !todo.status || !todo.activeForm) {\n return {\n success: false,\n content: `无效的任务项: 每项必须包含 content、status 和 activeForm。收到: ${JSON.stringify(todo)}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n if (![\"pending\", \"in_progress\", \"completed\"].includes(todo.status)) {\n return {\n success: false,\n content: `\"${todo.content}\" 的状态 \"${todo.status}\" 无效。必须为: pending, in_progress 或 completed。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n statusCounts[todo.status]++;\n }\n\n const lines = todos.map((t, _i) => {\n const icon = t.status === \"completed\" ? \"✓\" : t.status === \"in_progress\" ? \"●\" : \"○\";\n return `${icon} [${t.status}] ${t.activeForm}: ${t.content}`;\n });\n\n return {\n success: true,\n content:\n `任务列表已更新(共 ${todos.length} 项: ${statusCounts.in_progress} 项进行中, ${statusCounts.pending} 项待处理, ${statusCounts.completed} 项已完成):\\n\\n` +\n lines.join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * powershell — 在 Windows 上执行 PowerShell 命令。\n *\n * 仅在 Windows 平台可用。使用 child_process.exec 执行,\n * 默认 30 秒超时。返回 stdout 和 stderr。\n */\nimport { exec } from \"node:child_process\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"powershell\",\n description:\n \"在 Windows 上执行 PowerShell 命令。返回 stdout 和 stderr。\" +\n \"仅 Windows 平台可用。命令以 -NoProfile 模式运行。\",\n inputSchema: {\n type: \"object\",\n properties: {\n command: {\n type: \"string\",\n description: \"要执行的 PowerShell 命令\",\n },\n timeout: {\n type: \"number\",\n description: \"超时时间(毫秒),默认 30000\",\n default: 30000,\n },\n },\n required: [\"command\"],\n },\n kind: \"ExecutesCode\",\n safety: \"RequiresApproval\",\n availability: { type: \"platform\", platform: \"windows\" },\n executor: \"core:powershell\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { command, timeout } = invocation.payload as {\n command: string;\n timeout?: number;\n };\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (process.platform !== \"win32\") {\n return {\n success: false,\n content: \"PowerShell 工具仅支持 Windows 平台。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (!command || command.trim().length === 0) {\n return {\n success: false,\n content: \"请输入要执行的 PowerShell 命令。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const timeoutMs = timeout ?? 30000;\n const escapedCommand = command.replace(/\"/g, '\\\\\"');\n\n return new Promise<ToolResult>((resolve) => {\n let aborted = false;\n\n const onAbort = () => {\n aborted = true;\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n\n const child = exec(\n `powershell -NoProfile -Command \"${escapedCommand}\"`,\n { timeout: timeoutMs, windowsHide: true },\n (err, stdout, stderr) => {\n signal.removeEventListener(\"abort\", onAbort);\n\n if (aborted) {\n resolve({\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n });\n return;\n }\n\n if (err) {\n const isTimeout = (err as NodeJS.ErrnoException).code === \"ETIMEDOUT\";\n resolve({\n success: false,\n content: isTimeout\n ? `命令执行超时(${timeoutMs}ms)`\n : `命令执行失败: ${err.message}\\n\\nstderr:\\n${stderr}`,\n metadata: { durationMs: Date.now() - startTime },\n });\n return;\n }\n\n const output = [\n stdout ? `stdout:\\n${stdout.trimEnd()}` : null,\n stderr ? `stderr:\\n${stderr.trimEnd()}` : null,\n ]\n .filter(Boolean)\n .join(\"\\n\\n\");\n\n resolve({\n success: true,\n content: output || \"(无输出)\",\n metadata: { durationMs: Date.now() - startTime },\n });\n },\n );\n });\n },\n};\n","/**\n * NotebookEditTool — 编辑 Jupyter notebook (.ipynb) 文件中的单元格。\n *\n * 支持四种操作:\n * - list: 列出所有单元格(索引、类型、源码摘要)\n * - insert: 在指定位置插入新单元格\n * - replace: 替换指定位置的单元格内容\n * - delete: 删除指定位置的单元格\n *\n * .ipynb 文件结构为 JSON: { cells: [{ cell_type, source, ... }], ... }\n * source 字段可以是字符串或字符串数组,统一按字符串数组处理。\n */\nimport { readFileSync, writeFileSync, renameSync } from \"node:fs\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"NotebookEditTool\",\n description:\n \"编辑 Jupyter notebook (.ipynb) 文件中的单元格。\" +\n \"支持插入、替换、删除和列出代码与 Markdown 单元格。\",\n inputSchema: {\n type: \"object\",\n properties: {\n filePath: {\n type: \"string\",\n description: \".ipynb 文件的绝对路径\",\n },\n action: {\n type: \"string\",\n enum: [\"insert\", \"replace\", \"delete\", \"list\"],\n description: \"操作类型:list(列出)、insert(插入)、replace(替换)、delete(删除)\",\n },\n cellIndex: {\n type: \"integer\",\n description:\n \"单元格索引(从 0 开始)。insert 表示插入位置,replace/delete 表示目标单元格。\",\n },\n cellType: {\n type: \"string\",\n enum: [\"code\", \"markdown\"],\n description: \"单元格类型(insert 操作必填)\",\n },\n content: {\n type: \"string\",\n description: \"单元格源码内容(insert/replace 操作需要)\",\n },\n },\n required: [\"filePath\", \"action\"],\n },\n kind: \"WritesFiles\",\n safety: \"WorkspaceSafe\",\n availability: { type: \"always\" },\n executor: \"core:notebook_edit\",\n owner: \"core\",\n};\n\n/** .ipynb 文件内部结构 */\ninterface NotebookJson {\n cells: NotebookCell[];\n metadata?: Record<string, unknown>;\n nbformat?: number;\n nbformat_minor?: number;\n}\n\ninterface NotebookCell {\n cell_type: \"code\" | \"markdown\" | \"raw\";\n source: string | string[];\n metadata?: Record<string, unknown>;\n outputs?: unknown[];\n execution_count?: number | null;\n id?: string;\n}\n\n/** 将 source 字段统一转为字符串数组 */\nfunction normalizeSource(source: string | string[]): string[] {\n if (Array.isArray(source)) return source;\n // 按换行拆分,每行末尾保留换行符(Jupyter 惯例)\n const lines = source.split(\"\\n\");\n return lines.map((line, i) => (i < lines.length - 1 ? line + \"\\n\" : line));\n}\n\n/** 将 source 字段合并为单个字符串 */\nfunction sourceToString(source: string | string[]): string {\n if (typeof source === \"string\") return source;\n return source.join(\"\");\n}\n\n/** 生成单元格源码摘要(前 80 个字符) */\nfunction sourceSummary(source: string | string[]): string {\n const text = sourceToString(source).replace(/\\s+/g, \" \").trim();\n if (text.length <= 80) return text;\n return text.slice(0, 77) + \"...\";\n}\n\n/** 读取 .ipynb 文件并解析 JSON */\nfunction readNotebook(filePath: string, startTime: number): NotebookJson | ToolResult {\n let raw: string;\n try {\n raw = readFileSync(filePath, \"utf-8\");\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return {\n success: false,\n content: `文件未找到: ${filePath}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n return {\n success: false,\n content: `读取文件失败: ${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n return JSON.parse(raw) as NotebookJson;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `解析 .ipynb JSON 失败: ${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n}\n\n/** 原子写入 notebook JSON */\nfunction writeNotebookAtomically(\n filePath: string,\n notebook: NotebookJson,\n startTime: number,\n): ToolResult {\n try {\n const tmpPath = filePath + \".tmp\";\n writeFileSync(tmpPath, JSON.stringify(notebook, null, 1) + \"\\n\", \"utf-8\");\n renameSync(tmpPath, filePath);\n return {\n success: true,\n content: `已保存 notebook: ${filePath}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `写入文件失败: ${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n}\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { filePath, action, cellIndex, cellType, content } = invocation.payload as {\n filePath: string;\n action: string;\n cellIndex?: number;\n cellType?: string;\n content?: string;\n };\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (!filePath.endsWith(\".ipynb\")) {\n return {\n success: false,\n content: `不是 .ipynb 文件: ${filePath}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const notebookOrError = readNotebook(filePath, startTime);\n if (\"success\" in notebookOrError) return notebookOrError;\n const notebook = notebookOrError;\n\n if (!Array.isArray(notebook.cells)) {\n notebook.cells = [];\n }\n\n switch (action) {\n case \"list\": {\n if (notebook.cells.length === 0) {\n return {\n success: true,\n content: \"该 notebook 没有单元格。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const lines = notebook.cells.map((cell, i) => {\n const summary = sourceSummary(cell.source);\n const execCount =\n cell.cell_type === \"code\" && cell.execution_count != null\n ? ` [执行次数: ${cell.execution_count}]`\n : \"\";\n return `${i}: [${cell.cell_type}]${execCount} ${summary}`;\n });\n return {\n success: true,\n content: `共 ${notebook.cells.length} 个单元格:\\n${lines.join(\"\\n\")}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n case \"insert\": {\n if (cellIndex == null) {\n return {\n success: false,\n content: \"insert 操作需要提供 cellIndex 参数。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n if (!cellType || ![\"code\", \"markdown\"].includes(cellType)) {\n return {\n success: false,\n content: \"insert 操作需要提供有效的 cellType(code 或 markdown)。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const newCell: NotebookCell = {\n cell_type: cellType as \"code\" | \"markdown\",\n source: content ? normalizeSource(content) : [],\n metadata: {},\n outputs: cellType === \"code\" ? [] : undefined,\n execution_count: null,\n };\n const insertIndex = Math.min(cellIndex, notebook.cells.length);\n notebook.cells.splice(insertIndex, 0, newCell);\n return writeNotebookAtomically(filePath, notebook, startTime);\n }\n\n case \"replace\": {\n if (cellIndex == null) {\n return {\n success: false,\n content: \"replace 操作需要提供 cellIndex 参数。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n if (cellIndex < 0 || cellIndex >= notebook.cells.length) {\n return {\n success: false,\n content: `单元格索引 ${cellIndex} 超出范围(0-${notebook.cells.length - 1})。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const target = notebook.cells[cellIndex];\n if (content != null) {\n target.source = normalizeSource(content);\n }\n if (cellType && [\"code\", \"markdown\"].includes(cellType)) {\n target.cell_type = cellType as \"code\" | \"markdown\";\n }\n return writeNotebookAtomically(filePath, notebook, startTime);\n }\n\n case \"delete\": {\n if (cellIndex == null) {\n return {\n success: false,\n content: \"delete 操作需要提供 cellIndex 参数。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n if (cellIndex < 0 || cellIndex >= notebook.cells.length) {\n return {\n success: false,\n content: `单元格索引 ${cellIndex} 超出范围(0-${notebook.cells.length - 1})。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const removed = notebook.cells[cellIndex];\n notebook.cells.splice(cellIndex, 1);\n const result = writeNotebookAtomically(filePath, notebook, startTime);\n result.content = `已删除单元格 ${cellIndex} [${removed.cell_type}]: ${sourceSummary(removed.source)}\\n${result.content}`;\n return result;\n }\n\n default: {\n return {\n success: false,\n content: `不支持的操作: ${action}。支持的操作: list, insert, replace, delete。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n }\n },\n};\n","/**\n * SecretScanner — 扫描文件内容以查找潜在的密钥、令牌和凭证。\n *\n * 在写入文件操作前使用此工具检查敏感信息泄露。\n * 支持检测:私钥块、GitHub token、OpenAI key、Google API key、\n * JWT token、通用 API key 模式、密码赋值等。\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"SecretScanner\",\n description:\n \"扫描文件内容以查找潜在的密钥、令牌和凭证。\" +\n \"在写入操作前使用此工具检查敏感信息。\" +\n \"检测模式包括:私钥、GitHub token、OpenAI key、Google API key、JWT、通用 API key、密码赋值。\",\n inputSchema: {\n type: \"object\",\n properties: {\n content: {\n type: \"string\",\n description: \"要扫描的文件内容\",\n },\n filePath: {\n type: \"string\",\n description: \"可选的文件路径,用于在结果中标识来源\",\n },\n },\n required: [\"content\"],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:secret_scan\",\n owner: \"core\",\n};\n\n/** 单个密钥匹配结果 */\ninterface SecretMatch {\n /** 检测模式名称 */\n pattern: string;\n /** 已脱敏的匹配摘要(只显示前 4 个字符 + \"...\") */\n excerpt: string;\n}\n\n/** 预编译的密钥检测正则模式 */\nconst SECRET_PATTERNS: Array<{ name: string; regex: RegExp }> = [\n { name: \"私钥块\", regex: /-----BEGIN (?:RSA |EC |DSA )?PRIVATE KEY-----/ },\n { name: \"GitHub Token\", regex: /gh[pousr]_[A-Za-z0-9_]{36,}/ },\n { name: \"OpenAI Key\", regex: /sk-[A-Za-z0-9]{32,}/ },\n { name: \"Google API Key\", regex: /AIza[0-9A-Za-z\\-_]{35}/ },\n { name: \"JWT Token\", regex: /eyJ[A-Za-z0-9\\-_]+\\.eyJ[A-Za-z0-9\\-_]+.[A-Za-z0-9\\-_]+/ },\n {\n name: \"通用 API Key\",\n regex: /(?:api[_-]?key|apikey|api[_-]?secret)\\s*[:=]\\s*['\"][A-Za-z0-9_\\-]{20,}['\"]/gi,\n },\n {\n name: \"密码赋值\",\n regex: /(?:password|passwd|pwd)\\s*[:=]\\s*['\"][^'\"]+['\"]/gi,\n },\n];\n\n/** 对匹配内容进行脱敏:只显示前 4 个字符 + \"...\" */\nfunction redactExcerpt(fullMatch: string): string {\n if (fullMatch.length <= 8) {\n return fullMatch.slice(0, 4) + \"...\";\n }\n return fullMatch.slice(0, 4) + \"...\" + fullMatch.slice(-4);\n}\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { content, filePath } = invocation.payload as {\n content: string;\n filePath?: string;\n };\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (!content || content.length === 0) {\n return {\n success: true,\n content: \"内容为空,无需扫描。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const findings: SecretMatch[] = [];\n\n for (const { name, regex } of SECRET_PATTERNS) {\n // 重置 lastIndex(因为 regex 可能有 global 标志)\n const re = new RegExp(regex.source, regex.flags);\n let match: RegExpExecArray | null;\n while ((match = re.exec(content)) !== null) {\n const excerpt = redactExcerpt(match[0]);\n findings.push({ pattern: name, excerpt });\n }\n }\n\n if (findings.length === 0) {\n const pathInfo = filePath ? ` (${filePath})` : \"\";\n return {\n success: true,\n content: `未检测到密钥或凭证${pathInfo}。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n // 按模式分组\n const grouped = new Map<string, string[]>();\n for (const f of findings) {\n const excerpts = grouped.get(f.pattern) ?? [];\n excerpts.push(f.excerpt);\n grouped.set(f.pattern, excerpts);\n }\n\n const lines: string[] = [\n `检测到 ${findings.length} 个潜在密钥/凭证!`,\n filePath ? `文件: ${filePath}` : \"\",\n \"\",\n ];\n\n for (const [pattern, excerpts] of grouped) {\n lines.push(`**${pattern}** (${excerpts.length} 处):`);\n // 去重后列出\n const unique = [...new Set(excerpts)];\n for (const excerpt of unique.slice(0, 5)) {\n lines.push(` - ${excerpt}`);\n }\n if (unique.length > 5) {\n lines.push(` ... 还有 ${unique.length - 5} 处`);\n }\n lines.push(\"\");\n }\n\n return {\n success: true,\n content: lines.join(\"\\n\").trimEnd(),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * LSPTool — 语言服务器协议桥接工具。\n *\n * 提供 LSP 诊断、类型信息、跳转定义等功能的最小化接口。\n * 此工具默认隐藏(需设置 flag \"lsp_enabled\" 才会暴露)。\n * 当 IDE 连接后将提供完整的 LSP 集成,目前提供接口契约层。\n */\nimport { readFile } from \"node:fs/promises\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\n// ── Descriptor ────────────────────────────────────────\n\nexport const descriptor: ToolDescriptor = {\n name: \"LSPTool\",\n description:\n \"查询语言服务器协议(LSP)以获取诊断、类型信息、跳转定义等。\" +\n \"支持 diagnostics、hover、definition、references、format 等常见 LSP 操作。\",\n inputSchema: {\n type: \"object\",\n properties: {\n action: {\n type: \"string\",\n enum: [\"diagnostics\", \"hover\", \"definition\", \"references\", \"format\"],\n description: \"LSP 操作类型:诊断、悬停类型信息、跳转定义、查找引用、格式化\",\n },\n filePath: {\n type: \"string\",\n description: \"要查询的文件绝对路径\",\n },\n line: {\n type: \"integer\",\n description: \"行号(从 1 开始),hover/definition 操作使用\",\n },\n character: {\n type: \"integer\",\n description: \"列号(从 1 开始),hover/definition 操作使用\",\n },\n },\n required: [\"action\", \"filePath\"],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"flag\", flag: \"lsp_enabled\" },\n executor: \"core:lsp\",\n owner: \"core\",\n};\n\n// ── Handler ───────────────────────────────────────────\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { action, filePath, line, character } = invocation.payload as {\n action: string;\n filePath: string;\n line?: number;\n character?: number;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"LSP 操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n switch (action) {\n case \"diagnostics\":\n return await handleDiagnostics(filePath, startTime);\n case \"hover\":\n return handleHover(filePath, line, character, startTime);\n case \"definition\":\n return handleDefinition(filePath, line, character, startTime);\n case \"references\":\n return handleReferences(filePath, line, character, startTime);\n case \"format\":\n return handleFormat(filePath, startTime);\n default:\n return {\n success: false,\n content: `未知的 LSP 操作:${action}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `LSP 操作失败:${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n },\n};\n\n// ── Action handlers ───────────────────────────────────\n\n/**\n * 解析文件内容并用正则进行基础语法检查。\n * 真实 LSP 集成在 IDE 连接后提供完整诊断。\n */\nasync function handleDiagnostics(filePath: string, startTime: number): Promise<ToolResult> {\n let content: string;\n try {\n content = await readFile(filePath, \"utf-8\");\n } catch {\n return {\n success: false,\n content: `无法读取文件:${filePath}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const lines = content.split(\"\\n\");\n const issues: string[] = [];\n\n for (let i = 0; i < lines.length; i++) {\n const ln = lines[i];\n // 检查不闭合的括号\n if (countOccurrences(ln, \"{\") !== countOccurrences(ln, \"}\")) {\n issues.push(`第 ${i + 1} 行:花括号不匹配`);\n }\n if (countOccurrences(ln, \"(\") !== countOccurrences(ln, \")\")) {\n issues.push(`第 ${i + 1} 行:圆括号不匹配`);\n }\n if (countOccurrences(ln, \"[\") !== countOccurrences(ln, \"]\")) {\n issues.push(`第 ${i + 1} 行:方括号不匹配`);\n }\n }\n\n const contentText =\n issues.length > 0\n ? `诊断结果(${issues.length} 个问题):\\n${issues.join(\"\\n\")}`\n : \"未发现基础语法问题。完整 LSP 诊断在 IDE 连接后可用。\";\n\n return {\n success: true,\n content: contentText,\n metadata: { durationMs: Date.now() - startTime },\n };\n}\n\n/**\n * 悬停信息:提示 IDE 连接后可用。\n */\nfunction handleHover(\n filePath: string,\n line?: number,\n character?: number,\n startTime?: number,\n): ToolResult {\n const pos = line != null ? `第 ${line} 行` : \"光标位置\";\n const col = character != null ? `第 ${character} 列` : \"\";\n const loc = col ? `${pos},${col}` : pos;\n\n return {\n success: true,\n content: `LSP 悬停信息在 IDE 连接后可用。查询位置:${filePath} ${loc}。当前可用的类型信息需要 IDE 提供 language server 支持。`,\n metadata: { durationMs: Date.now() - (startTime ?? 0) },\n };\n}\n\n/**\n * 跳转定义:返回文件路径和行号提示。\n */\nfunction handleDefinition(\n filePath: string,\n line?: number,\n character?: number,\n startTime?: number,\n): ToolResult {\n const posHint = line != null ? `(接近第 ${line} 行)` : \"\";\n\n return {\n success: true,\n content: `跳转定义在 IDE 连接后可用。源文件:${filePath}${posHint}。连接 LSP 后将返回精确的定义位置。`,\n metadata: { durationMs: Date.now() - (startTime ?? 0) },\n };\n}\n\n/**\n * 查找引用:返回空列表并说明 IDE 连接后可用。\n */\nfunction handleReferences(\n filePath: string,\n line?: number,\n character?: number,\n startTime?: number,\n): ToolResult {\n const posHint = line != null ? `(第 ${line} 行)` : \"\";\n\n return {\n success: true,\n content:\n `引用查找在 IDE 连接后可用。查询:${filePath}${posHint}。当前未找到引用` +\n `(完整引用分析需要 IDE 的 language server 支持)。`,\n metadata: { durationMs: Date.now() - (startTime ?? 0) },\n };\n}\n\n/**\n * 格式化:提示 IDE 连接后可用。\n */\nfunction handleFormat(filePath: string, startTime: number): ToolResult {\n return {\n success: true,\n content: `格式化功能在 IDE 连接后可用。目标文件:${filePath}。LSP 连接后将提供基于 language server 的代码格式化。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n}\n\n// ── Helpers ───────────────────────────────────────────\n\n/** 统计字符串中某字符的出现次数。 */\nfunction countOccurrences(str: string, char: string): number {\n let count = 0;\n for (let i = 0; i < str.length; i++) {\n if (str[i] === char) count++;\n }\n return count;\n}\n","/**\n * REPLTool — 交互式 REPL 代码执行工具。\n *\n * 管理持久化 REPL 子进程(Node.js / Python / Bash),\n * 支持在多次调用之间保持运行状态。\n * 每个会话分配唯一 UUID,通过模块级 Map 跟踪。\n */\nimport { spawn, type ChildProcess } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\n// ── Session tracking ─────────────────────────────────\n\n/** REPL 会话信息。 */\ninterface ReplSession {\n id: string;\n language: string;\n process: ChildProcess;\n createdAt: number;\n}\n\n/** 活跃的 REPL 会话映射,key 为 session UUID。 */\nconst activeSessions = new Map<string, ReplSession>();\n\n// ── Descriptor ────────────────────────────────────────\n\nexport const descriptor: ToolDescriptor = {\n name: \"REPLTool\",\n description:\n \"在持久化 REPL 会话中执行代码。启动运行时(Node.js/Python/Bash)\" +\n \"并保持状态在多次调用之间。\" +\n \"支持 start(启动)、eval(执行)、stop(停止)、status(状态)四种操作。\",\n inputSchema: {\n type: \"object\",\n properties: {\n action: {\n type: \"string\",\n enum: [\"start\", \"eval\", \"stop\", \"status\"],\n description: \"操作类型:启动 REPL、执行代码、停止会话、查看状态\",\n },\n language: {\n type: \"string\",\n enum: [\"node\", \"python\", \"bash\"],\n description: \"运行时语言(start 操作时使用)\",\n },\n code: {\n type: \"string\",\n description: \"要执行的代码(eval 操作时使用)\",\n },\n sessionId: {\n type: \"string\",\n description: \"目标会话 ID(eval/stop 操作时使用)\",\n },\n },\n required: [\"action\"],\n },\n kind: \"ExecutesCode\",\n safety: \"RequiresApproval\",\n availability: { type: \"always\" },\n executor: \"core:repl\",\n owner: \"core\",\n};\n\n// ── Handler ───────────────────────────────────────────\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { action, language, code, sessionId } = invocation.payload as {\n action: string;\n language?: string;\n code?: string;\n sessionId?: string;\n };\n\n const startTime = Date.now();\n\n // 注册 AbortSignal 清理\n if (signal) {\n signal.addEventListener(\"abort\", () => {\n for (const [id, session] of activeSessions) {\n session.process.kill();\n activeSessions.delete(id);\n }\n });\n }\n\n try {\n switch (action) {\n case \"start\":\n return handleStart(language);\n case \"eval\":\n return await handleEval(code, sessionId, signal);\n case \"stop\":\n return handleStop(sessionId);\n case \"status\":\n return handleStatus();\n default:\n return {\n success: false,\n content: `未知操作:${action}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `REPL 操作失败:${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n },\n};\n\n// ── Action handlers ───────────────────────────────────\n\n/** 启动一个新的 REPL 会话并返回 session UUID。 */\nfunction handleStart(language?: string): ToolResult {\n if (!language || ![\"node\", \"python\", \"bash\"].includes(language)) {\n return {\n success: false,\n content: `不支持的语言:${language ?? \"未指定\"}。支持 node、python、bash。`,\n };\n }\n\n const id = randomUUID();\n let childProcess: ChildProcess;\n\n switch (language) {\n case \"node\":\n childProcess = spawn(\"node\", [\"-i\"], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n shell: true,\n });\n break;\n case \"python\":\n childProcess = spawn(\"python3\", [\"-i\"], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n shell: true,\n });\n break;\n case \"bash\":\n childProcess = spawn(\"bash\", [], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n shell: true,\n });\n break;\n default:\n throw new Error(`不支持的语言:${language}`);\n }\n\n const session: ReplSession = {\n id,\n language,\n process: childProcess,\n createdAt: Date.now(),\n };\n\n activeSessions.set(id, session);\n\n // 清理已退出的进程\n childProcess.on(\"exit\", () => {\n activeSessions.delete(id);\n });\n\n return {\n success: true,\n content: `REPL 会话已启动(${language})。会话 ID:${id}`,\n };\n}\n\n/** 在现有 REPL 会话中执行代码。 */\nasync function handleEval(\n code?: string,\n sessionId?: string,\n signal?: AbortSignal,\n): Promise<ToolResult> {\n if (!sessionId) {\n return { success: false, content: \"缺少 sessionId 参数\" };\n }\n if (!code) {\n return { success: false, content: \"缺少 code 参数\" };\n }\n\n const session = activeSessions.get(sessionId);\n if (!session) {\n return { success: false, content: `未找到 REPL 会话:${sessionId}` };\n }\n\n return new Promise((resolve) => {\n const chunks: string[] = [];\n const onData = (data: Buffer) => chunks.push(data.toString());\n session.process.stdout?.on(\"data\", onData);\n\n const timeout = setTimeout(() => {\n session.process.stdout?.removeListener(\"data\", onData);\n resolve({\n success: true,\n content: `执行超时(5s),已发送的代码:\\n\\`\\`\\`\\n${code}\\n\\`\\`\\``,\n });\n }, 5000);\n\n // 监听 abort\n if (signal) {\n const onAbort = () => {\n clearTimeout(timeout);\n session.process.stdout?.removeListener(\"data\", onData);\n resolve({ success: false, content: \"REPL 执行已取消\" });\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n\n session.process.stdin?.write(code + \"\\n\");\n\n // 等短暂时间收集输出\n setTimeout(() => {\n clearTimeout(timeout);\n session.process.stdout?.removeListener(\"data\", onData);\n const output = chunks.join(\"\").trim();\n resolve({\n success: true,\n content: output || \"(无输出)\",\n });\n }, 1000);\n });\n}\n\n/** 停止并移除 REPL 会话。 */\nfunction handleStop(sessionId?: string): ToolResult {\n if (!sessionId) {\n // 停止所有会话\n let count = 0;\n for (const [id, session] of activeSessions) {\n session.process.kill();\n activeSessions.delete(id);\n count++;\n }\n return { success: true, content: `已停止 ${count} 个 REPL 会话` };\n }\n\n const session = activeSessions.get(sessionId);\n if (!session) {\n return { success: false, content: `未找到 REPL 会话:${sessionId}` };\n }\n\n session.process.kill();\n activeSessions.delete(sessionId);\n return { success: true, content: `REPL 会话 ${sessionId} 已停止` };\n}\n\n/** 列出所有活跃会话。 */\nfunction handleStatus(): ToolResult {\n if (activeSessions.size === 0) {\n return { success: true, content: \"当前无活跃的 REPL 会话\" };\n }\n\n const lines: string[] = [];\n for (const session of activeSessions.values()) {\n const age = Math.round((Date.now() - session.createdAt) / 1000);\n lines.push(`${session.id} — ${session.language}(运行中,${age} 秒)`);\n }\n\n return { success: true, content: `活跃会话(${activeSessions.size}):\\n${lines.join(\"\\n\")}` };\n}\n","/**\n * agent — Spawn a sub-agent to handle complex multi-step tasks.\n *\n * The sub-agent runs in an isolated context with restricted tools and a\n * separate token budget (default: 1/4 of parent budget).\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"agent\",\n description:\n \"启动子 Agent 自主处理复杂多步骤任务。\" +\n \"每种子 Agent 类型拥有不同能力和可用工具。\" +\n \"子 Agent 将最终结果返回给父 Agent。\",\n inputSchema: {\n type: \"object\",\n properties: {\n description: { type: \"string\", description: \"任务的简短描述(3-5 个词)\" },\n prompt: { type: \"string\", description: \"子 Agent 要执行的任务\" },\n subagent_type: {\n type: \"string\",\n description: \"专用 Agent 类型:claude、explore、plan、general-purpose、statusline-setup\",\n },\n model: {\n type: \"string\",\n enum: [\"sonnet\", \"opus\", \"haiku\"],\n description: \"可选:为此子 Agent 指定模型覆盖\",\n },\n isolation: {\n type: \"string\",\n enum: [\"worktree\"],\n description: \"在隔离的 git worktree 中运行(开销大——仅用于并行文件修改场景)\",\n },\n allowed_tools: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"限制子 Agent 可用的工具。留空则继承父级工具。\",\n },\n },\n required: [\"description\", \"prompt\"],\n },\n kind: \"ExecutesCode\",\n safety: \"RequiresApproval\",\n availability: { type: \"always\" },\n executor: \"core:agent\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { description, prompt, subagent_type, model, isolation, allowed_tools } =\n invocation.payload as {\n description: string;\n prompt: string;\n subagent_type?: string;\n model?: \"sonnet\" | \"opus\" | \"haiku\";\n isolation?: \"worktree\";\n allowed_tools?: string[];\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"子 Agent 已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n // This tool's actual implementation lives in @lynx/agent (spawnSubAgent).\n // The built-in handler here is a thin adapter — the real logic wire-up\n // happens in lynx-cli bootstrap where the handler is swapped.\n //\n // For Phase 2, we provide a working mock that returns acknowledgement.\n // Phase 3 replaces this with the real spawnSubAgent integration.\n\n const agentType = subagent_type ?? \"general-purpose\";\n const budgetNote = \"子 Agent 获得父级 token 预算的 1/4。\";\n\n return {\n success: true,\n content: [\n `子 Agent 已调度 [${agentType}]:${description}`,\n `模型:${model ?? \"inherit\"}`,\n `隔离模式:${isolation ?? \"none\"}`,\n `工具:${allowed_tools ? allowed_tools.join(\", \") : \"inherit\"}`,\n budgetNote,\n \"\",\n \"--- 子 Agent 输出 ---\",\n `[Phase 3 集成:此处将调用真实 spawnSubAgent()。任务:${prompt.slice(0, 200)}]`,\n ].join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * task — Background task CRUD operations.\n *\n * Tasks are managed by the agent engine's TaskManager and represent\n * long‑running operations (file watchers, MCP heartbeats, etc.).\n * This tool lets the model inspect and stop running tasks.\n *\n * The descriptor stays unchanged; the handler is injected with a real\n * TaskManager during bootstrap via {@link injectTaskManager}.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\n/**\n * TaskManager 的最小接口 — lynx-tools 不依赖 lynx-agent,\n * 实际实例在 bootstrap 时注入。\n */\nexport interface TaskManagerOps {\n start(id: string, label: string, run: (signal: AbortSignal) => Promise<void>): Promise<void>;\n stop(id: string): Promise<void>;\n get(id: string):\n | {\n id: string;\n label: string;\n status: string;\n startedAt: number;\n stoppedAt?: number;\n error?: string;\n output?: string;\n progress?: number;\n }\n | undefined;\n list(): Array<{ id: string; label: string; status: string }>;\n getOutput(id: string): string;\n update(id: string, patch: { label?: string; status?: string }): void;\n}\n\nexport const descriptor: ToolDescriptor = {\n name: \"task\",\n description:\n \"管理后台任务——创建、列表、获取、更新或停止任务。\" +\n \"任务持久化到 SQLite,会话重启后仍存在。\" +\n \"适用于跨多个会话的长时间运行操作。\",\n inputSchema: {\n type: \"object\",\n properties: {\n action: {\n type: \"string\",\n enum: [\"create\", \"list\", \"get\", \"update\", \"stop\"],\n description: \"CRUD 操作:创建新任务、列出所有任务、获取特定任务、更新状态或停止/取消\",\n },\n task_id: { type: \"string\", description: \"任务 UUID(get/update/stop 操作必需)\" },\n type: {\n type: \"string\",\n description: \"任务类型,例如 'mcp_connect'、'plugin_install'(create 时使用)\",\n },\n payload: { type: \"object\", description: \"任务负载/数据(create/update 时使用)\" },\n status: {\n type: \"string\",\n enum: [\"queued\", \"running\", \"completed\", \"failed\", \"canceled\"],\n description: \"新状态(update 时使用)\",\n },\n },\n required: [\"action\"],\n },\n kind: \"ExecutesCode\",\n safety: \"WorkspaceSafe\",\n availability: { type: \"always\" },\n executor: \"core:task\",\n owner: \"core\",\n};\n\n// ── Module‑level TaskManager injection ─────────────────\n\n/** Backing TaskManager — injected during bootstrap, null before injection. */\nlet taskManager: TaskManagerOps | null = null;\n\n/**\n * Inject the real TaskManager backend.\n *\n * Called during bootstrap after the engine is created.\n * Before injection, the handler returns mock results for test compatibility.\n */\nexport function injectTaskManager(tm: TaskManagerOps): void {\n taskManager = tm;\n}\n\n// ── Handler factory ────────────────────────────────────\n\n/**\n * Create a task handler bound to a specific {@link TaskManagerOps}.\n *\n * Factory alternative to {@link injectTaskManager} — useful when the\n * handler needs to be registered independently of the module‑level singleton.\n */\nexport function createTaskHandler(tm: TaskManagerOps): ToolHandler {\n return buildHandler(tm);\n}\n\n// ── Internal handler builder ───────────────────────────\n\nfunction buildHandler(tm: TaskManagerOps | null): ToolHandler {\n return {\n async handle(invocation, signal): Promise<ToolResult> {\n const { action, task_id, type, payload, status } = invocation.payload as {\n action: \"create\" | \"list\" | \"get\" | \"update\" | \"stop\";\n task_id?: string;\n type?: string;\n payload?: Record<string, unknown>;\n status?: string;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"任务操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n // Use real TaskManager if injected, otherwise mock fallback\n if (tm) {\n return realDispatch(tm, action, task_id, type, payload, status, startTime);\n }\n return mockDispatch(action, task_id, type, payload, status, startTime);\n },\n };\n}\n\n// ── Real dispatch ───────────────────────────────────────\n\nasync function realDispatch(\n tm: TaskManagerOps,\n action: string,\n taskId: string | undefined,\n taskType: string | undefined,\n taskPayload: Record<string, unknown> | undefined,\n taskStatus: string | undefined,\n startTime: number,\n): Promise<ToolResult> {\n switch (action) {\n case \"create\": {\n // Tasks are started by the agent engine internally. This tool\n // only inspects and stops tasks; 'create' is a no‑op that explains this.\n return {\n success: true,\n content:\n \"任务创建由 Agent 引擎内部管理,无需手动创建。使用 'list' 查看当前运行中的任务,\" +\n \"使用 'get' 获取特定任务详情,使用 'stop' 停止任务。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n case \"list\": {\n const tasks = tm.list();\n if (tasks.length === 0) {\n return {\n success: true,\n content: \"当前没有运行中的后台任务。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const lines = tasks.map((t) => `- **${t.id}**: ${t.label} (${t.status})`);\n return {\n success: true,\n content: `后台任务列表(共 ${tasks.length} 项):\\n\\n${lines.join(\"\\n\")}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n case \"get\": {\n if (!taskId) {\n return {\n success: false,\n content: \"缺少必需参数 task_id\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const entry = tm.get(taskId);\n if (!entry) {\n return {\n success: true,\n content: `任务 \"${taskId}\" 未找到。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const output = tm.getOutput(taskId);\n const parts: string[] = [\n `**ID**: ${entry.id}`,\n `**标签**: ${entry.label}`,\n `**状态**: ${entry.status}`,\n `**开始时间**: ${new Date(entry.startedAt).toISOString()}`,\n ];\n if (entry.stoppedAt) {\n parts.push(`**停止时间**: ${new Date(entry.stoppedAt).toISOString()}`);\n }\n if (entry.error) {\n parts.push(`**错误**: ${entry.error}`);\n }\n if (entry.progress !== undefined) {\n parts.push(`**进度**: ${entry.progress}%`);\n }\n if (output) {\n parts.push(`**输出**:\\n${output}`);\n }\n return {\n success: true,\n content: parts.join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n case \"update\": {\n if (!taskId) {\n return {\n success: false,\n content: \"缺少必需参数 task_id\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const entry = tm.get(taskId);\n if (!entry) {\n return {\n success: true,\n content: `任务 \"${taskId}\" 未找到。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const patch: { label?: string; status?: string } = {};\n if (taskPayload?.label && typeof taskPayload.label === \"string\") {\n patch.label = taskPayload.label;\n }\n if (taskStatus) {\n patch.status = taskStatus;\n }\n if (Object.keys(patch).length === 0) {\n return {\n success: false,\n content: \"未提供要更新的字段。请指定 label 或 status。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n tm.update(taskId, patch);\n return {\n success: true,\n content: `任务 \"${taskId}\" 已更新:${JSON.stringify(patch)}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n case \"stop\": {\n if (!taskId) {\n return {\n success: false,\n content: \"缺少必需参数 task_id\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const entry = tm.get(taskId);\n if (!entry) {\n return {\n success: true,\n content: `任务 \"${taskId}\" 未找到。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n await tm.stop(taskId);\n return {\n success: true,\n content: `任务 \"${taskId}\"(${entry.label})已停止。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n default:\n return {\n success: false,\n content: `未知操作:${action}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n}\n\n// ── Mock dispatch (pre‑injection fallback) ──────────────\n\nfunction mockDispatch(\n action: string,\n taskId: string | undefined,\n taskType: string | undefined,\n taskPayload: Record<string, unknown> | undefined,\n taskStatus: string | undefined,\n startTime: number,\n): ToolResult {\n switch (action) {\n case \"create\":\n return {\n success: true,\n content: `任务已创建 [mock]:${taskType ?? \"generic\"} — Phase 4 TaskManager 接入后支持持久化。负载:${JSON.stringify(taskPayload ?? {})}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n case \"list\":\n return {\n success: true,\n content: \"任务列表 [mock]:暂无持久化任务。Phase 4 集成待完成。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n case \"get\":\n return {\n success: true,\n content: `任务 ${taskId} [mock]:未找到或 Phase 4 集成待完成。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n case \"update\":\n return {\n success: true,\n content: `任务 ${taskId} 已更新为 ${taskStatus ?? \"unknown\"} [mock]。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n case \"stop\":\n return {\n success: true,\n content: `任务 ${taskId} 已停止 [mock]。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n default:\n return {\n success: false,\n content: `未知操作:${action}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n}\n\n/** Exported handler — uses injectTaskManager() when wired, mock otherwise. */\nexport const handler: ToolHandler = buildHandler(null);\n","/**\n * team_create — Create a multi-agent collaboration team.\n *\n * Each member has a role, tool set, and model preference.\n * Default strategy: \"consensus\" (all members must agree on decisions).\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"team_create\",\n description:\n \"创建多 Agent 协作团队。每个成员拥有独立的角色、工具集和模型。\" +\n \"团队通过可配置的策略协作完成工作(默认:共识模式)。\",\n inputSchema: {\n type: \"object\",\n properties: {\n name: { type: \"string\", description: \"团队名称(会话内必须唯一)\" },\n members: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n name: { type: \"string\", description: \"成员显示名称\" },\n role: {\n type: \"string\",\n description: \"角色描述(例如 '安全审查员'、'代码架构师')\",\n },\n tools: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"该成员可用的工具(留空 = 全部工具)\",\n },\n model: { type: \"string\", description: \"该成员的模型覆盖\" },\n },\n required: [\"name\", \"role\"],\n },\n description: \"团队成员及其角色和能力\",\n },\n strategy: {\n type: \"string\",\n enum: [\"consensus\", \"majority\", \"delegated\"],\n description: \"决策策略:consensus(全员同意)、majority(投票)、delegated(领导者决策)\",\n },\n },\n required: [\"name\", \"members\"],\n },\n kind: \"ExecutesCode\",\n safety: \"RequiresApproval\",\n availability: { type: \"always\" },\n executor: \"core:team_create\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { name, members, strategy } = invocation.payload as {\n name: string;\n members: Array<{ name: string; role: string; tools?: string[]; model?: string }>;\n strategy?: \"consensus\" | \"majority\" | \"delegated\";\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"团队创建已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const strat = strategy ?? \"consensus\";\n const memberList = members\n .map((m) => ` - ${m.name} (${m.role})${m.model ? ` [${m.model}]` : \"\"}`)\n .join(\"\\n\");\n\n return {\n success: true,\n content: [\n `团队已创建:${name}`,\n `策略:${strat}`,\n `成员(${members.length} 人):`,\n memberList,\n \"\",\n \"[Phase 4 集成:通过 @lynx/agent 子 Agent 通道实现真实团队编排]\",\n ].join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * team_delete — Delete a multi-agent collaboration team.\n *\n * Cascades: terminates all in-flight member tasks before deletion.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"team_delete\",\n description: \"删除多 Agent 协作团队。\" + \"移除团队前会终止所有正在执行的成员任务。\",\n inputSchema: {\n type: \"object\",\n properties: {\n team_id: { type: \"string\", description: \"团队标识(名称或 UUID)\" },\n },\n required: [\"team_id\"],\n },\n kind: \"ExecutesCode\",\n safety: \"RequiresApproval\",\n availability: { type: \"all\", exprs: [{ type: \"always\" }] },\n executor: \"core:team_delete\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { team_id } = invocation.payload as { team_id: string };\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"团队删除已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n return {\n success: true,\n content: [\n `团队已删除:${team_id}`,\n \"所有成员任务已终止。\",\n \"[Phase 4 集成:通过 @lynx/agent 实现真实团队生命周期管理]\",\n ].join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * verify_plan_execution — Verify that a plan was executed completely.\n *\n * Checks each checkpoint's expected output against actual output.\n * Returns: { passed, failed, missing } counts + per-checkpoint details.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"verify_plan_execution\",\n description:\n \"验证计划执行是否匹配其规范。\" +\n \"逐一检查每个检查点的预期输出与实际输出是否一致。\" +\n \"在实施计划后使用此工具,确保无遗漏。\",\n inputSchema: {\n type: \"object\",\n properties: {\n plan_id: { type: \"string\", description: \"要验证的计划标识\" },\n checkpoints: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n description: { type: \"string\", description: \"该检查点的预期描述\" },\n expected: { type: \"string\", description: \"预期输出或状态\" },\n actual: { type: \"string\", description: \"实际观察到的输出或状态\" },\n },\n required: [\"description\", \"expected\", \"actual\"],\n },\n description: \"待验证的检查点列表\",\n },\n },\n required: [\"plan_id\", \"checkpoints\"],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:verify_plan_execution\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { plan_id, checkpoints } = invocation.payload as {\n plan_id: string;\n checkpoints: Array<{ description: string; expected: string; actual: string }>;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"验证已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const results = checkpoints.map((cp) => {\n // Simple string comparison (Phase 4: add semantic comparison via LLM)\n const passed = cp.expected.trim() === cp.actual.trim();\n return { ...cp, passed };\n });\n\n const passed = results.filter((r) => r.passed).length;\n const failed = results.filter((r) => !r.passed).length;\n const total = results.length;\n\n const lines = [\n `计划验证:${plan_id}`,\n `结果:${passed}/${total} 通过,${failed} 失败`,\n \"\",\n ...results.map((r) => {\n const icon = r.passed ? \"✓\" : \"✗\";\n return `${icon} ${r.description}\\n 预期:${r.expected.slice(0, 100)}\\n 实际:${r.actual.slice(0, 100)}`;\n }),\n ];\n\n return {\n success: true,\n content: lines.join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * remote_trigger — Trigger a remote task via HTTP callback.\n *\n * Sends an HTTP request to a remote URL and returns the response.\n * 30s timeout. Supports GET and POST methods.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"remote_trigger\",\n description:\n \"通过发送 HTTP 请求(webhook / CI 回调)触发远程任务。\" +\n \"支持 GET 和 POST 方法,可自定义请求头和请求体。默认超时 30 秒。\",\n inputSchema: {\n type: \"object\",\n properties: {\n url: { type: \"string\", format: \"uri\", description: \"要触发的远程 URL\" },\n method: {\n type: \"string\",\n enum: [\"GET\", \"POST\"],\n description: \"HTTP 方法(默认:POST)\",\n },\n headers: {\n type: \"object\",\n description: \"自定义 HTTP 请求头(例如 Authorization、Content-Type)\",\n },\n body: { type: \"string\", description: \"请求体(POST 时使用)\" },\n timeout: {\n type: \"integer\",\n description: \"请求超时时间,毫秒(默认:30000,最大:60000)\",\n },\n },\n required: [\"url\"],\n },\n kind: \"Network\",\n safety: \"RequiresApproval\",\n availability: { type: \"always\" },\n executor: \"core:remote_trigger\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { url, method, headers, body, timeout } = invocation.payload as {\n url: string;\n method?: \"GET\" | \"POST\";\n headers?: Record<string, string>;\n body?: string;\n timeout?: number;\n };\n\n const startTime = Date.now();\n const httpMethod = method ?? \"POST\";\n const timeoutMs = Math.min(timeout ?? 30_000, 60_000);\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"远程触发已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n signal.addEventListener(\n \"abort\",\n () => {\n clearTimeout(timeoutId);\n controller.abort();\n },\n { once: true },\n );\n\n const resp = await fetch(url, {\n method: httpMethod,\n headers: {\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"Lynx/1.0\",\n ...headers,\n },\n body: httpMethod === \"POST\" ? (body ?? undefined) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n const respBody = await resp.text().catch(() => \"(二进制响应)\");\n const truncated = respBody.length > 2000;\n const summary = truncated ? respBody.slice(0, 1997) + \"...\" : respBody;\n\n return {\n success: resp.ok,\n content: `HTTP ${resp.status} ${resp.statusText}\\n\\n${summary}`,\n metadata: { durationMs: Date.now() - startTime, truncated },\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if ((err as { name?: string }).name === \"AbortError\" || message.includes(\"abort\")) {\n return {\n success: false,\n content: signal.aborted ? \"操作已取消\" : `请求在 ${timeoutMs}ms 后超时`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n return {\n success: false,\n content: `远程触发失败:${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n },\n};\n","/**\n * ScheduleCronTool — 定时任务调度工具。\n *\n * 使用 cron 语法安排定时任务。支持一次性提醒和循环计划。\n * 任务持久化到 ~/.lynx/cron-jobs.json,进程重启后自动恢复。\n */\nimport { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { randomUUID } from \"node:crypto\";\nimport { homedir } from \"node:os\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\n// ── Types ─────────────────────────────────────────────\n\n/** cron 任务记录。 */\ninterface CronJob {\n id: string;\n cron: string;\n prompt: string;\n timer?: ReturnType<typeof setInterval> | ReturnType<typeof setTimeout>;\n nextFire: number;\n}\n\n// ── State ─────────────────────────────────────────────\n\nconst STORAGE_DIR = join(homedir(), \".lynx\");\nconst STORAGE_FILE = join(STORAGE_DIR, \"cron-jobs.json\");\n\n/** 活跃的 cron 任务映射,key 为 job UUID。 */\nconst jobs = new Map<string, CronJob>();\n\n/** 初始化:加载持久化任务并启动调度。 */\nfunction init(): void {\n try {\n const raw = readFileSync(STORAGE_FILE, \"utf-8\");\n const persisted: Array<{ id: string; cron: string; prompt: string }> = JSON.parse(raw);\n for (const j of persisted) {\n scheduleJob(j.id, j.cron, j.prompt);\n }\n } catch {\n // 文件不存在或损坏,从空开始\n }\n}\n\n/** 持久化所有任务到磁盘。 */\nfunction persist(): void {\n mkdirSync(STORAGE_DIR, { recursive: true });\n const arr: Array<{ id: string; cron: string; prompt: string }> = [];\n for (const job of jobs.values()) {\n arr.push({ id: job.id, cron: job.cron, prompt: job.prompt });\n }\n writeFileSync(STORAGE_FILE, JSON.stringify(arr, null, 2));\n}\n\n/** 根据 cron 表达式计算下次触发时间(简化实现)。 */\nfunction calcNextFire(cron: string): number {\n const now = new Date();\n\n // 支持 @ 别名\n if (cron === \"@hourly\") return now.getTime() + 3600_000;\n if (cron === \"@daily\") return now.getTime() + 86400_000;\n if (cron === \"@weekly\") return now.getTime() + 604800_000;\n\n const parts = cron.split(/\\s+/);\n if (parts.length !== 5) return now.getTime() + 60000; // 默认 1 分钟后\n\n const minute = parseField(parts[0], 0, 59);\n const hour = parseField(parts[1], 0, 23);\n\n if (minute !== null && hour !== null) {\n const next = new Date(now);\n next.setMinutes(next.getMinutes() + 1);\n next.setSeconds(0);\n next.setMilliseconds(0);\n return next.getTime();\n }\n\n return now.getTime() + 60000;\n}\n\n/** 解析 cron 字段值,支持 * 和步进语法。 */\nfunction parseField(field: string, _min: number, _max: number): number | null {\n if (field === \"*\") return 0;\n const step = field.match(/^\\*\\/(\\d+)$/);\n if (step) return parseInt(step[1], 10);\n const num = parseInt(field, 10);\n if (!isNaN(num)) return num;\n return null;\n}\n\n/** 调度一个 cron 任务。 */\nfunction scheduleJob(id: string, cron: string, prompt: string): CronJob {\n const nextFire = calcNextFire(cron);\n const delay = Math.max(0, nextFire - Date.now());\n\n const job: CronJob = { id, cron, prompt, nextFire };\n\n // 判断是否循环任务\n if (cron.includes(\"*\") || cron.startsWith(\"@\")) {\n // 循环任务:每 60 秒检查一次\n job.timer = setInterval(() => {\n const now = Date.now();\n if (now >= job.nextFire) {\n job.nextFire = calcNextFire(cron);\n }\n }, 60000);\n } else {\n // 一次性任务\n job.timer = setTimeout(() => {\n jobs.delete(id);\n persist();\n }, delay);\n }\n\n jobs.set(id, job);\n return job;\n}\n\n/** 验证 cron 表达式格式。 */\nfunction isValidCron(cron: string): boolean {\n if (cron.startsWith(\"@\") && [\"@hourly\", \"@daily\", \"@weekly\"].includes(cron)) {\n return true;\n }\n const parts = cron.trim().split(/\\s+/);\n if (parts.length !== 5) return false;\n return parts.every((p) => {\n if (p === \"*\") return true;\n if (/^\\*\\/\\d+$/.test(p)) return true;\n const n = parseInt(p, 10);\n return !isNaN(n);\n });\n}\n\n// ── 启动时加载 ───────────────────────────────────────\ninit();\n\n// ── Descriptor ────────────────────────────────────────\n\nexport const descriptor: ToolDescriptor = {\n name: \"ScheduleCronTool\",\n description:\n \"使用 cron 语法安排定时任务。任务在指定时间或间隔触发。\" +\n \"支持一次性提醒和循环计划。标准 cron 格式:分 时 日 月 周。\" +\n \"也支持 @hourly、@daily、@weekly 别名。\",\n inputSchema: {\n type: \"object\",\n properties: {\n action: {\n type: \"string\",\n enum: [\"create\", \"list\", \"delete\"],\n description: \"操作类型:创建任务、列出任务、删除任务\",\n },\n cron: {\n type: \"string\",\n description: \"5 字段 cron 表达式(如 '*/5 * * * *')或别名 @hourly/@daily/@weekly\",\n },\n prompt: {\n type: \"string\",\n description: \"任务触发时入队的提示文本\",\n },\n jobId: {\n type: \"string\",\n description: \"任务 ID(delete 操作时使用)\",\n },\n },\n required: [\"action\"],\n },\n kind: \"ExecutesCode\",\n safety: \"WorkspaceSafe\",\n availability: { type: \"always\" },\n executor: \"core:schedule_cron\",\n owner: \"core\",\n};\n\n// ── Handler ───────────────────────────────────────────\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { action, cron, prompt, jobId } = invocation.payload as {\n action: string;\n cron?: string;\n prompt?: string;\n jobId?: string;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"定时任务操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n switch (action) {\n case \"create\":\n return handleCreate(cron, prompt);\n case \"list\":\n return handleList();\n case \"delete\":\n return handleDelete(jobId);\n default:\n return {\n success: false,\n content: `未知操作:${action}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `定时任务操作失败:${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n },\n};\n\n// ── Action handlers ───────────────────────────────────\n\n/** 创建新的 cron 任务。 */\nfunction handleCreate(cron?: string, prompt?: string): ToolResult {\n if (!cron || !prompt) {\n return {\n success: false,\n content: \"缺少必要参数:cron 和 prompt 均为必填\",\n };\n }\n\n if (!isValidCron(cron)) {\n return {\n success: false,\n content: `无效的 cron 表达式:${cron}。格式:分 时 日 月 周(5 字段),或 @hourly/@daily/@weekly`,\n };\n }\n\n const id = randomUUID();\n const job = scheduleJob(id, cron, prompt);\n persist();\n\n const nextDate = new Date(job.nextFire).toISOString();\n return {\n success: true,\n content: `定时任务已创建。ID:${id}\\n计划:${cron}\\n下次触发:${nextDate}`,\n };\n}\n\n/** 列出所有活跃任务。 */\nfunction handleList(): ToolResult {\n if (jobs.size === 0) {\n return { success: true, content: \"当前无定时任务\" };\n }\n\n const lines: string[] = [];\n for (const job of jobs.values()) {\n const nextDate = new Date(job.nextFire).toISOString();\n lines.push(`${job.id} — ${job.cron} — 下次:${nextDate} — \"${job.prompt.slice(0, 40)}\"`);\n }\n\n return {\n success: true,\n content: `定时任务(${jobs.size}):\\n${lines.join(\"\\n\")}`,\n };\n}\n\n/** 删除指定任务。 */\nfunction handleDelete(jobId?: string): ToolResult {\n if (!jobId) {\n return { success: false, content: \"缺少 jobId 参数\" };\n }\n\n const job = jobs.get(jobId);\n if (!job) {\n return { success: false, content: `未找到任务:${jobId}` };\n }\n\n if (job.timer) {\n clearTimeout(job.timer);\n clearInterval(job.timer);\n }\n jobs.delete(jobId);\n persist();\n\n return { success: true, content: `任务 ${jobId} 已删除` };\n}\n","/**\n * WorkflowTool — 多步骤工作流定义和执行工具。\n *\n * 支持定义、运行、查看状态和列出工作流。\n * 工作流持久化到 ~/.lynx/workflows.json,进程重启后保留定义。\n */\nimport { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { randomUUID } from \"node:crypto\";\nimport { homedir } from \"node:os\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\n// ── Types ─────────────────────────────────────────────\n\n/** 工作流步骤定义。 */\ninterface WorkflowStep {\n name: string;\n toolName: string;\n args: Record<string, unknown>;\n}\n\n/** 工作流定义。 */\ninterface Workflow {\n id: string;\n name: string;\n steps: WorkflowStep[];\n createdAt: number;\n}\n\n// ── State ─────────────────────────────────────────────\n\nconst STORAGE_DIR = join(homedir(), \".lynx\");\nconst STORAGE_FILE = join(STORAGE_DIR, \"workflows.json\");\n\n/** 活跃的工作流映射,key 为 workflow UUID。 */\nconst workflows = new Map<string, Workflow>();\n\n/** 初始化:从磁盘加载持久化工作流。 */\nfunction init(): void {\n try {\n const raw = readFileSync(STORAGE_FILE, \"utf-8\");\n const persisted: Workflow[] = JSON.parse(raw);\n for (const w of persisted) {\n workflows.set(w.id, w);\n }\n } catch {\n // 文件不存在或损坏,从空开始\n }\n}\n\n/** 持久化所有工作流到磁盘。 */\nfunction persist(): void {\n mkdirSync(STORAGE_DIR, { recursive: true });\n writeFileSync(STORAGE_FILE, JSON.stringify(Array.from(workflows.values()), null, 2));\n}\n\n// ── 启动时加载 ───────────────────────────────────────\ninit();\n\n// ── Descriptor ────────────────────────────────────────\n\nexport const descriptor: ToolDescriptor = {\n name: \"WorkflowTool\",\n description:\n \"定义并执行多步骤工作流。每个步骤可以是一个工具调用,\" +\n \"步骤之间可以有依赖关系。支持 define(定义)、run(运行)、\" +\n \"status(查看状态)、list(列出所有)四种操作。\",\n inputSchema: {\n type: \"object\",\n properties: {\n action: {\n type: \"string\",\n enum: [\"define\", \"run\", \"status\", \"list\"],\n description: \"操作类型:定义工作流、运行工作流、查看状态、列出所有工作流\",\n },\n workflowId: {\n type: \"string\",\n description: \"工作流 ID(run/status 操作时使用)\",\n },\n name: {\n type: \"string\",\n description: \"工作流名称(define 操作时使用)\",\n },\n steps: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n name: { type: \"string\", description: \"步骤名称\" },\n toolName: { type: \"string\", description: \"要调用的工具名称\" },\n args: { type: \"object\", description: \"工具参数\" },\n },\n required: [\"name\", \"toolName\", \"args\"],\n },\n description: \"工作流步骤列表(define 操作时使用)\",\n },\n },\n required: [\"action\"],\n },\n kind: \"ExecutesCode\",\n safety: \"WorkspaceSafe\",\n availability: { type: \"always\" },\n executor: \"core:workflow\",\n owner: \"core\",\n};\n\n// ── Handler ───────────────────────────────────────────\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { action, workflowId, name, steps } = invocation.payload as {\n action: string;\n workflowId?: string;\n name?: string;\n steps?: WorkflowStep[];\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"工作流操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n switch (action) {\n case \"define\":\n return handleDefine(name, steps);\n case \"run\":\n return handleRun(workflowId);\n case \"status\":\n return handleStatus(workflowId);\n case \"list\":\n return handleList();\n default:\n return {\n success: false,\n content: `未知操作:${action}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `工作流操作失败:${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n },\n};\n\n// ── Action handlers ───────────────────────────────────\n\n/** 定义新工作流。 */\nfunction handleDefine(name?: string, steps?: WorkflowStep[]): ToolResult {\n if (!name || !steps || steps.length === 0) {\n return {\n success: false,\n content: \"缺少必要参数:name 和 steps 均为必填,且 steps 不能为空\",\n };\n }\n\n const id = randomUUID();\n const workflow: Workflow = { id, name, steps, createdAt: Date.now() };\n workflows.set(id, workflow);\n persist();\n\n const stepList = steps.map((s, i) => ` ${i + 1}. ${s.name} — 调用 ${s.toolName}`).join(\"\\n\");\n\n return {\n success: true,\n content: `工作流已定义。ID:${id}\\n名称:${name}\\n步骤:\\n${stepList}`,\n };\n}\n\n/** 运行工作流:返回步骤列表供 agent 按顺序执行。 */\nfunction handleRun(workflowId?: string): ToolResult {\n if (!workflowId) {\n return { success: false, content: \"缺少 workflowId 参数\" };\n }\n\n const workflow = workflows.get(workflowId);\n if (!workflow) {\n return { success: false, content: `未找到工作流:${workflowId}` };\n }\n\n const stepInstructions = workflow.steps\n .map((s, i) => {\n const argsStr = JSON.stringify(s.args);\n return `${i + 1}. **${s.name}** — 调用工具 \\`${s.toolName}\\`,参数:\\`${argsStr}\\``;\n })\n .join(\"\\n\");\n\n return {\n success: true,\n content: [\n `开始运行工作流:${workflow.name}(ID: ${workflow.id})`,\n \"\",\n \"按以下步骤依次执行:\",\n stepInstructions,\n \"\",\n \"请按顺序执行每个步骤,等待每步完成后再进行下一步。\",\n ].join(\"\\n\"),\n };\n}\n\n/** 查看工作流状态。 */\nfunction handleStatus(workflowId?: string): ToolResult {\n if (!workflowId) {\n return { success: false, content: \"缺少 workflowId 参数\" };\n }\n\n const workflow = workflows.get(workflowId);\n if (!workflow) {\n return { success: false, content: `未找到工作流:${workflowId}` };\n }\n\n const createdDate = new Date(workflow.createdAt).toISOString();\n const stepSummary = workflow.steps\n .map((s, i) => `${i + 1}. ${s.name}(工具:${s.toolName})`)\n .join(\"\\n\");\n\n return {\n success: true,\n content: [\n `工作流:${workflow.name}(ID: ${workflow.id})`,\n `创建时间:${createdDate}`,\n `步骤(${workflow.steps.length}):`,\n stepSummary,\n ].join(\"\\n\"),\n };\n}\n\n/** 列出所有工作流。 */\nfunction handleList(): ToolResult {\n if (workflows.size === 0) {\n return { success: true, content: \"暂无定义的工作流\" };\n }\n\n const lines: string[] = [];\n for (const w of workflows.values()) {\n const date = new Date(w.createdAt).toISOString().slice(0, 10);\n lines.push(`${w.id} — ${w.name}(${w.steps.length} 步骤,创建于 ${date})`);\n }\n\n return {\n success: true,\n content: `工作流(${workflows.size}):\\n${lines.join(\"\\n\")}`,\n };\n}\n","/**\n * TungstenTool — 重型并行 Agent 编排工具。\n *\n * \"Tungsten\" = 钨,象征高强度并行。\n * 将复杂任务拆解为子任务,生成并行执行计划和综合方案。\n * 实际并行执行由 agent 引擎的子 Agent 基础设施处理,\n * 本工具提供任务拆解和调度逻辑。\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\n// ── Types ─────────────────────────────────────────────\n\n/** 子任务分配。 */\ninterface SubtaskAssignment {\n id: number;\n name: string;\n description: string;\n suggestedAgentRole: string;\n}\n\n// ── Descriptor ────────────────────────────────────────\n\nexport const descriptor: ToolDescriptor = {\n name: \"TungstenTool\",\n description:\n \"重型复合工具:并行调度多个子 Agent 处理复杂任务的各个部分,然后综合结果。\" +\n \"支持 parallel(并行)、pipeline(流水线)、debate(辩论)三种策略。\" +\n \"适用于代码审查、多模块重构、全面调研等大规模任务。\",\n inputSchema: {\n type: \"object\",\n properties: {\n task: {\n type: \"string\",\n description: \"要执行的复杂任务描述\",\n },\n maxAgents: {\n type: \"number\",\n description: \"最大并行 Agent 数量(默认 3)\",\n },\n strategy: {\n type: \"string\",\n enum: [\"parallel\", \"pipeline\", \"debate\"],\n description: \"执行策略:parallel 并行执行、pipeline 流水线处理、debate 多角度辩论\",\n },\n },\n required: [\"task\"],\n },\n kind: \"ExecutesCode\",\n safety: \"WorkspaceSafe\",\n availability: { type: \"always\" },\n executor: \"core:tungsten\",\n owner: \"core\",\n};\n\n// ── Handler ───────────────────────────────────────────\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { task, maxAgents, strategy } = invocation.payload as {\n task: string;\n maxAgents?: number;\n strategy?: string;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"Tungsten 操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (!task || task.trim().length === 0) {\n return {\n success: false,\n content: \"缺少必要参数:task 为必填且不能为空\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n const agentCount = Math.min(Math.max(maxAgents ?? 3, 1), 10);\n const execStrategy = strategy ?? \"parallel\";\n\n // 拆解任务为子任务\n const subtasks = decomposeTask(task, agentCount);\n\n // 根据策略生成执行计划\n const plan = buildExecutionPlan(task, subtasks, agentCount, execStrategy);\n\n return {\n success: true,\n content: plan,\n metadata: { durationMs: Date.now() - startTime },\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `Tungsten 任务规划失败:${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n },\n};\n\n// ── Task decomposition ────────────────────────────────\n\n/**\n * 将任务拆解为子任务。\n *\n * 按语义标记(编号列表、段落、主题关键词)进行简单拆分。\n * 真实场景中可接入 LLM 辅助拆解以获得更精准的结果。\n */\nfunction decomposeTask(task: string, maxAgents: number): SubtaskAssignment[] {\n // 尝试按编号列表拆分:1. / 2. / - / *\n const numberedPattern = /(?:^|\\n)\\s*(?:\\d+[.)]\\s*|[-*]\\s+)(.+)/g;\n const matches: string[] = [];\n let match;\n while ((match = numberedPattern.exec(task)) !== null) {\n matches.push(match[1].trim());\n }\n\n if (matches.length >= 2) {\n // 有编号列表,直接作为子任务\n const count = Math.min(matches.length, maxAgents);\n return matches.slice(0, count).map((m, i) => ({\n id: i + 1,\n name: m.slice(0, 40),\n description: m,\n suggestedAgentRole: `${i + 1} 号子 Agent`,\n }));\n }\n\n // 按段落拆分\n const paragraphs = task\n .split(/\\n\\s*\\n/)\n .map((p) => p.trim())\n .filter((p) => p.length > 0);\n\n if (paragraphs.length >= 2) {\n const count = Math.min(paragraphs.length, maxAgents);\n const names = paragraphs.slice(0, count).map((p) => p.slice(0, 50));\n return names.map((n, i) => ({\n id: i + 1,\n name: n,\n description: paragraphs[i],\n suggestedAgentRole: `子 Agent ${i + 1}`,\n }));\n }\n\n // 按句子粗略拆分\n const sentences = task.split(/[..。!!??]+/).filter((s) => s.trim().length > 10);\n if (sentences.length >= 2) {\n const count = Math.min(sentences.length, maxAgents);\n return sentences.slice(0, count).map((s, i) => ({\n id: i + 1,\n name: s.trim().slice(0, 40),\n description: s.trim(),\n suggestedAgentRole: `子 Agent ${i + 1}`,\n }));\n }\n\n // 回退:单一子任务\n return [\n {\n id: 1,\n name: task.slice(0, 40),\n description: task,\n suggestedAgentRole: \"主执行 Agent\",\n },\n ];\n}\n\n// ── Plan generation ──────────────────────────────────\n\n/** 根据策略生成执行计划文本。 */\nfunction buildExecutionPlan(\n task: string,\n subtasks: SubtaskAssignment[],\n maxAgents: number,\n strategy: string,\n): string {\n const planLines: string[] = [\n \"═══════════════════════════════════════\",\n \" Tungsten 并行执行计划\",\n \"═══════════════════════════════════════\",\n \"\",\n `总任务:${task.slice(0, 120)}${task.length > 120 ? \"...\" : \"\"}`,\n `执行策略:${strategyLabel(strategy)}`,\n `并行 Agent 数:${maxAgents}`,\n `子任务数:${subtasks.length}`,\n \"\",\n \"── 子任务分配 ──\",\n \"\",\n ];\n\n for (const st of subtasks) {\n planLines.push(`[${st.id}] ${st.name}`);\n planLines.push(` 角色:${st.suggestedAgentRole}`);\n planLines.push(` 描述:${st.description.slice(0, 100)}`);\n planLines.push(\"\");\n }\n\n planLines.push(\"── 执行指令 ──\");\n planLines.push(\"\");\n\n switch (strategy) {\n case \"parallel\":\n planLines.push(\n \"所有子 Agent 同时并行执行各自的子任务。\",\n `请为每个子任务创建独立的 Agent,共 ${subtasks.length} 个,同时启动。`,\n \"完成后,由协调 Agent 综合所有结果形成最终输出。\",\n );\n break;\n case \"pipeline\":\n planLines.push(\n \"子任务按顺序流水线执行,每个子 Agent 的输出作为下一个的输入。\",\n `请依次启动 ${subtasks.length} 个 Agent,每个等待前一个完成后再开始。`,\n \"流水线末端的 Agent 产出最终结果。\",\n );\n break;\n case \"debate\":\n planLines.push(\n `每个子 Agent 从不同角度处理任务,共 ${subtasks.length} 个视角。`,\n \"各 Agent 独立产出观点/方案后,由协调 Agent 对比、批判、综合。\",\n \"最终输出应包括不同观点的对比分析和综合结论。\",\n );\n break;\n }\n\n planLines.push(\"\");\n planLines.push(\"── 综合指令 ──\");\n planLines.push(\"所有子任务完成后,将结果合并为统一的最终输出。\");\n planLines.push(\"═══════════════════════════════════════\");\n\n return planLines.join(\"\\n\");\n}\n\n/** 策略的中文标签。 */\nfunction strategyLabel(strategy: string): string {\n switch (strategy) {\n case \"parallel\":\n return \"并行\";\n case \"pipeline\":\n return \"流水线\";\n case \"debate\":\n return \"辩论\";\n default:\n return strategy;\n }\n}\n","/**\n * enter_plan_mode — Enter plan mode (read-only, design output only).\n *\n * In plan mode, all write tools are automatically denied by the permission pipeline\n * (Step 6: plan mode + write tool → deny). The agent can only read files and output\n * design documents.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"enter_plan_mode\",\n description:\n \"进入计划模式 — 切换为只读模式,Agent 只能读取文件和输出设计方案。\" +\n \"所有写入/编辑/执行工具将自动被拒绝。\" +\n \"在进行重大架构变更前使用此模式,以便在实施前获得用户对方案的认可。\",\n inputSchema: {\n type: \"object\",\n properties: {},\n required: [],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:enter_plan_mode\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(_invocation, signal): Promise<ToolResult> {\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"Operation cancelled\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n // The actual mode switch is handled by the permission pipeline (Step 6)\n // and the session state in lynx-agent. This tool is the trigger.\n return {\n success: true,\n content: [\n \"已进入计划模式。\",\n \"- 所有写入/编辑/执行工具当前已被拒绝。\",\n \"- 您可执行:读取文件、搜索代码、设计架构、编写计划。\",\n \"- 使用 exit_plan_mode 返回普通模式。\",\n ].join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * exit_plan_mode — Exit plan mode and return to the normal permission mode.\n *\n * Restores the previous PermissionMode. If the plan wasn't completed,\n * warns the user and asks for confirmation.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"exit_plan_mode\",\n description:\n \"退出计划模式,返回普通模式(写入工具重新启用)。\" + \"计划方案将在执行前展示给用户审批。\",\n inputSchema: {\n type: \"object\",\n properties: {},\n required: [],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:exit_plan_mode\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(_invocation, signal): Promise<ToolResult> {\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"Operation cancelled\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n return {\n success: true,\n content: [\n \"已退出计划模式。\",\n \"- 写入/编辑/执行工具已重新启用。\",\n \"- 计划方案已就绪,等待用户审批并执行。\",\n ].join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * enter_worktree — Create or enter a git worktree for isolated work.\n *\n * Worktrees are created under .claude/worktrees/. Each worktree has its own\n * branch and working directory. The agent's CWD is switched to the worktree.\n *\n * `name` and `path` are mutually exclusive:\n * - `name`: create a new worktree (auto-named if omitted)\n * - `path`: enter an existing worktree\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"enter_worktree\",\n description:\n \"创建新的 git worktree 或进入已有 worktree 进行隔离工作。\" +\n \"Worktree 存放在 .claude/worktrees/ 目录下。使用 name 参数创建新 worktree,使用 path 参数进入已有 worktree。\",\n inputSchema: {\n type: \"object\",\n properties: {\n name: {\n type: \"string\",\n description: \"新 worktree 的名称(与 path 互斥)。不填则自动生成随机名称。\",\n },\n path: {\n type: \"string\",\n description: \"要进入的已有 worktree 的路径(与 name 互斥)。\",\n },\n base_ref: {\n type: \"string\",\n description: \"分支的基准引用(默认:'fresh' 模式基于 origin/master,'head' 模式基于 HEAD)\",\n },\n },\n required: [],\n },\n kind: \"ExecutesCode\",\n safety: \"WorkspaceSafe\",\n availability: { type: \"all\", exprs: [{ type: \"always\" }] },\n executor: \"core:enter_worktree\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { name, path, base_ref } = invocation.payload as {\n name?: string;\n path?: string;\n base_ref?: string;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"Worktree 操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (name && path) {\n return {\n success: false,\n content: \"name 与 path 互斥。使用 name 创建新 worktree,或使用 path 进入已有 worktree。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (path) {\n return {\n success: true,\n content: `已进入已有 worktree:${path}\\n[Phase 4: 通过 @lynx/agent 实现真正的 git worktree 切换]`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const worktreeName = name ?? `worktree-${Date.now().toString(36)}`;\n const ref = base_ref ?? \"fresh\";\n\n return {\n success: true,\n content: [\n `Worktree 已创建:${worktreeName}`,\n `基准引用:${ref}`,\n `位置:.claude/worktrees/${worktreeName}`,\n \"\",\n \"[Phase 4: 通过 @lynx/agent 实现真正的 git worktree 创建 + 工作目录切换]\",\n ].join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * exit_worktree — Exit a worktree and return to the original working directory.\n *\n * Supports two actions:\n * - \"keep\": leave the worktree directory and branch intact\n * - \"remove\": delete the worktree directory and its branch\n *\n * For \"remove\", uncommitted changes require discard_changes: true.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"exit_worktree\",\n description:\n \"退出 git worktree 并返回原始目录。\" +\n \"使用 'keep' 保留 worktree,或使用 'remove' 删除(如有未提交变更需搭配 discard_changes)。\",\n inputSchema: {\n type: \"object\",\n properties: {\n action: {\n type: \"string\",\n enum: [\"keep\", \"remove\"],\n description: \"keep = 保留 worktree 不动,remove = 删除 worktree 及分支\",\n },\n discard_changes: {\n type: \"boolean\",\n description: \"当 action=remove 且 worktree 有未提交变更时必须设为 true\",\n },\n },\n required: [\"action\"],\n },\n kind: \"ExecutesCode\",\n safety: \"WorkspaceSafe\",\n availability: { type: \"all\", exprs: [{ type: \"always\" }] },\n executor: \"core:exit_worktree\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { action, discard_changes } = invocation.payload as {\n action: \"keep\" | \"remove\";\n discard_changes?: boolean;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"Worktree 操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (action === \"keep\") {\n return {\n success: true,\n content:\n \"已退出 worktree(保留在磁盘上)。已返回原始目录。\\n[Phase 4: 通过 @lynx/agent 实现真正的 worktree 退出]\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (action === \"remove\" && !discard_changes) {\n return {\n success: false,\n content:\n \"Worktree 可能有未提交的变更。设置 discard_changes: true 强制删除,或使用 action: 'keep' 保留。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n return {\n success: true,\n content:\n \"Worktree 已删除(目录及分支均已删除)。已返回原始目录。\\n[Phase 4: 通过 @lynx/agent 实现真正的 worktree 删除]\",\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * ConfigTool — 读取或修改 Lynx 配置。\n *\n * 配置存储在 ~/.lynx/config.json。支持四种操作:\n * - get: 获取指定 key 的配置值\n * - set: 设置指定 key 的配置值(原子写入)\n * - list: 列出所有配置项\n * - path: 返回配置文件路径\n */\nimport { readFileSync, writeFileSync, existsSync, mkdirSync, renameSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, dirname } from \"node:path\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"ConfigTool\",\n description:\n \"读取或修改 Lynx 配置。可以查看当前配置值或设置新的配置项。\" +\n \"支持四种操作:get(获取单个配置项)、set(设置配置项)、list(列出所有配置项)、path(查看配置文件路径)。\",\n inputSchema: {\n type: \"object\",\n properties: {\n action: {\n type: \"string\",\n enum: [\"get\", \"set\", \"list\", \"path\"],\n description: \"操作类型:get(获取)、set(设置)、list(列出全部)、path(查看路径)\",\n },\n key: {\n type: \"string\",\n description: \"配置项的键名(get/set 操作需要)\",\n },\n value: {\n type: \"string\",\n description: \"要设置的值(仅 set 操作需要)\",\n },\n },\n required: [\"action\"],\n },\n kind: \"WritesFiles\",\n safety: \"WorkspaceSafe\",\n availability: { type: \"always\" },\n executor: \"core:config_tool\",\n owner: \"core\",\n};\n\n/** 获取配置文件路径(POSIX 风格)。 */\nfunction resolveConfigPath(): string {\n const home = homedir();\n return join(home, \".lynx\", \"config.json\").replace(/\\\\/g, \"/\");\n}\n\n/** 加载当前配置,文件不存在时返回空对象。 */\nfunction loadConfig(path: string): Record<string, unknown> {\n if (!existsSync(path)) return {};\n try {\n return JSON.parse(readFileSync(path, \"utf-8\"));\n } catch {\n const backupPath = path + \".bak\";\n renameSync(path, backupPath);\n return {};\n }\n}\n\n/** 原子写入配置(先写临时文件再重命名)。 */\nfunction saveConfig(path: string, config: Record<string, unknown>): void {\n const dir = dirname(path);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n const tmpPath = path + \".tmp\";\n writeFileSync(tmpPath, JSON.stringify(config, null, 2) + \"\\n\", \"utf-8\");\n renameSync(tmpPath, path);\n}\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { action, key, value } = invocation.payload as {\n action: string;\n key?: string;\n value?: string;\n };\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const configPath = resolveConfigPath();\n\n switch (action) {\n case \"path\": {\n return {\n success: true,\n content: configPath,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n case \"list\": {\n const config = loadConfig(configPath);\n const keys = Object.keys(config);\n if (keys.length === 0) {\n return {\n success: true,\n content: \"当前没有配置项。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const lines = keys.map((k) => `${k} = ${JSON.stringify(config[k])}`);\n return {\n success: true,\n content: lines.join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n case \"get\": {\n if (!key) {\n return {\n success: false,\n content: \"get 操作需要提供 key 参数。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const config = loadConfig(configPath);\n if (!(key in config)) {\n return {\n success: false,\n content: `配置项 \"${key}\" 不存在。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n return {\n success: true,\n content: JSON.stringify(config[key]),\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n case \"set\": {\n if (!key) {\n return {\n success: false,\n content: \"set 操作需要提供 key 参数。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const config = loadConfig(configPath);\n const setValue = value ?? \"\";\n config[key] = setValue;\n try {\n saveConfig(configPath, config);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `写入配置文件失败: ${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n return {\n success: true,\n content: `已设置 ${key} = ${JSON.stringify(setValue)}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n default: {\n return {\n success: false,\n content: `不支持的操作: ${action}。支持的操作: get, set, list, path。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n }\n },\n};\n","/**\n * ask_user_question — Ask the user one or more questions and wait for answers.\n *\n * Supports single-select and multi-select questions. Up to 4 questions per call,\n * each with 2-4 options. The user can select \"Other\" for free-text input.\n *\n * This blocks the agent loop until the user responds.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"ask_user_question\",\n description:\n \"向用户提出一个或多个澄清性问题并等待回答。\" +\n \"支持单选、多选以及自由文本的「其他」选项。\" +\n \"当您被一个只有用户才能做决定的问题卡住时使用。\",\n inputSchema: {\n type: \"object\",\n properties: {\n questions: {\n type: \"array\",\n minItems: 1,\n maxItems: 4,\n items: {\n type: \"object\",\n properties: {\n question: { type: \"string\", description: \"向用户提出的完整问题\" },\n header: {\n type: \"string\",\n description: \"显示为标签的简短文字(最多 12 个字符)\",\n },\n options: {\n type: \"array\",\n minItems: 2,\n maxItems: 4,\n items: {\n type: \"object\",\n properties: {\n label: { type: \"string\", description: \"显示文本(1-5 个词)\" },\n description: {\n type: \"string\",\n description: \"对该选项含义的解释说明\",\n },\n },\n required: [\"label\", \"description\"],\n },\n description: \"可选项(2-4 个)。「其他」选项会自动追加。\",\n },\n multiSelect: { type: \"boolean\", description: \"是否允许多选\" },\n },\n required: [\"question\", \"header\", \"options\", \"multiSelect\"],\n },\n description: \"要提问的问题列表(1-4 个)\",\n },\n },\n required: [\"questions\"],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:ask_user_question\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { questions } = invocation.payload as {\n questions: Array<{\n question: string;\n header: string;\n options: Array<{ label: string; description: string }>;\n multiSelect: boolean;\n }>;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"提问已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n // This tool is special: it blocks the agent loop and requires the TUI\n // to render a modal and return user input. The real implementation lives\n // in lynx-cli bootstrap where the handler is wired to the TUI bridge.\n //\n // Phase 2 provides a mock for testing the tool contract.\n\n const questionList = questions\n .map((q, i) => {\n const opts = q.options.map((o) => ` - ${o.label}: ${o.description}`).join(\"\\n\");\n return `Q${i + 1}. [${q.header}] ${q.question}${q.multiSelect ? \" (multi-select)\" : \"\"}\\n${opts}`;\n })\n .join(\"\\n\\n\");\n\n return {\n success: true,\n content: [\n \"向用户提问:\",\n \"\",\n questionList,\n \"\",\n \"[Phase 4 TUI 集成: 通过 lynx-tui 桥接实现真正的 AskUserQuestion 弹窗]\",\n ].join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * brief — Generate a structured summary brief of the current context.\n *\n * Compresses the current conversation state into a structured summary with\n * configurable sections. Default sections: context, goal, progress, blockers, next.\n * Output format: markdown or JSON.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"brief\",\n description:\n \"生成当前对话上下文的结构化摘要简报。\" + \"适用于进度检查点、会话间交接、或向用户提供状态更新。\",\n inputSchema: {\n type: \"object\",\n properties: {\n format: {\n type: \"string\",\n enum: [\"markdown\", \"json\"],\n description: \"输出格式(默认:markdown)\",\n },\n sections: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"要包含的章节(默认:context, goal, progress, blockers, next)\",\n },\n },\n required: [],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:brief\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { format, sections } = invocation.payload as {\n format?: \"markdown\" | \"json\";\n sections?: string[];\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"简报生成已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const fmt = format ?? \"markdown\";\n const secs = sections ?? [\"context\", \"goal\", \"progress\", \"blockers\", \"next\"];\n\n if (fmt === \"json\") {\n const brief: Record<string, string> = {};\n for (const s of secs)\n brief[s] = `[Phase 3: real context extraction via @lynx/agent compaction]`;\n return {\n success: true,\n content: JSON.stringify(brief, null, 2),\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const lines = [\"# Brief\", \"\"];\n for (const s of secs) {\n lines.push(\n `## ${s}`,\n \"\",\n `[Phase 3: real context extraction via @lynx/agent compaction]`,\n \"\",\n );\n }\n\n return {\n success: true,\n content: lines.join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * synthetic_output — Generate structured output constrained by a JSON Schema.\n *\n * Used for sub-agent-to-agent data passing. The content must conform to the\n * provided schema. The LLM retries automatically on validation failure.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"synthetic_output\",\n description:\n \"生成符合 JSON Schema 的结构化输出。\" +\n \"用于在子 Agent 和父 Agent 之间传递带类型的数据。\" +\n \"如果输出无法通过 schema 校验,LLM 会自动重试。\",\n inputSchema: {\n type: \"object\",\n properties: {\n schema: {\n type: \"object\",\n description: \"输出必须符合的 JSON Schema\",\n },\n content: {\n type: \"object\",\n description: \"结构化内容(必须与 schema 匹配)\",\n },\n },\n required: [\"schema\", \"content\"],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:synthetic_output\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { schema, content } = invocation.payload as {\n schema: Record<string, unknown>;\n content: Record<string, unknown>;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"合成输出已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n // TODO Phase 3: validate content against schema using Ajv or similar\n // For Phase 2: pass-through with basic validation\n if (!schema || typeof schema !== \"object\") {\n return {\n success: false,\n content: \"无效的 schema:必须为 JSON Schema 对象\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n return {\n success: true,\n content: JSON.stringify(content, null, 2),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * sleep — Pause execution for a specified duration.\n *\n * Used for: waiting on external events, rate limit backoff, polling intervals.\n * Maximum 300 seconds. `reason` is required to prevent pointless waits.\n * Abort signal interrupts sleep early.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"sleep\",\n description:\n \"暂停执行指定秒数。\" +\n \"用于速率限制退避、等待外部事件或轮询间隔。\" +\n \"最长 300 秒。必须提供原因。\",\n inputSchema: {\n type: \"object\",\n properties: {\n seconds: {\n type: \"number\",\n description: \"等待的秒数(最多 300)\",\n minimum: 1,\n maximum: 300,\n },\n reason: {\n type: \"string\",\n description: \"为什么需要等待(必填 — 防止无意义的等待)\",\n },\n },\n required: [\"seconds\", \"reason\"],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:sleep\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { seconds, reason } = invocation.payload as {\n seconds: number;\n reason: string;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"等待已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const maxSeconds = 300;\n const clamped = Math.min(Math.max(1, Math.floor(seconds)), maxSeconds);\n\n if (clamped !== seconds) {\n // Clamped — warn but proceed\n }\n\n // Abort-aware sleep\n await new Promise<void>((resolve, reject) => {\n const timer = setTimeout(resolve, clamped * 1000);\n const onAbort = () => {\n clearTimeout(timer);\n reject(new Error(\"ABORTED\"));\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }).catch((err) => {\n if ((err as Error).message === \"ABORTED\") {\n // Expected — triggered by signal\n } else {\n throw err;\n }\n });\n\n const actualWait = Date.now() - startTime;\n\n if (signal.aborted) {\n return {\n success: true,\n content: `等待在 ${Math.round(actualWait / 1000)} 秒后被中断(请求:${clamped} 秒)。原因:${reason}`,\n metadata: { durationMs: actualWait },\n };\n }\n\n return {\n success: true,\n content: `已等待 ${clamped} 秒。原因:${reason}`,\n metadata: { durationMs: actualWait },\n };\n },\n};\n","/**\n * memory_write — 读写持久化长期记忆。\n *\n * 每个记忆条目以带 YAML frontmatter 的 markdown 文件形式存储在用户的\n * memory 目录(~/.lynx/memory/)中。AI 在启动时将这些文件加载到系统提示词中,\n * 实现跨会话的持久化记忆。\n *\n * 支持的操作:\n * - create / update / delete — 基本 CRUD\n * - search — 全文搜索记忆\n * - compact — 去重压缩相似条目\n * - forget — 按 glob 模式批量删除\n * - export — 导出全部记忆为 JSON\n * - import — 从 JSON 批量导入\n * - merge — 合并另一个 memory 目录\n *\n * 格式仿照 Claude Code 的记忆系统:\n * - Frontmatter: name, description, metadata.type\n * - 正文: 事实内容\n * - MEMORY.md 索引文件用于快速扫描\n */\n\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\nimport type { MemoryManager } from \"@lynx/agent\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"memory_write\",\n description:\n \"管理持久化记忆。支持以下操作:\" +\n \"create/update — 写入或更新一条记忆;\" +\n \"delete — 按名称删除;\" +\n \"search — 全文搜索记忆(按相关度排序);\" +\n \"compact — 去重压缩相似条目(Jaccard 相似度 > 0.8);\" +\n \"forget — 按 glob 模式批量删除匹配的记忆;\" +\n \"export — 导出全部记忆为 JSON 字符串;\" +\n \"import — 从 JSON 字符串批量导入记忆(跳过同名条目);\" +\n \"merge — 合并另一个 memory 目录中的记忆文件。\" +\n \"当用户要求记住某事、搜索记忆、清理重复记忆或迁移记忆时使用。\",\n inputSchema: {\n type: \"object\",\n properties: {\n action: {\n type: \"string\",\n enum: [\n \"create\",\n \"update\",\n \"delete\",\n \"search\",\n \"compact\",\n \"forget\",\n \"export\",\n \"import\",\n \"merge\",\n ],\n description:\n \"要执行的操作。create = 新建记忆,update = 更新已有记忆,\" +\n \"delete = 按名称删除,search = 全文搜索,\" +\n \"compact = 去重压缩,forget = 按 glob 批量删除,\" +\n \"export = 导出 JSON,import = 导入 JSON,merge = 合并目录。\",\n },\n name: {\n type: \"string\",\n description:\n \"记忆的简短 kebab-case 标识(例如 'user-prefers-pnpm')。用作文件名。\" +\n \"create/update/delete 操作必填。\",\n },\n content: {\n type: \"string\",\n description:\n \"记忆的完整 markdown 正文。用自然语言书写。\" +\n \"对于反馈/项目类记忆,请包含 **Why:** 和 **How to apply:** 段落。\" +\n \"使用 [[slug]] 引用关联相关记忆。\" +\n \"create/update 操作时提供。\",\n },\n description: {\n type: \"string\",\n description: \"一行摘要,用于在调用记忆时判断相关性。保持简短且具体。\",\n },\n type: {\n type: \"string\",\n enum: [\"user\", \"feedback\", \"project\", \"reference\"],\n description:\n \"记忆分类。'user' = 用户身份,'feedback' = 纠正/指引,\" +\n \"'project' = 进行中的工作/目标,'reference' = 外部资料引用。\",\n },\n query: {\n type: \"string\",\n description: \"搜索关键词,多个词用空格分隔(search 操作使用)。\",\n },\n pattern: {\n type: \"string\",\n description:\n \"glob 模式,用于匹配要删除的记忆名称(forget 操作使用)。\" + \"支持 * 和 ? 通配符。\",\n },\n data: {\n type: \"string\",\n description: \"要导入的 JSON 数据字符串,由 export 操作生成(import 操作使用)。\",\n },\n sourceDir: {\n type: \"string\",\n description: \"源 memory 目录的绝对路径(merge 操作使用)。\",\n },\n },\n required: [\"action\"],\n },\n kind: \"WritesFiles\",\n safety: \"WorkspaceSafe\",\n availability: { type: \"always\" },\n executor: \"core:memory_write\",\n owner: \"core\",\n};\n\n/**\n * 创建绑定到指定 {@link MemoryManager} 的 memory_write 处理器。\n *\n * 工厂模式 — 管理器在启动时注入,使工具写入真实的 memory 目录。\n */\nexport function createMemoryWriteHandler(memoryManager: MemoryManager): ToolHandler {\n return {\n async handle(invocation, _signal): Promise<ToolResult> {\n const payload = invocation.payload as {\n action?: string;\n name?: string;\n content?: string;\n description?: string;\n type?: \"user\" | \"feedback\" | \"project\" | \"reference\";\n query?: string;\n pattern?: string;\n data?: string;\n sourceDir?: string;\n };\n\n const action = payload.action ?? \"create\";\n\n switch (action) {\n case \"create\":\n case \"update\": {\n const { name, content } = payload;\n if (!name) {\n return {\n success: false,\n content: `缺少必填参数 \"name\"。`,\n };\n }\n if (!content) {\n return {\n success: false,\n content: `缺少必填参数 \"content\"。`,\n };\n }\n\n if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name)) {\n return {\n success: false,\n content: `无效的记忆名称 \"${name}\"。请使用 kebab-case 格式,仅含小写字母、数字和连字符(例如 \"user-prefers-pnpm\")。`,\n };\n }\n\n const effectiveType = payload.type ?? \"reference\";\n const updatedAt = Date.now();\n\n memoryManager.put({\n name,\n description: payload.description ?? \"\",\n type: effectiveType,\n content,\n updatedAt,\n filePath: \"\", // put() 内部处理文件路径\n });\n\n memoryManager.reload();\n\n const actionLabel = action === \"create\" ? \"已创建\" : \"已更新\";\n return {\n success: true,\n content: `记忆 \"${name}\" ${actionLabel}(类型:${effectiveType})。后续会话中将自动加载到上下文中。`,\n };\n }\n\n case \"delete\": {\n const { name } = payload;\n if (!name) {\n return {\n success: false,\n content: `缺少必填参数 \"name\"。`,\n };\n }\n\n const deleted = memoryManager.delete(name);\n if (deleted) {\n return {\n success: true,\n content: `记忆 \"${name}\" 已删除。`,\n };\n }\n return {\n success: false,\n content: `未找到名为 \"${name}\" 的记忆。`,\n };\n }\n\n case \"search\": {\n const { query } = payload;\n if (!query || !query.trim()) {\n return {\n success: false,\n content: `缺少必填参数 \"query\"(搜索关键词)。`,\n };\n }\n\n const results = memoryManager.search(query);\n if (results.length === 0) {\n return {\n success: true,\n content: `未找到与 \"${query}\" 匹配的记忆。`,\n };\n }\n\n const lines = [`搜索 \"${query}\" 找到 ${results.length} 条相关记忆:`, \"\"];\n for (const entry of results) {\n const typeLabel = entry.type;\n lines.push(`- **${entry.name}** [${typeLabel}]: ${entry.description}`);\n }\n return {\n success: true,\n content: lines.join(\"\\n\"),\n };\n }\n\n case \"compact\": {\n const before = memoryManager.list().length;\n const remaining = memoryManager.compact();\n const removed = before - remaining.length;\n\n if (removed === 0) {\n return {\n success: true,\n content: `去重压缩完成。未发现相似条目,${remaining.length} 条记忆保持不变。`,\n };\n }\n\n return {\n success: true,\n content: `去重压缩完成。移除了 ${removed} 条重复记忆,当前共 ${remaining.length} 条。`,\n };\n }\n\n case \"forget\": {\n const { pattern } = payload;\n if (!pattern || !pattern.trim()) {\n return {\n success: false,\n content: `缺少必填参数 \"pattern\"(glob 模式)。`,\n };\n }\n\n const count = memoryManager.forget(pattern);\n if (count === 0) {\n return {\n success: true,\n content: `没有记忆匹配模式 \"${pattern}\"。`,\n };\n }\n\n return {\n success: true,\n content: `已删除 ${count} 条匹配模式 \"${pattern}\" 的记忆。`,\n };\n }\n\n case \"export\": {\n const json = memoryManager.exportAll();\n return {\n success: true,\n content: json,\n };\n }\n\n case \"import\": {\n const { data } = payload;\n if (!data || !data.trim()) {\n return {\n success: false,\n content: `缺少必填参数 \"data\"(要导入的 JSON 数据)。`,\n };\n }\n\n const count = memoryManager.importAll(data);\n if (count === 0) {\n return {\n success: true,\n content: `未导入任何新记忆。JSON 数据可能为空,或所有条目已存在。`,\n };\n }\n\n return {\n success: true,\n content: `成功导入 ${count} 条新记忆。`,\n };\n }\n\n case \"merge\": {\n const { sourceDir } = payload;\n if (!sourceDir || !sourceDir.trim()) {\n return {\n success: false,\n content: `缺少必填参数 \"sourceDir\"(源目录路径)。`,\n };\n }\n\n const count = memoryManager.merge(sourceDir);\n if (count === 0) {\n return {\n success: true,\n content: `未合并任何新记忆。源目录可能不存在、为空,或所有条目已存在。`,\n };\n }\n\n return {\n success: true,\n content: `成功从 \"${sourceDir}\" 合并 ${count} 条新记忆。`,\n };\n }\n\n default:\n return {\n success: false,\n content: `不支持的操作 \"${action}\"。支持的操作:create, update, delete, search, compact, forget, export, import, merge。`,\n };\n }\n },\n };\n}\n","/**\n * McpAuthTool — 触发 MCP 服务器的重新认证流程(OAuth 或 XAA)。\n *\n * 用于在工具调用失败并返回认证错误时,支持模型主动触发重连。\n * 工厂函数注入 McpManager 的最小接口,避免 lynx-tools 依赖 lynx-agent。\n */\n\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\n/** McpManager 的最小接口 — lynx-tools 不依赖 lynx-agent。 */\nexport interface McpAuthOps {\n reconnect(serverName: string): Promise<{ status: string }>;\n}\n\n/** 工具描述符 — 注册到 ToolRegistry 的静态元数据。 */\nexport const descriptor: ToolDescriptor = {\n name: \"McpAuthTool\",\n description:\n \"触发 MCP 服务器的重新认证流程(OAuth 或 XAA)。\" + \"用于在工具调用失败并返回认证错误时。\",\n inputSchema: {\n type: \"object\",\n properties: {\n serverName: {\n type: \"string\",\n description: \"需要重新认证的 MCP 服务器名称\",\n },\n },\n required: [\"serverName\"],\n },\n kind: \"Network\",\n safety: \"RequiresApproval\",\n availability: { type: \"always\" as const },\n executor: \"core:mcp_auth\",\n owner: \"core\",\n};\n\n/**\n * 创建 McpAuthTool 的 handler,绑定到给定的 McpAuthOps。\n *\n * 工厂模式 — 实际 McpManager 在 bootstrap 时注入。\n */\nexport function createMcpAuthHandler(mcpOps: McpAuthOps): ToolHandler {\n return {\n async handle(invocation, signal): Promise<ToolResult> {\n const { serverName } = invocation.payload as {\n serverName: string;\n };\n\n if (!serverName || typeof serverName !== \"string\") {\n return { success: false, content: \"缺少必需参数 serverName\" };\n }\n\n if (signal.aborted) {\n return { success: false, content: \"操作已取消\" };\n }\n\n try {\n const result = await mcpOps.reconnect(serverName);\n return {\n success: true,\n content: `MCP 服务器 \"${serverName}\" 重新认证完成,当前状态:${result.status}`,\n };\n } catch (err) {\n return {\n success: false,\n content: `MCP 认证失败:${(err as Error).message}`,\n };\n }\n },\n };\n}\n","/**\n * SendMessageTool — 消息通道发送工具。\n *\n * 通过配置的消息通道(飞书等)发送通知或进度摘要。\n * 使用工厂模式注入 MessageSender 接口,避免硬依赖 lynx-channels。\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\n// ── Local interface (no import from lynx-channels) ───\n\n/** 消息发送器接口 —— 由调用方注入具体实现。 */\nexport interface MessageSender {\n /**\n * 通过指定通道发送消息。\n * @param channel 通道标识(如 \"feishu\")\n * @param content 消息内容\n * @param recipients 可选接收人列表\n * @returns 包含 messageId 的结果\n */\n send(channel: string, content: string, recipients?: string[]): Promise<{ messageId: string }>;\n}\n\n// ── Descriptor ────────────────────────────────────────\n\nexport const descriptor: ToolDescriptor = {\n name: \"SendMessageTool\",\n description:\n \"通过配置的消息通道发送消息(飞书等)。\" +\n \"用于向用户发送通知或进度摘要。需要提前配置消息通道。\",\n inputSchema: {\n type: \"object\",\n properties: {\n channel: {\n type: \"string\",\n description: \"消息通道名称(如 feishu)\",\n },\n content: {\n type: \"string\",\n description: \"要发送的消息内容\",\n },\n recipients: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"接收人列表(可选)\",\n },\n },\n required: [\"channel\", \"content\"],\n },\n kind: \"Network\",\n safety: \"RequiresApproval\",\n availability: { type: \"always\" },\n executor: \"core:send_message\",\n owner: \"core\",\n};\n\n// ── Factory ───────────────────────────────────────────\n\n/**\n * 创建 SendMessageTool 的处理器。\n *\n * 通过工厂注入 MessageSender 实现,避免直接 import lynx-channels。\n * 在 bootstrap 阶段将真实的通道发送器注入此处。\n */\nexport function createSendMessageHandler(sender: MessageSender): ToolHandler {\n return {\n async handle(invocation, signal): Promise<ToolResult> {\n const { channel, content, recipients } = invocation.payload as {\n channel: string;\n content: string;\n recipients?: string[];\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"消息发送已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (!channel || !content) {\n return {\n success: false,\n content: \"缺少必要参数:channel 和 content 均为必填\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n const result = await sender.send(channel, content, recipients);\n\n return {\n success: true,\n content: `消息已通过 ${channel} 发送${recipients ? ` 给 ${recipients.join(\", \")}` : \"\"}。消息 ID:${result.messageId}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `消息发送失败(${channel}):${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n },\n };\n}\n","/**\n * Built‑in tools — canonical registration entry point.\n *\n * Every tool is defined as a (descriptor, handler) pair in its own module.\n * This index imports all of them and provides a single {@link registerBuiltinTools}\n * function that the bootstrap layer calls to populate the {@link ToolRegistry}.\n *\n * Tool categories:\n * files/ — filesystem operations (read, write, edit, glob, grep, web)\n * agent/ — sub‑agent orchestration\n * mode/ — plan mode / worktree lifecycle\n * interact/ — user interaction (questions, brief, sleep)\n */\n\nimport type { ToolRegistry } from \"../registry.js\";\n\n// ── Files ──────────────────────────────────────────\nimport { descriptor as readFileDesc, handler as readFileHandler } from \"./files/read-file.js\";\nimport { descriptor as writeFileDesc, handler as writeFileHandler } from \"./files/write-file.js\";\nimport { descriptor as editFileDesc, handler as editFileHandler } from \"./files/edit-file.js\";\nimport { descriptor as globDesc, handler as globHandler } from \"./files/glob.js\";\nimport { descriptor as grepDesc, handler as grepHandler } from \"./files/grep.js\";\nimport { descriptor as webFetchDesc, handler as webFetchHandler } from \"./files/web-fetch.js\";\nimport { descriptor as webSearchDesc, handler as webSearchHandler } from \"./files/web-search.js\";\nimport { descriptor as todoWriteDesc, handler as todoWriteHandler } from \"./files/todo-write.js\";\nimport { descriptor as powershellDesc, handler as powershellHandler } from \"./files/powershell.js\";\nimport {\n descriptor as notebookEditDesc,\n handler as notebookEditHandler,\n} from \"./files/notebook-edit.js\";\nimport { descriptor as secretScanDesc, handler as secretScanHandler } from \"./files/secret-scan.js\";\nimport { descriptor as lspDesc, handler as lspHandler } from \"./files/lsp.js\";\nimport { descriptor as replDesc, handler as replHandler } from \"./files/repl.js\";\n\n// ── Agent ──────────────────────────────────────────\nimport { descriptor as agentDesc, handler as agentHandler } from \"./agent/agent.js\";\nimport { descriptor as taskDesc, handler as taskHandler } from \"./agent/task.js\";\nimport { descriptor as teamCreateDesc, handler as teamCreateHandler } from \"./agent/team-create.js\";\nimport { descriptor as teamDeleteDesc, handler as teamDeleteHandler } from \"./agent/team-delete.js\";\nimport { descriptor as verifyPlanDesc, handler as verifyPlanHandler } from \"./agent/verify-plan.js\";\nimport {\n descriptor as remoteTriggerDesc,\n handler as remoteTriggerHandler,\n} from \"./agent/remote-trigger.js\";\nimport {\n descriptor as scheduleCronDesc,\n handler as scheduleCronHandler,\n} from \"./agent/schedule-cron.js\";\nimport { descriptor as workflowDesc, handler as workflowHandler } from \"./agent/workflow.js\";\nimport { descriptor as tungstenDesc, handler as tungstenHandler } from \"./agent/tungsten.js\";\n\n// ── Mode ───────────────────────────────────────────\nimport {\n descriptor as enterPlanModeDesc,\n handler as enterPlanModeHandler,\n} from \"./mode/enter-plan-mode.js\";\nimport {\n descriptor as exitPlanModeDesc,\n handler as exitPlanModeHandler,\n} from \"./mode/exit-plan-mode.js\";\nimport {\n descriptor as enterWorktreeDesc,\n handler as enterWorktreeHandler,\n} from \"./mode/enter-worktree.js\";\nimport {\n descriptor as exitWorktreeDesc,\n handler as exitWorktreeHandler,\n} from \"./mode/exit-worktree.js\";\nimport { descriptor as configToolDesc, handler as configToolHandler } from \"./mode/config-tool.js\";\n\n// ── Interact ───────────────────────────────────────\nimport {\n descriptor as askUserDesc,\n handler as askUserHandler,\n} from \"./interact/ask-user-question.js\";\nimport { descriptor as briefDesc, handler as briefHandler } from \"./interact/brief.js\";\nimport {\n descriptor as syntheticOutputDesc,\n handler as syntheticOutputHandler,\n} from \"./interact/synthetic-output.js\";\nimport { descriptor as sleepDesc, handler as sleepHandler } from \"./interact/sleep.js\";\n\n// ── Agent factories ────────────────────────────────────\nexport { injectTaskManager, createTaskHandler } from \"./agent/task.js\";\n\n// ── Memory ───────────────────────────────────────────\nexport { descriptor as memoryWriteDescriptor } from \"./memory/memory-write.js\";\nexport { createMemoryWriteHandler } from \"./memory/memory-write.js\";\n\n// ── ToolSearch ─────────────────────────────────────────\nexport { descriptor as toolSearchDescriptor } from \"./files/tool-search.js\";\nexport { createToolSearchHandler } from \"./files/tool-search.js\";\n\n// ── MCP ──────────────────────────────────────────────\nexport { descriptor as mcpCallToolDescriptor } from \"./mcp/call-tool.js\";\nexport { createMcpCallToolHandler } from \"./mcp/call-tool.js\";\nexport { descriptor as listMcpResourcesDescriptor } from \"./mcp/list-resources.js\";\nexport { createListMcpResourcesHandler } from \"./mcp/list-resources.js\";\nexport { descriptor as readMcpResourceDescriptor } from \"./mcp/read-resource.js\";\nexport { createReadMcpResourceHandler } from \"./mcp/read-resource.js\";\nexport { descriptor as mcpAuthDescriptor } from \"./mcp/mcp-auth.js\";\nexport { createMcpAuthHandler } from \"./mcp/mcp-auth.js\";\n\n// ── Interact factories ──────────────────────────────\nexport { descriptor as sendMessageDescriptor } from \"./interact/send-message.js\";\nexport { createSendMessageHandler } from \"./interact/send-message.js\";\n\n// ── Registration ────────────────────────────────────\n\n/** All built‑in (descriptor, handler) pairs in registration order. */\nconst BUILTIN_TOOLS: Array<{\n descriptor: typeof readFileDesc;\n handler: typeof readFileHandler;\n}> = [\n // Files\n { descriptor: readFileDesc, handler: readFileHandler },\n { descriptor: writeFileDesc, handler: writeFileHandler },\n { descriptor: editFileDesc, handler: editFileHandler },\n { descriptor: globDesc, handler: globHandler },\n { descriptor: grepDesc, handler: grepHandler },\n { descriptor: webFetchDesc, handler: webFetchHandler },\n { descriptor: webSearchDesc, handler: webSearchHandler },\n { descriptor: todoWriteDesc, handler: todoWriteHandler },\n { descriptor: powershellDesc, handler: powershellHandler },\n { descriptor: notebookEditDesc, handler: notebookEditHandler },\n { descriptor: secretScanDesc, handler: secretScanHandler },\n { descriptor: lspDesc, handler: lspHandler },\n { descriptor: replDesc, handler: replHandler },\n // Agent\n { descriptor: agentDesc, handler: agentHandler },\n { descriptor: taskDesc, handler: taskHandler },\n { descriptor: teamCreateDesc, handler: teamCreateHandler },\n { descriptor: teamDeleteDesc, handler: teamDeleteHandler },\n { descriptor: verifyPlanDesc, handler: verifyPlanHandler },\n { descriptor: remoteTriggerDesc, handler: remoteTriggerHandler },\n { descriptor: scheduleCronDesc, handler: scheduleCronHandler },\n { descriptor: workflowDesc, handler: workflowHandler },\n { descriptor: tungstenDesc, handler: tungstenHandler },\n // Mode\n { descriptor: enterPlanModeDesc, handler: enterPlanModeHandler },\n { descriptor: exitPlanModeDesc, handler: exitPlanModeHandler },\n { descriptor: enterWorktreeDesc, handler: enterWorktreeHandler },\n { descriptor: exitWorktreeDesc, handler: exitWorktreeHandler },\n { descriptor: configToolDesc, handler: configToolHandler },\n // Interact\n { descriptor: askUserDesc, handler: askUserHandler },\n { descriptor: briefDesc, handler: briefHandler },\n { descriptor: syntheticOutputDesc, handler: syntheticOutputHandler },\n { descriptor: sleepDesc, handler: sleepHandler },\n];\n\n/**\n * Register all built‑in tool (descriptor, handler) pairs with the given registry.\n *\n * Each pair is registered atomically — if one fails (duplicate name), the error\n * propagates so the caller can decide whether to abort or skip.\n */\nexport function registerBuiltinTools(registry: ToolRegistry): void {\n for (const { descriptor, handler } of BUILTIN_TOOLS) {\n registry.register(descriptor, handler);\n }\n}\n\n/** Return the list of built‑in descriptors (without registering). */\nexport function listBuiltinDescriptors(): (typeof BUILTIN_TOOLS)[number][\"descriptor\"][] {\n return BUILTIN_TOOLS.map((t) => t.descriptor);\n}\n","/**\n * Tool planner — decides which tools are visible to the LLM this turn.\n *\n * Called at the start of every agent loop iteration so tool visibility\n * can change dynamically (e.g. permission mode switch, MCP server connected,\n * feature flags toggled).\n */\n\nimport type { ToolDescriptor, ToolPlan, HiddenTool } from \"./types.js\";\nimport type { EvalContext } from \"./availability.js\";\nimport { evaluateAvailability } from \"./availability.js\";\nimport type { ToolRegistry } from \"./registry.js\";\n\n// ── Public API ─────────────────────────────────────\n\n/**\n * Compute the tool plan for the current turn.\n *\n * Every registered tool is evaluated against the availability context.\n * Visible tools go into the LLM catalog; hidden tools are returned with\n * a reason so the debug/log layer can report them.\n *\n * ```ts\n * const plan = buildToolPlan(registry, evalCtx);\n * console.log(`${plan.visible.length} visible, ${plan.hidden.length} hidden`);\n * ```\n */\nexport function buildToolPlan(registry: ToolRegistry, ctx: EvalContext): ToolPlan {\n const visible: ToolDescriptor[] = [];\n const hidden: HiddenTool[] = [];\n\n for (const tool of registry.listAll()) {\n const result = evaluateAvailability(tool.availability, ctx);\n\n if (result.available) {\n visible.push(tool);\n } else {\n hidden.push({\n tool,\n reason: result.reason ?? \"unknown\",\n });\n }\n }\n\n return { visible, hidden };\n}\n","/**\n * Sensitive file classification — 4‑level protection system.\n *\n * Levels (increasing severity):\n * Low — normal files, write allowed\n * Medium — config/build files, write prompts confirmation\n * High — env/secret files, read‑only (write blocked)\n * Critical — SSH/GPG keys, never read or write\n *\n * This replaces the flat `SENSITIVE_PATHS` Set in safety.ts\n * with a tiered system that enables fine‑grained access control.\n */\n\n// ── Types ─────────────────────────────────────────────\n\nexport type SensitivityLevel = \"Low\" | \"Medium\" | \"High\" | \"Critical\";\n\nexport interface SensitivityCheck {\n level: SensitivityLevel;\n pattern: string;\n}\n\n// ── Patterns — ordered from most to least specific ────\n\ninterface SensitivityRule {\n patterns: string[];\n level: SensitivityLevel;\n}\n\nconst RULES: readonly SensitivityRule[] = [\n {\n level: \"Critical\",\n patterns: [\n \"**/.ssh/**\",\n \"**/.gnupg/**\",\n \"**/.aws/**\",\n \"/etc/**\",\n \"/root/**\",\n \"/var/log/**\",\n \"/proc/**\",\n \"/sys/**\",\n \"/dev/**\",\n \"**/secrets/**\",\n \"**/.lynx/auth.json\",\n \"**/.claude/auth.json\",\n \"**/credentials.json\",\n // Windows system paths (normalised to forward slashes)\n \"C:/Windows/**\",\n \"C:/Windows/System32/**\",\n \"C:/Program Files/**\",\n ],\n },\n {\n level: \"High\",\n patterns: [\n \".env\",\n \".env.*\",\n \"!**/.env.example\",\n \"!**/.env.sample\",\n \"**/.git/config\",\n \"~/.lynx/config.json\",\n \"yarn.lock\",\n \"pnpm-lock.yaml\",\n \"package-lock.json\",\n \"**/id_rsa*\",\n \"**/id_ed25519*\",\n \"**/*.pem\",\n \"**/*.key\",\n ],\n },\n {\n level: \"Medium\",\n patterns: [\n \"package.json\",\n \"tsconfig.json\",\n \"tsconfig.*.json\",\n \"Cargo.toml\",\n \"Makefile\",\n \"Dockerfile\",\n \".github/workflows/**\",\n \"docker-compose.yml\",\n \"docker-compose.yaml\",\n \"**/deploy/**\",\n \"**/terraform/**\",\n ],\n },\n];\n\n// ── Helpers ──────────────────────────────────────────\n\n/**\n * Simple glob‑to‑regex for the path patterns we use.\n * Handles **, *, and ! (negation prefix).\n */\nfunction patternToRegex(pattern: string): { regex: RegExp; negate: boolean } {\n const negate = pattern.startsWith(\"!\");\n const body = negate ? pattern.slice(1) : pattern;\n\n let escaped = body\n .replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n .replace(/\\*\\*/g, \"<<<GLOBSTAR>>>\")\n .replace(/\\*/g, \"[^/]*\")\n .replace(/<<<GLOBSTAR>>>/g, \".*\");\n\n // If the pattern starts with ** or has no directory prefix, match anywhere\n if (body.startsWith(\"**/\") || !body.includes(\"/\")) {\n escaped = \"(?:.*/)?\" + escaped;\n }\n\n return { regex: new RegExp(`^${escaped}$`, \"i\"), negate };\n}\n\n// Compile rules once\ninterface CompiledRule {\n regex: RegExp;\n level: SensitivityLevel;\n negate: boolean;\n}\n\nlet _compiled: CompiledRule[] | null = null;\n\nfunction compiledRules(): CompiledRule[] {\n if (_compiled) return _compiled;\n _compiled = [];\n for (const rule of RULES) {\n for (const pattern of rule.patterns) {\n const { regex, negate } = patternToRegex(pattern);\n _compiled.push({ regex, level: rule.level, negate });\n }\n }\n return _compiled;\n}\n\n// ── Public API ────────────────────────────────────────\n\n/**\n * Classify a file path by sensitivity level.\n *\n * The path is tested against all rules in order. The first match wins.\n * Negation patterns (`!`) remove previous matches at the same level.\n *\n * @returns The sensitivity level for the given path.\n */\nexport function classifySensitivity(filePath: string): SensitivityLevel {\n // Normalize to forward slashes\n const norm = filePath.replace(/\\\\/g, \"/\");\n let result: SensitivityLevel = \"Low\";\n\n for (const { regex, level, negate } of compiledRules()) {\n if (regex.test(norm)) {\n if (negate) {\n // Negation clears a previous match at this level\n if (result === level) result = \"Low\";\n } else {\n // Higher severity wins\n if (severityOrder(level) > severityOrder(result)) {\n result = level;\n }\n }\n }\n }\n\n return result;\n}\n\n/**\n * Returns true if the path requires special handling\n * (Medium or higher sensitivity).\n */\nexport function isSensitive(filePath: string): boolean {\n return classifySensitivity(filePath) !== \"Low\";\n}\n\n/**\n * Get all paths at a given sensitivity level or higher.\n * For use in permission prompts and audit displays.\n */\nexport function getSensitivitySummary(filePath: string): SensitivityCheck {\n return {\n level: classifySensitivity(filePath),\n pattern: filePath,\n };\n}\n\n// ── Internal helpers ─────────────────────────────────\n\nconst SEVERITY_MAP: Record<SensitivityLevel, number> = {\n Low: 0,\n Medium: 1,\n High: 2,\n Critical: 3,\n};\n\nfunction severityOrder(level: SensitivityLevel): number {\n return SEVERITY_MAP[level];\n}\n","/**\n * Command safety classification — 4 levels from totally safe to dangerous.\n *\n * This mirrors Claude Code's 4‑level system and CodeWhale's ExecPolicyEngine:\n *\n * Safe — read‑only, no side effects (e.g. file listing)\n * WorkspaceSafe — writes only within the workspace root\n * RequiresApproval — needs user confirmation (e.g. network access)\n * Dangerous — always requires approval (e.g. raw shell eval)\n */\n\nimport type { CommandSafety } from \"./types.js\";\nimport { classifySensitivity, type SensitivityLevel } from \"./safety/sensitive.js\";\n\n// ── Sensitivity mapping ──────────────────────────────\n\n/**\n * Map the 4‑level file sensitivity to a minimum command safety level.\n *\n * Low → no escalation\n * Medium → WorkspaceSafe (write needs confirmation)\n * High → RequiresApproval (read is ok, write is blocked)\n * Critical → Dangerous (no read, no write)\n */\nconst SENSITIVITY_ESCALATION: Record<SensitivityLevel, CommandSafety | null> = {\n Low: null,\n Medium: \"WorkspaceSafe\",\n High: \"RequiresApproval\",\n Critical: \"RequiresApproval\",\n};\n\n// ── Safety override ────────────────────────────────\n\n/**\n * Escalate the safety level if the command touches a sensitive path.\n *\n * Uses the 4‑level sensitivity classification from {@link classifySensitivity}.\n * Even a \"Safe\" tool becomes Dangerous if it tries to read ~/.ssh.\n */\nexport function escalateForSensitivePaths(safety: CommandSafety, paths: string[]): CommandSafety {\n const SAFETY_ORDER: CommandSafety[] = [\"Safe\", \"WorkspaceSafe\", \"RequiresApproval\", \"Dangerous\"];\n\n let maxSensitivity: SensitivityLevel = \"Low\";\n for (const p of paths) {\n const level = classifySensitivity(p);\n if (SENSITIVITY_ORDER[level] > SENSITIVITY_ORDER[maxSensitivity]) {\n maxSensitivity = level;\n }\n }\n\n const minSafety = SENSITIVITY_ESCALATION[maxSensitivity];\n if (minSafety && SAFETY_ORDER.indexOf(safety) < SAFETY_ORDER.indexOf(minSafety)) {\n return minSafety;\n }\n\n return safety;\n}\n\nconst SENSITIVITY_ORDER: Record<SensitivityLevel, number> = {\n Low: 0,\n Medium: 1,\n High: 2,\n Critical: 3,\n};\n\n// ── Quick checks ───────────────────────────────────\n\n/**\n * Returns true if the tool requires interactive user confirmation.\n */\nexport function needsApproval(safety: CommandSafety): boolean {\n return safety === \"RequiresApproval\" || safety === \"Dangerous\";\n}\n\n/**\n * Returns true if the tool can run automatically in yolo/headless mode.\n */\nexport function isHeadlessSafe(safety: CommandSafety): boolean {\n return safety === \"Safe\" || safety === \"WorkspaceSafe\";\n}\n\n// ── Safety labels ──────────────────────────────────\n\n/** Human‑readable labels for each safety level. */\nexport const SAFETY_LABELS: Record<CommandSafety, string> = {\n Safe: \"安全(只读,无副作用)\",\n WorkspaceSafe: \"工作区安全(仅在项目内写入)\",\n RequiresApproval: \"需要审批\",\n Dangerous: \"危险(始终需要确认)\",\n};\n","/**\n * Unicode sanitization — remove invisible and control characters\n * that could be used for prompt injection attacks.\n *\n * All patterns use new RegExp() with \\\\uXXXX string escapes\n * to avoid filesystem encoding of literal Unicode characters.\n *\n * References:\n * - Unicode Technical Report #36 (Security Considerations)\n * - CWE-838: Inappropriate Encoding for Output Context\n */\n\n// ── Pattern definitions ──────────────────────────────\n\ninterface StripRule {\n /** Human label for the character class being stripped. */\n label: string;\n /** RegExp source string (uses \\\\uXXXX escapes). */\n source: string;\n /** RegExp flags. */\n flags: string;\n /** Replacement string. */\n replacement: string;\n}\n\nconst STRIP_RULES: readonly StripRule[] = [\n {\n label: \"zero-width spaces\",\n source: \"[\\\\u200B-\\\\u200F]\",\n flags: \"g\",\n replacement: \"\",\n },\n {\n label: \"bidi overrides\",\n source: \"[\\\\u202A-\\\\u202E]\",\n flags: \"g\",\n replacement: \"\",\n },\n {\n label: \"deprecated format chars\",\n source: \"[\\\\u2060-\\\\u2069]\",\n flags: \"g\",\n replacement: \"\",\n },\n {\n label: \"byte order mark\",\n source: \"\\\\uFEFF\",\n flags: \"g\",\n replacement: \"\",\n },\n {\n label: \"variation selectors\",\n source: \"[\\\\uFE00-\\\\uFE0F]\",\n flags: \"g\",\n replacement: \"\",\n },\n {\n label: \"soft hyphen\",\n source: \"\\\\u00AD\",\n flags: \"g\",\n replacement: \"\",\n },\n {\n label: \"line separator\",\n source: \"\\\\u2028\",\n flags: \"g\",\n replacement: \"\\n\",\n },\n {\n label: \"paragraph separator\",\n source: \"\\\\u2029\",\n flags: \"g\",\n replacement: \"\\n\\n\",\n },\n {\n label: \"interlinear annotation anchors\",\n source: \"[\\\\uFFF9-\\\\uFFFB]\",\n flags: \"g\",\n replacement: \"\",\n },\n // Tag characters U+E0001..U+E007F use surrogate pair 󠀁..󠁿.\n // Character class can't span surrogate pairs, so match the high surrogate\n // followed by a low surrogate range.\n {\n label: \"tag characters\",\n source: \"\\\\uDB40[\\\\uDC01-\\\\uDC7F]\",\n flags: \"gu\",\n replacement: \"\",\n },\n];\n\n// Cache\nlet _compiled: Array<{ regex: RegExp; replacement: string; label: string }> | null = null;\n\nfunction compiledRules(): Array<{ regex: RegExp; replacement: string; label: string }> {\n if (_compiled) return _compiled;\n _compiled = STRIP_RULES.map((rule) => ({\n regex: new RegExp(rule.source, rule.flags),\n replacement: rule.replacement,\n label: rule.label,\n }));\n return _compiled;\n}\n\n// ── Public API ────────────────────────────────────────\n\n/**\n * Strip invisible and potentially dangerous Unicode characters from text.\n *\n * Preserves CJK Unified ideographs, emoji, combining diacritical marks,\n * and other legitimate Unicode.\n */\nexport function sanitizeUnicode(input: string): string {\n let output = input;\n for (const { regex, replacement } of compiledRules()) {\n output = output.replace(regex, replacement);\n }\n return output;\n}\n\n/**\n * Check if a string contains any suspicious Unicode characters.\n *\n * Returns the code point of the first offending character, or null if clean.\n */\nexport function findSuspiciousChars(input: string): string | null {\n for (const { regex, label } of compiledRules()) {\n const fresh = new RegExp(regex.source, regex.flags);\n if (fresh.test(input)) {\n return label;\n }\n }\n return null;\n}\n","/**\n * Path traversal / jailbreak detection.\n *\n * Verifies that a resolved file path stays within the workspace root.\n * Also catches null-byte injection attacks that can truncate paths\n * in C‑based filesystem APIs.\n */\n\nimport { resolve } from \"node:path\";\nimport { realpathSync, existsSync } from \"node:fs\";\n\n// ── Constants ────────────────────────────────────────\n\nconst NULL_BYTE_PATTERN = /\\x00/;\n\n// ── Public API ────────────────────────────────────────\n\n/**\n * Check whether a file path is safely contained within the workspace root.\n *\n * Algorithm:\n * 1. Reject paths containing null bytes (truncation attack).\n * 2. Resolve to absolute path, eliminating `../` segments.\n * 3. Resolve symlinks to their real physical location.\n * 4. Verify the final path starts with the workspace root.\n *\n * @returns true if the path is safely inside the workspace.\n */\nexport function isPathSafe(filePath: string, workspaceRoot: string): boolean {\n // Null‑byte injection — path is truncated at \\x00 in C APIs\n if (NULL_BYTE_PATTERN.test(filePath)) return false;\n\n const absolute = resolve(filePath);\n const wsRoot = resolve(workspaceRoot);\n\n // Check resolved path (handles ../ and .)\n if (!absolute.startsWith(wsRoot)) return false;\n\n // If the file already exists, also check the real path\n // (resolves symlinks that could point outside the workspace)\n try {\n if (existsSync(absolute)) {\n const real = realpathSync(absolute);\n return real.startsWith(wsRoot);\n }\n } catch {\n // realpath fails on broken symlinks — treat as unsafe\n return false;\n }\n\n return true;\n}\n\n/**\n * Returns the violation detail when a path escapes the workspace,\n * or null if the path is safe.\n *\n * Useful for audit logging and user‑facing error messages.\n */\nexport function getPathViolation(\n filePath: string,\n workspaceRoot: string,\n): { reason: string; resolved: string } | null {\n if (NULL_BYTE_PATTERN.test(filePath)) {\n return { reason: \"path contains null byte\", resolved: filePath };\n }\n\n const absolute = resolve(filePath);\n const wsRoot = resolve(workspaceRoot);\n\n if (!absolute.startsWith(wsRoot)) {\n return {\n reason: `resolved path \"${absolute}\" is outside workspace \"${wsRoot}\"`,\n resolved: absolute,\n };\n }\n\n try {\n if (existsSync(absolute)) {\n const real = realpathSync(absolute);\n if (!real.startsWith(wsRoot)) {\n return {\n reason: `real path \"${real}\" escapes workspace via symlink`,\n resolved: real,\n };\n }\n }\n } catch {\n return { reason: \"broken symlink\", resolved: absolute };\n }\n\n return null;\n}\n","/**\n * Trusted command whitelist — commands that are safe to execute\n * without interactive user confirmation.\n *\n * These are read‑only or read‑heavy commands that don't modify\n * the filesystem or network. Even in `--yolo` mode, commands\n * not on this list still go through safety escalation.\n */\n\n// ── Whitelist — sorted alphabetically ─────────────────\n\nconst TRUSTED_COMMANDS = new Set([\n \"bat\",\n \"cat\",\n \"df\",\n \"dir\", // Windows\n \"du\",\n \"echo\",\n \"env\",\n \"fd\",\n \"file\",\n \"find\",\n \"get-command\", // PowerShell\n \"grep\",\n \"head\",\n \"hostname\",\n \"less\",\n \"ls\",\n \"node\",\n \"pwd\",\n \"rg\",\n \"stat\",\n \"tail\",\n \"type\",\n \"uname\",\n \"wc\",\n \"where\",\n \"whereis\",\n \"which\",\n \"whoami\",\n]);\n\n// Sub‑command allowlist for commands whose safety depends on the sub‑command\nconst TRUSTED_SUBCOMMANDS: ReadonlyMap<string, Set<string>> = new Map([\n [\n \"git\",\n new Set([\n \"log\",\n \"status\",\n \"diff\",\n \"show\",\n \"branch\",\n \"tag\",\n \"rev-parse\",\n \"rev-list\",\n \"ls-files\",\n \"ls-tree\",\n \"describe\",\n \"shortlog\",\n \"stash\",\n \"blame\",\n ]),\n ],\n [\"npm\", new Set([\"list\", \"ls\", \"view\", \"info\", \"outdated\"])],\n [\"pnpm\", new Set([\"list\", \"ls\", \"view\", \"info\", \"outdated\", \"why\"])],\n]);\n\n// ── Public API ────────────────────────────────────────\n\n/**\n * Check if a command is on the trusted whitelist.\n *\n * For commands with sub‑command gating (git, npm, pnpm),\n * the first argument is checked against allowed sub‑commands.\n */\nexport function isTrustedCommand(command: string, args: string[] = []): boolean {\n // Direct match\n if (TRUSTED_COMMANDS.has(command)) return true;\n\n // Sub‑command match\n const allowed = TRUSTED_SUBCOMMANDS.get(command);\n if (allowed) {\n const sub = args[0];\n if (sub && allowed.has(sub)) return true;\n }\n\n // Version checks are always safe\n if (args.includes(\"--version\") || args.includes(\"-v\") || args.includes(\"-V\")) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Get the list of all trusted base commands (for display in help/config).\n */\nexport function getTrustedCommands(): ReadonlySet<string> {\n return TRUSTED_COMMANDS;\n}\n\n/**\n * Get trusted sub‑commands for a given base command.\n */\nexport function getTrustedSubcommands(command: string): ReadonlySet<string> | undefined {\n return TRUSTED_SUBCOMMANDS.get(command);\n}\n","/**\n * Blocked command blacklist — commands that are ALWAYS rejected\n * regardless of permission mode (including `--yolo`).\n *\n * These patterns match destructive or privilege‑escalation operations\n * that should never run through an AI agent.\n */\n\n// ── Blocklist — regex patterns ────────────────────────\n\ninterface BlockedPattern {\n /** Human‑readable reason for the block. */\n reason: string;\n /** Regex tested against the full command string (command + args). */\n pattern: RegExp;\n}\n\nconst BLOCKED_PATTERNS: readonly BlockedPattern[] = [\n {\n reason: \"cannot erase root filesystem\",\n pattern: /\\brm\\s+-rf\\s+\\/\\b/i,\n },\n {\n reason: \"cannot write raw disk devices\",\n pattern: /\\bdd\\s+if=/i,\n },\n {\n reason: \"cannot format filesystems\",\n pattern: /\\bmkfs\\./i,\n },\n {\n reason: \"cannot overwrite block devices\",\n pattern: />\\s*\\/dev\\/sd[a-z]/i,\n },\n {\n reason: \"cannot elevate privileges\",\n pattern: /\\bsudo\\b/i,\n },\n {\n reason: \"cannot switch user\",\n pattern: /\\bsu\\b(?:\\s+-)?/i,\n },\n {\n reason: \"cannot elevate via doas\",\n pattern: /\\bdoas\\b/i,\n },\n {\n reason: \"cannot make world‑writable files\",\n pattern: /\\bchmod\\s+777\\b/i,\n },\n {\n reason: \"cannot recursively chown root directory\",\n pattern: /\\bchown\\s+-R\\b.*\\s+\\//i,\n },\n {\n reason: \"cannot pipe curl to shell\",\n pattern: /\\bcurl\\b.*\\|\\s*(?:sh|bash)\\b/i,\n },\n {\n reason: \"cannot pipe wget to shell\",\n pattern: /\\bwget\\b.*\\|\\s*(?:sh|bash)\\b/i,\n },\n {\n reason: \"cannot force push to main/master\",\n pattern: /\\bgit\\s+push\\s+--force\\b.*\\b(?:main|master)\\b/i,\n },\n {\n reason: \"cannot delete git repository data\",\n pattern: /\\bgit\\s+reflog\\s+expire\\b/i,\n },\n {\n reason: \"cannot hard reset from remote\",\n pattern: /\\bgit\\s+reset\\s+--hard\\s+origin\\//i,\n },\n];\n\n// ── Public API ────────────────────────────────────────\n\n/**\n * Check if a command string matches any blocked pattern.\n *\n * @returns The block reason if blocked, or null if safe.\n */\nexport function isBlockedCommand(\n command: string,\n args: string[] = [],\n): { blocked: true; reason: string } | { blocked: false } {\n // Build the full command line for regex matching\n const fullCommand = args.length > 0 ? `${command} ${args.join(\" \")}` : command;\n\n for (const entry of BLOCKED_PATTERNS) {\n if (entry.pattern.test(fullCommand)) {\n return { blocked: true, reason: entry.reason };\n }\n }\n\n return { blocked: false };\n}\n\n/**\n * Get all blocked patterns for display in help/config/audit.\n */\nexport function getBlockedPatterns(): ReadonlyArray<{ reason: string; pattern: string }> {\n return BLOCKED_PATTERNS.map((p) => ({\n reason: p.reason,\n pattern: p.pattern.source,\n }));\n}\n","/**\n * Secret / key redaction — detect and redact sensitive credentials\n * from output before displaying to the user or logging.\n *\n * This is a defense‑in‑depth layer. The primary defense is never\n * reading .env / secret files, but if a secret leaks into output\n * (e.g. from a tool result or LLM response), we redact it here.\n */\n\n// ── Detection patterns ────────────────────────────────\n\ninterface SecretPattern {\n /** Human label for audit logging. */\n label: string;\n /** Regex to match the secret. */\n pattern: RegExp;\n /**\n * How to redact. \"partial\" keeps first 4 + last 4 chars;\n * \"full\" replaces the entire match.\n */\n mode: \"partial\" | \"full\";\n}\n\nconst SECRET_PATTERNS: readonly SecretPattern[] = [\n {\n label: \"OpenAI API key\",\n pattern: /sk-(?:proj-)?[A-Za-z0-9]{20,}/g,\n mode: \"partial\",\n },\n {\n label: \"DeepSeek API key\",\n pattern: /dsk-[A-Za-z0-9]{20,}/g,\n mode: \"partial\",\n },\n {\n label: \"Anthropic API key\",\n pattern: /sk-ant-(?:api\\d{2}-)?[A-Za-z0-9_-]{20,}/g,\n mode: \"partial\",\n },\n {\n label: \"GitHub token\",\n pattern: /gh[poiurse]_[A-Za-z0-9_]{36,}/g,\n mode: \"partial\",\n },\n {\n label: \"GitHub PAT\",\n pattern: /github_pat_[A-Za-z0-9_]{36,}/g,\n mode: \"partial\",\n },\n {\n label: \"AWS access key\",\n pattern: /AKIA[0-9A-Z]{16}/g,\n mode: \"partial\",\n },\n {\n label: \"AWS secret key\",\n pattern: /(?<=AWS_SECRET_ACCESS_KEY[=:])\\s*\\S+/gi,\n mode: \"full\",\n },\n {\n label: \"JWT token\",\n pattern: /eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+/g,\n mode: \"partial\",\n },\n {\n label: \"Private key header\",\n pattern: /-----BEGIN (?:RSA|EC|OPENSSH|DSA|PRIVATE) KEY-----/g,\n mode: \"full\",\n },\n {\n label: \"Generic base64 token\",\n pattern:\n /(?:(?:api_?key|auth_?token|access_?token|secret|password|apikey)[=:]\\s*)([A-Za-z0-9+/]{32,}={0,2})/gi,\n mode: \"full\",\n },\n];\n\n// ── Helpers ──────────────────────────────────────────\n\nfunction redactPartial(match: string): string {\n if (match.length < 8) return \"***\";\n return match.slice(0, 4) + \"...\" + match.slice(-4);\n}\n\n// ── Public API ────────────────────────────────────────\n\n/**\n * Redact all detected secrets from the given text.\n *\n * @returns The text with secrets replaced by `[REDACTED]` or `sk-...XyZ1`.\n */\nexport function redactSecrets(text: string): string {\n let result = text;\n for (const { pattern, mode } of SECRET_PATTERNS) {\n result = result.replace(pattern, (match) =>\n mode === \"partial\" ? redactPartial(match) : \"[REDACTED]\",\n );\n }\n return result;\n}\n\n/**\n * Scan text for secrets without redacting.\n *\n * @returns Array of detected secret labels (for audit/alerting).\n */\nexport function detectSecrets(text: string): string[] {\n const found: string[] = [];\n for (const { label, pattern } of SECRET_PATTERNS) {\n // Create a fresh regex to avoid stateful lastIndex issues\n const fresh = new RegExp(pattern.source, pattern.flags);\n if (fresh.test(text)) {\n found.push(label);\n }\n }\n return found;\n}\n\n/**\n * Check if the given text contains any detected secrets.\n */\nexport function hasSecrets(text: string): boolean {\n return detectSecrets(text).length > 0;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["e","descriptor","handler","descriptor","handler","descriptor","handler","countOccurrences","descriptor","handler","descriptor","handler","descriptor","cache","CACHE_TTL_MS","handler","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","SECRET_PATTERNS","handler","descriptor","handler","descriptor","handler","handleStatus","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","handler","STORAGE_DIR","STORAGE_FILE","init","persist","descriptor","handler","handleList","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","handler","descriptor","descriptor","descriptor","readFileDesc","readFileHandler","writeFileDesc","writeFileHandler","editFileDesc","editFileHandler","globDesc","globHandler","grepDesc","grepHandler","webFetchDesc","webFetchHandler","webSearchDesc","webSearchHandler","todoWriteDesc","todoWriteHandler","powershellDesc","powershellHandler","notebookEditDesc","notebookEditHandler","secretScanDesc","secretScanHandler","lspDesc","lspHandler","replDesc","replHandler","agentDesc","agentHandler","taskDesc","taskHandler","teamCreateDesc","teamCreateHandler","teamDeleteDesc","teamDeleteHandler","verifyPlanDesc","verifyPlanHandler","remoteTriggerDesc","remoteTriggerHandler","scheduleCronDesc","scheduleCronHandler","workflowDesc","workflowHandler","tungstenDesc","tungstenHandler","enterPlanModeDesc","enterPlanModeHandler","exitPlanModeDesc","exitPlanModeHandler","enterWorktreeDesc","enterWorktreeHandler","exitWorktreeDesc","exitWorktreeHandler","configToolDesc","configToolHandler","askUserDesc","askUserHandler","briefDesc","briefHandler","syntheticOutputDesc","syntheticOutputHandler","sleepDesc","sleepHandler","_compiled","compiledRules"],"sources":["../src/availability.ts","../src/registry.ts","../src/builtin/files/read-file.ts","../src/builtin/files/write-file.ts","../src/builtin/files/edit-file.ts","../src/builtin/files/glob.ts","../src/builtin/files/grep.ts","../src/builtin/files/web-fetch.ts","../src/builtin/files/web-search.ts","../src/builtin/files/todo-write.ts","../src/builtin/files/powershell.ts","../src/builtin/files/notebook-edit.ts","../src/builtin/files/secret-scan.ts","../src/builtin/files/lsp.ts","../src/builtin/files/repl.ts","../src/builtin/agent/agent.ts","../src/builtin/agent/task.ts","../src/builtin/agent/team-create.ts","../src/builtin/agent/team-delete.ts","../src/builtin/agent/verify-plan.ts","../src/builtin/agent/remote-trigger.ts","../src/builtin/agent/schedule-cron.ts","../src/builtin/agent/workflow.ts","../src/builtin/agent/tungsten.ts","../src/builtin/mode/enter-plan-mode.ts","../src/builtin/mode/exit-plan-mode.ts","../src/builtin/mode/enter-worktree.ts","../src/builtin/mode/exit-worktree.ts","../src/builtin/mode/config-tool.ts","../src/builtin/interact/ask-user-question.ts","../src/builtin/interact/brief.ts","../src/builtin/interact/synthetic-output.ts","../src/builtin/interact/sleep.ts","../src/builtin/memory/memory-write.ts","../src/builtin/mcp/mcp-auth.ts","../src/builtin/interact/send-message.ts","../src/builtin/index.ts","../src/planner.ts","../src/safety/sensitive.ts","../src/safety.ts","../src/safety/sanitize.ts","../src/safety/path-check.ts","../src/safety/trusted-cmd.ts","../src/safety/blocked-cmd.ts","../src/safety/redact.ts"],"sourcesContent":["/**\n * Availability expression evaluator.\n *\n * Each {@link AvailabilityExpr} is a pure expression tree.\n * The evaluator walks the tree against an {@link EvalContext} that\n * provides the runtime environment state.\n */\n\nimport type { AvailabilityExpr } from \"./types.js\";\n\n// ── Evaluation context ─────────────────────────────\n\n/**\n * Snapshot of the runtime environment passed to the availability evaluator.\n * Updated each turn before `buildToolPlan()` runs.\n */\nexport interface EvalContext {\n /** Current platform (\"windows\" | \"linux\"). */\n platform: \"windows\" | \"linux\";\n /** Current permission mode (from the session). */\n sessionMode: string;\n /** Enabled feature flags. */\n flags: Set<string>;\n /** Settings/configuration values keyed by dot‑path. */\n settings: Record<string, unknown>;\n /** Environment variable overrides. */\n env: Record<string, string>;\n /** Connected MCP server names. */\n connectedMcpServers: Set<string>;\n /** Loaded plugin ids. */\n loadedPlugins: Set<string>;\n}\n\n// ── Leaf evaluators ──────────────────────────────\n\ntype EvalResult = { available: boolean; reason?: string };\ntype EvalFn = (expr: AvailabilityExpr, ctx: EvalContext) => EvalResult;\n\nfunction evalAlways(): EvalResult {\n return { available: true };\n}\n\nfunction evalNever(expr: AvailabilityExpr): EvalResult {\n return { available: false, reason: (expr as { reason: string }).reason };\n}\n\nfunction evalEnv(expr: AvailabilityExpr, ctx: EvalContext): EvalResult {\n const e = expr as { key: string; equals: string };\n return { available: ctx.env[e.key] === e.equals };\n}\n\nfunction evalSetting(expr: AvailabilityExpr, ctx: EvalContext): EvalResult {\n const e = expr as { path: string; equals: unknown };\n return { available: getSetting(ctx.settings, e.path) === e.equals };\n}\n\nfunction evalFlag(expr: AvailabilityExpr, ctx: EvalContext): EvalResult {\n return { available: ctx.flags.has((expr as { flag: string }).flag) };\n}\n\nfunction evalPlatform(expr: AvailabilityExpr, ctx: EvalContext): EvalResult {\n return { available: ctx.platform === (expr as { platform: string }).platform };\n}\n\nfunction evalMcpConnected(expr: AvailabilityExpr, ctx: EvalContext): EvalResult {\n return { available: ctx.connectedMcpServers.has((expr as { serverName: string }).serverName) };\n}\n\nfunction evalHasPlugin(expr: AvailabilityExpr, ctx: EvalContext): EvalResult {\n return { available: ctx.loadedPlugins.has((expr as { pluginId: string }).pluginId) };\n}\n\nfunction evalSessionMode(expr: AvailabilityExpr, ctx: EvalContext): EvalResult {\n return { available: ctx.sessionMode === (expr as { mode: string }).mode };\n}\n\nfunction evalAll(expr: AvailabilityExpr, ctx: EvalContext): EvalResult {\n const e = expr as { exprs: AvailabilityExpr[] };\n for (const sub of e.exprs) {\n const result = evaluateAvailability(sub, ctx);\n if (!result.available) return result;\n }\n return { available: true };\n}\n\nfunction evalAny(expr: AvailabilityExpr, ctx: EvalContext): EvalResult {\n const e = expr as { exprs: AvailabilityExpr[] };\n const reasons: string[] = [];\n for (const sub of e.exprs) {\n const result = evaluateAvailability(sub, ctx);\n if (result.available) return { available: true };\n if (result.reason) reasons.push(result.reason);\n }\n return {\n available: false,\n reason: reasons.length > 0 ? reasons.join(\"; \") : \"no condition matched\",\n };\n}\n\nfunction evalNot(expr: AvailabilityExpr, ctx: EvalContext): EvalResult {\n const e = expr as { expr: AvailabilityExpr };\n const inner = evaluateAvailability(e.expr, ctx);\n return {\n available: !inner.available,\n reason: inner.available ? undefined : inner.reason,\n };\n}\n\nconst LEAF_EVALUATORS: Record<string, EvalFn> = {\n always: evalAlways,\n never: evalNever,\n env: evalEnv,\n setting: evalSetting,\n flag: evalFlag,\n platform: evalPlatform,\n mcp_connected: evalMcpConnected,\n has_plugin: evalHasPlugin,\n session_mode: evalSessionMode,\n all: evalAll,\n any: evalAny,\n not: evalNot,\n};\n\n// ── Public API ─────────────────────────────────────\n\n/**\n * Evaluate an availability expression against the current context.\n *\n * Returns `{ available: true }` or `{ available: false, reason: string }`.\n *\n * ```ts\n * const result = evaluateAvailability(expr, ctx);\n * if (!result.available) {\n * console.log(`Tool hidden because: ${result.reason}`);\n * }\n * ```\n */\nexport function evaluateAvailability(\n expr: AvailabilityExpr,\n ctx: EvalContext,\n): { available: boolean; reason?: string } {\n const evaluator = LEAF_EVALUATORS[expr.type];\n if (evaluator) {\n return evaluator(expr, ctx);\n }\n return {\n available: false,\n reason: `unknown expression type: ${expr.type}`,\n };\n}\n\n// ── Helpers ────────────────────────────────────────\n\n/** Navigate a dot‑path into a settings object. */\nfunction getSetting(settings: Record<string, unknown>, path: string): unknown {\n const parts = path.split(\".\");\n let current: unknown = settings;\n for (const part of parts) {\n if (current === null || current === undefined) return undefined;\n if (typeof current !== \"object\") return undefined;\n current = (current as Record<string, unknown>)[part];\n }\n return current;\n}\n","/**\n * ToolRegistry — central registration and lookup for all tools.\n *\n * Tools are registered by plugins during startup and the registry stays\n * immutable for the session lifetime. Lookups are O(1) by name and O(1)\n * by executor key.\n */\n\nimport { ToolError } from \"@24klynx/core\";\nimport type { ToolDescriptor, ToolHandler, ToolExecutorRef } from \"./types.js\";\n\n// ── Public API ─────────────────────────────────────\n\n/**\n * In‑memory registry of all registered tools and their handlers.\n *\n * Create one instance per process in the bootstrap phase.\n */\nexport interface ToolRegistry {\n /** Register a tool descriptor and its handler. */\n register(descriptor: ToolDescriptor, handler: ToolHandler): void;\n\n /** Look up a descriptor by name. Returns undefined if not found. */\n resolve(name: string): ToolDescriptor | undefined;\n\n /** Look up a handler by executor key. Throws if not registered. */\n resolveExecutor(descriptor: ToolDescriptor): ToolHandler;\n\n /** Return every registered descriptor. */\n listAll(): ToolDescriptor[];\n\n /** Return the total number of registered tools. */\n count(): number;\n}\n\n/**\n * Create a new empty ToolRegistry.\n */\nexport function createToolRegistry(): ToolRegistry {\n const descriptors = new Map<string, ToolDescriptor>();\n // A single handler may serve multiple descriptors (e.g. bash → bash handler)\n const handlers = new Map<ToolExecutorRef, ToolHandler>();\n\n const registry: ToolRegistry = {\n register(descriptor: ToolDescriptor, handler: ToolHandler): void {\n if (descriptors.has(descriptor.name)) {\n throw new ToolError(`Tool \"${descriptor.name}\" is already registered`, {\n recoverable: false,\n retryable: false,\n userVisible: false,\n diagnosticHint: \"tool_duplicate_name\",\n });\n }\n\n descriptors.set(descriptor.name, descriptor);\n\n if (!handlers.has(descriptor.executor)) {\n handlers.set(descriptor.executor, handler);\n }\n },\n\n resolve(name: string): ToolDescriptor | undefined {\n return descriptors.get(name);\n },\n\n resolveExecutor(descriptor: ToolDescriptor): ToolHandler {\n const handler = handlers.get(descriptor.executor);\n if (!handler) {\n throw new ToolError(\n `No handler registered for executor \"${descriptor.executor}\" (tool: \"${descriptor.name}\")`,\n {\n recoverable: false,\n retryable: false,\n userVisible: false,\n diagnosticHint: \"tool_missing_handler\",\n },\n );\n }\n return handler;\n },\n\n listAll(): ToolDescriptor[] {\n return [...descriptors.values()];\n },\n\n count(): number {\n return descriptors.size;\n },\n };\n\n return registry;\n}\n","/**\n * read_file — Read file contents from the filesystem.\n *\n * Limits: 2000 lines per call, binary files return MIME + base64.\n */\nimport { readFile, stat } from \"node:fs/promises\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"read_file\",\n description:\n \"读取文件内容。支持 offset/limit 分页。二进制和图片文件以 base64 编码数据加 MIME 类型返回。\",\n inputSchema: {\n type: \"object\",\n properties: {\n file_path: { type: \"string\", description: \"要读取的文件绝对路径\" },\n offset: { type: \"integer\", description: \"起始行号(从 1 开始)\" },\n limit: { type: \"integer\", description: \"最多读取行数\" },\n },\n required: [\"file_path\"],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:read_file\",\n owner: \"core\",\n};\n\nconst MAX_LINES = 2000;\nconst TEXT_EXTENSIONS = new Set([\n \".ts\",\n \".tsx\",\n \".js\",\n \".jsx\",\n \".json\",\n \".md\",\n \".txt\",\n \".yml\",\n \".yaml\",\n \".css\",\n \".html\",\n \".xml\",\n \".svg\",\n \".py\",\n \".rs\",\n \".go\",\n \".java\",\n \".sh\",\n \".bash\",\n \".zsh\",\n \".fish\",\n \".toml\",\n \".ini\",\n \".cfg\",\n \".env\",\n \".gitignore\",\n \".editorconfig\",\n \".c\",\n \".h\",\n \".cpp\",\n \".hpp\",\n \".rb\",\n \".php\",\n \".sql\",\n \".graphql\",\n \".proto\",\n \".vue\",\n \".svelte\",\n \".astro\",\n]);\n\nfunction isTextExtension(filePath: string): boolean {\n const ext = filePath.slice(filePath.lastIndexOf(\".\")).toLowerCase();\n return TEXT_EXTENSIONS.has(ext);\n}\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { file_path, offset, limit } = invocation.payload as {\n file_path: string;\n offset?: number;\n limit?: number;\n };\n\n const startTime = Date.now();\n\n // Check abort before I/O\n if (signal.aborted) {\n return {\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n const fileStat = await stat(file_path);\n\n if (!fileStat.isFile()) {\n return {\n success: false,\n content: `不是文件: ${file_path}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (fileStat.size > 10 * 1024 * 1024) {\n return {\n success: false,\n content: `文件过大 (${(fileStat.size / 1024 / 1024).toFixed(1)}MB)。请使用 offset/limit 分段读取。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (!isTextExtension(file_path)) {\n // Binary file — return MIME + base64\n const buf = await readFile(file_path);\n const mime = guessMime(file_path);\n const b64 = buf.toString(\"base64\");\n const truncated = b64.length > 50000;\n return {\n success: true,\n content: `[${mime}] base64 数据 (${buf.length} 字节):\\n${truncated ? b64.slice(0, 49997) + \"...\" : b64}`,\n metadata: { durationMs: Date.now() - startTime, truncated },\n };\n }\n\n const raw = await readFile(file_path, \"utf-8\");\n const lines = raw.split(\"\\n\");\n const startLine = (offset ?? 1) - 1;\n const endLine = limit ? startLine + limit : startLine + MAX_LINES;\n const slice = lines.slice(startLine, endLine);\n\n const truncated = endLine < lines.length;\n let content = slice.join(\"\\n\");\n\n if (truncated) {\n content += `\\n\\n[已截断 — 剩余 ${lines.length - endLine} 行。使用 offset=${endLine + 1} 继续读取。]`;\n }\n\n return {\n success: true,\n content,\n metadata: {\n durationMs: Date.now() - startTime,\n truncated,\n truncatedAt: truncated ? endLine : undefined,\n },\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return {\n success: false,\n content: `文件未找到: ${file_path}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n if ((err as NodeJS.ErrnoException).code === \"EACCES\") {\n return {\n success: false,\n content: `权限不足: ${file_path}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n return {\n success: false,\n content: `读取文件失败: ${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n },\n};\n\nfunction guessMime(filePath: string): string {\n const ext = filePath.slice(filePath.lastIndexOf(\".\")).toLowerCase();\n const map: Record<string, string> = {\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".svg\": \"image/svg+xml\",\n \".webp\": \"image/webp\",\n \".pdf\": \"application/pdf\",\n \".zip\": \"application/zip\",\n \".gz\": \"application/gzip\",\n \".mp3\": \"audio/mpeg\",\n \".wav\": \"audio/wav\",\n \".mp4\": \"video/mp4\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n \".ttf\": \"font/ttf\",\n \".ico\": \"image/x-icon\",\n \".bin\": \"application/octet-stream\",\n };\n return map[ext] ?? \"application/octet-stream\";\n}\n","/**\n * write_file — Create or overwrite a file with content.\n *\n * Creates parent directories automatically. Overwrites existing files\n * without asking (permission pipeline handles safety).\n */\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"write_file\",\n description: \"创建新文件或完全覆盖已有文件。父目录不存在时会自动创建。\",\n inputSchema: {\n type: \"object\",\n properties: {\n file_path: { type: \"string\", description: \"要写入的文件绝对路径\" },\n content: { type: \"string\", description: \"要写入文件的内容\" },\n },\n required: [\"file_path\", \"content\"],\n },\n kind: \"WritesFiles\",\n safety: \"WorkspaceSafe\",\n availability: { type: \"always\" },\n executor: \"core:write_file\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { file_path, content } = invocation.payload as {\n file_path: string;\n content: string;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n await mkdir(dirname(file_path), { recursive: true });\n await writeFile(file_path, content, \"utf-8\");\n\n return {\n success: true,\n content: `已写入 ${content.length} 字节到 ${file_path}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `写入文件失败: ${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n },\n};\n","/**\n * edit_file — Exact string replacement in an existing file.\n *\n * `old_string` must match EXACTLY once in the file (or use replace_all).\n * This is the primary editing tool — LLMs should use it instead of write_file\n * for targeted changes.\n */\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"edit_file\",\n description:\n \"在文件中执行精确字符串替换。old_string 必须在文件中精确匹配(包括空格和缩进),\" +\n \"除非设置 replace_all 为 true。\",\n inputSchema: {\n type: \"object\",\n properties: {\n file_path: { type: \"string\", description: \"要编辑的文件绝对路径\" },\n old_string: {\n type: \"string\",\n description: \"要替换的精确文本 — 必须唯一匹配\",\n },\n new_string: { type: \"string\", description: \"替换后的新文本\" },\n replace_all: {\n type: \"boolean\",\n description: \"替换所有匹配项(而非仅第一个)\",\n },\n },\n required: [\"file_path\", \"old_string\", \"new_string\"],\n },\n kind: \"WritesFiles\",\n safety: \"WorkspaceSafe\",\n availability: { type: \"always\" },\n executor: \"core:edit_file\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { file_path, old_string, new_string, replace_all } = invocation.payload as {\n file_path: string;\n old_string: string;\n new_string: string;\n replace_all?: boolean;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (old_string === new_string) {\n return {\n success: false,\n content: \"old_string 与 new_string 相同 — 未做任何更改\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n const original = await readFile(file_path, \"utf-8\");\n\n const count = countOccurrences(original, old_string);\n if (count === 0) {\n return {\n success: false,\n content: `在 ${file_path} 中未找到 old_string。请确认文本精确匹配(包括缩进和空格)。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (count > 1 && !replace_all) {\n return {\n success: false,\n content: `old_string 在 ${file_path} 中出现了 ${count} 次。请设置 replace_all: true 替换所有匹配项,或提供更多上下文使匹配唯一。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const updated = replace_all\n ? original.replaceAll(old_string, new_string)\n : original.replace(old_string, new_string);\n\n await writeFile(file_path, updated, \"utf-8\");\n\n const changed = replace_all ? count : 1;\n return {\n success: true,\n content: `已在 ${file_path} 中替换 ${changed} 处`,\n metadata: { durationMs: Date.now() - startTime },\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return {\n success: false,\n content: `文件未找到: ${file_path}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n return {\n success: false,\n content: `编辑文件失败: ${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n },\n};\n\nfunction countOccurrences(haystack: string, needle: string): number {\n if (needle.length === 0) return 0;\n let count = 0;\n let pos = 0;\n while ((pos = haystack.indexOf(needle, pos)) !== -1) {\n count++;\n pos += needle.length;\n }\n return count;\n}\n","/**\n * glob — Fast file pattern matching.\n *\n * Returns sorted absolute paths. Default excludes: node_modules, .git, dist, build.\n */\nimport { readdir } from \"node:fs/promises\";\nimport { join, relative, resolve } from \"node:path\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"glob\",\n description: \"用 glob 模式匹配文件。返回排序后的绝对路径。\" + \"支持 ** 递归匹配、* 通配符。\",\n inputSchema: {\n type: \"object\",\n properties: {\n pattern: {\n type: \"string\",\n description: '要匹配的 glob 模式(如 \"**/*.ts\" 或 \"src/**/*.test.ts\")',\n },\n path: { type: \"string\", description: \"搜索的根目录(默认为当前工作目录)\" },\n },\n required: [\"pattern\"],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:glob\",\n owner: \"core\",\n};\n\nconst DEFAULT_EXCLUDE = new Set([\n \"node_modules\",\n \".git\",\n \"dist\",\n \"build\",\n \".next\",\n \"coverage\",\n \"__pycache__\",\n \".venv\",\n \"venv\",\n]);\nconst MAX_RESULTS = 10000;\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { pattern, path: rootPath } = invocation.payload as {\n pattern: string;\n path?: string;\n };\n\n const startTime = Date.now();\n const base = rootPath ? resolve(rootPath) : process.cwd();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n const results: string[] = [];\n await walk({ dir: base, pattern, base, results, signal, maxResults: MAX_RESULTS });\n\n const truncated = results.length >= MAX_RESULTS;\n let content = results.sort().join(\"\\n\");\n if (truncated) {\n content += `\\n\\n[已截断 — ${results.length}+ 条结果。请缩小匹配范围。]`;\n }\n\n return {\n success: true,\n content: content || \"(无匹配)\",\n metadata: { durationMs: Date.now() - startTime, truncated },\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `文件匹配失败: ${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n },\n};\n\n/** Options for the recursive {@link walk} function. */\ninterface WalkOptions {\n dir: string;\n pattern: string;\n base: string;\n results: string[];\n signal: AbortSignal;\n maxResults: number;\n}\n\nasync function walk(opts: WalkOptions): Promise<void> {\n if (opts.results.length >= opts.maxResults || opts.signal.aborted) return;\n\n let entries;\n try {\n entries = await readdir(opts.dir, { withFileTypes: true });\n } catch {\n return; // Permission denied, etc. — skip silently\n }\n\n for (const entry of entries) {\n if (opts.results.length >= opts.maxResults || opts.signal.aborted) break;\n if (DEFAULT_EXCLUDE.has(entry.name) || entry.name.startsWith(\".\")) continue;\n\n const full = join(opts.dir, entry.name);\n\n if (entry.isDirectory()) {\n await walk({ ...opts, dir: full });\n } else if (entry.isFile()) {\n const rel = relative(opts.base, full).replace(/\\\\/g, \"/\");\n if (matchGlob(rel, opts.pattern)) {\n opts.results.push(full);\n }\n }\n }\n}\n\nfunction matchGlob(filepath: string, pattern: string): boolean {\n // Simple glob matching: **, *, and literal segments\n const patParts = pattern.replace(/\\\\/g, \"/\").split(\"/\");\n const fpParts = filepath.split(\"/\");\n\n let pi = 0;\n let fi = 0;\n\n while (pi < patParts.length && fi < fpParts.length) {\n const pp = patParts[pi];\n const fp = fpParts[fi];\n\n if (pp === \"**\") {\n // ** matches zero or more path segments\n if (pi === patParts.length - 1) return true; // trailing ** matches everything\n pi++;\n // Try matching the rest at current and subsequent positions\n const restPat = patParts.slice(pi);\n for (let k = fi; k < fpParts.length; k++) {\n if (matchRest(fpParts.slice(k), restPat)) return true;\n }\n return false;\n }\n\n if (!matchSegment(fp, pp)) return false;\n pi++;\n fi++;\n }\n\n // Both exhausted → match\n return pi === patParts.length && fi === fpParts.length;\n}\n\nfunction matchRest(fpParts: string[], patParts: string[]): boolean {\n if (patParts.length === 0) return fpParts.length === 0;\n if (fpParts.length === 0) return patParts.every((p) => p === \"**\");\n if (patParts[0] === \"**\") return matchGlob(fpParts.join(\"/\"), patParts.join(\"/\"));\n if (!matchSegment(fpParts[0], patParts[0])) return false;\n return matchRest(fpParts.slice(1), patParts.slice(1));\n}\n\nfunction matchSegment(name: string, seg: string): boolean {\n if (seg === \"*\") return !name.includes(\"/\");\n // Convert glob segment to regex\n const regex = new RegExp(\n \"^\" +\n seg\n .replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n .replace(/\\*/g, \"[^/]*\")\n .replace(/\\?/g, \"[^/]\") +\n \"$\",\n );\n return regex.test(name);\n}\n","/**\n * grep — Regular expression content search (ripgrep-backed).\n *\n * Falls back to a pure-JS implementation when rg is not available.\n * Default head_limit=250 to prevent overwhelming output.\n */\nimport { type ChildProcess, execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nconst _execFileAsync = promisify(execFile);\n\n/** Options for {@link buildRgArgs}. */\ninterface BuildRgArgsOptions {\n pattern: string;\n path?: string;\n glob?: string;\n outputMode?: string;\n showLineNum?: boolean;\n caseInsensitive?: boolean;\n context?: number;\n}\n\n/** Collected output from a ripgrep stream. */\ninterface RgCollectedOutput {\n lines: string[];\n byteTruncated: boolean;\n}\n\nexport const descriptor: ToolDescriptor = {\n name: \"grep\",\n description: \"使用正则表达式搜索文件内容。\" + \"返回匹配行及可选的上下文。优先使用 ripgrep。\",\n inputSchema: {\n type: \"object\",\n properties: {\n pattern: { type: \"string\", description: \"要搜索的正则表达式\" },\n path: { type: \"string\", description: \"搜索的文件或目录(默认为当前工作目录)\" },\n glob: { type: \"string\", description: '用于过滤文件的 glob 模式(如 \"*.ts\")' },\n output_mode: {\n type: \"string\",\n enum: [\"content\", \"files_with_matches\", \"count\"],\n description:\n \"输出模式: content 显示匹配行, files_with_matches 显示文件路径, count 显示匹配计数\",\n },\n \"-n\": { type: \"boolean\", description: \"显示行号\" },\n \"-i\": { type: \"boolean\", description: \"忽略大小写\" },\n \"-C\": {\n type: \"integer\",\n description: \"匹配前后各显示的行数(上下文行数)\",\n },\n head_limit: { type: \"integer\", description: \"最大输出行数(默认: 250)\" },\n },\n required: [\"pattern\"],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:grep\",\n owner: \"core\",\n};\n\nconst DEFAULT_HEAD_LIMIT = 250;\nconst MAX_LINE_LENGTH = 1000;\nconst MAX_TOTAL_BYTES = 50_000;\n\n/**\n * Stream stdout from a ripgrep child process, collecting lines with\n * per-line length and total-byte limits enforced inline.\n */\nfunction collectRgLines(child: ChildProcess, limit: number): Promise<RgCollectedOutput> {\n return new Promise((resolve, reject) => {\n const collected: string[] = [];\n let lineCount = 0;\n let totalBytes = 0;\n let byteTruncated = false;\n\n const killIfAlive = () => {\n if (!child.killed) child.kill();\n };\n\n if (child.stdout) {\n let buffer = \"\";\n child.stdout.on(\"data\", (chunk: Buffer) => {\n buffer += chunk.toString(\"utf-8\");\n const rawLines = buffer.split(\"\\n\");\n buffer = rawLines.pop() ?? \"\";\n\n for (const raw of rawLines) {\n if (lineCount >= limit) {\n killIfAlive();\n break;\n }\n\n let l = raw;\n if (l.length > MAX_LINE_LENGTH) {\n l = l.slice(0, MAX_LINE_LENGTH) + \" [已截断]\";\n }\n\n const lineBytes = Buffer.byteLength(l, \"utf-8\") + 1;\n if (totalBytes + lineBytes > MAX_TOTAL_BYTES) {\n byteTruncated = true;\n killIfAlive();\n break;\n }\n\n collected.push(l);\n lineCount++;\n totalBytes += lineBytes;\n }\n });\n }\n\n child.on(\"close\", () => resolve({ lines: collected, byteTruncated }));\n child.on(\"error\", reject);\n });\n}\n\n/**\n * Build the final {@link ToolResult} from collected grep output.\n */\nfunction buildGrepResult(\n collected: string[],\n limit: number,\n byteTruncated: boolean,\n startTime: number,\n): ToolResult {\n const lineCount = collected.length;\n const truncated = lineCount >= limit || byteTruncated;\n const output = collected.join(\"\\n\");\n\n if (output.length === 0 && !truncated) {\n return {\n success: true,\n content: \"(无匹配)\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const suffix = truncated\n ? byteTruncated\n ? `\\n\\n[已截断 — 输出超过 ${MAX_TOTAL_BYTES} 字节。请缩小搜索范围。]`\n : `\\n\\n[已截断 — 达到 ${limit} 行限制。请缩小搜索范围。]`\n : \"\";\n\n return {\n success: true,\n content: output + suffix,\n metadata: {\n durationMs: Date.now() - startTime,\n truncated,\n truncatedAt: truncated ? limit : undefined,\n },\n };\n}\n\n/**\n * Classify an error thrown during ripgrep execution and return the\n * appropriate {@link ToolResult}, or `null` if the caller should\n * fall through to the JS fallback.\n */\nfunction classifyRgError(\n err: unknown,\n signal: AbortSignal | undefined,\n startTime: number,\n): ToolResult | null {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return null; // rg not installed — fall through\n }\n if ((err as { killed?: boolean }).killed) {\n return {\n success: false,\n content: \"搜索超时(30 秒)\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n if (signal?.aborted) {\n return {\n success: false,\n content: \"Operation cancelled\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n // rg exit code 1 = no matches (not an error)\n const stderr = (err as { stderr?: string }).stderr;\n if (stderr) {\n return {\n success: false,\n content: `grep 错误: ${stderr.slice(0, 500)}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n return {\n success: true,\n content: \"(no matches)\",\n metadata: { durationMs: Date.now() - startTime },\n };\n}\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const {\n pattern,\n path,\n glob,\n output_mode,\n \"-n\": showLineNum,\n \"-i\": caseInsensitive,\n \"-C\": context,\n head_limit,\n } = invocation.payload as {\n pattern: string;\n path?: string;\n glob?: string;\n output_mode?: \"content\" | \"files_with_matches\" | \"count\";\n \"-n\"?: boolean;\n \"-i\"?: boolean;\n \"-C\"?: number;\n head_limit?: number;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const limit = head_limit ?? DEFAULT_HEAD_LIMIT;\n\n // Try ripgrep first\n try {\n const args = buildRgArgs({\n pattern,\n path,\n glob,\n outputMode: output_mode,\n showLineNum,\n caseInsensitive,\n context,\n });\n const child = execFile(\"rg\", args, {\n cwd: process.cwd(),\n timeout: 30_000,\n maxBuffer: 10 * 1024 * 1024,\n signal,\n });\n\n const { lines, byteTruncated } = await collectRgLines(child, limit);\n return buildGrepResult(lines, limit, byteTruncated, startTime);\n } catch (err) {\n const classified = classifyRgError(err, signal, startTime);\n if (classified !== null) return classified;\n // ENOENT — fall through to JS fallback\n }\n\n // Fallback: ripgrep not available\n return {\n success: false,\n content:\n \"ripgrep (rg) 未安装。请安装 ripgrep 以支持 grep 功能: https://github.com/BurntSushi/ripgrep\",\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n\nfunction buildRgArgs(opts: BuildRgArgsOptions): string[] {\n const args: string[] = [\"--no-heading\", \"--color=never\"];\n\n if (opts.showLineNum !== false) args.push(\"--line-number\"); // default on\n if (opts.caseInsensitive) args.push(\"--ignore-case\");\n if (opts.context !== undefined) args.push(\"-C\", String(opts.context));\n if (opts.glob) args.push(\"--glob\", opts.glob);\n\n switch (opts.outputMode) {\n case \"files_with_matches\":\n args.push(\"-l\");\n break;\n case \"count\":\n args.push(\"--count\");\n break;\n default:\n break; // content mode\n }\n\n args.push(\"--\", opts.pattern);\n if (opts.path) args.push(opts.path);\n\n return args;\n}\n","/**\n * web_fetch — Fetch URL content and return it as plain text.\n *\n * HTTP → HTTPS upgrade. Cross-host redirects are returned to the caller.\n * Results cached for 15 minutes per URL.\n * HTML content is converted to plain text (tags stripped, entities decoded).\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\n// ── URL Allowlist ──────────────────────────────────────\n\n/** 约 50 个常用安全域名 */\nconst ALLOWED_DOMAINS = new Set([\n \"github.com\",\n \"gitlab.com\",\n \"npmjs.com\",\n \"pypi.org\",\n \"crates.io\",\n \"docs.rs\",\n \"stackoverflow.com\",\n \"wikipedia.org\",\n \"nodejs.org\",\n \"typescriptlang.org\",\n \"developer.mozilla.org\",\n \"anthropic.com\",\n \"openai.com\",\n \"googleapis.com\",\n \"eslint.org\",\n \"prettier.io\",\n \"jestjs.io\",\n \"vitest.dev\",\n \"playwright.dev\",\n \"docker.com\",\n \"kubernetes.io\",\n \"terraform.io\",\n \"redis.io\",\n \"postgresql.org\",\n \"mysql.com\",\n \"mongodb.com\",\n \"sqlite.org\",\n \"rust-lang.org\",\n \"golang.org\",\n \"python.org\",\n \"ruby-lang.org\",\n \"php.net\",\n \"java.com\",\n \"kernel.org\",\n \"archlinux.org\",\n \"ubuntu.com\",\n \"debian.org\",\n \"redhat.com\",\n \"aws.amazon.com\",\n \"cloud.google.com\",\n \"azure.microsoft.com\",\n \"reactjs.org\",\n \"vuejs.org\",\n \"angular.io\",\n \"svelte.dev\",\n \"nextjs.org\",\n \"nuxt.com\",\n \"tailwindcss.com\",\n \"vitejs.dev\",\n \"webpack.js.org\",\n \"babeljs.io\",\n]);\n\n/** 禁止访问的域名(本地、云元数据端点等) */\nconst BLOCKED_DOMAINS = new Set([\n \"localhost\",\n \"127.0.0.1\",\n \"0.0.0.0\",\n \"::1\",\n \"metadata.google.internal\",\n \"169.254.169.254\",\n]);\n\n/** IPv4 地址正则 */\nconst IPV4_RE = /^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/;\n\n/**\n * 检查 URL 是否在允许访问的范围内。\n *\n * 规则(按优先级):\n * 1. URL 解析失败 → 拒绝\n * 2. IP 地址 → 拒绝\n * 3. 被阻止的域名 → 拒绝\n * 4. .local / .internal TLD → 拒绝\n * 5. URL 中包含 userinfo(username:password@host)→ 拒绝\n * 6. 域名在允许列表中(去除 www. 前缀后匹配,支持子域名通配)→ 允许\n * 7. 默认 → 拒绝\n */\nexport function isUrlAllowed(url: string): { allowed: boolean; reason: string } {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n return { allowed: false, reason: `URL 解析失败: ${url}` };\n }\n\n const host = parsed.hostname.toLowerCase();\n\n // 阻止 IP 地址\n if (IPV4_RE.test(host) || host === \"::1\") {\n return { allowed: false, reason: `不允许访问 IP 地址: ${host}` };\n }\n\n // 阻止被禁域名\n if (BLOCKED_DOMAINS.has(host)) {\n return { allowed: false, reason: `不允许访问该域名: ${host}` };\n }\n\n // 阻止 .local 和 .internal TLD\n if (host.endsWith(\".local\") || host.endsWith(\".internal\")) {\n return { allowed: false, reason: `不允许访问本地/内部域名: ${host}` };\n }\n\n // 阻止 URL 中包含 userinfo\n if (parsed.username || parsed.password) {\n return { allowed: false, reason: \"URL 中包含认证信息(username:password),已拒绝\" };\n }\n\n // 检查允许列表(去除 www. 前缀后匹配)\n const strippedHost = host.startsWith(\"www.\") ? host.slice(4) : host;\n if (ALLOWED_DOMAINS.has(strippedHost)) {\n return { allowed: true, reason: \"\" };\n }\n\n // 子域名通配:检查父域名是否在允许列表中\n const parts = strippedHost.split(\".\");\n for (let i = 1; i < parts.length; i++) {\n const parentDomain = parts.slice(i).join(\".\");\n if (ALLOWED_DOMAINS.has(parentDomain)) {\n return { allowed: true, reason: \"\" };\n }\n }\n\n return {\n allowed: false,\n reason: `域名 \"${host}\" 不在允许列表中。如需访问请联系用户确认。`,\n };\n}\n\nexport const descriptor: ToolDescriptor = {\n name: \"web_fetch\",\n description:\n \"从 URL 获取内容并以文本形式返回。\" +\n \"HTTP 自动升级为 HTTPS。跨域重定向会返回给调用方而非自动跟随。\" +\n \"每个 URL 的结果缓存 15 分钟。HTML 内容会转换为纯文本。\",\n inputSchema: {\n type: \"object\",\n properties: {\n url: { type: \"string\", format: \"uri\", description: \"要获取内容的 URL\" },\n maxChars: {\n type: \"integer\",\n description: \"返回的最大字符数(默认: 50000)\",\n },\n },\n required: [\"url\"],\n },\n kind: \"Network\",\n safety: \"RequiresApproval\",\n availability: { type: \"always\" },\n executor: \"core:web_fetch\",\n owner: \"core\",\n};\n\n// Simple in-memory cache: url → { content, timestamp }\nconst cache = new Map<string, { content: string; ts: number }>();\nconst CACHE_TTL_MS = 15 * 60 * 1000; // 15 minutes\n\n/**\n * Strip HTML tags and decode entities to produce readable plain text.\n *\n * Handles the most common HTML entities and normalizes whitespace.\n * Not a full HTML parser — just enough to extract readable content from\n * typical web pages.\n */\nfunction htmlToText(html: string): string {\n let text = html\n // Remove script and style elements with their contents\n .replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, \"\")\n .replace(/<style\\b[^<]*(?:(?!<\\/style>)<[^<]*)*<\\/style>/gi, \"\")\n // Replace block-level tags with newlines\n .replace(\n /<\\/(?:div|p|h[1-6]|li|tr|article|section|header|footer|nav|aside|main|table|thead|tbody|tfoot|form|fieldset|pre|blockquote|dl|dt|dd|hr|br)[^>]*>/gi,\n \"\\n\",\n )\n .replace(/<(?:br|hr)[^>]*\\/?>/gi, \"\\n\")\n // Remove remaining HTML tags\n .replace(/<[^>]*>/g, \"\")\n // Decode common HTML entities\n .replace(/&amp;/g, \"&\")\n .replace(/&lt;/g, \"<\")\n .replace(/&gt;/g, \">\")\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\")\n .replace(/&nbsp;/g, \" \")\n .replace(/&#x27;/g, \"'\")\n .replace(/&#x2F;/g, \"/\")\n .replace(/&#(\\d+);/g, (_m, code) => String.fromCodePoint(Number.parseInt(code, 10)))\n .replace(/&#[xX]([0-9a-fA-F]+);/g, (_m, hex) => String.fromCodePoint(Number.parseInt(hex, 16)))\n // Collapse whitespace\n .replace(/[ \\t]+/g, \" \")\n .replace(/\\n{3,}/g, \"\\n\\n\")\n .trim();\n\n return text;\n}\n\n/**\n * Extract readable text from raw response body based on Content-Type.\n *\n * HTML responses are converted to plain text. Non‑HTML responses are\n * returned as‑is.\n */\nfunction extractContent(raw: string, contentType?: string): string {\n const isHtml = contentType\n ? contentType.includes(\"text/html\") || contentType.includes(\"application/xhtml\")\n : raw.trim().startsWith(\"<\") || raw.includes(\"<html\");\n\n return isHtml ? htmlToText(raw) : raw;\n}\n\n/**\n * Trim text to the specified character limit, preserving the beginning\n * (most important content is usually at the top of a page).\n */\nfunction trimToLimit(text: string, limit: number): string {\n if (text.length <= limit) return text;\n return text.slice(0, limit);\n}\n\n/** Set of HTTP redirect status codes. */\nconst REDIRECT_CODES = new Set([301, 302, 307, 308]);\n\n/**\n * Validate and normalize a URL for fetching.\n *\n * Upgrades HTTP to HTTPS. Returns the normalized URL or an error result.\n */\nfunction validateUrl(\n rawUrl: string,\n startTime: number,\n): { ok: true; url: string } | { ok: false; error: ToolResult } {\n let normalized = rawUrl;\n if (normalized.startsWith(\"http://\")) {\n normalized = normalized.replace(\"http://\", \"https://\");\n }\n if (!normalized.startsWith(\"https://\")) {\n return {\n ok: false,\n error: {\n success: false,\n content: `无效的 URL: ${rawUrl}。必须使用 http:// 或 https://。`,\n metadata: { durationMs: Date.now() - startTime },\n },\n };\n }\n return { ok: true, url: normalized };\n}\n\n/** Options for {@link handleFetchRedirect}. */\ninterface FetchRedirectOptions {\n fetchUrl: string;\n originalUrl: string;\n resp: Response;\n controller: AbortController;\n charLimit: number;\n startTime: number;\n}\n\n/**\n * Handle an HTTP redirect response.\n *\n * For cross-host redirects, returns a message instructing the caller to\n * re-issue the request. For same-host redirects, follows the redirect\n * and returns the fetched content.\n */\nasync function handleFetchRedirect(opts: FetchRedirectOptions): Promise<ToolResult> {\n const location = opts.resp.headers.get(\"location\") || \"\";\n try {\n const redirectHost = new URL(location).host;\n const originalHost = new URL(opts.fetchUrl).host;\n if (redirectHost !== originalHost) {\n return {\n success: true,\n content: `重定向至: ${location}\\n\\n检测到跨域重定向。请使用重定向后的 URL 重新调用 web_fetch。`,\n metadata: { durationMs: Date.now() - opts.startTime },\n };\n }\n // Same-host redirect — follow it\n const followResp = await fetch(location, {\n signal: opts.controller.signal,\n headers: { \"User-Agent\": \"Lynx/1.0\" },\n });\n const raw = await followResp.text();\n const extracted = extractContent(raw, opts.resp.headers.get(\"content-type\") ?? undefined);\n cache.set(opts.originalUrl, { content: extracted, ts: Date.now() });\n const output = trimToLimit(extracted, opts.charLimit);\n return {\n success: true,\n content: output + (extracted.length > opts.charLimit ? \"\\n\\n[内容已截断]\" : \"\"),\n metadata: {\n durationMs: Date.now() - opts.startTime,\n truncated: extracted.length > opts.charLimit,\n },\n };\n } catch {\n return {\n success: true,\n content: `重定向至: ${location}`,\n metadata: { durationMs: Date.now() - opts.startTime },\n };\n }\n}\n\n/**\n * Build an error ToolResult from a fetch exception.\n */\nfunction buildFetchError(err: unknown, startTime: number): ToolResult {\n if ((err as { name?: string }).name === \"AbortError\") {\n return {\n success: false,\n content: \"获取已中止\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `获取失败: ${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n}\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { url, maxChars } = invocation.payload as { url: string; maxChars?: number };\n const charLimit = maxChars ?? 50_000;\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const validated = validateUrl(url, startTime);\n if (!validated.ok) return validated.error;\n const fetchUrl = validated.url;\n\n // Check URL allowlist\n const urlCheck = isUrlAllowed(fetchUrl);\n if (!urlCheck.allowed) {\n return {\n success: false,\n content: urlCheck.reason,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n // Check cache\n const cached = cache.get(fetchUrl);\n if (cached && Date.now() - cached.ts < CACHE_TTL_MS) {\n const content = trimToLimit(cached.content, charLimit);\n return {\n success: true,\n content: `[缓存于 ${Math.round((Date.now() - cached.ts) / 1000)} 秒前]\\n\\n${content}`,\n metadata: {\n durationMs: Date.now() - startTime,\n truncated: cached.content.length > charLimit,\n },\n };\n }\n\n try {\n const controller = new AbortController();\n signal.addEventListener(\"abort\", () => controller.abort(), { once: true });\n\n const resp = await fetch(fetchUrl, {\n signal: controller.signal,\n redirect: \"manual\",\n headers: { \"User-Agent\": \"Lynx/1.0\" },\n });\n\n if (REDIRECT_CODES.has(resp.status)) {\n return await handleFetchRedirect({\n fetchUrl,\n originalUrl: url,\n resp,\n controller,\n charLimit,\n startTime,\n });\n }\n\n if (!resp.ok) {\n return {\n success: false,\n content: `HTTP 错误 ${resp.status}: ${resp.statusText}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const raw = await resp.text();\n const contentType = resp.headers.get(\"content-type\") ?? undefined;\n const extracted = extractContent(raw, contentType);\n cache.set(url, { content: extracted, ts: Date.now() });\n\n const output = trimToLimit(extracted, charLimit);\n return {\n success: true,\n content: `已获取 ${fetchUrl} (${contentType || \"未知类型\"}):\\n\\n${output}${extracted.length > charLimit ? \"\\n\\n[内容已截断]\" : \"\"}`,\n metadata: { durationMs: Date.now() - startTime, truncated: extracted.length > charLimit },\n };\n } catch (err) {\n return buildFetchError(err, startTime);\n }\n },\n};\n","/**\n * web_search — Search the web via DuckDuckGo HTML search.\n *\n * Returns results with title, URL, and snippet. Supports domain filtering.\n * Uses DuckDuckGo's HTML endpoint (no API key required). Results cached\n * for 15 minutes per query.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\nimport { isUrlAllowed } from \"./web-fetch.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"web_search\",\n description: \"搜索网页并返回包含标题、URL 和摘要的结果。\" + \"支持域名白名单和黑名单过滤。\",\n inputSchema: {\n type: \"object\",\n properties: {\n query: { type: \"string\", description: \"搜索关键词\" },\n allowed_domains: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"只包含来自这些域名的结果\",\n },\n blocked_domains: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"排除来自这些域名的结果\",\n },\n },\n required: [\"query\"],\n },\n kind: \"Network\",\n safety: \"RequiresApproval\",\n availability: { type: \"always\" },\n executor: \"core:web_search\",\n owner: \"core\",\n};\n\n/** A single search result extracted from DuckDuckGo HTML. */\ninterface SearchResult {\n title: string;\n url: string;\n snippet: string;\n}\n\n/** In-memory cache: query → { results, timestamp } */\nconst cache = new Map<string, { results: SearchResult[]; ts: number }>();\nconst CACHE_TTL_MS = 15 * 60 * 1000; // 15 minutes\n\n/**\n * Build an error ToolResult from a fetch exception.\n */\nfunction buildSearchError(err: unknown, startTime: number): ToolResult {\n if ((err as { name?: string }).name === \"AbortError\") {\n return {\n success: false,\n content: \"搜索已中止\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `搜索失败: ${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n}\n\n/**\n * Parse DuckDuckGo HTML search results page into structured results.\n *\n * Extracts title, URL, and snippet from the HTML using regex patterns\n * matching DuckDuckGo's HTML-only result page markup.\n */\nfunction parseDdgHtml(html: string): SearchResult[] {\n const results: SearchResult[] = [];\n\n // DuckDuckGo HTML results use <a class=\"result__a\" href=\"...\"> for titles\n // and <a class=\"result__snippet\"> for snippets\n const linkRegex = /<a[^>]*class=\"result__a\"[^>]*href=\"([^\"]*)\"[^>]*>([\\s\\S]*?)<\\/a>/gi;\n const snippetRegex = /<a[^>]*class=\"result__snippet\"[^>]*>([\\s\\S]*?)<\\/a>/gi;\n\n // Collect all title/URL pairs and snippets separately, then pair them\n const links: Array<{ title: string; url: string }> = [];\n let linkMatch: RegExpExecArray | null;\n while ((linkMatch = linkRegex.exec(html)) !== null) {\n const url = linkMatch[1];\n const title = linkMatch[2].replace(/<[^>]*>/g, \"\").trim();\n if (url && title && !url.startsWith(\"//duckduckgo.com\")) {\n links.push({ title, url });\n }\n }\n\n const snippets: string[] = [];\n let snippetMatch: RegExpExecArray | null;\n while ((snippetMatch = snippetRegex.exec(html)) !== null) {\n const text = snippetMatch[1].replace(/<[^>]*>/g, \"\").trim();\n if (text) snippets.push(text);\n }\n\n // Pair links with snippets (they appear in order)\n const count = Math.min(links.length, snippets.length);\n for (let i = 0; i < count; i++) {\n results.push({\n title: links[i].title,\n url: links[i].url,\n snippet: snippets[i],\n });\n }\n\n return results;\n}\n\n/**\n * Filter search results by allowed/blocked domains.\n */\nfunction filterByDomain(\n results: SearchResult[],\n allowed?: string[],\n blocked?: string[],\n): SearchResult[] {\n let filtered = results;\n\n if (allowed && allowed.length > 0) {\n const allowedLower = allowed.map((d) => d.toLowerCase());\n filtered = filtered.filter((r) => {\n try {\n const host = new URL(r.url).host.toLowerCase();\n return allowedLower.some((d) => host.includes(d));\n } catch {\n return false;\n }\n });\n }\n\n if (blocked && blocked.length > 0) {\n const blockedLower = blocked.map((d) => d.toLowerCase());\n filtered = filtered.filter((r) => {\n try {\n const host = new URL(r.url).host.toLowerCase();\n return !blockedLower.some((d) => host.includes(d));\n } catch {\n return true;\n }\n });\n }\n\n return filtered;\n}\n\n/**\n * Format search results into a readable text block.\n */\nfunction formatResults(results: SearchResult[], query: string): string {\n if (results.length === 0) {\n return `未找到与 \"${query}\" 相关的结果。`;\n }\n return results\n .map((r, i) => `${i + 1}. **${r.title}**\\n ${r.url}\\n ${r.snippet}`)\n .join(\"\\n\\n\");\n}\n\n/** Generate a cache key from the query and domain filters. */\nfunction cacheKey(query: string, allowed?: string[], blocked?: string[]): string {\n const parts = [query];\n if (allowed?.length) parts.push(\"allow:\" + allowed.sort().join(\",\"));\n if (blocked?.length) parts.push(\"block:\" + blocked.sort().join(\",\"));\n return parts.join(\"|\");\n}\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { query, allowed_domains, blocked_domains } = invocation.payload as {\n query: string;\n allowed_domains?: string[];\n blocked_domains?: string[];\n };\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (!query || query.trim().length === 0) {\n return {\n success: false,\n content: \"请输入搜索关键词.\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const key = cacheKey(query.trim(), allowed_domains, blocked_domains);\n\n // Check cache\n const cached = cache.get(key);\n if (cached && Date.now() - cached.ts < CACHE_TTL_MS) {\n const age = Math.round((Date.now() - cached.ts) / 1000);\n const content = `[缓存于 ${age} 秒前]\\n\\n${formatResults(cached.results, query)}`;\n return {\n success: true,\n content,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n const controller = new AbortController();\n signal.addEventListener(\"abort\", () => controller.abort(), { once: true });\n\n const searchUrl = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(query.trim())}`;\n\n // Check URL allowlist\n const urlCheck = isUrlAllowed(searchUrl);\n if (!urlCheck.allowed) {\n return {\n success: false,\n content: urlCheck.reason,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const resp = await fetch(searchUrl, {\n signal: controller.signal,\n headers: {\n \"User-Agent\": \"Lynx/1.0\",\n Accept: \"text/html\",\n },\n });\n\n if (!resp.ok) {\n return {\n success: false,\n content: `搜索请求失败: HTTP ${resp.status} ${resp.statusText}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const html = await resp.text();\n const allResults = parseDdgHtml(html);\n const filtered = filterByDomain(allResults, allowed_domains, blocked_domains);\n\n // Cache the full results (pre-filter) for reuse with different domain filters\n cache.set(key, { results: filtered, ts: Date.now() });\n\n const content = formatResults(filtered, query);\n return {\n success: true,\n content,\n metadata: {\n durationMs: Date.now() - startTime,\n truncated: filtered.length < allResults.length,\n },\n };\n } catch (err) {\n return buildSearchError(err, startTime);\n }\n },\n};\n","/**\n * todo_write — Create or update the task list.\n *\n * Each call REPLACES the entire list (not incremental).\n * Status: pending → in_progress → completed.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"todo_write\",\n description:\n \"创建和更新任务列表以跟踪进度。\" +\n \"每次调用会替换整个列表。每项任务必须包含 content、status 和 activeForm。\",\n inputSchema: {\n type: \"object\",\n properties: {\n todos: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n content: { type: \"string\", description: \"任务描述\" },\n status: {\n type: \"string\",\n enum: [\"pending\", \"in_progress\", \"completed\"],\n description: \"任务当前状态\",\n },\n activeForm: {\n type: \"string\",\n description: \"任务进行中时显示的现在时标签\",\n },\n },\n required: [\"content\", \"status\", \"activeForm\"],\n },\n description: \"完整的任务列表(替换已有列表)\",\n },\n },\n required: [\"todos\"],\n },\n kind: \"WritesFiles\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:todo_write\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, _signal): Promise<ToolResult> {\n const { todos } = invocation.payload as {\n todos: Array<{\n content: string;\n status: \"pending\" | \"in_progress\" | \"completed\";\n activeForm: string;\n }>;\n };\n\n const startTime = Date.now();\n\n // Validate\n if (!Array.isArray(todos)) {\n return {\n success: false,\n content: \"todos 必须是一个数组\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const statusCounts = { pending: 0, in_progress: 0, completed: 0 };\n for (const todo of todos) {\n if (!todo.content || !todo.status || !todo.activeForm) {\n return {\n success: false,\n content: `无效的任务项: 每项必须包含 content、status 和 activeForm。收到: ${JSON.stringify(todo)}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n if (![\"pending\", \"in_progress\", \"completed\"].includes(todo.status)) {\n return {\n success: false,\n content: `\"${todo.content}\" 的状态 \"${todo.status}\" 无效。必须为: pending, in_progress 或 completed。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n statusCounts[todo.status]++;\n }\n\n const lines = todos.map((t, _i) => {\n const icon = t.status === \"completed\" ? \"✓\" : t.status === \"in_progress\" ? \"●\" : \"○\";\n return `${icon} [${t.status}] ${t.activeForm}: ${t.content}`;\n });\n\n return {\n success: true,\n content:\n `任务列表已更新(共 ${todos.length} 项: ${statusCounts.in_progress} 项进行中, ${statusCounts.pending} 项待处理, ${statusCounts.completed} 项已完成):\\n\\n` +\n lines.join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * powershell — 在 Windows 上执行 PowerShell 命令。\n *\n * 仅在 Windows 平台可用。使用 child_process.exec 执行,\n * 默认 30 秒超时。返回 stdout 和 stderr。\n */\nimport { exec } from \"node:child_process\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"powershell\",\n description:\n \"在 Windows 上执行 PowerShell 命令。返回 stdout 和 stderr。\" +\n \"仅 Windows 平台可用。命令以 -NoProfile 模式运行。\",\n inputSchema: {\n type: \"object\",\n properties: {\n command: {\n type: \"string\",\n description: \"要执行的 PowerShell 命令\",\n },\n timeout: {\n type: \"number\",\n description: \"超时时间(毫秒),默认 30000\",\n default: 30000,\n },\n },\n required: [\"command\"],\n },\n kind: \"ExecutesCode\",\n safety: \"RequiresApproval\",\n availability: { type: \"platform\", platform: \"windows\" },\n executor: \"core:powershell\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { command, timeout } = invocation.payload as {\n command: string;\n timeout?: number;\n };\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (process.platform !== \"win32\") {\n return {\n success: false,\n content: \"PowerShell 工具仅支持 Windows 平台。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (!command || command.trim().length === 0) {\n return {\n success: false,\n content: \"请输入要执行的 PowerShell 命令。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const timeoutMs = timeout ?? 30000;\n const escapedCommand = command.replace(/\"/g, '\\\\\"');\n\n return new Promise<ToolResult>((resolve) => {\n let aborted = false;\n\n const onAbort = () => {\n aborted = true;\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n\n const child = exec(\n `powershell -NoProfile -Command \"${escapedCommand}\"`,\n { timeout: timeoutMs, windowsHide: true },\n (err, stdout, stderr) => {\n signal.removeEventListener(\"abort\", onAbort);\n\n if (aborted) {\n resolve({\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n });\n return;\n }\n\n if (err) {\n const isTimeout = (err as NodeJS.ErrnoException).code === \"ETIMEDOUT\";\n resolve({\n success: false,\n content: isTimeout\n ? `命令执行超时(${timeoutMs}ms)`\n : `命令执行失败: ${err.message}\\n\\nstderr:\\n${stderr}`,\n metadata: { durationMs: Date.now() - startTime },\n });\n return;\n }\n\n const output = [\n stdout ? `stdout:\\n${stdout.trimEnd()}` : null,\n stderr ? `stderr:\\n${stderr.trimEnd()}` : null,\n ]\n .filter(Boolean)\n .join(\"\\n\\n\");\n\n resolve({\n success: true,\n content: output || \"(无输出)\",\n metadata: { durationMs: Date.now() - startTime },\n });\n },\n );\n });\n },\n};\n","/**\n * NotebookEditTool — 编辑 Jupyter notebook (.ipynb) 文件中的单元格。\n *\n * 支持四种操作:\n * - list: 列出所有单元格(索引、类型、源码摘要)\n * - insert: 在指定位置插入新单元格\n * - replace: 替换指定位置的单元格内容\n * - delete: 删除指定位置的单元格\n *\n * .ipynb 文件结构为 JSON: { cells: [{ cell_type, source, ... }], ... }\n * source 字段可以是字符串或字符串数组,统一按字符串数组处理。\n */\nimport { readFileSync, writeFileSync, renameSync } from \"node:fs\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"NotebookEditTool\",\n description:\n \"编辑 Jupyter notebook (.ipynb) 文件中的单元格。\" +\n \"支持插入、替换、删除和列出代码与 Markdown 单元格。\",\n inputSchema: {\n type: \"object\",\n properties: {\n filePath: {\n type: \"string\",\n description: \".ipynb 文件的绝对路径\",\n },\n action: {\n type: \"string\",\n enum: [\"insert\", \"replace\", \"delete\", \"list\"],\n description: \"操作类型:list(列出)、insert(插入)、replace(替换)、delete(删除)\",\n },\n cellIndex: {\n type: \"integer\",\n description:\n \"单元格索引(从 0 开始)。insert 表示插入位置,replace/delete 表示目标单元格。\",\n },\n cellType: {\n type: \"string\",\n enum: [\"code\", \"markdown\"],\n description: \"单元格类型(insert 操作必填)\",\n },\n content: {\n type: \"string\",\n description: \"单元格源码内容(insert/replace 操作需要)\",\n },\n },\n required: [\"filePath\", \"action\"],\n },\n kind: \"WritesFiles\",\n safety: \"WorkspaceSafe\",\n availability: { type: \"always\" },\n executor: \"core:notebook_edit\",\n owner: \"core\",\n};\n\n/** .ipynb 文件内部结构 */\ninterface NotebookJson {\n cells: NotebookCell[];\n metadata?: Record<string, unknown>;\n nbformat?: number;\n nbformat_minor?: number;\n}\n\ninterface NotebookCell {\n cell_type: \"code\" | \"markdown\" | \"raw\";\n source: string | string[];\n metadata?: Record<string, unknown>;\n outputs?: unknown[];\n execution_count?: number | null;\n id?: string;\n}\n\n/** 将 source 字段统一转为字符串数组 */\nfunction normalizeSource(source: string | string[]): string[] {\n if (Array.isArray(source)) return source;\n // 按换行拆分,每行末尾保留换行符(Jupyter 惯例)\n const lines = source.split(\"\\n\");\n return lines.map((line, i) => (i < lines.length - 1 ? line + \"\\n\" : line));\n}\n\n/** 将 source 字段合并为单个字符串 */\nfunction sourceToString(source: string | string[]): string {\n if (typeof source === \"string\") return source;\n return source.join(\"\");\n}\n\n/** 生成单元格源码摘要(前 80 个字符) */\nfunction sourceSummary(source: string | string[]): string {\n const text = sourceToString(source).replace(/\\s+/g, \" \").trim();\n if (text.length <= 80) return text;\n return text.slice(0, 77) + \"...\";\n}\n\n/** 读取 .ipynb 文件并解析 JSON */\nfunction readNotebook(filePath: string, startTime: number): NotebookJson | ToolResult {\n let raw: string;\n try {\n raw = readFileSync(filePath, \"utf-8\");\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return {\n success: false,\n content: `文件未找到: ${filePath}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n return {\n success: false,\n content: `读取文件失败: ${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n return JSON.parse(raw) as NotebookJson;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `解析 .ipynb JSON 失败: ${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n}\n\n/** 原子写入 notebook JSON */\nfunction writeNotebookAtomically(\n filePath: string,\n notebook: NotebookJson,\n startTime: number,\n): ToolResult {\n try {\n const tmpPath = filePath + \".tmp\";\n writeFileSync(tmpPath, JSON.stringify(notebook, null, 1) + \"\\n\", \"utf-8\");\n renameSync(tmpPath, filePath);\n return {\n success: true,\n content: `已保存 notebook: ${filePath}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `写入文件失败: ${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n}\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { filePath, action, cellIndex, cellType, content } = invocation.payload as {\n filePath: string;\n action: string;\n cellIndex?: number;\n cellType?: string;\n content?: string;\n };\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (!filePath.endsWith(\".ipynb\")) {\n return {\n success: false,\n content: `不是 .ipynb 文件: ${filePath}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const notebookOrError = readNotebook(filePath, startTime);\n if (\"success\" in notebookOrError) return notebookOrError;\n const notebook = notebookOrError;\n\n if (!Array.isArray(notebook.cells)) {\n notebook.cells = [];\n }\n\n switch (action) {\n case \"list\": {\n if (notebook.cells.length === 0) {\n return {\n success: true,\n content: \"该 notebook 没有单元格。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const lines = notebook.cells.map((cell, i) => {\n const summary = sourceSummary(cell.source);\n const execCount =\n cell.cell_type === \"code\" && cell.execution_count != null\n ? ` [执行次数: ${cell.execution_count}]`\n : \"\";\n return `${i}: [${cell.cell_type}]${execCount} ${summary}`;\n });\n return {\n success: true,\n content: `共 ${notebook.cells.length} 个单元格:\\n${lines.join(\"\\n\")}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n case \"insert\": {\n if (cellIndex == null) {\n return {\n success: false,\n content: \"insert 操作需要提供 cellIndex 参数。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n if (!cellType || ![\"code\", \"markdown\"].includes(cellType)) {\n return {\n success: false,\n content: \"insert 操作需要提供有效的 cellType(code 或 markdown)。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const newCell: NotebookCell = {\n cell_type: cellType as \"code\" | \"markdown\",\n source: content ? normalizeSource(content) : [],\n metadata: {},\n outputs: cellType === \"code\" ? [] : undefined,\n execution_count: null,\n };\n const insertIndex = Math.min(cellIndex, notebook.cells.length);\n notebook.cells.splice(insertIndex, 0, newCell);\n return writeNotebookAtomically(filePath, notebook, startTime);\n }\n\n case \"replace\": {\n if (cellIndex == null) {\n return {\n success: false,\n content: \"replace 操作需要提供 cellIndex 参数。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n if (cellIndex < 0 || cellIndex >= notebook.cells.length) {\n return {\n success: false,\n content: `单元格索引 ${cellIndex} 超出范围(0-${notebook.cells.length - 1})。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const target = notebook.cells[cellIndex];\n if (content != null) {\n target.source = normalizeSource(content);\n }\n if (cellType && [\"code\", \"markdown\"].includes(cellType)) {\n target.cell_type = cellType as \"code\" | \"markdown\";\n }\n return writeNotebookAtomically(filePath, notebook, startTime);\n }\n\n case \"delete\": {\n if (cellIndex == null) {\n return {\n success: false,\n content: \"delete 操作需要提供 cellIndex 参数。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n if (cellIndex < 0 || cellIndex >= notebook.cells.length) {\n return {\n success: false,\n content: `单元格索引 ${cellIndex} 超出范围(0-${notebook.cells.length - 1})。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const removed = notebook.cells[cellIndex];\n notebook.cells.splice(cellIndex, 1);\n const result = writeNotebookAtomically(filePath, notebook, startTime);\n result.content = `已删除单元格 ${cellIndex} [${removed.cell_type}]: ${sourceSummary(removed.source)}\\n${result.content}`;\n return result;\n }\n\n default: {\n return {\n success: false,\n content: `不支持的操作: ${action}。支持的操作: list, insert, replace, delete。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n }\n },\n};\n","/**\n * SecretScanner — 扫描文件内容以查找潜在的密钥、令牌和凭证。\n *\n * 在写入文件操作前使用此工具检查敏感信息泄露。\n * 支持检测:私钥块、GitHub token、OpenAI key、Google API key、\n * JWT token、通用 API key 模式、密码赋值等。\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"SecretScanner\",\n description:\n \"扫描文件内容以查找潜在的密钥、令牌和凭证。\" +\n \"在写入操作前使用此工具检查敏感信息。\" +\n \"检测模式包括:私钥、GitHub token、OpenAI key、Google API key、JWT、通用 API key、密码赋值。\",\n inputSchema: {\n type: \"object\",\n properties: {\n content: {\n type: \"string\",\n description: \"要扫描的文件内容\",\n },\n filePath: {\n type: \"string\",\n description: \"可选的文件路径,用于在结果中标识来源\",\n },\n },\n required: [\"content\"],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:secret_scan\",\n owner: \"core\",\n};\n\n/** 单个密钥匹配结果 */\ninterface SecretMatch {\n /** 检测模式名称 */\n pattern: string;\n /** 已脱敏的匹配摘要(只显示前 4 个字符 + \"...\") */\n excerpt: string;\n}\n\n/** 预编译的密钥检测正则模式 */\nconst SECRET_PATTERNS: Array<{ name: string; regex: RegExp }> = [\n { name: \"私钥块\", regex: /-----BEGIN (?:RSA |EC |DSA )?PRIVATE KEY-----/ },\n { name: \"GitHub Token\", regex: /gh[pousr]_[A-Za-z0-9_]{36,}/ },\n { name: \"OpenAI Key\", regex: /sk-[A-Za-z0-9]{32,}/ },\n { name: \"Google API Key\", regex: /AIza[0-9A-Za-z\\-_]{35}/ },\n { name: \"JWT Token\", regex: /eyJ[A-Za-z0-9\\-_]+\\.eyJ[A-Za-z0-9\\-_]+.[A-Za-z0-9\\-_]+/ },\n {\n name: \"通用 API Key\",\n regex: /(?:api[_-]?key|apikey|api[_-]?secret)\\s*[:=]\\s*['\"][A-Za-z0-9_\\-]{20,}['\"]/gi,\n },\n {\n name: \"密码赋值\",\n regex: /(?:password|passwd|pwd)\\s*[:=]\\s*['\"][^'\"]+['\"]/gi,\n },\n];\n\n/** 对匹配内容进行脱敏:只显示前 4 个字符 + \"...\" */\nfunction redactExcerpt(fullMatch: string): string {\n if (fullMatch.length <= 8) {\n return fullMatch.slice(0, 4) + \"...\";\n }\n return fullMatch.slice(0, 4) + \"...\" + fullMatch.slice(-4);\n}\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { content, filePath } = invocation.payload as {\n content: string;\n filePath?: string;\n };\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (!content || content.length === 0) {\n return {\n success: true,\n content: \"内容为空,无需扫描。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const findings: SecretMatch[] = [];\n\n for (const { name, regex } of SECRET_PATTERNS) {\n // 重置 lastIndex(因为 regex 可能有 global 标志)\n const re = new RegExp(regex.source, regex.flags);\n let match: RegExpExecArray | null;\n while ((match = re.exec(content)) !== null) {\n const excerpt = redactExcerpt(match[0]);\n findings.push({ pattern: name, excerpt });\n }\n }\n\n if (findings.length === 0) {\n const pathInfo = filePath ? ` (${filePath})` : \"\";\n return {\n success: true,\n content: `未检测到密钥或凭证${pathInfo}。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n // 按模式分组\n const grouped = new Map<string, string[]>();\n for (const f of findings) {\n const excerpts = grouped.get(f.pattern) ?? [];\n excerpts.push(f.excerpt);\n grouped.set(f.pattern, excerpts);\n }\n\n const lines: string[] = [\n `检测到 ${findings.length} 个潜在密钥/凭证!`,\n filePath ? `文件: ${filePath}` : \"\",\n \"\",\n ];\n\n for (const [pattern, excerpts] of grouped) {\n lines.push(`**${pattern}** (${excerpts.length} 处):`);\n // 去重后列出\n const unique = [...new Set(excerpts)];\n for (const excerpt of unique.slice(0, 5)) {\n lines.push(` - ${excerpt}`);\n }\n if (unique.length > 5) {\n lines.push(` ... 还有 ${unique.length - 5} 处`);\n }\n lines.push(\"\");\n }\n\n return {\n success: true,\n content: lines.join(\"\\n\").trimEnd(),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * LSPTool — 语言服务器协议桥接工具。\n *\n * 提供 LSP 诊断、类型信息、跳转定义等功能的最小化接口。\n * 此工具默认隐藏(需设置 flag \"lsp_enabled\" 才会暴露)。\n * 当 IDE 连接后将提供完整的 LSP 集成,目前提供接口契约层。\n */\nimport { readFile } from \"node:fs/promises\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\n// ── Descriptor ────────────────────────────────────────\n\nexport const descriptor: ToolDescriptor = {\n name: \"LSPTool\",\n description:\n \"查询语言服务器协议(LSP)以获取诊断、类型信息、跳转定义等。\" +\n \"支持 diagnostics、hover、definition、references、format 等常见 LSP 操作。\",\n inputSchema: {\n type: \"object\",\n properties: {\n action: {\n type: \"string\",\n enum: [\"diagnostics\", \"hover\", \"definition\", \"references\", \"format\"],\n description: \"LSP 操作类型:诊断、悬停类型信息、跳转定义、查找引用、格式化\",\n },\n filePath: {\n type: \"string\",\n description: \"要查询的文件绝对路径\",\n },\n line: {\n type: \"integer\",\n description: \"行号(从 1 开始),hover/definition 操作使用\",\n },\n character: {\n type: \"integer\",\n description: \"列号(从 1 开始),hover/definition 操作使用\",\n },\n },\n required: [\"action\", \"filePath\"],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"flag\", flag: \"lsp_enabled\" },\n executor: \"core:lsp\",\n owner: \"core\",\n};\n\n// ── Handler ───────────────────────────────────────────\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { action, filePath, line, character } = invocation.payload as {\n action: string;\n filePath: string;\n line?: number;\n character?: number;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"LSP 操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n switch (action) {\n case \"diagnostics\":\n return await handleDiagnostics(filePath, startTime);\n case \"hover\":\n return handleHover(filePath, line, character, startTime);\n case \"definition\":\n return handleDefinition(filePath, line, character, startTime);\n case \"references\":\n return handleReferences(filePath, line, character, startTime);\n case \"format\":\n return handleFormat(filePath, startTime);\n default:\n return {\n success: false,\n content: `未知的 LSP 操作:${action}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `LSP 操作失败:${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n },\n};\n\n// ── Action handlers ───────────────────────────────────\n\n/**\n * 解析文件内容并用正则进行基础语法检查。\n * 真实 LSP 集成在 IDE 连接后提供完整诊断。\n */\nasync function handleDiagnostics(filePath: string, startTime: number): Promise<ToolResult> {\n let content: string;\n try {\n content = await readFile(filePath, \"utf-8\");\n } catch {\n return {\n success: false,\n content: `无法读取文件:${filePath}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const lines = content.split(\"\\n\");\n const issues: string[] = [];\n\n for (let i = 0; i < lines.length; i++) {\n const ln = lines[i];\n // 检查不闭合的括号\n if (countOccurrences(ln, \"{\") !== countOccurrences(ln, \"}\")) {\n issues.push(`第 ${i + 1} 行:花括号不匹配`);\n }\n if (countOccurrences(ln, \"(\") !== countOccurrences(ln, \")\")) {\n issues.push(`第 ${i + 1} 行:圆括号不匹配`);\n }\n if (countOccurrences(ln, \"[\") !== countOccurrences(ln, \"]\")) {\n issues.push(`第 ${i + 1} 行:方括号不匹配`);\n }\n }\n\n const contentText =\n issues.length > 0\n ? `诊断结果(${issues.length} 个问题):\\n${issues.join(\"\\n\")}`\n : \"未发现基础语法问题。完整 LSP 诊断在 IDE 连接后可用。\";\n\n return {\n success: true,\n content: contentText,\n metadata: { durationMs: Date.now() - startTime },\n };\n}\n\n/**\n * 悬停信息:提示 IDE 连接后可用。\n */\nfunction handleHover(\n filePath: string,\n line?: number,\n character?: number,\n startTime?: number,\n): ToolResult {\n const pos = line != null ? `第 ${line} 行` : \"光标位置\";\n const col = character != null ? `第 ${character} 列` : \"\";\n const loc = col ? `${pos},${col}` : pos;\n\n return {\n success: true,\n content: `LSP 悬停信息在 IDE 连接后可用。查询位置:${filePath} ${loc}。当前可用的类型信息需要 IDE 提供 language server 支持。`,\n metadata: { durationMs: Date.now() - (startTime ?? 0) },\n };\n}\n\n/**\n * 跳转定义:返回文件路径和行号提示。\n */\nfunction handleDefinition(\n filePath: string,\n line?: number,\n character?: number,\n startTime?: number,\n): ToolResult {\n const posHint = line != null ? `(接近第 ${line} 行)` : \"\";\n\n return {\n success: true,\n content: `跳转定义在 IDE 连接后可用。源文件:${filePath}${posHint}。连接 LSP 后将返回精确的定义位置。`,\n metadata: { durationMs: Date.now() - (startTime ?? 0) },\n };\n}\n\n/**\n * 查找引用:返回空列表并说明 IDE 连接后可用。\n */\nfunction handleReferences(\n filePath: string,\n line?: number,\n character?: number,\n startTime?: number,\n): ToolResult {\n const posHint = line != null ? `(第 ${line} 行)` : \"\";\n\n return {\n success: true,\n content:\n `引用查找在 IDE 连接后可用。查询:${filePath}${posHint}。当前未找到引用` +\n `(完整引用分析需要 IDE 的 language server 支持)。`,\n metadata: { durationMs: Date.now() - (startTime ?? 0) },\n };\n}\n\n/**\n * 格式化:提示 IDE 连接后可用。\n */\nfunction handleFormat(filePath: string, startTime: number): ToolResult {\n return {\n success: true,\n content: `格式化功能在 IDE 连接后可用。目标文件:${filePath}。LSP 连接后将提供基于 language server 的代码格式化。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n}\n\n// ── Helpers ───────────────────────────────────────────\n\n/** 统计字符串中某字符的出现次数。 */\nfunction countOccurrences(str: string, char: string): number {\n let count = 0;\n for (let i = 0; i < str.length; i++) {\n if (str[i] === char) count++;\n }\n return count;\n}\n","/**\n * REPLTool — 交互式 REPL 代码执行工具。\n *\n * 管理持久化 REPL 子进程(Node.js / Python / Bash),\n * 支持在多次调用之间保持运行状态。\n * 每个会话分配唯一 UUID,通过模块级 Map 跟踪。\n */\nimport { spawn, type ChildProcess } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\n// ── Session tracking ─────────────────────────────────\n\n/** REPL 会话信息。 */\ninterface ReplSession {\n id: string;\n language: string;\n process: ChildProcess;\n createdAt: number;\n}\n\n/** 活跃的 REPL 会话映射,key 为 session UUID。 */\nconst activeSessions = new Map<string, ReplSession>();\n\n// ── Descriptor ────────────────────────────────────────\n\nexport const descriptor: ToolDescriptor = {\n name: \"REPLTool\",\n description:\n \"在持久化 REPL 会话中执行代码。启动运行时(Node.js/Python/Bash)\" +\n \"并保持状态在多次调用之间。\" +\n \"支持 start(启动)、eval(执行)、stop(停止)、status(状态)四种操作。\",\n inputSchema: {\n type: \"object\",\n properties: {\n action: {\n type: \"string\",\n enum: [\"start\", \"eval\", \"stop\", \"status\"],\n description: \"操作类型:启动 REPL、执行代码、停止会话、查看状态\",\n },\n language: {\n type: \"string\",\n enum: [\"node\", \"python\", \"bash\"],\n description: \"运行时语言(start 操作时使用)\",\n },\n code: {\n type: \"string\",\n description: \"要执行的代码(eval 操作时使用)\",\n },\n sessionId: {\n type: \"string\",\n description: \"目标会话 ID(eval/stop 操作时使用)\",\n },\n },\n required: [\"action\"],\n },\n kind: \"ExecutesCode\",\n safety: \"RequiresApproval\",\n availability: { type: \"always\" },\n executor: \"core:repl\",\n owner: \"core\",\n};\n\n// ── Handler ───────────────────────────────────────────\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { action, language, code, sessionId } = invocation.payload as {\n action: string;\n language?: string;\n code?: string;\n sessionId?: string;\n };\n\n const startTime = Date.now();\n\n // 注册 AbortSignal 清理\n if (signal) {\n signal.addEventListener(\"abort\", () => {\n for (const [id, session] of activeSessions) {\n session.process.kill();\n activeSessions.delete(id);\n }\n });\n }\n\n try {\n switch (action) {\n case \"start\":\n return handleStart(language);\n case \"eval\":\n return await handleEval(code, sessionId, signal);\n case \"stop\":\n return handleStop(sessionId);\n case \"status\":\n return handleStatus();\n default:\n return {\n success: false,\n content: `未知操作:${action}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `REPL 操作失败:${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n },\n};\n\n// ── Action handlers ───────────────────────────────────\n\n/** 启动一个新的 REPL 会话并返回 session UUID。 */\nfunction handleStart(language?: string): ToolResult {\n if (!language || ![\"node\", \"python\", \"bash\"].includes(language)) {\n return {\n success: false,\n content: `不支持的语言:${language ?? \"未指定\"}。支持 node、python、bash。`,\n };\n }\n\n const id = randomUUID();\n let childProcess: ChildProcess;\n\n switch (language) {\n case \"node\":\n childProcess = spawn(\"node\", [\"-i\"], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n shell: true,\n });\n break;\n case \"python\":\n childProcess = spawn(\"python3\", [\"-i\"], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n shell: true,\n });\n break;\n case \"bash\":\n childProcess = spawn(\"bash\", [], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n shell: true,\n });\n break;\n default:\n throw new Error(`不支持的语言:${language}`);\n }\n\n const session: ReplSession = {\n id,\n language,\n process: childProcess,\n createdAt: Date.now(),\n };\n\n activeSessions.set(id, session);\n\n // 清理已退出的进程\n childProcess.on(\"exit\", () => {\n activeSessions.delete(id);\n });\n\n return {\n success: true,\n content: `REPL 会话已启动(${language})。会话 ID:${id}`,\n };\n}\n\n/** 在现有 REPL 会话中执行代码。 */\nasync function handleEval(\n code?: string,\n sessionId?: string,\n signal?: AbortSignal,\n): Promise<ToolResult> {\n if (!sessionId) {\n return { success: false, content: \"缺少 sessionId 参数\" };\n }\n if (!code) {\n return { success: false, content: \"缺少 code 参数\" };\n }\n\n const session = activeSessions.get(sessionId);\n if (!session) {\n return { success: false, content: `未找到 REPL 会话:${sessionId}` };\n }\n\n return new Promise((resolve) => {\n const chunks: string[] = [];\n const onData = (data: Buffer) => chunks.push(data.toString());\n session.process.stdout?.on(\"data\", onData);\n\n const timeout = setTimeout(() => {\n session.process.stdout?.removeListener(\"data\", onData);\n resolve({\n success: true,\n content: `执行超时(5s),已发送的代码:\\n\\`\\`\\`\\n${code}\\n\\`\\`\\``,\n });\n }, 5000);\n\n // 监听 abort\n if (signal) {\n const onAbort = () => {\n clearTimeout(timeout);\n session.process.stdout?.removeListener(\"data\", onData);\n resolve({ success: false, content: \"REPL 执行已取消\" });\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n\n session.process.stdin?.write(code + \"\\n\");\n\n // 等短暂时间收集输出\n setTimeout(() => {\n clearTimeout(timeout);\n session.process.stdout?.removeListener(\"data\", onData);\n const output = chunks.join(\"\").trim();\n resolve({\n success: true,\n content: output || \"(无输出)\",\n });\n }, 1000);\n });\n}\n\n/** 停止并移除 REPL 会话。 */\nfunction handleStop(sessionId?: string): ToolResult {\n if (!sessionId) {\n // 停止所有会话\n let count = 0;\n for (const [id, session] of activeSessions) {\n session.process.kill();\n activeSessions.delete(id);\n count++;\n }\n return { success: true, content: `已停止 ${count} 个 REPL 会话` };\n }\n\n const session = activeSessions.get(sessionId);\n if (!session) {\n return { success: false, content: `未找到 REPL 会话:${sessionId}` };\n }\n\n session.process.kill();\n activeSessions.delete(sessionId);\n return { success: true, content: `REPL 会话 ${sessionId} 已停止` };\n}\n\n/** 列出所有活跃会话。 */\nfunction handleStatus(): ToolResult {\n if (activeSessions.size === 0) {\n return { success: true, content: \"当前无活跃的 REPL 会话\" };\n }\n\n const lines: string[] = [];\n for (const session of activeSessions.values()) {\n const age = Math.round((Date.now() - session.createdAt) / 1000);\n lines.push(`${session.id} — ${session.language}(运行中,${age} 秒)`);\n }\n\n return { success: true, content: `活跃会话(${activeSessions.size}):\\n${lines.join(\"\\n\")}` };\n}\n","/**\n * agent — Spawn a sub-agent to handle complex multi-step tasks.\n *\n * The sub-agent runs in an isolated context with restricted tools and a\n * separate token budget (default: 1/4 of parent budget).\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"agent\",\n description:\n \"启动子 Agent 自主处理复杂多步骤任务。\" +\n \"每种子 Agent 类型拥有不同能力和可用工具。\" +\n \"子 Agent 将最终结果返回给父 Agent。\",\n inputSchema: {\n type: \"object\",\n properties: {\n description: { type: \"string\", description: \"任务的简短描述(3-5 个词)\" },\n prompt: { type: \"string\", description: \"子 Agent 要执行的任务\" },\n subagent_type: {\n type: \"string\",\n description: \"专用 Agent 类型:claude、explore、plan、general-purpose、statusline-setup\",\n },\n model: {\n type: \"string\",\n enum: [\"sonnet\", \"opus\", \"haiku\"],\n description: \"可选:为此子 Agent 指定模型覆盖\",\n },\n isolation: {\n type: \"string\",\n enum: [\"worktree\"],\n description: \"在隔离的 git worktree 中运行(开销大——仅用于并行文件修改场景)\",\n },\n allowed_tools: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"限制子 Agent 可用的工具。留空则继承父级工具。\",\n },\n },\n required: [\"description\", \"prompt\"],\n },\n kind: \"ExecutesCode\",\n safety: \"RequiresApproval\",\n availability: { type: \"always\" },\n executor: \"core:agent\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { description, prompt, subagent_type, model, isolation, allowed_tools } =\n invocation.payload as {\n description: string;\n prompt: string;\n subagent_type?: string;\n model?: \"sonnet\" | \"opus\" | \"haiku\";\n isolation?: \"worktree\";\n allowed_tools?: string[];\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"子 Agent 已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n // This tool's actual implementation lives in @24klynx/agent (spawnSubAgent).\n // The built-in handler here is a thin adapter — the real logic wire-up\n // happens in lynx-cli bootstrap where the handler is swapped.\n //\n // For Phase 2, we provide a working mock that returns acknowledgement.\n // Phase 3 replaces this with the real spawnSubAgent integration.\n\n const agentType = subagent_type ?? \"general-purpose\";\n const budgetNote = \"子 Agent 获得父级 token 预算的 1/4。\";\n\n return {\n success: true,\n content: [\n `子 Agent 已调度 [${agentType}]:${description}`,\n `模型:${model ?? \"inherit\"}`,\n `隔离模式:${isolation ?? \"none\"}`,\n `工具:${allowed_tools ? allowed_tools.join(\", \") : \"inherit\"}`,\n budgetNote,\n \"\",\n \"--- 子 Agent 输出 ---\",\n `[Phase 3 集成:此处将调用真实 spawnSubAgent()。任务:${prompt.slice(0, 200)}]`,\n ].join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * task — Background task CRUD operations.\n *\n * Tasks are managed by the agent engine's TaskManager and represent\n * long‑running operations (file watchers, MCP heartbeats, etc.).\n * This tool lets the model inspect and stop running tasks.\n *\n * The descriptor stays unchanged; the handler is injected with a real\n * TaskManager during bootstrap via {@link injectTaskManager}.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\n/**\n * TaskManager 的最小接口 — lynx-tools 不依赖 lynx-agent,\n * 实际实例在 bootstrap 时注入。\n */\nexport interface TaskManagerOps {\n start(id: string, label: string, run: (signal: AbortSignal) => Promise<void>): Promise<void>;\n stop(id: string): Promise<void>;\n get(id: string):\n | {\n id: string;\n label: string;\n status: string;\n startedAt: number;\n stoppedAt?: number;\n error?: string;\n output?: string;\n progress?: number;\n }\n | undefined;\n list(): Array<{ id: string; label: string; status: string }>;\n getOutput(id: string): string;\n update(id: string, patch: { label?: string; status?: string }): void;\n}\n\nexport const descriptor: ToolDescriptor = {\n name: \"task\",\n description:\n \"管理后台任务——创建、列表、获取、更新或停止任务。\" +\n \"任务持久化到 SQLite,会话重启后仍存在。\" +\n \"适用于跨多个会话的长时间运行操作。\",\n inputSchema: {\n type: \"object\",\n properties: {\n action: {\n type: \"string\",\n enum: [\"create\", \"list\", \"get\", \"update\", \"stop\"],\n description: \"CRUD 操作:创建新任务、列出所有任务、获取特定任务、更新状态或停止/取消\",\n },\n task_id: { type: \"string\", description: \"任务 UUID(get/update/stop 操作必需)\" },\n type: {\n type: \"string\",\n description: \"任务类型,例如 'mcp_connect'、'plugin_install'(create 时使用)\",\n },\n payload: { type: \"object\", description: \"任务负载/数据(create/update 时使用)\" },\n status: {\n type: \"string\",\n enum: [\"queued\", \"running\", \"completed\", \"failed\", \"canceled\"],\n description: \"新状态(update 时使用)\",\n },\n },\n required: [\"action\"],\n },\n kind: \"ExecutesCode\",\n safety: \"WorkspaceSafe\",\n availability: { type: \"always\" },\n executor: \"core:task\",\n owner: \"core\",\n};\n\n// ── Module‑level TaskManager injection ─────────────────\n\n/** Backing TaskManager — injected during bootstrap, null before injection. */\nlet taskManager: TaskManagerOps | null = null;\n\n/**\n * Inject the real TaskManager backend.\n *\n * Called during bootstrap after the engine is created.\n * Before injection, the handler returns mock results for test compatibility.\n */\nexport function injectTaskManager(tm: TaskManagerOps): void {\n taskManager = tm;\n}\n\n// ── Handler factory ────────────────────────────────────\n\n/**\n * Create a task handler bound to a specific {@link TaskManagerOps}.\n *\n * Factory alternative to {@link injectTaskManager} — useful when the\n * handler needs to be registered independently of the module‑level singleton.\n */\nexport function createTaskHandler(tm: TaskManagerOps): ToolHandler {\n return buildHandler(tm);\n}\n\n// ── Internal handler builder ───────────────────────────\n\nfunction buildHandler(tm: TaskManagerOps | null): ToolHandler {\n return {\n async handle(invocation, signal): Promise<ToolResult> {\n const { action, task_id, type, payload, status } = invocation.payload as {\n action: \"create\" | \"list\" | \"get\" | \"update\" | \"stop\";\n task_id?: string;\n type?: string;\n payload?: Record<string, unknown>;\n status?: string;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"任务操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n // Use real TaskManager if injected, otherwise mock fallback\n if (tm) {\n return realDispatch(tm, action, task_id, type, payload, status, startTime);\n }\n return mockDispatch(action, task_id, type, payload, status, startTime);\n },\n };\n}\n\n// ── Real dispatch ───────────────────────────────────────\n\nasync function realDispatch(\n tm: TaskManagerOps,\n action: string,\n taskId: string | undefined,\n taskType: string | undefined,\n taskPayload: Record<string, unknown> | undefined,\n taskStatus: string | undefined,\n startTime: number,\n): Promise<ToolResult> {\n switch (action) {\n case \"create\": {\n // Tasks are started by the agent engine internally. This tool\n // only inspects and stops tasks; 'create' is a no‑op that explains this.\n return {\n success: true,\n content:\n \"任务创建由 Agent 引擎内部管理,无需手动创建。使用 'list' 查看当前运行中的任务,\" +\n \"使用 'get' 获取特定任务详情,使用 'stop' 停止任务。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n case \"list\": {\n const tasks = tm.list();\n if (tasks.length === 0) {\n return {\n success: true,\n content: \"当前没有运行中的后台任务。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const lines = tasks.map((t) => `- **${t.id}**: ${t.label} (${t.status})`);\n return {\n success: true,\n content: `后台任务列表(共 ${tasks.length} 项):\\n\\n${lines.join(\"\\n\")}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n case \"get\": {\n if (!taskId) {\n return {\n success: false,\n content: \"缺少必需参数 task_id\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const entry = tm.get(taskId);\n if (!entry) {\n return {\n success: true,\n content: `任务 \"${taskId}\" 未找到。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const output = tm.getOutput(taskId);\n const parts: string[] = [\n `**ID**: ${entry.id}`,\n `**标签**: ${entry.label}`,\n `**状态**: ${entry.status}`,\n `**开始时间**: ${new Date(entry.startedAt).toISOString()}`,\n ];\n if (entry.stoppedAt) {\n parts.push(`**停止时间**: ${new Date(entry.stoppedAt).toISOString()}`);\n }\n if (entry.error) {\n parts.push(`**错误**: ${entry.error}`);\n }\n if (entry.progress !== undefined) {\n parts.push(`**进度**: ${entry.progress}%`);\n }\n if (output) {\n parts.push(`**输出**:\\n${output}`);\n }\n return {\n success: true,\n content: parts.join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n case \"update\": {\n if (!taskId) {\n return {\n success: false,\n content: \"缺少必需参数 task_id\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const entry = tm.get(taskId);\n if (!entry) {\n return {\n success: true,\n content: `任务 \"${taskId}\" 未找到。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const patch: { label?: string; status?: string } = {};\n if (taskPayload?.label && typeof taskPayload.label === \"string\") {\n patch.label = taskPayload.label;\n }\n if (taskStatus) {\n patch.status = taskStatus;\n }\n if (Object.keys(patch).length === 0) {\n return {\n success: false,\n content: \"未提供要更新的字段。请指定 label 或 status。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n tm.update(taskId, patch);\n return {\n success: true,\n content: `任务 \"${taskId}\" 已更新:${JSON.stringify(patch)}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n case \"stop\": {\n if (!taskId) {\n return {\n success: false,\n content: \"缺少必需参数 task_id\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const entry = tm.get(taskId);\n if (!entry) {\n return {\n success: true,\n content: `任务 \"${taskId}\" 未找到。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n await tm.stop(taskId);\n return {\n success: true,\n content: `任务 \"${taskId}\"(${entry.label})已停止。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n default:\n return {\n success: false,\n content: `未知操作:${action}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n}\n\n// ── Mock dispatch (pre‑injection fallback) ──────────────\n\nfunction mockDispatch(\n action: string,\n taskId: string | undefined,\n taskType: string | undefined,\n taskPayload: Record<string, unknown> | undefined,\n taskStatus: string | undefined,\n startTime: number,\n): ToolResult {\n switch (action) {\n case \"create\":\n return {\n success: true,\n content: `任务已创建 [mock]:${taskType ?? \"generic\"} — Phase 4 TaskManager 接入后支持持久化。负载:${JSON.stringify(taskPayload ?? {})}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n case \"list\":\n return {\n success: true,\n content: \"任务列表 [mock]:暂无持久化任务。Phase 4 集成待完成。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n case \"get\":\n return {\n success: true,\n content: `任务 ${taskId} [mock]:未找到或 Phase 4 集成待完成。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n case \"update\":\n return {\n success: true,\n content: `任务 ${taskId} 已更新为 ${taskStatus ?? \"unknown\"} [mock]。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n case \"stop\":\n return {\n success: true,\n content: `任务 ${taskId} 已停止 [mock]。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n default:\n return {\n success: false,\n content: `未知操作:${action}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n}\n\n/** Exported handler — uses injectTaskManager() when wired, mock otherwise. */\nexport const handler: ToolHandler = buildHandler(null);\n","/**\n * team_create — Create a multi-agent collaboration team.\n *\n * Each member has a role, tool set, and model preference.\n * Default strategy: \"consensus\" (all members must agree on decisions).\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"team_create\",\n description:\n \"创建多 Agent 协作团队。每个成员拥有独立的角色、工具集和模型。\" +\n \"团队通过可配置的策略协作完成工作(默认:共识模式)。\",\n inputSchema: {\n type: \"object\",\n properties: {\n name: { type: \"string\", description: \"团队名称(会话内必须唯一)\" },\n members: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n name: { type: \"string\", description: \"成员显示名称\" },\n role: {\n type: \"string\",\n description: \"角色描述(例如 '安全审查员'、'代码架构师')\",\n },\n tools: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"该成员可用的工具(留空 = 全部工具)\",\n },\n model: { type: \"string\", description: \"该成员的模型覆盖\" },\n },\n required: [\"name\", \"role\"],\n },\n description: \"团队成员及其角色和能力\",\n },\n strategy: {\n type: \"string\",\n enum: [\"consensus\", \"majority\", \"delegated\"],\n description: \"决策策略:consensus(全员同意)、majority(投票)、delegated(领导者决策)\",\n },\n },\n required: [\"name\", \"members\"],\n },\n kind: \"ExecutesCode\",\n safety: \"RequiresApproval\",\n availability: { type: \"always\" },\n executor: \"core:team_create\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { name, members, strategy } = invocation.payload as {\n name: string;\n members: Array<{ name: string; role: string; tools?: string[]; model?: string }>;\n strategy?: \"consensus\" | \"majority\" | \"delegated\";\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"团队创建已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const strat = strategy ?? \"consensus\";\n const memberList = members\n .map((m) => ` - ${m.name} (${m.role})${m.model ? ` [${m.model}]` : \"\"}`)\n .join(\"\\n\");\n\n return {\n success: true,\n content: [\n `团队已创建:${name}`,\n `策略:${strat}`,\n `成员(${members.length} 人):`,\n memberList,\n \"\",\n \"[Phase 4 集成:通过 @24klynx/agent 子 Agent 通道实现真实团队编排]\",\n ].join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * team_delete — Delete a multi-agent collaboration team.\n *\n * Cascades: terminates all in-flight member tasks before deletion.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"team_delete\",\n description: \"删除多 Agent 协作团队。\" + \"移除团队前会终止所有正在执行的成员任务。\",\n inputSchema: {\n type: \"object\",\n properties: {\n team_id: { type: \"string\", description: \"团队标识(名称或 UUID)\" },\n },\n required: [\"team_id\"],\n },\n kind: \"ExecutesCode\",\n safety: \"RequiresApproval\",\n availability: { type: \"all\", exprs: [{ type: \"always\" }] },\n executor: \"core:team_delete\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { team_id } = invocation.payload as { team_id: string };\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"团队删除已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n return {\n success: true,\n content: [\n `团队已删除:${team_id}`,\n \"所有成员任务已终止。\",\n \"[Phase 4 集成:通过 @24klynx/agent 实现真实团队生命周期管理]\",\n ].join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * verify_plan_execution — Verify that a plan was executed completely.\n *\n * Checks each checkpoint's expected output against actual output.\n * Returns: { passed, failed, missing } counts + per-checkpoint details.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"verify_plan_execution\",\n description:\n \"验证计划执行是否匹配其规范。\" +\n \"逐一检查每个检查点的预期输出与实际输出是否一致。\" +\n \"在实施计划后使用此工具,确保无遗漏。\",\n inputSchema: {\n type: \"object\",\n properties: {\n plan_id: { type: \"string\", description: \"要验证的计划标识\" },\n checkpoints: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n description: { type: \"string\", description: \"该检查点的预期描述\" },\n expected: { type: \"string\", description: \"预期输出或状态\" },\n actual: { type: \"string\", description: \"实际观察到的输出或状态\" },\n },\n required: [\"description\", \"expected\", \"actual\"],\n },\n description: \"待验证的检查点列表\",\n },\n },\n required: [\"plan_id\", \"checkpoints\"],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:verify_plan_execution\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { plan_id, checkpoints } = invocation.payload as {\n plan_id: string;\n checkpoints: Array<{ description: string; expected: string; actual: string }>;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"验证已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const results = checkpoints.map((cp) => {\n // Simple string comparison (Phase 4: add semantic comparison via LLM)\n const passed = cp.expected.trim() === cp.actual.trim();\n return { ...cp, passed };\n });\n\n const passed = results.filter((r) => r.passed).length;\n const failed = results.filter((r) => !r.passed).length;\n const total = results.length;\n\n const lines = [\n `计划验证:${plan_id}`,\n `结果:${passed}/${total} 通过,${failed} 失败`,\n \"\",\n ...results.map((r) => {\n const icon = r.passed ? \"✓\" : \"✗\";\n return `${icon} ${r.description}\\n 预期:${r.expected.slice(0, 100)}\\n 实际:${r.actual.slice(0, 100)}`;\n }),\n ];\n\n return {\n success: true,\n content: lines.join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * remote_trigger — Trigger a remote task via HTTP callback.\n *\n * Sends an HTTP request to a remote URL and returns the response.\n * 30s timeout. Supports GET and POST methods.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"remote_trigger\",\n description:\n \"通过发送 HTTP 请求(webhook / CI 回调)触发远程任务。\" +\n \"支持 GET 和 POST 方法,可自定义请求头和请求体。默认超时 30 秒。\",\n inputSchema: {\n type: \"object\",\n properties: {\n url: { type: \"string\", format: \"uri\", description: \"要触发的远程 URL\" },\n method: {\n type: \"string\",\n enum: [\"GET\", \"POST\"],\n description: \"HTTP 方法(默认:POST)\",\n },\n headers: {\n type: \"object\",\n description: \"自定义 HTTP 请求头(例如 Authorization、Content-Type)\",\n },\n body: { type: \"string\", description: \"请求体(POST 时使用)\" },\n timeout: {\n type: \"integer\",\n description: \"请求超时时间,毫秒(默认:30000,最大:60000)\",\n },\n },\n required: [\"url\"],\n },\n kind: \"Network\",\n safety: \"RequiresApproval\",\n availability: { type: \"always\" },\n executor: \"core:remote_trigger\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { url, method, headers, body, timeout } = invocation.payload as {\n url: string;\n method?: \"GET\" | \"POST\";\n headers?: Record<string, string>;\n body?: string;\n timeout?: number;\n };\n\n const startTime = Date.now();\n const httpMethod = method ?? \"POST\";\n const timeoutMs = Math.min(timeout ?? 30_000, 60_000);\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"远程触发已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n signal.addEventListener(\n \"abort\",\n () => {\n clearTimeout(timeoutId);\n controller.abort();\n },\n { once: true },\n );\n\n const resp = await fetch(url, {\n method: httpMethod,\n headers: {\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"Lynx/1.0\",\n ...headers,\n },\n body: httpMethod === \"POST\" ? (body ?? undefined) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n const respBody = await resp.text().catch(() => \"(二进制响应)\");\n const truncated = respBody.length > 2000;\n const summary = truncated ? respBody.slice(0, 1997) + \"...\" : respBody;\n\n return {\n success: resp.ok,\n content: `HTTP ${resp.status} ${resp.statusText}\\n\\n${summary}`,\n metadata: { durationMs: Date.now() - startTime, truncated },\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if ((err as { name?: string }).name === \"AbortError\" || message.includes(\"abort\")) {\n return {\n success: false,\n content: signal.aborted ? \"操作已取消\" : `请求在 ${timeoutMs}ms 后超时`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n return {\n success: false,\n content: `远程触发失败:${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n },\n};\n","/**\n * ScheduleCronTool — 定时任务调度工具。\n *\n * 使用 cron 语法安排定时任务。支持一次性提醒和循环计划。\n * 任务持久化到 ~/.lynx/cron-jobs.json,进程重启后自动恢复。\n */\nimport { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { randomUUID } from \"node:crypto\";\nimport { homedir } from \"node:os\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\n// ── Types ─────────────────────────────────────────────\n\n/** cron 任务记录。 */\ninterface CronJob {\n id: string;\n cron: string;\n prompt: string;\n timer?: ReturnType<typeof setInterval> | ReturnType<typeof setTimeout>;\n nextFire: number;\n}\n\n// ── State ─────────────────────────────────────────────\n\nconst STORAGE_DIR = join(homedir(), \".lynx\");\nconst STORAGE_FILE = join(STORAGE_DIR, \"cron-jobs.json\");\n\n/** 活跃的 cron 任务映射,key 为 job UUID。 */\nconst jobs = new Map<string, CronJob>();\n\n/** 初始化:加载持久化任务并启动调度。 */\nfunction init(): void {\n try {\n const raw = readFileSync(STORAGE_FILE, \"utf-8\");\n const persisted: Array<{ id: string; cron: string; prompt: string }> = JSON.parse(raw);\n for (const j of persisted) {\n scheduleJob(j.id, j.cron, j.prompt);\n }\n } catch {\n // 文件不存在或损坏,从空开始\n }\n}\n\n/** 持久化所有任务到磁盘。 */\nfunction persist(): void {\n mkdirSync(STORAGE_DIR, { recursive: true });\n const arr: Array<{ id: string; cron: string; prompt: string }> = [];\n for (const job of jobs.values()) {\n arr.push({ id: job.id, cron: job.cron, prompt: job.prompt });\n }\n writeFileSync(STORAGE_FILE, JSON.stringify(arr, null, 2));\n}\n\n/** 根据 cron 表达式计算下次触发时间(简化实现)。 */\nfunction calcNextFire(cron: string): number {\n const now = new Date();\n\n // 支持 @ 别名\n if (cron === \"@hourly\") return now.getTime() + 3600_000;\n if (cron === \"@daily\") return now.getTime() + 86400_000;\n if (cron === \"@weekly\") return now.getTime() + 604800_000;\n\n const parts = cron.split(/\\s+/);\n if (parts.length !== 5) return now.getTime() + 60000; // 默认 1 分钟后\n\n const minute = parseField(parts[0], 0, 59);\n const hour = parseField(parts[1], 0, 23);\n\n if (minute !== null && hour !== null) {\n const next = new Date(now);\n next.setMinutes(next.getMinutes() + 1);\n next.setSeconds(0);\n next.setMilliseconds(0);\n return next.getTime();\n }\n\n return now.getTime() + 60000;\n}\n\n/** 解析 cron 字段值,支持 * 和步进语法。 */\nfunction parseField(field: string, _min: number, _max: number): number | null {\n if (field === \"*\") return 0;\n const step = field.match(/^\\*\\/(\\d+)$/);\n if (step) return parseInt(step[1], 10);\n const num = parseInt(field, 10);\n if (!isNaN(num)) return num;\n return null;\n}\n\n/** 调度一个 cron 任务。 */\nfunction scheduleJob(id: string, cron: string, prompt: string): CronJob {\n const nextFire = calcNextFire(cron);\n const delay = Math.max(0, nextFire - Date.now());\n\n const job: CronJob = { id, cron, prompt, nextFire };\n\n // 判断是否循环任务\n if (cron.includes(\"*\") || cron.startsWith(\"@\")) {\n // 循环任务:每 60 秒检查一次\n job.timer = setInterval(() => {\n const now = Date.now();\n if (now >= job.nextFire) {\n job.nextFire = calcNextFire(cron);\n }\n }, 60000);\n } else {\n // 一次性任务\n job.timer = setTimeout(() => {\n jobs.delete(id);\n persist();\n }, delay);\n }\n\n jobs.set(id, job);\n return job;\n}\n\n/** 验证 cron 表达式格式。 */\nfunction isValidCron(cron: string): boolean {\n if (cron.startsWith(\"@\") && [\"@hourly\", \"@daily\", \"@weekly\"].includes(cron)) {\n return true;\n }\n const parts = cron.trim().split(/\\s+/);\n if (parts.length !== 5) return false;\n return parts.every((p) => {\n if (p === \"*\") return true;\n if (/^\\*\\/\\d+$/.test(p)) return true;\n const n = parseInt(p, 10);\n return !isNaN(n);\n });\n}\n\n// ── 启动时加载 ───────────────────────────────────────\ninit();\n\n// ── Descriptor ────────────────────────────────────────\n\nexport const descriptor: ToolDescriptor = {\n name: \"ScheduleCronTool\",\n description:\n \"使用 cron 语法安排定时任务。任务在指定时间或间隔触发。\" +\n \"支持一次性提醒和循环计划。标准 cron 格式:分 时 日 月 周。\" +\n \"也支持 @hourly、@daily、@weekly 别名。\",\n inputSchema: {\n type: \"object\",\n properties: {\n action: {\n type: \"string\",\n enum: [\"create\", \"list\", \"delete\"],\n description: \"操作类型:创建任务、列出任务、删除任务\",\n },\n cron: {\n type: \"string\",\n description: \"5 字段 cron 表达式(如 '*/5 * * * *')或别名 @hourly/@daily/@weekly\",\n },\n prompt: {\n type: \"string\",\n description: \"任务触发时入队的提示文本\",\n },\n jobId: {\n type: \"string\",\n description: \"任务 ID(delete 操作时使用)\",\n },\n },\n required: [\"action\"],\n },\n kind: \"ExecutesCode\",\n safety: \"WorkspaceSafe\",\n availability: { type: \"always\" },\n executor: \"core:schedule_cron\",\n owner: \"core\",\n};\n\n// ── Handler ───────────────────────────────────────────\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { action, cron, prompt, jobId } = invocation.payload as {\n action: string;\n cron?: string;\n prompt?: string;\n jobId?: string;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"定时任务操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n switch (action) {\n case \"create\":\n return handleCreate(cron, prompt);\n case \"list\":\n return handleList();\n case \"delete\":\n return handleDelete(jobId);\n default:\n return {\n success: false,\n content: `未知操作:${action}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `定时任务操作失败:${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n },\n};\n\n// ── Action handlers ───────────────────────────────────\n\n/** 创建新的 cron 任务。 */\nfunction handleCreate(cron?: string, prompt?: string): ToolResult {\n if (!cron || !prompt) {\n return {\n success: false,\n content: \"缺少必要参数:cron 和 prompt 均为必填\",\n };\n }\n\n if (!isValidCron(cron)) {\n return {\n success: false,\n content: `无效的 cron 表达式:${cron}。格式:分 时 日 月 周(5 字段),或 @hourly/@daily/@weekly`,\n };\n }\n\n const id = randomUUID();\n const job = scheduleJob(id, cron, prompt);\n persist();\n\n const nextDate = new Date(job.nextFire).toISOString();\n return {\n success: true,\n content: `定时任务已创建。ID:${id}\\n计划:${cron}\\n下次触发:${nextDate}`,\n };\n}\n\n/** 列出所有活跃任务。 */\nfunction handleList(): ToolResult {\n if (jobs.size === 0) {\n return { success: true, content: \"当前无定时任务\" };\n }\n\n const lines: string[] = [];\n for (const job of jobs.values()) {\n const nextDate = new Date(job.nextFire).toISOString();\n lines.push(`${job.id} — ${job.cron} — 下次:${nextDate} — \"${job.prompt.slice(0, 40)}\"`);\n }\n\n return {\n success: true,\n content: `定时任务(${jobs.size}):\\n${lines.join(\"\\n\")}`,\n };\n}\n\n/** 删除指定任务。 */\nfunction handleDelete(jobId?: string): ToolResult {\n if (!jobId) {\n return { success: false, content: \"缺少 jobId 参数\" };\n }\n\n const job = jobs.get(jobId);\n if (!job) {\n return { success: false, content: `未找到任务:${jobId}` };\n }\n\n if (job.timer) {\n clearTimeout(job.timer);\n clearInterval(job.timer);\n }\n jobs.delete(jobId);\n persist();\n\n return { success: true, content: `任务 ${jobId} 已删除` };\n}\n","/**\n * WorkflowTool — 多步骤工作流定义和执行工具。\n *\n * 支持定义、运行、查看状态和列出工作流。\n * 工作流持久化到 ~/.lynx/workflows.json,进程重启后保留定义。\n */\nimport { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { randomUUID } from \"node:crypto\";\nimport { homedir } from \"node:os\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\n// ── Types ─────────────────────────────────────────────\n\n/** 工作流步骤定义。 */\ninterface WorkflowStep {\n name: string;\n toolName: string;\n args: Record<string, unknown>;\n}\n\n/** 工作流定义。 */\ninterface Workflow {\n id: string;\n name: string;\n steps: WorkflowStep[];\n createdAt: number;\n}\n\n// ── State ─────────────────────────────────────────────\n\nconst STORAGE_DIR = join(homedir(), \".lynx\");\nconst STORAGE_FILE = join(STORAGE_DIR, \"workflows.json\");\n\n/** 活跃的工作流映射,key 为 workflow UUID。 */\nconst workflows = new Map<string, Workflow>();\n\n/** 初始化:从磁盘加载持久化工作流。 */\nfunction init(): void {\n try {\n const raw = readFileSync(STORAGE_FILE, \"utf-8\");\n const persisted: Workflow[] = JSON.parse(raw);\n for (const w of persisted) {\n workflows.set(w.id, w);\n }\n } catch {\n // 文件不存在或损坏,从空开始\n }\n}\n\n/** 持久化所有工作流到磁盘。 */\nfunction persist(): void {\n mkdirSync(STORAGE_DIR, { recursive: true });\n writeFileSync(STORAGE_FILE, JSON.stringify(Array.from(workflows.values()), null, 2));\n}\n\n// ── 启动时加载 ───────────────────────────────────────\ninit();\n\n// ── Descriptor ────────────────────────────────────────\n\nexport const descriptor: ToolDescriptor = {\n name: \"WorkflowTool\",\n description:\n \"定义并执行多步骤工作流。每个步骤可以是一个工具调用,\" +\n \"步骤之间可以有依赖关系。支持 define(定义)、run(运行)、\" +\n \"status(查看状态)、list(列出所有)四种操作。\",\n inputSchema: {\n type: \"object\",\n properties: {\n action: {\n type: \"string\",\n enum: [\"define\", \"run\", \"status\", \"list\"],\n description: \"操作类型:定义工作流、运行工作流、查看状态、列出所有工作流\",\n },\n workflowId: {\n type: \"string\",\n description: \"工作流 ID(run/status 操作时使用)\",\n },\n name: {\n type: \"string\",\n description: \"工作流名称(define 操作时使用)\",\n },\n steps: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n name: { type: \"string\", description: \"步骤名称\" },\n toolName: { type: \"string\", description: \"要调用的工具名称\" },\n args: { type: \"object\", description: \"工具参数\" },\n },\n required: [\"name\", \"toolName\", \"args\"],\n },\n description: \"工作流步骤列表(define 操作时使用)\",\n },\n },\n required: [\"action\"],\n },\n kind: \"ExecutesCode\",\n safety: \"WorkspaceSafe\",\n availability: { type: \"always\" },\n executor: \"core:workflow\",\n owner: \"core\",\n};\n\n// ── Handler ───────────────────────────────────────────\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { action, workflowId, name, steps } = invocation.payload as {\n action: string;\n workflowId?: string;\n name?: string;\n steps?: WorkflowStep[];\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"工作流操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n switch (action) {\n case \"define\":\n return handleDefine(name, steps);\n case \"run\":\n return handleRun(workflowId);\n case \"status\":\n return handleStatus(workflowId);\n case \"list\":\n return handleList();\n default:\n return {\n success: false,\n content: `未知操作:${action}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `工作流操作失败:${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n },\n};\n\n// ── Action handlers ───────────────────────────────────\n\n/** 定义新工作流。 */\nfunction handleDefine(name?: string, steps?: WorkflowStep[]): ToolResult {\n if (!name || !steps || steps.length === 0) {\n return {\n success: false,\n content: \"缺少必要参数:name 和 steps 均为必填,且 steps 不能为空\",\n };\n }\n\n const id = randomUUID();\n const workflow: Workflow = { id, name, steps, createdAt: Date.now() };\n workflows.set(id, workflow);\n persist();\n\n const stepList = steps.map((s, i) => ` ${i + 1}. ${s.name} — 调用 ${s.toolName}`).join(\"\\n\");\n\n return {\n success: true,\n content: `工作流已定义。ID:${id}\\n名称:${name}\\n步骤:\\n${stepList}`,\n };\n}\n\n/** 运行工作流:返回步骤列表供 agent 按顺序执行。 */\nfunction handleRun(workflowId?: string): ToolResult {\n if (!workflowId) {\n return { success: false, content: \"缺少 workflowId 参数\" };\n }\n\n const workflow = workflows.get(workflowId);\n if (!workflow) {\n return { success: false, content: `未找到工作流:${workflowId}` };\n }\n\n const stepInstructions = workflow.steps\n .map((s, i) => {\n const argsStr = JSON.stringify(s.args);\n return `${i + 1}. **${s.name}** — 调用工具 \\`${s.toolName}\\`,参数:\\`${argsStr}\\``;\n })\n .join(\"\\n\");\n\n return {\n success: true,\n content: [\n `开始运行工作流:${workflow.name}(ID: ${workflow.id})`,\n \"\",\n \"按以下步骤依次执行:\",\n stepInstructions,\n \"\",\n \"请按顺序执行每个步骤,等待每步完成后再进行下一步。\",\n ].join(\"\\n\"),\n };\n}\n\n/** 查看工作流状态。 */\nfunction handleStatus(workflowId?: string): ToolResult {\n if (!workflowId) {\n return { success: false, content: \"缺少 workflowId 参数\" };\n }\n\n const workflow = workflows.get(workflowId);\n if (!workflow) {\n return { success: false, content: `未找到工作流:${workflowId}` };\n }\n\n const createdDate = new Date(workflow.createdAt).toISOString();\n const stepSummary = workflow.steps\n .map((s, i) => `${i + 1}. ${s.name}(工具:${s.toolName})`)\n .join(\"\\n\");\n\n return {\n success: true,\n content: [\n `工作流:${workflow.name}(ID: ${workflow.id})`,\n `创建时间:${createdDate}`,\n `步骤(${workflow.steps.length}):`,\n stepSummary,\n ].join(\"\\n\"),\n };\n}\n\n/** 列出所有工作流。 */\nfunction handleList(): ToolResult {\n if (workflows.size === 0) {\n return { success: true, content: \"暂无定义的工作流\" };\n }\n\n const lines: string[] = [];\n for (const w of workflows.values()) {\n const date = new Date(w.createdAt).toISOString().slice(0, 10);\n lines.push(`${w.id} — ${w.name}(${w.steps.length} 步骤,创建于 ${date})`);\n }\n\n return {\n success: true,\n content: `工作流(${workflows.size}):\\n${lines.join(\"\\n\")}`,\n };\n}\n","/**\n * TungstenTool — 重型并行 Agent 编排工具。\n *\n * \"Tungsten\" = 钨,象征高强度并行。\n * 将复杂任务拆解为子任务,生成并行执行计划和综合方案。\n * 实际并行执行由 agent 引擎的子 Agent 基础设施处理,\n * 本工具提供任务拆解和调度逻辑。\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\n// ── Types ─────────────────────────────────────────────\n\n/** 子任务分配。 */\ninterface SubtaskAssignment {\n id: number;\n name: string;\n description: string;\n suggestedAgentRole: string;\n}\n\n// ── Descriptor ────────────────────────────────────────\n\nexport const descriptor: ToolDescriptor = {\n name: \"TungstenTool\",\n description:\n \"重型复合工具:并行调度多个子 Agent 处理复杂任务的各个部分,然后综合结果。\" +\n \"支持 parallel(并行)、pipeline(流水线)、debate(辩论)三种策略。\" +\n \"适用于代码审查、多模块重构、全面调研等大规模任务。\",\n inputSchema: {\n type: \"object\",\n properties: {\n task: {\n type: \"string\",\n description: \"要执行的复杂任务描述\",\n },\n maxAgents: {\n type: \"number\",\n description: \"最大并行 Agent 数量(默认 3)\",\n },\n strategy: {\n type: \"string\",\n enum: [\"parallel\", \"pipeline\", \"debate\"],\n description: \"执行策略:parallel 并行执行、pipeline 流水线处理、debate 多角度辩论\",\n },\n },\n required: [\"task\"],\n },\n kind: \"ExecutesCode\",\n safety: \"WorkspaceSafe\",\n availability: { type: \"always\" },\n executor: \"core:tungsten\",\n owner: \"core\",\n};\n\n// ── Handler ───────────────────────────────────────────\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { task, maxAgents, strategy } = invocation.payload as {\n task: string;\n maxAgents?: number;\n strategy?: string;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"Tungsten 操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (!task || task.trim().length === 0) {\n return {\n success: false,\n content: \"缺少必要参数:task 为必填且不能为空\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n const agentCount = Math.min(Math.max(maxAgents ?? 3, 1), 10);\n const execStrategy = strategy ?? \"parallel\";\n\n // 拆解任务为子任务\n const subtasks = decomposeTask(task, agentCount);\n\n // 根据策略生成执行计划\n const plan = buildExecutionPlan(task, subtasks, agentCount, execStrategy);\n\n return {\n success: true,\n content: plan,\n metadata: { durationMs: Date.now() - startTime },\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `Tungsten 任务规划失败:${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n },\n};\n\n// ── Task decomposition ────────────────────────────────\n\n/**\n * 将任务拆解为子任务。\n *\n * 按语义标记(编号列表、段落、主题关键词)进行简单拆分。\n * 真实场景中可接入 LLM 辅助拆解以获得更精准的结果。\n */\nfunction decomposeTask(task: string, maxAgents: number): SubtaskAssignment[] {\n // 尝试按编号列表拆分:1. / 2. / - / *\n const numberedPattern = /(?:^|\\n)\\s*(?:\\d+[.)]\\s*|[-*]\\s+)(.+)/g;\n const matches: string[] = [];\n let match;\n while ((match = numberedPattern.exec(task)) !== null) {\n matches.push(match[1].trim());\n }\n\n if (matches.length >= 2) {\n // 有编号列表,直接作为子任务\n const count = Math.min(matches.length, maxAgents);\n return matches.slice(0, count).map((m, i) => ({\n id: i + 1,\n name: m.slice(0, 40),\n description: m,\n suggestedAgentRole: `${i + 1} 号子 Agent`,\n }));\n }\n\n // 按段落拆分\n const paragraphs = task\n .split(/\\n\\s*\\n/)\n .map((p) => p.trim())\n .filter((p) => p.length > 0);\n\n if (paragraphs.length >= 2) {\n const count = Math.min(paragraphs.length, maxAgents);\n const names = paragraphs.slice(0, count).map((p) => p.slice(0, 50));\n return names.map((n, i) => ({\n id: i + 1,\n name: n,\n description: paragraphs[i],\n suggestedAgentRole: `子 Agent ${i + 1}`,\n }));\n }\n\n // 按句子粗略拆分\n const sentences = task.split(/[..。!!??]+/).filter((s) => s.trim().length > 10);\n if (sentences.length >= 2) {\n const count = Math.min(sentences.length, maxAgents);\n return sentences.slice(0, count).map((s, i) => ({\n id: i + 1,\n name: s.trim().slice(0, 40),\n description: s.trim(),\n suggestedAgentRole: `子 Agent ${i + 1}`,\n }));\n }\n\n // 回退:单一子任务\n return [\n {\n id: 1,\n name: task.slice(0, 40),\n description: task,\n suggestedAgentRole: \"主执行 Agent\",\n },\n ];\n}\n\n// ── Plan generation ──────────────────────────────────\n\n/** 根据策略生成执行计划文本。 */\nfunction buildExecutionPlan(\n task: string,\n subtasks: SubtaskAssignment[],\n maxAgents: number,\n strategy: string,\n): string {\n const planLines: string[] = [\n \"═══════════════════════════════════════\",\n \" Tungsten 并行执行计划\",\n \"═══════════════════════════════════════\",\n \"\",\n `总任务:${task.slice(0, 120)}${task.length > 120 ? \"...\" : \"\"}`,\n `执行策略:${strategyLabel(strategy)}`,\n `并行 Agent 数:${maxAgents}`,\n `子任务数:${subtasks.length}`,\n \"\",\n \"── 子任务分配 ──\",\n \"\",\n ];\n\n for (const st of subtasks) {\n planLines.push(`[${st.id}] ${st.name}`);\n planLines.push(` 角色:${st.suggestedAgentRole}`);\n planLines.push(` 描述:${st.description.slice(0, 100)}`);\n planLines.push(\"\");\n }\n\n planLines.push(\"── 执行指令 ──\");\n planLines.push(\"\");\n\n switch (strategy) {\n case \"parallel\":\n planLines.push(\n \"所有子 Agent 同时并行执行各自的子任务。\",\n `请为每个子任务创建独立的 Agent,共 ${subtasks.length} 个,同时启动。`,\n \"完成后,由协调 Agent 综合所有结果形成最终输出。\",\n );\n break;\n case \"pipeline\":\n planLines.push(\n \"子任务按顺序流水线执行,每个子 Agent 的输出作为下一个的输入。\",\n `请依次启动 ${subtasks.length} 个 Agent,每个等待前一个完成后再开始。`,\n \"流水线末端的 Agent 产出最终结果。\",\n );\n break;\n case \"debate\":\n planLines.push(\n `每个子 Agent 从不同角度处理任务,共 ${subtasks.length} 个视角。`,\n \"各 Agent 独立产出观点/方案后,由协调 Agent 对比、批判、综合。\",\n \"最终输出应包括不同观点的对比分析和综合结论。\",\n );\n break;\n }\n\n planLines.push(\"\");\n planLines.push(\"── 综合指令 ──\");\n planLines.push(\"所有子任务完成后,将结果合并为统一的最终输出。\");\n planLines.push(\"═══════════════════════════════════════\");\n\n return planLines.join(\"\\n\");\n}\n\n/** 策略的中文标签。 */\nfunction strategyLabel(strategy: string): string {\n switch (strategy) {\n case \"parallel\":\n return \"并行\";\n case \"pipeline\":\n return \"流水线\";\n case \"debate\":\n return \"辩论\";\n default:\n return strategy;\n }\n}\n","/**\n * enter_plan_mode — Enter plan mode (read-only, design output only).\n *\n * In plan mode, all write tools are automatically denied by the permission pipeline\n * (Step 6: plan mode + write tool → deny). The agent can only read files and output\n * design documents.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"enter_plan_mode\",\n description:\n \"进入计划模式 — 切换为只读模式,Agent 只能读取文件和输出设计方案。\" +\n \"所有写入/编辑/执行工具将自动被拒绝。\" +\n \"在进行重大架构变更前使用此模式,以便在实施前获得用户对方案的认可。\",\n inputSchema: {\n type: \"object\",\n properties: {},\n required: [],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:enter_plan_mode\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(_invocation, signal): Promise<ToolResult> {\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"Operation cancelled\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n // The actual mode switch is handled by the permission pipeline (Step 6)\n // and the session state in lynx-agent. This tool is the trigger.\n return {\n success: true,\n content: [\n \"已进入计划模式。\",\n \"- 所有写入/编辑/执行工具当前已被拒绝。\",\n \"- 您可执行:读取文件、搜索代码、设计架构、编写计划。\",\n \"- 使用 exit_plan_mode 返回普通模式。\",\n ].join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * exit_plan_mode — Exit plan mode and return to the normal permission mode.\n *\n * Restores the previous PermissionMode. If the plan wasn't completed,\n * warns the user and asks for confirmation.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"exit_plan_mode\",\n description:\n \"退出计划模式,返回普通模式(写入工具重新启用)。\" + \"计划方案将在执行前展示给用户审批。\",\n inputSchema: {\n type: \"object\",\n properties: {},\n required: [],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:exit_plan_mode\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(_invocation, signal): Promise<ToolResult> {\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"Operation cancelled\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n return {\n success: true,\n content: [\n \"已退出计划模式。\",\n \"- 写入/编辑/执行工具已重新启用。\",\n \"- 计划方案已就绪,等待用户审批并执行。\",\n ].join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * enter_worktree — Create or enter a git worktree for isolated work.\n *\n * Worktrees are created under .claude/worktrees/. Each worktree has its own\n * branch and working directory. The agent's CWD is switched to the worktree.\n *\n * `name` and `path` are mutually exclusive:\n * - `name`: create a new worktree (auto-named if omitted)\n * - `path`: enter an existing worktree\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"enter_worktree\",\n description:\n \"创建新的 git worktree 或进入已有 worktree 进行隔离工作。\" +\n \"Worktree 存放在 .claude/worktrees/ 目录下。使用 name 参数创建新 worktree,使用 path 参数进入已有 worktree。\",\n inputSchema: {\n type: \"object\",\n properties: {\n name: {\n type: \"string\",\n description: \"新 worktree 的名称(与 path 互斥)。不填则自动生成随机名称。\",\n },\n path: {\n type: \"string\",\n description: \"要进入的已有 worktree 的路径(与 name 互斥)。\",\n },\n base_ref: {\n type: \"string\",\n description: \"分支的基准引用(默认:'fresh' 模式基于 origin/master,'head' 模式基于 HEAD)\",\n },\n },\n required: [],\n },\n kind: \"ExecutesCode\",\n safety: \"WorkspaceSafe\",\n availability: { type: \"all\", exprs: [{ type: \"always\" }] },\n executor: \"core:enter_worktree\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { name, path, base_ref } = invocation.payload as {\n name?: string;\n path?: string;\n base_ref?: string;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"Worktree 操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (name && path) {\n return {\n success: false,\n content: \"name 与 path 互斥。使用 name 创建新 worktree,或使用 path 进入已有 worktree。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (path) {\n return {\n success: true,\n content: `已进入已有 worktree:${path}\\n[Phase 4: 通过 @24klynx/agent 实现真正的 git worktree 切换]`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const worktreeName = name ?? `worktree-${Date.now().toString(36)}`;\n const ref = base_ref ?? \"fresh\";\n\n return {\n success: true,\n content: [\n `Worktree 已创建:${worktreeName}`,\n `基准引用:${ref}`,\n `位置:.claude/worktrees/${worktreeName}`,\n \"\",\n \"[Phase 4: 通过 @24klynx/agent 实现真正的 git worktree 创建 + 工作目录切换]\",\n ].join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * exit_worktree — Exit a worktree and return to the original working directory.\n *\n * Supports two actions:\n * - \"keep\": leave the worktree directory and branch intact\n * - \"remove\": delete the worktree directory and its branch\n *\n * For \"remove\", uncommitted changes require discard_changes: true.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"exit_worktree\",\n description:\n \"退出 git worktree 并返回原始目录。\" +\n \"使用 'keep' 保留 worktree,或使用 'remove' 删除(如有未提交变更需搭配 discard_changes)。\",\n inputSchema: {\n type: \"object\",\n properties: {\n action: {\n type: \"string\",\n enum: [\"keep\", \"remove\"],\n description: \"keep = 保留 worktree 不动,remove = 删除 worktree 及分支\",\n },\n discard_changes: {\n type: \"boolean\",\n description: \"当 action=remove 且 worktree 有未提交变更时必须设为 true\",\n },\n },\n required: [\"action\"],\n },\n kind: \"ExecutesCode\",\n safety: \"WorkspaceSafe\",\n availability: { type: \"all\", exprs: [{ type: \"always\" }] },\n executor: \"core:exit_worktree\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { action, discard_changes } = invocation.payload as {\n action: \"keep\" | \"remove\";\n discard_changes?: boolean;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"Worktree 操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (action === \"keep\") {\n return {\n success: true,\n content:\n \"已退出 worktree(保留在磁盘上)。已返回原始目录。\\n[Phase 4: 通过 @24klynx/agent 实现真正的 worktree 退出]\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (action === \"remove\" && !discard_changes) {\n return {\n success: false,\n content:\n \"Worktree 可能有未提交的变更。设置 discard_changes: true 强制删除,或使用 action: 'keep' 保留。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n return {\n success: true,\n content:\n \"Worktree 已删除(目录及分支均已删除)。已返回原始目录。\\n[Phase 4: 通过 @24klynx/agent 实现真正的 worktree 删除]\",\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * ConfigTool — 读取或修改 Lynx 配置。\n *\n * 配置存储在 ~/.lynx/config.json。支持四种操作:\n * - get: 获取指定 key 的配置值\n * - set: 设置指定 key 的配置值(原子写入)\n * - list: 列出所有配置项\n * - path: 返回配置文件路径\n */\nimport { readFileSync, writeFileSync, existsSync, mkdirSync, renameSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, dirname } from \"node:path\";\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"ConfigTool\",\n description:\n \"读取或修改 Lynx 配置。可以查看当前配置值或设置新的配置项。\" +\n \"支持四种操作:get(获取单个配置项)、set(设置配置项)、list(列出所有配置项)、path(查看配置文件路径)。\",\n inputSchema: {\n type: \"object\",\n properties: {\n action: {\n type: \"string\",\n enum: [\"get\", \"set\", \"list\", \"path\"],\n description: \"操作类型:get(获取)、set(设置)、list(列出全部)、path(查看路径)\",\n },\n key: {\n type: \"string\",\n description: \"配置项的键名(get/set 操作需要)\",\n },\n value: {\n type: \"string\",\n description: \"要设置的值(仅 set 操作需要)\",\n },\n },\n required: [\"action\"],\n },\n kind: \"WritesFiles\",\n safety: \"WorkspaceSafe\",\n availability: { type: \"always\" },\n executor: \"core:config_tool\",\n owner: \"core\",\n};\n\n/** 获取配置文件路径(POSIX 风格)。 */\nfunction resolveConfigPath(): string {\n const home = homedir();\n return join(home, \".lynx\", \"config.json\").replace(/\\\\/g, \"/\");\n}\n\n/** 加载当前配置,文件不存在时返回空对象。 */\nfunction loadConfig(path: string): Record<string, unknown> {\n if (!existsSync(path)) return {};\n try {\n return JSON.parse(readFileSync(path, \"utf-8\"));\n } catch {\n const backupPath = path + \".bak\";\n renameSync(path, backupPath);\n return {};\n }\n}\n\n/** 原子写入配置(先写临时文件再重命名)。 */\nfunction saveConfig(path: string, config: Record<string, unknown>): void {\n const dir = dirname(path);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n const tmpPath = path + \".tmp\";\n writeFileSync(tmpPath, JSON.stringify(config, null, 2) + \"\\n\", \"utf-8\");\n renameSync(tmpPath, path);\n}\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { action, key, value } = invocation.payload as {\n action: string;\n key?: string;\n value?: string;\n };\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"操作已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const configPath = resolveConfigPath();\n\n switch (action) {\n case \"path\": {\n return {\n success: true,\n content: configPath,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n case \"list\": {\n const config = loadConfig(configPath);\n const keys = Object.keys(config);\n if (keys.length === 0) {\n return {\n success: true,\n content: \"当前没有配置项。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const lines = keys.map((k) => `${k} = ${JSON.stringify(config[k])}`);\n return {\n success: true,\n content: lines.join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n case \"get\": {\n if (!key) {\n return {\n success: false,\n content: \"get 操作需要提供 key 参数。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const config = loadConfig(configPath);\n if (!(key in config)) {\n return {\n success: false,\n content: `配置项 \"${key}\" 不存在。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n return {\n success: true,\n content: JSON.stringify(config[key]),\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n case \"set\": {\n if (!key) {\n return {\n success: false,\n content: \"set 操作需要提供 key 参数。\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n const config = loadConfig(configPath);\n const setValue = value ?? \"\";\n config[key] = setValue;\n try {\n saveConfig(configPath, config);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `写入配置文件失败: ${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n return {\n success: true,\n content: `已设置 ${key} = ${JSON.stringify(setValue)}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n default: {\n return {\n success: false,\n content: `不支持的操作: ${action}。支持的操作: get, set, list, path。`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n }\n },\n};\n","/**\n * ask_user_question — Ask the user one or more questions and wait for answers.\n *\n * Supports single-select and multi-select questions. Up to 4 questions per call,\n * each with 2-4 options. The user can select \"Other\" for free-text input.\n *\n * This blocks the agent loop until the user responds.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"ask_user_question\",\n description:\n \"向用户提出一个或多个澄清性问题并等待回答。\" +\n \"支持单选、多选以及自由文本的「其他」选项。\" +\n \"当您被一个只有用户才能做决定的问题卡住时使用。\",\n inputSchema: {\n type: \"object\",\n properties: {\n questions: {\n type: \"array\",\n minItems: 1,\n maxItems: 4,\n items: {\n type: \"object\",\n properties: {\n question: { type: \"string\", description: \"向用户提出的完整问题\" },\n header: {\n type: \"string\",\n description: \"显示为标签的简短文字(最多 12 个字符)\",\n },\n options: {\n type: \"array\",\n minItems: 2,\n maxItems: 4,\n items: {\n type: \"object\",\n properties: {\n label: { type: \"string\", description: \"显示文本(1-5 个词)\" },\n description: {\n type: \"string\",\n description: \"对该选项含义的解释说明\",\n },\n },\n required: [\"label\", \"description\"],\n },\n description: \"可选项(2-4 个)。「其他」选项会自动追加。\",\n },\n multiSelect: { type: \"boolean\", description: \"是否允许多选\" },\n },\n required: [\"question\", \"header\", \"options\", \"multiSelect\"],\n },\n description: \"要提问的问题列表(1-4 个)\",\n },\n },\n required: [\"questions\"],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:ask_user_question\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { questions } = invocation.payload as {\n questions: Array<{\n question: string;\n header: string;\n options: Array<{ label: string; description: string }>;\n multiSelect: boolean;\n }>;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"提问已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n // This tool is special: it blocks the agent loop and requires the TUI\n // to render a modal and return user input. The real implementation lives\n // in lynx-cli bootstrap where the handler is wired to the TUI bridge.\n //\n // Phase 2 provides a mock for testing the tool contract.\n\n const questionList = questions\n .map((q, i) => {\n const opts = q.options.map((o) => ` - ${o.label}: ${o.description}`).join(\"\\n\");\n return `Q${i + 1}. [${q.header}] ${q.question}${q.multiSelect ? \" (multi-select)\" : \"\"}\\n${opts}`;\n })\n .join(\"\\n\\n\");\n\n return {\n success: true,\n content: [\n \"向用户提问:\",\n \"\",\n questionList,\n \"\",\n \"[Phase 4 TUI 集成: 通过 lynx-tui 桥接实现真正的 AskUserQuestion 弹窗]\",\n ].join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * brief — Generate a structured summary brief of the current context.\n *\n * Compresses the current conversation state into a structured summary with\n * configurable sections. Default sections: context, goal, progress, blockers, next.\n * Output format: markdown or JSON.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"brief\",\n description:\n \"生成当前对话上下文的结构化摘要简报。\" + \"适用于进度检查点、会话间交接、或向用户提供状态更新。\",\n inputSchema: {\n type: \"object\",\n properties: {\n format: {\n type: \"string\",\n enum: [\"markdown\", \"json\"],\n description: \"输出格式(默认:markdown)\",\n },\n sections: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"要包含的章节(默认:context, goal, progress, blockers, next)\",\n },\n },\n required: [],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:brief\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { format, sections } = invocation.payload as {\n format?: \"markdown\" | \"json\";\n sections?: string[];\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"简报生成已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const fmt = format ?? \"markdown\";\n const secs = sections ?? [\"context\", \"goal\", \"progress\", \"blockers\", \"next\"];\n\n if (fmt === \"json\") {\n const brief: Record<string, string> = {};\n for (const s of secs)\n brief[s] = `[Phase 3: real context extraction via @24klynx/agent compaction]`;\n return {\n success: true,\n content: JSON.stringify(brief, null, 2),\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const lines = [\"# Brief\", \"\"];\n for (const s of secs) {\n lines.push(\n `## ${s}`,\n \"\",\n `[Phase 3: real context extraction via @24klynx/agent compaction]`,\n \"\",\n );\n }\n\n return {\n success: true,\n content: lines.join(\"\\n\"),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * synthetic_output — Generate structured output constrained by a JSON Schema.\n *\n * Used for sub-agent-to-agent data passing. The content must conform to the\n * provided schema. The LLM retries automatically on validation failure.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"synthetic_output\",\n description:\n \"生成符合 JSON Schema 的结构化输出。\" +\n \"用于在子 Agent 和父 Agent 之间传递带类型的数据。\" +\n \"如果输出无法通过 schema 校验,LLM 会自动重试。\",\n inputSchema: {\n type: \"object\",\n properties: {\n schema: {\n type: \"object\",\n description: \"输出必须符合的 JSON Schema\",\n },\n content: {\n type: \"object\",\n description: \"结构化内容(必须与 schema 匹配)\",\n },\n },\n required: [\"schema\", \"content\"],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:synthetic_output\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { schema, content } = invocation.payload as {\n schema: Record<string, unknown>;\n content: Record<string, unknown>;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"合成输出已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n // TODO Phase 3: validate content against schema using Ajv or similar\n // For Phase 2: pass-through with basic validation\n if (!schema || typeof schema !== \"object\") {\n return {\n success: false,\n content: \"无效的 schema:必须为 JSON Schema 对象\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n return {\n success: true,\n content: JSON.stringify(content, null, 2),\n metadata: { durationMs: Date.now() - startTime },\n };\n },\n};\n","/**\n * sleep — Pause execution for a specified duration.\n *\n * Used for: waiting on external events, rate limit backoff, polling intervals.\n * Maximum 300 seconds. `reason` is required to prevent pointless waits.\n * Abort signal interrupts sleep early.\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"sleep\",\n description:\n \"暂停执行指定秒数。\" +\n \"用于速率限制退避、等待外部事件或轮询间隔。\" +\n \"最长 300 秒。必须提供原因。\",\n inputSchema: {\n type: \"object\",\n properties: {\n seconds: {\n type: \"number\",\n description: \"等待的秒数(最多 300)\",\n minimum: 1,\n maximum: 300,\n },\n reason: {\n type: \"string\",\n description: \"为什么需要等待(必填 — 防止无意义的等待)\",\n },\n },\n required: [\"seconds\", \"reason\"],\n },\n kind: \"ReadOnly\",\n safety: \"Safe\",\n availability: { type: \"always\" },\n executor: \"core:sleep\",\n owner: \"core\",\n};\n\nexport const handler: ToolHandler = {\n async handle(invocation, signal): Promise<ToolResult> {\n const { seconds, reason } = invocation.payload as {\n seconds: number;\n reason: string;\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"等待已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n const maxSeconds = 300;\n const clamped = Math.min(Math.max(1, Math.floor(seconds)), maxSeconds);\n\n if (clamped !== seconds) {\n // Clamped — warn but proceed\n }\n\n // Abort-aware sleep\n await new Promise<void>((resolve, reject) => {\n const timer = setTimeout(resolve, clamped * 1000);\n const onAbort = () => {\n clearTimeout(timer);\n reject(new Error(\"ABORTED\"));\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }).catch((err) => {\n if ((err as Error).message === \"ABORTED\") {\n // Expected — triggered by signal\n } else {\n throw err;\n }\n });\n\n const actualWait = Date.now() - startTime;\n\n if (signal.aborted) {\n return {\n success: true,\n content: `等待在 ${Math.round(actualWait / 1000)} 秒后被中断(请求:${clamped} 秒)。原因:${reason}`,\n metadata: { durationMs: actualWait },\n };\n }\n\n return {\n success: true,\n content: `已等待 ${clamped} 秒。原因:${reason}`,\n metadata: { durationMs: actualWait },\n };\n },\n};\n","/**\n * memory_write — 读写持久化长期记忆。\n *\n * 每个记忆条目以带 YAML frontmatter 的 markdown 文件形式存储在用户的\n * memory 目录(~/.lynx/memory/)中。AI 在启动时将这些文件加载到系统提示词中,\n * 实现跨会话的持久化记忆。\n *\n * 支持的操作:\n * - create / update / delete — 基本 CRUD\n * - search — 全文搜索记忆\n * - compact — 去重压缩相似条目\n * - forget — 按 glob 模式批量删除\n * - export — 导出全部记忆为 JSON\n * - import — 从 JSON 批量导入\n * - merge — 合并另一个 memory 目录\n *\n * 格式仿照 Claude Code 的记忆系统:\n * - Frontmatter: name, description, metadata.type\n * - 正文: 事实内容\n * - MEMORY.md 索引文件用于快速扫描\n */\n\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\nimport type { MemoryManager } from \"@24klynx/agent\";\n\nexport const descriptor: ToolDescriptor = {\n name: \"memory_write\",\n description:\n \"管理持久化记忆。支持以下操作:\" +\n \"create/update — 写入或更新一条记忆;\" +\n \"delete — 按名称删除;\" +\n \"search — 全文搜索记忆(按相关度排序);\" +\n \"compact — 去重压缩相似条目(Jaccard 相似度 > 0.8);\" +\n \"forget — 按 glob 模式批量删除匹配的记忆;\" +\n \"export — 导出全部记忆为 JSON 字符串;\" +\n \"import — 从 JSON 字符串批量导入记忆(跳过同名条目);\" +\n \"merge — 合并另一个 memory 目录中的记忆文件。\" +\n \"当用户要求记住某事、搜索记忆、清理重复记忆或迁移记忆时使用。\",\n inputSchema: {\n type: \"object\",\n properties: {\n action: {\n type: \"string\",\n enum: [\n \"create\",\n \"update\",\n \"delete\",\n \"search\",\n \"compact\",\n \"forget\",\n \"export\",\n \"import\",\n \"merge\",\n ],\n description:\n \"要执行的操作。create = 新建记忆,update = 更新已有记忆,\" +\n \"delete = 按名称删除,search = 全文搜索,\" +\n \"compact = 去重压缩,forget = 按 glob 批量删除,\" +\n \"export = 导出 JSON,import = 导入 JSON,merge = 合并目录。\",\n },\n name: {\n type: \"string\",\n description:\n \"记忆的简短 kebab-case 标识(例如 'user-prefers-pnpm')。用作文件名。\" +\n \"create/update/delete 操作必填。\",\n },\n content: {\n type: \"string\",\n description:\n \"记忆的完整 markdown 正文。用自然语言书写。\" +\n \"对于反馈/项目类记忆,请包含 **Why:** 和 **How to apply:** 段落。\" +\n \"使用 [[slug]] 引用关联相关记忆。\" +\n \"create/update 操作时提供。\",\n },\n description: {\n type: \"string\",\n description: \"一行摘要,用于在调用记忆时判断相关性。保持简短且具体。\",\n },\n type: {\n type: \"string\",\n enum: [\"user\", \"feedback\", \"project\", \"reference\"],\n description:\n \"记忆分类。'user' = 用户身份,'feedback' = 纠正/指引,\" +\n \"'project' = 进行中的工作/目标,'reference' = 外部资料引用。\",\n },\n query: {\n type: \"string\",\n description: \"搜索关键词,多个词用空格分隔(search 操作使用)。\",\n },\n pattern: {\n type: \"string\",\n description:\n \"glob 模式,用于匹配要删除的记忆名称(forget 操作使用)。\" + \"支持 * 和 ? 通配符。\",\n },\n data: {\n type: \"string\",\n description: \"要导入的 JSON 数据字符串,由 export 操作生成(import 操作使用)。\",\n },\n sourceDir: {\n type: \"string\",\n description: \"源 memory 目录的绝对路径(merge 操作使用)。\",\n },\n },\n required: [\"action\"],\n },\n kind: \"WritesFiles\",\n safety: \"WorkspaceSafe\",\n availability: { type: \"always\" },\n executor: \"core:memory_write\",\n owner: \"core\",\n};\n\n/**\n * 创建绑定到指定 {@link MemoryManager} 的 memory_write 处理器。\n *\n * 工厂模式 — 管理器在启动时注入,使工具写入真实的 memory 目录。\n */\nexport function createMemoryWriteHandler(memoryManager: MemoryManager): ToolHandler {\n return {\n async handle(invocation, _signal): Promise<ToolResult> {\n const payload = invocation.payload as {\n action?: string;\n name?: string;\n content?: string;\n description?: string;\n type?: \"user\" | \"feedback\" | \"project\" | \"reference\";\n query?: string;\n pattern?: string;\n data?: string;\n sourceDir?: string;\n };\n\n const action = payload.action ?? \"create\";\n\n switch (action) {\n case \"create\":\n case \"update\": {\n const { name, content } = payload;\n if (!name) {\n return {\n success: false,\n content: `缺少必填参数 \"name\"。`,\n };\n }\n if (!content) {\n return {\n success: false,\n content: `缺少必填参数 \"content\"。`,\n };\n }\n\n if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name)) {\n return {\n success: false,\n content: `无效的记忆名称 \"${name}\"。请使用 kebab-case 格式,仅含小写字母、数字和连字符(例如 \"user-prefers-pnpm\")。`,\n };\n }\n\n const effectiveType = payload.type ?? \"reference\";\n const updatedAt = Date.now();\n\n memoryManager.put({\n name,\n description: payload.description ?? \"\",\n type: effectiveType,\n content,\n updatedAt,\n filePath: \"\", // put() 内部处理文件路径\n });\n\n memoryManager.reload();\n\n const actionLabel = action === \"create\" ? \"已创建\" : \"已更新\";\n return {\n success: true,\n content: `记忆 \"${name}\" ${actionLabel}(类型:${effectiveType})。后续会话中将自动加载到上下文中。`,\n };\n }\n\n case \"delete\": {\n const { name } = payload;\n if (!name) {\n return {\n success: false,\n content: `缺少必填参数 \"name\"。`,\n };\n }\n\n const deleted = memoryManager.delete(name);\n if (deleted) {\n return {\n success: true,\n content: `记忆 \"${name}\" 已删除。`,\n };\n }\n return {\n success: false,\n content: `未找到名为 \"${name}\" 的记忆。`,\n };\n }\n\n case \"search\": {\n const { query } = payload;\n if (!query || !query.trim()) {\n return {\n success: false,\n content: `缺少必填参数 \"query\"(搜索关键词)。`,\n };\n }\n\n const results = memoryManager.search(query);\n if (results.length === 0) {\n return {\n success: true,\n content: `未找到与 \"${query}\" 匹配的记忆。`,\n };\n }\n\n const lines = [`搜索 \"${query}\" 找到 ${results.length} 条相关记忆:`, \"\"];\n for (const entry of results) {\n const typeLabel = entry.type;\n lines.push(`- **${entry.name}** [${typeLabel}]: ${entry.description}`);\n }\n return {\n success: true,\n content: lines.join(\"\\n\"),\n };\n }\n\n case \"compact\": {\n const before = memoryManager.list().length;\n const remaining = memoryManager.compact();\n const removed = before - remaining.length;\n\n if (removed === 0) {\n return {\n success: true,\n content: `去重压缩完成。未发现相似条目,${remaining.length} 条记忆保持不变。`,\n };\n }\n\n return {\n success: true,\n content: `去重压缩完成。移除了 ${removed} 条重复记忆,当前共 ${remaining.length} 条。`,\n };\n }\n\n case \"forget\": {\n const { pattern } = payload;\n if (!pattern || !pattern.trim()) {\n return {\n success: false,\n content: `缺少必填参数 \"pattern\"(glob 模式)。`,\n };\n }\n\n const count = memoryManager.forget(pattern);\n if (count === 0) {\n return {\n success: true,\n content: `没有记忆匹配模式 \"${pattern}\"。`,\n };\n }\n\n return {\n success: true,\n content: `已删除 ${count} 条匹配模式 \"${pattern}\" 的记忆。`,\n };\n }\n\n case \"export\": {\n const json = memoryManager.exportAll();\n return {\n success: true,\n content: json,\n };\n }\n\n case \"import\": {\n const { data } = payload;\n if (!data || !data.trim()) {\n return {\n success: false,\n content: `缺少必填参数 \"data\"(要导入的 JSON 数据)。`,\n };\n }\n\n const count = memoryManager.importAll(data);\n if (count === 0) {\n return {\n success: true,\n content: `未导入任何新记忆。JSON 数据可能为空,或所有条目已存在。`,\n };\n }\n\n return {\n success: true,\n content: `成功导入 ${count} 条新记忆。`,\n };\n }\n\n case \"merge\": {\n const { sourceDir } = payload;\n if (!sourceDir || !sourceDir.trim()) {\n return {\n success: false,\n content: `缺少必填参数 \"sourceDir\"(源目录路径)。`,\n };\n }\n\n const count = memoryManager.merge(sourceDir);\n if (count === 0) {\n return {\n success: true,\n content: `未合并任何新记忆。源目录可能不存在、为空,或所有条目已存在。`,\n };\n }\n\n return {\n success: true,\n content: `成功从 \"${sourceDir}\" 合并 ${count} 条新记忆。`,\n };\n }\n\n default:\n return {\n success: false,\n content: `不支持的操作 \"${action}\"。支持的操作:create, update, delete, search, compact, forget, export, import, merge。`,\n };\n }\n },\n };\n}\n","/**\n * McpAuthTool — 触发 MCP 服务器的重新认证流程(OAuth 或 XAA)。\n *\n * 用于在工具调用失败并返回认证错误时,支持模型主动触发重连。\n * 工厂函数注入 McpManager 的最小接口,避免 lynx-tools 依赖 lynx-agent。\n */\n\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\n/** McpManager 的最小接口 — lynx-tools 不依赖 lynx-agent。 */\nexport interface McpAuthOps {\n reconnect(serverName: string): Promise<{ status: string }>;\n}\n\n/** 工具描述符 — 注册到 ToolRegistry 的静态元数据。 */\nexport const descriptor: ToolDescriptor = {\n name: \"McpAuthTool\",\n description:\n \"触发 MCP 服务器的重新认证流程(OAuth 或 XAA)。\" + \"用于在工具调用失败并返回认证错误时。\",\n inputSchema: {\n type: \"object\",\n properties: {\n serverName: {\n type: \"string\",\n description: \"需要重新认证的 MCP 服务器名称\",\n },\n },\n required: [\"serverName\"],\n },\n kind: \"Network\",\n safety: \"RequiresApproval\",\n availability: { type: \"always\" as const },\n executor: \"core:mcp_auth\",\n owner: \"core\",\n};\n\n/**\n * 创建 McpAuthTool 的 handler,绑定到给定的 McpAuthOps。\n *\n * 工厂模式 — 实际 McpManager 在 bootstrap 时注入。\n */\nexport function createMcpAuthHandler(mcpOps: McpAuthOps): ToolHandler {\n return {\n async handle(invocation, signal): Promise<ToolResult> {\n const { serverName } = invocation.payload as {\n serverName: string;\n };\n\n if (!serverName || typeof serverName !== \"string\") {\n return { success: false, content: \"缺少必需参数 serverName\" };\n }\n\n if (signal.aborted) {\n return { success: false, content: \"操作已取消\" };\n }\n\n try {\n const result = await mcpOps.reconnect(serverName);\n return {\n success: true,\n content: `MCP 服务器 \"${serverName}\" 重新认证完成,当前状态:${result.status}`,\n };\n } catch (err) {\n return {\n success: false,\n content: `MCP 认证失败:${(err as Error).message}`,\n };\n }\n },\n };\n}\n","/**\n * SendMessageTool — 消息通道发送工具。\n *\n * 通过配置的消息通道(飞书等)发送通知或进度摘要。\n * 使用工厂模式注入 MessageSender 接口,避免硬依赖 lynx-channels。\n */\nimport type { ToolDescriptor, ToolHandler, ToolResult } from \"../../types.js\";\n\n// ── Local interface (no import from lynx-channels) ───\n\n/** 消息发送器接口 —— 由调用方注入具体实现。 */\nexport interface MessageSender {\n /**\n * 通过指定通道发送消息。\n * @param channel 通道标识(如 \"feishu\")\n * @param content 消息内容\n * @param recipients 可选接收人列表\n * @returns 包含 messageId 的结果\n */\n send(channel: string, content: string, recipients?: string[]): Promise<{ messageId: string }>;\n}\n\n// ── Descriptor ────────────────────────────────────────\n\nexport const descriptor: ToolDescriptor = {\n name: \"SendMessageTool\",\n description:\n \"通过配置的消息通道发送消息(飞书等)。\" +\n \"用于向用户发送通知或进度摘要。需要提前配置消息通道。\",\n inputSchema: {\n type: \"object\",\n properties: {\n channel: {\n type: \"string\",\n description: \"消息通道名称(如 feishu)\",\n },\n content: {\n type: \"string\",\n description: \"要发送的消息内容\",\n },\n recipients: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"接收人列表(可选)\",\n },\n },\n required: [\"channel\", \"content\"],\n },\n kind: \"Network\",\n safety: \"RequiresApproval\",\n availability: { type: \"always\" },\n executor: \"core:send_message\",\n owner: \"core\",\n};\n\n// ── Factory ───────────────────────────────────────────\n\n/**\n * 创建 SendMessageTool 的处理器。\n *\n * 通过工厂注入 MessageSender 实现,避免直接 import lynx-channels。\n * 在 bootstrap 阶段将真实的通道发送器注入此处。\n */\nexport function createSendMessageHandler(sender: MessageSender): ToolHandler {\n return {\n async handle(invocation, signal): Promise<ToolResult> {\n const { channel, content, recipients } = invocation.payload as {\n channel: string;\n content: string;\n recipients?: string[];\n };\n\n const startTime = Date.now();\n\n if (signal.aborted) {\n return {\n success: false,\n content: \"消息发送已取消\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n if (!channel || !content) {\n return {\n success: false,\n content: \"缺少必要参数:channel 和 content 均为必填\",\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n\n try {\n const result = await sender.send(channel, content, recipients);\n\n return {\n success: true,\n content: `消息已通过 ${channel} 发送${recipients ? ` 给 ${recipients.join(\", \")}` : \"\"}。消息 ID:${result.messageId}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n content: `消息发送失败(${channel}):${message}`,\n metadata: { durationMs: Date.now() - startTime },\n };\n }\n },\n };\n}\n","/**\n * Built‑in tools — canonical registration entry point.\n *\n * Every tool is defined as a (descriptor, handler) pair in its own module.\n * This index imports all of them and provides a single {@link registerBuiltinTools}\n * function that the bootstrap layer calls to populate the {@link ToolRegistry}.\n *\n * Tool categories:\n * files/ — filesystem operations (read, write, edit, glob, grep, web)\n * agent/ — sub‑agent orchestration\n * mode/ — plan mode / worktree lifecycle\n * interact/ — user interaction (questions, brief, sleep)\n */\n\nimport type { ToolRegistry } from \"../registry.js\";\n\n// ── Files ──────────────────────────────────────────\nimport { descriptor as readFileDesc, handler as readFileHandler } from \"./files/read-file.js\";\nimport { descriptor as writeFileDesc, handler as writeFileHandler } from \"./files/write-file.js\";\nimport { descriptor as editFileDesc, handler as editFileHandler } from \"./files/edit-file.js\";\nimport { descriptor as globDesc, handler as globHandler } from \"./files/glob.js\";\nimport { descriptor as grepDesc, handler as grepHandler } from \"./files/grep.js\";\nimport { descriptor as webFetchDesc, handler as webFetchHandler } from \"./files/web-fetch.js\";\nimport { descriptor as webSearchDesc, handler as webSearchHandler } from \"./files/web-search.js\";\nimport { descriptor as todoWriteDesc, handler as todoWriteHandler } from \"./files/todo-write.js\";\nimport { descriptor as powershellDesc, handler as powershellHandler } from \"./files/powershell.js\";\nimport {\n descriptor as notebookEditDesc,\n handler as notebookEditHandler,\n} from \"./files/notebook-edit.js\";\nimport { descriptor as secretScanDesc, handler as secretScanHandler } from \"./files/secret-scan.js\";\nimport { descriptor as lspDesc, handler as lspHandler } from \"./files/lsp.js\";\nimport { descriptor as replDesc, handler as replHandler } from \"./files/repl.js\";\n\n// ── Agent ──────────────────────────────────────────\nimport { descriptor as agentDesc, handler as agentHandler } from \"./agent/agent.js\";\nimport { descriptor as taskDesc, handler as taskHandler } from \"./agent/task.js\";\nimport { descriptor as teamCreateDesc, handler as teamCreateHandler } from \"./agent/team-create.js\";\nimport { descriptor as teamDeleteDesc, handler as teamDeleteHandler } from \"./agent/team-delete.js\";\nimport { descriptor as verifyPlanDesc, handler as verifyPlanHandler } from \"./agent/verify-plan.js\";\nimport {\n descriptor as remoteTriggerDesc,\n handler as remoteTriggerHandler,\n} from \"./agent/remote-trigger.js\";\nimport {\n descriptor as scheduleCronDesc,\n handler as scheduleCronHandler,\n} from \"./agent/schedule-cron.js\";\nimport { descriptor as workflowDesc, handler as workflowHandler } from \"./agent/workflow.js\";\nimport { descriptor as tungstenDesc, handler as tungstenHandler } from \"./agent/tungsten.js\";\n\n// ── Mode ───────────────────────────────────────────\nimport {\n descriptor as enterPlanModeDesc,\n handler as enterPlanModeHandler,\n} from \"./mode/enter-plan-mode.js\";\nimport {\n descriptor as exitPlanModeDesc,\n handler as exitPlanModeHandler,\n} from \"./mode/exit-plan-mode.js\";\nimport {\n descriptor as enterWorktreeDesc,\n handler as enterWorktreeHandler,\n} from \"./mode/enter-worktree.js\";\nimport {\n descriptor as exitWorktreeDesc,\n handler as exitWorktreeHandler,\n} from \"./mode/exit-worktree.js\";\nimport { descriptor as configToolDesc, handler as configToolHandler } from \"./mode/config-tool.js\";\n\n// ── Interact ───────────────────────────────────────\nimport {\n descriptor as askUserDesc,\n handler as askUserHandler,\n} from \"./interact/ask-user-question.js\";\nimport { descriptor as briefDesc, handler as briefHandler } from \"./interact/brief.js\";\nimport {\n descriptor as syntheticOutputDesc,\n handler as syntheticOutputHandler,\n} from \"./interact/synthetic-output.js\";\nimport { descriptor as sleepDesc, handler as sleepHandler } from \"./interact/sleep.js\";\n\n// ── Agent factories ────────────────────────────────────\nexport { injectTaskManager, createTaskHandler } from \"./agent/task.js\";\n\n// ── Memory ───────────────────────────────────────────\nexport { descriptor as memoryWriteDescriptor } from \"./memory/memory-write.js\";\nexport { createMemoryWriteHandler } from \"./memory/memory-write.js\";\n\n// ── ToolSearch ─────────────────────────────────────────\nexport { descriptor as toolSearchDescriptor } from \"./files/tool-search.js\";\nexport { createToolSearchHandler } from \"./files/tool-search.js\";\n\n// ── MCP ──────────────────────────────────────────────\nexport { descriptor as mcpCallToolDescriptor } from \"./mcp/call-tool.js\";\nexport { createMcpCallToolHandler } from \"./mcp/call-tool.js\";\nexport { descriptor as listMcpResourcesDescriptor } from \"./mcp/list-resources.js\";\nexport { createListMcpResourcesHandler } from \"./mcp/list-resources.js\";\nexport { descriptor as readMcpResourceDescriptor } from \"./mcp/read-resource.js\";\nexport { createReadMcpResourceHandler } from \"./mcp/read-resource.js\";\nexport { descriptor as mcpAuthDescriptor } from \"./mcp/mcp-auth.js\";\nexport { createMcpAuthHandler } from \"./mcp/mcp-auth.js\";\n\n// ── Interact factories ──────────────────────────────\nexport { descriptor as sendMessageDescriptor } from \"./interact/send-message.js\";\nexport { createSendMessageHandler } from \"./interact/send-message.js\";\n\n// ── Registration ────────────────────────────────────\n\n/** All built‑in (descriptor, handler) pairs in registration order. */\nconst BUILTIN_TOOLS: Array<{\n descriptor: typeof readFileDesc;\n handler: typeof readFileHandler;\n}> = [\n // Files\n { descriptor: readFileDesc, handler: readFileHandler },\n { descriptor: writeFileDesc, handler: writeFileHandler },\n { descriptor: editFileDesc, handler: editFileHandler },\n { descriptor: globDesc, handler: globHandler },\n { descriptor: grepDesc, handler: grepHandler },\n { descriptor: webFetchDesc, handler: webFetchHandler },\n { descriptor: webSearchDesc, handler: webSearchHandler },\n { descriptor: todoWriteDesc, handler: todoWriteHandler },\n { descriptor: powershellDesc, handler: powershellHandler },\n { descriptor: notebookEditDesc, handler: notebookEditHandler },\n { descriptor: secretScanDesc, handler: secretScanHandler },\n { descriptor: lspDesc, handler: lspHandler },\n { descriptor: replDesc, handler: replHandler },\n // Agent\n { descriptor: agentDesc, handler: agentHandler },\n { descriptor: taskDesc, handler: taskHandler },\n { descriptor: teamCreateDesc, handler: teamCreateHandler },\n { descriptor: teamDeleteDesc, handler: teamDeleteHandler },\n { descriptor: verifyPlanDesc, handler: verifyPlanHandler },\n { descriptor: remoteTriggerDesc, handler: remoteTriggerHandler },\n { descriptor: scheduleCronDesc, handler: scheduleCronHandler },\n { descriptor: workflowDesc, handler: workflowHandler },\n { descriptor: tungstenDesc, handler: tungstenHandler },\n // Mode\n { descriptor: enterPlanModeDesc, handler: enterPlanModeHandler },\n { descriptor: exitPlanModeDesc, handler: exitPlanModeHandler },\n { descriptor: enterWorktreeDesc, handler: enterWorktreeHandler },\n { descriptor: exitWorktreeDesc, handler: exitWorktreeHandler },\n { descriptor: configToolDesc, handler: configToolHandler },\n // Interact\n { descriptor: askUserDesc, handler: askUserHandler },\n { descriptor: briefDesc, handler: briefHandler },\n { descriptor: syntheticOutputDesc, handler: syntheticOutputHandler },\n { descriptor: sleepDesc, handler: sleepHandler },\n];\n\n/**\n * Register all built‑in tool (descriptor, handler) pairs with the given registry.\n *\n * Each pair is registered atomically — if one fails (duplicate name), the error\n * propagates so the caller can decide whether to abort or skip.\n */\nexport function registerBuiltinTools(registry: ToolRegistry): void {\n for (const { descriptor, handler } of BUILTIN_TOOLS) {\n registry.register(descriptor, handler);\n }\n}\n\n/** Return the list of built‑in descriptors (without registering). */\nexport function listBuiltinDescriptors(): (typeof BUILTIN_TOOLS)[number][\"descriptor\"][] {\n return BUILTIN_TOOLS.map((t) => t.descriptor);\n}\n","/**\n * Tool planner — decides which tools are visible to the LLM this turn.\n *\n * Called at the start of every agent loop iteration so tool visibility\n * can change dynamically (e.g. permission mode switch, MCP server connected,\n * feature flags toggled).\n */\n\nimport type { ToolDescriptor, ToolPlan, HiddenTool } from \"./types.js\";\nimport type { EvalContext } from \"./availability.js\";\nimport { evaluateAvailability } from \"./availability.js\";\nimport type { ToolRegistry } from \"./registry.js\";\n\n// ── Public API ─────────────────────────────────────\n\n/**\n * Compute the tool plan for the current turn.\n *\n * Every registered tool is evaluated against the availability context.\n * Visible tools go into the LLM catalog; hidden tools are returned with\n * a reason so the debug/log layer can report them.\n *\n * ```ts\n * const plan = buildToolPlan(registry, evalCtx);\n * console.log(`${plan.visible.length} visible, ${plan.hidden.length} hidden`);\n * ```\n */\nexport function buildToolPlan(registry: ToolRegistry, ctx: EvalContext): ToolPlan {\n const visible: ToolDescriptor[] = [];\n const hidden: HiddenTool[] = [];\n\n for (const tool of registry.listAll()) {\n const result = evaluateAvailability(tool.availability, ctx);\n\n if (result.available) {\n visible.push(tool);\n } else {\n hidden.push({\n tool,\n reason: result.reason ?? \"unknown\",\n });\n }\n }\n\n return { visible, hidden };\n}\n","/**\n * Sensitive file classification — 4‑level protection system.\n *\n * Levels (increasing severity):\n * Low — normal files, write allowed\n * Medium — config/build files, write prompts confirmation\n * High — env/secret files, read‑only (write blocked)\n * Critical — SSH/GPG keys, never read or write\n *\n * This replaces the flat `SENSITIVE_PATHS` Set in safety.ts\n * with a tiered system that enables fine‑grained access control.\n */\n\n// ── Types ─────────────────────────────────────────────\n\nexport type SensitivityLevel = \"Low\" | \"Medium\" | \"High\" | \"Critical\";\n\nexport interface SensitivityCheck {\n level: SensitivityLevel;\n pattern: string;\n}\n\n// ── Patterns — ordered from most to least specific ────\n\ninterface SensitivityRule {\n patterns: string[];\n level: SensitivityLevel;\n}\n\nconst RULES: readonly SensitivityRule[] = [\n {\n level: \"Critical\",\n patterns: [\n \"**/.ssh/**\",\n \"**/.gnupg/**\",\n \"**/.aws/**\",\n \"/etc/**\",\n \"/root/**\",\n \"/var/log/**\",\n \"/proc/**\",\n \"/sys/**\",\n \"/dev/**\",\n \"**/secrets/**\",\n \"**/.lynx/auth.json\",\n \"**/.claude/auth.json\",\n \"**/credentials.json\",\n // Windows system paths (normalised to forward slashes)\n \"C:/Windows/**\",\n \"C:/Windows/System32/**\",\n \"C:/Program Files/**\",\n ],\n },\n {\n level: \"High\",\n patterns: [\n \".env\",\n \".env.*\",\n \"!**/.env.example\",\n \"!**/.env.sample\",\n \"**/.git/config\",\n \"~/.lynx/config.json\",\n \"yarn.lock\",\n \"pnpm-lock.yaml\",\n \"package-lock.json\",\n \"**/id_rsa*\",\n \"**/id_ed25519*\",\n \"**/*.pem\",\n \"**/*.key\",\n ],\n },\n {\n level: \"Medium\",\n patterns: [\n \"package.json\",\n \"tsconfig.json\",\n \"tsconfig.*.json\",\n \"Cargo.toml\",\n \"Makefile\",\n \"Dockerfile\",\n \".github/workflows/**\",\n \"docker-compose.yml\",\n \"docker-compose.yaml\",\n \"**/deploy/**\",\n \"**/terraform/**\",\n ],\n },\n];\n\n// ── Helpers ──────────────────────────────────────────\n\n/**\n * Simple glob‑to‑regex for the path patterns we use.\n * Handles **, *, and ! (negation prefix).\n */\nfunction patternToRegex(pattern: string): { regex: RegExp; negate: boolean } {\n const negate = pattern.startsWith(\"!\");\n const body = negate ? pattern.slice(1) : pattern;\n\n let escaped = body\n .replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n .replace(/\\*\\*/g, \"<<<GLOBSTAR>>>\")\n .replace(/\\*/g, \"[^/]*\")\n .replace(/<<<GLOBSTAR>>>/g, \".*\");\n\n // If the pattern starts with ** or has no directory prefix, match anywhere\n if (body.startsWith(\"**/\") || !body.includes(\"/\")) {\n escaped = \"(?:.*/)?\" + escaped;\n }\n\n return { regex: new RegExp(`^${escaped}$`, \"i\"), negate };\n}\n\n// Compile rules once\ninterface CompiledRule {\n regex: RegExp;\n level: SensitivityLevel;\n negate: boolean;\n}\n\nlet _compiled: CompiledRule[] | null = null;\n\nfunction compiledRules(): CompiledRule[] {\n if (_compiled) return _compiled;\n _compiled = [];\n for (const rule of RULES) {\n for (const pattern of rule.patterns) {\n const { regex, negate } = patternToRegex(pattern);\n _compiled.push({ regex, level: rule.level, negate });\n }\n }\n return _compiled;\n}\n\n// ── Public API ────────────────────────────────────────\n\n/**\n * Classify a file path by sensitivity level.\n *\n * The path is tested against all rules in order. The first match wins.\n * Negation patterns (`!`) remove previous matches at the same level.\n *\n * @returns The sensitivity level for the given path.\n */\nexport function classifySensitivity(filePath: string): SensitivityLevel {\n // Normalize to forward slashes\n const norm = filePath.replace(/\\\\/g, \"/\");\n let result: SensitivityLevel = \"Low\";\n\n for (const { regex, level, negate } of compiledRules()) {\n if (regex.test(norm)) {\n if (negate) {\n // Negation clears a previous match at this level\n if (result === level) result = \"Low\";\n } else {\n // Higher severity wins\n if (severityOrder(level) > severityOrder(result)) {\n result = level;\n }\n }\n }\n }\n\n return result;\n}\n\n/**\n * Returns true if the path requires special handling\n * (Medium or higher sensitivity).\n */\nexport function isSensitive(filePath: string): boolean {\n return classifySensitivity(filePath) !== \"Low\";\n}\n\n/**\n * Get all paths at a given sensitivity level or higher.\n * For use in permission prompts and audit displays.\n */\nexport function getSensitivitySummary(filePath: string): SensitivityCheck {\n return {\n level: classifySensitivity(filePath),\n pattern: filePath,\n };\n}\n\n// ── Internal helpers ─────────────────────────────────\n\nconst SEVERITY_MAP: Record<SensitivityLevel, number> = {\n Low: 0,\n Medium: 1,\n High: 2,\n Critical: 3,\n};\n\nfunction severityOrder(level: SensitivityLevel): number {\n return SEVERITY_MAP[level];\n}\n","/**\n * Command safety classification — 4 levels from totally safe to dangerous.\n *\n * This mirrors Claude Code's 4‑level system and CodeWhale's ExecPolicyEngine:\n *\n * Safe — read‑only, no side effects (e.g. file listing)\n * WorkspaceSafe — writes only within the workspace root\n * RequiresApproval — needs user confirmation (e.g. network access)\n * Dangerous — always requires approval (e.g. raw shell eval)\n */\n\nimport type { CommandSafety } from \"./types.js\";\nimport { classifySensitivity, type SensitivityLevel } from \"./safety/sensitive.js\";\n\n// ── Sensitivity mapping ──────────────────────────────\n\n/**\n * Map the 4‑level file sensitivity to a minimum command safety level.\n *\n * Low → no escalation\n * Medium → WorkspaceSafe (write needs confirmation)\n * High → RequiresApproval (read is ok, write is blocked)\n * Critical → Dangerous (no read, no write)\n */\nconst SENSITIVITY_ESCALATION: Record<SensitivityLevel, CommandSafety | null> = {\n Low: null,\n Medium: \"WorkspaceSafe\",\n High: \"RequiresApproval\",\n Critical: \"RequiresApproval\",\n};\n\n// ── Safety override ────────────────────────────────\n\n/**\n * Escalate the safety level if the command touches a sensitive path.\n *\n * Uses the 4‑level sensitivity classification from {@link classifySensitivity}.\n * Even a \"Safe\" tool becomes Dangerous if it tries to read ~/.ssh.\n */\nexport function escalateForSensitivePaths(safety: CommandSafety, paths: string[]): CommandSafety {\n const SAFETY_ORDER: CommandSafety[] = [\"Safe\", \"WorkspaceSafe\", \"RequiresApproval\", \"Dangerous\"];\n\n let maxSensitivity: SensitivityLevel = \"Low\";\n for (const p of paths) {\n const level = classifySensitivity(p);\n if (SENSITIVITY_ORDER[level] > SENSITIVITY_ORDER[maxSensitivity]) {\n maxSensitivity = level;\n }\n }\n\n const minSafety = SENSITIVITY_ESCALATION[maxSensitivity];\n if (minSafety && SAFETY_ORDER.indexOf(safety) < SAFETY_ORDER.indexOf(minSafety)) {\n return minSafety;\n }\n\n return safety;\n}\n\nconst SENSITIVITY_ORDER: Record<SensitivityLevel, number> = {\n Low: 0,\n Medium: 1,\n High: 2,\n Critical: 3,\n};\n\n// ── Quick checks ───────────────────────────────────\n\n/**\n * Returns true if the tool requires interactive user confirmation.\n */\nexport function needsApproval(safety: CommandSafety): boolean {\n return safety === \"RequiresApproval\" || safety === \"Dangerous\";\n}\n\n/**\n * Returns true if the tool can run automatically in yolo/headless mode.\n */\nexport function isHeadlessSafe(safety: CommandSafety): boolean {\n return safety === \"Safe\" || safety === \"WorkspaceSafe\";\n}\n\n// ── Safety labels ──────────────────────────────────\n\n/** Human‑readable labels for each safety level. */\nexport const SAFETY_LABELS: Record<CommandSafety, string> = {\n Safe: \"安全(只读,无副作用)\",\n WorkspaceSafe: \"工作区安全(仅在项目内写入)\",\n RequiresApproval: \"需要审批\",\n Dangerous: \"危险(始终需要确认)\",\n};\n","/**\n * Unicode sanitization — remove invisible and control characters\n * that could be used for prompt injection attacks.\n *\n * All patterns use new RegExp() with \\\\uXXXX string escapes\n * to avoid filesystem encoding of literal Unicode characters.\n *\n * References:\n * - Unicode Technical Report #36 (Security Considerations)\n * - CWE-838: Inappropriate Encoding for Output Context\n */\n\n// ── Pattern definitions ──────────────────────────────\n\ninterface StripRule {\n /** Human label for the character class being stripped. */\n label: string;\n /** RegExp source string (uses \\\\uXXXX escapes). */\n source: string;\n /** RegExp flags. */\n flags: string;\n /** Replacement string. */\n replacement: string;\n}\n\nconst STRIP_RULES: readonly StripRule[] = [\n {\n label: \"zero-width spaces\",\n source: \"[\\\\u200B-\\\\u200F]\",\n flags: \"g\",\n replacement: \"\",\n },\n {\n label: \"bidi overrides\",\n source: \"[\\\\u202A-\\\\u202E]\",\n flags: \"g\",\n replacement: \"\",\n },\n {\n label: \"deprecated format chars\",\n source: \"[\\\\u2060-\\\\u2069]\",\n flags: \"g\",\n replacement: \"\",\n },\n {\n label: \"byte order mark\",\n source: \"\\\\uFEFF\",\n flags: \"g\",\n replacement: \"\",\n },\n {\n label: \"variation selectors\",\n source: \"[\\\\uFE00-\\\\uFE0F]\",\n flags: \"g\",\n replacement: \"\",\n },\n {\n label: \"soft hyphen\",\n source: \"\\\\u00AD\",\n flags: \"g\",\n replacement: \"\",\n },\n {\n label: \"line separator\",\n source: \"\\\\u2028\",\n flags: \"g\",\n replacement: \"\\n\",\n },\n {\n label: \"paragraph separator\",\n source: \"\\\\u2029\",\n flags: \"g\",\n replacement: \"\\n\\n\",\n },\n {\n label: \"interlinear annotation anchors\",\n source: \"[\\\\uFFF9-\\\\uFFFB]\",\n flags: \"g\",\n replacement: \"\",\n },\n // Tag characters U+E0001..U+E007F use surrogate pair 󠀁..󠁿.\n // Character class can't span surrogate pairs, so match the high surrogate\n // followed by a low surrogate range.\n {\n label: \"tag characters\",\n source: \"\\\\uDB40[\\\\uDC01-\\\\uDC7F]\",\n flags: \"gu\",\n replacement: \"\",\n },\n];\n\n// Cache\nlet _compiled: Array<{ regex: RegExp; replacement: string; label: string }> | null = null;\n\nfunction compiledRules(): Array<{ regex: RegExp; replacement: string; label: string }> {\n if (_compiled) return _compiled;\n _compiled = STRIP_RULES.map((rule) => ({\n regex: new RegExp(rule.source, rule.flags),\n replacement: rule.replacement,\n label: rule.label,\n }));\n return _compiled;\n}\n\n// ── Public API ────────────────────────────────────────\n\n/**\n * Strip invisible and potentially dangerous Unicode characters from text.\n *\n * Preserves CJK Unified ideographs, emoji, combining diacritical marks,\n * and other legitimate Unicode.\n */\nexport function sanitizeUnicode(input: string): string {\n let output = input;\n for (const { regex, replacement } of compiledRules()) {\n output = output.replace(regex, replacement);\n }\n return output;\n}\n\n/**\n * Check if a string contains any suspicious Unicode characters.\n *\n * Returns the code point of the first offending character, or null if clean.\n */\nexport function findSuspiciousChars(input: string): string | null {\n for (const { regex, label } of compiledRules()) {\n const fresh = new RegExp(regex.source, regex.flags);\n if (fresh.test(input)) {\n return label;\n }\n }\n return null;\n}\n","/**\n * Path traversal / jailbreak detection.\n *\n * Verifies that a resolved file path stays within the workspace root.\n * Also catches null-byte injection attacks that can truncate paths\n * in C‑based filesystem APIs.\n */\n\nimport { resolve } from \"node:path\";\nimport { realpathSync, existsSync } from \"node:fs\";\n\n// ── Constants ────────────────────────────────────────\n\nconst NULL_BYTE_PATTERN = /\\x00/;\n\n// ── Public API ────────────────────────────────────────\n\n/**\n * Check whether a file path is safely contained within the workspace root.\n *\n * Algorithm:\n * 1. Reject paths containing null bytes (truncation attack).\n * 2. Resolve to absolute path, eliminating `../` segments.\n * 3. Resolve symlinks to their real physical location.\n * 4. Verify the final path starts with the workspace root.\n *\n * @returns true if the path is safely inside the workspace.\n */\nexport function isPathSafe(filePath: string, workspaceRoot: string): boolean {\n // Null‑byte injection — path is truncated at \\x00 in C APIs\n if (NULL_BYTE_PATTERN.test(filePath)) return false;\n\n const absolute = resolve(filePath);\n const wsRoot = resolve(workspaceRoot);\n\n // Check resolved path (handles ../ and .)\n if (!absolute.startsWith(wsRoot)) return false;\n\n // If the file already exists, also check the real path\n // (resolves symlinks that could point outside the workspace)\n try {\n if (existsSync(absolute)) {\n const real = realpathSync(absolute);\n return real.startsWith(wsRoot);\n }\n } catch {\n // realpath fails on broken symlinks — treat as unsafe\n return false;\n }\n\n return true;\n}\n\n/**\n * Returns the violation detail when a path escapes the workspace,\n * or null if the path is safe.\n *\n * Useful for audit logging and user‑facing error messages.\n */\nexport function getPathViolation(\n filePath: string,\n workspaceRoot: string,\n): { reason: string; resolved: string } | null {\n if (NULL_BYTE_PATTERN.test(filePath)) {\n return { reason: \"path contains null byte\", resolved: filePath };\n }\n\n const absolute = resolve(filePath);\n const wsRoot = resolve(workspaceRoot);\n\n if (!absolute.startsWith(wsRoot)) {\n return {\n reason: `resolved path \"${absolute}\" is outside workspace \"${wsRoot}\"`,\n resolved: absolute,\n };\n }\n\n try {\n if (existsSync(absolute)) {\n const real = realpathSync(absolute);\n if (!real.startsWith(wsRoot)) {\n return {\n reason: `real path \"${real}\" escapes workspace via symlink`,\n resolved: real,\n };\n }\n }\n } catch {\n return { reason: \"broken symlink\", resolved: absolute };\n }\n\n return null;\n}\n","/**\n * Trusted command whitelist — commands that are safe to execute\n * without interactive user confirmation.\n *\n * These are read‑only or read‑heavy commands that don't modify\n * the filesystem or network. Even in `--yolo` mode, commands\n * not on this list still go through safety escalation.\n */\n\n// ── Whitelist — sorted alphabetically ─────────────────\n\nconst TRUSTED_COMMANDS = new Set([\n \"bat\",\n \"cat\",\n \"df\",\n \"dir\", // Windows\n \"du\",\n \"echo\",\n \"env\",\n \"fd\",\n \"file\",\n \"find\",\n \"get-command\", // PowerShell\n \"grep\",\n \"head\",\n \"hostname\",\n \"less\",\n \"ls\",\n \"node\",\n \"pwd\",\n \"rg\",\n \"stat\",\n \"tail\",\n \"type\",\n \"uname\",\n \"wc\",\n \"where\",\n \"whereis\",\n \"which\",\n \"whoami\",\n]);\n\n// Sub‑command allowlist for commands whose safety depends on the sub‑command\nconst TRUSTED_SUBCOMMANDS: ReadonlyMap<string, Set<string>> = new Map([\n [\n \"git\",\n new Set([\n \"log\",\n \"status\",\n \"diff\",\n \"show\",\n \"branch\",\n \"tag\",\n \"rev-parse\",\n \"rev-list\",\n \"ls-files\",\n \"ls-tree\",\n \"describe\",\n \"shortlog\",\n \"stash\",\n \"blame\",\n ]),\n ],\n [\"npm\", new Set([\"list\", \"ls\", \"view\", \"info\", \"outdated\"])],\n [\"pnpm\", new Set([\"list\", \"ls\", \"view\", \"info\", \"outdated\", \"why\"])],\n]);\n\n// ── Public API ────────────────────────────────────────\n\n/**\n * Check if a command is on the trusted whitelist.\n *\n * For commands with sub‑command gating (git, npm, pnpm),\n * the first argument is checked against allowed sub‑commands.\n */\nexport function isTrustedCommand(command: string, args: string[] = []): boolean {\n // Direct match\n if (TRUSTED_COMMANDS.has(command)) return true;\n\n // Sub‑command match\n const allowed = TRUSTED_SUBCOMMANDS.get(command);\n if (allowed) {\n const sub = args[0];\n if (sub && allowed.has(sub)) return true;\n }\n\n // Version checks are always safe\n if (args.includes(\"--version\") || args.includes(\"-v\") || args.includes(\"-V\")) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Get the list of all trusted base commands (for display in help/config).\n */\nexport function getTrustedCommands(): ReadonlySet<string> {\n return TRUSTED_COMMANDS;\n}\n\n/**\n * Get trusted sub‑commands for a given base command.\n */\nexport function getTrustedSubcommands(command: string): ReadonlySet<string> | undefined {\n return TRUSTED_SUBCOMMANDS.get(command);\n}\n","/**\n * Blocked command blacklist — commands that are ALWAYS rejected\n * regardless of permission mode (including `--yolo`).\n *\n * These patterns match destructive or privilege‑escalation operations\n * that should never run through an AI agent.\n */\n\n// ── Blocklist — regex patterns ────────────────────────\n\ninterface BlockedPattern {\n /** Human‑readable reason for the block. */\n reason: string;\n /** Regex tested against the full command string (command + args). */\n pattern: RegExp;\n}\n\nconst BLOCKED_PATTERNS: readonly BlockedPattern[] = [\n {\n reason: \"cannot erase root filesystem\",\n pattern: /\\brm\\s+-rf\\s+\\/\\b/i,\n },\n {\n reason: \"cannot write raw disk devices\",\n pattern: /\\bdd\\s+if=/i,\n },\n {\n reason: \"cannot format filesystems\",\n pattern: /\\bmkfs\\./i,\n },\n {\n reason: \"cannot overwrite block devices\",\n pattern: />\\s*\\/dev\\/sd[a-z]/i,\n },\n {\n reason: \"cannot elevate privileges\",\n pattern: /\\bsudo\\b/i,\n },\n {\n reason: \"cannot switch user\",\n pattern: /\\bsu\\b(?:\\s+-)?/i,\n },\n {\n reason: \"cannot elevate via doas\",\n pattern: /\\bdoas\\b/i,\n },\n {\n reason: \"cannot make world‑writable files\",\n pattern: /\\bchmod\\s+777\\b/i,\n },\n {\n reason: \"cannot recursively chown root directory\",\n pattern: /\\bchown\\s+-R\\b.*\\s+\\//i,\n },\n {\n reason: \"cannot pipe curl to shell\",\n pattern: /\\bcurl\\b.*\\|\\s*(?:sh|bash)\\b/i,\n },\n {\n reason: \"cannot pipe wget to shell\",\n pattern: /\\bwget\\b.*\\|\\s*(?:sh|bash)\\b/i,\n },\n {\n reason: \"cannot force push to main/master\",\n pattern: /\\bgit\\s+push\\s+--force\\b.*\\b(?:main|master)\\b/i,\n },\n {\n reason: \"cannot delete git repository data\",\n pattern: /\\bgit\\s+reflog\\s+expire\\b/i,\n },\n {\n reason: \"cannot hard reset from remote\",\n pattern: /\\bgit\\s+reset\\s+--hard\\s+origin\\//i,\n },\n];\n\n// ── Public API ────────────────────────────────────────\n\n/**\n * Check if a command string matches any blocked pattern.\n *\n * @returns The block reason if blocked, or null if safe.\n */\nexport function isBlockedCommand(\n command: string,\n args: string[] = [],\n): { blocked: true; reason: string } | { blocked: false } {\n // Build the full command line for regex matching\n const fullCommand = args.length > 0 ? `${command} ${args.join(\" \")}` : command;\n\n for (const entry of BLOCKED_PATTERNS) {\n if (entry.pattern.test(fullCommand)) {\n return { blocked: true, reason: entry.reason };\n }\n }\n\n return { blocked: false };\n}\n\n/**\n * Get all blocked patterns for display in help/config/audit.\n */\nexport function getBlockedPatterns(): ReadonlyArray<{ reason: string; pattern: string }> {\n return BLOCKED_PATTERNS.map((p) => ({\n reason: p.reason,\n pattern: p.pattern.source,\n }));\n}\n","/**\n * Secret / key redaction — detect and redact sensitive credentials\n * from output before displaying to the user or logging.\n *\n * This is a defense‑in‑depth layer. The primary defense is never\n * reading .env / secret files, but if a secret leaks into output\n * (e.g. from a tool result or LLM response), we redact it here.\n */\n\n// ── Detection patterns ────────────────────────────────\n\ninterface SecretPattern {\n /** Human label for audit logging. */\n label: string;\n /** Regex to match the secret. */\n pattern: RegExp;\n /**\n * How to redact. \"partial\" keeps first 4 + last 4 chars;\n * \"full\" replaces the entire match.\n */\n mode: \"partial\" | \"full\";\n}\n\nconst SECRET_PATTERNS: readonly SecretPattern[] = [\n {\n label: \"OpenAI API key\",\n pattern: /sk-(?:proj-)?[A-Za-z0-9]{20,}/g,\n mode: \"partial\",\n },\n {\n label: \"DeepSeek API key\",\n pattern: /dsk-[A-Za-z0-9]{20,}/g,\n mode: \"partial\",\n },\n {\n label: \"Anthropic API key\",\n pattern: /sk-ant-(?:api\\d{2}-)?[A-Za-z0-9_-]{20,}/g,\n mode: \"partial\",\n },\n {\n label: \"GitHub token\",\n pattern: /gh[poiurse]_[A-Za-z0-9_]{36,}/g,\n mode: \"partial\",\n },\n {\n label: \"GitHub PAT\",\n pattern: /github_pat_[A-Za-z0-9_]{36,}/g,\n mode: \"partial\",\n },\n {\n label: \"AWS access key\",\n pattern: /AKIA[0-9A-Z]{16}/g,\n mode: \"partial\",\n },\n {\n label: \"AWS secret key\",\n pattern: /(?<=AWS_SECRET_ACCESS_KEY[=:])\\s*\\S+/gi,\n mode: \"full\",\n },\n {\n label: \"JWT token\",\n pattern: /eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+/g,\n mode: \"partial\",\n },\n {\n label: \"Private key header\",\n pattern: /-----BEGIN (?:RSA|EC|OPENSSH|DSA|PRIVATE) KEY-----/g,\n mode: \"full\",\n },\n {\n label: \"Generic base64 token\",\n pattern:\n /(?:(?:api_?key|auth_?token|access_?token|secret|password|apikey)[=:]\\s*)([A-Za-z0-9+/]{32,}={0,2})/gi,\n mode: \"full\",\n },\n];\n\n// ── Helpers ──────────────────────────────────────────\n\nfunction redactPartial(match: string): string {\n if (match.length < 8) return \"***\";\n return match.slice(0, 4) + \"...\" + match.slice(-4);\n}\n\n// ── Public API ────────────────────────────────────────\n\n/**\n * Redact all detected secrets from the given text.\n *\n * @returns The text with secrets replaced by `[REDACTED]` or `sk-...XyZ1`.\n */\nexport function redactSecrets(text: string): string {\n let result = text;\n for (const { pattern, mode } of SECRET_PATTERNS) {\n result = result.replace(pattern, (match) =>\n mode === \"partial\" ? redactPartial(match) : \"[REDACTED]\",\n );\n }\n return result;\n}\n\n/**\n * Scan text for secrets without redacting.\n *\n * @returns Array of detected secret labels (for audit/alerting).\n */\nexport function detectSecrets(text: string): string[] {\n const found: string[] = [];\n for (const { label, pattern } of SECRET_PATTERNS) {\n // Create a fresh regex to avoid stateful lastIndex issues\n const fresh = new RegExp(pattern.source, pattern.flags);\n if (fresh.test(text)) {\n found.push(label);\n }\n }\n return found;\n}\n\n/**\n * Check if the given text contains any detected secrets.\n */\nexport function hasSecrets(text: string): boolean {\n return detectSecrets(text).length > 0;\n}\n"],"mappings":"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"}