@openspecui/web 3.11.3 → 3.11.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/CanvasRenderer-CaB1iANG.js +1 -0
- package/dist/assets/WebGLRenderer-BQkM8hJI.js +1 -0
- package/dist/assets/WebGPURenderer-DL2luov0.js +1 -0
- package/dist/assets/audio-preview-EEAGPjut.js +1 -0
- package/dist/assets/browserAll-77yDI0Dz.js +1 -0
- package/dist/assets/common-Cv1DC55Y.js +22 -0
- package/dist/assets/common-tDRAnupk.css +1 -0
- package/dist/assets/{dist-Bl4uejAA.js → dist-B85dtRfx.js} +1 -1
- package/dist/assets/dist-B8IUilny.js +1 -0
- package/dist/assets/{dist-CkEGbci5.js → dist-BRxF7Jkf.js} +1 -1
- package/dist/assets/{dist-DDPVC2MF.js → dist-BZECNWGg.js} +1 -1
- package/dist/assets/{dist-BVKuVv2H.js → dist-BfZLQFwN.js} +1 -1
- package/dist/assets/{dist-Caq73PXT.js → dist-CbJQUXs0.js} +1 -1
- package/dist/assets/{dist-rlrlm1HB.js → dist-CmKsGuOc.js} +1 -1
- package/dist/assets/{dist-YXnB8lV1.js → dist-DiwHgET9.js} +1 -1
- package/dist/assets/dist-Djq8Qfgl.js +1 -0
- package/dist/assets/dist-DpKtO7Rd.js +1 -0
- package/dist/assets/{dist-CZh2GIVt.js → dist-SfwxOhmW.js} +1 -1
- package/dist/assets/{dist-BKY1RG9s.js → dist-zpg9m3aC.js} +1 -1
- package/dist/assets/{image-preview-BvROjYK5.js → image-preview-D763uzFX.js} +1 -1
- package/dist/assets/{init-sSrVfvjg.js → init-fMWSa5Px.js} +1 -1
- package/dist/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
- package/dist/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
- package/dist/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/dist/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/dist/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
- package/dist/assets/main-C9sK_hBV.js +1669 -0
- package/dist/assets/main-X9jaWXie.css +1 -0
- package/dist/assets/{media-preview-DWkSTGaX.js → media-preview-CKyl7d05.js} +1 -1
- package/dist/assets/{pdf-preview-C7gTFuZg.js → pdf-preview-CZGViMN9.js} +1 -1
- package/dist/assets/share-tech-mono-latin-400-normal-15MgdvEM.woff +0 -0
- package/dist/assets/share-tech-mono-latin-400-normal-CCqdbj5z.woff2 +0 -0
- package/dist/assets/trpc-CYA_MIjc.js +1 -0
- package/dist/assets/video-preview-zIpjT8bC.js +1 -0
- package/dist/assets/webworkerAll-BDQFYrM_.js +1 -0
- package/dist/audio-preview.html +4 -3
- package/dist/image-preview.html +3 -2
- package/dist/index.html +2 -29
- package/dist/pdf-preview.html +3 -2
- package/dist/video-preview.html +4 -3
- package/dist-ssg/client/.vite/ssr-manifest.json +8565 -1080
- package/dist-ssg/client/assets/CanvasRenderer-tPU4vV1i.js +1 -0
- package/dist-ssg/client/assets/WebGLRenderer-8XaEJZ8d.js +1 -0
- package/dist-ssg/client/assets/WebGPURenderer-D_U45dp8.js +1 -0
- package/dist-ssg/client/assets/browserAll-6a90eROj.js +1 -0
- package/dist-ssg/client/assets/{dist-BKTT7Vdm.js → dist-B6MkJ-H7.js} +1 -1
- package/dist-ssg/client/assets/{dist-upAmtw9_.js → dist-B9IiVt9G.js} +1 -1
- package/dist-ssg/client/assets/{dist-CX1-5rfl.js → dist-BCjKNKOg.js} +1 -1
- package/dist-ssg/client/assets/dist-Bqpf_8HF.js +1 -0
- package/dist-ssg/client/assets/{dist-DJkx9TIh.js → dist-CFjNhfqM.js} +1 -1
- package/dist-ssg/client/assets/{dist-BPUIHtZ8.js → dist-CIMwXheF.js} +1 -1
- package/dist-ssg/client/assets/{dist-CVizFqBj.js → dist-CNLvbQSx.js} +1 -1
- package/dist-ssg/client/assets/dist-CWcubuXa.js +1 -0
- package/dist-ssg/client/assets/{dist-Cm5Vx6W8.js → dist-Ch_E0jle.js} +1 -1
- package/dist-ssg/client/assets/{dist-CLrPzzut.js → dist-CjF4SWnb.js} +1 -1
- package/dist-ssg/client/assets/dist-D2pHEmiw.js +1 -0
- package/dist-ssg/client/assets/{dist-HHQTTSi-.js → dist-DgYslwM5.js} +1 -1
- package/dist-ssg/client/assets/{ghostty-web-BKQcHDq5.js → ghostty-web-BYk-wneR.js} +1 -1
- package/dist-ssg/client/assets/index-8OoZ339S.css +1 -0
- package/dist-ssg/client/assets/{index.ssg-DBq9_pDs.js → index.ssg-BWQbO3uy.js} +164 -149
- package/dist-ssg/client/assets/{init-brQ3KbKB.js → init-DnSi5N8V.js} +1 -1
- package/dist-ssg/client/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
- package/dist-ssg/client/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
- package/dist-ssg/client/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/dist-ssg/client/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/dist-ssg/client/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
- package/dist-ssg/client/assets/share-tech-mono-latin-400-normal-15MgdvEM.woff +0 -0
- package/dist-ssg/client/assets/share-tech-mono-latin-400-normal-CCqdbj5z.woff2 +0 -0
- package/dist-ssg/client/assets/trpc-BhXIjp-3.js +1 -0
- package/dist-ssg/client/assets/webworkerAll-Dp42RyhF.js +1 -0
- package/dist-ssg/client/index.ssg.html +2 -29
- package/dist-ssg/server/entry-server.js +734 -108
- package/package.json +6 -4
- package/dist/assets/CanvasRenderer-DGnQw8uB.js +0 -1
- package/dist/assets/WebGLRenderer-DHRbteVS.js +0 -1
- package/dist/assets/WebGPURenderer-BnFcGKnW.js +0 -1
- package/dist/assets/audio-preview-DF-g2nKV.js +0 -1
- package/dist/assets/browserAll-BB7WVzo0.js +0 -1
- package/dist/assets/common-DiWYGJu_.js +0 -22
- package/dist/assets/dist-B0Que_Lt.js +0 -1
- package/dist/assets/dist-B8m1wxBF.js +0 -1
- package/dist/assets/dist-DP_rT4tp.js +0 -1
- package/dist/assets/main-DThx1JaQ.js +0 -1654
- package/dist/assets/main-fCQ7khWW.css +0 -1
- package/dist/assets/trpc-Dko2Zn9y.js +0 -1
- package/dist/assets/video-preview-CChWJOsP.js +0 -1
- package/dist/assets/webworkerAll-Bfbn1LyG.js +0 -1
- package/dist-ssg/client/assets/CanvasRenderer-Dpr5EYjp.js +0 -1
- package/dist-ssg/client/assets/WebGLRenderer-DCzH263Z.js +0 -1
- package/dist-ssg/client/assets/WebGPURenderer-DgF_8B9g.js +0 -1
- package/dist-ssg/client/assets/browserAll-CPl4rDmN.js +0 -1
- package/dist-ssg/client/assets/dist-BuFVGK1x.js +0 -1
- package/dist-ssg/client/assets/dist-DlrmChto.js +0 -1
- package/dist-ssg/client/assets/dist-bnfyzoQu.js +0 -1
- package/dist-ssg/client/assets/index-BtGAsAtP.css +0 -1
- package/dist-ssg/client/assets/trpc-DGapI9Ny.js +0 -1
- package/dist-ssg/client/assets/webworkerAll-BKMUeO96.js +0 -1
|
@@ -28325,13 +28325,13 @@ function reduceKernel(state, event) {
|
|
|
28325
28325
|
persist: "none"
|
|
28326
28326
|
};
|
|
28327
28327
|
case "APPLY_LAYOUT": {
|
|
28328
|
-
|
|
28328
|
+
const merged = mergeLayout(event.layout);
|
|
28329
|
+
if (!(event.layout.updatedAt !== state.updatedAt || !areTabsEqual(state.mainTabs, merged.mainTabs) || !areTabsEqual(state.bottomTabs, merged.bottomTabs)) || !event.force && event.layout.updatedAt <= state.updatedAt) return {
|
|
28329
28330
|
nextState: state,
|
|
28330
28331
|
changed: false,
|
|
28331
28332
|
notify: [],
|
|
28332
28333
|
persist: "none"
|
|
28333
28334
|
};
|
|
28334
|
-
const merged = mergeLayout(event.layout);
|
|
28335
28335
|
return {
|
|
28336
28336
|
nextState: {
|
|
28337
28337
|
...state,
|
|
@@ -28688,14 +28688,11 @@ var NavController = class {
|
|
|
28688
28688
|
rebindProjectScopedLayout(storageKey) {
|
|
28689
28689
|
const scopedLocal = readLocalStorageByKey(storageKey);
|
|
28690
28690
|
if (scopedLocal) {
|
|
28691
|
-
|
|
28692
|
-
|
|
28693
|
-
|
|
28694
|
-
|
|
28695
|
-
bottomTabs: merged.bottomTabs,
|
|
28696
|
-
updatedAt: scopedLocal.updatedAt
|
|
28691
|
+
this.dispatch({
|
|
28692
|
+
type: "APPLY_LAYOUT",
|
|
28693
|
+
layout: scopedLocal,
|
|
28694
|
+
force: true
|
|
28697
28695
|
});
|
|
28698
|
-
this.normalizeUrl();
|
|
28699
28696
|
return;
|
|
28700
28697
|
}
|
|
28701
28698
|
this.state = normalizeState({
|
|
@@ -32292,6 +32289,120 @@ ZodOptional.create;
|
|
|
32292
32289
|
ZodNullable.create;
|
|
32293
32290
|
var preprocessType = ZodEffects.createWithPreprocess;
|
|
32294
32291
|
ZodPipeline.create;
|
|
32292
|
+
//#endregion
|
|
32293
|
+
//#region ../core/src/translation-task-control.ts
|
|
32294
|
+
var BATCH_TRANSLATION_ERROR_KINDS = [
|
|
32295
|
+
"timeout",
|
|
32296
|
+
"memory-limit",
|
|
32297
|
+
"runtime",
|
|
32298
|
+
"abort"
|
|
32299
|
+
];
|
|
32300
|
+
async function runControlledTranslationTask(task, options = {}) {
|
|
32301
|
+
const controller = new AbortController();
|
|
32302
|
+
const cleanupCallbacks = [];
|
|
32303
|
+
const parentSignal = options.signal;
|
|
32304
|
+
const timeoutMs = normalizeTimeoutMs(options.timeoutMs);
|
|
32305
|
+
if (parentSignal) if (parentSignal.aborted) controller.abort(parentSignal.reason);
|
|
32306
|
+
else {
|
|
32307
|
+
const onAbort = () => controller.abort(parentSignal.reason);
|
|
32308
|
+
parentSignal.addEventListener("abort", onAbort, { once: true });
|
|
32309
|
+
cleanupCallbacks.push(() => parentSignal.removeEventListener("abort", onAbort));
|
|
32310
|
+
}
|
|
32311
|
+
if (controller.signal.aborted) {
|
|
32312
|
+
cleanupCallbacks.forEach((callback) => callback());
|
|
32313
|
+
return {
|
|
32314
|
+
ok: false,
|
|
32315
|
+
error: normalizeBatchTranslationError(controller.signal.reason, parentSignal)
|
|
32316
|
+
};
|
|
32317
|
+
}
|
|
32318
|
+
let timer;
|
|
32319
|
+
let timeoutError;
|
|
32320
|
+
const taskPromise = Promise.resolve().then(() => task(controller.signal));
|
|
32321
|
+
taskPromise.catch(() => void 0);
|
|
32322
|
+
const races = [taskPromise];
|
|
32323
|
+
if (!controller.signal.aborted) races.push(new Promise((_, reject) => {
|
|
32324
|
+
const onAbort = () => reject(new DOMException("Translation cancelled.", "AbortError"));
|
|
32325
|
+
controller.signal.addEventListener("abort", onAbort, { once: true });
|
|
32326
|
+
cleanupCallbacks.push(() => controller.signal.removeEventListener("abort", onAbort));
|
|
32327
|
+
}));
|
|
32328
|
+
if (timeoutMs !== void 0) races.push(new Promise((_, reject) => {
|
|
32329
|
+
timer = setTimeout(() => {
|
|
32330
|
+
timeoutError = /* @__PURE__ */ new Error(`Translation task timed out after ${timeoutMs}ms.`);
|
|
32331
|
+
controller.abort(timeoutError);
|
|
32332
|
+
reject(timeoutError);
|
|
32333
|
+
}, timeoutMs);
|
|
32334
|
+
}));
|
|
32335
|
+
try {
|
|
32336
|
+
return {
|
|
32337
|
+
ok: true,
|
|
32338
|
+
value: await Promise.race(races)
|
|
32339
|
+
};
|
|
32340
|
+
} catch (error) {
|
|
32341
|
+
controller.abort(error);
|
|
32342
|
+
if (timeoutError && controller.signal.reason === timeoutError) return {
|
|
32343
|
+
ok: false,
|
|
32344
|
+
error: {
|
|
32345
|
+
kind: "timeout",
|
|
32346
|
+
message: timeoutError.message
|
|
32347
|
+
}
|
|
32348
|
+
};
|
|
32349
|
+
return {
|
|
32350
|
+
ok: false,
|
|
32351
|
+
error: normalizeBatchTranslationError(error, parentSignal)
|
|
32352
|
+
};
|
|
32353
|
+
} finally {
|
|
32354
|
+
if (timer) clearTimeout(timer);
|
|
32355
|
+
cleanupCallbacks.forEach((callback) => callback());
|
|
32356
|
+
}
|
|
32357
|
+
}
|
|
32358
|
+
function normalizeBatchTranslationError(error, parentSignal) {
|
|
32359
|
+
if (isBatchTranslationError(error)) return error;
|
|
32360
|
+
if (parentSignal?.aborted) return {
|
|
32361
|
+
kind: "abort",
|
|
32362
|
+
message: readAbortMessage(parentSignal.reason) ?? "Translation cancelled."
|
|
32363
|
+
};
|
|
32364
|
+
if (error instanceof DOMException && error.name === "AbortError") return {
|
|
32365
|
+
kind: "abort",
|
|
32366
|
+
message: readAbortMessage(error) ?? "Translation cancelled."
|
|
32367
|
+
};
|
|
32368
|
+
const message = getErrorMessage$2(error);
|
|
32369
|
+
if (isTimeoutMessage(message)) return {
|
|
32370
|
+
kind: "timeout",
|
|
32371
|
+
message
|
|
32372
|
+
};
|
|
32373
|
+
if (isMemoryLimitMessage(message)) return {
|
|
32374
|
+
kind: "memory-limit",
|
|
32375
|
+
message
|
|
32376
|
+
};
|
|
32377
|
+
return {
|
|
32378
|
+
kind: "runtime",
|
|
32379
|
+
message
|
|
32380
|
+
};
|
|
32381
|
+
}
|
|
32382
|
+
function normalizeTimeoutMs(timeoutMs) {
|
|
32383
|
+
return typeof timeoutMs === "number" && Number.isFinite(timeoutMs) && timeoutMs > 0 ? Math.floor(timeoutMs) : void 0;
|
|
32384
|
+
}
|
|
32385
|
+
function getErrorMessage$2(error) {
|
|
32386
|
+
if (error instanceof Error && error.message.trim().length > 0) return error.message;
|
|
32387
|
+
if (typeof error === "string" && error.trim().length > 0) return error;
|
|
32388
|
+
return "Translation failed.";
|
|
32389
|
+
}
|
|
32390
|
+
function readAbortMessage(reason) {
|
|
32391
|
+
if (reason instanceof Error && reason.message.trim().length > 0) return reason.message;
|
|
32392
|
+
if (typeof reason === "string" && reason.trim().length > 0) return reason;
|
|
32393
|
+
}
|
|
32394
|
+
function isTimeoutMessage(message) {
|
|
32395
|
+
return /\btime(?:d)?\s*out\b/i.test(message);
|
|
32396
|
+
}
|
|
32397
|
+
function isMemoryLimitMessage(message) {
|
|
32398
|
+
return /out of memory/i.test(message) || /memory limit/i.test(message) || /insufficient memory/i.test(message) || /ERR_WORKER_OUT_OF_MEMORY/i.test(message);
|
|
32399
|
+
}
|
|
32400
|
+
function isBatchTranslationError(value) {
|
|
32401
|
+
if (typeof value !== "object" || value === null) return false;
|
|
32402
|
+
const kind = Reflect.get(value, "kind");
|
|
32403
|
+
const message = Reflect.get(value, "message");
|
|
32404
|
+
return typeof kind === "string" && BATCH_TRANSLATION_ERROR_KINDS.includes(kind) && typeof message === "string" && message.length > 0;
|
|
32405
|
+
}
|
|
32295
32406
|
var TranslationEngineIdSchema = enumType([
|
|
32296
32407
|
"browser",
|
|
32297
32408
|
"local",
|
|
@@ -32312,6 +32423,7 @@ enumType([
|
|
|
32312
32423
|
"local-llama",
|
|
32313
32424
|
"openai"
|
|
32314
32425
|
]);
|
|
32426
|
+
var DEFAULT_BATCH_TRANSLATION_TIMEOUT_MS = 15e3;
|
|
32315
32427
|
var LocalModelDownloadStatusSchema = enumType([
|
|
32316
32428
|
"not-downloaded",
|
|
32317
32429
|
"queued",
|
|
@@ -32556,19 +32668,23 @@ var TranslationOpenAISettingsSchema = objectType({
|
|
|
32556
32668
|
var TranslationLocalSettingsSchema = objectType({
|
|
32557
32669
|
model: stringType().default("Xenova/nllb-200-distilled-600M"),
|
|
32558
32670
|
selectedGroupId: stringType().optional(),
|
|
32559
|
-
hfEndpoint: stringType().default("")
|
|
32671
|
+
hfEndpoint: stringType().default(""),
|
|
32672
|
+
memoryBudgetPercent: numberType().min(0).max(100).default(25)
|
|
32560
32673
|
});
|
|
32561
32674
|
var TranslationLocalCt2SettingsSchema = objectType({
|
|
32562
32675
|
model: stringType().default("ooeoeo/opus-mt-en-zh-ct2-float16"),
|
|
32563
32676
|
selectedGroupId: stringType().optional(),
|
|
32564
|
-
hfEndpoint: stringType().default("")
|
|
32677
|
+
hfEndpoint: stringType().default(""),
|
|
32678
|
+
memoryBudgetPercent: numberType().min(0).max(100).default(25)
|
|
32565
32679
|
});
|
|
32566
32680
|
var TranslationLocalLlamaSettingsSchema = objectType({
|
|
32567
32681
|
model: stringType().default("bartowski/Qwen2.5-0.5B-Instruct-GGUF"),
|
|
32568
32682
|
selectedGroupId: stringType().optional(),
|
|
32569
|
-
hfEndpoint: stringType().default("")
|
|
32683
|
+
hfEndpoint: stringType().default(""),
|
|
32684
|
+
memoryBudgetPercent: numberType().min(0).max(100).default(25)
|
|
32570
32685
|
});
|
|
32571
32686
|
objectType({
|
|
32687
|
+
engineId: TranslationEngineIdSchema.default(DEFAULT_TRANSLATION_ENGINE_ID),
|
|
32572
32688
|
openai: TranslationOpenAISettingsSchema.default(TranslationOpenAISettingsSchema.parse({})),
|
|
32573
32689
|
local: TranslationLocalSettingsSchema.default(TranslationLocalSettingsSchema.parse({})),
|
|
32574
32690
|
localCt2: TranslationLocalCt2SettingsSchema.default(TranslationLocalCt2SettingsSchema.parse({})),
|
|
@@ -32582,11 +32698,16 @@ objectType({
|
|
|
32582
32698
|
selectedGroupId: stringType().min(1).optional(),
|
|
32583
32699
|
inputs: arrayType(stringType()).min(1),
|
|
32584
32700
|
instructions: stringType().optional(),
|
|
32585
|
-
context: stringType().optional()
|
|
32701
|
+
context: stringType().optional(),
|
|
32702
|
+
timeoutMs: numberType().int().positive().default(DEFAULT_BATCH_TRANSLATION_TIMEOUT_MS)
|
|
32586
32703
|
});
|
|
32587
32704
|
objectType({
|
|
32588
32705
|
index: numberType().int().nonnegative(),
|
|
32589
|
-
output: stringType()
|
|
32706
|
+
output: stringType().optional(),
|
|
32707
|
+
error: objectType({
|
|
32708
|
+
kind: enumType(BATCH_TRANSLATION_ERROR_KINDS),
|
|
32709
|
+
message: stringType().min(1)
|
|
32710
|
+
}).optional()
|
|
32590
32711
|
});
|
|
32591
32712
|
var DocumentTranslationDisplayModeSchema = enumType(["direct", "bilingual"]);
|
|
32592
32713
|
var TranslationEngineProjectSettingsSchema = objectType({
|
|
@@ -68061,6 +68182,25 @@ var InputPanel = class extends i {
|
|
|
68061
68182
|
}));
|
|
68062
68183
|
this.requestUpdate();
|
|
68063
68184
|
}
|
|
68185
|
+
_stopToolbarControlPointer(e) {
|
|
68186
|
+
e.stopPropagation();
|
|
68187
|
+
e.preventDefault();
|
|
68188
|
+
}
|
|
68189
|
+
_stopToolbarControlEvent(e) {
|
|
68190
|
+
e.stopPropagation();
|
|
68191
|
+
}
|
|
68192
|
+
_switchTabFromToolbar(e, tab) {
|
|
68193
|
+
this._stopToolbarControlEvent(e);
|
|
68194
|
+
this._switchTab(tab);
|
|
68195
|
+
}
|
|
68196
|
+
_toggleLayoutFromToolbar(e) {
|
|
68197
|
+
this._stopToolbarControlEvent(e);
|
|
68198
|
+
this._toggleLayout();
|
|
68199
|
+
}
|
|
68200
|
+
_closeFromToolbar(e) {
|
|
68201
|
+
this._stopToolbarControlEvent(e);
|
|
68202
|
+
this._close();
|
|
68203
|
+
}
|
|
68064
68204
|
_toggleLayout() {
|
|
68065
68205
|
this.layout = this.layout === "fixed" ? "floating" : "fixed";
|
|
68066
68206
|
if (this.layout === "fixed") this._closeFloatingDialog();
|
|
@@ -68297,17 +68437,32 @@ var InputPanel = class extends i {
|
|
|
68297
68437
|
class="tab-btn"
|
|
68298
68438
|
part="tab-btn"
|
|
68299
68439
|
?data-active=${this.activeTab === t.id}
|
|
68300
|
-
@
|
|
68440
|
+
@pointerdown=${(e) => this._stopToolbarControlPointer(e)}
|
|
68441
|
+
@mousedown=${(e) => this._stopToolbarControlPointer(e)}
|
|
68442
|
+
@click=${(e) => this._switchTabFromToolbar(e, t.id)}
|
|
68301
68443
|
>
|
|
68302
68444
|
${t.icon} ${this.activeTab === t.id ? t.label : ""}
|
|
68303
68445
|
</button>
|
|
68304
68446
|
`)}
|
|
68305
68447
|
</div>
|
|
68306
68448
|
<div class="action-group">
|
|
68307
|
-
<button
|
|
68449
|
+
<button
|
|
68450
|
+
class="icon-btn"
|
|
68451
|
+
@pointerdown=${(e) => this._stopToolbarControlPointer(e)}
|
|
68452
|
+
@mousedown=${(e) => this._stopToolbarControlPointer(e)}
|
|
68453
|
+
@click=${(e) => this._toggleLayoutFromToolbar(e)}
|
|
68454
|
+
title="Toggle layout mode"
|
|
68455
|
+
>
|
|
68308
68456
|
${this.layout === "fixed" ? iconPin(14) : iconPinOff(14)}
|
|
68309
68457
|
</button>
|
|
68310
|
-
<button
|
|
68458
|
+
<button
|
|
68459
|
+
class="icon-btn"
|
|
68460
|
+
part="close-btn"
|
|
68461
|
+
@pointerdown=${(e) => this._stopToolbarControlPointer(e)}
|
|
68462
|
+
@mousedown=${(e) => this._stopToolbarControlPointer(e)}
|
|
68463
|
+
@click=${(e) => this._closeFromToolbar(e)}
|
|
68464
|
+
title="Close panel"
|
|
68465
|
+
>
|
|
68311
68466
|
${iconX(14)}
|
|
68312
68467
|
</button>
|
|
68313
68468
|
</div>
|
|
@@ -90847,30 +91002,12 @@ var ShortcutTab = class extends i {
|
|
|
90847
91002
|
composed: true
|
|
90848
91003
|
}));
|
|
90849
91004
|
}
|
|
90850
|
-
|
|
90851
|
-
|
|
90852
|
-
|
|
90853
|
-
|
|
90854
|
-
|
|
90855
|
-
|
|
90856
|
-
} catch {
|
|
90857
|
-
document.execCommand("copy");
|
|
90858
|
-
}
|
|
90859
|
-
return;
|
|
90860
|
-
}
|
|
90861
|
-
if (command === "paste") {
|
|
90862
|
-
try {
|
|
90863
|
-
const text = await navigator.clipboard.readText();
|
|
90864
|
-
if (text) this._send(text);
|
|
90865
|
-
} catch {}
|
|
90866
|
-
return;
|
|
90867
|
-
}
|
|
90868
|
-
const active = document.activeElement;
|
|
90869
|
-
if (active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement) {
|
|
90870
|
-
active.select();
|
|
90871
|
-
return;
|
|
90872
|
-
}
|
|
90873
|
-
document.execCommand("selectAll");
|
|
91005
|
+
_handleCommand(command) {
|
|
91006
|
+
this.dispatchEvent(new CustomEvent("input-panel:command", {
|
|
91007
|
+
detail: { command },
|
|
91008
|
+
bubbles: true,
|
|
91009
|
+
composed: true
|
|
91010
|
+
}));
|
|
90874
91011
|
}
|
|
90875
91012
|
_dpadData(event, width, height, container) {
|
|
90876
91013
|
const local = container.toLocal(event.global);
|
|
@@ -90880,7 +91017,7 @@ var ShortcutTab = class extends i {
|
|
|
90880
91017
|
if (Math.abs(dx) > Math.abs(dy)) return dx < 0 ? "\x1B[D" : "\x1B[C";
|
|
90881
91018
|
return dy < 0 ? "\x1B[A" : "\x1B[B";
|
|
90882
91019
|
}
|
|
90883
|
-
|
|
91020
|
+
_activateShortcut(item, event, width, height, container) {
|
|
90884
91021
|
if (item.kind === "dpad") {
|
|
90885
91022
|
this._send(this._dpadData(event, width, height, container));
|
|
90886
91023
|
return;
|
|
@@ -90895,7 +91032,7 @@ var ShortcutTab = class extends i {
|
|
|
90895
91032
|
this._send(action.text);
|
|
90896
91033
|
return;
|
|
90897
91034
|
}
|
|
90898
|
-
|
|
91035
|
+
this._handleCommand(action.command);
|
|
90899
91036
|
}
|
|
90900
91037
|
_setActivePage(pageId) {
|
|
90901
91038
|
if (this.activePageId === pageId) return;
|
|
@@ -91444,8 +91581,11 @@ var VirtualKeyboardTab = class extends i {
|
|
|
91444
91581
|
this._activeKey = null;
|
|
91445
91582
|
this._activePointerId = null;
|
|
91446
91583
|
}
|
|
91584
|
+
_hostPlatform() {
|
|
91585
|
+
return this.platform === "windows" || this.platform === "macos" || this.platform === "common" ? this.platform : detectHostPlatform();
|
|
91586
|
+
}
|
|
91447
91587
|
getRows() {
|
|
91448
|
-
return LAYOUTS[this.
|
|
91588
|
+
return LAYOUTS[this._hostPlatform()];
|
|
91449
91589
|
}
|
|
91450
91590
|
async _initPixi() {
|
|
91451
91591
|
const host = this.shadowRoot?.querySelector(".pixi-host");
|
|
@@ -91791,14 +91931,44 @@ var VirtualKeyboardTab = class extends i {
|
|
|
91791
91931
|
if (this._isShifted(def, forceShift) && def.shift) return def.shift.data;
|
|
91792
91932
|
return def.data;
|
|
91793
91933
|
}
|
|
91794
|
-
|
|
91934
|
+
_resolveTerminalData(def, forceShift) {
|
|
91795
91935
|
let data = this._resolveOutputData(def, forceShift);
|
|
91796
|
-
if (!data) return;
|
|
91936
|
+
if (!data) return "";
|
|
91797
91937
|
if (this._modifiers.ctrl && data.length === 1) {
|
|
91798
91938
|
const code = data.toUpperCase().charCodeAt(0) - 64;
|
|
91799
91939
|
if (code > 0 && code < 32) data = String.fromCharCode(code);
|
|
91800
91940
|
}
|
|
91801
91941
|
if (this._modifiers.alt || this._modifiers.meta) data = `\x1b${data}`;
|
|
91942
|
+
return data;
|
|
91943
|
+
}
|
|
91944
|
+
_resolvePrimaryCommand(def) {
|
|
91945
|
+
if (this._modifiers.alt || this._modifiers.shift) return null;
|
|
91946
|
+
if (!(this._hostPlatform() === "macos" ? this._modifiers.meta && !this._modifiers.ctrl : this._modifiers.ctrl && !this._modifiers.meta)) return null;
|
|
91947
|
+
const key = def.data.toLowerCase();
|
|
91948
|
+
if (key === "c") return "copy";
|
|
91949
|
+
if (key === "v") return "paste";
|
|
91950
|
+
if (key === "a") return "select-all";
|
|
91951
|
+
return null;
|
|
91952
|
+
}
|
|
91953
|
+
_sendCommand(command, fallbackData) {
|
|
91954
|
+
this.dispatchEvent(new CustomEvent("input-panel:command", {
|
|
91955
|
+
detail: {
|
|
91956
|
+
command,
|
|
91957
|
+
fallbackData
|
|
91958
|
+
},
|
|
91959
|
+
bubbles: true,
|
|
91960
|
+
composed: true
|
|
91961
|
+
}));
|
|
91962
|
+
}
|
|
91963
|
+
_sendKey(def, forceShift) {
|
|
91964
|
+
const data = this._resolveTerminalData(def, forceShift);
|
|
91965
|
+
if (!data) return;
|
|
91966
|
+
const command = this._resolvePrimaryCommand(def);
|
|
91967
|
+
if (command) {
|
|
91968
|
+
const fallbackData = this._hostPlatform() === "macos" ? void 0 : data;
|
|
91969
|
+
this._sendCommand(command, fallbackData);
|
|
91970
|
+
return;
|
|
91971
|
+
}
|
|
91802
91972
|
this.dispatchEvent(new CustomEvent("input-panel:send", {
|
|
91803
91973
|
detail: { data },
|
|
91804
91974
|
bubbles: true,
|
|
@@ -92326,9 +92496,27 @@ var EDGE_SCROLL_OVERSHOOT = 15;
|
|
|
92326
92496
|
function isTouchDevice() {
|
|
92327
92497
|
return "ontouchstart" in window || navigator.maxTouchPoints > 0;
|
|
92328
92498
|
}
|
|
92499
|
+
function isTerminalTouchMouseOverlay(element) {
|
|
92500
|
+
return element instanceof HTMLElement && element.classList.contains("terminal-touch-mouse-overlay");
|
|
92501
|
+
}
|
|
92502
|
+
function resolveTerminalPointerTarget(container, clientX, clientY) {
|
|
92503
|
+
let element = document.elementFromPoint(clientX, clientY);
|
|
92504
|
+
if (element && isTerminalTouchMouseOverlay(element)) {
|
|
92505
|
+
const overlayElement = element;
|
|
92506
|
+
const previousPointerEvents = overlayElement.style.pointerEvents;
|
|
92507
|
+
overlayElement.style.pointerEvents = "none";
|
|
92508
|
+
element = document.elementFromPoint(clientX, clientY);
|
|
92509
|
+
overlayElement.style.pointerEvents = previousPointerEvents;
|
|
92510
|
+
}
|
|
92511
|
+
if (element && container.contains(element) && !isTerminalTouchMouseOverlay(element)) return element;
|
|
92512
|
+
return container.querySelector(".xterm-screen") ?? container;
|
|
92513
|
+
}
|
|
92329
92514
|
function isInputPanelTab(value) {
|
|
92330
92515
|
return value === "input" || value === "keys" || value === "shortcuts" || value === "trackpad" || value === "settings";
|
|
92331
92516
|
}
|
|
92517
|
+
function isInputPanelCommand(value) {
|
|
92518
|
+
return value === "copy" || value === "paste" || value === "select-all";
|
|
92519
|
+
}
|
|
92332
92520
|
function isRecord$1(value) {
|
|
92333
92521
|
return typeof value === "object" && value !== null;
|
|
92334
92522
|
}
|
|
@@ -92575,6 +92763,7 @@ var InputPanelAddon = class InputPanelAddon {
|
|
|
92575
92763
|
_persistentCleanups = [];
|
|
92576
92764
|
_listenersAttached = false;
|
|
92577
92765
|
_onInput;
|
|
92766
|
+
_onCommand;
|
|
92578
92767
|
_onOpenCb;
|
|
92579
92768
|
_onCloseCb;
|
|
92580
92769
|
_getHistory;
|
|
@@ -92590,6 +92779,7 @@ var InputPanelAddon = class InputPanelAddon {
|
|
|
92590
92779
|
_hasOwnPersistedState;
|
|
92591
92780
|
constructor(opts) {
|
|
92592
92781
|
this._onInput = opts?.onInput ?? (() => {});
|
|
92782
|
+
this._onCommand = opts?.onCommand ?? null;
|
|
92593
92783
|
this._onOpenCb = opts?.onOpen ?? null;
|
|
92594
92784
|
this._onCloseCb = opts?.onClose ?? null;
|
|
92595
92785
|
this._getHistory = opts?.getHistory ?? null;
|
|
@@ -92625,6 +92815,9 @@ var InputPanelAddon = class InputPanelAddon {
|
|
|
92625
92815
|
set onInput(fn) {
|
|
92626
92816
|
this._onInput = fn;
|
|
92627
92817
|
}
|
|
92818
|
+
set onCommand(fn) {
|
|
92819
|
+
this._onCommand = fn;
|
|
92820
|
+
}
|
|
92628
92821
|
setPlatform(platform) {
|
|
92629
92822
|
this._platform = platform;
|
|
92630
92823
|
this._applyPlatformToPanel();
|
|
@@ -92781,6 +92974,18 @@ var InputPanelAddon = class InputPanelAddon {
|
|
|
92781
92974
|
}).catch(() => {});
|
|
92782
92975
|
}
|
|
92783
92976
|
});
|
|
92977
|
+
this._on(panel, "input-panel:command", (e) => {
|
|
92978
|
+
const detail = e.detail;
|
|
92979
|
+
if (!isRecord$1(detail)) return;
|
|
92980
|
+
const command = detail.command;
|
|
92981
|
+
if (!isInputPanelCommand(command)) return;
|
|
92982
|
+
const fallbackData = typeof detail.fallbackData === "string" ? detail.fallbackData : void 0;
|
|
92983
|
+
Promise.resolve(this._onCommand?.(command, { fallbackData }) ?? false).then((handled) => {
|
|
92984
|
+
if (!handled && fallbackData) this._onInput(fallbackData);
|
|
92985
|
+
}).catch(() => {
|
|
92986
|
+
if (fallbackData) this._onInput(fallbackData);
|
|
92987
|
+
});
|
|
92988
|
+
});
|
|
92784
92989
|
this._on(inputTab, "input-panel:input-change", (e) => {
|
|
92785
92990
|
const value = e.detail?.value;
|
|
92786
92991
|
if (typeof value === "string") {
|
|
@@ -92998,9 +93203,7 @@ var InputPanelAddon = class InputPanelAddon {
|
|
|
92998
93203
|
_resolveTarget(clientX, clientY) {
|
|
92999
93204
|
const container = this._getTerminalHostElement();
|
|
93000
93205
|
if (!container) return document.body;
|
|
93001
|
-
|
|
93002
|
-
if (el && container.contains(el)) return el;
|
|
93003
|
-
return container.querySelector(".xterm-screen") ?? container;
|
|
93206
|
+
return resolveTerminalPointerTarget(container, clientX, clientY);
|
|
93004
93207
|
}
|
|
93005
93208
|
_dispatchMouse(type, opts = {}) {
|
|
93006
93209
|
const coords = this._getClientCoords();
|
|
@@ -93155,6 +93358,55 @@ var InputPanelAddon = class InputPanelAddon {
|
|
|
93155
93358
|
}
|
|
93156
93359
|
};
|
|
93157
93360
|
//#endregion
|
|
93361
|
+
//#region src/lib/google-font-loader.ts
|
|
93362
|
+
function getPreferredGoogleFontsHosts(lang) {
|
|
93363
|
+
const useCnCdn = /^zh\b/i.test(lang);
|
|
93364
|
+
return {
|
|
93365
|
+
apiHost: useCnCdn ? "https://fonts.googleapis.cn" : "https://fonts.googleapis.com",
|
|
93366
|
+
staticHost: useCnCdn ? "https://fonts.gstatic.cn" : "https://fonts.gstatic.com"
|
|
93367
|
+
};
|
|
93368
|
+
}
|
|
93369
|
+
function encodeGoogleFontFamily(family) {
|
|
93370
|
+
return family.trim().replace(/ /g, "+");
|
|
93371
|
+
}
|
|
93372
|
+
function buildGoogleFontsStylesheetHref(options) {
|
|
93373
|
+
const families = options.families.map(encodeGoogleFontFamily).filter(Boolean);
|
|
93374
|
+
const { apiHost } = getPreferredGoogleFontsHosts(options.lang ?? "");
|
|
93375
|
+
const familyParams = families.map((family) => `family=${family}`);
|
|
93376
|
+
const displayParam = `display=${options.display ?? "swap"}`;
|
|
93377
|
+
return `${apiHost}/css2?${[...familyParams, displayParam].join("&")}`;
|
|
93378
|
+
}
|
|
93379
|
+
/**
|
|
93380
|
+
* Legacy Google Fonts loader retained for optional large CJK/JCK font families.
|
|
93381
|
+
* The app shell uses local @fontsource assets by default.
|
|
93382
|
+
*/
|
|
93383
|
+
function loadGoogleFontsStylesheet(options) {
|
|
93384
|
+
const documentRef = options.documentRef ?? (typeof document === "undefined" ? null : document);
|
|
93385
|
+
if (!documentRef || options.families.length === 0) return null;
|
|
93386
|
+
const lang = options.lang ?? (typeof navigator === "undefined" ? "" : navigator.languages && navigator.languages[0] || navigator.language || navigator.userLanguage || "");
|
|
93387
|
+
const hosts = getPreferredGoogleFontsHosts(lang);
|
|
93388
|
+
const href = buildGoogleFontsStylesheetHref({
|
|
93389
|
+
...options,
|
|
93390
|
+
lang
|
|
93391
|
+
});
|
|
93392
|
+
if (documentRef.head.querySelector(`link[href="${href}"]`)) return null;
|
|
93393
|
+
const preconnectApi = documentRef.createElement("link");
|
|
93394
|
+
preconnectApi.rel = "preconnect";
|
|
93395
|
+
preconnectApi.href = hosts.apiHost;
|
|
93396
|
+
preconnectApi.dataset.openspecGoogleFonts = "preconnect-api";
|
|
93397
|
+
const preconnectStatic = documentRef.createElement("link");
|
|
93398
|
+
preconnectStatic.rel = "preconnect";
|
|
93399
|
+
preconnectStatic.href = hosts.staticHost;
|
|
93400
|
+
preconnectStatic.crossOrigin = "anonymous";
|
|
93401
|
+
preconnectStatic.dataset.openspecGoogleFonts = "preconnect-static";
|
|
93402
|
+
const stylesheet = documentRef.createElement("link");
|
|
93403
|
+
stylesheet.rel = "stylesheet";
|
|
93404
|
+
stylesheet.href = href;
|
|
93405
|
+
stylesheet.dataset.openspecGoogleFonts = "stylesheet";
|
|
93406
|
+
documentRef.head.append(preconnectApi, preconnectStatic, stylesheet);
|
|
93407
|
+
return stylesheet;
|
|
93408
|
+
}
|
|
93409
|
+
//#endregion
|
|
93158
93410
|
//#region src/lib/user-gesture-audio-context.ts
|
|
93159
93411
|
var audioContext = null;
|
|
93160
93412
|
var audioContextPromise = null;
|
|
@@ -93558,6 +93810,146 @@ var TerminalInputHistoryStore = class {
|
|
|
93558
93810
|
}
|
|
93559
93811
|
};
|
|
93560
93812
|
//#endregion
|
|
93813
|
+
//#region src/lib/terminal-keybindings.ts
|
|
93814
|
+
function isKeydown(event) {
|
|
93815
|
+
return event.type === "keydown";
|
|
93816
|
+
}
|
|
93817
|
+
function keyEquals(event, key) {
|
|
93818
|
+
return event.key.toLowerCase() === key;
|
|
93819
|
+
}
|
|
93820
|
+
function hasPrimaryModifier(event) {
|
|
93821
|
+
return event.metaKey || event.ctrlKey;
|
|
93822
|
+
}
|
|
93823
|
+
function hasPlainPrimaryModifier(event) {
|
|
93824
|
+
return hasPrimaryModifier(event) && !event.altKey;
|
|
93825
|
+
}
|
|
93826
|
+
function resolveClipboard(context) {
|
|
93827
|
+
if (context.clipboard) return context.clipboard;
|
|
93828
|
+
if (typeof navigator === "undefined") return null;
|
|
93829
|
+
return navigator.clipboard ?? null;
|
|
93830
|
+
}
|
|
93831
|
+
function runAsync(task, context) {
|
|
93832
|
+
task.catch((error) => {
|
|
93833
|
+
context.onAsyncError?.(error);
|
|
93834
|
+
});
|
|
93835
|
+
}
|
|
93836
|
+
async function copySelection(context, selection) {
|
|
93837
|
+
const clipboard = resolveClipboard(context);
|
|
93838
|
+
if (!clipboard?.writeText) return;
|
|
93839
|
+
await clipboard.writeText(selection);
|
|
93840
|
+
}
|
|
93841
|
+
async function pasteClipboard(context) {
|
|
93842
|
+
const clipboard = resolveClipboard(context);
|
|
93843
|
+
if (!clipboard?.readText) return;
|
|
93844
|
+
const text = await clipboard.readText();
|
|
93845
|
+
if (!text) return;
|
|
93846
|
+
try {
|
|
93847
|
+
context.terminal.paste?.(text);
|
|
93848
|
+
if (context.terminal.paste) return;
|
|
93849
|
+
} catch {}
|
|
93850
|
+
context.writeInput(text);
|
|
93851
|
+
}
|
|
93852
|
+
var defaultTerminalKeybindings = [
|
|
93853
|
+
{
|
|
93854
|
+
id: "terminal.copy-selection",
|
|
93855
|
+
handle: (event, context) => {
|
|
93856
|
+
if (!isKeydown(event) || !hasPlainPrimaryModifier(event) || !keyEquals(event, "c")) return null;
|
|
93857
|
+
if (!context.terminal.hasSelection?.()) return "allow";
|
|
93858
|
+
return copySelectionCommand(context);
|
|
93859
|
+
}
|
|
93860
|
+
},
|
|
93861
|
+
{
|
|
93862
|
+
id: "terminal.paste-clipboard",
|
|
93863
|
+
handle: (event, context) => {
|
|
93864
|
+
if (!isKeydown(event) || !hasPlainPrimaryModifier(event) || !keyEquals(event, "v")) return null;
|
|
93865
|
+
return pasteClipboardCommand(context);
|
|
93866
|
+
}
|
|
93867
|
+
},
|
|
93868
|
+
{
|
|
93869
|
+
id: "terminal.select-all",
|
|
93870
|
+
handle: (event, context) => {
|
|
93871
|
+
if (!isKeydown(event) || !event.metaKey || event.ctrlKey || event.altKey) return null;
|
|
93872
|
+
if (!keyEquals(event, "a")) return null;
|
|
93873
|
+
return selectAllCommand(context);
|
|
93874
|
+
}
|
|
93875
|
+
},
|
|
93876
|
+
{
|
|
93877
|
+
id: "terminal.zoom-in",
|
|
93878
|
+
handle: (event, context) => {
|
|
93879
|
+
if (!isKeydown(event) || !hasPrimaryModifier(event)) return null;
|
|
93880
|
+
if (event.key !== "=" && event.key !== "+") return null;
|
|
93881
|
+
context.zoomFont(1);
|
|
93882
|
+
return "block";
|
|
93883
|
+
}
|
|
93884
|
+
},
|
|
93885
|
+
{
|
|
93886
|
+
id: "terminal.zoom-out",
|
|
93887
|
+
handle: (event, context) => {
|
|
93888
|
+
if (!isKeydown(event) || !hasPrimaryModifier(event) || event.key !== "-") return null;
|
|
93889
|
+
context.zoomFont(-1);
|
|
93890
|
+
return "block";
|
|
93891
|
+
}
|
|
93892
|
+
},
|
|
93893
|
+
{
|
|
93894
|
+
id: "terminal.zoom-reset",
|
|
93895
|
+
handle: (event, context) => {
|
|
93896
|
+
if (!isKeydown(event) || !hasPrimaryModifier(event) || event.key !== "0") return null;
|
|
93897
|
+
context.resetFontSize();
|
|
93898
|
+
return "block";
|
|
93899
|
+
}
|
|
93900
|
+
}
|
|
93901
|
+
];
|
|
93902
|
+
function copySelectionCommand(context) {
|
|
93903
|
+
if (!context.terminal.hasSelection?.()) return "allow";
|
|
93904
|
+
const selection = context.terminal.getSelection?.() ?? "";
|
|
93905
|
+
if (!selection) return "allow";
|
|
93906
|
+
runAsync(copySelection(context, selection), context);
|
|
93907
|
+
return "block";
|
|
93908
|
+
}
|
|
93909
|
+
function pasteClipboardCommand(context) {
|
|
93910
|
+
if (!resolveClipboard(context)?.readText) return "allow";
|
|
93911
|
+
runAsync(pasteClipboard(context), context);
|
|
93912
|
+
return "block";
|
|
93913
|
+
}
|
|
93914
|
+
function selectAllCommand(context) {
|
|
93915
|
+
if (!context.terminal.selectAll) return "allow";
|
|
93916
|
+
context.terminal.selectAll();
|
|
93917
|
+
return "block";
|
|
93918
|
+
}
|
|
93919
|
+
var defaultTerminalCommandBindings = [
|
|
93920
|
+
{
|
|
93921
|
+
id: "terminal.command.copy-selection",
|
|
93922
|
+
command: "copy",
|
|
93923
|
+
run: copySelectionCommand
|
|
93924
|
+
},
|
|
93925
|
+
{
|
|
93926
|
+
id: "terminal.command.paste-clipboard",
|
|
93927
|
+
command: "paste",
|
|
93928
|
+
run: pasteClipboardCommand
|
|
93929
|
+
},
|
|
93930
|
+
{
|
|
93931
|
+
id: "terminal.command.select-all",
|
|
93932
|
+
command: "select-all",
|
|
93933
|
+
run: selectAllCommand
|
|
93934
|
+
}
|
|
93935
|
+
];
|
|
93936
|
+
var TerminalKeybindingRegistry = class {
|
|
93937
|
+
constructor(bindings = defaultTerminalKeybindings, commandBindings = defaultTerminalCommandBindings) {
|
|
93938
|
+
this.bindings = bindings;
|
|
93939
|
+
this.commandBindings = commandBindings;
|
|
93940
|
+
}
|
|
93941
|
+
handleKeyEvent(event, context) {
|
|
93942
|
+
for (const binding of this.bindings) {
|
|
93943
|
+
const result = binding.handle(event, context);
|
|
93944
|
+
if (result) return result;
|
|
93945
|
+
}
|
|
93946
|
+
return "allow";
|
|
93947
|
+
}
|
|
93948
|
+
runCommand(command, context) {
|
|
93949
|
+
return this.commandBindings.find((item) => item.command === command)?.run(context) ?? "allow";
|
|
93950
|
+
}
|
|
93951
|
+
};
|
|
93952
|
+
//#endregion
|
|
93561
93953
|
//#region src/lib/terminal-theme.ts
|
|
93562
93954
|
var TERMINAL_THEME_REGISTRY = {
|
|
93563
93955
|
"default-light": {
|
|
@@ -93747,7 +94139,7 @@ function resolveTerminalTheme(input) {
|
|
|
93747
94139
|
}
|
|
93748
94140
|
//#endregion
|
|
93749
94141
|
//#region src/lib/terminal-controller.ts
|
|
93750
|
-
var DEFAULT_FONT_FAMILY = "ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, monospace";
|
|
94142
|
+
var DEFAULT_FONT_FAMILY = "\"JetBrains Mono Variable\", \"JetBrains Mono\", ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, monospace";
|
|
93751
94143
|
var DEFAULT_TERMINAL_CONFIG = {
|
|
93752
94144
|
fontSize: 13,
|
|
93753
94145
|
fontFamily: "",
|
|
@@ -93796,6 +94188,10 @@ var GOOGLE_FONT_PRESETS = [
|
|
|
93796
94188
|
"Ubuntu Mono",
|
|
93797
94189
|
"Space Mono"
|
|
93798
94190
|
];
|
|
94191
|
+
var LOCAL_FONT_FAMILY_ALIASES = {
|
|
94192
|
+
"JetBrains Mono": "\"JetBrains Mono Variable\"",
|
|
94193
|
+
"Share Tech Mono": "\"Share Tech Mono\""
|
|
94194
|
+
};
|
|
93799
94195
|
/** Already-injected font sources, used for deduplication */
|
|
93800
94196
|
var loadedFontSources = /* @__PURE__ */ new Set();
|
|
93801
94197
|
/** Extract a font name from a URL pathname (strip extension, replace dashes with spaces) */
|
|
@@ -93844,13 +94240,8 @@ async function loadFontSource(source) {
|
|
|
93844
94240
|
function loadGoogleFont(fontName) {
|
|
93845
94241
|
const key = `google:${fontName}`;
|
|
93846
94242
|
if (loadedFontSources.has(key)) return;
|
|
93847
|
-
const
|
|
93848
|
-
|
|
93849
|
-
const link = document.createElement("link");
|
|
93850
|
-
link.rel = "stylesheet";
|
|
93851
|
-
link.href = `${apiHost}/css2?family=${fontName.replace(/ /g, "+")}&display=swap`;
|
|
93852
|
-
link.dataset.fontSrc = key;
|
|
93853
|
-
document.head.appendChild(link);
|
|
94243
|
+
const link = loadGoogleFontsStylesheet({ families: [fontName] });
|
|
94244
|
+
if (link) link.dataset.fontSrc = key;
|
|
93854
94245
|
loadedFontSources.add(key);
|
|
93855
94246
|
}
|
|
93856
94247
|
var TerminalController = class {
|
|
@@ -93862,6 +94253,7 @@ var TerminalController = class {
|
|
|
93862
94253
|
snapshotCache = null;
|
|
93863
94254
|
inputHistoryStore = new TerminalInputHistoryStore();
|
|
93864
94255
|
bellSoundEngine = new TerminalBellSoundEngine();
|
|
94256
|
+
keybindings = new TerminalKeybindingRegistry();
|
|
93865
94257
|
ghosttyModule = null;
|
|
93866
94258
|
ghosttyInitPromise = null;
|
|
93867
94259
|
appDarkMode = false;
|
|
@@ -94036,6 +94428,7 @@ var TerminalController = class {
|
|
|
94036
94428
|
createInputPanelAddon(sessionId, platform) {
|
|
94037
94429
|
return new InputPanelAddon({
|
|
94038
94430
|
onInput: (data) => this.writeToSession(sessionId, data),
|
|
94431
|
+
onCommand: (command) => this.runInputPanelCommand(sessionId, command),
|
|
94039
94432
|
getHistory: async () => this.inputHistoryStore.list(),
|
|
94040
94433
|
addHistory: async (text) => this.inputHistoryStore.add(text),
|
|
94041
94434
|
subscribeHistory: (listener) => this.inputHistoryStore.subscribe(listener),
|
|
@@ -94048,6 +94441,17 @@ var TerminalController = class {
|
|
|
94048
94441
|
}
|
|
94049
94442
|
});
|
|
94050
94443
|
}
|
|
94444
|
+
runInputPanelCommand(sessionId, command) {
|
|
94445
|
+
const instance = this.instances.get(sessionId);
|
|
94446
|
+
if (!instance) return false;
|
|
94447
|
+
return this.keybindings.runCommand(command, {
|
|
94448
|
+
terminal: instance.terminal,
|
|
94449
|
+
writeInput: (data) => this.writeToSession(sessionId, data),
|
|
94450
|
+
zoomFont: (delta) => this.zoomFont(delta),
|
|
94451
|
+
resetFontSize: () => this.resetFontSize(),
|
|
94452
|
+
onAsyncError: (error) => console.error("[terminal] input panel command failed:", error)
|
|
94453
|
+
}) === "block";
|
|
94454
|
+
}
|
|
94051
94455
|
applyGhosttyBackground(instance, container) {
|
|
94052
94456
|
if (instance.rendererEngine !== "ghostty") return;
|
|
94053
94457
|
const currentTheme = instance.terminal.options.theme ?? {};
|
|
@@ -94092,20 +94496,18 @@ var TerminalController = class {
|
|
|
94092
94496
|
}
|
|
94093
94497
|
const mod = event.metaKey || event.ctrlKey;
|
|
94094
94498
|
if (event.type !== "keydown" || !mod) return this.getKeyEventResult(engine, "allow");
|
|
94095
|
-
|
|
94096
|
-
|
|
94097
|
-
|
|
94098
|
-
|
|
94099
|
-
|
|
94100
|
-
|
|
94101
|
-
|
|
94102
|
-
|
|
94103
|
-
|
|
94104
|
-
|
|
94105
|
-
this.resetFontSize();
|
|
94106
|
-
handled = true;
|
|
94499
|
+
const keybindingResult = this.keybindings.handleKeyEvent(event, {
|
|
94500
|
+
terminal,
|
|
94501
|
+
writeInput,
|
|
94502
|
+
zoomFont: (delta) => this.zoomFont(delta),
|
|
94503
|
+
resetFontSize: () => this.resetFontSize(),
|
|
94504
|
+
onAsyncError: (error) => console.error("[terminal] keybinding failed:", error)
|
|
94505
|
+
});
|
|
94506
|
+
if (keybindingResult === "block") {
|
|
94507
|
+
event.preventDefault();
|
|
94508
|
+
event.stopPropagation();
|
|
94107
94509
|
}
|
|
94108
|
-
return this.getKeyEventResult(engine,
|
|
94510
|
+
return this.getKeyEventResult(engine, keybindingResult);
|
|
94109
94511
|
});
|
|
94110
94512
|
}
|
|
94111
94513
|
bindTerminalInput(instance) {
|
|
@@ -94383,12 +94785,16 @@ var TerminalController = class {
|
|
|
94383
94785
|
}
|
|
94384
94786
|
const entries = raw.split(/[,]+/).map((s) => s.trim()).filter(Boolean);
|
|
94385
94787
|
const resolved = [];
|
|
94386
|
-
for (const entry of entries)
|
|
94387
|
-
|
|
94388
|
-
resolved.push(
|
|
94389
|
-
|
|
94390
|
-
|
|
94391
|
-
|
|
94788
|
+
for (const entry of entries) {
|
|
94789
|
+
const localFontFamily = LOCAL_FONT_FAMILY_ALIASES[entry];
|
|
94790
|
+
if (localFontFamily) resolved.push(localFontFamily);
|
|
94791
|
+
else if (GOOGLE_FONT_PRESETS.includes(entry)) {
|
|
94792
|
+
loadGoogleFont(entry);
|
|
94793
|
+
resolved.push(entry);
|
|
94794
|
+
} else {
|
|
94795
|
+
const name = await loadFontSource(entry);
|
|
94796
|
+
if (name) resolved.push(name);
|
|
94797
|
+
}
|
|
94392
94798
|
}
|
|
94393
94799
|
resolved.push(DEFAULT_FONT_FAMILY);
|
|
94394
94800
|
this._setFontFamily(resolved.join(", "));
|
|
@@ -95376,7 +95782,7 @@ function Dialog({ open, title, headerActions, onClose, onDismissRequest, onClose
|
|
|
95376
95782
|
className: `flex h-full w-full items-center justify-center px-4 py-4 ${contentClassName} ${contentShellClassName}`,
|
|
95377
95783
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
95378
95784
|
ref: panelRef,
|
|
95379
|
-
className:
|
|
95785
|
+
className: `@container/dialog bg-background text-foreground relative flex h-fit w-[calc(100%-0.5rem)] max-w-2xl flex-col overflow-hidden rounded-[var(--openspec-dialog-radius,0.75rem)] border shadow-xl ${borderClass} ${className}`,
|
|
95380
95786
|
style: { maxHeight },
|
|
95381
95787
|
children: [
|
|
95382
95788
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
@@ -114783,10 +115189,20 @@ var BrowserTranslatorFactory = class {
|
|
|
114783
115189
|
}), options.signal);
|
|
114784
115190
|
return {
|
|
114785
115191
|
async *batchTranslate(inputs, batchOptions) {
|
|
114786
|
-
for (const [index, input] of inputs.entries())
|
|
114787
|
-
|
|
114788
|
-
|
|
114789
|
-
|
|
115192
|
+
for (const [index, input] of inputs.entries()) {
|
|
115193
|
+
const controlled = await runControlledTranslationTask((signal) => native.translate(input, { signal }), batchOptions);
|
|
115194
|
+
if (controlled.ok) {
|
|
115195
|
+
yield {
|
|
115196
|
+
index,
|
|
115197
|
+
output: controlled.value
|
|
115198
|
+
};
|
|
115199
|
+
continue;
|
|
115200
|
+
}
|
|
115201
|
+
yield {
|
|
115202
|
+
index,
|
|
115203
|
+
error: controlled.error
|
|
115204
|
+
};
|
|
115205
|
+
}
|
|
114790
115206
|
},
|
|
114791
115207
|
destroy() {
|
|
114792
115208
|
native.destroy?.();
|
|
@@ -136453,8 +136869,22 @@ buildSearchIndex(SUPPORTED_TRANSLATION_LANGUAGES.map((language) => ({
|
|
|
136453
136869
|
//#endregion
|
|
136454
136870
|
//#region src/lib/browser-translation.ts
|
|
136455
136871
|
var browserSupportTableCache = /* @__PURE__ */ new Map();
|
|
136872
|
+
function isFiniteTranslationOffset(value) {
|
|
136873
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
136874
|
+
}
|
|
136875
|
+
function isTranslationSegmentKind(value) {
|
|
136876
|
+
return value === "heading" || value === "listItem" || value === "paragraph" || value === "blockquote" || value === "text";
|
|
136877
|
+
}
|
|
136456
136878
|
function isRenderableTranslationSegment(segment) {
|
|
136457
|
-
|
|
136879
|
+
if (typeof segment !== "object" || segment === null || Array.isArray(segment)) return false;
|
|
136880
|
+
const id = Reflect.get(segment, "id");
|
|
136881
|
+
const sourceStartOffset = Reflect.get(segment, "sourceStartOffset");
|
|
136882
|
+
const sourceEndOffset = Reflect.get(segment, "sourceEndOffset");
|
|
136883
|
+
const sourceKind = Reflect.get(segment, "sourceKind");
|
|
136884
|
+
const source = Reflect.get(segment, "source");
|
|
136885
|
+
const translatorInput = Reflect.get(segment, "translatorInput");
|
|
136886
|
+
const kind = Reflect.get(segment, "kind");
|
|
136887
|
+
return typeof id === "string" && isFiniteTranslationOffset(sourceStartOffset) && isFiniteTranslationOffset(sourceEndOffset) && typeof sourceKind === "string" && typeof source === "string" && typeof translatorInput === "string" && isTranslationSegmentKind(kind);
|
|
136458
136888
|
}
|
|
136459
136889
|
function createBrowserTranslationExecution() {
|
|
136460
136890
|
return {
|
|
@@ -136782,6 +137212,7 @@ async function translateMarkdownDocumentProgressively(args, onPatch) {
|
|
|
136782
137212
|
sourceLanguage,
|
|
136783
137213
|
targetLanguage: args.targetLanguage,
|
|
136784
137214
|
signal: args.signal,
|
|
137215
|
+
timeoutMs: args.timeoutMs,
|
|
136785
137216
|
cache: args.cache,
|
|
136786
137217
|
jobs,
|
|
136787
137218
|
translatedSegments,
|
|
@@ -136867,9 +137298,25 @@ async function translatePendingJobsBySourceLanguage(input) {
|
|
|
136867
137298
|
startWorkersToDesired();
|
|
136868
137299
|
}
|
|
136869
137300
|
};
|
|
136870
|
-
const applyBatchResult = async (batch,
|
|
137301
|
+
const applyBatchResult = async (batch, result) => {
|
|
136871
137302
|
for (const [offset, job] of batch.jobs.entries()) {
|
|
136872
|
-
const
|
|
137303
|
+
const error = result.errors.get(offset);
|
|
137304
|
+
if (error) {
|
|
137305
|
+
const failedSegment = {
|
|
137306
|
+
...job.segment,
|
|
137307
|
+
sourceLanguage: job.sourceLanguage,
|
|
137308
|
+
targetLanguage: input.targetLanguage,
|
|
137309
|
+
status: "error",
|
|
137310
|
+
error
|
|
137311
|
+
};
|
|
137312
|
+
input.translatedSegments[job.segmentIndex] = failedSegment;
|
|
137313
|
+
input.onPatch({
|
|
137314
|
+
segmentIndex: job.segmentIndex,
|
|
137315
|
+
segment: failedSegment
|
|
137316
|
+
});
|
|
137317
|
+
continue;
|
|
137318
|
+
}
|
|
137319
|
+
const target = result.outputs.get(offset) ?? "";
|
|
136873
137320
|
const restoredTarget = job.segment.placeholderProtocol ? restoreTranslatedPlaceholderFragment(target, job.segment.placeholderProtocol) : { target: job.protectedInput.restore(target).trim() };
|
|
136874
137321
|
const translatedSegment = {
|
|
136875
137322
|
...job.segment,
|
|
@@ -136908,7 +137355,10 @@ async function translatePendingJobsBySourceLanguage(input) {
|
|
|
136908
137355
|
const batch = batches[batchIndex];
|
|
136909
137356
|
const startedAt = getCurrentTimeMs();
|
|
136910
137357
|
try {
|
|
136911
|
-
await applyBatchResult(batch, await collectBatchTranslationOutputs(translator.batchTranslate(batch.jobs.map((job) => job.protectedInput.text), {
|
|
137358
|
+
await applyBatchResult(batch, await collectBatchTranslationOutputs(translator.batchTranslate(batch.jobs.map((job) => job.protectedInput.text), {
|
|
137359
|
+
signal: input.signal,
|
|
137360
|
+
timeoutMs: input.timeoutMs ?? 15e3
|
|
137361
|
+
}), batch.jobs.length));
|
|
136912
137362
|
completedBatches += 1;
|
|
136913
137363
|
const elapsedMs = Math.max(1, getCurrentTimeMs() - startedAt);
|
|
136914
137364
|
appendTranslationAdaptiveConcurrencyLog({
|
|
@@ -136948,6 +137398,83 @@ async function translatePendingJobsBySourceLanguage(input) {
|
|
|
136948
137398
|
startWorkersToDesired();
|
|
136949
137399
|
while (workerPromises.size > 0) await Promise.race(workerPromises);
|
|
136950
137400
|
}
|
|
137401
|
+
async function retryTranslationSegment(input) {
|
|
137402
|
+
const engine = input.engine ?? createBrowserTranslationExecution();
|
|
137403
|
+
const sourceLanguage = input.sourceLanguage ?? input.segment.sourceLanguage ?? DEFAULT_SOURCE_LANGUAGE;
|
|
137404
|
+
if (areEquivalentTranslationLanguages(sourceLanguage, input.targetLanguage)) return {
|
|
137405
|
+
...input.segment,
|
|
137406
|
+
target: input.segment.source,
|
|
137407
|
+
sourceLanguage,
|
|
137408
|
+
targetLanguage: input.targetLanguage,
|
|
137409
|
+
status: "translated",
|
|
137410
|
+
error: void 0
|
|
137411
|
+
};
|
|
137412
|
+
const unsupportedLanguagePairMessage = getUnsupportedEngineLanguagePairMessage({
|
|
137413
|
+
engine,
|
|
137414
|
+
sourceLanguage,
|
|
137415
|
+
targetLanguage: input.targetLanguage
|
|
137416
|
+
});
|
|
137417
|
+
if (unsupportedLanguagePairMessage) return {
|
|
137418
|
+
...input.segment,
|
|
137419
|
+
sourceLanguage,
|
|
137420
|
+
targetLanguage: input.targetLanguage,
|
|
137421
|
+
status: "error",
|
|
137422
|
+
error: unsupportedLanguagePairMessage
|
|
137423
|
+
};
|
|
137424
|
+
const cacheKey = createSegmentCacheKey(input.segment, sourceLanguage, input.targetLanguage, engine.cacheIdentity);
|
|
137425
|
+
const cachedSegment = cacheKey ? await readCachedTranslationSegment(input.cache, cacheKey, input.segment, {
|
|
137426
|
+
sourceLanguage,
|
|
137427
|
+
targetLanguage: input.targetLanguage
|
|
137428
|
+
}) : null;
|
|
137429
|
+
if (cachedSegment) return cachedSegment;
|
|
137430
|
+
const protectedInput = input.segment.placeholderProtocol ? {
|
|
137431
|
+
text: input.segment.translatorInput,
|
|
137432
|
+
restore: (output) => output
|
|
137433
|
+
} : protectTranslatorInput(input.segment.translatorInput);
|
|
137434
|
+
let translator = null;
|
|
137435
|
+
try {
|
|
137436
|
+
translator = await engine.factory.create({
|
|
137437
|
+
sourceLanguage,
|
|
137438
|
+
targetLanguage: input.targetLanguage,
|
|
137439
|
+
signal: input.signal
|
|
137440
|
+
});
|
|
137441
|
+
const result = await collectBatchTranslationOutputs(translator.batchTranslate([protectedInput.text], {
|
|
137442
|
+
signal: input.signal,
|
|
137443
|
+
timeoutMs: input.timeoutMs ?? 15e3
|
|
137444
|
+
}), 1);
|
|
137445
|
+
const error = result.errors.get(0);
|
|
137446
|
+
if (error) return {
|
|
137447
|
+
...input.segment,
|
|
137448
|
+
sourceLanguage,
|
|
137449
|
+
targetLanguage: input.targetLanguage,
|
|
137450
|
+
status: "error",
|
|
137451
|
+
error
|
|
137452
|
+
};
|
|
137453
|
+
const target = result.outputs.get(0) ?? "";
|
|
137454
|
+
const restoredTarget = input.segment.placeholderProtocol ? restoreTranslatedPlaceholderFragment(target, input.segment.placeholderProtocol) : { target: protectedInput.restore(target).trim() };
|
|
137455
|
+
const translatedSegment = {
|
|
137456
|
+
...input.segment,
|
|
137457
|
+
...restoredTarget,
|
|
137458
|
+
sourceLanguage,
|
|
137459
|
+
targetLanguage: input.targetLanguage,
|
|
137460
|
+
status: "translated",
|
|
137461
|
+
error: void 0
|
|
137462
|
+
};
|
|
137463
|
+
if (cacheKey) writeCachedTranslationSegment(input.cache, cacheKey, translatedSegment);
|
|
137464
|
+
return translatedSegment;
|
|
137465
|
+
} catch (error) {
|
|
137466
|
+
if (input.signal.aborted) throw error;
|
|
137467
|
+
return {
|
|
137468
|
+
...input.segment,
|
|
137469
|
+
sourceLanguage,
|
|
137470
|
+
targetLanguage: input.targetLanguage,
|
|
137471
|
+
status: "error",
|
|
137472
|
+
error: getErrorMessage(error)
|
|
137473
|
+
};
|
|
137474
|
+
} finally {
|
|
137475
|
+
translator?.destroy?.();
|
|
137476
|
+
}
|
|
137477
|
+
}
|
|
136951
137478
|
function getUnsupportedEngineLanguagePairMessage(input) {
|
|
136952
137479
|
if (!isDirectionalManagedLocalTranslationEngineId(input.engine.cacheIdentity.engineId)) return null;
|
|
136953
137480
|
const directionCheck = checkLocalDirectionalModelLanguagePair({
|
|
@@ -137012,12 +137539,17 @@ function packTranslationJobs(jobs) {
|
|
|
137012
137539
|
}
|
|
137013
137540
|
async function collectBatchTranslationOutputs(stream, expectedCount) {
|
|
137014
137541
|
const outputs = /* @__PURE__ */ new Map();
|
|
137542
|
+
const errors = /* @__PURE__ */ new Map();
|
|
137015
137543
|
for await (const item of stream) {
|
|
137016
137544
|
if (item.index < 0 || item.index >= expectedCount) throw new Error(`Translator yielded output for unexpected index ${item.index}.`);
|
|
137017
|
-
if (!outputs.has(item.index)) outputs.set(item.index, item.output);
|
|
137545
|
+
if (item.output !== void 0 && !outputs.has(item.index)) outputs.set(item.index, item.output);
|
|
137546
|
+
if (item.error && !errors.has(item.index)) errors.set(item.index, item.error.message);
|
|
137018
137547
|
}
|
|
137019
|
-
if (outputs.size !== expectedCount) throw new Error(`Translator returned ${outputs.size}
|
|
137020
|
-
return
|
|
137548
|
+
if (outputs.size + errors.size !== expectedCount) throw new Error(`Translator returned ${outputs.size + errors.size} results for ${expectedCount} inputs.`);
|
|
137549
|
+
return {
|
|
137550
|
+
outputs,
|
|
137551
|
+
errors
|
|
137552
|
+
};
|
|
137021
137553
|
}
|
|
137022
137554
|
function estimateTranslationTokens(input) {
|
|
137023
137555
|
const trimmed = input.trim();
|
|
@@ -137561,8 +138093,14 @@ function useDocumentTranslationActivation() {
|
|
|
137561
138093
|
}
|
|
137562
138094
|
//#endregion
|
|
137563
138095
|
//#region src/lib/resolve-document-translation-config.ts
|
|
137564
|
-
function resolveDocumentTranslationConfig(translationConfig, globalSettings) {
|
|
138096
|
+
function resolveDocumentTranslationConfig(translationConfig, globalSettings, configPresence) {
|
|
137565
138097
|
if (!translationConfig) return void 0;
|
|
138098
|
+
const translationPresence = configPresence?.translation;
|
|
138099
|
+
const projectOwnsEnabled = translationPresence?.enabled ?? false;
|
|
138100
|
+
const projectOwnsTargetLanguage = translationPresence?.targetLanguage ?? false;
|
|
138101
|
+
const projectOwnsDisplayMode = translationPresence?.displayMode ?? false;
|
|
138102
|
+
const projectOwnsCacheEnabled = translationPresence?.cacheEnabled ?? false;
|
|
138103
|
+
const projectOwnsEngineId = translationPresence?.engineId ?? false;
|
|
137566
138104
|
const local = translationConfig.engines?.local ?? {};
|
|
137567
138105
|
const localCt2 = translationConfig.engines?.localCt2 ?? {};
|
|
137568
138106
|
const localLlama = translationConfig.engines?.localLlama ?? {};
|
|
@@ -137576,6 +138114,11 @@ function resolveDocumentTranslationConfig(translationConfig, globalSettings) {
|
|
|
137576
138114
|
const resolvedOpenAIModel = openai.model ?? globalSettings?.translationEngines.openai?.model;
|
|
137577
138115
|
return {
|
|
137578
138116
|
...translationConfig,
|
|
138117
|
+
enabled: projectOwnsEnabled ? translationConfig.enabled : globalSettings?.translation?.enabled ?? translationConfig.enabled,
|
|
138118
|
+
targetLanguage: projectOwnsTargetLanguage ? translationConfig.targetLanguage : globalSettings?.translation?.targetLanguage ?? translationConfig.targetLanguage,
|
|
138119
|
+
displayMode: projectOwnsDisplayMode ? translationConfig.displayMode : globalSettings?.translation?.displayMode ?? translationConfig.displayMode,
|
|
138120
|
+
cacheEnabled: projectOwnsCacheEnabled ? translationConfig.cacheEnabled : globalSettings?.translation?.cacheEnabled ?? translationConfig.cacheEnabled,
|
|
138121
|
+
engineId: projectOwnsEngineId ? translationConfig.engineId : globalSettings?.translationEngines.engineId ?? translationConfig.engineId,
|
|
137579
138122
|
engines: {
|
|
137580
138123
|
local: {
|
|
137581
138124
|
...local,
|
|
@@ -137673,6 +138216,11 @@ function projectTranslateServiceStatus(input) {
|
|
|
137673
138216
|
engineId: input.engineId,
|
|
137674
138217
|
message: getTranslationEngineLifecycleMessage(input.engineLifecycle) ?? "Translation engine runtime is not ready."
|
|
137675
138218
|
};
|
|
138219
|
+
if (input.engineLifecycle.assets.state === "error") return {
|
|
138220
|
+
state: "unavailable",
|
|
138221
|
+
engineId: input.engineId,
|
|
138222
|
+
message: input.engineLifecycle.assets.message ?? input.engineLifecycle.assets.error ?? "Selected local model is incompatible with the current translation runtime."
|
|
138223
|
+
};
|
|
137676
138224
|
}
|
|
137677
138225
|
if (isManagedLocalTranslationEngineId(input.engineId)) {
|
|
137678
138226
|
if (!input.localModel?.trim()) return {
|
|
@@ -137965,7 +138513,8 @@ var TrpcTranslator = class {
|
|
|
137965
138513
|
selectedGroupId: this.options.selectedGroupId,
|
|
137966
138514
|
inputs,
|
|
137967
138515
|
instructions: options?.instructions,
|
|
137968
|
-
context: options?.context
|
|
138516
|
+
context: options?.context,
|
|
138517
|
+
timeoutMs: options?.timeoutMs ?? 15e3
|
|
137969
138518
|
}, {
|
|
137970
138519
|
onData(event) {
|
|
137971
138520
|
queue.push(event);
|
|
@@ -138150,6 +138699,7 @@ function useDocumentTranslation(markdown, config) {
|
|
|
138150
138699
|
targetLanguage: config.targetLanguage,
|
|
138151
138700
|
displayMode: config.displayMode,
|
|
138152
138701
|
signal: controller.signal,
|
|
138702
|
+
timeoutMs: DEFAULT_BATCH_TRANSLATION_TIMEOUT_MS,
|
|
138153
138703
|
engine: createTranslationEngineExecution(config),
|
|
138154
138704
|
cache: config.cacheEnabled && !isStaticMode() ? {
|
|
138155
138705
|
read: (keyHash) => trpcClient.translationCache.read.query({ keyHash }),
|
|
@@ -138195,6 +138745,57 @@ function useDocumentTranslation(markdown, config) {
|
|
|
138195
138745
|
markdown,
|
|
138196
138746
|
serviceStatus
|
|
138197
138747
|
]);
|
|
138748
|
+
const retrySegment = (0, import_react.useCallback)(async (segmentId) => {
|
|
138749
|
+
if (!config?.enabled || !result) return;
|
|
138750
|
+
const segmentIndex = result.segments.findIndex((segment) => segment.id === segmentId);
|
|
138751
|
+
const segment = result.segments[segmentIndex];
|
|
138752
|
+
if (segmentIndex < 0 || !segment || segment.status !== "error") return;
|
|
138753
|
+
const controller = new AbortController();
|
|
138754
|
+
const retryingSegment = {
|
|
138755
|
+
...segment,
|
|
138756
|
+
error: void 0,
|
|
138757
|
+
status: "pending"
|
|
138758
|
+
};
|
|
138759
|
+
setResult((current) => current ? {
|
|
138760
|
+
...current,
|
|
138761
|
+
segments: current.segments.map((entry, index) => index === segmentIndex ? retryingSegment : entry)
|
|
138762
|
+
} : current);
|
|
138763
|
+
try {
|
|
138764
|
+
const nextSegment = await retryTranslationSegment({
|
|
138765
|
+
segment,
|
|
138766
|
+
sourceLanguage: segment.sourceLanguage,
|
|
138767
|
+
targetLanguage: config.targetLanguage,
|
|
138768
|
+
signal: controller.signal,
|
|
138769
|
+
timeoutMs: DEFAULT_BATCH_TRANSLATION_TIMEOUT_MS,
|
|
138770
|
+
engine: createTranslationEngineExecution(config),
|
|
138771
|
+
cache: config.cacheEnabled && !isStaticMode() ? {
|
|
138772
|
+
read: (keyHash) => trpcClient.translationCache.read.query({ keyHash }),
|
|
138773
|
+
write: (input) => trpcClient.translationCache.write.mutate(input)
|
|
138774
|
+
} : void 0
|
|
138775
|
+
});
|
|
138776
|
+
setResult((current) => current ? {
|
|
138777
|
+
...current,
|
|
138778
|
+
segments: current.segments.map((entry, index) => index === segmentIndex ? nextSegment : entry)
|
|
138779
|
+
} : current);
|
|
138780
|
+
setError((current) => {
|
|
138781
|
+
if (nextSegment.status === "error") return nextSegment.error ?? current;
|
|
138782
|
+
return getDocumentTranslationFailureMessage(buildRetriedDocumentResult(result, segmentIndex, nextSegment));
|
|
138783
|
+
});
|
|
138784
|
+
setStatus((current) => {
|
|
138785
|
+
if (nextSegment.status === "error") return current === "translated" ? "translated" : "error";
|
|
138786
|
+
return getDocumentTranslationFailureMessage(buildRetriedDocumentResult(result, segmentIndex, nextSegment)) ? "error" : "translated";
|
|
138787
|
+
});
|
|
138788
|
+
} catch (retryError) {
|
|
138789
|
+
setResult((current) => current ? {
|
|
138790
|
+
...current,
|
|
138791
|
+
segments: current.segments.map((entry, index) => index === segmentIndex ? {
|
|
138792
|
+
...segment,
|
|
138793
|
+
status: "error",
|
|
138794
|
+
error: retryError instanceof Error ? retryError.message : "Translation retry failed."
|
|
138795
|
+
} : entry)
|
|
138796
|
+
} : current);
|
|
138797
|
+
}
|
|
138798
|
+
}, [config, result]);
|
|
138198
138799
|
(0, import_react.useEffect)(() => {
|
|
138199
138800
|
latestStartRef.current = start;
|
|
138200
138801
|
}, [start]);
|
|
@@ -138217,12 +138818,13 @@ function useDocumentTranslation(markdown, config) {
|
|
|
138217
138818
|
error,
|
|
138218
138819
|
result,
|
|
138219
138820
|
start,
|
|
138821
|
+
retrySegment,
|
|
138220
138822
|
cancel,
|
|
138221
138823
|
reset
|
|
138222
138824
|
};
|
|
138223
138825
|
}
|
|
138224
138826
|
function isDocumentTranslationSegment(segment) {
|
|
138225
|
-
return
|
|
138827
|
+
return isRenderableTranslationSegment(segment);
|
|
138226
138828
|
}
|
|
138227
138829
|
function getDocumentTranslationFailureMessage(result) {
|
|
138228
138830
|
const segments = (Array.isArray(result.segments) ? result.segments : []).filter(isDocumentTranslationSegment);
|
|
@@ -138250,6 +138852,12 @@ function normalizeDocumentTranslationResult(result) {
|
|
|
138250
138852
|
segments: (Array.isArray(result.segments) ? result.segments : []).filter(isDocumentTranslationSegment)
|
|
138251
138853
|
};
|
|
138252
138854
|
}
|
|
138855
|
+
function buildRetriedDocumentResult(current, segmentIndex, nextSegment) {
|
|
138856
|
+
return normalizeDocumentTranslationResult({
|
|
138857
|
+
...current,
|
|
138858
|
+
segments: current.segments.map((entry, index) => index === segmentIndex ? nextSegment : entry)
|
|
138859
|
+
});
|
|
138860
|
+
}
|
|
138253
138861
|
//#endregion
|
|
138254
138862
|
//#region ../../node_modules/.pnpm/comma-separated-tokens@2.0.3/node_modules/comma-separated-tokens/index.js
|
|
138255
138863
|
/**
|
|
@@ -148855,8 +149463,9 @@ function transformSafeMarkdownUrl(value) {
|
|
|
148855
149463
|
}
|
|
148856
149464
|
//#endregion
|
|
148857
149465
|
//#region src/components/document-translation-segment-render.tsx
|
|
148858
|
-
function renderTranslationSegmentChildren({ sourceChildren, segment, displayMode, targetChildren, className }) {
|
|
149466
|
+
function renderTranslationSegmentChildren({ sourceChildren, segment, displayMode, targetChildren, className, onRetry }) {
|
|
148859
149467
|
const target = segment.target ?? "";
|
|
149468
|
+
const showRetry = segment.status === "error" && typeof onRetry === "function";
|
|
148860
149469
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
148861
149470
|
className: mergeClassName$1("document-translation-segment", className),
|
|
148862
149471
|
children: [displayMode === "bilingual" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
@@ -148869,7 +149478,19 @@ function renderTranslationSegmentChildren({ sourceChildren, segment, displayMode
|
|
|
148869
149478
|
title: displayMode === "direct" ? segment.source : void 0,
|
|
148870
149479
|
lang: segment.targetLanguage,
|
|
148871
149480
|
"data-translation-target": "",
|
|
148872
|
-
children:
|
|
149481
|
+
children: showRetry ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
149482
|
+
className: "inline-flex items-center gap-2",
|
|
149483
|
+
children: [displayMode === "direct" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
149484
|
+
className: "text-muted-foreground",
|
|
149485
|
+
children: segment.source
|
|
149486
|
+
}) : null, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
149487
|
+
size: "sm",
|
|
149488
|
+
variant: "secondary",
|
|
149489
|
+
"aria-label": "Retry translation",
|
|
149490
|
+
onClick: () => onRetry(segment.id),
|
|
149491
|
+
children: "Retry"
|
|
149492
|
+
})]
|
|
149493
|
+
}) : targetChildren ?? (segment.targetNodes ? renderTranslatedHastNodes(segment.targetNodes) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MarkdownInlineContent, { markdown: target }))
|
|
148873
149494
|
})]
|
|
148874
149495
|
});
|
|
148875
149496
|
}
|
|
@@ -148894,13 +149515,13 @@ var OPENSPEC_SECTION_TARGET_LABELS = {
|
|
|
148894
149515
|
overview: "目的",
|
|
148895
149516
|
requirements: "需求"
|
|
148896
149517
|
};
|
|
148897
|
-
function createTranslatedOpenSpecHeadingProjection(input, segment, displayMode) {
|
|
149518
|
+
function createTranslatedOpenSpecHeadingProjection(input, segment, displayMode, onRetry) {
|
|
148898
149519
|
const kind = getCurrentDataAttribute(input, "data-openspec-kind");
|
|
148899
|
-
if (kind === "section") return createTranslatedOpenSpecSectionHeadingProjection(input, segment, displayMode);
|
|
149520
|
+
if (kind === "section") return createTranslatedOpenSpecSectionHeadingProjection(input, segment, displayMode, onRetry);
|
|
148900
149521
|
if (kind !== "requirement" && kind !== "scenario") return void 0;
|
|
148901
|
-
return createTranslatedOpenSpecStructureHeadingProjection(input, segment, displayMode, kind);
|
|
149522
|
+
return createTranslatedOpenSpecStructureHeadingProjection(input, segment, displayMode, kind, onRetry);
|
|
148902
149523
|
}
|
|
148903
|
-
function createTranslatedOpenSpecSectionHeadingProjection(input, segment, displayMode) {
|
|
149524
|
+
function createTranslatedOpenSpecSectionHeadingProjection(input, segment, displayMode, onRetry) {
|
|
148904
149525
|
const sectionKind = getCurrentDataAttribute(input, "data-openspec-section-kind");
|
|
148905
149526
|
if (!sectionKind) return void 0;
|
|
148906
149527
|
const targetTitle = OPENSPEC_SECTION_TARGET_LABELS[sectionKind];
|
|
@@ -148918,11 +149539,12 @@ function createTranslatedOpenSpecSectionHeadingProjection(input, segment, displa
|
|
|
148918
149539
|
},
|
|
148919
149540
|
displayMode,
|
|
148920
149541
|
targetChildren: targetTitle,
|
|
148921
|
-
className: "document-translation-heading-segment"
|
|
149542
|
+
className: "document-translation-heading-segment",
|
|
149543
|
+
onRetry
|
|
148922
149544
|
})
|
|
148923
149545
|
};
|
|
148924
149546
|
}
|
|
148925
|
-
function createTranslatedOpenSpecStructureHeadingProjection(input, segment, displayMode, kind) {
|
|
149547
|
+
function createTranslatedOpenSpecStructureHeadingProjection(input, segment, displayMode, kind, onRetry) {
|
|
148926
149548
|
const sourceParts = splitOpenSpecHeadingText(segment.source, kind);
|
|
148927
149549
|
const targetParts = splitOpenSpecHeadingText(segment.target ?? "", kind);
|
|
148928
149550
|
const visualLabel = getCurrentDataAttribute(input, "data-openspec-visual-label") ?? getCurrentDataAttribute(input, "data-openspec-label");
|
|
@@ -148967,7 +149589,8 @@ function createTranslatedOpenSpecStructureHeadingProjection(input, segment, disp
|
|
|
148967
149589
|
segment: titleSegment,
|
|
148968
149590
|
displayMode,
|
|
148969
149591
|
targetChildren: targetNodes ? renderTranslatedHastNodes(targetNodes) : void 0,
|
|
148970
|
-
className: "document-translation-heading-segment"
|
|
149592
|
+
className: "document-translation-heading-segment",
|
|
149593
|
+
onRetry
|
|
148971
149594
|
})
|
|
148972
149595
|
})] }),
|
|
148973
149596
|
target: targetTitle
|
|
@@ -149028,7 +149651,7 @@ function useDocumentTranslationRenderPlugin({ markdown, translationConfig }) {
|
|
|
149028
149651
|
const resolvedTranslationConfig = (0, import_react.useMemo)(() => translationConfig === void 0 ? void 0 : DocumentTranslationConfigSchema.parse(resolveDocumentTranslationConfig(translationConfig, globalSettings)), [globalSettings, translationConfig]);
|
|
149029
149652
|
const session = useDocumentTranslation(markdown ?? "", resolvedTranslationConfig);
|
|
149030
149653
|
const canTranslate = resolvedTranslationConfig !== void 0 && typeof markdown === "string" && markdown.length > 0;
|
|
149031
|
-
const translationProjection = (0, import_react.useMemo)(() => createTranslationProjection(session.result), [session.result]);
|
|
149654
|
+
const translationProjection = (0, import_react.useMemo)(() => createTranslationProjection(session.result, session.retrySegment), [session.result, session.retrySegment]);
|
|
149032
149655
|
const translationAction = (0, import_react.useMemo)(() => canTranslate ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DocumentTranslationAction, {
|
|
149033
149656
|
enabled: resolvedTranslationConfig?.enabled ?? false,
|
|
149034
149657
|
session
|
|
@@ -149099,7 +149722,7 @@ function hashString(value) {
|
|
|
149099
149722
|
for (let index = 0; index < value.length; index++) hash = hash * 31 + value.charCodeAt(index) | 0;
|
|
149100
149723
|
return hash.toString(36);
|
|
149101
149724
|
}
|
|
149102
|
-
function createTranslationProjection(result) {
|
|
149725
|
+
function createTranslationProjection(result, onRetrySegment) {
|
|
149103
149726
|
if (!result) return { blockAnnotations: [] };
|
|
149104
149727
|
const segments = getRenderableTranslationSegments(result);
|
|
149105
149728
|
const segmentByOffset = new Map(segments.filter((segment) => segment.target).map((segment) => [segment.sourceStartOffset, segment]));
|
|
@@ -149121,7 +149744,7 @@ function createTranslationProjection(result) {
|
|
|
149121
149744
|
transformHeading(input) {
|
|
149122
149745
|
const segment = input.sourceStartOffset === void 0 ? void 0 : segmentByOffset.get(input.sourceStartOffset);
|
|
149123
149746
|
if (!segment?.target || segment.kind !== "heading") return void 0;
|
|
149124
|
-
return createTranslatedHeadingTransform(input, segment, result.displayMode);
|
|
149747
|
+
return createTranslatedHeadingTransform(input, segment, result.displayMode, onRetrySegment);
|
|
149125
149748
|
}
|
|
149126
149749
|
},
|
|
149127
149750
|
blockAnnotations: segments.filter((segment) => segment.target && segment.kind !== "heading").map((segment) => ({
|
|
@@ -149140,7 +149763,8 @@ function createTranslationProjection(result) {
|
|
|
149140
149763
|
renderChildren: (children) => segment.targetNodes && result.displayMode === "direct" ? children : renderTranslationSegmentChildren({
|
|
149141
149764
|
sourceChildren: children,
|
|
149142
149765
|
segment,
|
|
149143
|
-
displayMode: result.displayMode
|
|
149766
|
+
displayMode: result.displayMode,
|
|
149767
|
+
onRetry: onRetrySegment
|
|
149144
149768
|
})
|
|
149145
149769
|
}))
|
|
149146
149770
|
};
|
|
@@ -149148,9 +149772,9 @@ function createTranslationProjection(result) {
|
|
|
149148
149772
|
function getRenderableTranslationSegments(result) {
|
|
149149
149773
|
return (Array.isArray(result.segments) ? result.segments : []).filter(isRenderableTranslationSegment);
|
|
149150
149774
|
}
|
|
149151
|
-
function createTranslatedHeadingTransform(input, segment, displayMode) {
|
|
149775
|
+
function createTranslatedHeadingTransform(input, segment, displayMode, onRetrySegment) {
|
|
149152
149776
|
const projectedTarget = segment.target ?? "";
|
|
149153
|
-
const openSpecHeading = createTranslatedOpenSpecHeadingProjection(input, segment, displayMode);
|
|
149777
|
+
const openSpecHeading = createTranslatedOpenSpecHeadingProjection(input, segment, displayMode, onRetrySegment);
|
|
149154
149778
|
if (openSpecHeading) return {
|
|
149155
149779
|
tocDataLabel: displayMode === "direct" ? openSpecHeading.tocDataLabel : input.current?.tocLabel ?? input.text,
|
|
149156
149780
|
children: openSpecHeading.children,
|
|
@@ -149165,7 +149789,8 @@ function createTranslatedHeadingTransform(input, segment, displayMode) {
|
|
|
149165
149789
|
segment,
|
|
149166
149790
|
displayMode,
|
|
149167
149791
|
targetChildren,
|
|
149168
|
-
className: "document-translation-heading-segment"
|
|
149792
|
+
className: "document-translation-heading-segment",
|
|
149793
|
+
onRetry: onRetrySegment
|
|
149169
149794
|
}),
|
|
149170
149795
|
dataAttributes: createTranslationDataAttributes(segment, projectedTarget, displayMode)
|
|
149171
149796
|
};
|
|
@@ -149176,7 +149801,8 @@ function createTranslatedHeadingTransform(input, segment, displayMode) {
|
|
|
149176
149801
|
segment,
|
|
149177
149802
|
displayMode,
|
|
149178
149803
|
targetChildren,
|
|
149179
|
-
className: "document-translation-heading-segment"
|
|
149804
|
+
className: "document-translation-heading-segment",
|
|
149805
|
+
onRetry: onRetrySegment
|
|
149180
149806
|
}),
|
|
149181
149807
|
dataAttributes: createTranslationDataAttributes(segment, projectedTarget, displayMode)
|
|
149182
149808
|
};
|