@yfwu2020/dsh-selection-explain 0.12.0 → 0.13.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 (86) hide show
  1. package/README.md +18 -5
  2. package/lib/chat-context.js +6 -4
  3. package/lib/chat-context.js.map +1 -1
  4. package/lib/client.js +11810 -10118
  5. package/lib/client.js.map +4 -4
  6. package/lib/config-values.js +5 -1
  7. package/lib/config-values.js.map +1 -1
  8. package/lib/host/analyze-conclusion.js +115 -0
  9. package/lib/host/analyze-conclusion.js.map +1 -0
  10. package/lib/host/analyze-execution-types.js +2 -0
  11. package/lib/host/analyze-execution-types.js.map +1 -0
  12. package/lib/host/analyze-execution.js +166 -0
  13. package/lib/host/analyze-execution.js.map +1 -0
  14. package/lib/host/analyze-history.js +110 -0
  15. package/lib/host/analyze-history.js.map +1 -0
  16. package/lib/host/analyze-messages.js +95 -0
  17. package/lib/host/analyze-messages.js.map +1 -0
  18. package/lib/host/analyze-output.js +69 -0
  19. package/lib/host/analyze-output.js.map +1 -0
  20. package/lib/host/analyze-prompt.js +110 -0
  21. package/lib/host/analyze-prompt.js.map +1 -0
  22. package/lib/host/analyze-request.js +129 -0
  23. package/lib/host/analyze-request.js.map +1 -0
  24. package/lib/host/analyze-round.js +121 -0
  25. package/lib/host/analyze-round.js.map +1 -0
  26. package/lib/host/analyze-tool-execution.js +98 -0
  27. package/lib/host/analyze-tool-execution.js.map +1 -0
  28. package/lib/host/analyze-tools.js +79 -0
  29. package/lib/host/analyze-tools.js.map +1 -0
  30. package/lib/host/analyze-types.js +2 -0
  31. package/lib/host/analyze-types.js.map +1 -0
  32. package/lib/host/analyze.js +30 -926
  33. package/lib/host/analyze.js.map +1 -1
  34. package/lib/host/chat-context.js +8 -3
  35. package/lib/host/chat-context.js.map +1 -1
  36. package/lib/host/config.js +6 -0
  37. package/lib/host/config.js.map +1 -1
  38. package/lib/host/history-store.js +18 -6
  39. package/lib/host/history-store.js.map +1 -1
  40. package/lib/host/native-probe.js +66 -0
  41. package/lib/host/native-probe.js.map +1 -0
  42. package/lib/host/plugin.js +30 -0
  43. package/lib/host/plugin.js.map +1 -1
  44. package/lib/host/shot-capture.js +322 -0
  45. package/lib/host/shot-capture.js.map +1 -0
  46. package/lib/host/shot-geometry.js +183 -0
  47. package/lib/host/shot-geometry.js.map +1 -0
  48. package/lib/host/shot-platform.js +208 -0
  49. package/lib/host/shot-platform.js.map +1 -0
  50. package/lib/host/shot-service.js +127 -0
  51. package/lib/host/shot-service.js.map +1 -0
  52. package/lib/host/shot-types.js +5 -0
  53. package/lib/host/shot-types.js.map +1 -0
  54. package/lib/host/shot.js +136 -0
  55. package/lib/host/shot.js.map +1 -0
  56. package/lib/prompts.js +54 -1
  57. package/lib/prompts.js.map +1 -1
  58. package/lib/settings.js +13 -2
  59. package/lib/settings.js.map +1 -1
  60. package/lib/types/chat-context.d.ts +2 -2
  61. package/lib/types/config-values.d.ts +24 -0
  62. package/lib/types/host/analyze-conclusion.d.ts +3 -0
  63. package/lib/types/host/analyze-execution-types.d.ts +54 -0
  64. package/lib/types/host/analyze-execution.d.ts +3 -0
  65. package/lib/types/host/analyze-history.d.ts +41 -0
  66. package/lib/types/host/analyze-messages.d.ts +15 -0
  67. package/lib/types/host/analyze-output.d.ts +8 -0
  68. package/lib/types/host/analyze-prompt.d.ts +15 -0
  69. package/lib/types/host/analyze-request.d.ts +28 -0
  70. package/lib/types/host/analyze-round.d.ts +7 -0
  71. package/lib/types/host/analyze-tool-execution.d.ts +4 -0
  72. package/lib/types/host/analyze-tools.d.ts +15 -0
  73. package/lib/types/host/analyze-types.d.ts +13 -0
  74. package/lib/types/host/analyze.d.ts +4 -4
  75. package/lib/types/host/config.d.ts +12 -0
  76. package/lib/types/host/native-probe.d.ts +10 -0
  77. package/lib/types/host/shot-capture.d.ts +11 -0
  78. package/lib/types/host/shot-geometry.d.ts +37 -0
  79. package/lib/types/host/shot-platform.d.ts +11 -0
  80. package/lib/types/host/shot-service.d.ts +17 -0
  81. package/lib/types/host/shot-types.d.ts +105 -0
  82. package/lib/types/host/shot.d.ts +16 -0
  83. package/lib/types/host/types.d.ts +13 -0
  84. package/lib/types/prompts.d.ts +21 -0
  85. package/native/window-list.c +139 -0
  86. package/package.json +5 -2
