@shuind/dsh-codex-harness 0.1.11 → 0.1.12

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 CHANGED
@@ -16,11 +16,17 @@ DSH 的通用 `@deepseek-ai/dsh-llm-pi-ai` 继续负责用户配置的 provider
16
16
  ## 安装
17
17
 
18
18
  ```sh
19
- dsh plugin --profile web add @shuind/dsh-codex-harness@0.1.10
19
+ dsh plugin --profile web add @shuind/dsh-codex-harness@0.1.12
20
20
  ```
21
21
 
22
22
  重启 Web,创建新会话,在模式菜单中选择 `Codex 模式`。
23
23
 
24
+ ## Fast 与上下文大小
25
+
26
+ Codex 模式会在模型选择菜单中提供 `Fast` 控制。开启后,GPT Responses 请求会携带 `service_tier: "priority"`;它不是思考强度,也不会修改 `reasoning_effort`。该设置按 `codex` 设置命名空间保存,并作用于之后的请求。其他 preset 不会显示 Fast。
27
+
28
+ 点击上下文使用量指示器可以展开上下文设置。上下文大小使用整数 K tokens,可通过滑块或数字输入设置,范围为 `1K` 到 `1000K`;恢复模型默认值会删除覆盖。设置值用于下一次请求;上方的上下文 meter 显示当前请求实际使用的容量,因此修改设置后要发送下一次请求,上方的分母才会更新。这个值同时用于上下文容量投影、token meter、compaction 判断和适配器的响应 token 统计,而不只是修改显示文本。实际使用前请确认中转站和模型支持所选容量。
29
+
24
30
  ## 中转站配置
25
31
 
26
32
  请继续在 DSH 的 Models/`llm-pi-ai` 配置中填写你的 Responses 中转站地址、API key 和模型。例如 provider 下配置 `api: openai-responses`、`baseURL`、`apiKeyEnv`,并在 `models` 中填写中转站实际支持的 GPT 模型 id。Codex 模式不会替换这些配置。
