@waterwx/dsh-novel-forge 1.8.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -61,6 +61,18 @@ window.__ModuleLoader__.load({
61
61
  storyboardPrompts: "/api/dsh-novel-forge/storyboard/prompts",
62
62
  /** 生图接口连通性测试(设置页每个模型条目用)。 */
63
63
  imageTest: "/api/dsh-novel-forge/image-test",
64
+ /** LLM 模型连通性测试:真实最小调用,验证 Key / 端点 / 模型可用。 */
65
+ llmTest: "/api/dsh-novel-forge/llm-test",
66
+ /** 添加模型:厂商直填 key 或自定义路由,写进 DSH 凭据与 llm-pi-ai 路由。 */
67
+ addModel: "/api/dsh-novel-forge/llm-add",
68
+ /** 运行时厂商目录(DSH pi-ai 可配置提供方 + 内置适配器)。 */
69
+ llmVendors: "/api/dsh-novel-forge/llm-vendors",
70
+ /** 查询某个 provider 当前可用的模型(添加成功后可即时刷新)。 */
71
+ llmModels: "/api/dsh-novel-forge/llm-models",
72
+ /** 已注册的提供方路由列表(提供方管理)。 */
73
+ llmProviders: "/api/dsh-novel-forge/llm-providers",
74
+ /** 移除一个提供方。 */
75
+ llmRemove: "/api/dsh-novel-forge/llm-remove",
64
76
  /** 重置项目(可选携带新大纲):清空设定/卷/章节/伏笔/资产/事实库。 */
65
77
  reset: "/api/dsh-novel-forge/reset",
66
78
  /** 全书一致性质检:LLM 扫描已生成章节,输出矛盾问题清单。 */
@@ -129,6 +141,74 @@ window.__ModuleLoader__.load({
129
141
  /** 主题自定义背景:读取已上传文件(GET prefix,/theme/background/<name>)。 */
130
142
  themeBackgroundGet: "/api/dsh-novel-forge/theme/background"
131
143
  };
144
+ /** 预置的常见厂商(id=provider 路由;添加模型下拉兜底用,其余厂商由运行时目录动态补充)。 */
145
+ const LLM_VENDORS = [
146
+ {
147
+ id: "deepseek-official",
148
+ name: "DeepSeek",
149
+ route: "deepseek-official",
150
+ apiKeyEnv: "DEEPSEEK_API_KEY",
151
+ defaultModel: "deepseek-v4-flash",
152
+ models: [
153
+ "deepseek-v4-flash",
154
+ "deepseek-v4-pro",
155
+ "deepseek-chat",
156
+ "deepseek-reasoner"
157
+ ],
158
+ builtin: true
159
+ },
160
+ {
161
+ id: "zai-coding-cn",
162
+ name: "智谱 GLM",
163
+ route: "zai-coding-cn",
164
+ apiKeyEnv: "ZAI_CODING_CN_API_KEY",
165
+ defaultModel: "glm-5.3-flash",
166
+ models: [
167
+ "glm-4.5-air",
168
+ "glm-4.7",
169
+ "glm-5-turbo",
170
+ "glm-5.1",
171
+ "glm-5.2",
172
+ "glm-5.3",
173
+ "glm-5.3-flash",
174
+ "glm-5v-turbo"
175
+ ]
176
+ },
177
+ {
178
+ id: "qwen-token-plan-cn",
179
+ name: "千问百炼",
180
+ route: "qwen-token-plan-cn",
181
+ apiKeyEnv: "QWEN_TOKEN_PLAN_CN_API_KEY",
182
+ defaultModel: "qwen3.7-max",
183
+ models: [
184
+ "qwen3.6-flash",
185
+ "qwen3.6-plus",
186
+ "qwen3.7-max",
187
+ "qwen3.7-plus",
188
+ "qwen3.8-max",
189
+ "qwen3.8-max-preview"
190
+ ]
191
+ },
192
+ {
193
+ id: "openrouter",
194
+ name: "OpenRouter",
195
+ route: "openrouter",
196
+ apiKeyEnv: "OPENROUTER_API_KEY",
197
+ defaultModel: "z-ai/glm-5.3-flash",
198
+ models: [
199
+ "z-ai/glm-4.6",
200
+ "z-ai/glm-4.7",
201
+ "z-ai/glm-5",
202
+ "z-ai/glm-5-turbo",
203
+ "z-ai/glm-5.1",
204
+ "z-ai/glm-5.2",
205
+ "z-ai/glm-5.3-flash",
206
+ "auto",
207
+ "deepseek/deepseek-v4-flash",
208
+ "anthropic/claude-sonnet-4.6"
209
+ ]
210
+ }
211
+ ];
132
212
  //#endregion
133
213
  //#region src/client/api.ts
134
214
  /**
@@ -336,6 +416,33 @@ window.__ModuleLoader__.load({
336
416
  async imageTest(req) {
337
417
  return postJson(NOVEL_API.imageTest, req);
338
418
  }
419
+ /** 对选中的提供商/模型发一次最小真实调用,验证连通性。 */
420
+ async llmTest(provider, model) {
421
+ return postJson(NOVEL_API.llmTest, {
422
+ provider,
423
+ model
424
+ });
425
+ }
426
+ /** 添加模型:厂商直填 key,或自定义 OpenAI 兼容路由(写 DSH 凭据 + 注册路由)。 */
427
+ async addModel(req) {
428
+ return postJson(NOVEL_API.addModel, req);
429
+ }
430
+ /** 运行时厂商目录(DSH pi-ai 可配置提供方 + 内置适配器)。 */
431
+ async llmVendors() {
432
+ return readJson(await fetch(NOVEL_API.llmVendors));
433
+ }
434
+ /** 查询某个 provider 当前可用的模型(添加成功后可即时刷新)。 */
435
+ async llmModels(provider) {
436
+ return readJson(await fetch(NOVEL_API.llmModels + "?provider=" + encodeURIComponent(provider)));
437
+ }
438
+ /** 已注册的提供方路由列表(提供方管理卡片)。 */
439
+ async llmProviders() {
440
+ return readJson(await fetch(NOVEL_API.llmProviders));
441
+ }
442
+ /** 移除一个提供方(unset key + 移除 llm-pi-ai 路由)。 */
443
+ async removeProvider(req) {
444
+ return postJson(NOVEL_API.llmRemove, req);
445
+ }
339
446
  async roles(req) {
340
447
  return postJson(NOVEL_API.roles, req);
341
448
  }
@@ -742,7 +849,23 @@ window.__ModuleLoader__.load({
742
849
  "settings.provider": "模型提供商",
743
850
  "settings.model": "模型",
744
851
  "settings.modelCustom": "自定义…",
852
+ "settings.customProvider": "自定义提供商…",
853
+ "settings.edit": "编辑",
854
+ "settings.delete": "删除",
745
855
  "settings.modelCustomPlaceholder": "输入任意模型 id",
856
+ "settings.savedModels": "我的模型",
857
+ "settings.modelCards": "模型卡片(内置 + 已添加)",
858
+ "settings.savedModelName": "名称",
859
+ "settings.addModel": "添加模型",
860
+ "settings.catalogRefresh": "刷新厂商",
861
+ "settings.refreshModels": "刷新模型",
862
+ "settings.savedModelsHint": "手动添加常用模型(provider + 模型 id),点击即可切换当前模型;厂商模式会写入 DSH 凭据并注册路由。",
863
+ "settings.testConnection": "测试连通",
864
+ "settings.testRunning": "测试中",
865
+ "settings.testOk": "连通",
866
+ "settings.testFail": "失败",
867
+ "settings.testHint": "真实发送一次最小调用(约几十 token),验证 Key / 端点 / 模型可用。",
868
+ "settings.reasoningSection": "推理强度",
746
869
  "settings.reasoningEffort": "写作类任务思考强度 (reasoningEffort)",
747
870
  "settings.reasoningHint": "章节生成/润色/重写/审稿等写作任务使用;关掉更省更快。",
748
871
  "settings.analysisReasoning": "分析类任务思考强度(提炼/拆书/反推大纲)",
@@ -893,7 +1016,23 @@ window.__ModuleLoader__.load({
893
1016
  "settings.provider": "Provider",
894
1017
  "settings.model": "Model",
895
1018
  "settings.modelCustom": "Custom…",
1019
+ "settings.customProvider": "Custom provider…",
1020
+ "settings.edit": "Edit",
1021
+ "settings.delete": "Delete",
896
1022
  "settings.modelCustomPlaceholder": "Type any model id",
1023
+ "settings.savedModels": "My Models",
1024
+ "settings.modelCards": "Model cards (built-in + added)",
1025
+ "settings.savedModelName": "Name",
1026
+ "settings.addModel": "Add model",
1027
+ "settings.catalogRefresh": "Refresh vendors",
1028
+ "settings.refreshModels": "Refresh models",
1029
+ "settings.savedModelsHint": "Manually add a model (provider + model id); click to switch. Vendor mode writes the key into DSH credentials and registers the route.",
1030
+ "settings.testConnection": "Test",
1031
+ "settings.testRunning": "Testing",
1032
+ "settings.testOk": "OK",
1033
+ "settings.testFail": "Failed",
1034
+ "settings.testHint": "Sends one minimal real call (~dozens of tokens) to verify key / endpoint / model.",
1035
+ "settings.reasoningSection": "Reasoning",
897
1036
  "settings.reasoningEffort": "Writing-task reasoning effort",
898
1037
  "settings.analysisReasoning": "Analysis-task reasoning (extract / breakdown / reverse outline)",
899
1038
  "settings.analysisReasoningHint": "One-off analysis tasks (roles/scenes/bible extract, breakdown, reverse outline) default to low; not affected by the writing-level switch.",
@@ -35296,357 +35435,1088 @@ window.__ModuleLoader__.load({
35296
35435
  document.head.appendChild(tag);
35297
35436
  }
35298
35437
  var panel_module_css_default = {
35299
- "navAboutUpdate": "zE6uZW_navAboutUpdate",
35300
- "assetStat": "zE6uZW_assetStat",
35301
- "wsColumns": "zE6uZW_wsColumns",
35438
+ "diffAdd": "zE6uZW_diffAdd",
35439
+ "progressOverviewCard": "zE6uZW_progressOverviewCard",
35440
+ "toolStep": "zE6uZW_toolStep",
35441
+ "volumeGroupHeader": "zE6uZW_volumeGroupHeader",
35302
35442
  "authorRail": "zE6uZW_authorRail",
35303
- "spaceBetween": "zE6uZW_spaceBetween",
35304
- "dashHeroArrow": "zE6uZW_dashHeroArrow",
35305
- "diffSameBody": "zE6uZW_diffSameBody",
35306
- "assistantFloatHeader": "zE6uZW_assistantFloatHeader",
35307
- "shelfHero": "zE6uZW_shelfHero",
35308
- "importModalHead": "zE6uZW_importModalHead",
35309
- "bookChip": "zE6uZW_bookChip",
35310
- "diffLegend": "zE6uZW_diffLegend",
35311
- "shelfStatActive": "zE6uZW_shelfStatActive",
35312
- "panelBody": "zE6uZW_panelBody",
35313
- "panelNav": "zE6uZW_panelNav",
35314
- "dashHeroEyebrow": "zE6uZW_dashHeroEyebrow",
35315
- "tlSeg": "zE6uZW_tlSeg",
35316
- "todoWarning": "zE6uZW_todoWarning",
35317
- "dimCard": "zE6uZW_dimCard",
35443
+ "rowEnd": "zE6uZW_rowEnd",
35444
+ "readerSidebar": "zE6uZW_readerSidebar",
35445
+ "readerItemTitle": "zE6uZW_readerItemTitle",
35446
+ "importFileInfo": "zE6uZW_importFileInfo",
35447
+ "authorRailBtn": "zE6uZW_authorRailBtn",
35448
+ "adaptOutlinePre": "zE6uZW_adaptOutlinePre",
35449
+ "switchOn": "zE6uZW_switchOn",
35450
+ "progressLineLive": "zE6uZW_progressLineLive",
35451
+ "dashHeroTitle": "zE6uZW_dashHeroTitle",
35452
+ "bookSwitchCover": "zE6uZW_bookSwitchCover",
35453
+ "shelfStats": "zE6uZW_shelfStats",
35454
+ "wsSelectedText": "zE6uZW_wsSelectedText",
35455
+ "chatBubbleUser": "zE6uZW_chatBubbleUser",
35456
+ "badgeError": "zE6uZW_badgeError",
35457
+ "progressLive": "zE6uZW_progressLive",
35458
+ "readerBody": "zE6uZW_readerBody",
35459
+ "dashStageDot": "zE6uZW_dashStageDot",
35460
+ "assistantFloat": "zE6uZW_assistantFloat",
35461
+ "importError": "zE6uZW_importError",
35462
+ "adaptResult": "zE6uZW_adaptResult",
35463
+ "bookshelfLabel": "zE6uZW_bookshelfLabel",
35464
+ "bookChipRemove": "zE6uZW_bookChipRemove",
35465
+ "importField": "zE6uZW_importField",
35466
+ "tlBar": "zE6uZW_tlBar",
35467
+ "bookCardName": "zE6uZW_bookCardName",
35468
+ "bookCardCover": "zE6uZW_bookCardCover",
35469
+ "toolLive": "zE6uZW_toolLive",
35470
+ "shelfHeader": "zE6uZW_shelfHeader",
35318
35471
  "view": "zE6uZW_view",
35319
- "progressTotalBar": "zE6uZW_progressTotalBar",
35320
- "workflowLabel": "zE6uZW_workflowLabel",
35472
+ "bookAdd": "zE6uZW_bookAdd",
35473
+ "diffChange": "zE6uZW_diffChange",
35321
35474
  "navBadgePulse": "zE6uZW_navBadgePulse",
35322
- "dimTitle": "zE6uZW_dimTitle",
35323
- "navTabLabel": "zE6uZW_navTabLabel",
35324
- "progressBookActive": "zE6uZW_progressBookActive",
35325
- "readerItem": "zE6uZW_readerItem",
35326
- "importPreviewList": "zE6uZW_importPreviewList",
35327
- "volumeGroupHeader": "zE6uZW_volumeGroupHeader",
35328
- "diffAdd": "zE6uZW_diffAdd",
35329
- "entry": "zE6uZW_entry",
35330
- "dimCurrent": "zE6uZW_dimCurrent",
35475
+ "badgePending": "zE6uZW_badgePending",
35476
+ "assistantStatusBusy": "zE6uZW_assistantStatusBusy",
35477
+ "readerPara": "zE6uZW_readerPara",
35478
+ "chapterFocus": "zE6uZW_chapterFocus",
35479
+ "badgeDone": "zE6uZW_badgeDone",
35480
+ "dashHero": "zE6uZW_dashHero",
35481
+ "bookshelf": "zE6uZW_bookshelf",
35482
+ "importModalOverlay": "zE6uZW_importModalOverlay",
35483
+ "importHint": "zE6uZW_importHint",
35484
+ "workflowBody": "zE6uZW_workflowBody",
35331
35485
  "outlineReadonly": "zE6uZW_outlineReadonly",
35332
- "bookCreateCard": "zE6uZW_bookCreateCard",
35333
- "volumeGroupToggle": "zE6uZW_volumeGroupToggle",
35334
- "assetGrid": "zE6uZW_assetGrid",
35486
+ "progressBookFill": "zE6uZW_progressBookFill",
35487
+ "bookChipActive": "zE6uZW_bookChipActive",
35488
+ "bookChipName": "zE6uZW_bookChipName",
35489
+ "createBookView": "zE6uZW_createBookView",
35490
+ "diffNew": "zE6uZW_diffNew",
35491
+ "dashHeroSparkle": "zE6uZW_dashHeroSparkle",
35492
+ "assetLabel": "zE6uZW_assetLabel",
35493
+ "assetCardContent": "zE6uZW_assetCardContent",
35494
+ "readerFoot": "zE6uZW_readerFoot",
35495
+ "workflowDot": "zE6uZW_workflowDot",
35496
+ "dashFacts": "zE6uZW_dashFacts",
35497
+ "ideaCandidate": "zE6uZW_ideaCandidate",
35335
35498
  "workflowDotActive": "zE6uZW_workflowDotActive",
35336
- "chapterFocusPulse": "zE6uZW_chapterFocusPulse",
35337
- "dashStageCurrent": "zE6uZW_dashStageCurrent",
35338
- "bookAddCard": "zE6uZW_bookAddCard",
35339
- "readerItemBadge": "zE6uZW_readerItemBadge",
35340
- "navAbout": "zE6uZW_navAbout",
35341
- "toolSteps": "zE6uZW_toolSteps",
35342
- "diffList": "zE6uZW_diffList",
35343
- "assistantFloatBody": "zE6uZW_assistantFloatBody",
35344
- "toolStepError": "zE6uZW_toolStepError",
35345
- "dashJourneyBar": "zE6uZW_dashJourneyBar",
35346
- "card": "zE6uZW_card",
35347
- "authorPageBody": "zE6uZW_authorPageBody",
35348
- "dashJourney": "zE6uZW_dashJourney",
35499
+ "bookCardActions": "zE6uZW_bookCardActions",
35500
+ "liveText": "zE6uZW_liveText",
35501
+ "pulse": "zE6uZW_pulse",
35349
35502
  "diffSame": "zE6uZW_diffSame",
35350
- "importModalBody": "zE6uZW_importModalBody",
35351
- "chapter": "zE6uZW_chapter",
35352
- "readerMain": "zE6uZW_readerMain",
35353
- "wsPreviewText": "zE6uZW_wsPreviewText",
35354
- "readerGroupCount": "zE6uZW_readerGroupCount",
35355
- "bookshelfLabel": "zE6uZW_bookshelfLabel",
35356
- "navTitle": "zE6uZW_navTitle",
35357
- "badgePending": "zE6uZW_badgePending",
35358
- "navTitleBook": "zE6uZW_navTitleBook",
35503
+ "fieldLabel": "zE6uZW_fieldLabel",
35504
+ "diffList": "zE6uZW_diffList",
35505
+ "navGroupLabel": "zE6uZW_navGroupLabel",
35506
+ "assetGroup": "zE6uZW_assetGroup",
35507
+ "assistantFloatHeader": "zE6uZW_assistantFloatHeader",
35508
+ "dimCurrent": "zE6uZW_dimCurrent",
35509
+ "progressBookHead": "zE6uZW_progressBookHead",
35510
+ "diffLegend": "zE6uZW_diffLegend",
35511
+ "noticeError": "zE6uZW_noticeError",
35512
+ "bookCreateCard": "zE6uZW_bookCreateCard",
35513
+ "readerTitle": "zE6uZW_readerTitle",
35514
+ "bookSwitchMeta": "zE6uZW_bookSwitchMeta",
35359
35515
  "statCardD": "zE6uZW_statCardD",
35360
- "progress": "zE6uZW_progress",
35361
- "bookCardActive": "zE6uZW_bookCardActive",
35362
- "bookChipName": "zE6uZW_bookChipName",
35363
- "progressBarFill": "zE6uZW_progressBarFill",
35364
- "chatScroll": "zE6uZW_chatScroll",
35365
- "assetFilterChip": "zE6uZW_assetFilterChip",
35366
- "buttonSmall": "zE6uZW_buttonSmall",
35516
+ "wsColumns": "zE6uZW_wsColumns",
35517
+ "adaptTextarea": "zE6uZW_adaptTextarea",
35518
+ "diffTagOld": "zE6uZW_diffTagOld",
35519
+ "statRowD": "zE6uZW_statRowD",
35520
+ "tlSegFill": "zE6uZW_tlSegFill",
35521
+ "diffOld": "zE6uZW_diffOld",
35522
+ "workflowHint": "zE6uZW_workflowHint",
35523
+ "navTitleName": "zE6uZW_navTitleName",
35367
35524
  "chapterPreview": "zE6uZW_chapterPreview",
35368
- "dashHeroAction": "zE6uZW_dashHeroAction",
35369
- "shelfEmpty": "zE6uZW_shelfEmpty",
35370
- "authorRailTitle": "zE6uZW_authorRailTitle",
35525
+ "toolStepActive": "zE6uZW_toolStepActive",
35526
+ "progressBarFill": "zE6uZW_progressBarFill",
35527
+ "wsPreview": "zE6uZW_wsPreview",
35528
+ "assetStatValue": "zE6uZW_assetStatValue",
35529
+ "dashGrid": "zE6uZW_dashGrid",
35530
+ "shelfGrid": "zE6uZW_shelfGrid",
35531
+ "entry": "zE6uZW_entry",
35532
+ "progressLineDone": "zE6uZW_progressLineDone",
35533
+ "shelfFilterCount": "zE6uZW_shelfFilterCount",
35534
+ "fadeIn": "zE6uZW_fadeIn",
35535
+ "statCardDIcon": "zE6uZW_statCardDIcon",
35536
+ "readerText": "zE6uZW_readerText",
35537
+ "navTitleBook": "zE6uZW_navTitleBook",
35538
+ "readerLoading": "zE6uZW_readerLoading",
35539
+ "importPreview": "zE6uZW_importPreview",
35540
+ "buttonDanger": "zE6uZW_buttonDanger",
35541
+ "diffColumn": "zE6uZW_diffColumn",
35542
+ "wsPreviewText": "zE6uZW_wsPreviewText",
35543
+ "chatRole": "zE6uZW_chatRole",
35544
+ "chapterBeats": "zE6uZW_chapterBeats",
35545
+ "bookCreateOutline": "zE6uZW_bookCreateOutline",
35546
+ "volumeGroup": "zE6uZW_volumeGroup",
35547
+ "assistantResize": "zE6uZW_assistantResize",
35548
+ "panelTitle": "zE6uZW_panelTitle",
35549
+ "progressBook": "zE6uZW_progressBook",
35550
+ "readerChapterTitle": "zE6uZW_readerChapterTitle",
35551
+ "statCardDUnit": "zE6uZW_statCardDUnit",
35552
+ "readerError": "zE6uZW_readerError",
35553
+ "bookChip": "zE6uZW_bookChip",
35554
+ "dropzoneActive": "zE6uZW_dropzoneActive",
35555
+ "iconButton": "zE6uZW_iconButton",
35371
35556
  "toolStepName": "zE6uZW_toolStepName",
35372
- "assetGroupHeader": "zE6uZW_assetGroupHeader",
35557
+ "navGroupSep": "zE6uZW_navGroupSep",
35558
+ "readerSegBtn": "zE6uZW_readerSegBtn",
35559
+ "bigProgressBarFill": "zE6uZW_bigProgressBarFill",
35373
35560
  "bookCardBody": "zE6uZW_bookCardBody",
35374
- "dashStageDone": "zE6uZW_dashStageDone",
35375
- "progressBookFill": "zE6uZW_progressBookFill",
35376
- "bookCard": "zE6uZW_bookCard",
35377
- "ideaCard": "zE6uZW_ideaCard",
35378
- "dropzoneActive": "zE6uZW_dropzoneActive",
35561
+ "authorRailAbout": "zE6uZW_authorRailAbout",
35562
+ "readerHeader": "zE6uZW_readerHeader",
35563
+ "createBookTitle": "zE6uZW_createBookTitle",
35379
35564
  "statCardDValue": "zE6uZW_statCardDValue",
35380
- "badge": "zE6uZW_badge",
35381
- "bookCardProgressBar": "zE6uZW_bookCardProgressBar",
35382
- "shelfSearch": "zE6uZW_shelfSearch",
35383
- "bookChipRemove": "zE6uZW_bookChipRemove",
35384
- "input": "zE6uZW_input",
35385
- "bookChipMeta": "zE6uZW_bookChipMeta",
35386
- "navTabBadge": "zE6uZW_navTabBadge",
35387
- "assetStatValue": "zE6uZW_assetStatValue",
35565
+ "todoText": "zE6uZW_todoText",
35566
+ "dashStageCurrent": "zE6uZW_dashStageCurrent",
35567
+ "progressBookList": "zE6uZW_progressBookList",
35568
+ "bookCardCoverTitle": "zE6uZW_bookCardCoverTitle",
35569
+ "bookCardBlurb": "zE6uZW_bookCardBlurb",
35570
+ "ideaToggle": "zE6uZW_ideaToggle",
35571
+ "readerItem": "zE6uZW_readerItem",
35572
+ "fileList": "zE6uZW_fileList",
35573
+ "badgeRejected": "zE6uZW_badgeRejected",
35574
+ "dashJourneyFill": "zE6uZW_dashJourneyFill",
35575
+ "dashJourneyStages": "zE6uZW_dashJourneyStages",
35576
+ "assetFilterBar": "zE6uZW_assetFilterBar",
35577
+ "assetKind": "zE6uZW_assetKind",
35388
35578
  "dashHeroBook": "zE6uZW_dashHeroBook",
35389
- "adaptTable": "zE6uZW_adaptTable",
35390
- "workflowHint": "zE6uZW_workflowHint",
35391
- "navGroupSep": "zE6uZW_navGroupSep",
35392
- "diffColumn": "zE6uZW_diffColumn",
35393
- "importModal": "zE6uZW_importModal",
35394
- "adaptOutlinePre": "zE6uZW_adaptOutlinePre",
35579
+ "shelfFilters": "zE6uZW_shelfFilters",
35580
+ "shelfFilter": "zE6uZW_shelfFilter",
35581
+ "shelfStatActive": "zE6uZW_shelfStatActive",
35582
+ "shelfEmptyIcon": "zE6uZW_shelfEmptyIcon",
35583
+ "shelfFilterActive": "zE6uZW_shelfFilterActive",
35584
+ "createBookTop": "zE6uZW_createBookTop",
35585
+ "bookSwitchArrow": "zE6uZW_bookSwitchArrow",
35586
+ "shelfTitleRow": "zE6uZW_shelfTitleRow",
35587
+ "bookshelfList": "zE6uZW_bookshelfList",
35588
+ "navAbout": "zE6uZW_navAbout",
35589
+ "progressTotalFill": "zE6uZW_progressTotalFill",
35590
+ "navTitle": "zE6uZW_navTitle",
35395
35591
  "chatBubbleAssistant": "zE6uZW_chatBubbleAssistant",
35396
- "importResult": "zE6uZW_importResult",
35397
- "readerView": "zE6uZW_readerView",
35398
- "tlSegTrack": "zE6uZW_tlSegTrack",
35399
- "panelNavCollapsed": "zE6uZW_panelNavCollapsed",
35400
- "progressLine": "zE6uZW_progressLine",
35401
- "buttonPrimary": "zE6uZW_buttonPrimary",
35402
- "tab": "zE6uZW_tab",
35403
- "navTabBadgeWarn": "zE6uZW_navTabBadgeWarn",
35404
- "workflowDotDone": "zE6uZW_workflowDotDone",
35405
- "navGroup": "zE6uZW_navGroup",
35406
- "badgeGenerating": "zE6uZW_badgeGenerating",
35407
- "assetFilterBar": "zE6uZW_assetFilterBar",
35408
- "shelfEmptyTitle": "zE6uZW_shelfEmptyTitle",
35409
- "textarea": "zE6uZW_textarea",
35410
- "readerError": "zE6uZW_readerError",
35592
+ "assetStatLabel": "zE6uZW_assetStatLabel",
35593
+ "dashHeroArrow": "zE6uZW_dashHeroArrow",
35594
+ "shelfHero": "zE6uZW_shelfHero",
35595
+ "adaptInputCard": "zE6uZW_adaptInputCard",
35411
35596
  "shelfStat": "zE6uZW_shelfStat",
35412
- "authorPageHero": "zE6uZW_authorPageHero",
35413
- "fileList": "zE6uZW_fileList",
35414
- "readerSidebar": "zE6uZW_readerSidebar",
35415
- "importModalOverlay": "zE6uZW_importModalOverlay",
35416
- "navActionBtn": "zE6uZW_navActionBtn",
35417
- "statCardDIconRed": "zE6uZW_statCardDIconRed",
35418
- "assetCardName": "zE6uZW_assetCardName",
35419
- "navTitleName": "zE6uZW_navTitleName",
35420
- "assistantFloat": "zE6uZW_assistantFloat",
35421
- "entryIcon": "zE6uZW_entryIcon",
35422
- "chapterNum": "zE6uZW_chapterNum",
35423
- "readerGroupArrow": "zE6uZW_readerGroupArrow",
35424
- "assetTextarea": "zE6uZW_assetTextarea",
35425
- "createBookTop": "zE6uZW_createBookTop",
35597
+ "ideaCard": "zE6uZW_ideaCard",
35598
+ "readerSeg": "zE6uZW_readerSeg",
35599
+ "spaceBetween": "zE6uZW_spaceBetween",
35600
+ "readerItemBadge": "zE6uZW_readerItemBadge",
35601
+ "shelfView": "zE6uZW_shelfView",
35426
35602
  "switch": "zE6uZW_switch",
35427
- "tlSegFill": "zE6uZW_tlSegFill",
35428
- "dashStage": "zE6uZW_dashStage",
35429
- "busyRow": "zE6uZW_busyRow",
35430
- "dashFact": "zE6uZW_dashFact",
35603
+ "navTitleLogo": "zE6uZW_navTitleLogo",
35604
+ "importModalTabs": "zE6uZW_importModalTabs",
35605
+ "assetEditorRow": "zE6uZW_assetEditorRow",
35606
+ "navTabBadgeDanger": "zE6uZW_navTabBadgeDanger",
35607
+ "reviewBox": "zE6uZW_reviewBox",
35608
+ "toolSteps": "zE6uZW_toolSteps",
35609
+ "todoInfo": "zE6uZW_todoInfo",
35610
+ "dimTitle": "zE6uZW_dimTitle",
35611
+ "field": "zE6uZW_field",
35612
+ "assistantStatus": "zE6uZW_assistantStatus",
35613
+ "adaptProposal": "zE6uZW_adaptProposal",
35614
+ "legendOld": "zE6uZW_legendOld",
35615
+ "navActions": "zE6uZW_navActions",
35616
+ "volumeGroupToggle": "zE6uZW_volumeGroupToggle",
35617
+ "settingsCard": "zE6uZW_settingsCard",
35618
+ "dimCard": "zE6uZW_dimCard",
35619
+ "toolStepStatus": "zE6uZW_toolStepStatus",
35620
+ "wsAppliedBanner": "zE6uZW_wsAppliedBanner",
35621
+ "buttonSmall": "zE6uZW_buttonSmall",
35622
+ "buttonPrimary": "zE6uZW_buttonPrimary",
35431
35623
  "diffDel": "zE6uZW_diffDel",
35432
- "readerSegBtn": "zE6uZW_readerSegBtn",
35433
- "button": "zE6uZW_button",
35624
+ "assetFilterChip": "zE6uZW_assetFilterChip",
35625
+ "switchKnob": "zE6uZW_switchKnob",
35626
+ "tlSegLabel": "zE6uZW_tlSegLabel",
35627
+ "navActionBtn": "zE6uZW_navActionBtn",
35628
+ "bookAddIcon": "zE6uZW_bookAddIcon",
35434
35629
  "chapterMain": "zE6uZW_chapterMain",
35435
- "dashHero": "zE6uZW_dashHero",
35436
- "assetCardFooter": "zE6uZW_assetCardFooter",
35437
- "shelfFilters": "zE6uZW_shelfFilters",
35630
+ "workflowLabel": "zE6uZW_workflowLabel",
35631
+ "tlSegDone": "zE6uZW_tlSegDone",
35632
+ "assistantFloatBody": "zE6uZW_assistantFloatBody",
35633
+ "input": "zE6uZW_input",
35634
+ "diffText": "zE6uZW_diffText",
35635
+ "dashStage": "zE6uZW_dashStage",
35636
+ "coverPlaceholder": "zE6uZW_coverPlaceholder",
35637
+ "statCardDDown": "zE6uZW_statCardDDown",
35638
+ "bigProgressBar": "zE6uZW_bigProgressBar",
35639
+ "onlyChanges": "zE6uZW_onlyChanges",
35640
+ "assetGroupHeader": "zE6uZW_assetGroupHeader",
35641
+ "todoItem": "zE6uZW_todoItem",
35642
+ "assetFilterChipActive": "zE6uZW_assetFilterChipActive",
35643
+ "assetCard": "zE6uZW_assetCard",
35644
+ "shelfEmptyTitle": "zE6uZW_shelfEmptyTitle",
35645
+ "readerGroupArrow": "zE6uZW_readerGroupArrow",
35646
+ "busyRow": "zE6uZW_busyRow",
35647
+ "shelfToolbar": "zE6uZW_shelfToolbar",
35648
+ "bookCardTitleRow": "zE6uZW_bookCardTitleRow",
35649
+ "card": "zE6uZW_card",
35650
+ "chapterTitle": "zE6uZW_chapterTitle",
35651
+ "adaptMatrix": "zE6uZW_adaptMatrix",
35438
35652
  "dimCardHead": "zE6uZW_dimCardHead",
35439
- "navSpacer": "zE6uZW_navSpacer",
35440
- "wsSelected": "zE6uZW_wsSelected",
35441
- "toolStepStatus": "zE6uZW_toolStepStatus",
35442
- "rowEnd": "zE6uZW_rowEnd",
35443
- "dimCardSelected": "zE6uZW_dimCardSelected",
35444
- "createBookIcon": "zE6uZW_createBookIcon",
35445
- "readerChapterMeta": "zE6uZW_readerChapterMeta",
35446
- "bookCardBlurb": "zE6uZW_bookCardBlurb",
35447
- "helpTipText": "zE6uZW_helpTipText",
35448
- "bookAddIcon": "zE6uZW_bookAddIcon",
35449
- "tlSegCurrent": "zE6uZW_tlSegCurrent",
35450
- "readerSegActive": "zE6uZW_readerSegActive",
35451
- "createBookView": "zE6uZW_createBookView",
35452
- "dashHeroTitle": "zE6uZW_dashHeroTitle",
35453
- "navAboutRow": "zE6uZW_navAboutRow",
35454
- "bigProgressBarFill": "zE6uZW_bigProgressBarFill",
35455
- "coverPreview": "zE6uZW_coverPreview",
35653
+ "bookAddCard": "zE6uZW_bookAddCard",
35654
+ "createBookCard": "zE6uZW_createBookCard",
35655
+ "importModalActions": "zE6uZW_importModalActions",
35656
+ "workflowRow": "zE6uZW_workflowRow",
35657
+ "adaptOutline": "zE6uZW_adaptOutline",
35658
+ "diffSameBody": "zE6uZW_diffSameBody",
35659
+ "authorRailTitle": "zE6uZW_authorRailTitle",
35456
35660
  "panelContent": "zE6uZW_panelContent",
35457
- "onlyChanges": "zE6uZW_onlyChanges",
35458
- "adaptProposal": "zE6uZW_adaptProposal",
35459
- "wsEditor": "zE6uZW_wsEditor",
35460
- "fadeIn": "zE6uZW_fadeIn",
35461
- "dashStageDot": "zE6uZW_dashStageDot",
35462
- "assetGroup": "zE6uZW_assetGroup",
35463
- "adaptImpact": "zE6uZW_adaptImpact",
35464
- "dropzone": "zE6uZW_dropzone",
35465
- "importError": "zE6uZW_importError",
35466
- "navTabIcon": "zE6uZW_navTabIcon",
35467
- "wsSelectedText": "zE6uZW_wsSelectedText",
35468
- "bookSwitchCover": "zE6uZW_bookSwitchCover",
35469
- "tlSegTodo": "zE6uZW_tlSegTodo",
35470
- "workflowList": "zE6uZW_workflowList",
35471
- "adaptImpacts": "zE6uZW_adaptImpacts",
35472
- "volumeGroup": "zE6uZW_volumeGroup",
35473
- "shelfStats": "zE6uZW_shelfStats",
35474
- "ideaCandidate": "zE6uZW_ideaCandidate",
35475
- "chatBubbleUser": "zE6uZW_chatBubbleUser",
35476
- "readerItemNo": "zE6uZW_readerItemNo",
35477
- "bookCardCover": "zE6uZW_bookCardCover",
35478
- "bookshelfList": "zE6uZW_bookshelfList",
35479
- "row": "zE6uZW_row",
35480
- "dashFacts": "zE6uZW_dashFacts",
35481
- "chapterFocus": "zE6uZW_chapterFocus",
35482
- "diffChange": "zE6uZW_diffChange",
35661
+ "navAboutRow": "zE6uZW_navAboutRow",
35662
+ "panelNav": "zE6uZW_panelNav",
35663
+ "chapterFocusPulse": "zE6uZW_chapterFocusPulse",
35664
+ "entryIcon": "zE6uZW_entryIcon",
35665
+ "toolStepError": "zE6uZW_toolStepError",
35666
+ "progress": "zE6uZW_progress",
35667
+ "tab": "zE6uZW_tab",
35668
+ "dashHeroAction": "zE6uZW_dashHeroAction",
35483
35669
  "todoDanger": "zE6uZW_todoDanger",
35484
- "panel": "zE6uZW_panel",
35485
- "bookSwitch": "zE6uZW_bookSwitch",
35486
- "badgeError": "zE6uZW_badgeError",
35487
- "wsPageHeader": "zE6uZW_wsPageHeader",
35488
- "assistantResize": "zE6uZW_assistantResize",
35489
- "coverPlaceholder": "zE6uZW_coverPlaceholder",
35490
- "readerGroup": "zE6uZW_readerGroup",
35491
- "readerGroupTitle": "zE6uZW_readerGroupTitle",
35492
- "readerFoot": "zE6uZW_readerFoot",
35493
- "readerLoading": "zE6uZW_readerLoading",
35494
- "shelfFilter": "zE6uZW_shelfFilter",
35495
- "authorRailBtn": "zE6uZW_authorRailBtn",
35496
- "assetFilterChipActive": "zE6uZW_assetFilterChipActive",
35497
- "assetCardContent": "zE6uZW_assetCardContent",
35498
- "toolStepDetail": "zE6uZW_toolStepDetail",
35499
- "progressOverviewNum": "zE6uZW_progressOverviewNum",
35500
- "bookCardName": "zE6uZW_bookCardName",
35501
- "dashHeroSparkle": "zE6uZW_dashHeroSparkle",
35502
- "todoItem": "zE6uZW_todoItem",
35503
- "panelTitle": "zE6uZW_panelTitle",
35504
- "legendOld": "zE6uZW_legendOld",
35505
- "dashHeroActionTitle": "zE6uZW_dashHeroActionTitle",
35506
- "tlSegDone": "zE6uZW_tlSegDone",
35507
35670
  "dimEdit": "zE6uZW_dimEdit",
35508
- "shelfGrid": "zE6uZW_shelfGrid",
35509
- "assetCardTop": "zE6uZW_assetCardTop",
35510
- "authorRailBtnActive": "zE6uZW_authorRailBtnActive",
35511
- "iconBtn": "zE6uZW_iconBtn",
35512
- "iconButton": "zE6uZW_iconButton",
35513
- "workflowDot": "zE6uZW_workflowDot",
35514
- "bookCardCoverTitle": "zE6uZW_bookCardCoverTitle",
35515
- "readerSeg": "zE6uZW_readerSeg",
35516
- "diffTagNew": "zE6uZW_diffTagNew",
35517
- "importHint": "zE6uZW_importHint",
35518
- "switchOn": "zE6uZW_switchOn",
35519
- "bookAdd": "zE6uZW_bookAdd",
35520
- "progressLive": "zE6uZW_progressLive",
35521
- "workflowRow": "zE6uZW_workflowRow",
35522
- "progressBookBar": "zE6uZW_progressBookBar",
35523
- "readerItemActive": "zE6uZW_readerItemActive",
35524
- "readerPara": "zE6uZW_readerPara",
35525
- "workflowBody": "zE6uZW_workflowBody",
35526
- "dashJourneyFill": "zE6uZW_dashJourneyFill",
35527
- "reviewBox": "zE6uZW_reviewBox",
35528
- "meta": "zE6uZW_meta",
35529
- "authorPageHeader": "zE6uZW_authorPageHeader",
35530
- "bookCardProgressFill": "zE6uZW_bookCardProgressFill",
35531
- "importPreview": "zE6uZW_importPreview",
35671
+ "adaptImpact": "zE6uZW_adaptImpact",
35672
+ "progressOverview": "zE6uZW_progressOverview",
35673
+ "tlSegCurrent": "zE6uZW_tlSegCurrent",
35532
35674
  "bookCardMetaRow": "zE6uZW_bookCardMetaRow",
35675
+ "dropzoneIcon": "zE6uZW_dropzoneIcon",
35533
35676
  "statCardDDetail": "zE6uZW_statCardDDetail",
35534
- "progressBookHead": "zE6uZW_progressBookHead",
35535
- "assetKind": "zE6uZW_assetKind",
35536
- "importModalTabs": "zE6uZW_importModalTabs",
35537
- "statCardDUnit": "zE6uZW_statCardDUnit",
35538
- "navTitleLogo": "zE6uZW_navTitleLogo",
35539
- "bookCreateOutline": "zE6uZW_bookCreateOutline",
35540
- "progressOverview": "zE6uZW_progressOverview",
35541
- "shelfView": "zE6uZW_shelfView",
35677
+ "dashFact": "zE6uZW_dashFact",
35678
+ "navTabBadgeLive": "zE6uZW_navTabBadgeLive",
35542
35679
  "readerArticle": "zE6uZW_readerArticle",
35543
- "field": "zE6uZW_field",
35544
- "progressBookName": "zE6uZW_progressBookName",
35545
- "chapterActions": "zE6uZW_chapterActions",
35546
- "shelfEmptyIcon": "zE6uZW_shelfEmptyIcon",
35547
- "importModalActions": "zE6uZW_importModalActions",
35548
- "badgeRejected": "zE6uZW_badgeRejected",
35549
- "createBookTitle": "zE6uZW_createBookTitle",
35550
- "adaptOutline": "zE6uZW_adaptOutline",
35551
- "liveText": "zE6uZW_liveText",
35552
- "bookshelf": "zE6uZW_bookshelf",
35553
- "navActions": "zE6uZW_navActions",
35554
- "createBookCard": "zE6uZW_createBookCard",
35555
- "readerItemTitle": "zE6uZW_readerItemTitle",
35556
- "buttonDanger": "zE6uZW_buttonDanger",
35557
- "badgeWritten": "zE6uZW_badgeWritten",
35558
- "todoText": "zE6uZW_todoText",
35559
- "adaptInputCard": "zE6uZW_adaptInputCard",
35560
- "dashGrid": "zE6uZW_dashGrid",
35561
- "wsPreview": "zE6uZW_wsPreview",
35562
- "progressBar": "zE6uZW_progressBar",
35563
- "readerBody": "zE6uZW_readerBody",
35564
- "switchKnob": "zE6uZW_switchKnob",
35565
- "navTabBadgeDanger": "zE6uZW_navTabBadgeDanger",
35566
- "dashHeroActionBody": "zE6uZW_dashHeroActionBody",
35567
- "bookSwitchName": "zE6uZW_bookSwitchName",
35568
- "statRowD": "zE6uZW_statRowD",
35569
- "diffTagOld": "zE6uZW_diffTagOld",
35570
- "bookSwitchMeta": "zE6uZW_bookSwitchMeta",
35571
- "chapterTitle": "zE6uZW_chapterTitle",
35572
- "toolStep": "zE6uZW_toolStep",
35573
- "assetStatLabel": "zE6uZW_assetStatLabel",
35574
- "bigProgressBar": "zE6uZW_bigProgressBar",
35575
- "assetGroups": "zE6uZW_assetGroups",
35576
- "entryLabel": "zE6uZW_entryLabel",
35577
- "authorHome": "zE6uZW_authorHome",
35578
- "adaptResult": "zE6uZW_adaptResult",
35579
- "progressTotalFill": "zE6uZW_progressTotalFill",
35580
- "helpTip": "zE6uZW_helpTip",
35581
- "ideaToggle": "zE6uZW_ideaToggle",
35582
35680
  "toolStepIcon": "zE6uZW_toolStepIcon",
35583
- "shelfFilterActive": "zE6uZW_shelfFilterActive",
35584
- "authorRailAbout": "zE6uZW_authorRailAbout",
35585
- "settingsCard": "zE6uZW_settingsCard",
35586
- "navTab": "zE6uZW_navTab",
35587
- "assetEditor": "zE6uZW_assetEditor",
35588
- "assetEditorRow": "zE6uZW_assetEditorRow",
35589
- "diffText": "zE6uZW_diffText",
35681
+ "progressTotalBar": "zE6uZW_progressTotalBar",
35682
+ "wsColumn": "zE6uZW_wsColumn",
35683
+ "dashJourney": "zE6uZW_dashJourney",
35684
+ "chapterNum": "zE6uZW_chapterNum",
35685
+ "progressBookActive": "zE6uZW_progressBookActive",
35590
35686
  "navTabBadgeDone": "zE6uZW_navTabBadgeDone",
35591
- "progressOverviewCard": "zE6uZW_progressOverviewCard",
35687
+ "dashHeroActionBody": "zE6uZW_dashHeroActionBody",
35688
+ "shelfSearch": "zE6uZW_shelfSearch",
35689
+ "bookCardActive": "zE6uZW_bookCardActive",
35690
+ "assetCardFooter": "zE6uZW_assetCardFooter",
35691
+ "tlSeg": "zE6uZW_tlSeg",
35692
+ "navTabBadgeWarn": "zE6uZW_navTabBadgeWarn",
35693
+ "authorRailBtnActive": "zE6uZW_authorRailBtnActive",
35592
35694
  "genreDesc": "zE6uZW_genreDesc",
35593
- "wsPage": "zE6uZW_wsPage",
35594
- "todoInfo": "zE6uZW_todoInfo",
35595
- "readerChapterTitle": "zE6uZW_readerChapterTitle",
35596
- "importFileInfo": "zE6uZW_importFileInfo",
35597
- "tlBar": "zE6uZW_tlBar",
35598
- "assistantStatusBusy": "zE6uZW_assistantStatusBusy",
35599
- "tlSegLabel": "zE6uZW_tlSegLabel",
35600
- "statCardDIcon": "zE6uZW_statCardDIcon",
35601
- "chatRole": "zE6uZW_chatRole",
35602
- "toolLive": "zE6uZW_toolLive",
35603
- "dropzoneIcon": "zE6uZW_dropzoneIcon",
35604
- "progressBook": "zE6uZW_progressBook",
35605
- "bookSwitchArrow": "zE6uZW_bookSwitchArrow",
35606
- "readerText": "zE6uZW_readerText",
35607
- "readerHeader": "zE6uZW_readerHeader",
35608
- "adaptMatrix": "zE6uZW_adaptMatrix",
35609
- "badgeDone": "zE6uZW_badgeDone",
35610
- "fieldLabel": "zE6uZW_fieldLabel",
35611
- "toolStepActive": "zE6uZW_toolStepActive",
35695
+ "wsEditor": "zE6uZW_wsEditor",
35696
+ "progressLineError": "zE6uZW_progressLineError",
35697
+ "importModal": "zE6uZW_importModal",
35698
+ "readerItemNo": "zE6uZW_readerItemNo",
35699
+ "navAboutUpdate": "zE6uZW_navAboutUpdate",
35700
+ "tlSegTodo": "zE6uZW_tlSegTodo",
35701
+ "authorContent": "zE6uZW_authorContent",
35702
+ "row": "zE6uZW_row",
35703
+ "authorPageBody": "zE6uZW_authorPageBody",
35704
+ "readerView": "zE6uZW_readerView",
35705
+ "assetCardName": "zE6uZW_assetCardName",
35706
+ "navTabBadge": "zE6uZW_navTabBadge",
35707
+ "dashHeroEyebrow": "zE6uZW_dashHeroEyebrow",
35708
+ "readerItemActive": "zE6uZW_readerItemActive",
35709
+ "assetStatDetail": "zE6uZW_assetStatDetail",
35710
+ "chapterActions": "zE6uZW_chapterActions",
35711
+ "statCardDIconRed": "zE6uZW_statCardDIconRed",
35712
+ "panel": "zE6uZW_panel",
35713
+ "textarea": "zE6uZW_textarea",
35714
+ "wsPageHeader": "zE6uZW_wsPageHeader",
35715
+ "dashJourneyBar": "zE6uZW_dashJourneyBar",
35716
+ "panelBody": "zE6uZW_panelBody",
35717
+ "meta": "zE6uZW_meta",
35718
+ "navTabLabel": "zE6uZW_navTabLabel",
35719
+ "chapterList": "zE6uZW_chapterList",
35720
+ "badge": "zE6uZW_badge",
35721
+ "assetGroups": "zE6uZW_assetGroups",
35722
+ "todoWarning": "zE6uZW_todoWarning",
35723
+ "assetEditor": "zE6uZW_assetEditor",
35724
+ "progressBookBar": "zE6uZW_progressBookBar",
35725
+ "dropzone": "zE6uZW_dropzone",
35726
+ "readerGroupTitle": "zE6uZW_readerGroupTitle",
35727
+ "readerGroupCount": "zE6uZW_readerGroupCount",
35612
35728
  "legendNew": "zE6uZW_legendNew",
35613
- "assetLabel": "zE6uZW_assetLabel",
35729
+ "diffTagNew": "zE6uZW_diffTagNew",
35614
35730
  "cardTitle": "zE6uZW_cardTitle",
35615
- "shelfToolbar": "zE6uZW_shelfToolbar",
35616
- "bookCardCoverFallback": "zE6uZW_bookCardCoverFallback",
35617
- "bookCardTitleRow": "zE6uZW_bookCardTitleRow",
35618
- "progressLineDone": "zE6uZW_progressLineDone",
35619
- "importField": "zE6uZW_importField",
35620
- "adaptTextarea": "zE6uZW_adaptTextarea",
35621
- "statCardDDown": "zE6uZW_statCardDDown",
35622
- "assetCard": "zE6uZW_assetCard",
35623
- "readerTitle": "zE6uZW_readerTitle",
35624
- "shelfFilterCount": "zE6uZW_shelfFilterCount",
35625
- "assistantStatus": "zE6uZW_assistantStatus",
35626
- "shelfTitleRow": "zE6uZW_shelfTitleRow",
35627
- "progressLineLive": "zE6uZW_progressLineLive",
35628
- "dashJourneyStages": "zE6uZW_dashJourneyStages",
35731
+ "shelfEmpty": "zE6uZW_shelfEmpty",
35629
35732
  "statCardDLabel": "zE6uZW_statCardDLabel",
35630
- "bookChipActive": "zE6uZW_bookChipActive",
35631
- "chapterBeats": "zE6uZW_chapterBeats",
35632
- "assetStatDetail": "zE6uZW_assetStatDetail",
35633
- "pulse": "zE6uZW_pulse",
35634
- "navTabBadgeLive": "zE6uZW_navTabBadgeLive",
35635
- "shelfHeader": "zE6uZW_shelfHeader",
35733
+ "readerMain": "zE6uZW_readerMain",
35734
+ "importPreviewList": "zE6uZW_importPreviewList",
35735
+ "dashHeroActionTitle": "zE6uZW_dashHeroActionTitle",
35736
+ "bookCard": "zE6uZW_bookCard",
35737
+ "workflowList": "zE6uZW_workflowList",
35636
35738
  "bookCreateForm": "zE6uZW_bookCreateForm",
35637
- "bookCardActions": "zE6uZW_bookCardActions",
35638
- "progressLineError": "zE6uZW_progressLineError",
35639
- "noticeError": "zE6uZW_noticeError",
35739
+ "navTabIcon": "zE6uZW_navTabIcon",
35740
+ "navSpacer": "zE6uZW_navSpacer",
35741
+ "navGroup": "zE6uZW_navGroup",
35742
+ "workflowDotDone": "zE6uZW_workflowDotDone",
35743
+ "wsSelected": "zE6uZW_wsSelected",
35744
+ "progressBookName": "zE6uZW_progressBookName",
35745
+ "assetCardTop": "zE6uZW_assetCardTop",
35746
+ "progressOverviewNum": "zE6uZW_progressOverviewNum",
35747
+ "adaptTable": "zE6uZW_adaptTable",
35748
+ "bookSwitch": "zE6uZW_bookSwitch",
35749
+ "entryLabel": "zE6uZW_entryLabel",
35750
+ "adaptImpacts": "zE6uZW_adaptImpacts",
35751
+ "bookCardCoverFallback": "zE6uZW_bookCardCoverFallback",
35752
+ "importModalHead": "zE6uZW_importModalHead",
35753
+ "badgeGenerating": "zE6uZW_badgeGenerating",
35754
+ "badgeWritten": "zE6uZW_badgeWritten",
35755
+ "createBookIcon": "zE6uZW_createBookIcon",
35756
+ "tlSegTrack": "zE6uZW_tlSegTrack",
35757
+ "toolStepDetail": "zE6uZW_toolStepDetail",
35758
+ "bookSwitchName": "zE6uZW_bookSwitchName",
35759
+ "assetGrid": "zE6uZW_assetGrid",
35760
+ "panelNavCollapsed": "zE6uZW_panelNavCollapsed",
35761
+ "authorPageHero": "zE6uZW_authorPageHero",
35762
+ "chapter": "zE6uZW_chapter",
35763
+ "chatScroll": "zE6uZW_chatScroll",
35764
+ "iconBtn": "zE6uZW_iconBtn",
35765
+ "navTab": "zE6uZW_navTab",
35766
+ "bookCardProgressFill": "zE6uZW_bookCardProgressFill",
35767
+ "bookChipMeta": "zE6uZW_bookChipMeta",
35768
+ "readerSegActive": "zE6uZW_readerSegActive",
35769
+ "bookCardProgressBar": "zE6uZW_bookCardProgressBar",
35770
+ "readerGroup": "zE6uZW_readerGroup",
35771
+ "readerChapterMeta": "zE6uZW_readerChapterMeta",
35772
+ "dimCardSelected": "zE6uZW_dimCardSelected",
35640
35773
  "tabBar": "zE6uZW_tabBar",
35641
- "diffNew": "zE6uZW_diffNew",
35642
- "progressBookList": "zE6uZW_progressBookList",
35643
- "navGroupLabel": "zE6uZW_navGroupLabel",
35644
- "chapterList": "zE6uZW_chapterList",
35645
- "authorContent": "zE6uZW_authorContent",
35646
- "diffOld": "zE6uZW_diffOld",
35647
- "wsAppliedBanner": "zE6uZW_wsAppliedBanner",
35648
- "wsColumn": "zE6uZW_wsColumn"
35774
+ "button": "zE6uZW_button",
35775
+ "progressLine": "zE6uZW_progressLine",
35776
+ "dashStageDone": "zE6uZW_dashStageDone",
35777
+ "importModalBody": "zE6uZW_importModalBody",
35778
+ "assetTextarea": "zE6uZW_assetTextarea",
35779
+ "helpTip": "zE6uZW_helpTip",
35780
+ "authorHome": "zE6uZW_authorHome",
35781
+ "progressBar": "zE6uZW_progressBar",
35782
+ "importResult": "zE6uZW_importResult",
35783
+ "helpTipText": "zE6uZW_helpTipText",
35784
+ "wsPage": "zE6uZW_wsPage",
35785
+ "authorPageHeader": "zE6uZW_authorPageHeader",
35786
+ "coverPreview": "zE6uZW_coverPreview",
35787
+ "assetStat": "zE6uZW_assetStat"
35788
+ };
35789
+ //#endregion
35790
+ //#region src/client/panel/ModelManager.tsx
35791
+ /**
35792
+ * 模型管理(DSH 风格):两块分区——
35793
+ * ① 模型(提供方管理):提供方卡片(编辑/删除)+ 添加提供方 / 添加自定义提供方;
35794
+ * ② 当前写作模型:提供商/模型下拉 + 测试连通 + 推理强度。
35795
+ */
35796
+ /** 目录不可用时回退的内置预设(历史行为)。 */
35797
+ const FALLBACK_MODEL_PRESETS = [
35798
+ "deepseek-v4-flash",
35799
+ "deepseek-v4-pro",
35800
+ "deepseek-chat",
35801
+ "deepseek-reasoner"
35802
+ ];
35803
+ const CUSTOM = "__custom__";
35804
+ function fallbackVendors() {
35805
+ return LLM_VENDORS.map((v) => ({
35806
+ id: v.route,
35807
+ name: v.name,
35808
+ models: v.models,
35809
+ apiKeyEnv: v.apiKeyEnv,
35810
+ builtin: v.builtin
35811
+ }));
35812
+ }
35813
+ function ModelManager({ api, provider, model, onProvider, onModel }) {
35814
+ const [configuredProviders, setConfiguredProviders] = (0, react.useState)([]);
35815
+ const [providerModels, setProviderModels] = (0, react.useState)([]);
35816
+ const [modelsLoading, setModelsLoading] = (0, react.useState)(false);
35817
+ const [providerCustom, setProviderCustom] = (0, react.useState)(false);
35818
+ const [modelCustom, setModelCustom] = (0, react.useState)(false);
35819
+ const [test, setTest] = (0, react.useState)({ testing: false });
35820
+ const [vendors, setVendors] = (0, react.useState)(fallbackVendors());
35821
+ const [addPanel, setAddPanel] = (0, react.useState)("none");
35822
+ const [editTarget, setEditTarget] = (0, react.useState)("");
35823
+ const [vendorId, setVendorId] = (0, react.useState)("zai-coding-cn");
35824
+ const [addModel, setAddModel] = (0, react.useState)("");
35825
+ const [addApiKey, setAddApiKey] = (0, react.useState)("");
35826
+ const [addName, setAddName] = (0, react.useState)("");
35827
+ const [custProvider, setCustProvider] = (0, react.useState)("");
35828
+ const [custName, setCustName] = (0, react.useState)("");
35829
+ const [custBaseURL, setCustBaseURL] = (0, react.useState)("");
35830
+ const [custProtocol, setCustProtocol] = (0, react.useState)("openai-completions");
35831
+ const [custModel, setCustModel] = (0, react.useState)("");
35832
+ const [custApiKey, setCustApiKey] = (0, react.useState)("");
35833
+ const [savingAdd, setSavingAdd] = (0, react.useState)(false);
35834
+ const [addMsg, setAddMsg] = (0, react.useState)("");
35835
+ const [addErr, setAddErr] = (0, react.useState)("");
35836
+ const loadProviders = (0, react.useCallback)(async () => {
35837
+ try {
35838
+ const r = await api.llmProviders();
35839
+ if (r.providers.length > 0) setConfiguredProviders(r.providers);
35840
+ } catch {}
35841
+ }, [api]);
35842
+ const loadVendors = (0, react.useCallback)(async () => {
35843
+ try {
35844
+ const r = await api.llmVendors();
35845
+ if (r.vendors.length > 0) setVendors(r.vendors);
35846
+ } catch {}
35847
+ }, [api]);
35848
+ const loadProviderModels = (0, react.useCallback)(async (p) => {
35849
+ setModelsLoading(true);
35850
+ try {
35851
+ const r = await api.llmModels(p);
35852
+ setProviderModels(r.models);
35853
+ } catch {
35854
+ setProviderModels([]);
35855
+ } finally {
35856
+ setModelsLoading(false);
35857
+ }
35858
+ }, [api]);
35859
+ (0, react.useEffect)(() => {
35860
+ loadProviders();
35861
+ loadVendors();
35862
+ }, [
35863
+ api,
35864
+ loadProviders,
35865
+ loadVendors
35866
+ ]);
35867
+ (0, react.useEffect)(() => {
35868
+ if (provider !== "") loadProviderModels(provider);
35869
+ }, [provider, loadProviderModels]);
35870
+ const currentVendor = vendors.find((v) => v.id === vendorId);
35871
+ const runTest = async () => {
35872
+ const p = provider.trim();
35873
+ const m = model.trim();
35874
+ if (p === "" || m === "" || test.testing) return;
35875
+ setTest({ testing: true });
35876
+ try {
35877
+ const r = await api.llmTest(p, m);
35878
+ setTest({
35879
+ testing: false,
35880
+ ok: r.ok,
35881
+ ms: r.ms,
35882
+ message: r.message
35883
+ });
35884
+ } catch (err) {
35885
+ setTest({
35886
+ testing: false,
35887
+ ok: false,
35888
+ message: err.message
35889
+ });
35890
+ }
35891
+ };
35892
+ const openPanel = (panel, target = "") => {
35893
+ setAddPanel(panel);
35894
+ setEditTarget(target);
35895
+ setAddMsg("");
35896
+ setAddErr("");
35897
+ if (panel === "standard") {
35898
+ setVendorId(target !== "" ? target : "zai-coding-cn");
35899
+ setAddModel("");
35900
+ setAddApiKey("");
35901
+ setAddName("");
35902
+ } else if (panel === "custom") {
35903
+ setCustProvider(target);
35904
+ setCustName("");
35905
+ setCustBaseURL("");
35906
+ setCustModel("");
35907
+ setCustApiKey("");
35908
+ }
35909
+ };
35910
+ const saveStandard = async () => {
35911
+ if (vendorId.trim() === "") {
35912
+ setAddErr("请选择提供方");
35913
+ return;
35914
+ }
35915
+ if (addApiKey.trim() === "") {
35916
+ setAddErr("请填写 API 密钥(或留空使用环境认证)");
35917
+ return;
35918
+ }
35919
+ const modelId = addModel.trim();
35920
+ setSavingAdd(true);
35921
+ setAddMsg("");
35922
+ setAddErr("");
35923
+ try {
35924
+ const res = await api.addModel({
35925
+ mode: "vendor",
35926
+ vendor: vendorId,
35927
+ model: modelId || vendorId,
35928
+ apiKey: addApiKey.trim(),
35929
+ apiKeyEnv: currentVendor?.apiKeyEnv,
35930
+ name: addName.trim() || void 0
35931
+ });
35932
+ setAddMsg(res.message ?? "已保存");
35933
+ setAddPanel("none");
35934
+ setAddApiKey("");
35935
+ setAddModel("");
35936
+ setAddName("");
35937
+ setEditTarget("");
35938
+ await loadProviders();
35939
+ } catch (err) {
35940
+ setAddErr(err.message);
35941
+ } finally {
35942
+ setSavingAdd(false);
35943
+ }
35944
+ };
35945
+ const saveCustom = async () => {
35946
+ if (custProvider.trim() === "") {
35947
+ setAddErr("请填 Provider ID");
35948
+ return;
35949
+ }
35950
+ if (custBaseURL.trim() === "") {
35951
+ setAddErr("请填 API 地址");
35952
+ return;
35953
+ }
35954
+ if (custApiKey.trim() === "") {
35955
+ setAddErr("请填 API 密钥(或留空使用环境认证)");
35956
+ return;
35957
+ }
35958
+ if (custModel.trim() === "") {
35959
+ setAddErr("请填模型 id(或点“获取可用模型”)");
35960
+ return;
35961
+ }
35962
+ setSavingAdd(true);
35963
+ setAddMsg("");
35964
+ setAddErr("");
35965
+ try {
35966
+ const res = await api.addModel({
35967
+ mode: "custom",
35968
+ provider: custProvider.trim(),
35969
+ model: custModel.trim(),
35970
+ apiKey: custApiKey.trim(),
35971
+ baseURL: custBaseURL.trim(),
35972
+ name: custName.trim() || void 0
35973
+ });
35974
+ setAddMsg(res.message ?? "已创建提供方");
35975
+ setAddPanel("none");
35976
+ setCustProvider("");
35977
+ setCustName("");
35978
+ setCustBaseURL("");
35979
+ setCustModel("");
35980
+ setCustApiKey("");
35981
+ await loadProviders();
35982
+ } catch (err) {
35983
+ setAddErr(err.message);
35984
+ } finally {
35985
+ setSavingAdd(false);
35986
+ }
35987
+ };
35988
+ const removeProvider = async (p) => {
35989
+ if (!window.confirm("删除提供方「" + (p.name !== "" ? p.name : p.id) + "」?将移除 DSH 配置与 API 密钥。")) return;
35990
+ try {
35991
+ const vendor = vendors.find((v) => v.id === p.id);
35992
+ await api.removeProvider({
35993
+ provider: p.id,
35994
+ apiKeyEnv: vendor?.apiKeyEnv
35995
+ });
35996
+ await loadProviders();
35997
+ } catch (err) {
35998
+ setAddErr(err.message);
35999
+ }
36000
+ };
36001
+ const providerOptions = configuredProviders.some((p) => p.id === provider) ? configuredProviders : provider !== "" && provider !== CUSTOM ? [{
36002
+ id: provider,
36003
+ name: provider
36004
+ }, ...configuredProviders] : configuredProviders;
36005
+ const modelOptions = modelCustom ? [] : provider === "deepseek-official" ? [...FALLBACK_MODEL_PRESETS.map((id) => ({
36006
+ id,
36007
+ name: id
36008
+ })), ...providerModels.filter((m) => !FALLBACK_MODEL_PRESETS.includes(m.id))] : providerModels;
36009
+ const modelInList = modelOptions.some((m) => m.id === model);
36010
+ const modelValue = modelCustom || !modelInList && model !== "" && modelOptions.length > 0 ? CUSTOM : model;
36011
+ const providerValue = providerCustom ? CUSTOM : provider;
36012
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36013
+ style: {
36014
+ display: "flex",
36015
+ flexDirection: "column",
36016
+ gap: "var(--nf-space-24)"
36017
+ },
36018
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36019
+ className: panel_module_css_default.card + " " + panel_module_css_default.settingsCard,
36020
+ style: { gap: "var(--nf-space-16)" },
36021
+ children: [
36022
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
36023
+ className: panel_module_css_default.cardTitle,
36024
+ children: "模型"
36025
+ }),
36026
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
36027
+ className: panel_module_css_default.meta,
36028
+ children: "填入各提供方的 API 密钥即可使用其模型。"
36029
+ }),
36030
+ configuredProviders.map((p) => {
36031
+ const isBuiltin = p.id === "deepseek-official";
36032
+ const isKnownVendor = vendors.some((v) => v.id === p.id);
36033
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36034
+ style: {
36035
+ border: "1px solid var(--nf-border)",
36036
+ borderRadius: "var(--nf-radius-12)",
36037
+ padding: "var(--nf-space-12)",
36038
+ display: "flex",
36039
+ alignItems: "center",
36040
+ gap: "var(--nf-space-8)",
36041
+ flexWrap: "wrap",
36042
+ justifyContent: "space-between"
36043
+ },
36044
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36045
+ style: {
36046
+ display: "flex",
36047
+ alignItems: "center",
36048
+ gap: "var(--nf-space-8)"
36049
+ },
36050
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
36051
+ style: { fontWeight: 600 },
36052
+ children: p.name !== "" && p.name !== p.id ? p.name : p.id
36053
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: {
36054
+ width: 8,
36055
+ height: 8,
36056
+ borderRadius: "50%",
36057
+ background: "var(--nf-success)"
36058
+ } })]
36059
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36060
+ style: {
36061
+ display: "flex",
36062
+ gap: "var(--nf-space-6)",
36063
+ alignItems: "center"
36064
+ },
36065
+ children: [!isBuiltin && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
36066
+ type: "button",
36067
+ className: panel_module_css_default.button + " " + panel_module_css_default.buttonSmall,
36068
+ onClick: () => openPanel(isKnownVendor ? "standard" : "custom", p.id),
36069
+ children: tt("settings.edit")
36070
+ }), !isBuiltin && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
36071
+ type: "button",
36072
+ className: panel_module_css_default.button + " " + panel_module_css_default.buttonSmall,
36073
+ style: { color: "var(--nf-error)" },
36074
+ onClick: () => {
36075
+ removeProvider(p);
36076
+ },
36077
+ children: tt("settings.delete")
36078
+ })]
36079
+ })]
36080
+ }, p.id);
36081
+ }),
36082
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36083
+ className: panel_module_css_default.row,
36084
+ style: {
36085
+ gap: "var(--nf-space-10)",
36086
+ flexWrap: "wrap"
36087
+ },
36088
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
36089
+ type: "button",
36090
+ className: panel_module_css_default.button + " " + panel_module_css_default.buttonSmall,
36091
+ onClick: () => openPanel("standard"),
36092
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.Plus, {
36093
+ size: 13,
36094
+ style: { verticalAlign: -2 }
36095
+ }), " 添加提供方"]
36096
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
36097
+ type: "button",
36098
+ className: panel_module_css_default.button + " " + panel_module_css_default.buttonSmall,
36099
+ onClick: () => openPanel("custom"),
36100
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.Plus, {
36101
+ size: 13,
36102
+ style: { verticalAlign: -2 }
36103
+ }), " 添加自定义提供方"]
36104
+ })]
36105
+ }),
36106
+ addPanel !== "none" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36107
+ style: {
36108
+ border: "1px solid var(--nf-border)",
36109
+ borderRadius: "var(--nf-radius-12)",
36110
+ padding: "var(--nf-space-12)",
36111
+ display: "flex",
36112
+ flexDirection: "column",
36113
+ gap: "var(--nf-space-12)"
36114
+ },
36115
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36116
+ className: panel_module_css_default.row,
36117
+ style: {
36118
+ justifyContent: "space-between",
36119
+ alignItems: "center"
36120
+ },
36121
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
36122
+ className: panel_module_css_default.fieldLabel,
36123
+ children: addPanel === "standard" ? editTarget !== "" ? "编辑提供方" : "添加提供方" : "自定义提供方"
36124
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
36125
+ type: "button",
36126
+ className: panel_module_css_default.button + " " + panel_module_css_default.buttonSmall,
36127
+ onClick: () => openPanel("none"),
36128
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.X, {
36129
+ size: 13,
36130
+ style: { verticalAlign: -2 }
36131
+ }), " 关闭"]
36132
+ })]
36133
+ }), addPanel === "standard" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
36134
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36135
+ className: panel_module_css_default.field,
36136
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
36137
+ className: panel_module_css_default.fieldLabel,
36138
+ children: "提供方"
36139
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
36140
+ className: panel_module_css_default.input,
36141
+ value: vendorId,
36142
+ onChange: (e) => setVendorId(e.target.value),
36143
+ children: vendors.map((v) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
36144
+ value: v.id,
36145
+ children: v.name
36146
+ }, v.id))
36147
+ })]
36148
+ }),
36149
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36150
+ className: panel_module_css_default.field,
36151
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
36152
+ className: panel_module_css_default.fieldLabel,
36153
+ children: "API 密钥"
36154
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
36155
+ className: panel_module_css_default.input,
36156
+ type: "password",
36157
+ value: addApiKey,
36158
+ onChange: (e) => setAddApiKey(e.target.value),
36159
+ placeholder: "输入 API 密钥,或留空使用环境认证"
36160
+ })]
36161
+ }),
36162
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36163
+ className: panel_module_css_default.field,
36164
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
36165
+ className: panel_module_css_default.fieldLabel,
36166
+ children: "模型 id(可选)"
36167
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
36168
+ className: panel_module_css_default.input,
36169
+ value: addModel,
36170
+ onChange: (e) => setAddModel(e.target.value),
36171
+ placeholder: "例如 glm-5.3-flash"
36172
+ })]
36173
+ }),
36174
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36175
+ className: panel_module_css_default.row,
36176
+ style: {
36177
+ justifyContent: "flex-end",
36178
+ gap: "var(--nf-space-8)"
36179
+ },
36180
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
36181
+ type: "button",
36182
+ className: panel_module_css_default.button + " " + panel_module_css_default.buttonSmall,
36183
+ onClick: () => openPanel("none"),
36184
+ children: "取消"
36185
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
36186
+ type: "button",
36187
+ className: panel_module_css_default.button + " " + panel_module_css_default.buttonSmall + " " + panel_module_css_default.buttonPrimary,
36188
+ disabled: savingAdd,
36189
+ onClick: () => {
36190
+ saveStandard();
36191
+ },
36192
+ children: savingAdd ? "保存中…" : "保存"
36193
+ })]
36194
+ })
36195
+ ] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
36196
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36197
+ className: panel_module_css_default.field,
36198
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
36199
+ className: panel_module_css_default.fieldLabel,
36200
+ children: "Provider ID"
36201
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
36202
+ className: panel_module_css_default.input,
36203
+ value: custProvider,
36204
+ onChange: (e) => setCustProvider(e.target.value),
36205
+ placeholder: "acme-gateway"
36206
+ })]
36207
+ }),
36208
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36209
+ className: panel_module_css_default.field,
36210
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
36211
+ className: panel_module_css_default.fieldLabel,
36212
+ children: "显示名称"
36213
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
36214
+ className: panel_module_css_default.input,
36215
+ value: custName,
36216
+ onChange: (e) => setCustName(e.target.value),
36217
+ placeholder: "显示名称"
36218
+ })]
36219
+ }),
36220
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36221
+ className: panel_module_css_default.field,
36222
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
36223
+ className: panel_module_css_default.fieldLabel,
36224
+ children: "API 地址"
36225
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
36226
+ className: panel_module_css_default.input,
36227
+ value: custBaseURL,
36228
+ onChange: (e) => setCustBaseURL(e.target.value),
36229
+ placeholder: "https://gateway.example/v1"
36230
+ })]
36231
+ }),
36232
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36233
+ className: panel_module_css_default.field,
36234
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
36235
+ className: panel_module_css_default.fieldLabel,
36236
+ children: "API 协议"
36237
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
36238
+ className: panel_module_css_default.input,
36239
+ value: custProtocol,
36240
+ onChange: (e) => setCustProtocol(e.target.value),
36241
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
36242
+ value: "openai-completions",
36243
+ children: "openai-completions"
36244
+ })
36245
+ })]
36246
+ }),
36247
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36248
+ className: panel_module_css_default.field,
36249
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
36250
+ className: panel_module_css_default.fieldLabel,
36251
+ children: "API 密钥"
36252
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
36253
+ className: panel_module_css_default.input,
36254
+ type: "password",
36255
+ value: custApiKey,
36256
+ onChange: (e) => setCustApiKey(e.target.value),
36257
+ placeholder: "输入 API 密钥"
36258
+ })]
36259
+ }),
36260
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36261
+ className: panel_module_css_default.field,
36262
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
36263
+ className: panel_module_css_default.fieldLabel,
36264
+ children: "模型目录 / 模型 id"
36265
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
36266
+ className: panel_module_css_default.input,
36267
+ value: custModel,
36268
+ onChange: (e) => setCustModel(e.target.value),
36269
+ placeholder: "例如 glm-5.3-flash"
36270
+ })]
36271
+ }),
36272
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36273
+ className: panel_module_css_default.row,
36274
+ style: {
36275
+ justifyContent: "flex-end",
36276
+ gap: "var(--nf-space-8)"
36277
+ },
36278
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
36279
+ type: "button",
36280
+ className: panel_module_css_default.button + " " + panel_module_css_default.buttonSmall,
36281
+ onClick: () => openPanel("none"),
36282
+ children: "取消"
36283
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
36284
+ type: "button",
36285
+ className: panel_module_css_default.button + " " + panel_module_css_default.buttonSmall + " " + panel_module_css_default.buttonPrimary,
36286
+ disabled: savingAdd,
36287
+ onClick: () => {
36288
+ saveCustom();
36289
+ },
36290
+ children: savingAdd ? "创建中…" : "创建提供方"
36291
+ })]
36292
+ })
36293
+ ] })]
36294
+ }),
36295
+ addMsg !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
36296
+ className: panel_module_css_default.meta,
36297
+ style: { color: "var(--nf-success)" },
36298
+ children: ["✓ ", addMsg]
36299
+ }),
36300
+ addErr !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
36301
+ className: panel_module_css_default.meta,
36302
+ style: { color: "var(--nf-error)" },
36303
+ children: ["✗ ", addErr]
36304
+ })
36305
+ ]
36306
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36307
+ className: panel_module_css_default.card + " " + panel_module_css_default.settingsCard,
36308
+ style: { gap: "var(--nf-space-16)" },
36309
+ children: [
36310
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
36311
+ className: panel_module_css_default.cardTitle,
36312
+ children: "当前写作模型"
36313
+ }),
36314
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36315
+ className: panel_module_css_default.field,
36316
+ children: [
36317
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
36318
+ className: panel_module_css_default.fieldLabel,
36319
+ children: tt("settings.provider")
36320
+ }),
36321
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
36322
+ className: panel_module_css_default.input,
36323
+ value: providerValue,
36324
+ onChange: (e) => {
36325
+ const v = e.target.value;
36326
+ if (v === CUSTOM) setProviderCustom(true);
36327
+ else {
36328
+ setProviderCustom(false);
36329
+ onProvider(v);
36330
+ }
36331
+ },
36332
+ children: [providerOptions.map((p) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
36333
+ value: p.id,
36334
+ children: p.name !== "" && p.name !== p.id ? p.name + "(" + p.id + ")" : p.id
36335
+ }, p.id)), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
36336
+ value: CUSTOM,
36337
+ children: tt("settings.customProvider")
36338
+ })]
36339
+ }),
36340
+ providerCustom && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
36341
+ className: panel_module_css_default.input,
36342
+ style: { marginTop: "var(--nf-space-6)" },
36343
+ value: provider,
36344
+ placeholder: "provider 路由 id",
36345
+ onChange: (e) => onProvider(e.target.value)
36346
+ })
36347
+ ]
36348
+ }),
36349
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36350
+ className: panel_module_css_default.field,
36351
+ children: [
36352
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
36353
+ className: panel_module_css_default.fieldLabel,
36354
+ children: tt("settings.model")
36355
+ }),
36356
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36357
+ className: panel_module_css_default.row,
36358
+ style: {
36359
+ gap: "var(--nf-space-8)",
36360
+ flexWrap: "wrap"
36361
+ },
36362
+ children: [
36363
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
36364
+ className: panel_module_css_default.input,
36365
+ style: {
36366
+ flex: 1,
36367
+ minWidth: 200
36368
+ },
36369
+ value: modelValue,
36370
+ onChange: (e) => {
36371
+ const v = e.target.value;
36372
+ if (v === CUSTOM) setModelCustom(true);
36373
+ else {
36374
+ setModelCustom(false);
36375
+ onModel(v);
36376
+ }
36377
+ },
36378
+ children: [modelOptions.map((m) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
36379
+ value: m.id,
36380
+ children: m.name !== "" && m.name !== m.id ? m.name + "(" + m.id + ")" : m.id
36381
+ }, m.id)), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
36382
+ value: CUSTOM,
36383
+ children: tt("settings.modelCustom")
36384
+ })]
36385
+ }),
36386
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
36387
+ type: "button",
36388
+ className: panel_module_css_default.button + " " + panel_module_css_default.buttonSmall,
36389
+ disabled: modelsLoading || provider === "",
36390
+ title: "刷新模型",
36391
+ onClick: () => {
36392
+ loadProviderModels(provider);
36393
+ },
36394
+ children: [
36395
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.RefreshCw, {
36396
+ size: 13,
36397
+ style: { verticalAlign: -2 }
36398
+ }),
36399
+ " ",
36400
+ modelsLoading ? "…" : tt("settings.refreshModels")
36401
+ ]
36402
+ }),
36403
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
36404
+ type: "button",
36405
+ className: panel_module_css_default.button + " " + panel_module_css_default.buttonSmall,
36406
+ disabled: test.testing || provider.trim() === "" || model.trim() === "",
36407
+ onClick: () => {
36408
+ runTest();
36409
+ },
36410
+ title: tt("settings.testHint"),
36411
+ children: [
36412
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.PlugZap, {
36413
+ size: 13,
36414
+ style: { verticalAlign: -2 }
36415
+ }),
36416
+ " ",
36417
+ test.testing ? tt("settings.testRunning") : tt("settings.testConnection")
36418
+ ]
36419
+ })
36420
+ ]
36421
+ }),
36422
+ modelCustom && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
36423
+ className: panel_module_css_default.input,
36424
+ style: { marginTop: "var(--nf-space-6)" },
36425
+ value: model,
36426
+ placeholder: tt("settings.modelCustomPlaceholder"),
36427
+ onChange: (e) => onModel(e.target.value)
36428
+ }),
36429
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
36430
+ className: panel_module_css_default.meta,
36431
+ style: { color: test.ok === true ? "var(--nf-success)" : test.ok === false ? "var(--nf-error)" : void 0 },
36432
+ children: test.testing ? tt("settings.testRunning") + "…" : test.ok === true ? "✓ " + tt("settings.testOk") + " · " + (test.ms ?? "?") + "ms" : test.ok === false ? "✗ " + tt("settings.testFail") + (test.message !== void 0 ? ":" + test.message : "") : tt("settings.testHint")
36433
+ })
36434
+ ]
36435
+ })
36436
+ ]
36437
+ })]
36438
+ });
36439
+ }
36440
+ //#endregion
36441
+ //#region src/client/panel/ReasoningSection.tsx
36442
+ /**
36443
+ * 推理强度(思考强度)独立容器:写作类/分析类两个 reasoningEffort 下拉。
36444
+ */
36445
+ const REASONING_OPTIONS = [
36446
+ "off",
36447
+ "low",
36448
+ "high",
36449
+ "max"
36450
+ ];
36451
+ const REASONING_LABEL = {
36452
+ off: tt("settings.reasoning.off"),
36453
+ low: tt("settings.reasoning.low"),
36454
+ high: tt("settings.reasoning.high"),
36455
+ max: tt("settings.reasoning.max")
35649
36456
  };
