@openspecui/web 3.11.0 → 3.11.1
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-Bs7UxSWT.js +1 -0
- package/dist/assets/WebGLRenderer-l71uR9MI.js +1 -0
- package/dist/assets/WebGPURenderer-tjCbVxRm.js +1 -0
- package/dist/assets/browserAll-BDY91DxA.js +1 -0
- package/dist/assets/{dist-CcLC6JdJ.js → dist--JzlUmDP.js} +1 -1
- package/dist/assets/{dist-D0kk4OnI.js → dist-B09y0Ph7.js} +1 -1
- package/dist/assets/{dist-Co2y3Dp-.js → dist-BttXL4wz.js} +1 -1
- package/dist/assets/{dist-CRlC9_e7.js → dist-C9BN4134.js} +1 -1
- package/dist/assets/dist-CCD9CqTu.js +1 -0
- package/dist/assets/{dist-DSHRZu7v.js → dist-DdsOxRxJ.js} +1 -1
- package/dist/assets/dist-DjM_Envn.js +1 -0
- package/dist/assets/{dist-Deq3d3tg.js → dist-Dx00xLFT.js} +1 -1
- package/dist/assets/{dist-B_uzjHQN.js → dist-DxmYOUGn.js} +1 -1
- package/dist/assets/{dist-D7t0ICkd.js → dist-F0lgtwe2.js} +1 -1
- package/dist/assets/dist-UpX5-9sH.js +1 -0
- package/dist/assets/{dist-CjSC6Iz-.js → dist-rGlPGEMw.js} +1 -1
- package/dist/assets/{init-CXvIgPy6.js → init-C46YDZ2H.js} +1 -1
- package/dist/assets/main-B2c4pZCT.css +1 -0
- package/dist/assets/{main-DjDAttzm.js → main-Wj4p5q80.js} +175 -167
- package/dist/assets/trpc-1XzKnuJv.js +1 -0
- package/dist/assets/webworkerAll-CitYd6ji.js +1 -0
- package/dist/index.html +2 -2
- package/dist-ssg/client/.vite/ssr-manifest.json +33 -15
- package/dist-ssg/client/assets/CanvasRenderer-FPbXzOhu.js +1 -0
- package/dist-ssg/client/assets/WebGLRenderer-DTbkQ-Tc.js +1 -0
- package/dist-ssg/client/assets/WebGPURenderer-jYEtkBkX.js +1 -0
- package/dist-ssg/client/assets/browserAll-D2rErTpO.js +1 -0
- package/dist-ssg/client/assets/dist-03Q-XuhL.js +1 -0
- package/dist-ssg/client/assets/{dist-xlAWlzHU.js → dist-9ZjKnAh1.js} +1 -1
- package/dist-ssg/client/assets/{dist-zooxroSS.js → dist-BPn14NhJ.js} +1 -1
- package/dist-ssg/client/assets/{dist-C8h2jqYd.js → dist-BRxWvz6j.js} +1 -1
- package/dist-ssg/client/assets/dist-CNXuEBuZ.js +1 -0
- package/dist-ssg/client/assets/{dist-Ct0osEG9.js → dist-DOwxbW7B.js} +1 -1
- package/dist-ssg/client/assets/{dist-DYA7aYgJ.js → dist-D_7Z5apg.js} +1 -1
- package/dist-ssg/client/assets/{dist-B0rNAJNr.js → dist-Dg-rGFsy.js} +1 -1
- package/dist-ssg/client/assets/dist-Dj9a_D4b.js +1 -0
- package/dist-ssg/client/assets/{dist-nDVKH9rz.js → dist-DjZdWHNx.js} +1 -1
- package/dist-ssg/client/assets/{dist-CIDagwl8.js → dist-hWAvow10.js} +1 -1
- package/dist-ssg/client/assets/{dist-B_e3vKVI.js → dist-yriBIRgD.js} +1 -1
- package/dist-ssg/client/assets/{ghostty-web-MvkhtIaS.js → ghostty-web-BVM0FkWD.js} +1 -1
- package/dist-ssg/client/assets/index-5OettMZv.css +1 -0
- package/dist-ssg/client/assets/index.ssg-C4D0iHIp.js +1624 -0
- package/dist-ssg/client/assets/{init-CbwghP3k.js → init-DBoYmUC7.js} +1 -1
- package/dist-ssg/client/assets/trpc-J2T_izXe.js +1 -0
- package/dist-ssg/client/assets/webworkerAll-CLzsuMst.js +1 -0
- package/dist-ssg/client/index.ssg.html +2 -2
- package/dist-ssg/server/entry-server.js +1093 -457
- package/package.json +3 -3
- package/dist/assets/CanvasRenderer-Cntd8ry7.js +0 -1
- package/dist/assets/WebGLRenderer-DZEgkU7P.js +0 -1
- package/dist/assets/WebGPURenderer-DtnLusyN.js +0 -1
- package/dist/assets/browserAll-C0q2DkVO.js +0 -1
- package/dist/assets/dist-CfJPknqn.js +0 -1
- package/dist/assets/dist-DqB_uiSZ.js +0 -1
- package/dist/assets/dist-jEMUT-cO.js +0 -1
- package/dist/assets/main-Dyvh_8NL.css +0 -1
- package/dist/assets/trpc-CSBEzIgb.js +0 -1
- package/dist/assets/webworkerAll-DhUUBZ9J.js +0 -1
- package/dist-ssg/client/assets/CanvasRenderer-D3Q5_w9A.js +0 -1
- package/dist-ssg/client/assets/WebGLRenderer-D9oc2qKY.js +0 -1
- package/dist-ssg/client/assets/WebGPURenderer-C5zSqQBE.js +0 -1
- package/dist-ssg/client/assets/browserAll-CIBhnrSW.js +0 -1
- package/dist-ssg/client/assets/dist-BSCnmcZh.js +0 -1
- package/dist-ssg/client/assets/dist-C1zSmOmx.js +0 -1
- package/dist-ssg/client/assets/dist-CXNNfjwS.js +0 -1
- package/dist-ssg/client/assets/index-D2aBuJqY.css +0 -1
- package/dist-ssg/client/assets/index.ssg-Dp15bsQU.js +0 -1616
- package/dist-ssg/client/assets/trpc-BccI0xyZ.js +0 -1
- package/dist-ssg/client/assets/webworkerAll-CYURuxHF.js +0 -1
|
@@ -32268,7 +32268,7 @@ ZodSymbol.create;
|
|
|
32268
32268
|
ZodUndefined.create;
|
|
32269
32269
|
ZodNull.create;
|
|
32270
32270
|
ZodAny.create;
|
|
32271
|
-
ZodUnknown.create;
|
|
32271
|
+
var unknownType = ZodUnknown.create;
|
|
32272
32272
|
ZodNever.create;
|
|
32273
32273
|
ZodVoid.create;
|
|
32274
32274
|
var arrayType = ZodArray.create;
|
|
@@ -32311,7 +32311,11 @@ var LocalModelDownloadStatusSchema = enumType([
|
|
|
32311
32311
|
var TranslationDownloadFilePlanSchema = objectType({
|
|
32312
32312
|
path: stringType().min(1),
|
|
32313
32313
|
sizeBytes: numberType().int().nonnegative().optional(),
|
|
32314
|
-
required: booleanType()
|
|
32314
|
+
required: booleanType(),
|
|
32315
|
+
etag: stringType().min(1).optional(),
|
|
32316
|
+
revision: stringType().min(1).optional(),
|
|
32317
|
+
sourceUrl: stringType().min(1).optional(),
|
|
32318
|
+
raw: unknownType().optional()
|
|
32315
32319
|
});
|
|
32316
32320
|
var TranslationDownloadGroupPlanSchema = objectType({
|
|
32317
32321
|
id: stringType().min(1),
|
|
@@ -32320,14 +32324,97 @@ var TranslationDownloadGroupPlanSchema = objectType({
|
|
|
32320
32324
|
profile: stringType().min(1).optional(),
|
|
32321
32325
|
dtype: stringType().min(1).optional(),
|
|
32322
32326
|
estimatedTotalBytes: numberType().int().nonnegative().optional(),
|
|
32327
|
+
baseGroupId: stringType().min(1).optional(),
|
|
32328
|
+
commitHash: stringType().min(1).optional(),
|
|
32329
|
+
shortCommitHash: stringType().min(1).optional(),
|
|
32330
|
+
rootDir: stringType().min(1).optional(),
|
|
32331
|
+
status: LocalModelDownloadStatusSchema.optional(),
|
|
32332
|
+
progress: numberType().min(0).max(1).optional(),
|
|
32333
|
+
bytesDownloaded: numberType().int().nonnegative().optional(),
|
|
32334
|
+
totalBytes: numberType().int().nonnegative().optional(),
|
|
32335
|
+
resumable: booleanType().optional(),
|
|
32336
|
+
error: stringType().optional(),
|
|
32323
32337
|
selectable: booleanType(),
|
|
32324
32338
|
selected: booleanType(),
|
|
32325
32339
|
files: arrayType(TranslationDownloadFilePlanSchema)
|
|
32326
32340
|
});
|
|
32341
|
+
var LocalModelProfileStatusSchema = enumType([
|
|
32342
|
+
"idle",
|
|
32343
|
+
"loading",
|
|
32344
|
+
"ready",
|
|
32345
|
+
"error"
|
|
32346
|
+
]);
|
|
32347
|
+
var LocalModelProfileManifestFileSchema = objectType({
|
|
32348
|
+
path: stringType().min(1),
|
|
32349
|
+
sizeBytes: numberType().int().nonnegative().optional(),
|
|
32350
|
+
required: booleanType(),
|
|
32351
|
+
etag: stringType().min(1).optional(),
|
|
32352
|
+
revision: stringType().min(1).optional(),
|
|
32353
|
+
sourceUrl: stringType().min(1).optional(),
|
|
32354
|
+
raw: unknownType().optional()
|
|
32355
|
+
});
|
|
32356
|
+
var LocalModelProfileManifestGroupSchema = objectType({
|
|
32357
|
+
id: stringType().min(1),
|
|
32358
|
+
baseGroupId: stringType().min(1),
|
|
32359
|
+
label: stringType().min(1),
|
|
32360
|
+
displayLabel: stringType().min(1),
|
|
32361
|
+
description: stringType().optional(),
|
|
32362
|
+
profile: stringType().min(1).optional(),
|
|
32363
|
+
dtype: stringType().min(1).optional(),
|
|
32364
|
+
commitHash: stringType().min(1),
|
|
32365
|
+
shortCommitHash: stringType().min(1),
|
|
32366
|
+
rootDir: stringType().min(1),
|
|
32367
|
+
estimatedTotalBytes: numberType().int().nonnegative().optional(),
|
|
32368
|
+
selectable: booleanType(),
|
|
32369
|
+
files: arrayType(LocalModelProfileManifestFileSchema)
|
|
32370
|
+
});
|
|
32371
|
+
var LocalModelProfileManifestSchema = objectType({
|
|
32372
|
+
modelId: stringType().min(1),
|
|
32373
|
+
source: literalType("huggingface"),
|
|
32374
|
+
endpoint: stringType().default(""),
|
|
32375
|
+
revision: stringType().min(1),
|
|
32376
|
+
commitHash: stringType().min(1),
|
|
32377
|
+
shortCommitHash: stringType().min(1),
|
|
32378
|
+
fetchedAt: numberType().int().nonnegative(),
|
|
32379
|
+
updatedAt: numberType().int().nonnegative(),
|
|
32380
|
+
raw: unknownType().optional(),
|
|
32381
|
+
groups: recordType(stringType(), LocalModelProfileManifestGroupSchema).default({}),
|
|
32382
|
+
groupOrder: arrayType(stringType().min(1)).default([])
|
|
32383
|
+
});
|
|
32384
|
+
var LocalModelLifecycleFileStateSchema = objectType({
|
|
32385
|
+
path: stringType().min(1),
|
|
32386
|
+
sizeBytes: numberType().int().nonnegative().optional(),
|
|
32387
|
+
downloadedBytes: numberType().int().nonnegative().optional(),
|
|
32388
|
+
required: booleanType().default(true),
|
|
32389
|
+
status: LocalModelDownloadStatusSchema.default("not-downloaded"),
|
|
32390
|
+
updatedAt: numberType().int().nonnegative().optional(),
|
|
32391
|
+
error: stringType().optional()
|
|
32392
|
+
});
|
|
32393
|
+
var LocalModelLifecycleGroupStateSchema = objectType({
|
|
32394
|
+
groupId: stringType().min(1),
|
|
32395
|
+
baseGroupId: stringType().min(1).optional(),
|
|
32396
|
+
status: LocalModelDownloadStatusSchema.default("not-downloaded"),
|
|
32397
|
+
rootDir: stringType().min(1).optional(),
|
|
32398
|
+
bytesDownloaded: numberType().int().nonnegative().optional(),
|
|
32399
|
+
totalBytes: numberType().int().nonnegative().optional(),
|
|
32400
|
+
progress: numberType().min(0).max(1).optional(),
|
|
32401
|
+
resumable: booleanType().default(false),
|
|
32402
|
+
error: stringType().optional(),
|
|
32403
|
+
installedAt: numberType().int().nonnegative().optional(),
|
|
32404
|
+
updatedAt: numberType().int().nonnegative().optional(),
|
|
32405
|
+
files: arrayType(LocalModelLifecycleFileStateSchema).default([])
|
|
32406
|
+
});
|
|
32407
|
+
var LocalModelProfileLoadStateSchema = objectType({
|
|
32408
|
+
status: LocalModelProfileStatusSchema.default("idle"),
|
|
32409
|
+
message: stringType().optional(),
|
|
32410
|
+
error: stringType().optional(),
|
|
32411
|
+
updatedAt: numberType().int().nonnegative().optional()
|
|
32412
|
+
});
|
|
32327
32413
|
objectType({
|
|
32328
32414
|
engineId: literalType("local"),
|
|
32329
32415
|
modelId: stringType().min(1),
|
|
32330
32416
|
selectedGroupId: stringType().min(1).optional(),
|
|
32417
|
+
groupId: stringType().min(1).optional(),
|
|
32331
32418
|
status: LocalModelDownloadStatusSchema,
|
|
32332
32419
|
message: stringType(),
|
|
32333
32420
|
progress: numberType().min(0).max(1).optional(),
|
|
@@ -32352,8 +32439,10 @@ var LocalModelAssetPlanSnapshotSchema = objectType({
|
|
|
32352
32439
|
});
|
|
32353
32440
|
objectType({
|
|
32354
32441
|
modelId: stringType().min(1),
|
|
32442
|
+
version: literalType(2).default(2),
|
|
32355
32443
|
status: LocalModelDownloadStatusSchema.default("not-downloaded"),
|
|
32356
32444
|
selected: booleanType().default(false),
|
|
32445
|
+
selectedGroupId: stringType().min(1).optional(),
|
|
32357
32446
|
installedAt: numberType().int().nonnegative().optional(),
|
|
32358
32447
|
updatedAt: numberType().int().nonnegative().optional(),
|
|
32359
32448
|
bytesDownloaded: numberType().int().nonnegative().optional(),
|
|
@@ -32361,6 +32450,9 @@ objectType({
|
|
|
32361
32450
|
progress: numberType().min(0).max(1).optional(),
|
|
32362
32451
|
resumable: booleanType().default(false),
|
|
32363
32452
|
error: stringType().optional(),
|
|
32453
|
+
profileLoad: LocalModelProfileLoadStateSchema.default(LocalModelProfileLoadStateSchema.parse({})),
|
|
32454
|
+
profileManifest: LocalModelProfileManifestSchema.optional(),
|
|
32455
|
+
groupsState: recordType(stringType(), LocalModelLifecycleGroupStateSchema).default({}),
|
|
32364
32456
|
plan: LocalModelAssetPlanSnapshotSchema.optional(),
|
|
32365
32457
|
files: arrayType(objectType({
|
|
32366
32458
|
path: stringType().min(1),
|
|
@@ -42699,6 +42791,12 @@ function useConfigSubscription() {
|
|
|
42699
42791
|
onError: callbacks.onError
|
|
42700
42792
|
}), getConfig$1, [], "config.subscribe");
|
|
42701
42793
|
}
|
|
42794
|
+
function useGlobalSettingsSubscription() {
|
|
42795
|
+
return useSubscription((callbacks) => trpcClient.globalSettings.subscribe.subscribe(void 0, {
|
|
42796
|
+
onData: callbacks.onData,
|
|
42797
|
+
onError: callbacks.onError
|
|
42798
|
+
}), void 0, [], "globalSettings.subscribe");
|
|
42799
|
+
}
|
|
42702
42800
|
//#endregion
|
|
42703
42801
|
//#region src/lib/use-opsx.ts
|
|
42704
42802
|
function getOpsxStatusSubscriptionCacheKey(input) {
|
|
@@ -44002,6 +44100,15 @@ var Expand = createLucideIcon("Expand", [
|
|
|
44002
44100
|
key: "u9ee12"
|
|
44003
44101
|
}]
|
|
44004
44102
|
]);
|
|
44103
|
+
var Eye = createLucideIcon("Eye", [["path", {
|
|
44104
|
+
d: "M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0",
|
|
44105
|
+
key: "1nclc0"
|
|
44106
|
+
}], ["circle", {
|
|
44107
|
+
cx: "12",
|
|
44108
|
+
cy: "12",
|
|
44109
|
+
r: "3",
|
|
44110
|
+
key: "1v7zrd"
|
|
44111
|
+
}]]);
|
|
44005
44112
|
var FileCode2 = createLucideIcon("FileCode2", [
|
|
44006
44113
|
["path", {
|
|
44007
44114
|
d: "M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4",
|
|
@@ -44020,6 +44127,20 @@ var FileCode2 = createLucideIcon("FileCode2", [
|
|
|
44020
44127
|
key: "112psh"
|
|
44021
44128
|
}]
|
|
44022
44129
|
]);
|
|
44130
|
+
var FilePenLine = createLucideIcon("FilePenLine", [
|
|
44131
|
+
["path", {
|
|
44132
|
+
d: "m18 5-2.414-2.414A2 2 0 0 0 14.172 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2",
|
|
44133
|
+
key: "142zxg"
|
|
44134
|
+
}],
|
|
44135
|
+
["path", {
|
|
44136
|
+
d: "M21.378 12.626a1 1 0 0 0-3.004-3.004l-4.01 4.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z",
|
|
44137
|
+
key: "2t3380"
|
|
44138
|
+
}],
|
|
44139
|
+
["path", {
|
|
44140
|
+
d: "M8 18h1",
|
|
44141
|
+
key: "13wk12"
|
|
44142
|
+
}]
|
|
44143
|
+
]);
|
|
44023
44144
|
var FilePlus = createLucideIcon("FilePlus", [
|
|
44024
44145
|
["path", {
|
|
44025
44146
|
d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z",
|
|
@@ -44519,6 +44640,24 @@ var Save = createLucideIcon("Save", [
|
|
|
44519
44640
|
key: "t51u73"
|
|
44520
44641
|
}]
|
|
44521
44642
|
]);
|
|
44643
|
+
var ScrollText = createLucideIcon("ScrollText", [
|
|
44644
|
+
["path", {
|
|
44645
|
+
d: "M15 12h-5",
|
|
44646
|
+
key: "r7krc0"
|
|
44647
|
+
}],
|
|
44648
|
+
["path", {
|
|
44649
|
+
d: "M15 8h-5",
|
|
44650
|
+
key: "1khuty"
|
|
44651
|
+
}],
|
|
44652
|
+
["path", {
|
|
44653
|
+
d: "M19 17V5a2 2 0 0 0-2-2H4",
|
|
44654
|
+
key: "zz82l3"
|
|
44655
|
+
}],
|
|
44656
|
+
["path", {
|
|
44657
|
+
d: "M8 21h12a2 2 0 0 0 2-2v-1a1 1 0 0 0-1-1H11a1 1 0 0 0-1 1v1a2 2 0 1 1-4 0V5a2 2 0 1 0-4 0v2a1 1 0 0 0 1 1h3",
|
|
44658
|
+
key: "1ph1d7"
|
|
44659
|
+
}]
|
|
44660
|
+
]);
|
|
44522
44661
|
var Search = createLucideIcon("Search", [["circle", {
|
|
44523
44662
|
cx: "11",
|
|
44524
44663
|
cy: "11",
|
|
@@ -55153,8 +55292,12 @@ function inertValue(value) {
|
|
|
55153
55292
|
//#region src/components/tooltip.tsx
|
|
55154
55293
|
function Tooltip({ content, children, delay = 180, sideOffset = 8, className }) {
|
|
55155
55294
|
if (!content) return children;
|
|
55295
|
+
const trigger = typeof children.props === "object" && children.props !== null && "disabled" in children.props && Boolean(children.props.disabled) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
55296
|
+
className: "inline-flex max-w-full",
|
|
55297
|
+
children
|
|
55298
|
+
}) : children;
|
|
55156
55299
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TooltipRoot, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TooltipTrigger, {
|
|
55157
|
-
render:
|
|
55300
|
+
render: trigger,
|
|
55158
55301
|
delay
|
|
55159
55302
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TooltipPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TooltipPositioner, {
|
|
55160
55303
|
sideOffset,
|
|
@@ -96609,20 +96752,29 @@ var Button = (0, import_react.forwardRef)(function Button({ variant = "primary",
|
|
|
96609
96752
|
/**
|
|
96610
96753
|
* Compact segmented buttons with single-select behavior.
|
|
96611
96754
|
*/
|
|
96612
|
-
function ButtonGroup({ value, options, onChange, className = "", tone = "default" }) {
|
|
96755
|
+
function ButtonGroup({ value, options, onChange, className = "", tone = "default", presentation = "label" }) {
|
|
96613
96756
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
96614
96757
|
className: `inline-flex w-fit max-w-full shrink-0 self-start overflow-hidden rounded-md border ${tone === "terminal" ? "border-terminal-foreground/25 bg-terminal/70 text-terminal-foreground" : "border-border bg-card"} ${className}`,
|
|
96615
96758
|
children: options.map((option, index) => {
|
|
96616
96759
|
const active = option.value === value;
|
|
96617
96760
|
const stateClassName = active ? "bg-primary text-primary-foreground" : tone === "terminal" ? "text-terminal-foreground/72 hover:bg-terminal-foreground/10 hover:text-terminal-foreground" : "text-muted-foreground hover:bg-muted/60 hover:text-foreground";
|
|
96618
|
-
|
|
96761
|
+
const accessibleLabel = option.ariaLabel ?? (typeof option.label === "string" ? option.label : void 0);
|
|
96762
|
+
const tooltipContent = option.tooltip ?? accessibleLabel;
|
|
96763
|
+
const content = presentation === "icon-only" ? option.icon ?? option.label : presentation === "icon-label" && option.icon ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [option.icon, /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: option.label })] }) : option.label;
|
|
96764
|
+
const button = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
96619
96765
|
type: "button",
|
|
96620
96766
|
disabled: option.disabled,
|
|
96621
96767
|
onClick: () => onChange(option.value),
|
|
96622
96768
|
"aria-pressed": active,
|
|
96623
|
-
|
|
96624
|
-
|
|
96769
|
+
"aria-label": presentation === "icon-only" ? accessibleLabel : void 0,
|
|
96770
|
+
title: presentation === "icon-only" && typeof accessibleLabel === "string" ? accessibleLabel : void 0,
|
|
96771
|
+
className: `inline-flex items-center justify-center gap-1.5 text-xs font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50 ${presentation === "icon-only" ? "h-8 w-8 p-0" : "px-3 py-1.5"} ${index > 0 ? tone === "terminal" ? "border-terminal-foreground/20 border-l" : "border-border border-l" : ""} ${stateClassName}`,
|
|
96772
|
+
children: content
|
|
96625
96773
|
}, option.value);
|
|
96774
|
+
return tooltipContent ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tooltip, {
|
|
96775
|
+
content: tooltipContent,
|
|
96776
|
+
children: button
|
|
96777
|
+
}, option.value) : button;
|
|
96626
96778
|
})
|
|
96627
96779
|
});
|
|
96628
96780
|
}
|
|
@@ -114041,6 +114193,7 @@ var layoutStyles = String.raw`
|
|
|
114041
114193
|
display: flex;
|
|
114042
114194
|
flex-direction: column;
|
|
114043
114195
|
height: 100%;
|
|
114196
|
+
min-height: 0;
|
|
114044
114197
|
gap: 0.75rem;
|
|
114045
114198
|
}
|
|
114046
114199
|
.fev-sidebar-tabs {
|
|
@@ -114048,6 +114201,7 @@ var layoutStyles = String.raw`
|
|
|
114048
114201
|
}
|
|
114049
114202
|
.fev-sidebar-tree {
|
|
114050
114203
|
display: none;
|
|
114204
|
+
min-height: 0;
|
|
114051
114205
|
}
|
|
114052
114206
|
.fev-editor-wrapper {
|
|
114053
114207
|
display: flex;
|
|
@@ -114061,8 +114215,10 @@ var layoutStyles = String.raw`
|
|
|
114061
114215
|
.fev-layout {
|
|
114062
114216
|
display: grid;
|
|
114063
114217
|
grid-template-columns: minmax(0, 1fr) minmax(240px, clamp(240px, 30%, 420px));
|
|
114218
|
+
grid-template-rows: minmax(0, 1fr);
|
|
114064
114219
|
gap: 1rem;
|
|
114065
114220
|
min-height: 0;
|
|
114221
|
+
overflow: hidden;
|
|
114066
114222
|
}
|
|
114067
114223
|
.fev-sidebar-tabs {
|
|
114068
114224
|
display: none;
|
|
@@ -114070,9 +114226,13 @@ var layoutStyles = String.raw`
|
|
|
114070
114226
|
.fev-sidebar-tree {
|
|
114071
114227
|
display: block;
|
|
114072
114228
|
order: 2;
|
|
114229
|
+
height: 100%;
|
|
114230
|
+
min-height: 0;
|
|
114231
|
+
overflow: hidden;
|
|
114073
114232
|
}
|
|
114074
114233
|
.fev-editor-wrapper {
|
|
114075
114234
|
order: 1;
|
|
114235
|
+
min-height: 0;
|
|
114076
114236
|
}
|
|
114077
114237
|
}
|
|
114078
114238
|
.CodeMirror {
|
|
@@ -114250,7 +114410,8 @@ function FileTree({ entries, selectedPath, onSelect, headerLabel, headerActions,
|
|
|
114250
114410
|
const closeMenu = () => setMenuState(null);
|
|
114251
114411
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ContextMenuWrapper, {
|
|
114252
114412
|
ref: wrapperRef,
|
|
114253
|
-
className: "border-border bg-muted/30 flex h-full flex-col rounded-md border",
|
|
114413
|
+
className: "border-border bg-muted/30 flex h-full min-h-0 flex-col rounded-md border",
|
|
114414
|
+
"data-file-explorer-tree": "",
|
|
114254
114415
|
children: [
|
|
114255
114416
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
114256
114417
|
className: "border-border/50 text-muted-foreground flex items-center justify-between border-b px-3 py-2 text-xs font-medium",
|
|
@@ -114260,7 +114421,8 @@ function FileTree({ entries, selectedPath, onSelect, headerLabel, headerActions,
|
|
|
114260
114421
|
}), headerActions]
|
|
114261
114422
|
}),
|
|
114262
114423
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
114263
|
-
|
|
114424
|
+
"data-file-explorer-tree-scroll": "",
|
|
114425
|
+
className: "scrollbar-thin scrollbar-track-transparent min-h-0 flex-1 overflow-y-auto",
|
|
114264
114426
|
children: entries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
114265
114427
|
className: "text-muted-foreground px-3 py-2 text-xs",
|
|
114266
114428
|
children: "No files yet."
|
|
@@ -114327,7 +114489,7 @@ function FileExplorer({ entries, selectedPath, onSelect, breadcrumbRoot, headerL
|
|
|
114327
114489
|
return sortedEntries.find((entry) => entry.path === selectedPath && entry.type === "file") ?? null;
|
|
114328
114490
|
}, [sortedEntries, selectedPath]);
|
|
114329
114491
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
114330
|
-
className: "@container-[size] h-full",
|
|
114492
|
+
className: "@container-[size] h-full min-h-0 overflow-hidden",
|
|
114331
114493
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: layoutStyles }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
114332
114494
|
className: "fev-layout",
|
|
114333
114495
|
children: [
|
|
@@ -114487,6 +114649,30 @@ function useDocumentTranslationActivation() {
|
|
|
114487
114649
|
};
|
|
114488
114650
|
}
|
|
114489
114651
|
//#endregion
|
|
114652
|
+
//#region src/lib/resolve-document-translation-config.ts
|
|
114653
|
+
function resolveDocumentTranslationConfig(translationConfig, globalSettings) {
|
|
114654
|
+
if (!translationConfig) return void 0;
|
|
114655
|
+
const local = translationConfig.engines?.local ?? {};
|
|
114656
|
+
const openai = translationConfig.engines?.openai ?? {};
|
|
114657
|
+
const resolvedLocalModel = local.model ?? globalSettings?.translationEngines.local.model;
|
|
114658
|
+
const resolvedLocalSelectedGroupId = local.selectedGroupId ?? globalSettings?.translationEngines.local.selectedGroupId;
|
|
114659
|
+
const resolvedOpenAIModel = openai.model ?? globalSettings?.translationEngines.openai.model;
|
|
114660
|
+
return {
|
|
114661
|
+
...translationConfig,
|
|
114662
|
+
engines: {
|
|
114663
|
+
local: {
|
|
114664
|
+
...local,
|
|
114665
|
+
...resolvedLocalModel ? { model: resolvedLocalModel } : {},
|
|
114666
|
+
...resolvedLocalSelectedGroupId ? { selectedGroupId: resolvedLocalSelectedGroupId } : {}
|
|
114667
|
+
},
|
|
114668
|
+
openai: {
|
|
114669
|
+
...openai,
|
|
114670
|
+
...resolvedOpenAIModel ? { model: resolvedOpenAIModel } : {}
|
|
114671
|
+
}
|
|
114672
|
+
}
|
|
114673
|
+
};
|
|
114674
|
+
}
|
|
114675
|
+
//#endregion
|
|
114490
114676
|
//#region ../browser-translator/dist/index.mjs
|
|
114491
114677
|
async function scanBrowserTranslationSupportTable(options) {
|
|
114492
114678
|
const translator = (options.win ?? window).Translator;
|
|
@@ -131170,6 +131356,55 @@ function createProjectionContext(lookup, annotations, projections) {
|
|
|
131170
131356
|
};
|
|
131171
131357
|
}
|
|
131172
131358
|
//#endregion
|
|
131359
|
+
//#region ../core/src/translation-language-pair.ts
|
|
131360
|
+
var OPUS_MT_DIRECTION_PATTERN = /^opus-mt-([a-z]{2,3})-([a-z]{2,3})$/i;
|
|
131361
|
+
function inferLocalDirectionalModelLanguagePair(model) {
|
|
131362
|
+
const modelName = model?.trim().split("/").pop();
|
|
131363
|
+
if (!modelName) return null;
|
|
131364
|
+
const match = OPUS_MT_DIRECTION_PATTERN.exec(modelName);
|
|
131365
|
+
if (!match) return null;
|
|
131366
|
+
const [, sourceLanguage, targetLanguage] = match;
|
|
131367
|
+
if (!sourceLanguage || !targetLanguage) return null;
|
|
131368
|
+
return {
|
|
131369
|
+
sourceLanguage: normalizeLanguageCode(sourceLanguage),
|
|
131370
|
+
targetLanguage: normalizeLanguageCode(targetLanguage)
|
|
131371
|
+
};
|
|
131372
|
+
}
|
|
131373
|
+
function checkLocalDirectionalModelLanguagePair(input) {
|
|
131374
|
+
const expected = inferLocalDirectionalModelLanguagePair(input.model);
|
|
131375
|
+
if (!expected) return { supported: true };
|
|
131376
|
+
if (!areCompatibleLanguageTags(expected.targetLanguage, input.targetLanguage)) return {
|
|
131377
|
+
supported: false,
|
|
131378
|
+
expected,
|
|
131379
|
+
message: `Selected local model supports ${formatLanguagePair(expected)}, but document translation is configured for target ${input.targetLanguage}.`
|
|
131380
|
+
};
|
|
131381
|
+
if (input.sourceLanguage && !areCompatibleLanguageTags(expected.sourceLanguage, input.sourceLanguage)) return {
|
|
131382
|
+
supported: false,
|
|
131383
|
+
expected,
|
|
131384
|
+
message: `Selected local model supports ${formatLanguagePair(expected)}, but document segment was detected as ${input.sourceLanguage} -> ${input.targetLanguage}.`
|
|
131385
|
+
};
|
|
131386
|
+
return {
|
|
131387
|
+
supported: true,
|
|
131388
|
+
expected
|
|
131389
|
+
};
|
|
131390
|
+
}
|
|
131391
|
+
function areCompatibleLanguageTags(expected, actual) {
|
|
131392
|
+
const expectedNormalized = normalizeLanguageTag$1(expected);
|
|
131393
|
+
const actualNormalized = normalizeLanguageTag$1(actual);
|
|
131394
|
+
if (!expectedNormalized || !actualNormalized) return false;
|
|
131395
|
+
if (expectedNormalized === actualNormalized) return true;
|
|
131396
|
+
return expectedNormalized.split("-")[0] === actualNormalized.split("-")[0];
|
|
131397
|
+
}
|
|
131398
|
+
function normalizeLanguageCode(language) {
|
|
131399
|
+
return language.trim().toLowerCase().replace(/_/g, "-");
|
|
131400
|
+
}
|
|
131401
|
+
function normalizeLanguageTag$1(language) {
|
|
131402
|
+
return normalizeLanguageCode(language);
|
|
131403
|
+
}
|
|
131404
|
+
function formatLanguagePair(pair) {
|
|
131405
|
+
return `${pair.sourceLanguage} -> ${pair.targetLanguage}`;
|
|
131406
|
+
}
|
|
131407
|
+
//#endregion
|
|
131173
131408
|
//#region ../../node_modules/.pnpm/remark-gfm@4.0.1/node_modules/remark-gfm/lib/index.js
|
|
131174
131409
|
/**
|
|
131175
131410
|
* @import {Root} from 'mdast'
|
|
@@ -135698,6 +135933,43 @@ function escapeAttributeValue(value) {
|
|
|
135698
135933
|
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
135699
135934
|
}
|
|
135700
135935
|
//#endregion
|
|
135936
|
+
//#region src/lib/translation-adaptive-concurrency-log.ts
|
|
135937
|
+
var GLOBAL_STORAGE_KEY = "__OPENSPECUI_TRANSLATION_ADAPTIVE_CONCURRENCY_LOGS__";
|
|
135938
|
+
var MAX_LOG_AGE_MS = 1800 * 1e3;
|
|
135939
|
+
var MAX_LOG_ENTRIES = 256;
|
|
135940
|
+
var DEFAULT_SAMPLE_SIZE = 8;
|
|
135941
|
+
function createTranslationAdaptiveConcurrencyScopeKey(input) {
|
|
135942
|
+
return JSON.stringify({
|
|
135943
|
+
engineId: input.engineId,
|
|
135944
|
+
engineVersion: input.engineVersion ?? null,
|
|
135945
|
+
model: input.model ?? null,
|
|
135946
|
+
selectedGroupId: input.selectedGroupId ?? null,
|
|
135947
|
+
sourceLanguage: input.sourceLanguage.trim().toLowerCase(),
|
|
135948
|
+
targetLanguage: input.targetLanguage.trim().toLowerCase(),
|
|
135949
|
+
translatorContractVersion: input.translatorContractVersion
|
|
135950
|
+
});
|
|
135951
|
+
}
|
|
135952
|
+
function appendTranslationAdaptiveConcurrencyLog(entry) {
|
|
135953
|
+
const store = getTranslationAdaptiveConcurrencyLogStore();
|
|
135954
|
+
store.entries.push(entry);
|
|
135955
|
+
cleanupTranslationAdaptiveConcurrencyLogs(store);
|
|
135956
|
+
}
|
|
135957
|
+
function readRecentTranslationAdaptiveConcurrencyLogs(input = {}) {
|
|
135958
|
+
const store = getTranslationAdaptiveConcurrencyLogStore();
|
|
135959
|
+
cleanupTranslationAdaptiveConcurrencyLogs(store);
|
|
135960
|
+
return (input.scopeKey ? store.entries.filter((entry) => entry.scopeKey === input.scopeKey) : store.entries).slice(-Math.max(1, input.limit ?? DEFAULT_SAMPLE_SIZE));
|
|
135961
|
+
}
|
|
135962
|
+
function getTranslationAdaptiveConcurrencyLogStore() {
|
|
135963
|
+
const globalScope = globalThis;
|
|
135964
|
+
if (!globalScope[GLOBAL_STORAGE_KEY]) globalScope[GLOBAL_STORAGE_KEY] = { entries: [] };
|
|
135965
|
+
return globalScope[GLOBAL_STORAGE_KEY];
|
|
135966
|
+
}
|
|
135967
|
+
function cleanupTranslationAdaptiveConcurrencyLogs(store) {
|
|
135968
|
+
const cutoff = Date.now() - MAX_LOG_AGE_MS;
|
|
135969
|
+
if (store.entries.length === 0) return;
|
|
135970
|
+
store.entries = store.entries.filter((entry) => entry.recordedAt >= cutoff).slice(-MAX_LOG_ENTRIES);
|
|
135971
|
+
}
|
|
135972
|
+
//#endregion
|
|
135701
135973
|
//#region ../search/src/engine.ts
|
|
135702
135974
|
function normalizeText(input) {
|
|
135703
135975
|
return input.toLowerCase().replace(/\s+/g, " ").trim();
|
|
@@ -136157,6 +136429,7 @@ var DOCUMENT_LANGUAGE_CONFIDENCE_THRESHOLD = .45;
|
|
|
136157
136429
|
var SEGMENT_LANGUAGE_CONFIDENCE_THRESHOLD = .62;
|
|
136158
136430
|
var TRANSLATION_DISPLAY_POLICY_VERSION = 2;
|
|
136159
136431
|
var BROWSER_SOURCE_LANGUAGE_ORDER = new Map(SUPPORTED_TRANSLATION_LANGUAGES.map((language, index) => [language.code, index]));
|
|
136432
|
+
var SUPPORTED_TRANSLATION_LANGUAGE_CODES = new Set(SUPPORTED_TRANSLATION_LANGUAGES.map((language) => language.code));
|
|
136160
136433
|
function isBrowserTranslationSupported() {
|
|
136161
136434
|
return typeof window !== "undefined" && !!window.Translator;
|
|
136162
136435
|
}
|
|
@@ -136374,14 +136647,20 @@ function mergeBrowserSupportRows(rows, row) {
|
|
|
136374
136647
|
}
|
|
136375
136648
|
function sortBrowserSupportRows(rows) {
|
|
136376
136649
|
return [...rows].sort((left, right) => {
|
|
136377
|
-
const leftOrder =
|
|
136378
|
-
const rightOrder =
|
|
136650
|
+
const leftOrder = getBrowserSourceLanguageOrder(left.sourceLanguage) ?? Number.MAX_SAFE_INTEGER;
|
|
136651
|
+
const rightOrder = getBrowserSourceLanguageOrder(right.sourceLanguage) ?? Number.MAX_SAFE_INTEGER;
|
|
136379
136652
|
if (leftOrder !== rightOrder) return leftOrder - rightOrder;
|
|
136380
136653
|
const targetDelta = left.targetLanguage.localeCompare(right.targetLanguage);
|
|
136381
136654
|
if (targetDelta !== 0) return targetDelta;
|
|
136382
136655
|
return left.sourceLanguage.localeCompare(right.sourceLanguage);
|
|
136383
136656
|
});
|
|
136384
136657
|
}
|
|
136658
|
+
function getBrowserSourceLanguageOrder(sourceLanguage) {
|
|
136659
|
+
return isSupportedTranslationLanguageCode(sourceLanguage) ? BROWSER_SOURCE_LANGUAGE_ORDER.get(sourceLanguage) : void 0;
|
|
136660
|
+
}
|
|
136661
|
+
function isSupportedTranslationLanguageCode(language) {
|
|
136662
|
+
return SUPPORTED_TRANSLATION_LANGUAGE_CODES.has(language);
|
|
136663
|
+
}
|
|
136385
136664
|
async function translateMarkdownDocumentProgressively(args, onPatch) {
|
|
136386
136665
|
const segments = extractTranslatableSegments(args.markdown);
|
|
136387
136666
|
if (segments.length === 0) return {
|
|
@@ -136391,9 +136670,9 @@ async function translateMarkdownDocumentProgressively(args, onPatch) {
|
|
|
136391
136670
|
};
|
|
136392
136671
|
const engine = args.engine ?? createBrowserTranslationExecution();
|
|
136393
136672
|
const languageDetection = await createSourceLanguageDetectionSession(args.markdown, args.signal);
|
|
136394
|
-
const
|
|
136673
|
+
const translatedSegments = [...segments];
|
|
136674
|
+
const pendingJobsBySourceLanguage = /* @__PURE__ */ new Map();
|
|
136395
136675
|
try {
|
|
136396
|
-
const translatedSegments = [];
|
|
136397
136676
|
for (const [segmentIndex, segment] of segments.entries()) {
|
|
136398
136677
|
throwIfAborted(args.signal);
|
|
136399
136678
|
const sourceLanguage = await languageDetection.detectSegmentLanguage(segment.translatorInput, args.signal);
|
|
@@ -136407,7 +136686,7 @@ async function translateMarkdownDocumentProgressively(args, onPatch) {
|
|
|
136407
136686
|
targetLanguage: args.targetLanguage,
|
|
136408
136687
|
status: "translated"
|
|
136409
136688
|
};
|
|
136410
|
-
translatedSegments
|
|
136689
|
+
translatedSegments[segmentIndex] = translatedSegment;
|
|
136411
136690
|
onPatch({
|
|
136412
136691
|
segmentIndex,
|
|
136413
136692
|
segment: translatedSegment
|
|
@@ -136420,33 +136699,27 @@ async function translateMarkdownDocumentProgressively(args, onPatch) {
|
|
|
136420
136699
|
targetLanguage: args.targetLanguage
|
|
136421
136700
|
}) : null;
|
|
136422
136701
|
if (cachedSegment) {
|
|
136423
|
-
translatedSegments
|
|
136702
|
+
translatedSegments[segmentIndex] = cachedSegment;
|
|
136424
136703
|
onPatch({
|
|
136425
136704
|
segmentIndex,
|
|
136426
136705
|
segment: cachedSegment
|
|
136427
136706
|
});
|
|
136428
136707
|
continue;
|
|
136429
136708
|
}
|
|
136430
|
-
const
|
|
136431
|
-
|
|
136432
|
-
|
|
136433
|
-
restore: (output) => output
|
|
136434
|
-
} : protectTranslatorInput(segment.translatorInput);
|
|
136435
|
-
const target = await raceAbort(readSingleBatchOutput(translator.batchTranslate([protectedInput.text], { signal: args.signal })), args.signal);
|
|
136436
|
-
const restoredTarget = segment.placeholderProtocol ? restoreTranslatedPlaceholderFragment(target, segment.placeholderProtocol) : { target: protectedInput.restore(target).trim() };
|
|
136437
|
-
const translatedSegment = {
|
|
136438
|
-
...segment,
|
|
136439
|
-
...restoredTarget,
|
|
136709
|
+
const pendingJob = {
|
|
136710
|
+
segmentIndex,
|
|
136711
|
+
segment,
|
|
136440
136712
|
sourceLanguage,
|
|
136441
|
-
|
|
136442
|
-
|
|
136713
|
+
cacheKey,
|
|
136714
|
+
protectedInput: segment.placeholderProtocol ? {
|
|
136715
|
+
text: segment.translatorInput,
|
|
136716
|
+
restore: (output) => output
|
|
136717
|
+
} : protectTranslatorInput(segment.translatorInput),
|
|
136718
|
+
estimatedTokens: estimateTranslationTokens(segment.translatorInput)
|
|
136443
136719
|
};
|
|
136444
|
-
|
|
136445
|
-
|
|
136446
|
-
|
|
136447
|
-
segmentIndex,
|
|
136448
|
-
segment: translatedSegment
|
|
136449
|
-
});
|
|
136720
|
+
const pendingJobs = pendingJobsBySourceLanguage.get(sourceLanguage) ?? [];
|
|
136721
|
+
pendingJobs.push(pendingJob);
|
|
136722
|
+
pendingJobsBySourceLanguage.set(sourceLanguage, pendingJobs);
|
|
136450
136723
|
} catch (error) {
|
|
136451
136724
|
if (args.signal.aborted) throw error;
|
|
136452
136725
|
const failedSegment = {
|
|
@@ -136456,13 +136729,23 @@ async function translateMarkdownDocumentProgressively(args, onPatch) {
|
|
|
136456
136729
|
status: "error",
|
|
136457
136730
|
error: getErrorMessage(error)
|
|
136458
136731
|
};
|
|
136459
|
-
translatedSegments
|
|
136732
|
+
translatedSegments[segmentIndex] = failedSegment;
|
|
136460
136733
|
onPatch({
|
|
136461
136734
|
segmentIndex,
|
|
136462
136735
|
segment: failedSegment
|
|
136463
136736
|
});
|
|
136464
136737
|
}
|
|
136465
136738
|
}
|
|
136739
|
+
await Promise.all([...pendingJobsBySourceLanguage.entries()].map(([sourceLanguage, jobs]) => translatePendingJobsBySourceLanguage({
|
|
136740
|
+
engine,
|
|
136741
|
+
sourceLanguage,
|
|
136742
|
+
targetLanguage: args.targetLanguage,
|
|
136743
|
+
signal: args.signal,
|
|
136744
|
+
cache: args.cache,
|
|
136745
|
+
jobs,
|
|
136746
|
+
translatedSegments,
|
|
136747
|
+
onPatch
|
|
136748
|
+
})));
|
|
136466
136749
|
return {
|
|
136467
136750
|
segments: translatedSegments,
|
|
136468
136751
|
displayMode: args.displayMode,
|
|
@@ -136470,24 +136753,247 @@ async function translateMarkdownDocumentProgressively(args, onPatch) {
|
|
|
136470
136753
|
targetLanguage: args.targetLanguage
|
|
136471
136754
|
};
|
|
136472
136755
|
} finally {
|
|
136473
|
-
translatorBySourceLanguage.forEach((translator) => translator.destroy?.());
|
|
136474
136756
|
languageDetection.destroy();
|
|
136475
136757
|
}
|
|
136476
136758
|
}
|
|
136477
|
-
async function
|
|
136478
|
-
const
|
|
136479
|
-
|
|
136480
|
-
|
|
136481
|
-
|
|
136482
|
-
|
|
136483
|
-
|
|
136759
|
+
async function translatePendingJobsBySourceLanguage(input) {
|
|
136760
|
+
const markJobsError = (jobs, message) => {
|
|
136761
|
+
for (const job of jobs) {
|
|
136762
|
+
const failedSegment = {
|
|
136763
|
+
...job.segment,
|
|
136764
|
+
sourceLanguage: job.sourceLanguage,
|
|
136765
|
+
targetLanguage: input.targetLanguage,
|
|
136766
|
+
status: "error",
|
|
136767
|
+
error: message
|
|
136768
|
+
};
|
|
136769
|
+
input.translatedSegments[job.segmentIndex] = failedSegment;
|
|
136770
|
+
input.onPatch({
|
|
136771
|
+
segmentIndex: job.segmentIndex,
|
|
136772
|
+
segment: failedSegment
|
|
136773
|
+
});
|
|
136774
|
+
}
|
|
136775
|
+
};
|
|
136776
|
+
const unsupportedLanguagePairMessage = getUnsupportedEngineLanguagePairMessage({
|
|
136777
|
+
engine: input.engine,
|
|
136778
|
+
sourceLanguage: input.sourceLanguage,
|
|
136779
|
+
targetLanguage: input.targetLanguage
|
|
136484
136780
|
});
|
|
136485
|
-
|
|
136486
|
-
|
|
136781
|
+
if (unsupportedLanguagePairMessage) {
|
|
136782
|
+
markJobsError(input.jobs, unsupportedLanguagePairMessage);
|
|
136783
|
+
return;
|
|
136784
|
+
}
|
|
136785
|
+
const batches = packTranslationJobs(input.jobs);
|
|
136786
|
+
if (batches.length === 0) return;
|
|
136787
|
+
const maxConcurrency = Math.min(6, batches.length);
|
|
136788
|
+
const scopeKey = createTranslationAdaptiveConcurrencyScopeKey({
|
|
136789
|
+
engineId: input.engine.cacheIdentity.engineId,
|
|
136790
|
+
engineVersion: input.engine.cacheIdentity.engineVersion,
|
|
136791
|
+
model: input.engine.cacheIdentity.model,
|
|
136792
|
+
selectedGroupId: input.engine.cacheIdentity.selectedGroupId,
|
|
136793
|
+
sourceLanguage: input.sourceLanguage,
|
|
136794
|
+
targetLanguage: input.targetLanguage,
|
|
136795
|
+
translatorContractVersion: input.engine.cacheIdentity.translatorContractVersion
|
|
136796
|
+
});
|
|
136797
|
+
let desiredConcurrency = 1;
|
|
136798
|
+
let nextBatchIndex = 0;
|
|
136799
|
+
let activeWorkers = 0;
|
|
136800
|
+
let completedBatches = 0;
|
|
136801
|
+
const workerPromises = /* @__PURE__ */ new Set();
|
|
136802
|
+
const startWorkersToDesired = () => {
|
|
136803
|
+
while (activeWorkers < desiredConcurrency && nextBatchIndex < batches.length && !input.signal.aborted) startWorker();
|
|
136804
|
+
};
|
|
136805
|
+
const maybeGrowConcurrency = () => {
|
|
136806
|
+
if (desiredConcurrency >= maxConcurrency) return;
|
|
136807
|
+
const recentLogs = readRecentTranslationAdaptiveConcurrencyLogs({
|
|
136808
|
+
scopeKey,
|
|
136809
|
+
limit: Math.max(4, desiredConcurrency * 2)
|
|
136810
|
+
});
|
|
136811
|
+
if (desiredConcurrency === 1) {
|
|
136812
|
+
if (completedBatches >= 1 && batches.length > 1 && recentLogs.length > 0) {
|
|
136813
|
+
desiredConcurrency = 2;
|
|
136814
|
+
startWorkersToDesired();
|
|
136815
|
+
}
|
|
136816
|
+
return;
|
|
136817
|
+
}
|
|
136818
|
+
if (completedBatches < desiredConcurrency) return;
|
|
136819
|
+
if (recentLogs.length < desiredConcurrency * 2) return;
|
|
136820
|
+
const window = recentLogs.slice(-desiredConcurrency * 2);
|
|
136821
|
+
const split = Math.max(1, Math.floor(window.length / 2));
|
|
136822
|
+
const earlierThroughput = summarizeTranslationLogThroughput(window.slice(0, split));
|
|
136823
|
+
const laterThroughput = summarizeTranslationLogThroughput(window.slice(split));
|
|
136824
|
+
if (earlierThroughput > 0 && laterThroughput >= earlierThroughput * 1.08) {
|
|
136825
|
+
desiredConcurrency = Math.min(maxConcurrency, desiredConcurrency + 1);
|
|
136826
|
+
startWorkersToDesired();
|
|
136827
|
+
}
|
|
136828
|
+
};
|
|
136829
|
+
const applyBatchResult = async (batch, outputs) => {
|
|
136830
|
+
for (const [offset, job] of batch.jobs.entries()) {
|
|
136831
|
+
const target = outputs[offset] ?? "";
|
|
136832
|
+
const restoredTarget = job.segment.placeholderProtocol ? restoreTranslatedPlaceholderFragment(target, job.segment.placeholderProtocol) : { target: job.protectedInput.restore(target).trim() };
|
|
136833
|
+
const translatedSegment = {
|
|
136834
|
+
...job.segment,
|
|
136835
|
+
...restoredTarget,
|
|
136836
|
+
sourceLanguage: job.sourceLanguage,
|
|
136837
|
+
targetLanguage: input.targetLanguage,
|
|
136838
|
+
status: "translated"
|
|
136839
|
+
};
|
|
136840
|
+
input.translatedSegments[job.segmentIndex] = translatedSegment;
|
|
136841
|
+
if (job.cacheKey) writeCachedTranslationSegment(input.cache, job.cacheKey, translatedSegment);
|
|
136842
|
+
input.onPatch({
|
|
136843
|
+
segmentIndex: job.segmentIndex,
|
|
136844
|
+
segment: translatedSegment
|
|
136845
|
+
});
|
|
136846
|
+
}
|
|
136847
|
+
};
|
|
136848
|
+
const markBatchError = (batch, error) => {
|
|
136849
|
+
markJobsError(batch.jobs, getErrorMessage(error));
|
|
136850
|
+
};
|
|
136851
|
+
const startWorker = () => {
|
|
136852
|
+
if (input.signal.aborted || nextBatchIndex >= batches.length) return;
|
|
136853
|
+
activeWorkers += 1;
|
|
136854
|
+
let workerPromise;
|
|
136855
|
+
workerPromise = (async () => {
|
|
136856
|
+
let translator = null;
|
|
136857
|
+
try {
|
|
136858
|
+
translator = await input.engine.factory.create({
|
|
136859
|
+
sourceLanguage: input.sourceLanguage,
|
|
136860
|
+
targetLanguage: input.targetLanguage,
|
|
136861
|
+
signal: input.signal
|
|
136862
|
+
});
|
|
136863
|
+
while (!input.signal.aborted) {
|
|
136864
|
+
const batchIndex = nextBatchIndex;
|
|
136865
|
+
if (batchIndex >= batches.length) break;
|
|
136866
|
+
nextBatchIndex += 1;
|
|
136867
|
+
const batch = batches[batchIndex];
|
|
136868
|
+
const startedAt = getCurrentTimeMs();
|
|
136869
|
+
try {
|
|
136870
|
+
await applyBatchResult(batch, await collectBatchTranslationOutputs(translator.batchTranslate(batch.jobs.map((job) => job.protectedInput.text), { signal: input.signal }), batch.jobs.length));
|
|
136871
|
+
completedBatches += 1;
|
|
136872
|
+
const elapsedMs = Math.max(1, getCurrentTimeMs() - startedAt);
|
|
136873
|
+
appendTranslationAdaptiveConcurrencyLog({
|
|
136874
|
+
scopeKey,
|
|
136875
|
+
recordedAt: Date.now(),
|
|
136876
|
+
engineId: input.engine.cacheIdentity.engineId,
|
|
136877
|
+
engineVersion: input.engine.cacheIdentity.engineVersion,
|
|
136878
|
+
model: input.engine.cacheIdentity.model,
|
|
136879
|
+
selectedGroupId: input.engine.cacheIdentity.selectedGroupId,
|
|
136880
|
+
sourceLanguage: input.sourceLanguage,
|
|
136881
|
+
targetLanguage: input.targetLanguage,
|
|
136882
|
+
batchIndex,
|
|
136883
|
+
batchSize: batch.jobs.length,
|
|
136884
|
+
estimatedTokens: batch.estimatedTokens,
|
|
136885
|
+
elapsedMs,
|
|
136886
|
+
throughputTokensPerMs: batch.estimatedTokens / elapsedMs,
|
|
136887
|
+
desiredConcurrency,
|
|
136888
|
+
activeWorkers,
|
|
136889
|
+
maxConcurrency
|
|
136890
|
+
});
|
|
136891
|
+
maybeGrowConcurrency();
|
|
136892
|
+
} catch (error) {
|
|
136893
|
+
if (input.signal.aborted) throw error;
|
|
136894
|
+
markBatchError(batch, error);
|
|
136895
|
+
}
|
|
136896
|
+
}
|
|
136897
|
+
} finally {
|
|
136898
|
+
translator?.destroy?.();
|
|
136899
|
+
}
|
|
136900
|
+
})().finally(() => {
|
|
136901
|
+
activeWorkers -= 1;
|
|
136902
|
+
workerPromises.delete(workerPromise);
|
|
136903
|
+
startWorkersToDesired();
|
|
136904
|
+
});
|
|
136905
|
+
workerPromises.add(workerPromise);
|
|
136906
|
+
};
|
|
136907
|
+
startWorkersToDesired();
|
|
136908
|
+
while (workerPromises.size > 0) await Promise.race(workerPromises);
|
|
136909
|
+
}
|
|
136910
|
+
function getUnsupportedEngineLanguagePairMessage(input) {
|
|
136911
|
+
if (input.engine.cacheIdentity.engineId !== "local") return null;
|
|
136912
|
+
const directionCheck = checkLocalDirectionalModelLanguagePair({
|
|
136913
|
+
model: input.engine.cacheIdentity.model,
|
|
136914
|
+
sourceLanguage: input.sourceLanguage,
|
|
136915
|
+
targetLanguage: input.targetLanguage
|
|
136916
|
+
});
|
|
136917
|
+
if (directionCheck.supported) return null;
|
|
136918
|
+
return directionCheck.message ?? "Selected local model does not support the detected translation direction.";
|
|
136919
|
+
}
|
|
136920
|
+
function summarizeTranslationLogThroughput(logs) {
|
|
136921
|
+
if (logs.length === 0) return 0;
|
|
136922
|
+
const totalTokens = logs.reduce((total, log) => total + log.estimatedTokens, 0);
|
|
136923
|
+
const totalElapsedMs = logs.reduce((total, log) => total + log.elapsedMs, 0);
|
|
136924
|
+
if (totalTokens <= 0 || totalElapsedMs <= 0) return 0;
|
|
136925
|
+
return totalTokens / totalElapsedMs;
|
|
136926
|
+
}
|
|
136927
|
+
function packTranslationJobs(jobs) {
|
|
136928
|
+
if (jobs.length === 0) return [];
|
|
136929
|
+
const averageTokens = jobs.reduce((total, job) => total + job.estimatedTokens, 0) / Math.max(1, jobs.length);
|
|
136930
|
+
const targetTokens = Math.max(1, Math.round(averageTokens * 6));
|
|
136931
|
+
const batches = [];
|
|
136932
|
+
let currentJobs = [];
|
|
136933
|
+
let currentTokens = 0;
|
|
136934
|
+
const flush = () => {
|
|
136935
|
+
if (currentJobs.length === 0) return;
|
|
136936
|
+
batches.push({
|
|
136937
|
+
jobs: currentJobs,
|
|
136938
|
+
estimatedTokens: currentTokens
|
|
136939
|
+
});
|
|
136940
|
+
currentJobs = [];
|
|
136941
|
+
currentTokens = 0;
|
|
136942
|
+
};
|
|
136943
|
+
for (const job of jobs) {
|
|
136944
|
+
if (currentJobs.length === 0) {
|
|
136945
|
+
currentJobs = [job];
|
|
136946
|
+
currentTokens = job.estimatedTokens;
|
|
136947
|
+
continue;
|
|
136948
|
+
}
|
|
136949
|
+
const nextTokens = currentTokens + job.estimatedTokens;
|
|
136950
|
+
if (nextTokens <= targetTokens) {
|
|
136951
|
+
currentJobs.push(job);
|
|
136952
|
+
currentTokens = nextTokens;
|
|
136953
|
+
continue;
|
|
136954
|
+
}
|
|
136955
|
+
const withoutDelta = Math.abs(currentTokens - targetTokens);
|
|
136956
|
+
if (Math.abs(nextTokens - targetTokens) <= withoutDelta) {
|
|
136957
|
+
currentJobs.push(job);
|
|
136958
|
+
currentTokens = nextTokens;
|
|
136959
|
+
flush();
|
|
136960
|
+
continue;
|
|
136961
|
+
}
|
|
136962
|
+
flush();
|
|
136963
|
+
currentJobs = [job];
|
|
136964
|
+
currentTokens = job.estimatedTokens;
|
|
136965
|
+
}
|
|
136966
|
+
flush();
|
|
136967
|
+
return batches;
|
|
136968
|
+
}
|
|
136969
|
+
async function collectBatchTranslationOutputs(stream, expectedCount) {
|
|
136970
|
+
const outputs = /* @__PURE__ */ new Map();
|
|
136971
|
+
for await (const item of stream) {
|
|
136972
|
+
if (item.index < 0 || item.index >= expectedCount) throw new Error(`Translator yielded output for unexpected index ${item.index}.`);
|
|
136973
|
+
if (!outputs.has(item.index)) outputs.set(item.index, item.output);
|
|
136974
|
+
}
|
|
136975
|
+
if (outputs.size !== expectedCount) throw new Error(`Translator returned ${outputs.size} outputs for ${expectedCount} inputs.`);
|
|
136976
|
+
return Array.from({ length: expectedCount }, (_, index) => outputs.get(index) ?? "");
|
|
136977
|
+
}
|
|
136978
|
+
function estimateTranslationTokens(input) {
|
|
136979
|
+
const trimmed = input.trim();
|
|
136980
|
+
if (!trimmed) return 1;
|
|
136981
|
+
const segmenter = getTokenSegmenter();
|
|
136982
|
+
if (!segmenter) return Math.max(1, trimmed.split(/\s+/).filter(Boolean).length);
|
|
136983
|
+
let count = 0;
|
|
136984
|
+
for (const segment of segmenter.segment(trimmed)) if (segment.isWordLike ?? segment.segment.trim().length > 0) count += 1;
|
|
136985
|
+
return Math.max(1, count);
|
|
136487
136986
|
}
|
|
136488
|
-
|
|
136489
|
-
|
|
136490
|
-
|
|
136987
|
+
function getTokenSegmenter() {
|
|
136988
|
+
if (typeof Intl === "undefined" || typeof Intl.Segmenter !== "function") return null;
|
|
136989
|
+
try {
|
|
136990
|
+
return new Intl.Segmenter(void 0, { granularity: "word" });
|
|
136991
|
+
} catch {
|
|
136992
|
+
return null;
|
|
136993
|
+
}
|
|
136994
|
+
}
|
|
136995
|
+
function getCurrentTimeMs() {
|
|
136996
|
+
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
136491
136997
|
}
|
|
136492
136998
|
async function createSourceLanguageDetectionSession(markdown, signal) {
|
|
136493
136999
|
const detectorFactory = window.LanguageDetector;
|
|
@@ -136963,87 +137469,10 @@ function getErrorMessage(error) {
|
|
|
136963
137469
|
return error instanceof Error ? error.message : "Unknown translation error.";
|
|
136964
137470
|
}
|
|
136965
137471
|
//#endregion
|
|
136966
|
-
//#region src/lib/translate-service.ts
|
|
136967
|
-
function createTranslationEngineExecution(config) {
|
|
136968
|
-
if (config.engineId === "browser" || isStaticMode()) return createBrowserTranslationExecution();
|
|
136969
|
-
const model = config.engineId === "openai" ? config.engines.openai.model : config.engines.local.model;
|
|
136970
|
-
return {
|
|
136971
|
-
factory: new TrpcTranslatorFactory(config.engineId, model, config.engineId === "local" ? config.engines.local.selectedGroupId : void 0),
|
|
136972
|
-
cacheIdentity: {
|
|
136973
|
-
engineId: config.engineId,
|
|
136974
|
-
model,
|
|
136975
|
-
selectedGroupId: config.engineId === "local" ? config.engines.local.selectedGroupId : void 0,
|
|
136976
|
-
translatorContractVersion: 2
|
|
136977
|
-
}
|
|
136978
|
-
};
|
|
136979
|
-
}
|
|
136980
|
-
var TrpcTranslatorFactory = class {
|
|
136981
|
-
constructor(engineId, model, selectedGroupId) {
|
|
136982
|
-
this.engineId = engineId;
|
|
136983
|
-
this.model = model;
|
|
136984
|
-
this.selectedGroupId = selectedGroupId;
|
|
136985
|
-
}
|
|
136986
|
-
async create(options) {
|
|
136987
|
-
return new TrpcTranslator({
|
|
136988
|
-
engineId: this.engineId,
|
|
136989
|
-
sourceLanguage: options.sourceLanguage,
|
|
136990
|
-
targetLanguage: options.targetLanguage,
|
|
136991
|
-
model: options.model ?? this.model,
|
|
136992
|
-
selectedGroupId: this.engineId === "local" ? this.selectedGroupId : void 0
|
|
136993
|
-
});
|
|
136994
|
-
}
|
|
136995
|
-
};
|
|
136996
|
-
var TrpcTranslator = class {
|
|
136997
|
-
constructor(options) {
|
|
136998
|
-
this.options = options;
|
|
136999
|
-
}
|
|
137000
|
-
async *batchTranslate(inputs, options) {
|
|
137001
|
-
if (options?.signal?.aborted) throw new DOMException("Translation cancelled.", "AbortError");
|
|
137002
|
-
const queue = [];
|
|
137003
|
-
let completed = false;
|
|
137004
|
-
let thrown = null;
|
|
137005
|
-
const subscription = trpcClient.translationEngines.batchTranslate.subscribe({
|
|
137006
|
-
engineId: this.options.engineId,
|
|
137007
|
-
sourceLanguage: this.options.sourceLanguage,
|
|
137008
|
-
targetLanguage: this.options.targetLanguage,
|
|
137009
|
-
model: this.options.model,
|
|
137010
|
-
selectedGroupId: this.options.selectedGroupId,
|
|
137011
|
-
inputs,
|
|
137012
|
-
instructions: options?.instructions,
|
|
137013
|
-
context: options?.context
|
|
137014
|
-
}, {
|
|
137015
|
-
onData(event) {
|
|
137016
|
-
queue.push(event);
|
|
137017
|
-
},
|
|
137018
|
-
onError(error) {
|
|
137019
|
-
thrown = error instanceof Error ? error : new Error(String(error));
|
|
137020
|
-
completed = true;
|
|
137021
|
-
},
|
|
137022
|
-
onComplete() {
|
|
137023
|
-
completed = true;
|
|
137024
|
-
}
|
|
137025
|
-
});
|
|
137026
|
-
try {
|
|
137027
|
-
while (!completed || queue.length > 0) {
|
|
137028
|
-
if (options?.signal?.aborted) throw new DOMException("Translation cancelled.", "AbortError");
|
|
137029
|
-
const item = queue.shift();
|
|
137030
|
-
if (item) {
|
|
137031
|
-
yield item;
|
|
137032
|
-
continue;
|
|
137033
|
-
}
|
|
137034
|
-
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
137035
|
-
}
|
|
137036
|
-
if (thrown) throw thrown;
|
|
137037
|
-
} finally {
|
|
137038
|
-
subscription.unsubscribe();
|
|
137039
|
-
}
|
|
137040
|
-
}
|
|
137041
|
-
};
|
|
137042
|
-
//#endregion
|
|
137043
137472
|
//#region ../core/src/local-download-profiles.ts
|
|
137044
137473
|
function selectLocalDownloadGroup(plan, selectedGroupId) {
|
|
137045
137474
|
if (!plan?.groups?.length) return null;
|
|
137046
|
-
return (selectedGroupId ? plan.groups.find((group) => group.id === selectedGroupId
|
|
137475
|
+
return (selectedGroupId ? plan.groups.find((group) => group.selectable && (group.id === selectedGroupId || group.baseGroupId === selectedGroupId)) : void 0) ?? plan.groups.find((group) => group.selected) ?? selectSmallestSelectableGroup(plan.groups);
|
|
137047
137476
|
}
|
|
137048
137477
|
function selectSmallestSelectableGroup(groups) {
|
|
137049
137478
|
return groups.filter((group) => group.selectable && group.estimatedTotalBytes !== void 0).sort((left, right) => (left.estimatedTotalBytes ?? 0) - (right.estimatedTotalBytes ?? 0))[0] ?? null;
|
|
@@ -137142,6 +137571,253 @@ function isLocalAssetReady(asset, selectedGroupId) {
|
|
|
137142
137571
|
return allRequiredFilesReady;
|
|
137143
137572
|
}
|
|
137144
137573
|
//#endregion
|
|
137574
|
+
//#region src/lib/translate-service.ts
|
|
137575
|
+
async function resolveTranslateServiceState(input) {
|
|
137576
|
+
const config = input.config;
|
|
137577
|
+
if (!config?.enabled || !input.hasSource) return emitTranslateServiceState(input.onUpdate, { status: projectTranslateServiceStatus({
|
|
137578
|
+
enabled: config?.enabled ?? false,
|
|
137579
|
+
hasSource: input.hasSource,
|
|
137580
|
+
engineId: config?.engineId ?? "browser"
|
|
137581
|
+
}) });
|
|
137582
|
+
if (config.engineId === "local") {
|
|
137583
|
+
const model = config.engines.local.model?.trim();
|
|
137584
|
+
if (!model) return emitTranslateServiceState(input.onUpdate, { status: projectTranslateServiceStatus({
|
|
137585
|
+
enabled: config.enabled,
|
|
137586
|
+
hasSource: input.hasSource,
|
|
137587
|
+
engineId: "local",
|
|
137588
|
+
localModel: model,
|
|
137589
|
+
localSelectedGroupId: config.engines.local.selectedGroupId
|
|
137590
|
+
}) });
|
|
137591
|
+
const directionCheck = checkLocalDirectionalModelLanguagePair({
|
|
137592
|
+
model,
|
|
137593
|
+
targetLanguage: config.targetLanguage
|
|
137594
|
+
});
|
|
137595
|
+
if (!directionCheck.supported) return emitTranslateServiceState(input.onUpdate, { status: {
|
|
137596
|
+
state: "unavailable",
|
|
137597
|
+
engineId: "local",
|
|
137598
|
+
message: directionCheck.message ?? "Selected local model does not support the configured target language."
|
|
137599
|
+
} });
|
|
137600
|
+
input.onUpdate?.(createTranslateServiceState({ status: projectTranslateServiceStatus({
|
|
137601
|
+
enabled: config.enabled,
|
|
137602
|
+
hasSource: input.hasSource,
|
|
137603
|
+
engineId: "local",
|
|
137604
|
+
localModel: model,
|
|
137605
|
+
localSelectedGroupId: config.engines.local.selectedGroupId,
|
|
137606
|
+
localAssetLoading: true
|
|
137607
|
+
}) }));
|
|
137608
|
+
try {
|
|
137609
|
+
const panelState = await trpcClient.localModels.panelState.query({
|
|
137610
|
+
modelId: model,
|
|
137611
|
+
selectedGroupId: config.engines.local.selectedGroupId
|
|
137612
|
+
});
|
|
137613
|
+
const selectedGroupId = panelState.selectedGroupId ?? config.engines.local.selectedGroupId;
|
|
137614
|
+
return createTranslateServiceState({ status: projectTranslateServiceStatus({
|
|
137615
|
+
enabled: config.enabled,
|
|
137616
|
+
hasSource: input.hasSource,
|
|
137617
|
+
engineId: "local",
|
|
137618
|
+
localModel: model,
|
|
137619
|
+
localSelectedGroupId: selectedGroupId,
|
|
137620
|
+
localAsset: panelState.asset
|
|
137621
|
+
}) });
|
|
137622
|
+
} catch (assetError) {
|
|
137623
|
+
return createTranslateServiceState({ status: {
|
|
137624
|
+
state: "unavailable",
|
|
137625
|
+
engineId: "local",
|
|
137626
|
+
message: assetError instanceof Error ? assetError.message : "Unable to check local model files."
|
|
137627
|
+
} });
|
|
137628
|
+
}
|
|
137629
|
+
}
|
|
137630
|
+
if (config.engineId === "openai") return emitTranslateServiceState(input.onUpdate, { status: projectTranslateServiceStatus({
|
|
137631
|
+
enabled: config.enabled,
|
|
137632
|
+
hasSource: input.hasSource,
|
|
137633
|
+
engineId: "openai"
|
|
137634
|
+
}) });
|
|
137635
|
+
const cachedTable = getBrowserSupportTableState(config.targetLanguage);
|
|
137636
|
+
if (cachedTable) return emitTranslateServiceState(input.onUpdate, {
|
|
137637
|
+
browserSupportTable: cachedTable,
|
|
137638
|
+
status: projectTranslateServiceStatus({
|
|
137639
|
+
enabled: config.enabled,
|
|
137640
|
+
hasSource: input.hasSource,
|
|
137641
|
+
engineId: "browser",
|
|
137642
|
+
browserSupportTable: cachedTable
|
|
137643
|
+
})
|
|
137644
|
+
});
|
|
137645
|
+
const checkingTable = {
|
|
137646
|
+
state: "checking",
|
|
137647
|
+
table: null,
|
|
137648
|
+
message: "Checking browser translation pairs…"
|
|
137649
|
+
};
|
|
137650
|
+
input.onUpdate?.(createTranslateServiceState({
|
|
137651
|
+
browserSupportTable: checkingTable,
|
|
137652
|
+
status: projectTranslateServiceStatus({
|
|
137653
|
+
enabled: config.enabled,
|
|
137654
|
+
hasSource: input.hasSource,
|
|
137655
|
+
engineId: "browser",
|
|
137656
|
+
browserSupportTable: checkingTable
|
|
137657
|
+
})
|
|
137658
|
+
}));
|
|
137659
|
+
try {
|
|
137660
|
+
const nextTable = await scanBrowserTranslationPairs(config.targetLanguage, {
|
|
137661
|
+
signal: input.signal ?? new AbortController().signal,
|
|
137662
|
+
onProgress: (progressState) => {
|
|
137663
|
+
input.onUpdate?.(createTranslateServiceState({
|
|
137664
|
+
browserSupportTable: progressState,
|
|
137665
|
+
status: projectTranslateServiceStatus({
|
|
137666
|
+
enabled: config.enabled,
|
|
137667
|
+
hasSource: input.hasSource,
|
|
137668
|
+
engineId: "browser",
|
|
137669
|
+
browserSupportTable: progressState
|
|
137670
|
+
})
|
|
137671
|
+
}));
|
|
137672
|
+
}
|
|
137673
|
+
});
|
|
137674
|
+
return createTranslateServiceState({
|
|
137675
|
+
browserSupportTable: nextTable,
|
|
137676
|
+
status: projectTranslateServiceStatus({
|
|
137677
|
+
enabled: config.enabled,
|
|
137678
|
+
hasSource: input.hasSource,
|
|
137679
|
+
engineId: "browser",
|
|
137680
|
+
browserSupportTable: nextTable
|
|
137681
|
+
})
|
|
137682
|
+
});
|
|
137683
|
+
} catch (probeError) {
|
|
137684
|
+
const nextCapability = {
|
|
137685
|
+
availability: "error",
|
|
137686
|
+
message: probeError instanceof Error ? probeError.message : "Unable to check translation support."
|
|
137687
|
+
};
|
|
137688
|
+
return createTranslateServiceState({
|
|
137689
|
+
capability: nextCapability,
|
|
137690
|
+
status: projectTranslateServiceStatus({
|
|
137691
|
+
enabled: config.enabled,
|
|
137692
|
+
hasSource: input.hasSource,
|
|
137693
|
+
engineId: "browser",
|
|
137694
|
+
browserCapability: nextCapability
|
|
137695
|
+
})
|
|
137696
|
+
});
|
|
137697
|
+
}
|
|
137698
|
+
}
|
|
137699
|
+
function prepareTranslateServiceRun(input) {
|
|
137700
|
+
if (input.config.engineId !== "browser") return createTranslateServiceState({ status: projectTranslateServiceStatus({
|
|
137701
|
+
enabled: input.config.enabled,
|
|
137702
|
+
hasSource: input.hasSource,
|
|
137703
|
+
engineId: input.config.engineId
|
|
137704
|
+
}) });
|
|
137705
|
+
const preferredRow = input.browserSupportTable?.table?.rows.find((row) => row.availability === "available") ?? input.browserSupportTable?.table?.rows.find((row) => row.availability === "downloading") ?? input.browserSupportTable?.table?.rows.find((row) => row.availability === "downloadable") ?? null;
|
|
137706
|
+
if (!preferredRow) return createTranslateServiceState({
|
|
137707
|
+
browserSupportTable: input.browserSupportTable,
|
|
137708
|
+
status: projectTranslateServiceStatus({
|
|
137709
|
+
enabled: input.config.enabled,
|
|
137710
|
+
hasSource: input.hasSource,
|
|
137711
|
+
engineId: "browser",
|
|
137712
|
+
browserSupportTable: input.browserSupportTable
|
|
137713
|
+
})
|
|
137714
|
+
});
|
|
137715
|
+
const nextCapability = {
|
|
137716
|
+
availability: preferredRow.availability,
|
|
137717
|
+
progress: preferredRow.progress,
|
|
137718
|
+
message: preferredRow.message
|
|
137719
|
+
};
|
|
137720
|
+
const nextTable = patchBrowserSupportTableRow(input.config.targetLanguage, preferredRow, { message: void 0 });
|
|
137721
|
+
return createTranslateServiceState({
|
|
137722
|
+
capability: nextCapability,
|
|
137723
|
+
browserSupportTable: nextTable,
|
|
137724
|
+
status: projectTranslateServiceStatus({
|
|
137725
|
+
enabled: input.config.enabled,
|
|
137726
|
+
hasSource: input.hasSource,
|
|
137727
|
+
engineId: "browser",
|
|
137728
|
+
browserSupportTable: nextTable,
|
|
137729
|
+
browserCapability: nextCapability
|
|
137730
|
+
})
|
|
137731
|
+
});
|
|
137732
|
+
}
|
|
137733
|
+
function createTranslationEngineExecution(config) {
|
|
137734
|
+
if (config.engineId === "browser" || isStaticMode()) return createBrowserTranslationExecution();
|
|
137735
|
+
const model = config.engineId === "openai" ? config.engines.openai.model : config.engines.local.model;
|
|
137736
|
+
return {
|
|
137737
|
+
factory: new TrpcTranslatorFactory(config.engineId, model, config.engineId === "local" ? config.engines.local.selectedGroupId : void 0),
|
|
137738
|
+
cacheIdentity: {
|
|
137739
|
+
engineId: config.engineId,
|
|
137740
|
+
model,
|
|
137741
|
+
selectedGroupId: config.engineId === "local" ? config.engines.local.selectedGroupId : void 0,
|
|
137742
|
+
translatorContractVersion: 2
|
|
137743
|
+
}
|
|
137744
|
+
};
|
|
137745
|
+
}
|
|
137746
|
+
var TrpcTranslatorFactory = class {
|
|
137747
|
+
constructor(engineId, model, selectedGroupId) {
|
|
137748
|
+
this.engineId = engineId;
|
|
137749
|
+
this.model = model;
|
|
137750
|
+
this.selectedGroupId = selectedGroupId;
|
|
137751
|
+
}
|
|
137752
|
+
async create(options) {
|
|
137753
|
+
return new TrpcTranslator({
|
|
137754
|
+
engineId: this.engineId,
|
|
137755
|
+
sourceLanguage: options.sourceLanguage,
|
|
137756
|
+
targetLanguage: options.targetLanguage,
|
|
137757
|
+
model: options.model ?? this.model,
|
|
137758
|
+
selectedGroupId: this.engineId === "local" ? this.selectedGroupId : void 0
|
|
137759
|
+
});
|
|
137760
|
+
}
|
|
137761
|
+
};
|
|
137762
|
+
var TrpcTranslator = class {
|
|
137763
|
+
constructor(options) {
|
|
137764
|
+
this.options = options;
|
|
137765
|
+
}
|
|
137766
|
+
async *batchTranslate(inputs, options) {
|
|
137767
|
+
if (options?.signal?.aborted) throw new DOMException("Translation cancelled.", "AbortError");
|
|
137768
|
+
const queue = [];
|
|
137769
|
+
let completed = false;
|
|
137770
|
+
let thrown = null;
|
|
137771
|
+
const subscription = trpcClient.translationEngines.batchTranslate.subscribe({
|
|
137772
|
+
engineId: this.options.engineId,
|
|
137773
|
+
sourceLanguage: this.options.sourceLanguage,
|
|
137774
|
+
targetLanguage: this.options.targetLanguage,
|
|
137775
|
+
model: this.options.model,
|
|
137776
|
+
selectedGroupId: this.options.selectedGroupId,
|
|
137777
|
+
inputs,
|
|
137778
|
+
instructions: options?.instructions,
|
|
137779
|
+
context: options?.context
|
|
137780
|
+
}, {
|
|
137781
|
+
onData(event) {
|
|
137782
|
+
queue.push(event);
|
|
137783
|
+
},
|
|
137784
|
+
onError(error) {
|
|
137785
|
+
thrown = error instanceof Error ? error : new Error(String(error));
|
|
137786
|
+
completed = true;
|
|
137787
|
+
},
|
|
137788
|
+
onComplete() {
|
|
137789
|
+
completed = true;
|
|
137790
|
+
}
|
|
137791
|
+
});
|
|
137792
|
+
try {
|
|
137793
|
+
while (!completed || queue.length > 0) {
|
|
137794
|
+
if (options?.signal?.aborted) throw new DOMException("Translation cancelled.", "AbortError");
|
|
137795
|
+
const item = queue.shift();
|
|
137796
|
+
if (item) {
|
|
137797
|
+
yield item;
|
|
137798
|
+
continue;
|
|
137799
|
+
}
|
|
137800
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
137801
|
+
}
|
|
137802
|
+
if (thrown) throw thrown;
|
|
137803
|
+
} finally {
|
|
137804
|
+
subscription.unsubscribe();
|
|
137805
|
+
}
|
|
137806
|
+
}
|
|
137807
|
+
};
|
|
137808
|
+
function createTranslateServiceState(input) {
|
|
137809
|
+
return {
|
|
137810
|
+
capability: input.capability ?? null,
|
|
137811
|
+
browserSupportTable: input.browserSupportTable ?? null,
|
|
137812
|
+
status: input.status
|
|
137813
|
+
};
|
|
137814
|
+
}
|
|
137815
|
+
function emitTranslateServiceState(onUpdate, input) {
|
|
137816
|
+
const state = createTranslateServiceState(input);
|
|
137817
|
+
onUpdate?.(state);
|
|
137818
|
+
return state;
|
|
137819
|
+
}
|
|
137820
|
+
//#endregion
|
|
137145
137821
|
//#region src/lib/use-document-translation.ts
|
|
137146
137822
|
function useDocumentTranslation(markdown, config) {
|
|
137147
137823
|
const [status, setStatus] = (0, import_react.useState)("source");
|
|
@@ -137154,9 +137830,11 @@ function useDocumentTranslation(markdown, config) {
|
|
|
137154
137830
|
const [error, setError] = (0, import_react.useState)(null);
|
|
137155
137831
|
const [result, setResult] = (0, import_react.useState)(null);
|
|
137156
137832
|
const abortRef = (0, import_react.useRef)(null);
|
|
137833
|
+
const generationRef = (0, import_react.useRef)(0);
|
|
137157
137834
|
const latestStartRef = (0, import_react.useRef)(null);
|
|
137158
137835
|
const { activation } = useDocumentTranslationActivation();
|
|
137159
137836
|
const cancel = (0, import_react.useCallback)(() => {
|
|
137837
|
+
generationRef.current += 1;
|
|
137160
137838
|
abortRef.current?.abort();
|
|
137161
137839
|
abortRef.current = null;
|
|
137162
137840
|
setStatus("source");
|
|
@@ -137164,6 +137842,7 @@ function useDocumentTranslation(markdown, config) {
|
|
|
137164
137842
|
setError(null);
|
|
137165
137843
|
}, []);
|
|
137166
137844
|
const reset = (0, import_react.useCallback)(() => {
|
|
137845
|
+
generationRef.current += 1;
|
|
137167
137846
|
abortRef.current?.abort();
|
|
137168
137847
|
abortRef.current = null;
|
|
137169
137848
|
setStatus("source");
|
|
@@ -137172,6 +137851,7 @@ function useDocumentTranslation(markdown, config) {
|
|
|
137172
137851
|
}, []);
|
|
137173
137852
|
(0, import_react.useEffect)(() => reset, [reset]);
|
|
137174
137853
|
(0, import_react.useEffect)(() => {
|
|
137854
|
+
generationRef.current += 1;
|
|
137175
137855
|
setCapability(null);
|
|
137176
137856
|
setBrowserSupportTable(null);
|
|
137177
137857
|
setResult(null);
|
|
@@ -137181,141 +137861,39 @@ function useDocumentTranslation(markdown, config) {
|
|
|
137181
137861
|
markdown,
|
|
137182
137862
|
config?.displayMode,
|
|
137183
137863
|
config?.enabled,
|
|
137864
|
+
config?.engineId,
|
|
137865
|
+
config?.engines.local.model,
|
|
137866
|
+
config?.engines.local.selectedGroupId,
|
|
137867
|
+
config?.engines.openai.model,
|
|
137184
137868
|
config?.targetLanguage
|
|
137185
137869
|
]);
|
|
137186
137870
|
(0, import_react.useEffect)(() => {
|
|
137187
137871
|
let disposed = false;
|
|
137188
|
-
if (!config?.enabled || markdown.length === 0) {
|
|
137189
|
-
setCapability(null);
|
|
137190
|
-
setBrowserSupportTable(null);
|
|
137191
|
-
setServiceStatus(projectTranslateServiceStatus({
|
|
137192
|
-
enabled: config?.enabled ?? false,
|
|
137193
|
-
hasSource: markdown.length > 0,
|
|
137194
|
-
engineId: config?.engineId ?? "browser"
|
|
137195
|
-
}));
|
|
137196
|
-
return () => {
|
|
137197
|
-
disposed = true;
|
|
137198
|
-
};
|
|
137199
|
-
}
|
|
137200
|
-
if (config.engineId === "local") {
|
|
137201
|
-
setCapability(null);
|
|
137202
|
-
setBrowserSupportTable(null);
|
|
137203
|
-
setServiceStatus(projectTranslateServiceStatus({
|
|
137204
|
-
enabled: config.enabled,
|
|
137205
|
-
hasSource: markdown.length > 0,
|
|
137206
|
-
engineId: "local",
|
|
137207
|
-
localModel: config.engines.local.model,
|
|
137208
|
-
localSelectedGroupId: config.engines.local.selectedGroupId,
|
|
137209
|
-
localAssetLoading: true
|
|
137210
|
-
}));
|
|
137211
|
-
const model = config.engines.local.model?.trim();
|
|
137212
|
-
if (!model) {
|
|
137213
|
-
setServiceStatus(projectTranslateServiceStatus({
|
|
137214
|
-
enabled: config.enabled,
|
|
137215
|
-
hasSource: markdown.length > 0,
|
|
137216
|
-
engineId: "local",
|
|
137217
|
-
localModel: model,
|
|
137218
|
-
localSelectedGroupId: config.engines.local.selectedGroupId
|
|
137219
|
-
}));
|
|
137220
|
-
return () => {
|
|
137221
|
-
disposed = true;
|
|
137222
|
-
};
|
|
137223
|
-
}
|
|
137224
|
-
trpcClient.localModels.state.query({
|
|
137225
|
-
modelId: model,
|
|
137226
|
-
selectedGroupId: config.engines.local.selectedGroupId
|
|
137227
|
-
}).then((localAsset) => {
|
|
137228
|
-
if (disposed) return;
|
|
137229
|
-
setServiceStatus(projectTranslateServiceStatus({
|
|
137230
|
-
enabled: config.enabled,
|
|
137231
|
-
hasSource: markdown.length > 0,
|
|
137232
|
-
engineId: "local",
|
|
137233
|
-
localModel: model,
|
|
137234
|
-
localSelectedGroupId: config.engines.local.selectedGroupId,
|
|
137235
|
-
localAsset
|
|
137236
|
-
}));
|
|
137237
|
-
}).catch((assetError) => {
|
|
137238
|
-
if (disposed) return;
|
|
137239
|
-
setServiceStatus({
|
|
137240
|
-
state: "unavailable",
|
|
137241
|
-
engineId: "local",
|
|
137242
|
-
message: assetError instanceof Error ? assetError.message : "Unable to check local model files."
|
|
137243
|
-
});
|
|
137244
|
-
});
|
|
137245
|
-
return () => {
|
|
137246
|
-
disposed = true;
|
|
137247
|
-
};
|
|
137248
|
-
}
|
|
137249
|
-
if (config.engineId === "openai") {
|
|
137250
|
-
setCapability(null);
|
|
137251
|
-
setBrowserSupportTable(null);
|
|
137252
|
-
setServiceStatus(projectTranslateServiceStatus({
|
|
137253
|
-
enabled: config.enabled,
|
|
137254
|
-
hasSource: markdown.length > 0,
|
|
137255
|
-
engineId: "openai"
|
|
137256
|
-
}));
|
|
137257
|
-
return () => {
|
|
137258
|
-
disposed = true;
|
|
137259
|
-
};
|
|
137260
|
-
}
|
|
137261
|
-
const cachedTable = getBrowserSupportTableState(config.targetLanguage);
|
|
137262
|
-
if (cachedTable) {
|
|
137263
|
-
setBrowserSupportTable(cachedTable);
|
|
137264
|
-
setServiceStatus(projectTranslateServiceStatus({
|
|
137265
|
-
enabled: config.enabled,
|
|
137266
|
-
hasSource: markdown.length > 0,
|
|
137267
|
-
engineId: "browser",
|
|
137268
|
-
browserSupportTable: cachedTable
|
|
137269
|
-
}));
|
|
137270
|
-
return () => {
|
|
137271
|
-
disposed = true;
|
|
137272
|
-
};
|
|
137273
|
-
}
|
|
137274
|
-
setServiceStatus(projectTranslateServiceStatus({
|
|
137275
|
-
enabled: config.enabled,
|
|
137276
|
-
hasSource: markdown.length > 0,
|
|
137277
|
-
engineId: "browser",
|
|
137278
|
-
browserSupportTable: {
|
|
137279
|
-
state: "checking",
|
|
137280
|
-
table: null,
|
|
137281
|
-
message: "Checking browser translation pairs…"
|
|
137282
|
-
}
|
|
137283
|
-
}));
|
|
137284
137872
|
const controller = new AbortController();
|
|
137285
|
-
|
|
137873
|
+
resolveTranslateServiceState({
|
|
137874
|
+
config,
|
|
137875
|
+
hasSource: markdown.length > 0,
|
|
137286
137876
|
signal: controller.signal,
|
|
137287
|
-
|
|
137877
|
+
onUpdate: (nextState) => {
|
|
137288
137878
|
if (disposed) return;
|
|
137289
|
-
|
|
137290
|
-
|
|
137291
|
-
|
|
137292
|
-
hasSource: markdown.length > 0,
|
|
137293
|
-
engineId: "browser",
|
|
137294
|
-
browserSupportTable: nextState
|
|
137295
|
-
}));
|
|
137879
|
+
setCapability(nextState.capability);
|
|
137880
|
+
setBrowserSupportTable(nextState.browserSupportTable);
|
|
137881
|
+
setServiceStatus(nextState.status);
|
|
137296
137882
|
}
|
|
137297
137883
|
}).then((nextState) => {
|
|
137298
137884
|
if (disposed) return;
|
|
137299
|
-
|
|
137300
|
-
|
|
137301
|
-
|
|
137302
|
-
|
|
137303
|
-
engineId: "browser",
|
|
137304
|
-
browserSupportTable: nextState
|
|
137305
|
-
}));
|
|
137306
|
-
}).catch((probeError) => {
|
|
137885
|
+
setCapability(nextState.capability);
|
|
137886
|
+
setBrowserSupportTable(nextState.browserSupportTable);
|
|
137887
|
+
setServiceStatus(nextState.status);
|
|
137888
|
+
}).catch((stateError) => {
|
|
137307
137889
|
if (disposed) return;
|
|
137308
|
-
|
|
137309
|
-
|
|
137310
|
-
|
|
137311
|
-
|
|
137312
|
-
|
|
137313
|
-
|
|
137314
|
-
|
|
137315
|
-
hasSource: markdown.length > 0,
|
|
137316
|
-
engineId: "browser",
|
|
137317
|
-
browserCapability: nextCapability
|
|
137318
|
-
}));
|
|
137890
|
+
setCapability(null);
|
|
137891
|
+
setBrowserSupportTable(null);
|
|
137892
|
+
setServiceStatus({
|
|
137893
|
+
state: "unavailable",
|
|
137894
|
+
engineId: config?.engineId ?? "browser",
|
|
137895
|
+
message: stateError instanceof Error ? stateError.message : "Unable to check translation service."
|
|
137896
|
+
});
|
|
137319
137897
|
});
|
|
137320
137898
|
return () => {
|
|
137321
137899
|
disposed = true;
|
|
@@ -137333,6 +137911,8 @@ function useDocumentTranslation(markdown, config) {
|
|
|
137333
137911
|
if (!config?.enabled) return;
|
|
137334
137912
|
abortRef.current?.abort();
|
|
137335
137913
|
const controller = new AbortController();
|
|
137914
|
+
const generationId = generationRef.current + 1;
|
|
137915
|
+
generationRef.current = generationId;
|
|
137336
137916
|
abortRef.current = controller;
|
|
137337
137917
|
setError(null);
|
|
137338
137918
|
setStatus("initializing");
|
|
@@ -137343,27 +137923,19 @@ function useDocumentTranslation(markdown, config) {
|
|
|
137343
137923
|
return;
|
|
137344
137924
|
}
|
|
137345
137925
|
if (config.engineId === "browser") {
|
|
137346
|
-
const
|
|
137347
|
-
|
|
137348
|
-
|
|
137926
|
+
const nextState = prepareTranslateServiceRun({
|
|
137927
|
+
config,
|
|
137928
|
+
hasSource: markdown.length > 0,
|
|
137929
|
+
browserSupportTable
|
|
137930
|
+
});
|
|
137931
|
+
setCapability(nextState.capability);
|
|
137932
|
+
setBrowserSupportTable(nextState.browserSupportTable);
|
|
137933
|
+
setServiceStatus(nextState.status);
|
|
137934
|
+
if (nextState.status.state !== "ready") {
|
|
137935
|
+
setError(nextState.status.message);
|
|
137349
137936
|
setStatus("unavailable");
|
|
137350
137937
|
return;
|
|
137351
137938
|
}
|
|
137352
|
-
const nextCapability = {
|
|
137353
|
-
availability: preferredRow.availability,
|
|
137354
|
-
progress: preferredRow.progress,
|
|
137355
|
-
message: preferredRow.message
|
|
137356
|
-
};
|
|
137357
|
-
setCapability(nextCapability);
|
|
137358
|
-
const nextTable = patchBrowserSupportTableRow(config.targetLanguage, preferredRow, { message: void 0 });
|
|
137359
|
-
setBrowserSupportTable(nextTable);
|
|
137360
|
-
setServiceStatus(projectTranslateServiceStatus({
|
|
137361
|
-
enabled: config.enabled,
|
|
137362
|
-
hasSource: markdown.length > 0,
|
|
137363
|
-
engineId: "browser",
|
|
137364
|
-
browserSupportTable: nextTable,
|
|
137365
|
-
browserCapability: nextCapability
|
|
137366
|
-
}));
|
|
137367
137939
|
}
|
|
137368
137940
|
setStatus("translating");
|
|
137369
137941
|
setResult({
|
|
@@ -137382,21 +137954,27 @@ function useDocumentTranslation(markdown, config) {
|
|
|
137382
137954
|
write: (input) => trpcClient.translationCache.write.mutate(input)
|
|
137383
137955
|
} : void 0
|
|
137384
137956
|
}, (patch) => {
|
|
137385
|
-
if (controller.signal.aborted || abortRef.current !== controller) return;
|
|
137957
|
+
if (controller.signal.aborted || abortRef.current !== controller || generationRef.current !== generationId) return;
|
|
137386
137958
|
setResult((current) => applyDocumentTranslationPatch(current, patch, {
|
|
137387
137959
|
displayMode: config.displayMode,
|
|
137388
137960
|
targetLanguage: config.targetLanguage
|
|
137389
137961
|
}));
|
|
137390
137962
|
});
|
|
137391
|
-
if (controller.signal.aborted) return;
|
|
137963
|
+
if (controller.signal.aborted || abortRef.current !== controller || generationRef.current !== generationId) return;
|
|
137964
|
+
const documentFailure = getDocumentTranslationFailureMessage(nextResult);
|
|
137392
137965
|
setResult(nextResult);
|
|
137966
|
+
if (documentFailure) {
|
|
137967
|
+
setError(documentFailure);
|
|
137968
|
+
setStatus("error");
|
|
137969
|
+
return;
|
|
137970
|
+
}
|
|
137393
137971
|
setStatus("translated");
|
|
137394
137972
|
} catch (translationError) {
|
|
137395
|
-
if (controller.signal.aborted) return;
|
|
137973
|
+
if (controller.signal.aborted || abortRef.current !== controller || generationRef.current !== generationId) return;
|
|
137396
137974
|
setError(translationError instanceof Error ? translationError.message : "Translation failed.");
|
|
137397
137975
|
setStatus("error");
|
|
137398
137976
|
} finally {
|
|
137399
|
-
if (abortRef.current === controller) abortRef.current = null;
|
|
137977
|
+
if (abortRef.current === controller && generationRef.current === generationId) abortRef.current = null;
|
|
137400
137978
|
}
|
|
137401
137979
|
}, [
|
|
137402
137980
|
browserSupportTable,
|
|
@@ -137437,6 +138015,14 @@ function useDocumentTranslation(markdown, config) {
|
|
|
137437
138015
|
reset
|
|
137438
138016
|
};
|
|
137439
138017
|
}
|
|
138018
|
+
function getDocumentTranslationFailureMessage(result) {
|
|
138019
|
+
const segments = (Array.isArray(result.segments) ? result.segments : []).filter((segment) => segment !== void 0);
|
|
138020
|
+
if (segments.length === 0) return null;
|
|
138021
|
+
if (segments.some((segment) => segment.status !== "error" && typeof segment.target === "string")) return null;
|
|
138022
|
+
const errors = segments.map((segment) => segment.status === "error" ? segment.error : void 0).filter((message) => typeof message === "string" && message.length > 0);
|
|
138023
|
+
if (errors.length === 0) return null;
|
|
138024
|
+
return errors[0] ?? "Translation failed.";
|
|
138025
|
+
}
|
|
137440
138026
|
function applyDocumentTranslationPatch(current, patch, fallback) {
|
|
137441
138027
|
const segments = [...current?.segments ?? []];
|
|
137442
138028
|
segments[patch.segmentIndex] = patch.segment;
|
|
@@ -148221,7 +148807,8 @@ function stripOpenSpecHeadingKindFromTextNode(node, kind, state) {
|
|
|
148221
148807
|
//#endregion
|
|
148222
148808
|
//#region src/components/document-translation-action.tsx
|
|
148223
148809
|
function useDocumentTranslationRenderPlugin({ markdown, translationConfig }) {
|
|
148224
|
-
const
|
|
148810
|
+
const { data: globalSettings } = useGlobalSettingsSubscription();
|
|
148811
|
+
const resolvedTranslationConfig = (0, import_react.useMemo)(() => translationConfig === void 0 ? void 0 : DocumentTranslationConfigSchema.parse(resolveDocumentTranslationConfig(translationConfig, globalSettings)), [globalSettings, translationConfig]);
|
|
148225
148812
|
const session = useDocumentTranslation(markdown ?? "", resolvedTranslationConfig);
|
|
148226
148813
|
const canTranslate = resolvedTranslationConfig !== void 0 && typeof markdown === "string" && markdown.length > 0;
|
|
148227
148814
|
const translationProjection = (0, import_react.useMemo)(() => createTranslationProjection(session.result), [session.result]);
|
|
@@ -148261,6 +148848,7 @@ function DocumentTranslationAction({ enabled, session }) {
|
|
|
148261
148848
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DocumentTranslationButton, {
|
|
148262
148849
|
capability: session.capability,
|
|
148263
148850
|
enabled,
|
|
148851
|
+
error: session.error,
|
|
148264
148852
|
serviceStatus: session.serviceStatus,
|
|
148265
148853
|
status: session.status,
|
|
148266
148854
|
onActivate: () => {
|
|
@@ -148294,7 +148882,8 @@ function hashString(value) {
|
|
|
148294
148882
|
}
|
|
148295
148883
|
function createTranslationProjection(result) {
|
|
148296
148884
|
if (!result) return { blockAnnotations: [] };
|
|
148297
|
-
const
|
|
148885
|
+
const segments = Array.isArray(result.segments) ? result.segments : [];
|
|
148886
|
+
const segmentByOffset = new Map(segments.filter((segment) => segment.target).map((segment) => [segment.sourceStartOffset, segment]));
|
|
148298
148887
|
return {
|
|
148299
148888
|
headingProcessor: {
|
|
148300
148889
|
name: "document-translation",
|
|
@@ -148316,7 +148905,7 @@ function createTranslationProjection(result) {
|
|
|
148316
148905
|
return createTranslatedHeadingTransform(input, segment, result.displayMode);
|
|
148317
148906
|
}
|
|
148318
148907
|
},
|
|
148319
|
-
blockAnnotations:
|
|
148908
|
+
blockAnnotations: segments.filter((segment) => segment.target && segment.kind !== "heading").map((segment) => ({
|
|
148320
148909
|
sourceStartOffset: segment.sourceStartOffset,
|
|
148321
148910
|
sourceKind: segment.sourceKind,
|
|
148322
148911
|
className: result.displayMode === "direct" ? "document-translation-direct" : "document-translation-bilingual",
|
|
@@ -148415,28 +149004,31 @@ function sanitizeTranslatedProperties(properties) {
|
|
|
148415
149004
|
}
|
|
148416
149005
|
return nextProperties;
|
|
148417
149006
|
}
|
|
148418
|
-
function DocumentTranslationButton({ capability, enabled, serviceStatus, status, onActivate }) {
|
|
149007
|
+
function DocumentTranslationButton({ capability, enabled, error, serviceStatus, status, onActivate }) {
|
|
148419
149008
|
const isServiceChecking = serviceStatus.state === "checking";
|
|
148420
149009
|
const isServiceUnavailable = serviceStatus.state === "unavailable" || status === "unavailable";
|
|
148421
149010
|
const isSettingsDisabled = !enabled;
|
|
148422
149011
|
const isTranslated = status === "translated";
|
|
148423
149012
|
const isBusy = status === "initializing" || status === "translating";
|
|
148424
|
-
const
|
|
148425
|
-
const
|
|
148426
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
148427
|
-
|
|
148428
|
-
|
|
148429
|
-
|
|
148430
|
-
|
|
148431
|
-
|
|
148432
|
-
|
|
148433
|
-
|
|
148434
|
-
|
|
148435
|
-
|
|
148436
|
-
|
|
148437
|
-
|
|
148438
|
-
|
|
148439
|
-
|
|
149013
|
+
const isError = status === "error";
|
|
149014
|
+
const ariaLabel = isServiceUnavailable ? "Translation unavailable" : isSettingsDisabled ? "Configure translation" : isServiceChecking ? "Checking translation" : isError ? "Retry translation" : isBusy ? "Cancel translation" : isTranslated ? "Show source" : "Translate";
|
|
149015
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tooltip, {
|
|
149016
|
+
content: isServiceUnavailable ? serviceStatus.message ?? capability?.message ?? "Translation is unavailable." : isSettingsDisabled ? "Translation is disabled in settings." : isError ? `${error ?? "Translation failed."} Click to retry.` : ariaLabel,
|
|
149017
|
+
delay: 0,
|
|
149018
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
149019
|
+
size: "icon-sm",
|
|
149020
|
+
variant: "secondary",
|
|
149021
|
+
disabled: isServiceUnavailable || isServiceChecking,
|
|
149022
|
+
"aria-disabled": isSettingsDisabled ? true : void 0,
|
|
149023
|
+
onClick: (event) => {
|
|
149024
|
+
event.stopPropagation();
|
|
149025
|
+
onActivate();
|
|
149026
|
+
},
|
|
149027
|
+
"aria-label": ariaLabel,
|
|
149028
|
+
"data-translation-action-state": isServiceUnavailable ? "unavailable" : isServiceChecking ? "checking" : isSettingsDisabled ? "settings-disabled" : isError ? "error" : isBusy ? "busy" : isTranslated ? "translated" : "ready",
|
|
149029
|
+
className: isServiceUnavailable || isServiceChecking ? "border-border bg-muted text-muted-foreground disabled:border-border disabled:bg-muted disabled:text-muted-foreground" : isSettingsDisabled ? "border-border bg-muted/40 text-muted-foreground opacity-70" : isError ? "border-amber-500/50 bg-amber-500/10 text-amber-600 hover:bg-amber-500/15 dark:text-amber-400" : isTranslated ? "border-primary bg-primary text-primary-foreground hover:bg-primary/90" : "border-primary text-primary hover:bg-primary/10",
|
|
149030
|
+
children: isBusy || isServiceChecking ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LoaderCircle, { className: "h-4 w-4 animate-spin" }) : isServiceUnavailable || isError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TriangleAlert, { className: "h-4 w-4" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Languages, { className: "h-4 w-4" })
|
|
149031
|
+
})
|
|
148440
149032
|
});
|
|
148441
149033
|
}
|
|
148442
149034
|
//#endregion
|
|
@@ -150398,89 +150990,6 @@ var viewerStyles = String.raw`
|
|
|
150398
150990
|
/* MarkdownViewer keeps layout hooks local; shared ToC geometry lives in index.css. */
|
|
150399
150991
|
`;
|
|
150400
150992
|
//#endregion
|
|
150401
|
-
//#region src/components/scroll-spy.ts
|
|
150402
|
-
function hasVerticalScrollBehavior(overflowY) {
|
|
150403
|
-
return overflowY === "auto" || overflowY === "scroll" || overflowY === "overlay";
|
|
150404
|
-
}
|
|
150405
|
-
function findVerticalScrollContainer(node, options = {}) {
|
|
150406
|
-
const { allowNonScrollable = false } = options;
|
|
150407
|
-
let current = node?.parentElement ?? null;
|
|
150408
|
-
while (current) {
|
|
150409
|
-
if (hasVerticalScrollBehavior(window.getComputedStyle(current).overflowY)) {
|
|
150410
|
-
if (allowNonScrollable || current.scrollHeight > current.clientHeight) return current;
|
|
150411
|
-
}
|
|
150412
|
-
current = current.parentElement;
|
|
150413
|
-
}
|
|
150414
|
-
return null;
|
|
150415
|
-
}
|
|
150416
|
-
function scrollViewportBounds(root) {
|
|
150417
|
-
if (root) {
|
|
150418
|
-
const rect = root.getBoundingClientRect();
|
|
150419
|
-
return {
|
|
150420
|
-
top: rect.top,
|
|
150421
|
-
bottom: rect.bottom
|
|
150422
|
-
};
|
|
150423
|
-
}
|
|
150424
|
-
return {
|
|
150425
|
-
top: 0,
|
|
150426
|
-
bottom: window.innerHeight
|
|
150427
|
-
};
|
|
150428
|
-
}
|
|
150429
|
-
function measureAvailableViewportHeight(node, root = findVerticalScrollContainer(node, { allowNonScrollable: true })) {
|
|
150430
|
-
if (typeof window === "undefined" || !node) return null;
|
|
150431
|
-
const nodeRect = node.getBoundingClientRect();
|
|
150432
|
-
const viewport = scrollViewportBounds(root);
|
|
150433
|
-
return Math.max(Math.floor(viewport.bottom - Math.max(nodeRect.top, viewport.top)), 0);
|
|
150434
|
-
}
|
|
150435
|
-
function useViewportConstrainedHeight({ target, enabled = true }) {
|
|
150436
|
-
const [height, setHeight] = (0, import_react.useState)(null);
|
|
150437
|
-
(0, import_react.useLayoutEffect)(() => {
|
|
150438
|
-
if (!enabled || typeof window === "undefined") {
|
|
150439
|
-
setHeight(null);
|
|
150440
|
-
return;
|
|
150441
|
-
}
|
|
150442
|
-
if (!target) {
|
|
150443
|
-
setHeight(null);
|
|
150444
|
-
return;
|
|
150445
|
-
}
|
|
150446
|
-
let resizeObserver = null;
|
|
150447
|
-
let scrollRoot = null;
|
|
150448
|
-
let scrollTarget = window;
|
|
150449
|
-
const setConstrainedHeight = (nextHeight) => {
|
|
150450
|
-
setHeight((currentHeight) => currentHeight === nextHeight ? currentHeight : nextHeight);
|
|
150451
|
-
};
|
|
150452
|
-
const bindScrollRoot = (nextRoot) => {
|
|
150453
|
-
if (scrollRoot === nextRoot) return;
|
|
150454
|
-
scrollTarget.removeEventListener("scroll", handleUpdate);
|
|
150455
|
-
if (resizeObserver && scrollRoot) resizeObserver.unobserve(scrollRoot);
|
|
150456
|
-
scrollRoot = nextRoot;
|
|
150457
|
-
scrollTarget = nextRoot ?? window;
|
|
150458
|
-
scrollTarget.addEventListener("scroll", handleUpdate, { passive: true });
|
|
150459
|
-
if (resizeObserver && scrollRoot) resizeObserver.observe(scrollRoot);
|
|
150460
|
-
};
|
|
150461
|
-
const handleUpdate = () => {
|
|
150462
|
-
const nextRoot = findVerticalScrollContainer(target, { allowNonScrollable: true });
|
|
150463
|
-
bindScrollRoot(nextRoot);
|
|
150464
|
-
setConstrainedHeight(measureAvailableViewportHeight(target, nextRoot));
|
|
150465
|
-
};
|
|
150466
|
-
if (typeof ResizeObserver !== "undefined") {
|
|
150467
|
-
resizeObserver = new ResizeObserver(() => {
|
|
150468
|
-
handleUpdate();
|
|
150469
|
-
});
|
|
150470
|
-
resizeObserver.observe(target);
|
|
150471
|
-
if (target.parentElement) resizeObserver.observe(target.parentElement);
|
|
150472
|
-
}
|
|
150473
|
-
handleUpdate();
|
|
150474
|
-
window.addEventListener("resize", handleUpdate);
|
|
150475
|
-
return () => {
|
|
150476
|
-
window.removeEventListener("resize", handleUpdate);
|
|
150477
|
-
scrollTarget.removeEventListener("scroll", handleUpdate);
|
|
150478
|
-
resizeObserver?.disconnect();
|
|
150479
|
-
};
|
|
150480
|
-
}, [enabled, target]);
|
|
150481
|
-
return height;
|
|
150482
|
-
}
|
|
150483
|
-
//#endregion
|
|
150484
150993
|
//#region src/lib/file-preview.ts
|
|
150485
150994
|
async function prepareEntityFilePreview(input) {
|
|
150486
150995
|
if (isStaticMode()) return null;
|
|
@@ -150555,13 +151064,10 @@ function isPreviewOnlyFile(file) {
|
|
|
150555
151064
|
}
|
|
150556
151065
|
function resolveDefaultMode(file, inStaticMode) {
|
|
150557
151066
|
if (!file) return "read";
|
|
151067
|
+
if (!inStaticMode && isFileEntry(file) && file.previewKind === "html") return "preview";
|
|
150558
151068
|
if (!inStaticMode && isPreviewOnlyFile(file)) return "preview";
|
|
150559
151069
|
return "read";
|
|
150560
151070
|
}
|
|
150561
|
-
function clampPreviewHeight(viewportHeight) {
|
|
150562
|
-
if (viewportHeight == null) return 480;
|
|
150563
|
-
return Math.max(320, Math.min(viewportHeight - 112, 920));
|
|
150564
|
-
}
|
|
150565
151071
|
function resolveRemotePreviewFrameStyle(frameHeight) {
|
|
150566
151072
|
if (frameHeight == null) return void 0;
|
|
150567
151073
|
return {
|
|
@@ -150601,7 +151107,7 @@ async function sharePreview(input) {
|
|
|
150601
151107
|
}
|
|
150602
151108
|
function PreviewPane({ file, preview, loading, error, className = "", frameHeight, isDarkMode }) {
|
|
150603
151109
|
if (file.previewKind === "markdown") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
150604
|
-
className: `min-h-0
|
|
151110
|
+
className: `h-full min-h-0 flex-1 overflow-hidden ${className}`,
|
|
150605
151111
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MarkdownViewer, {
|
|
150606
151112
|
markdown: file.content ?? "",
|
|
150607
151113
|
path: file.path,
|
|
@@ -150621,7 +151127,7 @@ function PreviewPane({ file, preview, loading, error, className = "", frameHeigh
|
|
|
150621
151127
|
children: "Preview unavailable."
|
|
150622
151128
|
});
|
|
150623
151129
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
150624
|
-
className: `bg-background min-h-0
|
|
151130
|
+
className: `bg-background h-full min-h-0 overflow-hidden ${className}`,
|
|
150625
151131
|
style: resolveRemotePreviewFrameStyle(frameHeight),
|
|
150626
151132
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("iframe", {
|
|
150627
151133
|
src: resolvePreviewFrameUrl(preview, isDarkMode),
|
|
@@ -150635,7 +151141,6 @@ function FolderEditorViewer({ changeId, archived = false, files: providedFiles }
|
|
|
150635
151141
|
const isDarkMode = useDarkMode();
|
|
150636
151142
|
const { data: files, isLoading, error } = archived ? useArchiveFilesSubscription(changeId) : useChangeFilesSubscription(changeId);
|
|
150637
151143
|
const [selectedPath, setSelectedPath] = (0, import_react.useState)(null);
|
|
150638
|
-
const [viewportNode, setViewportNode] = (0, import_react.useState)(null);
|
|
150639
151144
|
const [mode, setMode] = (0, import_react.useState)("read");
|
|
150640
151145
|
const [draftContent, setDraftContent] = (0, import_react.useState)({});
|
|
150641
151146
|
const [savingPath, setSavingPath] = (0, import_react.useState)(null);
|
|
@@ -150644,10 +151149,6 @@ function FolderEditorViewer({ changeId, archived = false, files: providedFiles }
|
|
|
150644
151149
|
const [previewErrorByPath, setPreviewErrorByPath] = (0, import_react.useState)({});
|
|
150645
151150
|
const [previewMaximized, setPreviewMaximized] = (0, import_react.useState)(false);
|
|
150646
151151
|
const [shareFeedback, setShareFeedback] = (0, import_react.useState)(null);
|
|
150647
|
-
const viewportHeight = useViewportConstrainedHeight({
|
|
150648
|
-
target: viewportNode,
|
|
150649
|
-
enabled: viewportNode !== null
|
|
150650
|
-
});
|
|
150651
151152
|
const sortedEntries = (0, import_react.useMemo)(() => {
|
|
150652
151153
|
if (providedFiles) return [...providedFiles];
|
|
150653
151154
|
if (!files) return [];
|
|
@@ -150663,7 +151164,6 @@ function FolderEditorViewer({ changeId, archived = false, files: providedFiles }
|
|
|
150663
151164
|
const readEnabled = !isPreviewOnlyFile(activeFile);
|
|
150664
151165
|
const previewEnabled = !inStaticMode && canPreviewFile(activeFile);
|
|
150665
151166
|
const hasDirtyDraft = !!activeFile && isTextLikeFile(activeFile) && activeDraft !== (activeFile.content ?? "");
|
|
150666
|
-
const remotePreviewHeight = clampPreviewHeight(viewportHeight);
|
|
150667
151167
|
(0, import_react.useEffect)(() => {
|
|
150668
151168
|
if (!sortedEntries.length) {
|
|
150669
151169
|
setSelectedPath(null);
|
|
@@ -150694,6 +151194,7 @@ function FolderEditorViewer({ changeId, archived = false, files: providedFiles }
|
|
|
150694
151194
|
const nextDefaultMode = resolveDefaultMode(activeFile, inStaticMode);
|
|
150695
151195
|
setMode((currentMode) => {
|
|
150696
151196
|
if (currentMode === nextDefaultMode) return currentMode;
|
|
151197
|
+
if (currentMode === "read" && nextDefaultMode === "preview") return nextDefaultMode;
|
|
150697
151198
|
if (currentMode === "edit" && editEnabled) return currentMode;
|
|
150698
151199
|
if (currentMode === "preview" && previewEnabled) return currentMode;
|
|
150699
151200
|
if (currentMode === "read" && readEnabled) return currentMode;
|
|
@@ -150788,13 +151289,12 @@ function FolderEditorViewer({ changeId, archived = false, files: providedFiles }
|
|
|
150788
151289
|
};
|
|
150789
151290
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
|
|
150790
151291
|
"data-tab-scroll-root": "true",
|
|
150791
|
-
className: "
|
|
151292
|
+
className: "min-h-0 flex-1 overflow-hidden",
|
|
150792
151293
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
150793
|
-
className: "pr-1",
|
|
151294
|
+
className: "h-full min-h-0 pr-1",
|
|
150794
151295
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
150795
|
-
|
|
150796
|
-
className: "flex min-h-0 flex-col",
|
|
150797
|
-
style: viewportHeight != null ? { height: `${viewportHeight}px` } : void 0,
|
|
151296
|
+
"data-folder-viewport": "",
|
|
151297
|
+
className: "flex h-full min-h-0 flex-col overflow-hidden",
|
|
150798
151298
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileExplorer, {
|
|
150799
151299
|
entries: sortedEntries,
|
|
150800
151300
|
selectedPath,
|
|
@@ -150808,92 +151308,141 @@ function FolderEditorViewer({ changeId, archived = false, files: providedFiles }
|
|
|
150808
151308
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
150809
151309
|
className: "flex min-h-0 flex-1 flex-col",
|
|
150810
151310
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
150811
|
-
|
|
151311
|
+
"data-folder-toolbar": "",
|
|
151312
|
+
className: "border-border/60 bg-muted/20 flex flex-wrap items-center gap-3 border-b px-3 py-2",
|
|
150812
151313
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ButtonGroup, {
|
|
150813
151314
|
value: mode,
|
|
150814
151315
|
onChange: setMode,
|
|
151316
|
+
presentation: "icon-only",
|
|
151317
|
+
className: "min-w-0",
|
|
150815
151318
|
options: [
|
|
150816
151319
|
{
|
|
150817
151320
|
value: "read",
|
|
150818
151321
|
label: "Read",
|
|
151322
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScrollText, { className: "h-3.5 w-3.5" }),
|
|
151323
|
+
ariaLabel: "Read",
|
|
151324
|
+
tooltip: "Read",
|
|
150819
151325
|
disabled: !readEnabled
|
|
150820
151326
|
},
|
|
150821
151327
|
{
|
|
150822
151328
|
value: "edit",
|
|
150823
151329
|
label: "Edit",
|
|
151330
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FilePenLine, { className: "h-3.5 w-3.5" }),
|
|
151331
|
+
ariaLabel: "Edit",
|
|
151332
|
+
tooltip: "Edit",
|
|
150824
151333
|
disabled: !editEnabled
|
|
150825
151334
|
},
|
|
150826
151335
|
{
|
|
150827
151336
|
value: "preview",
|
|
150828
151337
|
label: "Preview",
|
|
151338
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Eye, { className: "h-3.5 w-3.5" }),
|
|
151339
|
+
ariaLabel: "Preview",
|
|
151340
|
+
tooltip: "Preview",
|
|
150829
151341
|
disabled: !previewEnabled
|
|
150830
151342
|
}
|
|
150831
151343
|
]
|
|
150832
151344
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
150833
|
-
|
|
150834
|
-
|
|
150835
|
-
|
|
150836
|
-
|
|
150837
|
-
|
|
150838
|
-
|
|
150839
|
-
if (!isTextLikeFile(activeFile)) return;
|
|
150840
|
-
setDraftContent((current) => ({
|
|
150841
|
-
...current,
|
|
150842
|
-
[activeFile.path]: activeFile.content ?? ""
|
|
150843
|
-
}));
|
|
150844
|
-
},
|
|
150845
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Undo2, { className: "h-3.5 w-3.5" }), "Revert"]
|
|
150846
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button, {
|
|
150847
|
-
variant: "primary",
|
|
150848
|
-
size: "sm",
|
|
150849
|
-
disabled: !hasDirtyDraft || savingPath === currentFile.path,
|
|
150850
|
-
onClick: saveActiveDraft,
|
|
150851
|
-
children: [savingPath === currentFile.path ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LoaderCircle, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Save, { className: "h-3.5 w-3.5" }), "Save"]
|
|
150852
|
-
})] }) : mode === "preview" && canPreviewRemote(activeFile) ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
150853
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button, {
|
|
151345
|
+
"data-folder-toolbar-actions": "",
|
|
151346
|
+
className: "ml-auto flex min-w-0 max-w-full flex-wrap items-center justify-end gap-2",
|
|
151347
|
+
children: mode === "edit" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tooltip, {
|
|
151348
|
+
content: "Revert",
|
|
151349
|
+
delay: 0,
|
|
151350
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
150854
151351
|
variant: "secondary",
|
|
150855
|
-
size: "sm",
|
|
151352
|
+
size: "icon-sm",
|
|
151353
|
+
"aria-label": "Revert",
|
|
151354
|
+
title: "Revert",
|
|
151355
|
+
disabled: !hasDirtyDraft,
|
|
150856
151356
|
onClick: () => {
|
|
150857
|
-
|
|
150858
|
-
|
|
150859
|
-
|
|
150860
|
-
|
|
150861
|
-
});
|
|
151357
|
+
if (!isTextLikeFile(activeFile)) return;
|
|
151358
|
+
setDraftContent((current) => ({
|
|
151359
|
+
...current,
|
|
151360
|
+
[activeFile.path]: activeFile.content ?? ""
|
|
151361
|
+
}));
|
|
150862
151362
|
},
|
|
150863
|
-
children:
|
|
151363
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Undo2, { className: "h-3.5 w-3.5" })
|
|
151364
|
+
})
|
|
151365
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tooltip, {
|
|
151366
|
+
content: "Save",
|
|
151367
|
+
delay: 0,
|
|
151368
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
151369
|
+
variant: "primary",
|
|
151370
|
+
size: "icon-sm",
|
|
151371
|
+
"aria-label": "Save",
|
|
151372
|
+
title: "Save",
|
|
151373
|
+
disabled: !hasDirtyDraft || savingPath === currentFile.path,
|
|
151374
|
+
onClick: saveActiveDraft,
|
|
151375
|
+
children: savingPath === currentFile.path ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LoaderCircle, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Save, { className: "h-3.5 w-3.5" })
|
|
151376
|
+
})
|
|
151377
|
+
})] }) : mode === "preview" && canPreviewRemote(activeFile) ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
151378
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tooltip, {
|
|
151379
|
+
content: "Refresh",
|
|
151380
|
+
delay: 0,
|
|
151381
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
151382
|
+
variant: "secondary",
|
|
151383
|
+
size: "icon-sm",
|
|
151384
|
+
"aria-label": "Refresh",
|
|
151385
|
+
title: "Refresh",
|
|
151386
|
+
onClick: () => {
|
|
151387
|
+
setPreviewByPath((current) => {
|
|
151388
|
+
const next = { ...current };
|
|
151389
|
+
delete next[currentFile.path];
|
|
151390
|
+
return next;
|
|
151391
|
+
});
|
|
151392
|
+
},
|
|
151393
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RefreshCw, { className: "h-3.5 w-3.5" })
|
|
151394
|
+
})
|
|
150864
151395
|
}),
|
|
150865
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
150866
|
-
|
|
150867
|
-
|
|
150868
|
-
|
|
150869
|
-
|
|
150870
|
-
|
|
150871
|
-
|
|
151396
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tooltip, {
|
|
151397
|
+
content: previewMaximized ? "Exit maximize" : "Maximize",
|
|
151398
|
+
delay: 0,
|
|
151399
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
151400
|
+
variant: "secondary",
|
|
151401
|
+
size: "icon-sm",
|
|
151402
|
+
"aria-label": previewMaximized ? "Exit maximize" : "Maximize",
|
|
151403
|
+
title: previewMaximized ? "Exit maximize" : "Maximize",
|
|
151404
|
+
onClick: () => {
|
|
151405
|
+
setPreviewMaximized((current) => !current);
|
|
151406
|
+
},
|
|
151407
|
+
children: previewMaximized ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Minimize, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Expand, { className: "h-3.5 w-3.5" })
|
|
151408
|
+
})
|
|
150872
151409
|
}),
|
|
150873
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
150874
|
-
|
|
150875
|
-
|
|
150876
|
-
|
|
150877
|
-
|
|
150878
|
-
|
|
150879
|
-
|
|
150880
|
-
|
|
150881
|
-
|
|
151410
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tooltip, {
|
|
151411
|
+
content: "Download",
|
|
151412
|
+
delay: 0,
|
|
151413
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
151414
|
+
variant: "secondary",
|
|
151415
|
+
size: "icon-sm",
|
|
151416
|
+
"aria-label": "Download",
|
|
151417
|
+
title: "Download",
|
|
151418
|
+
disabled: !previewDownloadUrl,
|
|
151419
|
+
onClick: () => {
|
|
151420
|
+
if (!previewDownloadUrl) return;
|
|
151421
|
+
triggerDownload(previewDownloadUrl, currentFile.path.split("/").pop() ?? "preview");
|
|
151422
|
+
},
|
|
151423
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Download, { className: "h-3.5 w-3.5" })
|
|
151424
|
+
})
|
|
150882
151425
|
}),
|
|
150883
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
150884
|
-
|
|
150885
|
-
|
|
150886
|
-
|
|
150887
|
-
|
|
150888
|
-
|
|
150889
|
-
|
|
150890
|
-
|
|
150891
|
-
|
|
150892
|
-
|
|
150893
|
-
|
|
150894
|
-
|
|
150895
|
-
|
|
150896
|
-
|
|
151426
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tooltip, {
|
|
151427
|
+
content: shareFeedback === "shared" ? "Shared" : shareFeedback === "copied" ? "Copied" : "Share",
|
|
151428
|
+
delay: 0,
|
|
151429
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
151430
|
+
variant: "secondary",
|
|
151431
|
+
size: "icon-sm",
|
|
151432
|
+
"aria-label": shareFeedback === "shared" ? "Shared" : shareFeedback === "copied" ? "Copied" : "Share",
|
|
151433
|
+
title: shareFeedback === "shared" ? "Shared" : shareFeedback === "copied" ? "Copied" : "Share",
|
|
151434
|
+
disabled: !previewShareUrl,
|
|
151435
|
+
onClick: () => {
|
|
151436
|
+
if (!previewShareUrl) return;
|
|
151437
|
+
sharePreview({
|
|
151438
|
+
url: previewShareUrl,
|
|
151439
|
+
title: currentFile.path
|
|
151440
|
+
}).then((shared) => {
|
|
151441
|
+
setShareFeedback(shared ? "shared" : "copied");
|
|
151442
|
+
});
|
|
151443
|
+
},
|
|
151444
|
+
children: shareFeedback === "shared" || shareFeedback === "copied" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Check, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Share2, { className: "h-3.5 w-3.5" })
|
|
151445
|
+
})
|
|
150897
151446
|
})
|
|
150898
151447
|
] }) : null
|
|
150899
151448
|
})]
|
|
@@ -150907,7 +151456,6 @@ function FolderEditorViewer({ changeId, archived = false, files: providedFiles }
|
|
|
150907
151456
|
preview,
|
|
150908
151457
|
loading: previewLoadingPath === currentFile.path,
|
|
150909
151458
|
error: previewError,
|
|
150910
|
-
frameHeight: canPreviewRemote(currentFile) ? remotePreviewHeight : void 0,
|
|
150911
151459
|
isDarkMode
|
|
150912
151460
|
})
|
|
150913
151461
|
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileExplorerCodeEditor, {
|
|
@@ -150939,7 +151487,7 @@ function FolderEditorViewer({ changeId, archived = false, files: providedFiles }
|
|
|
150939
151487
|
contentClassName: "px-3 py-3",
|
|
150940
151488
|
maxHeight: "96vh",
|
|
150941
151489
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
150942
|
-
className: "flex h-[80vh]
|
|
151490
|
+
className: "flex h-[80vh] max-h-[88vh] min-h-[420px] min-w-0 flex-col overflow-hidden",
|
|
150943
151491
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PreviewPane, {
|
|
150944
151492
|
file: activeFile,
|
|
150945
151493
|
preview,
|
|
@@ -151164,6 +151712,8 @@ function GlobContent({ changeId, artifact, translationConfig }) {
|
|
|
151164
151712
|
}
|
|
151165
151713
|
function ArtifactOutputViewer({ changeId, artifact }) {
|
|
151166
151714
|
const { data: config } = useConfigSubscription();
|
|
151715
|
+
const { data: globalSettings } = useGlobalSettingsSubscription();
|
|
151716
|
+
const translationConfig = resolveDocumentTranslationConfig(config?.translation, globalSettings);
|
|
151167
151717
|
if (artifact.files) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
151168
151718
|
className: "flex min-h-0 flex-1 flex-col",
|
|
151169
151719
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
@@ -151171,25 +151721,26 @@ function ArtifactOutputViewer({ changeId, artifact }) {
|
|
|
151171
151721
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArtifactFilesDocumentShell, {
|
|
151172
151722
|
artifact,
|
|
151173
151723
|
files: artifact.files,
|
|
151174
|
-
translationConfig
|
|
151724
|
+
translationConfig
|
|
151175
151725
|
})
|
|
151176
151726
|
})
|
|
151177
151727
|
});
|
|
151178
151728
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LiveArtifactOutputViewer, {
|
|
151179
151729
|
changeId,
|
|
151180
151730
|
artifact,
|
|
151181
|
-
translationConfig
|
|
151731
|
+
translationConfig
|
|
151182
151732
|
});
|
|
151183
151733
|
}
|
|
151184
151734
|
function ContentFallbackViewer({ fallback }) {
|
|
151185
151735
|
const { data: config } = useConfigSubscription();
|
|
151736
|
+
const { data: globalSettings } = useGlobalSettingsSubscription();
|
|
151186
151737
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
151187
151738
|
className: "flex min-h-0 flex-1 flex-col",
|
|
151188
151739
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
151189
151740
|
className: "min-h-0 flex-1",
|
|
151190
151741
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FallbackDocumentShell, {
|
|
151191
151742
|
fallback,
|
|
151192
|
-
translationConfig: config?.translation
|
|
151743
|
+
translationConfig: resolveDocumentTranslationConfig(config?.translation, globalSettings)
|
|
151193
151744
|
})
|
|
151194
151745
|
})
|
|
151195
151746
|
});
|
|
@@ -151786,6 +152337,89 @@ function renderAnsiLine(line) {
|
|
|
151786
152337
|
return parts.length > 0 ? parts : line;
|
|
151787
152338
|
}
|
|
151788
152339
|
//#endregion
|
|
152340
|
+
//#region src/components/scroll-spy.ts
|
|
152341
|
+
function hasVerticalScrollBehavior(overflowY) {
|
|
152342
|
+
return overflowY === "auto" || overflowY === "scroll" || overflowY === "overlay";
|
|
152343
|
+
}
|
|
152344
|
+
function findVerticalScrollContainer(node, options = {}) {
|
|
152345
|
+
const { allowNonScrollable = false } = options;
|
|
152346
|
+
let current = node?.parentElement ?? null;
|
|
152347
|
+
while (current) {
|
|
152348
|
+
if (hasVerticalScrollBehavior(window.getComputedStyle(current).overflowY)) {
|
|
152349
|
+
if (allowNonScrollable || current.scrollHeight > current.clientHeight) return current;
|
|
152350
|
+
}
|
|
152351
|
+
current = current.parentElement;
|
|
152352
|
+
}
|
|
152353
|
+
return null;
|
|
152354
|
+
}
|
|
152355
|
+
function scrollViewportBounds(root) {
|
|
152356
|
+
if (root) {
|
|
152357
|
+
const rect = root.getBoundingClientRect();
|
|
152358
|
+
return {
|
|
152359
|
+
top: rect.top,
|
|
152360
|
+
bottom: rect.bottom
|
|
152361
|
+
};
|
|
152362
|
+
}
|
|
152363
|
+
return {
|
|
152364
|
+
top: 0,
|
|
152365
|
+
bottom: window.innerHeight
|
|
152366
|
+
};
|
|
152367
|
+
}
|
|
152368
|
+
function measureAvailableViewportHeight(node, root = findVerticalScrollContainer(node, { allowNonScrollable: true })) {
|
|
152369
|
+
if (typeof window === "undefined" || !node) return null;
|
|
152370
|
+
const nodeRect = node.getBoundingClientRect();
|
|
152371
|
+
const viewport = scrollViewportBounds(root);
|
|
152372
|
+
return Math.max(Math.floor(viewport.bottom - Math.max(nodeRect.top, viewport.top)), 0);
|
|
152373
|
+
}
|
|
152374
|
+
function useViewportConstrainedHeight({ target, enabled = true }) {
|
|
152375
|
+
const [height, setHeight] = (0, import_react.useState)(null);
|
|
152376
|
+
(0, import_react.useLayoutEffect)(() => {
|
|
152377
|
+
if (!enabled || typeof window === "undefined") {
|
|
152378
|
+
setHeight(null);
|
|
152379
|
+
return;
|
|
152380
|
+
}
|
|
152381
|
+
if (!target) {
|
|
152382
|
+
setHeight(null);
|
|
152383
|
+
return;
|
|
152384
|
+
}
|
|
152385
|
+
let resizeObserver = null;
|
|
152386
|
+
let scrollRoot = null;
|
|
152387
|
+
let scrollTarget = window;
|
|
152388
|
+
const setConstrainedHeight = (nextHeight) => {
|
|
152389
|
+
setHeight((currentHeight) => currentHeight === nextHeight ? currentHeight : nextHeight);
|
|
152390
|
+
};
|
|
152391
|
+
const bindScrollRoot = (nextRoot) => {
|
|
152392
|
+
if (scrollRoot === nextRoot) return;
|
|
152393
|
+
scrollTarget.removeEventListener("scroll", handleUpdate);
|
|
152394
|
+
if (resizeObserver && scrollRoot) resizeObserver.unobserve(scrollRoot);
|
|
152395
|
+
scrollRoot = nextRoot;
|
|
152396
|
+
scrollTarget = nextRoot ?? window;
|
|
152397
|
+
scrollTarget.addEventListener("scroll", handleUpdate, { passive: true });
|
|
152398
|
+
if (resizeObserver && scrollRoot) resizeObserver.observe(scrollRoot);
|
|
152399
|
+
};
|
|
152400
|
+
const handleUpdate = () => {
|
|
152401
|
+
const nextRoot = findVerticalScrollContainer(target, { allowNonScrollable: true });
|
|
152402
|
+
bindScrollRoot(nextRoot);
|
|
152403
|
+
setConstrainedHeight(measureAvailableViewportHeight(target, nextRoot));
|
|
152404
|
+
};
|
|
152405
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
152406
|
+
resizeObserver = new ResizeObserver(() => {
|
|
152407
|
+
handleUpdate();
|
|
152408
|
+
});
|
|
152409
|
+
resizeObserver.observe(target);
|
|
152410
|
+
if (target.parentElement) resizeObserver.observe(target.parentElement);
|
|
152411
|
+
}
|
|
152412
|
+
handleUpdate();
|
|
152413
|
+
window.addEventListener("resize", handleUpdate);
|
|
152414
|
+
return () => {
|
|
152415
|
+
window.removeEventListener("resize", handleUpdate);
|
|
152416
|
+
scrollTarget.removeEventListener("scroll", handleUpdate);
|
|
152417
|
+
resizeObserver?.disconnect();
|
|
152418
|
+
};
|
|
152419
|
+
}, [enabled, target]);
|
|
152420
|
+
return height;
|
|
152421
|
+
}
|
|
152422
|
+
//#endregion
|
|
151789
152423
|
//#region ../../node_modules/.pnpm/@base-ui+utils@0.2.6_@types+react@19.2.7_react-dom@19.2.0_react@19.2.0__react@19.2.0/node_modules/@base-ui/utils/esm/useControlled.js
|
|
151790
152424
|
function useControlled({ controlled, default: defaultProp, name, state = "value" }) {
|
|
151791
152425
|
const { current: isControlled } = import_react.useRef(controlled !== void 0);
|
|
@@ -158633,6 +159267,8 @@ function SpecView() {
|
|
|
158633
159267
|
const { data: spec, isLoading } = useSpecSubscription(specId);
|
|
158634
159268
|
const { data: rawMarkdown, isLoading: isRawLoading } = useSpecRawSubscription(specId);
|
|
158635
159269
|
const { data: config } = useConfigSubscription();
|
|
159270
|
+
const { data: globalSettings } = useGlobalSettingsSubscription();
|
|
159271
|
+
const translationConfig = (0, import_react.useMemo)(() => resolveDocumentTranslationConfig(config?.translation, globalSettings), [config?.translation, globalSettings]);
|
|
158636
159272
|
const validation = null;
|
|
158637
159273
|
if (isLoading && !spec || isRawLoading && !rawMarkdown) {
|
|
158638
159274
|
if (handoff) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
@@ -158678,7 +159314,7 @@ function SpecView() {
|
|
|
158678
159314
|
spec,
|
|
158679
159315
|
rawMarkdown: rawMarkdown ?? "",
|
|
158680
159316
|
validation,
|
|
158681
|
-
translationConfig
|
|
159317
|
+
translationConfig
|
|
158682
159318
|
});
|
|
158683
159319
|
}
|
|
158684
159320
|
function SpecContent({ spec, rawMarkdown, validation, translationConfig }) {
|