package/lib/client.js ADDED
@@ -0,0 +1,633 @@
1
+ window.__ModuleLoader__.load({
2
+ id: "@shuind/dsh-codex-harness",
3
+ factory: (require) => {
4
+ var module = { exports: {} };
5
+ var exports = module.exports;
6
+ Object.defineProperties(exports, {
7
+ __esModule: { value: true },
8
+ [Symbol.toStringTag]: { value: "Module" }
9
+ });
10
+ //#region \0rolldown/runtime.js
11
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
12
+ //#endregion
13
+ //#region node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js
14
+ /**
15
+ * @license React
16
+ * react.production.min.js
17
+ *
18
+ * Copyright (c) Facebook, Inc. and its affiliates.
19
+ *
20
+ * This source code is licensed under the MIT license found in the
21
+ * LICENSE file in the root directory of this source tree.
22
+ */
23
+ var require_react_production_min = /* @__PURE__ */ __commonJSMin(((exports) => {
24
+ var l = Symbol.for("react.element");
25
+ var n = Symbol.for("react.portal");
26
+ var p = Symbol.for("react.fragment");
27
+ var q = Symbol.for("react.strict_mode");
28
+ var r = Symbol.for("react.profiler");
29
+ var t = Symbol.for("react.provider");
30
+ var u = Symbol.for("react.context");
31
+ var v = Symbol.for("react.forward_ref");
32
+ var w = Symbol.for("react.suspense");
33
+ var x = Symbol.for("react.memo");
34
+ var y = Symbol.for("react.lazy");
35
+ var z = Symbol.iterator;
36
+ function A(a) {
37
+ if (null === a || "object" !== typeof a) return null;
38
+ a = z && a[z] || a["@@iterator"];
39
+ return "function" === typeof a ? a : null;
40
+ }
41
+ var B = {
42
+ isMounted: function() {
43
+ return !1;
44
+ },
45
+ enqueueForceUpdate: function() {},
46
+ enqueueReplaceState: function() {},
47
+ enqueueSetState: function() {}
48
+ };
49
+ var C = Object.assign;
50
+ var D = {};
51
+ function E(a, b, e) {
52
+ this.props = a;
53
+ this.context = b;
54
+ this.refs = D;
55
+ this.updater = e || B;
56
+ }
57
+ E.prototype.isReactComponent = {};
58
+ E.prototype.setState = function(a, b) {
59
+ if ("object" !== typeof a && "function" !== typeof a && null != a) throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");
60
+ this.updater.enqueueSetState(this, a, b, "setState");
61
+ };
62
+ E.prototype.forceUpdate = function(a) {
63
+ this.updater.enqueueForceUpdate(this, a, "forceUpdate");
64
+ };
65
+ function F() {}
66
+ F.prototype = E.prototype;
67
+ function G(a, b, e) {
68
+ this.props = a;
69
+ this.context = b;
70
+ this.refs = D;
71
+ this.updater = e || B;
72
+ }
73
+ var H = G.prototype = new F();
74
+ H.constructor = G;
75
+ C(H, E.prototype);
76
+ H.isPureReactComponent = !0;
77
+ var I = Array.isArray;
78
+ var J = Object.prototype.hasOwnProperty;
79
+ var K = { current: null };
80
+ var L = {
81
+ key: !0,
82
+ ref: !0,
83
+ __self: !0,
84
+ __source: !0
85
+ };
86
+ function M(a, b, e) {
87
+ var d, c = {}, k = null, h = null;
88
+ if (null != b) for (d in void 0 !== b.ref && (h = b.ref), void 0 !== b.key && (k = "" + b.key), b) J.call(b, d) && !L.hasOwnProperty(d) && (c[d] = b[d]);
89
+ var g = arguments.length - 2;
90
+ if (1 === g) c.children = e;
91
+ else if (1 < g) {
92
+ for (var f = Array(g), m = 0; m < g; m++) f[m] = arguments[m + 2];
93
+ c.children = f;
94
+ }
95
+ if (a && a.defaultProps) for (d in g = a.defaultProps, g) void 0 === c[d] && (c[d] = g[d]);
96
+ return {
97
+ $$typeof: l,
98
+ type: a,
99
+ key: k,
100
+ ref: h,
101
+ props: c,
102
+ _owner: K.current
103
+ };
104
+ }
105
+ function N(a, b) {
106
+ return {
107
+ $$typeof: l,
108
+ type: a.type,
109
+ key: b,
110
+ ref: a.ref,
111
+ props: a.props,
112
+ _owner: a._owner
113
+ };
114
+ }
115
+ function O(a) {
116
+ return "object" === typeof a && null !== a && a.$$typeof === l;
117
+ }
118
+ function escape(a) {
119
+ var b = {
120
+ "=": "=0",
121
+ ":": "=2"
122
+ };
123
+ return "$" + a.replace(/[=:]/g, function(a) {
124
+ return b[a];
125
+ });
126
+ }
127
+ var P = /\/+/g;
128
+ function Q(a, b) {
129
+ return "object" === typeof a && null !== a && null != a.key ? escape("" + a.key) : b.toString(36);
130
+ }
131
+ function R(a, b, e, d, c) {
132
+ var k = typeof a;
133
+ if ("undefined" === k || "boolean" === k) a = null;
134
+ var h = !1;
135
+ if (null === a) h = !0;
136
+ else switch (k) {
137
+ case "string":
138
+ case "number":
139
+ h = !0;
140
+ break;
141
+ case "object": switch (a.$$typeof) {
142
+ case l:
143
+ case n: h = !0;
144
+ }
145
+ }
146
+ if (h) return h = a, c = c(h), a = "" === d ? "." + Q(h, 0) : d, I(c) ? (e = "", null != a && (e = a.replace(P, "$&/") + "/"), R(c, b, e, "", function(a) {
147
+ return a;
148
+ })) : null != c && (O(c) && (c = N(c, e + (!c.key || h && h.key === c.key ? "" : ("" + c.key).replace(P, "$&/") + "/") + a)), b.push(c)), 1;
149
+ h = 0;
150
+ d = "" === d ? "." : d + ":";
151
+ if (I(a)) for (var g = 0; g < a.length; g++) {
152
+ k = a[g];
153
+ var f = d + Q(k, g);
154
+ h += R(k, b, e, f, c);
155
+ }
156
+ else if (f = A(a), "function" === typeof f) for (a = f.call(a), g = 0; !(k = a.next()).done;) k = k.value, f = d + Q(k, g++), h += R(k, b, e, f, c);
157
+ else if ("object" === k) throw b = String(a), Error("Objects are not valid as a React child (found: " + ("[object Object]" === b ? "object with keys {" + Object.keys(a).join(", ") + "}" : b) + "). If you meant to render a collection of children, use an array instead.");
158
+ return h;
159
+ }
160
+ function S(a, b, e) {
161
+ if (null == a) return a;
162
+ var d = [], c = 0;
163
+ R(a, d, "", "", function(a) {
164
+ return b.call(e, a, c++);
165
+ });
166
+ return d;
167
+ }
168
+ function T(a) {
169
+ if (-1 === a._status) {
170
+ var b = a._result;
171
+ b = b();
172
+ b.then(function(b) {
173
+ if (0 === a._status || -1 === a._status) a._status = 1, a._result = b;
174
+ }, function(b) {
175
+ if (0 === a._status || -1 === a._status) a._status = 2, a._result = b;
176
+ });
177
+ -1 === a._status && (a._status = 0, a._result = b);
178
+ }
179
+ if (1 === a._status) return a._result.default;
180
+ throw a._result;
181
+ }
182
+ var U = { current: null };
183
+ var V = { transition: null };
184
+ var W = {
185
+ ReactCurrentDispatcher: U,
186
+ ReactCurrentBatchConfig: V,
187
+ ReactCurrentOwner: K
188
+ };
189
+ function X() {
190
+ throw Error("act(...) is not supported in production builds of React.");
191
+ }
192
+ exports.Children = {
193
+ map: S,
194
+ forEach: function(a, b, e) {
195
+ S(a, function() {
196
+ b.apply(this, arguments);
197
+ }, e);
198
+ },
199
+ count: function(a) {
200
+ var b = 0;
201
+ S(a, function() {
202
+ b++;
203
+ });
204
+ return b;
205
+ },
206
+ toArray: function(a) {
207
+ return S(a, function(a) {
208
+ return a;
209
+ }) || [];
210
+ },
211
+ only: function(a) {
212
+ if (!O(a)) throw Error("React.Children.only expected to receive a single React element child.");
213
+ return a;
214
+ }
215
+ };
216
+ exports.Component = E;
217
+ exports.Fragment = p;
218
+ exports.Profiler = r;
219
+ exports.PureComponent = G;
220
+ exports.StrictMode = q;
221
+ exports.Suspense = w;
222
+ exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = W;
223
+ exports.act = X;
224
+ exports.cloneElement = function(a, b, e) {
225
+ if (null === a || void 0 === a) throw Error("React.cloneElement(...): The argument must be a React element, but you passed " + a + ".");
226
+ var d = C({}, a.props), c = a.key, k = a.ref, h = a._owner;
227
+ if (null != b) {
228
+ void 0 !== b.ref && (k = b.ref, h = K.current);
229
+ void 0 !== b.key && (c = "" + b.key);
230
+ if (a.type && a.type.defaultProps) var g = a.type.defaultProps;
231
+ for (f in b) J.call(b, f) && !L.hasOwnProperty(f) && (d[f] = void 0 === b[f] && void 0 !== g ? g[f] : b[f]);
232
+ }
233
+ var f = arguments.length - 2;
234
+ if (1 === f) d.children = e;
235
+ else if (1 < f) {
236
+ g = Array(f);
237
+ for (var m = 0; m < f; m++) g[m] = arguments[m + 2];
238
+ d.children = g;
239
+ }
240
+ return {
241
+ $$typeof: l,
242
+ type: a.type,
243
+ key: c,
244
+ ref: k,
245
+ props: d,
246
+ _owner: h
247
+ };
248
+ };
249
+ exports.createContext = function(a) {
250
+ a = {
251
+ $$typeof: u,
252
+ _currentValue: a,
253
+ _currentValue2: a,
254
+ _threadCount: 0,
255
+ Provider: null,
256
+ Consumer: null,
257
+ _defaultValue: null,
258
+ _globalName: null
259
+ };
260
+ a.Provider = {
261
+ $$typeof: t,
262
+ _context: a
263
+ };
264
+ return a.Consumer = a;
265
+ };
266
+ exports.createElement = M;
267
+ exports.createFactory = function(a) {
268
+ var b = M.bind(null, a);
269
+ b.type = a;
270
+ return b;
271
+ };
272
+ exports.createRef = function() {
273
+ return { current: null };
274
+ };
275
+ exports.forwardRef = function(a) {
276
+ return {
277
+ $$typeof: v,
278
+ render: a
279
+ };
280
+ };
281
+ exports.isValidElement = O;
282
+ exports.lazy = function(a) {
283
+ return {
284
+ $$typeof: y,
285
+ _payload: {
286
+ _status: -1,
287
+ _result: a
288
+ },
289
+ _init: T
290
+ };
291
+ };
292
+ exports.memo = function(a, b) {
293
+ return {
294
+ $$typeof: x,
295
+ type: a,
296
+ compare: void 0 === b ? null : b
297
+ };
298
+ };
299
+ exports.startTransition = function(a) {
300
+ var b = V.transition;
301
+ V.transition = {};
302
+ try {
303
+ a();
304
+ } finally {
305
+ V.transition = b;
306
+ }
307
+ };
308
+ exports.unstable_act = X;
309
+ exports.useCallback = function(a, b) {
310
+ return U.current.useCallback(a, b);
311
+ };
312
+ exports.useContext = function(a) {
313
+ return U.current.useContext(a);
314
+ };
315
+ exports.useDebugValue = function() {};
316
+ exports.useDeferredValue = function(a) {
317
+ return U.current.useDeferredValue(a);
318
+ };
319
+ exports.useEffect = function(a, b) {
320
+ return U.current.useEffect(a, b);
321
+ };
322
+ exports.useId = function() {
323
+ return U.current.useId();
324
+ };
325
+ exports.useImperativeHandle = function(a, b, e) {
326
+ return U.current.useImperativeHandle(a, b, e);
327
+ };
328
+ exports.useInsertionEffect = function(a, b) {
329
+ return U.current.useInsertionEffect(a, b);
330
+ };
331
+ exports.useLayoutEffect = function(a, b) {
332
+ return U.current.useLayoutEffect(a, b);
333
+ };
334
+ exports.useMemo = function(a, b) {
335
+ return U.current.useMemo(a, b);
336
+ };
337
+ exports.useReducer = function(a, b, e) {
338
+ return U.current.useReducer(a, b, e);
339
+ };
340
+ exports.useRef = function(a) {
341
+ return U.current.useRef(a);
342
+ };
343
+ exports.useState = function(a) {
344
+ return U.current.useState(a);
345
+ };
346
+ exports.useSyncExternalStore = function(a, b, e) {
347
+ return U.current.useSyncExternalStore(a, b, e);
348
+ };
349
+ exports.useTransition = function() {
350
+ return U.current.useTransition();
351
+ };
352
+ exports.version = "18.3.1";
353
+ }));
354
+ //#endregion
355
+ //#region node_modules/.pnpm/react@18.3.1/node_modules/react/index.js
356
+ var require_react = /* @__PURE__ */ __commonJSMin(((exports, module) => {
357
+ module.exports = require_react_production_min();
358
+ }));
359
+ //#endregion
360
+ //#region node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react-jsx-runtime.production.min.js
361
+ /**
362
+ * @license React
363
+ * react-jsx-runtime.production.min.js
364
+ *
365
+ * Copyright (c) Facebook, Inc. and its affiliates.
366
+ *
367
+ * This source code is licensed under the MIT license found in the
368
+ * LICENSE file in the root directory of this source tree.
369
+ */
370
+ var require_react_jsx_runtime_production_min = /* @__PURE__ */ __commonJSMin(((exports) => {
371
+ var f = require_react();
372
+ var k = Symbol.for("react.element");
373
+ var m = Object.prototype.hasOwnProperty;
374
+ var n = f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner;
375
+ var p = {
376
+ key: !0,
377
+ ref: !0,
378
+ __self: !0,
379
+ __source: !0
380
+ };
381
+ function q(c, a, g) {
382
+ var b, d = {}, e = null, h = null;
383
+ void 0 !== g && (e = "" + g);
384
+ void 0 !== a.key && (e = "" + a.key);
385
+ void 0 !== a.ref && (h = a.ref);
386
+ for (b in a) m.call(a, b) && !p.hasOwnProperty(b) && (d[b] = a[b]);
387
+ if (c && c.defaultProps) for (b in a = c.defaultProps, a) void 0 === d[b] && (d[b] = a[b]);
388
+ return {
389
+ $$typeof: k,
390
+ type: c,
391
+ key: e,
392
+ ref: h,
393
+ props: d,
394
+ _owner: n.current
395
+ };
396
+ }
397
+ exports.jsx = q;
398
+ exports.jsxs = q;
399
+ }));
400
+ //#endregion
401
+ //#region lib/types/context.js
402
+ var import_jsx_runtime = (/* @__PURE__ */ __commonJSMin(((exports, module) => {
403
+ module.exports = require_react_jsx_runtime_production_min();
404
+ })))();
405
+ /** User-selectable Codex context controls use whole K-token units. */
406
+ const CODEX_CONTEXT_UNIT = 1e3;
407
+ const CODEX_CONTEXT_MAX = 1e6;
408
+ //#endregion
409
+ //#region lib/types/client/index.js
410
+ const NS = "codex";
411
+ const SETTINGS_NAMESPACE = "codex";
412
+ const en = {
413
+ fast: "Fast mode",
414
+ fastOn: "Fast mode on (priority tier)",
415
+ fastOff: "Fast mode off",
416
+ fastStateOn: "On",
417
+ fastStateOff: "Off",
418
+ contextSize: "Context size",
419
+ contextSizeDescription: "Next request capacity in K tokens. The meter above is current.",
420
+ contextRestore: "Restore model default"
421
+ };
422
+ const zh = {
423
+ fast: "Fast",
424
+ fastOn: "Fast mode on (priority tier)",
425
+ fastOff: "Fast mode off",
426
+ fastStateOn: "开",
427
+ fastStateOff: "关",
428
+ contextSize: "上下文大小",
429
+ contextSizeDescription: "设置下次请求的上下文容量,单位为 K tokens;上方是当前请求。",
430
+ contextRestore: "恢复模型默认值"
431
+ };
432
+ function FastModeButton({ sessionId, useSessions, useSettings, setSetting, t }) {
433
+ const agentPreset = useSessions((state) => state.byId[sessionId]?.agentPreset);
434
+ const snapshot = useSettings((state) => state);
435
+ const fast = snapshot.value?.fast ?? false;
436
+ if (agentPreset !== "codex") return null;
437
+ return (0, import_jsx_runtime.jsxs)("button", {
438
+ type: "button",
439
+ role: "menuitemcheckbox",
440
+ disabled: snapshot.writable === false,
441
+ "aria-pressed": fast,
442
+ "aria-label": fast ? t("fastOn") : t("fastOff"),
443
+ title: fast ? t("fastOn") : t("fastOff"),
444
+ onClick: () => {
445
+ setSetting("fast", !fast);
446
+ },
447
+ style: {
448
+ boxSizing: "border-box",
449
+ display: "flex",
450
+ alignItems: "center",
451
+ justifyContent: "space-between",
452
+ width: "100%",
453
+ height: 40,
454
+ border: 0,
455
+ borderRadius: 10,
456
+ padding: "0 10px",
457
+ color: fast ? "var(--dsw-static-blue-500)" : "var(--dsw-alias-label-secondary)",
458
+ background: fast ? "var(--dsw-alias-interactive-bg-selected)" : "transparent",
459
+ cursor: snapshot.writable === false ? "default" : "pointer",
460
+ font: "inherit",
461
+ fontSize: 14,
462
+ lineHeight: "22px",
463
+ fontWeight: fast ? 600 : 400,
464
+ textAlign: "left"
465
+ },
466
+ children: [(0, import_jsx_runtime.jsx)("span", { children: t("fast") }), (0, import_jsx_runtime.jsx)("span", {
467
+ style: {
468
+ color: "var(--dsw-alias-label-tertiary)",
469
+ fontSize: 12
470
+ },
471
+ children: fast ? t("fastStateOn") : t("fastStateOff")
472
+ })]
473
+ });
474
+ }
475
+ function ContextSizeControl({ contextWindow, useSettings, setSetting, unsetSetting, t }) {
476
+ const snapshot = useSettings((state) => state);
477
+ const configured = snapshot.value?.contextWindow;
478
+ const maxK = CODEX_CONTEXT_MAX / CODEX_CONTEXT_UNIT;
479
+ const valueK = Math.min(maxK, Math.max(1, Math.round((configured ?? contextWindow) / CODEX_CONTEXT_UNIT)));
480
+ const setValueK = (nextK) => {
481
+ if (!Number.isFinite(nextK)) return;
482
+ const normalized = Math.min(maxK, Math.max(1, Math.trunc(nextK))) * CODEX_CONTEXT_UNIT;
483
+ if (normalized === contextWindow) unsetSetting("contextWindow");
484
+ else setSetting("contextWindow", normalized);
485
+ };
486
+ return (0, import_jsx_runtime.jsxs)("div", {
487
+ style: {
488
+ marginTop: 10,
489
+ display: "grid",
490
+ gap: 5
491
+ },
492
+ children: [
493
+ (0, import_jsx_runtime.jsxs)("div", {
494
+ style: {
495
+ display: "flex",
496
+ alignItems: "baseline",
497
+ justifyContent: "space-between",
498
+ gap: 12
499
+ },
500
+ children: [(0, import_jsx_runtime.jsx)("strong", {
501
+ style: {
502
+ color: "var(--dsw-alias-label-primary)",
503
+ fontSize: 12
504
+ },
505
+ children: t("contextSize")
506
+ }), (0, import_jsx_runtime.jsxs)("span", {
507
+ style: {
508
+ color: "var(--dsw-alias-label-secondary)",
509
+ fontSize: 11
510
+ },
511
+ children: [valueK, "K"]
512
+ })]
513
+ }),
514
+ (0, import_jsx_runtime.jsx)("input", {
515
+ type: "range",
516
+ min: 1,
517
+ max: maxK,
518
+ step: 1,
519
+ value: valueK,
520
+ disabled: snapshot.writable === false,
521
+ "aria-label": t("contextSize"),
522
+ onChange: (event) => {
523
+ setValueK(Number(event.target.value));
524
+ }
525
+ }),
526
+ (0, import_jsx_runtime.jsxs)("div", {
527
+ style: {
528
+ display: "flex",
529
+ alignItems: "center",
530
+ gap: 7
531
+ },
532
+ children: [
533
+ (0, import_jsx_runtime.jsx)("input", {
534
+ type: "number",
535
+ min: 1,
536
+ max: maxK,
537
+ step: 1,
538
+ value: valueK,
539
+ disabled: snapshot.writable === false,
540
+ "aria-label": t("contextSize"),
541
+ onChange: (event) => {
542
+ setValueK(Number(event.target.value));
543
+ },
544
+ style: {
545
+ width: 76,
546
+ border: "1px solid var(--dsw-alias-border-primary)",
547
+ borderRadius: 5,
548
+ padding: "3px 5px",
549
+ color: "var(--dsw-alias-label-primary)",
550
+ background: "var(--dsw-alias-fill-primary)",
551
+ font: "inherit",
552
+ fontSize: 11
553
+ }
554
+ }),
555
+ (0, import_jsx_runtime.jsx)("span", {
556
+ style: {
557
+ color: "var(--dsw-alias-label-secondary)",
558
+ fontSize: 11
559
+ },
560
+ children: "K"
561
+ }),
562
+ (0, import_jsx_runtime.jsx)("span", {
563
+ style: {
564
+ color: "var(--dsw-alias-label-secondary)",
565
+ fontSize: 11
566
+ },
567
+ children: t("contextSizeDescription")
568
+ })
569
+ ]
570
+ }),
571
+ configured !== void 0 && (0, import_jsx_runtime.jsx)("button", {
572
+ type: "button",
573
+ onClick: () => {
574
+ unsetSetting("contextWindow");
575
+ },
576
+ style: {
577
+ justifySelf: "start",
578
+ border: 0,
579
+ padding: 0,
580
+ color: "var(--dsw-static-blue-500)",
581
+ background: "transparent",
582
+ cursor: "pointer",
583
+ font: "inherit",
584
+ fontSize: 11
585
+ },
586
+ children: t("contextRestore")
587
+ })
588
+ ]
589
+ });
590
+ }
591
+ const inject = [
592
+ "slots",
593
+ "locale",
594
+ "settingsScope"
595
+ ];
596
+ /** Mount Fast inside the model selector and context size inside the meter panel. */
597
+ function apply(ctx) {
598
+ ctx.effect(() => ctx.locale.register(NS, {
599
+ en,
600
+ zh
601
+ }), "codex client: dictionaries");
602
+ const settings = ctx.settingsScope.bind({ namespace: SETTINGS_NAMESPACE });
603
+ const injected = () => ({
604
+ hooks: { settings },
605
+ setSetting: (field, value) => settings.set(field, value),
606
+ unsetSetting: (field) => settings.unset(field)
607
+ });
608
+ ctx.slots.inject("conversation.input.model.settings", () => ctx.slots.register({
609
+ name: "conversation.input.model.settings",
610
+ id: "codex-fast",
611
+ order: 0,
612
+ locale: NS,
613
+ inject: injected
614
+ }, FastModeButton));
615
+ ctx.slots.inject("conversation.input.context.settings", () => ctx.slots.register({
616
+ name: "conversation.input.context.settings",
617
+ id: "codex-context-size",
618
+ order: 0,
619
+ locale: NS,
620
+ inject: injected
621
+ }, ContextSizeControl));
622
+ }
623
+ var client_default = {
624
+ inject,
625
+ apply
626
+ };
627
+ //#endregion
628
+ exports.apply = apply;
629
+ exports.default = client_default;
630
+ exports.inject = inject;
631
+ return module.exports;
632
+ }
633
+ });
package/lib/index.js CHANGED
@@ -1,10 +1,12 @@
1
1
  import z from "@deepseek-ai/schemastery";
