dsh-deepseek-web-login 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/lib/client.js +55 -0
- package/lib/client.js.map +1 -1
- package/lib/index.js +76 -6
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/tools/panel-preview.mjs +5 -0
package/lib/index.js
CHANGED
|
@@ -874,6 +874,46 @@ function clampMaxRefImages(value) {
|
|
|
874
874
|
if (!Number.isFinite(value)) return 24;
|
|
875
875
|
return Math.max(MAX_REF_IMAGES_BOUNDS.min, Math.min(MAX_REF_IMAGES_BOUNDS.max, Math.round(value)));
|
|
876
876
|
}
|
|
877
|
+
/**
|
|
878
|
+
* 对外声明的模型上下文窗口(token),即模型信息里的 `context.contextWindow`。
|
|
879
|
+
*
|
|
880
|
+
* 它决定的是**DSH 什么时候开始压缩/截断历史**,而不是插件发多少 —— 声明 1M,DSH 就认为
|
|
881
|
+
* "还装得下",于是一直不压,每轮都把整段转写重发。对只跑短任务的人来说,那部分体量是白烧的。
|
|
882
|
+
*
|
|
883
|
+
* ⚠️ 它和 `maxPromptChars` 是**两道独立阀门**,别混:
|
|
884
|
+
* - `maxPromptChars` 管"单次请求最多发多少字符"(插件自己切,见上);
|
|
885
|
+
* - `contextWindow` 管"DSH 认为模型能装多少"(DSH 据此决定压不压历史)。
|
|
886
|
+
* 两个都调小,单次体量才会真的降下来;只调一个,另一个仍会把请求撑大。
|
|
887
|
+
*
|
|
888
|
+
* 上限取 DeepSeek 标称的 1Mi(服务端自己的数字也都是 1024 的整数倍),也就是本插件
|
|
889
|
+
* 一直以来的硬编码值;下限 32K —— 再小的话工具目录(约 5.6 万字符)就先装不下了。
|
|
890
|
+
*/
|
|
891
|
+
const CONTEXT_WINDOW_BOUNDS = {
|
|
892
|
+
min: 32768,
|
|
893
|
+
max: 1048576
|
|
894
|
+
};
|
|
895
|
+
/** 默认=原来的硬编码值(1Mi)—— 不动这个开关的人行为完全不变。 */
|
|
896
|
+
const DEFAULT_CONTEXT_WINDOW = 1048576;
|
|
897
|
+
/**
|
|
898
|
+
* 面板滑块的档位。
|
|
899
|
+
*
|
|
900
|
+
* **用档位而不是线性连续值**:32K→1M 是 32 倍跨度,线性拖动时前四分之三的行程都挤在低档位,
|
|
901
|
+
* 手感很差;档位化之后每一格都是"翻倍"这个直觉,也正好落在 1024 的整数倍上。
|
|
902
|
+
* 直接调接口传任意值仍被接受(只做边界夹取,不强制吸附)—— 档位只约束面板。
|
|
903
|
+
*/
|
|
904
|
+
const CONTEXT_WINDOW_OPTIONS = [
|
|
905
|
+
32768,
|
|
906
|
+
65536,
|
|
907
|
+
131072,
|
|
908
|
+
262144,
|
|
909
|
+
524288,
|
|
910
|
+
1048576
|
|
911
|
+
];
|
|
912
|
+
/** 规整上下文窗口:非数 → 默认;越界 → 夹到边界。 */
|
|
913
|
+
function clampContextWindow(value) {
|
|
914
|
+
if (!Number.isFinite(value)) return DEFAULT_CONTEXT_WINDOW;
|
|
915
|
+
return Math.max(CONTEXT_WINDOW_BOUNDS.min, Math.min(CONTEXT_WINDOW_BOUNDS.max, Math.round(value)));
|
|
916
|
+
}
|
|
877
917
|
/** 距上次请求超过这么久就算"歇过了",连续计数归零。 */
|
|
878
918
|
const LONG_RUN_IDLE_RESET_MS = 12e4;
|
|
879
919
|
/** 间隔可选的推荐档位(设置页的快捷按钮用):[下限, 上限]。 */
|
|
@@ -965,6 +1005,7 @@ function readGateSettings() {
|
|
|
965
1005
|
if (lrb) out.longRunBreakMs = lrb;
|
|
966
1006
|
if (Number.isFinite(parsed?.maxPromptChars)) out.maxPromptChars = clampMaxPromptChars(Number(parsed.maxPromptChars));
|
|
967
1007
|
if (Number.isFinite(parsed?.maxRefImages)) out.maxRefImages = clampMaxRefImages(Number(parsed.maxRefImages));
|
|
1008
|
+
if (Number.isFinite(parsed?.contextWindow)) out.contextWindow = clampContextWindow(Number(parsed.contextWindow));
|
|
968
1009
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
969
1010
|
} catch {
|
|
970
1011
|
return;
|
|
@@ -1116,6 +1157,7 @@ function createRequestGate(options = {}) {
|
|
|
1116
1157
|
/** prompt 字符上限(同 cleanupMode:只是存着,执行在 adapter)。 */
|
|
1117
1158
|
let maxPromptChars = clampMaxPromptChars(options.maxPromptChars ?? 4e5);
|
|
1118
1159
|
let maxRefImages = clampMaxRefImages(options.maxRefImages ?? 24);
|
|
1160
|
+
let contextWindow = clampContextWindow(options.contextWindow ?? 1048576);
|
|
1119
1161
|
let cleanupMode = options.sessionCleanup;
|
|
1120
1162
|
let cleanupBatch = normalizeCleanupRange(options.cleanupBatch, CLEANUP_BATCH_BOUNDS);
|
|
1121
1163
|
let cleanupDelayMs = normalizeCleanupRange(options.cleanupDelayMs, CLEANUP_DELAY_BOUNDS_MS);
|
|
@@ -1132,7 +1174,8 @@ function createRequestGate(options = {}) {
|
|
|
1132
1174
|
longRunThreshold,
|
|
1133
1175
|
...longRunBreakMs ? { longRunBreakMs } : {},
|
|
1134
1176
|
maxPromptChars,
|
|
1135
|
-
maxRefImages
|
|
1177
|
+
maxRefImages,
|
|
1178
|
+
contextWindow
|
|
1136
1179
|
};
|
|
1137
1180
|
}
|
|
1138
1181
|
function configure(next) {
|
|
@@ -1142,6 +1185,7 @@ function createRequestGate(options = {}) {
|
|
|
1142
1185
|
if (next.sessionCleanup !== void 0) cleanupMode = next.sessionCleanup;
|
|
1143
1186
|
if (next.maxPromptChars !== void 0) maxPromptChars = clampMaxPromptChars(Number(next.maxPromptChars));
|
|
1144
1187
|
if (next.maxRefImages !== void 0) maxRefImages = clampMaxRefImages(Number(next.maxRefImages));
|
|
1188
|
+
if (next.contextWindow !== void 0) contextWindow = clampContextWindow(Number(next.contextWindow));
|
|
1145
1189
|
if (next.cleanupBatch !== void 0) {
|
|
1146
1190
|
const value = normalizeCleanupRange(next.cleanupBatch, CLEANUP_BATCH_BOUNDS);
|
|
1147
1191
|
if (value) cleanupBatch = value;
|
|
@@ -5160,10 +5204,19 @@ function modelInfoFor(provider, spec, requestedId) {
|
|
|
5160
5204
|
inputModalities: ["text", "image"]
|
|
5161
5205
|
};
|
|
5162
5206
|
}
|
|
5163
|
-
|
|
5207
|
+
/**
|
|
5208
|
+
* 组装模型信息。
|
|
5209
|
+
*
|
|
5210
|
+
* `contextWindowOverride` 来自设置页的「上下文范围」滑块(经 gate.json → index.ts → AdapterConfig)。
|
|
5211
|
+
* 传 undefined 就沿用 MODEL_SPECS 里的标称值(1Mi)—— 也就是不调这个开关时的原行为。
|
|
5212
|
+
*
|
|
5213
|
+
* ⚠️ 这个函数**每次请求都会被调用**(见下方 resolveModel / stream),所以滑块改完是即时生效的,
|
|
5214
|
+
* 不需要重启 DSH。
|
|
5215
|
+
*/
|
|
5216
|
+
function resolvedModelInfo(provider, spec, requestedId, contextWindowOverride) {
|
|
5164
5217
|
return {
|
|
5165
5218
|
...modelInfoFor(provider, spec, requestedId),
|
|
5166
|
-
context: { contextWindow: spec.contextWindow },
|
|
5219
|
+
context: { contextWindow: contextWindowOverride ?? spec.contextWindow },
|
|
5167
5220
|
defaultMaxTokens: spec.maxOutputTokens,
|
|
5168
5221
|
reasoning: spec.configurableThinking ? {
|
|
5169
5222
|
efforts: REASONING_EFFORTS,
|
|
@@ -5334,7 +5387,7 @@ function createAdapter(deps) {
|
|
|
5334
5387
|
return Promise.resolve(MODEL_SPECS.map((spec) => modelInfoFor(provider, spec)));
|
|
5335
5388
|
},
|
|
5336
5389
|
resolveModel(provider, model) {
|
|
5337
|
-
return Promise.resolve(resolvedModelInfo(provider, resolveSpec(model), String(model ?? "")));
|
|
5390
|
+
return Promise.resolve(resolvedModelInfo(provider, resolveSpec(model), String(model ?? ""), deps.config.contextWindow));
|
|
5338
5391
|
},
|
|
5339
5392
|
/**
|
|
5340
5393
|
* 运行时契约(dsh-llm 0.1.2-rc.1):dispatch 前先取「精确模型元数据 + 该次调用的 stream」。
|
|
@@ -5343,7 +5396,7 @@ function createAdapter(deps) {
|
|
|
5343
5396
|
prepareCall(provider, model, _signal) {
|
|
5344
5397
|
const spec = resolveSpec(model);
|
|
5345
5398
|
return Promise.resolve({
|
|
5346
|
-
model: resolvedModelInfo(provider, spec, String(model ?? "")),
|
|
5399
|
+
model: resolvedModelInfo(provider, spec, String(model ?? ""), deps.config.contextWindow),
|
|
5347
5400
|
stream: (options) => gatedStream(options)
|
|
5348
5401
|
});
|
|
5349
5402
|
},
|
|
@@ -8070,7 +8123,7 @@ async function checkForUpdate(current, fetchImpl) {
|
|
|
8070
8123
|
* 兜底常量与 package.json 的一致性由 `tests/check-smoke.mjs` 守着,不会漂。
|
|
8071
8124
|
*/
|
|
8072
8125
|
/** 与 package.json 保持一致的兜底版本(由测试保证不会漂)。 */
|
|
8073
|
-
const FALLBACK_VERSION = "0.
|
|
8126
|
+
const FALLBACK_VERSION = "0.3.0";
|
|
8074
8127
|
let cached;
|
|
8075
8128
|
/** 本插件版本(如 `0.1.26`)。 */
|
|
8076
8129
|
function pluginVersion() {
|
|
@@ -8601,6 +8654,7 @@ function apply(ctx, config = {}) {
|
|
|
8601
8654
|
longRunThreshold: savedGate?.longRunThreshold ?? 15,
|
|
8602
8655
|
maxPromptChars: savedGate?.maxPromptChars ?? config.maxPromptChars ?? 4e5,
|
|
8603
8656
|
maxRefImages: savedGate?.maxRefImages ?? config.maxRefImages ?? 24,
|
|
8657
|
+
contextWindow: savedGate?.contextWindow ?? 1048576,
|
|
8604
8658
|
longRunBreakMs: savedGate?.longRunBreakMs,
|
|
8605
8659
|
sessionCleanup: cleanupMode,
|
|
8606
8660
|
cleanupBatch: cleanupBatchRange,
|
|
@@ -8621,6 +8675,7 @@ function apply(ctx, config = {}) {
|
|
|
8621
8675
|
const adapterConfig = {
|
|
8622
8676
|
maxPromptChars: savedGate?.maxPromptChars ?? config.maxPromptChars ?? 4e5,
|
|
8623
8677
|
maxRefImages: savedGate?.maxRefImages ?? config.maxRefImages ?? 24,
|
|
8678
|
+
contextWindow: savedGate?.contextWindow ?? 1048576,
|
|
8624
8679
|
idleTimeoutMs: config.idleTimeoutMs ?? 12e4,
|
|
8625
8680
|
deleteWebSessions: config.deleteWebSessions !== false,
|
|
8626
8681
|
sessionReuseTurns: config.sessionReuseTurns ?? 20,
|
|
@@ -8790,6 +8845,9 @@ function apply(ctx, config = {}) {
|
|
|
8790
8845
|
maxPromptCharsDefault: DEFAULT_MAX_PROMPT_CHARS,
|
|
8791
8846
|
maxRefImagesBounds: MAX_REF_IMAGES_BOUNDS,
|
|
8792
8847
|
maxRefImagesDefault: 24,
|
|
8848
|
+
contextWindowBounds: CONTEXT_WINDOW_BOUNDS,
|
|
8849
|
+
contextWindowDefault: DEFAULT_CONTEXT_WINDOW,
|
|
8850
|
+
contextWindowOptions: CONTEXT_WINDOW_OPTIONS,
|
|
8793
8851
|
cleanup: sessionCleaner.policy(),
|
|
8794
8852
|
cleanupBounds: {
|
|
8795
8853
|
batch: CLEANUP_BATCH_BOUNDS,
|
|
@@ -8881,6 +8939,17 @@ function apply(ctx, config = {}) {
|
|
|
8881
8939
|
}
|
|
8882
8940
|
patch.maxRefImages = clampMaxRefImages(count);
|
|
8883
8941
|
}
|
|
8942
|
+
if (body.contextWindow !== void 0) {
|
|
8943
|
+
const window = Number(body.contextWindow);
|
|
8944
|
+
if (!Number.isFinite(window)) {
|
|
8945
|
+
sendJson(res, 400, {
|
|
8946
|
+
ok: false,
|
|
8947
|
+
error: "contextWindow 必须是数字"
|
|
8948
|
+
});
|
|
8949
|
+
return;
|
|
8950
|
+
}
|
|
8951
|
+
patch.contextWindow = clampContextWindow(window);
|
|
8952
|
+
}
|
|
8884
8953
|
if (Object.keys(patch).length === 0) {
|
|
8885
8954
|
sendJson(res, 400, {
|
|
8886
8955
|
ok: false,
|
|
@@ -8891,6 +8960,7 @@ function apply(ctx, config = {}) {
|
|
|
8891
8960
|
const applied = gate.configure(patch);
|
|
8892
8961
|
if (applied.maxPromptChars !== void 0) adapterConfig.maxPromptChars = applied.maxPromptChars;
|
|
8893
8962
|
if (applied.maxRefImages !== void 0) adapterConfig.maxRefImages = applied.maxRefImages;
|
|
8963
|
+
if (applied.contextWindow !== void 0) adapterConfig.contextWindow = applied.contextWindow;
|
|
8894
8964
|
if (patch.sessionCleanup) sessionCleaner.configure({ mode: patch.sessionCleanup });
|
|
8895
8965
|
const rangePatch = {};
|
|
8896
8966
|
if (patch.cleanupBatch) rangePatch.batchRange = patch.cleanupBatch;
|