@jkwd/inbase 0.1.21 → 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.
Files changed (58) hide show
  1. package/README.md +13 -7
  2. package/apps/explorer/package.json +1 -0
  3. package/apps/explorer/scripts/explain-store.d.ts +135 -0
  4. package/apps/explorer/scripts/explain-store.mjs +666 -0
  5. package/apps/explorer/scripts/patch-lib.mjs +4 -0
  6. package/apps/explorer/scripts/scan-target.mjs +22 -5
  7. package/apps/explorer/scripts/session-store.d.ts +86 -11
  8. package/apps/explorer/scripts/session-store.mjs +371 -58
  9. package/apps/explorer/scripts/target-config.d.ts +38 -3
  10. package/apps/explorer/scripts/target-config.mjs +147 -3
  11. package/apps/explorer/src/App.tsx +1073 -158
  12. package/apps/explorer/src/agentIntent.ts +61 -7
  13. package/apps/explorer/src/codebase.ts +1 -1
  14. package/apps/explorer/src/devTargets.ts +66 -0
  15. package/apps/explorer/src/explain.ts +312 -0
  16. package/apps/explorer/src/index.css +874 -222
  17. package/apps/explorer/src/layout.ts +55 -0
  18. package/apps/explorer/src/scene/DistantFileBlocks.tsx +4 -2
  19. package/apps/explorer/src/scene/FileBlock.tsx +95 -72
  20. package/apps/explorer/src/scene/FolderArea.tsx +55 -32
  21. package/apps/explorer/src/scene/MapView.tsx +506 -33
  22. package/apps/explorer/src/scene/RelationLines.tsx +7 -0
  23. package/apps/explorer/src/scene/World.tsx +146 -32
  24. package/apps/explorer/src/speech.ts +228 -0
  25. package/apps/explorer/src/theme.ts +29 -0
  26. package/apps/explorer/src/types.ts +98 -8
  27. package/apps/explorer/src/ui/CanvasErrorBoundary.tsx +1 -1
  28. package/apps/explorer/src/ui/ExplainAskCard.tsx +142 -0
  29. package/apps/explorer/src/ui/ExplainHud.tsx +524 -0
  30. package/apps/explorer/src/ui/ExplainInfoPanel.tsx +135 -0
  31. package/apps/explorer/src/ui/ExplainPointer.tsx +73 -0
  32. package/apps/explorer/src/ui/EyeIcon.tsx +38 -1
  33. package/apps/explorer/src/ui/HUD.tsx +1067 -795
  34. package/apps/explorer/src/ui/NameInput.tsx +114 -5
  35. package/apps/explorer/src/userContext.ts +0 -11
  36. package/apps/explorer/src/userCreated.ts +54 -1
  37. package/apps/explorer/vite.config.ts +173 -26
  38. package/bin/inbase.mjs +11 -2
  39. package/bin/project.mjs +1 -1
  40. package/bin/session.mjs +287 -38
  41. package/package.json +4 -1
  42. package/skill/commands/amber.md +23 -0
  43. package/skill/commands/blue.md +13 -0
  44. package/skill/commands/coral.md +23 -0
  45. package/skill/commands/explain.md +77 -0
  46. package/skill/commands/green.md +23 -0
  47. package/skill/commands/inbase.md +7 -5
  48. package/skill/commands/lime.md +23 -0
  49. package/skill/commands/orange.md +23 -0
  50. package/skill/commands/purple.md +23 -0
  51. package/skill/commands/red.md +23 -0
  52. package/skill/commands/skipinbase.md +1 -1
  53. package/skill/commands/violet.md +23 -0
  54. package/skill/commands/yellow.md +23 -0
  55. package/skill/inbase/SKILL.md +124 -76
  56. package/apps/explorer/src/scene/BlockPlacer.tsx +0 -78
  57. package/apps/explorer/src/scene/IslandPlacer.tsx +0 -31
  58. package/apps/explorer/src/scene/SelectionThumbnail.tsx +0 -1069
@@ -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[]
@@ -27,7 +27,7 @@ export class CanvasErrorBoundary extends Component<Props, State> {
27
27
  <div className="canvas-error">
28
28
  <div className="hud-gate-card">
29
29
  <h1>Visualizer stopped</h1>
30
- <p>The 3D view hit an error. Reload the page to restore it.</p>
30
+ <p>The visualizer hit an error. Reload the page to restore it.</p>
31
31
  <button
32
32
  className="hud-button"
33
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
+ }