@yfwu2020/dsh-selection-explain 0.13.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.
- package/README.md +3 -3
- package/lib/client.js +11672 -11473
- package/lib/client.js.map +4 -4
- package/lib/host/analyze-conclusion.js +115 -0
- package/lib/host/analyze-conclusion.js.map +1 -0
- package/lib/host/analyze-execution-types.js +2 -0
- package/lib/host/analyze-execution-types.js.map +1 -0
- package/lib/host/analyze-execution.js +166 -0
- package/lib/host/analyze-execution.js.map +1 -0
- package/lib/host/analyze-history.js +110 -0
- package/lib/host/analyze-history.js.map +1 -0
- package/lib/host/analyze-messages.js +95 -0
- package/lib/host/analyze-messages.js.map +1 -0
- package/lib/host/analyze-output.js +69 -0
- package/lib/host/analyze-output.js.map +1 -0
- package/lib/host/analyze-prompt.js +110 -0
- package/lib/host/analyze-prompt.js.map +1 -0
- package/lib/host/analyze-request.js +129 -0
- package/lib/host/analyze-request.js.map +1 -0
- package/lib/host/analyze-round.js +121 -0
- package/lib/host/analyze-round.js.map +1 -0
- package/lib/host/analyze-tool-execution.js +98 -0
- package/lib/host/analyze-tool-execution.js.map +1 -0
- package/lib/host/analyze-tools.js +79 -0
- package/lib/host/analyze-tools.js.map +1 -0
- package/lib/host/analyze-types.js +2 -0
- package/lib/host/analyze-types.js.map +1 -0
- package/lib/host/analyze.js +30 -977
- package/lib/host/analyze.js.map +1 -1
- package/lib/host/native-probe.js +66 -0
- package/lib/host/native-probe.js.map +1 -0
- package/lib/host/plugin.js +9 -10
- package/lib/host/plugin.js.map +1 -1
- package/lib/host/shot-capture.js +322 -0
- package/lib/host/shot-capture.js.map +1 -0
- package/lib/host/shot-geometry.js +183 -0
- package/lib/host/shot-geometry.js.map +1 -0
- package/lib/host/shot-platform.js +208 -0
- package/lib/host/shot-platform.js.map +1 -0
- package/lib/host/shot-service.js +127 -0
- package/lib/host/shot-service.js.map +1 -0
- package/lib/host/shot-types.js +5 -0
- package/lib/host/shot-types.js.map +1 -0
- package/lib/host/shot.js +117 -949
- package/lib/host/shot.js.map +1 -1
- package/lib/types/host/analyze-conclusion.d.ts +3 -0
- package/lib/types/host/analyze-execution-types.d.ts +54 -0
- package/lib/types/host/analyze-execution.d.ts +3 -0
- package/lib/types/host/analyze-history.d.ts +41 -0
- package/lib/types/host/analyze-messages.d.ts +15 -0
- package/lib/types/host/analyze-output.d.ts +8 -0
- package/lib/types/host/analyze-prompt.d.ts +15 -0
- package/lib/types/host/analyze-request.d.ts +28 -0
- package/lib/types/host/analyze-round.d.ts +7 -0
- package/lib/types/host/analyze-tool-execution.d.ts +4 -0
- package/lib/types/host/analyze-tools.d.ts +15 -0
- package/lib/types/host/analyze-types.d.ts +13 -0
- package/lib/types/host/analyze.d.ts +4 -4
- package/lib/types/host/native-probe.d.ts +10 -0
- package/lib/types/host/shot-capture.d.ts +11 -0
- package/lib/types/host/shot-geometry.d.ts +37 -0
- package/lib/types/host/shot-platform.d.ts +11 -0
- package/lib/types/host/shot-service.d.ts +17 -0
- package/lib/types/host/shot-types.d.ts +105 -0
- package/lib/types/host/shot.d.ts +14 -71
- package/native/window-list.c +139 -0
- package/package.json +2 -1
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { CHAT_SYSTEM_PROMPT, CODE_PROMPT, DETAIL_PROMPT, TRANSLATION_PROMPT, shotPromptFor } from '../prompts.js';
|
|
2
|
+
import { loadDesignSkill } from './design-skill.js';
|
|
3
|
+
import { sse } from './http.js';
|
|
4
|
+
/** Assemble the exact prompt prefix and map the requested effort to the selected model. */
|
|
5
|
+
export async function prepareAnalyzePrompt(deps, request, tools, res) {
|
|
6
|
+
const { ctx, config, models } = deps;
|
|
7
|
+
const { body, isChat, shotScope, shotFrame, effort, route, history } = request;
|
|
8
|
+
const { toolSchemas, wantsFsTools, readRoot, fetchBlockedSample } = tools;
|
|
9
|
+
const stage = typeof body.stage === 'string' ? body.stage : '';
|
|
10
|
+
// 选中文字是代码:首轮走「注释」提示词(代码块 + 逐句注释 + 小结)
|
|
11
|
+
const isCode = body.kind === 'code';
|
|
12
|
+
// 截图提问是**独立模式**:没有选中文字,只有一张图 + 一个问题,不能用"追问"那套提示词
|
|
13
|
+
const isShot = body.kind === 'shot';
|
|
14
|
+
const basePrompt = isShot
|
|
15
|
+
? shotPromptFor(shotScope, shotFrame)
|
|
16
|
+
: isChat
|
|
17
|
+
? CHAT_SYSTEM_PROMPT
|
|
18
|
+
: stage === 'detail'
|
|
19
|
+
? DETAIL_PROMPT
|
|
20
|
+
: isCode
|
|
21
|
+
? CODE_PROMPT
|
|
22
|
+
: TRANSLATION_PROMPT;
|
|
23
|
+
// 一个工具都没有时明确禁止伪造调用(模型会照着自己的习惯吐 <ds_safety_tool_call> 之类的格式)
|
|
24
|
+
// 正文里不许写"盘算过程"(模型在工具轮里很容易把"I should search again…"这类写进正文)
|
|
25
|
+
const narrateRule = '\n\n【正文只写结论】不要把思考、盘算、自查过程写进正文("我还得再搜一次""先看看拿到的标题""让我确认一下"这类一律不写);需要工具就直接调用,调用前后都不要解说。';
|
|
26
|
+
// 输出偏好(小窗开关):左档 Markdown / 右档 网页。
|
|
27
|
+
// 关档也要明确说"用 Markdown"——否则标签写着 Markdown、行为却可能自己给整页 HTML,开关就名不副实。
|
|
28
|
+
let webRule = '';
|
|
29
|
+
if (isChat && body.webAnswer !== true) {
|
|
30
|
+
webRule =
|
|
31
|
+
'\n\n【输出偏好:Markdown】用户把输出偏好设为 Markdown:默认用普通文字/Markdown 回答' +
|
|
32
|
+
'(标题、列表、表格、代码块都可以)。' +
|
|
33
|
+
'**这不禁止 HTML**——如果这个问题用一页 HTML 明显讲得更清楚,照样可以用网页回答;' +
|
|
34
|
+
'只是不要单纯为了"好看"就把简单问题做成页面。';
|
|
35
|
+
}
|
|
36
|
+
if (isChat && body.webAnswer === true) {
|
|
37
|
+
const skill = await loadDesignSkill();
|
|
38
|
+
webRule =
|
|
39
|
+
'\n\n【输出偏好:网页】这不是"一律用网页",而是**网页优先**:\n' +
|
|
40
|
+
'- **复杂问题**(需要对比、流程、层级、图表,或者文字答案会长到不好读)→ 直接给完整的单文件 HTML' +
|
|
41
|
+
'(放进 ```html 代码块),**页面本身就是答案**,不要再用文字复述一遍;\n' +
|
|
42
|
+
'- **简单问题**(一两段话能说清、不需要并列或图示)→ **仍然直接用文字回答**。' +
|
|
43
|
+
'不要为了用网页而用网页,也不要把简单问题包装成页面。\n' +
|
|
44
|
+
'拿不准时按"能不能用一小段话讲清"来判断:能,就文字。\n' +
|
|
45
|
+
'用网页时,页面会渲染在大约 **500px 宽**的小窗里,按下面的设计规范做:\n\n' +
|
|
46
|
+
skill +
|
|
47
|
+
(body.theme === 'dark'
|
|
48
|
+
? '\n\n【配色:跟随宿主,当前是深色】宿主界面此刻是**深色模式**,页面必须是深色:' +
|
|
49
|
+
'背景用 #16181c~#1f2126 一档,正文 #e6e6e6,次级文字 #a1a1aa,分隔线 rgba(255,255,255,.12),' +
|
|
50
|
+
'卡片底色比页面底再亮一档。**不要白底黑字**,也不要只写 prefers-color-scheme(宿主的深浅由用户设置决定,与系统不一定一致)。\n'
|
|
51
|
+
: '\n\n【配色:跟随宿主,当前是浅色】宿主界面此刻是**浅色模式**,页面必须是浅色:' +
|
|
52
|
+
'背景用 #ffffff~#f7f7f8 一档,正文 #171717,次级文字 #6b7280,分隔线 rgba(0,0,0,.10),' +
|
|
53
|
+
'卡片底色与页面底拉开一档。**不要深色底**,也不要只写 prefers-color-scheme(宿主的深浅由用户设置决定,与系统不一定一致)。\n');
|
|
54
|
+
}
|
|
55
|
+
// 访客名单要在**拼系统提示词之前**算好:提示词里要告诉模型"你附的那几个文件也在可读范围里"。
|
|
56
|
+
//
|
|
57
|
+
// ⚠️ 措辞很要紧。原来写的是「范围:项目目录。超出该范围的路径会被拒绝」,再追加一句
|
|
58
|
+
// "附带的文件也能读" —— 实测模型会**逮住前半句直接放弃**:它一次 read 都不试,
|
|
59
|
+
// 就回"这个文件我读不了,它在附件仓,而我的工具被限制在项目目录"。
|
|
60
|
+
// 所以改成**先把可读范围说全**(项目 + 本次附带的文件),再说"除此之外会被拒"。
|
|
61
|
+
history.attachedPaths = history.collectAttachedPaths(ctx);
|
|
62
|
+
const fileRule = wantsFsTools
|
|
63
|
+
? `\n\n【文件访问】你可以用read/grep/glob读取当前项目(${readRoot || '不限'})和本小窗已提供的文件附件。附件路径以经过验证的文件引用或selection_material返回为准。需要旧文件时先用selection_material取回路径,再按问题读取必要部分;上传成功不等于格式可解析,不能读取时明确说明。除此之外的路径会被拒绝。`
|
|
64
|
+
: '';
|
|
65
|
+
const fetchRule = fetchBlockedSample
|
|
66
|
+
? `\n\n【抓取网页不可用】本机域名解析到保留地址段(${fetchBlockedSample}),网页抓取会被安全策略拒绝:只做联网搜索,**不要尝试抓取具体网址**(省掉一次注定失败的往返)。`
|
|
67
|
+
: '';
|
|
68
|
+
const systemPrompt = (toolSchemas.length > 0
|
|
69
|
+
? basePrompt
|
|
70
|
+
: `${basePrompt}\n\n【本轮没有可用工具】不要输出任何工具调用格式(如 <ds_safety_tool_call>、tool_calls、JSON 形式的调用),也不要声称你查过;需要实时/外部信息时直接说明你无法联网或无法读取,只基于已知信息作答。`) +
|
|
71
|
+
narrateRule +
|
|
72
|
+
webRule +
|
|
73
|
+
fileRule +
|
|
74
|
+
fetchRule;
|
|
75
|
+
// 三档分开:翻译(默认 low,只要快)/详解(默认 reasoningEffort=high,要深)/追问(chatReasoningEffort=high,要准)
|
|
76
|
+
// 三档分开:翻译(默认 low,只要快)/详解(默认 reasoningEffort=high,要深)/追问(默认 chatReasoningEffort=high)
|
|
77
|
+
// 但**追问档**允许请求覆盖(小窗的「推理等级(追问档)」控件靠这条生效):
|
|
78
|
+
// 首轮/详解仍按各自的配置走 —— 首轮故意用低档换速度,不该被追问档的设置带跑。
|
|
79
|
+
await models.loadLeaky();
|
|
80
|
+
let bodyEffort = typeof body.effort === 'string' && body.effort.length > 0 ? body.effort : '';
|
|
81
|
+
// 这个模型在"关"档会把思考写进正文(实测过):别再发 none,直接抬到 low —— 既没泄漏,也不慢
|
|
82
|
+
const routeKey = `${route.provider}/${route.model}`;
|
|
83
|
+
if (isChat && bodyEffort === 'off' && models.leakyOnOff.has(routeKey)) {
|
|
84
|
+
bodyEffort = 'low';
|
|
85
|
+
sse(res, {
|
|
86
|
+
type: 'notice',
|
|
87
|
+
code: 'effort-clamped',
|
|
88
|
+
tier: 'off',
|
|
89
|
+
text: '该模型在「关」档会把思考写进正文,已自动改用「低」档',
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
let requestEffort = isChat
|
|
93
|
+
? bodyEffort || config.chatReasoningEffort || effort
|
|
94
|
+
: stage === 'detail'
|
|
95
|
+
? effort
|
|
96
|
+
: config.translationReasoningEffort || effort;
|
|
97
|
+
// 已知这个模型不接受"关"档(之前撞过一次并记下来了):直接换 low,不再先失败一轮。
|
|
98
|
+
// 首轮默认就是 off,所以这条对"默认配置 + 不吃 off 的模型"是必经之路。
|
|
99
|
+
if (requestEffort === 'off' && models.noOffRoutes.has(routeKey))
|
|
100
|
+
requestEffort = 'low';
|
|
101
|
+
// 规范四格 → 这个模型真实声明的档位(每次请求现算;'' = 这个模型不支持推理,干脆不带档位)。
|
|
102
|
+
// 注意:leaky / noOff 两条守卫仍在**规范档位**这一层判断(它们记的是"关档"的语义),
|
|
103
|
+
// 映射放在最后一步。
|
|
104
|
+
const sentEffort = models.effortForRoute(routeKey, requestEffort);
|
|
105
|
+
// 「关」这一格在这个模型上到底是哪个真实档位:重试判定与泄漏检查都要按**真实档位**比
|
|
106
|
+
// (模型可能没有 off,或叫 none/minimal —— 那就不能拿字符串 'off' 去比)
|
|
107
|
+
const offSlotEffort = requestEffort === 'off' ? sentEffort : models.effortForRoute(routeKey, 'off');
|
|
108
|
+
return { stage, isCode, isShot, systemPrompt, sentEffort, offSlotEffort, routeKey };
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=analyze-prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-prompt.js","sourceRoot":"","sources":["../../src/host/analyze-prompt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { contextSource, EMPTY_DIGEST, readContextState } from '../chat-context.js';
|
|
2
|
+
import { AnalyzeHistory } from './analyze-history.js';
|
|
3
|
+
import { fitBackground, resolveChatCapacity } from './chat-context.js';
|
|
4
|
+
import { sessionIdOf } from './context.js';
|
|
5
|
+
import { BODY_LIMIT, readBody, sendJson } from './http.js';
|
|
6
|
+
/** Validate, resolve route/background, and normalize request inputs before SSE starts. */
|
|
7
|
+
export async function prepareAnalyzeRequest(req, res, deps, allow) {
|
|
8
|
+
const { ctx, config, models, sessions, historyStore } = deps;
|
|
9
|
+
if (req.method !== 'POST') {
|
|
10
|
+
sendJson(res, 405, { error: '只支持 POST' });
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
let body;
|
|
14
|
+
try {
|
|
15
|
+
body = JSON.parse(await readBody(req, BODY_LIMIT));
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
sendJson(res, 400, { error: `请求体解析失败:${String(error?.message ?? error)}` });
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const text = typeof body.text === 'string' ? body.text.trim() : '';
|
|
22
|
+
if (text.length === 0) {
|
|
23
|
+
sendJson(res, 400, { error: '缺少 text(选中文字)' });
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
if (text.length > config.maxSelectionChars) {
|
|
27
|
+
sendJson(res, 413, { error: `选中文字过长(${text.length} > ${config.maxSelectionChars} 字符)` });
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
if (!allow()) {
|
|
31
|
+
sendJson(res, 429, { error: `请求过于频繁(上限 ${config.maxRequestsPerMinute}/分钟)` });
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
const override = typeof body.provider === 'string' && typeof body.model === 'string' && body.provider && body.model
|
|
35
|
+
? { provider: body.provider, model: body.model }
|
|
36
|
+
: undefined;
|
|
37
|
+
// 名字避开下面的 isChat(那里判的是"提示词用追问那套",此处判的是"模型用追问那个")
|
|
38
|
+
const isChatRound = typeof body.question === 'string' && body.question.trim().length > 0;
|
|
39
|
+
const route = models.resolveRoute(override, await sessions.sessionModelOf(sessionIdOf(body)), isChatRound);
|
|
40
|
+
if (!route) {
|
|
41
|
+
sendJson(res, 503, { error: '尚未确定模型路由:请先在设置里选择默认模型后重试' });
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
const context = historyStore.clampText(body.context, config.maxContextChars);
|
|
45
|
+
const label = historyStore.clampText(body.label, 80);
|
|
46
|
+
// 页面标题/地址不写进提示词:模型会把它当成「选中文字里的英文」去翻译(实测把标题 DSH 译了一遍)
|
|
47
|
+
const initialExplanation = typeof body.initialExplanation === 'string' ? body.initialExplanation : '';
|
|
48
|
+
const source = contextSource(sessionIdOf(body), text, typeof body.context === 'string' ? body.context : '', initialExplanation);
|
|
49
|
+
const restoredState = readContextState(body.contextState);
|
|
50
|
+
const historyStart = Number.isSafeInteger(body.historyStart) && Number(body.historyStart) >= 0 ? Number(body.historyStart) : 0;
|
|
51
|
+
if (isChatRound && historyStart > 0 && (!restoredState || restoredState.source !== source || restoredState.through !== historyStart)) {
|
|
52
|
+
sendJson(res, 409, { error: '对话记忆进度与当前来源不一致,请重新打开这段历史后重试' });
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
let contextState = restoredState && restoredState.source === source && restoredState.through === historyStart
|
|
56
|
+
? { ...restoredState, sessionId: sessionIdOf(body) } : { version: 1, sessionId: sessionIdOf(body), source, through: 0, digest: EMPTY_DIGEST, summary: '', background: null };
|
|
57
|
+
const capacity = isChatRound ? await resolveChatCapacity(ctx, config, route) : null;
|
|
58
|
+
// 会话背景:从 sessionQuery 读取当前会话的模型界面(live 优先,含持久化会话)
|
|
59
|
+
let background = null;
|
|
60
|
+
if (config.sessionContext) {
|
|
61
|
+
const sessionId = sessionIdOf(body);
|
|
62
|
+
if (isChatRound && restoredState && restoredState.source === source)
|
|
63
|
+
background = contextState.background;
|
|
64
|
+
else if (sessionId) {
|
|
65
|
+
// 背景预算按阶段:首轮只要翻译(8 条够定指代);详解与追问都是深度交互,吃满 24 条
|
|
66
|
+
const stage = typeof body.stage === 'string' ? body.stage : '';
|
|
67
|
+
const wantsFull = stage === 'detail' || typeof body.question === 'string';
|
|
68
|
+
background = await sessions.loadSessionBackground(sessionId, {
|
|
69
|
+
maxMessages: wantsFull ? config.sessionContextMaxMessages : config.sessionContextFastMessages,
|
|
70
|
+
maxChars: config.sessionContextMaxChars,
|
|
71
|
+
marker: text,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (isChatRound && capacity && !restoredState)
|
|
76
|
+
background = fitBackground(background, Math.max(128, capacity.budget * 0.2));
|
|
77
|
+
if (isChatRound)
|
|
78
|
+
contextState = { ...contextState, background };
|
|
79
|
+
// 顺序即缓存策略:前缀必须“只增不变”才能复用 ——
|
|
80
|
+
// ① 会话背景(同一会话内基本不变)→ ② 固定说明 → ③ 动态尾部(选中文字/局部片段)
|
|
81
|
+
// 反过来写(动态在前、背景在后)会让缓存前缀在“选中文字”处就断掉:
|
|
82
|
+
// 实测同会话换一处选中,命中量从 5760 tokens 掉到 640~768。
|
|
83
|
+
const stablePrefix = [];
|
|
84
|
+
if (background && background.transcript) {
|
|
85
|
+
stablePrefix.push(`【会话背景】(按时间顺序;${background.marked ? '最后一条即选中文字所在的消息,已用 ▶ 标出,其后的对话未包含' : '未能定位选中位置,取的是最近的对话'})`, background.transcript, '', '上面是会话背景;下面是需要你解读的【选中文字】及其上下文。', '');
|
|
86
|
+
}
|
|
87
|
+
const isShotMode = body.kind === 'shot';
|
|
88
|
+
/**
|
|
89
|
+
* 截图取景范围:决定提示词口径(有没有红框、图是不是只有选区)。
|
|
90
|
+
* 老客户端不带时按"整窗 + 红框"兜底;非法值也退到整窗,避免把提示词写坏。
|
|
91
|
+
*/
|
|
92
|
+
const shotScope = body.shotScope === 'screen' || body.shotScope === 'window' || body.shotScope === 'margin' || body.shotScope === 'selection'
|
|
93
|
+
? body.shotScope
|
|
94
|
+
: 'window';
|
|
95
|
+
const shotFrame = body.shotFrame !== false;
|
|
96
|
+
/**
|
|
97
|
+
* 取标题(截图提问的第二次调用)。
|
|
98
|
+
*
|
|
99
|
+
* 关键:**前缀必须与回答那次逐字节一致**(同样的 system、同样的图、同样的提问),
|
|
100
|
+
* 这样图那部分能命中前缀缓存;只在最后追加一句"只输出标题"。
|
|
101
|
+
* 并且工具轮次强制为 0 —— 这次不该去调工具。
|
|
102
|
+
*/
|
|
103
|
+
const titleOnly = isShotMode && body.titleOnly === true;
|
|
104
|
+
// 截图提问:**没有选中文字**,这轮的文字就是用户说的那句话,正文不该套"选中文字"模板
|
|
105
|
+
const userText = isShotMode
|
|
106
|
+
? text
|
|
107
|
+
: [
|
|
108
|
+
...stablePrefix,
|
|
109
|
+
'【选中文字】',
|
|
110
|
+
text,
|
|
111
|
+
'',
|
|
112
|
+
`【所在位置】${label || '页面内容'}`,
|
|
113
|
+
'',
|
|
114
|
+
'【选中处的上下文片段】(选中部分用【】标出)',
|
|
115
|
+
context || '(未能取到上下文片段,请仅根据选中文字与会话背景作答)',
|
|
116
|
+
].join('\n');
|
|
117
|
+
const effort = typeof body.effort === 'string' && body.effort.length > 0 ? body.effort : config.reasoningEffort;
|
|
118
|
+
// 追问模式:客户端带 question 时,就是「就这段选中文字继续聊」
|
|
119
|
+
const question = typeof body.question === 'string' ? body.question.trim() : '';
|
|
120
|
+
const isChat = question.length > 0;
|
|
121
|
+
// 这一轮的附件(追问):/api/attach 存好之后的持久引用。形状在这里**收敛一次**,
|
|
122
|
+
// 历史那条路用的也是同一个收敛器(见 history-attachments.ts)。
|
|
123
|
+
const history = new AnalyzeHistory(body, isChat, historyStart, route, contextState);
|
|
124
|
+
return {
|
|
125
|
+
body, text, context, label, route, initialExplanation, historyStart, capacity, background,
|
|
126
|
+
isShotMode, shotScope, shotFrame, titleOnly, userText, effort, question, isChat, history
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=analyze-request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-request.js","sourceRoot":"","sources":["../../src/host/analyze-request.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { BlockAssembler, ReasoningEffortId } from '@deepseek-ai/dsh-llm';
|
|
2
|
+
import { name } from './constants.js';
|
|
3
|
+
import { createThinkFilter } from './filters.js';
|
|
4
|
+
import { sse } from './http.js';
|
|
5
|
+
import { systemMessageOf } from './messages.js';
|
|
6
|
+
/** Stream and filter one upstream round, preserving chunk and diagnostic event order. */
|
|
7
|
+
export async function streamAnalyzeRound(env, state, round, wrapUp, roundEffort) {
|
|
8
|
+
const { deps, request, tools, prompt, messages, res, controller, executionState } = env;
|
|
9
|
+
const { ctx, config } = deps;
|
|
10
|
+
const { body, route } = request;
|
|
11
|
+
const { sessionId, toolSchemas } = tools;
|
|
12
|
+
const { systemPrompt } = prompt;
|
|
13
|
+
const { checkedMessages, baseMessage, openingMessages } = messages;
|
|
14
|
+
const roundStartedAt = Date.now();
|
|
15
|
+
const stream = ctx.llm.stream({
|
|
16
|
+
provider: route.provider,
|
|
17
|
+
model: route.model,
|
|
18
|
+
// 带上会话 id:主会话 agent loop 一直传它,适配器会据此设置上游的会话头。
|
|
19
|
+
// 插件以前没传,结果是所有小窗请求共用静态会话头 —— 而中继是按会话跟踪的(实测长回答被掐)。
|
|
20
|
+
...(sessionId ? { sessionId: sessionId } : {}),
|
|
21
|
+
system: undefined,
|
|
22
|
+
messages: checkedMessages([
|
|
23
|
+
// 第二参数(组装这段提示词的插件名):**新老版本签名不一样,两边都得能编译**——
|
|
24
|
+
// · npm 上按 peer 范围 `>=0.1.5-rc <2` 解析到的是 0.1.5-rc.3:`(text, plugin)` 两个必填
|
|
25
|
+
// (CI 就是拿这份类型做构建校验的,少传就 TS2554);
|
|
26
|
+
// · 本机 / 新版运行时(0.1.7-rc.x):只剩 `(text)`,多传的参数会被忽略。
|
|
27
|
+
// 所以统一走 systemMessageOf 这个宽松别名(见文件下方的定义),两边都调得动。
|
|
28
|
+
systemMessageOf(wrapUp
|
|
29
|
+
? `${systemPrompt}\n\n【收尾】工具轮次已用完:直接基于已经拿到的信息给出结论,不要再请求工具,也不要复述查询过程。` +
|
|
30
|
+
'正文里不要出现任何工具调用格式(包括 DeepSeek 的 DSML 写法,如 invoke/parameter 标记)——那些会被当作乱码展示给用户。'
|
|
31
|
+
: systemPrompt, name),
|
|
32
|
+
...(round === 0 ? [baseMessage, ...openingMessages] : [baseMessage, ...openingMessages, ...state.toolMessages]),
|
|
33
|
+
]),
|
|
34
|
+
// 工具**每轮都在请求里**(照主会话的做法):收尾轮以前故意不带工具"逼结论",
|
|
35
|
+
// 结果模型退到文本层、把工具调用标记写进正文(实测 wrapUp 轮 raw=726 → emitted=0)。
|
|
36
|
+
// 主会话从不摘工具,模型也就从不写这种标记 —— 这里与它保持一致。
|
|
37
|
+
...(toolSchemas.length > 0 ? { tools: toolSchemas } : {}),
|
|
38
|
+
...(config.temperature >= 0 ? { temperature: config.temperature } : {}),
|
|
39
|
+
...(config.maxTokens > 0 ? { maxTokens: config.maxTokens } : {}),
|
|
40
|
+
...(roundEffort ? { reasoningEffort: ReasoningEffortId(roundEffort) } : {}),
|
|
41
|
+
signal: controller.signal,
|
|
42
|
+
});
|
|
43
|
+
executionState.upstreamStarted = true;
|
|
44
|
+
const assembler = new BlockAssembler();
|
|
45
|
+
// 本轮吐出的正文字数:这一轮如果最后是要调工具,那这些字其实是"过程旁白"
|
|
46
|
+
// ("我还得再搜一次""先看看拿到的标题"这类),要被撤回,不能当成答案留在小窗里
|
|
47
|
+
let roundText = '';
|
|
48
|
+
// 有的模型把思考内联在正文里(<think>…</think>):拆出来走 thought,别当答案
|
|
49
|
+
// 每轮一个过滤器:未闭合的残渣块只在本轮内作废。
|
|
50
|
+
// 共用一个的话,某一轮吐了未闭合的 DSML(实测收尾轮很常见)会让 depth 一直 >0,
|
|
51
|
+
// 后面所有轮次的正文都被吞掉 —— 表现就是"只完成了工具查询,没有产出正文"(用户截图报的)。
|
|
52
|
+
const think = createThinkFilter();
|
|
53
|
+
let roundRaw = 0;
|
|
54
|
+
let roundEmitted = 0;
|
|
55
|
+
let roundThink = 0;
|
|
56
|
+
let roundFinish = '';
|
|
57
|
+
/** 诊断用:本轮最后若干分片的类型与大小(看上游是发了 finish 还是直接断流)。 */
|
|
58
|
+
const tailChunks = [];
|
|
59
|
+
const emit = (part) => {
|
|
60
|
+
if (part.think) {
|
|
61
|
+
roundThink += part.think.length;
|
|
62
|
+
sse(res, { type: 'thought', text: part.think });
|
|
63
|
+
}
|
|
64
|
+
// 残渣过滤放在 think 之后:先分出思考,再把正文里的工具调用标记丢掉
|
|
65
|
+
const text = part.text;
|
|
66
|
+
if (text) {
|
|
67
|
+
roundEmitted += text.length;
|
|
68
|
+
state.chars += text.length;
|
|
69
|
+
state.answer += text;
|
|
70
|
+
roundText += text;
|
|
71
|
+
sse(res, { type: 'delta', text: text });
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
for await (const chunk of stream) {
|
|
75
|
+
assembler.push(chunk);
|
|
76
|
+
if (body.debug === true) {
|
|
77
|
+
const size = chunk.type === 'text-delta' ? chunk.text.length : 0;
|
|
78
|
+
tailChunks.push(`${chunk.type}:${size}`);
|
|
79
|
+
if (tailChunks.length > 14)
|
|
80
|
+
tailChunks.shift();
|
|
81
|
+
}
|
|
82
|
+
if (chunk.type === 'text-delta') {
|
|
83
|
+
roundRaw += chunk.text.length;
|
|
84
|
+
emit(think.push(chunk.text));
|
|
85
|
+
}
|
|
86
|
+
else if (chunk.type === 'reasoning-delta') {
|
|
87
|
+
// 思考过程也透传:首字前那几秒如果只有转圈,用户会以为卡死了。
|
|
88
|
+
// 客户端只留尾部一小段当"正在想什么"的提示,不进正文。
|
|
89
|
+
sse(res, { type: 'thought', text: chunk.text });
|
|
90
|
+
}
|
|
91
|
+
else if (chunk.type === 'usage') {
|
|
92
|
+
state.usage = chunk.usage;
|
|
93
|
+
}
|
|
94
|
+
else if (chunk.type === 'finish') {
|
|
95
|
+
roundFinish = String(chunk.reason.kind);
|
|
96
|
+
if (chunk.reason.kind === 'error' || chunk.reason.kind === 'aborted') {
|
|
97
|
+
state.errored = true;
|
|
98
|
+
// 先只记下来:如果接下来要"换档重试",这条错误就不该发给用户
|
|
99
|
+
// (否则客户端先渲染一条失败提示,重试的正文就贴在失败提示后面了)
|
|
100
|
+
state.errorMessage =
|
|
101
|
+
chunk.reason.failure?.message ?? `模型调用${chunk.reason.kind === 'aborted' ? '被中断' : '失败'}`;
|
|
102
|
+
state.errorCode = chunk.reason.failure?.code;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
emit(think.flush());
|
|
107
|
+
state.roundDiag.push({
|
|
108
|
+
round,
|
|
109
|
+
wrapUp,
|
|
110
|
+
ms: Date.now() - roundStartedAt,
|
|
111
|
+
raw: roundRaw,
|
|
112
|
+
emitted: roundEmitted,
|
|
113
|
+
think: roundThink,
|
|
114
|
+
finish: roundFinish || '(none)',
|
|
115
|
+
tools: assembler.blocks().filter((block) => block.type === 'tool-call').length,
|
|
116
|
+
...(body.debug === true ? { tailChunks } : {}),
|
|
117
|
+
outTokens: state.usage?.outputTokens,
|
|
118
|
+
});
|
|
119
|
+
return { assembler, roundText };
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=analyze-round.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-round.js","sourceRoot":"","sources":["../../src/host/analyze-round.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { createAssistantMessage, createToolResultMessage, createUserMessage } from '@deepseek-ai/dsh-llm';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { estimateTextTokens } from '../chat-context.js';
|
|
4
|
+
import { MATERIAL_TOOL, restoreMaterial } from './chat-materials.js';
|
|
5
|
+
import { sse } from './http.js';
|
|
6
|
+
import { describeToolCall, digestToolResult, FS_TOOL_NAMES, isReadAllowed, runTool } from './tools.js';
|
|
7
|
+
/** Execute one round of allowed calls and admit restored materials into subsequent messages. */
|
|
8
|
+
export async function executeAnalyzeTools(env, state, blocks, calls, round) {
|
|
9
|
+
const { deps, request, tools, res, controller } = env;
|
|
10
|
+
const { ctx, config, historyStore } = deps;
|
|
11
|
+
const { body, route, history, capacity } = request;
|
|
12
|
+
const { agent, toolSchemas, readRoot } = tools;
|
|
13
|
+
state.toolMessages.push(createAssistantMessage({
|
|
14
|
+
content: blocks,
|
|
15
|
+
source: { provider: route.provider, model: route.model },
|
|
16
|
+
}));
|
|
17
|
+
const restoredBlocks = [];
|
|
18
|
+
state.toolContextTokens += estimateTextTokens(JSON.stringify(blocks));
|
|
19
|
+
for (const call of calls) {
|
|
20
|
+
if (call.type !== 'tool-call')
|
|
21
|
+
continue;
|
|
22
|
+
state.toolCalls += 1;
|
|
23
|
+
let parsed = {};
|
|
24
|
+
try {
|
|
25
|
+
parsed = call.arguments ? JSON.parse(call.arguments) : {};
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
parsed = {};
|
|
29
|
+
}
|
|
30
|
+
const label2 = describeToolCall(call.name, parsed);
|
|
31
|
+
const callId = String(call.id ?? `round${String(round)}-${String(state.toolCalls)}`);
|
|
32
|
+
sse(res, { type: 'tool', phase: 'start', callId, name: call.name, detail: label2, round });
|
|
33
|
+
const startedAt = Date.now();
|
|
34
|
+
// 参数名有讲究:read/write/edit 用 file_path,grep/glob 用 path。
|
|
35
|
+
// 只认 path 的话 read 的 file_path 会是 undefined → 边界检查被静默绕过(实测踩过)。
|
|
36
|
+
const rawPath = parsed?.file_path ?? parsed?.path;
|
|
37
|
+
const wantPath = typeof rawPath === 'string' ? rawPath : '';
|
|
38
|
+
let restored;
|
|
39
|
+
if (call.name === MATERIAL_TOOL.name && toolSchemas.some(schema => schema.name === call.name)) {
|
|
40
|
+
restored = await restoreMaterial(ctx, history.catalog, parsed, {
|
|
41
|
+
through: history.contextState.through, key: typeof body.key === 'string' ? body.key : '',
|
|
42
|
+
maxChars: config.toolResultMaxChars, readMessage: historyStore.readMessage
|
|
43
|
+
});
|
|
44
|
+
if (restored.restored && capacity && capacity.attachmentPrice(restored.restored) + history.contextEstimate + state.toolContextTokens > capacity.budget * 0.95) {
|
|
45
|
+
restored = { content: [{ type: 'text', text: '这份材料超过本轮剩余容量,请减少本轮材料后重新查看。' }], isError: true };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const execution = restored || (!toolSchemas.some((schema) => schema.name === call.name)
|
|
49
|
+
? { content: [{ type: 'text', text: `(调用已拒绝:${call.name} 不在本次允许的工具中)` }], isError: true }
|
|
50
|
+
: FS_TOOL_NAMES.includes(call.name) && !isReadAllowed(readRoot, wantPath, history.attachedPaths)
|
|
51
|
+
? {
|
|
52
|
+
content: [
|
|
53
|
+
{
|
|
54
|
+
type: 'text',
|
|
55
|
+
text: `(越界已拒绝:文件类工具只能访问当前项目目录${readRoot ? `(${readRoot})` : ''},以及用户本次附带的文件;请求的路径是 ${wantPath || '(未给)'})`,
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
isError: true,
|
|
59
|
+
}
|
|
60
|
+
: await runTool(ctx, call.name, parsed, controller.signal, config.toolResultMaxChars, agent));
|
|
61
|
+
state.toolContextTokens += estimateTextTokens(JSON.stringify(execution.content));
|
|
62
|
+
if (restored?.restored) {
|
|
63
|
+
const item = restored.restored;
|
|
64
|
+
restoredBlocks.push(item.kind === 'image' ? { type: 'image', attachment: item.ref } : { type: 'file', attachment: item.ref });
|
|
65
|
+
if (capacity)
|
|
66
|
+
state.toolContextTokens += capacity.attachmentPrice(item);
|
|
67
|
+
if (item.kind === 'file') {
|
|
68
|
+
const store = ctx.get('attachments');
|
|
69
|
+
const path = store?.fileHostPath?.(item.ref);
|
|
70
|
+
if (path)
|
|
71
|
+
history.attachedPaths.add(resolve(path));
|
|
72
|
+
}
|
|
73
|
+
sse(res, { type: 'material-restored', attachment: item });
|
|
74
|
+
}
|
|
75
|
+
// 结果也回传:小窗里能看见"查了什么、命中什么、链接是什么",否则工具是个黑盒
|
|
76
|
+
const digest = digestToolResult(execution.content);
|
|
77
|
+
sse(res, {
|
|
78
|
+
type: 'tool',
|
|
79
|
+
phase: 'done',
|
|
80
|
+
callId,
|
|
81
|
+
name: call.name,
|
|
82
|
+
detail: label2,
|
|
83
|
+
round,
|
|
84
|
+
ok: !execution.isError,
|
|
85
|
+
ms: Date.now() - startedAt,
|
|
86
|
+
chars: digest.chars,
|
|
87
|
+
preview: digest.preview,
|
|
88
|
+
urls: digest.urls,
|
|
89
|
+
});
|
|
90
|
+
state.toolMessages.push(createToolResultMessage({ callId: call.id, content: execution.content, isError: execution.isError }));
|
|
91
|
+
// 结论轮要用:把"查了什么 + 拿到了什么"写成纯文本,避免重放工具调用链
|
|
92
|
+
state.toolDigestLines.push(`· ${call.name}(${label2 || '查询'}):${digest.preview}`);
|
|
93
|
+
}
|
|
94
|
+
state.recoveredMaterialBlocks.push(...restoredBlocks);
|
|
95
|
+
if (restoredBlocks.length > 0)
|
|
96
|
+
state.toolMessages.push(createUserMessage({ source: { kind: 'user' }, content: restoredBlocks }));
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=analyze-tool-execution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-tool-execution.js","sourceRoot":"","sources":["../../src/host/analyze-tool-execution.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AACzG,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AACpE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAA;AAC/B,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,aAAa,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAItG,gGAAgG;AAChG,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,GAA4B,EAAE,KAAyB,EAAE,MAAsB,EAAE,KAAqB,EAAE,KAAa;IAC7J,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,GAAG,CAAA;IACrD,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI,CAAA;IAC1C,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAA;IAClD,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAA;IAC9C,KAAK,CAAC,YAAY,CAAC,IAAI,CACrB,sBAAsB,CAAC;QACrB,OAAO,EAAE,MAAM;QACf,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE;KACzD,CAAC,CACH,CAAA;IACD,MAAM,cAAc,GAAmB,EAAE,CAAA;IACzC,KAAK,CAAC,iBAAiB,IAAI,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAA;IACrE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW;YAAE,SAAQ;QACvC,KAAK,CAAC,SAAS,IAAI,CAAC,CAAA;QACpB,IAAI,MAAM,GAAY,EAAE,CAAA;QACxB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAC3D,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,GAAG,EAAE,CAAA;QACb,CAAC;QACD,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QAClD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,QAAQ,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;QACpF,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;QAC1F,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC5B,uDAAuD;QACvD,8DAA8D;QAC9D,MAAM,OAAO,GAAI,MAAkD,EAAE,SAAS,IAAK,MAA6B,EAAE,IAAI,CAAA;QACtH,MAAM,QAAQ,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;QAC3D,IAAI,QAAiE,CAAA;QACrE,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,CAAC,IAAI,IAAI,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9F,QAAQ,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE;gBAC7D,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,IAAI,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;gBACxF,QAAQ,EAAE,MAAM,CAAC,kBAAkB,EAAE,WAAW,EAAE,YAAY,CAAC,WAAW;aAC3E,CAAC,CAAA;YACF,IAAI,QAAQ,CAAC,QAAQ,IAAI,QAAQ,IAAI,QAAQ,CAAC,eAAe,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,eAAe,GAAG,KAAK,CAAC,iBAAiB,GAAG,QAAQ,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;gBAC9J,QAAQ,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,4BAA4B,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;YAC/F,CAAC;QACH,CAAC;QACD,MAAM,SAAS,GAAG,QAAQ,IAAI,CAC5B,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC;YACtD,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,IAAI,CAAC,IAAI,cAAc,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE;YAClG,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,aAAa,CAAC;gBAC9F,CAAC,CAAC;oBACA,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAe;4BACrB,IAAI,EAAE,yBAAyB,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,uBAAuB,QAAQ,IAAI,MAAM,GAAG;yBAC3G;qBACF;oBACD,OAAO,EAAE,IAAI;iBACd;gBACD,CAAC,CAAC,MAAM,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC,CAAA;QACnG,KAAK,CAAC,iBAAiB,IAAI,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAA;QAChF,IAAI,QAAQ,EAAE,QAAQ,EAAE,CAAC;YACvB,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAA;YAC9B,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,GAAY,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,GAAY,EAAE,CAAC,CAAA;YAC/I,IAAI,QAAQ;gBAAE,KAAK,CAAC,iBAAiB,IAAI,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,CAAA;YACvE,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBACzB,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,aAAa,CAAwE,CAAA;gBAC3G,MAAM,IAAI,GAAG,KAAK,EAAE,YAAY,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;gBAC5C,IAAI,IAAI;oBAAE,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;YACpD,CAAC;YACD,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,mBAAmB,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAA;QAC3D,CAAC;QACD,yCAAyC;QACzC,MAAM,MAAM,GAAG,gBAAgB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;QAClD,GAAG,CAAC,GAAG,EAAE;YACP,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,MAAM;YACb,MAAM;YACN,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,MAAM;YACd,KAAK;YACL,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO;YACtB,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;YAC1B,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,IAAI,EAAE,MAAM,CAAC,IAAI;SAClB,CAAC,CAAA;QACF,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,uBAAuB,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;QAC7H,uCAAuC;QACvC,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,IAAI,MAAM,IAAI,IAAI,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC,CAAA;IACnF,CAAC;IACD,KAAK,CAAC,uBAAuB,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,CAAA;IACrD,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,iBAAiB,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC,CAAA;AAElI,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { MATERIAL_TOOL } from './chat-materials.js';
|
|
2
|
+
import { name } from './constants.js';
|
|
3
|
+
import { sessionIdOf } from './context.js';
|
|
4
|
+
import { FS_TOOL_NAMES, resolveToolNames, webFetchUsable } from './tools.js';
|
|
5
|
+
/** Resolve session scope, allowed tools, fetch availability and filesystem boundary. */
|
|
6
|
+
export async function planAnalyzeTools(deps, request) {
|
|
7
|
+
const { ctx, config, sessions } = deps;
|
|
8
|
+
const { body, isChat, history } = request;
|
|
9
|
+
// 可用工具(白名单,默认只有联网搜索/抓取):交给模型自己决定要不要用。
|
|
10
|
+
// 注意工具是「按会话作用域」注册的(全局视图里看不到 web_search 等),
|
|
11
|
+
// 所以要拿该会话的 agent 当 scope 去查,并把同一个 agent 传给 execute。
|
|
12
|
+
const agents = ctx.get('agents');
|
|
13
|
+
const sessionId = sessionIdOf(body);
|
|
14
|
+
let agent = sessionId ? agents?.get?.(sessionId) : undefined;
|
|
15
|
+
let agentScope = agent ? 'session' : '';
|
|
16
|
+
if (!agent) {
|
|
17
|
+
// 回退:本会话还没起 agent(刚开的新会话/agent 已释放)时,用任一活跃 agent 当作用域。
|
|
18
|
+
// 不这么做的话,session-scoped 的 web_search/web_fetch 在全局视图里根本不可见 →
|
|
19
|
+
// 工具静默为空,模型还会把工具调用当正文吐出来(实测见过 <ds_safety_tool_call>)。
|
|
20
|
+
const live = agents?.list?.() ?? [];
|
|
21
|
+
if (live.length > 0) {
|
|
22
|
+
agent = live[0];
|
|
23
|
+
agentScope = 'fallback';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const toolSchemas = [];
|
|
27
|
+
/** 诊断:这一轮是不是走了"备用联网工具"(首选联网工具一个都不在)。 */
|
|
28
|
+
let toolFallbackUsed = false;
|
|
29
|
+
if (config.tools && config.maxToolRounds > 0) {
|
|
30
|
+
const registry = ctx.get('tools');
|
|
31
|
+
const split = (value) => value.split(',').map((item) => item.trim()).filter((item) => item.length > 0);
|
|
32
|
+
let visible = [];
|
|
33
|
+
try {
|
|
34
|
+
visible = registry?.schemas?.(agent) ?? [];
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
ctx.logger?.warn?.(`[${name}] 读取工具表失败:${String(error?.message ?? error)}`);
|
|
38
|
+
}
|
|
39
|
+
const allowed = resolveToolNames(split(config.toolNames), split(config.fallbackToolNames), visible.map((schema) => schema.name));
|
|
40
|
+
toolFallbackUsed = !allowed.includes('advanced_search') && !allowed.includes('platform_search');
|
|
41
|
+
for (const schema of visible) {
|
|
42
|
+
if (allowed.includes(schema.name))
|
|
43
|
+
toolSchemas.push(schema);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// 本机抓不了网页(fake-IP 代理 / SSRF 防护)时,把 web_fetch 摘掉:
|
|
47
|
+
// 否则模型每次都要白跑一轮(5~15s)才拿到"resolves to a non-public IP address"。
|
|
48
|
+
let fetchBlockedSample = '';
|
|
49
|
+
if (toolSchemas.some((schema) => schema.name === 'web_fetch')) {
|
|
50
|
+
const probe = await webFetchUsable();
|
|
51
|
+
if (!probe.usable) {
|
|
52
|
+
fetchBlockedSample = probe.sample;
|
|
53
|
+
for (let i = toolSchemas.length - 1; i >= 0; i -= 1) {
|
|
54
|
+
if (toolSchemas[i]?.name === 'web_fetch')
|
|
55
|
+
toolSchemas.splice(i, 1);
|
|
56
|
+
}
|
|
57
|
+
ctx.logger?.warn?.(`[${name}] 网页抓取不可用(域名解析到 ${probe.sample},属保留地址段),已从工具表移除 web_fetch`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (isChat && config.tools && config.maxToolRounds > 0 && (history.rawHistory.length > 0 || history.catalog.length > 0 || history.contextState.through > 0)) {
|
|
61
|
+
toolSchemas.push(MATERIAL_TOOL);
|
|
62
|
+
}
|
|
63
|
+
// 文件类工具的边界:默认只允许会话工作目录;'*' = 不限制;配置了具体目录就用它。
|
|
64
|
+
// 拿不到工作目录时**不设限**(否则新会话里 read 直接全废),但会打日志说明。
|
|
65
|
+
const wantsFsTools = toolSchemas.some((schema) => FS_TOOL_NAMES.includes(schema.name));
|
|
66
|
+
let readRoot = '';
|
|
67
|
+
if (wantsFsTools) {
|
|
68
|
+
if (config.toolReadRoot === '*') {
|
|
69
|
+
readRoot = '';
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
readRoot = config.toolReadRoot || (await sessions.resolveSessionCwd(sessionIdOf(body))) || '';
|
|
73
|
+
if (!readRoot)
|
|
74
|
+
ctx.logger?.warn?.(`[${name}] 拿不到会话工作目录,文件工具本次不设边界`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return { agent, agentScope, sessionId, toolSchemas, toolFallbackUsed, fetchBlockedSample, wantsFsTools, readRoot };
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=analyze-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-tools.js","sourceRoot":"","sources":["../../src/host/analyze-tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-types.js","sourceRoot":"","sources":["../../src/host/analyze-types.ts"],"names":[],"mappings":""}
|