@musnows/scriverse 0.4.7 → 0.4.10

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.
@@ -485,7 +485,8 @@ input[type="checkbox"][hidden] { display: none; }
485
485
  @keyframes onboarding-popover-in { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: translateY(0); } }
486
486
 
487
487
  .left-panel, .ai-panel { position: relative; min-height: 0; background: var(--panel); }
488
- .left-panel { border-right: 1px solid var(--line); padding: 18px 14px 16px; overflow-y: auto; }
488
+ .left-panel { display: flex; flex-direction: column; border-right: 1px solid var(--line); padding: 0; overflow: hidden; }
489
+ .left-panel-body { flex: 1 1 auto; min-height: 0; padding: 18px 14px 16px; overflow-y: auto; }
489
490
  .ai-panel { border-left: 1px solid var(--line); display: flex; flex-direction: column; padding: 18px; min-width: 0; }
490
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; }
491
492
  .ai-heading #ai-panel-toggle { flex-basis: 30px; width: 30px; height: 30px; }
@@ -496,7 +497,10 @@ input[type="checkbox"][hidden] { display: none; }
496
497
  body.is-panel-resizing { cursor: col-resize; user-select: none; }
497
498
  .app-shell.left-panel-collapsed { --left-panel-width: 42px !important; }.app-shell.ai-panel-collapsed { --ai-panel-width: 42px !important; }
498
499
  .app-shell.left-panel-collapsed .left-panel, .app-shell.ai-panel-collapsed .ai-panel { padding: 0; overflow: hidden; }
499
- .app-shell.left-panel-collapsed .left-panel > :not(.left-actions), .app-shell.ai-panel-collapsed .ai-panel > :not(.ai-heading) { display: none; }
500
+ .app-shell.left-panel-collapsed .left-panel > .panel-resize-handle,
501
+ .app-shell.left-panel-collapsed .left-panel-body > :not(.left-actions),
502
+ .app-shell.ai-panel-collapsed .ai-panel > :not(.ai-heading) { display: none; }
503
+ .app-shell.left-panel-collapsed .left-panel-body { padding: 0; overflow: hidden; }
500
504
  .app-shell.left-panel-collapsed .left-actions, .app-shell.ai-panel-collapsed .ai-heading { display: flex; justify-content: center; padding: 8px 0; border: 0; }
501
505
  .app-shell.left-panel-collapsed .left-actions > :not(.left-primary-actions), .app-shell.left-panel-collapsed .left-primary-actions > :not(.panel-collapse-button), .app-shell.ai-panel-collapsed .ai-heading > :not(.panel-collapse-button) { display: none; }
502
506
  .app-shell.left-panel-collapsed .left-primary-actions { display: flex; justify-content: center; }
@@ -619,17 +623,23 @@ body.is-panel-resizing { cursor: col-resize; user-select: none; }
619
623
  .app-shell.prose-hidden-mode:not(.shelf-mode) .panel-heading,
620
624
  .app-shell.prose-hidden-mode:not(.shelf-mode) #novel-tree { display: none !important; }
621
625
  .app-shell.prose-read-only-mode:not(.shelf-mode) #tidy-blank-lines-button,
622
- .app-shell.prose-read-only-mode:not(.shelf-mode) #save-button { display: none !important; }
626
+ .app-shell.prose-read-only-mode:not(.shelf-mode) #save-button,
627
+ .app-shell.prose-read-only-mode:not(.shelf-mode) #chapter-edit-button { display: none !important; }
623
628
  .app-shell.prose-read-only-mode:not(.shelf-mode) .left-primary-actions { justify-content: flex-end; }
624
629
  .app-shell.prose-read-only-mode:not(.shelf-mode) #chapter-title[readonly],
625
630
  .app-shell.prose-read-only-mode:not(.shelf-mode) #chapter-content[readonly] { cursor: default; }