36457
+ function ReasoningSection({ reasoningEffort, analysisReasoning, onChange }) {
36458
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36459
+ className: panel_module_css_default.card + " " + panel_module_css_default.settingsCard,
36460
+ style: { gap: "var(--nf-space-24)" },
36461
+ children: [
36462
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
36463
+ className: panel_module_css_default.cardTitle,
36464
+ children: [
36465
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.Brain, {
36466
+ size: 18,
36467
+ style: { verticalAlign: -3 }
36468
+ }),
36469
+ " ",
36470
+ tt("settings.reasoningSection")
36471
+ ]
36472
+ }),
36473
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36474
+ className: panel_module_css_default.field,
36475
+ children: [
36476
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
36477
+ className: panel_module_css_default.fieldLabel,
36478
+ children: tt("settings.reasoningEffort")
36479
+ }),
36480
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
36481
+ className: panel_module_css_default.input,
36482
+ value: reasoningEffort ?? "off",
36483
+ onChange: (e) => onChange({ reasoningEffort: e.target.value }),
36484
+ children: REASONING_OPTIONS.map((v) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
36485
+ value: v,
36486
+ children: REASONING_LABEL[v]
36487
+ }, v))
36488
+ }),
36489
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
36490
+ className: panel_module_css_default.meta,
36491
+ children: tt("settings.reasoningHint")
36492
+ })
36493
+ ]
36494
+ }),
36495
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36496
+ className: panel_module_css_default.field,
36497
+ children: [
36498
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
36499
+ className: panel_module_css_default.fieldLabel,
36500
+ children: tt("settings.analysisReasoning")
36501
+ }),
36502
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
36503
+ className: panel_module_css_default.input,
36504
+ value: analysisReasoning ?? "low",
36505
+ onChange: (e) => onChange({ analysisReasoning: e.target.value }),
36506
+ children: REASONING_OPTIONS.map((v) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
36507
+ value: v,
36508
+ children: REASONING_LABEL[v]
36509
+ }, v))
36510
+ }),
36511
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
36512
+ className: panel_module_css_default.meta,
36513
+ children: tt("settings.analysisReasoningHint")
36514
+ })
36515
+ ]
36516
+ })
36517
+ ]
36518
+ });
36519
+ }
35650
36520
  //#endregion
