@tnnevol/dsh-codex-auth 0.1.0-rc.8 → 0.1.0-rc.8.2
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/auth-paths.d.ts +3 -1
- package/lib/auth-paths.js +3 -1
- package/lib/client.js +691 -61
- package/lib/index.d.ts +2 -2
- package/lib/index.js +57 -3
- package/package.json +7 -2
package/lib/auth-paths.d.ts
CHANGED
|
@@ -8,5 +8,7 @@ declare const CODEX_AUTH_LOGOUT_PATH = "/plugins/dsh-codex-auth-plugin/auth/logo
|
|
|
8
8
|
declare const CODEX_USAGE_PATH = "/plugins/dsh-codex-auth-plugin/auth/usage";
|
|
9
9
|
/** Same-origin settings endpoint used when DSH marks a NAS browser as remote. */
|
|
10
10
|
declare const CODEX_AUTH_SETTINGS_PATH = "/plugins/dsh-codex-auth-plugin/auth/settings";
|
|
11
|
+
/** Same-origin endpoint for the DSH-wide Codex default model selection. */
|
|
12
|
+
declare const CODEX_GLOBAL_MODEL_PATH = "/plugins/dsh-codex-auth-plugin/auth/global-model";
|
|
11
13
|
//#endregion
|
|
12
|
-
export { CODEX_AUTH_LOGIN_PATH, CODEX_AUTH_LOGOUT_PATH, CODEX_AUTH_SETTINGS_NAMESPACE, CODEX_AUTH_SETTINGS_PATH, CODEX_AUTH_STATUS_PATH, CODEX_USAGE_PATH };
|
|
14
|
+
export { CODEX_AUTH_LOGIN_PATH, CODEX_AUTH_LOGOUT_PATH, CODEX_AUTH_SETTINGS_NAMESPACE, CODEX_AUTH_SETTINGS_PATH, CODEX_AUTH_STATUS_PATH, CODEX_GLOBAL_MODEL_PATH, CODEX_USAGE_PATH };
|
package/lib/auth-paths.js
CHANGED
|
@@ -8,5 +8,7 @@ const CODEX_AUTH_LOGOUT_PATH = "/plugins/dsh-codex-auth-plugin/auth/logout";
|
|
|
8
8
|
const CODEX_USAGE_PATH = "/plugins/dsh-codex-auth-plugin/auth/usage";
|
|
9
9
|
/** Same-origin settings endpoint used when DSH marks a NAS browser as remote. */
|
|
10
10
|
const CODEX_AUTH_SETTINGS_PATH = "/plugins/dsh-codex-auth-plugin/auth/settings";
|
|
11
|
+
/** Same-origin endpoint for the DSH-wide Codex default model selection. */
|
|
12
|
+
const CODEX_GLOBAL_MODEL_PATH = "/plugins/dsh-codex-auth-plugin/auth/global-model";
|
|
11
13
|
//#endregion
|
|
12
|
-
export { CODEX_AUTH_LOGIN_PATH, CODEX_AUTH_LOGOUT_PATH, CODEX_AUTH_SETTINGS_NAMESPACE, CODEX_AUTH_SETTINGS_PATH, CODEX_AUTH_STATUS_PATH, CODEX_USAGE_PATH };
|
|
14
|
+
export { CODEX_AUTH_LOGIN_PATH, CODEX_AUTH_LOGOUT_PATH, CODEX_AUTH_SETTINGS_NAMESPACE, CODEX_AUTH_SETTINGS_PATH, CODEX_AUTH_STATUS_PATH, CODEX_GLOBAL_MODEL_PATH, CODEX_USAGE_PATH };
|
package/lib/client.js
CHANGED
|
@@ -6,23 +6,24 @@ window.__ModuleLoader__.load({
|
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
7
|
let react = require("react");
|
|
8
8
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
|
+
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
9
10
|
//#region src/client/CodexCapabilities.tsx
|
|
10
11
|
/** Live optional-capability settings for the Codex Auth plugin. */
|
|
11
|
-
const sectionStyle = {
|
|
12
|
+
const sectionStyle$1 = {
|
|
12
13
|
display: "flex",
|
|
13
14
|
flexDirection: "column",
|
|
14
15
|
gap: 12,
|
|
15
16
|
borderTop: "1px solid var(--dsw-alias-border-l2)",
|
|
16
17
|
paddingTop: 14
|
|
17
18
|
};
|
|
18
|
-
const headingStyle = {
|
|
19
|
+
const headingStyle$1 = {
|
|
19
20
|
margin: 0,
|
|
20
21
|
fontSize: 14,
|
|
21
22
|
lineHeight: "20px",
|
|
22
23
|
fontWeight: 600,
|
|
23
24
|
color: "var(--dsw-alias-label-primary)"
|
|
24
25
|
};
|
|
25
|
-
const bodyStyle$
|
|
26
|
+
const bodyStyle$2 = {
|
|
26
27
|
margin: 0,
|
|
27
28
|
fontSize: 12,
|
|
28
29
|
lineHeight: "18px",
|
|
@@ -47,6 +48,7 @@ window.__ModuleLoader__.load({
|
|
|
47
48
|
cursor: "not-allowed",
|
|
48
49
|
opacity: .62
|
|
49
50
|
};
|
|
51
|
+
const checkboxStyle = { accentColor: "var(--dsw-alias-button-primary-fill)" };
|
|
50
52
|
const copyStyle = {
|
|
51
53
|
display: "flex",
|
|
52
54
|
flexDirection: "column",
|
|
@@ -58,7 +60,7 @@ window.__ModuleLoader__.load({
|
|
|
58
60
|
fontWeight: 500,
|
|
59
61
|
color: "var(--dsw-alias-label-primary)"
|
|
60
62
|
};
|
|
61
|
-
const actionsStyle = {
|
|
63
|
+
const actionsStyle$1 = {
|
|
62
64
|
display: "flex",
|
|
63
65
|
alignItems: "center",
|
|
64
66
|
justifyContent: "space-between",
|
|
@@ -69,7 +71,7 @@ window.__ModuleLoader__.load({
|
|
|
69
71
|
display: "flex",
|
|
70
72
|
gap: 8
|
|
71
73
|
};
|
|
72
|
-
const buttonStyle$
|
|
74
|
+
const buttonStyle$2 = {
|
|
73
75
|
boxSizing: "border-box",
|
|
74
76
|
minHeight: 30,
|
|
75
77
|
padding: "4px 12px",
|
|
@@ -81,18 +83,18 @@ window.__ModuleLoader__.load({
|
|
|
81
83
|
fontSize: 12,
|
|
82
84
|
cursor: "pointer"
|
|
83
85
|
};
|
|
84
|
-
const primaryButtonStyle$
|
|
85
|
-
...buttonStyle$
|
|
86
|
+
const primaryButtonStyle$2 = {
|
|
87
|
+
...buttonStyle$2,
|
|
86
88
|
border: 0,
|
|
87
89
|
background: "var(--dsw-alias-button-primary-fill)",
|
|
88
90
|
color: "var(--dsw-alias-label-primary-foreground)"
|
|
89
91
|
};
|
|
90
|
-
const errorStyle$
|
|
91
|
-
...bodyStyle$
|
|
92
|
+
const errorStyle$2 = {
|
|
93
|
+
...bodyStyle$2,
|
|
92
94
|
color: "var(--dsw-alias-state-error-primary, #d92d20)"
|
|
93
95
|
};
|
|
94
|
-
const successStyle = {
|
|
95
|
-
...bodyStyle$
|
|
96
|
+
const successStyle$1 = {
|
|
97
|
+
...bodyStyle$2,
|
|
96
98
|
color: "var(--dsw-alias-state-success-primary, #16825d)"
|
|
97
99
|
};
|
|
98
100
|
const UNAVAILABLE_SNAPSHOT = {
|
|
@@ -165,32 +167,32 @@ window.__ModuleLoader__.load({
|
|
|
165
167
|
const loading = snapshot.status === "loading";
|
|
166
168
|
const editable = snapshot.status === "ready" && snapshot.writable && !busy;
|
|
167
169
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
168
|
-
style: sectionStyle,
|
|
170
|
+
style: sectionStyle$1,
|
|
169
171
|
"aria-labelledby": "dsh-codex-capabilities-title",
|
|
170
172
|
children: [
|
|
171
173
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
172
174
|
id: "dsh-codex-capabilities-title",
|
|
173
|
-
style: headingStyle,
|
|
175
|
+
style: headingStyle$1,
|
|
174
176
|
children: t("capabilitiesTitle")
|
|
175
177
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
176
178
|
style: {
|
|
177
|
-
...bodyStyle$
|
|
179
|
+
...bodyStyle$2,
|
|
178
180
|
marginTop: 3
|
|
179
181
|
},
|
|
180
182
|
children: t("capabilitiesIntro")
|
|
181
183
|
})] }),
|
|
182
184
|
loading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
183
|
-
style: bodyStyle$
|
|
185
|
+
style: bodyStyle$2,
|
|
184
186
|
role: "status",
|
|
185
187
|
children: t("settingsLoading")
|
|
186
188
|
}) : null,
|
|
187
189
|
snapshot.status === "unavailable" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
188
|
-
style: errorStyle$
|
|
190
|
+
style: errorStyle$2,
|
|
189
191
|
role: "alert",
|
|
190
192
|
children: t("settingsUnavailable")
|
|
191
193
|
}) : null,
|
|
192
194
|
snapshot.status === "ready" && !snapshot.writable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
193
|
-
style: errorStyle$
|
|
195
|
+
style: errorStyle$2,
|
|
194
196
|
role: "alert",
|
|
195
197
|
children: t("settingsReadOnly")
|
|
196
198
|
}) : null,
|
|
@@ -201,6 +203,7 @@ window.__ModuleLoader__.load({
|
|
|
201
203
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
202
204
|
style: rowStyle$1,
|
|
203
205
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
206
|
+
style: checkboxStyle,
|
|
204
207
|
type: "checkbox",
|
|
205
208
|
checked: draft.enableImageTool,
|
|
206
209
|
onChange: (event) => {
|
|
@@ -212,7 +215,7 @@ window.__ModuleLoader__.load({
|
|
|
212
215
|
style: labelStyle,
|
|
213
216
|
children: t("enableImageRecognition")
|
|
214
217
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
215
|
-
style: bodyStyle$
|
|
218
|
+
style: bodyStyle$2,
|
|
216
219
|
children: t("enableImageRecognitionHelp")
|
|
217
220
|
})]
|
|
218
221
|
})]
|
|
@@ -220,6 +223,7 @@ window.__ModuleLoader__.load({
|
|
|
220
223
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
221
224
|
style: rowStyle$1,
|
|
222
225
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
226
|
+
style: checkboxStyle,
|
|
223
227
|
type: "checkbox",
|
|
224
228
|
checked: draft.enableImageUpload,
|
|
225
229
|
onChange: (event) => {
|
|
@@ -231,7 +235,7 @@ window.__ModuleLoader__.load({
|
|
|
231
235
|
style: labelStyle,
|
|
232
236
|
children: t("enableImageUpload")
|
|
233
237
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
234
|
-
style: bodyStyle$
|
|
238
|
+
style: bodyStyle$2,
|
|
235
239
|
children: t("enableImageUploadHelp")
|
|
236
240
|
})]
|
|
237
241
|
})]
|
|
@@ -240,6 +244,7 @@ window.__ModuleLoader__.load({
|
|
|
240
244
|
style: disabledRowStyle,
|
|
241
245
|
title: t("imageGenerationUnavailableHelp"),
|
|
242
246
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
247
|
+
style: checkboxStyle,
|
|
243
248
|
type: "checkbox",
|
|
244
249
|
checked: false,
|
|
245
250
|
disabled: true,
|
|
@@ -251,7 +256,7 @@ window.__ModuleLoader__.load({
|
|
|
251
256
|
style: labelStyle,
|
|
252
257
|
children: t("enableImageGeneration")
|
|
253
258
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
254
|
-
style: bodyStyle$
|
|
259
|
+
style: bodyStyle$2,
|
|
255
260
|
children: t("imageGenerationUnavailableHelp")
|
|
256
261
|
})]
|
|
257
262
|
})]
|
|
@@ -259,27 +264,27 @@ window.__ModuleLoader__.load({
|
|
|
259
264
|
]
|
|
260
265
|
}),
|
|
261
266
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
262
|
-
style: actionsStyle,
|
|
267
|
+
style: actionsStyle$1,
|
|
263
268
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
264
269
|
"aria-live": "polite",
|
|
265
270
|
children: [feedback === "saved" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
266
|
-
style: successStyle,
|
|
271
|
+
style: successStyle$1,
|
|
267
272
|
children: t("settingsSaved")
|
|
268
273
|
}) : null, feedback === "error" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
269
|
-
style: errorStyle$
|
|
274
|
+
style: errorStyle$2,
|
|
270
275
|
children: t("settingsSaveFailed")
|
|
271
276
|
}) : null]
|
|
272
277
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
273
278
|
style: buttonsStyle,
|
|
274
279
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
275
280
|
type: "button",
|
|
276
|
-
style: buttonStyle$
|
|
281
|
+
style: buttonStyle$2,
|
|
277
282
|
disabled: !dirty || busy,
|
|
278
283
|
onClick: discard,
|
|
279
284
|
children: t("discard")
|
|
280
285
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
281
286
|
type: "button",
|
|
282
|
-
style: primaryButtonStyle$
|
|
287
|
+
style: primaryButtonStyle$2,
|
|
283
288
|
disabled: !dirty || !snapshot.writable || busy,
|
|
284
289
|
onClick: () => {
|
|
285
290
|
save();
|
|
@@ -302,6 +307,566 @@ window.__ModuleLoader__.load({
|
|
|
302
307
|
const CODEX_USAGE_PATH = "/plugins/dsh-codex-auth-plugin/auth/usage";
|
|
303
308
|
/** Same-origin settings endpoint used when DSH marks a NAS browser as remote. */
|
|
304
309
|
const CODEX_AUTH_SETTINGS_PATH = "/plugins/dsh-codex-auth-plugin/auth/settings";
|
|
310
|
+
/** Same-origin endpoint for the DSH-wide Codex default model selection. */
|
|
311
|
+
const CODEX_GLOBAL_MODEL_PATH = "/plugins/dsh-codex-auth-plugin/auth/global-model";
|
|
312
|
+
//#endregion
|
|
313
|
+
//#region src/client/CodexGlobalModel.tsx
|
|
314
|
+
/** DSH-wide Codex default model controls. */
|
|
315
|
+
const sectionStyle = {
|
|
316
|
+
display: "flex",
|
|
317
|
+
flexDirection: "column",
|
|
318
|
+
gap: 12,
|
|
319
|
+
borderTop: "1px solid var(--dsw-alias-border-l2)",
|
|
320
|
+
paddingTop: 14
|
|
321
|
+
};
|
|
322
|
+
const headingStyle = {
|
|
323
|
+
margin: 0,
|
|
324
|
+
fontSize: 14,
|
|
325
|
+
lineHeight: "20px",
|
|
326
|
+
fontWeight: 600,
|
|
327
|
+
color: "var(--dsw-alias-label-primary)"
|
|
328
|
+
};
|
|
329
|
+
const bodyStyle$1 = {
|
|
330
|
+
margin: 0,
|
|
331
|
+
fontSize: 12,
|
|
332
|
+
lineHeight: "18px",
|
|
333
|
+
color: "var(--dsw-alias-label-secondary)"
|
|
334
|
+
};
|
|
335
|
+
const fieldsStyle = {
|
|
336
|
+
display: "flex",
|
|
337
|
+
alignItems: "center",
|
|
338
|
+
minWidth: 0
|
|
339
|
+
};
|
|
340
|
+
const actionsStyle = {
|
|
341
|
+
display: "flex",
|
|
342
|
+
alignItems: "center",
|
|
343
|
+
justifyContent: "space-between",
|
|
344
|
+
gap: 10,
|
|
345
|
+
flexWrap: "wrap"
|
|
346
|
+
};
|
|
347
|
+
const buttonStyle$1 = {
|
|
348
|
+
boxSizing: "border-box",
|
|
349
|
+
minHeight: 30,
|
|
350
|
+
padding: "4px 12px",
|
|
351
|
+
border: "1px solid var(--dsw-alias-border-l2)",
|
|
352
|
+
borderRadius: 16,
|
|
353
|
+
background: "var(--dsw-alias-bg-layer-1)",
|
|
354
|
+
color: "var(--dsw-alias-label-primary)",
|
|
355
|
+
font: "inherit",
|
|
356
|
+
fontSize: 12,
|
|
357
|
+
cursor: "pointer"
|
|
358
|
+
};
|
|
359
|
+
const primaryButtonStyle$1 = {
|
|
360
|
+
...buttonStyle$1,
|
|
361
|
+
border: 0,
|
|
362
|
+
background: "var(--dsw-alias-button-primary-fill)",
|
|
363
|
+
color: "var(--dsw-alias-label-primary-foreground)"
|
|
364
|
+
};
|
|
365
|
+
const errorStyle$1 = {
|
|
366
|
+
...bodyStyle$1,
|
|
367
|
+
color: "var(--dsw-alias-state-error-primary, #d92d20)"
|
|
368
|
+
};
|
|
369
|
+
const successStyle = {
|
|
370
|
+
...bodyStyle$1,
|
|
371
|
+
color: "var(--dsw-alias-state-success-primary, #16825d)"
|
|
372
|
+
};
|
|
373
|
+
async function request(method, body) {
|
|
374
|
+
const response = await fetch(CODEX_GLOBAL_MODEL_PATH, {
|
|
375
|
+
method,
|
|
376
|
+
headers: {
|
|
377
|
+
accept: "application/json",
|
|
378
|
+
...body === void 0 ? {} : { "content-type": "application/json" }
|
|
379
|
+
},
|
|
380
|
+
...body === void 0 ? {} : { body: JSON.stringify(body) },
|
|
381
|
+
credentials: "same-origin"
|
|
382
|
+
});
|
|
383
|
+
const payload = await response.json().catch(() => void 0);
|
|
384
|
+
if (!response.ok) throw new Error(typeof payload === "object" && payload !== null && "error" in payload && typeof payload.error === "string" ? payload.error : `HTTP ${response.status}`);
|
|
385
|
+
return payload;
|
|
386
|
+
}
|
|
387
|
+
function codexModels(groups) {
|
|
388
|
+
return groups.find((group) => group.id === "openai-codex")?.models ?? [];
|
|
389
|
+
}
|
|
390
|
+
const choiceButtonStyle = {
|
|
391
|
+
boxSizing: "border-box",
|
|
392
|
+
display: "flex",
|
|
393
|
+
alignItems: "center",
|
|
394
|
+
justifyContent: "space-between",
|
|
395
|
+
gap: 8,
|
|
396
|
+
width: "100%",
|
|
397
|
+
minHeight: 34,
|
|
398
|
+
padding: "5px 9px",
|
|
399
|
+
border: "1px solid var(--dsw-alias-border-l2)",
|
|
400
|
+
borderRadius: 8,
|
|
401
|
+
background: "var(--dsw-alias-bg-layer-1)",
|
|
402
|
+
color: "var(--dsw-alias-label-primary)",
|
|
403
|
+
font: "inherit",
|
|
404
|
+
fontSize: 13,
|
|
405
|
+
textAlign: "left",
|
|
406
|
+
cursor: "pointer"
|
|
407
|
+
};
|
|
408
|
+
const choicePanelStyle = {
|
|
409
|
+
position: "absolute",
|
|
410
|
+
zIndex: 20,
|
|
411
|
+
top: "calc(100% + 6px)",
|
|
412
|
+
left: 0,
|
|
413
|
+
width: "max(100%, 220px)",
|
|
414
|
+
maxHeight: 260,
|
|
415
|
+
overflowY: "auto",
|
|
416
|
+
boxSizing: "border-box",
|
|
417
|
+
padding: 6,
|
|
418
|
+
border: "1px solid var(--dsw-alias-border-l1, var(--dsw-alias-border-l2))",
|
|
419
|
+
borderRadius: 10,
|
|
420
|
+
background: "var(--dsw-alias-bg-layer-3, var(--dsw-alias-bg-layer-2))",
|
|
421
|
+
boxShadow: "var(--dsw-alias-shadow-popover, 0 12px 30px rgb(0 0 0 / 24%))"
|
|
422
|
+
};
|
|
423
|
+
const choiceItemStyle = {
|
|
424
|
+
display: "flex",
|
|
425
|
+
alignItems: "center",
|
|
426
|
+
justifyContent: "space-between",
|
|
427
|
+
gap: 10,
|
|
428
|
+
width: "100%",
|
|
429
|
+
minHeight: 34,
|
|
430
|
+
padding: "6px 9px",
|
|
431
|
+
border: 0,
|
|
432
|
+
borderRadius: 7,
|
|
433
|
+
background: "transparent",
|
|
434
|
+
color: "var(--dsw-alias-label-primary)",
|
|
435
|
+
font: "inherit",
|
|
436
|
+
fontSize: 13,
|
|
437
|
+
textAlign: "left",
|
|
438
|
+
cursor: "pointer"
|
|
439
|
+
};
|
|
440
|
+
function ChevronDown() {
|
|
441
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
442
|
+
"aria-hidden": "true",
|
|
443
|
+
style: {
|
|
444
|
+
display: "inline-flex",
|
|
445
|
+
alignItems: "center",
|
|
446
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
447
|
+
lineHeight: 1
|
|
448
|
+
},
|
|
449
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { size: 14 })
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
const pickerButtonStyle = {
|
|
453
|
+
...choiceButtonStyle,
|
|
454
|
+
width: "fit-content",
|
|
455
|
+
maxWidth: "100%",
|
|
456
|
+
minHeight: 30,
|
|
457
|
+
padding: "3px 4px",
|
|
458
|
+
border: 0,
|
|
459
|
+
borderRadius: 7,
|
|
460
|
+
background: "transparent",
|
|
461
|
+
fontSize: 14
|
|
462
|
+
};
|
|
463
|
+
const pickerPanelStyle = {
|
|
464
|
+
...choicePanelStyle,
|
|
465
|
+
display: "flex",
|
|
466
|
+
position: "absolute",
|
|
467
|
+
gap: 0,
|
|
468
|
+
width: "min(210px, calc(100vw - 32px))",
|
|
469
|
+
maxHeight: 260,
|
|
470
|
+
padding: 5,
|
|
471
|
+
overflow: "visible"
|
|
472
|
+
};
|
|
473
|
+
const pickerColumnStyle = {
|
|
474
|
+
display: "flex",
|
|
475
|
+
width: "100%",
|
|
476
|
+
flexDirection: "column",
|
|
477
|
+
gap: 2
|
|
478
|
+
};
|
|
479
|
+
const pickerSubmenuStyle = {
|
|
480
|
+
position: "absolute",
|
|
481
|
+
zIndex: 1,
|
|
482
|
+
top: 5,
|
|
483
|
+
left: "calc(100% + 4px)",
|
|
484
|
+
width: "210px",
|
|
485
|
+
maxHeight: 250,
|
|
486
|
+
overflowY: "auto",
|
|
487
|
+
boxSizing: "border-box",
|
|
488
|
+
display: "flex",
|
|
489
|
+
flexDirection: "column",
|
|
490
|
+
gap: 2,
|
|
491
|
+
padding: 5,
|
|
492
|
+
border: "1px solid var(--dsw-alias-border-l1, var(--dsw-alias-border-l2))",
|
|
493
|
+
borderRadius: 10,
|
|
494
|
+
background: "var(--dsw-alias-bg-layer-3, var(--dsw-alias-bg-layer-2))",
|
|
495
|
+
boxShadow: "var(--dsw-alias-shadow-popover, 0 12px 30px rgb(0 0 0 / 24%))"
|
|
496
|
+
};
|
|
497
|
+
function PickerRow({ label, value, disabled, active, onClick }) {
|
|
498
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
499
|
+
type: "button",
|
|
500
|
+
disabled,
|
|
501
|
+
style: {
|
|
502
|
+
...choiceItemStyle,
|
|
503
|
+
minHeight: 34,
|
|
504
|
+
padding: "4px 8px",
|
|
505
|
+
background: active ? "var(--dsw-alias-interactive-bg-active, var(--dsw-alias-interactive-bg-hover))" : "transparent",
|
|
506
|
+
opacity: disabled ? .5 : 1,
|
|
507
|
+
cursor: disabled ? "not-allowed" : "pointer"
|
|
508
|
+
},
|
|
509
|
+
onMouseEnter: (event) => {
|
|
510
|
+
if (!disabled) event.currentTarget.style.background = "var(--dsw-alias-interactive-bg-hover, var(--dsw-alias-bg-layer-1))";
|
|
511
|
+
},
|
|
512
|
+
onMouseLeave: (event) => {
|
|
513
|
+
event.currentTarget.style.background = active ? "var(--dsw-alias-interactive-bg-active, var(--dsw-alias-interactive-bg-hover))" : "transparent";
|
|
514
|
+
},
|
|
515
|
+
onClick,
|
|
516
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
517
|
+
style: {
|
|
518
|
+
minWidth: 0,
|
|
519
|
+
overflow: "hidden",
|
|
520
|
+
textOverflow: "ellipsis",
|
|
521
|
+
whiteSpace: "nowrap",
|
|
522
|
+
fontSize: 13
|
|
523
|
+
},
|
|
524
|
+
children: label
|
|
525
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
526
|
+
style: {
|
|
527
|
+
display: "inline-flex",
|
|
528
|
+
alignItems: "center",
|
|
529
|
+
gap: 6,
|
|
530
|
+
minWidth: 0,
|
|
531
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
532
|
+
fontSize: 13
|
|
533
|
+
},
|
|
534
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
535
|
+
style: {
|
|
536
|
+
maxWidth: 140,
|
|
537
|
+
overflow: "hidden",
|
|
538
|
+
textOverflow: "ellipsis",
|
|
539
|
+
whiteSpace: "nowrap"
|
|
540
|
+
},
|
|
541
|
+
children: value
|
|
542
|
+
}), !disabled ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
543
|
+
"aria-hidden": "true",
|
|
544
|
+
style: {
|
|
545
|
+
fontSize: 18,
|
|
546
|
+
lineHeight: 1
|
|
547
|
+
},
|
|
548
|
+
children: "›"
|
|
549
|
+
}) : null]
|
|
550
|
+
})]
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
function GlobalModelPicker({ modelMenuLabel, effortMenuLabel, modelLabel, modelPlaceholder, effortLabel, selectedModelId, selectedEffortId, modelOptions, effortOptions, activeMenu, onToggle, onOpenSubmenu, onChooseModel, onChooseEffort }) {
|
|
554
|
+
const open = activeMenu !== null;
|
|
555
|
+
const modelValue = modelLabel === "" ? modelPlaceholder : modelLabel;
|
|
556
|
+
const buttonValue = effortLabel === "" ? modelValue : `${modelValue} · ${effortLabel}`;
|
|
557
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
558
|
+
style: {
|
|
559
|
+
position: "relative",
|
|
560
|
+
width: "fit-content",
|
|
561
|
+
maxWidth: "100%"
|
|
562
|
+
},
|
|
563
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
564
|
+
type: "button",
|
|
565
|
+
"aria-haspopup": "menu",
|
|
566
|
+
"aria-expanded": open,
|
|
567
|
+
style: pickerButtonStyle,
|
|
568
|
+
onClick: onToggle,
|
|
569
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
570
|
+
style: {
|
|
571
|
+
minWidth: 0,
|
|
572
|
+
overflow: "hidden",
|
|
573
|
+
textOverflow: "ellipsis",
|
|
574
|
+
whiteSpace: "nowrap",
|
|
575
|
+
color: modelLabel === "" ? "var(--dsw-alias-label-dimmed)" : "var(--dsw-alias-label-primary)"
|
|
576
|
+
},
|
|
577
|
+
children: buttonValue
|
|
578
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronDown, {})]
|
|
579
|
+
}), open ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
580
|
+
role: "menu",
|
|
581
|
+
style: pickerPanelStyle,
|
|
582
|
+
children: [
|
|
583
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
584
|
+
style: pickerColumnStyle,
|
|
585
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PickerRow, {
|
|
586
|
+
label: modelMenuLabel,
|
|
587
|
+
value: modelValue,
|
|
588
|
+
active: activeMenu === "model",
|
|
589
|
+
onClick: () => {
|
|
590
|
+
onOpenSubmenu("model");
|
|
591
|
+
}
|
|
592
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PickerRow, {
|
|
593
|
+
label: effortMenuLabel,
|
|
594
|
+
value: effortLabel,
|
|
595
|
+
active: activeMenu === "effort",
|
|
596
|
+
onClick: () => {
|
|
597
|
+
onOpenSubmenu("effort");
|
|
598
|
+
}
|
|
599
|
+
})]
|
|
600
|
+
}),
|
|
601
|
+
activeMenu === "model" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
602
|
+
role: "menu",
|
|
603
|
+
"aria-label": modelMenuLabel,
|
|
604
|
+
style: pickerSubmenuStyle,
|
|
605
|
+
children: modelOptions.map((option) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
606
|
+
type: "button",
|
|
607
|
+
role: "menuitemradio",
|
|
608
|
+
"aria-checked": option.id === selectedModelId,
|
|
609
|
+
style: option.id === selectedModelId ? {
|
|
610
|
+
...choiceItemStyle,
|
|
611
|
+
background: "var(--dsw-alias-interactive-bg-active, var(--dsw-alias-interactive-bg-hover))"
|
|
612
|
+
} : choiceItemStyle,
|
|
613
|
+
onClick: () => {
|
|
614
|
+
onChooseModel(option.id);
|
|
615
|
+
},
|
|
616
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
617
|
+
style: {
|
|
618
|
+
minWidth: 0,
|
|
619
|
+
overflow: "hidden",
|
|
620
|
+
textOverflow: "ellipsis",
|
|
621
|
+
whiteSpace: "nowrap"
|
|
622
|
+
},
|
|
623
|
+
children: option.label
|
|
624
|
+
}), option.id === selectedModelId ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
625
|
+
"aria-hidden": "true",
|
|
626
|
+
children: "✓"
|
|
627
|
+
}) : null]
|
|
628
|
+
}, option.id))
|
|
629
|
+
}) : null,
|
|
630
|
+
activeMenu === "effort" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
631
|
+
role: "menu",
|
|
632
|
+
"aria-label": effortMenuLabel,
|
|
633
|
+
style: pickerSubmenuStyle,
|
|
634
|
+
children: effortOptions.map((option) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
635
|
+
type: "button",
|
|
636
|
+
role: "menuitemradio",
|
|
637
|
+
"aria-checked": option.id === selectedEffortId,
|
|
638
|
+
style: option.id === selectedEffortId ? {
|
|
639
|
+
...choiceItemStyle,
|
|
640
|
+
background: "var(--dsw-alias-interactive-bg-active, var(--dsw-alias-interactive-bg-hover))"
|
|
641
|
+
} : choiceItemStyle,
|
|
642
|
+
onClick: () => {
|
|
643
|
+
onChooseEffort(option.id);
|
|
644
|
+
},
|
|
645
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: option.label }), option.id === selectedEffortId ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
646
|
+
"aria-hidden": "true",
|
|
647
|
+
children: "✓"
|
|
648
|
+
}) : null]
|
|
649
|
+
}, option.id))
|
|
650
|
+
}) : null
|
|
651
|
+
]
|
|
652
|
+
}) : null]
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
/** Set the model used by new DSH sessions and the host-backed agent entry point. */
|
|
656
|
+
function CodexGlobalModel({ connection, t }) {
|
|
657
|
+
const [models, setModels] = (0, react.useState)([]);
|
|
658
|
+
const [current, setCurrent] = (0, react.useState)();
|
|
659
|
+
const [draftModel, setDraftModel] = (0, react.useState)("");
|
|
660
|
+
const [draftEffort, setDraftEffort] = (0, react.useState)("");
|
|
661
|
+
const [status, setStatus] = (0, react.useState)("loading");
|
|
662
|
+
const [busy, setBusy] = (0, react.useState)(false);
|
|
663
|
+
const [feedback, setFeedback] = (0, react.useState)("idle");
|
|
664
|
+
const [openMenu, setOpenMenu] = (0, react.useState)(null);
|
|
665
|
+
const fieldsRef = (0, react.useRef)(null);
|
|
666
|
+
const load = (0, react.useCallback)(async () => {
|
|
667
|
+
setStatus("loading");
|
|
668
|
+
try {
|
|
669
|
+
const [global, catalog] = await Promise.all([request("GET"), connection.api.llm.models({})]);
|
|
670
|
+
if (!catalog.result.ok) throw new Error(catalog.result.error.message);
|
|
671
|
+
const available = codexModels(catalog.result.value.groups);
|
|
672
|
+
setModels(available);
|
|
673
|
+
setCurrent(global.globalModel);
|
|
674
|
+
setDraftModel(global.globalModel?.model ?? "");
|
|
675
|
+
setDraftEffort(global.globalModel?.reasoningEffort ?? "");
|
|
676
|
+
setStatus("ready");
|
|
677
|
+
} catch {
|
|
678
|
+
setStatus("error");
|
|
679
|
+
}
|
|
680
|
+
}, [connection]);
|
|
681
|
+
(0, react.useEffect)(() => {
|
|
682
|
+
load();
|
|
683
|
+
}, [load]);
|
|
684
|
+
(0, react.useEffect)(() => {
|
|
685
|
+
if (openMenu === null) return;
|
|
686
|
+
const onPointerDown = (event) => {
|
|
687
|
+
if (event.target instanceof Node && fieldsRef.current?.contains(event.target)) return;
|
|
688
|
+
setOpenMenu(null);
|
|
689
|
+
};
|
|
690
|
+
const onKeyDown = (event) => {
|
|
691
|
+
if (event.key === "Escape") setOpenMenu(null);
|
|
692
|
+
};
|
|
693
|
+
document.addEventListener("pointerdown", onPointerDown);
|
|
694
|
+
document.addEventListener("keydown", onKeyDown);
|
|
695
|
+
return () => {
|
|
696
|
+
document.removeEventListener("pointerdown", onPointerDown);
|
|
697
|
+
document.removeEventListener("keydown", onKeyDown);
|
|
698
|
+
};
|
|
699
|
+
}, [openMenu]);
|
|
700
|
+
const selected = (0, react.useMemo)(() => models.find((model) => model.id === draftModel), [draftModel, models]);
|
|
701
|
+
const efforts = selected?.reasoning?.efforts ?? [];
|
|
702
|
+
const modelLabel = selected?.name ?? draftModel;
|
|
703
|
+
const modelOptions = [
|
|
704
|
+
{
|
|
705
|
+
id: "",
|
|
706
|
+
label: t("globalModelUnset")
|
|
707
|
+
},
|
|
708
|
+
...draftModel !== "" && !models.some((model) => model.id === draftModel) ? [{
|
|
709
|
+
id: draftModel,
|
|
710
|
+
label: draftModel
|
|
711
|
+
}] : [],
|
|
712
|
+
...models.map((model) => ({
|
|
713
|
+
id: model.id,
|
|
714
|
+
label: model.name
|
|
715
|
+
}))
|
|
716
|
+
];
|
|
717
|
+
const effortOptions = [{
|
|
718
|
+
id: "",
|
|
719
|
+
label: t("globalModelProviderDefault")
|
|
720
|
+
}, ...efforts.map((effort) => ({
|
|
721
|
+
id: effort.id,
|
|
722
|
+
label: effort.name
|
|
723
|
+
}))];
|
|
724
|
+
const dirty = draftModel.length > 0 && (current?.model !== draftModel || (current?.reasoningEffort ?? "") !== draftEffort);
|
|
725
|
+
const save = async () => {
|
|
726
|
+
if (!dirty || busy) return;
|
|
727
|
+
setBusy(true);
|
|
728
|
+
setFeedback("idle");
|
|
729
|
+
try {
|
|
730
|
+
const result = await request("PUT", {
|
|
731
|
+
model: draftModel,
|
|
732
|
+
...draftEffort.length === 0 ? {} : { reasoningEffort: draftEffort }
|
|
733
|
+
});
|
|
734
|
+
setCurrent(result.globalModel);
|
|
735
|
+
setDraftModel(result.globalModel?.model ?? draftModel);
|
|
736
|
+
setDraftEffort(result.globalModel?.reasoningEffort ?? "");
|
|
737
|
+
setFeedback("saved");
|
|
738
|
+
} catch {
|
|
739
|
+
setFeedback("error");
|
|
740
|
+
} finally {
|
|
741
|
+
setBusy(false);
|
|
742
|
+
}
|
|
743
|
+
};
|
|
744
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
745
|
+
style: sectionStyle,
|
|
746
|
+
"aria-labelledby": "dsh-codex-global-model-title",
|
|
747
|
+
children: [
|
|
748
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
749
|
+
id: "dsh-codex-global-model-title",
|
|
750
|
+
style: headingStyle,
|
|
751
|
+
children: t("globalModelTitle")
|
|
752
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
753
|
+
style: {
|
|
754
|
+
...bodyStyle$1,
|
|
755
|
+
marginTop: 3
|
|
756
|
+
},
|
|
757
|
+
children: t("globalModelIntro")
|
|
758
|
+
})] }),
|
|
759
|
+
status === "loading" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
760
|
+
style: bodyStyle$1,
|
|
761
|
+
children: t("settingsLoading")
|
|
762
|
+
}) : null,
|
|
763
|
+
status === "error" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
764
|
+
style: errorStyle$1,
|
|
765
|
+
role: "alert",
|
|
766
|
+
children: t("globalModelLoadFailed")
|
|
767
|
+
}) : null,
|
|
768
|
+
status === "ready" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
769
|
+
ref: fieldsRef,
|
|
770
|
+
style: fieldsStyle,
|
|
771
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(GlobalModelPicker, {
|
|
772
|
+
modelMenuLabel: t("globalModelModel"),
|
|
773
|
+
effortMenuLabel: t("globalModelThinking"),
|
|
774
|
+
modelLabel,
|
|
775
|
+
modelPlaceholder: t("globalModelUnset"),
|
|
776
|
+
effortLabel: effortOptions.find((option) => option.id === draftEffort)?.label ?? t("globalModelProviderDefault"),
|
|
777
|
+
selectedModelId: draftModel,
|
|
778
|
+
selectedEffortId: draftEffort,
|
|
779
|
+
modelOptions,
|
|
780
|
+
effortOptions,
|
|
781
|
+
activeMenu: openMenu,
|
|
782
|
+
onToggle: () => {
|
|
783
|
+
setOpenMenu((current) => current === null ? "root" : null);
|
|
784
|
+
},
|
|
785
|
+
onOpenSubmenu: (menu) => {
|
|
786
|
+
setOpenMenu(menu);
|
|
787
|
+
},
|
|
788
|
+
onChooseModel: (id) => {
|
|
789
|
+
setDraftModel(id);
|
|
790
|
+
setDraftEffort("");
|
|
791
|
+
setFeedback("idle");
|
|
792
|
+
setOpenMenu(null);
|
|
793
|
+
},
|
|
794
|
+
onChooseEffort: (id) => {
|
|
795
|
+
setDraftEffort(id);
|
|
796
|
+
setFeedback("idle");
|
|
797
|
+
setOpenMenu(null);
|
|
798
|
+
}
|
|
799
|
+
}), selected === void 0 && modelLabel !== "" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
800
|
+
style: bodyStyle$1,
|
|
801
|
+
children: t("globalModelUnavailable")
|
|
802
|
+
}) : null]
|
|
803
|
+
}) : null,
|
|
804
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
805
|
+
style: actionsStyle,
|
|
806
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
807
|
+
"aria-live": "polite",
|
|
808
|
+
children: [feedback === "saved" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
809
|
+
style: successStyle,
|
|
810
|
+
children: t("settingsSaved")
|
|
811
|
+
}) : null, feedback === "error" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
812
|
+
style: errorStyle$1,
|
|
813
|
+
children: t("settingsSaveFailed")
|
|
814
|
+
}) : null]
|
|
815
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
816
|
+
style: {
|
|
817
|
+
display: "flex",
|
|
818
|
+
gap: 8
|
|
819
|
+
},
|
|
820
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
821
|
+
type: "button",
|
|
822
|
+
style: buttonStyle$1,
|
|
823
|
+
disabled: status === "loading" || busy,
|
|
824
|
+
onClick: () => {
|
|
825
|
+
load();
|
|
826
|
+
},
|
|
827
|
+
children: t("refreshUsage")
|
|
828
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
829
|
+
type: "button",
|
|
830
|
+
style: primaryButtonStyle$1,
|
|
831
|
+
disabled: !dirty || busy,
|
|
832
|
+
onClick: () => {
|
|
833
|
+
save();
|
|
834
|
+
},
|
|
835
|
+
children: busy ? t("saving") : t("setGlobalModel")
|
|
836
|
+
})]
|
|
837
|
+
})]
|
|
838
|
+
})
|
|
839
|
+
]
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
//#endregion
|
|
843
|
+
//#region src/client/copy-to-clipboard.ts
|
|
844
|
+
async function copyTextToClipboard(text, environment = {}) {
|
|
845
|
+
const navigatorRef = environment.navigator ?? globalThis.navigator;
|
|
846
|
+
const documentRef = environment.document ?? globalThis.document;
|
|
847
|
+
try {
|
|
848
|
+
if (typeof navigatorRef?.clipboard?.writeText === "function") {
|
|
849
|
+
await navigatorRef.clipboard.writeText(text);
|
|
850
|
+
return;
|
|
851
|
+
}
|
|
852
|
+
} catch {}
|
|
853
|
+
if (documentRef === void 0) throw new Error("Clipboard is unavailable");
|
|
854
|
+
const textarea = documentRef.createElement("textarea");
|
|
855
|
+
textarea.value = text;
|
|
856
|
+
textarea.setAttribute("readonly", "");
|
|
857
|
+
textarea.style.position = "fixed";
|
|
858
|
+
textarea.style.top = "0";
|
|
859
|
+
textarea.style.left = "-9999px";
|
|
860
|
+
textarea.style.opacity = "0";
|
|
861
|
+
documentRef.body.appendChild(textarea);
|
|
862
|
+
textarea.focus();
|
|
863
|
+
textarea.select();
|
|
864
|
+
try {
|
|
865
|
+
if (!documentRef.execCommand("copy")) throw new Error("Copy command was rejected");
|
|
866
|
+
} finally {
|
|
867
|
+
documentRef.body.removeChild(textarea);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
305
870
|
//#endregion
|
|
306
871
|
//#region src/client/CodexAuthCard.tsx
|
|
307
872
|
/** Expandable account card for the DSH Plugins settings section. */
|
|
@@ -485,7 +1050,7 @@ window.__ModuleLoader__.load({
|
|
|
485
1050
|
maxWidth: 192,
|
|
486
1051
|
height: 8,
|
|
487
1052
|
borderRadius: 999,
|
|
488
|
-
background: "
|
|
1053
|
+
background: "rgba(127, 127, 127, 0.28)"
|
|
489
1054
|
};
|
|
490
1055
|
const usageFillStyle = {
|
|
491
1056
|
height: "100%",
|
|
@@ -617,13 +1182,15 @@ window.__ModuleLoader__.load({
|
|
|
617
1182
|
})
|
|
618
1183
|
});
|
|
619
1184
|
}
|
|
620
|
-
/** Render a standalone login/logout card in the rc.
|
|
621
|
-
function CodexAuthCard({ t, configScope }) {
|
|
1185
|
+
/** Render a standalone login/logout card in the rc.8 keyed Plugin slot. */
|
|
1186
|
+
function CodexAuthCard({ t, configScope, connection }) {
|
|
622
1187
|
if (t === void 0) throw new Error("Codex auth card requires its translation function");
|
|
1188
|
+
if (connection === void 0) throw new Error("Codex auth card requires the DSH connection");
|
|
623
1189
|
const [open, setOpen] = (0, react.useState)(false);
|
|
624
1190
|
const [status, setStatus] = (0, react.useState)({ status: "loading" });
|
|
625
1191
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
626
1192
|
const [challenge, setChallenge] = (0, react.useState)();
|
|
1193
|
+
const [copyStatus, setCopyStatus] = (0, react.useState)("idle");
|
|
627
1194
|
const [usage, setUsage] = (0, react.useState)({ status: "hidden" });
|
|
628
1195
|
const refreshUsage = (0, react.useCallback)(async () => {
|
|
629
1196
|
if (status.status !== "signed-in") return;
|
|
@@ -641,7 +1208,10 @@ window.__ModuleLoader__.load({
|
|
|
641
1208
|
try {
|
|
642
1209
|
const next = await jsonRequest(CODEX_AUTH_STATUS_PATH);
|
|
643
1210
|
setStatus(next);
|
|
644
|
-
if (next.status !== "signing-in")
|
|
1211
|
+
if (next.status !== "signing-in") {
|
|
1212
|
+
setChallenge(void 0);
|
|
1213
|
+
setCopyStatus("idle");
|
|
1214
|
+
}
|
|
645
1215
|
} catch (error) {
|
|
646
1216
|
setStatus(error instanceof AccountRequestError && error.code === "remote-web-origin-not-trusted" ? { status: "remote-web-origin-not-trusted" } : {
|
|
647
1217
|
status: "error",
|
|
@@ -687,6 +1257,7 @@ window.__ModuleLoader__.load({
|
|
|
687
1257
|
setBusy(true);
|
|
688
1258
|
setStatus({ status: "signing-in" });
|
|
689
1259
|
setChallenge(void 0);
|
|
1260
|
+
setCopyStatus("idle");
|
|
690
1261
|
try {
|
|
691
1262
|
const next = await jsonRequest(CODEX_AUTH_LOGIN_PATH, "POST");
|
|
692
1263
|
setChallenge(next);
|
|
@@ -694,6 +1265,7 @@ window.__ModuleLoader__.load({
|
|
|
694
1265
|
} catch (error) {
|
|
695
1266
|
popup.close();
|
|
696
1267
|
setChallenge(void 0);
|
|
1268
|
+
setCopyStatus("idle");
|
|
697
1269
|
setStatus(error instanceof AccountRequestError && error.code === "remote-web-origin-not-trusted" ? { status: "remote-web-origin-not-trusted" } : {
|
|
698
1270
|
status: "error",
|
|
699
1271
|
message: error instanceof Error ? error.message : t("requestFailed")
|
|
@@ -709,6 +1281,7 @@ window.__ModuleLoader__.load({
|
|
|
709
1281
|
setStatus({ status: "signed-out" });
|
|
710
1282
|
setUsage({ status: "hidden" });
|
|
711
1283
|
setChallenge(void 0);
|
|
1284
|
+
setCopyStatus("idle");
|
|
712
1285
|
} catch (error) {
|
|
713
1286
|
setStatus({
|
|
714
1287
|
status: "error",
|
|
@@ -718,6 +1291,15 @@ window.__ModuleLoader__.load({
|
|
|
718
1291
|
setBusy(false);
|
|
719
1292
|
}
|
|
720
1293
|
};
|
|
1294
|
+
const copyAuthorizationCode = async () => {
|
|
1295
|
+
if (challenge === void 0) return;
|
|
1296
|
+
try {
|
|
1297
|
+
await copyTextToClipboard(challenge.userCode);
|
|
1298
|
+
setCopyStatus("copied");
|
|
1299
|
+
} catch {
|
|
1300
|
+
setCopyStatus("failed");
|
|
1301
|
+
}
|
|
1302
|
+
};
|
|
721
1303
|
const label = status.status === "signed-in" ? t("signedIn") : status.status === "loading" ? t("loading") : status.status === "signing-in" ? t("signingIn") : status.status === "remote-web-origin-not-trusted" ? t("remoteOrigin") : status.status === "error" ? t("requestFailed") : t("signedOut");
|
|
722
1304
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
723
1305
|
style: {
|
|
@@ -827,34 +1409,56 @@ window.__ModuleLoader__.load({
|
|
|
827
1409
|
flexDirection: "column",
|
|
828
1410
|
gap: 8
|
|
829
1411
|
},
|
|
830
|
-
children: [
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
alignItems: "center",
|
|
837
|
-
flexWrap: "wrap",
|
|
838
|
-
gap: 8
|
|
839
|
-
},
|
|
840
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
|
|
841
|
-
"aria-label": t("authorizationCodeLabel"),
|
|
842
|
-
style: codeStyle,
|
|
843
|
-
children: challenge.userCode
|
|
844
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
845
|
-
href: challenge.verificationUri,
|
|
846
|
-
target: "_blank",
|
|
847
|
-
rel: "noreferrer",
|
|
1412
|
+
children: [
|
|
1413
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1414
|
+
style: bodyStyle,
|
|
1415
|
+
children: t("authorizationCodeHelp")
|
|
1416
|
+
}),
|
|
1417
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
848
1418
|
style: {
|
|
849
|
-
|
|
850
|
-
display: "inline-flex",
|
|
1419
|
+
display: "flex",
|
|
851
1420
|
alignItems: "center",
|
|
852
|
-
|
|
1421
|
+
flexWrap: "wrap",
|
|
1422
|
+
gap: 8
|
|
853
1423
|
},
|
|
854
|
-
children:
|
|
855
|
-
|
|
856
|
-
|
|
1424
|
+
children: [
|
|
1425
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
|
|
1426
|
+
"aria-label": t("authorizationCodeLabel"),
|
|
1427
|
+
style: codeStyle,
|
|
1428
|
+
children: challenge.userCode
|
|
1429
|
+
}),
|
|
1430
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1431
|
+
type: "button",
|
|
1432
|
+
style: buttonStyle,
|
|
1433
|
+
onClick: () => {
|
|
1434
|
+
copyAuthorizationCode();
|
|
1435
|
+
},
|
|
1436
|
+
children: copyStatus === "copied" ? t("authorizationCodeCopied") : t("copyAuthorizationCode")
|
|
1437
|
+
}),
|
|
1438
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
1439
|
+
href: challenge.verificationUri,
|
|
1440
|
+
target: "_blank",
|
|
1441
|
+
rel: "noreferrer",
|
|
1442
|
+
style: {
|
|
1443
|
+
...buttonStyle,
|
|
1444
|
+
display: "inline-flex",
|
|
1445
|
+
alignItems: "center",
|
|
1446
|
+
textDecoration: "none"
|
|
1447
|
+
},
|
|
1448
|
+
children: t("openAuthorization")
|
|
1449
|
+
})
|
|
1450
|
+
]
|
|
1451
|
+
}),
|
|
1452
|
+
copyStatus === "failed" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1453
|
+
style: errorStyle,
|
|
1454
|
+
children: t("authorizationCodeCopyFailed")
|
|
1455
|
+
}) : null
|
|
1456
|
+
]
|
|
857
1457
|
}) : null,
|
|
1458
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodexGlobalModel, {
|
|
1459
|
+
connection,
|
|
1460
|
+
t
|
|
1461
|
+
}),
|
|
858
1462
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodexCapabilities, {
|
|
859
1463
|
scope: configScope,
|
|
860
1464
|
t
|
|
@@ -1160,7 +1764,7 @@ window.__ModuleLoader__.load({
|
|
|
1160
1764
|
};
|
|
1161
1765
|
const markModelNameInputsReadonly = () => {
|
|
1162
1766
|
const current = /* @__PURE__ */ new Set();
|
|
1163
|
-
for (const
|
|
1767
|
+
for (const editor of document.querySelectorAll(`[${CODEX_EDITOR_ATTRIBUTE}="true"]`)) for (const input of editor.querySelectorAll("input")) {
|
|
1164
1768
|
if (!startsWithAny(labelOf(input), MODEL_READONLY_LABELS)) continue;
|
|
1165
1769
|
current.add(input);
|
|
1166
1770
|
if (!originalModelNameAttributes.has(input)) originalModelNameAttributes.set(input, {
|
|
@@ -1423,8 +2027,8 @@ window.__ModuleLoader__.load({
|
|
|
1423
2027
|
}
|
|
1424
2028
|
};
|
|
1425
2029
|
const updatePickers = () => {
|
|
1426
|
-
markModelNameInputsReadonly();
|
|
1427
2030
|
markEditors();
|
|
2031
|
+
markModelNameInputsReadonly();
|
|
1428
2032
|
for (const [dialog] of originalPickerCopy) if (!document.contains(dialog)) originalPickerCopy.delete(dialog);
|
|
1429
2033
|
const dialogs = [...document.querySelectorAll("[role=\"dialog\"]")];
|
|
1430
2034
|
const activePicker = dialogs.find(isModelPicker);
|
|
@@ -1646,6 +2250,9 @@ window.__ModuleLoader__.load({
|
|
|
1646
2250
|
remoteOrigin: "This browser origin is not trusted by the DSH Web server.",
|
|
1647
2251
|
authorizationCodeHelp: "The plugin generated a one-time authorization code. Enter it on the opened Codex authorization page; no workspace selection is required.",
|
|
1648
2252
|
authorizationCodeLabel: "Codex authorization code",
|
|
2253
|
+
copyAuthorizationCode: "Copy",
|
|
2254
|
+
authorizationCodeCopied: "Copied",
|
|
2255
|
+
authorizationCodeCopyFailed: "Unable to copy the authorization code. Please select and copy it manually.",
|
|
1649
2256
|
openAuthorization: "Open authorization page",
|
|
1650
2257
|
usageTitle: "General usage limits",
|
|
1651
2258
|
refreshUsage: "Refresh",
|
|
@@ -1671,7 +2278,7 @@ window.__ModuleLoader__.load({
|
|
|
1671
2278
|
enableImageUpload: "Enable image upload",
|
|
1672
2279
|
enableImageUploadHelp: "Allow image-capable Codex models to receive images pasted or dropped into the conversation.",
|
|
1673
2280
|
enableImageGeneration: "Enable image generation",
|
|
1674
|
-
imageGenerationUnavailableHelp: "Not supported by the Codex provider and DSH rc.
|
|
2281
|
+
imageGenerationUnavailableHelp: "Not supported by the Codex provider and DSH rc.8 model adapter.",
|
|
1675
2282
|
settingsLoading: "Loading plugin settings…",
|
|
1676
2283
|
settingsUnavailable: "Plugin settings are unavailable in this dsh profile.",
|
|
1677
2284
|
settingsReadOnly: "This profile exposes plugin settings as read-only.",
|
|
@@ -1679,7 +2286,16 @@ window.__ModuleLoader__.load({
|
|
|
1679
2286
|
settingsSaveFailed: "Unable to save settings.",
|
|
1680
2287
|
discard: "Discard",
|
|
1681
2288
|
save: "Save",
|
|
1682
|
-
saving: "Saving…"
|
|
2289
|
+
saving: "Saving…",
|
|
2290
|
+
globalModelTitle: "Global model",
|
|
2291
|
+
globalModelIntro: "Choose the default Codex model for new DSH sessions.",
|
|
2292
|
+
globalModelModel: "Model",
|
|
2293
|
+
globalModelThinking: "Reasoning effort",
|
|
2294
|
+
globalModelProviderDefault: "Provider default",
|
|
2295
|
+
globalModelUnset: "Select a model",
|
|
2296
|
+
globalModelLoadFailed: "Unable to load the Codex model catalog.",
|
|
2297
|
+
globalModelUnavailable: "This model is no longer in the current catalog.",
|
|
2298
|
+
setGlobalModel: "Set as global model"
|
|
1683
2299
|
};
|
|
1684
2300
|
const zh = {
|
|
1685
2301
|
title: "Codex Auth",
|
|
@@ -1698,6 +2314,9 @@ window.__ModuleLoader__.load({
|
|
|
1698
2314
|
remoteOrigin: "当前浏览器来源未被 DSH Web 服务信任。",
|
|
1699
2315
|
authorizationCodeHelp: "插件已生成一次性授权码。请在打开的 Codex 授权页面中输入此代码,无需选择工作空间。",
|
|
1700
2316
|
authorizationCodeLabel: "Codex 授权码",
|
|
2317
|
+
copyAuthorizationCode: "复制",
|
|
2318
|
+
authorizationCodeCopied: "已复制",
|
|
2319
|
+
authorizationCodeCopyFailed: "授权码复制失败,请手动选中并复制。",
|
|
1701
2320
|
openAuthorization: "打开授权页面",
|
|
1702
2321
|
usageTitle: "通用使用限额",
|
|
1703
2322
|
refreshUsage: "刷新",
|
|
@@ -1723,7 +2342,7 @@ window.__ModuleLoader__.load({
|
|
|
1723
2342
|
enableImageUpload: "启用图片上传",
|
|
1724
2343
|
enableImageUploadHelp: "允许具备图片输入能力的 Codex 模型接收粘贴或拖入对话的图片。",
|
|
1725
2344
|
enableImageGeneration: "启用图像生成",
|
|
1726
|
-
imageGenerationUnavailableHelp: "当前 Codex 提供方和 DSH rc.
|
|
2345
|
+
imageGenerationUnavailableHelp: "当前 Codex 提供方和 DSH rc.8 模型适配器暂不支持图像输出。",
|
|
1727
2346
|
settingsLoading: "正在加载插件设置…",
|
|
1728
2347
|
settingsUnavailable: "此 dsh profile 无法使用插件设置。",
|
|
1729
2348
|
settingsReadOnly: "此 profile 的插件设置为只读。",
|
|
@@ -1731,7 +2350,16 @@ window.__ModuleLoader__.load({
|
|
|
1731
2350
|
settingsSaveFailed: "设置保存失败。",
|
|
1732
2351
|
discard: "放弃",
|
|
1733
2352
|
save: "保存",
|
|
1734
|
-
saving: "保存中…"
|
|
2353
|
+
saving: "保存中…",
|
|
2354
|
+
globalModelTitle: "全局模型",
|
|
2355
|
+
globalModelIntro: "设置新 DSH 会话使用的 Codex 默认模型。",
|
|
2356
|
+
globalModelModel: "模型",
|
|
2357
|
+
globalModelThinking: "思考强度",
|
|
2358
|
+
globalModelProviderDefault: "提供方默认",
|
|
2359
|
+
globalModelUnset: "请选择模型",
|
|
2360
|
+
globalModelLoadFailed: "加载 Codex 模型目录失败。",
|
|
2361
|
+
globalModelUnavailable: "当前模型已不在可用目录中。",
|
|
2362
|
+
setGlobalModel: "设置为全局模型"
|
|
1735
2363
|
};
|
|
1736
2364
|
//#endregion
|
|
1737
2365
|
//#region src/client/index.tsx
|
|
@@ -1751,7 +2379,8 @@ window.__ModuleLoader__.load({
|
|
|
1751
2379
|
en
|
|
1752
2380
|
}), "dsh-codex-auth-plugin: locale");
|
|
1753
2381
|
const t = ctx.locale.bind(namespace);
|
|
1754
|
-
const
|
|
2382
|
+
const connection = ctx.get("connection");
|
|
2383
|
+
const remoteScope = connection.isLoopback ? void 0 : new CodexAuthRemoteSettingsScope();
|
|
1755
2384
|
const configScope = remoteScope ?? ctx.settingsScope.bind({
|
|
1756
2385
|
namespace: "dsh-codex-auth",
|
|
1757
2386
|
decode: decodeCodexAuthSettings
|
|
@@ -1767,7 +2396,8 @@ window.__ModuleLoader__.load({
|
|
|
1767
2396
|
key: CODEX_AUTH_SETTINGS_NAMESPACE,
|
|
1768
2397
|
inject: () => ({
|
|
1769
2398
|
t,
|
|
1770
|
-
configScope
|
|
2399
|
+
configScope,
|
|
2400
|
+
connection
|
|
1771
2401
|
})
|
|
1772
2402
|
}, CodexAuthCard));
|
|
1773
2403
|
}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CODEX_AUTH_LOGIN_PATH, CODEX_AUTH_LOGOUT_PATH, CODEX_AUTH_SETTINGS_NAMESPACE, CODEX_AUTH_STATUS_PATH } from "./auth-paths.js";
|
|
1
|
+
import { CODEX_AUTH_LOGIN_PATH, CODEX_AUTH_LOGOUT_PATH, CODEX_AUTH_SETTINGS_NAMESPACE, CODEX_AUTH_STATUS_PATH, CODEX_GLOBAL_MODEL_PATH } from "./auth-paths.js";
|
|
2
2
|
import { a as CODEX_AUTH_FILENAME, c as codexAuthPath, i as logoutCodex, n as codexAuthStatus, o as CODEX_PROVIDER, r as loginCodex, s as CodexCredentialStore, t as CodexAuthStatus } from "./auth-BBBeI24-.js";
|
|
3
3
|
import { CredentialProvider } from "@deepseek-ai/dsh-credentials";
|
|
4
4
|
import "@deepseek-ai/dsh-settings";
|
|
@@ -124,4 +124,4 @@ declare const name = "dsh-codex-auth-plugin";
|
|
|
124
124
|
declare const inject: string[];
|
|
125
125
|
declare function apply(ctx: Context): void;
|
|
126
126
|
//#endregion
|
|
127
|
-
export { CODEX_API_KEY_ENV, CODEX_API_KEY_REF, CODEX_AUTH_FILENAME, CODEX_AUTH_LOGIN_PATH, CODEX_AUTH_LOGOUT_PATH, CODEX_AUTH_SETTINGS_NAMESPACE, CODEX_AUTH_STATUS_PATH, CODEX_PROVIDER, CODEX_STREAM_IDLE_TIMEOUT_MS, type CodexAuthStatus, CodexCredentialMirror, CodexCredentialStore, type CodexLoginChallenge, CodexUsageService, CodexWebAuth, type CodexWebAuthStatus, apply, codexAuthPath, codexAuthStatus, createCodexAdapter, inject, loginCodex, logoutCodex, name, normalizeCodexUsagePayload, registerCodexAuthRoutes, trustedRequest };
|
|
127
|
+
export { CODEX_API_KEY_ENV, CODEX_API_KEY_REF, CODEX_AUTH_FILENAME, CODEX_AUTH_LOGIN_PATH, CODEX_AUTH_LOGOUT_PATH, CODEX_AUTH_SETTINGS_NAMESPACE, CODEX_AUTH_STATUS_PATH, CODEX_GLOBAL_MODEL_PATH, CODEX_PROVIDER, CODEX_STREAM_IDLE_TIMEOUT_MS, type CodexAuthStatus, CodexCredentialMirror, CodexCredentialStore, type CodexLoginChallenge, CodexUsageService, CodexWebAuth, type CodexWebAuthStatus, apply, codexAuthPath, codexAuthStatus, createCodexAdapter, inject, loginCodex, logoutCodex, name, normalizeCodexUsagePayload, registerCodexAuthRoutes, trustedRequest };
|
package/lib/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as CODEX_PROVIDER, i as CODEX_AUTH_FILENAME, n as loginCodex, o as CodexCredentialStore, r as logoutCodex, s as codexAuthPath, t as codexAuthStatus } from "./auth-DQ2F4vc6.js";
|
|
2
|
-
import { CODEX_AUTH_LOGIN_PATH, CODEX_AUTH_LOGOUT_PATH, CODEX_AUTH_SETTINGS_NAMESPACE, CODEX_AUTH_SETTINGS_PATH, CODEX_AUTH_STATUS_PATH, CODEX_USAGE_PATH } from "./auth-paths.js";
|
|
2
|
+
import { CODEX_AUTH_LOGIN_PATH, CODEX_AUTH_LOGOUT_PATH, CODEX_AUTH_SETTINGS_NAMESPACE, CODEX_AUTH_SETTINGS_PATH, CODEX_AUTH_STATUS_PATH, CODEX_GLOBAL_MODEL_PATH, CODEX_USAGE_PATH } from "./auth-paths.js";
|
|
3
3
|
import { createModels } from "@earendil-works/pi-ai";
|
|
4
4
|
import { openaiCodexProvider } from "@earendil-works/pi-ai/providers/openai-codex";
|
|
5
5
|
import { basename } from "node:path";
|
|
@@ -158,6 +158,7 @@ const CODEX_AUTH_URL_TIMEOUT_MS = 3e4;
|
|
|
158
158
|
const REMOTE_WEB_ORIGIN_NOT_TRUSTED = "remote-web-origin-not-trusted";
|
|
159
159
|
const CODEX_USAGE_UNAVAILABLE = "codex-usage-unavailable";
|
|
160
160
|
const CODEX_SETTINGS_INVALID = "codex-settings-invalid";
|
|
161
|
+
const CODEX_GLOBAL_MODEL_INVALID = "codex-global-model-invalid";
|
|
161
162
|
const CODEX_SETTINGS_BODY_LIMIT = 8192;
|
|
162
163
|
function signedInStatus(expiresAt) {
|
|
163
164
|
return expiresAt === void 0 ? { status: "signed-in" } : {
|
|
@@ -393,6 +394,56 @@ function decodeSettingsWrite(value) {
|
|
|
393
394
|
if (typeof record["enableImageTool"] !== "boolean" || typeof record["enableImageUpload"] !== "boolean") return;
|
|
394
395
|
return decodeCodexAuthSettings(record);
|
|
395
396
|
}
|
|
397
|
+
function codexGlobalModelOf(selection) {
|
|
398
|
+
if (selection.provider !== "openai-codex") return void 0;
|
|
399
|
+
return {
|
|
400
|
+
model: selection.model,
|
|
401
|
+
...selection.reasoningEffort === void 0 ? {} : { reasoningEffort: selection.reasoningEffort }
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
function decodeGlobalModelWrite(value) {
|
|
405
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
406
|
+
const record = value;
|
|
407
|
+
if (typeof record.model !== "string" || record.model.trim().length === 0) return void 0;
|
|
408
|
+
if (record.reasoningEffort !== void 0 && (typeof record.reasoningEffort !== "string" || record.reasoningEffort.trim().length === 0)) return void 0;
|
|
409
|
+
return {
|
|
410
|
+
model: record.model.trim(),
|
|
411
|
+
...typeof record.reasoningEffort === "string" ? { reasoningEffort: record.reasoningEffort } : {}
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
/** Register the plugin-owned bridge to DSH rc.8's shared Agent default model. */
|
|
415
|
+
function registerCodexGlobalModelRoute(ctx, defaultModel, llm) {
|
|
416
|
+
ctx.effect(() => {
|
|
417
|
+
const authorize = (req, res) => {
|
|
418
|
+
if (trustedRequest(req)) return true;
|
|
419
|
+
json(res, 403, { error: REMOTE_WEB_ORIGIN_NOT_TRUSTED });
|
|
420
|
+
return false;
|
|
421
|
+
};
|
|
422
|
+
return ctx.webServer.register({
|
|
423
|
+
kind: "exact",
|
|
424
|
+
path: CODEX_GLOBAL_MODEL_PATH,
|
|
425
|
+
handler: async (req, res) => {
|
|
426
|
+
if (req.method !== "GET" && req.method !== "PUT") return json(res, 405, { error: "method not allowed" });
|
|
427
|
+
if (!authorize(req, res)) return;
|
|
428
|
+
if (req.method === "GET") return json(res, 200, { globalModel: codexGlobalModelOf(defaultModel.currentSelection()) });
|
|
429
|
+
try {
|
|
430
|
+
const next = decodeGlobalModelWrite(await readJsonBody(req));
|
|
431
|
+
if (next === void 0) return json(res, 400, { error: CODEX_GLOBAL_MODEL_INVALID });
|
|
432
|
+
const resolved = await llm.resolveCallConfig({
|
|
433
|
+
provider: CODEX_PROVIDER,
|
|
434
|
+
model: next.model,
|
|
435
|
+
...next.reasoningEffort === void 0 ? {} : { reasoningEffort: next.reasoningEffort }
|
|
436
|
+
});
|
|
437
|
+
if (resolved.provider !== "openai-codex") return json(res, 400, { error: CODEX_GLOBAL_MODEL_INVALID });
|
|
438
|
+
await defaultModel.saveSelection(resolved);
|
|
439
|
+
return json(res, 200, { globalModel: codexGlobalModelOf(defaultModel.currentSelection()) });
|
|
440
|
+
} catch (error) {
|
|
441
|
+
return json(res, 400, { error: safeMessage(error) });
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
}, "dsh-codex-auth-plugin: global Codex model route");
|
|
446
|
+
}
|
|
396
447
|
/** Register the plugin-owned settings endpoint for browsers opened through a NAS authority. */
|
|
397
448
|
function registerCodexSettingsRoute(ctx, settings) {
|
|
398
449
|
ctx.effect(() => {
|
|
@@ -768,7 +819,9 @@ const name = "dsh-codex-auth-plugin";
|
|
|
768
819
|
const inject = [
|
|
769
820
|
"webServer",
|
|
770
821
|
"settings",
|
|
771
|
-
"credentials"
|
|
822
|
+
"credentials",
|
|
823
|
+
"agentDefaultModel",
|
|
824
|
+
"llm"
|
|
772
825
|
];
|
|
773
826
|
function apply(ctx) {
|
|
774
827
|
const settings = ctx.settings.register(CODEX_AUTH_SETTINGS_NS, CodexAuthSettingsSchema);
|
|
@@ -788,6 +841,7 @@ function apply(ctx) {
|
|
|
788
841
|
}, "dsh-codex-auth: credential mirror");
|
|
789
842
|
registerCodexAuthRoutes(ctx, store, mirror);
|
|
790
843
|
registerCodexSettingsRoute(ctx, settings);
|
|
844
|
+
registerCodexGlobalModelRoute(ctx, ctx.agentDefaultModel, ctx.llm);
|
|
791
845
|
let stopped = false;
|
|
792
846
|
let imageFiber;
|
|
793
847
|
let imageTail = Promise.resolve();
|
|
@@ -830,4 +884,4 @@ function apply(ctx) {
|
|
|
830
884
|
scheduleImageTool();
|
|
831
885
|
}
|
|
832
886
|
//#endregion
|
|
833
|
-
export { CODEX_API_KEY_ENV, CODEX_API_KEY_REF, CODEX_AUTH_FILENAME, CODEX_AUTH_LOGIN_PATH, CODEX_AUTH_LOGOUT_PATH, CODEX_AUTH_SETTINGS_NAMESPACE, CODEX_AUTH_STATUS_PATH, CODEX_PROVIDER, CODEX_STREAM_IDLE_TIMEOUT_MS, CodexCredentialMirror, CodexCredentialStore, CodexUsageService, CodexWebAuth, apply, codexAuthPath, codexAuthStatus, createCodexAdapter, inject, loginCodex, logoutCodex, name, normalizeCodexUsagePayload, registerCodexAuthRoutes, trustedRequest };
|
|
887
|
+
export { CODEX_API_KEY_ENV, CODEX_API_KEY_REF, CODEX_AUTH_FILENAME, CODEX_AUTH_LOGIN_PATH, CODEX_AUTH_LOGOUT_PATH, CODEX_AUTH_SETTINGS_NAMESPACE, CODEX_AUTH_STATUS_PATH, CODEX_GLOBAL_MODEL_PATH, CODEX_PROVIDER, CODEX_STREAM_IDLE_TIMEOUT_MS, CodexCredentialMirror, CodexCredentialStore, CodexUsageService, CodexWebAuth, apply, codexAuthPath, codexAuthStatus, createCodexAdapter, inject, loginCodex, logoutCodex, name, normalizeCodexUsagePayload, registerCodexAuthRoutes, trustedRequest };
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@tnnevol/dsh-codex-auth",
|
|
3
3
|
"displayName": "Codex Auth",
|
|
4
4
|
"description": "Standalone ChatGPT OAuth account management for DeepSeek Harness.",
|
|
5
|
-
"version": "0.1.0-rc.8",
|
|
5
|
+
"version": "0.1.0-rc.8.2",
|
|
6
6
|
"author": "tnnevol",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
@@ -64,6 +64,7 @@
|
|
|
64
64
|
"@deepseek-ai/dsh-client-runtime",
|
|
65
65
|
"@deepseek-ai/dsh-client-ui-conversation",
|
|
66
66
|
"@deepseek-ai/dsh-client-ui-model-selection",
|
|
67
|
+
"@deepseek-ai/dsh-client-ui-primitives",
|
|
67
68
|
"@deepseek-ai/dsh-client-ui-settings",
|
|
68
69
|
"@deepseek-ai/dsh-client-ui-settings-plugins",
|
|
69
70
|
"@deepseek-ai/dsh-client-locale"
|
|
@@ -75,6 +76,7 @@
|
|
|
75
76
|
"@earendil-works/pi-ai": "0.82.1",
|
|
76
77
|
"@deepseek-ai/cordis": "^4.0.1-rc.1",
|
|
77
78
|
"@deepseek-ai/dsh-attachment": "0.1.0-rc.8",
|
|
79
|
+
"@deepseek-ai/dsh-agent-default-model": "0.1.0-rc.8",
|
|
78
80
|
"@deepseek-ai/dsh-atomic-write": "0.1.0-rc.8",
|
|
79
81
|
"@deepseek-ai/dsh-home-paths": "0.1.0-rc.8",
|
|
80
82
|
"@deepseek-ai/dsh-host-webserver": "0.1.0-rc.8",
|
|
@@ -85,6 +87,7 @@
|
|
|
85
87
|
"@deepseek-ai/dsh-tools": "0.1.0-rc.8",
|
|
86
88
|
"@deepseek-ai/dsh-client-locale": "0.1.0-rc.8",
|
|
87
89
|
"@deepseek-ai/dsh-client-runtime": "0.1.0-rc.8",
|
|
90
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.0-rc.8",
|
|
88
91
|
"@deepseek-ai/dsh-client-ui-settings": "0.1.0-rc.8",
|
|
89
92
|
"@deepseek-ai/dsh-client-ui-settings-plugins": "0.1.0-rc.8",
|
|
90
93
|
"@deepseek-ai/dsh-client-ui-slots": "0.1.0-rc.8",
|
|
@@ -99,6 +102,7 @@
|
|
|
99
102
|
"@earendil-works/pi-ai": "0.82.1",
|
|
100
103
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
101
104
|
"@deepseek-ai/dsh-api-remotes": "0.1.0-rc.8",
|
|
105
|
+
"@deepseek-ai/dsh-agent-default-model": "0.1.0-rc.8",
|
|
102
106
|
"@deepseek-ai/dsh-attachment": "0.1.0-rc.8",
|
|
103
107
|
"@deepseek-ai/dsh-atomic-write": "0.1.0-rc.8",
|
|
104
108
|
"@deepseek-ai/dsh-client-connection": "0.1.0-rc.8",
|
|
@@ -106,6 +110,7 @@
|
|
|
106
110
|
"@deepseek-ai/dsh-client-runtime": "0.1.0-rc.8",
|
|
107
111
|
"@deepseek-ai/dsh-client-ui-conversation": "0.1.0-rc.8",
|
|
108
112
|
"@deepseek-ai/dsh-client-ui-model-selection": "0.1.0-rc.8",
|
|
113
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.0-rc.8",
|
|
109
114
|
"@deepseek-ai/dsh-client-ui-settings": "0.1.0-rc.8",
|
|
110
115
|
"@deepseek-ai/dsh-client-ui-settings-plugins": "0.1.0-rc.8",
|
|
111
116
|
"@deepseek-ai/dsh-client-ui-slots": "0.1.0-rc.8",
|
|
@@ -128,4 +133,4 @@
|
|
|
128
133
|
"typescript": "^5.9.3",
|
|
129
134
|
"vitest": "^4.1.8"
|
|
130
135
|
}
|
|
131
|
-
}
|
|
136
|
+
}
|