@jkwd/inbase 0.1.4 → 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.
@@ -8,9 +8,14 @@ import { SelectionController } from './SelectionController'
8
8
  import { UserContextTracker } from './UserContextTracker'
9
9
  import { BlockPlacer } from './BlockPlacer'
10
10
  import { IslandPlacer } from './IslandPlacer'
11
- import { folderOfFile, filesImporting } from '../layout'
11
+ import {
12
+ fileChangeKind,
13
+ filesImporting,
14
+ folderChangeHighlights,
15
+ folderOfFile,
16
+ mapPointOntoFolder,
17
+ } from '../layout'
12
18
  import { WORLD_VOID } from '../theme'
13
- import type { ChangeKind } from '../theme'
14
19
  import type {
15
20
  CodebaseGraph,
16
21
  FileNode,
@@ -49,6 +54,8 @@ type WorldProps = {
49
54
  flyTo: FlyTo | null
50
55
  aimedRelation: AimedRelation | null
51
56
  onAimRelation: (aim: AimedRelation | null) => void
57
+ onAimFile?: (fileId: string | null) => void
58
+ onInspect?: (fileId: string) => void
52
59
  onTravelTo: (fromId: string, toId: string) => void
53
60
  importedBy?: boolean
54
61
  namingId?: string | null
@@ -59,6 +66,8 @@ type WorldProps = {
59
66
  userCreatedBlocks?: UserCreatedBlock[]
60
67
  userCreatedIslands?: UserCreatedIsland[]
61
68
  namingIslandId?: string | null
69
+ mapGraph?: CodebaseGraph | null
70
+ mapLayout?: WorldLayout | null
62
71
  }
63
72
 
64
73
  export function World({
@@ -85,6 +94,8 @@ export function World({
85
94
  flyTo,
86
95
  aimedRelation,
87
96
  onAimRelation,
97
+ onAimFile,
98
+ onInspect,
88
99
  onTravelTo,
89
100
  importedBy = false,
90
101
  namingId = null,
@@ -95,10 +106,18 @@ export function World({
95
106
  onCancelName,
96
107
  userCreatedBlocks = [],
97
108
  userCreatedIslands = [],
109
+ mapGraph = null,
110
+ mapLayout = null,
98
111
  }: WorldProps) {
99
112
  const created = new Set(createdIds)
100
113
  const deleted = new Set(deletedIds)
101
114
  const mapping = mode === 'map'
115
+ const viewGraph = mapping && mapGraph ? mapGraph : graph
116
+ const viewLayout = mapping && mapLayout ? mapLayout : layout
117
+ const mapMarker =
118
+ viewLayout === layout
119
+ ? landAt
120
+ : mapPointOntoFolder(landAt[0], landAt[1], layout, viewLayout)
102
121
  const placing = Boolean(namingId || namingIslandId)
103
122
  const planned = new Set(plannedIds)
104
123
  const ghosts = previewFiles
@@ -127,37 +146,12 @@ export function World({
127
146
  Boolean(selectedFolder) ||
128
147
  planned.size > 0 ||
129
148
  deleted.size > 0
130
- const highlightedFolders: Partial<Record<string, ChangeKind>> = {}
131
- const folderKinds = new Map<string, Set<ChangeKind>>()
132
- const addFolderKind = (id: string, kind: ChangeKind) => {
133
- const folder = folderOfFile(id)
134
- const kinds = folderKinds.get(folder) ?? new Set<ChangeKind>()
135
- kinds.add(kind)
136
- folderKinds.set(folder, kinds)
137
- }
138
- for (const id of planned) {
139
- addFolderKind(id, created.has(id) ? 'add' : 'edit')
140
- }
141
- for (const id of deleted) addFolderKind(id, 'remove')
142
- for (const [folder, kinds] of folderKinds) {
143
- if (kinds.size === 1) highlightedFolders[folder] = [...kinds][0]
144
- }
145
- if (planned.size > 0 || deleted.size > 0) {
146
- for (const folder of Object.values(layout.folders)) {
147
- if (!folder.added) continue
148
- const kinds = folderKinds.get(folder.path)
149
- if (!kinds || kinds.size === 1) {
150
- highlightedFolders[folder.path] ??= 'add'
151
- }
152
- }
153
- }
154
-
155
- const changeKindOf = (id: string): ChangeKind | null => {
156
- if (deleted.has(id)) return 'remove'
157
- if (created.has(id)) return 'add'
158
- if (planned.has(id)) return 'edit'
159
- return null
160
- }
149
+ const highlightedFolders = folderChangeHighlights(
150
+ planned,
151
+ created,
152
+ deleted,
153
+ viewLayout.folders,
154
+ )
161
155
 
162
156
  return (
163
157
  <>
@@ -170,9 +164,9 @@ export function World({
170
164
  />
171
165
  <ambientLight intensity={mapping ? 0.7 : 0.42} />
172
166
  <MapView
173
- layout={layout}
167
+ layout={viewLayout}
174
168
  enabled={mapping}
175
- marker={landAt}
169
+ marker={mapMarker}
176
170
  highlightedFolders={highlightedFolders}
177
171
  selectedFolder={selectedFolder}
178
172
  onLand={onLand}
@@ -181,26 +175,28 @@ export function World({
181
175
  onTravelTo={onTravelTo}
182
176
  />
183
177
 
184
- {Object.values(layout.folders).map((folder) => (
178
+ {Object.values(viewLayout.folders).map((folder) => (
185
179
  <FolderArea
186
180
  key={folder.path}
187
181
  folder={folder}
188
182
  naming={folder.path === namingIslandId}
189
183
  selected={folder.path === selectedFolder}
190
184
  mapMode={mapping}
191
- highlightKind={highlightedFolders[folder.path] ?? null}
185
+ highlightKind={
186
+ mapping ? highlightedFolders[folder.path] ?? null : null
187
+ }
192
188
  />
193
189
  ))}
194
- {layout.bridges.map((bridge) => (
195
- <Bridge key={bridge.id} bridge={bridge} />
190
+ {viewLayout.bridges.map((bridge) => (
191
+ <Bridge key={bridge.id} bridge={bridge} folders={viewLayout.folders} />
196
192
  ))}
197
- {graph.files.map((file) => {
198
- const placed = layout.files[file.id]
193
+ {viewGraph.files.map((file) => {
194
+ const placed = viewLayout.files[file.id]
199
195
  if (!placed) return null
200
196
  const selected = file.id === selectedId
201
197
  const isRelated = related.has(file.id)
202
198
  const isPlanned = planned.has(file.id) || deleted.has(file.id)
203
- const changeKind = changeKindOf(file.id)
199
+ const changeKind = fileChangeKind(file.id, planned, created, deleted)
204
200
  const naming = file.id === namingId
205
201
  return (
206
202
  <FileBlock
@@ -267,8 +263,8 @@ export function World({
267
263
  <RelationLines
268
264
  selectedId={selectedId}
269
265
  aimedRelation={aimedRelation}
270
- files={graph.files}
271
- layout={layout}
266
+ files={viewGraph.files}
267
+ layout={viewLayout}
272
268
  extras={ghosts}
273
269
  plannedEdges={plannedImports}
274
270
  fromAbove={mapping}
@@ -302,6 +298,8 @@ export function World({
302
298
  <SelectionController
303
299
  locked={locked && !mapping}
304
300
  onSelect={onSelect}
301
+ onInspect={onInspect}
302
+ onAimFile={onAimFile}
305
303
  onAimRelation={onAimRelation}
306
304
  onTravelTo={onTravelTo}
307
305
  files={{ ...layout.files, ...ghosts }}
@@ -54,10 +54,16 @@ export const CHANGE_HIGHLIGHT: Record<
54
54
  },
55
55
  }
56
56
 
57
+ export const FILE_SELECTION = {
58
+ color: '#c026ff',
59
+ emissive: '#6d00b8',
60
+ }
61
+
57
62
  export const MAP_SELECTION = {
58
63
  color: '#000000',
64
+ island: FILE_SELECTION.color,
59
65
  islandPad: 0.38,
60
- blockPad: 0.2,
66
+ blockPad: 0.1,
61
67
  }
62
68
 
63
69
  export function fileHeight(lines: number) {
@@ -104,11 +110,18 @@ export function dimColor(hex: string, amount = 0.32) {
104
110
  return `#${channel(0)}${channel(2)}${channel(4)}`
105
111
  }
106
112
 
107
- export function folderFloorColor(path: string) {
113
+ function folderHue(path: string) {
108
114
  let hash = 0
109
115
  for (let i = 0; i < path.length; i += 1) {
110
116
  hash = path.charCodeAt(i) + ((hash << 5) - hash)
111
117
  }
112
- const hue = Math.abs(hash) % 360
113
- return `hsl(${hue}, 16%, 18%)`
118
+ return Math.abs(hash) % 360
119
+ }
120
+
121
+ export function folderFloorColor(path: string) {
122
+ return `hsl(${folderHue(path)}, 5%, 48%)`
123
+ }
124
+
125
+ export function folderAisleColor(path: string) {
126
+ return `hsl(${folderHue(path)}, 6%, 40%)`
114
127
  }
@@ -152,6 +152,13 @@ export function isReviewingIntent(status: AgentIntentStatus) {
152
152
  )
153
153
  }
154
154
 
155
+ export function canStopSession(intent: {
156
+ sessionId: string | null
157
+ status: AgentIntentStatus
158
+ }) {
159
+ return Boolean(intent.sessionId) && intent.status !== 'idle'
160
+ }
161
+
155
162
  export type PlanStep = {
156
163
  index: number
157
164
  title: string
@@ -207,6 +214,12 @@ export type WorkflowAction =
207
214
  | 'blueprint_no'
208
215
  | 'blueprint_send'
209
216
  | 'blueprint_update'
217
+ | 'set_step_by_step'
218
+
219
+ export type AgentIntentBundle = {
220
+ focusedSessionId: string | null
221
+ intents: AgentIntent[]
222
+ }
210
223
 
211
224
  export type AgentIntent = {
212
225
  updatedAt: string | null
@@ -215,6 +228,7 @@ export type AgentIntent = {
215
228
  feature: string | null
216
229
  steps: PlanStep[]
217
230
  step: number | null
231
+ stepByStep: boolean
218
232
  files: string[]
219
233
  creates: string[]
220
234
  deletes: string[]
@@ -224,6 +238,8 @@ export type AgentIntent = {
224
238
  addedFunctions: PatchSymbolAddition[]
225
239
  addedVariables: PatchSymbolAddition[]
226
240
  addedImports: PatchImportAddition[]
241
+ changedFunctions: PatchSymbolAddition[]
242
+ changedVariables: PatchSymbolAddition[]
227
243
  reason: string | null
228
244
  sessionId: string | null
229
245
  diffId: string | null
@@ -234,6 +250,7 @@ export type AgentIntent = {
234
250
  preview: boolean
235
251
  phase: WorkflowPhase | null
236
252
  working: boolean
253
+ stalledWait: boolean
237
254
  creationMode: boolean
238
255
  canEnterBlueprint: boolean
239
256
  blueprintSessionId: string | null