35651
36521
  //#region src/client/panel/AssistantTab.tsx
35652
36522
  /**
@@ -36929,7 +37799,7 @@ window.__ModuleLoader__.load({
36929
37799
  * 进入小说工坊默认展示;点击书卡进入该书工作台,+ 进入开书向导页。
36930
37800
  */
36931
37801
  /** 相对时间(人性化:刚刚 / N 分钟前 / N 小时前 / N 天前 / 日期)。 */
36932
- function relativeTime$1(iso) {
37802
+ function relativeTime(iso) {
36933
37803
  const t = new Date(iso).getTime();
36934
37804
  if (!Number.isFinite(t)) return "—";
36935
37805
  const diff = Date.now() - t;
@@ -36943,7 +37813,7 @@ window.__ModuleLoader__.load({
36943
37813
  });
36944
37814
  }
36945
37815
  /** 一本书的状态标签。 */
36946
- function bookStatus$1(book) {
37816
+ function bookStatus(book) {
36947
37817
  if (!book.hasProject) return "none";
36948
37818
  return book.total > 0 && book.done >= book.total ? "done" : "active";
36949
37819
  }
@@ -36965,7 +37835,7 @@ window.__ModuleLoader__.load({
36965
37835
  book.outputDir
36966
37836
  ]);
36967
37837
  const ratio = book.total > 0 ? Math.min(book.done / book.total, 1) : 0;
36968
- const status = bookStatus$1(book);
37838
+ const status = bookStatus(book);
36969
37839
  const statusLabel = status === "none" ? "未开书" : status === "done" ? "已完结" : "进行中";
36970
37840
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36971
37841
  className: `${panel_module_css_default.bookCard} ${active ? panel_module_css_default.bookCardActive : ""}`,
@@ -37019,7 +37889,7 @@ window.__ModuleLoader__.load({
37019
37889
  }), book.hasProject && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
37020
37890
  className: panel_module_css_default.meta,
37021
37891
  title: "最近活动时间",
37022
- children: ["更新于 ", relativeTime$1(book.updatedAt)]
37892
+ children: ["更新于 ", relativeTime(book.updatedAt)]
37023
37893
  })]
