@eddyskywalker/dsh-chatgpt-subscription 0.58.0 → 0.60.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/README.md +1 -1
- package/lib/client.js +1714 -255
- package/lib/client.js.map +1 -1
- package/lib/codemode.js +1952 -0
- package/lib/index.js +587 -243
- package/lib/llm-compat-u9mor0uu.js +110 -0
- package/lib/types/client/CodexImageToolView.d.ts.map +1 -1
- package/lib/types/client/codemode/CodeRunToolView.d.ts +68 -0
- package/lib/types/client/codemode/CodeRunToolView.d.ts.map +1 -0
- package/lib/types/client/codemode/highlight.d.ts +25 -0
- package/lib/types/client/codemode/highlight.d.ts.map +1 -0
- package/lib/types/client/codemode/styles.d.ts +11 -0
- package/lib/types/client/codemode/styles.d.ts.map +1 -0
- package/lib/types/client/codemode/tool-name.d.ts +10 -0
- package/lib/types/client/codemode/tool-name.d.ts.map +1 -0
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/locales-ru/hub.d.ts.map +1 -1
- package/lib/types/client/locales.d.ts +23 -1
- package/lib/types/client/locales.d.ts.map +1 -1
- package/lib/types/client/progress-updates/progress-row.d.ts.map +1 -1
- package/lib/types/client/styles.d.ts.map +1 -1
- package/lib/types/compat.d.ts +10 -1
- package/lib/types/compat.d.ts.map +1 -1
- package/lib/types/entry-codemode.d.ts +37 -0
- package/lib/types/entry-codemode.d.ts.map +1 -0
- package/lib/types/host/agent-preset.d.ts +24 -2
- package/lib/types/host/agent-preset.d.ts.map +1 -1
- package/lib/types/host/antigravity/image-tool.d.ts +10 -2
- package/lib/types/host/antigravity/image-tool.d.ts.map +1 -1
- package/lib/types/host/cache-warmup/install.d.ts +10 -4
- package/lib/types/host/cache-warmup/install.d.ts.map +1 -1
- package/lib/types/host/cache-warmup/projection.d.ts +17 -0
- package/lib/types/host/cache-warmup/projection.d.ts.map +1 -1
- package/lib/types/host/codemode/discovery.d.ts +33 -0
- package/lib/types/host/codemode/discovery.d.ts.map +1 -0
- package/lib/types/host/codemode/executor.d.ts +140 -0
- package/lib/types/host/codemode/executor.d.ts.map +1 -0
- package/lib/types/host/codemode/retention.d.ts +34 -0
- package/lib/types/host/codemode/retention.d.ts.map +1 -0
- package/lib/types/host/codemode/rules.d.ts +193 -0
- package/lib/types/host/codemode/rules.d.ts.map +1 -0
- package/lib/types/host/codemode/scope.d.ts +59 -0
- package/lib/types/host/codemode/scope.d.ts.map +1 -0
- package/lib/types/host/codemode/transport.d.ts +299 -0
- package/lib/types/host/codemode/transport.d.ts.map +1 -0
- package/lib/types/host/codex-images.d.ts +12 -0
- package/lib/types/host/codex-images.d.ts.map +1 -1
- package/lib/types/host/command-code/model-catalog.d.ts +14 -14
- package/lib/types/host/command-code/model-catalog.d.ts.map +1 -1
- package/lib/types/host/command-code/routes.d.ts.map +1 -1
- package/lib/types/host/preset-sync.d.ts +19 -4
- package/lib/types/host/preset-sync.d.ts.map +1 -1
- package/package.json +6 -1
- package/presets/dispatch/README.md +13 -6
- package/presets/dispatch/agent.cordis.yml +19 -16
- package/presets/dispatch/preset.yml +1 -1
package/lib/client.js
CHANGED
|
@@ -155,13 +155,41 @@ window.__ModuleLoader__.load({
|
|
|
155
155
|
}
|
|
156
156
|
//#endregion
|
|
157
157
|
//#region src/client/CodexImageToolView.tsx
|
|
158
|
+
/**
|
|
159
|
+
* Aspect ratios the Gemini image tool accepts in its `aspectRatio` argument.
|
|
160
|
+
*
|
|
161
|
+
* Mirrors `ANTIGRAVITY_IMAGE_ASPECT_RATIOS` in the host tool schema. The card
|
|
162
|
+
* only *sizes a placeholder* with it, so a drift here degrades to the default
|
|
163
|
+
* square instead of producing a wrong request — the value is never sent
|
|
164
|
+
* anywhere, and the host enum stays the single authority over what is legal.
|
|
165
|
+
*/
|
|
166
|
+
const IMAGE_ASPECT_RATIOS = /* @__PURE__ */ new Set([
|
|
167
|
+
"1:1",
|
|
168
|
+
"2:3",
|
|
169
|
+
"3:2",
|
|
170
|
+
"3:4",
|
|
171
|
+
"4:3",
|
|
172
|
+
"4:5",
|
|
173
|
+
"5:4",
|
|
174
|
+
"9:16",
|
|
175
|
+
"16:9",
|
|
176
|
+
"21:9",
|
|
177
|
+
"1:4",
|
|
178
|
+
"4:1",
|
|
179
|
+
"1:8",
|
|
180
|
+
"8:1"
|
|
181
|
+
]);
|
|
182
|
+
/** The model picks its own shape when the call names no ratio; the card guesses square. */
|
|
183
|
+
const DEFAULT_IMAGE_ASPECT_RATIO = "1:1";
|
|
184
|
+
/** The tray's short side, in px: a hint of the frame, not a billboard. */
|
|
185
|
+
const PLACEHOLDER_SHORT_SIDE = 112;
|
|
158
186
|
function CodexImageToolView({ block, loadImage, t }) {
|
|
159
187
|
const settled = "kind" in block;
|
|
160
188
|
const isError = settled ? block.isError : false;
|
|
161
|
-
const prompt = promptFromBlock$1(block);
|
|
162
189
|
const images = settled && !isError ? imageBlocks(block.content) : [];
|
|
163
190
|
const label = isError ? t("imageToolFailed") : settled ? t("imageToolDone") : t("imageToolRunning");
|
|
164
|
-
const summary =
|
|
191
|
+
const summary = promptFromBlock$1(block) ?? textSummary$1(settled ? block.content : []);
|
|
192
|
+
const tray = settled ? null : placeholderTray(aspectRatioFromBlock(block));
|
|
165
193
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
166
194
|
className: "dsh-codex-image-tool",
|
|
167
195
|
"data-state": isError ? "error" : settled ? "done" : "running",
|
|
@@ -174,12 +202,15 @@ window.__ModuleLoader__.load({
|
|
|
174
202
|
}),
|
|
175
203
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
176
204
|
className: "dsh-codex-image-title",
|
|
205
|
+
role: "status",
|
|
206
|
+
"aria-live": "polite",
|
|
177
207
|
children: label
|
|
178
208
|
}),
|
|
179
|
-
summary
|
|
209
|
+
summary === null ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
180
210
|
className: "dsh-codex-image-summary",
|
|
211
|
+
title: summary,
|
|
181
212
|
children: summary
|
|
182
|
-
})
|
|
213
|
+
})
|
|
183
214
|
]
|
|
184
215
|
}), images.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
185
216
|
className: "dsh-codex-image-grid",
|
|
@@ -189,7 +220,19 @@ window.__ModuleLoader__.load({
|
|
|
189
220
|
label: attachment.name ?? t("image"),
|
|
190
221
|
t
|
|
191
222
|
}, String(attachment.attachmentId)))
|
|
192
|
-
}) : null
|
|
223
|
+
}) : tray === null ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
224
|
+
className: "dsh-codex-image-grid",
|
|
225
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
226
|
+
className: "dsh-codex-image-placeholder",
|
|
227
|
+
"data-ratio": tray.ratio,
|
|
228
|
+
"data-short-side": tray.axis,
|
|
229
|
+
style: {
|
|
230
|
+
aspectRatio: tray.ratio.replace(":", " / "),
|
|
231
|
+
...tray.size
|
|
232
|
+
},
|
|
233
|
+
"aria-hidden": "true"
|
|
234
|
+
})
|
|
235
|
+
})]
|
|
193
236
|
});
|
|
194
237
|
}
|
|
195
238
|
function GeneratedImage({ attachment, load, label, t }) {
|
|
@@ -223,24 +266,64 @@ window.__ModuleLoader__.load({
|
|
|
223
266
|
});
|
|
224
267
|
}
|
|
225
268
|
function promptFromBlock$1(block) {
|
|
226
|
-
|
|
269
|
+
return argumentFromBlock(block, "prompt");
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Size the tray from one short side and let the ratio derive the other.
|
|
273
|
+
*
|
|
274
|
+
* A portrait frame fixes its height, and its width then stays narrow on its own.
|
|
275
|
+
* A landscape frame — and the 4:1 / 8:1 strips are exactly the case that forced
|
|
276
|
+
* this — fixes its width instead: deriving an 8:1 width from a 112px height
|
|
277
|
+
* would be 896px, which `max-width` would then clamp into a near-square box and
|
|
278
|
+
* the strip would stop looking like a strip. `min(…, 100%)` hands a narrow
|
|
279
|
+
* column back to the card and the height shrinks with it, so the shape survives
|
|
280
|
+
* the clamp.
|
|
281
|
+
*/
|
|
282
|
+
function placeholderTray(ratio) {
|
|
283
|
+
const [w, h] = ratio.split(":").map(Number);
|
|
284
|
+
return w !== void 0 && h !== void 0 && w >= h ? {
|
|
285
|
+
axis: "width",
|
|
286
|
+
ratio,
|
|
287
|
+
size: { width: `min(${Math.round(PLACEHOLDER_SHORT_SIDE * (w / h))}px, 100%)` }
|
|
288
|
+
} : {
|
|
289
|
+
axis: "height",
|
|
290
|
+
ratio,
|
|
291
|
+
size: { height: PLACEHOLDER_SHORT_SIDE }
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
/** The placeholder's shape: the call's own ratio when it is one the tool accepts. */
|
|
295
|
+
function aspectRatioFromBlock(block) {
|
|
296
|
+
const ratio = argumentFromBlock(block, "aspectRatio")?.trim();
|
|
297
|
+
return ratio !== void 0 && IMAGE_ASPECT_RATIOS.has(ratio) ? ratio : DEFAULT_IMAGE_ASPECT_RATIO;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* One string argument, read from whichever shape the current stage carries.
|
|
301
|
+
*
|
|
302
|
+
* While the arguments are still streaming, the harness hands over a lazy view
|
|
303
|
+
* instead of the JSON, so `args.text(key)` is tried first; once they are
|
|
304
|
+
* complete the same argument comes back as `argsRaw`.
|
|
305
|
+
*/
|
|
306
|
+
function argumentFromBlock(block, key) {
|
|
307
|
+
const partial = partialArgumentFromBlock(block, key);
|
|
227
308
|
if (partial !== null) return partial;
|
|
228
309
|
const raw = "kind" in block ? block.call?.argsRaw : dispatchedArgsRaw(block);
|
|
229
310
|
if (typeof raw !== "string" || raw.trim() === "") return null;
|
|
230
311
|
try {
|
|
231
312
|
const value = JSON.parse(raw);
|
|
232
|
-
|
|
313
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
|
|
314
|
+
const found = value[key];
|
|
315
|
+
return typeof found === "string" ? found : null;
|
|
233
316
|
} catch {
|
|
234
317
|
return null;
|
|
235
318
|
}
|
|
236
319
|
}
|
|
237
|
-
function
|
|
320
|
+
function partialArgumentFromBlock(block, key) {
|
|
238
321
|
if (!("args" in block)) return null;
|
|
239
322
|
const args = block.args;
|
|
240
323
|
if (typeof args?.text !== "function") return null;
|
|
241
324
|
try {
|
|
242
|
-
const
|
|
243
|
-
return typeof
|
|
325
|
+
const value = args.text.call(args, key);
|
|
326
|
+
return typeof value === "string" ? value : null;
|
|
244
327
|
} catch {
|
|
245
328
|
return null;
|
|
246
329
|
}
|
|
@@ -2895,10 +2978,10 @@ window.__ModuleLoader__.load({
|
|
|
2895
2978
|
"aria-label": label,
|
|
2896
2979
|
"data-copied": copied ? "true" : "false",
|
|
2897
2980
|
onClick,
|
|
2898
|
-
children: copied ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CheckIcon, {}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopyIcon, {})
|
|
2981
|
+
children: copied ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CheckIcon$1, {}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopyIcon$1, {})
|
|
2899
2982
|
});
|
|
2900
2983
|
}
|
|
2901
|
-
function CopyIcon() {
|
|
2984
|
+
function CopyIcon$1() {
|
|
2902
2985
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
2903
2986
|
viewBox: "0 0 16 16",
|
|
2904
2987
|
width: "14",
|
|
@@ -2922,7 +3005,7 @@ window.__ModuleLoader__.load({
|
|
|
2922
3005
|
})]
|
|
2923
3006
|
});
|
|
2924
3007
|
}
|
|
2925
|
-
function CheckIcon() {
|
|
3008
|
+
function CheckIcon$1() {
|
|
2926
3009
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
2927
3010
|
viewBox: "0 0 16 16",
|
|
2928
3011
|
width: "14",
|
|
@@ -7010,7 +7093,7 @@ window.__ModuleLoader__.load({
|
|
|
7010
7093
|
* rather than inferred from the JSX.
|
|
7011
7094
|
*/
|
|
7012
7095
|
/** The card's own dictionary; stable identity keeps effect dependencies intact. */
|
|
7013
|
-
const fallbackTranslate$
|
|
7096
|
+
const fallbackTranslate$6 = (key) => zh$11[key];
|
|
7014
7097
|
/**
|
|
7015
7098
|
* The shared pool card's labels, resolved through this card's dictionary.
|
|
7016
7099
|
*
|
|
@@ -7105,7 +7188,7 @@ window.__ModuleLoader__.load({
|
|
|
7105
7188
|
/** Device-code poll cadence. The host owns the real expiry. */
|
|
7106
7189
|
const LOGIN_POLL_INTERVAL_MS$3 = 2e3;
|
|
7107
7190
|
function useMinimaxCodeSection({ onModelChange }) {
|
|
7108
|
-
const t = fallbackTranslate$
|
|
7191
|
+
const t = fallbackTranslate$6;
|
|
7109
7192
|
const [status, setStatus] = (0, react.useState)(null);
|
|
7110
7193
|
const [loading, setLoading] = (0, react.useState)(true);
|
|
7111
7194
|
const [busy, setBusy] = (0, react.useState)(null);
|
|
@@ -8563,7 +8646,7 @@ window.__ModuleLoader__.load({
|
|
|
8563
8646
|
const { status, loading, busy, error, flow, copied, connectionNotice, contextDrafts, savingModel, pool, resetCards, resetNotice, selectedResetCardId } = state;
|
|
8564
8647
|
const { authenticated, account, quota, models, contextModels, overrideCount, poolLabels, resetCardList, resetCardFlows } = derived;
|
|
8565
8648
|
const { login, cancelLogin, copyCode, logout, poolAction, setStrategy, toggleModel, setAllModels, setCheckinEnabled, runCheckinNow, updateEffort, saveContextWindow, resetContextWindow, resetAllContextWindows, refreshQuota, refreshResetCards, selectResetCard, useResetCard, testConnection, updateContextDraft } = actions;
|
|
8566
|
-
const t = fallbackTranslate$
|
|
8649
|
+
const t = fallbackTranslate$6;
|
|
8567
8650
|
const videoDefaultsRef = react.default.useRef(null);
|
|
8568
8651
|
if (videoDefaultsRef.current === null) videoDefaultsRef.current = readVideoDefaults();
|
|
8569
8652
|
const saveVideoDefaults = react.default.useCallback((next) => {
|
|
@@ -9341,7 +9424,7 @@ window.__ModuleLoader__.load({
|
|
|
9341
9424
|
/** 登录状态机的轮询节奏。真实超时与间隔由 host 拥有,卡片只是跟随。 */
|
|
9342
9425
|
const LOGIN_POLL_INTERVAL_MS$2 = 2e3;
|
|
9343
9426
|
/** 本卡片的字典;身份稳定,依赖它的 effect 才不会每次渲染重建。 */
|
|
9344
|
-
const fallbackTranslate$
|
|
9427
|
+
const fallbackTranslate$5 = (key) => zh$10[key];
|
|
9345
9428
|
/**
|
|
9346
9429
|
* 共享账号池卡片需要的标签集,按本卡片的字典逐键查出来。
|
|
9347
9430
|
*
|
|
@@ -9405,7 +9488,7 @@ window.__ModuleLoader__.load({
|
|
|
9405
9488
|
});
|
|
9406
9489
|
}
|
|
9407
9490
|
function useGlmCodingPlanSection({ onModelChange } = {}) {
|
|
9408
|
-
const t = fallbackTranslate$
|
|
9491
|
+
const t = fallbackTranslate$5;
|
|
9409
9492
|
const [status, setStatus] = (0, react.useState)(null);
|
|
9410
9493
|
const [loading, setLoading] = (0, react.useState)(true);
|
|
9411
9494
|
const [busy, setBusy] = (0, react.useState)(null);
|
|
@@ -12494,7 +12577,7 @@ window.__ModuleLoader__.load({
|
|
|
12494
12577
|
/** 登录状态机的轮询节奏。真实超时与间隔由 host 拥有,卡片只是跟随。 */
|
|
12495
12578
|
const LOGIN_POLL_INTERVAL_MS$1 = 2e3;
|
|
12496
12579
|
/** 本卡片的字典;身份稳定,依赖它的 effect 才不会每次渲染重建。 */
|
|
12497
|
-
const fallbackTranslate$
|
|
12580
|
+
const fallbackTranslate$4 = (key) => zh$7[key];
|
|
12498
12581
|
/**
|
|
12499
12582
|
* 共享账号池卡片需要的标签集,按本卡片的字典逐键查出来。
|
|
12500
12583
|
*
|
|
@@ -12623,7 +12706,7 @@ window.__ModuleLoader__.load({
|
|
|
12623
12706
|
/** 写侧的线路常量;卡片用它渲染说明,而不是渲染一条永远为 0 的进度条。 */
|
|
12624
12707
|
const CACHE_WRITE_NOTE = STEP_CODE_CACHE_WRITE_NOTE;
|
|
12625
12708
|
function useStepCodeSection({ onModelChange } = {}) {
|
|
12626
|
-
const t = fallbackTranslate$
|
|
12709
|
+
const t = fallbackTranslate$4;
|
|
12627
12710
|
const [status, setStatus] = (0, react.useState)(null);
|
|
12628
12711
|
const [loading, setLoading] = (0, react.useState)(true);
|
|
12629
12712
|
const [busy, setBusy] = (0, react.useState)(null);
|
|
@@ -16296,7 +16379,7 @@ window.__ModuleLoader__.load({
|
|
|
16296
16379
|
/** 登录状态机的轮询节奏。真实超时与间隔由 host 拥有,卡片只是跟随。 */
|
|
16297
16380
|
const LOGIN_POLL_INTERVAL_MS = 2e3;
|
|
16298
16381
|
/** 本卡片的字典;身份稳定,依赖它的 effect 才不会每次渲染重建。 */
|
|
16299
|
-
const fallbackTranslate$
|
|
16382
|
+
const fallbackTranslate$3 = (key) => zh$5[key];
|
|
16300
16383
|
/**
|
|
16301
16384
|
* 共享账号池卡片需要的标签集,按本卡片的字典逐键查出来。
|
|
16302
16385
|
*
|
|
@@ -16395,7 +16478,7 @@ window.__ModuleLoader__.load({
|
|
|
16395
16478
|
return stats.cacheReadTokens / denominator;
|
|
16396
16479
|
}
|
|
16397
16480
|
function useQoderSection({ onModelChange } = {}) {
|
|
16398
|
-
const t = fallbackTranslate$
|
|
16481
|
+
const t = fallbackTranslate$3;
|
|
16399
16482
|
const [status, setStatus] = (0, react.useState)(null);
|
|
16400
16483
|
const [loading, setLoading] = (0, react.useState)(true);
|
|
16401
16484
|
const [busy, setBusy] = (0, react.useState)(null);
|
|
@@ -20940,217 +21023,229 @@ window.__ModuleLoader__.load({
|
|
|
20940
21023
|
//#endregion
|
|
20941
21024
|
//#region src/client/locales.ts
|
|
20942
21025
|
const NS = "dsh-chatgpt-subscription";
|
|
21026
|
+
const zh$2 = {
|
|
21027
|
+
...accountPoolZh,
|
|
21028
|
+
title: "ChatGPT",
|
|
21029
|
+
hubTitle: "订阅服务",
|
|
21030
|
+
intro: "使用 ChatGPT 账号登录,在 DSH 中使用订阅可用的模型。",
|
|
21031
|
+
account: "账号",
|
|
21032
|
+
signedOut: "尚未登录",
|
|
21033
|
+
signedIn: "已登录",
|
|
21034
|
+
plan: "套餐",
|
|
21035
|
+
accountId: "账号 ID",
|
|
21036
|
+
expires: "令牌到期",
|
|
21037
|
+
signIn: "使用 ChatGPT 登录",
|
|
21038
|
+
signInAgain: "重新登录",
|
|
21039
|
+
cancel: "取消登录",
|
|
21040
|
+
signOut: "注销",
|
|
21041
|
+
refreshToken: "刷新凭据",
|
|
21042
|
+
pending: "请在浏览器中完成登录。",
|
|
21043
|
+
popupBlocked: "浏览器拦截了登录窗口,请使用下面的链接继续。",
|
|
21044
|
+
continueLogin: "打开 ChatGPT 登录页",
|
|
21045
|
+
loading: "正在读取状态…",
|
|
21046
|
+
connection: "连接",
|
|
21047
|
+
testConnection: "测试连接",
|
|
21048
|
+
testing: "测试中…",
|
|
21049
|
+
latency: "最近延迟",
|
|
21050
|
+
selectAll: "全选",
|
|
21051
|
+
unselectAll: "全不选",
|
|
21052
|
+
models: "可用模型",
|
|
21053
|
+
modelsHint: "勾选后模型才会显示在对话页的模型选择列表中;全部取消勾选或关闭上方开关可在列表中隐藏该供应商。",
|
|
21054
|
+
proxySettings: "网络代理",
|
|
21055
|
+
proxyMode: "代理模式",
|
|
21056
|
+
proxyModeHint: "本插件的全部供应线路共用这一份代理设置,登录、令牌续期、模型目录与配额读取同样经过它;支持自动读取系统代理,修改后对后续请求生效。",
|
|
21057
|
+
proxyModeAuto: "系统代理(自动检测)",
|
|
21058
|
+
proxyModeCustom: "自定义代理",
|
|
21059
|
+
proxyModeDirect: "直连(禁用代理)",
|
|
21060
|
+
customProxyUrl: "自定义代理地址",
|
|
21061
|
+
customProxyUrlHint: "支持 HTTP/HTTPS/SOCKS5 代理地址,例如 http://127.0.0.1:7890",
|
|
21062
|
+
customProxyUrlPlaceholder: "例如: http://127.0.0.1:7890",
|
|
21063
|
+
saveProxyUrl: "保存代理地址",
|
|
21064
|
+
proxyDetected: "检测到系统代理",
|
|
21065
|
+
proxyDetectedEffective: "(已自动生效)",
|
|
21066
|
+
proxyNoneDetected: "未检测到系统代理,将使用直连",
|
|
21067
|
+
proxyDirectHint: "本插件的全部请求将直接连接,不经过任何代理服务器。",
|
|
21068
|
+
poolStorageTitle: "账号存储位置",
|
|
21069
|
+
poolStorageKeyring: "桌面密钥环",
|
|
21070
|
+
poolStorageCredentials: "DSH 凭据库",
|
|
21071
|
+
poolStorageKeyringHint: "仅限桌面安装:使用操作系统密钥环(DPAPI / 钥匙串 / Secret Service)。在服务器或无桌面的 Linux 主机上密钥环通常不可用,登录会失败——请改选 DSH 凭据库。",
|
|
21072
|
+
poolStorageCredentialsHint: "DSH 的标准密钥存储($DSH_HOME/.credentials.yaml)。POSIX 上强制 0600、创建者独占;Windows 上只有 profile ACL,没有权限位可强制。服务器以及任何没有桌面密钥环的主机都用它。静态不加密,靠宿主权限保护。",
|
|
21073
|
+
poolStorageEffective: "当前实际使用:{storage}",
|
|
21074
|
+
poolStorageBackendKeyring: "桌面密钥环(Secret Service),静态加密",
|
|
21075
|
+
poolStorageBackendDpapi: "Windows DPAPI,静态加密",
|
|
21076
|
+
poolStorageBackendKeychain: "macOS 钥匙串,静态加密",
|
|
21077
|
+
poolStorageBackendCredentials: "DSH 凭据库(.credentials.yaml),由文件权限保护",
|
|
21078
|
+
poolStorageSwitchWarning: "已保存在另一个存储里的账号会留在原处,切回去之前不会显示。不会做迁移。",
|
|
21079
|
+
poolStorageUnavailableKeyring: "这台主机上没有可用的桌面密钥环,因此号池无法读写。请把「账号存储位置」改成 DSH 凭据库。",
|
|
21080
|
+
poolStorageUnavailableCredentials: "这个 harness 没有凭据库(ctx.credentials),因此号池无法读写。请把「账号存储位置」改成桌面密钥环。",
|
|
21081
|
+
poolStorageUnavailableStore: "号池存储这次没有应答,所以这里没有列出账号——账号并没有被删除,存储恢复后重新打开本页即可。",
|
|
21082
|
+
enhancements: "增强功能",
|
|
21083
|
+
fastMode: "快速模式(1.5x 速度)",
|
|
21084
|
+
fastModeHint: "提升 Token 生成速度至约 1.5 倍;将以约 2x–2.5x 速度消耗 Codex 订阅额度。",
|
|
21085
|
+
outputVerbosity: "输出详细程度",
|
|
21086
|
+
outputVerbosityHint: "控制 Codex 最终回答的详细程度;不影响思考深度。默认值与官方 Codex 客户端一致(低)。",
|
|
21087
|
+
verbosityLow: "低(保持回答简洁)",
|
|
21088
|
+
verbosityMedium: "中(兼顾细节与简洁)",
|
|
21089
|
+
verbosityHigh: "高(在回答中包含更多细节)",
|
|
21090
|
+
reasoningSummary: "推理摘要",
|
|
21091
|
+
reasoningSummaryHint: "选择 ChatGPT 总结其推理的方式;不影响思考深度。默认值与官方 Codex 客户端一致(不生成摘要,可省额度)。",
|
|
21092
|
+
summaryAuto: "自动(让模型选择摘要详细程度)",
|
|
21093
|
+
summaryConcise: "简洁(显示简要推理摘要)",
|
|
21094
|
+
summaryDetailed: "详细(显示更详细的推理摘要)",
|
|
21095
|
+
summaryNone: "无(不显示推理摘要)",
|
|
21096
|
+
searchProvider: "搜索来源",
|
|
21097
|
+
searchProviderHint: "选择 DSH 联网搜索使用默认来源,或改用当前 ChatGPT 订阅的 Codex 来源(自动走代理隧道)。抓取模式为 auto 时,抓取来源跟随此选择。",
|
|
21098
|
+
searchProviderDsh: "DSH 默认",
|
|
21099
|
+
searchProviderCodex: "ChatGPT(代理隧道)",
|
|
21100
|
+
fetchStatus: "抓取来源(只读)",
|
|
21101
|
+
fetchStatusHint: "以下内容由 Host 上报,只读展示。",
|
|
21102
|
+
fetchConfiguredProvider: "配置的抓取 Provider",
|
|
21103
|
+
fetchProviderDshDefault: "DSH 默认(Host 未固定抓取 provider)",
|
|
21104
|
+
switcherState: "抓取选择器状态",
|
|
21105
|
+
switcherStateIdle: "空闲(尚未应用选择)",
|
|
21106
|
+
switcherStateApplying: "应用中(正在切换 Host 的 web provider)",
|
|
21107
|
+
switcherStateApplied: "已应用",
|
|
21108
|
+
switcherStateMissing: "未找到可切换的 web 服务",
|
|
21109
|
+
switcherStateFailed: "切换失败,请检查 Host 日志",
|
|
21110
|
+
fetchMode: "抓取模式",
|
|
21111
|
+
fetchModeAuto: "auto(有可用代理或选了 ChatGPT 搜索时用插件抓取)",
|
|
21112
|
+
fetchModePlugin: "plugin(始终用本插件抓取)",
|
|
21113
|
+
fetchModeDsh: "dsh(保留 DSH 原有抓取来源)",
|
|
21114
|
+
fetchMaxBodyChars: "插件正文上限",
|
|
21115
|
+
fetchMaxResponseBytes: "插件响应体上限",
|
|
21116
|
+
characters: "字符",
|
|
21117
|
+
bytes: "字节",
|
|
21118
|
+
fetchLimitsInactive: "仅在实际使用插件抓取时生效;走 DSH 原有抓取来源时不适用这两个上限。",
|
|
21119
|
+
fetchConfigSource: "模式与上限在插件 Config 中修改(不是本页面偏好),修改后重载插件或重启 DSH 生效。",
|
|
21120
|
+
providerDefault: "使用 Provider 默认值",
|
|
21121
|
+
contextWindows: "模型上下文窗口",
|
|
21122
|
+
contextWindowsHint: "只列出已勾选「可用模型」的条目。默认取模型目录值(GPT-6 系列 384K,最高 872K;其余最高 1M),该值用于 DSH 的压缩与溢出判断,可输入 872K、512K 等容量;改过的模型可单独或一键恢复默认。",
|
|
21123
|
+
contextWindow: "上下文窗口",
|
|
21124
|
+
contextWindowInvalid: "上下文窗口必须是正整数,且不能超过模型上限(GPT-6 系列为 872K,其余为 1M);可使用 K 或 M 后缀。",
|
|
21125
|
+
contextWindowReset: "恢复默认",
|
|
21126
|
+
contextWindowResetAll: "全部恢复默认",
|
|
21127
|
+
contextWindowResetAllConfirm: "确定把已改过的模型上下文窗口全部恢复为默认值吗?",
|
|
21128
|
+
contextWindowsNoneEnabled: "还没有勾选任何模型。在上方「可用模型」里勾选后,这里会出现该模型的上下文窗口设置。",
|
|
21129
|
+
saveContextWindow: "保存上下文窗口",
|
|
21130
|
+
save: "保存",
|
|
21131
|
+
tokens: "tokens",
|
|
21132
|
+
quickQuota: "在输入框旁显示快捷用量",
|
|
21133
|
+
quickQuotaHint: "仅在当前会话选中 codex-chatgpt 模型时显示。",
|
|
21134
|
+
quota: "用量与限额",
|
|
21135
|
+
quotaIntro: "数据来自 ChatGPT Codex 用量服务。页面可见时最多每 60 秒刷新一次。",
|
|
21136
|
+
refreshQuota: "刷新用量",
|
|
21137
|
+
refreshing: "刷新中…",
|
|
21138
|
+
noQuota: "当前套餐未返回可显示的限额窗口。",
|
|
21139
|
+
quotaSignedOut: "登录后可查看订阅限额。",
|
|
21140
|
+
stale: "显示的是上次成功获取的数据。",
|
|
21141
|
+
updated: "更新时间",
|
|
21142
|
+
primary: "主要窗口",
|
|
21143
|
+
secondary: "次要窗口",
|
|
21144
|
+
limitWindow: "额度",
|
|
21145
|
+
used: "已使用",
|
|
21146
|
+
remaining: "剩余",
|
|
21147
|
+
available: "可用",
|
|
21148
|
+
unavailable: "不可用",
|
|
21149
|
+
unlimited: "无限",
|
|
21150
|
+
credits: "Credits",
|
|
21151
|
+
monthlySpend: "月度消费控制",
|
|
21152
|
+
resetCredits: "重置次数",
|
|
21153
|
+
resetCreditExpires: "到期时间",
|
|
21154
|
+
useResetCredit: "使用重置卡",
|
|
21155
|
+
usingResetCredit: "使用中…",
|
|
21156
|
+
useResetCreditConfirm: "使用后会立即消耗 1 次重置机会,并重置符合条件的 Codex 额度窗口。确定继续吗?",
|
|
21157
|
+
resetCreditUsed: "重置卡已使用,用量数据已刷新。",
|
|
21158
|
+
spendControlReached: "已触发月度消费控制,新的订阅调用可能被限制。",
|
|
21159
|
+
limit: "上限",
|
|
21160
|
+
exhausted: "额度已用尽",
|
|
21161
|
+
resets: "重置",
|
|
21162
|
+
quickQuotaLabel: "Codex 剩余",
|
|
21163
|
+
quickQuotaLoading: "用量…",
|
|
21164
|
+
imageToolRunning: "正在生成图片",
|
|
21165
|
+
imageToolDone: "已生成图片",
|
|
21166
|
+
imageToolFailed: "图片生成失败",
|
|
21167
|
+
image: "图片",
|
|
21168
|
+
openImage: "打开图片",
|
|
21169
|
+
openNamedImage: "打开 {name}",
|
|
21170
|
+
imageLoading: "加载图片…",
|
|
21171
|
+
imageLoadFailed: "图片加载失败,点击重试",
|
|
21172
|
+
imagePreviewClose: "关闭",
|
|
21173
|
+
imagePreviewOpenOriginal: "打开原图",
|
|
21174
|
+
retry: "重试",
|
|
21175
|
+
unknown: "未知",
|
|
21176
|
+
hubBack: "订阅服务",
|
|
21177
|
+
hubOverviewHint: "选择供应商以管理账号、模型与配额;右侧开关控制该供应商是否出现在模型列表中。",
|
|
21178
|
+
hubAccountCount: "{count} 个账号",
|
|
21179
|
+
hubNoAccounts: "暂无账号,点击进入添加",
|
|
21180
|
+
hubStateEnabled: "已启用",
|
|
21181
|
+
hubStateDisabled: "已停用",
|
|
21182
|
+
hubModelsEnabled: "{count} 个模型可用",
|
|
21183
|
+
hubModelsEnabledOfTotal: "{count}/{total} 个模型可用",
|
|
21184
|
+
hubStatusFailed: "状态读取失败",
|
|
21185
|
+
hubSwitchOn: "启用 {name}",
|
|
21186
|
+
hubSwitchOff: "停用 {name}",
|
|
21187
|
+
hubCardLabel: "{name},{annotation}",
|
|
21188
|
+
hubUpdateCheck: "检测更新",
|
|
21189
|
+
hubUpdateChecking: "检测中…",
|
|
21190
|
+
hubUpdateApply: "更新到 v{version}",
|
|
21191
|
+
hubUpdateApplying: "更新中…",
|
|
21192
|
+
hubUpdateUpToDate: "已是最新版本 {version}",
|
|
21193
|
+
hubUpdateLatestWithUnknownCurrent: "最新版本 {version},当前版本未知",
|
|
21194
|
+
hubUpdateAvailable: "有新版本 {version},当前 {current}",
|
|
21195
|
+
hubUpdateInstalled: "已安装 v{version},重启宿主后生效",
|
|
21196
|
+
hubUpdateInstalledReplaced: "已移除旧版并安装 v{version},重启宿主后生效",
|
|
21197
|
+
hubUpdateInstalledLive: "已安装 v{version},当前已生效,无需重启",
|
|
21198
|
+
hubUpdateInstalledReplacedLive: "已移除旧版并安装 v{version},当前已生效,无需重启",
|
|
21199
|
+
hubUpdateFailedRestored: "更新失败,已恢复 v{version}",
|
|
21200
|
+
hubUpdateFailedRollbackFailed: "更新失败,且旧版本也没能重新装回来——插件可能已不可用",
|
|
21201
|
+
hubUpdateFailedRollbackSkipped: "更新失败,且无法自动恢复原版本——插件可能已被移除",
|
|
21202
|
+
hubUpdateDevelopmentInstall: "有新版本 {version};当前是本地链接安装,无法自动更新",
|
|
21203
|
+
hubUpdatePluginManagerMissing: "有新版本 {version};宿主未提供 pluginManager,无法自动更新",
|
|
21204
|
+
hubUpdateManualOnly: "有新版本 {version};当前安装方式无法自动更新",
|
|
21205
|
+
hubUpdateCheckFailed: "检测失败:无法连接 npm 源,请检查网络或代理",
|
|
21206
|
+
hubUpdateCommandLabel: "手动更新命令",
|
|
21207
|
+
localCodexLoginImport: "导入本机登录",
|
|
21208
|
+
localCodexLoginImporting: "导入中…",
|
|
21209
|
+
deviceCodeLogin: "设备代码登录",
|
|
21210
|
+
deviceCodeLoginStarting: "获取代码…",
|
|
21211
|
+
deviceCodeLoginDetail: "用设备代码添加账号",
|
|
21212
|
+
deviceCodeHint: "在任意设备上打开下面的链接并输入这个代码,本页会自动完成登录:这条路不需要浏览器回调到本机端口。",
|
|
21213
|
+
deviceCodeLabel: "设备代码",
|
|
21214
|
+
deviceCodeOpen: "打开确认页面",
|
|
21215
|
+
deviceCodeCopy: "复制到剪贴板",
|
|
21216
|
+
deviceCodeWaiting: "等待确认… 剩余 {time}",
|
|
21217
|
+
stopImporting: "停止导入全部本机登录",
|
|
21218
|
+
stopImportingLabel: "停止导入全部本机登录(当前 {count} 个)",
|
|
21219
|
+
stopImportingBusy: "停止导入中…",
|
|
21220
|
+
stopImportingHint: "停止导入只会让本插件忘记本机 CLI 登录的副本;Codex CLI 自己的登录文件不会被删除或修改。账号池不允许逐条删除借来的凭据,所以这里一次会停止全部导入。",
|
|
21221
|
+
"cardName.chatgpt": "ChatGPT",
|
|
21222
|
+
"cardName.antigravity": "Antigravity",
|
|
21223
|
+
"cardName.command-code": "Command Code",
|
|
21224
|
+
"cardName.kimi-code": "Kimi Code",
|
|
21225
|
+
"cardName.minimax-code": "MiniMax Code",
|
|
21226
|
+
"cardName.glm-coding-plan": "GLM(ZCode 账号)",
|
|
21227
|
+
"cardName.claude": "Claude",
|
|
21228
|
+
"cardName.ollama": "Ollama",
|
|
21229
|
+
"cardName.step-code": "Step Code(Step Plan 订阅)",
|
|
21230
|
+
"cardName.cline-pass": "Cline Pass",
|
|
21231
|
+
"cardName.qoder": "Qoder(订阅)",
|
|
21232
|
+
"cardName.opendesign": "OpenDesign",
|
|
21233
|
+
"cardName.workbuddy": "WorkBuddy",
|
|
21234
|
+
modelChecklistCount: "已启用 {count}/{total}",
|
|
21235
|
+
codeRunTitle: "代码",
|
|
21236
|
+
codeRunOutput: "输出",
|
|
21237
|
+
codeRunCopy: "复制",
|
|
21238
|
+
codeRunCopied: "已复制",
|
|
21239
|
+
codeRunWrap: "自动换行",
|
|
21240
|
+
codeRunUnwrap: "取消自动换行",
|
|
21241
|
+
codeRunInspect: "查看轨迹",
|
|
21242
|
+
codeRunPreparing: "准备中",
|
|
21243
|
+
codeRunRunning: "运行中",
|
|
21244
|
+
codeRunFailed: "失败",
|
|
21245
|
+
codeRunStopped: "已停止"
|
|
21246
|
+
};
|
|
20943
21247
|
const dictionaries$2 = {
|
|
20944
|
-
zh:
|
|
20945
|
-
...accountPoolZh,
|
|
20946
|
-
title: "ChatGPT",
|
|
20947
|
-
hubTitle: "订阅服务",
|
|
20948
|
-
intro: "使用 ChatGPT 账号登录,在 DSH 中使用订阅可用的模型。",
|
|
20949
|
-
account: "账号",
|
|
20950
|
-
signedOut: "尚未登录",
|
|
20951
|
-
signedIn: "已登录",
|
|
20952
|
-
plan: "套餐",
|
|
20953
|
-
accountId: "账号 ID",
|
|
20954
|
-
expires: "令牌到期",
|
|
20955
|
-
signIn: "使用 ChatGPT 登录",
|
|
20956
|
-
signInAgain: "重新登录",
|
|
20957
|
-
cancel: "取消登录",
|
|
20958
|
-
signOut: "注销",
|
|
20959
|
-
refreshToken: "刷新凭据",
|
|
20960
|
-
pending: "请在浏览器中完成登录。",
|
|
20961
|
-
popupBlocked: "浏览器拦截了登录窗口,请使用下面的链接继续。",
|
|
20962
|
-
continueLogin: "打开 ChatGPT 登录页",
|
|
20963
|
-
loading: "正在读取状态…",
|
|
20964
|
-
connection: "连接",
|
|
20965
|
-
testConnection: "测试连接",
|
|
20966
|
-
testing: "测试中…",
|
|
20967
|
-
latency: "最近延迟",
|
|
20968
|
-
selectAll: "全选",
|
|
20969
|
-
unselectAll: "全不选",
|
|
20970
|
-
models: "可用模型",
|
|
20971
|
-
modelsHint: "勾选后模型才会显示在对话页的模型选择列表中;全部取消勾选或关闭上方开关可在列表中隐藏该供应商。",
|
|
20972
|
-
proxySettings: "网络代理",
|
|
20973
|
-
proxyMode: "代理模式",
|
|
20974
|
-
proxyModeHint: "本插件的全部供应线路共用这一份代理设置,登录、令牌续期、模型目录与配额读取同样经过它;支持自动读取系统代理,修改后对后续请求生效。",
|
|
20975
|
-
proxyModeAuto: "系统代理(自动检测)",
|
|
20976
|
-
proxyModeCustom: "自定义代理",
|
|
20977
|
-
proxyModeDirect: "直连(禁用代理)",
|
|
20978
|
-
customProxyUrl: "自定义代理地址",
|
|
20979
|
-
customProxyUrlHint: "支持 HTTP/HTTPS/SOCKS5 代理地址,例如 http://127.0.0.1:7890",
|
|
20980
|
-
customProxyUrlPlaceholder: "例如: http://127.0.0.1:7890",
|
|
20981
|
-
saveProxyUrl: "保存代理地址",
|
|
20982
|
-
proxyDetected: "检测到系统代理",
|
|
20983
|
-
proxyDetectedEffective: "(已自动生效)",
|
|
20984
|
-
proxyNoneDetected: "未检测到系统代理,将使用直连",
|
|
20985
|
-
proxyDirectHint: "本插件的全部请求将直接连接,不经过任何代理服务器。",
|
|
20986
|
-
poolStorageTitle: "账号存储位置",
|
|
20987
|
-
poolStorageKeyring: "桌面密钥环",
|
|
20988
|
-
poolStorageCredentials: "DSH 凭据库",
|
|
20989
|
-
poolStorageKeyringHint: "仅限桌面安装:使用操作系统密钥环(DPAPI / 钥匙串 / Secret Service)。在服务器或无桌面的 Linux 主机上密钥环通常不可用,登录会失败——请改选 DSH 凭据库。",
|
|
20990
|
-
poolStorageCredentialsHint: "DSH 的标准密钥存储($DSH_HOME/.credentials.yaml)。POSIX 上强制 0600、创建者独占;Windows 上只有 profile ACL,没有权限位可强制。服务器以及任何没有桌面密钥环的主机都用它。静态不加密,靠宿主权限保护。",
|
|
20991
|
-
poolStorageEffective: "当前实际使用:{storage}",
|
|
20992
|
-
poolStorageBackendKeyring: "桌面密钥环(Secret Service),静态加密",
|
|
20993
|
-
poolStorageBackendDpapi: "Windows DPAPI,静态加密",
|
|
20994
|
-
poolStorageBackendKeychain: "macOS 钥匙串,静态加密",
|
|
20995
|
-
poolStorageBackendCredentials: "DSH 凭据库(.credentials.yaml),由文件权限保护",
|
|
20996
|
-
poolStorageSwitchWarning: "已保存在另一个存储里的账号会留在原处,切回去之前不会显示。不会做迁移。",
|
|
20997
|
-
poolStorageUnavailableKeyring: "这台主机上没有可用的桌面密钥环,因此号池无法读写。请把「账号存储位置」改成 DSH 凭据库。",
|
|
20998
|
-
poolStorageUnavailableCredentials: "这个 harness 没有凭据库(ctx.credentials),因此号池无法读写。请把「账号存储位置」改成桌面密钥环。",
|
|
20999
|
-
poolStorageUnavailableStore: "号池存储这次没有应答,所以这里没有列出账号——账号并没有被删除,存储恢复后重新打开本页即可。",
|
|
21000
|
-
enhancements: "增强功能",
|
|
21001
|
-
fastMode: "快速模式(1.5x 速度)",
|
|
21002
|
-
fastModeHint: "提升 Token 生成速度至约 1.5 倍;将以约 2x–2.5x 速度消耗 Codex 订阅额度。",
|
|
21003
|
-
outputVerbosity: "输出详细程度",
|
|
21004
|
-
outputVerbosityHint: "控制 Codex 最终回答的详细程度;不影响思考深度。默认值与官方 Codex 客户端一致(低)。",
|
|
21005
|
-
verbosityLow: "低(保持回答简洁)",
|
|
21006
|
-
verbosityMedium: "中(兼顾细节与简洁)",
|
|
21007
|
-
verbosityHigh: "高(在回答中包含更多细节)",
|
|
21008
|
-
reasoningSummary: "推理摘要",
|
|
21009
|
-
reasoningSummaryHint: "选择 ChatGPT 总结其推理的方式;不影响思考深度。默认值与官方 Codex 客户端一致(不生成摘要,可省额度)。",
|
|
21010
|
-
summaryAuto: "自动(让模型选择摘要详细程度)",
|
|
21011
|
-
summaryConcise: "简洁(显示简要推理摘要)",
|
|
21012
|
-
summaryDetailed: "详细(显示更详细的推理摘要)",
|
|
21013
|
-
summaryNone: "无(不显示推理摘要)",
|
|
21014
|
-
searchProvider: "搜索来源",
|
|
21015
|
-
searchProviderHint: "选择 DSH 联网搜索使用默认来源,或改用当前 ChatGPT 订阅的 Codex 来源(自动走代理隧道)。抓取模式为 auto 时,抓取来源跟随此选择。",
|
|
21016
|
-
searchProviderDsh: "DSH 默认",
|
|
21017
|
-
searchProviderCodex: "ChatGPT(代理隧道)",
|
|
21018
|
-
fetchStatus: "抓取来源(只读)",
|
|
21019
|
-
fetchStatusHint: "以下内容由 Host 上报,只读展示。",
|
|
21020
|
-
fetchConfiguredProvider: "配置的抓取 Provider",
|
|
21021
|
-
fetchProviderDshDefault: "DSH 默认(Host 未固定抓取 provider)",
|
|
21022
|
-
switcherState: "抓取选择器状态",
|
|
21023
|
-
switcherStateIdle: "空闲(尚未应用选择)",
|
|
21024
|
-
switcherStateApplying: "应用中(正在切换 Host 的 web provider)",
|
|
21025
|
-
switcherStateApplied: "已应用",
|
|
21026
|
-
switcherStateMissing: "未找到可切换的 web 服务",
|
|
21027
|
-
switcherStateFailed: "切换失败,请检查 Host 日志",
|
|
21028
|
-
fetchMode: "抓取模式",
|
|
21029
|
-
fetchModeAuto: "auto(有可用代理或选了 ChatGPT 搜索时用插件抓取)",
|
|
21030
|
-
fetchModePlugin: "plugin(始终用本插件抓取)",
|
|
21031
|
-
fetchModeDsh: "dsh(保留 DSH 原有抓取来源)",
|
|
21032
|
-
fetchMaxBodyChars: "插件正文上限",
|
|
21033
|
-
fetchMaxResponseBytes: "插件响应体上限",
|
|
21034
|
-
characters: "字符",
|
|
21035
|
-
bytes: "字节",
|
|
21036
|
-
fetchLimitsInactive: "仅在实际使用插件抓取时生效;走 DSH 原有抓取来源时不适用这两个上限。",
|
|
21037
|
-
fetchConfigSource: "模式与上限在插件 Config 中修改(不是本页面偏好),修改后重载插件或重启 DSH 生效。",
|
|
21038
|
-
providerDefault: "使用 Provider 默认值",
|
|
21039
|
-
contextWindows: "模型上下文窗口",
|
|
21040
|
-
contextWindowsHint: "只列出已勾选「可用模型」的条目。默认取模型目录值(GPT-6 系列 384K,最高 872K;其余最高 1M),该值用于 DSH 的压缩与溢出判断,可输入 872K、512K 等容量;改过的模型可单独或一键恢复默认。",
|
|
21041
|
-
contextWindow: "上下文窗口",
|
|
21042
|
-
contextWindowInvalid: "上下文窗口必须是正整数,且不能超过模型上限(GPT-6 系列为 872K,其余为 1M);可使用 K 或 M 后缀。",
|
|
21043
|
-
contextWindowReset: "恢复默认",
|
|
21044
|
-
contextWindowResetAll: "全部恢复默认",
|
|
21045
|
-
contextWindowResetAllConfirm: "确定把已改过的模型上下文窗口全部恢复为默认值吗?",
|
|
21046
|
-
contextWindowsNoneEnabled: "还没有勾选任何模型。在上方「可用模型」里勾选后,这里会出现该模型的上下文窗口设置。",
|
|
21047
|
-
saveContextWindow: "保存上下文窗口",
|
|
21048
|
-
save: "保存",
|
|
21049
|
-
tokens: "tokens",
|
|
21050
|
-
quickQuota: "在输入框旁显示快捷用量",
|
|
21051
|
-
quickQuotaHint: "仅在当前会话选中 codex-chatgpt 模型时显示。",
|
|
21052
|
-
quota: "用量与限额",
|
|
21053
|
-
quotaIntro: "数据来自 ChatGPT Codex 用量服务。页面可见时最多每 60 秒刷新一次。",
|
|
21054
|
-
refreshQuota: "刷新用量",
|
|
21055
|
-
refreshing: "刷新中…",
|
|
21056
|
-
noQuota: "当前套餐未返回可显示的限额窗口。",
|
|
21057
|
-
quotaSignedOut: "登录后可查看订阅限额。",
|
|
21058
|
-
stale: "显示的是上次成功获取的数据。",
|
|
21059
|
-
updated: "更新时间",
|
|
21060
|
-
primary: "主要窗口",
|
|
21061
|
-
secondary: "次要窗口",
|
|
21062
|
-
limitWindow: "额度",
|
|
21063
|
-
used: "已使用",
|
|
21064
|
-
remaining: "剩余",
|
|
21065
|
-
available: "可用",
|
|
21066
|
-
unavailable: "不可用",
|
|
21067
|
-
unlimited: "无限",
|
|
21068
|
-
credits: "Credits",
|
|
21069
|
-
monthlySpend: "月度消费控制",
|
|
21070
|
-
resetCredits: "重置次数",
|
|
21071
|
-
resetCreditExpires: "到期时间",
|
|
21072
|
-
useResetCredit: "使用重置卡",
|
|
21073
|
-
usingResetCredit: "使用中…",
|
|
21074
|
-
useResetCreditConfirm: "使用后会立即消耗 1 次重置机会,并重置符合条件的 Codex 额度窗口。确定继续吗?",
|
|
21075
|
-
resetCreditUsed: "重置卡已使用,用量数据已刷新。",
|
|
21076
|
-
spendControlReached: "已触发月度消费控制,新的订阅调用可能被限制。",
|
|
21077
|
-
limit: "上限",
|
|
21078
|
-
exhausted: "额度已用尽",
|
|
21079
|
-
resets: "重置",
|
|
21080
|
-
quickQuotaLabel: "Codex 剩余",
|
|
21081
|
-
quickQuotaLoading: "用量…",
|
|
21082
|
-
imageToolRunning: "正在生成图片",
|
|
21083
|
-
imageToolDone: "已生成图片",
|
|
21084
|
-
imageToolFailed: "图片生成失败",
|
|
21085
|
-
image: "图片",
|
|
21086
|
-
openImage: "打开图片",
|
|
21087
|
-
openNamedImage: "打开 {name}",
|
|
21088
|
-
imageLoading: "加载图片…",
|
|
21089
|
-
imageLoadFailed: "图片加载失败,点击重试",
|
|
21090
|
-
imagePreviewClose: "关闭",
|
|
21091
|
-
imagePreviewOpenOriginal: "打开原图",
|
|
21092
|
-
retry: "重试",
|
|
21093
|
-
unknown: "未知",
|
|
21094
|
-
hubBack: "订阅服务",
|
|
21095
|
-
hubOverviewHint: "选择供应商以管理账号、模型与配额;右侧开关控制该供应商是否出现在模型列表中。",
|
|
21096
|
-
hubAccountCount: "{count} 个账号",
|
|
21097
|
-
hubNoAccounts: "暂无账号,点击进入添加",
|
|
21098
|
-
hubStateEnabled: "已启用",
|
|
21099
|
-
hubStateDisabled: "已停用",
|
|
21100
|
-
hubModelsEnabled: "{count} 个模型可用",
|
|
21101
|
-
hubModelsEnabledOfTotal: "{count}/{total} 个模型可用",
|
|
21102
|
-
hubStatusFailed: "状态读取失败",
|
|
21103
|
-
hubSwitchOn: "启用 {name}",
|
|
21104
|
-
hubSwitchOff: "停用 {name}",
|
|
21105
|
-
hubCardLabel: "{name},{annotation}",
|
|
21106
|
-
hubUpdateCheck: "检测更新",
|
|
21107
|
-
hubUpdateChecking: "检测中…",
|
|
21108
|
-
hubUpdateApply: "更新到 v{version}",
|
|
21109
|
-
hubUpdateApplying: "更新中…",
|
|
21110
|
-
hubUpdateUpToDate: "已是最新版本 {version}",
|
|
21111
|
-
hubUpdateLatestWithUnknownCurrent: "最新版本 {version},当前版本未知",
|
|
21112
|
-
hubUpdateAvailable: "有新版本 {version},当前 {current}",
|
|
21113
|
-
hubUpdateInstalled: "已安装 v{version},重启宿主后生效",
|
|
21114
|
-
hubUpdateInstalledReplaced: "已移除旧版并安装 v{version},重启宿主后生效",
|
|
21115
|
-
hubUpdateInstalledLive: "已安装 v{version},当前已生效,无需重启",
|
|
21116
|
-
hubUpdateInstalledReplacedLive: "已移除旧版并安装 v{version},当前已生效,无需重启",
|
|
21117
|
-
hubUpdateFailedRestored: "更新失败,已恢复 v{version}",
|
|
21118
|
-
hubUpdateFailedRollbackFailed: "更新失败,且旧版本也没能重新装回来——插件可能已不可用",
|
|
21119
|
-
hubUpdateFailedRollbackSkipped: "更新失败,且无法自动恢复原版本——插件可能已被移除",
|
|
21120
|
-
hubUpdateDevelopmentInstall: "有新版本 {version};当前是本地链接安装,无法自动更新",
|
|
21121
|
-
hubUpdatePluginManagerMissing: "有新版本 {version};宿主未提供 pluginManager,无法自动更新",
|
|
21122
|
-
hubUpdateManualOnly: "有新版本 {version};当前安装方式无法自动更新",
|
|
21123
|
-
hubUpdateCheckFailed: "检测失败:无法连接 npm 源,请检查网络或代理",
|
|
21124
|
-
hubUpdateCommandLabel: "手动更新命令",
|
|
21125
|
-
localCodexLoginImport: "导入本机登录",
|
|
21126
|
-
localCodexLoginImporting: "导入中…",
|
|
21127
|
-
deviceCodeLogin: "设备代码登录",
|
|
21128
|
-
deviceCodeLoginStarting: "获取代码…",
|
|
21129
|
-
deviceCodeLoginDetail: "用设备代码添加账号",
|
|
21130
|
-
deviceCodeHint: "在任意设备上打开下面的链接并输入这个代码,本页会自动完成登录:这条路不需要浏览器回调到本机端口。",
|
|
21131
|
-
deviceCodeLabel: "设备代码",
|
|
21132
|
-
deviceCodeOpen: "打开确认页面",
|
|
21133
|
-
deviceCodeCopy: "复制到剪贴板",
|
|
21134
|
-
deviceCodeWaiting: "等待确认… 剩余 {time}",
|
|
21135
|
-
stopImporting: "停止导入全部本机登录",
|
|
21136
|
-
stopImportingLabel: "停止导入全部本机登录(当前 {count} 个)",
|
|
21137
|
-
stopImportingBusy: "停止导入中…",
|
|
21138
|
-
stopImportingHint: "停止导入只会让本插件忘记本机 CLI 登录的副本;Codex CLI 自己的登录文件不会被删除或修改。账号池不允许逐条删除借来的凭据,所以这里一次会停止全部导入。",
|
|
21139
|
-
"cardName.chatgpt": "ChatGPT",
|
|
21140
|
-
"cardName.antigravity": "Antigravity",
|
|
21141
|
-
"cardName.command-code": "Command Code",
|
|
21142
|
-
"cardName.kimi-code": "Kimi Code",
|
|
21143
|
-
"cardName.minimax-code": "MiniMax Code",
|
|
21144
|
-
"cardName.glm-coding-plan": "GLM(ZCode 账号)",
|
|
21145
|
-
"cardName.claude": "Claude",
|
|
21146
|
-
"cardName.ollama": "Ollama",
|
|
21147
|
-
"cardName.step-code": "Step Code(Step Plan 订阅)",
|
|
21148
|
-
"cardName.cline-pass": "Cline Pass",
|
|
21149
|
-
"cardName.qoder": "Qoder(订阅)",
|
|
21150
|
-
"cardName.opendesign": "OpenDesign",
|
|
21151
|
-
"cardName.workbuddy": "WorkBuddy",
|
|
21152
|
-
modelChecklistCount: "已启用 {count}/{total}"
|
|
21153
|
-
},
|
|
21248
|
+
zh: zh$2,
|
|
21154
21249
|
en: {
|
|
21155
21250
|
...accountPoolEn,
|
|
21156
21251
|
title: "ChatGPT",
|
|
@@ -21359,7 +21454,18 @@ window.__ModuleLoader__.load({
|
|
|
21359
21454
|
"cardName.qoder": "Qoder Subscription",
|
|
21360
21455
|
"cardName.opendesign": "OpenDesign",
|
|
21361
21456
|
"cardName.workbuddy": "WorkBuddy",
|
|
21362
|
-
modelChecklistCount: "{count}/{total} enabled"
|
|
21457
|
+
modelChecklistCount: "{count}/{total} enabled",
|
|
21458
|
+
codeRunTitle: "Code",
|
|
21459
|
+
codeRunOutput: "Output",
|
|
21460
|
+
codeRunCopy: "Copy",
|
|
21461
|
+
codeRunCopied: "Copied",
|
|
21462
|
+
codeRunWrap: "Wrap lines",
|
|
21463
|
+
codeRunUnwrap: "Do not wrap lines",
|
|
21464
|
+
codeRunInspect: "Inspect",
|
|
21465
|
+
codeRunPreparing: "Preparing",
|
|
21466
|
+
codeRunRunning: "Running",
|
|
21467
|
+
codeRunFailed: "Failed",
|
|
21468
|
+
codeRunStopped: "Stopped"
|
|
21363
21469
|
}
|
|
21364
21470
|
};
|
|
21365
21471
|
//#endregion
|
|
@@ -22360,7 +22466,18 @@ window.__ModuleLoader__.load({
|
|
|
22360
22466
|
"cardName.qoder": "Qoder (подписка)",
|
|
22361
22467
|
"cardName.opendesign": "OpenDesign",
|
|
22362
22468
|
"cardName.workbuddy": "WorkBuddy",
|
|
22363
|
-
modelChecklistCount: "Включено {count}/{total}"
|
|
22469
|
+
modelChecklistCount: "Включено {count}/{total}",
|
|
22470
|
+
codeRunTitle: "Код",
|
|
22471
|
+
codeRunOutput: "Вывод",
|
|
22472
|
+
codeRunCopy: "Копировать",
|
|
22473
|
+
codeRunCopied: "Скопировано",
|
|
22474
|
+
codeRunWrap: "Переносить строки",
|
|
22475
|
+
codeRunUnwrap: "Не переносить строки",
|
|
22476
|
+
codeRunInspect: "Инспектор",
|
|
22477
|
+
codeRunPreparing: "Подготовка",
|
|
22478
|
+
codeRunRunning: "Выполняется",
|
|
22479
|
+
codeRunFailed: "Ошибка",
|
|
22480
|
+
codeRunStopped: "Остановлено"
|
|
22364
22481
|
};
|
|
22365
22482
|
//#endregion
|
|
22366
22483
|
//#region src/client/locales-ru/kimi-code.ts
|
|
@@ -23564,18 +23681,32 @@ window.__ModuleLoader__.load({
|
|
|
23564
23681
|
.dsh-codex-composer-quota[data-level=warning] strong{color:var(--dsw-alias-label-warning,#d58a24)}
|
|
23565
23682
|
.dsh-codex-composer-quota[data-level=danger] strong{color:var(--dsw-alias-label-danger,#d94b4b)}
|
|
23566
23683
|
.dsh-codex-image-tool{border:0.5px solid var(--dsw-alias-border-l2);border-radius:8px;display:flex;flex-direction:column;gap:8px;margin:4px 0 4px 4px;max-width:520px;padding:10px 12px}
|
|
23567
|
-
.
|
|
23684
|
+
/* One line, always. In a 320px column the label used to be squeezed until it
|
|
23685
|
+
stacked one character per row, which reads as broken text rather than a card.
|
|
23686
|
+
The dot and the label therefore keep their own size (flex:none + nowrap) and
|
|
23687
|
+
the summary is the only thing that gives way — it shrinks to zero width and
|
|
23688
|
+
ellipsizes, with the full prompt left in its title attribute. */
|
|
23689
|
+
.dsh-codex-image-tool-head{align-items:center;display:flex;flex-wrap:nowrap;font-size:13px;gap:8px;min-width:0}
|
|
23568
23690
|
.dsh-codex-image-dot{background:var(--dsw-alias-button-info-fill,#397ee8);border-radius:50%;corner-shape:round;display:inline-block;flex:none;height:8px;width:8px}
|
|
23569
23691
|
.dsh-codex-image-tool[data-state=error] .dsh-codex-image-dot{background:var(--dsw-alias-label-danger,#d94b4b)}
|
|
23570
|
-
.dsh-codex-image-title{font-weight:600}
|
|
23571
|
-
.dsh-codex-image-summary{color:var(--dsw-alias-label-tertiary);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
23692
|
+
.dsh-codex-image-title{flex:none;font-weight:600;white-space:nowrap}
|
|
23693
|
+
.dsh-codex-image-summary{color:var(--dsw-alias-label-tertiary);flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
23572
23694
|
.dsh-codex-image-grid{display:flex;flex-wrap:wrap;gap:8px}
|
|
23695
|
+
/* The tray the image will land in, drawn while the call is still running so the
|
|
23696
|
+
card does not jump from one text row to a full picture when the result
|
|
23697
|
+
arrives. Neither dimension is set here: the view fixes the short side (height
|
|
23698
|
+
for a portrait frame, width for a landscape one) and the inline aspect-ratio
|
|
23699
|
+
derives the other, which is what keeps the 4:1 and 8:1 strips from being
|
|
23700
|
+
clamped into squarer boxes. max-width is the card's edge. The breathe is the
|
|
23701
|
+
same restrained opacity pulse the settings skeleton uses, and the
|
|
23702
|
+
reduced-motion block below turns it off. */
|
|
23703
|
+
.dsh-codex-image-placeholder{animation:dsh-codex-pulse 2s ease-in-out infinite;background:var(--dsw-alias-bg-layer-2);border:0.5px dashed var(--dsw-alias-border-l2);border-radius:8px;display:block;flex:none;max-width:100%}
|
|
23573
23704
|
.dsh-codex-image-preview{background:var(--dsw-alias-bg-layer-2);border:0.5px solid var(--dsw-alias-border-l2);border-radius:8px;display:block;max-height:260px;max-width:min(100%,360px);object-fit:contain}
|
|
23574
23705
|
.dsh-codex-image-loading,.dsh-codex-image-failed{border:0.5px dashed var(--dsw-alias-border-l2);border-radius:8px;color:var(--dsw-alias-label-tertiary);display:inline-flex;font-size:12px;line-height:1.4;padding:18px 20px}
|
|
23575
23706
|
.dsh-codex-image-failed{color:var(--dsw-alias-label-danger,#d94b4b)}
|
|
23576
23707
|
@keyframes dsh-codex-pulse{0%,100%{opacity:.45}50%{opacity:.85}}
|
|
23577
23708
|
@media(max-width:560px){.dsh-codex-row,.dsh-codex-pref-row,.dsh-codex-quota-fact,.dsh-codex-reset-credits{align-items:flex-start;flex-direction:column;gap:3px}.dsh-codex-value,.dsh-codex-quota-fact strong{text-align:left}.dsh-codex-actions{justify-content:flex-start}.dsh-codex-grouphead{align-items:flex-start;flex-direction:column;gap:0;padding:12px 0}.dsh-codex-meter-meta{align-items:flex-start;flex-direction:column;gap:2px}.dsh-codex-errorbar{align-items:flex-start;flex-direction:column}.dsh-codex-segments{width:100%}.dsh-codex-select{max-width:none;width:100%}.dsh-codex-context-row{align-items:flex-start;flex-direction:column;gap:5px}.dsh-codex-segments label{flex:1}.dsh-codex-segments span{text-align:center}.dsh-codex-image-tool{max-width:100%;margin-left:0}}
|
|
23578
|
-
@media(prefers-reduced-motion:reduce){.dsh-codex-meter>span{transition:none}.dsh-codex-skeleton span{animation:none}}
|
|
23709
|
+
@media(prefers-reduced-motion:reduce){.dsh-codex-meter>span{transition:none}.dsh-codex-skeleton span{animation:none}.dsh-codex-image-placeholder{animation:none}}
|
|
23579
23710
|
`;
|
|
23580
23711
|
/**
|
|
23581
23712
|
* Install the ChatGPT tab's stylesheet as a document-owned, never-removed
|
|
@@ -27418,7 +27549,7 @@ window.__ModuleLoader__.load({
|
|
|
27418
27549
|
}
|
|
27419
27550
|
}
|
|
27420
27551
|
/** 兜底翻译:只在没有 locale 服务时用到(测试、以及菜单渲染早于字典注册)。 */
|
|
27421
|
-
function fallbackTranslate$
|
|
27552
|
+
function fallbackTranslate$2(key, params) {
|
|
27422
27553
|
const template = zh$11[key] ?? key;
|
|
27423
27554
|
if (params === void 0) return template;
|
|
27424
27555
|
return template.replace(/\{(\w+)\}/g, (_match, name) => String(params[name] ?? ""));
|
|
@@ -27434,7 +27565,7 @@ window.__ModuleLoader__.load({
|
|
|
27434
27565
|
* @returns 一份可直接交给 `commandUi.register` 的贡献。
|
|
27435
27566
|
*/
|
|
27436
27567
|
function createVideoCommand(ctx, options) {
|
|
27437
|
-
const t = options.translate ?? fallbackTranslate$
|
|
27568
|
+
const t = options.translate ?? fallbackTranslate$2;
|
|
27438
27569
|
const defaultsOf = options.defaults ?? (() => normalizeVideoDefaults({}));
|
|
27439
27570
|
return {
|
|
27440
27571
|
name: VIDEO_COMMAND_NAME,
|
|
@@ -27594,7 +27725,7 @@ window.__ModuleLoader__.load({
|
|
|
27594
27725
|
defaults: request?.defaults ?? normalizeVideoDefaults({}),
|
|
27595
27726
|
seedPrompt: request?.seedPrompt ?? "",
|
|
27596
27727
|
listWorkspace,
|
|
27597
|
-
t: fallbackTranslate$
|
|
27728
|
+
t: fallbackTranslate$2
|
|
27598
27729
|
});
|
|
27599
27730
|
};
|
|
27600
27731
|
}
|
|
@@ -27639,7 +27770,7 @@ window.__ModuleLoader__.load({
|
|
|
27639
27770
|
return commandUi.register(createVideoCommand(ctx, {
|
|
27640
27771
|
openForm: openVideoForm,
|
|
27641
27772
|
defaults: () => readVideoDefaults(),
|
|
27642
|
-
translate: fallbackTranslate$
|
|
27773
|
+
translate: fallbackTranslate$2
|
|
27643
27774
|
}));
|
|
27644
27775
|
} catch {
|
|
27645
27776
|
return () => {};
|
|
@@ -54629,7 +54760,7 @@ window.__ModuleLoader__.load({
|
|
|
54629
54760
|
* @param params - `{name}` 模板参数。
|
|
54630
54761
|
* @returns 该键的文案;缺键时回退为键本身。
|
|
54631
54762
|
*/
|
|
54632
|
-
function fallbackTranslate(key, params) {
|
|
54763
|
+
function fallbackTranslate$1(key, params) {
|
|
54633
54764
|
return interpolate(zh$1[key] ?? key, params);
|
|
54634
54765
|
}
|
|
54635
54766
|
/**
|
|
@@ -54929,7 +55060,7 @@ window.__ModuleLoader__.load({
|
|
|
54929
55060
|
* @returns 面板标题文本。
|
|
54930
55061
|
*/
|
|
54931
55062
|
function ProgressUpdatesTabTitle({ t }) {
|
|
54932
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: t === void 0 ? fallbackTranslate("progressTitle") : t("progressTitle") });
|
|
55063
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: t === void 0 ? fallbackTranslate$1("progressTitle") : t("progressTitle") });
|
|
54933
55064
|
}
|
|
54934
55065
|
//#endregion
|
|
54935
55066
|
//#region src/client/progress-updates/progress-row.tsx
|
|
@@ -54970,22 +55101,36 @@ window.__ModuleLoader__.load({
|
|
|
54970
55101
|
done: "rowDone",
|
|
54971
55102
|
error: "rowError"
|
|
54972
55103
|
};
|
|
54973
|
-
/**
|
|
55104
|
+
/**
|
|
55105
|
+
* 行的外框样式。
|
|
55106
|
+
*
|
|
55107
|
+
* 字号与官方工具行标题对齐(13px):同一条时间线上混着 12px 的进展行与 13px 的
|
|
55108
|
+
* 工具行,读者看到的是两套字号。
|
|
55109
|
+
*/
|
|
54974
55110
|
const rowStyle = {
|
|
54975
55111
|
display: "flex",
|
|
54976
55112
|
flexDirection: "column",
|
|
54977
55113
|
gap: "6px",
|
|
54978
55114
|
width: "100%",
|
|
54979
|
-
fontSize: "
|
|
55115
|
+
fontSize: "13px",
|
|
54980
55116
|
color: "var(--dsw-alias-label-primary, #1f2329)"
|
|
54981
55117
|
};
|
|
54982
|
-
/**
|
|
55118
|
+
/**
|
|
55119
|
+
* 标题行按钮样式(整行可点,去掉原生按钮外观)。
|
|
55120
|
+
*
|
|
55121
|
+
* `minHeight: 36px` 与 `padding: 6px 0` 抄的是官方工具行那层 `_row_` 的实测取值
|
|
55122
|
+
* (`height:36px; min-height:36px; padding:6px 0`)。少了这两个值,进展行只有
|
|
55123
|
+
* 18px 左右,夹在一排 36px 的工具行里会明显更矮、更挤——用户报的就是这个。
|
|
55124
|
+
* 用 minHeight 而不是 height:正文换行、标题很长时允许它撑高,官方那种固定高度
|
|
55125
|
+
* 在文字折行时会把内容裁掉。
|
|
55126
|
+
*/
|
|
54983
55127
|
const headerStyle = {
|
|
54984
55128
|
display: "flex",
|
|
54985
|
-
alignItems: "
|
|
55129
|
+
alignItems: "center",
|
|
54986
55130
|
gap: "8px",
|
|
54987
55131
|
width: "100%",
|
|
54988
|
-
|
|
55132
|
+
minHeight: "36px",
|
|
55133
|
+
padding: "6px 0",
|
|
54989
55134
|
border: "0",
|
|
54990
55135
|
background: "transparent",
|
|
54991
55136
|
color: "inherit",
|
|
@@ -54997,9 +55142,9 @@ window.__ModuleLoader__.load({
|
|
|
54997
55142
|
const titleStyle = {
|
|
54998
55143
|
flex: "1 1 auto",
|
|
54999
55144
|
minWidth: "0",
|
|
55000
|
-
fontSize: "
|
|
55145
|
+
fontSize: "13px",
|
|
55001
55146
|
fontWeight: 500,
|
|
55002
|
-
lineHeight: "
|
|
55147
|
+
lineHeight: "16px",
|
|
55003
55148
|
overflowWrap: "anywhere"
|
|
55004
55149
|
};
|
|
55005
55150
|
/** 状态词的小字样式。 */
|
|
@@ -55012,6 +55157,8 @@ window.__ModuleLoader__.load({
|
|
|
55012
55157
|
/**
|
|
55013
55158
|
* 正文样式:只管外边距、字号与颜色。
|
|
55014
55159
|
*
|
|
55160
|
+
* 字号与标题一致(13px)—— 早先正文比标题小一号,展开后两节字不同大,读起来碎。
|
|
55161
|
+
*
|
|
55015
55162
|
* **不再**在这里写 `whiteSpace: 'pre-wrap'`:正文交给 {@link MarkdownLite} 渲染,
|
|
55016
55163
|
* 换行该不该保留由它产出的块级元素决定。早先这里是纯文本 `<p>{message}</p>`,
|
|
55017
55164
|
* 于是列表符号、`**粗体**` 和管道符表格全部原样上屏 —— 同一份进展在侧栏面板里
|
|
@@ -55020,8 +55167,8 @@ window.__ModuleLoader__.load({
|
|
|
55020
55167
|
const messageStyle = {
|
|
55021
55168
|
overflowWrap: "anywhere",
|
|
55022
55169
|
margin: "0",
|
|
55023
|
-
fontSize: "
|
|
55024
|
-
lineHeight: "1.
|
|
55170
|
+
fontSize: "13px",
|
|
55171
|
+
lineHeight: "1.6",
|
|
55025
55172
|
color: "var(--dsw-alias-label-secondary, #5b6270)"
|
|
55026
55173
|
};
|
|
55027
55174
|
/**
|
|
@@ -55073,7 +55220,7 @@ window.__ModuleLoader__.load({
|
|
|
55073
55220
|
* @returns 一行进展;标题行常显,正文按交互展开。
|
|
55074
55221
|
*/
|
|
55075
55222
|
function ProgressRow({ block, t }) {
|
|
55076
|
-
const translate = (key) => t === void 0 ? fallbackTranslate(key) : t(key);
|
|
55223
|
+
const translate = (key) => t === void 0 ? fallbackTranslate$1(key) : t(key);
|
|
55077
55224
|
const state = isSettled(block) ? block.isError === true ? "error" : "done" : "running";
|
|
55078
55225
|
const { title, message } = progressOfBlock(block);
|
|
55079
55226
|
const heading = title ?? message.split("\n").find((line) => line.trim() !== "") ?? translate("rowPending");
|
|
@@ -55400,7 +55547,7 @@ window.__ModuleLoader__.load({
|
|
|
55400
55547
|
*/
|
|
55401
55548
|
function ProgressUpdatesSettingsSection(props) {
|
|
55402
55549
|
const { openPanel, close, settings, t } = props;
|
|
55403
|
-
const translate = (key) => t === void 0 ? fallbackTranslate(key) : t(key);
|
|
55550
|
+
const translate = (key) => t === void 0 ? fallbackTranslate$1(key) : t(key);
|
|
55404
55551
|
const snapshot = (0, react.useSyncExternalStore)(settings?.subscribe ?? NO_SETTINGS_SUBSCRIBE, settings?.getSnapshot ?? NO_SETTINGS_READ, settings?.getSnapshot ?? NO_SETTINGS_READ);
|
|
55405
55552
|
/** 写入被拒/失败时落在哪一行、说什么。 */
|
|
55406
55553
|
const [failure, setFailure] = (0, react.useState)(void 0);
|
|
@@ -59025,6 +59172,1312 @@ window.__ModuleLoader__.load({
|
|
|
59025
59172
|
return installPluginStyle(STYLE_NAME, SUBAGENT_CSS);
|
|
59026
59173
|
}
|
|
59027
59174
|
//#endregion
|
|
59175
|
+
//#region src/client/codemode/highlight.ts
|
|
59176
|
+
/** 宿主 `ui-theme/src/styles/shiki.css` 定义的标准变量表(带合理回退色以兼容测试环境)。 */
|
|
59177
|
+
const SHIKI_TOKEN_COLORS = {
|
|
59178
|
+
plain: void 0,
|
|
59179
|
+
keyword: "var(--shiki-token-keyword, #d6336c)",
|
|
59180
|
+
string: "var(--shiki-token-string, #2f9e44)",
|
|
59181
|
+
"string-expression": "var(--shiki-token-string-expression, #2b8a3e)",
|
|
59182
|
+
comment: "var(--shiki-token-comment, #868e96)",
|
|
59183
|
+
constant: "var(--shiki-token-constant, #1c7ed6)",
|
|
59184
|
+
function: "var(--shiki-token-function, #6741d9)",
|
|
59185
|
+
parameter: "var(--shiki-token-parameter, #e8590c)",
|
|
59186
|
+
punctuation: "var(--shiki-token-punctuation, #495057)"
|
|
59187
|
+
};
|
|
59188
|
+
/** 单字符数超长保护上限(与宿主 `TOKENIZE_MAX_LINE_LENGTH` 对齐,防止超长单行卡顿)。 */
|
|
59189
|
+
const MAX_HIGHLIGHT_CHARS = 1e5;
|
|
59190
|
+
const TS_KEYWORDS = /* @__PURE__ */ new Set([
|
|
59191
|
+
"as",
|
|
59192
|
+
"async",
|
|
59193
|
+
"await",
|
|
59194
|
+
"break",
|
|
59195
|
+
"case",
|
|
59196
|
+
"catch",
|
|
59197
|
+
"class",
|
|
59198
|
+
"const",
|
|
59199
|
+
"continue",
|
|
59200
|
+
"debugger",
|
|
59201
|
+
"declare",
|
|
59202
|
+
"default",
|
|
59203
|
+
"delete",
|
|
59204
|
+
"do",
|
|
59205
|
+
"else",
|
|
59206
|
+
"enum",
|
|
59207
|
+
"export",
|
|
59208
|
+
"extends",
|
|
59209
|
+
"finally",
|
|
59210
|
+
"for",
|
|
59211
|
+
"from",
|
|
59212
|
+
"function",
|
|
59213
|
+
"get",
|
|
59214
|
+
"if",
|
|
59215
|
+
"implements",
|
|
59216
|
+
"import",
|
|
59217
|
+
"in",
|
|
59218
|
+
"infer",
|
|
59219
|
+
"instanceof",
|
|
59220
|
+
"interface",
|
|
59221
|
+
"is",
|
|
59222
|
+
"keyof",
|
|
59223
|
+
"let",
|
|
59224
|
+
"module",
|
|
59225
|
+
"namespace",
|
|
59226
|
+
"new",
|
|
59227
|
+
"of",
|
|
59228
|
+
"override",
|
|
59229
|
+
"package",
|
|
59230
|
+
"private",
|
|
59231
|
+
"protected",
|
|
59232
|
+
"public",
|
|
59233
|
+
"readonly",
|
|
59234
|
+
"return",
|
|
59235
|
+
"satisfies",
|
|
59236
|
+
"set",
|
|
59237
|
+
"static",
|
|
59238
|
+
"super",
|
|
59239
|
+
"switch",
|
|
59240
|
+
"throw",
|
|
59241
|
+
"try",
|
|
59242
|
+
"type",
|
|
59243
|
+
"typeof",
|
|
59244
|
+
"using",
|
|
59245
|
+
"var",
|
|
59246
|
+
"void",
|
|
59247
|
+
"while",
|
|
59248
|
+
"with",
|
|
59249
|
+
"yield"
|
|
59250
|
+
]);
|
|
59251
|
+
const TS_CONSTANTS = /* @__PURE__ */ new Set([
|
|
59252
|
+
"true",
|
|
59253
|
+
"false",
|
|
59254
|
+
"null",
|
|
59255
|
+
"undefined",
|
|
59256
|
+
"NaN",
|
|
59257
|
+
"Infinity",
|
|
59258
|
+
"this",
|
|
59259
|
+
"globalThis",
|
|
59260
|
+
"console",
|
|
59261
|
+
"Promise",
|
|
59262
|
+
"Math",
|
|
59263
|
+
"JSON",
|
|
59264
|
+
"Object",
|
|
59265
|
+
"Array",
|
|
59266
|
+
"Map",
|
|
59267
|
+
"Set",
|
|
59268
|
+
"RegExp",
|
|
59269
|
+
"Error",
|
|
59270
|
+
"String",
|
|
59271
|
+
"Number",
|
|
59272
|
+
"Boolean",
|
|
59273
|
+
"Buffer",
|
|
59274
|
+
"process"
|
|
59275
|
+
]);
|
|
59276
|
+
const PY_KEYWORDS = /* @__PURE__ */ new Set([
|
|
59277
|
+
"and",
|
|
59278
|
+
"as",
|
|
59279
|
+
"assert",
|
|
59280
|
+
"async",
|
|
59281
|
+
"await",
|
|
59282
|
+
"break",
|
|
59283
|
+
"class",
|
|
59284
|
+
"continue",
|
|
59285
|
+
"def",
|
|
59286
|
+
"del",
|
|
59287
|
+
"elif",
|
|
59288
|
+
"else",
|
|
59289
|
+
"except",
|
|
59290
|
+
"finally",
|
|
59291
|
+
"for",
|
|
59292
|
+
"from",
|
|
59293
|
+
"global",
|
|
59294
|
+
"if",
|
|
59295
|
+
"import",
|
|
59296
|
+
"in",
|
|
59297
|
+
"is",
|
|
59298
|
+
"lambda",
|
|
59299
|
+
"match",
|
|
59300
|
+
"nonlocal",
|
|
59301
|
+
"not",
|
|
59302
|
+
"or",
|
|
59303
|
+
"pass",
|
|
59304
|
+
"raise",
|
|
59305
|
+
"return",
|
|
59306
|
+
"try",
|
|
59307
|
+
"while",
|
|
59308
|
+
"with",
|
|
59309
|
+
"yield"
|
|
59310
|
+
]);
|
|
59311
|
+
const PY_CONSTANTS = /* @__PURE__ */ new Set([
|
|
59312
|
+
"True",
|
|
59313
|
+
"False",
|
|
59314
|
+
"None",
|
|
59315
|
+
"self",
|
|
59316
|
+
"cls",
|
|
59317
|
+
"Ellipsis",
|
|
59318
|
+
"NotImplemented"
|
|
59319
|
+
]);
|
|
59320
|
+
/** 允许紧跟正则表达式字面量的前置关键字。 */
|
|
59321
|
+
const REGEX_PRECEDING_KEYWORDS = /* @__PURE__ */ new Set([
|
|
59322
|
+
"return",
|
|
59323
|
+
"throw",
|
|
59324
|
+
"case",
|
|
59325
|
+
"in",
|
|
59326
|
+
"of",
|
|
59327
|
+
"typeof",
|
|
59328
|
+
"instanceof",
|
|
59329
|
+
"void",
|
|
59330
|
+
"delete",
|
|
59331
|
+
"new",
|
|
59332
|
+
"yield",
|
|
59333
|
+
"await"
|
|
59334
|
+
]);
|
|
59335
|
+
/** 允许紧跟正则表达式字面量的末尾标点字符。 */
|
|
59336
|
+
const REGEX_PRECEDING_PUNCT = /* @__PURE__ */ new Set([
|
|
59337
|
+
"(",
|
|
59338
|
+
"[",
|
|
59339
|
+
"{",
|
|
59340
|
+
",",
|
|
59341
|
+
";",
|
|
59342
|
+
":",
|
|
59343
|
+
"=",
|
|
59344
|
+
"!",
|
|
59345
|
+
"?",
|
|
59346
|
+
"&",
|
|
59347
|
+
"|",
|
|
59348
|
+
"^",
|
|
59349
|
+
"~",
|
|
59350
|
+
"+",
|
|
59351
|
+
"-",
|
|
59352
|
+
"*",
|
|
59353
|
+
"%",
|
|
59354
|
+
"<",
|
|
59355
|
+
">"
|
|
59356
|
+
]);
|
|
59357
|
+
/**
|
|
59358
|
+
* 将完整源码切分为带颜色类别的跨行数组(每个子数组代表源码的一行)。
|
|
59359
|
+
*/
|
|
59360
|
+
function tokenizeCodeLines(code, language = "typescript") {
|
|
59361
|
+
const normalized = code.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
59362
|
+
const trimmed = normalized.endsWith("\n") ? normalized.slice(0, -1) : normalized;
|
|
59363
|
+
if (trimmed.length === 0) return [[{
|
|
59364
|
+
text: "",
|
|
59365
|
+
kind: "plain"
|
|
59366
|
+
}]];
|
|
59367
|
+
if (trimmed.length > MAX_HIGHLIGHT_CHARS) return trimmed.split("\n").map((line) => [{
|
|
59368
|
+
text: line,
|
|
59369
|
+
kind: "plain"
|
|
59370
|
+
}]);
|
|
59371
|
+
return splitTokensIntoLines(language === "python" ? scanPython(trimmed) : scanTypeScript(trimmed));
|
|
59372
|
+
}
|
|
59373
|
+
function pushToken(out, text, kind) {
|
|
59374
|
+
if (text.length === 0) return;
|
|
59375
|
+
const prev = out[out.length - 1];
|
|
59376
|
+
if (prev !== void 0 && prev.kind === kind) {
|
|
59377
|
+
out[out.length - 1] = {
|
|
59378
|
+
text: prev.text + text,
|
|
59379
|
+
kind
|
|
59380
|
+
};
|
|
59381
|
+
return;
|
|
59382
|
+
}
|
|
59383
|
+
out.push({
|
|
59384
|
+
text,
|
|
59385
|
+
kind
|
|
59386
|
+
});
|
|
59387
|
+
}
|
|
59388
|
+
function splitTokensIntoLines(tokens) {
|
|
59389
|
+
const lines = [[]];
|
|
59390
|
+
for (const token of tokens) {
|
|
59391
|
+
const parts = token.text.split("\n");
|
|
59392
|
+
for (let index = 0; index < parts.length; index += 1) {
|
|
59393
|
+
if (index > 0) lines.push([]);
|
|
59394
|
+
const part = parts[index];
|
|
59395
|
+
if (part.length > 0) lines[lines.length - 1].push({
|
|
59396
|
+
text: part,
|
|
59397
|
+
kind: token.kind
|
|
59398
|
+
});
|
|
59399
|
+
}
|
|
59400
|
+
}
|
|
59401
|
+
return lines;
|
|
59402
|
+
}
|
|
59403
|
+
function isIdentStart(ch) {
|
|
59404
|
+
return ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 || ch === 95 || ch === 36 || ch > 127;
|
|
59405
|
+
}
|
|
59406
|
+
function isIdentPart(ch) {
|
|
59407
|
+
return isIdentStart(ch) || ch >= 48 && ch <= 57;
|
|
59408
|
+
}
|
|
59409
|
+
function isDigit(ch) {
|
|
59410
|
+
return ch >= 48 && ch <= 57;
|
|
59411
|
+
}
|
|
59412
|
+
function skipWhitespaceLookahead(src, from) {
|
|
59413
|
+
let pos = from;
|
|
59414
|
+
while (pos < src.length) {
|
|
59415
|
+
const ch = src.charCodeAt(pos);
|
|
59416
|
+
if (ch === 32 || ch === 9) pos += 1;
|
|
59417
|
+
else break;
|
|
59418
|
+
}
|
|
59419
|
+
return pos;
|
|
59420
|
+
}
|
|
59421
|
+
function scanNumber(src, start) {
|
|
59422
|
+
let i = start;
|
|
59423
|
+
if (src[i] === "0" && i + 1 < src.length && /[xXbBoO]/.test(src[i + 1])) {
|
|
59424
|
+
i += 2;
|
|
59425
|
+
while (i < src.length && /[0-9a-fA-F_]/.test(src[i])) i += 1;
|
|
59426
|
+
if (src[i] === "n") i += 1;
|
|
59427
|
+
return i;
|
|
59428
|
+
}
|
|
59429
|
+
while (i < src.length && (isDigit(src.charCodeAt(i)) || src[i] === "_")) i += 1;
|
|
59430
|
+
if (src[i] === "." && i + 1 < src.length && isDigit(src.charCodeAt(i + 1))) {
|
|
59431
|
+
i += 1;
|
|
59432
|
+
while (i < src.length && (isDigit(src.charCodeAt(i)) || src[i] === "_")) i += 1;
|
|
59433
|
+
}
|
|
59434
|
+
if (i < src.length && (src[i] === "e" || src[i] === "E")) {
|
|
59435
|
+
let next = i + 1;
|
|
59436
|
+
if (src[next] === "+" || src[next] === "-") next += 1;
|
|
59437
|
+
if (next < src.length && isDigit(src.charCodeAt(next))) {
|
|
59438
|
+
i = next + 1;
|
|
59439
|
+
while (i < src.length && (isDigit(src.charCodeAt(i)) || src[i] === "_")) i += 1;
|
|
59440
|
+
}
|
|
59441
|
+
}
|
|
59442
|
+
if (src[i] === "n") i += 1;
|
|
59443
|
+
return i;
|
|
59444
|
+
}
|
|
59445
|
+
/**
|
|
59446
|
+
* 尝试从 `start`(`src[start] === '/'`)扫描单行正则表达式字面量;不合法时返回 -1。
|
|
59447
|
+
*/
|
|
59448
|
+
function tryScanRegexLiteral(src, start) {
|
|
59449
|
+
let i = start + 1;
|
|
59450
|
+
let inCharClass = false;
|
|
59451
|
+
if (i >= src.length || src[i] === "\n") return -1;
|
|
59452
|
+
while (i < src.length) {
|
|
59453
|
+
const ch = src[i];
|
|
59454
|
+
if (ch === "\n") return -1;
|
|
59455
|
+
if (ch === "\\") {
|
|
59456
|
+
if (i + 1 >= src.length || src[i + 1] === "\n") return -1;
|
|
59457
|
+
i += 2;
|
|
59458
|
+
continue;
|
|
59459
|
+
}
|
|
59460
|
+
if (ch === "[") {
|
|
59461
|
+
inCharClass = true;
|
|
59462
|
+
i += 1;
|
|
59463
|
+
continue;
|
|
59464
|
+
}
|
|
59465
|
+
if (ch === "]") {
|
|
59466
|
+
inCharClass = false;
|
|
59467
|
+
i += 1;
|
|
59468
|
+
continue;
|
|
59469
|
+
}
|
|
59470
|
+
if (ch === "/" && !inCharClass) {
|
|
59471
|
+
i += 1;
|
|
59472
|
+
while (i < src.length && /[dgimsuvy]/.test(src[i])) i += 1;
|
|
59473
|
+
return i;
|
|
59474
|
+
}
|
|
59475
|
+
i += 1;
|
|
59476
|
+
}
|
|
59477
|
+
return -1;
|
|
59478
|
+
}
|
|
59479
|
+
function scanTypeScript(src) {
|
|
59480
|
+
const tokens = [];
|
|
59481
|
+
/** 模板字符串 `${ ... }` 嵌套栈:记录每一层尚未闭合的左花括号深度。 */
|
|
59482
|
+
const templateBraceStack = [];
|
|
59483
|
+
let canStartRegex = true;
|
|
59484
|
+
let i = 0;
|
|
59485
|
+
const scanTemplateBody = (from) => {
|
|
59486
|
+
let pos = from;
|
|
59487
|
+
let segStart = pos;
|
|
59488
|
+
while (pos < src.length) {
|
|
59489
|
+
const ch = src[pos];
|
|
59490
|
+
if (ch === "\\") {
|
|
59491
|
+
pos = Math.min(src.length, pos + 2);
|
|
59492
|
+
continue;
|
|
59493
|
+
}
|
|
59494
|
+
if (ch === "`") {
|
|
59495
|
+
pushToken(tokens, src.slice(segStart, pos + 1), "string");
|
|
59496
|
+
canStartRegex = false;
|
|
59497
|
+
return pos + 1;
|
|
59498
|
+
}
|
|
59499
|
+
if (ch === "$" && src[pos + 1] === "{") {
|
|
59500
|
+
if (pos > segStart) pushToken(tokens, src.slice(segStart, pos), "string");
|
|
59501
|
+
pushToken(tokens, "${", "punctuation");
|
|
59502
|
+
templateBraceStack.push(0);
|
|
59503
|
+
canStartRegex = true;
|
|
59504
|
+
return pos + 2;
|
|
59505
|
+
}
|
|
59506
|
+
pos += 1;
|
|
59507
|
+
}
|
|
59508
|
+
pushToken(tokens, src.slice(segStart), "string");
|
|
59509
|
+
canStartRegex = false;
|
|
59510
|
+
return pos;
|
|
59511
|
+
};
|
|
59512
|
+
while (i < src.length) {
|
|
59513
|
+
const ch = src[i];
|
|
59514
|
+
const code = src.charCodeAt(i);
|
|
59515
|
+
if (ch === " " || ch === " " || ch === "\n") {
|
|
59516
|
+
let end = i + 1;
|
|
59517
|
+
while (end < src.length && (src[end] === " " || src[end] === " " || src[end] === "\n")) end += 1;
|
|
59518
|
+
pushToken(tokens, src.slice(i, end), "plain");
|
|
59519
|
+
i = end;
|
|
59520
|
+
continue;
|
|
59521
|
+
}
|
|
59522
|
+
if (ch === "/" && src[i + 1] === "/") {
|
|
59523
|
+
const nl = src.indexOf("\n", i + 2);
|
|
59524
|
+
const end = nl === -1 ? src.length : nl;
|
|
59525
|
+
pushToken(tokens, src.slice(i, end), "comment");
|
|
59526
|
+
i = end;
|
|
59527
|
+
continue;
|
|
59528
|
+
}
|
|
59529
|
+
if (ch === "/" && src[i + 1] === "*") {
|
|
59530
|
+
const close = src.indexOf("*/", i + 2);
|
|
59531
|
+
const end = close === -1 ? src.length : close + 2;
|
|
59532
|
+
pushToken(tokens, src.slice(i, end), "comment");
|
|
59533
|
+
i = end;
|
|
59534
|
+
continue;
|
|
59535
|
+
}
|
|
59536
|
+
if (ch === "/" && canStartRegex) {
|
|
59537
|
+
const regexEnd = tryScanRegexLiteral(src, i);
|
|
59538
|
+
if (regexEnd > i) {
|
|
59539
|
+
pushToken(tokens, src.slice(i, regexEnd), "string-expression");
|
|
59540
|
+
canStartRegex = false;
|
|
59541
|
+
i = regexEnd;
|
|
59542
|
+
continue;
|
|
59543
|
+
}
|
|
59544
|
+
}
|
|
59545
|
+
if (ch === "\"" || ch === "'") {
|
|
59546
|
+
let end = i + 1;
|
|
59547
|
+
while (end < src.length) {
|
|
59548
|
+
const c = src[end];
|
|
59549
|
+
if (c === "\\") {
|
|
59550
|
+
end = Math.min(src.length, end + 2);
|
|
59551
|
+
continue;
|
|
59552
|
+
}
|
|
59553
|
+
end += 1;
|
|
59554
|
+
if (c === ch || c === "\n") break;
|
|
59555
|
+
}
|
|
59556
|
+
pushToken(tokens, src.slice(i, end), "string");
|
|
59557
|
+
canStartRegex = false;
|
|
59558
|
+
i = end;
|
|
59559
|
+
continue;
|
|
59560
|
+
}
|
|
59561
|
+
if (ch === "`") {
|
|
59562
|
+
pushToken(tokens, "`", "string");
|
|
59563
|
+
i = scanTemplateBody(i + 1);
|
|
59564
|
+
continue;
|
|
59565
|
+
}
|
|
59566
|
+
if (ch === "{" && templateBraceStack.length > 0) {
|
|
59567
|
+
templateBraceStack[templateBraceStack.length - 1] += 1;
|
|
59568
|
+
pushToken(tokens, "{", "punctuation");
|
|
59569
|
+
canStartRegex = true;
|
|
59570
|
+
i += 1;
|
|
59571
|
+
continue;
|
|
59572
|
+
}
|
|
59573
|
+
if (ch === "}" && templateBraceStack.length > 0) {
|
|
59574
|
+
const top = templateBraceStack[templateBraceStack.length - 1];
|
|
59575
|
+
if (top === 0) {
|
|
59576
|
+
templateBraceStack.pop();
|
|
59577
|
+
pushToken(tokens, "}", "punctuation");
|
|
59578
|
+
i = scanTemplateBody(i + 1);
|
|
59579
|
+
continue;
|
|
59580
|
+
}
|
|
59581
|
+
templateBraceStack[templateBraceStack.length - 1] = top - 1;
|
|
59582
|
+
pushToken(tokens, "}", "punctuation");
|
|
59583
|
+
canStartRegex = false;
|
|
59584
|
+
i += 1;
|
|
59585
|
+
continue;
|
|
59586
|
+
}
|
|
59587
|
+
if (isDigit(code) || ch === "." && i + 1 < src.length && isDigit(src.charCodeAt(i + 1))) {
|
|
59588
|
+
const end = scanNumber(src, i);
|
|
59589
|
+
pushToken(tokens, src.slice(i, end), "constant");
|
|
59590
|
+
canStartRegex = false;
|
|
59591
|
+
i = end;
|
|
59592
|
+
continue;
|
|
59593
|
+
}
|
|
59594
|
+
if (isIdentStart(code)) {
|
|
59595
|
+
let end = i + 1;
|
|
59596
|
+
while (end < src.length && isIdentPart(src.charCodeAt(end))) end += 1;
|
|
59597
|
+
const word = src.slice(i, end);
|
|
59598
|
+
let prevNonSpace = i - 1;
|
|
59599
|
+
while (prevNonSpace >= 0 && (src[prevNonSpace] === " " || src[prevNonSpace] === " ")) prevNonSpace -= 1;
|
|
59600
|
+
const afterDot = prevNonSpace >= 0 && (src[prevNonSpace] === "." || src[prevNonSpace] === "?");
|
|
59601
|
+
const beforeCall = src[skipWhitespaceLookahead(src, end)] === "(";
|
|
59602
|
+
if (!afterDot && TS_KEYWORDS.has(word)) {
|
|
59603
|
+
pushToken(tokens, word, "keyword");
|
|
59604
|
+
canStartRegex = REGEX_PRECEDING_KEYWORDS.has(word);
|
|
59605
|
+
} else if (!afterDot && TS_CONSTANTS.has(word)) {
|
|
59606
|
+
pushToken(tokens, word, "constant");
|
|
59607
|
+
canStartRegex = false;
|
|
59608
|
+
} else if (beforeCall) {
|
|
59609
|
+
pushToken(tokens, word, "function");
|
|
59610
|
+
canStartRegex = false;
|
|
59611
|
+
} else if (/^[A-Z][A-Z0-9_]{2,}$/.test(word)) {
|
|
59612
|
+
pushToken(tokens, word, "constant");
|
|
59613
|
+
canStartRegex = false;
|
|
59614
|
+
} else {
|
|
59615
|
+
pushToken(tokens, word, "plain");
|
|
59616
|
+
canStartRegex = false;
|
|
59617
|
+
}
|
|
59618
|
+
i = end;
|
|
59619
|
+
continue;
|
|
59620
|
+
}
|
|
59621
|
+
if (ch === "@" && i + 1 < src.length && isIdentStart(src.charCodeAt(i + 1))) {
|
|
59622
|
+
let end = i + 2;
|
|
59623
|
+
while (end < src.length && isIdentPart(src.charCodeAt(end))) end += 1;
|
|
59624
|
+
pushToken(tokens, src.slice(i, end), "function");
|
|
59625
|
+
canStartRegex = false;
|
|
59626
|
+
i = end;
|
|
59627
|
+
continue;
|
|
59628
|
+
}
|
|
59629
|
+
pushToken(tokens, ch, "punctuation");
|
|
59630
|
+
canStartRegex = REGEX_PRECEDING_PUNCT.has(ch);
|
|
59631
|
+
i += 1;
|
|
59632
|
+
}
|
|
59633
|
+
return tokens;
|
|
59634
|
+
}
|
|
59635
|
+
function scanPython(src) {
|
|
59636
|
+
const tokens = [];
|
|
59637
|
+
let i = 0;
|
|
59638
|
+
while (i < src.length) {
|
|
59639
|
+
const ch = src[i];
|
|
59640
|
+
const code = src.charCodeAt(i);
|
|
59641
|
+
if (ch === " " || ch === " " || ch === "\n") {
|
|
59642
|
+
let end = i + 1;
|
|
59643
|
+
while (end < src.length && (src[end] === " " || src[end] === " " || src[end] === "\n")) end += 1;
|
|
59644
|
+
pushToken(tokens, src.slice(i, end), "plain");
|
|
59645
|
+
i = end;
|
|
59646
|
+
continue;
|
|
59647
|
+
}
|
|
59648
|
+
if (ch === "#") {
|
|
59649
|
+
const nl = src.indexOf("\n", i + 1);
|
|
59650
|
+
const end = nl === -1 ? src.length : nl;
|
|
59651
|
+
pushToken(tokens, src.slice(i, end), "comment");
|
|
59652
|
+
i = end;
|
|
59653
|
+
continue;
|
|
59654
|
+
}
|
|
59655
|
+
let strStart = i;
|
|
59656
|
+
if (/[rRfFbBuU]/.test(ch)) {
|
|
59657
|
+
let p = i + 1;
|
|
59658
|
+
if (p < src.length && /[rRfFbBuU]/.test(src[p])) p += 1;
|
|
59659
|
+
if (src[p] === "\"" || src[p] === "'") strStart = p;
|
|
59660
|
+
}
|
|
59661
|
+
if (src[strStart] === "\"" || src[strStart] === "'") {
|
|
59662
|
+
const quote = src[strStart];
|
|
59663
|
+
const triple = src[strStart + 1] === quote && src[strStart + 2] === quote;
|
|
59664
|
+
const delim = triple ? quote.repeat(3) : quote;
|
|
59665
|
+
let end = strStart + delim.length;
|
|
59666
|
+
while (end < src.length) {
|
|
59667
|
+
if (src[end] === "\\") {
|
|
59668
|
+
end = Math.min(src.length, end + 2);
|
|
59669
|
+
continue;
|
|
59670
|
+
}
|
|
59671
|
+
if (triple && src.startsWith(delim, end)) {
|
|
59672
|
+
end += 3;
|
|
59673
|
+
break;
|
|
59674
|
+
}
|
|
59675
|
+
if (!triple && (src[end] === quote || src[end] === "\n")) {
|
|
59676
|
+
if (src[end] === quote) end += 1;
|
|
59677
|
+
break;
|
|
59678
|
+
}
|
|
59679
|
+
end += 1;
|
|
59680
|
+
}
|
|
59681
|
+
pushToken(tokens, src.slice(i, end), "string");
|
|
59682
|
+
i = end;
|
|
59683
|
+
continue;
|
|
59684
|
+
}
|
|
59685
|
+
if (isDigit(code) || ch === "." && i + 1 < src.length && isDigit(src.charCodeAt(i + 1))) {
|
|
59686
|
+
const end = scanNumber(src, i);
|
|
59687
|
+
pushToken(tokens, src.slice(i, end), "constant");
|
|
59688
|
+
i = end;
|
|
59689
|
+
continue;
|
|
59690
|
+
}
|
|
59691
|
+
if (isIdentStart(code)) {
|
|
59692
|
+
let end = i + 1;
|
|
59693
|
+
while (end < src.length && isIdentPart(src.charCodeAt(end))) end += 1;
|
|
59694
|
+
const word = src.slice(i, end);
|
|
59695
|
+
let prevNonSpace = i - 1;
|
|
59696
|
+
while (prevNonSpace >= 0 && (src[prevNonSpace] === " " || src[prevNonSpace] === " ")) prevNonSpace -= 1;
|
|
59697
|
+
const afterDot = prevNonSpace >= 0 && src[prevNonSpace] === ".";
|
|
59698
|
+
const beforeCall = src[skipWhitespaceLookahead(src, end)] === "(";
|
|
59699
|
+
if (!afterDot && PY_KEYWORDS.has(word)) pushToken(tokens, word, "keyword");
|
|
59700
|
+
else if (!afterDot && PY_CONSTANTS.has(word)) pushToken(tokens, word, "constant");
|
|
59701
|
+
else if (beforeCall) pushToken(tokens, word, "function");
|
|
59702
|
+
else pushToken(tokens, word, "plain");
|
|
59703
|
+
i = end;
|
|
59704
|
+
continue;
|
|
59705
|
+
}
|
|
59706
|
+
if (ch === "@" && i + 1 < src.length && isIdentStart(src.charCodeAt(i + 1))) {
|
|
59707
|
+
let end = i + 2;
|
|
59708
|
+
while (end < src.length && isIdentPart(src.charCodeAt(end))) end += 1;
|
|
59709
|
+
pushToken(tokens, src.slice(i, end), "function");
|
|
59710
|
+
i = end;
|
|
59711
|
+
continue;
|
|
59712
|
+
}
|
|
59713
|
+
pushToken(tokens, ch, "punctuation");
|
|
59714
|
+
i += 1;
|
|
59715
|
+
}
|
|
59716
|
+
return tokens;
|
|
59717
|
+
}
|
|
59718
|
+
//#endregion
|
|
59719
|
+
//#region src/client/codemode/CodeRunToolView.tsx
|
|
59720
|
+
/**
|
|
59721
|
+
* `code_run` 在对话流中的语法高亮工具行组件 —— 对齐宿主内置 PTC `run_code` 的呈现体验。
|
|
59722
|
+
*
|
|
59723
|
+
* ## 与宿主 `run_code` 一致的四点设计
|
|
59724
|
+
*
|
|
59725
|
+
* 1. **标题行**:代码图标 `</>` + 本地化标题「代码 / Code」+ `description` 摘要(不再出现
|
|
59726
|
+
* `工具 · code_run · ...`),直接接入框架传入的 `useDisclosure` 控制展开/收起;
|
|
59727
|
+
* 2. **源码区**:提取 `args.code` 纯源码文本(剥离外层 JSON 参数包装),提供语言标识
|
|
59728
|
+
* (`typescript` / `python`)、自动换行切换与一键复制源码按钮,并使用宿主 `--shiki-*`
|
|
59729
|
+
* 主题色进行语法高亮;
|
|
59730
|
+
* 3. **输出区**:已结算结果独立展示在下方 `输出` 卡片中(无结果文本时不画空卡片),子调用由外层
|
|
59731
|
+
* `ToolCallTree` 通过 `tool/ptc-dispatch` 自动挂载在本行下方;
|
|
59732
|
+
* 4. **三阶段支持**:覆盖 `preparing`(流式生成参数)、`start`(执行中)与 `result`(成功/失败/停止)。
|
|
59733
|
+
*
|
|
59734
|
+
* @module @eddyskywalker/dsh-chatgpt-subscription/client/codemode/CodeRunToolView
|
|
59735
|
+
*/
|
|
59736
|
+
function fallbackTranslate(key) {
|
|
59737
|
+
return zh$2[key] ?? key;
|
|
59738
|
+
}
|
|
59739
|
+
function firstLine(text) {
|
|
59740
|
+
const nl = text.indexOf("\n");
|
|
59741
|
+
return nl === -1 ? text : text.slice(0, nl);
|
|
59742
|
+
}
|
|
59743
|
+
function rawArgsOf(block) {
|
|
59744
|
+
if (typeof block.argsRaw === "string" && block.argsRaw !== "") return block.argsRaw;
|
|
59745
|
+
if (typeof block.call?.argsRaw === "string" && block.call.argsRaw !== "") return block.call.argsRaw;
|
|
59746
|
+
}
|
|
59747
|
+
function parseArgsObject(raw) {
|
|
59748
|
+
if (raw === void 0 || raw === "") return void 0;
|
|
59749
|
+
try {
|
|
59750
|
+
const parsed = JSON.parse(raw);
|
|
59751
|
+
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) return parsed;
|
|
59752
|
+
return;
|
|
59753
|
+
} catch {
|
|
59754
|
+
return;
|
|
59755
|
+
}
|
|
59756
|
+
}
|
|
59757
|
+
/** 从流式参数视图或完整 JSON 中读取字段(与 `ProgressRow` / `MinimaxVideoToolView` 一致)。 */
|
|
59758
|
+
function extractCodeRunArgs(block) {
|
|
59759
|
+
let streamCode;
|
|
59760
|
+
let streamDesc;
|
|
59761
|
+
const readText = block.args?.text;
|
|
59762
|
+
if (typeof readText === "function") {
|
|
59763
|
+
try {
|
|
59764
|
+
const c = readText.call(block.args, "code");
|
|
59765
|
+
if (typeof c === "string" && c !== "") streamCode = c;
|
|
59766
|
+
} catch {}
|
|
59767
|
+
try {
|
|
59768
|
+
const d = readText.call(block.args, "description");
|
|
59769
|
+
if (typeof d === "string" && d !== "") streamDesc = d;
|
|
59770
|
+
} catch {}
|
|
59771
|
+
}
|
|
59772
|
+
const raw = rawArgsOf(block);
|
|
59773
|
+
const parsed = parseArgsObject(raw);
|
|
59774
|
+
const jsonCode = typeof parsed?.["code"] === "string" && parsed["code"] !== "" ? parsed["code"] : void 0;
|
|
59775
|
+
const jsonDesc = typeof parsed?.["description"] === "string" && parsed["description"] !== "" ? parsed["description"] : void 0;
|
|
59776
|
+
const code = jsonCode ?? streamCode ?? null;
|
|
59777
|
+
return {
|
|
59778
|
+
code,
|
|
59779
|
+
description: firstLine(jsonDesc ?? streamDesc ?? ""),
|
|
59780
|
+
rawFallback: code === null && raw !== void 0 ? raw : null
|
|
59781
|
+
};
|
|
59782
|
+
}
|
|
59783
|
+
/** 展平已结算结果的内容块(对齐宿主 `resultText`)。 */
|
|
59784
|
+
function flattenCodeRunOutput(block) {
|
|
59785
|
+
if (block.kind === void 0) return null;
|
|
59786
|
+
const parts = [];
|
|
59787
|
+
for (const item of block.content ?? []) if (item.type === "text" && typeof item.text === "string") parts.push(item.text);
|
|
59788
|
+
else try {
|
|
59789
|
+
parts.push(JSON.stringify(item, null, 2));
|
|
59790
|
+
} catch {
|
|
59791
|
+
parts.push(String(item));
|
|
59792
|
+
}
|
|
59793
|
+
if (parts.length === 0 && block.error !== void 0) {
|
|
59794
|
+
const errName = block.error.name ?? "Error";
|
|
59795
|
+
const errCode = block.error.code ?? "UNKNOWN";
|
|
59796
|
+
parts.push(`${errName}: ${errCode}`);
|
|
59797
|
+
}
|
|
59798
|
+
const joined = parts.join("\n");
|
|
59799
|
+
return joined === "" ? null : joined;
|
|
59800
|
+
}
|
|
59801
|
+
function resolveLanguage(meta) {
|
|
59802
|
+
if (typeof meta === "object" && meta !== null && !Array.isArray(meta)) {
|
|
59803
|
+
if (meta["language"] === "python") return "python";
|
|
59804
|
+
}
|
|
59805
|
+
return "typescript";
|
|
59806
|
+
}
|
|
59807
|
+
function resolveState(phase, block) {
|
|
59808
|
+
if (!(block.kind !== void 0 || phase === "result")) return block.phase === "preparing" || phase === "preparing" ? "preparing" : "running";
|
|
59809
|
+
if (block.error?.code === "interrupted") return "stopped";
|
|
59810
|
+
const stopped = typeof block.meta === "object" && block.meta !== null && !Array.isArray(block.meta) && block.meta["stopped"] === true;
|
|
59811
|
+
if (block.isError === true || stopped) return "error";
|
|
59812
|
+
return "ok";
|
|
59813
|
+
}
|
|
59814
|
+
async function copyTextToClipboard(text) {
|
|
59815
|
+
try {
|
|
59816
|
+
if (typeof navigator !== "undefined" && typeof navigator.clipboard?.writeText === "function") {
|
|
59817
|
+
await navigator.clipboard.writeText(text);
|
|
59818
|
+
return true;
|
|
59819
|
+
}
|
|
59820
|
+
} catch {}
|
|
59821
|
+
if (typeof document === "undefined") return false;
|
|
59822
|
+
try {
|
|
59823
|
+
const textarea = document.createElement("textarea");
|
|
59824
|
+
textarea.value = text;
|
|
59825
|
+
textarea.setAttribute("readonly", "true");
|
|
59826
|
+
textarea.style.position = "fixed";
|
|
59827
|
+
textarea.style.opacity = "0";
|
|
59828
|
+
document.body.appendChild(textarea);
|
|
59829
|
+
textarea.select();
|
|
59830
|
+
const ok = document.execCommand("copy");
|
|
59831
|
+
document.body.removeChild(textarea);
|
|
59832
|
+
return ok;
|
|
59833
|
+
} catch {
|
|
59834
|
+
return false;
|
|
59835
|
+
}
|
|
59836
|
+
}
|
|
59837
|
+
function useFallbackDisclosure() {
|
|
59838
|
+
const [expanded, setExpanded] = (0, react.useState)(false);
|
|
59839
|
+
return {
|
|
59840
|
+
expanded,
|
|
59841
|
+
toggle: (0, react.useCallback)(() => {
|
|
59842
|
+
setExpanded((prev) => !prev);
|
|
59843
|
+
}, [])
|
|
59844
|
+
};
|
|
59845
|
+
}
|
|
59846
|
+
function CodeRunToolView(props) {
|
|
59847
|
+
const { block, phase, inspect, useDisclosure } = props;
|
|
59848
|
+
const t = props.t ?? fallbackTranslate;
|
|
59849
|
+
const { expanded, toggle } = (useDisclosure ?? useFallbackDisclosure)();
|
|
59850
|
+
const [wrapped, setWrapped] = (0, react.useState)(true);
|
|
59851
|
+
const [copied, setCopied] = (0, react.useState)(false);
|
|
59852
|
+
const state = resolveState(phase, block);
|
|
59853
|
+
const { code, description, rawFallback } = (0, react.useMemo)(() => extractCodeRunArgs(block), [block]);
|
|
59854
|
+
const outputText = (0, react.useMemo)(() => flattenCodeRunOutput(block), [block]);
|
|
59855
|
+
const language = (0, react.useMemo)(() => resolveLanguage(block.meta), [block.meta]);
|
|
59856
|
+
const sourceText = code ?? rawFallback;
|
|
59857
|
+
const expandable = state !== "preparing" && (sourceText !== null || outputText !== null);
|
|
59858
|
+
const open = expanded && expandable;
|
|
59859
|
+
const running = state === "preparing" || state === "running";
|
|
59860
|
+
const summaryText = (state === "error" && outputText !== null ? firstLine(outputText) : null) ?? (description !== "" ? description : block.callId ?? "");
|
|
59861
|
+
const highlightedLines = (0, react.useMemo)(() => open && sourceText !== null ? tokenizeCodeLines(sourceText, language) : null, [
|
|
59862
|
+
open,
|
|
59863
|
+
sourceText,
|
|
59864
|
+
language
|
|
59865
|
+
]);
|
|
59866
|
+
const onCopy = (0, react.useCallback)(() => {
|
|
59867
|
+
if (copied || sourceText === null) return;
|
|
59868
|
+
copyTextToClipboard(sourceText.endsWith("\n") ? sourceText.slice(0, -1) : sourceText).then((ok) => {
|
|
59869
|
+
if (!ok) return;
|
|
59870
|
+
setCopied(true);
|
|
59871
|
+
setTimeout(() => {
|
|
59872
|
+
setCopied(false);
|
|
59873
|
+
}, 1e3);
|
|
59874
|
+
});
|
|
59875
|
+
}, [copied, sourceText]);
|
|
59876
|
+
const onRowKeyDown = (0, react.useCallback)((event) => {
|
|
59877
|
+
if (!expandable || event.key !== "Enter" && event.key !== " ") return;
|
|
59878
|
+
event.preventDefault();
|
|
59879
|
+
toggle();
|
|
59880
|
+
}, [expandable, toggle]);
|
|
59881
|
+
const a11yStatus = state === "preparing" ? t("codeRunPreparing") : state === "running" ? t("codeRunRunning") : state === "error" ? t("codeRunFailed") : state === "stopped" ? t("codeRunStopped") : null;
|
|
59882
|
+
const wrapLabel = wrapped ? t("codeRunUnwrap") : t("codeRunWrap");
|
|
59883
|
+
const copyLabel = copied ? t("codeRunCopied") : t("codeRunCopy");
|
|
59884
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
59885
|
+
className: "dshc-code-root",
|
|
59886
|
+
"data-variant": "code",
|
|
59887
|
+
"data-tool": props.toolName ?? "code_run",
|
|
59888
|
+
"data-state": state,
|
|
59889
|
+
children: [
|
|
59890
|
+
a11yStatus !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
59891
|
+
className: "dshc-code-visually-hidden",
|
|
59892
|
+
children: a11yStatus
|
|
59893
|
+
}),
|
|
59894
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
59895
|
+
className: "dshc-code-header",
|
|
59896
|
+
"data-disclosure-header": true,
|
|
59897
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
59898
|
+
className: "dshc-code-row",
|
|
59899
|
+
"data-disclosure-row": true,
|
|
59900
|
+
"data-expandable": expandable ? "true" : void 0,
|
|
59901
|
+
role: expandable ? "button" : void 0,
|
|
59902
|
+
tabIndex: expandable ? 0 : void 0,
|
|
59903
|
+
"aria-expanded": expandable ? open : void 0,
|
|
59904
|
+
onClick: expandable ? toggle : void 0,
|
|
59905
|
+
onKeyDown: expandable ? onRowKeyDown : void 0,
|
|
59906
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
59907
|
+
className: "dshc-code-leading",
|
|
59908
|
+
"aria-hidden": "true",
|
|
59909
|
+
children: open ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronUpIcon, {}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
59910
|
+
className: "dshc-code-icon-idle",
|
|
59911
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodeGlyphIcon, {})
|
|
59912
|
+
}), expandable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
59913
|
+
className: "dshc-code-chevron-hover",
|
|
59914
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronDownIcon, {})
|
|
59915
|
+
})] })
|
|
59916
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
59917
|
+
className: "dshc-code-text-flow",
|
|
59918
|
+
"data-running": running ? "true" : void 0,
|
|
59919
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
59920
|
+
className: "dshc-code-title",
|
|
59921
|
+
children: t("codeRunTitle")
|
|
59922
|
+
}), summaryText !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
59923
|
+
className: "dshc-code-sep",
|
|
59924
|
+
"aria-hidden": "true"
|
|
59925
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
59926
|
+
className: "dshc-code-summary",
|
|
59927
|
+
"data-state": state === "error" || state === "stopped" ? state : void 0,
|
|
59928
|
+
children: summaryText
|
|
59929
|
+
})] })]
|
|
59930
|
+
})]
|
|
59931
|
+
})
|
|
59932
|
+
}),
|
|
59933
|
+
open && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
59934
|
+
className: "dshc-code-body-wrap",
|
|
59935
|
+
children: [
|
|
59936
|
+
sourceText !== null && highlightedLines !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
59937
|
+
className: "dshc-code-body-scroll",
|
|
59938
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
59939
|
+
className: "dshc-code-card md-code-block",
|
|
59940
|
+
"data-code-wrap": wrapped ? "true" : "false",
|
|
59941
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
59942
|
+
className: "dshc-code-toolbar",
|
|
59943
|
+
"data-code-block-banner": true,
|
|
59944
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
59945
|
+
className: "dshc-code-lang",
|
|
59946
|
+
children: language
|
|
59947
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
59948
|
+
className: "dshc-code-actions",
|
|
59949
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
59950
|
+
type: "button",
|
|
59951
|
+
className: "dshc-code-action",
|
|
59952
|
+
title: wrapLabel,
|
|
59953
|
+
"aria-label": t("codeRunWrap"),
|
|
59954
|
+
"aria-pressed": wrapped,
|
|
59955
|
+
onClick: () => {
|
|
59956
|
+
setWrapped((prev) => !prev);
|
|
59957
|
+
},
|
|
59958
|
+
children: wrapped ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NowrapIcon, {}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WrapIcon, {})
|
|
59959
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
59960
|
+
type: "button",
|
|
59961
|
+
className: "dshc-code-action",
|
|
59962
|
+
title: copyLabel,
|
|
59963
|
+
"aria-label": copyLabel,
|
|
59964
|
+
onClick: onCopy,
|
|
59965
|
+
children: copied ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CheckIcon, {}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopyIcon, {})
|
|
59966
|
+
})]
|
|
59967
|
+
})]
|
|
59968
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
|
|
59969
|
+
className: "shiki css-variables dshc-code-pre",
|
|
59970
|
+
tabIndex: 0,
|
|
59971
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: highlightedLines.map((line, lineIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [lineIndex > 0 && "\n", /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
59972
|
+
className: "line",
|
|
59973
|
+
children: line.map((span, spanIndex) => {
|
|
59974
|
+
const color = SHIKI_TOKEN_COLORS[span.kind];
|
|
59975
|
+
return color === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Fragment, { children: span.text }, spanIndex) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
59976
|
+
style: { color },
|
|
59977
|
+
children: span.text
|
|
59978
|
+
}, spanIndex);
|
|
59979
|
+
})
|
|
59980
|
+
})] }, lineIndex)) })
|
|
59981
|
+
})]
|
|
59982
|
+
})
|
|
59983
|
+
}),
|
|
59984
|
+
outputText !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
59985
|
+
className: "dshc-code-io-card",
|
|
59986
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
59987
|
+
className: "dshc-code-io-section",
|
|
59988
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
59989
|
+
className: "dshc-code-io-label",
|
|
59990
|
+
children: t("codeRunOutput")
|
|
59991
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
59992
|
+
className: "dshc-code-io-text",
|
|
59993
|
+
"data-error": state === "error" ? "true" : void 0,
|
|
59994
|
+
children: outputText
|
|
59995
|
+
})]
|
|
59996
|
+
})
|
|
59997
|
+
}),
|
|
59998
|
+
inspect !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
59999
|
+
type: "button",
|
|
60000
|
+
className: "dshc-code-inspect-btn",
|
|
60001
|
+
onClick: inspect,
|
|
60002
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(InspectIcon, {}), t("codeRunInspect")]
|
|
60003
|
+
})
|
|
60004
|
+
]
|
|
60005
|
+
})
|
|
60006
|
+
]
|
|
60007
|
+
});
|
|
60008
|
+
}
|
|
60009
|
+
function CodeGlyphIcon() {
|
|
60010
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
60011
|
+
viewBox: "0 0 16 16",
|
|
60012
|
+
fill: "none",
|
|
60013
|
+
stroke: "currentColor",
|
|
60014
|
+
strokeWidth: "1.4",
|
|
60015
|
+
strokeLinecap: "round",
|
|
60016
|
+
strokeLinejoin: "round",
|
|
60017
|
+
children: [
|
|
60018
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M5.2 4.5L1.8 8l3.4 3.5" }),
|
|
60019
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M10.8 4.5L14.2 8l-3.4 3.5" }),
|
|
60020
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M9.2 3L6.8 13" })
|
|
60021
|
+
]
|
|
60022
|
+
});
|
|
60023
|
+
}
|
|
60024
|
+
function ChevronDownIcon() {
|
|
60025
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
60026
|
+
viewBox: "0 0 16 16",
|
|
60027
|
+
fill: "none",
|
|
60028
|
+
stroke: "currentColor",
|
|
60029
|
+
strokeWidth: "1.5",
|
|
60030
|
+
strokeLinecap: "round",
|
|
60031
|
+
strokeLinejoin: "round",
|
|
60032
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M4 6l4 4 4-4" })
|
|
60033
|
+
});
|
|
60034
|
+
}
|
|
60035
|
+
function ChevronUpIcon() {
|
|
60036
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
60037
|
+
viewBox: "0 0 16 16",
|
|
60038
|
+
fill: "none",
|
|
60039
|
+
stroke: "currentColor",
|
|
60040
|
+
strokeWidth: "1.5",
|
|
60041
|
+
strokeLinecap: "round",
|
|
60042
|
+
strokeLinejoin: "round",
|
|
60043
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M4 10l4-4 4 4" })
|
|
60044
|
+
});
|
|
60045
|
+
}
|
|
60046
|
+
function CopyIcon() {
|
|
60047
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
60048
|
+
width: "14",
|
|
60049
|
+
height: "14",
|
|
60050
|
+
viewBox: "0 0 16 16",
|
|
60051
|
+
fill: "none",
|
|
60052
|
+
stroke: "currentColor",
|
|
60053
|
+
strokeWidth: "1.35",
|
|
60054
|
+
strokeLinecap: "round",
|
|
60055
|
+
strokeLinejoin: "round",
|
|
60056
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
|
|
60057
|
+
x: "5.5",
|
|
60058
|
+
y: "5.5",
|
|
60059
|
+
width: "8",
|
|
60060
|
+
height: "8",
|
|
60061
|
+
rx: "1.5"
|
|
60062
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M10.5 5.5V3.8A1.3 1.3 0 0 0 9.2 2.5H3.8A1.3 1.3 0 0 0 2.5 3.8v5.4a1.3 1.3 0 0 0 1.3 1.3h1.7" })]
|
|
60063
|
+
});
|
|
60064
|
+
}
|
|
60065
|
+
function CheckIcon() {
|
|
60066
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
60067
|
+
width: "14",
|
|
60068
|
+
height: "14",
|
|
60069
|
+
viewBox: "0 0 16 16",
|
|
60070
|
+
fill: "none",
|
|
60071
|
+
stroke: "currentColor",
|
|
60072
|
+
strokeWidth: "1.6",
|
|
60073
|
+
strokeLinecap: "round",
|
|
60074
|
+
strokeLinejoin: "round",
|
|
60075
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M3.2 8.4l3.1 3.1 6.5-6.5" })
|
|
60076
|
+
});
|
|
60077
|
+
}
|
|
60078
|
+
function WrapIcon() {
|
|
60079
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
60080
|
+
width: "14",
|
|
60081
|
+
height: "14",
|
|
60082
|
+
viewBox: "0 0 16 16",
|
|
60083
|
+
fill: "none",
|
|
60084
|
+
stroke: "currentColor",
|
|
60085
|
+
strokeWidth: "1.35",
|
|
60086
|
+
strokeLinecap: "round",
|
|
60087
|
+
strokeLinejoin: "round",
|
|
60088
|
+
children: [
|
|
60089
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M2.5 4h11" }),
|
|
60090
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M2.5 8h8.5a2.2 2.2 0 1 1 0 4.4H8.2" }),
|
|
60091
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M9.8 10.8L8 12.4l1.8 1.6" }),
|
|
60092
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M2.5 12.4h3" })
|
|
60093
|
+
]
|
|
60094
|
+
});
|
|
60095
|
+
}
|
|
60096
|
+
function NowrapIcon() {
|
|
60097
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
60098
|
+
width: "14",
|
|
60099
|
+
height: "14",
|
|
60100
|
+
viewBox: "0 0 16 16",
|
|
60101
|
+
fill: "none",
|
|
60102
|
+
stroke: "currentColor",
|
|
60103
|
+
strokeWidth: "1.35",
|
|
60104
|
+
strokeLinecap: "round",
|
|
60105
|
+
strokeLinejoin: "round",
|
|
60106
|
+
children: [
|
|
60107
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M2.5 4h11" }),
|
|
60108
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M2.5 8h11" }),
|
|
60109
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M11.5 6.2L13.5 8l-2 1.8" }),
|
|
60110
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M2.5 12h7" })
|
|
60111
|
+
]
|
|
60112
|
+
});
|
|
60113
|
+
}
|
|
60114
|
+
function InspectIcon() {
|
|
60115
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
60116
|
+
width: "12",
|
|
60117
|
+
height: "12",
|
|
60118
|
+
viewBox: "0 0 16 16",
|
|
60119
|
+
fill: "none",
|
|
60120
|
+
stroke: "currentColor",
|
|
60121
|
+
strokeWidth: "1.4",
|
|
60122
|
+
strokeLinecap: "round",
|
|
60123
|
+
strokeLinejoin: "round",
|
|
60124
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
|
|
60125
|
+
cx: "7.2",
|
|
60126
|
+
cy: "7.2",
|
|
60127
|
+
r: "4.5"
|
|
60128
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M10.6 10.6L13.8 13.8" })]
|
|
60129
|
+
});
|
|
60130
|
+
}
|
|
60131
|
+
//#endregion
|
|
60132
|
+
//#region src/client/codemode/styles.ts
|
|
60133
|
+
/**
|
|
60134
|
+
* `code_run` 工具行样式表 —— 对齐宿主内置 `run_code`(`DisclosureRow` + `ToolRow` +
|
|
60135
|
+
* `CodeBlock` + `CodeToolbar`)的视觉令牌与排版节奏。
|
|
60136
|
+
*
|
|
60137
|
+
* 所有颜色、字号与圆角均直接引用宿主 `--dsw-*` / `--dsh-*` / `--shiki-*` CSS 变量。
|
|
60138
|
+
*
|
|
60139
|
+
* @module @eddyskywalker/dsh-chatgpt-subscription/client/codemode/styles
|
|
60140
|
+
*/
|
|
60141
|
+
const CODEMODE_CSS = `
|
|
60142
|
+
.dshc-code-root {
|
|
60143
|
+
display: flex;
|
|
60144
|
+
flex-direction: column;
|
|
60145
|
+
width: 100%;
|
|
60146
|
+
min-width: 0;
|
|
60147
|
+
}
|
|
60148
|
+
|
|
60149
|
+
.dshc-code-visually-hidden {
|
|
60150
|
+
position: absolute;
|
|
60151
|
+
width: 1px;
|
|
60152
|
+
height: 1px;
|
|
60153
|
+
overflow: hidden;
|
|
60154
|
+
clip: rect(0 0 0 0);
|
|
60155
|
+
white-space: nowrap;
|
|
60156
|
+
}
|
|
60157
|
+
|
|
60158
|
+
.dshc-code-header {
|
|
60159
|
+
display: flex;
|
|
60160
|
+
align-items: center;
|
|
60161
|
+
min-width: 0;
|
|
60162
|
+
}
|
|
60163
|
+
|
|
60164
|
+
.dshc-code-row {
|
|
60165
|
+
flex: 1 1 auto;
|
|
60166
|
+
position: relative;
|
|
60167
|
+
overflow: hidden;
|
|
60168
|
+
display: flex;
|
|
60169
|
+
align-items: center;
|
|
60170
|
+
height: calc(24px + var(--dsh-content-font-delta, 0px));
|
|
60171
|
+
min-width: 0;
|
|
60172
|
+
color: var(--dsw-alias-label-tertiary, #8a9099);
|
|
60173
|
+
transition: color 100ms ease;
|
|
60174
|
+
user-select: none;
|
|
60175
|
+
}
|
|
60176
|
+
|
|
60177
|
+
.dshc-code-row[data-expandable='true'] {
|
|
60178
|
+
cursor: pointer;
|
|
60179
|
+
}
|
|
60180
|
+
|
|
60181
|
+
@media (hover: hover) {
|
|
60182
|
+
.dshc-code-row:hover {
|
|
60183
|
+
color: var(--dsw-alias-label-secondary, #5b6270);
|
|
60184
|
+
}
|
|
60185
|
+
}
|
|
60186
|
+
|
|
60187
|
+
.dshc-code-row:focus-visible {
|
|
60188
|
+
outline: 1px solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary, #4d6bfe));
|
|
60189
|
+
outline-offset: 2px;
|
|
60190
|
+
border-radius: var(--dsw-radius-sm, 4px);
|
|
60191
|
+
}
|
|
60192
|
+
|
|
60193
|
+
.dshc-code-leading {
|
|
60194
|
+
position: relative;
|
|
60195
|
+
flex: none;
|
|
60196
|
+
width: calc(16px + var(--dsh-content-font-delta, 0px));
|
|
60197
|
+
height: calc(16px + var(--dsh-content-font-delta, 0px));
|
|
60198
|
+
display: inline-flex;
|
|
60199
|
+
align-items: center;
|
|
60200
|
+
justify-content: center;
|
|
60201
|
+
margin-right: 6px;
|
|
60202
|
+
color: inherit;
|
|
60203
|
+
}
|
|
60204
|
+
|
|
60205
|
+
.dshc-code-leading svg {
|
|
60206
|
+
width: calc(14px + var(--dsh-content-font-delta, 0px));
|
|
60207
|
+
height: calc(14px + var(--dsh-content-font-delta, 0px));
|
|
60208
|
+
}
|
|
60209
|
+
|
|
60210
|
+
.dshc-code-icon-idle {
|
|
60211
|
+
display: inline-flex;
|
|
60212
|
+
opacity: 1;
|
|
60213
|
+
transition: opacity 100ms ease;
|
|
60214
|
+
}
|
|
60215
|
+
|
|
60216
|
+
.dshc-code-chevron-hover {
|
|
60217
|
+
position: absolute;
|
|
60218
|
+
inset: 0;
|
|
60219
|
+
margin: auto;
|
|
60220
|
+
opacity: 0;
|
|
60221
|
+
transition: opacity 100ms ease;
|
|
60222
|
+
}
|
|
60223
|
+
|
|
60224
|
+
@media (hover: hover) {
|
|
60225
|
+
.dshc-code-row[data-expandable='true']:hover .dshc-code-icon-idle {
|
|
60226
|
+
opacity: 0;
|
|
60227
|
+
}
|
|
60228
|
+
.dshc-code-row[data-expandable='true']:hover .dshc-code-chevron-hover {
|
|
60229
|
+
opacity: 1;
|
|
60230
|
+
}
|
|
60231
|
+
}
|
|
60232
|
+
|
|
60233
|
+
.dshc-code-text-flow {
|
|
60234
|
+
display: flex;
|
|
60235
|
+
align-items: center;
|
|
60236
|
+
flex: 1 1 auto;
|
|
60237
|
+
min-width: 0;
|
|
60238
|
+
overflow: hidden;
|
|
60239
|
+
}
|
|
60240
|
+
|
|
60241
|
+
@keyframes dshc-shimmer-pulse {
|
|
60242
|
+
0%, 100% { opacity: 1; }
|
|
60243
|
+
50% { opacity: 0.55; }
|
|
60244
|
+
}
|
|
60245
|
+
|
|
60246
|
+
.dshc-code-text-flow[data-running='true'] {
|
|
60247
|
+
animation: dshc-shimmer-pulse 1.6s ease-in-out infinite;
|
|
60248
|
+
}
|
|
60249
|
+
|
|
60250
|
+
.dshc-code-title {
|
|
60251
|
+
flex: none;
|
|
60252
|
+
font-weight: 400;
|
|
60253
|
+
font-size: var(--dsh-content-font-size-secondary, 13px);
|
|
60254
|
+
line-height: calc(24px + var(--dsh-content-font-delta, 0px));
|
|
60255
|
+
color: inherit;
|
|
60256
|
+
}
|
|
60257
|
+
|
|
60258
|
+
.dshc-code-sep {
|
|
60259
|
+
flex: none;
|
|
60260
|
+
width: 2px;
|
|
60261
|
+
height: 2px;
|
|
60262
|
+
border-radius: 1px;
|
|
60263
|
+
margin: 0 8px;
|
|
60264
|
+
background: var(--dsw-alias-label-caption, #8a9099);
|
|
60265
|
+
}
|
|
60266
|
+
|
|
60267
|
+
.dshc-code-summary {
|
|
60268
|
+
flex: 1 1 auto;
|
|
60269
|
+
min-width: 0;
|
|
60270
|
+
overflow: hidden;
|
|
60271
|
+
text-overflow: ellipsis;
|
|
60272
|
+
white-space: nowrap;
|
|
60273
|
+
font-size: var(--dsh-content-font-size-secondary, 13px);
|
|
60274
|
+
line-height: calc(24px + var(--dsh-content-font-delta, 0px));
|
|
60275
|
+
}
|
|
60276
|
+
|
|
60277
|
+
.dshc-code-summary[data-state='error'] {
|
|
60278
|
+
color: var(--dsw-alias-state-error-primary, #d54941);
|
|
60279
|
+
}
|
|
60280
|
+
|
|
60281
|
+
.dshc-code-summary[data-state='stopped'] {
|
|
60282
|
+
color: var(--dsw-alias-state-warn-label, #d97706);
|
|
60283
|
+
}
|
|
60284
|
+
|
|
60285
|
+
.dshc-code-body-wrap {
|
|
60286
|
+
display: flex;
|
|
60287
|
+
flex-direction: column;
|
|
60288
|
+
}
|
|
60289
|
+
|
|
60290
|
+
.dshc-code-body-scroll {
|
|
60291
|
+
max-height: 260px;
|
|
60292
|
+
overflow-y: auto;
|
|
60293
|
+
margin: 4px 0 4px 4px;
|
|
60294
|
+
border-radius: var(--dsw-radius-lg, 10px);
|
|
60295
|
+
border: 0.5px solid var(--dsw-alias-border-l1, rgba(128, 128, 128, 0.18));
|
|
60296
|
+
background: var(--dsw-alias-markdown-code-block, rgba(128, 128, 128, 0.08));
|
|
60297
|
+
}
|
|
60298
|
+
|
|
60299
|
+
.dshc-code-card {
|
|
60300
|
+
position: relative;
|
|
60301
|
+
color: var(--dsw-alias-label-primary, inherit);
|
|
60302
|
+
background: transparent;
|
|
60303
|
+
font: var(--dsw-font-markdown-code-block, 13px/20px var(--ds-font-family-code, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace));
|
|
60304
|
+
}
|
|
60305
|
+
|
|
60306
|
+
.dshc-code-toolbar {
|
|
60307
|
+
position: sticky;
|
|
60308
|
+
top: 0;
|
|
60309
|
+
z-index: 6;
|
|
60310
|
+
display: flex;
|
|
60311
|
+
align-items: center;
|
|
60312
|
+
justify-content: space-between;
|
|
60313
|
+
gap: 12px;
|
|
60314
|
+
padding: 10px 18px 8px 22px;
|
|
60315
|
+
background: var(--dsw-alias-markdown-code-block, #1e222a);
|
|
60316
|
+
color: var(--dsw-alias-label-secondary, #8a9099);
|
|
60317
|
+
font: 11px/18px var(--dsw-font-family, system-ui, sans-serif);
|
|
60318
|
+
}
|
|
60319
|
+
|
|
60320
|
+
.dshc-code-lang {
|
|
60321
|
+
color: var(--dsw-alias-label-tertiary, #8a9099);
|
|
60322
|
+
flex: none;
|
|
60323
|
+
font-family: var(--ds-font-family-code, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
|
|
60324
|
+
}
|
|
60325
|
+
|
|
60326
|
+
.dshc-code-actions {
|
|
60327
|
+
display: flex;
|
|
60328
|
+
align-items: center;
|
|
60329
|
+
gap: 4px;
|
|
60330
|
+
flex: none;
|
|
60331
|
+
}
|
|
60332
|
+
|
|
60333
|
+
.dshc-code-action {
|
|
60334
|
+
display: inline-flex;
|
|
60335
|
+
align-items: center;
|
|
60336
|
+
justify-content: center;
|
|
60337
|
+
width: 24px;
|
|
60338
|
+
height: 24px;
|
|
60339
|
+
padding: 0;
|
|
60340
|
+
border: 0;
|
|
60341
|
+
border-radius: var(--dsw-radius-sm, 4px);
|
|
60342
|
+
color: var(--dsw-alias-label-secondary, #8a9099);
|
|
60343
|
+
background: transparent;
|
|
60344
|
+
cursor: pointer;
|
|
60345
|
+
}
|
|
60346
|
+
|
|
60347
|
+
@media (hover: hover) {
|
|
60348
|
+
.dshc-code-action:hover {
|
|
60349
|
+
background: var(--dsw-alias-interactive-bg-hover, rgba(128, 128, 128, 0.14));
|
|
60350
|
+
color: var(--dsw-alias-label-primary, inherit);
|
|
60351
|
+
}
|
|
60352
|
+
}
|
|
60353
|
+
|
|
60354
|
+
.dshc-code-action:focus-visible {
|
|
60355
|
+
outline: 1px solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary, #4d6bfe));
|
|
60356
|
+
outline-offset: 2px;
|
|
60357
|
+
}
|
|
60358
|
+
|
|
60359
|
+
.dshc-code-pre {
|
|
60360
|
+
margin: 0 !important;
|
|
60361
|
+
padding: 6px 22px 20px;
|
|
60362
|
+
font: var(--dsw-font-markdown-code-block, 13px/20px var(--ds-font-family-code, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace));
|
|
60363
|
+
background: transparent !important;
|
|
60364
|
+
color: var(--shiki-foreground, var(--dsw-alias-label-primary, inherit));
|
|
60365
|
+
overflow-x: auto;
|
|
60366
|
+
white-space: pre-wrap;
|
|
60367
|
+
word-break: normal;
|
|
60368
|
+
overflow-wrap: anywhere;
|
|
60369
|
+
}
|
|
60370
|
+
|
|
60371
|
+
.dshc-code-card[data-code-wrap='false'] .dshc-code-pre {
|
|
60372
|
+
white-space: pre;
|
|
60373
|
+
overflow-wrap: normal;
|
|
60374
|
+
}
|
|
60375
|
+
|
|
60376
|
+
.dshc-code-pre code {
|
|
60377
|
+
font: inherit;
|
|
60378
|
+
background: none;
|
|
60379
|
+
padding: 0;
|
|
60380
|
+
}
|
|
60381
|
+
|
|
60382
|
+
.dshc-code-io-card {
|
|
60383
|
+
display: flex;
|
|
60384
|
+
flex-direction: column;
|
|
60385
|
+
margin: 4px 0 4px 4px;
|
|
60386
|
+
border: 0.5px solid var(--dsw-alias-border-l1, rgba(128, 128, 128, 0.18));
|
|
60387
|
+
border-radius: var(--dsw-radius-lg, 10px);
|
|
60388
|
+
background: var(--dsw-alias-markdown-code-block, rgba(128, 128, 128, 0.08));
|
|
60389
|
+
font: var(--dsw-font-markdown-code-block-small, 12px/18px var(--ds-font-family-code, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace));
|
|
60390
|
+
}
|
|
60391
|
+
|
|
60392
|
+
.dshc-code-io-section {
|
|
60393
|
+
display: grid;
|
|
60394
|
+
grid-template-columns: max-content 1fr;
|
|
60395
|
+
column-gap: 14px;
|
|
60396
|
+
align-items: baseline;
|
|
60397
|
+
padding: 12px 16px;
|
|
60398
|
+
max-height: 150px;
|
|
60399
|
+
overflow-y: auto;
|
|
60400
|
+
}
|
|
60401
|
+
|
|
60402
|
+
.dshc-code-io-label {
|
|
60403
|
+
position: sticky;
|
|
60404
|
+
top: 0;
|
|
60405
|
+
align-self: start;
|
|
60406
|
+
color: var(--dsw-alias-label-caption, #8a9099);
|
|
60407
|
+
}
|
|
60408
|
+
|
|
60409
|
+
.dshc-code-io-text {
|
|
60410
|
+
min-width: 0;
|
|
60411
|
+
white-space: pre-wrap;
|
|
60412
|
+
word-break: break-word;
|
|
60413
|
+
color: var(--dsw-alias-label-secondary, #8a9099);
|
|
60414
|
+
}
|
|
60415
|
+
|
|
60416
|
+
.dshc-code-io-text[data-error='true'] {
|
|
60417
|
+
color: var(--dsw-alias-state-error-primary, #d54941);
|
|
60418
|
+
}
|
|
60419
|
+
|
|
60420
|
+
.dshc-code-inspect-btn {
|
|
60421
|
+
display: inline-flex;
|
|
60422
|
+
align-self: flex-start;
|
|
60423
|
+
align-items: center;
|
|
60424
|
+
gap: 4px;
|
|
60425
|
+
margin: 4px 0 2px 4px;
|
|
60426
|
+
padding: 2px 8px;
|
|
60427
|
+
border: 0.5px solid var(--dsw-alias-border-l3, rgba(128, 128, 128, 0.25));
|
|
60428
|
+
border-radius: 999px;
|
|
60429
|
+
background: var(--dsw-alias-bg-base, transparent);
|
|
60430
|
+
color: var(--dsw-alias-label-secondary, #8a9099);
|
|
60431
|
+
font-size: 11px;
|
|
60432
|
+
line-height: 16px;
|
|
60433
|
+
cursor: pointer;
|
|
60434
|
+
opacity: 0;
|
|
60435
|
+
transition: opacity 100ms ease;
|
|
60436
|
+
}
|
|
60437
|
+
|
|
60438
|
+
.dshc-code-inspect-btn:focus-visible {
|
|
60439
|
+
opacity: 1;
|
|
60440
|
+
}
|
|
60441
|
+
|
|
60442
|
+
@media (hover: hover) {
|
|
60443
|
+
.dshc-code-root:hover .dshc-code-inspect-btn {
|
|
60444
|
+
opacity: 1;
|
|
60445
|
+
}
|
|
60446
|
+
.dshc-code-inspect-btn:hover {
|
|
60447
|
+
background: var(--dsw-alias-interactive-bg-hover-solid, rgba(128, 128, 128, 0.18));
|
|
60448
|
+
color: var(--dsw-alias-label-primary, inherit);
|
|
60449
|
+
}
|
|
60450
|
+
}
|
|
60451
|
+
|
|
60452
|
+
@media (hover: none) {
|
|
60453
|
+
.dshc-code-inspect-btn {
|
|
60454
|
+
opacity: 1;
|
|
60455
|
+
}
|
|
60456
|
+
}
|
|
60457
|
+
|
|
60458
|
+
@media (prefers-reduced-motion: reduce) {
|
|
60459
|
+
.dshc-code-row,
|
|
60460
|
+
.dshc-code-text-flow[data-running='true'] {
|
|
60461
|
+
transition: none;
|
|
60462
|
+
animation: none;
|
|
60463
|
+
}
|
|
60464
|
+
}
|
|
60465
|
+
`;
|
|
60466
|
+
function installCodemodeStyles() {
|
|
60467
|
+
return installPluginStyle("codemode", CODEMODE_CSS);
|
|
60468
|
+
}
|
|
60469
|
+
//#endregion
|
|
60470
|
+
//#region src/client/codemode/tool-name.ts
|
|
60471
|
+
/**
|
|
60472
|
+
* 客户端半边的 `code_run` 工具名常量。
|
|
60473
|
+
*
|
|
60474
|
+
* 独立于 `../../host/codemode/transport.ts`,避免浏览器 bundle 引入 Node 端模块;
|
|
60475
|
+
* 单测会校验两边字面量逐字一致。
|
|
60476
|
+
*
|
|
60477
|
+
* @module @eddyskywalker/dsh-chatgpt-subscription/client/codemode/tool-name
|
|
60478
|
+
*/
|
|
60479
|
+
const CODE_RUN_TOOL_NAME = "code_run";
|
|
60480
|
+
//#endregion
|
|
59028
60481
|
//#region src/client/index.tsx
|
|
59029
60482
|
const inject = [
|
|
59030
60483
|
"slots",
|
|
@@ -59110,6 +60563,7 @@ window.__ModuleLoader__.load({
|
|
|
59110
60563
|
}, "dsh-subagent-settings: styles");
|
|
59111
60564
|
ctx.effect(() => {
|
|
59112
60565
|
installPoolStyles();
|
|
60566
|
+
installCodemodeStyles();
|
|
59113
60567
|
return () => {};
|
|
59114
60568
|
}, "dsh-chatgpt-subscription: pool styles");
|
|
59115
60569
|
ctx.effect(() => setupMermaidObserver(), "dsh-mermaid: observer");
|
|
@@ -59239,6 +60693,11 @@ window.__ModuleLoader__.load({
|
|
|
59239
60693
|
readVideo: videoBytesLoader(ctx)
|
|
59240
60694
|
})
|
|
59241
60695
|
}, MinimaxVideoToolView));
|
|
60696
|
+
ctx.slots.inject("tool.call.toolview", () => ctx.slots.register({
|
|
60697
|
+
name: "tool.call.toolview",
|
|
60698
|
+
key: CODE_RUN_TOOL_NAME,
|
|
60699
|
+
locale: NS
|
|
60700
|
+
}, CodeRunToolView));
|
|
59242
60701
|
installVideoDocumentPreview(ctx);
|
|
59243
60702
|
installSubagentSettingsCard(ctx);
|
|
59244
60703
|
installProgressUpdatesClient(ctx);
|