@oh-story/dsh 0.1.1 → 0.1.2
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.md +2 -2
- package/lib/client.js +285 -135
- package/lib/client.js.map +3 -3
- package/lib/index.js +120 -14677
- package/lib/index.js.map +4 -4
- package/lib/types/client/file-activity.d.ts +6 -3
- package/lib/types/client/file-activity.d.ts.map +1 -1
- package/lib/types/client/index.d.ts +9 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/native-hooks.d.ts +4 -1
- package/lib/types/native-hooks.d.ts.map +1 -1
- package/package.json +1 -3
- package/lib/types/file-activity-projection-types.d.ts +0 -11
- package/lib/types/file-activity-projection-types.d.ts.map +0 -1
- package/lib/types/file-activity-projection.d.ts +0 -24
- package/lib/types/file-activity-projection.d.ts.map +0 -1
package/lib/client.js
CHANGED
|
@@ -24,10 +24,21 @@ __export(index_exports, {
|
|
|
24
24
|
name: () => name
|
|
25
25
|
});
|
|
26
26
|
module.exports = __toCommonJS(index_exports);
|
|
27
|
-
var import_react = require("react"), import_react_dom = require("react-dom");
|
|
27
|
+
var import_client = require("@deepseek-ai/dsh-client-runtime/client"), import_react = require("react"), import_react_dom = require("react-dom");
|
|
28
28
|
|
|
29
29
|
// src/client/file-activity.ts
|
|
30
30
|
var STORY_DIRECTORIES = /* @__PURE__ */ new Set(["\u6B63\u6587", "\u5927\u7EB2", "\u8BBE\u5B9A", "\u8FFD\u8E2A", "\u5BF9\u6807", "\u53C2\u8003\u8D44\u6599"]), DRAMA_DIRECTORIES = /* @__PURE__ */ new Set(["\u8F93\u5165", "\u9879\u76EE\u5F00\u53D1", "\u8BBE\u5B9A\u96C6", "\u5267\u96C6", "\u4EA4\u4ED8", "\u521B\u4F5C\u8005\u51B3\u7B56", "\u5BA1\u67E5"]), EDITABLE_EXTENSION = /\.(?:md|txt|json|jsonl)$/iu, MUTATING_CALLS = /* @__PURE__ */ new Set(["write", "edit", "str_replace_editor", "bash", "run_code", "oh_story_role"]);
|
|
31
|
+
function streamingAssistant(timeline) {
|
|
32
|
+
for (let turnNumber of timeline.turnOrder.toReversed()) {
|
|
33
|
+
let turn = timeline.turns.get(turnNumber);
|
|
34
|
+
if (turn !== void 0)
|
|
35
|
+
for (let step of turn.steps.toReversed()) {
|
|
36
|
+
let assistant = step.data.get("assistant-step");
|
|
37
|
+
if (assistant?.status === "running") return assistant;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
31
42
|
function decodeEscape(character) {
|
|
32
43
|
switch (character) {
|
|
33
44
|
case '"':
|
|
@@ -167,13 +178,14 @@ function visitRunning(blocks, visit) {
|
|
|
167
178
|
for (let block of blocks)
|
|
168
179
|
"kind" in block || visit(block), visitRunning(block.subCalls, visit);
|
|
169
180
|
}
|
|
170
|
-
function fileMutations(runningCalls,
|
|
181
|
+
function fileMutations(runningCalls, partial = null) {
|
|
171
182
|
let values = [];
|
|
172
183
|
visitRunning(runningCalls, (call) => {
|
|
173
184
|
values.push(...mutationsFromRunning(call));
|
|
174
185
|
});
|
|
175
|
-
for (let
|
|
176
|
-
|
|
186
|
+
for (let block of partial?.blocks ?? []) {
|
|
187
|
+
if (block.kind !== "tool-call") continue;
|
|
188
|
+
let value = mutationFromArgs(block.name, block.callId, block.argsRaw, "streaming");
|
|
177
189
|
value !== void 0 && !values.some((candidate) => candidate.callId === value.callId) && values.push(value);
|
|
178
190
|
}
|
|
179
191
|
return values;
|
|
@@ -184,6 +196,26 @@ function mutatingCallIds(runningCalls) {
|
|
|
184
196
|
MUTATING_CALLS.has(call.name) && ids.add(call.callId);
|
|
185
197
|
}), ids;
|
|
186
198
|
}
|
|
199
|
+
function settledMutationSignals(block) {
|
|
200
|
+
let nested = block.subCalls.flatMap(settledMutationSignals);
|
|
201
|
+
if (!("kind" in block) || block.isError) return nested;
|
|
202
|
+
let diffs = block.resultView?.card === "diff" ? block.resultView.diffs : block.callView?.card === "diff" ? block.callView.diffs : void 0;
|
|
203
|
+
if (diffs !== void 0) return [
|
|
204
|
+
...diffs.map((diff, index) => `${block.callId}:${String(index)}\0${diff.path}`),
|
|
205
|
+
...nested
|
|
206
|
+
];
|
|
207
|
+
if (block.call === null) return nested;
|
|
208
|
+
let mutation = mutationFromArgs(block.call.name, block.callId, block.call.argsRaw, "running");
|
|
209
|
+
return mutation?.path === void 0 ? nested : [`${block.callId}\0${mutation.path}`, ...nested];
|
|
210
|
+
}
|
|
211
|
+
function latestSettledMutation(chat) {
|
|
212
|
+
for (let key of chat.order.toReversed()) {
|
|
213
|
+
let node = chat.nodes.get(key);
|
|
214
|
+
if (node?.kind !== "tool-call") continue;
|
|
215
|
+
let root = node.data.root, signal = root === void 0 ? void 0 : settledMutationSignals(root).at(-1);
|
|
216
|
+
if (signal !== void 0) return signal;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
187
219
|
function creativeRelativePath(path, cwd) {
|
|
188
220
|
if (path === void 0 || path === "") return;
|
|
189
221
|
let normalized = path.replaceAll("\\", "/"), root = cwd?.replaceAll("\\", "/").replace(/\/$/u, ""), insideRoot = root !== void 0 && normalized.startsWith(`${root}/`);
|
|
@@ -494,16 +526,16 @@ function MarkdownPreview({ content, label }) {
|
|
|
494
526
|
|
|
495
527
|
// inline-css:/home/runner/work/oh-story-dsh/oh-story-dsh/packages/dsh-plugin/src/client/plugin.css
|
|
496
528
|
var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
497
|
-
.oh-story-split-surface { display: contents; }
|
|
529
|
+
.oh-story-split-surface { display: contents; font-family: var(--dsw-font-family); }
|
|
498
530
|
|
|
499
531
|
/* DSH documents every [data-slot] wrapper as a stable addressable styling
|
|
500
532
|
seam. The official Session body and composer stay mounted; this only turns
|
|
501
533
|
their scroll host into a three-column writing surface. */
|
|
502
534
|
[data-conversation-scroll]:has(> [data-slot="conversation.session"] > .oh-story-split-surface) {
|
|
503
535
|
--os-border: var(--dsw-alias-border-l2);
|
|
504
|
-
--os-muted: var(--dsw-alias-label-
|
|
536
|
+
--os-muted: var(--dsw-alias-label-secondary);
|
|
505
537
|
display: grid;
|
|
506
|
-
grid-template-columns: clamp(
|
|
538
|
+
grid-template-columns: clamp(184px, 16%, 200px) minmax(240px, 1fr) clamp(408px, 40%, 520px);
|
|
507
539
|
grid-template-rows: minmax(0, 1fr);
|
|
508
540
|
min-height: 0;
|
|
509
541
|
overflow-x: hidden;
|
|
@@ -571,7 +603,10 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
571
603
|
gap: 12px;
|
|
572
604
|
}
|
|
573
605
|
|
|
574
|
-
.oh-story-brand { min-height: 28px; padding: 0 5px
|
|
606
|
+
.oh-story-brand { min-height: 28px; gap: 8px; padding: 0 5px 8px 7px; font-size: 14px; font-weight: 500; white-space: nowrap; }
|
|
607
|
+
.oh-story-brand-cluster { display: flex; min-width: 0; align-items: center; gap: 6px; }
|
|
608
|
+
.oh-story-brand-cluster strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: inherit; }
|
|
609
|
+
.oh-story-kind { flex: none; padding: 1px 6px; border-radius: 5px; color: var(--dsw-alias-label-secondary); background: var(--dsw-alias-button-ghost-active-fill); font-size: 11px; line-height: 16px; font-weight: 500; }
|
|
575
610
|
|
|
576
611
|
.oh-story-brand button,
|
|
577
612
|
.oh-story-save,
|
|
@@ -597,39 +632,26 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
597
632
|
.oh-story-role button:focus-visible { outline: 2px solid var(--dsw-alias-state-business-primary); outline-offset: -2px; }
|
|
598
633
|
.oh-story-save:disabled { opacity: .48; cursor: default; }
|
|
599
634
|
|
|
600
|
-
.oh-story-mode-tabs {
|
|
601
|
-
display: grid;
|
|
602
|
-
grid-template-columns: 1fr 1fr;
|
|
603
|
-
margin: 0 4px 10px;
|
|
604
|
-
border-bottom: 1px solid var(--os-border);
|
|
605
|
-
}
|
|
635
|
+
.oh-story-mode-tabs { display: flex; margin: 0 4px 8px; padding: 2px; border: 1px solid var(--os-border); border-radius: 7px; background: var(--dsw-alias-bg-layer-1); }
|
|
606
636
|
|
|
607
637
|
.oh-story-mode-tabs button,
|
|
608
638
|
.oh-story-editor-tabs button {
|
|
609
639
|
position: relative;
|
|
610
|
-
min-height:
|
|
640
|
+
min-height: 24px;
|
|
641
|
+
flex: 1;
|
|
611
642
|
border: 0;
|
|
612
643
|
color: var(--os-muted);
|
|
613
644
|
background: transparent;
|
|
645
|
+
border-radius: 5px;
|
|
614
646
|
cursor: pointer;
|
|
615
647
|
font: inherit;
|
|
616
|
-
font-size:
|
|
648
|
+
font-size: 11px;
|
|
617
649
|
}
|
|
618
650
|
|
|
619
651
|
.oh-story-mode-tabs button:hover,
|
|
620
652
|
.oh-story-editor-tabs button:hover { color: var(--dsw-alias-label-primary); }
|
|
621
653
|
.oh-story-mode-tabs button[aria-selected="true"],
|
|
622
|
-
.oh-story-editor-tabs button[aria-selected="true"] { color: var(--dsw-alias-label-primary); font-weight: 500; }
|
|
623
|
-
.oh-story-mode-tabs button[aria-selected="true"]::after {
|
|
624
|
-
position: absolute;
|
|
625
|
-
right: 14px;
|
|
626
|
-
bottom: -1px;
|
|
627
|
-
left: 14px;
|
|
628
|
-
height: 2px;
|
|
629
|
-
border-radius: 2px 2px 0 0;
|
|
630
|
-
background: var(--dsw-alias-state-business-primary);
|
|
631
|
-
content: "";
|
|
632
|
-
}
|
|
654
|
+
.oh-story-editor-tabs button[aria-selected="true"] { color: var(--dsw-alias-label-primary); background: var(--dsw-alias-bg-base); box-shadow: 0 1px 2px rgb(0 0 0 / 8%); font-weight: 500; }
|
|
633
655
|
|
|
634
656
|
.oh-story-file-group,
|
|
635
657
|
.oh-story-file-folder { margin: 0; }
|
|
@@ -647,6 +669,7 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
647
669
|
font-size: 11px;
|
|
648
670
|
font-weight: 600;
|
|
649
671
|
}
|
|
672
|
+
.oh-story-file-folder > summary { padding-left: min(calc(7px + var(--oh-story-indent, 0px)), 49px); }
|
|
650
673
|
.oh-story-file-group > summary { margin-top: 3px; }
|
|
651
674
|
.oh-story-file-group > summary::-webkit-details-marker,
|
|
652
675
|
.oh-story-file-folder > summary::-webkit-details-marker { display: none; }
|
|
@@ -657,13 +680,13 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
657
680
|
.oh-story-file-group > summary:hover,
|
|
658
681
|
.oh-story-file-folder > summary:hover { color: var(--dsw-alias-label-primary); background: var(--dsw-alias-interactive-bg-hover); }
|
|
659
682
|
.oh-story-file-group > summary span,
|
|
660
|
-
.oh-story-file-folder > summary span { margin-left: auto; color: var(--dsw-alias-label-
|
|
683
|
+
.oh-story-file-folder > summary span { margin-left: auto; color: var(--dsw-alias-label-secondary); font-weight: 400; }
|
|
661
684
|
|
|
662
685
|
.oh-story-tree nav button {
|
|
663
686
|
display: block;
|
|
664
687
|
width: 100%;
|
|
665
688
|
overflow: hidden;
|
|
666
|
-
padding: 6px 8px;
|
|
689
|
+
padding: 6px 8px 6px min(calc(14px + var(--oh-story-indent, 0px)), 56px);
|
|
667
690
|
border: 0;
|
|
668
691
|
border-radius: 6px;
|
|
669
692
|
color: inherit;
|
|
@@ -686,13 +709,17 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
686
709
|
border-bottom: 1px solid var(--os-border);
|
|
687
710
|
}
|
|
688
711
|
|
|
689
|
-
.oh-story-editor
|
|
712
|
+
.oh-story-editor-path {
|
|
690
713
|
overflow: hidden;
|
|
714
|
+
min-width: 0;
|
|
715
|
+
flex: 1;
|
|
691
716
|
text-overflow: ellipsis;
|
|
692
717
|
white-space: nowrap;
|
|
693
718
|
font-size: 12px;
|
|
694
719
|
color: var(--os-muted);
|
|
695
720
|
}
|
|
721
|
+
.oh-story-editor-path > span { overflow: hidden; display: block; text-overflow: ellipsis; }
|
|
722
|
+
.oh-story-editor-path > strong { display: none; overflow: hidden; text-overflow: ellipsis; font: inherit; }
|
|
696
723
|
|
|
697
724
|
.oh-story-editor-actions { display: flex; flex: none; align-items: center; gap: 8px; }
|
|
698
725
|
.oh-story-editor-tabs {
|
|
@@ -703,7 +730,6 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
703
730
|
background: var(--dsw-alias-bg-layer-1);
|
|
704
731
|
}
|
|
705
732
|
.oh-story-editor-tabs button { min-height: 24px; padding: 0 9px; border-radius: 5px; font-size: 11px; }
|
|
706
|
-
.oh-story-editor-tabs button[aria-selected="true"] { background: var(--dsw-alias-bg-base); box-shadow: 0 1px 2px rgb(0 0 0 / 8%); }
|
|
707
733
|
.oh-story-save { min-height: 28px; }
|
|
708
734
|
|
|
709
735
|
.oh-story-editor textarea {
|
|
@@ -714,7 +740,7 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
714
740
|
resize: none;
|
|
715
741
|
border: 0;
|
|
716
742
|
outline: 0;
|
|
717
|
-
padding: clamp(20px,
|
|
743
|
+
padding: clamp(20px, 6%, 48px) clamp(22px, 10%, 84px) 48px;
|
|
718
744
|
color: var(--dsw-alias-label-primary);
|
|
719
745
|
background: transparent;
|
|
720
746
|
font: 16px/1.9 ui-serif, "Songti SC", "STSong", Georgia, serif;
|
|
@@ -730,7 +756,7 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
730
756
|
min-height: 0;
|
|
731
757
|
flex: 1;
|
|
732
758
|
overflow: auto;
|
|
733
|
-
padding: clamp(24px,
|
|
759
|
+
padding: clamp(24px, 8%, 56px) clamp(24px, 10%, 92px) 64px;
|
|
734
760
|
color: var(--dsw-alias-label-primary);
|
|
735
761
|
font: 16px/1.85 ui-serif, "Songti SC", "STSong", Georgia, serif;
|
|
736
762
|
overflow-wrap: anywhere;
|
|
@@ -742,7 +768,7 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
742
768
|
.oh-story-markdown h3,
|
|
743
769
|
.oh-story-markdown h4,
|
|
744
770
|
.oh-story-markdown h5,
|
|
745
|
-
.oh-story-markdown h6 { margin: 1.45em 0 .6em; font-family:
|
|
771
|
+
.oh-story-markdown h6 { margin: 1.45em 0 .6em; font-family: var(--dsw-font-family); line-height: 1.35; letter-spacing: -.01em; }
|
|
746
772
|
.oh-story-markdown h1 { font-size: 1.75em; }
|
|
747
773
|
.oh-story-markdown h2 { padding-bottom: .35em; border-bottom: 1px solid var(--os-border); font-size: 1.35em; }
|
|
748
774
|
.oh-story-markdown h3 { font-size: 1.15em; }
|
|
@@ -787,7 +813,7 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
787
813
|
.oh-story-jsonl-records { overflow: auto; padding: 14px 18px 36px; }
|
|
788
814
|
.oh-story-jsonl details,
|
|
789
815
|
.oh-story-jsonl-error { overflow: hidden; margin-bottom: 10px; border: 1px solid var(--os-border); border-radius: 10px; background: var(--dsw-alias-bg-layer-1); }
|
|
790
|
-
.oh-story-jsonl summary { display: flex; min-height: 42px; align-items: center; gap: 9px; padding: 0 12px; cursor: pointer; list-style: none; font: 12px/1.4
|
|
816
|
+
.oh-story-jsonl summary { display: flex; min-height: 42px; align-items: center; gap: 9px; padding: 0 12px; cursor: pointer; list-style: none; font: 12px/1.4 var(--dsw-font-family); }
|
|
791
817
|
.oh-story-jsonl summary::-webkit-details-marker { display: none; }
|
|
792
818
|
.oh-story-jsonl summary::before { content: "\u203A"; color: var(--os-muted); font-size: 16px; transition: transform .12s ease; }
|
|
793
819
|
.oh-story-jsonl details[open] summary::before { transform: rotate(90deg); }
|
|
@@ -843,49 +869,104 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
843
869
|
.oh-story-role pre { max-height: 260px; overflow: auto; margin: 4px 0 4px 4px; padding: 12px 16px; border: 1px solid var(--dsw-alias-border-l1); border-radius: 12px; color: var(--dsw-alias-label-secondary); background: var(--dsw-alias-markdown-code-block); white-space: pre-wrap; font: var(--dsw-font-markdown-code-block-small); }
|
|
844
870
|
.oh-story-role > button { align-self: flex-start; margin: 4px 0 2px 4px; font-size: 11px; }
|
|
845
871
|
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
grid-template-columns: 104px minmax(210px, 1fr) minmax(252px, 40%);
|
|
849
|
-
}
|
|
850
|
-
.oh-story-editor textarea { padding-right: 28px; padding-left: 28px; }
|
|
872
|
+
[data-conversation-scroll][data-oh-story-layout="medium"]:has(> [data-slot="conversation.session"] > .oh-story-split-surface) {
|
|
873
|
+
grid-template-columns: clamp(104px, 18%, 184px) minmax(200px, 1fr) clamp(300px, 45%, 408px);
|
|
851
874
|
}
|
|
852
875
|
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
grid-template-columns: 72px minmax(0, 1fr) 236px;
|
|
856
|
-
}
|
|
857
|
-
.oh-story-tree { padding-inline: 5px; }
|
|
858
|
-
.oh-story-brand { padding-inline: 3px; font-size: 11px; }
|
|
859
|
-
.oh-story-brand button { width: 24px; }
|
|
860
|
-
.oh-story-mode-tabs { margin-inline: 0; }
|
|
861
|
-
.oh-story-mode-tabs button { font-size: 10px; }
|
|
862
|
-
.oh-story-editor header { padding-inline: 7px; }
|
|
863
|
-
.oh-story-editor header > span { display: none; }
|
|
864
|
-
.oh-story-editor-tabs button { padding-inline: 6px; }
|
|
865
|
-
.oh-story-jsonl summary > code,
|
|
866
|
-
.oh-story-jsonl summary > em { display: none; }
|
|
876
|
+
[data-conversation-scroll][data-oh-story-layout="compact"]:has(> [data-slot="conversation.session"] > .oh-story-split-surface) {
|
|
877
|
+
grid-template-columns: clamp(80px, 16%, 104px) minmax(0, 1fr) clamp(228px, 48%, 300px);
|
|
867
878
|
}
|
|
868
|
-
`;
|
|
869
879
|
|
|
870
|
-
|
|
871
|
-
var
|
|
880
|
+
[data-oh-story-layout="medium"] .oh-story-file-folder > summary { padding-left: min(calc(7px + var(--oh-story-indent, 0px)), 35px); }
|
|
881
|
+
[data-oh-story-layout="medium"] .oh-story-tree nav button { padding-left: min(calc(14px + var(--oh-story-indent, 0px)), 42px); }
|
|
882
|
+
[data-oh-story-layout="medium"] .oh-story-editor textarea { padding-right: 28px; padding-left: 28px; }
|
|
883
|
+
|
|
884
|
+
[data-oh-story-layout="compact"] .oh-story-tree { padding-inline: 4px; }
|
|
885
|
+
[data-oh-story-layout="compact"] .oh-story-brand { gap: 4px; padding-inline: 2px; font-size: 11px; }
|
|
886
|
+
[data-oh-story-layout="compact"] .oh-story-brand-cluster { gap: 4px; }
|
|
887
|
+
[data-oh-story-layout="compact"] .oh-story-brand-cluster strong > span { display: none; }
|
|
888
|
+
[data-oh-story-layout="compact"] .oh-story-kind { padding-inline: 4px; font-size: 11px; }
|
|
889
|
+
[data-oh-story-layout="compact"] .oh-story-brand button { width: 24px; height: 24px; }
|
|
890
|
+
[data-oh-story-layout="compact"] .oh-story-mode-tabs { margin-inline: 0; }
|
|
891
|
+
[data-oh-story-layout="compact"] .oh-story-mode-tabs button { padding-inline: 3px; font-size: 11px; }
|
|
892
|
+
[data-oh-story-layout="compact"] .oh-story-file-folder > summary { padding-left: min(calc(5px + var(--oh-story-indent, 0px)), 19px); }
|
|
893
|
+
[data-oh-story-layout="compact"] .oh-story-tree nav button { padding-right: 4px; padding-left: min(calc(7px + var(--oh-story-indent, 0px)), 21px); }
|
|
894
|
+
[data-oh-story-layout="compact"] .oh-story-editor header {
|
|
895
|
+
display: grid;
|
|
896
|
+
min-height: 68px;
|
|
897
|
+
grid-template-columns: minmax(0, 1fr);
|
|
898
|
+
grid-template-rows: 24px 36px;
|
|
899
|
+
align-content: center;
|
|
900
|
+
gap: 0;
|
|
901
|
+
padding: 4px 3px;
|
|
902
|
+
}
|
|
903
|
+
[data-oh-story-layout="compact"] .oh-story-editor-path > span { display: none; }
|
|
904
|
+
[data-oh-story-layout="compact"] .oh-story-editor-path > strong { display: block; font-size: 11px; line-height: 24px; }
|
|
905
|
+
[data-oh-story-layout="compact"] .oh-story-editor-actions { width: 100%; min-width: 0; justify-content: flex-end; gap: 4px; }
|
|
906
|
+
[data-oh-story-layout="compact"] .oh-story-editor-tabs { min-width: 0; flex: 1; }
|
|
907
|
+
[data-oh-story-layout="compact"] .oh-story-editor-tabs button { min-width: 0; padding-inline: 2px; white-space: nowrap; }
|
|
908
|
+
[data-oh-story-layout="compact"] .oh-story-save { flex: none; padding-inline: 4px; white-space: nowrap; font-size: 11px; }
|
|
909
|
+
[data-oh-story-layout="compact"] .oh-story-editor textarea { padding: 16px 12px 40px; }
|
|
910
|
+
[data-oh-story-layout="compact"] .oh-story-markdown { padding: 18px 12px 48px; }
|
|
911
|
+
[data-oh-story-layout="compact"] .oh-story-jsonl-summary { padding-inline: 10px; }
|
|
912
|
+
[data-oh-story-layout="compact"] .oh-story-jsonl-records { padding: 8px 7px 28px; }
|
|
913
|
+
[data-oh-story-layout="compact"] .oh-story-jsonl summary { gap: 6px; padding-inline: 7px; }
|
|
914
|
+
[data-oh-story-layout="compact"] .oh-story-jsonl summary > span { display: none; }
|
|
915
|
+
[data-oh-story-layout="compact"] .oh-story-jsonl summary > strong { min-width: 32px; }
|
|
916
|
+
[data-oh-story-layout="compact"] .oh-story-jsonl summary > code,
|
|
917
|
+
[data-oh-story-layout="compact"] .oh-story-jsonl summary > em { display: none; }
|
|
918
|
+
`;
|
|
872
919
|
|
|
873
920
|
// src/client/index.tsx
|
|
874
|
-
var import_jsx_runtime3 = require("react/jsx-runtime"), name = "oh-story", inject = ["
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
921
|
+
var import_jsx_runtime3 = require("react/jsx-runtime"), name = "oh-story", inject = ["slots"];
|
|
922
|
+
function applyUpdate(current, update) {
|
|
923
|
+
return typeof update == "function" ? update(current) : update;
|
|
924
|
+
}
|
|
925
|
+
function createWorkbenchStore() {
|
|
926
|
+
return (0, import_client.defineStore)({
|
|
927
|
+
init: () => ({
|
|
928
|
+
buffers: {},
|
|
929
|
+
editorMode: "preview",
|
|
930
|
+
expanded: {},
|
|
931
|
+
selected: void 0,
|
|
932
|
+
workbench: "story"
|
|
933
|
+
}),
|
|
934
|
+
actions: {
|
|
935
|
+
setBuffers: (draft, update) => {
|
|
936
|
+
draft.buffers = applyUpdate(draft.buffers, update);
|
|
937
|
+
},
|
|
938
|
+
setEditorMode: (draft, update) => {
|
|
939
|
+
draft.editorMode = applyUpdate(draft.editorMode, update);
|
|
940
|
+
},
|
|
941
|
+
setExpanded: (draft, update) => {
|
|
942
|
+
draft.expanded = applyUpdate(draft.expanded, update);
|
|
943
|
+
},
|
|
944
|
+
setSelected: (draft, update) => {
|
|
945
|
+
draft.selected = applyUpdate(draft.selected, update);
|
|
946
|
+
},
|
|
947
|
+
setWorkbench: (draft, update) => {
|
|
948
|
+
draft.workbench = applyUpdate(draft.workbench, update);
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
});
|
|
952
|
+
}
|
|
953
|
+
var WorkspaceRequestError = class extends Error {
|
|
880
954
|
constructor(status, message) {
|
|
881
955
|
super(message);
|
|
882
956
|
this.status = status;
|
|
883
957
|
}
|
|
884
958
|
status;
|
|
885
|
-
},
|
|
959
|
+
}, GROUP_ORDER = {
|
|
886
960
|
story: ["\u6B63\u6587", "\u5927\u7EB2", "\u8BBE\u5B9A", "\u8FFD\u8E2A", "\u5BF9\u6807", "\u53C2\u8003\u8D44\u6599"],
|
|
887
961
|
drama: ["\u9879\u76EE", "\u8F93\u5165", "\u9879\u76EE\u5F00\u53D1", "\u8BBE\u5B9A\u96C6", "\u5267\u96C6", "\u5BA1\u67E5", "\u521B\u4F5C\u8005\u51B3\u7B56", "\u4EA4\u4ED8"]
|
|
888
|
-
};
|
|
962
|
+
}, WORKBENCH_MODES = ["story", "drama"], EDITOR_MODES = ["preview", "source"];
|
|
963
|
+
function handleTabKey(event, values, current, select) {
|
|
964
|
+
let index;
|
|
965
|
+
if (event.key === "Home" ? index = 0 : event.key === "End" ? index = values.length - 1 : event.key === "ArrowRight" ? index = (values.indexOf(current) + 1) % values.length : event.key === "ArrowLeft" && (index = (values.indexOf(current) - 1 + values.length) % values.length), index === void 0) return;
|
|
966
|
+
event.preventDefault();
|
|
967
|
+
let value = values[index];
|
|
968
|
+
value !== void 0 && (select(value), event.currentTarget.parentElement?.querySelectorAll("[role='tab']")[index]?.focus());
|
|
969
|
+
}
|
|
889
970
|
function groupForPath(path) {
|
|
890
971
|
return path === "short-drama.json" ? "\u9879\u76EE" : path.split("/", 1)[0] ?? "\u5176\u4ED6";
|
|
891
972
|
}
|
|
@@ -897,7 +978,6 @@ function preferredFile(files, mode) {
|
|
|
897
978
|
}
|
|
898
979
|
return matching[0]?.path;
|
|
899
980
|
}
|
|
900
|
-
var EMPTY_CALLS = [];
|
|
901
981
|
function endpoint(path, sessionId, file) {
|
|
902
982
|
let url = new URL(`/oh-story/${path}`, globalThis.location.origin);
|
|
903
983
|
return url.searchParams.set("sessionId", sessionId), file !== void 0 && url.searchParams.set("path", file), url.toString();
|
|
@@ -921,7 +1001,9 @@ function FileTreeNodes({
|
|
|
921
1001
|
"button",
|
|
922
1002
|
{
|
|
923
1003
|
type: "button",
|
|
924
|
-
style: {
|
|
1004
|
+
style: { "--oh-story-indent": `${String(depth * 14)}px` },
|
|
1005
|
+
title: node.path,
|
|
1006
|
+
"aria-label": node.path,
|
|
925
1007
|
"data-file-path": node.path,
|
|
926
1008
|
"data-agent-target": node.path === activityPath || void 0,
|
|
927
1009
|
"aria-current": node.path === selected ? "page" : void 0,
|
|
@@ -936,7 +1018,7 @@ function FileTreeNodes({
|
|
|
936
1018
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("details", { className: "oh-story-file-folder", open, onToggle: (event) => {
|
|
937
1019
|
onToggle(node.path, event.currentTarget.open);
|
|
938
1020
|
}, children: [
|
|
939
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("summary", { style: {
|
|
1021
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("summary", { style: { "--oh-story-indent": `${String(depth * 14)}px` }, title: node.path, children: [
|
|
940
1022
|
node.name,
|
|
941
1023
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: node.fileCount })
|
|
942
1024
|
] }),
|
|
@@ -973,20 +1055,43 @@ function useWorkspace(sessionId) {
|
|
|
973
1055
|
function CreativeWorkbench({
|
|
974
1056
|
sessionId,
|
|
975
1057
|
runningCalls,
|
|
976
|
-
|
|
1058
|
+
partial,
|
|
1059
|
+
settledMutation,
|
|
1060
|
+
useStore,
|
|
1061
|
+
actions
|
|
977
1062
|
}) {
|
|
978
1063
|
let { workspace, error, loading: workspaceLoading, reload } = useWorkspace(sessionId), activities = (0, import_react.useMemo)(
|
|
979
|
-
() => fileMutations(runningCalls,
|
|
980
|
-
[
|
|
1064
|
+
() => fileMutations(runningCalls, partial),
|
|
1065
|
+
[partial, runningCalls]
|
|
981
1066
|
), normalizedActivities = (0, import_react.useMemo)(() => activities.flatMap((activity2) => {
|
|
982
1067
|
let path = creativeRelativePath(activity2.path, workspace?.cwd);
|
|
983
1068
|
return path === void 0 ? [] : [{ activity: activity2, path }];
|
|
984
|
-
}), [activities, workspace?.cwd]), primaryActivity = normalizedActivities.at(-1), activityPaths = (0, import_react.useMemo)(() => new Set(normalizedActivities.map((value) => value.path)), [normalizedActivities]), activity = primaryActivity?.activity, activityPath = primaryActivity?.path,
|
|
1069
|
+
}), [activities, workspace?.cwd]), primaryActivity = normalizedActivities.at(-1), activityPaths = (0, import_react.useMemo)(() => new Set(normalizedActivities.map((value) => value.path)), [normalizedActivities]), activity = primaryActivity?.activity, activityPath = primaryActivity?.path, workbench = useStore((memory) => memory.workbench), setWorkbench = actions.setWorkbench, initializedWorkbench = (0, import_react.useRef)(!1), selected = useStore((memory) => memory.selected), setSelected = actions.setSelected, buffers = useStore((memory) => memory.buffers), setBuffers = actions.setBuffers, buffersRef = (0, import_react.useRef)({}), expanded = useStore((memory) => memory.expanded), setExpanded = actions.setExpanded, surfaceRef = (0, import_react.useRef)(null), navRef = (0, import_react.useRef)(null), activityBases = (0, import_react.useRef)(/* @__PURE__ */ new Map()), previousSignals = (0, import_react.useRef)(/* @__PURE__ */ new Set()), previousSettledMutation = (0, import_react.useRef)(settledMutation), saveLocks = (0, import_react.useRef)(/* @__PURE__ */ new Set()), buffer = selected === void 0 ? void 0 : buffers[selected], dirty = buffer?.source === "human" && buffer.content !== buffer.saved, saving = buffer?.saving === !0, fileError = buffer?.error, conflict = buffer?.conflict, selectedLower = selected?.toLocaleLowerCase(), markdown = selectedLower?.endsWith(".md") === !0, jsonl = selectedLower?.endsWith(".jsonl") === !0, structured = jsonl || selectedLower?.endsWith(".json") === !0, previewable = markdown || jsonl, editorMode = useStore((memory) => memory.editorMode), setEditorMode = actions.setEditorMode, modeSelection = (0, import_react.useRef)(selected), textareaRef = (0, import_react.useRef)(null), editorPositions = (0, import_react.useRef)(/* @__PURE__ */ new Map()), editorReady = buffer !== void 0 && buffer.missing !== !0, availableModes = (0, import_react.useMemo)(() => {
|
|
1070
|
+
let value = /* @__PURE__ */ new Set();
|
|
1071
|
+
for (let file of workspace?.files ?? []) {
|
|
1072
|
+
let mode = workbenchModeForPath(file.path);
|
|
1073
|
+
mode !== void 0 && value.add(mode);
|
|
1074
|
+
}
|
|
1075
|
+
return WORKBENCH_MODES.filter((mode) => value.has(mode));
|
|
1076
|
+
}, [workspace?.files]), showModeTabs = workspace !== void 0 && availableModes.length !== 1, workspaceKind = availableModes.length === 1 ? availableModes[0] : void 0;
|
|
985
1077
|
(0, import_react.useEffect)(() => {
|
|
986
1078
|
buffersRef.current = buffers;
|
|
987
|
-
}, [buffers])
|
|
988
|
-
|
|
989
|
-
|
|
1079
|
+
}, [buffers]);
|
|
1080
|
+
let rememberEditorPosition = (0, import_react.useCallback)(() => {
|
|
1081
|
+
let element = textareaRef.current;
|
|
1082
|
+
element === null || selected === void 0 || element.getAttribute("aria-label") !== selected || editorPositions.current.set(selected, {
|
|
1083
|
+
scrollTop: element.scrollTop,
|
|
1084
|
+
selectionStart: element.selectionStart,
|
|
1085
|
+
selectionEnd: element.selectionEnd
|
|
1086
|
+
});
|
|
1087
|
+
}, [selected]);
|
|
1088
|
+
(0, import_react.useLayoutEffect)(() => {
|
|
1089
|
+
if (editorMode !== "source" || selected === void 0 || !editorReady) return;
|
|
1090
|
+
let element = textareaRef.current, position = editorPositions.current.get(selected);
|
|
1091
|
+
if (element === null || position === void 0) return;
|
|
1092
|
+
let end = Math.min(position.selectionEnd, element.value.length);
|
|
1093
|
+
element.setSelectionRange(Math.min(position.selectionStart, end), end), element.scrollTop = position.scrollTop;
|
|
1094
|
+
}, [editorMode, editorReady, selected]), (0, import_react.useEffect)(() => {
|
|
990
1095
|
let warn = (event) => {
|
|
991
1096
|
Object.values(buffersRef.current).some((value) => value.source === "human" && value.content !== value.saved) && event.preventDefault();
|
|
992
1097
|
};
|
|
@@ -994,8 +1099,7 @@ function CreativeWorkbench({
|
|
|
994
1099
|
globalThis.removeEventListener("beforeunload", warn);
|
|
995
1100
|
};
|
|
996
1101
|
}, []);
|
|
997
|
-
let
|
|
998
|
-
setWorkbench(workbenchModeForPath(path) ?? "story"), setSelected(path);
|
|
1102
|
+
let expandPath = (0, import_react.useCallback)((path) => {
|
|
999
1103
|
let segments = path.split("/"), ancestors = [groupForPath(path)];
|
|
1000
1104
|
for (let index = 1; index < segments.length - 1; index += 1) ancestors.push(segments.slice(0, index + 1).join("/"));
|
|
1001
1105
|
setExpanded((current) => {
|
|
@@ -1003,24 +1107,22 @@ function CreativeWorkbench({
|
|
|
1003
1107
|
for (let ancestor of ancestors) next[ancestor] = !0;
|
|
1004
1108
|
return next;
|
|
1005
1109
|
});
|
|
1006
|
-
}, [])
|
|
1110
|
+
}, []), revealPath = (0, import_react.useCallback)((path) => {
|
|
1111
|
+
rememberEditorPosition(), setWorkbench(workbenchModeForPath(path) ?? "story"), setSelected(path), expandPath(path);
|
|
1112
|
+
}, [expandPath, rememberEditorPosition]), followAgentPath = (0, import_react.useCallback)((path) => {
|
|
1113
|
+
expandPath(path);
|
|
1114
|
+
let current = selected === void 0 ? void 0 : buffersRef.current[selected];
|
|
1115
|
+
path !== selected && current?.source === "human" && current.content !== current.saved && surfaceRef.current?.ownerDocument.activeElement === textareaRef.current || revealPath(path);
|
|
1116
|
+
}, [expandPath, revealPath, selected]);
|
|
1007
1117
|
(0, import_react.useEffect)(() => {
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
}, [
|
|
1012
|
-
activityPath !== void 0 && setEditorMode("source");
|
|
1013
|
-
}, [activityPath]), (0, import_react.useEffect)(() => {
|
|
1118
|
+
workspace === void 0 || initializedWorkbench.current || (availableModes.length === 1 && setWorkbench(availableModes[0] ?? "story"), initializedWorkbench.current = !0);
|
|
1119
|
+
}, [availableModes, workspace]), (0, import_react.useEffect)(() => {
|
|
1120
|
+
activityPath !== void 0 && activityPath === selected && setEditorMode("source");
|
|
1121
|
+
}, [activityPath, selected]), (0, import_react.useEffect)(() => {
|
|
1014
1122
|
modeSelection.current !== selected && (modeSelection.current = selected, setEditorMode(activityPath === selected ? "source" : previewable ? "preview" : "source"));
|
|
1015
1123
|
}, [activityPath, previewable, selected]), (0, import_react.useEffect)(() => {
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
revealPath(activityPath);
|
|
1019
|
-
return;
|
|
1020
|
-
}
|
|
1021
|
-
selected !== void 0 && ((workspace?.files.some((file) => file.path === selected) ?? !1) || buffers[selected] !== void 0) && workbenchModeForPath(selected) === workbench || setSelected(workspace === void 0 ? void 0 : preferredFile(workspace.files, workbench));
|
|
1022
|
-
}
|
|
1023
|
-
}, [activityPath, buffers, revealPath, selected, workbench, workspace, workspaceLoading]), (0, import_react.useEffect)(() => {
|
|
1124
|
+
workspaceLoading || activityPath === void 0 && (selected !== void 0 && ((workspace?.files.some((file) => file.path === selected) ?? !1) || buffers[selected] !== void 0) && workbenchModeForPath(selected) === workbench || setSelected(workspace === void 0 ? void 0 : preferredFile(workspace.files, workbench)));
|
|
1125
|
+
}, [activityPath, buffers, selected, workbench, workspace, workspaceLoading]), (0, import_react.useEffect)(() => {
|
|
1024
1126
|
if (workspace === void 0 || workspaceLoading) return;
|
|
1025
1127
|
let paths = new Set(workspace.files.map((file) => file.path));
|
|
1026
1128
|
setBuffers((current) => {
|
|
@@ -1068,8 +1170,8 @@ function CreativeWorkbench({
|
|
|
1068
1170
|
};
|
|
1069
1171
|
}, [activityPaths, selected, sessionId, workspace?.files]), (0, import_react.useEffect)(() => {
|
|
1070
1172
|
if (normalizedActivities.length !== 0) {
|
|
1071
|
-
for (let { path } of normalizedActivities)
|
|
1072
|
-
setBuffers((current) => {
|
|
1173
|
+
for (let { path } of normalizedActivities) expandPath(path);
|
|
1174
|
+
activityPath !== void 0 && followAgentPath(activityPath), setBuffers((current) => {
|
|
1073
1175
|
let next = current;
|
|
1074
1176
|
for (let { activity: currentActivity, path } of normalizedActivities) {
|
|
1075
1177
|
let existing = next[path];
|
|
@@ -1099,7 +1201,7 @@ function CreativeWorkbench({
|
|
|
1099
1201
|
return next;
|
|
1100
1202
|
});
|
|
1101
1203
|
}
|
|
1102
|
-
}, [
|
|
1204
|
+
}, [activityPath, expandPath, followAgentPath, normalizedActivities]), (0, import_react.useEffect)(() => {
|
|
1103
1205
|
let signals = new Set(mutatingCallIds(runningCalls));
|
|
1104
1206
|
for (let { activity: currentActivity } of normalizedActivities) signals.add(currentActivity.callId.split(":", 1)[0] ?? currentActivity.callId);
|
|
1105
1207
|
let settled = [...previousSignals.current].some((callId) => !signals.has(callId));
|
|
@@ -1107,6 +1209,11 @@ function CreativeWorkbench({
|
|
|
1107
1209
|
signals.has(callId.split(":", 1)[0] ?? callId) || activityBases.current.delete(callId);
|
|
1108
1210
|
previousSignals.current = signals, settled && reload();
|
|
1109
1211
|
}, [normalizedActivities, reload, runningCalls]), (0, import_react.useEffect)(() => {
|
|
1212
|
+
if (settledMutation === void 0 || settledMutation === previousSettledMutation.current) return;
|
|
1213
|
+
previousSettledMutation.current = settledMutation;
|
|
1214
|
+
let path = creativeRelativePath(settledMutation.slice(settledMutation.indexOf("\0") + 1), workspace?.cwd);
|
|
1215
|
+
path !== void 0 && followAgentPath(path), reload();
|
|
1216
|
+
}, [followAgentPath, reload, settledMutation, workspace?.cwd]), (0, import_react.useEffect)(() => {
|
|
1110
1217
|
if (selected !== void 0) {
|
|
1111
1218
|
for (let button of navRef.current?.querySelectorAll("button[data-file-path]") ?? [])
|
|
1112
1219
|
if (button.dataset.filePath === selected) {
|
|
@@ -1230,7 +1337,9 @@ function CreativeWorkbench({
|
|
|
1230
1337
|
setWorkbench(next);
|
|
1231
1338
|
let target = workspace === void 0 ? void 0 : preferredFile(workspace.files, next);
|
|
1232
1339
|
target === void 0 ? setSelected(void 0) : revealPath(target);
|
|
1233
|
-
},
|
|
1340
|
+
}, selectEditorMode = (next) => {
|
|
1341
|
+
next === "preview" && rememberEditorPosition(), setEditorMode(next);
|
|
1342
|
+
}, selectedLabel = selected ?? `\u5728\u5F53\u524D DSH workspace \u4E2D\u9009\u62E9${workbench === "story" ? "\u5C0F\u8BF4" : "\u77ED\u5267"}\u6587\u4EF6`, selectedBasename = selected?.split("/").at(-1) ?? selectedLabel, selectedGroup = selected === void 0 ? void 0 : groupForPath(selected), toggleGroup = (key, open) => {
|
|
1234
1343
|
setExpanded((current) => ({ ...current, [key]: open }));
|
|
1235
1344
|
}, resolveConflict = (keepLocal) => {
|
|
1236
1345
|
if (selected === void 0 || conflict?.theirs === void 0 || conflict.theirsVersion === void 0) return;
|
|
@@ -1247,17 +1356,32 @@ function CreativeWorkbench({
|
|
|
1247
1356
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("style", { children: plugin_default }),
|
|
1248
1357
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("aside", { className: "oh-story-tree", children: [
|
|
1249
1358
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "oh-story-brand", children: [
|
|
1250
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button",
|
|
1258
|
-
selectWorkbench("drama");
|
|
1259
|
-
}, children: "\u77ED\u5267" })
|
|
1359
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "oh-story-brand-cluster", children: [
|
|
1360
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("strong", { children: [
|
|
1361
|
+
"\u2726 ",
|
|
1362
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "Oh Story" })
|
|
1363
|
+
] }),
|
|
1364
|
+
workspaceKind !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "oh-story-kind", children: workspaceKind === "story" ? "\u5C0F\u8BF4" : "\u77ED\u5267" })
|
|
1365
|
+
] }),
|
|
1366
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", onClick: reload, title: "\u5237\u65B0", "aria-label": "\u5237\u65B0\u9879\u76EE\u6587\u4EF6", children: "\u21BB" })
|
|
1260
1367
|
] }),
|
|
1368
|
+
showModeTabs && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "oh-story-mode-tabs", role: "tablist", "aria-label": "\u521B\u4F5C\u5DE5\u4F5C\u53F0", children: WORKBENCH_MODES.map((mode) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1369
|
+
"button",
|
|
1370
|
+
{
|
|
1371
|
+
type: "button",
|
|
1372
|
+
role: "tab",
|
|
1373
|
+
tabIndex: workbench === mode ? 0 : -1,
|
|
1374
|
+
"aria-selected": workbench === mode,
|
|
1375
|
+
onKeyDown: (event) => {
|
|
1376
|
+
handleTabKey(event, WORKBENCH_MODES, workbench, selectWorkbench);
|
|
1377
|
+
},
|
|
1378
|
+
onClick: () => {
|
|
1379
|
+
selectWorkbench(mode);
|
|
1380
|
+
},
|
|
1381
|
+
children: mode === "story" ? "\u5C0F\u8BF4" : "\u77ED\u5267"
|
|
1382
|
+
},
|
|
1383
|
+
mode
|
|
1384
|
+
)) }),
|
|
1261
1385
|
error !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "oh-story-error", children: error }),
|
|
1262
1386
|
workspace?.metadataErrors.map((message) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "oh-story-warning", children: message }, message)),
|
|
1263
1387
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("nav", { ref: navRef, "aria-label": workbench === "story" ? "\u5C0F\u8BF4\u9879\u76EE\u6587\u4EF6" : "\u77ED\u5267\u9879\u76EE\u6587\u4EF6", children: groups.map(([directory2, files]) => {
|
|
@@ -1286,16 +1410,28 @@ function CreativeWorkbench({
|
|
|
1286
1410
|
] }),
|
|
1287
1411
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("main", { className: "oh-story-editor", children: [
|
|
1288
1412
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("header", { children: [
|
|
1289
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
1413
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "oh-story-editor-path", title: selected, children: [
|
|
1414
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: selectedLabel }),
|
|
1415
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: selectedBasename })
|
|
1416
|
+
] }),
|
|
1290
1417
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "oh-story-editor-actions", children: [
|
|
1291
|
-
previewable && /* @__PURE__ */ (0, import_jsx_runtime3.
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1418
|
+
previewable && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "oh-story-editor-tabs", role: "tablist", "aria-label": markdown ? "Markdown \u67E5\u770B\u65B9\u5F0F" : "JSONL \u67E5\u770B\u65B9\u5F0F", children: EDITOR_MODES.map((mode) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1419
|
+
"button",
|
|
1420
|
+
{
|
|
1421
|
+
type: "button",
|
|
1422
|
+
role: "tab",
|
|
1423
|
+
tabIndex: editorMode === mode ? 0 : -1,
|
|
1424
|
+
"aria-selected": editorMode === mode,
|
|
1425
|
+
onKeyDown: (event) => {
|
|
1426
|
+
handleTabKey(event, EDITOR_MODES, editorMode, selectEditorMode);
|
|
1427
|
+
},
|
|
1428
|
+
onClick: () => {
|
|
1429
|
+
selectEditorMode(mode);
|
|
1430
|
+
},
|
|
1431
|
+
children: mode === "preview" ? "\u9884\u89C8" : "\u6E90\u7801"
|
|
1432
|
+
},
|
|
1433
|
+
mode
|
|
1434
|
+
)) }),
|
|
1299
1435
|
(dirty || saving) && selected !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { className: "oh-story-save", type: "button", disabled: saving || buffer?.missing === !0, onClick: () => {
|
|
1300
1436
|
savePath(selected);
|
|
1301
1437
|
}, children: saving ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58" })
|
|
@@ -1340,8 +1476,12 @@ function CreativeWorkbench({
|
|
|
1340
1476
|
] }) : previewable && editorMode === "preview" ? markdown ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MarkdownPreview, { content: buffer.content, label: selected }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(JsonlPreview, { content: buffer.content, label: selected }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1341
1477
|
"textarea",
|
|
1342
1478
|
{
|
|
1479
|
+
ref: textareaRef,
|
|
1343
1480
|
value: buffer.content,
|
|
1344
1481
|
"data-format": structured ? "structured" : "prose",
|
|
1482
|
+
onBlur: rememberEditorPosition,
|
|
1483
|
+
onScroll: rememberEditorPosition,
|
|
1484
|
+
onSelect: rememberEditorPosition,
|
|
1345
1485
|
onChange: (event) => {
|
|
1346
1486
|
let content = event.target.value;
|
|
1347
1487
|
setBuffers((current) => ({
|
|
@@ -1363,12 +1503,8 @@ function CreativeWorkbench({
|
|
|
1363
1503
|
] })
|
|
1364
1504
|
] });
|
|
1365
1505
|
}
|
|
1366
|
-
function CreativeSplitBridge({
|
|
1367
|
-
let marker = (0, import_react.useRef)(null), [target, setTarget] = (0, import_react.useState)(),
|
|
1368
|
-
}), [source]), getSnapshot = (0, import_react.useCallback)(() => source?.getSnapshot(), [source]), snapshot = (0, import_react.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot), projectionSource = (0, import_react.useMemo)(
|
|
1369
|
-
() => provide.projections?.faceOf(FILE_ACTIVITY_PROJECTION_KEY) ?? EMPTY_FILE_ACTIVITY_STORE,
|
|
1370
|
-
[provide.projections]
|
|
1371
|
-
), subscribeProjection = (0, import_react.useCallback)((listener) => projectionSource.subscribe(listener), [projectionSource]), getProjection = (0, import_react.useCallback)(() => projectionSource.getSnapshot(), [projectionSource]), projection = (0, import_react.useSyncExternalStore)(subscribeProjection, getProjection, getProjection);
|
|
1506
|
+
function CreativeSplitBridge({ sessionId, useSession, useStore, actions }) {
|
|
1507
|
+
let marker = (0, import_react.useRef)(null), [target, setTarget] = (0, import_react.useState)(), runningCalls = useSession((snapshot) => snapshot.runningCalls), partial = useSession((snapshot) => streamingAssistant(snapshot.chat.timeline)), settledMutation = useSession((snapshot) => latestSettledMutation(snapshot.chat));
|
|
1372
1508
|
return (0, import_react.useLayoutEffect)(() => {
|
|
1373
1509
|
let document = marker.current?.ownerDocument;
|
|
1374
1510
|
if (document === void 0) return;
|
|
@@ -1384,27 +1520,34 @@ function CreativeSplitBridge({ context }) {
|
|
|
1384
1520
|
}, [sessionId]), (0, import_react.useLayoutEffect)(() => {
|
|
1385
1521
|
let scroller = target?.parentElement;
|
|
1386
1522
|
if (scroller == null) return;
|
|
1387
|
-
let
|
|
1523
|
+
let publishLayout = () => {
|
|
1388
1524
|
scroller.style.setProperty("--oh-story-scroll-height", `${String(scroller.clientHeight)}px`);
|
|
1525
|
+
let layout = scroller.clientWidth < 620 ? "compact" : scroller.clientWidth < 900 ? "medium" : "wide";
|
|
1526
|
+
scroller.dataset.ohStoryLayout !== layout && (scroller.dataset.ohStoryLayout = layout);
|
|
1389
1527
|
};
|
|
1390
|
-
|
|
1391
|
-
let observer = new ResizeObserver(
|
|
1528
|
+
publishLayout();
|
|
1529
|
+
let observer = new ResizeObserver(publishLayout);
|
|
1392
1530
|
return observer.observe(scroller), () => {
|
|
1393
|
-
observer.disconnect(), scroller.style.removeProperty("--oh-story-scroll-height");
|
|
1531
|
+
observer.disconnect(), scroller.style.removeProperty("--oh-story-scroll-height"), delete scroller.dataset.ohStoryLayout;
|
|
1394
1532
|
};
|
|
1395
1533
|
}, [target]), /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
1396
1534
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { ref: marker, className: "oh-story-bridge-marker", "aria-hidden": !0 }),
|
|
1397
|
-
target === void 0
|
|
1535
|
+
target === void 0 ? null : (0, import_react_dom.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1398
1536
|
CreativeWorkbench,
|
|
1399
1537
|
{
|
|
1400
1538
|
sessionId,
|
|
1401
|
-
runningCalls
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1539
|
+
runningCalls,
|
|
1540
|
+
partial,
|
|
1541
|
+
settledMutation,
|
|
1542
|
+
useStore,
|
|
1543
|
+
actions
|
|
1544
|
+
}
|
|
1405
1545
|
), target)
|
|
1406
1546
|
] });
|
|
1407
1547
|
}
|
|
1548
|
+
function WorkbenchSeat({ SessionProvider, renderSlot }) {
|
|
1549
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SessionProvider, { children: () => renderSlot("oh-story.workspace", {}) });
|
|
1550
|
+
}
|
|
1408
1551
|
function argsOf(block) {
|
|
1409
1552
|
let raw = ("kind" in block ? block.call?.argsRaw : block.argsRaw) ?? "{}";
|
|
1410
1553
|
try {
|
|
@@ -1433,11 +1576,18 @@ function RoleToolView({ block, inspect }) {
|
|
|
1433
1576
|
] });
|
|
1434
1577
|
}
|
|
1435
1578
|
function apply(context) {
|
|
1436
|
-
context.slots.inject("shell.overlay", () =>
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1579
|
+
context.slots.inject("shell.overlay", () => {
|
|
1580
|
+
let disposeSeat = context.slots.register({
|
|
1581
|
+
name: "shell.overlay",
|
|
1582
|
+
id: "oh-story-workspace",
|
|
1583
|
+
order: -100,
|
|
1584
|
+
children: { "oh-story.workspace": { kind: "single", scope: "session" } }
|
|
1585
|
+
}, WorkbenchSeat), disposeWorkbench = context.slots.register({
|
|
1586
|
+
name: "oh-story.workspace",
|
|
1587
|
+
store: createWorkbenchStore
|
|
1588
|
+
}, CreativeSplitBridge);
|
|
1589
|
+
return [disposeSeat, disposeWorkbench];
|
|
1590
|
+
}), context.slots.inject("tool.call.toolview", () => context.slots.register({
|
|
1441
1591
|
name: "tool.call.toolview",
|
|
1442
1592
|
key: "oh_story_role"
|
|
1443
1593
|
}, RoleToolView));
|