37024
37894
  }),
37025
37895
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -37060,7 +37930,7 @@ window.__ModuleLoader__.load({
37060
37930
  const stats = (0, react.useMemo)(() => {
37061
37931
  let active = 0, done = 0, none = 0;
37062
37932
  for (const b of shelf.books) {
37063
- const s = bookStatus$1(b);
37933
+ const s = bookStatus(b);
37064
37934
  if (s === "none") none++;
37065
37935
  else if (s === "done") done++;
37066
37936
  else active++;
@@ -37074,7 +37944,7 @@ window.__ModuleLoader__.load({
37074
37944
  const visible = (0, react.useMemo)(() => {
37075
37945
  const q = query.trim().toLowerCase();
37076
37946
  return shelf.books.filter((b) => {
37077
- if (filter !== "all" && bookStatus$1(b) !== filter) return false;
37947
+ if (filter !== "all" && bookStatus(b) !== filter) return false;
37078
37948
  if (q === "") return true;
37079
37949
  return b.bookName.toLowerCase().includes(q) || (b.blurb ?? "").toLowerCase().includes(q);
37080
37950
  });
@@ -37425,16 +38295,17 @@ window.__ModuleLoader__.load({
37425
38295
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
37426
38296
  className: panel_module_css_default.authorPageBody,
37427
38297
  children: [
37428
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
37429
- className: panel_module_css_default.authorPageHeader,
37430
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
38298
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
38299
+ className: panel_module_css_default.card + " " + panel_module_css_default.settingsCard,
38300
+ style: { gap: "var(--nf-space-6)" },
38301
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
37431
38302
  className: panel_module_css_default.panelTitle,
37432
38303
  style: { margin: 0 },
37433
38304
  children: "🎬 改编模式"
37434
38305
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
37435
38306
  className: panel_module_css_default.meta,
37436
38307
  children: "上传全文 → 分析可改范围 → 勾选/填新值 → 生成映射表 → 术语替换执行。"
37437
- })] })
38308
+ })]
37438
38309
  }),
37439
38310
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
37440
38311
  className: panel_module_css_default.adaptInputCard,
@@ -38158,202 +39029,124 @@ window.__ModuleLoader__.load({
38158
39029
  });
38159
39030
  }
38160
39031
  //#endregion
38161
- //#region src/client/panel/ProgressHomeView.tsx
39032
+ //#region src/client/panel/ProgressConsole.tsx
38162
39033
  /**
38163
- * 首页 AI 进度视图:书架级聚合进度——总览 + 每本书进度条 + 进行中高亮。
38164
- * 读取 BookshelfSnapshot,不依赖打开某本书。
39034
+ * 共享「AI 进度」实时控制台:当前任务大进度条 + 全量活动日志。
39035
+ * 书内与首页共用一个表现,内容来自同一份进度状态。
38165
39036
  */
38166
- function relativeTime(iso) {
38167
- const t = new Date(iso).getTime();
38168
- if (!Number.isFinite(t)) return "—";
38169
- const diff = Date.now() - t;
38170
- if (diff < 6e4) return "刚刚";
38171
- if (diff < 36e5) return Math.floor(diff / 6e4) + " 分钟前";
38172
- if (diff < 864e5) return Math.floor(diff / 36e5) + " 小时前";
38173
- if (diff < 7 * 864e5) return Math.floor(diff / 864e5) + " 天前";
38174
- return new Date(t).toLocaleDateString("zh-CN", {
38175
- month: "numeric",
38176
- day: "numeric"
38177
- });
38178
- }
38179
- function bookStatus(book) {
38180
- if (!book.hasProject) return "none";
38181
- return book.total > 0 && book.done >= book.total ? "done" : "active";
38182
- }
38183
- function ProgressHomeView({ shelf, onOpenBook }) {
38184
- const stats = (0, react.useMemo)(() => {
38185
- let active = 0, done = 0, none = 0, chapters = 0, written = 0;
38186
- for (const b of shelf.books) {
38187
- const s = bookStatus(b);
38188
- if (s === "none") none++;
38189
- else if (s === "done") done++;
38190
- else active++;
38191
- chapters += b.total;
38192
- written += b.done;
38193
- }
38194
- return {
38195
- active,
38196
- done,
38197
- none,
38198
- chapters,
38199
- written
38200
- };
38201
- }, [shelf.books]);
38202
- const progressPct = stats.chapters > 0 ? Math.round(stats.written / stats.chapters * 100) : 0;
39037
+ function ProgressConsole({ progress, busy, busyLabel, liveBar, onClear }) {
39038
+ const endRef = (0, react.useRef)(null);
39039
+ (0, react.useEffect)(() => {
39040
+ endRef.current?.scrollIntoView({
39041
+ behavior: "smooth",
39042
+ block: "nearest"
39043
+ });
39044
+ }, [progress]);
38203
39045
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
38204
- className: panel_module_css_default.authorPageBody,
39046
+ style: {
39047
+ display: "flex",
39048
+ flexDirection: "column",
39049
+ gap: "var(--nf-space-10)",
39050
+ height: "100%",
39051
+ minHeight: 0
39052
+ },
38205
39053
  children: [
38206
39054
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
38207
- className: panel_module_css_default.authorPageHeader,
38208
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
38209
- className: panel_module_css_default.panelTitle,
38210
- style: { margin: 0 },
39055
+ style: {
39056
+ display: "flex",
39057
+ alignItems: "center",
39058
+ justifyContent: "space-between"
39059
+ },
39060
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
39061
+ style: { fontWeight: 600 },
38211
39062
  children: "📊 AI 进度"
38212
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
38213
- className: panel_module_css_default.meta,
38214
- children: "跨书架聚合进度与最近活动"
39063
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
39064
+ type: "button",
39065
+ className: panel_module_css_default.button + " " + panel_module_css_default.buttonSmall,
39066
+ onClick: onClear,
39067
+ title: "清空活动记录",
39068
+ children: "清空"
38215
39069
  })]
38216
39070
  }),
