@musnows/scriverse 1.0.11 → 1.1.0
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/README.en.md +6 -3
- package/README.md +6 -3
- package/dist/ai-stream-steer.js +96 -0
- package/dist/ai-stream-steer.js.map +1 -0
- package/dist/ai-write-plans.js +44 -38
- package/dist/ai-write-plans.js.map +1 -1
- package/dist/ai.js +241 -128
- package/dist/ai.js.map +1 -1
- package/dist/app.js +134 -14
- package/dist/app.js.map +1 -1
- package/dist/attachment-storage.js +3 -0
- package/dist/attachment-storage.js.map +1 -1
- package/dist/chapter-annotation-note.js +14 -0
- package/dist/chapter-annotation-note.js.map +1 -0
- package/dist/character-structured-fields.js +7 -0
- package/dist/character-structured-fields.js.map +1 -0
- package/dist/cli-contract.js +1 -1
- package/dist/cli-contract.js.map +1 -1
- package/dist/database.js +29 -2
- package/dist/database.js.map +1 -1
- package/dist/im.js +2 -1
- package/dist/im.js.map +1 -1
- package/dist/public/ai-prompt-keyboard.js +5 -1
- package/dist/public/ai-prompt-queue.js +226 -0
- package/dist/public/ai-send-mode.js +31 -0
- package/dist/public/app.js +689 -74
- package/dist/public/chapter-editor-scroll.d.ts +37 -0
- package/dist/public/chapter-editor-scroll.js +52 -0
- package/dist/public/character-profile.d.ts +7 -0
- package/dist/public/character-profile.js +123 -5
- package/dist/public/index.html +31 -10
- package/dist/public/styles.css +75 -8
- package/dist/security.js +22 -3
- package/dist/security.js.map +1 -1
- package/dist/server-runtime.js +2 -0
- package/dist/server-runtime.js.map +1 -1
- package/dist/store.js +7 -6
- package/dist/store.js.map +1 -1
- package/dist/user-auth.js +125 -15
- package/dist/user-auth.js.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type ChapterEditorScrollMetrics = {
|
|
2
|
+
scrollTop: number;
|
|
3
|
+
scrollLeft: number;
|
|
4
|
+
clientHeight: number;
|
|
5
|
+
clientWidth: number;
|
|
6
|
+
scrollHeight: number;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export type ChapterLineVirtualWindow = {
|
|
10
|
+
start: number;
|
|
11
|
+
end: number;
|
|
12
|
+
lineCount: number;
|
|
13
|
+
top: number;
|
|
14
|
+
bottom: number;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export function readChapterEditorScrollMetrics(scroller?: { scrollTop?: number; scrollLeft?: number; clientHeight?: number; clientWidth?: number; scrollHeight?: number } | null): ChapterEditorScrollMetrics;
|
|
18
|
+
|
|
19
|
+
export function calculateChapterEditorContentHeight(input?: {
|
|
20
|
+
measureHeight?: number;
|
|
21
|
+
paddingTop?: number;
|
|
22
|
+
paddingBottom?: number;
|
|
23
|
+
viewportHeight?: number;
|
|
24
|
+
}): number;
|
|
25
|
+
|
|
26
|
+
export function needsChapterLineVirtualWindowRefresh(
|
|
27
|
+
virtualWindow?: ChapterLineVirtualWindow | null,
|
|
28
|
+
metrics?: Pick<ChapterEditorScrollMetrics, "scrollTop" | "clientHeight"> | null,
|
|
29
|
+
bufferRatio?: number
|
|
30
|
+
): boolean;
|
|
31
|
+
|
|
32
|
+
export function chapterLineNumberLayerTransform(): "none";
|
|
33
|
+
|
|
34
|
+
export function transferNestedEditorScroll(
|
|
35
|
+
source?: { scrollTop?: number; scrollLeft?: number } | null,
|
|
36
|
+
destination?: { scrollTop?: number; scrollLeft?: number } | null
|
|
37
|
+
): { transferredTop: number; transferredLeft: number };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** 正文行号与文字共用同一滚动容器,行号层不再独立滚动。 */
|
|
2
|
+
|
|
3
|
+
export function readChapterEditorScrollMetrics(scroller) {
|
|
4
|
+
return {
|
|
5
|
+
scrollTop: Math.max(0, Number(scroller?.scrollTop) || 0),
|
|
6
|
+
scrollLeft: Number(scroller?.scrollLeft) || 0,
|
|
7
|
+
clientHeight: Math.max(0, Number(scroller?.clientHeight) || 0),
|
|
8
|
+
clientWidth: Math.max(0, Number(scroller?.clientWidth) || 0),
|
|
9
|
+
scrollHeight: Math.max(0, Number(scroller?.scrollHeight) || 0)
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function calculateChapterEditorContentHeight({
|
|
14
|
+
measureHeight,
|
|
15
|
+
paddingTop,
|
|
16
|
+
paddingBottom,
|
|
17
|
+
viewportHeight
|
|
18
|
+
} = {}) {
|
|
19
|
+
const contentHeight = Math.max(0, Number(measureHeight) || 0)
|
|
20
|
+
+ Math.max(0, Number(paddingTop) || 0)
|
|
21
|
+
+ Math.max(0, Number(paddingBottom) || 0);
|
|
22
|
+
return Math.max(contentHeight, Math.max(0, Number(viewportHeight) || 0));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function needsChapterLineVirtualWindowRefresh(virtualWindow, metrics, bufferRatio = 0.35) {
|
|
26
|
+
if (!virtualWindow) return false;
|
|
27
|
+
const scrollTop = Math.max(0, Number(metrics?.scrollTop) || 0);
|
|
28
|
+
const clientHeight = Math.max(0, Number(metrics?.clientHeight) || 0);
|
|
29
|
+
const buffer = clientHeight * (Number.isFinite(Number(bufferRatio)) ? Number(bufferRatio) : 0.35);
|
|
30
|
+
const viewportBottom = scrollTop + clientHeight;
|
|
31
|
+
const needsPreviousLines = virtualWindow.start > 0 && scrollTop < virtualWindow.top + buffer;
|
|
32
|
+
const needsNextLines = virtualWindow.end < virtualWindow.lineCount
|
|
33
|
+
&& viewportBottom > virtualWindow.bottom - buffer;
|
|
34
|
+
return needsPreviousLines || needsNextLines;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function chapterLineNumberLayerTransform() {
|
|
38
|
+
return "none";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function transferNestedEditorScroll(source, destination) {
|
|
42
|
+
const transferredTop = Number(source?.scrollTop) || 0;
|
|
43
|
+
const transferredLeft = Number(source?.scrollLeft) || 0;
|
|
44
|
+
if (!source || !destination || (transferredTop === 0 && transferredLeft === 0)) {
|
|
45
|
+
return { transferredTop: 0, transferredLeft: 0 };
|
|
46
|
+
}
|
|
47
|
+
destination.scrollTop += transferredTop;
|
|
48
|
+
destination.scrollLeft += transferredLeft;
|
|
49
|
+
source.scrollTop = 0;
|
|
50
|
+
source.scrollLeft = 0;
|
|
51
|
+
return { transferredTop, transferredLeft };
|
|
52
|
+
}
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
export type CharacterDetail = { label: string; value: string };
|
|
2
2
|
export type CharacterSection = { title: string; content: string };
|
|
3
|
+
export type CharacterAttributes = {
|
|
4
|
+
identity?: string;
|
|
5
|
+
species?: string;
|
|
6
|
+
details?: CharacterDetail[];
|
|
7
|
+
};
|
|
3
8
|
|
|
4
9
|
export function normalizeCharacterDetails(value: unknown): CharacterDetail[];
|
|
10
|
+
export function normalizeCharacterAttributes(value: unknown): CharacterAttributes;
|
|
11
|
+
export function normalizeCharacterState(value: unknown): Record<string, unknown>;
|
|
5
12
|
export function normalizeCharacterSections(value: unknown): CharacterSection[];
|
|
6
13
|
export function buildCharacterDetails(labels: unknown[], values: unknown[]): CharacterDetail[];
|
|
7
14
|
export function buildCharacterSections(titles: unknown[], contents: unknown[]): CharacterSection[];
|
|
@@ -2,12 +2,130 @@ function text(value) {
|
|
|
2
2
|
return typeof value === "string" ? value.trim() : "";
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
+
const FORBIDDEN_OBJECT_KEYS = new Set(["__proto__", "constructor", "prototype"]);
|
|
6
|
+
const IDENTITY_ALIAS_KEYS = new Set(["identity", "身份", "身份定位", "定位", "身份与定位", "身份简介"]);
|
|
7
|
+
const MAX_ATTRIBUTE_DETAILS = 200;
|
|
8
|
+
const MAX_ATTRIBUTE_LABEL = 200;
|
|
9
|
+
const MAX_ATTRIBUTE_VALUE = 20_000;
|
|
10
|
+
const MAX_ATTRIBUTE_IDENTITY = 20_000;
|
|
11
|
+
const MAX_ATTRIBUTE_SPECIES = 200;
|
|
12
|
+
|
|
13
|
+
function isPlainObject(value) {
|
|
14
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function clipText(value, maximum) {
|
|
18
|
+
return value.length <= maximum ? value : value.slice(0, maximum);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function scalarText(value) {
|
|
22
|
+
if (typeof value === "string") return value.trim();
|
|
23
|
+
if (typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
24
|
+
if (typeof value === "boolean") return value ? "true" : "false";
|
|
25
|
+
return "";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function normalizeDetailLabel(value) {
|
|
29
|
+
return clipText(text(value).replace(/[\s·.•。::、,,;;]+$/u, ""), MAX_ATTRIBUTE_LABEL);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function addCharacterDetail(details, seen, label, rawValue) {
|
|
33
|
+
const previewKey = normalizeDetailLabel(label).toLocaleLowerCase("zh-CN");
|
|
34
|
+
if (details.length >= MAX_ATTRIBUTE_DETAILS && !seen.has(previewKey)) return;
|
|
35
|
+
const normalizedLabel = normalizeDetailLabel(label);
|
|
36
|
+
const normalizedValue = clipText(scalarText(rawValue), MAX_ATTRIBUTE_VALUE);
|
|
37
|
+
if (!normalizedLabel || !normalizedValue || FORBIDDEN_OBJECT_KEYS.has(normalizedLabel)) return;
|
|
38
|
+
const key = normalizedLabel.toLocaleLowerCase("zh-CN");
|
|
39
|
+
if (seen.has(key)) {
|
|
40
|
+
const index = details.findIndex((item) => item.label.toLocaleLowerCase("zh-CN") === key);
|
|
41
|
+
if (index >= 0) details[index] = { label: normalizedLabel, value: normalizedValue };
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
seen.add(key);
|
|
45
|
+
details.push({ label: normalizedLabel, value: normalizedValue });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function addCharacterDetailsFromUnknown(details, seen, value) {
|
|
49
|
+
if (Array.isArray(value)) {
|
|
50
|
+
for (const item of value) {
|
|
51
|
+
if (isPlainObject(item)) addCharacterDetail(details, seen, item.label, item.value);
|
|
52
|
+
}
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (!isPlainObject(value)) return;
|
|
56
|
+
if ("label" in value || "value" in value) {
|
|
57
|
+
addCharacterDetail(details, seen, value.label, value.value);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
for (const [label, item] of Object.entries(value)) addCharacterDetail(details, seen, label, item);
|
|
61
|
+
}
|
|
62
|
+
|
|
5
63
|
export function normalizeCharacterDetails(value) {
|
|
6
|
-
if (
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
64
|
+
if (Array.isArray(value)) {
|
|
65
|
+
return value.map((item) => ({
|
|
66
|
+
label: text(item?.label),
|
|
67
|
+
value: text(item?.value)
|
|
68
|
+
})).filter((item) => item.label && item.value);
|
|
69
|
+
}
|
|
70
|
+
if (!isPlainObject(value)) return [];
|
|
71
|
+
const details = [];
|
|
72
|
+
const seen = new Set();
|
|
73
|
+
addCharacterDetailsFromUnknown(details, seen, value);
|
|
74
|
+
return details;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** 把模型混写的自由对象剪枝为编辑器可维护的 identity / details。 */
|
|
78
|
+
export function normalizeCharacterAttributes(value) {
|
|
79
|
+
if (!isPlainObject(value)) return {};
|
|
80
|
+
const details = [];
|
|
81
|
+
const seen = new Set();
|
|
82
|
+
let identity = clipText(scalarText(value.identity), MAX_ATTRIBUTE_IDENTITY);
|
|
83
|
+
const species = clipText(scalarText(value.species), MAX_ATTRIBUTE_SPECIES);
|
|
84
|
+
|
|
85
|
+
for (const [key, item] of Object.entries(value)) {
|
|
86
|
+
if (FORBIDDEN_OBJECT_KEYS.has(key) || key === "details" || key === "species" || key === "identity") continue;
|
|
87
|
+
if (IDENTITY_ALIAS_KEYS.has(key)) {
|
|
88
|
+
const aliasValue = clipText(scalarText(item), MAX_ATTRIBUTE_IDENTITY);
|
|
89
|
+
if (!identity && aliasValue) identity = aliasValue;
|
|
90
|
+
else if (aliasValue && aliasValue !== identity) addCharacterDetail(details, seen, key, aliasValue);
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
if (Array.isArray(item)) {
|
|
94
|
+
if (item.every((entry) => isPlainObject(entry))) addCharacterDetailsFromUnknown(details, seen, item);
|
|
95
|
+
else if (item.every((entry) => scalarText(entry))) addCharacterDetail(details, seen, key, item.map((entry) => scalarText(entry)).filter(Boolean).join("、"));
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (isPlainObject(item)) {
|
|
99
|
+
addCharacterDetailsFromUnknown(details, seen, item);
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
addCharacterDetail(details, seen, key, item);
|
|
103
|
+
}
|
|
104
|
+
addCharacterDetailsFromUnknown(details, seen, value.details);
|
|
105
|
+
|
|
106
|
+
const result = {};
|
|
107
|
+
if (identity) result.identity = identity;
|
|
108
|
+
if (species) result.species = species;
|
|
109
|
+
if (details.length) result.details = details;
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function normalizeCharacterState(value) {
|
|
114
|
+
if (!isPlainObject(value)) return {};
|
|
115
|
+
const state = {};
|
|
116
|
+
for (const [key, item] of Object.entries(value)) {
|
|
117
|
+
const label = text(key);
|
|
118
|
+
if (!label || FORBIDDEN_OBJECT_KEYS.has(label)) continue;
|
|
119
|
+
if (item === undefined || item === null) continue;
|
|
120
|
+
if (typeof item === "string") {
|
|
121
|
+
const trimmed = item.trim();
|
|
122
|
+
if (!trimmed) continue;
|
|
123
|
+
state[label] = trimmed;
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
state[label] = item;
|
|
127
|
+
}
|
|
128
|
+
return state;
|
|
11
129
|
}
|
|
12
130
|
|
|
13
131
|
export function normalizeCharacterSections(value) {
|
package/dist/public/index.html
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<script src="/theme-init.js?v=20260827-reader-prefetch-v1"></script>
|
|
10
10
|
<link rel="icon" href="/icon.svg?v=20260712" type="image/svg+xml">
|
|
11
11
|
<link rel="manifest" href="/site.webmanifest">
|
|
12
|
-
<link rel="stylesheet" href="/styles.css?v=20260816-task-scope-volume-collapse-v2&feature=ai-tool-call-copy-feedback-v2&feature=ai-send-control-v3&feature=character-gender-v1&feature=character-filter-state-v1&feature=relationship-canvas-scale-v1&feature=relationship-table-scroll-v1&feature=galaxy-compact-controls-v2&feature=galaxy-motion-mode-v2&feature=chapter-search-replace-v3&feature=task-auto-run-ring-center-v3&feature=character-relationship-delete-v1&feature=ai-assistant-workspace-v2&feature=mobile-module-tab-position-v1&feature=volume-detail-icon-v1&feature=editor-actions-flow-v1&feature=reader-controls-subpanel-v1&feature=reader-focus-ring-v1&feature=ai-message-actions-v1&feature=assistant-responsive-navigation-v2&feature=ai-composer-square-controls-v2&feature=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">
|
|
12
|
+
<link rel="stylesheet" href="/styles.css?v=20260816-task-scope-volume-collapse-v2&feature=ai-tool-call-copy-feedback-v2&feature=ai-send-control-v3&feature=character-gender-v1&feature=character-filter-state-v1&feature=relationship-canvas-scale-v1&feature=relationship-table-scroll-v1&feature=galaxy-compact-controls-v2&feature=galaxy-motion-mode-v2&feature=chapter-search-replace-v3&feature=task-auto-run-ring-center-v3&feature=character-relationship-delete-v1&feature=ai-assistant-workspace-v2&feature=mobile-module-tab-position-v1&feature=volume-detail-icon-v1&feature=editor-actions-flow-v1&feature=reader-controls-subpanel-v1&feature=reader-focus-ring-v1&feature=ai-message-actions-v1&feature=assistant-responsive-navigation-v2&feature=ai-composer-square-controls-v2&feature=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">
|
|
13
13
|
</head>
|
|
14
14
|
<body class="auth-pending">
|
|
15
15
|
<section id="auth-view" class="auth-view hidden" aria-labelledby="auth-title">
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
<form id="register-form" class="auth-form hidden" method="post" action="/api/auth/register">
|
|
41
41
|
<label>用户名<input name="username" autocomplete="username" minlength="3" maxlength="40" pattern="[A-Za-z0-9_.\-\u4e00-\u9fff]+" required></label>
|
|
42
42
|
<label id="register-setup-token-field" class="hidden">初始化令牌<input name="setupToken" type="password" autocomplete="off" minlength="32" maxlength="500" aria-describedby="register-setup-token-hint"><small id="register-setup-token-hint">请输入服务端 APP_SETUP_TOKEN 的值。</small></label>
|
|
43
|
+
<label id="register-invite-code-field" class="hidden">邀请码<input name="inviteCode" type="text" autocomplete="off" maxlength="32" spellcheck="false" autocapitalize="characters" aria-describedby="register-invite-code-hint"><small id="register-invite-code-hint">请输入系统管理员提供的一次性邀请码。</small></label>
|
|
43
44
|
<label>密码<span class="password-field"><input id="register-password" name="password" type="password" autocomplete="new-password" minlength="10" maxlength="200" required><button class="password-toggle" type="button" data-password-toggle="register-password" aria-label="显示密码" aria-pressed="false" title="显示密码"><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M2.5 12s3.3-5.5 9.5-5.5S21.5 12 21.5 12 18.2 17.5 12 17.5 2.5 12 2.5 12Z"/><circle cx="12" cy="12" r="2.8"/></svg></button></span></label>
|
|
44
45
|
<label>确认密码<span class="password-field"><input id="register-password-confirmation" name="passwordConfirmation" type="password" autocomplete="new-password" minlength="10" maxlength="200" required><button class="password-toggle" type="button" data-password-toggle="register-password-confirmation" aria-label="显示确认密码" aria-pressed="false" title="显示确认密码"><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M2.5 12s3.3-5.5 9.5-5.5S21.5 12 21.5 12 18.2 17.5 12 17.5 2.5 12 2.5 12Z"/><circle cx="12" cy="12" r="2.8"/></svg></button></span></label>
|
|
45
46
|
<div class="auth-captcha">
|
|
@@ -136,7 +137,6 @@
|
|
|
136
137
|
<button type="button" data-module="relationships"><svg class="nav-icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><path d="m8.59 13.51 6.83 3.98"/><path d="m15.41 6.51-6.82 3.98"/></svg>关系</button>
|
|
137
138
|
<button type="button" data-module="races"><svg class="nav-icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="11" cy="4" r="2"/><circle cx="18" cy="8" r="2"/><circle cx="20" cy="16" r="2"/><path d="M9 10a5 5 0 0 1 5 5v3.5a3.5 3.5 0 0 1-6.84 1.045Q6.52 17.48 4.46 16.84A3.5 3.5 0 0 1 5.5 10Z"/></svg>种族</button>
|
|
138
139
|
<button class="ai-analysis-entry" type="button" data-module="tasks"><svg class="nav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"/><path d="M20 3v4"/><path d="M22 5h-4"/><path d="M4 17v2"/><path d="M5 18H3"/></svg>AI 分析</button>
|
|
139
|
-
<button id="writing-progress-button" type="button"><svg class="nav-icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="8"/><circle cx="12" cy="12" r="3"/><path d="M12 2v2M12 20v2M2 12h2M20 12h2"/></svg>写作目标</button>
|
|
140
140
|
<button id="module-more-button" type="button" aria-expanded="false"><svg class="nav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg><span class="nav-label">更多</span></button>
|
|
141
141
|
<button id="ai-assistant-entry" class="module-nav-secondary hidden ai-assistant-entry" type="button" aria-controls="ai-panel" aria-expanded="false"><svg class="nav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 5.25a3.25 3.25 0 0 0-5.95 1.82A3.74 3.74 0 0 0 4.7 13.5a3.25 3.25 0 0 0 4.55 4.53A3.6 3.6 0 0 0 12 19.5"></path><path d="M12 5.25a3.25 3.25 0 0 1 5.95 1.82 3.74 3.74 0 0 1 1.35 6.43 3.25 3.25 0 0 1-4.55 4.53A3.6 3.6 0 0 1 12 19.5"></path><path d="M12 5.25v14.25"></path><path d="M8 9.1c1.1.1 2 .9 2.25 1.95"></path><path d="M16 9.1c-1.1.1-2 .9-2.25 1.95"></path></svg>创作助手</button>
|
|
142
142
|
<button id="reader-open-button" class="module-nav-secondary hidden" type="button" aria-label="打开沉浸式阅读预览" title="阅读预览"><svg class="nav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M3 5.5A2.5 2.5 0 0 1 5.5 3H11v16H5.5A2.5 2.5 0 0 0 3 21.5Z"/><path d="M21 5.5A2.5 2.5 0 0 0 18.5 3H13v16h5.5a2.5 2.5 0 0 1 2.5 2.5Z"/></svg>阅读预览</button>
|
|
@@ -145,6 +145,7 @@
|
|
|
145
145
|
<button class="module-nav-secondary hidden" type="button" data-module="reviews"><svg class="nav-icon" viewBox="0 0 24 24" aria-hidden="true"><rect width="8" height="4" x="8" y="2" rx="1" ry="1"/><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><path d="m9 14 2 2 4-4"/></svg>审核</button>
|
|
146
146
|
<button class="module-nav-secondary hidden" type="button" data-module="ai-settings"><svg class="nav-icon" viewBox="0 0 24 24" aria-hidden="true"><rect width="16" height="16" x="4" y="4" rx="2"/><rect width="6" height="6" x="9" y="9" rx="1"/><path d="M15 2v2"/><path d="M15 20v2"/><path d="M2 15h2"/><path d="M2 9h2"/><path d="M20 15h2"/><path d="M20 9h2"/><path d="M9 2v2"/><path d="M9 20v2"/></svg>AI 设置</button>
|
|
147
147
|
<button class="module-nav-secondary hidden" type="button" data-work-settings><svg class="nav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.09a2 2 0 0 1 1 1.74v.5a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.38a2 2 0 0 0-.73-2.73l-.15-.09a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2Z"/><circle cx="12" cy="12" r="3"/></svg>作品设置</button>
|
|
148
|
+
<button id="writing-progress-button" class="module-nav-secondary hidden" type="button"><svg class="nav-icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="8"/><circle cx="12" cy="12" r="3"/><path d="M12 2v2M12 20v2M2 12h2M20 12h2"/></svg><span class="nav-label">写作目标</span></button>
|
|
148
149
|
</nav>
|
|
149
150
|
<div class="panel-heading">
|
|
150
151
|
<span class="panel-heading-label"><span class="panel-heading-label-full">作品目录</span><span class="panel-heading-label-compact">目录</span></span>
|
|
@@ -240,7 +241,7 @@
|
|
|
240
241
|
<div class="settings-hub-grid">
|
|
241
242
|
<button id="platform-ai-button" class="settings-hub-card hidden" type="button" data-settings-action="ai"><span class="settings-card-mark">AI</span><strong>AI 管理</strong><small>供应商、模型、上下文与全局提示词</small></button>
|
|
242
243
|
<button id="platform-usage-button" class="settings-hub-card hidden" type="button"><span class="settings-card-mark">T</span><strong>Token 用量</strong><small>总消耗、缓存命中率、每日网格与作品明细</small></button>
|
|
243
|
-
<button id="user-management-button" class="settings-hub-card hidden" type="button"><span class="settings-card-mark">人</span><strong>用户管理</strong><small
|
|
244
|
+
<button id="user-management-button" class="settings-hub-card hidden" type="button"><span class="settings-card-mark">人</span><strong>用户管理</strong><small>管理员、普通用户、邀请码与账户状态</small></button>
|
|
244
245
|
<button id="admin-ai-conversations-button" class="settings-hub-card hidden" type="button"><span class="settings-card-mark">话</span><strong>Chat 对话</strong><small>查看所有作品、所有用户的对话记录</small></button>
|
|
245
246
|
<button id="platform-ui-settings-button" class="settings-hub-card hidden" type="button"><span class="settings-card-mark">界</span><strong>界面与分页</strong><small>设置通知位置、银河图性能及各模块的单页数量</small></button>
|
|
246
247
|
<button id="s3-backup-button" class="settings-hub-card hidden" type="button"><span class="settings-card-mark">S3</span><strong>S3 备份</strong><small>将整个系统的数据库和图片同步到多个目标</small></button>
|
|
@@ -324,10 +325,12 @@
|
|
|
324
325
|
</dl>
|
|
325
326
|
</section>
|
|
326
327
|
<div class="editor-body">
|
|
327
|
-
<div class="chapter-editor-frame">
|
|
328
|
-
<
|
|
329
|
-
|
|
330
|
-
|
|
328
|
+
<div id="chapter-editor-frame" class="chapter-editor-frame">
|
|
329
|
+
<div id="chapter-editor-scroll" class="chapter-editor-scroll">
|
|
330
|
+
<aside id="chapter-line-numbers" class="chapter-line-numbers" aria-label="正文行号,可拖拽引用多行"><div id="chapter-line-numbers-inner"></div></aside>
|
|
331
|
+
<textarea id="chapter-content" class="chapter-content" aria-label="章节正文" placeholder="在这里开始你的故事……"></textarea>
|
|
332
|
+
<div id="chapter-whitespace-overlay" class="chapter-whitespace-overlay is-visible" aria-hidden="true"><div id="chapter-whitespace-inner"></div></div>
|
|
333
|
+
</div>
|
|
331
334
|
<div id="chapter-line-measure" class="chapter-line-measure" aria-hidden="true"></div>
|
|
332
335
|
</div>
|
|
333
336
|
</div>
|
|
@@ -402,7 +405,10 @@
|
|
|
402
405
|
<div><strong id="ai-context-warning-title">对话上下文过长</strong><p id="ai-context-warning-message">当前对话上下文过长,是否进行压缩?不压缩可能会导致后续请求失败</p></div>
|
|
403
406
|
<div><button id="ai-context-compact" type="button">压缩</button><button id="ai-context-dismiss" type="button">忽略</button><button id="ai-context-new-conversation" type="button">新开对话</button></div>
|
|
404
407
|
</section>
|
|
405
|
-
|
|
408
|
+
<section id="ai-prompt-queue" class="ai-prompt-queue hidden" aria-label="排队 Prompt">
|
|
409
|
+
<ul id="ai-prompt-queue-list" class="ai-prompt-queue-list" aria-label="待发送的 Prompt"></ul>
|
|
410
|
+
</section>
|
|
411
|
+
<div class="prompt-options">
|
|
406
412
|
<select id="ai-task" aria-label="对话模式">
|
|
407
413
|
<option value="chat">问答</option>
|
|
408
414
|
<option value="roleplay">角色扮演</option>
|
|
@@ -418,6 +424,10 @@
|
|
|
418
424
|
<select id="ai-roleplay-character" class="ai-roleplay-character hidden" aria-label="角色扮演角色卡">
|
|
419
425
|
<option value="">选择角色卡</option>
|
|
420
426
|
</select>
|
|
427
|
+
<select id="ai-send-mode" aria-label="发送方式">
|
|
428
|
+
<option value="queue">排队发送</option>
|
|
429
|
+
<option value="steer">引导发送</option>
|
|
430
|
+
</select>
|
|
421
431
|
<select id="ai-roleplay-user-character" class="ai-roleplay-character ai-roleplay-user-character hidden" aria-label="我扮演的角色">
|
|
422
432
|
<option value="">选择我的角色(可选)</option>
|
|
423
433
|
</select>
|
|
@@ -437,7 +447,7 @@
|
|
|
437
447
|
<button id="ai-scene-button" class="ai-scene-button hidden" type="button" aria-label="旁白与场景" title="旁白与场景" aria-expanded="false" aria-controls="ai-scene-panel"><svg class="ai-scene-button-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><rect x="4.5" y="6.5" width="15" height="13" rx="1.5"></rect><path d="M8 10.5h8M8 14h5.5"></path></svg></button>
|
|
438
448
|
</div>
|
|
439
449
|
<input id="ai-attachment-input" class="ai-attachment-input" type="file" accept="image/png,image/jpeg,.jpg,.jpeg" multiple aria-label="选择图片附件">
|
|
440
|
-
<div id="ai-prompt" class="ai-prompt" contenteditable="true" role="textbox" aria-multiline="true" aria-autocomplete="list" aria-controls="ai-mention-menu" aria-haspopup="listbox" aria-expanded="false" aria-keyshortcuts="Enter" title="Enter
|
|
450
|
+
<div id="ai-prompt" class="ai-prompt" contenteditable="true" role="textbox" aria-multiline="true" aria-autocomplete="list" aria-controls="ai-mention-menu" aria-haspopup="listbox" aria-expanded="false" aria-keyshortcuts="Enter" title="Enter 按策略栏发送方式发送,Shift+Enter 换行" data-placeholder="告诉 AI 你想讨论或修改什么……"></div>
|
|
441
451
|
<div id="ai-mention-menu" class="ai-mention-menu hidden" role="listbox" aria-label="引用角色、设定、章节或上下文能力"></div>
|
|
442
452
|
<div class="prompt-composer-actions">
|
|
443
453
|
<button id="ai-context-meter" class="ai-context-meter is-empty" type="button" aria-haspopup="dialog" aria-expanded="false" aria-controls="ai-context-popover" aria-live="polite" aria-label="当前上下文用量"></button>
|
|
@@ -986,6 +996,17 @@
|
|
|
986
996
|
<dialog id="users-dialog" class="dialog wide-dialog" aria-labelledby="users-dialog-title">
|
|
987
997
|
<div class="dialog-header"><div><span class="eyebrow">系统管理员</span><h2 id="users-dialog-title">用户管理</h2></div><div class="settings-dialog-header-actions"><button id="users-settings-return" class="ghost-button settings-parent-button" type="button">返回设置</button><button id="users-dialog-close" class="dialog-close" aria-label="关闭" type="button">×</button></div></div>
|
|
988
998
|
<div class="access-dialog-body">
|
|
999
|
+
<section id="invite-codes-panel" class="invite-codes-panel" aria-labelledby="invite-codes-title">
|
|
1000
|
+
<div class="invite-codes-heading">
|
|
1001
|
+
<div>
|
|
1002
|
+
<h3 id="invite-codes-title">注册邀请码</h3>
|
|
1003
|
+
<p id="invite-codes-mode" class="dialog-header-meta">正在读取注册策略……</p>
|
|
1004
|
+
</div>
|
|
1005
|
+
<button id="invite-code-generate" class="primary-button" type="button">生成邀请码</button>
|
|
1006
|
+
</div>
|
|
1007
|
+
<p id="invite-code-latest" class="invite-code-latest hidden" role="status"></p>
|
|
1008
|
+
<div id="invite-codes-list" class="access-list" aria-live="polite"></div>
|
|
1009
|
+
</section>
|
|
989
1010
|
<div id="users-list" class="access-list"></div>
|
|
990
1011
|
</div>
|
|
991
1012
|
</dialog>
|
|
@@ -1427,7 +1448,7 @@
|
|
|
1427
1448
|
</dialog>
|
|
1428
1449
|
|
|
1429
1450
|
<div id="auth-loading" class="auth-loading" role="status" aria-label="正在载入工作台"></div>
|
|
1430
|
-
<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-v1"></script>
|
|
1451
|
+
<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"></script>
|
|
1431
1452
|
|
|
1432
1453
|
</body>
|
|
1433
1454
|
</html>
|
package/dist/public/styles.css
CHANGED
|
@@ -885,6 +885,43 @@ button.usage-calendar-cell:hover, button.usage-calendar-cell:focus-visible { pos
|
|
|
885
885
|
cursor: not-allowed;
|
|
886
886
|
opacity: .46;
|
|
887
887
|
}
|
|
888
|
+
.invite-codes-panel {
|
|
889
|
+
display: grid;
|
|
890
|
+
gap: 12px;
|
|
891
|
+
padding-bottom: 4px;
|
|
892
|
+
border-bottom: 1px solid color-mix(in srgb, var(--line) 82%, transparent);
|
|
893
|
+
}
|
|
894
|
+
.invite-codes-heading {
|
|
895
|
+
display: flex;
|
|
896
|
+
align-items: flex-end;
|
|
897
|
+
justify-content: space-between;
|
|
898
|
+
gap: 12px;
|
|
899
|
+
}
|
|
900
|
+
.invite-codes-heading h3 {
|
|
901
|
+
margin: 0;
|
|
902
|
+
color: var(--ink);
|
|
903
|
+
font-size: 15px;
|
|
904
|
+
font-weight: 650;
|
|
905
|
+
}
|
|
906
|
+
.invite-codes-heading .primary-button {
|
|
907
|
+
min-height: 36px;
|
|
908
|
+
padding: 7px 12px;
|
|
909
|
+
white-space: nowrap;
|
|
910
|
+
}
|
|
911
|
+
.invite-code-latest {
|
|
912
|
+
margin: 0;
|
|
913
|
+
padding: 10px 12px;
|
|
914
|
+
border: 1px solid color-mix(in srgb, var(--accent) 38%, var(--line));
|
|
915
|
+
border-radius: 7px;
|
|
916
|
+
background: color-mix(in srgb, var(--accent) 8%, var(--surface));
|
|
917
|
+
color: var(--ink);
|
|
918
|
+
font-family: var(--font-latin), ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
919
|
+
font-size: 13px;
|
|
920
|
+
line-height: 1.5;
|
|
921
|
+
}
|
|
922
|
+
.invite-code-latest strong { font-weight: 700; letter-spacing: .06em; }
|
|
923
|
+
.invite-code-row { grid-template-columns: minmax(0, 1fr) auto; }
|
|
924
|
+
.invite-code-row > span { font-family: var(--font-latin), ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; }
|
|
888
925
|
.dialog.admin-ai-conversations-dialog { width: min(1040px, 94vw); height: min(760px, calc(100dvh - 24px)); max-height: calc(100dvh - 24px); overflow: hidden; }
|
|
889
926
|
.admin-ai-conversations-dialog { grid-template-rows: auto minmax(0, 1fr) auto; }
|
|
890
927
|
.admin-ai-conversations-dialog[open] { display: grid; }
|
|
@@ -1436,7 +1473,8 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1436
1473
|
.module-nav > #reader-open-button,
|
|
1437
1474
|
.module-nav > button[data-module="comments"],
|
|
1438
1475
|
.module-nav > button[data-module="outlines"],
|
|
1439
|
-
.module-nav > button[data-work-settings]
|
|
1476
|
+
.module-nav > button[data-work-settings],
|
|
1477
|
+
.module-nav > #writing-progress-button {
|
|
1440
1478
|
display: grid;
|
|
1441
1479
|
grid-template-columns: auto minmax(0, 2em);
|
|
1442
1480
|
align-items: start;
|
|
@@ -1540,9 +1578,10 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1540
1578
|
.chapter-foreshadow-reminder-details { grid-template-columns: minmax(0, 1fr); }
|
|
1541
1579
|
}
|
|
1542
1580
|
.editor-body { display: flex; grid-row: 3; min-height: 0; flex-direction: column; }
|
|
1543
|
-
.chapter-editor-frame { position: relative; display:
|
|
1544
|
-
.chapter-
|
|
1545
|
-
|
|
1581
|
+
.chapter-editor-frame { position: relative; display: flex; flex-direction: column; flex: 1 1 auto; width: 100%; min-height: 0; margin: 0; overflow: hidden; }
|
|
1582
|
+
.chapter-editor-scroll { position: relative; display: grid; grid-template-columns: 38px minmax(0, 1fr); flex: 1 1 auto; width: 100%; min-height: 0; overflow-x: hidden; overflow-y: auto; overscroll-behavior: contain; scrollbar-gutter: stable; }
|
|
1583
|
+
.chapter-line-numbers { position: relative; z-index: 2; grid-column: 1; grid-row: 1; min-height: 0; overflow: hidden; border-right: 1px solid var(--line); background: linear-gradient(to right, transparent, rgba(143,132,116,.04)); color: var(--muted); font-family: var(--font-latin), monospace; font-size: clamp(11px, calc(var(--editor-font-size) * .72), 14px); line-height: 1.2; user-select: none; }
|
|
1584
|
+
#chapter-line-numbers-inner { position: absolute; top: 32px; left: 0; right: 0; }
|
|
1546
1585
|
.chapter-line-number { position: absolute; left: 0; box-sizing: border-box; display: flex; width: 100%; align-items: flex-start; justify-content: center; padding: 0; border: 0; background: transparent; color: inherit; font: inherit; font-variant-numeric: tabular-nums; text-align: center; }
|
|
1547
1586
|
.chapter-line-number-select { position: relative; display: flex; width: 100%; height: 100%; align-items: flex-start; justify-content: center; padding-inline: 3px; border: 0; background: transparent; color: inherit; font: inherit; font-variant-numeric: tabular-nums; cursor: pointer; }
|
|
1548
1587
|
.chapter-line-number-select:focus-visible { z-index: 1; outline: 1px solid var(--accent); outline-offset: -1px; }
|
|
@@ -1552,12 +1591,12 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1552
1591
|
.chapter-line-number:hover { background: rgba(139,61,44,.08); color: var(--accent-dark); }
|
|
1553
1592
|
.chapter-line-number.is-line-selected { background: rgba(139,61,44,.16); color: var(--accent-dark); font-weight: 700; }
|
|
1554
1593
|
.chapter-line-number.is-line-selected::after { content: ""; position: absolute; top: 0; left: 100%; width: 100vw; height: 100%; background: rgba(139,61,44,.085); box-shadow: inset 3px 0 rgba(139,61,44,.28); pointer-events: none; }
|
|
1555
|
-
.chapter-content { position: relative; z-index: 1; grid-column: 2; grid-row: 1; resize: none; width: 100%; height:
|
|
1594
|
+
.chapter-content { position: relative; z-index: 1; grid-column: 2; grid-row: 1; resize: none; width: 100%; height: auto; min-height: 100%; margin: 0; padding: 32px 36px 72px; border: 0; background: transparent; border-radius: 0; font-size: var(--editor-font-size); line-height: var(--editor-line-height); letter-spacing: .01em; overflow-wrap: break-word; overflow: hidden; }
|
|
1556
1595
|
.app-shell.editor-typewriter-mode .chapter-content { padding-bottom: max(72px, 45dvh); }
|
|
1557
1596
|
.chapter-content:focus { box-shadow: none; }
|
|
1558
1597
|
.chapter-whitespace-overlay { position: relative; z-index: 2; grid-column: 2; grid-row: 1; width: 100%; height: 100%; overflow: hidden; opacity: 0; pointer-events: none; }
|
|
1559
1598
|
.chapter-whitespace-overlay.is-visible { opacity: 1; }
|
|
1560
|
-
#chapter-whitespace-inner { box-sizing: border-box; min-height: 100%; color: transparent; white-space: pre-wrap;
|
|
1599
|
+
#chapter-whitespace-inner { box-sizing: border-box; min-height: 100%; color: transparent; white-space: pre-wrap; }
|
|
1561
1600
|
.chapter-space-marker { position: relative; color: transparent; }
|
|
1562
1601
|
.chapter-space-marker::after { content: "·"; position: absolute; inset: 0; color: color-mix(in srgb, var(--muted) 62%, transparent); font-family: var(--font-latin), monospace; text-align: center; }
|
|
1563
1602
|
.chapter-space-marker.ideographic-space::after { content: "□"; color: color-mix(in srgb, var(--accent) 58%, transparent); font-size: .62em; line-height: 1.7; }
|
|
@@ -3090,6 +3129,23 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
3090
3129
|
.message-actions { display: flex; gap: 7px; margin-top: 10px; }
|
|
3091
3130
|
.message-actions button { border: 1px solid rgba(139,61,44,.25); background: var(--surface); color: var(--accent-dark); font-size: 10px; padding: 5px 8px; border-radius: 3px; }
|
|
3092
3131
|
.prompt-box { border-top: 1px solid var(--line); padding-top: 12px; }
|
|
3132
|
+
.ai-prompt-queue { display: grid; gap: 6px; margin-bottom: 8px; }
|
|
3133
|
+
.ai-prompt-queue.hidden { display: none; }
|
|
3134
|
+
.ai-prompt-queue-list { display: grid; gap: 6px; margin: 0; padding: 0; list-style: none; }
|
|
3135
|
+
.ai-prompt-queue-item { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 8px; padding: 7px 8px; border: 1px solid color-mix(in srgb, var(--accent) 28%, var(--line)); border-radius: 5px; background: color-mix(in srgb, var(--accent) 6%, var(--paper)); box-shadow: 0 8px 20px rgba(36, 30, 24, .1); cursor: grab; }
|
|
3136
|
+
.ai-prompt-queue-item.is-dragging { opacity: .42; cursor: grabbing; }
|
|
3137
|
+
.ai-prompt-queue-item.is-drag-over { box-shadow: 0 8px 20px rgba(36, 30, 24, .1), inset 0 2px 0 var(--accent); }
|
|
3138
|
+
.ai-prompt-queue-item.is-drag-over.drop-after { box-shadow: 0 8px 20px rgba(36, 30, 24, .1), inset 0 -2px 0 var(--accent); }
|
|
3139
|
+
.ai-prompt-queue-item.is-editing { cursor: text; }
|
|
3140
|
+
.ai-prompt-queue-preview { min-width: 0; margin: 0; color: var(--ink); font-size: 10px; line-height: 1.45; overflow-wrap: anywhere; cursor: text; }
|
|
3141
|
+
.ai-prompt-queue-editor { box-sizing: border-box; min-width: 0; width: 100%; min-height: 24px; max-height: 120px; margin: 0; padding: 3px 6px; overflow-y: auto; border: 1px solid color-mix(in srgb, var(--accent) 42%, var(--line)); border-radius: 4px; background: var(--surface); color: var(--ink); font: inherit; font-size: 10px; line-height: 1.45; resize: vertical; }
|
|
3142
|
+
.ai-prompt-queue-editor:focus { border-color: #a77768; box-shadow: 0 0 0 3px rgba(167,119,104,.12); outline: 0; }
|
|
3143
|
+
.ai-prompt-queue-actions { display: flex; flex: 0 0 auto; align-items: center; gap: 4px; cursor: auto; }
|
|
3144
|
+
.ai-prompt-queue-steer, .ai-prompt-queue-send { min-height: 24px; padding: 3px 7px; border: 1px solid color-mix(in srgb, var(--accent) 42%, var(--line)); border-radius: 4px; background: var(--surface); color: var(--accent-dark); font-size: 9px; }
|
|
3145
|
+
.ai-prompt-queue-steer:hover, .ai-prompt-queue-steer:focus-visible, .ai-prompt-queue-send:hover, .ai-prompt-queue-send:focus-visible { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, var(--surface)); outline: 0; }
|
|
3146
|
+
.ai-prompt-queue-steer:disabled, .ai-prompt-queue-send:disabled { cursor: not-allowed; opacity: .56; }
|
|
3147
|
+
.ai-prompt-queue-remove { display: grid; place-items: center; width: 24px; min-width: 24px; height: 24px; padding: 0; border: 1px solid var(--line); border-radius: 4px; background: transparent; color: var(--muted); font: 15px/1 var(--font-latin), sans-serif; }
|
|
3148
|
+
.ai-prompt-queue-remove:hover, .ai-prompt-queue-remove:focus-visible { border-color: var(--accent); color: var(--accent-dark); outline: 0; }
|
|
3093
3149
|
.ai-semantic-search-panel { display: grid; grid-template-rows: auto auto auto minmax(0, 1fr) auto; min-height: 0; height: min(520px, 58vh); max-height: min(520px, 58vh); margin-bottom: 9px; overflow: hidden; border: 1px solid var(--line); border-radius: 7px; background: var(--surface); box-shadow: 0 12px 30px rgba(49,42,32,.12); }
|
|
3094
3150
|
.ai-semantic-search-panel > header, .ai-semantic-search-panel > footer { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 9px 10px; border-bottom: 1px solid var(--line); }
|
|
3095
3151
|
.ai-semantic-search-panel > header > div { display: grid; min-width: 0; gap: 2px; }
|
|
@@ -3133,7 +3189,7 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
3133
3189
|
.ai-context-warning button:first-child { border-color: var(--accent); background: var(--accent); color: #fff; }
|
|
3134
3190
|
.ai-context-warning button:hover, .ai-context-warning button:focus-visible { border-color: var(--accent); color: var(--accent-dark); }
|
|
3135
3191
|
.ai-context-warning button:first-child:hover, .ai-context-warning button:first-child:focus-visible { background: var(--accent-dark); color: #fff; }
|
|
3136
|
-
.prompt-options { display: grid; grid-template-columns:
|
|
3192
|
+
.prompt-options { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; margin-bottom: 7px; }
|
|
3137
3193
|
.prompt-options select { padding: 6px; color: var(--muted); font-size: 10px; }
|
|
3138
3194
|
.prompt-options .ai-roleplay-character { min-width: 0; }
|
|
3139
3195
|
.prompt-options .ai-roleplay-user-character { grid-column: 1 / -1; }
|
|
@@ -3231,6 +3287,11 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
3231
3287
|
.ai-prompt-reference button { width: 16px; height: 16px; padding: 0; border: 0; border-radius: 50%; background: transparent; color: inherit; font: 14px/1 var(--font-latin), monospace; }
|
|
3232
3288
|
.ai-prompt-reference button:hover, .ai-prompt-reference button:focus-visible { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent); }
|
|
3233
3289
|
.prompt-composer-actions { position: absolute; right: 8px; bottom: 8px; display: flex; gap: 6px; align-items: center; }
|
|
3290
|
+
@media (max-width: 540px) {
|
|
3291
|
+
.prompt-options { grid-template-columns: 1fr 1fr; }
|
|
3292
|
+
.ai-prompt-queue-item { grid-template-columns: minmax(0, 1fr); }
|
|
3293
|
+
.ai-prompt-queue-actions { justify-content: flex-end; flex-wrap: wrap; }
|
|
3294
|
+
}
|
|
3234
3295
|
.ai-context-meter { --context-usage: 0; --context-meter-color: var(--green); position: relative; display: grid; flex: 0 0 24px; place-items: center; width: 24px; min-height: 24px; height: 24px; overflow: visible; border: 0; border-radius: 50%; background: transparent; color: var(--ink); font-family: var(--font-latin); line-height: 1; cursor: pointer; }
|
|
3235
3296
|
.ai-context-meter::before { content: ""; position: absolute; top: 1px; left: 1px; width: 22px; height: 22px; border-radius: 50%; background: conic-gradient(var(--context-meter-color) calc(var(--context-usage) * 1%), rgba(143,132,116,.2) 0); }
|
|
3236
3297
|
.ai-context-meter::after { content: ""; position: absolute; inset: 3px; border-radius: 50%; background: var(--paper); box-shadow: inset 0 0 0 1px rgba(143,132,116,.12); }
|
|
@@ -3291,6 +3352,11 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
3291
3352
|
.ai-message-image-preview:hover, .ai-message-image-preview:focus-visible { outline: 2px solid color-mix(in srgb, var(--accent) 72%, transparent); outline-offset: 1px; }
|
|
3292
3353
|
.ai-message-image-preview img { display: block; width: 100%; height: 100%; object-fit: cover; }
|
|
3293
3354
|
.ai-send-button.is-stop .ai-send-button-icon { width: 12px; height: 12px; fill: currentColor; stroke: none; }
|
|
3355
|
+
.ai-send-button.is-queue { background: color-mix(in srgb, var(--accent) 88%, #3d2a24); }
|
|
3356
|
+
.ai-send-button.is-queue .ai-send-button-icon { width: 13px; height: 13px; }
|
|
3357
|
+
.user-message.is-steer { background: color-mix(in srgb, var(--accent) 78%, var(--paper)); box-shadow: inset 0 0 0 1px color-mix(in srgb, #fff 22%, transparent); }
|
|
3358
|
+
.user-message.is-steer > .message-heading > span { display: inline-flex; align-items: center; gap: 7px; }
|
|
3359
|
+
.ai-message-status.is-steer { border-color: color-mix(in srgb, currentColor 55%, transparent); background: color-mix(in srgb, currentColor 16%, transparent); color: inherit; }
|
|
3294
3360
|
.ai-citations { display: grid; gap: 6px; max-height: 190px; overflow-y: auto; margin-bottom: 8px; }
|
|
3295
3361
|
.ai-citation-card { display: grid; grid-template-columns: minmax(0, 1fr) auto; border: 1px solid var(--line); border-radius: 5px; background: var(--paper); overflow: hidden; }
|
|
3296
3362
|
.ai-citation-main { min-width: 0; padding: 8px 9px; border: 0; background: transparent; text-align: left; }
|
|
@@ -4210,6 +4276,7 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
4210
4276
|
.member-permission-form .primary-button { justify-self: stretch; }
|
|
4211
4277
|
.access-row { grid-template-columns: minmax(0, 1fr); align-items: stretch; }
|
|
4212
4278
|
.access-row select, .access-row button { width: 100%; }
|
|
4279
|
+
.invite-codes-heading { align-items: stretch; flex-direction: column; }
|
|
4213
4280
|
.admin-ai-conversations-dialog .dialog-header { gap: 10px; }
|
|
4214
4281
|
.admin-ai-conversations-dialog .dialog-header > div:first-child { min-width: 0; }
|
|
4215
4282
|
.admin-ai-conversations-dialog .dialog-header-meta { display: none; }
|
|
@@ -4506,7 +4573,7 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
4506
4573
|
.chapter-content { padding: 22px 16px 64px 12px; font-size: max(16px, var(--editor-font-size)); }
|
|
4507
4574
|
.app-shell.editor-typewriter-mode .chapter-content { padding-bottom: max(64px, 45dvh); }
|
|
4508
4575
|
.chapter-line-numbers { width: 32px; font-size: 11px; }
|
|
4509
|
-
.chapter-editor-
|
|
4576
|
+
.chapter-editor-scroll { grid-template-columns: 32px minmax(0, 1fr); }
|
|
4510
4577
|
.chapter-line-measure { left: 32px; }
|
|
4511
4578
|
.module-view { padding: 26px var(--mobile-gutter) 46px; }
|
|
4512
4579
|
.module-header { padding-bottom: 18px; }
|