@musnows/scriverse 1.1.4 → 1.1.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.
- package/dist/ai.js +19 -13
- package/dist/ai.js.map +1 -1
- package/dist/image-captcha.js +35 -9
- package/dist/image-captcha.js.map +1 -1
- package/dist/public/app.js +152 -55
- package/dist/public/index.html +12 -3
- package/dist/public/roleplay-turn.js +10 -0
- package/dist/public/styles.css +13 -0
- package/dist/roleplay-turn.js +6 -0
- package/dist/roleplay-turn.js.map +1 -1
- package/dist/store.js +20 -5
- package/dist/store.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
package/dist/image-captcha.js
CHANGED
|
@@ -2,8 +2,16 @@ import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
|
|
|
2
2
|
import { AppError } from "./errors.js";
|
|
3
3
|
const alphabet = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
|
|
4
4
|
const captchaLength = 4;
|
|
5
|
-
|
|
5
|
+
/** 默认有效期 300 秒。任何配置或调用若短于下限,都会被抬到 180 秒。 */
|
|
6
|
+
export const CAPTCHA_LIFETIME_DEFAULT_MS = 300_000;
|
|
7
|
+
export const CAPTCHA_LIFETIME_MINIMUM_MS = 180_000;
|
|
6
8
|
const maximumChallenges = 5_000;
|
|
9
|
+
/** 把请求的有效期抬到下限;未提供或非法时使用默认 300 秒。 */
|
|
10
|
+
export function resolveCaptchaLifetimeMs(requestedMs) {
|
|
11
|
+
if (typeof requestedMs !== "number" || !Number.isFinite(requestedMs))
|
|
12
|
+
return CAPTCHA_LIFETIME_DEFAULT_MS;
|
|
13
|
+
return Math.max(CAPTCHA_LIFETIME_MINIMUM_MS, Math.trunc(requestedMs));
|
|
14
|
+
}
|
|
7
15
|
/**
|
|
8
16
|
* 5×7 点阵字形会被渲染为 path,而不是 SVG text:这样不会把答案以可直接读取的
|
|
9
17
|
* 文本节点放进 data URL。它不是对抗专业视觉模型的单独安全边界,但能阻止最基础的
|
|
@@ -44,8 +52,15 @@ const glyphPatterns = {
|
|
|
44
52
|
"9": ["01110", "10001", "10001", "01111", "00001", "00001", "01110"]
|
|
45
53
|
};
|
|
46
54
|
const fallbackGlyph = ["11111", "00001", "00010", "00100", "00100", "00000", "00100"];
|
|
55
|
+
/**
|
|
56
|
+
* 全角字母和数字与半角外观相同,但直接比较会失败。
|
|
57
|
+
* 先做 NFKC,再去掉空白和格式字符(含零宽空格),最后按 en-US 大写。
|
|
58
|
+
*/
|
|
59
|
+
export function normalizeCaptchaAnswer(answer) {
|
|
60
|
+
return answer.normalize("NFKC").replace(/[\p{Cf}\p{Z}\s]+/gu, "").toLocaleUpperCase("en-US");
|
|
61
|
+
}
|
|
47
62
|
function digestAnswer(answer) {
|
|
48
|
-
return createHash("sha256").update(answer
|
|
63
|
+
return createHash("sha256").update(normalizeCaptchaAnswer(answer)).digest();
|
|
49
64
|
}
|
|
50
65
|
function randomCode() {
|
|
51
66
|
const bytes = randomBytes(captchaLength);
|
|
@@ -131,8 +146,13 @@ export function renderCaptchaSvg(code, seed = randomBytes(8)) {
|
|
|
131
146
|
export class ImageCaptchaService {
|
|
132
147
|
options;
|
|
133
148
|
challenges = new Map();
|
|
149
|
+
lifetimeMs;
|
|
134
150
|
constructor(options = {}) {
|
|
135
151
|
this.options = options;
|
|
152
|
+
this.lifetimeMs = resolveCaptchaLifetimeMs(options.lifetimeMs);
|
|
153
|
+
}
|
|
154
|
+
currentTime() {
|
|
155
|
+
return this.options.now?.() ?? Date.now();
|
|
136
156
|
}
|
|
137
157
|
create() {
|
|
138
158
|
this.pruneExpired();
|
|
@@ -145,7 +165,7 @@ export class ImageCaptchaService {
|
|
|
145
165
|
const svg = renderCaptchaSvg(answer, seed);
|
|
146
166
|
this.challenges.set(captchaId, {
|
|
147
167
|
answerDigest: digestAnswer(answer),
|
|
148
|
-
expiresAt:
|
|
168
|
+
expiresAt: this.currentTime() + this.lifetimeMs
|
|
149
169
|
});
|
|
150
170
|
return {
|
|
151
171
|
captchaId,
|
|
@@ -153,20 +173,26 @@ export class ImageCaptchaService {
|
|
|
153
173
|
...(this.options.revealAnswer ? { answer } : {})
|
|
154
174
|
};
|
|
155
175
|
}
|
|
156
|
-
/**
|
|
176
|
+
/**
|
|
177
|
+
* 校验验证码。答案错误时保留挑战,允许用同一张图继续重试。
|
|
178
|
+
* 只有答案正确后才核销。过期,以及已核销或未知的挑战,返回已失效。
|
|
179
|
+
*/
|
|
157
180
|
consume(captchaId, answer) {
|
|
181
|
+
const currentTime = this.currentTime();
|
|
158
182
|
const challenge = this.challenges.get(captchaId);
|
|
159
|
-
|
|
160
|
-
|
|
183
|
+
if (!challenge || challenge.expiresAt <= currentTime) {
|
|
184
|
+
if (challenge)
|
|
185
|
+
this.challenges.delete(captchaId);
|
|
161
186
|
throw new AppError(400, "CAPTCHA_INVALID", "验证码已失效,请刷新后重试");
|
|
162
187
|
}
|
|
163
|
-
const provided = digestAnswer(answer
|
|
188
|
+
const provided = digestAnswer(answer);
|
|
164
189
|
if (provided.length !== challenge.answerDigest.length || !timingSafeEqual(provided, challenge.answerDigest)) {
|
|
165
|
-
throw new AppError(400, "
|
|
190
|
+
throw new AppError(400, "CAPTCHA_INCORRECT", "验证码不正确");
|
|
166
191
|
}
|
|
192
|
+
this.challenges.delete(captchaId);
|
|
167
193
|
}
|
|
168
194
|
pruneExpired() {
|
|
169
|
-
const currentTime =
|
|
195
|
+
const currentTime = this.currentTime();
|
|
170
196
|
for (const [captchaId, challenge] of this.challenges) {
|
|
171
197
|
if (challenge.expiresAt <= currentTime)
|
|
172
198
|
this.challenges.delete(captchaId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-captcha.js","sourceRoot":"","sources":["../src/image-captcha.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAcvC,MAAM,QAAQ,GAAG,kCAAkC,CAAC;AACpD,MAAM,aAAa,GAAG,CAAC,CAAC;AACxB,MAAM,iBAAiB,GAAG,CAAC,GAAG,MAAM,CAAC;AACrC,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAEhC;;;;GAIG;AACH,MAAM,aAAa,GAAsC;IACvD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,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"}
|
|
1
|
+
{"version":3,"file":"image-captcha.js","sourceRoot":"","sources":["../src/image-captcha.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAcvC,MAAM,QAAQ,GAAG,kCAAkC,CAAC;AACpD,MAAM,aAAa,GAAG,CAAC,CAAC;AACxB,4CAA4C;AAC5C,MAAM,CAAC,MAAM,2BAA2B,GAAG,OAAO,CAAC;AACnD,MAAM,CAAC,MAAM,2BAA2B,GAAG,OAAO,CAAC;AACnD,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAEhC,qCAAqC;AACrC,MAAM,UAAU,wBAAwB,CAAC,WAAoB;IAC3D,IAAI,OAAO,WAAW,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC;QAAE,OAAO,2BAA2B,CAAC;IACzG,OAAO,IAAI,CAAC,GAAG,CAAC,2BAA2B,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;AACxE,CAAC;AAED;;;;GAIG;AACH,MAAM,aAAa,GAAsC;IACvD,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;IAClE,CAAC,EAAE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"}
|
package/dist/public/app.js
CHANGED
|
@@ -9,14 +9,14 @@ import { createImWorkspace } from "/im.js?v=20260904-im-judge-outcomes-v106";
|
|
|
9
9
|
import { findAiMention, listAiMentionOptions, mergeAiReferenceScope } from "/ai-mentions.js?v=20260811-user-message-mentions-v1";
|
|
10
10
|
import { applyAiSkillCommand, findAiSkillCommand, listAiSlashOptions } from "/ai-skill-menu.js?v=20260921-ai-compact-slash-command-v2";
|
|
11
11
|
import {
|
|
12
|
+
aiConversationTitleSource,
|
|
12
13
|
composeRoleplayStoredUserContent,
|
|
13
14
|
emptyRoleplayScenePin,
|
|
14
15
|
normalizeRoleplayScenePin,
|
|
15
16
|
parseRoleplayUserTurn,
|
|
16
17
|
roleplayScenePinHasContent,
|
|
17
|
-
roleplayUserTurnDisplayText
|
|
18
|
-
|
|
19
|
-
} from "/roleplay-turn.js?v=20260823-ai-roleplay-scene-turn-v2";
|
|
18
|
+
roleplayUserTurnDisplayText
|
|
19
|
+
} from "/roleplay-turn.js?v=20260930-ai-title-xml-v1";
|
|
20
20
|
import { shouldShowAiQuickActions } from "/ai-conversation.js?v=20260713-quick-actions";
|
|
21
21
|
import { createAiChatTabManager, normalizeAiChatTabLimit } from "/ai-chat-tabs.js?v=20260816-ai-chat-switcher-v2";
|
|
22
22
|
import { aiRequestTargetsState, createAiRequestAbortError, createAiRequestManager, isAiRequestCancellation } from "/ai-request-manager.js?v=20260905-question-stream-v2";
|
|
@@ -1977,6 +1977,8 @@ let chapterDraftLineIdState = null;
|
|
|
1977
1977
|
let chapterBeforeInputState = null;
|
|
1978
1978
|
let chapterSearchMatchIndex = -1;
|
|
1979
1979
|
let chapterSelectionRequestId = 0;
|
|
1980
|
+
let chapterBodyAbort = null;
|
|
1981
|
+
let chapterContentReadyId = null;
|
|
1980
1982
|
let chapterForeshadowReminderRequestId = 0;
|
|
1981
1983
|
let chapterForeshadowReminders = [];
|
|
1982
1984
|
let chapterForeshadowReminderIndex = 0;
|
|
@@ -2082,9 +2084,12 @@ function applyChapterEditorMode() {
|
|
|
2082
2084
|
$("#chapter-content").readOnly = viewOnly;
|
|
2083
2085
|
$("#chapter-title").setAttribute("aria-readonly", String(viewOnly));
|
|
2084
2086
|
$("#chapter-content").setAttribute("aria-readonly", String(viewOnly));
|
|
2087
|
+
const waitingForChapter = chapterEditingLocked();
|
|
2085
2088
|
editButton.classList.toggle("hidden", permissionBlocked || !state.chapter);
|
|
2086
2089
|
editButton.classList.toggle("primary-button", chapterEditorReadOnly);
|
|
2087
2090
|
editButton.classList.toggle("ghost-button", !chapterEditorReadOnly);
|
|
2091
|
+
editButton.disabled = waitingForChapter;
|
|
2092
|
+
editButton.setAttribute("aria-disabled", String(waitingForChapter));
|
|
2088
2093
|
editButton.textContent = chapterEditorReadOnly ? "编辑" : "预览";
|
|
2089
2094
|
editButton.setAttribute("aria-pressed", String(!chapterEditorReadOnly));
|
|
2090
2095
|
editButton.setAttribute("aria-label", chapterEditorReadOnly ? "切换到编辑模式" : "切换到预览模式");
|
|
@@ -2095,6 +2100,8 @@ function applyChapterEditorMode() {
|
|
|
2095
2100
|
}
|
|
2096
2101
|
|
|
2097
2102
|
function enterChapterEditMode() {
|
|
2103
|
+
// 缓存或占位正文还没被本次请求确认前,编辑按钮不进入编辑。
|
|
2104
|
+
if (chapterEditingLocked()) return;
|
|
2098
2105
|
if (!state.chapter || !canEditProse()) return;
|
|
2099
2106
|
chapterEditorReadOnly = false;
|
|
2100
2107
|
applyChapterEditorMode();
|
|
@@ -2105,6 +2112,7 @@ function enterChapterEditMode() {
|
|
|
2105
2112
|
}
|
|
2106
2113
|
|
|
2107
2114
|
function toggleChapterEditPreviewMode() {
|
|
2115
|
+
if (chapterEditingLocked()) return;
|
|
2108
2116
|
if (!state.chapter || !canEditProse()) return;
|
|
2109
2117
|
if (chapterEditorReadOnly) {
|
|
2110
2118
|
enterChapterEditMode();
|
|
@@ -4962,7 +4970,7 @@ async function updateRoleplayMemoryAction(memory, action) {
|
|
|
4962
4970
|
}
|
|
4963
4971
|
|
|
4964
4972
|
function defaultAiConversationTitle(prompt) {
|
|
4965
|
-
const normalized =
|
|
4973
|
+
const normalized = aiConversationTitleSource(String(prompt ?? "")).replace(/\s+/gu, " ").trim();
|
|
4966
4974
|
return Array.from(normalized).slice(0, 15).join("") || "新对话";
|
|
4967
4975
|
}
|
|
4968
4976
|
|
|
@@ -6535,6 +6543,7 @@ async function api(path, options = {}) {
|
|
|
6535
6543
|
body: body && typeof body !== "string" ? JSON.stringify(body) : body
|
|
6536
6544
|
});
|
|
6537
6545
|
} catch (error) {
|
|
6546
|
+
if (error?.name === "AbortError") throw error;
|
|
6538
6547
|
if (mobileOfflineRuntime.enabled) {
|
|
6539
6548
|
const offlineSession = await mobileOfflineRuntime.activateOffline();
|
|
6540
6549
|
if (offlineSession) return mobileOfflineRuntime.request(path, { method, body });
|
|
@@ -7660,6 +7669,7 @@ async function persistChapter({ automatic = false } = {}) {
|
|
|
7660
7669
|
const saved = await request;
|
|
7661
7670
|
if (state.work?.id !== workId || state.chapter?.id !== draft.chapterId) return saved.chapter;
|
|
7662
7671
|
state.chapter = saved.chapter;
|
|
7672
|
+
chapterContentReadyId = saved.chapter.id;
|
|
7663
7673
|
state.work = saved.work;
|
|
7664
7674
|
resetChapterDraftLineIds(state.chapter);
|
|
7665
7675
|
lastSavedChapterSnapshot = draft;
|
|
@@ -9374,6 +9384,9 @@ function renderShelf() {
|
|
|
9374
9384
|
|
|
9375
9385
|
function resetWorkScopedUiCaches() {
|
|
9376
9386
|
chapterSelectionRequestId += 1;
|
|
9387
|
+
chapterContentReadyId = null;
|
|
9388
|
+
chapterBodyAbort?.abort();
|
|
9389
|
+
chapterBodyAbort = null;
|
|
9377
9390
|
clearChapterForeshadowReminders({ invalidateRequest: true });
|
|
9378
9391
|
invalidateAiConversationNavigation("已切换作品");
|
|
9379
9392
|
stopBackgroundTaskCenter();
|
|
@@ -9861,7 +9874,10 @@ async function submitChapterBatch(event) {
|
|
|
9861
9874
|
state.work = await api(`/api/works/${encodeURIComponent(workId)}`);
|
|
9862
9875
|
const currentEditorVisible = state.module === "editor";
|
|
9863
9876
|
const currentStillExists = state.chapter && state.work.volumes.some((volume) => volume.chapters.some((chapter) => chapter.id === state.chapter.id));
|
|
9864
|
-
if (state.chapter && currentStillExists)
|
|
9877
|
+
if (state.chapter && currentStillExists) {
|
|
9878
|
+
state.chapter = await api(`/api/chapters/${encodeURIComponent(state.chapter.id)}`);
|
|
9879
|
+
chapterContentReadyId = state.chapter.id;
|
|
9880
|
+
}
|
|
9865
9881
|
if (state.chapter && !currentStillExists) {
|
|
9866
9882
|
state.chapter = null;
|
|
9867
9883
|
showWelcome(true);
|
|
@@ -9997,6 +10013,7 @@ async function deleteChapter(chapterId) {
|
|
|
9997
10013
|
const deletingSelectedChapter = state.chapter?.id === chapterId;
|
|
9998
10014
|
const expectedVersionNo = deletingSelectedChapter ? state.chapter.versionNo : chapter.versionNo;
|
|
9999
10015
|
await api(`/api/chapters/${chapterId}`, { method: "DELETE", body: { expectedVersionNo } });
|
|
10016
|
+
if (String(chapterContentReadyId ?? "") === String(chapterId)) chapterContentReadyId = null;
|
|
10000
10017
|
const workId = state.work.id;
|
|
10001
10018
|
state.work = await api(`/api/works/${workId}`);
|
|
10002
10019
|
if (deletingSelectedChapter) {
|
|
@@ -10215,33 +10232,47 @@ async function resolveCurrentChapterForeshadowReminder() {
|
|
|
10215
10232
|
}
|
|
10216
10233
|
}
|
|
10217
10234
|
|
|
10218
|
-
|
|
10219
|
-
|
|
10220
|
-
|
|
10221
|
-
|
|
10222
|
-
|
|
10223
|
-
|
|
10224
|
-
|
|
10225
|
-
|
|
10226
|
-
|
|
10227
|
-
|
|
10235
|
+
function setChapterContentSkeleton(visible) {
|
|
10236
|
+
const skeleton = $("#chapter-content-skeleton");
|
|
10237
|
+
skeleton.classList.toggle("hidden", !visible);
|
|
10238
|
+
skeleton.setAttribute("aria-busy", String(visible));
|
|
10239
|
+
$("#editor-view").setAttribute("aria-busy", String(visible));
|
|
10240
|
+
if (!visible) return;
|
|
10241
|
+
$("#chapter-line-numbers-inner").replaceChildren();
|
|
10242
|
+
$("#chapter-whitespace-inner").replaceChildren();
|
|
10243
|
+
}
|
|
10244
|
+
|
|
10245
|
+
function chapterEditingLocked() {
|
|
10246
|
+
return !state.chapter || String(chapterContentReadyId ?? "") !== String(state.chapter.id);
|
|
10247
|
+
}
|
|
10248
|
+
|
|
10249
|
+
function directoryChapterEntry(chapterId) {
|
|
10250
|
+
for (const volume of state.work?.volumes ?? []) {
|
|
10251
|
+
const chapter = volume.chapters?.find((item) => String(item.id) === String(chapterId));
|
|
10252
|
+
if (chapter) return chapter;
|
|
10228
10253
|
}
|
|
10229
|
-
|
|
10230
|
-
|
|
10231
|
-
|
|
10232
|
-
|
|
10233
|
-
|
|
10234
|
-
|
|
10235
|
-
|
|
10236
|
-
|
|
10237
|
-
|
|
10238
|
-
|
|
10239
|
-
|
|
10240
|
-
|
|
10241
|
-
|
|
10242
|
-
|
|
10243
|
-
|
|
10244
|
-
|
|
10254
|
+
return null;
|
|
10255
|
+
}
|
|
10256
|
+
|
|
10257
|
+
function chapterRequestStillCurrent(workId, selectionGeneration, selectionRequestId) {
|
|
10258
|
+
return selectionGeneration === chapterSelectionRequestGeneration
|
|
10259
|
+
&& selectionRequestId === chapterSelectionRequestId
|
|
10260
|
+
&& state.work?.id === workId;
|
|
10261
|
+
}
|
|
10262
|
+
|
|
10263
|
+
function presentChapter(chapter, { editMode = false, contentReady = false, syncRoute = true } = {}) {
|
|
10264
|
+
state.chapter = chapter;
|
|
10265
|
+
if (chapter?.volumeId && typeof chapter.content === "string" && (contentReady || chapter.content.length > 0)) {
|
|
10266
|
+
mergeChapterDirectoryEntry(state.chapter);
|
|
10267
|
+
}
|
|
10268
|
+
if (chapter?.volumeId) state.collapsedVolumeIds.delete(chapter.volumeId);
|
|
10269
|
+
lastSavedChapterSnapshot = {
|
|
10270
|
+
chapterId: state.chapter.id,
|
|
10271
|
+
title: state.chapter.title ?? "",
|
|
10272
|
+
content: state.chapter.content ?? ""
|
|
10273
|
+
};
|
|
10274
|
+
chapterContentReadyId = contentReady ? state.chapter.id : null;
|
|
10275
|
+
chapterEditorReadOnly = !contentReady || !editMode;
|
|
10245
10276
|
state.module = "editor";
|
|
10246
10277
|
applyWorkAccessMode();
|
|
10247
10278
|
markActiveModule("editor");
|
|
@@ -10249,22 +10280,77 @@ async function selectChapter(chapterId, { editMode = false } = {}) {
|
|
|
10249
10280
|
$("#module-view").classList.add("hidden");
|
|
10250
10281
|
$("#editor-view").classList.remove("hidden");
|
|
10251
10282
|
updateChapterPath();
|
|
10252
|
-
$("#chapter-title")
|
|
10253
|
-
$("#chapter-content")
|
|
10283
|
+
const titleInput = $("#chapter-title");
|
|
10284
|
+
const contentInput = $("#chapter-content");
|
|
10285
|
+
const nextTitle = state.chapter.title ?? "";
|
|
10286
|
+
const nextContent = state.chapter.content ?? "";
|
|
10287
|
+
if (titleInput.value !== nextTitle) titleInput.value = nextTitle;
|
|
10288
|
+
if (contentInput.value !== nextContent) contentInput.value = nextContent;
|
|
10254
10289
|
resetChapterDraftLineIds(state.chapter);
|
|
10255
10290
|
chapterAnnotationCounts = new Map();
|
|
10256
10291
|
clearChapterLineSelection();
|
|
10257
10292
|
scheduleChapterLineNumbers();
|
|
10258
|
-
void loadChapterAnnotationCounts(state.chapter.id).catch((error) => {
|
|
10259
|
-
if (String(state.chapter?.id ?? "") === String(chapterId)) toast("正文评论数量读取失败,请稍后重试", "error");
|
|
10260
|
-
});
|
|
10261
10293
|
dismissChapterInsightToast();
|
|
10262
10294
|
updateChapterStats();
|
|
10295
|
+
if (!contentReady) $("#chapter-stats").textContent = "正在载入";
|
|
10263
10296
|
if (!canEditProse()) setSaveState("正文只读");
|
|
10297
|
+
else if (!contentReady) setSaveState("正在同步正文");
|
|
10264
10298
|
else if (chapterEditorReadOnly) setSaveState("阅读模式");
|
|
10265
10299
|
else setSaveState("已保存");
|
|
10300
|
+
setChapterContentSkeleton(!contentReady);
|
|
10266
10301
|
syncChapterTreeSelection();
|
|
10267
|
-
replacePageRoute({ view: "editor", workId: state.work.id, chapterId: state.chapter.id });
|
|
10302
|
+
if (syncRoute) replacePageRoute({ view: "editor", workId: state.work.id, chapterId: state.chapter.id });
|
|
10303
|
+
}
|
|
10304
|
+
|
|
10305
|
+
async function selectChapter(chapterId, { editMode = false } = {}) {
|
|
10306
|
+
imWorkspace.close();
|
|
10307
|
+
const workId = state.work?.id;
|
|
10308
|
+
if (!workId) return false;
|
|
10309
|
+
const sameChapter = String(state.chapter?.id ?? "") === String(chapterId);
|
|
10310
|
+
if (sameChapter && chapterEditingLocked() && chapterBodyAbort && !chapterBodyAbort.signal.aborted) return true;
|
|
10311
|
+
const selectionGeneration = ++chapterSelectionRequestGeneration;
|
|
10312
|
+
const selectionRequestId = ++chapterSelectionRequestId;
|
|
10313
|
+
if (!sameChapter) clearChapterForeshadowReminders({ invalidateRequest: true });
|
|
10314
|
+
if (!sameChapter && !(await confirmDiscardChanges("当前章节有未保存修改,仍要切换吗?"))) {
|
|
10315
|
+
if (selectionRequestId === chapterSelectionRequestId) void loadChapterForeshadowReminders();
|
|
10316
|
+
return false;
|
|
10317
|
+
}
|
|
10318
|
+
resetChapterSearchPanel();
|
|
10319
|
+
dismissDeleteToasts();
|
|
10320
|
+
if (!chapterRequestStillCurrent(workId, selectionGeneration, selectionRequestId)) return false;
|
|
10321
|
+
cancelChapterAutoSave();
|
|
10322
|
+
if (sameChapter && String(chapterContentReadyId ?? "") === String(chapterId) && state.chapter) {
|
|
10323
|
+
presentChapter(state.chapter, { editMode, contentReady: true });
|
|
10324
|
+
syncChapterTreeSelection();
|
|
10325
|
+
return true;
|
|
10326
|
+
}
|
|
10327
|
+
const directoryEntry = directoryChapterEntry(chapterId);
|
|
10328
|
+
const previewChapter = directoryEntry
|
|
10329
|
+
? { ...directoryEntry, content: "", lineIds: [] }
|
|
10330
|
+
: { id: chapterId, workId, volumeId: "", title: "", content: "", wordCount: 0, versionNo: 0, chapterType: "正文", lineIds: [] };
|
|
10331
|
+
presentChapter(previewChapter, { editMode: false, contentReady: false });
|
|
10332
|
+
syncChapterTreeSelection();
|
|
10333
|
+
chapterBodyAbort?.abort();
|
|
10334
|
+
const chapterBodyController = new AbortController();
|
|
10335
|
+
chapterBodyAbort = chapterBodyController;
|
|
10336
|
+
let selectedChapter = null;
|
|
10337
|
+
try {
|
|
10338
|
+
selectedChapter = await api(`/api/chapters/${encodeURIComponent(chapterId)}`, { signal: chapterBodyController.signal });
|
|
10339
|
+
} catch (error) {
|
|
10340
|
+
if (chapterBodyAbort === chapterBodyController) chapterBodyAbort = null;
|
|
10341
|
+
if (error?.name === "AbortError" || !chapterRequestStillCurrent(workId, selectionGeneration, selectionRequestId)) return false;
|
|
10342
|
+
if (String(state.chapter?.id ?? "") === String(chapterId)) setSaveState("正文载入失败", true);
|
|
10343
|
+
toast(error.message || "章节读取失败", "error");
|
|
10344
|
+
return false;
|
|
10345
|
+
}
|
|
10346
|
+
if (chapterBodyAbort === chapterBodyController) chapterBodyAbort = null;
|
|
10347
|
+
if (!chapterRequestStillCurrent(workId, selectionGeneration, selectionRequestId)) return false;
|
|
10348
|
+
if (String(selectedChapter?.id ?? "") !== String(chapterId) || String(selectedChapter?.workId ?? "") !== String(workId)) return false;
|
|
10349
|
+
presentChapter(selectedChapter, { editMode, contentReady: true, syncRoute: false });
|
|
10350
|
+
syncChapterTreeSelection();
|
|
10351
|
+
void loadChapterAnnotationCounts(state.chapter.id).catch(() => {
|
|
10352
|
+
if (String(state.chapter?.id ?? "") === String(chapterId)) toast("正文评论数量读取失败,请稍后重试", "error");
|
|
10353
|
+
});
|
|
10268
10354
|
void loadChapterForeshadowReminders();
|
|
10269
10355
|
return true;
|
|
10270
10356
|
}
|
|
@@ -10836,6 +10922,8 @@ async function showModule(module) {
|
|
|
10836
10922
|
state.module = module;
|
|
10837
10923
|
if (module !== "editor") {
|
|
10838
10924
|
chapterSelectionRequestId += 1;
|
|
10925
|
+
chapterBodyAbort?.abort();
|
|
10926
|
+
chapterBodyAbort = null;
|
|
10839
10927
|
clearChapterForeshadowReminders({ invalidateRequest: true });
|
|
10840
10928
|
}
|
|
10841
10929
|
if (module !== "tasks") stopTaskProgressRefresh();
|
|
@@ -11651,8 +11739,9 @@ function openDraftDialog(item = null, { readOnly = false } = {}) {
|
|
|
11651
11739
|
void renderDrafts(moduleListPages.drafts).catch((error) => toast(`想法列表刷新失败:${error instanceof Error ? error.message : "未知错误"}`, "error"));
|
|
11652
11740
|
});
|
|
11653
11741
|
$("#draft-dialog-edit")?.addEventListener("click", () => {
|
|
11654
|
-
|
|
11742
|
+
// 复用当前模态弹窗,避免旧 close 事件销毁新编辑器。
|
|
11655
11743
|
openDraftDialog(draftDialogItem);
|
|
11744
|
+
$("#dialog-title-input").focus();
|
|
11656
11745
|
});
|
|
11657
11746
|
}
|
|
11658
11747
|
}
|
|
@@ -11897,12 +11986,13 @@ async function renderCharacters(page = characterListPage) {
|
|
|
11897
11986
|
|| characterFilters.genderValues.length > 0
|
|
11898
11987
|
|| characterFilters.deathState !== "all";
|
|
11899
11988
|
const pageSize = pageSizeFor("characters");
|
|
11989
|
+
const needsCharacterFilterCatalog = hasCharacterFilters || characterFiltersPanelOpen;
|
|
11900
11990
|
const [characterSource, races, organizations] = await Promise.all([
|
|
11901
11991
|
hasCharacterFilters
|
|
11902
11992
|
? moduleApiAllPages("characters", `/api/works/${state.work.id}/characters`)
|
|
11903
11993
|
: moduleApiPage("characters", `/api/works/${state.work.id}/characters`, page, pageSize),
|
|
11904
|
-
canReadModule("races") ? moduleApi("characters", `/api/works/${state.work.id}/races`) : Promise.resolve([]),
|
|
11905
|
-
canReadModule("organizations") ? moduleApiAllPages("characters", `/api/works/${state.work.id}/organizations`) : Promise.resolve([])
|
|
11994
|
+
needsCharacterFilterCatalog && canReadModule("races") ? moduleApi("characters", `/api/works/${state.work.id}/races`) : Promise.resolve([]),
|
|
11995
|
+
needsCharacterFilterCatalog && canReadModule("organizations") ? moduleApiAllPages("characters", `/api/works/${state.work.id}/organizations`) : Promise.resolve([])
|
|
11906
11996
|
]);
|
|
11907
11997
|
const characterPage = hasCharacterFilters
|
|
11908
11998
|
? paginateCharacters(filterCharacters(characterSource, characterFilters), page, pageSize)
|
|
@@ -11910,7 +12000,7 @@ async function renderCharacters(page = characterListPage) {
|
|
|
11910
12000
|
if (!characterPage.items.length && page > 1) return renderCharacters(page - 1);
|
|
11911
12001
|
characterListPage = characterPage.page;
|
|
11912
12002
|
const pageCharacters = characterPage.items;
|
|
11913
|
-
[state.races, state.organizations] = [races, organizations];
|
|
12003
|
+
if (needsCharacterFilterCatalog) [state.races, state.organizations] = [races, organizations];
|
|
11914
12004
|
mountModuleCount(characterPage.total);
|
|
11915
12005
|
const layout = readModuleLayout();
|
|
11916
12006
|
const characterActions = (item) => `${characterPinButton(item)}${characterFavoriteButton(item)}${recordCardEditButton("edit-character", item.id, `角色“${item.name}”`)}`;
|
|
@@ -14164,10 +14254,7 @@ function updateBackgroundTaskCenterVisibility() {
|
|
|
14164
14254
|
$("#background-task-count")?.classList.add("hidden");
|
|
14165
14255
|
return;
|
|
14166
14256
|
}
|
|
14167
|
-
const activityCount = backgroundTaskActivityCount(
|
|
14168
|
-
backgroundTaskCenterSnapshot.taskPage,
|
|
14169
|
-
backgroundTaskCenterSnapshot.relationshipIndex
|
|
14170
|
-
) + (productUpdateChecking ? 1 : 0);
|
|
14257
|
+
const activityCount = backgroundTaskActivityCount(backgroundTaskCenterSnapshot.taskPage) + (productUpdateChecking ? 1 : 0);
|
|
14171
14258
|
const badge = $("#background-task-count");
|
|
14172
14259
|
badge.textContent = activityCount > 99 ? "99+" : String(activityCount);
|
|
14173
14260
|
badge.classList.toggle("hidden", activityCount === 0);
|
|
@@ -14251,7 +14338,7 @@ function backgroundIndexMarkup(relationshipIndex, error) {
|
|
|
14251
14338
|
const editable = canEditModule("ai-settings");
|
|
14252
14339
|
return `<section class="background-task-section">
|
|
14253
14340
|
<div class="background-task-section-heading">
|
|
14254
|
-
<div><strong>人物关系拼音索引</strong><small
|
|
14341
|
+
<div><strong>人物关系拼音索引</strong><small>打开本窗口时显示当前索引状态</small></div>
|
|
14255
14342
|
<div class="background-index-actions ${editable ? "" : "hidden"}">
|
|
14256
14343
|
<button class="primary-button" type="button" data-background-index-action="sync">同步增量队列</button>
|
|
14257
14344
|
<button class="ghost-button" type="button" data-background-index-action="rebuild">完整重建</button>
|
|
@@ -14322,10 +14409,7 @@ function scheduleBackgroundTaskCenterRefresh() {
|
|
|
14322
14409
|
if (backgroundTaskCenterTimer !== null) window.clearTimeout(backgroundTaskCenterTimer);
|
|
14323
14410
|
backgroundTaskCenterTimer = null;
|
|
14324
14411
|
if (!backgroundTaskCenterWorkId) return;
|
|
14325
|
-
const activityCount = backgroundTaskActivityCount(
|
|
14326
|
-
backgroundTaskCenterSnapshot.taskPage,
|
|
14327
|
-
backgroundTaskCenterSnapshot.relationshipIndex
|
|
14328
|
-
);
|
|
14412
|
+
const activityCount = backgroundTaskActivityCount(backgroundTaskCenterSnapshot.taskPage);
|
|
14329
14413
|
const delay = backgroundTaskPollDelay(activityCount, Boolean($("#background-task-dialog")?.open));
|
|
14330
14414
|
backgroundTaskCenterTimer = window.setTimeout(() => {
|
|
14331
14415
|
backgroundTaskCenterTimer = null;
|
|
@@ -14339,8 +14423,9 @@ async function refreshBackgroundTaskCenter({ announce = true } = {}) {
|
|
|
14339
14423
|
if (backgroundTaskCenterTimer !== null) window.clearTimeout(backgroundTaskCenterTimer);
|
|
14340
14424
|
backgroundTaskCenterTimer = null;
|
|
14341
14425
|
const requestId = ++backgroundTaskCenterRequest;
|
|
14426
|
+
const dialogOpen = Boolean($("#background-task-dialog")?.open);
|
|
14342
14427
|
const readTasks = canReadModule("tasks");
|
|
14343
|
-
const readIndex = canReadModule("ai-settings");
|
|
14428
|
+
const readIndex = dialogOpen && canReadModule("ai-settings");
|
|
14344
14429
|
const [taskResult, indexResult] = await Promise.all([
|
|
14345
14430
|
readTasks
|
|
14346
14431
|
? api(`/api/works/${encodeURIComponent(workId)}/tasks?page=1&limit=30`)
|
|
@@ -15982,6 +16067,7 @@ async function openDialog(title, fields, onSubmit, eyebrow = "新增", options =
|
|
|
15982
16067
|
submit.textContent = options.pendingLabel ?? "处理中…";
|
|
15983
16068
|
try {
|
|
15984
16069
|
commitRelationshipKeywordInputs(form);
|
|
16070
|
+
syncVditorEditorValues(form);
|
|
15985
16071
|
const formData = new FormData(form);
|
|
15986
16072
|
disabledStates = [...form.elements].map((control) => [control, control.disabled]);
|
|
15987
16073
|
disabledStates.forEach(([control]) => {
|
|
@@ -17392,6 +17478,16 @@ function destroyVditorEditor(editor) {
|
|
|
17392
17478
|
if (host) delete host.__vditor;
|
|
17393
17479
|
}
|
|
17394
17480
|
|
|
17481
|
+
function syncVditorEditorValues(container) {
|
|
17482
|
+
// Vditor 的 input 回调有延迟,提交前直接读取正文。
|
|
17483
|
+
container.querySelectorAll("[data-vditor-editor]").forEach((host) => {
|
|
17484
|
+
const valueField = host.parentElement?.querySelector("[data-vditor-value]");
|
|
17485
|
+
const editor = host.__vditor;
|
|
17486
|
+
if (!valueField || valueField.readOnly || typeof editor?.getValue !== "function") return;
|
|
17487
|
+
valueField.value = String(editor.getValue() ?? "");
|
|
17488
|
+
});
|
|
17489
|
+
}
|
|
17490
|
+
|
|
17395
17491
|
function bindVditorEditors(container) {
|
|
17396
17492
|
const editors = [];
|
|
17397
17493
|
container.querySelectorAll("[data-vditor-editor]").forEach((host) => {
|
|
@@ -20373,6 +20469,7 @@ async function showVersions() {
|
|
|
20373
20469
|
}
|
|
20374
20470
|
try {
|
|
20375
20471
|
state.chapter = await api(`/api/chapters/${state.chapter.id}/restore`, { method: "POST", body: { versionNo: Number(button.dataset.restoreVersion) } });
|
|
20472
|
+
chapterContentReadyId = state.chapter.id;
|
|
20376
20473
|
resetChapterDraftLineIds(state.chapter);
|
|
20377
20474
|
lastSavedChapterSnapshot = { chapterId: state.chapter.id, title: state.chapter.title, content: state.chapter.content };
|
|
20378
20475
|
$("#chapter-title").value = state.chapter.title;
|
|
@@ -21456,8 +21553,8 @@ $("#login-form").addEventListener("submit", async (event) => {
|
|
|
21456
21553
|
window.location.reload();
|
|
21457
21554
|
} catch (error) {
|
|
21458
21555
|
$("#auth-error").textContent = error.message;
|
|
21459
|
-
//
|
|
21460
|
-
if (!$("#login-captcha-image").hidden) refreshAuthCaptcha("login").catch(() => {});
|
|
21556
|
+
// 答案错误时保留同一张图;过期、已核销或其他失败才换一张
|
|
21557
|
+
if (error?.code !== "CAPTCHA_INCORRECT" && !$("#login-captcha-image").hidden) refreshAuthCaptcha("login").catch(() => {});
|
|
21461
21558
|
}
|
|
21462
21559
|
});
|
|
21463
21560
|
$("#register-form").addEventListener("submit", async (event) => {
|
|
@@ -21485,8 +21582,8 @@ $("#register-form").addEventListener("submit", async (event) => {
|
|
|
21485
21582
|
window.location.reload();
|
|
21486
21583
|
} catch (error) {
|
|
21487
21584
|
$("#auth-error").textContent = error.message;
|
|
21488
|
-
//
|
|
21489
|
-
if (!$("#register-captcha-image").hidden) refreshAuthCaptcha("register").catch(() => {});
|
|
21585
|
+
// 答案错误时保留同一张图;过期、已核销或其他失败才换一张
|
|
21586
|
+
if (error?.code !== "CAPTCHA_INCORRECT" && !$("#register-captcha-image").hidden) refreshAuthCaptcha("register").catch(() => {});
|
|
21490
21587
|
}
|
|
21491
21588
|
});
|
|
21492
21589
|
$("#settings-return").addEventListener("click", () => returnFromSettings().catch((error) => toast(error.message, "error")));
|
package/dist/public/index.html
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<link rel="icon" href="/icon.svg?v=20260712" type="image/svg+xml">
|
|
11
11
|
<link rel="manifest" href="/site.webmanifest">
|
|
12
12
|
<link rel="stylesheet" href="/mobile-app.css?v=20260922-mobile-offline-v2">
|
|
13
|
-
<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=ai-composer-compact-controls-v1&feature=ai-context-meter-ring-only-v2&feature=ai-context-cache-hit-v1&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-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-v5&feature=ai-model-config-dialog-v1&feature=system-prompt-override-v3&feature=entity-editor-back-icon-v1&feature=toast-stack-v1&feature=chapter-header-compact-v4&feature=ai-attachment-disabled-v1&feature=ai-prose-acceptance-removed-v1&feature=chapter-line-scroll-bind-v1&feature=writing-goal-module-navigation-v2&feature=invite-registration-v1&feature=ai-send-mode-v2&feature=character-attributes-prune-v1&feature=chapter-directory-click-priority-v1&feature=annotation-bubble-visibility-v1&feature=chapter-auto-title-menu-v1&feature=chapter-insert-menu-v1">
|
|
13
|
+
<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=ai-composer-compact-controls-v1&feature=ai-context-meter-ring-only-v2&feature=ai-context-cache-hit-v1&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-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-v5&feature=ai-model-config-dialog-v1&feature=system-prompt-override-v3&feature=entity-editor-back-icon-v1&feature=toast-stack-v1&feature=chapter-header-compact-v4&feature=ai-attachment-disabled-v1&feature=ai-prose-acceptance-removed-v1&feature=chapter-line-scroll-bind-v1&feature=writing-goal-module-navigation-v2&feature=invite-registration-v1&feature=ai-send-mode-v2&feature=character-attributes-prune-v1&feature=chapter-directory-click-priority-v1&feature=annotation-bubble-visibility-v1&feature=chapter-auto-title-menu-v1&feature=chapter-insert-menu-v1&feature=chapter-switch-skeleton-v1">
|
|
14
14
|
</head>
|
|
15
15
|
<body class="auth-pending">
|
|
16
16
|
<section id="auth-view" class="auth-view hidden" aria-labelledby="auth-title">
|
|
@@ -330,6 +330,16 @@
|
|
|
330
330
|
<div id="chapter-editor-scroll" class="chapter-editor-scroll">
|
|
331
331
|
<aside id="chapter-line-numbers" class="chapter-line-numbers" aria-label="正文行号,可拖拽引用多行"><div id="chapter-line-numbers-inner"></div></aside>
|
|
332
332
|
<textarea id="chapter-content" class="chapter-content" aria-label="章节正文" placeholder="在这里开始你的故事……"></textarea>
|
|
333
|
+
<div id="chapter-content-skeleton" class="chapter-content-skeleton hidden" role="status" aria-live="polite" aria-busy="false" aria-label="正在载入正文">
|
|
334
|
+
<span class="chapter-content-skeleton-line"></span>
|
|
335
|
+
<span class="chapter-content-skeleton-line"></span>
|
|
336
|
+
<span class="chapter-content-skeleton-line"></span>
|
|
337
|
+
<span class="chapter-content-skeleton-line"></span>
|
|
338
|
+
<span class="chapter-content-skeleton-line"></span>
|
|
339
|
+
<span class="chapter-content-skeleton-line"></span>
|
|
340
|
+
<span class="chapter-content-skeleton-line"></span>
|
|
341
|
+
<span class="chapter-content-skeleton-line"></span>
|
|
342
|
+
</div>
|
|
333
343
|
<div id="chapter-whitespace-overlay" class="chapter-whitespace-overlay is-visible" aria-hidden="true"><div id="chapter-whitespace-inner"></div></div>
|
|
334
344
|
</div>
|
|
335
345
|
<div id="chapter-line-measure" class="chapter-line-measure" aria-hidden="true"></div>
|
|
@@ -1459,7 +1469,6 @@
|
|
|
1459
1469
|
</dialog>
|
|
1460
1470
|
|
|
1461
1471
|
<div id="auth-loading" class="auth-loading" role="status" aria-label="正在载入工作台"></div>
|
|
1462
|
-
<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-context-meter-ring-only-v1&feature=ai-context-cache-hit-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=ai-all-message-references-v2&feature=ai-question-render-recovery-v3&feature=setting-category-preservation-v1&feature=toast-stack-v1&feature=toast-stack-label-v2&feature=agent-tool-limits-300-v1&feature=server-dev-logo-v1&feature=chapter-directory-ai-reference-v3&feature=ai-error-origin-v1&feature=ai-stream-render-performance-v2&feature=ai-attachment-disabled-v1&feature=ai-prose-acceptance-removed-v1&feature=ai-inline-message-references-v1&feature=ai-write-plan-status-sync-v1&feature=writing-goal-module-navigation-v2&feature=chapter-line-scroll-bind-v1&feature=invite-registration-v1&feature=ai-send-mode-v2&feature=character-attributes-prune-v1&feature=annotation-note-limit-v1&feature=chapter-directory-performance-v2&feature=chapter-directory-click-priority-v1&feature=mobile-offline-runtime-v6&feature=ai-title-first-turn-v1&feature=ai-optimistic-send-v1&feature=chapter-auto-title-menu-v1&feature=chapter-insert-menu-v1"></script>
|
|
1463
|
-
|
|
1472
|
+
<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-context-meter-ring-only-v1&feature=ai-context-cache-hit-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=ai-all-message-references-v2&feature=ai-question-render-recovery-v3&feature=setting-category-preservation-v1&feature=toast-stack-v1&feature=toast-stack-label-v2&feature=agent-tool-limits-300-v1&feature=server-dev-logo-v1&feature=chapter-directory-ai-reference-v3&feature=ai-error-origin-v1&feature=ai-stream-render-performance-v2&feature=ai-attachment-disabled-v1&feature=ai-prose-acceptance-removed-v1&feature=ai-inline-message-references-v1&feature=ai-write-plan-status-sync-v1&feature=writing-goal-module-navigation-v2&feature=chapter-line-scroll-bind-v1&feature=invite-registration-v1&feature=ai-send-mode-v2&feature=character-attributes-prune-v1&feature=annotation-note-limit-v1&feature=chapter-directory-performance-v2&feature=chapter-directory-click-priority-v1&feature=chapter-switch-skeleton-v1&feature=mobile-offline-runtime-v6&feature=ai-title-first-turn-v1&feature=ai-title-xml-v1&feature=ai-optimistic-send-v1&feature=chapter-auto-title-menu-v1&feature=chapter-insert-menu-v1&feature=captcha-retry-same-image-v1&feature=relationship-index-dialog-poll-v1&feature=draft-editor-transition-v2&feature=vditor-submit-sync-v1"></script>
|
|
1464
1473
|
</body>
|
|
1465
1474
|
</html>
|