@jkwd/inbase 0.1.5 → 0.1.6
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 +4 -1
- package/apps/explorer/scripts/patch-lib.d.ts +13 -0
- package/apps/explorer/scripts/patch-lib.mjs +162 -25
- package/apps/explorer/scripts/session-store.d.ts +18 -1
- package/apps/explorer/scripts/session-store.mjs +102 -26
- package/apps/explorer/src/App.tsx +153 -3
- package/apps/explorer/src/agentIntent.ts +9 -0
- package/apps/explorer/src/index.css +103 -11
- package/apps/explorer/src/layout.ts +65 -1
- package/apps/explorer/src/scene/Bridge.tsx +23 -5
- package/apps/explorer/src/scene/FileBlock.tsx +13 -9
- package/apps/explorer/src/scene/FolderArea.tsx +18 -12
- package/apps/explorer/src/scene/MapView.tsx +69 -12
- package/apps/explorer/src/scene/Player.tsx +9 -1
- package/apps/explorer/src/scene/SelectionController.tsx +36 -13
- package/apps/explorer/src/scene/SelectionThumbnail.tsx +477 -33
- package/apps/explorer/src/scene/World.tsx +27 -10
- package/apps/explorer/src/theme.ts +10 -3
- package/apps/explorer/src/types.ts +5 -0
- package/apps/explorer/src/ui/HUD.tsx +294 -37
- package/apps/explorer/vite.config.ts +11 -1
- package/bin/session.mjs +18 -6
- package/package.json +1 -1
- package/skill/inbase/SKILL.md +13 -8
|
@@ -58,17 +58,83 @@ function importLabels(items: PatchImportAddition[]) {
|
|
|
58
58
|
function PanelList({
|
|
59
59
|
title,
|
|
60
60
|
items,
|
|
61
|
+
tone,
|
|
61
62
|
}: {
|
|
62
63
|
title: string
|
|
63
64
|
items: Array<{ key: string; label: string }>
|
|
65
|
+
tone?: 'add' | 'edit' | 'remove'
|
|
64
66
|
}) {
|
|
65
67
|
if (items.length === 0) return null
|
|
68
|
+
const titleClass =
|
|
69
|
+
tone === 'add'
|
|
70
|
+
? 'hud-section-title hud-section-title-add'
|
|
71
|
+
: tone === 'edit'
|
|
72
|
+
? 'hud-section-title hud-section-title-edit'
|
|
73
|
+
: tone === 'remove'
|
|
74
|
+
? 'hud-section-title hud-section-title-remove'
|
|
75
|
+
: 'hud-section-title'
|
|
76
|
+
const itemClass =
|
|
77
|
+
tone === 'add'
|
|
78
|
+
? 'hud-file-add'
|
|
79
|
+
: tone === 'edit'
|
|
80
|
+
? 'hud-file-edit'
|
|
81
|
+
: tone === 'remove'
|
|
82
|
+
? 'hud-file-remove'
|
|
83
|
+
: undefined
|
|
66
84
|
return (
|
|
67
85
|
<>
|
|
68
|
-
<div className=
|
|
86
|
+
<div className={titleClass}>{title}</div>
|
|
69
87
|
<ul>
|
|
70
88
|
{items.map((item) => (
|
|
71
|
-
<li key={item.key}>
|
|
89
|
+
<li className={itemClass} key={item.key}>
|
|
90
|
+
{item.label}
|
|
91
|
+
</li>
|
|
92
|
+
))}
|
|
93
|
+
</ul>
|
|
94
|
+
</>
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function symbolChangeClass(kind: 'add' | 'edit' | null | undefined) {
|
|
99
|
+
if (kind === 'add') return 'hud-file-add'
|
|
100
|
+
if (kind === 'edit') return 'hud-file-edit'
|
|
101
|
+
return undefined
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function extraAddedSymbols(
|
|
105
|
+
existing: Array<{ name: string }>,
|
|
106
|
+
added: PatchSymbolAddition[],
|
|
107
|
+
) {
|
|
108
|
+
const have = new Set(existing.map((item) => item.name))
|
|
109
|
+
return added.filter((item) => !have.has(item.name))
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function PatchSymbolChanges({
|
|
113
|
+
title,
|
|
114
|
+
added,
|
|
115
|
+
changed,
|
|
116
|
+
}: {
|
|
117
|
+
title: string
|
|
118
|
+
added: PatchSymbolAddition[]
|
|
119
|
+
changed: PatchSymbolAddition[]
|
|
120
|
+
}) {
|
|
121
|
+
if (added.length === 0 && changed.length === 0) return null
|
|
122
|
+
const addedNames = new Set(added.map((item) => item.name))
|
|
123
|
+
return (
|
|
124
|
+
<>
|
|
125
|
+
<div className="hud-section-title">{title}</div>
|
|
126
|
+
<ul>
|
|
127
|
+
{changed
|
|
128
|
+
.filter((item) => !addedNames.has(item.name))
|
|
129
|
+
.map((item) => (
|
|
130
|
+
<li className="hud-file-edit" key={`edit-${item.file}:${item.name}`}>
|
|
131
|
+
{item.name}
|
|
132
|
+
</li>
|
|
133
|
+
))}
|
|
134
|
+
{added.map((item) => (
|
|
135
|
+
<li className="hud-file-add" key={`add-${item.file}:${item.name}`}>
|
|
136
|
+
{item.name}
|
|
137
|
+
</li>
|
|
72
138
|
))}
|
|
73
139
|
</ul>
|
|
74
140
|
</>
|
|
@@ -174,7 +240,7 @@ type SessionPanelProps = {
|
|
|
174
240
|
onWorkflowAction: (
|
|
175
241
|
sessionId: string,
|
|
176
242
|
action: WorkflowAction,
|
|
177
|
-
options?: { instruction?: string; step?: number },
|
|
243
|
+
options?: { instruction?: string; step?: number; stepByStep?: boolean },
|
|
178
244
|
) => void
|
|
179
245
|
onNavigateDiff: (sessionId: string, diffId: string) => void
|
|
180
246
|
}
|
|
@@ -208,9 +274,12 @@ function SessionPanel({
|
|
|
208
274
|
typeof intent.step === 'number' &&
|
|
209
275
|
intent.steps.length > 0 &&
|
|
210
276
|
intent.step >= intent.steps.length
|
|
277
|
+
const stepByStep = intent.stepByStep !== false
|
|
211
278
|
const addedFunctions = intent.addedFunctions ?? []
|
|
212
279
|
const addedVariables = intent.addedVariables ?? []
|
|
213
280
|
const addedImports = intent.addedImports ?? []
|
|
281
|
+
const changedFunctions = intent.changedFunctions ?? []
|
|
282
|
+
const changedVariables = intent.changedVariables ?? []
|
|
214
283
|
const doneSteps = new Set(
|
|
215
284
|
intent.status === 'finished'
|
|
216
285
|
? intent.steps.map((step) => step.index)
|
|
@@ -247,7 +316,7 @@ function SessionPanel({
|
|
|
247
316
|
|
|
248
317
|
const act = (
|
|
249
318
|
action: WorkflowAction,
|
|
250
|
-
options?: { instruction?: string; step?: number },
|
|
319
|
+
options?: { instruction?: string; step?: number; stepByStep?: boolean },
|
|
251
320
|
) => onWorkflowAction(sessionId, action, options)
|
|
252
321
|
|
|
253
322
|
return (
|
|
@@ -268,6 +337,24 @@ function SessionPanel({
|
|
|
268
337
|
/>
|
|
269
338
|
{!minimized && (
|
|
270
339
|
<>
|
|
340
|
+
<label className="hud-mode-switch">
|
|
341
|
+
<span>Step by step</span>
|
|
342
|
+
<button
|
|
343
|
+
className="hud-switch"
|
|
344
|
+
type="button"
|
|
345
|
+
role="switch"
|
|
346
|
+
aria-checked={stepByStep}
|
|
347
|
+
aria-label="Step by step"
|
|
348
|
+
onKeyDown={(event) => event.stopPropagation()}
|
|
349
|
+
onClick={() => act('set_step_by_step', { stepByStep: !stepByStep })}
|
|
350
|
+
/>
|
|
351
|
+
</label>
|
|
352
|
+
{!stepByStep && (
|
|
353
|
+
<p className="hud-mode-hint">
|
|
354
|
+
LLM implements the full plan. You can still walk the diffs, then
|
|
355
|
+
Complete.
|
|
356
|
+
</p>
|
|
357
|
+
)}
|
|
271
358
|
{intent.feature && <p className="hud-feature">{intent.feature}</p>}
|
|
272
359
|
{askingBlueprint ? (
|
|
273
360
|
<>
|
|
@@ -346,7 +433,9 @@ function SessionPanel({
|
|
|
346
433
|
<span>
|
|
347
434
|
{intent.status === 'replanning'
|
|
348
435
|
? 'Updating the remaining plan from your instruction…'
|
|
349
|
-
:
|
|
436
|
+
: intent.stalledWait
|
|
437
|
+
? 'The LLM is still waiting on this step…'
|
|
438
|
+
: `Implementing ${stepLabel.toLowerCase()}…`}
|
|
350
439
|
</span>
|
|
351
440
|
<button
|
|
352
441
|
className="hud-button hud-button-reject"
|
|
@@ -383,7 +472,9 @@ function SessionPanel({
|
|
|
383
472
|
<span className="hud-step-index">{step.index}.</span>
|
|
384
473
|
<span className="hud-step-main">
|
|
385
474
|
<span className="hud-step-title">{step.title}</span>
|
|
386
|
-
{((
|
|
475
|
+
{((stepByStep &&
|
|
476
|
+
canRunNext &&
|
|
477
|
+
nextStep?.index === step.index) ||
|
|
387
478
|
(canComplete && step.index === intent.step)) && (
|
|
388
479
|
<button
|
|
389
480
|
className="hud-button hud-button-approve hud-run-step"
|
|
@@ -443,6 +534,8 @@ function SessionPanel({
|
|
|
443
534
|
addedFunctions.length > 0 ||
|
|
444
535
|
addedVariables.length > 0 ||
|
|
445
536
|
addedImports.length > 0 ||
|
|
537
|
+
changedFunctions.length > 0 ||
|
|
538
|
+
changedVariables.length > 0 ||
|
|
446
539
|
(intent.imports ?? []).length > 0)
|
|
447
540
|
}
|
|
448
541
|
>
|
|
@@ -503,12 +596,24 @@ function SessionPanel({
|
|
|
503
596
|
</>
|
|
504
597
|
)}
|
|
505
598
|
<PanelList
|
|
506
|
-
title="
|
|
599
|
+
title="Changed functions"
|
|
600
|
+
items={symbolLabels(changedFunctions)}
|
|
601
|
+
tone="edit"
|
|
602
|
+
/>
|
|
603
|
+
<PanelList
|
|
604
|
+
title="Added functions"
|
|
507
605
|
items={symbolLabels(addedFunctions)}
|
|
606
|
+
tone="add"
|
|
607
|
+
/>
|
|
608
|
+
<PanelList
|
|
609
|
+
title="Changed variables"
|
|
610
|
+
items={symbolLabels(changedVariables)}
|
|
611
|
+
tone="edit"
|
|
508
612
|
/>
|
|
509
613
|
<PanelList
|
|
510
|
-
title="
|
|
614
|
+
title="Added variables"
|
|
511
615
|
items={symbolLabels(addedVariables)}
|
|
616
|
+
tone="add"
|
|
512
617
|
/>
|
|
513
618
|
{addedImports.length > 0 && (
|
|
514
619
|
<PanelList title="Imports" items={importLabels(addedImports)} />
|
|
@@ -594,9 +699,11 @@ type HUDProps = {
|
|
|
594
699
|
locked: boolean
|
|
595
700
|
selectedId: string | null
|
|
596
701
|
selectedTick?: number
|
|
702
|
+
inspectTick?: number
|
|
597
703
|
selectedFolder?: string | null
|
|
598
704
|
landAt: [number, number]
|
|
599
705
|
aimedRelation: AimedRelation | null
|
|
706
|
+
aimedFileId?: string | null
|
|
600
707
|
currentFolder: string
|
|
601
708
|
intent: AgentIntent
|
|
602
709
|
intents?: AgentIntent[]
|
|
@@ -605,7 +712,7 @@ type HUDProps = {
|
|
|
605
712
|
onWorkflowAction: (
|
|
606
713
|
sessionId: string,
|
|
607
714
|
action: WorkflowAction,
|
|
608
|
-
options?: { instruction?: string; step?: number },
|
|
715
|
+
options?: { instruction?: string; step?: number; stepByStep?: boolean },
|
|
609
716
|
) => void
|
|
610
717
|
onNavigateDiff: (sessionId: string, diffId: string) => void
|
|
611
718
|
onOpenMap: () => void
|
|
@@ -614,6 +721,9 @@ type HUDProps = {
|
|
|
614
721
|
onToggleFollowLook: () => void
|
|
615
722
|
importedBy: boolean
|
|
616
723
|
onToggleImportedBy: () => void
|
|
724
|
+
changePathsOnly?: boolean
|
|
725
|
+
hasChangeSet?: boolean
|
|
726
|
+
onToggleChangePathsOnly?: () => void
|
|
617
727
|
naming?: boolean
|
|
618
728
|
namingIsland?: boolean
|
|
619
729
|
onCommitIslandName?: (name: string) => void
|
|
@@ -634,6 +744,7 @@ type HUDProps = {
|
|
|
634
744
|
onMapAddFile?: (folderPath: string) => void
|
|
635
745
|
onMapAddFolder?: (folderPath: string) => void
|
|
636
746
|
onInspectFile?: (fileId: string) => void
|
|
747
|
+
onInspectBlock?: (fileId: string) => void
|
|
637
748
|
plannedIds?: string[]
|
|
638
749
|
createdIds?: string[]
|
|
639
750
|
deletedIds?: string[]
|
|
@@ -646,9 +757,11 @@ export function HUD({
|
|
|
646
757
|
locked,
|
|
647
758
|
selectedId,
|
|
648
759
|
selectedTick = 0,
|
|
760
|
+
inspectTick = 0,
|
|
649
761
|
selectedFolder = null,
|
|
650
762
|
landAt,
|
|
651
763
|
aimedRelation,
|
|
764
|
+
aimedFileId = null,
|
|
652
765
|
currentFolder,
|
|
653
766
|
intent,
|
|
654
767
|
intents,
|
|
@@ -662,6 +775,9 @@ export function HUD({
|
|
|
662
775
|
onToggleFollowLook,
|
|
663
776
|
importedBy,
|
|
664
777
|
onToggleImportedBy,
|
|
778
|
+
changePathsOnly = false,
|
|
779
|
+
hasChangeSet = false,
|
|
780
|
+
onToggleChangePathsOnly,
|
|
665
781
|
naming = false,
|
|
666
782
|
namingIsland = false,
|
|
667
783
|
onCommitIslandName,
|
|
@@ -678,6 +794,7 @@ export function HUD({
|
|
|
678
794
|
onMapAddFile,
|
|
679
795
|
onMapAddFolder,
|
|
680
796
|
onInspectFile,
|
|
797
|
+
onInspectBlock,
|
|
681
798
|
plannedIds = [],
|
|
682
799
|
createdIds = [],
|
|
683
800
|
deletedIds = [],
|
|
@@ -716,6 +833,8 @@ export function HUD({
|
|
|
716
833
|
const addedFunctions = intent.addedFunctions ?? []
|
|
717
834
|
const addedVariables = intent.addedVariables ?? []
|
|
718
835
|
const addedImports = intent.addedImports ?? []
|
|
836
|
+
const changedFunctions = intent.changedFunctions ?? []
|
|
837
|
+
const changedVariables = intent.changedVariables ?? []
|
|
719
838
|
const selectedAddedFunctions = selected
|
|
720
839
|
? addedFunctions.filter((item) => item.file === selected.id)
|
|
721
840
|
: []
|
|
@@ -725,6 +844,12 @@ export function HUD({
|
|
|
725
844
|
const selectedAddedImports = selected
|
|
726
845
|
? addedImports.filter((item) => item.file === selected.id)
|
|
727
846
|
: []
|
|
847
|
+
const selectedChangedFunctions = selected
|
|
848
|
+
? changedFunctions.filter((item) => item.file === selected.id)
|
|
849
|
+
: []
|
|
850
|
+
const selectedChangedVariables = selected
|
|
851
|
+
? changedVariables.filter((item) => item.file === selected.id)
|
|
852
|
+
: []
|
|
728
853
|
const selectedClasses = selected
|
|
729
854
|
? selected.symbols.filter((symbol) => symbol.kind === 'class')
|
|
730
855
|
: []
|
|
@@ -734,6 +859,26 @@ export function HUD({
|
|
|
734
859
|
const selectedVariables = selected
|
|
735
860
|
? selected.symbols.filter((symbol) => symbol.kind === 'variable')
|
|
736
861
|
: []
|
|
862
|
+
const functionChange = new Map<string, 'add' | 'edit'>([
|
|
863
|
+
...selectedChangedFunctions.map(
|
|
864
|
+
(item) => [item.name, 'edit'] as const,
|
|
865
|
+
),
|
|
866
|
+
...selectedAddedFunctions.map((item) => [item.name, 'add'] as const),
|
|
867
|
+
])
|
|
868
|
+
const variableChange = new Map<string, 'add' | 'edit'>([
|
|
869
|
+
...selectedChangedVariables.map(
|
|
870
|
+
(item) => [item.name, 'edit'] as const,
|
|
871
|
+
),
|
|
872
|
+
...selectedAddedVariables.map((item) => [item.name, 'add'] as const),
|
|
873
|
+
])
|
|
874
|
+
const extraAddedFunctions = extraAddedSymbols(
|
|
875
|
+
selectedFunctions,
|
|
876
|
+
selectedAddedFunctions,
|
|
877
|
+
)
|
|
878
|
+
const extraAddedVariables = extraAddedSymbols(
|
|
879
|
+
selectedVariables,
|
|
880
|
+
selectedAddedVariables,
|
|
881
|
+
)
|
|
737
882
|
const selectedBlueprintFunctions = selected
|
|
738
883
|
? blueprintFunctions.filter((item) => item.file === selected.id)
|
|
739
884
|
: []
|
|
@@ -781,13 +926,33 @@ export function HUD({
|
|
|
781
926
|
}, [selectedId, selectedFolder])
|
|
782
927
|
|
|
783
928
|
useEffect(() => {
|
|
929
|
+
if (mode === 'walk') return
|
|
784
930
|
if (selectedId) setInfoVisible(true)
|
|
785
|
-
}, [selectedId, selectedTick])
|
|
931
|
+
}, [mode, selectedId, selectedTick])
|
|
932
|
+
|
|
933
|
+
useEffect(() => {
|
|
934
|
+
if (inspectTick > 0) {
|
|
935
|
+
setInfoVisible(true)
|
|
936
|
+
setInfoMinimized(false)
|
|
937
|
+
}
|
|
938
|
+
}, [inspectTick])
|
|
786
939
|
|
|
787
940
|
useEffect(() => {
|
|
788
941
|
if (selectedFolder) setInfoVisible(true)
|
|
789
942
|
}, [selectedFolder])
|
|
790
943
|
|
|
944
|
+
useEffect(() => {
|
|
945
|
+
if (!locked) return
|
|
946
|
+
setInfoVisible(false)
|
|
947
|
+
setInfoMinimized(false)
|
|
948
|
+
}, [locked])
|
|
949
|
+
|
|
950
|
+
const infoOpen = infoVisible && Boolean(selected || selectedFolderNode)
|
|
951
|
+
|
|
952
|
+
useEffect(() => {
|
|
953
|
+
if (infoOpen) document.exitPointerLock()
|
|
954
|
+
}, [infoOpen])
|
|
955
|
+
|
|
791
956
|
useEffect(() => {
|
|
792
957
|
const onKey = (event: KeyboardEvent) => {
|
|
793
958
|
if (event.repeat || event.code !== 'KeyI') return
|
|
@@ -802,14 +967,22 @@ export function HUD({
|
|
|
802
967
|
return
|
|
803
968
|
}
|
|
804
969
|
event.preventDefault()
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
970
|
+
if (infoVisible) {
|
|
971
|
+
setInfoVisible(false)
|
|
972
|
+
setInfoMinimized(false)
|
|
973
|
+
return
|
|
974
|
+
}
|
|
975
|
+
const blockId = aimedFileId ?? selectedId
|
|
976
|
+
if (mode === 'walk') {
|
|
977
|
+
if (!blockId) return
|
|
978
|
+
onInspectBlock?.(blockId)
|
|
979
|
+
}
|
|
980
|
+
setInfoMinimized(false)
|
|
981
|
+
setInfoVisible(true)
|
|
809
982
|
}
|
|
810
983
|
window.addEventListener('keydown', onKey)
|
|
811
984
|
return () => window.removeEventListener('keydown', onKey)
|
|
812
|
-
}, [])
|
|
985
|
+
}, [aimedFileId, infoVisible, mode, onInspectBlock, selectedId])
|
|
813
986
|
|
|
814
987
|
useEffect(() => {
|
|
815
988
|
if (!mapping) return
|
|
@@ -879,7 +1052,7 @@ export function HUD({
|
|
|
879
1052
|
, <kbd>Space</kbd> place a file, <kbd>B</kbd> place an island
|
|
880
1053
|
</>
|
|
881
1054
|
) : null}
|
|
882
|
-
, click a block for info.
|
|
1055
|
+
, double-click a block or press <kbd>I</kbd> for info.
|
|
883
1056
|
</p>
|
|
884
1057
|
</div>
|
|
885
1058
|
</div>
|
|
@@ -987,13 +1160,45 @@ export function HUD({
|
|
|
987
1160
|
Inspect file
|
|
988
1161
|
</button>
|
|
989
1162
|
)}
|
|
1163
|
+
{previewing &&
|
|
1164
|
+
(selectedChangedFunctions.length > 0 ||
|
|
1165
|
+
selectedAddedFunctions.length > 0 ||
|
|
1166
|
+
selectedChangedVariables.length > 0 ||
|
|
1167
|
+
selectedAddedVariables.length > 0 ||
|
|
1168
|
+
selectedAddedImports.length > 0) && (
|
|
1169
|
+
<>
|
|
1170
|
+
<div className="hud-section-title hud-section-title-edit">
|
|
1171
|
+
LLM changes
|
|
1172
|
+
</div>
|
|
1173
|
+
<PatchSymbolChanges
|
|
1174
|
+
title="Functions"
|
|
1175
|
+
added={selectedAddedFunctions}
|
|
1176
|
+
changed={selectedChangedFunctions}
|
|
1177
|
+
/>
|
|
1178
|
+
<PatchSymbolChanges
|
|
1179
|
+
title="Vars"
|
|
1180
|
+
added={selectedAddedVariables}
|
|
1181
|
+
changed={selectedChangedVariables}
|
|
1182
|
+
/>
|
|
1183
|
+
<PanelList
|
|
1184
|
+
title="Imports"
|
|
1185
|
+
items={importLabels(selectedAddedImports)}
|
|
1186
|
+
tone="add"
|
|
1187
|
+
/>
|
|
1188
|
+
</>
|
|
1189
|
+
)}
|
|
990
1190
|
{selectedClasses.length > 0 && (
|
|
991
1191
|
<>
|
|
992
1192
|
<div className="hud-section-title">Classes</div>
|
|
993
1193
|
<ul>
|
|
994
1194
|
{selectedClasses.map((symbol) => (
|
|
995
1195
|
<li key={`class-${symbol.name}`}>
|
|
996
|
-
<span
|
|
1196
|
+
<span
|
|
1197
|
+
className={
|
|
1198
|
+
symbolChangeClass(functionChange.get(symbol.name)) ??
|
|
1199
|
+
(symbol.intended ? 'hud-intended' : undefined)
|
|
1200
|
+
}
|
|
1201
|
+
>
|
|
997
1202
|
{symbol.name}
|
|
998
1203
|
</span>
|
|
999
1204
|
</li>
|
|
@@ -1003,13 +1208,19 @@ export function HUD({
|
|
|
1003
1208
|
)}
|
|
1004
1209
|
<div className="hud-section-title">Functions</div>
|
|
1005
1210
|
{selectedFunctions.length === 0 &&
|
|
1211
|
+
extraAddedFunctions.length === 0 &&
|
|
1006
1212
|
selectedBlueprintFunctions.length === 0 ? (
|
|
1007
1213
|
<p>No functions</p>
|
|
1008
1214
|
) : (
|
|
1009
1215
|
<ul>
|
|
1010
1216
|
{selectedFunctions.map((symbol) => (
|
|
1011
1217
|
<li key={`fn-${symbol.name}`}>
|
|
1012
|
-
<span
|
|
1218
|
+
<span
|
|
1219
|
+
className={
|
|
1220
|
+
symbolChangeClass(functionChange.get(symbol.name)) ??
|
|
1221
|
+
(symbol.intended ? 'hud-intended' : undefined)
|
|
1222
|
+
}
|
|
1223
|
+
>
|
|
1013
1224
|
{symbol.name}
|
|
1014
1225
|
</span>
|
|
1015
1226
|
{canEditBlueprint && symbol.intended && (
|
|
@@ -1026,6 +1237,11 @@ export function HUD({
|
|
|
1026
1237
|
)}
|
|
1027
1238
|
</li>
|
|
1028
1239
|
))}
|
|
1240
|
+
{extraAddedFunctions.map((item) => (
|
|
1241
|
+
<li key={`fn-add-${item.name}`}>
|
|
1242
|
+
<span className="hud-file-add">{item.name}</span>
|
|
1243
|
+
</li>
|
|
1244
|
+
))}
|
|
1029
1245
|
</ul>
|
|
1030
1246
|
)}
|
|
1031
1247
|
{canEditBlueprint && onAddBlueprintFunction && (
|
|
@@ -1036,13 +1252,19 @@ export function HUD({
|
|
|
1036
1252
|
)}
|
|
1037
1253
|
<div className="hud-section-title">Vars</div>
|
|
1038
1254
|
{selectedVariables.length === 0 &&
|
|
1255
|
+
extraAddedVariables.length === 0 &&
|
|
1039
1256
|
selectedBlueprintVariables.length === 0 ? (
|
|
1040
1257
|
<p>No vars</p>
|
|
1041
1258
|
) : (
|
|
1042
1259
|
<ul>
|
|
1043
1260
|
{selectedVariables.map((symbol) => (
|
|
1044
1261
|
<li key={`var-${symbol.name}`}>
|
|
1045
|
-
<span
|
|
1262
|
+
<span
|
|
1263
|
+
className={
|
|
1264
|
+
symbolChangeClass(variableChange.get(symbol.name)) ??
|
|
1265
|
+
(symbol.intended ? 'hud-intended' : undefined)
|
|
1266
|
+
}
|
|
1267
|
+
>
|
|
1046
1268
|
{symbol.name}
|
|
1047
1269
|
</span>
|
|
1048
1270
|
{canEditBlueprint && symbol.intended && (
|
|
@@ -1059,6 +1281,11 @@ export function HUD({
|
|
|
1059
1281
|
)}
|
|
1060
1282
|
</li>
|
|
1061
1283
|
))}
|
|
1284
|
+
{extraAddedVariables.map((item) => (
|
|
1285
|
+
<li key={`var-add-${item.name}`}>
|
|
1286
|
+
<span className="hud-file-add">{item.name}</span>
|
|
1287
|
+
</li>
|
|
1288
|
+
))}
|
|
1062
1289
|
</ul>
|
|
1063
1290
|
)}
|
|
1064
1291
|
{canEditBlueprint && onAddBlueprintVariable && (
|
|
@@ -1067,22 +1294,6 @@ export function HUD({
|
|
|
1067
1294
|
onAdd={(name) => onAddBlueprintVariable(selected.id, name)}
|
|
1068
1295
|
/>
|
|
1069
1296
|
)}
|
|
1070
|
-
{previewing && (
|
|
1071
|
-
<>
|
|
1072
|
-
<PanelList
|
|
1073
|
-
title="Added functions"
|
|
1074
|
-
items={symbolLabels(selectedAddedFunctions)}
|
|
1075
|
-
/>
|
|
1076
|
-
<PanelList
|
|
1077
|
-
title="Added variables"
|
|
1078
|
-
items={symbolLabels(selectedAddedVariables)}
|
|
1079
|
-
/>
|
|
1080
|
-
<PanelList
|
|
1081
|
-
title="Added imports"
|
|
1082
|
-
items={importLabels(selectedAddedImports)}
|
|
1083
|
-
/>
|
|
1084
|
-
</>
|
|
1085
|
-
)}
|
|
1086
1297
|
<div className="hud-section-title">
|
|
1087
1298
|
{importedBy ? 'Imported by' : 'Imports'}
|
|
1088
1299
|
</div>
|
|
@@ -1201,7 +1412,7 @@ export function HUD({
|
|
|
1201
1412
|
<ul>
|
|
1202
1413
|
{folderFiles.map((file) => (
|
|
1203
1414
|
<li key={file.id}>
|
|
1204
|
-
<span>{file.
|
|
1415
|
+
<span>{file.name}</span>
|
|
1205
1416
|
{canInspectFile(file.id, file.userCreated) && (
|
|
1206
1417
|
<button
|
|
1207
1418
|
className="hud-item-inspect"
|
|
@@ -1277,6 +1488,13 @@ export function HUD({
|
|
|
1277
1488
|
)}
|
|
1278
1489
|
<span>Click a line to fly there</span>
|
|
1279
1490
|
<span>Ctrl-click an island to walk</span>
|
|
1491
|
+
{hasChangeSet && (
|
|
1492
|
+
<span>
|
|
1493
|
+
{changePathsOnly
|
|
1494
|
+
? 'C show all paths'
|
|
1495
|
+
: 'C show only changed paths'}
|
|
1496
|
+
</span>
|
|
1497
|
+
)}
|
|
1280
1498
|
{selected?.userCreated && creatingBlueprint && (
|
|
1281
1499
|
<span>Backspace delete</span>
|
|
1282
1500
|
)}
|
|
@@ -1311,7 +1529,7 @@ export function HUD({
|
|
|
1311
1529
|
{selected?.userCreated && creatingBlueprint && (
|
|
1312
1530
|
<span>Backspace delete</span>
|
|
1313
1531
|
)}
|
|
1314
|
-
<span>
|
|
1532
|
+
<span>Double-click a block for info</span>
|
|
1315
1533
|
<span>Aim a line to fly</span>
|
|
1316
1534
|
<span>{infoVisible ? 'I hide info' : 'I show info'}</span>
|
|
1317
1535
|
{infoVisible && <span>↑↓ scroll info</span>}
|
|
@@ -1331,6 +1549,45 @@ export function HUD({
|
|
|
1331
1549
|
)}
|
|
1332
1550
|
</div>
|
|
1333
1551
|
<div className="hud-icon-row">
|
|
1552
|
+
{mapping && hasChangeSet && onToggleChangePathsOnly && (
|
|
1553
|
+
<button
|
|
1554
|
+
className="hud-button hud-icon-button"
|
|
1555
|
+
data-active={changePathsOnly}
|
|
1556
|
+
aria-label={
|
|
1557
|
+
changePathsOnly
|
|
1558
|
+
? 'Show all folder paths'
|
|
1559
|
+
: 'Show only changed paths'
|
|
1560
|
+
}
|
|
1561
|
+
aria-keyshortcuts="C"
|
|
1562
|
+
aria-pressed={changePathsOnly}
|
|
1563
|
+
type="button"
|
|
1564
|
+
onClick={onToggleChangePathsOnly}
|
|
1565
|
+
>
|
|
1566
|
+
<svg
|
|
1567
|
+
viewBox="0 0 24 24"
|
|
1568
|
+
width="18"
|
|
1569
|
+
height="18"
|
|
1570
|
+
fill="none"
|
|
1571
|
+
stroke="currentColor"
|
|
1572
|
+
strokeWidth="2"
|
|
1573
|
+
strokeLinecap="round"
|
|
1574
|
+
strokeLinejoin="round"
|
|
1575
|
+
aria-hidden="true"
|
|
1576
|
+
>
|
|
1577
|
+
<circle cx="12" cy="5" r="2.4" />
|
|
1578
|
+
<path d="M12 7.4v4.2" />
|
|
1579
|
+
<path d="M12 11.6 6.2 16" />
|
|
1580
|
+
<path d="M12 11.6 17.8 16" />
|
|
1581
|
+
<circle cx="6.2" cy="18" r="2.1" />
|
|
1582
|
+
<circle cx="17.8" cy="18" r="2.1" />
|
|
1583
|
+
</svg>
|
|
1584
|
+
<span className="hud-tooltip">
|
|
1585
|
+
{changePathsOnly
|
|
1586
|
+
? 'C show all paths'
|
|
1587
|
+
: 'C show only changed paths'}
|
|
1588
|
+
</span>
|
|
1589
|
+
</button>
|
|
1590
|
+
)}
|
|
1334
1591
|
{mapping && (
|
|
1335
1592
|
<button
|
|
1336
1593
|
className="hud-button hud-icon-button"
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
requestReplan,
|
|
20
20
|
sendBlueprint,
|
|
21
21
|
sessionIntent,
|
|
22
|
+
setStepByStep,
|
|
22
23
|
stopSession,
|
|
23
24
|
updateBlueprint,
|
|
24
25
|
} from './scripts/session-store.mjs'
|
|
@@ -180,6 +181,7 @@ async function decideIntent(req: IncomingMessage, res: ServerResponse) {
|
|
|
180
181
|
diffId?: string
|
|
181
182
|
instruction?: string
|
|
182
183
|
step?: number
|
|
184
|
+
stepByStep?: boolean
|
|
183
185
|
userCreatedBlocks?: unknown[]
|
|
184
186
|
userCreatedIslands?: unknown[]
|
|
185
187
|
addedFunctions?: unknown[]
|
|
@@ -195,7 +197,8 @@ async function decideIntent(req: IncomingMessage, res: ServerResponse) {
|
|
|
195
197
|
action !== 'blueprint_yes' &&
|
|
196
198
|
action !== 'blueprint_no' &&
|
|
197
199
|
action !== 'blueprint_send' &&
|
|
198
|
-
action !== 'blueprint_update'
|
|
200
|
+
action !== 'blueprint_update' &&
|
|
201
|
+
action !== 'set_step_by_step'
|
|
199
202
|
) {
|
|
200
203
|
sendJson(res, 400, { error: 'invalid workflow action' })
|
|
201
204
|
return
|
|
@@ -257,6 +260,13 @@ async function decideIntent(req: IncomingMessage, res: ServerResponse) {
|
|
|
257
260
|
addedVariables: body.addedVariables,
|
|
258
261
|
addedImports: body.addedImports,
|
|
259
262
|
})
|
|
263
|
+
} else if (action === 'set_step_by_step') {
|
|
264
|
+
if (typeof body.stepByStep !== 'boolean') {
|
|
265
|
+
sendJson(res, 400, { error: 'stepByStep is required' })
|
|
266
|
+
return
|
|
267
|
+
}
|
|
268
|
+
setStepByStep(dataDir, body.sessionId, body.stepByStep, targetRoot)
|
|
269
|
+
rescanTarget('after changing step-by-step mode')
|
|
260
270
|
} else {
|
|
261
271
|
stopSession(dataDir, body.sessionId, targetRoot)
|
|
262
272
|
rescanTarget('after stopping session')
|
package/bin/session.mjs
CHANGED
|
@@ -125,7 +125,9 @@ export async function reportPlan(args) {
|
|
|
125
125
|
stepTitles: stepsParsed.values,
|
|
126
126
|
})
|
|
127
127
|
console.log(
|
|
128
|
-
|
|
128
|
+
manifest.phase === 'working'
|
|
129
|
+
? `VISUAL_CODER_PLAN_READY Reported ${manifest.steps.length} plan step(s) for session ${sessionId}. Step by step is off, so step ${manifest.currentStep} is already invoked. Implement it, then wait again.`
|
|
130
|
+
: `VISUAL_CODER_PLAN_READY Reported ${manifest.steps.length} plan step(s) for session ${sessionId}. Wait for the user to invoke step ${manifest.currentStep}.`,
|
|
129
131
|
)
|
|
130
132
|
}
|
|
131
133
|
|
|
@@ -148,16 +150,21 @@ export async function waitForApproval(args) {
|
|
|
148
150
|
console.error(`No workflow session found for ${sessionId}`)
|
|
149
151
|
process.exit(1)
|
|
150
152
|
}
|
|
153
|
+
store.autoAdvance(config.dataDir, sessionId, config.targetRoot)
|
|
154
|
+
const afterAdvance = store.readManifest(config.dataDir, sessionId) ?? initial
|
|
151
155
|
console.log(
|
|
152
|
-
|
|
153
|
-
? `Waiting for the user to invoke step ${
|
|
154
|
-
:
|
|
155
|
-
?
|
|
156
|
+
afterAdvance.phase === 'plan_ready'
|
|
157
|
+
? `Waiting for the user to invoke step ${afterAdvance.currentStep}...`
|
|
158
|
+
: afterAdvance.phase === 'review' && afterAdvance.diffs?.at(-1)
|
|
159
|
+
? afterAdvance.stepByStep === false
|
|
160
|
+
? `Waiting for the finish step after ${afterAdvance.diffs.at(-1).id}...`
|
|
161
|
+
: `Waiting for the user to run the next step after ${afterAdvance.diffs.at(-1).id}...`
|
|
156
162
|
: `Waiting for the visual workflow in session ${sessionId}...`,
|
|
157
163
|
)
|
|
158
164
|
|
|
159
165
|
while (Date.now() - started < timeoutMs) {
|
|
160
166
|
store.touchSessionConnection(config.dataDir, sessionId)
|
|
167
|
+
store.autoAdvance(config.dataDir, sessionId, config.targetRoot)
|
|
161
168
|
const manifest = store.readManifest(config.dataDir, sessionId)
|
|
162
169
|
if (!manifest) {
|
|
163
170
|
console.error(
|
|
@@ -249,7 +256,12 @@ export async function proposePatch(args) {
|
|
|
249
256
|
patchText,
|
|
250
257
|
})
|
|
251
258
|
|
|
259
|
+
const last = entry.step >= manifest.steps.length
|
|
252
260
|
console.log(
|
|
253
|
-
|
|
261
|
+
manifest.phase === 'working'
|
|
262
|
+
? `VISUAL_CODER_STEP_READY Published diff ${entry.id} for session ${sessionId}, step ${entry.step}/${manifest.steps.length}: ${parsed.files.length} changed, ${parsed.creates.length} added. Step by step is off, so the next step is already invoked. Wait again.`
|
|
263
|
+
: last
|
|
264
|
+
? `VISUAL_CODER_STEP_READY Published diff ${entry.id} for session ${sessionId}, step ${entry.step}/${manifest.steps.length}: ${parsed.files.length} changed, ${parsed.creates.length} added. Walk the diffs, then Complete to finish.`
|
|
265
|
+
: `VISUAL_CODER_STEP_READY Published diff ${entry.id} for session ${sessionId}, step ${entry.step}/${manifest.steps.length}: ${parsed.files.length} changed, ${parsed.creates.length} added. Wait for Continue or an alternative instruction.`,
|
|
254
266
|
)
|
|
255
267
|
}
|