38217
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
38218
- className: panel_module_css_default.progressOverview,
39071
+ busy && (busyLabel !== "" || liveBar !== null) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
39072
+ style: {
39073
+ border: "1px solid var(--nf-accent)",
39074
+ borderRadius: "var(--nf-radius-10)",
39075
+ padding: "var(--nf-space-8) var(--nf-space-12)",
39076
+ display: "flex",
39077
+ flexDirection: "column",
39078
+ gap: "var(--nf-space-6)",
39079
+ background: "color-mix(in srgb, var(--nf-accent) 6%, transparent)"
39080
+ },
38219
39081
  children: [
38220
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
38221
- className: panel_module_css_default.progressOverviewCard,
38222
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
38223
- className: panel_module_css_default.progressOverviewNum,
38224
- children: shelf.books.length
38225
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
38226
- className: panel_module_css_default.meta,
38227
- children: "总书数"
38228
- })]
38229
- }),
38230
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
38231
- className: panel_module_css_default.progressOverviewCard,
38232
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
38233
- className: panel_module_css_default.progressOverviewNum,
38234
- children: stats.active
38235
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
38236
- className: panel_module_css_default.meta,
38237
- children: "进行中"
38238
- })]
39082
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
39083
+ style: {
39084
+ fontSize: "var(--nf-fs-12)",
39085
+ fontWeight: 600,
39086
+ color: "var(--nf-accent)"
39087
+ },
39088
+ children: [
39089
+ "✍ ",
39090
+ busyLabel !== "" ? busyLabel : liveBar?.text ?? "任务进行中",
39091
+ "…"
39092
+ ]
38239
39093
  }),