626
631
  .app-shell.view-only-mode:not(.shelf-mode) #module-create-button,
627
632
  .app-shell.view-only-mode:not(.shelf-mode) [data-work-settings],
628
633
  .app-shell.view-only-mode:not(.shelf-mode) #tidy-blank-lines-button,
629
- .app-shell.view-only-mode:not(.shelf-mode) #save-button { display: none !important; }
634
+ .app-shell.view-only-mode:not(.shelf-mode) #save-button,
635
+ .app-shell.view-only-mode:not(.shelf-mode) #chapter-edit-button { display: none !important; }
630
636
  .app-shell.view-only-mode:not(.shelf-mode) .left-primary-actions { justify-content: flex-end; }
631
637
  .app-shell.view-only-mode:not(.shelf-mode) #chapter-title[readonly],
632
638
  .app-shell.view-only-mode:not(.shelf-mode) #chapter-content[readonly] { cursor: default; }
639
+ .editor-view.is-read-only #tidy-blank-lines-button,
640
+ .editor-view.is-read-only #save-button { display: none !important; }
641
+ .editor-view.is-read-only #chapter-title[readonly],
642
+ .editor-view.is-read-only #chapter-content[readonly] { cursor: default; }
633
643
  body.work-viewer-mode [data-setting-status],
634
644
  body.work-viewer-mode [data-edit-setting],
635
645
  body.work-viewer-mode [data-edit-character],
@@ -747,6 +757,74 @@ body.work-viewer-mode .character-editor-actions { display: none !important; }
747
757
  .avatar-settings-actions { display: flex; flex-wrap: wrap; gap: 8px; }
748
758
  .avatar-settings-actions button { min-height: 32px; padding: 6px 11px; font-size: 11px; }
749
759
  .avatar-settings-actions button:disabled { cursor: wait; opacity: .5; }
