dsh-gpt-adapter 0.2.2 → 0.2.4

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/lib/client.js CHANGED
@@ -25,14 +25,204 @@ __export(index_exports, {
25
25
  inject: () => inject
26
26
  });
27
27
  module.exports = __toCommonJS(index_exports);
28
- var import_react = require("react");
29
- var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
28
+ var import_react2 = require("react");
29
+ var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
30
30
 
31
31
  // gpt-native:native-settings-styles
32
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
33
 
34
- // src/client/index.tsx
34
+ // src/client/context-window.tsx
35
+ var import_react = require("react");
36
+ var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
37
+
38
+ // src/context-window.ts
39
+ var officialModels = [
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
35
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
+ }
223
+
224
+ // src/client/index.tsx
225
+ var import_jsx_runtime2 = require("react/jsx-runtime");
36
226
  var inject = ["slots", "connection", "sessions", "modelDirectories"];
37
227
  function apply(ctx) {
38
228
  async function call(method, args) {
@@ -45,20 +235,24 @@ function apply(ctx) {
45
235
  return result.value;
46
236
  }
47
237
  function useProvider(provider) {
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
- (0, import_react.useEffect)(() => {
238
+ const [value, setValue] = (0, import_react2.useState)();
239
+ const [error, setError] = (0, import_react2.useState)("");
240
+ const [busy, setBusy] = (0, import_react2.useState)(false);
241
+ const requests = (0, import_react2.useRef)({ sequence: 0, writing: false });
242
+ (0, import_react2.useEffect)(() => {
52
243
  let active = true;
244
+ requests.current.writing = false;
245
+ setBusy(false);
53
246
  const refresh = () => {
54
- if (!provider) return;
247
+ if (!provider || requests.current.writing) return;
248
+ const sequence = ++requests.current.sequence;
55
249
  void call("status", { provider }).then((value2) => {
56
- if (active) {
250
+ if (active && sequence === requests.current.sequence) {
57
251
  setValue(value2);
58
252
  setError("");
59
253
  }
60
254
  }).catch((error2) => {
61
- if (active)
255
+ if (active && sequence === requests.current.sequence)
62
256
  setError(
63
257
  error2 instanceof Error ? error2.message : "\u65E0\u6CD5\u8BFB\u53D6 GPT \u8BBE\u7F6E"
64
258
  );
@@ -68,22 +262,32 @@ function apply(ctx) {
68
262
  const timer = setInterval(refresh, 3e3);
69
263
  return () => {
70
264
  active = false;
265
+ requests.current.sequence++;
71
266
  clearInterval(timer);
72
267
  };
73
268
  }, [provider]);
74
269
  async function act(method, args) {
75
- if (busy) return;
270
+ if (requests.current.writing) return;
271
+ requests.current.writing = true;
272
+ const sequence = ++requests.current.sequence;
76
273
  setBusy(true);
77
274
  try {
78
275
  await call(method, args);
79
- setValue(await call("status", { provider }));
276
+ if (sequence !== requests.current.sequence) return false;
277
+ const next = await call("status", { provider });
278
+ if (sequence !== requests.current.sequence) return false;
279
+ setValue(next);
80
280
  setError("");
81
281
  return true;
82
282
  } catch (error2) {
83
- setError(error2 instanceof Error ? error2.message : "\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5");
283
+ if (sequence === requests.current.sequence)
284
+ setError(error2 instanceof Error ? error2.message : "\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5");
84
285
  return false;
85
286
  } finally {
86
- setBusy(false);
287
+ if (sequence === requests.current.sequence) {
288
+ requests.current.writing = false;
289
+ setBusy(false);
290
+ }
87
291
  }
88
292
  }
89
293
  return { value, error, busy, act };
@@ -94,15 +298,15 @@ function apply(ctx) {
94
298
  busy,
95
299
  act
96
300
  }) {
97
- const id = (0, import_react.useId)();
98
- const [url, setUrl] = (0, import_react.useState)(value.options.capabilityCatalogUrl ?? "");
99
- const [seconds, setSeconds] = (0, import_react.useState)(
301
+ const id = (0, import_react2.useId)();
302
+ const [url, setUrl] = (0, import_react2.useState)(value.options.capabilityCatalogUrl ?? "");
303
+ const [seconds, setSeconds] = (0, import_react2.useState)(
100
304
  String(value.options.refreshIntervalMs / 1e3)
101
305
  );
102
- const [overrides, setOverrides] = (0, import_react.useState)(value.options.overridesJSON);
103
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { className: native_settings_styles_default.customized, children: [
104
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { className: native_settings_styles_default.customizedSummary, children: "\u540C\u6B65\u8BBE\u7F6E" }),
105
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
306
+ const [overrides, setOverrides] = (0, import_react2.useState)(value.options.overridesJSON);
307
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("details", { className: native_settings_styles_default.customized, children: [
308
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("summary", { className: native_settings_styles_default.customizedSummary, children: "\u540C\u6B65\u8BBE\u7F6E" }),
309
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
106
310
  "form",
107
311
  {
108
312
  className: native_settings_styles_default.customizedBody,
@@ -116,10 +320,10 @@ function apply(ctx) {
116
320
  });
117
321
  },
118
322
  children: [
119
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: native_settings_styles_default.field, children: [
120
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: native_settings_styles_default.fieldLabel, htmlFor: `${id}-catalog`, children: "\u80FD\u529B\u76EE\u5F55 URL" }),
121
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
122
- import_dsh_client_ui_primitives.Input,
323
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: native_settings_styles_default.field, children: [
324
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: native_settings_styles_default.fieldLabel, htmlFor: `${id}-catalog`, children: "\u80FD\u529B\u76EE\u5F55 URL" }),
325
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
326
+ import_dsh_client_ui_primitives2.Input,
123
327
  {
124
328
  id: `${id}-catalog`,
125
329
  className: native_settings_styles_default.input,
@@ -130,10 +334,10 @@ function apply(ctx) {
130
334
  }
131
335
  )
132
336
  ] }),
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}-interval`, children: "\u540C\u6B65\u95F4\u9694\uFF08\u79D2\uFF09" }),
135
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
136
- import_dsh_client_ui_primitives.Input,
337
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: native_settings_styles_default.field, children: [
338
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: native_settings_styles_default.fieldLabel, htmlFor: `${id}-interval`, children: "\u540C\u6B65\u95F4\u9694\uFF08\u79D2\uFF09" }),
339
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
340
+ import_dsh_client_ui_primitives2.Input,
137
341
  {
138
342
  id: `${id}-interval`,
139
343
  className: native_settings_styles_default.input,
@@ -146,10 +350,10 @@ function apply(ctx) {
146
350
  }
147
351
  )
148
352
  ] }),
149
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: native_settings_styles_default.field, children: [
150
- /* @__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" }),
151
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
152
- import_dsh_client_ui_primitives.Input,
353
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: native_settings_styles_default.field, children: [
354
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: native_settings_styles_default.fieldLabel, htmlFor: `${id}-overrides`, children: "\u6A21\u578B\u80FD\u529B\u8986\u76D6\uFF08JSON\uFF09" }),
355
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
356
+ import_dsh_client_ui_primitives2.Input,
153
357
  {
154
358
  id: `${id}-overrides`,
155
359
  className: native_settings_styles_default.input,
@@ -159,7 +363,7 @@ function apply(ctx) {
159
363
  }
160
364
  )
161
365
  ] }),
162
- /* @__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" }) })
366
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: native_settings_styles_default.editorActions, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Button, { type: "submit", variant: "primary", size: "sm", disabled: busy, children: "\u4FDD\u5B58\u540C\u6B65\u8BBE\u7F6E" }) })
163
367
  ]
164
368
  }
165
369
  )
@@ -171,12 +375,12 @@ function apply(ctx) {
171
375
  }) {
172
376
  const { value, error, busy, act } = useProvider(provider.provider);
173
377
  const stale = value?.models.filter((model) => model.stale).length ?? 0;
174
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: native_settings_styles_default.customized, "aria-label": "GPT \u6A21\u578B\u9002\u914D", children: [
175
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: native_settings_styles_default.rowHead, children: [
176
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: native_settings_styles_default.rowName, children: "GPT \u81EA\u52A8\u9002\u914D" }),
177
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: native_settings_styles_default.rowActions, children: [
178
- value?.enabled && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
179
- import_dsh_client_ui_primitives.Button,
378
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: native_settings_styles_default.customized, "aria-label": "GPT \u6A21\u578B\u9002\u914D", children: [
379
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: native_settings_styles_default.rowHead, children: [
380
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: native_settings_styles_default.rowName, children: "GPT \u81EA\u52A8\u9002\u914D" }),
381
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: native_settings_styles_default.rowActions, children: [
382
+ value?.enabled && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
383
+ import_dsh_client_ui_primitives2.Button,
180
384
  {
181
385
  type: "button",
182
386
  variant: "ghost",
@@ -188,8 +392,8 @@ function apply(ctx) {
188
392
  children: value.status.state === "refreshing" ? "\u6B63\u5728\u540C\u6B65\u2026" : "\u7ACB\u5373\u540C\u6B65"
189
393
  }
190
394
  ),
191
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
192
- import_dsh_client_ui_primitives.Switch,
395
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
396
+ import_dsh_client_ui_primitives2.Switch,
193
397
  {
194
398
  label: "GPT \u81EA\u52A8\u9002\u914D",
195
399
  checked: value?.enabled ?? false,
@@ -201,10 +405,10 @@ function apply(ctx) {
201
405
  )
202
406
  ] })
203
407
  ] }),
204
- value?.enabled && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: native_settings_styles_default.customizedBody, children: [
205
- /* @__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" }),
206
- stale > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: native_settings_styles_default.rowActions, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
207
- import_dsh_client_ui_primitives.Button,
408
+ value?.enabled && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: native_settings_styles_default.customizedBody, children: [
409
+ /* @__PURE__ */ (0, import_jsx_runtime2.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" }),
410
+ stale > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: native_settings_styles_default.rowActions, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
411
+ import_dsh_client_ui_primitives2.Button,
208
412
  {
209
413
  type: "button",
210
414
  variant: "ghost",
@@ -220,7 +424,24 @@ function apply(ctx) {
220
424
  ]
221
425
  }
222
426
  ) }),
223
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
427
+ Object.keys(value.contextWindows ?? {}).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("details", { className: native_settings_styles_default.customized, children: [
428
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("summary", { className: native_settings_styles_default.customizedSummary, children: "\u4E0A\u4E0B\u6587\u7A97\u53E3" }),
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)(
224
445
  AdvancedSettings,
225
446
  {
226
447
  provider: provider.provider,
@@ -231,14 +452,14 @@ function apply(ctx) {
231
452
  provider.provider
232
453
  )
233
454
  ] }),
234
- error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: native_settings_styles_default.error, role: "alert", children: error })
455
+ error && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: native_settings_styles_default.error, role: "alert", children: error })
235
456
  ] });
236
457
  }
237
458
  function SpeedOptions({
238
459
  sessionId
239
460
  }) {
240
461
  const directory = ctx.get("modelDirectories").directoryFor(sessionId).store;
241
- const selection = (0, import_react.useSyncExternalStore)(
462
+ const selection = (0, import_react2.useSyncExternalStore)(
242
463
  (fn) => directory.subscribe(fn),
243
464
  () => directory.getSnapshot(),
244
465
  () => directory.getSnapshot()
@@ -246,14 +467,14 @@ function apply(ctx) {
246
467
  const provider = selection?.provider ?? "";
247
468
  const modelId = selection?.model ?? "";
248
469
  const { value } = useProvider(provider);
249
- const [speed, setSpeed] = (0, import_react.useState)({
470
+ const [speed, setSpeed] = (0, import_react2.useState)({
250
471
  selected: "default",
251
472
  last: null
252
473
  });
253
- const [open, setOpen] = (0, import_react.useState)(false);
254
- const [busy, setBusy] = (0, import_react.useState)(false);
255
- const [error, setError] = (0, import_react.useState)("");
256
- (0, import_react.useEffect)(() => {
474
+ const [open, setOpen] = (0, import_react2.useState)(false);
475
+ const [busy, setBusy] = (0, import_react2.useState)(false);
476
+ const [error, setError] = (0, import_react2.useState)("");
477
+ (0, import_react2.useEffect)(() => {
257
478
  let active = true;
258
479
  const refresh = () => {
259
480
  if (provider && modelId)
@@ -291,9 +512,9 @@ function apply(ctx) {
291
512
  }
292
513
  }
293
514
  const label = capability.serviceTiers.find((tier) => tier.id === speed.selected)?.label ?? "Standard";
294
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
295
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
296
- import_dsh_client_ui_primitives.Menu,
515
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
516
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
517
+ import_dsh_client_ui_primitives2.Menu,
297
518
  {
298
519
  open,
299
520
  portal: true,
@@ -309,8 +530,8 @@ function apply(ctx) {
309
530
  onSelect: (tier) => {
310
531
  void select(tier);
311
532
  },
312
- anchor: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
313
- import_dsh_client_ui_primitives.Button,
533
+ anchor: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
534
+ import_dsh_client_ui_primitives2.Button,
314
535
  {
315
536
  type: "button",
316
537
  variant: "toolbar",
@@ -323,13 +544,13 @@ function apply(ctx) {
323
544
  onClick: () => setOpen(!open),
324
545
  children: [
325
546
  label,
326
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconChevronDownOutlineRegular, { size: 12 })
547
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.IconChevronDownOutlineRegular, { size: 12 })
327
548
  ]
328
549
  }
329
550
  )
330
551
  }
331
552
  ),
332
- error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: native_settings_styles_default.error, role: "alert", children: error })
553
+ error && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: native_settings_styles_default.error, role: "alert", children: error })
333
554
  ] });
334
555
  }
335
556
  ctx.slots.inject(
package/lib/core.js CHANGED
@@ -121,6 +121,33 @@ function capabilityForSelection(capabilities, reasoningId, serviceTier2) {
121
121
  };
122
122
  }
123
123
 
124
+ // src/context-window.ts
125
+ var officialModels = [
126
+ ["gpt-6-astra", 105e4],
127
+ ["gpt-6.1-sol", 105e4],
128
+ ["gpt-6.1-terra", 105e4],
129
+ ["gpt-6-luna", 105e4],
130
+ ["gpt-5.4", 105e4],
131
+ ["gpt-4.1", 1047576],
132
+ ["gpt-4o", 128e3],
133
+ ["gpt-5.4-2026-03-05", 105e4, "gpt-5.4"],
134
+ ["gpt-4.1-2025-04-14", 1047576, "gpt-4.1"],
135
+ ["gpt-4o-2024-08-06", 128e3, "gpt-4o"]
136
+ ];
137
+ var OFFICIAL_CONTEXT_WINDOWS = Object.fromEntries(
138
+ officialModels.map(([id, tokens, page]) => [
139
+ id,
140
+ {
141
+ tokens,
142
+ url: `https://developers.openai.com/api/docs/models/${page ?? id}`,
143
+ verifiedAt: "2026-11-13"
144
+ }
145
+ ])
146
+ );
147
+ function validContextWindow(value) {
148
+ return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
149
+ }
150
+
124
151
  // src/sync.ts
125
152
  import { createHash } from "node:crypto";
126
153
  var MAX_RESPONSE_BYTES = 4 * 1024 * 1024;
@@ -298,7 +325,7 @@ function parseCapabilityHints(row, modelId) {
298
325
  ...typeof defaultReasoningValue === "string" ? { defaultReasoningId: defaultReasoningValue } : {},
299
326
  ...hasTierSignal ? { serviceTiers: tiers } : {},
300
327
  ...defaultTier ? { defaultServiceTier: defaultTier } : {},
301
- ...typeof contextWindow === "number" && contextWindow > 0 ? { contextWindow } : {},
328
+ ...validContextWindow(contextWindow) ? { contextWindow } : {},
302
329
  ...typeof maxOutputTokens === "number" && maxOutputTokens > 0 ? { maxOutputTokens } : {}
303
330
  };
304
331
  return Object.keys(hints).length === 0 ? void 0 : hints;