@musnows/scriverse 1.0.3 → 1.0.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/app.js +24 -5
- package/dist/app.js.map +1 -1
- package/dist/public/ai-interactive.js +59 -6
- package/dist/public/app.js +124 -42
- package/dist/public/index.html +1 -1
- package/dist/store.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -51,6 +51,17 @@ export function aiQuestionStatusLabel(status) {
|
|
|
51
51
|
return QUESTION_STATUS_LABELS[String(status)] ?? String(status);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
/** 待回答或尚未加载完成时不允许静默关闭提问窗口。 */
|
|
55
|
+
export function aiQuestionDialogCanClose(question) {
|
|
56
|
+
return ["answered", "rejected", "expired"].includes(String(question?.status ?? ""));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** 优先读取结构化错误码,并兼容修复前只保存了错误正文的历史消息。 */
|
|
60
|
+
export function aiFailureCode(text, metadata = {}) {
|
|
61
|
+
if (typeof metadata?.errorCode === "string" && metadata.errorCode) return metadata.errorCode;
|
|
62
|
+
return String(text ?? "").match(/(?:^|\n)错误码:([^\n]+)(?:\n|$)/u)?.[1]?.trim() ?? "";
|
|
63
|
+
}
|
|
64
|
+
|
|
54
65
|
/** 状态徽章色调:CSS 里按 data-tone 展示统一配色。 */
|
|
55
66
|
export function statusTone(status) {
|
|
56
67
|
switch (String(status)) {
|
|
@@ -114,19 +125,63 @@ export function parseInteractiveToolPayload(toolCall) {
|
|
|
114
125
|
error
|
|
115
126
|
};
|
|
116
127
|
}
|
|
117
|
-
const
|
|
128
|
+
const rawArguments = toolCall?.arguments;
|
|
129
|
+
let suppliedArguments = rawArguments;
|
|
130
|
+
if (typeof rawArguments === "string") {
|
|
131
|
+
try { suppliedArguments = JSON.parse(rawArguments); } catch { suppliedArguments = null; }
|
|
132
|
+
}
|
|
133
|
+
const argumentQuestions = Array.isArray(suppliedArguments?.questions)
|
|
134
|
+
? suppliedArguments.questions
|
|
135
|
+
: suppliedArguments?.question
|
|
136
|
+
? [{ question: suppliedArguments.question, options: suppliedArguments.options }]
|
|
137
|
+
: [];
|
|
138
|
+
const resultQuestion = ok && result?.question && typeof result.question === "object" && !Array.isArray(result.question)
|
|
139
|
+
? result.question
|
|
140
|
+
: null;
|
|
141
|
+
const question = resultQuestion && (!Array.isArray(resultQuestion.questions) || resultQuestion.questions.length === 0) && argumentQuestions.length > 0
|
|
142
|
+
? { ...resultQuestion, questions: argumentQuestions }
|
|
143
|
+
: resultQuestion;
|
|
118
144
|
return {
|
|
119
145
|
kind: "question",
|
|
120
146
|
ok,
|
|
121
147
|
name,
|
|
122
148
|
calledAt: toolCall?.calledAt ?? "",
|
|
123
|
-
question
|
|
124
|
-
|
|
149
|
+
question,
|
|
150
|
+
argumentQuestions,
|
|
125
151
|
message: typeof result?.message === "string" ? result.message : "",
|
|
126
152
|
error
|
|
127
153
|
};
|
|
128
154
|
}
|
|
129
155
|
|
|
156
|
+
/** 兼容历史单题、批量题目、字符串选项与完整 API 选项对象。 */
|
|
157
|
+
export function normalizeAiQuestionItems(question) {
|
|
158
|
+
const items = Array.isArray(question?.questions) && question.questions.length > 0
|
|
159
|
+
? question.questions
|
|
160
|
+
: [{
|
|
161
|
+
question: question?.question ?? "",
|
|
162
|
+
options: question?.options ?? [],
|
|
163
|
+
selectedOption: question?.selectedOption ?? null,
|
|
164
|
+
customAnswer: question?.customAnswer ?? "",
|
|
165
|
+
answerText: question?.answerText ?? "",
|
|
166
|
+
isCustomAnswer: question?.isCustomAnswer === true
|
|
167
|
+
}];
|
|
168
|
+
return items.map((item, index) => ({
|
|
169
|
+
...item,
|
|
170
|
+
index,
|
|
171
|
+
question: String(item?.question ?? ""),
|
|
172
|
+
options: (Array.isArray(item?.options) ? item.options : []).map((option, optionIndex) => (
|
|
173
|
+
option && typeof option === "object" && !Array.isArray(option)
|
|
174
|
+
? {
|
|
175
|
+
...option,
|
|
176
|
+
index: Number.isInteger(option.index) ? Number(option.index) : optionIndex,
|
|
177
|
+
label: String(option.label ?? ""),
|
|
178
|
+
recommended: option.recommended === true || (option.recommended === undefined && optionIndex === 0)
|
|
179
|
+
}
|
|
180
|
+
: { index: optionIndex, label: String(option ?? ""), recommended: optionIndex === 0 }
|
|
181
|
+
))
|
|
182
|
+
}));
|
|
183
|
+
}
|
|
184
|
+
|
|
130
185
|
/**
|
|
131
186
|
* 会话内的最新审批详情缓存:确认/撤销之后写回,避免卡片在重渲染时回退到提交时刻的快照。
|
|
132
187
|
*/
|
|
@@ -294,9 +349,7 @@ function buildQuestionCard(model, actions) {
|
|
|
294
349
|
card.append(body);
|
|
295
350
|
}
|
|
296
351
|
|
|
297
|
-
const options = question
|
|
298
|
-
? question.options.map((option) => option.label)
|
|
299
|
-
: model.argumentOptions;
|
|
352
|
+
const options = normalizeAiQuestionItems(question).flatMap((item) => item.options.map((option) => option.label));
|
|
300
353
|
if (options.length > 0) {
|
|
301
354
|
const list = document.createElement("ol");
|
|
302
355
|
list.className = "ai-question-option-preview";
|
package/dist/public/app.js
CHANGED
|
@@ -41,15 +41,18 @@ import { isPhoneClient } from "/phone-client.js?v=20260819-phone-client-v1";
|
|
|
41
41
|
import { formatAiToolCallResult } from "/ai-tool-call.js?v=20260801-ai-tool-result-chars-v1";
|
|
42
42
|
import {
|
|
43
43
|
AI_WRITE_TOOLS_META,
|
|
44
|
+
aiFailureCode,
|
|
45
|
+
aiQuestionDialogCanClose,
|
|
44
46
|
cacheAiQuestionView,
|
|
45
47
|
cacheAiWritePlanDetail,
|
|
46
48
|
createInteractiveToolCard,
|
|
49
|
+
normalizeAiQuestionItems,
|
|
47
50
|
parseInteractiveToolPayload,
|
|
48
51
|
renderApprovalCenterRows,
|
|
49
52
|
renderWritePlanDetailMarkup,
|
|
50
53
|
isInteractiveToolPending,
|
|
51
54
|
aiFormatDateTime
|
|
52
|
-
} from "/ai-interactive.js?v=
|
|
55
|
+
} from "/ai-interactive.js?v=20260906-question-recovery-v1";
|
|
53
56
|
import { copyAiRawMarkdown } from "/ai-message-actions.js?v=20260713-copy-raw-markdown";
|
|
54
57
|
import { bindPlainTextPaste } from "/plain-text-paste.js?v=20260815-plain-text-paste-v1";
|
|
55
58
|
import { clipboardImageFiles } from "/character-markdown.js?v=20260820-ai-chat-image-attachments-v1";
|
|
@@ -2898,6 +2901,41 @@ function aiRetryStreamRequestBody(body, retry) {
|
|
|
2898
2901
|
: body;
|
|
2899
2902
|
}
|
|
2900
2903
|
|
|
2904
|
+
async function discardPendingAiQuestion(message, button) {
|
|
2905
|
+
const feed = message.closest(".ai-feed");
|
|
2906
|
+
const tab = aiChatTabManager.get(feed?.dataset.aiTabId);
|
|
2907
|
+
if (!tab?.conversationId || !tab.workId || String(tab.workId) !== String(state.work?.id ?? "")) {
|
|
2908
|
+
throw new Error("无法确定待回答问题所属的当前对话");
|
|
2909
|
+
}
|
|
2910
|
+
const label = button.querySelector("span");
|
|
2911
|
+
button.disabled = true;
|
|
2912
|
+
if (label) label.textContent = "正在作废提问";
|
|
2913
|
+
try {
|
|
2914
|
+
const expectedQuestionId = String(message.dataset.pendingQuestionId ?? "");
|
|
2915
|
+
const parameters = new URLSearchParams({ conversationId: tab.conversationId, status: "pending", limit: "1" });
|
|
2916
|
+
const payload = await api(`/api/works/${encodeURIComponent(tab.workId)}/ai/questions?${parameters}`);
|
|
2917
|
+
const questions = Array.isArray(payload) ? payload : (Array.isArray(payload?.questions) ? payload.questions : []);
|
|
2918
|
+
const questionId = String(questions.find((question) => String(question?.id ?? "") === expectedQuestionId)?.id ?? questions[0]?.id ?? "");
|
|
2919
|
+
if (!questionId) {
|
|
2920
|
+
if (label) label.textContent = "提问已处理";
|
|
2921
|
+
button.setAttribute("aria-label", "待回答提问已处理");
|
|
2922
|
+
toast("当前对话已经没有待回答问题,可以重新发送消息");
|
|
2923
|
+
return;
|
|
2924
|
+
}
|
|
2925
|
+
await respondAiUserQuestion(questionId, { action: "reject" });
|
|
2926
|
+
for (const action of tab.feed.querySelectorAll(".ai-question-discard-button")) {
|
|
2927
|
+
action.disabled = true;
|
|
2928
|
+
action.setAttribute("aria-label", "待回答提问已作废");
|
|
2929
|
+
const actionLabel = action.querySelector("span");
|
|
2930
|
+
if (actionLabel) actionLabel.textContent = "提问已作废";
|
|
2931
|
+
}
|
|
2932
|
+
} catch (error) {
|
|
2933
|
+
button.disabled = false;
|
|
2934
|
+
if (label) label.textContent = "作废提问并继续";
|
|
2935
|
+
throw error;
|
|
2936
|
+
}
|
|
2937
|
+
}
|
|
2938
|
+
|
|
2901
2939
|
function renderMessageCardActions(message) {
|
|
2902
2940
|
let actions = message.querySelector(".message-card-actions");
|
|
2903
2941
|
if (!actions) {
|
|
@@ -2927,18 +2965,30 @@ function renderMessageCardActions(message) {
|
|
|
2927
2965
|
actions.append(copy);
|
|
2928
2966
|
}
|
|
2929
2967
|
if (message.dataset.status === "failed" && message.classList.contains("assistant-message")) {
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
if (retry.isConnected) retry.disabled = false;
|
|
2968
|
+
if (message.dataset.errorCode === "AI_QUESTION_PENDING") {
|
|
2969
|
+
const discard = document.createElement("button");
|
|
2970
|
+
discard.type = "button";
|
|
2971
|
+
discard.className = "message-retry-button ai-question-discard-button";
|
|
2972
|
+
discard.setAttribute("aria-label", "作废待回答提问并让 AI 继续");
|
|
2973
|
+
discard.innerHTML = '<svg class="message-action-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M5 5l14 14M19 5 5 19"/><path d="M15 12h6M18 9l3 3-3 3"/></svg><span>作废提问并继续</span>';
|
|
2974
|
+
discard.addEventListener("click", () => {
|
|
2975
|
+
void discardPendingAiQuestion(message, discard).catch((error) => toast(`作废提问失败:${error.message}`, "error"));
|
|
2939
2976
|
});
|
|
2940
|
-
|
|
2941
|
-
|
|
2977
|
+
actions.append(discard);
|
|
2978
|
+
} else {
|
|
2979
|
+
const retry = document.createElement("button");
|
|
2980
|
+
retry.type = "button";
|
|
2981
|
+
retry.className = "message-retry-button";
|
|
2982
|
+
retry.setAttribute("aria-label", "重试");
|
|
2983
|
+
retry.innerHTML = '<svg class="message-action-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M20 11a8 8 0 0 0-14.7-4L4 9"/><path d="M4 4v5h5"/><path d="M4 13a8 8 0 0 0 14.7 4L20 15"/><path d="M20 20v-5h-5"/></svg><span>重试</span>';
|
|
2984
|
+
retry.addEventListener("click", () => {
|
|
2985
|
+
retry.disabled = true;
|
|
2986
|
+
void retryAiMessage(message).finally(() => {
|
|
2987
|
+
if (retry.isConnected) retry.disabled = false;
|
|
2988
|
+
});
|
|
2989
|
+
});
|
|
2990
|
+
actions.append(retry);
|
|
2991
|
+
}
|
|
2942
2992
|
} else if (message.dataset.messageId && message.classList.contains("assistant-message")) {
|
|
2943
2993
|
const fork = document.createElement("button");
|
|
2944
2994
|
fork.type = "button";
|
|
@@ -3262,14 +3312,14 @@ function handleInteractiveToolCallEvent(toolCall) {
|
|
|
3262
3312
|
return;
|
|
3263
3313
|
}
|
|
3264
3314
|
if (name !== "ask_user_question" || toolCall.status === "failed") return;
|
|
3265
|
-
const question = toolCall
|
|
3315
|
+
const question = parseInteractiveToolPayload(toolCall)?.question;
|
|
3266
3316
|
if (!question?.id) return;
|
|
3267
3317
|
cacheAiQuestionView(question);
|
|
3268
3318
|
const questionId = String(question.id);
|
|
3269
3319
|
if (autoOpenedQuestionIds.has(questionId)) return;
|
|
3270
3320
|
autoOpenedQuestionIds.add(questionId);
|
|
3271
3321
|
// 直接弹出回答框等待作者选择;不会预填任何答案。
|
|
3272
|
-
openAiUserQuestionDialog(questionId).catch(() => undefined);
|
|
3322
|
+
openAiUserQuestionDialog(questionId, question).catch(() => undefined);
|
|
3273
3323
|
}
|
|
3274
3324
|
|
|
3275
3325
|
function questionsEndpoint(path) {
|
|
@@ -3392,22 +3442,7 @@ async function fetchAiUserQuestion(questionId) {
|
|
|
3392
3442
|
}
|
|
3393
3443
|
|
|
3394
3444
|
function aiQuestionItems(question) {
|
|
3395
|
-
|
|
3396
|
-
? question.questions
|
|
3397
|
-
: [{
|
|
3398
|
-
question: question?.question ?? "",
|
|
3399
|
-
options: question?.options ?? [],
|
|
3400
|
-
selectedOption: question?.selectedOption ?? null,
|
|
3401
|
-
customAnswer: question?.customAnswer ?? "",
|
|
3402
|
-
answerText: question?.answerText ?? "",
|
|
3403
|
-
isCustomAnswer: question?.isCustomAnswer === true
|
|
3404
|
-
}];
|
|
3405
|
-
return items.map((item, index) => ({
|
|
3406
|
-
...item,
|
|
3407
|
-
index,
|
|
3408
|
-
question: String(item?.question ?? ""),
|
|
3409
|
-
options: Array.isArray(item?.options) ? item.options : []
|
|
3410
|
-
}));
|
|
3445
|
+
return normalizeAiQuestionItems(question);
|
|
3411
3446
|
}
|
|
3412
3447
|
|
|
3413
3448
|
function resetAiQuestionDialogState(question) {
|
|
@@ -3448,6 +3483,14 @@ function syncAiQuestionAnswerCount() {
|
|
|
3448
3483
|
$("#ai-question-answer-count").textContent = `已填写 ${input.value.length} / ${maximum}`;
|
|
3449
3484
|
}
|
|
3450
3485
|
|
|
3486
|
+
function syncAiQuestionDismissState() {
|
|
3487
|
+
const closeButton = $("#ai-question-close");
|
|
3488
|
+
const canClose = aiQuestionDialogCanClose(currentAiQuestionDialogView);
|
|
3489
|
+
closeButton.disabled = !canClose;
|
|
3490
|
+
closeButton.classList.toggle("hidden", !canClose);
|
|
3491
|
+
$("#ai-question-dialog").dataset.dismissLocked = String(!canClose);
|
|
3492
|
+
}
|
|
3493
|
+
|
|
3451
3494
|
function renderAiUserQuestionOptions(question) {
|
|
3452
3495
|
const host = $("#ai-question-options");
|
|
3453
3496
|
const customInput = $("#ai-question-custom-answer");
|
|
@@ -3502,6 +3545,7 @@ function renderAiUserQuestionOptions(question) {
|
|
|
3502
3545
|
// 提交按钮由选择状态驱动:待回答且已选择(或输入)时才可提交。
|
|
3503
3546
|
if (isPending) syncAiQuestionSubmitState();
|
|
3504
3547
|
else $("#ai-question-submit").disabled = true;
|
|
3548
|
+
syncAiQuestionDismissState();
|
|
3505
3549
|
$("#ai-question-submit").textContent = items.length > 1 ? "提交全部回答" : "提交回答";
|
|
3506
3550
|
$("#ai-question-skip").disabled = !isPending;
|
|
3507
3551
|
$("#ai-question-expiry").textContent = isPending
|
|
@@ -3517,17 +3561,25 @@ async function refreshAiQuestionDialog() {
|
|
|
3517
3561
|
return question;
|
|
3518
3562
|
}
|
|
3519
3563
|
|
|
3520
|
-
async function openAiUserQuestionDialog(questionId) {
|
|
3564
|
+
async function openAiUserQuestionDialog(questionId, initialQuestion = null) {
|
|
3521
3565
|
aiQuestionDialogQuestionId = String(questionId);
|
|
3522
3566
|
const dialog = $("#ai-question-dialog");
|
|
3523
3567
|
if (!dialog.open) dialog.showModal();
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3568
|
+
if (initialQuestion?.id && String(initialQuestion.id) === aiQuestionDialogQuestionId) {
|
|
3569
|
+
currentAiQuestionDialogView = initialQuestion;
|
|
3570
|
+
resetAiQuestionDialogState(initialQuestion);
|
|
3571
|
+
renderAiUserQuestionOptions(initialQuestion);
|
|
3572
|
+
} else {
|
|
3573
|
+
currentAiQuestionDialogView = null;
|
|
3574
|
+
$("#ai-question-text").textContent = "";
|
|
3575
|
+
$("#ai-question-options").replaceChildren();
|
|
3576
|
+
$("#ai-question-custom-answer").value = "";
|
|
3577
|
+
$("#ai-question-navigation").classList.add("hidden");
|
|
3578
|
+
$("#ai-question-progress").textContent = "正在加载问题";
|
|
3579
|
+
syncAiQuestionAnswerCount();
|
|
3580
|
+
$("#ai-question-expiry").textContent = "正在加载问题……";
|
|
3581
|
+
syncAiQuestionDismissState();
|
|
3582
|
+
}
|
|
3531
3583
|
try {
|
|
3532
3584
|
return await refreshAiQuestionDialog();
|
|
3533
3585
|
} catch (error) {
|
|
@@ -5908,6 +5960,15 @@ function formatAiFailureMessage(error) {
|
|
|
5908
5960
|
return lines.join("\n");
|
|
5909
5961
|
}
|
|
5910
5962
|
|
|
5963
|
+
function aiFailureMessageMetadata(error) {
|
|
5964
|
+
const details = error?.details && typeof error.details === "object" && !Array.isArray(error.details) ? error.details : {};
|
|
5965
|
+
return {
|
|
5966
|
+
...(typeof error?.code === "string" ? { errorCode: error.code.slice(0, 100) } : {}),
|
|
5967
|
+
...(Number.isInteger(error?.status) ? { errorStatus: error.status } : {}),
|
|
5968
|
+
...(typeof details.questionId === "string" ? { pendingQuestionId: details.questionId } : {})
|
|
5969
|
+
};
|
|
5970
|
+
}
|
|
5971
|
+
|
|
5911
5972
|
function isAgentToolCallLimitFailure(text) {
|
|
5912
5973
|
return /more than \d+ tool calls in one response cycle\./u.test(String(text ?? ""));
|
|
5913
5974
|
}
|
|
@@ -18290,6 +18351,7 @@ async function sendAiWithOptions({ ignoreContextWarning = false, retry = null }
|
|
|
18290
18351
|
return;
|
|
18291
18352
|
}
|
|
18292
18353
|
const failureMessage = formatAiFailureMessage(error);
|
|
18354
|
+
const failureMetadata = aiFailureMessageMetadata(error);
|
|
18293
18355
|
let persistedFailureMessage = null;
|
|
18294
18356
|
try {
|
|
18295
18357
|
persistedFailureMessage = await persistAiConversationMessage(
|
|
@@ -18297,13 +18359,13 @@ async function sendAiWithOptions({ ignoreContextWarning = false, retry = null }
|
|
|
18297
18359
|
"assistant",
|
|
18298
18360
|
failureMessage,
|
|
18299
18361
|
[],
|
|
18300
|
-
|
|
18362
|
+
failureMetadata,
|
|
18301
18363
|
{ requestId: aiAssistantRequestId(request) }
|
|
18302
18364
|
);
|
|
18303
18365
|
updateAiConversationSummaryFromMessage(persistedFailureMessage);
|
|
18304
18366
|
} catch { /* 主请求错误已显示,历史记录保存失败不覆盖原始错误 */ }
|
|
18305
18367
|
if (aiRequestTargetsCurrentState(request)) {
|
|
18306
|
-
appendMessage("assistant", failureMessage, [], persistedFailureMessage?.createdAt,
|
|
18368
|
+
appendMessage("assistant", failureMessage, [], persistedFailureMessage?.createdAt, failureMetadata, persistedFailureMessage?.id, { tab });
|
|
18307
18369
|
}
|
|
18308
18370
|
} finally {
|
|
18309
18371
|
aiRequestManager.finish(requestHolder.snapshot);
|
|
@@ -18686,6 +18748,9 @@ function appendMessage(role, text, citations = [], createdAt = null, metadata =
|
|
|
18686
18748
|
const isInterrupted = role === "assistant" && metadata?.interrupted === true;
|
|
18687
18749
|
const interruptionCode = typeof metadata?.interruptionCode === "string" ? metadata.interruptionCode : "AI_STREAM_FAILED";
|
|
18688
18750
|
message.className = `${role === "user" ? "user-message" : "assistant-message"}${isFailure || isInterrupted ? " is-error" : ""}`;
|
|
18751
|
+
const errorCode = isFailure ? aiFailureCode(text, metadata) : "";
|
|
18752
|
+
if (errorCode) message.dataset.errorCode = errorCode;
|
|
18753
|
+
if (isFailure && typeof metadata?.pendingQuestionId === "string") message.dataset.pendingQuestionId = metadata.pendingQuestionId;
|
|
18689
18754
|
const parsedUserTurn = role === "user" ? parseRoleplayUserTurn(text) : null;
|
|
18690
18755
|
const messageBody = isFailure
|
|
18691
18756
|
? `<p class="ai-error-text">${esc(text)}</p>${aiToolCallSettingsLinkMarkup(text)}`
|
|
@@ -18723,11 +18788,20 @@ function appendMessage(role, text, citations = [], createdAt = null, metadata =
|
|
|
18723
18788
|
scene.append(sceneLabel, sceneBody);
|
|
18724
18789
|
message.querySelector(".message-body")?.prepend(scene);
|
|
18725
18790
|
}
|
|
18791
|
+
const chapterReferences = state.work?.volumes.flatMap((volume) => volume.chapters.map((chapter) => ({
|
|
18792
|
+
id: chapter.id,
|
|
18793
|
+
name: `${volume.title} / ${chapter.title}`
|
|
18794
|
+
}))) ?? [];
|
|
18795
|
+
const settingReferences = state.settings.map((setting) => ({ id: setting.id, name: setting.title }));
|
|
18796
|
+
const contextSettingReferences = [{ id: "include-setting-info", name: "注入上下文设定" }];
|
|
18726
18797
|
const mentionGroups = role === "user"
|
|
18727
18798
|
? [
|
|
18728
18799
|
["角色", metadata?.mentionCharacterIds, state.characters],
|
|
18729
18800
|
["种族", metadata?.mentionRaceIds, state.races],
|
|
18730
|
-
["组织", metadata?.mentionOrganizationIds, state.organizations]
|
|
18801
|
+
["组织", metadata?.mentionOrganizationIds, state.organizations],
|
|
18802
|
+
["设定", metadata?.mentionSettingIds, settingReferences],
|
|
18803
|
+
["章节", metadata?.mentionChapterIds, chapterReferences],
|
|
18804
|
+
["能力", metadata?.mentionContextSettingIds, contextSettingReferences]
|
|
18731
18805
|
]
|
|
18732
18806
|
.flatMap(([kind, ids, items]) => userMessageMentionNames(ids, items).map((name) => ({ kind, name })))
|
|
18733
18807
|
: [];
|
|
@@ -21317,7 +21391,15 @@ $("#ai-write-plan-undo").addEventListener("click", () => {
|
|
|
21317
21391
|
if (!aiWritePlanDialogPlanId) return;
|
|
21318
21392
|
undoAiWritePlan(aiWritePlanDialogPlanId);
|
|
21319
21393
|
});
|
|
21320
|
-
$("#ai-question-close").addEventListener("click", () =>
|
|
21394
|
+
$("#ai-question-close").addEventListener("click", () => {
|
|
21395
|
+
if (!aiQuestionDialogCanClose(currentAiQuestionDialogView)) return;
|
|
21396
|
+
$("#ai-question-dialog").close();
|
|
21397
|
+
});
|
|
21398
|
+
$("#ai-question-dialog").addEventListener("cancel", (event) => {
|
|
21399
|
+
if (aiQuestionDialogCanClose(currentAiQuestionDialogView)) return;
|
|
21400
|
+
event.preventDefault();
|
|
21401
|
+
toast("请先提交全部回答,或选择“暂不回答”让 AI 继续", "warning");
|
|
21402
|
+
});
|
|
21321
21403
|
|
|
21322
21404
|
function syncAiQuestionSubmitState() {
|
|
21323
21405
|
const submit = $("#ai-question-submit");
|
package/dist/public/index.html
CHANGED
|
@@ -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-v3&feature=ai-background-stream-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=ai-fork-progress-toast-v1&feature=im-settings-gear-v1&feature=compact-sidebar-directory-v2&feature=chapter-word-count-consistency-v1&feature=continuation-guard-failure-details-v1"></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-v3&feature=ai-background-stream-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=ai-fork-progress-toast-v1&feature=im-settings-gear-v1&feature=compact-sidebar-directory-v2&feature=chapter-word-count-consistency-v1&feature=continuation-guard-failure-details-v1&feature=ai-all-message-references-v2&feature=ai-question-render-recovery-v3"></script>
|
|
1429
1429
|
</body>
|
|
1430
1430
|
</html>
|