@musnows/scriverse 0.8.3 → 0.8.4
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/app.js +22 -16
- package/dist/public/index.html +1 -1
- package/dist/store.js +17 -16
- package/dist/store.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/public/app.js
CHANGED
|
@@ -3255,6 +3255,10 @@ function renderAiRoleplayUserCharacterSelect() {
|
|
|
3255
3255
|
|
|
3256
3256
|
const aiConversationOptionLockedMessage = "会话选项在会话开始后不支持修改,若需要修改,请新建会话";
|
|
3257
3257
|
|
|
3258
|
+
function aiConversationModelLocked() {
|
|
3259
|
+
return typeof state.aiConversationModelId === "string" && state.aiConversationModelId.trim().length > 0;
|
|
3260
|
+
}
|
|
3261
|
+
|
|
3258
3262
|
function selectedAiModelLabel() {
|
|
3259
3263
|
return $("#ai-model").selectedOptions[0]?.textContent?.trim() || "尚未选择模型";
|
|
3260
3264
|
}
|
|
@@ -3263,20 +3267,21 @@ function syncAiModelPicker() {
|
|
|
3263
3267
|
const select = $("#ai-model");
|
|
3264
3268
|
const button = $("#ai-model-picker");
|
|
3265
3269
|
const interactionBusy = aiInteractionBusy();
|
|
3270
|
+
const modelLocked = aiConversationModelLocked();
|
|
3266
3271
|
const selectedLabel = selectedAiModelLabel();
|
|
3267
|
-
const label =
|
|
3272
|
+
const label = modelLocked
|
|
3268
3273
|
? `当前模型:${selectedLabel}。${aiConversationOptionLockedMessage}`
|
|
3269
3274
|
: `选择实际使用模型:${selectedLabel}`;
|
|
3270
3275
|
select.disabled = interactionBusy;
|
|
3271
|
-
select.title =
|
|
3276
|
+
select.title = modelLocked ? aiConversationOptionLockedMessage : "";
|
|
3272
3277
|
button.disabled = interactionBusy;
|
|
3273
3278
|
button.title = label;
|
|
3274
3279
|
button.setAttribute("aria-label", label);
|
|
3275
3280
|
if (interactionBusy) setAiModelPickerVisible(false);
|
|
3276
3281
|
}
|
|
3277
3282
|
|
|
3278
|
-
function notifyAiConversationOptionLocked(select) {
|
|
3279
|
-
if (!
|
|
3283
|
+
function notifyAiConversationOptionLocked(select, locked = state.aiPromptSent) {
|
|
3284
|
+
if (!locked) return false;
|
|
3280
3285
|
const now = Date.now();
|
|
3281
3286
|
const lastToastAt = Number(select.dataset.lockedToastAt ?? 0);
|
|
3282
3287
|
if (now - lastToastAt > 500) toast(aiConversationOptionLockedMessage);
|
|
@@ -3284,9 +3289,16 @@ function notifyAiConversationOptionLocked(select) {
|
|
|
3284
3289
|
return true;
|
|
3285
3290
|
}
|
|
3286
3291
|
|
|
3292
|
+
function notifyAiConversationModelLocked(control) {
|
|
3293
|
+
return notifyAiConversationOptionLocked(control, aiConversationModelLocked());
|
|
3294
|
+
}
|
|
3295
|
+
|
|
3287
3296
|
function blockLockedAiConversationOptionInteraction(event) {
|
|
3288
3297
|
const select = event.currentTarget;
|
|
3289
|
-
|
|
3298
|
+
const locked = select.id === "ai-model"
|
|
3299
|
+
? notifyAiConversationModelLocked(select)
|
|
3300
|
+
: notifyAiConversationOptionLocked(select);
|
|
3301
|
+
if (!locked) return;
|
|
3290
3302
|
event.preventDefault();
|
|
3291
3303
|
event.stopPropagation();
|
|
3292
3304
|
}
|
|
@@ -15032,13 +15044,9 @@ function createAiStreamCharacterCount(value) {
|
|
|
15032
15044
|
return count;
|
|
15033
15045
|
}
|
|
15034
15046
|
|
|
15035
|
-
function renderAiStreamingCharacterProgress(meta, visibleCharacters
|
|
15047
|
+
function renderAiStreamingCharacterProgress(meta, visibleCharacters) {
|
|
15036
15048
|
const visible = Math.max(0, Number(visibleCharacters) || 0);
|
|
15037
|
-
|
|
15038
|
-
const children = ["正在生成 · ", createAiStreamCharacterCount(visible)];
|
|
15039
|
-
if (received > visible) children.push(" / ", createAiStreamCharacterCount(received));
|
|
15040
|
-
children.push(" 字");
|
|
15041
|
-
meta.replaceChildren(...children);
|
|
15049
|
+
meta.replaceChildren("正在生成 · ", createAiStreamCharacterCount(visible), " 字");
|
|
15042
15050
|
}
|
|
15043
15051
|
|
|
15044
15052
|
async function streamChat(requestHolder, body, idempotencyKey) {
|
|
@@ -15067,8 +15075,7 @@ async function streamChat(requestHolder, body, idempotencyKey) {
|
|
|
15067
15075
|
onRender: (text, progress) => {
|
|
15068
15076
|
if (!aiRequestTargetsCurrentState(requestHolder.snapshot) || !mountAssistantMessage()) return;
|
|
15069
15077
|
content.innerHTML = renderMarkdown(text);
|
|
15070
|
-
|
|
15071
|
-
renderAiStreamingCharacterProgress(meta, progress.visibleCharacters, receivedCharacters);
|
|
15078
|
+
renderAiStreamingCharacterProgress(meta, progress.visibleCharacters);
|
|
15072
15079
|
scrollAiFeedToBottom(feed);
|
|
15073
15080
|
}
|
|
15074
15081
|
});
|
|
@@ -15178,7 +15185,6 @@ async function streamChat(requestHolder, body, idempotencyKey) {
|
|
|
15178
15185
|
streamedText += delta;
|
|
15179
15186
|
streamedPendingText += delta;
|
|
15180
15187
|
typewriter.append(delta);
|
|
15181
|
-
meta.textContent = "正在生成回复……";
|
|
15182
15188
|
} else if (eventName === "process_step") {
|
|
15183
15189
|
mountAssistantMessage();
|
|
15184
15190
|
const step = { ...payload };
|
|
@@ -16996,7 +17002,7 @@ $("#ai-model").addEventListener("focus", () => {
|
|
|
16996
17002
|
ensureAiModelsLoaded().catch((error) => toast(`模型加载失败:${error.message}`, "error"));
|
|
16997
17003
|
});
|
|
16998
17004
|
$("#ai-model").addEventListener("change", (event) => {
|
|
16999
|
-
if (
|
|
17005
|
+
if (aiConversationModelLocked()) {
|
|
17000
17006
|
event.currentTarget.value = state.aiConversationModelId ?? event.currentTarget.value;
|
|
17001
17007
|
syncAiModelPicker();
|
|
17002
17008
|
return toast(aiConversationOptionLockedMessage);
|
|
@@ -17007,7 +17013,7 @@ $("#ai-model").addEventListener("change", (event) => {
|
|
|
17007
17013
|
});
|
|
17008
17014
|
$("#ai-model-picker").addEventListener("click", async (event) => {
|
|
17009
17015
|
const button = event.currentTarget;
|
|
17010
|
-
if (
|
|
17016
|
+
if (notifyAiConversationModelLocked(button)) return;
|
|
17011
17017
|
const willOpen = $("#ai-model-popover").classList.contains("hidden");
|
|
17012
17018
|
setAiContextDistributionVisible(false);
|
|
17013
17019
|
setAiModelPickerVisible(willOpen);
|
package/dist/public/index.html
CHANGED
|
@@ -1210,6 +1210,6 @@
|
|
|
1210
1210
|
<div id="auth-loading" class="auth-loading" role="status" aria-label="正在载入工作台"></div>
|
|
1211
1211
|
<script id="vditorIconScript" src="/vendor/vditor/dist/js/icons/ant.js?v=3.11.2"></script>
|
|
1212
1212
|
<script src="/vendor/vditor/dist/index.min.js?v=3.11.2"></script>
|
|
1213
|
-
<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-v1&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-v1&feature=volume-detail-icon-v1&feature=reader-manual-chapter-navigation-v1&feature=ai-message-reference-badges-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-model-picker-v1&feature=context-percent-format-v1&feature=annotation-precise-locate-v1&feature=markdown-word-count-stable-v1&feature=ai-stream-character-count-stable-
|
|
1213
|
+
<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-v1&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-v1&feature=volume-detail-icon-v1&feature=reader-manual-chapter-navigation-v1&feature=ai-message-reference-badges-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-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=phone-client-entry-v1"></script>
|
|
1214
1214
|
</body>
|
|
1215
1215
|
</html>
|
package/dist/store.js
CHANGED
|
@@ -5582,12 +5582,18 @@ export class Store {
|
|
|
5582
5582
|
throw notFound("AI 对话");
|
|
5583
5583
|
if (requiredString(conversation, "work_id") !== workId)
|
|
5584
5584
|
throw new AppError(400, "CONVERSATION_WORK_MISMATCH", "AI 对话不属于当前作品");
|
|
5585
|
-
|
|
5585
|
+
return this.aiConversationLockedModelId(conversationId);
|
|
5586
|
+
}
|
|
5587
|
+
aiConversationLockedModelId(conversationId) {
|
|
5588
|
+
const messages = this.db.all(`SELECT metadata_json FROM ai_conversation_messages
|
|
5586
5589
|
WHERE conversation_id = ? AND role = 'user'
|
|
5587
|
-
ORDER BY created_at, rowid
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5590
|
+
ORDER BY created_at, rowid`, conversationId);
|
|
5591
|
+
for (const message of messages) {
|
|
5592
|
+
const metadata = json(requiredString(message, "metadata_json"), {});
|
|
5593
|
+
if (typeof metadata.modelId === "string" && metadata.modelId.trim())
|
|
5594
|
+
return metadata.modelId.trim();
|
|
5595
|
+
}
|
|
5596
|
+
return null;
|
|
5591
5597
|
}
|
|
5592
5598
|
getAiConversationInjectedEntities(conversationId, workId) {
|
|
5593
5599
|
const conversation = this.db.get("SELECT work_id, injected_entities_json FROM ai_conversations WHERE id = ?", conversationId);
|
|
@@ -6070,7 +6076,11 @@ export class Store {
|
|
|
6070
6076
|
? JSON.stringify(normalizeWorkAgentTools(this.getWorkAiSettings(workId).agentTools))
|
|
6071
6077
|
: String(conversation.agent_tools_json), injectedEntitiesJson, systemClockText, timestamp, timestamp, currentRequestActor()?.userId ?? null);
|
|
6072
6078
|
for (const message of messages.slice(0, targetIndex + 1)) {
|
|
6073
|
-
|
|
6079
|
+
const role = requiredString(message, "role");
|
|
6080
|
+
const inheritedMetadata = json(requiredString(message, "metadata_json"), {});
|
|
6081
|
+
if (role === "user")
|
|
6082
|
+
delete inheritedMetadata.modelId;
|
|
6083
|
+
this.db.run("INSERT INTO ai_conversation_messages (id, conversation_id, role, content, citations_json, metadata_json, request_id, created_at, created_by_user_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", id("message"), forkId, role, requiredString(message, "content"), requiredString(message, "citations_json"), JSON.stringify(inheritedMetadata), optionalString(message, "request_id"), requiredString(message, "created_at"), currentRequestActor()?.userId ?? null);
|
|
6074
6084
|
}
|
|
6075
6085
|
if (normalizedRequestId) {
|
|
6076
6086
|
this.db.run("INSERT INTO ai_conversation_forks (source_conversation_id, source_message_id, request_id, conversation_id, created_at) VALUES (?, ?, ?, ?, ?)", conversationId, messageId, normalizedRequestId, forkId, timestamp);
|
|
@@ -6110,16 +6120,7 @@ export class Store {
|
|
|
6110
6120
|
mapAiConversation(row) {
|
|
6111
6121
|
const roleplayCharacterId = optionalString(row, "roleplay_character_id");
|
|
6112
6122
|
const roleplayUserCharacterId = optionalString(row, "roleplay_user_character_id");
|
|
6113
|
-
const
|
|
6114
|
-
WHERE conversation_id = ? AND role = 'user'
|
|
6115
|
-
ORDER BY created_at, rowid
|
|
6116
|
-
LIMIT 1`, requiredString(row, "id"));
|
|
6117
|
-
const firstUserMetadata = firstUserMessage
|
|
6118
|
-
? json(requiredString(firstUserMessage, "metadata_json"), {})
|
|
6119
|
-
: {};
|
|
6120
|
-
const lockedModelId = typeof firstUserMetadata.modelId === "string" && firstUserMetadata.modelId.trim()
|
|
6121
|
-
? firstUserMetadata.modelId.trim()
|
|
6122
|
-
: null;
|
|
6123
|
+
const lockedModelId = this.aiConversationLockedModelId(requiredString(row, "id"));
|
|
6123
6124
|
const roleplayCharacter = roleplayCharacterId
|
|
6124
6125
|
? this.db.get("SELECT id, name, code FROM characters WHERE id = ? AND work_id = ?", roleplayCharacterId, requiredString(row, "work_id"))
|
|
6125
6126
|
: undefined;
|