dsh-agent-toolkit 0.1.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["z","z","MAX_BODY_BYTES","json","readJsonBody","z","readJsonBody","readJsonBody","z","z"],"sources":["../src/agents/store.ts","../src/agents/builtin.ts","../src/agents/import-yaml.ts","../src/channels/basic-tools.ts","../src/agents/registry.ts","../src/shared/storage.ts","../src/prompt/defaults.ts","../src/prompt/match.ts","../src/prompt/index.ts","../src/prompt/layer-source.ts","../src/shared/webserver.ts","../src/shared/http.ts","../src/prompt/api.ts","../src/prompt/persona.ts","../src/delegate/tool.ts","../src/delegate/index.ts","../src/agents/api.ts","../src/channels/agent-setup.ts","../src/channels/feishu/api.ts","../src/channels/directive.ts","../src/channels/feishu/parse.ts","../src/channels/feishu/cards.ts","../src/channels/feishu/reply.ts","../src/channels/feishu/index.ts","../src/bots/store.ts","../src/channels/inbound.ts","../src/channels/outbound.ts","../src/channels/ports.ts","../src/channels/router.ts","../src/channels/runtime.ts","../src/bots/api.ts","../src/bots/register-app.ts","../src/bots/index.ts","../src/index.ts"],"sourcesContent":["/** agents 注册表存储域声明:记录 schema + domain 布局的单一来源。 */\r\nimport { z } from 'zod'\r\nimport { defineDomain, domainTable } from '@deepseek-ai/dsh-storage-domain'\r\nimport type { LayerConfig } from '../prompt/types.ts'\r\n\r\n/** Agent id 约束:'main' 或小写字母开头、仅 [a-z0-9-]、总长 ≤ 32。 */\r\nexport const AGENT_ID_RE = /^(?:main|[a-z][a-z0-9-]{0,31})$/\r\n\r\n/** 一条 Agent 注册表记录。tools 仅白名单(用户定案:deny 不做)。 */\r\nexport interface AgentRecord {\r\n id: string // 'main' 或 [a-z0-9-] slug\r\n name: string\r\n description?: string\r\n persona?: string // 角色唯一可自定义提示层(固定分层中的 persona 层文本)\r\n /** @deprecated 仅迁移输入:旧版多分层,createRegistry 读取时拼接进 persona 后剥离。 */\r\n promptLayers?: LayerConfig[]\r\n model?: { provider: string; model: string }\r\n tools?: { allow: string[] } // 仅白名单;空数组拒绝(min(1) 语义)\r\n builtin?: boolean\r\n}\r\n\r\nexport const LayerConfigSchema = z.object({\r\n name: z.string(),\r\n order: z.number(),\r\n text: z.string(),\r\n})\r\n\r\nexport const AgentRecordSchema: z.ZodType<AgentRecord> = z.object({\r\n id: z.string().regex(AGENT_ID_RE),\r\n name: z.string().min(1),\r\n description: z.string().optional(),\r\n persona: z.string().optional(),\r\n promptLayers: z.array(LayerConfigSchema).optional(),\r\n model: z.object({ provider: z.string(), model: z.string() }).optional(),\r\n tools: z.object({ allow: z.array(z.string()).min(1) }).optional(),\r\n builtin: z.boolean().optional(),\r\n})\r\n\r\n/** domain 名/表名受 UNIT_NAME_RE 约束(^[a-z][a-z0-9_]*$),不允许连字符。 */\r\nexport const agentToolkitDomain = defineDomain({\r\n name: 'dsh_agent_toolkit',\r\n version: 1,\r\n tables: {\r\n agents: domainTable<string, AgentRecord>(AgentRecordSchema),\r\n // meta 表存一次性标记(如 roles_yaml_imported),schema 无法表达则独立成表。\r\n meta: domainTable<string, { value: string }>(z.object({ value: z.string() })),\r\n // 分层提示词层列表:单行 JSON(key 常量 'layers'),整体替换语义,与 agents 表同构校验。\r\n prompt_layers: domainTable<string, { layers: LayerConfig[] }>(z.object({ layers: z.array(LayerConfigSchema) })),\r\n },\r\n})\r\n\r\n/**\r\n * 旧记录迁移:promptLayers 按 order 升序拼接进 persona(忽略纯空白层;persona 已存在不覆盖),\r\n * 剥离 promptLayers 返回新对象;无需迁移返回原引用(调用方按引用比较决定是否写回)。\r\n */\r\nexport function migrateAgentRecord(record: AgentRecord): AgentRecord {\r\n if (record.promptLayers === undefined) return record\r\n const { promptLayers, ...rest } = record\r\n const joined = [...promptLayers]\r\n .sort((a, b) => a.order - b.order)\r\n .map((layer) => layer.text)\r\n .filter((text) => text.trim().length > 0)\r\n .join('\\n\\n')\r\n const persona = rest.persona ?? joined\r\n return persona.length > 0 ? { ...rest, persona } : rest\r\n}\r\n","/** 内置保底 Agent 记录:main + explorer(只读)/ general(可读写)。 */\r\nimport type { AgentRecord } from './store.ts'\r\n\r\nexport const BUILTIN_AGENTS: readonly AgentRecord[] = [\r\n {\r\n id: 'main',\r\n name: '主 Agent',\r\n builtin: true,\r\n },\r\n {\r\n id: 'explorer',\r\n name: 'Explorer',\r\n description: '快速只读代码库探索:定位文件/符号、回答结构与调用关系问题,不做任何修改',\r\n persona: `你是代码库探索员。快速定位与任务相关的文件与符号,回答关于代码结构、\r\n调用关系、实现位置的问题。你只读不写:不修改任何文件、不运行有副作用的命令。\r\n输出结论清单,每条附文件路径与行号;信息不足时说明缺口,不要猜测。`,\r\n builtin: true,\r\n },\r\n {\r\n id: 'general',\r\n name: 'General',\r\n description: '通用多步骤任务执行:可读可写、可运行命令,完成实现/修复类任务',\r\n persona: `你是通用执行员。按任务书独立完成多步骤工作,可以读写文件、运行命令。\r\n动手前先阅读相关 AGENTS.md 并遵循项目约定;完成后运行与改动相关的检查\r\n(测试/类型检查)验证改动,并在最终输出中报告验证结果。`,\r\n builtin: true,\r\n },\r\n]\r\n","/** 首启导入:把旧 agent-team 角色名册 $DSH_HOME/agent-team/roles/*.yml 一次性并入注册表。 */\r\nimport { readdir, readFile } from 'node:fs/promises'\r\nimport { join } from 'node:path'\r\nimport { z } from 'zod'\r\nimport yaml from 'js-yaml'\r\nimport { resolveDshHome } from '@deepseek-ai/dsh-home-paths'\r\nimport type { KvTable } from '@deepseek-ai/dsh-storage-domain'\r\nimport type { AgentRecord } from './store.ts'\r\nimport { AGENT_ID_RE } from './store.ts'\r\n\r\n/** 导入一次性标记在 meta 表中的键。 */\r\nexport const ROLES_YAML_IMPORTED_KEY = 'roles_yaml_imported'\r\n\r\nexport interface ImportRolesContext {\r\n agents: KvTable<string, AgentRecord>\r\n meta: KvTable<string, { value: string }>\r\n warn: (msg: string) => void\r\n}\r\n\r\nexport interface ImportResult {\r\n /** 成功导入(覆盖/新增)的条数。 */\r\n imported: number\r\n /** 解析失败被跳过的文件名列表。 */\r\n skipped: string[]\r\n}\r\n\r\nconst RoleYamlSchema = z.object({\r\n name: z.string().optional(),\r\n description: z.string().min(1),\r\n persona: z.string().min(1),\r\n provider: z.string().optional(),\r\n model: z.string().optional(),\r\n tools: z.object({\r\n allow: z.array(z.string()).optional(),\r\n deny: z.array(z.string()).optional(),\r\n }).optional(),\r\n})\r\n\r\n/**\r\n * 解析校验单个角色 YAML 文件并转成 AgentRecord。\r\n * @param text - 文件内容。\r\n * @param source - 用于错误信息的来源名(通常是文件路径)。\r\n * @param fileName - 文件名(去 .yml),name 省略时的取值;显式 name 须与它一致。\r\n * @param warn - 非致命丢弃(如 tools.deny)的通知通道。\r\n * @throws YAML 语法错误、结构非法、name 与文件名不一致、id 非法、tools 空。\r\n */\r\nexport function parseRoleYaml(text: string, source: string, fileName: string, warn?: (msg: string) => void): AgentRecord {\r\n let parsed: unknown\r\n try {\r\n parsed = yaml.load(text)\r\n } catch (error) {\r\n throw new Error(`dsh-agent-toolkit: 角色文件 ${source} 不是合法 YAML:${error instanceof Error ? error.message : String(error)}`)\r\n }\r\n const hasTools = parsed !== null && typeof parsed === 'object' && 'tools' in (parsed as object)\r\n let raw: z.infer<typeof RoleYamlSchema>\r\n try {\r\n raw = RoleYamlSchema.parse(parsed)\r\n } catch (error) {\r\n throw new Error(`dsh-agent-toolkit: 角色文件 ${source} 校验失败:${error instanceof Error ? error.message : String(error)}`)\r\n }\r\n const id = raw.name ?? fileName\r\n if (raw.name !== undefined && raw.name !== fileName) {\r\n throw new Error(`dsh-agent-toolkit: 角色文件 ${source} 的 name \"${raw.name}\" 与文件名 \"${fileName}\" 不一致(省略 name 即取文件名)`)\r\n }\r\n if (!AGENT_ID_RE.test(id)) {\r\n throw new Error(`dsh-agent-toolkit: 角色 id \"${id}\" 非法(${source}):只允许小写字母、数字、-,且以小写字母开头`)\r\n }\r\n if (hasTools && raw.tools !== undefined && (raw.tools.allow?.length ?? 0) === 0 && (raw.tools.deny?.length ?? 0) === 0) {\r\n throw new Error(`dsh-agent-toolkit: 角色文件 ${source} 的 tools 为空:allow/deny 至少配一个`)\r\n }\r\n if (raw.tools?.deny !== undefined && raw.tools.deny.length > 0) {\r\n warn?.(`dsh-agent-toolkit: 角色文件 ${source} 的 tools.deny 已忽略(注册表仅支持 allow 白名单)`)\r\n }\r\n const model = raw.provider !== undefined && raw.model !== undefined ? { provider: raw.provider, model: raw.model } : undefined\r\n const tools = hasTools && raw.tools !== undefined && raw.tools.allow !== undefined && raw.tools.allow.length > 0\r\n ? { allow: raw.tools.allow }\r\n : undefined\r\n return {\r\n id,\r\n name: id,\r\n description: raw.description,\r\n persona: raw.persona,\r\n ...(model !== undefined ? { model } : {}),\r\n ...(tools !== undefined ? { tools } : {}),\r\n }\r\n}\r\n\r\n/** 一个角色 YAML 文件引用:完整文件名 + 完整路径 + 去 .yml 的文件名(name 缺省取值)。 */\r\ninterface RoleFileRef {\r\n name: string\r\n path: string\r\n fileName: string\r\n}\r\n\r\n/**\r\n * 枚举 roles 目录下全部 .yml 角色文件,按文件名字典序返回。\r\n * 共享骨架(readdir/ENOENT/过滤/排序/文件名推导)——YAML 文件命名约定只在这里维护。\r\n * @param dir - roles 目录绝对路径。\r\n * @returns 文件引用列表;目录不存在或无 .yml 文件时返回空列表(静默跳过,属正常态)。\r\n * @throws 目录存在但不可读(非 ENOENT)。读取/解析的严格与宽容由调用方自行处理。\r\n */\r\nasync function enumerateRoleFiles(dir: string): Promise<RoleFileRef[]> {\r\n let entries: string[]\r\n try {\r\n entries = await readdir(dir)\r\n } catch (error) {\r\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return []\r\n throw new Error(`dsh-agent-toolkit: 角色目录不可读:${dir}(${error instanceof Error ? error.message : String(error)})`)\r\n }\r\n return entries\r\n .filter(f => f.endsWith('.yml'))\r\n .sort()\r\n .map(file => ({ name: file, path: join(dir, file), fileName: file.slice(0, -'.yml'.length) }))\r\n}\r\n\r\n/**\r\n * 读取 roles 目录下全部 .yml 角色文件,按文件名字典序返回(严格模式:任一文件非法即抛错)。\r\n * @param dir - roles 目录绝对路径。\r\n * @returns 角色记录列表;目录不存在或无 .yml 文件时返回空列表(静默跳过,属正常态)。\r\n * @throws 目录存在但不可读(非 ENOENT)、任一文件不可读/非法。\r\n */\r\nexport async function loadRolesDir(dir: string): Promise<AgentRecord[]> {\r\n const refs = await enumerateRoleFiles(dir)\r\n const records: AgentRecord[] = []\r\n for (const ref of refs) {\r\n let text: string\r\n try {\r\n text = await readFile(ref.path, 'utf8')\r\n } catch (error) {\r\n throw new Error(`dsh-agent-toolkit: 角色文件不可读:${ref.path}(${error instanceof Error ? error.message : String(error)})`)\r\n }\r\n records.push(parseRoleYaml(text, ref.path, ref.fileName))\r\n }\r\n return records\r\n}\r\n\r\n/**\r\n * 首启一次性导入:meta 表 roles_yaml_imported 标记短路;逐文件解析失败 warn 跳过(不阻塞激活);\r\n * 同名 YAML 覆盖内置保底记录。\r\n * @param ctx - agents/meta 表句柄与 warn 通道。\r\n * @param rolesDir - roles 目录;缺省为 $DSH_HOME/agent-team/roles。\r\n */\r\nexport async function importRolesYaml(ctx: ImportRolesContext, rolesDir?: string): Promise<ImportResult> {\r\n const result: ImportResult = { imported: 0, skipped: [] }\r\n if (ctx.meta.get(ROLES_YAML_IMPORTED_KEY) !== undefined) return result\r\n const dir = rolesDir ?? join(resolveDshHome(), 'agent-team', 'roles')\r\n let refs: RoleFileRef[]\r\n try {\r\n refs = await enumerateRoleFiles(dir)\r\n } catch (error) {\r\n // 目录不可读(非 ENOENT):warn 后标记完成,不阻塞激活。\r\n ctx.warn(error instanceof Error ? error.message : String(error))\r\n await markImported(ctx)\r\n return result\r\n }\r\n for (const ref of refs) {\r\n try {\r\n const text = await readFile(ref.path, 'utf8')\r\n const record = parseRoleYaml(text, ref.path, ref.fileName, ctx.warn)\r\n await ctx.agents.put(record.id, record)\r\n result.imported++\r\n } catch (error) {\r\n result.skipped.push(ref.name)\r\n ctx.warn(`dsh-agent-toolkit: 角色文件 ${ref.path} 导入失败,已跳过:${error instanceof Error ? error.message : String(error)}`)\r\n }\r\n }\r\n await markImported(ctx)\r\n return result\r\n}\r\n\r\nasync function markImported(ctx: ImportRolesContext): Promise<void> {\r\n await ctx.meta.put(ROLES_YAML_IMPORTED_KEY, { value: '1' })\r\n}\r\n","/** 基础工具行(与 dsh standard agent preset 同源):persona / instructions / shell / fs / fs-search。\r\n * 源:archive/2026-08-26-merged-plugins/agent-team/presets/team/agent.cordis.yml 的基础工具行,\r\n * 逐行对照 deepseek-harness/apps/cli/config/agent-presets/standard/agent.cordis.yml 核对 id 与 config。\r\n * shell 双行按平台互斥(win32 用 pwsh,其余用 bash),与两 preset 的 disabled 条件一致。\r\n * 这些行在 agent 创建期经 setupAgentScope scoped 挂载进各会话,不再依赖 preset 机制。 */\r\n\r\nexport interface BasicTool {\r\n /** 插件包名(preset 行的 name 字段)。 */\r\n id: string\r\n /** 插件 config(preset 行的 config 字段;无则省略)。 */\r\n config?: Record<string, unknown>\r\n}\r\n\r\nexport const BASIC_TOOLS: BasicTool[] = [\r\n {\r\n id: '@deepseek-ai/dsh-persona',\r\n config: { text: 'You are a coding agent powered by the {{model}} model. Your working directory is {{cwd}}.' },\r\n },\r\n {\r\n id: '@deepseek-ai/dsh-agent-instructions',\r\n config: { maxBytes: 65536 },\r\n },\r\n ...(process.platform === 'win32'\r\n ? [{ id: '@deepseek-ai/dsh-tool-pwsh' }]\r\n : [{ id: '@deepseek-ai/dsh-tool-bash' }]),\r\n { id: '@deepseek-ai/dsh-tool-fs' },\r\n {\r\n id: '@deepseek-ai/dsh-tool-fs-search',\r\n config: { sampleOverCapGlobResults: false },\r\n },\r\n]\r\n\r\n/** 原生工具名(白名单 UI 与存量迁移用):与 BASIC_TOOLS 挂载插件注册的工具名一一对应。\r\n * 名字来源(摘自 deepseek-harness 源码):dsh-tool-pwsh/dsh-tool-bash → 'pwsh'/'bash'(平台互斥);\r\n * dsh-tool-fs → 'read'/'write'/'edit'/'read_image';dsh-tool-fs-search → 'glob'/'grep'。\r\n * 这些工具 scoped 挂载在 agentCtx,不出现在顶层 ctx.tools.schemas(),故需显式常量。 */\r\nexport const NATIVE_TOOL_NAMES: readonly string[] = [\r\n process.platform === 'win32' ? 'pwsh' : 'bash',\r\n 'read',\r\n 'write',\r\n 'edit',\r\n 'read_image',\r\n 'glob',\r\n 'grep',\r\n]\r\n","/** Agent 注册表:内存缓存 + 持久化回写 + 订阅通知;main 置顶、内置保底不可删。 */\r\nimport type { KvTable } from '@deepseek-ai/dsh-storage-domain'\r\nimport { AgentRecordSchema, migrateAgentRecord, type AgentRecord } from './store.ts'\r\nimport { BUILTIN_AGENTS } from './builtin.ts'\r\nimport { importRolesYaml } from './import-yaml.ts'\r\nimport { NATIVE_TOOL_NAMES } from '../channels/basic-tools.ts'\r\n\r\nexport interface AgentRegistry {\r\n /** main 置顶,其余按 id 字典序。 */\r\n list(): AgentRecord[]\r\n get(id: string): AgentRecord | undefined\r\n /** main 的 name/builtin 不可改;builtin 可改配置不可删。 */\r\n upsert(record: AgentRecord): Promise<void>\r\n /** main 与 builtin 抛错。 */\r\n remove(id: string): Promise<void>\r\n /** UI/委派提示段热更新用;返回退订函数。 */\r\n subscribe(listener: () => void): () => void\r\n}\r\n\r\n/** tools.allow 一次性并入原生工具名的 meta 表标记键。 */\r\nexport const TOOLS_NATIVE_MIGRATED_KEY = 'tools_native_migrated'\r\n\r\n/**\r\n * 打开 dsh_agent_toolkit 域 → 缺 main/explorer/general 时种入内置 → 首启 YAML 导入 →\r\n * 构建内存缓存。域由 apply 统一 open(storage-domain 同名单开),此处只消费表句柄。\r\n */\r\nexport async function createRegistry(\r\n warn: (msg: string) => void,\r\n tables: { agents: KvTable<string, AgentRecord>; meta: KvTable<string, { value: string }> },\r\n): Promise<AgentRegistry> {\r\n const { agents, meta } = tables\r\n\r\n await seedBuiltins(agents)\r\n await importRolesYaml({ agents, meta, warn })\r\n\r\n // 旧记录迁移:promptLayers → persona(逐条幂等);tools.allow 一次性并入原生工具名\r\n // (meta 标记幂等——UI 从未提供原生工具勾选项,存量白名单缺原生名非用户本意;\r\n // 标记置位后用户再编辑 allow 不会被回收改)。\r\n const nativeMigrated = meta.get(TOOLS_NATIVE_MIGRATED_KEY) !== undefined\r\n for (const [id, record] of agents.entries()) {\r\n let next = migrateAgentRecord(record)\r\n if (!nativeMigrated && next.tools !== undefined) {\r\n const allow = next.tools.allow\r\n const missing = NATIVE_TOOL_NAMES.filter((name) => !allow.includes(name))\r\n if (missing.length > 0) next = { ...next, tools: { allow: [...allow, ...missing] } }\r\n }\r\n if (next !== record) await agents.put(id, next)\r\n }\r\n if (!nativeMigrated) await meta.put(TOOLS_NATIVE_MIGRATED_KEY, { value: '1' })\r\n\r\n const cache = new Map<string, AgentRecord>()\r\n for (const [id, record] of agents.entries()) cache.set(id, record)\r\n\r\n const listeners = new Set<() => void>()\r\n const notify = () => {\r\n for (const listener of [...listeners]) listener()\r\n }\r\n\r\n return {\r\n list(): AgentRecord[] {\r\n const main = cache.get('main')\r\n const rest = [...cache.entries()]\r\n .filter(([id]) => id !== 'main')\r\n .map(([, record]) => record)\r\n .sort((a, b) => a.id.localeCompare(b.id))\r\n return main === undefined ? rest : [main, ...rest]\r\n },\r\n get(id: string): AgentRecord | undefined {\r\n return cache.get(id)\r\n },\r\n async upsert(record: AgentRecord): Promise<void> {\r\n const parsed = AgentRecordSchema.safeParse(record)\r\n if (!parsed.success) {\r\n throw new Error(`dsh-agent-toolkit: Agent 记录校验失败:${parsed.error.message}`)\r\n }\r\n const normalized = migrateAgentRecord(parsed.data)\r\n const existing = cache.get(record.id)\r\n if (record.id === 'main' && existing !== undefined) {\r\n if (existing.name !== record.name || existing.builtin !== record.builtin) {\r\n throw new Error('dsh-agent-toolkit: 主 Agent(main)的 name/builtin 字段不可修改')\r\n }\r\n }\r\n if (existing?.builtin === true && record.builtin !== true) {\r\n throw new Error(`dsh-agent-toolkit: 内置角色 ${record.id} 的 builtin 标记不可修改`)\r\n }\r\n await agents.put(record.id, normalized)\r\n cache.set(record.id, normalized)\r\n notify()\r\n },\r\n async remove(id: string): Promise<void> {\r\n if (id === 'main') throw new Error('dsh-agent-toolkit: 主 Agent(main)不可删除')\r\n const existing = cache.get(id)\r\n if (existing?.builtin === true) {\r\n throw new Error(`dsh-agent-toolkit: 内置角色 ${id} 不可删除`)\r\n }\r\n const deleted = await agents.delete(id)\r\n if (deleted) {\r\n cache.delete(id)\r\n notify()\r\n }\r\n },\r\n subscribe(listener: () => void): () => void {\r\n listeners.add(listener)\r\n return () => { listeners.delete(listener) }\r\n },\r\n }\r\n}\r\n\r\nasync function seedBuiltins(agents: KvTable<string, AgentRecord>): Promise<void> {\r\n for (const builtin of BUILTIN_AGENTS) {\r\n if (agents.get(builtin.id) === undefined) {\r\n await agents.put(builtin.id, builtin)\r\n }\r\n }\r\n}\r\n","/** shared storage 助手:安全打开存储域(open 失败挂 rejection handler)并在卸载时关闭。 */\r\nimport type { Context } from '@deepseek-ai/cordis'\r\nimport type { Domain, DomainSpec } from '@deepseek-ai/dsh-storage-domain'\r\n\r\n/** 类型擦除后的存储域句柄(跨 spec 泛型的统一承载面)。 */\r\nexport type DomainHandle = Domain<DomainSpec>\r\n\r\nexport function openDomainSafely(\r\n ctx: Context,\r\n domain: DomainSpec,\r\n warn: (msg: string) => void,\r\n beforeClose?: () => void | Promise<void>,\r\n): Promise<DomainHandle> {\r\n const ready = ctx.storageDomain.open(domain)\r\n // open 失败(version-mismatch/malformed-medium/invalid-record)时创建即挂\r\n // rejection handler:避免 unhandled rejection 崩掉宿主进程(Node 默认 throw)。\r\n // ready 仍保持 reject,调用方仍感知失败而不次生崩溃。\r\n ready.catch((error) => {\r\n warn(error instanceof Error ? error.message : String(error))\r\n })\r\n // 域句柄由本 fiber 持有:卸载时 close(消费方自己不关闭)。open 失败时\r\n // close 无从谈起,吞掉该 rejection,避免卸载路径次生崩溃。\r\n ctx.effect(() => async () => {\r\n // beforeClose 在 close 前排空消费方自己的写链(如 usage 的 tail):close 一旦\r\n // 开始(disposing=true)就拒绝新入队的写,未落队的采集会被静默丢弃。drain\r\n // 失败不阻断 close——卸载路径不因 drain 异常次生崩溃。\r\n await Promise.resolve(beforeClose?.()).catch(() => undefined)\r\n await ready.then((domain) => domain.close()).catch(() => undefined)\r\n })\r\n return ready\r\n}\r\n","// 默认文本改写自 opencode(MIT 许可,https://github.com/anomalyco/opencode,\r\n// packages/opencode/src/session/prompt/*.txt @ dev 分支):剔除 opencode 专有内容\r\n// (身份自述、具体工具名、/help /bug ctrl+p、issues URL、opencode.ai),保留模型族\r\n// 行为指导。身份首句刻意不写——dsh 原生 `harness:identity` 段(order -100)已覆盖身份。\r\nimport type { LayerConfig, Rule } from './types.ts'\r\n\r\n/** 通用基座层文本(default.txt 改写版)。 */\r\nexport const BASE_TEXT = `IMPORTANT: You must NEVER generate or guess URLs for the user unless you are confident that the URLs are for helping the user with programming. You may use URLs provided by the user in their messages or local files.\r\n\r\n# Tone and style\r\nYou should be concise, direct, and to the point. When you run a non-trivial shell command, explain what the command does and why you are running it, so the user understands what you are doing (this is especially important when the command changes the user's system).\r\nYour output will be displayed on a command line interface. You can use GitHub-flavored markdown for formatting; it will be rendered in a monospace font using the CommonMark specification.\r\nOutput text to communicate with the user; all text you output outside of tool use is displayed to the user. Only use tools to complete tasks. Never use tools or code comments as a means to communicate with the user during the session.\r\nIf you cannot or will not help the user with something, do not preach about why or what it could lead to. Offer helpful alternatives if possible, and otherwise keep your response to 1-2 sentences.\r\nOnly use emojis if the user explicitly requests it. Avoid using emojis in all communication unless asked.\r\nIMPORTANT: Minimize output tokens as much as possible while maintaining helpfulness, quality, and accuracy. Only address the specific query or task at hand, avoiding tangential information unless absolutely critical. If you can answer in 1-3 sentences or a short paragraph, please do.\r\nIMPORTANT: Do not answer with unnecessary preamble or postamble (such as explaining your code or summarizing your actions) unless the user asks you to.\r\nKeep responses short: answer the user's question directly, without elaboration. Avoid introductions, conclusions, and restatements such as \"The answer is ...\" or \"Here is what I will do next ...\".\r\n<example>\r\nuser: what is 2+2?\r\nassistant: 4\r\n</example>\r\n\r\n<example>\r\nuser: what files are in the directory src/?\r\nassistant: [lists files and sees foo.c, bar.c, baz.c]\r\nuser: which file contains the implementation of foo?\r\nassistant: src/foo.c\r\n</example>\r\n\r\n# Proactiveness\r\nBe proactive only when the user asks you to do something. Strike a balance between:\r\n1. Doing the right thing when asked, including follow-up actions the request implies.\r\n2. Not surprising the user with actions taken without asking.\r\nIf the user asks how to approach something, answer the question first instead of immediately jumping into action.\r\nDo not add a code-explanation summary unless requested. After working on a file, just stop.\r\n\r\n# Following conventions\r\nWhen making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\r\n- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses it (neighboring files, package manifests such as package.json or cargo.toml).\r\n- When you create a new component, first look at existing components: framework choice, naming conventions, typing, and other conventions.\r\n- When you edit a piece of code, read its surrounding context (especially its imports) and make the change idiomatic to it.\r\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\r\n\r\n# Code style\r\n- IMPORTANT: DO NOT ADD ***ANY*** COMMENTS unless asked.\r\n\r\n# Doing tasks\r\nFor software engineering tasks (fixing bugs, adding features, refactoring, explaining code, and more):\r\n- Use the available search tools extensively, in parallel and sequentially, to understand the codebase and the user's query.\r\n- Implement the solution using all tools available to you.\r\n- Verify the solution with tests where possible. NEVER assume a specific test framework or test script; check the README or search the codebase to determine the testing approach.\r\n- When you have completed a task, run the project's lint and typecheck commands if they exist. If you cannot find the correct command, ask the user for it.\r\n- NEVER commit changes unless the user explicitly asks you to.\r\n\r\nTool results and user messages may include <system-reminder> tags. They contain useful information and reminders. They are NOT part of the user's provided input or the tool result.\r\n\r\n# Tool usage policy\r\n- For file or content search, prefer dedicated search tools over shell commands to reduce context usage.\r\n- You can call multiple tools in a single response. Batch independent calls together for optimal performance; run dependent calls sequentially.\r\n\r\nBefore you begin work, think about what the code you are editing is supposed to do, based on filenames and directory structure.\r\n\r\n# Code references\r\nWhen referencing specific functions or pieces of code, use the pattern \\`file_path:line_number\\` so the user can easily navigate to the source location.`\r\n\r\n/** 模型族行为指导文本(anthropic/gemini/beast/codex/gpt/kimi 改写版,\r\n * 内容按下文\"6 个模型族 TEXT 的改写契约\"逐条产出,英文,不写身份首句)。 */\r\nexport const ANTHROPIC_TEXT = `IMPORTANT: You must NEVER generate or guess URLs for the user unless you are confident that the URLs are for helping the user with programming. You may use URLs provided by the user in their messages or local files.\r\n\r\n# Tone and style\r\n- Only use emojis if the user explicitly requests it. Avoid using emojis in all communication unless asked.\r\n- Your output will be displayed on a command line interface. Your responses should be short and concise. You can use GitHub-flavored markdown for formatting, and it will be rendered in a monospace font using the CommonMark specification.\r\n- Output text to communicate with the user; all text you output outside of tool use is displayed to the user. Only use tools to complete tasks. Never use shell commands or code comments as a means to communicate with the user during the session.\r\n- NEVER create files unless they are absolutely necessary for achieving your goal. ALWAYS prefer editing an existing file to creating a new one.\r\n\r\n# Professional objectivity\r\nPrioritize technical accuracy and truthfulness over validating the user's beliefs. Focus on facts and problem-solving, providing direct, objective technical information without unnecessary superlatives, praise, or emotional validation. Apply the same rigorous standards to all ideas and disagree when necessary, even if it may not be what the user wants to hear. Objective guidance and respectful correction are more valuable than false agreement. Whenever there is uncertainty, investigate to find the truth first rather than instinctively confirming the user's beliefs.\r\n\r\n# Planning and tracking\r\nUse a task list frequently to plan and track your work, giving the user visibility into your progress. These lists are also helpful for breaking down larger, complex tasks into smaller steps. Mark each task as completed as soon as you are done; do not batch up multiple tasks before marking them completed.\r\n\r\n# Doing tasks\r\nThe user will primarily request software engineering tasks: fixing bugs, adding new functionality, refactoring code, explaining code, and more. Search the codebase to understand the user's query, implement the solution using all tools available to you, then verify it. Tool results and user messages may include <system-reminder> tags. They contain useful information and reminders; they are authoritative and are NOT part of the user's provided input or the tool result.\r\n\r\n# Tool usage policy\r\n- For file or content search, prefer dedicated search tools over shell commands to reduce context usage.\r\n- Prefer dedicated editing tools over shell for modifying files.\r\n- You can call multiple tools in a single response. Make all independent tool calls in parallel; run dependent calls sequentially. Never use placeholders or guess missing parameters in tool calls.\r\n\r\n# Code references\r\nWhen referencing specific functions or pieces of code, use the pattern \\`file_path:line_number\\` so the user can easily navigate to the source location.`\r\n\r\nexport const GEMINI_TEXT = `# Core Mandates\r\n\r\n- **Conventions:** Rigorously adhere to existing project conventions when reading or modifying code. Analyze surrounding code, tests, and configuration first.\r\n- **Libraries/Frameworks:** NEVER assume a library or framework is available or appropriate. Verify its established usage within the project (check imports and configuration files, or observe neighboring files) before employing it.\r\n- **Style & Structure:** Mimic the style (formatting, naming), structure, framework choices, typing, and architectural patterns of existing code in the project.\r\n- **Idiomatic Changes:** When editing, understand the local context (imports, functions, classes) to ensure your changes integrate naturally and idiomatically.\r\n- **Comments:** Add code comments sparingly. Focus on *why* something is done, especially for complex logic, rather than *what* is done. Only add high-value comments if necessary for clarity or if requested by the user. Do not edit comments that are separate from the code you are changing. *NEVER* talk to the user or describe your changes through comments.\r\n- **Proactiveness:** Fulfill the user's request thoroughly, including reasonable, directly implied follow-up actions.\r\n- **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If asked *how* to do something, explain first; do not just do it.\r\n- **Explaining Changes:** After completing a code modification or file operation, do not provide summaries unless asked.\r\n- **Path Construction:** Before using any file system tool, construct the full absolute path for the file argument. Always combine the absolute path of the project root with the file's path relative to the root. If the user provides a relative path, resolve it against the root to create an absolute path.\r\n- **Do Not Revert Changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they resulted in an error or if the user has explicitly asked you to revert them.\r\n\r\n# Primary Workflows\r\n\r\n## Software Engineering Tasks\r\nWhen requested to fix bugs, add features, refactor, or explain code, follow this sequence:\r\n1. **Understand:** Think about the request and the relevant codebase context. Search extensively (in parallel if independent) to understand file structures, existing patterns, and conventions. Read to validate any assumptions.\r\n2. **Plan:** Build a coherent, grounded plan for how you intend to resolve the task. Share an extremely concise yet clear plan with the user if it would help. Use a self-verification loop by writing unit tests where relevant; use output logs or debug statements as part of this loop to arrive at a solution.\r\n3. **Implement:** Act on the plan using available tools, strictly adhering to the project's established conventions.\r\n4. **Verify (Tests):** If applicable and feasible, verify the changes using the project's testing procedures. Identify the correct test commands and frameworks by examining README files and build or package configuration; NEVER assume standard test commands.\r\n5. **Verify (Standards):** After making code changes, execute the project-specific build, lint, and type-checking commands you have identified. If unsure about these commands, ask the user.\r\n\r\n## New Applications\r\nAutonomously implement and deliver a visually appealing, substantially complete, functional prototype:\r\n1. **Understand Requirements:** Analyze the request to identify core features, desired user experience, visual aesthetic, application type and platform, and explicit constraints. If critical information for planning is missing or ambiguous, ask concise, targeted clarification questions.\r\n2. **Propose Plan:** Formulate an internal development plan and present a clear, concise summary covering the application's type and core purpose, key technologies, main features, interaction model, and the approach to a polished visual design and user experience.\r\n3. **User Approval:** Obtain user approval for the proposed plan before implementing.\r\n4. **Implementation:** Autonomously implement each feature and design element per the approved plan. Use placeholder assets only when essential for progress, intending to replace them with more refined versions or instructing the user on replacement during polishing.\r\n5. **Verify:** Review work against the original request and approved plan. Fix bugs, deviations, and placeholders where feasible. Build the application and ensure there are no compile errors.\r\n6. **Solicit Feedback:** Provide instructions on how to start the application and request user feedback.\r\n\r\n# Operational Guidelines\r\n\r\n## Tone and Style (CLI Interaction)\r\n- **Concise & Direct:** Adopt a professional, direct, and concise tone suitable for a CLI environment.\r\n- **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use and code generation) per response whenever practical. Focus strictly on the user's query.\r\n- **Clarity over Brevity (When Needed):** While conciseness is key, prioritize clarity for essential explanations or when seeking necessary clarification.\r\n- **No Chitchat:** Avoid conversational filler, preambles, or postambles. Get straight to the action or answer.\r\n- **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.\r\n- **Tools vs. Text:** Use tools for actions; text output only for communication. Do not add explanatory comments within tool calls or code blocks unless specifically part of the required code.\r\n- **Handling Inability:** If unable or unwilling to fulfill a request, state so briefly (1-2 sentences) without excessive justification. Offer alternatives if appropriate.\r\n\r\n## Security and Safety Rules\r\n- **Explain Critical Commands:** Before executing commands that modify the file system, codebase, or system state, provide a brief explanation of the command's purpose and potential impact. Prioritize user understanding and safety.\r\n- **Security First:** Always apply security best practices. Never introduce code that exposes, logs, or commits secrets, API keys, or other sensitive information.\r\n\r\n## Tool Usage\r\n- **File Paths:** Always use absolute paths when referring to files with file tools. Relative paths are not supported; you must provide an absolute path.\r\n- **Parallelism:** Execute multiple independent tool calls in parallel when feasible.\r\n- **Command Execution:** Run shell commands for actual system commands and terminal operations, remembering to explain modifying commands first.\r\n- **Respect User Confirmations:** Tool calls will first require confirmation from the user, where they will either approve or cancel. If a user cancels a call, respect their choice and do not try to make the call again; it is okay to request it again only if the user asks on a subsequent prompt.\r\n\r\n# Final Reminder\r\nYour core function is efficient and safe assistance. Balance extreme conciseness with the crucial need for clarity, especially regarding safety and potential system modifications. Always prioritize user control and project conventions. Never make assumptions about the contents of files; instead read to ensure you are not making broad assumptions. Keep going until the user's query is completely resolved.`\r\n\r\nexport const BEAST_TEXT = `Keep going until the user's query is completely resolved, before ending your turn and yielding back to the user.\r\n\r\nYour thinking should be thorough, and it is fine if it is very long. However, avoid unnecessary repetition and verbosity. You should be concise, but thorough.\r\n\r\nYou MUST iterate and keep going until the problem is solved. You have everything you need to resolve this problem. Fully solve it autonomously before coming back. Only terminate your turn when you are sure the problem is solved and all items have been checked off. Go through the problem step by step, verify that your changes are correct, and never end your turn without having truly and completely solved the problem. When you say you are going to make a tool call, make sure you ACTUALLY make the tool call instead of ending your turn.\r\n\r\nYour knowledge may be out of date because your training date is in the past. Use available search means to verify your understanding of third-party packages and dependencies is up to date every time you install or implement one. It is not enough to just search; you must also read the content of the pages you find and gather all relevant information until you have everything you need.\r\n\r\nAlways tell the user what you are going to do before making a tool call with a single concise sentence.\r\n\r\nTake your time and think through every step. Check your solution rigorously and watch out for boundary cases, especially with the changes you made. Your solution must be perfect; if not, continue working on it. Test your code rigorously using the tools provided, many times, to catch all edge cases. If it is not robust, iterate more. Failing to test your code rigorously is the number one failure mode; make sure you handle all edge cases and run existing tests if they are provided.\r\n\r\nPlan extensively before each function call, and reflect extensively on the outcomes of the previous calls. Do not do this entire process by making function calls only, as this can impair your ability to solve the problem and think insightfully. Keep working until the problem is completely solved and all items in the todo list are checked off; do not end your turn until you have completed all steps and verified that everything is working correctly.\r\n\r\n# Workflow\r\n1. Fetch any URLs provided by the user using the search tool.\r\n2. Understand the problem deeply. Carefully read the issue and think critically about what is required. Break down the problem into manageable parts, considering the expected behavior, edge cases, potential pitfalls, the larger context of the codebase, and the dependencies and interactions with other parts of the code.\r\n3. Investigate the codebase. Explore relevant files, search for key functions, and gather context.\r\n4. Research the problem using available search means by reading relevant articles, documentation, and forums.\r\n5. Develop a clear, step-by-step plan. Break down the fix into manageable, incremental steps and display the plan as a todo list, checking off each item as you go.\r\n6. Implement the fix incrementally. Make small, testable code changes.\r\n7. Debug as needed. Use debugging techniques to isolate and resolve issues.\r\n8. Test frequently. Run tests after each change to verify correctness.\r\n9. Iterate until the root cause is fixed and all tests pass.\r\n10. Reflect and validate comprehensively. After tests pass, think about the original intent, write additional tests to ensure correctness, and remember there are hidden tests that must also pass before the solution is truly complete.\r\n\r\n## Debugging\r\n- Make code changes only if you have high confidence they can solve the problem.\r\n- When debugging, determine the root cause rather than addressing symptoms. Use print statements, logs, or temporary code to inspect program state and test your hypotheses. Revisit your assumptions if unexpected behavior occurs.\r\n- Always read enough context to understand the code before editing; avoid re-reading files whose content has not changed.\r\n\r\n# Communication\r\nCommunicate clearly and concisely in a casual, friendly yet professional tone. Avoid unnecessary explanations, repetition, and filler. Always write code directly to the correct files, and do not display code to the user unless they specifically ask for it.\r\n\r\n# Memory\r\nRemember user preferences expressed across the session and apply them consistently.\r\n\r\n# Git\r\nNever stage and commit files automatically unless the user explicitly tells you to.`\r\n\r\nexport const CODEX_TEXT = `## Editing constraints\r\n- Default to ASCII when editing or creating files. Only introduce non-ASCII or other Unicode characters when there is a clear justification and the file already uses them.\r\n- Only add comments if they are necessary to make a non-obvious block easier to understand.\r\n\r\n## Tool usage\r\n- Prefer dedicated tools over shell for file operations: use an editing tool to modify files, a reading tool to view files, and search tools to find files by name or search file contents.\r\n- Use shell for terminal operations: git, builds, tests, and running scripts.\r\n- Run tool calls in parallel when neither call needs the other's output; otherwise run them sequentially.\r\n\r\n## Git and workspace hygiene\r\n- You may be in a dirty git worktree.\r\n * NEVER revert existing changes you did not make unless explicitly requested, since these changes were made by the user.\r\n * If asked to make a commit or code edits and there are unrelated changes to your work or changes you did not make in those files, do not revert those changes.\r\n * If the changes are in files you have touched recently, read them carefully and understand how you can work with the changes rather than reverting them.\r\n * If the changes are in unrelated files, just ignore them and do not revert them.\r\n- Do not amend commits unless explicitly requested.\r\n- **NEVER** use destructive commands like \\`git reset --hard\\` or \\`git checkout --\\` unless specifically requested or approved by the user.\r\n\r\n## Frontend tasks\r\nWhen doing frontend design tasks, avoid collapsing into bland, generic layouts. Aim for interfaces that feel intentional and deliberate.\r\n- Typography: Use expressive, purposeful fonts and avoid default stacks.\r\n- Color & Look: Choose a clear visual direction; define CSS variables; avoid generic defaults.\r\n- Motion: Use a few meaningful animations (page-load, staggered reveals) instead of generic micro-motions.\r\n- Background: Don't rely on flat, single-color backgrounds; use gradients, shapes, or subtle patterns to build atmosphere.\r\n- Overall: Avoid boilerplate layouts and interchangeable UI patterns. Vary themes, type families, and visual languages across outputs.\r\n- Ensure the page loads properly on both desktop and mobile.\r\nException: If working within an existing website or design system, preserve the established patterns, structure, and visual language.\r\n\r\n## Presenting your work and final message\r\n- Default: be very concise; friendly coding teammate tone.\r\n- Default: do the work without asking questions. Treat short tasks as sufficient direction; infer missing details by reading the codebase and following existing conventions.\r\n- Questions: only ask when you are truly blocked after checking relevant context AND you cannot safely pick a reasonable default. This usually means one of: the request is ambiguous in a way that materially changes the result and you cannot disambiguate by reading the repo; the action is destructive or irreversible, touches production, or changes billing or security posture; you need a secret or credential or value that cannot be inferred.\r\n- If you must ask: do all non-blocked work first, then ask exactly one targeted question, include your recommended default, and state what would change based on the answer.\r\n- Never ask permission questions like \"Should I proceed?\"; proceed with the most reasonable option and mention what you did.\r\n- For substantial work, summarize clearly and follow the final-answer formatting rules.\r\n- Skip heavy formatting for simple confirmations.\r\n- Don't dump large files you have written; reference paths only.\r\n- Offer logical next steps (tests, commits, build) briefly; add verify steps if you could not do something.\r\n- For code changes: lead with a quick explanation of the change, then give more details on the context covering where and why the change was made. If there are natural next steps, suggest them at the end of your response.\r\n\r\n## Final answer structure and style guidelines\r\n- Plain text; the CLI handles styling. Use structure only when it helps scannability.\r\n- Headers: optional; short Title Case (1-3 words); add only if they truly help.\r\n- Bullets: use -; merge related points; keep to one line when possible; keep phrasing consistent.\r\n- Monospace: use inline code for commands, paths, env vars, code ids, and inline examples; never combine with bold.\r\n- Code samples or multi-line snippets should be wrapped in fenced code blocks; include a language tag as often as possible.\r\n- Structure: group related bullets; order sections general to specific.\r\n- Tone: collaborative, concise, factual; present tense, active voice; self-contained.\r\n- Don'ts: no nested bullets or hierarchies; no ANSI codes; don't cram unrelated keywords; avoid naming formatting styles in answers.\r\n- File references: reference files with inline code so paths are clickable; each reference should have a standalone path; optionally include line/column (1-based) using the pattern \\`file_path:line_number\\`.`\r\n\r\nexport const GPT_TEXT = `Be a deeply pragmatic, effective software engineer. Take engineering quality seriously; collaboration comes through as direct, factual statements. Communicate efficiently, keeping the user clearly informed about ongoing actions without unnecessary detail. Build context by examining the codebase first without making assumptions or jumping to conclusions. Think through the nuances of the code you encounter and embody the mentality of a skilled senior software engineer.\r\n\r\n## Editing Approach\r\n\r\n- The best changes are often the smallest correct changes.\r\n- When you are weighing two correct approaches, prefer the more minimal one (less new names, helpers, tests, and so on).\r\n- Keep things in one function unless composable or reusable.\r\n- Do not add backward-compatibility code unless there is a concrete need, such as persisted data, shipped behavior, external consumers, or an explicit user requirement; if unclear, ask one short question instead of guessing.\r\n\r\n## Autonomy and persistence\r\n\r\nUnless the user explicitly asks for a plan, asks a question about the code, is brainstorming potential solutions, or some other intent makes it clear that code should not be written, assume the user wants you to make code changes or run tools to solve the user's problem. In these cases it is bad to output your proposed solution in a message; you should go ahead and actually implement the change. If you encounter challenges or blockers, attempt to resolve them yourself.\r\n\r\nPersist until the task is fully handled end-to-end within the current turn whenever feasible: do not stop at analysis or partial fixes; carry changes through implementation, verification, and a clear explanation of outcomes unless the user explicitly pauses or redirects you.\r\n\r\nIf you notice unexpected changes in the worktree or staging area that you did not make, continue with your task. NEVER revert, undo, or modify changes you did not make unless the user explicitly asks you to. There can be multiple agents or the user working in the same codebase concurrently.\r\n\r\n## Editing constraints\r\n\r\n- Default to ASCII when editing or creating files. Only introduce non-ASCII or other Unicode characters when there is a clear justification and the file already uses them.\r\n- Add succinct code comments that explain what is going on if code is not self-explanatory. Do not add comments like \"assigns the value to the variable\"; a brief comment might be useful ahead of a complex code block. Usage of these comments should be rare.\r\n- Use dedicated tools rather than scripts for reading and writing files when a simple dedicated tool call would suffice.\r\n- You may be in a dirty git worktree.\r\n * NEVER revert existing changes you did not make unless explicitly requested, since these changes were made by the user.\r\n * If asked to make a commit or code edits and there are unrelated changes to your work or changes you did not make in those files, do not revert those changes.\r\n * If the changes are in files you have touched recently, read them carefully and understand how you can work with them rather than reverting them.\r\n * If the changes are in unrelated files, just ignore them and do not revert them.\r\n- Do not amend a commit unless explicitly requested.\r\n- **NEVER** use destructive commands like \\`git reset --hard\\` or \\`git checkout --\\` unless specifically requested or approved by the user.\r\n\r\n## Special user requests\r\n\r\nIf the user makes a simple request (such as asking for the time) which you can fulfill by running a terminal command, do so.\r\n\r\nIf the user pastes an error description or a bug report, help them diagnose the root cause. You can try to reproduce it if it seems feasible with the available tools.\r\n\r\nIf the user asks for a \"review\", default to a code review mindset: prioritize identifying bugs, risks, behavioural regressions, and missing tests. Findings must be the primary focus of the response; keep summaries or overviews brief and only after enumerating the issues. Present findings first, ordered by severity with file/line references, followed by open questions or assumptions, and offer a change summary only as a secondary detail. If no findings are discovered, state that explicitly and mention any residual risks or testing gaps.\r\n\r\n## Frontend tasks\r\n\r\nWhen doing frontend design tasks, avoid collapsing into \"AI slop\" or safe, average-looking layouts.\r\n- Ensure the page loads properly on both desktop and mobile.\r\n- Overall: Avoid boilerplate layouts and interchangeable UI patterns. Vary themes, type families, and visual languages across outputs.\r\nException: If working within an existing website or design system, preserve the established patterns, structure, and visual language.\r\n\r\n# Working with the user\r\n\r\n## General\r\n\r\nDo not begin responses with conversational interjections or meta commentary. Avoid openers such as acknowledgements or framing phrases.\r\n\r\nBalance conciseness to not overwhelm the user with appropriate detail for the request. Do not narrate abstractly; explain what you are doing and why.\r\n\r\n## Formatting rules\r\n\r\nYour responses are rendered as GitHub-flavored Markdown.\r\n\r\nNever use nested bullets. Keep lists flat (single level). If you need hierarchy, split into separate lists or sections. For numbered lists, only use the \\`1. 2. 3.\\` style markers (with a period), never \\`1)\\`.\r\n\r\nHeaders are optional, only use them when you think they are necessary. If you do use them, use short Title Case (1-3 words). Don't add a blank line.\r\n\r\nUse inline code blocks for commands, paths, environment variables, function names, inline examples, and keywords.\r\n\r\nCode samples or multi-line snippets should be wrapped in fenced code blocks. Include a language tag when possible.\r\n\r\nDon't use emojis or em dashes unless explicitly instructed.\r\n\r\n## Progress and final responses\r\n\r\nKeep intermediate progress updates short and send them only when they add meaningful new information: a discovery, a tradeoff, a blocker, a substantial plan, or the start of a non-trivial edit or verification step. Do not narrate routine reads, searches, obvious next steps, or minor confirmations. Do not begin responses with conversational interjections or meta commentary. Before substantial work, send a short update describing your first step. Before editing files, send an update describing the edit.\r\n\r\nMatch the final answer to the complexity of the task. Structure it if necessary, ordering sections from general to specific to supporting. If the task is simple, answer with a one-liner. If the user asks for a code explanation, include code references. For simple tasks, just state the outcome without heavy formatting. For large or complex changes, lead with the solution, then explain what you did and why. For casual chat, just chat. If something could not be done (tests, builds, and so on), say so. Suggest next steps only when they are natural and useful; if you list options, use numbered items.`\r\n\r\nexport const KIMI_TEXT = `Your primary goal is to help users with software engineering tasks by taking action: use the tools available to you to make real changes on the user's system. You should also answer questions when asked.\r\n\r\n# Prompt and Tool Use\r\n\r\nThe user's messages may contain questions and/or task descriptions. Read them, understand them, and do what the user requested. For simple questions or greetings that do not involve any information in the working directory or on the internet, reply directly. For anything else, default to taking action with tools. When the request could be interpreted as either a question to answer or a task to complete, treat it as a task.\r\n\r\nWhen handling the user's request, if it involves creating, modifying, or running code or files, you MUST use the appropriate tools to make actual changes; do not just describe the solution in text. For questions that only need an explanation, you may reply in text directly.\r\n\r\nIf a subagent tool is available, you can use it to delegate a focused subtask to a subagent instance. When delegating, provide a complete prompt with all necessary context because a newly created subagent does not automatically see your context.\r\n\r\nYou can output any number of tool calls in a single response. If you anticipate making multiple non-interfering tool calls, make them in parallel to significantly improve efficiency. The results of the tool calls will be returned to you; determine your next action based on the results.\r\n\r\nTool results and user messages may include <system-reminder> tags. These are authoritative system directives that you MUST follow. They may override or constrain your normal behavior, and they bear no direct relation to the specific tool results or user messages in which they appear.\r\n\r\nWhen responding to the user, you MUST use the same language as the user, unless explicitly instructed to do otherwise.\r\n\r\n# General Guidelines for Coding\r\n\r\nWhen building something from scratch, you should:\r\n- Understand the user's requirements.\r\n- Ask the user for clarification if there is anything unclear.\r\n- Design the architecture and make a plan for the implementation.\r\n- Write the code in a modular and maintainable way.\r\n\r\nAlways use tools to implement your code changes: use editing tools to create or modify source files. Code that only appears in your text response is NOT saved to the file system and will not take effect. Use shell to run and test your code after writing it. Iterate: if tests fail, read the error, fix the code, and re-test.\r\n\r\nWhen working on an existing codebase, you should:\r\n- Understand the codebase by reading it with tools before making changes. Identify the ultimate goal and the most important criteria to achieve it.\r\n- For a bug fix, check error logs or failed tests, scan the codebase to find the root cause, and figure out a fix. If the user mentioned failed tests, make sure they pass after the changes.\r\n- For a feature, design the architecture and write the code with minimal intrusion into existing code. Add new tests if the project already has tests.\r\n- For a refactor, update all call sites if the interface changes. DO NOT change existing logic, especially in tests; focus only on fixing errors caused by the interface changes.\r\n- Make MINIMAL changes to achieve the goal. This is very important to your performance.\r\n- Follow the coding style of existing code in the project.\r\n\r\nDO NOT run git commit, git push, git reset, git rebase, or any other git mutations unless explicitly asked to do so. Ask for confirmation each time you need to do git mutations, even if the user has confirmed in earlier conversations.\r\n\r\n# General Guidelines for Research and Data Processing\r\n\r\nSearch on the Internet if possible, with carefully-designed search queries to improve efficiency and accuracy. Use proper tools or shell commands to process or generate files, ensuring that third-party packages are installed in a virtual or isolated environment if needed. Once you generate or edit any files, read them again before proceeding to ensure the content is as expected. Avoid installing or deleting anything outside of the current working directory; if you have to, ask the user for confirmation.\r\n\r\n# Working Environment\r\n\r\nThe operating environment is not in a sandbox. Any actions you do will immediately affect the user's system, so you MUST be extremely cautious. Unless explicitly instructed to do so, never access (read, write, or execute) files outside of the working directory. Use absolute paths for file operations.\r\n\r\n# Project Information\r\n\r\nMarkdown files named AGENTS.md usually contain the background, structure, coding styles, user preferences, and other relevant information about the project. You should read the project's AGENTS.md and README files to understand its conventions and preferences. If they are empty or insufficient, check README files or AGENTS.md files in subdirectories for more information.\r\n\r\n# Ultimate Reminders\r\n\r\nAt any time, you should be HELPFUL, CONCISE, and ACCURATE. Be thorough in your actions: test what you build and verify what you change, not in your explanations.\r\n- Never diverge from the requirements and goals of the task you work on. Stay on track.\r\n- Never give the user more than what they want.\r\n- Try your best to avoid hallucination. Do fact checking before providing any factual information.\r\n- Think about the best approach, then take action decisively.\r\n- Do not give up too early.\r\n- ALWAYS keep it stupidly simple. Do not overcomplicate things.\r\n- When the task requires creating or modifying files, always use tools to do so. Never treat displaying code in your response as a substitute for actually writing it to the file system.`\r\n\r\n/** DeepSeek 官方建议蒸馏(仅追加,不覆盖 base)。 */\r\nexport const DEEPSEEK_APPEND = `Notes for DeepSeek models:\r\n- Tool calls follow the OpenAI function-calling style; pass arguments strictly according to each tool's JSON schema.\r\n- Reasoning models (e.g. deepseek-reasoner) emit their reasoning before the final answer; do not ask them to skip the thinking process.`\r\n\r\n/** 智谱官方建议蒸馏(仅追加,不覆盖 base)。 */\r\nexport const GLM_APPEND = `Notes for GLM models:\r\n- Tool calls follow the OpenAI function-calling style; pass arguments strictly according to each tool's JSON schema.\r\n- For thinking-enabled GLM models, the reasoning_content of each message must be passed back verbatim on the next request; never drop or rewrite it.\r\n- With interleaved thinking, keep the reasoning context across tool-call rounds.`\r\n\r\n/** 默认语义层(固定层栈的唯一可编辑层):persona。\r\n * 结构固定——UI 与服务端均不允许增删层、改名、改序,仅文本可编辑。\r\n * persona 注册为普通 prompt-stack:persona(order 10),排在内置模型层\r\n * prompt-stack:base(order 0)之后;默认空串:dsh「空段不渲染」,未填写时行为零变化。\r\n * persona 是唯一可编辑存储层;base 为内置模型层(保留层名,不进存储),见 index.ts。 */\r\nexport const DEFAULT_LAYERS: LayerConfig[] = [\r\n { name: 'persona', order: 10, text: '' },\r\n]\r\n\r\n/** 默认模型规则(顺序即同分仲裁序,勿调整)。 */\r\nexport const DEFAULT_RULES: Rule[] = [\r\n { match: { modelPattern: 'claude*' }, overrides: { base: ANTHROPIC_TEXT } },\r\n { match: { modelPattern: 'gemini-*' }, overrides: { base: GEMINI_TEXT } },\r\n { match: { modelPattern: 'gpt-4*' }, overrides: { base: BEAST_TEXT } },\r\n { match: { modelPattern: 'o1*' }, overrides: { base: BEAST_TEXT } },\r\n { match: { modelPattern: 'o3*' }, overrides: { base: BEAST_TEXT } },\r\n { match: { modelPattern: 'gpt*codex*' }, overrides: { base: CODEX_TEXT } },\r\n { match: { modelPattern: 'gpt*' }, overrides: { base: GPT_TEXT } },\r\n { match: { modelPattern: 'kimi*' }, overrides: { base: KIMI_TEXT } },\r\n // kimi 官方模型 id 不带 kimi 前缀(k2、k3-256k 等),且常挂在自定义 provider 名下。\r\n { match: { modelPattern: 'k2*' }, overrides: { base: KIMI_TEXT } },\r\n { match: { modelPattern: 'k3*' }, overrides: { base: KIMI_TEXT } },\r\n { match: { provider: 'moonshotai' }, overrides: { base: KIMI_TEXT } },\r\n { match: { provider: 'moonshotai-cn' }, overrides: { base: KIMI_TEXT } },\r\n { match: { provider: 'kimi-for-coding' }, overrides: { base: KIMI_TEXT } },\r\n { match: { modelPattern: 'deepseek*' }, append: DEEPSEEK_APPEND },\r\n { match: { modelPattern: 'glm-*' }, append: GLM_APPEND },\r\n]\r\n","/** 模型规则匹配:glob 编译、AND 打分、最高分选择。 */\r\nimport type { Rule, RuleMatch } from './types.ts'\r\n\r\n/** 正则元字符(`*` 与 `?` 除外——它们是 glob 通配符,之后单独展开)。 */\r\nconst REGEXP_META = /[.+^${}()|[\\]\\\\]/g\r\n\r\n/**\r\n * 把 glob(`*` = 任意串,`?` = 单字符)编译为锚定全串的正则。\r\n * @param pattern - 非空 glob;空或全空白抛错(激活期响亮报错的调用点在 apply)。\r\n * @returns 锚定全串的正则。\r\n */\r\nexport function globToRegExp(pattern: string): RegExp {\r\n if (pattern.trim() === '') {\r\n throw new Error('prompt-stack: modelPattern must be a non-empty glob')\r\n }\r\n const source = pattern\r\n .replace(REGEXP_META, '\\\\$&')\r\n .replaceAll('*', '.*')\r\n .replaceAll('?', '.')\r\n return new RegExp(`^${source}$`)\r\n}\r\n\r\n/**\r\n * 给一条规则的 match 打分:任一指定字段不匹配则整条不命中(返回 0);\r\n * 命中分值为 model=4 / modelPattern=2 / provider=1 的累加。\r\n * @param match - 规则的匹配条件。\r\n * @param provider - 当前 agent 的 provider(创建期配置),可缺失。\r\n * @param model - 当前 agent 的模型 id,可缺失。\r\n * @returns 命中分值,0 表示不命中。\r\n */\r\nexport function scoreRule(match: RuleMatch, provider: string | undefined, model: string | undefined): number {\r\n let score = 0\r\n if (match.provider !== undefined) {\r\n if (match.provider !== provider) return 0\r\n score += 1\r\n }\r\n if (match.model !== undefined) {\r\n if (match.model !== model) return 0\r\n score += 4\r\n }\r\n if (match.modelPattern !== undefined) {\r\n if (model === undefined || !globToRegExp(match.modelPattern).test(model)) return 0\r\n score += 2\r\n }\r\n return score\r\n}\r\n\r\n/**\r\n * 选出唯一命中规则:最高分者,同分取配置序靠前者。\r\n * @param rules - 配置中的规则数组(顺序即优先级仲裁序)。\r\n * @param provider - 当前 agent 的 provider,可缺失。\r\n * @param model - 当前 agent 的模型 id,可缺失。\r\n * @returns 命中规则;无命中返回 undefined。\r\n */\r\nexport function selectRule(rules: readonly Rule[], provider: string | undefined, model: string | undefined): Rule | undefined {\r\n let best: Rule | undefined\r\n let bestScore = 0\r\n for (const rule of rules) {\r\n const score = scoreRule(rule.match, provider, model)\r\n if (score > bestScore) {\r\n best = rule\r\n bestScore = score\r\n }\r\n }\r\n return best\r\n}\r\n","/** prompt 模块:内置模型层(按模型规则整体覆盖)+ persona 可编辑层 + model-notes 自动层。 */\r\nimport type { Context } from '@deepseek-ai/cordis'\r\n// type-only 导入激活声明合并:Context.systemPrompt 与 AssembleContext.agent。\r\nimport type { Agent } from '@deepseek-ai/dsh-agent'\r\nimport type { AssembleContext } from '@deepseek-ai/dsh-system-prompt'\r\nimport { BASE_TEXT } from './defaults.ts'\r\nimport { globToRegExp, selectRule } from './match.ts'\r\nimport type { Config as ConfigT, LayerConfig, Rule } from './types.ts'\r\n\r\nexport type { Config, LayerConfig, Rule, RuleMatch } from './types.ts'\r\n\r\n/** 固定追加层的层名(保留,用户层不得使用)。 */\r\nexport const MODEL_NOTES_LAYER = 'model-notes'\r\n\r\n/** 内置模型层名(保留):固定注册 prompt-stack:base 段、不进存储,仍是 rules overrides 的合法目标。 */\r\nexport const BASE_LAYER = 'base'\r\n\r\nconst BASE_SECTION = `prompt-stack:${BASE_LAYER}`\r\n\r\n/** 原生身份段名与原生文本(与 dsh system-prompt 宿主一致;覆盖判定的基准值)。 */\r\nconst IDENTITY_SECTION = 'harness:identity'\r\nconst NATIVE_IDENTITY_TEXT = 'You are an AI agent powered by DeepSeek Harness.'\r\n\r\n/** 运行时层视图:setupPrompt 只消费 get/getIdentity + subscribe,不关心存储细节(测试可注入假实现)。 */\r\nexport interface LayerView {\r\n get(): LayerConfig[]\r\n /** identity 段覆盖文本(空串 = 原生)。 */\r\n getIdentity(): string\r\n subscribe(listener: () => void): () => void\r\n}\r\n\r\n/** 层列表语义校验:空、层名重复、保留层名(base/model-notes)。 */\r\nexport function validateLayers(layers: LayerConfig[]): void {\r\n if (layers.length === 0) {\r\n throw new Error('prompt-stack: config.layers must define at least one layer')\r\n }\r\n const names = new Set<string>()\r\n for (const layer of layers) {\r\n if (layer.name === MODEL_NOTES_LAYER || layer.name === BASE_LAYER) {\r\n throw new Error(`prompt-stack: layer name \"${layer.name}\" is reserved`)\r\n }\r\n if (names.has(layer.name)) {\r\n throw new Error(`prompt-stack: duplicate layer name \"${layer.name}\"`)\r\n }\r\n names.add(layer.name)\r\n }\r\n}\r\n\r\n/**\r\n * 激活期校验(dsh「误配置响亮失败」惯例):空 layers、层名重复、保留层名、\r\n * overrides 引用未知层(内置 base 与 model-notes 之外的存储层名)、空 match、非法 glob 全部抛错。\r\n */\r\nexport function validateConfig(config: ConfigT): void {\r\n validateLayers(config.layers)\r\n const names = new Set([BASE_LAYER, ...config.layers.map(layer => layer.name)])\r\n for (const [index, rule] of config.rules.entries()) {\r\n const { provider, model, modelPattern } = rule.match\r\n if (provider === undefined && model === undefined && modelPattern === undefined) {\r\n throw new Error(`prompt-stack: rules[${index}].match must set at least one of provider, model, modelPattern`)\r\n }\r\n if (modelPattern !== undefined) globToRegExp(modelPattern)\r\n for (const key of Object.keys(rule.overrides ?? {})) {\r\n if (!names.has(key)) {\r\n throw new Error(`prompt-stack: rules[${index}].overrides references unknown layer \"${key}\"`)\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * 固定注册 prompt-stack:base(模型层,order 0)+ 每个存储层一个段 + model-notes。\r\n * 文本在每次组装时按当前 agent 的 provider/model 选唯一命中规则(最高分、同分取配置序靠前),\r\n * 模型层用 overrides.base 整体替换内置 BASE_TEXT,存储层用 overrides 替换该层文本。\r\n * 裸组装(无 agent)静默用默认文本。deployment:persona 槽位还原生,本模块不触碰。\r\n *\r\n * 运行时选模型与首条消息钉住语义不变(见 waterfall 注释)。\r\n */\r\nexport function setupPrompt(ctx: Context, config: { source: LayerView; rules: Rule[] }): void {\r\n const { source, rules } = config\r\n const hitRule = (context: AssembleContext): Rule | undefined =>\r\n selectRule(rules, context.agent?.options?.provider, context.agent?.options?.model)\r\n // 子 Agent 隔离:模型层/persona 不泄漏进子 Agent 组装;model-notes 是模型层\r\n // (模型的通用使用说明),主子共用、按子的生效模型命中规则。\r\n const isSubagent = (context: AssembleContext): boolean =>\r\n context.agent?.session?.header?.origin === 'subagent'\r\n\r\n // 层文本可经 UI 修改:registerSections 先 dispose 上一轮再按当前层重注册,\r\n // source 变更时经 subscribe 触发。base 与 model-notes 恒注册,不随层集变化。\r\n let disposers: Array<() => void> = []\r\n const registerSections = (): void => {\r\n for (const dispose of disposers) dispose()\r\n disposers = []\r\n const layers = source.get()\r\n validateLayers(layers)\r\n const notesOrder = Math.max(0, ...layers.map(layer => layer.order)) + 1\r\n disposers.push(ctx.systemPrompt.section({\r\n name: BASE_SECTION,\r\n order: 0,\r\n text: (context) =>\r\n isSubagent(context) ? '' : (hitRule(context)?.overrides?.[BASE_LAYER] ?? BASE_TEXT),\r\n }))\r\n for (const layer of layers) {\r\n disposers.push(ctx.systemPrompt.section({\r\n name: `prompt-stack:${layer.name}`,\r\n order: layer.order,\r\n text: (context) =>\r\n isSubagent(context) ? '' : (hitRule(context)?.overrides?.[layer.name] ?? layer.text),\r\n }))\r\n }\r\n disposers.push(ctx.systemPrompt.section({\r\n name: `prompt-stack:${MODEL_NOTES_LAYER}`,\r\n order: notesOrder,\r\n text: (context) => hitRule(context)?.append ?? '',\r\n }))\r\n }\r\n registerSections()\r\n ctx.effect(() => source.subscribe(registerSections))\r\n\r\n const notesSection = `prompt-stack:${MODEL_NOTES_LAYER}`\r\n // 首条消息钉住:每个会话的首次组装解析出的 provider/model 缓存起来,会话中途\r\n // 切模型不再改写系统提示词(对话的行为契约保持稳定)。键带 session id:\r\n // clear/新会话(id 变化)自动重新解析。HMR 重挂载换新闭包,缓存随之重置。\r\n const pinned = new WeakMap<Agent, { sessionId: unknown; provider: string | undefined; model: string | undefined }>()\r\n ctx.on('system-prompt/assemble', async (_assembly, context, next) => {\r\n const assembled = await next()\r\n let provider = assembled.variables.provider ?? context.agent?.options?.provider\r\n let model = assembled.variables.model ?? context.agent?.options?.model\r\n const agent = context.agent\r\n if (agent !== undefined) {\r\n const cached = pinned.get(agent)\r\n if (cached !== undefined && cached.sessionId === agent.session.id) {\r\n provider = cached.provider\r\n model = cached.model\r\n } else if (provider !== undefined || model !== undefined) {\r\n pinned.set(agent, { sessionId: agent.session.id, provider, model })\r\n }\r\n }\r\n const rule = selectRule(rules, provider, model)\r\n const layers = source.get()\r\n // 本插件全局注册各段在本次组装的产出(不含钉住改写)。scoped 同名段(bot 角色\r\n // persona 等)经 dsh 原生 shadow 机制已覆盖全局段,其文本 ≠ 本插件产出,\r\n // 据此识别并跳过、不介入 shadow(spec §3「对主 Agent persona 层 waterfall 不介入」)。\r\n const ownSection = (section: { name: string }): string | undefined => {\r\n if (section.name === BASE_SECTION) {\r\n return isSubagent(context) ? '' : (hitRule(context)?.overrides?.[BASE_LAYER] ?? BASE_TEXT)\r\n }\r\n const layer = layers.find(l => section.name === `prompt-stack:${l.name}`)\r\n if (layer === undefined) return undefined\r\n return isSubagent(context) ? '' : (hitRule(context)?.overrides?.[layer.name] ?? layer.text)\r\n }\r\n const sections = assembled.sections.map((section) => {\r\n // identity 覆盖:非空覆盖文本整份替换原生身份句(空 = 还原原生;子 Agent 隔离;\r\n // 段文本 ≠ 原生常量即 scoped shadow,不介入——同下方 ownSection 守卫语义)。\r\n if (section.name === IDENTITY_SECTION) {\r\n const override = source.getIdentity()\r\n if (override === '' || isSubagent(context) || section.text !== NATIVE_IDENTITY_TEXT) return section\r\n return { ...section, text: override }\r\n }\r\n if (section.name === notesSection) {\r\n return { ...section, text: rule?.append ?? '' }\r\n }\r\n const own = ownSection(section)\r\n if (own === undefined || section.text !== own) return section\r\n if (section.name === BASE_SECTION) {\r\n return { ...section, text: isSubagent(context) ? '' : (rule?.overrides?.[BASE_LAYER] ?? BASE_TEXT) }\r\n }\r\n const layer = layers.find(l => section.name === `prompt-stack:${l.name}`)!\r\n return { ...section, text: isSubagent(context) ? '' : (rule?.overrides?.[layer.name] ?? layer.text) }\r\n })\r\n return { ...assembled, sections }\r\n })\r\n}\r\n","/** 分层提示词层源:内存缓存 + prompt_layers 表回写 + 订阅通知;Config 仅作首启种子。 */\r\nimport type { KvTable } from '@deepseek-ai/dsh-storage-domain'\r\nimport type { LayerConfig } from './types.ts'\r\nimport { validateLayers, type LayerView } from './index.ts'\r\n\r\n/** prompt_layers 表单行的 key 常量。 */\r\nexport const PROMPT_LAYERS_KEY = 'layers'\r\n/** meta 表首启种子一次性标记键。 */\r\nexport const PROMPT_LAYERS_SEEDED_KEY = 'prompt_layers_seeded'\r\n\r\nexport interface PromptLayersRow {\r\n layers: LayerConfig[]\r\n /** identity 段覆盖文本(可选,仅非空时写入;空/缺省 = 原生句)。 */\r\n identity?: string\r\n}\r\n\r\n/** 层源的完整能力:setupPrompt 只消费 get/getIdentity/subscribe(LayerView),存储层消费 set/setIdentity/reset。 */\r\nexport interface LayerSource extends LayerView {\r\n /** 校验 → 写表 → 更新内存 → 通知订阅者。 */\r\n set(layers: LayerConfig[]): Promise<void>\r\n /** 写入 identity 覆盖文本(空串 = 还原原生)→ 更新内存 → 通知订阅者。 */\r\n setIdentity(text: string): Promise<void>\r\n /** 清表 + 清种子标记 → 重写种子 → 通知订阅者。连带清空 identity 覆盖。 */\r\n reset(): Promise<void>\r\n}\r\n\r\nexport interface PromptLayerTables {\r\n promptLayers: KvTable<string, PromptLayersRow>\r\n meta: KvTable<string, { value: string }>\r\n}\r\n\r\n/** 组装存储行:identity 仅非空时落字段(空串 = 还原原生,不留残字段)。 */\r\nfunction row(layers: LayerConfig[], identity: string): PromptLayersRow {\r\n return identity === '' ? { layers } : { layers, identity }\r\n}\r\n\r\n/** 固定结构校验:name+order 多重集合必须等于种子(仅 text 可变)。 */\r\nexport function validateFixedLayers(layers: LayerConfig[], seedLayers: LayerConfig[]): void {\r\n const key = (layer: LayerConfig): string => `${layer.name}@${String(layer.order)}`\r\n const seed = seedLayers.map(key).sort()\r\n const actual = layers.map(key).sort()\r\n if (actual.length !== seed.length || actual.some((k, i) => k !== seed[i])) {\r\n throw new Error(`prompt-stack: layer structure is fixed (${seedLayers.map(l => l.name).join(', ')}); only layer text is editable`)\r\n }\r\n}\r\n\r\n/** 按种子结构 reconcile 已存储层:同名层保留已存文本(order 以种子为准)、补缺失、丢多余。 */\r\nexport function reconcileLayers(stored: LayerConfig[], seedLayers: LayerConfig[]): LayerConfig[] {\r\n return seedLayers.map(seed => ({\r\n ...seed,\r\n text: stored.find(layer => layer.name === seed.name)?.text ?? seed.text,\r\n }))\r\n}\r\n\r\n/**\r\n * 打开层源。域由 apply 统一 open(storage-domain 同名单开),本函数只消费表句柄。\r\n * 首启(表无数据)种入 Config 种子并置标记;此后读存储并按种子结构 reconcile\r\n * (层栈固定化迁移:保留已编辑文本、补新层、丢多余层)。\r\n */\r\nexport async function openLayerSource(tables: PromptLayerTables, seedLayers: LayerConfig[]): Promise<LayerSource> {\r\n const { promptLayers, meta } = tables\r\n validateLayers(seedLayers)\r\n let cache: LayerConfig[]\r\n let identity: string\r\n const existing = promptLayers.get(PROMPT_LAYERS_KEY)\r\n if (existing !== undefined) {\r\n // 不再 validateLayers(existing.layers):旧存储可能含已退役的层名(如 base),\r\n // reconcile 负责对齐种子结构,校验只针对 reconcile 后的结果(恒合法,防御性保留)。\r\n cache = reconcileLayers(existing.layers, seedLayers)\r\n validateLayers(cache)\r\n identity = existing.identity ?? ''\r\n await promptLayers.put(PROMPT_LAYERS_KEY, row(cache, identity))\r\n } else {\r\n cache = seedLayers\r\n identity = ''\r\n await promptLayers.put(PROMPT_LAYERS_KEY, { layers: cache })\r\n }\r\n if (meta.get(PROMPT_LAYERS_SEEDED_KEY) === undefined) {\r\n await meta.put(PROMPT_LAYERS_SEEDED_KEY, { value: '1' })\r\n }\r\n\r\n const listeners = new Set<() => void>()\r\n const notify = (): void => { for (const listener of [...listeners]) listener() }\r\n\r\n return {\r\n get: () => cache,\r\n getIdentity: () => identity,\r\n async set(layers: LayerConfig[]): Promise<void> {\r\n validateLayers(layers)\r\n validateFixedLayers(layers, seedLayers)\r\n await promptLayers.put(PROMPT_LAYERS_KEY, row(layers, identity))\r\n cache = layers\r\n notify()\r\n },\r\n async setIdentity(text: string): Promise<void> {\r\n await promptLayers.put(PROMPT_LAYERS_KEY, row(cache, text))\r\n identity = text\r\n notify()\r\n },\r\n async reset(): Promise<void> {\r\n await promptLayers.delete(PROMPT_LAYERS_KEY)\r\n await meta.delete(PROMPT_LAYERS_SEEDED_KEY)\r\n await promptLayers.put(PROMPT_LAYERS_KEY, { layers: seedLayers })\r\n await meta.put(PROMPT_LAYERS_SEEDED_KEY, { value: '1' })\r\n cache = seedLayers\r\n identity = ''\r\n notify()\r\n },\r\n subscribe(listener: () => void): () => void {\r\n listeners.add(listener)\r\n return () => { listeners.delete(listener) }\r\n },\r\n }\r\n}\r\n","/** shared webServer 助手:可选服务模式下注册路由(headless/CLI 无 webServer 时惰性、不注册、不抛错)。 */\r\nimport type { Context } from '@deepseek-ai/cordis'\r\n\r\nexport function registerOptionalRoutes(\r\n ctx: Context,\r\n register: (webCtx: Context) => () => void,\r\n): void {\r\n // 经 ctx.inject 子 fiber 等待 webServer 挂载后再注册:子 fiber 未激活时惰性、\r\n // 随父 fiber 卸载而清理;webServer 永不出现时任何分支都不注册。注册走\r\n // ctx.effect 接线 disposer(\"Registrations are effects\"),HMR 重挂不会因\r\n // 重复 exact 路径抛错。\r\n ctx.inject(['webServer'], (webCtx) => {\r\n webCtx.effect(() => register(webCtx))\r\n })\r\n}\r\n","import type { IncomingMessage, ServerResponse } from 'node:http'\r\n\r\nexport const MAX_BODY_BYTES = 64 * 1024\r\n\r\nexport function json(res: ServerResponse, code: number, body: unknown): void {\r\n res.writeHead(code, { 'content-type': 'application/json' }).end(JSON.stringify(body))\r\n}\r\n\r\n/** 读 JSON body;超限 413 / 非法 JSON 400(已写响应时返回 undefined)。 */\r\nexport async function readJsonBody(req: IncomingMessage, res: ServerResponse): Promise<unknown | undefined> {\r\n const chunks: Buffer[] = []\r\n let received = 0\r\n for await (const chunk of req) {\r\n const buffer = chunk as Buffer\r\n received += buffer.byteLength\r\n if (received > MAX_BODY_BYTES) {\r\n json(res, 413, { error: 'body too large' })\r\n req.destroy()\r\n return undefined\r\n }\r\n chunks.push(buffer)\r\n }\r\n try {\r\n return JSON.parse(Buffer.concat(chunks).toString('utf8'))\r\n } catch {\r\n json(res, 400, { error: 'invalid JSON body' })\r\n return undefined\r\n }\r\n}\r\n","/** 分层提示词 RPC 端点组:读(layers+rules+seed+native 探测)、写(PUT 全量替换)、reset。 */\r\nimport type { IncomingMessage, ServerResponse } from 'node:http'\r\nimport type { Context } from '@deepseek-ai/cordis'\r\nimport { z } from 'zod'\r\nimport { registerOptionalRoutes } from '../shared/webserver.ts'\r\nimport { json, readJsonBody } from '../shared/http.ts'\r\nimport { LayerConfigSchema } from '../agents/store.ts'\r\nimport { BASE_TEXT } from './defaults.ts'\r\nimport { validateLayers } from './index.ts'\r\nimport { validateFixedLayers, type LayerSource } from './layer-source.ts'\r\nimport type { LayerConfig, Rule } from './types.ts'\r\n\r\n/** 裸组装探测结果:原生 sections / 动态 contexts 的名称与当前文本(只读展示用)。 */\r\nexport interface NativeProbe {\r\n sections: Array<{ name: string; text: string }>\r\n contexts: Array<{ name: string; text: string }>\r\n}\r\n\r\nexport interface PromptLayersApiDeps {\r\n source: LayerSource\r\n rules: Rule[]\r\n seedLayers: LayerConfig[]\r\n /** 裸 assemble 探测(apply 闭包注入);失败降级为空列表,不阻塞主数据。 */\r\n probe: () => Promise<NativeProbe>\r\n}\r\n\r\nconst LayersBodySchema = z.object({ layers: z.array(LayerConfigSchema), identityOverride: z.string().optional() })\r\n\r\nexport function createPromptLayersApiHandler(deps: PromptLayersApiDeps): (req: IncomingMessage, res: ServerResponse) => Promise<void> {\r\n return async (req, res) => {\r\n const url = new URL(req.url ?? '/', 'http://127.0.0.1')\r\n const sub = url.pathname.replace(/^\\/dsh-agent-toolkit\\/api\\/prompt-layers/, '') || '/'\r\n const method = req.method ?? 'GET'\r\n\r\n if (sub === '/' && method === 'GET') {\r\n let native: NativeProbe = { sections: [], contexts: [] }\r\n try {\r\n native = await deps.probe()\r\n } catch { /* 探测失败降级为空,layers/rules/seedLayers 主数据照常返回 */ }\r\n json(res, 200, { layers: deps.source.get(), rules: deps.rules, seedLayers: deps.seedLayers, native, modelFallbackText: BASE_TEXT, identityOverride: deps.source.getIdentity() })\r\n return\r\n }\r\n\r\n if (sub === '/' && method === 'PUT') {\r\n const body = await readJsonBody(req, res)\r\n if (body === undefined) return\r\n const parsed = LayersBodySchema.safeParse(body)\r\n if (!parsed.success) {\r\n json(res, 400, { error: parsed.error.issues[0]?.message ?? 'invalid layers body' })\r\n return\r\n }\r\n try {\r\n validateLayers(parsed.data.layers)\r\n validateFixedLayers(parsed.data.layers, deps.seedLayers)\r\n } catch (error) {\r\n json(res, 400, { error: error instanceof Error ? error.message : String(error) })\r\n return\r\n }\r\n try {\r\n await deps.source.set(parsed.data.layers)\r\n if (parsed.data.identityOverride !== undefined) {\r\n await deps.source.setIdentity(parsed.data.identityOverride)\r\n }\r\n } catch (error) {\r\n json(res, 500, { error: error instanceof Error ? error.message : String(error) })\r\n return\r\n }\r\n json(res, 200, { ok: true })\r\n return\r\n }\r\n\r\n if (sub === '/reset' && method === 'POST') {\r\n try {\r\n await deps.source.reset()\r\n } catch (error) {\r\n json(res, 500, { error: error instanceof Error ? error.message : String(error) })\r\n return\r\n }\r\n json(res, 200, { ok: true })\r\n return\r\n }\r\n\r\n if (sub === '/reset' || sub === '/') {\r\n json(res, 405, { error: 'method not allowed' })\r\n return\r\n }\r\n json(res, 404, { error: 'not found' })\r\n }\r\n}\r\n\r\n/** 注册 /dsh-agent-toolkit/api/prompt-layers 前缀路由(webServer 可选服务,缺席惰性不注册)。 */\r\nexport function setupPromptLayersApi(ctx: Context, deps: PromptLayersApiDeps): void {\r\n const handler = createPromptLayersApiHandler(deps)\r\n registerOptionalRoutes(ctx, (webCtx) => {\r\n const dispose = webCtx.webServer.register({ kind: 'prefix', path: '/dsh-agent-toolkit/api/prompt-layers', handler })\r\n return () => dispose()\r\n })\r\n}\r\n","/** 委派子 Agent 的 persona 装配:契约段 + 内置模型层(按子的模型改写)+ 角色 persona。 */\r\nimport { BASE_TEXT } from './defaults.ts'\r\nimport { selectRule } from './match.ts'\r\nimport type { Rule } from './types.ts'\r\n\r\nconst SECTION_A = (roleName: string): string => `你是团队中的一名成员(角色:${roleName}),由主 Agent 委派任务。\r\n- 你看不到主对话;任务书包含你完成工作所需的全部上下文。\r\n- 你的最终输出会作为结果完整返回给主 Agent:直接给出结论与必要细节。\r\n- 你不能再次委派他人;任务需要拆分时,自己按顺序完成。`\r\n\r\nconst SECTION_B = `能力使用守则:\r\n- 你可以使用与主 Agent 相同的工具与 MCP 资源,但只在任务必需时调用。\r\n- 动手修改代码前,先阅读项目根目录及涉及目录的 AGENTS.md,并遵循其中约定。\r\n- 产生或修改文件后,运行相关检查(测试、类型检查)验证你的改动。`\r\n\r\n/**\r\n * 子 Agent 提示词 = 契约段 A/B + 模型层文本(命中规则 overrides.base 整份替换内置\r\n * BASE_TEXT)+ 角色 persona(非空时,排在模型层之后)+ 命中规则的 append(model-notes)。\r\n * 全局 persona 层是主 Agent 的人设,不进入子 Agent(子的角色由 role.persona 顶替)。\r\n */\r\nexport function buildAgentPersona(\r\n config: { rules: Rule[] },\r\n role: { name: string; persona?: string },\r\n model?: { provider?: string; model?: string },\r\n): string {\r\n const rule = selectRule(config.rules, model?.provider, model?.model)\r\n const texts = [rule?.overrides?.base ?? BASE_TEXT]\r\n if (role.persona !== undefined && role.persona.trim().length > 0) texts.push(role.persona)\r\n if (rule?.append !== undefined) texts.push(rule.append)\r\n return [SECTION_A(role.name), SECTION_B, ...texts].join('\\n\\n')\r\n}\r\n","/** team_delegate 工具:查角色 → 一次性 spawn 前台委派 → 规范 JSON 返回。 */\r\nimport type { Agent } from '@deepseek-ai/dsh-agent'\r\nimport type { ContentBlock } from '@deepseek-ai/dsh-llm'\r\nimport type { JsonValue } from '@deepseek-ai/dsh-session'\r\nimport { defineTool } from '@deepseek-ai/dsh-tools'\r\nimport type { SubagentResult, SubagentRun, SubagentStartRequest } from '@deepseek-ai/dsh-subagent'\r\nimport type { AgentRecord } from '../agents/store.ts'\r\n\r\n/** createDelegateTool 的外部依赖。 */\r\nexport interface DelegateToolDeps {\r\n /** 当前生效名册(闭包返回同一数组;查找与错误清单均排除 main)。 */\r\n readonly roster: () => readonly AgentRecord[]\r\n /** ctx.subagents 的 provider 名(默认 'spawn')。 */\r\n readonly provider: string\r\n /** 成员 persona 装配(生产为 buildAgentPersona,测试注入假实现)。 */\r\n readonly buildPersona: (role: AgentRecord) => string\r\n /** 委派入口:生产为 ctx.subagents.start.bind(ctx.subagents),测试注入假实现。 */\r\n readonly startRun: (provider: string, request: SubagentStartRequest) => Promise<SubagentRun>\r\n}\r\n\r\n/** 非 completed 的 stopReason 意味着成员未干净完成。 */\r\nfunction stopReasonError(result: SubagentResult): string | undefined {\r\n switch (result.stopReason) {\r\n case 'completed': return undefined\r\n case 'aborted': return '成员运行被取消'\r\n case 'error': return '成员运行失败'\r\n case 'max-tokens': return '成员在结束前触及 token 上限'\r\n case 'refusal': return '成员拒绝了该任务'\r\n default: return `成员运行异常结束(${String(result.stopReason)})`\r\n }\r\n}\r\n\r\n/** 报错时附上成员已产出的部分文本,让截断/取消的真实产出仍回到主 Agent。 */\r\nfunction withPartialText(error: string, output: ContentBlock[]): string {\r\n const text = output\r\n .filter((block): block is Extract<ContentBlock, { type: 'text' }> => block.type === 'text')\r\n .map(block => block.text)\r\n .join('')\r\n return text.length === 0 ? error : `${error}\\n成员中断前的部分产出:\\n${text}`\r\n}\r\n\r\n/** 收集并释放一次前台运行;dispose 失败不掩盖独立的结果失败。 */\r\nasync function settleForegroundRun(run: SubagentRun, roleId: string) {\r\n // 本地 run 的 run.id 契约上即子 session id(dsh-subagent types.ts:249-255)。\r\n const childSessionId = String(run.id)\r\n const [execution] = await Promise.allSettled([\r\n run.result.then((result) => {\r\n const error = stopReasonError(result)\r\n if (error !== undefined) throw new Error(withPartialText(error, result.output))\r\n return {\r\n kind: 'foreground' as const,\r\n role: roleId,\r\n runId: String(run.id),\r\n childSessionId,\r\n output: result.output as unknown as JsonValue[],\r\n }\r\n }),\r\n ])\r\n const [disposal] = await Promise.allSettled([Promise.resolve().then(() => run.dispose())])\r\n if (execution.status === 'rejected') {\r\n if (disposal.status === 'rejected') {\r\n throw new AggregateError([execution.reason, disposal.reason],\r\n `成员运行失败:${String(execution.reason)};dispose 失败:${String(disposal.reason)}`)\r\n }\r\n throw execution.reason\r\n }\r\n if (disposal.status === 'rejected') throw disposal.reason\r\n return execution.value\r\n}\r\n\r\n/**\r\n * 创建 team_delegate 工具。\r\n * @param toolName - 模型可见工具名(Config.toolName,默认 team_delegate)。\r\n * @param deps - 名册、provider、persona 装配与委派入口。\r\n * @returns defineTool 产物,交给 ctx.tools.register。\r\n *\r\n * 工具注册是 standing scope 的单次注册,description 无法内嵌名册;名册对模型的\r\n * 可见性走系统提示团队段(index.ts)。\r\n */\r\nexport function createDelegateTool(toolName: string, deps: DelegateToolDeps) {\r\n const tool = defineTool({\r\n name: toolName,\r\n description:\r\n 'Delegate a self-contained task to a team member (a separate agent with its own persona and '\r\n + 'optional model override). The member does NOT see this conversation — give it a complete, '\r\n + 'standalone prompt. Available members and their descriptions are listed in the team section '\r\n + 'of the system prompt. This call waits for the member and returns its result.',\r\n parameters: {\r\n role: { type: 'string', required: true, description: 'The member to delegate to. Must be one of the listed names.' },\r\n description: { type: 'string', required: true, description: 'A short (3-5 word) description of the delegated task, for display.' },\r\n prompt: { type: 'string', required: true, description: 'The complete, self-contained task for the member. It does not share this conversation\\'s context, so include everything it needs.' },\r\n },\r\n output: {\r\n schema: {\r\n type: 'object',\r\n additionalProperties: false,\r\n properties: {\r\n kind: { type: 'string', required: true, const: 'foreground' },\r\n role: { type: 'string', required: true },\r\n runId: { type: 'string', required: true },\r\n childSessionId: { type: 'string', required: true },\r\n output: { type: 'array', required: true, items: { type: 'json' } },\r\n },\r\n },\r\n render: (_args, value) => [{\r\n type: 'text' as const,\r\n text: (value.output as { type: string; text?: string }[])\r\n .filter(block => block.type === 'text' && typeof block.text === 'string')\r\n .map(block => block.text).join(''),\r\n }],\r\n // 浏览器半委派卡经 tool/result 的持久化 meta 读子会话坐标(回放可重建)。\r\n presentationMeta: (_args, value) => ({\r\n role: value.role as string,\r\n runId: value.runId as string,\r\n childSessionId: value.childSessionId as string,\r\n }),\r\n },\r\n // 成员不改父会话;父方无写操作。与内置 subagent 工具同款。\r\n isConcurrencySafe: () => true,\r\n // generic 兜底(浏览器半缺席/回放旧事件时降级;generic title 在 Web 不渲染,\r\n // 供 headless 与日志使用)。\r\n presentCall: (args) => ({\r\n card: 'generic' as const,\r\n title: `委派 · ${args.role}: ${args.description}`,\r\n rawInput: args.prompt,\r\n }),\r\n presentResult: (_args, result) => (result.isError ? undefined : { card: 'generic' as const }),\r\n async execute(args, exec) {\r\n const parent: Agent | undefined = exec.agent\r\n if (!parent) throw new Error('team_delegate 需要调用方 agent(exec.agent 为空)')\r\n // 主 Agent 不可委派:查找与错误清单都排除 main。\r\n const roster = deps.roster().filter(r => r.id !== 'main')\r\n const role = roster.find(r => r.id === args.role)\r\n if (!role) {\r\n throw new Error(`未知角色 \"${args.role}\"。可用角色:${roster.map(r => r.id).join(', ')}`)\r\n }\r\n const persona = deps.buildPersona(role)\r\n const request: SubagentStartRequest = {\r\n label: `role:${role.id}: ${args.description}`,\r\n prompt: [{ type: 'text', text: args.prompt } as ContentBlock],\r\n parent,\r\n persona,\r\n maxDepth: 1, // 禁止套娃:成员(深度 1)再委派时 childDepth 2 > 1,provider 响亮拒绝\r\n signal: exec.signal,\r\n ...role.model !== undefined\r\n ? { agentOptions: { provider: role.model.provider, model: role.model.model } }\r\n : {},\r\n ...role.tools !== undefined\r\n ? { toolFilter: { allow: [...role.tools.allow] } }\r\n : {},\r\n } as SubagentStartRequest\r\n const run = await deps.startRun(deps.provider, request)\r\n return settleForegroundRun(run, role.id)\r\n },\r\n })\r\n return tool\r\n}\r\n","/** delegate 模块:注册表驱动的 team_delegate 委派工具 + 函数式团队提示段。 */\r\nimport type { Context } from '@deepseek-ai/cordis'\r\nimport type { SubagentProvider } from '@deepseek-ai/dsh-subagent'\r\nimport type { AgentRecord } from '../agents/store.ts'\r\nimport type { AgentRegistry } from '../agents/registry.ts'\r\nimport { buildAgentPersona } from '../prompt/persona.ts'\r\nimport type { Rule } from '../prompt/types.ts'\r\nimport { createDelegateTool } from './tool.ts'\r\n\r\nexport type { DelegateToolDeps } from './tool.ts'\r\nexport { createDelegateTool } from './tool.ts'\r\n\r\n/** 团队名册段在 prompt 中的位置:紧随内置 subagent 段(116.5)之后。 */\r\nconst TEAM_SECTION_ORDER = 116.6\r\n\r\nexport interface DelegateConfig {\r\n /** ctx.subagents provider 名(默认 'spawn')。 */\r\n provider: string\r\n /** 模型可见工具名(默认 'team_delegate')。注意:浏览器半委派卡按 'team_delegate' key 注册,改名后卡片不生效(落 generic 兜底)。 */\r\n toolName: string\r\n /** 按模型规则(Task 7 产物)。 */\r\n rules: Rule[]\r\n}\r\n\r\n/**\r\n * 挂载 team_delegate 工具与函数式团队提示段。\r\n * provider 能力守卫与生命周期镜像同归档 tool-subagent:persona/depthLimit 缺失响亮报错,\r\n * 工具随 provider 在场与否挂载/摘除。名册来自注册表(main 排除),工具与提示段都经\r\n * 闭包读取 registry,UI 改角色后新会话即生效。\r\n */\r\nexport function setupDelegate(ctx: Context, config: DelegateConfig, registry: AgentRegistry): void {\r\n const { provider, toolName } = config\r\n let disposeTool: (() => void) | undefined\r\n let providerFailed = false\r\n const mountTool = (p: SubagentProvider): void => {\r\n const missing: string[] = []\r\n if (!p.capabilities.persona) missing.push('persona')\r\n if (!p.capabilities.depthLimit) missing.push('depthLimit')\r\n if (missing.length > 0) {\r\n throw new Error(\r\n `dsh-agent-toolkit: provider \"${p.name}\" 缺少 team_delegate 委派必需能力 ${missing.join('/')}(固定发送 persona 与 maxDepth:1)——请配置具备 persona 与 depthLimit 能力的 provider(如 spawn/fork)`,\r\n )\r\n }\r\n if (disposeTool === undefined) {\r\n disposeTool = ctx.tools.register(createDelegateTool(toolName, {\r\n roster: () => registry.list(),\r\n provider,\r\n buildPersona: (role: AgentRecord) =>\r\n buildAgentPersona({ rules: config.rules }, role, role.model),\r\n startRun: (pr, request) => ctx.subagents.start(pr, request),\r\n }))\r\n }\r\n }\r\n ctx.on('subagent/provider-added', (p) => {\r\n if (p.name !== provider || providerFailed) return\r\n try {\r\n mountTool(p)\r\n } catch (error) {\r\n providerFailed = true\r\n ctx.logger.error(error instanceof Error ? error.message : String(error))\r\n }\r\n })\r\n ctx.on('subagent/provider-removed', (removed) => {\r\n if (removed !== provider) return\r\n providerFailed = false\r\n if (disposeTool !== undefined) {\r\n disposeTool()\r\n disposeTool = undefined\r\n }\r\n })\r\n const present = ctx.subagents.getProvider(provider)\r\n if (present !== undefined) {\r\n mountTool(present)\r\n } else {\r\n ctx.logger.info(`dsh-agent-toolkit: subagent provider \"${provider}\" 尚未注册;team_delegate 将等它出现时挂载`)\r\n }\r\n ctx.systemPrompt.section({\r\n name: 'plugin:dsh-agent-toolkit:team',\r\n order: TEAM_SECTION_ORDER, // 紧随内置 subagent 段(116.5)之后,同归档 agent-team\r\n text: () => {\r\n const roles = registry.list().filter(r => r.id !== 'main')\r\n const rosterText = roles.map(r => `${r.id}: ${r.description ?? r.name}`).join('\\n')\r\n return `你有一组可委派的成员:用 ${config.toolName} 把自包含的子任务委派给合适的成员,成员结果会作为工具返回值回到本对话。\\n可用成员:\\n${rosterText}`\r\n },\r\n })\r\n}\r\n","/** Agents RPC 端点组:注册表 CRUD + providers/models 级联 + 工具名列表。核心恒启用(不随 feishu 门控)。 */\r\nimport type { IncomingMessage, ServerResponse } from 'node:http'\r\nimport type { Context } from '@deepseek-ai/cordis'\r\nimport { json, readJsonBody } from '../shared/http.ts'\r\nimport { registerOptionalRoutes } from '../shared/webserver.ts'\r\nimport { AgentRecordSchema } from './store.ts'\r\nimport type { AgentRegistry } from './registry.ts'\r\nimport { NATIVE_TOOL_NAMES } from '../channels/basic-tools.ts'\r\n\r\n/** 一个可选的 provider 路由(id = agentOptions.provider 的值)。 */\r\nexport interface ProviderOption { id: string; name: string }\r\n/** 一个可选的模型条目(id = agentOptions.model 的值)。 */\r\nexport interface ModelOption { id: string; name: string }\r\n\r\nexport interface AgentsApiDeps {\r\n registry: AgentRegistry\r\n listTools(): string[]\r\n listProviders(): ProviderOption[]\r\n /** 失败由调用方(路由)兜底为空数组,不抛错。 */\r\n listModels(provider: string): Promise<ModelOption[]>\r\n}\r\n\r\nexport function createAgentsApiHandler(deps: AgentsApiDeps): (req: IncomingMessage, res: ServerResponse) => Promise<void> {\r\n return async (req, res) => {\r\n const url = new URL(req.url ?? '/', 'http://127.0.0.1')\r\n const sub = url.pathname.replace(/^\\/dsh-agent-toolkit\\/api/, '') || '/'\r\n const method = req.method ?? 'GET'\r\n\r\n if (sub === '/agents' && method === 'GET') {\r\n json(res, 200, deps.registry.list())\r\n return\r\n }\r\n\r\n if (sub === '/tools' && method === 'GET') {\r\n // 分组名册:native = BASIC_TOOLS scoped 挂载的原生工具名(常量),global = 顶层注册表全局工具。\r\n json(res, 200, { native: [...NATIVE_TOOL_NAMES], global: deps.listTools() })\r\n return\r\n }\r\n\r\n if (sub === '/providers' && method === 'GET') {\r\n json(res, 200, deps.listProviders())\r\n return\r\n }\r\n\r\n const modelsMatch = /^\\/providers\\/([^/]+)\\/models$/.exec(sub)\r\n if (modelsMatch !== null && method === 'GET') {\r\n // 模型列举可能走网络(adapter 探测),失败静默降级为空数组。\r\n let models: ModelOption[] = []\r\n try {\r\n models = await deps.listModels(decodeURIComponent(modelsMatch[1]))\r\n } catch {\r\n models = []\r\n }\r\n json(res, 200, models)\r\n return\r\n }\r\n\r\n const agentMatch = /^\\/agents\\/([^/]+)$/.exec(sub)\r\n if (agentMatch !== null) {\r\n const id = decodeURIComponent(agentMatch[1])\r\n\r\n if (method === 'PUT') {\r\n const body = await readJsonBody(req, res)\r\n if (body === undefined) return\r\n // builtin 是服务端保留字段:剥离客户端携带值(防经 PUT 自创不可删记录),\r\n // id 以资源路径为准(覆盖 body.id),保证一致性。\r\n const bodyRecord: Record<string, unknown> = { ...(body as Record<string, unknown>) }\r\n delete bodyRecord.builtin\r\n const candidate: Record<string, unknown> = { ...bodyRecord, id }\r\n // 服务端保留字段回填:builtin 由既有记录决定(客户端不携带),否则 registry 的\r\n // \"内置标记不可修改\" 守卫会让所有内置角色/主 Agent 的配置编辑必然 409。\r\n const existing = deps.registry.get(id)\r\n if (existing?.builtin === true) candidate.builtin = true\r\n const parsed = AgentRecordSchema.safeParse(candidate)\r\n if (!parsed.success) {\r\n json(res, 400, { error: parsed.error.issues[0]?.message ?? 'invalid agent record' })\r\n return\r\n }\r\n try {\r\n await deps.registry.upsert(parsed.data)\r\n } catch (error) {\r\n json(res, 409, { error: error instanceof Error ? error.message : String(error) })\r\n return\r\n }\r\n json(res, 200, { ok: true })\r\n return\r\n }\r\n\r\n if (method === 'DELETE') {\r\n if (deps.registry.get(id) === undefined) {\r\n json(res, 404, { error: `agent \"${id}\" 不存在` })\r\n return\r\n }\r\n try {\r\n await deps.registry.remove(id)\r\n } catch (error) {\r\n json(res, 409, { error: error instanceof Error ? error.message : String(error) })\r\n return\r\n }\r\n json(res, 200, { ok: true })\r\n return\r\n }\r\n\r\n json(res, 405, { error: 'method not allowed' })\r\n return\r\n }\r\n\r\n if (['/agents', '/providers', '/tools'].some((p) => sub === p || sub.startsWith(`${p}/`))) {\r\n json(res, 405, { error: 'method not allowed' })\r\n return\r\n }\r\n json(res, 404, { error: 'not found' })\r\n }\r\n}\r\n\r\n/**\r\n * 注册 agents 核心 RPC 路由(恒启用,不随 modules.feishu 门控——Agents 面板总是挂载,\r\n * 这些端点缺失即「加载失败」)。webServer 为可选服务:缺席时经 registerOptionalRoutes\r\n * 惰性不注册。挂载点与 bots 同处 /dsh-agent-toolkit/api 前缀,但按路径空间拆成独立\r\n * prefix/exact 条目(webServer 精确先于最长前缀),互不重叠:\r\n * - prefix /dsh-agent-toolkit/api/agents → /agents 与 /agents/:id\r\n * - prefix /dsh-agent-toolkit/api/providers → /providers 与 /providers/:p/models\r\n * - exact /dsh-agent-toolkit/api/tools\r\n * - prefix /dsh-agent-toolkit/api → 兜底:api 前缀下未被更具体路由(bots/usage)\r\n * 认领的未知路径仍回 404 JSON(与旧统一分发行为字节一致)。\r\n */\r\nexport function setupAgentsApi(ctx: Context, deps: AgentsApiDeps): void {\r\n const handler = createAgentsApiHandler(deps)\r\n registerOptionalRoutes(ctx, (webCtx) => {\r\n const dispose = [\r\n webCtx.webServer.register({ kind: 'prefix', path: '/dsh-agent-toolkit/api/agents', handler }),\r\n webCtx.webServer.register({ kind: 'prefix', path: '/dsh-agent-toolkit/api/providers', handler }),\r\n webCtx.webServer.register({ kind: 'exact', path: '/dsh-agent-toolkit/api/tools', handler }),\r\n webCtx.webServer.register({ kind: 'prefix', path: '/dsh-agent-toolkit/api', handler }),\r\n ]\r\n return () => dispose.forEach((unregister) => unregister())\r\n })\r\n}\r\n","/** agent 创建/恢复的作用域组合:基础工具行 scoped 挂载 → persona/tools 创作期注入。 */\r\nimport type { Context, Plugin } from '@deepseek-ai/cordis'\r\n// type-only 激活 dsh-system-prompt / dsh-tools 对 cordis Context 的声明合并(agentCtx.systemPrompt / agentCtx.tools)。\r\nimport type {} from '@deepseek-ai/dsh-system-prompt'\r\nimport type {} from '@deepseek-ai/dsh-tools'\r\nimport { BASIC_TOOLS } from './basic-tools.ts'\r\nimport type { AgentHooks } from './ports.ts'\r\n\r\n/** 工具行模块加载器(测试注入 fake;生产经动态 import 解析宿主 node_modules 中的插件包)。 */\r\nexport type ToolModuleLoader = (specifier: string) => Promise<Plugin>\r\n\r\n/** bot 会话角色 persona 的 scoped 段名:与全局 persona 层同名,scoped 注册即 shadow 覆盖主 Agent persona。 */\r\nexport const TOOLKIT_PERSONA_SECTION = 'prompt-stack:persona'\r\n\r\n/** 默认加载器:复刻 preset mount 的模块解析——loader 的 unwrapExports 取 `default ?? 命名导出模块`。 */\r\nasync function loadToolModule(specifier: string): Promise<Plugin> {\r\n const mod: unknown = await import(specifier)\r\n return ((mod as { default?: unknown }).default ?? mod) as Plugin\r\n}\r\n\r\n/**\r\n * 组合 agent 作用域:先 scoped 挂载基础工具行(persona/instructions/shell/fs/fs-search,\r\n * 与原生 UI 会话的 standard preset 同源),再叠 bot 的 persona 与 tools 白名单。\r\n * 顺序敏感:restrict 必须在工具行挂载之后,否则白名单命中不到挂载带入的工具名。\r\n */\r\nexport async function setupAgentScope(\r\n agentCtx: Context,\r\n hooks: AgentHooks,\r\n loadTool: ToolModuleLoader = loadToolModule,\r\n): Promise<void> {\r\n for (const tool of BASIC_TOOLS) {\r\n await agentCtx.plugin(await loadTool(tool.id), tool.config)\r\n }\r\n if (hooks.persona !== undefined) {\r\n agentCtx.systemPrompt.section({ name: TOOLKIT_PERSONA_SECTION, order: 10, text: hooks.persona })\r\n }\r\n if (hooks.sections !== undefined) {\r\n for (const section of hooks.sections) {\r\n agentCtx.systemPrompt.section({ name: section.name, order: section.order, text: section.text })\r\n }\r\n }\r\n if (hooks.tools !== undefined) {\r\n agentCtx.tools.restrict({ allow: hooks.tools })\r\n }\r\n}\r\n","/** 飞书 OpenAPI 的结构化端口:reply/channel 只依赖本接口,SDK 类型不外泄。 */\r\nimport type * as lark from '@larksuiteoapi/node-sdk'\r\n\r\nexport interface FeishuApi {\r\n createCard(cardJson: string): Promise<string>\r\n sendCardMessage(chatId: string, cardId: string): Promise<void>\r\n updateCardElement(cardId: string, elementId: string, content: string, sequence: number): Promise<void>\r\n insertElement(cardId: string, elementJson: string, targetElementId: string, sequence: number): Promise<void>\r\n setCardStreaming(cardId: string, streaming: boolean, sequence: number, summary?: string): Promise<void>\r\n replaceCard(cardId: string, cardJson: string, sequence: number): Promise<void>\r\n sendText(chatId: string, text: string): Promise<void>\r\n addReaction(messageId: string, emojiType: string): Promise<string>\r\n removeReaction(messageId: string, reactionId: string): Promise<void>\r\n}\r\n\r\n/** SDK 薄封装:tenant_access_token 由 SDK 自动管理;错误带 code/msg 上下文。 */\r\nexport function createFeishuApi(client: lark.Client): FeishuApi {\r\n return {\r\n async createCard(cardJson) {\r\n const res = await client.cardkit.v1.card.create({ data: { type: 'card_json', data: cardJson } })\r\n const cardId = res.data?.card_id\r\n if (typeof cardId !== 'string' || cardId.length === 0) {\r\n throw new Error(`cardkit 建卡失败:code=${res.code} msg=${res.msg}`)\r\n }\r\n return cardId\r\n },\r\n async sendCardMessage(chatId, cardId) {\r\n await client.im.message.create({\r\n params: { receive_id_type: 'chat_id' },\r\n data: { receive_id: chatId, msg_type: 'interactive', content: JSON.stringify({ type: 'card', data: { card_id: cardId } }) },\r\n })\r\n },\r\n async updateCardElement(cardId, elementId, content, sequence) {\r\n await client.cardkit.v1.cardElement.content({ path: { card_id: cardId, element_id: elementId }, data: { content, sequence } })\r\n },\r\n async insertElement(cardId, elementJson, targetElementId, sequence) {\r\n await client.cardkit.v1.cardElement.create({\r\n path: { card_id: cardId },\r\n data: { type: 'insert_before', target_element_id: targetElementId, elements: `[${elementJson}]`, sequence },\r\n })\r\n },\r\n async setCardStreaming(cardId, streaming, sequence, summary) {\r\n await client.cardkit.v1.card.settings({\r\n path: { card_id: cardId },\r\n data: {\r\n settings: JSON.stringify({\r\n config: {\r\n streaming_mode: streaming,\r\n ...(summary !== undefined ? { summary: { content: summary } } : {}),\r\n },\r\n }),\r\n sequence,\r\n },\r\n })\r\n },\r\n async replaceCard(cardId, cardJson, sequence) {\r\n await client.cardkit.v1.card.update({ path: { card_id: cardId }, data: { card: { type: 'card_json', data: cardJson }, sequence } })\r\n },\r\n async sendText(chatId, text) {\r\n await client.im.message.create({\r\n params: { receive_id_type: 'chat_id' },\r\n data: { receive_id: chatId, msg_type: 'text', content: JSON.stringify({ text }) },\r\n })\r\n },\r\n async addReaction(messageId, emojiType) {\r\n const res = await client.im.messageReaction.create({\r\n path: { message_id: messageId },\r\n data: { reaction_type: { emoji_type: emojiType } },\r\n })\r\n const reactionId = res.data?.reaction_id\r\n if (typeof reactionId !== 'string') throw new Error(`加表情失败:code=${res.code} msg=${res.msg}`)\r\n return reactionId\r\n },\r\n async removeReaction(messageId, reactionId) {\r\n await client.im.messageReaction.delete({ path: { message_id: messageId, reaction_id: reactionId } })\r\n },\r\n }\r\n}\r\n","/** 飞书内的运维文本指令(不走模型)。 */\r\nexport type Directive = 'new' | 'stop' | 'status'\r\n\r\n/** 仅当整条消息就是一个指令时命中;带参数/前后文的按普通消息处理。 */\r\nexport function parseDirective(text: string): Directive | null {\r\n const t = text.trim().toLowerCase()\r\n if (t === '/new') return 'new'\r\n if (t === '/stop') return 'stop'\r\n if (t === '/status') return 'status'\r\n return null\r\n}\r\n\r\n/** 群消息正文中的 @ 占位符(@_user_1 等)剥掉,得到纯净指令文本。 */\r\nexport function stripMentionPlaceholders(text: string): string {\r\n return text.replace(/@_user_\\d+\\s*/g, '').trim()\r\n}\r\n","/** im.message.receive_v1 事件解析:窄化为渠道无关的 ParsedMessage;message_id 去重。 */\r\nimport { stripMentionPlaceholders } from '../directive.ts'\r\n\r\nexport interface ParsedMessage {\r\n messageId: string\r\n chatId: string\r\n chatType: 'p2p' | 'group'\r\n userId: string\r\n text: string\r\n}\r\n\r\ninterface RawEvent {\r\n sender?: { sender_type?: unknown; sender_id?: { open_id?: unknown } }\r\n message?: {\r\n message_id?: unknown\r\n chat_id?: unknown\r\n chat_type?: unknown\r\n message_type?: unknown\r\n content?: unknown\r\n mentions?: readonly { mentioned_type?: unknown }[]\r\n }\r\n}\r\n\r\n/**\r\n * SDK handler 收到的 data 即事件体(README 示例 `data.message` 直接解构);\r\n * 兼容包一层 { event } 的形态。过滤:机器人消息、非文本、群内未 @机器人、空文本。\r\n */\r\nexport function parseMessageEvent(data: unknown): ParsedMessage | null {\r\n const wrapped = data as { event?: RawEvent } & RawEvent\r\n const event: RawEvent = wrapped.event ?? wrapped\r\n if (event.sender?.sender_type !== 'user') return null\r\n const userId = event.sender.sender_id?.open_id\r\n const msg = event.message\r\n if (typeof userId !== 'string' || msg === undefined) return null\r\n if (msg.message_type !== 'text' || typeof msg.content !== 'string') return null\r\n if (typeof msg.message_id !== 'string' || typeof msg.chat_id !== 'string') return null\r\n if (msg.chat_type !== 'p2p' && msg.chat_type !== 'group') return null\r\n if (msg.chat_type === 'group' && !(msg.mentions ?? []).some((m) => m.mentioned_type === 'bot')) return null\r\n\r\n let text: string\r\n try {\r\n const parsed = JSON.parse(msg.content) as { text?: unknown }\r\n if (typeof parsed.text !== 'string') return null\r\n text = stripMentionPlaceholders(parsed.text)\r\n } catch {\r\n return null\r\n }\r\n if (text.length === 0) return null\r\n\r\n return { messageId: msg.message_id, chatId: msg.chat_id, chatType: msg.chat_type, userId, text }\r\n}\r\n\r\n/** message_id 去重(飞书会重推);FIFO 容量淘汰。 */\r\nexport class MessageDedup {\r\n private readonly seen = new Set<string>()\r\n private readonly order: string[] = []\r\n\r\n constructor(private readonly cap = 1000) {}\r\n\r\n /** true = 新消息。 */\r\n check(id: string): boolean {\r\n if (this.seen.has(id)) return false\r\n this.seen.add(id)\r\n this.order.push(id)\r\n if (this.order.length > this.cap) this.seen.delete(this.order.shift()!)\r\n return true\r\n }\r\n}\r\n","/** 飞书卡片纯函数:JSON 2.0 构建、UTF-8 字节切分、段序列流式操作规划(拆卡决策全在这里)。 */\r\nimport type { TurnSegment, TurnStatus } from '../channel.ts'\r\n\r\nexport type { TurnSegment }\r\n\r\nexport const STATUS_ELEMENT_ID = 'status'\r\n\r\n/** create 未返回真实 card_id 前的占位哨兵(executor 赋值;防并发 flush 重复建卡)。 */\r\nexport const PENDING_CARD_ID = '__pending__'\r\n\r\n/** 过程区截尾后的头部省略标记。 */\r\nexport const PROCESS_OMITTED = '…(已省略前文)\\n'\r\n\r\n/** 输出中状态行文案。 */\r\nconst STATUS_STREAMING = '⏳ 输出中…'\r\n\r\n/** 定格状态行文案。 */\r\nconst STATUS_FINAL: Record<TurnStatus, string> = {\r\n done: '✅ 输出完成',\r\n error: '❌ 输出出错',\r\n cancelled: '⏹ 已取消',\r\n}\r\n\r\n/** 新卡固定开销字节数(状态行 + 结构,粗算进预算)。 */\r\nconst CARD_FIXED_BYTES = 64\r\n\r\n/** 单卡组件数安全上限(飞书硬上限 200;面板按 2 计:面板 + 内嵌 markdown)。 */\r\nconst CARD_ELEMENT_LIMIT = 190\r\n\r\n/** 按 UTF-8 字节上限截头(保留头部),不劈开多字节字符与代理对。 */\r\nexport function sliceByBytes(text: string, maxBytes: number): string {\r\n if (Buffer.byteLength(text, 'utf8') <= maxBytes) return text\r\n let lo = 0\r\n let hi = text.length\r\n while (lo < hi) {\r\n const mid = Math.ceil((lo + hi) / 2)\r\n if (Buffer.byteLength(text.slice(0, mid), 'utf8') <= maxBytes) lo = mid\r\n else hi = mid - 1\r\n }\r\n let cut = lo\r\n if (cut > 0) {\r\n const code = text.charCodeAt(cut - 1)\r\n if (code >= 0xd8_00 && code <= 0xdb_ff) cut -= 1 // 高位代理在末尾:整对移除\r\n }\r\n return text.slice(0, cut)\r\n}\r\n\r\n/** 按 UTF-8 字节上限截尾(保留尾部),不劈开多字节字符与代理对;截断时头部加省略标记。 */\r\nexport function sliceTailByBytes(text: string, maxBytes: number): string {\r\n if (Buffer.byteLength(text, 'utf8') <= maxBytes) return text\r\n const budget = maxBytes - Buffer.byteLength(PROCESS_OMITTED, 'utf8')\r\n if (budget <= 0) throw new Error(`processMaxBytes=${maxBytes} 过小,连省略标记都容纳不了`)\r\n let lo = 0\r\n let hi = text.length\r\n while (lo < hi) {\r\n const mid = Math.floor((lo + hi) / 2)\r\n if (Buffer.byteLength(text.slice(mid), 'utf8') <= budget) hi = mid\r\n else lo = mid + 1\r\n }\r\n let cut = lo\r\n if (cut < text.length) {\r\n const code = text.charCodeAt(cut)\r\n if (code >= 0xdc_00 && code <= 0xdf_ff) cut += 1 // 低位代理在开头:整对移除\r\n }\r\n return PROCESS_OMITTED + text.slice(cut)\r\n}\r\n\r\n/** 新卡:仅状态行的流式卡;段后续经插入组件 API 动态加入。 */\r\nexport function buildCardJson(): string {\r\n return JSON.stringify({\r\n schema: '2.0',\r\n config: {\r\n streaming_mode: true,\r\n summary: { content: '生成中…' },\r\n streaming_config: { print_frequency_ms: { default: 70 }, print_step: { default: 1 }, print_strategy: 'fast' },\r\n },\r\n body: { elements: [{ tag: 'markdown', content: STATUS_STREAMING, element_id: STATUS_ELEMENT_ID }] },\r\n })\r\n}\r\n\r\n/** 段元素 JSON(insert op 负载):process = 默认收起折叠面板;text = 纯 markdown。 */\r\nexport function buildSegmentJson(kind: 'text' | 'process', elementId: string, content: string): string {\r\n if (kind === 'process') {\r\n return JSON.stringify({\r\n tag: 'collapsible_panel',\r\n expanded: false,\r\n header: { title: { tag: 'plain_text', content: '思考与工具调用过程' } },\r\n elements: [{ tag: 'markdown', content, element_id: elementId }],\r\n })\r\n }\r\n return JSON.stringify({ tag: 'markdown', content, element_id: elementId })\r\n}\r\n\r\nexport interface StreamState {\r\n /** 当前卡片 id(PENDING_CARD_ID = 创建中);null = 下一张卡待创建。 */\r\n cardId: string | null\r\n /** 当前卡片已消耗的 sequence 计数(create/send 不占)。 */\r\n seq: number\r\n /** 当前卡已提交内容字节数(段内容 + 固定开销合计)。 */\r\n cardBytes: number\r\n /** 当前卡组件数(含状态行;面板按 2 计)。 */\r\n cardElements: number\r\n /** 全局段计数(element_id 生成用,跨卡递增)。 */\r\n segCounter: number\r\n /** 已在历史卡封闭、不再关注的段数(段 0..closedSegCount-1)。 */\r\n closedSegCount: number\r\n /** 当前卡上打开的段(永远是最新的有内容段);base = 元素内容在该段 content 中的 char 起始偏移(process 恒 0)。 */\r\n tail: { segIndex: number; elementId: string; base: number; shownText: string } | undefined\r\n /** text 段跨卡续写基准(char offset into 该段 content)。 */\r\n carry: { segIndex: number; base: number } | undefined\r\n}\r\n\r\nexport const initialStreamState = (): StreamState => ({\r\n cardId: null, seq: 0, cardBytes: 0, cardElements: 0, segCounter: 0,\r\n closedSegCount: 0, tail: undefined, carry: undefined,\r\n})\r\n\r\nexport type CardOp =\r\n | { type: 'create'; cardJson: string }\r\n | { type: 'send' }\r\n | { type: 'insert'; elementJson: string; sequence: number }\r\n | { type: 'update'; elementId: string; content: string; sequence: number }\r\n | { type: 'settings'; streaming: boolean; sequence: number; summary?: string }\r\n\r\n/** 把段序列的新增部分同步到卡片;新段 insert 到状态行之前,尾段增长走元素 update,满卡关流开续卡。 */\r\nexport function planSync(\r\n state: StreamState,\r\n segments: readonly TurnSegment[],\r\n maxBytes: number,\r\n processMaxBytes: number,\r\n): { state: StreamState; ops: CardOp[] } {\r\n const ops: CardOp[] = []\r\n let { cardId, seq, cardBytes, cardElements, segCounter, closedSegCount, tail, carry } = state\r\n\r\n const ensureCard = (): void => {\r\n if (cardId !== null) return\r\n ops.push({ type: 'create', cardJson: buildCardJson() })\r\n ops.push({ type: 'send' })\r\n cardId = PENDING_CARD_ID\r\n seq = 0\r\n cardBytes = CARD_FIXED_BYTES\r\n cardElements = 1\r\n }\r\n\r\n const closeCard = (): void => {\r\n seq += 1\r\n ops.push({ type: 'settings', streaming: false, sequence: seq })\r\n cardId = null\r\n tail = undefined\r\n }\r\n\r\n let i = tail?.segIndex ?? closedSegCount\r\n while (i < segments.length) {\r\n const seg = segments[i]\r\n const content = seg.kind === 'process' ? sliceTailByBytes(seg.content, processMaxBytes) : seg.content\r\n const base = tail !== undefined && tail.segIndex === i\r\n ? tail.base\r\n : carry?.segIndex === i ? carry.base : 0\r\n const elementContent = seg.kind === 'text' ? content.slice(base) : content\r\n\r\n if (tail !== undefined && tail.segIndex === i) {\r\n // 当前卡上的打开段:内容增长走 update\r\n if (elementContent !== tail.shownText) {\r\n const delta = Buffer.byteLength(elementContent, 'utf8') - Buffer.byteLength(tail.shownText, 'utf8')\r\n if (cardBytes + delta <= maxBytes) {\r\n seq += 1\r\n ops.push({ type: 'update', elementId: tail.elementId, content: elementContent, sequence: seq })\r\n cardBytes += delta\r\n tail = { ...tail, shownText: elementContent }\r\n } else if (seg.kind === 'text') {\r\n // 部分更新到满 → 拆卡,剩余经 carry 续写\r\n const piece = sliceByBytes(elementContent, Buffer.byteLength(tail.shownText, 'utf8') + (maxBytes - cardBytes))\r\n if (piece.length > tail.shownText.length) {\r\n seq += 1\r\n ops.push({ type: 'update', elementId: tail.elementId, content: piece, sequence: seq })\r\n cardBytes += Buffer.byteLength(piece, 'utf8') - Buffer.byteLength(tail.shownText, 'utf8')\r\n tail = { ...tail, shownText: piece }\r\n }\r\n carry = { segIndex: i, base: tail.base + tail.shownText.length }\r\n closeCard()\r\n continue\r\n } else {\r\n // process:旧卡定格,续卡整窗重放\r\n closeCard()\r\n continue\r\n }\r\n }\r\n // 已完整同步:是最新段则保活收尾;有更新段则封闭前段\r\n if (i === segments.length - 1) break\r\n tail = undefined\r\n closedSegCount = i + 1\r\n carry = undefined\r\n i += 1\r\n continue\r\n }\r\n\r\n // 当前卡上还没有该段的元素 → insert\r\n if (seg.kind === 'process') {\r\n const windowBytes = Buffer.byteLength(elementContent, 'utf8')\r\n if (cardId !== null && (cardBytes + windowBytes > maxBytes || cardElements + 2 > CARD_ELEMENT_LIMIT)) {\r\n closeCard()\r\n continue\r\n }\r\n ensureCard()\r\n // 过程窗口由 processMaxBytes 兜底(sliceTailByBytes 已截尾);新卡整窗插入,不再受卡预算约束。\r\n segCounter += 1\r\n const elementId = `seg_${segCounter}`\r\n seq += 1\r\n ops.push({ type: 'insert', elementJson: buildSegmentJson('process', elementId, elementContent), sequence: seq })\r\n cardBytes += windowBytes\r\n cardElements += 2\r\n tail = { segIndex: i, elementId, base: 0, shownText: elementContent }\r\n } else {\r\n if (elementContent.length === 0) { // 空 text 段不占卡\r\n closedSegCount = i + 1\r\n carry = undefined\r\n i += 1\r\n continue\r\n }\r\n if (cardId !== null && cardElements + 1 > CARD_ELEMENT_LIMIT) {\r\n closeCard()\r\n continue\r\n }\r\n ensureCard()\r\n const piece = sliceByBytes(elementContent, maxBytes - cardBytes)\r\n if (piece.length === 0) {\r\n throw new Error(`cardMaxBytes=${maxBytes} 过小,扣固定开销后连一个字符都容纳不了`)\r\n }\r\n segCounter += 1\r\n const elementId = `seg_${segCounter}`\r\n seq += 1\r\n ops.push({ type: 'insert', elementJson: buildSegmentJson('text', elementId, piece), sequence: seq })\r\n cardBytes += Buffer.byteLength(piece, 'utf8')\r\n cardElements += 1\r\n tail = { segIndex: i, elementId, base, shownText: piece }\r\n if (piece.length < elementContent.length) {\r\n carry = { segIndex: i, base: base + piece.length }\r\n closeCard()\r\n continue\r\n }\r\n }\r\n carry = undefined\r\n if (i === segments.length - 1) break\r\n tail = undefined\r\n closedSegCount = i + 1\r\n i += 1\r\n }\r\n return { state: { cardId, seq, cardBytes, cardElements, segCounter, closedSegCount, tail, carry }, ops }\r\n}\r\n\r\n/** 定格:先 update 状态行(流式还开着),再关闭 + summary。 */\r\nexport function planFinalize(state: StreamState, status: TurnStatus): { ops: CardOp[] } {\r\n if (state.cardId === null) return { ops: [] }\r\n return {\r\n ops: [\r\n { type: 'update', elementId: STATUS_ELEMENT_ID, content: STATUS_FINAL[status], sequence: state.seq + 1 },\r\n { type: 'settings', streaming: false, sequence: state.seq + 2, summary: STATUS_FINAL[status] },\r\n ],\r\n }\r\n}\r\n","/** 出站句柄:turn 级流式卡片(节流合并 + 拆卡 + 定格着色)与表情回复。 */\r\nimport type { ChannelTunables, Disposer, ReplyHandle, TurnSegment, TurnStatus } from '../channel.ts'\r\nimport type { FeishuApi } from './api.ts'\r\nimport {\r\n initialStreamState, PENDING_CARD_ID, STATUS_ELEMENT_ID,\r\n planFinalize, planSync, type CardOp, type StreamState,\r\n} from './cards.ts'\r\n\r\n/** 指数退避重试(默认 3 次,300ms 起)。 */\r\nexport async function withRetry<T>(fn: () => Promise<T>, attempts = 3, baseDelayMs = 300): Promise<T> {\r\n let lastError: unknown\r\n for (let i = 0; i < attempts; i++) {\r\n try {\r\n return await fn()\r\n } catch (error) {\r\n lastError = error\r\n if (i < attempts - 1) await new Promise((resolve) => setTimeout(resolve, baseDelayMs * 2 ** i))\r\n }\r\n }\r\n throw lastError\r\n}\r\n\r\nexport class FeishuReplyHandle implements ReplyHandle {\r\n private state: StreamState = initialStreamState()\r\n private segments: readonly TurnSegment[] = []\r\n private tail: Promise<unknown> = Promise.resolve()\r\n private timer: ReturnType<typeof setTimeout> | undefined\r\n private finalized = false\r\n\r\n constructor(\r\n private readonly api: FeishuApi,\r\n private readonly chatId: string,\r\n private readonly tunables: ChannelTunables,\r\n private readonly log: (message: string) => void,\r\n ) {}\r\n\r\n /** 惰性建卡:无文本输出的 turn 不产生空卡片。 */\r\n beginTurn(): Promise<void> {\r\n return Promise.resolve()\r\n }\r\n\r\n update(segments: readonly TurnSegment[]): Promise<void> {\r\n if (this.finalized) return Promise.resolve()\r\n this.segments = segments\r\n if (this.timer === undefined) {\r\n this.timer = setTimeout(() => {\r\n this.timer = undefined\r\n this.flush()\r\n }, this.tunables.cardUpdateThrottleMs)\r\n }\r\n return Promise.resolve()\r\n }\r\n\r\n async finalize(status: TurnStatus, detail?: string): Promise<void> {\r\n if (this.finalized) {\r\n await this.tail\r\n return\r\n }\r\n this.finalized = true\r\n if (this.timer !== undefined) {\r\n clearTimeout(this.timer)\r\n this.timer = undefined\r\n }\r\n this.flush()\r\n // 等 flush 定局(含失败回退)后再规划定格:失败回退时按未建卡降级为文本,\r\n // 而不是按乐观状态对幻影卡发 update/settings。\r\n await this.tail\r\n const { ops } = planFinalize(this.state, status)\r\n this.enqueue(() => this.exec(ops))\r\n if (this.state.cardId === null && detail !== undefined) {\r\n this.enqueue(() => withRetry(() => this.api.sendText(this.chatId, detail)).then(() => undefined))\r\n }\r\n await this.tail\r\n }\r\n\r\n notice(text: string): Promise<void> {\r\n this.enqueue(() => withRetry(() => this.api.sendText(this.chatId, text)).then(() => undefined))\r\n return this.tail.then(() => undefined)\r\n }\r\n\r\n private flush(): void {\r\n const planned = planSync(this.state, this.segments, this.tunables.cardMaxBytes, this.tunables.processMaxBytes)\r\n if (planned.ops.length === 0) return\r\n this.state = planned.state\r\n this.enqueue(() => this.exec(planned.ops))\r\n }\r\n\r\n private enqueue(task: () => Promise<void>): void {\r\n this.tail = this.tail.then(task).catch((error) => {\r\n // 建卡链路失败(create 未返回,卡片从未可见):回到未建卡状态,并把乐观推进的\r\n // tail 回卷为 carry(base 保持原位——幻影卡上什么都没真正显示),让下一次\r\n // flush 走 insert 分支重新建卡、完整插入未显示内容,而不是对 null 卡号发 update。\r\n if (this.state.cardId === PENDING_CARD_ID) {\r\n const t = this.state.tail\r\n this.state = {\r\n ...this.state,\r\n cardId: null,\r\n ...(t !== undefined\r\n ? { tail: undefined, carry: { segIndex: t.segIndex, base: t.base }, closedSegCount: t.segIndex }\r\n : {}),\r\n }\r\n }\r\n this.log(`[project-bot] 卡片操作失败:${error instanceof Error ? error.message : String(error)}`)\r\n })\r\n }\r\n\r\n private async exec(ops: readonly CardOp[]): Promise<void> {\r\n for (const op of ops) {\r\n if (op.type === 'create') {\r\n this.state.cardId = await withRetry(() => this.api.createCard(op.cardJson))\r\n } else if (op.type === 'send') {\r\n await withRetry(() => this.api.sendCardMessage(this.chatId, this.state.cardId!))\r\n } else if (op.type === 'insert') {\r\n await withRetry(() => this.api.insertElement(this.state.cardId!, op.elementJson, STATUS_ELEMENT_ID, op.sequence))\r\n } else if (op.type === 'update') {\r\n await withRetry(() => this.api.updateCardElement(this.state.cardId!, op.elementId, op.content, op.sequence))\r\n } else {\r\n await withRetry(() => this.api.setCardStreaming(this.state.cardId!, op.streaming, op.sequence, op.summary))\r\n }\r\n }\r\n }\r\n}\r\n\r\n/** 「处理中」表情:加上后返回删除 disposer;加/删失败都静默(表情残留无害)。 */\r\nexport function makeAck(api: FeishuApi, messageId: string, emojiType: string): () => Promise<Disposer | undefined> {\r\n return async () => {\r\n try {\r\n const reactionId = await api.addReaction(messageId, emojiType)\r\n return () => {\r\n void api.removeReaction(messageId, reactionId).catch(() => undefined)\r\n }\r\n } catch {\r\n return undefined\r\n }\r\n }\r\n}\r\n","/** 飞书渠道:WSClient 长连接收事件 → 解析 → 核心;出站走 FeishuReplyHandle。 */\r\nimport * as lark from '@larksuiteoapi/node-sdk'\r\nimport type { BotChannel, ChannelHandle } from '../channel.ts'\r\nimport { createFeishuApi } from './api.ts'\r\nimport { MessageDedup, parseMessageEvent } from './parse.ts'\r\nimport { FeishuReplyHandle, makeAck } from './reply.ts'\r\n\r\nexport const feishuChannel: BotChannel = {\r\n type: 'feishu',\r\n\r\n async start(bot, io, tunables, log): Promise<ChannelHandle> {\r\n const { appId } = bot.record.feishu\r\n const client = new lark.Client({ appId, appSecret: bot.secret })\r\n const api = createFeishuApi(client)\r\n const dedup = new MessageDedup()\r\n\r\n const dispatcher = new lark.EventDispatcher({}).register({\r\n // WS 事件须 3 秒内返回:解析同步完成,业务投递 fire-and-forget。\r\n 'im.message.receive_v1': async (data: unknown) => {\r\n const parsed = parseMessageEvent(data)\r\n if (parsed === null || !dedup.check(parsed.messageId)) return\r\n const reply = new FeishuReplyHandle(api, parsed.chatId, tunables, log)\r\n io.onMessage({\r\n botId: bot.record.id,\r\n chatId: parsed.chatId,\r\n userId: parsed.userId,\r\n messageId: parsed.messageId,\r\n text: parsed.text,\r\n reply,\r\n ackProcessing: makeAck(api, parsed.messageId, tunables.processingReactionEmoji),\r\n })\r\n },\r\n })\r\n\r\n const ws = new lark.WSClient({ appId, appSecret: bot.secret, loggerLevel: lark.LoggerLevel.warn })\r\n await ws.start({ eventDispatcher: dispatcher })\r\n\r\n return {\r\n close: () => {\r\n ws.close({ force: true })\r\n return Promise.resolve()\r\n },\r\n status: () => ws.getConnectionStatus().state,\r\n }\r\n },\r\n}\r\n","/** project-bot 存储域声明:身份、版本、记录 zod schema 的单一来源。 */\r\nimport { z } from 'zod'\r\nimport { defineDomain, domainTable } from '@deepseek-ai/dsh-storage-domain'\r\n\r\n/** 飞书自建应用 appId 形态(WSClient 同款校验)。 */\r\nexport const FEISHU_APP_ID_RE = /^cli_[0-9a-fA-F]{16}$/\r\n/** CredentialRef 字符集(credentials 服务 credentialRef() 的校验规则)。 */\r\nexport const CREDENTIAL_REF_RE = /^[A-Za-z_][A-Za-z0-9_]*$/\r\n/** bot id:小写 slug。 */\r\nexport const BOT_ID_RE = /^[a-z][a-z0-9-]{0,31}$/\r\n\r\nexport const FeishuConfigSchema = z.object({\r\n appId: z.string().regex(FEISHU_APP_ID_RE),\r\n appSecretRef: z.string().regex(CREDENTIAL_REF_RE),\r\n})\r\nexport type FeishuConfig = z.infer<typeof FeishuConfigSchema>\r\n\r\nexport const BotRecordSchema = z.object({\r\n id: z.string().regex(BOT_ID_RE),\r\n name: z.string().min(1).max(64),\r\n channel: z.literal('feishu'),\r\n feishu: FeishuConfigSchema,\r\n /** 绑定项目(agent 的 cwd,绝对路径)。一 bot 一项目。 */\r\n project: z.string().min(1),\r\n /** 透传到 agent 创作期的 persona 提示段。 */\r\n persona: z.string().max(8000).optional(),\r\n /** 绑定的 Agent('main' 或注册表角色 id,缺省 = 'main')。 */\r\n agentRef: z.string().min(1).optional(),\r\n /** 可用工具白名单(缺省 = 不限制);空数组无意义,直接拒绝。 */\r\n tools: z.array(z.string().min(1)).min(1).optional(),\r\n agentOptions: z.object({\r\n provider: z.string().min(1).optional(),\r\n model: z.string().min(1).optional(),\r\n }).optional(),\r\n createdAt: z.number().int().nonnegative(),\r\n updatedAt: z.number().int().nonnegative(),\r\n})\r\nexport type BotRecord = z.infer<typeof BotRecordSchema>\r\n\r\nexport const BindingSchema = z.object({ sessionId: z.string().min(1) })\r\nexport type Binding = z.infer<typeof BindingSchema>\r\n\r\n/** domain 名受 UNIT_NAME_RE 约束(^[a-z][a-z0-9_]*$),不允许连字符。 */\r\nexport const projectBotDomain = defineDomain({\r\n name: 'project_bot',\r\n version: 1,\r\n tables: {\r\n bots: domainTable<string, BotRecord>(BotRecordSchema),\r\n bindings: domainTable<string, Binding>(BindingSchema),\r\n },\r\n})\r\n\r\n/** bindings 表 key:(botId, chatId) → sessionId。 */\r\nexport function bindingKey(botId: string, chatId: string): string {\r\n return `${botId}:${chatId}`\r\n}\r\n","/** 入站:指令分流 → 路由 → 单 in-flight 准入 → 表情回复 → followup 投递。 */\r\nimport { createUserMessage } from '@deepseek-ai/dsh-llm'\r\nimport type { BotRecord } from '../bots/store.ts'\r\nimport type { InboundMessage } from './channel.ts'\r\nimport { parseDirective } from './directive.ts'\r\nimport type { Router } from './router.ts'\r\n\r\nexport interface InboundDeps {\r\n router: Router\r\n bots: { get(botId: string): BotRecord | undefined }\r\n onError(message: string): void\r\n}\r\n\r\nexport class Inbound {\r\n constructor(private readonly deps: InboundDeps) {}\r\n\r\n onMessage(msg: InboundMessage): void {\r\n void this.handle(msg).catch(async (error) => {\r\n this.deps.onError(`[project-bot] 入站处理失败:${error instanceof Error ? error.message : String(error)}`)\r\n await msg.reply.notice('处理失败,请稍后再试').catch(() => undefined)\r\n })\r\n }\r\n\r\n private async handle(msg: InboundMessage): Promise<void> {\r\n const bot = this.deps.bots.get(msg.botId)\r\n if (bot === undefined) return\r\n\r\n const directive = parseDirective(msg.text)\r\n if (directive === 'new') {\r\n await this.deps.router.reset(bot, msg.chatId, msg.reply)\r\n await msg.reply.notice('已开启新会话')\r\n return\r\n }\r\n if (directive === 'stop') {\r\n const rt = this.deps.router.lookup(bot.id, msg.chatId)\r\n if (rt?.inflight !== undefined) {\r\n rt.agent.cancel()\r\n await msg.reply.notice('已请求停止当前任务')\r\n } else {\r\n await msg.reply.notice('当前没有进行中的任务')\r\n }\r\n return\r\n }\r\n if (directive === 'status') {\r\n const rt = this.deps.router.lookup(bot.id, msg.chatId)\r\n await msg.reply.notice(rt === undefined\r\n ? `项目:${bot.project}\\n会话:未创建(发送消息即创建)`\r\n : `项目:${bot.project}\\n会话:${rt.sessionId}\\n状态:${rt.inflight !== undefined ? '处理中' : '空闲'}`)\r\n return\r\n }\r\n\r\n const rt = await this.deps.router.ensure(bot, msg.chatId, msg.reply)\r\n if (rt.inflight !== undefined) {\r\n await msg.reply.notice('上一条还在处理中,请稍候(或发送 /stop 取消)')\r\n return\r\n }\r\n // 准入:先占槽再异步;表情回复失败不阻塞处理。\r\n rt.inflight = { ack: undefined }\r\n rt.inflight.ack = (await msg.ackProcessing().catch(() => undefined)) ?? undefined\r\n // source kind 用 'user'(与 ACP 同款):dsh sessionTitle 服务只接纳 user 消息生成会话标题。\r\n const message = createUserMessage({\r\n content: [{ type: 'text', text: msg.text }],\r\n source: { kind: 'user' },\r\n })\r\n try {\r\n rt.agent.followup(message)\r\n } catch (error) {\r\n const ack = rt.inflight.ack\r\n rt.inflight = undefined\r\n await ack?.()\r\n throw error\r\n }\r\n }\r\n}\r\n","/** 出站:持久会话事件 → turn 级回复驱动(per-session Promise 链保序)。 */\r\nimport type { TurnSegment, TurnStatus } from './channel.ts'\r\nimport type { SessionRuntime } from './ports.ts'\r\n\r\n/** 窄化的事件信封:核心只读 type/data。 */\r\nexport interface SessionEventLike {\r\n type: string\r\n data: Record<string, unknown>\r\n}\r\n\r\n/** 从 assistant 消息内容块提取正文纯文本(只取 text 块进正文;reasoning/tool_call 由 processOf 进过程区)。 */\r\nexport function textOf(content: readonly unknown[]): string {\r\n return (content as readonly { type?: unknown; text?: unknown }[])\r\n .filter((b): b is { type: 'text'; text: string } => b.type === 'text' && typeof b.text === 'string')\r\n .map((b) => b.text)\r\n .join('')\r\n}\r\n\r\n/** 工具调用参数摘要最大字符数。 */\r\nexport const TOOL_ARGS_MAX_CHARS = 120\r\n\r\n/** 向段序列追加内容:与尾段同类则合并,异类开新段。 */\r\nexport function appendToSegments(segments: TurnSegment[], kind: 'text' | 'process', text: string): void {\r\n const tail = segments[segments.length - 1]\r\n if (tail !== undefined && tail.kind === kind) tail.content += text\r\n else segments.push({ kind, content: text })\r\n}\r\n\r\n/** (保留供测试)从组装消息提取过程输出:reasoning 全文 + tool_call 摘要行(段落间空行分隔)。 */\r\nexport function processOf(content: readonly unknown[]): string {\r\n const parts: string[] = []\r\n for (const b of content as readonly { type?: unknown; text?: unknown; name?: unknown; arguments?: unknown }[]) {\r\n if (b.type === 'reasoning' && typeof b.text === 'string' && b.text.length > 0) {\r\n parts.push(b.text)\r\n } else if (b.type === 'tool_call' && typeof b.name === 'string') {\r\n const args = typeof b.arguments === 'string' ? b.arguments : JSON.stringify(b.arguments ?? {})\r\n parts.push(`🔧 ${b.name} — ${truncateDetail(args, TOOL_ARGS_MAX_CHARS)}`)\r\n }\r\n }\r\n return parts.length === 0 ? '' : `${parts.join('\\n\\n')}\\n\\n`\r\n}\r\n\r\n/** turn/end 的 reason 形状(宿主 TurnEndReason 的窄化视图:核心只读 kind 与 error.message)。 */\r\nexport interface TurnEndReasonLike {\r\n kind: string\r\n error?: { message?: unknown }\r\n}\r\n\r\nexport function mapTurnEnd(reason: TurnEndReasonLike): TurnStatus {\r\n if (reason.kind === 'completed') return 'done'\r\n if (reason.kind === 'aborted' || reason.kind === 'interrupted') return 'cancelled'\r\n return 'error'\r\n}\r\n\r\n/** 截断错误摘要到 max 字符,超出追加省略号。 */\r\nexport function truncateDetail(text: string, max: number): string {\r\n return text.length > max ? `${text.slice(0, max)}…` : text\r\n}\r\n\r\n/** 从 turn/end reason 提取错误摘要;非 error 或无 message 返回 undefined。 */\r\nfunction errorDetailOf(reason: TurnEndReasonLike, max: number): string | undefined {\r\n if (reason.kind !== 'error') return undefined\r\n const message = reason.error?.message\r\n const text = typeof message === 'string' && message.length > 0 ? message : '未知错误'\r\n return truncateDetail(text, max)\r\n}\r\n\r\nexport class Outbound {\r\n constructor(\r\n private readonly sessions: Map<string, SessionRuntime>,\r\n private readonly onError: (message: string) => void,\r\n /** 回传渠道的错误摘要最大字符数。 */\r\n private readonly maxErrorDetailChars = 500,\r\n ) {}\r\n\r\n handleSessionEvent(sessionId: string, event: SessionEventLike): void {\r\n const rt = this.sessions.get(sessionId)\r\n if (rt === undefined) return\r\n\r\n if (event.type === 'turn/start') {\r\n rt.turn = { n: event.data.turn as number, segments: [], began: false }\r\n return\r\n }\r\n\r\n if (event.type === 'assistant/chunk') {\r\n const turn = rt.turn\r\n if (turn === undefined || turn.n !== (event.data.turn as number)) return\r\n const chunk = event.data.chunk as { type: string; text?: string; block?: { type?: unknown } }\r\n if (chunk.type === 'text-delta' && typeof chunk.text === 'string') {\r\n appendToSegments(turn.segments, 'text', chunk.text)\r\n } else if (chunk.type === 'reasoning-delta' && typeof chunk.text === 'string') {\r\n appendToSegments(turn.segments, 'process', chunk.text)\r\n } else if (chunk.type === 'block-end' && chunk.block?.type === 'reasoning' && turn.segments[turn.segments.length - 1]?.kind === 'process') {\r\n appendToSegments(turn.segments, 'process', '\\n\\n') // 推理块段落分隔\r\n } else {\r\n return\r\n }\r\n const snapshot = turn.segments.map((s) => ({ ...s }))\r\n this.enqueue(rt, async () => {\r\n if (rt.reply === undefined) return\r\n if (!turn.began) {\r\n await rt.reply.beginTurn()\r\n turn.began = true\r\n }\r\n await rt.reply.update(snapshot)\r\n })\r\n return\r\n }\r\n\r\n if (event.type === 'tool/call') {\r\n const turn = rt.turn\r\n if (turn === undefined || turn.n !== (event.data.turn as number)) return\r\n const name = event.data.name as string\r\n const args = typeof event.data.arguments === 'string' ? event.data.arguments : JSON.stringify(event.data.arguments ?? {})\r\n appendToSegments(turn.segments, 'process', `🔧 ${name} — ${truncateDetail(args, TOOL_ARGS_MAX_CHARS)}\\n\\n`)\r\n const snapshot = turn.segments.map((s) => ({ ...s }))\r\n this.enqueue(rt, async () => {\r\n if (rt.reply === undefined) return\r\n if (!turn.began) {\r\n await rt.reply.beginTurn()\r\n turn.began = true\r\n }\r\n await rt.reply.update(snapshot)\r\n })\r\n return\r\n }\r\n\r\n if (event.type === 'turn/end') {\r\n const turn = rt.turn\r\n if (turn === undefined || turn.n !== (event.data.turn as number)) return\r\n const reason = event.data.reason as TurnEndReasonLike\r\n const status = mapTurnEnd(reason)\r\n const detail = errorDetailOf(reason, this.maxErrorDetailChars)\r\n this.enqueue(rt, async () => {\r\n // 有卡定格;无卡但有错误 detail 时也要调 finalize(渠道降级为文本送出)。\r\n if ((turn.began || detail !== undefined) && rt.reply !== undefined) await rt.reply.finalize(status, detail)\r\n const ack = rt.inflight?.ack\r\n rt.inflight = undefined\r\n if (ack !== undefined) await ack()\r\n })\r\n rt.turn = undefined\r\n }\r\n }\r\n\r\n /**\r\n * turn 外错误(agent/error:resume/驱动边界失败等没有 turn/end 的场景):\r\n * notice 错误摘要并释放 inflight 槽 + 删除表情;turn 进行中的错误由 turn/end 报告,跳过防双发。\r\n */\r\n handleAgentError(sessionId: string, errorText: string): void {\r\n const rt = this.sessions.get(sessionId)\r\n if (rt === undefined || rt.turn !== undefined) return\r\n const detail = truncateDetail(errorText, this.maxErrorDetailChars)\r\n this.enqueue(rt, async () => {\r\n if (rt.reply !== undefined) await rt.reply.notice(`出错了:${detail}`)\r\n const ack = rt.inflight?.ack\r\n rt.inflight = undefined\r\n if (ack !== undefined) await ack()\r\n })\r\n }\r\n\r\n private enqueue(rt: SessionRuntime, task: () => Promise<void>): void {\r\n rt.tail = rt.tail.then(task).catch((error) => {\r\n this.onError(`[project-bot] 出站处理失败:${error instanceof Error ? error.message : String(error)}`)\r\n })\r\n }\r\n}\r\n","/** 核心对宿主 agents 服务 / 绑定表的结构化端口(测试用 fake 注入)。 */\r\nimport type { BotRecord } from '../bots/store.ts'\r\nimport type { Disposer, ReplyHandle, TurnSegment } from './channel.ts'\r\n\r\nexport interface AgentPort {\r\n readonly sessionId: string\r\n followup(message: unknown): void\r\n cancel(): void\r\n whenIdle(): Promise<void>\r\n}\r\n\r\n/** 一个创作期注册到 agent 系统提示的提示段(name/order/text 与 LayerConfig 同构)。 */\r\nexport interface AgentSection {\r\n name: string\r\n order: number\r\n text: string\r\n}\r\n\r\n/** 创作期注入(真实适配器里映射为 setup(agentCtx) 内的 mount/section/restrict)。 */\r\nexport interface AgentHooks {\r\n persona?: string\r\n tools?: readonly string[]\r\n /** 绑定角色时逐层注册的提示段(name = `dsh-agent-toolkit:agent:<layer>`)。 */\r\n sections?: readonly AgentSection[]\r\n}\r\n\r\nexport interface AgentsPort {\r\n create(input: {\r\n sessionId: string\r\n cwd: string\r\n agentOptions?: { provider?: string; model?: string }\r\n hooks: AgentHooks\r\n }): Promise<AgentPort>\r\n resume(input: {\r\n sessionId: string\r\n agentOptions?: { provider?: string; model?: string }\r\n hooks: AgentHooks\r\n }): Promise<AgentPort>\r\n}\r\n\r\n/** 无 agentOptions 的存量 bot 回退宿主默认模型(取 {provider, model})。 */\r\nexport type DefaultModelAccessor = () => { provider: string; model: string }\r\n\r\n/** 会话归属:把 session 挂到 cwd 对应 workspace(宿主侧幂等;无则自动建)。 */\r\nexport interface WorkspacePort {\r\n attach(cwd: string, sessionId: string): Promise<void>\r\n}\r\n\r\nexport interface BindingStore {\r\n get(botId: string, chatId: string): string | undefined\r\n set(botId: string, chatId: string, sessionId: string): Promise<void>\r\n delete(botId: string, chatId: string): Promise<void>\r\n /** 删除某 bot 的全部绑定(bot 被删除时)。 */\r\n deleteBot(botId: string): Promise<void>\r\n}\r\n\r\n/** 一个活跃会话的运行时状态(inbound/outbound 共享)。 */\r\nexport interface SessionRuntime {\r\n readonly botId: string\r\n readonly chatId: string\r\n readonly sessionId: string\r\n agent: AgentPort\r\n /** 最近一次入站消息携带的回复句柄(回复永远回到 chat)。 */\r\n reply: ReplyHandle | undefined\r\n /** 单会话单 in-flight 槽;ack = 表情回复的 disposer。 */\r\n inflight: { ack: Disposer | undefined } | undefined\r\n /** 出站操作串行化 Promise 链(保序)。 */\r\n tail: Promise<unknown>\r\n /** 当前 turn 归集状态;无进行中 turn 为 undefined。 */\r\n turn: { n: number; segments: TurnSegment[]; began: boolean } | undefined\r\n}\r\n\r\n/** 从 bot 记录提取创作期注入(主 Agent 绑定形态)。 */\r\nexport function hooksOf(bot: BotRecord): AgentHooks {\r\n return {\r\n ...(bot.persona !== undefined ? { persona: bot.persona } : {}),\r\n ...(bot.tools !== undefined ? { tools: bot.tools } : {}),\r\n }\r\n}\r\n","/** 绑定路由:(botId, chatId) → 长期会话;create / resume / reset。 */\r\nimport { randomUUID } from 'node:crypto'\r\nimport type { AgentRegistry } from '../agents/registry.ts'\r\nimport type { BotRecord } from '../bots/store.ts'\r\nimport type { ReplyHandle } from './channel.ts'\r\nimport { hooksOf, type AgentHooks, type AgentsPort, type BindingStore, type DefaultModelAccessor, type SessionRuntime, type WorkspacePort } from './ports.ts'\r\n\r\nexport class Router {\r\n constructor(\r\n private readonly agents: AgentsPort,\r\n private readonly bindings: BindingStore,\r\n /** sessionId → runtime(进程内活跃会话表,与 bindings 持久表互补)。 */\r\n private readonly sessions: Map<string, SessionRuntime>,\r\n /** 存量 bot 无 agentOptions 时回退宿主默认模型。 */\r\n private readonly defaultModel: DefaultModelAccessor,\r\n /** 会话归入 bot 项目 workspace(与原生 UI session.create 同款挂载)。 */\r\n private readonly workspace: WorkspacePort,\r\n private readonly onWarn: (message: string) => void,\r\n /** Agent 注册表(agentRef → main/角色),会话创建时决定 persona/工具/模型装配。 */\r\n private readonly registry: AgentRegistry,\r\n ) {}\r\n\r\n /** 取(或建/恢复)该 chat 的会话 runtime;reply 刷新为最近一次入站携带的句柄。 */\r\n async ensure(bot: BotRecord, chatId: string, reply: ReplyHandle): Promise<SessionRuntime> {\r\n const bound = this.bindings.get(bot.id, chatId)\r\n if (bound !== undefined) {\r\n const existing = this.sessions.get(bound)\r\n if (existing !== undefined) {\r\n existing.reply = reply\r\n return existing\r\n }\r\n const agent = await this.agents.resume({ sessionId: bound, ...this.resolveSession(bot) })\r\n await this.attach(bot.project, bound)\r\n return this.adopt(bot.id, chatId, bound, agent, reply)\r\n }\r\n const sessionId = randomUUID()\r\n const agent = await this.agents.create({ sessionId, cwd: bot.project, ...this.resolveSession(bot) })\r\n await this.bindings.set(bot.id, chatId, sessionId)\r\n await this.attach(bot.project, sessionId)\r\n return this.adopt(bot.id, chatId, sessionId, agent, reply)\r\n }\r\n\r\n /** attach 失败仅告警(会话降级为未分组),不阻塞消息处理。 */\r\n private async attach(cwd: string, sessionId: string): Promise<void> {\r\n try {\r\n await this.workspace.attach(cwd, sessionId)\r\n } catch (error) {\r\n this.onWarn(`[project-bot] 会话 ${sessionId} 挂载 workspace 失败:${error instanceof Error ? error.message : String(error)}`)\r\n }\r\n }\r\n\r\n /** 有 agentOptions 原样透传;无则回退宿主默认模型(存量 bot 不抛 no provider/model)。 */\r\n private resolveOptions(bot: BotRecord): { provider?: string; model?: string } {\r\n return bot.agentOptions ?? this.defaultModel()\r\n }\r\n\r\n /**\r\n * 按 bot.agentRef 解析会话组装(agentOptions + 创作期 hooks):\r\n * - 缺省/指向 main → 主 Agent 形态:bot 自带 persona/tools + 默认模型回退;\r\n * - 指向角色 → 角色形态:persona 单 section + tools.restrict + role.model;\r\n * - 指向不存在角色 → warn 并降级为主 Agent 形态。\r\n */\r\n private resolveSession(bot: BotRecord): { agentOptions: { provider?: string; model?: string }; hooks: AgentHooks } {\r\n const ref = bot.agentRef ?? 'main'\r\n const role = this.registry.get(ref)\r\n if (role === undefined || ref === 'main') {\r\n if (role === undefined && ref !== 'main') {\r\n this.onWarn(`[project-bot] bot \"${bot.id}\" 的 agentRef \"${ref}\" 不存在,降级绑定主 Agent`)\r\n }\r\n return { agentOptions: this.resolveOptions(bot), hooks: hooksOf(bot) }\r\n }\r\n const sections = role.persona === undefined || role.persona.trim().length === 0\r\n ? []\r\n : [{ name: 'dsh-agent-toolkit:agent:persona', order: 0, text: role.persona }]\r\n return {\r\n agentOptions: role.model ?? this.resolveOptions(bot),\r\n hooks: {\r\n ...(sections.length > 0 ? { sections } : {}),\r\n ...(role.tools !== undefined ? { tools: role.tools.allow } : {}),\r\n },\r\n }\r\n }\r\n\r\n /** /new:取消旧会话、清绑定、开新会话。 */\r\n async reset(bot: BotRecord, chatId: string, reply: ReplyHandle): Promise<SessionRuntime> {\r\n const bound = this.bindings.get(bot.id, chatId)\r\n if (bound !== undefined) {\r\n this.sessions.get(bound)?.agent.cancel()\r\n this.sessions.delete(bound)\r\n await this.bindings.delete(bot.id, chatId)\r\n }\r\n return this.ensure(bot, chatId, reply)\r\n }\r\n\r\n lookup(botId: string, chatId: string): SessionRuntime | undefined {\r\n const bound = this.bindings.get(botId, chatId)\r\n return bound === undefined ? undefined : this.sessions.get(bound)\r\n }\r\n\r\n private adopt(botId: string, chatId: string, sessionId: string, agent: SessionRuntime['agent'], reply: ReplyHandle): SessionRuntime {\r\n const rt: SessionRuntime = {\r\n botId, chatId, sessionId, agent, reply,\r\n inflight: undefined, tail: Promise.resolve(), turn: undefined,\r\n }\r\n this.sessions.set(sessionId, rt)\r\n return rt\r\n }\r\n}\r\n","/** BotRuntime:bot 名册 → 渠道生命周期;聚合 router/inbound/outbound。 */\r\nimport type { KvTable } from '@deepseek-ai/dsh-storage-domain'\r\nimport type { AgentRegistry } from '../agents/registry.ts'\r\nimport { bindingKey, type Binding, type BotRecord } from '../bots/store.ts'\r\nimport type { BotChannel, ChannelHandle, ChannelStatus, ChannelTunables } from './channel.ts'\r\nimport { Inbound } from './inbound.ts'\r\nimport { Outbound } from './outbound.ts'\r\nimport type { AgentsPort, BindingStore, DefaultModelAccessor, SessionRuntime, WorkspacePort } from './ports.ts'\r\nimport { Router } from './router.ts'\r\n\r\nexport interface RuntimeDeps {\r\n bots: KvTable<string, BotRecord>\r\n bindings: KvTable<string, Binding>\r\n agents: AgentsPort\r\n /** Agent 注册表(agentRef → main/角色),Router 会话创建时决定 persona/工具/模型装配。 */\r\n registry: AgentRegistry\r\n /** 存量 bot 无 agentOptions 时回退宿主默认模型。 */\r\n defaultModel: DefaultModelAccessor\r\n /** 会话归入 bot 项目 workspace。 */\r\n workspace: WorkspacePort\r\n channels: ReadonlyMap<string, BotChannel>\r\n tunables: ChannelTunables\r\n /** 回传渠道的错误摘要最大字符数。 */\r\n maxErrorDetailChars: number\r\n resolveSecret(ref: string): Promise<string | undefined>\r\n validateProject(path: string): boolean\r\n log: { warn(message: string): void; info(message: string): void }\r\n}\r\n\r\nexport type BotStatus = ChannelStatus | 'not-running'\r\n\r\nexport class BotRuntime {\r\n readonly sessions = new Map<string, SessionRuntime>()\r\n readonly router: Router\r\n readonly inbound: Inbound\r\n readonly outbound: Outbound\r\n private readonly handles = new Map<string, ChannelHandle>()\r\n\r\n constructor(private readonly deps: RuntimeDeps) {\r\n const bindingStore = this.bindingStore()\r\n this.router = new Router(deps.agents, bindingStore, this.sessions, deps.defaultModel, deps.workspace, (m) => deps.log.warn(m), deps.registry)\r\n this.inbound = new Inbound({ router: this.router, bots: deps.bots, onError: (m) => deps.log.warn(m) })\r\n this.outbound = new Outbound(this.sessions, (m) => deps.log.warn(m), deps.maxErrorDetailChars)\r\n }\r\n\r\n async startAll(): Promise<void> {\r\n for (const botId of [...this.deps.bots.keys()]) await this.reconcile(botId)\r\n }\r\n\r\n /** 按最新记录重建该 bot 的渠道(创建/更新后调用;记录已删则纯停止)。 */\r\n async reconcile(botId: string): Promise<void> {\r\n await this.stopChannel(botId)\r\n const record = this.deps.bots.get(botId)\r\n if (record === undefined) return\r\n if (!this.deps.validateProject(record.project)) {\r\n this.deps.log.warn(`[project-bot] bot \"${botId}\" 的项目路径不可用:${record.project}`)\r\n return\r\n }\r\n const secret = await this.deps.resolveSecret(record.feishu.appSecretRef)\r\n if (secret === undefined) {\r\n this.deps.log.warn(`[project-bot] bot \"${botId}\" 的密钥 ${record.feishu.appSecretRef} 未配置`)\r\n return\r\n }\r\n const channel = this.deps.channels.get(record.channel)\r\n if (channel === undefined) {\r\n this.deps.log.warn(`[project-bot] bot \"${botId}\" 的渠道 \"${record.channel}\" 未实现`)\r\n return\r\n }\r\n try {\r\n const handle = await channel.start(\r\n { record, secret },\r\n { onMessage: (msg) => this.inbound.onMessage(msg) },\r\n this.deps.tunables,\r\n (m) => this.deps.log.warn(m),\r\n )\r\n this.handles.set(botId, handle)\r\n } catch (error) {\r\n this.deps.log.warn(`[project-bot] bot \"${botId}\" 渠道启动失败:${error instanceof Error ? error.message : String(error)}`)\r\n }\r\n }\r\n\r\n /** 删除 bot:停渠道、取消会话、清绑定。 */\r\n async stopBot(botId: string): Promise<void> {\r\n await this.stopChannel(botId)\r\n for (const [sessionId, rt] of [...this.sessions]) {\r\n if (rt.botId === botId) {\r\n rt.agent.cancel()\r\n this.sessions.delete(sessionId)\r\n }\r\n }\r\n await this.bindingStore().deleteBot(botId)\r\n }\r\n\r\n statusOf(botId: string): BotStatus {\r\n return this.handles.get(botId)?.status() ?? 'not-running'\r\n }\r\n\r\n /** 卸载时序:取消在飞会话 → 等 idle → drain 出站链(卡片定格)→ 断全部渠道。 */\r\n async stopAll(): Promise<void> {\r\n for (const rt of this.sessions.values()) rt.agent.cancel()\r\n await Promise.allSettled([...this.sessions.values()].map(async (rt) => {\r\n await rt.agent.whenIdle().catch(() => undefined)\r\n await rt.tail\r\n }))\r\n await Promise.allSettled([...this.handles.values()].map((h) => h.close()))\r\n this.handles.clear()\r\n }\r\n\r\n private async stopChannel(botId: string): Promise<void> {\r\n const handle = this.handles.get(botId)\r\n if (handle === undefined) return\r\n this.handles.delete(botId)\r\n await handle.close().catch((error) => {\r\n this.deps.log.warn(`[project-bot] bot \"${botId}\" 渠道关闭异常:${error instanceof Error ? error.message : String(error)}`)\r\n })\r\n }\r\n\r\n private bindingStore(): BindingStore {\r\n const { bindings } = this.deps\r\n return {\r\n get: (b, c) => bindings.get(bindingKey(b, c))?.sessionId,\r\n set: async (b, c, s) => { await bindings.put(bindingKey(b, c), { sessionId: s }) },\r\n delete: async (b, c) => { await bindings.delete(bindingKey(b, c)) },\r\n deleteBot: async (b) => {\r\n for (const key of [...bindings.keys()]) {\r\n if (key.startsWith(`${b}:`)) await bindings.delete(key)\r\n }\r\n },\r\n }\r\n }\r\n}\r\n","/** 浏览器半 RPC:单前缀路由 /dsh-agent-toolkit/api/bots + 内部路径分发。 */\r\nimport { randomBytes } from 'node:crypto'\r\nimport type { IncomingMessage, ServerResponse } from 'node:http'\r\nimport type { KvTable } from '@deepseek-ai/dsh-storage-domain'\r\nimport { z } from 'zod'\r\nimport type { BotRuntime } from '../channels/runtime.ts'\r\nimport type { RegisterAppService } from './register-app.ts'\r\nimport { BOT_ID_RE, BotRecordSchema, FEISHU_APP_ID_RE, type BotRecord } from './store.ts'\r\n\r\n/** 一个可选的 provider 路由(id = agentOptions.provider 的值)。 */\r\nexport interface ProviderOption { id: string; name: string }\r\n/** 一个可选的模型条目(id = agentOptions.model 的值)。 */\r\nexport interface ModelOption { id: string; name: string }\r\n\r\nexport interface ApiDeps {\r\n bots: KvTable<string, BotRecord>\r\n runtime: BotRuntime\r\n registerApp: RegisterAppService\r\n listTools(): string[]\r\n listProviders(): ProviderOption[]\r\n /** 失败由调用方(路由)兜底为空数组,不抛错。 */\r\n listModels(provider: string): Promise<ModelOption[]>\r\n /** 密钥入 credentials,返回 CredentialRef 字符串。 */\r\n storeSecret(key: string, secret: string): Promise<string>\r\n deleteSecret(ref: string): Promise<void>\r\n validateProject(path: string): boolean\r\n now(): number\r\n}\r\n\r\nconst MAX_BODY_BYTES = 64 * 1024\r\n\r\nconst CreateBodySchema = z.object({\r\n /** 缺省时后端自动生成(bot-<8 位随机小写字母数字>)。 */\r\n id: z.string().regex(BOT_ID_RE).optional(),\r\n name: z.string().min(1).max(64),\r\n project: z.string().min(1),\r\n persona: z.string().max(8000).optional(),\r\n /** 绑定的 Agent('main' 或注册表角色 id;缺省 = main)。 */\r\n agentRef: z.string().min(1).optional(),\r\n tools: z.array(z.string().min(1)).min(1).optional(),\r\n agentOptions: z.object({ provider: z.string().min(1).optional(), model: z.string().min(1).optional() }).optional(),\r\n feishu: z.object({\r\n appId: z.string().regex(FEISHU_APP_ID_RE),\r\n /** 手动填写路径:明文密钥(立即入 credentials,不落表)。 */\r\n appSecret: z.string().min(1).optional(),\r\n /** 扫码路径:registerApp 已入库,直接给引用。 */\r\n appSecretRef: z.string().optional(),\r\n }),\r\n})\r\n\r\nconst UpdateBodySchema = z.object({\r\n name: z.string().min(1).max(64).optional(),\r\n project: z.string().min(1).optional(),\r\n persona: z.string().max(8000).nullable().optional(),\r\n agentRef: z.string().min(1).nullable().optional(),\r\n tools: z.array(z.string().min(1)).min(1).nullable().optional(),\r\n agentOptions: z.object({ provider: z.string().min(1).optional(), model: z.string().min(1).optional() }).nullable().optional(),\r\n /** 换绑应用:明文新密钥(立即入 credentials)。 */\r\n feishu: z.object({ appId: z.string().regex(FEISHU_APP_ID_RE), appSecret: z.string().min(1) }).optional(),\r\n})\r\n\r\nfunction json(res: ServerResponse, code: number, body: unknown): void {\r\n res.writeHead(code, { 'content-type': 'application/json' }).end(JSON.stringify(body))\r\n}\r\n\r\nconst ID_CHARS = 'abcdefghijklmnopqrstuvwxyz0123456789'\r\n\r\n/** 生成 bot-<8 位随机小写字母数字>(符合 BOT_ID_RE);与现有 id 冲突时重试。 */\r\nfunction generateBotId(occupied: (id: string) => boolean): string {\r\n for (;;) {\r\n const bytes = randomBytes(8)\r\n let id = 'bot-'\r\n for (let i = 0; i < 8; i++) id += ID_CHARS[bytes[i] % ID_CHARS.length]\r\n if (!occupied(id)) return id\r\n }\r\n}\r\n\r\n/** 读 JSON body;超限 413 / 非法 JSON 400(已写响应时返回 undefined)。 */\r\nasync function readJsonBody(req: IncomingMessage, res: ServerResponse): Promise<unknown | undefined> {\r\n const chunks: Buffer[] = []\r\n let received = 0\r\n for await (const chunk of req) {\r\n const buffer = chunk as Buffer\r\n received += buffer.byteLength\r\n if (received > MAX_BODY_BYTES) {\r\n json(res, 413, { error: 'body too large' })\r\n req.destroy()\r\n return undefined\r\n }\r\n chunks.push(buffer)\r\n }\r\n try {\r\n return JSON.parse(Buffer.concat(chunks).toString('utf8'))\r\n } catch {\r\n json(res, 400, { error: 'invalid JSON body' })\r\n return undefined\r\n }\r\n}\r\n\r\nexport function createApiHandler(deps: ApiDeps): (req: IncomingMessage, res: ServerResponse) => Promise<void> {\r\n return async (req, res) => {\r\n const url = new URL(req.url ?? '/', 'http://127.0.0.1')\r\n const sub = url.pathname.replace(/^\\/dsh-agent-toolkit\\/api\\/bots/, '') || '/'\r\n const method = req.method ?? 'GET'\r\n\r\n if (sub === '/bots' && method === 'GET') {\r\n const bots = [...deps.bots.entries()].map(([, record]) => ({ ...record, status: deps.runtime.statusOf(record.id) }))\r\n json(res, 200, { bots })\r\n return\r\n }\r\n\r\n if (sub === '/bots' && method === 'POST') {\r\n const body = await readJsonBody(req, res)\r\n if (body === undefined) return\r\n const parsed = CreateBodySchema.safeParse(body)\r\n if (!parsed.success) {\r\n json(res, 400, { error: parsed.error.issues[0]?.message ?? 'invalid body' })\r\n return\r\n }\r\n const input = parsed.data\r\n const id = input.id ?? generateBotId((candidate) => deps.bots.get(candidate) !== undefined)\r\n if (deps.bots.get(id) !== undefined) {\r\n json(res, 409, { error: `bot id \"${id}\" 已存在` })\r\n return\r\n }\r\n for (const [, existing] of deps.bots.entries()) {\r\n if (existing.feishu.appId === input.feishu.appId) {\r\n json(res, 409, { error: `appId 已被 bot \"${existing.id}\" 使用` })\r\n return\r\n }\r\n }\r\n if (!deps.validateProject(input.project)) {\r\n json(res, 400, { error: `项目路径不可用:${input.project}` })\r\n return\r\n }\r\n let appSecretRef = input.feishu.appSecretRef\r\n if (appSecretRef === undefined) {\r\n if (input.feishu.appSecret === undefined) {\r\n json(res, 400, { error: '缺少 appSecret 或 appSecretRef' })\r\n return\r\n }\r\n appSecretRef = await deps.storeSecret(id, input.feishu.appSecret)\r\n }\r\n const record = BotRecordSchema.parse({\r\n id, name: input.name, channel: 'feishu',\r\n feishu: { appId: input.feishu.appId, appSecretRef },\r\n project: input.project,\r\n ...(input.persona !== undefined ? { persona: input.persona } : {}),\r\n ...(input.agentRef !== undefined ? { agentRef: input.agentRef } : {}),\r\n ...(input.tools !== undefined ? { tools: input.tools } : {}),\r\n ...(input.agentOptions !== undefined ? { agentOptions: input.agentOptions } : {}),\r\n createdAt: deps.now(), updatedAt: deps.now(),\r\n } satisfies BotRecord)\r\n await deps.bots.put(record.id, record)\r\n await deps.runtime.reconcile(record.id)\r\n json(res, 200, { bot: { ...record, status: deps.runtime.statusOf(record.id) } })\r\n return\r\n }\r\n\r\n if (sub === '/bots' && method === 'PUT') {\r\n const id = url.searchParams.get('id') ?? ''\r\n const existing = deps.bots.get(id)\r\n if (existing === undefined) {\r\n json(res, 404, { error: `bot \"${id}\" 不存在` })\r\n return\r\n }\r\n const body = await readJsonBody(req, res)\r\n if (body === undefined) return\r\n const parsed = UpdateBodySchema.safeParse(body)\r\n if (!parsed.success) {\r\n json(res, 400, { error: parsed.error.issues[0]?.message ?? 'invalid body' })\r\n return\r\n }\r\n const input = parsed.data\r\n let feishu = existing.feishu\r\n if (input.feishu !== undefined) {\r\n feishu = { appId: input.feishu.appId, appSecretRef: await deps.storeSecret(id, input.feishu.appSecret) }\r\n }\r\n const project = input.project ?? existing.project\r\n if (!deps.validateProject(project)) {\r\n json(res, 400, { error: `项目路径不可用:${project}` })\r\n return\r\n }\r\n const merged: Record<string, unknown> = {\r\n ...existing,\r\n ...(input.name !== undefined ? { name: input.name } : {}),\r\n project,\r\n feishu,\r\n updatedAt: deps.now(),\r\n }\r\n if (input.persona === null) delete merged.persona\r\n else if (input.persona !== undefined) merged.persona = input.persona\r\n if (input.agentRef === null) delete merged.agentRef\r\n else if (input.agentRef !== undefined) merged.agentRef = input.agentRef\r\n if (input.tools === null) delete merged.tools\r\n else if (input.tools !== undefined) merged.tools = input.tools\r\n if (input.agentOptions === null) delete merged.agentOptions\r\n else if (input.agentOptions !== undefined) merged.agentOptions = input.agentOptions\r\n const record = BotRecordSchema.parse(merged)\r\n await deps.bots.put(id, record)\r\n await deps.runtime.reconcile(id)\r\n json(res, 200, { bot: { ...record, status: deps.runtime.statusOf(id) } })\r\n return\r\n }\r\n\r\n if (sub === '/bots' && method === 'DELETE') {\r\n const id = url.searchParams.get('id') ?? ''\r\n const existing = deps.bots.get(id)\r\n if (existing === undefined) {\r\n json(res, 404, { error: `bot \"${id}\" 不存在` })\r\n return\r\n }\r\n await deps.runtime.stopBot(id)\r\n await deps.bots.delete(id)\r\n await deps.deleteSecret(existing.feishu.appSecretRef)\r\n json(res, 200, { ok: true })\r\n return\r\n }\r\n\r\n if (sub === '/register-app' && method === 'POST') {\r\n json(res, 200, { id: deps.registerApp.start() })\r\n return\r\n }\r\n\r\n if (sub === '/register-app/status' && method === 'GET') {\r\n const id = url.searchParams.get('id') ?? ''\r\n const state = deps.registerApp.get(id)\r\n if (state === undefined) {\r\n json(res, 404, { error: 'register session 不存在' })\r\n return\r\n }\r\n json(res, 200, { state })\r\n return\r\n }\r\n\r\n if (sub === '/tools' && method === 'GET') {\r\n json(res, 200, { tools: deps.listTools() })\r\n return\r\n }\r\n\r\n if (sub === '/providers' && method === 'GET') {\r\n json(res, 200, { providers: deps.listProviders() })\r\n return\r\n }\r\n\r\n if (sub === '/models' && method === 'GET') {\r\n // 模型列举可能走网络(adapter 探测),失败静默降级为空数组。\r\n let models: ModelOption[] = []\r\n try {\r\n models = await deps.listModels(url.searchParams.get('provider') ?? '')\r\n } catch {\r\n models = []\r\n }\r\n json(res, 200, { models })\r\n return\r\n }\r\n\r\n if (['/bots', '/register-app', '/register-app/status', '/tools', '/providers', '/models'].includes(sub)) {\r\n json(res, 405, { error: 'method not allowed' })\r\n return\r\n }\r\n json(res, 404, { error: 'not found' })\r\n }\r\n}\r\n","/** 扫码一键创建飞书应用:lark.registerApp(OAuth 2.0 Device Authorization Grant)的状态机封装。 */\r\nimport { randomUUID } from 'node:crypto'\r\n\r\nexport interface QRInfo {\r\n url: string\r\n expireIn: number\r\n}\r\n\r\n/** lark.registerApp 的结构化签名(便于 fake 注入)。 */\r\nexport type RegisterAppFn = (options: {\r\n signal: AbortSignal\r\n onQRCodeReady(info: QRInfo): void\r\n}) => Promise<{ client_id: string; client_secret: string }>\r\n\r\nexport type RegisterState =\r\n | { status: 'pending'; url?: string; expireIn?: number }\r\n | { status: 'done'; appId: string; credentialRef: string }\r\n | { status: 'error'; code: string; description?: string }\r\n\r\nexport interface RegisterAppDeps {\r\n registerApp: RegisterAppFn\r\n /** 把 appSecret 存进 credentials,返回 CredentialRef 字符串。 */\r\n storeSecret(appId: string, secret: string): Promise<string>\r\n timeoutMs: number\r\n newId?: () => string\r\n}\r\n\r\nexport class RegisterAppService {\r\n private readonly sessions = new Map<string, {\r\n state: RegisterState\r\n controller: AbortController\r\n timer: ReturnType<typeof setTimeout>\r\n }>()\r\n\r\n constructor(private readonly deps: RegisterAppDeps) {}\r\n\r\n /** 发起一轮扫码创建;返回轮询 id。 */\r\n start(): string {\r\n const id = (this.deps.newId ?? randomUUID)()\r\n const controller = new AbortController()\r\n const entry = {\r\n state: { status: 'pending' } as RegisterState,\r\n controller,\r\n timer: setTimeout(() => { controller.abort() }, this.deps.timeoutMs),\r\n }\r\n this.sessions.set(id, entry)\r\n void this.deps.registerApp({\r\n signal: controller.signal,\r\n onQRCodeReady: (info) => {\r\n entry.state = { status: 'pending', url: info.url, expireIn: info.expireIn }\r\n },\r\n }).then(async (result) => {\r\n const credentialRef = await this.deps.storeSecret(result.client_id, result.client_secret)\r\n entry.state = { status: 'done', appId: result.client_id, credentialRef }\r\n }).catch((error: unknown) => {\r\n const e = error as { code?: unknown; description?: unknown }\r\n entry.state = {\r\n status: 'error',\r\n code: typeof e.code === 'string' ? e.code : 'unknown',\r\n ...(typeof e.description === 'string' ? { description: e.description } : {}),\r\n }\r\n }).finally(() => {\r\n clearTimeout(entry.timer)\r\n })\r\n return id\r\n }\r\n\r\n get(id: string): RegisterState | undefined {\r\n return this.sessions.get(id)?.state\r\n }\r\n\r\n /** 卸载:中断全部进行中的轮询。 */\r\n dispose(): void {\r\n for (const entry of this.sessions.values()) {\r\n entry.controller.abort()\r\n clearTimeout(entry.timer)\r\n }\r\n this.sessions.clear()\r\n }\r\n}\r\n","/** bots 模块:项目机器人(飞书渠道)——多 bot 作为项目 agent 的交互入口(project-bot Node 半迁移,去 preset 化)。 */\r\nimport { existsSync } from 'node:fs'\r\nimport type { IncomingMessage, ServerResponse } from 'node:http'\r\nimport type { Context } from '@deepseek-ai/cordis'\r\nimport { SessionId } from '@deepseek-ai/dsh-session'\r\nimport { credentialRef } from '@deepseek-ai/dsh-credentials'\r\nimport type { AgentHandle } from '@deepseek-ai/dsh-agent'\r\n// type-only 导入激活各包对 cordis Context 的声明合并(inject 的服务属性)。\r\nimport type {} from '@deepseek-ai/dsh-system-prompt'\r\nimport type {} from '@deepseek-ai/dsh-tools'\r\nimport type {} from '@deepseek-ai/dsh-host-webserver'\r\nimport type {} from '@deepseek-ai/dsh-llm'\r\nimport type {} from '@deepseek-ai/dsh-agent-default-model'\r\nimport type { AgentRegistry } from '../agents/registry.ts'\r\nimport { openDomainSafely } from '../shared/storage.ts'\r\nimport { registerOptionalRoutes } from '../shared/webserver.ts'\r\nimport { setupAgentScope } from '../channels/agent-setup.ts'\r\nimport type { BotChannel, ChannelTunables } from '../channels/channel.ts'\r\nimport { feishuChannel } from '../channels/feishu/index.ts'\r\nimport type { AgentPort, AgentsPort, WorkspacePort } from '../channels/ports.ts'\r\nimport { BotRuntime } from '../channels/runtime.ts'\r\nimport { createApiHandler } from './api.ts'\r\nimport { RegisterAppService } from './register-app.ts'\r\nimport { projectBotDomain, type Binding, type BotRecord } from './store.ts'\r\n\r\n/** project-bot Config 的 6 个全局可调参数(字段名不变;schemastery 定义与默认值源:archive/2026-08-26-merged-plugins/project-bot/src/index.ts:38-45,由 Task 15 平移进 suite Config)。 */\r\nexport interface BotsModuleConfig {\r\n /** 卡片流式更新节流间隔(毫秒)。 */\r\n cardUpdateThrottleMs: number\r\n /** 单张卡片内容字节上限(飞书硬上限 30KB,留余量)。 */\r\n cardMaxBytes: number\r\n /** 过程区(思考 + 工具调用)字节上限(截尾保留最近内容)。 */\r\n processMaxBytes: number\r\n /** 扫码创建应用的轮询超时(毫秒)。 */\r\n registerAppTimeoutMs: number\r\n /** 「处理中」表情回复的 emoji_type。 */\r\n processingReactionEmoji: string\r\n /** 回传飞书的错误摘要最大字符数。 */\r\n errorDetailMaxChars: number\r\n}\r\n\r\n/** setupBots 的宿主接线依赖(registry 供运行时委派/API 消费;prompt 无消费方,Task 13 定案不装配 persona)。 */\r\nexport interface BotsDeps {\r\n registry: AgentRegistry\r\n}\r\n\r\nexport function setupBots(ctx: Context, config: BotsModuleConfig, deps: BotsDeps): void {\r\n const log = { warn: (m: string) => ctx.logger.warn(m), info: (m: string) => ctx.logger.info(m) }\r\n const channels: ReadonlyMap<string, BotChannel> = new Map([['feishu', feishuChannel]])\r\n const tunables: ChannelTunables = {\r\n cardUpdateThrottleMs: config.cardUpdateThrottleMs,\r\n cardMaxBytes: config.cardMaxBytes,\r\n processMaxBytes: config.processMaxBytes,\r\n processingReactionEmoji: config.processingReactionEmoji,\r\n }\r\n\r\n const storeSecret = async (key: string, secret: string): Promise<string> => {\r\n const ref = `project_bot_${key.replace(/[^A-Za-z0-9_]/g, '_')}`\r\n await ctx.credentials.set(credentialRef(ref), secret)\r\n return ref\r\n }\r\n\r\n /** 创作期注入已迁至 agent-setup.ts(基础工具 scoped 挂载 + persona/tools),preset 机制整体移除。 */\r\n\r\n const agentsPort: AgentsPort = {\r\n async create(input) {\r\n const handle: AgentHandle = await ctx.agents.create({\r\n sessionId: SessionId(input.sessionId),\r\n meta: { cwd: input.cwd },\r\n ...(input.agentOptions !== undefined ? { agentOptions: input.agentOptions } : {}),\r\n setup: (agentCtx) => setupAgentScope(agentCtx, input.hooks),\r\n })\r\n return adaptAgent(handle)\r\n },\r\n async resume(input) {\r\n const handle: AgentHandle = await ctx.agents.resume({\r\n resumeSessionId: SessionId(input.sessionId),\r\n ...(input.agentOptions !== undefined ? { agentOptions: input.agentOptions } : {}),\r\n setup: (agentCtx) => setupAgentScope(agentCtx, input.hooks),\r\n })\r\n return adaptAgent(handle)\r\n },\r\n }\r\n\r\n function adaptAgent(handle: AgentHandle): AgentPort {\r\n const { agent } = handle\r\n return {\r\n sessionId: String(agent.id),\r\n followup: (message) => agent.followup(message as Parameters<typeof agent.followup>[0]),\r\n cancel: () => agent.cancel({ kind: 'user' }),\r\n whenIdle: () => agent.whenIdle(),\r\n }\r\n }\r\n\r\n // workspaceRegistry 是可选服务(ctx.get 非严格模式):缺失时 attach 抛错,\r\n // 由 Router 捕获降级为\"未分组 + 告警\",不阻塞消息处理。\r\n interface WorkspaceRegistryLike {\r\n create(path: string): Promise<{ attachSession(sessionId: SessionId): Promise<void> }>\r\n }\r\n const workspaceRegistry = ctx.get('workspaceRegistry', false) as WorkspaceRegistryLike | undefined\r\n const workspacePort: WorkspacePort = {\r\n async attach(cwd, sessionId) {\r\n if (workspaceRegistry === undefined) throw new Error('workspaceRegistry 服务不可用')\r\n const workspace = await workspaceRegistry.create(cwd)\r\n await workspace.attachSession(SessionId(sessionId))\r\n },\r\n }\r\n\r\n // 存储域:open 失败挂 rejection handler 防次生崩溃,调用方仍感知失败(token-usage 同款)。\r\n // 卸载顺序由 openDomainSafely 的 beforeClose 保证:先等启动链落定、排空在飞会话与出站链\r\n // (stopAll 内含卡片定格 drain),再关存储域——close 一旦开始就拒绝新入队的写。\r\n let botsTable: import('@deepseek-ai/dsh-storage-domain').KvTable<string, BotRecord> | undefined\r\n let bindingsTable: import('@deepseek-ai/dsh-storage-domain').KvTable<string, Binding> | undefined\r\n let runtime: BotRuntime | undefined\r\n let started: Promise<void> = Promise.resolve()\r\n const domainReady = openDomainSafely(\r\n ctx,\r\n projectBotDomain,\r\n (msg) => log.warn(msg),\r\n async () => {\r\n await started.catch(() => undefined)\r\n await runtime?.stopAll()\r\n },\r\n ).then((domain) => {\r\n botsTable = domain.table('bots') as import('@deepseek-ai/dsh-storage-domain').KvTable<string, BotRecord>\r\n bindingsTable = domain.table('bindings') as import('@deepseek-ai/dsh-storage-domain').KvTable<string, Binding>\r\n return domain\r\n })\r\n\r\n const registerAppService = new RegisterAppService({\r\n registerApp: (options) => import('@larksuiteoapi/node-sdk').then((lark) => lark.registerApp(options)),\r\n storeSecret,\r\n timeoutMs: config.registerAppTimeoutMs,\r\n })\r\n\r\n started = domainReady.then(() => {\r\n runtime = new BotRuntime({\r\n bots: botsTable!,\r\n bindings: bindingsTable!,\r\n agents: agentsPort,\r\n registry: deps.registry,\r\n defaultModel: () => {\r\n const selection = ctx.agentDefaultModel.currentSelection()\r\n return { provider: selection.provider, model: selection.model }\r\n },\r\n workspace: workspacePort,\r\n channels,\r\n tunables,\r\n maxErrorDetailChars: config.errorDetailMaxChars,\r\n resolveSecret: async (ref) => (await ctx.credentials.resolve(credentialRef(ref)))?.value,\r\n validateProject: (path) => existsSync(path),\r\n log,\r\n })\r\n return runtime.startAll()\r\n })\r\n started.catch((error) => {\r\n log.warn(`[project-bot] 启动失败:${error instanceof Error ? error.message : String(error)}`)\r\n })\r\n\r\n // 出站:持久会话事件 → runtime.outbound(session id 匹配自有 runtime,其余忽略)。\r\n ctx.on('session/event', (session, event) => {\r\n runtime?.outbound.handleSessionEvent(String(session.header.id), event as { type: string; data: Record<string, unknown> })\r\n })\r\n\r\n // turn 外错误(无 turn/end 兜底):agent/error → notice 错误摘要 + 释放 inflight(outbound 内去重)。\r\n ctx.on('agent/error', ({ agent, error }) => {\r\n const text = error instanceof Error\r\n ? error.message\r\n : String((error as { message?: unknown } | null)?.message ?? error)\r\n runtime?.outbound.handleAgentError(String(agent.session.id), text)\r\n })\r\n\r\n // webServer 是可选能力(headless 无此服务):经 registerOptionalRoutes 子 fiber 惰性注册\r\n // (token-usage 同款);子 fiber 未激活时惰性、随父 fiber 卸载而清理。\r\n // 仅注册本模块自己的 /dsh-agent-toolkit/api/bots 前缀;agents/providers/tools 核心端点由\r\n // setupAgentsApi 恒启用注册(同前缀下 longest-prefix 匹配、路径互不重叠),本分支不涉足。\r\n registerOptionalRoutes(ctx, (webCtx) => {\r\n // bots handler 请求时才构造:runtime 在 started 落定后才赋值,注册期捕获会拿到 undefined。\r\n const botsHandler: (req: IncomingMessage, res: ServerResponse) => Promise<void> = async (req, res) => {\r\n if (runtime === undefined) throw new Error('runtime unavailable')\r\n await createApiHandler({\r\n bots: botsTable!,\r\n runtime,\r\n registerApp: registerAppService,\r\n listTools: () => ctx.tools.schemas().map((s) => s.name),\r\n listProviders: () => ctx.llm.listProviders().map(({ id, name }) => ({ id, name })),\r\n listModels: (provider) => ctx.llm.listModels(provider).then((models) => models.map(({ id, name }) => ({ id, name }))),\r\n storeSecret,\r\n deleteSecret: async (ref) => ctx.credentials.unset(credentialRef(ref)),\r\n validateProject: (path) => existsSync(path),\r\n now: () => Date.now(),\r\n })(req, res)\r\n }\r\n const dispose = webCtx.webServer.register({\r\n kind: 'prefix',\r\n path: '/dsh-agent-toolkit/api/bots',\r\n handler: async (req, res) => {\r\n try {\r\n // 请求时才等待自身启动链:避免连带失败与注册期捕获 undefined runtime。\r\n await started\r\n await botsHandler(req, res)\r\n } catch (error) {\r\n res.writeHead(500, { 'content-type': 'application/json' })\r\n .end(JSON.stringify({ error: error instanceof Error ? error.message : String(error) }))\r\n }\r\n },\r\n })\r\n return () => dispose()\r\n })\r\n\r\n // 卸载:中断扫码轮询;runtime drain(stopAll)与关存储域的顺序由 openDomainSafely 的 beforeClose 保证。\r\n ctx.effect(() => async () => {\r\n registerAppService.dispose()\r\n })\r\n}\r\n","/** dsh-agent-toolkit 插件总入口:Agent 注册表 + 分层提示词 + 并行委派 + 飞书 bots + token 用量。 */\r\nimport type { Context } from '@deepseek-ai/cordis'\r\nimport type { KvTable } from '@deepseek-ai/dsh-storage-domain'\r\nimport z from '@deepseek-ai/schemastery'\r\nimport { createRegistry } from './agents/registry.ts'\r\nimport { agentToolkitDomain, type AgentRecord } from './agents/store.ts'\r\nimport { openDomainSafely } from './shared/storage.ts'\r\nimport { DEFAULT_LAYERS, DEFAULT_RULES } from './prompt/defaults.ts'\r\nimport { setupPrompt, validateConfig as validatePromptConfig } from './prompt/index.ts'\r\nimport { openLayerSource, type PromptLayersRow } from './prompt/layer-source.ts'\r\nimport { setupPromptLayersApi } from './prompt/api.ts'\r\nimport type { LayerConfig, Rule } from './prompt/types.ts'\r\nimport { setupDelegate } from './delegate/index.ts'\r\nimport { setupAgentsApi } from './agents/api.ts'\r\nimport { setupBots, type BotsModuleConfig } from './bots/index.ts'\r\nimport { setupUsage } from '@dsh-agent-toolkit/token-usage'\r\n\r\nexport const name = 'dsh-agent-toolkit'\r\n\r\n// 全部硬依赖服务(merged 模块直接消费;archive token-usage/project-bot 的 inject 并集)。\r\n// storageDomain(registry/bots/usage 经 openDomainSafely 消费)、tokenMeter(usage)、\r\n// credentials(bots)不在 brief 骨架的 7 项里,但均为插件运行必需,补齐。\r\nexport const inject = [\r\n 'storageDomain',\r\n 'tools',\r\n 'subagents',\r\n 'systemPrompt',\r\n 'commands',\r\n 'llm',\r\n 'agentDefaultModel',\r\n 'agents',\r\n 'tokenMeter',\r\n 'credentials',\r\n]\r\n\r\n/** 插件配置输出型。 */\r\nexport interface Config {\r\n modules: { feishu: boolean; usage: boolean }\r\n layers: LayerConfig[]\r\n rules: Rule[]\r\n timezone: string\r\n provider: string\r\n toolName: string\r\n feishu: BotsModuleConfig\r\n}\r\n\r\n/** layers/rules 的 schemastery schema 照归档 prompt-stack/src/index.ts:21-41 逐字段平移(含 overrides transform hack)。 */\r\nexport const Config: z<unknown, Config> = z.object({\r\n modules: z.object({\r\n feishu: z.boolean().default(true),\r\n usage: z.boolean().default(true),\r\n }).default({ feishu: true, usage: true }),\r\n layers: z.array(z.object({\r\n name: z.string().required(),\r\n order: z.number().required(),\r\n text: z.string().required(),\r\n })).default(DEFAULT_LAYERS),\r\n // 元素 cast 为 z<Rule>:Rule.overrides/append 可选,而 z.object 输出键全必填,\r\n // 直接 .default(DEFAULT_RULES) 会类型不匹配。transform 丢弃空 overrides:\r\n // z.dict 隐式默认 {},会给 append-only 默认规则注入 overrides: {}(破坏\r\n // Config({}) 与 DEFAULT_RULES 的精确相等)。\r\n rules: z.array((z.object({\r\n match: z.object({\r\n provider: z.string(),\r\n model: z.string(),\r\n modelPattern: z.string(),\r\n }).required(),\r\n overrides: z.transform(z.dict(z.string()), value => Object.keys(value).length === 0 ? undefined : value),\r\n append: z.string(),\r\n }) as z<Rule>)).default(DEFAULT_RULES),\r\n timezone: z.string().default('Asia/Shanghai'),\r\n provider: z.string().default('spawn'),\r\n toolName: z.string().default('team_delegate'),\r\n // feishu 6 个全局可调参数照归档 project-bot/src/index.ts:38-45,字段名/默认值原样平移。\r\n feishu: z.object({\r\n cardUpdateThrottleMs: z.number().default(500),\r\n cardMaxBytes: z.number().default(28_000),\r\n processMaxBytes: z.number().default(8_000),\r\n registerAppTimeoutMs: z.number().default(600_000),\r\n processingReactionEmoji: z.string().default('OneSecond'),\r\n errorDetailMaxChars: z.number().default(500),\r\n }).default({\r\n cardUpdateThrottleMs: 500,\r\n cardMaxBytes: 28_000,\r\n processMaxBytes: 8_000,\r\n registerAppTimeoutMs: 600_000,\r\n processingReactionEmoji: 'OneSecond',\r\n errorDetailMaxChars: 500,\r\n }),\r\n}) as z<unknown, Config>\r\n\r\nexport async function apply(ctx: Context, config: Config): Promise<void> {\r\n validatePromptConfig({ layers: config.layers, rules: config.rules })\r\n const warn = (msg: string): void => ctx.logger.warn(msg)\r\n const domain = await openDomainSafely(ctx, agentToolkitDomain, warn)\r\n const tables = {\r\n agents: domain.table('agents') as KvTable<string, AgentRecord>,\r\n meta: domain.table('meta') as KvTable<string, { value: string }>,\r\n promptLayers: domain.table('prompt_layers') as KvTable<string, PromptLayersRow>,\r\n }\r\n const registry = await createRegistry(warn, { agents: tables.agents, meta: tables.meta })\r\n const layerSource = await openLayerSource({ promptLayers: tables.promptLayers, meta: tables.meta }, config.layers)\r\n setupPrompt(ctx, { source: layerSource, rules: config.rules })\r\n setupDelegate(ctx, {\r\n provider: config.provider,\r\n toolName: config.toolName,\r\n rules: config.rules,\r\n }, registry)\r\n // agents/providers/tools RPC 为核心恒启用(Agents 面板总是挂载,端点缺失即「加载失败」),\r\n // 不随 modules.feishu 门控;仅 bots 分支受 feishu 开关控制。\r\n setupAgentsApi(ctx, {\r\n registry,\r\n listTools: () => ctx.tools.schemas().map((s) => s.name),\r\n listProviders: () => ctx.llm.listProviders().map(({ id, name }) => ({ id, name })),\r\n listModels: (provider) => ctx.llm.listModels(provider).then((models) => models.map(({ id, name }) => ({ id, name }))),\r\n })\r\n setupPromptLayersApi(ctx, {\r\n source: layerSource,\r\n rules: config.rules,\r\n seedLayers: config.layers,\r\n // 裸组装探测:面板只读区展示原生 sections 与动态层 contexts 的当前快照。\r\n probe: async () => {\r\n const assembly = await ctx.systemPrompt.assemble({})\r\n return {\r\n sections: assembly.sections.map(({ name: n, text }) => ({ name: n, text })),\r\n contexts: assembly.contexts.map(({ name: n, text }) => ({ name: n, text })),\r\n }\r\n },\r\n })\r\n if (config.modules.feishu) setupBots(ctx, config.feishu, { registry })\r\n if (config.modules.usage) setupUsage(ctx, { timezone: config.timezone }, name)\r\n}\r\n"],"mappings":"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"}