760
+ .avatar-crop-dialog { width: min(720px, 94vw); }
761
+ .avatar-crop-body { display: grid; grid-template-columns: minmax(0, 1fr) 96px; gap: 16px; align-items: start; padding: 18px 24px 8px; }
762
+ .avatar-crop-stage {
763
+ position: relative;
764
+ display: grid;
765
+ place-items: center;
766
+ width: 100%;
767
+ aspect-ratio: 1;
768
+ max-height: min(52vh, 480px);
769
+ overflow: hidden;
770
+ border: 1px solid var(--line);
771
+ border-radius: 6px;
772
+ background:
773
+ linear-gradient(45deg, color-mix(in srgb, var(--line) 55%, transparent) 25%, transparent 25%) 0 0 / 16px 16px,
774
+ linear-gradient(-45deg, color-mix(in srgb, var(--line) 55%, transparent) 25%, transparent 25%) 0 8px / 16px 16px,
775
+ var(--surface-soft);
776
+ touch-action: none;
777
+ user-select: none;
778
+ }
779
+ .avatar-crop-image {
780
+ position: absolute;
781
+ inset: 0;
782
+ width: 100%;
783
+ height: 100%;
784
+ object-fit: contain;
785
+ pointer-events: none;
786
+ }
787
+ .avatar-crop-shade {
788
+ position: absolute;
789
+ inset: 0;
790
+ pointer-events: none;
791
+ background: color-mix(in srgb, var(--ink) 42%, transparent);
792
+ -webkit-mask-image: linear-gradient(#000, #000), linear-gradient(#000, #000);
793
+ mask-image: linear-gradient(#000, #000), linear-gradient(#000, #000);
794
+ -webkit-mask-repeat: no-repeat;
795
+ mask-repeat: no-repeat;
796
+ -webkit-mask-composite: xor;
797
+ mask-composite: exclude;
798
+ }
799
+ .avatar-crop-selection {
800
+ position: absolute;
801
+ box-sizing: border-box;
802
+ border: 2px solid color-mix(in srgb, white 88%, var(--accent));
803
+ border-radius: 2px;
804
+ box-shadow: 0 0 0 1px color-mix(in srgb, var(--ink) 35%, transparent);
805
+ cursor: grab;
806
+ touch-action: none;
807
+ }
808
+ .avatar-crop-selection.is-dragging { cursor: grabbing; }
809
+ .avatar-crop-selection[hidden] { display: none; }
810
+ .avatar-crop-handle {
811
+ position: absolute;
812
+ width: 12px;
813
+ height: 12px;
814
+ padding: 0;
815
+ border: 2px solid color-mix(in srgb, white 90%, var(--accent));
816
+ border-radius: 2px;
817
+ background: var(--accent);
818
+ box-shadow: 0 0 0 1px color-mix(in srgb, var(--ink) 28%, transparent);
819
+ }
820
+ .avatar-crop-handle[data-avatar-crop-handle="nw"] { top: -7px; left: -7px; cursor: nwse-resize; }
821
+ .avatar-crop-handle[data-avatar-crop-handle="ne"] { top: -7px; right: -7px; cursor: nesw-resize; }
822
+ .avatar-crop-handle[data-avatar-crop-handle="sw"] { bottom: -7px; left: -7px; cursor: nesw-resize; }
823
+ .avatar-crop-handle[data-avatar-crop-handle="se"] { bottom: -7px; right: -7px; cursor: nwse-resize; }
824
+ .avatar-crop-side { display: grid; justify-items: center; gap: 8px; padding-top: 8px; }
825
+ .avatar-crop-side p { margin: 0; color: var(--muted); font-size: 10px; }
826
+ .avatar-crop-preview { width: 76px; height: 76px; border: 2px solid color-mix(in srgb, var(--line) 72%, transparent); background: var(--surface); }
827
+ .avatar-crop-preview canvas { position: absolute; inset: 0; width: 100%; height: 100%; border-radius: 50%; }
750
828
  .account-settings-form { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: end; gap: 12px; margin-top: 16px; }
751
829
  .account-settings-form label { display: grid; min-width: 0; gap: 6px; color: var(--muted); font-size: 11px; }
752
830
  .account-settings-form input { width: 100%; min-height: 38px; padding: 9px 10px; background: var(--surface); font-size: 12px; }
@@ -944,8 +1022,10 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
944
1022
  .module-header { display: flex; justify-content: space-between; align-items: flex-end; gap: 18px; padding-bottom: 24px; border-bottom: 1px solid var(--line); }
945
1023
  .module-header-actions { display: flex; align-items: center; justify-content: flex-end; gap: 8px; flex-wrap: wrap; }
946
1024
  .module-header-actions > [data-module-header-action] { order: 1; }
1025
+ .module-header-actions > .module-count-badge { order: 0; }
947
1026
  .module-header-actions > #module-create-button { order: 2; min-height: 36px; }
948
- .module-header h1 { margin: 0 0 8px; font-weight: 500; font-size: 34px; }
1027
+ .module-count-badge { display: inline-grid; min-width: 28px; height: 28px; padding: 0 7px; place-items: center; border: 1px solid var(--line); border-radius: 14px; background: var(--surface); color: var(--accent-dark); font-family: var(--font-latin), monospace; font-size: 11px; font-weight: 650; }
1028
+ .module-header h1 { margin: 0 0 6px; font-weight: 500; font-size: 24px; line-height: 1.25; }
949
1029
  .module-header p { margin: 0; color: var(--muted); font-size: 13px; }
950
1030
  .module-content { padding: 24px 0 80px; }
951
1031
  .card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 13px; }
@@ -963,6 +1043,8 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
963
1043
  .module-filter-toggle svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.7; }
964
1044
  .module-filter-toggle + .module-layout-toolbar { order: 2; }
965
1045
  .module-filter-toggle ~ #module-create-button { order: 3; }
