@musnows/scriverse 0.4.10 → 0.4.12
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 +209 -17
- package/dist/ai.js.map +1 -1
- package/dist/app.js +53 -5
- package/dist/app.js.map +1 -1
- package/dist/public/ai-message-meta.js +7 -2
- package/dist/public/app.js +207 -22
- package/dist/public/index.html +8 -9
- package/dist/public/race-hierarchy.js +36 -0
- package/dist/public/relationship-graph.js +32 -10
- package/dist/public/styles.css +57 -11
- package/dist/store.js +21 -6
- package/dist/store.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/public/styles.css
CHANGED
|
@@ -487,7 +487,7 @@ input[type="checkbox"][hidden] { display: none; }
|
|
|
487
487
|
.left-panel, .ai-panel { position: relative; min-height: 0; background: var(--panel); }
|
|
488
488
|
.left-panel { display: flex; flex-direction: column; border-right: 1px solid var(--line); padding: 0; overflow: hidden; }
|
|
489
489
|
.left-panel-body { flex: 1 1 auto; min-height: 0; padding: 18px 14px 16px; overflow-y: auto; }
|
|
490
|
-
.ai-panel { border-left: 1px solid var(--line); display: flex; flex-direction: column; padding: 18px; min-width: 0; }
|
|
490
|
+
.ai-panel { border-left: 1px solid var(--line); display: flex; flex-direction: column; padding: 14px 16px 18px; min-width: 0; }
|
|
491
491
|
.panel-collapse-button { z-index: 8; flex: 0 0 auto; width: 24px; height: 24px; padding: 0; border: 1px solid var(--line); border-radius: 4px; background: var(--panel); color: var(--muted); font-size: 18px; line-height: 1; }
|
|
492
492
|
.ai-heading #ai-panel-toggle { flex-basis: 30px; width: 30px; height: 30px; }
|
|
493
493
|
.panel-resize-handle { position: absolute; z-index: 7; top: 0; bottom: 0; width: 7px; cursor: col-resize; touch-action: none; }
|
|
@@ -1180,6 +1180,13 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1180
1180
|
margin: 0;
|
|
1181
1181
|
}
|
|
1182
1182
|
.task-auto-run-meta { margin: 0; color: var(--muted); font-size: 10px; }
|
|
1183
|
+
.task-auto-run-progress { display: grid; gap: 6px; width: min(100%, 420px); }
|
|
1184
|
+
.task-auto-run-progress-label { display: flex; align-items: center; justify-content: space-between; gap: 12px; color: var(--muted); font-size: 10px; }
|
|
1185
|
+
.task-auto-run-progress-label strong { color: var(--ink); font-family: var(--font-latin), monospace; font-size: 10px; font-weight: 600; }
|
|
1186
|
+
.task-auto-run-progress-bar { width: 100%; height: 6px; overflow: hidden; border: 0; border-radius: 999px; appearance: none; background: color-mix(in srgb, var(--line) 72%, transparent); }
|
|
1187
|
+
.task-auto-run-progress-bar::-webkit-progress-bar { border-radius: inherit; background: color-mix(in srgb, var(--line) 72%, transparent); }
|
|
1188
|
+
.task-auto-run-progress-bar::-webkit-progress-value { border-radius: inherit; background: var(--accent); transition: width .25s ease; }
|
|
1189
|
+
.task-auto-run-progress-bar::-moz-progress-bar { border-radius: inherit; background: var(--accent); transition: width .25s ease; }
|
|
1183
1190
|
.task-row-actions { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
1184
1191
|
.task-detail { display: grid; gap: 12px; }
|
|
1185
1192
|
.task-detail p, .task-detail div { margin: 0; font-size: 12px; line-height: 1.55; }
|
|
@@ -1322,6 +1329,8 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1322
1329
|
}
|
|
1323
1330
|
.relationship-network .mind-node,
|
|
1324
1331
|
.relationship-network .obsidian-node {
|
|
1332
|
+
--node-color: var(--node-color-light, #626b78);
|
|
1333
|
+
--node-glow: var(--node-glow-light, rgba(98,107,120,.42));
|
|
1325
1334
|
width: var(--node-size);
|
|
1326
1335
|
height: var(--node-size);
|
|
1327
1336
|
min-height: 0;
|
|
@@ -1338,6 +1347,11 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1338
1347
|
transition: opacity .12s ease, transform .12s ease, box-shadow .12s ease;
|
|
1339
1348
|
will-change: left, top;
|
|
1340
1349
|
}
|
|
1350
|
+
:root[data-theme="dark"] .relationship-network .mind-node,
|
|
1351
|
+
:root[data-theme="dark"] .relationship-network .obsidian-node {
|
|
1352
|
+
--node-color: var(--node-color-dark, #aab3c0);
|
|
1353
|
+
--node-glow: var(--node-glow-dark, rgba(170,179,192,.56));
|
|
1354
|
+
}
|
|
1341
1355
|
.relationship-network .mind-node span {
|
|
1342
1356
|
position: absolute;
|
|
1343
1357
|
left: 50%;
|
|
@@ -1468,14 +1482,16 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1468
1482
|
.galaxy-detail { position: fixed; z-index: 7; left: 22px; top: 22px; width: min(300px, 30vw); max-height: 55vh; overflow: auto; padding: 15px; border: 1px solid rgba(255,255,255,.14); border-radius: 8px; background: rgba(5,7,13,.74); backdrop-filter: blur(14px); }.galaxy-detail strong, .galaxy-detail small { display: block; }.galaxy-detail strong { font-size: 18px; }.galaxy-detail small, .galaxy-detail p { color: rgba(220,235,250,.65); font-size: 9px; }.galaxy-detail ul { display: grid; gap: 7px; padding: 0; list-style: none; font-size: 9px; }.galaxy-detail li { display: flex; align-items: center; gap: 6px; }
|
|
1469
1483
|
.sr-only { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
|
|
1470
1484
|
|
|
1471
|
-
.ai-heading { display: flex; align-items: center; gap: 8px; padding-bottom:
|
|
1472
|
-
.ai-heading
|
|
1473
|
-
.ai-heading
|
|
1485
|
+
.ai-heading { display: flex; align-items: center; gap: 8px; min-width: 0; padding-bottom: 9px; border-bottom: 1px solid var(--line); }
|
|
1486
|
+
.ai-heading-title { display: flex; flex: 0 0 auto; gap: 8px; align-items: center; }
|
|
1487
|
+
.ai-heading-title strong { white-space: nowrap; }
|
|
1488
|
+
.ai-heading-actions { display: flex; align-items: center; min-width: 0; margin-left: auto; gap: 5px; }
|
|
1489
|
+
.ai-heading-actions > span { min-width: 0; max-width: 88px; overflow: hidden; color: var(--muted); font-size: 9px; text-overflow: ellipsis; white-space: nowrap; }
|
|
1490
|
+
.ai-heading-actions button { min-width: 28px; height: 28px; padding: 0 7px; border: 1px solid var(--line); border-radius: 4px; background: transparent; color: var(--muted); font-size: 9px; }
|
|
1491
|
+
.ai-heading-action-icon { display: block; width: 15px; height: 15px; margin: auto; fill: none; stroke: currentColor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.8; }
|
|
1492
|
+
.ai-heading-actions #ai-new-conversation { padding: 0; font: 17px/1 var(--font-latin), monospace; }
|
|
1493
|
+
.ai-heading-actions button:hover, .ai-heading-actions button[aria-expanded="true"] { background: var(--paper-deep); color: var(--ink); }
|
|
1474
1494
|
.status-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--green); box-shadow: 0 0 0 3px rgba(94,118,92,.14); }
|
|
1475
|
-
.ai-conversation-toolbar { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 5px; align-items: center; padding: 10px 0; }
|
|
1476
|
-
.ai-conversation-toolbar > span { min-width: 0; overflow: hidden; color: var(--muted); font-size: 9px; text-overflow: ellipsis; white-space: nowrap; }
|
|
1477
|
-
.ai-conversation-toolbar button { padding: 5px 7px; border: 1px solid var(--line); border-radius: 4px; background: transparent; color: var(--muted); font-size: 9px; }
|
|
1478
|
-
.ai-conversation-toolbar button:hover, .ai-conversation-toolbar button[aria-expanded="true"] { background: var(--paper-deep); color: var(--ink); }
|
|
1479
1495
|
.ai-history-dialog-body { min-height: min(360px, 55vh); max-height: 65vh; overflow-y: auto; padding: 18px 24px 24px; }
|
|
1480
1496
|
.ai-history-list { display: grid; gap: 8px; }
|
|
1481
1497
|
.ai-history-item { display: grid; gap: 5px; width: 100%; min-width: 0; padding: 14px 16px; border: 1px solid var(--line); border-radius: 5px; background: var(--surface-soft); text-align: left; }
|
|
@@ -1504,10 +1520,10 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1504
1520
|
line-height: 1.65;
|
|
1505
1521
|
resize: vertical;
|
|
1506
1522
|
}
|
|
1507
|
-
.quick-actions { display: grid; grid-template-columns:
|
|
1508
|
-
.quick-actions button { border: 1px solid var(--line); background: transparent; border-radius: 3px; padding:
|
|
1523
|
+
.quick-actions { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 5px; margin-top: 8px; }
|
|
1524
|
+
.quick-actions button { min-width: 0; min-height: 30px; border: 1px solid var(--line); background: transparent; border-radius: 3px; padding: 5px 3px; color: var(--muted); font-size: 10px; white-space: nowrap; }
|
|
1509
1525
|
.quick-actions button:hover { color: var(--ink); background: var(--paper-deep); }
|
|
1510
|
-
.ai-feed { flex: 1; min-height: 0; overflow-y: auto; margin:
|
|
1526
|
+
.ai-feed { flex: 1; min-height: 0; overflow-y: auto; margin: 10px -5px 12px; padding: 0 5px; }
|
|
1511
1527
|
.assistant-message, .user-message { position: relative; margin-bottom: 12px; padding: 12px 13px; border-radius: 5px; font-size: 12px; line-height: 1.55; }
|
|
1512
1528
|
.assistant-message { background: var(--paper-deep); }
|
|
1513
1529
|
.assistant-message.has-message-actions, .user-message.has-message-actions { margin-bottom: 42px; }
|
|
@@ -1732,6 +1748,36 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1732
1748
|
.task-chapter-field { transition: opacity .15s ease; }
|
|
1733
1749
|
.task-chapter-field.is-disabled { opacity: .48; }
|
|
1734
1750
|
.task-chapter-field select:disabled { cursor: not-allowed; }
|
|
1751
|
+
.relationship-analysis-options { display: grid; gap: 14px; }
|
|
1752
|
+
.relationship-character-field { min-width: 0; }
|
|
1753
|
+
.relationship-character-picker { display: grid; gap: 8px; min-width: 0; }
|
|
1754
|
+
.dialog-fields .relationship-character-trigger { display: flex; width: 100%; min-height: 42px; align-items: center; justify-content: space-between; gap: 12px; padding: 9px 11px; border: 1px solid var(--line); border-radius: 4px; background: var(--surface); color: var(--ink); font-size: 12px; text-align: left; }
|
|
1755
|
+
.relationship-character-trigger:hover, .relationship-character-trigger:focus-visible, .relationship-character-trigger[aria-expanded="true"] { border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 12%, transparent); outline: none; }
|
|
1756
|
+
.relationship-character-trigger:disabled { cursor: not-allowed; opacity: .48; }
|
|
1757
|
+
.relationship-character-trigger > span:first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1758
|
+
.relationship-character-trigger-meta { display: inline-flex; flex: 0 0 auto; align-items: center; gap: 8px; color: var(--muted); font-family: var(--font-latin), monospace; font-size: 10px; }
|
|
1759
|
+
.relationship-character-chevron { font-size: 15px; line-height: 1; transition: transform .15s ease; }
|
|
1760
|
+
.relationship-character-trigger[aria-expanded="true"] .relationship-character-chevron { transform: rotate(180deg); }
|
|
1761
|
+
.relationship-character-bubble { position: relative; display: grid; gap: 9px; padding: 12px; border: 1px solid color-mix(in srgb, var(--accent) 36%, var(--line)); border-radius: 8px; background: var(--surface-soft); box-shadow: 0 10px 30px rgba(48,39,31,.12); }
|
|
1762
|
+
.relationship-character-bubble::before { position: absolute; top: -6px; right: 20px; width: 10px; height: 10px; border-top: 1px solid color-mix(in srgb, var(--accent) 36%, var(--line)); border-left: 1px solid color-mix(in srgb, var(--accent) 36%, var(--line)); background: var(--surface-soft); content: ""; transform: rotate(45deg); }
|
|
1763
|
+
.dialog-fields .relationship-character-search { gap: 5px; }
|
|
1764
|
+
.dialog-fields .relationship-character-search input { min-height: 36px; padding: 7px 9px; background: var(--surface); }
|
|
1765
|
+
.relationship-character-bubble-meta { display: flex; align-items: center; justify-content: space-between; gap: 10px; color: var(--muted); font-size: 9px; }
|
|
1766
|
+
.relationship-character-bubble-meta button { padding: 2px 0; border: 0; background: transparent; color: var(--accent-dark); font-size: 9px; }
|
|
1767
|
+
.relationship-character-bubble-meta button:disabled { color: var(--muted); cursor: default; opacity: .45; }
|
|
1768
|
+
.relationship-character-options { display: flex; flex-wrap: wrap; gap: 7px; max-height: 220px; overflow-y: auto; padding: 2px 2px 2px 0; }
|
|
1769
|
+
.dialog-fields .relationship-character-chip { position: relative; display: inline-flex; width: auto; cursor: pointer; }
|
|
1770
|
+
.relationship-character-chip input { position: absolute; width: 1px !important; min-width: 1px; height: 1px; opacity: 0; }
|
|
1771
|
+
.relationship-character-chip span { display: inline-flex; align-items: center; min-height: 30px; padding: 5px 10px; border: 1px solid var(--line); border-radius: 16px; background: var(--panel); color: var(--muted); font-size: 10px; transition: background .14s ease, border-color .14s ease, color .14s ease; }
|
|
1772
|
+
.relationship-character-chip input:checked + span { border-color: var(--accent); background: var(--accent); color: #fff; }
|
|
1773
|
+
.relationship-character-chip input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
1774
|
+
.relationship-character-empty { margin: 0; padding: 18px 8px; color: var(--muted); font-size: 10px; text-align: center; }
|
|
1775
|
+
.relationship-analysis-helper { display: flex; gap: 7px; align-items: flex-start; margin: -7px 2px 0; color: var(--muted); font-size: 10px; line-height: 1.55; }
|
|
1776
|
+
.relationship-analysis-helper > span:first-child { display: inline-grid; flex: 0 0 16px; width: 16px; height: 16px; margin-top: 1px; place-items: center; border: 1px solid var(--line); border-radius: 50%; color: var(--accent-dark); font-family: var(--font-latin), monospace; font-size: 9px; font-style: normal; font-weight: 700; line-height: 1; }
|
|
1777
|
+
.relationship-overwrite-card { display: grid; gap: 5px; padding: 11px 12px; border: 1px solid var(--line); border-radius: 5px; background: var(--surface-soft); transition: border-color .15s ease, background .15s ease, opacity .15s ease; }
|
|
1778
|
+
.relationship-overwrite-card .checkbox-field { color: var(--ink); font-size: 11px; font-weight: 600; }
|
|
1779
|
+
.relationship-overwrite-card > p { margin: 0 0 0 25px; color: var(--muted); font-size: 10px; line-height: 1.55; }
|
|
1780
|
+
.relationship-overwrite-card:has(input:checked) { border-color: color-mix(in srgb, var(--accent) 62%, var(--line)); background: color-mix(in srgb, var(--accent) 7%, var(--surface)); }
|
|
1735
1781
|
.model-temperature-hint { margin: 0; color: var(--accent-dark); font-size: 10px; line-height: 1.55; }
|
|
1736
1782
|
.item-list-rows { display: grid; gap: 7px; }
|
|
1737
1783
|
.item-list-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 7px; }
|
package/dist/store.js
CHANGED
|
@@ -3607,6 +3607,15 @@ export class Store {
|
|
|
3607
3607
|
const timestamp = now();
|
|
3608
3608
|
const scope = input.scope ?? { type: "book" };
|
|
3609
3609
|
const sourceVersions = {};
|
|
3610
|
+
if (Array.isArray(scope.characterIds)) {
|
|
3611
|
+
for (const characterId of scope.characterIds) {
|
|
3612
|
+
if (typeof characterId !== "string")
|
|
3613
|
+
throw new AppError(400, "CHARACTER_REQUIRED", "被分析角色标识无效");
|
|
3614
|
+
const character = this.getCharacter(characterId);
|
|
3615
|
+
if (character.workId !== workId)
|
|
3616
|
+
throw new AppError(400, "CHARACTER_WORK_MISMATCH", "被分析角色不属于当前作品");
|
|
3617
|
+
}
|
|
3618
|
+
}
|
|
3610
3619
|
if (typeof scope.chapterId === "string") {
|
|
3611
3620
|
const chapter = this.getChapter(scope.chapterId);
|
|
3612
3621
|
if (chapter.workId !== workId)
|
|
@@ -3759,17 +3768,23 @@ export class Store {
|
|
|
3759
3768
|
};
|
|
3760
3769
|
}
|
|
3761
3770
|
taskScopeSummaryFromMaps(scope, chapterSummaries, volumeTitles) {
|
|
3771
|
+
const targetedSuffix = Array.isArray(scope.characterIds) && scope.characterIds.length
|
|
3772
|
+
? ` · 定向 ${scope.characterIds.length} 人${scope.replaceExistingRelationships === true ? " · 覆盖已有关系" : ""}`
|
|
3773
|
+
: "";
|
|
3762
3774
|
if (typeof scope.chapterId === "string")
|
|
3763
|
-
return chapterSummaries.get(scope.chapterId) ?? "章节已删除"
|
|
3775
|
+
return `${chapterSummaries.get(scope.chapterId) ?? "章节已删除"}${targetedSuffix}`;
|
|
3764
3776
|
if (scope.type === "volume" && typeof scope.volumeId === "string") {
|
|
3765
3777
|
const title = volumeTitles.get(scope.volumeId);
|
|
3766
|
-
return title ? `分卷 · ${title}` : "分卷已删除";
|
|
3778
|
+
return title ? `分卷 · ${title}${targetedSuffix}` : "分卷已删除";
|
|
3767
3779
|
}
|
|
3768
3780
|
if (scope.type === "book" || Object.keys(scope).length === 0)
|
|
3769
|
-
return "全书"
|
|
3781
|
+
return `${scope.includeAllSettings === true ? "全书 + 所有设定" : "全书"}${targetedSuffix}`;
|
|
3770
3782
|
return "未指定范围";
|
|
3771
3783
|
}
|
|
3772
3784
|
taskScopeSummary(workId, scope) {
|
|
3785
|
+
const targetedSuffix = Array.isArray(scope.characterIds) && scope.characterIds.length
|
|
3786
|
+
? ` · 定向 ${scope.characterIds.length} 人${scope.replaceExistingRelationships === true ? " · 覆盖已有关系" : ""}`
|
|
3787
|
+
: "";
|
|
3773
3788
|
if (typeof scope.chapterId === "string") {
|
|
3774
3789
|
const chapter = this.db.get(`SELECT chapter.title AS title, volume.title AS volume_title
|
|
3775
3790
|
FROM chapters chapter
|
|
@@ -3779,14 +3794,14 @@ export class Store {
|
|
|
3779
3794
|
return "章节已删除";
|
|
3780
3795
|
const title = requiredString(chapter, "title");
|
|
3781
3796
|
const volumeTitle = requiredString(chapter, "volume_title");
|
|
3782
|
-
return `${volumeTitle} · ${title}`;
|
|
3797
|
+
return `${volumeTitle} · ${title}${targetedSuffix}`;
|
|
3783
3798
|
}
|
|
3784
3799
|
if (scope.type === "volume" && typeof scope.volumeId === "string") {
|
|
3785
3800
|
const volume = this.db.get("SELECT title FROM volumes WHERE id = ? AND work_id = ?", scope.volumeId, workId);
|
|
3786
|
-
return volume ? `分卷 · ${requiredString(volume, "title")}` : "分卷已删除";
|
|
3801
|
+
return volume ? `分卷 · ${requiredString(volume, "title")}${targetedSuffix}` : "分卷已删除";
|
|
3787
3802
|
}
|
|
3788
3803
|
if (scope.type === "book" || Object.keys(scope).length === 0)
|
|
3789
|
-
return "全书"
|
|
3804
|
+
return `${scope.includeAllSettings === true ? "全书 + 所有设定" : "全书"}${targetedSuffix}`;
|
|
3790
3805
|
return "未指定范围";
|
|
3791
3806
|
}
|
|
3792
3807
|
taskScopeDetails(workId, scope) {
|