@agentdevjs/core 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/BasicAgent-UBGLABDV.js +12 -0
- package/dist/ExplorerAgent-C62LOUTX.js +12 -0
- package/dist/{chunk-BVF7RUXV.js → chunk-KCCLSQC4.js} +1 -1
- package/dist/chunk-KCCLSQC4.js.map +1 -0
- package/dist/{chunk-KO4DJKM6.js → chunk-OFBE43IS.js} +1 -1
- package/dist/{chunk-KO4DJKM6.js.map → chunk-OFBE43IS.js.map} +1 -1
- package/dist/{chunk-YFSM6IYU.js → chunk-TKVOWEJ2.js} +154 -49
- package/dist/chunk-TKVOWEJ2.js.map +1 -0
- package/dist/{chunk-574NG4UB.js → chunk-U3LWOJ3Q.js} +4 -4
- package/dist/chunk-U3LWOJ3Q.js.map +1 -0
- package/dist/{chunk-UCEIJEM5.js → chunk-V3WM6EII.js} +2 -2
- package/dist/chunk-V3WM6EII.js.map +1 -0
- package/dist/{chunk-TIJV6GJW.js → chunk-YYNP7MZC.js} +4 -3
- package/dist/chunk-YYNP7MZC.js.map +1 -0
- package/dist/features/example-feature/templates/example-tool.render.js.map +1 -1
- package/dist/features/opencode-basic/templates/edit.render.js +1 -1
- package/dist/features/opencode-basic/templates/edit.render.js.map +1 -1
- package/dist/features/opencode-basic/templates/glob.render.js.map +1 -1
- package/dist/features/opencode-basic/templates/grep.render.js.map +1 -1
- package/dist/features/opencode-basic/templates/ls.render.js.map +1 -1
- package/dist/features/opencode-basic/templates/read.render.js +1 -1
- package/dist/features/opencode-basic/templates/read.render.js.map +1 -1
- package/dist/features/opencode-basic/templates/write.render.js +1 -1
- package/dist/features/opencode-basic/templates/write.render.js.map +1 -1
- package/dist/features/skill/templates/skill.render.js.map +1 -1
- package/dist/features/subagent/templates/agent-close.render.js.map +1 -1
- package/dist/features/subagent/templates/agent-list.render.js.map +1 -1
- package/dist/features/subagent/templates/agent-send.render.js.map +1 -1
- package/dist/features/subagent/templates/agent-spawn.render.js.map +1 -1
- package/dist/features/subagent/templates/wait.render.js.map +1 -1
- package/dist/features/todo/templates/task-clear.render.js.map +1 -1
- package/dist/features/todo/templates/task-create.render.js.map +1 -1
- package/dist/features/todo/templates/task-list.render.js.map +1 -1
- package/dist/features/todo/templates/task-update.render.js.map +1 -1
- package/dist/index.d.ts +2276 -2024
- package/dist/index.js +519 -205
- package/dist/index.js.map +1 -1
- package/dist/{notification-5DFBYKKN.js → notification-CASV7QYT.js} +2 -2
- package/dist/{resolver-F5SM2RHQ.js → resolver-4JA7VPYP.js} +2 -2
- package/dist/{session-events-TETMQI45.js → session-events-S7LMJ6MM.js} +2 -2
- package/package.json +55 -55
- package/dist/BasicAgent-RPYJHYCM.js +0 -12
- package/dist/ExplorerAgent-ITTSJRJI.js +0 -12
- package/dist/chunk-574NG4UB.js.map +0 -1
- package/dist/chunk-BVF7RUXV.js.map +0 -1
- package/dist/chunk-TIJV6GJW.js.map +0 -1
- package/dist/chunk-UCEIJEM5.js.map +0 -1
- package/dist/chunk-YFSM6IYU.js.map +0 -1
- /package/dist/{BasicAgent-RPYJHYCM.js.map → BasicAgent-UBGLABDV.js.map} +0 -0
- /package/dist/{ExplorerAgent-ITTSJRJI.js.map → ExplorerAgent-C62LOUTX.js.map} +0 -0
- /package/dist/{notification-5DFBYKKN.js.map → notification-CASV7QYT.js.map} +0 -0
- /package/dist/{resolver-F5SM2RHQ.js.map → resolver-4JA7VPYP.js.map} +0 -0
- /package/dist/{session-events-TETMQI45.js.map → session-events-S7LMJ6MM.js.map} +0 -0
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/features/skill/index.ts","../src/core/feature.ts","../src/features/skill/tools.ts","../src/features/subagent/index.ts","../src/features/subagent/pool.ts","../src/features/subagent/tools.ts","../src/features/todo/index.ts","../src/features/todo/tools.ts","../src/features/user-input/index.ts","../src/features/file-history/index.ts","../src/features/file-history/file-history.ts","../src/features/handoff-seed/index.ts","../src/features/opencode-basic/index.ts","../src/features/opencode-basic/tools.ts","../src/features/example-feature/index.ts","../src/features/example-feature/tools.ts","../src/features/lsp/index.ts","../src/features/lsp/client.ts","../src/features/lsp/servers.ts","../src/features/lsp/which.ts","../src/features/output-guard/index.ts","../src/features/output-guard/truncate.ts","../src/core/config.ts","../src/core/feature-config.ts","../src/core/render.ts","../src/template/types.ts","../src/core/continuity/transforms/trim-transcript.ts","../src/core/continuity/transforms/summary.ts","../src/core/continuity/participant.ts","../src/core/workthread/store.ts","../src/core/workthread/inbox.ts","../src/core/workthread/bridge.ts","../src/core/workthread/core.ts","../src/core/workthread/board.ts"],"sourcesContent":["/**\n * Skill Feature - Skills 发现和 invoke_skill 工具\n *\n * 将 Skills 集成从 Agent 核心中解耦,实现可外挂功能\n *\n * @example\n * ```typescript\n * // 使用默认路径 .agentdev/skills\n * agent.use(new SkillFeature());\n *\n * // 使用自定义路径\n * agent.use(new SkillFeature('./custom/skills'));\n * agent.use(new SkillFeature({ dir: './custom/skills' }));\n * ```\n */\n\nimport { fileURLToPath } from 'url';\nimport { readFile } from 'fs/promises';\nimport { normalize, dirname } from 'path';\nimport type {\n AgentFeature,\n FeatureInitContext,\n FeatureManifestDefinition,\n ContextInjector,\n ToolContextValue,\n PackageInfo,\n} from '../../core/feature.js';\nimport { getPackageInfoFromSource } from '../../core/feature.js';\nimport type { Tool } from '../../core/types.js';\nimport type { CapabilityDefinition } from '../../core/capability.js';\nimport type { Logger } from '../../core/logging.js';\nimport { invokeSkillTool } from './tools.js';\nimport { discoverMulti, splitFrontmatter } from '../../skills/loader.js';\nimport type { SkillMetadata, SkillsOptions } from '../../skills/types.js';\nimport type { PlaceholderContext } from '../../template/types.js';\nimport { PlaceholderResolver } from '../../template/resolver.js';\n\n// ESM 中获取 __filename\nconst __filename = fileURLToPath(import.meta.url);\n\n/**\n * 技能文档注入时统一降级标题层级(+3,封顶 h6)。\n * SKILL.md 惯例以 `#` 开篇,聊天界面按 h1 渲染会撑爆消息块;\n * 注入场景只需要最小标题 + 正文的密度,保留相对层级即可。\n */\nfunction demoteHeadings(md: string): string {\n return md.replace(/^(#{1,6})(\\s)/gm, (_m, hashes: string, sep: string) => {\n return `${'#'.repeat(Math.min(hashes.length + 3, 6))}${sep}`;\n });\n}\n\n/**\n * Skill Feature 配置类型\n */\nexport interface SkillFeatureConfig extends SkillsOptions {\n /** Skills 目录路径 */\n dir?: string;\n /** 是否扫描 .agentdev/skills,默认 true */\n scanAgentdevDir?: boolean;\n /** 是否扫描 .claude/skills,默认 false */\n scanClaudeDir?: boolean;\n /** 额外 skills 目录列表 */\n extraDirs?: string[];\n /** 相对路径基准目录,默认 process.cwd() */\n baseDir?: string;\n}\n\n/**\n * Skill Feature 输入类型\n */\nexport type SkillFeatureInput = SkillFeatureConfig | string | undefined;\n\n/**\n * Skill Feature 实现\n */\nexport class SkillFeature implements AgentFeature {\n readonly name = 'skill';\n readonly source = __filename.replace(/\\\\/g, '/');\n readonly description = '发现本地 skills,并提供 invoke_skill 工具与技能数据源。';\n\n private skillsDir?: string;\n private skills: SkillMetadata[] = [];\n private featureSkills: SkillMetadata[] = [];\n private scanAgentdevDir: boolean = true;\n private scanClaudeDir: boolean = false;\n private extraDirs: string[] = [];\n\n private logger?: Logger;\n\n /**\n * 缓存包信息\n */\n private _packageInfo: PackageInfo | null = null;\n\n /**\n * 获取包信息(统一打包方案)\n */\n getPackageInfo(): PackageInfo | null {\n if (!this._packageInfo) {\n this._packageInfo = getPackageInfoFromSource(this.source);\n }\n return this._packageInfo;\n }\n\n /**\n * 获取模板名称列表(统一打包方案)\n */\n getTemplateNames(): string[] {\n return ['skill'];\n }\n\n constructor(input?: SkillFeatureInput) {\n if (typeof input === 'string') {\n // Relative paths must remain unresolved until onInitiate, when the\n // session-scoped workspaceDir is available. Resolving here would bind a\n // shared runtime to its host process cwd instead.\n this.skillsDir = input;\n } else if (input && typeof input === 'object') {\n this.skillsDir = input.dir;\n this.scanAgentdevDir = input.scanAgentdevDir ?? true;\n this.scanClaudeDir = input.scanClaudeDir ?? false;\n this.extraDirs = Array.isArray(input.extraDirs) ? input.extraDirs.filter(Boolean) : [];\n } else {\n this.skillsDir = undefined;\n }\n }\n\n /**\n * 获取同步工具(invoke_skill)\n */\n getTools(): Tool[] {\n return [invokeSkillTool];\n }\n\n /**\n * 将已发现的 skills 动态注册为 capability 命令。\n *\n * 每个 skill 一条 `skill.<name>` 命令,双入口:用户经 slash 菜单激活,\n * 或其他 feature / 编排经 registry invoke 激活。激活凭证是随消息流动\n * 的结构化通知(user-turn 的 capabilityActivations 元数据,见\n * onCapabilityActivations)——invoke 只做选中校验与审计,不承载激活态:\n * 排队投递、线程交接、后继会话等\"消息晚到 / 换进程\"场景下,激活通知\n * 始终作为消息本体的元数据到达,不依赖进程内暂存或输入文本解析。\n */\n getCapabilities(): CapabilityDefinition[] {\n return this.skills.map((skill) => ({\n name: skill.name,\n kind: 'prompt' as const,\n title: `技能:${skill.name}`,\n description: skill.description,\n entryPoints: ['slash', 'feature'],\n execute: () => {\n if (!this.skills.some((s) => s.name === skill.name)) {\n return Promise.reject(new Error(`skill \"${skill.name}\" no longer exists`));\n }\n return Promise.resolve({\n activated: skill.name,\n note: `技能「${skill.name}」已激活,随下一条消息自动加载`,\n });\n },\n }));\n }\n\n /**\n * 消费随消息到达的技能激活通知,注入对应技能文档。\n *\n * Agent 在两个消息落地点派发(新 call 的 onCall 第三参 / busy 排队\n * 消息的步边界注入),refs 只含本 feature 前缀的条目。文档以 system\n * 位置注入(与 flow 提示词 / force-continuation 的既有形态一致)。\n * 注入失败(文件缺失等)记日志,不阻断本轮 call。\n */\n async onCapabilityActivations(refs: string[], ctx: { context: import('../../core/context.js').Context }): Promise<void> {\n const names = new Set<string>();\n for (const ref of refs) {\n if (typeof ref !== 'string') continue;\n if (!ref.startsWith('skill.')) continue;\n names.add(ref.slice('skill.'.length));\n }\n if (names.size === 0) return;\n\n for (const skillName of names) {\n const skill = this.skills.find((s) => s.name === skillName);\n if (!skill) {\n this.logger?.warn(`Activated skill \"${skillName}\" no longer exists, skipped injection`);\n continue;\n }\n\n try {\n // frontmatter 原样保留但包进 yaml 围栏代码块:直接拼进 markdown 时\n // `---` 会渲染成水平线、YAML 文本被 setext 语法解析成大标题\n const { frontmatter, body } = splitFrontmatter(await readFile(skill.path, 'utf-8'));\n const content = [\n frontmatter ? ['```yaml', frontmatter, '```', ''].join('\\n') : '',\n body,\n ].filter(Boolean).join('\\n');\n const basePath = normalize(dirname(skill.path)).replace(/\\\\/g, '/');\n ctx.context.add({\n role: 'system',\n content: [\n `[技能激活:${skill.name}]`,\n `技能基础目录:\\`${basePath}\\``,\n '',\n '---',\n '',\n demoteHeadings(content),\n ].join('\\n'),\n });\n this.logger?.info(`Skill \"${skill.name}\" injected via turn activation notification`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n this.logger?.warn(`Failed to inject activated skill \"${skillName}\": ${msg}`);\n }\n }\n }\n\n /**\n * 向 Flow 暴露 Skills 相关变量\n */\n getFlowVariables() {\n return [\n {\n key: 'skillSummaryItems',\n type: 'string',\n title: '技能列表数组',\n description: '可用技能的“名称:介绍”数组,适合做变量遍历或直接插入。',\n resolver: () => this.skills.map(skill => `${skill.name}:${skill.description}`),\n },\n {\n key: 'skillSummaryText',\n type: 'string',\n title: '技能列表文本',\n description: '可用技能的多行文本版本,每行一条“- 名称:介绍”。',\n resolver: () => this.skills.map(skill => `- ${skill.name}:${skill.description}`).join('\\n'),\n },\n ];\n }\n\n /**\n * 向 Flow 暴露可直接复用的节点 Prompt 模板\n */\n getFlowNodeTemplates() {\n return [\n {\n id: 'skill-availability-prompt',\n name: '技能列表提示',\n description: '向 Agent 注入当前可用技能列表,并提示通过 invoke_skill 激活具体技能。',\n prompt: '你有以下技能可用,可使用invoke_skill工具激活:\\n{{skillSummaryText}}',\n tools: { enable: ['invoke_skill'] },\n },\n ];\n }\n\n getFeatureManifest(): FeatureManifestDefinition {\n return {\n schemaVersion: 1 as const,\n settings: {\n properties: {\n scanAgentdevDir: {\n type: 'boolean',\n title: '扫描 .agentdev/skills',\n description: '是否从工作目录的 .agentdev/skills/ 加载技能文件。',\n default: true,\n },\n scanClaudeDir: {\n type: 'boolean',\n title: '扫描 .claude/skills',\n description: '是否从工作目录的 .claude/skills/ 加载技能文件。',\n default: false,\n },\n extraDirs: {\n type: 'directory',\n title: '额外技能目录',\n description: '额外加载技能文件的目录列表(至多 5 个)。相对路径以工作目录为基准,绝对路径直接使用。同名技能会自动加后缀区分。',\n default: [],\n maxItems: 5,\n },\n },\n },\n };\n }\n\n /**\n * 声明上下文注入器\n * 为 invoke_skill 工具注入 _context.skills\n */\n getContextInjectors(): Map<string | RegExp, ContextInjector> {\n return new Map<string | RegExp, ContextInjector>([\n ['invoke_skill', (): ToolContextValue => ({ _context: { skills: this.skills } })],\n ]);\n }\n\n /**\n * 初始化钩子\n * 执行 Skills 发现并注册数据源\n *\n * featureConfig(运行时配置)覆盖构造函数的默认值。\n * 路径解析以 agent 的 workspaceDir 为基准。\n */\n async onInitiate(ctx: FeatureInitContext): Promise<void> {\n this.logger = ctx.logger;\n // 从 featureConfig 读取运行时配置,覆盖构造函数默认值\n const fc = ctx.featureConfig;\n let scanAgentdevDir = this.scanAgentdevDir;\n let scanClaudeDir = this.scanClaudeDir;\n let extraDirs = this.extraDirs;\n\n if (fc && typeof fc === 'object') {\n const c = fc as Record<string, unknown>;\n if (typeof c.scanAgentdevDir === 'boolean') scanAgentdevDir = c.scanAgentdevDir;\n if (typeof c.scanClaudeDir === 'boolean') scanClaudeDir = c.scanClaudeDir;\n if (Array.isArray(c.extraDirs)) {\n extraDirs = c.extraDirs.filter((d): d is string => typeof d === 'string' && d.trim() !== '');\n }\n }\n\n // 使用 agent 的 workspaceDir 作为路径基准\n const baseDir = ctx.config?.workspaceDir;\n\n // 使用多目录发现:.agentdev/skills + .claude/skills + 额外目录\n this.skills = await discoverMulti({\n dir: this.skillsDir,\n scanAgentdevDir,\n scanClaudeDir,\n extraDirs,\n baseDir,\n });\n\n // 合并 Feature 自带 skills,用户 skills 优先(同名覆盖)\n if (this.featureSkills.length > 0) {\n const userSkillNames = new Set(this.skills.map(s => s.name));\n for (const s of this.featureSkills) {\n if (!userSkillNames.has(s.name)) {\n this.skills.push(s);\n }\n }\n }\n\n // 注册 skills 数据源到 Agent 级注册表(per-Agent 实例,非进程全局)\n ctx.dataSourceRegistry.register({\n name: 'skills',\n getData: () => this.skills,\n renderItem: (skill: SkillMetadata, template: string, context: PlaceholderContext) => {\n const skillContext: PlaceholderContext = {\n ...context,\n name: skill.name,\n description: skill.description,\n this: skill,\n };\n return PlaceholderResolver.resolve(template, skillContext);\n },\n });\n }\n\n /**\n * 注入来自其他 Feature 的 skills\n * 由 Agent 在 onInitiate 之前调用\n */\n addFeatureSkills(skills: SkillMetadata[]): void {\n this.featureSkills = skills;\n }\n\n /**\n * 获取已加载的 Skills\n */\n getSkills(): SkillMetadata[] {\n return this.skills;\n }\n\n /**\n * 设置 Skills 目录\n */\n setSkillsDir(dir: string): void {\n this.skillsDir = dir;\n }\n}\n","/**\n * Feature System - 可外挂功能模块接口\n *\n * Feature 系统允许将功能(MCP、Skills、子代理等)从 Agent 核心中解耦,\n * 实现新功能的声明式注册和统一的生命周期管理。\n */\n\nimport type { Tool } from './types.js';\nimport type { ToolCall } from './types.js';\nimport type { InlineRenderTemplate } from './types.js';\nimport type { LLMClient } from './types.js';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { existsSync, readFileSync } from 'fs';\n\n/**\n * Feature 上下文值类型\n */\nexport type ToolContextValue = Record<string, unknown>;\n\n/**\n * Feature 上下文注入器\n * 返回要注入到 tool.execute() 的额外参数\n */\nexport type ContextInjector = (call: ToolCall) => ToolContextValue;\n\n/**\n * Feature 初始化上下文\n */\nexport interface FeatureInitContext {\n /** Agent ID */\n agentId: string;\n /** Agent 配置 */\n config: import('./types.js').AgentConfig;\n /** Feature 级结构化日志 */\n logger: import('./logging.js').Logger;\n /** Feature 特定配置 */\n featureConfig?: unknown;\n /** 获取其他 Feature */\n getFeature<T extends AgentFeature>(name: string): T | undefined;\n /** 注册工具 */\n registerTool(tool: Tool): void;\n /** Agent 级数据源注册表(per-Agent 实例,非进程全局) */\n dataSourceRegistry: import('../template/data-source.js').DataSourceRegistry;\n}\n\n/**\n * Feature 运行时上下文\n */\nexport interface FeatureContext {\n agentId: string;\n config: import('./types.js').AgentConfig;\n getFeature<T extends AgentFeature>(name: string): T | undefined;\n}\n\n/**\n * Feature 快照状态\n *\n * 第一阶段只支持显式白名单状态:\n * - Feature 自己决定要保存什么\n * - 未声明的状态一律不保证恢复\n */\nexport type FeatureStateSnapshot = unknown;\n\n/**\n * 包信息\n */\nexport interface PackageInfo {\n /** 包名,如 '@agentdevjs/shell-feature' 或 'agentdev' */\n name: string;\n /** 版本号(可选) */\n version?: string;\n /** 包根目录绝对路径 */\n root: string;\n}\n\n/**\n * 模板信息\n */\nexport interface TemplateInfo {\n /** 包名 */\n packageName: string;\n /** 模板名(不含扩展名) */\n templateName: string;\n}\n\n/**\n * Feature Manifest 配置项\n *\n * 用于声明 Feature 在 Agent Project 级别可配置的静态参数。\n * Claw 等消费端可根据该契约自动渲染表单。\n */\nexport interface FeatureManifestSettingProperty {\n type: 'string' | 'number' | 'boolean' | 'select' | 'file' | 'directory' | 'group';\n title: string;\n description?: string;\n default?: unknown;\n options?: Array<{ label: string; value: string | number | boolean }>;\n placeholder?: string;\n /** number 类型下的最小值 */\n min?: number;\n /** number 类型下的最大值 */\n max?: number;\n /** number 类型下的步进值 */\n step?: number;\n /** file 类型下的可接受文件类型,如 '.mp3,.wav' 或 'audio/*' */\n accept?: string | string[];\n /** directory 类型下的最大条目数 */\n maxItems?: number;\n /** type: 'group' 时的嵌套子属性 */\n properties?: Record<string, FeatureManifestSettingProperty>;\n /** 条件可见性:仅当同级指定属性值在 values 中时渲染此字段 */\n showWhen?: { property: string; values: (string | number | boolean)[] };\n}\n\nexport interface FeatureManifestDefinition {\n schemaVersion: 1;\n settings?: {\n properties: Record<string, FeatureManifestSettingProperty>;\n /** 有序分区,用于 UI 分组渲染。省略则平铺全部属性 */\n sections?: Array<{\n id: string;\n title: string;\n description?: string;\n /** 分区内属性 key 的显示顺序 */\n properties: string[];\n }>;\n };\n}\n\n/**\n * Agent Feature 接口\n *\n * 可外挂的功能模块,提供工具和上下文注入\n */\nexport interface AgentFeature {\n /** Feature 名称 */\n readonly name: string;\n /**\n * 依赖的其他 Feature(装配时拓扑排序,工作项 A3)。\n *\n * 声明位置在类的静态属性上(实例字段无法装配时静态读取):\n * ```typescript\n * class MyFeature implements AgentFeature {\n * name = 'my-feature';\n * static inject = ['storage'];\n * }\n * ```\n * 读取与校验见 feature-graph.ts(readInjectDeclarations / resolveFeatureOrder)。\n */\n // (接口本身不声明静态成员;inject 约定见上方文档)\n /**\n * Feature 源文件路径(import.meta.url)。\n *\n * 既是调试器展示的源码位置,也是框架自动发现 Feature 自带资源的唯一锚点。\n *\n * 约定:Feature 的所有静态资源放在 source 文件的同级目录下。\n * 框架会自动扫描 `dirname(source)/skills/` 发现内置 skill 并注入系统提示词。\n * 其他资源(图片、模板等)由 Feature 代码通过 import.meta.url 自行解析。\n *\n * 标准写法(由 create-feature 脚手架自动生成):\n * ```typescript\n * readonly source = fileURLToPath(import.meta.url).replace(/\\\\/g, '/');\n * ```\n */\n readonly source?: string;\n /** 可选:用于调试器展示的 Feature 描述 */\n readonly description?: string;\n\n /**\n * 获取同步工具(已知工具列表)\n */\n getTools?(): Tool[];\n\n /**\n * 获取异步工具(需要连接、发现等)\n */\n getAsyncTools?(ctx: FeatureInitContext): Promise<Tool[]>;\n\n /**\n * 获取包信息\n * \n * 返回 Feature 所在的包信息(包名、版本、根目录)\n * 用于统一模板路径解析和包管理\n * \n * @returns 包信息,如果 Feature 不属于任何包则返回 null\n * \n * @example\n * ```typescript\n * getPackageInfo(): PackageInfo | null {\n * return {\n * name: '@agentdevjs/shell-feature',\n * version: '1.0.0',\n * root: '/path/to/package/root'\n * };\n * }\n * ```\n */\n getPackageInfo?(): PackageInfo | null;\n\n /**\n * 获取模板名称列表\n * \n * 返回 Feature 提供的模板名称列表(不含扩展名)\n * 模板文件必须位于 {packageRoot}/dist/templates/{templateName}.render.js\n * \n * @returns 模板名称数组\n * \n * @example\n * ```typescript\n * getTemplateNames(): string[] {\n * return ['bash', 'trash-delete', 'trash-list'];\n * }\n * ```\n */\n getTemplateNames?(): string[];\n\n /**\n * 声明渲染模板(推荐方式)\n * 直接返回模板对象,无需文件路径\n *\n * @example\n * ```typescript\n * getRenderTemplates(): Record<string, InlineRenderTemplate> {\n * return {\n * 'bash': {\n * call: (args) => `<div class=\"bash-command\">> ${escapeHtml(args.command)}</div>`,\n * result: (data, success) => success\n * ? `<pre class=\"bash-output\">${escapeHtml(data)}</pre>`\n * : `<div class=\"tool-error\">${escapeHtml(data)}</div>`\n * }\n * };\n * }\n * ```\n */\n getRenderTemplates?(): Record<string, InlineRenderTemplate>;\n\n /**\n * 声明 Feature 的项目级静态配置契约(Manifest)\n *\n * 该契约回答“这个 Feature 平时怎么工作”,\n * 与 Flow 节点中的 Mode(什么时候、以什么状态工作)是正交的。\n */\n getFeatureManifest?(): FeatureManifestDefinition | null;\n\n /**\n * 声明可调用命令(Capability)\n *\n * 命令以 `featureName.commandName` 在注册表内平面寻址,两类消费入口:\n * - 用户命令菜单:宿主下发清单时按 entryPoints 含 'slash' 过滤\n * - 其他 Feature:进程内 invokeCapability,entryPoint 为 'feature';\n * 宿主前端转发的用户触发同样经注册表,entryPoint 为 'slash'。\n * entryPoints 是契约约束(不匹配返回 entry_point_denied),不是安全边界。\n */\n getCapabilities?(): import('./capability.js').CapabilityDefinition[];\n\n /**\n * 消费\"随消息到达的能力激活通知\"(可选)。\n *\n * 激活通知(capability refs 数组)作为用户输入的结构化元数据随消息\n * 本体流动:新 call 开始时(onCall 第三参)与 busy 排队消息的步边界\n * 注入时(react-loop drain)两个消息落地点,Agent 会按 ref 归属分组\n * 调用对应 feature 的本方法。refs 是完整引用(`featureName.commandName`),\n * feature 只需处理自己前缀的条目。\n *\n * 这是 prompt 型命令(skill 等)的唯一消费口——不解析输入文本,\n * 不维护跨消息的 pending 状态。\n */\n onCapabilityActivations?(refs: string[], ctx: { context: import('./context.js').Context }): Promise<void>;\n\n /**\n * 声明上下文注入器\n */\n getContextInjectors?(): Map<string | RegExp, ContextInjector>;\n\n /**\n * 初始化钩子\n */\n onInitiate?(ctx: FeatureInitContext): Promise<void>;\n\n /**\n * 清理钩子\n */\n onDestroy?(ctx: FeatureContext): Promise<void>;\n\n /**\n * LLM 变更时调用(可选)\n *\n * Feature 可在此重新绑定对 LLM 的引用、更新阈值等。\n * 该钩子在 Agent.setLLM() 中被同步调用,且仅在 onCall 间隙执行。\n */\n onLLMSwap?(newLLM: LLMClient, oldLLM: LLMClient): void;\n\n /**\n * 捕获可回滚的 Feature 状态\n *\n * 仅返回显式声明、可序列化的状态。\n * 未返回的字段不会参与 rollback。\n */\n captureState?(): FeatureStateSnapshot;\n\n /**\n * 从快照恢复 Feature 状态\n */\n restoreState?(snapshot: FeatureStateSnapshot): void | Promise<void>;\n\n /**\n * rollback 前钩子\n */\n beforeRollback?(snapshot: FeatureStateSnapshot): void | Promise<void>;\n\n /**\n * rollback 后钩子\n */\n afterRollback?(snapshot: FeatureStateSnapshot): void | Promise<void>;\n\n /**\n * 可选:为调试器提供 hook 的人类可读说明\n */\n getHookDescription?(lifecycle: string, methodName: string): string | undefined;\n\n // ========== 反向钩子通过 static hooks 静态声明注册,无需接口声明 ==========\n // 见 hook-declarations.ts:static hooks = { methodName: { lifecycle, kind, role? } }\n // 例如:ToolFinished, LLMFinish, StepFinish 等生命周期\n}\n\n// ========== 辅助函数 ==========\n\n/**\n * 从 Feature 的 source 属性获取包信息\n * \n * 通过向上查找 package.json 文件来确定包信息\n * 支持三种场景:\n * 1. 框架内置 Feature:找到 AgentDev 的 package.json\n * 2. 外部 npm 包:找到包的 package.json\n * 3. 用户本地 Feature:找到用户项目的 package.json\n * \n * @param source Feature 的源文件路径(import.meta.url)\n * @returns 包信息,如果找不到 package.json 则返回 null\n */\nexport function getPackageInfoFromSource(source: string | undefined): PackageInfo | null {\n if (!source) {\n return null;\n }\n\n try {\n // 将 file:// URL 转换为文件系统路径\n const filePath = source.startsWith('file://') ? fileURLToPath(source) : source;\n const featureDir = dirname(filePath);\n \n // 向上查找 package.json\n let currentDir = featureDir;\n const root = process.platform === 'win32' ? currentDir.split(/[/\\\\]/)[0] : '';\n \n while (currentDir && currentDir !== root) {\n try {\n const packageJsonPath = join(currentDir, 'package.json');\n \n // 检查文件是否存在\n if (!existsSync(packageJsonPath)) {\n throw new Error('Not found');\n }\n \n // 读取并解析 package.json\n const content = readFileSync(packageJsonPath, 'utf-8');\n const packageJson = JSON.parse(content);\n \n // 找到了 package.json\n return {\n name: packageJson.name || 'unknown',\n version: packageJson.version,\n root: currentDir,\n };\n } catch {\n // 没找到,继续向上查找\n const parentDir = dirname(currentDir);\n if (parentDir === currentDir) {\n // 已经到达根目录,停止查找\n break;\n }\n currentDir = parentDir;\n }\n }\n \n return null;\n } catch {\n // 任何错误都返回 null\n return null;\n }\n}\n","/**\n * Skill Feature 工具定义\n *\n * 提供 invoke_skill 工具,用于动态加载和展示技能的详细文档\n */\n\nimport { readFile } from 'fs/promises';\nimport { dirname, normalize } from 'path';\nimport type { Tool } from '../../core/types.js';\nimport type { SkillMetadata } from '../../skills/types.js';\nimport { splitFrontmatter } from '../../skills/loader.js';\nimport { createTool } from '../../core/tool.js';\n\n/**\n * invoke_skill 工具\n *\n * 调用并展开指定技能的详细文档\n */\nexport const invokeSkillTool: Tool = createTool({\n name: 'invoke_skill',\n description: '调用并展开指定技能的详细文档。技能提供专门的能力和领域知识。',\n parallelizable: true,\n parameters: {\n type: 'object',\n properties: {\n skill: {\n type: 'string',\n description: '技能名称(如 xlsx, pdf 等)'\n }\n },\n required: ['skill']\n },\n render: { call: 'skill', result: 'skill' },\n execute: async (args, context) => {\n const { skill } = args as { skill: string };\n console.log(`[invoke_skill] ${skill}`);\n\n // 从 context 中获取 skills 列表\n const ctx = context?._context as { skills?: SkillMetadata[] } | undefined;\n const skills = ctx?.skills || [];\n\n // 查找匹配的 skill\n const skillMetadata = skills.find(s => s.name === skill);\n\n if (!skillMetadata) {\n const availableSkills = skills.map(s => s.name).join(', ');\n return `错误:技能 \"${skill}\" 不存在。\n\n可用技能列表:${availableSkills || '(无可用技能)'}\n\n提示:请确保技能名称正确。`;\n }\n\n try {\n // frontmatter 原样保留但包进 yaml 围栏代码块,避免 markdown 渲染异常\n const raw = await readFile(skillMetadata.path, 'utf-8');\n const { frontmatter, body } = splitFrontmatter(raw);\n const content = [\n frontmatter ? ['```yaml', frontmatter, '```', ''].join('\\n') : '',\n body,\n ].filter(Boolean).join('\\n');\n\n // 获取技能目录路径,并规范化路径格式\n const basePath = normalize(dirname(skillMetadata.path));\n\n // 返回格式化的技能文档\n // 使用行内代码块包裹路径,避免 markdown 转义\n return `**技能名称**:${skillMetadata.name}\n\n**技能描述**:${skillMetadata.description}\n\n**技能的基础目录路径**:\\`${basePath}\\`\n\n---\n\n${content}`;\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n return `错误:无法读取技能文件 \"${skill}\"\n\n详细信息:${errorMsg}\n\n文件路径:${skillMetadata.path}`;\n }\n },\n});\n","/**\n * SubAgent Feature - 子代理功能模块\n *\n * 提供子代理创建、管理、消息回传等完整能力\n *\n * 重构说明:\n * - 使用 static hooks 静态声明实现反向钩子\n * - 移除旧的方法(handleNoToolCalls, handleWait, consumeMessages)\n * - 通过 ToolFinished 和 StepFinish 钩子(静态声明)实现子代理等待机制\n */\n\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport type { ToolFinishedHook, StepFinishHook } from '../../core/hook-declarations.js';\nimport type { HookDeclarations } from '../../core/hook-declarations.js';\nimport type { Agent } from '../../core/agent.js';\nimport type { Context } from '../../core/context.js';\nimport type {\n AgentFeature,\n FeatureInitContext,\n FeatureContext,\n ContextInjector,\n FeatureStateSnapshot,\n PackageInfo,\n} from '../../core/feature.js';\nimport { getPackageInfoFromSource } from '../../core/feature.js';\nimport type { Tool } from '../../core/types.js';\nimport type { ToolCall } from '../../core/types.js';\nimport type { SubAgentStatus } from '../../core/lifecycle.js';\nimport type { ToolFinishedDecisionContext, StepFinishDecisionContext } from '../../core/lifecycle.js';\nimport { CoreLifecycle, Decision, type DecisionResult } from '../../core/lifecycle.js';\nimport { AgentPool } from './pool.js';\nimport { SubAgentToolFactory } from './tools.js';\n\n// ESM 中获取 __dirname\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// ========== SubAgent Feature ==========\n\n/**\n * 子代理 Feature\n *\n * 提供子代理创建、管理、消息回传等完整能力\n *\n * 重构说明:\n * - 使用 static hooks 静态声明实现反向钩子\n * - ToolFinished: 处理 wait 工具完成后的等待逻辑\n * - StepFinish: 处理无工具调用时的子代理等待逻辑\n */\nexport class SubAgentFeature implements AgentFeature {\n\n static hooks: HookDeclarations = {\n handleWaitTool: { lifecycle: CoreLifecycle.ToolFinished, kind: 'observe' as const },\n handleNoToolCalls: { lifecycle: CoreLifecycle.StepFinish, kind: 'guard' as const, role: 'advisor' as const },\n };\n readonly name = 'subagent';\n readonly source = __filename.replace(/\\\\/g, '/');\n readonly description = '提供子代理创建、等待与消息回传能力,让主循环可以协同多个代理工作。';\n\n private agentPool?: AgentPool;\n private parentAgent?: Agent;\n\n // 工具工厂实例\n private toolFactory?: SubAgentToolFactory;\n\n /**\n * 缓存包信息\n */\n private _packageInfo: PackageInfo | null = null;\n\n /**\n * 获取包信息(统一打包方案)\n */\n getPackageInfo(): PackageInfo | null {\n if (!this._packageInfo) {\n this._packageInfo = getPackageInfoFromSource(this.source);\n }\n return this._packageInfo;\n }\n\n /**\n * 获取模板名称列表(统一打包方案)\n */\n getTemplateNames(): string[] {\n return [\n 'agent-spawn',\n 'agent-list',\n 'agent-send',\n 'agent-close',\n 'wait',\n ];\n }\n\n constructor() {\n // 无参数配置(可扩展)\n }\n\n /**\n * 获取 AgentPool(供外部访问)\n */\n get pool(): AgentPool | undefined {\n return this.agentPool;\n }\n\n // ========== AgentFeature 接口实现 ==========\n\n /**\n * 初始化钩子\n */\n async onInitiate(_ctx: FeatureInitContext): Promise<void> {\n // 工具工厂在 _setParentAgent 中初始化\n }\n\n /**\n * 设置父代理引用(由 Agent 在 use() 时调用)\n */\n _setParentAgent(agent: Agent): void {\n this.parentAgent = agent;\n this.agentPool = new AgentPool(agent);\n\n // 初始化工具工厂\n this.toolFactory = new SubAgentToolFactory({\n getPool: () => {\n if (!this.agentPool) throw new Error('AgentPool not initialized');\n return this.agentPool;\n },\n getParentAgent: () => this.parentAgent,\n });\n }\n\n /**\n * 获取同步工具\n */\n getTools(): Tool[] {\n return this.toolFactory?.getAllTools() || [];\n }\n\n getContextInjectors(): Map<string | RegExp, ContextInjector> {\n return new Map([\n ['spawn_agent', () => ({ parentAgent: this.parentAgent })],\n ['list_agents', () => ({ parentAgent: this.parentAgent })],\n ['send_to_agent', () => ({ parentAgent: this.parentAgent })],\n ['close_agent', () => ({ parentAgent: this.parentAgent })],\n ['wait', () => ({ parentAgent: this.parentAgent })],\n ]);\n }\n\n getHookDescription(lifecycle: string, methodName: string): string | undefined {\n if (lifecycle === 'ToolFinished' && methodName === 'handleWaitTool') {\n return '在 wait 工具结束后阻塞等待子代理消息,并把结果回填到主代理上下文。';\n }\n if (lifecycle === 'StepFinish' && methodName === 'handleNoToolCalls') {\n return '当本轮没有工具调用但仍有活跃子代理时,等待回信并强制继续下一轮 ReAct。';\n }\n return undefined;\n }\n\n // ========== 反向钩子(static hooks 声明)==========\n\n /**\n * 处理 wait 工具\n *\n * 触发时机:wait 工具执行完成后\n * 处理逻辑:\n * 1. 检测刚才执行的工具是否是 wait\n * 2. 如果不是,直接返回(不处理)\n * 3. 如果是,检查是否有 busy 状态的子代理\n * 4. 如果有,调用 agentPool.waitForMessage() 阻塞等待(await 阻塞主循环)\n * 5. 消息插入到主代理 context\n *\n * 注意:这是纯通知钩子(void),流程控制通过 await 阻塞实现\n */\n async handleWaitTool(ctx: ToolFinishedDecisionContext): Promise<void> {\n // 1. 只处理 wait 工具\n if (ctx.toolName !== 'wait') {\n return;\n }\n\n // 2. 检查是否有 busy 子代理\n if (!this.agentPool?.hasActiveAgents()) {\n return;\n }\n\n // 3. 阻塞等待(await 本身就会让主循环等待)\n const result = await this.agentPool.waitForMessage();\n\n // 4. 消息插入到 context\n ctx.context.add({\n role: 'assistant',\n content: `[子代理 ${result.agentId} 执行完成]:\\n\\n${result.message}`,\n });\n }\n\n /**\n * 处理无工具调用时的子代理等待\n *\n * 触发时机:Step 结束时\n * 处理逻辑:\n * 1. 检查是否有 busy 状态的子代理\n * 2. 如果没有,返回 Continue(正常结束)\n * 3. 如果有,调用 agentPool.waitForMessage() 阻塞等待\n * 4. 消息插入到主代理 context\n * 5. 返回 Approve(重启 ReAct 循环)\n */\n async handleNoToolCalls(ctx: StepFinishDecisionContext): Promise<DecisionResult> {\n // 只在无工具调用时处理\n if (ctx.llmResponse.toolCalls && ctx.llmResponse.toolCalls.length > 0) {\n return Decision.Continue;\n }\n\n // 1. 检查是否有活跃子代理\n if (!this.agentPool?.hasActiveAgents()) {\n return Decision.Continue;\n }\n\n // 2. 阻塞等待\n const result = await this.agentPool.waitForMessage();\n\n // 3. 消息插入到 context\n ctx.context.add({\n role: 'assistant',\n content: `[子代理 ${result.agentId} 执行完成]:\\n\\n${result.message}`,\n });\n\n // 4. 重启 ReAct 循环\n return Decision.Approve;\n }\n\n async onDestroy(): Promise<void> {\n return this.agentPool?.shutdown() ?? Promise.resolve();\n }\n\n captureState(): FeatureStateSnapshot {\n const runtime = this.agentPool?.getRuntimeSnapshot();\n return {\n counters: runtime?.counters ?? [],\n hadInstances: (runtime?.instances.length ?? 0) > 0,\n hadActiveAgents: runtime?.instances.some(instance => instance.status === 'busy') ?? false,\n hadPendingMessages: runtime?.pendingMessages.some(([, messages]) => messages.length > 0) ?? false,\n };\n }\n\n async restoreState(snapshot: FeatureStateSnapshot): Promise<void> {\n if (!this.agentPool) {\n return;\n }\n\n const state = snapshot as {\n counters?: Array<[string, number]>;\n hadInstances?: boolean;\n hadActiveAgents?: boolean;\n hadPendingMessages?: boolean;\n };\n\n await this.agentPool.restoreRuntimeSnapshot({\n counters: state.counters,\n });\n\n if (state.hadInstances || state.hadActiveAgents || state.hadPendingMessages) {\n console.warn(\n '[SubAgentFeature] Restored session/rollback snapshot dropped live subagent runtime. ' +\n 'Subagents are not resumable and have been reset to an empty pool.'\n );\n }\n }\n}\n\n// 重新导出 AgentPool\nexport { AgentPool };\n","/**\n * AgentPool - 子代理管理核心\n * 管理父代理创建的所有子代理实例\n */\n\nimport type { Agent } from '../../core/agent.js';\nimport type { SubAgentStatus } from '../../core/lifecycle.js';\n\n/**\n * 子代理实例信息\n */\nexport interface SubAgentInstance {\n id: string;\n type: string;\n agent: Agent;\n status: SubAgentStatus;\n initialInstruction: string;\n createdAt: number;\n completedAt?: number;\n result?: string;\n error?: string;\n}\n\n/**\n * Agent 创建函数类型(异步)\n */\nexport type AgentFactory = (type: string) => Agent | Promise<Agent>;\n\n/**\n * AgentPool - 子代理管理核心\n * 管理父代理创建的所有子代理实例\n */\nexport class AgentPool {\n private _instances = new Map<string, SubAgentInstance>();\n private _counters = new Map<string, number>();\n private _parent: Agent;\n\n // 子代理消息回传机制\n /** 待回传消息队列:agentId -> messages[] */\n private _pendingMessages: Map<string, string[]> = new Map();\n /** 消息就绪解析器:key -> resolver function */\n private _messageResolvers: Map<string, (message: string | null) => void> = new Map();\n\n constructor(parent: Agent) {\n this._parent = parent;\n }\n\n /**\n * 创建子代理(不自动执行,等待 sendTo 激活)\n */\n async spawn(type: string, createAgentFn: AgentFactory): Promise<string> {\n // 生成 ID: type_序号\n const count = (this._counters.get(type) || 0) + 1;\n this._counters.set(type, count);\n const id = `${type}_${count}`;\n\n // 创建 Agent 实例(异步)\n const agent = await createAgentFn(type);\n\n // 注入 agentId 和 pool 引用到子代理\n // 用于子代理回传消息\n (agent as any)._agentId = id;\n (agent as any)._parentPool = this;\n\n // 如果父代理启用了 debug,子代理也启用并注册到同一个 DebugHub\n if ((this._parent as any).debugEnabled && (this._parent as any).debugHub) {\n const parentDebugHub = (this._parent as any).debugHub;\n // 子代理注册到 debug 服务器\n await agent.withViewer(`${type}_${count}`);\n // 使用父代理的同一个 debugHub 实例\n (agent as any).debugHub = parentDebugHub;\n }\n\n // 存储实例信息\n const instance: SubAgentInstance = {\n id,\n type,\n agent,\n status: 'idle',\n initialInstruction: '',\n createdAt: Date.now(),\n };\n this._instances.set(id, instance);\n\n // 触发 onSubAgentSpawn 钩子\n await this._parent.onSubAgentSpawn?.({\n agentId: id,\n type,\n agent,\n instruction: '',\n });\n\n // 子代理创建后处于空闲状态,等待 sendTo 激活\n return id;\n }\n\n /**\n * 获取实例信息\n */\n get(id: string): SubAgentInstance | undefined {\n return this._instances.get(id);\n }\n\n /**\n * 列出所有实例\n */\n list(filter?: SubAgentStatus): SubAgentInstance[] {\n const all = Array.from(this._instances.values());\n if (!filter) return all;\n return all.filter(i => i.status === filter);\n }\n\n /**\n * 向子代理发送消息(非阻塞)\n */\n async sendTo(id: string, message: string): Promise<void> {\n const timestamp = new Date().toISOString();\n console.log(`[DEBUG:sendTo] ${timestamp} agentId=${id}, msg=\"${message.slice(0, 50)}...\"`);\n\n const instance = this._instances.get(id);\n if (!instance) throw new Error(`子代理不存在: ${id}`);\n\n // 更新状态为 busy\n const oldStatus = instance.status;\n instance.status = 'busy';\n console.log(`[DEBUG:sendTo] 状态: ${oldStatus} -> busy`);\n\n // 异步执行,立即返回\n instance.agent.onCall(message)\n .then(result => {\n const thenTime = new Date().toISOString();\n console.log(`[DEBUG:sendTo.then] ${thenTime} agentId=${id}, 完成,result=\"${result.slice(0, 50)}...\"`);\n // 正常完成\n instance.status = 'idle';\n instance.result = result;\n // 报告消息(入队)\n this.report(id, result);\n })\n .catch(error => {\n const catchTime = new Date().toISOString();\n console.log(`[DEBUG:sendTo.catch] ${catchTime} agentId=${id}, error=${error.message}`);\n // 执行失败\n instance.status = 'failed';\n this._onError(id, error);\n });\n }\n\n /**\n * 关闭子代理\n */\n async close(id: string, reason: string = 'manual'): Promise<void> {\n const instance = this._instances.get(id);\n if (!instance) return;\n\n await instance.agent.dispose();\n instance.status = 'terminated';\n this._instances.delete(id);\n\n await this._parent.onSubAgentDestroy?.({\n agentId: id,\n type: instance.type,\n reason: reason as any,\n });\n }\n\n /**\n * 子代理回传消息到父代理\n * @param agentId 子代理 ID\n * @param message 消息内容\n */\n async report(agentId: string, message: string): Promise<void> {\n const timestamp = new Date().toISOString();\n const msgPreview = message.slice(0, 50);\n\n console.log(`[DEBUG:report] ${timestamp} agentId=${agentId}, msg=\"${msgPreview}...\"`);\n console.trace('[DEBUG:report] 调用栈:');\n\n // 添加到待回传队列\n if (!this._pendingMessages.has(agentId)) {\n this._pendingMessages.set(agentId, []);\n }\n this._pendingMessages.get(agentId)!.push(message);\n\n console.log(`[DEBUG:report] 入队后队列长度: ${this._pendingMessages.get(agentId)!.length}`);\n\n // 通知等待的解析器\n // 优先查找专门等待此 agent 的解析器\n const resolver = this._messageResolvers.get(agentId);\n if (resolver) {\n console.log(`[DEBUG:report] 触发专门 resolver: ${agentId}`);\n resolver(message);\n this._messageResolvers.delete(agentId);\n return;\n }\n\n // 如果没有专门解析器,查找通用等待解析器(以 wait_ 开头的)\n for (const [key, resolver] of this._messageResolvers) {\n if (key.startsWith('wait_')) {\n console.log(`[DEBUG:report] 触发通用 resolver: ${key}`);\n resolver(message);\n this._messageResolvers.delete(key);\n break;\n }\n }\n }\n\n /**\n * 等待任意子代理的消息\n * @returns { agentId, message }\n */\n async waitForMessage(): Promise<{ agentId: string; message: string }> {\n const timestamp = new Date().toISOString();\n console.log(`[DEBUG:waitForMessage] ${timestamp} 开始等待`);\n\n // 检查是否有待处理消息\n for (const [agentId, messages] of this._pendingMessages) {\n if (messages.length > 0) {\n const message = messages.shift()!;\n console.log(`[DEBUG:waitForMessage] ${timestamp} 从队列取出消息 agentId=${agentId}, 队列剩余: ${messages.length}`);\n if (messages.length === 0) {\n this._pendingMessages.delete(agentId);\n }\n return { agentId, message };\n }\n }\n\n console.log(`[DEBUG:waitForMessage] ${timestamp} 队列为空,注册 resolver`);\n\n // 等待新消息(无超时,一直等待直到有消息)\n return new Promise((resolve) => {\n // 临时存储解析器(任意子代理都可以触发)\n const tempKey = `wait_${Date.now()}`;\n console.log(`[DEBUG:waitForMessage] ${timestamp} 注册 resolver: ${tempKey}`);\n this._messageResolvers.set(tempKey, () => {\n const resolveTime = new Date().toISOString();\n console.log(`[DEBUG:waitForMessage.resolver] ${resolveTime} resolver 被触发`);\n // 查找发送消息的 agentId\n for (const [agentId, messages] of this._pendingMessages) {\n if (messages.length > 0) {\n const message = messages.shift()!;\n console.log(`[DEBUG:waitForMessage.resolver] ${resolveTime} 从队列取出消息 agentId=${agentId}, 队列剩余: ${messages.length}`);\n if (messages.length === 0) {\n this._pendingMessages.delete(agentId);\n }\n resolve({ agentId, message });\n return;\n }\n }\n console.log(`[DEBUG:waitForMessage.resolver] ${resolveTime} 队列为空!`);\n });\n });\n }\n\n /**\n * 检查是否有活跃的子代理或待处理的消息\n *\n * 注意:先检查消息队列,避免竞态条件\n */\n hasActiveAgents(): boolean {\n const timestamp = new Date().toISOString();\n // 优先检查消息队列\n for (const [agentId, messages] of this._pendingMessages.entries()) {\n if (messages.length > 0) {\n console.log(`[DEBUG:hasActiveAgents] ${timestamp} 发现消息队列: ${agentId}, ${messages.length} 条`);\n return true;\n }\n }\n // 再检查 busy 状态的子代理\n for (const instance of this._instances.values()) {\n if (instance.status === 'busy') {\n console.log(`[DEBUG:hasActiveAgents] ${timestamp} 发现 busy 子代理: ${instance.id}`);\n return true;\n }\n }\n console.log(`[DEBUG:hasActiveAgents] ${timestamp} 无活跃子代理`);\n return false;\n }\n\n /**\n * 检查是否有待处理的子代理消息\n */\n hasPendingMessages(): boolean {\n const timestamp = new Date().toISOString();\n for (const [agentId, messages] of this._pendingMessages.entries()) {\n if (messages.length > 0) {\n console.log(`[DEBUG:hasPendingMessages] ${timestamp} agentId=${agentId}, ${messages.length} 条消息`);\n return true;\n }\n }\n console.log(`[DEBUG:hasPendingMessages] ${timestamp} 无待处理消息`);\n return false;\n }\n\n /**\n * 处理子代理中断\n * @param agentId 子代理 ID\n * @param reason 中断原因\n * @param result 中断时的结果\n */\n async handleInterrupt(\n agentId: string,\n reason: 'limit_reached' | 'error' | 'cancelled',\n result: string\n ): Promise<void> {\n const timestamp = new Date().toISOString();\n console.log(`[DEBUG:handleInterrupt] ${timestamp} agentId=${agentId}, reason=${reason}, result=\"${result.slice(0, 50)}...\"`);\n\n const instance = this._instances.get(agentId);\n if (!instance) return;\n\n const oldStatus = instance.status;\n instance.status = 'idle';\n instance.result = result;\n console.log(`[DEBUG:handleInterrupt] ${timestamp} 状态: ${oldStatus} -> idle`);\n\n // 报告消息(入队)\n await this.report(agentId, result);\n\n // 触发钩子\n await this._parent.onSubAgentInterrupt?.({\n agentId,\n type: instance.type,\n reason,\n result,\n });\n }\n\n /**\n * 关闭所有子代理\n */\n async shutdown(): Promise<void> {\n const promises = Array.from(this._instances.keys())\n .map(id => this.close(id, 'parent_dispose'));\n await Promise.all(promises);\n }\n\n getRuntimeSnapshot(): {\n counters: Array<[string, number]>;\n instances: Array<{ id: string; type: string; status: SubAgentStatus }>;\n pendingMessages: Array<[string, string[]]>;\n } {\n return {\n counters: Array.from(this._counters.entries()),\n instances: Array.from(this._instances.values()).map(instance => ({\n id: instance.id,\n type: instance.type,\n status: instance.status,\n })),\n pendingMessages: Array.from(this._pendingMessages.entries()).map(([agentId, messages]) => [\n agentId,\n [...messages],\n ]),\n };\n }\n\n async restoreRuntimeSnapshot(snapshot: {\n counters?: Array<[string, number]>;\n }): Promise<void> {\n await this.shutdown();\n this._pendingMessages.clear();\n this._messageResolvers.clear();\n this._counters = new Map(snapshot.counters ?? []);\n }\n\n // 内部方法\n private async _onComplete(id: string, result: string): Promise<void> {\n const timestamp = new Date().toISOString();\n console.log(`[DEBUG:_onComplete] ${timestamp} agentId=${id}, result=\"${result.slice(0, 50)}...\"`);\n\n const instance = this._instances.get(id);\n if (!instance) return;\n\n const oldStatus = instance.status;\n\n // 先回传消息给主代理(确保消息先入队,避免竞态条件)\n await this.report(id, result);\n\n // 再更新状态(子代理持久存在,完成任务后回到 idle)\n instance.status = 'idle';\n instance.result = result;\n instance.completedAt = Date.now();\n\n console.log(`[DEBUG:_onComplete] ${timestamp} 状态: ${oldStatus} -> idle`);\n\n await this._parent.onSubAgentUpdate?.({\n agentId: id,\n type: instance.type,\n oldStatus,\n newStatus: 'idle',\n result,\n });\n }\n\n private async _onError(id: string, error: Error): Promise<void> {\n const instance = this._instances.get(id);\n if (!instance) return;\n\n const oldStatus = instance.status;\n\n // 先更新状态(错误情况不需要回传消息,因为父代理无法处理错误子代理的结果)\n instance.status = 'failed';\n instance.error = error.message;\n instance.completedAt = Date.now();\n\n await this._parent.onSubAgentUpdate?.({\n agentId: id,\n type: instance.type,\n oldStatus,\n newStatus: 'failed',\n error: error.message,\n });\n }\n}\n","/**\n * SubAgent Feature 工具定义\n *\n * 提供 5 个子代理管理工具:spawn_agent, list_agents, send_to_agent, close_agent, wait\n */\n\nimport type { Tool } from '../../core/types.js';\nimport type { Agent } from '../../core/agent.js';\nimport type { AgentPool } from './pool.js';\nimport { createTool } from '../../core/tool.js';\n\n/**\n * SubAgent 工具工厂类\n * 用于创建子代理工具,需要传入 Feature 实例来访问 AgentPool\n */\nexport class SubAgentToolFactory {\n private getPoolFn: () => AgentPool;\n private getParentAgentFn: () => Agent | undefined;\n\n constructor(options: {\n getPool: () => AgentPool;\n getParentAgent: () => Agent | undefined;\n }) {\n this.getPoolFn = options.getPool;\n this.getParentAgentFn = options.getParentAgent;\n }\n\n /**\n * 创建 spawn_agent 工具\n */\n createSpawnAgentTool(): Tool {\n const self = this;\n return createTool({\n name: 'spawn_agent',\n description: '创建一个子代理实例。子代理创建后处于idle状态,等待通过 send_to_agent 发送指令来激活。返回实例 ID(格式:类型名_序号)。\\n\\n子代理完成工作后,其结果会自动添加到你的上下文中,你将收到 \"[子代理 ID_执行完成]:\" 格式的消息。',\n parameters: {\n type: 'object',\n properties: {\n type: {\n type: 'string',\n description: '子代理类型名'\n }\n },\n required: ['type']\n },\n render: { call: 'agent-spawn', result: 'agent-spawn' },\n execute: async (args, context) => {\n const { type } = args as { type: string };\n const parentAgent = (context?.parentAgent as Agent | undefined) ?? self.getParentAgentFn();\n const pool = self.getPoolFn();\n\n if (!parentAgent) {\n return { error: '无法获取父代理引用' };\n }\n\n // 动态校验类型是否在注册表中\n const availableTypes = parentAgent.getRegisteredAgentTypes();\n if (availableTypes.length > 0 && !availableTypes.includes(type)) {\n return {\n error: `未知的子代理类型: \"${type}\"。可用类型: ${availableTypes.join(', ')}`,\n availableTypes,\n };\n }\n\n const agentId = await pool.spawn(type, async (t) => await parentAgent.createAgentByType(t));\n\n return {\n agentId,\n type,\n status: 'idle',\n availableTypes: parentAgent.getRegisteredAgentTypes(),\n allAgents: pool.list().map(i => ({\n agentId: i.id,\n type: i.type,\n status: i.status,\n })),\n };\n },\n });\n }\n\n /**\n * 创建 list_agents 工具\n */\n createListAgentsTool(): Tool {\n const self = this;\n return createTool({\n name: 'list_agents',\n description: '列出所有子代理及其状态(ID、类型、状态等)。\\n\\n注意:子代理的执行结果会自动添加到你的上下文中,你不需要调用此工具来获取结果。此工具主要用于确认子代理正确启动,不要在运行期间不断监控运行情况',\n parameters: {\n type: 'object',\n properties: {\n filter: {\n type: 'string',\n enum: ['all', 'running', 'completed', 'failed', 'terminated'],\n description: '筛选条件,默认显示所有子代理',\n default: 'all'\n }\n }\n },\n render: { call: 'agent-list', result: 'json' },\n execute: async (args) => {\n const { filter = 'all' } = args as { filter?: string };\n const pool = self.getPoolFn();\n const instances = pool.list(filter === 'all' ? undefined : filter as any);\n\n return {\n agents: instances.map(i => ({\n agentId: i.id,\n type: i.type,\n status: i.status,\n createdAt: i.createdAt,\n result: i.result,\n error: i.error,\n })),\n total: instances.length,\n running: instances.filter(i => i.status === 'busy' || i.status === 'idle').length,\n tips: '当确认子代理工作正常时,你无需重复调用此工具以获取最新状态,可停止输出,等待子代理完成任务后自动添加到上下文中。',\n };\n },\n });\n }\n\n /**\n * 创建 send_to_agent 工具\n */\n createSendToAgentTool(): Tool {\n const self = this;\n return createTool({\n name: 'send_to_agent',\n description: '向指定的子代理发送指令。只能向处于idle状态的子代理发送消息,如果子代理正在执行(busy状态),发送会失败。子代理运行期间可以执行其他工作,若无需求,应停止输出或使用wait工具,待子代理完成任务时会主动唤起',\n parameters: {\n type: 'object',\n properties: {\n agentId: {\n type: 'string',\n description: '子代理实例 ID,如 \"BasicAgent_1\" 或 \"ExplorerAgent_2\"'\n },\n message: {\n type: 'string',\n description: '要发送给子代理的消息或指令'\n }\n },\n required: ['agentId', 'message']\n },\n render: { call: 'agent-send', result: 'agent-send' },\n execute: async (args) => {\n const { agentId, message } = args as { agentId: string; message: string };\n const pool = self.getPoolFn();\n\n // 检查子代理是否存在以及状态\n const instance = pool.get(agentId);\n if (!instance) {\n return {\n error: `子代理不存在: ${agentId}`,\n allAgents: pool.list().map(i => ({\n agentId: i.id,\n type: i.type,\n status: i.status,\n })),\n };\n }\n\n // 检查子代理是否正在执行\n if (instance.status === 'busy') {\n return {\n error: `子代理 ${agentId} 正在执行任务(busy状态),无法接收新消息。请等待其完成后再发送`,\n agentId,\n currentStatus: instance.status,\n allAgents: pool.list().map(i => ({\n agentId: i.id,\n type: i.type,\n status: i.status,\n })),\n };\n }\n\n await pool.sendTo(agentId, message);\n\n return {\n agentId,\n status: 'message_sent',\n previousStatus: instance.status,\n message: '消息已成功发送到子代理,可以继续执行你尚未完成的其他任务,若无必要,请停止输出,等待子代理完成任务',\n allAgents: pool.list().map(i => ({\n agentId: i.id,\n type: i.type,\n status: i.status,\n })),\n };\n },\n });\n }\n\n /**\n * 创建 close_agent 工具\n */\n createCloseAgentTool(): Tool {\n const self = this;\n return createTool({\n name: 'close_agent',\n description: '关闭指定的子代理并释放其资源。子代理将被终止并从池中移除。',\n parameters: {\n type: 'object',\n properties: {\n agentId: {\n type: 'string',\n description: '要关闭的子代理实例 ID'\n },\n reason: {\n type: 'string',\n description: '关闭原因(可选)',\n default: 'manual'\n }\n },\n required: ['agentId']\n },\n render: { call: 'agent-close', result: 'json' },\n execute: async (args) => {\n const { agentId, reason = 'manual' } = args as { agentId: string; reason?: string };\n const pool = self.getPoolFn();\n await pool.close(agentId, reason);\n\n return {\n agentId,\n status: 'closed',\n message: `子代理 ${agentId} 已关闭`\n };\n },\n });\n }\n\n /**\n * 创建 wait 工具\n */\n createWaitTool(): Tool {\n const self = this;\n return createTool({\n name: 'wait',\n description: '调用本工具后,系统将被阻塞,等待子代理返回运行结果后继续运行。可以与 spawn_agent、send_to_agent 等工具在同一轮一起调用,表示执行完这些操作后等待子代理完成。',\n parameters: {\n type: 'object',\n properties: {},\n },\n render: { call: 'wait', result: 'wait' },\n execute: async (_args) => {\n const pool = self.getPoolFn();\n\n // 安全检查:是否有活跃的子代理\n if (!pool.hasActiveAgents()) {\n return {\n error: '当前没有正在执行的子代理(busy状态),调用 wait 无意义。请先使用 spawn_agent 创建子代理或使用 send_to_agent 向子代理发送任务。',\n allAgents: pool.list().map(i => ({\n agentId: i.id,\n type: i.type,\n status: i.status,\n })),\n };\n }\n\n // 只是一个标志,实际等待逻辑由反向钩子处理\n return {\n action: 'waiting_for_subagents',\n message: '系统将在子代理完成任务后继续...',\n allAgents: pool.list().map(i => ({\n agentId: i.id,\n type: i.type,\n status: i.status,\n })),\n };\n },\n });\n }\n\n /**\n * 获取所有工具\n */\n getAllTools(): Tool[] {\n return [\n this.createSpawnAgentTool(),\n this.createListAgentsTool(),\n this.createSendToAgentTool(),\n this.createCloseAgentTool(),\n this.createWaitTool(),\n ];\n }\n}\n","/**\r\n * Todo Feature - 任务列表管理功能模块\r\n *\r\n * 提供任务创建、查询、更新等能力,用于跟踪复杂任务的进度\r\n * 内置智能提醒功能,自动跟踪工具使用并在合适时机注入提醒\r\n *\r\n * 重构说明:\r\n * - 使用 static hooks 静态声明反向钩子实现提醒逻辑\r\n * - 不再需要在 Agent 中重写 onStepStart/onStepFinished\r\n * - 每个发生 Todo 写操作的 Step 结束后,自动注入一次最新完整任务列表\r\n */\r\n\r\nimport { fileURLToPath } from 'url';\r\nimport { dirname, join } from 'path';\r\nimport { readFile } from 'fs/promises';\r\nimport type {\r\n AgentFeature,\r\n FeatureInitContext,\r\n FeatureContext,\r\n FeatureStateSnapshot,\r\n PackageInfo,\r\n} from '../../core/feature.js';\r\nimport type { HookDeclarations } from '../../core/hook-declarations.js';\r\nimport { CoreLifecycle } from '../../core/lifecycle.js';\r\nimport type { Context } from '../../core/context.js';\r\nimport { getPackageInfoFromSource } from '../../core/feature.js';\r\nimport type { StepStartContext, StepFinishDecisionContext, CallStartContext } from '../../core/lifecycle.js';\r\nimport { Decision } from '../../core/lifecycle.js';\r\nimport type { DecisionResult } from '../../core/lifecycle.js';\r\nimport type { Tool } from '../../core/types.js';\r\nimport type { TodoPlanSnapshot } from '../../core/types.js';\r\nimport { DebugHub } from '../../core/debug-hub.js';\r\nimport { TodoToolFactory } from './tools.js';\r\nimport type { TodoTask, TodoTaskUpdate, TodoTaskSummary, TaskStatus, TodoFeatureConfig } from './types.js';\r\n\r\n// ESM 中获取 __dirname\r\nconst __filename = fileURLToPath(import.meta.url);\r\nconst __dirname = dirname(__filename);\r\n\r\n/** StepFinish 注入的任务列表体积上限 */\r\nconst MAX_INJECT_TASKS = 20;\r\nconst MAX_SUBJECT_LENGTH = 160;\r\nconst MAX_DESCRIPTION_LENGTH = 500;\r\n\r\n/**\r\n * TodoFeature 实现\r\n *\r\n * 提供任务管理和智能提醒功能\r\n * 使用反向钩子自动处理提醒逻辑,无需在 Agent 中重写钩子方法\r\n */\r\nexport class TodoFeature implements AgentFeature {\r\n\r\n static hooks: HookDeclarations = {\r\n checkAndInjectReminder: { lifecycle: CoreLifecycle.StepStart, kind: 'observe' as const },\r\n onCallStart: { lifecycle: CoreLifecycle.CallStart, kind: 'observe' as const },\r\n recordToolUsage: { lifecycle: CoreLifecycle.StepFinish, kind: 'guard' as const, role: 'advisor' as const },\r\n };\r\n readonly name = 'todo';\r\n readonly source = __filename.replace(/\\\\/g, '/');\r\n readonly description = '维护任务清单,并在合适的循环时机自动提醒模型更新 todo 状态。';\r\n\r\n private tasks = new Map<string, TodoTask>();\r\n private counter = 0;\r\n private debugAgentId = '';\r\n private config: Required<Omit<TodoFeatureConfig, 'reminderTemplate' | 'reminderThresholdWithTasks' | 'reminderThresholdWithoutTasks'>> & {\r\n reminderTemplate?: string;\r\n reminderThresholdWithTasks?: number;\r\n reminderThresholdWithoutTasks?: number;\r\n };\r\n\r\n // Reminder 相关状态\r\n private reminderContent = '';\r\n\r\n // 连续未使用 todo 工具的轮次计数器\r\n private consecutiveNoTodoTurns = 0;\r\n // 上一轮是否已注入 reminder(防止重复注入)\r\n private reminderInjected = false;\r\n\r\n // 工具工厂实例\r\n private toolFactory?: TodoToolFactory;\r\n\r\n private _packageInfo: PackageInfo | null = null;\r\n\r\n constructor(config: TodoFeatureConfig = {}) {\r\n this.config = {\r\n reminderThresholdWithTasks: config.reminderThresholdWithTasks ?? 3,\r\n reminderThresholdWithoutTasks: config.reminderThresholdWithoutTasks ?? 6,\r\n reminderTemplate: config.reminderTemplate,\r\n };\r\n this.reminderContent = this.getDefaultReminder();\r\n\r\n // 初始化工具工厂\r\n this.toolFactory = new TodoToolFactory({\r\n getTask: (taskId) => this.getTask(taskId),\r\n createTask: (subject, description, options) => this.createTask(subject, description, options),\r\n listTasks: (filter) => this.listTasks(filter),\r\n updateTask: (taskId, updates) => this.updateTask(taskId, updates),\r\n clearTasks: () => this.clearTasks(),\r\n });\r\n }\r\n\r\n // ========== AgentFeature 接口实现 ==========\r\n\r\n /**\r\n * 获取包信息(统一打包方案)\r\n */\r\n getPackageInfo(): PackageInfo | null {\r\n if (!this._packageInfo) {\r\n this._packageInfo = getPackageInfoFromSource(this.source);\r\n }\r\n return this._packageInfo;\r\n }\r\n\r\n /**\r\n * 获取模板名称列表(统一打包方案)\r\n */\r\n getTemplateNames(): string[] {\r\n return [\r\n 'task-create',\r\n 'task-list',\r\n 'task-update',\r\n 'task-clear',\r\n ];\r\n }\r\n\r\n getTools(): Tool[] {\r\n return this.toolFactory?.getAllTools() || [];\r\n }\r\n\r\n async onInitiate(_ctx: FeatureInitContext): Promise<void> {\r\n console.log(`[TodoFeature] Initialized with reminderThresholdWithTasks=${this.config.reminderThresholdWithTasks}, reminderThresholdWithoutTasks=${this.config.reminderThresholdWithoutTasks}`);\r\n\r\n // 如果配置了模板文件,异步加载\r\n const templatePath = this.config.reminderTemplate;\r\n if (templatePath) {\r\n try {\r\n this.reminderContent = await readFile(templatePath, 'utf-8');\r\n console.log('[TodoFeature] Loaded reminder template from: ' + templatePath);\r\n } catch (e) {\r\n console.log('[TodoFeature] Failed to load template, using default reminder');\r\n // 保持默认 reminder\r\n }\r\n }\r\n }\r\n\r\n async onDestroy(_ctx: FeatureContext): Promise<void> {\r\n this.pushDebugSnapshot();\r\n }\r\n\r\n captureState(): FeatureStateSnapshot {\r\n return {\r\n tasks: Array.from(this.tasks.values()),\r\n counter: this.counter,\r\n reminderContent: this.reminderContent,\r\n consecutiveNoTodoTurns: this.consecutiveNoTodoTurns,\r\n reminderInjected: this.reminderInjected,\r\n };\r\n }\r\n\r\n restoreState(snapshot: FeatureStateSnapshot): void {\r\n const state = snapshot as {\r\n tasks?: TodoTask[];\r\n counter?: number;\r\n reminderContent?: string;\r\n consecutiveNoTodoTurns?: number;\r\n reminderInjected?: boolean;\r\n };\r\n\r\n // 白名单重建:仅保留新 schema 字段,丢弃旧 session 中可能存在的\r\n // activeForm/owner/blocks/blockedBy 等已删除字段\r\n this.tasks = new Map((state.tasks ?? []).map(task => [\r\n task.id,\r\n {\r\n id: task.id,\r\n subject: task.subject,\r\n description: task.description,\r\n status: task.status,\r\n metadata: task.metadata,\r\n createdAt: task.createdAt,\r\n updatedAt: task.updatedAt,\r\n },\r\n ]));\r\n this.counter = typeof state.counter === 'number' ? state.counter : 0;\r\n this.reminderContent = typeof state.reminderContent === 'string'\r\n ? state.reminderContent\r\n : this.getDefaultReminder();\r\n this.consecutiveNoTodoTurns = typeof state.consecutiveNoTodoTurns === 'number'\r\n ? state.consecutiveNoTodoTurns\r\n : 0;\r\n this.reminderInjected = Boolean(state.reminderInjected);\r\n this.pushDebugSnapshot();\r\n }\r\n\r\n pushDebugSnapshot(agentId?: string): void {\r\n if (agentId) {\r\n this.debugAgentId = agentId;\r\n }\r\n // 身份自持:只用显式传入或上次记住的 agentId,不依赖全局选中状态\r\n const targetAgentId = agentId || this.debugAgentId;\r\n if (!targetAgentId || !DebugHub.getInstance().isConnected()) return;\r\n DebugHub.getInstance().updateTodoPlan(targetAgentId, this.getPlanSnapshot());\r\n }\r\n\r\n getHookDescription(lifecycle: string, methodName: string): string | undefined {\r\n if (lifecycle === 'StepStart' && methodName === 'checkAndInjectReminder') {\r\n return '在每轮开始时检查提醒阈值;连续多轮未使用 todo 工具时注入系统提醒(含当前/下一任务状态)。';\r\n }\r\n if (lifecycle === 'StepFinish' && methodName === 'recordToolUsage') {\r\n return '统计 todo 工具使用并更新计数;若本轮有写操作,向 Context 注入一次最新完整任务列表。';\r\n }\r\n return undefined;\r\n }\r\n\r\n // ========== 反向钩子(static hooks 声明)==========\r\n\r\n /**\r\n * Step 开始时检查是否需要注入 reminder\r\n *\r\n * 触发时机:每轮 ReAct 迭代开始时\r\n * 处理逻辑:\r\n * 1. 检查连续未使用 todo 工具的轮次\r\n * 2. 达到阈值时注入 reminder 系统消息(包含当前/下一任务状态)\r\n * 3. 防止重复注入\r\n */\r\n async checkAndInjectReminder(ctx: StepStartContext): Promise<void> {\r\n const threshold = this.getCurrentThreshold();\r\n console.log(`[TodoFeature] callIndex=${ctx.callIndex}, counter=${this.consecutiveNoTodoTurns}, threshold=${threshold}, injected=${this.reminderInjected}`);\r\n\r\n // 检查是否需要注入 reminder\r\n if (this.consecutiveNoTodoTurns >= threshold && !this.reminderInjected) {\r\n console.log('[TodoFeature] Threshold reached, injecting reminder');\r\n ctx.context.add({ role: 'system', content: this.buildDynamicReminder() });\r\n this.reminderInjected = true;\r\n }\r\n }\r\n\r\n /**\r\n * Call 开始时注入简短任务状态\r\n *\r\n * 触发时机:每次用户发送新消息、Agent 开始处理时\r\n * 处理逻辑:\r\n * 1. 首次调用跳过(还没有任务)\r\n * 2. 无待执行任务时跳过\r\n * 3. 有待执行任务时注入简短的\"当前/下一项\"状态\r\n * 4. 重置 no-todo 计数器(新一轮用户交互)\r\n */\r\n async onCallStart(ctx: CallStartContext): Promise<void> {\r\n // 首次调用不注入\r\n if (ctx.isFirstCall) return;\r\n\r\n // 检查是否有待执行任务\r\n const hasActiveTasks = Array.from(this.tasks.values()).some(\r\n t => t.status === 'pending' || t.status === 'in_progress'\r\n );\r\n if (!hasActiveTasks) return;\r\n\r\n // 注入简短任务状态\r\n ctx.context.add({ role: 'system', content: this.buildCallStartBrief() });\r\n\r\n // 重置计数器(新的用户消息代表新一轮交互)\r\n this.consecutiveNoTodoTurns = 0;\r\n this.reminderInjected = false;\r\n\r\n console.log('[TodoFeature] CallStart: injected brief task status, reset counter');\r\n }\r\n\r\n /**\r\n * Step 结束时记录是否使用了 todo 工具\r\n *\r\n * 触发时机:每轮 ReAct 迭代结束时(工具结果已写入 Context 后)\r\n * 处理逻辑:\r\n * 1. 检查本轮是否使用了 todo 工具\r\n * 2. 若有写操作(create/update/clear),向 Context 追加一次最新完整任务列表\r\n * 3. 使用了则重置计数器,未使用则计数器+1\r\n * 4. 返回 Continue 使用默认行为\r\n */\r\n async recordToolUsage(ctx: StepFinishDecisionContext): Promise<DecisionResult> {\r\n const toolCalls = ctx.llmResponse.toolCalls ?? [];\r\n const usedTodoTool = toolCalls.some((call: { name: string }) => this.isTodoTool(call.name));\r\n const wroteTodo = toolCalls.some((call: { name: string }) => this.isTodoWriteTool(call.name));\r\n\r\n if (usedTodoTool) {\r\n // 使用了 todo 工具,重置计数器\r\n this.consecutiveNoTodoTurns = 0;\r\n this.reminderInjected = false;\r\n console.log(`[TodoFeature] Todo tool used, reset counter`);\r\n } else {\r\n // 未使用 todo 工具,计数器加 1\r\n this.consecutiveNoTodoTurns++;\r\n const threshold = this.getCurrentThreshold();\r\n console.log(`[TodoFeature] No todo tool, counter=${this.consecutiveNoTodoTurns}/${threshold}`);\r\n }\r\n\r\n // 若本轮有 Todo 写操作,注入一次最新完整任务列表\r\n if (wroteTodo) {\r\n const planContext = this.buildCurrentTaskPlanContext();\r\n ctx.context.addSystemMessage(\r\n planContext,\r\n ctx.callIndex,\r\n this.name,\r\n 'todo-current-plan',\r\n );\r\n console.log('[TodoFeature] Injected current task plan after write operations');\r\n }\r\n\r\n // 返回 Continue 使用默认行为\r\n return Decision.Continue;\r\n }\r\n\r\n // ========== 公开 API ==========\r\n\r\n /**\r\n * 设置 reminder 内容\r\n */\r\n setReminderContent(content: string): void {\r\n this.reminderContent = content;\r\n }\r\n\r\n /**\r\n * 获取当前的提醒阈值(根据任务状态动态调整)\r\n */\r\n private getCurrentThreshold(): number {\r\n // 检查是否有待执行的任务(pending 或 in_progress)\r\n const hasActiveTasks = Array.from(this.tasks.values()).some(\r\n t => t.status === 'pending' || t.status === 'in_progress'\r\n );\r\n return hasActiveTasks\r\n ? this.config.reminderThresholdWithTasks!\r\n : this.config.reminderThresholdWithoutTasks!;\r\n }\r\n\r\n /**\r\n * 创建任务\r\n */\r\n createTask(\r\n subject: string,\r\n description: string = '',\r\n options?: { metadata?: Record<string, unknown> }\r\n ): TodoTask {\r\n this.counter++;\r\n const task: TodoTask = {\r\n id: String(this.counter),\r\n subject,\r\n description: description || undefined,\r\n status: 'pending',\r\n metadata: options?.metadata,\r\n createdAt: Date.now(),\r\n updatedAt: Date.now(),\r\n };\r\n this.tasks.set(task.id, task);\r\n console.log(`[TodoFeature] Created task ${task.id}: ${subject} (total tasks: ${this.tasks.size})`);\r\n this.pushDebugSnapshot();\r\n return task;\r\n }\r\n\r\n /**\r\n * 获取任务详情\r\n */\r\n getTask(taskId: string): TodoTask | undefined {\r\n return this.tasks.get(taskId);\r\n }\r\n\r\n /**\r\n * 列出所有任务摘要\r\n */\r\n listTasks(filter?: { status?: TaskStatus }): TodoTaskSummary[] {\r\n let tasks = Array.from(this.tasks.values());\r\n if (filter?.status) {\r\n tasks = tasks.filter(t => t.status === filter.status);\r\n }\r\n return tasks.map(task => ({\r\n id: task.id,\r\n subject: task.subject,\r\n status: task.status,\r\n }));\r\n }\r\n\r\n /**\r\n * 更新任务\r\n *\r\n * 允许更新的字段:status, subject, description(模型工具可见)。\r\n * metadata 不在模型工具 schema 中,但内部代码(如 ControlledTodoFeature)\r\n * 需要通过它记录终态时间戳等生命周期数据。\r\n */\r\n updateTask(taskId: string, updates: TodoTaskUpdate & { metadata?: Record<string, unknown> }): TodoTask | undefined {\r\n const task = this.tasks.get(taskId);\r\n if (!task) return undefined;\r\n\r\n const allowedFields: string[] = ['status', 'subject', 'description', 'metadata'];\r\n for (const field of allowedFields) {\r\n if (updates[field as keyof typeof updates] !== undefined) {\r\n (task as unknown as Record<string, unknown>)[field] = updates[field as keyof typeof updates];\r\n }\r\n }\r\n task.updatedAt = Date.now();\r\n\r\n this.pushDebugSnapshot();\r\n return task;\r\n }\r\n\r\n /**\r\n * 清空所有未完成任务,返回被取消的任务数量\r\n */\r\n clearTasks(): number {\r\n const now = Date.now();\r\n let count = 0;\r\n for (const task of this.tasks.values()) {\r\n if (task.status === 'pending' || task.status === 'in_progress') {\r\n task.status = 'deleted';\r\n task.updatedAt = now;\r\n count++;\r\n }\r\n }\r\n this.pushDebugSnapshot();\r\n return count;\r\n }\r\n\r\n getPlanSnapshot(): TodoPlanSnapshot {\r\n const tasks = Array.from(this.tasks.values())\r\n .map(task => ({\r\n id: task.id,\r\n subject: task.subject,\r\n description: task.description || '',\r\n status: task.status,\r\n metadata: task.metadata && typeof task.metadata === 'object' ? { ...task.metadata } : undefined,\r\n createdAt: task.createdAt,\r\n updatedAt: task.updatedAt,\r\n }))\r\n .sort((left, right) => left.createdAt - right.createdAt || Number(left.id) - Number(right.id));\r\n return {\r\n feature: 'todo',\r\n updatedAt: Date.now(),\r\n counter: this.counter,\r\n tasks,\r\n summary: {\r\n total: tasks.length,\r\n pending: tasks.filter(task => task.status === 'pending').length,\r\n inProgress: tasks.filter(task => task.status === 'in_progress').length,\r\n completed: tasks.filter(task => task.status === 'completed').length,\r\n cancelled: tasks.filter(task => task.status === 'deleted').length,\r\n },\r\n };\r\n }\r\n\r\n // ========== 私有方法 ==========\r\n\r\n /** 判断是否是 todo 工具(读或写) */\r\n private isTodoTool(name: string): boolean {\r\n return name === 'task_create' || name === 'task_list' ||\r\n name === 'task_update' || name === 'task_clear';\r\n }\r\n\r\n /** 判断是否是 todo 写工具(仅 task_create 触发完整列表注入) */\r\n private isTodoWriteTool(name: string): boolean {\r\n return name === 'task_create';\r\n }\r\n\r\n /** 截断文本到指定长度 */\r\n private truncate(text: string, maxLength: number): string {\r\n if (text.length <= maxLength) return text;\r\n return text.slice(0, maxLength) + '…';\r\n }\r\n\r\n /**\r\n * 构建 StepFinish 注入的最新完整任务列表文本\r\n * 仅包含 active tasks(pending + in_progress),按 createdAt 升序\r\n */\r\n private buildCurrentTaskPlanContext(): string {\r\n const activeTasks = Array.from(this.tasks.values())\r\n .filter(task => task.status === 'pending' || task.status === 'in_progress')\r\n .sort((a, b) => a.createdAt - b.createdAt || Number(a.id) - Number(b.id));\r\n\r\n if (activeTasks.length === 0) {\r\n return '当前没有待执行任务。若当前工作仍需多步跟踪,可创建任务。不要向用户提及此内部提示。';\r\n }\r\n\r\n const visible = activeTasks.slice(0, MAX_INJECT_TASKS);\r\n const omitted = activeTasks.length - visible.length;\r\n\r\n const lines: string[] = ['[当前任务计划]'];\r\n for (const task of visible) {\r\n const subject = this.truncate(task.subject, MAX_SUBJECT_LENGTH);\r\n const desc = task.description ? this.truncate(task.description, MAX_DESCRIPTION_LENGTH) : '';\r\n lines.push(`- #${task.id} [${task.status}] ${subject}`);\r\n if (desc) {\r\n lines.push(` ${desc}`);\r\n }\r\n }\r\n if (omitted > 0) {\r\n lines.push(`(其余 ${omitted} 项未展示;如需查看全部计划,请使用 task_list。)`);\r\n }\r\n lines.push('');\r\n lines.push('请以此列表作为当前任务计划继续推进;任务开始、完成、调整或取消时,使用 Todo 工具同步状态。');\r\n lines.push('不要向用户提及此内部提示。');\r\n\r\n return lines.join('\\n');\r\n }\r\n\r\n /**\r\n * 构建动态 reminder 文本\r\n * 如果有 active tasks,包含\"当前\"和\"下一项\"信息\r\n * 否则回退到默认温和提醒\r\n */\r\n private buildDynamicReminder(): string {\r\n const activeTasks = Array.from(this.tasks.values())\r\n .filter(task => task.status === 'pending' || task.status === 'in_progress')\r\n .sort((a, b) => a.createdAt - b.createdAt || Number(a.id) - Number(b.id));\r\n\r\n if (activeTasks.length === 0) {\r\n // 无待执行任务,使用自定义模板或默认提醒\r\n return this.reminderContent || this.getDefaultReminder();\r\n }\r\n\r\n const currentTask = activeTasks.find(t => t.status === 'in_progress');\r\n const nextTask = activeTasks.find(t => t.status === 'pending');\r\n\r\n const lines: string[] = ['[任务状态提醒]'];\r\n if (currentTask) {\r\n lines.push(`当前:#${currentTask.id} ${currentTask.subject}`);\r\n } else {\r\n lines.push('当前:无');\r\n }\r\n if (nextTask) {\r\n lines.push(`下一项:#${nextTask.id} ${nextTask.subject}`);\r\n } else {\r\n lines.push('下一项:无');\r\n }\r\n lines.push('');\r\n // 拼接自定义模板尾部或默认提醒文本\r\n const tail = this.reminderContent || this.getDefaultReminder();\r\n lines.push(tail);\r\n\r\n return lines.join('\\n');\r\n }\r\n\r\n /** 获取默认 reminder 内容 */\r\n private getDefaultReminder(): string {\r\n return '最近没有更新任务状态。若该计划仍适用,请在开始、完成、调整或取消任务时使用 Todo 工具同步状态;若计划已不适用,可清理未完成任务。仅在与当前工作相关时使用这些工具。这只是温和的提醒——如果不适用请忽略。务必注意:绝不要向用户提及此提醒。';\r\n }\r\n\r\n /**\r\n * 构建 CallStart 简短任务状态\r\n * 仅包含\"当前/下一项\"两行,不附带催促语\r\n */\r\n private buildCallStartBrief(): string {\r\n const activeTasks = Array.from(this.tasks.values())\r\n .filter(task => task.status === 'pending' || task.status === 'in_progress')\r\n .sort((a, b) => a.createdAt - b.createdAt || Number(a.id) - Number(b.id));\r\n\r\n const currentTask = activeTasks.find(t => t.status === 'in_progress');\r\n const nextTask = activeTasks.find(t => t.status === 'pending');\r\n\r\n const lines: string[] = ['[任务状态]'];\r\n if (currentTask) {\r\n lines.push(`当前:#${currentTask.id} ${currentTask.subject}`);\r\n } else {\r\n lines.push('当前:无');\r\n }\r\n if (nextTask) {\r\n lines.push(`下一项:#${nextTask.id} ${nextTask.subject}`);\r\n } else {\r\n lines.push('下一项:无');\r\n }\r\n lines.push('');\r\n lines.push('请根据当前任务计划继续推进。不要向用户提及此内部提示。');\r\n\r\n return lines.join('\\n');\r\n }\r\n}\r\n\r\n// 重新导出类型\r\nexport type { TodoTask, TodoTaskUpdate, TodoTaskSummary, TaskStatus, TodoFeatureConfig };\r\n","/**\n * Todo Feature 工具定义\n *\n * 提供 4 个任务管理工具:task_create, task_list, task_update, task_clear\n *\n * 设计要点:\n * - execute 返回 withDisplay(精简文本, 丰富 display 数据)\n * - 模型只看到精简确认(如 { ok, taskId, status })\n * - 前端通过 display 数据渲染完整卡片(如任务列表)\n * - 真正的完整任务列表在 StepFinish 时注入一次,而非每次 create 重复\n */\n\nimport type { Tool } from '../../core/types.js';\nimport { createTool } from '../../core/tool.js';\nimport { withDisplay } from '../../core/tool-result-display.js';\nimport type { TodoTask, TodoTaskUpdate, TodoTaskSummary, TaskStatus } from './types.js';\n\n/**\n * Todo 工具工厂类\n * 用于创建 Todo 工具,需要传入 Feature 实例来访问任务数据\n */\nexport class TodoToolFactory {\n private getTaskFn: (taskId: string) => TodoTask | undefined;\n private createTaskFn: (\n subject: string,\n description: string,\n options?: { metadata?: Record<string, unknown> }\n ) => TodoTask;\n private listTasksFn: (filter?: { status?: TaskStatus }) => TodoTaskSummary[];\n private updateTaskFn: (taskId: string, updates: TodoTaskUpdate) => TodoTask | undefined;\n private clearTasksFn: () => number;\n\n constructor(options: {\n getTask: (taskId: string) => TodoTask | undefined;\n createTask: (\n subject: string,\n description: string,\n options?: { metadata?: Record<string, unknown> }\n ) => TodoTask;\n listTasks: (filter?: { status?: TaskStatus }) => TodoTaskSummary[];\n updateTask: (taskId: string, updates: TodoTaskUpdate) => TodoTask | undefined;\n clearTasks: () => number;\n }) {\n this.getTaskFn = options.getTask;\n this.createTaskFn = options.createTask;\n this.listTasksFn = options.listTasks;\n this.updateTaskFn = options.updateTask;\n this.clearTasksFn = options.clearTasks;\n }\n\n /**\n * 创建 task_create 工具\n */\n createCreateTool(): Tool {\n const self = this;\n return createTool({\n name: 'task_create',\n description: `创建一个结构化的任务列表,用于跟踪当前会话的工作进度。\n\n使用时机:\n- 复杂的多步骤任务(需要 3 个或以上独立步骤)\n- 非平凡且复杂的任务(需要仔细规划)\n- 用户明确要求创建任务列表\n- 收到新指令时捕获任务\n\n任务字段:\n- subject: 简短可执行的标题,使用祈使句形式(如 \"修复认证漏洞\")\n- description: 详细描述,包括上下文和验收标准(可选)\n\n重要说明:\n- subject 应该是祈使句形式(\"执行任务\")\n- description 是可选的,简单任务不需要填写\n- 创建后任务状态为 pending,可以通过 task_update 更新为 in_progress、completed 或 deleted(取消并保留记录)`,\n parameters: {\n type: 'object',\n properties: {\n subject: { type: 'string', description: '简短的任务标题,使用祈使句形式(如 \"运行测试\")' },\n description: { type: 'string', description: '详细的任务描述,包括上下文、具体步骤和验收标准' },\n },\n required: ['subject'],\n },\n render: { call: 'task-create', result: 'task-create' },\n execute: ({ subject, description = '' }) => {\n const task = self.createTaskFn(subject, description);\n // 模型只看极简确认;前端通过 display 看到完整信息\n return Promise.resolve(withDisplay(\n JSON.stringify({ ok: true, taskId: task.id, status: task.status }),\n {\n task: {\n id: task.id,\n subject: task.subject,\n description: task.description || '',\n status: task.status,\n },\n allTasks: self.listTasksFn(),\n message: `任务已创建,ID: ${task.id}`,\n },\n ));\n },\n });\n }\n\n /**\n * 创建 task_list 工具\n */\n createListTool(): Tool {\n const self = this;\n return createTool({\n name: 'task_list',\n description: `列出任务列表中的所有任务摘要。\n\n使用时机:\n- 查看当前所有任务的状态\n- 了解整体进度\n\n返回信息:\n- id: 任务标识符\n- subject: 简短描述\n- status: 任务状态(pending/in_progress/completed/deleted)`,\n parameters: {\n type: 'object',\n properties: {\n status: {\n type: 'string',\n enum: ['pending', 'in_progress', 'completed', 'deleted', 'all'],\n description: '按状态筛选任务,默认显示所有任务',\n default: 'all',\n },\n },\n },\n render: { call: 'task-list', result: 'task-list' },\n execute: ({ status = 'all' }) => {\n const tasks = self.listTasksFn(status === 'all' ? undefined : { status });\n const summary = {\n total: tasks.length,\n pending: tasks.filter(t => t.status === 'pending').length,\n inProgress: tasks.filter(t => t.status === 'in_progress').length,\n completed: tasks.filter(t => t.status === 'completed').length,\n cancelled: tasks.filter(t => t.status === 'deleted').length,\n };\n return Promise.resolve(withDisplay(\n JSON.stringify({ tasks }),\n { tasks, summary },\n ));\n },\n });\n }\n\n /**\n * 创建 task_update 工具\n */\n createUpdateTool(): Tool {\n const self = this;\n return createTool({\n name: 'task_update',\n description: `更新任务的状态或详细信息。\n\n状态工作流:pending → in_progress → completed\n\n主要用途:\n1. 标记任务进行中:将 status 设置为 \"in_progress\"\n2. 标记任务完成:将 status 设置为 \"completed\"\n3. 取消任务并保留记录:将 status 设置为 \"deleted\"\n\n任务字段:\n- subject: 简短可执行的标题,使用祈使句形式(如 \"执行任务\")\n- description: 详细描述,包括上下文和验收标准`,\n parameters: {\n type: 'object',\n properties: {\n taskId: { type: 'string', description: '要更新的任务 ID' },\n status: {\n type: 'string',\n enum: ['pending', 'in_progress', 'completed', 'deleted'],\n description: '任务状态',\n },\n subject: { type: 'string', description: '新的任务标题' },\n description: { type: 'string', description: '新的任务描述' },\n },\n required: ['taskId'],\n },\n render: { call: 'task-update', result: 'task-update' },\n execute: ({ taskId, ...updates }) => {\n const task = self.updateTaskFn(taskId, updates);\n if (!task) {\n return Promise.resolve({ ok: false, error: `任务 ${taskId} 不存在` });\n }\n return Promise.resolve(withDisplay(\n JSON.stringify({ ok: true, taskId: task.id, status: task.status }),\n {\n id: task.id,\n subject: task.subject,\n status: task.status,\n message: `任务 ${taskId} 已更新`,\n },\n ));\n },\n });\n }\n\n /**\n * 创建 task_clear 工具\n */\n createClearTool(): Tool {\n const self = this;\n return createTool({\n name: 'task_clear',\n description: `取消任务列表中的所有未完成任务,并保留历史记录。\n\n注意:此操作不会移除历史;pending/in_progress 会变为 deleted,completed 会保留。`,\n parameters: {\n type: 'object',\n properties: {},\n },\n render: { call: 'task-clear', result: 'task-clear' },\n execute: () => {\n const cancelledCount = self.clearTasksFn();\n return Promise.resolve(withDisplay(\n JSON.stringify({ ok: true, cancelledCount }),\n { message: `已取消 ${cancelledCount} 个未完成任务` },\n ));\n },\n });\n }\n\n /**\n * 获取所有工具\n */\n getAllTools(): Tool[] {\n return [\n this.createCreateTool(),\n this.createListTool(),\n this.createUpdateTool(),\n this.createClearTool(),\n ];\n }\n}\n","/**\n * UserInputFeature - 通过调试界面获取用户输入\n *\n * 功能:\n * - 提供 get_user_input 工具,允许 LLM 请求用户输入\n * - 通过 DebugHub 的 UDS 通道与 ViewerWorker 通信\n * - 前端显示输入框,用户提交后返回给 Agent\n */\n\nimport { fileURLToPath } from 'url';\nimport { createTool } from '../../core/tool.js';\nimport type {\n Tool,\n UserInputAction,\n UserInputChoiceAnswer,\n UserInputQuestion,\n UserInputRequest,\n UserInputResponse,\n} from '../../core/types.js';\nimport type { AgentFeature, FeatureInitContext, FeatureContext, PackageInfo } from '../../core/feature.js';\nimport { getPackageInfoFromSource } from '../../core/feature.js';\nimport { DebugHub } from '../../core/debug-hub.js';\n\nexport interface UserInputFeatureConfig {\n /** 默认超时时间(毫秒),默认无限等待 */\n timeout?: number;\n}\n\ninterface ChoiceToolQuestionInput {\n id: string;\n question: string;\n options: Array<{\n id: string;\n label: string;\n description?: string;\n allowSupplement?: boolean;\n supplementRequired?: boolean;\n supplementLabel?: string;\n supplementPlaceholder?: string;\n }>;\n allowCustom?: boolean;\n customLabel?: string;\n customPlaceholder?: string;\n}\n\nconst choiceToolRender = {\n call: {\n call: '<div class=\"bash-command\">等待用户在选择弹窗中决策</div>',\n result: '',\n },\n result: {\n call: '',\n result: '<div class=\"bash-command\">用户已完成选择</div>',\n },\n};\n\nexport class UserInputFeature implements AgentFeature {\n readonly name = 'user-input';\n readonly source = fileURLToPath(import.meta.url).replace(/\\\\/g, '/');\n readonly description = '允许 Agent 通过调试界面向用户发起输入请求并等待回复。';\n\n private defaultTimeout: number;\n private nextDraftInput = '';\n private _agentId: string | null = null;\n\n /**\n * 缓存包信息\n */\n private _packageInfo: PackageInfo | null = null;\n\n /**\n * 获取包信息(统一打包方案)\n */\n getPackageInfo(): PackageInfo | null {\n if (!this._packageInfo) {\n this._packageInfo = getPackageInfoFromSource(this.source);\n }\n return this._packageInfo;\n }\n\n /**\n * 获取模板名称列表(统一打包方案)\n * 注意:UserInputFeature 没有渲染模板\n */\n getTemplateNames(): string[] {\n return [];\n }\n\n constructor(config: UserInputFeatureConfig = {}) {\n this.defaultTimeout = config.timeout ?? Infinity; // 无限等待\n }\n\n setNextDraftInput(input: string): void {\n this.nextDraftInput = input;\n }\n\n /**\n * 请求用户输入(核心方法)\n */\n async requestUserInput(prompt: string, timeout?: number): Promise<string> {\n const response = await this.requestUserInputEvent({ prompt }, timeout);\n if (response.kind !== 'text') {\n throw new Error(`Expected text input but received action '${response.actionId ?? 'unknown'}'`);\n }\n return response.text ?? '';\n }\n\n async requestUserInputEvent(\n request: UserInputRequest,\n timeout?: number,\n ): Promise<UserInputResponse> {\n // 直接获取 DebugHub 实例\n const debugHub = DebugHub.getInstance();\n\n // 使用 install 时保存的 agentId,而非全局 getCurrentAgentId()\n const agentId = this._agentId;\n const capabilities = debugHub.getCapabilities();\n\n if (!agentId) {\n throw new Error('Agent ID not available. UserInputFeature requires onInitiate() to be called first.');\n }\n\n if (!debugHub.isAgentRegistered(agentId) || !debugHub.isConnected()) {\n throw new Error('Interactive input is not attached. Call withViewer() before requesting user input.');\n }\n\n if (!capabilities.interactiveInput) {\n throw new Error(\n `Interactive input is not available for transport '${capabilities.transportMode}'. Current runtime URL: ${capabilities.runtimeUrl ?? 'n/a'}.`\n );\n }\n\n const response = await debugHub.requestUserInputEvent(\n agentId,\n {\n ...request,\n initialValue: request.initialValue ?? this.nextDraftInput,\n },\n timeout ?? this.defaultTimeout\n );\n this.nextDraftInput = '';\n return response;\n }\n\n /**\n * 获取用户输入(公开接口,供主循环直接调用)\n * @param prompt 提示信息\n * @param timeout 超时时间(毫秒)\n * @returns 用户输入内容\n */\n async getUserInput(prompt: string = '请输入:', timeout?: number): Promise<string> {\n return this.requestUserInput(prompt, timeout);\n }\n\n async getUserInputEvent(\n prompt: string = '请输入:',\n timeout?: number,\n actions?: UserInputAction[],\n ): Promise<UserInputResponse> {\n return this.requestUserInputEvent({\n prompt,\n placeholder: prompt,\n actions,\n }, timeout);\n }\n\n async requestUserChoices(\n prompt: string,\n questions: UserInputQuestion[],\n timeout?: number,\n ): Promise<UserInputChoiceAnswer[]> {\n const normalizedQuestions = this.normalizeChoiceQuestions(questions);\n const response = await this.requestUserInputEvent({\n prompt,\n mode: 'choices',\n questions: normalizedQuestions,\n }, timeout);\n\n if (response.kind !== 'choices') {\n throw new Error(`Expected choice input but received '${response.kind}'`);\n }\n return response.choices ?? [];\n }\n\n private normalizeChoiceQuestions(questions: UserInputQuestion[]): UserInputQuestion[] {\n if (!Array.isArray(questions) || questions.length === 0) {\n throw new Error('At least one choice question is required.');\n }\n\n return questions.map((question, index) => {\n const id = String(question.id || `question_${index + 1}`).trim();\n const text = String(question.question || '').trim();\n const options = Array.isArray(question.options) ? question.options : [];\n\n if (!text) {\n throw new Error(`Question ${index + 1} is missing a question prompt.`);\n }\n if (options.length < 1 || options.length > 4) {\n throw new Error(`Question ${index + 1} must provide 1 to 4 options.`);\n }\n\n return {\n id,\n question: text,\n options: options.map((option, optionIndex) => {\n const optionId = String(option.id || `option_${optionIndex + 1}`).trim();\n const label = String(option.label || '').trim();\n if (!label) {\n throw new Error(`Question ${index + 1}, option ${optionIndex + 1} is missing a label.`);\n }\n return {\n id: optionId,\n label,\n description: option.description ? String(option.description) : undefined,\n allowSupplement: Boolean(option.allowSupplement),\n supplementRequired: Boolean(option.supplementRequired),\n supplementLabel: option.supplementLabel ? String(option.supplementLabel) : undefined,\n supplementPlaceholder: option.supplementPlaceholder ? String(option.supplementPlaceholder) : undefined,\n };\n }),\n allowCustom: Boolean(question.allowCustom),\n customLabel: question.customLabel ? String(question.customLabel) : undefined,\n customPlaceholder: question.customPlaceholder ? String(question.customPlaceholder) : undefined,\n };\n });\n }\n\n getTools(): Tool[] {\n return [\n createTool({\n name: 'ask_user_choice',\n description: '向用户展示 1 道或多道选择题,让用户点击或用键盘选择选项;可允许用户选择\"其他\"并输入自定义内容。展示多道时,用户完成一道后直接进入下一道。',\n parameters: {\n type: 'object',\n properties: {\n prompt: {\n type: 'string',\n description: '选择卡片的总说明,简要说明为什么需要用户决策。'\n },\n questions: {\n type: 'array',\n description: '一组选择题(至少 1 道)。每道题必须有 1~4 个选项。',\n minItems: 1,\n items: {\n type: 'object',\n properties: {\n id: { type: 'string', description: '稳定问题 ID。' },\n question: { type: 'string', description: '问题文本。' },\n options: {\n type: 'array',\n minItems: 1,\n maxItems: 4,\n items: {\n type: 'object',\n properties: {\n id: { type: 'string', description: '稳定选项 ID。' },\n label: { type: 'string', description: '选项显示文本。' },\n description: { type: 'string', description: '可选的补充说明。' },\n allowSupplement: { type: 'boolean', description: '是否允许用户在选择此选项后补充自由文本。' },\n supplementRequired: { type: 'boolean', description: '补充文本是否为必填。' },\n supplementLabel: { type: 'string', description: '补充文本输入框的标签。' },\n supplementPlaceholder: { type: 'string', description: '补充文本输入框的占位提示。' }\n },\n required: ['id', 'label']\n }\n },\n allowCustom: { type: 'boolean', description: '是否允许用户输入自定义内容。' },\n customLabel: { type: 'string', description: '自定义选项显示文本。' },\n customPlaceholder: { type: 'string', description: '自定义输入框占位提示。' }\n },\n required: ['id', 'question', 'options']\n }\n }\n },\n required: ['prompt', 'questions']\n },\n execute: async (args) => {\n const { prompt, questions } = args as { prompt: string; questions: ChoiceToolQuestionInput[] };\n const choices = await this.requestUserChoices(prompt, questions);\n return { choices };\n },\n render: choiceToolRender,\n }),\n ];\n }\n\n async onInitiate(ctx: FeatureInitContext): Promise<void> {\n // 保存 agentId,后续 requestUserInputEvent 使用此 ID 而非全局 getCurrentAgentId()\n this._agentId = ctx.agentId;\n }\n\n async onDestroy(_ctx: FeatureContext): Promise<void> {\n if (this._agentId) {\n DebugHub.getInstance().cancelInputRequests(\n this._agentId,\n `UserInputFeature for Agent '${this._agentId}' was destroyed`,\n );\n this._agentId = null;\n }\n }\n}\n","/**\n * FileHistoryFeature - 文件修改历史追踪与回退\n *\n * 独立 Feature,无侵入地接入 AgentDev 的 checkpoint/rollback 体系:\n *\n * - ToolUse 反向钩子:在 write/edit 执行前自动备份文件\n * - CallStart 反向钩子:在每轮用户输入时创建快照\n * - captureState/restoreState:与 Agent 的 CallRollback 集成(仅恢复内存状态)\n * - rewindToSnapshot / rewindToLastSnapshot:用户显式触发的文件回退\n *\n * 文件回退是独立于对话回退的操作(与 Claude Code 的设计一致),\n * 用户可以选择\"仅回退代码\"/\"仅回退对话\"/\"两者都回退\"。\n *\n * 使用方式(消费端,如 Claw):\n * const fh = agent.features?.get('file-history');\n * if (fh) {\n * const snapshots = fh.getSnapshotList();\n * await fh.rewindToSnapshot(selectedId);\n * }\n */\n\nimport { fileURLToPath } from 'url'\nimport { randomUUID } from 'crypto'\nimport { Decision } from '../../core/lifecycle.js';\nimport type { HookDeclarations } from '../../core/hook-declarations.js';\nimport { CoreLifecycle } from '../../core/lifecycle.js';\nimport type { AgentFeature, FeatureStateSnapshot, FeatureInitContext, FeatureContext, PackageInfo } from '../../core/feature.js'\nimport { getPackageInfoFromSource } from '../../core/feature.js'\nimport type { ToolContext } from '../../core/lifecycle.js'\nimport type { DecisionResult } from '../../core/lifecycle.js'\nimport {\n createInitialState,\n trackEdit,\n makeSnapshot,\n rewindToSnapshot as rewindToSnapshotCore,\n rewindToLastSnapshot as rewindToLastSnapshotCore,\n getDiffStats as getDiffStatsCore,\n type FileHistoryState,\n type DiffStats,\n} from './file-history.js'\n\nexport interface FileHistoryFeatureConfig {\n /** 覆盖工作区目录,默认 process.cwd() */\n workspaceDir?: string\n}\n\nexport type SnapshotInfo = {\n id: number\n timestamp: number\n trackedFileCount: number\n}\n\nexport class FileHistoryFeature implements AgentFeature {\n\n static hooks: HookDeclarations = {\n trackFileEdits: { lifecycle: CoreLifecycle.ToolUse, kind: 'guard' as const, role: 'advisor' as const },\n onCallStart: { lifecycle: CoreLifecycle.CallStart, kind: 'observe' as const },\n };\n readonly name = 'file-history'\n readonly source = fileURLToPath(import.meta.url).replace(/\\\\/g, '/')\n readonly description = '追踪文件修改历史,支持代码回退到任意轮次的状态。'\n\n private _packageInfo: PackageInfo | null = null\n private logger: any\n private state: FileHistoryState | null = null\n private readonly workspaceDir: string\n\n constructor(config: FileHistoryFeatureConfig = {}) {\n this.workspaceDir = config.workspaceDir || process.cwd()\n }\n\n getPackageInfo(): PackageInfo | null {\n if (!this._packageInfo) {\n this._packageInfo = getPackageInfoFromSource(this.source)\n }\n return this._packageInfo\n }\n\n // ========== 生命周期 ==========\n\n async onInitiate(ctx: FeatureInitContext): Promise<void> {\n this.logger = ctx.logger\n const sessionId = randomUUID()\n this.state = createInitialState(sessionId, this.workspaceDir)\n\n this.logger?.info('File history initialized', {\n feature: 'file-history',\n sessionId,\n workspaceDir: this.workspaceDir,\n })\n }\n\n async onDestroy(_ctx: FeatureContext): Promise<void> {\n this.state = null\n }\n\n // ========== 反向钩子 ==========\n\n /**\n * ToolUse 反向钩子:在 write/edit 工具执行前备份文件\n *\n * 在所有 Feature 的 ToolUse 钩子中,本钩子只关注 write/edit 两个工具,\n * 其余一律放行 (Decision.Continue)。\n */\n async trackFileEdits(ctx: ToolContext): Promise<DecisionResult> {\n if (!this.state) return Decision.Continue\n\n const toolName = ctx.call.name\n if (toolName !== 'write' && toolName !== 'edit') {\n return Decision.Continue\n }\n\n const filePath = ctx.call.arguments?.filePath as string\n if (!filePath) return Decision.Continue\n\n try {\n this.state = await trackEdit(this.state, filePath)\n } catch (error) {\n // 备份失败不应阻止工具执行,记录日志后放行\n this.logger?.error('File history track failed', {\n filePath,\n toolName,\n error: error instanceof Error ? error.message : String(error),\n feature: 'file-history',\n })\n }\n\n return Decision.Continue\n }\n\n /**\n * CallStart 反向钩子:每轮用户输入时创建文件快照\n *\n * 第一次 CallStart 创建空快照,后续 CallStart 检测已追踪文件是否有变化,\n * 有变化的创建新版本备份。\n */\n async onCallStart(_ctx: any): Promise<void> {\n if (!this.state) return\n\n try {\n this.state = await makeSnapshot(this.state)\n } catch (error) {\n this.logger?.error('File history snapshot failed', {\n error: error instanceof Error ? error.message : String(error),\n feature: 'file-history',\n })\n }\n }\n\n // ========== Checkpoint 集成 ==========\n\n /**\n * 捕获当前文件历史状态(纯内存,不碰磁盘)\n *\n * 由 Agent 的 commitCallCheckpoint 调用。\n * 保存快照元数据,使得 rollbackToCall 时能恢复到对应的文件历史状态。\n */\n captureState(): FeatureStateSnapshot {\n if (!this.state) return null\n // 只保存可序列化的元数据,不保存文件内容\n return {\n snapshots: this.state.snapshots,\n trackedFiles: this.state.trackedFiles,\n snapshotCounter: this.state.snapshotCounter,\n sessionId: this.state.sessionId,\n workspaceDir: this.state.workspaceDir,\n }\n }\n\n /**\n * 恢复文件历史状态(仅恢复内存,不恢复磁盘文件)\n *\n * 在三种场景下被调用:step rollback、call rollback、session load。\n * 这里只恢复内存中的快照索引,不做文件回退。\n * 文件回退由用户显式调用 rewindToSnapshot / rewindToLastSnapshot 触发。\n */\n restoreState(snapshot: FeatureStateSnapshot): void {\n const prevState = snapshot as FileHistoryState | null\n if (!prevState || !prevState.snapshots) return\n\n this.state = {\n snapshots: prevState.snapshots,\n trackedFiles: prevState.trackedFiles ?? [],\n snapshotCounter: prevState.snapshotCounter ?? prevState.snapshots.length,\n sessionId: prevState.sessionId,\n workspaceDir: prevState.workspaceDir ?? this.workspaceDir,\n }\n }\n\n // ========== 公开 API(供消费端调用) ==========\n\n /**\n * 获取快照列表(供 UI 展示)\n */\n getSnapshotList(): SnapshotInfo[] {\n if (!this.state) return []\n return this.state.snapshots.map(s => ({\n id: s.id,\n timestamp: s.timestamp,\n trackedFileCount: Object.keys(s.trackedFileBackups).length,\n }))\n }\n\n /**\n * 获取当前追踪的文件数量\n */\n getTrackedFileCount(): number {\n return this.state?.trackedFiles.length ?? 0\n }\n\n /**\n * 获取快照数量\n */\n getSnapshotCount(): number {\n return this.state?.snapshots.length ?? 0\n }\n\n /**\n * 回退文件到指定快照\n *\n * @returns 被修改的文件路径列表\n */\n async rewindToSnapshot(snapshotId: number): Promise<string[]> {\n if (!this.state) throw new Error('File history not initialized')\n const changed = await rewindToSnapshotCore(this.state, snapshotId)\n this.logger?.info('Files rewound to snapshot', {\n snapshotId,\n changedFilesCount: changed.length,\n changedFiles: changed,\n feature: 'file-history',\n })\n return changed\n }\n\n /**\n * 回退文件到当前内存状态的最后一个快照\n *\n * 典型用法:先 rollbackToCall 恢复对话 + 内存状态,再调此方法恢复文件。\n * await agent.rollbackToCall(targetCallIndex)\n * const fh = agent.features?.get('file-history')\n * await fh?.rewindToLastSnapshot()\n */\n async rewindToLastSnapshot(): Promise<string[]> {\n if (!this.state) throw new Error('File history not initialized')\n const changed = await rewindToLastSnapshotCore(this.state)\n this.logger?.info('Files rewound to last snapshot', {\n changedFilesCount: changed.length,\n changedFiles: changed,\n feature: 'file-history',\n })\n return changed\n }\n\n /**\n * 计算回退到指定快照的 diff 统计(预览用,不修改文件)\n */\n async getDiffStats(snapshotId: number): Promise<DiffStats> {\n if (!this.state) return { filesChanged: [], insertions: 0, deletions: 0 }\n return getDiffStatsCore(this.state, snapshotId)\n }\n}\n","/**\n * 文件历史核心逻辑\n *\n * 改写自 Claude Code 的 fileHistory.ts,去掉 React 状态管理、遥测、VSCode 通知等,\n * 保留纯粹的备份/快照/回退能力。\n *\n * 设计要点:\n * - 备份文件以 {sha256(path)[:16]}@v{N} 命名,存放在 ~/.agentdev/file-history/{sessionId}/\n * - 快照绑定一个递增 ID,记录当时所有被追踪文件的备份版本\n * - 快照上限 100,超过自动淘汰最早的\n * - 变更检测走三层快速路径:stat → size → mtime → content\n */\n\nimport { createHash } from 'crypto'\nimport {\n chmod,\n copyFile,\n mkdir,\n readFile,\n stat,\n unlink,\n} from 'fs/promises'\nimport { dirname, isAbsolute, join, relative } from 'path'\nimport { homedir } from 'os'\nimport type { Stats } from 'fs'\n\n// ========== 类型 ==========\n\ntype BackupFileName = string | null // null = 该版本文件不存在\n\nexport interface FileHistoryBackup {\n backupFileName: BackupFileName\n version: number\n}\n\nexport interface FileHistorySnapshot {\n id: number\n trackedFileBackups: Record<string, FileHistoryBackup>\n timestamp: number\n}\n\nexport interface FileHistoryState {\n snapshots: FileHistorySnapshot[]\n trackedFiles: string[]\n snapshotCounter: number\n sessionId: string\n workspaceDir: string\n}\n\nexport interface DiffStats {\n filesChanged: string[]\n insertions: number\n deletions: number\n}\n\nconst MAX_SNAPSHOTS = 100\n\n// ========== 路径工具 ==========\n\nexport function getBackupDir(sessionId: string): string {\n return join(homedir(), '.agentdev', 'file-history', sessionId)\n}\n\nfunction getBackupFileName(filePath: string, version: number): string {\n const hash = createHash('sha256')\n .update(filePath)\n .digest('hex')\n .slice(0, 16)\n return `${hash}@v${version}`\n}\n\nfunction resolveBackupPath(backupFileName: string, sessionId: string): string {\n return join(getBackupDir(sessionId), backupFileName)\n}\n\nfunction toTrackingPath(filePath: string, workspaceDir: string): string {\n if (!isAbsolute(filePath)) return filePath\n if (filePath.startsWith(workspaceDir)) {\n return relative(workspaceDir, filePath)\n }\n return filePath\n}\n\nfunction toAbsolutePath(trackingPath: string, workspaceDir: string): string {\n if (isAbsolute(trackingPath)) return trackingPath\n return join(workspaceDir, trackingPath)\n}\n\n// ========== 备份操作 ==========\n\nasync function createBackup(\n filePath: string,\n version: number,\n sessionId: string,\n): Promise<FileHistoryBackup> {\n const backupFileName = getBackupFileName(filePath, version)\n const backupPath = resolveBackupPath(backupFileName, sessionId)\n\n // 源文件不存在 → 记录 null 标记\n let srcStats: Stats\n try {\n srcStats = await stat(filePath)\n } catch (e: any) {\n if (e.code === 'ENOENT') {\n return { backupFileName: null, version }\n }\n throw e\n }\n\n // copyFile 不经过 JS 堆,大文件安全\n try {\n await copyFile(filePath, backupPath)\n } catch (e: any) {\n if (e.code === 'ENOENT') {\n await mkdir(dirname(backupPath), { recursive: true })\n await copyFile(filePath, backupPath)\n } else {\n throw e\n }\n }\n\n await chmod(backupPath, srcStats.mode)\n return { backupFileName, version }\n}\n\n/**\n * 三层快速路径:stat → size/mode → mtime → content\n * 来自 Claude Code 的 checkOriginFileChanged\n */\nasync function fileHasChanged(\n originalFile: string,\n backupFileName: string,\n sessionId: string,\n): Promise<boolean> {\n const backupPath = resolveBackupPath(backupFileName, sessionId)\n\n let origStats: Stats | null = null\n try { origStats = await stat(originalFile) } catch {}\n\n let bakStats: Stats | null = null\n try { bakStats = await stat(backupPath) } catch {}\n\n // 一个存在一个不存在 → 变了\n if ((origStats === null) !== (bakStats === null)) return true\n // 都不存在 → 没变\n if (!origStats || !bakStats) return false\n\n // size 或 mode 不同 → 变了\n if (origStats.size !== bakStats.size || origStats.mode !== bakStats.mode) {\n return true\n }\n\n // mtime 快速路径:原文件比备份旧 → 没变(跳过内容比较)\n if (origStats.mtimeMs < bakStats.mtimeMs) return false\n\n // 兜底:读内容比较\n try {\n const [orig, bak] = await Promise.all([\n readFile(originalFile, 'utf-8'),\n readFile(backupPath, 'utf-8'),\n ])\n return orig !== bak\n } catch {\n return true\n }\n}\n\nasync function restoreFile(\n filePath: string,\n backupFileName: string,\n sessionId: string,\n): Promise<void> {\n const backupPath = resolveBackupPath(backupFileName, sessionId)\n try {\n await copyFile(backupPath, filePath)\n } catch (e: any) {\n if (e.code === 'ENOENT') {\n await mkdir(dirname(filePath), { recursive: true })\n await copyFile(backupPath, filePath)\n } else {\n throw e\n }\n }\n}\n\n// ========== 状态初始化 ==========\n\nexport function createInitialState(\n sessionId: string,\n workspaceDir: string,\n): FileHistoryState {\n return {\n snapshots: [],\n trackedFiles: [],\n snapshotCounter: 0,\n sessionId,\n workspaceDir,\n }\n}\n\n// ========== 核心操作 ==========\n\n/**\n * 追踪文件编辑 —— 在 write/edit 工具执行前调用\n *\n * 只在当前最新快照中还没有该文件备份时才创建 v1 备份。\n * 同一快照内多次调用(如同一轮内编辑同一文件两次)会跳过,保留首次编辑前的状态。\n */\nexport async function trackEdit(\n state: FileHistoryState,\n filePath: string,\n): Promise<FileHistoryState> {\n const trackingPath = toTrackingPath(filePath, state.workspaceDir)\n const latestSnapshot = state.snapshots[state.snapshots.length - 1]\n\n if (!latestSnapshot) return state\n\n // 已在当前快照中追踪过 → 跳过(保持 pre-edit 的 v1 备份不被覆盖)\n if (latestSnapshot.trackedFileBackups[trackingPath]) {\n return state\n }\n\n const absolutePath = toAbsolutePath(trackingPath, state.workspaceDir)\n const backup = await createBackup(absolutePath, 1, state.sessionId)\n\n const newTrackedFiles = state.trackedFiles.includes(trackingPath)\n ? state.trackedFiles\n : [...state.trackedFiles, trackingPath]\n\n // 更新最新快照,添加该文件的备份\n return {\n ...state,\n trackedFiles: newTrackedFiles,\n snapshots: state.snapshots.map((s, i) =>\n i === state.snapshots.length - 1\n ? {\n ...s,\n trackedFileBackups: {\n ...s.trackedFileBackups,\n [trackingPath]: backup,\n },\n }\n : s\n ),\n }\n}\n\n/**\n * 创建快照 —— 在每轮 Call 开始时调用\n *\n * 遍历所有已追踪文件,有变化的创建新版本备份,没变化的复用上一版本引用。\n */\nexport async function makeSnapshot(\n state: FileHistoryState,\n): Promise<FileHistoryState> {\n const latestSnapshot = state.snapshots[state.snapshots.length - 1]\n const newBackups: Record<string, FileHistoryBackup> = {}\n\n if (latestSnapshot) {\n await Promise.all(\n state.trackedFiles.map(async (trackingPath) => {\n const absolutePath = toAbsolutePath(trackingPath, state.workspaceDir)\n const lastBackup = latestSnapshot.trackedFileBackups[trackingPath]\n const nextVersion = lastBackup ? lastBackup.version + 1 : 1\n\n let fileStats: Stats | undefined\n try {\n fileStats = await stat(absolutePath)\n } catch (e: any) {\n if (e.code === 'ENOENT') {\n // 文件被删了\n newBackups[trackingPath] = { backupFileName: null, version: nextVersion }\n return\n }\n throw e\n }\n\n // 文件存在,检查是否有变化\n if (\n lastBackup &&\n lastBackup.backupFileName !== null &&\n !(await fileHasChanged(absolutePath, lastBackup.backupFileName, state.sessionId))\n ) {\n // 未变化,复用上一版本\n newBackups[trackingPath] = lastBackup\n return\n }\n\n // 有变化,创建新版本备份\n newBackups[trackingPath] = await createBackup(\n absolutePath,\n nextVersion,\n state.sessionId,\n )\n }),\n )\n }\n\n // 继承上一快照中未被新快照覆盖的备份\n if (latestSnapshot) {\n for (const path of state.trackedFiles) {\n if (!(path in newBackups) && latestSnapshot.trackedFileBackups[path]) {\n newBackups[path] = latestSnapshot.trackedFileBackups[path]\n }\n }\n }\n\n const newSnapshot: FileHistorySnapshot = {\n id: state.snapshotCounter,\n trackedFileBackups: newBackups,\n timestamp: Date.now(),\n }\n\n const allSnapshots = [...state.snapshots, newSnapshot]\n\n return {\n ...state,\n snapshots:\n allSnapshots.length > MAX_SNAPSHOTS\n ? allSnapshots.slice(-MAX_SNAPSHOTS)\n : allSnapshots,\n snapshotCounter: state.snapshotCounter + 1,\n }\n}\n\n/**\n * 回退文件到指定快照\n *\n * 遍历所有已追踪文件,将其恢复到目标快照记录的版本。\n * 返回被修改的文件路径列表。\n */\nexport async function rewindToSnapshot(\n state: FileHistoryState,\n snapshotId: number,\n): Promise<string[]> {\n const targetSnapshot = [...state.snapshots].reverse().find(s => s.id === snapshotId)\n if (!targetSnapshot) {\n throw new Error(`Snapshot ${snapshotId} not found`)\n }\n\n return applySnapshot(state, targetSnapshot)\n}\n\n/**\n * 回退到给定状态的最后一个快照(rollbackToCall 后调用)\n */\nexport async function rewindToLastSnapshot(\n state: FileHistoryState,\n): Promise<string[]> {\n const lastSnapshot = state.snapshots[state.snapshots.length - 1]\n if (!lastSnapshot) return []\n return applySnapshot(state, lastSnapshot)\n}\n\n/**\n * 计算回退到指定快照的 diff 统计(不实际修改文件)\n */\nexport async function getDiffStats(\n state: FileHistoryState,\n snapshotId: number,\n): Promise<DiffStats> {\n const targetSnapshot = [...state.snapshots].reverse().find(s => s.id === snapshotId)\n if (!targetSnapshot) {\n return { filesChanged: [], insertions: 0, deletions: 0 }\n }\n\n // 动态导入 diffLines 避免硬依赖\n const { diffLines } = await import('diff')\n\n const filesChanged: string[] = []\n let insertions = 0\n let deletions = 0\n\n for (const trackingPath of state.trackedFiles) {\n const absolutePath = toAbsolutePath(trackingPath, state.workspaceDir)\n const targetBackup = targetSnapshot.trackedFileBackups[trackingPath]\n\n const backupFileName: BackupFileName | undefined = targetBackup\n ? targetBackup.backupFileName\n : getBackupFileNameFirstVersion(trackingPath, state)\n\n if (backupFileName === undefined) continue\n\n try {\n let currentContent: string | null = null\n let snapshotContent: string | null = null\n\n try {\n currentContent = await readFile(absolutePath, 'utf-8')\n } catch {}\n\n if (backupFileName !== null) {\n const backupPath = resolveBackupPath(backupFileName, state.sessionId)\n try {\n snapshotContent = await readFile(backupPath, 'utf-8')\n } catch {}\n }\n\n const changes = diffLines(currentContent ?? '', snapshotContent ?? '')\n let hasChanges = false\n for (const c of changes) {\n if (c.added) { insertions += c.count || 0; hasChanges = true }\n if (c.removed) { deletions += c.count || 0; hasChanges = true }\n }\n if (hasChanges) filesChanged.push(absolutePath)\n } catch {\n // 跳过无法比较的文件\n }\n }\n\n return { filesChanged, insertions, deletions }\n}\n\n// ========== 内部工具 ==========\n\nasync function applySnapshot(\n state: FileHistoryState,\n targetSnapshot: FileHistorySnapshot,\n): Promise<string[]> {\n const changedFiles: string[] = []\n\n for (const trackingPath of state.trackedFiles) {\n const absolutePath = toAbsolutePath(trackingPath, state.workspaceDir)\n const targetBackup = targetSnapshot.trackedFileBackups[trackingPath]\n\n const backupFileName: BackupFileName | undefined = targetBackup\n ? targetBackup.backupFileName\n : getBackupFileNameFirstVersion(trackingPath, state)\n\n if (backupFileName === undefined) continue\n\n if (backupFileName === null) {\n // 目标版本文件不存在,删除当前文件\n try {\n await unlink(absolutePath)\n changedFiles.push(absolutePath)\n } catch (e: any) {\n if (e.code !== 'ENOENT') throw e\n }\n continue\n }\n\n // 仅当文件确实变了才恢复\n if (await fileHasChanged(absolutePath, backupFileName, state.sessionId)) {\n await restoreFile(absolutePath, backupFileName, state.sessionId)\n changedFiles.push(absolutePath)\n }\n }\n\n return changedFiles\n}\n\n/**\n * 查找文件最早的 v1 备份(用于回退到快照中未追踪的文件)\n */\nfunction getBackupFileNameFirstVersion(\n trackingPath: string,\n state: FileHistoryState,\n): BackupFileName | undefined {\n for (const s of state.snapshots) {\n const backup = s.trackedFileBackups[trackingPath]\n if (backup !== undefined && backup.version === 1) {\n return backup.backupFileName\n }\n }\n return undefined\n}\n","/**\n * Handoff-Seed Feature(ticket 006 自 Claw context-handoff-seed 下沉为框架标准 feature)。\n *\n * 当 runtime 从一次会话接续包启动时,在首个 CallStart 精确注入一次裁剪后的\n * handoff 转录(seed messages),并推进 `_callIndex` 避免轮次冲突。\n *\n * 随迁已解决的关键实现:\n * - typed Context API 注入(messages[] / enrichedMessages[] 同步)\n * - seed turn 对齐与 `_callIndex` 推进\n * - serialized tool message 重放(保留图片附件,不丢字段)\n *\n * env 传递约定(如 handoff 文件路径)留宿主,框架只提供 feature 类。\n */\n\nimport { fileURLToPath } from 'url';\nimport { existsSync, readFileSync } from 'fs';\nimport { join, resolve, normalize } from 'path';\nimport type {\n AgentFeature,\n FeatureContext,\n FeatureInitContext,\n FeatureStateSnapshot,\n} from '../../core/feature.js';\nimport type { HookDeclarations } from '../../core/hook-declarations.js';\nimport { CoreLifecycle } from '../../core/lifecycle.js';\nimport type { CallStartContext } from '../../core/lifecycle.js';\nimport type {\n HandoffSeedFeatureConfig,\n HandoffSeedPayload,\n HandoffSeedMessage,\n HandoffSeedSnapshot,\n} from './types.js';\n\nconst __filename = fileURLToPath(import.meta.url);\n\nconst MAX_FILE_CHARS = 8000;\nconst MAX_TOTAL_FILE_CHARS = 30000;\nconst MAX_SKILL_CHARS = 5000;\nconst MAX_TOTAL_SKILL_CHARS = 15000;\n\nfunction cleanValue(value: unknown): string {\n return typeof value === 'string' ? value.trim() : '';\n}\n\nfunction buildTrimContextLabel(handoff: HandoffSeedPayload): string {\n const lines = [\n '## 会话续接元信息',\n '',\n '当前会话是从更早的对话裁剪续接而来。上方已注入裁剪后的完整对话历史。',\n '以下仅为该会话的任务元信息,不需要重新执行这些任务。',\n ];\n const sourceSessionId = cleanValue(handoff.sourceSessionId);\n if (sourceSessionId) {\n lines.push('', `来源会话:${sourceSessionId}`);\n }\n const sourceSummary = cleanValue(handoff.sourceSummary);\n if (sourceSummary) {\n lines.push('', sourceSummary);\n }\n return lines.join('\\n');\n}\n\nfunction buildSummarySeedMessage(handoff: HandoffSeedPayload): string {\n const lines = [\n '## 上下文交接摘要',\n '',\n '以下压缩上下文来自更早的一次会话导出,用于让当前运行时继续同一个任务。',\n ];\n const sourceSessionId = cleanValue(handoff.sourceSessionId);\n if (sourceSessionId) {\n lines.push('', `来源会话:${sourceSessionId}`);\n }\n const sourceSummary = cleanValue(handoff.sourceSummary);\n if (sourceSummary) {\n lines.push('', sourceSummary);\n }\n return lines.join('\\n');\n}\n\n/**\n * Inject a single seed message into Context via the typed API that keeps\n * both messages[] and enrichedMessages[] in sync.\n *\n * tool messages use addSerializedToolMessage() because their content is already\n * serialized in the handoff package and must be replayed without lossy parsing.\n */\nfunction injectSeedMessage(\n context: CallStartContext['context'],\n message: HandoffSeedMessage,\n turn: number,\n): void {\n const content = typeof message.content === 'string' ? message.content : '';\n const role = message.role;\n const tag = typeof message.tag === 'string' ? message.tag : undefined;\n\n if (role === 'system') {\n context.addSystemMessage(content, turn, 'handoff-seed', tag);\n } else if (role === 'user') {\n context.addUserMessage(content, turn, message.images as any);\n } else if (role === 'assistant') {\n context.addAssistantMessage(\n {\n content,\n toolCalls: message.toolCalls as any,\n reasoning: message.reasoning as any,\n thinkingBlocks: message.thinkingBlocks as any,\n },\n turn,\n );\n } else if (role === 'tool' && message.toolCallId) {\n context.addSerializedToolMessage(message.toolCallId, content, turn, message.images as any);\n } else {\n context.add({ role, content, turn, toolCallId: message.toolCallId, images: message.images, ...(tag ? { tag } : {}) } as any);\n }\n}\n\nexport class HandoffSeedFeature implements AgentFeature {\n\n static hooks: HookDeclarations = {\n injectHandoffSummary: { lifecycle: CoreLifecycle.CallStart, kind: 'observe' as const },\n };\n readonly name = 'handoff-seed';\n readonly dependencies: string[] = [];\n readonly source = __filename.replace(/\\\\/g, '/');\n readonly description = 'Injects a trimmed handoff transcript exactly once on the first CallStart when a runtime is booted from a handoff package.';\n\n private readonly handoff: HandoffSeedPayload;\n private injected = false;\n private logger?: FeatureInitContext['logger'];\n\n constructor(config: HandoffSeedFeatureConfig) {\n const rawSeedMessages = Array.isArray(config?.handoff?.seedMessages)\n ? config.handoff.seedMessages\n : [];\n this.handoff = {\n packageId: cleanValue(config?.handoff?.packageId),\n sourceSessionId: cleanValue(config?.handoff?.sourceSessionId),\n sourceSummary: cleanValue(config?.handoff?.sourceSummary),\n mode: cleanValue(config?.handoff?.mode),\n seedMessages: rawSeedMessages as any,\n importantFiles: Array.isArray(config?.handoff?.importantFiles)\n ? config.handoff.importantFiles.filter(f => typeof f === 'string')\n : [],\n importantSkills: Array.isArray(config?.handoff?.importantSkills)\n ? config.handoff.importantSkills.filter(s => typeof s === 'string')\n : [],\n fileRanges: typeof config?.handoff?.fileRanges === 'object' && config.handoff.fileRanges !== null\n ? config.handoff.fileRanges\n : {},\n featureContinuity: config?.handoff?.featureContinuity,\n };\n }\n\n async onInitiate(ctx: FeatureInitContext): Promise<void> {\n this.logger = ctx.logger;\n this.logger?.info('Handoff seed feature initiated', {\n packageId: this.handoff.packageId || null,\n sourceSessionId: this.handoff.sourceSessionId || null,\n mode: this.handoff.mode || null,\n seedMessageCount: this.handoff.seedMessages?.length || 0,\n hasSourceSummary: Boolean(this.handoff.sourceSummary),\n });\n }\n\n async onDestroy(_ctx: FeatureContext): Promise<void> {\n this.logger?.info('Handoff seed feature destroyed', {\n injected: this.injected,\n });\n }\n\n captureState(): FeatureStateSnapshot {\n const snapshot: HandoffSeedSnapshot = {\n injected: this.injected,\n };\n return snapshot;\n }\n\n restoreState(snapshot: FeatureStateSnapshot): void {\n const state = snapshot as HandoffSeedSnapshot | null | undefined;\n this.injected = Boolean(state?.injected);\n }\n\n async injectHandoffSummary(ctx: CallStartContext): Promise<void> {\n if (this.injected || !ctx.isFirstCall) {\n return;\n }\n\n const fallbackTurn = typeof (ctx.agent as any)?._callIndex === 'number' ? (ctx.agent as any)._callIndex : 0;\n const seedMessages: HandoffSeedMessage[] = Array.isArray(this.handoff.seedMessages) ? this.handoff.seedMessages : [];\n\n let injectionTurn = fallbackTurn;\n\n if (seedMessages.length > 0) {\n seedMessages.forEach((message, index) => {\n const turn = typeof message?.turn === 'number' && Number.isFinite(message.turn)\n ? Number(message.turn)\n : (fallbackTurn + index);\n injectionTurn = Math.max(injectionTurn, turn + 1);\n injectSeedMessage(ctx.context, message, turn);\n });\n\n const agentRef = ctx.agent as any;\n if (typeof agentRef?._callIndex === 'number' && injectionTurn > agentRef._callIndex) {\n agentRef._callIndex = injectionTurn;\n }\n }\n\n if (this.handoff.sourceSummary && seedMessages.length === 0) {\n const isTrim = cleanValue(this.handoff.mode).startsWith('trim');\n const label = isTrim\n ? buildTrimContextLabel(this.handoff)\n : buildSummarySeedMessage(this.handoff);\n ctx.context.addSystemMessage(label, injectionTurn, this.name);\n }\n\n if (seedMessages.length === 0 && !this.handoff.sourceSummary) {\n return;\n }\n\n this.injected = true;\n this.logger?.info('Injected handoff seed', {\n packageId: this.handoff.packageId || null,\n sourceSessionId: this.handoff.sourceSessionId || null,\n seedMessageCount: seedMessages.length,\n turn: fallbackTurn,\n });\n\n this.injectImportantContext(ctx, injectionTurn);\n }\n\n private injectImportantContext(ctx: CallStartContext, baseTurn: number): void {\n const projectRoot = typeof (ctx.agent as any)?.projectRoot === 'string'\n ? (ctx.agent as any).projectRoot\n : process.cwd();\n\n let injectionTurn = baseTurn + 1;\n\n const fileBlocks = this.buildFileBlocks(projectRoot);\n for (const block of fileBlocks) {\n ctx.context.addSystemMessage(block, injectionTurn, this.name);\n injectionTurn += 1;\n }\n\n const skillBlocks = this.buildSkillBlocks(projectRoot);\n for (const block of skillBlocks) {\n ctx.context.addSystemMessage(block, injectionTurn, this.name);\n injectionTurn += 1;\n }\n }\n\n private resolveFilePath(filePath: string, projectRoot: string): string {\n if (existsSync(filePath)) return filePath;\n const resolved = resolve(projectRoot, filePath);\n if (existsSync(resolved)) return resolved;\n return filePath;\n }\n\n private buildFileBlocks(projectRoot: string): string[] {\n const files = this.handoff.importantFiles || [];\n if (files.length === 0) return [];\n\n const ranges = this.handoff.fileRanges || {};\n const blocks: string[] = [];\n const nameOnlyList: string[] = [];\n let totalChars = 0;\n\n for (const filePath of files) {\n const resolved = this.resolveFilePath(filePath, projectRoot);\n const content = this.tryReadFile(resolved);\n const range = ranges[filePath];\n const rangeLabel = range ? `(上次阅读行 ${range})` : '';\n\n if (content === null) {\n nameOnlyList.push(`${filePath} ${rangeLabel}(文件未找到)`);\n continue;\n }\n const budget = Math.max(0, MAX_TOTAL_FILE_CHARS - totalChars);\n if (content.length <= budget && content.length <= MAX_FILE_CHARS) {\n blocks.push([\n `以下文件在此会话的前一轮中被标记为重要,内容已重新加载(行号为参考值,文件可能已变更):`,\n '',\n `### ${filePath} ${rangeLabel}`,\n content,\n ].join('\\n'));\n totalChars += content.length;\n } else {\n nameOnlyList.push(`${filePath} ${rangeLabel}`);\n }\n }\n\n if (nameOnlyList.length > 0) {\n const nameBlockLines = [\n '以下文件在此会话的前一轮中被标记为重要,但因超出显示上限或文件未找到仅保留路径(行号为参考值,文件可能已变更):',\n '',\n ];\n for (const p of nameOnlyList) nameBlockLines.push(`- ${p}`);\n blocks.push(nameBlockLines.join('\\n'));\n }\n\n return blocks;\n }\n\n private buildSkillBlocks(projectRoot: string): string[] {\n const skills = this.handoff.importantSkills || [];\n if (skills.length === 0) return [];\n\n const blocks: string[] = [];\n const nameOnlyList: string[] = [];\n let totalChars = 0;\n\n for (const skillName of skills) {\n const skillDir = join(projectRoot, '.agentdev', 'skills', skillName);\n const skillMdPath = join(skillDir, 'SKILL.md');\n const content = this.tryReadFile(skillMdPath);\n const basePath = normalize(skillDir);\n\n if (content === null) {\n nameOnlyList.push(`${skillName}(技能定义未找到,目录:${basePath})`);\n continue;\n }\n\n const parsed = this.parseSkillMd(content);\n const header = [\n `**技能名称**:${parsed.name || skillName}`,\n parsed.description ? `**技能描述**:${parsed.description}` : '',\n `**技能的基础目录路径**:\\`${basePath}\\``,\n '',\n '---',\n '',\n parsed.body,\n ].filter(Boolean).join('\\n');\n\n const budget = Math.max(0, MAX_TOTAL_SKILL_CHARS - totalChars);\n const truncated = header.length > MAX_SKILL_CHARS\n ? header.slice(0, MAX_SKILL_CHARS) + '\\n(已截断)'\n : header;\n if (truncated.length <= budget) {\n blocks.push([\n '以下技能在此会话的前一轮中被标记为重要:',\n '',\n `### 技能: ${skillName}`,\n truncated,\n ].join('\\n'));\n totalChars += truncated.length;\n } else {\n nameOnlyList.push(`${skillName}(目录:${basePath})`);\n }\n }\n\n if (nameOnlyList.length > 0) {\n const nameBlockLines = [\n '以下技能在此会话的前一轮中被标记为重要,但因超出显示上限或定义未找到仅保留名称:',\n '',\n ];\n for (const s of nameOnlyList) nameBlockLines.push(`- ${s}`);\n blocks.push(nameBlockLines.join('\\n'));\n }\n\n return blocks;\n }\n\n private parseSkillMd(content: string): { name: string; description: string; body: string } {\n const result = { name: '', description: '', body: content };\n const frontmatterMatch = content.match(/^---\\s*\\n([\\s\\S]*?)\\n---/);\n if (!frontmatterMatch) return result;\n const yaml = frontmatterMatch[1];\n const nameMatch = yaml.match(/^name:\\s*[\"']?(.+?)[\"']?\\s*$/m);\n if (nameMatch) result.name = nameMatch[1].trim();\n const descMatch = yaml.match(/^description:\\s*[\"'](.+?)[\"']\\s*$/m);\n if (descMatch) result.description = descMatch[1].trim();\n result.body = content.slice(frontmatterMatch[0].length).trim();\n return result;\n }\n\n private tryReadFile(filePath: string): string | null {\n try {\n if (!existsSync(filePath)) return null;\n const content = readFileSync(filePath, 'utf8');\n return content.length > MAX_FILE_CHARS\n ? content.slice(0, MAX_FILE_CHARS) + '\\n(已截断)'\n : content;\n } catch {\n return null;\n }\n }\n}\n","/**\n * OpencodeBasicFeature - 基础文件操作工具集\n * 来自 opencode 项目的优秀基础文件工具实现\n *\n * 包含工具:\n * - read: 文件读取(支持 offset/limit 分页)\n * - write: 文件写入(覆盖模式)\n * - edit: 文件编辑(智能匹配策略)\n * - ls: 目录列表(树形结构)\n * - glob: 文件模式搜索\n * - grep: 内容搜索(基于 ripgrep)\n *\n * 安全机制:\n * - \"先读后写\"保护:write 工具前必须先 read 过该文件\n */\n\nimport { fileURLToPath } from 'url';\nimport { resolve } from 'path';\nimport { promises as fs } from 'fs';\nimport { Decision } from '../../core/lifecycle.js';\nimport type { HookDeclarations } from '../../core/hook-declarations.js';\nimport { CoreLifecycle } from '../../core/lifecycle.js';\nimport type { AgentFeature, FeatureStateSnapshot, PackageInfo } from '../../core/feature.js';\nimport type { ToolContext } from '../../core/lifecycle.js';\nimport type { FeatureInitContext } from '../../core/feature.js';\nimport type { DecisionResult } from '../../core/lifecycle.js';\nimport { getPackageInfoFromSource } from '../../core/feature.js';\nimport {\n createReadTool,\n createWriteTool,\n createEditTool,\n createLsTool,\n createGlobTool,\n createGrepTool,\n normalizeNamedPathArg,\n resolveWorkspacePath,\n serializeReadDedupState,\n deserializeReadDedupState,\n} from './tools.js';\n\nconst __filename = fileURLToPath(import.meta.url);\n\nexport interface OpencodeBasicFeatureConfig {\n workspaceDir?: string;\n}\n\n/**\n * OpencodeBasic Feature - 基础文件操作工具集\n */\nexport class OpencodeBasicFeature implements AgentFeature {\n\n static hooks: HookDeclarations = {\n validateWriteOperation: { lifecycle: CoreLifecycle.ToolUse, kind: 'guard' as const, role: 'advisor' as const },\n };\n readonly name = 'opencode-basic';\n readonly source = __filename.replace(/\\\\/g, '/');\n readonly description = '提供读写文件、编辑、列目录、glob 和 grep 等基础工程化工具。包含\"先读后写\"安全保护机制。';\n\n /**\n * 存储已读取文件的路径(绝对路径)\n * 在整个 Session 生命周期中保持,用于验证 write 操作\n */\n private readFiles = new Set<string>();\n\n /**\n * 缓存包信息\n */\n private _packageInfo: PackageInfo | null = null;\n\n /**\n * 获取包信息(统一打包方案)\n */\n getPackageInfo(): PackageInfo | null {\n if (!this._packageInfo) {\n this._packageInfo = getPackageInfoFromSource(this.source);\n }\n return this._packageInfo;\n }\n\n /**\n * 获取模板名称列表(统一打包方案)\n */\n getTemplateNames(): string[] {\n return [\n 'read',\n 'write',\n 'edit',\n 'ls',\n 'glob',\n 'grep',\n ];\n }\n\n /**\n * Logger 实例,用于记录结构化日志\n */\n private logger: any;\n private readonly workspaceDir: string;\n\n constructor(config: OpencodeBasicFeatureConfig = {}) {\n this.workspaceDir = config.workspaceDir || process.cwd();\n }\n\n /**\n * Feature 初始化时清空读取历史\n */\n async onInitiate(ctx: FeatureInitContext): Promise<void> {\n this.readFiles.clear();\n this.logger = ctx.logger;\n this.logger?.info('OpencodeBasic read history initialized', {\n feature: 'opencode-basic',\n lifecycle: 'AgentInitiate'\n });\n }\n\n captureState(): FeatureStateSnapshot {\n return {\n readFiles: Array.from(this.readFiles),\n readDedupState: serializeReadDedupState(),\n };\n }\n\n restoreState(snapshot: FeatureStateSnapshot): void {\n const state = snapshot as { readFiles?: string[]; readDedupState?: unknown };\n this.readFiles = new Set(state.readFiles ?? []);\n deserializeReadDedupState(state.readDedupState);\n }\n\n /**\n * 工具使用前拦截器\n * - 记录 read 操作的文件路径\n * - 验证 write / edit 操作是否已先读取(write 创建的新文件自动豁免)\n */\n async validateWriteOperation(ctx: ToolContext): Promise<DecisionResult> {\n const toolName = ctx.call.name;\n\n // 记录 read 操作\n if (toolName === 'read') {\n const filePath = normalizeNamedPathArg(ctx.call.arguments || {}, 'filePath', 'filepath', 'path');\n const normalizedPath = resolveWorkspacePath(filePath, this.workspaceDir);\n this.readFiles.add(normalizedPath);\n\n this.logger?.info('File read tracked', {\n filePath: normalizedPath,\n totalReadFiles: this.readFiles.size,\n feature: 'opencode-basic',\n lifecycle: 'ToolUse',\n hookMethod: 'validateWriteOperation'\n });\n\n return Decision.Continue;\n }\n\n // 验证 write 和 edit 操作\n if (toolName === 'write' || toolName === 'edit') {\n const filePath = normalizeNamedPathArg(ctx.call.arguments || {}, 'filePath', 'filepath', 'path');\n const normalizedPath = resolveWorkspacePath(filePath, this.workspaceDir);\n\n // 检查文件是否存在\n const exists = await fs.stat(normalizedPath)\n .then(() => true)\n .catch(() => false);\n\n // 新建文件(仅 write 会走到此分支),允许并记录,\n // 这样后续可以直接 edit 而不需要重新 read\n if (!exists) {\n this.readFiles.add(normalizedPath);\n\n this.logger?.info('Write allowed for new file', {\n filePath: normalizedPath,\n feature: 'opencode-basic',\n lifecycle: 'ToolUse',\n hookMethod: 'validateWriteOperation'\n });\n return Decision.Continue;\n }\n\n // 修改现有文件,检查是否已读或已 write 过\n if (!this.readFiles.has(normalizedPath)) {\n this.logger?.warn(`${toolName} blocked: file not read in this session`, {\n filePath: normalizedPath,\n readFiles: Array.from(this.readFiles),\n feature: 'opencode-basic',\n lifecycle: 'ToolUse',\n hookMethod: 'validateWriteOperation'\n });\n\n return {\n action: Decision.Deny,\n reason: `文件 ${filePath} 在当前会话中未读取过。请先使用 read 工具查看文件内容后再进行修改。`\n };\n }\n\n this.logger?.info(`${toolName} allowed: file was read or written previously`, {\n filePath: normalizedPath,\n feature: 'opencode-basic',\n lifecycle: 'ToolUse',\n hookMethod: 'validateWriteOperation'\n });\n\n return Decision.Continue;\n }\n\n // 其他工具,放行\n return Decision.Continue;\n }\n\n /**\n * 获取所有工具\n */\n getTools() {\n return [\n createReadTool(this.workspaceDir),\n createWriteTool(this.workspaceDir),\n createEditTool(this.workspaceDir),\n createLsTool(this.workspaceDir),\n createGlobTool(this.workspaceDir),\n createGrepTool(this.workspaceDir),\n ];\n }\n\n}\n","/**\n * OpencodeBasic 工具定义\n * 来自 opencode 项目的优秀基础文件工具实现\n */\n\nimport { createTool } from '../../core/tool.js';\nimport { withDisplay } from '../../core/tool-result-display.js';\nimport { readFile, writeFile, readdir, stat, mkdir } from 'fs/promises';\nimport { glob } from 'glob';\nimport { spawn } from 'child_process';\nimport { createTwoFilesPatch, diffLines } from 'diff';\nimport path from 'path';\nimport { homedir } from 'os';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_READ_LIMIT = 2000;\nconst MAX_LINE_LENGTH = 2000;\nconst MAX_BYTES = 50 * 1024;\nconst LS_LIMIT = 100;\nconst SEARCH_LIMIT = 100;\nconst DEFAULT_WORKSPACE_DIR = process.cwd();\n\nconst IGNORE_PATTERNS = [\n 'node_modules/**',\n '__pycache__/**',\n '.git/**',\n 'dist/**',\n 'build/**',\n 'target/**',\n 'vendor/**',\n 'bin/**',\n 'obj/**',\n '.idea/**',\n '.vscode/**',\n '.zig-cache/**',\n 'zig-out/**',\n '.coverage/**',\n 'coverage/**',\n 'tmp/**',\n 'temp/**',\n '.cache/**',\n 'cache/**',\n 'logs/**',\n '.venv/**',\n 'venv/**',\n 'env/**'\n];\n\n/**\n * Read 去重状态:记录已读文件的 { mtime, offset, limit }。\n * 同一文件同一范围已读过且 mtime 没变时,返回 stub 而非重新读取全文。\n */\ninterface ReadDedupEntry {\n mtimeMs: number;\n /** undefined = set by Edit/Write, not a Read */\n offset: number | undefined;\n limit: number | undefined;\n}\nconst readDedupState = new Map<string, ReadDedupEntry>();\n\n/**\n * 序列化 readDedupState(模块级状态),供 feature captureState 导出。\n * 用于会话精简/恢复时保持 edit/write 的\"先读后写\"校验状态。\n */\nexport function serializeReadDedupState(): Record<string, ReadDedupEntry> {\n return Object.fromEntries(readDedupState);\n}\n\n/**\n * 反序列化 readDedupState,供 feature restoreState 恢复。\n * 先清空再填充,避免残留状态。\n */\nexport function deserializeReadDedupState(data: unknown): void {\n readDedupState.clear();\n if (!data || typeof data !== 'object') return;\n for (const [key, value] of Object.entries(data as Record<string, unknown>)) {\n if (!value || typeof value !== 'object') continue;\n const entry = value as { mtimeMs?: unknown; offset?: unknown; limit?: unknown };\n if (typeof entry.mtimeMs !== 'number') continue;\n readDedupState.set(key, {\n mtimeMs: entry.mtimeMs,\n offset: typeof entry.offset === 'number' ? entry.offset : undefined,\n limit: typeof entry.limit === 'number' ? entry.limit : undefined,\n });\n }\n}\n\nfunction normalizeNamedPathArg(args: unknown, ...keys: string[]): string {\n if (!args || typeof args !== 'object') {\n throw new Error(`Missing required parameter: \"${keys[0]}\"`);\n }\n for (const key of keys) {\n const value = (args as Record<string, unknown>)[key];\n if (typeof value === 'string' && value.trim()) {\n return value;\n }\n }\n const receivedKeys = Object.keys(args as Record<string, unknown>);\n const hint = receivedKeys.length > 0\n ? ` Received keys: [${receivedKeys.join(', ')}]`\n : ' Received an empty object.';\n throw new Error(`Missing required parameter: \"${keys[0]}\".${hint}`);\n}\n\n/**\n * 与 normalizeNamedPathArg 类似,但找不到时返回 undefined 而非抛错。\n * 用于可选路径参数(如 glob/grep 的 searchPath)。\n */\nfunction tryNamedPathArg(args: unknown, ...keys: string[]): string | undefined {\n if (!args || typeof args !== 'object') return undefined;\n for (const key of keys) {\n const value = (args as Record<string, unknown>)[key];\n if (typeof value === 'string' && value.trim()) {\n return value;\n }\n }\n return undefined;\n}\n\nfunction resolveWorkspacePath(filePath: string, workspaceDir: string = DEFAULT_WORKSPACE_DIR): string {\n return expandPath(filePath, workspaceDir);\n}\n\nfunction resolveWorkspaceSearchPath(searchPath: string | undefined, workspaceDir: string = DEFAULT_WORKSPACE_DIR): string {\n if (!searchPath) {\n return workspaceDir;\n }\n return resolveWorkspacePath(searchPath, workspaceDir);\n}\n\n/**\n * 增强版路径解析:~ 展开、空白 trim、null byte 安全检查、NFC 标准化。\n * 参考 Claude Code 的 expandPath 实现。\n */\nfunction expandPath(inputPath: string, baseDir: string = DEFAULT_WORKSPACE_DIR): string {\n if (typeof inputPath !== 'string') {\n throw new TypeError(`Path must be a string, received ${typeof inputPath}`);\n }\n\n // Null byte 安全检查\n if (inputPath.includes('\\0')) {\n throw new Error('Path contains null bytes');\n }\n\n const trimmed = inputPath.trim();\n if (!trimmed) {\n return path.normalize(baseDir).normalize('NFC');\n }\n\n // ~ 展开\n let resolved: string;\n if (trimmed === '~') {\n resolved = homedir();\n } else if (trimmed.startsWith('~/')) {\n resolved = path.join(homedir(), trimmed.slice(2));\n } else if (path.isAbsolute(trimmed)) {\n resolved = path.normalize(trimmed);\n } else {\n resolved = path.resolve(baseDir, trimmed);\n }\n\n return resolved.normalize('NFC');\n}\n\n/**\n * 检查是否为 UNC 路径(Windows 网络路径)。\n * 访问 UNC 路径会触发 SMB 认证,可能泄露 NTLM 凭据。\n */\nfunction isUncPath(filePath: string): boolean {\n return filePath.startsWith('\\\\\\\\') || filePath.startsWith('//');\n}\n\n// ============================================================================\n// 设备文件阻断 — 防止读取无限输出或阻塞输入的设备文件\n// ============================================================================\n\nconst BLOCKED_DEVICE_PATHS = new Set([\n '/dev/zero',\n '/dev/random',\n '/dev/urandom',\n '/dev/full',\n '/dev/stdin',\n '/dev/tty',\n '/dev/console',\n '/dev/stdout',\n '/dev/stderr',\n '/dev/fd/0',\n '/dev/fd/1',\n '/dev/fd/2',\n]);\n\nfunction isBlockedDevicePath(filePath: string): boolean {\n if (BLOCKED_DEVICE_PATHS.has(filePath)) return true;\n if (\n filePath.startsWith('/proc/') &&\n (filePath.endsWith('/fd/0') || filePath.endsWith('/fd/1') || filePath.endsWith('/fd/2'))\n ) {\n return true;\n }\n return false;\n}\n\n// ============================================================================\n// 编码与行尾符检测\n// ============================================================================\n\ntype FileEncoding = 'utf8' | 'utf16le';\ntype LineEndingType = 'LF' | 'CRLF';\n\ninterface FileMetadata {\n content: string;\n encoding: FileEncoding;\n lineEndings: LineEndingType;\n}\n\n/**\n * 从 Buffer 检测编码(UTF-16LE BOM 检测)\n */\nfunction detectEncoding(buffer: Buffer): FileEncoding {\n if (buffer.length >= 2 && buffer[0] === 0xff && buffer[1] === 0xfe) {\n return 'utf16le';\n }\n return 'utf8';\n}\n\n/**\n * 从内容检测行尾符\n */\nfunction detectLineEndings(content: string): LineEndingType {\n const sample = content.slice(0, 4096);\n return sample.includes('\\r\\n') ? 'CRLF' : 'LF';\n}\n\n/**\n * 写入文件时保留行尾符。\n * 如果目标文件使用 CRLF,将 content 中的 LF 转换为 CRLF。\n */\nfunction writeTextContent(\n filePath: string,\n content: string,\n encoding: FileEncoding = 'utf8',\n lineEndings: LineEndingType = 'LF',\n): Promise<void> {\n let toWrite = content;\n if (lineEndings === 'CRLF') {\n toWrite = content.replaceAll('\\r\\n', '\\n').split('\\n').join('\\r\\n');\n }\n return writeFile(filePath, toWrite, encoding);\n}\n\n// ============================================================================\n// 引号标准化(curly quotes ↔ straight quotes)\n// 参考 Claude Code 的 findActualString / normalizeQuotes\n// ============================================================================\n\nconst CURLY_QUOTES: Array<[string, string]> = [\n ['\\u2018', \"'\"], // LEFT SINGLE\n ['\\u2019', \"'\"], // RIGHT SINGLE\n ['\\u201C', '\"'], // LEFT DOUBLE\n ['\\u201D', '\"'], // RIGHT DOUBLE\n];\n\nfunction normalizeQuotes(str: string): string {\n let result = str;\n for (const [curly, straight] of CURLY_QUOTES) {\n result = result.replaceAll(curly, straight);\n }\n return result;\n}\n\n/**\n * 在文件内容中查找匹配字符串。\n * 先精确匹配,失败后做引号标准化再匹配。\n * 返回文件中实际存在的字符串(可能带 curly quotes),或 null。\n */\nfunction findActualString(fileContent: string, searchString: string): string | null {\n if (fileContent.includes(searchString)) {\n return searchString;\n }\n\n const normalizedSearch = normalizeQuotes(searchString);\n const normalizedFile = normalizeQuotes(fileContent);\n const index = normalizedFile.indexOf(normalizedSearch);\n if (index !== -1) {\n return fileContent.substring(index, index + searchString.length);\n }\n\n return null;\n}\n\n// ============================================================================\n// Read Tool - 文件读取\n// ============================================================================\n\n/**\n * 检测是否为二进制文件\n */\nasync function isBinaryFile(filepath: string): Promise<boolean> {\n const ext = path.extname(filepath).toLowerCase();\n\n const binaryExts = [\n '.zip', '.tar', '.gz', '.exe', '.dll', '.so', '.class', '.jar', '.war',\n '.7z', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.odt',\n '.ods', '.odp', '.bin', '.dat', '.obj', '.o', '.a', '.lib', '.wasm',\n '.pyc', '.pyo'\n ];\n\n if (binaryExts.includes(ext)) {\n return true;\n }\n\n try {\n const content = await readFile(filepath, { encoding: null });\n if (content.length === 0) return false;\n\n const bufferSize = Math.min(4096, content.length);\n const bytes = content.subarray(0, bufferSize);\n\n let nonPrintableCount = 0;\n for (let i = 0; i < bytes.length; i++) {\n if (bytes[i] === 0) return true;\n if (bytes[i] < 9 || (bytes[i] > 13 && bytes[i] < 32)) {\n nonPrintableCount++;\n }\n }\n\n return nonPrintableCount / bytes.length > 0.3;\n } catch {\n return false;\n }\n}\n\n/**\n * 文件读取工具\n */\nexport function createReadTool(workspaceDir: string = DEFAULT_WORKSPACE_DIR) {\n return createTool({\n name: 'read',\n description: 'Read a file from the local filesystem. Can read files with offset/limit for pagination, and can also read directory contents. For large files, use offset and limit parameters to read in chunks.',\n render: 'read',\n parallelizable: true,\n parameters: {\n type: 'object',\n properties: {\n filePath: {\n type: 'string',\n description: 'The absolute path to the file or directory to read'\n },\n offset: {\n type: 'number',\n description: 'The line number to start reading from (1-indexed, defaults to 1)'\n },\n limit: {\n type: 'number',\n description: 'The maximum number of lines to read (defaults to 2000)'\n }\n },\n additionalProperties: false,\n required: ['filePath']\n },\n execute: async (args = {}) => {\n const filePath = normalizeNamedPathArg(args, 'filePath', 'filepath', 'path');\n const offsetParam = typeof (args as Record<string, unknown>).offset === 'number'\n ? (args as Record<string, unknown>).offset as number\n : undefined;\n const limitParam = typeof (args as Record<string, unknown>).limit === 'number'\n ? (args as Record<string, unknown>).limit as number\n : undefined;\n const resolvedFilePath = resolveWorkspacePath(filePath, workspaceDir);\n console.log(`[read] ${resolvedFilePath}`);\n\n if (offsetParam !== undefined && offsetParam < 1) {\n throw new Error('offset must be greater than or equal to 1');\n }\n\n // 设备文件阻断 — 防止进程挂死\n if (isBlockedDevicePath(resolvedFilePath)) {\n throw new Error(`Cannot read '${filePath}': this device file would block or produce infinite output.`);\n }\n\n const stats = await stat(resolvedFilePath).catch(() => null);\n if (!stats) {\n throw new Error(`File not found: ${resolvedFilePath}`);\n }\n\n // 处理目录\n if (stats.isDirectory()) {\n const dirents = await readdir(resolvedFilePath, { withFileTypes: true });\n const entries: string[] = [];\n\n for (const dirent of dirents) {\n if (dirent.isDirectory()) {\n entries.push(dirent.name + path.sep);\n } else if (dirent.isSymbolicLink()) {\n try {\n const targetStats = await stat(path.join(resolvedFilePath, dirent.name));\n entries.push(targetStats.isDirectory() ? dirent.name + path.sep : dirent.name);\n } catch {\n entries.push(dirent.name);\n }\n } else {\n entries.push(dirent.name);\n }\n }\n\n entries.sort((a, b) => a.localeCompare(b));\n\n const limit = limitParam ?? DEFAULT_READ_LIMIT;\n const offset = offsetParam ?? 1;\n const start = offset - 1;\n const sliced = entries.slice(start, start + limit);\n const truncated = start + sliced.length < entries.length;\n\n return {\n type: 'directory',\n path: resolvedFilePath,\n totalEntries: entries.length,\n offset,\n limit,\n truncated,\n entries: sliced\n };\n }\n\n // 处理文件\n const isBinary = await isBinaryFile(resolvedFilePath);\n if (isBinary) {\n throw new Error(`Cannot read binary file: ${resolvedFilePath}`);\n }\n\n const content = await readFile(resolvedFilePath, 'utf-8');\n const lines = content.split('\\n');\n\n const limit = limitParam ?? DEFAULT_READ_LIMIT;\n const offset = offsetParam ?? 1;\n const start = offset - 1;\n\n if (start >= lines.length) {\n throw new Error(`Offset ${offset} is out of range for this file (${lines.length} lines)`);\n }\n\n // 读取并处理行\n const raw: string[] = [];\n let bytes = 0;\n let truncatedByBytes = false;\n\n for (let i = start; i < Math.min(lines.length, start + limit); i++) {\n const line = lines[i].length > MAX_LINE_LENGTH\n ? lines[i].substring(0, MAX_LINE_LENGTH) + '...'\n : lines[i];\n const size = Buffer.byteLength(line, 'utf-8') + (raw.length > 0 ? 1 : 0);\n\n if (bytes + size > MAX_BYTES) {\n truncatedByBytes = true;\n break;\n }\n\n raw.push(line);\n bytes += size;\n }\n\n // 生成带行号的输出\n const contentWithLines = raw.map((line, index) => {\n return `${index + offset}: ${line}`;\n });\n\n const totalLines = lines.length;\n const lastReadLine = offset + raw.length - 1;\n const hasMoreLines = totalLines > lastReadLine;\n const truncated = hasMoreLines || truncatedByBytes;\n\n // 更新去重状态\n try {\n const mtimeMs = (await stat(resolvedFilePath)).mtimeMs;\n readDedupState.set(resolvedFilePath, { mtimeMs, offset, limit: limitParam });\n } catch {\n // stat 失败,跳过去重状态更新\n }\n\n return {\n type: 'file',\n path: resolvedFilePath,\n totalLines,\n offset,\n limit,\n truncated,\n truncatedByBytes,\n lastReadLine,\n content: contentWithLines.join('\\n')\n };\n }\n });\n}\n\nexport const readTool = createReadTool();\n\n// ============================================================================\n// Write Tool - 文件写入\n// ============================================================================\n\n/**\n * 文件写入工具\n */\nexport function createWriteTool(workspaceDir: string = DEFAULT_WORKSPACE_DIR) {\n return createTool({\n name: 'write',\n description: 'Write content to a file. Creates new files or overwrites existing files. THIS TOOL WILL OVERWRITE THE EXISTING FILE IF it exists. Only use this tool when explicitly requested to do so. Always prefer editing existing files using the edit tool when the file already exists.',\n render: 'write',\n parameters: {\n type: 'object',\n properties: {\n filePath: {\n type: 'string',\n description: 'The absolute path to the file to write'\n },\n content: {\n type: 'string',\n description: 'The content to write to the file'\n }\n },\n additionalProperties: false,\n required: ['filePath', 'content']\n },\n execute: async (args = {}) => {\n const filePath = normalizeNamedPathArg(args, 'filePath', 'filepath', 'path');\n const content = (args as Record<string, unknown>).content as string;\n const resolvedFilePath = resolveWorkspacePath(filePath, workspaceDir);\n console.log(`[write] ${resolvedFilePath}`);\n\n // 检测现有文件的编码\n let encoding: FileEncoding = 'utf8';\n const exists = await stat(resolvedFilePath).then(() => true).catch(() => false);\n let contentOld = '';\n if (exists) {\n // Read-before-write 校验:必须先读才能写\n const dedupEntry = readDedupState.get(resolvedFilePath);\n if (!dedupEntry) {\n throw new Error(\n `File has not been read yet. Read it first before writing to it: ${resolvedFilePath}`\n );\n }\n // Staleness 校验:文件在上次读取后被外部修改则拒绝写入\n const currentMtime = (await stat(resolvedFilePath)).mtimeMs;\n if (currentMtime !== dedupEntry.mtimeMs) {\n throw new Error(\n `File has been modified since last read. Read the file again before writing to it: ${resolvedFilePath}`\n );\n }\n\n const buffer = await readFile(resolvedFilePath, { encoding: null });\n encoding = detectEncoding(buffer);\n const rawContent = buffer.toString(encoding);\n contentOld = rawContent.replaceAll('\\r\\n', '\\n');\n }\n\n // 生成 diff\n const diff = createTwoFilesPatch(resolvedFilePath, resolvedFilePath, contentOld, content);\n\n // 确保父目录存在\n const dir = path.dirname(resolvedFilePath);\n await mkdir(dir, { recursive: true });\n\n // 写入文件(保留编码,强制 LF 行尾符以避免跨平台损坏)\n await writeTextContent(resolvedFilePath, content, encoding, 'LF');\n\n // 更新 read 去重状态(offset=undefined 表示由 Write 设置,非 Read 产生)\n try {\n const mtimeMs = (await stat(resolvedFilePath)).mtimeMs;\n readDedupState.set(resolvedFilePath, { mtimeMs, offset: undefined, limit: undefined });\n } catch {\n // ignore\n }\n\n return withDisplay(\n JSON.stringify({\n filePath: resolvedFilePath,\n existed: exists,\n lines: content.split('\\n').length,\n message: `File ${exists ? 'updated' : 'created'} successfully`,\n }),\n { filePath: resolvedFilePath, existed: exists, diff }\n );\n }\n });\n}\n\nexport const writeTool = createWriteTool();\n\n// ============================================================================\n// Edit Tool - 文件编辑\n// ============================================================================\n\n/**\n * Levenshtein 距离算法\n */\nfunction levenshtein(a: string, b: string): number {\n if (a === '' || b === '') {\n return Math.max(a.length, b.length);\n }\n\n const matrix = Array.from({ length: a.length + 1 }, (_, i) =>\n Array.from({ length: b.length + 1 }, (_, j) => (i === 0 ? j : j === 0 ? i : 0))\n );\n\n for (let i = 1; i <= a.length; i++) {\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n matrix[i][j] = Math.min(\n matrix[i - 1][j] + 1,\n matrix[i][j - 1] + 1,\n matrix[i - 1][j - 1] + cost\n );\n }\n }\n\n return matrix[a.length][b.length];\n}\n\n/**\n * Replacer 类型\n */\ntype Replacer = (content: string, find: string) => Generator<string, void, unknown>;\n\n/**\n * 带名称的 Replacer 条目\n */\ninterface ReplacerEntry {\n name: string;\n fn: Replacer;\n}\n\n/**\n * 精确匹配替换器\n */\nconst simpleReplacer: Replacer = function* (_content, find) {\n yield find;\n};\n\n/**\n * 行修剪匹配替换器\n */\nconst lineTrimmedReplacer: Replacer = function* (content, find) {\n const originalLines = content.split('\\n');\n const searchLines = find.split('\\n');\n\n if (searchLines[searchLines.length - 1] === '') {\n searchLines.pop();\n }\n\n for (let i = 0; i <= originalLines.length - searchLines.length; i++) {\n let matches = true;\n\n for (let j = 0; j < searchLines.length; j++) {\n if (originalLines[i + j].trim() !== searchLines[j].trim()) {\n matches = false;\n break;\n }\n }\n\n if (matches) {\n let matchStartIndex = 0;\n for (let k = 0; k < i; k++) {\n matchStartIndex += originalLines[k].length + 1;\n }\n\n let matchEndIndex = matchStartIndex;\n for (let k = 0; k < searchLines.length; k++) {\n matchEndIndex += originalLines[i + k].length;\n if (k < searchLines.length - 1) {\n matchEndIndex += 1;\n }\n }\n\n yield content.substring(matchStartIndex, matchEndIndex);\n }\n }\n};\n\n/**\n * 块锚点匹配替换器(基于首尾行匹配)\n */\nconst blockAnchorReplacer: Replacer = function* (content, find) {\n const originalLines = content.split('\\n');\n const searchLines = find.split('\\n');\n\n if (searchLines.length < 3) return;\n\n if (searchLines[searchLines.length - 1] === '') {\n searchLines.pop();\n }\n\n const firstLineSearch = searchLines[0].trim();\n const lastLineSearch = searchLines[searchLines.length - 1].trim();\n\n const candidates: Array<{ startLine: number; endLine: number }> = [];\n for (let i = 0; i < originalLines.length; i++) {\n if (originalLines[i].trim() !== firstLineSearch) continue;\n\n for (let j = i + 2; j < originalLines.length; j++) {\n if (originalLines[j].trim() === lastLineSearch) {\n candidates.push({ startLine: i, endLine: j });\n break;\n }\n }\n }\n\n if (candidates.length === 0) return;\n\n const SINGLE_CANDIDATE_THRESHOLD = 0.0;\n const MULTIPLE_CANDIDATES_THRESHOLD = 0.3;\n\n if (candidates.length === 1) {\n const { startLine, endLine } = candidates[0];\n const searchBlockSize = searchLines.length;\n const actualBlockSize = endLine - startLine + 1;\n\n let similarity = 0;\n const linesToCheck = Math.min(searchBlockSize - 2, actualBlockSize - 2);\n\n if (linesToCheck > 0) {\n for (let j = 1; j < searchBlockSize - 1 && j < actualBlockSize - 1; j++) {\n const originalLine = originalLines[startLine + j].trim();\n const searchLine = searchLines[j].trim();\n const maxLen = Math.max(originalLine.length, searchLine.length);\n if (maxLen === 0) continue;\n const distance = levenshtein(originalLine, searchLine);\n similarity += (1 - distance / maxLen) / linesToCheck;\n if (similarity >= SINGLE_CANDIDATE_THRESHOLD) break;\n }\n } else {\n similarity = 1.0;\n }\n\n if (similarity >= SINGLE_CANDIDATE_THRESHOLD) {\n let matchStartIndex = 0;\n for (let k = 0; k < startLine; k++) {\n matchStartIndex += originalLines[k].length + 1;\n }\n let matchEndIndex = matchStartIndex;\n for (let k = startLine; k <= endLine; k++) {\n matchEndIndex += originalLines[k].length;\n if (k < endLine) matchEndIndex += 1;\n }\n yield content.substring(matchStartIndex, matchEndIndex);\n }\n return;\n }\n\n // 多个候选,找最佳匹配\n let bestMatch: { startLine: number; endLine: number } | null = null;\n let maxSimilarity = -1;\n\n for (const candidate of candidates) {\n const { startLine, endLine } = candidate;\n const searchBlockSize = searchLines.length;\n const actualBlockSize = endLine - startLine + 1;\n\n let similarity = 0;\n const linesToCheck = Math.min(searchBlockSize - 2, actualBlockSize - 2);\n\n if (linesToCheck > 0) {\n for (let j = 1; j < searchBlockSize - 1 && j < actualBlockSize - 1; j++) {\n const originalLine = originalLines[startLine + j].trim();\n const searchLine = searchLines[j].trim();\n const maxLen = Math.max(originalLine.length, searchLine.length);\n if (maxLen === 0) continue;\n const distance = levenshtein(originalLine, searchLine);\n similarity += 1 - distance / maxLen;\n }\n similarity /= linesToCheck;\n } else {\n similarity = 1.0;\n }\n\n if (similarity > maxSimilarity) {\n maxSimilarity = similarity;\n bestMatch = candidate;\n }\n }\n\n if (maxSimilarity >= MULTIPLE_CANDIDATES_THRESHOLD && bestMatch) {\n const { startLine, endLine } = bestMatch;\n let matchStartIndex = 0;\n for (let k = 0; k < startLine; k++) {\n matchStartIndex += originalLines[k].length + 1;\n }\n let matchEndIndex = matchStartIndex;\n for (let k = startLine; k <= endLine; k++) {\n matchEndIndex += originalLines[k].length;\n if (k < endLine) matchEndIndex += 1;\n }\n yield content.substring(matchStartIndex, matchEndIndex);\n }\n};\n\n/**\n * 空白标准化替换器\n */\nconst whitespaceNormalizedReplacer: Replacer = function* (content, find) {\n const normalizeWhitespace = (text: string) => text.replace(/\\s+/g, ' ').trim();\n const normalizedFind = normalizeWhitespace(find);\n\n const lines = content.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n if (normalizeWhitespace(lines[i]) === normalizedFind) {\n yield lines[i];\n }\n }\n\n const findLines = find.split('\\n');\n if (findLines.length > 1) {\n for (let i = 0; i <= lines.length - findLines.length; i++) {\n const block = lines.slice(i, i + findLines.length).join('\\n');\n if (normalizeWhitespace(block) === normalizedFind) {\n yield block;\n }\n }\n }\n};\n\n/**\n * 缩进灵活替换器\n */\nconst indentationFlexibleReplacer: Replacer = function* (content, find) {\n const removeIndentation = (text: string) => {\n const lines = text.split('\\n');\n const nonEmptyLines = lines.filter((line) => line.trim().length > 0);\n if (nonEmptyLines.length === 0) return text;\n\n const minIndent = Math.min(\n ...nonEmptyLines.map((line) => {\n const match = line.match(/^(\\s*)/);\n return match ? match[1].length : 0;\n })\n );\n\n return lines.map((line) => (line.trim().length === 0 ? line : line.slice(minIndent))).join('\\n');\n };\n\n const normalizedFind = removeIndentation(find);\n const contentLines = content.split('\\n');\n const findLines = find.split('\\n');\n\n for (let i = 0; i <= contentLines.length - findLines.length; i++) {\n const block = contentLines.slice(i, i + findLines.length).join('\\n');\n if (removeIndentation(block) === normalizedFind) {\n yield block;\n }\n }\n};\n\n/**\n * 转义符标准化替换器\n */\nconst escapeNormalizedReplacer: Replacer = function* (content, find) {\n const unescapeString = (str: string): string => {\n return str.replace(/\\\\(n|t|r|'|\"|`|\\\\|\\n|\\$)/g, (_, capturedChar) => {\n switch (capturedChar) {\n case 'n': return '\\n';\n case 't': return '\\t';\n case 'r': return '\\r';\n case \"'\": return \"'\";\n case '\"': return '\"';\n case '`': return '`';\n case '\\\\': return '\\\\';\n case '\\n': return '\\n';\n case '$': return '$';\n default: return _;\n }\n });\n };\n\n const unescapedFind = unescapeString(find);\n\n if (content.includes(unescapedFind)) {\n yield unescapedFind;\n }\n\n const lines = content.split('\\n');\n const findLines = unescapedFind.split('\\n');\n\n for (let i = 0; i <= lines.length - findLines.length; i++) {\n const block = lines.slice(i, i + findLines.length).join('\\n');\n if (unescapeString(block) === unescapedFind) {\n yield block;\n }\n }\n};\n\n/**\n * 边界修剪替换器\n */\nconst trimmedBoundaryReplacer: Replacer = function* (content, find) {\n const trimmedFind = find.trim();\n\n if (trimmedFind === find) return;\n\n if (content.includes(trimmedFind)) {\n yield trimmedFind;\n }\n\n const lines = content.split('\\n');\n const findLines = find.split('\\n');\n\n for (let i = 0; i <= lines.length - findLines.length; i++) {\n const block = lines.slice(i, i + findLines.length).join('\\n');\n if (block.trim() === trimmedFind) {\n yield block;\n }\n }\n};\n\n/**\n * 上下文感知替换器\n */\nconst contextAwareReplacer: Replacer = function* (content, find) {\n const findLines = find.split('\\n');\n if (findLines.length < 3) return;\n\n if (findLines[findLines.length - 1] === '') {\n findLines.pop();\n }\n\n const contentLines = content.split('\\n');\n const firstLine = findLines[0].trim();\n const lastLine = findLines[findLines.length - 1].trim();\n\n for (let i = 0; i < contentLines.length; i++) {\n if (contentLines[i].trim() !== firstLine) continue;\n\n for (let j = i + 2; j < contentLines.length; j++) {\n if (contentLines[j].trim() === lastLine) {\n const blockLines = contentLines.slice(i, j + 1);\n\n if (blockLines.length === findLines.length) {\n let matchingLines = 0;\n let totalNonEmptyLines = 0;\n\n for (let k = 1; k < blockLines.length - 1; k++) {\n const blockLine = blockLines[k].trim();\n const findLine = findLines[k].trim();\n\n if (blockLine.length > 0 || findLine.length > 0) {\n totalNonEmptyLines++;\n if (blockLine === findLine) {\n matchingLines++;\n }\n }\n }\n\n if (totalNonEmptyLines === 0 || matchingLines / totalNonEmptyLines >= 0.5) {\n yield blockLines.join('\\n');\n break;\n }\n }\n break;\n }\n }\n }\n};\n\n/**\n * 多次出现替换器\n */\nconst multiOccurrenceReplacer: Replacer = function* (content, find) {\n let startIndex = 0;\n\n while (true) {\n const index = content.indexOf(find, startIndex);\n if (index === -1) break;\n\n yield find;\n startIndex = index + find.length;\n }\n};\n\n/**\n * 所有替换器列表(按精确度从高到低排序)\n */\nconst REPLACERS: ReplacerEntry[] = [\n { name: 'simpleReplacer', fn: simpleReplacer },\n { name: 'lineTrimmedReplacer', fn: lineTrimmedReplacer },\n { name: 'blockAnchorReplacer', fn: blockAnchorReplacer },\n { name: 'whitespaceNormalizedReplacer', fn: whitespaceNormalizedReplacer },\n { name: 'indentationFlexibleReplacer', fn: indentationFlexibleReplacer },\n { name: 'escapeNormalizedReplacer', fn: escapeNormalizedReplacer },\n { name: 'trimmedBoundaryReplacer', fn: trimmedBoundaryReplacer },\n { name: 'contextAwareReplacer', fn: contextAwareReplacer },\n { name: 'multiOccurrenceReplacer', fn: multiOccurrenceReplacer },\n];\n\n/**\n * replace() 的返回结果\n */\ninterface ReplaceResult {\n content: string;\n /** 命中的替换器名称 */\n matchedReplacer: string;\n /** 文件中实际匹配到的字符串(可能与 oldString 缩进/空白不同) */\n actualMatchedString: string;\n}\n\n/**\n * 执行替换\n */\nfunction replace(content: string, oldString: string, newString: string, replaceAll = false): ReplaceResult {\n if (oldString === newString) {\n throw new Error('No changes to apply: oldString and newString are identical.');\n }\n\n let notFound = true;\n\n for (const { name, fn: replacer } of REPLACERS) {\n for (const search of replacer(content, oldString)) {\n const index = content.indexOf(search);\n if (index === -1) continue;\n\n notFound = false;\n\n if (replaceAll) {\n return {\n content: content.replaceAll(search, newString),\n matchedReplacer: name,\n actualMatchedString: search,\n };\n }\n\n const lastIndex = content.lastIndexOf(search);\n if (index !== lastIndex) continue;\n\n return {\n content: content.substring(0, index) + newString + content.substring(index + search.length),\n matchedReplacer: name,\n actualMatchedString: search,\n };\n }\n }\n\n if (notFound) {\n throw new Error(\n 'Could not find oldString in the file. It must match exactly, including whitespace, indentation, and line endings.'\n );\n }\n\n throw new Error('Found multiple matches for oldString. Provide more surrounding context to make the match unique.');\n}\n\n/**\n * 文件编辑工具\n */\nexport function createEditTool(workspaceDir: string = DEFAULT_WORKSPACE_DIR) {\n return createTool({\n name: 'edit',\n description: 'Make exact string replacements in a file. Uses multiple intelligent matching strategies including block anchor matching, whitespace normalization, and indentation flexibility. Always provides a diff preview of changes.',\n render: 'edit',\n parameters: {\n type: 'object',\n properties: {\n filePath: {\n type: 'string',\n description: 'The absolute path to the file to modify'\n },\n oldString: {\n type: 'string',\n description: 'The text to replace'\n },\n newString: {\n type: 'string',\n description: 'The text to replace it with (must be different from oldString)'\n },\n replaceAll: {\n type: 'boolean',\n default: false,\n description: 'Replace all occurrences of oldString (default false)'\n }\n },\n additionalProperties: false,\n required: ['filePath', 'oldString', 'newString']\n },\n execute: async (args = {}) => {\n const filePath = normalizeNamedPathArg(args, 'filePath', 'filepath', 'path');\n const oldString = (args as Record<string, unknown>).oldString as string;\n const newString = (args as Record<string, unknown>).newString as string;\n const replaceAll = (args as Record<string, unknown>).replaceAll as boolean | undefined;\n const resolvedFilePath = resolveWorkspacePath(filePath, workspaceDir);\n console.log(`[edit] ${resolvedFilePath}`);\n\n if (oldString === newString) {\n throw new Error('No changes to apply: oldString and newString are identical.');\n }\n\n // 检查文件是否存在\n const exists = await stat(resolvedFilePath).then(() => true).catch(() => false);\n if (!exists) {\n throw new Error(`File not found: ${resolvedFilePath}`);\n }\n\n // Read-before-write 校验:必须先读才能编辑\n const dedupEntry = readDedupState.get(resolvedFilePath);\n if (!dedupEntry) {\n throw new Error(\n `File has not been read yet. Read it first before editing it: ${resolvedFilePath}`\n );\n }\n // Staleness 校验:文件在上次读取后被外部修改则拒绝编辑\n const currentMtime = (await stat(resolvedFilePath)).mtimeMs;\n if (currentMtime !== dedupEntry.mtimeMs) {\n throw new Error(\n `File has been modified since last read. Read the file again before editing it: ${resolvedFilePath}`\n );\n }\n\n // 读取文件,检测编码和行尾符\n const buffer = await readFile(resolvedFilePath, { encoding: null });\n const encoding = detectEncoding(buffer);\n const lineEndings = detectLineEndings(buffer.toString(encoding));\n const contentOld = buffer.toString(encoding).replaceAll('\\r\\n', '\\n');\n\n // 引号标准化:尝试将 oldString 匹配到文件中的实际字符串(可能含 curly quotes)\n const actualOldString = findActualString(contentOld, oldString);\n const effectiveOldString = actualOldString ?? oldString;\n\n const replaceResult = replace(contentOld, effectiveOldString, newString, replaceAll);\n const contentNew = replaceResult.content;\n\n // 当使用了非精确匹配(模糊匹配器)时,生成警告信息\n let warning: string | undefined;\n if (replaceResult.matchedReplacer !== 'simpleReplacer') {\n const actualLines = replaceResult.actualMatchedString.split('\\n');\n const providedLines = effectiveOldString.split('\\n');\n\n // 检测是否为纯缩进差异\n let indentOnly = true;\n if (actualLines.length === providedLines.length) {\n for (let i = 0; i < actualLines.length; i++) {\n if (actualLines[i].trim() !== providedLines[i].trim()) {\n indentOnly = false;\n break;\n }\n }\n } else {\n indentOnly = false;\n }\n\n const diffType = indentOnly ? 'indentation/whitespace' : 'content formatting';\n warning =\n `Edit applied via fuzzy matching (${replaceResult.matchedReplacer}). ` +\n `The oldString did not exactly match the file content — ${diffType} differs. ` +\n `The newString was written as-is, which may produce incorrect indentation or formatting. ` +\n `Please re-read the file to verify the result is correct.`;\n }\n\n // 生成 diff\n const diff = createTwoFilesPatch(resolvedFilePath, resolvedFilePath, contentOld, contentNew);\n\n // 计算变更统计\n let additions = 0;\n let deletions = 0;\n for (const change of diffLines(contentOld, contentNew)) {\n if (change.added) additions += change.count || 0;\n if (change.removed) deletions += change.count || 0;\n }\n\n // 写入文件(保留编码和行尾符)\n await writeTextContent(resolvedFilePath, contentNew, encoding, lineEndings);\n\n // 更新 read 去重状态(offset=undefined 表示由 Edit 设置,非 Read 产生)\n try {\n const mtimeMs = (await stat(resolvedFilePath)).mtimeMs;\n readDedupState.set(resolvedFilePath, { mtimeMs, offset: undefined, limit: undefined });\n } catch {\n // ignore\n }\n\n return withDisplay(\n JSON.stringify({\n filePath: resolvedFilePath,\n additions,\n deletions,\n message: warning ?? 'Edit applied successfully',\n ...(warning && { warning }),\n }),\n { filePath: resolvedFilePath, diff, additions, deletions }\n );\n }\n });\n}\n\nexport const editTool = createEditTool();\n\n// ============================================================================\n// LS Tool - 目录列表\n// ============================================================================\n\n/**\n * 目录列表工具\n */\nexport function createLsTool(workspaceDir: string = DEFAULT_WORKSPACE_DIR) {\n return createTool({\n name: 'ls',\n description: 'List files in a directory with tree structure output. Automatically ignores common build/cache directories.',\n render: 'ls',\n parallelizable: true,\n parameters: {\n type: 'object',\n properties: {\n dirPath: {\n type: 'string',\n description: 'The absolute path to the directory to list'\n },\n ignore: {\n type: 'array',\n items: { type: 'string' },\n description: 'List of glob patterns to ignore'\n }\n },\n additionalProperties: false,\n required: ['dirPath']\n },\n execute: async (args = {}) => {\n const dirPath = normalizeNamedPathArg(args, 'dirPath', 'dirpath', 'path', 'filePath', 'filepath');\n const ignore = ((args as Record<string, unknown>).ignore as string[]) ?? [];\n const resolvedDirPath = resolveWorkspacePath(dirPath, workspaceDir);\n console.log(`[ls] ${resolvedDirPath}`);\n\n const ignoreGlobs = [...IGNORE_PATTERNS, ...ignore.map((p: string) => `${p}/**`)];\n\n // glob 返回 Promise<string[]>,不是异步迭代器\n const matches = await glob('**/*', {\n cwd: resolvedDirPath,\n absolute: false,\n dot: true,\n ignore: ignoreGlobs,\n nodir: true\n });\n\n const files: string[] = [];\n for (const file of matches) {\n files.push(file);\n if (files.length >= LS_LIMIT) break;\n }\n\n // 构建目录结构\n const dirs = new Set<string>();\n const filesByDir = new Map<string, string[]>();\n\n for (const file of files) {\n const dir = path.dirname(file);\n const parts = dir === '.' ? [] : dir.split(path.sep);\n\n // 添加所有父目录\n for (let i = 0; i <= parts.length; i++) {\n const dirPath = i === 0 ? '.' : parts.slice(0, i).join(path.sep);\n dirs.add(dirPath);\n }\n\n // 将文件添加到其目录\n if (!filesByDir.has(dir)) {\n filesByDir.set(dir, []);\n }\n filesByDir.get(dir)!.push(path.basename(file));\n }\n\n // 渲染目录树\n function renderDir(dirPath: string, depth: number): string {\n const indent = ' '.repeat(depth);\n let output = '';\n\n if (depth > 0) {\n output += `${indent}${path.basename(dirPath)}/\\n`;\n }\n\n const children = Array.from(dirs)\n .filter((d) => path.dirname(d) === dirPath && d !== dirPath)\n .sort();\n\n // 先渲染子目录\n for (const child of children) {\n output += renderDir(child, depth + 1);\n }\n\n // 渲染文件\n const dirFiles = filesByDir.get(dirPath) || [];\n for (const file of dirFiles.sort()) {\n output += `${' '.repeat(depth + 1)}${file}\\n`;\n }\n\n return output;\n }\n\n const treeOutput = `${resolvedDirPath}${path.sep}\\n${renderDir('.', 0)}`;\n\n return {\n path: resolvedDirPath,\n count: files.length,\n truncated: files.length >= LS_LIMIT,\n tree: treeOutput\n };\n }\n });\n}\n\nexport const lsTool = createLsTool();\n\n// ============================================================================\n// Glob Tool - 文件模式搜索\n// ============================================================================\n\n/**\n * Glob 文件搜索工具\n */\nexport function createGlobTool(workspaceDir: string = DEFAULT_WORKSPACE_DIR) {\n return createTool({\n name: 'glob',\n description: 'Fast file pattern matching tool that works with any codebase size. Supports glob patterns like \"**/*.js\" or \"src/**/*.ts\". Returns matching file paths sorted by modification time.',\n render: 'glob',\n parallelizable: true,\n parameters: {\n type: 'object',\n properties: {\n pattern: {\n type: 'string',\n description: 'The glob pattern to match files against'\n },\n searchPath: {\n type: 'string',\n description: 'The directory to search in (defaults to current working directory)'\n }\n },\n additionalProperties: false,\n required: ['pattern']\n },\n execute: async (args = {}) => {\n const pattern = (args as Record<string, unknown>).pattern as string;\n const searchPath = tryNamedPathArg(args, 'searchPath', 'searchpath', 'path', 'filePath', 'filepath');\n const resolvedSearchPath = resolveWorkspaceSearchPath(searchPath, workspaceDir);\n console.log(`[glob] ${pattern} in ${resolvedSearchPath}`);\n\n const files: Array<{ path: string; mtime: number }> = [];\n\n // 使用 glob 进行文件搜索\n const matches = await glob(pattern, {\n cwd: resolvedSearchPath,\n absolute: true,\n windowsPathsNoEscape: true,\n nodir: true,\n });\n\n for (const file of matches) {\n if (files.length >= SEARCH_LIMIT) break;\n\n try {\n const stats = await stat(file);\n files.push({\n path: file,\n mtime: stats.mtimeMs\n });\n } catch {\n // File may have been deleted, skip\n }\n }\n\n // 按修改时间排序\n files.sort((a, b) => b.mtime - a.mtime);\n\n return {\n count: files.length,\n truncated: files.length >= SEARCH_LIMIT,\n files: files.map(f => f.path)\n };\n }\n });\n}\n\nexport const globTool = createGlobTool();\n\n// ============================================================================\n// Grep Tool - 内容搜索\n// ============================================================================\n\n/**\n * 获取 ripgrep 路径\n */\nasync function getRipgrepPath(): Promise<string> {\n return new Promise((resolve, reject) => {\n const child = spawn('rg', ['--version'], { windowsHide: true });\n let hasOutput = false;\n\n child.stdout.on('data', () => { hasOutput = true; });\n child.stderr.on('data', () => { hasOutput = true; });\n\n child.on('close', (code) => {\n if (hasOutput || code === 0) {\n resolve('rg');\n } else {\n reject(new Error('ripgrep (rg) is not installed. Please install it from https://github.com/BurntSushi/ripgrep'));\n }\n });\n\n child.on('error', () => {\n reject(new Error('ripgrep (rg) is not installed. Please install it from https://github.com/BurntSushi/ripgrep'));\n });\n });\n}\n\n/**\n * Grep 内容搜索工具\n */\nexport function createGrepTool(workspaceDir: string = DEFAULT_WORKSPACE_DIR) {\n return createTool({\n name: 'grep',\n description: 'A powerful search tool built on ripgrep. Supports full regex syntax, file type filtering, and context control. Use this tool for content searches; NEVER invoke grep or rg as Bash commands.',\n render: 'grep',\n parallelizable: true,\n parameters: {\n type: 'object',\n properties: {\n pattern: {\n type: 'string',\n description: 'The regex pattern to search for in file contents'\n },\n searchPath: {\n type: 'string',\n description: 'The directory to search in (defaults to current working directory)'\n },\n include: {\n type: 'string',\n description: 'File pattern to include in the search (e.g. \"*.js\", \"*.{ts,tsx}\")'\n }\n },\n additionalProperties: false,\n required: ['pattern']\n },\n execute: async (args = {}, context) => {\n const pattern = (args as Record<string, unknown>).pattern as string;\n const searchPath = tryNamedPathArg(args, 'searchPath', 'searchpath', 'path', 'filePath', 'filepath');\n const include = (args as Record<string, unknown>).include as string | undefined;\n const resolvedSearchPath = resolveWorkspaceSearchPath(searchPath, workspaceDir);\n console.log(`[grep] ${pattern} in ${resolvedSearchPath}`);\n\n const rgPath = await getRipgrepPath();\n const rgArgs = ['-nH', '--hidden', '--no-messages', '--field-match-separator=|', '--regexp', pattern];\n\n if (include) {\n rgArgs.push('--glob', include);\n }\n rgArgs.push(resolvedSearchPath);\n\n try {\n // 使用 spawn 避免在 Windows 上 shell 解析特殊字符(如 |)的问题\n const stdout = await new Promise<string>((resolve, reject) => {\n const chunks: Buffer[] = [];\n const child = spawn(rgPath, rgArgs, {\n windowsHide: true\n });\n\n child.stdout.on('data', (chunk) => chunks.push(chunk));\n child.stderr.on('data', (chunk) => {\n // ripgrep 将匹配结果输出到 stdout,错误信息到 stderr\n });\n\n // 支持取消\n const onSearchAbort = () => child.kill();\n if (context?.signal) {\n context.signal.addEventListener('abort', onSearchAbort, { once: true });\n }\n\n child.on('error', (err) => {\n context?.signal?.removeEventListener('abort', onSearchAbort);\n reject(err);\n });\n child.on('close', (code) => {\n context?.signal?.removeEventListener('abort', onSearchAbort);\n if (context?.signal?.aborted) {\n return reject(new Error('Search was aborted'));\n }\n // code 1 表示没有匹配,不是错误\n if (code !== 0 && code !== 1) {\n return reject(new Error(`rg exited with code ${code}`));\n }\n resolve(Buffer.concat(chunks).toString('utf-8'));\n });\n });\n\n const lines = stdout.trim().split(/\\r?\\n/);\n const matches: Array<{ path: string; lineNum: number; lineText: string }> = [];\n\n for (const line of lines) {\n if (!line) continue;\n\n const parts = line.split('|');\n if (parts.length < 3) continue;\n\n const [filePath, lineNumStr, ...lineTextParts] = parts;\n const lineNum = parseInt(lineNumStr, 10);\n const lineText = lineTextParts.join('|');\n\n matches.push({\n path: filePath,\n lineNum,\n lineText: lineText.length > MAX_LINE_LENGTH ? lineText.substring(0, MAX_LINE_LENGTH) + '...' : lineText,\n });\n }\n\n // 按文件路径 + 行号排序\n matches.sort((a, b) => a.path === b.path ? a.lineNum - b.lineNum : a.path < b.path ? -1 : 1);\n\n const truncated = matches.length > SEARCH_LIMIT;\n const finalMatches = truncated ? matches.slice(0, SEARCH_LIMIT) : matches;\n\n return {\n pattern,\n matches: matches.length,\n truncated,\n results: finalMatches\n };\n } catch (error: any) {\n if (error.message?.includes('Search was aborted') || context?.signal?.aborted) {\n throw new Error('Search was aborted');\n }\n throw error;\n }\n }\n });\n}\n\nexport const grepTool = createGrepTool();\n\nexport { normalizeNamedPathArg };\n\nexport { tryNamedPathArg };\n\nexport { resolveWorkspacePath };\n","import { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport type {\n AgentFeature,\n FeatureContext,\n FeatureInitContext,\n FeatureStateSnapshot,\n ContextInjector,\n PackageInfo,\n} from '../../core/feature.js';\nimport type { HookDeclarations } from '../../core/hook-declarations.js';\nimport { CoreLifecycle } from '../../core/lifecycle.js';\nimport type { Tool } from '../../core/types.js';\nimport type {\n CallStartContext,\n StepFinishDecisionContext,\n ToolContext,\n} from '../../core/lifecycle.js';\nimport { Decision } from '../../core/lifecycle.js';\nimport { getPackageInfoFromSource } from '../../core/feature.js';\nimport { createExampleTool } from './tools.js';\nimport type {\n ExampleFeatureConfig,\n ExampleFeatureRuntimeState,\n ExampleFeatureSnapshot,\n} from './types.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexport class ExampleFeature implements AgentFeature {\n\n static hooks: HookDeclarations = {\n handleCallStart: { lifecycle: CoreLifecycle.CallStart, kind: 'observe' as const },\n validateExampleTool: { lifecycle: CoreLifecycle.ToolUse, kind: 'guard' as const, role: 'advisor' as const },\n handleStepFinish: { lifecycle: CoreLifecycle.StepFinish, kind: 'guard' as const, role: 'advisor' as const },\n };\n readonly name = 'example-feature';\n readonly source = __filename.replace(/\\\\/g, '/');\n readonly description = '示范用 Feature 骨架:展示工具、模板、上下文注入、回滚快照和反向钩子的标准写法。';\n\n private readonly config: Required<ExampleFeatureConfig>;\n private readonly runtime: ExampleFeatureRuntimeState = {\n enabled: true,\n counter: 0,\n lastInput: '',\n notes: [],\n };\n private logger?: FeatureInitContext['logger'];\n\n private _packageInfo: PackageInfo | null = null;\n\n constructor(config: ExampleFeatureConfig = {}) {\n this.config = {\n enabledByDefault: config.enabledByDefault ?? true,\n notePrefix: config.notePrefix ?? '[example]',\n };\n this.runtime.enabled = this.config.enabledByDefault;\n }\n\n /**\n * 公开 API 只保留“其他 Feature 真会读取的东西”。\n * 不要把整个 runtime 对象直接暴露出去。\n */\n isEnabled(): boolean {\n return this.runtime.enabled;\n }\n\n getCounter(): number {\n return this.runtime.counter;\n }\n\n listNotes(): string[] {\n return [...this.runtime.notes];\n }\n\n /**\n * 内部 helper 比直接在钩子和工具里散改字段更容易维护。\n * 如果 Feature 很简单,也可以不抽这些方法。\n */\n private appendNote(note: string): void {\n const normalized = note.trim();\n if (!normalized) return;\n this.runtime.notes.push(`${this.config.notePrefix} ${normalized}`.trim());\n }\n\n private setEnabled(enabled: boolean): void {\n this.runtime.enabled = enabled;\n }\n\n private buildReminder(): string {\n return `${this.config.notePrefix} example feature is active`;\n }\n\n getTools(): Tool[] {\n return [\n createExampleTool({\n getState: () => this.runtime,\n incrementCounter: () => {\n this.runtime.counter += 1;\n },\n addNote: (note: string) => {\n this.appendNote(note);\n },\n }),\n ];\n }\n\n /**\n * 获取包信息(统一打包方案)\n */\n getPackageInfo(): PackageInfo | null {\n if (!this._packageInfo) {\n this._packageInfo = getPackageInfoFromSource(this.source);\n }\n return this._packageInfo;\n }\n\n /**\n * 获取模板名称列表(统一打包方案)\n */\n getTemplateNames(): string[] {\n return ['example-tool'];\n }\n\n getContextInjectors(): Map<string | RegExp, ContextInjector> {\n return new Map([\n ['example_tool', () => ({\n _exampleFeature: {\n enabled: this.runtime.enabled,\n counter: this.runtime.counter,\n },\n })],\n ]);\n }\n\n async onInitiate(ctx: FeatureInitContext): Promise<void> {\n this.logger = ctx.logger;\n\n // 在这里做一次性初始化:\n // - 创建 client\n // - 注册数据源\n // - 加载配置文件\n // - 打印启动日志\n this.logger?.info('ExampleFeature initiated', {\n enabled: this.runtime.enabled,\n counter: this.runtime.counter,\n });\n\n // 如果 Feature 依赖其他 Feature,优先在这里拿公开 API:\n // const other = ctx.getFeature<SomePublicApi & AgentFeature>('other-feature');\n // 不要把其他 Feature 的内部字段当成稳定接口。\n }\n\n async onDestroy(_ctx: FeatureContext): Promise<void> {\n // 在这里做资源清理:\n // - 关闭 client\n // - 停止 worker / interval\n // - 释放文件句柄\n this.logger?.info('ExampleFeature destroyed');\n }\n\n captureState(): FeatureStateSnapshot {\n const snapshot: ExampleFeatureSnapshot = {\n enabled: this.runtime.enabled,\n counter: this.runtime.counter,\n lastInput: this.runtime.lastInput,\n notes: [...this.runtime.notes],\n };\n return snapshot;\n }\n\n restoreState(snapshot: FeatureStateSnapshot): void {\n const state = snapshot as ExampleFeatureSnapshot;\n\n this.runtime.enabled = Boolean(state.enabled);\n this.runtime.counter = typeof state.counter === 'number' ? state.counter : 0;\n this.runtime.lastInput = typeof state.lastInput === 'string' ? state.lastInput : '';\n this.runtime.notes = [...(state.notes ?? [])];\n }\n\n async beforeRollback(snapshot: FeatureStateSnapshot): Promise<void> {\n const state = snapshot as ExampleFeatureSnapshot;\n this.logger?.info('ExampleFeature before rollback', {\n restoringCounter: state.counter,\n });\n }\n\n async afterRollback(snapshot: FeatureStateSnapshot): Promise<void> {\n const state = snapshot as ExampleFeatureSnapshot;\n this.logger?.info('ExampleFeature after rollback', {\n restoredCounter: state.counter,\n });\n }\n\n async handleCallStart(ctx: CallStartContext): Promise<void> {\n this.runtime.lastInput = ctx.agent?.getUserInput() ?? ctx.input;\n\n // 典型用法:\n // - slash command 改写输入\n // - 模式切换\n // - 注入轻量 system reminder\n // - 记录当前轮的轻量状态\n\n // 示例 1:处理一个最简单的 slash command\n // if (this.runtime.lastInput === '/example-off') {\n // this.setEnabled(false);\n // ctx.agent?.setUserInput('');\n // }\n\n // 示例 2:仅在模式开启时注入提醒\n // if (this.runtime.enabled) {\n // ctx.context.add({ role: 'system', content: this.buildReminder() });\n // }\n }\n\n async validateExampleTool(ctx: ToolContext): Promise<typeof Decision.Continue | typeof Decision.Deny> {\n if (ctx.call.name !== 'example_tool') {\n return Decision.Continue;\n }\n\n // 典型用法:\n // - 校验参数\n // - 拦截危险工具调用\n // - 改写 call.arguments\n\n // 示例:模式关闭时拒绝执行\n // if (!this.runtime.enabled) {\n // return {\n // action: Decision.Deny,\n // reason: 'example feature disabled',\n // };\n // }\n\n // 示例:标准化参数后继续\n // if (typeof ctx.call.arguments?.note === 'string') {\n // ctx.call.arguments.note = ctx.call.arguments.note.trim();\n // }\n\n return Decision.Continue;\n }\n\n async handleStepFinish(ctx: StepFinishDecisionContext): Promise<typeof Decision.Continue> {\n // 典型用法:\n // - 统计本轮是否命中特定工具\n // - 决定是否继续下一轮\n // - 更新 reminder 计数器\n\n // 示例:只有当本轮真的用了本 Feature 的工具,才更新某个计数器\n // const usedExampleTool = ctx.llmResponse.toolCalls?.some(call => call.name === 'example_tool');\n // if (usedExampleTool) {\n // this.appendNote('tool used in this step');\n // }\n\n return Decision.Continue;\n }\n}\n","import { createTool } from '../../core/tool.js';\nimport type { Tool } from '../../core/types.js';\nimport type { ExampleFeatureRuntimeState, ExampleFeatureToolResult } from './types.js';\n\nexport function createExampleTool(deps: {\n getState(): ExampleFeatureRuntimeState;\n incrementCounter(): void;\n addNote(note: string): void;\n}): Tool {\n return createTool({\n name: 'example_tool',\n description: '示范工具:展示 Feature 内部状态、模板渲染和上下文注入是如何连起来的。',\n parameters: {\n type: 'object',\n properties: {\n note: {\n type: 'string',\n description: '要记录的一条示意说明',\n },\n },\n required: [],\n },\n render: {\n call: 'example-tool',\n result: 'example-tool',\n },\n execute: async (args, context) => {\n const { note } = args as { note?: string };\n // 这里故意保留一个最常见的 Feature 工具结构:\n // 1. 读取注入的运行时上下文\n // 2. 更新 Feature 状态\n // 3. 返回纯对象,交给模板渲染\n const injected = (context as { _exampleFeature?: { enabled: boolean; counter: number } } | undefined)?._exampleFeature;\n\n deps.incrementCounter();\n if (typeof note === 'string' && note.trim()) {\n deps.addNote(note.trim());\n }\n\n const result: ExampleFeatureToolResult = {\n enabled: deps.getState().enabled,\n counter: deps.getState().counter,\n lastInput: deps.getState().lastInput,\n notes: deps.getState().notes,\n injected,\n };\n return result;\n },\n });\n}\n","/**\n * LSP Feature - Language Server Protocol 代码智能\n *\n * 为 AI agent 提供代码智能能力:跳转定义、查找引用、悬停提示等\n * 支持 14 种语言的 LSP 服务器,每个支持 exec / runtime 两种启动模式\n */\n\nimport { fileURLToPath } from 'url';\nimport path from 'path';\nimport os from 'os';\nimport type { AgentFeature, FeatureInitContext, FeatureManifestDefinition, PackageInfo } from '../../core/feature.js';\nimport type { FeatureManifestSettingProperty } from '../../core/feature.js';\nimport type { Tool } from '../../core/types.js';\nimport { getPackageInfoFromSource } from '../../core/feature.js';\nimport { LspClient } from './client.js';\nimport { SERVERS } from './servers.js';\nimport type { LspFeatureConfig, LspServerConfig, ServerInfo } from './types.js';\n\nconst __filename = fileURLToPath(import.meta.url);\n\nexport type { LspFeatureConfig, LspServerConfig, ServerInfo, ServerSpawnConfig, ServerDefaults } from './types.js';\nexport { LspClient } from './client.js';\nexport { SERVERS } from './servers.js';\n\nfunction createLspTools(feature: LspFeature): Tool[] {\n const operations = [\n { name: 'lsp_go_to_definition', op: 'goToDefinition', desc: 'Go to symbol definition' },\n { name: 'lsp_find_references', op: 'findReferences', desc: 'Find all references to a symbol' },\n { name: 'lsp_hover', op: 'hover', desc: 'Get type information and documentation' },\n { name: 'lsp_document_symbol', op: 'documentSymbol', desc: 'List all symbols in a document' },\n { name: 'lsp_workspace_symbol', op: 'workspaceSymbol', desc: 'Search for symbols across workspace' },\n { name: 'lsp_go_to_implementation', op: 'goToImplementation', desc: 'Go to interface/abstract implementations' },\n { name: 'lsp_prepare_call_hierarchy', op: 'prepareCallHierarchy', desc: 'Prepare call hierarchy for a symbol' },\n { name: 'lsp_incoming_calls', op: 'incomingCalls', desc: 'Find incoming calls to a function' },\n { name: 'lsp_outgoing_calls', op: 'outgoingCalls', desc: 'Find outgoing calls from a function' },\n ];\n\n return operations.map(({ name, op, desc }) => ({\n name,\n description: desc,\n parallelizable: true,\n parameters: {\n type: 'object',\n properties: {\n filePath: { type: 'string', description: 'Path to the file (relative or absolute)' },\n line: { type: 'number', description: '1-based line number' },\n character: { type: 'number', description: '1-based character position' },\n },\n required: ['filePath', 'line', 'character'],\n },\n async execute(args: Record<string, unknown>) {\n const { filePath: fp, line, character } = args as { filePath: string; line: number; character: number };\n const workdir = feature.getWorkdir();\n const filePath = path.isAbsolute(fp)\n ? fp\n : path.resolve(workdir, fp);\n\n const fs = await import('fs/promises');\n try { await fs.access(filePath); } catch { throw new Error(`File not found: ${filePath}`); }\n\n const hasServer = await feature.hasServer(filePath);\n if (!hasServer) throw new Error('No LSP server available for this file type.');\n\n await feature.touchFile(filePath);\n\n const position = { file: filePath, line: line - 1, character: character - 1 };\n const uri = `file://${filePath}`;\n\n let result: any;\n switch (op) {\n case 'goToDefinition':\n result = await feature.executeOnFile(filePath, (c) => c.definition(position.file, position.line, position.character));\n break;\n case 'findReferences':\n result = await feature.executeOnFile(filePath, (c) => c.references(position.file, position.line, position.character));\n break;\n case 'hover':\n result = await feature.executeOnFile(filePath, (c) => c.hover(position.file, position.line, position.character));\n break;\n case 'documentSymbol':\n result = await feature.executeOnFile(filePath, (c) => c.documentSymbol(uri));\n break;\n case 'workspaceSymbol':\n result = await feature.executeAll((c) => c.workspaceSymbol(''));\n break;\n case 'goToImplementation':\n result = await feature.executeOnFile(filePath, (c) => c.implementation(position.file, position.line, position.character));\n break;\n case 'prepareCallHierarchy':\n result = await feature.executeOnFile(filePath, (c) => c.prepareCallHierarchy(position.file, position.line, position.character));\n break;\n case 'incomingCalls':\n result = await feature.executeOnFile(filePath, (c) => c.incomingCalls(position.file, position.line, position.character));\n break;\n case 'outgoingCalls':\n result = await feature.executeOnFile(filePath, (c) => c.outgoingCalls(position.file, position.line, position.character));\n break;\n default: throw new Error(`Unknown operation: ${op}`);\n }\n\n const output = Array.isArray(result) && result.length === 0\n ? `No results found for ${op}`\n : JSON.stringify(result, null, 2);\n\n return {\n title: `${op} ${path.relative(workdir, filePath)}:${args.line}:${args.character}`,\n output,\n metadata: { result },\n };\n },\n }));\n}\n\nexport class LspFeature implements AgentFeature {\n readonly name = 'lsp';\n readonly source = __filename.replace(/\\\\/g, '/');\n readonly description = 'LSP (Language Server Protocol) - 提供代码智能能力:跳转定义、查找引用、悬停提示等';\n\n private config: {\n workdir: string;\n binDir: string;\n disableDownload: boolean;\n runtimes: { nodejs?: string; uv?: string };\n servers: Record<string, LspServerConfig>;\n };\n\n private _packageInfo: PackageInfo | null = null;\n private logger: { info: (msg: string, data?: any) => void; error: (msg: string, data?: any) => void } | null = null;\n\n private clients: Map<string, LspClient> = new Map();\n private spawning: Map<string, Promise<LspClient | undefined>> = new Map();\n private broken: Set<string> = new Set();\n\n constructor(config: LspFeatureConfig = {}) {\n this.config = {\n workdir: config.workdir || process.cwd(),\n binDir: config.binDir || path.join(os.homedir(), '.agentdev', 'lsp-bin'),\n disableDownload: config.disableDownload ?? false,\n runtimes: config.runtimes || {},\n servers: config.servers || {},\n };\n }\n\n getPackageInfo(): PackageInfo | null {\n if (!this._packageInfo) this._packageInfo = getPackageInfoFromSource(this.source);\n return this._packageInfo;\n }\n\n getTemplateNames(): string[] { return []; }\n getTools(): Tool[] { return createLspTools(this); }\n async getAsyncTools(_ctx: FeatureInitContext): Promise<Tool[]> { return []; }\n\n async onInitiate(ctx: FeatureInitContext): Promise<void> {\n this.logger = ctx.logger;\n\n // 从 Agent 的 workspaceDir 更新 workdir(覆盖构造函数的默认值)\n if (ctx.config?.workspaceDir) {\n this.config.workdir = ctx.config.workspaceDir;\n }\n\n if (ctx.featureConfig && typeof ctx.featureConfig === 'object') {\n const fc = ctx.featureConfig as Record<string, unknown>;\n\n // Extract shared runtimes\n if (fc.runtimes && typeof fc.runtimes === 'object') {\n const rt = fc.runtimes as Record<string, unknown>;\n if (typeof rt.nodejs === 'string' && rt.nodejs) this.config.runtimes.nodejs = rt.nodejs;\n if (typeof rt.uv === 'string' && rt.uv) this.config.runtimes.uv = rt.uv;\n }\n\n // Extract per-server config\n for (const serverId of Object.keys(SERVERS)) {\n const entry = fc[serverId];\n if (entry && typeof entry === 'object' && !Array.isArray(entry)) {\n const sc = entry as Record<string, unknown>;\n const existing = this.config.servers[serverId] || {};\n if (typeof sc.mode === 'string') (existing as any).mode = sc.mode;\n if (typeof sc.runtime === 'string') (existing as any).runtime = sc.runtime;\n if (typeof sc.binary === 'string') existing.binary = sc.binary;\n if (typeof sc.package === 'string') (existing as any).package = sc.package;\n if (typeof sc.uvPackage === 'string') (existing as any).uvPackage = sc.uvPackage;\n if (typeof sc.args === 'string' && sc.args.trim()) {\n (existing as any).args = sc.args.trim().split(/\\s+/);\n }\n this.config.servers[serverId] = existing;\n }\n }\n }\n\n this.logger.info('LSP Feature initialized', { workdir: this.config.workdir });\n }\n\n async onDestroy(): Promise<void> {\n this.logger?.info('LSP Feature shutting down');\n await this.shutdownAll();\n }\n\n // ── Manifest ────────────────────────────────────────────────\n\n getFeatureManifest(): FeatureManifestDefinition {\n const serverDefs: Array<{ id: string; name: string }> = [\n { id: 'typescript', name: 'TypeScript / JavaScript' },\n { id: 'pyright', name: 'Python (Pyright)' },\n { id: 'gopls', name: 'Go (gopls)' },\n { id: 'rust-analyzer', name: 'Rust (rust-analyzer)' },\n { id: 'clangd', name: 'C/C++ (clangd)' },\n { id: 'vue', name: 'Vue' },\n { id: 'svelte', name: 'Svelte' },\n { id: 'eslint', name: 'ESLint' },\n { id: 'deno', name: 'Deno' },\n { id: 'bash', name: 'Bash' },\n { id: 'yaml', name: 'YAML' },\n { id: 'json', name: 'JSON' },\n { id: 'html', name: 'HTML' },\n { id: 'css', name: 'CSS' },\n ];\n\n const properties: Record<string, FeatureManifestSettingProperty> = {\n runtimes: {\n type: 'group',\n title: 'Runtimes',\n description: 'Shared runtime paths. Leave empty to auto-detect from PATH.',\n properties: {\n nodejs: { type: 'file', title: 'Node.js', placeholder: 'Auto-detect' },\n uv: { type: 'file', title: 'uv / uvx', placeholder: 'Auto-detect' },\n },\n },\n };\n\n for (const server of serverDefs) {\n const defaults = SERVERS[server.id]?.defaults;\n properties[server.id] = {\n type: 'group',\n title: server.name,\n properties: {\n mode: {\n type: 'select',\n title: 'Mode',\n default: defaults?.defaultMode,\n options: [\n { label: 'Exec (Binary)', value: 'exec' },\n { label: 'Runtime (npx/uvx)', value: 'runtime' },\n ],\n },\n binary: {\n type: 'file',\n title: 'Binary',\n placeholder: 'Auto-detect',\n default: defaults?.execBinary,\n showWhen: { property: 'mode', values: ['exec'] },\n },\n runtime: {\n type: 'select',\n title: 'Runtime',\n default: defaults?.defaultRuntime || 'nodejs',\n options: [\n { label: 'Node.js (npx)', value: 'nodejs' },\n { label: 'uv (uvx)', value: 'uv' },\n ],\n showWhen: { property: 'mode', values: ['runtime'] },\n },\n package: {\n type: 'string',\n title: 'Package (npx)',\n description: defaults?.runtimePackage ? `Default: ${defaults.runtimePackage}` : '',\n placeholder: defaults?.runtimePackage || 'e.g. typescript-language-server',\n showWhen: { property: 'mode', values: ['runtime'] },\n },\n uvPackage: {\n type: 'string',\n title: 'Package (uvx)',\n description: defaults?.uvPackage ? `Default: ${defaults.uvPackage}` : (defaults?.runtimePackage ? `Default: ${defaults.runtimePackage}` : ''),\n placeholder: defaults?.uvPackage || defaults?.runtimePackage || '',\n showWhen: { property: 'runtime', values: ['uv'] },\n },\n args: {\n type: 'string',\n title: 'Arguments',\n description: defaults?.runtimeArgs?.length ? `Default: ${defaults.runtimeArgs.join(' ')}` : '',\n placeholder: defaults?.runtimeArgs?.join(' ') || '--stdio',\n },\n },\n };\n }\n\n return {\n schemaVersion: 1,\n settings: {\n properties,\n sections: [\n { id: 'runtimes', title: 'Runtimes', properties: ['runtimes'] },\n { id: 'lsp', title: 'Language Servers', properties: serverDefs.map(s => s.id) },\n ],\n },\n };\n }\n\n // ── State ───────────────────────────────────────────────────\n\n captureState(): { activeServerIds: string[] } {\n return { activeServerIds: Array.from(this.clients.keys()) };\n }\n\n restoreState(_state: any): void {\n this.logger?.info('LSP Feature state restored, servers will be started on demand');\n }\n\n // ── Public API ──────────────────────────────────────────────\n\n getWorkdir(): string { return this.config.workdir; }\n\n async hasServer(file: string): Promise<boolean> {\n const extension = path.extname(file) || file;\n for (const server of Object.values(SERVERS)) {\n const serverConfig = this.config.servers?.[server.id];\n if (serverConfig?.disabled) continue;\n if (server.extensions.length && !server.extensions.includes(extension)) continue;\n const root = await server.root(file, this.config.workdir);\n if (root) return true;\n }\n return false;\n }\n\n async touchFile(file: string): Promise<void> {\n const clients = await this.getClientsForFile(file);\n await Promise.all(\n clients.map(async (client) => {\n const wait = client.waitForDiagnostics(file);\n await client.notifyOpen(file);\n return wait;\n })\n ).catch((err) => {\n this.logger?.error('failed to touch file', { err, file });\n });\n }\n\n async executeOnFile<T>(file: string, fn: (client: LspClient) => Promise<T>): Promise<T[]> {\n const clients = await this.getClientsForFile(file);\n return Promise.all(clients.map((client) => fn(client)));\n }\n\n async executeAll<T>(fn: (client: LspClient) => Promise<T>): Promise<T[]> {\n return Promise.all(Array.from(this.clients.values()).map((client) => fn(client)));\n }\n\n // ── Internal ────────────────────────────────────────────────\n\n private async getClientsForFile(file: string): Promise<LspClient[]> {\n const extension = path.extname(file) || file;\n const result: LspClient[] = [];\n\n for (const server of Object.values(SERVERS)) {\n const serverConfig = this.config.servers?.[server.id];\n if (serverConfig?.disabled) continue;\n if (server.extensions.length && !server.extensions.includes(extension)) continue;\n\n const root = await server.root(file, this.config.workdir);\n if (!root) continue;\n\n const key = root + server.id;\n if (this.broken.has(key)) continue;\n\n const existing = this.clients.get(key);\n if (existing) { result.push(existing); continue; }\n\n const inflight = this.spawning.get(key);\n if (inflight) { const c = await inflight; if (c) result.push(c); continue; }\n\n const task = this.spawnServer(server, root, serverConfig);\n this.spawning.set(key, task);\n task.finally(() => { if (this.spawning.get(key) === task) this.spawning.delete(key); });\n\n const client = await task;\n if (client) result.push(client);\n }\n\n return result;\n }\n\n private async spawnServer(\n server: ServerInfo,\n root: string,\n serverConfig?: LspServerConfig\n ): Promise<LspClient | undefined> {\n const key = root + server.id;\n const spawnConfig = {\n binDir: this.config.binDir,\n workdir: this.config.workdir,\n disableDownload: this.config.disableDownload,\n binary: serverConfig?.binary,\n mode: (serverConfig as any)?.mode,\n runtime: (serverConfig as any)?.runtime,\n package: (serverConfig as any)?.package,\n uvPackage: (serverConfig as any)?.uvPackage,\n args: (serverConfig as any)?.args,\n runtimes: this.config.runtimes,\n env: serverConfig?.env,\n initialization: serverConfig?.initialization,\n };\n\n let handle;\n try {\n const result = await server.spawn(root, spawnConfig);\n if (!result) {\n this.logger?.error(`LSP server ${server.id} spawn returned undefined`);\n this.broken.add(key);\n return undefined;\n }\n handle = result;\n } catch (err: any) {\n this.logger?.error(`Failed to spawn LSP server ${server.id}`, {\n error: err, errorMessage: err.message, errorStack: err.stack,\n });\n this.broken.add(key);\n return undefined;\n }\n\n this.logger?.info('spawned lsp server', { serverID: server.id, pid: handle.process.pid });\n\n handle.process.on('error', (err: Error) => {\n this.logger?.error(`LSP server ${server.id} process error`, { error: err });\n this.broken.add(key);\n this.clients.delete(key);\n });\n\n const client = new LspClient(server.id, handle, root, this.logger!);\n try {\n await client.initialize();\n } catch (err: any) {\n this.logger?.error(`Failed to initialize LSP client ${server.id}`, {\n error: err, errorMessage: err.message, errorStack: err.stack,\n });\n this.broken.add(key);\n try { handle.process.kill(15); } catch {}\n return undefined;\n }\n\n const existing = this.clients.get(key);\n if (existing) {\n try { handle.process.kill(15); } catch {}\n return existing;\n }\n\n this.clients.set(key, client);\n return client;\n }\n\n private async shutdownAll(): Promise<void> {\n await Promise.all(Array.from(this.clients.values()).map((client) => client.shutdown()));\n this.clients.clear();\n this.spawning.clear();\n this.broken.clear();\n }\n}\n","/**\n * LSP Client - 通过 JSON-RPC 与 LSP 服务器通信\n */\n\nimport { EventEmitter } from 'events';\nimport path from 'path';\nimport { readFile } from 'fs/promises';\nimport { pathToFileURL, fileURLToPath } from 'url';\nimport {\n createMessageConnection,\n StreamMessageReader,\n StreamMessageWriter,\n} from 'vscode-jsonrpc/node.js';\nimport type { Diagnostic } from 'vscode-languageserver-types';\nimport { LANGUAGE_EXTENSIONS } from './servers.js';\nimport type { LspServerHandle } from './types.js';\n\nconst DIAGNOSTICS_DEBOUNCE_MS = 150;\nconst INIT_TIMEOUT_MS = 45000;\nconst DIAGNOSTICS_WAIT_TIMEOUT_MS = 3000;\n// 单次查询请求的超时:LSP server 进程假死(活着但不回话)时,\n// 底层 JSON-RPC 永远不会 settle,统一在此兜底\nconst REQUEST_TIMEOUT_MS = 15000;\n\nfunction normalizePath(p: string): string {\n return p.replace(/\\\\/g, '/');\n}\n\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => reject(new Error('Timeout')), ms);\n promise.then(\n (value) => {\n clearTimeout(timer);\n resolve(value);\n },\n (error) => {\n clearTimeout(timer);\n reject(error);\n }\n );\n });\n}\n\n/**\n * LSP Client - 处理与 LSP 服务器的 JSON-RPC 通信\n */\nexport class LspClient extends EventEmitter {\n private connection: any;\n private diagnostics: Map<string, Diagnostic[]> = new Map();\n private files: Record<string, number> = {};\n\n constructor(\n private serverID: string,\n private handle: LspServerHandle,\n private root: string,\n private logger: { info: (msg: string, data?: any) => void; error: (msg: string, data?: any) => void }\n ) {\n super();\n this.connection = createMessageConnection(\n new StreamMessageReader(handle.process.stdout),\n new StreamMessageWriter(handle.process.stdin)\n );\n this.setupHandlers();\n }\n\n private setupHandlers(): void {\n this.connection.onNotification('textDocument/publishDiagnostics', (params: any) => {\n const filePath = normalizePath(fileURLToPath(params.uri));\n this.logger.info('diagnostics received', {\n path: filePath,\n count: params.diagnostics.length,\n });\n this.diagnostics.set(filePath, params.diagnostics);\n this.emit('diagnostics', { path: filePath, serverID: this.serverID });\n });\n\n this.connection.onRequest('window/workDoneProgress/create', () => null);\n this.connection.onRequest('workspace/configuration', async () => [\n this.handle.initialization ?? {},\n ]);\n this.connection.onRequest('client/registerCapability', async () => {});\n this.connection.onRequest('client/unregisterCapability', async () => {});\n this.connection.onRequest('workspace/workspaceFolders', async () => [\n { name: 'workspace', uri: pathToFileURL(this.root).href },\n ]);\n }\n\n async initialize(): Promise<void> {\n this.connection.listen();\n this.logger.info('sending initialize');\n\n await withTimeout(\n this.connection.sendRequest('initialize', {\n rootUri: pathToFileURL(this.root).href,\n processId: this.handle.process.pid,\n workspaceFolders: [{ name: 'workspace', uri: pathToFileURL(this.root).href }],\n initializationOptions: { ...this.handle.initialization },\n capabilities: {\n window: { workDoneProgress: true },\n workspace: {\n configuration: true,\n didChangeWatchedFiles: { dynamicRegistration: true },\n },\n textDocument: {\n synchronization: { didOpen: true, didChange: true },\n publishDiagnostics: { versionSupport: true },\n },\n },\n }),\n INIT_TIMEOUT_MS\n );\n\n await this.connection.sendNotification('initialized', {});\n\n if (this.handle.initialization) {\n await this.connection.sendNotification('workspace/didChangeConfiguration', {\n settings: this.handle.initialization,\n });\n }\n\n this.logger.info('initialized');\n }\n\n get serverId(): string {\n return this.serverID;\n }\n\n get clientRoot(): string {\n return this.root;\n }\n\n getDiagnostics(): Map<string, Diagnostic[]> {\n return this.diagnostics;\n }\n\n async notifyOpen(filePath: string): Promise<void> {\n filePath = path.isAbsolute(filePath) ? filePath : path.resolve(this.root, filePath);\n const text = await readFile(filePath, 'utf-8');\n const extension = path.extname(filePath);\n const languageId = LANGUAGE_EXTENSIONS[extension] ?? 'plaintext';\n const version = this.files[filePath];\n\n if (version !== undefined) {\n await this.connection.sendNotification('workspace/didChangeWatchedFiles', {\n changes: [{ uri: pathToFileURL(filePath).href, type: 2 }],\n });\n const next = version + 1;\n this.files[filePath] = next;\n await this.connection.sendNotification('textDocument/didChange', {\n textDocument: { uri: pathToFileURL(filePath).href, version: next },\n contentChanges: [{ text }],\n });\n } else {\n await this.connection.sendNotification('workspace/didChangeWatchedFiles', {\n changes: [{ uri: pathToFileURL(filePath).href, type: 1 }],\n });\n this.diagnostics.delete(filePath);\n await this.connection.sendNotification('textDocument/didOpen', {\n textDocument: {\n uri: pathToFileURL(filePath).href,\n languageId,\n version: 0,\n text,\n },\n });\n this.files[filePath] = 0;\n }\n }\n\n async waitForDiagnostics(filePath: string): Promise<void> {\n const normalizedPath = normalizePath(\n path.isAbsolute(filePath) ? filePath : path.resolve(this.root, filePath)\n );\n\n return withTimeout(\n new Promise<void>((resolve) => {\n let debounceTimer: NodeJS.Timeout;\n const handler = (data: { path: string; serverID: string }) => {\n if (data.path === normalizedPath && data.serverID === this.serverID) {\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => {\n this.off('diagnostics', handler);\n resolve();\n }, DIAGNOSTICS_DEBOUNCE_MS);\n }\n };\n this.on('diagnostics', handler);\n }),\n DIAGNOSTICS_WAIT_TIMEOUT_MS\n ).catch(() => {});\n }\n\n // LSP request methods\n\n /**\n * 带超时的查询请求:超时或出错时降级为 fallback 值(与既有 catch 语义一致),\n * 避免语言服务器无响应时请求永久挂起。\n */\n private sendRequestWithTimeout(method: string, params: unknown, fallback: unknown): Promise<unknown> {\n return withTimeout(this.connection.sendRequest(method, params), REQUEST_TIMEOUT_MS).catch(() => fallback);\n }\n\n async definition(filePath: string, line: number, character: number): Promise<unknown> {\n return this.sendRequestWithTimeout('textDocument/definition', {\n textDocument: { uri: pathToFileURL(filePath).href },\n position: { line, character },\n }, null);\n }\n\n async references(filePath: string, line: number, character: number): Promise<unknown> {\n return this.sendRequestWithTimeout('textDocument/references', {\n textDocument: { uri: pathToFileURL(filePath).href },\n position: { line, character },\n context: { includeDeclaration: true },\n }, []);\n }\n\n async hover(filePath: string, line: number, character: number): Promise<unknown> {\n return this.sendRequestWithTimeout('textDocument/hover', {\n textDocument: { uri: pathToFileURL(filePath).href },\n position: { line, character },\n }, null);\n }\n\n async documentSymbol(uri: string): Promise<unknown> {\n return this.sendRequestWithTimeout('textDocument/documentSymbol', { textDocument: { uri } }, []);\n }\n\n async workspaceSymbol(query: string): Promise<unknown> {\n return this.sendRequestWithTimeout('workspace/symbol', { query }, []);\n }\n\n async implementation(filePath: string, line: number, character: number): Promise<unknown> {\n return this.sendRequestWithTimeout('textDocument/implementation', {\n textDocument: { uri: pathToFileURL(filePath).href },\n position: { line, character },\n }, null);\n }\n\n async prepareCallHierarchy(filePath: string, line: number, character: number): Promise<unknown> {\n return this.sendRequestWithTimeout('textDocument/prepareCallHierarchy', {\n textDocument: { uri: pathToFileURL(filePath).href },\n position: { line, character },\n }, []);\n }\n\n async incomingCalls(filePath: string, line: number, character: number): Promise<unknown> {\n return this.sendRequestWithTimeout('callHierarchy/incomingCalls', {\n item: {\n uri: pathToFileURL(filePath).href,\n range: {\n start: { line, character },\n end: { line, character },\n },\n },\n }, []);\n }\n\n async outgoingCalls(filePath: string, line: number, character: number): Promise<unknown> {\n return this.sendRequestWithTimeout('callHierarchy/outgoingCalls', {\n item: {\n uri: pathToFileURL(filePath).href,\n range: {\n start: { line, character },\n end: { line, character },\n },\n },\n }, []);\n }\n\n async shutdown(): Promise<void> {\n try {\n await this.connection.sendRequest('shutdown');\n await this.connection.sendNotification('exit');\n } catch (error) {\n this.logger.error('Error during LSP shutdown', { error });\n }\n this.connection.dispose();\n }\n}\n","/**\n * LSP 服务器定义\n *\n * 支持 14 种语言的 LSP 服务器\n * 每个服务器通过 ServerDefaults 声明启动模式与包名,\n * resolveSpawn() 根据 mode/runtime 统一派生 spawn 参数。\n */\n\nimport { spawn } from 'child_process';\nimport path from 'path';\nimport { access } from 'fs/promises';\nimport type { ServerInfo, ServerSpawnConfig, ServerDefaults } from './types.js';\nimport { findExecutable } from './which.js';\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport const LANGUAGE_EXTENSIONS: Record<string, string> = {\n '.abap': 'abap', '.bat': 'bat', '.bib': 'bibtex', '.clj': 'clojure',\n '.cljs': 'clojure', '.cljc': 'clojure', '.coffee': 'coffeescript',\n '.c': 'c', '.cpp': 'cpp', '.cxx': 'cpp', '.cc': 'cpp',\n '.cs': 'csharp', '.css': 'css', '.d': 'd', '.pas': 'pascal',\n '.diff': 'diff', '.patch': 'diff', '.dart': 'dart',\n '.dockerfile': 'dockerfile', '.ex': 'elixir', '.exs': 'elixir',\n '.erl': 'erlang', '.hrl': 'erlang', '.fs': 'fsharp', '.fsi': 'fsharp',\n '.fsx': 'fsharp', '.go': 'go', '.groovy': 'groovy', '.gleam': 'gleam',\n '.hbs': 'handlebars', '.hs': 'haskell', '.lhs': 'haskell',\n '.html': 'html', '.htm': 'html', '.ini': 'ini', '.java': 'java',\n '.js': 'javascript', '.kt': 'kotlin', '.kts': 'kotlin',\n '.jsx': 'javascriptreact', '.json': 'json', '.tex': 'latex',\n '.less': 'less', '.lua': 'lua', '.md': 'markdown', '.markdown': 'markdown',\n '.m': 'objective-c', '.mm': 'objective-cpp', '.pl': 'perl', '.pm': 'perl',\n '.php': 'php', '.ps1': 'powershell', '.py': 'python', '.r': 'r',\n '.rb': 'ruby', '.rake': 'ruby', '.gemspec': 'ruby', '.erb': 'erb',\n '.rs': 'rust', '.scss': 'scss', '.sass': 'sass', '.scala': 'scala',\n '.sh': 'shellscript', '.bash': 'shellscript', '.zsh': 'shellscript',\n '.sql': 'sql', '.svelte': 'svelte', '.swift': 'swift',\n '.ts': 'typescript', '.tsx': 'typescriptreact', '.mts': 'typescript',\n '.cts': 'typescript', '.xml': 'xml', '.yaml': 'yaml', '.yml': 'yaml',\n '.mjs': 'javascript', '.cjs': 'javascript', '.vue': 'vue',\n '.zig': 'zig', '.astro': 'astro', '.ml': 'ocaml', '.mli': 'ocaml',\n '.tf': 'terraform', '.nix': 'nix',\n};\n\nfunction nearestRoot(\n markers: string[],\n excludeMarkers?: string[]\n): (file: string) => Promise<string | undefined> {\n return async (file: string) => {\n let current = path.dirname(file);\n while (true) {\n for (const marker of markers) {\n if (await pathExists(path.join(current, marker))) {\n if (excludeMarkers) {\n for (const exclude of excludeMarkers) {\n if (await pathExists(path.join(current, exclude))) {\n return undefined;\n }\n }\n }\n return current;\n }\n }\n const parent = path.dirname(current);\n if (parent === current) break;\n current = parent;\n }\n return undefined;\n };\n}\n\n// ── resolveSpawn ────────────────────────────────────────────────\n\nfunction resolveSpawn(\n defaults: ServerDefaults,\n config: ServerSpawnConfig,\n root: string,\n extraInit?: Record<string, any>\n): { process: any; initialization?: Record<string, any> } | undefined {\n const mode = config.mode || defaults.defaultMode;\n const args = config.args || [];\n\n if (mode === 'exec') {\n const bin = config.binary || findExecutable(defaults.execBinary || '');\n if (!bin) return undefined;\n const proc = spawn(bin, [...(defaults.execArgs || []), ...args], {\n cwd: root,\n env: { ...process.env, ...config.env },\n });\n return { process: proc, initialization: { ...extraInit, ...config.initialization } };\n }\n\n // runtime mode\n const runtime = config.runtime || defaults.defaultRuntime || 'nodejs';\n\n if (runtime === 'uv') {\n const bin = config.runtimes?.uv || findExecutable('uv');\n if (!bin) return undefined;\n const pkg = config.uvPackage || config.package || defaults.uvPackage || defaults.runtimePackage || '';\n const proc = spawn(bin, ['tool', 'run', ...(pkg ? [pkg] : []), ...(defaults.runtimeArgs || []), ...args], {\n cwd: root,\n env: { ...process.env, ...config.env },\n });\n return { process: proc, initialization: { ...extraInit, ...config.initialization } };\n }\n\n // nodejs — npx semantics\n const npxBin = config.runtimes?.nodejs\n ? path.join(path.dirname(config.runtimes.nodejs), process.platform === 'win32' ? 'npx.cmd' : 'npx')\n : findExecutable('npx');\n if (!npxBin) return undefined;\n const pkg = config.package || defaults.runtimePackage || '';\n const proc = spawn(npxBin, ['-y', ...(pkg ? [pkg] : []), ...(defaults.runtimeArgs || []), ...args], {\n cwd: root,\n env: { ...process.env, ...config.env },\n shell: true,\n });\n return { process: proc, initialization: { ...extraInit, ...config.initialization } };\n}\n\n// ── Server definitions ──────────────────────────────────────────\n\nexport const Typescript: ServerInfo = {\n id: 'typescript',\n defaults: {\n defaultMode: 'runtime', defaultRuntime: 'nodejs',\n execBinary: 'typescript-language-server', execArgs: ['--stdio'],\n runtimePackage: 'typescript-language-server', runtimeArgs: ['--stdio'],\n },\n root: nearestRoot(\n ['package-lock.json', 'bun.lockb', 'bun.lock', 'pnpm-lock.yaml', 'yarn.lock'],\n ['deno.json', 'deno.jsonc']\n ),\n extensions: ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.mts', '.cts'],\n async spawn(root, config) {\n return resolveSpawn(this.defaults, config, root);\n },\n};\n\nexport const Python: ServerInfo = {\n id: 'pyright',\n defaults: {\n defaultMode: 'runtime', defaultRuntime: 'nodejs',\n execBinary: 'pyright-langserver', execArgs: ['--stdio'],\n runtimePackage: 'pyright-langserver', runtimeArgs: ['--stdio'],\n uvPackage: 'pyright',\n },\n root: nearestRoot([\n 'pyproject.toml', 'setup.py', 'setup.cfg', 'requirements.txt', 'Pipfile', 'pyrightconfig.json',\n ]),\n extensions: ['.py', '.pyi'],\n async spawn(root, config) {\n const initialization: Record<string, any> = {};\n const venvPaths = [\n process.env.VIRTUAL_ENV,\n path.join(root, '.venv'),\n path.join(root, 'venv'),\n ].filter(Boolean) as string[];\n for (const venvPath of venvPaths) {\n const pythonPath =\n process.platform === 'win32'\n ? path.join(venvPath, 'Scripts', 'python.exe')\n : path.join(venvPath, 'bin', 'python');\n if (await pathExists(pythonPath)) {\n initialization.pythonPath = pythonPath;\n break;\n }\n }\n return resolveSpawn(this.defaults, config, root, initialization);\n },\n};\n\nexport const Go: ServerInfo = {\n id: 'gopls',\n defaults: {\n defaultMode: 'exec',\n execBinary: 'gopls',\n },\n root: async (file: string) => {\n const workRoot = await nearestRoot(['go.work'])(file);\n if (workRoot) return workRoot;\n return nearestRoot(['go.mod', 'go.sum'])(file);\n },\n extensions: ['.go'],\n async spawn(root, config) {\n return resolveSpawn(this.defaults, config, root);\n },\n};\n\nexport const Rust: ServerInfo = {\n id: 'rust-analyzer',\n defaults: {\n defaultMode: 'exec',\n execBinary: 'rust-analyzer',\n },\n root: nearestRoot(['Cargo.toml', 'Cargo.lock']),\n extensions: ['.rs'],\n async spawn(root, config) {\n return resolveSpawn(this.defaults, config, root);\n },\n};\n\nexport const Clangd: ServerInfo = {\n id: 'clangd',\n defaults: {\n defaultMode: 'exec',\n execBinary: 'clangd',\n execArgs: ['--background-index', '--clang-tidy'],\n },\n root: nearestRoot(['compile_commands.json', 'compile_flags.txt', '.clangd', 'CMakeLists.txt', 'Makefile']),\n extensions: ['.c', '.cpp', '.cc', '.cxx', '.h', '.hpp', '.hh', '.hxx'],\n async spawn(root, config) {\n return resolveSpawn(this.defaults, config, root);\n },\n};\n\nexport const Vue: ServerInfo = {\n id: 'vue',\n defaults: {\n defaultMode: 'runtime', defaultRuntime: 'nodejs',\n execBinary: 'vue-language-server', execArgs: ['--stdio'],\n runtimePackage: '@vue/language-server', runtimeArgs: ['--stdio'],\n },\n root: nearestRoot(['package-lock.json', 'bun.lockb', 'bun.lock', 'pnpm-lock.yaml', 'yarn.lock']),\n extensions: ['.vue'],\n async spawn(root, config) {\n return resolveSpawn(this.defaults, config, root);\n },\n};\n\nexport const Svelte: ServerInfo = {\n id: 'svelte',\n defaults: {\n defaultMode: 'runtime', defaultRuntime: 'nodejs',\n execBinary: 'svelteserver', execArgs: ['--stdio'],\n runtimePackage: 'svelte-language-server', runtimeArgs: ['--stdio'],\n },\n root: nearestRoot(['package-lock.json', 'bun.lockb', 'bun.lock', 'pnpm-lock.yaml', 'yarn.lock']),\n extensions: ['.svelte'],\n async spawn(root, config) {\n return resolveSpawn(this.defaults, config, root);\n },\n};\n\nexport const ESLint: ServerInfo = {\n id: 'eslint',\n defaults: {\n defaultMode: 'runtime', defaultRuntime: 'nodejs',\n runtimePackage: 'vscode-eslint-language-server', runtimeArgs: ['--stdio'],\n },\n root: nearestRoot(['package-lock.json', 'bun.lockb', 'bun.lock', 'pnpm-lock.yaml', 'yarn.lock']),\n extensions: ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.mts', '.cts', '.vue'],\n async spawn(root, config) {\n const localBin = path.join(root, 'node_modules', '.bin', 'eslint');\n if (!(await pathExists(localBin))) return undefined;\n return resolveSpawn(this.defaults, config, root);\n },\n};\n\nexport const Deno: ServerInfo = {\n id: 'deno',\n defaults: {\n defaultMode: 'exec',\n execBinary: 'deno',\n execArgs: ['lsp'],\n },\n root: async (file: string) => {\n const files = ['deno.json', 'deno.jsonc'];\n let current = path.dirname(file);\n while (true) {\n for (const f of files) {\n if (await pathExists(path.join(current, f))) return current;\n }\n const parent = path.dirname(current);\n if (parent === current) break;\n current = parent;\n }\n return undefined;\n },\n extensions: ['.ts', '.tsx', '.js', '.jsx', '.mjs'],\n async spawn(root, config) {\n return resolveSpawn(this.defaults, config, root);\n },\n};\n\nexport const Bash: ServerInfo = {\n id: 'bash',\n defaults: {\n defaultMode: 'runtime', defaultRuntime: 'nodejs',\n execBinary: 'bash-language-server', execArgs: ['start'],\n runtimePackage: 'bash-language-server', runtimeArgs: ['start'],\n },\n root: async (_file, workspaceDir) => workspaceDir,\n extensions: ['.sh', '.bash', '.zsh', '.ksh'],\n async spawn(root, config) {\n return resolveSpawn(this.defaults, config, root);\n },\n};\n\nexport const Yaml: ServerInfo = {\n id: 'yaml',\n defaults: {\n defaultMode: 'runtime', defaultRuntime: 'nodejs',\n execBinary: 'yaml-language-server', execArgs: ['--stdio'],\n runtimePackage: 'yaml-language-server', runtimeArgs: ['--stdio'],\n },\n root: async (_file, workspaceDir) => workspaceDir,\n extensions: ['.yaml', '.yml'],\n async spawn(root, config) {\n return resolveSpawn(this.defaults, config, root);\n },\n};\n\nexport const Json: ServerInfo = {\n id: 'json',\n defaults: {\n defaultMode: 'runtime', defaultRuntime: 'nodejs',\n execBinary: 'vscode-json-language-server', execArgs: ['--stdio'],\n runtimePackage: 'vscode-languageserver-json', runtimeArgs: ['--stdio'],\n },\n root: async (_file, workspaceDir) => workspaceDir,\n extensions: ['.json', '.jsonc'],\n async spawn(root, config) {\n return resolveSpawn(this.defaults, config, root);\n },\n};\n\nexport const Html: ServerInfo = {\n id: 'html',\n defaults: {\n defaultMode: 'runtime', defaultRuntime: 'nodejs',\n execBinary: 'vscode-html-language-server', execArgs: ['--stdio'],\n runtimePackage: 'vscode-languageserver-html', runtimeArgs: ['--stdio'],\n },\n root: async (_file, workspaceDir) => workspaceDir,\n extensions: ['.html', '.htm'],\n async spawn(root, config) {\n return resolveSpawn(this.defaults, config, root);\n },\n};\n\nexport const Css: ServerInfo = {\n id: 'css',\n defaults: {\n defaultMode: 'runtime', defaultRuntime: 'nodejs',\n execBinary: 'vscode-css-language-server', execArgs: ['--stdio'],\n runtimePackage: 'vscode-languageserver-css', runtimeArgs: ['--stdio'],\n },\n root: async (_file, workspaceDir) => workspaceDir,\n extensions: ['.css', '.scss', '.less'],\n async spawn(root, config) {\n return resolveSpawn(this.defaults, config, root);\n },\n};\n\nexport const SERVERS: Record<string, ServerInfo> = {\n typescript: Typescript,\n pyright: Python,\n gopls: Go,\n 'rust-analyzer': Rust,\n clangd: Clangd,\n vue: Vue,\n svelte: Svelte,\n eslint: ESLint,\n deno: Deno,\n bash: Bash,\n yaml: Yaml,\n json: Json,\n html: Html,\n css: Css,\n};\n","/**\n * 跨平台可执行文件查找\n *\n * Windows 使用 `where`,其他平台使用 `which`。\n * 返回第一个匹配的路径,找不到返回 undefined。\n */\n\nimport { execSync } from 'child_process';\n\nexport function findExecutable(command: string): string | undefined {\n if (!command) return undefined;\n try {\n const isWin = process.platform === 'win32';\n const cmd = isWin ? `where ${command}` : `which ${command}`;\n const result = execSync(cmd, {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim();\n if (!result) return undefined;\n return result.split(/\\r?\\n/)[0].trim() || undefined;\n } catch {\n return undefined;\n }\n}\n","/**\n * OutputGuard Feature - 工具输出安全网\n *\n * 框架级 Feature,通过 ToolResultTransform 钩子在工具结果写入 context 前进行截断。\n *\n * 设计层次:\n * - Layer 0(工具自截断):工具在自己的 execute() 中自行截断(如 shell 的 30K)。\n * 只要结果在 hardLimit 以下,OutputGuard 不会介入。\n * - Layer 1(安全网):OutputGuard 在 ToolResultTransform 钩子中捕获超限结果,\n * 使用级联截断策略(JSON 字段截断 → 行感知 head+tail → 字符 head+tail)。\n *\n * @example\n * ```typescript\n * import { OutputGuardFeature } from '@agentdevjs/core';\n * const agent = new Agent({ ... }).use(new OutputGuardFeature());\n * ```\n */\n\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { mkdir, writeFile } from 'fs/promises';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nimport type {\n AgentFeature,\n FeatureInitContext,\n FeatureContext,\n ContextInjector,\n PackageInfo,\n FeatureStateSnapshot,\n} from '../../core/feature.js';\nimport type { HookDeclarations } from '../../core/hook-declarations.js';\nimport { CoreLifecycle } from '../../core/lifecycle.js';\nimport type { Tool } from '../../core/types.js';\nimport type { ToolResultTransformContext } from '../../core/lifecycle.js';\nimport type { ToolExecResult } from '../../core/context.js';\nimport { getPackageInfoFromSource } from '../../core/feature.js';\nimport {\n truncateOutput,\n DEFAULT_HARD_LIMIT,\n DEFAULT_FIELD_LIMIT,\n} from './truncate.js';\nimport type { TruncateOptions } from './truncate.js';\n\n// ========== 类型定义 ==========\n\nexport interface OutputGuardConfig {\n /** 总体积硬限制(默认 50000 字符) */\n hardLimit?: number;\n /** 单个字符串字段截断长度(默认 5000 字符) */\n fieldLimit?: number;\n /** 按工具名覆盖配置 */\n toolOverrides?: Record<string, { hardLimit?: number; fieldLimit?: number }>;\n /** 工作目录,用于持久化截断内容(默认 process.cwd()) */\n workdir?: string;\n}\n\n// ========== Feature 实现 ==========\n\nexport class OutputGuardFeature implements AgentFeature {\n\n static hooks: HookDeclarations = {\n handleToolResultTransform: { lifecycle: CoreLifecycle.ToolResultTransform, kind: 'transform' as const },\n };\n readonly name = 'output-guard';\n readonly source = __filename.replace(/\\\\/g, '/');\n readonly description =\n '工具输出安全网:在工具结果写入 context 前截断超限输出,防止上下文溢出。';\n\n private readonly config: Required<Omit<OutputGuardConfig, 'toolOverrides'>> & {\n toolOverrides: Record<string, { hardLimit?: number; fieldLimit?: number }>;\n };\n\n private logger?: FeatureInitContext['logger'];\n private _packageInfo: PackageInfo | null = null;\n private truncateCount = 0;\n\n constructor(config: OutputGuardConfig = {}) {\n this.config = {\n hardLimit: config.hardLimit ?? DEFAULT_HARD_LIMIT,\n fieldLimit: config.fieldLimit ?? DEFAULT_FIELD_LIMIT,\n workdir: config.workdir ?? process.cwd(),\n toolOverrides: config.toolOverrides ?? {},\n };\n }\n\n // ========== AgentFeature 接口实现 ==========\n\n getTools(): Tool[] {\n return []; // 纯钩子 Feature,不注册工具\n }\n\n getPackageInfo(): PackageInfo | null {\n if (!this._packageInfo) {\n this._packageInfo = getPackageInfoFromSource(this.source);\n }\n return this._packageInfo;\n }\n\n getTemplateNames(): string[] {\n return [];\n }\n\n getContextInjectors(): Map<string | RegExp, ContextInjector> {\n return new Map();\n }\n\n async onInitiate(ctx: FeatureInitContext): Promise<void> {\n this.logger = ctx.logger;\n this.logger?.info('OutputGuardFeature initiated', {\n hardLimit: this.config.hardLimit,\n fieldLimit: this.config.fieldLimit,\n });\n }\n\n async onDestroy(_ctx: FeatureContext): Promise<void> {\n this.logger?.info('OutputGuardFeature destroyed', {\n totalTruncations: this.truncateCount,\n });\n }\n\n captureState(): FeatureStateSnapshot {\n return { truncateCount: this.truncateCount };\n }\n\n restoreState(snapshot: FeatureStateSnapshot): void {\n const state = snapshot as { truncateCount?: number } | null;\n this.truncateCount = typeof state?.truncateCount === 'number' ? state.truncateCount : 0;\n }\n\n async beforeRollback(_snapshot: FeatureStateSnapshot): Promise<void> {}\n async afterRollback(_snapshot: FeatureStateSnapshot): Promise<void> {}\n\n // ========== ToolResultTransform 钩子 ==========\n\n async handleToolResultTransform(\n ctx: ToolResultTransformContext,\n ): Promise<ToolExecResult | undefined> {\n const { result, toolName } = ctx;\n\n // 只处理成功的结果(错误结果通常很短)\n if (!result.success) return undefined;\n\n // result.result 可能是 string 或 Record<string, any>\n // 统一转为字符串进行截断判断\n const rawResult = result.result;\n const resultStr = typeof rawResult === 'string'\n ? rawResult\n : JSON.stringify(rawResult);\n\n // 获取该工具的配置覆盖\n const options = this.getOptions(toolName);\n\n // 执行截断\n const truncateResult = truncateOutput(resultStr, options);\n\n // 不超限,不修改\n if (!truncateResult.truncated) return undefined;\n\n // 记录截断\n this.truncateCount++;\n this.logger?.warn('Tool output truncated', {\n toolName,\n strategy: truncateResult.strategy,\n originalLength: truncateResult.originalLength,\n truncatedLength: truncateResult.truncatedLength,\n });\n\n // 持久化完整输出到磁盘,并将文件路径注入截断结果\n const finalOutput = await this.persistAndAnnotate(\n truncateResult.output,\n truncateResult.strategy,\n resultStr,\n truncateResult.originalLength,\n toolName,\n );\n\n // 返回截断后的结果\n return {\n ...result,\n result: finalOutput,\n };\n }\n\n // ========== 内部方法 ==========\n\n private getOptions(toolName: string): TruncateOptions {\n const override = this.config.toolOverrides[toolName];\n return {\n hardLimit: override?.hardLimit ?? this.config.hardLimit,\n fieldLimit: override?.fieldLimit ?? this.config.fieldLimit,\n };\n }\n\n /**\n * 将完整输出持久化到磁盘,并在截断结果中注入文件路径引用。\n *\n * - JSON 结果:在顶层对象中注入 `_outputGuard` 字段(保持 JSON 合法性)\n * - 文本结果:在头部插入提示行(与 shell 工具风格一致)\n *\n * 如果落盘失败(权限、磁盘满等),不注入路径引用,截断结果照常返回。\n */\n private async persistAndAnnotate(\n truncatedOutput: string,\n strategy: string,\n fullOutput: string,\n originalLength: number,\n toolName: string,\n ): Promise<string> {\n // 尝试落盘\n let filePath: string | null;\n let diskContent = fullOutput;\n try {\n const tempDir = join(this.config.workdir, '.agentdev', 'temp');\n const now = new Date();\n const ts = now.getFullYear().toString() +\n String(now.getMonth() + 1).padStart(2, '0') +\n String(now.getDate()).padStart(2, '0') + '-' +\n String(now.getHours()).padStart(2, '0') +\n String(now.getMinutes()).padStart(2, '0') +\n String(now.getSeconds()).padStart(2, '0');\n const suffix = Math.random().toString(36).slice(2, 8);\n const safeToolName = toolName.replace(/[^a-zA-Z0-9_-]/g, '_').slice(0, 30);\n const fileName = `tool-output-${safeToolName}-${ts}-${suffix}.log`;\n filePath = join(tempDir, fileName);\n\n // 尝试 pretty-print JSON 以便 read 工具按行分页\n try {\n const parsed = JSON.parse(fullOutput);\n diskContent = JSON.stringify(parsed, null, 2);\n } catch {\n // 非 JSON 文本,保持原始换行\n }\n\n await mkdir(tempDir, { recursive: true });\n await writeFile(filePath, diskContent, 'utf-8');\n } catch (err) {\n this.logger?.error('Failed to persist truncated output', { error: String(err) });\n filePath = null;\n }\n\n // 落盘失败,原样返回截断结果\n if (!filePath) return truncatedOutput;\n\n const totalKB = Math.round(originalLength / 1024);\n const totalLines = diskContent.split('\\n').length;\n\n // 根据截断策略决定注入方式\n const isJsonStrategy = strategy === 'json-fields' || strategy === 'json-array';\n\n if (isJsonStrategy) {\n // JSON 结果:在顶层注入 _outputGuard 字段\n try {\n const parsed = JSON.parse(truncatedOutput);\n if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {\n parsed._outputGuard = {\n fullOutputPath: filePath,\n originalSize: originalLength,\n originalSizeKB: totalKB,\n originalLines: totalLines,\n };\n return JSON.stringify(parsed);\n }\n } catch {\n // 截断后不是合法 JSON(理论上不应发生,但防御性处理)\n }\n // 如果 JSON 注入失败,回退到文本方式\n }\n\n // 文本结果:在头部插入提示\n const notice =\n `[OutputGuard: full output (${totalKB}KB, ${totalLines} lines) saved to: ${filePath}]\\n` +\n `Use the read tool with offset/limit to access specific portions.\\n`;\n return notice + truncatedOutput;\n }\n}\n","/**\n * OutputGuard 核心截断逻辑\n *\n * 三级级联策略:\n * 1. JSON 字段截断(保结构):解析 JSON → 递归截断长字段值 → 裁剪数组条目 → 重新序列化\n * 2. 行感知 head+tail:按行分割,保留首尾行,中间插入标记\n * 3. 字符级 head+tail:兜底,永不失败\n *\n * 所有截断函数都保证:\n * - 不破坏外层 JSON 信封的合法性(截断发生在 string 值内部)\n * - 截断标记清晰可读,LLM 能理解数据不完整\n * - Unicode 安全(不在多字节字符中间切割)\n */\n\n// ========== 常量 ==========\n\n/** 默认硬限制(安全网触发阈值) */\nexport const DEFAULT_HARD_LIMIT = 50_000;\n\n/** 默认单个字段截断长度(JSON 字段截断时,每个 string 值的上限) */\nexport const DEFAULT_FIELD_LIMIT = 5_000;\n\n/** 截断标记保留预算(从总预算中扣除给标记文本留空间) */\nconst MARKER_BUDGET = 300;\n\n// ========== 公共类型 ==========\n\nexport interface TruncateOptions {\n /** 总体积硬限制 */\n hardLimit?: number;\n /** 单个字符串字段截断长度 */\n fieldLimit?: number;\n}\n\nexport interface TruncateResult {\n /** 截断后的结果字符串 */\n output: string;\n /** 是否发生了截断 */\n truncated: boolean;\n /** 使用的截断策略 */\n strategy: 'none' | 'json-fields' | 'json-array' | 'line-headtail' | 'char-headtail';\n /** 原始长度 */\n originalLength: number;\n /** 截断后长度 */\n truncatedLength: number;\n}\n\n// ========== Unicode 安全工具 ==========\n\n/**\n * 找到不超过 maxBytes 的最后一个完整 UTF-8 字符边界。\n * JavaScript 字符串是 UTF-16,但大部分情况下用码点(code point)判断就够了。\n * 我们用 Array.from 来按 Unicode 码点分割,避免在代理对中间切割。\n */\nfunction safeSliceFromCodePoints(str: string, maxChars: number): string {\n const codePoints = Array.from(str);\n if (codePoints.length <= maxChars) return str;\n return codePoints.slice(0, maxChars).join('');\n}\n\nfunction safeSliceTailFromCodePoints(str: string, maxChars: number): string {\n const codePoints = Array.from(str);\n if (codePoints.length <= maxChars) return str;\n return codePoints.slice(-maxChars).join('');\n}\n\n// ========== 截断标记 ==========\n\nfunction buildMarker(omitted: number, total: number): string {\n const totalKB = Math.round(total / 1024);\n return `\\n[... truncated: ${omitted} chars omitted (${totalKB}KB total) ...]\\n`;\n}\n\nfunction buildFieldMarker(omitted: number): string {\n return ` [...${omitted} chars omitted...] `;\n}\n\n// ========== 策略 1: JSON 字段截断 ==========\n\n/**\n * 递归遍历 JSON 节点,截断超长的 string 值。\n * 不改变结构(key、数组长度、嵌套层级不变),只缩短 string 叶子值。\n */\nexport function truncateJsonNode(node: unknown, fieldLimit: number): unknown {\n if (typeof node === 'string') {\n if (node.length <= fieldLimit) return node;\n const headSize = Math.floor(fieldLimit * 0.6);\n const tailSize = Math.floor(fieldLimit * 0.3);\n const head = safeSliceFromCodePoints(node, headSize);\n const tail = safeSliceTailFromCodePoints(node, tailSize);\n const omitted = node.length - head.length - tail.length;\n return head + buildFieldMarker(omitted) + tail;\n }\n\n if (Array.isArray(node)) {\n return node.map((item) => truncateJsonNode(item, fieldLimit));\n }\n\n if (node !== null && typeof node === 'object') {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(node)) {\n result[key] = truncateJsonNode(value, fieldLimit);\n }\n return result;\n }\n\n // number, boolean, null, undefined, bigint, symbol, function → 原样返回\n return node;\n}\n\n/**\n * 裁剪数组:保留头部和尾部的元素,中间用标记元素替代。\n *\n * 标记元素是一个字符串(合法 JSON 值),格式为 `<<N items omitted>>`。\n */\nexport function shrinkArray(arr: unknown[], targetBudget: number): unknown[] {\n const serialized = JSON.stringify(arr);\n if (serialized.length <= targetBudget) return arr;\n\n const halfBudget = Math.floor(targetBudget / 2);\n const head: unknown[] = [];\n const tail: unknown[] = [];\n let headSize = 0;\n let tailSize = 0;\n\n // 从头部收集\n for (const item of arr) {\n const s = JSON.stringify(item);\n if (headSize + s.length + 2 > halfBudget) break; // +2 for \", \"\n head.push(item);\n headSize += s.length + 2;\n }\n\n // 从尾部收集\n for (let i = arr.length - 1; i >= 0; i--) {\n if (head.length + tail.length >= arr.length) break; // 防止重叠\n const s = JSON.stringify(arr[i]);\n if (tailSize + s.length + 2 > halfBudget) break;\n tail.unshift(arr[i]);\n tailSize += s.length + 2;\n }\n\n const omitted = arr.length - head.length - tail.length;\n if (omitted <= 0) return arr;\n\n return [...head, `<<${omitted} items omitted>>`, ...tail];\n}\n\n/**\n * 在 JSON 对象树中寻找最长的数组并裁剪。\n * 递归遍历所有对象和数组,对每个数组尝试裁剪。\n */\nfunction shrinkLongestArrays(node: unknown, targetBudget: number): unknown {\n if (Array.isArray(node)) {\n // 先递归处理子节点\n let processed = node.map((item) => shrinkLongestArrays(item, targetBudget));\n // 再尝试裁剪当前数组\n processed = shrinkArray(processed, targetBudget);\n return processed;\n }\n\n if (node !== null && typeof node === 'object') {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(node)) {\n result[key] = shrinkLongestArrays(value, targetBudget);\n }\n return result;\n }\n\n return node;\n}\n\n/**\n * 尝试 JSON 字段截断策略。\n * 返回截断后的字符串,或 null(表示不是 JSON 或截断后仍然超限)。\n */\nexport function tryJsonTruncate(\n str: string,\n hardLimit: number,\n fieldLimit: number,\n): { output: string; strategy: 'json-fields' | 'json-array' } | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(str);\n } catch {\n return null; // 不是合法 JSON\n }\n\n // 只处理 object/array,原始值(string/number/boolean/null)不在此策略范围\n if (parsed === null || typeof parsed !== 'object') {\n return null;\n }\n\n // Pass 1: 字段值截断\n const truncated = truncateJsonNode(parsed, fieldLimit);\n let serialized = JSON.stringify(truncated);\n\n if (serialized.length <= hardLimit) {\n return { output: serialized, strategy: 'json-fields' };\n }\n\n // Pass 2: 数组裁剪(逐步收紧 budget 直到达标)\n let budget = hardLimit - MARKER_BUDGET;\n let withShrunkArrays = truncateJsonNode(parsed, fieldLimit); // 从原始重新开始\n while (budget > 1000) {\n withShrunkArrays = shrinkLongestArrays(withShrunkArrays, budget);\n serialized = JSON.stringify(withShrunkArrays);\n if (serialized.length <= hardLimit) {\n return { output: serialized, strategy: 'json-array' };\n }\n budget = Math.floor(budget * 0.7); // 收紧 30%\n }\n\n // JSON 策略无法压到目标以下,交由上层回退\n return null;\n}\n\n// ========== 策略 2: 行感知 head+tail ==========\n\n/**\n * 按行分割,保留首尾行,中间插入截断标记。\n * 适合多行文本(shell 输出、日志、格式化文本、pretty-printed JSON)。\n */\nexport function truncateByLines(str: string, limit: number): string {\n if (str.length <= limit) return str;\n\n const lines = str.split('\\n');\n const budget = limit - MARKER_BUDGET;\n const halfBudget = Math.floor(budget / 2);\n\n const headLines: string[] = [];\n const tailLines: string[] = [];\n let headSize = 0;\n let tailSize = 0;\n\n for (const line of lines) {\n const lineLen = line.length + 1; // +1 for \\n\n if (headSize + lineLen > halfBudget) break;\n headLines.push(line);\n headSize += lineLen;\n }\n\n for (let i = lines.length - 1; i >= 0; i--) {\n if (headLines.length + tailLines.length >= lines.length) break; // 防止重叠\n const lineLen = lines[i].length + 1;\n if (tailSize + lineLen > halfBudget) break;\n tailLines.unshift(lines[i]);\n tailSize += lineLen;\n }\n\n const omittedLines = lines.length - headLines.length - tailLines.length;\n const omittedChars = str.length - headLines.join('\\n').length - tailLines.join('\\n').length - 1;\n\n const marker = buildMarker(Math.max(0, omittedChars), str.length);\n // 在标记中也提及行数,帮助 LLM 理解规模\n const lineInfo = omittedLines > 0 ? ` (${omittedLines} of ${lines.length} lines)` : '';\n\n return (\n headLines.join('\\n') +\n marker.slice(0, -1) + lineInfo + '\\n' +\n tailLines.join('\\n')\n );\n}\n\n// ========== 策略 3: 字符级 head+tail(兜底) ==========\n\n/**\n * 纯字符级 head+tail 截断。\n * 永不失败,但不保证行/结构完整性。\n */\nexport function truncateHeadTail(str: string, limit: number): string {\n const budget = limit - MARKER_BUDGET;\n const headSize = Math.floor(budget * 0.6);\n const tailSize = budget - headSize;\n\n const head = safeSliceFromCodePoints(str, headSize);\n const tail = safeSliceTailFromCodePoints(str, tailSize);\n const omitted = str.length - head.length - tail.length;\n\n return head + buildMarker(omitted, str.length) + tail;\n}\n\n// ========== 主入口:级联截断 ==========\n\n/**\n * 对工具结果字符串执行级联截断。\n *\n * 策略优先级:\n * 1. 如果不超限,直接返回\n * 2. 尝试 JSON 字段截断(保结构、保 JSON 合法性)\n * 3. 尝试行感知 head+tail(保行边界)\n * 4. 字符级 head+tail(兜底)\n *\n * 返回包含截断结果和元信息的 TruncateResult。\n */\nexport function truncateOutput(\n str: string,\n options?: TruncateOptions,\n): TruncateResult {\n const hardLimit = options?.hardLimit ?? DEFAULT_HARD_LIMIT;\n const fieldLimit = options?.fieldLimit ?? DEFAULT_FIELD_LIMIT;\n const originalLength = str.length;\n\n // 不超限,直接返回\n if (originalLength <= hardLimit) {\n return {\n output: str,\n truncated: false,\n strategy: 'none',\n originalLength,\n truncatedLength: originalLength,\n };\n }\n\n // 策略 1: JSON 字段截断\n const jsonResult = tryJsonTruncate(str, hardLimit, fieldLimit);\n if (jsonResult !== null) {\n return {\n output: jsonResult.output,\n truncated: true,\n strategy: jsonResult.strategy,\n originalLength,\n truncatedLength: jsonResult.output.length,\n };\n }\n\n // 策略 2: 行感知 head+tail\n // 仅当文本有足够的行数时使用(否则行分割本身就是开销)\n const lineCount = str.split('\\n').length;\n if (lineCount >= 5) {\n const lineResult = truncateByLines(str, hardLimit);\n if (lineResult.length <= hardLimit) {\n return {\n output: lineResult,\n truncated: true,\n strategy: 'line-headtail',\n originalLength,\n truncatedLength: lineResult.length,\n };\n }\n }\n\n // 策略 3: 字符级 head+tail(兜底,永不失败)\n const fallback = truncateHeadTail(str, hardLimit);\n return {\n output: fallback,\n truncated: true,\n strategy: 'char-headtail',\n originalLength,\n truncatedLength: fallback.length,\n };\n}\n","/**\r\n * 配置加载\r\n * 从 config 目录读取 JSON 配置文件\r\n *\r\n * 提供两种方式:\r\n * - loadConfig() - 异步加载(用于特殊场景)\r\n * - loadConfigSync() - 同步加载(推荐,用于 Agent 构造)\r\n */\r\n\r\nimport { readFile, readdir } from 'fs/promises';\r\nimport { readFileSync, readdirSync, existsSync } from 'fs';\r\nimport { resolve, join } from 'path';\r\nimport { cwd } from 'process';\r\n\r\n/**\r\n * 自定义请求头条目\r\n * - valueMode 'static': 使用 value 原样\r\n * - valueMode 'uuid': 每次请求生成新的 UUID v4\r\n * - valueMode 'random': 每次请求生成新的随机数\r\n */\r\nexport interface CustomHeaderEntry {\r\n key: string;\r\n value: string;\r\n valueMode?: 'static' | 'uuid' | 'random';\r\n}\r\n\r\n/**\r\n * 思考力度档位\r\n *\r\n * 各厂商支持的值不同,配置层接受所有值的并集,\r\n * 各 provider 自行筛选自己支持的值,不支持的忽略。\r\n */\r\nexport type ThinkingEffort =\r\n | 'none' // 关闭思考(Anthropic → thinking.disabled,OpenAI → effort: none)\r\n | 'minimal' // OpenAI 专属\r\n | 'low' // 两家通用\r\n | 'medium' // 两家通用\r\n | 'high' // 两家通用\r\n | 'xhigh' // 两家通用\r\n | 'max'; // Anthropic 专属\r\n\r\n/** OpenAI 支持的思考力度档位(供 UI 和校验使用) */\r\nexport const OPENAI_THINKING_EFFORTS: readonly ThinkingEffort[] = [\r\n 'none', 'minimal', 'low', 'medium', 'high', 'xhigh',\r\n];\r\n\r\n/** Anthropic 支持的思考力度档位(供 UI 和校验使用) */\r\nexport const ANTHROPIC_THINKING_EFFORTS: readonly ThinkingEffort[] = [\r\n 'none', 'low', 'medium', 'high', 'xhigh', 'max',\r\n];\r\n\r\n/**\r\n * 统一配置类型\r\n * 字段允许冗余,各 LLM 实现只取自己需要的\r\n */\r\nexport interface ModelConfig {\r\n provider: 'openai' | 'anthropic' | string;\r\n apiKey: string;\r\n model: string;\r\n baseUrl?: string;\r\n maxTokens?: number;\r\n thinkingEffort?: ThinkingEffort;\r\n thinkingBudgetTokens?: number;\r\n thinkingKeepTurns?: number;\r\n providerOptions?: Record<string, unknown>;\r\n /** 追加到每次 LLM API 请求的自定义请求头 */\r\n customHeaders?: CustomHeaderEntry[];\r\n /** OpenAI 专用接口面:chat / responses */\r\n apiSurface?: 'chat' | 'responses';\r\n /** Responses 后端契约。codex 用于 ChatGPT 管理的 Codex Responses 端点。 */\r\n responsesProfile?: 'standard' | 'codex';\r\n /** 是否启用视觉(多模态图片输入)支持,默认 false */\r\n vision?: boolean;\r\n /**\r\n * 单次模型请求的最大重试次数(不含首次)。\r\n * 缺省时由 LLM 工厂自动填充 DEFAULT_MODEL_MAX_RETRIES。\r\n */\r\n maxRetries?: number;\r\n /**\r\n * 单次模型调用的整体时限(毫秒,覆盖建连、排队与流式传输全程)。\r\n * 超时以 AbortError 中止本次调用,交由上层按中断处理(不重试)。\r\n * 缺省时由 LLM 工厂自动填充 DEFAULT_MODEL_TIMEOUT_MS。\r\n */\r\n timeoutMs?: number;\r\n // 未来可扩展\r\n region?: string;\r\n projectId?: string;\r\n}\r\n\r\nexport interface AgentConfigFile {\r\n defaultModel: ModelConfig;\r\n agent: {\r\n maxTurns: number;\r\n temperature: number;\r\n };\r\n}\r\n\r\n/**\r\n * 获取项目根目录\r\n *\r\n * 使用 process.cwd() 而不是模块路径,以支持 npm link 环境\r\n */\r\nfunction getProjectRoot(): string {\r\n return cwd();\r\n}\r\n\r\n/**\r\n * 读取配置文件(异步版本)\r\n * @param name 配置文件名(不含路径和扩展名),默认 'default'\r\n */\r\nexport async function loadConfig(name: string = 'default'): Promise<AgentConfigFile> {\r\n const projectRoot = getProjectRoot();\r\n const configDir = join(projectRoot, 'config');\r\n const configPath = resolve(configDir, `${name}.json`);\r\n\r\n if (!existsSync(configPath)) {\r\n throw new Error(\r\n `配置文件不存在: ${configPath}\\n` +\r\n `请在项目目录下创建 config/${name}.json 文件,\\n` +\r\n `或通过 config.llm 参数直接传入 LLM 实例。`\r\n );\r\n }\r\n\r\n const content = await readFile(configPath, 'utf-8');\r\n const raw = JSON.parse(content);\r\n\r\n // 替换环境变量 ${VAR_NAME}\r\n return replaceEnvVars(raw) as AgentConfigFile;\r\n}\r\n\r\n/**\r\n * 读取配置文件(同步版本,推荐用于 Agent 构造)\r\n * @param name 配置文件名(不含路径和扩展名),默认 'default'\r\n */\r\nexport function loadConfigSync(name: string = 'default'): AgentConfigFile {\r\n const projectRoot = getProjectRoot();\r\n const configDir = join(projectRoot, 'config');\r\n const configPath = resolve(configDir, `${name}.json`);\r\n\r\n if (!existsSync(configPath)) {\r\n throw new Error(\r\n `配置文件不存在: ${configPath}\\n` +\r\n `请在项目目录下创建 config/${name}.json 文件,\\n` +\r\n `或通过 config.llm 参数直接传入 LLM 实例。`\r\n );\r\n }\r\n\r\n const content = readFileSync(configPath, 'utf-8');\r\n const raw = JSON.parse(content);\r\n\r\n // 替换环境变量 ${VAR_NAME}\r\n return replaceEnvVars(raw) as AgentConfigFile;\r\n}\r\n\r\n/**\r\n * 列出所有可用的配置文件\r\n */\r\nexport async function listConfigs(): Promise<string[]> {\r\n const projectRoot = getProjectRoot();\r\n const configDir = join(projectRoot, 'config');\r\n\r\n try {\r\n const files = await readdir(configDir);\r\n return files\r\n .filter(f => f.endsWith('.json'))\r\n .map(f => f.replace('.json', ''));\r\n } catch {\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * 递归替换对象中的环境变量\r\n */\r\nfunction replaceEnvVars(obj: any): any {\r\n if (typeof obj === 'string') {\r\n // 匹配 ${VAR_NAME} 格式\r\n return obj.replace(/\\$\\{([^}]+)\\}/g, (_, varName) => {\r\n return process.env[varName] || '';\r\n });\r\n }\r\n\r\n if (Array.isArray(obj)) {\r\n return obj.map(replaceEnvVars);\r\n }\r\n\r\n if (obj && typeof obj === 'object') {\r\n const result: any = {};\r\n for (const [key, value] of Object.entries(obj)) {\r\n result[key] = replaceEnvVars(value);\r\n }\r\n return result;\r\n }\r\n\r\n return obj;\r\n}\r\n","/**\r\n * Feature 配置队列解析(config queue)\r\n *\r\n * 框架不认识\"层\"(global/agent/dir/profile 都是产品语义),只接受一个有序\r\n * 配置数组,按序 deep merge 出最终配置,并同步产出 provenance 与 warnings。\r\n *\r\n * 本模块是队列 merge 与 provenance 的唯一权威实现:纯函数、无 IO、无 logger、\r\n * 无进程状态;warning 以返回值交付,由调用方决定记日志方式。\r\n *\r\n * merge 规范(D5):\r\n * 1. 对象:递归合并(同 key 且两侧均为普通对象时深入)\r\n * 2. 标量:替换(后层胜)\r\n * 3. 数组:整体替换,绝不按索引/按 key 合并\r\n * 4. null:视为\"删除该字段\",从合并结果移除并产生 warning\r\n * 5. 未出现的 key:继承(不写入即不覆盖)\r\n * 6. 空队列返回空结果\r\n */\r\n\r\n/**\r\n * 单个 feature 的配置对象形态。顶层 key = featureName(如 'lsp'、'shell'),\r\n * 值为该 feature 的配置对象。\r\n */\r\nexport type FeatureConfig = Record<string, unknown>;\r\n\r\n/**\r\n * 某个点路径字段的来源信息。\r\n */\r\nexport interface ConfigProvenanceEntry {\r\n /** 该字段最终生效值 */\r\n value: unknown;\r\n /** 队列中最后写入该字段的元素索引 */\r\n sourceIndex: number;\r\n}\r\n\r\n/**\r\n * 解析过程中产生的警告。第一版只有 null 删除一种。\r\n */\r\nexport interface ConfigWarning {\r\n /** 点路径,如 'lsp.typescript.mode' */\r\n fieldPath: string;\r\n /** 触发该警告的队列元素索引 */\r\n layerIndex: number;\r\n kind: 'null-removed';\r\n message: string;\r\n}\r\n\r\n/**\r\n * resolveFeatureConfig 的返回结构。provenance 的 key 是完整点路径\r\n * (含 featureName 前缀)。\r\n */\r\nexport interface ResolvedFeatureConfig {\r\n /** 最终合并配置 */\r\n merged: FeatureConfig;\r\n /** key = 完整点路径(如 'lsp.typescript.mode') */\r\n provenance: Record<string, ConfigProvenanceEntry>;\r\n warnings: ConfigWarning[];\r\n}\r\n\r\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\r\n return typeof value === 'object' && value !== null && !Array.isArray(value);\r\n}\r\n\r\n/** 整体赋值前深拷贝,保证输入队列不被结果持有引用(纯函数纪律)。 */\r\nfunction copyValue(value: unknown): unknown {\r\n if (Array.isArray(value)) {\r\n return value.map(copyValue);\r\n }\r\n if (isPlainObject(value)) {\r\n const out: Record<string, unknown> = {};\r\n for (const [k, v] of Object.entries(value)) {\r\n out[k] = copyValue(v);\r\n }\r\n return out;\r\n }\r\n return value;\r\n}\r\n\r\n/**\r\n * 把有序配置队列按序 deep merge 为最终配置。\r\n *\r\n * @param queue 有序配置数组,顶层按 featureName 分桶;越靠后优先级越高\r\n */\r\nexport function resolveFeatureConfig(queue: FeatureConfig[]): ResolvedFeatureConfig {\r\n const merged: FeatureConfig = {};\r\n const provenance: Record<string, ConfigProvenanceEntry> = {};\r\n const warnings: ConfigWarning[] = [];\r\n\r\n const removeProvenanceSubtree = (path: string): void => {\r\n delete provenance[path];\r\n const prefix = `${path}.`;\r\n for (const key of Object.keys(provenance)) {\r\n if (key.startsWith(prefix)) {\r\n delete provenance[key];\r\n }\r\n }\r\n };\r\n\r\n // 单次遍历:merge 与 provenance 同源(D6),逐层把 layerValue 并入 target\r\n const applyLayer = (\r\n target: Record<string, unknown>,\r\n layerValue: Record<string, unknown>,\r\n prefix: string,\r\n layerIndex: number,\r\n ): void => {\r\n for (const [key, incoming] of Object.entries(layerValue)) {\r\n const path = prefix ? `${prefix}.${key}` : key;\r\n\r\n // 规范 4:null 按删除处理并产生 warning\r\n if (incoming === null) {\r\n delete target[key];\r\n removeProvenanceSubtree(path);\r\n warnings.push({\r\n fieldPath: path,\r\n layerIndex,\r\n kind: 'null-removed',\r\n message: `字段 '${path}' 在第 ${layerIndex} 层被置为 null,已从合并结果中删除`,\r\n });\r\n continue;\r\n }\r\n\r\n const existing = target[key];\r\n\r\n // 规范 1:两侧均为普通对象时递归合并\r\n if (isPlainObject(existing) && isPlainObject(incoming)) {\r\n applyLayer(existing, incoming, path, layerIndex);\r\n continue;\r\n }\r\n\r\n if (isPlainObject(incoming)) {\r\n // 新出现的对象分支:建新容器后继续深入;\r\n // 若该路径此前是叶子值,先清掉其 provenance 再替换\r\n removeProvenanceSubtree(path);\r\n const branch: Record<string, unknown> = {};\r\n target[key] = branch;\r\n applyLayer(branch, incoming, path, layerIndex);\r\n continue;\r\n }\r\n\r\n // 规范 2 / 3:标量与数组整体替换(数组绝不按索引合并)\r\n target[key] = copyValue(incoming);\r\n provenance[path] = { value: target[key], sourceIndex: layerIndex };\r\n }\r\n };\r\n\r\n queue.forEach((layer, layerIndex) => {\r\n if (isPlainObject(layer)) {\r\n applyLayer(merged, layer, '', layerIndex);\r\n }\r\n });\r\n\r\n return { merged, provenance, warnings };\r\n}\r\n","/**\r\n * 渲染配置\r\n * 定义工具渲染模板、样式和默认映射\r\n */\r\n\r\nimport type { ToolRenderConfig, RenderTemplateItem, RenderTemplateFn } from './types.js';\r\n\r\n// ============= 类型定义 =============\r\nexport interface RenderTemplate {\r\n /** 调用时的渲染模板 */\r\n call: RenderTemplateItem;\r\n /** 结果时的渲染模板 */\r\n result: RenderTemplateItem;\r\n}\r\n\r\n// ============= 模板定义 =============\r\n/**\r\n * 渲染模板集合\r\n * 包含所有预定义的渲染模板(字符串模板和函数模板)\r\n */\r\nexport const RENDER_TEMPLATES: Record<string, RenderTemplate> = {\r\n // ----- 文件操作模板 -----\r\n 'file': {\r\n call: '<div class=\"bash-command\">Read <span class=\"file-path\">{{path}}</span></div>',\r\n result: (data) => `<pre class=\"bash-output\" style=\"max-height:300px;\">${escapeHtml(data)}</pre>`\r\n },\r\n\r\n 'file-write': {\r\n call: '<div class=\"bash-command\">Write <span class=\"file-path\">{{path}}</span></div>',\r\n result: (data) => `<div style=\"color:var(--success-color)\">✓ File written successfully</div>`\r\n },\r\n\r\n 'file-list': {\r\n call: '<div class=\"bash-command\">List <span class=\"file-path\">{{path}}</span></div>',\r\n result: (data) => {\r\n const files = (data || '').split('\\n').filter((f: string) => f);\r\n return `<div style=\"display:grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap:4px; font-family:monospace; font-size:12px;\">\r\n ${files.map((f: string) => `<div style=\"color:var(--text-primary);\">${escapeHtml(f)}</div>`).join('')}\r\n </div>`;\r\n }\r\n },\r\n\r\n // ----- 命令执行模板 -----\r\n 'command': {\r\n call: '<div class=\"bash-command\">> {{command}}</div>',\r\n result: (data) => `<pre class=\"bash-output\">${escapeHtml(data)}</pre>`\r\n },\r\n\r\n // ----- 网络请求模板 -----\r\n 'web': {\r\n call: '<div>GET <a href=\"{{url}}\" target=\"_blank\" style=\"color:var(--accent-color)\">{{url}}</a></div>',\r\n result: (data) => `<div style=\"font-size:12px; opacity:0.8;\">Fetched ${String(data).length} chars</div>`\r\n },\r\n\r\n // ----- 数学计算模板 -----\r\n 'math': {\r\n call: '<div class=\"bash-command\">{{expression}}</div>',\r\n result: (data) => `<div class=\"bash-command\" style=\"color:#d2a8ff\">= ${escapeHtml(data)}</div>`\r\n },\r\n\r\n // ----- 内置类型 -----\r\n 'json': {\r\n call: (args) => `<pre style=\"margin:0; font-size:12px;\">${escapeHtml(JSON.stringify(args, null, 2))}</pre>`,\r\n result: (data) => {\r\n const displayData = typeof data === 'object' ? JSON.stringify(data, null, 2) : data;\r\n return `<pre class=\"bash-output\">${escapeHtml(displayData)}</pre>`;\r\n }\r\n },\r\n\r\n // ----- Skills 工具 -----\r\n 'skill': {\r\n call: '<div class=\"bash-command\">Skill <span class=\"file-path\">{{skill}}</span></div>',\r\n result: (data) => `<pre class=\"bash-output\" style=\"max-height:400px;\">${escapeHtml(data)}</pre>`\r\n },\r\n\r\n // ----- Agent Spawn -----\r\n 'agent-spawn': {\r\n call: '<div class=\"bash-command\">Spawn <span class=\"pattern\">{{type}}</span> agent: {{instruction}}</div>',\r\n result: (data) => {\r\n if (data.error) {\r\n return `<div style=\"color:var(--error-color)\">✗ ${data.error}</div>`;\r\n }\r\n return `<div style=\"color:var(--success-color)\">✓ Agent ${data.agentId} (${data.type}) completed</div>`;\r\n }\r\n },\r\n\r\n // ----- Agent List -----\r\n 'agent-list': {\r\n call: '<div class=\"bash-command\">List agents</div>',\r\n result: (data) => {\r\n if (!data.agents || data.agents.length === 0) {\r\n return `<div style=\"color:var(--warning-color)\">No agents found</div>`;\r\n }\r\n return `<div style=\"font-size:12px; color:var(--text-secondary);\">Total: ${data.total} | Running: ${data.running}</div>`;\r\n }\r\n },\r\n\r\n // ----- Agent Send -----\r\n 'agent-send': {\r\n call: '<div class=\"bash-command\">Send to <span class=\"pattern\">{{agentId}}</span></div>',\r\n result: (data) => {\r\n if (data.error) {\r\n return `<div style=\"color:var(--error-color)\">✗ ${data.error}</div>`;\r\n }\r\n return `<div style=\"color:var(--success-color)\">✓ Message sent</div>`;\r\n }\r\n },\r\n\r\n // ----- Agent Close -----\r\n 'agent-close': {\r\n call: '<div class=\"bash-command\">Close <span class=\"pattern\">{{agentId}}</span></div>',\r\n result: (data) => {\r\n if (data.error) {\r\n return `<div style=\"color:var(--error-color)\">✗ ${data.error}</div>`;\r\n }\r\n return `<div style=\"color:var(--success-color)\">✓ ${data.message || 'Agent closed'}</div>`;\r\n }\r\n },\r\n\r\n // ----- Safe Trash Delete -----\r\n 'trash-delete': {\r\n call: (args) => {\r\n const paths = args.paths || [];\r\n const pathList = Array.isArray(paths) ? paths : [paths];\r\n const displayPaths = pathList.slice(0, 3).map((p: string) => escapeHtml(p)).join(', ');\r\n const more = pathList.length > 3 ? ` +${pathList.length - 3} more` : '';\r\n return `<div class=\"bash-command\">Safe delete <span class=\"file-path\">${displayPaths}${more}</span></div>`;\r\n },\r\n result: (data) => {\r\n const movedCount = data.moved_count || 0;\r\n const failed = data.failed || [];\r\n const failedCount = failed.length;\r\n\r\n if (movedCount > 0 && failedCount === 0) {\r\n return `<div style=\"color:var(--success-color)\">✓ Moved ${movedCount} item(s) to trash</div>`;\r\n }\r\n if (movedCount > 0) {\r\n return `<div style=\"color:var(--warning-color)\">⚠ Moved ${movedCount}, ${failedCount} failed</div>`;\r\n }\r\n return `<div style=\"color:var(--text-secondary)\">No files moved</div>`;\r\n }\r\n },\r\n\r\n // ----- Safe Trash List -----\r\n 'trash-list': {\r\n call: '<div class=\"bash-command\">List trash</div>',\r\n result: (data) => {\r\n const total = data.total || 0;\r\n const files = data.files || [];\r\n if (total === 0) {\r\n return `<div style=\"color:var(--text-secondary)\">Trash is empty</div>`;\r\n }\r\n return `<div style=\"font-size:12px; color:var(--text-secondary);\">${total} item(s) in trash</div>`;\r\n }\r\n },\r\n\r\n // ----- Safe Trash Restore -----\r\n 'trash-restore': {\r\n call: (args) => `<div class=\"bash-command\">Restore <span class=\"pattern\">${escapeHtml(args.target)}</span></div>`,\r\n result: (data) => {\r\n const restored = data.restored || [];\r\n const failed = data.failed || [];\r\n const restoredCount = restored.length;\r\n const failedCount = failed.length;\r\n\r\n if (restoredCount > 0 && failedCount === 0) {\r\n return `<div style=\"color:var(--success-color)\">✓ Restored ${restoredCount} item(s)</div>`;\r\n }\r\n if (restoredCount > 0 || failedCount > 0) {\r\n return `<div style=\"color:var(--warning-color)\">Restored ${restoredCount}, ${failedCount} failed</div>`;\r\n }\r\n return `<div style=\"color:var(--text-secondary)\">Nothing restored</div>`;\r\n }\r\n },\r\n} as const;\r\n\r\n// ============= 默认映射 =============\r\n/**\r\n * 系统工具的默认渲染模板映射\r\n * 工具名称 -> 模板名称\r\n */\r\nexport const SYSTEM_RENDER_MAP: Record<string, string> = {\r\n // ===== 系统工具 =====\r\n // 文件系统工具(旧版,已废弃)\r\n 'read_file': 'file',\r\n 'write_file': 'file-write',\r\n 'list_directory': 'file-list',\r\n\r\n // Shell 工具\r\n 'run_shell_command': 'command',\r\n 'bash': 'command',\r\n 'shell': 'command',\r\n\r\n // Safe Trash 工具\r\n 'safe_trash_delete': 'trash-delete',\r\n 'safe_trash_list': 'trash-list',\r\n 'safe_trash_restore': 'trash-restore',\r\n\r\n // Web 工具\r\n 'web_fetch': 'web',\r\n\r\n // Math 工具\r\n 'calculator': 'math',\r\n\r\n // Skills 工具\r\n 'invoke_skill': 'skill',\r\n\r\n // Agent 工具\r\n 'spawn_agent': 'agent-spawn',\r\n 'list_agents': 'agent-list',\r\n 'send_to_agent': 'agent-send',\r\n 'close_agent': 'agent-close',\r\n} as const;\r\n\r\n// ============= 工具显示名称映射 =============\r\n/**\r\n * 工具显示名称(用于UI展示)\r\n */\r\nexport const TOOL_DISPLAY_NAMES: Record<string, string> = {\r\n // ===== 系统工具 =====\r\n 'run_shell_command': 'Bash',\r\n 'bash': 'Bash',\r\n 'shell': 'Bash',\r\n 'read_file': 'Read File',\r\n 'write_file': 'Write File',\r\n 'list_directory': 'LS',\r\n 'web_fetch': 'Web',\r\n 'calculator': 'Calc',\r\n 'invoke_skill': 'Invoke Skill',\r\n 'spawn_agent': 'Spawn Agent',\r\n 'list_agents': 'List Agents',\r\n 'send_to_agent': 'Send to Agent',\r\n 'close_agent': 'Close Agent',\r\n\r\n // ===== Safe Trash 工具 =====\r\n 'safe_trash_delete': 'Safe Delete',\r\n 'safe_trash_list': 'Trash List',\r\n 'safe_trash_restore': 'Restore',\r\n\r\n // ===== Opencode 工具 =====\r\n 'read': 'Read',\r\n 'write': 'Write',\r\n 'edit': 'Edit',\r\n 'glob': 'Glob',\r\n 'grep': 'Grep',\r\n 'ls': 'LS',\r\n} as const;\r\n\r\n// ============= 辅助函数 =============\r\n/**\r\n * HTML 转义\r\n */\r\nfunction escapeHtml(text: any): string {\r\n const str = String(text);\r\n const map: Record<string, string> = {\r\n '&': '&',\r\n '<': '<',\r\n '>': '>',\r\n '\"': '"',\r\n \"'\": '''\r\n };\r\n return str.replace(/[&<>\"']/g, m => map[m]);\r\n}\r\n\r\n// ============= 模板引擎 =============\r\n/**\r\n * 简单的字符串模板插值\r\n * 支持 {{key}} 语法\r\n */\r\nexport function interpolateTemplate(template: string, data: Record<string, any>): string {\r\n return template.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key) => {\r\n const value = data[key];\r\n return value !== undefined ? String(value) : `{{${key}}}`;\r\n });\r\n}\r\n\r\n/**\r\n * 应用渲染模板\r\n */\r\nexport function applyTemplate(\r\n template: RenderTemplateItem,\r\n data: Record<string, any>,\r\n success = true\r\n): string {\r\n if (typeof template === 'function') {\r\n return template(data, success);\r\n }\r\n return interpolateTemplate(template, data);\r\n}\r\n\r\n// ============= 动态模板加载 =============\r\n/**\r\n * 从文件加载渲染模板\r\n * @param toolPath 工具路径(相对于项目根目录)\r\n */\r\nexport async function loadRenderTemplate(\r\n toolPath: string\r\n): Promise<RenderTemplate | undefined> {\r\n try {\r\n // 构建模板文件路径:工具目录 + .render.ts\r\n const templatePath = toolPath + '.render.ts';\r\n\r\n // 动态导入模板模块\r\n const module = await import(templatePath);\r\n\r\n // 模块应导出 default 或 render 函数返回 RenderTemplate\r\n if (module.default && typeof module.default === 'object') {\r\n return module.default as RenderTemplate;\r\n }\r\n if (module.render && typeof module.render === 'function') {\r\n return await module.render();\r\n }\r\n\r\n return undefined;\r\n } catch {\r\n // 文件不存在或导入失败,返回 undefined\r\n return undefined;\r\n }\r\n}\r\n\r\n// ============= 导出合并函数 =============\r\n/**\r\n * 获取工具的渲染配置(合并默认值)\r\n */\r\nexport function getToolRenderConfig(\r\n toolName: string,\r\n customRender?: ToolRenderConfig\r\n): ToolRenderConfig {\r\n // 优先级:自定义配置 > 系统默认映射 > 'json'\r\n const systemDefault = SYSTEM_RENDER_MAP[toolName];\r\n const defaultTemplate = systemDefault || 'json';\r\n\r\n return {\r\n call: customRender?.call || defaultTemplate,\r\n result: customRender?.result || defaultTemplate,\r\n };\r\n}\r\n\r\n/**\r\n * 获取工具的渲染模板\r\n */\r\nexport function getToolRenderTemplate(toolName: string, customRender?: ToolRenderConfig): RenderTemplate {\r\n const config = getToolRenderConfig(toolName, customRender);\r\n\r\n // 处理 call 模板\r\n let callTemplate: RenderTemplateItem;\r\n if (typeof config.call === 'object' && config.call !== null) {\r\n // 内联模板\r\n callTemplate = config.call.call;\r\n } else {\r\n // 字符串引用\r\n const callTemplateName = config.call || 'json';\r\n callTemplate = RENDER_TEMPLATES[callTemplateName]?.call || RENDER_TEMPLATES['json'].call;\r\n }\r\n\r\n // 处理 result 模板\r\n let resultTemplate: RenderTemplateItem;\r\n if (typeof config.result === 'object' && config.result !== null) {\r\n // 内联模板\r\n resultTemplate = config.result.result;\r\n } else {\r\n // 字符串引用\r\n const resultTemplateName = config.result || 'json';\r\n resultTemplate = RENDER_TEMPLATES[resultTemplateName]?.result || RENDER_TEMPLATES['json'].result;\r\n }\r\n\r\n return {\r\n call: callTemplate,\r\n result: resultTemplate,\r\n };\r\n}\r\n\r\n/**\r\n * 获取工具显示名称\r\n */\r\nexport function getToolDisplayName(toolName: string): string {\r\n return TOOL_DISPLAY_NAMES[toolName] || toolName;\r\n}\r\n","/**\n * 提示词模板系统 - 核心类型定义\n */\n\n/**\n * 模板源\n * - string: 硬编码字符串\n * - { file: string }: 文件路径\n * - [dataSourceName: string]: 数据源名称(如 skills, tasks 等)\n * - TemplateComposer: 组合模板\n *\n * @example\n * ```typescript\n * // 静态字符串\n * 'Hello {{name}}'\n *\n * // 文件\n * { file: 'prompts/system.md' }\n *\n * // 数据源(列表渲染)\n * { skills: '- **{{name}}**: {{description}}' }\n * { tasks: '- [{{title}}](#{{id}}) ({{priority}})' }\n *\n * // 条件渲染\n * { conditional: { part: { file: 'advanced.md' }, condition: (ctx) => ctx.advanced } }\n * ```\n */\nexport type TemplateSource =\n | string\n | { file: string }\n | { conditional: ConditionalSource }\n | { [dataSourceName: string]: string } // 数据源 -> 模板\n | import('./composer.js').TemplateComposer;\n\n/**\n * 条件源配置\n */\nexport interface ConditionalSource {\n /** 条件模板源 */\n part: TemplateSource;\n /** 条件函数(true 时渲染) */\n condition: (context: PlaceholderContext) => boolean;\n}\n\n/**\n * 占位符上下文 - 变量替换的键值对\n * 支持原始类型和复杂对象(用于数据源渲染)\n */\nexport type PlaceholderContext = Record<string, string | number | boolean | undefined | object>;\n\n/**\n * 模板渲染结果\n */\nexport interface TemplateResult {\n /** 渲染后的内容 */\n content: string;\n /** 使用的源文件列表(用于调试) */\n sources: string[];\n}\n\n/**\n * 模板加载器配置\n */\nexport interface TemplateLoaderOptions {\n /** 缓存启用状态,默认 true */\n cacheEnabled?: boolean;\n /** 模板搜索目录(相对于项目根目录) */\n searchDirs?: string[];\n /** 项目根目录(自动检测) */\n projectRoot?: string;\n}\n\n/**\n * 缓存统计\n */\nexport interface CacheStats {\n size: number; // 缓存条目数\n hits: number; // 命中次数\n misses: number; // 未命中次数\n hitRate: number; // 命中率\n}\n\n/**\n * 模板相关错误\n */\nexport class TemplateError extends Error {\n constructor(\n message: string,\n public code:\n | 'FILE_NOT_FOUND'\n | 'INVALID_PATH'\n | 'READ_ERROR'\n | 'UNSUPPORTED_FORMAT',\n public path?: string\n ) {\n super(message);\n this.name = 'TemplateError';\n }\n}\n","/**\n * Trim-Transcript 官方变换(ticket 006 下沉自 Claw)。\n *\n * 策略引擎:对源会话快照的 messages 施加一次「裁剪 + 工具活动折叠」变换,\n * 产出下一个 Session 的种子消息(与 Claw `handoff-package.js` 的策略引擎\n * 逐字节等价——golden 对照以 Claw 现行测试数据验收)。\n *\n * 本模块只实现纯策略(DEFAULT_EXPORT_POLICY / normalizeExportPolicy /\n * buildTrimmedSeedMessages)+ 一个实现 005 Transformation 契约的\n * `TrimTranscriptTransformation`。宿主侧的写盘、文件路径等职责不在此处。\n */\n\nimport type { Message } from '../../types.js';\nimport type { AgentSessionSnapshot } from '../../session-store.js';\nimport type {\n SessionTransformation,\n TransformInput,\n TransformContext,\n SuccessorSeed,\n SessionSeedMessage,\n} from '../index.js';\n\n// ============ 常量与默认策略 ============\n\nexport const HANDOFF_SCHEMA_VERSION = 1;\nexport const HANDOFF_COMPILER_VERSION = 'trim-transcript-v1';\n\nexport const DEFAULT_EXPORT_POLICY = {\n strategy: 'trim-transcript',\n includeSystemMessages: false,\n keepSystemTags: ['folded-tool-activity'],\n includeUserMessages: true,\n includeAssistantMessages: true,\n keepRecentTurns: null,\n fullPreserveFromTurn: null,\n preservedTurns: null,\n preservedMsgRanges: null,\n assistantToolCallMode: 'fold',\n toolMessageMode: 'fold',\n toolFoldScope: 'all',\n toolFoldRecentTurns: null,\n foldConsecutiveToolActivity: true,\n foldedToolNoteRole: 'system',\n foldToolCallArgs: false,\n foldToolResultSummary: false,\n maxFoldedToolChars: 240,\n preserveToolNames: [],\n};\n\nconst VALID_TOOL_MODES = new Set(['keep', 'drop', 'fold']);\nconst VALID_TOOL_SCOPES = new Set(['all', 'recent']);\nconst VALID_FOLDED_NOTE_ROLES = new Set(['system', 'assistant']);\n\n// ============ 清洗工具(与 Claw 逐字节一致) ============\n\nfunction sanitizeFragment(value: unknown): string {\n return String(value || '')\n .trim()\n .replace(/[^a-zA-Z0-9_-]+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '') || 'default';\n}\n\nfunction cleanInlineText(value: unknown): string {\n return typeof value === 'string'\n ? value.replace(/\\s+/g, ' ').trim()\n : '';\n}\n\nfunction cleanMultilineText(value: unknown): string {\n if (typeof value !== 'string') return '';\n const normalized = value.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\n const lines = normalized.split('\\n').map((line) => line.replace(/[ \\t]+/g, ' ').trimEnd());\n const compacted: string[] = [];\n let blankRun = 0;\n for (const line of lines) {\n if (line.trim() === '') {\n blankRun += 1;\n if (blankRun <= 1) {\n compacted.push('');\n }\n continue;\n }\n blankRun = 0;\n compacted.push(line);\n }\n return compacted.join('\\n').trim();\n}\n\nfunction clampInteger(value: unknown, fallback: number, min: number, max: number): number {\n const parsed = Number.parseInt(String(value ?? ''), 10);\n if (!Number.isFinite(parsed)) return fallback;\n return Math.min(max, Math.max(min, parsed));\n}\n\nfunction normalizeNullableTurnCount(value: unknown): number | null {\n if (value === null || value === undefined || value === '') return null;\n return clampInteger(value, 1, 1, 2000);\n}\n\nfunction normalizeNullableTurnIndex(value: unknown): number | null {\n if (value === null || value === undefined || value === '') return null;\n return clampInteger(value, 0, 0, 2000);\n}\n\nfunction normalizeKeepRecentSkillInvokes(value: unknown): number | null | typeof Infinity {\n if (value === null || value === undefined || value === '' || value === false) return null;\n if (value === Infinity || value === 'Infinity') return Infinity;\n return clampInteger(value as number, 1, 1, 2000);\n}\n\nfunction normalizeToolNameList(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return [...new Set(value.map(cleanInlineText).filter(Boolean))];\n}\n\nfunction normalizeKeepSystemTags(value: unknown): string[] {\n if (!Array.isArray(value)) return [...DEFAULT_EXPORT_POLICY.keepSystemTags];\n return [...new Set(value.map(cleanInlineText).filter(Boolean))];\n}\n\nfunction normalizeEnum(value: unknown, validValues: Set<string>, fallback: string): string {\n const text = cleanInlineText(value);\n return validValues.has(text) ? text : fallback;\n}\n\n// ============ 策略归一化 ============\n\nexport interface TrimExportPolicy {\n strategy: 'trim-transcript';\n includeSystemMessages: boolean;\n keepSystemTags: string[];\n includeUserMessages: boolean;\n includeAssistantMessages: boolean;\n keepRecentTurns: number | null;\n fullPreserveFromTurn: number | null;\n preservedTurns: number[] | null;\n preservedMsgRanges: Array<[number, number]> | null;\n assistantToolCallMode: string;\n toolMessageMode: string;\n toolFoldScope: string;\n toolFoldRecentTurns: number | null;\n foldConsecutiveToolActivity: boolean;\n foldedToolNoteRole: string;\n foldToolCallArgs: boolean;\n foldToolResultSummary: boolean;\n maxFoldedToolChars: number;\n keepRecentSkillInvokes?: number | null | typeof Infinity;\n preserveToolNames: string[];\n}\n\nexport function normalizeExportPolicy(rawPolicy: Record<string, unknown> = {}): TrimExportPolicy {\n return {\n strategy: 'trim-transcript',\n includeSystemMessages: rawPolicy?.includeSystemMessages === true,\n keepSystemTags: normalizeKeepSystemTags(rawPolicy?.keepSystemTags),\n includeUserMessages: rawPolicy?.includeUserMessages !== false,\n includeAssistantMessages: rawPolicy?.includeAssistantMessages !== false,\n keepRecentTurns: normalizeNullableTurnCount(rawPolicy?.keepRecentTurns as unknown),\n fullPreserveFromTurn: normalizeNullableTurnIndex(rawPolicy?.fullPreserveFromTurn as unknown),\n preservedTurns: Array.isArray(rawPolicy?.preservedTurns)\n ? [...new Set((rawPolicy.preservedTurns as unknown[]).filter(t => Number.isFinite(t)).map(Number))]\n : null,\n preservedMsgRanges: Array.isArray(rawPolicy?.preservedMsgRanges) && (rawPolicy.preservedMsgRanges as unknown[]).length > 0\n ? (rawPolicy.preservedMsgRanges as Array<[unknown, unknown]>)\n .filter(r => Array.isArray(r) && r.length === 2 && Number.isFinite(r[0]) && Number.isFinite(r[1]))\n .map(([s, e]) => [Math.floor(s as number), Math.floor(e as number)])\n : null,\n assistantToolCallMode: normalizeEnum(rawPolicy?.assistantToolCallMode, VALID_TOOL_MODES, DEFAULT_EXPORT_POLICY.assistantToolCallMode),\n toolMessageMode: normalizeEnum(rawPolicy?.toolMessageMode, VALID_TOOL_MODES, DEFAULT_EXPORT_POLICY.toolMessageMode),\n toolFoldScope: normalizeEnum(rawPolicy?.toolFoldScope, VALID_TOOL_SCOPES, DEFAULT_EXPORT_POLICY.toolFoldScope),\n toolFoldRecentTurns: normalizeNullableTurnCount(rawPolicy?.toolFoldRecentTurns as unknown),\n foldConsecutiveToolActivity: rawPolicy?.foldConsecutiveToolActivity !== false,\n foldedToolNoteRole: normalizeEnum(rawPolicy?.foldedToolNoteRole, VALID_FOLDED_NOTE_ROLES, DEFAULT_EXPORT_POLICY.foldedToolNoteRole),\n foldToolCallArgs: rawPolicy?.foldToolCallArgs === true,\n foldToolResultSummary: rawPolicy?.foldToolResultSummary === true,\n maxFoldedToolChars: clampInteger(rawPolicy?.maxFoldedToolChars as unknown, DEFAULT_EXPORT_POLICY.maxFoldedToolChars, 80, 4000),\n keepRecentSkillInvokes: normalizeKeepRecentSkillInvokes(rawPolicy?.keepRecentSkillInvokes),\n preserveToolNames: normalizeToolNameList(rawPolicy?.preserveToolNames),\n };\n}\n\n// ============ 策略引擎(与 handoff-package.js 逐字节一致) ============\n\nfunction safeJsonSnippet(value: unknown, maxChars: number): string {\n try {\n const text = cleanMultilineText(typeof value === 'string' ? value : JSON.stringify(value));\n return text.length > maxChars ? `${text.slice(0, Math.max(0, maxChars - 18)).trimEnd()} [truncated]` : text;\n } catch {\n const text = cleanMultilineText(String(value ?? ''));\n return text.length > maxChars ? `${text.slice(0, Math.max(0, maxChars - 18)).trimEnd()} [truncated]` : text;\n }\n}\n\nfunction extractToolCallKeyInfo(name: string, rawArgs: unknown): string | null {\n let args = rawArgs;\n if (typeof args === 'string') { try { args = JSON.parse(args); } catch { return null; } }\n if (!args || typeof args !== 'object') return null;\n const record = args as Record<string, unknown>;\n if (name === 'read' || name === 'edit' || name === 'write') {\n const filePath = typeof record.filePath === 'string' ? record.filePath : '';\n if (filePath) {\n const baseName = filePath.split(/[\\\\/]/).pop() || filePath;\n return `${name}(${baseName})`;\n }\n }\n if (name === 'invoke_skill') {\n const skill = typeof record.skill === 'string' ? record.skill : '';\n if (skill) return `invoke_skill(${skill})`;\n }\n return null;\n}\n\nfunction summarizeAssistantToolCalls(toolCalls: unknown[], policy: TrimExportPolicy): string[] {\n if (!Array.isArray(toolCalls) || toolCalls.length === 0) return [];\n return toolCalls.map((call) => {\n const name = cleanInlineText((call as Record<string, unknown>)?.name) || 'tool';\n const keyInfo = extractToolCallKeyInfo(name, (call as Record<string, unknown>)?.args ?? (call as Record<string, unknown>)?.arguments);\n if (keyInfo) return keyInfo;\n if (!policy.foldToolCallArgs) {\n return name;\n }\n const args = safeJsonSnippet((call as Record<string, unknown>)?.args ?? (call as Record<string, unknown>)?.arguments ?? {}, policy.maxFoldedToolChars);\n return args ? `${name}(${args})` : `${name}()`;\n });\n}\n\nfunction getMessageTurn(message: any, fallbackIndex: number): number {\n return Number.isFinite(message?.turn) ? Number(message.turn) : fallbackIndex;\n}\n\nfunction getRetainedTurnSet(rawMessages: any[], policy: TrimExportPolicy): Set<number> | null {\n if (!policy.keepRecentTurns) return null;\n const turns = rawMessages\n .filter(message => Number.isFinite(message?.turn))\n .map(message => Number(message.turn));\n if (turns.length === 0) return null;\n const uniqueTurns = [...new Set(turns)].sort((a, b) => a - b);\n const keptTurns = uniqueTurns.slice(-policy.keepRecentTurns);\n return new Set(keptTurns);\n}\n\nfunction getFoldedToolTurnSet(rawMessages: any[], retainedTurns: Set<number> | null, policy: TrimExportPolicy): Set<number> | null {\n if (policy.toolFoldScope === 'all') return null;\n if (policy.toolFoldRecentTurns) {\n const turns = rawMessages\n .map((message, index) => getMessageTurn(message, index))\n .filter(Number.isFinite);\n if (turns.length === 0) return null;\n const uniqueTurns = [...new Set(turns)].sort((a, b) => a - b);\n return new Set(uniqueTurns.slice(-policy.toolFoldRecentTurns));\n }\n return retainedTurns;\n}\n\nfunction shouldKeepDialogueMessage(role: string, policy: TrimExportPolicy, tag?: string): boolean {\n if (role === 'user') return policy.includeUserMessages;\n if (role === 'assistant') return policy.includeAssistantMessages;\n if (role === 'system') {\n if (tag && Array.isArray(policy.keepSystemTags) && policy.keepSystemTags.includes(tag)) return true;\n return policy.includeSystemMessages;\n }\n return false;\n}\n\nfunction shouldHandleToolActivity(messageTurn: number, foldedToolTurns: Set<number> | null, policy: TrimExportPolicy): boolean {\n if (policy.toolFoldScope === 'all') return true;\n if (!foldedToolTurns) return false;\n return foldedToolTurns.has(messageTurn);\n}\n\nfunction getSkillInvokeProtectedMessages(rawMessages: any[], policy: TrimExportPolicy): Set<number> | null {\n if (!policy.keepRecentSkillInvokes) return null;\n\n // Phase 1: find the N most recent turns that contain invoke_skill calls.\n const skillTurns: number[] = [];\n for (let i = rawMessages.length - 1; i >= 0; i--) {\n const m = rawMessages[i];\n if (m?.role !== 'assistant') continue;\n const toolCalls = Array.isArray(m.toolCalls) ? m.toolCalls : [];\n const hasSkill = toolCalls.some((tc: any) => tc?.name === 'invoke_skill');\n if (!hasSkill) continue;\n const turn = getMessageTurn(m, i);\n if (!skillTurns.includes(turn)) {\n skillTurns.unshift(turn);\n if (skillTurns.length >= (policy.keepRecentSkillInvokes as number) && policy.keepRecentSkillInvokes !== Infinity) break;\n }\n }\n if (skillTurns.length === 0) return null;\n const protectedTurnSet = new Set(skillTurns);\n\n // Phase 2: collect only the specific messages to protect —\n // the assistant messages that actually carry invoke_skill calls,\n // and the tool-result messages whose toolCallId matches those calls.\n const protectedIndices = new Set<number>();\n const skillToolCallIds = new Set<string>();\n\n rawMessages.forEach((message, index) => {\n const turn = getMessageTurn(message, index);\n if (!protectedTurnSet.has(turn)) return;\n if (message?.role !== 'assistant') return;\n const toolCalls = Array.isArray(message.toolCalls) ? message.toolCalls : [];\n const skillCalls = toolCalls.filter((tc: any) => tc?.name === 'invoke_skill');\n if (skillCalls.length === 0) return;\n protectedIndices.add(index);\n for (const tc of skillCalls) {\n const id = cleanInlineText(tc?.id);\n if (id) skillToolCallIds.add(id);\n }\n });\n\n // Protect tool results for those skill calls (may be in a different turn\n // in edge cases, so match by toolCallId rather than turn).\n rawMessages.forEach((message, index) => {\n if (message?.role !== 'tool') return;\n const toolCallId = cleanInlineText(message?.toolCallId);\n if (toolCallId && skillToolCallIds.has(toolCallId)) {\n protectedIndices.add(index);\n }\n });\n\n return protectedIndices.size > 0 ? protectedIndices : null;\n}\n\nfunction createSeedMessage(role: string, content: string, turn: number, tag?: string): SessionSeedMessage | null {\n const text = cleanMultilineText(content);\n if (!text) return null;\n return {\n role,\n content: text,\n turn: Number.isFinite(turn) ? turn : null,\n ...(tag ? { tag } : {}),\n } as SessionSeedMessage;\n}\n\nfunction deduplicateToolCallSummaries(summaries: string[]): string[] {\n const counts = new Map<string, number>();\n const order: string[] = [];\n for (const s of summaries) {\n if (counts.has(s)) {\n counts.set(s, counts.get(s)! + 1);\n } else {\n counts.set(s, 1);\n order.push(s);\n }\n }\n return order.map(s => {\n const c = counts.get(s)!;\n return c > 1 ? `${s} ×${c}` : s;\n });\n}\n\nfunction flushPendingToolFold(seedMessages: SessionSeedMessage[], pendingFold: any, policy: TrimExportPolicy, stats: any): null {\n if (!pendingFold || pendingFold.toolCalls.length === 0) {\n return null;\n }\n\n const deduped = deduplicateToolCallSummaries(pendingFold.toolCalls);\n const lines = ['[Folded tool activity]'];\n lines.push(`assistant tool calls: ${deduped.join('; ')}`);\n\n const note = createSeedMessage(policy.foldedToolNoteRole, lines.join('\\n'), pendingFold.turn, 'folded-tool-activity');\n if (note) {\n seedMessages.push(note);\n stats.foldedToolNoteCount += 1;\n }\n return null;\n}\n\nexport interface TrimStats {\n originalMessageCount: number;\n keptSeedMessageCount: number;\n droppedMessageCount: number;\n keptDialogueMessageCount: number;\n droppedDialogueMessageCount: number;\n foldedToolCallCount: number;\n droppedToolCallCount: number;\n foldedToolMessageCount: number;\n droppedToolMessageCount: number;\n foldedToolNoteCount: number;\n keptProtectedToolCallCount: number;\n keptProtectedToolMessageCount: number;\n retainedTurnCount: number | null;\n foldedToolTurnCount: number | null;\n}\n\nexport interface TrimmedSeedResult {\n seedMessages: SessionSeedMessage[];\n stats: TrimStats;\n}\n\nexport function buildTrimmedSeedMessages(rawMessages: any[], policy: TrimExportPolicy): TrimmedSeedResult {\n const retainedTurns = getRetainedTurnSet(rawMessages, policy);\n const foldedToolTurns = getFoldedToolTurnSet(rawMessages, retainedTurns, policy);\n const skillProtectedIndices = getSkillInvokeProtectedMessages(rawMessages, policy);\n const protectedToolNames = new Set(Array.isArray(policy?.preserveToolNames) ? policy.preserveToolNames : []);\n const protectedToolCallIds = new Set<string>();\n for (const message of rawMessages) {\n const toolCalls = Array.isArray(message?.toolCalls) ? message.toolCalls : [];\n for (const call of toolCalls) {\n const name = cleanInlineText(call?.name);\n const id = cleanInlineText(call?.id);\n if (name && id && protectedToolNames.has(name)) {\n protectedToolCallIds.add(id);\n }\n }\n }\n if (skillProtectedIndices) {\n rawMessages.forEach((message, index) => {\n if (!skillProtectedIndices.has(index) || message?.role !== 'assistant') return;\n const toolCalls = Array.isArray(message?.toolCalls) ? message.toolCalls : [];\n for (const call of toolCalls) {\n const id = cleanInlineText(call?.id);\n if (id && cleanInlineText(call?.name) === 'invoke_skill') {\n protectedToolCallIds.add(id);\n }\n }\n });\n }\n const fullPreserveFrom = policy.fullPreserveFromTurn;\n const preservedTurnSet = Array.isArray(policy.preservedTurns) && policy.preservedTurns.length > 0\n ? new Set(policy.preservedTurns)\n : null;\n const preservedMsgIndices = Array.isArray(policy.preservedMsgRanges) && policy.preservedMsgRanges.length > 0\n ? new Set<number>()\n : null;\n if (preservedMsgIndices) {\n for (const [start, end] of policy.preservedMsgRanges!) {\n for (let i = start; i <= end; i++) {\n preservedMsgIndices.add(i);\n }\n }\n }\n const hasPreserveBoundary = preservedMsgIndices || preservedTurnSet || Number.isFinite(fullPreserveFrom as number);\n const seedMessages: SessionSeedMessage[] = [];\n const stats: Omit<TrimStats, 'retainedTurnCount' | 'foldedToolTurnCount'> = {\n originalMessageCount: rawMessages.length,\n keptSeedMessageCount: 0,\n droppedMessageCount: 0,\n keptDialogueMessageCount: 0,\n droppedDialogueMessageCount: 0,\n foldedToolCallCount: 0,\n droppedToolCallCount: 0,\n foldedToolMessageCount: 0,\n droppedToolMessageCount: 0,\n foldedToolNoteCount: 0,\n keptProtectedToolCallCount: 0,\n keptProtectedToolMessageCount: 0,\n };\n\n let pendingFold: any = null;\n\n const ensurePendingFold = (turn: number): any => {\n if (!pendingFold) {\n pendingFold = {\n turn,\n toolCalls: [],\n toolResults: [],\n };\n }\n return pendingFold;\n };\n\n const flushIfNeeded = (): void => {\n pendingFold = flushPendingToolFold(seedMessages, pendingFold, policy, stats);\n };\n\n const flushImmediatelyIfConfigured = (): void => {\n if (policy.foldConsecutiveToolActivity === false) {\n flushIfNeeded();\n }\n };\n\n rawMessages.forEach((message, index) => {\n const role = cleanInlineText(message?.role);\n if (!role) {\n stats.droppedMessageCount += 1;\n return;\n }\n\n const turn = getMessageTurn(message, index);\n const withinDialogueWindow = hasPreserveBoundary || !retainedTurns || retainedTurns.has(turn);\n\n const inPreserveZone = preservedMsgIndices\n ? preservedMsgIndices.has(index)\n : preservedTurnSet\n ? preservedTurnSet.has(turn)\n : (Number.isFinite(fullPreserveFrom as number) && turn >= (fullPreserveFrom as number));\n if (inPreserveZone) {\n flushIfNeeded();\n if (role === 'tool' || shouldKeepDialogueMessage(role, policy, message?.tag)) {\n seedMessages.push({ ...message, turn } as SessionSeedMessage);\n stats.keptSeedMessageCount += 1;\n if (role !== 'tool') {\n stats.keptDialogueMessageCount += 1;\n }\n } else {\n stats.droppedDialogueMessageCount += 1;\n stats.droppedMessageCount += 1;\n }\n return;\n }\n\n let toolCalls = Array.isArray(message?.toolCalls) ? message.toolCalls : [];\n const protectedCalls = role === 'assistant'\n ? toolCalls.filter((call: any) => protectedToolCallIds.has(cleanInlineText(call?.id)))\n : [];\n if (protectedCalls.length > 0 && shouldKeepDialogueMessage(role, policy, message?.tag)) {\n flushIfNeeded();\n seedMessages.push({ ...message, toolCalls: protectedCalls, turn } as SessionSeedMessage);\n stats.keptSeedMessageCount += 1;\n stats.keptDialogueMessageCount += 1;\n stats.keptProtectedToolCallCount += protectedCalls.length;\n\n toolCalls = toolCalls.filter((call: any) => !protectedToolCallIds.has(cleanInlineText(call?.id)));\n if (toolCalls.length === 0) {\n return;\n }\n message = { ...message, content: '', toolCalls };\n }\n\n if (role === 'tool' && protectedToolCallIds.has(cleanInlineText(message?.toolCallId))) {\n seedMessages.push({ ...message, turn } as SessionSeedMessage);\n stats.keptSeedMessageCount += 1;\n stats.keptProtectedToolMessageCount += 1;\n return;\n }\n\n if (role === 'tool') {\n if (!withinDialogueWindow) {\n stats.droppedToolMessageCount += 1;\n stats.droppedMessageCount += 1;\n return;\n }\n\n const shouldHandle = hasPreserveBoundary\n ? true\n : shouldHandleToolActivity(turn, foldedToolTurns, policy);\n if (policy.toolMessageMode === 'keep' || !shouldHandle) {\n flushIfNeeded();\n const seedMessage = createSeedMessage('tool', message.content, turn, message?.tag);\n if (seedMessage) {\n seedMessages.push(seedMessage);\n stats.keptSeedMessageCount += 1;\n } else {\n stats.droppedMessageCount += 1;\n }\n return;\n }\n\n if (policy.toolMessageMode === 'drop') {\n stats.droppedToolMessageCount += 1;\n stats.droppedMessageCount += 1;\n return;\n }\n\n ensurePendingFold(turn);\n stats.foldedToolMessageCount += 1;\n stats.droppedMessageCount += 1;\n flushImmediatelyIfConfigured();\n return;\n }\n\n const shouldHandleToolCalls = toolCalls.length > 0 && (hasPreserveBoundary\n ? true\n : shouldHandleToolActivity(turn, foldedToolTurns, policy));\n const toolCallSummaries = summarizeAssistantToolCalls(toolCalls, policy);\n\n if (!withinDialogueWindow) {\n if (role === 'assistant' || role === 'user' || role === 'system') {\n stats.droppedDialogueMessageCount += 1;\n }\n if (shouldHandleToolCalls) {\n if (policy.assistantToolCallMode === 'fold') {\n stats.foldedToolCallCount += toolCalls.length;\n } else if (policy.assistantToolCallMode === 'drop') {\n stats.droppedToolCallCount += toolCalls.length;\n }\n }\n stats.droppedMessageCount += 1;\n return;\n }\n\n const isToolOnlyAssistantFold = role === 'assistant'\n && !cleanMultilineText(message.content)\n && toolCalls.length > 0\n && policy.assistantToolCallMode === 'fold'\n && shouldHandleToolCalls;\n if (!isToolOnlyAssistantFold) {\n flushIfNeeded();\n }\n\n if (!shouldKeepDialogueMessage(role, policy, message?.tag)) {\n stats.droppedDialogueMessageCount += 1;\n stats.droppedMessageCount += 1;\n } else {\n let assistantContent = cleanMultilineText(message.content);\n if (role === 'assistant' && toolCalls.length > 0 && policy.assistantToolCallMode === 'keep' && toolCallSummaries.length > 0 && shouldHandleToolCalls) {\n assistantContent = `${assistantContent}\\n[tool calls kept inline] ${toolCallSummaries.join('; ')}`.trim();\n }\n const seedMessage = createSeedMessage(role, assistantContent, turn, message?.tag);\n if (seedMessage) {\n seedMessages.push(seedMessage);\n stats.keptSeedMessageCount += 1;\n if (role === 'assistant' || role === 'user' || role === 'system') {\n stats.keptDialogueMessageCount += 1;\n }\n } else if (role !== 'assistant' || toolCalls.length === 0) {\n stats.droppedMessageCount += 1;\n }\n }\n\n if (role === 'assistant' && toolCalls.length > 0 && shouldHandleToolCalls) {\n if (policy.assistantToolCallMode === 'fold') {\n const fold = ensurePendingFold(turn);\n fold.toolCalls.push(...toolCallSummaries);\n stats.foldedToolCallCount += toolCalls.length;\n flushImmediatelyIfConfigured();\n } else if (policy.assistantToolCallMode === 'drop') {\n stats.droppedToolCallCount += toolCalls.length;\n }\n }\n });\n\n flushPendingToolFold(seedMessages, pendingFold, policy, stats);\n return {\n seedMessages,\n stats: {\n ...stats,\n retainedTurnCount: retainedTurns ? retainedTurns.size : null,\n foldedToolTurnCount: foldedToolTurns ? foldedToolTurns.size : null,\n },\n };\n}\n\n// ============ Transformation 契约实现 ============\n\nexport interface TrimTranscriptTransformationOptions {\n /**\n * 默认策略(可被 `transform` 传入的 policy 按需覆盖)。缺省为空对象,\n * 即 `normalizeExportPolicy({})` 的默认裁剪行为。\n */\n defaultPolicy?: Record<string, unknown>;\n}\n\n/**\n * Trim-Transcript 变换:对源会话快照施加裁剪变换,产出 SuccessorSeed。\n *\n * 从 `sourceSnapshot.runtime.context.messages` 读取消息(session-store 契约级\n * 消费面),以 `policy` 为裁剪策略面(归一化语义见 normalizeExportPolicy)。\n */\nexport class TrimTranscriptTransformation implements SessionTransformation {\n readonly id = 'agentdev.trim-transcript';\n\n private readonly defaultPolicy: Record<string, unknown>;\n\n constructor(options: TrimTranscriptTransformationOptions = {}) {\n this.defaultPolicy = options.defaultPolicy ?? {};\n }\n\n async transform(input: TransformInput, _ctx: TransformContext): Promise<SuccessorSeed> {\n const snapshot: AgentSessionSnapshot = input.sourceSnapshot;\n const rawMessages = Array.isArray(snapshot?.runtime?.context?.messages)\n ? snapshot.runtime.context.messages\n : [];\n\n const policy = normalizeExportPolicy({ ...this.defaultPolicy, ...(input.policy ?? {}) });\n const { seedMessages, stats } = buildTrimmedSeedMessages(rawMessages, policy);\n\n return {\n schemaVersion: HANDOFF_SCHEMA_VERSION,\n seedMessages,\n meta: {\n compilerVersion: HANDOFF_COMPILER_VERSION,\n seedKind: 'message-replay',\n mode: policy.strategy,\n policy,\n stats,\n },\n };\n }\n}\n\n// 兼容导出(与 Claw 策略引擎同名,便于 golden 对照直读)\nexport { sanitizeFragment, cleanInlineText, cleanMultilineText };\n","/**\r\n * Summary 官方变换(ticket 006 新增)。\r\n *\r\n * 基于 005 的 `TransformContext.llm` 进程内注入,对源会话快照做一次摘要变换,\r\n * 产出 SuccessorSeed(summary-message seed)。提示词以 Claw\r\n * `claude-compact-prompts.js` 为蓝本。\r\n *\r\n * 不移植 Claw 的 mirror 子进程管线——那是 Claw 装配细节(模型配置来源),\r\n * 由 Claw 侧决定何时切换到进程内注入。\r\n *\r\n * 组合语义(ticket 006 收敛定案):不做通用 compose 组合子机制。官方单实现\r\n * 先落——`TrimTranscriptWithSummaryTransformation` 把「trim 裁剪 + 追加摘要」\r\n * 硬编码混合语义 1:1 迁移(对齐 Claw `trim-transcript-with-summary`)。\r\n */\r\n\r\nimport type { Message, LLMResponse } from '../../types.js';\r\nimport type { AgentSessionSnapshot } from '../../session-store.js';\r\nimport type {\r\n SessionTransformation,\r\n TransformInput,\r\n TransformContext,\r\n SuccessorSeed,\r\n SessionSeedMessage,\r\n} from '../index.js';\r\nimport {\r\n DEFAULT_EXPORT_POLICY,\r\n normalizeExportPolicy,\r\n buildTrimmedSeedMessages,\r\n HANDOFF_SCHEMA_VERSION,\r\n} from './trim-transcript.js';\r\n\r\n// ============ 提示词(以 claude-compact-prompts.js 为蓝本) ============\r\n\r\nconst BASE_SUMMARY_PROMPT = `你的任务是为当前对话创建一份详细摘要,重点关注用户的明确请求和该 agent 之前采取的行动。\r\n这份摘要应保留恢复工作所需的任务连续性关键信息。\r\n\r\n按时间顺序分析对话:\r\n\r\n1. 识别用户的明确请求和意图\r\n2. 保留用户较为模糊的术语概念与情况表述,不做过多推测与转述\r\n3. 识别该 agent 的方法和关键决策,以及用户的反馈,特别注意该 agent 曾理解有误、或后续改变方向的用户反馈\r\n4. 记录与用户探讨的重要结论,以及最终放弃、或纠正某些决策的原因\r\n5. 记录当前讨论要点之于整个项目的层次,以及重要的技术概念、文件名、代码模式\r\n6. 记录遇到的错误及修复方式\r\n\r\n摘要使用以下十段式结构:\r\n\r\n1. 主要请求与意图\r\n2. 用户观点表态与方向调整\r\n3. 关键技术概念\r\n4. 重要结论与决策\r\n5. 参考文件、技能与代码段\r\n6. 错误与修复\r\n7. 问题解决过程\r\n8. 待办事项\r\n9. 当前工作\r\n10. 可选的下一步\r\n\r\n摘要控制在 3000 个词以内,优先使用要点而非段落。`;\r\n\r\nconst TRIM_APPENDED_SUMMARY_PROMPT = `你的任务是为当前对话创建一份详细摘要,留存其中的关键信息,并让摘要本身结构清晰、脉络连贯、可以独立阅读。\r\n\r\n需要注意:在摘要生成后,工具调用记录中的参数细节和返回内容可能不会继续保留;在这次精简场景中,工具活动通常只保留调用签名。用户消息和 Agent 的主要回复则通常仍会保留。因此,工具返回中出现过的完整标识符、文件内容与代码事实、统计数字、命令与查询的实际输出、报错原文、外部资料中的具体机制等信息,需要在摘要中重新落地,不能假定读者还能从工具记录中找回。\r\n\r\n摘要应同时承担两类内容:一类是工具调用带来的具体信息,另一类是对话脉络、方向变化、决策和结论的概括。后者可以适度复述,使摘要流畅、完整、独立可读;前者则应覆盖工具呈现的不同信息维度,而不要只围绕某一条显眼的主线进行筛选。信息是否保留,主要依据它本身的具体程度、独立价值和对理解会话的帮助,不要过早假定某个维度之后不会用到。\r\n\r\n按时间顺序分析对话,重点关注:\r\n\r\n1. 工具调用中获得的重要事实、技术信息、代码机制、文件内容、测试结果和外部资料。这些内容在精简后可能无处可查,应从多个相关维度尽量完整地保留。\r\n2. 重要的文件名、路径、函数、类型、数据结构、关键参数、代码位置、错误信息、数字、版本、命令结果等具体信息,一律使用完整值,例如完整的 ID、哈希和路径,不要用省略号或“等 N 项”带过。对于实现细节和机制说明,可以适当保留具体的定位信息。\r\n3. 对于已经在 Agent 回复中明确表达的重要结论、技术判断和决策,可以概括复述,以保持叙事连贯;同时记录其中主要存在于工具调用中的事实、证据和必要依据。\r\n4. 用户对方向的重要反馈和纠正,尤其是曾经理解有误、后来改变方向的部分;可以用概括方式复述,让读者能够理解对话如何发展。\r\n5. 已经尝试但被否定或放弃的重要方向,以及不再沿用这些方向的原因。普通操作失误或偶发错误通常无需记录,除非它提供了一个独立的技术事实、边界或判断依据。\r\n6. 已经实际完成的重要修改、操作和状态变化,以及仍然存在的重要问题。注意区分计划、尝试、完成和验证;验证结果应落到具体数字或其他可核对的最终值。\r\n7. 如果某个结论或机制只能概括表达,而原始工具信息中还有可能需要重新确认的细节,应说明缺少什么,并给出完整的定位信息,例如完整路径、完整 ID 或可复查的命令。\r\n8. 对外部调研和参考资料,优先保留资料本身提供的具体机制、实现方式、差异和关键事实,不要只记录最终评价或笼统结论。对于较长的工具输出,提炼其中多个独立且有代表性的事实和关键片段,而不是只保留一个总结性结论。\r\n\r\n在提供最终摘要之前,先用 <analysis> 标签进行一次信息对照:检查准备写入的具体标识符、数字、路径、输出片段和其他事实,区分哪些信息已经在用户消息或 Agent 回复中完整出现,哪些信息主要或仅存在于工具调用中。对话中已经存在的信息可以用概括方式复述;工具调用中出现的具体信息则应以完整、可核对的形式写入摘要。\r\n\r\n摘要使用自然的 Markdown 结构,根据实际内容组织,例如:\r\n\r\n## 重要发现与技术信息\r\n\r\n## 关键证据与实现细节\r\n\r\n## 结论背后的补充依据\r\n\r\n## 已排除的问题与方向\r\n\r\n## 修改、执行结果与当前状态\r\n\r\n## 需要重新查看的细节与位置\r\n\r\n不要求所有章节都出现,也不要为了填充结构重复内容。\r\n\r\n摘要应覆盖工具调用带来的具体信息和对话脉络的必要概括。对话已有的完整论述不必逐字重现,但可以提炼其发展过程、方向变化和结论,使摘要读起来完整自然;工具信息则应注意覆盖不同维度,并保留其中能够独立说明事实的细节。\r\n\r\n不要为了完整而记录所有工具调用、所有错误或完整的问题解决过程。纯粹的中间操作过程、偶发错误、与任何结论无关的临时输出可以省略;已经被后续结果取代的中间值可以不记,但最终值和独立的技术事实应保留。\r\n\r\n摘要控制在 3000 个词以内,优先使用要点而非长段落;长度以信息完整和结构清晰为准。`;\r\n\r\nexport interface SummaryPromptOptions {\r\n /** 附加压缩指令(追加到提示词末尾)。 */\r\n additionalInstructions?: string;\r\n /** true 时使用 trim-appended 专用提示词(组合语义用)。 */\r\n trimAppended?: boolean;\r\n /** exploration 会话使用三段式探索提示词。 */\r\n exploration?: boolean;\r\n}\r\n\r\n/** 生成摘要提示词(对齐 claude-compact-prompts.js 的 buildClaudeCompactPrompt)。 */\r\nexport function buildSummaryPrompt(options: SummaryPromptOptions = {}): string {\r\n const extra = typeof options.additionalInstructions === 'string' && options.additionalInstructions.trim()\r\n ? `## 额外压缩指令\\n${options.additionalInstructions.trim()}`\r\n : '';\r\n if (options.trimAppended) {\r\n return [TRIM_APPENDED_SUMMARY_PROMPT, extra].filter(Boolean).join('\\n');\r\n }\r\n return [BASE_SUMMARY_PROMPT, extra].filter(Boolean).join('\\n');\r\n}\r\n\r\n// ============ 文本清洗 / 摘要提取(对齐 claude-compact-prompts.js) ============\r\n\r\nfunction cleanMultilineText(value: unknown): string {\r\n if (typeof value !== 'string') return '';\r\n const normalized = value.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\r\n const lines = normalized.split('\\n').map((line) => line.replace(/[ \\t]+/g, ' ').trimEnd());\r\n const compacted: string[] = [];\r\n let blankRun = 0;\r\n for (const line of lines) {\r\n if (line.trim() === '') {\r\n blankRun += 1;\r\n if (blankRun <= 1) {\r\n compacted.push('');\r\n }\r\n continue;\r\n }\r\n blankRun = 0;\r\n compacted.push(line);\r\n }\r\n return compacted.join('\\n').trim();\r\n}\r\n\r\n/** 从 LLM 原始响应中剥离 <analysis> 与 <summary> 包裹,得到纯摘要文本。 */\r\nexport function stripCompactAnalysis(rawText: string): string {\r\n const text = typeof rawText === 'string' ? rawText.trim() : '';\r\n if (!text) return '';\r\n\r\n const withoutAnalysis = text.replace(/<analysis>[\\s\\S]*?<\\/analysis>/gi, '').trim();\r\n const summaryMatch = withoutAnalysis.match(/<summary>([\\s\\S]*?)<\\/summary>/i);\r\n const summaryBody = summaryMatch ? summaryMatch[1].trim() : withoutAnalysis;\r\n return summaryBody.replace(/\\n{3,}/g, '\\n\\n').trim();\r\n}\r\n\r\n// ============ 扫描重要文件 / 技能(对齐 claude-compact-prompts.js) ============\r\n\r\nexport interface ScanFilesAndSkillsResult {\r\n files: string[];\r\n skills: string[];\r\n fileRanges: Record<string, string>;\r\n}\r\n\r\n/** 从原始消息中扫描 read/write/edit 与 invoke_skill 调用,收集重要文件、技能与行号范围。 */\r\nexport function scanFilesAndSkills(rawMessages: any[]): ScanFilesAndSkillsResult {\r\n const files = new Set<string>();\r\n const skills = new Set<string>();\r\n const fileRanges: Record<string, string> = {};\r\n for (const message of rawMessages) {\r\n if (message.role !== 'assistant' || !Array.isArray(message.toolCalls)) continue;\r\n for (const tc of message.toolCalls) {\r\n const name = typeof tc?.name === 'string' ? tc.name : '';\r\n const args = tc?.arguments && typeof tc.arguments === 'object' ? tc.arguments : {};\r\n if ((name === 'read' || name === 'write' || name === 'edit') && typeof args.filePath === 'string') {\r\n files.add(args.filePath);\r\n }\r\n if (name === 'read' && typeof args.filePath === 'string') {\r\n const offset = typeof args.offset === 'number' ? args.offset : (typeof args.line === 'number' ? args.line : 0);\r\n const limit = typeof args.limit === 'number' ? args.limit : 0;\r\n if (offset > 0 || limit > 0) {\r\n const start = Math.max(1, offset || 1);\r\n const end = limit > 0 ? start + limit - 1 : start;\r\n fileRanges[args.filePath] = `${start}-${end}`;\r\n }\r\n }\r\n if (name === 'invoke_skill' && typeof args.skill === 'string') {\r\n skills.add(args.skill);\r\n }\r\n }\r\n }\r\n return { files: [...files], skills: [...skills], fileRanges };\r\n}\r\n\r\n// ============ 策略归一化 ============\r\n\r\nexport interface SummaryExportPolicy {\r\n strategy: string;\r\n summaryShape: string;\r\n maxAttempts: number;\r\n additionalInstructions: string;\r\n}\r\n\r\nexport function normalizeSummaryPolicy(rawPolicy: Record<string, unknown> = {}): SummaryExportPolicy {\r\n return {\r\n strategy: 'summarized-nine-section',\r\n summaryShape: 'claude-nine-section-v1',\r\n maxAttempts: Number.isFinite(rawPolicy?.maxAttempts)\r\n ? Math.max(1, Math.min(5, Number(rawPolicy.maxAttempts)))\r\n : 3,\r\n additionalInstructions: cleanMultilineText(rawPolicy?.additionalInstructions),\r\n };\r\n}\r\n\r\n// ============ 种子消息构建 ============\r\n\r\n/**\r\n * 构建 summary 种子消息(对齐 summarized-handoff / trim-appended-summary)。\r\n * 返回 role:'system' 的摘要消息。\r\n */\r\nexport function buildSummarySeedMessage(summaryText: string): SessionSeedMessage {\r\n const body = cleanMultilineText(summaryText);\r\n return {\r\n role: 'system',\r\n content: [\r\n '以下是前一会话的工作摘要,用于延续同一任务上下文。',\r\n '摘要涵盖前一轮对话的关键内容。',\r\n '',\r\n '摘要:',\r\n body,\r\n '',\r\n '请基于此摘要继续工作,无需要求用户重复陈述背景。',\r\n ].join('\\n'),\r\n turn: 0,\r\n };\r\n}\r\n\r\n// ============ LLM 调用 ============\r\n\r\nfunction extractMessages(snapshot: AgentSessionSnapshot): any[] {\r\n return Array.isArray(snapshot?.runtime?.context?.messages)\r\n ? snapshot.runtime.context.messages\r\n : [];\r\n}\r\n\r\n/**\r\n * 身份澄清前缀:摘要请求携带原会话完整记录注入,需明确告知模型\r\n * 这是一份已存在的会话记录而非其真实交互,防止模型代入原 agent 身份\r\n * (尤其当记录中途残留原身份相关内容时)。\r\n */\r\nconst SUMMARY_ROLE_PREAMBLE = `以下呈现的是一份已经存在的会话记录(transcript)。注意:这份记录不是你与任何人的真实交互,你也不是该会话中的任何角色——不要代入其中 agent 的身份,不要延续其中的任务或对话。你的唯一任务是:以旁观者身份,按本提示的要求为这份完整记录撰写摘要。`;\r\n\r\n/** 结尾锚定:标记会话记录到此为止,其上全部内容才是概括对象。 */\r\nconst SUMMARY_CLOSING_ANCHOR = '会话记录到此为止。请基于以上全部记录,按照系统提示的要求输出摘要;不要续写会话,不要扮演其中的任何角色。';\r\n\r\n/** 单条工具返回注入摘要请求的最大字符数(长输出截断,防止撑爆上下文)。 */\r\nconst TOOL_RESULT_MAX_CHARS = 1200;\r\n\r\nfunction truncateToolResult(content: unknown): string {\r\n const text = typeof content === 'string' ? content : '';\r\n if (text.length <= TOOL_RESULT_MAX_CHARS) return text;\r\n return `${text.slice(0, TOOL_RESULT_MAX_CHARS)}\\n…(返回已截断,原始长度 ${text.length} 字符)`;\r\n}\r\n\r\n/** 调用签名(与 folded-tool-activity 折叠行同格式):read/edit/write 取文件名,invoke_skill 取技能名,其余用工具名。 */\r\nfunction toolCallSignature(call: any): string {\r\n const name = typeof call?.name === 'string' && call.name ? call.name : 'tool';\r\n let args = call?.arguments ?? call?.args;\r\n if (typeof args === 'string') {\r\n try { args = JSON.parse(args); } catch { args = null; }\r\n }\r\n if (args && typeof args === 'object') {\r\n const record = args as Record<string, unknown>;\r\n const filePath = typeof record.filePath === 'string' ? record.filePath : '';\r\n if ((name === 'read' || name === 'edit' || name === 'write') && filePath) {\r\n return `${name}(${filePath.split(/[\\\\/]/).pop() || filePath})`;\r\n }\r\n if (name === 'invoke_skill' && typeof record.skill === 'string') {\r\n return `invoke_skill(${record.skill})`;\r\n }\r\n }\r\n return name;\r\n}\r\n\r\nfunction buildChatMessages(snapshot: AgentSessionSnapshot, prompt: string): Message[] {\r\n const rawMessages = extractMessages(snapshot);\r\n const sys: Message = { role: 'system', content: `${SUMMARY_ROLE_PREAMBLE}\\n\\n${prompt}` };\r\n // 剥离会话头部的静态 system 前缀(身份设定、环境文档、全局约束),\r\n // 由摘要指令替换其成为唯一 system 前缀,避免模型在摘要请求中继续扮演原 agent。\r\n // 对话中途注入的 system(folded-tool-activity、前轮摘要 seed、任务状态等)\r\n // 不在头部前缀内,作为摘要素材原样保留。\r\n let headEnd = 0;\r\n while (headEnd < rawMessages.length && rawMessages[headEnd]?.role === 'system') headEnd++;\r\n\r\n // 工具返回配对表:toolCallId → 调用签名,让摘要模型能把每条返回对应到具体调用。\r\n // 补偿型摘要的增量信息(文件内容、命令输出、报错原文)都在工具返回里,\r\n // 必须随对话主体一起进入摘要请求,否则模型只能依赖 assistant 的转述。\r\n const callSignatures = new Map<string, string>();\r\n for (const m of rawMessages) {\r\n if (m?.role !== 'assistant' || !Array.isArray(m.toolCalls)) continue;\r\n for (const tc of m.toolCalls) {\r\n const id = typeof tc?.id === 'string' ? tc.id : '';\r\n if (id) callSignatures.set(id, toolCallSignature(tc));\r\n }\r\n }\r\n\r\n const history: Message[] = [];\r\n for (const m of rawMessages.slice(headEnd)) {\r\n if (m?.role === 'tool') {\r\n const signature = (typeof m?.toolCallId === 'string' && callSignatures.get(m.toolCallId)) || '未匹配调用';\r\n history.push({\r\n role: 'system',\r\n content: `[工具返回 ${signature}]\\n${truncateToolResult(m?.content)}`,\r\n tag: 'tool-result',\r\n } as Message);\r\n continue;\r\n }\r\n history.push({\r\n role: m?.role,\r\n content: typeof m?.content === 'string' ? m.content : '',\r\n turn: m?.turn,\r\n ...(m?.tag ? { tag: m.tag } : {}),\r\n } as Message);\r\n }\r\n const closing: Message = { role: 'user', content: SUMMARY_CLOSING_ANCHOR };\r\n return [sys, ...history, closing].filter((m) => m.role === 'system' || m.role === 'user' || m.role === 'assistant');\r\n}\r\n\r\n/** 调用 llm 生成摘要文本(空工具集、非流式)。失败时抛出。 */\r\nexport async function generateSummaryText(\r\n ctx: TransformContext,\r\n snapshot: AgentSessionSnapshot,\r\n prompt: string,\r\n): Promise<string> {\r\n const messages = buildChatMessages(snapshot, prompt);\r\n const response: LLMResponse = await ctx.llm.chat(messages, [], {\r\n noStream: true,\r\n ...(ctx.signal ? { signal: ctx.signal } : {}),\r\n });\r\n const text = stripCompactAnalysis(response.content ?? '');\r\n if (!text) {\r\n throw new Error('Summary LLM returned an empty summary');\r\n }\r\n return text;\r\n}\r\n\r\n// ============ Transformation 契约实现 ============\r\n\r\nexport interface SummaryTransformationOptions {\r\n defaultPolicy?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Summary 变换:对源会话快照做摘要变换,产出 SuccessorSeed。\r\n * 摘要由 `TransformContext.llm` 进程内生成(对齐 ADR-0002 Q3=A)。\r\n */\r\nexport class SummaryTransformation implements SessionTransformation {\r\n readonly id = 'agentdev.summary';\r\n\r\n private readonly defaultPolicy: Record<string, unknown>;\r\n\r\n constructor(options: SummaryTransformationOptions = {}) {\r\n this.defaultPolicy = options.defaultPolicy ?? {};\r\n }\r\n\r\n async transform(input: TransformInput, ctx: TransformContext): Promise<SuccessorSeed> {\r\n const snapshot: AgentSessionSnapshot = input.sourceSnapshot;\r\n const policy = normalizeSummaryPolicy({ ...this.defaultPolicy, ...(input.policy ?? {}) });\r\n const prompt = buildSummaryPrompt({ additionalInstructions: policy.additionalInstructions });\r\n const summaryText = await generateSummaryText(ctx, snapshot, prompt);\r\n const scanned = scanFilesAndSkills(extractMessages(snapshot));\r\n\r\n return {\r\n schemaVersion: HANDOFF_SCHEMA_VERSION,\r\n seedMessages: [buildSummarySeedMessage(summaryText)],\r\n importantFiles: scanned.files,\r\n importantSkills: scanned.skills,\r\n fileRanges: scanned.fileRanges,\r\n meta: {\r\n compilerVersion: 'summarized-nine-section-v1',\r\n seedKind: 'summary-message',\r\n mode: policy.strategy,\r\n summaryShape: policy.summaryShape,\r\n policy,\r\n summaryText,\r\n summaryChars: summaryText.length,\r\n },\r\n };\r\n }\r\n}\r\n\r\nexport interface TrimTranscriptWithSummaryOptions {\r\n /** 注入自定 trim 初始策略(组合语义,硬编码追加摘要)。 */\r\n trimPolicy?: Record<string, unknown>;\r\n /** 摘要生成时的附加指令。 */\r\n additionalInstructions?: string;\r\n}\r\n\r\n/**\r\n * Trim-Transcript-with-Summary 官方单实现(ticket 006 收敛定案)。\r\n *\r\n * 组合语义 1:1 迁移自 Claw `trim-transcript-with-summary`:先对源会话做\r\n * trim 裁剪(默认策略),再用 `TransformContext.llm` 生成摘要,并把摘要\r\n * 种子消息追加到裁剪后的种子消息尾部。不做通用 compose 组合子机制。\r\n */\r\nexport class TrimTranscriptWithSummaryTransformation implements SessionTransformation {\r\n readonly id = 'agentdev.trim-transcript-with-summary';\r\n\r\n private readonly options: TrimTranscriptWithSummaryOptions;\r\n\r\n constructor(options: TrimTranscriptWithSummaryOptions = {}) {\r\n this.options = options;\r\n }\r\n\r\n async transform(input: TransformInput, ctx: TransformContext): Promise<SuccessorSeed> {\r\n const snapshot: AgentSessionSnapshot = input.sourceSnapshot;\r\n const rawMessages = extractMessages(snapshot);\r\n\r\n // 1) trim 裁剪\r\n const trimPolicy = normalizeExportPolicy({ ...DEFAULT_EXPORT_POLICY, ...(this.options.trimPolicy ?? {}), ...(input.policy ?? {}) });\r\n const { seedMessages, stats } = buildTrimmedSeedMessages(rawMessages, trimPolicy);\r\n\r\n // 2) 摘要生成(trimAppended 提示词)\r\n const prompt = buildSummaryPrompt({\r\n trimAppended: true,\r\n additionalInstructions: this.options.additionalInstructions,\r\n });\r\n const summaryText = await generateSummaryText(ctx, snapshot, prompt);\r\n const scanned = scanFilesAndSkills(rawMessages);\r\n\r\n // 3) 摘要种子消息追加到末尾\r\n const combinedSeedMessages = [\r\n ...seedMessages,\r\n buildSummarySeedMessage(summaryText),\r\n ];\r\n\r\n return {\r\n schemaVersion: HANDOFF_SCHEMA_VERSION,\r\n seedMessages: combinedSeedMessages,\r\n importantFiles: scanned.files,\r\n importantSkills: scanned.skills,\r\n fileRanges: scanned.fileRanges,\r\n meta: {\r\n compilerVersion: 'trim-transcript-v1',\r\n seedKind: 'message-replay',\r\n mode: 'trim-transcript-with-summary',\r\n trimPolicy,\r\n trimStats: stats,\r\n summaryText,\r\n summaryChars: summaryText.length,\r\n appendedSummary: {\r\n summaryText,\r\n importantFiles: scanned.files,\r\n importantSkills: scanned.skills,\r\n fileRanges: scanned.fileRanges,\r\n },\r\n },\r\n };\r\n }\r\n}\r\n","/**\n * Continuity Participant(中性化协议层,ticket 006 从 Claw 下沉)。\n *\n * 让一个 Feature 类获得 AgentDev continuity 协议的自声明能力。\n *\n * 设计理念:\n * - 框架自带的 Feature 不需要知道 continuity 的具体协议,本模块以「包装类继承\n * 原 feature」模式为它们附加协议字段,与「extends 原 feature 添加能力」是\n * 同一种模式。\n * - 包装类负责三件事:\n * 1. 提供 getContinuityDescriptor(),让 import 端可从 agent 实例查询声明\n * 2. override captureState(),把 descriptor 注入 snapshot(让无 agent 的\n * export 端也能读到)\n * 3. override restoreState(),把 descriptor 字段剥离后再交给原 feature 处理\n * - 第三方 feature 想参与 continuity 时,自己 declareContinuity 包装一下即可,\n * 无需回框架中心登记。\n */\n\nimport type { AgentFeature, FeatureStateSnapshot } from '../feature.js';\n\n/**\n * 快照中携带 continuity descriptor 的保留字段名。\n * 加 __ 前缀降低与业务字段碰撞的概率。\n *\n * (ticket 006 中性化:原 Claw 字段 `__claw_continuity__` → `__agentdev_continuity__`)\n */\nexport const CONTINUITY_FIELD_KEY = '__agentdev_continuity__';\n\n/**\n * 通用 continuity 协议:无 schema 适配,state 原样进出。\n *\n * 大多数 feature 用这个协议就够了——只要它的 captureState 返回值是\n * 可序列化的纯数据,无需特化清理。\n */\nexport const GENERIC_CONTINUITY_PROTOCOL = 'agentdev.feature-continuity.v1';\n\n/**\n * OpencodeBasic 的专用 continuity 协议。\n *\n * 接续时保留「先读后写」校验需要的 readFiles,\n * 但不继承依赖旧上下文内容的 readDedupState。\n */\nexport const OPENCODE_BASIC_CONTINUITY_PROTOCOL = 'agentdev.opencode-basic-continuity.v1';\n\n/**\n * AgentDev continuity descriptor:feature 自声明参与 continuity 的合约。\n *\n * protocol —— 协议标识符。协议层维护一张 protocol → adapter 的开放命名空间,\n * 未登记的 protocol 走透传(无 adapter)。只有需要特化清理\n * (如 schema 规范化)的协议才在协议层登记 adapter。\n * importMode —— 导入时的合并语义。当前仅 'replace'(直接覆盖 feature 内存状态)。\n */\nexport interface AgentdevContinuityDescriptor {\n protocol: string;\n importMode?: 'replace' | 'merge';\n}\n\n/** 从 snapshot 读取 continuity descriptor。无声明返回 null。 */\nexport function readContinuityDescriptor(snapshot: unknown): AgentdevContinuityDescriptor | null {\n if (!snapshot || typeof snapshot !== 'object') return null;\n const descriptor = (snapshot as Record<string, unknown>)[CONTINUITY_FIELD_KEY];\n if (!descriptor || typeof descriptor !== 'object') return null;\n const protocol = (descriptor as { protocol?: unknown }).protocol;\n if (typeof protocol !== 'string' || !protocol.trim()) return null;\n return descriptor as AgentdevContinuityDescriptor;\n}\n\n/** 从 snapshot 剥离 continuity 字段,返回纯 state。 */\nexport function stripContinuityField(snapshot: unknown): unknown {\n if (!snapshot || typeof snapshot !== 'object') return snapshot;\n const record = snapshot as Record<string, unknown>;\n if (!(CONTINUITY_FIELD_KEY in record)) return snapshot;\n const rest: Record<string, unknown> = {};\n for (const key of Object.keys(record)) {\n if (key !== CONTINUITY_FIELD_KEY) {\n rest[key] = record[key];\n }\n }\n return rest;\n}\n\ntype AnyFeatureConstructor = new (...args: any[]) => AgentFeature;\n\n/**\n * 高阶函数:让一个 Feature 类获得 continuity 自声明能力。\n *\n * @example\n * ```ts\n * import { OpencodeBasicFeature } from '@agentdevjs/core';\n * import { declareContinuity, GENERIC_CONTINUITY_PROTOCOL } from '@agentdevjs/core';\n *\n * export const ContinuityAwareOpencodeBasic = declareContinuity(OpencodeBasicFeature, {\n * protocol: GENERIC_CONTINUITY_PROTOCOL,\n * importMode: 'replace',\n * });\n * ```\n *\n * 包装后的类:\n * - 继承原 feature 的所有行为(工具、hooks、原 captureState/restoreState 语义)\n * - 多出 getContinuityDescriptor() 方法\n * - captureState 在原返回值上叠加 [CONTINUITY_FIELD_KEY] 字段\n * - restoreState 先剥离该字段再调用原 restoreState\n */\nexport function declareContinuity<T extends AnyFeatureConstructor>(\n Base: T,\n descriptor: AgentdevContinuityDescriptor,\n): T {\n const normalizedDescriptor: AgentdevContinuityDescriptor = {\n protocol: descriptor.protocol,\n importMode: descriptor.importMode === 'merge' ? 'merge' : 'replace',\n };\n\n return class ContinuityAware extends Base {\n /**\n * 标志位:restoreState 是否被调用过。\n * - restored resume / session load 场景:restoreState 被调用 → true\n * - 全新 session 首次启动:restoreState 未被调用 → false\n * onInitiate 根据此标志决定是否保护已恢复的状态。\n */\n private _continuityStateRestored = false;\n\n getContinuityDescriptor(): AgentdevContinuityDescriptor {\n return { ...normalizedDescriptor };\n }\n\n /**\n * Override onInitiate:防止基类的初始化逻辑清空 continuity/session 已恢复的状态。\n *\n * 策略:仅当 restoreState 被调用过(_continuityStateRestored=true)时,才在基类\n * onInitiate 执行后用 buffer 恢复状态。全新 session 首次启动时不干预,保留基类\n * onInitiate 的默认初始化行为。\n */\n async onInitiate(ctx: any): Promise<void> {\n const wasRestored = this._continuityStateRestored;\n const beforeBuffer = wasRestored ? stripContinuityField(super.captureState!()) : null;\n\n if (typeof super.onInitiate === 'function') {\n await super.onInitiate(ctx);\n }\n\n if (wasRestored && beforeBuffer && typeof beforeBuffer === 'object') {\n await super.restoreState!(beforeBuffer as FeatureStateSnapshot);\n }\n }\n\n captureState(): FeatureStateSnapshot {\n const base = super.captureState!();\n if (base && typeof base === 'object') {\n return { ...(base as Record<string, unknown>), [CONTINUITY_FIELD_KEY]: normalizedDescriptor };\n }\n return { [CONTINUITY_FIELD_KEY]: normalizedDescriptor } as FeatureStateSnapshot;\n }\n\n async restoreState(snapshot: FeatureStateSnapshot): Promise<void> {\n this._continuityStateRestored = true;\n if (snapshot && typeof snapshot === 'object' && CONTINUITY_FIELD_KEY in (snapshot as Record<string, unknown>)) {\n const stripped = stripContinuityField(snapshot);\n await super.restoreState!(stripped as FeatureStateSnapshot);\n return;\n }\n await super.restoreState!(snapshot);\n }\n };\n}\n","/**\r\n * WorkThreadStore — WorkThread 锚点层持久化存储\r\n *\r\n * 移植自 Claw `server/thread-control/thread-store.js`(原子写 / per-thread 串行锁 /\r\n * revision 乐观并发),只保留锚点层字段——sessionChain / head / pendingSuccession /\r\n * commands / hold / 接续编排状态(open / rotating / rotation_failed / closed)。\r\n *\r\n * 执行调度看板字段(executionEvents / mode / idle–failed 状态)不在此文件;\r\n * 那是可选 WorkThreadBoard 的持久化域,见 board.ts。本模块 import 面不含看板状态值。\r\n *\r\n * 设计要点:\r\n * - 每个 WorkThread 一个 JSON 文件(thread 记录 + inbox commands + hold),\r\n * 保证「head 推进 + 指令状态变更 + 挡板清除」可以在同一次原子写内完成。\r\n * - index.json 仅保存列表摘要,供轻量列举。\r\n * - 所有写操作走 per-thread 串行锁 + revision 自增 + tmp/rename 原子写。\r\n * - 支持 expectedRevision 乐观并发控制(head 推进等关键事务使用)。\r\n *\r\n * 数据目录由构造时必传 rootDir(框架不定义默认根,宿主决定归属规模)。\r\n * 并发模型:per-thread 串行锁只在单宿主进程内成立;多宿主进程共用同一数据\r\n * 目录时未定义,当前单宿主前提下接受(ADR-0002 后果项)。\r\n */\r\n\r\nimport { copyFile, mkdir, readFile, rename, unlink, writeFile } from 'fs/promises';\r\nimport { join } from 'path';\r\nimport { randomUUID } from 'crypto';\r\nimport type { WorkThreadCommand } from './inbox.js';\r\n\r\nexport interface WorkThreadChainEntry {\r\n sessionId: string;\r\n role: 'head' | 'predecessor';\r\n startedAt: number;\r\n endedAt: number | null;\r\n endKind: string | null;\r\n successorSessionId: string | null;\r\n}\r\n\r\n/** 交接意图(pendingSuccession)单一真相、落盘。 */\r\nexport interface WorkThreadPendingSuccession {\r\n fromSessionId: string;\r\n reason: string;\r\n stage: string;\r\n startedAt: number;\r\n}\r\n\r\n/** 锚点层接续编排状态。执行调度状态机(看板执行态)归看板层。 */\r\nexport type WorkThreadStatus = 'open' | 'rotating' | 'rotation_failed' | 'closed';\r\n\r\nexport interface WorkThreadLifecycleEvent {\r\n type: string;\r\n status: string;\r\n at: number;\r\n [key: string]: unknown;\r\n}\r\n\r\nexport interface WorkThreadRecord {\r\n threadId: string;\r\n agentId: string;\r\n workspaceId?: string;\r\n title?: string;\r\n status: WorkThreadStatus;\r\n /**\r\n * 线程的产品身份归属(T001:身份连续性不变量的事实来源)。\r\n * 新建线程时从 root Session 解析确定;`null` = 身份未知(历史数据缺少\r\n * 该字段时的读时归一值——明确「未知」,绝不静默回填为任何具体身份)。\r\n */\r\n identity?: string | null;\r\n rootSessionId: string;\r\n headSessionId: string;\r\n sessionChain: WorkThreadChainEntry[];\r\n commands: WorkThreadCommand[];\r\n pendingSuccession: WorkThreadPendingSuccession | null;\r\n /** 宿主级「暂停投递」落盘第一等布尔开关(重启不丢)。 */\r\n hold: boolean;\r\n closedAt?: number;\r\n closeReason?: string;\r\n lifecycleEvents: WorkThreadLifecycleEvent[];\r\n lastLifecycleEvent: WorkThreadLifecycleEvent | null;\r\n revision: number;\r\n createdAt: number;\r\n updatedAt: number;\r\n}\r\n\r\nexport class WorkThreadNotFoundError extends Error {\r\n readonly code = 'workthread_not_found';\r\n constructor(threadId: string) {\r\n super(`WorkThread \"${threadId}\" not found`);\r\n this.name = 'WorkThreadNotFoundError';\r\n }\r\n}\r\n\r\nexport class WorkThreadRevisionConflictError extends Error {\r\n readonly code = 'revision_conflict';\r\n readonly expected: number;\r\n readonly actual: number;\r\n constructor(threadId: string, expected: number, actual: number) {\r\n super(`Revision conflict on workthread \"${threadId}\": expected ${expected}, current ${actual}`);\r\n this.name = 'WorkThreadRevisionConflictError';\r\n this.expected = expected;\r\n this.actual = actual;\r\n }\r\n}\r\n\r\nexport function generateWorkThreadId(): string {\r\n return `wt-${randomUUID()}`;\r\n}\r\n\r\n/**\r\n * 线程 id 用于文件名:清除非法字符,防止路径穿越。\r\n * 与 Claw shared/string-helpers.sanitizeSessionFragment 逐字节一致。\r\n */\r\nexport function sanitizeWorkThreadFragment(value: unknown): string {\r\n return String(value || '')\r\n .trim()\r\n .replace(/[^a-zA-Z0-9_-]+/g, '-')\r\n .replace(/-+/g, '-')\r\n .replace(/^-|-$/g, '') || 'default';\r\n}\r\n\r\nfunction threadContentSignature(record: WorkThreadRecord): string {\r\n const { revision: _revision, updatedAt: _updatedAt, ...rest } = record;\r\n return JSON.stringify(rest);\r\n}\r\n\r\n// 旧状态空间(active/completed/cancelled/blocked)的读时归一,映射到新锚点域。\r\n// 盘上旧值不允许流入控制器,下次写盘会自动落成新值。\r\nconst LEGACY_STATUS_MAP: Record<string, WorkThreadStatus> = {\r\n active: 'open',\r\n completed: 'closed',\r\n cancelled: 'closed',\r\n blocked: 'open',\r\n};\r\n\r\nfunction normalizeThreadRecord(record: WorkThreadRecord): WorkThreadRecord {\r\n if (record && typeof record === 'object') {\r\n if (LEGACY_STATUS_MAP[record.status]) {\r\n record.status = LEGACY_STATUS_MAP[record.status];\r\n }\r\n // T001 身份归属读时归一:缺失 / 空串统一为 null(身份未知)。\r\n // 不可静默把历史线程成员当成 main——未知是明确的机器可判定状态。\r\n record.identity =\r\n typeof record.identity === 'string' && record.identity.trim()\r\n ? record.identity.trim()\r\n : null;\r\n }\r\n return record;\r\n}\r\n\r\nexport interface WorkThreadStoreOptions {\r\n rootDir: string;\r\n}\r\n\r\nexport class WorkThreadStore {\r\n readonly rootDir: string;\r\n readonly threadsDir: string;\r\n readonly indexPath: string;\r\n private _threadLocks = new Map<string, Promise<void>>();\r\n private _indexLock: Promise<void> = Promise.resolve();\r\n\r\n constructor({ rootDir }: WorkThreadStoreOptions) {\r\n if (!rootDir || typeof rootDir !== 'string') {\r\n throw new Error('WorkThreadStore requires a rootDir');\r\n }\r\n this.rootDir = rootDir;\r\n this.threadsDir = join(rootDir, 'threads');\r\n this.indexPath = join(rootDir, 'index.json');\r\n }\r\n\r\n // ── 路径 ──────────────────────────────────────────────────────────\r\n\r\n private threadFilePath(threadId: string): string {\r\n return join(this.threadsDir, `${sanitizeWorkThreadFragment(threadId)}.json`);\r\n }\r\n\r\n // ── 原子写(对齐 FileSessionStore 模式,兼容 Windows EPERM/EXDEV)─\r\n\r\n private async atomicWriteJson(filePath: string, data: unknown): Promise<void> {\r\n const tmpPath = `${filePath}.tmp`;\r\n await writeFile(tmpPath, JSON.stringify(data, null, 2), 'utf8');\r\n try {\r\n await rename(tmpPath, filePath);\r\n } catch (err) {\r\n const code = (err as NodeJS.ErrnoException).code;\r\n if (code === 'EPERM' || code === 'EACCES') {\r\n await unlink(filePath).catch(() => {});\r\n await rename(tmpPath, filePath);\r\n } else if (code === 'EXDEV') {\r\n await copyFile(tmpPath, filePath);\r\n await unlink(tmpPath).catch(() => {});\r\n } else {\r\n throw err;\r\n }\r\n }\r\n }\r\n\r\n // ── index(列表摘要)─────────────────────────────────────────────\r\n\r\n private async readIndex(): Promise<{ revision: number; threads: unknown[] }> {\r\n try {\r\n const raw = JSON.parse(await readFile(this.indexPath, 'utf8')) as {\r\n revision?: number;\r\n threads?: unknown[];\r\n };\r\n const threads = Array.isArray(raw.threads) ? raw.threads : [];\r\n return {\r\n revision:\r\n Number.isSafeInteger(Number(raw.revision)) && Number(raw.revision) >= 0\r\n ? Number(raw.revision)\r\n : 0,\r\n threads,\r\n };\r\n } catch {\r\n return { revision: 0, threads: [] };\r\n }\r\n }\r\n\r\n private async writeIndex(index: unknown): Promise<void> {\r\n await mkdir(this.rootDir, { recursive: true });\r\n await this.atomicWriteJson(this.indexPath, index);\r\n }\r\n\r\n private async updateIndexEntry(record: WorkThreadRecord): Promise<void> {\r\n const prev = this._indexLock;\r\n let release!: () => void;\r\n const next = new Promise<void>((r) => (release = r));\r\n this._indexLock = next;\r\n await prev.catch(() => {});\r\n try {\r\n const index = await this.readIndex();\r\n const entry = {\r\n threadId: record.threadId,\r\n agentId: record.agentId,\r\n workspaceId: record.workspaceId || '',\r\n title: record.title || '',\r\n status: LEGACY_STATUS_MAP[record.status] || record.status || 'open',\r\n rootSessionId: record.rootSessionId || '',\r\n headSessionId: record.headSessionId || '',\r\n // T001:线程身份归属(轻量事实,供成员/head 查询统一取用);\r\n // 旧记录缺字段时为 null(身份未知,前端不得据此默认渲染)。\r\n identity: typeof record.identity === 'string' && record.identity.trim()\r\n ? record.identity.trim()\r\n : null,\r\n // 链成员 id 列表(轻量,供前端徽标判定「会话是否属于线程」)\r\n sessionIds: (Array.isArray(record.sessionChain) ? record.sessionChain : []).map(\r\n (entry) => entry?.sessionId || '',\r\n ).filter(Boolean),\r\n // 每棒接力边(轻量,供前端接力分隔条渲染):非 root 会话的来源与方式\r\n chainEdges: buildChainEdges(record),\r\n // 交接意图原始时间戳(0 = 无);fresh 与否由读取方按统一规则派生\r\n handoffStartedAt: Number(record.pendingSuccession?.startedAt) || 0,\r\n handoffStage: record.pendingSuccession?.stage || null,\r\n hold: record.hold === true,\r\n lastLifecycleEvent: record.lastLifecycleEvent || null,\r\n // pending 指令文本预览(轻量,上限 5 条)\r\n pendingTexts: (Array.isArray(record.commands) ? record.commands : [])\r\n .filter((c) => c?.status === 'pending')\r\n .slice(0, 5)\r\n .map((c) => String(c?.text || '').slice(0, 120)),\r\n revision: record.revision,\r\n createdAt: record.createdAt,\r\n updatedAt: record.updatedAt,\r\n };\r\n const existingIdx = (index.threads as Array<{ threadId?: string }>).findIndex(\r\n (t) => t?.threadId === record.threadId,\r\n );\r\n if (existingIdx >= 0) {\r\n (index.threads as unknown[])[existingIdx] = entry;\r\n } else {\r\n index.threads.push(entry as unknown);\r\n }\r\n index.revision = (Number(index.revision) || 0) + 1;\r\n await this.writeIndex(index);\r\n } finally {\r\n release();\r\n }\r\n }\r\n\r\n // ── 读 ───────────────────────────────────────────────────────────\r\n\r\n async list(): Promise<unknown[]> {\r\n const index = await this.readIndex();\r\n return index.threads;\r\n }\r\n\r\n async get(threadId: string): Promise<WorkThreadRecord | null> {\r\n if (!threadId || typeof threadId !== 'string') return null;\r\n try {\r\n const parsed = JSON.parse(\r\n await readFile(this.threadFilePath(threadId), 'utf8'),\r\n ) as WorkThreadRecord;\r\n return normalizeThreadRecord(parsed);\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n // ── 写 ───────────────────────────────────────────────────────────\r\n\r\n /** 创建线程记录。要求调用方已构建完整初始记录。 */\r\n async create(record: WorkThreadRecord): Promise<WorkThreadRecord> {\r\n const threadId = record?.threadId;\r\n if (!threadId) throw new Error('WorkThreadStore.create requires record.threadId');\r\n await mkdir(this.threadsDir, { recursive: true });\r\n const existing = await this.get(threadId);\r\n if (existing) {\r\n throw new Error(`WorkThread \"${threadId}\" already exists`);\r\n }\r\n const normalized = normalizeThreadRecord(record);\r\n await this.atomicWriteJson(this.threadFilePath(threadId), normalized);\r\n await this.updateIndexEntry(normalized);\r\n return normalized;\r\n }\r\n\r\n /**\r\n * 串行化更新单个线程记录。\r\n * @param expectedRevision 乐观并发检查\r\n * @returns {changed} 无内容变更(元数据更新)时 false,revision 不递增\r\n */\r\n async update(\r\n threadId: string,\r\n mutFn: (\r\n record: WorkThreadRecord,\r\n ) => WorkThreadRecord | null | undefined | Promise<WorkThreadRecord | null | undefined>,\r\n options: { expectedRevision?: number } = {},\r\n ): Promise<{ record: WorkThreadRecord; changed: boolean }> {\r\n const prev = this._threadLocks.get(threadId) || Promise.resolve();\r\n let release!: () => void;\r\n const next = new Promise<void>((r) => (release = r));\r\n this._threadLocks.set(threadId, next);\r\n await prev.catch(() => {});\r\n try {\r\n const record = await this.get(threadId);\r\n if (!record) {\r\n throw new WorkThreadNotFoundError(threadId);\r\n }\r\n if (Number.isInteger(options.expectedRevision) && record.revision !== options.expectedRevision) {\r\n throw new WorkThreadRevisionConflictError(\r\n threadId,\r\n options.expectedRevision as number,\r\n record.revision,\r\n );\r\n }\r\n\r\n const before = threadContentSignature(record);\r\n const proposed = await mutFn(record);\r\n if (!proposed || typeof proposed !== 'object') {\r\n throw new Error('WorkThreadStore.update mutFn must return the record');\r\n }\r\n const after = threadContentSignature(proposed);\r\n\r\n if (after === before) {\r\n return { record, changed: false };\r\n }\r\n\r\n const nextRecord: WorkThreadRecord = {\r\n ...proposed,\r\n revision: (Number(record.revision) || 0) + 1,\r\n updatedAt: Date.now(),\r\n };\r\n await this.atomicWriteJson(this.threadFilePath(threadId), nextRecord);\r\n await this.updateIndexEntry(nextRecord);\r\n return { record: nextRecord, changed: true };\r\n } finally {\r\n release();\r\n if (this._threadLocks.get(threadId) === next) this._threadLocks.delete(threadId);\r\n }\r\n }\r\n}\r\n\r\nfunction buildChainEdges(record: WorkThreadRecord): Array<{\r\n sessionId: string;\r\n fromSessionId: string;\r\n relayKind: string;\r\n}> {\r\n const chain = Array.isArray(record.sessionChain) ? record.sessionChain : [];\r\n const bySuccessor = new Map<string, WorkThreadChainEntry>();\r\n for (const entry of chain) {\r\n if (entry?.successorSessionId && entry?.sessionId) {\r\n bySuccessor.set(entry.successorSessionId, entry);\r\n }\r\n }\r\n return chain\r\n .filter((entry) => entry?.sessionId && entry.sessionId !== record.rootSessionId)\r\n .map((entry) => {\r\n const pred = bySuccessor.get(entry.sessionId);\r\n return {\r\n sessionId: entry.sessionId,\r\n fromSessionId: pred?.sessionId || '',\r\n relayKind: pred?.endKind || '',\r\n };\r\n });\r\n}\r\n","/**\n * WorkThread Inbox — WorkThread 级待投递指令(纯函数层)\n *\n * 移植自 Claw `server/thread-control/thread-inbox.js`(幂等入队 / 稳定排序 /\n * 终态裁剪)。语义定位:这条指令属于某项连续工作(WorkThread),而不属于某个\n * 可能被替换的 runtime。指令先持久化(pending),由 WorkThread 在当前承接会话\n * 可用时经 bridge 下沉为 runtime envelope(delivered)。\n *\n * 本模块不持有状态、不做 IO;所有操作作用于 thread record 的 `commands` 数组,\n * 由 WorkThreadStore 的原子写保证持久化。\n *\n * 不承诺 LLM 副作用 exactly-once:只承诺命令身份持久化 + 幂等入队 + 可追踪的\n * 投递状态。真实世界副作用由新会话核对现实状态后继续。\n */\n\nimport { randomUUID } from 'crypto';\n\nexport const WorkThreadCommandStatus = Object.freeze({\n PENDING: 'pending',\n IN_FLIGHT: 'in_flight',\n DELIVERED: 'delivered',\n FAILED: 'failed',\n CANCELLED: 'cancelled',\n} as const);\n\nexport type WorkThreadCommandStatusValue = (typeof WorkThreadCommandStatus)[keyof typeof WorkThreadCommandStatus];\n\nexport type WorkThreadCommandStatusName = keyof typeof WorkThreadCommandStatus;\n\nconst TERMINAL_STATUSES = new Set<string>([\n WorkThreadCommandStatus.DELIVERED,\n WorkThreadCommandStatus.FAILED,\n WorkThreadCommandStatus.CANCELLED,\n]);\n\nexport const WorkThreadCommandKind = Object.freeze({\n USER_MESSAGE: 'user_message',\n SYSTEM_CONTINUATION: 'system_continuation',\n EXTERNAL: 'external',\n} as const);\n\nexport type WorkThreadCommandKindValue = (typeof WorkThreadCommandKind)[keyof typeof WorkThreadCommandKind];\n\n/** 终态指令保留上限(超出按时间裁剪,防止 commands 无限增长) */\nexport const MAX_RETAINED_TERMINAL_COMMANDS = 200;\n\nexport function generateCommandId(): string {\n return `cmd-${randomUUID()}`;\n}\n\nexport interface WorkThreadCommand {\n commandId: string;\n threadId: string;\n kind: string;\n text: string;\n source: string;\n idempotencyKey: string;\n status: WorkThreadCommandStatusValue;\n attempts: number;\n envelopeId: string | null;\n lastReason: string | null;\n createdAt: number;\n updatedAt: number;\n deliveredAt: number | null;\n deliveryRef?: string | null;\n /** 随指令流动的能力激活通知(capability refs),投递时随 user-turn 元数据转发 */\n capabilityActivations?: string[];\n}\n\n/**\n * 构造新指令记录(不修改 thread record)。\n */\nexport function createCommandRecord(opts: {\n threadId: string;\n kind?: string;\n text?: string;\n source?: string;\n idempotencyKey?: string;\n capabilityActivations?: string[];\n}): WorkThreadCommand {\n const now = Date.now();\n return {\n commandId: generateCommandId(),\n threadId: opts.threadId || '',\n kind: opts.kind || WorkThreadCommandKind.USER_MESSAGE,\n text: typeof opts.text === 'string' ? opts.text : '',\n source: opts.source || 'ui',\n idempotencyKey: opts.idempotencyKey || '',\n status: WorkThreadCommandStatus.PENDING,\n attempts: 0,\n envelopeId: null,\n lastReason: null,\n createdAt: now,\n updatedAt: now,\n deliveredAt: null,\n ...(Array.isArray(opts.capabilityActivations) && opts.capabilityActivations.length > 0\n ? { capabilityActivations: opts.capabilityActivations.filter((a) => typeof a === 'string') }\n : {}),\n };\n}\n\n/**\n * 幂等追加指令。若 idempotencyKey 命中既有的 pending / in_flight / delivered\n * 指令,直接返回既有指令(重复提交不产生副作用)。\n * @returns {{command: WorkThreadCommand, duplicate: boolean}}\n */\nexport function appendCommand(\n record: { commands?: WorkThreadCommand[] },\n command: WorkThreadCommand,\n): { command: WorkThreadCommand; duplicate: boolean } {\n const commands = Array.isArray(record.commands) ? record.commands : [];\n record.commands = commands;\n\n if (command.idempotencyKey) {\n const existing = commands.find(\n (c) =>\n c.idempotencyKey === command.idempotencyKey &&\n (c.status === WorkThreadCommandStatus.PENDING ||\n c.status === WorkThreadCommandStatus.IN_FLIGHT ||\n c.status === WorkThreadCommandStatus.DELIVERED),\n );\n if (existing) {\n return { command: existing, duplicate: true };\n }\n }\n\n commands.push(command);\n return { command, duplicate: false };\n}\n\n/** 按 createdAt + commandId 稳定排序的 pending 指令。 */\nexport function pendingCommands(record: { commands?: WorkThreadCommand[] }): WorkThreadCommand[] {\n const commands = Array.isArray(record?.commands) ? record.commands : [];\n return commands\n .filter((c) => c?.status === WorkThreadCommandStatus.PENDING)\n .sort((a, b) => a.createdAt - b.createdAt || (a.commandId < b.commandId ? -1 : 1));\n}\n\nexport function findCommand(\n record: { commands?: WorkThreadCommand[] },\n commandId: string,\n): WorkThreadCommand | null {\n const commands = Array.isArray(record?.commands) ? record.commands : [];\n return commands.find((c) => c?.commandId === commandId) || null;\n}\n\n/**\n * 裁剪终态指令,保留最近 maxRetained 条。pending / in_flight 永不裁剪。\n * @returns 是否有被裁掉的(内容变更)\n */\nexport function pruneCommands(\n record: { commands?: WorkThreadCommand[] },\n maxRetained: number = MAX_RETAINED_TERMINAL_COMMANDS,\n): boolean {\n const commands = Array.isArray(record?.commands) ? record.commands : [];\n const terminal = commands.filter((c) => TERMINAL_STATUSES.has(c?.status));\n if (terminal.length <= maxRetained) return false;\n\n const dropSet = new Set(\n terminal\n .sort((a, b) => (b.updatedAt || b.createdAt || 0) - (a.updatedAt || a.createdAt || 0))\n .slice(maxRetained)\n .map((c) => c.commandId),\n );\n record.commands = commands.filter((c) => !dropSet.has(c.commandId));\n return true;\n}\n","/**\n * WorkThreadRuntimeBridge — WorkThread Inbox → head runtime 的最后一跳\n *\n * 移植自 Claw `server/thread-control/thread-runtime-bridge.js`。职责:把一条\n * pending 的 WorkThread 指令下沉到当前承接会话(head session)对应的 runtime。\n * 仅此而已——不运行 Agent、不判断任务完成、不理解执行调度。\n *\n * 注入契约(宿主可 stub,现有测试注入模式不破坏):\n * - `enabled`:桥是否启用(休眠默认 false)。\n * - `resolveRuntimeViewerId(agentId, sessionId)`:runtime 存活且可接收时返回\n * viewerAgentId,否则 null(= runtime 未就绪,指令保持 pending 由调用方重试)。\n * - `submitTurn(params)`:真实投递函数,默认 submitUserTurn。\n */\n\nexport const WORKTHREAD_BRIDGE_DISABLED_REASON = 'bridge_disabled';\nexport const RUNTIME_NOT_ACCEPTING_REASON = 'runtime_not_accepting';\n\nexport interface WorkThreadBridgeSubmitTurnParams {\n agentId: string;\n text: string;\n source: string;\n sourceRef: string;\n capabilityActivations?: string[];\n}\n\nexport interface WorkThreadDeliveryOutcome {\n accepted: boolean;\n reason?: string;\n retryable?: boolean;\n deliveryRef?: string;\n}\n\n/** WorkThread 与 runtime 之间的投递契约(经 {thread, command} 定位目标)。 */\nexport interface WorkThreadBridge {\n isEnabled(): boolean;\n deliver(params: {\n thread: { agentId?: string; headSessionId?: string; threadId?: string };\n command: { commandId?: string; text?: string };\n }): Promise<WorkThreadDeliveryOutcome>;\n}\n\nexport function buildRuntimeKey(agentId: string, sessionId: string): string {\n return `${agentId}::${sessionId}`;\n}\n\nexport interface WorkThreadRuntimeBridgeOptions {\n enabled?: boolean;\n resolveRuntimeViewerId?: ((agentId: string, sessionId: string) => string | null) | null;\n submitTurn?: ((params: WorkThreadBridgeSubmitTurnParams) => Promise<unknown>) | null;\n}\n\nexport class WorkThreadRuntimeBridge implements WorkThreadBridge {\n private readonly _enabled: boolean;\n private readonly _resolveRuntimeViewerId: ((agentId: string, sessionId: string) => string | null) | null;\n private readonly _submitTurn: (params: WorkThreadBridgeSubmitTurnParams) => Promise<unknown>;\n\n constructor({\n enabled = false,\n resolveRuntimeViewerId = null,\n submitTurn = null,\n }: WorkThreadRuntimeBridgeOptions = {}) {\n this._enabled = enabled === true;\n this._resolveRuntimeViewerId =\n typeof resolveRuntimeViewerId === 'function' ? resolveRuntimeViewerId : null;\n this._submitTurn = typeof submitTurn === 'function' ? submitTurn : defaultSubmitTurn;\n }\n\n isEnabled(): boolean {\n return this._enabled === true;\n }\n\n async deliver(params: {\n thread: { agentId?: string; headSessionId?: string; threadId?: string };\n command: { commandId?: string; text?: string; capabilityActivations?: string[] };\n }): Promise<WorkThreadDeliveryOutcome> {\n const { thread, command } = params;\n if (!this.isEnabled()) {\n return { accepted: false, reason: WORKTHREAD_BRIDGE_DISABLED_REASON, retryable: true };\n }\n if (!thread?.agentId || !thread?.headSessionId) {\n return { accepted: false, reason: 'invalid_thread_target', retryable: false };\n }\n\n const viewerAgentId = this._resolveRuntimeViewerId\n ? this._resolveRuntimeViewerId(thread.agentId, thread.headSessionId)\n : null;\n if (!viewerAgentId) {\n // runtime 未就绪(未启动 / 正在换代 / 已停止):指令保持 pending,\n // 由调用方在 head 推进或 runtime ready 后重试。\n return { accepted: false, reason: RUNTIME_NOT_ACCEPTING_REASON, retryable: true };\n }\n\n try {\n // 契约对齐:submitUserTurn 的参数名是 agentId。参数漂移会让客户端预校验\n // 抛 invalid_input(不可重试),指令被误判 failed——契约测试覆盖此点。\n await this._submitTurn({\n agentId: viewerAgentId,\n text: command.text || '',\n source: 'thread',\n sourceRef: command.commandId || '',\n ...(Array.isArray(command.capabilityActivations) && command.capabilityActivations.length > 0\n ? { capabilityActivations: command.capabilityActivations }\n : {}),\n });\n } catch (error) {\n if (isUserTurnDeliveryError(error)) {\n return {\n accepted: false,\n reason: error.code || 'delivery_failed',\n retryable: error.retryable !== false,\n };\n }\n return { accepted: false, reason: 'delivery_failed', retryable: true };\n }\n\n return { accepted: true, deliveryRef: viewerAgentId };\n }\n}\n\ninterface UserTurnDeliveryErrorLike {\n name: string;\n code?: string;\n retryable?: boolean;\n}\n\nfunction isUserTurnDeliveryError(error: unknown): error is UserTurnDeliveryErrorLike {\n return (\n typeof error === 'object' &&\n error !== null &&\n (error as UserTurnDeliveryErrorLike).name === 'UserTurnDeliveryError'\n );\n}\n\n/**\n * 默认 submitTurn。框架 core 域不背 HTTP 客户端依赖,真实投递由宿主经\n * `submitTurn` 注入;未注入时返回一个非重试失败,指令标记 failed。\n */\nasync function defaultSubmitTurn(_params: WorkThreadBridgeSubmitTurnParams): Promise<unknown> {\n const err = new Error('WorkThreadRuntimeBridge: no submitTurn provided (host must inject)');\n (err as Error & { name: string }).name = 'UserTurnDeliveryError';\n (err as Error & { code: string }).code = 'bridge_no_provider';\n (err as Error & { retryable: boolean }).retryable = false;\n throw err;\n}\n","/**\r\n * WorkThread — 框架层「Session + 接续变换」的连续性锚点(锚点层)\r\n *\r\n * 移植自 Claw `server/thread-control/thread-controller.js` 的锚点层成员,按\r\n * ADR-0002/Q4=C 拆分。WorkThread 只承载连续性锚点与接续编排状态:\r\n * - sessionChain / headSessionId(先后接力的 Session 认作同一项工作)\r\n * - 交接挡板 pendingSuccession(beginSessionHandoff / isHandoffActive /\r\n * advanceHead 换代+清挡板原子成对)\r\n * - 指令暂存 Inbox(appendCommand / deliverPendingCommands / cancelCommand)\r\n * - 接续编排状态(rotating / rotation_failed / failSessionHandoff(stage))\r\n * - 宿主级 hold 布尔开关(落盘第一等,重启不丢)\r\n * - closeThread 锚点收口(取消 pending 指令 + terminal 判定)\r\n *\r\n * 不承载执行调度看板(看板执行状态机 / executionEvents / resume / mode)——\r\n * 那是可选平行模块 WorkThreadBoard(board.ts),经 workThreadId 关联,永不反写\r\n * 锚点状态。本模块 import 面不含任何看板状态值。\r\n *\r\n * 投递门槛只保留客观事实:closed?交接窗口 fresh?hold?bridge enabled?\r\n * runtime 接收就绪(注入的 resolveRuntime)。失败 / 等待输入的暂停投递由宿主\r\n * 经 hold 开关表达,不在此层。\r\n */\r\n\r\nimport type { WorkThreadStore, WorkThreadRecord } from './store.js';\r\nimport {\r\n WorkThreadNotFoundError,\r\n} from './store.js';\r\nimport {\r\n createCommandRecord,\r\n appendCommand as appendCommandToRecord,\r\n pendingCommands,\r\n findCommand,\r\n pruneCommands,\r\n WorkThreadCommandStatus,\r\n WorkThreadCommandKind,\r\n type WorkThreadCommand,\r\n} from './inbox.js';\r\nimport { WorkThreadRuntimeBridge, WORKTHREAD_BRIDGE_DISABLED_REASON } from './bridge.js';\r\nimport type { WorkThreadBridge } from './bridge.js';\r\nimport { generateWorkThreadId } from './store.js';\r\n\r\nexport { WorkThreadNotFoundError };\r\n\r\nexport const WORKTHREAD_TERMINAL_STATUS = 'closed';\r\n\r\n/** 交接意图陈旧线:pendingSuccession 超过该时长视为已失效(compact 失败、进程\r\n * 崩溃等路径不会显式清除)。失效后投递自动恢复——此时 head 仍是权威值(旧会话),\r\n * 指令投向它即正确语义。 */\r\nexport const HANDOFF_STALE_MS = 5 * 60 * 1000;\r\n\r\nconst VALID_ID_RE = /^[\\w.-]{1,200}$/;\r\n\r\nfunction validateId(value: unknown, label: string): string {\r\n const id = String(value || '').trim();\r\n if (!VALID_ID_RE.test(id)) {\r\n throw Object.assign(new Error(`Invalid ${label}: ${JSON.stringify(String(value || ''))}`), {\r\n code: 'invalid_request',\r\n status: 400,\r\n });\r\n }\r\n return id;\r\n}\r\n\r\nfunction cleanText(value: unknown): string {\r\n return typeof value === 'string' ? value.trim() : '';\r\n}\r\n\r\nfunction pushLifecycleEvent(\r\n record: WorkThreadRecord,\r\n event: WorkThreadRecord['lifecycleEvents'][number],\r\n maxEvents = 200,\r\n): void {\r\n record.lifecycleEvents = Array.isArray(record.lifecycleEvents) ? record.lifecycleEvents : [];\r\n record.lifecycleEvents.push(event);\r\n if (record.lifecycleEvents.length > maxEvents) {\r\n record.lifecycleEvents.splice(0, record.lifecycleEvents.length - maxEvents);\r\n }\r\n record.lastLifecycleEvent = event;\r\n}\r\n\r\nexport interface WorkThreadStartOptions {\r\n sessionRef: { agentId: string; sessionId: string };\r\n title?: string;\r\n workspaceId?: string;\r\n /**\r\n * T001:显式指定线程身份归属。缺省时由 identitySource 从 root Session\r\n * 解析;解析不到(身份未知)时归属为 null,而不是默认成某个具体身份。\r\n */\r\n identity?: string | null;\r\n}\r\n\r\nexport interface WorkThreadOptions {\r\n store: WorkThreadStore;\r\n bridge?: WorkThreadBridge;\r\n /**\r\n * T001:线程身份解析器(宿主注入的会话身份真相源,如 Claw 的 session\r\n * index)。框架不内置产品身份词汇:返回值即线程归属;空值 = 身份未知。\r\n */\r\n identitySource?: (agentId: string, sessionId: string) => Promise<string | null> | string | null;\r\n}\r\n\r\nfunction threadIdentityError(message: string, code: string, status: number): Error {\r\n return Object.assign(new Error(message), { code, status });\r\n}\r\n\r\nexport class WorkThread {\r\n readonly store: WorkThreadStore;\r\n private readonly _bridge: WorkThreadBridge;\r\n private readonly _identitySource?: (agentId: string, sessionId: string) => Promise<string | null> | string | null;\r\n\r\n constructor({ store, bridge, identitySource }: WorkThreadOptions) {\r\n this.store = store;\r\n this._bridge = bridge || new WorkThreadRuntimeBridge();\r\n this._identitySource =\r\n identitySource && typeof identitySource === 'function' ? identitySource : undefined;\r\n }\r\n\r\n // ── 查询 ─────────────────────────────────────────────────────────\r\n\r\n async listThreads(opts: { agentId?: string } = {}): Promise<unknown[]> {\r\n const entries = await this.store.list();\r\n const normalized = cleanText(opts.agentId || '');\r\n return normalized ? entries.filter((t) => (t as { agentId?: string }).agentId === normalized) : entries;\r\n }\r\n\r\n async getThread(threadId: string): Promise<WorkThreadRecord | null> {\r\n return this.store.get(threadId);\r\n }\r\n\r\n isTerminal(record: WorkThreadRecord | null | undefined): boolean {\r\n return Boolean(record && record.status === WORKTHREAD_TERMINAL_STATUS);\r\n }\r\n\r\n /**\r\n * 按会话查线程:sessionId 是某线程的当前承接会话(head)时返回该线程。\r\n * 返回完整线程记录(权威真相,含 pendingSuccession / commands / hold)。\r\n */\r\n async findThreadByHeadSession(agentId: string, sessionId: string): Promise<WorkThreadRecord | null> {\r\n const normalizedAgentId = cleanText(agentId);\r\n const normalizedSessionId = cleanText(sessionId);\r\n if (!normalizedAgentId || !normalizedSessionId) return null;\r\n const threads = await this.listThreads({ agentId: normalizedAgentId });\r\n const matched = threads.find(\r\n (t) => (t as { headSessionId?: string }).headSessionId === normalizedSessionId,\r\n ) as { threadId?: string } | undefined;\r\n if (!matched?.threadId) return null;\r\n return this.store.get(matched.threadId);\r\n }\r\n\r\n /**\r\n * 按成员查线程(T001):sessionId 是该线程任一成员(root / predecessor /\r\n * head)时返回线程完整记录。成员事实唯一来自 sessionChain 链记录,\r\n * 不用 UI 投影或运行时扫描推导;记录上的 identity 即为该成员统一的\r\n * 身份归属事实(root / head / 历史成员同属一条记录,取值一致)。\r\n */\r\n async findThreadBySession(agentId: string, sessionId: string): Promise<WorkThreadRecord | null> {\r\n const normalizedAgentId = cleanText(agentId);\r\n const normalizedSessionId = cleanText(sessionId);\r\n if (!normalizedAgentId || !normalizedSessionId) return null;\r\n const threads = await this.listThreads({ agentId: normalizedAgentId });\r\n for (const summary of threads as Array<{ threadId?: string }>) {\r\n if (!summary?.threadId) continue;\r\n const record = await this.store.get(summary.threadId);\r\n if (Array.isArray(record?.sessionChain)\r\n && record.sessionChain.some((entry) => entry?.sessionId === normalizedSessionId)) {\r\n return record;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n // ── 创建(显式 opt-in,Q5=B)────────────────────────────────────\r\n\r\n /** 解析线程身份归属(T001):显式参数优先,否则经 identitySource 从 root\r\n * Session 解析;解析不到归一为 null(身份未知,绝不默认成具体身份)。 */\r\n private async resolveIdentity(\r\n explicit: string | null | undefined,\r\n agentId: string,\r\n sessionId: string,\r\n ): Promise<string | null> {\r\n const normalizedExplicit = cleanText(explicit);\r\n if (explicit === null) return null;\r\n if (normalizedExplicit) return normalizedExplicit;\r\n if (!this._identitySource) return null;\r\n const resolved = await this._identitySource(agentId, sessionId);\r\n return cleanText(resolved) || null;\r\n }\r\n\r\n /**\r\n * 唯一创建入口:把一个既有会话认作 root 并成为初始 head。\r\n * 不提供「session 创建即自动建线程」的框架语义——那是宿主策略(integration 层)。\r\n *\r\n * T001:创建时从 root Session 确定线程身份归属(record.identity)。\r\n */\r\n async start({ sessionRef, title = '', workspaceId = '', identity }: WorkThreadStartOptions): Promise<WorkThreadRecord> {\r\n if (!sessionRef || typeof sessionRef !== 'object') {\r\n throw Object.assign(new Error('start requires sessionRef'), { code: 'invalid_request', status: 400 });\r\n }\r\n const agentId = validateId(sessionRef.agentId, 'agentId');\r\n const sessionId = validateId(sessionRef.sessionId, 'sessionId');\r\n const threadIdentity = await this.resolveIdentity(identity, agentId, sessionId);\r\n\r\n const now = Date.now();\r\n const record: WorkThreadRecord = {\r\n threadId: generateWorkThreadId(),\r\n agentId,\r\n workspaceId: cleanText(workspaceId) || agentId,\r\n title: cleanText(title),\r\n status: 'open',\r\n identity: threadIdentity,\r\n rootSessionId: sessionId,\r\n headSessionId: sessionId,\r\n sessionChain: [\r\n {\r\n sessionId,\r\n role: 'head',\r\n startedAt: now,\r\n endedAt: null,\r\n endKind: null,\r\n successorSessionId: null,\r\n },\r\n ],\r\n commands: [],\r\n pendingSuccession: null,\r\n hold: false,\r\n lifecycleEvents: [],\r\n lastLifecycleEvent: null,\r\n revision: 1,\r\n createdAt: now,\r\n updatedAt: now,\r\n };\r\n\r\n return this.store.create(record);\r\n }\r\n\r\n // ── 交接意图(pendingSuccession)────────────────────────────────\r\n\r\n /**\r\n * 派生:交接意图是否仍然有效(fresh)。stale 视为无交接。\r\n */\r\n isHandoffActive(record: WorkThreadRecord): boolean {\r\n const pending = record?.pendingSuccession;\r\n if (!pending?.startedAt) return false;\r\n return Date.now() - pending.startedAt < HANDOFF_STALE_MS;\r\n }\r\n\r\n /**\r\n * 标记线程进入交接:写入 pendingSuccession(幂等,重复调用刷新时间戳)。\r\n * 同步置 status=rotating(接续编排状态归锚点层)。\r\n */\r\n async beginSessionHandoff(opts: {\r\n threadId: string;\r\n fromSessionId: string;\r\n reason?: string;\r\n }): Promise<WorkThreadRecord> {\r\n const threadId = validateId(opts.threadId, 'threadId');\r\n const normalizedFrom = validateId(opts.fromSessionId, 'fromSessionId');\r\n const normalizedReason = cleanText(opts.reason) || 'manual';\r\n const { record } = await this.store.update(threadId, (draft) => {\r\n if (draft.status === WORKTHREAD_TERMINAL_STATUS) {\r\n throw Object.assign(new Error(`WorkThread \"${threadId}\" is closed`), {\r\n code: 'thread_closed',\r\n status: 409,\r\n });\r\n }\r\n if (draft.headSessionId !== normalizedFrom) {\r\n throw Object.assign(\r\n new Error(`Handoff source is not the current head of workthread \"${threadId}\"`),\r\n { code: 'head_mismatch', status: 409 },\r\n );\r\n }\r\n const now = Date.now();\r\n draft.status = 'rotating';\r\n draft.pendingSuccession = {\r\n fromSessionId: normalizedFrom,\r\n reason: normalizedReason,\r\n stage: 'started',\r\n startedAt: now,\r\n };\r\n pushLifecycleEvent(draft, {\r\n type: 'handoff_started',\r\n status: 'rotating',\r\n at: now,\r\n fromSessionId: normalizedFrom,\r\n reason: normalizedReason,\r\n });\r\n return draft;\r\n });\r\n return record;\r\n }\r\n\r\n /**\r\n * 惰性清除陈旧的交接意图(投递路径发现 stale 时恢复常态)。\r\n */\r\n private async clearStaleHandoff(threadId: string): Promise<void> {\r\n await this.store.update(threadId, (draft) => {\r\n if (!draft.pendingSuccession) return draft;\r\n draft.pendingSuccession = null;\r\n if (draft.status === 'rotating') draft.status = 'open';\r\n pushLifecycleEvent(draft, { type: 'handoff_stale', status: draft.status, at: Date.now() });\r\n return draft;\r\n });\r\n }\r\n\r\n /**\r\n * 标记交接失败为接续编排状态 rotation_failed,不折叠成通用执行失败。\r\n * pendingSuccession 保留在盘上,供后续 resume 检查被打断的确切 stage。\r\n */\r\n async failSessionHandoff(\r\n threadId: string,\r\n opts: { reason?: string; stage?: string; error?: unknown } = {},\r\n ): Promise<WorkThreadRecord> {\r\n const thread = await this.store.get(threadId);\r\n if (!thread) throw new WorkThreadNotFoundError(threadId);\r\n const { record } = await this.store.update(threadId, (draft) => {\r\n draft.status = 'rotation_failed';\r\n if (draft.pendingSuccession) {\r\n draft.pendingSuccession.stage = cleanText(opts.stage) || draft.pendingSuccession.stage || 'unknown';\r\n }\r\n pushLifecycleEvent(draft, {\r\n type: 'handoff_failed',\r\n status: 'rotation_failed',\r\n at: Date.now(),\r\n reason: cleanText(opts.reason) || 'handoff_failed',\r\n stage: cleanText(opts.stage) || 'unknown',\r\n error: opts.error != null ? String(opts.error) : null,\r\n });\r\n return draft;\r\n });\r\n return record;\r\n }\r\n\r\n // ── 指令(WorkThread Inbox)────────────────────────────────────\r\n\r\n /**\r\n * 幂等追加一条线程指令。\r\n * @returns {{command, duplicate, threadRevision}}\r\n */\r\n async appendCommand(opts: {\r\n threadId: string;\r\n kind?: string;\r\n text: string;\r\n source?: string;\r\n idempotencyKey?: string;\r\n capabilityActivations?: string[];\r\n }): Promise<{ command: WorkThreadCommand; duplicate: boolean; threadRevision: number }> {\r\n const threadId = validateId(opts.threadId, 'threadId');\r\n const normalizedKind =\r\n opts.kind && Object.values(WorkThreadCommandKind).includes(opts.kind as never)\r\n ? opts.kind\r\n : WorkThreadCommandKind.USER_MESSAGE;\r\n const normalizedText = String(opts.text || '');\r\n if (!normalizedText.trim()) {\r\n throw Object.assign(new Error('Command text must be non-empty'), {\r\n code: 'invalid_request',\r\n status: 400,\r\n });\r\n }\r\n if (normalizedText.length > 100_000) {\r\n throw Object.assign(new Error('Command text too large'), {\r\n code: 'invalid_request',\r\n status: 400,\r\n });\r\n }\r\n\r\n const command = createCommandRecord({\r\n threadId,\r\n kind: normalizedKind,\r\n text: normalizedText,\r\n source: cleanText(opts.source) || 'ui',\r\n idempotencyKey: cleanText(opts.idempotencyKey),\r\n ...(Array.isArray(opts.capabilityActivations) ? { capabilityActivations: opts.capabilityActivations } : {}),\r\n });\r\n\r\n let appendOutcome = { command, duplicate: false };\r\n const { record } = await this.store.update(threadId, (draft) => {\r\n appendOutcome = appendCommandToRecord(draft, command);\r\n pruneCommands(draft);\r\n return draft;\r\n });\r\n\r\n return {\r\n command: appendOutcome.command,\r\n duplicate: appendOutcome.duplicate,\r\n threadRevision: record.revision,\r\n };\r\n }\r\n\r\n /** 取消一条尚未投递的指令(pending → cancelled)。 */\r\n async cancelCommand(threadId: string, commandId: string): Promise<WorkThreadCommand | null> {\r\n const tid = validateId(threadId, 'threadId');\r\n const cid = validateId(commandId, 'commandId');\r\n const { record } = await this.store.update(tid, (draft) => {\r\n const command = findCommand(draft, cid);\r\n if (command && command.status === WorkThreadCommandStatus.PENDING) {\r\n command.status = WorkThreadCommandStatus.CANCELLED;\r\n command.updatedAt = Date.now();\r\n }\r\n return draft;\r\n });\r\n return findCommand(record, cid);\r\n }\r\n\r\n /**\r\n * 尝试把 pending 指令下沉到当前 head runtime。\r\n *\r\n * 投递判定(锚点层只保留客观事实):\r\n * - terminal(closed)→ thread_closed\r\n * - 交接窗口 fresh(pendingSuccession 未 stale)→ handoff_in_progress\r\n * - hold 开关置位 → thread_held(宿主级暂停投递)\r\n * - bridge disabled → bridge_disabled\r\n * - head runtime 未就绪(注入 resolveRuntime 返回 null)→ runtime_not_accepting\r\n *\r\n * @returns {{attempted, delivered, reason?, results}}\r\n */\r\n async deliverPendingCommands(threadId: string): Promise<{\r\n attempted: number;\r\n delivered: number;\r\n reason?: string;\r\n results: Array<{ commandId?: string; accepted?: boolean; reason?: string; retryable?: boolean; deliveryRef?: string }>;\r\n }> {\r\n const tid = validateId(threadId, 'threadId');\r\n\r\n const thread = await this.store.get(tid);\r\n if (!thread) throw new WorkThreadNotFoundError(tid);\r\n if (this.isTerminal(thread)) {\r\n return { attempted: 0, delivered: 0, reason: 'thread_closed', results: [] };\r\n }\r\n if (thread.hold === true) {\r\n return { attempted: 0, delivered: 0, reason: 'thread_held', results: [] };\r\n }\r\n\r\n // 交接进行中:指令保持 pending,等 advanceHead 后由宿主导流到新 head。\r\n // stale 的交接意图(失败路径残留)惰性清除后照常投递。\r\n if (thread.pendingSuccession) {\r\n if (this.isHandoffActive(thread)) {\r\n return { attempted: 0, delivered: 0, reason: 'handoff_in_progress', results: [] };\r\n }\r\n await this.clearStaleHandoff(tid);\r\n }\r\n\r\n const pending = pendingCommands(thread);\r\n if (pending.length === 0) {\r\n return { attempted: 0, delivered: 0, results: [] };\r\n }\r\n\r\n if (!this._bridge.isEnabled()) {\r\n return { attempted: 0, delivered: 0, reason: WORKTHREAD_BRIDGE_DISABLED_REASON, results: [] };\r\n }\r\n\r\n const results: Array<{\r\n commandId?: string;\r\n accepted?: boolean;\r\n reason?: string;\r\n retryable?: boolean;\r\n deliveryRef?: string;\r\n }> = [];\r\n let deliveredCount = 0;\r\n let stopReason: string | null = null;\r\n\r\n for (const command of pending) {\r\n const outcome = await this._bridge.deliver({ thread, command });\r\n results.push({ commandId: command.commandId, ...outcome });\r\n\r\n if (outcome.accepted) {\r\n deliveredCount += 1;\r\n } else if (outcome.retryable) {\r\n stopReason = outcome.reason || stopReason;\r\n break;\r\n }\r\n }\r\n\r\n const deliveredIds = new Set(\r\n results.filter((r) => r.accepted).map((r) => r.commandId as string),\r\n );\r\n const failedResults = new Map<string, string | undefined>(\r\n results\r\n .filter((r) => !r.accepted && r.retryable === false)\r\n .map((r) => [r.commandId as string, r.reason]),\r\n );\r\n\r\n if (deliveredIds.size > 0 || failedResults.size > 0) {\r\n const { record } = await this.store.update(tid, (draft) => {\r\n for (const c of draft.commands || []) {\r\n if (deliveredIds.has(c.commandId)) {\r\n c.status = WorkThreadCommandStatus.DELIVERED;\r\n c.deliveryRef = results.find((r) => r.commandId === c.commandId)?.deliveryRef || null;\r\n c.attempts = (Number(c.attempts) || 0) + 1;\r\n c.updatedAt = Date.now();\r\n c.deliveredAt = Date.now();\r\n c.lastReason = null;\r\n } else if (failedResults.has(c.commandId)) {\r\n c.status = WorkThreadCommandStatus.FAILED;\r\n c.lastReason = failedResults.get(c.commandId) || null;\r\n c.attempts = (Number(c.attempts) || 0) + 1;\r\n c.updatedAt = Date.now();\r\n }\r\n }\r\n return draft;\r\n });\r\n thread.revision = record.revision;\r\n }\r\n\r\n return {\r\n attempted: results.length,\r\n delivered: deliveredCount,\r\n reason: stopReason ?? undefined,\r\n results,\r\n };\r\n }\r\n\r\n /**\r\n * 宿主级「暂停投递」布尔开关(落盘第一等,重启不丢)。\r\n * @param held true 暂停投递(deliverPendingCommands 返回 thread_held)\r\n */\r\n async setHold(threadId: string, held: boolean): Promise<WorkThreadRecord> {\r\n const tid = validateId(threadId, 'threadId');\r\n const wantHold = held === true;\r\n const { record } = await this.store.update(tid, (draft) => {\r\n if (draft.hold === wantHold) return draft;\r\n draft.hold = wantHold;\r\n return draft;\r\n });\r\n return record;\r\n }\r\n\r\n // ── 会话接力(head 推进)────────────────────────────────────────\r\n\r\n /**\r\n * 推进线程 head:headSessionId: fromSessionId → toSessionId。\r\n *\r\n * 关键不变量(与 store 原子写共同保证):任一时刻线程要么明确指向旧 head,\r\n * 要么明确指向新 head;推进与指令状态 / 清挡板在同一次落盘中变更。\r\n *\r\n * 交接挡板(pendingSuccession)与 head 推进原子成对清除(换代 + 清挡板)。\r\n *\r\n * T001 身份连续性不变量:successor 加入前必须通过三道校验,任何一道失败\r\n * 都抛稳定错误且线程记录零变更(旧 head 保持有效):\r\n * - thread_identity_missing:线程身份归属未知(旧数据缺字段),拒绝静默\r\n * 放行;须宿主显式补全后重试;\r\n * - session_workspace_mismatch:successor 不属于线程同一工作空间宿主;\r\n * - thread_identity_mismatch:successor 身份与线程身份不一致;\r\n * - session_already_in_thread:successor 已是某条线程成员(本线程的重复\r\n * 成员由既有 duplicate_session 覆盖)。\r\n */\r\n async advanceHead(opts: {\r\n threadId: string;\r\n toSessionId: string;\r\n fromSessionId?: string;\r\n expectedRevision?: number;\r\n endKind?: string;\r\n }): Promise<WorkThreadRecord> {\r\n const threadId = validateId(opts.threadId, 'threadId');\r\n const normalizedTo = validateId(opts.toSessionId, 'toSessionId');\r\n const normalizedFrom = opts.fromSessionId ? validateId(opts.fromSessionId, 'fromSessionId') : null;\r\n\r\n // T001 身份连续性不变量:successor 加入前的三道校验在下方 store 事务内\r\n // 执行(per-thread 串行锁保护,结构守卫在前);任一失败抛稳定错误且\r\n // 线程记录零变更(旧 head 保持有效):\r\n // - session_workspace_mismatch:successor 不属于线程的工作空间宿主;\r\n // - thread_identity_mismatch:successor 身份与线程身份不一致;\r\n // - thread_identity_missing:线程身份未知且无法从 root Session 再推导\r\n // (旧数据缺字段的明确失败,绝不静默放行或默认成具体身份);\r\n // - session_already_in_thread:successor 已是其它线程的成员。\r\n // 未注入 identitySource 时(框架独立使用)保持既有行为:不校验身份。\r\n const { record } = await this.store.update(\r\n threadId,\r\n async (draft) => {\r\n if (draft.status === WORKTHREAD_TERMINAL_STATUS) {\r\n throw Object.assign(new Error(`WorkThread \"${threadId}\" is closed`), {\r\n code: 'thread_closed',\r\n status: 409,\r\n });\r\n }\r\n if (normalizedFrom && draft.headSessionId !== normalizedFrom) {\r\n throw Object.assign(\r\n new Error(\r\n `Head mismatch on workthread \"${threadId}\": expected ${normalizedFrom}, current ${draft.headSessionId}`,\r\n ),\r\n { code: 'head_mismatch', status: 409 },\r\n );\r\n }\r\n if (draft.headSessionId === normalizedTo) {\r\n throw Object.assign(\r\n new Error(`Session \"${normalizedTo}\" is already the head of workthread \"${threadId}\"`),\r\n { code: 'already_head', status: 409 },\r\n );\r\n }\r\n if ((draft.sessionChain || []).some((entry) => entry.sessionId === normalizedTo)) {\r\n throw Object.assign(\r\n new Error(`Session \"${normalizedTo}\" already appears in the chain of workthread \"${threadId}\"`),\r\n { code: 'duplicate_session', status: 409 },\r\n );\r\n }\r\n\r\n // T001 身份连续性不变量(事务内校验,结构守卫在前):\r\n // - session_workspace_mismatch:successor 不属于线程的工作空间宿主\r\n // (identitySource 以线程自身 agentId 定位不到该会话 = 非本宿主);\r\n // - thread_identity_missing:线程身份未知且无法从 root Session 再推导\r\n // (旧数据缺字段的明确失败,绝不静默放行或默认成具体身份);\r\n // - thread_identity_mismatch:successor 身份与线程身份不一致;\r\n // - session_already_in_thread:successor 已是其它线程的成员。\r\n if (this._identitySource) {\r\n const threadAgentId = cleanText(draft.agentId);\r\n const toIdentity = cleanText(await this._identitySource(threadAgentId, normalizedTo));\r\n if (!toIdentity) {\r\n throw threadIdentityError(\r\n `Session \"${normalizedTo}\" does not belong to workspace host \"${threadAgentId}\" of thread \"${threadId}\"`,\r\n 'session_workspace_mismatch',\r\n 409,\r\n );\r\n }\r\n // 线程身份归属:优先盘上事实;旧记录缺字段(null)时从 root Session\r\n // 的真实身份再推导并回填(事实推导,非默认值);仍不可得则明确失败。\r\n let effectiveThreadIdentity = draft.identity;\r\n if (!effectiveThreadIdentity) {\r\n effectiveThreadIdentity =\r\n cleanText(await this._identitySource(threadAgentId, draft.rootSessionId)) || null;\r\n if (!effectiveThreadIdentity) {\r\n throw threadIdentityError(\r\n `Thread \"${threadId}\" has no identity attribution and its root session identity is unknown; backfill the root identity before advancing the head`,\r\n 'thread_identity_missing',\r\n 409,\r\n );\r\n }\r\n // 回填与 head 推进同盘原子落盘(下方 draft.identity 赋值)。\r\n draft.identity = effectiveThreadIdentity;\r\n }\r\n if (toIdentity !== effectiveThreadIdentity) {\r\n throw threadIdentityError(\r\n `Session \"${normalizedTo}\" has identity \"${toIdentity}\" but thread \"${threadId}\" is bound to identity \"${effectiveThreadIdentity}\"`,\r\n 'thread_identity_mismatch',\r\n 409,\r\n );\r\n }\r\n // 成员独占:successor 不得已是其它线程的成员(本线程内的重复由\r\n // 上方 duplicate_session 覆盖)。\r\n const summaries = await this.store.list();\r\n for (const summary of summaries as Array<{ threadId?: string }>) {\r\n if (!summary?.threadId || summary.threadId === threadId) continue;\r\n const other = await this.store.get(summary.threadId);\r\n if (Array.isArray(other?.sessionChain)\r\n && other.sessionChain.some((entry) => entry?.sessionId === normalizedTo)) {\r\n throw threadIdentityError(\r\n `Session \"${normalizedTo}\" is already a member of thread \"${summary.threadId}\"`,\r\n 'session_already_in_thread',\r\n 409,\r\n );\r\n }\r\n }\r\n }\r\n\r\n const now = Date.now();\r\n const currentHead = (draft.sessionChain || []).find(\r\n (entry) => entry.sessionId === draft.headSessionId,\r\n );\r\n if (currentHead) {\r\n currentHead.role = 'predecessor';\r\n currentHead.endedAt = now;\r\n currentHead.endKind = cleanText(opts.endKind) || 'manual';\r\n currentHead.successorSessionId = normalizedTo;\r\n }\r\n draft.sessionChain = draft.sessionChain || [];\r\n draft.sessionChain.push({\r\n sessionId: normalizedTo,\r\n role: 'head',\r\n startedAt: now,\r\n endedAt: null,\r\n endKind: null,\r\n successorSessionId: null,\r\n });\r\n draft.headSessionId = normalizedTo;\r\n // 交接完成:同一次落盘内清除交接意图(与 head 推进原子成对)。\r\n draft.pendingSuccession = null;\r\n // 接续编排状态复位为 open(执行调度运行时状态归看板,不在此层驱动)。\r\n draft.status = 'open';\r\n pushLifecycleEvent(draft, {\r\n type: 'handoff_completed',\r\n status: 'open',\r\n at: now,\r\n fromSessionId: normalizedFrom || currentHead?.sessionId || null,\r\n toSessionId: normalizedTo,\r\n reason: cleanText(opts.endKind) || 'manual',\r\n });\r\n return draft;\r\n },\r\n { expectedRevision: Number.isInteger(opts.expectedRevision) ? opts.expectedRevision : undefined },\r\n );\r\n\r\n return record;\r\n }\r\n\r\n // ── 状态迁移(锚点收口)────────────────────────────────────────\r\n\r\n /**\r\n * 关闭只表示锚点收口 + 执行载体终态(terminal 判定),不表示编排层任务完成。\r\n * pending 指令随关闭一并取消。\r\n */\r\n async closeThread(threadId: string, opts: { reason?: string } = {}): Promise<WorkThreadRecord> {\r\n const tid = validateId(threadId, 'threadId');\r\n const { record } = await this.store.update(tid, (draft) => {\r\n if (this.isTerminal(draft)) return draft;\r\n draft.status = WORKTHREAD_TERMINAL_STATUS;\r\n draft.closedAt = Date.now();\r\n draft.closeReason = cleanText(opts.reason) || 'closed';\r\n pushLifecycleEvent(draft, {\r\n type: 'closed',\r\n status: WORKTHREAD_TERMINAL_STATUS,\r\n at: draft.closedAt,\r\n reason: draft.closeReason,\r\n });\r\n const now = Date.now();\r\n for (const c of draft.commands || []) {\r\n if (c.status === WorkThreadCommandStatus.PENDING) {\r\n c.status = WorkThreadCommandStatus.CANCELLED;\r\n c.lastReason = 'thread_closed';\r\n c.updatedAt = now;\r\n }\r\n }\r\n return draft;\r\n });\r\n return record;\r\n }\r\n\r\n /** 桥注入面(供测试 stub 与宿主替换)。 */\r\n getBridge(): WorkThreadBridge {\r\n return this._bridge;\r\n }\r\n}\r\n","/**\r\n * WorkThreadBoard — WorkThread 的可选平行执行看板(看板层)\r\n *\r\n * 移植自 Claw `server/thread-control/thread-controller.js` 的执行调度部分,按\r\n * ADR-0002/Q4=C 拆分为独立平行模块,经 workThreadId 与锚点层关联,宿主选用。\r\n *\r\n * 承载:\r\n * - executionEvents 持久化(codex `turn.*` / `item.*` 事件审计)\r\n * - `recordRuntimeEvent`(codex turn 事件流 → 看板状态翻译)\r\n * - resume、mode\r\n * - idle / running / waiting_input / failed 执行状态机\r\n *\r\n * 纪律(写死在本模块头注释):**看板永不反写锚点状态。** 本模块只读锚点记录的\r\n * 定位信息(经 core.findThreadByHeadSession 取 workThreadId 与 closed 判定),\r\n * 只写自己独立的看板持久化域,绝不调用 core 的 advanceHead / beginSessionHandoff /\r\n * setHold / closeThread 等锚点写路径。\r\n *\r\n * closed 两处语义(核心 terminal 判定 + 看板终态):看板对 closed 线程拒绝\r\n * runtime 事件(thread_closed);宿主在锚点关闭时经 closeBoard 将看板置为终态。\r\n */\r\n\r\nimport { copyFile, mkdir, readFile, rename, unlink, writeFile } from 'fs/promises';\r\nimport { join } from 'path';\r\nimport type { WorkThread } from './core.js';\r\nimport { sanitizeWorkThreadFragment } from './store.js';\r\n\r\nexport type WorkThreadBoardStatus =\r\n | 'idle'\r\n | 'running'\r\n | 'waiting_input'\r\n | 'failed'\r\n | 'closed';\r\n\r\nexport type WorkThreadBoardMode = 'interactive' | 'autonomous';\r\n\r\nexport interface WorkThreadBoardExecutionEvent {\r\n eventId: string;\r\n receivedAt: number;\r\n sessionId: string;\r\n runtimeInstanceId: string | null;\r\n event: Record<string, unknown>;\r\n}\r\n\r\nexport interface WorkThreadBoardLifecycleEvent {\r\n type: string;\r\n status: string;\r\n at: number;\r\n [key: string]: unknown;\r\n}\r\n\r\nexport interface WorkThreadBoardState {\r\n workThreadId: string;\r\n mode: WorkThreadBoardMode;\r\n status: WorkThreadBoardStatus;\r\n executionEvents: WorkThreadBoardExecutionEvent[];\r\n /**\r\n * 已从 executionEvents 窗口裁掉的事件总数(ticket 017)。\r\n * 绝对游标 = executionEventBaseOffset + executionEvents.length,随状态落盘,\r\n * 保证进程重启后 cursor 不回退。旧状态文件缺省时按 0 读取。\r\n */\r\n executionEventBaseOffset: number;\r\n lifecycleEvents: WorkThreadBoardLifecycleEvent[];\r\n lastLifecycleEvent: WorkThreadBoardLifecycleEvent | null;\r\n revision: number;\r\n createdAt: number;\r\n updatedAt: number;\r\n}\r\n\r\nexport const WORKTHREAD_BOARD_STATUSES: ReadonlySet<WorkThreadBoardStatus> = new Set([\r\n 'idle',\r\n 'running',\r\n 'waiting_input',\r\n 'failed',\r\n 'closed',\r\n]);\r\n\r\nexport const WORKTHREAD_BOARD_OPEN_STATUSES: ReadonlySet<WorkThreadBoardStatus> = new Set([\r\n 'idle',\r\n 'running',\r\n 'waiting_input',\r\n 'failed',\r\n]);\r\n\r\n// 执行状态机转换矩阵(看板层契约)。closed 为终态。\r\n//\r\n// `waiting_input` 是宿主播种的预留状态,事件翻译(recordRuntimeEvent)永不产生它:\r\n// turn.started → running、turn.completed → idle、turn.failed → failed,\r\n// item.* / turn.cancelled 不做状态转换。宿主经 setStatus 显式置位(如前端等待\r\n// 人工输入);其出边(→ running / idle / failed / closed)保证播种后后续 runtime\r\n// 事件(含终态失败)仍能自洽收敛,不会卡死在预留态或丢失终态事件。\r\nconst BOARD_TRANSITIONS: Record<WorkThreadBoardStatus, ReadonlySet<WorkThreadBoardStatus>> = {\r\n idle: new Set(['running', 'waiting_input', 'failed', 'closed']),\r\n running: new Set(['idle', 'waiting_input', 'failed', 'closed']),\r\n waiting_input: new Set(['running', 'idle', 'failed', 'closed']),\r\n failed: new Set(['running', 'idle', 'closed']),\r\n closed: new Set(),\r\n};\r\n\r\nconst BOARD_STATUSES = new Set<string>([\r\n 'idle',\r\n 'running',\r\n 'waiting_input',\r\n 'failed',\r\n 'closed',\r\n]);\r\nconst BOARD_MODES = new Set<string>(['interactive', 'autonomous']);\r\n\r\nconst MAX_EXECUTION_EVENTS = 500;\r\nconst MAX_LIFECYCLE_EVENTS = 200;\r\n\r\nexport interface WorkThreadBoardOptions {\r\n core: WorkThread;\r\n rootDir: string;\r\n}\r\n\r\nexport class WorkThreadBoard {\r\n readonly core: WorkThread;\r\n readonly boardsDir: string;\r\n private _locks = new Map<string, Promise<void>>();\r\n\r\n constructor({ core, rootDir }: WorkThreadBoardOptions) {\r\n if (!rootDir || typeof rootDir !== 'string') {\r\n throw new Error('WorkThreadBoard requires a rootDir');\r\n }\r\n this.core = core;\r\n this.boardsDir = join(rootDir, 'boards');\r\n }\r\n\r\n // ── 内部持久化(独立看板域,与锚点 store 分离)──────────────\r\n\r\n private boardFilePath(workThreadId: string): string {\r\n return join(this.boardsDir, `${sanitizeWorkThreadFragment(workThreadId)}.board.json`);\r\n }\r\n\r\n async getBoardId(workThreadId: string): Promise<string> {\r\n return workThreadId;\r\n }\r\n\r\n async getState(workThreadId: string): Promise<WorkThreadBoardState | null> {\r\n try {\r\n return JSON.parse(\r\n await readFile(this.boardFilePath(workThreadId), 'utf8'),\r\n ) as WorkThreadBoardState;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n private async atomicWriteJson(filePath: string, data: unknown): Promise<void> {\r\n const tmpPath = `${filePath}.tmp`;\r\n await writeFile(tmpPath, JSON.stringify(data, null, 2), 'utf8');\r\n try {\r\n await rename(tmpPath, filePath);\r\n } catch (err) {\r\n const code = (err as NodeJS.ErrnoException).code;\r\n if (code === 'EPERM' || code === 'EACCES') {\r\n await unlink(filePath).catch(() => {});\r\n await rename(tmpPath, filePath);\r\n } else if (code === 'EXDEV') {\r\n await copyFile(tmpPath, filePath);\r\n await unlink(tmpPath).catch(() => {});\r\n } else {\r\n throw err;\r\n }\r\n }\r\n }\r\n\r\n private async ensureInit(workThreadId: string, mode: WorkThreadBoardMode): Promise<WorkThreadBoardState> {\r\n const existing = await this.getState(workThreadId);\r\n if (existing) return existing;\r\n await mkdir(this.boardsDir, { recursive: true });\r\n const now = Date.now();\r\n const initial: WorkThreadBoardState = {\r\n workThreadId,\r\n mode,\r\n status: 'idle',\r\n executionEvents: [],\r\n executionEventBaseOffset: 0,\r\n lifecycleEvents: [],\r\n lastLifecycleEvent: null,\r\n revision: 1,\r\n createdAt: now,\r\n updatedAt: now,\r\n };\r\n await this.atomicWriteJson(this.boardFilePath(workThreadId), initial);\r\n return initial;\r\n }\r\n\r\n private async mutate(\r\n workThreadId: string,\r\n mutFn: (state: WorkThreadBoardState) => WorkThreadBoardState,\r\n mode: WorkThreadBoardMode = 'interactive',\r\n ): Promise<{ state: WorkThreadBoardState; changed: boolean }> {\r\n const prev = this._locks.get(workThreadId) || Promise.resolve();\r\n let release!: () => void;\r\n const next = new Promise<void>((r) => (release = r));\r\n this._locks.set(workThreadId, next);\r\n await prev.catch(() => {});\r\n try {\r\n const state = (await this.getState(workThreadId)) || (await this.ensureInit(workThreadId, mode));\r\n const before = JSON.stringify(state);\r\n const proposed = mutFn(state);\r\n if (!proposed) return { state, changed: false };\r\n const after = JSON.stringify(proposed);\r\n if (after === before) {\r\n return { state, changed: false };\r\n }\r\n const nextState: WorkThreadBoardState = {\r\n ...proposed,\r\n revision: (Number(state.revision) || 0) + 1,\r\n updatedAt: Date.now(),\r\n };\r\n await this.atomicWriteJson(this.boardFilePath(workThreadId), nextState);\r\n return { state: nextState, changed: true };\r\n } finally {\r\n release();\r\n if (this._locks.get(workThreadId) === next) this._locks.delete(workThreadId);\r\n }\r\n }\r\n\r\n private pushLifecycle(state: WorkThreadBoardState, event: WorkThreadBoardLifecycleEvent): void {\r\n state.lifecycleEvents = Array.isArray(state.lifecycleEvents) ? state.lifecycleEvents : [];\r\n state.lifecycleEvents.push(event);\r\n if (state.lifecycleEvents.length > MAX_LIFECYCLE_EVENTS) {\r\n state.lifecycleEvents.splice(0, state.lifecycleEvents.length - MAX_LIFECYCLE_EVENTS);\r\n }\r\n state.lastLifecycleEvent = event;\r\n }\r\n\r\n private canTransition(from: WorkThreadBoardStatus, to: WorkThreadBoardStatus): boolean {\r\n return from === to || BOARD_TRANSITIONS[from]?.has(to) === true;\r\n }\r\n\r\n // ── 查询 ─────────────────────────────────────────────────────────\r\n\r\n /**\r\n * 读取看板 executionEvents,支持 cursor 切片。\r\n *\r\n * cursor 是绝对游标(baseOffset + 窗口长度,ticket 017):跨裁剪点单调递增,\r\n * 长期增量消费者(轮询 after=cursor)不丢事件。`after` 落后于窗口起点时\r\n * clamp 到窗口起点从头返回当前可用窗口——旧数据已裁掉不可恢复,但绝不以\r\n * 空数组静默丢读;消费者可用 eventId 去重。\r\n * @returns {{events, cursor}}\r\n */\r\n async getExecutionEvents(\r\n workThreadId: string,\r\n opts: { after?: number } = {},\r\n ): Promise<{ events: Record<string, unknown>[]; cursor: number }> {\r\n const state = await this.getState(workThreadId);\r\n if (!state) return { events: [], cursor: 0 };\r\n const events = Array.isArray(state.executionEvents) ? state.executionEvents : [];\r\n const baseOffset = Math.max(0, Number(state.executionEventBaseOffset) || 0);\r\n const after = Math.max(0, Number(opts.after) || 0);\r\n const from = after < baseOffset ? 0 : after - baseOffset;\r\n return {\r\n events: events.slice(from).map((entry) => entry.event),\r\n cursor: baseOffset + events.length,\r\n };\r\n }\r\n\r\n // ── 事件翻译(执行调度状态机)─────────────────────────────────\r\n\r\n /**\r\n * 把一个 codex (`turn.*` / `item.*`) 运行时事件应用到看板层。\r\n *\r\n * 通过 core.findThreadByHeadSession 定位 workThreadId(只读锚点定位),\r\n * 只在看板域写状态与 executionEvents;closed 线程拒绝迟到观测事件。\r\n *\r\n * 事件翻译只产生 running / idle / failed 三个目标态,永不产生 waiting_input\r\n * (该状态由宿主经 setStatus 显式播种,见 BOARD_TRANSITIONS 注释)。\r\n *\r\n * @returns {{applied: boolean, reason?: string, thread?: WorkThreadBoardState}}\r\n */\r\n async recordRuntimeEvent(opts: {\r\n agentId: string;\r\n sessionId: string;\r\n runtimeInstanceId?: string | null;\r\n event: Record<string, unknown>;\r\n }): Promise<{ applied: boolean; reason?: string; state?: WorkThreadBoardState }> {\r\n const { agentId, sessionId, runtimeInstanceId = null, event } = opts;\r\n\r\n const anchor = await this.core.findThreadByHeadSession(agentId, sessionId);\r\n if (!anchor) return { applied: false, reason: 'no_thread_for_session' };\r\n // closed 线程不再接受任何 runtime 事件(含 item.*),迟到的观测事件显式忽略。\r\n if (this.core.isTerminal(anchor)) return { applied: false, reason: 'thread_closed' };\r\n\r\n const type = typeof event?.type === 'string' ? event.type.trim() : '';\r\n if (!type) return { applied: false, reason: 'invalid_event' };\r\n\r\n const workThreadId = anchor.threadId;\r\n const details = {\r\n sessionId: typeof sessionId === 'string' ? sessionId.trim() : '',\r\n runtimeInstanceId:\r\n typeof runtimeInstanceId === 'string' && runtimeInstanceId.trim()\r\n ? runtimeInstanceId.trim()\r\n : null,\r\n turn: Number.isInteger(event?.turn) ? event.turn : null,\r\n };\r\n\r\n const eventId =\r\n (typeof event?.eventId === 'string' && event.eventId.trim()) ||\r\n `${details.runtimeInstanceId || 'runtime'}:${type}:${details.turn ?? 'none'}:${\r\n (event?.item as { id?: unknown })?.id || Date.now()\r\n }`;\r\n\r\n const appendExecutionEvent = async (threadId: string): Promise<WorkThreadBoardState> => {\r\n const { state } = await this.mutate(threadId, (draft) => {\r\n draft.executionEvents = Array.isArray(draft.executionEvents) ? draft.executionEvents : [];\r\n if (draft.executionEvents.some((entry) => entry.eventId === eventId)) return draft;\r\n draft.executionEvents.push({\r\n eventId,\r\n receivedAt: Date.now(),\r\n sessionId: details.sessionId,\r\n runtimeInstanceId: details.runtimeInstanceId,\r\n event: { ...event },\r\n });\r\n if (draft.executionEvents.length > MAX_EXECUTION_EVENTS) {\r\n const removed = draft.executionEvents.length - MAX_EXECUTION_EVENTS;\r\n draft.executionEvents.splice(0, removed);\r\n draft.executionEventBaseOffset = Math.max(0, Number(draft.executionEventBaseOffset) || 0) + removed;\r\n }\r\n return draft;\r\n });\r\n return state;\r\n };\r\n\r\n const transition = async (\r\n threadId: string,\r\n status: WorkThreadBoardStatus,\r\n eventType: string,\r\n extra: Record<string, unknown> = {},\r\n ): Promise<WorkThreadBoardState> => {\r\n const { state } = await this.mutate(threadId, (draft) => {\r\n if (draft.status === 'closed') return draft;\r\n if (!this.canTransition(draft.status, status)) {\r\n throw Object.assign(\r\n new Error(`Invalid board transition: ${draft.status} -> ${status}`),\r\n { code: 'invalid_board_transition', status: 409 },\r\n );\r\n }\r\n draft.status = status;\r\n this.pushLifecycle(draft, { type: eventType, status, at: Date.now(), ...details, ...extra });\r\n return draft;\r\n });\r\n return state;\r\n };\r\n\r\n if (type === 'item.started' || type === 'item.completed') {\r\n return { applied: true, state: await appendExecutionEvent(workThreadId) };\r\n }\r\n if (type === 'turn.started') {\r\n await transition(workThreadId, 'running', type);\r\n return { applied: true, state: await appendExecutionEvent(workThreadId) };\r\n }\r\n if (type === 'turn.completed') {\r\n await transition(workThreadId, 'idle', type, { usage: event.usage || null });\r\n return { applied: true, state: await appendExecutionEvent(workThreadId) };\r\n }\r\n if (type === 'turn.cancelled') {\r\n // 生命周期信号(guard 轮换 / 宿主中断):只记录,不做状态转换。\r\n return { applied: true, state: await appendExecutionEvent(workThreadId) };\r\n }\r\n if (type === 'turn.failed') {\r\n await transition(workThreadId, 'failed', type, { error: event.error || null });\r\n return { applied: true, state: await appendExecutionEvent(workThreadId) };\r\n }\r\n return { applied: false, reason: 'unsupported_event' };\r\n }\r\n\r\n // ── resume / mode ──────────────────────────────────────────────\r\n\r\n /**\r\n * 从 failed / waiting_input 恢复执行(看板状态 running)。\r\n * 看板永不反写锚点状态——恢复只改看板状态,锚点交接意图由宿主另行收拾。\r\n */\r\n async resume(workThreadId: string, opts: { source?: string } = {}): Promise<WorkThreadBoardState> {\r\n const state = (await this.getState(workThreadId)) || (await this.ensureInit(workThreadId, 'interactive'));\r\n if (state.status === 'closed') {\r\n throw Object.assign(new Error(`WorkThreadBoard \"${workThreadId}\" is closed`), {\r\n code: 'thread_closed',\r\n status: 409,\r\n });\r\n }\r\n if (state.status !== 'failed' && state.status !== 'waiting_input') {\r\n throw Object.assign(new Error(`WorkThreadBoard \"${workThreadId}\" cannot be resumed from ${state.status}`), {\r\n code: 'board_not_resumable',\r\n status: 409,\r\n });\r\n }\r\n const { state: next } = await this.mutate(workThreadId, (draft) => {\r\n draft.status = 'running';\r\n this.pushLifecycle(draft, {\r\n type: 'resumed',\r\n status: 'running',\r\n at: Date.now(),\r\n source: typeof opts.source === 'string' ? opts.source.trim() : 'api',\r\n });\r\n return draft;\r\n });\r\n return next;\r\n }\r\n\r\n async setMode(workThreadId: string, mode: WorkThreadBoardMode): Promise<WorkThreadBoardState> {\r\n if (!BOARD_MODES.has(mode)) {\r\n throw Object.assign(new Error(`Invalid board mode: ${mode}`), {\r\n code: 'invalid_board_mode',\r\n status: 400,\r\n });\r\n }\r\n const { state } = await this.mutate(workThreadId, (draft) => {\r\n if (draft.mode === mode) return draft;\r\n draft.mode = mode;\r\n return draft;\r\n });\r\n return state;\r\n }\r\n\r\n /**\r\n * 手动播种看板状态(宿主用于 `waiting_input` 等无事件源的场景——例如前端在\r\n * 等待人工输入时显式置位)。仅改看板域,不反写锚点状态。\r\n */\r\n async setStatus(workThreadId: string, status: WorkThreadBoardStatus): Promise<WorkThreadBoardState> {\r\n if (!BOARD_STATUSES.has(status)) {\r\n throw Object.assign(new Error(`Invalid board status: ${status}`), {\r\n code: 'invalid_board_status',\r\n status: 400,\r\n });\r\n }\r\n const { state } = await this.mutate(workThreadId, (draft) => {\r\n if (draft.status === status) return draft;\r\n draft.status = status;\r\n this.pushLifecycle(draft, { type: 'status_seeded', status, at: Date.now() });\r\n return draft;\r\n });\r\n return state;\r\n }\r\n\r\n /**\r\n * 把看板置为终态(锚点已关闭)。与核心 terminal 判定对应的看板终态。\r\n */\r\n async closeBoard(workThreadId: string, opts: { reason?: string } = {}): Promise<WorkThreadBoardState> {\r\n const { state } = await this.mutate(workThreadId, (draft) => {\r\n if (draft.status === 'closed') return draft;\r\n draft.status = 'closed';\r\n this.pushLifecycle(draft, {\r\n type: 'board_closed',\r\n status: 'closed',\r\n at: Date.now(),\r\n reason: typeof opts.reason === 'string' ? opts.reason.trim() : 'closed',\r\n });\r\n return draft;\r\n });\r\n return state;\r\n }\r\n\r\n /**\r\n * Reopen a board after a host-level archive is cancelled.\r\n *\r\n * `closed` is terminal for runtime events, so reopening is intentionally\r\n * separate from `resume`: resume handles failed/waiting_input, while this\r\n * operation restores an archived board to an idle, not-running state.\r\n */\r\n async reopenBoard(workThreadId: string, opts: { source?: string } = {}): Promise<WorkThreadBoardState> {\r\n const state = await this.getState(workThreadId);\r\n if (!state) {\r\n return this.ensureInit(workThreadId, 'autonomous');\r\n }\r\n if (state.status !== 'closed') return state;\r\n const { state: next } = await this.mutate(workThreadId, (draft) => {\r\n draft.status = 'idle';\r\n this.pushLifecycle(draft, {\r\n type: 'board_reopened',\r\n status: 'idle',\r\n at: Date.now(),\r\n source: typeof opts.source === 'string' ? opts.source.trim() : 'api',\r\n });\r\n return draft;\r\n });\r\n return next;\r\n }\r\n\r\n /** 状态机转换矩阵(公开,供测试与宿主校验)。 */\r\n getTransitionMatrix(): Record<WorkThreadBoardStatus, WorkThreadBoardStatus[]> {\r\n const out = {} as Record<WorkThreadBoardStatus, WorkThreadBoardStatus[]>;\r\n for (const s of Object.keys(BOARD_STATUSES) as WorkThreadBoardStatus[]) {\r\n out[s] = [...BOARD_TRANSITIONS[s]];\r\n }\r\n return out;\r\n }\r\n}\r\n"],"mappings":"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","names":["fileURLToPath","readFile","normalize","dirname","dirname","dirname","fileURLToPath","readFile","normalize","dirname","fileURLToPath","dirname","resolver","resolve","__filename","fileURLToPath","dirname","fileURLToPath","dirname","readFile","__filename","fileURLToPath","__dirname","dirname","readFile","fileURLToPath","fileURLToPath","fileURLToPath","readFile","dirname","join","path","diffLines","fileURLToPath","fileURLToPath","existsSync","readFileSync","join","normalize","__filename","fileURLToPath","existsSync","join","normalize","readFileSync","fileURLToPath","readFile","stat","mkdir","homedir","readFile","stat","limit","offset","start","truncated","mkdir","_","dirPath","resolve","__filename","fileURLToPath","fileURLToPath","dirname","__filename","fileURLToPath","__dirname","dirname","fileURLToPath","path","path","readFile","fileURLToPath","spawn","path","path","proc","spawn","pkg","resolve","fileURLToPath","path","readFile","__filename","fileURLToPath","path","fs","fileURLToPath","dirname","join","mkdir","writeFile","__filename","fileURLToPath","__dirname","dirname","join","mkdir","writeFile","readFile","readdir","readFileSync","existsSync","resolve","join","path","path","cleanMultilineText","buildSummarySeedMessage","copyFile","mkdir","readFile","unlink","writeFile","join","randomUUID","entry","randomUUID","copyFile","mkdir","readFile","rename","unlink","writeFile","join","join","readFile","writeFile","rename","unlink","copyFile","mkdir"]}
|
|
1
|
+
{"version":3,"sources":["../src/features/skill/index.ts","../src/core/feature.ts","../src/features/skill/tools.ts","../src/features/subagent/index.ts","../src/features/subagent/pool.ts","../src/features/subagent/tools.ts","../src/features/todo/index.ts","../src/features/todo/tools.ts","../src/features/user-input/index.ts","../src/features/file-history/index.ts","../src/features/file-history/file-history.ts","../src/features/handoff-seed/index.ts","../src/features/opencode-basic/index.ts","../src/features/opencode-basic/tools.ts","../src/features/example-feature/index.ts","../src/features/example-feature/tools.ts","../src/features/lsp/index.ts","../src/features/lsp/client.ts","../src/features/lsp/servers.ts","../src/features/lsp/which.ts","../src/features/output-guard/index.ts","../src/features/output-guard/truncate.ts","../src/core/config.ts","../src/core/feature-config.ts","../src/core/render.ts","../src/template/types.ts","../src/core/continuity/transforms/trim-transcript.ts","../src/core/continuity/transforms/summary.ts","../src/core/continuity/participant.ts","../src/core/workthread/store.ts","../src/core/workthread/inbox.ts","../src/core/workthread/bridge.ts","../src/core/workthread/core.ts","../src/core/workthread/board.ts"],"sourcesContent":["/**\r\n * Skill Feature - Skills 发现和 invoke_skill 工具\r\n *\r\n * 将 Skills 集成从 Agent 核心中解耦,实现可外挂功能\r\n *\r\n * @example\r\n * ```typescript\r\n * // 使用默认路径 .agentdev/skills\r\n * agent.use(new SkillFeature());\r\n *\r\n * // 使用自定义路径\r\n * agent.use(new SkillFeature('./custom/skills'));\r\n * agent.use(new SkillFeature({ dir: './custom/skills' }));\r\n * ```\r\n */\r\n\r\nimport { fileURLToPath } from 'url';\r\nimport { readFile } from 'fs/promises';\r\nimport { normalize, dirname } from 'path';\r\nimport type { Context } from '../../core/context.js';\r\nimport type {\r\n AgentFeature,\r\n FeatureInitContext,\r\n FeatureManifestDefinition,\r\n ContextInjector,\r\n ToolContextValue,\r\n PackageInfo,\r\n} from '../../core/feature.js';\r\nimport { getPackageInfoFromSource } from '../../core/feature.js';\r\nimport type { Tool } from '../../core/types.js';\r\nimport type { CapabilityDefinition } from '../../core/capability.js';\r\nimport type { Logger } from '../../core/logging.js';\r\nimport { invokeSkillTool } from './tools.js';\r\nimport { discoverMulti, splitFrontmatter } from '../../skills/loader.js';\r\nimport type { SkillMetadata, SkillsOptions } from '../../skills/types.js';\r\nimport type { PlaceholderContext } from '../../template/types.js';\r\nimport { PlaceholderResolver } from '../../template/resolver.js';\r\n\r\n// ESM 中获取 __filename\r\nconst __filename = fileURLToPath(import.meta.url);\r\n\r\n/**\r\n * 技能文档注入时统一降级标题层级(+3,封顶 h6)。\r\n * SKILL.md 惯例以 `#` 开篇,聊天界面按 h1 渲染会撑爆消息块;\r\n * 注入场景只需要最小标题 + 正文的密度,保留相对层级即可。\r\n */\r\nfunction demoteHeadings(md: string): string {\r\n return md.replace(/^(#{1,6})(\\s)/gm, (_m, hashes: string, sep: string) => {\r\n return `${'#'.repeat(Math.min(hashes.length + 3, 6))}${sep}`;\r\n });\r\n}\r\n\r\n/**\r\n * Skill Feature 配置类型\r\n */\r\nexport interface SkillFeatureConfig extends SkillsOptions {\r\n /** Skills 目录路径 */\r\n dir?: string;\r\n /** 是否扫描 .agentdev/skills,默认 true */\r\n scanAgentdevDir?: boolean;\r\n /** 是否扫描 .claude/skills,默认 false */\r\n scanClaudeDir?: boolean;\r\n /** 额外 skills 目录列表 */\r\n extraDirs?: string[];\r\n /** 相对路径基准目录,默认 process.cwd() */\r\n baseDir?: string;\r\n}\r\n\r\n/**\r\n * Skill Feature 输入类型\r\n */\r\nexport type SkillFeatureInput = SkillFeatureConfig | string | undefined;\r\n\r\n/**\r\n * Skill Feature 实现\r\n */\r\nexport class SkillFeature implements AgentFeature {\r\n readonly name = 'skill';\r\n readonly source = __filename.replace(/\\\\/g, '/');\r\n readonly description = '发现本地 skills,并提供 invoke_skill 工具与技能数据源。';\r\n\r\n private skillsDir?: string;\r\n private skills: SkillMetadata[] = [];\r\n private featureSkills: SkillMetadata[] = [];\r\n private scanAgentdevDir: boolean = true;\r\n private scanClaudeDir: boolean = false;\r\n private extraDirs: string[] = [];\r\n\r\n private logger?: Logger;\r\n\r\n /**\r\n * 缓存包信息\r\n */\r\n private _packageInfo: PackageInfo | null = null;\r\n\r\n /**\r\n * 获取包信息(统一打包方案)\r\n */\r\n getPackageInfo(): PackageInfo | null {\r\n if (!this._packageInfo) {\r\n this._packageInfo = getPackageInfoFromSource(this.source);\r\n }\r\n return this._packageInfo;\r\n }\r\n\r\n /**\r\n * 获取模板名称列表(统一打包方案)\r\n */\r\n getTemplateNames(): string[] {\r\n return ['skill'];\r\n }\r\n\r\n constructor(input?: SkillFeatureInput) {\r\n if (typeof input === 'string') {\r\n // Relative paths must remain unresolved until onInitiate, when the\r\n // session-scoped workspaceDir is available. Resolving here would bind a\r\n // shared runtime to its host process cwd instead.\r\n this.skillsDir = input;\r\n } else if (input && typeof input === 'object') {\r\n this.skillsDir = input.dir;\r\n this.scanAgentdevDir = input.scanAgentdevDir ?? true;\r\n this.scanClaudeDir = input.scanClaudeDir ?? false;\r\n this.extraDirs = Array.isArray(input.extraDirs) ? input.extraDirs.filter(Boolean) : [];\r\n } else {\r\n this.skillsDir = undefined;\r\n }\r\n }\r\n\r\n /**\r\n * 获取同步工具(invoke_skill)\r\n */\r\n getTools(): Tool[] {\r\n return [invokeSkillTool];\r\n }\r\n\r\n /**\r\n * 将已发现的 skills 动态注册为 capability 命令。\r\n *\r\n * 每个 skill 一条 `skill.<name>` 命令,双入口:用户经 slash 菜单激活,\r\n * 或其他 feature / 编排经 registry invoke 激活。激活凭证是随消息流动\r\n * 的结构化通知(user-turn 的 capabilityActivations 元数据,见\r\n * onCapabilityActivations)——invoke 只做选中校验与审计,不承载激活态:\r\n * 排队投递、线程交接、后继会话等\"消息晚到 / 换进程\"场景下,激活通知\r\n * 始终作为消息本体的元数据到达,不依赖进程内暂存或输入文本解析。\r\n */\r\n getCapabilities(): CapabilityDefinition[] {\r\n return this.skills.map((skill) => ({\r\n name: skill.name,\r\n kind: 'prompt' as const,\r\n title: `技能:${skill.name}`,\r\n description: skill.description,\r\n entryPoints: ['slash', 'feature'],\r\n execute: () => {\r\n if (!this.skills.some((s) => s.name === skill.name)) {\r\n return Promise.reject(new Error(`skill \"${skill.name}\" no longer exists`));\r\n }\r\n return Promise.resolve({\r\n activated: skill.name,\r\n note: `技能「${skill.name}」已激活,随下一条消息自动加载`,\r\n });\r\n },\r\n }));\r\n }\r\n\r\n /**\r\n * 消费随消息到达的技能激活通知,注入对应技能文档。\r\n *\r\n * Agent 在两个消息落地点派发(新 call 的 onCall 第三参 / busy 排队\r\n * 消息的步边界注入),refs 只含本 feature 前缀的条目。文档以 system\r\n * 位置注入(与 flow 提示词 / force-continuation 的既有形态一致)。\r\n * 注入失败(文件缺失等)记日志,不阻断本轮 call。\r\n */\r\n async onCapabilityActivations(refs: string[], ctx: { context: Context }): Promise<void> {\r\n const names = new Set<string>();\r\n for (const ref of refs) {\r\n if (typeof ref !== 'string') continue;\r\n if (!ref.startsWith('skill.')) continue;\r\n names.add(ref.slice('skill.'.length));\r\n }\r\n if (names.size === 0) return;\r\n\r\n for (const skillName of names) {\r\n const skill = this.skills.find((s) => s.name === skillName);\r\n if (!skill) {\r\n this.logger?.warn(`Activated skill \"${skillName}\" no longer exists, skipped injection`);\r\n continue;\r\n }\r\n\r\n try {\r\n // frontmatter 原样保留但包进 yaml 围栏代码块:直接拼进 markdown 时\r\n // `---` 会渲染成水平线、YAML 文本被 setext 语法解析成大标题\r\n const { frontmatter, body } = splitFrontmatter(await readFile(skill.path, 'utf-8'));\r\n const content = [\r\n frontmatter ? ['```yaml', frontmatter, '```', ''].join('\\n') : '',\r\n body,\r\n ].filter(Boolean).join('\\n');\r\n const basePath = normalize(dirname(skill.path)).replace(/\\\\/g, '/');\r\n ctx.context.add({\r\n role: 'system',\r\n content: [\r\n `[技能激活:${skill.name}]`,\r\n `技能基础目录:\\`${basePath}\\``,\r\n '',\r\n '---',\r\n '',\r\n demoteHeadings(content),\r\n ].join('\\n'),\r\n });\r\n this.logger?.info(`Skill \"${skill.name}\" injected via turn activation notification`);\r\n } catch (error) {\r\n const msg = error instanceof Error ? error.message : String(error);\r\n this.logger?.warn(`Failed to inject activated skill \"${skillName}\": ${msg}`);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 向 Flow 暴露 Skills 相关变量\r\n */\r\n getFlowVariables() {\r\n return [\r\n {\r\n key: 'skillSummaryItems',\r\n type: 'string',\r\n title: '技能列表数组',\r\n description: '可用技能的“名称:介绍”数组,适合做变量遍历或直接插入。',\r\n resolver: () => this.skills.map(skill => `${skill.name}:${skill.description}`),\r\n },\r\n {\r\n key: 'skillSummaryText',\r\n type: 'string',\r\n title: '技能列表文本',\r\n description: '可用技能的多行文本版本,每行一条“- 名称:介绍”。',\r\n resolver: () => this.skills.map(skill => `- ${skill.name}:${skill.description}`).join('\\n'),\r\n },\r\n ];\r\n }\r\n\r\n /**\r\n * 向 Flow 暴露可直接复用的节点 Prompt 模板\r\n */\r\n getFlowNodeTemplates() {\r\n return [\r\n {\r\n id: 'skill-availability-prompt',\r\n name: '技能列表提示',\r\n description: '向 Agent 注入当前可用技能列表,并提示通过 invoke_skill 激活具体技能。',\r\n prompt: '你有以下技能可用,可使用invoke_skill工具激活:\\n{{skillSummaryText}}',\r\n tools: { enable: ['invoke_skill'] },\r\n },\r\n ];\r\n }\r\n\r\n getFeatureManifest(): FeatureManifestDefinition {\r\n return {\r\n schemaVersion: 1 as const,\r\n settings: {\r\n properties: {\r\n scanAgentdevDir: {\r\n type: 'boolean',\r\n title: '扫描 .agentdev/skills',\r\n description: '是否从工作目录的 .agentdev/skills/ 加载技能文件。',\r\n default: true,\r\n },\r\n scanClaudeDir: {\r\n type: 'boolean',\r\n title: '扫描 .claude/skills',\r\n description: '是否从工作目录的 .claude/skills/ 加载技能文件。',\r\n default: false,\r\n },\r\n extraDirs: {\r\n type: 'directory',\r\n title: '额外技能目录',\r\n description: '额外加载技能文件的目录列表(至多 5 个)。相对路径以工作目录为基准,绝对路径直接使用。同名技能会自动加后缀区分。',\r\n default: [],\r\n maxItems: 5,\r\n },\r\n },\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * 声明上下文注入器\r\n * 为 invoke_skill 工具注入 _context.skills\r\n */\r\n getContextInjectors(): Map<string | RegExp, ContextInjector> {\r\n return new Map<string | RegExp, ContextInjector>([\r\n ['invoke_skill', (): ToolContextValue => ({ _context: { skills: this.skills } })],\r\n ]);\r\n }\r\n\r\n /**\r\n * 初始化钩子\r\n * 执行 Skills 发现并注册数据源\r\n *\r\n * featureConfig(运行时配置)覆盖构造函数的默认值。\r\n * 路径解析以 agent 的 workspaceDir 为基准。\r\n */\r\n async onInitiate(ctx: FeatureInitContext): Promise<void> {\r\n this.logger = ctx.logger;\r\n // 从 featureConfig 读取运行时配置,覆盖构造函数默认值\r\n const fc = ctx.featureConfig;\r\n let scanAgentdevDir = this.scanAgentdevDir;\r\n let scanClaudeDir = this.scanClaudeDir;\r\n let extraDirs = this.extraDirs;\r\n\r\n if (fc && typeof fc === 'object') {\r\n const c = fc as Record<string, unknown>;\r\n if (typeof c.scanAgentdevDir === 'boolean') scanAgentdevDir = c.scanAgentdevDir;\r\n if (typeof c.scanClaudeDir === 'boolean') scanClaudeDir = c.scanClaudeDir;\r\n if (Array.isArray(c.extraDirs)) {\r\n extraDirs = c.extraDirs.filter((d): d is string => typeof d === 'string' && d.trim() !== '');\r\n }\r\n }\r\n\r\n // 使用 agent 的 workspaceDir 作为路径基准\r\n const baseDir = ctx.config?.workspaceDir;\r\n\r\n // 使用多目录发现:.agentdev/skills + .claude/skills + 额外目录\r\n this.skills = await discoverMulti({\r\n dir: this.skillsDir,\r\n scanAgentdevDir,\r\n scanClaudeDir,\r\n extraDirs,\r\n baseDir,\r\n });\r\n\r\n // 合并 Feature 自带 skills,用户 skills 优先(同名覆盖)\r\n if (this.featureSkills.length > 0) {\r\n const userSkillNames = new Set(this.skills.map(s => s.name));\r\n for (const s of this.featureSkills) {\r\n if (!userSkillNames.has(s.name)) {\r\n this.skills.push(s);\r\n }\r\n }\r\n }\r\n\r\n // 注册 skills 数据源到 Agent 级注册表(per-Agent 实例,非进程全局)\r\n ctx.dataSourceRegistry.register({\r\n name: 'skills',\r\n getData: () => this.skills,\r\n renderItem: (skill: SkillMetadata, template: string, context: PlaceholderContext) => {\r\n const skillContext: PlaceholderContext = {\r\n ...context,\r\n name: skill.name,\r\n description: skill.description,\r\n this: skill,\r\n };\r\n return PlaceholderResolver.resolve(template, skillContext);\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * 注入来自其他 Feature 的 skills\r\n * 由 Agent 在 onInitiate 之前调用\r\n */\r\n addFeatureSkills(skills: SkillMetadata[]): void {\r\n this.featureSkills = skills;\r\n }\r\n\r\n /**\r\n * 获取已加载的 Skills\r\n */\r\n getSkills(): SkillMetadata[] {\r\n return this.skills;\r\n }\r\n\r\n /**\r\n * 设置 Skills 目录\r\n */\r\n setSkillsDir(dir: string): void {\r\n this.skillsDir = dir;\r\n }\r\n}\r\n","/**\r\n * Feature System - 可外挂功能模块接口\r\n *\r\n * Feature 系统允许将功能(MCP、Skills、子代理等)从 Agent 核心中解耦,\r\n * 实现新功能的声明式注册和统一的生命周期管理。\r\n */\r\n\r\nimport type { Tool } from './types.js';\r\nimport type { ToolCall } from './types.js';\r\nimport type { InlineRenderTemplate } from './types.js';\r\nimport type { LLMClient } from './types.js';\r\nimport type { AgentConfig } from './types.js';\r\nimport type { Logger } from './logging.js';\r\nimport type { DataSourceRegistry } from '../template/data-source.js';\r\nimport type { CapabilityDefinition } from './capability.js';\r\nimport type { Context } from './context.js';\r\nimport { fileURLToPath } from 'url';\r\nimport { dirname, join } from 'path';\r\nimport { existsSync, readFileSync } from 'fs';\r\n\r\n/**\r\n * Feature 上下文值类型\r\n */\r\nexport type ToolContextValue = Record<string, unknown>;\r\n\r\n/**\r\n * Feature 上下文注入器\r\n * 返回要注入到 tool.execute() 的额外参数\r\n */\r\nexport type ContextInjector = (call: ToolCall) => ToolContextValue;\r\n\r\n/**\r\n * Feature 初始化上下文\r\n */\r\nexport interface FeatureInitContext {\r\n /** Agent ID */\r\n agentId: string;\r\n /** Agent 配置 */\r\n config: AgentConfig;\r\n /** Feature 级结构化日志 */\r\n logger: Logger;\r\n /** Feature 特定配置 */\r\n featureConfig?: unknown;\r\n /** 获取其他 Feature */\r\n getFeature<T extends AgentFeature>(name: string): T | undefined;\r\n /** 注册工具 */\r\n registerTool(tool: Tool): void;\r\n /** Agent 级数据源注册表(per-Agent 实例,非进程全局) */\r\n dataSourceRegistry: DataSourceRegistry;\r\n}\r\n\r\n/**\r\n * Feature 运行时上下文\r\n */\r\nexport interface FeatureContext {\r\n agentId: string;\r\n config: AgentConfig;\r\n getFeature<T extends AgentFeature>(name: string): T | undefined;\r\n}\r\n\r\n/**\r\n * Feature 快照状态\r\n *\r\n * 第一阶段只支持显式白名单状态:\r\n * - Feature 自己决定要保存什么\r\n * - 未声明的状态一律不保证恢复\r\n */\r\nexport type FeatureStateSnapshot = unknown;\r\n\r\n/**\r\n * 包信息\r\n */\r\nexport interface PackageInfo {\r\n /** 包名,如 '@agentdevjs/shell-feature' 或 'agentdev' */\r\n name: string;\r\n /** 版本号(可选) */\r\n version?: string;\r\n /** 包根目录绝对路径 */\r\n root: string;\r\n}\r\n\r\n/**\r\n * 模板信息\r\n */\r\nexport interface TemplateInfo {\r\n /** 包名 */\r\n packageName: string;\r\n /** 模板名(不含扩展名) */\r\n templateName: string;\r\n}\r\n\r\n/**\r\n * Feature Manifest 配置项\r\n *\r\n * 用于声明 Feature 在 Agent Project 级别可配置的静态参数。\r\n * Claw 等消费端可根据该契约自动渲染表单。\r\n */\r\nexport interface FeatureManifestSettingProperty {\r\n type: 'string' | 'number' | 'boolean' | 'select' | 'file' | 'directory' | 'group';\r\n title: string;\r\n description?: string;\r\n default?: unknown;\r\n options?: Array<{ label: string; value: string | number | boolean }>;\r\n placeholder?: string;\r\n /** number 类型下的最小值 */\r\n min?: number;\r\n /** number 类型下的最大值 */\r\n max?: number;\r\n /** number 类型下的步进值 */\r\n step?: number;\r\n /** file 类型下的可接受文件类型,如 '.mp3,.wav' 或 'audio/*' */\r\n accept?: string | string[];\r\n /** directory 类型下的最大条目数 */\r\n maxItems?: number;\r\n /** type: 'group' 时的嵌套子属性 */\r\n properties?: Record<string, FeatureManifestSettingProperty>;\r\n /** 条件可见性:仅当同级指定属性值在 values 中时渲染此字段 */\r\n showWhen?: { property: string; values: (string | number | boolean)[] };\r\n /**\r\n * select 类型下的动态选项来源:options 由宿主在渲染时提供(活数据,\r\n * 无法静态枚举),options 字段省略。当前定义 'model-presets' =\r\n * 宿主模型 preset 清单。静态 options 存在时本字段被忽略。\r\n */\r\n dynamicOptions?: 'model-presets';\r\n}\r\n\r\nexport interface FeatureManifestDefinition {\r\n schemaVersion: 1;\r\n settings?: {\r\n properties: Record<string, FeatureManifestSettingProperty>;\r\n /** 有序分区,用于 UI 分组渲染。省略则平铺全部属性 */\r\n sections?: Array<{\r\n id: string;\r\n title: string;\r\n description?: string;\r\n /** 分区内属性 key 的显示顺序 */\r\n properties: string[];\r\n }>;\r\n };\r\n}\r\n\r\n/**\r\n * Agent Feature 接口\r\n *\r\n * 可外挂的功能模块,提供工具和上下文注入\r\n */\r\nexport interface AgentFeature {\r\n /** Feature 名称 */\r\n readonly name: string;\r\n /**\r\n * 依赖的其他 Feature(装配时拓扑排序,工作项 A3)。\r\n *\r\n * 声明位置在类的静态属性上(实例字段无法装配时静态读取):\r\n * ```typescript\r\n * class MyFeature implements AgentFeature {\r\n * name = 'my-feature';\r\n * static inject = ['storage'];\r\n * }\r\n * ```\r\n * 读取与校验见 feature-graph.ts(readInjectDeclarations / resolveFeatureOrder)。\r\n */\r\n // (接口本身不声明静态成员;inject 约定见上方文档)\r\n /**\r\n * Feature 源文件路径(import.meta.url)。\r\n *\r\n * 既是调试器展示的源码位置,也是框架自动发现 Feature 自带资源的唯一锚点。\r\n *\r\n * 约定:Feature 的所有静态资源放在 source 文件的同级目录下。\r\n * 框架会自动扫描 `dirname(source)/skills/` 发现内置 skill 并注入系统提示词。\r\n * 其他资源(图片、模板等)由 Feature 代码通过 import.meta.url 自行解析。\r\n *\r\n * 标准写法(由 create-feature 脚手架自动生成):\r\n * ```typescript\r\n * readonly source = fileURLToPath(import.meta.url).replace(/\\\\/g, '/');\r\n * ```\r\n */\r\n readonly source?: string;\r\n /** 可选:用于调试器展示的 Feature 描述 */\r\n readonly description?: string;\r\n\r\n /**\r\n * 获取同步工具(已知工具列表)\r\n */\r\n getTools?(): Tool[];\r\n\r\n /**\r\n * 获取异步工具(需要连接、发现等)\r\n */\r\n getAsyncTools?(ctx: FeatureInitContext): Promise<Tool[]>;\r\n\r\n /**\r\n * 获取包信息\r\n * \r\n * 返回 Feature 所在的包信息(包名、版本、根目录)\r\n * 用于统一模板路径解析和包管理\r\n * \r\n * @returns 包信息,如果 Feature 不属于任何包则返回 null\r\n * \r\n * @example\r\n * ```typescript\r\n * getPackageInfo(): PackageInfo | null {\r\n * return {\r\n * name: '@agentdevjs/shell-feature',\r\n * version: '1.0.0',\r\n * root: '/path/to/package/root'\r\n * };\r\n * }\r\n * ```\r\n */\r\n getPackageInfo?(): PackageInfo | null;\r\n\r\n /**\r\n * 获取模板名称列表\r\n * \r\n * 返回 Feature 提供的模板名称列表(不含扩展名)\r\n * 模板文件必须位于 {packageRoot}/dist/templates/{templateName}.render.js\r\n * \r\n * @returns 模板名称数组\r\n * \r\n * @example\r\n * ```typescript\r\n * getTemplateNames(): string[] {\r\n * return ['bash', 'trash-delete', 'trash-list'];\r\n * }\r\n * ```\r\n */\r\n getTemplateNames?(): string[];\r\n\r\n /**\r\n * 声明渲染模板(推荐方式)\r\n * 直接返回模板对象,无需文件路径\r\n *\r\n * @example\r\n * ```typescript\r\n * getRenderTemplates(): Record<string, InlineRenderTemplate> {\r\n * return {\r\n * 'bash': {\r\n * call: (args) => `<div class=\"bash-command\">> ${escapeHtml(args.command)}</div>`,\r\n * result: (data, success) => success\r\n * ? `<pre class=\"bash-output\">${escapeHtml(data)}</pre>`\r\n * : `<div class=\"tool-error\">${escapeHtml(data)}</div>`\r\n * }\r\n * };\r\n * }\r\n * ```\r\n */\r\n getRenderTemplates?(): Record<string, InlineRenderTemplate>;\r\n\r\n /**\r\n * 声明 Feature 的项目级静态配置契约(Manifest)\r\n *\r\n * 该契约回答“这个 Feature 平时怎么工作”,\r\n * 与 Flow 节点中的 Mode(什么时候、以什么状态工作)是正交的。\r\n */\r\n getFeatureManifest?(): FeatureManifestDefinition | null;\r\n\r\n /**\r\n * 声明可调用命令(Capability)\r\n *\r\n * 命令以 `featureName.commandName` 在注册表内平面寻址,两类消费入口:\r\n * - 用户命令菜单:宿主下发清单时按 entryPoints 含 'slash' 过滤\r\n * - 其他 Feature:进程内 invokeCapability,entryPoint 为 'feature';\r\n * 宿主前端转发的用户触发同样经注册表,entryPoint 为 'slash'。\r\n * entryPoints 是契约约束(不匹配返回 entry_point_denied),不是安全边界。\r\n */\r\n getCapabilities?(): CapabilityDefinition[];\r\n\r\n /**\r\n * 消费\"随消息到达的能力激活通知\"(可选)。\r\n *\r\n * 激活通知(capability refs 数组)作为用户输入的结构化元数据随消息\r\n * 本体流动:新 call 开始时(onCall 第三参)与 busy 排队消息的步边界\r\n * 注入时(react-loop drain)两个消息落地点,Agent 会按 ref 归属分组\r\n * 调用对应 feature 的本方法。refs 是完整引用(`featureName.commandName`),\r\n * feature 只需处理自己前缀的条目。\r\n *\r\n * 这是 prompt 型命令(skill 等)的唯一消费口——不解析输入文本,\r\n * 不维护跨消息的 pending 状态。\r\n */\r\n onCapabilityActivations?(refs: string[], ctx: { context: Context }): Promise<void>;\r\n\r\n /**\r\n * 声明上下文注入器\r\n */\r\n getContextInjectors?(): Map<string | RegExp, ContextInjector>;\r\n\r\n /**\r\n * 初始化钩子\r\n */\r\n onInitiate?(ctx: FeatureInitContext): Promise<void>;\r\n\r\n /**\r\n * 清理钩子\r\n */\r\n onDestroy?(ctx: FeatureContext): Promise<void>;\r\n\r\n /**\r\n * LLM 变更时调用(可选)\r\n *\r\n * Feature 可在此重新绑定对 LLM 的引用、更新阈值等。\r\n * 该钩子在 Agent.setLLM() 中被同步调用,且仅在 onCall 间隙执行。\r\n */\r\n onLLMSwap?(newLLM: LLMClient, oldLLM: LLMClient): void;\r\n\r\n /**\r\n * 捕获可回滚的 Feature 状态\r\n *\r\n * 仅返回显式声明、可序列化的状态。\r\n * 未返回的字段不会参与 rollback。\r\n */\r\n captureState?(): FeatureStateSnapshot;\r\n\r\n /**\r\n * 从快照恢复 Feature 状态\r\n */\r\n restoreState?(snapshot: FeatureStateSnapshot): void | Promise<void>;\r\n\r\n /**\r\n * rollback 前钩子\r\n */\r\n beforeRollback?(snapshot: FeatureStateSnapshot): void | Promise<void>;\r\n\r\n /**\r\n * rollback 后钩子\r\n */\r\n afterRollback?(snapshot: FeatureStateSnapshot): void | Promise<void>;\r\n\r\n /**\r\n * 可选:为调试器提供 hook 的人类可读说明\r\n */\r\n getHookDescription?(lifecycle: string, methodName: string): string | undefined;\r\n\r\n // ========== 反向钩子通过 static hooks 静态声明注册,无需接口声明 ==========\r\n // 见 hook-declarations.ts:static hooks = { methodName: { lifecycle, kind, role? } }\r\n // 例如:ToolFinished, LLMFinish, StepFinish 等生命周期\r\n}\r\n\r\n// ========== 辅助函数 ==========\r\n\r\n/**\r\n * 从 Feature 的 source 属性获取包信息\r\n * \r\n * 通过向上查找 package.json 文件来确定包信息\r\n * 支持三种场景:\r\n * 1. 框架内置 Feature:找到 AgentDev 的 package.json\r\n * 2. 外部 npm 包:找到包的 package.json\r\n * 3. 用户本地 Feature:找到用户项目的 package.json\r\n * \r\n * @param source Feature 的源文件路径(import.meta.url)\r\n * @returns 包信息,如果找不到 package.json 则返回 null\r\n */\r\nexport function getPackageInfoFromSource(source: string | undefined): PackageInfo | null {\r\n if (!source) {\r\n return null;\r\n }\r\n\r\n try {\r\n // 将 file:// URL 转换为文件系统路径\r\n const filePath = source.startsWith('file://') ? fileURLToPath(source) : source;\r\n const featureDir = dirname(filePath);\r\n \r\n // 向上查找 package.json\r\n let currentDir = featureDir;\r\n const root = process.platform === 'win32' ? currentDir.split(/[/\\\\]/)[0] : '';\r\n \r\n while (currentDir && currentDir !== root) {\r\n try {\r\n const packageJsonPath = join(currentDir, 'package.json');\r\n \r\n // 检查文件是否存在\r\n if (!existsSync(packageJsonPath)) {\r\n throw new Error('Not found');\r\n }\r\n \r\n // 读取并解析 package.json\r\n const content = readFileSync(packageJsonPath, 'utf-8');\r\n const packageJson = JSON.parse(content);\r\n \r\n // 找到了 package.json\r\n return {\r\n name: packageJson.name || 'unknown',\r\n version: packageJson.version,\r\n root: currentDir,\r\n };\r\n } catch {\r\n // 没找到,继续向上查找\r\n const parentDir = dirname(currentDir);\r\n if (parentDir === currentDir) {\r\n // 已经到达根目录,停止查找\r\n break;\r\n }\r\n currentDir = parentDir;\r\n }\r\n }\r\n \r\n return null;\r\n } catch {\r\n // 任何错误都返回 null\r\n return null;\r\n }\r\n}\r\n","/**\r\n * Skill Feature 工具定义\r\n *\r\n * 提供 invoke_skill 工具,用于动态加载和展示技能的详细文档\r\n */\r\n\r\nimport { readFile } from 'fs/promises';\r\nimport { dirname, normalize } from 'path';\r\nimport type { Tool } from '../../core/types.js';\r\nimport type { SkillMetadata } from '../../skills/types.js';\r\nimport { splitFrontmatter } from '../../skills/loader.js';\r\nimport { createTool } from '../../core/tool.js';\r\n\r\n/**\r\n * invoke_skill 工具\r\n *\r\n * 调用并展开指定技能的详细文档\r\n */\r\nexport const invokeSkillTool: Tool = createTool({\r\n name: 'invoke_skill',\r\n description: '调用并展开指定技能的详细文档。技能提供专门的能力和领域知识。',\r\n parallelizable: true,\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n skill: {\r\n type: 'string',\r\n description: '技能名称(如 xlsx, pdf 等)'\r\n }\r\n },\r\n required: ['skill']\r\n },\r\n render: { call: 'skill', result: 'skill' },\r\n execute: async (args, context) => {\r\n const { skill } = args as { skill: string };\r\n console.log(`[invoke_skill] ${skill}`);\r\n\r\n // 从 context 中获取 skills 列表\r\n const ctx = context?._context as { skills?: SkillMetadata[] } | undefined;\r\n const skills = ctx?.skills || [];\r\n\r\n // 查找匹配的 skill\r\n const skillMetadata = skills.find(s => s.name === skill);\r\n\r\n if (!skillMetadata) {\r\n const availableSkills = skills.map(s => s.name).join(', ');\r\n return `错误:技能 \"${skill}\" 不存在。\r\n\r\n可用技能列表:${availableSkills || '(无可用技能)'}\r\n\r\n提示:请确保技能名称正确。`;\r\n }\r\n\r\n try {\r\n // frontmatter 原样保留但包进 yaml 围栏代码块,避免 markdown 渲染异常\r\n const raw = await readFile(skillMetadata.path, 'utf-8');\r\n const { frontmatter, body } = splitFrontmatter(raw);\r\n const content = [\r\n frontmatter ? ['```yaml', frontmatter, '```', ''].join('\\n') : '',\r\n body,\r\n ].filter(Boolean).join('\\n');\r\n\r\n // 获取技能目录路径,并规范化路径格式\r\n const basePath = normalize(dirname(skillMetadata.path));\r\n\r\n // 返回格式化的技能文档\r\n // 使用行内代码块包裹路径,避免 markdown 转义\r\n return `**技能名称**:${skillMetadata.name}\r\n\r\n**技能描述**:${skillMetadata.description}\r\n\r\n**技能的基础目录路径**:\\`${basePath}\\`\r\n\r\n---\r\n\r\n${content}`;\r\n } catch (error) {\r\n const errorMsg = error instanceof Error ? error.message : String(error);\r\n return `错误:无法读取技能文件 \"${skill}\"\r\n\r\n详细信息:${errorMsg}\r\n\r\n文件路径:${skillMetadata.path}`;\r\n }\r\n },\r\n});\r\n","/**\r\n * SubAgent Feature - 子代理功能模块\r\n *\r\n * 提供子代理创建、管理、消息回传等完整能力\r\n *\r\n * 重构说明:\r\n * - 使用 static hooks 静态声明实现反向钩子\r\n * - 移除旧的方法(handleNoToolCalls, handleWait, consumeMessages)\r\n * - 通过 ToolFinished 和 StepFinish 钩子(静态声明)实现子代理等待机制\r\n */\r\n\r\nimport { fileURLToPath } from 'url';\r\nimport { dirname } from 'path';\r\nimport type { HookDeclarations } from '../../core/hook-declarations.js';\r\nimport type { Agent } from '../../core/agent.js';\r\nimport type {\r\n AgentFeature,\r\n FeatureInitContext,\r\n ContextInjector,\r\n FeatureStateSnapshot,\r\n PackageInfo,\r\n} from '../../core/feature.js';\r\nimport { getPackageInfoFromSource } from '../../core/feature.js';\r\nimport type { Tool } from '../../core/types.js';\r\nimport type { ToolFinishedDecisionContext, StepFinishDecisionContext } from '../../core/lifecycle.js';\r\nimport { CoreLifecycle, Decision, type DecisionResult } from '../../core/lifecycle.js';\r\nimport { AgentPool } from './pool.js';\r\nimport { SubAgentToolFactory } from './tools.js';\r\n\r\n// ESM 中获取 __dirname\r\nconst __filename = fileURLToPath(import.meta.url);\r\nconst __dirname = dirname(__filename);\r\n\r\n// ========== SubAgent Feature ==========\r\n\r\n/**\r\n * 子代理 Feature\r\n *\r\n * 提供子代理创建、管理、消息回传等完整能力\r\n *\r\n * 重构说明:\r\n * - 使用 static hooks 静态声明实现反向钩子\r\n * - ToolFinished: 处理 wait 工具完成后的等待逻辑\r\n * - StepFinish: 处理无工具调用时的子代理等待逻辑\r\n */\r\nexport class SubAgentFeature implements AgentFeature {\r\n\r\n static hooks: HookDeclarations = {\r\n handleWaitTool: { lifecycle: CoreLifecycle.ToolFinished, kind: 'observe' as const },\r\n handleNoToolCalls: { lifecycle: CoreLifecycle.StepFinish, kind: 'guard' as const, role: 'advisor' as const },\r\n };\r\n readonly name = 'subagent';\r\n readonly source = __filename.replace(/\\\\/g, '/');\r\n readonly description = '提供子代理创建、等待与消息回传能力,让主循环可以协同多个代理工作。';\r\n\r\n private agentPool?: AgentPool;\r\n private parentAgent?: Agent;\r\n\r\n // 工具工厂实例\r\n private toolFactory?: SubAgentToolFactory;\r\n\r\n /**\r\n * 缓存包信息\r\n */\r\n private _packageInfo: PackageInfo | null = null;\r\n\r\n /**\r\n * 获取包信息(统一打包方案)\r\n */\r\n getPackageInfo(): PackageInfo | null {\r\n if (!this._packageInfo) {\r\n this._packageInfo = getPackageInfoFromSource(this.source);\r\n }\r\n return this._packageInfo;\r\n }\r\n\r\n /**\r\n * 获取模板名称列表(统一打包方案)\r\n */\r\n getTemplateNames(): string[] {\r\n return [\r\n 'agent-spawn',\r\n 'agent-list',\r\n 'agent-send',\r\n 'agent-close',\r\n 'wait',\r\n ];\r\n }\r\n\r\n constructor() {\r\n // 无参数配置(可扩展)\r\n }\r\n\r\n /**\r\n * 获取 AgentPool(供外部访问)\r\n */\r\n get pool(): AgentPool | undefined {\r\n return this.agentPool;\r\n }\r\n\r\n // ========== AgentFeature 接口实现 ==========\r\n\r\n /**\r\n * 初始化钩子\r\n */\r\n async onInitiate(_ctx: FeatureInitContext): Promise<void> {\r\n // 工具工厂在 _setParentAgent 中初始化\r\n }\r\n\r\n /**\r\n * 设置父代理引用(由 Agent 在 use() 时调用)\r\n */\r\n _setParentAgent(agent: Agent): void {\r\n this.parentAgent = agent;\r\n this.agentPool = new AgentPool(agent);\r\n\r\n // 初始化工具工厂\r\n this.toolFactory = new SubAgentToolFactory({\r\n getPool: () => {\r\n if (!this.agentPool) throw new Error('AgentPool not initialized');\r\n return this.agentPool;\r\n },\r\n getParentAgent: () => this.parentAgent,\r\n });\r\n }\r\n\r\n /**\r\n * 获取同步工具\r\n */\r\n getTools(): Tool[] {\r\n return this.toolFactory?.getAllTools() || [];\r\n }\r\n\r\n getContextInjectors(): Map<string | RegExp, ContextInjector> {\r\n return new Map([\r\n ['spawn_agent', () => ({ parentAgent: this.parentAgent })],\r\n ['list_agents', () => ({ parentAgent: this.parentAgent })],\r\n ['send_to_agent', () => ({ parentAgent: this.parentAgent })],\r\n ['close_agent', () => ({ parentAgent: this.parentAgent })],\r\n ['wait', () => ({ parentAgent: this.parentAgent })],\r\n ]);\r\n }\r\n\r\n getHookDescription(lifecycle: string, methodName: string): string | undefined {\r\n if (lifecycle === 'ToolFinished' && methodName === 'handleWaitTool') {\r\n return '在 wait 工具结束后阻塞等待子代理消息,并把结果回填到主代理上下文。';\r\n }\r\n if (lifecycle === 'StepFinish' && methodName === 'handleNoToolCalls') {\r\n return '当本轮没有工具调用但仍有活跃子代理时,等待回信并强制继续下一轮 ReAct。';\r\n }\r\n return undefined;\r\n }\r\n\r\n // ========== 反向钩子(static hooks 声明)==========\r\n\r\n /**\r\n * 处理 wait 工具\r\n *\r\n * 触发时机:wait 工具执行完成后\r\n * 处理逻辑:\r\n * 1. 检测刚才执行的工具是否是 wait\r\n * 2. 如果不是,直接返回(不处理)\r\n * 3. 如果是,检查是否有 busy 状态的子代理\r\n * 4. 如果有,调用 agentPool.waitForMessage() 阻塞等待(await 阻塞主循环)\r\n * 5. 消息插入到主代理 context\r\n *\r\n * 注意:这是纯通知钩子(void),流程控制通过 await 阻塞实现\r\n */\r\n async handleWaitTool(ctx: ToolFinishedDecisionContext): Promise<void> {\r\n // 1. 只处理 wait 工具\r\n if (ctx.toolName !== 'wait') {\r\n return;\r\n }\r\n\r\n // 2. 检查是否有 busy 子代理\r\n if (!this.agentPool?.hasActiveAgents()) {\r\n return;\r\n }\r\n\r\n // 3. 阻塞等待(await 本身就会让主循环等待)\r\n const result = await this.agentPool.waitForMessage();\r\n\r\n // 4. 消息插入到 context\r\n ctx.context.add({\r\n role: 'assistant',\r\n content: `[子代理 ${result.agentId} 执行完成]:\\n\\n${result.message}`,\r\n });\r\n }\r\n\r\n /**\r\n * 处理无工具调用时的子代理等待\r\n *\r\n * 触发时机:Step 结束时\r\n * 处理逻辑:\r\n * 1. 检查是否有 busy 状态的子代理\r\n * 2. 如果没有,返回 Continue(正常结束)\r\n * 3. 如果有,调用 agentPool.waitForMessage() 阻塞等待\r\n * 4. 消息插入到主代理 context\r\n * 5. 返回 Approve(重启 ReAct 循环)\r\n */\r\n async handleNoToolCalls(ctx: StepFinishDecisionContext): Promise<DecisionResult> {\r\n // 只在无工具调用时处理\r\n if (ctx.llmResponse.toolCalls && ctx.llmResponse.toolCalls.length > 0) {\r\n return Decision.Continue;\r\n }\r\n\r\n // 1. 检查是否有活跃子代理\r\n if (!this.agentPool?.hasActiveAgents()) {\r\n return Decision.Continue;\r\n }\r\n\r\n // 2. 阻塞等待\r\n const result = await this.agentPool.waitForMessage();\r\n\r\n // 3. 消息插入到 context\r\n ctx.context.add({\r\n role: 'assistant',\r\n content: `[子代理 ${result.agentId} 执行完成]:\\n\\n${result.message}`,\r\n });\r\n\r\n // 4. 重启 ReAct 循环\r\n return Decision.Approve;\r\n }\r\n\r\n async onDestroy(): Promise<void> {\r\n return this.agentPool?.shutdown() ?? Promise.resolve();\r\n }\r\n\r\n captureState(): FeatureStateSnapshot {\r\n const runtime = this.agentPool?.getRuntimeSnapshot();\r\n return {\r\n counters: runtime?.counters ?? [],\r\n hadInstances: (runtime?.instances.length ?? 0) > 0,\r\n hadActiveAgents: runtime?.instances.some(instance => instance.status === 'busy') ?? false,\r\n hadPendingMessages: runtime?.pendingMessages.some(([, messages]) => messages.length > 0) ?? false,\r\n };\r\n }\r\n\r\n async restoreState(snapshot: FeatureStateSnapshot): Promise<void> {\r\n if (!this.agentPool) {\r\n return;\r\n }\r\n\r\n const state = snapshot as {\r\n counters?: Array<[string, number]>;\r\n hadInstances?: boolean;\r\n hadActiveAgents?: boolean;\r\n hadPendingMessages?: boolean;\r\n };\r\n\r\n await this.agentPool.restoreRuntimeSnapshot({\r\n counters: state.counters,\r\n });\r\n\r\n if (state.hadInstances || state.hadActiveAgents || state.hadPendingMessages) {\r\n console.warn(\r\n '[SubAgentFeature] Restored session/rollback snapshot dropped live subagent runtime. ' +\r\n 'Subagents are not resumable and have been reset to an empty pool.'\r\n );\r\n }\r\n }\r\n}\r\n\r\n// 重新导出 AgentPool\r\nexport { AgentPool };\r\n","/**\r\n * AgentPool - 子代理管理核心\r\n * 管理父代理创建的所有子代理实例\r\n */\r\n\r\nimport type { Agent } from '../../core/agent.js';\r\nimport type { SubAgentStatus } from '../../core/lifecycle.js';\r\n\r\n/**\r\n * 子代理实例信息\r\n */\r\nexport interface SubAgentInstance {\r\n id: string;\r\n type: string;\r\n agent: Agent;\r\n status: SubAgentStatus;\r\n initialInstruction: string;\r\n createdAt: number;\r\n completedAt?: number;\r\n result?: string;\r\n error?: string;\r\n}\r\n\r\n/**\r\n * Agent 创建函数类型(异步)\r\n */\r\nexport type AgentFactory = (type: string) => Agent | Promise<Agent>;\r\n\r\n/**\r\n * AgentPool - 子代理管理核心\r\n * 管理父代理创建的所有子代理实例\r\n */\r\nexport class AgentPool {\r\n private _instances = new Map<string, SubAgentInstance>();\r\n private _counters = new Map<string, number>();\r\n private _parent: Agent;\r\n\r\n // 子代理消息回传机制\r\n /** 待回传消息队列:agentId -> messages[] */\r\n private _pendingMessages: Map<string, string[]> = new Map();\r\n /** 消息就绪解析器:key -> resolver function */\r\n private _messageResolvers: Map<string, (message: string | null) => void> = new Map();\r\n\r\n constructor(parent: Agent) {\r\n this._parent = parent;\r\n }\r\n\r\n /**\r\n * 创建子代理(不自动执行,等待 sendTo 激活)\r\n */\r\n async spawn(type: string, createAgentFn: AgentFactory): Promise<string> {\r\n // 生成 ID: type_序号\r\n const count = (this._counters.get(type) || 0) + 1;\r\n this._counters.set(type, count);\r\n const id = `${type}_${count}`;\r\n\r\n // 创建 Agent 实例(异步)\r\n const agent = await createAgentFn(type);\r\n\r\n // 注入 agentId 和 pool 引用到子代理\r\n // 用于子代理回传消息\r\n (agent as any)._agentId = id;\r\n (agent as any)._parentPool = this;\r\n\r\n // 如果父代理启用了 debug,子代理也启用并注册到同一个 DebugHub\r\n if ((this._parent as any).debugEnabled && (this._parent as any).debugHub) {\r\n const parentDebugHub = (this._parent as any).debugHub;\r\n // 子代理注册到 debug 服务器\r\n await agent.withViewer(`${type}_${count}`);\r\n // 使用父代理的同一个 debugHub 实例\r\n (agent as any).debugHub = parentDebugHub;\r\n }\r\n\r\n // 存储实例信息\r\n const instance: SubAgentInstance = {\r\n id,\r\n type,\r\n agent,\r\n status: 'idle',\r\n initialInstruction: '',\r\n createdAt: Date.now(),\r\n };\r\n this._instances.set(id, instance);\r\n\r\n // 触发 onSubAgentSpawn 钩子\r\n await this._parent.onSubAgentSpawn?.({\r\n agentId: id,\r\n type,\r\n agent,\r\n instruction: '',\r\n });\r\n\r\n // 子代理创建后处于空闲状态,等待 sendTo 激活\r\n return id;\r\n }\r\n\r\n /**\r\n * 获取实例信息\r\n */\r\n get(id: string): SubAgentInstance | undefined {\r\n return this._instances.get(id);\r\n }\r\n\r\n /**\r\n * 列出所有实例\r\n */\r\n list(filter?: SubAgentStatus): SubAgentInstance[] {\r\n const all = Array.from(this._instances.values());\r\n if (!filter) return all;\r\n return all.filter(i => i.status === filter);\r\n }\r\n\r\n /**\r\n * 向子代理发送消息(非阻塞)\r\n */\r\n async sendTo(id: string, message: string): Promise<void> {\r\n const timestamp = new Date().toISOString();\r\n console.log(`[DEBUG:sendTo] ${timestamp} agentId=${id}, msg=\"${message.slice(0, 50)}...\"`);\r\n\r\n const instance = this._instances.get(id);\r\n if (!instance) throw new Error(`子代理不存在: ${id}`);\r\n\r\n // 更新状态为 busy\r\n const oldStatus = instance.status;\r\n instance.status = 'busy';\r\n console.log(`[DEBUG:sendTo] 状态: ${oldStatus} -> busy`);\r\n\r\n // 异步执行,立即返回\r\n instance.agent.onCall(message)\r\n .then(result => {\r\n const thenTime = new Date().toISOString();\r\n console.log(`[DEBUG:sendTo.then] ${thenTime} agentId=${id}, 完成,result=\"${result.slice(0, 50)}...\"`);\r\n // 正常完成\r\n instance.status = 'idle';\r\n instance.result = result;\r\n // 报告消息(入队)\r\n this.report(id, result);\r\n })\r\n .catch(error => {\r\n const catchTime = new Date().toISOString();\r\n console.log(`[DEBUG:sendTo.catch] ${catchTime} agentId=${id}, error=${error.message}`);\r\n // 执行失败\r\n instance.status = 'failed';\r\n this._onError(id, error);\r\n });\r\n }\r\n\r\n /**\r\n * 关闭子代理\r\n */\r\n async close(id: string, reason: string = 'manual'): Promise<void> {\r\n const instance = this._instances.get(id);\r\n if (!instance) return;\r\n\r\n await instance.agent.dispose();\r\n instance.status = 'terminated';\r\n this._instances.delete(id);\r\n\r\n await this._parent.onSubAgentDestroy?.({\r\n agentId: id,\r\n type: instance.type,\r\n reason: reason as any,\r\n });\r\n }\r\n\r\n /**\r\n * 子代理回传消息到父代理\r\n * @param agentId 子代理 ID\r\n * @param message 消息内容\r\n */\r\n async report(agentId: string, message: string): Promise<void> {\r\n const timestamp = new Date().toISOString();\r\n const msgPreview = message.slice(0, 50);\r\n\r\n console.log(`[DEBUG:report] ${timestamp} agentId=${agentId}, msg=\"${msgPreview}...\"`);\r\n console.trace('[DEBUG:report] 调用栈:');\r\n\r\n // 添加到待回传队列\r\n if (!this._pendingMessages.has(agentId)) {\r\n this._pendingMessages.set(agentId, []);\r\n }\r\n this._pendingMessages.get(agentId)!.push(message);\r\n\r\n console.log(`[DEBUG:report] 入队后队列长度: ${this._pendingMessages.get(agentId)!.length}`);\r\n\r\n // 通知等待的解析器\r\n // 优先查找专门等待此 agent 的解析器\r\n const resolver = this._messageResolvers.get(agentId);\r\n if (resolver) {\r\n console.log(`[DEBUG:report] 触发专门 resolver: ${agentId}`);\r\n resolver(message);\r\n this._messageResolvers.delete(agentId);\r\n return;\r\n }\r\n\r\n // 如果没有专门解析器,查找通用等待解析器(以 wait_ 开头的)\r\n for (const [key, resolver] of this._messageResolvers) {\r\n if (key.startsWith('wait_')) {\r\n console.log(`[DEBUG:report] 触发通用 resolver: ${key}`);\r\n resolver(message);\r\n this._messageResolvers.delete(key);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 等待任意子代理的消息\r\n * @returns { agentId, message }\r\n */\r\n async waitForMessage(): Promise<{ agentId: string; message: string }> {\r\n const timestamp = new Date().toISOString();\r\n console.log(`[DEBUG:waitForMessage] ${timestamp} 开始等待`);\r\n\r\n // 检查是否有待处理消息\r\n for (const [agentId, messages] of this._pendingMessages) {\r\n if (messages.length > 0) {\r\n const message = messages.shift()!;\r\n console.log(`[DEBUG:waitForMessage] ${timestamp} 从队列取出消息 agentId=${agentId}, 队列剩余: ${messages.length}`);\r\n if (messages.length === 0) {\r\n this._pendingMessages.delete(agentId);\r\n }\r\n return { agentId, message };\r\n }\r\n }\r\n\r\n console.log(`[DEBUG:waitForMessage] ${timestamp} 队列为空,注册 resolver`);\r\n\r\n // 等待新消息(无超时,一直等待直到有消息)\r\n return new Promise((resolve) => {\r\n // 临时存储解析器(任意子代理都可以触发)\r\n const tempKey = `wait_${Date.now()}`;\r\n console.log(`[DEBUG:waitForMessage] ${timestamp} 注册 resolver: ${tempKey}`);\r\n this._messageResolvers.set(tempKey, () => {\r\n const resolveTime = new Date().toISOString();\r\n console.log(`[DEBUG:waitForMessage.resolver] ${resolveTime} resolver 被触发`);\r\n // 查找发送消息的 agentId\r\n for (const [agentId, messages] of this._pendingMessages) {\r\n if (messages.length > 0) {\r\n const message = messages.shift()!;\r\n console.log(`[DEBUG:waitForMessage.resolver] ${resolveTime} 从队列取出消息 agentId=${agentId}, 队列剩余: ${messages.length}`);\r\n if (messages.length === 0) {\r\n this._pendingMessages.delete(agentId);\r\n }\r\n resolve({ agentId, message });\r\n return;\r\n }\r\n }\r\n console.log(`[DEBUG:waitForMessage.resolver] ${resolveTime} 队列为空!`);\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * 检查是否有活跃的子代理或待处理的消息\r\n *\r\n * 注意:先检查消息队列,避免竞态条件\r\n */\r\n hasActiveAgents(): boolean {\r\n const timestamp = new Date().toISOString();\r\n // 优先检查消息队列\r\n for (const [agentId, messages] of this._pendingMessages.entries()) {\r\n if (messages.length > 0) {\r\n console.log(`[DEBUG:hasActiveAgents] ${timestamp} 发现消息队列: ${agentId}, ${messages.length} 条`);\r\n return true;\r\n }\r\n }\r\n // 再检查 busy 状态的子代理\r\n for (const instance of this._instances.values()) {\r\n if (instance.status === 'busy') {\r\n console.log(`[DEBUG:hasActiveAgents] ${timestamp} 发现 busy 子代理: ${instance.id}`);\r\n return true;\r\n }\r\n }\r\n console.log(`[DEBUG:hasActiveAgents] ${timestamp} 无活跃子代理`);\r\n return false;\r\n }\r\n\r\n /**\r\n * 检查是否有待处理的子代理消息\r\n */\r\n hasPendingMessages(): boolean {\r\n const timestamp = new Date().toISOString();\r\n for (const [agentId, messages] of this._pendingMessages.entries()) {\r\n if (messages.length > 0) {\r\n console.log(`[DEBUG:hasPendingMessages] ${timestamp} agentId=${agentId}, ${messages.length} 条消息`);\r\n return true;\r\n }\r\n }\r\n console.log(`[DEBUG:hasPendingMessages] ${timestamp} 无待处理消息`);\r\n return false;\r\n }\r\n\r\n /**\r\n * 处理子代理中断\r\n * @param agentId 子代理 ID\r\n * @param reason 中断原因\r\n * @param result 中断时的结果\r\n */\r\n async handleInterrupt(\r\n agentId: string,\r\n reason: 'limit_reached' | 'error' | 'cancelled',\r\n result: string\r\n ): Promise<void> {\r\n const timestamp = new Date().toISOString();\r\n console.log(`[DEBUG:handleInterrupt] ${timestamp} agentId=${agentId}, reason=${reason}, result=\"${result.slice(0, 50)}...\"`);\r\n\r\n const instance = this._instances.get(agentId);\r\n if (!instance) return;\r\n\r\n const oldStatus = instance.status;\r\n instance.status = 'idle';\r\n instance.result = result;\r\n console.log(`[DEBUG:handleInterrupt] ${timestamp} 状态: ${oldStatus} -> idle`);\r\n\r\n // 报告消息(入队)\r\n await this.report(agentId, result);\r\n\r\n // 触发钩子\r\n await this._parent.onSubAgentInterrupt?.({\r\n agentId,\r\n type: instance.type,\r\n reason,\r\n result,\r\n });\r\n }\r\n\r\n /**\r\n * 关闭所有子代理\r\n */\r\n async shutdown(): Promise<void> {\r\n const promises = Array.from(this._instances.keys())\r\n .map(id => this.close(id, 'parent_dispose'));\r\n await Promise.all(promises);\r\n }\r\n\r\n getRuntimeSnapshot(): {\r\n counters: Array<[string, number]>;\r\n instances: Array<{ id: string; type: string; status: SubAgentStatus }>;\r\n pendingMessages: Array<[string, string[]]>;\r\n } {\r\n return {\r\n counters: Array.from(this._counters.entries()),\r\n instances: Array.from(this._instances.values()).map(instance => ({\r\n id: instance.id,\r\n type: instance.type,\r\n status: instance.status,\r\n })),\r\n pendingMessages: Array.from(this._pendingMessages.entries()).map(([agentId, messages]) => [\r\n agentId,\r\n [...messages],\r\n ]),\r\n };\r\n }\r\n\r\n async restoreRuntimeSnapshot(snapshot: {\r\n counters?: Array<[string, number]>;\r\n }): Promise<void> {\r\n await this.shutdown();\r\n this._pendingMessages.clear();\r\n this._messageResolvers.clear();\r\n this._counters = new Map(snapshot.counters ?? []);\r\n }\r\n\r\n // 内部方法\r\n private async _onComplete(id: string, result: string): Promise<void> {\r\n const timestamp = new Date().toISOString();\r\n console.log(`[DEBUG:_onComplete] ${timestamp} agentId=${id}, result=\"${result.slice(0, 50)}...\"`);\r\n\r\n const instance = this._instances.get(id);\r\n if (!instance) return;\r\n\r\n const oldStatus = instance.status;\r\n\r\n // 先回传消息给主代理(确保消息先入队,避免竞态条件)\r\n await this.report(id, result);\r\n\r\n // 再更新状态(子代理持久存在,完成任务后回到 idle)\r\n instance.status = 'idle';\r\n instance.result = result;\r\n instance.completedAt = Date.now();\r\n\r\n console.log(`[DEBUG:_onComplete] ${timestamp} 状态: ${oldStatus} -> idle`);\r\n\r\n await this._parent.onSubAgentUpdate?.({\r\n agentId: id,\r\n type: instance.type,\r\n oldStatus,\r\n newStatus: 'idle',\r\n result,\r\n });\r\n }\r\n\r\n private async _onError(id: string, error: Error): Promise<void> {\r\n const instance = this._instances.get(id);\r\n if (!instance) return;\r\n\r\n const oldStatus = instance.status;\r\n\r\n // 先更新状态(错误情况不需要回传消息,因为父代理无法处理错误子代理的结果)\r\n instance.status = 'failed';\r\n instance.error = error.message;\r\n instance.completedAt = Date.now();\r\n\r\n await this._parent.onSubAgentUpdate?.({\r\n agentId: id,\r\n type: instance.type,\r\n oldStatus,\r\n newStatus: 'failed',\r\n error: error.message,\r\n });\r\n }\r\n}\r\n","/**\r\n * SubAgent Feature 工具定义\r\n *\r\n * 提供 5 个子代理管理工具:spawn_agent, list_agents, send_to_agent, close_agent, wait\r\n */\r\n\r\nimport type { Tool } from '../../core/types.js';\r\nimport type { Agent } from '../../core/agent.js';\r\nimport type { AgentPool } from './pool.js';\r\nimport { createTool } from '../../core/tool.js';\r\n\r\n/**\r\n * SubAgent 工具工厂类\r\n * 用于创建子代理工具,需要传入 Feature 实例来访问 AgentPool\r\n */\r\nexport class SubAgentToolFactory {\r\n private getPoolFn: () => AgentPool;\r\n private getParentAgentFn: () => Agent | undefined;\r\n\r\n constructor(options: {\r\n getPool: () => AgentPool;\r\n getParentAgent: () => Agent | undefined;\r\n }) {\r\n this.getPoolFn = options.getPool;\r\n this.getParentAgentFn = options.getParentAgent;\r\n }\r\n\r\n /**\r\n * 创建 spawn_agent 工具\r\n */\r\n createSpawnAgentTool(): Tool {\r\n const self = this;\r\n return createTool({\r\n name: 'spawn_agent',\r\n description: '创建一个子代理实例。子代理创建后处于idle状态,等待通过 send_to_agent 发送指令来激活。返回实例 ID(格式:类型名_序号)。\\n\\n子代理完成工作后,其结果会自动添加到你的上下文中,你将收到 \"[子代理 ID_执行完成]:\" 格式的消息。',\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n type: {\r\n type: 'string',\r\n description: '子代理类型名'\r\n }\r\n },\r\n required: ['type']\r\n },\r\n render: { call: 'agent-spawn', result: 'agent-spawn' },\r\n execute: async (args, context) => {\r\n const { type } = args as { type: string };\r\n const parentAgent = (context?.parentAgent as Agent | undefined) ?? self.getParentAgentFn();\r\n const pool = self.getPoolFn();\r\n\r\n if (!parentAgent) {\r\n return { error: '无法获取父代理引用' };\r\n }\r\n\r\n // 动态校验类型是否在注册表中\r\n const availableTypes = parentAgent.getRegisteredAgentTypes();\r\n if (availableTypes.length > 0 && !availableTypes.includes(type)) {\r\n return {\r\n error: `未知的子代理类型: \"${type}\"。可用类型: ${availableTypes.join(', ')}`,\r\n availableTypes,\r\n };\r\n }\r\n\r\n const agentId = await pool.spawn(type, async (t) => await parentAgent.createAgentByType(t));\r\n\r\n return {\r\n agentId,\r\n type,\r\n status: 'idle',\r\n availableTypes: parentAgent.getRegisteredAgentTypes(),\r\n allAgents: pool.list().map(i => ({\r\n agentId: i.id,\r\n type: i.type,\r\n status: i.status,\r\n })),\r\n };\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * 创建 list_agents 工具\r\n */\r\n createListAgentsTool(): Tool {\r\n const self = this;\r\n return createTool({\r\n name: 'list_agents',\r\n description: '列出所有子代理及其状态(ID、类型、状态等)。\\n\\n注意:子代理的执行结果会自动添加到你的上下文中,你不需要调用此工具来获取结果。此工具主要用于确认子代理正确启动,不要在运行期间不断监控运行情况',\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n filter: {\r\n type: 'string',\r\n enum: ['all', 'running', 'completed', 'failed', 'terminated'],\r\n description: '筛选条件,默认显示所有子代理',\r\n default: 'all'\r\n }\r\n }\r\n },\r\n render: { call: 'agent-list', result: 'json' },\r\n execute: async (args) => {\r\n const { filter = 'all' } = args as { filter?: string };\r\n const pool = self.getPoolFn();\r\n const instances = pool.list(filter === 'all' ? undefined : filter as any);\r\n\r\n return {\r\n agents: instances.map(i => ({\r\n agentId: i.id,\r\n type: i.type,\r\n status: i.status,\r\n createdAt: i.createdAt,\r\n result: i.result,\r\n error: i.error,\r\n })),\r\n total: instances.length,\r\n running: instances.filter(i => i.status === 'busy' || i.status === 'idle').length,\r\n tips: '当确认子代理工作正常时,你无需重复调用此工具以获取最新状态,可停止输出,等待子代理完成任务后自动添加到上下文中。',\r\n };\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * 创建 send_to_agent 工具\r\n */\r\n createSendToAgentTool(): Tool {\r\n const self = this;\r\n return createTool({\r\n name: 'send_to_agent',\r\n description: '向指定的子代理发送指令。只能向处于idle状态的子代理发送消息,如果子代理正在执行(busy状态),发送会失败。子代理运行期间可以执行其他工作,若无需求,应停止输出或使用wait工具,待子代理完成任务时会主动唤起',\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n agentId: {\r\n type: 'string',\r\n description: '子代理实例 ID,如 \"BasicAgent_1\" 或 \"ExplorerAgent_2\"'\r\n },\r\n message: {\r\n type: 'string',\r\n description: '要发送给子代理的消息或指令'\r\n }\r\n },\r\n required: ['agentId', 'message']\r\n },\r\n render: { call: 'agent-send', result: 'agent-send' },\r\n execute: async (args) => {\r\n const { agentId, message } = args as { agentId: string; message: string };\r\n const pool = self.getPoolFn();\r\n\r\n // 检查子代理是否存在以及状态\r\n const instance = pool.get(agentId);\r\n if (!instance) {\r\n return {\r\n error: `子代理不存在: ${agentId}`,\r\n allAgents: pool.list().map(i => ({\r\n agentId: i.id,\r\n type: i.type,\r\n status: i.status,\r\n })),\r\n };\r\n }\r\n\r\n // 检查子代理是否正在执行\r\n if (instance.status === 'busy') {\r\n return {\r\n error: `子代理 ${agentId} 正在执行任务(busy状态),无法接收新消息。请等待其完成后再发送`,\r\n agentId,\r\n currentStatus: instance.status,\r\n allAgents: pool.list().map(i => ({\r\n agentId: i.id,\r\n type: i.type,\r\n status: i.status,\r\n })),\r\n };\r\n }\r\n\r\n await pool.sendTo(agentId, message);\r\n\r\n return {\r\n agentId,\r\n status: 'message_sent',\r\n previousStatus: instance.status,\r\n message: '消息已成功发送到子代理,可以继续执行你尚未完成的其他任务,若无必要,请停止输出,等待子代理完成任务',\r\n allAgents: pool.list().map(i => ({\r\n agentId: i.id,\r\n type: i.type,\r\n status: i.status,\r\n })),\r\n };\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * 创建 close_agent 工具\r\n */\r\n createCloseAgentTool(): Tool {\r\n const self = this;\r\n return createTool({\r\n name: 'close_agent',\r\n description: '关闭指定的子代理并释放其资源。子代理将被终止并从池中移除。',\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n agentId: {\r\n type: 'string',\r\n description: '要关闭的子代理实例 ID'\r\n },\r\n reason: {\r\n type: 'string',\r\n description: '关闭原因(可选)',\r\n default: 'manual'\r\n }\r\n },\r\n required: ['agentId']\r\n },\r\n render: { call: 'agent-close', result: 'json' },\r\n execute: async (args) => {\r\n const { agentId, reason = 'manual' } = args as { agentId: string; reason?: string };\r\n const pool = self.getPoolFn();\r\n await pool.close(agentId, reason);\r\n\r\n return {\r\n agentId,\r\n status: 'closed',\r\n message: `子代理 ${agentId} 已关闭`\r\n };\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * 创建 wait 工具\r\n */\r\n createWaitTool(): Tool {\r\n const self = this;\r\n return createTool({\r\n name: 'wait',\r\n description: '调用本工具后,系统将被阻塞,等待子代理返回运行结果后继续运行。可以与 spawn_agent、send_to_agent 等工具在同一轮一起调用,表示执行完这些操作后等待子代理完成。',\r\n parameters: {\r\n type: 'object',\r\n properties: {},\r\n },\r\n render: { call: 'wait', result: 'wait' },\r\n execute: async (_args) => {\r\n const pool = self.getPoolFn();\r\n\r\n // 安全检查:是否有活跃的子代理\r\n if (!pool.hasActiveAgents()) {\r\n return {\r\n error: '当前没有正在执行的子代理(busy状态),调用 wait 无意义。请先使用 spawn_agent 创建子代理或使用 send_to_agent 向子代理发送任务。',\r\n allAgents: pool.list().map(i => ({\r\n agentId: i.id,\r\n type: i.type,\r\n status: i.status,\r\n })),\r\n };\r\n }\r\n\r\n // 只是一个标志,实际等待逻辑由反向钩子处理\r\n return {\r\n action: 'waiting_for_subagents',\r\n message: '系统将在子代理完成任务后继续...',\r\n allAgents: pool.list().map(i => ({\r\n agentId: i.id,\r\n type: i.type,\r\n status: i.status,\r\n })),\r\n };\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * 获取所有工具\r\n */\r\n getAllTools(): Tool[] {\r\n return [\r\n this.createSpawnAgentTool(),\r\n this.createListAgentsTool(),\r\n this.createSendToAgentTool(),\r\n this.createCloseAgentTool(),\r\n this.createWaitTool(),\r\n ];\r\n }\r\n}\r\n","/**\r\n * Todo Feature - 任务列表管理功能模块\r\n *\r\n * 提供任务创建、查询、更新等能力,用于跟踪复杂任务的进度\r\n * 内置智能提醒功能,自动跟踪工具使用并在合适时机注入提醒\r\n *\r\n * 重构说明:\r\n * - 使用 static hooks 静态声明反向钩子实现提醒逻辑\r\n * - 不再需要在 Agent 中重写 onStepStart/onStepFinished\r\n * - 每个发生 Todo 写操作的 Step 结束后,自动注入一次最新完整任务列表\r\n */\r\n\r\nimport { fileURLToPath } from 'url';\r\nimport { dirname } from 'path';\r\nimport { readFile } from 'fs/promises';\r\nimport type {\r\n AgentFeature,\r\n FeatureInitContext,\r\n FeatureContext,\r\n FeatureStateSnapshot,\r\n PackageInfo,\r\n} from '../../core/feature.js';\r\nimport type { HookDeclarations } from '../../core/hook-declarations.js';\r\nimport { CoreLifecycle } from '../../core/lifecycle.js';\r\nimport { getPackageInfoFromSource } from '../../core/feature.js';\r\nimport type { StepStartContext, StepFinishDecisionContext, CallStartContext } from '../../core/lifecycle.js';\r\nimport { Decision } from '../../core/lifecycle.js';\r\nimport type { DecisionResult } from '../../core/lifecycle.js';\r\nimport type { Tool } from '../../core/types.js';\r\nimport type { TodoPlanSnapshot } from '../../core/types.js';\r\nimport { DebugHub } from '../../core/debug-hub.js';\r\nimport { TodoToolFactory } from './tools.js';\r\nimport type { TodoTask, TodoTaskUpdate, TodoTaskSummary, TaskStatus, TodoFeatureConfig } from './types.js';\r\n\r\n// ESM 中获取 __dirname\r\nconst __filename = fileURLToPath(import.meta.url);\r\nconst __dirname = dirname(__filename);\r\n\r\n/** StepFinish 注入的任务列表体积上限 */\r\nconst MAX_INJECT_TASKS = 20;\r\nconst MAX_SUBJECT_LENGTH = 160;\r\nconst MAX_DESCRIPTION_LENGTH = 500;\r\n\r\n/**\r\n * TodoFeature 实现\r\n *\r\n * 提供任务管理和智能提醒功能\r\n * 使用反向钩子自动处理提醒逻辑,无需在 Agent 中重写钩子方法\r\n */\r\nexport class TodoFeature implements AgentFeature {\r\n\r\n static hooks: HookDeclarations = {\r\n checkAndInjectReminder: { lifecycle: CoreLifecycle.StepStart, kind: 'observe' as const },\r\n onCallStart: { lifecycle: CoreLifecycle.CallStart, kind: 'observe' as const },\r\n recordToolUsage: { lifecycle: CoreLifecycle.StepFinish, kind: 'guard' as const, role: 'advisor' as const },\r\n };\r\n readonly name = 'todo';\r\n readonly source = __filename.replace(/\\\\/g, '/');\r\n readonly description = '维护任务清单,并在合适的循环时机自动提醒模型更新 todo 状态。';\r\n\r\n private tasks = new Map<string, TodoTask>();\r\n private counter = 0;\r\n private debugAgentId = '';\r\n private config: Required<Omit<TodoFeatureConfig, 'reminderTemplate' | 'reminderThresholdWithTasks' | 'reminderThresholdWithoutTasks'>> & {\r\n reminderTemplate?: string;\r\n reminderThresholdWithTasks?: number;\r\n reminderThresholdWithoutTasks?: number;\r\n };\r\n\r\n // Reminder 相关状态\r\n private reminderContent = '';\r\n\r\n // 连续未使用 todo 工具的轮次计数器\r\n private consecutiveNoTodoTurns = 0;\r\n // 上一轮是否已注入 reminder(防止重复注入)\r\n private reminderInjected = false;\r\n\r\n // 工具工厂实例\r\n private toolFactory?: TodoToolFactory;\r\n\r\n private _packageInfo: PackageInfo | null = null;\r\n\r\n constructor(config: TodoFeatureConfig = {}) {\r\n this.config = {\r\n reminderThresholdWithTasks: config.reminderThresholdWithTasks ?? 3,\r\n reminderThresholdWithoutTasks: config.reminderThresholdWithoutTasks ?? 6,\r\n reminderTemplate: config.reminderTemplate,\r\n };\r\n this.reminderContent = this.getDefaultReminder();\r\n\r\n // 初始化工具工厂\r\n this.toolFactory = new TodoToolFactory({\r\n getTask: (taskId) => this.getTask(taskId),\r\n createTask: (subject, description, options) => this.createTask(subject, description, options),\r\n listTasks: (filter) => this.listTasks(filter),\r\n updateTask: (taskId, updates) => this.updateTask(taskId, updates),\r\n clearTasks: () => this.clearTasks(),\r\n });\r\n }\r\n\r\n // ========== AgentFeature 接口实现 ==========\r\n\r\n /**\r\n * 获取包信息(统一打包方案)\r\n */\r\n getPackageInfo(): PackageInfo | null {\r\n if (!this._packageInfo) {\r\n this._packageInfo = getPackageInfoFromSource(this.source);\r\n }\r\n return this._packageInfo;\r\n }\r\n\r\n /**\r\n * 获取模板名称列表(统一打包方案)\r\n */\r\n getTemplateNames(): string[] {\r\n return [\r\n 'task-create',\r\n 'task-list',\r\n 'task-update',\r\n 'task-clear',\r\n ];\r\n }\r\n\r\n getTools(): Tool[] {\r\n return this.toolFactory?.getAllTools() || [];\r\n }\r\n\r\n async onInitiate(_ctx: FeatureInitContext): Promise<void> {\r\n console.log(`[TodoFeature] Initialized with reminderThresholdWithTasks=${this.config.reminderThresholdWithTasks}, reminderThresholdWithoutTasks=${this.config.reminderThresholdWithoutTasks}`);\r\n\r\n // 如果配置了模板文件,异步加载\r\n const templatePath = this.config.reminderTemplate;\r\n if (templatePath) {\r\n try {\r\n this.reminderContent = await readFile(templatePath, 'utf-8');\r\n console.log('[TodoFeature] Loaded reminder template from: ' + templatePath);\r\n } catch {\r\n console.log('[TodoFeature] Failed to load template, using default reminder');\r\n // 保持默认 reminder\r\n }\r\n }\r\n }\r\n\r\n async onDestroy(_ctx: FeatureContext): Promise<void> {\r\n this.pushDebugSnapshot();\r\n }\r\n\r\n captureState(): FeatureStateSnapshot {\r\n return {\r\n tasks: Array.from(this.tasks.values()),\r\n counter: this.counter,\r\n reminderContent: this.reminderContent,\r\n consecutiveNoTodoTurns: this.consecutiveNoTodoTurns,\r\n reminderInjected: this.reminderInjected,\r\n };\r\n }\r\n\r\n restoreState(snapshot: FeatureStateSnapshot): void {\r\n const state = snapshot as {\r\n tasks?: TodoTask[];\r\n counter?: number;\r\n reminderContent?: string;\r\n consecutiveNoTodoTurns?: number;\r\n reminderInjected?: boolean;\r\n };\r\n\r\n // 白名单重建:仅保留新 schema 字段,丢弃旧 session 中可能存在的\r\n // activeForm/owner/blocks/blockedBy 等已删除字段\r\n this.tasks = new Map((state.tasks ?? []).map(task => [\r\n task.id,\r\n {\r\n id: task.id,\r\n subject: task.subject,\r\n description: task.description,\r\n status: task.status,\r\n metadata: task.metadata,\r\n createdAt: task.createdAt,\r\n updatedAt: task.updatedAt,\r\n },\r\n ]));\r\n this.counter = typeof state.counter === 'number' ? state.counter : 0;\r\n this.reminderContent = typeof state.reminderContent === 'string'\r\n ? state.reminderContent\r\n : this.getDefaultReminder();\r\n this.consecutiveNoTodoTurns = typeof state.consecutiveNoTodoTurns === 'number'\r\n ? state.consecutiveNoTodoTurns\r\n : 0;\r\n this.reminderInjected = Boolean(state.reminderInjected);\r\n this.pushDebugSnapshot();\r\n }\r\n\r\n pushDebugSnapshot(agentId?: string): void {\r\n if (agentId) {\r\n this.debugAgentId = agentId;\r\n }\r\n // 身份自持:只用显式传入或上次记住的 agentId,不依赖全局选中状态\r\n const targetAgentId = agentId || this.debugAgentId;\r\n if (!targetAgentId || !DebugHub.getInstance().isConnected()) return;\r\n DebugHub.getInstance().updateTodoPlan(targetAgentId, this.getPlanSnapshot());\r\n }\r\n\r\n getHookDescription(lifecycle: string, methodName: string): string | undefined {\r\n if (lifecycle === 'StepStart' && methodName === 'checkAndInjectReminder') {\r\n return '在每轮开始时检查提醒阈值;连续多轮未使用 todo 工具时注入系统提醒(含当前/下一任务状态)。';\r\n }\r\n if (lifecycle === 'StepFinish' && methodName === 'recordToolUsage') {\r\n return '统计 todo 工具使用并更新计数;若本轮有写操作,向 Context 注入一次最新完整任务列表。';\r\n }\r\n return undefined;\r\n }\r\n\r\n // ========== 反向钩子(static hooks 声明)==========\r\n\r\n /**\r\n * Step 开始时检查是否需要注入 reminder\r\n *\r\n * 触发时机:每轮 ReAct 迭代开始时\r\n * 处理逻辑:\r\n * 1. 检查连续未使用 todo 工具的轮次\r\n * 2. 达到阈值时注入 reminder 系统消息(包含当前/下一任务状态)\r\n * 3. 防止重复注入\r\n */\r\n async checkAndInjectReminder(ctx: StepStartContext): Promise<void> {\r\n const threshold = this.getCurrentThreshold();\r\n console.log(`[TodoFeature] callIndex=${ctx.callIndex}, counter=${this.consecutiveNoTodoTurns}, threshold=${threshold}, injected=${this.reminderInjected}`);\r\n\r\n // 检查是否需要注入 reminder\r\n if (this.consecutiveNoTodoTurns >= threshold && !this.reminderInjected) {\r\n console.log('[TodoFeature] Threshold reached, injecting reminder');\r\n ctx.context.add({ role: 'system', content: this.buildDynamicReminder() });\r\n this.reminderInjected = true;\r\n }\r\n }\r\n\r\n /**\r\n * Call 开始时注入简短任务状态\r\n *\r\n * 触发时机:每次用户发送新消息、Agent 开始处理时\r\n * 处理逻辑:\r\n * 1. 首次调用跳过(还没有任务)\r\n * 2. 无待执行任务时跳过\r\n * 3. 有待执行任务时注入简短的\"当前/下一项\"状态\r\n * 4. 重置 no-todo 计数器(新一轮用户交互)\r\n */\r\n async onCallStart(ctx: CallStartContext): Promise<void> {\r\n // 首次调用不注入\r\n if (ctx.isFirstCall) return;\r\n\r\n // 检查是否有待执行任务\r\n const hasActiveTasks = Array.from(this.tasks.values()).some(\r\n t => t.status === 'pending' || t.status === 'in_progress'\r\n );\r\n if (!hasActiveTasks) return;\r\n\r\n // 注入简短任务状态\r\n ctx.context.add({ role: 'system', content: this.buildCallStartBrief() });\r\n\r\n // 重置计数器(新的用户消息代表新一轮交互)\r\n this.consecutiveNoTodoTurns = 0;\r\n this.reminderInjected = false;\r\n\r\n console.log('[TodoFeature] CallStart: injected brief task status, reset counter');\r\n }\r\n\r\n /**\r\n * Step 结束时记录是否使用了 todo 工具\r\n *\r\n * 触发时机:每轮 ReAct 迭代结束时(工具结果已写入 Context 后)\r\n * 处理逻辑:\r\n * 1. 检查本轮是否使用了 todo 工具\r\n * 2. 若有写操作(create/update/clear),向 Context 追加一次最新完整任务列表\r\n * 3. 使用了则重置计数器,未使用则计数器+1\r\n * 4. 返回 Continue 使用默认行为\r\n */\r\n async recordToolUsage(ctx: StepFinishDecisionContext): Promise<DecisionResult> {\r\n const toolCalls = ctx.llmResponse.toolCalls ?? [];\r\n const usedTodoTool = toolCalls.some((call: { name: string }) => this.isTodoTool(call.name));\r\n const wroteTodo = toolCalls.some((call: { name: string }) => this.isTodoWriteTool(call.name));\r\n\r\n if (usedTodoTool) {\r\n // 使用了 todo 工具,重置计数器\r\n this.consecutiveNoTodoTurns = 0;\r\n this.reminderInjected = false;\r\n console.log(`[TodoFeature] Todo tool used, reset counter`);\r\n } else {\r\n // 未使用 todo 工具,计数器加 1\r\n this.consecutiveNoTodoTurns++;\r\n const threshold = this.getCurrentThreshold();\r\n console.log(`[TodoFeature] No todo tool, counter=${this.consecutiveNoTodoTurns}/${threshold}`);\r\n }\r\n\r\n // 若本轮有 Todo 写操作,注入一次最新完整任务列表\r\n if (wroteTodo) {\r\n const planContext = this.buildCurrentTaskPlanContext();\r\n ctx.context.addSystemMessage(\r\n planContext,\r\n ctx.callIndex,\r\n this.name,\r\n 'todo-current-plan',\r\n );\r\n console.log('[TodoFeature] Injected current task plan after write operations');\r\n }\r\n\r\n // 返回 Continue 使用默认行为\r\n return Decision.Continue;\r\n }\r\n\r\n // ========== 公开 API ==========\r\n\r\n /**\r\n * 设置 reminder 内容\r\n */\r\n setReminderContent(content: string): void {\r\n this.reminderContent = content;\r\n }\r\n\r\n /**\r\n * 获取当前的提醒阈值(根据任务状态动态调整)\r\n */\r\n private getCurrentThreshold(): number {\r\n // 检查是否有待执行的任务(pending 或 in_progress)\r\n const hasActiveTasks = Array.from(this.tasks.values()).some(\r\n t => t.status === 'pending' || t.status === 'in_progress'\r\n );\r\n return hasActiveTasks\r\n ? this.config.reminderThresholdWithTasks!\r\n : this.config.reminderThresholdWithoutTasks!;\r\n }\r\n\r\n /**\r\n * 创建任务\r\n */\r\n createTask(\r\n subject: string,\r\n description: string = '',\r\n options?: { metadata?: Record<string, unknown> }\r\n ): TodoTask {\r\n this.counter++;\r\n const task: TodoTask = {\r\n id: String(this.counter),\r\n subject,\r\n description: description || undefined,\r\n status: 'pending',\r\n metadata: options?.metadata,\r\n createdAt: Date.now(),\r\n updatedAt: Date.now(),\r\n };\r\n this.tasks.set(task.id, task);\r\n console.log(`[TodoFeature] Created task ${task.id}: ${subject} (total tasks: ${this.tasks.size})`);\r\n this.pushDebugSnapshot();\r\n return task;\r\n }\r\n\r\n /**\r\n * 获取任务详情\r\n */\r\n getTask(taskId: string): TodoTask | undefined {\r\n return this.tasks.get(taskId);\r\n }\r\n\r\n /**\r\n * 列出所有任务摘要\r\n */\r\n listTasks(filter?: { status?: TaskStatus }): TodoTaskSummary[] {\r\n let tasks = Array.from(this.tasks.values());\r\n if (filter?.status) {\r\n tasks = tasks.filter(t => t.status === filter.status);\r\n }\r\n return tasks.map(task => ({\r\n id: task.id,\r\n subject: task.subject,\r\n status: task.status,\r\n }));\r\n }\r\n\r\n /**\r\n * 更新任务\r\n *\r\n * 允许更新的字段:status, subject, description(模型工具可见)。\r\n * metadata 不在模型工具 schema 中,但内部代码(如 ControlledTodoFeature)\r\n * 需要通过它记录终态时间戳等生命周期数据。\r\n */\r\n updateTask(taskId: string, updates: TodoTaskUpdate & { metadata?: Record<string, unknown> }): TodoTask | undefined {\r\n const task = this.tasks.get(taskId);\r\n if (!task) return undefined;\r\n\r\n const allowedFields: string[] = ['status', 'subject', 'description', 'metadata'];\r\n for (const field of allowedFields) {\r\n if (updates[field as keyof typeof updates] !== undefined) {\r\n (task as unknown as Record<string, unknown>)[field] = updates[field as keyof typeof updates];\r\n }\r\n }\r\n task.updatedAt = Date.now();\r\n\r\n this.pushDebugSnapshot();\r\n return task;\r\n }\r\n\r\n /**\r\n * 清空所有未完成任务,返回被取消的任务数量\r\n */\r\n clearTasks(): number {\r\n const now = Date.now();\r\n let count = 0;\r\n for (const task of this.tasks.values()) {\r\n if (task.status === 'pending' || task.status === 'in_progress') {\r\n task.status = 'deleted';\r\n task.updatedAt = now;\r\n count++;\r\n }\r\n }\r\n this.pushDebugSnapshot();\r\n return count;\r\n }\r\n\r\n getPlanSnapshot(): TodoPlanSnapshot {\r\n const tasks = Array.from(this.tasks.values())\r\n .map(task => ({\r\n id: task.id,\r\n subject: task.subject,\r\n description: task.description || '',\r\n status: task.status,\r\n metadata: task.metadata && typeof task.metadata === 'object' ? { ...task.metadata } : undefined,\r\n createdAt: task.createdAt,\r\n updatedAt: task.updatedAt,\r\n }))\r\n .sort((left, right) => left.createdAt - right.createdAt || Number(left.id) - Number(right.id));\r\n return {\r\n feature: 'todo',\r\n updatedAt: Date.now(),\r\n counter: this.counter,\r\n tasks,\r\n summary: {\r\n total: tasks.length,\r\n pending: tasks.filter(task => task.status === 'pending').length,\r\n inProgress: tasks.filter(task => task.status === 'in_progress').length,\r\n completed: tasks.filter(task => task.status === 'completed').length,\r\n cancelled: tasks.filter(task => task.status === 'deleted').length,\r\n },\r\n };\r\n }\r\n\r\n // ========== 私有方法 ==========\r\n\r\n /** 判断是否是 todo 工具(读或写) */\r\n private isTodoTool(name: string): boolean {\r\n return name === 'task_create' || name === 'task_list' ||\r\n name === 'task_update' || name === 'task_clear';\r\n }\r\n\r\n /** 判断是否是 todo 写工具(仅 task_create 触发完整列表注入) */\r\n private isTodoWriteTool(name: string): boolean {\r\n return name === 'task_create';\r\n }\r\n\r\n /** 截断文本到指定长度 */\r\n private truncate(text: string, maxLength: number): string {\r\n if (text.length <= maxLength) return text;\r\n return text.slice(0, maxLength) + '…';\r\n }\r\n\r\n /**\r\n * 构建 StepFinish 注入的最新完整任务列表文本\r\n * 仅包含 active tasks(pending + in_progress),按 createdAt 升序\r\n */\r\n private buildCurrentTaskPlanContext(): string {\r\n const activeTasks = Array.from(this.tasks.values())\r\n .filter(task => task.status === 'pending' || task.status === 'in_progress')\r\n .sort((a, b) => a.createdAt - b.createdAt || Number(a.id) - Number(b.id));\r\n\r\n if (activeTasks.length === 0) {\r\n return '当前没有待执行任务。若当前工作仍需多步跟踪,可创建任务。不要向用户提及此内部提示。';\r\n }\r\n\r\n const visible = activeTasks.slice(0, MAX_INJECT_TASKS);\r\n const omitted = activeTasks.length - visible.length;\r\n\r\n const lines: string[] = ['[当前任务计划]'];\r\n for (const task of visible) {\r\n const subject = this.truncate(task.subject, MAX_SUBJECT_LENGTH);\r\n const desc = task.description ? this.truncate(task.description, MAX_DESCRIPTION_LENGTH) : '';\r\n lines.push(`- #${task.id} [${task.status}] ${subject}`);\r\n if (desc) {\r\n lines.push(` ${desc}`);\r\n }\r\n }\r\n if (omitted > 0) {\r\n lines.push(`(其余 ${omitted} 项未展示;如需查看全部计划,请使用 task_list。)`);\r\n }\r\n lines.push('');\r\n lines.push('请以此列表作为当前任务计划继续推进;任务开始、完成、调整或取消时,使用 Todo 工具同步状态。');\r\n lines.push('不要向用户提及此内部提示。');\r\n\r\n return lines.join('\\n');\r\n }\r\n\r\n /**\r\n * 构建动态 reminder 文本\r\n * 如果有 active tasks,包含\"当前\"和\"下一项\"信息\r\n * 否则回退到默认温和提醒\r\n */\r\n private buildDynamicReminder(): string {\r\n const activeTasks = Array.from(this.tasks.values())\r\n .filter(task => task.status === 'pending' || task.status === 'in_progress')\r\n .sort((a, b) => a.createdAt - b.createdAt || Number(a.id) - Number(b.id));\r\n\r\n if (activeTasks.length === 0) {\r\n // 无待执行任务,使用自定义模板或默认提醒\r\n return this.reminderContent || this.getDefaultReminder();\r\n }\r\n\r\n const currentTask = activeTasks.find(t => t.status === 'in_progress');\r\n const nextTask = activeTasks.find(t => t.status === 'pending');\r\n\r\n const lines: string[] = ['[任务状态提醒]'];\r\n if (currentTask) {\r\n lines.push(`当前:#${currentTask.id} ${currentTask.subject}`);\r\n } else {\r\n lines.push('当前:无');\r\n }\r\n if (nextTask) {\r\n lines.push(`下一项:#${nextTask.id} ${nextTask.subject}`);\r\n } else {\r\n lines.push('下一项:无');\r\n }\r\n lines.push('');\r\n // 拼接自定义模板尾部或默认提醒文本\r\n const tail = this.reminderContent || this.getDefaultReminder();\r\n lines.push(tail);\r\n\r\n return lines.join('\\n');\r\n }\r\n\r\n /** 获取默认 reminder 内容 */\r\n private getDefaultReminder(): string {\r\n return '最近没有更新任务状态。若该计划仍适用,请在开始、完成、调整或取消任务时使用 Todo 工具同步状态;若计划已不适用,可清理未完成任务。仅在与当前工作相关时使用这些工具。这只是温和的提醒——如果不适用请忽略。务必注意:绝不要向用户提及此提醒。';\r\n }\r\n\r\n /**\r\n * 构建 CallStart 简短任务状态\r\n * 仅包含\"当前/下一项\"两行,不附带催促语\r\n */\r\n private buildCallStartBrief(): string {\r\n const activeTasks = Array.from(this.tasks.values())\r\n .filter(task => task.status === 'pending' || task.status === 'in_progress')\r\n .sort((a, b) => a.createdAt - b.createdAt || Number(a.id) - Number(b.id));\r\n\r\n const currentTask = activeTasks.find(t => t.status === 'in_progress');\r\n const nextTask = activeTasks.find(t => t.status === 'pending');\r\n\r\n const lines: string[] = ['[任务状态]'];\r\n if (currentTask) {\r\n lines.push(`当前:#${currentTask.id} ${currentTask.subject}`);\r\n } else {\r\n lines.push('当前:无');\r\n }\r\n if (nextTask) {\r\n lines.push(`下一项:#${nextTask.id} ${nextTask.subject}`);\r\n } else {\r\n lines.push('下一项:无');\r\n }\r\n lines.push('');\r\n lines.push('请根据当前任务计划继续推进。不要向用户提及此内部提示。');\r\n\r\n return lines.join('\\n');\r\n }\r\n}\r\n\r\n// 重新导出类型\r\nexport type { TodoTask, TodoTaskUpdate, TodoTaskSummary, TaskStatus, TodoFeatureConfig };\r\n","/**\r\n * Todo Feature 工具定义\r\n *\r\n * 提供 4 个任务管理工具:task_create, task_list, task_update, task_clear\r\n *\r\n * 设计要点:\r\n * - execute 返回 withDisplay(精简文本, 丰富 display 数据)\r\n * - 模型只看到精简确认(如 { ok, taskId, status })\r\n * - 前端通过 display 数据渲染完整卡片(如任务列表)\r\n * - 真正的完整任务列表在 StepFinish 时注入一次,而非每次 create 重复\r\n */\r\n\r\nimport type { Tool } from '../../core/types.js';\r\nimport { createTool } from '../../core/tool.js';\r\nimport { withDisplay } from '../../core/tool-result-display.js';\r\nimport type { TodoTask, TodoTaskUpdate, TodoTaskSummary, TaskStatus } from './types.js';\r\n/**\r\n * Todo 工具工厂类\r\n * 用于创建 Todo 工具,需要传入 Feature 实例来访问任务数据\r\n */\r\nexport class TodoToolFactory {\r\n private getTaskFn: (taskId: string) => TodoTask | undefined;\r\n private createTaskFn: (\r\n subject: string,\r\n description: string,\r\n options?: { metadata?: Record<string, unknown> }\r\n ) => TodoTask;\r\n private listTasksFn: (filter?: { status?: TaskStatus }) => TodoTaskSummary[];\r\n private updateTaskFn: (taskId: string, updates: TodoTaskUpdate) => TodoTask | undefined;\r\n private clearTasksFn: () => number;\r\n\r\n constructor(options: {\r\n getTask: (taskId: string) => TodoTask | undefined;\r\n createTask: (\r\n subject: string,\r\n description: string,\r\n options?: { metadata?: Record<string, unknown> }\r\n ) => TodoTask;\r\n listTasks: (filter?: { status?: TaskStatus }) => TodoTaskSummary[];\r\n updateTask: (taskId: string, updates: TodoTaskUpdate) => TodoTask | undefined;\r\n clearTasks: () => number;\r\n }) {\r\n this.getTaskFn = options.getTask;\r\n this.createTaskFn = options.createTask;\r\n this.listTasksFn = options.listTasks;\r\n this.updateTaskFn = options.updateTask;\r\n this.clearTasksFn = options.clearTasks;\r\n }\r\n\r\n /**\r\n * 创建 task_create 工具\r\n */\r\n createCreateTool(): Tool {\r\n const self = this;\r\n return createTool({\r\n name: 'task_create',\r\n description: `创建一个结构化的任务列表,用于跟踪当前会话的工作进度。\r\n\r\n使用时机:\r\n- 复杂的多步骤任务(需要 3 个或以上独立步骤)\r\n- 非平凡且复杂的任务(需要仔细规划)\r\n- 用户明确要求创建任务列表\r\n- 收到新指令时捕获任务\r\n\r\n任务字段:\r\n- subject: 简短可执行的标题,使用祈使句形式(如 \"修复认证漏洞\")\r\n- description: 详细描述,包括上下文和验收标准(可选)\r\n\r\n重要说明:\r\n- subject 应该是祈使句形式(\"执行任务\")\r\n- description 是可选的,简单任务不需要填写\r\n- 创建后任务状态为 pending,可以通过 task_update 更新为 in_progress、completed 或 deleted(取消并保留记录)`,\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n subject: { type: 'string', description: '简短的任务标题,使用祈使句形式(如 \"运行测试\")' },\r\n description: { type: 'string', description: '详细的任务描述,包括上下文、具体步骤和验收标准' },\r\n },\r\n required: ['subject'],\r\n },\r\n render: { call: 'task-create', result: 'task-create' },\r\n execute: ({ subject, description = '' }: { subject?: unknown; description?: unknown }) => {\r\n const task = self.createTaskFn(String(subject), String(description));\r\n // 模型只看极简确认;前端通过 display 看到完整信息\r\n return Promise.resolve(withDisplay(\r\n JSON.stringify({ ok: true, taskId: task.id, status: task.status }),\r\n {\r\n task: {\r\n id: task.id,\r\n subject: task.subject,\r\n description: task.description || '',\r\n status: task.status,\r\n },\r\n allTasks: self.listTasksFn(),\r\n message: `任务已创建,ID: ${task.id}`,\r\n },\r\n ));\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * 创建 task_list 工具\r\n */\r\n createListTool(): Tool {\r\n const self = this;\r\n return createTool({\r\n name: 'task_list',\r\n description: `列出任务列表中的所有任务摘要。\r\n\r\n使用时机:\r\n- 查看当前所有任务的状态\r\n- 了解整体进度\r\n\r\n返回信息:\r\n- id: 任务标识符\r\n- subject: 简短描述\r\n- status: 任务状态(pending/in_progress/completed/deleted)`,\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n status: {\r\n type: 'string',\r\n enum: ['pending', 'in_progress', 'completed', 'deleted', 'all'],\r\n description: '按状态筛选任务,默认显示所有任务',\r\n default: 'all',\r\n },\r\n },\r\n },\r\n render: { call: 'task-list', result: 'task-list' },\r\n execute: ({ status = 'all' }: { status?: TaskStatus | 'all' }) => {\r\n const tasks = self.listTasksFn(status === 'all' ? undefined : { status });\r\n const summary = {\r\n total: tasks.length,\r\n pending: tasks.filter(t => t.status === 'pending').length,\r\n inProgress: tasks.filter(t => t.status === 'in_progress').length,\r\n completed: tasks.filter(t => t.status === 'completed').length,\r\n cancelled: tasks.filter(t => t.status === 'deleted').length,\r\n };\r\n return Promise.resolve(withDisplay(\r\n JSON.stringify({ tasks }),\r\n { tasks, summary },\r\n ));\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * 创建 task_update 工具\r\n */\r\n createUpdateTool(): Tool {\r\n const self = this;\r\n return createTool({\r\n name: 'task_update',\r\n description: `更新任务的状态或详细信息。\r\n\r\n状态工作流:pending → in_progress → completed\r\n\r\n主要用途:\r\n1. 标记任务进行中:将 status 设置为 \"in_progress\"\r\n2. 标记任务完成:将 status 设置为 \"completed\"\r\n3. 取消任务并保留记录:将 status 设置为 \"deleted\"\r\n\r\n任务字段:\r\n- subject: 简短可执行的标题,使用祈使句形式(如 \"执行任务\")\r\n- description: 详细描述,包括上下文和验收标准`,\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n taskId: { type: 'string', description: '要更新的任务 ID' },\r\n status: {\r\n type: 'string',\r\n enum: ['pending', 'in_progress', 'completed', 'deleted'],\r\n description: '任务状态',\r\n },\r\n subject: { type: 'string', description: '新的任务标题' },\r\n description: { type: 'string', description: '新的任务描述' },\r\n },\r\n required: ['taskId'],\r\n },\r\n render: { call: 'task-update', result: 'task-update' },\r\n execute: (rawArgs: Record<string, unknown>) => {\r\n const { taskId, ...rest } = rawArgs as unknown as { taskId: string } & TodoTaskUpdate;\r\n const task = self.updateTaskFn(taskId, rest);\r\n if (!task) {\r\n return Promise.resolve({ ok: false, error: `任务 ${taskId} 不存在` });\r\n }\r\n return Promise.resolve(withDisplay(\r\n JSON.stringify({ ok: true, taskId: task.id, status: task.status }),\r\n {\r\n id: task.id,\r\n subject: task.subject,\r\n status: task.status,\r\n message: `任务 ${taskId} 已更新`,\r\n },\r\n ));\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * 创建 task_clear 工具\r\n */\r\n createClearTool(): Tool {\r\n const self = this;\r\n return createTool({\r\n name: 'task_clear',\r\n description: `取消任务列表中的所有未完成任务,并保留历史记录。\r\n\r\n注意:此操作不会移除历史;pending/in_progress 会变为 deleted,completed 会保留。`,\r\n parameters: {\r\n type: 'object',\r\n properties: {},\r\n },\r\n render: { call: 'task-clear', result: 'task-clear' },\r\n execute: () => {\r\n const cancelledCount = self.clearTasksFn();\r\n return Promise.resolve(withDisplay(\r\n JSON.stringify({ ok: true, cancelledCount }),\r\n { message: `已取消 ${cancelledCount} 个未完成任务` },\r\n ));\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * 获取所有工具\r\n */\r\n getAllTools(): Tool[] {\r\n return [\r\n this.createCreateTool(),\r\n this.createListTool(),\r\n this.createUpdateTool(),\r\n this.createClearTool(),\r\n ];\r\n }\r\n}\r\n","/**\r\n * UserInputFeature - 通过调试界面获取用户输入\r\n *\r\n * 功能:\r\n * - 提供 get_user_input 工具,允许 LLM 请求用户输入\r\n * - 通过 DebugHub 的 UDS 通道与 ViewerWorker 通信\r\n * - 前端显示输入框,用户提交后返回给 Agent\r\n */\r\n\r\nimport { fileURLToPath } from 'url';\r\nimport { createTool } from '../../core/tool.js';\r\nimport type {\r\n Tool,\r\n UserInputAction,\r\n UserInputChoiceAnswer,\r\n UserInputQuestion,\r\n UserInputRequest,\r\n UserInputResponse,\r\n} from '../../core/types.js';\r\nimport type { AgentFeature, FeatureInitContext, FeatureContext, PackageInfo } from '../../core/feature.js';\r\nimport { getPackageInfoFromSource } from '../../core/feature.js';\r\nimport { DebugHub } from '../../core/debug-hub.js';\r\n\r\nexport interface UserInputFeatureConfig {\r\n /** 默认超时时间(毫秒),默认无限等待 */\r\n timeout?: number;\r\n}\r\n\r\ninterface ChoiceToolQuestionInput {\r\n id: string;\r\n question: string;\r\n options: Array<{\r\n id: string;\r\n label: string;\r\n description?: string;\r\n allowSupplement?: boolean;\r\n supplementRequired?: boolean;\r\n supplementLabel?: string;\r\n supplementPlaceholder?: string;\r\n }>;\r\n allowCustom?: boolean;\r\n customLabel?: string;\r\n customPlaceholder?: string;\r\n}\r\n\r\nconst choiceToolRender = {\r\n call: {\r\n call: '<div class=\"bash-command\">等待用户在选择弹窗中决策</div>',\r\n result: '',\r\n },\r\n result: {\r\n call: '',\r\n result: '<div class=\"bash-command\">用户已完成选择</div>',\r\n },\r\n};\r\n\r\nexport class UserInputFeature implements AgentFeature {\r\n readonly name = 'user-input';\r\n readonly source = fileURLToPath(import.meta.url).replace(/\\\\/g, '/');\r\n readonly description = '允许 Agent 通过调试界面向用户发起输入请求并等待回复。';\r\n\r\n private defaultTimeout: number;\r\n private nextDraftInput = '';\r\n private _agentId: string | null = null;\r\n\r\n /**\r\n * 缓存包信息\r\n */\r\n private _packageInfo: PackageInfo | null = null;\r\n\r\n /**\r\n * 获取包信息(统一打包方案)\r\n */\r\n getPackageInfo(): PackageInfo | null {\r\n if (!this._packageInfo) {\r\n this._packageInfo = getPackageInfoFromSource(this.source);\r\n }\r\n return this._packageInfo;\r\n }\r\n\r\n /**\r\n * 获取模板名称列表(统一打包方案)\r\n * 注意:UserInputFeature 没有渲染模板\r\n */\r\n getTemplateNames(): string[] {\r\n return [];\r\n }\r\n\r\n constructor(config: UserInputFeatureConfig = {}) {\r\n this.defaultTimeout = config.timeout ?? Infinity; // 无限等待\r\n }\r\n\r\n setNextDraftInput(input: string): void {\r\n this.nextDraftInput = input;\r\n }\r\n\r\n /**\r\n * 请求用户输入(核心方法)\r\n */\r\n async requestUserInput(prompt: string, timeout?: number): Promise<string> {\r\n const response = await this.requestUserInputEvent({ prompt }, timeout);\r\n if (response.kind !== 'text') {\r\n throw new Error(`Expected text input but received action '${response.actionId ?? 'unknown'}'`);\r\n }\r\n return response.text ?? '';\r\n }\r\n\r\n async requestUserInputEvent(\r\n request: UserInputRequest,\r\n timeout?: number,\r\n ): Promise<UserInputResponse> {\r\n // 直接获取 DebugHub 实例\r\n const debugHub = DebugHub.getInstance();\r\n\r\n // 使用 install 时保存的 agentId,而非全局 getCurrentAgentId()\r\n const agentId = this._agentId;\r\n const capabilities = debugHub.getCapabilities();\r\n\r\n if (!agentId) {\r\n throw new Error('Agent ID not available. UserInputFeature requires onInitiate() to be called first.');\r\n }\r\n\r\n if (!debugHub.isAgentRegistered(agentId) || !debugHub.isConnected()) {\r\n throw new Error('Interactive input is not attached. Call withViewer() before requesting user input.');\r\n }\r\n\r\n if (!capabilities.interactiveInput) {\r\n throw new Error(\r\n `Interactive input is not available for transport '${capabilities.transportMode}'. Current runtime URL: ${capabilities.runtimeUrl ?? 'n/a'}.`\r\n );\r\n }\r\n\r\n const response = await debugHub.requestUserInputEvent(\r\n agentId,\r\n {\r\n ...request,\r\n initialValue: request.initialValue ?? this.nextDraftInput,\r\n },\r\n timeout ?? this.defaultTimeout\r\n );\r\n this.nextDraftInput = '';\r\n return response;\r\n }\r\n\r\n /**\r\n * 获取用户输入(公开接口,供主循环直接调用)\r\n * @param prompt 提示信息\r\n * @param timeout 超时时间(毫秒)\r\n * @returns 用户输入内容\r\n */\r\n async getUserInput(prompt: string = '请输入:', timeout?: number): Promise<string> {\r\n return this.requestUserInput(prompt, timeout);\r\n }\r\n\r\n async getUserInputEvent(\r\n prompt: string = '请输入:',\r\n timeout?: number,\r\n actions?: UserInputAction[],\r\n ): Promise<UserInputResponse> {\r\n return this.requestUserInputEvent({\r\n prompt,\r\n placeholder: prompt,\r\n actions,\r\n }, timeout);\r\n }\r\n\r\n async requestUserChoices(\r\n prompt: string,\r\n questions: UserInputQuestion[],\r\n timeout?: number,\r\n ): Promise<UserInputChoiceAnswer[]> {\r\n const normalizedQuestions = this.normalizeChoiceQuestions(questions);\r\n const response = await this.requestUserInputEvent({\r\n prompt,\r\n mode: 'choices',\r\n questions: normalizedQuestions,\r\n }, timeout);\r\n\r\n if (response.kind !== 'choices') {\r\n throw new Error(`Expected choice input but received '${response.kind}'`);\r\n }\r\n return response.choices ?? [];\r\n }\r\n\r\n private normalizeChoiceQuestions(questions: UserInputQuestion[]): UserInputQuestion[] {\r\n if (!Array.isArray(questions) || questions.length === 0) {\r\n throw new Error('At least one choice question is required.');\r\n }\r\n\r\n return questions.map((question, index) => {\r\n const id = String(question.id || `question_${index + 1}`).trim();\r\n const text = String(question.question || '').trim();\r\n const options = Array.isArray(question.options) ? question.options : [];\r\n\r\n if (!text) {\r\n throw new Error(`Question ${index + 1} is missing a question prompt.`);\r\n }\r\n if (options.length < 1 || options.length > 4) {\r\n throw new Error(`Question ${index + 1} must provide 1 to 4 options.`);\r\n }\r\n\r\n return {\r\n id,\r\n question: text,\r\n options: options.map((option, optionIndex) => {\r\n const optionId = String(option.id || `option_${optionIndex + 1}`).trim();\r\n const label = String(option.label || '').trim();\r\n if (!label) {\r\n throw new Error(`Question ${index + 1}, option ${optionIndex + 1} is missing a label.`);\r\n }\r\n return {\r\n id: optionId,\r\n label,\r\n description: option.description ? String(option.description) : undefined,\r\n allowSupplement: Boolean(option.allowSupplement),\r\n supplementRequired: Boolean(option.supplementRequired),\r\n supplementLabel: option.supplementLabel ? String(option.supplementLabel) : undefined,\r\n supplementPlaceholder: option.supplementPlaceholder ? String(option.supplementPlaceholder) : undefined,\r\n };\r\n }),\r\n allowCustom: Boolean(question.allowCustom),\r\n customLabel: question.customLabel ? String(question.customLabel) : undefined,\r\n customPlaceholder: question.customPlaceholder ? String(question.customPlaceholder) : undefined,\r\n };\r\n });\r\n }\r\n\r\n getTools(): Tool[] {\r\n return [\r\n createTool({\r\n name: 'ask_user_choice',\r\n description: '向用户展示 1 道或多道选择题,让用户点击或用键盘选择选项;可允许用户选择\"其他\"并输入自定义内容。展示多道时,用户完成一道后直接进入下一道。',\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n prompt: {\r\n type: 'string',\r\n description: '选择卡片的总说明,简要说明为什么需要用户决策。'\r\n },\r\n questions: {\r\n type: 'array',\r\n description: '一组选择题(至少 1 道)。每道题必须有 1~4 个选项。',\r\n minItems: 1,\r\n items: {\r\n type: 'object',\r\n properties: {\r\n id: { type: 'string', description: '稳定问题 ID。' },\r\n question: { type: 'string', description: '问题文本。' },\r\n options: {\r\n type: 'array',\r\n minItems: 1,\r\n maxItems: 4,\r\n items: {\r\n type: 'object',\r\n properties: {\r\n id: { type: 'string', description: '稳定选项 ID。' },\r\n label: { type: 'string', description: '选项显示文本。' },\r\n description: { type: 'string', description: '可选的补充说明。' },\r\n allowSupplement: { type: 'boolean', description: '是否允许用户在选择此选项后补充自由文本。' },\r\n supplementRequired: { type: 'boolean', description: '补充文本是否为必填。' },\r\n supplementLabel: { type: 'string', description: '补充文本输入框的标签。' },\r\n supplementPlaceholder: { type: 'string', description: '补充文本输入框的占位提示。' }\r\n },\r\n required: ['id', 'label']\r\n }\r\n },\r\n allowCustom: { type: 'boolean', description: '是否允许用户输入自定义内容。' },\r\n customLabel: { type: 'string', description: '自定义选项显示文本。' },\r\n customPlaceholder: { type: 'string', description: '自定义输入框占位提示。' }\r\n },\r\n required: ['id', 'question', 'options']\r\n }\r\n }\r\n },\r\n required: ['prompt', 'questions']\r\n },\r\n execute: async (args) => {\r\n const { prompt, questions } = args as { prompt: string; questions: ChoiceToolQuestionInput[] };\r\n const choices = await this.requestUserChoices(prompt, questions);\r\n return { choices };\r\n },\r\n render: choiceToolRender,\r\n }),\r\n ];\r\n }\r\n\r\n async onInitiate(ctx: FeatureInitContext): Promise<void> {\r\n // 保存 agentId,后续 requestUserInputEvent 使用此 ID 而非全局 getCurrentAgentId()\r\n this._agentId = ctx.agentId;\r\n }\r\n\r\n async onDestroy(_ctx: FeatureContext): Promise<void> {\r\n if (this._agentId) {\r\n DebugHub.getInstance().cancelInputRequests(\r\n this._agentId,\r\n `UserInputFeature for Agent '${this._agentId}' was destroyed`,\r\n );\r\n this._agentId = null;\r\n }\r\n }\r\n}\r\n","/**\r\n * FileHistoryFeature - 文件修改历史追踪与回退\r\n *\r\n * 独立 Feature,无侵入地接入 AgentDev 的 checkpoint/rollback 体系:\r\n *\r\n * - ToolUse 反向钩子:在 write/edit 执行前自动备份文件\r\n * - CallStart 反向钩子:在每轮用户输入时创建快照\r\n * - captureState/restoreState:与 Agent 的 CallRollback 集成(仅恢复内存状态)\r\n * - rewindToSnapshot / rewindToLastSnapshot:用户显式触发的文件回退\r\n *\r\n * 文件回退是独立于对话回退的操作(与 Claude Code 的设计一致),\r\n * 用户可以选择\"仅回退代码\"/\"仅回退对话\"/\"两者都回退\"。\r\n *\r\n * 使用方式(消费端,如 Claw):\r\n * const fh = agent.features?.get('file-history');\r\n * if (fh) {\r\n * const snapshots = fh.getSnapshotList();\r\n * await fh.rewindToSnapshot(selectedId);\r\n * }\r\n */\r\n\r\nimport { fileURLToPath } from 'url'\r\nimport { randomUUID } from 'crypto'\r\nimport { Decision } from '../../core/lifecycle.js';\r\nimport type { HookDeclarations } from '../../core/hook-declarations.js';\r\nimport { CoreLifecycle } from '../../core/lifecycle.js';\r\nimport type { AgentFeature, FeatureStateSnapshot, FeatureInitContext, FeatureContext, PackageInfo } from '../../core/feature.js'\r\nimport { getPackageInfoFromSource } from '../../core/feature.js'\r\nimport type { ToolContext } from '../../core/lifecycle.js'\r\nimport type { DecisionResult } from '../../core/lifecycle.js'\r\nimport {\r\n createInitialState,\r\n trackEdit,\r\n makeSnapshot,\r\n rewindToSnapshot as rewindToSnapshotCore,\r\n rewindToLastSnapshot as rewindToLastSnapshotCore,\r\n getDiffStats as getDiffStatsCore,\r\n type FileHistoryState,\r\n type DiffStats,\r\n} from './file-history.js'\r\n\r\nexport interface FileHistoryFeatureConfig {\r\n /** 覆盖工作区目录,默认 process.cwd() */\r\n workspaceDir?: string\r\n}\r\n\r\nexport type SnapshotInfo = {\r\n id: number\r\n timestamp: number\r\n trackedFileCount: number\r\n}\r\n\r\nexport class FileHistoryFeature implements AgentFeature {\r\n\r\n static hooks: HookDeclarations = {\r\n trackFileEdits: { lifecycle: CoreLifecycle.ToolUse, kind: 'guard' as const, role: 'advisor' as const },\r\n onCallStart: { lifecycle: CoreLifecycle.CallStart, kind: 'observe' as const },\r\n };\r\n readonly name = 'file-history'\r\n readonly source = fileURLToPath(import.meta.url).replace(/\\\\/g, '/')\r\n readonly description = '追踪文件修改历史,支持代码回退到任意轮次的状态。'\r\n\r\n private _packageInfo: PackageInfo | null = null\r\n private logger: any\r\n private state: FileHistoryState | null = null\r\n private readonly workspaceDir: string\r\n\r\n constructor(config: FileHistoryFeatureConfig = {}) {\r\n // eslint-disable-next-line no-restricted-syntax -- 防御性默认值,共享进程下返回 Claw 根目录;宿主应显式传 workspaceDir\r\n this.workspaceDir = config.workspaceDir || process.cwd()\r\n }\r\n\r\n getPackageInfo(): PackageInfo | null {\r\n if (!this._packageInfo) {\r\n this._packageInfo = getPackageInfoFromSource(this.source)\r\n }\r\n return this._packageInfo\r\n }\r\n\r\n // ========== 生命周期 ==========\r\n\r\n async onInitiate(ctx: FeatureInitContext): Promise<void> {\r\n this.logger = ctx.logger\r\n const sessionId = randomUUID()\r\n this.state = createInitialState(sessionId, this.workspaceDir)\r\n\r\n this.logger?.info('File history initialized', {\r\n feature: 'file-history',\r\n sessionId,\r\n workspaceDir: this.workspaceDir,\r\n })\r\n }\r\n\r\n async onDestroy(_ctx: FeatureContext): Promise<void> {\r\n this.state = null\r\n }\r\n\r\n // ========== 反向钩子 ==========\r\n\r\n /**\r\n * ToolUse 反向钩子:在 write/edit 工具执行前备份文件\r\n *\r\n * 在所有 Feature 的 ToolUse 钩子中,本钩子只关注 write/edit 两个工具,\r\n * 其余一律放行 (Decision.Continue)。\r\n */\r\n async trackFileEdits(ctx: ToolContext): Promise<DecisionResult> {\r\n if (!this.state) return Decision.Continue\r\n\r\n const toolName = ctx.call.name\r\n if (toolName !== 'write' && toolName !== 'edit') {\r\n return Decision.Continue\r\n }\r\n\r\n const filePath = ctx.call.arguments?.filePath as string\r\n if (!filePath) return Decision.Continue\r\n\r\n try {\r\n this.state = await trackEdit(this.state, filePath)\r\n } catch (error) {\r\n // 备份失败不应阻止工具执行,记录日志后放行\r\n this.logger?.error('File history track failed', {\r\n filePath,\r\n toolName,\r\n error: error instanceof Error ? error.message : String(error),\r\n feature: 'file-history',\r\n })\r\n }\r\n\r\n return Decision.Continue\r\n }\r\n\r\n /**\r\n * CallStart 反向钩子:每轮用户输入时创建文件快照\r\n *\r\n * 第一次 CallStart 创建空快照,后续 CallStart 检测已追踪文件是否有变化,\r\n * 有变化的创建新版本备份。\r\n */\r\n async onCallStart(_ctx: any): Promise<void> {\r\n if (!this.state) return\r\n\r\n try {\r\n this.state = await makeSnapshot(this.state)\r\n } catch (error) {\r\n this.logger?.error('File history snapshot failed', {\r\n error: error instanceof Error ? error.message : String(error),\r\n feature: 'file-history',\r\n })\r\n }\r\n }\r\n\r\n // ========== Checkpoint 集成 ==========\r\n\r\n /**\r\n * 捕获当前文件历史状态(纯内存,不碰磁盘)\r\n *\r\n * 由 Agent 的 commitCallCheckpoint 调用。\r\n * 保存快照元数据,使得 rollbackToCall 时能恢复到对应的文件历史状态。\r\n */\r\n captureState(): FeatureStateSnapshot {\r\n if (!this.state) return null\r\n // 只保存可序列化的元数据,不保存文件内容\r\n return {\r\n snapshots: this.state.snapshots,\r\n trackedFiles: this.state.trackedFiles,\r\n snapshotCounter: this.state.snapshotCounter,\r\n sessionId: this.state.sessionId,\r\n workspaceDir: this.state.workspaceDir,\r\n }\r\n }\r\n\r\n /**\r\n * 恢复文件历史状态(仅恢复内存,不恢复磁盘文件)\r\n *\r\n * 在三种场景下被调用:step rollback、call rollback、session load。\r\n * 这里只恢复内存中的快照索引,不做文件回退。\r\n * 文件回退由用户显式调用 rewindToSnapshot / rewindToLastSnapshot 触发。\r\n */\r\n restoreState(snapshot: FeatureStateSnapshot): void {\r\n const prevState = snapshot as FileHistoryState | null\r\n if (!prevState || !prevState.snapshots) return\r\n\r\n this.state = {\r\n snapshots: prevState.snapshots,\r\n trackedFiles: prevState.trackedFiles ?? [],\r\n snapshotCounter: prevState.snapshotCounter ?? prevState.snapshots.length,\r\n sessionId: prevState.sessionId,\r\n workspaceDir: prevState.workspaceDir ?? this.workspaceDir,\r\n }\r\n }\r\n\r\n // ========== 公开 API(供消费端调用) ==========\r\n\r\n /**\r\n * 获取快照列表(供 UI 展示)\r\n */\r\n getSnapshotList(): SnapshotInfo[] {\r\n if (!this.state) return []\r\n return this.state.snapshots.map(s => ({\r\n id: s.id,\r\n timestamp: s.timestamp,\r\n trackedFileCount: Object.keys(s.trackedFileBackups).length,\r\n }))\r\n }\r\n\r\n /**\r\n * 获取当前追踪的文件数量\r\n */\r\n getTrackedFileCount(): number {\r\n return this.state?.trackedFiles.length ?? 0\r\n }\r\n\r\n /**\r\n * 获取快照数量\r\n */\r\n getSnapshotCount(): number {\r\n return this.state?.snapshots.length ?? 0\r\n }\r\n\r\n /**\r\n * 回退文件到指定快照\r\n *\r\n * @returns 被修改的文件路径列表\r\n */\r\n async rewindToSnapshot(snapshotId: number): Promise<string[]> {\r\n if (!this.state) throw new Error('File history not initialized')\r\n const changed = await rewindToSnapshotCore(this.state, snapshotId)\r\n this.logger?.info('Files rewound to snapshot', {\r\n snapshotId,\r\n changedFilesCount: changed.length,\r\n changedFiles: changed,\r\n feature: 'file-history',\r\n })\r\n return changed\r\n }\r\n\r\n /**\r\n * 回退文件到当前内存状态的最后一个快照\r\n *\r\n * 典型用法:先 rollbackToCall 恢复对话 + 内存状态,再调此方法恢复文件。\r\n * await agent.rollbackToCall(targetCallIndex)\r\n * const fh = agent.features?.get('file-history')\r\n * await fh?.rewindToLastSnapshot()\r\n */\r\n async rewindToLastSnapshot(): Promise<string[]> {\r\n if (!this.state) throw new Error('File history not initialized')\r\n const changed = await rewindToLastSnapshotCore(this.state)\r\n this.logger?.info('Files rewound to last snapshot', {\r\n changedFilesCount: changed.length,\r\n changedFiles: changed,\r\n feature: 'file-history',\r\n })\r\n return changed\r\n }\r\n\r\n /**\r\n * 计算回退到指定快照的 diff 统计(预览用,不修改文件)\r\n */\r\n async getDiffStats(snapshotId: number): Promise<DiffStats> {\r\n if (!this.state) return { filesChanged: [], insertions: 0, deletions: 0 }\r\n return getDiffStatsCore(this.state, snapshotId)\r\n }\r\n}\r\n","/**\r\n * 文件历史核心逻辑\r\n *\r\n * 改写自 Claude Code 的 fileHistory.ts,去掉 React 状态管理、遥测、VSCode 通知等,\r\n * 保留纯粹的备份/快照/回退能力。\r\n *\r\n * 设计要点:\r\n * - 备份文件以 {sha256(path)[:16]}@v{N} 命名,存放在 ~/.agentdev/file-history/{sessionId}/\r\n * - 快照绑定一个递增 ID,记录当时所有被追踪文件的备份版本\r\n * - 快照上限 100,超过自动淘汰最早的\r\n * - 变更检测走三层快速路径:stat → size → mtime → content\r\n */\r\n\r\nimport { createHash } from 'crypto'\r\nimport {\r\n chmod,\r\n copyFile,\r\n mkdir,\r\n readFile,\r\n stat,\r\n unlink,\r\n} from 'fs/promises'\r\nimport { dirname, isAbsolute, join, relative } from 'path'\r\nimport { homedir } from 'os'\r\nimport type { Stats } from 'fs'\r\n\r\n// ========== 类型 ==========\r\n\r\ntype BackupFileName = string | null // null = 该版本文件不存在\r\n\r\nexport interface FileHistoryBackup {\r\n backupFileName: BackupFileName\r\n version: number\r\n}\r\n\r\nexport interface FileHistorySnapshot {\r\n id: number\r\n trackedFileBackups: Record<string, FileHistoryBackup>\r\n timestamp: number\r\n}\r\n\r\nexport interface FileHistoryState {\r\n snapshots: FileHistorySnapshot[]\r\n trackedFiles: string[]\r\n snapshotCounter: number\r\n sessionId: string\r\n workspaceDir: string\r\n}\r\n\r\nexport interface DiffStats {\r\n filesChanged: string[]\r\n insertions: number\r\n deletions: number\r\n}\r\n\r\nconst MAX_SNAPSHOTS = 100\r\n\r\n// ========== 路径工具 ==========\r\n\r\nexport function getBackupDir(sessionId: string): string {\r\n return join(homedir(), '.agentdev', 'file-history', sessionId)\r\n}\r\n\r\nfunction getBackupFileName(filePath: string, version: number): string {\r\n const hash = createHash('sha256')\r\n .update(filePath)\r\n .digest('hex')\r\n .slice(0, 16)\r\n return `${hash}@v${version}`\r\n}\r\n\r\nfunction resolveBackupPath(backupFileName: string, sessionId: string): string {\r\n return join(getBackupDir(sessionId), backupFileName)\r\n}\r\n\r\nfunction toTrackingPath(filePath: string, workspaceDir: string): string {\r\n if (!isAbsolute(filePath)) return filePath\r\n if (filePath.startsWith(workspaceDir)) {\r\n return relative(workspaceDir, filePath)\r\n }\r\n return filePath\r\n}\r\n\r\nfunction toAbsolutePath(trackingPath: string, workspaceDir: string): string {\r\n if (isAbsolute(trackingPath)) return trackingPath\r\n return join(workspaceDir, trackingPath)\r\n}\r\n\r\n// ========== 备份操作 ==========\r\n\r\nasync function createBackup(\r\n filePath: string,\r\n version: number,\r\n sessionId: string,\r\n): Promise<FileHistoryBackup> {\r\n const backupFileName = getBackupFileName(filePath, version)\r\n const backupPath = resolveBackupPath(backupFileName, sessionId)\r\n\r\n // 源文件不存在 → 记录 null 标记\r\n let srcStats: Stats\r\n try {\r\n srcStats = await stat(filePath)\r\n } catch (e: any) {\r\n if (e.code === 'ENOENT') {\r\n return { backupFileName: null, version }\r\n }\r\n throw e\r\n }\r\n\r\n // copyFile 不经过 JS 堆,大文件安全\r\n try {\r\n await copyFile(filePath, backupPath)\r\n } catch (e: any) {\r\n if (e.code === 'ENOENT') {\r\n await mkdir(dirname(backupPath), { recursive: true })\r\n await copyFile(filePath, backupPath)\r\n } else {\r\n throw e\r\n }\r\n }\r\n\r\n await chmod(backupPath, srcStats.mode)\r\n return { backupFileName, version }\r\n}\r\n\r\n/**\r\n * 三层快速路径:stat → size/mode → mtime → content\r\n * 来自 Claude Code 的 checkOriginFileChanged\r\n */\r\nasync function fileHasChanged(\r\n originalFile: string,\r\n backupFileName: string,\r\n sessionId: string,\r\n): Promise<boolean> {\r\n const backupPath = resolveBackupPath(backupFileName, sessionId)\r\n\r\n let origStats: Stats | null = null\r\n try { origStats = await stat(originalFile) } catch {}\r\n\r\n let bakStats: Stats | null = null\r\n try { bakStats = await stat(backupPath) } catch {}\r\n\r\n // 一个存在一个不存在 → 变了\r\n if ((origStats === null) !== (bakStats === null)) return true\r\n // 都不存在 → 没变\r\n if (!origStats || !bakStats) return false\r\n\r\n // size 或 mode 不同 → 变了\r\n if (origStats.size !== bakStats.size || origStats.mode !== bakStats.mode) {\r\n return true\r\n }\r\n\r\n // mtime 快速路径:原文件比备份旧 → 没变(跳过内容比较)\r\n if (origStats.mtimeMs < bakStats.mtimeMs) return false\r\n\r\n // 兜底:读内容比较\r\n try {\r\n const [orig, bak] = await Promise.all([\r\n readFile(originalFile, 'utf-8'),\r\n readFile(backupPath, 'utf-8'),\r\n ])\r\n return orig !== bak\r\n } catch {\r\n return true\r\n }\r\n}\r\n\r\nasync function restoreFile(\r\n filePath: string,\r\n backupFileName: string,\r\n sessionId: string,\r\n): Promise<void> {\r\n const backupPath = resolveBackupPath(backupFileName, sessionId)\r\n try {\r\n await copyFile(backupPath, filePath)\r\n } catch (e: any) {\r\n if (e.code === 'ENOENT') {\r\n await mkdir(dirname(filePath), { recursive: true })\r\n await copyFile(backupPath, filePath)\r\n } else {\r\n throw e\r\n }\r\n }\r\n}\r\n\r\n// ========== 状态初始化 ==========\r\n\r\nexport function createInitialState(\r\n sessionId: string,\r\n workspaceDir: string,\r\n): FileHistoryState {\r\n return {\r\n snapshots: [],\r\n trackedFiles: [],\r\n snapshotCounter: 0,\r\n sessionId,\r\n workspaceDir,\r\n }\r\n}\r\n\r\n// ========== 核心操作 ==========\r\n\r\n/**\r\n * 追踪文件编辑 —— 在 write/edit 工具执行前调用\r\n *\r\n * 只在当前最新快照中还没有该文件备份时才创建 v1 备份。\r\n * 同一快照内多次调用(如同一轮内编辑同一文件两次)会跳过,保留首次编辑前的状态。\r\n */\r\nexport async function trackEdit(\r\n state: FileHistoryState,\r\n filePath: string,\r\n): Promise<FileHistoryState> {\r\n const trackingPath = toTrackingPath(filePath, state.workspaceDir)\r\n const latestSnapshot = state.snapshots[state.snapshots.length - 1]\r\n\r\n if (!latestSnapshot) return state\r\n\r\n // 已在当前快照中追踪过 → 跳过(保持 pre-edit 的 v1 备份不被覆盖)\r\n if (latestSnapshot.trackedFileBackups[trackingPath]) {\r\n return state\r\n }\r\n\r\n const absolutePath = toAbsolutePath(trackingPath, state.workspaceDir)\r\n const backup = await createBackup(absolutePath, 1, state.sessionId)\r\n\r\n const newTrackedFiles = state.trackedFiles.includes(trackingPath)\r\n ? state.trackedFiles\r\n : [...state.trackedFiles, trackingPath]\r\n\r\n // 更新最新快照,添加该文件的备份\r\n return {\r\n ...state,\r\n trackedFiles: newTrackedFiles,\r\n snapshots: state.snapshots.map((s, i) =>\r\n i === state.snapshots.length - 1\r\n ? {\r\n ...s,\r\n trackedFileBackups: {\r\n ...s.trackedFileBackups,\r\n [trackingPath]: backup,\r\n },\r\n }\r\n : s\r\n ),\r\n }\r\n}\r\n\r\n/**\r\n * 创建快照 —— 在每轮 Call 开始时调用\r\n *\r\n * 遍历所有已追踪文件,有变化的创建新版本备份,没变化的复用上一版本引用。\r\n */\r\nexport async function makeSnapshot(\r\n state: FileHistoryState,\r\n): Promise<FileHistoryState> {\r\n const latestSnapshot = state.snapshots[state.snapshots.length - 1]\r\n const newBackups: Record<string, FileHistoryBackup> = {}\r\n\r\n if (latestSnapshot) {\r\n await Promise.all(\r\n state.trackedFiles.map(async (trackingPath) => {\r\n const absolutePath = toAbsolutePath(trackingPath, state.workspaceDir)\r\n const lastBackup = latestSnapshot.trackedFileBackups[trackingPath]\r\n const nextVersion = lastBackup ? lastBackup.version + 1 : 1\r\n\r\n try {\r\n await stat(absolutePath)\r\n } catch (e: any) {\r\n if (e.code === 'ENOENT') {\r\n // 文件被删了\r\n newBackups[trackingPath] = { backupFileName: null, version: nextVersion }\r\n return\r\n }\r\n throw e\r\n }\r\n\r\n // 文件存在,检查是否有变化\r\n if (\r\n lastBackup &&\r\n lastBackup.backupFileName !== null &&\r\n !(await fileHasChanged(absolutePath, lastBackup.backupFileName, state.sessionId))\r\n ) {\r\n // 未变化,复用上一版本\r\n newBackups[trackingPath] = lastBackup\r\n return\r\n }\r\n\r\n // 有变化,创建新版本备份\r\n newBackups[trackingPath] = await createBackup(\r\n absolutePath,\r\n nextVersion,\r\n state.sessionId,\r\n )\r\n }),\r\n )\r\n }\r\n\r\n // 继承上一快照中未被新快照覆盖的备份\r\n if (latestSnapshot) {\r\n for (const path of state.trackedFiles) {\r\n if (!(path in newBackups) && latestSnapshot.trackedFileBackups[path]) {\r\n newBackups[path] = latestSnapshot.trackedFileBackups[path]\r\n }\r\n }\r\n }\r\n\r\n const newSnapshot: FileHistorySnapshot = {\r\n id: state.snapshotCounter,\r\n trackedFileBackups: newBackups,\r\n timestamp: Date.now(),\r\n }\r\n\r\n const allSnapshots = [...state.snapshots, newSnapshot]\r\n\r\n return {\r\n ...state,\r\n snapshots:\r\n allSnapshots.length > MAX_SNAPSHOTS\r\n ? allSnapshots.slice(-MAX_SNAPSHOTS)\r\n : allSnapshots,\r\n snapshotCounter: state.snapshotCounter + 1,\r\n }\r\n}\r\n\r\n/**\r\n * 回退文件到指定快照\r\n *\r\n * 遍历所有已追踪文件,将其恢复到目标快照记录的版本。\r\n * 返回被修改的文件路径列表。\r\n */\r\nexport async function rewindToSnapshot(\r\n state: FileHistoryState,\r\n snapshotId: number,\r\n): Promise<string[]> {\r\n const targetSnapshot = [...state.snapshots].reverse().find(s => s.id === snapshotId)\r\n if (!targetSnapshot) {\r\n throw new Error(`Snapshot ${snapshotId} not found`)\r\n }\r\n\r\n return applySnapshot(state, targetSnapshot)\r\n}\r\n\r\n/**\r\n * 回退到给定状态的最后一个快照(rollbackToCall 后调用)\r\n */\r\nexport async function rewindToLastSnapshot(\r\n state: FileHistoryState,\r\n): Promise<string[]> {\r\n const lastSnapshot = state.snapshots[state.snapshots.length - 1]\r\n if (!lastSnapshot) return []\r\n return applySnapshot(state, lastSnapshot)\r\n}\r\n\r\n/**\r\n * 计算回退到指定快照的 diff 统计(不实际修改文件)\r\n */\r\nexport async function getDiffStats(\r\n state: FileHistoryState,\r\n snapshotId: number,\r\n): Promise<DiffStats> {\r\n const targetSnapshot = [...state.snapshots].reverse().find(s => s.id === snapshotId)\r\n if (!targetSnapshot) {\r\n return { filesChanged: [], insertions: 0, deletions: 0 }\r\n }\r\n\r\n // 动态导入 diffLines 避免硬依赖\r\n const { diffLines } = await import('diff')\r\n\r\n const filesChanged: string[] = []\r\n let insertions = 0\r\n let deletions = 0\r\n\r\n for (const trackingPath of state.trackedFiles) {\r\n const absolutePath = toAbsolutePath(trackingPath, state.workspaceDir)\r\n const targetBackup = targetSnapshot.trackedFileBackups[trackingPath]\r\n\r\n const backupFileName: BackupFileName | undefined = targetBackup\r\n ? targetBackup.backupFileName\r\n : getBackupFileNameFirstVersion(trackingPath, state)\r\n\r\n if (backupFileName === undefined) continue\r\n\r\n try {\r\n let currentContent: string | null = null\r\n let snapshotContent: string | null = null\r\n\r\n try {\r\n currentContent = await readFile(absolutePath, 'utf-8')\r\n } catch {}\r\n\r\n if (backupFileName !== null) {\r\n const backupPath = resolveBackupPath(backupFileName, state.sessionId)\r\n try {\r\n snapshotContent = await readFile(backupPath, 'utf-8')\r\n } catch {}\r\n }\r\n\r\n const changes = diffLines(currentContent ?? '', snapshotContent ?? '')\r\n let hasChanges = false\r\n for (const c of changes) {\r\n if (c.added) { insertions += c.count || 0; hasChanges = true }\r\n if (c.removed) { deletions += c.count || 0; hasChanges = true }\r\n }\r\n if (hasChanges) filesChanged.push(absolutePath)\r\n } catch {\r\n // 跳过无法比较的文件\r\n }\r\n }\r\n\r\n return { filesChanged, insertions, deletions }\r\n}\r\n\r\n// ========== 内部工具 ==========\r\n\r\nasync function applySnapshot(\r\n state: FileHistoryState,\r\n targetSnapshot: FileHistorySnapshot,\r\n): Promise<string[]> {\r\n const changedFiles: string[] = []\r\n\r\n for (const trackingPath of state.trackedFiles) {\r\n const absolutePath = toAbsolutePath(trackingPath, state.workspaceDir)\r\n const targetBackup = targetSnapshot.trackedFileBackups[trackingPath]\r\n\r\n const backupFileName: BackupFileName | undefined = targetBackup\r\n ? targetBackup.backupFileName\r\n : getBackupFileNameFirstVersion(trackingPath, state)\r\n\r\n if (backupFileName === undefined) continue\r\n\r\n if (backupFileName === null) {\r\n // 目标版本文件不存在,删除当前文件\r\n try {\r\n await unlink(absolutePath)\r\n changedFiles.push(absolutePath)\r\n } catch (e: any) {\r\n if (e.code !== 'ENOENT') throw e\r\n }\r\n continue\r\n }\r\n\r\n // 仅当文件确实变了才恢复\r\n if (await fileHasChanged(absolutePath, backupFileName, state.sessionId)) {\r\n await restoreFile(absolutePath, backupFileName, state.sessionId)\r\n changedFiles.push(absolutePath)\r\n }\r\n }\r\n\r\n return changedFiles\r\n}\r\n\r\n/**\r\n * 查找文件最早的 v1 备份(用于回退到快照中未追踪的文件)\r\n */\r\nfunction getBackupFileNameFirstVersion(\r\n trackingPath: string,\r\n state: FileHistoryState,\r\n): BackupFileName | undefined {\r\n for (const s of state.snapshots) {\r\n const backup = s.trackedFileBackups[trackingPath]\r\n if (backup !== undefined && backup.version === 1) {\r\n return backup.backupFileName\r\n }\r\n }\r\n return undefined\r\n}\r\n","/**\r\n * Handoff-Seed Feature(ticket 006 自 Claw context-handoff-seed 下沉为框架标准 feature)。\r\n *\r\n * 当 runtime 从一次会话接续包启动时,在首个 CallStart 精确注入一次裁剪后的\r\n * handoff 转录(seed messages),并推进 `_callIndex` 避免轮次冲突。\r\n *\r\n * 随迁已解决的关键实现:\r\n * - typed Context API 注入(messages[] / enrichedMessages[] 同步)\r\n * - seed turn 对齐与 `_callIndex` 推进\r\n * - serialized tool message 重放(保留图片附件,不丢字段)\r\n *\r\n * env 传递约定(如 handoff 文件路径)留宿主,框架只提供 feature 类。\r\n */\r\n\r\nimport { fileURLToPath } from 'url';\r\nimport { existsSync, readFileSync } from 'fs';\r\nimport { join, resolve, normalize } from 'path';\r\nimport type {\r\n AgentFeature,\r\n FeatureContext,\r\n FeatureInitContext,\r\n FeatureStateSnapshot,\r\n} from '../../core/feature.js';\r\nimport type { HookDeclarations } from '../../core/hook-declarations.js';\r\nimport { CoreLifecycle } from '../../core/lifecycle.js';\r\nimport type { CallStartContext } from '../../core/lifecycle.js';\r\nimport type {\r\n HandoffSeedFeatureConfig,\r\n HandoffSeedPayload,\r\n HandoffSeedMessage,\r\n HandoffSeedSnapshot,\r\n} from './types.js';\r\n\r\nconst __filename = fileURLToPath(import.meta.url);\r\n\r\nconst MAX_FILE_CHARS = 8000;\r\nconst MAX_TOTAL_FILE_CHARS = 30000;\r\nconst MAX_SKILL_CHARS = 5000;\r\nconst MAX_TOTAL_SKILL_CHARS = 15000;\r\n\r\nfunction cleanValue(value: unknown): string {\r\n return typeof value === 'string' ? value.trim() : '';\r\n}\r\n\r\nfunction buildTrimContextLabel(handoff: HandoffSeedPayload): string {\r\n const lines = [\r\n '## 会话续接元信息',\r\n '',\r\n '当前会话是从更早的对话裁剪续接而来。上方已注入裁剪后的完整对话历史。',\r\n '以下仅为该会话的任务元信息,不需要重新执行这些任务。',\r\n ];\r\n const sourceSessionId = cleanValue(handoff.sourceSessionId);\r\n if (sourceSessionId) {\r\n lines.push('', `来源会话:${sourceSessionId}`);\r\n }\r\n const sourceSummary = cleanValue(handoff.sourceSummary);\r\n if (sourceSummary) {\r\n lines.push('', sourceSummary);\r\n }\r\n return lines.join('\\n');\r\n}\r\n\r\nfunction buildSummarySeedMessage(handoff: HandoffSeedPayload): string {\r\n const lines = [\r\n '## 上下文交接摘要',\r\n '',\r\n '以下压缩上下文来自更早的一次会话导出,用于让当前运行时继续同一个任务。',\r\n ];\r\n const sourceSessionId = cleanValue(handoff.sourceSessionId);\r\n if (sourceSessionId) {\r\n lines.push('', `来源会话:${sourceSessionId}`);\r\n }\r\n const sourceSummary = cleanValue(handoff.sourceSummary);\r\n if (sourceSummary) {\r\n lines.push('', sourceSummary);\r\n }\r\n return lines.join('\\n');\r\n}\r\n\r\n/**\r\n * Inject a single seed message into Context via the typed API that keeps\r\n * both messages[] and enrichedMessages[] in sync.\r\n *\r\n * tool messages use addSerializedToolMessage() because their content is already\r\n * serialized in the handoff package and must be replayed without lossy parsing.\r\n */\r\nfunction injectSeedMessage(\r\n context: CallStartContext['context'],\r\n message: HandoffSeedMessage,\r\n turn: number,\r\n): void {\r\n const content = typeof message.content === 'string' ? message.content : '';\r\n const role = message.role;\r\n const tag = typeof message.tag === 'string' ? message.tag : undefined;\r\n\r\n if (role === 'system') {\r\n context.addSystemMessage(content, turn, 'handoff-seed', tag);\r\n } else if (role === 'user') {\r\n context.addUserMessage(content, turn, message.images as any);\r\n } else if (role === 'assistant') {\r\n context.addAssistantMessage(\r\n {\r\n content,\r\n toolCalls: message.toolCalls as any,\r\n reasoning: message.reasoning as any,\r\n thinkingBlocks: message.thinkingBlocks as any,\r\n },\r\n turn,\r\n );\r\n } else if (role === 'tool' && message.toolCallId) {\r\n context.addSerializedToolMessage(message.toolCallId, content, turn, message.images as any);\r\n } else {\r\n context.add({ role, content, turn, toolCallId: message.toolCallId, images: message.images, ...(tag ? { tag } : {}) } as any);\r\n }\r\n}\r\n\r\nexport class HandoffSeedFeature implements AgentFeature {\r\n\r\n static hooks: HookDeclarations = {\r\n injectHandoffSummary: { lifecycle: CoreLifecycle.CallStart, kind: 'observe' as const },\r\n };\r\n readonly name = 'handoff-seed';\r\n readonly dependencies: string[] = [];\r\n readonly source = __filename.replace(/\\\\/g, '/');\r\n readonly description = 'Injects a trimmed handoff transcript exactly once on the first CallStart when a runtime is booted from a handoff package.';\r\n\r\n private readonly handoff: HandoffSeedPayload;\r\n private injected = false;\r\n private logger?: FeatureInitContext['logger'];\r\n\r\n constructor(config: HandoffSeedFeatureConfig) {\r\n const rawSeedMessages = Array.isArray(config?.handoff?.seedMessages)\r\n ? config.handoff.seedMessages\r\n : [];\r\n this.handoff = {\r\n packageId: cleanValue(config?.handoff?.packageId),\r\n sourceSessionId: cleanValue(config?.handoff?.sourceSessionId),\r\n sourceSummary: cleanValue(config?.handoff?.sourceSummary),\r\n mode: cleanValue(config?.handoff?.mode),\r\n seedMessages: rawSeedMessages as any,\r\n importantFiles: Array.isArray(config?.handoff?.importantFiles)\r\n ? config.handoff.importantFiles.filter(f => typeof f === 'string')\r\n : [],\r\n importantSkills: Array.isArray(config?.handoff?.importantSkills)\r\n ? config.handoff.importantSkills.filter(s => typeof s === 'string')\r\n : [],\r\n fileRanges: typeof config?.handoff?.fileRanges === 'object' && config.handoff.fileRanges !== null\r\n ? config.handoff.fileRanges\r\n : {},\r\n featureContinuity: config?.handoff?.featureContinuity,\r\n };\r\n }\r\n\r\n async onInitiate(ctx: FeatureInitContext): Promise<void> {\r\n this.logger = ctx.logger;\r\n this.logger?.info('Handoff seed feature initiated', {\r\n packageId: this.handoff.packageId || null,\r\n sourceSessionId: this.handoff.sourceSessionId || null,\r\n mode: this.handoff.mode || null,\r\n seedMessageCount: this.handoff.seedMessages?.length || 0,\r\n hasSourceSummary: Boolean(this.handoff.sourceSummary),\r\n });\r\n }\r\n\r\n async onDestroy(_ctx: FeatureContext): Promise<void> {\r\n this.logger?.info('Handoff seed feature destroyed', {\r\n injected: this.injected,\r\n });\r\n }\r\n\r\n captureState(): FeatureStateSnapshot {\r\n const snapshot: HandoffSeedSnapshot = {\r\n injected: this.injected,\r\n };\r\n return snapshot;\r\n }\r\n\r\n restoreState(snapshot: FeatureStateSnapshot): void {\r\n const state = snapshot as HandoffSeedSnapshot | null | undefined;\r\n this.injected = Boolean(state?.injected);\r\n }\r\n\r\n async injectHandoffSummary(ctx: CallStartContext): Promise<void> {\r\n if (this.injected || !ctx.isFirstCall) {\r\n return;\r\n }\r\n\r\n const fallbackTurn = typeof (ctx.agent as any)?._callIndex === 'number' ? (ctx.agent as any)._callIndex : 0;\r\n const seedMessages: HandoffSeedMessage[] = Array.isArray(this.handoff.seedMessages) ? this.handoff.seedMessages : [];\r\n\r\n let injectionTurn = fallbackTurn;\r\n\r\n if (seedMessages.length > 0) {\r\n seedMessages.forEach((message, index) => {\r\n const turn = typeof message?.turn === 'number' && Number.isFinite(message.turn)\r\n ? Number(message.turn)\r\n : (fallbackTurn + index);\r\n injectionTurn = Math.max(injectionTurn, turn + 1);\r\n injectSeedMessage(ctx.context, message, turn);\r\n });\r\n\r\n const agentRef = ctx.agent as any;\r\n if (typeof agentRef?._callIndex === 'number' && injectionTurn > agentRef._callIndex) {\r\n agentRef._callIndex = injectionTurn;\r\n }\r\n }\r\n\r\n if (this.handoff.sourceSummary && seedMessages.length === 0) {\r\n const isTrim = cleanValue(this.handoff.mode).startsWith('trim');\r\n const label = isTrim\r\n ? buildTrimContextLabel(this.handoff)\r\n : buildSummarySeedMessage(this.handoff);\r\n ctx.context.addSystemMessage(label, injectionTurn, this.name);\r\n }\r\n\r\n if (seedMessages.length === 0 && !this.handoff.sourceSummary) {\r\n return;\r\n }\r\n\r\n this.injected = true;\r\n this.logger?.info('Injected handoff seed', {\r\n packageId: this.handoff.packageId || null,\r\n sourceSessionId: this.handoff.sourceSessionId || null,\r\n seedMessageCount: seedMessages.length,\r\n turn: fallbackTurn,\r\n });\r\n\r\n this.injectImportantContext(ctx, injectionTurn);\r\n }\r\n\r\n private injectImportantContext(ctx: CallStartContext, baseTurn: number): void {\r\n const projectRoot = typeof (ctx.agent as any)?.projectRoot === 'string'\r\n ? (ctx.agent as any).projectRoot\r\n // eslint-disable-next-line no-restricted-syntax -- 防御性默认值,共享进程下返回 Claw 根目录;Agent 已注册 projectRoot 时不会走到这里\r\n : process.cwd();\r\n\r\n let injectionTurn = baseTurn + 1;\r\n\r\n const fileBlocks = this.buildFileBlocks(projectRoot);\r\n for (const block of fileBlocks) {\r\n ctx.context.addSystemMessage(block, injectionTurn, this.name);\r\n injectionTurn += 1;\r\n }\r\n\r\n const skillBlocks = this.buildSkillBlocks(projectRoot);\r\n for (const block of skillBlocks) {\r\n ctx.context.addSystemMessage(block, injectionTurn, this.name);\r\n injectionTurn += 1;\r\n }\r\n }\r\n\r\n private resolveFilePath(filePath: string, projectRoot: string): string {\r\n if (existsSync(filePath)) return filePath;\r\n const resolved = resolve(projectRoot, filePath);\r\n if (existsSync(resolved)) return resolved;\r\n return filePath;\r\n }\r\n\r\n private buildFileBlocks(projectRoot: string): string[] {\r\n const files = this.handoff.importantFiles || [];\r\n if (files.length === 0) return [];\r\n\r\n const ranges = this.handoff.fileRanges || {};\r\n const blocks: string[] = [];\r\n const nameOnlyList: string[] = [];\r\n let totalChars = 0;\r\n\r\n for (const filePath of files) {\r\n const resolved = this.resolveFilePath(filePath, projectRoot);\r\n const content = this.tryReadFile(resolved);\r\n const range = ranges[filePath];\r\n const rangeLabel = range ? `(上次阅读行 ${range})` : '';\r\n\r\n if (content === null) {\r\n nameOnlyList.push(`${filePath} ${rangeLabel}(文件未找到)`);\r\n continue;\r\n }\r\n const budget = Math.max(0, MAX_TOTAL_FILE_CHARS - totalChars);\r\n if (content.length <= budget && content.length <= MAX_FILE_CHARS) {\r\n blocks.push([\r\n `以下文件在此会话的前一轮中被标记为重要,内容已重新加载(行号为参考值,文件可能已变更):`,\r\n '',\r\n `### ${filePath} ${rangeLabel}`,\r\n content,\r\n ].join('\\n'));\r\n totalChars += content.length;\r\n } else {\r\n nameOnlyList.push(`${filePath} ${rangeLabel}`);\r\n }\r\n }\r\n\r\n if (nameOnlyList.length > 0) {\r\n const nameBlockLines = [\r\n '以下文件在此会话的前一轮中被标记为重要,但因超出显示上限或文件未找到仅保留路径(行号为参考值,文件可能已变更):',\r\n '',\r\n ];\r\n for (const p of nameOnlyList) nameBlockLines.push(`- ${p}`);\r\n blocks.push(nameBlockLines.join('\\n'));\r\n }\r\n\r\n return blocks;\r\n }\r\n\r\n private buildSkillBlocks(projectRoot: string): string[] {\r\n const skills = this.handoff.importantSkills || [];\r\n if (skills.length === 0) return [];\r\n\r\n const blocks: string[] = [];\r\n const nameOnlyList: string[] = [];\r\n let totalChars = 0;\r\n\r\n for (const skillName of skills) {\r\n const skillDir = join(projectRoot, '.agentdev', 'skills', skillName);\r\n const skillMdPath = join(skillDir, 'SKILL.md');\r\n const content = this.tryReadFile(skillMdPath);\r\n const basePath = normalize(skillDir);\r\n\r\n if (content === null) {\r\n nameOnlyList.push(`${skillName}(技能定义未找到,目录:${basePath})`);\r\n continue;\r\n }\r\n\r\n const parsed = this.parseSkillMd(content);\r\n const header = [\r\n `**技能名称**:${parsed.name || skillName}`,\r\n parsed.description ? `**技能描述**:${parsed.description}` : '',\r\n `**技能的基础目录路径**:\\`${basePath}\\``,\r\n '',\r\n '---',\r\n '',\r\n parsed.body,\r\n ].filter(Boolean).join('\\n');\r\n\r\n const budget = Math.max(0, MAX_TOTAL_SKILL_CHARS - totalChars);\r\n const truncated = header.length > MAX_SKILL_CHARS\r\n ? header.slice(0, MAX_SKILL_CHARS) + '\\n(已截断)'\r\n : header;\r\n if (truncated.length <= budget) {\r\n blocks.push([\r\n '以下技能在此会话的前一轮中被标记为重要:',\r\n '',\r\n `### 技能: ${skillName}`,\r\n truncated,\r\n ].join('\\n'));\r\n totalChars += truncated.length;\r\n } else {\r\n nameOnlyList.push(`${skillName}(目录:${basePath})`);\r\n }\r\n }\r\n\r\n if (nameOnlyList.length > 0) {\r\n const nameBlockLines = [\r\n '以下技能在此会话的前一轮中被标记为重要,但因超出显示上限或定义未找到仅保留名称:',\r\n '',\r\n ];\r\n for (const s of nameOnlyList) nameBlockLines.push(`- ${s}`);\r\n blocks.push(nameBlockLines.join('\\n'));\r\n }\r\n\r\n return blocks;\r\n }\r\n\r\n private parseSkillMd(content: string): { name: string; description: string; body: string } {\r\n const result = { name: '', description: '', body: content };\r\n const frontmatterMatch = content.match(/^---\\s*\\n([\\s\\S]*?)\\n---/);\r\n if (!frontmatterMatch) return result;\r\n const yaml = frontmatterMatch[1];\r\n const nameMatch = yaml.match(/^name:\\s*[\"']?(.+?)[\"']?\\s*$/m);\r\n if (nameMatch) result.name = nameMatch[1].trim();\r\n const descMatch = yaml.match(/^description:\\s*[\"'](.+?)[\"']\\s*$/m);\r\n if (descMatch) result.description = descMatch[1].trim();\r\n result.body = content.slice(frontmatterMatch[0].length).trim();\r\n return result;\r\n }\r\n\r\n private tryReadFile(filePath: string): string | null {\r\n try {\r\n if (!existsSync(filePath)) return null;\r\n const content = readFileSync(filePath, 'utf8');\r\n return content.length > MAX_FILE_CHARS\r\n ? content.slice(0, MAX_FILE_CHARS) + '\\n(已截断)'\r\n : content;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n}\r\n","/**\r\n * OpencodeBasicFeature - 基础文件操作工具集\r\n * 来自 opencode 项目的优秀基础文件工具实现\r\n *\r\n * 包含工具:\r\n * - read: 文件读取(支持 offset/limit 分页)\r\n * - write: 文件写入(覆盖模式)\r\n * - edit: 文件编辑(智能匹配策略)\r\n * - ls: 目录列表(树形结构)\r\n * - glob: 文件模式搜索\r\n * - grep: 内容搜索(基于 ripgrep)\r\n *\r\n * 安全机制:\r\n * - \"先读后写\"保护:write 工具前必须先 read 过该文件\r\n */\r\n\r\nimport { fileURLToPath } from 'url';\r\nimport { promises as fs } from 'fs';\r\nimport { Decision } from '../../core/lifecycle.js';\r\nimport type { HookDeclarations } from '../../core/hook-declarations.js';\r\nimport { CoreLifecycle } from '../../core/lifecycle.js';\r\nimport type { AgentFeature, FeatureStateSnapshot, PackageInfo } from '../../core/feature.js';\r\nimport type { ToolContext } from '../../core/lifecycle.js';\r\nimport type { FeatureInitContext } from '../../core/feature.js';\r\nimport type { DecisionResult } from '../../core/lifecycle.js';\r\nimport { getPackageInfoFromSource } from '../../core/feature.js';\r\nimport {\r\n createReadTool,\r\n createWriteTool,\r\n createEditTool,\r\n createLsTool,\r\n createGlobTool,\r\n createGrepTool,\r\n normalizeNamedPathArg,\r\n resolveWorkspacePath,\r\n serializeReadDedupState,\r\n deserializeReadDedupState,\r\n} from './tools.js';\r\n\r\nconst __filename = fileURLToPath(import.meta.url);\r\n\r\nexport interface OpencodeBasicFeatureConfig {\r\n workspaceDir?: string;\r\n}\r\n\r\n/**\r\n * OpencodeBasic Feature - 基础文件操作工具集\r\n */\r\nexport class OpencodeBasicFeature implements AgentFeature {\r\n\r\n static hooks: HookDeclarations = {\r\n validateWriteOperation: { lifecycle: CoreLifecycle.ToolUse, kind: 'guard' as const, role: 'advisor' as const },\r\n };\r\n readonly name = 'opencode-basic';\r\n readonly source = __filename.replace(/\\\\/g, '/');\r\n readonly description = '提供读写文件、编辑、列目录、glob 和 grep 等基础工程化工具。包含\"先读后写\"安全保护机制。';\r\n\r\n /**\r\n * 存储已读取文件的路径(绝对路径)\r\n * 在整个 Session 生命周期中保持,用于验证 write 操作\r\n */\r\n private readFiles = new Set<string>();\r\n\r\n /**\r\n * 缓存包信息\r\n */\r\n private _packageInfo: PackageInfo | null = null;\r\n\r\n /**\r\n * 获取包信息(统一打包方案)\r\n */\r\n getPackageInfo(): PackageInfo | null {\r\n if (!this._packageInfo) {\r\n this._packageInfo = getPackageInfoFromSource(this.source);\r\n }\r\n return this._packageInfo;\r\n }\r\n\r\n /**\r\n * 获取模板名称列表(统一打包方案)\r\n */\r\n getTemplateNames(): string[] {\r\n return [\r\n 'read',\r\n 'write',\r\n 'edit',\r\n 'ls',\r\n 'glob',\r\n 'grep',\r\n ];\r\n }\r\n\r\n /**\r\n * Logger 实例,用于记录结构化日志\r\n */\r\n private logger: any;\r\n private readonly workspaceDir: string;\r\n\r\n constructor(config: OpencodeBasicFeatureConfig = {}) {\r\n // eslint-disable-next-line no-restricted-syntax -- 防御性默认值,共享进程下返回 Claw 根目录;宿主应显式传 workspaceDir\r\n this.workspaceDir = config.workspaceDir || process.cwd();\r\n }\r\n\r\n /**\r\n * Feature 初始化时清空读取历史\r\n */\r\n async onInitiate(ctx: FeatureInitContext): Promise<void> {\r\n this.readFiles.clear();\r\n this.logger = ctx.logger;\r\n this.logger?.info('OpencodeBasic read history initialized', {\r\n feature: 'opencode-basic',\r\n lifecycle: 'AgentInitiate'\r\n });\r\n }\r\n\r\n captureState(): FeatureStateSnapshot {\r\n return {\r\n readFiles: Array.from(this.readFiles),\r\n readDedupState: serializeReadDedupState(),\r\n };\r\n }\r\n\r\n restoreState(snapshot: FeatureStateSnapshot): void {\r\n const state = snapshot as { readFiles?: string[]; readDedupState?: unknown };\r\n this.readFiles = new Set(state.readFiles ?? []);\r\n deserializeReadDedupState(state.readDedupState);\r\n }\r\n\r\n /**\r\n * 工具使用前拦截器\r\n * - 记录 read 操作的文件路径\r\n * - 验证 write / edit 操作是否已先读取(write 创建的新文件自动豁免)\r\n */\r\n async validateWriteOperation(ctx: ToolContext): Promise<DecisionResult> {\r\n const toolName = ctx.call.name;\r\n\r\n // 记录 read 操作\r\n if (toolName === 'read') {\r\n const filePath = normalizeNamedPathArg(ctx.call.arguments || {}, 'filePath', 'filepath', 'path');\r\n const normalizedPath = resolveWorkspacePath(filePath, this.workspaceDir);\r\n this.readFiles.add(normalizedPath);\r\n\r\n this.logger?.info('File read tracked', {\r\n filePath: normalizedPath,\r\n totalReadFiles: this.readFiles.size,\r\n feature: 'opencode-basic',\r\n lifecycle: 'ToolUse',\r\n hookMethod: 'validateWriteOperation'\r\n });\r\n\r\n return Decision.Continue;\r\n }\r\n\r\n // 验证 write 和 edit 操作\r\n if (toolName === 'write' || toolName === 'edit') {\r\n const filePath = normalizeNamedPathArg(ctx.call.arguments || {}, 'filePath', 'filepath', 'path');\r\n const normalizedPath = resolveWorkspacePath(filePath, this.workspaceDir);\r\n\r\n // 检查文件是否存在\r\n const exists = await fs.stat(normalizedPath)\r\n .then(() => true)\r\n .catch(() => false);\r\n\r\n // 新建文件(仅 write 会走到此分支),允许并记录,\r\n // 这样后续可以直接 edit 而不需要重新 read\r\n if (!exists) {\r\n this.readFiles.add(normalizedPath);\r\n\r\n this.logger?.info('Write allowed for new file', {\r\n filePath: normalizedPath,\r\n feature: 'opencode-basic',\r\n lifecycle: 'ToolUse',\r\n hookMethod: 'validateWriteOperation'\r\n });\r\n return Decision.Continue;\r\n }\r\n\r\n // 修改现有文件,检查是否已读或已 write 过\r\n if (!this.readFiles.has(normalizedPath)) {\r\n this.logger?.warn(`${toolName} blocked: file not read in this session`, {\r\n filePath: normalizedPath,\r\n readFiles: Array.from(this.readFiles),\r\n feature: 'opencode-basic',\r\n lifecycle: 'ToolUse',\r\n hookMethod: 'validateWriteOperation'\r\n });\r\n\r\n return {\r\n action: Decision.Deny,\r\n reason: `文件 ${filePath} 在当前会话中未读取过。请先使用 read 工具查看文件内容后再进行修改。`\r\n };\r\n }\r\n\r\n this.logger?.info(`${toolName} allowed: file was read or written previously`, {\r\n filePath: normalizedPath,\r\n feature: 'opencode-basic',\r\n lifecycle: 'ToolUse',\r\n hookMethod: 'validateWriteOperation'\r\n });\r\n\r\n return Decision.Continue;\r\n }\r\n\r\n // 其他工具,放行\r\n return Decision.Continue;\r\n }\r\n\r\n /**\r\n * 获取所有工具\r\n */\r\n getTools() {\r\n return [\r\n createReadTool(this.workspaceDir),\r\n createWriteTool(this.workspaceDir),\r\n createEditTool(this.workspaceDir),\r\n createLsTool(this.workspaceDir),\r\n createGlobTool(this.workspaceDir),\r\n createGrepTool(this.workspaceDir),\r\n ];\r\n }\r\n\r\n}\r\n","/**\r\n * OpencodeBasic 工具定义\r\n * 来自 opencode 项目的优秀基础文件工具实现\r\n */\r\n\r\nimport { createTool } from '../../core/tool.js';\r\nimport { withDisplay } from '../../core/tool-result-display.js';\r\nimport { open, readFile, writeFile, opendir, stat, mkdir } from 'fs/promises';\r\nimport { globIterate } from 'glob';\r\nimport { spawn } from 'child_process';\r\nimport { createTwoFilesPatch, diffLines } from 'diff';\r\nimport path from 'path';\r\nimport { homedir } from 'os';\r\n\r\n// ============================================================================\r\n// Constants\r\n// ============================================================================\r\n\r\nconst DEFAULT_READ_LIMIT = 2000;\r\nconst MAX_LINE_LENGTH = 2000;\r\nconst MAX_BYTES = 50 * 1024;\r\nconst SEARCH_LIMIT = 100;\r\n// eslint-disable-next-line no-restricted-syntax -- 仅作工具函数默认参数的兜底;OpencodeBasicFeature 总是显式传入 workspaceDir\r\nconst DEFAULT_WORKSPACE_DIR = process.cwd();\r\n\r\nconst IGNORE_PATTERNS = [\r\n 'node_modules/**',\r\n '__pycache__/**',\r\n '.git/**',\r\n 'dist/**',\r\n 'build/**',\r\n 'target/**',\r\n 'vendor/**',\r\n 'bin/**',\r\n 'obj/**',\r\n '.idea/**',\r\n '.vscode/**',\r\n '.zig-cache/**',\r\n 'zig-out/**',\r\n '.coverage/**',\r\n 'coverage/**',\r\n 'tmp/**',\r\n 'temp/**',\r\n '.cache/**',\r\n 'cache/**',\r\n 'logs/**',\r\n '.venv/**',\r\n 'venv/**',\r\n 'env/**'\r\n];\r\n\r\n/**\r\n * Read 去重状态:记录已读文件的 { mtime, offset, limit }。\r\n * 同一文件同一范围已读过且 mtime 没变时,返回 stub 而非重新读取全文。\r\n */\r\ninterface ReadDedupEntry {\r\n mtimeMs: number;\r\n /** undefined = set by Edit/Write, not a Read */\r\n offset: number | undefined;\r\n limit: number | undefined;\r\n}\r\nconst readDedupState = new Map<string, ReadDedupEntry>();\r\n\r\n/**\r\n * 序列化 readDedupState(模块级状态),供 feature captureState 导出。\r\n * 用于会话精简/恢复时保持 edit/write 的\"先读后写\"校验状态。\r\n */\r\nexport function serializeReadDedupState(): Record<string, ReadDedupEntry> {\r\n return Object.fromEntries(readDedupState);\r\n}\r\n\r\n/**\r\n * 反序列化 readDedupState,供 feature restoreState 恢复。\r\n * 先清空再填充,避免残留状态。\r\n */\r\nexport function deserializeReadDedupState(data: unknown): void {\r\n readDedupState.clear();\r\n if (!data || typeof data !== 'object') return;\r\n for (const [key, value] of Object.entries(data as Record<string, unknown>)) {\r\n if (!value || typeof value !== 'object') continue;\r\n const entry = value as { mtimeMs?: unknown; offset?: unknown; limit?: unknown };\r\n if (typeof entry.mtimeMs !== 'number') continue;\r\n readDedupState.set(key, {\r\n mtimeMs: entry.mtimeMs,\r\n offset: typeof entry.offset === 'number' ? entry.offset : undefined,\r\n limit: typeof entry.limit === 'number' ? entry.limit : undefined,\r\n });\r\n }\r\n}\r\n\r\nfunction normalizeNamedPathArg(args: unknown, ...keys: string[]): string {\r\n if (!args || typeof args !== 'object') {\r\n throw new Error(`Missing required parameter: \"${keys[0]}\"`);\r\n }\r\n for (const key of keys) {\r\n const value = (args as Record<string, unknown>)[key];\r\n if (typeof value === 'string' && value.trim()) {\r\n return value;\r\n }\r\n }\r\n const receivedKeys = Object.keys(args as Record<string, unknown>);\r\n const hint = receivedKeys.length > 0\r\n ? ` Received keys: [${receivedKeys.join(', ')}]`\r\n : ' Received an empty object.';\r\n throw new Error(`Missing required parameter: \"${keys[0]}\".${hint}`);\r\n}\r\n\r\n/**\r\n * 与 normalizeNamedPathArg 类似,但找不到时返回 undefined 而非抛错。\r\n * 用于可选路径参数(如 glob/grep 的 searchPath)。\r\n */\r\nfunction tryNamedPathArg(args: unknown, ...keys: string[]): string | undefined {\r\n if (!args || typeof args !== 'object') return undefined;\r\n for (const key of keys) {\r\n const value = (args as Record<string, unknown>)[key];\r\n if (typeof value === 'string' && value.trim()) {\r\n return value;\r\n }\r\n }\r\n return undefined;\r\n}\r\n\r\nfunction resolveWorkspacePath(filePath: string, workspaceDir: string = DEFAULT_WORKSPACE_DIR): string {\r\n return expandPath(filePath, workspaceDir);\r\n}\r\n\r\nfunction resolveWorkspaceSearchPath(searchPath: string | undefined, workspaceDir: string = DEFAULT_WORKSPACE_DIR): string {\r\n if (!searchPath) {\r\n return workspaceDir;\r\n }\r\n return resolveWorkspacePath(searchPath, workspaceDir);\r\n}\r\n\r\n/**\r\n * 增强版路径解析:~ 展开、空白 trim、null byte 安全检查、NFC 标准化。\r\n * 参考 Claude Code 的 expandPath 实现。\r\n */\r\nfunction expandPath(inputPath: string, baseDir: string = DEFAULT_WORKSPACE_DIR): string {\r\n if (typeof inputPath !== 'string') {\r\n throw new TypeError(`Path must be a string, received ${typeof inputPath}`);\r\n }\r\n\r\n // Null byte 安全检查\r\n if (inputPath.includes('\\0')) {\r\n throw new Error('Path contains null bytes');\r\n }\r\n\r\n const trimmed = inputPath.trim();\r\n if (!trimmed) {\r\n return path.normalize(baseDir).normalize('NFC');\r\n }\r\n\r\n // ~ 展开\r\n let resolved: string;\r\n if (trimmed === '~') {\r\n resolved = homedir();\r\n } else if (trimmed.startsWith('~/')) {\r\n resolved = path.join(homedir(), trimmed.slice(2));\r\n } else if (path.isAbsolute(trimmed)) {\r\n resolved = path.normalize(trimmed);\r\n } else {\r\n resolved = path.resolve(baseDir, trimmed);\r\n }\r\n\r\n return resolved.normalize('NFC');\r\n}\r\n\r\n// ============================================================================\r\n// 设备文件阻断 — 防止读取无限输出或阻塞输入的设备文件\r\n// ============================================================================\r\n\r\nconst BLOCKED_DEVICE_PATHS = new Set([\r\n '/dev/zero',\r\n '/dev/random',\r\n '/dev/urandom',\r\n '/dev/full',\r\n '/dev/stdin',\r\n '/dev/tty',\r\n '/dev/console',\r\n '/dev/stdout',\r\n '/dev/stderr',\r\n '/dev/fd/0',\r\n '/dev/fd/1',\r\n '/dev/fd/2',\r\n]);\r\n\r\nfunction isBlockedDevicePath(filePath: string): boolean {\r\n if (BLOCKED_DEVICE_PATHS.has(filePath)) return true;\r\n if (\r\n filePath.startsWith('/proc/') &&\r\n (filePath.endsWith('/fd/0') || filePath.endsWith('/fd/1') || filePath.endsWith('/fd/2'))\r\n ) {\r\n return true;\r\n }\r\n return false;\r\n}\r\n\r\n// ============================================================================\r\n// 编码与行尾符检测\r\n// ============================================================================\r\n\r\ntype FileEncoding = 'utf8' | 'utf16le';\r\ntype LineEndingType = 'LF' | 'CRLF';\r\n\r\n/**\r\n * 从 Buffer 检测编码(UTF-16LE BOM 检测)\r\n */\r\nfunction detectEncoding(buffer: Buffer): FileEncoding {\r\n if (buffer.length >= 2 && buffer[0] === 0xff && buffer[1] === 0xfe) {\r\n return 'utf16le';\r\n }\r\n return 'utf8';\r\n}\r\n\r\n/**\r\n * 从内容检测行尾符\r\n */\r\nfunction detectLineEndings(content: string): LineEndingType {\r\n const sample = content.slice(0, 4096);\r\n return sample.includes('\\r\\n') ? 'CRLF' : 'LF';\r\n}\r\n\r\n/**\r\n * 写入文件时保留行尾符。\r\n * 如果目标文件使用 CRLF,将 content 中的 LF 转换为 CRLF。\r\n */\r\nfunction writeTextContent(\r\n filePath: string,\r\n content: string,\r\n encoding: FileEncoding = 'utf8',\r\n lineEndings: LineEndingType = 'LF',\r\n): Promise<void> {\r\n let toWrite = content;\r\n if (lineEndings === 'CRLF') {\r\n toWrite = content.replaceAll('\\r\\n', '\\n').split('\\n').join('\\r\\n');\r\n }\r\n return writeFile(filePath, toWrite, encoding);\r\n}\r\n\r\n// ============================================================================\r\n// 字符归一化(弯引号、Unicode 空白、零宽字符)\r\n// 参考 Claude Code 的 findActualString / normalizeQuotes,空白与零宽字符\r\n// 视为复制粘贴事故残留:归一化只用于把 oldString 对位到文件原文,\r\n// 命中即视为精确匹配(与弯引号语义一致)。\r\n// ============================================================================\r\n\r\n/** 等长归一表:弯引号与 Unicode 空白统一为 ASCII 等价字符 */\r\nconst EQUIVALENT_CHARS: Map<string, string> = new Map([\r\n ['\\u2018', \"'\"], // LEFT SINGLE QUOTATION MARK\r\n ['\\u2019', \"'\"], // RIGHT SINGLE QUOTATION MARK\r\n ['\\u201C', '\"'], // LEFT DOUBLE QUOTATION MARK\r\n ['\\u201D', '\"'], // RIGHT DOUBLE QUOTATION MARK\r\n ['\\u00A0', ' '], // NO-BREAK SPACE\r\n ['\\u1680', ' '], // OGHAM SPACE MARK\r\n ['\\u2002', ' '], // EN QUAD\r\n ['\\u2003', ' '], // EM QUAD\r\n ['\\u2004', ' '], // THREE-PER-EM SPACE\r\n ['\\u2005', ' '], // FOUR-PER-EM SPACE\r\n ['\\u2006', ' '], // SIX-PER-EM SPACE\r\n ['\\u2007', ' '], // FIGURE SPACE\r\n ['\\u2008', ' '], // PUNCTUATION SPACE\r\n ['\\u2009', ' '], // THIN SPACE\r\n ['\\u200A', ' '], // HAIR SPACE\r\n ['\\u202F', ' '], // NARROW NO-BREAK SPACE\r\n ['\\u205F', ' '], // MEDIUM MATHEMATICAL SPACE\r\n ['\\u3000', ' '], // IDEOGRAPHIC SPACE(全角空格)\r\n]);\r\n\r\n/** 删除型归一:零宽字符与 BOM,在匹配视图中剔除(不参与长度计算) */\r\nconst INVISIBLE_CHARS = new Set(['\\u200B', '\\u200C', '\\u200D', '\\uFEFF']);\r\n\r\n/** 任意一侧含特殊字符时才值得进入归一化匹配,避免大文件白付归一化成本 */\r\nconst SPECIAL_CHARS_RE = /[\\u00A0\\u1680\\u2002-\\u200A\\u200B-\\u200D\\u2018\\u2019\\u201C\\u201D\\u202F\\u205F\\u3000\\uFEFF]/;\r\n\r\nfunction normalizeForMatch(str: string): string {\r\n let result = '';\r\n for (const ch of str) {\r\n if (INVISIBLE_CHARS.has(ch)) continue;\r\n result += EQUIVALENT_CHARS.get(ch) ?? ch;\r\n }\r\n return result;\r\n}\r\n\r\n/**\r\n * 在文件内容中查找匹配字符串。\r\n * 先精确匹配,失败后做字符归一化(弯引号、Unicode 空白、零宽字符)再匹配。\r\n * 返回文件中实际存在的字符串,或 null。\r\n * 零宽字符会使归一化视图与原文长度不一致,因此记录视图字符到原文\r\n * 下标的映射,命中后换算回原文区间(区间外的零宽字符保留在文件中)。\r\n */\r\nfunction findActualString(fileContent: string, searchString: string): string | null {\r\n if (fileContent.includes(searchString)) {\r\n return searchString;\r\n }\r\n if (!SPECIAL_CHARS_RE.test(fileContent) && !SPECIAL_CHARS_RE.test(searchString)) {\r\n return null;\r\n }\r\n\r\n let normalizedFile = '';\r\n const sourceIndex: number[] = [];\r\n for (let i = 0; i < fileContent.length; i++) {\r\n const ch = fileContent[i]!;\r\n if (INVISIBLE_CHARS.has(ch)) continue;\r\n normalizedFile += EQUIVALENT_CHARS.get(ch) ?? ch;\r\n sourceIndex.push(i);\r\n }\r\n const normalizedSearch = normalizeForMatch(searchString);\r\n if (!normalizedSearch) {\r\n return null;\r\n }\r\n\r\n const index = normalizedFile.indexOf(normalizedSearch);\r\n if (index === -1) {\r\n return null;\r\n }\r\n const start = sourceIndex[index]!;\r\n const end = sourceIndex[index + normalizedSearch.length - 1]! + 1;\r\n return fileContent.substring(start, end);\r\n}\r\n\r\n// ============================================================================\r\n// Read Tool - 文件读取\r\n// ============================================================================\r\n\r\n/**\r\n * 检测是否为二进制文件\r\n */\r\nasync function isBinaryFile(filepath: string): Promise<boolean> {\r\n const ext = path.extname(filepath).toLowerCase();\r\n\r\n const binaryExts = [\r\n '.zip', '.tar', '.gz', '.exe', '.dll', '.so', '.class', '.jar', '.war',\r\n '.7z', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.odt',\r\n '.ods', '.odp', '.bin', '.dat', '.obj', '.o', '.a', '.lib', '.wasm',\r\n '.pyc', '.pyo'\r\n ];\r\n\r\n if (binaryExts.includes(ext)) {\r\n return true;\r\n }\r\n\r\n let handle: Awaited<ReturnType<typeof open>> | undefined;\r\n try {\r\n handle = await open(filepath, 'r');\r\n const buffer = Buffer.allocUnsafe(4096);\r\n const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);\r\n if (bytesRead === 0) return false;\r\n\r\n let nonPrintableCount = 0;\r\n for (let i = 0; i < bytesRead; i += 1) {\r\n if (buffer[i] === 0) return true;\r\n if (buffer[i]! < 9 || (buffer[i]! > 13 && buffer[i]! < 32)) {\r\n nonPrintableCount += 1;\r\n }\r\n }\r\n\r\n return nonPrintableCount / bytesRead > 0.3;\r\n } catch {\r\n return false;\r\n } finally {\r\n await handle?.close().catch(() => {});\r\n }\r\n}\r\n\r\n/**\r\n * 文件读取工具\r\n */\r\nexport function createReadTool(workspaceDir: string = DEFAULT_WORKSPACE_DIR) {\r\n return createTool({\r\n name: 'read',\r\n description: 'Read a file from the local filesystem. Can read files with offset/limit for pagination, and can also read directory contents. For large files, use offset and limit parameters to read in chunks.',\r\n render: 'read',\r\n parallelizable: true,\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n filePath: {\r\n type: 'string',\r\n description: 'The absolute path to the file or directory to read'\r\n },\r\n offset: {\r\n type: 'number',\r\n description: 'The line number to start reading from (1-indexed, defaults to 1)'\r\n },\r\n limit: {\r\n type: 'number',\r\n description: 'The maximum number of lines to read (defaults to 2000)'\r\n }\r\n },\r\n additionalProperties: false,\r\n required: ['filePath']\r\n },\r\n execute: async (args = {}) => {\r\n const filePath = normalizeNamedPathArg(args, 'filePath', 'filepath', 'path');\r\n const offsetParam = typeof (args as Record<string, unknown>).offset === 'number'\r\n ? (args as Record<string, unknown>).offset as number\r\n : undefined;\r\n const limitParam = typeof (args as Record<string, unknown>).limit === 'number'\r\n ? (args as Record<string, unknown>).limit as number\r\n : undefined;\r\n const resolvedFilePath = resolveWorkspacePath(filePath, workspaceDir);\r\n\r\n if (offsetParam !== undefined && offsetParam < 1) {\r\n throw new Error('offset must be greater than or equal to 1');\r\n }\r\n\r\n // 设备文件阻断 — 防止进程挂死\r\n if (isBlockedDevicePath(resolvedFilePath)) {\r\n throw new Error(`Cannot read '${filePath}': this device file would block or produce infinite output.`);\r\n }\r\n\r\n const stats = await stat(resolvedFilePath).catch(() => null);\r\n if (!stats) {\r\n throw new Error(`File not found: ${resolvedFilePath}`);\r\n }\r\n\r\n // 处理目录\r\n if (stats.isDirectory()) {\r\n const limit = limitParam ?? DEFAULT_READ_LIMIT;\r\n const offset = offsetParam ?? 1;\r\n const start = offset - 1;\r\n const end = start + limit;\r\n const candidates: Array<{ name: string; isDirectory: boolean; isSymbolicLink: boolean }> = [];\r\n let totalEntries = 0;\r\n const directory = await opendir(resolvedFilePath);\r\n\r\n try {\r\n for await (const dirent of directory) {\r\n totalEntries += 1;\r\n candidates.push({\r\n name: dirent.name,\r\n isDirectory: dirent.isDirectory(),\r\n isSymbolicLink: dirent.isSymbolicLink(),\r\n });\r\n candidates.sort((left, right) => left.name.localeCompare(right.name));\r\n if (candidates.length > end) candidates.pop();\r\n }\r\n } finally {\r\n await directory.close().catch(() => {});\r\n }\r\n\r\n const visibleCandidates = candidates.slice(start, end);\r\n const entries: string[] = [];\r\n for (const candidate of visibleCandidates) {\r\n if (candidate.isDirectory) {\r\n entries.push(candidate.name + path.sep);\r\n } else if (candidate.isSymbolicLink) {\r\n try {\r\n const targetStats = await stat(path.join(resolvedFilePath, candidate.name));\r\n entries.push(targetStats.isDirectory() ? candidate.name + path.sep : candidate.name);\r\n } catch {\r\n entries.push(candidate.name);\r\n }\r\n } else {\r\n entries.push(candidate.name);\r\n }\r\n }\r\n\r\n const truncated = totalEntries > end;\r\n return {\r\n type: 'directory',\r\n path: resolvedFilePath,\r\n totalEntries,\r\n offset,\r\n limit,\r\n truncated,\r\n entries\r\n };\r\n }\r\n\r\n // 处理文件\r\n const isBinary = await isBinaryFile(resolvedFilePath);\r\n if (isBinary) {\r\n throw new Error(`Cannot read binary file: ${resolvedFilePath}`);\r\n }\r\n\r\n const content = await readFile(resolvedFilePath, 'utf-8');\r\n const lines = content.split('\\n');\r\n\r\n const limit = limitParam ?? DEFAULT_READ_LIMIT;\r\n const offset = offsetParam ?? 1;\r\n const start = offset - 1;\r\n\r\n if (start >= lines.length) {\r\n throw new Error(`Offset ${offset} is out of range for this file (${lines.length} lines)`);\r\n }\r\n\r\n // 读取并处理行\r\n const raw: string[] = [];\r\n let bytes = 0;\r\n let truncatedByBytes = false;\r\n\r\n for (let i = start; i < Math.min(lines.length, start + limit); i++) {\r\n const line = lines[i].length > MAX_LINE_LENGTH\r\n ? lines[i].substring(0, MAX_LINE_LENGTH) + '...'\r\n : lines[i];\r\n const size = Buffer.byteLength(line, 'utf-8') + (raw.length > 0 ? 1 : 0);\r\n\r\n if (bytes + size > MAX_BYTES) {\r\n truncatedByBytes = true;\r\n break;\r\n }\r\n\r\n raw.push(line);\r\n bytes += size;\r\n }\r\n\r\n // 生成带行号的输出\r\n const contentWithLines = raw.map((line, index) => {\r\n return `${index + offset}: ${line}`;\r\n });\r\n\r\n const totalLines = lines.length;\r\n const lastReadLine = offset + raw.length - 1;\r\n const hasMoreLines = totalLines > lastReadLine;\r\n const truncated = hasMoreLines || truncatedByBytes;\r\n\r\n // 更新去重状态\r\n try {\r\n const mtimeMs = (await stat(resolvedFilePath)).mtimeMs;\r\n readDedupState.set(resolvedFilePath, { mtimeMs, offset, limit: limitParam });\r\n } catch {\r\n // stat 失败,跳过去重状态更新\r\n }\r\n\r\n return {\r\n type: 'file',\r\n path: resolvedFilePath,\r\n totalLines,\r\n offset,\r\n limit,\r\n truncated,\r\n truncatedByBytes,\r\n lastReadLine,\r\n content: contentWithLines.join('\\n')\r\n };\r\n }\r\n });\r\n}\r\n\r\nexport const readTool = createReadTool();\r\n\r\n// ============================================================================\r\n// Write Tool - 文件写入\r\n// ============================================================================\r\n\r\n/**\r\n * 文件写入工具\r\n */\r\nexport function createWriteTool(workspaceDir: string = DEFAULT_WORKSPACE_DIR) {\r\n return createTool({\r\n name: 'write',\r\n description: 'Write content to a file. Creates new files or overwrites existing files. THIS TOOL WILL OVERWRITE THE EXISTING FILE IF it exists. Only use this tool when explicitly requested to do so. Always prefer editing existing files using the edit tool when the file already exists.',\r\n render: 'write',\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n filePath: {\r\n type: 'string',\r\n description: 'The absolute path to the file to write'\r\n },\r\n content: {\r\n type: 'string',\r\n description: 'The content to write to the file'\r\n }\r\n },\r\n additionalProperties: false,\r\n required: ['filePath', 'content']\r\n },\r\n execute: async (args = {}) => {\r\n const filePath = normalizeNamedPathArg(args, 'filePath', 'filepath', 'path');\r\n const content = (args as Record<string, unknown>).content as string;\r\n const resolvedFilePath = resolveWorkspacePath(filePath, workspaceDir);\r\n\r\n // 检测现有文件的编码\r\n let encoding: FileEncoding = 'utf8';\r\n const exists = await stat(resolvedFilePath).then(() => true).catch(() => false);\r\n let contentOld = '';\r\n if (exists) {\r\n // Read-before-write 校验:必须先读才能写\r\n const dedupEntry = readDedupState.get(resolvedFilePath);\r\n if (!dedupEntry) {\r\n throw new Error(\r\n `File has not been read yet. Read it first before writing to it: ${resolvedFilePath}`\r\n );\r\n }\r\n // Staleness 校验:文件在上次读取后被外部修改则拒绝写入\r\n const currentMtime = (await stat(resolvedFilePath)).mtimeMs;\r\n if (currentMtime !== dedupEntry.mtimeMs) {\r\n throw new Error(\r\n `File has been modified since last read. Read the file again before writing to it: ${resolvedFilePath}`\r\n );\r\n }\r\n\r\n const buffer = await readFile(resolvedFilePath, { encoding: null });\r\n encoding = detectEncoding(buffer);\r\n const rawContent = buffer.toString(encoding);\r\n contentOld = rawContent.replaceAll('\\r\\n', '\\n');\r\n }\r\n\r\n // 生成 diff\r\n const diff = createTwoFilesPatch(resolvedFilePath, resolvedFilePath, contentOld, content);\r\n\r\n // 确保父目录存在\r\n const dir = path.dirname(resolvedFilePath);\r\n await mkdir(dir, { recursive: true });\r\n\r\n // 写入文件(保留编码,强制 LF 行尾符以避免跨平台损坏)\r\n await writeTextContent(resolvedFilePath, content, encoding, 'LF');\r\n\r\n // 更新 read 去重状态(offset=undefined 表示由 Write 设置,非 Read 产生)\r\n try {\r\n const mtimeMs = (await stat(resolvedFilePath)).mtimeMs;\r\n readDedupState.set(resolvedFilePath, { mtimeMs, offset: undefined, limit: undefined });\r\n } catch {\r\n // ignore\r\n }\r\n\r\n return withDisplay(\r\n JSON.stringify({\r\n filePath: resolvedFilePath,\r\n existed: exists,\r\n lines: content.split('\\n').length,\r\n message: `File ${exists ? 'updated' : 'created'} successfully`,\r\n }),\r\n { filePath: resolvedFilePath, existed: exists, diff }\r\n );\r\n }\r\n });\r\n}\r\n\r\nexport const writeTool = createWriteTool();\r\n\r\n// ============================================================================\r\n// Edit Tool - 文件编辑\r\n// ============================================================================\r\n\r\n/**\r\n * Levenshtein 距离算法\r\n */\r\nfunction levenshtein(a: string, b: string): number {\r\n if (a === '' || b === '') {\r\n return Math.max(a.length, b.length);\r\n }\r\n\r\n const matrix = Array.from({ length: a.length + 1 }, (_, i) =>\r\n Array.from({ length: b.length + 1 }, (_, j) => (i === 0 ? j : j === 0 ? i : 0))\r\n );\r\n\r\n for (let i = 1; i <= a.length; i++) {\r\n for (let j = 1; j <= b.length; j++) {\r\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\r\n matrix[i][j] = Math.min(\r\n matrix[i - 1][j] + 1,\r\n matrix[i][j - 1] + 1,\r\n matrix[i - 1][j - 1] + cost\r\n );\r\n }\r\n }\r\n\r\n return matrix[a.length][b.length];\r\n}\r\n\r\n/**\r\n * Replacer 类型\r\n */\r\ntype Replacer = (content: string, find: string) => Generator<string, void, unknown>;\r\n\r\n/**\r\n * 带名称的 Replacer 条目\r\n */\r\ninterface ReplacerEntry {\r\n name: string;\r\n fn: Replacer;\r\n}\r\n\r\n/**\r\n * 精确匹配替换器\r\n */\r\nconst simpleReplacer: Replacer = function* (_content, find) {\r\n yield find;\r\n};\r\n\r\n/**\r\n * 行修剪匹配替换器\r\n */\r\nconst lineTrimmedReplacer: Replacer = function* (content, find) {\r\n const originalLines = content.split('\\n');\r\n const searchLines = find.split('\\n');\r\n\r\n if (searchLines[searchLines.length - 1] === '') {\r\n searchLines.pop();\r\n }\r\n\r\n for (let i = 0; i <= originalLines.length - searchLines.length; i++) {\r\n let matches = true;\r\n\r\n for (let j = 0; j < searchLines.length; j++) {\r\n if (originalLines[i + j].trim() !== searchLines[j].trim()) {\r\n matches = false;\r\n break;\r\n }\r\n }\r\n\r\n if (matches) {\r\n let matchStartIndex = 0;\r\n for (let k = 0; k < i; k++) {\r\n matchStartIndex += originalLines[k].length + 1;\r\n }\r\n\r\n let matchEndIndex = matchStartIndex;\r\n for (let k = 0; k < searchLines.length; k++) {\r\n matchEndIndex += originalLines[i + k].length;\r\n if (k < searchLines.length - 1) {\r\n matchEndIndex += 1;\r\n }\r\n }\r\n\r\n yield content.substring(matchStartIndex, matchEndIndex);\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * 块锚点匹配替换器(基于首尾行匹配)\r\n */\r\nconst blockAnchorReplacer: Replacer = function* (content, find) {\r\n const originalLines = content.split('\\n');\r\n const searchLines = find.split('\\n');\r\n\r\n if (searchLines.length < 3) return;\r\n\r\n if (searchLines[searchLines.length - 1] === '') {\r\n searchLines.pop();\r\n }\r\n\r\n const firstLineSearch = searchLines[0].trim();\r\n const lastLineSearch = searchLines[searchLines.length - 1].trim();\r\n\r\n const candidates: Array<{ startLine: number; endLine: number }> = [];\r\n for (let i = 0; i < originalLines.length; i++) {\r\n if (originalLines[i].trim() !== firstLineSearch) continue;\r\n\r\n for (let j = i + 2; j < originalLines.length; j++) {\r\n if (originalLines[j].trim() === lastLineSearch) {\r\n candidates.push({ startLine: i, endLine: j });\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (candidates.length === 0) return;\r\n\r\n const SINGLE_CANDIDATE_THRESHOLD = 0.0;\r\n const MULTIPLE_CANDIDATES_THRESHOLD = 0.3;\r\n\r\n if (candidates.length === 1) {\r\n const { startLine, endLine } = candidates[0];\r\n const searchBlockSize = searchLines.length;\r\n const actualBlockSize = endLine - startLine + 1;\r\n\r\n let similarity = 0;\r\n const linesToCheck = Math.min(searchBlockSize - 2, actualBlockSize - 2);\r\n\r\n if (linesToCheck > 0) {\r\n for (let j = 1; j < searchBlockSize - 1 && j < actualBlockSize - 1; j++) {\r\n const originalLine = originalLines[startLine + j].trim();\r\n const searchLine = searchLines[j].trim();\r\n const maxLen = Math.max(originalLine.length, searchLine.length);\r\n if (maxLen === 0) continue;\r\n const distance = levenshtein(originalLine, searchLine);\r\n similarity += (1 - distance / maxLen) / linesToCheck;\r\n if (similarity >= SINGLE_CANDIDATE_THRESHOLD) break;\r\n }\r\n } else {\r\n similarity = 1.0;\r\n }\r\n\r\n if (similarity >= SINGLE_CANDIDATE_THRESHOLD) {\r\n let matchStartIndex = 0;\r\n for (let k = 0; k < startLine; k++) {\r\n matchStartIndex += originalLines[k].length + 1;\r\n }\r\n let matchEndIndex = matchStartIndex;\r\n for (let k = startLine; k <= endLine; k++) {\r\n matchEndIndex += originalLines[k].length;\r\n if (k < endLine) matchEndIndex += 1;\r\n }\r\n yield content.substring(matchStartIndex, matchEndIndex);\r\n }\r\n return;\r\n }\r\n\r\n // 多个候选,找最佳匹配\r\n let bestMatch: { startLine: number; endLine: number } | null = null;\r\n let maxSimilarity = -1;\r\n\r\n for (const candidate of candidates) {\r\n const { startLine, endLine } = candidate;\r\n const searchBlockSize = searchLines.length;\r\n const actualBlockSize = endLine - startLine + 1;\r\n\r\n let similarity = 0;\r\n const linesToCheck = Math.min(searchBlockSize - 2, actualBlockSize - 2);\r\n\r\n if (linesToCheck > 0) {\r\n for (let j = 1; j < searchBlockSize - 1 && j < actualBlockSize - 1; j++) {\r\n const originalLine = originalLines[startLine + j].trim();\r\n const searchLine = searchLines[j].trim();\r\n const maxLen = Math.max(originalLine.length, searchLine.length);\r\n if (maxLen === 0) continue;\r\n const distance = levenshtein(originalLine, searchLine);\r\n similarity += 1 - distance / maxLen;\r\n }\r\n similarity /= linesToCheck;\r\n } else {\r\n similarity = 1.0;\r\n }\r\n\r\n if (similarity > maxSimilarity) {\r\n maxSimilarity = similarity;\r\n bestMatch = candidate;\r\n }\r\n }\r\n\r\n if (maxSimilarity >= MULTIPLE_CANDIDATES_THRESHOLD && bestMatch) {\r\n const { startLine, endLine } = bestMatch;\r\n let matchStartIndex = 0;\r\n for (let k = 0; k < startLine; k++) {\r\n matchStartIndex += originalLines[k].length + 1;\r\n }\r\n let matchEndIndex = matchStartIndex;\r\n for (let k = startLine; k <= endLine; k++) {\r\n matchEndIndex += originalLines[k].length;\r\n if (k < endLine) matchEndIndex += 1;\r\n }\r\n yield content.substring(matchStartIndex, matchEndIndex);\r\n }\r\n};\r\n\r\n/**\r\n * 空白标准化替换器\r\n */\r\nconst whitespaceNormalizedReplacer: Replacer = function* (content, find) {\r\n const normalizeWhitespace = (text: string) => text.replace(/\\s+/g, ' ').trim();\r\n const normalizedFind = normalizeWhitespace(find);\r\n\r\n const lines = content.split('\\n');\r\n for (let i = 0; i < lines.length; i++) {\r\n if (normalizeWhitespace(lines[i]) === normalizedFind) {\r\n yield lines[i];\r\n }\r\n }\r\n\r\n const findLines = find.split('\\n');\r\n if (findLines.length > 1) {\r\n for (let i = 0; i <= lines.length - findLines.length; i++) {\r\n const block = lines.slice(i, i + findLines.length).join('\\n');\r\n if (normalizeWhitespace(block) === normalizedFind) {\r\n yield block;\r\n }\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * 缩进灵活替换器\r\n */\r\nconst indentationFlexibleReplacer: Replacer = function* (content, find) {\r\n const removeIndentation = (text: string) => {\r\n const lines = text.split('\\n');\r\n const nonEmptyLines = lines.filter((line) => line.trim().length > 0);\r\n if (nonEmptyLines.length === 0) return text;\r\n\r\n const minIndent = Math.min(\r\n ...nonEmptyLines.map((line) => {\r\n const match = line.match(/^(\\s*)/);\r\n return match ? match[1].length : 0;\r\n })\r\n );\r\n\r\n return lines.map((line) => (line.trim().length === 0 ? line : line.slice(minIndent))).join('\\n');\r\n };\r\n\r\n const normalizedFind = removeIndentation(find);\r\n const contentLines = content.split('\\n');\r\n const findLines = find.split('\\n');\r\n\r\n for (let i = 0; i <= contentLines.length - findLines.length; i++) {\r\n const block = contentLines.slice(i, i + findLines.length).join('\\n');\r\n if (removeIndentation(block) === normalizedFind) {\r\n yield block;\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * 转义符标准化替换器\r\n */\r\nconst escapeNormalizedReplacer: Replacer = function* (content, find) {\r\n const unescapeString = (str: string): string => {\r\n return str.replace(/\\\\(n|t|r|'|\"|`|\\\\|\\n|\\$)/g, (_, capturedChar) => {\r\n switch (capturedChar) {\r\n case 'n': return '\\n';\r\n case 't': return '\\t';\r\n case 'r': return '\\r';\r\n case \"'\": return \"'\";\r\n case '\"': return '\"';\r\n case '`': return '`';\r\n case '\\\\': return '\\\\';\r\n case '\\n': return '\\n';\r\n case '$': return '$';\r\n default: return _;\r\n }\r\n });\r\n };\r\n\r\n const unescapedFind = unescapeString(find);\r\n\r\n if (content.includes(unescapedFind)) {\r\n yield unescapedFind;\r\n }\r\n\r\n const lines = content.split('\\n');\r\n const findLines = unescapedFind.split('\\n');\r\n\r\n for (let i = 0; i <= lines.length - findLines.length; i++) {\r\n const block = lines.slice(i, i + findLines.length).join('\\n');\r\n if (unescapeString(block) === unescapedFind) {\r\n yield block;\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * 边界修剪替换器\r\n */\r\nconst trimmedBoundaryReplacer: Replacer = function* (content, find) {\r\n const trimmedFind = find.trim();\r\n\r\n if (trimmedFind === find) return;\r\n\r\n if (content.includes(trimmedFind)) {\r\n yield trimmedFind;\r\n }\r\n\r\n const lines = content.split('\\n');\r\n const findLines = find.split('\\n');\r\n\r\n for (let i = 0; i <= lines.length - findLines.length; i++) {\r\n const block = lines.slice(i, i + findLines.length).join('\\n');\r\n if (block.trim() === trimmedFind) {\r\n yield block;\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * 上下文感知替换器\r\n */\r\nconst contextAwareReplacer: Replacer = function* (content, find) {\r\n const findLines = find.split('\\n');\r\n if (findLines.length < 3) return;\r\n\r\n if (findLines[findLines.length - 1] === '') {\r\n findLines.pop();\r\n }\r\n\r\n const contentLines = content.split('\\n');\r\n const firstLine = findLines[0].trim();\r\n const lastLine = findLines[findLines.length - 1].trim();\r\n\r\n for (let i = 0; i < contentLines.length; i++) {\r\n if (contentLines[i].trim() !== firstLine) continue;\r\n\r\n for (let j = i + 2; j < contentLines.length; j++) {\r\n if (contentLines[j].trim() === lastLine) {\r\n const blockLines = contentLines.slice(i, j + 1);\r\n\r\n if (blockLines.length === findLines.length) {\r\n let matchingLines = 0;\r\n let totalNonEmptyLines = 0;\r\n\r\n for (let k = 1; k < blockLines.length - 1; k++) {\r\n const blockLine = blockLines[k].trim();\r\n const findLine = findLines[k].trim();\r\n\r\n if (blockLine.length > 0 || findLine.length > 0) {\r\n totalNonEmptyLines++;\r\n if (blockLine === findLine) {\r\n matchingLines++;\r\n }\r\n }\r\n }\r\n\r\n if (totalNonEmptyLines === 0 || matchingLines / totalNonEmptyLines >= 0.5) {\r\n yield blockLines.join('\\n');\r\n break;\r\n }\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * 多次出现替换器\r\n */\r\nconst multiOccurrenceReplacer: Replacer = function* (content, find) {\r\n let startIndex = 0;\r\n\r\n while (true) {\r\n const index = content.indexOf(find, startIndex);\r\n if (index === -1) break;\r\n\r\n yield find;\r\n startIndex = index + find.length;\r\n }\r\n};\r\n\r\n/**\r\n * 所有替换器列表(按精确度从高到低排序)\r\n */\r\nconst REPLACERS: ReplacerEntry[] = [\r\n { name: 'simpleReplacer', fn: simpleReplacer },\r\n { name: 'lineTrimmedReplacer', fn: lineTrimmedReplacer },\r\n { name: 'blockAnchorReplacer', fn: blockAnchorReplacer },\r\n { name: 'whitespaceNormalizedReplacer', fn: whitespaceNormalizedReplacer },\r\n { name: 'indentationFlexibleReplacer', fn: indentationFlexibleReplacer },\r\n { name: 'escapeNormalizedReplacer', fn: escapeNormalizedReplacer },\r\n { name: 'trimmedBoundaryReplacer', fn: trimmedBoundaryReplacer },\r\n { name: 'contextAwareReplacer', fn: contextAwareReplacer },\r\n { name: 'multiOccurrenceReplacer', fn: multiOccurrenceReplacer },\r\n];\r\n\r\n/**\r\n * replace() 的返回结果\r\n */\r\ninterface ReplaceResult {\r\n content: string;\r\n /** 命中的替换器名称 */\r\n matchedReplacer: string;\r\n /** 文件中实际匹配到的字符串(可能与 oldString 缩进/空白不同) */\r\n actualMatchedString: string;\r\n}\r\n\r\n/**\r\n * 执行替换\r\n */\r\nfunction replace(content: string, oldString: string, newString: string, replaceAll = false): ReplaceResult {\r\n if (oldString === newString) {\r\n throw new Error('No changes to apply: oldString and newString are identical.');\r\n }\r\n\r\n let notFound = true;\r\n\r\n for (const { name, fn: replacer } of REPLACERS) {\r\n for (const search of replacer(content, oldString)) {\r\n const index = content.indexOf(search);\r\n if (index === -1) continue;\r\n\r\n notFound = false;\r\n\r\n if (replaceAll) {\r\n return {\r\n content: content.replaceAll(search, newString),\r\n matchedReplacer: name,\r\n actualMatchedString: search,\r\n };\r\n }\r\n\r\n const lastIndex = content.lastIndexOf(search);\r\n if (index !== lastIndex) continue;\r\n\r\n return {\r\n content: content.substring(0, index) + newString + content.substring(index + search.length),\r\n matchedReplacer: name,\r\n actualMatchedString: search,\r\n };\r\n }\r\n }\r\n\r\n if (notFound) {\r\n throw new Error(\r\n 'Could not find oldString in the file. It must match exactly, including whitespace, indentation, and line endings.'\r\n );\r\n }\r\n\r\n throw new Error('Found multiple matches for oldString. Provide more surrounding context to make the match unique.');\r\n}\r\n\r\n/**\r\n * 文件编辑工具\r\n */\r\nexport function createEditTool(workspaceDir: string = DEFAULT_WORKSPACE_DIR) {\r\n return createTool({\r\n name: 'edit',\r\n description: 'Make exact string replacements in a file. Uses multiple intelligent matching strategies including block anchor matching, whitespace normalization, and indentation flexibility. Always provides a diff preview of changes.',\r\n render: 'edit',\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n filePath: {\r\n type: 'string',\r\n description: 'The absolute path to the file to modify'\r\n },\r\n oldString: {\r\n type: 'string',\r\n description: 'The text to replace'\r\n },\r\n newString: {\r\n type: 'string',\r\n description: 'The text to replace it with (must be different from oldString)'\r\n },\r\n replaceAll: {\r\n type: 'boolean',\r\n default: false,\r\n description: 'Replace all occurrences of oldString (default false)'\r\n }\r\n },\r\n additionalProperties: false,\r\n required: ['filePath', 'oldString', 'newString']\r\n },\r\n execute: async (args = {}) => {\r\n const filePath = normalizeNamedPathArg(args, 'filePath', 'filepath', 'path');\r\n const oldString = (args as Record<string, unknown>).oldString as string;\r\n const newString = (args as Record<string, unknown>).newString as string;\r\n const replaceAll = (args as Record<string, unknown>).replaceAll as boolean | undefined;\r\n const resolvedFilePath = resolveWorkspacePath(filePath, workspaceDir);\r\n\r\n if (oldString === newString) {\r\n throw new Error('No changes to apply: oldString and newString are identical.');\r\n }\r\n\r\n // 检查文件是否存在\r\n const exists = await stat(resolvedFilePath).then(() => true).catch(() => false);\r\n if (!exists) {\r\n throw new Error(`File not found: ${resolvedFilePath}`);\r\n }\r\n\r\n // Read-before-write 校验:必须先读才能编辑\r\n const dedupEntry = readDedupState.get(resolvedFilePath);\r\n if (!dedupEntry) {\r\n throw new Error(\r\n `File has not been read yet. Read it first before editing it: ${resolvedFilePath}`\r\n );\r\n }\r\n // Staleness 校验:文件在上次读取后被外部修改则拒绝编辑\r\n const currentMtime = (await stat(resolvedFilePath)).mtimeMs;\r\n if (currentMtime !== dedupEntry.mtimeMs) {\r\n throw new Error(\r\n `File has been modified since last read. Read the file again before editing it: ${resolvedFilePath}`\r\n );\r\n }\r\n\r\n // 读取文件,检测编码和行尾符\r\n const buffer = await readFile(resolvedFilePath, { encoding: null });\r\n const encoding = detectEncoding(buffer);\r\n const lineEndings = detectLineEndings(buffer.toString(encoding));\r\n const contentOld = buffer.toString(encoding).replaceAll('\\r\\n', '\\n');\r\n\r\n // 引号标准化:尝试将 oldString 匹配到文件中的实际字符串(可能含 curly quotes)\r\n const actualOldString = findActualString(contentOld, oldString);\r\n const effectiveOldString = actualOldString ?? oldString;\r\n\r\n const replaceResult = replace(contentOld, effectiveOldString, newString, replaceAll);\r\n const contentNew = replaceResult.content;\r\n\r\n // 当使用了非精确匹配(模糊匹配器)时,生成警告信息\r\n let warning: string | undefined;\r\n if (replaceResult.matchedReplacer !== 'simpleReplacer') {\r\n const actualLines = replaceResult.actualMatchedString.split('\\n');\r\n const providedLines = effectiveOldString.split('\\n');\r\n\r\n // 检测是否为纯缩进差异\r\n let indentOnly = true;\r\n if (actualLines.length === providedLines.length) {\r\n for (let i = 0; i < actualLines.length; i++) {\r\n if (actualLines[i].trim() !== providedLines[i].trim()) {\r\n indentOnly = false;\r\n break;\r\n }\r\n }\r\n } else {\r\n indentOnly = false;\r\n }\r\n\r\n const diffType = indentOnly ? 'indentation/whitespace' : 'content formatting';\r\n warning =\r\n `Edit applied via fuzzy matching (${replaceResult.matchedReplacer}). ` +\r\n `The oldString did not exactly match the file content — ${diffType} differs. ` +\r\n `The newString was written as-is, which may produce incorrect indentation or formatting. ` +\r\n `Please re-read the file to verify the result is correct.`;\r\n }\r\n\r\n // 生成 diff\r\n const diff = createTwoFilesPatch(resolvedFilePath, resolvedFilePath, contentOld, contentNew);\r\n\r\n // 计算变更统计\r\n let additions = 0;\r\n let deletions = 0;\r\n for (const change of diffLines(contentOld, contentNew)) {\r\n if (change.added) additions += change.count || 0;\r\n if (change.removed) deletions += change.count || 0;\r\n }\r\n\r\n // 写入文件(保留编码和行尾符)\r\n await writeTextContent(resolvedFilePath, contentNew, encoding, lineEndings);\r\n\r\n // 更新 read 去重状态(offset=undefined 表示由 Edit 设置,非 Read 产生)\r\n try {\r\n const mtimeMs = (await stat(resolvedFilePath)).mtimeMs;\r\n readDedupState.set(resolvedFilePath, { mtimeMs, offset: undefined, limit: undefined });\r\n } catch {\r\n // ignore\r\n }\r\n\r\n return withDisplay(\r\n JSON.stringify({\r\n filePath: resolvedFilePath,\r\n additions,\r\n deletions,\r\n message: warning ?? 'Edit applied successfully',\r\n ...(warning && { warning }),\r\n }),\r\n { filePath: resolvedFilePath, diff, additions, deletions }\r\n );\r\n }\r\n });\r\n}\r\n\r\nexport const editTool = createEditTool();\r\n\r\n// ============================================================================\r\n// LS Tool - 目录列表\r\n// ============================================================================\r\n\r\nconst LS_MAX_DEPTH = 2;\r\nconst LS_ROOT_LIMIT = 100;\r\nconst LS_CHILD_LIMIT = 12;\r\n\r\ntype DirectoryTreeEntry = {\r\n name: string;\r\n relativePath: string;\r\n isDirectory: boolean;\r\n children: DirectoryTreeEntry[];\r\n droppedCount: number;\r\n};\r\n\r\ninterface DirectoryTreeResult {\r\n root: DirectoryTreeEntry;\r\n fileCount: number;\r\n truncated: boolean;\r\n}\r\n\r\n/** 将常用 glob 忽略规则编译成匹配相对路径的正则表达式。 */\r\nfunction compileIgnorePattern(pattern: string): RegExp | null {\r\n let normalized = pattern.trim().replaceAll('\\\\', '/').replace(/^\\.\\//, '');\r\n if (!normalized) return null;\r\n if (normalized.endsWith('/**')) {\r\n normalized = normalized.slice(0, -3).replace(/\\/$/, '');\r\n if (!normalized) return null;\r\n return new RegExp(`^(?:${globPatternToRegexSource(normalized)})(?:/.*)?$`);\r\n }\r\n if (!/[?*[]/.test(normalized)) {\r\n return new RegExp(`^(?:${globPatternToRegexSource(normalized)})(?:/.*)?$`);\r\n }\r\n return new RegExp(`^${globPatternToRegexSource(normalized)}$`);\r\n}\r\n\r\nfunction globPatternToRegexSource(pattern: string): string {\r\n let source = '';\r\n for (let index = 0; index < pattern.length; index += 1) {\r\n const char = pattern[index];\r\n if (char === '*') {\r\n if (pattern[index + 1] === '*') {\r\n source += '.*';\r\n index += 1;\r\n } else {\r\n source += '[^/]*';\r\n }\r\n } else if (char === '?') {\r\n source += '[^/]';\r\n } else {\r\n source += char.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\r\n }\r\n }\r\n return source;\r\n}\r\n\r\nfunction shouldIgnoreDirectoryEntry(relativePath: string, patterns: readonly RegExp[]): boolean {\r\n return patterns.some(pattern => pattern.test(relativePath));\r\n}\r\n\r\nasync function buildLimitedDirectoryTree(\r\n rootPath: string,\r\n ignorePatterns: readonly string[],\r\n maxDepth = LS_MAX_DEPTH,\r\n rootLimit = LS_ROOT_LIMIT,\r\n childLimit = LS_CHILD_LIMIT,\r\n): Promise<DirectoryTreeResult> {\r\n const compiledPatterns = ignorePatterns\r\n .map(compileIgnorePattern)\r\n .filter((pattern): pattern is RegExp => pattern !== null);\r\n let fileCount = 0;\r\n let truncated = false;\r\n\r\n const visit = async (absolutePath: string, relativePath: string, depth: number): Promise<DirectoryTreeEntry[]> => {\r\n const limit = depth === 0 ? rootLimit : childLimit;\r\n const entries: DirectoryTreeEntry[] = [];\r\n let droppedCount = 0;\r\n // 目录不可读(Windows 回收站等系统目录)时按空目录继续,不中断整个列表。\r\n const directory = await opendir(absolutePath).catch(() => null);\r\n if (directory === null) return entries;\r\n const compareEntries = (left: DirectoryTreeEntry, right: DirectoryTreeEntry): number => {\r\n if (left.isDirectory !== right.isDirectory) return left.isDirectory ? -1 : 1;\r\n return left.name.localeCompare(right.name);\r\n };\r\n\r\n try {\r\n for await (const dirent of directory) {\r\n const childRelativePath = relativePath ? `${relativePath}/${dirent.name}` : dirent.name;\r\n if (shouldIgnoreDirectoryEntry(childRelativePath, compiledPatterns)) continue;\r\n\r\n const entry: DirectoryTreeEntry = {\r\n name: dirent.name,\r\n relativePath: childRelativePath,\r\n isDirectory: dirent.isDirectory(),\r\n children: [],\r\n droppedCount: 0,\r\n };\r\n const insertAt = entries.findIndex(existing => compareEntries(entry, existing) < 0);\r\n if (insertAt === -1) entries.push(entry);\r\n else entries.splice(insertAt, 0, entry);\r\n\r\n if (entries.length > limit) {\r\n entries.pop();\r\n droppedCount += 1;\r\n }\r\n }\r\n } finally {\r\n await directory.close().catch(() => {});\r\n }\r\n\r\n if (droppedCount > 0) {\r\n truncated = true;\r\n if (entries.length > 0) entries[entries.length - 1]!.droppedCount = droppedCount;\r\n }\r\n\r\n for (const entry of entries) {\r\n if (!entry.isDirectory) {\r\n fileCount += 1;\r\n continue;\r\n }\r\n if (depth >= maxDepth) continue;\r\n entry.children = await visit(path.join(rootPath, entry.relativePath), entry.relativePath, depth + 1);\r\n }\r\n\r\n return entries;\r\n };\r\n\r\n const root: DirectoryTreeEntry = {\r\n name: '.',\r\n relativePath: '',\r\n isDirectory: true,\r\n children: await visit(rootPath, '', 0),\r\n droppedCount: 0,\r\n };\r\n return { root, fileCount, truncated };\r\n}\r\n\r\nfunction renderLimitedDirectoryTree(root: DirectoryTreeEntry, rootPath: string): string {\r\n const lines = [`${rootPath}${path.sep}`];\r\n const render = (entry: DirectoryTreeEntry, depth: number): void => {\r\n const indent = ' '.repeat(depth);\r\n lines.push(`${indent}${entry.name}${entry.isDirectory ? '/' : ''}`);\r\n if (entry.droppedCount > 0) {\r\n lines.push(`${' '.repeat(depth + 1)}… ${entry.droppedCount} more`);\r\n }\r\n for (const child of entry.children) render(child, depth + 1);\r\n };\r\n for (const entry of root.children) render(entry, 0);\r\n return `${lines.join('\\n')}\\n`;\r\n}\r\n\r\n/**\r\n * 目录列表工具。只遍历有限深度,并在每个目录边界截断,避免对大仓库做全量 glob 扫描。\r\n */\r\nexport function createLsTool(workspaceDir: string = DEFAULT_WORKSPACE_DIR) {\r\n return createTool({\r\n name: 'ls',\r\n description: 'List a bounded directory tree. It shows up to two levels, ignores common build/cache directories, and truncates large directories per level.',\r\n render: 'ls',\r\n parallelizable: true,\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n dirPath: {\r\n type: 'string',\r\n description: 'The absolute path to the directory to list'\r\n },\r\n ignore: {\r\n type: 'array',\r\n items: { type: 'string' },\r\n description: 'List of glob patterns to ignore'\r\n }\r\n },\r\n additionalProperties: false,\r\n required: ['dirPath']\r\n },\r\n execute: async (args = {}) => {\r\n const dirPath = normalizeNamedPathArg(args, 'dirPath', 'dirpath', 'path', 'filePath', 'filepath');\r\n const rawIgnore = (args as Record<string, unknown>).ignore;\r\n const ignore = Array.isArray(rawIgnore) ? rawIgnore.filter((item): item is string => typeof item === 'string') : [];\r\n const resolvedDirPath = resolveWorkspacePath(dirPath, workspaceDir);\r\n const stats = await stat(resolvedDirPath).catch(() => null);\r\n if (!stats) throw new Error(`Directory not found: ${resolvedDirPath}`);\r\n if (!stats.isDirectory()) throw new Error(`Path is not a directory: ${resolvedDirPath}`);\r\n\r\n const result = await buildLimitedDirectoryTree(\r\n resolvedDirPath,\r\n [...IGNORE_PATTERNS, ...ignore.map(pattern => pattern.endsWith('/**') ? pattern : `${pattern}/**`)],\r\n );\r\n return {\r\n path: resolvedDirPath,\r\n count: result.fileCount,\r\n truncated: result.truncated,\r\n tree: renderLimitedDirectoryTree(result.root, resolvedDirPath),\r\n };\r\n }\r\n });\r\n}\r\n\r\nexport const lsTool = createLsTool();\r\n\r\n// ============================================================================\r\n// Glob Tool - 文件模式搜索\r\n// ============================================================================\r\n\r\n/**\r\n * Glob 文件搜索工具\r\n */\r\nexport function createGlobTool(workspaceDir: string = DEFAULT_WORKSPACE_DIR) {\r\n return createTool({\r\n name: 'glob',\r\n description: 'Fast file pattern matching tool that works with any codebase size. Supports glob patterns like \"**/*.js\" or \"src/**/*.ts\". Returns matching file paths sorted by modification time.',\r\n render: 'glob',\r\n parallelizable: true,\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n pattern: {\r\n type: 'string',\r\n description: 'The glob pattern to match files against'\r\n },\r\n searchPath: {\r\n type: 'string',\r\n description: 'The directory to search in (defaults to current working directory)'\r\n }\r\n },\r\n additionalProperties: false,\r\n required: ['pattern']\r\n },\r\n execute: async (args = {}) => {\r\n const pattern = (args as Record<string, unknown>).pattern as string;\r\n const searchPath = tryNamedPathArg(args, 'searchPath', 'searchpath', 'path', 'filePath', 'filepath');\r\n const resolvedSearchPath = resolveWorkspaceSearchPath(searchPath, workspaceDir);\r\n\r\n const files: Array<{ path: string; mtime: number }> = [];\r\n let truncated = false;\r\n\r\n for await (const file of globIterate(pattern, {\r\n cwd: resolvedSearchPath,\r\n absolute: true,\r\n windowsPathsNoEscape: true,\r\n nodir: true,\r\n ignore: IGNORE_PATTERNS,\r\n })) {\r\n if (files.length >= SEARCH_LIMIT) {\r\n truncated = true;\r\n break;\r\n }\r\n\r\n try {\r\n const stats = await stat(file);\r\n files.push({ path: file, mtime: stats.mtimeMs });\r\n } catch {\r\n // File may have been deleted, skip.\r\n }\r\n }\r\n\r\n files.sort((a, b) => b.mtime - a.mtime || a.path.localeCompare(b.path));\r\n\r\n return {\r\n count: files.length,\r\n truncated,\r\n files: files.map(file => file.path),\r\n };\r\n }\r\n });\r\n}\r\n\r\nexport const globTool = createGlobTool();\r\n\r\n// ============================================================================\r\n// Grep Tool - 内容搜索\r\n// ============================================================================\r\n\r\n/**\r\n * 获取 ripgrep 路径\r\n */\r\nasync function getRipgrepPath(): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n const child = spawn('rg', ['--version'], { windowsHide: true });\r\n let hasOutput = false;\r\n\r\n child.stdout.on('data', () => { hasOutput = true; });\r\n child.stderr.on('data', () => { hasOutput = true; });\r\n\r\n child.on('close', (code) => {\r\n if (hasOutput || code === 0) {\r\n resolve('rg');\r\n } else {\r\n reject(new Error('ripgrep (rg) is not installed. Please install it from https://github.com/BurntSushi/ripgrep'));\r\n }\r\n });\r\n\r\n child.on('error', () => {\r\n reject(new Error('ripgrep (rg) is not installed. Please install it from https://github.com/BurntSushi/ripgrep'));\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Grep 内容搜索工具\r\n */\r\nexport function createGrepTool(workspaceDir: string = DEFAULT_WORKSPACE_DIR) {\r\n return createTool({\r\n name: 'grep',\r\n description: 'A powerful search tool built on ripgrep. Supports full regex syntax, file type filtering, and context control. Use this tool for content searches; NEVER invoke grep or rg as Bash commands.',\r\n render: 'grep',\r\n parallelizable: true,\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n pattern: {\r\n type: 'string',\r\n description: 'The regex pattern to search for in file contents'\r\n },\r\n searchPath: {\r\n type: 'string',\r\n description: 'The directory to search in (defaults to current working directory)'\r\n },\r\n include: {\r\n type: 'string',\r\n description: 'File pattern to include in the search (e.g. \"*.js\", \"*.{ts,tsx}\")'\r\n }\r\n },\r\n additionalProperties: false,\r\n required: ['pattern']\r\n },\r\n execute: async (args = {}, context) => {\r\n const pattern = (args as Record<string, unknown>).pattern as string;\r\n const searchPath = tryNamedPathArg(args, 'searchPath', 'searchpath', 'path', 'filePath', 'filepath');\r\n const include = (args as Record<string, unknown>).include as string | undefined;\r\n const resolvedSearchPath = resolveWorkspaceSearchPath(searchPath, workspaceDir);\r\n\r\n const rgPath = await getRipgrepPath();\r\n const rgArgs = ['-nH', '--hidden', '--no-messages', '--field-match-separator=|', '--regexp', pattern];\r\n\r\n if (include) {\r\n rgArgs.push('--glob', include);\r\n }\r\n rgArgs.push(resolvedSearchPath);\r\n\r\n try {\r\n // 使用 spawn 避免在 Windows 上 shell 解析特殊字符(如 |)的问题。\r\n // 逐行消费 stdout,并在达到上限后终止 rg,避免把整个仓库的结果读入内存。\r\n const { matches, truncated } = await new Promise<{\r\n matches: Array<{ path: string; lineNum: number; lineText: string }>;\r\n truncated: boolean;\r\n }>((resolve, reject) => {\r\n const child = spawn(rgPath, rgArgs, { windowsHide: true });\r\n const collected: Array<{ path: string; lineNum: number; lineText: string }> = [];\r\n let pending = '';\r\n let truncated = false;\r\n let killRequested = false;\r\n\r\n const stopSearch = (): void => {\r\n if (killRequested) return;\r\n killRequested = true;\r\n child.kill();\r\n };\r\n\r\n const processLine = (line: string): void => {\r\n if (!line || truncated) return;\r\n const parts = line.split('|');\r\n if (parts.length < 3) return;\r\n\r\n const [filePath, lineNumStr, ...lineTextParts] = parts;\r\n const lineNum = parseInt(lineNumStr, 10);\r\n if (!filePath || !Number.isFinite(lineNum)) return;\r\n const lineText = lineTextParts.join('|');\r\n\r\n if (collected.length >= SEARCH_LIMIT) {\r\n truncated = true;\r\n stopSearch();\r\n return;\r\n }\r\n collected.push({\r\n path: filePath,\r\n lineNum,\r\n lineText: lineText.length > MAX_LINE_LENGTH ? `${lineText.substring(0, MAX_LINE_LENGTH)}...` : lineText,\r\n });\r\n };\r\n\r\n const onSearchAbort = () => {\r\n stopSearch();\r\n };\r\n if (context?.signal) {\r\n context.signal.addEventListener('abort', onSearchAbort, { once: true });\r\n }\r\n\r\n child.stdout.setEncoding('utf8');\r\n child.stdout.on('data', (chunk: string) => {\r\n pending += chunk;\r\n let newlineIndex = pending.indexOf(String.fromCharCode(10));\r\n while (newlineIndex !== -1) {\r\n processLine(pending.slice(0, newlineIndex).replace(new RegExp(String.fromCharCode(13) + '$'), ''));\r\n pending = pending.slice(newlineIndex + 1);\r\n if (killRequested) return;\r\n newlineIndex = pending.indexOf(String.fromCharCode(10));\r\n }\r\n });\r\n child.stderr.resume();\r\n\r\n child.on('error', (err) => {\r\n context?.signal?.removeEventListener('abort', onSearchAbort);\r\n reject(err);\r\n });\r\n child.on('close', (code) => {\r\n context?.signal?.removeEventListener('abort', onSearchAbort);\r\n if (context?.signal?.aborted) {\r\n reject(new Error('Search was aborted'));\r\n return;\r\n }\r\n if (!killRequested) {\r\n processLine(pending);\r\n }\r\n // code 1 表示没有匹配;被我们主动终止时的非零状态也是预期结果。\r\n if (!killRequested && code !== 0 && code !== 1) {\r\n reject(new Error(`rg exited with code ${code}`));\r\n return;\r\n }\r\n resolve({ matches: collected, truncated });\r\n });\r\n });\r\n\r\n // 按文件路径 + 行号排序\r\n matches.sort((a, b) => a.path === b.path ? a.lineNum - b.lineNum : a.path < b.path ? -1 : 1);\r\n\r\n return {\r\n pattern,\r\n matches: matches.length,\r\n truncated,\r\n results: matches,\r\n };\r\n } catch (error: any) {\r\n if (error.message?.includes('Search was aborted') || context?.signal?.aborted) {\r\n throw new Error('Search was aborted', { cause: error });\r\n }\r\n throw error;\r\n }\r\n }\r\n });\r\n}\r\n\r\nexport const grepTool = createGrepTool();\r\n\r\nexport { normalizeNamedPathArg };\r\n\r\nexport { tryNamedPathArg };\r\n\r\nexport { resolveWorkspacePath };\r\n","import { fileURLToPath } from 'url';\r\nimport { dirname } from 'path';\r\nimport type {\r\n AgentFeature,\r\n FeatureContext,\r\n FeatureInitContext,\r\n FeatureStateSnapshot,\r\n ContextInjector,\r\n PackageInfo,\r\n} from '../../core/feature.js';\r\nimport type { HookDeclarations } from '../../core/hook-declarations.js';\r\nimport { CoreLifecycle } from '../../core/lifecycle.js';\r\nimport type { Tool } from '../../core/types.js';\r\nimport type {\r\n CallStartContext,\r\n StepFinishDecisionContext,\r\n ToolContext,\r\n} from '../../core/lifecycle.js';\r\nimport { Decision } from '../../core/lifecycle.js';\r\nimport { getPackageInfoFromSource } from '../../core/feature.js';\r\nimport { createExampleTool } from './tools.js';\r\nimport type {\r\n ExampleFeatureConfig,\r\n ExampleFeatureRuntimeState,\r\n ExampleFeatureSnapshot,\r\n} from './types.js';\r\n\r\nconst __filename = fileURLToPath(import.meta.url);\r\nconst __dirname = dirname(__filename);\r\n\r\nexport class ExampleFeature implements AgentFeature {\r\n\r\n static hooks: HookDeclarations = {\r\n handleCallStart: { lifecycle: CoreLifecycle.CallStart, kind: 'observe' as const },\r\n validateExampleTool: { lifecycle: CoreLifecycle.ToolUse, kind: 'guard' as const, role: 'advisor' as const },\r\n handleStepFinish: { lifecycle: CoreLifecycle.StepFinish, kind: 'guard' as const, role: 'advisor' as const },\r\n };\r\n readonly name = 'example-feature';\r\n readonly source = __filename.replace(/\\\\/g, '/');\r\n readonly description = '示范用 Feature 骨架:展示工具、模板、上下文注入、回滚快照和反向钩子的标准写法。';\r\n\r\n private readonly config: Required<ExampleFeatureConfig>;\r\n private readonly runtime: ExampleFeatureRuntimeState = {\r\n enabled: true,\r\n counter: 0,\r\n lastInput: '',\r\n notes: [],\r\n };\r\n private logger?: FeatureInitContext['logger'];\r\n\r\n private _packageInfo: PackageInfo | null = null;\r\n\r\n constructor(config: ExampleFeatureConfig = {}) {\r\n this.config = {\r\n enabledByDefault: config.enabledByDefault ?? true,\r\n notePrefix: config.notePrefix ?? '[example]',\r\n };\r\n this.runtime.enabled = this.config.enabledByDefault;\r\n }\r\n\r\n /**\r\n * 公开 API 只保留“其他 Feature 真会读取的东西”。\r\n * 不要把整个 runtime 对象直接暴露出去。\r\n */\r\n isEnabled(): boolean {\r\n return this.runtime.enabled;\r\n }\r\n\r\n getCounter(): number {\r\n return this.runtime.counter;\r\n }\r\n\r\n listNotes(): string[] {\r\n return [...this.runtime.notes];\r\n }\r\n\r\n /**\r\n * 内部 helper 比直接在钩子和工具里散改字段更容易维护。\r\n * 如果 Feature 很简单,也可以不抽这些方法。\r\n */\r\n private appendNote(note: string): void {\r\n const normalized = note.trim();\r\n if (!normalized) return;\r\n this.runtime.notes.push(`${this.config.notePrefix} ${normalized}`.trim());\r\n }\r\n\r\n private setEnabled(enabled: boolean): void {\r\n this.runtime.enabled = enabled;\r\n }\r\n\r\n private buildReminder(): string {\r\n return `${this.config.notePrefix} example feature is active`;\r\n }\r\n\r\n getTools(): Tool[] {\r\n return [\r\n createExampleTool({\r\n getState: () => this.runtime,\r\n incrementCounter: () => {\r\n this.runtime.counter += 1;\r\n },\r\n addNote: (note: string) => {\r\n this.appendNote(note);\r\n },\r\n }),\r\n ];\r\n }\r\n\r\n /**\r\n * 获取包信息(统一打包方案)\r\n */\r\n getPackageInfo(): PackageInfo | null {\r\n if (!this._packageInfo) {\r\n this._packageInfo = getPackageInfoFromSource(this.source);\r\n }\r\n return this._packageInfo;\r\n }\r\n\r\n /**\r\n * 获取模板名称列表(统一打包方案)\r\n */\r\n getTemplateNames(): string[] {\r\n return ['example-tool'];\r\n }\r\n\r\n getContextInjectors(): Map<string | RegExp, ContextInjector> {\r\n return new Map([\r\n ['example_tool', () => ({\r\n _exampleFeature: {\r\n enabled: this.runtime.enabled,\r\n counter: this.runtime.counter,\r\n },\r\n })],\r\n ]);\r\n }\r\n\r\n async onInitiate(ctx: FeatureInitContext): Promise<void> {\r\n this.logger = ctx.logger;\r\n\r\n // 在这里做一次性初始化:\r\n // - 创建 client\r\n // - 注册数据源\r\n // - 加载配置文件\r\n // - 打印启动日志\r\n this.logger?.info('ExampleFeature initiated', {\r\n enabled: this.runtime.enabled,\r\n counter: this.runtime.counter,\r\n });\r\n\r\n // 如果 Feature 依赖其他 Feature,优先在这里拿公开 API:\r\n // const other = ctx.getFeature<SomePublicApi & AgentFeature>('other-feature');\r\n // 不要把其他 Feature 的内部字段当成稳定接口。\r\n }\r\n\r\n async onDestroy(_ctx: FeatureContext): Promise<void> {\r\n // 在这里做资源清理:\r\n // - 关闭 client\r\n // - 停止 worker / interval\r\n // - 释放文件句柄\r\n this.logger?.info('ExampleFeature destroyed');\r\n }\r\n\r\n captureState(): FeatureStateSnapshot {\r\n const snapshot: ExampleFeatureSnapshot = {\r\n enabled: this.runtime.enabled,\r\n counter: this.runtime.counter,\r\n lastInput: this.runtime.lastInput,\r\n notes: [...this.runtime.notes],\r\n };\r\n return snapshot;\r\n }\r\n\r\n restoreState(snapshot: FeatureStateSnapshot): void {\r\n const state = snapshot as ExampleFeatureSnapshot;\r\n\r\n this.runtime.enabled = Boolean(state.enabled);\r\n this.runtime.counter = typeof state.counter === 'number' ? state.counter : 0;\r\n this.runtime.lastInput = typeof state.lastInput === 'string' ? state.lastInput : '';\r\n this.runtime.notes = [...(state.notes ?? [])];\r\n }\r\n\r\n async beforeRollback(snapshot: FeatureStateSnapshot): Promise<void> {\r\n const state = snapshot as ExampleFeatureSnapshot;\r\n this.logger?.info('ExampleFeature before rollback', {\r\n restoringCounter: state.counter,\r\n });\r\n }\r\n\r\n async afterRollback(snapshot: FeatureStateSnapshot): Promise<void> {\r\n const state = snapshot as ExampleFeatureSnapshot;\r\n this.logger?.info('ExampleFeature after rollback', {\r\n restoredCounter: state.counter,\r\n });\r\n }\r\n\r\n async handleCallStart(ctx: CallStartContext): Promise<void> {\r\n this.runtime.lastInput = ctx.agent?.getUserInput() ?? ctx.input;\r\n\r\n // 典型用法:\r\n // - slash command 改写输入\r\n // - 模式切换\r\n // - 注入轻量 system reminder\r\n // - 记录当前轮的轻量状态\r\n\r\n // 示例 1:处理一个最简单的 slash command\r\n // if (this.runtime.lastInput === '/example-off') {\r\n // this.setEnabled(false);\r\n // ctx.agent?.setUserInput('');\r\n // }\r\n\r\n // 示例 2:仅在模式开启时注入提醒\r\n // if (this.runtime.enabled) {\r\n // ctx.context.add({ role: 'system', content: this.buildReminder() });\r\n // }\r\n }\r\n\r\n async validateExampleTool(ctx: ToolContext): Promise<typeof Decision.Continue | typeof Decision.Deny> {\r\n if (ctx.call.name !== 'example_tool') {\r\n return Decision.Continue;\r\n }\r\n\r\n // 典型用法:\r\n // - 校验参数\r\n // - 拦截危险工具调用\r\n // - 改写 call.arguments\r\n\r\n // 示例:模式关闭时拒绝执行\r\n // if (!this.runtime.enabled) {\r\n // return {\r\n // action: Decision.Deny,\r\n // reason: 'example feature disabled',\r\n // };\r\n // }\r\n\r\n // 示例:标准化参数后继续\r\n // if (typeof ctx.call.arguments?.note === 'string') {\r\n // ctx.call.arguments.note = ctx.call.arguments.note.trim();\r\n // }\r\n\r\n return Decision.Continue;\r\n }\r\n\r\n async handleStepFinish(_ctx: StepFinishDecisionContext): Promise<typeof Decision.Continue> {\r\n // 典型用法:\r\n // - 统计本轮是否命中特定工具\r\n // - 决定是否继续下一轮\r\n // - 更新 reminder 计数器\r\n\r\n // 示例:只有当本轮真的用了本 Feature 的工具,才更新某个计数器\r\n // const usedExampleTool = ctx.llmResponse.toolCalls?.some(call => call.name === 'example_tool');\r\n // if (usedExampleTool) {\r\n // this.appendNote('tool used in this step');\r\n // }\r\n\r\n return Decision.Continue;\r\n }\r\n}\r\n","import { createTool } from '../../core/tool.js';\r\nimport type { Tool } from '../../core/types.js';\r\nimport type { ExampleFeatureRuntimeState, ExampleFeatureToolResult } from './types.js';\r\n\r\nexport function createExampleTool(deps: {\r\n getState(): ExampleFeatureRuntimeState;\r\n incrementCounter(): void;\r\n addNote(note: string): void;\r\n}): Tool {\r\n return createTool({\r\n name: 'example_tool',\r\n description: '示范工具:展示 Feature 内部状态、模板渲染和上下文注入是如何连起来的。',\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n note: {\r\n type: 'string',\r\n description: '要记录的一条示意说明',\r\n },\r\n },\r\n required: [],\r\n },\r\n render: {\r\n call: 'example-tool',\r\n result: 'example-tool',\r\n },\r\n execute: async (args, context) => {\r\n const { note } = args as { note?: string };\r\n // 这里故意保留一个最常见的 Feature 工具结构:\r\n // 1. 读取注入的运行时上下文\r\n // 2. 更新 Feature 状态\r\n // 3. 返回纯对象,交给模板渲染\r\n const injected = (context as { _exampleFeature?: { enabled: boolean; counter: number } } | undefined)?._exampleFeature;\r\n\r\n deps.incrementCounter();\r\n if (typeof note === 'string' && note.trim()) {\r\n deps.addNote(note.trim());\r\n }\r\n\r\n const result: ExampleFeatureToolResult = {\r\n enabled: deps.getState().enabled,\r\n counter: deps.getState().counter,\r\n lastInput: deps.getState().lastInput,\r\n notes: deps.getState().notes,\r\n injected,\r\n };\r\n return result;\r\n },\r\n });\r\n}\r\n","/**\r\n * LSP Feature - Language Server Protocol 代码智能\r\n *\r\n * 为 AI agent 提供代码智能能力:跳转定义、查找引用、悬停提示等\r\n * 支持 14 种语言的 LSP 服务器,每个支持 exec / runtime 两种启动模式\r\n */\r\n\r\nimport { fileURLToPath } from 'url';\r\nimport path from 'path';\r\nimport os from 'os';\r\nimport type { AgentFeature, FeatureInitContext, FeatureManifestDefinition, PackageInfo } from '../../core/feature.js';\r\nimport type { FeatureManifestSettingProperty } from '../../core/feature.js';\r\nimport type { Tool } from '../../core/types.js';\r\nimport { getPackageInfoFromSource } from '../../core/feature.js';\r\nimport { LspClient } from './client.js';\r\nimport { SERVERS } from './servers.js';\r\nimport type { LspFeatureConfig, LspServerConfig, ServerInfo } from './types.js';\r\n\r\nconst __filename = fileURLToPath(import.meta.url);\r\n\r\nexport type { LspFeatureConfig, LspServerConfig, ServerInfo, ServerSpawnConfig, ServerDefaults } from './types.js';\r\nexport { LspClient } from './client.js';\r\nexport { SERVERS } from './servers.js';\r\n\r\nfunction createLspTools(feature: LspFeature): Tool[] {\r\n const operations = [\r\n { name: 'lsp_go_to_definition', op: 'goToDefinition', desc: 'Go to symbol definition' },\r\n { name: 'lsp_find_references', op: 'findReferences', desc: 'Find all references to a symbol' },\r\n { name: 'lsp_hover', op: 'hover', desc: 'Get type information and documentation' },\r\n { name: 'lsp_document_symbol', op: 'documentSymbol', desc: 'List all symbols in a document' },\r\n { name: 'lsp_workspace_symbol', op: 'workspaceSymbol', desc: 'Search for symbols across workspace' },\r\n { name: 'lsp_go_to_implementation', op: 'goToImplementation', desc: 'Go to interface/abstract implementations' },\r\n { name: 'lsp_prepare_call_hierarchy', op: 'prepareCallHierarchy', desc: 'Prepare call hierarchy for a symbol' },\r\n { name: 'lsp_incoming_calls', op: 'incomingCalls', desc: 'Find incoming calls to a function' },\r\n { name: 'lsp_outgoing_calls', op: 'outgoingCalls', desc: 'Find outgoing calls from a function' },\r\n ];\r\n\r\n return operations.map(({ name, op, desc }) => ({\r\n name,\r\n description: desc,\r\n parallelizable: true,\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n filePath: { type: 'string', description: 'Path to the file (relative or absolute)' },\r\n line: { type: 'number', description: '1-based line number' },\r\n character: { type: 'number', description: '1-based character position' },\r\n },\r\n required: ['filePath', 'line', 'character'],\r\n },\r\n async execute(args: Record<string, unknown>) {\r\n const { filePath: fp, line, character } = args as { filePath: string; line: number; character: number };\r\n const workdir = feature.getWorkdir();\r\n const filePath = path.isAbsolute(fp)\r\n ? fp\r\n : path.resolve(workdir, fp);\r\n\r\n const fs = await import('fs/promises');\r\n try { await fs.access(filePath); } catch { throw new Error(`File not found: ${filePath}`); }\r\n\r\n const hasServer = await feature.hasServer(filePath);\r\n if (!hasServer) throw new Error('No LSP server available for this file type.');\r\n\r\n await feature.touchFile(filePath);\r\n\r\n const position = { file: filePath, line: line - 1, character: character - 1 };\r\n const uri = `file://${filePath}`;\r\n\r\n let result: any;\r\n switch (op) {\r\n case 'goToDefinition':\r\n result = await feature.executeOnFile(filePath, (c) => c.definition(position.file, position.line, position.character));\r\n break;\r\n case 'findReferences':\r\n result = await feature.executeOnFile(filePath, (c) => c.references(position.file, position.line, position.character));\r\n break;\r\n case 'hover':\r\n result = await feature.executeOnFile(filePath, (c) => c.hover(position.file, position.line, position.character));\r\n break;\r\n case 'documentSymbol':\r\n result = await feature.executeOnFile(filePath, (c) => c.documentSymbol(uri));\r\n break;\r\n case 'workspaceSymbol':\r\n result = await feature.executeAll((c) => c.workspaceSymbol(''));\r\n break;\r\n case 'goToImplementation':\r\n result = await feature.executeOnFile(filePath, (c) => c.implementation(position.file, position.line, position.character));\r\n break;\r\n case 'prepareCallHierarchy':\r\n result = await feature.executeOnFile(filePath, (c) => c.prepareCallHierarchy(position.file, position.line, position.character));\r\n break;\r\n case 'incomingCalls':\r\n result = await feature.executeOnFile(filePath, (c) => c.incomingCalls(position.file, position.line, position.character));\r\n break;\r\n case 'outgoingCalls':\r\n result = await feature.executeOnFile(filePath, (c) => c.outgoingCalls(position.file, position.line, position.character));\r\n break;\r\n default: throw new Error(`Unknown operation: ${op}`);\r\n }\r\n\r\n const output = Array.isArray(result) && result.length === 0\r\n ? `No results found for ${op}`\r\n : JSON.stringify(result, null, 2);\r\n\r\n return {\r\n title: `${op} ${path.relative(workdir, filePath)}:${args.line}:${args.character}`,\r\n output,\r\n metadata: { result },\r\n };\r\n },\r\n }));\r\n}\r\n\r\nexport class LspFeature implements AgentFeature {\r\n readonly name = 'lsp';\r\n readonly source = __filename.replace(/\\\\/g, '/');\r\n readonly description = 'LSP (Language Server Protocol) - 提供代码智能能力:跳转定义、查找引用、悬停提示等';\r\n\r\n private config: {\r\n workdir: string;\r\n binDir: string;\r\n disableDownload: boolean;\r\n runtimes: { nodejs?: string; uv?: string };\r\n servers: Record<string, LspServerConfig>;\r\n };\r\n\r\n private _packageInfo: PackageInfo | null = null;\r\n private logger: { info: (msg: string, data?: any) => void; error: (msg: string, data?: any) => void } | null = null;\r\n\r\n private clients: Map<string, LspClient> = new Map();\r\n private spawning: Map<string, Promise<LspClient | undefined>> = new Map();\r\n private broken: Set<string> = new Set();\r\n\r\n constructor(config: LspFeatureConfig = {}) {\r\n this.config = {\r\n // eslint-disable-next-line no-restricted-syntax -- 防御性默认值,onInitiate 会用 ctx.config.workspaceDir 覆盖\r\n workdir: config.workdir || process.cwd(),\r\n binDir: config.binDir || path.join(os.homedir(), '.agentdev', 'lsp-bin'),\r\n disableDownload: config.disableDownload ?? false,\r\n runtimes: config.runtimes || {},\r\n servers: config.servers || {},\r\n };\r\n }\r\n\r\n getPackageInfo(): PackageInfo | null {\r\n if (!this._packageInfo) this._packageInfo = getPackageInfoFromSource(this.source);\r\n return this._packageInfo;\r\n }\r\n\r\n getTemplateNames(): string[] { return []; }\r\n getTools(): Tool[] { return createLspTools(this); }\r\n async getAsyncTools(_ctx: FeatureInitContext): Promise<Tool[]> { return []; }\r\n\r\n async onInitiate(ctx: FeatureInitContext): Promise<void> {\r\n this.logger = ctx.logger;\r\n\r\n // 从 Agent 的 workspaceDir 更新 workdir(覆盖构造函数的默认值)\r\n if (ctx.config?.workspaceDir) {\r\n this.config.workdir = ctx.config.workspaceDir;\r\n }\r\n\r\n if (ctx.featureConfig && typeof ctx.featureConfig === 'object') {\r\n const fc = ctx.featureConfig as Record<string, unknown>;\r\n\r\n // Extract shared runtimes\r\n if (fc.runtimes && typeof fc.runtimes === 'object') {\r\n const rt = fc.runtimes as Record<string, unknown>;\r\n if (typeof rt.nodejs === 'string' && rt.nodejs) this.config.runtimes.nodejs = rt.nodejs;\r\n if (typeof rt.uv === 'string' && rt.uv) this.config.runtimes.uv = rt.uv;\r\n }\r\n\r\n // Extract per-server config\r\n for (const serverId of Object.keys(SERVERS)) {\r\n const entry = fc[serverId];\r\n if (entry && typeof entry === 'object' && !Array.isArray(entry)) {\r\n const sc = entry as Record<string, unknown>;\r\n const existing = this.config.servers[serverId] || {};\r\n if (typeof sc.mode === 'string') (existing as any).mode = sc.mode;\r\n if (typeof sc.runtime === 'string') (existing as any).runtime = sc.runtime;\r\n if (typeof sc.binary === 'string') existing.binary = sc.binary;\r\n if (typeof sc.package === 'string') (existing as any).package = sc.package;\r\n if (typeof sc.uvPackage === 'string') (existing as any).uvPackage = sc.uvPackage;\r\n if (typeof sc.args === 'string' && sc.args.trim()) {\r\n (existing as any).args = sc.args.trim().split(/\\s+/);\r\n }\r\n this.config.servers[serverId] = existing;\r\n }\r\n }\r\n }\r\n\r\n this.logger.info('LSP Feature initialized', { workdir: this.config.workdir });\r\n }\r\n\r\n async onDestroy(): Promise<void> {\r\n this.logger?.info('LSP Feature shutting down');\r\n await this.shutdownAll();\r\n }\r\n\r\n // ── Manifest ────────────────────────────────────────────────\r\n\r\n getFeatureManifest(): FeatureManifestDefinition {\r\n const serverDefs: Array<{ id: string; name: string }> = [\r\n { id: 'typescript', name: 'TypeScript / JavaScript' },\r\n { id: 'pyright', name: 'Python (Pyright)' },\r\n { id: 'gopls', name: 'Go (gopls)' },\r\n { id: 'rust-analyzer', name: 'Rust (rust-analyzer)' },\r\n { id: 'clangd', name: 'C/C++ (clangd)' },\r\n { id: 'vue', name: 'Vue' },\r\n { id: 'svelte', name: 'Svelte' },\r\n { id: 'eslint', name: 'ESLint' },\r\n { id: 'deno', name: 'Deno' },\r\n { id: 'bash', name: 'Bash' },\r\n { id: 'yaml', name: 'YAML' },\r\n { id: 'json', name: 'JSON' },\r\n { id: 'html', name: 'HTML' },\r\n { id: 'css', name: 'CSS' },\r\n ];\r\n\r\n const properties: Record<string, FeatureManifestSettingProperty> = {\r\n runtimes: {\r\n type: 'group',\r\n title: 'Runtimes',\r\n description: 'Shared runtime paths. Leave empty to auto-detect from PATH.',\r\n properties: {\r\n nodejs: { type: 'file', title: 'Node.js', placeholder: 'Auto-detect' },\r\n uv: { type: 'file', title: 'uv / uvx', placeholder: 'Auto-detect' },\r\n },\r\n },\r\n };\r\n\r\n for (const server of serverDefs) {\r\n const defaults = SERVERS[server.id]?.defaults;\r\n properties[server.id] = {\r\n type: 'group',\r\n title: server.name,\r\n properties: {\r\n mode: {\r\n type: 'select',\r\n title: 'Mode',\r\n default: defaults?.defaultMode,\r\n options: [\r\n { label: 'Exec (Binary)', value: 'exec' },\r\n { label: 'Runtime (npx/uvx)', value: 'runtime' },\r\n ],\r\n },\r\n binary: {\r\n type: 'file',\r\n title: 'Binary',\r\n placeholder: 'Auto-detect',\r\n default: defaults?.execBinary,\r\n showWhen: { property: 'mode', values: ['exec'] },\r\n },\r\n runtime: {\r\n type: 'select',\r\n title: 'Runtime',\r\n default: defaults?.defaultRuntime || 'nodejs',\r\n options: [\r\n { label: 'Node.js (npx)', value: 'nodejs' },\r\n { label: 'uv (uvx)', value: 'uv' },\r\n ],\r\n showWhen: { property: 'mode', values: ['runtime'] },\r\n },\r\n package: {\r\n type: 'string',\r\n title: 'Package (npx)',\r\n description: defaults?.runtimePackage ? `Default: ${defaults.runtimePackage}` : '',\r\n placeholder: defaults?.runtimePackage || 'e.g. typescript-language-server',\r\n showWhen: { property: 'mode', values: ['runtime'] },\r\n },\r\n uvPackage: {\r\n type: 'string',\r\n title: 'Package (uvx)',\r\n description: defaults?.uvPackage ? `Default: ${defaults.uvPackage}` : (defaults?.runtimePackage ? `Default: ${defaults.runtimePackage}` : ''),\r\n placeholder: defaults?.uvPackage || defaults?.runtimePackage || '',\r\n showWhen: { property: 'runtime', values: ['uv'] },\r\n },\r\n args: {\r\n type: 'string',\r\n title: 'Arguments',\r\n description: defaults?.runtimeArgs?.length ? `Default: ${defaults.runtimeArgs.join(' ')}` : '',\r\n placeholder: defaults?.runtimeArgs?.join(' ') || '--stdio',\r\n },\r\n },\r\n };\r\n }\r\n\r\n return {\r\n schemaVersion: 1,\r\n settings: {\r\n properties,\r\n sections: [\r\n { id: 'runtimes', title: 'Runtimes', properties: ['runtimes'] },\r\n { id: 'lsp', title: 'Language Servers', properties: serverDefs.map(s => s.id) },\r\n ],\r\n },\r\n };\r\n }\r\n\r\n // ── State ───────────────────────────────────────────────────\r\n\r\n captureState(): { activeServerIds: string[] } {\r\n return { activeServerIds: Array.from(this.clients.keys()) };\r\n }\r\n\r\n restoreState(_state: any): void {\r\n this.logger?.info('LSP Feature state restored, servers will be started on demand');\r\n }\r\n\r\n // ── Public API ──────────────────────────────────────────────\r\n\r\n getWorkdir(): string { return this.config.workdir; }\r\n\r\n async hasServer(file: string): Promise<boolean> {\r\n const extension = path.extname(file) || file;\r\n for (const server of Object.values(SERVERS)) {\r\n const serverConfig = this.config.servers?.[server.id];\r\n if (serverConfig?.disabled) continue;\r\n if (server.extensions.length && !server.extensions.includes(extension)) continue;\r\n const root = await server.root(file, this.config.workdir);\r\n if (root) return true;\r\n }\r\n return false;\r\n }\r\n\r\n async touchFile(file: string): Promise<void> {\r\n const clients = await this.getClientsForFile(file);\r\n await Promise.all(\r\n clients.map(async (client) => {\r\n const wait = client.waitForDiagnostics(file);\r\n await client.notifyOpen(file);\r\n return wait;\r\n })\r\n ).catch((err) => {\r\n this.logger?.error('failed to touch file', { err, file });\r\n });\r\n }\r\n\r\n async executeOnFile<T>(file: string, fn: (client: LspClient) => Promise<T>): Promise<T[]> {\r\n const clients = await this.getClientsForFile(file);\r\n return Promise.all(clients.map((client) => fn(client)));\r\n }\r\n\r\n async executeAll<T>(fn: (client: LspClient) => Promise<T>): Promise<T[]> {\r\n return Promise.all(Array.from(this.clients.values()).map((client) => fn(client)));\r\n }\r\n\r\n // ── Internal ────────────────────────────────────────────────\r\n\r\n private async getClientsForFile(file: string): Promise<LspClient[]> {\r\n const extension = path.extname(file) || file;\r\n const result: LspClient[] = [];\r\n\r\n for (const server of Object.values(SERVERS)) {\r\n const serverConfig = this.config.servers?.[server.id];\r\n if (serverConfig?.disabled) continue;\r\n if (server.extensions.length && !server.extensions.includes(extension)) continue;\r\n\r\n const root = await server.root(file, this.config.workdir);\r\n if (!root) continue;\r\n\r\n const key = root + server.id;\r\n if (this.broken.has(key)) continue;\r\n\r\n const existing = this.clients.get(key);\r\n if (existing) { result.push(existing); continue; }\r\n\r\n const inflight = this.spawning.get(key);\r\n if (inflight) { const c = await inflight; if (c) result.push(c); continue; }\r\n\r\n const task = this.spawnServer(server, root, serverConfig);\r\n this.spawning.set(key, task);\r\n task.finally(() => { if (this.spawning.get(key) === task) this.spawning.delete(key); });\r\n\r\n const client = await task;\r\n if (client) result.push(client);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n private async spawnServer(\r\n server: ServerInfo,\r\n root: string,\r\n serverConfig?: LspServerConfig\r\n ): Promise<LspClient | undefined> {\r\n const key = root + server.id;\r\n const spawnConfig = {\r\n binDir: this.config.binDir,\r\n workdir: this.config.workdir,\r\n disableDownload: this.config.disableDownload,\r\n binary: serverConfig?.binary,\r\n mode: (serverConfig as any)?.mode,\r\n runtime: (serverConfig as any)?.runtime,\r\n package: (serverConfig as any)?.package,\r\n uvPackage: (serverConfig as any)?.uvPackage,\r\n args: (serverConfig as any)?.args,\r\n runtimes: this.config.runtimes,\r\n env: serverConfig?.env,\r\n initialization: serverConfig?.initialization,\r\n };\r\n\r\n let handle;\r\n try {\r\n const result = await server.spawn(root, spawnConfig);\r\n if (!result) {\r\n this.logger?.error(`LSP server ${server.id} spawn returned undefined`);\r\n this.broken.add(key);\r\n return undefined;\r\n }\r\n handle = result;\r\n } catch (err: any) {\r\n this.logger?.error(`Failed to spawn LSP server ${server.id}`, {\r\n error: err, errorMessage: err.message, errorStack: err.stack,\r\n });\r\n this.broken.add(key);\r\n return undefined;\r\n }\r\n\r\n this.logger?.info('spawned lsp server', { serverID: server.id, pid: handle.process.pid });\r\n\r\n handle.process.on('error', (err: Error) => {\r\n this.logger?.error(`LSP server ${server.id} process error`, { error: err });\r\n this.broken.add(key);\r\n this.clients.delete(key);\r\n });\r\n\r\n const client = new LspClient(server.id, handle, root, this.logger!);\r\n try {\r\n await client.initialize();\r\n } catch (err: any) {\r\n this.logger?.error(`Failed to initialize LSP client ${server.id}`, {\r\n error: err, errorMessage: err.message, errorStack: err.stack,\r\n });\r\n this.broken.add(key);\r\n try { handle.process.kill(15); } catch {}\r\n return undefined;\r\n }\r\n\r\n const existing = this.clients.get(key);\r\n if (existing) {\r\n try { handle.process.kill(15); } catch {}\r\n return existing;\r\n }\r\n\r\n this.clients.set(key, client);\r\n return client;\r\n }\r\n\r\n private async shutdownAll(): Promise<void> {\r\n await Promise.all(Array.from(this.clients.values()).map((client) => client.shutdown()));\r\n this.clients.clear();\r\n this.spawning.clear();\r\n this.broken.clear();\r\n }\r\n}\r\n","/**\r\n * LSP Client - 通过 JSON-RPC 与 LSP 服务器通信\r\n */\r\n\r\nimport { EventEmitter } from 'events';\r\nimport path from 'path';\r\nimport { readFile } from 'fs/promises';\r\nimport { pathToFileURL, fileURLToPath } from 'url';\r\nimport {\r\n createMessageConnection,\r\n StreamMessageReader,\r\n StreamMessageWriter,\r\n} from 'vscode-jsonrpc/node.js';\r\nimport type { Diagnostic } from 'vscode-languageserver-types';\r\nimport { LANGUAGE_EXTENSIONS } from './servers.js';\r\nimport type { LspServerHandle } from './types.js';\r\n\r\nconst DIAGNOSTICS_DEBOUNCE_MS = 150;\r\nconst INIT_TIMEOUT_MS = 45000;\r\nconst DIAGNOSTICS_WAIT_TIMEOUT_MS = 3000;\r\n// 单次查询请求的超时:LSP server 进程假死(活着但不回话)时,\r\n// 底层 JSON-RPC 永远不会 settle,统一在此兜底\r\nconst REQUEST_TIMEOUT_MS = 15000;\r\n\r\nfunction normalizePath(p: string): string {\r\n return p.replace(/\\\\/g, '/');\r\n}\r\n\r\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\r\n return new Promise<T>((resolve, reject) => {\r\n const timer = setTimeout(() => reject(new Error('Timeout')), ms);\r\n promise.then(\r\n (value) => {\r\n clearTimeout(timer);\r\n resolve(value);\r\n },\r\n (error) => {\r\n clearTimeout(timer);\r\n reject(error);\r\n }\r\n );\r\n });\r\n}\r\n\r\n/**\r\n * LSP Client - 处理与 LSP 服务器的 JSON-RPC 通信\r\n */\r\nexport class LspClient extends EventEmitter {\r\n private connection: any;\r\n private diagnostics: Map<string, Diagnostic[]> = new Map();\r\n private files: Record<string, number> = {};\r\n\r\n constructor(\r\n private serverID: string,\r\n private handle: LspServerHandle,\r\n private root: string,\r\n private logger: { info: (msg: string, data?: any) => void; error: (msg: string, data?: any) => void }\r\n ) {\r\n super();\r\n this.connection = createMessageConnection(\r\n new StreamMessageReader(handle.process.stdout),\r\n new StreamMessageWriter(handle.process.stdin)\r\n );\r\n this.setupHandlers();\r\n }\r\n\r\n private setupHandlers(): void {\r\n this.connection.onNotification('textDocument/publishDiagnostics', (params: any) => {\r\n const filePath = normalizePath(fileURLToPath(params.uri));\r\n this.logger.info('diagnostics received', {\r\n path: filePath,\r\n count: params.diagnostics.length,\r\n });\r\n this.diagnostics.set(filePath, params.diagnostics);\r\n this.emit('diagnostics', { path: filePath, serverID: this.serverID });\r\n });\r\n\r\n this.connection.onRequest('window/workDoneProgress/create', () => null);\r\n this.connection.onRequest('workspace/configuration', async () => [\r\n this.handle.initialization ?? {},\r\n ]);\r\n this.connection.onRequest('client/registerCapability', async () => {});\r\n this.connection.onRequest('client/unregisterCapability', async () => {});\r\n this.connection.onRequest('workspace/workspaceFolders', async () => [\r\n { name: 'workspace', uri: pathToFileURL(this.root).href },\r\n ]);\r\n }\r\n\r\n async initialize(): Promise<void> {\r\n this.connection.listen();\r\n this.logger.info('sending initialize');\r\n\r\n await withTimeout(\r\n this.connection.sendRequest('initialize', {\r\n rootUri: pathToFileURL(this.root).href,\r\n processId: this.handle.process.pid,\r\n workspaceFolders: [{ name: 'workspace', uri: pathToFileURL(this.root).href }],\r\n initializationOptions: { ...this.handle.initialization },\r\n capabilities: {\r\n window: { workDoneProgress: true },\r\n workspace: {\r\n configuration: true,\r\n didChangeWatchedFiles: { dynamicRegistration: true },\r\n },\r\n textDocument: {\r\n synchronization: { didOpen: true, didChange: true },\r\n publishDiagnostics: { versionSupport: true },\r\n },\r\n },\r\n }),\r\n INIT_TIMEOUT_MS\r\n );\r\n\r\n await this.connection.sendNotification('initialized', {});\r\n\r\n if (this.handle.initialization) {\r\n await this.connection.sendNotification('workspace/didChangeConfiguration', {\r\n settings: this.handle.initialization,\r\n });\r\n }\r\n\r\n this.logger.info('initialized');\r\n }\r\n\r\n get serverId(): string {\r\n return this.serverID;\r\n }\r\n\r\n get clientRoot(): string {\r\n return this.root;\r\n }\r\n\r\n getDiagnostics(): Map<string, Diagnostic[]> {\r\n return this.diagnostics;\r\n }\r\n\r\n async notifyOpen(filePath: string): Promise<void> {\r\n filePath = path.isAbsolute(filePath) ? filePath : path.resolve(this.root, filePath);\r\n const text = await readFile(filePath, 'utf-8');\r\n const extension = path.extname(filePath);\r\n const languageId = LANGUAGE_EXTENSIONS[extension] ?? 'plaintext';\r\n const version = this.files[filePath];\r\n\r\n if (version !== undefined) {\r\n await this.connection.sendNotification('workspace/didChangeWatchedFiles', {\r\n changes: [{ uri: pathToFileURL(filePath).href, type: 2 }],\r\n });\r\n const next = version + 1;\r\n this.files[filePath] = next;\r\n await this.connection.sendNotification('textDocument/didChange', {\r\n textDocument: { uri: pathToFileURL(filePath).href, version: next },\r\n contentChanges: [{ text }],\r\n });\r\n } else {\r\n await this.connection.sendNotification('workspace/didChangeWatchedFiles', {\r\n changes: [{ uri: pathToFileURL(filePath).href, type: 1 }],\r\n });\r\n this.diagnostics.delete(filePath);\r\n await this.connection.sendNotification('textDocument/didOpen', {\r\n textDocument: {\r\n uri: pathToFileURL(filePath).href,\r\n languageId,\r\n version: 0,\r\n text,\r\n },\r\n });\r\n this.files[filePath] = 0;\r\n }\r\n }\r\n\r\n async waitForDiagnostics(filePath: string): Promise<void> {\r\n const normalizedPath = normalizePath(\r\n path.isAbsolute(filePath) ? filePath : path.resolve(this.root, filePath)\r\n );\r\n\r\n return withTimeout(\r\n new Promise<void>((resolve) => {\r\n let debounceTimer: NodeJS.Timeout;\r\n const handler = (data: { path: string; serverID: string }) => {\r\n if (data.path === normalizedPath && data.serverID === this.serverID) {\r\n if (debounceTimer) clearTimeout(debounceTimer);\r\n debounceTimer = setTimeout(() => {\r\n this.off('diagnostics', handler);\r\n resolve();\r\n }, DIAGNOSTICS_DEBOUNCE_MS);\r\n }\r\n };\r\n this.on('diagnostics', handler);\r\n }),\r\n DIAGNOSTICS_WAIT_TIMEOUT_MS\r\n ).catch(() => {});\r\n }\r\n\r\n // LSP request methods\r\n\r\n /**\r\n * 带超时的查询请求:超时或出错时降级为 fallback 值(与既有 catch 语义一致),\r\n * 避免语言服务器无响应时请求永久挂起。\r\n */\r\n private sendRequestWithTimeout(method: string, params: unknown, fallback: unknown): Promise<unknown> {\r\n return withTimeout(this.connection.sendRequest(method, params), REQUEST_TIMEOUT_MS).catch(() => fallback);\r\n }\r\n\r\n async definition(filePath: string, line: number, character: number): Promise<unknown> {\r\n return this.sendRequestWithTimeout('textDocument/definition', {\r\n textDocument: { uri: pathToFileURL(filePath).href },\r\n position: { line, character },\r\n }, null);\r\n }\r\n\r\n async references(filePath: string, line: number, character: number): Promise<unknown> {\r\n return this.sendRequestWithTimeout('textDocument/references', {\r\n textDocument: { uri: pathToFileURL(filePath).href },\r\n position: { line, character },\r\n context: { includeDeclaration: true },\r\n }, []);\r\n }\r\n\r\n async hover(filePath: string, line: number, character: number): Promise<unknown> {\r\n return this.sendRequestWithTimeout('textDocument/hover', {\r\n textDocument: { uri: pathToFileURL(filePath).href },\r\n position: { line, character },\r\n }, null);\r\n }\r\n\r\n async documentSymbol(uri: string): Promise<unknown> {\r\n return this.sendRequestWithTimeout('textDocument/documentSymbol', { textDocument: { uri } }, []);\r\n }\r\n\r\n async workspaceSymbol(query: string): Promise<unknown> {\r\n return this.sendRequestWithTimeout('workspace/symbol', { query }, []);\r\n }\r\n\r\n async implementation(filePath: string, line: number, character: number): Promise<unknown> {\r\n return this.sendRequestWithTimeout('textDocument/implementation', {\r\n textDocument: { uri: pathToFileURL(filePath).href },\r\n position: { line, character },\r\n }, null);\r\n }\r\n\r\n async prepareCallHierarchy(filePath: string, line: number, character: number): Promise<unknown> {\r\n return this.sendRequestWithTimeout('textDocument/prepareCallHierarchy', {\r\n textDocument: { uri: pathToFileURL(filePath).href },\r\n position: { line, character },\r\n }, []);\r\n }\r\n\r\n async incomingCalls(filePath: string, line: number, character: number): Promise<unknown> {\r\n return this.sendRequestWithTimeout('callHierarchy/incomingCalls', {\r\n item: {\r\n uri: pathToFileURL(filePath).href,\r\n range: {\r\n start: { line, character },\r\n end: { line, character },\r\n },\r\n },\r\n }, []);\r\n }\r\n\r\n async outgoingCalls(filePath: string, line: number, character: number): Promise<unknown> {\r\n return this.sendRequestWithTimeout('callHierarchy/outgoingCalls', {\r\n item: {\r\n uri: pathToFileURL(filePath).href,\r\n range: {\r\n start: { line, character },\r\n end: { line, character },\r\n },\r\n },\r\n }, []);\r\n }\r\n\r\n async shutdown(): Promise<void> {\r\n try {\r\n await this.connection.sendRequest('shutdown');\r\n await this.connection.sendNotification('exit');\r\n } catch (error) {\r\n this.logger.error('Error during LSP shutdown', { error });\r\n }\r\n this.connection.dispose();\r\n }\r\n}\r\n","/**\r\n * LSP 服务器定义\r\n *\r\n * 支持 14 种语言的 LSP 服务器\r\n * 每个服务器通过 ServerDefaults 声明启动模式与包名,\r\n * resolveSpawn() 根据 mode/runtime 统一派生 spawn 参数。\r\n */\r\n\r\nimport { spawn } from 'child_process';\r\nimport path from 'path';\r\nimport { access } from 'fs/promises';\r\nimport type { ServerInfo, ServerSpawnConfig, ServerDefaults } from './types.js';\r\nimport { findExecutable } from './which.js';\r\n\r\nasync function pathExists(filePath: string): Promise<boolean> {\r\n try {\r\n await access(filePath);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nexport const LANGUAGE_EXTENSIONS: Record<string, string> = {\r\n '.abap': 'abap', '.bat': 'bat', '.bib': 'bibtex', '.clj': 'clojure',\r\n '.cljs': 'clojure', '.cljc': 'clojure', '.coffee': 'coffeescript',\r\n '.c': 'c', '.cpp': 'cpp', '.cxx': 'cpp', '.cc': 'cpp',\r\n '.cs': 'csharp', '.css': 'css', '.d': 'd', '.pas': 'pascal',\r\n '.diff': 'diff', '.patch': 'diff', '.dart': 'dart',\r\n '.dockerfile': 'dockerfile', '.ex': 'elixir', '.exs': 'elixir',\r\n '.erl': 'erlang', '.hrl': 'erlang', '.fs': 'fsharp', '.fsi': 'fsharp',\r\n '.fsx': 'fsharp', '.go': 'go', '.groovy': 'groovy', '.gleam': 'gleam',\r\n '.hbs': 'handlebars', '.hs': 'haskell', '.lhs': 'haskell',\r\n '.html': 'html', '.htm': 'html', '.ini': 'ini', '.java': 'java',\r\n '.js': 'javascript', '.kt': 'kotlin', '.kts': 'kotlin',\r\n '.jsx': 'javascriptreact', '.json': 'json', '.tex': 'latex',\r\n '.less': 'less', '.lua': 'lua', '.md': 'markdown', '.markdown': 'markdown',\r\n '.m': 'objective-c', '.mm': 'objective-cpp', '.pl': 'perl', '.pm': 'perl',\r\n '.php': 'php', '.ps1': 'powershell', '.py': 'python', '.r': 'r',\r\n '.rb': 'ruby', '.rake': 'ruby', '.gemspec': 'ruby', '.erb': 'erb',\r\n '.rs': 'rust', '.scss': 'scss', '.sass': 'sass', '.scala': 'scala',\r\n '.sh': 'shellscript', '.bash': 'shellscript', '.zsh': 'shellscript',\r\n '.sql': 'sql', '.svelte': 'svelte', '.swift': 'swift',\r\n '.ts': 'typescript', '.tsx': 'typescriptreact', '.mts': 'typescript',\r\n '.cts': 'typescript', '.xml': 'xml', '.yaml': 'yaml', '.yml': 'yaml',\r\n '.mjs': 'javascript', '.cjs': 'javascript', '.vue': 'vue',\r\n '.zig': 'zig', '.astro': 'astro', '.ml': 'ocaml', '.mli': 'ocaml',\r\n '.tf': 'terraform', '.nix': 'nix',\r\n};\r\n\r\nfunction nearestRoot(\r\n markers: string[],\r\n excludeMarkers?: string[]\r\n): (file: string) => Promise<string | undefined> {\r\n return async (file: string) => {\r\n let current = path.dirname(file);\r\n while (true) {\r\n for (const marker of markers) {\r\n if (await pathExists(path.join(current, marker))) {\r\n if (excludeMarkers) {\r\n for (const exclude of excludeMarkers) {\r\n if (await pathExists(path.join(current, exclude))) {\r\n return undefined;\r\n }\r\n }\r\n }\r\n return current;\r\n }\r\n }\r\n const parent = path.dirname(current);\r\n if (parent === current) break;\r\n current = parent;\r\n }\r\n return undefined;\r\n };\r\n}\r\n\r\n// ── resolveSpawn ────────────────────────────────────────────────\r\n\r\nfunction resolveSpawn(\r\n defaults: ServerDefaults,\r\n config: ServerSpawnConfig,\r\n root: string,\r\n extraInit?: Record<string, any>\r\n): { process: any; initialization?: Record<string, any> } | undefined {\r\n const mode = config.mode || defaults.defaultMode;\r\n const args = config.args || [];\r\n\r\n if (mode === 'exec') {\r\n const bin = config.binary || findExecutable(defaults.execBinary || '');\r\n if (!bin) return undefined;\r\n const proc = spawn(bin, [...(defaults.execArgs || []), ...args], {\r\n cwd: root,\r\n env: { ...process.env, ...config.env },\r\n });\r\n return { process: proc, initialization: { ...extraInit, ...config.initialization } };\r\n }\r\n\r\n // runtime mode\r\n const runtime = config.runtime || defaults.defaultRuntime || 'nodejs';\r\n\r\n if (runtime === 'uv') {\r\n const bin = config.runtimes?.uv || findExecutable('uv');\r\n if (!bin) return undefined;\r\n const pkg = config.uvPackage || config.package || defaults.uvPackage || defaults.runtimePackage || '';\r\n const proc = spawn(bin, ['tool', 'run', ...(pkg ? [pkg] : []), ...(defaults.runtimeArgs || []), ...args], {\r\n cwd: root,\r\n env: { ...process.env, ...config.env },\r\n });\r\n return { process: proc, initialization: { ...extraInit, ...config.initialization } };\r\n }\r\n\r\n // nodejs — npx semantics\r\n const npxBin = config.runtimes?.nodejs\r\n ? path.join(path.dirname(config.runtimes.nodejs), process.platform === 'win32' ? 'npx.cmd' : 'npx')\r\n : findExecutable('npx');\r\n if (!npxBin) return undefined;\r\n const pkg = config.package || defaults.runtimePackage || '';\r\n const proc = spawn(npxBin, ['-y', ...(pkg ? [pkg] : []), ...(defaults.runtimeArgs || []), ...args], {\r\n cwd: root,\r\n env: { ...process.env, ...config.env },\r\n shell: true,\r\n });\r\n return { process: proc, initialization: { ...extraInit, ...config.initialization } };\r\n}\r\n\r\n// ── Server definitions ──────────────────────────────────────────\r\n\r\nexport const Typescript: ServerInfo = {\r\n id: 'typescript',\r\n defaults: {\r\n defaultMode: 'runtime', defaultRuntime: 'nodejs',\r\n execBinary: 'typescript-language-server', execArgs: ['--stdio'],\r\n runtimePackage: 'typescript-language-server', runtimeArgs: ['--stdio'],\r\n },\r\n root: nearestRoot(\r\n ['package-lock.json', 'bun.lockb', 'bun.lock', 'pnpm-lock.yaml', 'yarn.lock'],\r\n ['deno.json', 'deno.jsonc']\r\n ),\r\n extensions: ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.mts', '.cts'],\r\n async spawn(root, config) {\r\n return resolveSpawn(this.defaults, config, root);\r\n },\r\n};\r\n\r\nexport const Python: ServerInfo = {\r\n id: 'pyright',\r\n defaults: {\r\n defaultMode: 'runtime', defaultRuntime: 'nodejs',\r\n execBinary: 'pyright-langserver', execArgs: ['--stdio'],\r\n runtimePackage: 'pyright-langserver', runtimeArgs: ['--stdio'],\r\n uvPackage: 'pyright',\r\n },\r\n root: nearestRoot([\r\n 'pyproject.toml', 'setup.py', 'setup.cfg', 'requirements.txt', 'Pipfile', 'pyrightconfig.json',\r\n ]),\r\n extensions: ['.py', '.pyi'],\r\n async spawn(root, config) {\r\n const initialization: Record<string, any> = {};\r\n const venvPaths = [\r\n process.env.VIRTUAL_ENV,\r\n path.join(root, '.venv'),\r\n path.join(root, 'venv'),\r\n ].filter(Boolean) as string[];\r\n for (const venvPath of venvPaths) {\r\n const pythonPath =\r\n process.platform === 'win32'\r\n ? path.join(venvPath, 'Scripts', 'python.exe')\r\n : path.join(venvPath, 'bin', 'python');\r\n if (await pathExists(pythonPath)) {\r\n initialization.pythonPath = pythonPath;\r\n break;\r\n }\r\n }\r\n return resolveSpawn(this.defaults, config, root, initialization);\r\n },\r\n};\r\n\r\nexport const Go: ServerInfo = {\r\n id: 'gopls',\r\n defaults: {\r\n defaultMode: 'exec',\r\n execBinary: 'gopls',\r\n },\r\n root: async (file: string) => {\r\n const workRoot = await nearestRoot(['go.work'])(file);\r\n if (workRoot) return workRoot;\r\n return nearestRoot(['go.mod', 'go.sum'])(file);\r\n },\r\n extensions: ['.go'],\r\n async spawn(root, config) {\r\n return resolveSpawn(this.defaults, config, root);\r\n },\r\n};\r\n\r\nexport const Rust: ServerInfo = {\r\n id: 'rust-analyzer',\r\n defaults: {\r\n defaultMode: 'exec',\r\n execBinary: 'rust-analyzer',\r\n },\r\n root: nearestRoot(['Cargo.toml', 'Cargo.lock']),\r\n extensions: ['.rs'],\r\n async spawn(root, config) {\r\n return resolveSpawn(this.defaults, config, root);\r\n },\r\n};\r\n\r\nexport const Clangd: ServerInfo = {\r\n id: 'clangd',\r\n defaults: {\r\n defaultMode: 'exec',\r\n execBinary: 'clangd',\r\n execArgs: ['--background-index', '--clang-tidy'],\r\n },\r\n root: nearestRoot(['compile_commands.json', 'compile_flags.txt', '.clangd', 'CMakeLists.txt', 'Makefile']),\r\n extensions: ['.c', '.cpp', '.cc', '.cxx', '.h', '.hpp', '.hh', '.hxx'],\r\n async spawn(root, config) {\r\n return resolveSpawn(this.defaults, config, root);\r\n },\r\n};\r\n\r\nexport const Vue: ServerInfo = {\r\n id: 'vue',\r\n defaults: {\r\n defaultMode: 'runtime', defaultRuntime: 'nodejs',\r\n execBinary: 'vue-language-server', execArgs: ['--stdio'],\r\n runtimePackage: '@vue/language-server', runtimeArgs: ['--stdio'],\r\n },\r\n root: nearestRoot(['package-lock.json', 'bun.lockb', 'bun.lock', 'pnpm-lock.yaml', 'yarn.lock']),\r\n extensions: ['.vue'],\r\n async spawn(root, config) {\r\n return resolveSpawn(this.defaults, config, root);\r\n },\r\n};\r\n\r\nexport const Svelte: ServerInfo = {\r\n id: 'svelte',\r\n defaults: {\r\n defaultMode: 'runtime', defaultRuntime: 'nodejs',\r\n execBinary: 'svelteserver', execArgs: ['--stdio'],\r\n runtimePackage: 'svelte-language-server', runtimeArgs: ['--stdio'],\r\n },\r\n root: nearestRoot(['package-lock.json', 'bun.lockb', 'bun.lock', 'pnpm-lock.yaml', 'yarn.lock']),\r\n extensions: ['.svelte'],\r\n async spawn(root, config) {\r\n return resolveSpawn(this.defaults, config, root);\r\n },\r\n};\r\n\r\nexport const ESLint: ServerInfo = {\r\n id: 'eslint',\r\n defaults: {\r\n defaultMode: 'runtime', defaultRuntime: 'nodejs',\r\n runtimePackage: 'vscode-eslint-language-server', runtimeArgs: ['--stdio'],\r\n },\r\n root: nearestRoot(['package-lock.json', 'bun.lockb', 'bun.lock', 'pnpm-lock.yaml', 'yarn.lock']),\r\n extensions: ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.mts', '.cts', '.vue'],\r\n async spawn(root, config) {\r\n const localBin = path.join(root, 'node_modules', '.bin', 'eslint');\r\n if (!(await pathExists(localBin))) return undefined;\r\n return resolveSpawn(this.defaults, config, root);\r\n },\r\n};\r\n\r\nexport const Deno: ServerInfo = {\r\n id: 'deno',\r\n defaults: {\r\n defaultMode: 'exec',\r\n execBinary: 'deno',\r\n execArgs: ['lsp'],\r\n },\r\n root: async (file: string) => {\r\n const files = ['deno.json', 'deno.jsonc'];\r\n let current = path.dirname(file);\r\n while (true) {\r\n for (const f of files) {\r\n if (await pathExists(path.join(current, f))) return current;\r\n }\r\n const parent = path.dirname(current);\r\n if (parent === current) break;\r\n current = parent;\r\n }\r\n return undefined;\r\n },\r\n extensions: ['.ts', '.tsx', '.js', '.jsx', '.mjs'],\r\n async spawn(root, config) {\r\n return resolveSpawn(this.defaults, config, root);\r\n },\r\n};\r\n\r\nexport const Bash: ServerInfo = {\r\n id: 'bash',\r\n defaults: {\r\n defaultMode: 'runtime', defaultRuntime: 'nodejs',\r\n execBinary: 'bash-language-server', execArgs: ['start'],\r\n runtimePackage: 'bash-language-server', runtimeArgs: ['start'],\r\n },\r\n root: async (_file, workspaceDir) => workspaceDir,\r\n extensions: ['.sh', '.bash', '.zsh', '.ksh'],\r\n async spawn(root, config) {\r\n return resolveSpawn(this.defaults, config, root);\r\n },\r\n};\r\n\r\nexport const Yaml: ServerInfo = {\r\n id: 'yaml',\r\n defaults: {\r\n defaultMode: 'runtime', defaultRuntime: 'nodejs',\r\n execBinary: 'yaml-language-server', execArgs: ['--stdio'],\r\n runtimePackage: 'yaml-language-server', runtimeArgs: ['--stdio'],\r\n },\r\n root: async (_file, workspaceDir) => workspaceDir,\r\n extensions: ['.yaml', '.yml'],\r\n async spawn(root, config) {\r\n return resolveSpawn(this.defaults, config, root);\r\n },\r\n};\r\n\r\nexport const Json: ServerInfo = {\r\n id: 'json',\r\n defaults: {\r\n defaultMode: 'runtime', defaultRuntime: 'nodejs',\r\n execBinary: 'vscode-json-language-server', execArgs: ['--stdio'],\r\n runtimePackage: 'vscode-languageserver-json', runtimeArgs: ['--stdio'],\r\n },\r\n root: async (_file, workspaceDir) => workspaceDir,\r\n extensions: ['.json', '.jsonc'],\r\n async spawn(root, config) {\r\n return resolveSpawn(this.defaults, config, root);\r\n },\r\n};\r\n\r\nexport const Html: ServerInfo = {\r\n id: 'html',\r\n defaults: {\r\n defaultMode: 'runtime', defaultRuntime: 'nodejs',\r\n execBinary: 'vscode-html-language-server', execArgs: ['--stdio'],\r\n runtimePackage: 'vscode-languageserver-html', runtimeArgs: ['--stdio'],\r\n },\r\n root: async (_file, workspaceDir) => workspaceDir,\r\n extensions: ['.html', '.htm'],\r\n async spawn(root, config) {\r\n return resolveSpawn(this.defaults, config, root);\r\n },\r\n};\r\n\r\nexport const Css: ServerInfo = {\r\n id: 'css',\r\n defaults: {\r\n defaultMode: 'runtime', defaultRuntime: 'nodejs',\r\n execBinary: 'vscode-css-language-server', execArgs: ['--stdio'],\r\n runtimePackage: 'vscode-languageserver-css', runtimeArgs: ['--stdio'],\r\n },\r\n root: async (_file, workspaceDir) => workspaceDir,\r\n extensions: ['.css', '.scss', '.less'],\r\n async spawn(root, config) {\r\n return resolveSpawn(this.defaults, config, root);\r\n },\r\n};\r\n\r\nexport const SERVERS: Record<string, ServerInfo> = {\r\n typescript: Typescript,\r\n pyright: Python,\r\n gopls: Go,\r\n 'rust-analyzer': Rust,\r\n clangd: Clangd,\r\n vue: Vue,\r\n svelte: Svelte,\r\n eslint: ESLint,\r\n deno: Deno,\r\n bash: Bash,\r\n yaml: Yaml,\r\n json: Json,\r\n html: Html,\r\n css: Css,\r\n};\r\n","/**\r\n * 跨平台可执行文件查找\r\n *\r\n * Windows 使用 `where`,其他平台使用 `which`。\r\n * 返回第一个匹配的路径,找不到返回 undefined。\r\n */\r\n\r\nimport { execSync } from 'child_process';\r\n\r\nexport function findExecutable(command: string): string | undefined {\r\n if (!command) return undefined;\r\n try {\r\n const isWin = process.platform === 'win32';\r\n const cmd = isWin ? `where ${command}` : `which ${command}`;\r\n const result = execSync(cmd, {\r\n encoding: 'utf-8',\r\n stdio: ['pipe', 'pipe', 'pipe'],\r\n }).trim();\r\n if (!result) return undefined;\r\n return result.split(/\\r?\\n/)[0].trim() || undefined;\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n","/**\r\n * OutputGuard Feature - 工具输出安全网\r\n *\r\n * 框架级 Feature,通过 ToolResultTransform 钩子在工具结果写入 context 前进行截断。\r\n *\r\n * 设计层次:\r\n * - Layer 0(工具自截断):工具在自己的 execute() 中自行截断(如 shell 的 30K)。\r\n * 只要结果在 hardLimit 以下,OutputGuard 不会介入。\r\n * - Layer 1(安全网):OutputGuard 在 ToolResultTransform 钩子中捕获超限结果,\r\n * 使用级联截断策略(JSON 字段截断 → 行感知 head+tail → 字符 head+tail)。\r\n *\r\n * @example\r\n * ```typescript\r\n * import { OutputGuardFeature } from '@agentdevjs/core';\r\n * const agent = new Agent({ ... }).use(new OutputGuardFeature());\r\n * ```\r\n */\r\n\r\nimport { fileURLToPath } from 'url';\r\nimport { dirname, join } from 'path';\r\nimport { mkdir, writeFile } from 'fs/promises';\r\n\r\nconst __filename = fileURLToPath(import.meta.url);\r\nconst __dirname = dirname(__filename);\r\n\r\nimport type {\r\n AgentFeature,\r\n FeatureInitContext,\r\n FeatureContext,\r\n ContextInjector,\r\n PackageInfo,\r\n FeatureStateSnapshot,\r\n} from '../../core/feature.js';\r\nimport type { HookDeclarations } from '../../core/hook-declarations.js';\r\nimport { CoreLifecycle } from '../../core/lifecycle.js';\r\nimport type { Tool } from '../../core/types.js';\r\nimport type { ToolResultTransformContext } from '../../core/lifecycle.js';\r\nimport type { ToolExecResult } from '../../core/context.js';\r\nimport { getPackageInfoFromSource } from '../../core/feature.js';\r\nimport {\r\n truncateOutput,\r\n DEFAULT_HARD_LIMIT,\r\n DEFAULT_FIELD_LIMIT,\r\n} from './truncate.js';\r\nimport type { TruncateOptions } from './truncate.js';\r\n\r\n// ========== 类型定义 ==========\r\n\r\nexport interface OutputGuardConfig {\r\n /** 总体积硬限制(默认 50000 字符) */\r\n hardLimit?: number;\r\n /** 单个字符串字段截断长度(默认 5000 字符) */\r\n fieldLimit?: number;\r\n /** 按工具名覆盖配置 */\r\n toolOverrides?: Record<string, { hardLimit?: number; fieldLimit?: number }>;\r\n /** 工作目录,用于持久化截断内容(默认 process.cwd()) */\r\n workdir?: string;\r\n}\r\n\r\n// ========== Feature 实现 ==========\r\n\r\nexport class OutputGuardFeature implements AgentFeature {\r\n\r\n static hooks: HookDeclarations = {\r\n handleToolResultTransform: { lifecycle: CoreLifecycle.ToolResultTransform, kind: 'transform' as const },\r\n };\r\n readonly name = 'output-guard';\r\n readonly source = __filename.replace(/\\\\/g, '/');\r\n readonly description =\r\n '工具输出安全网:在工具结果写入 context 前截断超限输出,防止上下文溢出。';\r\n\r\n private readonly config: Required<Omit<OutputGuardConfig, 'toolOverrides'>> & {\r\n toolOverrides: Record<string, { hardLimit?: number; fieldLimit?: number }>;\r\n };\r\n\r\n private logger?: FeatureInitContext['logger'];\r\n private _packageInfo: PackageInfo | null = null;\r\n private truncateCount = 0;\r\n\r\n constructor(config: OutputGuardConfig = {}) {\r\n this.config = {\r\n hardLimit: config.hardLimit ?? DEFAULT_HARD_LIMIT,\r\n fieldLimit: config.fieldLimit ?? DEFAULT_FIELD_LIMIT,\r\n // eslint-disable-next-line no-restricted-syntax -- 防御性默认值,仅用于临时文件落盘目录;宿主应显式传 workdir\r\n workdir: config.workdir ?? process.cwd(),\r\n toolOverrides: config.toolOverrides ?? {},\r\n };\r\n }\r\n\r\n // ========== AgentFeature 接口实现 ==========\r\n\r\n getTools(): Tool[] {\r\n return []; // 纯钩子 Feature,不注册工具\r\n }\r\n\r\n getPackageInfo(): PackageInfo | null {\r\n if (!this._packageInfo) {\r\n this._packageInfo = getPackageInfoFromSource(this.source);\r\n }\r\n return this._packageInfo;\r\n }\r\n\r\n getTemplateNames(): string[] {\r\n return [];\r\n }\r\n\r\n getContextInjectors(): Map<string | RegExp, ContextInjector> {\r\n return new Map();\r\n }\r\n\r\n async onInitiate(ctx: FeatureInitContext): Promise<void> {\r\n this.logger = ctx.logger;\r\n this.logger?.info('OutputGuardFeature initiated', {\r\n hardLimit: this.config.hardLimit,\r\n fieldLimit: this.config.fieldLimit,\r\n });\r\n }\r\n\r\n async onDestroy(_ctx: FeatureContext): Promise<void> {\r\n this.logger?.info('OutputGuardFeature destroyed', {\r\n totalTruncations: this.truncateCount,\r\n });\r\n }\r\n\r\n captureState(): FeatureStateSnapshot {\r\n return { truncateCount: this.truncateCount };\r\n }\r\n\r\n restoreState(snapshot: FeatureStateSnapshot): void {\r\n const state = snapshot as { truncateCount?: number } | null;\r\n this.truncateCount = typeof state?.truncateCount === 'number' ? state.truncateCount : 0;\r\n }\r\n\r\n async beforeRollback(_snapshot: FeatureStateSnapshot): Promise<void> {}\r\n async afterRollback(_snapshot: FeatureStateSnapshot): Promise<void> {}\r\n\r\n // ========== ToolResultTransform 钩子 ==========\r\n\r\n async handleToolResultTransform(\r\n ctx: ToolResultTransformContext,\r\n ): Promise<ToolExecResult | undefined> {\r\n const { result, toolName } = ctx;\r\n\r\n // 只处理成功的结果(错误结果通常很短)\r\n if (!result.success) return undefined;\r\n\r\n // result.result 可能是 string 或 Record<string, any>\r\n // 统一转为字符串进行截断判断\r\n const rawResult = result.result;\r\n const resultStr = typeof rawResult === 'string'\r\n ? rawResult\r\n : JSON.stringify(rawResult);\r\n\r\n // 获取该工具的配置覆盖\r\n const options = this.getOptions(toolName);\r\n\r\n // 执行截断\r\n const truncateResult = truncateOutput(resultStr, options);\r\n\r\n // 不超限,不修改\r\n if (!truncateResult.truncated) return undefined;\r\n\r\n // 记录截断\r\n this.truncateCount++;\r\n this.logger?.warn('Tool output truncated', {\r\n toolName,\r\n strategy: truncateResult.strategy,\r\n originalLength: truncateResult.originalLength,\r\n truncatedLength: truncateResult.truncatedLength,\r\n });\r\n\r\n // 持久化完整输出到磁盘,并将文件路径注入截断结果\r\n const finalOutput = await this.persistAndAnnotate(\r\n truncateResult.output,\r\n truncateResult.strategy,\r\n resultStr,\r\n truncateResult.originalLength,\r\n toolName,\r\n );\r\n\r\n // 返回截断后的结果\r\n return {\r\n ...result,\r\n result: finalOutput,\r\n };\r\n }\r\n\r\n // ========== 内部方法 ==========\r\n\r\n private getOptions(toolName: string): TruncateOptions {\r\n const override = this.config.toolOverrides[toolName];\r\n return {\r\n hardLimit: override?.hardLimit ?? this.config.hardLimit,\r\n fieldLimit: override?.fieldLimit ?? this.config.fieldLimit,\r\n };\r\n }\r\n\r\n /**\r\n * 将完整输出持久化到磁盘,并在截断结果中注入文件路径引用。\r\n *\r\n * - JSON 结果:在顶层对象中注入 `_outputGuard` 字段(保持 JSON 合法性)\r\n * - 文本结果:在头部插入提示行(与 shell 工具风格一致)\r\n *\r\n * 如果落盘失败(权限、磁盘满等),不注入路径引用,截断结果照常返回。\r\n */\r\n private async persistAndAnnotate(\r\n truncatedOutput: string,\r\n strategy: string,\r\n fullOutput: string,\r\n originalLength: number,\r\n toolName: string,\r\n ): Promise<string> {\r\n // 尝试落盘\r\n let filePath: string | null;\r\n let diskContent = fullOutput;\r\n try {\r\n const tempDir = join(this.config.workdir, '.agentdev', 'temp');\r\n const now = new Date();\r\n const ts = now.getFullYear().toString() +\r\n String(now.getMonth() + 1).padStart(2, '0') +\r\n String(now.getDate()).padStart(2, '0') + '-' +\r\n String(now.getHours()).padStart(2, '0') +\r\n String(now.getMinutes()).padStart(2, '0') +\r\n String(now.getSeconds()).padStart(2, '0');\r\n const suffix = Math.random().toString(36).slice(2, 8);\r\n const safeToolName = toolName.replace(/[^a-zA-Z0-9_-]/g, '_').slice(0, 30);\r\n const fileName = `tool-output-${safeToolName}-${ts}-${suffix}.log`;\r\n filePath = join(tempDir, fileName);\r\n\r\n // 尝试 pretty-print JSON 以便 read 工具按行分页\r\n try {\r\n const parsed = JSON.parse(fullOutput);\r\n diskContent = JSON.stringify(parsed, null, 2);\r\n } catch {\r\n // 非 JSON 文本,保持原始换行\r\n }\r\n\r\n await mkdir(tempDir, { recursive: true });\r\n await writeFile(filePath, diskContent, 'utf-8');\r\n } catch (err) {\r\n this.logger?.error('Failed to persist truncated output', { error: String(err) });\r\n filePath = null;\r\n }\r\n\r\n // 落盘失败,原样返回截断结果\r\n if (!filePath) return truncatedOutput;\r\n\r\n const totalKB = Math.round(originalLength / 1024);\r\n const totalLines = diskContent.split('\\n').length;\r\n\r\n // 根据截断策略决定注入方式\r\n const isJsonStrategy = strategy === 'json-fields' || strategy === 'json-array';\r\n\r\n if (isJsonStrategy) {\r\n // JSON 结果:在顶层注入 _outputGuard 字段\r\n try {\r\n const parsed = JSON.parse(truncatedOutput);\r\n if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {\r\n parsed._outputGuard = {\r\n fullOutputPath: filePath,\r\n originalSize: originalLength,\r\n originalSizeKB: totalKB,\r\n originalLines: totalLines,\r\n };\r\n return JSON.stringify(parsed);\r\n }\r\n } catch {\r\n // 截断后不是合法 JSON(理论上不应发生,但防御性处理)\r\n }\r\n // 如果 JSON 注入失败,回退到文本方式\r\n }\r\n\r\n // 文本结果:在头部插入提示\r\n const notice =\r\n `[OutputGuard: full output (${totalKB}KB, ${totalLines} lines) saved to: ${filePath}]\\n` +\r\n `Use the read tool with offset/limit to access specific portions.\\n`;\r\n return notice + truncatedOutput;\r\n }\r\n}\r\n","/**\r\n * OutputGuard 核心截断逻辑\r\n *\r\n * 三级级联策略:\r\n * 1. JSON 字段截断(保结构):解析 JSON → 递归截断长字段值 → 裁剪数组条目 → 重新序列化\r\n * 2. 行感知 head+tail:按行分割,保留首尾行,中间插入标记\r\n * 3. 字符级 head+tail:兜底,永不失败\r\n *\r\n * 所有截断函数都保证:\r\n * - 不破坏外层 JSON 信封的合法性(截断发生在 string 值内部)\r\n * - 截断标记清晰可读,LLM 能理解数据不完整\r\n * - Unicode 安全(不在多字节字符中间切割)\r\n */\r\n\r\n// ========== 常量 ==========\r\n\r\n/** 默认硬限制(安全网触发阈值) */\r\nexport const DEFAULT_HARD_LIMIT = 50_000;\r\n\r\n/** 默认单个字段截断长度(JSON 字段截断时,每个 string 值的上限) */\r\nexport const DEFAULT_FIELD_LIMIT = 5_000;\r\n\r\n/** 截断标记保留预算(从总预算中扣除给标记文本留空间) */\r\nconst MARKER_BUDGET = 300;\r\n\r\n// ========== 公共类型 ==========\r\n\r\nexport interface TruncateOptions {\r\n /** 总体积硬限制 */\r\n hardLimit?: number;\r\n /** 单个字符串字段截断长度 */\r\n fieldLimit?: number;\r\n}\r\n\r\nexport interface TruncateResult {\r\n /** 截断后的结果字符串 */\r\n output: string;\r\n /** 是否发生了截断 */\r\n truncated: boolean;\r\n /** 使用的截断策略 */\r\n strategy: 'none' | 'json-fields' | 'json-array' | 'line-headtail' | 'char-headtail';\r\n /** 原始长度 */\r\n originalLength: number;\r\n /** 截断后长度 */\r\n truncatedLength: number;\r\n}\r\n\r\n// ========== Unicode 安全工具 ==========\r\n\r\n/**\r\n * 找到不超过 maxBytes 的最后一个完整 UTF-8 字符边界。\r\n * JavaScript 字符串是 UTF-16,但大部分情况下用码点(code point)判断就够了。\r\n * 我们用 Array.from 来按 Unicode 码点分割,避免在代理对中间切割。\r\n */\r\nfunction safeSliceFromCodePoints(str: string, maxChars: number): string {\r\n const codePoints = Array.from(str);\r\n if (codePoints.length <= maxChars) return str;\r\n return codePoints.slice(0, maxChars).join('');\r\n}\r\n\r\nfunction safeSliceTailFromCodePoints(str: string, maxChars: number): string {\r\n const codePoints = Array.from(str);\r\n if (codePoints.length <= maxChars) return str;\r\n return codePoints.slice(-maxChars).join('');\r\n}\r\n\r\n// ========== 截断标记 ==========\r\n\r\nfunction buildMarker(omitted: number, total: number): string {\r\n const totalKB = Math.round(total / 1024);\r\n return `\\n[... truncated: ${omitted} chars omitted (${totalKB}KB total) ...]\\n`;\r\n}\r\n\r\nfunction buildFieldMarker(omitted: number): string {\r\n return ` [...${omitted} chars omitted...] `;\r\n}\r\n\r\n// ========== 策略 1: JSON 字段截断 ==========\r\n\r\n/**\r\n * 递归遍历 JSON 节点,截断超长的 string 值。\r\n * 不改变结构(key、数组长度、嵌套层级不变),只缩短 string 叶子值。\r\n */\r\nexport function truncateJsonNode(node: unknown, fieldLimit: number): unknown {\r\n if (typeof node === 'string') {\r\n if (node.length <= fieldLimit) return node;\r\n const headSize = Math.floor(fieldLimit * 0.6);\r\n const tailSize = Math.floor(fieldLimit * 0.3);\r\n const head = safeSliceFromCodePoints(node, headSize);\r\n const tail = safeSliceTailFromCodePoints(node, tailSize);\r\n const omitted = node.length - head.length - tail.length;\r\n return head + buildFieldMarker(omitted) + tail;\r\n }\r\n\r\n if (Array.isArray(node)) {\r\n return node.map((item) => truncateJsonNode(item, fieldLimit));\r\n }\r\n\r\n if (node !== null && typeof node === 'object') {\r\n const result: Record<string, unknown> = {};\r\n for (const [key, value] of Object.entries(node)) {\r\n result[key] = truncateJsonNode(value, fieldLimit);\r\n }\r\n return result;\r\n }\r\n\r\n // number, boolean, null, undefined, bigint, symbol, function → 原样返回\r\n return node;\r\n}\r\n\r\n/**\r\n * 裁剪数组:保留头部和尾部的元素,中间用标记元素替代。\r\n *\r\n * 标记元素是一个字符串(合法 JSON 值),格式为 `<<N items omitted>>`。\r\n */\r\nexport function shrinkArray(arr: unknown[], targetBudget: number): unknown[] {\r\n const serialized = JSON.stringify(arr);\r\n if (serialized.length <= targetBudget) return arr;\r\n\r\n const halfBudget = Math.floor(targetBudget / 2);\r\n const head: unknown[] = [];\r\n const tail: unknown[] = [];\r\n let headSize = 0;\r\n let tailSize = 0;\r\n\r\n // 从头部收集\r\n for (const item of arr) {\r\n const s = JSON.stringify(item);\r\n if (headSize + s.length + 2 > halfBudget) break; // +2 for \", \"\r\n head.push(item);\r\n headSize += s.length + 2;\r\n }\r\n\r\n // 从尾部收集\r\n for (let i = arr.length - 1; i >= 0; i--) {\r\n if (head.length + tail.length >= arr.length) break; // 防止重叠\r\n const s = JSON.stringify(arr[i]);\r\n if (tailSize + s.length + 2 > halfBudget) break;\r\n tail.unshift(arr[i]);\r\n tailSize += s.length + 2;\r\n }\r\n\r\n const omitted = arr.length - head.length - tail.length;\r\n if (omitted <= 0) return arr;\r\n\r\n return [...head, `<<${omitted} items omitted>>`, ...tail];\r\n}\r\n\r\n/**\r\n * 在 JSON 对象树中寻找最长的数组并裁剪。\r\n * 递归遍历所有对象和数组,对每个数组尝试裁剪。\r\n */\r\nfunction shrinkLongestArrays(node: unknown, targetBudget: number): unknown {\r\n if (Array.isArray(node)) {\r\n // 先递归处理子节点\r\n let processed = node.map((item) => shrinkLongestArrays(item, targetBudget));\r\n // 再尝试裁剪当前数组\r\n processed = shrinkArray(processed, targetBudget);\r\n return processed;\r\n }\r\n\r\n if (node !== null && typeof node === 'object') {\r\n const result: Record<string, unknown> = {};\r\n for (const [key, value] of Object.entries(node)) {\r\n result[key] = shrinkLongestArrays(value, targetBudget);\r\n }\r\n return result;\r\n }\r\n\r\n return node;\r\n}\r\n\r\n/**\r\n * 尝试 JSON 字段截断策略。\r\n * 返回截断后的字符串,或 null(表示不是 JSON 或截断后仍然超限)。\r\n */\r\nexport function tryJsonTruncate(\r\n str: string,\r\n hardLimit: number,\r\n fieldLimit: number,\r\n): { output: string; strategy: 'json-fields' | 'json-array' } | null {\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(str);\r\n } catch {\r\n return null; // 不是合法 JSON\r\n }\r\n\r\n // 只处理 object/array,原始值(string/number/boolean/null)不在此策略范围\r\n if (parsed === null || typeof parsed !== 'object') {\r\n return null;\r\n }\r\n\r\n // Pass 1: 字段值截断\r\n const truncated = truncateJsonNode(parsed, fieldLimit);\r\n let serialized = JSON.stringify(truncated);\r\n\r\n if (serialized.length <= hardLimit) {\r\n return { output: serialized, strategy: 'json-fields' };\r\n }\r\n\r\n // Pass 2: 数组裁剪(逐步收紧 budget 直到达标)\r\n let budget = hardLimit - MARKER_BUDGET;\r\n let withShrunkArrays = truncateJsonNode(parsed, fieldLimit); // 从原始重新开始\r\n while (budget > 1000) {\r\n withShrunkArrays = shrinkLongestArrays(withShrunkArrays, budget);\r\n serialized = JSON.stringify(withShrunkArrays);\r\n if (serialized.length <= hardLimit) {\r\n return { output: serialized, strategy: 'json-array' };\r\n }\r\n budget = Math.floor(budget * 0.7); // 收紧 30%\r\n }\r\n\r\n // JSON 策略无法压到目标以下,交由上层回退\r\n return null;\r\n}\r\n\r\n// ========== 策略 2: 行感知 head+tail ==========\r\n\r\n/**\r\n * 按行分割,保留首尾行,中间插入截断标记。\r\n * 适合多行文本(shell 输出、日志、格式化文本、pretty-printed JSON)。\r\n */\r\nexport function truncateByLines(str: string, limit: number): string {\r\n if (str.length <= limit) return str;\r\n\r\n const lines = str.split('\\n');\r\n const budget = limit - MARKER_BUDGET;\r\n const halfBudget = Math.floor(budget / 2);\r\n\r\n const headLines: string[] = [];\r\n const tailLines: string[] = [];\r\n let headSize = 0;\r\n let tailSize = 0;\r\n\r\n for (const line of lines) {\r\n const lineLen = line.length + 1; // +1 for \\n\r\n if (headSize + lineLen > halfBudget) break;\r\n headLines.push(line);\r\n headSize += lineLen;\r\n }\r\n\r\n for (let i = lines.length - 1; i >= 0; i--) {\r\n if (headLines.length + tailLines.length >= lines.length) break; // 防止重叠\r\n const lineLen = lines[i].length + 1;\r\n if (tailSize + lineLen > halfBudget) break;\r\n tailLines.unshift(lines[i]);\r\n tailSize += lineLen;\r\n }\r\n\r\n const omittedLines = lines.length - headLines.length - tailLines.length;\r\n const omittedChars = str.length - headLines.join('\\n').length - tailLines.join('\\n').length - 1;\r\n\r\n const marker = buildMarker(Math.max(0, omittedChars), str.length);\r\n // 在标记中也提及行数,帮助 LLM 理解规模\r\n const lineInfo = omittedLines > 0 ? ` (${omittedLines} of ${lines.length} lines)` : '';\r\n\r\n return (\r\n headLines.join('\\n') +\r\n marker.slice(0, -1) + lineInfo + '\\n' +\r\n tailLines.join('\\n')\r\n );\r\n}\r\n\r\n// ========== 策略 3: 字符级 head+tail(兜底) ==========\r\n\r\n/**\r\n * 纯字符级 head+tail 截断。\r\n * 永不失败,但不保证行/结构完整性。\r\n */\r\nexport function truncateHeadTail(str: string, limit: number): string {\r\n const budget = limit - MARKER_BUDGET;\r\n const headSize = Math.floor(budget * 0.6);\r\n const tailSize = budget - headSize;\r\n\r\n const head = safeSliceFromCodePoints(str, headSize);\r\n const tail = safeSliceTailFromCodePoints(str, tailSize);\r\n const omitted = str.length - head.length - tail.length;\r\n\r\n return head + buildMarker(omitted, str.length) + tail;\r\n}\r\n\r\n// ========== 主入口:级联截断 ==========\r\n\r\n/**\r\n * 对工具结果字符串执行级联截断。\r\n *\r\n * 策略优先级:\r\n * 1. 如果不超限,直接返回\r\n * 2. 尝试 JSON 字段截断(保结构、保 JSON 合法性)\r\n * 3. 尝试行感知 head+tail(保行边界)\r\n * 4. 字符级 head+tail(兜底)\r\n *\r\n * 返回包含截断结果和元信息的 TruncateResult。\r\n */\r\nexport function truncateOutput(\r\n str: string,\r\n options?: TruncateOptions,\r\n): TruncateResult {\r\n const hardLimit = options?.hardLimit ?? DEFAULT_HARD_LIMIT;\r\n const fieldLimit = options?.fieldLimit ?? DEFAULT_FIELD_LIMIT;\r\n const originalLength = str.length;\r\n\r\n // 不超限,直接返回\r\n if (originalLength <= hardLimit) {\r\n return {\r\n output: str,\r\n truncated: false,\r\n strategy: 'none',\r\n originalLength,\r\n truncatedLength: originalLength,\r\n };\r\n }\r\n\r\n // 策略 1: JSON 字段截断\r\n const jsonResult = tryJsonTruncate(str, hardLimit, fieldLimit);\r\n if (jsonResult !== null) {\r\n return {\r\n output: jsonResult.output,\r\n truncated: true,\r\n strategy: jsonResult.strategy,\r\n originalLength,\r\n truncatedLength: jsonResult.output.length,\r\n };\r\n }\r\n\r\n // 策略 2: 行感知 head+tail\r\n // 仅当文本有足够的行数时使用(否则行分割本身就是开销)\r\n const lineCount = str.split('\\n').length;\r\n if (lineCount >= 5) {\r\n const lineResult = truncateByLines(str, hardLimit);\r\n if (lineResult.length <= hardLimit) {\r\n return {\r\n output: lineResult,\r\n truncated: true,\r\n strategy: 'line-headtail',\r\n originalLength,\r\n truncatedLength: lineResult.length,\r\n };\r\n }\r\n }\r\n\r\n // 策略 3: 字符级 head+tail(兜底,永不失败)\r\n const fallback = truncateHeadTail(str, hardLimit);\r\n return {\r\n output: fallback,\r\n truncated: true,\r\n strategy: 'char-headtail',\r\n originalLength,\r\n truncatedLength: fallback.length,\r\n };\r\n}\r\n","/**\r\n * 配置加载\r\n * 从 config 目录读取 JSON 配置文件\r\n *\r\n * 提供两种方式:\r\n * - loadConfig() - 异步加载(用于特殊场景)\r\n * - loadConfigSync() - 同步加载(推荐,用于 Agent 构造)\r\n */\r\n\r\nimport { readFile, readdir } from 'fs/promises';\r\nimport { readFileSync, existsSync } from 'fs';\r\nimport { resolve, join } from 'path';\r\nimport { cwd } from 'process';\r\n\r\n/**\r\n * 自定义请求头条目\r\n * - valueMode 'static': 使用 value 原样\r\n * - valueMode 'uuid': 每次请求生成新的 UUID v4\r\n * - valueMode 'random': 每次请求生成新的随机数\r\n */\r\nexport interface CustomHeaderEntry {\r\n key: string;\r\n value: string;\r\n valueMode?: 'static' | 'uuid' | 'random';\r\n}\r\n\r\n/**\r\n * 思考力度档位\r\n *\r\n * 各厂商支持的值不同,配置层接受所有值的并集,\r\n * 各 provider 自行筛选自己支持的值,不支持的忽略。\r\n */\r\nexport type ThinkingEffort =\r\n | 'none' // 关闭思考(Anthropic → thinking.disabled,OpenAI → effort: none)\r\n | 'minimal' // OpenAI 专属\r\n | 'low' // 两家通用\r\n | 'medium' // 两家通用\r\n | 'high' // 两家通用\r\n | 'xhigh' // 两家通用\r\n | 'max'; // Anthropic 专属\r\n\r\n/** OpenAI 支持的思考力度档位(供 UI 和校验使用) */\r\nexport const OPENAI_THINKING_EFFORTS: readonly ThinkingEffort[] = [\r\n 'none', 'minimal', 'low', 'medium', 'high', 'xhigh',\r\n];\r\n\r\n/** Anthropic 支持的思考力度档位(供 UI 和校验使用) */\r\nexport const ANTHROPIC_THINKING_EFFORTS: readonly ThinkingEffort[] = [\r\n 'none', 'low', 'medium', 'high', 'xhigh', 'max',\r\n];\r\n\r\n/**\r\n * 统一配置类型\r\n * 字段允许冗余,各 LLM 实现只取自己需要的\r\n */\r\nexport interface ModelConfig {\r\n provider: 'openai' | 'anthropic' | string;\r\n apiKey: string;\r\n model: string;\r\n baseUrl?: string;\r\n maxTokens?: number;\r\n thinkingEffort?: ThinkingEffort;\r\n thinkingBudgetTokens?: number;\r\n thinkingKeepTurns?: number;\r\n providerOptions?: Record<string, unknown>;\r\n /** 追加到每次 LLM API 请求的自定义请求头 */\r\n customHeaders?: CustomHeaderEntry[];\r\n /** OpenAI 专用接口面:chat / responses */\r\n apiSurface?: 'chat' | 'responses';\r\n /** Responses 后端契约。codex 用于 ChatGPT 管理的 Codex Responses 端点。 */\r\n responsesProfile?: 'standard' | 'codex';\r\n /** 是否启用视觉(多模态图片输入)支持,默认 false */\r\n vision?: boolean;\r\n /**\r\n * 单次模型请求的最大重试次数(不含首次)。\r\n * 缺省时由 LLM 工厂自动填充 DEFAULT_MODEL_MAX_RETRIES。\r\n */\r\n maxRetries?: number;\r\n /**\r\n * 单次模型调用的整体时限(毫秒,覆盖建连、排队与流式传输全程)。\r\n * 超时以 AbortError 中止本次调用,交由上层按中断处理(不重试)。\r\n * 缺省时由 LLM 工厂自动填充 DEFAULT_MODEL_TIMEOUT_MS。\r\n */\r\n timeoutMs?: number;\r\n // 未来可扩展\r\n region?: string;\r\n projectId?: string;\r\n}\r\n\r\nexport interface AgentConfigFile {\r\n defaultModel: ModelConfig;\r\n agent: {\r\n maxTurns: number;\r\n temperature: number;\r\n };\r\n}\r\n\r\n/**\r\n * 获取项目根目录\r\n *\r\n * 使用 process.cwd() 而不是模块路径,以支持 npm link 环境\r\n */\r\nfunction getProjectRoot(): string {\r\n return cwd();\r\n}\r\n\r\n/**\r\n * 读取配置文件(异步版本)\r\n * @param name 配置文件名(不含路径和扩展名),默认 'default'\r\n */\r\nexport async function loadConfig(name: string = 'default'): Promise<AgentConfigFile> {\r\n const projectRoot = getProjectRoot();\r\n const configDir = join(projectRoot, 'config');\r\n const configPath = resolve(configDir, `${name}.json`);\r\n\r\n if (!existsSync(configPath)) {\r\n throw new Error(\r\n `配置文件不存在: ${configPath}\\n` +\r\n `请在项目目录下创建 config/${name}.json 文件,\\n` +\r\n `或通过 config.llm 参数直接传入 LLM 实例。`\r\n );\r\n }\r\n\r\n const content = await readFile(configPath, 'utf-8');\r\n const raw = JSON.parse(content);\r\n\r\n // 替换环境变量 ${VAR_NAME}\r\n return replaceEnvVars(raw) as AgentConfigFile;\r\n}\r\n\r\n/**\r\n * 读取配置文件(同步版本,推荐用于 Agent 构造)\r\n * @param name 配置文件名(不含路径和扩展名),默认 'default'\r\n */\r\nexport function loadConfigSync(name: string = 'default'): AgentConfigFile {\r\n const projectRoot = getProjectRoot();\r\n const configDir = join(projectRoot, 'config');\r\n const configPath = resolve(configDir, `${name}.json`);\r\n\r\n if (!existsSync(configPath)) {\r\n throw new Error(\r\n `配置文件不存在: ${configPath}\\n` +\r\n `请在项目目录下创建 config/${name}.json 文件,\\n` +\r\n `或通过 config.llm 参数直接传入 LLM 实例。`\r\n );\r\n }\r\n\r\n const content = readFileSync(configPath, 'utf-8');\r\n const raw = JSON.parse(content);\r\n\r\n // 替换环境变量 ${VAR_NAME}\r\n return replaceEnvVars(raw) as AgentConfigFile;\r\n}\r\n\r\n/**\r\n * 列出所有可用的配置文件\r\n */\r\nexport async function listConfigs(): Promise<string[]> {\r\n const projectRoot = getProjectRoot();\r\n const configDir = join(projectRoot, 'config');\r\n\r\n try {\r\n const files = await readdir(configDir);\r\n return files\r\n .filter(f => f.endsWith('.json'))\r\n .map(f => f.replace('.json', ''));\r\n } catch {\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * 递归替换对象中的环境变量\r\n */\r\nfunction replaceEnvVars(obj: any): any {\r\n if (typeof obj === 'string') {\r\n // 匹配 ${VAR_NAME} 格式\r\n return obj.replace(/\\$\\{([^}]+)\\}/g, (_, varName) => {\r\n return process.env[varName] || '';\r\n });\r\n }\r\n\r\n if (Array.isArray(obj)) {\r\n return obj.map(replaceEnvVars);\r\n }\r\n\r\n if (obj && typeof obj === 'object') {\r\n const result: any = {};\r\n for (const [key, value] of Object.entries(obj)) {\r\n result[key] = replaceEnvVars(value);\r\n }\r\n return result;\r\n }\r\n\r\n return obj;\r\n}\r\n","/**\r\n * Feature 配置队列解析(config queue)\r\n *\r\n * 框架不认识\"层\"(global/agent/dir/profile 都是产品语义),只接受一个有序\r\n * 配置数组,按序 deep merge 出最终配置,并同步产出 provenance 与 warnings。\r\n *\r\n * 本模块是队列 merge 与 provenance 的唯一权威实现:纯函数、无 IO、无 logger、\r\n * 无进程状态;warning 以返回值交付,由调用方决定记日志方式。\r\n *\r\n * merge 规范(D5):\r\n * 1. 对象:递归合并(同 key 且两侧均为普通对象时深入)\r\n * 2. 标量:替换(后层胜)\r\n * 3. 数组:整体替换,绝不按索引/按 key 合并\r\n * 4. null:视为\"删除该字段\",从合并结果移除并产生 warning\r\n * 5. 未出现的 key:继承(不写入即不覆盖)\r\n * 6. 空队列返回空结果\r\n */\r\n\r\n/**\r\n * 单个 feature 的配置对象形态。顶层 key = featureName(如 'lsp'、'shell'),\r\n * 值为该 feature 的配置对象。\r\n */\r\nexport type FeatureConfig = Record<string, unknown>;\r\n\r\n/**\r\n * 某个点路径字段的来源信息。\r\n */\r\nexport interface ConfigProvenanceEntry {\r\n /** 该字段最终生效值 */\r\n value: unknown;\r\n /** 队列中最后写入该字段的元素索引 */\r\n sourceIndex: number;\r\n}\r\n\r\n/**\r\n * 解析过程中产生的警告。第一版只有 null 删除一种。\r\n */\r\nexport interface ConfigWarning {\r\n /** 点路径,如 'lsp.typescript.mode' */\r\n fieldPath: string;\r\n /** 触发该警告的队列元素索引 */\r\n layerIndex: number;\r\n kind: 'null-removed';\r\n message: string;\r\n}\r\n\r\n/**\r\n * resolveFeatureConfig 的返回结构。provenance 的 key 是完整点路径\r\n * (含 featureName 前缀)。\r\n */\r\nexport interface ResolvedFeatureConfig {\r\n /** 最终合并配置 */\r\n merged: FeatureConfig;\r\n /** key = 完整点路径(如 'lsp.typescript.mode') */\r\n provenance: Record<string, ConfigProvenanceEntry>;\r\n warnings: ConfigWarning[];\r\n}\r\n\r\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\r\n return typeof value === 'object' && value !== null && !Array.isArray(value);\r\n}\r\n\r\n/** 整体赋值前深拷贝,保证输入队列不被结果持有引用(纯函数纪律)。 */\r\nfunction copyValue(value: unknown): unknown {\r\n if (Array.isArray(value)) {\r\n return value.map(copyValue);\r\n }\r\n if (isPlainObject(value)) {\r\n const out: Record<string, unknown> = {};\r\n for (const [k, v] of Object.entries(value)) {\r\n out[k] = copyValue(v);\r\n }\r\n return out;\r\n }\r\n return value;\r\n}\r\n\r\n/**\r\n * 把有序配置队列按序 deep merge 为最终配置。\r\n *\r\n * @param queue 有序配置数组,顶层按 featureName 分桶;越靠后优先级越高\r\n */\r\nexport function resolveFeatureConfig(queue: FeatureConfig[]): ResolvedFeatureConfig {\r\n const merged: FeatureConfig = {};\r\n const provenance: Record<string, ConfigProvenanceEntry> = {};\r\n const warnings: ConfigWarning[] = [];\r\n\r\n const removeProvenanceSubtree = (path: string): void => {\r\n delete provenance[path];\r\n const prefix = `${path}.`;\r\n for (const key of Object.keys(provenance)) {\r\n if (key.startsWith(prefix)) {\r\n delete provenance[key];\r\n }\r\n }\r\n };\r\n\r\n // 单次遍历:merge 与 provenance 同源(D6),逐层把 layerValue 并入 target\r\n const applyLayer = (\r\n target: Record<string, unknown>,\r\n layerValue: Record<string, unknown>,\r\n prefix: string,\r\n layerIndex: number,\r\n ): void => {\r\n for (const [key, incoming] of Object.entries(layerValue)) {\r\n const path = prefix ? `${prefix}.${key}` : key;\r\n\r\n // 规范 4:null 按删除处理并产生 warning\r\n if (incoming === null) {\r\n delete target[key];\r\n removeProvenanceSubtree(path);\r\n warnings.push({\r\n fieldPath: path,\r\n layerIndex,\r\n kind: 'null-removed',\r\n message: `字段 '${path}' 在第 ${layerIndex} 层被置为 null,已从合并结果中删除`,\r\n });\r\n continue;\r\n }\r\n\r\n const existing = target[key];\r\n\r\n // 规范 1:两侧均为普通对象时递归合并\r\n if (isPlainObject(existing) && isPlainObject(incoming)) {\r\n applyLayer(existing, incoming, path, layerIndex);\r\n continue;\r\n }\r\n\r\n if (isPlainObject(incoming)) {\r\n // 新出现的对象分支:建新容器后继续深入;\r\n // 若该路径此前是叶子值,先清掉其 provenance 再替换\r\n removeProvenanceSubtree(path);\r\n const branch: Record<string, unknown> = {};\r\n target[key] = branch;\r\n applyLayer(branch, incoming, path, layerIndex);\r\n continue;\r\n }\r\n\r\n // 规范 2 / 3:标量与数组整体替换(数组绝不按索引合并)\r\n target[key] = copyValue(incoming);\r\n provenance[path] = { value: target[key], sourceIndex: layerIndex };\r\n }\r\n };\r\n\r\n queue.forEach((layer, layerIndex) => {\r\n if (isPlainObject(layer)) {\r\n applyLayer(merged, layer, '', layerIndex);\r\n }\r\n });\r\n\r\n return { merged, provenance, warnings };\r\n}\r\n","/**\r\n * 渲染配置\r\n * 定义工具渲染模板、样式和默认映射\r\n */\r\n\r\nimport type { ToolRenderConfig, RenderTemplateItem } from './types.js';\r\n\r\n// ============= 类型定义 =============\r\nexport interface RenderTemplate {\r\n /** 调用时的渲染模板 */\r\n call: RenderTemplateItem;\r\n /** 结果时的渲染模板 */\r\n result: RenderTemplateItem;\r\n}\r\n\r\n// ============= 模板定义 =============\r\n/**\r\n * 渲染模板集合\r\n * 包含所有预定义的渲染模板(字符串模板和函数模板)\r\n */\r\nexport const RENDER_TEMPLATES: Record<string, RenderTemplate> = {\r\n // ----- 文件操作模板 -----\r\n 'file': {\r\n call: '<div class=\"bash-command\">Read <span class=\"file-path\">{{path}}</span></div>',\r\n result: (data) => `<pre class=\"bash-output\" style=\"max-height:300px;\">${escapeHtml(data)}</pre>`\r\n },\r\n\r\n 'file-write': {\r\n call: '<div class=\"bash-command\">Write <span class=\"file-path\">{{path}}</span></div>',\r\n result: (_data) => `<div style=\"color:var(--success-color)\">✓ File written successfully</div>`\r\n },\r\n\r\n 'file-list': {\r\n call: '<div class=\"bash-command\">List <span class=\"file-path\">{{path}}</span></div>',\r\n result: (data) => {\r\n const files = (data || '').split('\\n').filter((f: string) => f);\r\n return `<div style=\"display:grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap:4px; font-family:monospace; font-size:12px;\">\r\n ${files.map((f: string) => `<div style=\"color:var(--text-primary);\">${escapeHtml(f)}</div>`).join('')}\r\n </div>`;\r\n }\r\n },\r\n\r\n // ----- 命令执行模板 -----\r\n 'command': {\r\n call: '<div class=\"bash-command\">> {{command}}</div>',\r\n result: (data) => `<pre class=\"bash-output\">${escapeHtml(data)}</pre>`\r\n },\r\n\r\n // ----- 网络请求模板 -----\r\n 'web': {\r\n call: '<div>GET <a href=\"{{url}}\" target=\"_blank\" style=\"color:var(--accent-color)\">{{url}}</a></div>',\r\n result: (data) => `<div style=\"font-size:12px; opacity:0.8;\">Fetched ${String(data).length} chars</div>`\r\n },\r\n\r\n // ----- 数学计算模板 -----\r\n 'math': {\r\n call: '<div class=\"bash-command\">{{expression}}</div>',\r\n result: (data) => `<div class=\"bash-command\" style=\"color:#d2a8ff\">= ${escapeHtml(data)}</div>`\r\n },\r\n\r\n // ----- 内置类型 -----\r\n 'json': {\r\n call: (args) => `<pre style=\"margin:0; font-size:12px;\">${escapeHtml(JSON.stringify(args, null, 2))}</pre>`,\r\n result: (data) => {\r\n const displayData = typeof data === 'object' ? JSON.stringify(data, null, 2) : data;\r\n return `<pre class=\"bash-output\">${escapeHtml(displayData)}</pre>`;\r\n }\r\n },\r\n\r\n // ----- Skills 工具 -----\r\n 'skill': {\r\n call: '<div class=\"bash-command\">Skill <span class=\"file-path\">{{skill}}</span></div>',\r\n result: (data) => `<pre class=\"bash-output\" style=\"max-height:400px;\">${escapeHtml(data)}</pre>`\r\n },\r\n\r\n // ----- Agent Spawn -----\r\n 'agent-spawn': {\r\n call: '<div class=\"bash-command\">Spawn <span class=\"pattern\">{{type}}</span> agent: {{instruction}}</div>',\r\n result: (data) => {\r\n if (data.error) {\r\n return `<div style=\"color:var(--error-color)\">✗ ${data.error}</div>`;\r\n }\r\n return `<div style=\"color:var(--success-color)\">✓ Agent ${data.agentId} (${data.type}) completed</div>`;\r\n }\r\n },\r\n\r\n // ----- Agent List -----\r\n 'agent-list': {\r\n call: '<div class=\"bash-command\">List agents</div>',\r\n result: (data) => {\r\n if (!data.agents || data.agents.length === 0) {\r\n return `<div style=\"color:var(--warning-color)\">No agents found</div>`;\r\n }\r\n return `<div style=\"font-size:12px; color:var(--text-secondary);\">Total: ${data.total} | Running: ${data.running}</div>`;\r\n }\r\n },\r\n\r\n // ----- Agent Send -----\r\n 'agent-send': {\r\n call: '<div class=\"bash-command\">Send to <span class=\"pattern\">{{agentId}}</span></div>',\r\n result: (data) => {\r\n if (data.error) {\r\n return `<div style=\"color:var(--error-color)\">✗ ${data.error}</div>`;\r\n }\r\n return `<div style=\"color:var(--success-color)\">✓ Message sent</div>`;\r\n }\r\n },\r\n\r\n // ----- Agent Close -----\r\n 'agent-close': {\r\n call: '<div class=\"bash-command\">Close <span class=\"pattern\">{{agentId}}</span></div>',\r\n result: (data) => {\r\n if (data.error) {\r\n return `<div style=\"color:var(--error-color)\">✗ ${data.error}</div>`;\r\n }\r\n return `<div style=\"color:var(--success-color)\">✓ ${data.message || 'Agent closed'}</div>`;\r\n }\r\n },\r\n\r\n // ----- Safe Trash Delete -----\r\n 'trash-delete': {\r\n call: (args) => {\r\n const paths = args.paths || [];\r\n const pathList = Array.isArray(paths) ? paths : [paths];\r\n const displayPaths = pathList.slice(0, 3).map((p: string) => escapeHtml(p)).join(', ');\r\n const more = pathList.length > 3 ? ` +${pathList.length - 3} more` : '';\r\n return `<div class=\"bash-command\">Safe delete <span class=\"file-path\">${displayPaths}${more}</span></div>`;\r\n },\r\n result: (data) => {\r\n const movedCount = data.moved_count || 0;\r\n const failed = data.failed || [];\r\n const failedCount = failed.length;\r\n\r\n if (movedCount > 0 && failedCount === 0) {\r\n return `<div style=\"color:var(--success-color)\">✓ Moved ${movedCount} item(s) to trash</div>`;\r\n }\r\n if (movedCount > 0) {\r\n return `<div style=\"color:var(--warning-color)\">⚠ Moved ${movedCount}, ${failedCount} failed</div>`;\r\n }\r\n return `<div style=\"color:var(--text-secondary)\">No files moved</div>`;\r\n }\r\n },\r\n\r\n // ----- Safe Trash List -----\r\n 'trash-list': {\r\n call: '<div class=\"bash-command\">List trash</div>',\r\n result: (data) => {\r\n const total = data.total || 0;\r\n if (total === 0) {\r\n return `<div style=\"color:var(--text-secondary)\">Trash is empty</div>`;\r\n }\r\n return `<div style=\"font-size:12px; color:var(--text-secondary);\">${total} item(s) in trash</div>`;\r\n }\r\n },\r\n\r\n // ----- Safe Trash Restore -----\r\n 'trash-restore': {\r\n call: (args) => `<div class=\"bash-command\">Restore <span class=\"pattern\">${escapeHtml(args.target)}</span></div>`,\r\n result: (data) => {\r\n const restored = data.restored || [];\r\n const failed = data.failed || [];\r\n const restoredCount = restored.length;\r\n const failedCount = failed.length;\r\n\r\n if (restoredCount > 0 && failedCount === 0) {\r\n return `<div style=\"color:var(--success-color)\">✓ Restored ${restoredCount} item(s)</div>`;\r\n }\r\n if (restoredCount > 0 || failedCount > 0) {\r\n return `<div style=\"color:var(--warning-color)\">Restored ${restoredCount}, ${failedCount} failed</div>`;\r\n }\r\n return `<div style=\"color:var(--text-secondary)\">Nothing restored</div>`;\r\n }\r\n },\r\n} as const;\r\n\r\n// ============= 默认映射 =============\r\n/**\r\n * 系统工具的默认渲染模板映射\r\n * 工具名称 -> 模板名称\r\n */\r\nexport const SYSTEM_RENDER_MAP: Record<string, string> = {\r\n // ===== 系统工具 =====\r\n // 文件系统工具(旧版,已废弃)\r\n 'read_file': 'file',\r\n 'write_file': 'file-write',\r\n 'list_directory': 'file-list',\r\n\r\n // Shell 工具\r\n 'run_shell_command': 'command',\r\n 'bash': 'command',\r\n 'shell': 'command',\r\n\r\n // Safe Trash 工具\r\n 'safe_trash_delete': 'trash-delete',\r\n 'safe_trash_list': 'trash-list',\r\n 'safe_trash_restore': 'trash-restore',\r\n\r\n // Web 工具\r\n 'web_fetch': 'web',\r\n\r\n // Math 工具\r\n 'calculator': 'math',\r\n\r\n // Skills 工具\r\n 'invoke_skill': 'skill',\r\n\r\n // Agent 工具\r\n 'spawn_agent': 'agent-spawn',\r\n 'list_agents': 'agent-list',\r\n 'send_to_agent': 'agent-send',\r\n 'close_agent': 'agent-close',\r\n} as const;\r\n\r\n// ============= 工具显示名称映射 =============\r\n/**\r\n * 工具显示名称(用于UI展示)\r\n */\r\nexport const TOOL_DISPLAY_NAMES: Record<string, string> = {\r\n // ===== 系统工具 =====\r\n 'run_shell_command': 'Bash',\r\n 'bash': 'Bash',\r\n 'shell': 'Bash',\r\n 'read_file': 'Read File',\r\n 'write_file': 'Write File',\r\n 'list_directory': 'LS',\r\n 'web_fetch': 'Web',\r\n 'calculator': 'Calc',\r\n 'invoke_skill': 'Invoke Skill',\r\n 'spawn_agent': 'Spawn Agent',\r\n 'list_agents': 'List Agents',\r\n 'send_to_agent': 'Send to Agent',\r\n 'close_agent': 'Close Agent',\r\n\r\n // ===== Safe Trash 工具 =====\r\n 'safe_trash_delete': 'Safe Delete',\r\n 'safe_trash_list': 'Trash List',\r\n 'safe_trash_restore': 'Restore',\r\n\r\n // ===== Opencode 工具 =====\r\n 'read': 'Read',\r\n 'write': 'Write',\r\n 'edit': 'Edit',\r\n 'glob': 'Glob',\r\n 'grep': 'Grep',\r\n 'ls': 'LS',\r\n} as const;\r\n\r\n// ============= 辅助函数 =============\r\n/**\r\n * HTML 转义\r\n */\r\nfunction escapeHtml(text: any): string {\r\n const str = String(text);\r\n const map: Record<string, string> = {\r\n '&': '&',\r\n '<': '<',\r\n '>': '>',\r\n '\"': '"',\r\n \"'\": '''\r\n };\r\n return str.replace(/[&<>\"']/g, m => map[m]);\r\n}\r\n\r\n// ============= 模板引擎 =============\r\n/**\r\n * 简单的字符串模板插值\r\n * 支持 {{key}} 语法\r\n */\r\nexport function interpolateTemplate(template: string, data: Record<string, any>): string {\r\n return template.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key) => {\r\n const value = data[key];\r\n return value !== undefined ? String(value) : `{{${key}}}`;\r\n });\r\n}\r\n\r\n/**\r\n * 应用渲染模板\r\n */\r\nexport function applyTemplate(\r\n template: RenderTemplateItem,\r\n data: Record<string, any>,\r\n success = true\r\n): string {\r\n if (typeof template === 'function') {\r\n return template(data, success);\r\n }\r\n return interpolateTemplate(template, data);\r\n}\r\n\r\n// ============= 动态模板加载 =============\r\n/**\r\n * 从文件加载渲染模板\r\n * @param toolPath 工具路径(相对于项目根目录)\r\n */\r\nexport async function loadRenderTemplate(\r\n toolPath: string\r\n): Promise<RenderTemplate | undefined> {\r\n try {\r\n // 构建模板文件路径:工具目录 + .render.ts\r\n const templatePath = toolPath + '.render.ts';\r\n\r\n // 动态导入模板模块\r\n const module = await import(templatePath);\r\n\r\n // 模块应导出 default 或 render 函数返回 RenderTemplate\r\n if (module.default && typeof module.default === 'object') {\r\n return module.default as RenderTemplate;\r\n }\r\n if (module.render && typeof module.render === 'function') {\r\n return await module.render();\r\n }\r\n\r\n return undefined;\r\n } catch {\r\n // 文件不存在或导入失败,返回 undefined\r\n return undefined;\r\n }\r\n}\r\n\r\n// ============= 导出合并函数 =============\r\n/**\r\n * 获取工具的渲染配置(合并默认值)\r\n */\r\nexport function getToolRenderConfig(\r\n toolName: string,\r\n customRender?: ToolRenderConfig\r\n): ToolRenderConfig {\r\n // 优先级:自定义配置 > 系统默认映射 > 'json'\r\n const systemDefault = SYSTEM_RENDER_MAP[toolName];\r\n const defaultTemplate = systemDefault || 'json';\r\n\r\n return {\r\n call: customRender?.call || defaultTemplate,\r\n result: customRender?.result || defaultTemplate,\r\n };\r\n}\r\n\r\n/**\r\n * 获取工具的渲染模板\r\n */\r\nexport function getToolRenderTemplate(toolName: string, customRender?: ToolRenderConfig): RenderTemplate {\r\n const config = getToolRenderConfig(toolName, customRender);\r\n\r\n // 处理 call 模板\r\n let callTemplate: RenderTemplateItem;\r\n if (typeof config.call === 'object' && config.call !== null) {\r\n // 内联模板\r\n callTemplate = config.call.call;\r\n } else {\r\n // 字符串引用\r\n const callTemplateName = config.call || 'json';\r\n callTemplate = RENDER_TEMPLATES[callTemplateName]?.call || RENDER_TEMPLATES['json'].call;\r\n }\r\n\r\n // 处理 result 模板\r\n let resultTemplate: RenderTemplateItem;\r\n if (typeof config.result === 'object' && config.result !== null) {\r\n // 内联模板\r\n resultTemplate = config.result.result;\r\n } else {\r\n // 字符串引用\r\n const resultTemplateName = config.result || 'json';\r\n resultTemplate = RENDER_TEMPLATES[resultTemplateName]?.result || RENDER_TEMPLATES['json'].result;\r\n }\r\n\r\n return {\r\n call: callTemplate,\r\n result: resultTemplate,\r\n };\r\n}\r\n\r\n/**\r\n * 获取工具显示名称\r\n */\r\nexport function getToolDisplayName(toolName: string): string {\r\n return TOOL_DISPLAY_NAMES[toolName] || toolName;\r\n}\r\n","/**\r\n * 提示词模板系统 - 核心类型定义\r\n */\r\n\r\nimport type { TemplateComposer } from './composer.js';\r\n\r\n/**\r\n * 模板源\r\n * - string: 硬编码字符串\r\n * - { file: string }: 文件路径\r\n * - [dataSourceName: string]: 数据源名称(如 skills, tasks 等)\r\n * - TemplateComposer: 组合模板\r\n *\r\n * @example\r\n * ```typescript\r\n * // 静态字符串\r\n * 'Hello {{name}}'\r\n *\r\n * // 文件\r\n * { file: 'prompts/system.md' }\r\n *\r\n * // 数据源(列表渲染)\r\n * { skills: '- **{{name}}**: {{description}}' }\r\n * { tasks: '- [{{title}}](#{{id}}) ({{priority}})' }\r\n *\r\n * // 条件渲染\r\n * { conditional: { part: { file: 'advanced.md' }, condition: (ctx) => ctx.advanced } }\r\n * ```\r\n */\r\nexport type TemplateSource =\r\n | string\r\n | { file: string }\r\n | { conditional: ConditionalSource }\r\n | { [dataSourceName: string]: string } // 数据源 -> 模板\r\n | TemplateComposer;\r\n\r\n/**\r\n * 条件源配置\r\n */\r\nexport interface ConditionalSource {\r\n /** 条件模板源 */\r\n part: TemplateSource;\r\n /** 条件函数(true 时渲染) */\r\n condition: (context: PlaceholderContext) => boolean;\r\n}\r\n\r\n/**\r\n * 占位符上下文 - 变量替换的键值对\r\n * 支持原始类型和复杂对象(用于数据源渲染)\r\n */\r\nexport type PlaceholderContext = Record<string, string | number | boolean | undefined | object>;\r\n\r\n/**\r\n * 模板渲染结果\r\n */\r\nexport interface TemplateResult {\r\n /** 渲染后的内容 */\r\n content: string;\r\n /** 使用的源文件列表(用于调试) */\r\n sources: string[];\r\n}\r\n\r\n/**\r\n * 模板加载器配置\r\n */\r\nexport interface TemplateLoaderOptions {\r\n /** 缓存启用状态,默认 true */\r\n cacheEnabled?: boolean;\r\n /** 模板搜索目录(相对于项目根目录) */\r\n searchDirs?: string[];\r\n /** 项目根目录(自动检测) */\r\n projectRoot?: string;\r\n}\r\n\r\n/**\r\n * 缓存统计\r\n */\r\nexport interface CacheStats {\r\n size: number; // 缓存条目数\r\n hits: number; // 命中次数\r\n misses: number; // 未命中次数\r\n hitRate: number; // 命中率\r\n}\r\n\r\n/**\r\n * 模板相关错误\r\n */\r\nexport class TemplateError extends Error {\r\n constructor(\r\n message: string,\r\n public code:\r\n | 'FILE_NOT_FOUND'\r\n | 'INVALID_PATH'\r\n | 'READ_ERROR'\r\n | 'UNSUPPORTED_FORMAT',\r\n public path?: string\r\n ) {\r\n super(message);\r\n this.name = 'TemplateError';\r\n }\r\n}\r\n","/**\r\n * Trim-Transcript 官方变换(ticket 006 下沉自 Claw)。\r\n *\r\n * 策略引擎:对源会话快照的 messages 施加一次「裁剪 + 工具活动折叠」变换,\r\n * 产出下一个 Session 的种子消息(与 Claw `handoff-package.js` 的策略引擎\r\n * 逐字节等价——golden 对照以 Claw 现行测试数据验收)。\r\n *\r\n * 本模块只实现纯策略(DEFAULT_EXPORT_POLICY / normalizeExportPolicy /\r\n * buildTrimmedSeedMessages)+ 一个实现 005 Transformation 契约的\r\n * `TrimTranscriptTransformation`。宿主侧的写盘、文件路径等职责不在此处。\r\n */\r\n\r\nimport type { AgentSessionSnapshot } from '../../session-store.js';\r\nimport type {\r\n SessionTransformation,\r\n TransformInput,\r\n TransformContext,\r\n SuccessorSeed,\r\n SessionSeedMessage,\r\n} from '../index.js';\r\n\r\n// ============ 常量与默认策略 ============\r\n\r\nexport const HANDOFF_SCHEMA_VERSION = 1;\r\nexport const HANDOFF_COMPILER_VERSION = 'trim-transcript-v1';\r\n\r\nexport const DEFAULT_EXPORT_POLICY = {\r\n strategy: 'trim-transcript',\r\n includeSystemMessages: false,\r\n keepSystemTags: ['folded-tool-activity'],\r\n includeUserMessages: true,\r\n includeAssistantMessages: true,\r\n keepRecentTurns: null,\r\n fullPreserveFromTurn: null,\r\n preservedTurns: null,\r\n preservedMsgRanges: null,\r\n assistantToolCallMode: 'fold',\r\n toolMessageMode: 'fold',\r\n toolFoldScope: 'all',\r\n toolFoldRecentTurns: null,\r\n foldConsecutiveToolActivity: true,\r\n foldedToolNoteRole: 'system',\r\n foldToolCallArgs: false,\r\n foldToolResultSummary: false,\r\n maxFoldedToolChars: 240,\r\n preserveToolNames: [],\r\n};\r\n\r\nconst VALID_TOOL_MODES = new Set(['keep', 'drop', 'fold']);\r\nconst VALID_TOOL_SCOPES = new Set(['all', 'recent']);\r\nconst VALID_FOLDED_NOTE_ROLES = new Set(['system', 'assistant']);\r\n\r\n// ============ 清洗工具(与 Claw 逐字节一致) ============\r\n\r\nfunction sanitizeFragment(value: unknown): string {\r\n return String(value || '')\r\n .trim()\r\n .replace(/[^a-zA-Z0-9_-]+/g, '-')\r\n .replace(/-+/g, '-')\r\n .replace(/^-|-$/g, '') || 'default';\r\n}\r\n\r\nfunction cleanInlineText(value: unknown): string {\r\n return typeof value === 'string'\r\n ? value.replace(/\\s+/g, ' ').trim()\r\n : '';\r\n}\r\n\r\nfunction cleanMultilineText(value: unknown): string {\r\n if (typeof value !== 'string') return '';\r\n const normalized = value.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\r\n const lines = normalized.split('\\n').map((line) => line.replace(/[ \\t]+/g, ' ').trimEnd());\r\n const compacted: string[] = [];\r\n let blankRun = 0;\r\n for (const line of lines) {\r\n if (line.trim() === '') {\r\n blankRun += 1;\r\n if (blankRun <= 1) {\r\n compacted.push('');\r\n }\r\n continue;\r\n }\r\n blankRun = 0;\r\n compacted.push(line);\r\n }\r\n return compacted.join('\\n').trim();\r\n}\r\n\r\nfunction clampInteger(value: unknown, fallback: number, min: number, max: number): number {\r\n const parsed = Number.parseInt(String(value ?? ''), 10);\r\n if (!Number.isFinite(parsed)) return fallback;\r\n return Math.min(max, Math.max(min, parsed));\r\n}\r\n\r\nfunction normalizeNullableTurnCount(value: unknown): number | null {\r\n if (value === null || value === undefined || value === '') return null;\r\n return clampInteger(value, 1, 1, 2000);\r\n}\r\n\r\nfunction normalizeNullableTurnIndex(value: unknown): number | null {\r\n if (value === null || value === undefined || value === '') return null;\r\n return clampInteger(value, 0, 0, 2000);\r\n}\r\n\r\nfunction normalizeKeepRecentSkillInvokes(value: unknown): number | null | typeof Infinity {\r\n if (value === null || value === undefined || value === '' || value === false) return null;\r\n if (value === Infinity || value === 'Infinity') return Infinity;\r\n return clampInteger(value as number, 1, 1, 2000);\r\n}\r\n\r\nfunction normalizeToolNameList(value: unknown): string[] {\r\n if (!Array.isArray(value)) return [];\r\n return [...new Set(value.map(cleanInlineText).filter(Boolean))];\r\n}\r\n\r\nfunction normalizeKeepSystemTags(value: unknown): string[] {\r\n if (!Array.isArray(value)) return [...DEFAULT_EXPORT_POLICY.keepSystemTags];\r\n return [...new Set(value.map(cleanInlineText).filter(Boolean))];\r\n}\r\n\r\nfunction normalizeEnum(value: unknown, validValues: Set<string>, fallback: string): string {\r\n const text = cleanInlineText(value);\r\n return validValues.has(text) ? text : fallback;\r\n}\r\n\r\n// ============ 策略归一化 ============\r\n\r\nexport interface TrimExportPolicy {\r\n strategy: 'trim-transcript';\r\n includeSystemMessages: boolean;\r\n keepSystemTags: string[];\r\n includeUserMessages: boolean;\r\n includeAssistantMessages: boolean;\r\n keepRecentTurns: number | null;\r\n fullPreserveFromTurn: number | null;\r\n preservedTurns: number[] | null;\r\n preservedMsgRanges: Array<[number, number]> | null;\r\n assistantToolCallMode: string;\r\n toolMessageMode: string;\r\n toolFoldScope: string;\r\n toolFoldRecentTurns: number | null;\r\n foldConsecutiveToolActivity: boolean;\r\n foldedToolNoteRole: string;\r\n foldToolCallArgs: boolean;\r\n foldToolResultSummary: boolean;\r\n maxFoldedToolChars: number;\r\n keepRecentSkillInvokes?: number | null | typeof Infinity;\r\n preserveToolNames: string[];\r\n}\r\n\r\nexport function normalizeExportPolicy(rawPolicy: Record<string, unknown> = {}): TrimExportPolicy {\r\n return {\r\n strategy: 'trim-transcript',\r\n includeSystemMessages: rawPolicy?.includeSystemMessages === true,\r\n keepSystemTags: normalizeKeepSystemTags(rawPolicy?.keepSystemTags),\r\n includeUserMessages: rawPolicy?.includeUserMessages !== false,\r\n includeAssistantMessages: rawPolicy?.includeAssistantMessages !== false,\r\n keepRecentTurns: normalizeNullableTurnCount(rawPolicy?.keepRecentTurns as unknown),\r\n fullPreserveFromTurn: normalizeNullableTurnIndex(rawPolicy?.fullPreserveFromTurn as unknown),\r\n preservedTurns: Array.isArray(rawPolicy?.preservedTurns)\r\n ? [...new Set((rawPolicy.preservedTurns as unknown[]).filter(t => Number.isFinite(t)).map(Number))]\r\n : null,\r\n preservedMsgRanges: Array.isArray(rawPolicy?.preservedMsgRanges) && (rawPolicy.preservedMsgRanges as unknown[]).length > 0\r\n ? (rawPolicy.preservedMsgRanges as Array<[unknown, unknown]>)\r\n .filter(r => Array.isArray(r) && r.length === 2 && Number.isFinite(r[0]) && Number.isFinite(r[1]))\r\n .map(([s, e]) => [Math.floor(s as number), Math.floor(e as number)])\r\n : null,\r\n assistantToolCallMode: normalizeEnum(rawPolicy?.assistantToolCallMode, VALID_TOOL_MODES, DEFAULT_EXPORT_POLICY.assistantToolCallMode),\r\n toolMessageMode: normalizeEnum(rawPolicy?.toolMessageMode, VALID_TOOL_MODES, DEFAULT_EXPORT_POLICY.toolMessageMode),\r\n toolFoldScope: normalizeEnum(rawPolicy?.toolFoldScope, VALID_TOOL_SCOPES, DEFAULT_EXPORT_POLICY.toolFoldScope),\r\n toolFoldRecentTurns: normalizeNullableTurnCount(rawPolicy?.toolFoldRecentTurns as unknown),\r\n foldConsecutiveToolActivity: rawPolicy?.foldConsecutiveToolActivity !== false,\r\n foldedToolNoteRole: normalizeEnum(rawPolicy?.foldedToolNoteRole, VALID_FOLDED_NOTE_ROLES, DEFAULT_EXPORT_POLICY.foldedToolNoteRole),\r\n foldToolCallArgs: rawPolicy?.foldToolCallArgs === true,\r\n foldToolResultSummary: rawPolicy?.foldToolResultSummary === true,\r\n maxFoldedToolChars: clampInteger(rawPolicy?.maxFoldedToolChars as unknown, DEFAULT_EXPORT_POLICY.maxFoldedToolChars, 80, 4000),\r\n keepRecentSkillInvokes: normalizeKeepRecentSkillInvokes(rawPolicy?.keepRecentSkillInvokes),\r\n preserveToolNames: normalizeToolNameList(rawPolicy?.preserveToolNames),\r\n };\r\n}\r\n\r\n// ============ 策略引擎(与 handoff-package.js 逐字节一致) ============\r\n\r\nfunction safeJsonSnippet(value: unknown, maxChars: number): string {\r\n try {\r\n const text = cleanMultilineText(typeof value === 'string' ? value : JSON.stringify(value));\r\n return text.length > maxChars ? `${text.slice(0, Math.max(0, maxChars - 18)).trimEnd()} [truncated]` : text;\r\n } catch {\r\n const text = cleanMultilineText(String(value ?? ''));\r\n return text.length > maxChars ? `${text.slice(0, Math.max(0, maxChars - 18)).trimEnd()} [truncated]` : text;\r\n }\r\n}\r\n\r\nfunction extractToolCallKeyInfo(name: string, rawArgs: unknown): string | null {\r\n let args = rawArgs;\r\n if (typeof args === 'string') { try { args = JSON.parse(args); } catch { return null; } }\r\n if (!args || typeof args !== 'object') return null;\r\n const record = args as Record<string, unknown>;\r\n if (name === 'read' || name === 'edit' || name === 'write') {\r\n const filePath = typeof record.filePath === 'string' ? record.filePath : '';\r\n if (filePath) {\r\n const baseName = filePath.split(/[\\\\/]/).pop() || filePath;\r\n return `${name}(${baseName})`;\r\n }\r\n }\r\n if (name === 'invoke_skill') {\r\n const skill = typeof record.skill === 'string' ? record.skill : '';\r\n if (skill) return `invoke_skill(${skill})`;\r\n }\r\n return null;\r\n}\r\n\r\nfunction summarizeAssistantToolCalls(toolCalls: unknown[], policy: TrimExportPolicy): string[] {\r\n if (!Array.isArray(toolCalls) || toolCalls.length === 0) return [];\r\n return toolCalls.map((call) => {\r\n const name = cleanInlineText((call as Record<string, unknown>)?.name) || 'tool';\r\n const keyInfo = extractToolCallKeyInfo(name, (call as Record<string, unknown>)?.args ?? (call as Record<string, unknown>)?.arguments);\r\n if (keyInfo) return keyInfo;\r\n if (!policy.foldToolCallArgs) {\r\n return name;\r\n }\r\n const args = safeJsonSnippet((call as Record<string, unknown>)?.args ?? (call as Record<string, unknown>)?.arguments ?? {}, policy.maxFoldedToolChars);\r\n return args ? `${name}(${args})` : `${name}()`;\r\n });\r\n}\r\n\r\nfunction getMessageTurn(message: any, fallbackIndex: number): number {\r\n return Number.isFinite(message?.turn) ? Number(message.turn) : fallbackIndex;\r\n}\r\n\r\nfunction getRetainedTurnSet(rawMessages: any[], policy: TrimExportPolicy): Set<number> | null {\r\n if (!policy.keepRecentTurns) return null;\r\n const turns = rawMessages\r\n .filter(message => Number.isFinite(message?.turn))\r\n .map(message => Number(message.turn));\r\n if (turns.length === 0) return null;\r\n const uniqueTurns = [...new Set(turns)].sort((a, b) => a - b);\r\n const keptTurns = uniqueTurns.slice(-policy.keepRecentTurns);\r\n return new Set(keptTurns);\r\n}\r\n\r\nfunction getFoldedToolTurnSet(rawMessages: any[], retainedTurns: Set<number> | null, policy: TrimExportPolicy): Set<number> | null {\r\n if (policy.toolFoldScope === 'all') return null;\r\n if (policy.toolFoldRecentTurns) {\r\n const turns = rawMessages\r\n .map((message, index) => getMessageTurn(message, index))\r\n .filter(Number.isFinite);\r\n if (turns.length === 0) return null;\r\n const uniqueTurns = [...new Set(turns)].sort((a, b) => a - b);\r\n return new Set(uniqueTurns.slice(-policy.toolFoldRecentTurns));\r\n }\r\n return retainedTurns;\r\n}\r\n\r\nfunction shouldKeepDialogueMessage(role: string, policy: TrimExportPolicy, tag?: string): boolean {\r\n if (role === 'user') return policy.includeUserMessages;\r\n if (role === 'assistant') return policy.includeAssistantMessages;\r\n if (role === 'system') {\r\n if (tag && Array.isArray(policy.keepSystemTags) && policy.keepSystemTags.includes(tag)) return true;\r\n return policy.includeSystemMessages;\r\n }\r\n return false;\r\n}\r\n\r\nfunction shouldHandleToolActivity(messageTurn: number, foldedToolTurns: Set<number> | null, policy: TrimExportPolicy): boolean {\r\n if (policy.toolFoldScope === 'all') return true;\r\n if (!foldedToolTurns) return false;\r\n return foldedToolTurns.has(messageTurn);\r\n}\r\n\r\nfunction getSkillInvokeProtectedMessages(rawMessages: any[], policy: TrimExportPolicy): Set<number> | null {\r\n if (!policy.keepRecentSkillInvokes) return null;\r\n\r\n // Phase 1: find the N most recent turns that contain invoke_skill calls.\r\n const skillTurns: number[] = [];\r\n for (let i = rawMessages.length - 1; i >= 0; i--) {\r\n const m = rawMessages[i];\r\n if (m?.role !== 'assistant') continue;\r\n const toolCalls = Array.isArray(m.toolCalls) ? m.toolCalls : [];\r\n const hasSkill = toolCalls.some((tc: any) => tc?.name === 'invoke_skill');\r\n if (!hasSkill) continue;\r\n const turn = getMessageTurn(m, i);\r\n if (!skillTurns.includes(turn)) {\r\n skillTurns.unshift(turn);\r\n if (skillTurns.length >= (policy.keepRecentSkillInvokes as number) && policy.keepRecentSkillInvokes !== Infinity) break;\r\n }\r\n }\r\n if (skillTurns.length === 0) return null;\r\n const protectedTurnSet = new Set(skillTurns);\r\n\r\n // Phase 2: collect only the specific messages to protect —\r\n // the assistant messages that actually carry invoke_skill calls,\r\n // and the tool-result messages whose toolCallId matches those calls.\r\n const protectedIndices = new Set<number>();\r\n const skillToolCallIds = new Set<string>();\r\n\r\n rawMessages.forEach((message, index) => {\r\n const turn = getMessageTurn(message, index);\r\n if (!protectedTurnSet.has(turn)) return;\r\n if (message?.role !== 'assistant') return;\r\n const toolCalls = Array.isArray(message.toolCalls) ? message.toolCalls : [];\r\n const skillCalls = toolCalls.filter((tc: any) => tc?.name === 'invoke_skill');\r\n if (skillCalls.length === 0) return;\r\n protectedIndices.add(index);\r\n for (const tc of skillCalls) {\r\n const id = cleanInlineText(tc?.id);\r\n if (id) skillToolCallIds.add(id);\r\n }\r\n });\r\n\r\n // Protect tool results for those skill calls (may be in a different turn\r\n // in edge cases, so match by toolCallId rather than turn).\r\n rawMessages.forEach((message, index) => {\r\n if (message?.role !== 'tool') return;\r\n const toolCallId = cleanInlineText(message?.toolCallId);\r\n if (toolCallId && skillToolCallIds.has(toolCallId)) {\r\n protectedIndices.add(index);\r\n }\r\n });\r\n\r\n return protectedIndices.size > 0 ? protectedIndices : null;\r\n}\r\n\r\nfunction createSeedMessage(role: string, content: string, turn: number, tag?: string): SessionSeedMessage | null {\r\n const text = cleanMultilineText(content);\r\n if (!text) return null;\r\n return {\r\n role,\r\n content: text,\r\n turn: Number.isFinite(turn) ? turn : null,\r\n ...(tag ? { tag } : {}),\r\n } as SessionSeedMessage;\r\n}\r\n\r\nfunction deduplicateToolCallSummaries(summaries: string[]): string[] {\r\n const counts = new Map<string, number>();\r\n const order: string[] = [];\r\n for (const s of summaries) {\r\n if (counts.has(s)) {\r\n counts.set(s, counts.get(s)! + 1);\r\n } else {\r\n counts.set(s, 1);\r\n order.push(s);\r\n }\r\n }\r\n return order.map(s => {\r\n const c = counts.get(s)!;\r\n return c > 1 ? `${s} ×${c}` : s;\r\n });\r\n}\r\n\r\nfunction flushPendingToolFold(seedMessages: SessionSeedMessage[], pendingFold: any, policy: TrimExportPolicy, stats: any): null {\r\n if (!pendingFold || pendingFold.toolCalls.length === 0) {\r\n return null;\r\n }\r\n\r\n const deduped = deduplicateToolCallSummaries(pendingFold.toolCalls);\r\n const lines = ['[Folded tool activity]'];\r\n lines.push(`assistant tool calls: ${deduped.join('; ')}`);\r\n\r\n const note = createSeedMessage(policy.foldedToolNoteRole, lines.join('\\n'), pendingFold.turn, 'folded-tool-activity');\r\n if (note) {\r\n seedMessages.push(note);\r\n stats.foldedToolNoteCount += 1;\r\n }\r\n return null;\r\n}\r\n\r\nexport interface TrimStats {\r\n originalMessageCount: number;\r\n keptSeedMessageCount: number;\r\n droppedMessageCount: number;\r\n keptDialogueMessageCount: number;\r\n droppedDialogueMessageCount: number;\r\n foldedToolCallCount: number;\r\n droppedToolCallCount: number;\r\n foldedToolMessageCount: number;\r\n droppedToolMessageCount: number;\r\n foldedToolNoteCount: number;\r\n keptProtectedToolCallCount: number;\r\n keptProtectedToolMessageCount: number;\r\n retainedTurnCount: number | null;\r\n foldedToolTurnCount: number | null;\r\n}\r\n\r\nexport interface TrimmedSeedResult {\r\n seedMessages: SessionSeedMessage[];\r\n stats: TrimStats;\r\n}\r\n\r\nexport function buildTrimmedSeedMessages(rawMessages: any[], policy: TrimExportPolicy): TrimmedSeedResult {\r\n const retainedTurns = getRetainedTurnSet(rawMessages, policy);\r\n const foldedToolTurns = getFoldedToolTurnSet(rawMessages, retainedTurns, policy);\r\n const skillProtectedIndices = getSkillInvokeProtectedMessages(rawMessages, policy);\r\n const protectedToolNames = new Set(Array.isArray(policy?.preserveToolNames) ? policy.preserveToolNames : []);\r\n const protectedToolCallIds = new Set<string>();\r\n for (const message of rawMessages) {\r\n const toolCalls = Array.isArray(message?.toolCalls) ? message.toolCalls : [];\r\n for (const call of toolCalls) {\r\n const name = cleanInlineText(call?.name);\r\n const id = cleanInlineText(call?.id);\r\n if (name && id && protectedToolNames.has(name)) {\r\n protectedToolCallIds.add(id);\r\n }\r\n }\r\n }\r\n if (skillProtectedIndices) {\r\n rawMessages.forEach((message, index) => {\r\n if (!skillProtectedIndices.has(index) || message?.role !== 'assistant') return;\r\n const toolCalls = Array.isArray(message?.toolCalls) ? message.toolCalls : [];\r\n for (const call of toolCalls) {\r\n const id = cleanInlineText(call?.id);\r\n if (id && cleanInlineText(call?.name) === 'invoke_skill') {\r\n protectedToolCallIds.add(id);\r\n }\r\n }\r\n });\r\n }\r\n const fullPreserveFrom = policy.fullPreserveFromTurn;\r\n const preservedTurnSet = Array.isArray(policy.preservedTurns) && policy.preservedTurns.length > 0\r\n ? new Set(policy.preservedTurns)\r\n : null;\r\n const preservedMsgIndices = Array.isArray(policy.preservedMsgRanges) && policy.preservedMsgRanges.length > 0\r\n ? new Set<number>()\r\n : null;\r\n if (preservedMsgIndices) {\r\n for (const [start, end] of policy.preservedMsgRanges!) {\r\n for (let i = start; i <= end; i++) {\r\n preservedMsgIndices.add(i);\r\n }\r\n }\r\n }\r\n const hasPreserveBoundary = preservedMsgIndices || preservedTurnSet || Number.isFinite(fullPreserveFrom as number);\r\n const seedMessages: SessionSeedMessage[] = [];\r\n const stats: Omit<TrimStats, 'retainedTurnCount' | 'foldedToolTurnCount'> = {\r\n originalMessageCount: rawMessages.length,\r\n keptSeedMessageCount: 0,\r\n droppedMessageCount: 0,\r\n keptDialogueMessageCount: 0,\r\n droppedDialogueMessageCount: 0,\r\n foldedToolCallCount: 0,\r\n droppedToolCallCount: 0,\r\n foldedToolMessageCount: 0,\r\n droppedToolMessageCount: 0,\r\n foldedToolNoteCount: 0,\r\n keptProtectedToolCallCount: 0,\r\n keptProtectedToolMessageCount: 0,\r\n };\r\n\r\n let pendingFold: any = null;\r\n\r\n const ensurePendingFold = (turn: number): any => {\r\n if (!pendingFold) {\r\n pendingFold = {\r\n turn,\r\n toolCalls: [],\r\n toolResults: [],\r\n };\r\n }\r\n return pendingFold;\r\n };\r\n\r\n const flushIfNeeded = (): void => {\r\n pendingFold = flushPendingToolFold(seedMessages, pendingFold, policy, stats);\r\n };\r\n\r\n const flushImmediatelyIfConfigured = (): void => {\r\n if (policy.foldConsecutiveToolActivity === false) {\r\n flushIfNeeded();\r\n }\r\n };\r\n\r\n rawMessages.forEach((message, index) => {\r\n const role = cleanInlineText(message?.role);\r\n if (!role) {\r\n stats.droppedMessageCount += 1;\r\n return;\r\n }\r\n\r\n const turn = getMessageTurn(message, index);\r\n const withinDialogueWindow = hasPreserveBoundary || !retainedTurns || retainedTurns.has(turn);\r\n\r\n const inPreserveZone = preservedMsgIndices\r\n ? preservedMsgIndices.has(index)\r\n : preservedTurnSet\r\n ? preservedTurnSet.has(turn)\r\n : (Number.isFinite(fullPreserveFrom as number) && turn >= (fullPreserveFrom as number));\r\n if (inPreserveZone) {\r\n flushIfNeeded();\r\n if (role === 'tool' || shouldKeepDialogueMessage(role, policy, message?.tag)) {\r\n seedMessages.push({ ...message, turn } as SessionSeedMessage);\r\n stats.keptSeedMessageCount += 1;\r\n if (role !== 'tool') {\r\n stats.keptDialogueMessageCount += 1;\r\n }\r\n } else {\r\n stats.droppedDialogueMessageCount += 1;\r\n stats.droppedMessageCount += 1;\r\n }\r\n return;\r\n }\r\n\r\n let toolCalls = Array.isArray(message?.toolCalls) ? message.toolCalls : [];\r\n const protectedCalls = role === 'assistant'\r\n ? toolCalls.filter((call: any) => protectedToolCallIds.has(cleanInlineText(call?.id)))\r\n : [];\r\n if (protectedCalls.length > 0 && shouldKeepDialogueMessage(role, policy, message?.tag)) {\r\n flushIfNeeded();\r\n seedMessages.push({ ...message, toolCalls: protectedCalls, turn } as SessionSeedMessage);\r\n stats.keptSeedMessageCount += 1;\r\n stats.keptDialogueMessageCount += 1;\r\n stats.keptProtectedToolCallCount += protectedCalls.length;\r\n\r\n toolCalls = toolCalls.filter((call: any) => !protectedToolCallIds.has(cleanInlineText(call?.id)));\r\n if (toolCalls.length === 0) {\r\n return;\r\n }\r\n message = { ...message, content: '', toolCalls };\r\n }\r\n\r\n if (role === 'tool' && protectedToolCallIds.has(cleanInlineText(message?.toolCallId))) {\r\n seedMessages.push({ ...message, turn } as SessionSeedMessage);\r\n stats.keptSeedMessageCount += 1;\r\n stats.keptProtectedToolMessageCount += 1;\r\n return;\r\n }\r\n\r\n if (role === 'tool') {\r\n if (!withinDialogueWindow) {\r\n stats.droppedToolMessageCount += 1;\r\n stats.droppedMessageCount += 1;\r\n return;\r\n }\r\n\r\n const shouldHandle = hasPreserveBoundary\r\n ? true\r\n : shouldHandleToolActivity(turn, foldedToolTurns, policy);\r\n if (policy.toolMessageMode === 'keep' || !shouldHandle) {\r\n flushIfNeeded();\r\n const seedMessage = createSeedMessage('tool', message.content, turn, message?.tag);\r\n if (seedMessage) {\r\n seedMessages.push(seedMessage);\r\n stats.keptSeedMessageCount += 1;\r\n } else {\r\n stats.droppedMessageCount += 1;\r\n }\r\n return;\r\n }\r\n\r\n if (policy.toolMessageMode === 'drop') {\r\n stats.droppedToolMessageCount += 1;\r\n stats.droppedMessageCount += 1;\r\n return;\r\n }\r\n\r\n ensurePendingFold(turn);\r\n stats.foldedToolMessageCount += 1;\r\n stats.droppedMessageCount += 1;\r\n flushImmediatelyIfConfigured();\r\n return;\r\n }\r\n\r\n const shouldHandleToolCalls = toolCalls.length > 0 && (hasPreserveBoundary\r\n ? true\r\n : shouldHandleToolActivity(turn, foldedToolTurns, policy));\r\n const toolCallSummaries = summarizeAssistantToolCalls(toolCalls, policy);\r\n\r\n if (!withinDialogueWindow) {\r\n if (role === 'assistant' || role === 'user' || role === 'system') {\r\n stats.droppedDialogueMessageCount += 1;\r\n }\r\n if (shouldHandleToolCalls) {\r\n if (policy.assistantToolCallMode === 'fold') {\r\n stats.foldedToolCallCount += toolCalls.length;\r\n } else if (policy.assistantToolCallMode === 'drop') {\r\n stats.droppedToolCallCount += toolCalls.length;\r\n }\r\n }\r\n stats.droppedMessageCount += 1;\r\n return;\r\n }\r\n\r\n const isToolOnlyAssistantFold = role === 'assistant'\r\n && !cleanMultilineText(message.content)\r\n && toolCalls.length > 0\r\n && policy.assistantToolCallMode === 'fold'\r\n && shouldHandleToolCalls;\r\n if (!isToolOnlyAssistantFold) {\r\n flushIfNeeded();\r\n }\r\n\r\n if (!shouldKeepDialogueMessage(role, policy, message?.tag)) {\r\n stats.droppedDialogueMessageCount += 1;\r\n stats.droppedMessageCount += 1;\r\n } else {\r\n let assistantContent = cleanMultilineText(message.content);\r\n if (role === 'assistant' && toolCalls.length > 0 && policy.assistantToolCallMode === 'keep' && toolCallSummaries.length > 0 && shouldHandleToolCalls) {\r\n assistantContent = `${assistantContent}\\n[tool calls kept inline] ${toolCallSummaries.join('; ')}`.trim();\r\n }\r\n const seedMessage = createSeedMessage(role, assistantContent, turn, message?.tag);\r\n if (seedMessage) {\r\n seedMessages.push(seedMessage);\r\n stats.keptSeedMessageCount += 1;\r\n if (role === 'assistant' || role === 'user' || role === 'system') {\r\n stats.keptDialogueMessageCount += 1;\r\n }\r\n } else if (role !== 'assistant' || toolCalls.length === 0) {\r\n stats.droppedMessageCount += 1;\r\n }\r\n }\r\n\r\n if (role === 'assistant' && toolCalls.length > 0 && shouldHandleToolCalls) {\r\n if (policy.assistantToolCallMode === 'fold') {\r\n const fold = ensurePendingFold(turn);\r\n fold.toolCalls.push(...toolCallSummaries);\r\n stats.foldedToolCallCount += toolCalls.length;\r\n flushImmediatelyIfConfigured();\r\n } else if (policy.assistantToolCallMode === 'drop') {\r\n stats.droppedToolCallCount += toolCalls.length;\r\n }\r\n }\r\n });\r\n\r\n flushPendingToolFold(seedMessages, pendingFold, policy, stats);\r\n return {\r\n seedMessages,\r\n stats: {\r\n ...stats,\r\n retainedTurnCount: retainedTurns ? retainedTurns.size : null,\r\n foldedToolTurnCount: foldedToolTurns ? foldedToolTurns.size : null,\r\n },\r\n };\r\n}\r\n\r\n// ============ Transformation 契约实现 ============\r\n\r\nexport interface TrimTranscriptTransformationOptions {\r\n /**\r\n * 默认策略(可被 `transform` 传入的 policy 按需覆盖)。缺省为空对象,\r\n * 即 `normalizeExportPolicy({})` 的默认裁剪行为。\r\n */\r\n defaultPolicy?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Trim-Transcript 变换:对源会话快照施加裁剪变换,产出 SuccessorSeed。\r\n *\r\n * 从 `sourceSnapshot.runtime.context.messages` 读取消息(session-store 契约级\r\n * 消费面),以 `policy` 为裁剪策略面(归一化语义见 normalizeExportPolicy)。\r\n */\r\nexport class TrimTranscriptTransformation implements SessionTransformation {\r\n readonly id = 'agentdev.trim-transcript';\r\n\r\n private readonly defaultPolicy: Record<string, unknown>;\r\n\r\n constructor(options: TrimTranscriptTransformationOptions = {}) {\r\n this.defaultPolicy = options.defaultPolicy ?? {};\r\n }\r\n\r\n async transform(input: TransformInput, _ctx: TransformContext): Promise<SuccessorSeed> {\r\n const snapshot: AgentSessionSnapshot = input.sourceSnapshot;\r\n const rawMessages = Array.isArray(snapshot?.runtime?.context?.messages)\r\n ? snapshot.runtime.context.messages\r\n : [];\r\n\r\n const policy = normalizeExportPolicy({ ...this.defaultPolicy, ...(input.policy ?? {}) });\r\n const { seedMessages, stats } = buildTrimmedSeedMessages(rawMessages, policy);\r\n\r\n return {\r\n schemaVersion: HANDOFF_SCHEMA_VERSION,\r\n seedMessages,\r\n meta: {\r\n compilerVersion: HANDOFF_COMPILER_VERSION,\r\n seedKind: 'message-replay',\r\n mode: policy.strategy,\r\n policy,\r\n stats,\r\n },\r\n };\r\n }\r\n}\r\n\r\n// 兼容导出(与 Claw 策略引擎同名,便于 golden 对照直读)\r\nexport { sanitizeFragment, cleanInlineText, cleanMultilineText };\r\n","/**\r\n * Summary 官方变换(ticket 006 新增)。\r\n *\r\n * 基于 005 的 `TransformContext.llm` 进程内注入,对源会话快照做一次摘要变换,\r\n * 产出 SuccessorSeed(summary-message seed)。提示词以 Claw\r\n * `claude-compact-prompts.js` 为蓝本。\r\n *\r\n * 不移植 Claw 的 mirror 子进程管线——那是 Claw 装配细节(模型配置来源),\r\n * 由 Claw 侧决定何时切换到进程内注入。\r\n *\r\n * 组合语义(ticket 006 收敛定案):不做通用 compose 组合子机制。官方单实现\r\n * 先落——`TrimTranscriptWithSummaryTransformation` 把「trim 裁剪 + 追加摘要」\r\n * 硬编码混合语义 1:1 迁移(对齐 Claw `trim-transcript-with-summary`)。\r\n */\r\n\r\nimport type { Message, LLMResponse } from '../../types.js';\r\nimport type { AgentSessionSnapshot } from '../../session-store.js';\r\nimport type {\r\n SessionTransformation,\r\n TransformInput,\r\n TransformContext,\r\n SuccessorSeed,\r\n SessionSeedMessage,\r\n} from '../index.js';\r\nimport {\r\n DEFAULT_EXPORT_POLICY,\r\n normalizeExportPolicy,\r\n buildTrimmedSeedMessages,\r\n HANDOFF_SCHEMA_VERSION,\r\n} from './trim-transcript.js';\r\n\r\n// ============ 提示词(以 claude-compact-prompts.js 为蓝本) ============\r\n\r\nconst BASE_SUMMARY_PROMPT = `你的任务是为当前对话创建一份详细摘要,重点关注用户的明确请求和该 agent 之前采取的行动。\r\n这份摘要应保留恢复工作所需的任务连续性关键信息。\r\n\r\n按时间顺序分析对话:\r\n\r\n1. 识别用户的明确请求和意图\r\n2. 保留用户较为模糊的术语概念与情况表述,不做过多推测与转述\r\n3. 识别该 agent 的方法和关键决策,以及用户的反馈,特别注意该 agent 曾理解有误、或后续改变方向的用户反馈\r\n4. 记录与用户探讨的重要结论,以及最终放弃、或纠正某些决策的原因\r\n5. 记录当前讨论要点之于整个项目的层次,以及重要的技术概念、文件名、代码模式\r\n6. 记录遇到的错误及修复方式\r\n\r\n摘要使用以下十段式结构:\r\n\r\n1. 主要请求与意图\r\n2. 用户观点表态与方向调整\r\n3. 关键技术概念\r\n4. 重要结论与决策\r\n5. 参考文件、技能与代码段\r\n6. 错误与修复\r\n7. 问题解决过程\r\n8. 待办事项\r\n9. 当前工作\r\n10. 可选的下一步\r\n\r\n摘要控制在 3000 个词以内,优先使用要点而非段落。`;\r\n\r\nconst TRIM_APPENDED_SUMMARY_PROMPT = `你的任务是为当前对话创建一份详细摘要,留存其中的关键信息,并让摘要本身结构清晰、脉络连贯、可以独立阅读。\r\n\r\n需要注意:在摘要生成后,工具调用记录中的参数细节和返回内容可能不会继续保留;在这次精简场景中,工具活动通常只保留调用签名。用户消息和 Agent 的主要回复则通常仍会保留。因此,工具返回中出现过的完整标识符、文件内容与代码事实、统计数字、命令与查询的实际输出、报错原文、外部资料中的具体机制等信息,需要在摘要中重新落地,不能假定读者还能从工具记录中找回。\r\n\r\n摘要应同时承担两类内容:一类是工具调用带来的具体信息,另一类是对话脉络、方向变化、决策和结论的概括。后者可以适度复述,使摘要流畅、完整、独立可读;前者则应覆盖工具呈现的不同信息维度,而不要只围绕某一条显眼的主线进行筛选。信息是否保留,主要依据它本身的具体程度、独立价值和对理解会话的帮助,不要过早假定某个维度之后不会用到。\r\n\r\n按时间顺序分析对话,重点关注:\r\n\r\n1. 工具调用中获得的重要事实、技术信息、代码机制、文件内容、测试结果和外部资料。这些内容在精简后可能无处可查,应从多个相关维度尽量完整地保留。\r\n2. 重要的文件名、路径、函数、类型、数据结构、关键参数、代码位置、错误信息、数字、版本、命令结果等具体信息,一律使用完整值,例如完整的 ID、哈希和路径,不要用省略号或“等 N 项”带过。对于实现细节和机制说明,可以适当保留具体的定位信息。\r\n3. 对于已经在 Agent 回复中明确表达的重要结论、技术判断和决策,可以概括复述,以保持叙事连贯;同时记录其中主要存在于工具调用中的事实、证据和必要依据。\r\n4. 用户对方向的重要反馈和纠正,尤其是曾经理解有误、后来改变方向的部分;可以用概括方式复述,让读者能够理解对话如何发展。\r\n5. 已经尝试但被否定或放弃的重要方向,以及不再沿用这些方向的原因。普通操作失误或偶发错误通常无需记录,除非它提供了一个独立的技术事实、边界或判断依据。\r\n6. 已经实际完成的重要修改、操作和状态变化,以及仍然存在的重要问题。注意区分计划、尝试、完成和验证;验证结果应落到具体数字或其他可核对的最终值。\r\n7. 如果某个结论或机制只能概括表达,而原始工具信息中还有可能需要重新确认的细节,应说明缺少什么,并给出完整的定位信息,例如完整路径、完整 ID 或可复查的命令。\r\n8. 对外部调研和参考资料,优先保留资料本身提供的具体机制、实现方式、差异和关键事实,不要只记录最终评价或笼统结论。对于较长的工具输出,提炼其中多个独立且有代表性的事实和关键片段,而不是只保留一个总结性结论。\r\n\r\n在提供最终摘要之前,先用 <analysis> 标签进行一次信息对照:检查准备写入的具体标识符、数字、路径、输出片段和其他事实,区分哪些信息已经在用户消息或 Agent 回复中完整出现,哪些信息主要或仅存在于工具调用中。对话中已经存在的信息可以用概括方式复述;工具调用中出现的具体信息则应以完整、可核对的形式写入摘要。\r\n\r\n摘要使用自然的 Markdown 结构,根据实际内容组织,例如:\r\n\r\n## 重要发现与技术信息\r\n\r\n## 关键证据与实现细节\r\n\r\n## 结论背后的补充依据\r\n\r\n## 已排除的问题与方向\r\n\r\n## 修改、执行结果与当前状态\r\n\r\n## 需要重新查看的细节与位置\r\n\r\n不要求所有章节都出现,也不要为了填充结构重复内容。\r\n\r\n摘要应覆盖工具调用带来的具体信息和对话脉络的必要概括。对话已有的完整论述不必逐字重现,但可以提炼其发展过程、方向变化和结论,使摘要读起来完整自然;工具信息则应注意覆盖不同维度,并保留其中能够独立说明事实的细节。\r\n\r\n不要为了完整而记录所有工具调用、所有错误或完整的问题解决过程。纯粹的中间操作过程、偶发错误、与任何结论无关的临时输出可以省略;已经被后续结果取代的中间值可以不记,但最终值和独立的技术事实应保留。\r\n\r\n摘要控制在 3000 个词以内,优先使用要点而非长段落;长度以信息完整和结构清晰为准。`;\r\n\r\nexport interface SummaryPromptOptions {\r\n /** 附加压缩指令(追加到提示词末尾)。 */\r\n additionalInstructions?: string;\r\n /** true 时使用 trim-appended 专用提示词(组合语义用)。 */\r\n trimAppended?: boolean;\r\n /** exploration 会话使用三段式探索提示词。 */\r\n exploration?: boolean;\r\n}\r\n\r\n/** 生成摘要提示词(对齐 claude-compact-prompts.js 的 buildClaudeCompactPrompt)。 */\r\nexport function buildSummaryPrompt(options: SummaryPromptOptions = {}): string {\r\n const extra = typeof options.additionalInstructions === 'string' && options.additionalInstructions.trim()\r\n ? `## 额外压缩指令\\n${options.additionalInstructions.trim()}`\r\n : '';\r\n if (options.trimAppended) {\r\n return [TRIM_APPENDED_SUMMARY_PROMPT, extra].filter(Boolean).join('\\n');\r\n }\r\n return [BASE_SUMMARY_PROMPT, extra].filter(Boolean).join('\\n');\r\n}\r\n\r\n// ============ 文本清洗 / 摘要提取(对齐 claude-compact-prompts.js) ============\r\n\r\nfunction cleanMultilineText(value: unknown): string {\r\n if (typeof value !== 'string') return '';\r\n const normalized = value.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\r\n const lines = normalized.split('\\n').map((line) => line.replace(/[ \\t]+/g, ' ').trimEnd());\r\n const compacted: string[] = [];\r\n let blankRun = 0;\r\n for (const line of lines) {\r\n if (line.trim() === '') {\r\n blankRun += 1;\r\n if (blankRun <= 1) {\r\n compacted.push('');\r\n }\r\n continue;\r\n }\r\n blankRun = 0;\r\n compacted.push(line);\r\n }\r\n return compacted.join('\\n').trim();\r\n}\r\n\r\n/** 从 LLM 原始响应中剥离 <analysis> 与 <summary> 包裹,得到纯摘要文本。 */\r\nexport function stripCompactAnalysis(rawText: string): string {\r\n const text = typeof rawText === 'string' ? rawText.trim() : '';\r\n if (!text) return '';\r\n\r\n const withoutAnalysis = text.replace(/<analysis>[\\s\\S]*?<\\/analysis>/gi, '').trim();\r\n const summaryMatch = withoutAnalysis.match(/<summary>([\\s\\S]*?)<\\/summary>/i);\r\n const summaryBody = summaryMatch ? summaryMatch[1].trim() : withoutAnalysis;\r\n return summaryBody.replace(/\\n{3,}/g, '\\n\\n').trim();\r\n}\r\n\r\n// ============ 扫描重要文件 / 技能(对齐 claude-compact-prompts.js) ============\r\n\r\nexport interface ScanFilesAndSkillsResult {\r\n files: string[];\r\n skills: string[];\r\n fileRanges: Record<string, string>;\r\n}\r\n\r\n/** 从原始消息中扫描 read/write/edit 与 invoke_skill 调用,收集重要文件、技能与行号范围。 */\r\nexport function scanFilesAndSkills(rawMessages: any[]): ScanFilesAndSkillsResult {\r\n const files = new Set<string>();\r\n const skills = new Set<string>();\r\n const fileRanges: Record<string, string> = {};\r\n for (const message of rawMessages) {\r\n if (message.role !== 'assistant' || !Array.isArray(message.toolCalls)) continue;\r\n for (const tc of message.toolCalls) {\r\n const name = typeof tc?.name === 'string' ? tc.name : '';\r\n const args = tc?.arguments && typeof tc.arguments === 'object' ? tc.arguments : {};\r\n if ((name === 'read' || name === 'write' || name === 'edit') && typeof args.filePath === 'string') {\r\n files.add(args.filePath);\r\n }\r\n if (name === 'read' && typeof args.filePath === 'string') {\r\n const offset = typeof args.offset === 'number' ? args.offset : (typeof args.line === 'number' ? args.line : 0);\r\n const limit = typeof args.limit === 'number' ? args.limit : 0;\r\n if (offset > 0 || limit > 0) {\r\n const start = Math.max(1, offset || 1);\r\n const end = limit > 0 ? start + limit - 1 : start;\r\n fileRanges[args.filePath] = `${start}-${end}`;\r\n }\r\n }\r\n if (name === 'invoke_skill' && typeof args.skill === 'string') {\r\n skills.add(args.skill);\r\n }\r\n }\r\n }\r\n return { files: [...files], skills: [...skills], fileRanges };\r\n}\r\n\r\n// ============ 策略归一化 ============\r\n\r\nexport interface SummaryExportPolicy {\r\n strategy: string;\r\n summaryShape: string;\r\n maxAttempts: number;\r\n additionalInstructions: string;\r\n}\r\n\r\nexport function normalizeSummaryPolicy(rawPolicy: Record<string, unknown> = {}): SummaryExportPolicy {\r\n return {\r\n strategy: 'summarized-nine-section',\r\n summaryShape: 'claude-nine-section-v1',\r\n maxAttempts: Number.isFinite(rawPolicy?.maxAttempts)\r\n ? Math.max(1, Math.min(5, Number(rawPolicy.maxAttempts)))\r\n : 3,\r\n additionalInstructions: cleanMultilineText(rawPolicy?.additionalInstructions),\r\n };\r\n}\r\n\r\n// ============ 种子消息构建 ============\r\n\r\n/**\r\n * 构建 summary 种子消息(对齐 summarized-handoff / trim-appended-summary)。\r\n * 返回 role:'system' 的摘要消息。\r\n */\r\nexport function buildSummarySeedMessage(summaryText: string): SessionSeedMessage {\r\n const body = cleanMultilineText(summaryText);\r\n return {\r\n role: 'system',\r\n content: [\r\n '以下是前一会话的工作摘要,用于延续同一任务上下文。',\r\n '摘要涵盖前一轮对话的关键内容。',\r\n '',\r\n '摘要:',\r\n body,\r\n '',\r\n '请基于此摘要继续工作,无需要求用户重复陈述背景。',\r\n ].join('\\n'),\r\n turn: 0,\r\n };\r\n}\r\n\r\n// ============ LLM 调用 ============\r\n\r\nfunction extractMessages(snapshot: AgentSessionSnapshot): any[] {\r\n return Array.isArray(snapshot?.runtime?.context?.messages)\r\n ? snapshot.runtime.context.messages\r\n : [];\r\n}\r\n\r\n/**\r\n * 身份澄清前缀:摘要请求携带原会话完整记录注入,需明确告知模型\r\n * 这是一份已存在的会话记录而非其真实交互,防止模型代入原 agent 身份\r\n * (尤其当记录中途残留原身份相关内容时)。\r\n */\r\nconst SUMMARY_ROLE_PREAMBLE = `以下呈现的是一份已经存在的会话记录(transcript)。注意:这份记录不是你与任何人的真实交互,你也不是该会话中的任何角色——不要代入其中 agent 的身份,不要延续其中的任务或对话。你的唯一任务是:以旁观者身份,按本提示的要求为这份完整记录撰写摘要。`;\r\n\r\n/** 结尾锚定:标记会话记录到此为止,其上全部内容才是概括对象。 */\r\nconst SUMMARY_CLOSING_ANCHOR = '会话记录到此为止。请基于以上全部记录,按照系统提示的要求输出摘要;不要续写会话,不要扮演其中的任何角色。';\r\n\r\n/** 单条工具返回注入摘要请求的最大字符数(长输出截断,防止撑爆上下文)。 */\r\nconst TOOL_RESULT_MAX_CHARS = 1200;\r\n\r\nfunction truncateToolResult(content: unknown): string {\r\n const text = typeof content === 'string' ? content : '';\r\n if (text.length <= TOOL_RESULT_MAX_CHARS) return text;\r\n return `${text.slice(0, TOOL_RESULT_MAX_CHARS)}\\n…(返回已截断,原始长度 ${text.length} 字符)`;\r\n}\r\n\r\n/** 调用签名(与 folded-tool-activity 折叠行同格式):read/edit/write 取文件名,invoke_skill 取技能名,其余用工具名。 */\r\nfunction toolCallSignature(call: any): string {\r\n const name = typeof call?.name === 'string' && call.name ? call.name : 'tool';\r\n let args = call?.arguments ?? call?.args;\r\n if (typeof args === 'string') {\r\n try { args = JSON.parse(args); } catch { args = null; }\r\n }\r\n if (args && typeof args === 'object') {\r\n const record = args as Record<string, unknown>;\r\n const filePath = typeof record.filePath === 'string' ? record.filePath : '';\r\n if ((name === 'read' || name === 'edit' || name === 'write') && filePath) {\r\n return `${name}(${filePath.split(/[\\\\/]/).pop() || filePath})`;\r\n }\r\n if (name === 'invoke_skill' && typeof record.skill === 'string') {\r\n return `invoke_skill(${record.skill})`;\r\n }\r\n }\r\n return name;\r\n}\r\n\r\nfunction buildChatMessages(snapshot: AgentSessionSnapshot, prompt: string): Message[] {\r\n const rawMessages = extractMessages(snapshot);\r\n const sys: Message = { role: 'system', content: `${SUMMARY_ROLE_PREAMBLE}\\n\\n${prompt}` };\r\n // 剥离会话头部的静态 system 前缀(身份设定、环境文档、全局约束),\r\n // 由摘要指令替换其成为唯一 system 前缀,避免模型在摘要请求中继续扮演原 agent。\r\n // 对话中途注入的 system(folded-tool-activity、前轮摘要 seed、任务状态等)\r\n // 不在头部前缀内,作为摘要素材原样保留。\r\n let headEnd = 0;\r\n while (headEnd < rawMessages.length && rawMessages[headEnd]?.role === 'system') headEnd++;\r\n\r\n // 工具返回配对表:toolCallId → 调用签名,让摘要模型能把每条返回对应到具体调用。\r\n // 补偿型摘要的增量信息(文件内容、命令输出、报错原文)都在工具返回里,\r\n // 必须随对话主体一起进入摘要请求,否则模型只能依赖 assistant 的转述。\r\n const callSignatures = new Map<string, string>();\r\n for (const m of rawMessages) {\r\n if (m?.role !== 'assistant' || !Array.isArray(m.toolCalls)) continue;\r\n for (const tc of m.toolCalls) {\r\n const id = typeof tc?.id === 'string' ? tc.id : '';\r\n if (id) callSignatures.set(id, toolCallSignature(tc));\r\n }\r\n }\r\n\r\n const history: Message[] = [];\r\n for (const m of rawMessages.slice(headEnd)) {\r\n if (m?.role === 'tool') {\r\n const signature = (typeof m?.toolCallId === 'string' && callSignatures.get(m.toolCallId)) || '未匹配调用';\r\n history.push({\r\n role: 'system',\r\n content: `[工具返回 ${signature}]\\n${truncateToolResult(m?.content)}`,\r\n tag: 'tool-result',\r\n } as Message);\r\n continue;\r\n }\r\n history.push({\r\n role: m?.role,\r\n content: typeof m?.content === 'string' ? m.content : '',\r\n turn: m?.turn,\r\n ...(m?.tag ? { tag: m.tag } : {}),\r\n } as Message);\r\n }\r\n const closing: Message = { role: 'user', content: SUMMARY_CLOSING_ANCHOR };\r\n return [sys, ...history, closing].filter((m) => m.role === 'system' || m.role === 'user' || m.role === 'assistant');\r\n}\r\n\r\n/** 调用 llm 生成摘要文本(空工具集、非流式)。失败时抛出。 */\r\nexport async function generateSummaryText(\r\n ctx: TransformContext,\r\n snapshot: AgentSessionSnapshot,\r\n prompt: string,\r\n): Promise<string> {\r\n const messages = buildChatMessages(snapshot, prompt);\r\n const response: LLMResponse = await ctx.llm.chat(messages, [], {\r\n noStream: true,\r\n ...(ctx.signal ? { signal: ctx.signal } : {}),\r\n });\r\n const text = stripCompactAnalysis(response.content ?? '');\r\n if (!text) {\r\n throw new Error('Summary LLM returned an empty summary');\r\n }\r\n return text;\r\n}\r\n\r\n// ============ Transformation 契约实现 ============\r\n\r\nexport interface SummaryTransformationOptions {\r\n defaultPolicy?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Summary 变换:对源会话快照做摘要变换,产出 SuccessorSeed。\r\n * 摘要由 `TransformContext.llm` 进程内生成(对齐 ADR-0002 Q3=A)。\r\n */\r\nexport class SummaryTransformation implements SessionTransformation {\r\n readonly id = 'agentdev.summary';\r\n\r\n private readonly defaultPolicy: Record<string, unknown>;\r\n\r\n constructor(options: SummaryTransformationOptions = {}) {\r\n this.defaultPolicy = options.defaultPolicy ?? {};\r\n }\r\n\r\n async transform(input: TransformInput, ctx: TransformContext): Promise<SuccessorSeed> {\r\n const snapshot: AgentSessionSnapshot = input.sourceSnapshot;\r\n const policy = normalizeSummaryPolicy({ ...this.defaultPolicy, ...(input.policy ?? {}) });\r\n const prompt = buildSummaryPrompt({ additionalInstructions: policy.additionalInstructions });\r\n const summaryText = await generateSummaryText(ctx, snapshot, prompt);\r\n const scanned = scanFilesAndSkills(extractMessages(snapshot));\r\n\r\n return {\r\n schemaVersion: HANDOFF_SCHEMA_VERSION,\r\n seedMessages: [buildSummarySeedMessage(summaryText)],\r\n importantFiles: scanned.files,\r\n importantSkills: scanned.skills,\r\n fileRanges: scanned.fileRanges,\r\n meta: {\r\n compilerVersion: 'summarized-nine-section-v1',\r\n seedKind: 'summary-message',\r\n mode: policy.strategy,\r\n summaryShape: policy.summaryShape,\r\n policy,\r\n summaryText,\r\n summaryChars: summaryText.length,\r\n },\r\n };\r\n }\r\n}\r\n\r\nexport interface TrimTranscriptWithSummaryOptions {\r\n /** 注入自定 trim 初始策略(组合语义,硬编码追加摘要)。 */\r\n trimPolicy?: Record<string, unknown>;\r\n /** 摘要生成时的附加指令。 */\r\n additionalInstructions?: string;\r\n}\r\n\r\n/**\r\n * Trim-Transcript-with-Summary 官方单实现(ticket 006 收敛定案)。\r\n *\r\n * 组合语义 1:1 迁移自 Claw `trim-transcript-with-summary`:先对源会话做\r\n * trim 裁剪(默认策略),再用 `TransformContext.llm` 生成摘要,并把摘要\r\n * 种子消息追加到裁剪后的种子消息尾部。不做通用 compose 组合子机制。\r\n */\r\nexport class TrimTranscriptWithSummaryTransformation implements SessionTransformation {\r\n readonly id = 'agentdev.trim-transcript-with-summary';\r\n\r\n private readonly options: TrimTranscriptWithSummaryOptions;\r\n\r\n constructor(options: TrimTranscriptWithSummaryOptions = {}) {\r\n this.options = options;\r\n }\r\n\r\n async transform(input: TransformInput, ctx: TransformContext): Promise<SuccessorSeed> {\r\n const snapshot: AgentSessionSnapshot = input.sourceSnapshot;\r\n const rawMessages = extractMessages(snapshot);\r\n\r\n // 1) trim 裁剪\r\n const trimPolicy = normalizeExportPolicy({ ...DEFAULT_EXPORT_POLICY, ...(this.options.trimPolicy ?? {}), ...(input.policy ?? {}) });\r\n const { seedMessages, stats } = buildTrimmedSeedMessages(rawMessages, trimPolicy);\r\n\r\n // 2) 摘要生成(trimAppended 提示词)\r\n const prompt = buildSummaryPrompt({\r\n trimAppended: true,\r\n additionalInstructions: this.options.additionalInstructions,\r\n });\r\n const summaryText = await generateSummaryText(ctx, snapshot, prompt);\r\n const scanned = scanFilesAndSkills(rawMessages);\r\n\r\n // 3) 摘要种子消息追加到末尾\r\n const combinedSeedMessages = [\r\n ...seedMessages,\r\n buildSummarySeedMessage(summaryText),\r\n ];\r\n\r\n return {\r\n schemaVersion: HANDOFF_SCHEMA_VERSION,\r\n seedMessages: combinedSeedMessages,\r\n importantFiles: scanned.files,\r\n importantSkills: scanned.skills,\r\n fileRanges: scanned.fileRanges,\r\n meta: {\r\n compilerVersion: 'trim-transcript-v1',\r\n seedKind: 'message-replay',\r\n mode: 'trim-transcript-with-summary',\r\n trimPolicy,\r\n trimStats: stats,\r\n summaryText,\r\n summaryChars: summaryText.length,\r\n appendedSummary: {\r\n summaryText,\r\n importantFiles: scanned.files,\r\n importantSkills: scanned.skills,\r\n fileRanges: scanned.fileRanges,\r\n },\r\n },\r\n };\r\n }\r\n}\r\n","/**\r\n * Continuity Participant(中性化协议层,ticket 006 从 Claw 下沉)。\r\n *\r\n * 让一个 Feature 类获得 AgentDev continuity 协议的自声明能力。\r\n *\r\n * 设计理念:\r\n * - 框架自带的 Feature 不需要知道 continuity 的具体协议,本模块以「包装类继承\r\n * 原 feature」模式为它们附加协议字段,与「extends 原 feature 添加能力」是\r\n * 同一种模式。\r\n * - 包装类负责三件事:\r\n * 1. 提供 getContinuityDescriptor(),让 import 端可从 agent 实例查询声明\r\n * 2. override captureState(),把 descriptor 注入 snapshot(让无 agent 的\r\n * export 端也能读到)\r\n * 3. override restoreState(),把 descriptor 字段剥离后再交给原 feature 处理\r\n * - 第三方 feature 想参与 continuity 时,自己 declareContinuity 包装一下即可,\r\n * 无需回框架中心登记。\r\n */\r\n\r\nimport type { AgentFeature, FeatureStateSnapshot } from '../feature.js';\r\n\r\n/**\r\n * 快照中携带 continuity descriptor 的保留字段名。\r\n * 加 __ 前缀降低与业务字段碰撞的概率。\r\n *\r\n * (ticket 006 中性化:原 Claw 字段 `__claw_continuity__` → `__agentdev_continuity__`)\r\n */\r\nexport const CONTINUITY_FIELD_KEY = '__agentdev_continuity__';\r\n\r\n/**\r\n * 通用 continuity 协议:无 schema 适配,state 原样进出。\r\n *\r\n * 大多数 feature 用这个协议就够了——只要它的 captureState 返回值是\r\n * 可序列化的纯数据,无需特化清理。\r\n */\r\nexport const GENERIC_CONTINUITY_PROTOCOL = 'agentdev.feature-continuity.v1';\r\n\r\n/**\r\n * OpencodeBasic 的专用 continuity 协议。\r\n *\r\n * 接续时保留「先读后写」校验需要的 readFiles,\r\n * 但不继承依赖旧上下文内容的 readDedupState。\r\n */\r\nexport const OPENCODE_BASIC_CONTINUITY_PROTOCOL = 'agentdev.opencode-basic-continuity.v1';\r\n\r\n/**\r\n * AgentDev continuity descriptor:feature 自声明参与 continuity 的合约。\r\n *\r\n * protocol —— 协议标识符。协议层维护一张 protocol → adapter 的开放命名空间,\r\n * 未登记的 protocol 走透传(无 adapter)。只有需要特化清理\r\n * (如 schema 规范化)的协议才在协议层登记 adapter。\r\n * importMode —— 导入时的合并语义。当前仅 'replace'(直接覆盖 feature 内存状态)。\r\n */\r\nexport interface AgentdevContinuityDescriptor {\r\n protocol: string;\r\n importMode?: 'replace' | 'merge';\r\n}\r\n\r\n/** 从 snapshot 读取 continuity descriptor。无声明返回 null。 */\r\nexport function readContinuityDescriptor(snapshot: unknown): AgentdevContinuityDescriptor | null {\r\n if (!snapshot || typeof snapshot !== 'object') return null;\r\n const descriptor = (snapshot as Record<string, unknown>)[CONTINUITY_FIELD_KEY];\r\n if (!descriptor || typeof descriptor !== 'object') return null;\r\n const protocol = (descriptor as { protocol?: unknown }).protocol;\r\n if (typeof protocol !== 'string' || !protocol.trim()) return null;\r\n return descriptor as AgentdevContinuityDescriptor;\r\n}\r\n\r\n/** 从 snapshot 剥离 continuity 字段,返回纯 state。 */\r\nexport function stripContinuityField(snapshot: unknown): unknown {\r\n if (!snapshot || typeof snapshot !== 'object') return snapshot;\r\n const record = snapshot as Record<string, unknown>;\r\n if (!(CONTINUITY_FIELD_KEY in record)) return snapshot;\r\n const rest: Record<string, unknown> = {};\r\n for (const key of Object.keys(record)) {\r\n if (key !== CONTINUITY_FIELD_KEY) {\r\n rest[key] = record[key];\r\n }\r\n }\r\n return rest;\r\n}\r\n\r\ntype AnyFeatureConstructor = new (...args: any[]) => AgentFeature;\r\n\r\n/**\r\n * 高阶函数:让一个 Feature 类获得 continuity 自声明能力。\r\n *\r\n * @example\r\n * ```ts\r\n * import { OpencodeBasicFeature } from '@agentdevjs/core';\r\n * import { declareContinuity, GENERIC_CONTINUITY_PROTOCOL } from '@agentdevjs/core';\r\n *\r\n * export const ContinuityAwareOpencodeBasic = declareContinuity(OpencodeBasicFeature, {\r\n * protocol: GENERIC_CONTINUITY_PROTOCOL,\r\n * importMode: 'replace',\r\n * });\r\n * ```\r\n *\r\n * 包装后的类:\r\n * - 继承原 feature 的所有行为(工具、hooks、原 captureState/restoreState 语义)\r\n * - 多出 getContinuityDescriptor() 方法\r\n * - captureState 在原返回值上叠加 [CONTINUITY_FIELD_KEY] 字段\r\n * - restoreState 先剥离该字段再调用原 restoreState\r\n */\r\nexport function declareContinuity<T extends AnyFeatureConstructor>(\r\n Base: T,\r\n descriptor: AgentdevContinuityDescriptor,\r\n): T {\r\n const normalizedDescriptor: AgentdevContinuityDescriptor = {\r\n protocol: descriptor.protocol,\r\n importMode: descriptor.importMode === 'merge' ? 'merge' : 'replace',\r\n };\r\n\r\n return class ContinuityAware extends Base {\r\n /**\r\n * 标志位:restoreState 是否被调用过。\r\n * - restored resume / session load 场景:restoreState 被调用 → true\r\n * - 全新 session 首次启动:restoreState 未被调用 → false\r\n * onInitiate 根据此标志决定是否保护已恢复的状态。\r\n */\r\n private _continuityStateRestored = false;\r\n\r\n getContinuityDescriptor(): AgentdevContinuityDescriptor {\r\n return { ...normalizedDescriptor };\r\n }\r\n\r\n /**\r\n * Override onInitiate:防止基类的初始化逻辑清空 continuity/session 已恢复的状态。\r\n *\r\n * 策略:仅当 restoreState 被调用过(_continuityStateRestored=true)时,才在基类\r\n * onInitiate 执行后用 buffer 恢复状态。全新 session 首次启动时不干预,保留基类\r\n * onInitiate 的默认初始化行为。\r\n */\r\n async onInitiate(ctx: any): Promise<void> {\r\n const wasRestored = this._continuityStateRestored;\r\n const beforeBuffer = wasRestored ? stripContinuityField(super.captureState!()) : null;\r\n\r\n if (typeof super.onInitiate === 'function') {\r\n await super.onInitiate(ctx);\r\n }\r\n\r\n if (wasRestored && beforeBuffer && typeof beforeBuffer === 'object') {\r\n await super.restoreState!(beforeBuffer as FeatureStateSnapshot);\r\n }\r\n }\r\n\r\n captureState(): FeatureStateSnapshot {\r\n const base = super.captureState!();\r\n if (base && typeof base === 'object') {\r\n return { ...(base as Record<string, unknown>), [CONTINUITY_FIELD_KEY]: normalizedDescriptor };\r\n }\r\n return { [CONTINUITY_FIELD_KEY]: normalizedDescriptor } as FeatureStateSnapshot;\r\n }\r\n\r\n async restoreState(snapshot: FeatureStateSnapshot): Promise<void> {\r\n this._continuityStateRestored = true;\r\n if (snapshot && typeof snapshot === 'object' && CONTINUITY_FIELD_KEY in (snapshot as Record<string, unknown>)) {\r\n const stripped = stripContinuityField(snapshot);\r\n await super.restoreState!(stripped as FeatureStateSnapshot);\r\n return;\r\n }\r\n await super.restoreState!(snapshot);\r\n }\r\n };\r\n}\r\n","/**\r\n * WorkThreadStore — WorkThread 锚点层持久化存储\r\n *\r\n * 移植自 Claw `server/thread-control/thread-store.js`(原子写 / per-thread 串行锁 /\r\n * revision 乐观并发),只保留锚点层字段——sessionChain / head / pendingSuccession /\r\n * commands / hold / 接续编排状态(open / rotating / rotation_failed / closed)。\r\n *\r\n * 执行调度看板字段(executionEvents / mode / idle–failed 状态)不在此文件;\r\n * 那是可选 WorkThreadBoard 的持久化域,见 board.ts。本模块 import 面不含看板状态值。\r\n *\r\n * 设计要点:\r\n * - 每个 WorkThread 一个 JSON 文件(thread 记录 + inbox commands + hold),\r\n * 保证「head 推进 + 指令状态变更 + 挡板清除」可以在同一次原子写内完成。\r\n * - index.json 仅保存列表摘要,供轻量列举。\r\n * - 所有写操作走 per-thread 串行锁 + revision 自增 + tmp/rename 原子写。\r\n * - 支持 expectedRevision 乐观并发控制(head 推进等关键事务使用)。\r\n *\r\n * 数据目录由构造时必传 rootDir(框架不定义默认根,宿主决定归属规模)。\r\n * 并发模型:per-thread 串行锁只在单宿主进程内成立;多宿主进程共用同一数据\r\n * 目录时未定义,当前单宿主前提下接受(ADR-0002 后果项)。\r\n */\r\n\r\nimport { copyFile, mkdir, readFile, rename, unlink, writeFile } from 'fs/promises';\r\nimport { join } from 'path';\r\nimport { randomUUID } from 'crypto';\r\nimport type { WorkThreadCommand } from './inbox.js';\r\n\r\nexport interface WorkThreadChainEntry {\r\n sessionId: string;\r\n role: 'head' | 'predecessor';\r\n startedAt: number;\r\n endedAt: number | null;\r\n endKind: string | null;\r\n successorSessionId: string | null;\r\n}\r\n\r\n/** 交接意图(pendingSuccession)单一真相、落盘。 */\r\nexport interface WorkThreadPendingSuccession {\r\n fromSessionId: string;\r\n reason: string;\r\n stage: string;\r\n startedAt: number;\r\n}\r\n\r\n/** 锚点层接续编排状态。执行调度状态机(看板执行态)归看板层。 */\r\nexport type WorkThreadStatus = 'open' | 'rotating' | 'rotation_failed' | 'closed';\r\n\r\nexport interface WorkThreadLifecycleEvent {\r\n type: string;\r\n status: string;\r\n at: number;\r\n [key: string]: unknown;\r\n}\r\n\r\nexport interface WorkThreadRecord {\r\n threadId: string;\r\n agentId: string;\r\n workspaceId?: string;\r\n title?: string;\r\n status: WorkThreadStatus;\r\n /**\r\n * 线程的产品身份归属(T001:身份连续性不变量的事实来源)。\r\n * 新建线程时从 root Session 解析确定;`null` = 身份未知(历史数据缺少\r\n * 该字段时的读时归一值——明确「未知」,绝不静默回填为任何具体身份)。\r\n */\r\n identity?: string | null;\r\n rootSessionId: string;\r\n headSessionId: string;\r\n sessionChain: WorkThreadChainEntry[];\r\n commands: WorkThreadCommand[];\r\n pendingSuccession: WorkThreadPendingSuccession | null;\r\n /** 宿主级「暂停投递」落盘第一等布尔开关(重启不丢)。 */\r\n hold: boolean;\r\n closedAt?: number;\r\n closeReason?: string;\r\n lifecycleEvents: WorkThreadLifecycleEvent[];\r\n lastLifecycleEvent: WorkThreadLifecycleEvent | null;\r\n revision: number;\r\n createdAt: number;\r\n updatedAt: number;\r\n}\r\n\r\nexport class WorkThreadNotFoundError extends Error {\r\n readonly code = 'workthread_not_found';\r\n constructor(threadId: string) {\r\n super(`WorkThread \"${threadId}\" not found`);\r\n this.name = 'WorkThreadNotFoundError';\r\n }\r\n}\r\n\r\nexport class WorkThreadRevisionConflictError extends Error {\r\n readonly code = 'revision_conflict';\r\n readonly expected: number;\r\n readonly actual: number;\r\n constructor(threadId: string, expected: number, actual: number) {\r\n super(`Revision conflict on workthread \"${threadId}\": expected ${expected}, current ${actual}`);\r\n this.name = 'WorkThreadRevisionConflictError';\r\n this.expected = expected;\r\n this.actual = actual;\r\n }\r\n}\r\n\r\nexport function generateWorkThreadId(): string {\r\n return `wt-${randomUUID()}`;\r\n}\r\n\r\n/**\r\n * 线程 id 用于文件名:清除非法字符,防止路径穿越。\r\n * 与 Claw shared/string-helpers.sanitizeSessionFragment 逐字节一致。\r\n */\r\nexport function sanitizeWorkThreadFragment(value: unknown): string {\r\n return String(value || '')\r\n .trim()\r\n .replace(/[^a-zA-Z0-9_-]+/g, '-')\r\n .replace(/-+/g, '-')\r\n .replace(/^-|-$/g, '') || 'default';\r\n}\r\n\r\nfunction threadContentSignature(record: WorkThreadRecord): string {\r\n const { revision: _revision, updatedAt: _updatedAt, ...rest } = record;\r\n return JSON.stringify(rest);\r\n}\r\n\r\n// 旧状态空间(active/completed/cancelled/blocked)的读时归一,映射到新锚点域。\r\n// 盘上旧值不允许流入控制器,下次写盘会自动落成新值。\r\nconst LEGACY_STATUS_MAP: Record<string, WorkThreadStatus> = {\r\n active: 'open',\r\n completed: 'closed',\r\n cancelled: 'closed',\r\n blocked: 'open',\r\n};\r\n\r\nfunction normalizeThreadRecord(record: WorkThreadRecord): WorkThreadRecord {\r\n if (record && typeof record === 'object') {\r\n if (LEGACY_STATUS_MAP[record.status]) {\r\n record.status = LEGACY_STATUS_MAP[record.status];\r\n }\r\n // T001 身份归属读时归一:缺失 / 空串统一为 null(身份未知)。\r\n // 不可静默把历史线程成员当成 main——未知是明确的机器可判定状态。\r\n record.identity =\r\n typeof record.identity === 'string' && record.identity.trim()\r\n ? record.identity.trim()\r\n : null;\r\n }\r\n return record;\r\n}\r\n\r\nexport interface WorkThreadStoreOptions {\r\n rootDir: string;\r\n}\r\n\r\nexport class WorkThreadStore {\r\n readonly rootDir: string;\r\n readonly threadsDir: string;\r\n readonly indexPath: string;\r\n private _threadLocks = new Map<string, Promise<void>>();\r\n private _indexLock: Promise<void> = Promise.resolve();\r\n\r\n constructor({ rootDir }: WorkThreadStoreOptions) {\r\n if (!rootDir || typeof rootDir !== 'string') {\r\n throw new Error('WorkThreadStore requires a rootDir');\r\n }\r\n this.rootDir = rootDir;\r\n this.threadsDir = join(rootDir, 'threads');\r\n this.indexPath = join(rootDir, 'index.json');\r\n }\r\n\r\n // ── 路径 ──────────────────────────────────────────────────────────\r\n\r\n private threadFilePath(threadId: string): string {\r\n return join(this.threadsDir, `${sanitizeWorkThreadFragment(threadId)}.json`);\r\n }\r\n\r\n // ── 原子写(对齐 FileSessionStore 模式,兼容 Windows EPERM/EXDEV)─\r\n\r\n private async atomicWriteJson(filePath: string, data: unknown): Promise<void> {\r\n const tmpPath = `${filePath}.tmp`;\r\n await writeFile(tmpPath, JSON.stringify(data, null, 2), 'utf8');\r\n try {\r\n await rename(tmpPath, filePath);\r\n } catch (err) {\r\n const code = (err as NodeJS.ErrnoException).code;\r\n if (code === 'EPERM' || code === 'EACCES') {\r\n await unlink(filePath).catch(() => {});\r\n await rename(tmpPath, filePath);\r\n } else if (code === 'EXDEV') {\r\n await copyFile(tmpPath, filePath);\r\n await unlink(tmpPath).catch(() => {});\r\n } else {\r\n throw err;\r\n }\r\n }\r\n }\r\n\r\n // ── index(列表摘要)─────────────────────────────────────────────\r\n\r\n private async readIndex(): Promise<{ revision: number; threads: unknown[] }> {\r\n try {\r\n const raw = JSON.parse(await readFile(this.indexPath, 'utf8')) as {\r\n revision?: number;\r\n threads?: unknown[];\r\n };\r\n const threads = Array.isArray(raw.threads) ? raw.threads : [];\r\n return {\r\n revision:\r\n Number.isSafeInteger(Number(raw.revision)) && Number(raw.revision) >= 0\r\n ? Number(raw.revision)\r\n : 0,\r\n threads,\r\n };\r\n } catch {\r\n return { revision: 0, threads: [] };\r\n }\r\n }\r\n\r\n private async writeIndex(index: unknown): Promise<void> {\r\n await mkdir(this.rootDir, { recursive: true });\r\n await this.atomicWriteJson(this.indexPath, index);\r\n }\r\n\r\n private async updateIndexEntry(record: WorkThreadRecord): Promise<void> {\r\n const prev = this._indexLock;\r\n let release!: () => void;\r\n const next = new Promise<void>((r) => (release = r));\r\n this._indexLock = next;\r\n await prev.catch(() => {});\r\n try {\r\n const index = await this.readIndex();\r\n const entry = {\r\n threadId: record.threadId,\r\n agentId: record.agentId,\r\n workspaceId: record.workspaceId || '',\r\n title: record.title || '',\r\n status: LEGACY_STATUS_MAP[record.status] || record.status || 'open',\r\n rootSessionId: record.rootSessionId || '',\r\n headSessionId: record.headSessionId || '',\r\n // T001:线程身份归属(轻量事实,供成员/head 查询统一取用);\r\n // 旧记录缺字段时为 null(身份未知,前端不得据此默认渲染)。\r\n identity: typeof record.identity === 'string' && record.identity.trim()\r\n ? record.identity.trim()\r\n : null,\r\n // 链成员 id 列表(轻量,供前端徽标判定「会话是否属于线程」)\r\n sessionIds: (Array.isArray(record.sessionChain) ? record.sessionChain : []).map(\r\n (entry) => entry?.sessionId || '',\r\n ).filter(Boolean),\r\n // 每棒接力边(轻量,供前端接力分隔条渲染):非 root 会话的来源与方式\r\n chainEdges: buildChainEdges(record),\r\n // 交接意图原始时间戳(0 = 无);fresh 与否由读取方按统一规则派生\r\n handoffStartedAt: Number(record.pendingSuccession?.startedAt) || 0,\r\n handoffStage: record.pendingSuccession?.stage || null,\r\n hold: record.hold === true,\r\n lastLifecycleEvent: record.lastLifecycleEvent || null,\r\n // pending 指令文本预览(轻量,上限 5 条)\r\n pendingTexts: (Array.isArray(record.commands) ? record.commands : [])\r\n .filter((c) => c?.status === 'pending')\r\n .slice(0, 5)\r\n .map((c) => String(c?.text || '').slice(0, 120)),\r\n revision: record.revision,\r\n createdAt: record.createdAt,\r\n updatedAt: record.updatedAt,\r\n };\r\n const existingIdx = (index.threads as Array<{ threadId?: string }>).findIndex(\r\n (t) => t?.threadId === record.threadId,\r\n );\r\n if (existingIdx >= 0) {\r\n (index.threads as unknown[])[existingIdx] = entry;\r\n } else {\r\n index.threads.push(entry as unknown);\r\n }\r\n index.revision = (Number(index.revision) || 0) + 1;\r\n await this.writeIndex(index);\r\n } finally {\r\n release();\r\n }\r\n }\r\n\r\n // ── 读 ───────────────────────────────────────────────────────────\r\n\r\n async list(): Promise<unknown[]> {\r\n const index = await this.readIndex();\r\n return index.threads;\r\n }\r\n\r\n async get(threadId: string): Promise<WorkThreadRecord | null> {\r\n if (!threadId || typeof threadId !== 'string') return null;\r\n try {\r\n const parsed = JSON.parse(\r\n await readFile(this.threadFilePath(threadId), 'utf8'),\r\n ) as WorkThreadRecord;\r\n return normalizeThreadRecord(parsed);\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n // ── 写 ───────────────────────────────────────────────────────────\r\n\r\n /** 创建线程记录。要求调用方已构建完整初始记录。 */\r\n async create(record: WorkThreadRecord): Promise<WorkThreadRecord> {\r\n const threadId = record?.threadId;\r\n if (!threadId) throw new Error('WorkThreadStore.create requires record.threadId');\r\n await mkdir(this.threadsDir, { recursive: true });\r\n const existing = await this.get(threadId);\r\n if (existing) {\r\n throw new Error(`WorkThread \"${threadId}\" already exists`);\r\n }\r\n const normalized = normalizeThreadRecord(record);\r\n await this.atomicWriteJson(this.threadFilePath(threadId), normalized);\r\n await this.updateIndexEntry(normalized);\r\n return normalized;\r\n }\r\n\r\n /**\r\n * 串行化更新单个线程记录。\r\n * @param expectedRevision 乐观并发检查\r\n * @returns {changed} 无内容变更(元数据更新)时 false,revision 不递增\r\n */\r\n async update(\r\n threadId: string,\r\n mutFn: (\r\n record: WorkThreadRecord,\r\n ) => WorkThreadRecord | null | undefined | Promise<WorkThreadRecord | null | undefined>,\r\n options: { expectedRevision?: number } = {},\r\n ): Promise<{ record: WorkThreadRecord; changed: boolean }> {\r\n const prev = this._threadLocks.get(threadId) || Promise.resolve();\r\n let release!: () => void;\r\n const next = new Promise<void>((r) => (release = r));\r\n this._threadLocks.set(threadId, next);\r\n await prev.catch(() => {});\r\n try {\r\n const record = await this.get(threadId);\r\n if (!record) {\r\n throw new WorkThreadNotFoundError(threadId);\r\n }\r\n if (Number.isInteger(options.expectedRevision) && record.revision !== options.expectedRevision) {\r\n throw new WorkThreadRevisionConflictError(\r\n threadId,\r\n options.expectedRevision as number,\r\n record.revision,\r\n );\r\n }\r\n\r\n const before = threadContentSignature(record);\r\n const proposed = await mutFn(record);\r\n if (!proposed || typeof proposed !== 'object') {\r\n throw new Error('WorkThreadStore.update mutFn must return the record');\r\n }\r\n const after = threadContentSignature(proposed);\r\n\r\n if (after === before) {\r\n return { record, changed: false };\r\n }\r\n\r\n const nextRecord: WorkThreadRecord = {\r\n ...proposed,\r\n revision: (Number(record.revision) || 0) + 1,\r\n updatedAt: Date.now(),\r\n };\r\n await this.atomicWriteJson(this.threadFilePath(threadId), nextRecord);\r\n await this.updateIndexEntry(nextRecord);\r\n return { record: nextRecord, changed: true };\r\n } finally {\r\n release();\r\n if (this._threadLocks.get(threadId) === next) this._threadLocks.delete(threadId);\r\n }\r\n }\r\n\r\n /**\r\n * 删除线程记录文件与 index 条目(破坏性生命周期操作的存储原语)。\r\n *\r\n * 幂等:记录不存在时返回 { removed: false, alreadyAbsent: true }——\r\n * 已删除对象视为删除成功,供宿主的级联删除重试收敛。\r\n * 走与 create / update 相同的 per-thread 串行锁;index 条目移除走\r\n * _indexLock 串行链(与 updateIndexEntry 同链,并发创建 / 更新其它\r\n * 线程时双方的 index 快照不会互相覆盖丢失对方的条目)。\r\n */\r\n async remove(threadId: string): Promise<{ removed: boolean; alreadyAbsent: boolean }> {\r\n if (!threadId || typeof threadId !== 'string') {\r\n throw new WorkThreadNotFoundError(String(threadId || ''));\r\n }\r\n const prev = this._threadLocks.get(threadId) || Promise.resolve();\r\n let release!: () => void;\r\n const next = new Promise<void>((r) => (release = r));\r\n this._threadLocks.set(threadId, next);\r\n await prev.catch(() => {});\r\n try {\r\n const record = await this.get(threadId);\r\n if (!record) return { removed: false, alreadyAbsent: true };\r\n\r\n await unlink(this.threadFilePath(threadId)).catch(() => {});\r\n\r\n const indexPrev = this._indexLock;\r\n let indexRelease!: () => void;\r\n const indexNext = new Promise<void>((r) => (indexRelease = r));\r\n this._indexLock = indexNext;\r\n try {\r\n await indexPrev.catch(() => {});\r\n const index = await this.readIndex();\r\n if (index.threads.some((t) => (t as { threadId?: string })?.threadId === threadId)) {\r\n index.threads = index.threads.filter(\r\n (t) => (t as { threadId?: string })?.threadId !== threadId,\r\n );\r\n index.revision = (Number(index.revision) || 0) + 1;\r\n await this.writeIndex(index);\r\n }\r\n } finally {\r\n indexRelease();\r\n }\r\n return { removed: true, alreadyAbsent: false };\r\n } finally {\r\n release();\r\n if (this._threadLocks.get(threadId) === next) this._threadLocks.delete(threadId);\r\n }\r\n }\r\n}\r\n\r\nfunction buildChainEdges(record: WorkThreadRecord): Array<{\r\n sessionId: string;\r\n fromSessionId: string;\r\n relayKind: string;\r\n}> {\r\n const chain = Array.isArray(record.sessionChain) ? record.sessionChain : [];\r\n const bySuccessor = new Map<string, WorkThreadChainEntry>();\r\n for (const entry of chain) {\r\n if (entry?.successorSessionId && entry?.sessionId) {\r\n bySuccessor.set(entry.successorSessionId, entry);\r\n }\r\n }\r\n return chain\r\n .filter((entry) => entry?.sessionId && entry.sessionId !== record.rootSessionId)\r\n .map((entry) => {\r\n const pred = bySuccessor.get(entry.sessionId);\r\n return {\r\n sessionId: entry.sessionId,\r\n fromSessionId: pred?.sessionId || '',\r\n relayKind: pred?.endKind || '',\r\n };\r\n });\r\n}\r\n","/**\r\n * WorkThread Inbox — WorkThread 级待投递指令(纯函数层)\r\n *\r\n * 移植自 Claw `server/thread-control/thread-inbox.js`(幂等入队 / 稳定排序 /\r\n * 终态裁剪)。语义定位:这条指令属于某项连续工作(WorkThread),而不属于某个\r\n * 可能被替换的 runtime。指令先持久化(pending),由 WorkThread 在当前承接会话\r\n * 可用时经 bridge 下沉为 runtime envelope(delivered)。\r\n *\r\n * 本模块不持有状态、不做 IO;所有操作作用于 thread record 的 `commands` 数组,\r\n * 由 WorkThreadStore 的原子写保证持久化。\r\n *\r\n * 不承诺 LLM 副作用 exactly-once:只承诺命令身份持久化 + 幂等入队 + 可追踪的\r\n * 投递状态。真实世界副作用由新会话核对现实状态后继续。\r\n */\r\n\r\nimport { randomUUID } from 'crypto';\r\n\r\nexport const WorkThreadCommandStatus = Object.freeze({\r\n PENDING: 'pending',\r\n DELIVERED: 'delivered',\r\n FAILED: 'failed',\r\n CANCELLED: 'cancelled',\r\n} as const);\r\n\r\nexport type WorkThreadCommandStatusValue = (typeof WorkThreadCommandStatus)[keyof typeof WorkThreadCommandStatus];\r\n\r\nexport type WorkThreadCommandStatusName = keyof typeof WorkThreadCommandStatus;\r\n\r\nconst TERMINAL_STATUSES = new Set<string>([\r\n WorkThreadCommandStatus.DELIVERED,\r\n WorkThreadCommandStatus.FAILED,\r\n WorkThreadCommandStatus.CANCELLED,\r\n]);\r\n\r\nexport const WorkThreadCommandKind = Object.freeze({\r\n USER_MESSAGE: 'user_message',\r\n SYSTEM_CONTINUATION: 'system_continuation',\r\n EXTERNAL: 'external',\r\n} as const);\r\n\r\nexport type WorkThreadCommandKindValue = (typeof WorkThreadCommandKind)[keyof typeof WorkThreadCommandKind];\r\n\r\n/** 终态指令保留上限(超出按时间裁剪,防止 commands 无限增长) */\r\nexport const MAX_RETAINED_TERMINAL_COMMANDS = 200;\r\n\r\nexport function generateCommandId(): string {\r\n return `cmd-${randomUUID()}`;\r\n}\r\n\r\nexport interface WorkThreadCommand {\r\n commandId: string;\r\n threadId: string;\r\n kind: string;\r\n text: string;\r\n source: string;\r\n idempotencyKey: string;\r\n status: WorkThreadCommandStatusValue;\r\n attempts: number;\r\n envelopeId: string | null;\r\n lastReason: string | null;\r\n createdAt: number;\r\n updatedAt: number;\r\n deliveredAt: number | null;\r\n deliveryRef?: string | null;\r\n /** 随指令流动的能力激活通知(capability refs),投递时随 user-turn 元数据转发 */\r\n capabilityActivations?: string[];\r\n /** 随指令流动的图片引用(附件名/路径/URL),投递时转发给 viewer user-turn */\r\n images?: string[];\r\n}\r\n\r\n/**\r\n * 构造新指令记录(不修改 thread record)。\r\n */\r\nexport function createCommandRecord(opts: {\r\n threadId: string;\r\n kind?: string;\r\n text?: string;\r\n source?: string;\r\n idempotencyKey?: string;\r\n capabilityActivations?: string[];\r\n images?: string[];\r\n}): WorkThreadCommand {\r\n const now = Date.now();\r\n return {\r\n commandId: generateCommandId(),\r\n threadId: opts.threadId || '',\r\n kind: opts.kind || WorkThreadCommandKind.USER_MESSAGE,\r\n text: typeof opts.text === 'string' ? opts.text : '',\r\n source: opts.source || 'ui',\r\n idempotencyKey: opts.idempotencyKey || '',\r\n status: WorkThreadCommandStatus.PENDING,\r\n attempts: 0,\r\n envelopeId: null,\r\n lastReason: null,\r\n createdAt: now,\r\n updatedAt: now,\r\n deliveredAt: null,\r\n ...(Array.isArray(opts.capabilityActivations) && opts.capabilityActivations.length > 0\r\n ? { capabilityActivations: opts.capabilityActivations.filter((a) => typeof a === 'string') }\r\n : {}),\r\n ...(Array.isArray(opts.images) && opts.images.filter((i) => typeof i === 'string' && i.length > 0).length > 0\r\n ? { images: opts.images.filter((i) => typeof i === 'string' && i.length > 0) }\r\n : {}),\r\n };\r\n}\r\n\r\n/**\r\n * 幂等追加指令。若 idempotencyKey 命中既有的 pending / delivered\r\n * 指令,直接返回既有指令(重复提交不产生副作用)。\r\n * @returns {{command: WorkThreadCommand, duplicate: boolean}}\r\n */\r\nexport function appendCommand(\r\n record: { commands?: WorkThreadCommand[] },\r\n command: WorkThreadCommand,\r\n): { command: WorkThreadCommand; duplicate: boolean } {\r\n const commands = Array.isArray(record.commands) ? record.commands : [];\r\n record.commands = commands;\r\n\r\n if (command.idempotencyKey) {\r\n const existing = commands.find(\r\n (c) =>\r\n c.idempotencyKey === command.idempotencyKey &&\r\n (c.status === WorkThreadCommandStatus.PENDING ||\r\n c.status === WorkThreadCommandStatus.DELIVERED),\r\n );\r\n if (existing) {\r\n return { command: existing, duplicate: true };\r\n }\r\n }\r\n\r\n commands.push(command);\r\n return { command, duplicate: false };\r\n}\r\n\r\n/** 按 createdAt + commandId 稳定排序的 pending 指令。 */\r\nexport function pendingCommands(record: { commands?: WorkThreadCommand[] }): WorkThreadCommand[] {\r\n const commands = Array.isArray(record?.commands) ? record.commands : [];\r\n return commands\r\n .filter((c) => c?.status === WorkThreadCommandStatus.PENDING)\r\n .sort((a, b) => a.createdAt - b.createdAt || (a.commandId < b.commandId ? -1 : 1));\r\n}\r\n\r\nexport function findCommand(\r\n record: { commands?: WorkThreadCommand[] },\r\n commandId: string,\r\n): WorkThreadCommand | null {\r\n const commands = Array.isArray(record?.commands) ? record.commands : [];\r\n return commands.find((c) => c?.commandId === commandId) || null;\r\n}\r\n\r\n/**\r\n * 裁剪终态指令,保留最近 maxRetained 条。pending 永不裁剪。\r\n * @returns 是否有被裁掉的(内容变更)\r\n */\r\nexport function pruneCommands(\r\n record: { commands?: WorkThreadCommand[] },\r\n maxRetained: number = MAX_RETAINED_TERMINAL_COMMANDS,\r\n): boolean {\r\n const commands = Array.isArray(record?.commands) ? record.commands : [];\r\n const terminal = commands.filter((c) => TERMINAL_STATUSES.has(c?.status));\r\n if (terminal.length <= maxRetained) return false;\r\n\r\n const dropSet = new Set(\r\n terminal\r\n .sort((a, b) => (b.updatedAt || b.createdAt || 0) - (a.updatedAt || a.createdAt || 0))\r\n .slice(maxRetained)\r\n .map((c) => c.commandId),\r\n );\r\n record.commands = commands.filter((c) => !dropSet.has(c.commandId));\r\n return true;\r\n}\r\n","/**\r\n * WorkThreadRuntimeBridge — WorkThread Inbox → head runtime 的最后一跳\r\n *\r\n * 移植自 Claw `server/thread-control/thread-runtime-bridge.js`。职责:把一条\r\n * pending 的 WorkThread 指令下沉到当前承接会话(head session)对应的 runtime。\r\n * 仅此而已——不运行 Agent、不判断任务完成、不理解执行调度。\r\n *\r\n * 注入契约(宿主可 stub,现有测试注入模式不破坏):\r\n * - `enabled`:桥是否启用(休眠默认 false)。\r\n * - `resolveRuntimeViewerId(agentId, sessionId)`:runtime 存活且可接收时返回\r\n * viewerAgentId,否则 null(= runtime 未就绪,指令保持 pending 由调用方重试)。\r\n * - `submitTurn(params)`:真实投递函数,默认 submitUserTurn。\r\n */\r\n\r\nexport const WORKTHREAD_BRIDGE_DISABLED_REASON = 'bridge_disabled';\r\nexport const RUNTIME_NOT_ACCEPTING_REASON = 'runtime_not_accepting';\r\n\r\nexport interface WorkThreadBridgeSubmitTurnParams {\r\n agentId: string;\r\n text: string;\r\n source: string;\r\n sourceRef: string;\r\n capabilityActivations?: string[];\r\n images?: string[];\r\n}\r\n\r\nexport interface WorkThreadDeliveryOutcome {\r\n accepted: boolean;\r\n reason?: string;\r\n retryable?: boolean;\r\n deliveryRef?: string;\r\n}\r\n\r\n/** WorkThread 与 runtime 之间的投递契约(经 {thread, command} 定位目标)。 */\r\nexport interface WorkThreadBridge {\r\n isEnabled(): boolean;\r\n deliver(params: {\r\n thread: { agentId?: string; headSessionId?: string; threadId?: string };\r\n command: { commandId?: string; text?: string };\r\n }): Promise<WorkThreadDeliveryOutcome>;\r\n}\r\n\r\nexport function buildRuntimeKey(agentId: string, sessionId: string): string {\r\n return `${agentId}::${sessionId}`;\r\n}\r\n\r\nexport interface WorkThreadRuntimeBridgeOptions {\r\n enabled?: boolean;\r\n resolveRuntimeViewerId?: ((agentId: string, sessionId: string) => string | null) | null;\r\n submitTurn?: ((params: WorkThreadBridgeSubmitTurnParams) => Promise<unknown>) | null;\r\n}\r\n\r\nexport class WorkThreadRuntimeBridge implements WorkThreadBridge {\r\n private readonly _enabled: boolean;\r\n private readonly _resolveRuntimeViewerId: ((agentId: string, sessionId: string) => string | null) | null;\r\n private readonly _submitTurn: (params: WorkThreadBridgeSubmitTurnParams) => Promise<unknown>;\r\n\r\n constructor({\r\n enabled = false,\r\n resolveRuntimeViewerId = null,\r\n submitTurn = null,\r\n }: WorkThreadRuntimeBridgeOptions = {}) {\r\n this._enabled = enabled === true;\r\n this._resolveRuntimeViewerId =\r\n typeof resolveRuntimeViewerId === 'function' ? resolveRuntimeViewerId : null;\r\n this._submitTurn = typeof submitTurn === 'function' ? submitTurn : defaultSubmitTurn;\r\n }\r\n\r\n isEnabled(): boolean {\r\n return this._enabled === true;\r\n }\r\n\r\n async deliver(params: {\r\n thread: { agentId?: string; headSessionId?: string; threadId?: string };\r\n command: { commandId?: string; text?: string; capabilityActivations?: string[]; images?: string[] };\r\n }): Promise<WorkThreadDeliveryOutcome> {\r\n const { thread, command } = params;\r\n if (!this.isEnabled()) {\r\n return { accepted: false, reason: WORKTHREAD_BRIDGE_DISABLED_REASON, retryable: true };\r\n }\r\n if (!thread?.agentId || !thread?.headSessionId) {\r\n return { accepted: false, reason: 'invalid_thread_target', retryable: false };\r\n }\r\n\r\n const viewerAgentId = this._resolveRuntimeViewerId\r\n ? this._resolveRuntimeViewerId(thread.agentId, thread.headSessionId)\r\n : null;\r\n if (!viewerAgentId) {\r\n // runtime 未就绪(未启动 / 正在换代 / 已停止):指令保持 pending,\r\n // 由调用方在 head 推进或 runtime ready 后重试。\r\n return { accepted: false, reason: RUNTIME_NOT_ACCEPTING_REASON, retryable: true };\r\n }\r\n\r\n try {\r\n // 契约对齐:submitUserTurn 的参数名是 agentId。参数漂移会让客户端预校验\r\n // 抛 invalid_input(不可重试),指令被误判 failed——契约测试覆盖此点。\r\n await this._submitTurn({\r\n agentId: viewerAgentId,\r\n text: command.text || '',\r\n source: 'thread',\r\n sourceRef: command.commandId || '',\r\n ...(Array.isArray(command.capabilityActivations) && command.capabilityActivations.length > 0\r\n ? { capabilityActivations: command.capabilityActivations }\r\n : {}),\r\n ...(Array.isArray(command.images) && command.images.length > 0\r\n ? { images: command.images }\r\n : {}),\r\n });\r\n } catch (error) {\r\n if (isUserTurnDeliveryError(error)) {\r\n return {\r\n accepted: false,\r\n reason: error.code || 'delivery_failed',\r\n retryable: error.retryable !== false,\r\n };\r\n }\r\n return { accepted: false, reason: 'delivery_failed', retryable: true };\r\n }\r\n\r\n return { accepted: true, deliveryRef: viewerAgentId };\r\n }\r\n}\r\n\r\ninterface UserTurnDeliveryErrorLike {\r\n name: string;\r\n code?: string;\r\n retryable?: boolean;\r\n}\r\n\r\nfunction isUserTurnDeliveryError(error: unknown): error is UserTurnDeliveryErrorLike {\r\n return (\r\n typeof error === 'object' &&\r\n error !== null &&\r\n (error as UserTurnDeliveryErrorLike).name === 'UserTurnDeliveryError'\r\n );\r\n}\r\n\r\n/**\r\n * 默认 submitTurn。框架 core 域不背 HTTP 客户端依赖,真实投递由宿主经\r\n * `submitTurn` 注入;未注入时返回一个非重试失败,指令标记 failed。\r\n */\r\nasync function defaultSubmitTurn(_params: WorkThreadBridgeSubmitTurnParams): Promise<unknown> {\r\n const err = new Error('WorkThreadRuntimeBridge: no submitTurn provided (host must inject)');\r\n (err as Error & { name: string }).name = 'UserTurnDeliveryError';\r\n (err as Error & { code: string }).code = 'bridge_no_provider';\r\n (err as Error & { retryable: boolean }).retryable = false;\r\n throw err;\r\n}\r\n","/**\r\n * WorkThread — 框架层「Session + 接续变换」的连续性锚点(锚点层)\r\n *\r\n * 移植自 Claw `server/thread-control/thread-controller.js` 的锚点层成员,按\r\n * ADR-0002/Q4=C 拆分。WorkThread 只承载连续性锚点与接续编排状态:\r\n * - sessionChain / headSessionId(先后接力的 Session 认作同一项工作)\r\n * - 交接挡板 pendingSuccession(beginSessionHandoff / isHandoffActive /\r\n * advanceHead 换代+清挡板原子成对)\r\n * - 指令暂存 Inbox(appendCommand / deliverPendingCommands / cancelCommand)\r\n * - 接续编排状态(rotating / rotation_failed / failSessionHandoff(stage))\r\n * - 宿主级 hold 布尔开关(落盘第一等,重启不丢)\r\n * - closeThread 锚点收口(取消 pending 指令 + terminal 判定)\r\n *\r\n * 不承载执行调度看板(看板执行状态机 / executionEvents / resume / mode)——\r\n * 那是可选平行模块 WorkThreadBoard(board.ts),经 workThreadId 关联,永不反写\r\n * 锚点状态。本模块 import 面不含任何看板状态值。\r\n *\r\n * 投递门槛只保留客观事实:closed?交接窗口 fresh?hold?bridge enabled?\r\n * runtime 接收就绪(注入的 resolveRuntime)。失败 / 等待输入的暂停投递由宿主\r\n * 经 hold 开关表达,不在此层。\r\n */\r\n\r\nimport type { WorkThreadStore, WorkThreadRecord } from './store.js';\r\nimport {\r\n WorkThreadNotFoundError,\r\n} from './store.js';\r\nimport {\r\n createCommandRecord,\r\n appendCommand as appendCommandToRecord,\r\n pendingCommands,\r\n findCommand,\r\n pruneCommands,\r\n WorkThreadCommandStatus,\r\n WorkThreadCommandKind,\r\n type WorkThreadCommand,\r\n} from './inbox.js';\r\nimport { WorkThreadRuntimeBridge, WORKTHREAD_BRIDGE_DISABLED_REASON } from './bridge.js';\r\nimport type { WorkThreadBridge } from './bridge.js';\r\nimport { generateWorkThreadId } from './store.js';\r\n\r\nexport { WorkThreadNotFoundError };\r\n\r\nexport const WORKTHREAD_TERMINAL_STATUS = 'closed';\r\n\r\n/** 交接意图陈旧线:pendingSuccession 超过该时长视为已失效(compact 失败、进程\r\n * 崩溃等路径不会显式清除)。失效后投递自动恢复——此时 head 仍是权威值(旧会话),\r\n * 指令投向它即正确语义。 */\r\nexport const HANDOFF_STALE_MS = 5 * 60 * 1000;\r\n\r\nconst VALID_ID_RE = /^[\\w.-]{1,200}$/;\r\n\r\nfunction validateId(value: unknown, label: string): string {\r\n const id = String(value || '').trim();\r\n if (!VALID_ID_RE.test(id)) {\r\n throw Object.assign(new Error(`Invalid ${label}: ${JSON.stringify(String(value || ''))}`), {\r\n code: 'invalid_request',\r\n status: 400,\r\n });\r\n }\r\n return id;\r\n}\r\n\r\nfunction cleanText(value: unknown): string {\r\n return typeof value === 'string' ? value.trim() : '';\r\n}\r\n\r\nfunction pushLifecycleEvent(\r\n record: WorkThreadRecord,\r\n event: WorkThreadRecord['lifecycleEvents'][number],\r\n maxEvents = 200,\r\n): void {\r\n record.lifecycleEvents = Array.isArray(record.lifecycleEvents) ? record.lifecycleEvents : [];\r\n record.lifecycleEvents.push(event);\r\n if (record.lifecycleEvents.length > maxEvents) {\r\n record.lifecycleEvents.splice(0, record.lifecycleEvents.length - maxEvents);\r\n }\r\n record.lastLifecycleEvent = event;\r\n}\r\n\r\nexport interface WorkThreadStartOptions {\r\n sessionRef: { agentId: string; sessionId: string };\r\n title?: string;\r\n workspaceId?: string;\r\n /**\r\n * T001:显式指定线程身份归属。缺省时由 identitySource 从 root Session\r\n * 解析;解析不到(身份未知)时归属为 null,而不是默认成某个具体身份。\r\n */\r\n identity?: string | null;\r\n}\r\n\r\nexport interface WorkThreadOptions {\r\n store: WorkThreadStore;\r\n bridge?: WorkThreadBridge;\r\n /**\r\n * T001:线程身份解析器(宿主注入的会话身份真相源,如 Claw 的 session\r\n * index)。框架不内置产品身份词汇:返回值即线程归属;空值 = 身份未知。\r\n */\r\n identitySource?: (agentId: string, sessionId: string) => Promise<string | null> | string | null;\r\n /**\r\n * R3:接续恢复指令策略。官方默认为静态文案;宿主可注入替换。\r\n * 策略必须是纯同步文本生成——恢复路径禁止叠加 LLM 调用等易碎件。\r\n */\r\n continuationPolicy?: WorkThreadContinuationPolicy;\r\n}\r\n\r\n/** 交接移交易上下文(beginSessionHandoff 播种恢复指令时传入策略)。 */\r\nexport interface WorkThreadSuccessionContext {\r\n threadId: string;\r\n fromSessionId: string;\r\n reason: string;\r\n}\r\n\r\n/** R3:接续恢复指令策略接口。compose 必须同步、纯函数。 */\r\nexport interface WorkThreadContinuationPolicy {\r\n composeSuccessionInstruction(ctx: WorkThreadSuccessionContext): string;\r\n}\r\n\r\n/** R3 官方默认恢复指令(随挡板播种,睁眼第一句:先核对现实再继续)。 */\r\nexport const DEFAULT_SUCCESSION_INSTRUCTION = [\r\n '上下文已精简接力。先检查当前工作树、已有变更、测试结果和上一棒摘要,',\r\n '确认哪些步骤已经完成;不要重复可能已有副作用的操作,然后继续当前任务。',\r\n '需要人工决策或无法安全判断时,明确说明原因。',\r\n].join('');\r\n\r\nfunction threadIdentityError(message: string, code: string, status: number): Error {\r\n return Object.assign(new Error(message), { code, status });\r\n}\r\n\r\nexport class WorkThread {\r\n readonly store: WorkThreadStore;\r\n private readonly _bridge: WorkThreadBridge;\r\n private readonly _identitySource?: (agentId: string, sessionId: string) => Promise<string | null> | string | null;\r\n private readonly _continuationPolicy: WorkThreadContinuationPolicy;\r\n\r\n constructor({ store, bridge, identitySource, continuationPolicy }: WorkThreadOptions) {\r\n this.store = store;\r\n this._bridge = bridge || new WorkThreadRuntimeBridge();\r\n this._identitySource =\r\n identitySource && typeof identitySource === 'function' ? identitySource : undefined;\r\n this._continuationPolicy =\r\n continuationPolicy && typeof continuationPolicy.composeSuccessionInstruction === 'function'\r\n ? continuationPolicy\r\n : { composeSuccessionInstruction: () => DEFAULT_SUCCESSION_INSTRUCTION };\r\n }\r\n\r\n // ── 查询 ─────────────────────────────────────────────────────────\r\n\r\n async listThreads(opts: { agentId?: string } = {}): Promise<unknown[]> {\r\n const entries = await this.store.list();\r\n const normalized = cleanText(opts.agentId || '');\r\n return normalized ? entries.filter((t) => (t as { agentId?: string }).agentId === normalized) : entries;\r\n }\r\n\r\n async getThread(threadId: string): Promise<WorkThreadRecord | null> {\r\n return this.store.get(threadId);\r\n }\r\n\r\n isTerminal(record: WorkThreadRecord | null | undefined): boolean {\r\n return Boolean(record && record.status === WORKTHREAD_TERMINAL_STATUS);\r\n }\r\n\r\n /**\r\n * 按会话查线程:sessionId 是某线程的当前承接会话(head)时返回该线程。\r\n * 返回完整线程记录(权威真相,含 pendingSuccession / commands / hold)。\r\n */\r\n async findThreadByHeadSession(agentId: string, sessionId: string): Promise<WorkThreadRecord | null> {\r\n const normalizedAgentId = cleanText(agentId);\r\n const normalizedSessionId = cleanText(sessionId);\r\n if (!normalizedAgentId || !normalizedSessionId) return null;\r\n const threads = await this.listThreads({ agentId: normalizedAgentId });\r\n const matched = threads.find(\r\n (t) => (t as { headSessionId?: string }).headSessionId === normalizedSessionId,\r\n ) as { threadId?: string } | undefined;\r\n if (!matched?.threadId) return null;\r\n return this.store.get(matched.threadId);\r\n }\r\n\r\n /**\r\n * 按成员查线程(T001):sessionId 是该线程任一成员(root / predecessor /\r\n * head)时返回线程完整记录。成员事实唯一来自 sessionChain 链记录,\r\n * 不用 UI 投影或运行时扫描推导;记录上的 identity 即为该成员统一的\r\n * 身份归属事实(root / head / 历史成员同属一条记录,取值一致)。\r\n */\r\n async findThreadBySession(agentId: string, sessionId: string): Promise<WorkThreadRecord | null> {\r\n const normalizedAgentId = cleanText(agentId);\r\n const normalizedSessionId = cleanText(sessionId);\r\n if (!normalizedAgentId || !normalizedSessionId) return null;\r\n const threads = await this.listThreads({ agentId: normalizedAgentId });\r\n for (const summary of threads as Array<{ threadId?: string }>) {\r\n if (!summary?.threadId) continue;\r\n const record = await this.store.get(summary.threadId);\r\n if (Array.isArray(record?.sessionChain)\r\n && record.sessionChain.some((entry) => entry?.sessionId === normalizedSessionId)) {\r\n return record;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n // ── 创建(显式 opt-in,Q5=B)────────────────────────────────────\r\n\r\n /** 解析线程身份归属(T001):显式参数优先,否则经 identitySource 从 root\r\n * Session 解析;解析不到归一为 null(身份未知,绝不默认成具体身份)。 */\r\n private async resolveIdentity(\r\n explicit: string | null | undefined,\r\n agentId: string,\r\n sessionId: string,\r\n ): Promise<string | null> {\r\n const normalizedExplicit = cleanText(explicit);\r\n if (explicit === null) return null;\r\n if (normalizedExplicit) return normalizedExplicit;\r\n if (!this._identitySource) return null;\r\n const resolved = await this._identitySource(agentId, sessionId);\r\n return cleanText(resolved) || null;\r\n }\r\n\r\n /**\r\n * 唯一创建入口:把一个既有会话认作 root 并成为初始 head。\r\n * 不提供「session 创建即自动建线程」的框架语义——那是宿主策略(integration 层)。\r\n *\r\n * T001:创建时从 root Session 确定线程身份归属(record.identity)。\r\n */\r\n async start({ sessionRef, title = '', workspaceId = '', identity }: WorkThreadStartOptions): Promise<WorkThreadRecord> {\r\n if (!sessionRef || typeof sessionRef !== 'object') {\r\n throw Object.assign(new Error('start requires sessionRef'), { code: 'invalid_request', status: 400 });\r\n }\r\n const agentId = validateId(sessionRef.agentId, 'agentId');\r\n const sessionId = validateId(sessionRef.sessionId, 'sessionId');\r\n const threadIdentity = await this.resolveIdentity(identity, agentId, sessionId);\r\n\r\n const now = Date.now();\r\n const record: WorkThreadRecord = {\r\n threadId: generateWorkThreadId(),\r\n agentId,\r\n workspaceId: cleanText(workspaceId) || agentId,\r\n title: cleanText(title),\r\n status: 'open',\r\n identity: threadIdentity,\r\n rootSessionId: sessionId,\r\n headSessionId: sessionId,\r\n sessionChain: [\r\n {\r\n sessionId,\r\n role: 'head',\r\n startedAt: now,\r\n endedAt: null,\r\n endKind: null,\r\n successorSessionId: null,\r\n },\r\n ],\r\n commands: [],\r\n pendingSuccession: null,\r\n hold: false,\r\n lifecycleEvents: [],\r\n lastLifecycleEvent: null,\r\n revision: 1,\r\n createdAt: now,\r\n updatedAt: now,\r\n };\r\n\r\n return this.store.create(record);\r\n }\r\n\r\n // ── 交接意图(pendingSuccession)────────────────────────────────\r\n\r\n /**\r\n * 派生:交接意图是否仍然有效(fresh)。stale 视为无交接。\r\n */\r\n isHandoffActive(record: WorkThreadRecord): boolean {\r\n const pending = record?.pendingSuccession;\r\n if (!pending?.startedAt) return false;\r\n return Date.now() - pending.startedAt < HANDOFF_STALE_MS;\r\n }\r\n\r\n /**\r\n * 标记线程进入交接:原子写入 pendingSuccession + status=rotating,并在同\r\n * 一笔事务内播种接续恢复指令(R3:createdAt 与挡板同拍,早于一切交接期\r\n * 积压;幂等键绑移交易 (threadId, fromSessionId),失败恢复重走不会重复)。\r\n *\r\n * 门禁(按序):\r\n * - closed → thread_closed(硬终态)\r\n * - hold → thread_held(归档/行政冻结期不开新交接,K9)\r\n * - 已有 fresh 交接在办 → handoff_in_progress(并发竞争显式拒绝而非\r\n * 幂等刷新续命,R8 跨入口 single-flight 锚点;stale 残卷可覆写重开)\r\n * - fromSessionId ≠ 当前 head → head_mismatch\r\n */\r\n async beginSessionHandoff(opts: {\r\n threadId: string;\r\n fromSessionId: string;\r\n reason?: string;\r\n }): Promise<WorkThreadRecord> {\r\n const threadId = validateId(opts.threadId, 'threadId');\r\n const normalizedFrom = validateId(opts.fromSessionId, 'fromSessionId');\r\n const normalizedReason = cleanText(opts.reason) || 'manual';\r\n const { record } = await this.store.update(threadId, (draft) => {\r\n if (draft.status === WORKTHREAD_TERMINAL_STATUS) {\r\n throw Object.assign(new Error(`WorkThread \"${threadId}\" is closed`), {\r\n code: 'thread_closed',\r\n status: 409,\r\n });\r\n }\r\n if (draft.hold === true) {\r\n throw Object.assign(new Error(`WorkThread \"${threadId}\" is held (administrative freeze)`), {\r\n code: 'thread_held',\r\n status: 409,\r\n });\r\n }\r\n if (\r\n draft.status === 'rotating'\r\n && draft.pendingSuccession?.startedAt\r\n && Date.now() - draft.pendingSuccession.startedAt < HANDOFF_STALE_MS\r\n ) {\r\n throw Object.assign(\r\n new Error(`WorkThread \"${threadId}\" already has a handoff in progress; concurrent succession requests are rejected`),\r\n { code: 'handoff_in_progress', status: 409 },\r\n );\r\n }\r\n if (draft.headSessionId !== normalizedFrom) {\r\n throw Object.assign(\r\n new Error(`Handoff source is not the current head of workthread \"${threadId}\"`),\r\n { code: 'head_mismatch', status: 409 },\r\n );\r\n }\r\n const now = Date.now();\r\n draft.status = 'rotating';\r\n draft.pendingSuccession = {\r\n fromSessionId: normalizedFrom,\r\n reason: normalizedReason,\r\n stage: 'started',\r\n startedAt: now,\r\n };\r\n // R3:恢复指令随挡板同笔原子写入。策略抛错 = 整个 begin 失败,\r\n // 不留半套挡板(显式失败优于静默缺指令)。\r\n const instructionText = this._continuationPolicy.composeSuccessionInstruction({\r\n threadId,\r\n fromSessionId: normalizedFrom,\r\n reason: normalizedReason,\r\n });\r\n if (typeof instructionText === 'string' && instructionText.trim()) {\r\n const instruction = createCommandRecord({\r\n threadId,\r\n kind: WorkThreadCommandKind.SYSTEM_CONTINUATION,\r\n text: instructionText,\r\n source: 'thread-succession',\r\n idempotencyKey: `succession:${threadId}:${normalizedFrom}`,\r\n });\r\n instruction.createdAt = now;\r\n appendCommandToRecord(draft, instruction);\r\n pruneCommands(draft);\r\n }\r\n pushLifecycleEvent(draft, {\r\n type: 'handoff_started',\r\n status: 'rotating',\r\n at: now,\r\n fromSessionId: normalizedFrom,\r\n reason: normalizedReason,\r\n });\r\n return draft;\r\n });\r\n return record;\r\n }\r\n\r\n /**\r\n * 惰性清除陈旧的交接意图(投递路径发现 stale 时恢复常态)。\r\n */\r\n private async clearStaleHandoff(threadId: string): Promise<void> {\r\n await this.store.update(threadId, (draft) => {\r\n if (!draft.pendingSuccession) return draft;\r\n draft.pendingSuccession = null;\r\n if (draft.status === 'rotating') draft.status = 'open';\r\n pushLifecycleEvent(draft, { type: 'handoff_stale', status: draft.status, at: Date.now() });\r\n return draft;\r\n });\r\n }\r\n\r\n /**\r\n * 标记交接失败为接续编排状态 rotation_failed,不折叠成通用执行失败。\r\n * pendingSuccession 保留在盘上,供后续 resume 检查被打断的确切 stage。\r\n *\r\n * K3 守卫(事务内):失败记录的资格来自「在办移交」本身——\r\n * - closed 线程:硬终态,任何迟到失败不得覆写(返回原记录,零写入);\r\n * - 无 pendingSuccession(移交已成功推进 / 从未开始):迟到的失败者\r\n * 没有立卷资格,no-op 返回。这两条共同保证:只有「挡板仍在」的在办\r\n * 移交失败才会落 rotation_failed。\r\n */\r\n async failSessionHandoff(\r\n threadId: string,\r\n opts: { reason?: string; stage?: string; error?: unknown } = {},\r\n ): Promise<WorkThreadRecord> {\r\n const tid = validateId(threadId, 'threadId');\r\n const { record } = await this.store.update(tid, (draft) => {\r\n if (draft.status === WORKTHREAD_TERMINAL_STATUS || !draft.pendingSuccession) {\r\n return draft;\r\n }\r\n draft.status = 'rotation_failed';\r\n draft.pendingSuccession.stage = cleanText(opts.stage) || draft.pendingSuccession.stage || 'unknown';\r\n pushLifecycleEvent(draft, {\r\n type: 'handoff_failed',\r\n status: 'rotation_failed',\r\n at: Date.now(),\r\n reason: cleanText(opts.reason) || 'handoff_failed',\r\n stage: cleanText(opts.stage) || 'unknown',\r\n error: opts.error != null ? String(opts.error) : null,\r\n });\r\n return draft;\r\n });\r\n return record;\r\n }\r\n\r\n // ── 指令(WorkThread Inbox)────────────────────────────────────\r\n\r\n /**\r\n * 幂等追加一条线程指令。\r\n * @returns {{command, duplicate, threadRevision}}\r\n */\r\n async appendCommand(opts: {\r\n threadId: string;\r\n kind?: string;\r\n text: string;\r\n source?: string;\r\n idempotencyKey?: string;\r\n capabilityActivations?: string[];\r\n images?: string[];\r\n }): Promise<{ command: WorkThreadCommand; duplicate: boolean; threadRevision: number }> {\r\n const threadId = validateId(opts.threadId, 'threadId');\r\n // kind 为官方封闭词表:未传按 user_message;显式传入未知值直接拒绝——\r\n // 静默降级会让自定义词汇的调用方误以为意图已按原样入箱。\r\n const normalizedKind = opts.kind === undefined || opts.kind === ''\r\n ? WorkThreadCommandKind.USER_MESSAGE\r\n : opts.kind;\r\n if (!Object.values(WorkThreadCommandKind).includes(normalizedKind as never)) {\r\n throw Object.assign(\r\n new Error(\r\n `Unknown command kind \"${normalizedKind}\" (expected one of: ${Object.values(WorkThreadCommandKind).join(', ')})`,\r\n ),\r\n { code: 'invalid_request', status: 400 },\r\n );\r\n }\r\n const normalizedText = String(opts.text || '');\r\n const normalizedImages = Array.isArray(opts.images)\r\n ? opts.images.filter((entry) => typeof entry === 'string' && entry.trim())\r\n : [];\r\n // K8:images 与 text 至少其一非空——图片优先的输入不应被强制携带占位文本\r\n if (!normalizedText.trim() && normalizedImages.length === 0) {\r\n throw Object.assign(new Error('Command text must be non-empty'), {\r\n code: 'invalid_request',\r\n status: 400,\r\n });\r\n }\r\n if (normalizedText.length > 100_000) {\r\n throw Object.assign(new Error('Command text too large'), {\r\n code: 'invalid_request',\r\n status: 400,\r\n });\r\n }\r\n\r\n const command = createCommandRecord({\r\n threadId,\r\n kind: normalizedKind,\r\n text: normalizedText,\r\n source: cleanText(opts.source) || 'ui',\r\n idempotencyKey: cleanText(opts.idempotencyKey),\r\n ...(Array.isArray(opts.capabilityActivations) ? { capabilityActivations: opts.capabilityActivations } : {}),\r\n ...(normalizedImages.length > 0 ? { images: normalizedImages } : {}),\r\n });\r\n\r\n let appendOutcome = { command, duplicate: false };\r\n const { record } = await this.store.update(threadId, (draft) => {\r\n if (draft.status === WORKTHREAD_TERMINAL_STATUS) {\r\n throw Object.assign(new Error(`WorkThread \"${threadId}\" is closed; terminal threads hold no new commands`), {\r\n code: 'thread_closed',\r\n status: 409,\r\n });\r\n }\r\n appendOutcome = appendCommandToRecord(draft, command);\r\n pruneCommands(draft);\r\n return draft;\r\n });\r\n\r\n return {\r\n command: appendOutcome.command,\r\n duplicate: appendOutcome.duplicate,\r\n threadRevision: record.revision,\r\n };\r\n }\r\n\r\n /** 取消一条尚未投递的指令(pending → cancelled)。 */\r\n async cancelCommand(threadId: string, commandId: string): Promise<WorkThreadCommand | null> {\r\n const tid = validateId(threadId, 'threadId');\r\n const cid = validateId(commandId, 'commandId');\r\n const { record } = await this.store.update(tid, (draft) => {\r\n const command = findCommand(draft, cid);\r\n if (command && command.status === WorkThreadCommandStatus.PENDING) {\r\n command.status = WorkThreadCommandStatus.CANCELLED;\r\n command.updatedAt = Date.now();\r\n }\r\n return draft;\r\n });\r\n return findCommand(record, cid);\r\n }\r\n\r\n /**\r\n * 尝试把 pending 指令下沉到当前 head runtime。\r\n *\r\n * 投递判定(锚点层只保留客观事实):\r\n * - terminal(closed)→ thread_closed\r\n * - 交接窗口 fresh(pendingSuccession 未 stale)→ handoff_in_progress\r\n * - hold 开关置位 → thread_held(宿主级暂停投递)\r\n * - bridge disabled → bridge_disabled\r\n * - head runtime 未就绪(注入 resolveRuntime 返回 null)→ runtime_not_accepting\r\n *\r\n * @returns {{attempted, delivered, reason?, results}}\r\n */\r\n async deliverPendingCommands(threadId: string): Promise<{\r\n attempted: number;\r\n delivered: number;\r\n reason?: string;\r\n results: Array<{ commandId?: string; accepted?: boolean; reason?: string; retryable?: boolean; deliveryRef?: string }>;\r\n }> {\r\n const tid = validateId(threadId, 'threadId');\r\n\r\n const thread = await this.store.get(tid);\r\n if (!thread) throw new WorkThreadNotFoundError(tid);\r\n if (this.isTerminal(thread)) {\r\n return { attempted: 0, delivered: 0, reason: 'thread_closed', results: [] };\r\n }\r\n if (thread.hold === true) {\r\n return { attempted: 0, delivered: 0, reason: 'thread_held', results: [] };\r\n }\r\n\r\n // 交接进行中:指令保持 pending,等 advanceHead 后由宿主导流到新 head。\r\n // stale 的交接意图(失败路径残留)惰性清除后照常投递。\r\n if (thread.pendingSuccession) {\r\n if (this.isHandoffActive(thread)) {\r\n return { attempted: 0, delivered: 0, reason: 'handoff_in_progress', results: [] };\r\n }\r\n await this.clearStaleHandoff(tid);\r\n }\r\n\r\n const pending = pendingCommands(thread);\r\n if (pending.length === 0) {\r\n return { attempted: 0, delivered: 0, results: [] };\r\n }\r\n\r\n if (!this._bridge.isEnabled()) {\r\n return { attempted: 0, delivered: 0, reason: WORKTHREAD_BRIDGE_DISABLED_REASON, results: [] };\r\n }\r\n\r\n const results: Array<{\r\n commandId?: string;\r\n accepted?: boolean;\r\n reason?: string;\r\n retryable?: boolean;\r\n deliveryRef?: string;\r\n }> = [];\r\n let deliveredCount = 0;\r\n let stopReason: string | null = null;\r\n\r\n // K20:逐条投递前重读线程记录。HTTP 投递是慢操作,循环期间 head 可能\r\n // 换代、挡板可能竖起、指令可能被取消——按入口快照盲投会把指令送进已\r\n // 退役的会话(delivered 但结果留在旧棒)。每条指令以「当下事实」投递;\r\n // 客观门禁任一失守即停(剩余指令保持 pending,交给下一个触发点)。\r\n for (const command of pending) {\r\n const fresh = await this.store.get(tid);\r\n if (!fresh) throw new WorkThreadNotFoundError(tid);\r\n if (this.isTerminal(fresh)) {\r\n stopReason = 'thread_closed';\r\n break;\r\n }\r\n if (fresh.hold === true) {\r\n stopReason = 'thread_held';\r\n break;\r\n }\r\n if (fresh.pendingSuccession && this.isHandoffActive(fresh)) {\r\n stopReason = 'handoff_in_progress';\r\n break;\r\n }\r\n if (fresh.headSessionId !== thread.headSessionId) {\r\n stopReason = 'head_changed';\r\n break;\r\n }\r\n const freshCommand = (fresh.commands || []).find((c) => c?.commandId === command.commandId) || null;\r\n if (!freshCommand || freshCommand.status !== WorkThreadCommandStatus.PENDING) {\r\n // 循环期间被取消/已终态:跳过(不投递、不标记、不进结果集)\r\n continue;\r\n }\r\n\r\n const outcome = await this._bridge.deliver({ thread: fresh, command: freshCommand });\r\n results.push({ commandId: command.commandId, ...outcome });\r\n\r\n if (outcome.accepted) {\r\n deliveredCount += 1;\r\n } else if (outcome.retryable) {\r\n stopReason = outcome.reason || stopReason;\r\n break;\r\n }\r\n }\r\n\r\n const deliveredIds = new Set(\r\n results.filter((r) => r.accepted).map((r) => r.commandId as string),\r\n );\r\n const failedResults = new Map<string, string | undefined>(\r\n results\r\n .filter((r) => !r.accepted && r.retryable === false)\r\n .map((r) => [r.commandId as string, r.reason]),\r\n );\r\n\r\n if (deliveredIds.size > 0 || failedResults.size > 0) {\r\n const { record } = await this.store.update(tid, (draft) => {\r\n for (const c of draft.commands || []) {\r\n // 循环期间被并发 cancel 的指令不覆写终态:取消意图保留\r\n if (c.status !== WorkThreadCommandStatus.PENDING) continue;\r\n if (deliveredIds.has(c.commandId)) {\r\n c.status = WorkThreadCommandStatus.DELIVERED;\r\n c.deliveryRef = results.find((r) => r.commandId === c.commandId)?.deliveryRef || null;\r\n c.attempts = (Number(c.attempts) || 0) + 1;\r\n c.updatedAt = Date.now();\r\n c.deliveredAt = Date.now();\r\n c.lastReason = null;\r\n } else if (failedResults.has(c.commandId)) {\r\n c.status = WorkThreadCommandStatus.FAILED;\r\n c.lastReason = failedResults.get(c.commandId) || null;\r\n c.attempts = (Number(c.attempts) || 0) + 1;\r\n c.updatedAt = Date.now();\r\n }\r\n }\r\n return draft;\r\n });\r\n thread.revision = record.revision;\r\n }\r\n\r\n return {\r\n attempted: results.length,\r\n delivered: deliveredCount,\r\n reason: stopReason ?? undefined,\r\n results,\r\n };\r\n }\r\n\r\n /**\r\n * 宿主级「暂停投递」布尔开关(落盘第一等,重启不丢)。\r\n * @param held true 暂停投递(deliverPendingCommands 返回 thread_held)\r\n */\r\n async setHold(threadId: string, held: boolean): Promise<WorkThreadRecord> {\r\n const tid = validateId(threadId, 'threadId');\r\n const wantHold = held === true;\r\n const { record } = await this.store.update(tid, (draft) => {\r\n if (draft.hold === wantHold) return draft;\r\n draft.hold = wantHold;\r\n return draft;\r\n });\r\n return record;\r\n }\r\n\r\n // ── 会话接力(head 推进)────────────────────────────────────────\r\n\r\n /**\r\n * 推进线程 head:headSessionId: fromSessionId → toSessionId。\r\n *\r\n * fromSessionId 必填(K23):它是调用方声明的 CAS 期望值——不传即\r\n * 「接受任意当前 head」,幽灵任务防串台将被合法绕过。调用方若不知道\r\n * 当前 head,应先读线程再用读到的值调用(CLI 的自动填充即此语义)。\r\n *\r\n * 关键不变量(与 store 原子写共同保证):任一时刻线程要么明确指向旧 head,\r\n * 要么明确指向新 head;推进与指令状态 / 清挡板在同一次落盘中变更。\r\n *\r\n * 交接挡板(pendingSuccession)与 head 推进原子成对清除(换代 + 清挡板)。\r\n *\r\n * T001 身份连续性不变量:successor 加入前必须通过三道校验,任何一道失败\r\n * 都抛稳定错误且线程记录零变更(旧 head 保持有效):\r\n * - thread_identity_missing:线程身份归属未知(旧数据缺字段),拒绝静默\r\n * 放行;须宿主显式补全后重试;\r\n * - session_workspace_mismatch:successor 不属于线程同一工作空间宿主;\r\n * - thread_identity_mismatch:successor 身份与线程身份不一致;\r\n * - session_already_in_thread:successor 已是某条线程成员(本线程的重复\r\n * 成员由既有 duplicate_session 覆盖)。\r\n */\r\n async advanceHead(opts: {\r\n threadId: string;\r\n toSessionId: string;\r\n fromSessionId: string;\r\n expectedRevision?: number;\r\n endKind?: string;\r\n }): Promise<WorkThreadRecord> {\r\n const threadId = validateId(opts.threadId, 'threadId');\r\n const normalizedTo = validateId(opts.toSessionId, 'toSessionId');\r\n const normalizedFrom = validateId(opts.fromSessionId, 'fromSessionId');\r\n\r\n // T001 身份连续性不变量:successor 加入前的三道校验在下方 store 事务内\r\n // 执行(per-thread 串行锁保护,结构守卫在前);任一失败抛稳定错误且\r\n // 线程记录零变更(旧 head 保持有效):\r\n // - thread_held:行政冻结期(归档)head 不得推进——归档宣告终局后,\r\n // 在途接力的迟到推进同样被拒(与 begin 的 K9 门禁同源);\r\n // - session_workspace_mismatch:successor 不属于线程的工作空间宿主;\r\n // - thread_identity_mismatch:successor 身份与线程身份不一致;\r\n // - thread_identity_missing:线程身份未知且无法从 root Session 再推导\r\n // (旧数据缺字段的明确失败,绝不静默放行或默认成具体身份);\r\n // - session_already_in_thread:successor 已是其它线程的成员。\r\n // 未注入 identitySource 时(框架独立使用)保持既有行为:不校验身份。\r\n const { record } = await this.store.update(\r\n threadId,\r\n async (draft) => {\r\n if (draft.status === WORKTHREAD_TERMINAL_STATUS) {\r\n throw Object.assign(new Error(`WorkThread \"${threadId}\" is closed`), {\r\n code: 'thread_closed',\r\n status: 409,\r\n });\r\n }\r\n if (draft.hold === true) {\r\n throw Object.assign(\r\n new Error(`WorkThread \"${threadId}\" is held (administrative freeze); head cannot advance`),\r\n { code: 'thread_held', status: 409 },\r\n );\r\n }\r\n if (draft.headSessionId !== normalizedFrom) {\r\n throw Object.assign(\r\n new Error(\r\n `Head mismatch on workthread \"${threadId}\": expected ${normalizedFrom}, current ${draft.headSessionId}`,\r\n ),\r\n { code: 'head_mismatch', status: 409 },\r\n );\r\n }\r\n if (draft.headSessionId === normalizedTo) {\r\n throw Object.assign(\r\n new Error(`Session \"${normalizedTo}\" is already the head of workthread \"${threadId}\"`),\r\n { code: 'already_head', status: 409 },\r\n );\r\n }\r\n if ((draft.sessionChain || []).some((entry) => entry.sessionId === normalizedTo)) {\r\n throw Object.assign(\r\n new Error(`Session \"${normalizedTo}\" already appears in the chain of workthread \"${threadId}\"`),\r\n { code: 'duplicate_session', status: 409 },\r\n );\r\n }\r\n\r\n // T001 身份连续性不变量(事务内校验,结构守卫在前):\r\n // - session_workspace_mismatch:successor 不属于线程的工作空间宿主\r\n // (identitySource 以线程自身 agentId 定位不到该会话 = 非本宿主);\r\n // - thread_identity_missing:线程身份未知且无法从 root Session 再推导\r\n // (旧数据缺字段的明确失败,绝不静默放行或默认成具体身份);\r\n // - thread_identity_mismatch:successor 身份与线程身份不一致;\r\n // - session_already_in_thread:successor 已是其它线程的成员。\r\n if (this._identitySource) {\r\n const threadAgentId = cleanText(draft.agentId);\r\n const toIdentity = cleanText(await this._identitySource(threadAgentId, normalizedTo));\r\n if (!toIdentity) {\r\n throw threadIdentityError(\r\n `Session \"${normalizedTo}\" does not belong to workspace host \"${threadAgentId}\" of thread \"${threadId}\"`,\r\n 'session_workspace_mismatch',\r\n 409,\r\n );\r\n }\r\n // 线程身份归属:优先盘上事实;旧记录缺字段(null)时从 root Session\r\n // 的真实身份再推导并回填(事实推导,非默认值);仍不可得则明确失败。\r\n let effectiveThreadIdentity = draft.identity;\r\n if (!effectiveThreadIdentity) {\r\n effectiveThreadIdentity =\r\n cleanText(await this._identitySource(threadAgentId, draft.rootSessionId)) || null;\r\n if (!effectiveThreadIdentity) {\r\n throw threadIdentityError(\r\n `Thread \"${threadId}\" has no identity attribution and its root session identity is unknown; backfill the root identity before advancing the head`,\r\n 'thread_identity_missing',\r\n 409,\r\n );\r\n }\r\n // 回填与 head 推进同盘原子落盘(下方 draft.identity 赋值)。\r\n draft.identity = effectiveThreadIdentity;\r\n }\r\n if (toIdentity !== effectiveThreadIdentity) {\r\n throw threadIdentityError(\r\n `Session \"${normalizedTo}\" has identity \"${toIdentity}\" but thread \"${threadId}\" is bound to identity \"${effectiveThreadIdentity}\"`,\r\n 'thread_identity_mismatch',\r\n 409,\r\n );\r\n }\r\n // 成员独占:successor 不得已是其它线程的成员(本线程内的重复由\r\n // 上方 duplicate_session 覆盖)。\r\n const summaries = await this.store.list();\r\n for (const summary of summaries as Array<{ threadId?: string }>) {\r\n if (!summary?.threadId || summary.threadId === threadId) continue;\r\n const other = await this.store.get(summary.threadId);\r\n if (Array.isArray(other?.sessionChain)\r\n && other.sessionChain.some((entry) => entry?.sessionId === normalizedTo)) {\r\n throw threadIdentityError(\r\n `Session \"${normalizedTo}\" is already a member of thread \"${summary.threadId}\"`,\r\n 'session_already_in_thread',\r\n 409,\r\n );\r\n }\r\n }\r\n }\r\n\r\n const now = Date.now();\r\n const currentHead = (draft.sessionChain || []).find(\r\n (entry) => entry.sessionId === draft.headSessionId,\r\n );\r\n if (currentHead) {\r\n currentHead.role = 'predecessor';\r\n currentHead.endedAt = now;\r\n currentHead.endKind = cleanText(opts.endKind) || 'manual';\r\n currentHead.successorSessionId = normalizedTo;\r\n }\r\n draft.sessionChain = draft.sessionChain || [];\r\n draft.sessionChain.push({\r\n sessionId: normalizedTo,\r\n role: 'head',\r\n startedAt: now,\r\n endedAt: null,\r\n endKind: null,\r\n successorSessionId: null,\r\n });\r\n draft.headSessionId = normalizedTo;\r\n // 交接完成:同一次落盘内清除交接意图(与 head 推进原子成对)。\r\n draft.pendingSuccession = null;\r\n // 接续编排状态复位为 open(执行调度运行时状态归看板,不在此层驱动)。\r\n draft.status = 'open';\r\n pushLifecycleEvent(draft, {\r\n type: 'handoff_completed',\r\n status: 'open',\r\n at: now,\r\n fromSessionId: normalizedFrom,\r\n toSessionId: normalizedTo,\r\n reason: cleanText(opts.endKind) || 'manual',\r\n });\r\n return draft;\r\n },\r\n { expectedRevision: Number.isInteger(opts.expectedRevision) ? opts.expectedRevision : undefined },\r\n );\r\n\r\n return record;\r\n }\r\n\r\n // ── 状态迁移(锚点收口)────────────────────────────────────────\r\n\r\n /**\r\n * 关闭只表示锚点收口 + 执行载体终态(terminal 判定),不表示编排层任务完成。\r\n * pending 指令随关闭一并取消。\r\n */\r\n async closeThread(threadId: string, opts: { reason?: string } = {}): Promise<WorkThreadRecord> {\r\n const tid = validateId(threadId, 'threadId');\r\n const { record } = await this.store.update(tid, (draft) => {\r\n if (this.isTerminal(draft)) return draft;\r\n draft.status = WORKTHREAD_TERMINAL_STATUS;\r\n draft.closedAt = Date.now();\r\n draft.closeReason = cleanText(opts.reason) || 'closed';\r\n pushLifecycleEvent(draft, {\r\n type: 'closed',\r\n status: WORKTHREAD_TERMINAL_STATUS,\r\n at: draft.closedAt,\r\n reason: draft.closeReason,\r\n });\r\n const now = Date.now();\r\n for (const c of draft.commands || []) {\r\n if (c.status === WorkThreadCommandStatus.PENDING) {\r\n c.status = WorkThreadCommandStatus.CANCELLED;\r\n c.lastReason = 'thread_closed';\r\n c.updatedAt = now;\r\n }\r\n }\r\n return draft;\r\n });\r\n return record;\r\n }\r\n\r\n /** 桥注入面(供测试 stub 与宿主替换)。 */\r\n getBridge(): WorkThreadBridge {\r\n return this._bridge;\r\n }\r\n}\r\n","/**\r\n * WorkThreadBoard — WorkThread 的可选平行执行看板(看板层)\r\n *\r\n * 移植自 Claw `server/thread-control/thread-controller.js` 的执行调度部分,按\r\n * ADR-0002/Q4=C 拆分为独立平行模块,经 workThreadId 与锚点层关联,宿主选用。\r\n *\r\n * 承载:\r\n * - executionEvents 持久化(codex `turn.*` / `item.*` 事件审计)\r\n * - `recordRuntimeEvent`(codex turn 事件流 → 看板状态翻译)\r\n * - resume、mode\r\n * - idle / running / waiting_input / failed 执行状态机\r\n *\r\n * 纪律(写死在本模块头注释):**看板永不反写锚点状态。** 本模块只读锚点记录的\r\n * 定位信息(经 core.findThreadByHeadSession 取 workThreadId 与 closed 判定),\r\n * 只写自己独立的看板持久化域,绝不调用 core 的 advanceHead / beginSessionHandoff /\r\n * setHold / closeThread 等锚点写路径。\r\n *\r\n * closed 两处语义(核心 terminal 判定 + 看板终态):看板对 closed 线程拒绝\r\n * runtime 事件(thread_closed);宿主在锚点关闭时经 closeBoard 将看板置为终态。\r\n */\r\n\r\nimport { copyFile, mkdir, readFile, rename, unlink, writeFile } from 'fs/promises';\r\nimport { join } from 'path';\r\nimport type { WorkThread } from './core.js';\r\nimport { sanitizeWorkThreadFragment } from './store.js';\r\n\r\nexport type WorkThreadBoardStatus =\r\n | 'idle'\r\n | 'running'\r\n | 'waiting_input'\r\n | 'failed'\r\n | 'closed';\r\n\r\nexport type WorkThreadBoardMode = 'interactive' | 'autonomous';\r\n\r\nexport interface WorkThreadBoardExecutionEvent {\r\n eventId: string;\r\n receivedAt: number;\r\n sessionId: string;\r\n runtimeInstanceId: string | null;\r\n event: Record<string, unknown>;\r\n}\r\n\r\nexport interface WorkThreadBoardLifecycleEvent {\r\n type: string;\r\n status: string;\r\n at: number;\r\n [key: string]: unknown;\r\n}\r\n\r\nexport interface WorkThreadBoardState {\r\n workThreadId: string;\r\n mode: WorkThreadBoardMode;\r\n status: WorkThreadBoardStatus;\r\n executionEvents: WorkThreadBoardExecutionEvent[];\r\n /**\r\n * 已从 executionEvents 窗口裁掉的事件总数(ticket 017)。\r\n * 绝对游标 = executionEventBaseOffset + executionEvents.length,随状态落盘,\r\n * 保证进程重启后 cursor 不回退。旧状态文件缺省时按 0 读取。\r\n */\r\n executionEventBaseOffset: number;\r\n lifecycleEvents: WorkThreadBoardLifecycleEvent[];\r\n lastLifecycleEvent: WorkThreadBoardLifecycleEvent | null;\r\n revision: number;\r\n createdAt: number;\r\n updatedAt: number;\r\n}\r\n\r\nexport const WORKTHREAD_BOARD_STATUSES: ReadonlySet<WorkThreadBoardStatus> = new Set([\r\n 'idle',\r\n 'running',\r\n 'waiting_input',\r\n 'failed',\r\n 'closed',\r\n]);\r\n\r\nexport const WORKTHREAD_BOARD_OPEN_STATUSES: ReadonlySet<WorkThreadBoardStatus> = new Set([\r\n 'idle',\r\n 'running',\r\n 'waiting_input',\r\n 'failed',\r\n]);\r\n\r\n// 执行状态机转换矩阵(看板层契约)。closed 为终态。\r\n//\r\n// `waiting_input` 是宿主播种的预留状态,事件翻译(recordRuntimeEvent)永不产生它:\r\n// turn.started → running、turn.completed → idle、turn.failed → failed,\r\n// item.* / turn.cancelled 不做状态转换。宿主经 setStatus 显式置位(如前端等待\r\n// 人工输入);其出边(→ running / idle / failed / closed)保证播种后后续 runtime\r\n// 事件(含终态失败)仍能自洽收敛,不会卡死在预留态或丢失终态事件。\r\nconst BOARD_TRANSITIONS: Record<WorkThreadBoardStatus, ReadonlySet<WorkThreadBoardStatus>> = {\r\n idle: new Set(['running', 'waiting_input', 'failed', 'closed']),\r\n running: new Set(['idle', 'waiting_input', 'failed', 'closed']),\r\n waiting_input: new Set(['running', 'idle', 'failed', 'closed']),\r\n failed: new Set(['running', 'idle', 'closed']),\r\n closed: new Set(),\r\n};\r\n\r\nconst BOARD_STATUSES = new Set<string>([\r\n 'idle',\r\n 'running',\r\n 'waiting_input',\r\n 'failed',\r\n 'closed',\r\n]);\r\nconst BOARD_MODES = new Set<string>(['interactive', 'autonomous']);\r\n\r\nconst MAX_EXECUTION_EVENTS = 500;\r\nconst MAX_LIFECYCLE_EVENTS = 200;\r\n\r\nexport interface WorkThreadBoardOptions {\r\n core: WorkThread;\r\n rootDir: string;\r\n}\r\n\r\nexport class WorkThreadBoard {\r\n readonly core: WorkThread;\r\n readonly boardsDir: string;\r\n private _locks = new Map<string, Promise<void>>();\r\n\r\n constructor({ core, rootDir }: WorkThreadBoardOptions) {\r\n if (!rootDir || typeof rootDir !== 'string') {\r\n throw new Error('WorkThreadBoard requires a rootDir');\r\n }\r\n this.core = core;\r\n this.boardsDir = join(rootDir, 'boards');\r\n }\r\n\r\n // ── 内部持久化(独立看板域,与锚点 store 分离)──────────────\r\n\r\n private boardFilePath(workThreadId: string): string {\r\n return join(this.boardsDir, `${sanitizeWorkThreadFragment(workThreadId)}.board.json`);\r\n }\r\n\r\n async getBoardId(workThreadId: string): Promise<string> {\r\n return workThreadId;\r\n }\r\n\r\n async getState(workThreadId: string): Promise<WorkThreadBoardState | null> {\r\n try {\r\n return JSON.parse(\r\n await readFile(this.boardFilePath(workThreadId), 'utf8'),\r\n ) as WorkThreadBoardState;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n private async atomicWriteJson(filePath: string, data: unknown): Promise<void> {\r\n const tmpPath = `${filePath}.tmp`;\r\n await writeFile(tmpPath, JSON.stringify(data, null, 2), 'utf8');\r\n try {\r\n await rename(tmpPath, filePath);\r\n } catch (err) {\r\n const code = (err as NodeJS.ErrnoException).code;\r\n if (code === 'EPERM' || code === 'EACCES') {\r\n await unlink(filePath).catch(() => {});\r\n await rename(tmpPath, filePath);\r\n } else if (code === 'EXDEV') {\r\n await copyFile(tmpPath, filePath);\r\n await unlink(tmpPath).catch(() => {});\r\n } else {\r\n throw err;\r\n }\r\n }\r\n }\r\n\r\n private async ensureInit(workThreadId: string, mode: WorkThreadBoardMode): Promise<WorkThreadBoardState> {\r\n const existing = await this.getState(workThreadId);\r\n if (existing) return existing;\r\n await mkdir(this.boardsDir, { recursive: true });\r\n const now = Date.now();\r\n const initial: WorkThreadBoardState = {\r\n workThreadId,\r\n mode,\r\n status: 'idle',\r\n executionEvents: [],\r\n executionEventBaseOffset: 0,\r\n lifecycleEvents: [],\r\n lastLifecycleEvent: null,\r\n revision: 1,\r\n createdAt: now,\r\n updatedAt: now,\r\n };\r\n await this.atomicWriteJson(this.boardFilePath(workThreadId), initial);\r\n return initial;\r\n }\r\n\r\n private async mutate(\r\n workThreadId: string,\r\n mutFn: (state: WorkThreadBoardState) => WorkThreadBoardState,\r\n mode: WorkThreadBoardMode = 'interactive',\r\n ): Promise<{ state: WorkThreadBoardState; changed: boolean }> {\r\n const prev = this._locks.get(workThreadId) || Promise.resolve();\r\n let release!: () => void;\r\n const next = new Promise<void>((r) => (release = r));\r\n this._locks.set(workThreadId, next);\r\n await prev.catch(() => {});\r\n try {\r\n const state = (await this.getState(workThreadId)) || (await this.ensureInit(workThreadId, mode));\r\n const before = JSON.stringify(state);\r\n const proposed = mutFn(state);\r\n if (!proposed) return { state, changed: false };\r\n const after = JSON.stringify(proposed);\r\n if (after === before) {\r\n return { state, changed: false };\r\n }\r\n const nextState: WorkThreadBoardState = {\r\n ...proposed,\r\n revision: (Number(state.revision) || 0) + 1,\r\n updatedAt: Date.now(),\r\n };\r\n await this.atomicWriteJson(this.boardFilePath(workThreadId), nextState);\r\n return { state: nextState, changed: true };\r\n } finally {\r\n release();\r\n if (this._locks.get(workThreadId) === next) this._locks.delete(workThreadId);\r\n }\r\n }\r\n\r\n private pushLifecycle(state: WorkThreadBoardState, event: WorkThreadBoardLifecycleEvent): void {\r\n state.lifecycleEvents = Array.isArray(state.lifecycleEvents) ? state.lifecycleEvents : [];\r\n state.lifecycleEvents.push(event);\r\n if (state.lifecycleEvents.length > MAX_LIFECYCLE_EVENTS) {\r\n state.lifecycleEvents.splice(0, state.lifecycleEvents.length - MAX_LIFECYCLE_EVENTS);\r\n }\r\n state.lastLifecycleEvent = event;\r\n }\r\n\r\n private canTransition(from: WorkThreadBoardStatus, to: WorkThreadBoardStatus): boolean {\r\n return from === to || BOARD_TRANSITIONS[from]?.has(to) === true;\r\n }\r\n\r\n // ── 查询 ─────────────────────────────────────────────────────────\r\n\r\n /**\r\n * 读取看板 executionEvents,支持 cursor 切片。\r\n *\r\n * cursor 是绝对游标(baseOffset + 窗口长度,ticket 017):跨裁剪点单调递增,\r\n * 长期增量消费者(轮询 after=cursor)不丢事件。`after` 落后于窗口起点时\r\n * clamp 到窗口起点从头返回当前可用窗口——旧数据已裁掉不可恢复,但绝不以\r\n * 空数组静默丢读;消费者可用 eventId 去重。\r\n * @returns {{events, cursor}}\r\n */\r\n async getExecutionEvents(\r\n workThreadId: string,\r\n opts: { after?: number } = {},\r\n ): Promise<{ events: Record<string, unknown>[]; cursor: number }> {\r\n const state = await this.getState(workThreadId);\r\n if (!state) return { events: [], cursor: 0 };\r\n const events = Array.isArray(state.executionEvents) ? state.executionEvents : [];\r\n const baseOffset = Math.max(0, Number(state.executionEventBaseOffset) || 0);\r\n const after = Math.max(0, Number(opts.after) || 0);\r\n const from = after < baseOffset ? 0 : after - baseOffset;\r\n return {\r\n events: events.slice(from).map((entry) => entry.event),\r\n cursor: baseOffset + events.length,\r\n };\r\n }\r\n\r\n // ── 事件翻译(执行调度状态机)─────────────────────────────────\r\n\r\n /**\r\n * 把一个 codex (`turn.*` / `item.*`) 运行时事件应用到看板层。\r\n *\r\n * 通过 core.findThreadByHeadSession 定位 workThreadId(只读锚点定位),\r\n * 只在看板域写状态与 executionEvents;closed 线程拒绝迟到观测事件。\r\n *\r\n * 事件翻译只产生 running / idle / failed 三个目标态,永不产生 waiting_input\r\n * (该状态由宿主经 setStatus 显式播种,见 BOARD_TRANSITIONS 注释)。\r\n *\r\n * @returns {{applied: boolean, reason?: string, thread?: WorkThreadBoardState}}\r\n */\r\n async recordRuntimeEvent(opts: {\r\n agentId: string;\r\n sessionId: string;\r\n runtimeInstanceId?: string | null;\r\n event: Record<string, unknown>;\r\n }): Promise<{ applied: boolean; reason?: string; state?: WorkThreadBoardState }> {\r\n const { agentId, sessionId, runtimeInstanceId = null, event } = opts;\r\n\r\n const anchor = await this.core.findThreadByHeadSession(agentId, sessionId);\r\n if (!anchor) return { applied: false, reason: 'no_thread_for_session' };\r\n // closed 线程不再接受任何 runtime 事件(含 item.*),迟到的观测事件显式忽略。\r\n if (this.core.isTerminal(anchor)) return { applied: false, reason: 'thread_closed' };\r\n\r\n const type = typeof event?.type === 'string' ? event.type.trim() : '';\r\n if (!type) return { applied: false, reason: 'invalid_event' };\r\n\r\n const workThreadId = anchor.threadId;\r\n const details = {\r\n sessionId: typeof sessionId === 'string' ? sessionId.trim() : '',\r\n runtimeInstanceId:\r\n typeof runtimeInstanceId === 'string' && runtimeInstanceId.trim()\r\n ? runtimeInstanceId.trim()\r\n : null,\r\n turn: Number.isInteger(event?.turn) ? event.turn : null,\r\n };\r\n\r\n const eventId =\r\n (typeof event?.eventId === 'string' && event.eventId.trim()) ||\r\n `${details.runtimeInstanceId || 'runtime'}:${type}:${details.turn ?? 'none'}:${\r\n (event?.item as { id?: unknown })?.id || Date.now()\r\n }`;\r\n\r\n const appendExecutionEvent = async (threadId: string): Promise<WorkThreadBoardState> => {\r\n const { state } = await this.mutate(threadId, (draft) => {\r\n draft.executionEvents = Array.isArray(draft.executionEvents) ? draft.executionEvents : [];\r\n if (draft.executionEvents.some((entry) => entry.eventId === eventId)) return draft;\r\n draft.executionEvents.push({\r\n eventId,\r\n receivedAt: Date.now(),\r\n sessionId: details.sessionId,\r\n runtimeInstanceId: details.runtimeInstanceId,\r\n event: { ...event },\r\n });\r\n if (draft.executionEvents.length > MAX_EXECUTION_EVENTS) {\r\n const removed = draft.executionEvents.length - MAX_EXECUTION_EVENTS;\r\n draft.executionEvents.splice(0, removed);\r\n draft.executionEventBaseOffset = Math.max(0, Number(draft.executionEventBaseOffset) || 0) + removed;\r\n }\r\n return draft;\r\n });\r\n return state;\r\n };\r\n\r\n const transition = async (\r\n threadId: string,\r\n status: WorkThreadBoardStatus,\r\n eventType: string,\r\n extra: Record<string, unknown> = {},\r\n ): Promise<WorkThreadBoardState> => {\r\n const { state } = await this.mutate(threadId, (draft) => {\r\n if (draft.status === 'closed') return draft;\r\n if (!this.canTransition(draft.status, status)) {\r\n throw Object.assign(\r\n new Error(`Invalid board transition: ${draft.status} -> ${status}`),\r\n { code: 'invalid_board_transition', status: 409 },\r\n );\r\n }\r\n draft.status = status;\r\n this.pushLifecycle(draft, { type: eventType, status, at: Date.now(), ...details, ...extra });\r\n return draft;\r\n });\r\n return state;\r\n };\r\n\r\n if (type === 'item.started' || type === 'item.completed') {\r\n return { applied: true, state: await appendExecutionEvent(workThreadId) };\r\n }\r\n if (type === 'turn.started') {\r\n await transition(workThreadId, 'running', type);\r\n return { applied: true, state: await appendExecutionEvent(workThreadId) };\r\n }\r\n if (type === 'turn.completed') {\r\n await transition(workThreadId, 'idle', type, { usage: event.usage || null });\r\n return { applied: true, state: await appendExecutionEvent(workThreadId) };\r\n }\r\n if (type === 'turn.cancelled') {\r\n // 生命周期信号(guard 轮换 / 宿主中断):只记录,不做状态转换。\r\n return { applied: true, state: await appendExecutionEvent(workThreadId) };\r\n }\r\n if (type === 'turn.failed') {\r\n await transition(workThreadId, 'failed', type, { error: event.error || null });\r\n return { applied: true, state: await appendExecutionEvent(workThreadId) };\r\n }\r\n return { applied: false, reason: 'unsupported_event' };\r\n }\r\n\r\n // ── resume / mode ──────────────────────────────────────────────\r\n\r\n /**\r\n * 从 failed / waiting_input 恢复执行(看板状态 running)。\r\n * 看板永不反写锚点状态——恢复只改看板状态,锚点交接意图由宿主另行收拾。\r\n */\r\n async resume(workThreadId: string, opts: { source?: string } = {}): Promise<WorkThreadBoardState> {\r\n const state = (await this.getState(workThreadId)) || (await this.ensureInit(workThreadId, 'interactive'));\r\n if (state.status === 'closed') {\r\n throw Object.assign(new Error(`WorkThreadBoard \"${workThreadId}\" is closed`), {\r\n code: 'thread_closed',\r\n status: 409,\r\n });\r\n }\r\n if (state.status !== 'failed' && state.status !== 'waiting_input') {\r\n throw Object.assign(new Error(`WorkThreadBoard \"${workThreadId}\" cannot be resumed from ${state.status}`), {\r\n code: 'board_not_resumable',\r\n status: 409,\r\n });\r\n }\r\n const { state: next } = await this.mutate(workThreadId, (draft) => {\r\n draft.status = 'running';\r\n this.pushLifecycle(draft, {\r\n type: 'resumed',\r\n status: 'running',\r\n at: Date.now(),\r\n source: typeof opts.source === 'string' ? opts.source.trim() : 'api',\r\n });\r\n return draft;\r\n });\r\n return next;\r\n }\r\n\r\n async setMode(workThreadId: string, mode: WorkThreadBoardMode): Promise<WorkThreadBoardState> {\r\n if (!BOARD_MODES.has(mode)) {\r\n throw Object.assign(new Error(`Invalid board mode: ${mode}`), {\r\n code: 'invalid_board_mode',\r\n status: 400,\r\n });\r\n }\r\n const { state } = await this.mutate(workThreadId, (draft) => {\r\n if (draft.mode === mode) return draft;\r\n draft.mode = mode;\r\n return draft;\r\n });\r\n return state;\r\n }\r\n\r\n /**\r\n * 手动播种看板状态(宿主用于 `waiting_input` 等无事件源的场景——例如前端在\r\n * 等待人工输入时显式置位)。仅改看板域,不反写锚点状态。\r\n */\r\n async setStatus(workThreadId: string, status: WorkThreadBoardStatus): Promise<WorkThreadBoardState> {\r\n if (!BOARD_STATUSES.has(status)) {\r\n throw Object.assign(new Error(`Invalid board status: ${status}`), {\r\n code: 'invalid_board_status',\r\n status: 400,\r\n });\r\n }\r\n const { state } = await this.mutate(workThreadId, (draft) => {\r\n if (draft.status === status) return draft;\r\n draft.status = status;\r\n this.pushLifecycle(draft, { type: 'status_seeded', status, at: Date.now() });\r\n return draft;\r\n });\r\n return state;\r\n }\r\n\r\n /**\r\n * 把看板置为终态(锚点已关闭)。与核心 terminal 判定对应的看板终态。\r\n */\r\n async closeBoard(workThreadId: string, opts: { reason?: string } = {}): Promise<WorkThreadBoardState> {\r\n const { state } = await this.mutate(workThreadId, (draft) => {\r\n if (draft.status === 'closed') return draft;\r\n draft.status = 'closed';\r\n this.pushLifecycle(draft, {\r\n type: 'board_closed',\r\n status: 'closed',\r\n at: Date.now(),\r\n reason: typeof opts.reason === 'string' ? opts.reason.trim() : 'closed',\r\n });\r\n return draft;\r\n });\r\n return state;\r\n }\r\n\r\n /**\r\n * Reopen a board after a host-level archive is cancelled.\r\n *\r\n * `closed` is terminal for runtime events, so reopening is intentionally\r\n * separate from `resume`: resume handles failed/waiting_input, while this\r\n * operation restores an archived board to an idle, not-running state.\r\n */\r\n async reopenBoard(workThreadId: string, opts: { source?: string } = {}): Promise<WorkThreadBoardState> {\r\n const state = await this.getState(workThreadId);\r\n if (!state) {\r\n return this.ensureInit(workThreadId, 'autonomous');\r\n }\r\n if (state.status !== 'closed') return state;\r\n const { state: next } = await this.mutate(workThreadId, (draft) => {\r\n draft.status = 'idle';\r\n this.pushLifecycle(draft, {\r\n type: 'board_reopened',\r\n status: 'idle',\r\n at: Date.now(),\r\n source: typeof opts.source === 'string' ? opts.source.trim() : 'api',\r\n });\r\n return draft;\r\n });\r\n return next;\r\n }\r\n\r\n /** 状态机转换矩阵(公开,供测试与宿主校验)。 */\r\n getTransitionMatrix(): Record<WorkThreadBoardStatus, WorkThreadBoardStatus[]> {\r\n const out = {} as Record<WorkThreadBoardStatus, WorkThreadBoardStatus[]>;\r\n for (const s of Object.keys(BOARD_STATUSES) as WorkThreadBoardStatus[]) {\r\n out[s] = [...BOARD_TRANSITIONS[s]];\r\n }\r\n return out;\r\n }\r\n}\r\n"],"mappings":"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","names":["fileURLToPath","readFile","normalize","dirname","dirname","dirname","fileURLToPath","readFile","normalize","dirname","fileURLToPath","dirname","resolver","resolve","__filename","fileURLToPath","dirname","fileURLToPath","dirname","readFile","__filename","fileURLToPath","__dirname","dirname","readFile","fileURLToPath","fileURLToPath","fileURLToPath","readFile","dirname","join","path","diffLines","fileURLToPath","fileURLToPath","existsSync","readFileSync","join","normalize","__filename","fileURLToPath","existsSync","join","normalize","readFileSync","fileURLToPath","readFile","stat","mkdir","homedir","limit","offset","start","truncated","_","resolve","__filename","fileURLToPath","fileURLToPath","dirname","__filename","fileURLToPath","__dirname","dirname","fileURLToPath","path","path","readFile","fileURLToPath","spawn","path","path","proc","spawn","pkg","resolve","fileURLToPath","path","readFile","__filename","fileURLToPath","path","fs","fileURLToPath","dirname","join","mkdir","writeFile","__filename","fileURLToPath","__dirname","dirname","join","mkdir","writeFile","readFile","readFileSync","existsSync","resolve","join","path","path","cleanMultilineText","buildSummarySeedMessage","copyFile","mkdir","readFile","unlink","writeFile","join","randomUUID","entry","randomUUID","copyFile","mkdir","readFile","rename","unlink","writeFile","join","join","readFile","writeFile","rename","unlink","copyFile","mkdir"]}
|