1046
+ .race-tree-expand-toolbar ~ .module-layout-toolbar { order: 2; }
1047
+ .race-tree-expand-toolbar ~ #module-create-button { order: 3; }
966
1048
  .settings-layout-hint { color: var(--muted); font-size: 10px; }
967
1049
  .settings-layout-toggle, .module-layout-toggle { display: inline-flex; border: 1px solid var(--line); border-radius: 4px; overflow: hidden; background: var(--surface); }
968
1050
  .settings-layout-toggle button { min-height: 34px; padding: 0 12px; border: 0; border-right: 1px solid var(--line); background: transparent; color: var(--muted); font-size: 11px; }
@@ -1407,6 +1489,12 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
1407
1489
  .book-summary-context-percent-field { width: min(100%, 280px); }
1408
1490
  .context-compact-threshold-field { width: min(100%, 280px); }
1409
1491
  .book-summary-context-percent-field input, .context-compact-threshold-field input { width: 64px; min-height: 32px; padding: 5px 8px; font-size: 13px; font-family: var(--font-latin), monospace; }
1492
+ .config-inline-save { display: flex; align-items: flex-end; gap: 10px; margin: 14px 0 4px; flex-wrap: wrap; }
1493
+ .config-inline-save .book-summary-context-percent-field,
1494
+ .config-inline-save .context-compact-threshold-field { display: grid; gap: 6px; width: auto; margin: 0; color: var(--muted); font-size: 10px; }
1495
+ .config-section .config-save-button { min-height: 32px; padding: 5px 11px; font-size: 11px; }
1496
+ .config-section .card-actions { margin-top: 12px; }
1497
+ .config-section .card-actions .config-save-button { border: 1px solid var(--line); background: transparent; color: var(--ink); }
1410
1498
  .field-label textarea {
1411
1499
  width: 100%;
1412
1500
  min-height: 140px;
@@ -1776,6 +1864,10 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
1776
1864
  .vditor-editor-host .vditor-reset { color: var(--ink); font-family: var(--font-cjk), var(--font-latin), sans-serif; }
1777
1865
  .vditor-editor-host .vditor-ir, .vditor-editor-host .vditor-sv, .vditor-editor-host .vditor-wysiwyg { background: var(--surface); color: var(--ink); }
1778
1866
  .vditor-editor-host .vditor-sv textarea { color: var(--ink); }
1867
+ .vditor-editor-host.vditor--dark .vditor-reset table { background: var(--surface); color: var(--ink); }
1868
+ .vditor-editor-host.vditor--dark .vditor-reset table tr { background: var(--surface); border-top-color: var(--line); }
1869
+ .vditor-editor-host.vditor--dark .vditor-reset table td, .vditor-editor-host.vditor--dark .vditor-reset table th { border-color: var(--line); color: var(--ink); }
1870
+ .vditor-editor-host.vditor--dark .vditor-reset table tbody tr:nth-child(2n) { background: var(--surface-soft); }
1779
1871
  .record-markdown-preview { display: -webkit-box; margin: 12px 0 8px; overflow: hidden; overflow-wrap: anywhere; color: var(--ink); font-size: 12px; line-height: 1.7; -webkit-box-orient: vertical; -webkit-line-clamp: 12; }
1780
1872
  .record-markdown-preview > :first-child, .knowledge-markdown-block .message-body > :first-child { margin-top: 0; }
1781
1873
  .record-markdown-preview > :last-child, .knowledge-markdown-block .message-body > :last-child { margin-bottom: 0; }
@@ -1975,7 +2067,7 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
1975
2067
  }
1976
2068
 
