@jkwd/inbase 0.1.20 → 0.1.22
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 +13 -7
- package/apps/explorer/package.json +1 -0
- package/apps/explorer/scripts/explain-store.d.ts +135 -0
- package/apps/explorer/scripts/explain-store.mjs +666 -0
- package/apps/explorer/scripts/patch-lib.mjs +4 -0
- package/apps/explorer/scripts/scan-ignore.mjs +9 -0
- package/apps/explorer/scripts/scan-target.mjs +22 -5
- package/apps/explorer/scripts/session-store.d.ts +86 -11
- package/apps/explorer/scripts/session-store.mjs +371 -58
- package/apps/explorer/scripts/target-config.d.ts +38 -3
- package/apps/explorer/scripts/target-config.mjs +147 -3
- package/apps/explorer/src/App.tsx +1080 -158
- package/apps/explorer/src/agentIntent.ts +61 -7
- package/apps/explorer/src/codebase.ts +1 -1
- package/apps/explorer/src/devTargets.ts +66 -0
- package/apps/explorer/src/explain.ts +312 -0
- package/apps/explorer/src/index.css +884 -223
- package/apps/explorer/src/layout.ts +55 -0
- package/apps/explorer/src/scene/DistantFileBlocks.tsx +4 -2
- package/apps/explorer/src/scene/FileBlock.tsx +95 -72
- package/apps/explorer/src/scene/FolderArea.tsx +55 -32
- package/apps/explorer/src/scene/MapView.tsx +506 -33
- package/apps/explorer/src/scene/RelationLines.tsx +7 -0
- package/apps/explorer/src/scene/World.tsx +146 -32
- package/apps/explorer/src/speech.ts +228 -0
- package/apps/explorer/src/theme.ts +29 -0
- package/apps/explorer/src/types.ts +98 -8
- package/apps/explorer/src/ui/CanvasErrorBoundary.tsx +3 -1
- package/apps/explorer/src/ui/ExplainAskCard.tsx +142 -0
- package/apps/explorer/src/ui/ExplainHud.tsx +524 -0
- package/apps/explorer/src/ui/ExplainInfoPanel.tsx +135 -0
- package/apps/explorer/src/ui/ExplainPointer.tsx +73 -0
- package/apps/explorer/src/ui/EyeIcon.tsx +38 -1
- package/apps/explorer/src/ui/HUD.tsx +1067 -792
- package/apps/explorer/src/ui/NameInput.tsx +114 -5
- package/apps/explorer/src/userContext.ts +0 -11
- package/apps/explorer/src/userCreated.ts +54 -1
- package/apps/explorer/vite.config.ts +173 -26
- package/bin/inbase.mjs +11 -2
- package/bin/project.mjs +1 -1
- package/bin/session.mjs +287 -38
- package/package.json +4 -1
- package/skill/commands/amber.md +23 -0
- package/skill/commands/blue.md +13 -0
- package/skill/commands/coral.md +23 -0
- package/skill/commands/explain.md +77 -0
- package/skill/commands/green.md +23 -0
- package/skill/commands/inbase.md +7 -5
- package/skill/commands/lime.md +23 -0
- package/skill/commands/orange.md +23 -0
- package/skill/commands/purple.md +23 -0
- package/skill/commands/red.md +23 -0
- package/skill/commands/skipinbase.md +1 -1
- package/skill/commands/violet.md +23 -0
- package/skill/commands/yellow.md +23 -0
- package/skill/inbase/SKILL.md +124 -76
- package/apps/explorer/src/scene/BlockPlacer.tsx +0 -78
- package/apps/explorer/src/scene/IslandPlacer.tsx +0 -31
- package/apps/explorer/src/scene/SelectionThumbnail.tsx +0 -1050
|
@@ -16,6 +16,7 @@ export type FileNode = {
|
|
|
16
16
|
symbols: CodeSymbol[]
|
|
17
17
|
imports: string[]
|
|
18
18
|
userCreated?: boolean
|
|
19
|
+
colorHex?: string
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
export type FolderNode = {
|
|
@@ -25,6 +26,7 @@ export type FolderNode = {
|
|
|
25
26
|
files: string[]
|
|
26
27
|
children: string[]
|
|
27
28
|
userCreated?: boolean
|
|
29
|
+
colorHex?: string
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
export type CodebaseGraph = {
|
|
@@ -49,6 +51,7 @@ export type PlacedFolder = {
|
|
|
49
51
|
width: number
|
|
50
52
|
depth: number
|
|
51
53
|
added?: boolean
|
|
54
|
+
colorHex?: string
|
|
52
55
|
}
|
|
53
56
|
|
|
54
57
|
export type PlacedBridge = {
|
|
@@ -88,6 +91,7 @@ export type UserCreatedBlock = {
|
|
|
88
91
|
x: number
|
|
89
92
|
z: number
|
|
90
93
|
naming?: boolean
|
|
94
|
+
colorHex?: string
|
|
91
95
|
}
|
|
92
96
|
|
|
93
97
|
export type UserCreatedIsland = {
|
|
@@ -96,6 +100,7 @@ export type UserCreatedIsland = {
|
|
|
96
100
|
path: string
|
|
97
101
|
parent: string
|
|
98
102
|
naming?: boolean
|
|
103
|
+
colorHex?: string
|
|
99
104
|
}
|
|
100
105
|
|
|
101
106
|
export type UserContext = {
|
|
@@ -113,7 +118,6 @@ export type UserContext = {
|
|
|
113
118
|
x: number
|
|
114
119
|
z: number
|
|
115
120
|
}
|
|
116
|
-
followLook?: boolean
|
|
117
121
|
showBranchChanges?: boolean
|
|
118
122
|
userCreatedBlocks?: UserCreatedBlock[]
|
|
119
123
|
userCreatedIslands?: UserCreatedIsland[]
|
|
@@ -154,13 +158,6 @@ export function isReviewingIntent(status: AgentIntentStatus) {
|
|
|
154
158
|
)
|
|
155
159
|
}
|
|
156
160
|
|
|
157
|
-
export function canStopSession(intent: {
|
|
158
|
-
sessionId: string | null
|
|
159
|
-
status: AgentIntentStatus
|
|
160
|
-
}) {
|
|
161
|
-
return Boolean(intent.sessionId) && intent.status !== 'idle'
|
|
162
|
-
}
|
|
163
|
-
|
|
164
161
|
export function llmIsMakingChanges(intent: {
|
|
165
162
|
working: boolean
|
|
166
163
|
preview: boolean
|
|
@@ -262,6 +259,7 @@ export type WorkflowAction =
|
|
|
262
259
|
| 'invoke'
|
|
263
260
|
| 'continue'
|
|
264
261
|
| 'instruct'
|
|
262
|
+
| 'explain_proposal'
|
|
265
263
|
| 'stop'
|
|
266
264
|
| 'blueprint_yes'
|
|
267
265
|
| 'blueprint_no'
|
|
@@ -286,11 +284,98 @@ export type SharedBlueprint = {
|
|
|
286
284
|
pointers: BlueprintPointer[]
|
|
287
285
|
}
|
|
288
286
|
|
|
287
|
+
export const GLOBAL_BLUEPRINT_COLOR = {
|
|
288
|
+
id: 'global',
|
|
289
|
+
name: 'Global',
|
|
290
|
+
hex: '#38bdf8',
|
|
291
|
+
} as const
|
|
292
|
+
|
|
293
|
+
export type BlueprintColorId = typeof GLOBAL_BLUEPRINT_COLOR.id | string
|
|
294
|
+
|
|
295
|
+
export type LocalBlueprint = SharedBlueprint & {
|
|
296
|
+
color: string
|
|
297
|
+
colorName: string
|
|
298
|
+
colorHex: string
|
|
299
|
+
sessionId: string
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export type BlueprintOption = {
|
|
303
|
+
id: string
|
|
304
|
+
name: string
|
|
305
|
+
hex: string
|
|
306
|
+
kind: 'global' | 'local'
|
|
307
|
+
sessionId?: string | null
|
|
308
|
+
}
|
|
309
|
+
|
|
289
310
|
export type AgentIntentBundle = {
|
|
290
311
|
focusedSessionId: string | null
|
|
291
312
|
nextAttachSessionId: string | null
|
|
292
313
|
intents: AgentIntent[]
|
|
293
314
|
blueprint: SharedBlueprint
|
|
315
|
+
localBlueprints: LocalBlueprint[]
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
export type ExplainRelation = {
|
|
319
|
+
from: string
|
|
320
|
+
to: string
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
export type ExplainSymbolKind = 'function' | 'variable' | 'class' | 'file' | 'symbol'
|
|
324
|
+
|
|
325
|
+
export type ExplainSymbolRef = {
|
|
326
|
+
kind: ExplainSymbolKind
|
|
327
|
+
name: string
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
export type ExplainPendingQuestion = {
|
|
331
|
+
parent: string
|
|
332
|
+
question: string
|
|
333
|
+
from: string
|
|
334
|
+
fromTitle: string
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
export type ExplainTargetKind =
|
|
338
|
+
| 'file'
|
|
339
|
+
| 'folder'
|
|
340
|
+
| 'function'
|
|
341
|
+
| 'variable'
|
|
342
|
+
| 'class'
|
|
343
|
+
|
|
344
|
+
export type ExplainPendingStart = {
|
|
345
|
+
kind: ExplainTargetKind
|
|
346
|
+
path: string
|
|
347
|
+
name?: string
|
|
348
|
+
question: string
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export type ExplainStep = {
|
|
352
|
+
index: string
|
|
353
|
+
title: string
|
|
354
|
+
body: string
|
|
355
|
+
asked: string
|
|
356
|
+
files: string[]
|
|
357
|
+
folders: string[]
|
|
358
|
+
select: string | null
|
|
359
|
+
zoom: string | null
|
|
360
|
+
relations: ExplainRelation[]
|
|
361
|
+
importedBy: boolean
|
|
362
|
+
info: boolean
|
|
363
|
+
highlights: ExplainSymbolRef[]
|
|
364
|
+
point: ExplainSymbolRef | null
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
export type ExplainPresentation = 'walk' | 'card'
|
|
368
|
+
|
|
369
|
+
export type ExplainSession = {
|
|
370
|
+
active: boolean
|
|
371
|
+
question: string
|
|
372
|
+
steps: ExplainStep[]
|
|
373
|
+
currentStep: string
|
|
374
|
+
pendingQuestion: ExplainPendingQuestion | null
|
|
375
|
+
pendingStart: ExplainPendingStart | null
|
|
376
|
+
answering: boolean
|
|
377
|
+
presentation: ExplainPresentation
|
|
378
|
+
updatedAt: string | null
|
|
294
379
|
}
|
|
295
380
|
|
|
296
381
|
export type AgentIntent = {
|
|
@@ -298,6 +383,9 @@ export type AgentIntent = {
|
|
|
298
383
|
showMap: boolean
|
|
299
384
|
status: AgentIntentStatus
|
|
300
385
|
name: string | null
|
|
386
|
+
color?: string | null
|
|
387
|
+
colorName?: string | null
|
|
388
|
+
colorHex?: string | null
|
|
301
389
|
feature: string | null
|
|
302
390
|
steps: PlanStep[]
|
|
303
391
|
step: number | null
|
|
@@ -332,6 +420,7 @@ export type AgentIntent = {
|
|
|
332
420
|
detail: string
|
|
333
421
|
at: string | null
|
|
334
422
|
} | null
|
|
423
|
+
pendingExplain?: boolean
|
|
335
424
|
initialInstruction?: string | null
|
|
336
425
|
contextFiles?: Array<{
|
|
337
426
|
id: string
|
|
@@ -344,6 +433,7 @@ export type AgentIntent = {
|
|
|
344
433
|
blueprintHidden?: boolean
|
|
345
434
|
blueprintRevision?: number
|
|
346
435
|
blueprintSessionId: string | null
|
|
436
|
+
localBlueprintEnabled?: boolean
|
|
347
437
|
userCreatedBlocks: UserCreatedBlock[]
|
|
348
438
|
userCreatedIslands: UserCreatedIsland[]
|
|
349
439
|
blueprintFunctions: PatchSymbolAddition[]
|
|
@@ -2,6 +2,7 @@ import { Component, type ReactNode } from 'react'
|
|
|
2
2
|
|
|
3
3
|
type Props = {
|
|
4
4
|
children: ReactNode
|
|
5
|
+
fallback?: ReactNode
|
|
5
6
|
}
|
|
6
7
|
|
|
7
8
|
type State = {
|
|
@@ -21,11 +22,12 @@ export class CanvasErrorBoundary extends Component<Props, State> {
|
|
|
21
22
|
|
|
22
23
|
render() {
|
|
23
24
|
if (this.state.failed) {
|
|
25
|
+
if (this.props.fallback !== undefined) return this.props.fallback
|
|
24
26
|
return (
|
|
25
27
|
<div className="canvas-error">
|
|
26
28
|
<div className="hud-gate-card">
|
|
27
29
|
<h1>Visualizer stopped</h1>
|
|
28
|
-
<p>The
|
|
30
|
+
<p>The visualizer hit an error. Reload the page to restore it.</p>
|
|
29
31
|
<button
|
|
30
32
|
className="hud-button"
|
|
31
33
|
type="button"
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { useCallback, useEffect, useState } from 'react'
|
|
2
|
+
import type { ExplainSession } from '../types'
|
|
3
|
+
import {
|
|
4
|
+
explainCardCopy,
|
|
5
|
+
explainSpeechText,
|
|
6
|
+
explainTargetLabel,
|
|
7
|
+
} from '../explain'
|
|
8
|
+
import { shouldIgnoreShortcut } from '../keyboard'
|
|
9
|
+
import {
|
|
10
|
+
canSpeak,
|
|
11
|
+
speakText,
|
|
12
|
+
stopSpeaking,
|
|
13
|
+
subscribeSpeakStatus,
|
|
14
|
+
type SpeakStatus,
|
|
15
|
+
} from '../speech'
|
|
16
|
+
|
|
17
|
+
export function ExplainAskCard({
|
|
18
|
+
explain,
|
|
19
|
+
onClose,
|
|
20
|
+
}: {
|
|
21
|
+
explain: ExplainSession
|
|
22
|
+
onClose: () => void
|
|
23
|
+
}) {
|
|
24
|
+
const copy = explainCardCopy(explain)
|
|
25
|
+
const pending = explain.pendingStart
|
|
26
|
+
const subtitle = pending
|
|
27
|
+
? explainTargetLabel(pending)
|
|
28
|
+
: explain.question || 'Explanation'
|
|
29
|
+
const speechAvailable = canSpeak()
|
|
30
|
+
const [telling, setTelling] = useState(false)
|
|
31
|
+
const [speakStatus, setSpeakStatus] = useState<SpeakStatus>('idle')
|
|
32
|
+
const spoken = explainSpeechText({
|
|
33
|
+
title: copy.title,
|
|
34
|
+
body: copy.body,
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
const stopTelling = useCallback(() => {
|
|
38
|
+
setTelling(false)
|
|
39
|
+
stopSpeaking()
|
|
40
|
+
}, [])
|
|
41
|
+
|
|
42
|
+
const toggleTell = () => {
|
|
43
|
+
if (!speechAvailable || !copy.ready) return
|
|
44
|
+
if (telling) {
|
|
45
|
+
stopTelling()
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
setTelling(true)
|
|
49
|
+
speakText(spoken, () => setTelling(false))
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
useEffect(() => subscribeSpeakStatus(setSpeakStatus), [])
|
|
53
|
+
|
|
54
|
+
useEffect(
|
|
55
|
+
() => () => {
|
|
56
|
+
stopSpeaking()
|
|
57
|
+
},
|
|
58
|
+
[],
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
const onKey = (event: KeyboardEvent) => {
|
|
63
|
+
if (event.repeat) return
|
|
64
|
+
if (event.code !== 'Escape') return
|
|
65
|
+
if (shouldIgnoreShortcut(event) && event.code !== 'Escape') return
|
|
66
|
+
event.preventDefault()
|
|
67
|
+
onClose()
|
|
68
|
+
}
|
|
69
|
+
window.addEventListener('keydown', onKey)
|
|
70
|
+
return () => window.removeEventListener('keydown', onKey)
|
|
71
|
+
}, [onClose])
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<div className="hud-note-overlay explain-ask-overlay" onClick={onClose}>
|
|
75
|
+
<div
|
|
76
|
+
className="explain-ask-card"
|
|
77
|
+
role="dialog"
|
|
78
|
+
aria-modal="true"
|
|
79
|
+
aria-labelledby="explain-ask-title"
|
|
80
|
+
onClick={(event) => event.stopPropagation()}
|
|
81
|
+
>
|
|
82
|
+
<div className="explain-ask-card-header">
|
|
83
|
+
<div className="explain-ask-card-heading">
|
|
84
|
+
<h1 id="explain-ask-title">{copy.title}</h1>
|
|
85
|
+
<p className="explain-ask-card-subtitle">{subtitle}</p>
|
|
86
|
+
</div>
|
|
87
|
+
<button
|
|
88
|
+
className="hud-button explain-exit"
|
|
89
|
+
type="button"
|
|
90
|
+
aria-label="Close explanation"
|
|
91
|
+
title="Close explanation"
|
|
92
|
+
onClick={onClose}
|
|
93
|
+
>
|
|
94
|
+
<svg
|
|
95
|
+
viewBox="0 0 24 24"
|
|
96
|
+
width="18"
|
|
97
|
+
height="18"
|
|
98
|
+
fill="none"
|
|
99
|
+
stroke="currentColor"
|
|
100
|
+
strokeWidth="2.2"
|
|
101
|
+
strokeLinecap="round"
|
|
102
|
+
aria-hidden="true"
|
|
103
|
+
>
|
|
104
|
+
<path d="M6 6l12 12" />
|
|
105
|
+
<path d="M18 6L6 18" />
|
|
106
|
+
</svg>
|
|
107
|
+
</button>
|
|
108
|
+
</div>
|
|
109
|
+
{copy.ready ? (
|
|
110
|
+
<p className="explain-body explain-ask-card-body">{copy.body}</p>
|
|
111
|
+
) : (
|
|
112
|
+
<p className="explain-preparing" role="status">
|
|
113
|
+
Preparing an explanation…
|
|
114
|
+
</p>
|
|
115
|
+
)}
|
|
116
|
+
<div className="explain-ask-card-footer">
|
|
117
|
+
{telling && speakStatus === 'loading' ? (
|
|
118
|
+
<p className="explain-voice-status">Loading a natural voice…</p>
|
|
119
|
+
) : null}
|
|
120
|
+
<button
|
|
121
|
+
className="hud-button explain-tell"
|
|
122
|
+
type="button"
|
|
123
|
+
data-active={telling}
|
|
124
|
+
aria-pressed={telling}
|
|
125
|
+
aria-label={telling ? 'Stop telling' : 'Tell me'}
|
|
126
|
+
title={
|
|
127
|
+
speechAvailable
|
|
128
|
+
? telling
|
|
129
|
+
? 'Stop reading this explanation'
|
|
130
|
+
: 'Read this explanation aloud'
|
|
131
|
+
: 'Speech is not available in this browser'
|
|
132
|
+
}
|
|
133
|
+
disabled={!speechAvailable || !copy.ready}
|
|
134
|
+
onClick={toggleTell}
|
|
135
|
+
>
|
|
136
|
+
{telling ? 'Stop' : 'Tell me'}
|
|
137
|
+
</button>
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
)
|
|
142
|
+
}
|