@openspecui/web 3.11.0 → 3.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/CanvasRenderer-C0z1_uAq.js +1 -0
- package/dist/assets/WebGLRenderer-BgB0b-_m.js +1 -0
- package/dist/assets/WebGPURenderer-DUOyTSOY.js +1 -0
- package/dist/assets/browserAll-DrkY7ahm.js +1 -0
- package/dist/assets/{dist-D0kk4OnI.js → dist-B9Ltz3Au.js} +1 -1
- package/dist/assets/dist-BLzDSe4i.js +1 -0
- package/dist/assets/{dist-D7t0ICkd.js → dist-B_UFDOda.js} +1 -1
- package/dist/assets/{dist-B_uzjHQN.js → dist-BggZ7cyQ.js} +1 -1
- package/dist/assets/dist-C2tzK2BJ.js +1 -0
- package/dist/assets/{dist-CRlC9_e7.js → dist-DHhbIMeO.js} +1 -1
- package/dist/assets/{dist-CcLC6JdJ.js → dist-DRc-odji.js} +1 -1
- package/dist/assets/{dist-CjSC6Iz-.js → dist-Drgp5ero.js} +1 -1
- package/dist/assets/{dist-Deq3d3tg.js → dist-HIi-Q3U-.js} +1 -1
- package/dist/assets/dist-LSzi3-xz.js +1 -0
- package/dist/assets/{dist-Co2y3Dp-.js → dist-j6cthCRX.js} +1 -1
- package/dist/assets/{dist-DSHRZu7v.js → dist-wEqYYKag.js} +1 -1
- package/dist/assets/{init-CXvIgPy6.js → init-D41cyy2z.js} +1 -1
- package/dist/assets/main-DpM-T-Pk.js +1654 -0
- package/dist/assets/main-fCQ7khWW.css +1 -0
- package/dist/assets/trpc-lJhbxi32.js +1 -0
- package/dist/assets/webworkerAll-DXrA-UNG.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-pScAgtDS.js +1 -0
- package/dist-ssg/client/assets/WebGLRenderer-BAJXWFrw.js +1 -0
- package/dist-ssg/client/assets/WebGPURenderer-BeNNGqxY.js +1 -0
- package/dist-ssg/client/assets/browserAll-CkiE7Jmg.js +1 -0
- package/dist-ssg/client/assets/{dist-DYA7aYgJ.js → dist-BJ0zzLee.js} +1 -1
- package/dist-ssg/client/assets/dist-BJBQISim.js +1 -0
- package/dist-ssg/client/assets/dist-BPi1lJ-H.js +1 -0
- package/dist-ssg/client/assets/{dist-B0rNAJNr.js → dist-BZ35ju6s.js} +1 -1
- package/dist-ssg/client/assets/{dist-nDVKH9rz.js → dist-Bg-C799P.js} +1 -1
- package/dist-ssg/client/assets/dist-CNPnfIVE.js +1 -0
- package/dist-ssg/client/assets/{dist-Ct0osEG9.js → dist-CrdkjkLH.js} +1 -1
- package/dist-ssg/client/assets/{dist-CIDagwl8.js → dist-CuFabXJ8.js} +1 -1
- package/dist-ssg/client/assets/{dist-B_e3vKVI.js → dist-CzScJNYz.js} +1 -1
- package/dist-ssg/client/assets/{dist-C8h2jqYd.js → dist-lNUMJW4A.js} +1 -1
- package/dist-ssg/client/assets/{dist-zooxroSS.js → dist-nDBVtvCj.js} +1 -1
- package/dist-ssg/client/assets/{dist-xlAWlzHU.js → dist-xprslEpB.js} +1 -1
- package/dist-ssg/client/assets/{ghostty-web-MvkhtIaS.js → ghostty-web-D9IXftv-.js} +1 -1
- package/dist-ssg/client/assets/index-BtGAsAtP.css +1 -0
- package/dist-ssg/client/assets/index.ssg-L1BBuH-7.js +1624 -0
- package/dist-ssg/client/assets/{init-CbwghP3k.js → init-C058TQcq.js} +1 -1
- package/dist-ssg/client/assets/trpc-BTuQHFNd.js +1 -0
- package/dist-ssg/client/assets/webworkerAll-ByOBLjhR.js +1 -0
- package/dist-ssg/client/index.ssg.html +2 -2
- package/dist-ssg/server/entry-server.js +1261 -468
- 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-DjDAttzm.js +0 -1646
- 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;
|
|
@@ -32295,10 +32295,18 @@ ZodPipeline.create;
|
|
|
32295
32295
|
var TranslationEngineIdSchema = enumType([
|
|
32296
32296
|
"browser",
|
|
32297
32297
|
"local",
|
|
32298
|
+
"local-ct2",
|
|
32298
32299
|
"openai"
|
|
32299
32300
|
]);
|
|
32300
32301
|
var DEFAULT_TRANSLATION_ENGINE_ID = "browser";
|
|
32301
|
-
|
|
32302
|
+
function isManagedLocalTranslationEngineId(engineId) {
|
|
32303
|
+
return engineId === "local" || engineId === "local-ct2";
|
|
32304
|
+
}
|
|
32305
|
+
enumType([
|
|
32306
|
+
"local",
|
|
32307
|
+
"local-ct2",
|
|
32308
|
+
"openai"
|
|
32309
|
+
]);
|
|
32302
32310
|
var LocalModelDownloadStatusSchema = enumType([
|
|
32303
32311
|
"not-downloaded",
|
|
32304
32312
|
"queued",
|
|
@@ -32311,7 +32319,11 @@ var LocalModelDownloadStatusSchema = enumType([
|
|
|
32311
32319
|
var TranslationDownloadFilePlanSchema = objectType({
|
|
32312
32320
|
path: stringType().min(1),
|
|
32313
32321
|
sizeBytes: numberType().int().nonnegative().optional(),
|
|
32314
|
-
required: booleanType()
|
|
32322
|
+
required: booleanType(),
|
|
32323
|
+
etag: stringType().min(1).optional(),
|
|
32324
|
+
revision: stringType().min(1).optional(),
|
|
32325
|
+
sourceUrl: stringType().min(1).optional(),
|
|
32326
|
+
raw: unknownType().optional()
|
|
32315
32327
|
});
|
|
32316
32328
|
var TranslationDownloadGroupPlanSchema = objectType({
|
|
32317
32329
|
id: stringType().min(1),
|
|
@@ -32320,14 +32332,97 @@ var TranslationDownloadGroupPlanSchema = objectType({
|
|
|
32320
32332
|
profile: stringType().min(1).optional(),
|
|
32321
32333
|
dtype: stringType().min(1).optional(),
|
|
32322
32334
|
estimatedTotalBytes: numberType().int().nonnegative().optional(),
|
|
32335
|
+
baseGroupId: stringType().min(1).optional(),
|
|
32336
|
+
commitHash: stringType().min(1).optional(),
|
|
32337
|
+
shortCommitHash: stringType().min(1).optional(),
|
|
32338
|
+
rootDir: stringType().min(1).optional(),
|
|
32339
|
+
status: LocalModelDownloadStatusSchema.optional(),
|
|
32340
|
+
progress: numberType().min(0).max(1).optional(),
|
|
32341
|
+
bytesDownloaded: numberType().int().nonnegative().optional(),
|
|
32342
|
+
totalBytes: numberType().int().nonnegative().optional(),
|
|
32343
|
+
resumable: booleanType().optional(),
|
|
32344
|
+
error: stringType().optional(),
|
|
32323
32345
|
selectable: booleanType(),
|
|
32324
32346
|
selected: booleanType(),
|
|
32325
32347
|
files: arrayType(TranslationDownloadFilePlanSchema)
|
|
32326
32348
|
});
|
|
32349
|
+
var LocalModelProfileStatusSchema = enumType([
|
|
32350
|
+
"idle",
|
|
32351
|
+
"loading",
|
|
32352
|
+
"ready",
|
|
32353
|
+
"error"
|
|
32354
|
+
]);
|
|
32355
|
+
var LocalModelProfileManifestFileSchema = objectType({
|
|
32356
|
+
path: stringType().min(1),
|
|
32357
|
+
sizeBytes: numberType().int().nonnegative().optional(),
|
|
32358
|
+
required: booleanType(),
|
|
32359
|
+
etag: stringType().min(1).optional(),
|
|
32360
|
+
revision: stringType().min(1).optional(),
|
|
32361
|
+
sourceUrl: stringType().min(1).optional(),
|
|
32362
|
+
raw: unknownType().optional()
|
|
32363
|
+
});
|
|
32364
|
+
var LocalModelProfileManifestGroupSchema = objectType({
|
|
32365
|
+
id: stringType().min(1),
|
|
32366
|
+
baseGroupId: stringType().min(1),
|
|
32367
|
+
label: stringType().min(1),
|
|
32368
|
+
displayLabel: stringType().min(1),
|
|
32369
|
+
description: stringType().optional(),
|
|
32370
|
+
profile: stringType().min(1).optional(),
|
|
32371
|
+
dtype: stringType().min(1).optional(),
|
|
32372
|
+
commitHash: stringType().min(1),
|
|
32373
|
+
shortCommitHash: stringType().min(1),
|
|
32374
|
+
rootDir: stringType().min(1),
|
|
32375
|
+
estimatedTotalBytes: numberType().int().nonnegative().optional(),
|
|
32376
|
+
selectable: booleanType(),
|
|
32377
|
+
files: arrayType(LocalModelProfileManifestFileSchema)
|
|
32378
|
+
});
|
|
32379
|
+
var LocalModelProfileManifestSchema = objectType({
|
|
32380
|
+
modelId: stringType().min(1),
|
|
32381
|
+
source: literalType("huggingface"),
|
|
32382
|
+
endpoint: stringType().default(""),
|
|
32383
|
+
revision: stringType().min(1),
|
|
32384
|
+
commitHash: stringType().min(1),
|
|
32385
|
+
shortCommitHash: stringType().min(1),
|
|
32386
|
+
fetchedAt: numberType().int().nonnegative(),
|
|
32387
|
+
updatedAt: numberType().int().nonnegative(),
|
|
32388
|
+
raw: unknownType().optional(),
|
|
32389
|
+
groups: recordType(stringType(), LocalModelProfileManifestGroupSchema).default({}),
|
|
32390
|
+
groupOrder: arrayType(stringType().min(1)).default([])
|
|
32391
|
+
});
|
|
32392
|
+
var LocalModelLifecycleFileStateSchema = objectType({
|
|
32393
|
+
path: stringType().min(1),
|
|
32394
|
+
sizeBytes: numberType().int().nonnegative().optional(),
|
|
32395
|
+
downloadedBytes: numberType().int().nonnegative().optional(),
|
|
32396
|
+
required: booleanType().default(true),
|
|
32397
|
+
status: LocalModelDownloadStatusSchema.default("not-downloaded"),
|
|
32398
|
+
updatedAt: numberType().int().nonnegative().optional(),
|
|
32399
|
+
error: stringType().optional()
|
|
32400
|
+
});
|
|
32401
|
+
var LocalModelLifecycleGroupStateSchema = objectType({
|
|
32402
|
+
groupId: stringType().min(1),
|
|
32403
|
+
baseGroupId: stringType().min(1).optional(),
|
|
32404
|
+
status: LocalModelDownloadStatusSchema.default("not-downloaded"),
|
|
32405
|
+
rootDir: stringType().min(1).optional(),
|
|
32406
|
+
bytesDownloaded: numberType().int().nonnegative().optional(),
|
|
32407
|
+
totalBytes: numberType().int().nonnegative().optional(),
|
|
32408
|
+
progress: numberType().min(0).max(1).optional(),
|
|
32409
|
+
resumable: booleanType().default(false),
|
|
32410
|
+
error: stringType().optional(),
|
|
32411
|
+
installedAt: numberType().int().nonnegative().optional(),
|
|
32412
|
+
updatedAt: numberType().int().nonnegative().optional(),
|
|
32413
|
+
files: arrayType(LocalModelLifecycleFileStateSchema).default([])
|
|
32414
|
+
});
|
|
32415
|
+
var LocalModelProfileLoadStateSchema = objectType({
|
|
32416
|
+
status: LocalModelProfileStatusSchema.default("idle"),
|
|
32417
|
+
message: stringType().optional(),
|
|
32418
|
+
error: stringType().optional(),
|
|
32419
|
+
updatedAt: numberType().int().nonnegative().optional()
|
|
32420
|
+
});
|
|
32327
32421
|
objectType({
|
|
32328
|
-
engineId:
|
|
32422
|
+
engineId: enumType(["local", "local-ct2"]),
|
|
32329
32423
|
modelId: stringType().min(1),
|
|
32330
32424
|
selectedGroupId: stringType().min(1).optional(),
|
|
32425
|
+
groupId: stringType().min(1).optional(),
|
|
32331
32426
|
status: LocalModelDownloadStatusSchema,
|
|
32332
32427
|
message: stringType(),
|
|
32333
32428
|
progress: numberType().min(0).max(1).optional(),
|
|
@@ -32352,8 +32447,10 @@ var LocalModelAssetPlanSnapshotSchema = objectType({
|
|
|
32352
32447
|
});
|
|
32353
32448
|
objectType({
|
|
32354
32449
|
modelId: stringType().min(1),
|
|
32450
|
+
version: literalType(2).default(2),
|
|
32355
32451
|
status: LocalModelDownloadStatusSchema.default("not-downloaded"),
|
|
32356
32452
|
selected: booleanType().default(false),
|
|
32453
|
+
selectedGroupId: stringType().min(1).optional(),
|
|
32357
32454
|
installedAt: numberType().int().nonnegative().optional(),
|
|
32358
32455
|
updatedAt: numberType().int().nonnegative().optional(),
|
|
32359
32456
|
bytesDownloaded: numberType().int().nonnegative().optional(),
|
|
@@ -32361,6 +32458,9 @@ objectType({
|
|
|
32361
32458
|
progress: numberType().min(0).max(1).optional(),
|
|
32362
32459
|
resumable: booleanType().default(false),
|
|
32363
32460
|
error: stringType().optional(),
|
|
32461
|
+
profileLoad: LocalModelProfileLoadStateSchema.default(LocalModelProfileLoadStateSchema.parse({})),
|
|
32462
|
+
profileManifest: LocalModelProfileManifestSchema.optional(),
|
|
32463
|
+
groupsState: recordType(stringType(), LocalModelLifecycleGroupStateSchema).default({}),
|
|
32364
32464
|
plan: LocalModelAssetPlanSnapshotSchema.optional(),
|
|
32365
32465
|
files: arrayType(objectType({
|
|
32366
32466
|
path: stringType().min(1),
|
|
@@ -32368,6 +32468,72 @@ objectType({
|
|
|
32368
32468
|
downloadedBytes: numberType().int().nonnegative().optional()
|
|
32369
32469
|
})).default([])
|
|
32370
32470
|
});
|
|
32471
|
+
var TranslationEngineDependencyStateSchema = enumType([
|
|
32472
|
+
"installed",
|
|
32473
|
+
"installing",
|
|
32474
|
+
"missing",
|
|
32475
|
+
"error",
|
|
32476
|
+
"not-applicable"
|
|
32477
|
+
]);
|
|
32478
|
+
var TranslationEngineRuntimeStateSchema = enumType([
|
|
32479
|
+
"ready",
|
|
32480
|
+
"probing",
|
|
32481
|
+
"failed",
|
|
32482
|
+
"error",
|
|
32483
|
+
"not-applicable"
|
|
32484
|
+
]);
|
|
32485
|
+
var TranslationEngineAssetStateSchema = enumType([
|
|
32486
|
+
"ready",
|
|
32487
|
+
"missing",
|
|
32488
|
+
"downloading",
|
|
32489
|
+
"error",
|
|
32490
|
+
"not-applicable"
|
|
32491
|
+
]);
|
|
32492
|
+
var TranslationEngineLifecyclePhaseMetaSchema = objectType({
|
|
32493
|
+
message: stringType().optional(),
|
|
32494
|
+
progress: numberType().min(0).max(1).optional(),
|
|
32495
|
+
error: stringType().optional()
|
|
32496
|
+
});
|
|
32497
|
+
var TranslationEngineLifecycleStatusSchema = objectType({
|
|
32498
|
+
dependency: TranslationEngineLifecyclePhaseMetaSchema.extend({ state: TranslationEngineDependencyStateSchema }),
|
|
32499
|
+
runtime: TranslationEngineLifecyclePhaseMetaSchema.extend({ state: TranslationEngineRuntimeStateSchema }),
|
|
32500
|
+
assets: TranslationEngineLifecyclePhaseMetaSchema.extend({ state: TranslationEngineAssetStateSchema }),
|
|
32501
|
+
summary: stringType().optional()
|
|
32502
|
+
});
|
|
32503
|
+
function isTranslationEngineDependencyReady(status) {
|
|
32504
|
+
return status.dependency.state === "installed" || status.dependency.state === "not-applicable";
|
|
32505
|
+
}
|
|
32506
|
+
function isTranslationEngineRuntimeReady(status) {
|
|
32507
|
+
return status.runtime.state === "ready" || status.runtime.state === "not-applicable";
|
|
32508
|
+
}
|
|
32509
|
+
function shouldShowTranslationEngineInstallGate(status) {
|
|
32510
|
+
if (!status) return false;
|
|
32511
|
+
return !isTranslationEngineDependencyReady(status) || !isTranslationEngineRuntimeReady(status);
|
|
32512
|
+
}
|
|
32513
|
+
function getTranslationEngineLifecycleMessage(status) {
|
|
32514
|
+
if (!status) return void 0;
|
|
32515
|
+
return status.summary ?? status.runtime.error ?? status.runtime.message ?? status.dependency.error ?? status.dependency.message ?? status.assets.error ?? status.assets.message;
|
|
32516
|
+
}
|
|
32517
|
+
var TranslationEngineInstallLogStreamSchema = enumType(["stdout", "stderr"]);
|
|
32518
|
+
objectType({
|
|
32519
|
+
stream: TranslationEngineInstallLogStreamSchema,
|
|
32520
|
+
text: stringType()
|
|
32521
|
+
});
|
|
32522
|
+
discriminatedUnionType("type", [
|
|
32523
|
+
objectType({
|
|
32524
|
+
type: literalType("status"),
|
|
32525
|
+
lifecycle: TranslationEngineLifecycleStatusSchema
|
|
32526
|
+
}),
|
|
32527
|
+
objectType({
|
|
32528
|
+
type: literalType("log"),
|
|
32529
|
+
stream: TranslationEngineInstallLogStreamSchema,
|
|
32530
|
+
text: stringType()
|
|
32531
|
+
}),
|
|
32532
|
+
objectType({
|
|
32533
|
+
type: literalType("exit"),
|
|
32534
|
+
lifecycle: TranslationEngineLifecycleStatusSchema
|
|
32535
|
+
})
|
|
32536
|
+
]);
|
|
32371
32537
|
var TranslationOpenAISettingsSchema = objectType({
|
|
32372
32538
|
baseUrl: stringType().default(""),
|
|
32373
32539
|
token: stringType().default(""),
|
|
@@ -32378,9 +32544,15 @@ var TranslationLocalSettingsSchema = objectType({
|
|
|
32378
32544
|
selectedGroupId: stringType().optional(),
|
|
32379
32545
|
hfEndpoint: stringType().default("")
|
|
32380
32546
|
});
|
|
32547
|
+
var TranslationLocalCt2SettingsSchema = objectType({
|
|
32548
|
+
model: stringType().default("ooeoeo/opus-mt-en-zh-ct2-float16"),
|
|
32549
|
+
selectedGroupId: stringType().optional(),
|
|
32550
|
+
hfEndpoint: stringType().default("")
|
|
32551
|
+
});
|
|
32381
32552
|
objectType({
|
|
32382
32553
|
openai: TranslationOpenAISettingsSchema.default(TranslationOpenAISettingsSchema.parse({})),
|
|
32383
|
-
local: TranslationLocalSettingsSchema.default(TranslationLocalSettingsSchema.parse({}))
|
|
32554
|
+
local: TranslationLocalSettingsSchema.default(TranslationLocalSettingsSchema.parse({})),
|
|
32555
|
+
localCt2: TranslationLocalCt2SettingsSchema.default(TranslationLocalCt2SettingsSchema.parse({}))
|
|
32384
32556
|
});
|
|
32385
32557
|
objectType({
|
|
32386
32558
|
engineId: TranslationEngineIdSchema,
|
|
@@ -32402,6 +32574,10 @@ var TranslationEngineProjectSettingsSchema = objectType({
|
|
|
32402
32574
|
model: stringType().min(1).optional(),
|
|
32403
32575
|
selectedGroupId: stringType().min(1).optional()
|
|
32404
32576
|
}).default({}),
|
|
32577
|
+
localCt2: objectType({
|
|
32578
|
+
model: stringType().min(1).optional(),
|
|
32579
|
+
selectedGroupId: stringType().min(1).optional()
|
|
32580
|
+
}).default({}),
|
|
32405
32581
|
openai: objectType({ model: stringType().min(1).optional() }).default({})
|
|
32406
32582
|
}).default({});
|
|
32407
32583
|
var DocumentTranslationConfigSchema = objectType({
|
|
@@ -42699,6 +42875,12 @@ function useConfigSubscription() {
|
|
|
42699
42875
|
onError: callbacks.onError
|
|
42700
42876
|
}), getConfig$1, [], "config.subscribe");
|
|
42701
42877
|
}
|
|
42878
|
+
function useGlobalSettingsSubscription() {
|
|
42879
|
+
return useSubscription((callbacks) => trpcClient.globalSettings.subscribe.subscribe(void 0, {
|
|
42880
|
+
onData: callbacks.onData,
|
|
42881
|
+
onError: callbacks.onError
|
|
42882
|
+
}), void 0, [], "globalSettings.subscribe");
|
|
42883
|
+
}
|
|
42702
42884
|
//#endregion
|
|
42703
42885
|
//#region src/lib/use-opsx.ts
|
|
42704
42886
|
function getOpsxStatusSubscriptionCacheKey(input) {
|
|
@@ -44002,6 +44184,15 @@ var Expand = createLucideIcon("Expand", [
|
|
|
44002
44184
|
key: "u9ee12"
|
|
44003
44185
|
}]
|
|
44004
44186
|
]);
|
|
44187
|
+
var Eye = createLucideIcon("Eye", [["path", {
|
|
44188
|
+
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",
|
|
44189
|
+
key: "1nclc0"
|
|
44190
|
+
}], ["circle", {
|
|
44191
|
+
cx: "12",
|
|
44192
|
+
cy: "12",
|
|
44193
|
+
r: "3",
|
|
44194
|
+
key: "1v7zrd"
|
|
44195
|
+
}]]);
|
|
44005
44196
|
var FileCode2 = createLucideIcon("FileCode2", [
|
|
44006
44197
|
["path", {
|
|
44007
44198
|
d: "M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4",
|
|
@@ -44020,6 +44211,20 @@ var FileCode2 = createLucideIcon("FileCode2", [
|
|
|
44020
44211
|
key: "112psh"
|
|
44021
44212
|
}]
|
|
44022
44213
|
]);
|
|
44214
|
+
var FilePenLine = createLucideIcon("FilePenLine", [
|
|
44215
|
+
["path", {
|
|
44216
|
+
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",
|
|
44217
|
+
key: "142zxg"
|
|
44218
|
+
}],
|
|
44219
|
+
["path", {
|
|
44220
|
+
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",
|
|
44221
|
+
key: "2t3380"
|
|
44222
|
+
}],
|
|
44223
|
+
["path", {
|
|
44224
|
+
d: "M8 18h1",
|
|
44225
|
+
key: "13wk12"
|
|
44226
|
+
}]
|
|
44227
|
+
]);
|
|
44023
44228
|
var FilePlus = createLucideIcon("FilePlus", [
|
|
44024
44229
|
["path", {
|
|
44025
44230
|
d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z",
|
|
@@ -44519,6 +44724,24 @@ var Save = createLucideIcon("Save", [
|
|
|
44519
44724
|
key: "t51u73"
|
|
44520
44725
|
}]
|
|
44521
44726
|
]);
|
|
44727
|
+
var ScrollText = createLucideIcon("ScrollText", [
|
|
44728
|
+
["path", {
|
|
44729
|
+
d: "M15 12h-5",
|
|
44730
|
+
key: "r7krc0"
|
|
44731
|
+
}],
|
|
44732
|
+
["path", {
|
|
44733
|
+
d: "M15 8h-5",
|
|
44734
|
+
key: "1khuty"
|
|
44735
|
+
}],
|
|
44736
|
+
["path", {
|
|
44737
|
+
d: "M19 17V5a2 2 0 0 0-2-2H4",
|
|
44738
|
+
key: "zz82l3"
|
|
44739
|
+
}],
|
|
44740
|
+
["path", {
|
|
44741
|
+
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",
|
|
44742
|
+
key: "1ph1d7"
|
|
44743
|
+
}]
|
|
44744
|
+
]);
|
|
44522
44745
|
var Search = createLucideIcon("Search", [["circle", {
|
|
44523
44746
|
cx: "11",
|
|
44524
44747
|
cy: "11",
|
|
@@ -55153,8 +55376,12 @@ function inertValue(value) {
|
|
|
55153
55376
|
//#region src/components/tooltip.tsx
|
|
55154
55377
|
function Tooltip({ content, children, delay = 180, sideOffset = 8, className }) {
|
|
55155
55378
|
if (!content) return children;
|
|
55379
|
+
const trigger = typeof children.props === "object" && children.props !== null && "disabled" in children.props && Boolean(children.props.disabled) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
55380
|
+
className: "inline-flex max-w-full",
|
|
55381
|
+
children
|
|
55382
|
+
}) : children;
|
|
55156
55383
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TooltipRoot, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TooltipTrigger, {
|
|
55157
|
-
render:
|
|
55384
|
+
render: trigger,
|
|
55158
55385
|
delay
|
|
55159
55386
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TooltipPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TooltipPositioner, {
|
|
55160
55387
|
sideOffset,
|
|
@@ -96609,20 +96836,29 @@ var Button = (0, import_react.forwardRef)(function Button({ variant = "primary",
|
|
|
96609
96836
|
/**
|
|
96610
96837
|
* Compact segmented buttons with single-select behavior.
|
|
96611
96838
|
*/
|
|
96612
|
-
function ButtonGroup({ value, options, onChange, className = "", tone = "default" }) {
|
|
96839
|
+
function ButtonGroup({ value, options, onChange, className = "", tone = "default", presentation = "label" }) {
|
|
96613
96840
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
96614
96841
|
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
96842
|
children: options.map((option, index) => {
|
|
96616
96843
|
const active = option.value === value;
|
|
96617
96844
|
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
|
-
|
|
96845
|
+
const accessibleLabel = option.ariaLabel ?? (typeof option.label === "string" ? option.label : void 0);
|
|
96846
|
+
const tooltipContent = option.tooltip ?? accessibleLabel;
|
|
96847
|
+
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;
|
|
96848
|
+
const button = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
96619
96849
|
type: "button",
|
|
96620
96850
|
disabled: option.disabled,
|
|
96621
96851
|
onClick: () => onChange(option.value),
|
|
96622
96852
|
"aria-pressed": active,
|
|
96623
|
-
|
|
96624
|
-
|
|
96853
|
+
"aria-label": presentation === "icon-only" ? accessibleLabel : void 0,
|
|
96854
|
+
title: presentation === "icon-only" && typeof accessibleLabel === "string" ? accessibleLabel : void 0,
|
|
96855
|
+
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}`,
|
|
96856
|
+
children: content
|
|
96625
96857
|
}, option.value);
|
|
96858
|
+
return tooltipContent ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tooltip, {
|
|
96859
|
+
content: tooltipContent,
|
|
96860
|
+
children: button
|
|
96861
|
+
}, option.value) : button;
|
|
96626
96862
|
})
|
|
96627
96863
|
});
|
|
96628
96864
|
}
|
|
@@ -114041,6 +114277,7 @@ var layoutStyles = String.raw`
|
|
|
114041
114277
|
display: flex;
|
|
114042
114278
|
flex-direction: column;
|
|
114043
114279
|
height: 100%;
|
|
114280
|
+
min-height: 0;
|
|
114044
114281
|
gap: 0.75rem;
|
|
114045
114282
|
}
|
|
114046
114283
|
.fev-sidebar-tabs {
|
|
@@ -114048,6 +114285,7 @@ var layoutStyles = String.raw`
|
|
|
114048
114285
|
}
|
|
114049
114286
|
.fev-sidebar-tree {
|
|
114050
114287
|
display: none;
|
|
114288
|
+
min-height: 0;
|
|
114051
114289
|
}
|
|
114052
114290
|
.fev-editor-wrapper {
|
|
114053
114291
|
display: flex;
|
|
@@ -114061,8 +114299,10 @@ var layoutStyles = String.raw`
|
|
|
114061
114299
|
.fev-layout {
|
|
114062
114300
|
display: grid;
|
|
114063
114301
|
grid-template-columns: minmax(0, 1fr) minmax(240px, clamp(240px, 30%, 420px));
|
|
114302
|
+
grid-template-rows: minmax(0, 1fr);
|
|
114064
114303
|
gap: 1rem;
|
|
114065
114304
|
min-height: 0;
|
|
114305
|
+
overflow: hidden;
|
|
114066
114306
|
}
|
|
114067
114307
|
.fev-sidebar-tabs {
|
|
114068
114308
|
display: none;
|
|
@@ -114070,9 +114310,13 @@ var layoutStyles = String.raw`
|
|
|
114070
114310
|
.fev-sidebar-tree {
|
|
114071
114311
|
display: block;
|
|
114072
114312
|
order: 2;
|
|
114313
|
+
height: 100%;
|
|
114314
|
+
min-height: 0;
|
|
114315
|
+
overflow: hidden;
|
|
114073
114316
|
}
|
|
114074
114317
|
.fev-editor-wrapper {
|
|
114075
114318
|
order: 1;
|
|
114319
|
+
min-height: 0;
|
|
114076
114320
|
}
|
|
114077
114321
|
}
|
|
114078
114322
|
.CodeMirror {
|
|
@@ -114250,7 +114494,8 @@ function FileTree({ entries, selectedPath, onSelect, headerLabel, headerActions,
|
|
|
114250
114494
|
const closeMenu = () => setMenuState(null);
|
|
114251
114495
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ContextMenuWrapper, {
|
|
114252
114496
|
ref: wrapperRef,
|
|
114253
|
-
className: "border-border bg-muted/30 flex h-full flex-col rounded-md border",
|
|
114497
|
+
className: "border-border bg-muted/30 flex h-full min-h-0 flex-col rounded-md border",
|
|
114498
|
+
"data-file-explorer-tree": "",
|
|
114254
114499
|
children: [
|
|
114255
114500
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
114256
114501
|
className: "border-border/50 text-muted-foreground flex items-center justify-between border-b px-3 py-2 text-xs font-medium",
|
|
@@ -114260,7 +114505,8 @@ function FileTree({ entries, selectedPath, onSelect, headerLabel, headerActions,
|
|
|
114260
114505
|
}), headerActions]
|
|
114261
114506
|
}),
|
|
114262
114507
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
114263
|
-
|
|
114508
|
+
"data-file-explorer-tree-scroll": "",
|
|
114509
|
+
className: "scrollbar-thin scrollbar-track-transparent min-h-0 flex-1 overflow-y-auto",
|
|
114264
114510
|
children: entries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
114265
114511
|
className: "text-muted-foreground px-3 py-2 text-xs",
|
|
114266
114512
|
children: "No files yet."
|
|
@@ -114327,7 +114573,7 @@ function FileExplorer({ entries, selectedPath, onSelect, breadcrumbRoot, headerL
|
|
|
114327
114573
|
return sortedEntries.find((entry) => entry.path === selectedPath && entry.type === "file") ?? null;
|
|
114328
114574
|
}, [sortedEntries, selectedPath]);
|
|
114329
114575
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
114330
|
-
className: "@container-[size] h-full",
|
|
114576
|
+
className: "@container-[size] h-full min-h-0 overflow-hidden",
|
|
114331
114577
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: layoutStyles }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
114332
114578
|
className: "fev-layout",
|
|
114333
114579
|
children: [
|
|
@@ -114487,6 +114733,38 @@ function useDocumentTranslationActivation() {
|
|
|
114487
114733
|
};
|
|
114488
114734
|
}
|
|
114489
114735
|
//#endregion
|
|
114736
|
+
//#region src/lib/resolve-document-translation-config.ts
|
|
114737
|
+
function resolveDocumentTranslationConfig(translationConfig, globalSettings) {
|
|
114738
|
+
if (!translationConfig) return void 0;
|
|
114739
|
+
const local = translationConfig.engines?.local ?? {};
|
|
114740
|
+
const localCt2 = translationConfig.engines?.localCt2 ?? {};
|
|
114741
|
+
const openai = translationConfig.engines?.openai ?? {};
|
|
114742
|
+
const resolvedLocalModel = local.model ?? globalSettings?.translationEngines.local?.model;
|
|
114743
|
+
const resolvedLocalSelectedGroupId = local.selectedGroupId ?? globalSettings?.translationEngines.local?.selectedGroupId;
|
|
114744
|
+
const resolvedLocalCt2Model = localCt2.model ?? globalSettings?.translationEngines.localCt2?.model;
|
|
114745
|
+
const resolvedLocalCt2SelectedGroupId = localCt2.selectedGroupId ?? globalSettings?.translationEngines.localCt2?.selectedGroupId;
|
|
114746
|
+
const resolvedOpenAIModel = openai.model ?? globalSettings?.translationEngines.openai?.model;
|
|
114747
|
+
return {
|
|
114748
|
+
...translationConfig,
|
|
114749
|
+
engines: {
|
|
114750
|
+
local: {
|
|
114751
|
+
...local,
|
|
114752
|
+
...resolvedLocalModel ? { model: resolvedLocalModel } : {},
|
|
114753
|
+
...resolvedLocalSelectedGroupId ? { selectedGroupId: resolvedLocalSelectedGroupId } : {}
|
|
114754
|
+
},
|
|
114755
|
+
localCt2: {
|
|
114756
|
+
...localCt2,
|
|
114757
|
+
...resolvedLocalCt2Model ? { model: resolvedLocalCt2Model } : {},
|
|
114758
|
+
...resolvedLocalCt2SelectedGroupId ? { selectedGroupId: resolvedLocalCt2SelectedGroupId } : {}
|
|
114759
|
+
},
|
|
114760
|
+
openai: {
|
|
114761
|
+
...openai,
|
|
114762
|
+
...resolvedOpenAIModel ? { model: resolvedOpenAIModel } : {}
|
|
114763
|
+
}
|
|
114764
|
+
}
|
|
114765
|
+
};
|
|
114766
|
+
}
|
|
114767
|
+
//#endregion
|
|
114490
114768
|
//#region ../browser-translator/dist/index.mjs
|
|
114491
114769
|
async function scanBrowserTranslationSupportTable(options) {
|
|
114492
114770
|
const translator = (options.win ?? window).Translator;
|
|
@@ -131170,6 +131448,56 @@ function createProjectionContext(lookup, annotations, projections) {
|
|
|
131170
131448
|
};
|
|
131171
131449
|
}
|
|
131172
131450
|
//#endregion
|
|
131451
|
+
//#region ../core/src/translation-language-pair.ts
|
|
131452
|
+
var OPUS_MT_DIRECTION_PATTERN = /^opus-mt-([a-z]{2,3})-([a-z]{2,3})$/i;
|
|
131453
|
+
var OPUS_MT_CT2_SUFFIX_PATTERN = /-(?:ct2|ctranslate2)(?:-[a-z0-9]+)*$/i;
|
|
131454
|
+
function inferLocalDirectionalModelLanguagePair(model) {
|
|
131455
|
+
const modelName = model?.trim().split("/").pop()?.replace(OPUS_MT_CT2_SUFFIX_PATTERN, "");
|
|
131456
|
+
if (!modelName) return null;
|
|
131457
|
+
const match = OPUS_MT_DIRECTION_PATTERN.exec(modelName);
|
|
131458
|
+
if (!match) return null;
|
|
131459
|
+
const [, sourceLanguage, targetLanguage] = match;
|
|
131460
|
+
if (!sourceLanguage || !targetLanguage) return null;
|
|
131461
|
+
return {
|
|
131462
|
+
sourceLanguage: normalizeLanguageCode(sourceLanguage),
|
|
131463
|
+
targetLanguage: normalizeLanguageCode(targetLanguage)
|
|
131464
|
+
};
|
|
131465
|
+
}
|
|
131466
|
+
function checkLocalDirectionalModelLanguagePair(input) {
|
|
131467
|
+
const expected = inferLocalDirectionalModelLanguagePair(input.model);
|
|
131468
|
+
if (!expected) return { supported: true };
|
|
131469
|
+
if (!areCompatibleLanguageTags(expected.targetLanguage, input.targetLanguage)) return {
|
|
131470
|
+
supported: false,
|
|
131471
|
+
expected,
|
|
131472
|
+
message: `Selected local model supports ${formatLanguagePair(expected)}, but document translation is configured for target ${input.targetLanguage}.`
|
|
131473
|
+
};
|
|
131474
|
+
if (input.sourceLanguage && !areCompatibleLanguageTags(expected.sourceLanguage, input.sourceLanguage)) return {
|
|
131475
|
+
supported: false,
|
|
131476
|
+
expected,
|
|
131477
|
+
message: `Selected local model supports ${formatLanguagePair(expected)}, but document segment was detected as ${input.sourceLanguage} -> ${input.targetLanguage}.`
|
|
131478
|
+
};
|
|
131479
|
+
return {
|
|
131480
|
+
supported: true,
|
|
131481
|
+
expected
|
|
131482
|
+
};
|
|
131483
|
+
}
|
|
131484
|
+
function areCompatibleLanguageTags(expected, actual) {
|
|
131485
|
+
const expectedNormalized = normalizeLanguageTag$1(expected);
|
|
131486
|
+
const actualNormalized = normalizeLanguageTag$1(actual);
|
|
131487
|
+
if (!expectedNormalized || !actualNormalized) return false;
|
|
131488
|
+
if (expectedNormalized === actualNormalized) return true;
|
|
131489
|
+
return expectedNormalized.split("-")[0] === actualNormalized.split("-")[0];
|
|
131490
|
+
}
|
|
131491
|
+
function normalizeLanguageCode(language) {
|
|
131492
|
+
return language.trim().toLowerCase().replace(/_/g, "-");
|
|
131493
|
+
}
|
|
131494
|
+
function normalizeLanguageTag$1(language) {
|
|
131495
|
+
return normalizeLanguageCode(language);
|
|
131496
|
+
}
|
|
131497
|
+
function formatLanguagePair(pair) {
|
|
131498
|
+
return `${pair.sourceLanguage} -> ${pair.targetLanguage}`;
|
|
131499
|
+
}
|
|
131500
|
+
//#endregion
|
|
131173
131501
|
//#region ../../node_modules/.pnpm/remark-gfm@4.0.1/node_modules/remark-gfm/lib/index.js
|
|
131174
131502
|
/**
|
|
131175
131503
|
* @import {Root} from 'mdast'
|
|
@@ -135698,6 +136026,43 @@ function escapeAttributeValue(value) {
|
|
|
135698
136026
|
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
135699
136027
|
}
|
|
135700
136028
|
//#endregion
|
|
136029
|
+
//#region src/lib/translation-adaptive-concurrency-log.ts
|
|
136030
|
+
var GLOBAL_STORAGE_KEY = "__OPENSPECUI_TRANSLATION_ADAPTIVE_CONCURRENCY_LOGS__";
|
|
136031
|
+
var MAX_LOG_AGE_MS = 1800 * 1e3;
|
|
136032
|
+
var MAX_LOG_ENTRIES = 256;
|
|
136033
|
+
var DEFAULT_SAMPLE_SIZE = 8;
|
|
136034
|
+
function createTranslationAdaptiveConcurrencyScopeKey(input) {
|
|
136035
|
+
return JSON.stringify({
|
|
136036
|
+
engineId: input.engineId,
|
|
136037
|
+
engineVersion: input.engineVersion ?? null,
|
|
136038
|
+
model: input.model ?? null,
|
|
136039
|
+
selectedGroupId: input.selectedGroupId ?? null,
|
|
136040
|
+
sourceLanguage: input.sourceLanguage.trim().toLowerCase(),
|
|
136041
|
+
targetLanguage: input.targetLanguage.trim().toLowerCase(),
|
|
136042
|
+
translatorContractVersion: input.translatorContractVersion
|
|
136043
|
+
});
|
|
136044
|
+
}
|
|
136045
|
+
function appendTranslationAdaptiveConcurrencyLog(entry) {
|
|
136046
|
+
const store = getTranslationAdaptiveConcurrencyLogStore();
|
|
136047
|
+
store.entries.push(entry);
|
|
136048
|
+
cleanupTranslationAdaptiveConcurrencyLogs(store);
|
|
136049
|
+
}
|
|
136050
|
+
function readRecentTranslationAdaptiveConcurrencyLogs(input = {}) {
|
|
136051
|
+
const store = getTranslationAdaptiveConcurrencyLogStore();
|
|
136052
|
+
cleanupTranslationAdaptiveConcurrencyLogs(store);
|
|
136053
|
+
return (input.scopeKey ? store.entries.filter((entry) => entry.scopeKey === input.scopeKey) : store.entries).slice(-Math.max(1, input.limit ?? DEFAULT_SAMPLE_SIZE));
|
|
136054
|
+
}
|
|
136055
|
+
function getTranslationAdaptiveConcurrencyLogStore() {
|
|
136056
|
+
const globalScope = globalThis;
|
|
136057
|
+
if (!globalScope[GLOBAL_STORAGE_KEY]) globalScope[GLOBAL_STORAGE_KEY] = { entries: [] };
|
|
136058
|
+
return globalScope[GLOBAL_STORAGE_KEY];
|
|
136059
|
+
}
|
|
136060
|
+
function cleanupTranslationAdaptiveConcurrencyLogs(store) {
|
|
136061
|
+
const cutoff = Date.now() - MAX_LOG_AGE_MS;
|
|
136062
|
+
if (store.entries.length === 0) return;
|
|
136063
|
+
store.entries = store.entries.filter((entry) => entry.recordedAt >= cutoff).slice(-MAX_LOG_ENTRIES);
|
|
136064
|
+
}
|
|
136065
|
+
//#endregion
|
|
135701
136066
|
//#region ../search/src/engine.ts
|
|
135702
136067
|
function normalizeText(input) {
|
|
135703
136068
|
return input.toLowerCase().replace(/\s+/g, " ").trim();
|
|
@@ -136148,7 +136513,7 @@ function createBrowserTranslationExecution() {
|
|
|
136148
136513
|
factory: createBrowserTranslatorFactory(),
|
|
136149
136514
|
cacheIdentity: {
|
|
136150
136515
|
engineId: DEFAULT_TRANSLATION_ENGINE_ID,
|
|
136151
|
-
translatorContractVersion:
|
|
136516
|
+
translatorContractVersion: 3
|
|
136152
136517
|
}
|
|
136153
136518
|
};
|
|
136154
136519
|
}
|
|
@@ -136157,6 +136522,7 @@ var DOCUMENT_LANGUAGE_CONFIDENCE_THRESHOLD = .45;
|
|
|
136157
136522
|
var SEGMENT_LANGUAGE_CONFIDENCE_THRESHOLD = .62;
|
|
136158
136523
|
var TRANSLATION_DISPLAY_POLICY_VERSION = 2;
|
|
136159
136524
|
var BROWSER_SOURCE_LANGUAGE_ORDER = new Map(SUPPORTED_TRANSLATION_LANGUAGES.map((language, index) => [language.code, index]));
|
|
136525
|
+
var SUPPORTED_TRANSLATION_LANGUAGE_CODES = new Set(SUPPORTED_TRANSLATION_LANGUAGES.map((language) => language.code));
|
|
136160
136526
|
function isBrowserTranslationSupported() {
|
|
136161
136527
|
return typeof window !== "undefined" && !!window.Translator;
|
|
136162
136528
|
}
|
|
@@ -136374,14 +136740,20 @@ function mergeBrowserSupportRows(rows, row) {
|
|
|
136374
136740
|
}
|
|
136375
136741
|
function sortBrowserSupportRows(rows) {
|
|
136376
136742
|
return [...rows].sort((left, right) => {
|
|
136377
|
-
const leftOrder =
|
|
136378
|
-
const rightOrder =
|
|
136743
|
+
const leftOrder = getBrowserSourceLanguageOrder(left.sourceLanguage) ?? Number.MAX_SAFE_INTEGER;
|
|
136744
|
+
const rightOrder = getBrowserSourceLanguageOrder(right.sourceLanguage) ?? Number.MAX_SAFE_INTEGER;
|
|
136379
136745
|
if (leftOrder !== rightOrder) return leftOrder - rightOrder;
|
|
136380
136746
|
const targetDelta = left.targetLanguage.localeCompare(right.targetLanguage);
|
|
136381
136747
|
if (targetDelta !== 0) return targetDelta;
|
|
136382
136748
|
return left.sourceLanguage.localeCompare(right.sourceLanguage);
|
|
136383
136749
|
});
|
|
136384
136750
|
}
|
|
136751
|
+
function getBrowserSourceLanguageOrder(sourceLanguage) {
|
|
136752
|
+
return isSupportedTranslationLanguageCode(sourceLanguage) ? BROWSER_SOURCE_LANGUAGE_ORDER.get(sourceLanguage) : void 0;
|
|
136753
|
+
}
|
|
136754
|
+
function isSupportedTranslationLanguageCode(language) {
|
|
136755
|
+
return SUPPORTED_TRANSLATION_LANGUAGE_CODES.has(language);
|
|
136756
|
+
}
|
|
136385
136757
|
async function translateMarkdownDocumentProgressively(args, onPatch) {
|
|
136386
136758
|
const segments = extractTranslatableSegments(args.markdown);
|
|
136387
136759
|
if (segments.length === 0) return {
|
|
@@ -136391,9 +136763,9 @@ async function translateMarkdownDocumentProgressively(args, onPatch) {
|
|
|
136391
136763
|
};
|
|
136392
136764
|
const engine = args.engine ?? createBrowserTranslationExecution();
|
|
136393
136765
|
const languageDetection = await createSourceLanguageDetectionSession(args.markdown, args.signal);
|
|
136394
|
-
const
|
|
136766
|
+
const translatedSegments = [...segments];
|
|
136767
|
+
const pendingJobsBySourceLanguage = /* @__PURE__ */ new Map();
|
|
136395
136768
|
try {
|
|
136396
|
-
const translatedSegments = [];
|
|
136397
136769
|
for (const [segmentIndex, segment] of segments.entries()) {
|
|
136398
136770
|
throwIfAborted(args.signal);
|
|
136399
136771
|
const sourceLanguage = await languageDetection.detectSegmentLanguage(segment.translatorInput, args.signal);
|
|
@@ -136407,7 +136779,7 @@ async function translateMarkdownDocumentProgressively(args, onPatch) {
|
|
|
136407
136779
|
targetLanguage: args.targetLanguage,
|
|
136408
136780
|
status: "translated"
|
|
136409
136781
|
};
|
|
136410
|
-
translatedSegments
|
|
136782
|
+
translatedSegments[segmentIndex] = translatedSegment;
|
|
136411
136783
|
onPatch({
|
|
136412
136784
|
segmentIndex,
|
|
136413
136785
|
segment: translatedSegment
|
|
@@ -136420,33 +136792,27 @@ async function translateMarkdownDocumentProgressively(args, onPatch) {
|
|
|
136420
136792
|
targetLanguage: args.targetLanguage
|
|
136421
136793
|
}) : null;
|
|
136422
136794
|
if (cachedSegment) {
|
|
136423
|
-
translatedSegments
|
|
136795
|
+
translatedSegments[segmentIndex] = cachedSegment;
|
|
136424
136796
|
onPatch({
|
|
136425
136797
|
segmentIndex,
|
|
136426
136798
|
segment: cachedSegment
|
|
136427
136799
|
});
|
|
136428
136800
|
continue;
|
|
136429
136801
|
}
|
|
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,
|
|
136802
|
+
const pendingJob = {
|
|
136803
|
+
segmentIndex,
|
|
136804
|
+
segment,
|
|
136440
136805
|
sourceLanguage,
|
|
136441
|
-
|
|
136442
|
-
|
|
136806
|
+
cacheKey,
|
|
136807
|
+
protectedInput: segment.placeholderProtocol ? {
|
|
136808
|
+
text: segment.translatorInput,
|
|
136809
|
+
restore: (output) => output
|
|
136810
|
+
} : protectTranslatorInput(segment.translatorInput),
|
|
136811
|
+
estimatedTokens: estimateTranslationTokens(segment.translatorInput)
|
|
136443
136812
|
};
|
|
136444
|
-
|
|
136445
|
-
|
|
136446
|
-
|
|
136447
|
-
segmentIndex,
|
|
136448
|
-
segment: translatedSegment
|
|
136449
|
-
});
|
|
136813
|
+
const pendingJobs = pendingJobsBySourceLanguage.get(sourceLanguage) ?? [];
|
|
136814
|
+
pendingJobs.push(pendingJob);
|
|
136815
|
+
pendingJobsBySourceLanguage.set(sourceLanguage, pendingJobs);
|
|
136450
136816
|
} catch (error) {
|
|
136451
136817
|
if (args.signal.aborted) throw error;
|
|
136452
136818
|
const failedSegment = {
|
|
@@ -136456,13 +136822,23 @@ async function translateMarkdownDocumentProgressively(args, onPatch) {
|
|
|
136456
136822
|
status: "error",
|
|
136457
136823
|
error: getErrorMessage(error)
|
|
136458
136824
|
};
|
|
136459
|
-
translatedSegments
|
|
136825
|
+
translatedSegments[segmentIndex] = failedSegment;
|
|
136460
136826
|
onPatch({
|
|
136461
136827
|
segmentIndex,
|
|
136462
136828
|
segment: failedSegment
|
|
136463
136829
|
});
|
|
136464
136830
|
}
|
|
136465
136831
|
}
|
|
136832
|
+
await Promise.all([...pendingJobsBySourceLanguage.entries()].map(([sourceLanguage, jobs]) => translatePendingJobsBySourceLanguage({
|
|
136833
|
+
engine,
|
|
136834
|
+
sourceLanguage,
|
|
136835
|
+
targetLanguage: args.targetLanguage,
|
|
136836
|
+
signal: args.signal,
|
|
136837
|
+
cache: args.cache,
|
|
136838
|
+
jobs,
|
|
136839
|
+
translatedSegments,
|
|
136840
|
+
onPatch
|
|
136841
|
+
})));
|
|
136466
136842
|
return {
|
|
136467
136843
|
segments: translatedSegments,
|
|
136468
136844
|
displayMode: args.displayMode,
|
|
@@ -136470,24 +136846,247 @@ async function translateMarkdownDocumentProgressively(args, onPatch) {
|
|
|
136470
136846
|
targetLanguage: args.targetLanguage
|
|
136471
136847
|
};
|
|
136472
136848
|
} finally {
|
|
136473
|
-
translatorBySourceLanguage.forEach((translator) => translator.destroy?.());
|
|
136474
136849
|
languageDetection.destroy();
|
|
136475
136850
|
}
|
|
136476
136851
|
}
|
|
136477
|
-
async function
|
|
136478
|
-
const
|
|
136479
|
-
|
|
136480
|
-
|
|
136481
|
-
|
|
136482
|
-
|
|
136483
|
-
|
|
136852
|
+
async function translatePendingJobsBySourceLanguage(input) {
|
|
136853
|
+
const markJobsError = (jobs, message) => {
|
|
136854
|
+
for (const job of jobs) {
|
|
136855
|
+
const failedSegment = {
|
|
136856
|
+
...job.segment,
|
|
136857
|
+
sourceLanguage: job.sourceLanguage,
|
|
136858
|
+
targetLanguage: input.targetLanguage,
|
|
136859
|
+
status: "error",
|
|
136860
|
+
error: message
|
|
136861
|
+
};
|
|
136862
|
+
input.translatedSegments[job.segmentIndex] = failedSegment;
|
|
136863
|
+
input.onPatch({
|
|
136864
|
+
segmentIndex: job.segmentIndex,
|
|
136865
|
+
segment: failedSegment
|
|
136866
|
+
});
|
|
136867
|
+
}
|
|
136868
|
+
};
|
|
136869
|
+
const unsupportedLanguagePairMessage = getUnsupportedEngineLanguagePairMessage({
|
|
136870
|
+
engine: input.engine,
|
|
136871
|
+
sourceLanguage: input.sourceLanguage,
|
|
136872
|
+
targetLanguage: input.targetLanguage
|
|
136484
136873
|
});
|
|
136485
|
-
|
|
136486
|
-
|
|
136874
|
+
if (unsupportedLanguagePairMessage) {
|
|
136875
|
+
markJobsError(input.jobs, unsupportedLanguagePairMessage);
|
|
136876
|
+
return;
|
|
136877
|
+
}
|
|
136878
|
+
const batches = packTranslationJobs(input.jobs);
|
|
136879
|
+
if (batches.length === 0) return;
|
|
136880
|
+
const maxConcurrency = Math.min(6, batches.length);
|
|
136881
|
+
const scopeKey = createTranslationAdaptiveConcurrencyScopeKey({
|
|
136882
|
+
engineId: input.engine.cacheIdentity.engineId,
|
|
136883
|
+
engineVersion: input.engine.cacheIdentity.engineVersion,
|
|
136884
|
+
model: input.engine.cacheIdentity.model,
|
|
136885
|
+
selectedGroupId: input.engine.cacheIdentity.selectedGroupId,
|
|
136886
|
+
sourceLanguage: input.sourceLanguage,
|
|
136887
|
+
targetLanguage: input.targetLanguage,
|
|
136888
|
+
translatorContractVersion: input.engine.cacheIdentity.translatorContractVersion
|
|
136889
|
+
});
|
|
136890
|
+
let desiredConcurrency = 1;
|
|
136891
|
+
let nextBatchIndex = 0;
|
|
136892
|
+
let activeWorkers = 0;
|
|
136893
|
+
let completedBatches = 0;
|
|
136894
|
+
const workerPromises = /* @__PURE__ */ new Set();
|
|
136895
|
+
const startWorkersToDesired = () => {
|
|
136896
|
+
while (activeWorkers < desiredConcurrency && nextBatchIndex < batches.length && !input.signal.aborted) startWorker();
|
|
136897
|
+
};
|
|
136898
|
+
const maybeGrowConcurrency = () => {
|
|
136899
|
+
if (desiredConcurrency >= maxConcurrency) return;
|
|
136900
|
+
const recentLogs = readRecentTranslationAdaptiveConcurrencyLogs({
|
|
136901
|
+
scopeKey,
|
|
136902
|
+
limit: Math.max(4, desiredConcurrency * 2)
|
|
136903
|
+
});
|
|
136904
|
+
if (desiredConcurrency === 1) {
|
|
136905
|
+
if (completedBatches >= 1 && batches.length > 1 && recentLogs.length > 0) {
|
|
136906
|
+
desiredConcurrency = 2;
|
|
136907
|
+
startWorkersToDesired();
|
|
136908
|
+
}
|
|
136909
|
+
return;
|
|
136910
|
+
}
|
|
136911
|
+
if (completedBatches < desiredConcurrency) return;
|
|
136912
|
+
if (recentLogs.length < desiredConcurrency * 2) return;
|
|
136913
|
+
const window = recentLogs.slice(-desiredConcurrency * 2);
|
|
136914
|
+
const split = Math.max(1, Math.floor(window.length / 2));
|
|
136915
|
+
const earlierThroughput = summarizeTranslationLogThroughput(window.slice(0, split));
|
|
136916
|
+
const laterThroughput = summarizeTranslationLogThroughput(window.slice(split));
|
|
136917
|
+
if (earlierThroughput > 0 && laterThroughput >= earlierThroughput * 1.08) {
|
|
136918
|
+
desiredConcurrency = Math.min(maxConcurrency, desiredConcurrency + 1);
|
|
136919
|
+
startWorkersToDesired();
|
|
136920
|
+
}
|
|
136921
|
+
};
|
|
136922
|
+
const applyBatchResult = async (batch, outputs) => {
|
|
136923
|
+
for (const [offset, job] of batch.jobs.entries()) {
|
|
136924
|
+
const target = outputs[offset] ?? "";
|
|
136925
|
+
const restoredTarget = job.segment.placeholderProtocol ? restoreTranslatedPlaceholderFragment(target, job.segment.placeholderProtocol) : { target: job.protectedInput.restore(target).trim() };
|
|
136926
|
+
const translatedSegment = {
|
|
136927
|
+
...job.segment,
|
|
136928
|
+
...restoredTarget,
|
|
136929
|
+
sourceLanguage: job.sourceLanguage,
|
|
136930
|
+
targetLanguage: input.targetLanguage,
|
|
136931
|
+
status: "translated"
|
|
136932
|
+
};
|
|
136933
|
+
input.translatedSegments[job.segmentIndex] = translatedSegment;
|
|
136934
|
+
if (job.cacheKey) writeCachedTranslationSegment(input.cache, job.cacheKey, translatedSegment);
|
|
136935
|
+
input.onPatch({
|
|
136936
|
+
segmentIndex: job.segmentIndex,
|
|
136937
|
+
segment: translatedSegment
|
|
136938
|
+
});
|
|
136939
|
+
}
|
|
136940
|
+
};
|
|
136941
|
+
const markBatchError = (batch, error) => {
|
|
136942
|
+
markJobsError(batch.jobs, getErrorMessage(error));
|
|
136943
|
+
};
|
|
136944
|
+
const startWorker = () => {
|
|
136945
|
+
if (input.signal.aborted || nextBatchIndex >= batches.length) return;
|
|
136946
|
+
activeWorkers += 1;
|
|
136947
|
+
let workerPromise;
|
|
136948
|
+
workerPromise = (async () => {
|
|
136949
|
+
let translator = null;
|
|
136950
|
+
try {
|
|
136951
|
+
translator = await input.engine.factory.create({
|
|
136952
|
+
sourceLanguage: input.sourceLanguage,
|
|
136953
|
+
targetLanguage: input.targetLanguage,
|
|
136954
|
+
signal: input.signal
|
|
136955
|
+
});
|
|
136956
|
+
while (!input.signal.aborted) {
|
|
136957
|
+
const batchIndex = nextBatchIndex;
|
|
136958
|
+
if (batchIndex >= batches.length) break;
|
|
136959
|
+
nextBatchIndex += 1;
|
|
136960
|
+
const batch = batches[batchIndex];
|
|
136961
|
+
const startedAt = getCurrentTimeMs();
|
|
136962
|
+
try {
|
|
136963
|
+
await applyBatchResult(batch, await collectBatchTranslationOutputs(translator.batchTranslate(batch.jobs.map((job) => job.protectedInput.text), { signal: input.signal }), batch.jobs.length));
|
|
136964
|
+
completedBatches += 1;
|
|
136965
|
+
const elapsedMs = Math.max(1, getCurrentTimeMs() - startedAt);
|
|
136966
|
+
appendTranslationAdaptiveConcurrencyLog({
|
|
136967
|
+
scopeKey,
|
|
136968
|
+
recordedAt: Date.now(),
|
|
136969
|
+
engineId: input.engine.cacheIdentity.engineId,
|
|
136970
|
+
engineVersion: input.engine.cacheIdentity.engineVersion,
|
|
136971
|
+
model: input.engine.cacheIdentity.model,
|
|
136972
|
+
selectedGroupId: input.engine.cacheIdentity.selectedGroupId,
|
|
136973
|
+
sourceLanguage: input.sourceLanguage,
|
|
136974
|
+
targetLanguage: input.targetLanguage,
|
|
136975
|
+
batchIndex,
|
|
136976
|
+
batchSize: batch.jobs.length,
|
|
136977
|
+
estimatedTokens: batch.estimatedTokens,
|
|
136978
|
+
elapsedMs,
|
|
136979
|
+
throughputTokensPerMs: batch.estimatedTokens / elapsedMs,
|
|
136980
|
+
desiredConcurrency,
|
|
136981
|
+
activeWorkers,
|
|
136982
|
+
maxConcurrency
|
|
136983
|
+
});
|
|
136984
|
+
maybeGrowConcurrency();
|
|
136985
|
+
} catch (error) {
|
|
136986
|
+
if (input.signal.aborted) throw error;
|
|
136987
|
+
markBatchError(batch, error);
|
|
136988
|
+
}
|
|
136989
|
+
}
|
|
136990
|
+
} finally {
|
|
136991
|
+
translator?.destroy?.();
|
|
136992
|
+
}
|
|
136993
|
+
})().finally(() => {
|
|
136994
|
+
activeWorkers -= 1;
|
|
136995
|
+
workerPromises.delete(workerPromise);
|
|
136996
|
+
startWorkersToDesired();
|
|
136997
|
+
});
|
|
136998
|
+
workerPromises.add(workerPromise);
|
|
136999
|
+
};
|
|
137000
|
+
startWorkersToDesired();
|
|
137001
|
+
while (workerPromises.size > 0) await Promise.race(workerPromises);
|
|
137002
|
+
}
|
|
137003
|
+
function getUnsupportedEngineLanguagePairMessage(input) {
|
|
137004
|
+
if (!isManagedLocalTranslationEngineId(input.engine.cacheIdentity.engineId)) return null;
|
|
137005
|
+
const directionCheck = checkLocalDirectionalModelLanguagePair({
|
|
137006
|
+
model: input.engine.cacheIdentity.model,
|
|
137007
|
+
sourceLanguage: input.sourceLanguage,
|
|
137008
|
+
targetLanguage: input.targetLanguage
|
|
137009
|
+
});
|
|
137010
|
+
if (directionCheck.supported) return null;
|
|
137011
|
+
return directionCheck.message ?? "Selected local model does not support the detected translation direction.";
|
|
137012
|
+
}
|
|
137013
|
+
function summarizeTranslationLogThroughput(logs) {
|
|
137014
|
+
if (logs.length === 0) return 0;
|
|
137015
|
+
const totalTokens = logs.reduce((total, log) => total + log.estimatedTokens, 0);
|
|
137016
|
+
const totalElapsedMs = logs.reduce((total, log) => total + log.elapsedMs, 0);
|
|
137017
|
+
if (totalTokens <= 0 || totalElapsedMs <= 0) return 0;
|
|
137018
|
+
return totalTokens / totalElapsedMs;
|
|
137019
|
+
}
|
|
137020
|
+
function packTranslationJobs(jobs) {
|
|
137021
|
+
if (jobs.length === 0) return [];
|
|
137022
|
+
const averageTokens = jobs.reduce((total, job) => total + job.estimatedTokens, 0) / Math.max(1, jobs.length);
|
|
137023
|
+
const targetTokens = Math.max(1, Math.round(averageTokens * 6));
|
|
137024
|
+
const batches = [];
|
|
137025
|
+
let currentJobs = [];
|
|
137026
|
+
let currentTokens = 0;
|
|
137027
|
+
const flush = () => {
|
|
137028
|
+
if (currentJobs.length === 0) return;
|
|
137029
|
+
batches.push({
|
|
137030
|
+
jobs: currentJobs,
|
|
137031
|
+
estimatedTokens: currentTokens
|
|
137032
|
+
});
|
|
137033
|
+
currentJobs = [];
|
|
137034
|
+
currentTokens = 0;
|
|
137035
|
+
};
|
|
137036
|
+
for (const job of jobs) {
|
|
137037
|
+
if (currentJobs.length === 0) {
|
|
137038
|
+
currentJobs = [job];
|
|
137039
|
+
currentTokens = job.estimatedTokens;
|
|
137040
|
+
continue;
|
|
137041
|
+
}
|
|
137042
|
+
const nextTokens = currentTokens + job.estimatedTokens;
|
|
137043
|
+
if (nextTokens <= targetTokens) {
|
|
137044
|
+
currentJobs.push(job);
|
|
137045
|
+
currentTokens = nextTokens;
|
|
137046
|
+
continue;
|
|
137047
|
+
}
|
|
137048
|
+
const withoutDelta = Math.abs(currentTokens - targetTokens);
|
|
137049
|
+
if (Math.abs(nextTokens - targetTokens) <= withoutDelta) {
|
|
137050
|
+
currentJobs.push(job);
|
|
137051
|
+
currentTokens = nextTokens;
|
|
137052
|
+
flush();
|
|
137053
|
+
continue;
|
|
137054
|
+
}
|
|
137055
|
+
flush();
|
|
137056
|
+
currentJobs = [job];
|
|
137057
|
+
currentTokens = job.estimatedTokens;
|
|
137058
|
+
}
|
|
137059
|
+
flush();
|
|
137060
|
+
return batches;
|
|
137061
|
+
}
|
|
137062
|
+
async function collectBatchTranslationOutputs(stream, expectedCount) {
|
|
137063
|
+
const outputs = /* @__PURE__ */ new Map();
|
|
137064
|
+
for await (const item of stream) {
|
|
137065
|
+
if (item.index < 0 || item.index >= expectedCount) throw new Error(`Translator yielded output for unexpected index ${item.index}.`);
|
|
137066
|
+
if (!outputs.has(item.index)) outputs.set(item.index, item.output);
|
|
137067
|
+
}
|
|
137068
|
+
if (outputs.size !== expectedCount) throw new Error(`Translator returned ${outputs.size} outputs for ${expectedCount} inputs.`);
|
|
137069
|
+
return Array.from({ length: expectedCount }, (_, index) => outputs.get(index) ?? "");
|
|
137070
|
+
}
|
|
137071
|
+
function estimateTranslationTokens(input) {
|
|
137072
|
+
const trimmed = input.trim();
|
|
137073
|
+
if (!trimmed) return 1;
|
|
137074
|
+
const segmenter = getTokenSegmenter();
|
|
137075
|
+
if (!segmenter) return Math.max(1, trimmed.split(/\s+/).filter(Boolean).length);
|
|
137076
|
+
let count = 0;
|
|
137077
|
+
for (const segment of segmenter.segment(trimmed)) if (segment.isWordLike ?? segment.segment.trim().length > 0) count += 1;
|
|
137078
|
+
return Math.max(1, count);
|
|
137079
|
+
}
|
|
137080
|
+
function getTokenSegmenter() {
|
|
137081
|
+
if (typeof Intl === "undefined" || typeof Intl.Segmenter !== "function") return null;
|
|
137082
|
+
try {
|
|
137083
|
+
return new Intl.Segmenter(void 0, { granularity: "word" });
|
|
137084
|
+
} catch {
|
|
137085
|
+
return null;
|
|
137086
|
+
}
|
|
136487
137087
|
}
|
|
136488
|
-
|
|
136489
|
-
|
|
136490
|
-
throw new Error("Translator returned no batch output.");
|
|
137088
|
+
function getCurrentTimeMs() {
|
|
137089
|
+
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
136491
137090
|
}
|
|
136492
137091
|
async function createSourceLanguageDetectionSession(markdown, signal) {
|
|
136493
137092
|
const detectorFactory = window.LanguageDetector;
|
|
@@ -136963,87 +137562,10 @@ function getErrorMessage(error) {
|
|
|
136963
137562
|
return error instanceof Error ? error.message : "Unknown translation error.";
|
|
136964
137563
|
}
|
|
136965
137564
|
//#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
137565
|
//#region ../core/src/local-download-profiles.ts
|
|
137044
137566
|
function selectLocalDownloadGroup(plan, selectedGroupId) {
|
|
137045
137567
|
if (!plan?.groups?.length) return null;
|
|
137046
|
-
return (selectedGroupId ? plan.groups.find((group) => group.id === selectedGroupId
|
|
137568
|
+
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
137569
|
}
|
|
137048
137570
|
function selectSmallestSelectableGroup(groups) {
|
|
137049
137571
|
return groups.filter((group) => group.selectable && group.estimatedTotalBytes !== void 0).sort((left, right) => (left.estimatedTotalBytes ?? 0) - (right.estimatedTotalBytes ?? 0))[0] ?? null;
|
|
@@ -137102,25 +137624,37 @@ function projectTranslateServiceStatus(input) {
|
|
|
137102
137624
|
};
|
|
137103
137625
|
}
|
|
137104
137626
|
}
|
|
137105
|
-
if (input.
|
|
137627
|
+
if (input.engineLifecycleLoading || input.engineLifecycle !== void 0) {
|
|
137628
|
+
if (input.engineLifecycleLoading || !input.engineLifecycle) return {
|
|
137629
|
+
state: "checking",
|
|
137630
|
+
engineId: input.engineId,
|
|
137631
|
+
message: "Checking translation engine runtime."
|
|
137632
|
+
};
|
|
137633
|
+
if (shouldShowTranslationEngineInstallGate(input.engineLifecycle)) return {
|
|
137634
|
+
state: "unavailable",
|
|
137635
|
+
engineId: input.engineId,
|
|
137636
|
+
message: getTranslationEngineLifecycleMessage(input.engineLifecycle) ?? "Translation engine runtime is not ready."
|
|
137637
|
+
};
|
|
137638
|
+
}
|
|
137639
|
+
if (isManagedLocalTranslationEngineId(input.engineId)) {
|
|
137106
137640
|
if (!input.localModel?.trim()) return {
|
|
137107
137641
|
state: "unavailable",
|
|
137108
|
-
engineId:
|
|
137109
|
-
message: "Select a
|
|
137642
|
+
engineId: input.engineId,
|
|
137643
|
+
message: "Select a model before translating."
|
|
137110
137644
|
};
|
|
137111
137645
|
if (input.localAssetLoading || !input.localAsset) return {
|
|
137112
137646
|
state: "checking",
|
|
137113
|
-
engineId:
|
|
137647
|
+
engineId: input.engineId,
|
|
137114
137648
|
message: "Checking local model files."
|
|
137115
137649
|
};
|
|
137116
137650
|
if (isLocalAssetReady(input.localAsset, input.localSelectedGroupId)) return {
|
|
137117
137651
|
state: "ready",
|
|
137118
|
-
engineId:
|
|
137652
|
+
engineId: input.engineId,
|
|
137119
137653
|
message: "Selected local model files are ready."
|
|
137120
137654
|
};
|
|
137121
137655
|
return {
|
|
137122
137656
|
state: "unavailable",
|
|
137123
|
-
engineId:
|
|
137657
|
+
engineId: input.engineId,
|
|
137124
137658
|
message: "Selected local model files are not installed locally."
|
|
137125
137659
|
};
|
|
137126
137660
|
}
|
|
@@ -137142,6 +137676,294 @@ function isLocalAssetReady(asset, selectedGroupId) {
|
|
|
137142
137676
|
return allRequiredFilesReady;
|
|
137143
137677
|
}
|
|
137144
137678
|
//#endregion
|
|
137679
|
+
//#region src/lib/translate-service.ts
|
|
137680
|
+
async function resolveTranslateServiceState(input) {
|
|
137681
|
+
const config = input.config;
|
|
137682
|
+
if (!config?.enabled || !input.hasSource) return emitTranslateServiceState(input.onUpdate, { status: projectTranslateServiceStatus({
|
|
137683
|
+
enabled: config?.enabled ?? false,
|
|
137684
|
+
hasSource: input.hasSource,
|
|
137685
|
+
engineId: config?.engineId ?? "browser"
|
|
137686
|
+
}) });
|
|
137687
|
+
let engineLifecycle = null;
|
|
137688
|
+
if (config.engineId !== "browser") {
|
|
137689
|
+
input.onUpdate?.(createTranslateServiceState({ status: projectTranslateServiceStatus({
|
|
137690
|
+
enabled: config.enabled,
|
|
137691
|
+
hasSource: input.hasSource,
|
|
137692
|
+
engineId: config.engineId,
|
|
137693
|
+
engineLifecycleLoading: true
|
|
137694
|
+
}) }));
|
|
137695
|
+
try {
|
|
137696
|
+
engineLifecycle = await trpcClient.translationEngines.getLifecycle.query({ engineId: config.engineId });
|
|
137697
|
+
} catch (lifecycleError) {
|
|
137698
|
+
return createTranslateServiceState({ status: {
|
|
137699
|
+
state: "unavailable",
|
|
137700
|
+
engineId: config.engineId,
|
|
137701
|
+
message: lifecycleError instanceof Error ? lifecycleError.message : "Unable to check translation engine runtime."
|
|
137702
|
+
} });
|
|
137703
|
+
}
|
|
137704
|
+
if (shouldShowTranslationEngineInstallGate(engineLifecycle)) return createTranslateServiceState({ status: projectTranslateServiceStatus({
|
|
137705
|
+
enabled: config.enabled,
|
|
137706
|
+
hasSource: input.hasSource,
|
|
137707
|
+
engineId: config.engineId,
|
|
137708
|
+
engineLifecycle
|
|
137709
|
+
}) });
|
|
137710
|
+
}
|
|
137711
|
+
if (isManagedLocalTranslationEngineId(config.engineId)) {
|
|
137712
|
+
const localEngineConfig = getManagedLocalEngineConfig(config);
|
|
137713
|
+
const model = localEngineConfig.model?.trim();
|
|
137714
|
+
if (!model) return emitTranslateServiceState(input.onUpdate, { status: projectTranslateServiceStatus({
|
|
137715
|
+
enabled: config.enabled,
|
|
137716
|
+
hasSource: input.hasSource,
|
|
137717
|
+
engineId: config.engineId,
|
|
137718
|
+
engineLifecycle,
|
|
137719
|
+
localModel: model,
|
|
137720
|
+
localSelectedGroupId: localEngineConfig.selectedGroupId
|
|
137721
|
+
}) });
|
|
137722
|
+
const directionCheck = checkLocalDirectionalModelLanguagePair({
|
|
137723
|
+
model,
|
|
137724
|
+
targetLanguage: config.targetLanguage
|
|
137725
|
+
});
|
|
137726
|
+
if (!directionCheck.supported) return emitTranslateServiceState(input.onUpdate, { status: {
|
|
137727
|
+
state: "unavailable",
|
|
137728
|
+
engineId: config.engineId,
|
|
137729
|
+
message: directionCheck.message ?? "Selected local model does not support the configured target language."
|
|
137730
|
+
} });
|
|
137731
|
+
input.onUpdate?.(createTranslateServiceState({ status: projectTranslateServiceStatus({
|
|
137732
|
+
enabled: config.enabled,
|
|
137733
|
+
hasSource: input.hasSource,
|
|
137734
|
+
engineId: config.engineId,
|
|
137735
|
+
engineLifecycle,
|
|
137736
|
+
localModel: model,
|
|
137737
|
+
localSelectedGroupId: localEngineConfig.selectedGroupId,
|
|
137738
|
+
localAssetLoading: true
|
|
137739
|
+
}) }));
|
|
137740
|
+
try {
|
|
137741
|
+
const panelState = await queryManagedLocalPanelState(config.engineId, {
|
|
137742
|
+
modelId: model,
|
|
137743
|
+
selectedGroupId: localEngineConfig.selectedGroupId
|
|
137744
|
+
});
|
|
137745
|
+
const selectedGroupId = panelState.selectedGroupId ?? localEngineConfig.selectedGroupId;
|
|
137746
|
+
return createTranslateServiceState({ status: projectTranslateServiceStatus({
|
|
137747
|
+
enabled: config.enabled,
|
|
137748
|
+
hasSource: input.hasSource,
|
|
137749
|
+
engineId: config.engineId,
|
|
137750
|
+
engineLifecycle,
|
|
137751
|
+
localModel: model,
|
|
137752
|
+
localSelectedGroupId: selectedGroupId,
|
|
137753
|
+
localAsset: panelState.asset
|
|
137754
|
+
}) });
|
|
137755
|
+
} catch (assetError) {
|
|
137756
|
+
return createTranslateServiceState({ status: {
|
|
137757
|
+
state: "unavailable",
|
|
137758
|
+
engineId: config.engineId,
|
|
137759
|
+
message: assetError instanceof Error ? assetError.message : "Unable to check local model files."
|
|
137760
|
+
} });
|
|
137761
|
+
}
|
|
137762
|
+
}
|
|
137763
|
+
if (config.engineId === "openai") return emitTranslateServiceState(input.onUpdate, { status: projectTranslateServiceStatus({
|
|
137764
|
+
enabled: config.enabled,
|
|
137765
|
+
hasSource: input.hasSource,
|
|
137766
|
+
engineId: "openai",
|
|
137767
|
+
engineLifecycle
|
|
137768
|
+
}) });
|
|
137769
|
+
const cachedTable = getBrowserSupportTableState(config.targetLanguage);
|
|
137770
|
+
if (cachedTable) return emitTranslateServiceState(input.onUpdate, {
|
|
137771
|
+
browserSupportTable: cachedTable,
|
|
137772
|
+
status: projectTranslateServiceStatus({
|
|
137773
|
+
enabled: config.enabled,
|
|
137774
|
+
hasSource: input.hasSource,
|
|
137775
|
+
engineId: "browser",
|
|
137776
|
+
browserSupportTable: cachedTable
|
|
137777
|
+
})
|
|
137778
|
+
});
|
|
137779
|
+
const checkingTable = {
|
|
137780
|
+
state: "checking",
|
|
137781
|
+
table: null,
|
|
137782
|
+
message: "Checking browser translation pairs…"
|
|
137783
|
+
};
|
|
137784
|
+
input.onUpdate?.(createTranslateServiceState({
|
|
137785
|
+
browserSupportTable: checkingTable,
|
|
137786
|
+
status: projectTranslateServiceStatus({
|
|
137787
|
+
enabled: config.enabled,
|
|
137788
|
+
hasSource: input.hasSource,
|
|
137789
|
+
engineId: "browser",
|
|
137790
|
+
browserSupportTable: checkingTable
|
|
137791
|
+
})
|
|
137792
|
+
}));
|
|
137793
|
+
try {
|
|
137794
|
+
const nextTable = await scanBrowserTranslationPairs(config.targetLanguage, {
|
|
137795
|
+
signal: input.signal ?? new AbortController().signal,
|
|
137796
|
+
onProgress: (progressState) => {
|
|
137797
|
+
input.onUpdate?.(createTranslateServiceState({
|
|
137798
|
+
browserSupportTable: progressState,
|
|
137799
|
+
status: projectTranslateServiceStatus({
|
|
137800
|
+
enabled: config.enabled,
|
|
137801
|
+
hasSource: input.hasSource,
|
|
137802
|
+
engineId: "browser",
|
|
137803
|
+
browserSupportTable: progressState
|
|
137804
|
+
})
|
|
137805
|
+
}));
|
|
137806
|
+
}
|
|
137807
|
+
});
|
|
137808
|
+
return createTranslateServiceState({
|
|
137809
|
+
browserSupportTable: nextTable,
|
|
137810
|
+
status: projectTranslateServiceStatus({
|
|
137811
|
+
enabled: config.enabled,
|
|
137812
|
+
hasSource: input.hasSource,
|
|
137813
|
+
engineId: "browser",
|
|
137814
|
+
browserSupportTable: nextTable
|
|
137815
|
+
})
|
|
137816
|
+
});
|
|
137817
|
+
} catch (probeError) {
|
|
137818
|
+
const nextCapability = {
|
|
137819
|
+
availability: "error",
|
|
137820
|
+
message: probeError instanceof Error ? probeError.message : "Unable to check translation support."
|
|
137821
|
+
};
|
|
137822
|
+
return createTranslateServiceState({
|
|
137823
|
+
capability: nextCapability,
|
|
137824
|
+
status: projectTranslateServiceStatus({
|
|
137825
|
+
enabled: config.enabled,
|
|
137826
|
+
hasSource: input.hasSource,
|
|
137827
|
+
engineId: "browser",
|
|
137828
|
+
browserCapability: nextCapability
|
|
137829
|
+
})
|
|
137830
|
+
});
|
|
137831
|
+
}
|
|
137832
|
+
}
|
|
137833
|
+
function prepareTranslateServiceRun(input) {
|
|
137834
|
+
if (input.config.engineId !== "browser") return createTranslateServiceState({ status: projectTranslateServiceStatus({
|
|
137835
|
+
enabled: input.config.enabled,
|
|
137836
|
+
hasSource: input.hasSource,
|
|
137837
|
+
engineId: input.config.engineId
|
|
137838
|
+
}) });
|
|
137839
|
+
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;
|
|
137840
|
+
if (!preferredRow) return createTranslateServiceState({
|
|
137841
|
+
browserSupportTable: input.browserSupportTable,
|
|
137842
|
+
status: projectTranslateServiceStatus({
|
|
137843
|
+
enabled: input.config.enabled,
|
|
137844
|
+
hasSource: input.hasSource,
|
|
137845
|
+
engineId: "browser",
|
|
137846
|
+
browserSupportTable: input.browserSupportTable
|
|
137847
|
+
})
|
|
137848
|
+
});
|
|
137849
|
+
const nextCapability = {
|
|
137850
|
+
availability: preferredRow.availability,
|
|
137851
|
+
progress: preferredRow.progress,
|
|
137852
|
+
message: preferredRow.message
|
|
137853
|
+
};
|
|
137854
|
+
const nextTable = patchBrowserSupportTableRow(input.config.targetLanguage, preferredRow, { message: void 0 });
|
|
137855
|
+
return createTranslateServiceState({
|
|
137856
|
+
capability: nextCapability,
|
|
137857
|
+
browserSupportTable: nextTable,
|
|
137858
|
+
status: projectTranslateServiceStatus({
|
|
137859
|
+
enabled: input.config.enabled,
|
|
137860
|
+
hasSource: input.hasSource,
|
|
137861
|
+
engineId: "browser",
|
|
137862
|
+
browserSupportTable: nextTable,
|
|
137863
|
+
browserCapability: nextCapability
|
|
137864
|
+
})
|
|
137865
|
+
});
|
|
137866
|
+
}
|
|
137867
|
+
function createTranslationEngineExecution(config) {
|
|
137868
|
+
if (config.engineId === "browser" || isStaticMode()) return createBrowserTranslationExecution();
|
|
137869
|
+
const model = config.engineId === "openai" ? config.engines.openai.model : getManagedLocalEngineConfig(config).model;
|
|
137870
|
+
return {
|
|
137871
|
+
factory: new TrpcTranslatorFactory(config.engineId, model, isManagedLocalTranslationEngineId(config.engineId) ? getManagedLocalEngineConfig(config).selectedGroupId : void 0),
|
|
137872
|
+
cacheIdentity: {
|
|
137873
|
+
engineId: config.engineId,
|
|
137874
|
+
model,
|
|
137875
|
+
selectedGroupId: isManagedLocalTranslationEngineId(config.engineId) ? getManagedLocalEngineConfig(config).selectedGroupId : void 0,
|
|
137876
|
+
translatorContractVersion: 3
|
|
137877
|
+
}
|
|
137878
|
+
};
|
|
137879
|
+
}
|
|
137880
|
+
var TrpcTranslatorFactory = class {
|
|
137881
|
+
constructor(engineId, model, selectedGroupId) {
|
|
137882
|
+
this.engineId = engineId;
|
|
137883
|
+
this.model = model;
|
|
137884
|
+
this.selectedGroupId = selectedGroupId;
|
|
137885
|
+
}
|
|
137886
|
+
async create(options) {
|
|
137887
|
+
return new TrpcTranslator({
|
|
137888
|
+
engineId: this.engineId,
|
|
137889
|
+
sourceLanguage: options.sourceLanguage,
|
|
137890
|
+
targetLanguage: options.targetLanguage,
|
|
137891
|
+
model: options.model ?? this.model,
|
|
137892
|
+
selectedGroupId: isManagedLocalTranslationEngineId(this.engineId) ? this.selectedGroupId : void 0
|
|
137893
|
+
});
|
|
137894
|
+
}
|
|
137895
|
+
};
|
|
137896
|
+
function getManagedLocalEngineConfig(config) {
|
|
137897
|
+
return config.engineId === "local-ct2" ? {
|
|
137898
|
+
model: config.engines.localCt2.model,
|
|
137899
|
+
selectedGroupId: config.engines.localCt2.selectedGroupId
|
|
137900
|
+
} : {
|
|
137901
|
+
model: config.engines.local.model,
|
|
137902
|
+
selectedGroupId: config.engines.local.selectedGroupId
|
|
137903
|
+
};
|
|
137904
|
+
}
|
|
137905
|
+
async function queryManagedLocalPanelState(engineId, input) {
|
|
137906
|
+
return engineId === "local" ? trpcClient.localModels.panelState.query(input) : trpcClient.localCt2Models.panelState.query(input);
|
|
137907
|
+
}
|
|
137908
|
+
var TrpcTranslator = class {
|
|
137909
|
+
constructor(options) {
|
|
137910
|
+
this.options = options;
|
|
137911
|
+
}
|
|
137912
|
+
async *batchTranslate(inputs, options) {
|
|
137913
|
+
if (options?.signal?.aborted) throw new DOMException("Translation cancelled.", "AbortError");
|
|
137914
|
+
const queue = [];
|
|
137915
|
+
let completed = false;
|
|
137916
|
+
let thrown = null;
|
|
137917
|
+
const subscription = trpcClient.translationEngines.batchTranslate.subscribe({
|
|
137918
|
+
engineId: this.options.engineId,
|
|
137919
|
+
sourceLanguage: this.options.sourceLanguage,
|
|
137920
|
+
targetLanguage: this.options.targetLanguage,
|
|
137921
|
+
model: this.options.model,
|
|
137922
|
+
selectedGroupId: this.options.selectedGroupId,
|
|
137923
|
+
inputs,
|
|
137924
|
+
instructions: options?.instructions,
|
|
137925
|
+
context: options?.context
|
|
137926
|
+
}, {
|
|
137927
|
+
onData(event) {
|
|
137928
|
+
queue.push(event);
|
|
137929
|
+
},
|
|
137930
|
+
onError(error) {
|
|
137931
|
+
thrown = error instanceof Error ? error : new Error(String(error));
|
|
137932
|
+
completed = true;
|
|
137933
|
+
},
|
|
137934
|
+
onComplete() {
|
|
137935
|
+
completed = true;
|
|
137936
|
+
}
|
|
137937
|
+
});
|
|
137938
|
+
try {
|
|
137939
|
+
while (!completed || queue.length > 0) {
|
|
137940
|
+
if (options?.signal?.aborted) throw new DOMException("Translation cancelled.", "AbortError");
|
|
137941
|
+
const item = queue.shift();
|
|
137942
|
+
if (item) {
|
|
137943
|
+
yield item;
|
|
137944
|
+
continue;
|
|
137945
|
+
}
|
|
137946
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
137947
|
+
}
|
|
137948
|
+
if (thrown) throw thrown;
|
|
137949
|
+
} finally {
|
|
137950
|
+
subscription.unsubscribe();
|
|
137951
|
+
}
|
|
137952
|
+
}
|
|
137953
|
+
};
|
|
137954
|
+
function createTranslateServiceState(input) {
|
|
137955
|
+
return {
|
|
137956
|
+
capability: input.capability ?? null,
|
|
137957
|
+
browserSupportTable: input.browserSupportTable ?? null,
|
|
137958
|
+
status: input.status
|
|
137959
|
+
};
|
|
137960
|
+
}
|
|
137961
|
+
function emitTranslateServiceState(onUpdate, input) {
|
|
137962
|
+
const state = createTranslateServiceState(input);
|
|
137963
|
+
onUpdate?.(state);
|
|
137964
|
+
return state;
|
|
137965
|
+
}
|
|
137966
|
+
//#endregion
|
|
137145
137967
|
//#region src/lib/use-document-translation.ts
|
|
137146
137968
|
function useDocumentTranslation(markdown, config) {
|
|
137147
137969
|
const [status, setStatus] = (0, import_react.useState)("source");
|
|
@@ -137154,9 +137976,11 @@ function useDocumentTranslation(markdown, config) {
|
|
|
137154
137976
|
const [error, setError] = (0, import_react.useState)(null);
|
|
137155
137977
|
const [result, setResult] = (0, import_react.useState)(null);
|
|
137156
137978
|
const abortRef = (0, import_react.useRef)(null);
|
|
137979
|
+
const generationRef = (0, import_react.useRef)(0);
|
|
137157
137980
|
const latestStartRef = (0, import_react.useRef)(null);
|
|
137158
137981
|
const { activation } = useDocumentTranslationActivation();
|
|
137159
137982
|
const cancel = (0, import_react.useCallback)(() => {
|
|
137983
|
+
generationRef.current += 1;
|
|
137160
137984
|
abortRef.current?.abort();
|
|
137161
137985
|
abortRef.current = null;
|
|
137162
137986
|
setStatus("source");
|
|
@@ -137164,6 +137988,7 @@ function useDocumentTranslation(markdown, config) {
|
|
|
137164
137988
|
setError(null);
|
|
137165
137989
|
}, []);
|
|
137166
137990
|
const reset = (0, import_react.useCallback)(() => {
|
|
137991
|
+
generationRef.current += 1;
|
|
137167
137992
|
abortRef.current?.abort();
|
|
137168
137993
|
abortRef.current = null;
|
|
137169
137994
|
setStatus("source");
|
|
@@ -137172,6 +137997,7 @@ function useDocumentTranslation(markdown, config) {
|
|
|
137172
137997
|
}, []);
|
|
137173
137998
|
(0, import_react.useEffect)(() => reset, [reset]);
|
|
137174
137999
|
(0, import_react.useEffect)(() => {
|
|
138000
|
+
generationRef.current += 1;
|
|
137175
138001
|
setCapability(null);
|
|
137176
138002
|
setBrowserSupportTable(null);
|
|
137177
138003
|
setResult(null);
|
|
@@ -137181,141 +138007,41 @@ function useDocumentTranslation(markdown, config) {
|
|
|
137181
138007
|
markdown,
|
|
137182
138008
|
config?.displayMode,
|
|
137183
138009
|
config?.enabled,
|
|
138010
|
+
config?.engineId,
|
|
138011
|
+
config?.engines.local.model,
|
|
138012
|
+
config?.engines.local.selectedGroupId,
|
|
138013
|
+
config?.engines.localCt2.model,
|
|
138014
|
+
config?.engines.localCt2.selectedGroupId,
|
|
138015
|
+
config?.engines.openai.model,
|
|
137184
138016
|
config?.targetLanguage
|
|
137185
138017
|
]);
|
|
137186
138018
|
(0, import_react.useEffect)(() => {
|
|
137187
138019
|
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
138020
|
const controller = new AbortController();
|
|
137285
|
-
|
|
138021
|
+
resolveTranslateServiceState({
|
|
138022
|
+
config,
|
|
138023
|
+
hasSource: markdown.length > 0,
|
|
137286
138024
|
signal: controller.signal,
|
|
137287
|
-
|
|
138025
|
+
onUpdate: (nextState) => {
|
|
137288
138026
|
if (disposed) return;
|
|
137289
|
-
|
|
137290
|
-
|
|
137291
|
-
|
|
137292
|
-
hasSource: markdown.length > 0,
|
|
137293
|
-
engineId: "browser",
|
|
137294
|
-
browserSupportTable: nextState
|
|
137295
|
-
}));
|
|
138027
|
+
setCapability(nextState.capability);
|
|
138028
|
+
setBrowserSupportTable(nextState.browserSupportTable);
|
|
138029
|
+
setServiceStatus(nextState.status);
|
|
137296
138030
|
}
|
|
137297
138031
|
}).then((nextState) => {
|
|
137298
138032
|
if (disposed) return;
|
|
137299
|
-
|
|
137300
|
-
|
|
137301
|
-
|
|
137302
|
-
|
|
137303
|
-
engineId: "browser",
|
|
137304
|
-
browserSupportTable: nextState
|
|
137305
|
-
}));
|
|
137306
|
-
}).catch((probeError) => {
|
|
138033
|
+
setCapability(nextState.capability);
|
|
138034
|
+
setBrowserSupportTable(nextState.browserSupportTable);
|
|
138035
|
+
setServiceStatus(nextState.status);
|
|
138036
|
+
}).catch((stateError) => {
|
|
137307
138037
|
if (disposed) return;
|
|
137308
|
-
|
|
137309
|
-
|
|
137310
|
-
|
|
137311
|
-
|
|
137312
|
-
|
|
137313
|
-
|
|
137314
|
-
|
|
137315
|
-
hasSource: markdown.length > 0,
|
|
137316
|
-
engineId: "browser",
|
|
137317
|
-
browserCapability: nextCapability
|
|
137318
|
-
}));
|
|
138038
|
+
setCapability(null);
|
|
138039
|
+
setBrowserSupportTable(null);
|
|
138040
|
+
setServiceStatus({
|
|
138041
|
+
state: "unavailable",
|
|
138042
|
+
engineId: config?.engineId ?? "browser",
|
|
138043
|
+
message: stateError instanceof Error ? stateError.message : "Unable to check translation service."
|
|
138044
|
+
});
|
|
137319
138045
|
});
|
|
137320
138046
|
return () => {
|
|
137321
138047
|
disposed = true;
|
|
@@ -137326,6 +138052,8 @@ function useDocumentTranslation(markdown, config) {
|
|
|
137326
138052
|
config?.engineId,
|
|
137327
138053
|
config?.engines.local.model,
|
|
137328
138054
|
config?.engines.local.selectedGroupId,
|
|
138055
|
+
config?.engines.localCt2.model,
|
|
138056
|
+
config?.engines.localCt2.selectedGroupId,
|
|
137329
138057
|
config?.targetLanguage,
|
|
137330
138058
|
markdown.length
|
|
137331
138059
|
]);
|
|
@@ -137333,6 +138061,8 @@ function useDocumentTranslation(markdown, config) {
|
|
|
137333
138061
|
if (!config?.enabled) return;
|
|
137334
138062
|
abortRef.current?.abort();
|
|
137335
138063
|
const controller = new AbortController();
|
|
138064
|
+
const generationId = generationRef.current + 1;
|
|
138065
|
+
generationRef.current = generationId;
|
|
137336
138066
|
abortRef.current = controller;
|
|
137337
138067
|
setError(null);
|
|
137338
138068
|
setStatus("initializing");
|
|
@@ -137343,27 +138073,19 @@ function useDocumentTranslation(markdown, config) {
|
|
|
137343
138073
|
return;
|
|
137344
138074
|
}
|
|
137345
138075
|
if (config.engineId === "browser") {
|
|
137346
|
-
const
|
|
137347
|
-
|
|
137348
|
-
|
|
138076
|
+
const nextState = prepareTranslateServiceRun({
|
|
138077
|
+
config,
|
|
138078
|
+
hasSource: markdown.length > 0,
|
|
138079
|
+
browserSupportTable
|
|
138080
|
+
});
|
|
138081
|
+
setCapability(nextState.capability);
|
|
138082
|
+
setBrowserSupportTable(nextState.browserSupportTable);
|
|
138083
|
+
setServiceStatus(nextState.status);
|
|
138084
|
+
if (nextState.status.state !== "ready") {
|
|
138085
|
+
setError(nextState.status.message);
|
|
137349
138086
|
setStatus("unavailable");
|
|
137350
138087
|
return;
|
|
137351
138088
|
}
|
|
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
138089
|
}
|
|
137368
138090
|
setStatus("translating");
|
|
137369
138091
|
setResult({
|
|
@@ -137382,21 +138104,27 @@ function useDocumentTranslation(markdown, config) {
|
|
|
137382
138104
|
write: (input) => trpcClient.translationCache.write.mutate(input)
|
|
137383
138105
|
} : void 0
|
|
137384
138106
|
}, (patch) => {
|
|
137385
|
-
if (controller.signal.aborted || abortRef.current !== controller) return;
|
|
138107
|
+
if (controller.signal.aborted || abortRef.current !== controller || generationRef.current !== generationId) return;
|
|
137386
138108
|
setResult((current) => applyDocumentTranslationPatch(current, patch, {
|
|
137387
138109
|
displayMode: config.displayMode,
|
|
137388
138110
|
targetLanguage: config.targetLanguage
|
|
137389
138111
|
}));
|
|
137390
138112
|
});
|
|
137391
|
-
if (controller.signal.aborted) return;
|
|
138113
|
+
if (controller.signal.aborted || abortRef.current !== controller || generationRef.current !== generationId) return;
|
|
138114
|
+
const documentFailure = getDocumentTranslationFailureMessage(nextResult);
|
|
137392
138115
|
setResult(nextResult);
|
|
138116
|
+
if (documentFailure) {
|
|
138117
|
+
setError(documentFailure);
|
|
138118
|
+
setStatus("error");
|
|
138119
|
+
return;
|
|
138120
|
+
}
|
|
137393
138121
|
setStatus("translated");
|
|
137394
138122
|
} catch (translationError) {
|
|
137395
|
-
if (controller.signal.aborted) return;
|
|
138123
|
+
if (controller.signal.aborted || abortRef.current !== controller || generationRef.current !== generationId) return;
|
|
137396
138124
|
setError(translationError instanceof Error ? translationError.message : "Translation failed.");
|
|
137397
138125
|
setStatus("error");
|
|
137398
138126
|
} finally {
|
|
137399
|
-
if (abortRef.current === controller) abortRef.current = null;
|
|
138127
|
+
if (abortRef.current === controller && generationRef.current === generationId) abortRef.current = null;
|
|
137400
138128
|
}
|
|
137401
138129
|
}, [
|
|
137402
138130
|
browserSupportTable,
|
|
@@ -137408,6 +138136,8 @@ function useDocumentTranslation(markdown, config) {
|
|
|
137408
138136
|
config?.engines.openai.model,
|
|
137409
138137
|
config?.engines.local.model,
|
|
137410
138138
|
config?.engines.local.selectedGroupId,
|
|
138139
|
+
config?.engines.localCt2.model,
|
|
138140
|
+
config?.engines.localCt2.selectedGroupId,
|
|
137411
138141
|
markdown,
|
|
137412
138142
|
serviceStatus
|
|
137413
138143
|
]);
|
|
@@ -137437,8 +138167,16 @@ function useDocumentTranslation(markdown, config) {
|
|
|
137437
138167
|
reset
|
|
137438
138168
|
};
|
|
137439
138169
|
}
|
|
138170
|
+
function getDocumentTranslationFailureMessage(result) {
|
|
138171
|
+
const segments = (Array.isArray(result.segments) ? result.segments : []).filter((segment) => segment !== void 0);
|
|
138172
|
+
if (segments.length === 0) return null;
|
|
138173
|
+
if (segments.some((segment) => segment.status !== "error" && typeof segment.target === "string")) return null;
|
|
138174
|
+
const errors = segments.map((segment) => segment.status === "error" ? segment.error : void 0).filter((message) => typeof message === "string" && message.length > 0);
|
|
138175
|
+
if (errors.length === 0) return null;
|
|
138176
|
+
return errors[0] ?? "Translation failed.";
|
|
138177
|
+
}
|
|
137440
138178
|
function applyDocumentTranslationPatch(current, patch, fallback) {
|
|
137441
|
-
const segments =
|
|
138179
|
+
const segments = current?.segments.slice() ?? [];
|
|
137442
138180
|
segments[patch.segmentIndex] = patch.segment;
|
|
137443
138181
|
return {
|
|
137444
138182
|
displayMode: current?.displayMode ?? fallback.displayMode,
|
|
@@ -148221,7 +148959,8 @@ function stripOpenSpecHeadingKindFromTextNode(node, kind, state) {
|
|
|
148221
148959
|
//#endregion
|
|
148222
148960
|
//#region src/components/document-translation-action.tsx
|
|
148223
148961
|
function useDocumentTranslationRenderPlugin({ markdown, translationConfig }) {
|
|
148224
|
-
const
|
|
148962
|
+
const { data: globalSettings } = useGlobalSettingsSubscription();
|
|
148963
|
+
const resolvedTranslationConfig = (0, import_react.useMemo)(() => translationConfig === void 0 ? void 0 : DocumentTranslationConfigSchema.parse(resolveDocumentTranslationConfig(translationConfig, globalSettings)), [globalSettings, translationConfig]);
|
|
148225
148964
|
const session = useDocumentTranslation(markdown ?? "", resolvedTranslationConfig);
|
|
148226
148965
|
const canTranslate = resolvedTranslationConfig !== void 0 && typeof markdown === "string" && markdown.length > 0;
|
|
148227
148966
|
const translationProjection = (0, import_react.useMemo)(() => createTranslationProjection(session.result), [session.result]);
|
|
@@ -148245,6 +148984,8 @@ function useDocumentTranslationRenderPlugin({ markdown, translationConfig }) {
|
|
|
148245
148984
|
resolvedTranslationConfig?.engineId,
|
|
148246
148985
|
resolvedTranslationConfig?.engines.local.model ?? "no-local-model",
|
|
148247
148986
|
resolvedTranslationConfig?.engines.local.selectedGroupId ?? "no-local-group",
|
|
148987
|
+
resolvedTranslationConfig?.engines.localCt2.model ?? "no-local-ct2-model",
|
|
148988
|
+
resolvedTranslationConfig?.engines.localCt2.selectedGroupId ?? "no-local-ct2-group",
|
|
148248
148989
|
session.capability?.availability ?? "unknown",
|
|
148249
148990
|
session.capability?.message ?? "no-message",
|
|
148250
148991
|
session.serviceStatus.state,
|
|
@@ -148261,6 +149002,7 @@ function DocumentTranslationAction({ enabled, session }) {
|
|
|
148261
149002
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DocumentTranslationButton, {
|
|
148262
149003
|
capability: session.capability,
|
|
148263
149004
|
enabled,
|
|
149005
|
+
error: session.error,
|
|
148264
149006
|
serviceStatus: session.serviceStatus,
|
|
148265
149007
|
status: session.status,
|
|
148266
149008
|
onActivate: () => {
|
|
@@ -148294,7 +149036,8 @@ function hashString(value) {
|
|
|
148294
149036
|
}
|
|
148295
149037
|
function createTranslationProjection(result) {
|
|
148296
149038
|
if (!result) return { blockAnnotations: [] };
|
|
148297
|
-
const
|
|
149039
|
+
const segments = getRenderableTranslationSegments(result);
|
|
149040
|
+
const segmentByOffset = new Map(segments.filter((segment) => segment.target).map((segment) => [segment.sourceStartOffset, segment]));
|
|
148298
149041
|
return {
|
|
148299
149042
|
headingProcessor: {
|
|
148300
149043
|
name: "document-translation",
|
|
@@ -148316,7 +149059,7 @@ function createTranslationProjection(result) {
|
|
|
148316
149059
|
return createTranslatedHeadingTransform(input, segment, result.displayMode);
|
|
148317
149060
|
}
|
|
148318
149061
|
},
|
|
148319
|
-
blockAnnotations:
|
|
149062
|
+
blockAnnotations: segments.filter((segment) => segment.target && segment.kind !== "heading").map((segment) => ({
|
|
148320
149063
|
sourceStartOffset: segment.sourceStartOffset,
|
|
148321
149064
|
sourceKind: segment.sourceKind,
|
|
148322
149065
|
className: result.displayMode === "direct" ? "document-translation-direct" : "document-translation-bilingual",
|
|
@@ -148337,6 +149080,9 @@ function createTranslationProjection(result) {
|
|
|
148337
149080
|
}))
|
|
148338
149081
|
};
|
|
148339
149082
|
}
|
|
149083
|
+
function getRenderableTranslationSegments(result) {
|
|
149084
|
+
return (Array.isArray(result.segments) ? result.segments : []).filter((segment) => segment !== void 0);
|
|
149085
|
+
}
|
|
148340
149086
|
function createTranslatedHeadingTransform(input, segment, displayMode) {
|
|
148341
149087
|
const projectedTarget = segment.target ?? "";
|
|
148342
149088
|
const openSpecHeading = createTranslatedOpenSpecHeadingProjection(input, segment, displayMode);
|
|
@@ -148415,28 +149161,31 @@ function sanitizeTranslatedProperties(properties) {
|
|
|
148415
149161
|
}
|
|
148416
149162
|
return nextProperties;
|
|
148417
149163
|
}
|
|
148418
|
-
function DocumentTranslationButton({ capability, enabled, serviceStatus, status, onActivate }) {
|
|
149164
|
+
function DocumentTranslationButton({ capability, enabled, error, serviceStatus, status, onActivate }) {
|
|
148419
149165
|
const isServiceChecking = serviceStatus.state === "checking";
|
|
148420
149166
|
const isServiceUnavailable = serviceStatus.state === "unavailable" || status === "unavailable";
|
|
148421
149167
|
const isSettingsDisabled = !enabled;
|
|
148422
149168
|
const isTranslated = status === "translated";
|
|
148423
149169
|
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
|
-
|
|
149170
|
+
const isError = status === "error";
|
|
149171
|
+
const ariaLabel = isServiceUnavailable ? "Translation unavailable" : isSettingsDisabled ? "Configure translation" : isServiceChecking ? "Checking translation" : isError ? "Retry translation" : isBusy ? "Cancel translation" : isTranslated ? "Show source" : "Translate";
|
|
149172
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tooltip, {
|
|
149173
|
+
content: isServiceUnavailable ? serviceStatus.message ?? capability?.message ?? "Translation is unavailable." : isSettingsDisabled ? "Translation is disabled in settings." : isError ? `${error ?? "Translation failed."} Click to retry.` : ariaLabel,
|
|
149174
|
+
delay: 0,
|
|
149175
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
149176
|
+
size: "icon-sm",
|
|
149177
|
+
variant: "secondary",
|
|
149178
|
+
disabled: isServiceUnavailable || isServiceChecking,
|
|
149179
|
+
"aria-disabled": isSettingsDisabled ? true : void 0,
|
|
149180
|
+
onClick: (event) => {
|
|
149181
|
+
event.stopPropagation();
|
|
149182
|
+
onActivate();
|
|
149183
|
+
},
|
|
149184
|
+
"aria-label": ariaLabel,
|
|
149185
|
+
"data-translation-action-state": isServiceUnavailable ? "unavailable" : isServiceChecking ? "checking" : isSettingsDisabled ? "settings-disabled" : isError ? "error" : isBusy ? "busy" : isTranslated ? "translated" : "ready",
|
|
149186
|
+
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",
|
|
149187
|
+
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" })
|
|
149188
|
+
})
|
|
148440
149189
|
});
|
|
148441
149190
|
}
|
|
148442
149191
|
//#endregion
|
|
@@ -150398,89 +151147,6 @@ var viewerStyles = String.raw`
|
|
|
150398
151147
|
/* MarkdownViewer keeps layout hooks local; shared ToC geometry lives in index.css. */
|
|
150399
151148
|
`;
|
|
150400
151149
|
//#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
151150
|
//#region src/lib/file-preview.ts
|
|
150485
151151
|
async function prepareEntityFilePreview(input) {
|
|
150486
151152
|
if (isStaticMode()) return null;
|
|
@@ -150555,13 +151221,10 @@ function isPreviewOnlyFile(file) {
|
|
|
150555
151221
|
}
|
|
150556
151222
|
function resolveDefaultMode(file, inStaticMode) {
|
|
150557
151223
|
if (!file) return "read";
|
|
151224
|
+
if (!inStaticMode && isFileEntry(file) && file.previewKind === "html") return "preview";
|
|
150558
151225
|
if (!inStaticMode && isPreviewOnlyFile(file)) return "preview";
|
|
150559
151226
|
return "read";
|
|
150560
151227
|
}
|
|
150561
|
-
function clampPreviewHeight(viewportHeight) {
|
|
150562
|
-
if (viewportHeight == null) return 480;
|
|
150563
|
-
return Math.max(320, Math.min(viewportHeight - 112, 920));
|
|
150564
|
-
}
|
|
150565
151228
|
function resolveRemotePreviewFrameStyle(frameHeight) {
|
|
150566
151229
|
if (frameHeight == null) return void 0;
|
|
150567
151230
|
return {
|
|
@@ -150601,7 +151264,7 @@ async function sharePreview(input) {
|
|
|
150601
151264
|
}
|
|
150602
151265
|
function PreviewPane({ file, preview, loading, error, className = "", frameHeight, isDarkMode }) {
|
|
150603
151266
|
if (file.previewKind === "markdown") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
150604
|
-
className: `min-h-0
|
|
151267
|
+
className: `h-full min-h-0 flex-1 overflow-hidden ${className}`,
|
|
150605
151268
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MarkdownViewer, {
|
|
150606
151269
|
markdown: file.content ?? "",
|
|
150607
151270
|
path: file.path,
|
|
@@ -150621,7 +151284,7 @@ function PreviewPane({ file, preview, loading, error, className = "", frameHeigh
|
|
|
150621
151284
|
children: "Preview unavailable."
|
|
150622
151285
|
});
|
|
150623
151286
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
150624
|
-
className: `bg-background min-h-0
|
|
151287
|
+
className: `bg-background h-full min-h-0 overflow-hidden ${className}`,
|
|
150625
151288
|
style: resolveRemotePreviewFrameStyle(frameHeight),
|
|
150626
151289
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("iframe", {
|
|
150627
151290
|
src: resolvePreviewFrameUrl(preview, isDarkMode),
|
|
@@ -150635,7 +151298,6 @@ function FolderEditorViewer({ changeId, archived = false, files: providedFiles }
|
|
|
150635
151298
|
const isDarkMode = useDarkMode();
|
|
150636
151299
|
const { data: files, isLoading, error } = archived ? useArchiveFilesSubscription(changeId) : useChangeFilesSubscription(changeId);
|
|
150637
151300
|
const [selectedPath, setSelectedPath] = (0, import_react.useState)(null);
|
|
150638
|
-
const [viewportNode, setViewportNode] = (0, import_react.useState)(null);
|
|
150639
151301
|
const [mode, setMode] = (0, import_react.useState)("read");
|
|
150640
151302
|
const [draftContent, setDraftContent] = (0, import_react.useState)({});
|
|
150641
151303
|
const [savingPath, setSavingPath] = (0, import_react.useState)(null);
|
|
@@ -150644,10 +151306,6 @@ function FolderEditorViewer({ changeId, archived = false, files: providedFiles }
|
|
|
150644
151306
|
const [previewErrorByPath, setPreviewErrorByPath] = (0, import_react.useState)({});
|
|
150645
151307
|
const [previewMaximized, setPreviewMaximized] = (0, import_react.useState)(false);
|
|
150646
151308
|
const [shareFeedback, setShareFeedback] = (0, import_react.useState)(null);
|
|
150647
|
-
const viewportHeight = useViewportConstrainedHeight({
|
|
150648
|
-
target: viewportNode,
|
|
150649
|
-
enabled: viewportNode !== null
|
|
150650
|
-
});
|
|
150651
151309
|
const sortedEntries = (0, import_react.useMemo)(() => {
|
|
150652
151310
|
if (providedFiles) return [...providedFiles];
|
|
150653
151311
|
if (!files) return [];
|
|
@@ -150663,7 +151321,6 @@ function FolderEditorViewer({ changeId, archived = false, files: providedFiles }
|
|
|
150663
151321
|
const readEnabled = !isPreviewOnlyFile(activeFile);
|
|
150664
151322
|
const previewEnabled = !inStaticMode && canPreviewFile(activeFile);
|
|
150665
151323
|
const hasDirtyDraft = !!activeFile && isTextLikeFile(activeFile) && activeDraft !== (activeFile.content ?? "");
|
|
150666
|
-
const remotePreviewHeight = clampPreviewHeight(viewportHeight);
|
|
150667
151324
|
(0, import_react.useEffect)(() => {
|
|
150668
151325
|
if (!sortedEntries.length) {
|
|
150669
151326
|
setSelectedPath(null);
|
|
@@ -150694,6 +151351,7 @@ function FolderEditorViewer({ changeId, archived = false, files: providedFiles }
|
|
|
150694
151351
|
const nextDefaultMode = resolveDefaultMode(activeFile, inStaticMode);
|
|
150695
151352
|
setMode((currentMode) => {
|
|
150696
151353
|
if (currentMode === nextDefaultMode) return currentMode;
|
|
151354
|
+
if (currentMode === "read" && nextDefaultMode === "preview") return nextDefaultMode;
|
|
150697
151355
|
if (currentMode === "edit" && editEnabled) return currentMode;
|
|
150698
151356
|
if (currentMode === "preview" && previewEnabled) return currentMode;
|
|
150699
151357
|
if (currentMode === "read" && readEnabled) return currentMode;
|
|
@@ -150788,13 +151446,12 @@ function FolderEditorViewer({ changeId, archived = false, files: providedFiles }
|
|
|
150788
151446
|
};
|
|
150789
151447
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
|
|
150790
151448
|
"data-tab-scroll-root": "true",
|
|
150791
|
-
className: "
|
|
151449
|
+
className: "min-h-0 flex-1 overflow-hidden",
|
|
150792
151450
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
150793
|
-
className: "pr-1",
|
|
151451
|
+
className: "h-full min-h-0 pr-1",
|
|
150794
151452
|
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,
|
|
151453
|
+
"data-folder-viewport": "",
|
|
151454
|
+
className: "flex h-full min-h-0 flex-col overflow-hidden",
|
|
150798
151455
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileExplorer, {
|
|
150799
151456
|
entries: sortedEntries,
|
|
150800
151457
|
selectedPath,
|
|
@@ -150808,92 +151465,141 @@ function FolderEditorViewer({ changeId, archived = false, files: providedFiles }
|
|
|
150808
151465
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
150809
151466
|
className: "flex min-h-0 flex-1 flex-col",
|
|
150810
151467
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
150811
|
-
|
|
151468
|
+
"data-folder-toolbar": "",
|
|
151469
|
+
className: "border-border/60 bg-muted/20 flex flex-wrap items-center gap-3 border-b px-3 py-2",
|
|
150812
151470
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ButtonGroup, {
|
|
150813
151471
|
value: mode,
|
|
150814
151472
|
onChange: setMode,
|
|
151473
|
+
presentation: "icon-only",
|
|
151474
|
+
className: "min-w-0",
|
|
150815
151475
|
options: [
|
|
150816
151476
|
{
|
|
150817
151477
|
value: "read",
|
|
150818
151478
|
label: "Read",
|
|
151479
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScrollText, { className: "h-3.5 w-3.5" }),
|
|
151480
|
+
ariaLabel: "Read",
|
|
151481
|
+
tooltip: "Read",
|
|
150819
151482
|
disabled: !readEnabled
|
|
150820
151483
|
},
|
|
150821
151484
|
{
|
|
150822
151485
|
value: "edit",
|
|
150823
151486
|
label: "Edit",
|
|
151487
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FilePenLine, { className: "h-3.5 w-3.5" }),
|
|
151488
|
+
ariaLabel: "Edit",
|
|
151489
|
+
tooltip: "Edit",
|
|
150824
151490
|
disabled: !editEnabled
|
|
150825
151491
|
},
|
|
150826
151492
|
{
|
|
150827
151493
|
value: "preview",
|
|
150828
151494
|
label: "Preview",
|
|
151495
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Eye, { className: "h-3.5 w-3.5" }),
|
|
151496
|
+
ariaLabel: "Preview",
|
|
151497
|
+
tooltip: "Preview",
|
|
150829
151498
|
disabled: !previewEnabled
|
|
150830
151499
|
}
|
|
150831
151500
|
]
|
|
150832
151501
|
}), /* @__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, {
|
|
151502
|
+
"data-folder-toolbar-actions": "",
|
|
151503
|
+
className: "ml-auto flex min-w-0 max-w-full flex-wrap items-center justify-end gap-2",
|
|
151504
|
+
children: mode === "edit" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tooltip, {
|
|
151505
|
+
content: "Revert",
|
|
151506
|
+
delay: 0,
|
|
151507
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
150854
151508
|
variant: "secondary",
|
|
150855
|
-
size: "sm",
|
|
151509
|
+
size: "icon-sm",
|
|
151510
|
+
"aria-label": "Revert",
|
|
151511
|
+
title: "Revert",
|
|
151512
|
+
disabled: !hasDirtyDraft,
|
|
150856
151513
|
onClick: () => {
|
|
150857
|
-
|
|
150858
|
-
|
|
150859
|
-
|
|
150860
|
-
|
|
150861
|
-
});
|
|
151514
|
+
if (!isTextLikeFile(activeFile)) return;
|
|
151515
|
+
setDraftContent((current) => ({
|
|
151516
|
+
...current,
|
|
151517
|
+
[activeFile.path]: activeFile.content ?? ""
|
|
151518
|
+
}));
|
|
150862
151519
|
},
|
|
150863
|
-
children:
|
|
151520
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Undo2, { className: "h-3.5 w-3.5" })
|
|
151521
|
+
})
|
|
151522
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tooltip, {
|
|
151523
|
+
content: "Save",
|
|
151524
|
+
delay: 0,
|
|
151525
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
151526
|
+
variant: "primary",
|
|
151527
|
+
size: "icon-sm",
|
|
151528
|
+
"aria-label": "Save",
|
|
151529
|
+
title: "Save",
|
|
151530
|
+
disabled: !hasDirtyDraft || savingPath === currentFile.path,
|
|
151531
|
+
onClick: saveActiveDraft,
|
|
151532
|
+
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" })
|
|
151533
|
+
})
|
|
151534
|
+
})] }) : mode === "preview" && canPreviewRemote(activeFile) ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
151535
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tooltip, {
|
|
151536
|
+
content: "Refresh",
|
|
151537
|
+
delay: 0,
|
|
151538
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
151539
|
+
variant: "secondary",
|
|
151540
|
+
size: "icon-sm",
|
|
151541
|
+
"aria-label": "Refresh",
|
|
151542
|
+
title: "Refresh",
|
|
151543
|
+
onClick: () => {
|
|
151544
|
+
setPreviewByPath((current) => {
|
|
151545
|
+
const next = { ...current };
|
|
151546
|
+
delete next[currentFile.path];
|
|
151547
|
+
return next;
|
|
151548
|
+
});
|
|
151549
|
+
},
|
|
151550
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RefreshCw, { className: "h-3.5 w-3.5" })
|
|
151551
|
+
})
|
|
150864
151552
|
}),
|
|
150865
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
150866
|
-
|
|
150867
|
-
|
|
150868
|
-
|
|
150869
|
-
|
|
150870
|
-
|
|
150871
|
-
|
|
151553
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tooltip, {
|
|
151554
|
+
content: previewMaximized ? "Exit maximize" : "Maximize",
|
|
151555
|
+
delay: 0,
|
|
151556
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
151557
|
+
variant: "secondary",
|
|
151558
|
+
size: "icon-sm",
|
|
151559
|
+
"aria-label": previewMaximized ? "Exit maximize" : "Maximize",
|
|
151560
|
+
title: previewMaximized ? "Exit maximize" : "Maximize",
|
|
151561
|
+
onClick: () => {
|
|
151562
|
+
setPreviewMaximized((current) => !current);
|
|
151563
|
+
},
|
|
151564
|
+
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" })
|
|
151565
|
+
})
|
|
150872
151566
|
}),
|
|
150873
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
150874
|
-
|
|
150875
|
-
|
|
150876
|
-
|
|
150877
|
-
|
|
150878
|
-
|
|
150879
|
-
|
|
150880
|
-
|
|
150881
|
-
|
|
151567
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tooltip, {
|
|
151568
|
+
content: "Download",
|
|
151569
|
+
delay: 0,
|
|
151570
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
151571
|
+
variant: "secondary",
|
|
151572
|
+
size: "icon-sm",
|
|
151573
|
+
"aria-label": "Download",
|
|
151574
|
+
title: "Download",
|
|
151575
|
+
disabled: !previewDownloadUrl,
|
|
151576
|
+
onClick: () => {
|
|
151577
|
+
if (!previewDownloadUrl) return;
|
|
151578
|
+
triggerDownload(previewDownloadUrl, currentFile.path.split("/").pop() ?? "preview");
|
|
151579
|
+
},
|
|
151580
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Download, { className: "h-3.5 w-3.5" })
|
|
151581
|
+
})
|
|
150882
151582
|
}),
|
|
150883
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
150884
|
-
|
|
150885
|
-
|
|
150886
|
-
|
|
150887
|
-
|
|
150888
|
-
|
|
150889
|
-
|
|
150890
|
-
|
|
150891
|
-
|
|
150892
|
-
|
|
150893
|
-
|
|
150894
|
-
|
|
150895
|
-
|
|
150896
|
-
|
|
151583
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tooltip, {
|
|
151584
|
+
content: shareFeedback === "shared" ? "Shared" : shareFeedback === "copied" ? "Copied" : "Share",
|
|
151585
|
+
delay: 0,
|
|
151586
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
151587
|
+
variant: "secondary",
|
|
151588
|
+
size: "icon-sm",
|
|
151589
|
+
"aria-label": shareFeedback === "shared" ? "Shared" : shareFeedback === "copied" ? "Copied" : "Share",
|
|
151590
|
+
title: shareFeedback === "shared" ? "Shared" : shareFeedback === "copied" ? "Copied" : "Share",
|
|
151591
|
+
disabled: !previewShareUrl,
|
|
151592
|
+
onClick: () => {
|
|
151593
|
+
if (!previewShareUrl) return;
|
|
151594
|
+
sharePreview({
|
|
151595
|
+
url: previewShareUrl,
|
|
151596
|
+
title: currentFile.path
|
|
151597
|
+
}).then((shared) => {
|
|
151598
|
+
setShareFeedback(shared ? "shared" : "copied");
|
|
151599
|
+
});
|
|
151600
|
+
},
|
|
151601
|
+
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" })
|
|
151602
|
+
})
|
|
150897
151603
|
})
|
|
150898
151604
|
] }) : null
|
|
150899
151605
|
})]
|
|
@@ -150907,7 +151613,6 @@ function FolderEditorViewer({ changeId, archived = false, files: providedFiles }
|
|
|
150907
151613
|
preview,
|
|
150908
151614
|
loading: previewLoadingPath === currentFile.path,
|
|
150909
151615
|
error: previewError,
|
|
150910
|
-
frameHeight: canPreviewRemote(currentFile) ? remotePreviewHeight : void 0,
|
|
150911
151616
|
isDarkMode
|
|
150912
151617
|
})
|
|
150913
151618
|
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileExplorerCodeEditor, {
|
|
@@ -150939,7 +151644,7 @@ function FolderEditorViewer({ changeId, archived = false, files: providedFiles }
|
|
|
150939
151644
|
contentClassName: "px-3 py-3",
|
|
150940
151645
|
maxHeight: "96vh",
|
|
150941
151646
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
150942
|
-
className: "flex h-[80vh]
|
|
151647
|
+
className: "flex h-[80vh] max-h-[88vh] min-h-[420px] min-w-0 flex-col overflow-hidden",
|
|
150943
151648
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PreviewPane, {
|
|
150944
151649
|
file: activeFile,
|
|
150945
151650
|
preview,
|
|
@@ -151164,6 +151869,8 @@ function GlobContent({ changeId, artifact, translationConfig }) {
|
|
|
151164
151869
|
}
|
|
151165
151870
|
function ArtifactOutputViewer({ changeId, artifact }) {
|
|
151166
151871
|
const { data: config } = useConfigSubscription();
|
|
151872
|
+
const { data: globalSettings } = useGlobalSettingsSubscription();
|
|
151873
|
+
const translationConfig = resolveDocumentTranslationConfig(config?.translation, globalSettings);
|
|
151167
151874
|
if (artifact.files) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
151168
151875
|
className: "flex min-h-0 flex-1 flex-col",
|
|
151169
151876
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
@@ -151171,25 +151878,26 @@ function ArtifactOutputViewer({ changeId, artifact }) {
|
|
|
151171
151878
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArtifactFilesDocumentShell, {
|
|
151172
151879
|
artifact,
|
|
151173
151880
|
files: artifact.files,
|
|
151174
|
-
translationConfig
|
|
151881
|
+
translationConfig
|
|
151175
151882
|
})
|
|
151176
151883
|
})
|
|
151177
151884
|
});
|
|
151178
151885
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LiveArtifactOutputViewer, {
|
|
151179
151886
|
changeId,
|
|
151180
151887
|
artifact,
|
|
151181
|
-
translationConfig
|
|
151888
|
+
translationConfig
|
|
151182
151889
|
});
|
|
151183
151890
|
}
|
|
151184
151891
|
function ContentFallbackViewer({ fallback }) {
|
|
151185
151892
|
const { data: config } = useConfigSubscription();
|
|
151893
|
+
const { data: globalSettings } = useGlobalSettingsSubscription();
|
|
151186
151894
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
151187
151895
|
className: "flex min-h-0 flex-1 flex-col",
|
|
151188
151896
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
151189
151897
|
className: "min-h-0 flex-1",
|
|
151190
151898
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FallbackDocumentShell, {
|
|
151191
151899
|
fallback,
|
|
151192
|
-
translationConfig: config?.translation
|
|
151900
|
+
translationConfig: resolveDocumentTranslationConfig(config?.translation, globalSettings)
|
|
151193
151901
|
})
|
|
151194
151902
|
})
|
|
151195
151903
|
});
|
|
@@ -151786,6 +152494,89 @@ function renderAnsiLine(line) {
|
|
|
151786
152494
|
return parts.length > 0 ? parts : line;
|
|
151787
152495
|
}
|
|
151788
152496
|
//#endregion
|
|
152497
|
+
//#region src/components/scroll-spy.ts
|
|
152498
|
+
function hasVerticalScrollBehavior(overflowY) {
|
|
152499
|
+
return overflowY === "auto" || overflowY === "scroll" || overflowY === "overlay";
|
|
152500
|
+
}
|
|
152501
|
+
function findVerticalScrollContainer(node, options = {}) {
|
|
152502
|
+
const { allowNonScrollable = false } = options;
|
|
152503
|
+
let current = node?.parentElement ?? null;
|
|
152504
|
+
while (current) {
|
|
152505
|
+
if (hasVerticalScrollBehavior(window.getComputedStyle(current).overflowY)) {
|
|
152506
|
+
if (allowNonScrollable || current.scrollHeight > current.clientHeight) return current;
|
|
152507
|
+
}
|
|
152508
|
+
current = current.parentElement;
|
|
152509
|
+
}
|
|
152510
|
+
return null;
|
|
152511
|
+
}
|
|
152512
|
+
function scrollViewportBounds(root) {
|
|
152513
|
+
if (root) {
|
|
152514
|
+
const rect = root.getBoundingClientRect();
|
|
152515
|
+
return {
|
|
152516
|
+
top: rect.top,
|
|
152517
|
+
bottom: rect.bottom
|
|
152518
|
+
};
|
|
152519
|
+
}
|
|
152520
|
+
return {
|
|
152521
|
+
top: 0,
|
|
152522
|
+
bottom: window.innerHeight
|
|
152523
|
+
};
|
|
152524
|
+
}
|
|
152525
|
+
function measureAvailableViewportHeight(node, root = findVerticalScrollContainer(node, { allowNonScrollable: true })) {
|
|
152526
|
+
if (typeof window === "undefined" || !node) return null;
|
|
152527
|
+
const nodeRect = node.getBoundingClientRect();
|
|
152528
|
+
const viewport = scrollViewportBounds(root);
|
|
152529
|
+
return Math.max(Math.floor(viewport.bottom - Math.max(nodeRect.top, viewport.top)), 0);
|
|
152530
|
+
}
|
|
152531
|
+
function useViewportConstrainedHeight({ target, enabled = true }) {
|
|
152532
|
+
const [height, setHeight] = (0, import_react.useState)(null);
|
|
152533
|
+
(0, import_react.useLayoutEffect)(() => {
|
|
152534
|
+
if (!enabled || typeof window === "undefined") {
|
|
152535
|
+
setHeight(null);
|
|
152536
|
+
return;
|
|
152537
|
+
}
|
|
152538
|
+
if (!target) {
|
|
152539
|
+
setHeight(null);
|
|
152540
|
+
return;
|
|
152541
|
+
}
|
|
152542
|
+
let resizeObserver = null;
|
|
152543
|
+
let scrollRoot = null;
|
|
152544
|
+
let scrollTarget = window;
|
|
152545
|
+
const setConstrainedHeight = (nextHeight) => {
|
|
152546
|
+
setHeight((currentHeight) => currentHeight === nextHeight ? currentHeight : nextHeight);
|
|
152547
|
+
};
|
|
152548
|
+
const bindScrollRoot = (nextRoot) => {
|
|
152549
|
+
if (scrollRoot === nextRoot) return;
|
|
152550
|
+
scrollTarget.removeEventListener("scroll", handleUpdate);
|
|
152551
|
+
if (resizeObserver && scrollRoot) resizeObserver.unobserve(scrollRoot);
|
|
152552
|
+
scrollRoot = nextRoot;
|
|
152553
|
+
scrollTarget = nextRoot ?? window;
|
|
152554
|
+
scrollTarget.addEventListener("scroll", handleUpdate, { passive: true });
|
|
152555
|
+
if (resizeObserver && scrollRoot) resizeObserver.observe(scrollRoot);
|
|
152556
|
+
};
|
|
152557
|
+
const handleUpdate = () => {
|
|
152558
|
+
const nextRoot = findVerticalScrollContainer(target, { allowNonScrollable: true });
|
|
152559
|
+
bindScrollRoot(nextRoot);
|
|
152560
|
+
setConstrainedHeight(measureAvailableViewportHeight(target, nextRoot));
|
|
152561
|
+
};
|
|
152562
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
152563
|
+
resizeObserver = new ResizeObserver(() => {
|
|
152564
|
+
handleUpdate();
|
|
152565
|
+
});
|
|
152566
|
+
resizeObserver.observe(target);
|
|
152567
|
+
if (target.parentElement) resizeObserver.observe(target.parentElement);
|
|
152568
|
+
}
|
|
152569
|
+
handleUpdate();
|
|
152570
|
+
window.addEventListener("resize", handleUpdate);
|
|
152571
|
+
return () => {
|
|
152572
|
+
window.removeEventListener("resize", handleUpdate);
|
|
152573
|
+
scrollTarget.removeEventListener("scroll", handleUpdate);
|
|
152574
|
+
resizeObserver?.disconnect();
|
|
152575
|
+
};
|
|
152576
|
+
}, [enabled, target]);
|
|
152577
|
+
return height;
|
|
152578
|
+
}
|
|
152579
|
+
//#endregion
|
|
151789
152580
|
//#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
152581
|
function useControlled({ controlled, default: defaultProp, name, state = "value" }) {
|
|
151791
152582
|
const { current: isControlled } = import_react.useRef(controlled !== void 0);
|
|
@@ -158633,6 +159424,8 @@ function SpecView() {
|
|
|
158633
159424
|
const { data: spec, isLoading } = useSpecSubscription(specId);
|
|
158634
159425
|
const { data: rawMarkdown, isLoading: isRawLoading } = useSpecRawSubscription(specId);
|
|
158635
159426
|
const { data: config } = useConfigSubscription();
|
|
159427
|
+
const { data: globalSettings } = useGlobalSettingsSubscription();
|
|
159428
|
+
const translationConfig = (0, import_react.useMemo)(() => resolveDocumentTranslationConfig(config?.translation, globalSettings), [config?.translation, globalSettings]);
|
|
158636
159429
|
const validation = null;
|
|
158637
159430
|
if (isLoading && !spec || isRawLoading && !rawMarkdown) {
|
|
158638
159431
|
if (handoff) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
@@ -158678,7 +159471,7 @@ function SpecView() {
|
|
|
158678
159471
|
spec,
|
|
158679
159472
|
rawMarkdown: rawMarkdown ?? "",
|
|
158680
159473
|
validation,
|
|
158681
|
-
translationConfig
|
|
159474
|
+
translationConfig
|
|
158682
159475
|
});
|
|
158683
159476
|
}
|
|
158684
159477
|
function SpecContent({ spec, rawMarkdown, validation, translationConfig }) {
|