@musnows/scriverse 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/public/im.js CHANGED
@@ -134,10 +134,14 @@ export function mergeImMessagePages(previousMessages, ...nextPages) {
134
134
  }
135
135
 
136
136
  export function mergeImFailedReplyPages(...pages) {
137
+ return mergeImTriggeredTurnPages(...pages);
138
+ }
139
+
140
+ export function mergeImTriggeredTurnPages(...pages) {
137
141
  const byId = new Map();
138
142
  for (const reply of pages.flatMap(array)) byId.set(String(reply?.id || ""), reply);
139
143
  byId.delete("");
140
- return [...byId.values()].sort((left, right) => Number(left.triggerSequence) - Number(right.triggerSequence)
144
+ return [...byId.values()].sort((left, right) => Number(left.triggerSequence ?? left.sourceSequence) - Number(right.triggerSequence ?? right.sourceSequence)
141
145
  || String(left.createdAt || "").localeCompare(String(right.createdAt || ""))
142
146
  || String(left.id || "").localeCompare(String(right.id || "")));
143
147
  }
@@ -220,6 +224,7 @@ export function createImWorkspace({ api, esc, renderMarkdown, toast, confirmToas
220
224
  let settings = null;
221
225
  let eventSource = null;
222
226
  const provisionalReplies = new Map();
227
+ const provisionalJudges = new Map();
223
228
  const conversationDrafts = new Map();
224
229
  const groupSettingsDrafts = new Map();
225
230
  let mentionOptions = [];
@@ -561,6 +566,52 @@ export function createImWorkspace({ api, esc, renderMarkdown, toast, confirmToas
561
566
  }
562
567
  }
563
568
 
569
+ function upsertProvisionalJudge(payload) {
570
+ const turnId = String(payload?.turnId || payload?.id || "");
571
+ if (!turnId) return null;
572
+ const previous = provisionalJudges.get(turnId) || {};
573
+ const eventCharacter = value(payload, "character", {});
574
+ const characterId = String(payload?.characterId || eventCharacter.characterId || previous.characterId || "");
575
+ const character = activeCharacters().find((item) => item.characterId === characterId);
576
+ const eventError = value(payload, "error", {});
577
+ const next = {
578
+ ...previous,
579
+ turnId,
580
+ chainId: String(payload?.chainId || previous.chainId || ""),
581
+ sourceMessageId: String(payload?.sourceMessageId || previous.sourceMessageId || ""),
582
+ characterId,
583
+ name: eventCharacter.name || character?.name || previous.name || "角色",
584
+ avatarUrl: eventCharacter.avatarUrl || character?.avatarUrl || previous.avatarUrl || null,
585
+ status: String(payload?.status || previous.status || "pending"),
586
+ selected: payload?.selected === true,
587
+ error: eventError.message || payload?.failure || previous.error || ""
588
+ };
589
+ provisionalJudges.set(turnId, next);
590
+ return next;
591
+ }
592
+
593
+ function syncProvisionalJudges() {
594
+ const previous = new Map(provisionalJudges);
595
+ provisionalJudges.clear();
596
+ for (const turn of array(current?.judgeOutcomes)) {
597
+ const retained = previous.get(String(turn.id));
598
+ const next = upsertProvisionalJudge({ ...retained, ...turn, turnId: turn.id });
599
+ if (next && retained?.error && !next.error) next.error = retained.error;
600
+ }
601
+ for (const turn of array(current?.activeChain?.judges)) {
602
+ if (turn.selected === true) continue;
603
+ const retained = previous.get(String(turn.id));
604
+ const next = upsertProvisionalJudge({ ...retained, ...turn, turnId: turn.id });
605
+ if (next && retained?.error && !next.error) next.error = retained.error;
606
+ }
607
+ }
608
+
609
+ function clearPendingProvisionalJudges() {
610
+ for (const [turnId, judge] of provisionalJudges) {
611
+ if (["pending", "running"].includes(String(judge.status))) provisionalJudges.delete(turnId);
612
+ }
613
+ }
614
+
564
615
  function provisionalReplyBodyHtml(reply) {
565
616
  const failed = ["failed", "skipped"].includes(reply.status);
566
617
  const pendingCopy = reply.status === "pending" ? "等待角色开始回答…" : "正在组织回答…";
@@ -569,10 +620,27 @@ export function createImWorkspace({ api, esc, renderMarkdown, toast, confirmToas
569
620
  return `${content}${failure}`;
570
621
  }
571
622
 
623
+ function provisionalJudgeStatusLabel(judge) {
624
+ if (judge.status === "pending") return "等待判断";
625
+ if (judge.status === "running") return "模型判断中";
626
+ if (judge.status === "completed") return "无需回答";
627
+ if (judge.status === "cancelled") return "判断已取消";
628
+ return "判断失败";
629
+ }
630
+
631
+ function provisionalJudgeBodyHtml(judge) {
632
+ if (["failed", "cancelled"].includes(judge.status)) {
633
+ return `<p class="im-provisional-error">${esc(judge.error || "模型判断失败")}</p>`;
634
+ }
635
+ if (judge.status === "completed") return '<p class="im-provisional-placeholder">模型判断当前无需回答</p>';
636
+ return '<p class="im-provisional-placeholder">模型正在判断是否回答…</p>';
637
+ }
638
+
572
639
  function syncGeneratingSummary() {
573
640
  const count = [...provisionalReplies.values()].filter((reply) => ["pending", "running"].includes(reply.status)).length;
574
641
  const summary = feed.querySelector(".im-generating-summary");
575
- if (summary && count > 0) summary.textContent = `${count} 个角色正在生成回答`;
642
+ const label = count ? `${count} 个角色正在生成回答` : "";
643
+ if (summary && label) summary.textContent = label;
576
644
  else if (summary) summary.remove();
577
645
  return count;
578
646
  }
@@ -595,6 +663,11 @@ export function createImWorkspace({ api, esc, renderMarkdown, toast, confirmToas
595
663
  if (follow) feed.scrollTop = feed.scrollHeight;
596
664
  }
597
665
 
666
+ function updateProvisionalJudgeElement(judge) {
667
+ const follow = feed.scrollHeight - feed.scrollTop - feed.clientHeight < 80;
668
+ renderMessages({ scrollToBottom: follow });
669
+ }
670
+
598
671
  function commitRealtimeMessage(message) {
599
672
  if (!message?.id) return;
600
673
  current.messages = mergeImMessagePages(current.messages, [message]);
@@ -609,7 +682,9 @@ export function createImWorkspace({ api, esc, renderMarkdown, toast, confirmToas
609
682
  const previousTop = feed.scrollTop;
610
683
  const messages = array(current?.messages);
611
684
  const provisional = [...provisionalReplies.values()];
685
+ const provisionalJudgeList = [...provisionalJudges.values()];
612
686
  const failedRepliesByMessage = new Map();
687
+ const judgesByMessage = new Map();
613
688
  for (const reply of array(current?.failedReplies)) {
614
689
  const triggerMessageId = String(reply.triggerMessageId || "");
615
690
  if (!triggerMessageId) continue;
@@ -617,7 +692,14 @@ export function createImWorkspace({ api, esc, renderMarkdown, toast, confirmToas
617
692
  replies.push(reply);
618
693
  failedRepliesByMessage.set(triggerMessageId, replies);
619
694
  }
620
- if (!messages.length && !provisional.length && failedRepliesByMessage.size === 0) {
695
+ for (const judge of provisionalJudgeList) {
696
+ const sourceMessageId = String(judge.sourceMessageId || "");
697
+ if (!sourceMessageId) continue;
698
+ const judges = judgesByMessage.get(sourceMessageId) ?? [];
699
+ judges.push(judge);
700
+ judgesByMessage.set(sourceMessageId, judges);
701
+ }
702
+ if (!messages.length && !provisional.length && !provisionalJudgeList.length && failedRepliesByMessage.size === 0) {
621
703
  feed.innerHTML = '<p class="im-feed-empty">从一条消息开始。角色单聊会直接回复;群聊按当前回复模式调度 AI。</p>';
622
704
  return;
623
705
  }
@@ -628,6 +710,14 @@ export function createImWorkspace({ api, esc, renderMarkdown, toast, confirmToas
628
710
  const generatingSummary = generatingCount
629
711
  ? `<div class="im-generating-summary" role="status">${generatingCount} 个角色正在生成回答</div>`
630
712
  : "";
713
+ const provisionalJudgeHtml = (judge) => {
714
+ const failed = ['failed', 'cancelled'].includes(judge.status);
715
+ const quiet = judge.status === "completed";
716
+ return `<article class="im-message is-character is-provisional is-judge${failed ? " is-failed" : ""}${quiet ? " is-quiet" : ""}" data-im-provisional-judge="${esc(judge.turnId)}" data-im-provisional-judge-status="${esc(judge.status)}">
717
+ <header>${imAvatarHtml(judge, "character", "im-message-avatar")}<strong>${esc(judge.name || "角色")}</strong><span class="im-provisional-status">${provisionalJudgeStatusLabel(judge)}</span></header>
718
+ <div class="im-message-body message-body">${provisionalJudgeBodyHtml(judge)}</div>
719
+ </article>`;
720
+ };
631
721
  const provisionalHtml = provisional.map((reply) => {
632
722
  const failed = ['failed', 'skipped'].includes(reply.status);
633
723
  const statusLabel = reply.status === "pending" ? "等待生成" : reply.status === "running" ? "正在生成" : reply.status === "skipped" ? "未生成" : "生成失败";
@@ -645,6 +735,12 @@ export function createImWorkspace({ api, esc, renderMarkdown, toast, confirmToas
645
735
  const avatar = announcement || message.senderKind === "system"
646
736
  ? ""
647
737
  : imAvatarHtml(sender, message.senderKind === "character" ? "character" : "user", "im-message-avatar");
738
+ const judges = array(judgesByMessage.get(String(message.id)));
739
+ const judgingCount = judges.filter((judge) => ['pending', 'running'].includes(judge.status)).length;
740
+ const judgeSummary = judgingCount
741
+ ? `<div class="im-generating-summary" role="status">${judgingCount} 个角色正在判断是否回答</div>`
742
+ : "";
743
+ const judgeResults = judges.map(provisionalJudgeHtml).join("");
648
744
  const failedReplies = array(failedRepliesByMessage.get(String(message.id))).map((reply) => {
649
745
  const character = value(reply, "character", {});
650
746
  return `<article class="im-message is-character is-provisional is-failed" data-im-failed-turn="${esc(reply.id)}">
@@ -656,7 +752,7 @@ export function createImWorkspace({ api, esc, renderMarkdown, toast, confirmToas
656
752
  <header>${avatar}<strong>${esc(label)}</strong><time>${esc(new Date(message.createdAt).toLocaleString("zh-CN", { month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" }))}</time></header>
657
753
  <div class="im-message-body message-body">${messageHtml(message)}</div>
658
754
  ${message.senderKind === "character" ? `<details class="im-model-details"><summary>调用详情</summary><span>${esc(model.modelDisplayName || model.modelId || "未知模型")} · ${model.modelStage === "fallback" ? "fallback" : "主模型"} · ${Number(model.attemptCount || 1)} 次请求 · ${Number(model.durationMs || 0)} ms</span></details>` : ""}
659
- </article>${failedReplies}`;
755
+ </article>${judgeSummary}${judgeResults}${failedReplies}`;
660
756
  }).join("") + generatingSummary + provisionalHtml;
661
757
  bindImAvatarFallbacks(feed);
662
758
  feed.scrollTop = follow ? feed.scrollHeight : previousTop;
@@ -679,6 +775,7 @@ export function createImWorkspace({ api, esc, renderMarkdown, toast, confirmToas
679
775
  ].map((message) => [message.id, message]));
680
776
  current.messages = [...messagesById.values()].sort((left, right) => Number(left.sequence) - Number(right.sequence));
681
777
  current.failedReplies = mergeImFailedReplyPages(page.failedReplies, current.failedReplies);
778
+ current.judgeOutcomes = mergeImTriggeredTurnPages(page.judgeOutcomes, current.judgeOutcomes);
682
779
  current.hasMoreMessages = page.hasMoreMessages === true;
683
780
  renderMessages();
684
781
  feed.scrollTop = previousTop + Math.max(0, feed.scrollHeight - previousHeight);
@@ -989,17 +1086,20 @@ export function createImWorkspace({ api, esc, renderMarkdown, toast, confirmToas
989
1086
  const conversationChanged = !previousConversation;
990
1087
  if (previousConversation) {
991
1088
  const gapFailedReplies = [];
1089
+ const gapJudgeOutcomes = [];
992
1090
  const gapMessages = await collectImMessageGap(previousConversation.messages, nextConversation.messages, async (cursor) => {
993
1091
  const page = await api(`/api/im/conversations/${encodeURIComponent(conversationId)}?afterSequence=${encodeURIComponent(cursor)}`);
994
1092
  if (request !== conversationRequest || (requestedConversationId && requestedConversationId !== conversationId)) {
995
1093
  throw new Error("IM 会话请求已失效");
996
1094
  }
997
1095
  gapFailedReplies.push(...array(page.failedReplies));
1096
+ gapJudgeOutcomes.push(...array(page.judgeOutcomes));
998
1097
  return page;
999
1098
  });
1000
1099
  if (request !== conversationRequest || (requestedConversationId && requestedConversationId !== conversationId)) return;
1001
1100
  nextConversation.messages = mergeImMessagePages(previousConversation.messages, gapMessages, nextConversation.messages);
1002
1101
  nextConversation.failedReplies = mergeImFailedReplyPages(previousConversation.failedReplies, gapFailedReplies, nextConversation.failedReplies);
1102
+ nextConversation.judgeOutcomes = mergeImTriggeredTurnPages(previousConversation.judgeOutcomes, gapJudgeOutcomes, nextConversation.judgeOutcomes);
1003
1103
  nextConversation.hasMoreMessages = previousConversation.hasMoreMessages === true;
1004
1104
  }
1005
1105
  if (current?.id && current.id !== conversationId) {
@@ -1015,6 +1115,7 @@ export function createImWorkspace({ api, esc, renderMarkdown, toast, confirmToas
1015
1115
  if (requestedConversationId === conversationId) requestedConversationId = null;
1016
1116
  workspace.classList.add("has-conversation");
1017
1117
  syncProvisionalReplies();
1118
+ syncProvisionalJudges();
1018
1119
  const shouldRestoreDetailsFocus = detailsFocus && document.activeElement?.id === detailsFocus.id;
1019
1120
  renderConversationList();
1020
1121
  renderConversation(conversationChanged);
@@ -1427,6 +1528,7 @@ export function createImWorkspace({ api, esc, renderMarkdown, toast, confirmToas
1427
1528
  conversationDrafts.delete(conversationId);
1428
1529
  closeMentionMenu();
1429
1530
  provisionalReplies.clear();
1531
+ clearPendingProvisionalJudges();
1430
1532
  let committed = false;
1431
1533
  try {
1432
1534
  const result = await api(`/api/im/conversations/${encodeURIComponent(conversationId)}/messages`, {
@@ -1473,7 +1575,11 @@ export function createImWorkspace({ api, esc, renderMarkdown, toast, confirmToas
1473
1575
  return;
1474
1576
  }
1475
1577
  if (envelope.type === "message" && current?.id === eventConversationId && envelope.payload.message) {
1476
- if (Object.prototype.hasOwnProperty.call(envelope.payload, "chain")) current.activeChain = envelope.payload.chain ?? null;
1578
+ if (Object.prototype.hasOwnProperty.call(envelope.payload, "chain")) {
1579
+ const nextChain = envelope.payload.chain ?? null;
1580
+ if (String(current.activeChain?.id || "") !== String(nextChain?.id || "")) clearPendingProvisionalJudges();
1581
+ current.activeChain = nextChain;
1582
+ }
1477
1583
  commitRealtimeMessage(envelope.payload.message);
1478
1584
  }
1479
1585
  if (envelope.type === "turn" && current?.id === eventConversationId && envelope.payload.kind === "reply") {
@@ -1490,6 +1596,18 @@ export function createImWorkspace({ api, esc, renderMarkdown, toast, confirmToas
1490
1596
  }
1491
1597
  return;
1492
1598
  }
1599
+ if (envelope.type === "turn" && current?.id === eventConversationId && envelope.payload.kind === "judge") {
1600
+ if (!isImRealtimeChainCurrent(current.activeChain, envelope.payload)) return;
1601
+ const turnId = String(envelope.payload.turnId || "");
1602
+ if (envelope.payload.selected === true) {
1603
+ provisionalJudges.delete(turnId);
1604
+ renderMessages();
1605
+ } else {
1606
+ const provisional = upsertProvisionalJudge(envelope.payload);
1607
+ if (provisional) updateProvisionalJudgeElement(provisional);
1608
+ }
1609
+ return;
1610
+ }
1493
1611
  if (envelope.type === "delta" && current?.id === eventConversationId) {
1494
1612
  if (!isImRealtimeChainCurrent(current.activeChain, envelope.payload)) return;
1495
1613
  const provisional = upsertProvisionalReply({ ...envelope.payload, status: "running" });
@@ -1570,6 +1688,7 @@ export function createImWorkspace({ api, esc, renderMarkdown, toast, confirmToas
1570
1688
  resetDetailsDrawer();
1571
1689
  document.querySelector("#app").classList.remove("im-mode");
1572
1690
  provisionalReplies.clear();
1691
+ provisionalJudges.clear();
1573
1692
  closeMentionMenu();
1574
1693
  }
1575
1694
 
@@ -1715,6 +1834,7 @@ export function createImWorkspace({ api, esc, renderMarkdown, toast, confirmToas
1715
1834
  const result = await performMutation(event.currentTarget, () => api(`/api/im/conversations/${encodeURIComponent(conversationId)}/stop`, { method: "POST", body: {} }));
1716
1835
  if (!result.ok) return;
1717
1836
  provisionalReplies.clear();
1837
+ provisionalJudges.clear();
1718
1838
  if (current?.id === conversationId) await refreshAfterMutation("停止 AI", () => openConversation(conversationId));
1719
1839
  });
1720
1840
  document.querySelector("#im-retry").addEventListener("click", async (event) => {
@@ -1744,6 +1864,7 @@ export function createImWorkspace({ api, esc, renderMarkdown, toast, confirmToas
1744
1864
  workspace.classList.remove("has-conversation");
1745
1865
  resetDetailsDrawer();
1746
1866
  provisionalReplies.clear();
1867
+ provisionalJudges.clear();
1747
1868
  renderConversationList();
1748
1869
  renderConversation();
1749
1870
  const previousConversationButton = [...listHost.querySelectorAll("[data-im-conversation]")]
@@ -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=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=work-editor-preference-checkbox-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=ai-question-batch-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&feature=ai-settings-textarea-font-v1&feature=ai-usage-stat-display-v1&feature=ai-usage-year-v1&feature=ai-skill-slash-menu-v1&feature=ai-message-citation-popover-v1&feature=line-citation-menu-separator-v1&feature=global-im-v103&feature=im-sidebar-compact-v1&feature=im-narration-contrast-v1&feature=im-member-add-plus-v2&feature=im-button-hierarchy-v1&feature=im-icon-button-size-v1&feature=compact-sidebar-directory-v4">
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=work-editor-preference-checkbox-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=ai-question-batch-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&feature=ai-settings-textarea-font-v1&feature=ai-usage-stat-display-v1&feature=ai-usage-year-v1&feature=ai-skill-slash-menu-v1&feature=ai-message-citation-popover-v1&feature=line-citation-menu-separator-v1&feature=global-im-v106&feature=im-sidebar-compact-v1&feature=im-narration-contrast-v1&feature=im-member-add-plus-v2&feature=im-button-hierarchy-v1&feature=im-icon-button-size-v1&feature=compact-sidebar-directory-v4">
13
13
  </head>
14
14
  <body class="auth-pending">
15
15
  <section id="auth-view" class="auth-view hidden" aria-labelledby="auth-title">
@@ -1425,6 +1425,6 @@
1425
1425
  </dialog>
1426
1426
 
1427
1427
  <div id="auth-loading" class="auth-loading" role="status" aria-label="正在载入工作台"></div>
1428
- <script type="module" src="/app.js?v=20260816-extended-thinking-effort-v1&feature=ai-history-rename-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-v2&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-tool-summary-v1&feature=ai-question-submit-guidance-v1&feature=ai-question-batch-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&feature=ai-usage-stat-display-v1&feature=ai-usage-year-v1&feature=semantic-search-rag-label-v1&feature=ai-skill-slash-menu-v1&feature=ai-roleplay-scene-bubble-v1&feature=ai-roleplay-scene-collapse-v1&feature=markdown-adjacent-blockquotes-v1&feature=chapter-save-shortcut-v2&feature=ai-message-citation-popover-v1&feature=line-citation-menu-separator-v1&feature=global-im-v103&feature=im-sidebar-compact-v1&feature=im-settings-gear-v1&feature=compact-sidebar-directory-v2"></script>
1428
+ <script type="module" src="/app.js?v=20260816-extended-thinking-effort-v1&feature=ai-history-rename-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-v2&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-tool-summary-v1&feature=ai-question-submit-guidance-v1&feature=ai-question-batch-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&feature=ai-usage-stat-display-v1&feature=ai-usage-year-v1&feature=semantic-search-rag-label-v1&feature=ai-skill-slash-menu-v1&feature=ai-roleplay-scene-bubble-v1&feature=ai-roleplay-scene-collapse-v1&feature=markdown-adjacent-blockquotes-v1&feature=chapter-save-shortcut-v2&feature=ai-message-citation-popover-v1&feature=line-citation-menu-separator-v1&feature=global-im-v106&feature=im-sidebar-compact-v1&feature=im-settings-gear-v1&feature=compact-sidebar-directory-v2"></script>
1429
1429
  </body>
1430
1430
  </html>
@@ -4800,6 +4800,8 @@ body.is-im-conversations-resizing { cursor: ew-resize; user-select: none; }
4800
4800
  .im-generating-summary { width: min(78%, 720px); margin: 2px auto 9px 0; color: var(--muted); font-size: 9px; line-height: 1.4; }
4801
4801
  .im-message.is-provisional { opacity: .82; }
4802
4802
  .im-message.is-provisional.is-failed { opacity: 1; }
4803
+ .im-message.is-provisional.is-judge .im-message-body { border-style: dashed; background: color-mix(in srgb, var(--panel) 88%, var(--paper-deep)); }
4804
+ .im-message.is-provisional.is-judge.is-quiet { opacity: .72; }
4803
4805
  .im-provisional-status { color: var(--muted); font-size: 8px; }
4804
4806
  .im-provisional-placeholder { margin: 0; color: var(--muted); }
4805
4807
  .im-provisional-error { margin: 0; color: color-mix(in srgb, #c44949 82%, var(--ink)); font-weight: 600; }
package/dist/version.js CHANGED
@@ -1,4 +1,4 @@
1
- export const APP_VERSION = "1.0.0";
1
+ export const APP_VERSION = "1.0.1";
2
2
  export const SCRIVERSE_BETA_COMMIT_ENV = "SCRIVERSE_BETA_COMMIT";
3
3
  export function resolveBetaVersionLabel(environment) {
4
4
  const commit = environment[SCRIVERSE_BETA_COMMIT_ENV]?.trim().toLocaleLowerCase() ?? "";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@musnows/scriverse",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Command-line client and local server for the Scriverse long-form fiction workspace",
5
5
  "license": "AGPL-3.0-only",
6
6
  "author": "musnows",