38240
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
38241
- className: panel_module_css_default.progressOverviewCard,
38242
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
38243
- className: panel_module_css_default.progressOverviewNum,
38244
- children: stats.done
38245
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
38246
- className: panel_module_css_default.meta,
38247
- children: "已完结"
38248
- })]
39094
+ liveBar?.ratio !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
39095
+ className: panel_module_css_default.bigProgressBar,
39096
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
39097
+ className: panel_module_css_default.bigProgressBarFill,
39098
+ style: { width: Math.round(liveBar.ratio * 100) + "%" }
39099
+ })
38249
39100
  }),
38250
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
38251
- className: panel_module_css_default.progressOverviewCard,
38252
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
38253
- className: panel_module_css_default.progressOverviewNum,
38254
- children: [
38255
- stats.written,
38256
- "/",
38257
- stats.chapters
38258
- ]
38259
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
38260
- className: panel_module_css_default.meta,
38261
- children: "已完成章节"
38262
- })]
39101
+ liveBar?.text !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
39102
+ className: panel_module_css_default.liveText,
39103
+ children: liveBar.text
38263
39104
  })
38264
39105
  ]
38265
39106
  }),
38266
39107
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
38267
- className: panel_module_css_default.progressTotalBar,
38268
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
38269
- className: panel_module_css_default.progressTotalFill,
38270
- style: { width: progressPct + "%" }
38271
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
38272
- className: panel_module_css_default.meta,
39108
+ className: panel_module_css_default.progress,
39109
+ style: {
39110
+ flex: 1,
39111
+ minHeight: 0,
39112
+ overflowY: "auto",
39113
+ border: "1px solid var(--nf-border)",
39114
+ borderRadius: "var(--nf-radius-10)",
39115
+ background: "var(--nf-bg-inset)",
39116
+ padding: "var(--nf-space-8)",
39117
+ display: "flex",
39118
+ flexDirection: "column"
39119
+ },
39120
+ children: [progress.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
39121
+ style: {
39122
+ flex: 1,
39123
+ display: "flex",
39124
+ flexDirection: "column",
39125
+ alignItems: "center",
39126
+ justifyContent: "center",
39127
+ gap: "var(--nf-space-4)",
39128
+ color: "var(--nf-text-3)",
39129
+ fontSize: "var(--nf-fs-12)",
39130
+ minHeight: 120
39131
+ },
38273
39132
  children: [
38274
- "全书架整体进度 ",
38275
- progressPct,
38276
- "%"
39133
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
39134
+ style: { fontSize: "var(--nf-fs-22)" },
39135
+ children: "📭"
39136
+ }),
39137
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "暂无活动记录" }),
39138
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "生成、审稿等操作会显示在这里" })
38277
39139
  ]