1977
2069
  @media (max-width: 1100px) {
1978
- .left-panel { padding-inline: 10px; }
2070
+ .left-panel-body { padding-inline: 10px; }
1979
2071
  .ai-panel { padding-inline: 14px; }
1980
2072
  .editor-toolbar { grid-template-areas: "path" "title" "actions"; grid-template-columns: minmax(0, 1fr); gap: 12px; padding-inline: 6%; }
1981
2073
  .editor-actions { justify-content: flex-end; flex-wrap: wrap; }
@@ -2038,6 +2130,9 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
2038
2130
  .account-settings-form, .password-settings-form, .api-key-settings, .api-key-result { grid-template-columns: minmax(0, 1fr); }
2039
2131
  .avatar-settings { grid-template-columns: 64px minmax(0, 1fr); }
2040
2132
  .profile-avatar-preview { width: 64px; height: 64px; }
2133
+ .avatar-crop-body { grid-template-columns: minmax(0, 1fr); gap: 12px; padding: 14px 16px 4px; }
2134
+ .avatar-crop-side { grid-template-columns: auto 1fr; align-items: center; justify-items: start; gap: 10px; padding-top: 0; }
2135
+ .avatar-crop-preview { width: 64px; height: 64px; }
2041
2136
  .account-settings-form .primary-button { width: 100%; }
2042
2137
  }
2043
2138
 
@@ -2111,17 +2206,19 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
2111
2206
  grid-column: auto;
2112
2207
  grid-row: auto;
2113
2208
  min-width: 0;
2114
- padding: 76px var(--mobile-gutter) 18px;
2209
+ padding: 0;
2115
2210
  border-left: 1px solid var(--line);
2116
2211
  border-bottom: 1px solid var(--line);
2117
2212
  box-shadow: -12px 0 36px rgba(36, 30, 24, .2);
2118
- overflow-y: auto;
2213
+ overflow: hidden;
2119
2214
  transform: translateX(0);
2120
2215
  transition: transform .2s ease;
2121
2216
  }
2122
- .app-shell.left-panel-collapsed .left-panel { padding: 76px var(--mobile-gutter) 18px; transform: translateX(100%); }
2123
- .app-shell.left-panel-collapsed .left-panel > :not(.left-actions) { display: block; }
2124
- .app-shell.left-panel-collapsed .left-panel > .module-nav { display: grid; }
2217
+ .left-panel-body { padding: 76px var(--mobile-gutter) 18px; }
2218
+ .app-shell.left-panel-collapsed .left-panel { transform: translateX(100%); }
2219
+ .app-shell.left-panel-collapsed .left-panel > .panel-resize-handle { display: none; }
2220
+ .app-shell.left-panel-collapsed .left-panel-body > :not(.left-actions) { display: block; }
2221
+ .app-shell.left-panel-collapsed .left-panel-body > .module-nav { display: grid; }
2125
2222
  .left-panel > .panel-resize-handle { display: none; }
2126
2223
  .left-actions { margin: 0 0 8px; }
2127
2224
  .left-primary-actions { gap: 6px; }
@@ -2137,7 +2234,7 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
2137
2234
  .module-nav .nav-icon { width: 16px; height: 16px; }
2138
2235
  .module-nav .module-nav-secondary.hidden { display: none !important; }
2139
2236
  .panel-heading, #novel-tree { display: none; }
2140
- .app-shell.left-panel-collapsed .left-panel { padding: 8px var(--mobile-gutter) 0; }
2237
+ .app-shell.left-panel-collapsed .left-panel-body { padding: 8px var(--mobile-gutter) 0; }
2141
2238
  .app-shell.left-panel-collapsed .left-actions { display: block; padding: 0; }
2142
2239
 
