@whispering233/ai-editor-server 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/client-dist/assets/index-Bi1eymph.js +14 -0
  2. package/client-dist/assets/index-j-zzWAuh.css +1 -0
  3. package/client-dist/index.html +22 -0
  4. package/dist/consistency.d.ts +33 -0
  5. package/dist/consistency.d.ts.map +1 -0
  6. package/dist/consistency.js +53 -0
  7. package/dist/consistency.js.map +1 -0
  8. package/dist/debug.d.ts +29 -0
  9. package/dist/debug.d.ts.map +1 -0
  10. package/dist/debug.js +105 -0
  11. package/dist/debug.js.map +1 -0
  12. package/dist/index.d.ts +61 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +284 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/middleware/error.d.ts +40 -0
  17. package/dist/middleware/error.d.ts.map +1 -0
  18. package/dist/middleware/error.js +64 -0
  19. package/dist/middleware/error.js.map +1 -0
  20. package/dist/middleware/project.d.ts +67 -0
  21. package/dist/middleware/project.d.ts.map +1 -0
  22. package/dist/middleware/project.js +146 -0
  23. package/dist/middleware/project.js.map +1 -0
  24. package/dist/routes/chat.d.ts +98 -0
  25. package/dist/routes/chat.d.ts.map +1 -0
  26. package/dist/routes/chat.js +478 -0
  27. package/dist/routes/chat.js.map +1 -0
  28. package/dist/routes/delta.d.ts +4 -0
  29. package/dist/routes/delta.d.ts.map +1 -0
  30. package/dist/routes/delta.js +144 -0
  31. package/dist/routes/delta.js.map +1 -0
  32. package/dist/routes/entity.d.ts +7 -0
  33. package/dist/routes/entity.d.ts.map +1 -0
  34. package/dist/routes/entity.js +126 -0
  35. package/dist/routes/entity.js.map +1 -0
  36. package/dist/routes/outline.d.ts +11 -0
  37. package/dist/routes/outline.d.ts.map +1 -0
  38. package/dist/routes/outline.js +250 -0
  39. package/dist/routes/outline.js.map +1 -0
  40. package/dist/routes/project.d.ts +27 -0
  41. package/dist/routes/project.d.ts.map +1 -0
  42. package/dist/routes/project.js +552 -0
  43. package/dist/routes/project.js.map +1 -0
  44. package/dist/routes/proposal.d.ts +4 -0
  45. package/dist/routes/proposal.d.ts.map +1 -0
  46. package/dist/routes/proposal.js +145 -0
  47. package/dist/routes/proposal.js.map +1 -0
  48. package/dist/routes/relation.d.ts +6 -0
  49. package/dist/routes/relation.d.ts.map +1 -0
  50. package/dist/routes/relation.js +87 -0
  51. package/dist/routes/relation.js.map +1 -0
  52. package/dist/routes/settings.d.ts +37 -0
  53. package/dist/routes/settings.d.ts.map +1 -0
  54. package/dist/routes/settings.js +91 -0
  55. package/dist/routes/settings.js.map +1 -0
  56. package/dist/routes/trash.d.ts +4 -0
  57. package/dist/routes/trash.d.ts.map +1 -0
  58. package/dist/routes/trash.js +135 -0
  59. package/dist/routes/trash.js.map +1 -0
  60. package/package.json +48 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/middleware/project.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ import { Hono, type Context } from "hono";