2
- import { settingsNamespace } from "@deepseek-ai/dsh-settings";
2
+ import { installSettingsSection, settingsNamespace } from "@deepseek-ai/dsh-settings";
3
3
  import { defineTool } from "@deepseek-ai/dsh-tools";
4
4
  import { randomBytes } from "node:crypto";
5
5
  import { resolve } from "node:path";
6
6
  import { credentialRef } from "@deepseek-ai/dsh-credentials";
7
7
  import { AsyncLocalStorage } from "node:async_hooks";
8
+ //#region lib/types/context.js
9
+ const CODEX_CONTEXT_MAX = 1e6;
8
10
  String.raw`start: begin_patch hunk+ end_patch
9
11
  begin_patch: "*** Begin Patch" LF
10
12
  end_patch: "*** End Patch" LF?
@@ -714,7 +716,8 @@ const inject = [
714
716
  "shell",
715
717
  "fs",
716
718
  "llm",
717
- "credentials"
719
+ "credentials",
720
+ "settings"
718
721
  ];
719
722
  /** Runtime configuration schema for the Codex tool bridge. */
720
723
  const Config = z.object({
@@ -726,6 +729,13 @@ const Config = z.object({
726
729
  remoteCompact: z.boolean().default(true)
727
730
  });
728
731
  const LLM_PI_AI_SETTINGS = settingsNamespace("llm-pi-ai");
732
+ /** Live Codex-only request controls shared by the Web controls and agent layer. */
733
+ const CODEX_SETTINGS_NAMESPACE = settingsNamespace("codex");
734
+ const CODEX_SETTINGS_SCHEMA = z.object({
735
+ fast: z.boolean().default(false),
736
+ contextWindow: z.number().step(1).min(1).max(CODEX_CONTEXT_MAX)
737
+ });
738
+ const CODEX_SETTINGS_ENTRY = { fast: false };
729
739
  const GPT_REASONING_EFFORTS = {
730
740
  low: "low",
731
741
  medium: "medium",
@@ -809,6 +819,27 @@ function watchConfiguredGptModels(ctx) {
809
819
  });
810
820
  schedule();
811
821
  }
822
+ /** Install the optional settings source used by the request waterfall. */
823
+ function installCodexSettings(ctx) {
824
+ let source = () => CODEX_SETTINGS_ENTRY;
825
+ installSettingsSection(ctx, CODEX_SETTINGS_NAMESPACE, CODEX_SETTINGS_SCHEMA, CODEX_SETTINGS_ENTRY, {
826
+ setSource: (current) => {
827
+ source = current;
828
+ },
829
+ onChange: () => {}
830
+ });
831
+ return { current: () => source() };
832
+ }
833
+ /** Apply the live Codex controls to one agent request without leaking them to other routes. */
834
+ function applyCodexRequestSettings(request, settings) {
835
+ const { contextWindow: _inheritedContextWindow, serviceTier: _inheritedServiceTier, ...withoutCodexControls } = request;
836
+ if (!isGptModel(request.model)) return withoutCodexControls;
837
+ return {
838
+ ...withoutCodexControls,
839
+ ...settings.contextWindow === void 0 ? {} : { contextWindow: settings.contextWindow },
840
+ ...settings.fast ? { serviceTier: "priority" } : {}
841
+ };
842
+ }
812
843
  const CODEX_BASE_PROMPT = String.raw`You are Codex, based on {{model}}. You are running as a coding agent in dsh Web on a user's computer.