38278
- })]
38279
- }),
38280
- shelf.books.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
38281
- className: panel_module_css_default.shelfEmpty,
38282
- style: { minHeight: 160 },
38283
- children: [
38284
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
38285
- className: panel_module_css_default.shelfEmptyIcon,
38286
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.BarChart3, { size: 30 })
38287
- }),
38288
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
38289
- className: panel_module_css_default.shelfEmptyTitle,
38290
- children: "还没有书"
38291
- }),
38292
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
38293
- className: panel_module_css_default.meta,
38294
- children: "去书架开一本书或导入全文后,这里会显示进度。"
38295
- })
38296
- ]
38297
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
38298
- className: panel_module_css_default.progressBookList,
38299
- children: shelf.books.map((book) => {
38300
- const s = bookStatus(book);
38301
- const ratio = book.total > 0 ? Math.min(book.done / book.total, 1) : 0;
38302
- const statusLabel = s === "none" ? "未开书" : s === "done" ? "已完结" : "进行中";
38303
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
38304
- className: panel_module_css_default.progressBook + (s === "active" ? " " + panel_module_css_default.progressBookActive : ""),
38305
- children: [
38306
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
38307
- className: panel_module_css_default.progressBookHead,
38308
- children: [
38309
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
38310
- className: panel_module_css_default.progressBookName,
38311
- title: book.bookName,
38312
- children: book.bookName
38313
- }),
38314
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
38315
- className: panel_module_css_default.badge + (s === "done" ? " " + panel_module_css_default.badgeDone : s === "active" ? " " + panel_module_css_default.badgeWritten : " " + panel_module_css_default.badgePending),
38316
- children: statusLabel
38317
- }),
38318
- s === "active" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
38319
- className: panel_module_css_default.meta + " " + panel_module_css_default.progressLive,
38320
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.RefreshCw, {
38321
- size: 12,
38322
- style: { verticalAlign: -2 }
38323
- }), " 创作中"]
38324
- })
38325
- ]
38326
- }),
38327
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
38328
- className: panel_module_css_default.progressBookBar,
38329
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
38330
- className: panel_module_css_default.progressBookFill,
38331
- style: { width: Math.round(ratio * 100) + "%" }
38332
- })
38333
- }),
38334
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
38335
- className: panel_module_css_default.rowEnd,
38336
- style: { justifyContent: "space-between" },
38337
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
38338
- className: panel_module_css_default.meta,
38339
- children: [
38340
- book.total > 0 ? "已完成 " + book.done + " / " + book.total + " 章" : "尚未规划章节",
38341
- " · 更新于 ",
38342
- relativeTime(book.updatedAt)
38343
- ]
38344
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
38345
- type: "button",
38346
- className: panel_module_css_default.button + " " + panel_module_css_default.buttonSmall,
38347
- onClick: () => onOpenBook(book.id),
38348
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.PenLine, {
38349
- size: 12,
38350
- style: { verticalAlign: -2 }
38351
- }), " 进入"]
38352
- })]
38353
- })
38354
- ]
38355
- }, book.id);
38356
- })
39140
+ }) : progress.map((line) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
39141
+ className: line.kind === "done" ? panel_module_css_default.progressLineDone : line.kind === "error" ? panel_module_css_default.progressLineError : line.live === true ? panel_module_css_default.progressLineLive : panel_module_css_default.progressLine,
39142
+ children: [line.live === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
39143
+ className: panel_module_css_default.progressBar,
39144
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
39145
+ className: panel_module_css_default.progressBarFill,
39146
+ style: { width: Math.round((line.ratio ?? 0) * 100) + "%" }
39147
+ })
39148
+ }), line.text]
39149
+ }, line.id)), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { ref: endRef })]
38357
39150
  })
38358
39151
  ]
38359
39152
  });
@@ -38365,24 +39158,6 @@ window.__ModuleLoader__.load({
38365
39158
  * 自给自足:挂载时通过 api.status() 拉取全局配置,支持 model/writing/image/files/appearance 五组,
38366
39159
  * 保存走 api.patchConfig。不与某个书绑定,因此新装用户无书也能用。
38367
39160
  */
38368
- const MODEL_PRESETS$1 = [
38369
- "deepseek-v4-flash",
38370
- "deepseek-v4-pro",
38371
- "deepseek-chat",
38372
- "deepseek-reasoner"
38373
- ];
38374
- const REASONING_OPTIONS$1 = [
38375
- "off",
38376
- "low",
38377
- "high",
38378
- "max"
38379
- ];
38380
- const REASONING_LABEL = {
38381
- off: tt("settings.reasoning.off"),
38382
- low: tt("settings.reasoning.low"),
38383
- high: tt("settings.reasoning.high"),
38384
- max: tt("settings.reasoning.max")
38385
- };
38386
39161
  const SETTINGS_SECTIONS$1 = [
38387
39162
  {
38388
39163
  id: "model",
@@ -38408,11 +39183,6 @@ window.__ModuleLoader__.load({
38408
39183
  id: "appearance",
38409
39184
  label: "外观与主题",
38410
39185
  icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.Sparkles, { size: 16 })
38411
- },
38412
- {
38413
- id: "background",
38414
- label: "自定义背景",
38415
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.Image, { size: 16 })
38416
39186
  }
38417
39187
  ];
38418
39188
  function readLS(key, fallback, allowed) {
@@ -38429,14 +39199,12 @@ window.__ModuleLoader__.load({
38429
39199
  const [busy, setBusy] = (0, react.useState)(false);
38430
39200
  const [error, setError] = (0, react.useState)("");
38431
39201
  const [notice, setNotice] = (0, react.useState)("");
38432
- const [modelCustomMode, setModelCustomMode] = (0, react.useState)(false);
38433
39202
  const [settingsTab, setSettingsTabState] = (0, react.useState)(() => readLS("dsh-novel-forge.settings.tab", "model", [
38434
39203
  "model",
38435
39204
  "writing",
38436
39205
  "image",
38437
39206
  "files",
38438
- "appearance",
38439
- "background"
39207
+ "appearance"
38440
39208
  ]));
38441
39209
  const [imageTestState, setImageTestState] = (0, react.useState)({});
38442
39210
  const [editorFontSize, setEditorFontSize] = (0, react.useState)(() => {
@@ -38508,7 +39276,8 @@ window.__ModuleLoader__.load({
38508
39276
  themeBackground: configDraft.themeBackground ?? "",
38509
39277
  themeBackgroundBlur: configDraft.themeBackgroundBlur ?? 0,
38510
39278
  themeOpacity: configDraft.themeOpacity ?? 100,
38511
- imageModels: configDraft.imageModels ?? []
39279
+ imageModels: configDraft.imageModels ?? [],
39280
+ savedModels: configDraft.savedModels ?? []
38512
39281
  });
38513
39282
  setConfig(result.config);
38514
39283
  setConfigDraft(result.config);
@@ -38678,23 +39447,29 @@ window.__ModuleLoader__.load({
38678
39447
  "data-nf-mode": themeMode === "system" ? void 0 : themeMode,
38679
39448
  "data-nf-density": themeDensity,
38680
39449
  children: [
38681
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
38682
- className: panel_module_css_default.authorPageHeader,
38683
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
38684
- className: panel_module_css_default.panelTitle,
38685
- style: { margin: 0 },
38686
- children: "⚙️ 设置"
38687
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
38688
- className: panel_module_css_default.meta,
38689
- children: [
38690
- "当前:",
38691
- config?.provider,
38692
- " / ",
38693
- config?.model,
38694
- " · ",
38695
- config?.outputDir
38696
- ]
38697
- })] })
39450
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
39451
+ className: panel_module_css_default.card + " " + panel_module_css_default.settingsCard,
39452
+ style: { gap: "var(--nf-space-6)" },
39453
+ children: [
39454
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
39455
+ className: panel_module_css_default.panelTitle,
39456
+ style: { margin: 0 },
39457
+ children: "⚙️ 设置"
39458
+ }),
39459
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
39460
+ className: panel_module_css_default.meta,
39461
+ children: [
39462
+ "当前模型:",
39463
+ config?.provider,
39464
+ " / ",
39465
+ config?.model
39466
+ ]
39467
+ }),
39468
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
39469
+ className: panel_module_css_default.meta,
39470
+ children: ["输出目录:", config?.outputDir]
39471
+ })
39472
+ ]
38698
39473
  }),
38699
39474
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
38700
39475
  className: panel_module_css_default.row,
@@ -38726,123 +39501,41 @@ window.__ModuleLoader__.load({
38726
39501
  className: panel_module_css_default.meta,
38727
39502
  children: notice
38728
39503
  }),
38729
- settingsTab === "model" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
39504
+ settingsTab === "model" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
38730
39505
  className: panel_module_css_default.card + " " + panel_module_css_default.settingsCard,
38731
39506
  style: { gap: "var(--nf-space-24)" },
38732
- children: [
38733
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
38734
- className: panel_module_css_default.cardTitle,
38735
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.Brain, {
38736
- size: 18,
38737
- style: { verticalAlign: -3 }
38738
- }), " 模型与推理"]
38739
- }),
38740
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
38741
- className: panel_module_css_default.field,
38742
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
38743
- className: panel_module_css_default.fieldLabel,
38744
- children: tt("settings.provider")
38745
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
38746
- className: panel_module_css_default.input,
38747
- value: configDraft.provider,
38748
- onChange: (e) => setConfigDraft({
38749
- ...configDraft,
38750
- provider: e.target.value
38751
- })
38752
- })]
38753
- }),
38754
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
38755
- className: panel_module_css_default.field,
38756
- children: [
38757
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
38758
- className: panel_module_css_default.fieldLabel,
38759
- children: tt("settings.model")
38760
- }),
38761
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
38762
- className: panel_module_css_default.input,
38763
- value: modelCustomMode ? "__custom__" : configDraft.model,
38764
- onChange: (e) => {
38765
- const v = e.target.value;
38766
- if (v === "__custom__") setModelCustomMode(true);
38767
- else {
38768
- setModelCustomMode(false);
38769
- setConfigDraft({
38770
- ...configDraft,
38771
- model: v
38772
- });
38773
- }
38774
- },
38775
- children: [MODEL_PRESETS$1.map((m) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
38776
- value: m,
38777
- children: m
38778
- }, m)), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
38779
- value: "__custom__",
38780
- children: tt("settings.modelCustom")
38781
- })]
38782
- }),
38783
- modelCustomMode && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
38784
- className: panel_module_css_default.input,
38785
- value: configDraft.model,
38786
- placeholder: tt("settings.modelCustomPlaceholder"),
38787
- onChange: (e) => setConfigDraft({
38788
- ...configDraft,
38789
- model: e.target.value
38790
- })
38791
- })
38792
- ]
39507
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
39508
+ className: panel_module_css_default.cardTitle,
39509
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.Brain, {
39510
+ size: 18,
39511
+ style: { verticalAlign: -3 }
39512
+ }), " 模型与推理"]
39513
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelManager, {
39514
+ api,
39515
+ provider: configDraft.provider,
39516
+ model: configDraft.model,
39517
+ savedModels: configDraft.savedModels ?? [],
39518
+ onProvider: (v) => setConfigDraft({
39519
+ ...configDraft,
39520
+ provider: v
38793
39521
  }),
38794
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
38795
- className: panel_module_css_default.field,
38796
- children: [
38797
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
38798
- className: panel_module_css_default.fieldLabel,
38799
- children: tt("settings.reasoningEffort")
38800
- }),
38801
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
38802
- className: panel_module_css_default.input,
38803
- value: configDraft.reasoningEffort ?? "off",
38804
- onChange: (e) => setConfigDraft({
38805
- ...configDraft,
38806
- reasoningEffort: e.target.value
38807
- }),
38808
- children: REASONING_OPTIONS$1.map((v) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
38809
- value: v,
38810
- children: REASONING_LABEL[v]
38811
- }, v))
38812
- }),
38813
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
38814
- className: panel_module_css_default.meta,
38815
- children: tt("settings.reasoningHint")
38816
- })
38817
- ]
39522
+ onModel: (v) => setConfigDraft({
39523
+ ...configDraft,
39524
+ model: v
38818
39525
  }),
38819
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
38820
- className: panel_module_css_default.field,
38821
- children: [
38822
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
38823
- className: panel_module_css_default.fieldLabel,
38824
- children: tt("settings.analysisReasoning")
38825
- }),
38826
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
38827
- className: panel_module_css_default.input,
38828
- value: configDraft.analysisReasoning ?? "low",
38829
- onChange: (e) => setConfigDraft({
38830
- ...configDraft,
38831
- analysisReasoning: e.target.value
38832
- }),
38833
- children: REASONING_OPTIONS$1.map((v) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
38834
- value: v,
38835
- children: REASONING_LABEL[v]
38836
- }, v))
38837
- }),
38838
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
38839
- className: panel_module_css_default.meta,
38840
- children: tt("settings.analysisReasoningHint")
38841
- })
38842
- ]
39526
+ onSavedModels: (models) => setConfigDraft({
39527
+ ...configDraft,
39528
+ savedModels: models
38843
39529
  })