2
+ import { type z } from "zod";
3
+ import { type AgentEvent, type ProposalStore, type RunAgentDeps, type ToolDispatcher } from "@whispering233/ai-editor-agent";
4
+ import type { LLMToolDefinition } from "@whispering233/ai-editor-llm";
5
+ import { type ToolDefinition } from "@whispering233/ai-editor-tools";
6
+ /** 心跳间隔(决策 20:15-30s 随机;测试经 deps.heartbeat 覆盖为毫秒级) */
7
+ export declare const DEFAULT_HEARTBEAT_MS: {
8
+ readonly minMs: 15000;
9
+ readonly maxMs: 30000;
10
+ };
11
+ /** 续聊历史重建的条数上限(超限按尾部保留——决策 6 的 token 裁剪由 S7.2 buildContext
12
+ * 按预算二次兜底,此处仅防御病态超长会话的加载开销) */
13
+ export declare const SESSION_HISTORY_MAX_MESSAGES = 2000;
14
+ /**
15
+ * 单个工具 argsSchema(zod)→ OpenAI 兼容 JSON Schema(LLMToolDefinition.parameters)。
16
+ * 方案:**zod 4 内置 toJSONSchema**(`import { toJSONSchema } from "zod"`,v4.4+ 自带,
17
+ * 无新增依赖)——32 个工具参数均为简单对象 + string/enum/array/record/literal/union 字段,
18
+ * 内置转换全覆盖且输出 draft 2020-12 合法 schema(`.strict()` → additionalProperties:false、
19
+ * `.refine()` 仅影响校验不改变类型 schema、`z.record` → propertyNames 形态)。
20
+ * 仅剥离顶层 `$schema` 关键字——OpenAI 兼容端点(含 DeepSeek)对 parameters 内未知关键字
21
+ * 存在严格模式拒绝风险,剥离后零风险(其余关键字为标准 JSON Schema 内容,兼容)。
22
+ */
23
+ export declare function zodArgsToJsonSchema(schema: z.ZodTypeAny): Record<string, unknown>;
24
+ /**
25
+ * registry 工具定义 → LLM function calling 工具定义(决策点:只转换 AUTO + PROPOSAL 权限的
26
+ * 32 个工具——listTools 已不注册执行类(S6.7 核心设计原则「AI 只能提案不能直接写」),
27
+ * 此处权限过滤为双保险:未来误注册执行类工具也不会暴露给模型)。
28
+ */
29
+ export declare function toLLMToolDefinitions(defs: readonly ToolDefinition[]): LLMToolDefinition[];
30
+ /**
31
+ * [llm] 请求调试日志装饰器:给 produce 包一层(真实路径经
32
+ * `createLLMRequestLogger(createRealProduce(...), { model, tools })` 组装),对应类别开启时:
33
+ * - **request 日志**(类别 request):模型名 + 请求参数 + **完整 messages JSON(不截断——
34
+ * 用户核心诉求「最终组装的 prompt」)** + 工具名列表;每轮每次 attempt 各打一次(含重试)
35
+ * - **usage 日志**(类别 usage):onEvent 转发处捕获 finish 事件,打真实 token 数
36
+ * (需求 3,流内真实 usage)——与 request **分开判定**(categories: ["request","usage"]
37
+ * 时只显示请求与 tokens 统计)
38
+ * - **敏感红线**:只打印请求体(messages 本身无 key——key 走 fetch header),
39
+ * 绝不打印 apiKey / headers
40
+ * - 两类别全关(request + usage 均未开启)时**零开销直通**:不包装 onEvent、不拼接字符串
41
+ * 独立成装饰器而非塞进 createRealProduce:测试可用 mock produce 直测日志层,
42
+ * 不经真实 DeepSeek 网络调用(与 createChatEventLogger 的「工厂 + 组合」同款模式)。
43
+ * 注:produce 契约(run.ts)不含 maxTokens/temperature(当前无对应配置),如实标注 <未设置>。
44
+ */
45
+ export declare function createLLMRequestLogger(produce: RunAgentDeps["produce"], ctx: {
46
+ model: string;
47
+ tools: LLMToolDefinition[];
48
+ }): RunAgentDeps["produce"];
49
+ /** POST /chat 可注入依赖(全部可选;缺省走真实实现。测试注入 mock 避免真实 DeepSeek 调用) */
50
+ export interface ChatRouteDeps {
51
+ /** 测试注入:produce 覆盖(缺省构造真实 chatStream 闭包;提供时无需真实 apiKey) */
52
+ produce?: RunAgentDeps["produce"];
53
+ /** 测试注入:工具调度器覆盖(缺省 createToolDispatcher({db, outlineDir, projectId}, {store})) */
54
+ dispatcher?: ToolDispatcher;
55
+ /** 提案仓(缺省 defaultProposalStore 单例——与 S7.5 confirm/reject 同仓;测试注入独立实例隔离) */
56
+ store?: ProposalStore;
57
+ /** 心跳间隔覆盖 ms(缺省 15-30s 随机,决策 20;测试注入毫秒级) */
58
+ heartbeat?: {
59
+ minMs: number;
60
+ maxMs: number;
61
+ };
62
+ /** 时间注入(缺省 db nowIso——应用层写 ISO 8601 约定) */
63
+ now?: () => string;
64
+ /** 模型名覆盖(缺省设置页模型或 DEFAULT_MODEL) */
65
+ model?: string;
66
+ /** apiKey 覆盖(缺省 effectiveApiKey() 环境变量 > 用户级配置,决策 17) */
67
+ apiKey?: string;
68
+ /** 已转换工具定义覆盖(缺省 listTools → toLLMToolDefinitions) */
69
+ tools?: LLMToolDefinition[];
70
+ /** 续聊历史条数上限覆盖(缺省 SESSION_HISTORY_MAX_MESSAGES;测试可收紧) */
71
+ sessionHistoryMaxCount?: number;
72
+ }
73
+ /**
74
+ * 创建 [chat] 事件调试日志器(对话链路调试,打到服务端终端 stdout/stderr;类别 chat):
75
+ * - 类别未开启(配置文件未列 chat 且 env 关)时零开销早退——不做任何字符串拼接
76
+ * (onEvent 高频路径无条件调用)
77
+ * - turn_start → 轮次;tool_call → 工具名 + 参数 JSON 摘要(截断);tool_result → 工具名 + 结果
78
+ * 摘要(截断);proposal → proposal_id + type;text → **只打 delta 长度**(流式高频防刷屏);
79
+ * done → sessionId + 轮次;error → code + message
80
+ * - 注:AgentEvent.tool_result 契约(run.ts)不含 ok/isError 字段——工具成败已编码进 result
81
+ * 文本(失败为错误说明),日志只摘要该文本
82
+ */
83
+ export declare function createChatEventLogger(): (event: AgentEvent) => void;
84
+ /**
85
+ * POST /chat 处理器工厂(测试经 createChatRoutes 注入 deps)。
86
+ * 流程:项目/请求校验(JSON 错误,不开流)→ 会话解析(历史重建或新建 sess_)→ 用户消息落库
87
+ * (决策 18)→ 三路断开检测挂接 → SSE 流内:心跳协程 + runAgent(produce/dispatcher 组装、
88
+ * onEvent 转 SSE 帧、onMessages 落库)→ 取消作废提案(决策 16,B2 取舍见下)→ 关流。
89
+ */
90
+ export declare function chatSendHandler(deps?: ChatRouteDeps): (c: Context) => Promise<Response>;
91
+ /**
92
+ * 创建对话路由(S7.6 起支持 deps 注入:测试经 createChatRoutes({ produce: mock, ... }) 构造
93
+ * 独立实例挂载测试 app,避免真实 DeepSeek 调用;index.ts 挂载默认实例)。
94
+ */
95
+ export declare function createChatRoutes(deps?: ChatRouteDeps): Hono;
96
+ /** 默认对话路由实例(index.ts 挂载于 /api/v1/chat) */
97
+ export declare const chatRoutes: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
98
+ //# sourceMappingURL=chat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/routes/chat.ts"],"names":[],"mappings":"AAgCA,OAAO,EAAE,IAAI,EAAE,KAAK,OAAO,EAAE,MAAM,MAAM,CAAC;AAE1C,OAAO,EAAgB,KAAK,CAAC,EAAE,MAAM,KAAK,CAAC;AAC3C,OAAO,EAKL,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,YAAY,EAGjB,KAAK,cAAc,EACpB,MAAM,gCAAgC,CAAC;AAExC,OAAO,KAAK,EAA+C,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACnH,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAqBhF,sDAAsD;AACtD,eAAO,MAAM,oBAAoB;;;CAA4C,CAAC;AAE9E;+BAC+B;AAC/B,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAIjD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAIjF;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,SAAS,cAAc,EAAE,GAAG,iBAAiB,EAAE,CAQzF;AAsBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,YAAY,CAAC,SAAS,CAAC,EAChC,GAAG,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,iBAAiB,EAAE,CAAA;CAAE,GACjD,YAAY,CAAC,SAAS,CAAC,CA4BzB;AAID,gEAAgE;AAChE,MAAM,WAAW,aAAa;IAC5B,2DAA2D;IAC3D,OAAO,CAAC,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC;IAClC,kFAAkF;IAClF,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,2EAA2E;IAC3E,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,4CAA4C;IAC5C,SAAS,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,2CAA2C;IAC3C,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qDAAqD;IACrD,KAAK,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC5B,wDAAwD;IACxD,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAwED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,IAAI,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CA6BnE;AAID;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,GAAE,aAAkB,GAAG,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAqN3F;AAID;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,GAAE,aAAkB,GAAG,IAAI,CAc/D;AAED,0CAA0C;AAC1C,eAAO,MAAM,UAAU,4EAAqB,CAAC"}
@@ -0,0 +1,478 @@
1
+ // 对话路由(U3 切片 1 + S7.6):GET /api/v1/chat/sessions、GET /api/v1/chat/sessions/:id/messages、
2
+ // POST /api/v1/chat(POST + SSE 对话端点,切片 7 最后一张卡)
3
+ //
4
+ // 契约来源:
5
+ // - doc/api/endpoints.md 第 752-803 行(POST /api/v1/chat 整节:Req { message, session_id?,
6
+ // context? };SSE 事件 ping/tool_call/tool_result/text/proposal/done/error 与 data 形态;
7
+ // 顺序与生命周期约定——proposal 在对应 tool_result 后、循环继续前,error 后流立即关闭,
8
+ // 确认/拒绝提案与 SSE 生命周期解耦;客户端解析约束——POST+SSE,EventSource 不支持)
9
+ // - doc/design/decisions.md 决策 16(SSE 断开全链路取消:AbortController 终止 agent 循环、
10
+ // 中止 DeepSeek fetch;未确认提案按产生它的会话作废——本文件 B2 取舍见 cancel 后注释)、
11
+ // 决策 17(key 来源:环境变量 DEEPSEEK_API_KEY > ~/.ai-editor/config.json,settings.ts
12
+ // 的 effectiveApiKey 解析)、决策 18(chat_messages 持久化:用户/assistant/tool 消息落库、
13
+ // tool_calls/tool_call_id 配对列)、决策 20(心跳 15-30s + 三路断开检测 + 半开连接限制)
14
+ // - S7.3 run.ts(runAgent 输入输出契约:produce 闭包转发 onEvent 给 chatStream、失败 resolve
15
+ // 不 throw;onMessages 每轮输出 [assistant, ...tool 结果],用户消息自行持久化;AgentEvent
16
+ // 六类事件 + turn_start——本文件只转 SSE 帧、不产生事件)
17
+ // - S7.4 executor.ts(createToolDispatcher 真实现;提案仓 defaultProposalStore)
18
+ // - S6.1 llm client.ts(chatStream:tools 需 OpenAI function schema 格式)
19
+ // - S6.3-S6.6 registry.ts(listTools 32 个 AUTO+PROPOSAL 工具;执行类不注册不暴露——
20
+ // 本文件 zod schema → JSON Schema 转换,zod 4 内置 toJSONSchema,无新依赖)
21
+ //
22
+ // 语义约定:
23
+ // - 无当前项目 → 409 NO_PROJECT_OPEN(requireCurrentProject,与其他业务路由一致)
24
+ // - 请求体校验失败 → 400 VALIDATION_ERROR(JSON,非 SSE——校验在开流之前)
25
+ // - 未配置 DeepSeek key → 400 LLM_API_KEY_MISSING(决策 17;同样在开流之前,JSON)
26
+ // - session_id 提供 → 按项目加载历史重建 SessionState(跨项目 session_id 加载为空数组——
27
+ // 与 GET /messages 的「不泄露存在性」语义一致,新消息按当前项目写入)
28
+ // - session_id 缺省 → generateRuntimeId("session") 新建 sess_ 会话(endpoints.md id 约定)
29
+ //
30
+ // 可测试性:路由经 createChatRoutes(deps) 工厂构造——测试注入 mock produce/dispatcher/心跳/
31
+ // 时间/提案仓,避免真实 DeepSeek 调用与全局单例污染;index.ts 挂载默认实例 chatRoutes。
32
+ import { Hono } from "hono";
33
+ import { streamSSE } from "hono/streaming";
34
+ import { toJSONSchema } from "zod";
35
+ import { createToolDispatcher, defaultProposalStore, restoreSession, runAgent, } from "@whispering233/ai-editor-agent";
36
+ import { chatStream } from "@whispering233/ai-editor-llm";
37
+ import { listTools } from "@whispering233/ai-editor-tools";
38
+ import { findOutlineNode, getEntity, insertChatMessage, listMessageRows, listMessages, listSessions, nowIso, readOutlineFile, } from "@whispering233/ai-editor-db";
39
+ import { TOOL_PERMISSION, generateRuntimeId } from "@whispering233/ai-editor-shared";
40
+ import { chatMessagesResSchema, chatSendReqSchema, chatSessionsResSchema } from "@whispering233/ai-editor-shared/schemas";
41
+ import { HttpError, ok } from "../middleware/error.js";
42
+ import { requireCurrentProject } from "../middleware/project.js";
43
+ import { debugLog, isCategoryEnabled } from "../debug.js";
44
+ import { DEFAULT_MODEL, effectiveApiKey, getUserConfig } from "./settings.js";
45
+ // ============ 常量 ============
46
+ /** 心跳间隔(决策 20:15-30s 随机;测试经 deps.heartbeat 覆盖为毫秒级) */
47
+ export const DEFAULT_HEARTBEAT_MS = { minMs: 15_000, maxMs: 30_000 };
48
+ /** 续聊历史重建的条数上限(超限按尾部保留——决策 6 的 token 裁剪由 S7.2 buildContext
49
+ * 按预算二次兜底,此处仅防御病态超长会话的加载开销) */
50
+ export const SESSION_HISTORY_MAX_MESSAGES = 2000;
51
+ // ============ zod → JSON Schema(OpenAI function calling 格式) ============
52
+ /**
53
+ * 单个工具 argsSchema(zod)→ OpenAI 兼容 JSON Schema(LLMToolDefinition.parameters)。
54
+ * 方案:**zod 4 内置 toJSONSchema**(`import { toJSONSchema } from "zod"`,v4.4+ 自带,
55
+ * 无新增依赖)——32 个工具参数均为简单对象 + string/enum/array/record/literal/union 字段,
56
+ * 内置转换全覆盖且输出 draft 2020-12 合法 schema(`.strict()` → additionalProperties:false、
57
+ * `.refine()` 仅影响校验不改变类型 schema、`z.record` → propertyNames 形态)。
58
+ * 仅剥离顶层 `$schema` 关键字——OpenAI 兼容端点(含 DeepSeek)对 parameters 内未知关键字
59
+ * 存在严格模式拒绝风险,剥离后零风险(其余关键字为标准 JSON Schema 内容,兼容)。
60
+ */
61
+ export function zodArgsToJsonSchema(schema) {
62
+ const js = toJSONSchema(schema);
63
+ delete js.$schema;
64
+ return js;
65
+ }
66
+ /**
67
+ * registry 工具定义 → LLM function calling 工具定义(决策点:只转换 AUTO + PROPOSAL 权限的
68
+ * 32 个工具——listTools 已不注册执行类(S6.7 核心设计原则「AI 只能提案不能直接写」),
69
+ * 此处权限过滤为双保险:未来误注册执行类工具也不会暴露给模型)。
70
+ */
71
+ export function toLLMToolDefinitions(defs) {
72
+ return defs
73
+ .filter((d) => d.permission === TOOL_PERMISSION.AUTO || d.permission === TOOL_PERMISSION.PROPOSAL)
74
+ .map((d) => ({
75
+ name: d.name,
76
+ description: d.description,
77
+ parameters: zodArgsToJsonSchema(d.argsSchema),
78
+ }));
79
+ }
80
+ // ============ 真实 produce / dispatcher 构造 ============
81
+ /**
82
+ * 真实 produce 闭包(S7.3 契约:把 onEvent 转发给 chatStream 的 onEvent——runAgent 依赖它
83
+ * 累积文本与收集工具调用;失败按 chatStream 契约 resolve 出 { ok:false, ... } 不 throw;
84
+ * signal 由 runAgent 注入 attempt 级独立控制器——超时 abort 与用户取消分离,决策 15)。
85
+ */
86
+ function createRealProduce(apiKey, model, tools, debugStream) {
87
+ return (messages, signal, onEvent) =>
88
+ // debugStream 显式传布尔(含 false)——stream 类别关时压过 env,保证配置文件类别隔离语义
89
+ chatStream({ apiKey, model, messages, tools, signal, onEvent, debugStream });
90
+ }
91
+ // ============ [llm] 请求 / usage 调试日志装饰器(细粒度类别 request / usage) ============
92
+ /**
93
+ * [llm] 请求调试日志装饰器:给 produce 包一层(真实路径经
94
+ * `createLLMRequestLogger(createRealProduce(...), { model, tools })` 组装),对应类别开启时:
95
+ * - **request 日志**(类别 request):模型名 + 请求参数 + **完整 messages JSON(不截断——
96
+ * 用户核心诉求「最终组装的 prompt」)** + 工具名列表;每轮每次 attempt 各打一次(含重试)
97
+ * - **usage 日志**(类别 usage):onEvent 转发处捕获 finish 事件,打真实 token 数
98
+ * (需求 3,流内真实 usage)——与 request **分开判定**(categories: ["request","usage"]
99
+ * 时只显示请求与 tokens 统计)
100
+ * - **敏感红线**:只打印请求体(messages 本身无 key——key 走 fetch header),
101
+ * 绝不打印 apiKey / headers
102
+ * - 两类别全关(request + usage 均未开启)时**零开销直通**:不包装 onEvent、不拼接字符串
103
+ * 独立成装饰器而非塞进 createRealProduce:测试可用 mock produce 直测日志层,
104
+ * 不经真实 DeepSeek 网络调用(与 createChatEventLogger 的「工厂 + 组合」同款模式)。
105
+ * 注:produce 契约(run.ts)不含 maxTokens/temperature(当前无对应配置),如实标注 <未设置>。
106
+ */
107
+ export function createLLMRequestLogger(produce, ctx) {
108
+ const toolNames = ctx.tools.map((t) => t.name).join(", ");
109
+ return (messages, signal, onEvent) => {
110
+ // 两类别全关:零开销直通(不包装 onEvent、不拼接字符串)
111
+ if (!isCategoryEnabled("request") && !isCategoryEnabled("usage")) {
112
+ return produce(messages, signal, onEvent);
113
+ }
114
+ if (isCategoryEnabled("request")) {
115
+ debugLog("request", "llm", `request model=${ctx.model} max_tokens=<未设置> temperature=<未设置> tools=[${toolNames}]`);
116
+ debugLog("request", "llm", `request messages=${JSON.stringify(messages, null, 2)}`); // 完整打印不截断
117
+ }
118
+ // usage 类别开启时才需要包装 onEvent(捕获 finish 事件)
119
+ const loggedOnEvent = isCategoryEnabled("usage") && onEvent
120
+ ? (event) => {
121
+ if (event.type === "finish") {
122
+ const u = event.usage;
123
+ debugLog("usage", "llm", `usage prompt_tokens=${u?.prompt_tokens ?? "?"} completion_tokens=${u?.completion_tokens ?? "?"} total=${u?.total_tokens ?? "?"} stop=${event.stopReason}`);
124
+ }
125
+ onEvent(event); // 原样转发(日志先于事件)
126
+ }
127
+ : onEvent;
128
+ return produce(messages, signal, loggedOnEvent);
129
+ };
130
+ }
131
+ // ============ 聚焦上下文拼装(S7.2 输入形态) ============
132
+ /**
133
+ * 聚焦上下文文本(决策 6 聚焦层):focus_entity_* → getEntity 查询实体、focus_node_id →
134
+ * 大纲节点查询,拼成结构化文本注入 system 聚焦消息。
135
+ * 查询不到(已软删/不存在/跨项目)→ 跳过该项(不报错)——聚焦缺失不阻断对话,属防御性
136
+ * 正常路径(客户端可能携带过期 focus 发送);两项皆无 → undefined(无聚焦注入)。
137
+ */
138
+ function buildFocusText(project, context) {
139
+ const parts = [];
140
+ if (context?.focus_entity_id !== undefined) {
141
+ const row = getEntity(project.db, context.focus_entity_id);
142
+ if (row !== null) {
143
+ parts.push(`实体:${row.type}「${row.name}」(id=${row.id})\n数据:${JSON.stringify(row.data)}`);
144
+ }
145
+ }
146
+ if (context?.focus_node_id !== undefined) {
147
+ const node = findOutlineNode(readOutlineFile(project.root), context.focus_node_id);
148
+ if (node !== undefined && node.deleted !== true) {
149
+ parts.push(`大纲节点:${node.type}「${node.title}」(id=${node.id})${node.summary ? `\n摘要:${node.summary}` : ""}`);
150
+ }
151
+ }
152
+ return parts.length > 0 ? parts.join("\n\n") : undefined;
153
+ }
154
+ // ============ 内部辅助 ============
155
+ /** 可中止 sleep:任一 signal 触发即提前返回(心跳停止 / 断连即时唤醒,不空等满间隔) */
156
+ function sleepAbortable(ms, signals) {
157
+ return new Promise((resolve) => {
158
+ if (signals.some((s) => s.aborted)) {
159
+ resolve();
160
+ return;
161
+ }
162
+ const onAbort = () => {
163
+ clearTimeout(timer);
164
+ resolve();
165
+ };
166
+ const timer = setTimeout(() => {
167
+ for (const s of signals)
168
+ s.removeEventListener("abort", onAbort);
169
+ resolve();
170
+ }, ms);
171
+ for (const s of signals)
172
+ s.addEventListener("abort", onAbort, { once: true });
173
+ });
174
+ }
175
+ // ============ [chat] 事件调试日志(配置文件 chat 类别) ============
176
+ /** 调试日志字段摘要长度上限(tool_call args / tool_result 长文本截断,防刷屏) */
177
+ const DEBUG_FIELD_MAX = 200;
178
+ /**
179
+ * 调试日志字段摘要:字符串原样、对象 JSON 序列化,超长截断并标注原长。
180
+ * 仅在调试开启时被调用(createChatEventLogger 内部早退),关闭时零开销。
181
+ */
182
+ function debugSummary(value, max = DEBUG_FIELD_MAX) {
183
+ let text;
184
+ try {
185
+ text = typeof value === "string" ? value : JSON.stringify(value) ?? "undefined";
186
+ }
187
+ catch {
188
+ text = String(value);
189
+ }
190
+ return text.length > max ? `${text.slice(0, max)}…(${text.length} 字符)` : text;
191
+ }
192
+ /**
193
+ * 创建 [chat] 事件调试日志器(对话链路调试,打到服务端终端 stdout/stderr;类别 chat):
194
+ * - 类别未开启(配置文件未列 chat 且 env 关)时零开销早退——不做任何字符串拼接
195
+ * (onEvent 高频路径无条件调用)
196
+ * - turn_start → 轮次;tool_call → 工具名 + 参数 JSON 摘要(截断);tool_result → 工具名 + 结果
197
+ * 摘要(截断);proposal → proposal_id + type;text → **只打 delta 长度**(流式高频防刷屏);
198
+ * done → sessionId + 轮次;error → code + message
199
+ * - 注:AgentEvent.tool_result 契约(run.ts)不含 ok/isError 字段——工具成败已编码进 result
200
+ * 文本(失败为错误说明),日志只摘要该文本
201
+ */
202
+ export function createChatEventLogger() {
203
+ let round = 0; // 轮次计数器(turn_start 刷新;done 事件附带——AgentEvent.done 无轮次字段)
204
+ return (event) => {
205
+ if (!isCategoryEnabled("chat"))
206
+ return; // 短路由早退:类别未开时不产生任何字符串拼接
207
+ switch (event.type) {
208
+ case "turn_start":
209
+ round = event.round;
210
+ debugLog("chat", "chat", `turn_start round=${event.round}`);
211
+ return;
212
+ case "text":
213
+ debugLog("chat", "chat", `text delta=+${event.delta.length} 字符`); // 只打长度不打内容
214
+ return;
215
+ case "tool_call":
216
+ debugLog("chat", "chat", `tool_call tool=${event.tool} id=${event.id} args=${debugSummary(event.args)}`);
217
+ return;
218
+ case "tool_result":
219
+ debugLog("chat", "chat", `tool_result tool=${event.tool} id=${event.id} result=${debugSummary(event.result)}`);
220
+ return;
221
+ case "proposal":
222
+ debugLog("chat", "chat", `proposal id=${event.proposal.proposal_id} type=${event.proposal.type}`);
223
+ return;
224
+ case "done":
225
+ debugLog("chat", "chat", `done session=${event.sessionId} round=${round}`);
226
+ return;
227
+ case "error":
228
+ debugLog("chat", "chat", `error code=${event.code} message=${event.message} aborted=${event.aborted}`);
229
+ return;
230
+ }
231
+ };
232
+ }
233
+ // ============ POST /api/v1/chat(S7.6:POST + SSE 对话端点) ============
234
+ /**
235
+ * POST /chat 处理器工厂(测试经 createChatRoutes 注入 deps)。
236
+ * 流程:项目/请求校验(JSON 错误,不开流)→ 会话解析(历史重建或新建 sess_)→ 用户消息落库
237
+ * (决策 18)→ 三路断开检测挂接 → SSE 流内:心跳协程 + runAgent(produce/dispatcher 组装、
238
+ * onEvent 转 SSE 帧、onMessages 落库)→ 取消作废提案(决策 16,B2 取舍见下)→ 关流。
239
+ */
240
+ export function chatSendHandler(deps = {}) {
241
+ return async (c) => {
242
+ const project = requireCurrentProject();
243
+ // ---- 请求校验(开流之前:失败走统一 JSON 错误,非 SSE) ----
244
+ const raw = await c.req.json().catch(() => null); // 空 body / 非法 JSON → 校验失败
245
+ const parsed = chatSendReqSchema.safeParse(raw);
246
+ if (!parsed.success) {
247
+ throw parsed.error; // → app.onError → 400 VALIDATION_ERROR(含 fields)
248
+ }
249
+ const { message, session_id, context } = parsed.data;
250
+ // ---- key/模型/工具解析(决策 17:环境变量 > 用户级配置;测试注入 deps 时无需真实 key) ----
251
+ const envKey = deps.apiKey ?? effectiveApiKey().key;
252
+ if (envKey === null && deps.produce === undefined) {
253
+ throw new HttpError(400, "LLM_API_KEY_MISSING", "未配置 DeepSeek API key:请设置环境变量 DEEPSEEK_API_KEY 或在设置页配置(决策 17)");
254
+ }
255
+ // 守卫收窄:deps.produce 注入(测试)时不使用 apiKey;否则 envKey 已保证非 null
256
+ const apiKey = envKey ?? "";
257
+ const model = deps.model ?? getUserConfig().model ?? DEFAULT_MODEL;
258
+ const tools = deps.tools ?? toLLMToolDefinitions(listTools());
259
+ const store = deps.store ?? defaultProposalStore;
260
+ const now = deps.now ?? nowIso;
261
+ return streamSSE(c, async (stream) => {
262
+ // ---- 1. 会话解析(决策 18 续聊重建) ----
263
+ const sessionId = session_id ?? generateRuntimeId("session");
264
+ // 跨项目 session_id:listMessageRows 按项目过滤 → 空历史(不泄露存在性,与 GET 一致);
265
+ // 后续写入按当前项目——单项目 MVP 下等价于「该项目内的续聊」,注释留扩展点
266
+ const session = session_id === undefined
267
+ ? []
268
+ : restoreSession(listMessageRows(project.db, sessionId, project.config.id), deps.sessionHistoryMaxCount ?? SESSION_HISTORY_MAX_MESSAGES);
269
+ // ---- 2. 聚焦上下文(决策 6;查不到跳过,不阻断) ----
270
+ const focus = buildFocusText(project, context);
271
+ // ---- 3. 用户消息落库(决策 18;assistant/tool 消息由 onMessages 落库) ----
272
+ insertChatMessage(project.db, {
273
+ session_id: sessionId,
274
+ project_id: project.config.id,
275
+ role: "user",
276
+ content: message,
277
+ created_at: now(),
278
+ });
279
+ // ---- 4. 取消信号 + 三路断开检测(决策 16/20) ----
280
+ // controller.signal 即 runAgent 的 signal(决策 16 全链路第 0 层——四层穿透的
281
+ // fetch/读循环/工具执行/重试 sleep 已由 llm/tools/agent 各层承担,本卡链路总装)
282
+ const controller = new AbortController();
283
+ const cancel = () => {
284
+ if (!controller.signal.aborted)
285
+ controller.abort();
286
+ };
287
+ // ① stream.onAbort:客户端断开 → 响应流 cancel → Hono StreamingApi.abort() → 本回调
288
+ stream.onAbort(cancel);
289
+ // ② c.req.raw 的 close/error 监听:@hono/node-server v2 的 c.req.raw 是标准 Request
290
+ // (无 close 事件,signal 随请求中止触发)——两种形态按能力探测都挂上,双保险
291
+ c.req.raw.signal.addEventListener("abort", cancel, { once: true });
292
+ const rawReq = c.req.raw;
293
+ if (typeof rawReq.on === "function") {
294
+ rawReq.on("close", cancel);
295
+ rawReq.on("error", cancel);
296
+ }
297
+ // ③ 心跳写失败:Hono write() 吞错无法从 promise 观察写失败(stream.js write try/catch)
298
+ // ——断连时 ① 已同步置位 controller.signal,心跳每次写后复查该旗标兜底
299
+ // (时延 ≤ 心跳间隔,决策 20 三路并用中的最后一道防线)
300
+ // ---- 5. SSE 写帧器(endpoints.md 事件契约;断连后不再写) ----
301
+ const writeEvent = async (event, data) => {
302
+ if (controller.signal.aborted)
303
+ return; // 已断开:写也失败,跳过
304
+ try {
305
+ await stream.writeSSE({ event, data: JSON.stringify(data) });
306
+ }
307
+ catch {
308
+ cancel(); // 写抛错(writeSSE 理论上吞错,防御路径)
309
+ }
310
+ };
311
+ // ---- 6. 心跳协程(决策 20:15-30s 随机 ping;停止/断连即时唤醒退出) ----
312
+ const heartbeatStop = new AbortController();
313
+ const heartbeat = (async () => {
314
+ const { minMs, maxMs } = deps.heartbeat ?? DEFAULT_HEARTBEAT_MS;
315
+ while (!heartbeatStop.signal.aborted) {
316
+ const ms = minMs + Math.floor(Math.random() * (maxMs - minMs + 1));
317
+ await sleepAbortable(ms, [heartbeatStop.signal, controller.signal]);
318
+ if (heartbeatStop.signal.aborted || controller.signal.aborted)
319
+ return;
320
+ await stream.writeSSE({ event: "ping", data: "{}" });
321
+ // ③ 写后复查:客户端断开时 onAbort 已置位 controller(见第 4 步注释)
322
+ if (controller.signal.aborted)
323
+ return;
324
+ }
325
+ })();
326
+ // ---- 7. onEvent → SSE 帧(AgentEvent 六类 + turn_start;proposal 顺序由 runAgent 保证) ----
327
+ // 帧写入经 void 异步排入 writer(WritableStream FIFO 保证顺序,await 仅背压)——
328
+ // 事件回调恒同步返回,不阻塞 runAgent 循环
329
+ const logChatEvent = createChatEventLogger(); // [chat] 调试日志(chat 类别;关闭时零开销)
330
+ const onEvent = (event) => {
331
+ logChatEvent(event); // 对话链路调试:工具调用/提案/文本增量长度等打到服务端终端
332
+ switch (event.type) {
333
+ case "turn_start":
334
+ return; // 循环内部事件:不映射 SSE 帧(日志/调试用)
335
+ case "text":
336
+ void writeEvent("text", { delta: event.delta });
337
+ return;
338
+ case "tool_call":
339
+ void writeEvent("tool_call", { tool: event.tool, args: event.args, id: event.id });
340
+ return;
341
+ case "tool_result":
342
+ void writeEvent("tool_result", { tool: event.tool, result: event.result, id: event.id });
343
+ return;
344
+ case "proposal":
345
+ // endpoints.md:proposal 在对应 tool_result 之后、循环继续之前(runAgent 保证)
346
+ void writeEvent("proposal", {
347
+ proposal_id: event.proposal.proposal_id,
348
+ type: event.proposal.type,
349
+ preview: event.proposal.preview,
350
+ });
351
+ return;
352
+ case "done":
353
+ void writeEvent("done", { session_id: event.sessionId });
354
+ return;
355
+ case "error":
356
+ // 用户取消/断开(aborted=true):客户端已不可达,不写 error 帧(写了也失败)
357
+ if (!event.aborted)
358
+ void writeEvent("error", { code: event.code, message: event.message });
359
+ return;
360
+ }
361
+ };
362
+ // ---- 8. onMessages → 落库(决策 18:assistant + tool 消息,含 tool_calls/tool_call_id 配对) ----
363
+ // 硬契约(run.ts 注释):onMessages 抛错不逃逸(runAgent 兜底吞掉)——落库失败
364
+ // 不中断 agent 循环,此处由 db 抛错自然触发该契约(本路由不额外 try/catch)
365
+ const onMessages = (messages) => {
366
+ const ts = now();
367
+ for (const m of messages) {
368
+ insertChatMessage(project.db, {
369
+ session_id: sessionId,
370
+ project_id: project.config.id,
371
+ role: m.role,
372
+ content: m.content ?? null,
373
+ ...(m.role === "assistant" && m.tool_calls !== undefined ? { tool_calls: m.tool_calls } : {}),
374
+ ...(m.role === "tool" ? { tool_call_id: m.tool_call_id } : {}),
375
+ created_at: ts,
376
+ });
377
+ }
378
+ };
379
+ // ---- 9. runAgent 接线(S7.3:produce/dispatcher 由本路由组装注入) ----
380
+ // 真实 produce 外包 [llm] 请求/usage 调试日志装饰器(细粒度类别 request/usage,关闭零开销直通);
381
+ // debugStream 按 stream 类别显式传入(false 也传——压过 env,保证类别隔离语义)
382
+ const produce = deps.produce ??
383
+ createLLMRequestLogger(createRealProduce(apiKey, model, tools, isCategoryEnabled("stream")), {
384
+ model,
385
+ tools,
386
+ });
387
+ // S7.4 真实现:ToolContext { db, outlineDir, projectId } + 同仓提案(S7.5 消费)
388
+ const dispatcher = deps.dispatcher ?? createToolDispatcher({ db: project.db, outlineDir: project.root, projectId: project.config.id }, { store });
389
+ const result = await runAgent({
390
+ sessionId,
391
+ userMessage: message, // runAgent 追加进会话(传入 session 不应已含本轮消息)
392
+ session,
393
+ focus,
394
+ projectPrompt: project.config.prompt || undefined, // 决策 7 项目层
395
+ deps: { produce, dispatcher, onEvent, onMessages },
396
+ signal: controller.signal, // 决策 16:断开即取消(abort 永不重试)
397
+ });
398
+ // ---- 10. B2 取舍落地(决策 16「未确认提案按产生它的会话作废」) ----
399
+ // 三选项评估:a) Proposal 加 sessionId + 仓按会话清除(跨包改动 S6.6/S7.4,成本中);
400
+ // b) SSE 取消时 clear() 全量;c) 依赖 TTL(10 分钟)。
401
+ // 选择 **b**:最小改动、单项目单会话 MVP 下与「按会话作废」语义等价——取消只发生在
402
+ // 客户端断连(同会话)或项目切换(提案本就按项目绑定,切换时全清)场景,clear() 不会
403
+ // 误伤其他会话的待确认提案。与决策 16 原文的偏差(提案记录来源 session_id、按会话粒度
404
+ // 作废)记录为扩展点:多会话并发(backlog 多标签页)时按选项 a 演进——Proposal 增
405
+ // session_id 字段、ProposalStore 增 clearBySession(sessionId),调度时由 S7.6 透传会话。
406
+ if (result.aborted) {
407
+ store.clear();
408
+ }
409
+ // ---- 11. 停心跳 + 关流(error 后流立即关闭;done 自然结束——streamSSE run 的
410
+ // finally 亦兜底 close,此处显式确保顺序:帧排入 writer 后 close,FIFO 保证送达) ----
411
+ heartbeatStop.abort(); // sleep 即时唤醒(sleepAbortable 监听该 signal)
412
+ await heartbeat;
413
+ await stream.close();
414
+ },
415
+ // 防御路径 onError:cb 内部异常(正常流程 error 事件已由 runAgent 发出,理论不可达)——
416
+ // 转契约形态 JSON error 帧(客户端 use-sse 收到 error 即终止解析)
417
+ async (err, stream) => {
418
+ console.error("[server] chat SSE 流异常:", err);
419
+ try {
420
+ await stream.writeSSE({
421
+ event: "error",
422
+ data: JSON.stringify({
423
+ code: "INTERNAL_ERROR",
424
+ message: err instanceof Error ? err.message : "SSE 流内部错误",
425
+ }),
426
+ });
427
+ }
428
+ catch {
429
+ // 客户端已断开:放弃通知
430
+ }
431
+ });
432
+ };
433
+ }
434
+ // ============ 路由装配 ============
435
+ /**
436
+ * 创建对话路由(S7.6 起支持 deps 注入:测试经 createChatRoutes({ produce: mock, ... }) 构造
437
+ * 独立实例挂载测试 app,避免真实 DeepSeek 调用;index.ts 挂载默认实例)。
438
+ */
439
+ export function createChatRoutes(deps = {}) {
440
+ const routes = new Hono();
441
+ routes.get("/sessions", (c) => {
442
+ const project = requireCurrentProject();
443
+ return sessionsResponse(c, listSessions(project.db, project.config.id));
444
+ });
445
+ routes.get("/sessions/:id/messages", (c) => {
446
+ const project = requireCurrentProject();
447
+ const sessionId = c.req.param("id");
448
+ return messagesResponse(c, sessionId, listMessages(project.db, sessionId, project.config.id));
449
+ });
450
+ // POST /api/v1/chat —— POST + SSE 对话端点(S7.6;U3 起为后续切片预留)
451
+ routes.post("/", chatSendHandler(deps));
452
+ return routes;
453
+ }
454
+ /** 默认对话路由实例(index.ts 挂载于 /api/v1/chat) */
455
+ export const chatRoutes = createChatRoutes();
456
+ /**
457
+ * sessions 响应契约自检出口(参照 project.ts listResponse):
458
+ * parse 失败 = 服务端构造的响应不符合 shared 契约(服务端 bug),转 500 INTERNAL_ERROR;
459
+ * 不让 ZodError 冒泡——否则 errorHandler 会按入参语义误报 400 VALIDATION_ERROR。
460
+ */
461
+ function sessionsResponse(c, sessions) {
462
+ try {
463
+ return c.json(ok(chatSessionsResSchema.parse({ sessions })));
464
+ }
465
+ catch (err) {
466
+ throw new HttpError(500, "INTERNAL_ERROR", `sessions 响应不符合契约: ${err instanceof Error ? err.message : String(err)}`);
467
+ }
468
+ }
469
+ /** messages 响应契约自检出口(同上;db 消息含 sessionId/projectId 附加字段,parse 按契约剥离) */
470
+ function messagesResponse(c, sessionId, messages) {
471
+ try {
472
+ return c.json(ok(chatMessagesResSchema.parse({ sessionId, messages })));
473
+ }
474
+ catch (err) {
475
+ throw new HttpError(500, "INTERNAL_ERROR", `messages 响应不符合契约: ${err instanceof Error ? err.message : String(err)}`);
476
+ }
477
+ }
478
+ //# sourceMappingURL=chat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat.js","sourceRoot":"","sources":["../../src/routes/chat.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { Hono } from "hono";
2
+ /** Delta 路由(挂载于 /api/v1/delta,index.ts) */
3
+ export declare const deltaRoutes: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
4
+ //# sourceMappingURL=delta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delta.d.ts","sourceRoot":"","sources":["../../src/routes/delta.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAQ5B,2CAA2C;AAC3C,eAAO,MAAM,WAAW,4EAAa,CAAC"}