@musnows/scriverse 0.9.5 → 0.9.6

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.
@@ -11,6 +11,12 @@ export function normalizeChapterLineIdDraft(
11
11
  lineIds: unknown
12
12
  ): Array<string | null>;
13
13
 
14
+ export function remapChapterLineCounts(
15
+ beforeLineIds: unknown,
16
+ afterLineIds: unknown,
17
+ lineCounts: unknown
18
+ ): Map<number, number>;
19
+
14
20
  export function reconcileChapterLineIdDraft(
15
21
  beforeContent: unknown,
16
22
  afterContent: unknown,
@@ -84,6 +84,30 @@ export function normalizeChapterLineIdDraft(content, lineIds) {
84
84
  });
85
85
  }
86
86
 
87
+ export function remapChapterLineCounts(beforeLineIdsValue, afterLineIdsValue, lineCountsValue) {
88
+ const counts = lineCountsValue instanceof Map ? lineCountsValue : new Map();
89
+ const beforeLineIds = Array.isArray(beforeLineIdsValue) ? beforeLineIdsValue : [];
90
+ const afterLineIds = Array.isArray(afterLineIdsValue) ? afterLineIdsValue : [];
91
+ if (beforeLineIds.length === 0 || afterLineIds.length === 0) return new Map(counts);
92
+
93
+ const countsByLineId = new Map();
94
+ counts.forEach((countValue, lineValue) => {
95
+ const line = Number(lineValue);
96
+ const count = Number(countValue);
97
+ const lineId = beforeLineIds[line - 1];
98
+ if (!Number.isInteger(line) || line < 1 || !Number.isInteger(count) || count < 1 || typeof lineId !== "string" || !lineId) return;
99
+ countsByLineId.set(lineId, count);
100
+ });
101
+
102
+ const remapped = new Map();
103
+ afterLineIds.forEach((lineId, index) => {
104
+ if (typeof lineId !== "string" || !lineId) return;
105
+ const count = countsByLineId.get(lineId);
106
+ if (count !== undefined) remapped.set(index + 1, count);
107
+ });
108
+ return remapped;
109
+ }
110
+
87
111
  export function reconcileChapterLineIdDraft(beforeContentValue, afterContentValue, beforeLineIdsValue, hint = null) {
88
112
  const beforeContent = String(beforeContentValue ?? "").replace(/\r\n?/gu, "\n");
89
113
  const afterContent = String(afterContentValue ?? "").replace(/\r\n?/gu, "\n");
@@ -9,7 +9,7 @@
9
9
  <script src="/theme-init.js?v=20260827-reader-prefetch-v1"></script>
10
10
  <link rel="icon" href="/icon.svg?v=20260712" type="image/svg+xml">
11
11
  <link rel="manifest" href="/site.webmanifest">
12
- <link rel="stylesheet" href="/styles.css?v=20260816-task-scope-volume-collapse-v2&feature=ai-tool-call-copy-feedback-v2&feature=ai-send-control-v3&feature=character-gender-v1&feature=character-filter-state-v1&feature=relationship-canvas-scale-v1&feature=relationship-table-scroll-v1&feature=galaxy-compact-controls-v2&feature=galaxy-motion-mode-v2&feature=chapter-search-replace-v3&feature=task-auto-run-ring-center-v3&feature=character-relationship-delete-v1&feature=ai-assistant-workspace-v2&feature=mobile-module-tab-position-v1&feature=volume-detail-icon-v1&feature=editor-actions-flow-v1&feature=reader-controls-subpanel-v1&feature=reader-focus-ring-v1&feature=ai-message-actions-v1&feature=assistant-responsive-navigation-v2&feature=ai-composer-square-controls-v2&feature=annotation-line-counts-v1&feature=line-number-gutter-fill-v1&feature=ai-relationship-roleplay-v1&feature=ai-model-picker-v1&feature=markdown-word-count-five-digit-v2&feature=ai-stream-character-count-stable-v1&feature=ai-stream-character-count-five-digit-v1&feature=annotation-marker-offset-v1&feature=mobile-ai-entry-hidden-v1&feature=phone-client-entry-v1&feature=ai-stream-idle-timeout-v1&feature=ai-user-message-width-v2&feature=ai-chat-image-attachments-v9&feature=ai-message-image-preview-v1&feature=ai-thinking-scroll-v2&feature=toast-click-dismiss-v3&feature=character-avatar-v6&feature=admin-ai-conversations-v1&feature=ai-usage-pricing-v1&feature=ai-usage-pricing-badge-v2&feature=ai-token-quota-positive-v5&feature=ai-token-usage-details-v1&feature=ai-token-usage-details-centered-v1&feature=ai-stream-connection-seconds-v1&feature=ai-token-usage-estimated-price-v1&feature=record-favorites-v1&feature=entity-detail-favorites-v1&feature=entity-pin-v1&feature=character-persona-summary-v1&feature=ai-roleplay-scene-turn-v1&feature=admin-account-identity-v2&feature=task-detail-failure-orange-v1&feature=character-card-header-alignment-v6&feature=character-card-title-fit-v2&feature=book-import-progress-v1&feature=editor-toolbar-compact-v2&feature=reader-first-frame-v1&feature=auth-compact-v2&feature=editor-preview-toggle-v2&feature=setting-title-chrome-v2&feature=entity-pin-icon-center-v1&feature=chapter-center-bottom-space-v1&feature=work-editor-preferences-v1&feature=ai-roleplay-memory-v2&feature=ai-roleplay-memory-v3&feature=ai-roleplay-memory-v5&feature=character-editor-header-actions-v1&feature=roleplay-memory-header-actions-v1&feature=roleplay-memory-header-toolbar-v1&feature=roleplay-memory-action-icons-v1&feature=roleplay-memory-action-colors-v1&feature=roleplay-memory-pin-border-v1&feature=ai-write-tools-v2&feature=ai-write-card-actions-compact-v1&feature=ai-write-plan-actions-footer-v1&feature=ai-question-actions-footer-v1&feature=ai-question-selection-highlight-v1&feature=ai-question-submit-guidance-v1&feature=ai-question-answer-limit-v1">
12
+ <link rel="stylesheet" href="/styles.css?v=20260816-task-scope-volume-collapse-v2&feature=ai-tool-call-copy-feedback-v2&feature=ai-send-control-v3&feature=character-gender-v1&feature=character-filter-state-v1&feature=relationship-canvas-scale-v1&feature=relationship-table-scroll-v1&feature=galaxy-compact-controls-v2&feature=galaxy-motion-mode-v2&feature=chapter-search-replace-v3&feature=task-auto-run-ring-center-v3&feature=character-relationship-delete-v1&feature=ai-assistant-workspace-v2&feature=mobile-module-tab-position-v1&feature=volume-detail-icon-v1&feature=editor-actions-flow-v1&feature=reader-controls-subpanel-v1&feature=reader-focus-ring-v1&feature=ai-message-actions-v1&feature=assistant-responsive-navigation-v2&feature=ai-composer-square-controls-v2&feature=annotation-line-counts-v1&feature=chapter-comment-filters-v1&feature=line-number-gutter-fill-v1&feature=ai-relationship-roleplay-v1&feature=ai-model-picker-v1&feature=markdown-word-count-five-digit-v2&feature=ai-stream-character-count-stable-v1&feature=ai-stream-character-count-five-digit-v1&feature=annotation-marker-offset-v1&feature=mobile-ai-entry-hidden-v1&feature=phone-client-entry-v1&feature=ai-stream-idle-timeout-v1&feature=ai-user-message-width-v2&feature=ai-chat-image-attachments-v9&feature=ai-message-image-preview-v1&feature=ai-thinking-scroll-v2&feature=toast-click-dismiss-v3&feature=character-avatar-v6&feature=admin-ai-conversations-v1&feature=ai-usage-pricing-v1&feature=ai-usage-pricing-badge-v2&feature=ai-token-quota-positive-v5&feature=ai-token-usage-details-v1&feature=ai-token-usage-details-centered-v1&feature=ai-stream-connection-seconds-v1&feature=ai-token-usage-estimated-price-v1&feature=record-favorites-v1&feature=entity-detail-favorites-v1&feature=entity-pin-v1&feature=character-persona-summary-v1&feature=ai-roleplay-scene-turn-v1&feature=admin-account-identity-v2&feature=task-detail-failure-orange-v1&feature=character-card-header-alignment-v6&feature=character-card-title-fit-v2&feature=book-import-progress-v1&feature=editor-toolbar-compact-v2&feature=reader-first-frame-v1&feature=auth-compact-v2&feature=editor-preview-toggle-v2&feature=setting-title-chrome-v2&feature=entity-pin-icon-center-v1&feature=chapter-center-bottom-space-v1&feature=work-editor-preferences-v1&feature=ai-roleplay-memory-v2&feature=ai-roleplay-memory-v3&feature=ai-roleplay-memory-v5&feature=character-editor-header-actions-v1&feature=roleplay-memory-header-actions-v1&feature=roleplay-memory-header-toolbar-v1&feature=roleplay-memory-action-icons-v1&feature=roleplay-memory-action-colors-v1&feature=roleplay-memory-pin-border-v1&feature=ai-write-tools-v2&feature=ai-write-card-actions-compact-v1&feature=ai-write-plan-actions-footer-v1&feature=ai-question-actions-footer-v1&feature=ai-question-selection-highlight-v1&feature=ai-question-submit-guidance-v1&feature=ai-question-answer-limit-v1&feature=semantic-search-v6&feature=chapter-title-renumber-v1&feature=ai-writing-skills-v1&feature=remote-mcp-v1&feature=character-alias-chips-v2&feature=character-title-input-v1&feature=character-detail-value-wrap-v2">
13
13
  </head>
14
14
  <body class="auth-pending">
15
15
  <section id="auth-view" class="auth-view hidden" aria-labelledby="auth-title">
@@ -330,6 +330,7 @@
330
330
  <div class="ai-heading-actions">
331
331
  <button id="ai-conversation-switcher" class="ai-conversation-switcher" type="button" aria-label="切换打开的对话" aria-controls="ai-conversation-switcher-menu" aria-expanded="false" aria-haspopup="dialog" title="切换打开的对话"><span id="ai-conversation-title">新对话</span><small id="ai-open-conversation-count">1</small><svg viewBox="0 0 12 8" aria-hidden="true" focusable="false"><path d="M1 1.5 6 6.5l5-5"></path></svg></button>
332
332
  <button id="ai-history-toggle" type="button" aria-label="历史记录" aria-controls="ai-history-dialog" aria-expanded="false" aria-haspopup="dialog" title="历史记录"><svg class="ai-heading-action-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M3 12a9 9 0 1 0 3-6.7L3 8"></path><path d="M3 3v5h5M12 7v5l3.5 2"></path></svg></button>
333
+ <button id="ai-semantic-search-toggle" type="button" aria-label="主动语义检索" aria-controls="ai-semantic-search-panel" aria-expanded="false" title="主动语义检索"><svg class="ai-heading-action-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="10.5" cy="10.5" r="6.5"></circle><path d="m15.5 15.5 5 5M7.5 10.5h6M10.5 7.5v6"></path></svg></button>
333
334
  <button id="ai-approval-center-toggle" type="button" aria-label="AI 操作审批中心" aria-controls="ai-approval-center-dialog" aria-expanded="false" aria-haspopup="dialog" title="AI 操作审批中心"><svg class="ai-heading-action-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12 3l7 3v5c0 4.4-2.9 8.2-7 10-4.1-1.8-7-5.6-7-10V6z"></path><path d="M9 12l2.2 2.2L15.5 9.5"></path></svg></button>
334
335
  <button id="ai-new-conversation" type="button" aria-label="新建对话" title="新建对话">+</button>
335
336
  </div>
@@ -342,7 +343,7 @@
342
343
  <div id="ai-chat-tabs" class="ai-chat-tabs hidden" role="tablist" aria-label="Agent 对话页签" aria-hidden="true"></div>
343
344
  <div class="quick-actions" aria-label="快捷指令">
344
345
  <button type="button" data-task="chat" data-prompt="总结当前章节,并列出尚未解决的冲突。">总结本章</button>
345
- <button type="button" data-task="continue" data-prompt="续写当前章节,保持现有叙事风格和人物状态。">续写</button>
346
+ <button type="button" data-task="chat" data-prompt="续写当前章节,保持现有叙事风格和人物状态。">续写</button>
346
347
  <button type="button" data-task="chat" data-prompt="提供三种后续剧情方向,并说明各自与既有设定的兼容性。">三种方向</button>
347
348
  <button type="button" data-task="chat" data-prompt="检查当前章节与锁定设定、人物状态和时间线的冲突。">检查冲突</button>
348
349
  </div>
@@ -350,22 +351,28 @@
350
351
  <div id="ai-feed" class="ai-feed" role="tabpanel">
351
352
  <div class="assistant-message">
352
353
  <span>助手</span>
353
- <div class="message-body"><p>选择章节和模型后,可以问答、续写或校对。所有引用都基于已保存正文。</p></div>
354
+ <div class="message-body"><p>选择章节和模型后即可开始问答;提到续写或润色时会自动加载对应 Skill,也可用 /continue-writing 或 /polish-writing 强制加载。所有引用都基于已保存正文。</p></div>
354
355
  </div>
355
356
  </div>
356
357
  </div>
357
358
  <div class="prompt-box">
359
+ <section id="ai-semantic-search-panel" class="ai-semantic-search-panel hidden" aria-labelledby="ai-semantic-search-title">
360
+ <header><div><strong id="ai-semantic-search-title">主动语义检索</strong><small>只在点击检索后调用 embedding;结果默认仅查看。</small></div><button id="ai-semantic-search-close" type="button" aria-label="关闭主动语义检索">×</button></header>
361
+ <div class="ai-semantic-search-form"><label for="ai-semantic-query">自然语言问题<input id="ai-semantic-query" type="search" maxlength="2000" placeholder="例如:谁掌管北港的远航审批?"></label><label for="ai-semantic-scope">检索模块<select id="ai-semantic-scope"><option value="">全部可读模块</option><option value="chapter">正文</option><option value="setting">设定</option><option value="character">人物档案</option><option value="race">种族</option><option value="organization">组织</option><option value="timeline">时间线</option><option value="relationship">人物关系</option><option value="outlines">大纲与伏笔</option></select></label><button id="ai-semantic-search-run" class="primary-button" type="button">开始检索</button></div>
362
+ <p id="ai-semantic-search-status" class="usage-measurement-note" role="status" aria-live="polite">输入整句问题后主动检索;不会改变普通消息的隐藏上下文。</p>
363
+ <div id="ai-semantic-search-results" class="ai-semantic-search-results" tabindex="0" aria-label="语义检索结果,可滚动"></div>
364
+ <footer><span id="ai-semantic-selection-summary">尚未选择结果</span><button id="ai-semantic-inject" class="ghost-button" type="button" disabled>将选中结果注入本轮</button></footer>
365
+ </section>
366
+ <div id="ai-semantic-injection" class="ai-semantic-injection hidden" aria-live="polite"></div>
358
367
  <div id="ai-citations" class="ai-citations hidden" aria-label="已添加的正文引用"></div>
359
368
  <section id="ai-context-warning" class="ai-context-warning hidden" role="status" aria-live="polite">
360
369
  <div><strong id="ai-context-warning-title">对话上下文过长</strong><p id="ai-context-warning-message">当前对话上下文过长,是否进行压缩?不压缩可能会导致后续请求失败</p></div>
361
370
  <div><button id="ai-context-compact" type="button">压缩</button><button id="ai-context-dismiss" type="button">忽略</button><button id="ai-context-new-conversation" type="button">新开对话</button></div>
362
371
  </section>
363
372
  <div class="prompt-options">
364
- <select id="ai-task" aria-label="任务类型">
373
+ <select id="ai-task" aria-label="对话模式">
365
374
  <option value="chat">问答</option>
366
375
  <option value="roleplay">角色扮演</option>
367
- <option value="continue">续写</option>
368
- <option value="polish">润色选中文本</option>
369
376
  </select>
370
377
  <select id="ai-scope" aria-label="上下文范围">
371
378
  <option value="none">无上下文</option>
@@ -583,7 +590,7 @@
583
590
  <dialog id="chapter-batch-dialog" class="dialog chapter-batch-dialog" aria-labelledby="chapter-batch-title">
584
591
  <form id="chapter-batch-form" method="post">
585
592
  <div class="dialog-header">
586
- <div><span class="eyebrow">正文工具</span><h2 id="chapter-batch-title">章节批量管理</h2><p class="dialog-header-meta">选择多个章节后统一移动、修改属性或软删除。</p></div>
593
+ <div><span class="eyebrow">正文工具</span><h2 id="chapter-batch-title">章节批量管理</h2><p class="dialog-header-meta">选择多个章节后统一移动、重排标题、修改属性或软删除。</p></div>
587
594
  <button id="chapter-batch-close" class="dialog-close" type="button" aria-label="关闭章节批量管理">×</button>
588
595
  </div>
589
596
  <div class="chapter-batch-toolbar">
@@ -601,9 +608,13 @@
601
608
  </div>
602
609
  <div id="chapter-batch-list" class="chapter-batch-list"></div>
603
610
  <div class="chapter-batch-controls">
604
- <label>批量操作<select id="chapter-batch-action"><option value="move">移动到分卷</option><option value="setType">修改章节类型</option><option value="exclude">排除 AI 分析</option><option value="include">纳入 AI 分析</option><option value="delete">软删除章节</option></select></label>
611
+ <label>批量操作<select id="chapter-batch-action"><option value="move">移动到分卷</option><option value="setType">修改章节类型</option><option value="renumberTitles">重排标题序号</option><option value="exclude">排除 AI 分析</option><option value="include">纳入 AI 分析</option><option value="delete">软删除章节</option></select></label>
605
612
  <label id="chapter-batch-volume-field">目标分卷<select id="chapter-batch-volume"></select></label>
606
613
  <label id="chapter-batch-type-field" class="hidden">章节类型<select id="chapter-batch-type"><option value="正文">正文</option><option value="设定">设定</option><option value="作者的话">作者的话</option><option value="其他">其他</option></select></label>
614
+ <label id="chapter-batch-template-field" class="hidden">标题格式<input id="chapter-batch-template" type="text" value="第{n}章" maxlength="50" autocomplete="off" aria-describedby="chapter-batch-renumber-note"></label>
615
+ <label id="chapter-batch-number-style-field" class="hidden">序号样式<select id="chapter-batch-number-style"><option value="chinese">中文数字(一、二、三)</option><option value="arabic">阿拉伯数字(1、2、3)</option></select></label>
616
+ <label id="chapter-batch-start-field" class="hidden">起始序号<input id="chapter-batch-start" type="number" value="1" min="1" max="999999" step="1" inputmode="numeric" aria-describedby="chapter-batch-renumber-note"></label>
617
+ <p id="chapter-batch-renumber-note" class="chapter-batch-renumber-note hidden">格式必须且只能包含一个 <code>{n}</code>。系统按目录顺序重排所选章节,清洗可识别的旧序号;异常标题会完整保留为副标题。</p>
607
618
  </div>
608
619
  <div class="dialog-actions">
609
620
  <button id="chapter-batch-cancel" class="ghost-button" type="button">取消</button>
@@ -677,12 +688,12 @@
677
688
  </div>
678
689
  </form>
679
690
 
680
- <form id="character-editor-form" class="entity-editor-page hidden" aria-labelledby="character-editor-title" method="post">
691
+ <form id="character-editor-form" class="entity-editor-page hidden" aria-label="人物档案编辑器" method="post">
681
692
  <header class="character-editor-header">
682
693
  <button id="character-editor-close" class="entity-editor-back" type="button">返回角色列表</button>
683
694
  <div>
684
695
  <span id="character-editor-eyebrow" class="eyebrow">人物主档案</span>
685
- <div class="character-editor-title-row"><h1 id="character-editor-title">新建角色</h1><span id="character-editor-version" class="character-version-badge">新档案</span><span id="character-editor-readonly-badge" class="entity-editor-readonly-badge hidden">只读模式</span></div>
696
+ <div class="character-editor-title-row"><input id="character-editor-name" class="character-editor-title-input" name="name" maxlength="200" placeholder="新建角色" aria-label="角色标准名" required><span id="character-editor-version" class="character-version-badge">新档案</span><span id="character-editor-readonly-badge" class="entity-editor-readonly-badge hidden">只读模式</span></div>
686
697
  </div>
687
698
  <div class="character-editor-header-actions">
688
699
  <button id="character-editor-pin" class="entity-detail-pin-button hidden" type="button" aria-pressed="false"></button>
@@ -1311,6 +1322,6 @@
1311
1322
  </dialog>
1312
1323
 
1313
1324
  <div id="auth-loading" class="auth-loading" role="status" aria-label="正在载入工作台"></div>
1314
- <script type="module" src="/app.js?v=20260816-extended-thinking-effort-v1&feature=ai-tool-call-copy-feedback-v2&feature=ai-send-control-v2&feature=analysis-task-queue-refresh-v1&feature=character-gender-v1&feature=character-filter-state-v1&feature=relationship-canvas-scale-v1&feature=relationship-table-scroll-v1&feature=ai-session-id-copy-v2&feature=galaxy-motion-mode-v3&feature=galaxy-edge-label-threshold-v1&feature=calculate-time-tool-v2&feature=analysis-task-expired-toast-v1&feature=global-replace-volume-v1&feature=chapter-search-replace-v1&feature=chapter-save-toast-v1&feature=character-relationship-delete-v1&feature=character-relationship-group-v1&feature=analysis-task-stability-delay-v1&feature=ai-assistant-workspace-v2&feature=volume-detail-icon-v1&feature=volume-story-order-v1&feature=reader-manual-chapter-navigation-v1&feature=ai-message-reference-badges-v1&feature=ai-roleplay-message-reference-v1&feature=ai-message-actions-v1&feature=assistant-responsive-navigation-v3&feature=annotation-permissions-v1&feature=annotation-line-counts-v1&feature=ai-relationship-roleplay-v1&feature=ai-roleplay-user-character-visibility-v1&feature=ai-roleplay-story-recall-v1&feature=ai-model-picker-v1&feature=ai-fork-model-unlock-v1&feature=context-percent-format-v1&feature=annotation-precise-locate-v1&feature=markdown-word-count-stable-v1&feature=ai-stream-character-count-stable-v2&feature=ai-process-empty-intermediate-v1&feature=ai-feed-scroll-follow-v1&feature=ai-message-retry-v1&feature=ai-stream-idle-timeout-v2&feature=ai-config-delete-v1&feature=ai-provider-protocol-options-v1&feature=ai-provider-thinking-type-v1&feature=ai-chat-image-attachments-v8&feature=ai-message-image-preview-v1&feature=ai-thinking-scroll-v2&feature=ai-image-conversation-model-lock-v1&feature=toast-click-dismiss-v2&feature=system-restart-dialog-delay-v1&feature=character-avatar-v6&feature=character-death-position-v1&feature=admin-ai-conversations-v1&feature=ai-usage-pricing-v1&feature=ai-usage-pricing-badge-v2&feature=ai-usage-pricing-label-v1&feature=ai-usage-token-breakdown-v1&feature=ai-usage-pricing-cache-v2&feature=ai-usage-pricing-manual-refresh-v1&feature=ai-monthly-token-quota-v1&feature=ai-provider-token-quota-v1&feature=ai-token-quota-positive-v6&feature=ai-model-thinking-label-v1&feature=ai-model-picker-focus-v1&feature=ai-provider-model-import-v1&feature=ai-assistant-brain-icon-v1&feature=ai-token-usage-details-v1&feature=ai-token-usage-details-centered-v1&feature=ai-token-usage-raw-input-v1&feature=ai-stream-connection-seconds-v1&feature=phone-client-entry-v1&feature=ai-usage-pricing-cache-v1&feature=ai-model-thinking-label-v3&feature=ai-roleplay-speaker-label-v1&feature=toast-modal-host-v1&feature=api-key-copy-existing-v1&feature=character-favorite-v1&feature=record-favorites-v1&feature=ai-token-usage-estimated-price-v1&feature=entity-detail-favorites-v1&feature=entity-pin-v1&feature=entity-pin-icon-v1&feature=roleplay-favorite-label-v1&feature=ai-roleplay-knowledge-tools-v1&feature=character-persona-summary-v1&feature=ai-roleplay-scene-turn-v2&feature=admin-account-identity-v2&feature=ai-provider-analysis-timeout-v1&feature=task-detail-failure-orange-v1&feature=book-import-progress-v1&feature=presence-multiple-users-v1&feature=ai-context-input-output-v1&feature=editor-blank-lines-preserved-v1&feature=reader-first-frame-v1&feature=vditor-lazy-load-v1&feature=ui-module-preload-v1&feature=reader-initial-prefetch-v1&feature=editor-preview-toggle-v2&feature=vditor-fullscreen-disabled-v1&feature=chapter-auto-indent-v1&feature=chapter-centered-scroll-v1&feature=work-editor-preferences-v1&feature=ai-context-output-usage-v1&feature=ai-roleplay-memory-v4&feature=ai-roleplay-memory-v5&feature=roleplay-memory-header-actions-v1&feature=roleplay-memory-header-toolbar-v1&feature=roleplay-memory-action-icons-v1&feature=roleplay-memory-action-colors-v1&feature=annotation-line-anchor-v1&feature=stable-line-ids-v1&feature=ai-write-tools-v3&feature=ai-question-option-supplement-v1&feature=ai-question-selection-highlight-v1&feature=ai-question-continuation-ui-v1&feature=ai-question-tool-result-v1&feature=ai-question-submit-guidance-v1&feature=ai-question-answer-limit-v1"></script>
1325
+ <script type="module" src="/app.js?v=20260816-extended-thinking-effort-v1&feature=ai-tool-call-copy-feedback-v2&feature=ai-send-control-v2&feature=analysis-task-queue-refresh-v1&feature=character-gender-v1&feature=character-filter-state-v1&feature=relationship-canvas-scale-v1&feature=relationship-table-scroll-v1&feature=ai-session-id-copy-v2&feature=galaxy-motion-mode-v3&feature=galaxy-edge-label-threshold-v1&feature=calculate-time-tool-v2&feature=analysis-task-expired-toast-v1&feature=global-replace-volume-v1&feature=chapter-search-replace-v1&feature=chapter-save-toast-v1&feature=character-relationship-delete-v1&feature=character-relationship-group-v1&feature=analysis-task-stability-delay-v1&feature=ai-assistant-workspace-v2&feature=volume-detail-icon-v1&feature=volume-story-order-v1&feature=reader-manual-chapter-navigation-v1&feature=ai-message-reference-badges-v1&feature=ai-roleplay-message-reference-v1&feature=ai-message-actions-v1&feature=assistant-responsive-navigation-v3&feature=annotation-permissions-v1&feature=annotation-line-counts-v1&feature=ai-relationship-roleplay-v1&feature=ai-roleplay-user-character-visibility-v1&feature=ai-roleplay-story-recall-v1&feature=ai-model-picker-v1&feature=ai-fork-model-unlock-v1&feature=context-percent-format-v1&feature=annotation-precise-locate-v1&feature=markdown-word-count-stable-v1&feature=ai-stream-character-count-stable-v2&feature=ai-process-empty-intermediate-v1&feature=ai-feed-scroll-follow-v1&feature=ai-message-retry-v1&feature=ai-stream-idle-timeout-v2&feature=ai-config-delete-v1&feature=ai-provider-protocol-options-v1&feature=ai-provider-thinking-type-v1&feature=ai-chat-image-attachments-v8&feature=ai-message-image-preview-v1&feature=ai-thinking-scroll-v2&feature=ai-image-conversation-model-lock-v1&feature=toast-click-dismiss-v2&feature=system-restart-dialog-delay-v1&feature=character-avatar-v6&feature=character-death-position-v1&feature=admin-ai-conversations-v1&feature=ai-usage-pricing-v1&feature=ai-usage-pricing-badge-v2&feature=ai-usage-pricing-label-v1&feature=ai-usage-token-breakdown-v1&feature=ai-usage-pricing-cache-v2&feature=ai-usage-pricing-manual-refresh-v1&feature=ai-monthly-token-quota-v1&feature=ai-provider-token-quota-v1&feature=ai-token-quota-positive-v6&feature=ai-model-thinking-label-v1&feature=ai-model-picker-focus-v1&feature=ai-provider-model-import-v1&feature=ai-assistant-brain-icon-v1&feature=ai-token-usage-details-v1&feature=ai-token-usage-details-centered-v1&feature=ai-token-usage-raw-input-v1&feature=ai-stream-connection-seconds-v1&feature=phone-client-entry-v1&feature=ai-usage-pricing-cache-v1&feature=ai-model-thinking-label-v3&feature=ai-roleplay-speaker-label-v1&feature=toast-modal-host-v1&feature=api-key-copy-existing-v1&feature=character-favorite-v1&feature=record-favorites-v1&feature=ai-token-usage-estimated-price-v1&feature=entity-detail-favorites-v1&feature=entity-pin-v1&feature=entity-pin-icon-v1&feature=roleplay-favorite-label-v1&feature=ai-roleplay-knowledge-tools-v1&feature=character-persona-summary-v1&feature=ai-roleplay-scene-turn-v2&feature=admin-account-identity-v2&feature=ai-provider-analysis-timeout-v1&feature=task-detail-failure-orange-v1&feature=book-import-progress-v1&feature=presence-multiple-users-v1&feature=ai-context-input-output-v1&feature=editor-blank-lines-preserved-v1&feature=reader-first-frame-v1&feature=vditor-lazy-load-v1&feature=ui-module-preload-v1&feature=reader-initial-prefetch-v1&feature=editor-preview-toggle-v2&feature=vditor-fullscreen-disabled-v1&feature=chapter-auto-indent-v1&feature=chapter-centered-scroll-v1&feature=work-editor-preferences-v1&feature=ai-context-output-usage-v1&feature=ai-roleplay-memory-v4&feature=ai-roleplay-memory-v5&feature=roleplay-memory-header-actions-v1&feature=roleplay-memory-header-toolbar-v1&feature=roleplay-memory-action-icons-v1&feature=roleplay-memory-action-colors-v1&feature=annotation-line-anchor-v1&feature=stable-line-ids-v1&feature=live-annotation-anchors-v1&feature=chapter-comment-filters-v1&feature=ai-write-tools-v3&feature=ai-question-option-supplement-v1&feature=ai-question-selection-highlight-v1&feature=ai-question-continuation-ui-v1&feature=ai-question-tool-result-v1&feature=ai-question-submit-guidance-v1&feature=ai-question-answer-limit-v1&feature=semantic-search-v6&feature=chapter-title-renumber-v1&feature=ai-writing-skills-v3&feature=ai-cancel-preserve-process-v2&feature=remote-mcp-v1&feature=character-alias-chips-v2&feature=character-title-input-v1&feature=character-detail-value-wrap-v2&feature=chapter-batch-editor-refresh-v1"></script>
1315
1326
  </body>
1316
1327
  </html>
@@ -8,6 +8,7 @@ export function supportsMultimodalModelProtocol(protocol: string | null | undefi
8
8
  export type ModelFormValues = {
9
9
  displayName: string;
10
10
  modelId: string;
11
+ modelKind: "chat" | "embedding" | "rerank";
11
12
  purposes: string[];
12
13
  contextWindow: number;
13
14
  temperature: number;
@@ -20,6 +20,7 @@ export const MODEL_THINKING_EFFORT_OPTIONS = Object.freeze([
20
20
  ]);
21
21
 
22
22
  const modelThinkingEfforts = new Set(MODEL_THINKING_EFFORT_OPTIONS.map(([value]) => value));
23
+ const modelKinds = new Set(["chat", "embedding", "rerank"]);
23
24
 
24
25
  export const MIN_MODEL_CONTEXT_WINDOW = 32_768;
25
26
  export const RECOMMENDED_MODEL_CONTEXT_WINDOW = 128_000;
@@ -58,11 +59,13 @@ export function modelContextWindowGuidance(value) {
58
59
 
59
60
  export function modelFormValues(model = null) {
60
61
  const modelId = String(model?.modelId ?? "");
62
+ const modelKind = modelKinds.has(model?.modelKind) ? model.modelKind : "chat";
61
63
  const configuredTemperature = model?.preset?.temperature;
62
64
  return {
63
65
  displayName: model?.displayName ?? "",
64
66
  modelId,
65
- purposes: model ? normalizeModelPurposes(model.purposes) : ["chat", "continue"],
67
+ modelKind,
68
+ purposes: modelKind === "chat" ? (model ? normalizeModelPurposes(model.purposes) : ["chat", "continue"]) : [],
66
69
  contextWindow: model?.contextWindow ?? 128000,
67
70
  temperature: isKimiModelId(modelId) && !(typeof configuredTemperature === "number" && Number.isFinite(configuredTemperature))
68
71
  ? 1
@@ -78,10 +81,12 @@ export function modelFormValues(model = null) {
78
81
 
79
82
  export function modelPayload(values, existingPreset = {}) {
80
83
  const modelId = String(values.modelId);
84
+ const modelKind = modelKinds.has(values.modelKind) ? values.modelKind : "chat";
81
85
  return {
82
86
  displayName: String(values.displayName),
83
87
  modelId,
84
- purposes: normalizeModelPurposes(values.purposes),
88
+ modelKind,
89
+ purposes: modelKind === "chat" ? normalizeModelPurposes(values.purposes) : [],
85
90
  contextWindow: Number(values.contextWindow),
86
91
  preset: {
87
92
  ...existingPreset,
@@ -90,8 +95,8 @@ export function modelPayload(values, existingPreset = {}) {
90
95
  },
91
96
  thinkingEnabled: Boolean(values.thinkingEnabled),
92
97
  thinkingEffort: modelThinkingEfforts.has(values.thinkingEffort) ? values.thinkingEffort : "default",
93
- multimodalEnabled: Boolean(values.multimodalEnabled),
94
- imageToolDefault: Boolean(values.imageToolDefault),
98
+ multimodalEnabled: modelKind === "chat" && Boolean(values.multimodalEnabled),
99
+ imageToolDefault: modelKind === "chat" && Boolean(values.imageToolDefault),
95
100
  enabled: Boolean(values.enabled)
96
101
  };
97
102
  }
@@ -1420,6 +1420,10 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
1420
1420
  .chapter-batch-controls select:hover:not(:disabled) { border-color: color-mix(in srgb, var(--accent) 58%, var(--line)); }
1421
1421
  .chapter-batch-controls select:focus-visible { border-color: var(--accent); outline: none; box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent); }
1422
1422
  .chapter-batch-controls select:disabled { cursor: not-allowed; opacity: .52; }
1423
+ .chapter-batch-controls input { width: 100%; min-width: 0; min-height: 40px; padding: 8px 12px; border-color: color-mix(in srgb, var(--line) 82%, var(--ink)); border-radius: 5px; background: var(--surface); color: var(--ink); font-size: 12px; font-weight: 500; }
1424
+ .chapter-batch-controls input:focus-visible { border-color: var(--accent); outline: none; box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent); }
1425
+ .chapter-batch-renumber-note { grid-column: 1 / -1; margin: 0; color: var(--muted); font-size: 10px; line-height: 1.6; }
1426
+ .chapter-batch-renumber-note code { color: var(--accent-dark); font-family: var(--font-mono), monospace; }
1423
1427
  @media (max-width: 620px) { .chapter-batch-controls { grid-template-columns: 1fr; } }
1424
1428
 
1425
1429
  .ghost-button, .primary-button { border-radius: 4px; padding: 8px 13px; font-size: 12px; }
@@ -1642,6 +1646,7 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
1642
1646
  .draft-type-filter-field > span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
1643
1647
  .draft-type-filter-field select { width: 100%; min-width: 0; min-height: 38px; padding: 8px 10px; background: var(--surface); color: var(--ink); font-size: 11px; }
1644
1648
  .setting-filter-toolbar { grid-template-columns: minmax(0, 1.2fr) repeat(2, minmax(0, .8fr)) auto; }
1649
+ .chapter-comment-filter-toolbar { grid-template-columns: minmax(180px, .8fr) minmax(240px, 1.2fr) auto; }
1645
1650
  .setting-filter-field { display: grid; min-width: 0; }
1646
1651
  .setting-filter-field > span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
1647
1652
  .setting-filter-field input, .setting-filter-field select { width: 100%; min-width: 0; min-height: 38px; padding: 8px 10px; background: var(--surface); color: var(--ink); font-size: 11px; }
@@ -2133,6 +2138,29 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
2133
2138
  .ai-agent-tools strong { color: var(--ink); font-size: 12px; font-weight: 600; }
2134
2139
  .ai-agent-tools small { display: block; margin-top: 2px; font-size: 10px; }
2135
2140
  .ai-agent-tools-section + .empty-state { margin-top: 24px; border-top: 1px solid var(--line); }
2141
+ .remote-mcp-config-field { display: grid; gap: 7px; }
2142
+ .remote-mcp-config-field > span { color: var(--ink); font-size: 11px; font-weight: 600; }
2143
+ .remote-mcp-config-field textarea {
2144
+ width: 100%;
2145
+ min-height: 260px;
2146
+ resize: vertical;
2147
+ overflow: auto;
2148
+ padding: 11px 12px;
2149
+ border: 1px solid var(--line);
2150
+ border-radius: 5px;
2151
+ background: var(--surface-soft);
2152
+ color: var(--ink);
2153
+ font-family: var(--font-latin), ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
2154
+ font-size: 11px;
2155
+ line-height: 1.55;
2156
+ tab-size: 2;
2157
+ white-space: pre;
2158
+ }
2159
+ .remote-mcp-config-help { display: block; margin-top: 7px; color: var(--muted); font-size: 10px; line-height: 1.55; }
2160
+ .remote-mcp-status { margin: 10px 0 0; color: var(--muted); font-size: 10px; line-height: 1.5; }
2161
+ @media (max-width: 700px) {
2162
+ .remote-mcp-config-field textarea { min-height: 220px; font-size: 10px; }
2163
+ }
2136
2164
  .default-model-select { min-width: 260px; padding: 7px 9px; font-size: 11px; }
2137
2165
  .empty-state { padding: 70px 30px; text-align: center; color: var(--muted); border: 1px dashed var(--line); }
2138
2166
  .empty-state b { display: block; color: var(--ink); margin-bottom: 8px; }
@@ -2706,6 +2734,7 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
2706
2734
  .config-inline-save > .config-checkbox-field input[type="checkbox"] { width: 18px; min-width: 18px; height: 18px; }
2707
2735
  .agent-tool-call-global-multiplier-toggle button { width: 32px; min-width: 32px; height: 30px; min-height: 30px; padding: 0; font-family: var(--font-latin), monospace; font-size: 11px; font-variant-numeric: tabular-nums; }
2708
2736
  .relationship-index-summary { display: grid; gap: 14px; padding: 15px; border: 1px solid var(--line); border-radius: 6px; background: var(--surface-soft); }
2737
+ .semantic-index-summary { display: grid; gap: 14px; padding: 15px; border: 1px solid var(--line); border-radius: 6px; background: var(--surface-soft); }
2709
2738
  .relationship-index-state-row { display: flex; align-items: center; gap: 12px 18px; flex-wrap: wrap; color: var(--muted); font-size: 10px; }
2710
2739
  .relationship-index-state-row strong { color: var(--ink); font-family: var(--font-latin), monospace; font-weight: 600; }
2711
2740
  .relationship-index-state { display: inline-flex; align-items: center; min-height: 23px; padding: 3px 9px; border: 1px solid var(--line); border-radius: 12px; background: var(--surface); color: var(--muted); font-size: 10px; font-weight: 650; }
@@ -2713,6 +2742,7 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
2713
2742
  .relationship-index-state.is-building { border-color: color-mix(in srgb, var(--task-running) 45%, var(--line)); background: color-mix(in srgb, var(--task-running) 9%, var(--surface)); color: var(--task-running); }
2714
2743
  .relationship-index-state.is-queued { border-color: color-mix(in srgb, var(--accent) 38%, var(--line)); background: color-mix(in srgb, var(--accent) 7%, var(--surface)); color: var(--accent-dark); }
2715
2744
  .relationship-index-state.is-failed { border-color: color-mix(in srgb, var(--accent) 60%, var(--line)); background: color-mix(in srgb, var(--accent) 12%, var(--surface)); color: var(--accent-dark); }
2745
+ .relationship-index-state.is-paused, .relationship-index-state.is-unconfigured { border-color: color-mix(in srgb, var(--accent) 60%, var(--line)); background: color-mix(in srgb, var(--accent) 12%, var(--surface)); color: var(--accent-dark); }
2716
2746
  .relationship-index-metrics { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin: 0; }
2717
2747
  .relationship-index-metrics > div { display: grid; gap: 3px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 4px; background: var(--surface); }
2718
2748
  .relationship-index-metrics dt { color: var(--muted); font-size: 9px; }
@@ -2726,6 +2756,18 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
2726
2756
  .relationship-index-queue-chip strong { display: inline-grid; min-width: 18px; height: 18px; padding: 0 4px; place-items: center; border-radius: 9px; background: var(--paper-deep); color: var(--ink); font-family: var(--font-latin), monospace; font-size: 9px; }
2727
2757
  .relationship-index-error { margin: 0; padding: 8px 10px; border-left: 3px solid var(--accent); background: color-mix(in srgb, var(--accent) 6%, var(--surface)); color: var(--accent-dark); font-size: 10px; }
2728
2758
  .relationship-index-actions { display: flex; align-items: center; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
2759
+ .semantic-settings-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 14px; margin-bottom: 10px; }
2760
+ .semantic-settings-grid > label { display: grid; align-content: start; gap: 6px; color: var(--muted); font-size: 10px; }
2761
+ .semantic-settings-grid :is(input, select) { width: 100%; min-width: 0; }
2762
+ .semantic-settings-grid :is(input:not([type="checkbox"]), select) { min-height: 36px; padding: 6px 8px; }
2763
+ .semantic-settings-grid .semantic-enabled-field { grid-column: 1 / -1; display: flex; }
2764
+ .semantic-index-progress { width: 100%; height: 8px; overflow: hidden; border: 0; border-radius: 4px; accent-color: var(--accent); }
2765
+ .semantic-index-progress::-webkit-progress-bar { background: var(--paper-deep); }
2766
+ .semantic-index-progress::-webkit-progress-value { background: var(--accent); }
2767
+ .usage-call-types { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; margin: 8px 0 14px; }
2768
+ .usage-call-type-chip { display: inline-flex; align-items: center; gap: 7px; padding: 5px 8px; border: 1px solid var(--line); border-radius: 4px; background: var(--surface-soft); font-size: 9px; }
2769
+ .usage-call-type-chip strong { color: var(--ink); }
2770
+ .usage-call-type-chip span { color: var(--muted); }
2729
2771
  .config-section .config-save-button { min-height: 32px; padding: 5px 11px; font-size: 11px; }
2730
2772
  .config-section .card-actions { margin-top: 12px; }
2731
2773
  .config-section .card-actions .config-save-button { border: 1px solid var(--line); background: transparent; color: var(--ink); }
@@ -2743,6 +2785,9 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
2743
2785
  @media (max-width: 640px) {
2744
2786
  .config-inline-save .book-summary-context-percent-field,
2745
2787
  .config-inline-save .context-compact-threshold-field { grid-template-columns: minmax(0, 1fr); row-gap: 6px; width: 100%; }
2788
+ .semantic-settings-grid { grid-template-columns: minmax(0, 1fr); }
2789
+ .semantic-settings-grid .semantic-enabled-field { grid-column: auto; }
2790
+ .semantic-index-summary .relationship-index-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
2746
2791
  }
2747
2792
  .field-label textarea {
2748
2793
  width: 100%;
@@ -2976,11 +3021,46 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
2976
3021
  }
2977
3022
 
2978
3023
  .guard-card { margin-top: 10px; padding: 9px 10px; border: 1px solid var(--line); border-left: 3px solid var(--green); border-radius: 4px; background: var(--surface-soft); }
3024
+ .writing-suggestion-ui { display: contents; }
2979
3025
  .guard-card.warning { border-left-color: #c07b31; }.guard-card.failed { border-left-color: var(--accent); }
2980
3026
  .guard-card strong { display: block; margin-bottom: 5px; font-size: 10px; }.guard-card p { margin: 4px 0; color: var(--muted); font-size: 9px; line-height: 1.45; }.guard-card p b { color: var(--ink); }
2981
3027
  .message-actions { display: flex; gap: 7px; margin-top: 10px; }
2982
3028
  .message-actions button { border: 1px solid rgba(139,61,44,.25); background: var(--surface); color: var(--accent-dark); font-size: 10px; padding: 5px 8px; border-radius: 3px; }
2983
3029
  .prompt-box { border-top: 1px solid var(--line); padding-top: 12px; }
3030
+ .ai-semantic-search-panel { display: grid; grid-template-rows: auto auto auto minmax(0, 1fr) auto; min-height: 0; height: min(520px, 58vh); max-height: min(520px, 58vh); margin-bottom: 9px; overflow: hidden; border: 1px solid var(--line); border-radius: 7px; background: var(--surface); box-shadow: 0 12px 30px rgba(49,42,32,.12); }
3031
+ .ai-semantic-search-panel > header, .ai-semantic-search-panel > footer { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 9px 10px; border-bottom: 1px solid var(--line); }
3032
+ .ai-semantic-search-panel > header > div { display: grid; min-width: 0; gap: 2px; }
3033
+ .ai-semantic-search-panel > header strong { font-size: 11px; }
3034
+ .ai-semantic-search-panel > header small, .ai-semantic-search-panel > footer span { color: var(--muted); font-size: 9px; }
3035
+ .ai-semantic-search-panel > header button { width: 25px; min-width: 25px; height: 25px; padding: 0; border: 0; background: transparent; color: var(--muted); font-size: 17px; }
3036
+ .ai-semantic-search-form { display: grid; grid-template-columns: minmax(0, 1fr) minmax(108px, .45fr); gap: 7px; padding: 10px; }
3037
+ .ai-semantic-search-form label { display: grid; gap: 4px; color: var(--muted); font-size: 9px; }
3038
+ .ai-semantic-search-form button { grid-column: 1 / -1; }
3039
+ #ai-semantic-search-status { margin: 0; padding: 0 10px 8px; }
3040
+ .ai-semantic-search-results { display: grid; align-content: start; gap: 6px; min-height: 0; padding: 0 10px 10px; overflow-x: hidden; overflow-y: auto; overscroll-behavior: contain; scrollbar-gutter: stable; -webkit-overflow-scrolling: touch; }
3041
+ .ai-semantic-result { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start; gap: 7px; padding: 8px; border: 1px solid var(--line); border-radius: 5px; background: var(--surface-soft); }
3042
+ .ai-semantic-result > label { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: start; gap: 7px; min-width: 0; cursor: pointer; }
3043
+ .ai-semantic-result-copy { display: grid; min-width: 0; gap: 4px; }
3044
+ .ai-semantic-result-copy strong { font-size: 10px; line-height: 1.4; }
3045
+ .ai-semantic-result-copy > small { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; color: var(--muted); font-size: 8px; }
3046
+ .ai-semantic-result-copy > span { display: -webkit-box; overflow: hidden; color: var(--ink); font-size: 9px; line-height: 1.55; overflow-wrap: anywhere; -webkit-box-orient: vertical; -webkit-line-clamp: 4; }
3047
+ .ai-semantic-result > button { min-height: 25px; padding: 4px 7px; font-size: 8px; }
3048
+ .ai-semantic-view-only { padding: 2px 5px; border-radius: 3px; background: var(--paper-deep); color: var(--muted); font-size: 8px; white-space: nowrap; }
3049
+ .ai-semantic-empty { margin: 0; padding: 14px; color: var(--muted); font-size: 9px; text-align: center; }
3050
+ .ai-semantic-search-panel > footer { position: relative; z-index: 1; min-width: 0; border-top: 1px solid var(--line); border-bottom: 0; background: var(--surface); }
3051
+ .ai-semantic-injection { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; padding: 7px 8px; border: 1px solid color-mix(in srgb, var(--accent) 40%, var(--line)); border-radius: 5px; background: color-mix(in srgb, var(--accent) 6%, var(--surface)); }
3052
+ .ai-semantic-injection > div { display: grid; min-width: 0; gap: 2px; }
3053
+ .ai-semantic-injection strong { color: var(--accent-dark); font-size: 9px; }
3054
+ .ai-semantic-injection span, .ai-semantic-injection small { overflow: hidden; color: var(--muted); font-size: 8px; text-overflow: ellipsis; white-space: nowrap; }
3055
+ .ai-semantic-injection button { width: 23px; min-width: 23px; height: 23px; padding: 0; }
3056
+ @container (max-width: 460px) {
3057
+ .ai-semantic-search-panel { height: 40vh; max-height: 40vh; }
3058
+ .ai-semantic-search-form { grid-template-columns: minmax(0, 1fr) minmax(112px, .48fr); }
3059
+ .ai-semantic-search-form label:first-child { grid-column: 1 / -1; }
3060
+ .ai-semantic-search-form button { grid-column: 2; align-self: end; }
3061
+ .ai-semantic-result { grid-template-columns: minmax(0, 1fr); }
3062
+ .ai-semantic-result > button { justify-self: end; }
3063
+ }
2984
3064
  .ai-context-warning { display: grid; gap: 9px; margin-bottom: 9px; padding: 10px; border: 1px solid color-mix(in srgb, #bf6a35 58%, var(--line)); border-radius: 5px; background: color-mix(in srgb, #bf6a35 10%, var(--surface)); }
2985
3065
  .ai-context-warning.hidden { display: none; }
2986
3066
  .ai-context-warning strong { display: block; color: var(--ink); font-size: 11px; }
@@ -3298,6 +3378,16 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
3298
3378
  .chapter-annotations-dialog { width: min(820px, 94vw); }
3299
3379
  .chapter-annotations-list { display: grid; gap: 10px; max-height: 62vh; overflow: auto; padding: 18px 24px; }
3300
3380
  .chapter-comment-module-list { display: grid; gap: 10px; }
3381
+ .chapter-comment-completed-group { overflow: hidden; border: 1px solid var(--line); border-radius: 6px; background: var(--surface-soft); }
3382
+ .chapter-comment-completed-group > summary { display: flex; min-height: 44px; align-items: center; gap: 9px; padding: 9px 13px; color: var(--muted); cursor: pointer; list-style: none; }
3383
+ .chapter-comment-completed-group > summary::-webkit-details-marker { display: none; }
3384
+ .chapter-comment-completed-group > summary::before { content: "›"; color: var(--accent-dark); font-family: var(--font-latin), monospace; font-size: 16px; line-height: 1; transition: transform .15s ease; }
3385
+ .chapter-comment-completed-group[open] > summary::before { transform: rotate(90deg); }
3386
+ .chapter-comment-completed-group > summary span { color: var(--ink); font-size: 11px; font-weight: 600; }
3387
+ .chapter-comment-completed-group > summary strong { display: inline-grid; min-width: 22px; height: 22px; padding: 0 6px; place-items: center; border: 1px solid var(--line); border-radius: 11px; color: var(--accent-dark); font-family: var(--font-latin), monospace; font-size: 9px; }
3388
+ .chapter-comment-completed-group > summary small { margin-left: auto; font-size: 9px; }
3389
+ .chapter-comment-completed-group[open] > summary { border-bottom: 1px solid var(--line); }
3390
+ .chapter-comment-completed-list { display: grid; gap: 10px; padding: 10px; }
3301
3391
  .chapter-annotation-card { display: grid; gap: 8px; padding: 13px; border: 1px solid var(--line); border-radius: 6px; background: var(--surface-soft); }
3302
3392
  .chapter-annotation-card.is-resolved { opacity: .65; }
3303
3393
  .chapter-annotation-card header { display: flex; align-items: center; gap: 8px; }
@@ -3399,7 +3489,8 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
3399
3489
  .provider-token-quota-toggle { color: var(--ink) !important; font-size: 10px !important; }
3400
3490
  .provider-token-quota-input { display: grid; gap: 5px; min-width: 0; }
3401
3491
  .provider-token-quota-input input:disabled { opacity: .58; }
3402
- .model-multimodal-fields { gap: 9px; padding: 12px; border: 1px solid var(--line); border-radius: 6px; background: var(--surface-soft); }
3492
+ .model-multimodal-fields, .model-kind-fields { gap: 9px; padding: 12px; border: 1px solid var(--line); border-radius: 6px; background: var(--surface-soft); }
3493
+ .model-kind-fields .model-capability-option { display: grid !important; grid-template-columns: 16px minmax(0, 1fr); align-items: start; gap: 9px; margin: 0; padding: 10px; border: 1px solid var(--line); border-radius: 5px; background: var(--surface); color: var(--ink) !important; }
3403
3494
  .model-multimodal-heading { color: var(--ink); font-size: 12px; font-weight: 600; }
3404
3495
  .model-multimodal-fields .model-capability-option { display: grid !important; grid-template-columns: 16px minmax(0, 1fr); align-items: start; gap: 9px; margin: 0; padding: 10px; border: 1px solid var(--line); border-radius: 5px; background: var(--surface); color: var(--ink) !important; transition: border-color .15s ease, background-color .15s ease; }
3405
3496
  .model-multimodal-fields .model-capability-option[hidden], .model-multimodal-fields .model-capability-option.hidden { display: none !important; }
@@ -3545,11 +3636,13 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
3545
3636
  .item-list-row button { padding: 0 10px; }
3546
3637
  .item-list-add { justify-self: start; padding: 7px 11px; }
3547
3638
  .keyword-chip-field > small { color: var(--muted); font-size: 10px; line-height: 1.5; }
3548
- .keyword-chip-editor { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-height: 42px; padding: 6px 8px; border: 1px solid var(--line); border-radius: 4px; background: var(--surface); }
3639
+ .keyword-chip-field { min-width: 0; }
3640
+ .keyword-chip-editor { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; width: 100%; min-width: 0; max-width: 100%; box-sizing: border-box; min-height: 42px; padding: 6px 8px; overflow-x: hidden; border: 1px solid var(--line); border-radius: 4px; background: var(--surface); }
3549
3641
  .keyword-chip-editor:focus-within { border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 14%, transparent); }
3550
- .keyword-chip-editor > input[data-keyword-input] { flex: 1 1 160px; width: auto; min-width: 140px; padding: 6px 3px; border: 0; background: transparent; color: var(--ink); outline: none; }
3642
+ .keyword-chip-editor > input[data-keyword-input] { flex: 1 1 160px; width: auto; min-width: min(140px, 100%); max-width: 100%; box-sizing: border-box; padding: 6px 3px; border: 0; background: transparent; color: var(--ink); outline: none; }
3551
3643
  .keyword-chip-editor > input[data-keyword-input]:focus { border: 0; box-shadow: none; }
3552
- .keyword-chip { display: inline-flex; align-items: center; gap: 5px; min-height: 28px; padding: 3px 5px 3px 10px; border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--line)); border-radius: 16px; background: var(--paper-deep); color: var(--ink); font-size: 11px; line-height: 1.3; }
3644
+ .keyword-chip { display: inline-flex; align-items: center; gap: 5px; min-width: 0; max-width: 100%; box-sizing: border-box; min-height: 28px; padding: 3px 5px 3px 10px; overflow-wrap: anywhere; border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--line)); border-radius: 16px; background: var(--paper-deep); color: var(--ink); font-size: 11px; line-height: 1.3; }
3645
+ .keyword-chip > span { min-width: 0; overflow-wrap: anywhere; }
3553
3646
  .keyword-chip button { display: inline-grid; place-items: center; width: 20px; height: 20px; padding: 0; border: 0; border-radius: 50%; background: transparent; color: var(--muted); font-size: 15px; line-height: 1; opacity: 0; pointer-events: none; transition: opacity .15s ease; }
3554
3647
  .keyword-chip:hover button, .keyword-chip:focus-within button { opacity: 1; pointer-events: auto; }
3555
3648
  .keyword-chip button:hover, .keyword-chip button:focus-visible { background: color-mix(in srgb, var(--accent) 14%, transparent); color: var(--accent-dark); outline: none; }
@@ -3660,6 +3753,7 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
3660
3753
  .character-filter-toolbar-actions { justify-content: flex-start; }
3661
3754
  .draft-filter-toolbar { grid-template-columns: minmax(0, 1fr); }
3662
3755
  .setting-filter-toolbar { grid-template-columns: minmax(0, 1fr); }
3756
+ .chapter-comment-filter-toolbar { grid-template-columns: minmax(0, 1fr); }
3663
3757
  }
3664
3758
  .entity-editor-open { overflow: hidden; }
3665
3759
  .preview-record-card { cursor: pointer; }
@@ -3758,9 +3852,13 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
3758
3852
  .knowledge-markdown-block .message-body { overflow-wrap: anywhere; font-size: 12px; line-height: 1.65; }
3759
3853
  .character-editor-header > div:nth-child(2) { min-width: 0; text-align: center; }
3760
3854
  .character-editor-header h1, .character-editor-header h3 { margin: 0; }
3761
- .character-editor-title-row { display: flex; align-items: center; gap: 10px; margin-top: 3px; }
3762
- .character-editor-title-row { justify-content: center; }
3855
+ .character-editor-title-row { display: flex; align-items: center; justify-content: center; min-width: 0; gap: 10px; margin-top: 3px; }
3763
3856
  .character-editor-title-row h1 { overflow: hidden; font-size: 24px; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
3857
+ .character-editor-title-input { flex: 0 1 520px; width: min(100%, 520px); min-width: 0; padding: 0 0 4px; border: 0; border-bottom: 1px solid transparent; border-radius: 0; background: transparent; color: var(--ink); font-size: 24px; font-weight: 600; line-height: 1.2; text-align: center; }
3858
+ .character-editor-title-input::placeholder { color: var(--muted); opacity: 1; }
3859
+ .character-editor-title-input:focus { border-color: var(--accent); box-shadow: none; }
3860
+ .character-editor-title-input[readonly] { cursor: default; }
3861
+ .character-editor-title-input[readonly]:focus { border-color: transparent; }
3764
3862
  .knowledge-editor-header-note { color: var(--muted); font-size: 10px; text-align: right; }
3765
3863
  .character-version-badge { display: inline-flex; align-items: center; min-height: 22px; padding: 2px 8px; border: 1px solid var(--line); border-radius: 12px; background: var(--paper-deep); color: var(--accent-dark); font: 10px/1 var(--font-latin), monospace; }
3766
3864
  .character-editor-header-actions { display: flex; align-items: center; justify-content: flex-end; gap: 8px; }
@@ -3785,9 +3883,10 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
3785
3883
  .character-editor-section.has-header-actions > header .roleplay-memory-toolbar { flex: 0 0 auto; }
3786
3884
  .character-editor-section-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 17px 20px; }
3787
3885
  .character-editor-section-fields > label, .character-editor-section-fields > .form-field { display: grid; align-content: start; gap: 7px; color: var(--muted); font-size: 11px; }
3788
- .character-editor-section-fields > label:has(textarea), .character-editor-section-fields > .form-field:has(textarea), .character-editor-section-fields > .structured-list-field, .character-editor-section-fields > .chip-field, .character-editor-section-fields > .markdown-editor-field, .character-editor-field-help { grid-column: 1 / -1; }
3886
+ .character-editor-section-fields > label:has(textarea), .character-editor-section-fields > .form-field:has(textarea), .character-editor-section-fields > .keyword-chip-field, .character-editor-section-fields > .structured-list-field, .character-editor-section-fields > .chip-field, .character-editor-section-fields > .markdown-editor-field, .character-editor-field-help { grid-column: 1 / -1; }
3789
3887
  .character-editor-section-fields input, .character-editor-section-fields textarea, .character-editor-section-fields select { width: 100%; padding: 10px 11px; border: 1px solid var(--line); border-radius: 4px; background: var(--surface); font-size: 13px; }
3790
3888
  .character-editor-section-fields textarea { min-height: 120px; resize: vertical; line-height: 1.65; }
3889
+ .character-editor-section-fields .key-value-list-value { min-height: 42px; max-height: 240px; overflow-y: auto; resize: none; field-sizing: content; overflow-wrap: anywhere; }
3791
3890
  .character-editor-section-fields .section-list-row textarea { min-height: 180px; }
3792
3891
  .character-editor-section-fields .member-chip { position: relative; display: inline-flex; width: auto; cursor: pointer; }
3793
3892
  .character-editor-section-fields .member-chip input[type="checkbox"] { position: absolute; width: 1px !important; min-width: 1px; height: 1px; padding: 0; border: 0; opacity: 0; }
@@ -4024,7 +4123,7 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
4024
4123
  .setting-row, .module-row { grid-template-columns: minmax(0, 1fr); gap: 6px; }
4025
4124
  .setting-row .card-actions, .module-row .card-actions { justify-content: flex-start; }
4026
4125
  .entity-editor-header, .character-editor-header { grid-template-columns: auto minmax(0, 1fr) auto; gap: 10px; padding-inline: 12px; }
4027
- .entity-editor-heading h1, .character-editor-title-row h1 { font-size: 18px; }
4126
+ .entity-editor-heading h1, .character-editor-title-row h1, .character-editor-title-input { font-size: 18px; }
4028
4127
  .entity-editor-back { overflow: hidden; width: 40px; min-width: 40px; padding-inline: 11px; white-space: nowrap; }
4029
4128
  .entity-editor-back::before { margin-right: 18px; }
4030
4129
  .setting-editor-header { min-height: 102px; }