dsh-connect-modelscope-token-plan 0.2.0 → 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 +101 -0
- package/README.md +33 -2
- package/client.js +778 -85
- package/cordis.patch.yml +27 -0
- package/lib/{host-config-C4bWNPWU.js → host-config.js} +206 -47
- package/lib/index.js +2003 -297
- package/lib/{llm-adapter-DnaNNORe.js → llm-adapter.js} +21 -12
- package/locale/en.json +2 -1
- package/package.json +13 -5
package/cordis.patch.yml
CHANGED
|
@@ -54,5 +54,32 @@
|
|
|
54
54
|
# 次数计费」的口径这反而是对的)。详见 src/host/usage-observer.ts 文件头
|
|
55
55
|
# 与 README「诚实声明」。
|
|
56
56
|
registerProvider: false
|
|
57
|
+
# ------------------------------------------------------------------
|
|
58
|
+
# 给 agent 注册出图工具(`modelscope_draw_image`)。**与上面的
|
|
59
|
+
# registerProvider 是两条独立开关**:那个管「魔搭作为 chat provider」,
|
|
60
|
+
# 这个管「agent 能不能出图」。默认同样关(opt-in)。
|
|
61
|
+
#
|
|
62
|
+
# 实测要点(docs/SPIKE-image-gen.md):
|
|
63
|
+
# · 上游是**异步两段式**:提交拿 task_id,再带
|
|
64
|
+
# `X-ModelScope-Task-Type: image_generation` 轮询到终态;
|
|
65
|
+
# · 提交响应里的 task_status 恒为 SUCCEED 且**不可信**,成功只看轮询终态;
|
|
66
|
+
# · 耗时不稳(实测 61s–537s,免费池排队),故超时取 15 分钟;
|
|
67
|
+
# · 出图**不扣**魔粒(chat 才扣,1 次 = 1 魔粒),所以面板刻意**不显示**
|
|
68
|
+
# 出图计数——那会变成拿 chat 的口径给生图记账。
|
|
69
|
+
#
|
|
70
|
+
# 生效时机:开关值立即保存,但**工具的挂载发生在下次 Host 启动**——
|
|
71
|
+
# peer 的 tools registry 没有 unregister,工具一旦注册就摘不下来。
|
|
72
|
+
# 面板会就这一点给出提示(draw.restartHint)。
|
|
73
|
+
drawEnabled: false
|
|
74
|
+
# 出图默认模型(空 = 自动取目录里第一个出图模型)。
|
|
75
|
+
# 注意只有目录内**平台声明**出图能力的模型才进候选:实测目录 35 条里
|
|
76
|
+
# 只有 2 条 image-to-image(Qwen/Qwen-Image-Edit、MusePublic/…),
|
|
77
|
+
# 没有任何 text-to-image。官方示例里的 Qwen/Qwen-Image-2.1-Turbo 与
|
|
78
|
+
# black-forest-labs/FLUX.1-Kontext-dev **都不在目录内**,后者实测 FAILED。
|
|
79
|
+
drawModelId: ""
|
|
80
|
+
# 单次出图总预算(毫秒),含提交与全部轮询。上界 900000(15 分钟)。
|
|
81
|
+
# 别调小:实测最慢一次 859s 才成功,而超时放弃**不等于**任务死亡
|
|
82
|
+
# (上游会继续跑),把预算压到 5 分钟曾实测击穿。
|
|
83
|
+
drawTimeoutMs: 900000
|
|
57
84
|
# 追加可信 Host 名(默认 localhost / 127.0.0.1 / ::1,只增不替)。
|
|
58
85
|
# allowedHosts: []
|
|
@@ -61,9 +61,11 @@ function pluginError(code, message, extra = {}) {
|
|
|
61
61
|
*
|
|
62
62
|
* 根因(对照 peer 源码 `@deepseek-ai/dsh-llm-pi-ai` 的 `classifyPiAiError`
|
|
63
63
|
* 与 `@deepseek-ai/dsh-llm` 的 `isQuotaExceededError`,二者均为**非行号锚**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
64
|
+
* 的稳定符号。**注意:peer 的判定顺序与措辞命中面目前没有任何测试钉死**——验证
|
|
65
|
+
* 它需要运行时 peer,而 peer 未 vendored 进本仓库,所以进不了 `npm test` 离线
|
|
66
|
+
* 门禁(见 docs/ROADMAP.md 的 Backlog)。本模块自身的纠正判定由
|
|
67
|
+
* `test/error-fix.test.mjs` 钉死;那只能证明「给定这样的 peer 行为,我们的纠正
|
|
68
|
+
* 是对的」,证明不了 peer 的行为本身没有漂移):
|
|
67
69
|
* `classifyPiAiError` **先**跑 `isQuotaExceededError`(命中面极宽:`out of
|
|
68
70
|
* ... budget`、`balance/credits exhausted` 等),**后**才跑纯限频分支
|
|
69
71
|
* (`\b429\b|rate.?limit`)。凡是魔搭 429 体里带上一两个 “budget/credits/
|
|
@@ -256,25 +258,26 @@ async function* reclassifyStream(source) {
|
|
|
256
258
|
/**
|
|
257
259
|
* 目录条目 → pi-ai model descriptor 的映射层——魔搭 provider 注册的**纯函数半边**。
|
|
258
260
|
*
|
|
259
|
-
*
|
|
260
|
-
* `@deepseek-ai/dsh-llm-pi-ai
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
269
|
-
*
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
*
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
261
|
+
* **TL;DR**:本模块只产普通对象、刻意不 import 任何 Host peer(`@earendil-works/pi-ai`、
|
|
262
|
+
* `@deepseek-ai/dsh-llm-pi-ai`),所以这些映射决策可以在一个干净的 checkout 上
|
|
263
|
+
* 离线测;peer 依赖的另一半(把 descriptor 交给 `createProvider`)在 `llm-adapter.ts`。
|
|
264
|
+
* 下面三条是**当前契约**,改动前请先读文末「演变记录」。
|
|
265
|
+
*
|
|
266
|
+
* 1. `compat.supportsDeveloperRole: false`——pi-ai 缺省会**自动探测**这个标志,
|
|
267
|
+
* 对非标准 provider 一律猜 `true`,于是每条请求都用 `developer` 角色,魔搭这个
|
|
268
|
+
* 多模型代理不认识,会 400 或 403。qoder 路由证明必须显式写 false。
|
|
269
|
+
* 2. `maxTokens` 只在目录**声明了**上限时声明——harness 对未声明的 maxTokens
|
|
270
|
+
* 用 `defaultMaxTokens ?? 32768` 兜底,所以「不声明」是「平台没说」的诚实处理,
|
|
271
|
+
* 别猜数字填。
|
|
272
|
+
* 3. `reasoning: false` + **不设** `thinkingLevelMap`——魔搭 API-Inference 是
|
|
273
|
+
* 多模型代理,是否吃 `reasoning_effort` 取决于背后那个具体模型,本插件无法
|
|
274
|
+
* 离线得知每个 id 的档位表(sensenova 那份是拿真令牌逐模型探测才钉出来的)。
|
|
275
|
+
*
|
|
276
|
+
* ## 演变记录(历史,非契约)
|
|
277
|
+
* 关于第 3 条,真实障碍**不是**「发错档位会整条请求 400」——该理由于 2026-10-05
|
|
278
|
+
* 被真机证伪(`"bogus"` 同样 200,值不被校验)——而是无法区分「参数生效」与
|
|
279
|
+
* 「被静默忽略」(两者都 200),且该端点会在真响应与空壳 200 之间摇摆,档位表
|
|
280
|
+
* 做不出来。理由与实测见 PROVIDER-M4.md §4。
|
|
278
281
|
*
|
|
279
282
|
* @module dsh-connect-modelscope-token-plan/llm-models
|
|
280
283
|
*/
|
|
@@ -550,6 +553,24 @@ function contextWindowOf(entry) {
|
|
|
550
553
|
return FALLBACK_CONTEXT_WINDOW;
|
|
551
554
|
}
|
|
552
555
|
/**
|
|
556
|
+
* 这个条目的窗口数字从真值链哪一级来——与 contextWindowOf 配对的来源标记。
|
|
557
|
+
*
|
|
558
|
+
* catalog = 目录四键声明过(平台真值);override = fetchModels 打标时写入的
|
|
559
|
+
* 用户覆盖;curated = 打标时写入的策展表值。后两者在归一条目上是不可区分的
|
|
560
|
+
* (都表现为 contextWindow 键有值),所以打标侧各自留指纹:覆盖命中时在
|
|
561
|
+
* source 上放 `__contextSource: "override"`,策展命中放 `"curated"`,本函数
|
|
562
|
+
* 只读指纹。都没有 → "catalog"(含义是「目录说了算」,包括目录没声明、值
|
|
563
|
+
* 就是 pi-ai 兜底 128k 的条目——面板把 128k 徽章留给这个状态,策展命中会
|
|
564
|
+
* 显示自己的数值)。
|
|
565
|
+
* @param {object} entry - 一条归一目录条目。
|
|
566
|
+
* @returns {"catalog"|"override"|"curated"} 来源标记。
|
|
567
|
+
*/
|
|
568
|
+
function contextWindowSourceOf(entry) {
|
|
569
|
+
const mark = (entry?.raw)?.__contextSource;
|
|
570
|
+
if (mark === "override" || mark === "curated") return mark;
|
|
571
|
+
return "catalog";
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
553
574
|
* 读目录声明的单次输出上限,0 = 未声明。
|
|
554
575
|
*
|
|
555
576
|
* 这个数**只用于展示/投影**。descriptor 只在 >0 时声明 `maxTokens`(见模块头注
|
|
@@ -645,6 +666,50 @@ function filterByEnabled(entries, enabledIds) {
|
|
|
645
666
|
return (Array.isArray(entries) ? entries : []).filter((entry) => allow.has(str(entry?.id, "")));
|
|
646
667
|
}
|
|
647
668
|
/**
|
|
669
|
+
* 面板用的 roster:每条可寻址 chat 条目一行。
|
|
670
|
+
*
|
|
671
|
+
* 刻意是投影而非原始条目:快照只带 picker 需要的(id、展示名、与 descriptor
|
|
672
|
+
* 相同的 vision 判定、以及供能力路由用的 capability),平台将来新增的目录字段
|
|
673
|
+
* 不会为了没理由泄到面板。
|
|
674
|
+
*
|
|
675
|
+
* 去重保留**末次出现**(与 {@link buildDescriptors} 一致):同 id 更新的读取赢。
|
|
676
|
+
* 这里要是分叉了,面板清单和注册结果就会就「哪些模型存在」说两套话,勾选的模型
|
|
677
|
+
* 可能变成未注册的。
|
|
678
|
+
* @param {object[]} entries - 归一目录条目。
|
|
679
|
+
* @returns {{id: string, name: string, vision: boolean, capability: ModelCapability}[]}
|
|
680
|
+
*/
|
|
681
|
+
/**
|
|
682
|
+
* 构建一份去重 roster 的**共享循环骨架**:过滤 chat 模型 → 取 id → 投 row →
|
|
683
|
+
* position-map 去重(末次出现赢)。两个公开 roster 函数(rosterOf /
|
|
684
|
+
* rosterWithAvailability)只投各自的 row 形状,过滤/取 id/去重不再各写一遍
|
|
685
|
+
* ——它们曾各写一份相同的循环,jscpd 抓到 :493-504 ↔ :568-577。
|
|
686
|
+
*
|
|
687
|
+
* 语义承重,与 {@link buildDescriptors} 一致:同 id 末次出现赢;顺序为目录
|
|
688
|
+
* 首见序。这里分叉了,面板清单和注册结果就会就「哪些模型存在」说两套话。
|
|
689
|
+
* @template T - 一行 roster 的形状(由调用方投)。
|
|
690
|
+
* @param {object[]} entries - 归一目录条目。
|
|
691
|
+
* @param {(entry: CatalogEntry, id: string) => T} project - 条目 → 行。
|
|
692
|
+
* @returns {T[]}
|
|
693
|
+
*/
|
|
694
|
+
function buildRosterRows(entries, project) {
|
|
695
|
+
const position = /* @__PURE__ */ new Map();
|
|
696
|
+
const out = [];
|
|
697
|
+
for (const entry of Array.isArray(entries) ? entries : []) {
|
|
698
|
+
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) continue;
|
|
699
|
+
const catalogEntry = entry;
|
|
700
|
+
if (!isChatModel(catalogEntry)) continue;
|
|
701
|
+
const id = str(catalogEntry.id, "");
|
|
702
|
+
if (id === "") continue;
|
|
703
|
+
const row = project(catalogEntry, id);
|
|
704
|
+
if (position.has(id)) out[position.get(id)] = row;
|
|
705
|
+
else {
|
|
706
|
+
position.set(id, out.length);
|
|
707
|
+
out.push(row);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
return out;
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
648
713
|
* 为一份目录构建整份 descriptor 列表。
|
|
649
714
|
*
|
|
650
715
|
* 没有 id 的条目丢弃(线上没法寻址),重复 id 保留末次出现,与 `rosterOf` 的
|
|
@@ -682,6 +747,81 @@ function buildDescriptors(entries, options = {}) {
|
|
|
682
747
|
return out;
|
|
683
748
|
}
|
|
684
749
|
/**
|
|
750
|
+
* 一条目录条目能不能**出图**。
|
|
751
|
+
*
|
|
752
|
+
* 判据是能力枚举里的两个出图档:`text-to-image`(文生图)与 `image-to-image`
|
|
753
|
+
* (图生图/改图)。**只认平台声明的能力**(详情端点 `Tasks[].Name` 或结构化模态
|
|
754
|
+
* 字段),不额外加名字正则——名字启发是 `resolveModelCapability` 里最后才用的兜底,
|
|
755
|
+
* 它把「说不清」的条目标成 `unknown`,那种条目**不**进候选。
|
|
756
|
+
*
|
|
757
|
+
* 与 `isVisionModel` 的严格方向同源:吃图判定宁可漏(漏了报 UNSUPPORTED_CONTENT,
|
|
758
|
+
* 面板看得见),出图判定同理宁可漏(漏了报「目录里没有出图模型」,可诊断);反过来
|
|
759
|
+
* 猜错会把 agent 的请求发给一个出不了图的模型,换回一个原因不可知的 FAILED。
|
|
760
|
+
*
|
|
761
|
+
* 实测(2026-10-10):api-inference 的 35 条目录里**没有 `text-to-image`**,只有 2 条
|
|
762
|
+
* `image-to-image`(`Qwen/Qwen-Image-Edit`、`MusePublic/Qwen-Image-Edit`),两者均
|
|
763
|
+
* 经 `/v1/images/generations` 出图成功。详见 docs/SPIKE-image-gen.md。
|
|
764
|
+
* @param {object} entry - 一条归一目录条目。
|
|
765
|
+
* @returns {boolean} 是否可用于出图。
|
|
766
|
+
*/
|
|
767
|
+
function isImageGenModel(entry) {
|
|
768
|
+
const capability = resolveModelCapability(entry);
|
|
769
|
+
return capability === "text-to-image" || capability === "image-to-image";
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* 一份目录里匹配某判定的模型 id,按首见顺序去重。
|
|
773
|
+
*
|
|
774
|
+
* 去重口径与 `buildDescriptors` / `rosterOf` 一致(保留末次出现的值、占首见位置),
|
|
775
|
+
* 这样出图候选列表与 chat roster 不会对「有哪些 id」各说一套。`imageGenModelIds`
|
|
776
|
+
* 与 `textToImageModelIds` 共用这一份骨架,避免两处各自写一份相同的循环。
|
|
777
|
+
* @param {unknown} entries - 归一目录条目。
|
|
778
|
+
* @param {(entry: CatalogEntry) => boolean} isMatch - 条目匹配判定。
|
|
779
|
+
* @returns {string[]} 匹配的模型 id。
|
|
780
|
+
*/
|
|
781
|
+
function idsOf(entries, isMatch) {
|
|
782
|
+
const position = /* @__PURE__ */ new Map();
|
|
783
|
+
const out = [];
|
|
784
|
+
for (const entry of Array.isArray(entries) ? entries : []) {
|
|
785
|
+
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) continue;
|
|
786
|
+
if (!isMatch(entry)) continue;
|
|
787
|
+
const id = str(entry.id, "");
|
|
788
|
+
if (id === "") continue;
|
|
789
|
+
const seen = position.get(id);
|
|
790
|
+
if (seen === void 0) {
|
|
791
|
+
position.set(id, out.length);
|
|
792
|
+
out.push(id);
|
|
793
|
+
} else out[seen] = id;
|
|
794
|
+
}
|
|
795
|
+
return out;
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* 一份目录里可用于出图的模型 id,按首见顺序去重。
|
|
799
|
+
*
|
|
800
|
+
* 去重口径见 {@link idsOf}。**注意**:这里只保证「平台声明能出图」,不保证
|
|
801
|
+
* 「能纯文生图」——真实目录里唯一的出图条目是 `image-to-image`,其中
|
|
802
|
+
* `MusePublic/Qwen-Image-Edit` 纯文生图被上游拒绝(见 `draw-runtime.ts` 的
|
|
803
|
+
* `KNOWN_T2I_MODEL_ID`)。挑默认模型要走 `pickDrawModel` 的完整优先级,别直接
|
|
804
|
+
* 取这里的第一个。
|
|
805
|
+
* @param {unknown} entries - 归一目录条目。
|
|
806
|
+
* @returns {string[]} 出图模型 id。
|
|
807
|
+
*/
|
|
808
|
+
function imageGenModelIds(entries) {
|
|
809
|
+
return idsOf(entries, isImageGenModel);
|
|
810
|
+
}
|
|
811
|
+
/**
|
|
812
|
+
* 一份目录里**平台声明为文生图**(`text-to-image`)的模型 id,按首见顺序去重。
|
|
813
|
+
*
|
|
814
|
+
* 与 `imageGenModelIds` 同一份去重骨架,只筛能力为 `text-to-image` 的条目。
|
|
815
|
+
* 真实目录至今为空集(api-inference 的 36 条里没有 `text-to-image`),但将来
|
|
816
|
+
* 目录补上真文生图模型时,`pickDrawModel` 应当优先挑它们——这个函数就是那个
|
|
817
|
+
* 「平台说了算」的优先通道。
|
|
818
|
+
* @param {unknown} entries - 归一目录条目。
|
|
819
|
+
* @returns {string[]} 文生图模型 id。
|
|
820
|
+
*/
|
|
821
|
+
function textToImageModelIds(entries) {
|
|
822
|
+
return idsOf(entries, (entry) => resolveModelCapability(entry) === "text-to-image");
|
|
823
|
+
}
|
|
824
|
+
/**
|
|
685
825
|
* 带额度可用性的面板 roster。
|
|
686
826
|
*
|
|
687
827
|
* 与 {@link rosterOf} 一样每 chat 模型 id 一行,但每行还带该模型额度池是否耗尽。
|
|
@@ -693,29 +833,17 @@ function buildDescriptors(entries, options = {}) {
|
|
|
693
833
|
*/
|
|
694
834
|
function rosterWithAvailability(entries, unavailableIds) {
|
|
695
835
|
const blocked = new Set(Array.isArray(unavailableIds) ? unavailableIds : []);
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
available: !blocked.has(id),
|
|
708
|
-
quotaExhausted: blocked.has(id),
|
|
709
|
-
contextWindow: contextWindowOf(entry),
|
|
710
|
-
maxOutputLength: maxOutputLengthOf(entry)
|
|
711
|
-
};
|
|
712
|
-
if (position.has(id)) out[position.get(id)] = row;
|
|
713
|
-
else {
|
|
714
|
-
position.set(id, out.length);
|
|
715
|
-
out.push(row);
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
return out;
|
|
836
|
+
return buildRosterRows(entries, (entry, id) => ({
|
|
837
|
+
id,
|
|
838
|
+
name: str(entry.name, id),
|
|
839
|
+
vision: isVisionModel(entry),
|
|
840
|
+
capability: resolveModelCapability(entry),
|
|
841
|
+
available: !blocked.has(id),
|
|
842
|
+
quotaExhausted: blocked.has(id),
|
|
843
|
+
contextWindow: contextWindowOf(entry),
|
|
844
|
+
contextSource: contextWindowSourceOf(entry),
|
|
845
|
+
maxOutputLength: maxOutputLengthOf(entry)
|
|
846
|
+
}));
|
|
719
847
|
}
|
|
720
848
|
|
|
721
849
|
//#endregion
|
|
@@ -744,7 +872,7 @@ const inject = ["webServer"];
|
|
|
744
872
|
* 产物反而引入第二份真源;这里用常量、由 test/config.test.mjs 钉住与
|
|
745
873
|
* package.json 一致。
|
|
746
874
|
*/
|
|
747
|
-
const PLUGIN_VERSION = "0.
|
|
875
|
+
const PLUGIN_VERSION = "0.3.0";
|
|
748
876
|
/**
|
|
749
877
|
* 默认值。刻意不含额度常数——理由见本文件头。
|
|
750
878
|
* 面板头条是官方魔粒余额,次数口径的推算已在面板收敛时删除,这里若留着
|
|
@@ -767,6 +895,31 @@ const CONFIG_DEFAULTS = Object.freeze({
|
|
|
767
895
|
maxEvents: 50,
|
|
768
896
|
/** provider 注册的 patch 默认值(面板保存值优先于它)。 */
|
|
769
897
|
registerProvider: false,
|
|
898
|
+
/**
|
|
899
|
+
* 出图工具的 patch 默认值(面板保存值优先于它)。
|
|
900
|
+
*
|
|
901
|
+
* **与 `registerProvider` 是两个独立开关**:前者是「把魔搭当 chat provider」,
|
|
902
|
+
* 后者是「给 agent 一个出图工具」。默认同为 false(opt-in),但互不牵连。
|
|
903
|
+
* 实测依据见 docs/SPIKE-image-gen.md。
|
|
904
|
+
*/
|
|
905
|
+
drawEnabled: false,
|
|
906
|
+
/** 出图默认模型(空 = 自动挑目录里第一个出图模型)。 */
|
|
907
|
+
drawModelId: "",
|
|
908
|
+
/**
|
|
909
|
+
* 单次出图的总预算(毫秒),含提交与全部轮询。
|
|
910
|
+
*
|
|
911
|
+
* 默认 **15 分钟**。这是本字段第三次调整,每次都有实测依据:
|
|
912
|
+
* 1. 最初据「任务慢」定 10 分钟,后归因为「轮询太密」,改为 5 分钟;
|
|
913
|
+
* 2. 该归因**已被推翻**——2026-10-10 同一模型、同样 15s 轮询连测三次,
|
|
914
|
+
* 耗时 61s → 261s → **537s**,单调恶化。是上游免费池的**排队时长在波动**,
|
|
915
|
+
* 与轮询间隔无关(那次 5s 轮询的 >185s 观测不能再当作证据);
|
|
916
|
+
* 3. 5 分钟预算因此**实测被击穿**:一次真实 e2e 在 300s 处放弃,而任务仍活着。
|
|
917
|
+
*
|
|
918
|
+
* 取 15 分钟:覆盖已观测到的最慢一次(537s)并留一倍余量。**注意超时放弃不等于
|
|
919
|
+
* 任务死亡**——上游任务会继续跑(且记录最终会被回收,见 docs/SPIKE-image-gen.md
|
|
920
|
+
* §坑 5)。宁可多等,不要把一张已经在生成的图扔掉。
|
|
921
|
+
*/
|
|
922
|
+
drawTimeoutMs: 9e5,
|
|
770
923
|
/** Host 应答的默认主机名;操作者的列表是「只增不替」。 */
|
|
771
924
|
admittedHosts: [
|
|
772
925
|
"localhost",
|
|
@@ -816,6 +969,9 @@ function resolveSettings(config) {
|
|
|
816
969
|
inferenceTimeoutMs: clampInt(source.inferenceTimeoutMs, CONFIG_DEFAULTS.inferenceTimeoutMs, 1e3, 6e5),
|
|
817
970
|
maxEvents: clampInt(source.maxEvents, CONFIG_DEFAULTS.maxEvents, 1, 1e3),
|
|
818
971
|
registerProvider: source.registerProvider === true,
|
|
972
|
+
drawEnabled: source.drawEnabled === true,
|
|
973
|
+
drawModelId: str(source.drawModelId, CONFIG_DEFAULTS.drawModelId),
|
|
974
|
+
drawTimeoutMs: clampInt(source.drawTimeoutMs, CONFIG_DEFAULTS.drawTimeoutMs, 3e4, 9e5),
|
|
819
975
|
allowedHosts: resolveAllowedHosts(source)
|
|
820
976
|
},
|
|
821
977
|
configError: null
|
|
@@ -831,6 +987,9 @@ function resolveSettings(config) {
|
|
|
831
987
|
inferenceTimeoutMs: CONFIG_DEFAULTS.inferenceTimeoutMs,
|
|
832
988
|
maxEvents: CONFIG_DEFAULTS.maxEvents,
|
|
833
989
|
registerProvider: false,
|
|
990
|
+
drawEnabled: false,
|
|
991
|
+
drawModelId: CONFIG_DEFAULTS.drawModelId,
|
|
992
|
+
drawTimeoutMs: CONFIG_DEFAULTS.drawTimeoutMs,
|
|
834
993
|
allowedHosts: new Set(CONFIG_DEFAULTS.admittedHosts)
|
|
835
994
|
},
|
|
836
995
|
configError: redactSecrets(errMsg(error))
|
|
@@ -897,4 +1056,4 @@ function isAdmitted(request, allowedHosts) {
|
|
|
897
1056
|
}
|
|
898
1057
|
|
|
899
1058
|
//#endregion
|
|
900
|
-
export {
|
|
1059
|
+
export { optional as C, verbatim as D, str as E, obj as S, redactSecrets as T, hasHardQuotaWordingIn as _, resolveSettings as a, degrade as b, LLM_PROVIDER_ID as c, isVisionModel as d, normalizeEntry as f, CODE as g, textToImageModelIds as h, name as i, buildDescriptors as l, rosterWithAvailability as m, inject as n, LLM_API_KEY_NAME as o, resolveAllowedList as p, isAdmitted as r, LLM_DISPLAY_NAME as s, PLUGIN_VERSION as t, imageGenModelIds as u, looksLikeRateLimit as v, pluginError as w, errMsg as x, reclassifyStream as y };
|