2143
2240
  .main-panel {
@@ -2201,7 +2298,7 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
2201
2298
 
2202
2299
  .module-view { padding: 26px var(--mobile-gutter) 46px; }
2203
2300
  .module-header { padding-bottom: 18px; }
2204
- .module-header h1 { font-size: 29px; }
2301
+ .module-header h1 { font-size: 22px; }
2205
2302
  .module-header-actions { justify-content: stretch; }
2206
2303
  .module-header-actions > * { flex: 1 1 auto; }
2207
2304
  .module-content { padding: 18px 0 56px; }
package/dist/store.js CHANGED
@@ -608,7 +608,9 @@ export class Store {
608
608
  autoRunBatchLimit: Math.min(200, Math.max(1, Number(row?.auto_run_batch_limit ?? 20) || 20)),
609
609
  bookSummaryContextPercent: Math.min(90, Math.max(1, Number(row?.book_summary_context_percent ?? 50) || 50)),
610
610
  contextCompactThreshold: Math.min(90, Math.max(50, Number(row?.context_compact_threshold ?? 85) || 85)),
611
- agentTools: json(String(row?.agent_tools_json ?? '["story_index","read_chapters","query_story_knowledge","grep","read_character_sections"]'), ["story_index", "read_chapters", "query_story_knowledge", "grep", "read_character_sections"]),
611
+ agentTools: json(String(row?.agent_tools_json ?? '["story_index","read_chapters","search_story_entities","grep","read_character_sections"]'), ["story_index", "read_chapters", "search_story_entities", "grep", "read_character_sections"])
612
+ .map((tool) => tool === "query_story_knowledge" ? "search_story_entities" : tool)
613
+ .filter((tool, index, tools) => tools.indexOf(tool) === index),
612
614
  updatedAt: String(row?.updated_at ?? "")
613
615
  };
614
616
  }
@@ -762,9 +764,9 @@ export class Store {
762
764
  const chapterRows = this.db.all(`SELECT id, work_id, volume_id, title, chapter_type, sort_order, word_count, version_no,
763
765
  analysis_status, excluded_from_analysis, created_at, updated_at
764
766
  FROM chapters WHERE work_id = ? ORDER BY sort_order, created_at${page.sql}`, workId, ...page.params);
765
- const chapters = chapterRows.map((row) => this.mapChapterDirectoryEntry(row));
767
+ const pageResult = paginated(chapterRows.map((row) => this.mapChapterDirectoryEntry(row)), pagination);
766
768
  const chaptersByVolume = new Map();
767
- for (const chapter of chapters) {
769
+ for (const chapter of pageResult.items) {
768
770
  const volumeId = String(chapter.volumeId);
769
771
  const list = chaptersByVolume.get(volumeId) ?? [];
770
772
  list.push(chapter);
@@ -774,7 +776,7 @@ export class Store {
774
776
  ...this.mapVolume(row),
775
777
  chapters: chaptersByVolume.get(requiredString(row, "id")) ?? []
776
778
  }));
777
- return { ...work, volumes, directoryPage: paginated(chapters, pagination) };
779
+ return { ...work, volumes, directoryPage: pageResult };
778
780
  }
779
781
  listFileVersions(workId) {
780
782
  this.getWork(workId);
@@ -2282,8 +2284,9 @@ export class Store {
2282
2284
  listCharactersPage(workId, pagination, includeProfileSections = false, includeMerged = false, includeRaceMarkdown = true) {
2283
2285
  this.getWork(workId);
2284
2286
  const page = paginationSql(pagination);
2287
+ const count = this.db.get(`SELECT COUNT(*) AS count FROM characters WHERE work_id = ?${includeMerged ? "" : " AND merged_into_character_id IS NULL"}`, workId);
2285
2288
  const rows = this.db.all(`SELECT * FROM characters WHERE work_id = ?${includeMerged ? "" : " AND merged_into_character_id IS NULL"} ORDER BY name${page.sql}`, workId, ...page.params);
2286
- return paginated(rows.map((row) => this.mapCharacter(row, includeProfileSections, includeRaceMarkdown)), pagination);
2289
+ return paginated(rows.map((row) => this.mapCharacter(row, includeProfileSections, includeRaceMarkdown)), pagination, Number(count?.count ?? 0));
2287
2290
  }
2288
2291
  mapCharacterProfileSection(row) {
2289
2292
  return {