dsh-gpt-adapter 0.2.4 → 0.2.5
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 +11 -14
- package/README.zh-CN.md +11 -14
- package/dist/src/host.d.ts +13 -1
- package/dist/src/settings-overlay.d.ts +2 -0
- package/lib/client.js +56 -262
- package/lib/index.js +125 -79
- package/package.json +1 -1
- package/dist/src/client/context-window.d.ts +0 -9
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ Install one plugin to reuse local Codex instructions, skills, enabled plugin res
|
|
|
12
12
|
|
|
13
13
|
- Discover upstream models with `GET /models` and retain stale entries until explicit cleanup.
|
|
14
14
|
- Provide the GPT reasoning preset `low / medium / high / xhigh / max / ultra` through the native Models page and conversation menu.
|
|
15
|
-
-
|
|
15
|
+
- Reuse the native per-model context field for manual capacities and automatic resolution, with support for K/M input.
|
|
16
16
|
- Offer independent Standard and Fast speed choices. Fast sends `service_tier: "priority"`; Ultrafast requires an explicit upstream declaration or override.
|
|
17
17
|
- Preserve optional function arguments on GPT Responses requests by setting missing `strict` values to `false`.
|
|
18
18
|
- Read Codex instruction files and refresh them at the next model step without repeating unchanged baselines.
|
|
@@ -23,14 +23,14 @@ Reasoning and speed presets are requests to the configured gateway, not guarante
|
|
|
23
23
|
|
|
24
24
|
## Compatibility and installation
|
|
25
25
|
|
|
26
|
-
The native integration targets DSH `0.2.2-rc.1`, Cordis `4.1.0`, and the pinned adapter source hash. The development dependency uses Pi AI `1.3.0`. Installed third-party package files are never edited. The package version is `dsh-gpt-adapter@0.2.
|
|
26
|
+
The native integration targets DSH `0.2.2-rc.1`, Cordis `4.1.0`, and the pinned adapter source hash. The development dependency uses Pi AI `1.3.0`. Installed third-party package files are never edited. The package version is `dsh-gpt-adapter@0.2.5`.
|
|
27
27
|
|
|
28
28
|
Requires Node.js `>=24.9.0` and DSH. Source builds also require pnpm.
|
|
29
29
|
|
|
30
30
|
Install the published package in the web profile:
|
|
31
31
|
|
|
32
32
|
```sh
|
|
33
|
-
dsh plugin --profile web add dsh-gpt-adapter@0.2.
|
|
33
|
+
dsh plugin --profile web add dsh-gpt-adapter@0.2.5
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
Restart the DSH host after installing or upgrading. Configure GPT connections under **Settings → Models**; Codex environment reuse is enabled by default. The plugin extends the existing native settings and conversation controls.
|
|
@@ -43,7 +43,7 @@ cd dsh-gpt-adapter
|
|
|
43
43
|
pnpm install --frozen-lockfile
|
|
44
44
|
mkdir -p artifacts
|
|
45
45
|
pnpm pack --pack-destination artifacts
|
|
46
|
-
dsh plugin --profile web add ./artifacts/dsh-gpt-adapter-0.2.
|
|
46
|
+
dsh plugin --profile web add ./artifacts/dsh-gpt-adapter-0.2.5.tgz
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
`pnpm pack` runs the production build.
|
|
@@ -128,22 +128,19 @@ Capability precedence is user override, explicit upstream metadata, external cat
|
|
|
128
128
|
|
|
129
129
|
### Context windows
|
|
130
130
|
|
|
131
|
-
Under **Settings → Models**,
|
|
131
|
+
Under **Settings → Models → Custom settings → Model catalog**, edit the native **Context window** field. The plugin reuses this field and adds no separate context editor. Enter a count, `516K` (`516000` tokens), or `1M` (`1000000` tokens); clear the field and save to restore automatic resolution.
|
|
132
132
|
|
|
133
|
-
|
|
134
|
-
| --- | --- |
|
|
135
|
-
| Default | Resolve automatically for this model and provider. |
|
|
136
|
-
| 516K | `516000` |
|
|
137
|
-
| 1M | `1000000` |
|
|
138
|
-
| Custom | A positive safe integer entered by the user. |
|
|
133
|
+
Inherited model rows and provider defaults participate in edit detection and final budget validation. A failed legacy cleanup restores the previous native capacity while preserving unrelated edits.
|
|
139
134
|
|
|
140
|
-
|
|
135
|
+
An empty native field means automatic resolution. Automatic capacities stay in the effective model information; the editable draft contains manual values only, including existing legacy overrides. An explicit value equal to the current automatic capacity is still saved as a manual value.
|
|
141
136
|
|
|
142
|
-
|
|
137
|
+
Capacity suffixes use decimal units. Automatic resolution uses a distinguishable explicit provider default, upstream model metadata, the configured capability catalog, the shipped exact-model preset, then the native catalog/DSH fallback. Shipped presets are dated data, not a live fetch from OpenAI: `gpt-6-astra`, `gpt-6.1-sol`, `gpt-6.1-terra`, `gpt-6-luna`, and `gpt-5.4` use `1050000`; `gpt-4.1` uses `1047576`; `gpt-4o` uses `128000`. Only documented snapshot aliases share these presets. References and verification dates are in [the preset table](src/context-window.ts).
|
|
138
|
+
|
|
139
|
+
Existing native per-model values, including catalog `modelOverrides`, and legacy JSON context overrides remain effective until deliberately edited. Editing the native context field clears only that model's legacy context override; clearing the field removes its manual context values while retaining provider defaults and other settings. Saving unrelated settings or discovering models does not turn automatic values into manual overrides. Identical model IDs on different providers are independent.
|
|
143
140
|
|
|
144
141
|
Providers using native catalog `modelOverrides` keep their catalog configuration during synchronization. Discovery and stale cleanup update the plugin snapshot without creating an incompatible explicit `models` list or deleting native overrides.
|
|
145
142
|
|
|
146
|
-
Native forms reject stale drafts when their automatic capacities change; refresh the form before retrying.
|
|
143
|
+
Native forms reject stale drafts when their automatic capacities change; refresh the form before retrying. Context, output-limit, and relevant provider-default edits are checked against the saved draft's output budget and native compaction headroom. An omitted output limit uses the native model catalog or provider/schema default. Invalid saves leave the previous values in place.
|
|
147
144
|
|
|
148
145
|
Changes apply to the next prepared call; calls already prepared retain their captured capacity. Model information, the inference model, overflow detection, and native compaction use the same effective window. Maximum output tokens and DSH's compaction policy remain independent. A larger local window does not increase the gateway's accepted limit.
|
|
149
146
|
|
package/README.zh-CN.md
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
- 通过 `GET /models` 发现上游模型;失效模型保留到用户主动清理。
|
|
14
14
|
- 在原生模型设置页和对话菜单中提供 `low / medium / high / xhigh / max / ultra` 六档思考预设。
|
|
15
|
-
-
|
|
15
|
+
- 复用原生逐模型上下文字段,支持 K/M 输入、手动容量和自动解析。
|
|
16
16
|
- 提供独立的 Standard 和 Fast 速度选择。Fast 发送 `service_tier: "priority"`;Ultrafast 由上游明确声明或用户覆盖提供。
|
|
17
17
|
- 为 GPT Responses 函数工具补齐缺失的 `strict: false`,保留可选参数。
|
|
18
18
|
- 读取 Codex 指令,在下一模型步骤更新;内容不变时不重复注入。
|
|
@@ -23,14 +23,14 @@
|
|
|
23
23
|
|
|
24
24
|
## 兼容性与安装
|
|
25
25
|
|
|
26
|
-
原生集成面向 DSH `0.2.2-rc.1`、Cordis `4.1.0`,并校验适配器源码指纹。开发依赖固定 Pi AI `1.3.0`。插件不会修改已安装的第三方包文件。插件版本为 `dsh-gpt-adapter@0.2.
|
|
26
|
+
原生集成面向 DSH `0.2.2-rc.1`、Cordis `4.1.0`,并校验适配器源码指纹。开发依赖固定 Pi AI `1.3.0`。插件不会修改已安装的第三方包文件。插件版本为 `dsh-gpt-adapter@0.2.5`。
|
|
27
27
|
|
|
28
28
|
需要 Node.js `>=24.9.0` 和 DSH。源码构建另外需要 pnpm。
|
|
29
29
|
|
|
30
30
|
在 `web` 配置档(profile)中安装已发布的 npm 包:
|
|
31
31
|
|
|
32
32
|
```sh
|
|
33
|
-
dsh plugin --profile web add dsh-gpt-adapter@0.2.
|
|
33
|
+
dsh plugin --profile web add dsh-gpt-adapter@0.2.5
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
安装或升级后重启 DSH 宿主。在「设置 → 模型」中配置 GPT 连接;Codex 环境复用默认开启。插件扩展现有原生设置与对话控件。
|
|
@@ -43,7 +43,7 @@ cd dsh-gpt-adapter
|
|
|
43
43
|
pnpm install --frozen-lockfile
|
|
44
44
|
mkdir -p artifacts
|
|
45
45
|
pnpm pack --pack-destination artifacts
|
|
46
|
-
dsh plugin --profile web add ./artifacts/dsh-gpt-adapter-0.2.
|
|
46
|
+
dsh plugin --profile web add ./artifacts/dsh-gpt-adapter-0.2.5.tgz
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
`pnpm pack` 会自动执行生产构建。
|
|
@@ -128,22 +128,19 @@ codexCompatibility:
|
|
|
128
128
|
|
|
129
129
|
### 上下文窗口
|
|
130
130
|
|
|
131
|
-
在「设置 →
|
|
131
|
+
在「设置 → 模型 → 自定义设置 → 模型目录」中,直接编辑原生「上下文窗口」字段。插件复用这一字段,不再增加独立编辑入口。可输入完整词元数、`516K`(`516000`)或 `1M`(`1000000`);清空字段并保存可恢复自动解析。
|
|
132
132
|
|
|
133
|
-
|
|
134
|
-
| --- | --- |
|
|
135
|
-
| 默认 | 根据当前模型与提供商自动解析。 |
|
|
136
|
-
| 516K | `516000` |
|
|
137
|
-
| 1M | `1000000` |
|
|
138
|
-
| 自定义 | 用户输入的正安全整数。 |
|
|
133
|
+
编辑前后状态比较和最终预算校验会纳入继承模型及提供商默认值。旧覆盖清理失败时,恢复原生容量并保留无关修改。
|
|
139
134
|
|
|
140
|
-
|
|
135
|
+
原生字段留空表示自动解析。自动容量保留在模型有效信息中,编辑草稿只显示手动值(包括已有旧版覆盖);明确输入与当前自动容量相同的数值,也会保存为手动值。
|
|
141
136
|
|
|
142
|
-
|
|
137
|
+
容量后缀使用十进制单位。自动解析依次采用可辨识的显式提供商默认值、上游模型元数据、已配置的能力目录、插件内置的精确模型预设、原生目录或 DSH 后备值。内置预设是带核验日期的数据,不会实时抓取 OpenAI 页面:`gpt-6-astra`、`gpt-6.1-sol`、`gpt-6.1-terra`、`gpt-6-luna`、`gpt-5.4` 为 `1050000`,`gpt-4.1` 为 `1047576`,`gpt-4o` 为 `128000`;仅为有文档依据的快照别名复用预设。参考页面和核验日期见[预设表](src/context-window.ts)。
|
|
138
|
+
|
|
139
|
+
已有原生模型数值(包括目录模型的 `modelOverrides`)和旧版 JSON 上下文覆盖继续生效,直到用户主动编辑。编辑原生上下文字段时,仅清除该模型的旧版上下文覆盖;清空字段会删除该模型的手动上下文数值,保留提供商默认值和其他设置。保存无关设置或发现模型不会把自动值固化为手动覆盖。同名模型在不同提供商下独立设置。
|
|
143
140
|
|
|
144
141
|
使用原生目录 `modelOverrides` 的提供商在同步时保留目录配置。模型发现和失效清理只更新插件快照,不会生成不兼容的显式 `models` 列表,也不会删除原生覆盖。
|
|
145
142
|
|
|
146
|
-
|
|
143
|
+
原生表单的自动容量变化后,过期草稿会被拒绝,刷新表单再保存即可。修改上下文、最大输出或相关提供商默认值时,会校验同次保存的输出预算和原生压缩预留;未填写输出上限时采用原生模型目录或提供商、参数结构的默认值;无效数值不会覆盖已保存设置。
|
|
147
144
|
|
|
148
145
|
修改对下一次准备的调用生效,已准备的调用继续使用原有容量。模型信息、推理模型、溢出判断和原生上下文压缩采用同一有效窗口;最大输出词元设置与 DSH 原生压缩策略保持独立。扩大本地窗口不会提高网关实际接受的上限。
|
|
149
146
|
|
package/dist/src/host.d.ts
CHANGED
|
@@ -98,8 +98,20 @@ export declare class GptModels extends Service {
|
|
|
98
98
|
updateOptions(provider: string, refreshIntervalMs: number, capabilityCatalogUrl: string, overridesJSON: string): Promise<void>;
|
|
99
99
|
refresh(provider: string): Promise<void>;
|
|
100
100
|
removeStale(provider: string): Promise<void>;
|
|
101
|
+
/** Internal model-list writes must use the same manual fields as native drafts. */
|
|
102
|
+
private editableModel;
|
|
103
|
+
editableContextWindow(provider: string, model: Record<string, any>): any;
|
|
101
104
|
/** Resolve raw metadata separately from merged capabilities and cached overrides. */
|
|
102
|
-
contextWindow(provider: string, modelId: string, nativeDefault?: number
|
|
105
|
+
contextWindow(provider: string, modelId: string, nativeDefault?: number, profileOverride?: {
|
|
106
|
+
defaultContextWindow?: number;
|
|
107
|
+
models?: Array<{
|
|
108
|
+
id: string;
|
|
109
|
+
[key: string]: unknown;
|
|
110
|
+
}>;
|
|
111
|
+
modelOverrides?: Record<string, Record<string, unknown>>;
|
|
112
|
+
}): ContextWindowResolution;
|
|
113
|
+
/** Both native form saves and the compatibility RPC validate the same budget. */
|
|
114
|
+
validateContextWindow(provider: string, model: Record<string, any>, profile: Record<string, any>): void;
|
|
103
115
|
contextWriteRevision(): number | undefined;
|
|
104
116
|
/** Public form revisions also cover changes to projected model capacities. */
|
|
105
117
|
private modelsRevision;
|
|
@@ -11,6 +11,8 @@ export type ContextWindowEdit = {
|
|
|
11
11
|
previousTokens: number | undefined;
|
|
12
12
|
};
|
|
13
13
|
type ContextWrites = {
|
|
14
|
+
editableContext?(provider: string, model: JsonObject): number | undefined;
|
|
15
|
+
validate?(provider: string, model: JsonObject, profile: JsonObject): void;
|
|
14
16
|
revision(): number | undefined;
|
|
15
17
|
saved(edits: ContextWindowEdit[], revision: number | undefined): Promise<void>;
|
|
16
18
|
};
|
package/lib/client.js
CHANGED
|
@@ -25,204 +25,14 @@ __export(index_exports, {
|
|
|
25
25
|
inject: () => inject
|
|
26
26
|
});
|
|
27
27
|
module.exports = __toCommonJS(index_exports);
|
|
28
|
-
var import_react2 = require("react");
|
|
29
|
-
var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
30
|
-
|
|
31
|
-
// gpt-native:native-settings-styles
|
|
32
|
-
var native_settings_styles_default = { "customized": "zGbnIq_customized", "customizedSummary": "zGbnIq_customizedSummary", "customizedBody": "zGbnIq_customizedBody", "rowHead": "zGbnIq_rowHead", "rowName": "zGbnIq_rowName", "rowActions": "zGbnIq_rowActions", "advancedHint": "zGbnIq_advancedHint", "field": "zGbnIq_field", "fieldLabel": "zGbnIq_fieldLabel", "input": "zGbnIq_input", "editorActions": "zGbnIq_editorActions", "error": "zGbnIq_error" };
|
|
33
|
-
|
|
34
|
-
// src/client/context-window.tsx
|
|
35
28
|
var import_react = require("react");
|
|
36
29
|
var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
37
30
|
|
|
38
|
-
//
|
|
39
|
-
var
|
|
40
|
-
["gpt-6-astra", 105e4],
|
|
41
|
-
["gpt-6.1-sol", 105e4],
|
|
42
|
-
["gpt-6.1-terra", 105e4],
|
|
43
|
-
["gpt-6-luna", 105e4],
|
|
44
|
-
["gpt-5.4", 105e4],
|
|
45
|
-
["gpt-4.1", 1047576],
|
|
46
|
-
["gpt-4o", 128e3],
|
|
47
|
-
["gpt-5.4-2026-03-05", 105e4, "gpt-5.4"],
|
|
48
|
-
["gpt-4.1-2025-04-14", 1047576, "gpt-4.1"],
|
|
49
|
-
["gpt-4o-2024-08-06", 128e3, "gpt-4o"]
|
|
50
|
-
];
|
|
51
|
-
var OFFICIAL_CONTEXT_WINDOWS = Object.fromEntries(
|
|
52
|
-
officialModels.map(([id, tokens, page]) => [
|
|
53
|
-
id,
|
|
54
|
-
{
|
|
55
|
-
tokens,
|
|
56
|
-
url: `https://developers.openai.com/api/docs/models/${page ?? id}`,
|
|
57
|
-
verifiedAt: "2026-11-13"
|
|
58
|
-
}
|
|
59
|
-
])
|
|
60
|
-
);
|
|
61
|
-
function validContextWindow(value) {
|
|
62
|
-
return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// src/client/context-window.tsx
|
|
66
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
|
67
|
-
var sources = {
|
|
68
|
-
"legacy-override": "\u5DF2\u6709\u80FD\u529B\u8986\u76D6",
|
|
69
|
-
"native-user": "\u624B\u52A8\u8BBE\u7F6E",
|
|
70
|
-
"provider-default": "\u4F9B\u5E94\u5546\u9ED8\u8BA4",
|
|
71
|
-
upstream: "\u4E0A\u6E38\u6A21\u578B\u76EE\u5F55",
|
|
72
|
-
"capability-catalog": "\u80FD\u529B\u76EE\u5F55",
|
|
73
|
-
"official-preset": "\u5B98\u65B9\u6A21\u578B\u9884\u8BBE",
|
|
74
|
-
"native-default": "DSH \u9ED8\u8BA4"
|
|
75
|
-
};
|
|
76
|
-
function ContextWindowControl({
|
|
77
|
-
provider,
|
|
78
|
-
modelId,
|
|
79
|
-
value,
|
|
80
|
-
revision,
|
|
81
|
-
busy,
|
|
82
|
-
save
|
|
83
|
-
}) {
|
|
84
|
-
const id = (0, import_react.useId)();
|
|
85
|
-
const [mode, setMode] = (0, import_react.useState)(value.mode);
|
|
86
|
-
const [custom, setCustom] = (0, import_react.useState)(String(value.effectiveTokens));
|
|
87
|
-
const [dirty, setDirty] = (0, import_react.useState)(false);
|
|
88
|
-
const [draftRevision, setDraftRevision] = (0, import_react.useState)(revision);
|
|
89
|
-
const contextKey = JSON.stringify([
|
|
90
|
-
value.mode,
|
|
91
|
-
value.effectiveTokens,
|
|
92
|
-
value.defaultTokens,
|
|
93
|
-
value.source
|
|
94
|
-
]);
|
|
95
|
-
const [draftContext, setDraftContext] = (0, import_react.useState)(contextKey);
|
|
96
|
-
(0, import_react.useEffect)(() => {
|
|
97
|
-
if (dirty) {
|
|
98
|
-
if (draftContext === contextKey) setDraftRevision(revision);
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
setMode(value.mode);
|
|
102
|
-
setCustom(String(value.effectiveTokens));
|
|
103
|
-
setDraftRevision(revision);
|
|
104
|
-
setDraftContext(contextKey);
|
|
105
|
-
}, [
|
|
106
|
-
value.mode,
|
|
107
|
-
value.effectiveTokens,
|
|
108
|
-
revision,
|
|
109
|
-
dirty,
|
|
110
|
-
contextKey,
|
|
111
|
-
draftContext
|
|
112
|
-
]);
|
|
113
|
-
const conflict = dirty && draftContext !== contextKey;
|
|
114
|
-
const valid = mode !== "custom" || custom.trim() !== "" && validContextWindow(Number(custom));
|
|
115
|
-
function edit() {
|
|
116
|
-
if (!dirty) {
|
|
117
|
-
setDraftRevision(revision);
|
|
118
|
-
setDraftContext(contextKey);
|
|
119
|
-
}
|
|
120
|
-
setDirty(true);
|
|
121
|
-
}
|
|
122
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
123
|
-
"form",
|
|
124
|
-
{
|
|
125
|
-
className: native_settings_styles_default.field,
|
|
126
|
-
onSubmit: (event) => {
|
|
127
|
-
event.preventDefault();
|
|
128
|
-
if (!valid || busy || conflict) return;
|
|
129
|
-
void save({
|
|
130
|
-
provider,
|
|
131
|
-
modelId,
|
|
132
|
-
mode,
|
|
133
|
-
...mode === "custom" ? { customTokens: Number(custom) } : {},
|
|
134
|
-
expectedRevision: draftRevision
|
|
135
|
-
}).then((saved) => {
|
|
136
|
-
if (saved) setDirty(false);
|
|
137
|
-
});
|
|
138
|
-
},
|
|
139
|
-
children: [
|
|
140
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: native_settings_styles_default.fieldLabel, htmlFor: id, children: modelId }),
|
|
141
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
142
|
-
"select",
|
|
143
|
-
{
|
|
144
|
-
id,
|
|
145
|
-
"aria-label": `${modelId} \u4E0A\u4E0B\u6587\u9884\u8BBE`,
|
|
146
|
-
className: native_settings_styles_default.input,
|
|
147
|
-
value: mode,
|
|
148
|
-
disabled: busy,
|
|
149
|
-
onChange: (event) => {
|
|
150
|
-
edit();
|
|
151
|
-
setMode(event.target.value);
|
|
152
|
-
},
|
|
153
|
-
children: [
|
|
154
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "default", children: "\u9ED8\u8BA4" }),
|
|
155
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "516k", children: "516K" }),
|
|
156
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "1m", children: "1M" }),
|
|
157
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "custom", children: "\u81EA\u5B9A\u4E49" })
|
|
158
|
-
]
|
|
159
|
-
}
|
|
160
|
-
),
|
|
161
|
-
mode === "custom" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
162
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: native_settings_styles_default.fieldLabel, htmlFor: `${id}-custom`, children: "\u81EA\u5B9A\u4E49\u7A97\u53E3\uFF08tokens\uFF09" }),
|
|
163
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
164
|
-
import_dsh_client_ui_primitives.Input,
|
|
165
|
-
{
|
|
166
|
-
id: `${id}-custom`,
|
|
167
|
-
className: native_settings_styles_default.input,
|
|
168
|
-
type: "number",
|
|
169
|
-
min: "1",
|
|
170
|
-
step: "1",
|
|
171
|
-
"aria-label": `${modelId} \u81EA\u5B9A\u4E49\u7A97\u53E3`,
|
|
172
|
-
"aria-invalid": !valid,
|
|
173
|
-
"aria-describedby": !valid ? `${id}-error` : void 0,
|
|
174
|
-
value: custom,
|
|
175
|
-
disabled: busy,
|
|
176
|
-
onChange: (event) => {
|
|
177
|
-
edit();
|
|
178
|
-
setCustom(event.target.value);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
)
|
|
182
|
-
] }),
|
|
183
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: native_settings_styles_default.advancedHint, children: [
|
|
184
|
-
"\u5F53\u524D\uFF1A",
|
|
185
|
-
value.effectiveTokens.toLocaleString("en-US"),
|
|
186
|
-
" tokens \xB7 \u6765\u6E90\uFF1A",
|
|
187
|
-
sources[value.source]
|
|
188
|
-
] }),
|
|
189
|
-
!valid && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { id: `${id}-error`, className: native_settings_styles_default.error, role: "alert", children: "\u8BF7\u8F93\u5165\u6B63\u7684\u5B89\u5168\u6574\u6570" }),
|
|
190
|
-
conflict && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: native_settings_styles_default.error, role: "alert", children: "\u6B64\u6A21\u578B\u7684\u8BBE\u7F6E\u5DF2\u53D8\u5316\uFF0C\u8BF7\u6838\u5BF9\u4E0A\u65B9\u5F53\u524D\u503C\u540E\u7EE7\u7EED\u7F16\u8F91\u3002" }),
|
|
191
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: native_settings_styles_default.editorActions, children: [
|
|
192
|
-
conflict && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
193
|
-
import_dsh_client_ui_primitives.Button,
|
|
194
|
-
{
|
|
195
|
-
type: "button",
|
|
196
|
-
variant: "ghost",
|
|
197
|
-
size: "sm",
|
|
198
|
-
disabled: busy,
|
|
199
|
-
"aria-label": `\u4FDD\u7559 ${modelId} \u8349\u7A3F`,
|
|
200
|
-
onClick: () => {
|
|
201
|
-
setDraftRevision(revision);
|
|
202
|
-
setDraftContext(contextKey);
|
|
203
|
-
},
|
|
204
|
-
children: "\u4FDD\u7559\u8349\u7A3F\u7EE7\u7EED\u7F16\u8F91"
|
|
205
|
-
}
|
|
206
|
-
),
|
|
207
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
208
|
-
import_dsh_client_ui_primitives.Button,
|
|
209
|
-
{
|
|
210
|
-
type: "submit",
|
|
211
|
-
variant: "primary",
|
|
212
|
-
size: "sm",
|
|
213
|
-
disabled: busy || !dirty || !valid || conflict,
|
|
214
|
-
"aria-label": `\u4FDD\u5B58 ${modelId} \u4E0A\u4E0B\u6587`,
|
|
215
|
-
children: busy ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58"
|
|
216
|
-
}
|
|
217
|
-
)
|
|
218
|
-
] })
|
|
219
|
-
]
|
|
220
|
-
}
|
|
221
|
-
);
|
|
222
|
-
}
|
|
31
|
+
// gpt-native:native-settings-styles
|
|
32
|
+
var native_settings_styles_default = { "customized": "zGbnIq_customized", "customizedSummary": "zGbnIq_customizedSummary", "customizedBody": "zGbnIq_customizedBody", "rowHead": "zGbnIq_rowHead", "rowName": "zGbnIq_rowName", "rowActions": "zGbnIq_rowActions", "advancedHint": "zGbnIq_advancedHint", "field": "zGbnIq_field", "fieldLabel": "zGbnIq_fieldLabel", "input": "zGbnIq_input", "editorActions": "zGbnIq_editorActions", "error": "zGbnIq_error" };
|
|
223
33
|
|
|
224
34
|
// src/client/index.tsx
|
|
225
|
-
var
|
|
35
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
226
36
|
var inject = ["slots", "connection", "sessions", "modelDirectories"];
|
|
227
37
|
function apply(ctx) {
|
|
228
38
|
async function call(method, args) {
|
|
@@ -235,11 +45,11 @@ function apply(ctx) {
|
|
|
235
45
|
return result.value;
|
|
236
46
|
}
|
|
237
47
|
function useProvider(provider) {
|
|
238
|
-
const [value, setValue] = (0,
|
|
239
|
-
const [error, setError] = (0,
|
|
240
|
-
const [busy, setBusy] = (0,
|
|
241
|
-
const requests = (0,
|
|
242
|
-
(0,
|
|
48
|
+
const [value, setValue] = (0, import_react.useState)();
|
|
49
|
+
const [error, setError] = (0, import_react.useState)("");
|
|
50
|
+
const [busy, setBusy] = (0, import_react.useState)(false);
|
|
51
|
+
const requests = (0, import_react.useRef)({ sequence: 0, writing: false });
|
|
52
|
+
(0, import_react.useEffect)(() => {
|
|
243
53
|
let active = true;
|
|
244
54
|
requests.current.writing = false;
|
|
245
55
|
setBusy(false);
|
|
@@ -298,15 +108,15 @@ function apply(ctx) {
|
|
|
298
108
|
busy,
|
|
299
109
|
act
|
|
300
110
|
}) {
|
|
301
|
-
const id = (0,
|
|
302
|
-
const [url, setUrl] = (0,
|
|
303
|
-
const [seconds, setSeconds] = (0,
|
|
111
|
+
const id = (0, import_react.useId)();
|
|
112
|
+
const [url, setUrl] = (0, import_react.useState)(value.options.capabilityCatalogUrl ?? "");
|
|
113
|
+
const [seconds, setSeconds] = (0, import_react.useState)(
|
|
304
114
|
String(value.options.refreshIntervalMs / 1e3)
|
|
305
115
|
);
|
|
306
|
-
const [overrides, setOverrides] = (0,
|
|
307
|
-
return /* @__PURE__ */ (0,
|
|
308
|
-
/* @__PURE__ */ (0,
|
|
309
|
-
/* @__PURE__ */ (0,
|
|
116
|
+
const [overrides, setOverrides] = (0, import_react.useState)(value.options.overridesJSON);
|
|
117
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { className: native_settings_styles_default.customized, children: [
|
|
118
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { className: native_settings_styles_default.customizedSummary, children: "\u540C\u6B65\u8BBE\u7F6E" }),
|
|
119
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
310
120
|
"form",
|
|
311
121
|
{
|
|
312
122
|
className: native_settings_styles_default.customizedBody,
|
|
@@ -320,10 +130,10 @@ function apply(ctx) {
|
|
|
320
130
|
});
|
|
321
131
|
},
|
|
322
132
|
children: [
|
|
323
|
-
/* @__PURE__ */ (0,
|
|
324
|
-
/* @__PURE__ */ (0,
|
|
325
|
-
/* @__PURE__ */ (0,
|
|
326
|
-
|
|
133
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: native_settings_styles_default.field, children: [
|
|
134
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: native_settings_styles_default.fieldLabel, htmlFor: `${id}-catalog`, children: "\u80FD\u529B\u76EE\u5F55 URL" }),
|
|
135
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
136
|
+
import_dsh_client_ui_primitives.Input,
|
|
327
137
|
{
|
|
328
138
|
id: `${id}-catalog`,
|
|
329
139
|
className: native_settings_styles_default.input,
|
|
@@ -334,10 +144,10 @@ function apply(ctx) {
|
|
|
334
144
|
}
|
|
335
145
|
)
|
|
336
146
|
] }),
|
|
337
|
-
/* @__PURE__ */ (0,
|
|
338
|
-
/* @__PURE__ */ (0,
|
|
339
|
-
/* @__PURE__ */ (0,
|
|
340
|
-
|
|
147
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: native_settings_styles_default.field, children: [
|
|
148
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: native_settings_styles_default.fieldLabel, htmlFor: `${id}-interval`, children: "\u540C\u6B65\u95F4\u9694\uFF08\u79D2\uFF09" }),
|
|
149
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
150
|
+
import_dsh_client_ui_primitives.Input,
|
|
341
151
|
{
|
|
342
152
|
id: `${id}-interval`,
|
|
343
153
|
className: native_settings_styles_default.input,
|
|
@@ -350,10 +160,10 @@ function apply(ctx) {
|
|
|
350
160
|
}
|
|
351
161
|
)
|
|
352
162
|
] }),
|
|
353
|
-
/* @__PURE__ */ (0,
|
|
354
|
-
/* @__PURE__ */ (0,
|
|
355
|
-
/* @__PURE__ */ (0,
|
|
356
|
-
|
|
163
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: native_settings_styles_default.field, children: [
|
|
164
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: native_settings_styles_default.fieldLabel, htmlFor: `${id}-overrides`, children: "\u6A21\u578B\u80FD\u529B\u8986\u76D6\uFF08JSON\uFF09" }),
|
|
165
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
166
|
+
import_dsh_client_ui_primitives.Input,
|
|
357
167
|
{
|
|
358
168
|
id: `${id}-overrides`,
|
|
359
169
|
className: native_settings_styles_default.input,
|
|
@@ -363,7 +173,7 @@ function apply(ctx) {
|
|
|
363
173
|
}
|
|
364
174
|
)
|
|
365
175
|
] }),
|
|
366
|
-
/* @__PURE__ */ (0,
|
|
176
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: native_settings_styles_default.editorActions, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { type: "submit", variant: "primary", size: "sm", disabled: busy, children: "\u4FDD\u5B58\u540C\u6B65\u8BBE\u7F6E" }) })
|
|
367
177
|
]
|
|
368
178
|
}
|
|
369
179
|
)
|
|
@@ -375,12 +185,12 @@ function apply(ctx) {
|
|
|
375
185
|
}) {
|
|
376
186
|
const { value, error, busy, act } = useProvider(provider.provider);
|
|
377
187
|
const stale = value?.models.filter((model) => model.stale).length ?? 0;
|
|
378
|
-
return /* @__PURE__ */ (0,
|
|
379
|
-
/* @__PURE__ */ (0,
|
|
380
|
-
/* @__PURE__ */ (0,
|
|
381
|
-
/* @__PURE__ */ (0,
|
|
382
|
-
value?.enabled && /* @__PURE__ */ (0,
|
|
383
|
-
|
|
188
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: native_settings_styles_default.customized, "aria-label": "GPT \u6A21\u578B\u9002\u914D", children: [
|
|
189
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: native_settings_styles_default.rowHead, children: [
|
|
190
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: native_settings_styles_default.rowName, children: "GPT \u81EA\u52A8\u9002\u914D" }),
|
|
191
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: native_settings_styles_default.rowActions, children: [
|
|
192
|
+
value?.enabled && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
193
|
+
import_dsh_client_ui_primitives.Button,
|
|
384
194
|
{
|
|
385
195
|
type: "button",
|
|
386
196
|
variant: "ghost",
|
|
@@ -392,8 +202,8 @@ function apply(ctx) {
|
|
|
392
202
|
children: value.status.state === "refreshing" ? "\u6B63\u5728\u540C\u6B65\u2026" : "\u7ACB\u5373\u540C\u6B65"
|
|
393
203
|
}
|
|
394
204
|
),
|
|
395
|
-
/* @__PURE__ */ (0,
|
|
396
|
-
|
|
205
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
206
|
+
import_dsh_client_ui_primitives.Switch,
|
|
397
207
|
{
|
|
398
208
|
label: "GPT \u81EA\u52A8\u9002\u914D",
|
|
399
209
|
checked: value?.enabled ?? false,
|
|
@@ -405,10 +215,10 @@ function apply(ctx) {
|
|
|
405
215
|
)
|
|
406
216
|
] })
|
|
407
217
|
] }),
|
|
408
|
-
value?.enabled && /* @__PURE__ */ (0,
|
|
409
|
-
/* @__PURE__ */ (0,
|
|
410
|
-
stale > 0 && /* @__PURE__ */ (0,
|
|
411
|
-
|
|
218
|
+
value?.enabled && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: native_settings_styles_default.customizedBody, children: [
|
|
219
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: native_settings_styles_default.advancedHint, role: "status", children: value.status.state === "ready" ? `\u5DF2\u540C\u6B65 ${value.models.length} \u4E2A\u6A21\u578B \xB7 GPT \u516D\u6863\u9884\u8BBE\u5DF2\u63A5\u7BA1\u539F\u751F\u7B49\u7EA7\uFF1B\u505C\u7528\u81EA\u52A8\u9002\u914D\u53EF\u6062\u590D` : value.status.state === "error" ? value.status.error : "\u7B49\u5F85\u540C\u6B65" }),
|
|
220
|
+
stale > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: native_settings_styles_default.rowActions, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
221
|
+
import_dsh_client_ui_primitives.Button,
|
|
412
222
|
{
|
|
413
223
|
type: "button",
|
|
414
224
|
variant: "ghost",
|
|
@@ -424,24 +234,8 @@ function apply(ctx) {
|
|
|
424
234
|
]
|
|
425
235
|
}
|
|
426
236
|
) }),
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: native_settings_styles_default.customizedBody, children: Object.entries(value.contextWindows).map(
|
|
430
|
-
([modelId, context]) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
431
|
-
ContextWindowControl,
|
|
432
|
-
{
|
|
433
|
-
provider: provider.provider,
|
|
434
|
-
modelId,
|
|
435
|
-
value: context,
|
|
436
|
-
revision: value.contextRevision,
|
|
437
|
-
busy,
|
|
438
|
-
save: (args) => act("setContextWindow", args)
|
|
439
|
-
},
|
|
440
|
-
modelId
|
|
441
|
-
)
|
|
442
|
-
) })
|
|
443
|
-
] }),
|
|
444
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
237
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: native_settings_styles_default.advancedHint, children: "\u4E0A\u4E0B\u6587\u7A97\u53E3\u8BF7\u5728\u300C\u81EA\u5B9A\u4E49\u8BBE\u7F6E \u2192 \u6A21\u578B\u76EE\u5F55\u300D\u7684\u539F\u751F\u5B57\u6BB5\u4E2D\u4FEE\u6539\uFF0C\u652F\u6301 516K\u30011M \u6216\u81EA\u5B9A\u4E49\u6570\u503C\uFF1B\u6E05\u7A7A\u540E\u4FDD\u5B58\u53EF\u6062\u590D\u81EA\u52A8\u503C\u3002" }),
|
|
238
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
445
239
|
AdvancedSettings,
|
|
446
240
|
{
|
|
447
241
|
provider: provider.provider,
|
|
@@ -452,14 +246,14 @@ function apply(ctx) {
|
|
|
452
246
|
provider.provider
|
|
453
247
|
)
|
|
454
248
|
] }),
|
|
455
|
-
error && /* @__PURE__ */ (0,
|
|
249
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: native_settings_styles_default.error, role: "alert", children: error })
|
|
456
250
|
] });
|
|
457
251
|
}
|
|
458
252
|
function SpeedOptions({
|
|
459
253
|
sessionId
|
|
460
254
|
}) {
|
|
461
255
|
const directory = ctx.get("modelDirectories").directoryFor(sessionId).store;
|
|
462
|
-
const selection = (0,
|
|
256
|
+
const selection = (0, import_react.useSyncExternalStore)(
|
|
463
257
|
(fn) => directory.subscribe(fn),
|
|
464
258
|
() => directory.getSnapshot(),
|
|
465
259
|
() => directory.getSnapshot()
|
|
@@ -467,14 +261,14 @@ function apply(ctx) {
|
|
|
467
261
|
const provider = selection?.provider ?? "";
|
|
468
262
|
const modelId = selection?.model ?? "";
|
|
469
263
|
const { value } = useProvider(provider);
|
|
470
|
-
const [speed, setSpeed] = (0,
|
|
264
|
+
const [speed, setSpeed] = (0, import_react.useState)({
|
|
471
265
|
selected: "default",
|
|
472
266
|
last: null
|
|
473
267
|
});
|
|
474
|
-
const [open, setOpen] = (0,
|
|
475
|
-
const [busy, setBusy] = (0,
|
|
476
|
-
const [error, setError] = (0,
|
|
477
|
-
(0,
|
|
268
|
+
const [open, setOpen] = (0, import_react.useState)(false);
|
|
269
|
+
const [busy, setBusy] = (0, import_react.useState)(false);
|
|
270
|
+
const [error, setError] = (0, import_react.useState)("");
|
|
271
|
+
(0, import_react.useEffect)(() => {
|
|
478
272
|
let active = true;
|
|
479
273
|
const refresh = () => {
|
|
480
274
|
if (provider && modelId)
|
|
@@ -512,9 +306,9 @@ function apply(ctx) {
|
|
|
512
306
|
}
|
|
513
307
|
}
|
|
514
308
|
const label = capability.serviceTiers.find((tier) => tier.id === speed.selected)?.label ?? "Standard";
|
|
515
|
-
return /* @__PURE__ */ (0,
|
|
516
|
-
/* @__PURE__ */ (0,
|
|
517
|
-
|
|
309
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
310
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
311
|
+
import_dsh_client_ui_primitives.Menu,
|
|
518
312
|
{
|
|
519
313
|
open,
|
|
520
314
|
portal: true,
|
|
@@ -530,8 +324,8 @@ function apply(ctx) {
|
|
|
530
324
|
onSelect: (tier) => {
|
|
531
325
|
void select(tier);
|
|
532
326
|
},
|
|
533
|
-
anchor: /* @__PURE__ */ (0,
|
|
534
|
-
|
|
327
|
+
anchor: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
328
|
+
import_dsh_client_ui_primitives.Button,
|
|
535
329
|
{
|
|
536
330
|
type: "button",
|
|
537
331
|
variant: "toolbar",
|
|
@@ -544,13 +338,13 @@ function apply(ctx) {
|
|
|
544
338
|
onClick: () => setOpen(!open),
|
|
545
339
|
children: [
|
|
546
340
|
label,
|
|
547
|
-
/* @__PURE__ */ (0,
|
|
341
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconChevronDownOutlineRegular, { size: 12 })
|
|
548
342
|
]
|
|
549
343
|
}
|
|
550
344
|
)
|
|
551
345
|
}
|
|
552
346
|
),
|
|
553
|
-
error && /* @__PURE__ */ (0,
|
|
347
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: native_settings_styles_default.error, role: "alert", children: error })
|
|
554
348
|
] });
|
|
555
349
|
}
|
|
556
350
|
ctx.slots.inject(
|
package/lib/index.js
CHANGED
|
@@ -809,7 +809,7 @@ var JsonStorage = class {
|
|
|
809
809
|
};
|
|
810
810
|
|
|
811
811
|
// src/host.ts
|
|
812
|
-
import { PiAiAdapter } from "@deepseek-ai/dsh-llm-pi-ai";
|
|
812
|
+
import { Config as NativeConfig, PiAiAdapter } from "@deepseek-ai/dsh-llm-pi-ai";
|
|
813
813
|
import { createRequire } from "node:module";
|
|
814
814
|
import { readFileSync } from "node:fs";
|
|
815
815
|
import { createHash as createHash6 } from "node:crypto";
|
|
@@ -989,58 +989,72 @@ function projectSchema(json, preserveNativeLevels) {
|
|
|
989
989
|
keys.list = offered.map((level) => z.const(level));
|
|
990
990
|
return schema.toJSON();
|
|
991
991
|
}
|
|
992
|
-
function nativeWrite(next, current, resolve4, contextEdits) {
|
|
992
|
+
function nativeWrite(next, current, base, resolve4, contextEdits, contextWrites) {
|
|
993
993
|
if (!next.providers) return next;
|
|
994
994
|
return {
|
|
995
995
|
...next,
|
|
996
996
|
providers: Object.fromEntries(
|
|
997
997
|
Object.entries(next.providers).map(([provider, raw]) => {
|
|
998
998
|
const profile = raw;
|
|
999
|
-
|
|
1000
|
-
const
|
|
999
|
+
const inherited = base?.providers?.[provider] ?? {};
|
|
1000
|
+
const ownershipProfile = {
|
|
1001
|
+
...inherited,
|
|
1002
|
+
...current.providers?.[provider]
|
|
1003
|
+
};
|
|
1004
|
+
const effectiveProfile = { ...inherited, ...profile };
|
|
1005
|
+
const ownsModels = Array.isArray(profile?.models);
|
|
1006
|
+
const models = ownsModels ? profile.models : inherited.models?.map(
|
|
1007
|
+
(model) => projectModel(provider, model, resolve4, ownershipProfile)
|
|
1008
|
+
);
|
|
1009
|
+
if (!Array.isArray(models)) return [provider, profile];
|
|
1010
|
+
const previous = ownershipProfile.models ?? [];
|
|
1011
|
+
const savedModels = models.map((model) => {
|
|
1012
|
+
const original = previous.find((row) => row.id === model.id);
|
|
1013
|
+
const capability = resolve4(provider, model, ownershipProfile);
|
|
1014
|
+
if (!capability) return model;
|
|
1015
|
+
const managed = projectModel(
|
|
1016
|
+
provider,
|
|
1017
|
+
model,
|
|
1018
|
+
resolve4,
|
|
1019
|
+
ownershipProfile
|
|
1020
|
+
);
|
|
1021
|
+
if (original && JSON.stringify(model.reasoningEfforts) !== JSON.stringify(managed.reasoningEfforts))
|
|
1022
|
+
throw new Error(
|
|
1023
|
+
"GPT \u601D\u8003\u7B49\u7EA7\u7531\u63D2\u4EF6\u9884\u8BBE\u7BA1\u7406\uFF1B\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5\uFF0C\u6216\u5728\u6A21\u578B\u80FD\u529B\u8986\u76D6\u4E2D\u4FEE\u6539\uFF0C\u505C\u7528\u81EA\u52A8\u9002\u914D\u53EF\u6062\u590D\u539F\u751F\u7F16\u8F91\u3002"
|
|
1024
|
+
);
|
|
1025
|
+
const restored = { ...model };
|
|
1026
|
+
const projectedContext = original ? projectModel(provider, original, resolve4, ownershipProfile).contextWindow : void 0;
|
|
1027
|
+
const editedContext = ownsModels && (original ? model.contextWindow !== projectedContext : Object.hasOwn(model, "contextWindow"));
|
|
1028
|
+
const budgetChanged = editedContext || !original || model.maxTokens !== original.maxTokens || model.maxTokens === void 0 && effectiveProfile.defaultMaxTokens !== ownershipProfile.defaultMaxTokens || model.contextWindow === void 0 && effectiveProfile.defaultContextWindow !== ownershipProfile.defaultContextWindow;
|
|
1029
|
+
if (!editedContext) {
|
|
1030
|
+
if (original && Object.hasOwn(original, "contextWindow"))
|
|
1031
|
+
restored.contextWindow = original.contextWindow;
|
|
1032
|
+
else delete restored.contextWindow;
|
|
1033
|
+
} else {
|
|
1034
|
+
if (model.contextWindow !== void 0 && !validContextWindow(model.contextWindow))
|
|
1035
|
+
throw new Error("\u4E0A\u4E0B\u6587\u7A97\u53E3\u5FC5\u987B\u662F\u6B63\u7684\u5B89\u5168\u6574\u6570");
|
|
1036
|
+
contextEdits.push({
|
|
1037
|
+
provider,
|
|
1038
|
+
modelId: model.id,
|
|
1039
|
+
previousTokens: original?.contextWindow
|
|
1040
|
+
});
|
|
1041
|
+
}
|
|
1042
|
+
if (budgetChanged)
|
|
1043
|
+
contextWrites?.validate?.(
|
|
1044
|
+
provider,
|
|
1045
|
+
editedContext ? model : { ...model, contextWindow: capability.contextWindow },
|
|
1046
|
+
profile
|
|
1047
|
+
);
|
|
1048
|
+
if (original && Object.hasOwn(original, "reasoningEfforts"))
|
|
1049
|
+
restored.reasoningEfforts = structuredClone(
|
|
1050
|
+
original.reasoningEfforts
|
|
1051
|
+
);
|
|
1052
|
+
else delete restored.reasoningEfforts;
|
|
1053
|
+
return restored;
|
|
1054
|
+
});
|
|
1001
1055
|
return [
|
|
1002
1056
|
provider,
|
|
1003
|
-
{
|
|
1004
|
-
...profile,
|
|
1005
|
-
models: profile.models.map((model) => {
|
|
1006
|
-
const original = previous.find((row) => row.id === model.id);
|
|
1007
|
-
const ownershipProfile = current.providers?.[provider] ?? profile;
|
|
1008
|
-
const capability = resolve4(provider, model, ownershipProfile);
|
|
1009
|
-
if (!capability) return model;
|
|
1010
|
-
const managed = projectModel(
|
|
1011
|
-
provider,
|
|
1012
|
-
model,
|
|
1013
|
-
resolve4,
|
|
1014
|
-
ownershipProfile
|
|
1015
|
-
);
|
|
1016
|
-
if (original && JSON.stringify(model.reasoningEfforts) !== JSON.stringify(managed.reasoningEfforts))
|
|
1017
|
-
throw new Error(
|
|
1018
|
-
"GPT \u601D\u8003\u7B49\u7EA7\u7531\u63D2\u4EF6\u9884\u8BBE\u7BA1\u7406\uFF1B\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5\uFF0C\u6216\u5728\u6A21\u578B\u80FD\u529B\u8986\u76D6\u4E2D\u4FEE\u6539\uFF0C\u505C\u7528\u81EA\u52A8\u9002\u914D\u53EF\u6062\u590D\u539F\u751F\u7F16\u8F91\u3002"
|
|
1019
|
-
);
|
|
1020
|
-
const restored = { ...model };
|
|
1021
|
-
const projectedContext = original ? projectModel(provider, original, resolve4, ownershipProfile).contextWindow : void 0;
|
|
1022
|
-
const editedContext = original ? model.contextWindow !== projectedContext : Object.hasOwn(model, "contextWindow");
|
|
1023
|
-
if (!editedContext) {
|
|
1024
|
-
if (original && Object.hasOwn(original, "contextWindow"))
|
|
1025
|
-
restored.contextWindow = original.contextWindow;
|
|
1026
|
-
else delete restored.contextWindow;
|
|
1027
|
-
} else {
|
|
1028
|
-
if (model.contextWindow !== void 0 && !validContextWindow(model.contextWindow))
|
|
1029
|
-
throw new Error("\u4E0A\u4E0B\u6587\u7A97\u53E3\u5FC5\u987B\u662F\u6B63\u7684\u5B89\u5168\u6574\u6570");
|
|
1030
|
-
contextEdits.push({
|
|
1031
|
-
provider,
|
|
1032
|
-
modelId: model.id,
|
|
1033
|
-
previousTokens: original?.contextWindow
|
|
1034
|
-
});
|
|
1035
|
-
}
|
|
1036
|
-
if (original && Object.hasOwn(original, "reasoningEfforts"))
|
|
1037
|
-
restored.reasoningEfforts = structuredClone(
|
|
1038
|
-
original.reasoningEfforts
|
|
1039
|
-
);
|
|
1040
|
-
else delete restored.reasoningEfforts;
|
|
1041
|
-
return restored;
|
|
1042
|
-
})
|
|
1043
|
-
}
|
|
1057
|
+
ownsModels ? { ...profile, models: savedModels } : profile
|
|
1044
1058
|
];
|
|
1045
1059
|
})
|
|
1046
1060
|
)
|
|
@@ -1050,6 +1064,15 @@ function installSettingsOverlay(settings, resolve4, contextWrites) {
|
|
|
1050
1064
|
settings = settings[symbols.original] ?? settings;
|
|
1051
1065
|
const originalDescribe = settings.describe;
|
|
1052
1066
|
const originalWrite = settings.write;
|
|
1067
|
+
const editableResolve = (provider, model, profile) => {
|
|
1068
|
+
const capability = resolve4(provider, model, profile);
|
|
1069
|
+
if (!capability) return void 0;
|
|
1070
|
+
const manual = contextWrites?.editableContext ? contextWrites.editableContext(provider, model) : model.contextWindow;
|
|
1071
|
+
const projected = { ...capability };
|
|
1072
|
+
if (manual === void 0) delete projected.contextWindow;
|
|
1073
|
+
else projected.contextWindow = manual;
|
|
1074
|
+
return projected;
|
|
1075
|
+
};
|
|
1053
1076
|
let viewRevision;
|
|
1054
1077
|
function describe(options) {
|
|
1055
1078
|
return originalDescribe.call(this, options).map((row) => {
|
|
@@ -1091,8 +1114,8 @@ function installSettingsOverlay(settings, resolve4, contextWrites) {
|
|
|
1091
1114
|
...managed ? {
|
|
1092
1115
|
schema: projectSchema(row.schema, other),
|
|
1093
1116
|
value,
|
|
1094
|
-
base: projectConfiguration(row.base,
|
|
1095
|
-
user: projectConfiguration(row.user,
|
|
1117
|
+
base: projectConfiguration(row.base, editableResolve),
|
|
1118
|
+
user: projectConfiguration(row.user, editableResolve)
|
|
1096
1119
|
} : {},
|
|
1097
1120
|
...typeof row.revision === "number" ? { revision: viewRevision.revision } : {}
|
|
1098
1121
|
};
|
|
@@ -1106,13 +1129,15 @@ function installSettingsOverlay(settings, resolve4, contextWrites) {
|
|
|
1106
1129
|
ns,
|
|
1107
1130
|
ns !== "llm-pi-ai" ? change : (current, base, schema) => nativeWrite(
|
|
1108
1131
|
change(
|
|
1109
|
-
projectConfiguration(current,
|
|
1110
|
-
projectConfiguration(base,
|
|
1132
|
+
projectConfiguration(structuredClone(current), editableResolve),
|
|
1133
|
+
projectConfiguration(structuredClone(base), editableResolve),
|
|
1111
1134
|
schema
|
|
1112
1135
|
),
|
|
1113
1136
|
current,
|
|
1114
|
-
|
|
1115
|
-
|
|
1137
|
+
base,
|
|
1138
|
+
editableResolve,
|
|
1139
|
+
edits,
|
|
1140
|
+
contextWrites
|
|
1116
1141
|
),
|
|
1117
1142
|
expected,
|
|
1118
1143
|
paths
|
|
@@ -1179,6 +1204,7 @@ function installSettingsOverlay(settings, resolve4, contextWrites) {
|
|
|
1179
1204
|
edits.push({ provider, modelId, previousTokens: model.contextWindow });
|
|
1180
1205
|
if (tokens === void 0) delete model.contextWindow;
|
|
1181
1206
|
else model.contextWindow = tokens;
|
|
1207
|
+
contextWrites?.validate?.(provider, model, next.providers[provider]);
|
|
1182
1208
|
return next;
|
|
1183
1209
|
},
|
|
1184
1210
|
expected,
|
|
@@ -2646,13 +2672,7 @@ var GptModels = class extends (_a = Service, _codexStatus_dec = [Remote], _refre
|
|
|
2646
2672
|
op: "set",
|
|
2647
2673
|
path: ["providers", provider, "models"],
|
|
2648
2674
|
value: [...existing, ...added].map(
|
|
2649
|
-
(model) =>
|
|
2650
|
-
provider,
|
|
2651
|
-
model,
|
|
2652
|
-
(route, row) => this.capability(route, row.id, row.name),
|
|
2653
|
-
void 0,
|
|
2654
|
-
ids.has(model.id)
|
|
2655
|
-
)
|
|
2675
|
+
(model) => this.editableModel(provider, model, ids.has(model.id))
|
|
2656
2676
|
)
|
|
2657
2677
|
}
|
|
2658
2678
|
],
|
|
@@ -2786,12 +2806,7 @@ var GptModels = class extends (_a = Service, _codexStatus_dec = [Remote], _refre
|
|
|
2786
2806
|
op: "set",
|
|
2787
2807
|
path: ["providers", provider, "models"],
|
|
2788
2808
|
value: nextModels.map(
|
|
2789
|
-
(model) =>
|
|
2790
|
-
provider,
|
|
2791
|
-
model,
|
|
2792
|
-
(route, row) => this.capability(route, row.id, row.name),
|
|
2793
|
-
void 0
|
|
2794
|
-
)
|
|
2809
|
+
(model) => this.editableModel(provider, model)
|
|
2795
2810
|
)
|
|
2796
2811
|
}
|
|
2797
2812
|
],
|
|
@@ -2799,16 +2814,35 @@ var GptModels = class extends (_a = Service, _codexStatus_dec = [Remote], _refre
|
|
|
2799
2814
|
);
|
|
2800
2815
|
await runner.removeStale(staleIds);
|
|
2801
2816
|
}
|
|
2817
|
+
/** Internal model-list writes must use the same manual fields as native drafts. */
|
|
2818
|
+
editableModel(provider, model, existing = true) {
|
|
2819
|
+
const capability = this.capability(provider, model.id, model.name);
|
|
2820
|
+
if (!capability) return model;
|
|
2821
|
+
const tokens = existing ? this.editableContextWindow(provider, model) : model.contextWindow;
|
|
2822
|
+
return projectModel(
|
|
2823
|
+
provider,
|
|
2824
|
+
tokens === void 0 ? model : { ...model, contextWindow: tokens },
|
|
2825
|
+
() => capability,
|
|
2826
|
+
void 0,
|
|
2827
|
+
false
|
|
2828
|
+
);
|
|
2829
|
+
}
|
|
2830
|
+
editableContextWindow(provider, model) {
|
|
2831
|
+
const context = this.contextWindow(provider, model.id);
|
|
2832
|
+
return context.source === "legacy-override" ? context.effectiveTokens : model.contextWindow;
|
|
2833
|
+
}
|
|
2802
2834
|
/** Resolve raw metadata separately from merged capabilities and cached overrides. */
|
|
2803
|
-
contextWindow(provider, modelId, nativeDefault) {
|
|
2804
|
-
const { descriptor, profile } = this.profile(provider);
|
|
2835
|
+
contextWindow(provider, modelId, nativeDefault, profileOverride) {
|
|
2836
|
+
const { descriptor, profile: storedProfile } = this.profile(provider);
|
|
2837
|
+
const inherited = descriptor.base?.providers?.[provider];
|
|
2838
|
+
const profile = profileOverride ? { ...inherited, ...profileOverride } : storedProfile;
|
|
2805
2839
|
const overrides = JSON.parse(
|
|
2806
2840
|
this.routeOptions(provider, profile)?.overridesJSON ?? "{}"
|
|
2807
2841
|
);
|
|
2808
2842
|
const row = profile.models?.length ? profile.models.find((model) => model.id === modelId) : profile.modelOverrides?.[modelId];
|
|
2809
2843
|
const snapshot = this.snapshots.get(provider);
|
|
2810
2844
|
const raw = snapshot?.models.find((model) => model.id === modelId);
|
|
2811
|
-
const userProfile = descriptor.user?.providers?.[provider];
|
|
2845
|
+
const userProfile = profileOverride ?? descriptor.user?.providers?.[provider];
|
|
2812
2846
|
const providerDefault = userProfile?.defaultContextWindow ?? (profile.defaultContextWindow !== 1e6 || descriptor.base === void 0 && descriptor.user === void 0 ? profile.defaultContextWindow : void 0);
|
|
2813
2847
|
const catalogModel = getBuiltinModels(provider).find(
|
|
2814
2848
|
(model) => model.id === modelId
|
|
@@ -2823,6 +2857,28 @@ var GptModels = class extends (_a = Service, _codexStatus_dec = [Remote], _refre
|
|
|
2823
2857
|
nativeDefault: nativeDefault ?? catalogModel?.contextWindow ?? profile.defaultContextWindow
|
|
2824
2858
|
});
|
|
2825
2859
|
}
|
|
2860
|
+
/** Both native form saves and the compatibility RPC validate the same budget. */
|
|
2861
|
+
validateContextWindow(provider, model, profile) {
|
|
2862
|
+
const effective = model.contextWindow ?? this.contextWindow(provider, model.id, void 0, profile).defaultTokens;
|
|
2863
|
+
const compaction = this.nativeDescribe().find(
|
|
2864
|
+
(entry) => entry.ns === "compaction-basic"
|
|
2865
|
+
)?.value;
|
|
2866
|
+
const policy = compaction?.modelPolicies?.find(
|
|
2867
|
+
(entry) => entry.provider === provider && entry.model === model.id
|
|
2868
|
+
);
|
|
2869
|
+
const headroom = policy?.headroomTokens ?? compaction?.headroomTokens ?? 0;
|
|
2870
|
+
const inherited = this.nativeDescribe().find((entry) => entry.ns === "llm-pi-ai")?.base?.providers?.[provider];
|
|
2871
|
+
const defaults = NativeConfig({
|
|
2872
|
+
providers: {
|
|
2873
|
+
[provider]: {
|
|
2874
|
+
defaultMaxTokens: profile.defaultMaxTokens ?? inherited?.defaultMaxTokens
|
|
2875
|
+
}
|
|
2876
|
+
}
|
|
2877
|
+
}).providers.get()[provider];
|
|
2878
|
+
const output = model.maxTokens ?? getBuiltinModels(provider).find((entry) => entry.id === model.id)?.maxTokens ?? defaults.defaultMaxTokens;
|
|
2879
|
+
if (effective <= output + headroom)
|
|
2880
|
+
throw new Error("\u4E0A\u4E0B\u6587\u7A97\u53E3\u5FC5\u987B\u5927\u4E8E\u5F53\u524D\u6700\u5927\u8F93\u51FA\u548C\u538B\u7F29\u9884\u7559\u7684\u603B\u548C");
|
|
2881
|
+
}
|
|
2826
2882
|
contextWriteRevision() {
|
|
2827
2883
|
return this.nativeDescribe().find((row) => row.ns === this.settingsNs)?.revision;
|
|
2828
2884
|
}
|
|
@@ -2863,18 +2919,6 @@ var GptModels = class extends (_a = Service, _codexStatus_dec = [Remote], _refre
|
|
|
2863
2919
|
throw new Error("\u8BF7\u5148\u542F\u7528\u8BE5 GPT \u6A21\u578B\u7684\u81EA\u52A8\u9002\u914D");
|
|
2864
2920
|
const index = profile.models?.findIndex((model) => model.id === modelId) ?? -1;
|
|
2865
2921
|
if (index < 0) throw new Error("\u6A21\u578B\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5");
|
|
2866
|
-
const effective = tokens ?? this.contextWindow(provider, modelId).defaultTokens;
|
|
2867
|
-
const row = profile.models[index];
|
|
2868
|
-
const compaction = this.nativeDescribe().find(
|
|
2869
|
-
(entry) => entry.ns === "compaction-basic"
|
|
2870
|
-
)?.value;
|
|
2871
|
-
const policy = compaction?.modelPolicies?.find(
|
|
2872
|
-
(entry) => entry.provider === provider && entry.model === modelId
|
|
2873
|
-
);
|
|
2874
|
-
const headroom = policy?.headroomTokens ?? compaction?.headroomTokens ?? 0;
|
|
2875
|
-
const output = validContextWindow(row.maxTokens) ? row.maxTokens : 0;
|
|
2876
|
-
if (effective <= output + headroom)
|
|
2877
|
-
throw new Error("\u4E0A\u4E0B\u6587\u7A97\u53E3\u5FC5\u987B\u5927\u4E8E\u5F53\u524D\u6700\u5927\u8F93\u51FA\u548C\u538B\u7F29\u9884\u7559\u7684\u603B\u548C");
|
|
2878
2922
|
if (!this.contextWriter) throw new Error("\u4E0A\u4E0B\u6587\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528");
|
|
2879
2923
|
await this.contextWriter(
|
|
2880
2924
|
provider,
|
|
@@ -3041,6 +3085,8 @@ async function apply2(ctx, config) {
|
|
|
3041
3085
|
ctx.settings,
|
|
3042
3086
|
(provider, model, profile) => typeof model.id === "string" ? service.capability(provider, model.id, model.name, profile) : void 0,
|
|
3043
3087
|
{
|
|
3088
|
+
editableContext: (provider, model) => service.editableContextWindow(provider, model),
|
|
3089
|
+
validate: (provider, model, profile) => service.validateContextWindow(provider, model, profile),
|
|
3044
3090
|
revision: () => service.contextWriteRevision(),
|
|
3045
3091
|
saved: (edits, revision) => service.clearLegacyContext(edits, revision)
|
|
3046
3092
|
}
|
package/package.json
CHANGED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { type ContextWindowResolution } from '../context-window.js';
|
|
2
|
-
export declare function ContextWindowControl({ provider, modelId, value, revision, busy, save, }: {
|
|
3
|
-
provider: string;
|
|
4
|
-
modelId: string;
|
|
5
|
-
value: ContextWindowResolution;
|
|
6
|
-
revision: number;
|
|
7
|
-
busy: boolean;
|
|
8
|
-
save(args: Record<string, unknown>): Promise<boolean | undefined>;
|
|
9
|
-
}): import("react/jsx-runtime").JSX.Element;
|