@@ -5,7 +5,7 @@ export const CONFIG_DEFAULTS = Object.freeze({
5
5
  chatModel: '',
6
6
  reasoningEffort: 'high',
7
7
  translationReasoningEffort: 'off',
8
- chatContextTokens: 32768,
8
+ chatContextTokens: 200000,
9
9
  historyMaxEntries: 20,
10
10
  temperature: -1,
11
11
  maxTokens: 0,
@@ -33,6 +33,9 @@ export const CONFIG_DEFAULTS = Object.freeze({
33
33
  pillIdleMs: 10000,
34
34
  voiceCancelOnSilence: true,
35
35
  voiceAutoSend: true,
36
+ shotCardScope: 'window',
37
+ shotPanelScope: 'selection',
38
+ shotMargin: 48,
36
39
  });
37
40
  export const CONFIG_LIMITS = {
38
41
  chatContextTokens: { min: 4096, max: 262144 },
@@ -53,5 +56,6 @@ export const CONFIG_LIMITS = {
53
56
  maxToolRounds: { min: 0, max: 8 },
54
57
  toolResultMaxChars: { min: 200, max: 20000 },
55
58
  pillIdleMs: { min: 2000, max: 600000 },
59
+ shotMargin: { min: 0, max: 400 },
56
60
  };
57
61
  //# sourceMappingURL=config-values.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config-values.js","sourceRoot":"","sources":["../src/config-values.ts"],"names":[],"mappings":"AA2GA,MAAM,CAAC,MAAM,eAAe,GAAqB,MAAM,CAAC,MAAM,CAAC;IAC3D,QAAQ,EAAE,EAAE;IACZ,KAAK,EAAE,EAAE;IACT,YAAY,EAAE,EAAE;IAChB,SAAS,EAAE,EAAE;IACb,eAAe,EAAE,MAAM;IACvB,0BAA0B,EAAE,KAAK;IACjC,iBAAiB,EAAE,KAAK;IACxB,iBAAiB,EAAE,EAAE;IACrB,WAAW,EAAE,CAAC,CAAC;IACf,SAAS,EAAE,CAAC;IACZ,SAAS,EAAE,MAAM;IACjB,iBAAiB,EAAE,IAAI;IACvB,eAAe,EAAE,KAAK;IACtB,oBAAoB,EAAE,EAAE;IACxB,cAAc,EAAE,IAAI;IACpB,yBAAyB,EAAE,EAAE;IAC7B,0BAA0B,EAAE,CAAC;IAC7B,sBAAsB,EAAE,CAAC;IACzB,kBAAkB,EAAE,CAAC;IACrB,2BAA2B,EAAE,IAAI;IACjC,oBAAoB,EAAE,IAAI;IAC1B,gBAAgB,EAAE,MAAM;IACxB,KAAK,EAAE,IAAI;IACX,SAAS,EAAE,gDAAgD;IAC3D,iBAAiB,EAAE,YAAY;IAC/B,aAAa,EAAE,CAAC;IAChB,kBAAkB,EAAE,IAAI;IACxB,YAAY,EAAE,EAAE;IAChB,mBAAmB,EAAE,MAAM;IAC3B,oBAAoB,EAAE,IAAI;IAC1B,WAAW,EAAE,IAAI;IACjB,UAAU,EAAE,KAAK;IACjB,oBAAoB,EAAE,IAAI;IAC1B,aAAa,EAAE,IAAI;CACpB,CAAC,CAAA;AAEJ,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,iBAAiB,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE;IAC7C,iBAAiB,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE;IACvC,WAAW,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE;IAChC,SAAS,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE;IACjC,SAAS,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE;IACrC,iBAAiB,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE;IAC1C,eAAe,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE;IACzC,oBAAoB,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE;IAC1C,yBAAyB,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE;IAC/C,0BAA0B,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE;IAChD,sBAAsB,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE;IAChD,kBAAkB,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE;IACvC,2BAA2B,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE;IACrD,oBAAoB,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE;IAC/C,gBAAgB,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE;IAC3C,aAAa,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE;IACjC,kBAAkB,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE;IAC5C,UAAU,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE;CAC9B,CAAA"}
1
+ {"version":3,"file":"config-values.js","sourceRoot":"","sources":["../src/config-values.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ import { createUserMessage, ReasoningEffortId } from '@deepseek-ai/dsh-llm';
2
+ import { name } from './constants.js';
3
+ import { createThinkFilter, splitLeakedReasoning } from './filters.js';
4
+ import { sse } from './http.js';
5
+ import { systemMessageOf } from './messages.js';
6
+ /** Recover a final answer from tool digests when normal rounds produced no body text. */
7
+ export async function concludeAnalyze(env, state, roundEffort) {
8
+ const { deps, request, tools, prompt, messages, res, controller } = env;
9
+ const { ctx, config, models } = deps;
10
+ const { route, question } = request;
11
+ const { sessionId, toolSchemas } = tools;
12
+ const { systemPrompt, routeKey } = prompt;
13
+ const { checkedMessages, baseMessage, openingMessages } = messages;
14
+ // 收尾轮常常"只吐一段工具调用、不写正文"(实测「今天的新闻」一个字都没有)。
15
+ // 这里自己补结论轮:**不重放工具调用链**,而是把结果写成一段自包含的提示 ——
16
+ // 重放消息链的方式实测也不稳(模型面对 tool-call 历史仍可能继续吐工具调用)。
17
+ state.conclusionInfo.tried = true;
18
+ sse(res, { type: 'notice', code: 'conclusion-retry', text: '查询已完成,正在整理结论…' });
19
+ const conclusionUser = [
20
+ '【补充结论】',
21
+ // ⚠️ **必须带上用户这一轮问的是什么**:这一段是最终正文的来源,而它以前只有
22
+ // 「选区块 + 检索资料 + 请给出最终答案」—— 模型看不到问题,就只能顺着选中文字写。
23
+ // 实测症状:问"搜索今天的AI新闻。",正文却在解释选区那个词(如 diagLog / exit)。
24
+ // 特别是收尾轮也带上工具之后(照主会话的做法),正文**每次都**由这里产出,
25
+ // 缺了问题就等于每次都答非所问。
26
+ question ? `【用户这一轮的问题】(这就是你要回答的对象)\n${question}` : '',
27
+ '',
28
+ '【已经查到的资料】',
29
+ ...state.toolDigestLines.slice(0, 12),
30
+ '',
31
+ '请**直接回答上面那条「用户这一轮的问题」**:结论先行、必要处带来源链接。',
32
+ '不要复述选中文字,也不要解释它是什么 —— 除非问题问的就是它。',
33
+ '不要再请求工具,不要输出任何工具调用格式,也不要写"我先看看""让我核对一下"这类过程。',
34
+ ].join('\n');
35
+ // 先按当前档位试一次;空则**换一个档位**再试(同一档重发没意义)。
36
+ // 以前这里写死 `'off'`:对"必须开推理"的端点(noOffRoutes 里的那些)等于注定失败一轮 ——
37
+ // 用户看到的"工具查询完成了,但模型没有产出正文"就常有它一份。
38
+ const conclusionEfforts = [
39
+ roundEffort,
40
+ models.nextEffortFor(routeKey, roundEffort, new Set(roundEffort ? [roundEffort] : [])),
41
+ ].filter((id) => id.length > 0);
42
+ for (const attemptEffort of conclusionEfforts) {
43
+ if (state.answer.trim().length > 0)
44
+ break;
45
+ state.conclusionInfo.rounds += 1;
46
+ try {
47
+ const resume = ctx.llm.stream({
48
+ provider: route.provider,
49
+ model: route.model,
50
+ ...(sessionId ? { sessionId: sessionId } : {}),
51
+ system: undefined,
52
+ // 工具**依然带着**(照主会话:任何一轮都不摘工具)。
53
+ // 以前这一轮不带工具,模型要调工具时只能退回文本层 —— 那正是正文里出现
54
+ // DSML / ds_safety_tool_call 标记的唯一来源。带上之后它走协议层,正文就是正文。
55
+ ...(toolSchemas.length > 0 ? { tools: toolSchemas } : {}),
56
+ messages: checkedMessages([
57
+ systemMessageOf(systemPrompt, name),
58
+ baseMessage, ...openingMessages,
59
+ createUserMessage({ source: { kind: 'user' }, content: [...state.recoveredMaterialBlocks, { type: 'text', text: conclusionUser }] }),
60
+ ]),
61
+ ...(config.temperature >= 0 ? { temperature: config.temperature } : {}),
62
+ ...(config.maxTokens > 0 ? { maxTokens: config.maxTokens } : {}),
63
+ ...(attemptEffort ? { reasoningEffort: ReasoningEffortId(attemptEffort) } : {}),
64
+ signal: controller.signal,
65
+ });
66
+ const thinkAgain = createThinkFilter();
67
+ for await (const chunk of resume) {
68
+ if (chunk.type === 'text-delta') {
69
+ const part = thinkAgain.push(chunk.text);
70
+ if (part.think)
71
+ sse(res, { type: 'thought', text: part.think });
72
+ const text = part.text;
73
+ if (text) {
74
+ state.chars += text.length;
75
+ state.answer += text;
76
+ state.conclusionInfo.chars += text.length;
77
+ sse(res, { type: 'delta', text: text });
78
+ }
79
+ }
80
+ else if (chunk.type === 'usage') {
81
+ state.usage = chunk.usage;
82
+ }
83
+ else if (chunk.type === 'finish') {
84
+ if (chunk.reason.kind === 'error') {
85
+ state.conclusionInfo.error = chunk.reason.failure?.message ?? '模型调用失败';
86
+ }
87
+ }
88
+ }
89
+ const tail = thinkAgain.flush();
90
+ if (tail.think)
91
+ sse(res, { type: 'thought', text: tail.think });
92
+ if (tail.text) {
93
+ state.chars += tail.text.length;
94
+ state.answer += tail.text;
95
+ state.conclusionInfo.chars += tail.text.length;
96
+ sse(res, { type: 'delta', text: tail.text });
97
+ }
98
+ // 结论轮也可能把"英文核对过程"写进正文:一律按泄漏裁一次
99
+ const leaked = splitLeakedReasoning(state.answer);
100
+ if (leaked.prefix) {
101
+ state.answer = leaked.rest;
102
+ state.chars = state.answer.length;
103
+ sse(res, { type: 'strip', text: leaked.prefix });
104
+ sse(res, { type: 'notice', code: 'reasoning-leak', text: '已去掉模型写进正文的核对过程' });
105
+ }
106
+ }
107
+ catch (error) {
108
+ if (error?.code === 'context-capacity')
109
+ throw error;
110
+ state.conclusionInfo.error = String(error?.message ?? error);
111
+ ctx.logger?.warn?.(`[${name}] 结论轮失败:${state.conclusionInfo.error}`);
112
+ }
113
+ }
114
+ }
115
+ //# sourceMappingURL=analyze-conclusion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze-conclusion.js","sourceRoot":"","sources":["../../src/host/analyze-conclusion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAC3E,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AACrC,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACtE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAA;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAI/C,yFAAyF;AACzF,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAA4B,EAAE,KAAyB,EAAE,WAAmB;IAChH,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,GAAG,CAAA;IACvE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;IACpC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAA;IACnC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,KAAK,CAAA;IACxC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAA;IACzC,MAAM,EAAE,eAAe,EAAE,WAAW,EAAE,eAAe,EAAE,GAAG,QAAQ,CAAA;IAClE,yCAAyC;IACzC,2CAA2C;IAC3C,8CAA8C;IAC9C,KAAK,CAAC,cAAc,CAAC,KAAK,GAAG,IAAI,CAAA;IACjC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,CAAA;IAC7E,MAAM,cAAc,GAAG;QACrB,QAAQ;QACR,2CAA2C;QAC3C,+CAA+C;QAC/C,oDAAoD;QACpD,yCAAyC;QACzC,kBAAkB;QAClB,QAAQ,CAAC,CAAC,CAAC,2BAA2B,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE;QACrD,EAAE;QACF,WAAW;QACX,GAAG,KAAK,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;QACrC,EAAE;QACF,wCAAwC;QACxC,kCAAkC;QAClC,8CAA8C;KAC/C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACZ,qCAAqC;IACrC,0DAA0D;IAC1D,kCAAkC;IAClC,MAAM,iBAAiB,GAAG;QACxB,WAAW;QACX,MAAM,CAAC,aAAa,CAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;KACvF,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAC/B,KAAK,MAAM,aAAa,IAAI,iBAAiB,EAAE,CAAC;QAC9C,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;YAAE,MAAK;QACzC,KAAK,CAAC,cAAc,CAAC,MAAM,IAAI,CAAC,CAAA;QAChC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC;gBAC5B,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,SAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACvD,MAAM,EAAE,SAAS;gBACjB,8BAA8B;gBAC9B,uCAAuC;gBACvC,uDAAuD;gBACvD,GAAG,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACzD,QAAQ,EAAE,eAAe,CAAC;oBACxB,eAAe,CAAC,YAAY,EAAE,IAAI,CAAC;oBACnC,WAAW,EAAE,GAAG,eAAe;oBAC/B,iBAAiB,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,GAAG,KAAK,CAAC,uBAAuB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC;iBACrI,CAAC;gBACF,GAAG,CAAC,MAAM,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACvE,GAAG,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAChE,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,iBAAiB,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC/E,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAA;YACF,MAAM,UAAU,GAAG,iBAAiB,EAAE,CAAA;YACtC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBACjC,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBAChC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;oBACxC,IAAI,IAAI,CAAC,KAAK;wBAAE,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;oBAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;oBACtB,IAAI,IAAI,EAAE,CAAC;wBACT,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAA;wBAC1B,KAAK,CAAC,MAAM,IAAI,IAAI,CAAA;wBACpB,KAAK,CAAC,cAAc,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAA;wBACzC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;oBACzC,CAAC;gBACH,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;oBAClC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAA;gBAC3B,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACnC,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;wBAClC,KAAK,CAAC,cAAc,CAAC,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,IAAI,QAAQ,CAAA;oBACxE,CAAC;gBACH,CAAC;YACH,CAAC;YACD,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,EAAE,CAAA;YAC/B,IAAI,IAAI,CAAC,KAAK;gBAAE,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;YAC/D,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;gBAAC,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC;gBAAC,KAAK,CAAC,cAAc,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAA;gBAC1G,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA;YAC9C,CAAC;YACD,+BAA+B;YAC/B,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;YACjD,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClB,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAA;gBAC1B,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAA;gBACjC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAA;gBAChD,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAA;YAC9E,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAK,KAA2B,EAAE,IAAI,KAAK,kBAAkB;gBAAE,MAAM,KAAK,CAAA;YAC1E,KAAK,CAAC,cAAc,CAAC,KAAK,GAAG,MAAM,CAAE,KAAe,EAAE,OAAO,IAAI,KAAK,CAAC,CAAA;YACvE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI,IAAI,WAAW,KAAK,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC,CAAA;QACrE,CAAC;IACH,CAAC;AAEH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=analyze-execution-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze-execution-types.js","sourceRoot":"","sources":["../../src/host/analyze-execution-types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,166 @@
1
+ import { createUserMessage } from '@deepseek-ai/dsh-llm';
2
+ import { EFFORT_LABEL, looksLikeReasoningRequired, looksLikeUnsupportedTier } from './effort.js';
3
+ import { looksLikeLeakedReasoning, splitLeakedReasoning } from './filters.js';
4
+ import { looksLikeAttachmentFailure } from './history-attachments.js';
5
+ import { sse } from './http.js';
6
+ import { concludeAnalyze } from './analyze-conclusion.js';
7
+ import { finishAnalyzeOutput } from './analyze-output.js';
8
+ import { streamAnalyzeRound } from './analyze-round.js';
9
+ import { executeAnalyzeTools } from './analyze-tool-execution.js';
10
+ /** Coordinate rounds and retries. History attachment recovery always precedes effort retries. */
11
+ export async function executeAnalyze(env) {
12
+ const { deps, request, tools, prompt, messages, res } = env;
13
+ const { ctx, config, models } = deps;
14
+ const { isChat, titleOnly, history } = request;
15
+ const { toolSchemas } = tools;
16
+ const { sentEffort, offSlotEffort, routeKey, isShot } = prompt;
17
+ const { memoryMessages, questionContent } = messages;
18
+ const { clientClosedEarly } = env;
19
+ const state = {
20
+ chars: 0, errored: false, usage: null, answer: '', toolMessages: [], recoveredMaterialBlocks: [],
21
+ toolContextTokens: 0, toolCalls: 0, errorMessage: '', toolDigestLines: [], roundDiag: [],
22
+ conclusionInfo: { tried: false, chars: 0, rounds: 0, error: '' },
23
+ };
24
+ const toolRounds = config.maxToolRounds;
25
+ // 档位被上游拒绝时(400/401/500)重试一次:清单里声明的档位是**建议值**,
26
+ // 实测很多模型并不接受 max(qwen3.7-max 直接 400、minimax-m2.7/gpt-5.6-luna 500)。
27
+ //
28
+ // 以前这里限定了 `isChat && bodyEffort.length > 0` —— 只有追问、且客户端显式传了档位才重试。
29
+ // 于是**首轮**(档位来自配置、默认 off)撞上不吃 off 的模型时无人兜底,整个划词解读全挂。
30
+ // 现在按"这一轮实际在发显式档位"判,三种轮次一视同仁。
31
+ //
32
+ // 2026-10-09 改:重试**不再"去掉档位"**,而是换一个没试过的档(见 nextEffortFor)。
33
+ // 老代码对非 off 档的重试是 `roundEffort = ''`(省略 reasoning),
34
+ // 而省略对"必须开推理"的端点就是关掉推理 —— 实测 20 次重试 0 次成功。
35
+ // 同时给两次机会:上游偶发失败约一半,两次能把成功率抬到 ~90%(代价是多一次往返)。
36
+ const EFFORT_RETRY_LIMIT = 2;
37
+ // 重试与"泄漏检查"都看**真正发出去**的那个档位(sentEffort,映射之后的值):
38
+ // 规范档位是"关"、但这个模型的关档叫 none/minimal 时,检查的必须是发出去的那个。
39
+ let effortRetries = sentEffort.length > 0 ? EFFORT_RETRY_LIMIT : 0;
40
+ const triedEfforts = new Set(sentEffort ? [sentEffort] : []);
41
+ const firstSentEffort = sentEffort;
42
+ let roundEffort = sentEffort;
43
+ const effectiveToolRounds = titleOnly ? 0 : toolRounds;
44
+ for (let round = 0; round <= effectiveToolRounds; round += 1) {
45
+ const wrapUp = round === effectiveToolRounds;
46
+ const { assembler, roundText } = await streamAnalyzeRound(env, state, round, wrapUp, roundEffort);
47
+ if (state.errored) {
48
+ // 附件读不回来(对象仓里的字节被清理/损坏):把**历史**里的附件全降级成文字再试一次。
49
+ // 这是持久化带来的新故障面 —— 引用的寿命超过了那一轮,字节却不一定还在。
50
+ //
51
+ // ⚠️ 必须排在**换档重试前面**:换档是冲着"上游不认这个推理档"去的,
52
+ // 对"附件读不到"毫无意义 —— 排后面的话会先白烧两次模型调用(实测事件序列就是
53
+ // upstream-retry → upstream-retry → attachments-dropped),还会把档位无谓地换掉。
54
+ if (roundText.length === 0 && history.historyHadAttachments && !history.historyDropped && looksLikeAttachmentFailure(state.errorMessage, state.errorCode)) {
55
+ history.historyDropped = true;
56
+ history.historyImages = { kept: 0, omitted: 0, files: 0 };
57
+ messages.openingMessages = [
58
+ ...memoryMessages,
59
+ ...history.buildHistoryMessages(),
60
+ ...(isShot ? [] : [createUserMessage({ source: { kind: 'user' }, content: questionContent })]),
61
+ ];
62
+ // 历史附件被丢掉了 → 名单跟着缩小(只放"还看得见的"那些)
63
+ history.attachedPaths = history.collectAttachedPaths(ctx);
64
+ state.errored = false;
65
+ sse(res, {
66
+ type: 'notice',
67
+ code: 'attachments-dropped',
68
+ text: '历史里的附件已经读不回来了(可能被清理过),这一轮先不带上它,其余照常',
69
+ });
70
+ round -= 1;
71
+ continue;
72
+ }
73
+ // 一个字都没吐出来 → 可以安全重试**同一轮**(保守:已经吐出正文的失败不重试,
74
+ // 免得把半截答案丢掉)。重试换一个没试过的档位,而不是把档位去掉。
75
+ if (roundText.length === 0 && effortRetries > 0) {
76
+ const rejected = roundEffort;
77
+ const next = models.nextEffortFor(routeKey, rejected, triedEfforts);
78
+ if (next) {
79
+ effortRetries -= 1;
80
+ triedEfforts.add(next);
81
+ // 只有"我们发的这个档位确实不被接受"才值得记成事实:
82
+ // · 发的是关档 + 上游说"必须开推理" → 这个 route 不吃关档,记下来;
83
+ // · 发的是开着的档(low/high/max)+ 上游还在说"推理不能关" → **这句不是冲我们来的**
84
+ // (我们没关它),是上游偶发抽风(实测同档位 5/8 成功)。这种情况不记、不诊断,
85
+ // 只如实说"上游返回了错误,已换档重试"。
86
+ // "必须开推理"这句只有在我们发的是**「关」那一格对应的真实档位**时才算数
87
+ // (模型没有 off、关档落在 minimal/low 上时,字符串比较会漏判)
88
+ const rejectedOffSlot = rejected === offSlotEffort;
89
+ const tierIssue = rejectedOffSlot
90
+ ? looksLikeReasoningRequired(state.errorMessage)
91
+ : looksLikeUnsupportedTier(state.errorMessage);
92
+ if (rejectedOffSlot && tierIssue)
93
+ models.markNoOff(routeKey);
94
+ roundEffort = next;
95
+ state.errored = false;
96
+ sse(res, {
97
+ type: 'notice',
98
+ code: tierIssue ? 'effort-rejected' : 'upstream-retry',
99
+ ...(tierIssue ? { tier: rejected } : {}),
100
+ text: tierIssue
101
+ ? rejectedOffSlot
102
+ ? `该模型不接受「关」档,已自动改用「${EFFORT_LABEL[next] ?? next}」档(以后不再尝试关档)`
103
+ : `「${EFFORT_LABEL[rejected] ?? rejected}」档该模型不支持,已改用「${EFFORT_LABEL[next] ?? next}」档重试`
104
+ : '上游这次返回了错误,已自动重试',
105
+ });
106
+ round -= 1;
107
+ continue;
108
+ }
109
+ }
110
+ sse(res, { type: 'error', message: state.errorMessage, code: state.errorCode });
111
+ break;
112
+ }
113
+ const blocks = assembler.blocks();
114
+ const calls = blocks.filter((block) => block.type === 'tool-call');
115
+ if (calls.length === 0) {
116
+ // 最终答案到手:如果发出去的是「关」那一格对应的真实档位,检查有没有把思考写进正文
117
+ if (isChat && firstSentEffort === offSlotEffort) {
118
+ const split = splitLeakedReasoning(state.answer);
119
+ if (split.prefix) {
120
+ models.markLeaky(routeKey);
121
+ state.answer = split.rest;
122
+ state.chars = state.answer.length;
123
+ sse(res, { type: 'strip', text: split.prefix });
124
+ sse(res, {
125
+ type: 'notice',
126
+ code: 'reasoning-leak',
127
+ // 报**真实档位**(模型可能没有 off,叫 none/minimal):客户端据此标对那个档位按钮
128
+ tier: firstSentEffort,
129
+ text: '该模型在「关」档会把思考写进正文,已撤回泄漏段;以后这一档会自动改用「低」',
130
+ });
131
+ }
132
+ else if (looksLikeLeakedReasoning(state.answer)) {
133
+ // 句式没认准(模型每次换说法)→ 这次不裁(怕误删正文),但记住它,下次自动抬档
134
+ models.markLeaky(routeKey);
135
+ sse(res, {
136
+ type: 'notice',
137
+ code: 'reasoning-leak',
138
+ tier: firstSentEffort,
139
+ text: '这个模型在「关」档会把思考写进正文;这一档以后自动改用「低」',
140
+ });
141
+ }
142
+ }
143
+ break;
144
+ }
145
+ // 既然这一轮要调工具,它刚才流出来的正文就是"过程旁白",不是答案:
146
+ // 让前端把这部分撤回去(顺带当成思考尾巴显示),免得"我怎么想的"混进小窗正文。
147
+ // 实测踩过:追问"搜索今天的新闻"时,模型在工具轮里先吐了一段英文盘算
148
+ // (I have sources with dates… Maybe I should do one more search…),
149
+ // 然后才给中文结论,这段英文被当正文渲染进了消息框。
150
+ if (roundText.length > 0) {
151
+ state.answer = state.answer.slice(0, Math.max(0, state.answer.length - roundText.length));
152
+ sse(res, { type: 'drop', chars: roundText.length, text: roundText.slice(-2000), round });
153
+ }
154
+ // 有的模型不带工具定义也会返回调用;执行端同样遵守开关和轮数上限。
155
+ if (wrapUp || toolSchemas.length === 0)
156
+ break;
157
+ // 执行工具→把结果回灌,再让模型继续(上限 maxToolRounds 轮)
158
+ await executeAnalyzeTools(env, state, blocks, calls, round);
159
+ }
160
+ if (!state.errored && state.answer.trim().length === 0 && state.toolCalls > 0 && triedEfforts.size === 1) {
161
+ await concludeAnalyze(env, state, roundEffort);
162
+ }
163
+ finishAnalyzeOutput(res, state, clientClosedEarly);
164
+ return state.errored ? null : state.answer;
165
+ }
166
+ //# sourceMappingURL=analyze-execution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze-execution.js","sourceRoot":"","sources":["../../src/host/analyze-execution.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,110 @@
1
+ import { createAssistantMessage, createUserMessage } from '@deepseek-ai/dsh-llm';
2
+ import { resolve } from 'node:path';
3
+ import { readMaterialCatalog } from './chat-materials.js';
4
+ import { historyContentBlocks, readHistoryAttachments } from './history-attachments.js';
5
+ /** Mutable history and attachment admission state shared by context planning and retries. */
6
+ export class AnalyzeHistory {
7
+ isChat;
8
+ contextState;
9
+ currentAttachments;
10
+ rawHistory;
11
+ selectedHistory;
12
+ catalog;
13
+ historySource;
14
+ historyImages = { kept: 0, omitted: 0, files: 0 };
15
+ historyHadAttachments = false;
16
+ historyDropped = false;
17
+ attachedPaths = new Set();
18
+ contextEstimate = 0;
19
+ constructor(body, isChat, historyStart, route, contextState) {
20
+ this.isChat = isChat;
21
+ this.contextState = contextState;
22
+ this.currentAttachments = readHistoryAttachments(body.attachments);
23
+ this.rawHistory = (Array.isArray(body.history) ? body.history : []).map(raw => {
24
+ const item = (raw || {});
25
+ const attachments = readHistoryAttachments(item.attachments);
26
+ return {
27
+ role: item.role === 'assistant' ? 'assistant' : 'user', text: typeof item.text === 'string' ? item.text : '',
28
+ ...(attachments.length ? { attachments } : {})
29
+ };
30
+ });
31
+ this.selectedHistory = this.rawHistory;
32
+ this.catalog = readMaterialCatalog([...(Array.isArray(body.materials) ? body.materials : []),
33
+ ...this.rawHistory.flatMap((t, i) => (t.attachments || []).map(a => ({ ...a, turn: historyStart + i }))),
34
+ ...this.currentAttachments.map(a => ({ ...a, turn: historyStart + this.rawHistory.length }))]);
35
+ this.historySource = { provider: route.provider, model: route.model };
36
+ }
37
+ /**
38
+ * 历史规划(纯计算):预算、降级、以及**这次请求真的进了消息的那些附件**。
39
+ * 每次都要能重算 —— 引用失效时会降级再跑一遍(见下面 errored 分支里的那一跳)。
40
+ */
41
+ planHistory() {
42
+ if (!this.isChat)
43
+ return { blocks: [], kept: [], keptImages: 0, omittedImages: 0, keptFiles: 0, omittedFiles: 0 };
44
+ const window = this.selectedHistory;
45
+ const turns = this.historyDropped
46
+ ? window.map((turn) => {
47
+ const item = (turn ?? {});
48
+ return { role: item.role, text: item.text };
49
+ })
50
+ : window;
51
+ const plan = historyContentBlocks(turns, this.currentAttachments);
52
+ this.historyImages = { kept: plan.keptImages, omitted: plan.omittedImages, files: plan.keptFiles + plan.omittedFiles };
53
+ return plan;
54
+ }
55
+ /** 重建历史消息。 */
56
+ buildHistoryMessages() {
57
+ const out = [];
58
+ if (!this.isChat)
59
+ return out;
60
+ const window = this.selectedHistory;
61
+ const plan = this.planHistory();
62
+ window.forEach((turn, index) => {
63
+ const item = turn;
64
+ if (!this.historyDropped && Array.isArray(item.attachments) && item.attachments.length > 0)
65
+ this.historyHadAttachments = true;
66
+ const content = plan.blocks[index] ?? [];
67
+ if (content.length === 0)
68
+ return;
69
+ if (item.role === 'assistant') {
70
+ out.push(createAssistantMessage({ content, source: this.historySource }));
71
+ }
72
+ else {
73
+ out.push(createUserMessage({ source: { kind: 'user' }, content }));
74
+ }
75
+ });
76
+ return out;
77
+ }
78
+ /**
79
+ * 文件工具的访客名单:本轮附件与本小窗保存的文件材料目录。
80
+ * 材料目录中的旧文件可由 selection_material 恢复;不接纳任意外部路径。
81
+ *
82
+ * 路径由附件服务按内容哈希推出(不碰磁盘,纯路径计算,所以每次请求重算没有成本);
83
+ * 引用不合法就当场丢掉 —— 它本来也读不出来,让门禁拒掉即可。
84
+ */
85
+ collectAttachedPaths(ctx) {
86
+ const paths = new Set();
87
+ const store = ctx.get('attachments');
88
+ if (!store || typeof store.fileHostPath !== 'function')
89
+ return paths;
90
+ const refs = [];
91
+ for (const item of this.currentAttachments)
92
+ if (item.kind === 'file')
93
+ refs.push(item.ref);
94
+ for (const item of this.catalog)
95
+ if (item.kind === 'file')
96
+ refs.push(item.ref);
97
+ for (const ref of refs) {
98
+ try {
99
+ const hostPath = store.fileHostPath(ref);
100
+ if (hostPath)
101
+ paths.add(resolve(hostPath));
102
+ }
103
+ catch {
104
+ /* 引用不合法:当它不存在(读的时候自然会被门禁拒) */
105
+ }
106
+ }
107
+ return paths;
108
+ }
109
+ }
110
+ //# sourceMappingURL=analyze-history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze-history.js","sourceRoot":"","sources":["../../src/host/analyze-history.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ import { createAssistantMessage, createUserMessage } from '@deepseek-ai/dsh-llm';
2
+ import { estimateTextTokens } from '../chat-context.js';
3
+ import { shotTitlePromptFor } from '../prompts.js';
4
+ import { estimateRequestTokens, planChatContext } from './chat-context.js';
5
+ import { materialIndex } from './chat-materials.js';
6
+ import { sse } from './http.js';
7
+ /** Compact chat memory if necessary, then construct the initial multimodal messages. */
8
+ export async function prepareAnalyzeMessages(deps, request, tools, prompt, res, controller) {
9
+ const { ctx } = deps;
10
+ const { body, isChat, capacity, initialExplanation, userText, question, route, historyStart, isShotMode, titleOnly, shotScope, shotFrame, history } = request;
11
+ const { currentAttachments, rawHistory, catalog, historySource } = history;
12
+ const { systemPrompt, sentEffort, isShot } = prompt;
13
+ const { toolSchemas } = tools;
14
+ history.contextEstimate = 0;
15
+ if (isChat && capacity) {
16
+ try {
17
+ const fixedTokens = 256 + estimateTextTokens(systemPrompt + userText + initialExplanation + question)
18
+ + estimateTextTokens(JSON.stringify(toolSchemas))
19
+ + estimateTextTokens(materialIndex(catalog, historyStart + rawHistory.length))
20
+ + estimateTextTokens(typeof body.toolDigest === 'string' ? body.toolDigest.slice(0, 2000) : '')
21
+ + currentAttachments.reduce((n, a) => n + capacity.attachmentPrice(a), 0);
22
+ const planned = await planChatContext(ctx, route, capacity, { state: history.contextState, history: rawHistory, fixedTokens, signal: controller.signal, effort: sentEffort });
23
+ history.contextState = planned.state;
24
+ history.selectedHistory = planned.history;
25
+ history.contextEstimate = planned.estimatedTokens;
26
+ sse(res, {
27
+ type: 'context-state', state: history.contextState,
28
+ budget: capacity.budget, estimatedTokens: history.contextEstimate, modelWindow: capacity.modelWindow,
29
+ compacted: planned.compacted, retainedMessages: history.selectedHistory.length
30
+ });
31
+ }
32
+ catch (error) {
33
+ sse(res, { type: 'error', code: 'context-rejected', message: String(error?.message || error) });
34
+ return null;
35
+ }
36
+ }
37
+ const memoryMessages = isChat ? [
38
+ ...(initialExplanation ? [createAssistantMessage({ source: historySource, content: [{ type: 'text', text: initialExplanation }] })] : []),
39
+ ...(history.contextState.summary ? [createUserMessage({
40
+ source: { kind: 'user' }, content: [{
41
+ type: 'text',
42
+ text: '【较早对话摘要,可能遗漏细节】\n' + history.contextState.summary + '\n' + materialIndex(catalog, history.contextState.through)
43
+ }]
44
+ })] : []),
45
+ ] : [];
46
+ function checkedMessages(messages) {
47
+ if (capacity && estimateRequestTokens(messages, capacity, toolSchemas) > capacity.budget) {
48
+ throw Object.assign(new Error('本轮材料与工具结果超过上下文容量,请缩小问题或引用范围'), { code: 'context-capacity' });
49
+ }
50
+ return messages;
51
+ }
52
+ // ⚠️ 截图模式:图必须**在这一条消息里**。
53
+ // 原先只有 isChat(追问) 才拼 openingMessages,截图走的是 baseMessage 纯文本那条 ——
54
+ // 结果图根本没进请求,模型只会说"我没收到截图"(实测踩到)。
55
+ const shotImageBlocks = isShotMode
56
+ ? currentAttachments.map((item) => item.kind === 'image'
57
+ ? { type: 'image', attachment: item.ref }
58
+ : { type: 'file', attachment: item.ref })
59
+ : [];
60
+ const baseMessage = createUserMessage({
61
+ source: { kind: 'user' },
62
+ content: shotImageBlocks.length > 0
63
+ ? [...shotImageBlocks, { type: 'text', text: userText }]
64
+ : [{ type: 'text', text: userText }],
65
+ });
66
+ // 上一轮查过的东西一并带上:否则追问会反复重查同样的内容(一次工具往返 20~34s)
67
+ const toolDigest = typeof body.toolDigest === 'string' ? body.toolDigest.trim().slice(0, 2000) : '';
68
+ // 顺序很重要:把"已经查到的结果"放**前面**、问题放**最后**。
69
+ // 反过来的话,模型最后读到的是原始检索结果,容易"整理资料"而不是回答问题
70
+ //(实测:问新闻却把上一次的检索结果当成要总结的对象)。
71
+ const questionText = toolDigest
72
+ ? `【本会话已经查到的结果】(同一会话里查过的,不要重复查同样的内容;只在与本轮问题相关时才用)\n${toolDigest}\n\n【用户这一轮的问题】\n${question}`
73
+ : question;
74
+ // 附件排在正文**前面**:模型先拿到材料(图片 / 文件句柄),再读到这一轮的问题。
75
+ // 没有附件时 content 与从前逐字节一致(一个元素、纯文本),既有行为一点不变。
76
+ const currentBlocks = currentAttachments.map((item) => item.kind === 'image' ? { type: 'image', attachment: item.ref } : { type: 'file', attachment: item.ref });
77
+ const questionContent = currentBlocks.length > 0 ? [...currentBlocks, { type: 'text', text: questionText }] : [{ type: 'text', text: questionText }];
78
+ let openingMessages = isChat
79
+ ? [
80
+ ...memoryMessages,
81
+ ...history.buildHistoryMessages(),
82
+ // 截图首轮:图 + 问题已经放进 baseMessage(只需要一份,避免图片和问题各发两遍);
83
+ // 追问不走截图模式,当前问题仍然放在这里。
84
+ ...(isShot ? [] : [createUserMessage({ source: { kind: 'user' }, content: questionContent })]),
85
+ ]
86
+ : [];
87
+ if (titleOnly) {
88
+ // 截图:base 那条消息里已经带了图 + 提问,这里只多一句"只输出标题"
89
+ openingMessages = [
90
+ createUserMessage({ source: { kind: 'user' }, content: [{ type: 'text', text: shotTitlePromptFor(shotScope, shotFrame) }] }),
91
+ ];
92
+ }
93
+ return { memoryMessages, baseMessage, questionContent, openingMessages, checkedMessages };
94
+ }
95
+ //# sourceMappingURL=analyze-messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze-messages.js","sourceRoot":"","sources":["../../src/host/analyze-messages.ts"],"names":[],"mappings":"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"}