@oh-story/dsh 0.1.1 → 0.1.3
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 +292 -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,24 +526,26 @@ 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;
|
|
510
542
|
overflow-y: auto;
|
|
511
543
|
position: relative;
|
|
512
544
|
scrollbar-gutter: stable;
|
|
545
|
+
scroll-padding-bottom: calc(var(--dsh-composer-height, 152px) + 16px);
|
|
513
546
|
}
|
|
514
547
|
|
|
548
|
+
/* Keep the final Chat flow above the overlapping official Composer. */
|
|
515
549
|
[data-conversation-scroll]:has(> [data-slot="conversation.session"] > .oh-story-split-surface)
|
|
516
550
|
> [data-slot="conversation.session"] > :not(.oh-story-split-surface) {
|
|
517
551
|
grid-column: 3;
|
|
@@ -521,6 +555,11 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
521
555
|
border-left: 1px solid var(--os-border);
|
|
522
556
|
}
|
|
523
557
|
|
|
558
|
+
[data-conversation-scroll]:has(> [data-slot="conversation.session"] > .oh-story-split-surface)
|
|
559
|
+
[data-chat-flow] {
|
|
560
|
+
padding-bottom: calc(var(--dsh-composer-height, 152px) + 16px);
|
|
561
|
+
}
|
|
562
|
+
|
|
524
563
|
[data-conversation-scroll]:has(> [data-slot="conversation.session"] > .oh-story-split-surface)
|
|
525
564
|
> [data-composer-seat] {
|
|
526
565
|
grid-column: 3;
|
|
@@ -571,7 +610,10 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
571
610
|
gap: 12px;
|
|
572
611
|
}
|
|
573
612
|
|
|
574
|
-
.oh-story-brand { min-height: 28px; padding: 0 5px
|
|
613
|
+
.oh-story-brand { min-height: 28px; gap: 8px; padding: 0 5px 8px 7px; font-size: 14px; font-weight: 500; white-space: nowrap; }
|
|
614
|
+
.oh-story-brand-cluster { display: flex; min-width: 0; align-items: center; gap: 6px; }
|
|
615
|
+
.oh-story-brand-cluster strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: inherit; }
|
|
616
|
+
.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
617
|
|
|
576
618
|
.oh-story-brand button,
|
|
577
619
|
.oh-story-save,
|
|
@@ -597,39 +639,26 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
597
639
|
.oh-story-role button:focus-visible { outline: 2px solid var(--dsw-alias-state-business-primary); outline-offset: -2px; }
|
|
598
640
|
.oh-story-save:disabled { opacity: .48; cursor: default; }
|
|
599
641
|
|
|
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
|
-
}
|
|
642
|
+
.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
643
|
|
|
607
644
|
.oh-story-mode-tabs button,
|
|
608
645
|
.oh-story-editor-tabs button {
|
|
609
646
|
position: relative;
|
|
610
|
-
min-height:
|
|
647
|
+
min-height: 24px;
|
|
648
|
+
flex: 1;
|
|
611
649
|
border: 0;
|
|
612
650
|
color: var(--os-muted);
|
|
613
651
|
background: transparent;
|
|
652
|
+
border-radius: 5px;
|
|
614
653
|
cursor: pointer;
|
|
615
654
|
font: inherit;
|
|
616
|
-
font-size:
|
|
655
|
+
font-size: 11px;
|
|
617
656
|
}
|
|
618
657
|
|
|
619
658
|
.oh-story-mode-tabs button:hover,
|
|
620
659
|
.oh-story-editor-tabs button:hover { color: var(--dsw-alias-label-primary); }
|
|
621
660
|
.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
|
-
}
|
|
661
|
+
.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
662
|
|
|
634
663
|
.oh-story-file-group,
|
|
635
664
|
.oh-story-file-folder { margin: 0; }
|
|
@@ -647,6 +676,7 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
647
676
|
font-size: 11px;
|
|
648
677
|
font-weight: 600;
|
|
649
678
|
}
|
|
679
|
+
.oh-story-file-folder > summary { padding-left: min(calc(7px + var(--oh-story-indent, 0px)), 49px); }
|
|
650
680
|
.oh-story-file-group > summary { margin-top: 3px; }
|
|
651
681
|
.oh-story-file-group > summary::-webkit-details-marker,
|
|
652
682
|
.oh-story-file-folder > summary::-webkit-details-marker { display: none; }
|
|
@@ -657,13 +687,13 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
657
687
|
.oh-story-file-group > summary:hover,
|
|
658
688
|
.oh-story-file-folder > summary:hover { color: var(--dsw-alias-label-primary); background: var(--dsw-alias-interactive-bg-hover); }
|
|
659
689
|
.oh-story-file-group > summary span,
|
|
660
|
-
.oh-story-file-folder > summary span { margin-left: auto; color: var(--dsw-alias-label-
|
|
690
|
+
.oh-story-file-folder > summary span { margin-left: auto; color: var(--dsw-alias-label-secondary); font-weight: 400; }
|
|
661
691
|
|
|
662
692
|
.oh-story-tree nav button {
|
|
663
693
|
display: block;
|
|
664
694
|
width: 100%;
|
|
665
695
|
overflow: hidden;
|
|
666
|
-
padding: 6px 8px;
|
|
696
|
+
padding: 6px 8px 6px min(calc(14px + var(--oh-story-indent, 0px)), 56px);
|
|
667
697
|
border: 0;
|
|
668
698
|
border-radius: 6px;
|
|
669
699
|
color: inherit;
|
|
@@ -686,13 +716,17 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
686
716
|
border-bottom: 1px solid var(--os-border);
|
|
687
717
|
}
|
|
688
718
|
|
|
689
|
-
.oh-story-editor
|
|
719
|
+
.oh-story-editor-path {
|
|
690
720
|
overflow: hidden;
|
|
721
|
+
min-width: 0;
|
|
722
|
+
flex: 1;
|
|
691
723
|
text-overflow: ellipsis;
|
|
692
724
|
white-space: nowrap;
|
|
693
725
|
font-size: 12px;
|
|
694
726
|
color: var(--os-muted);
|
|
695
727
|
}
|
|
728
|
+
.oh-story-editor-path > span { overflow: hidden; display: block; text-overflow: ellipsis; }
|
|
729
|
+
.oh-story-editor-path > strong { display: none; overflow: hidden; text-overflow: ellipsis; font: inherit; }
|
|
696
730
|
|
|
697
731
|
.oh-story-editor-actions { display: flex; flex: none; align-items: center; gap: 8px; }
|
|
698
732
|
.oh-story-editor-tabs {
|
|
@@ -703,7 +737,6 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
703
737
|
background: var(--dsw-alias-bg-layer-1);
|
|
704
738
|
}
|
|
705
739
|
.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
740
|
.oh-story-save { min-height: 28px; }
|
|
708
741
|
|
|
709
742
|
.oh-story-editor textarea {
|
|
@@ -714,7 +747,7 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
714
747
|
resize: none;
|
|
715
748
|
border: 0;
|
|
716
749
|
outline: 0;
|
|
717
|
-
padding: clamp(20px,
|
|
750
|
+
padding: clamp(20px, 6%, 48px) clamp(22px, 10%, 84px) 48px;
|
|
718
751
|
color: var(--dsw-alias-label-primary);
|
|
719
752
|
background: transparent;
|
|
720
753
|
font: 16px/1.9 ui-serif, "Songti SC", "STSong", Georgia, serif;
|
|
@@ -730,7 +763,7 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
730
763
|
min-height: 0;
|
|
731
764
|
flex: 1;
|
|
732
765
|
overflow: auto;
|
|
733
|
-
padding: clamp(24px,
|
|
766
|
+
padding: clamp(24px, 8%, 56px) clamp(24px, 10%, 92px) 64px;
|
|
734
767
|
color: var(--dsw-alias-label-primary);
|
|
735
768
|
font: 16px/1.85 ui-serif, "Songti SC", "STSong", Georgia, serif;
|
|
736
769
|
overflow-wrap: anywhere;
|
|
@@ -742,7 +775,7 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
742
775
|
.oh-story-markdown h3,
|
|
743
776
|
.oh-story-markdown h4,
|
|
744
777
|
.oh-story-markdown h5,
|
|
745
|
-
.oh-story-markdown h6 { margin: 1.45em 0 .6em; font-family:
|
|
778
|
+
.oh-story-markdown h6 { margin: 1.45em 0 .6em; font-family: var(--dsw-font-family); line-height: 1.35; letter-spacing: -.01em; }
|
|
746
779
|
.oh-story-markdown h1 { font-size: 1.75em; }
|
|
747
780
|
.oh-story-markdown h2 { padding-bottom: .35em; border-bottom: 1px solid var(--os-border); font-size: 1.35em; }
|
|
748
781
|
.oh-story-markdown h3 { font-size: 1.15em; }
|
|
@@ -787,7 +820,7 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
787
820
|
.oh-story-jsonl-records { overflow: auto; padding: 14px 18px 36px; }
|
|
788
821
|
.oh-story-jsonl details,
|
|
789
822
|
.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
|
|
823
|
+
.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
824
|
.oh-story-jsonl summary::-webkit-details-marker { display: none; }
|
|
792
825
|
.oh-story-jsonl summary::before { content: "\u203A"; color: var(--os-muted); font-size: 16px; transition: transform .12s ease; }
|
|
793
826
|
.oh-story-jsonl details[open] summary::before { transform: rotate(90deg); }
|
|
@@ -843,49 +876,104 @@ var plugin_default = `.oh-story-bridge-marker { display: none; }
|
|
|
843
876
|
.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
877
|
.oh-story-role > button { align-self: flex-start; margin: 4px 0 2px 4px; font-size: 11px; }
|
|
845
878
|
|
|
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; }
|
|
879
|
+
[data-conversation-scroll][data-oh-story-layout="medium"]:has(> [data-slot="conversation.session"] > .oh-story-split-surface) {
|
|
880
|
+
grid-template-columns: clamp(104px, 18%, 184px) minmax(200px, 1fr) clamp(300px, 45%, 408px);
|
|
851
881
|
}
|
|
852
882
|
|
|
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; }
|
|
883
|
+
[data-conversation-scroll][data-oh-story-layout="compact"]:has(> [data-slot="conversation.session"] > .oh-story-split-surface) {
|
|
884
|
+
grid-template-columns: clamp(80px, 16%, 104px) minmax(0, 1fr) clamp(228px, 48%, 300px);
|
|
867
885
|
}
|
|
868
|
-
`;
|
|
869
886
|
|
|
870
|
-
|
|
871
|
-
var
|
|
887
|
+
[data-oh-story-layout="medium"] .oh-story-file-folder > summary { padding-left: min(calc(7px + var(--oh-story-indent, 0px)), 35px); }
|
|
888
|
+
[data-oh-story-layout="medium"] .oh-story-tree nav button { padding-left: min(calc(14px + var(--oh-story-indent, 0px)), 42px); }
|
|
889
|
+
[data-oh-story-layout="medium"] .oh-story-editor textarea { padding-right: 28px; padding-left: 28px; }
|
|
890
|
+
|
|
891
|
+
[data-oh-story-layout="compact"] .oh-story-tree { padding-inline: 4px; }
|
|
892
|
+
[data-oh-story-layout="compact"] .oh-story-brand { gap: 4px; padding-inline: 2px; font-size: 11px; }
|
|
893
|
+
[data-oh-story-layout="compact"] .oh-story-brand-cluster { gap: 4px; }
|
|
894
|
+
[data-oh-story-layout="compact"] .oh-story-brand-cluster strong > span { display: none; }
|
|
895
|
+
[data-oh-story-layout="compact"] .oh-story-kind { padding-inline: 4px; font-size: 11px; }
|
|
896
|
+
[data-oh-story-layout="compact"] .oh-story-brand button { width: 24px; height: 24px; }
|
|
897
|
+
[data-oh-story-layout="compact"] .oh-story-mode-tabs { margin-inline: 0; }
|
|
898
|
+
[data-oh-story-layout="compact"] .oh-story-mode-tabs button { padding-inline: 3px; font-size: 11px; }
|
|
899
|
+
[data-oh-story-layout="compact"] .oh-story-file-folder > summary { padding-left: min(calc(5px + var(--oh-story-indent, 0px)), 19px); }
|
|
900
|
+
[data-oh-story-layout="compact"] .oh-story-tree nav button { padding-right: 4px; padding-left: min(calc(7px + var(--oh-story-indent, 0px)), 21px); }
|
|
901
|
+
[data-oh-story-layout="compact"] .oh-story-editor header {
|
|
902
|
+
display: grid;
|
|
903
|
+
min-height: 68px;
|
|
904
|
+
grid-template-columns: minmax(0, 1fr);
|
|
905
|
+
grid-template-rows: 24px 36px;
|
|
906
|
+
align-content: center;
|
|
907
|
+
gap: 0;
|
|
908
|
+
padding: 4px 3px;
|
|
909
|
+
}
|
|
910
|
+
[data-oh-story-layout="compact"] .oh-story-editor-path > span { display: none; }
|
|
911
|
+
[data-oh-story-layout="compact"] .oh-story-editor-path > strong { display: block; font-size: 11px; line-height: 24px; }
|
|
912
|
+
[data-oh-story-layout="compact"] .oh-story-editor-actions { width: 100%; min-width: 0; justify-content: flex-end; gap: 4px; }
|
|
913
|
+
[data-oh-story-layout="compact"] .oh-story-editor-tabs { min-width: 0; flex: 1; }
|
|
914
|
+
[data-oh-story-layout="compact"] .oh-story-editor-tabs button { min-width: 0; padding-inline: 2px; white-space: nowrap; }
|
|
915
|
+
[data-oh-story-layout="compact"] .oh-story-save { flex: none; padding-inline: 4px; white-space: nowrap; font-size: 11px; }
|
|
916
|
+
[data-oh-story-layout="compact"] .oh-story-editor textarea { padding: 16px 12px 40px; }
|
|
917
|
+
[data-oh-story-layout="compact"] .oh-story-markdown { padding: 18px 12px 48px; }
|
|
918
|
+
[data-oh-story-layout="compact"] .oh-story-jsonl-summary { padding-inline: 10px; }
|
|
919
|
+
[data-oh-story-layout="compact"] .oh-story-jsonl-records { padding: 8px 7px 28px; }
|
|
920
|
+
[data-oh-story-layout="compact"] .oh-story-jsonl summary { gap: 6px; padding-inline: 7px; }
|
|
921
|
+
[data-oh-story-layout="compact"] .oh-story-jsonl summary > span { display: none; }
|
|
922
|
+
[data-oh-story-layout="compact"] .oh-story-jsonl summary > strong { min-width: 32px; }
|
|
923
|
+
[data-oh-story-layout="compact"] .oh-story-jsonl summary > code,
|
|
924
|
+
[data-oh-story-layout="compact"] .oh-story-jsonl summary > em { display: none; }
|
|
925
|
+
`;
|
|
872
926
|
|
|
873
927
|
// src/client/index.tsx
|
|
874
|
-
var import_jsx_runtime3 = require("react/jsx-runtime"), name = "oh-story", inject = ["
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
928
|
+
var import_jsx_runtime3 = require("react/jsx-runtime"), name = "oh-story", inject = ["slots"];
|
|
929
|
+
function applyUpdate(current, update) {
|
|
930
|
+
return typeof update == "function" ? update(current) : update;
|
|
931
|
+
}
|
|
932
|
+
function createWorkbenchStore() {
|
|
933
|
+
return (0, import_client.defineStore)({
|
|
934
|
+
init: () => ({
|
|
935
|
+
buffers: {},
|
|
936
|
+
editorMode: "preview",
|
|
937
|
+
expanded: {},
|
|
938
|
+
selected: void 0,
|
|
939
|
+
workbench: "story"
|
|
940
|
+
}),
|
|
941
|
+
actions: {
|
|
942
|
+
setBuffers: (draft, update) => {
|
|
943
|
+
draft.buffers = applyUpdate(draft.buffers, update);
|
|
944
|
+
},
|
|
945
|
+
setEditorMode: (draft, update) => {
|
|
946
|
+
draft.editorMode = applyUpdate(draft.editorMode, update);
|
|
947
|
+
},
|
|
948
|
+
setExpanded: (draft, update) => {
|
|
949
|
+
draft.expanded = applyUpdate(draft.expanded, update);
|
|
950
|
+
},
|
|
951
|
+
setSelected: (draft, update) => {
|
|
952
|
+
draft.selected = applyUpdate(draft.selected, update);
|
|
953
|
+
},
|
|
954
|
+
setWorkbench: (draft, update) => {
|
|
955
|
+
draft.workbench = applyUpdate(draft.workbench, update);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
});
|
|
959
|
+
}
|
|
960
|
+
var WorkspaceRequestError = class extends Error {
|
|
880
961
|
constructor(status, message) {
|
|
881
962
|
super(message);
|
|
882
963
|
this.status = status;
|
|
883
964
|
}
|
|
884
965
|
status;
|
|
885
|
-
},
|
|
966
|
+
}, GROUP_ORDER = {
|
|
886
967
|
story: ["\u6B63\u6587", "\u5927\u7EB2", "\u8BBE\u5B9A", "\u8FFD\u8E2A", "\u5BF9\u6807", "\u53C2\u8003\u8D44\u6599"],
|
|
887
968
|
drama: ["\u9879\u76EE", "\u8F93\u5165", "\u9879\u76EE\u5F00\u53D1", "\u8BBE\u5B9A\u96C6", "\u5267\u96C6", "\u5BA1\u67E5", "\u521B\u4F5C\u8005\u51B3\u7B56", "\u4EA4\u4ED8"]
|
|
888
|
-
};
|
|
969
|
+
}, WORKBENCH_MODES = ["story", "drama"], EDITOR_MODES = ["preview", "source"];
|
|
970
|
+
function handleTabKey(event, values, current, select) {
|
|
971
|
+
let index;
|
|
972
|
+
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;
|
|
973
|
+
event.preventDefault();
|
|
974
|
+
let value = values[index];
|
|
975
|
+
value !== void 0 && (select(value), event.currentTarget.parentElement?.querySelectorAll("[role='tab']")[index]?.focus());
|
|
976
|
+
}
|
|
889
977
|
function groupForPath(path) {
|
|
890
978
|
return path === "short-drama.json" ? "\u9879\u76EE" : path.split("/", 1)[0] ?? "\u5176\u4ED6";
|
|
891
979
|
}
|
|
@@ -897,7 +985,6 @@ function preferredFile(files, mode) {
|
|
|
897
985
|
}
|
|
898
986
|
return matching[0]?.path;
|
|
899
987
|
}
|
|
900
|
-
var EMPTY_CALLS = [];
|
|
901
988
|
function endpoint(path, sessionId, file) {
|
|
902
989
|
let url = new URL(`/oh-story/${path}`, globalThis.location.origin);
|
|
903
990
|
return url.searchParams.set("sessionId", sessionId), file !== void 0 && url.searchParams.set("path", file), url.toString();
|
|
@@ -921,7 +1008,9 @@ function FileTreeNodes({
|
|
|
921
1008
|
"button",
|
|
922
1009
|
{
|
|
923
1010
|
type: "button",
|
|
924
|
-
style: {
|
|
1011
|
+
style: { "--oh-story-indent": `${String(depth * 14)}px` },
|
|
1012
|
+
title: node.path,
|
|
1013
|
+
"aria-label": node.path,
|
|
925
1014
|
"data-file-path": node.path,
|
|
926
1015
|
"data-agent-target": node.path === activityPath || void 0,
|
|
927
1016
|
"aria-current": node.path === selected ? "page" : void 0,
|
|
@@ -936,7 +1025,7 @@ function FileTreeNodes({
|
|
|
936
1025
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("details", { className: "oh-story-file-folder", open, onToggle: (event) => {
|
|
937
1026
|
onToggle(node.path, event.currentTarget.open);
|
|
938
1027
|
}, children: [
|
|
939
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("summary", { style: {
|
|
1028
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("summary", { style: { "--oh-story-indent": `${String(depth * 14)}px` }, title: node.path, children: [
|
|
940
1029
|
node.name,
|
|
941
1030
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: node.fileCount })
|
|
942
1031
|
] }),
|
|
@@ -973,20 +1062,43 @@ function useWorkspace(sessionId) {
|
|
|
973
1062
|
function CreativeWorkbench({
|
|
974
1063
|
sessionId,
|
|
975
1064
|
runningCalls,
|
|
976
|
-
|
|
1065
|
+
partial,
|
|
1066
|
+
settledMutation,
|
|
1067
|
+
useStore,
|
|
1068
|
+
actions
|
|
977
1069
|
}) {
|
|
978
1070
|
let { workspace, error, loading: workspaceLoading, reload } = useWorkspace(sessionId), activities = (0, import_react.useMemo)(
|
|
979
|
-
() => fileMutations(runningCalls,
|
|
980
|
-
[
|
|
1071
|
+
() => fileMutations(runningCalls, partial),
|
|
1072
|
+
[partial, runningCalls]
|
|
981
1073
|
), normalizedActivities = (0, import_react.useMemo)(() => activities.flatMap((activity2) => {
|
|
982
1074
|
let path = creativeRelativePath(activity2.path, workspace?.cwd);
|
|
983
1075
|
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,
|
|
1076
|
+
}), [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)(() => {
|
|
1077
|
+
let value = /* @__PURE__ */ new Set();
|
|
1078
|
+
for (let file of workspace?.files ?? []) {
|
|
1079
|
+
let mode = workbenchModeForPath(file.path);
|
|
1080
|
+
mode !== void 0 && value.add(mode);
|
|
1081
|
+
}
|
|
1082
|
+
return WORKBENCH_MODES.filter((mode) => value.has(mode));
|
|
1083
|
+
}, [workspace?.files]), showModeTabs = workspace !== void 0 && availableModes.length !== 1, workspaceKind = availableModes.length === 1 ? availableModes[0] : void 0;
|
|
985
1084
|
(0, import_react.useEffect)(() => {
|
|
986
1085
|
buffersRef.current = buffers;
|
|
987
|
-
}, [buffers])
|
|
988
|
-
|
|
989
|
-
|
|
1086
|
+
}, [buffers]);
|
|
1087
|
+
let rememberEditorPosition = (0, import_react.useCallback)(() => {
|
|
1088
|
+
let element = textareaRef.current;
|
|
1089
|
+
element === null || selected === void 0 || element.getAttribute("aria-label") !== selected || editorPositions.current.set(selected, {
|
|
1090
|
+
scrollTop: element.scrollTop,
|
|
1091
|
+
selectionStart: element.selectionStart,
|
|
1092
|
+
selectionEnd: element.selectionEnd
|
|
1093
|
+
});
|
|
1094
|
+
}, [selected]);
|
|
1095
|
+
(0, import_react.useLayoutEffect)(() => {
|
|
1096
|
+
if (editorMode !== "source" || selected === void 0 || !editorReady) return;
|
|
1097
|
+
let element = textareaRef.current, position = editorPositions.current.get(selected);
|
|
1098
|
+
if (element === null || position === void 0) return;
|
|
1099
|
+
let end = Math.min(position.selectionEnd, element.value.length);
|
|
1100
|
+
element.setSelectionRange(Math.min(position.selectionStart, end), end), element.scrollTop = position.scrollTop;
|
|
1101
|
+
}, [editorMode, editorReady, selected]), (0, import_react.useEffect)(() => {
|
|
990
1102
|
let warn = (event) => {
|
|
991
1103
|
Object.values(buffersRef.current).some((value) => value.source === "human" && value.content !== value.saved) && event.preventDefault();
|
|
992
1104
|
};
|
|
@@ -994,8 +1106,7 @@ function CreativeWorkbench({
|
|
|
994
1106
|
globalThis.removeEventListener("beforeunload", warn);
|
|
995
1107
|
};
|
|
996
1108
|
}, []);
|
|
997
|
-
let
|
|
998
|
-
setWorkbench(workbenchModeForPath(path) ?? "story"), setSelected(path);
|
|
1109
|
+
let expandPath = (0, import_react.useCallback)((path) => {
|
|
999
1110
|
let segments = path.split("/"), ancestors = [groupForPath(path)];
|
|
1000
1111
|
for (let index = 1; index < segments.length - 1; index += 1) ancestors.push(segments.slice(0, index + 1).join("/"));
|
|
1001
1112
|
setExpanded((current) => {
|
|
@@ -1003,24 +1114,22 @@ function CreativeWorkbench({
|
|
|
1003
1114
|
for (let ancestor of ancestors) next[ancestor] = !0;
|
|
1004
1115
|
return next;
|
|
1005
1116
|
});
|
|
1006
|
-
}, [])
|
|
1117
|
+
}, []), revealPath = (0, import_react.useCallback)((path) => {
|
|
1118
|
+
rememberEditorPosition(), setWorkbench(workbenchModeForPath(path) ?? "story"), setSelected(path), expandPath(path);
|
|
1119
|
+
}, [expandPath, rememberEditorPosition]), followAgentPath = (0, import_react.useCallback)((path) => {
|
|
1120
|
+
expandPath(path);
|
|
1121
|
+
let current = selected === void 0 ? void 0 : buffersRef.current[selected];
|
|
1122
|
+
path !== selected && current?.source === "human" && current.content !== current.saved && surfaceRef.current?.ownerDocument.activeElement === textareaRef.current || revealPath(path);
|
|
1123
|
+
}, [expandPath, revealPath, selected]);
|
|
1007
1124
|
(0, import_react.useEffect)(() => {
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
}, [
|
|
1012
|
-
activityPath !== void 0 && setEditorMode("source");
|
|
1013
|
-
}, [activityPath]), (0, import_react.useEffect)(() => {
|
|
1125
|
+
workspace === void 0 || initializedWorkbench.current || (availableModes.length === 1 && setWorkbench(availableModes[0] ?? "story"), initializedWorkbench.current = !0);
|
|
1126
|
+
}, [availableModes, workspace]), (0, import_react.useEffect)(() => {
|
|
1127
|
+
activityPath !== void 0 && activityPath === selected && setEditorMode("source");
|
|
1128
|
+
}, [activityPath, selected]), (0, import_react.useEffect)(() => {
|
|
1014
1129
|
modeSelection.current !== selected && (modeSelection.current = selected, setEditorMode(activityPath === selected ? "source" : previewable ? "preview" : "source"));
|
|
1015
1130
|
}, [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)(() => {
|
|
1131
|
+
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)));
|
|
1132
|
+
}, [activityPath, buffers, selected, workbench, workspace, workspaceLoading]), (0, import_react.useEffect)(() => {
|
|
1024
1133
|
if (workspace === void 0 || workspaceLoading) return;
|
|
1025
1134
|
let paths = new Set(workspace.files.map((file) => file.path));
|
|
1026
1135
|
setBuffers((current) => {
|
|
@@ -1068,8 +1177,8 @@ function CreativeWorkbench({
|
|
|
1068
1177
|
};
|
|
1069
1178
|
}, [activityPaths, selected, sessionId, workspace?.files]), (0, import_react.useEffect)(() => {
|
|
1070
1179
|
if (normalizedActivities.length !== 0) {
|
|
1071
|
-
for (let { path } of normalizedActivities)
|
|
1072
|
-
setBuffers((current) => {
|
|
1180
|
+
for (let { path } of normalizedActivities) expandPath(path);
|
|
1181
|
+
activityPath !== void 0 && followAgentPath(activityPath), setBuffers((current) => {
|
|
1073
1182
|
let next = current;
|
|
1074
1183
|
for (let { activity: currentActivity, path } of normalizedActivities) {
|
|
1075
1184
|
let existing = next[path];
|
|
@@ -1099,7 +1208,7 @@ function CreativeWorkbench({
|
|
|
1099
1208
|
return next;
|
|
1100
1209
|
});
|
|
1101
1210
|
}
|
|
1102
|
-
}, [
|
|
1211
|
+
}, [activityPath, expandPath, followAgentPath, normalizedActivities]), (0, import_react.useEffect)(() => {
|
|
1103
1212
|
let signals = new Set(mutatingCallIds(runningCalls));
|
|
1104
1213
|
for (let { activity: currentActivity } of normalizedActivities) signals.add(currentActivity.callId.split(":", 1)[0] ?? currentActivity.callId);
|
|
1105
1214
|
let settled = [...previousSignals.current].some((callId) => !signals.has(callId));
|
|
@@ -1107,6 +1216,11 @@ function CreativeWorkbench({
|
|
|
1107
1216
|
signals.has(callId.split(":", 1)[0] ?? callId) || activityBases.current.delete(callId);
|
|
1108
1217
|
previousSignals.current = signals, settled && reload();
|
|
1109
1218
|
}, [normalizedActivities, reload, runningCalls]), (0, import_react.useEffect)(() => {
|
|
1219
|
+
if (settledMutation === void 0 || settledMutation === previousSettledMutation.current) return;
|
|
1220
|
+
previousSettledMutation.current = settledMutation;
|
|
1221
|
+
let path = creativeRelativePath(settledMutation.slice(settledMutation.indexOf("\0") + 1), workspace?.cwd);
|
|
1222
|
+
path !== void 0 && followAgentPath(path), reload();
|
|
1223
|
+
}, [followAgentPath, reload, settledMutation, workspace?.cwd]), (0, import_react.useEffect)(() => {
|
|
1110
1224
|
if (selected !== void 0) {
|
|
1111
1225
|
for (let button of navRef.current?.querySelectorAll("button[data-file-path]") ?? [])
|
|
1112
1226
|
if (button.dataset.filePath === selected) {
|
|
@@ -1230,7 +1344,9 @@ function CreativeWorkbench({
|
|
|
1230
1344
|
setWorkbench(next);
|
|
1231
1345
|
let target = workspace === void 0 ? void 0 : preferredFile(workspace.files, next);
|
|
1232
1346
|
target === void 0 ? setSelected(void 0) : revealPath(target);
|
|
1233
|
-
},
|
|
1347
|
+
}, selectEditorMode = (next) => {
|
|
1348
|
+
next === "preview" && rememberEditorPosition(), setEditorMode(next);
|
|
1349
|
+
}, 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
1350
|
setExpanded((current) => ({ ...current, [key]: open }));
|
|
1235
1351
|
}, resolveConflict = (keepLocal) => {
|
|
1236
1352
|
if (selected === void 0 || conflict?.theirs === void 0 || conflict.theirsVersion === void 0) return;
|
|
@@ -1247,17 +1363,32 @@ function CreativeWorkbench({
|
|
|
1247
1363
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("style", { children: plugin_default }),
|
|
1248
1364
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("aside", { className: "oh-story-tree", children: [
|
|
1249
1365
|
/* @__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" })
|
|
1366
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "oh-story-brand-cluster", children: [
|
|
1367
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("strong", { children: [
|
|
1368
|
+
"\u2726 ",
|
|
1369
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "Oh Story" })
|
|
1370
|
+
] }),
|
|
1371
|
+
workspaceKind !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "oh-story-kind", children: workspaceKind === "story" ? "\u5C0F\u8BF4" : "\u77ED\u5267" })
|
|
1372
|
+
] }),
|
|
1373
|
+
/* @__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
1374
|
] }),
|
|
1375
|
+
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)(
|
|
1376
|
+
"button",
|
|
1377
|
+
{
|
|
1378
|
+
type: "button",
|
|
1379
|
+
role: "tab",
|
|
1380
|
+
tabIndex: workbench === mode ? 0 : -1,
|
|
1381
|
+
"aria-selected": workbench === mode,
|
|
1382
|
+
onKeyDown: (event) => {
|
|
1383
|
+
handleTabKey(event, WORKBENCH_MODES, workbench, selectWorkbench);
|
|
1384
|
+
},
|
|
1385
|
+
onClick: () => {
|
|
1386
|
+
selectWorkbench(mode);
|
|
1387
|
+
},
|
|
1388
|
+
children: mode === "story" ? "\u5C0F\u8BF4" : "\u77ED\u5267"
|
|
1389
|
+
},
|
|
1390
|
+
mode
|
|
1391
|
+
)) }),
|
|
1261
1392
|
error !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "oh-story-error", children: error }),
|
|
1262
1393
|
workspace?.metadataErrors.map((message) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "oh-story-warning", children: message }, message)),
|
|
1263
1394
|
/* @__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 +1417,28 @@ function CreativeWorkbench({
|
|
|
1286
1417
|
] }),
|
|
1287
1418
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("main", { className: "oh-story-editor", children: [
|
|
1288
1419
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("header", { children: [
|
|
1289
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
1420
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "oh-story-editor-path", title: selected, children: [
|
|
1421
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: selectedLabel }),
|
|
1422
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: selectedBasename })
|
|
1423
|
+
] }),
|
|
1290
1424
|
/* @__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
|
-
|
|
1425
|
+
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)(
|
|
1426
|
+
"button",
|
|
1427
|
+
{
|
|
1428
|
+
type: "button",
|
|
1429
|
+
role: "tab",
|
|
1430
|
+
tabIndex: editorMode === mode ? 0 : -1,
|
|
1431
|
+
"aria-selected": editorMode === mode,
|
|
1432
|
+
onKeyDown: (event) => {
|
|
1433
|
+
handleTabKey(event, EDITOR_MODES, editorMode, selectEditorMode);
|
|
1434
|
+
},
|
|
1435
|
+
onClick: () => {
|
|
1436
|
+
selectEditorMode(mode);
|
|
1437
|
+
},
|
|
1438
|
+
children: mode === "preview" ? "\u9884\u89C8" : "\u6E90\u7801"
|
|
1439
|
+
},
|
|
1440
|
+
mode
|
|
1441
|
+
)) }),
|
|
1299
1442
|
(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
1443
|
savePath(selected);
|
|
1301
1444
|
}, children: saving ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58" })
|
|
@@ -1340,8 +1483,12 @@ function CreativeWorkbench({
|
|
|
1340
1483
|
] }) : 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
1484
|
"textarea",
|
|
1342
1485
|
{
|
|
1486
|
+
ref: textareaRef,
|
|
1343
1487
|
value: buffer.content,
|
|
1344
1488
|
"data-format": structured ? "structured" : "prose",
|
|
1489
|
+
onBlur: rememberEditorPosition,
|
|
1490
|
+
onScroll: rememberEditorPosition,
|
|
1491
|
+
onSelect: rememberEditorPosition,
|
|
1345
1492
|
onChange: (event) => {
|
|
1346
1493
|
let content = event.target.value;
|
|
1347
1494
|
setBuffers((current) => ({
|
|
@@ -1363,12 +1510,8 @@ function CreativeWorkbench({
|
|
|
1363
1510
|
] })
|
|
1364
1511
|
] });
|
|
1365
1512
|
}
|
|
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);
|
|
1513
|
+
function CreativeSplitBridge({ sessionId, useSession, useStore, actions }) {
|
|
1514
|
+
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
1515
|
return (0, import_react.useLayoutEffect)(() => {
|
|
1373
1516
|
let document = marker.current?.ownerDocument;
|
|
1374
1517
|
if (document === void 0) return;
|
|
@@ -1384,27 +1527,34 @@ function CreativeSplitBridge({ context }) {
|
|
|
1384
1527
|
}, [sessionId]), (0, import_react.useLayoutEffect)(() => {
|
|
1385
1528
|
let scroller = target?.parentElement;
|
|
1386
1529
|
if (scroller == null) return;
|
|
1387
|
-
let
|
|
1530
|
+
let publishLayout = () => {
|
|
1388
1531
|
scroller.style.setProperty("--oh-story-scroll-height", `${String(scroller.clientHeight)}px`);
|
|
1532
|
+
let layout = scroller.clientWidth < 620 ? "compact" : scroller.clientWidth < 900 ? "medium" : "wide";
|
|
1533
|
+
scroller.dataset.ohStoryLayout !== layout && (scroller.dataset.ohStoryLayout = layout);
|
|
1389
1534
|
};
|
|
1390
|
-
|
|
1391
|
-
let observer = new ResizeObserver(
|
|
1535
|
+
publishLayout();
|
|
1536
|
+
let observer = new ResizeObserver(publishLayout);
|
|
1392
1537
|
return observer.observe(scroller), () => {
|
|
1393
|
-
observer.disconnect(), scroller.style.removeProperty("--oh-story-scroll-height");
|
|
1538
|
+
observer.disconnect(), scroller.style.removeProperty("--oh-story-scroll-height"), delete scroller.dataset.ohStoryLayout;
|
|
1394
1539
|
};
|
|
1395
1540
|
}, [target]), /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
1396
1541
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { ref: marker, className: "oh-story-bridge-marker", "aria-hidden": !0 }),
|
|
1397
|
-
target === void 0
|
|
1542
|
+
target === void 0 ? null : (0, import_react_dom.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1398
1543
|
CreativeWorkbench,
|
|
1399
1544
|
{
|
|
1400
1545
|
sessionId,
|
|
1401
|
-
runningCalls
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1546
|
+
runningCalls,
|
|
1547
|
+
partial,
|
|
1548
|
+
settledMutation,
|
|
1549
|
+
useStore,
|
|
1550
|
+
actions
|
|
1551
|
+
}
|
|
1405
1552
|
), target)
|
|
1406
1553
|
] });
|
|
1407
1554
|
}
|
|
1555
|
+
function WorkbenchSeat({ SessionProvider, renderSlot }) {
|
|
1556
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SessionProvider, { children: () => renderSlot("oh-story.workspace", {}) });
|
|
1557
|
+
}
|
|
1408
1558
|
function argsOf(block) {
|
|
1409
1559
|
let raw = ("kind" in block ? block.call?.argsRaw : block.argsRaw) ?? "{}";
|
|
1410
1560
|
try {
|
|
@@ -1433,11 +1583,18 @@ function RoleToolView({ block, inspect }) {
|
|
|
1433
1583
|
] });
|
|
1434
1584
|
}
|
|
1435
1585
|
function apply(context) {
|
|
1436
|
-
context.slots.inject("shell.overlay", () =>
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1586
|
+
context.slots.inject("shell.overlay", () => {
|
|
1587
|
+
let disposeSeat = context.slots.register({
|
|
1588
|
+
name: "shell.overlay",
|
|
1589
|
+
id: "oh-story-workspace",
|
|
1590
|
+
order: -100,
|
|
1591
|
+
children: { "oh-story.workspace": { kind: "single", scope: "session" } }
|
|
1592
|
+
}, WorkbenchSeat), disposeWorkbench = context.slots.register({
|
|
1593
|
+
name: "oh-story.workspace",
|
|
1594
|
+
store: createWorkbenchStore
|
|
1595
|
+
}, CreativeSplitBridge);
|
|
1596
|
+
return [disposeSeat, disposeWorkbench];
|
|
1597
|
+
}), context.slots.inject("tool.call.toolview", () => context.slots.register({
|
|
1441
1598
|
name: "tool.call.toolview",
|
|
1442
1599
|
key: "oh_story_role"
|
|
1443
1600
|
}, RoleToolView));
|