38844
- ]
38845
- }),
39530
+ })]
39531
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReasoningSection, {
39532
+ reasoningEffort: configDraft.reasoningEffort ?? "off",
39533
+ analysisReasoning: configDraft.analysisReasoning ?? "low",
39534
+ onChange: (patch) => setConfigDraft({
39535
+ ...configDraft,
39536
+ ...patch
39537
+ })
39538
+ })] }),
38846
39539
  settingsTab === "writing" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
38847
39540
  className: panel_module_css_default.card + " " + panel_module_css_default.settingsCard,
38848
39541
  style: { gap: "var(--nf-space-24)" },
@@ -39033,9 +39726,28 @@ window.__ModuleLoader__.load({
39033
39726
  size: 18,
39034
39727
  style: { verticalAlign: -3 }
39035
39728
  }), " 生图模型"]
39036
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
39037
- className: panel_module_css_default.meta,
39038
- children: "启用生图功能"
39729
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
39730
+ className: panel_module_css_default.row,
39731
+ style: {
39732
+ gap: "var(--nf-space-8)",
39733
+ alignItems: "center"
39734
+ },
39735
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
39736
+ className: panel_module_css_default.meta,
39737
+ children: "启用生图功能"
39738
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
39739
+ type: "button",
39740
+ role: "switch",
39741
+ "aria-checked": configDraft.imageApiEnabled === true,
39742
+ className: `${panel_module_css_default.switch} ${configDraft.imageApiEnabled === true ? panel_module_css_default.switchOn : ""}`,
39743
+ onClick: () => {
39744
+ setConfigDraft((prev) => prev === null ? prev : {
39745
+ ...prev,
39746
+ imageApiEnabled: prev.imageApiEnabled !== true
39747
+ });
39748
+ },
39749
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: panel_module_css_default.switchKnob })
39750
+ })]
39039
39751
  })]
39040
39752
  }),
39041
39753
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
@@ -39228,7 +39940,7 @@ window.__ModuleLoader__.load({
39228
39940
  })
39229
39941
  ]
39230
39942
  }),
39231
- settingsTab === "appearance" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
39943
+ settingsTab === "appearance" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
39232
39944
  className: panel_module_css_default.card + " " + panel_module_css_default.settingsCard,
39233
39945
  children: [
39234
39946
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
@@ -39352,8 +40064,7 @@ window.__ModuleLoader__.load({
39352
40064
  })
39353
40065
  })
39354
40066
  ]
39355
- }),
39356
- settingsTab === "background" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
40067
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
39357
40068
  className: panel_module_css_default.card + " " + panel_module_css_default.settingsCard,
39358
40069
  style: { gap: "var(--nf-space-12)" },
39359
40070
  children: [
@@ -39452,7 +40163,7 @@ window.__ModuleLoader__.load({
39452
40163
  ]
39453
40164
  })
39454
40165
  ]
39455
- }),
40166
+ })] }),
39456
40167
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
39457
40168
  className: panel_module_css_default.row,
39458
40169
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
@@ -39474,6 +40185,7 @@ window.__ModuleLoader__.load({
39474
40185
  * 作者级首页容器:书架页左侧导航 + 内容区。
39475
40186
  * 导航复用工作区 .panelNav 玻璃卡片样式(同款),导航项为作者级:书架/改编/资产库/全局资产库/AI 进度/设置。
39476
40187
  */
40188
+ const PLUGIN_VERSION$1 = "1.9.0";
39477
40189
  const NAV_ITEMS = [
39478
40190
  {
39479
40191
  id: "shelf",
@@ -39510,7 +40222,8 @@ window.__ModuleLoader__.load({
39510
40222
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
39511
40223
  className: panel_module_css_default.authorPageBody,
39512
40224
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
39513
- className: panel_module_css_default.authorPageHeader,
40225
+ className: panel_module_css_default.card + " " + panel_module_css_default.settingsCard,
40226
+ style: { gap: "var(--nf-space-6)" },
39514
40227
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
39515
40228
  className: panel_module_css_default.panelTitle,
39516
40229
  style: { margin: 0 },
@@ -39539,7 +40252,7 @@ window.__ModuleLoader__.load({
39539
40252
  })]
39540
40253
  });
39541
40254
  }
39542
- function AuthorHome({ api, shelf, onOpenBook, onReadBook, onAddBook, onImportBook, onOpenSettings, onTheme, onBackground, onOpacity, adaptEnabled }) {
40255
+ function AuthorHome({ api, shelf, onOpenBook, onReadBook, onAddBook, onImportBook, onOpenSettings, onTheme, onBackground, onOpacity, adaptEnabled, progress, busy, busyLabel, liveBar, onClearProgress }) {
39543
40256
  const [nav, setNav] = (0, react.useState)("shelf");
39544
40257
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
39545
40258
  className: panel_module_css_default.authorHome,
@@ -39606,7 +40319,11 @@ window.__ModuleLoader__.load({
39606
40319
  className: panel_module_css_default.navAbout,
39607
40320
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
39608
40321
  className: panel_module_css_default.navAboutRow,
39609
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "ℹ️ v1.7.3 · 改编/资产库" })
40322
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
40323
+ "ℹ️ v",
40324
+ PLUGIN_VERSION$1,
40325
+ " · 改编/资产库"
40326
+ ] })
39610
40327
  })
39611
40328
  })
39612
40329
  ]
@@ -39627,9 +40344,15 @@ window.__ModuleLoader__.load({
39627
40344
  title: "🎨 全局写作资产库",
39628
40345
  hint: "内置题材基底库 / 反AI规则库 / 风格模板 / 推进模式(跨书)"
39629
40346
  }),
39630
- nav === "progress" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProgressHomeView, {
39631
- shelf,
39632
- onOpenBook
40347
+ nav === "progress" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
40348
+ className: panel_module_css_default.authorPageBody,
40349
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProgressConsole, {
40350
+ progress: progress ?? [],
40351
+ busy: busy ?? false,
40352
+ busyLabel: busyLabel ?? "",
40353
+ liveBar: liveBar ?? null,
40354
+ onClear: () => onClearProgress?.()
40355
+ })
39633
40356
  }),
39634
40357
  nav === "settings" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingsView, {
39635
40358
  api,
@@ -47519,19 +48242,6 @@ window.__ModuleLoader__.load({
47519
48242
  label: tt("tab.settings"),
47520
48243
  icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.Settings, { size: 18 })
47521
48244
  };
47522
- /** Common DeepSeek model presets shown in settings; users can also type any model id. */
47523
- const MODEL_PRESETS = [
47524
- "deepseek-v4-flash",
47525
- "deepseek-v4-pro",
47526
- "deepseek-chat",
47527
- "deepseek-reasoner"
47528
- ];
47529
- const REASONING_OPTIONS = [
47530
- "off",
47531
- "low",
47532
- "high",
47533
- "max"
47534
- ];
47535
48245
  /** 设置页内子导航分组。 */
47536
48246
  const SETTINGS_SECTIONS = [
47537
48247
  {
@@ -47560,7 +48270,7 @@ window.__ModuleLoader__.load({
47560
48270
  icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.Sparkles, { size: 16 })
47561
48271
  }
47562
48272
  ];
47563
- const PLUGIN_VERSION = "1.8.0";
48273
+ const PLUGIN_VERSION = "1.9.0";
47564
48274
  /** GitHub 仓库地址(关于区块点击跳转)。 */
47565
48275
  const REPO_URL = "https://github.com/watersxya/dsh-novel-forge";
47566
48276
  /** Whether any chapter is being generated right now. */
@@ -47836,7 +48546,6 @@ window.__ModuleLoader__.load({
47836
48546
  const [notice, setNotice] = (0, react.useState)("");
47837
48547
  const [progress, setProgress] = (0, react.useState)([]);
47838
48548
  const [configDraft, setConfigDraft] = (0, react.useState)(null);
47839
- const [modelCustomMode, setModelCustomMode] = (0, react.useState)(false);
47840
48549
  const [expandedChapter, setExpandedChapter] = (0, react.useState)(null);
47841
48550
  /** 复盘记录页:当前展开的章节号。 */
47842
48551
  const [expandedReviewChapter, setExpandedReviewChapter] = (0, react.useState)(null);
@@ -48258,7 +48967,6 @@ window.__ModuleLoader__.load({
48258
48967
  const status = await api.status();
48259
48968
  setConfig(status.config);
48260
48969
  setConfigDraft(status.config);
48261
- setModelCustomMode(!MODEL_PRESETS.includes(status.config.model));
48262
48970
  setAuditStatus(status.audit ?? null);
48263
48971
  setProject(status.project ?? null);
48264
48972
  if (status.project?.roleStatus !== void 0) setCharCards(status.project.roleStatus);
@@ -49644,7 +50352,8 @@ window.__ModuleLoader__.load({
49644
50352
  imageApiKey: configDraft.imageApiKey,
49645
50353
  imageApiModel: configDraft.imageApiModel,
49646
50354
  imageApiEnabled: configDraft.imageApiEnabled ?? false,
49647
- imageModels: configDraft.imageModels ?? []
50355
+ imageModels: configDraft.imageModels ?? [],
50356
+ savedModels: configDraft.savedModels ?? []
49648
50357
  });
49649
50358
  setConfig(result.config);
49650
50359
  setConfigDraft(result.config);
@@ -50103,7 +50812,14 @@ window.__ModuleLoader__.load({
50103
50812
  onOpacity: (n) => {
50104
50813
  setThemeOpacity(n);
50105
50814
  },
50106
- adaptEnabled: config?.enableAdaptMode === true
50815
+ adaptEnabled: config?.enableAdaptMode === true,
50816
+ progress,
50817
+ busy,
50818
+ busyLabel,
50819
+ liveBar,
50820
+ onClearProgress: () => {
50821
+ setProgress([]);
50822
+ }
50107
50823
  }) : viewMode === "create" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CreateBookView, {
50108
50824
  api,
50109
50825
  onBack: () => {
@@ -52765,7 +53481,7 @@ window.__ModuleLoader__.load({
52765
53481
  }, s.id))
52766
53482
  })]
52767
53483
  }),
52768
- settingsTab === "model" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
53484
+ settingsTab === "model" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
52769
53485
  className: `${panel_module_css_default.card} ${panel_module_css_default.settingsCard}`,
52770
53486
  style: { gap: "var(--nf-space-24)" },
52771
53487
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
@@ -52774,129 +53490,36 @@ window.__ModuleLoader__.load({
52774
53490
  size: 18,
52775
53491
  style: { verticalAlign: -3 }
52776
53492
  }), " 模型与推理"]
52777
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
52778
- style: {
52779
- display: "flex",
52780
- flexDirection: "column",
52781
- gap: "var(--nf-space-24)"
53493
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelManager, {
53494
+ api,
53495
+ provider: configDraft.provider,
53496
+ model: configDraft.model,
53497
+ savedModels: configDraft.savedModels ?? [],
53498
+ onProvider: (v) => {
53499
+ setConfigDraft({
53500
+ ...configDraft,
53501
+ provider: v
53502
+ });
52782
53503
  },
52783
- children: [
52784
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
52785
- className: panel_module_css_default.field,
52786
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
52787
- className: panel_module_css_default.fieldLabel,
52788
- children: tt("settings.provider")
52789
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
52790
- className: panel_module_css_default.input,
52791
- value: configDraft.provider,
52792
- onChange: (e) => {
52793
- setConfigDraft({
52794
- ...configDraft,
52795
- provider: e.target.value
52796
- });
52797
- }
52798
- })]
52799
- }),
52800
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
52801
- className: panel_module_css_default.field,
52802
- children: [
52803
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
52804
- className: panel_module_css_default.fieldLabel,
52805
- children: tt("settings.model")
52806
- }),
52807
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
52808
- className: panel_module_css_default.input,
52809
- value: modelCustomMode ? "__custom__" : configDraft.model,
52810
- onChange: (e) => {
52811
- const v = e.target.value;
52812
- if (v === "__custom__") setModelCustomMode(true);
52813
- else {
52814
- setModelCustomMode(false);
52815
- setConfigDraft({
52816
- ...configDraft,
52817
- model: v
52818
- });
52819
- }
52820
- },
52821
- children: [MODEL_PRESETS.map((m) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
52822
- value: m,
52823
- children: m
52824
- }, m)), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
52825
- value: "__custom__",
52826
- children: tt("settings.modelCustom")
52827
- })]
52828
- }),
52829
- modelCustomMode && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
52830
- className: panel_module_css_default.input,
52831
- style: { marginTop: "var(--nf-space-6)" },
52832
- value: configDraft.model,
52833
- placeholder: tt("settings.modelCustomPlaceholder"),
52834
- onChange: (e) => {
52835
- setConfigDraft({
52836
- ...configDraft,
52837
- model: e.target.value
52838
- });
52839
- }
52840
- })
52841
- ]
52842
- }),
52843
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
52844
- className: panel_module_css_default.field,
52845
- children: [
52846
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
52847
- className: panel_module_css_default.fieldLabel,
52848
- children: tt("settings.reasoningEffort")
52849
- }),
52850
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
52851
- className: panel_module_css_default.input,
52852
- value: configDraft.reasoningEffort ?? "off",
52853
- onChange: (e) => {
52854
- setConfigDraft({
52855
- ...configDraft,
52856
- reasoningEffort: e.target.value
52857
- });
52858
- },
52859
- children: REASONING_OPTIONS.map((v) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
52860
- value: v,
52861
- children: tt(`settings.reasoning.${v}`)
52862
- }, v))
52863
- }),
52864
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
52865
- className: panel_module_css_default.meta,
52866
- children: tt("settings.reasoningHint")
52867
- })
52868
- ]
52869
- }),
52870
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
52871
- className: panel_module_css_default.field,
52872
- children: [
52873
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
52874
- className: panel_module_css_default.fieldLabel,
52875
- children: tt("settings.analysisReasoning")
52876
- }),
52877
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
52878
- className: panel_module_css_default.input,
52879
- value: configDraft.analysisReasoning ?? "low",
52880
- onChange: (e) => {
52881
- setConfigDraft({
52882
- ...configDraft,
52883
- analysisReasoning: e.target.value
52884
- });
52885
- },
52886
- children: REASONING_OPTIONS.map((v) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
52887
- value: v,
52888
- children: tt(`settings.reasoning.${v}`)
52889
- }, v))
52890
- }),
52891
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
52892
- className: panel_module_css_default.meta,
52893
- children: tt("settings.analysisReasoningHint")
52894
- })
52895
- ]
52896
- })
52897
- ]
53504
+ onModel: (v) => {
53505
+ setConfigDraft({
53506
+ ...configDraft,
53507
+ model: v
53508
+ });
53509
+ },
53510
+ onSavedModels: (models) => setConfigDraft({
53511
+ ...configDraft,
53512
+ savedModels: models
53513
+ })
52898
53514
  })]
52899
- }),
53515
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReasoningSection, {
53516
+ reasoningEffort: configDraft.reasoningEffort ?? "off",
53517
+ analysisReasoning: configDraft.analysisReasoning ?? "low",
53518
+ onChange: (patch) => setConfigDraft({
53519
+ ...configDraft,
53520
+ ...patch
53521
+ })
53522
+ })] }),
52900
53523
  settingsTab === "writing" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
52901
53524
  className: `${panel_module_css_default.card} ${panel_module_css_default.settingsCard}`,
52902
53525
  style: { gap: "var(--nf-space-24)" },