@yfwu2020/dsh-selection-explain 0.10.4 → 0.10.6
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 +13 -11
- package/cordis.patch.yml +1 -1
- package/lib/client.js +10698 -12424
- package/lib/client.js.map +7 -0
- package/lib/config-values.js +55 -0
- package/lib/config-values.js.map +1 -0
- package/lib/host/analyze.js +795 -0
- package/lib/host/analyze.js.map +1 -0
- package/lib/host/config.js +81 -0
- package/lib/host/config.js.map +1 -0
- package/lib/host/constants.js +25 -0
- package/lib/host/constants.js.map +1 -0
- package/lib/host/context.js +237 -0
- package/lib/host/context.js.map +1 -0
- package/lib/host/design-skill.js +42 -0
- package/lib/host/design-skill.js.map +1 -0
- package/lib/host/effort.js +239 -0
- package/lib/host/effort.js.map +1 -0
- package/lib/host/filters.js +132 -0
- package/lib/host/filters.js.map +1 -0
- package/lib/host/history-store.js +404 -0
- package/lib/host/history-store.js.map +1 -0
- package/lib/host/http.js +46 -0
- package/lib/host/http.js.map +1 -0
- package/lib/host/messages.js +14 -0
- package/lib/host/messages.js.map +1 -0
- package/lib/host/mic.js +246 -0
- package/lib/host/mic.js.map +1 -0
- package/lib/host/models.js +246 -0
- package/lib/host/models.js.map +1 -0
- package/lib/host/plugin.js +41 -0
- package/lib/host/plugin.js.map +1 -0
- package/lib/host/promote.js +219 -0
- package/lib/host/promote.js.map +1 -0
- package/lib/host/routes.js +237 -0
- package/lib/host/routes.js.map +1 -0
- package/lib/host/sessions.js +181 -0
- package/lib/host/sessions.js.map +1 -0
- package/lib/host/settings-store.js +140 -0
- package/lib/host/settings-store.js.map +1 -0
- package/lib/host/speech.js +320 -0
- package/lib/host/speech.js.map +1 -0
- package/lib/host/tools.js +179 -0
- package/lib/host/tools.js.map +1 -0
- package/lib/host/types.js +2 -0
- package/lib/host/types.js.map +1 -0
- package/lib/index.js +10 -3765
- package/lib/index.js.map +1 -1
- package/lib/prompts.js +1 -1
- package/lib/settings.js +17 -27
- package/lib/settings.js.map +1 -1
- package/lib/types/config-values.d.ts +175 -0
- package/lib/types/host/analyze.d.ts +10 -0
- package/lib/types/host/config.d.ts +147 -0
- package/lib/types/host/constants.d.ts +24 -0
- package/lib/types/host/context.d.ts +41 -0
- package/lib/types/host/design-skill.d.ts +1 -0
- package/lib/types/host/effort.d.ts +61 -0
- package/lib/types/host/filters.d.ts +20 -0
- package/lib/types/host/history-store.d.ts +13 -0
- package/lib/types/host/http.d.ts +8 -0
- package/lib/types/host/messages.d.ts +13 -0
- package/lib/types/host/mic.d.ts +17 -0
- package/lib/types/host/models.d.ts +57 -0
- package/lib/types/host/plugin.d.ts +3 -0
- package/lib/types/host/promote.d.ts +9 -0
- package/lib/types/host/routes.d.ts +14 -0
- package/lib/types/host/sessions.d.ts +14 -0
- package/lib/types/host/settings-store.d.ts +8 -0
- package/lib/types/host/speech.d.ts +23 -0
- package/lib/types/host/tools.d.ts +39 -0
- package/lib/types/host/types.d.ts +89 -0
- package/lib/types/index.d.ts +12 -441
- package/lib/types/prompts.d.ts +1 -1
- package/lib/types/settings.d.ts +1 -1
- package/package.json +31 -21
- package/assets/code.png +0 -0
- package/assets/detail.png +0 -0
- package/assets/quotes.png +0 -0
- package/assets/stage1.png +0 -0
- package/assets/stage2.png +0 -0
- package/assets/translation.png +0 -0
- package/assets/voice-card-light.png +0 -0
- package/assets/voice-inserted.png +0 -0
- package/assets/voice-settings.png +0 -0
- package/assets/voice.png +0 -0
- package/assets/web.png +0 -0
- package/scripts/build-demo-pages.mjs +0 -350
- package/scripts/build-vcard-lab.mjs +0 -834
- package/scripts/build.sh +0 -147
- package/scripts/crop-png.mjs +0 -142
- package/scripts/dump-prompt.mjs +0 -143
- package/scripts/fixtures/fake-mic-probe.sh +0 -9
- package/scripts/gen-star-path.mjs +0 -71
- package/scripts/measure-cost.mjs +0 -251
- package/scripts/smoke-bridge.mjs +0 -365
- package/scripts/smoke-panel.mjs +0 -1903
- package/scripts/smoke-voice.mjs +0 -774
- package/scripts/test-bridge.mjs +0 -412
- package/scripts/test-client.mjs +0 -6175
- package/scripts/test-effort-map.mjs +0 -129
- package/scripts/test-effort-retry.mjs +0 -109
- package/scripts/test-escape-focus.mjs +0 -101
- package/scripts/test-filters.mjs +0 -146
- package/scripts/test-format.mjs +0 -93
- package/scripts/test-guard.mjs +0 -48
- package/scripts/test-mic-build.mjs +0 -146
- package/scripts/test-mic-idle.mjs +0 -158
- package/scripts/test-model-follow.mjs +0 -193
- package/scripts/test-prompt.mjs +0 -193
- package/scripts/test-route-cache.mjs +0 -138
- package/scripts/test-settings-behavior.mjs +0 -188
- package/scripts/test-settings-host.mjs +0 -48
- package/scripts/test-settings.mjs +0 -329
- package/scripts/test-speech.mjs +0 -220
- package/scripts/test-transcript.mjs +0 -151
- package/src/client/index.js +0 -12580
- package/src/index.ts +0 -4254
- package/src/prompts.ts +0 -144
- package/src/settings.ts +0 -313
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/** Shared defaults and boundaries; no host or browser dependencies. */
|
|
2
|
+
/** 插件配置。 */
|
|
3
|
+
export interface Config {
|
|
4
|
+
/** 固定 provider 路由;留空 = 跟随主会话(用户在 DSH 里选的默认模型)。 */
|
|
5
|
+
provider: string;
|
|
6
|
+
/** 固定 model id;留空 = 跟随主会话。 */
|
|
7
|
+
model: string;
|
|
8
|
+
/**
|
|
9
|
+
* **追问**单独用的 provider;留空 = 跟首轮/次轮同一个(默认如此)。
|
|
10
|
+
*
|
|
11
|
+
* 为什么要能单独设:首轮/次轮要的是"读懂上下文",追问往往是"快速问一句",
|
|
12
|
+
* 两者对模型的要求不同(一个要准、一个要快)。
|
|
13
|
+
*/
|
|
14
|
+
chatProvider: string;
|
|
15
|
+
/** **追问**单独用的 model id;留空 = 跟首轮/次轮同一个。 */
|
|
16
|
+
chatModel: string;
|
|
17
|
+
/** **次轮详解**的推理档位(off / low / high / max);留空 = 适配器默认。 */
|
|
18
|
+
reasoningEffort: string;
|
|
19
|
+
/** **首轮**(翻译 / 解读 / 注释)的推理档位。 */
|
|
20
|
+
translationReasoningEffort: string;
|
|
21
|
+
historyMaxEntries: number;
|
|
22
|
+
/** 采样温度。 */
|
|
23
|
+
temperature: number;
|
|
24
|
+
/** 输出上限。 */
|
|
25
|
+
maxTokens: number;
|
|
26
|
+
/** 单次调用超时(毫秒)。 */
|
|
27
|
+
timeoutMs: number;
|
|
28
|
+
/** 选中文字长度上限(字符)。 */
|
|
29
|
+
maxSelectionChars: number;
|
|
30
|
+
/** 上下文长度上限(字符)。 */
|
|
31
|
+
maxContextChars: number;
|
|
32
|
+
/** 每分钟最大请求数(本地限流,防止误触发刷爆额度)。 */
|
|
33
|
+
maxRequestsPerMinute: number;
|
|
34
|
+
/** 是否注入当前会话的对话背景(判断指代与前提的关键)。 */
|
|
35
|
+
sessionContext: boolean;
|
|
36
|
+
/** 会话背景最多保留多少条消息(从最新往前取);第二阶段(详解)用这个值。 */
|
|
37
|
+
sessionContextMaxMessages: number;
|
|
38
|
+
/** 第一阶段(仅翻译)用的背景条数:更少 → 首字更快;点「展开详解」时才用上面那个上限。 */
|
|
39
|
+
sessionContextFastMessages: number;
|
|
40
|
+
/** 会话背景字符上限;0 = 不限(默认),只按消息条数取窗口。 */
|
|
41
|
+
sessionContextMaxChars: number;
|
|
42
|
+
/**
|
|
43
|
+
* 引用(❝)上下文:引用文字所在的那一组对话 ± 几组(一组 = 用户消息 + 它的助手回复)。
|
|
44
|
+
* 默认 1 = 上下各一组(需求:至少带上引用所在那一组与上下各一组)。
|
|
45
|
+
*/
|
|
46
|
+
quoteContextRounds: number;
|
|
47
|
+
/** 引用上下文里单条消息的字数上限(超了**围绕引用**截断,不裁掉引用本身)。 */
|
|
48
|
+
quoteContextMaxCharsPerTurn: number;
|
|
49
|
+
/** 引用上下文整段的字数上限(超了丢最早的几组)。 */
|
|
50
|
+
quoteContextMaxChars: number;
|
|
51
|
+
/** 共享结果缓存 TTL(毫秒):同会话+同选中+同局部片段+同背景时直接回放;0 = 关闭。 */
|
|
52
|
+
resultCacheTtlMs: number;
|
|
53
|
+
/** 是否允许解读过程调用工具(联网搜索等)。 */
|
|
54
|
+
tools: boolean;
|
|
55
|
+
/** 允许调用的工具名(逗号分隔);默认只放联网搜索与抓取。 */
|
|
56
|
+
toolNames: string;
|
|
57
|
+
fallbackToolNames: string;
|
|
58
|
+
/** 最多几轮工具调用。 */
|
|
59
|
+
maxToolRounds: number;
|
|
60
|
+
/** 单个工具结果注入模型前的字符上限。 */
|
|
61
|
+
toolResultMaxChars: number;
|
|
62
|
+
/** 文件类工具(read/grep/glob)的读取边界:'' = 会话工作目录,'*' = 不限制,其他 = 该目录 */
|
|
63
|
+
toolReadRoot: string;
|
|
64
|
+
/** 追问(对话小窗)用的推理档位:通常比次轮详解轻,响应更快。 */
|
|
65
|
+
chatReasoningEffort: string;
|
|
66
|
+
/**
|
|
67
|
+
* 侧边栏 HTML 预览里的划词桥(默认开)。
|
|
68
|
+
*
|
|
69
|
+
* 侧边栏的预览是不透明源沙箱 iframe,父页面读不到里面的选区 —— 只有往被预览的
|
|
70
|
+
* 文档里注入一段桥脚本才能划词。代价:预览帧要多一个 `allow-scripts`
|
|
71
|
+
* (仍然**没有** `allow-same-origin`,预览页读不到 GUI 数据),基础预览那份
|
|
72
|
+
* 已清洗过的 HTML 的 CSP 会从 `script-src 'none'` 放宽到 `'unsafe-inline'`。
|
|
73
|
+
* 关掉 = 侧边栏网页里不弹「解读」按钮。
|
|
74
|
+
*/
|
|
75
|
+
bridgeSidebarPreview: boolean;
|
|
76
|
+
/** 是否显示右下角悬浮胶囊(最近一次划词的状态入口)。 */
|
|
77
|
+
pillEnabled: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* 静置多久把胶囊收成小球(毫秒)。
|
|
80
|
+
*
|
|
81
|
+
* 只在**没装费用胶囊**时生效 —— 有费用胶囊时两者并排,收球会让它们错位。
|
|
82
|
+
* 默认 10 秒:短于这个数会显得"刚看一眼就没了",长了又失去"收起来不挡视线"的意义。
|
|
83
|
+
*/
|
|
84
|
+
pillIdleMs: number;
|
|
85
|
+
/**
|
|
86
|
+
* 开麦结束、**一个字都没说**时,直接收起临时输入框。
|
|
87
|
+
*
|
|
88
|
+
* 默认开(2026-10-09 用户指定):等于替用户按了 Esc(带关机动画)。
|
|
89
|
+
* 关掉则回到"卡片留着" —— 一个字没说时可以接着手动打字。
|
|
90
|
+
*
|
|
91
|
+
* 注意"结束"不是"松手那一瞬间":输入法在松手后还会做一次**智能整理**(改写输入框内容),
|
|
92
|
+
* 所以真正动作要等到文字定稿(见客户端的 VOICE_SETTLE_MS)。否则会取消掉马上就要落进来的整理结果。
|
|
93
|
+
*/
|
|
94
|
+
voiceCancelOnSilence: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* 开麦结束、**已经说出文字**时,直接发送(跳过手动点发送键)。
|
|
97
|
+
*
|
|
98
|
+
* 默认开(2026-10-09 用户指定):等于替用户点了发送键。
|
|
99
|
+
* 关掉则回到"先看一眼再点" —— 发送会开小窗、开始一次真实请求,不可逆。
|
|
100
|
+
*
|
|
101
|
+
* 同样要等文字定稿:松手那一刻输入法还没整理完,立刻发送发出去的是没整理的草稿。
|
|
102
|
+
*/
|
|
103
|
+
voiceAutoSend: boolean;
|
|
104
|
+
}
|
|
105
|
+
export declare const CONFIG_DEFAULTS: Readonly<Config>;
|
|
106
|
+
export declare const CONFIG_LIMITS: {
|
|
107
|
+
readonly historyMaxEntries: {
|
|
108
|
+
readonly min: 0;
|
|
109
|
+
readonly max: 500;
|
|
110
|
+
};
|
|
111
|
+
readonly temperature: {
|
|
112
|
+
readonly min: -1;
|
|
113
|
+
readonly max: 2;
|
|
114
|
+
};
|
|
115
|
+
readonly maxTokens: {
|
|
116
|
+
readonly min: 0;
|
|
117
|
+
readonly max: 32000;
|
|
118
|
+
};
|
|
119
|
+
readonly timeoutMs: {
|
|
120
|
+
readonly min: 5000;
|
|
121
|
+
readonly max: 600000;
|
|
122
|
+
};
|
|
123
|
+
readonly maxSelectionChars: {
|
|
124
|
+
readonly min: 20;
|
|
125
|
+
readonly max: 20000;
|
|
126
|
+
};
|
|
127
|
+
readonly maxContextChars: {
|
|
128
|
+
readonly min: 200;
|
|
129
|
+
readonly max: 60000;
|
|
130
|
+
};
|
|
131
|
+
readonly maxRequestsPerMinute: {
|
|
132
|
+
readonly min: 1;
|
|
133
|
+
readonly max: 600;
|
|
134
|
+
};
|
|
135
|
+
readonly sessionContextMaxMessages: {
|
|
136
|
+
readonly min: 1;
|
|
137
|
+
readonly max: 200;
|
|
138
|
+
};
|
|
139
|
+
readonly sessionContextFastMessages: {
|
|
140
|
+
readonly min: 1;
|
|
141
|
+
readonly max: 200;
|
|
142
|
+
};
|
|
143
|
+
readonly sessionContextMaxChars: {
|
|
144
|
+
readonly min: 0;
|
|
145
|
+
readonly max: 2000000;
|
|
146
|
+
};
|
|
147
|
+
readonly quoteContextRounds: {
|
|
148
|
+
readonly min: 0;
|
|
149
|
+
readonly max: 10;
|
|
150
|
+
};
|
|
151
|
+
readonly quoteContextMaxCharsPerTurn: {
|
|
152
|
+
readonly min: 200;
|
|
153
|
+
readonly max: 20000;
|
|
154
|
+
};
|
|
155
|
+
readonly quoteContextMaxChars: {
|
|
156
|
+
readonly min: 400;
|
|
157
|
+
readonly max: 100000;
|
|
158
|
+
};
|
|
159
|
+
readonly resultCacheTtlMs: {
|
|
160
|
+
readonly min: 0;
|
|
161
|
+
readonly max: 86400000;
|
|
162
|
+
};
|
|
163
|
+
readonly maxToolRounds: {
|
|
164
|
+
readonly min: 0;
|
|
165
|
+
readonly max: 8;
|
|
166
|
+
};
|
|
167
|
+
readonly toolResultMaxChars: {
|
|
168
|
+
readonly min: 200;
|
|
169
|
+
readonly max: 20000;
|
|
170
|
+
};
|
|
171
|
+
readonly pillIdleMs: {
|
|
172
|
+
readonly min: 2000;
|
|
173
|
+
readonly max: 600000;
|
|
174
|
+
};
|
|
175
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { createHistoryStore } from './history-store.js';
|
|
2
|
+
import type { createSessions } from './sessions.js';
|
|
3
|
+
import type { createModels } from './models.js';
|
|
4
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
5
|
+
import type { Config } from './config.js';
|
|
6
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
7
|
+
/** Owns analyze state for one plugin instance. */
|
|
8
|
+
export declare function createAnalyze(ctx: Context, config: Config, models: ReturnType<typeof createModels>, sessions: ReturnType<typeof createSessions>, historyStore: ReturnType<typeof createHistoryStore>): {
|
|
9
|
+
handleAnalyze: (req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
10
|
+
};
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import z from '@deepseek-ai/schemastery';
|
|
2
|
+
import type { Config as PluginConfig } from '../config-values.js';
|
|
3
|
+
export type Config = PluginConfig;
|
|
4
|
+
/** 配置 schema(缺省值即推荐值)。 */
|
|
5
|
+
export declare const Config: z<Schemastery.ObjectS<{
|
|
6
|
+
provider: z<string, string>;
|
|
7
|
+
model: z<string, string>;
|
|
8
|
+
chatProvider: z<string, string>;
|
|
9
|
+
chatModel: z<string, string>;
|
|
10
|
+
reasoningEffort: z<string, string>;
|
|
11
|
+
/** 首轮单独一档:默认关闭思考,优先快速给出翻译、解读或注释。 */
|
|
12
|
+
translationReasoningEffort: z<string, string>;
|
|
13
|
+
/**
|
|
14
|
+
* 小窗对话历史(A′):把整段对话落到插件自己的目录,重划同一个词直接回放。
|
|
15
|
+
* 0 = 关闭历史。只留最近 N 个「划词条目」(每个条目内含它自己的全部追问轮次)。
|
|
16
|
+
*/
|
|
17
|
+
historyMaxEntries: z<number, number>;
|
|
18
|
+
/** 采样温度。**默认 -1 = 不传**(交给供应商默认,与主会话一致)。0~2 之间才真的传。 */
|
|
19
|
+
temperature: z<number, number>;
|
|
20
|
+
/**
|
|
21
|
+
* 单次调用的输出上限(tokens)。**默认 0 = 不限制** —— 不传这个参数,交给模型/供应商自己的上限。
|
|
22
|
+
*
|
|
23
|
+
* 为什么不默认给个数:这是**每次调用**的上限,联网检索后的答案经常要 2~4k tokens,
|
|
24
|
+
* 之前默认 1200 会让回答"悄悄截断在句子中间"(实测);而给死一个更大的数也一样会在别的场景截断。
|
|
25
|
+
* 想限制(控成本/控时延)就填正数,仍然生效。
|
|
26
|
+
*/
|
|
27
|
+
maxTokens: z<number, number>;
|
|
28
|
+
timeoutMs: z<number, number>;
|
|
29
|
+
maxSelectionChars: z<number, number>;
|
|
30
|
+
maxContextChars: z<number, number>;
|
|
31
|
+
maxRequestsPerMinute: z<number, number>;
|
|
32
|
+
sessionContext: z<boolean, boolean>;
|
|
33
|
+
sessionContextMaxMessages: z<number, number>;
|
|
34
|
+
sessionContextFastMessages: z<number, number>;
|
|
35
|
+
sessionContextMaxChars: z<number, number>;
|
|
36
|
+
quoteContextRounds: z<number, number>;
|
|
37
|
+
quoteContextMaxCharsPerTurn: z<number, number>;
|
|
38
|
+
quoteContextMaxChars: z<number, number>;
|
|
39
|
+
resultCacheTtlMs: z<number, number>;
|
|
40
|
+
tools: z<boolean, boolean>;
|
|
41
|
+
/**
|
|
42
|
+
* 工具白名单(逗号分隔)。
|
|
43
|
+
*
|
|
44
|
+
* 默认改用 **free-search 插件**的工具(`advanced_search` / `platform_search`),不再用 `web_search`:
|
|
45
|
+
* 会话里的 `web_search` 是官方 DeepSeek 搜索(复用 @deepseek-ai/dsh-tool-web 的 schema),
|
|
46
|
+
* 而新装的 dsh-free-search 只注册了 advanced_search / platform_search / free_search_test ——
|
|
47
|
+
* 引擎更多(ddg/bing/searxng/anysearch/exa/tavily/keenable/firecrawl/parallel…)、失败自动换引擎、
|
|
48
|
+
* 还支持时间过滤与平台搜索。
|
|
49
|
+
*/
|
|
50
|
+
toolNames: z<string, string>;
|
|
51
|
+
/**
|
|
52
|
+
* **备用**工具清单:只在"首选里的联网工具一个都不在"时才补进来。
|
|
53
|
+
*
|
|
54
|
+
* 场景:没装 free-search 插件(或它没注册工具)时,会话里通常仍有官方 `web_search`;
|
|
55
|
+
* 不补的话小窗会变成完全不能联网。装了 free-search 就完全用不到这一项。
|
|
56
|
+
*/
|
|
57
|
+
fallbackToolNames: z<string, string>;
|
|
58
|
+
maxToolRounds: z<number, number>;
|
|
59
|
+
toolResultMaxChars: z<number, number>;
|
|
60
|
+
toolReadRoot: z<string, string>;
|
|
61
|
+
chatReasoningEffort: z<string, string>;
|
|
62
|
+
/**
|
|
63
|
+
* 侧边栏 HTML 预览里的划词桥。关掉就不往预览帧里注入桥脚本,
|
|
64
|
+
* 侧边栏网页里选中文字不会再弹「解读」。
|
|
65
|
+
*/
|
|
66
|
+
bridgeSidebarPreview: z<boolean, boolean>;
|
|
67
|
+
/** 悬浮胶囊开关(小窗设置页可改)。 */
|
|
68
|
+
pillEnabled: z<boolean, boolean>;
|
|
69
|
+
/** 静置收球时长(毫秒)——默认 10 秒,见 Config 注释。 */
|
|
70
|
+
pillIdleMs: z<number, number>;
|
|
71
|
+
/** 空录音是否收起卡片(默认开,见 Config 注释)。 */
|
|
72
|
+
voiceCancelOnSilence: z<boolean, boolean>;
|
|
73
|
+
/** 有字是否自动发送(默认开,见 Config 注释)。 */
|
|
74
|
+
voiceAutoSend: z<boolean, boolean>;
|
|
75
|
+
}>, Schemastery.ObjectT<{
|
|
76
|
+
provider: z<string, string>;
|
|
77
|
+
model: z<string, string>;
|
|
78
|
+
chatProvider: z<string, string>;
|
|
79
|
+
chatModel: z<string, string>;
|
|
80
|
+
reasoningEffort: z<string, string>;
|
|
81
|
+
/** 首轮单独一档:默认关闭思考,优先快速给出翻译、解读或注释。 */
|
|
82
|
+
translationReasoningEffort: z<string, string>;
|
|
83
|
+
/**
|
|
84
|
+
* 小窗对话历史(A′):把整段对话落到插件自己的目录,重划同一个词直接回放。
|
|
85
|
+
* 0 = 关闭历史。只留最近 N 个「划词条目」(每个条目内含它自己的全部追问轮次)。
|
|
86
|
+
*/
|
|
87
|
+
historyMaxEntries: z<number, number>;
|
|
88
|
+
/** 采样温度。**默认 -1 = 不传**(交给供应商默认,与主会话一致)。0~2 之间才真的传。 */
|
|
89
|
+
temperature: z<number, number>;
|
|
90
|
+
/**
|
|
91
|
+
* 单次调用的输出上限(tokens)。**默认 0 = 不限制** —— 不传这个参数,交给模型/供应商自己的上限。
|
|
92
|
+
*
|
|
93
|
+
* 为什么不默认给个数:这是**每次调用**的上限,联网检索后的答案经常要 2~4k tokens,
|
|
94
|
+
* 之前默认 1200 会让回答"悄悄截断在句子中间"(实测);而给死一个更大的数也一样会在别的场景截断。
|
|
95
|
+
* 想限制(控成本/控时延)就填正数,仍然生效。
|
|
96
|
+
*/
|
|
97
|
+
maxTokens: z<number, number>;
|
|
98
|
+
timeoutMs: z<number, number>;
|
|
99
|
+
maxSelectionChars: z<number, number>;
|
|
100
|
+
maxContextChars: z<number, number>;
|
|
101
|
+
maxRequestsPerMinute: z<number, number>;
|
|
102
|
+
sessionContext: z<boolean, boolean>;
|
|
103
|
+
sessionContextMaxMessages: z<number, number>;
|
|
104
|
+
sessionContextFastMessages: z<number, number>;
|
|
105
|
+
sessionContextMaxChars: z<number, number>;
|
|
106
|
+
quoteContextRounds: z<number, number>;
|
|
107
|
+
quoteContextMaxCharsPerTurn: z<number, number>;
|
|
108
|
+
quoteContextMaxChars: z<number, number>;
|
|
109
|
+
resultCacheTtlMs: z<number, number>;
|
|
110
|
+
tools: z<boolean, boolean>;
|
|
111
|
+
/**
|
|
112
|
+
* 工具白名单(逗号分隔)。
|
|
113
|
+
*
|
|
114
|
+
* 默认改用 **free-search 插件**的工具(`advanced_search` / `platform_search`),不再用 `web_search`:
|
|
115
|
+
* 会话里的 `web_search` 是官方 DeepSeek 搜索(复用 @deepseek-ai/dsh-tool-web 的 schema),
|
|
116
|
+
* 而新装的 dsh-free-search 只注册了 advanced_search / platform_search / free_search_test ——
|
|
117
|
+
* 引擎更多(ddg/bing/searxng/anysearch/exa/tavily/keenable/firecrawl/parallel…)、失败自动换引擎、
|
|
118
|
+
* 还支持时间过滤与平台搜索。
|
|
119
|
+
*/
|
|
120
|
+
toolNames: z<string, string>;
|
|
121
|
+
/**
|
|
122
|
+
* **备用**工具清单:只在"首选里的联网工具一个都不在"时才补进来。
|
|
123
|
+
*
|
|
124
|
+
* 场景:没装 free-search 插件(或它没注册工具)时,会话里通常仍有官方 `web_search`;
|
|
125
|
+
* 不补的话小窗会变成完全不能联网。装了 free-search 就完全用不到这一项。
|
|
126
|
+
*/
|
|
127
|
+
fallbackToolNames: z<string, string>;
|
|
128
|
+
maxToolRounds: z<number, number>;
|
|
129
|
+
toolResultMaxChars: z<number, number>;
|
|
130
|
+
toolReadRoot: z<string, string>;
|
|
131
|
+
chatReasoningEffort: z<string, string>;
|
|
132
|
+
/**
|
|
133
|
+
* 侧边栏 HTML 预览里的划词桥。关掉就不往预览帧里注入桥脚本,
|
|
134
|
+
* 侧边栏网页里选中文字不会再弹「解读」。
|
|
135
|
+
*/
|
|
136
|
+
bridgeSidebarPreview: z<boolean, boolean>;
|
|
137
|
+
/** 悬浮胶囊开关(小窗设置页可改)。 */
|
|
138
|
+
pillEnabled: z<boolean, boolean>;
|
|
139
|
+
/** 静置收球时长(毫秒)——默认 10 秒,见 Config 注释。 */
|
|
140
|
+
pillIdleMs: z<number, number>;
|
|
141
|
+
/** 空录音是否收起卡片(默认开,见 Config 注释)。 */
|
|
142
|
+
voiceCancelOnSilence: z<boolean, boolean>;
|
|
143
|
+
/** 有字是否自动发送(默认开,见 Config 注释)。 */
|
|
144
|
+
voiceAutoSend: z<boolean, boolean>;
|
|
145
|
+
}>>;
|
|
146
|
+
/** Preserve nullish-default semantics without duplicating the defaults. */
|
|
147
|
+
export declare function resolveConfig(rawConfig?: Partial<Config>): Config;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** 插件名(= package.json name,客户端 bundle 的模块 id 也是它)。 */
|
|
2
|
+
export declare const name = "@yfwu2020/dsh-selection-explain";
|
|
3
|
+
/**
|
|
4
|
+
* 升格时那条「上下文注入」消息的 `source.kind` —— 生产者**自有**的来源标识。
|
|
5
|
+
*
|
|
6
|
+
* 会话格式 v4 起(本机实测内核 0.2.0-rc.2),消息来源必须是生产者自报的 kind;
|
|
7
|
+
* v3 那种 `plugin` 包装(`kind: 'plugin'` 配一个 `plugin` 字段)已经退役,会被
|
|
8
|
+
* v4 准入当场拒掉:
|
|
9
|
+
* SessionFormatError: format v4 message requires a producer-owned source kind
|
|
10
|
+
* 症状极具迷惑性:`↗ 升格` 的 HTTP 请求返回 `ok: true`(那时只写进了内存里的会话面),
|
|
11
|
+
* 随后那轮 opener 运行失败、整个 artifact 一个字都没落盘 —— 新会话只剩表头。
|
|
12
|
+
* 离线测试也照样全绿(校验发生在真实内核里,不在构建期),所以另配了
|
|
13
|
+
* tests/unit/format.test.mjs 钉住这个 shape。
|
|
14
|
+
*
|
|
15
|
+
* 第三方插件的规范形态是 `plugin:<插件名>`:内核 v3→v4 迁移把那种 `plugin` 包装
|
|
16
|
+
* 重写成 `plugin:<完整插件名>`(`producerKind()` 对不在同名表里的插件就是这么算的),
|
|
17
|
+
* 所以这里写的与迁移结果逐字节一致 —— 新旧会话归因相同,且 v3 内核下同样合法
|
|
18
|
+
* (直写的 kind 迁移时原样保留)。
|
|
19
|
+
*/
|
|
20
|
+
export declare const PLUGIN_SOURCE_KIND = "plugin:@yfwu2020/dsh-selection-explain";
|
|
21
|
+
/** 路由注册与模型调用所需的服务。 */
|
|
22
|
+
export declare const inject: string[];
|
|
23
|
+
/** 路由前缀。 */
|
|
24
|
+
export declare const API_PREFIX = "/selection-explain/api";
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { AnalyzeBody, BackgroundOptions, SessionBackground } from './types.js';
|
|
2
|
+
/** 请求里带的会话 id(空串 = 客户端没取到)。 */
|
|
3
|
+
export declare function sessionIdOf(body: AnalyzeBody): string;
|
|
4
|
+
/**
|
|
5
|
+
* 把会话的当前模型界面整理成「会话背景」文本。
|
|
6
|
+
*
|
|
7
|
+
* 只保留**真实对话**:用户真正发的话(source.kind === 'user')与助手回复的正文。
|
|
8
|
+
* 三类内容一律剔除,否则会把有效窗口挤没(实测:430 条 surface 事件里绝大多数是
|
|
9
|
+
* 工具调用/结果,且 harness 注入的 system-reminder 单条可达 1.2 万字):
|
|
10
|
+
* - tool/result 与纯工具调用的助手步骤(无正文)
|
|
11
|
+
* - system/message(系统提示词)
|
|
12
|
+
* - source.kind !== 'user' 的用户角色消息(运行环境快照、skill 目录等 harness 注入)
|
|
13
|
+
*/
|
|
14
|
+
export declare function transcriptOf(events: readonly unknown[], options: BackgroundOptions): SessionBackground;
|
|
15
|
+
/** 引用上下文的结果。 */
|
|
16
|
+
export interface QuoteContext {
|
|
17
|
+
/** 「用户:…/助手:…」逐行拼好的上下文(引用部分用【】标出);没命中时为空串。 */
|
|
18
|
+
transcript: string;
|
|
19
|
+
/** 引用文字是否在会话里定位到了(没定位到 → 客户端退回自己的局部上下文)。 */
|
|
20
|
+
matched: boolean;
|
|
21
|
+
/** 带进来的对话组数(一组 = 一条用户消息 + 它的助手回复)。 */
|
|
22
|
+
rounds: number;
|
|
23
|
+
}
|
|
24
|
+
/** 引用上下文的窗口与长度(默认值:上下各一组、单条 2000 字、总共 6000 字)。 */
|
|
25
|
+
export interface QuoteContextOptions {
|
|
26
|
+
/** 引用前后各取几组对话(默认 1)。 */
|
|
27
|
+
roundsAround?: number;
|
|
28
|
+
/** 单条消息的字数上限(超出时**围绕引用**截断,别把引用本身裁掉)。 */
|
|
29
|
+
maxCharsPerTurn?: number;
|
|
30
|
+
/** 整段上下文的字数上限(超出时丢最早的那几组)。 */
|
|
31
|
+
maxChars?: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* **引用上下文**:引用文字所在的那一组对话 ± N 组(一组 = 一条用户消息 + 它的助手回复)。
|
|
35
|
+
*
|
|
36
|
+
* 与 `transcriptOf`(解读用的会话背景)的区别,两条都是为引用量身定的:
|
|
37
|
+
* ① 窗口是**锚点两侧** —— 引用常常是"上面那句"和"下面那句"的对照,只有上文不够;
|
|
38
|
+
* ② 按**轮**取整 —— 上下各至少一整组(用户消息 + AI 回复),不会切在半个回合上。
|
|
39
|
+
* 噪音过滤与 `transcriptOf` 完全一致(工具调用/结果、系统提示、harness 注入一律不进)。
|
|
40
|
+
*/
|
|
41
|
+
export declare function quoteContextOf(events: readonly unknown[], marker: string, options?: QuoteContextOptions): QuoteContext;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function loadDesignSkill(): Promise<string>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 规范四格 → 当前模型**真实声明**的档位(返回 '' 表示这个模型没有可发的档位)。
|
|
3
|
+
*
|
|
4
|
+
* 规则一条到底(对 `off>low>high>max` 这类 4 档模型恰好是恒等映射):
|
|
5
|
+
* · 关 → 声明里**最弱**的那档(模型没有 off 这类档时,就是它"能关到"的最小思考)
|
|
6
|
+
* · 最高 → 声明里**最强**的那档
|
|
7
|
+
* · 低/高 → 在整条刻度上取 1/3、2/3 处**最近的档**;候选**排除两端**(最弱那档留给「关」、
|
|
8
|
+
* 最强那档留给「最高」,四个格子于是各有落点),并保证 关 ≤ 低 ≤ 高 ≤ 最高 单调;
|
|
9
|
+
* 同样近时「低」取更浅的、「高」取更深的 —— 低要省、高要深。
|
|
10
|
+
*
|
|
11
|
+
* ⚠️ 这里**没有**任何按模型写死的表:输入只有"这个模型自己声明的档位列表"。
|
|
12
|
+
* 名字认得出来(off/low/high/max、minimal、xhigh…)就用名字的深度刻度;认不出来
|
|
13
|
+
* (别的 adapter 可能叫 a/b/c、tier1/tier2,或者干脆是数字)就按**它在声明里的位置**插值 ——
|
|
14
|
+
* 所以任何用户换任何模型都能落位,插件作者没见过那个模型也能映射。
|
|
15
|
+
* 为什么不让「低/高」也去抢最弱那档:那两个格子表达的是"开着思考、但别太深",
|
|
16
|
+
* 落到"关"那一档等于**把用户要的思考关掉**;只有「关」该动那一档。
|
|
17
|
+
* 只有一档可发时(如 kimi-k3 只有 max),四格都落到它 —— 模型没有别的选择。
|
|
18
|
+
*
|
|
19
|
+
* 返回 '' 表示"这个模型没有可发的档位"(声明为空),调用方据此**不带** reasoningEffort。
|
|
20
|
+
*/
|
|
21
|
+
export declare function mapEffortToModel(declared: Array<{
|
|
22
|
+
id: string;
|
|
23
|
+
name?: string;
|
|
24
|
+
}>, canonical: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* 一个模型的四格映射(设置页给用户看的就是它;请求时也走这份算)。
|
|
27
|
+
* 返回空串的格子表示"没有可发的档位"(模型不支持推理时四个格子都是空串)。
|
|
28
|
+
*/
|
|
29
|
+
export declare function effortMapOf(declared: Array<{
|
|
30
|
+
id: string;
|
|
31
|
+
name?: string;
|
|
32
|
+
}>): Record<string, string>;
|
|
33
|
+
/** 档位的中文名(notice 文案用,与客户端 TIER_LABEL 一致)。 */
|
|
34
|
+
export declare const EFFORT_LABEL: Record<string, string>;
|
|
35
|
+
/**
|
|
36
|
+
* 这条上游错误是不是"**我们发的这个档位**不被接受"。
|
|
37
|
+
*
|
|
38
|
+
* ⚠️ 判据必须窄。免费/预览端点的上游会**偶发**返回
|
|
39
|
+
* `Reasoning is mandatory for this endpoint and cannot be disabled.` ——
|
|
40
|
+
* 2026-10-09 实测(`opencode-go/step-5-preview-free`,交错发送排除时间漂移):
|
|
41
|
+
* · effort=low 成功 5/8;effort=high 成功 5/8 —— **同一档位时好时坏,档位不是变量**;
|
|
42
|
+
* · 对照模型 `longcat-2.5-preview-free` 6/6 成功(连 off 都收)。
|
|
43
|
+
* 所以只认"明确说这个档位无效"的措辞;"必须开推理"另有一条判据
|
|
44
|
+
* (见 looksLikeReasoningRequired,只在**我们发的是关档**时才算数)。
|
|
45
|
+
* 把偶发失败当成"档位不支持"会连锁出三个错:给用户一句错诊断、把失败永久记进
|
|
46
|
+
* noOffRoutes(以后再也不发这个档)、清掉用户选的档位。
|
|
47
|
+
*/
|
|
48
|
+
export declare function looksLikeUnsupportedTier(message: string): boolean;
|
|
49
|
+
/** 上游要求"必须开推理"——只有在**我们这次把推理关掉**(发的 off)时,这句才是冲我们来的。 */
|
|
50
|
+
export declare function looksLikeReasoningRequired(message: string): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* 换一个"没试过的"档位(重试用)。
|
|
53
|
+
*
|
|
54
|
+
* 为什么**绝不能省略档位**(老代码就是省略):省略 = 请求里不带 reasoning,
|
|
55
|
+
* 对"必须开推理"的端点等于把推理关掉 —— 实测 20 次这样的重试 **0 次成功**,
|
|
56
|
+
* 而同一档位首发成功率约 60%。省略比"发一个可能不被接受的档"更糟。
|
|
57
|
+
*
|
|
58
|
+
* 顺序:模型自己声明的 defaultEffort → 沿档位阶梯往上走一格(离"关"越远越安全)。
|
|
59
|
+
* 返回空串表示"没档位可换了",调用方就不重试。
|
|
60
|
+
*/
|
|
61
|
+
export declare function pickNextEffort(declared: string[], defaultEffort: string | null | undefined, rejected: string, tried: Set<string>): string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare function createThinkFilter(): {
|
|
2
|
+
push: (text: string) => {
|
|
3
|
+
text: string;
|
|
4
|
+
think: string;
|
|
5
|
+
};
|
|
6
|
+
flush: () => {
|
|
7
|
+
text: string;
|
|
8
|
+
think: string;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* 宽松判据:开头是**英文盘算**、后面才是**中文答案**。
|
|
13
|
+
* 只用来"记住这个模型在关档会泄漏"(下次自动抬档),**不用来裁剪** ——
|
|
14
|
+
* 裁错了会误删正文,而记错了只是下次少一个档位可选,代价不对称。
|
|
15
|
+
*/
|
|
16
|
+
export declare function looksLikeLeakedReasoning(text: string): boolean;
|
|
17
|
+
export declare function splitLeakedReasoning(text: string): {
|
|
18
|
+
prefix: string;
|
|
19
|
+
rest: string;
|
|
20
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { createSettingsStore } from './settings-store.js';
|
|
2
|
+
import type { createModels } from './models.js';
|
|
3
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
4
|
+
import type { Config } from './config.js';
|
|
5
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
6
|
+
/** Owns history-store state for one plugin instance. */
|
|
7
|
+
export declare function createHistoryStore(ctx: Context, config: Config, models: ReturnType<typeof createModels>, settingsStore: ReturnType<typeof createSettingsStore>): {
|
|
8
|
+
clampText: (value: unknown, max: number) => string;
|
|
9
|
+
historyFile: () => string;
|
|
10
|
+
handleHistory: (req: IncomingMessage, res: ServerResponse) => void;
|
|
11
|
+
handlePanelSize: (req: IncomingMessage, res: ServerResponse) => void;
|
|
12
|
+
handlePillPos: (req: IncomingMessage, res: ServerResponse) => void;
|
|
13
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ServerResponse, IncomingMessage } from 'node:http';
|
|
2
|
+
/** 单次请求体上限(字节)。 */
|
|
3
|
+
export declare const BODY_LIMIT: number;
|
|
4
|
+
/** 写一条 SSE 事件。 */
|
|
5
|
+
export declare function sse(res: ServerResponse, payload: unknown): void;
|
|
6
|
+
export declare function sendJson(res: ServerResponse, status: number, body: unknown): void;
|
|
7
|
+
/** 读取请求体(带长度上限)。 */
|
|
8
|
+
export declare function readBody(req: IncomingMessage, limit: number): Promise<string>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createSystemMessage } from '@deepseek-ai/dsh-llm';
|
|
2
|
+
/**
|
|
3
|
+
* `createSystemMessage` 的**跨版本兼容调用**。
|
|
4
|
+
*
|
|
5
|
+
* 这个函数的签名在两个版本间不一样,而两份类型都得能编译通过:
|
|
6
|
+
* · **0.1.5-rc.3**(npm 上按 peer 范围 `>=0.1.5-rc <2` 解析到的就是它,CI 的构建校验用的这份):
|
|
7
|
+
* `createSystemMessage(text, plugin)` —— 两个都必填,少传一个直接 TS2554(发布被卡过一次);
|
|
8
|
+
* · **0.1.7-rc.x**(本机/新运行时):`createSystemMessage(text)` —— 第二参数是历史遗留,传了会被忽略。
|
|
9
|
+
*
|
|
10
|
+
* 所以这里把它当"接受可选第二参数"的函数来调:两个版本都编译得过,运行时也都正确
|
|
11
|
+
* (旧版正好拿到它想要的"组装这段提示词的插件名",新版直接忽略)。
|
|
12
|
+
*/
|
|
13
|
+
export declare const systemMessageOf: (text: string, plugin?: string) => ReturnType<typeof createSystemMessage>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
/**
|
|
3
|
+
* 停掉探针(没人看了 / 插件卸载)。**下次有人来问会重新启动**。
|
|
4
|
+
*
|
|
5
|
+
* 注意 available 要跟着回落到 false:探针都停了,再报"正在录"就是过期数据 ——
|
|
6
|
+
* 客户端看到 !available 会停掉轮询(不假装),这正是我们要的。
|
|
7
|
+
*/
|
|
8
|
+
export declare function stopMicProbe(): void;
|
|
9
|
+
/**
|
|
10
|
+
* GET /selection-explain/api/mic
|
|
11
|
+
* → { ok, available, capturing, processes:[{pid,bundleId,name}], reason }
|
|
12
|
+
*
|
|
13
|
+
* 客户端只关心 `capturing` 和某个进程的 bundleId 是不是目标输入法;
|
|
14
|
+
* 一次把所有占用者给全,是因为"同时在录的还有别的 App"很常见(会议软件、录音工具),
|
|
15
|
+
* 只报第一个会让特性在那种情况下静默失效。
|
|
16
|
+
*/
|
|
17
|
+
export declare const handleMic: (req: IncomingMessage, res: ServerResponse) => void;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import type { Config } from './config.js';
|
|
3
|
+
import type { Route } from './types.js';
|
|
4
|
+
/** 解析本次调用使用的模型路由。 */
|
|
5
|
+
/**
|
|
6
|
+
* 可选模型清单(带每个模型支持的推理等级)。
|
|
7
|
+
*
|
|
8
|
+
* 用 `llm.listProviders()`(同步)→ `llm.listModels(provider)`(异步,可能触发端点发现)→
|
|
9
|
+
* `llm.resolveModel(provider, model)` 拿 `reasoning.efforts`。因为可能慢,这里做 60 秒缓存,
|
|
10
|
+
* 并且**只在 /models 路由里调用**,不进 ping / analyze 的热路径。
|
|
11
|
+
*/
|
|
12
|
+
export type ModelChoice = {
|
|
13
|
+
provider: string;
|
|
14
|
+
providerName: string;
|
|
15
|
+
model: string;
|
|
16
|
+
name: string;
|
|
17
|
+
efforts: Array<{
|
|
18
|
+
id: string;
|
|
19
|
+
name: string;
|
|
20
|
+
}>;
|
|
21
|
+
defaultEffort: string | null;
|
|
22
|
+
/**
|
|
23
|
+
* 这个模型到底支不支持"思考强度":
|
|
24
|
+
* true = 有推理档位(efforts 非空)
|
|
25
|
+
* false = 明确不支持(dsh-llm 的 resolveModelInfo 说它没有 reasoning)
|
|
26
|
+
* null = 没读到(还没加载 / 这次调用失败)→ 原样发规范档位,被拒时由换档重试兜
|
|
27
|
+
*/
|
|
28
|
+
hasReasoning: boolean | null;
|
|
29
|
+
/**
|
|
30
|
+
* 规范四格 → 这个模型**真实**的档位 id('' = 没有可发的档位)。
|
|
31
|
+
* 由 `effortMapOf(model.efforts)` 实时算出,随清单一起下发 —— 设置页据此显示"这四格现在落到哪"。
|
|
32
|
+
*/
|
|
33
|
+
effortMap: Record<string, string>;
|
|
34
|
+
};
|
|
35
|
+
/** Owns models state for one plugin instance. */
|
|
36
|
+
export declare function createModels(ctx: Context, config: Config): {
|
|
37
|
+
resolveRoute: (override?: {
|
|
38
|
+
provider?: string;
|
|
39
|
+
model?: string;
|
|
40
|
+
}, sessionModel?: {
|
|
41
|
+
provider?: string;
|
|
42
|
+
model?: string;
|
|
43
|
+
} | null, chat?: boolean) => Route | null;
|
|
44
|
+
loadLeaky: () => Promise<void>;
|
|
45
|
+
leakyOnOff: Set<string>;
|
|
46
|
+
noOffRoutes: Set<string>;
|
|
47
|
+
effortForRoute: (route: string, canonical: string) => string;
|
|
48
|
+
nextEffortFor: (route: string, rejected: string, tried: Set<string>) => string;
|
|
49
|
+
markNoOff: (route: string) => void;
|
|
50
|
+
markLeaky: (route: string) => void;
|
|
51
|
+
listModelChoices: (force?: boolean) => Promise<ModelChoice[]>;
|
|
52
|
+
readonly modelCache: {
|
|
53
|
+
at: number;
|
|
54
|
+
items: ModelChoice[];
|
|
55
|
+
};
|
|
56
|
+
MODEL_CACHE_MS: number;
|
|
57
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { createHistoryStore } from './history-store.js';
|
|
2
|
+
import type { createSessions } from './sessions.js';
|
|
3
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
4
|
+
import type { Config } from './config.js';
|
|
5
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
6
|
+
/** Owns promote state for one plugin instance. */
|
|
7
|
+
export declare function createPromote(ctx: Context, config: Config, sessions: ReturnType<typeof createSessions>, historyStore: ReturnType<typeof createHistoryStore>): {
|
|
8
|
+
handlePromote: (req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
9
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { createSettingsStore } from './settings-store.js';
|
|
2
|
+
import type { createModels } from './models.js';
|
|
3
|
+
import type { createSessions } from './sessions.js';
|
|
4
|
+
import type { createHistoryStore } from './history-store.js';
|
|
5
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
6
|
+
import type { Config } from './config.js';
|
|
7
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
8
|
+
/** Owns routes state for one plugin instance. */
|
|
9
|
+
export declare function createRoutes(ctx: Context, config: Config, historyStore: ReturnType<typeof createHistoryStore>, sessions: ReturnType<typeof createSessions>, models: ReturnType<typeof createModels>, settingsStore: ReturnType<typeof createSettingsStore>): {
|
|
10
|
+
handleRoute: (req: IncomingMessage, res: ServerResponse) => void;
|
|
11
|
+
handlePing: (req: IncomingMessage, res: ServerResponse) => void;
|
|
12
|
+
handleModels: (req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
13
|
+
handleQuoteContext: (req: IncomingMessage, res: ServerResponse) => void;
|
|
14
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import type { Config } from './config.js';
|
|
3
|
+
import type { SessionModel, BackgroundOptions, SessionBackground } from './types.js';
|
|
4
|
+
/** 可写的 live 会话(只用到 append)。 */
|
|
5
|
+
export interface LiveSessionLike {
|
|
6
|
+
append?: (type: string, data: unknown, options?: unknown) => unknown;
|
|
7
|
+
}
|
|
8
|
+
/** Owns sessions state for one plugin instance. */
|
|
9
|
+
export declare function createSessions(ctx: Context, config: Config): {
|
|
10
|
+
sessionModelOf: (sessionId: string, useCache?: boolean) => Promise<SessionModel | null>;
|
|
11
|
+
loadSessionBackground: (sessionId: string, options: BackgroundOptions) => Promise<SessionBackground | null>;
|
|
12
|
+
resolveSessionCwd: (sessionId: string) => Promise<string | undefined>;
|
|
13
|
+
readSurfaceEvents: (sessionId: string) => Promise<readonly unknown[]>;
|
|
14
|
+
};
|