813
844
 
814
845
  ## General
@@ -1221,15 +1252,19 @@ function apply(ctx, config = {}) {
1221
1252
  };
1222
1253
  if (ctx.fs.sandboxMode !== void 0 && ctx.get("sandboxPolicy") === void 0) throw new Error("codex: a sandboxing filesystem requires ctx.sandboxPolicy");
1223
1254
  watchConfiguredGptModels(ctx);
1255
+ const codexSettings = installCodexSettings(ctx);
1256
+ ctx.on("agent/request", async (_payload, next) => {
1257
+ return applyCodexRequestSettings(await next(), codexSettings.current());
1258
+ });
1224
1259
  if ((resolved.hostedWebSearch || resolved.remoteCompact) && typeof ctx.effect === "function") {
1225
1260
  const disposeHostedWebSearch = installHostedWebSearch();
1226
1261
  ctx.effect(() => disposeHostedWebSearch, "codex: Responses transport wrapper");
1227
1262
  }
1228
- if (resolved.hostedWebSearch || resolved.remoteCompact) ctx.on("llm/stream", (options, next) => {
1263
+ if (resolved.hostedWebSearch || resolved.remoteCompact) ctx.on("llm/stream", ((options, next) => {
1229
1264
  if (resolved.remoteCompact && options.purpose === "compaction" && isGptModel(options.model)) return remoteCompactStream(ctx, options, next);
1230
1265
  if ((resolved.hostedWebSearch || resolved.remoteCompact) && options.purpose === void 0 && isGptModel(options.model)) return hostedWebSearchStream(next);
1231
1266
  return next();
1232
- });
1267
+ }));
1233
1268
  ctx.systemPrompt.section({
1234
1269
  name: "codex:base",
1235
1270
  order: 10,
@@ -1246,4 +1281,4 @@ var types_default = {
1246
1281
  apply
1247
1282
  };
1248
1283
  //#endregion
1249
- export { Config, apply, types_default as default, enrichCodexModel, inject, name };
1284
+ export { CODEX_SETTINGS_NAMESPACE, CODEX_SETTINGS_SCHEMA, Config, apply, applyCodexRequestSettings, types_default as default, enrichCodexModel, inject, name };
@@ -0,0 +1,40 @@
1
+ /** Browser controls for the Codex request settings mounted by the Host plugin. */
2
+ import type { Context } from '@deepseek-ai/cordis';
3
+ declare const en: {
4
+ readonly fast: "Fast mode";
5
+ readonly fastOn: "Fast mode on (priority tier)";
6
+ readonly fastOff: "Fast mode off";
7
+ readonly fastStateOn: "On";
8
+ readonly fastStateOff: "Off";
9
+ readonly contextSize: "Context size";
10
+ readonly contextSizeDescription: "Next request capacity in K tokens. The meter above is current.";
11
+ readonly contextRestore: "Restore model default";
12
+ };
13
+ type CodexKey = keyof typeof en;
14
+ declare module '@deepseek-ai/dsh-client-ui-slots' {
15
+ interface LocaleNamespaceMap {
16
+ codex: CodexKey;
17
+ }
18
+ interface SlotMap {
19
+ 'conversation.input.model.settings': {
20
+ kind: 'list';
21
+ scope: 'session';
22
+ };
23
+ 'conversation.input.context.settings': {
24
+ kind: 'list';
25
+ scope: 'session';
26
+ owner: {
27
+ contextWindow: number;
28
+ };
29
+ };
30
+ }
31
+ }
32
+ export declare const inject: string[];
33
+ /** Mount Fast inside the model selector and context size inside the meter panel. */
34
+ export declare function apply(ctx: Context): void;
35
+ declare const _default: {
36
+ inject: string[];
37
+ apply: typeof apply;
38
+ };
39
+ export default _default;
40
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,112 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { CODEX_CONTEXT_MAX, CODEX_CONTEXT_UNIT, CODEX_PRESET_ID } from "../context.js";
3
+ const NS = 'codex';
4
+ const SETTINGS_NAMESPACE = 'codex';
5
+ const en = {
6
+ fast: 'Fast mode',
7
+ fastOn: 'Fast mode on (priority tier)',
8
+ fastOff: 'Fast mode off',
9
+ fastStateOn: 'On',
10
+ fastStateOff: 'Off',
11
+ contextSize: 'Context size',
12
+ contextSizeDescription: 'Next request capacity in K tokens. The meter above is current.',
13
+ contextRestore: 'Restore model default',
14
+ };
15
+ const zh = {
16
+ fast: 'Fast',
17
+ fastOn: 'Fast mode on (priority tier)',
18
+ fastOff: 'Fast mode off',
19
+ fastStateOn: '开',
20
+ fastStateOff: '关',
21
+ contextSize: '上下文大小',
22
+ contextSizeDescription: '设置下次请求的上下文容量,单位为 K tokens;上方是当前请求。',
23
+ contextRestore: '恢复模型默认值',
24
+ };
25
+ function FastModeButton({ sessionId, useSessions, useSettings, setSetting, t }) {
26
+ const agentPreset = useSessions(state => state.byId[sessionId]?.agentPreset);
27
+ const snapshot = useSettings(state => state);
28
+ const fast = snapshot.value?.fast ?? false;
29
+ if (agentPreset !== CODEX_PRESET_ID)
30
+ return null;
31
+ return (_jsxs("button", { type: "button", role: "menuitemcheckbox", disabled: snapshot.writable === false, "aria-pressed": fast, "aria-label": fast ? t('fastOn') : t('fastOff'), title: fast ? t('fastOn') : t('fastOff'), onClick: () => { void setSetting('fast', !fast); }, style: {
32
+ boxSizing: 'border-box',
33
+ display: 'flex',
34
+ alignItems: 'center',
35
+ justifyContent: 'space-between',
36
+ width: '100%',
37
+ height: 40,
38
+ border: 0,
39
+ borderRadius: 10,
40
+ padding: '0 10px',
41
+ color: fast ? 'var(--dsw-static-blue-500)' : 'var(--dsw-alias-label-secondary)',
42
+ background: fast ? 'var(--dsw-alias-interactive-bg-selected)' : 'transparent',
43
+ cursor: snapshot.writable === false ? 'default' : 'pointer',
44
+ font: 'inherit',
45
+ fontSize: 14,
46
+ lineHeight: '22px',
47
+ fontWeight: fast ? 600 : 400,
48
+ textAlign: 'left',
49
+ }, children: [_jsx("span", { children: t('fast') }), _jsx("span", { style: { color: 'var(--dsw-alias-label-tertiary)', fontSize: 12 }, children: fast ? t('fastStateOn') : t('fastStateOff') })] }));
50
+ }
51
+ function ContextSizeControl({ contextWindow, useSettings, setSetting, unsetSetting, t }) {
52
+ const snapshot = useSettings(state => state);
53
+ const configured = snapshot.value?.contextWindow;
54
+ const maxK = CODEX_CONTEXT_MAX / CODEX_CONTEXT_UNIT;
55
+ const valueK = Math.min(maxK, Math.max(1, Math.round((configured ?? contextWindow) / CODEX_CONTEXT_UNIT)));
56
+ const setValueK = (nextK) => {
57
+ if (!Number.isFinite(nextK))
58
+ return;
59
+ const normalizedK = Math.min(maxK, Math.max(1, Math.trunc(nextK)));
60
+ const normalized = normalizedK * CODEX_CONTEXT_UNIT;
61
+ if (normalized === contextWindow)
62
+ void unsetSetting('contextWindow');
63
+ else
64
+ void setSetting('contextWindow', normalized);
65
+ };
66
+ return (_jsxs("div", { style: { marginTop: 10, display: 'grid', gap: 5 }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 12 }, children: [_jsx("strong", { style: { color: 'var(--dsw-alias-label-primary)', fontSize: 12 }, children: t('contextSize') }), _jsxs("span", { style: { color: 'var(--dsw-alias-label-secondary)', fontSize: 11 }, children: [valueK, "K"] })] }), _jsx("input", { type: "range", min: 1, max: maxK, step: 1, value: valueK, disabled: snapshot.writable === false, "aria-label": t('contextSize'), onChange: event => { setValueK(Number(event.target.value)); } }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 7 }, children: [_jsx("input", { type: "number", min: 1, max: maxK, step: 1, value: valueK, disabled: snapshot.writable === false, "aria-label": t('contextSize'), onChange: event => { setValueK(Number(event.target.value)); }, style: {
67
+ width: 76,
68
+ border: '1px solid var(--dsw-alias-border-primary)',
69
+ borderRadius: 5,
70
+ padding: '3px 5px',
71
+ color: 'var(--dsw-alias-label-primary)',
72
+ background: 'var(--dsw-alias-fill-primary)',
73
+ font: 'inherit',
74
+ fontSize: 11,
75
+ } }), _jsx("span", { style: { color: 'var(--dsw-alias-label-secondary)', fontSize: 11 }, children: "K" }), _jsx("span", { style: { color: 'var(--dsw-alias-label-secondary)', fontSize: 11 }, children: t('contextSizeDescription') })] }), configured !== undefined && (_jsx("button", { type: "button", onClick: () => { void unsetSetting('contextWindow'); }, style: {
76
+ justifySelf: 'start',
77
+ border: 0,
78
+ padding: 0,
79
+ color: 'var(--dsw-static-blue-500)',
80
+ background: 'transparent',
81
+ cursor: 'pointer',
82
+ font: 'inherit',
83
+ fontSize: 11,
84
+ }, children: t('contextRestore') }))] }));
85
+ }
86
+ export const inject = ['slots', 'locale', 'settingsScope'];
87
+ /** Mount Fast inside the model selector and context size inside the meter panel. */
88
+ export function apply(ctx) {
89
+ ctx.effect(() => ctx.locale.register(NS, { en, zh }), 'codex client: dictionaries');
90
+ const settings = ctx.settingsScope.bind({ namespace: SETTINGS_NAMESPACE });
91
+ const injected = () => ({
92
+ hooks: { settings },
93
+ setSetting: (field, value) => settings.set(field, value),
94
+ unsetSetting: (field) => settings.unset(field),
95
+ });
96
+ ctx.slots.inject('conversation.input.model.settings', () => ctx.slots.register({
97
+ name: 'conversation.input.model.settings',
98
+ id: 'codex-fast',
99
+ order: 0,
100
+ locale: NS,
101
+ inject: injected,
102
+ }, FastModeButton));
103
+ ctx.slots.inject('conversation.input.context.settings', () => ctx.slots.register({
104
+ name: 'conversation.input.context.settings',
105
+ id: 'codex-context-size',
106
+ order: 0,
107
+ locale: NS,
108
+ inject: injected,
109
+ }, ContextSizeControl));
110
+ }
111
+ export default { inject, apply };
112
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,5 @@
1
+ /** User-selectable Codex context controls use whole K-token units. */
2
+ export declare const CODEX_CONTEXT_UNIT = 1000;
3
+ export declare const CODEX_CONTEXT_MAX = 1000000;
4
+ export declare const CODEX_PRESET_ID = "codex";
5
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1,5 @@
1
+ /** User-selectable Codex context controls use whole K-token units. */
2
+ export const CODEX_CONTEXT_UNIT = 1_000;
3
+ export const CODEX_CONTEXT_MAX = 1_000_000;
4
+ export const CODEX_PRESET_ID = 'codex';
5
+ //# sourceMappingURL=context.js.map
@@ -1,6 +1,15 @@
1
1
  /** Codex-compatible prompt overlay and core tools for a dsh agent preset. */
2
2
  import type { Context } from '@deepseek-ai/cordis';
3
3
  import z from '@deepseek-ai/schemastery';
4
+ import type { LlmCallConfig } from '@deepseek-ai/dsh-llm';
5
+ declare module '@deepseek-ai/dsh-llm' {
6
+ interface LlmCallConfig {
7
+ /** Codex request context capacity override, in tokens. */
8
+ contextWindow?: number;
9
+ /** Provider-facing service tier, for example Responses `priority`. */
10
+ serviceTier?: string;
11
+ }
12
+ }
4
13
  export declare const name = "codex";
5
14
  export declare const inject: string[];
6
15
  /** Configuration for the Codex shell result bridge. */
@@ -20,6 +29,15 @@ export interface Config {
20
29
  }
21
30
  /** Runtime configuration schema for the Codex tool bridge. */
22
31
  export declare const Config: z<Config>;
32
+ /** Live Codex-only request controls shared by the Web controls and agent layer. */
33
+ export declare const CODEX_SETTINGS_NAMESPACE: import("@deepseek-ai/dsh-settings").SettingsNamespace;
34
+ export interface CodexSettings {
35
+ /** Use the Responses priority service tier for GPT requests. */
36
+ fast: boolean;
37
+ /** Optional context capacity override, in tokens. */
38
+ contextWindow?: number;
39
+ }
40
+ export declare const CODEX_SETTINGS_SCHEMA: z<CodexSettings>;
23
41
  export interface CodexModelProfile {
24
42
  id: string;
25
43
  input?: string[];
@@ -28,6 +46,8 @@ export interface CodexModelProfile {
28
46
  }
29
47
  /** Add Codex defaults without overwriting explicit user capabilities. */
30
48
  export declare function enrichCodexModel(model: CodexModelProfile): CodexModelProfile;
49
+ /** Apply the live Codex controls to one agent request without leaking them to other routes. */
50
+ export declare function applyCodexRequestSettings(request: LlmCallConfig, settings: CodexSettings): LlmCallConfig;
31
51
  /** Mount the Codex prompt/tool layer inside one fixed agent preset. */
32
52
  export declare function apply(ctx: Context, config?: Config): void;
33
53
  declare const _default: {
@@ -1,12 +1,13 @@
1
1
  /** Codex-compatible prompt overlay and core tools for a dsh agent preset. */
2
2
  import z from '@deepseek-ai/schemastery';
3
- import { settingsNamespace } from '@deepseek-ai/dsh-settings';
3
+ import { installSettingsSection, settingsNamespace } from '@deepseek-ai/dsh-settings';
4
4
  import { defineTool } from '@deepseek-ai/dsh-tools';
5
+ import { CODEX_CONTEXT_MAX } from "./context.js";
5
6
  import { applyPatchHunks, parsePatch } from "./patch.js";
6
7
  import { renderExecResult, runExecCommand, runWriteStdin } from "./exec.js";
7
8
  import { hostedWebSearchStream, installHostedWebSearch, remoteCompactStream } from "./remote.js";
8
9
  export const name = 'codex';
9
- export const inject = ['tools', 'systemPrompt', 'shell', 'fs', 'llm', 'credentials'];
10
+ export const inject = ['tools', 'systemPrompt', 'shell', 'fs', 'llm', 'credentials', 'settings'];
10
11
  /** Runtime configuration schema for the Codex tool bridge. */
11
12
  export const Config = z.object({
12
13
  defaultYieldTimeMs: z.number().step(1).min(0).default(10_000),
@@ -17,6 +18,13 @@ export const Config = z.object({
17
18
  remoteCompact: z.boolean().default(true),
18
19
  });
19
20
  const LLM_PI_AI_SETTINGS = settingsNamespace('llm-pi-ai');
21
+ /** Live Codex-only request controls shared by the Web controls and agent layer. */
22
+ export const CODEX_SETTINGS_NAMESPACE = settingsNamespace('codex');
23
+ export const CODEX_SETTINGS_SCHEMA = z.object({
24
+ fast: z.boolean().default(false),
25
+ contextWindow: z.number().step(1).min(1).max(CODEX_CONTEXT_MAX),
26
+ });
27
+ const CODEX_SETTINGS_ENTRY = { fast: false };
20
28
  const GPT_REASONING_EFFORTS = {
21
29
  low: 'low',
22
30
  medium: 'medium',
@@ -108,6 +116,26 @@ function watchConfiguredGptModels(ctx) {
108
116
  });
109
117
  schedule();
110
118
  }
119
+ /** Install the optional settings source used by the request waterfall. */
120
+ function installCodexSettings(ctx) {
121
+ let source = () => CODEX_SETTINGS_ENTRY;
122
+ installSettingsSection(ctx, CODEX_SETTINGS_NAMESPACE, CODEX_SETTINGS_SCHEMA, CODEX_SETTINGS_ENTRY, {
123
+ setSource: (current) => { source = current; },
124
+ onChange: () => { },
125
+ });
126
+ return { current: () => source() };
127
+ }
128
+ /** Apply the live Codex controls to one agent request without leaking them to other routes. */
129
+ export function applyCodexRequestSettings(request, settings) {
130
+ const { contextWindow: _inheritedContextWindow, serviceTier: _inheritedServiceTier, ...withoutCodexControls } = request;
131
+ if (!isGptModel(request.model))
132
+ return withoutCodexControls;
133
+ return {
134
+ ...withoutCodexControls,
135
+ ...settings.contextWindow === undefined ? {} : { contextWindow: settings.contextWindow },
136
+ ...settings.fast ? { serviceTier: 'priority' } : {},
137
+ };
138
+ }
111
139
  const CODEX_BASE_PROMPT = String.raw `You are Codex, based on {{model}}. You are running as a coding agent in dsh Web on a user's computer.
112
140
 
113
141
  ## General
@@ -414,12 +442,20 @@ export function apply(ctx, config = {}) {
414
442
  // provider routes. Codex adds only scoped transport behavior and capability
415
443
  // metadata; failed remote operations continue through the generic path.
416
444
  watchConfiguredGptModels(ctx);
445
+ const codexSettings = installCodexSettings(ctx);
446
+ // Keep these controls in the request config rather than mutating provider
447
+ // settings. That makes a change apply to the next step without rebuilding
448
+ // the user's model catalog, while the LLM service still freezes it per call.
449
+ ctx.on('agent/request', async (_payload, next) => {
450
+ const request = await next();
451
+ return applyCodexRequestSettings(request, codexSettings.current());
452
+ });
417
453
  if ((resolved.hostedWebSearch || resolved.remoteCompact) && typeof ctx.effect === 'function') {
418
454
  const disposeHostedWebSearch = installHostedWebSearch();
419
455
  ctx.effect(() => disposeHostedWebSearch, 'codex: Responses transport wrapper');
420
456
  }
421
457
  if (resolved.hostedWebSearch || resolved.remoteCompact) {
422
- ctx.on('llm/stream', (options, next) => {
458
+ ctx.on('llm/stream', ((options, next) => {
423
459
  if (resolved.remoteCompact && options.purpose === 'compaction' && isGptModel(options.model)) {
424
460
  return remoteCompactStream(ctx, options, next);
425
461
  }
@@ -429,7 +465,7 @@ export function apply(ctx, config = {}) {
429
465
  return hostedWebSearchStream(next);
430
466
  }
431
467
  return next();
432
- });
468
+ }));
433
469
  }
434
470
  ctx.systemPrompt.section({ name: 'codex:base', order: 10, text: CODEX_BASE_PROMPT });
435
471
  registerExecTools(ctx, resolved);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shuind/dsh-codex-harness",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "A minimal Codex harness for GPT models that do not fit DSH's native interface, while remaining compatible with the DSH plugin ecosystem.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -18,6 +18,10 @@
18
18
  "types": "./lib/types/installer.d.ts",
19
19
  "default": "./lib/installer.js"
20
20
  },
21
+ "./client": {
22
+ "types": "./lib/types/client/index.d.ts",
23
+ "default": "./lib/client.js"
24
+ },
21
25
  "./cordis.patch.yml": "./cordis.patch.yml",
22
26
  "./src/*": "./src/*",
23
27
  "./package.json": "./package.json"
@@ -28,6 +32,7 @@
28
32
  "lib/installer.js",
29
33
  "lib/types/**/*.js",
30
34
  "lib/types/**/*.d.ts",
35
+ "lib/client.js",
31
36
  "cordis.patch.yml",
32
37
  "presets/codex",
33
38
  "README.md",
@@ -58,6 +63,16 @@
58
63
  "dsh": {
59
64
  "bundle": {
60
65
  "patch": "./cordis.patch.yml"
66
+ },
67
+ "client": {
68
+ "inject": [
69
+ "@deepseek-ai/dsh-client-locale",
70
+ "@deepseek-ai/dsh-client-runtime",
71
+ "@deepseek-ai/dsh-client-ui-conversation",
72
+ "@deepseek-ai/dsh-client-ui-settings",
73
+ "@deepseek-ai/dsh-client-ui-slots"
74
+ ],
75
+ "platform": "web"
61
76
  }
62
77
  },
63
78
  "dependencies": {
@@ -67,6 +82,11 @@
67
82
  "peerDependencies": {
68
83
  "@deepseek-ai/cordis": ">=4.0.1",
69
84
  "@deepseek-ai/dsh-agent": ">=0.1.0-rc.6",
85
+ "@deepseek-ai/dsh-client-locale": ">=0.1.0-rc.8",
86
+ "@deepseek-ai/dsh-client-runtime": ">=0.1.0-rc.8",
87
+ "@deepseek-ai/dsh-client-ui-conversation": ">=0.1.0-rc.8",
88
+ "@deepseek-ai/dsh-client-ui-settings": ">=0.1.0-rc.8",
89
+ "@deepseek-ai/dsh-client-ui-slots": ">=0.1.0-rc.8",
70
90
  "@deepseek-ai/dsh-credentials": ">=0.1.0-rc.8",
71
91
  "@deepseek-ai/dsh-fs": ">=0.0.1-rc.1",
72
92
  "@deepseek-ai/dsh-invariants": ">=0.0.1-rc.1",
@@ -89,6 +109,21 @@
89
109
  "@deepseek-ai/dsh-agent": {
90
110
  "optional": true
91
111
  },
112
+ "@deepseek-ai/dsh-client-locale": {
113
+ "optional": true
114
+ },
115
+ "@deepseek-ai/dsh-client-runtime": {
116
+ "optional": true
117
+ },
118
+ "@deepseek-ai/dsh-client-ui-conversation": {
119
+ "optional": true
120
+ },
121
+ "@deepseek-ai/dsh-client-ui-settings": {
122
+ "optional": true
123
+ },
124
+ "@deepseek-ai/dsh-client-ui-slots": {
125
+ "optional": true
126
+ },
92
127
  "@deepseek-ai/dsh-credentials": {
93
128
  "optional": true
94
129
  },
@@ -135,6 +170,11 @@
135
170
  "devDependencies": {
136
171
  "@deepseek-ai/cordis": "4.0.1",
137
172
  "@deepseek-ai/dsh-agent": "0.1.0-rc.6",
173
+ "@deepseek-ai/dsh-client-locale": "0.1.0-rc.8",
174
+ "@deepseek-ai/dsh-client-runtime": "0.1.0-rc.8",
175
+ "@deepseek-ai/dsh-client-ui-conversation": "0.1.0-rc.8",
176
+ "@deepseek-ai/dsh-client-ui-settings": "0.1.0-rc.8",
177
+ "@deepseek-ai/dsh-client-ui-slots": "0.1.0-rc.8",
138
178
  "@deepseek-ai/dsh-credentials": "0.1.0-rc.8",
139
179
  "@deepseek-ai/dsh-fs": "0.1.0-rc.6",
140
180
  "@deepseek-ai/dsh-invariants": "0.1.0-rc.6",
@@ -150,6 +190,8 @@
150
190
  "@deepseek-ai/dsh-terminal": "0.1.0-rc.6",
151
191
  "@deepseek-ai/dsh-tools": "0.1.0-rc.6",
152
192
  "@types/node": "^22.20.0",
193
+ "@types/react": "~18.3.1",
194
+ "react": "^18.3.1",
153
195
  "tsdown": "^0.22.2",
154
196
  "typescript": "^6.0.3",
155
197
  "unrun": "^0.3.1",