@jkwd/inbase 0.1.19 → 0.1.20
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 +1 -1
- package/apps/explorer/scripts/patch-lib.d.ts +1 -0
- package/apps/explorer/scripts/patch-lib.mjs +1 -0
- package/apps/explorer/scripts/session-store.d.ts +3 -0
- package/apps/explorer/scripts/session-store.mjs +54 -2
- package/apps/explorer/src/App.tsx +112 -3
- package/apps/explorer/src/agentIntent.ts +10 -1
- package/apps/explorer/src/scene/FileBlock.tsx +27 -0
- package/apps/explorer/src/scene/FolderArea.tsx +21 -0
- package/apps/explorer/src/scene/SelectionThumbnail.tsx +16 -3
- package/apps/explorer/src/scene/World.tsx +22 -3
- package/apps/explorer/src/types.ts +10 -0
- package/apps/explorer/src/ui/EyeIcon.tsx +26 -0
- package/apps/explorer/src/ui/HUD.tsx +179 -23
- package/apps/explorer/src/ui/MapContextMenu.tsx +18 -1
- package/apps/explorer/src/userCreated.ts +97 -0
- package/apps/explorer/vite.config.ts +4 -0
- package/package.json +1 -1
- package/skill/inbase/SKILL.md +17 -20
|
@@ -3,6 +3,8 @@ import { folderOfFile, folderParent } from './layout'
|
|
|
3
3
|
import type {
|
|
4
4
|
BlueprintNote,
|
|
5
5
|
BlueprintNoteKind,
|
|
6
|
+
BlueprintPointer,
|
|
7
|
+
BlueprintPointerKind,
|
|
6
8
|
CodebaseGraph,
|
|
7
9
|
FileNode,
|
|
8
10
|
PatchImportAddition,
|
|
@@ -437,6 +439,101 @@ export function dropBlueprintSymbolNote(
|
|
|
437
439
|
)
|
|
438
440
|
}
|
|
439
441
|
|
|
442
|
+
export function blueprintPointerKey(
|
|
443
|
+
pointer: Pick<BlueprintPointer, 'kind' | 'path' | 'name'>,
|
|
444
|
+
) {
|
|
445
|
+
return pointer.kind === 'file' || pointer.kind === 'folder'
|
|
446
|
+
? `${pointer.kind}:${pointer.path}`
|
|
447
|
+
: `${pointer.kind}:${pointer.path}:${pointer.name ?? ''}`
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
function parseBlueprintPointer(value: unknown): BlueprintPointer | null {
|
|
451
|
+
if (!value || typeof value !== 'object') return null
|
|
452
|
+
const item = value as Partial<BlueprintPointer>
|
|
453
|
+
const path = typeof item.path === 'string' ? item.path.trim() : ''
|
|
454
|
+
if (!path) return null
|
|
455
|
+
if (item.kind === 'file' || item.kind === 'folder') {
|
|
456
|
+
return { kind: item.kind, path }
|
|
457
|
+
}
|
|
458
|
+
if (item.kind !== 'function' && item.kind !== 'variable') return null
|
|
459
|
+
const name = typeof item.name === 'string' ? item.name.trim() : ''
|
|
460
|
+
if (!name) return null
|
|
461
|
+
return { kind: item.kind, path, name }
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
export function parseBlueprintPointers(value: unknown): BlueprintPointer[] {
|
|
465
|
+
if (!Array.isArray(value)) return []
|
|
466
|
+
const seen = new Set<string>()
|
|
467
|
+
const pointers: BlueprintPointer[] = []
|
|
468
|
+
for (const item of value) {
|
|
469
|
+
const parsed = parseBlueprintPointer(item)
|
|
470
|
+
if (!parsed) continue
|
|
471
|
+
const key = blueprintPointerKey(parsed)
|
|
472
|
+
if (seen.has(key)) continue
|
|
473
|
+
seen.add(key)
|
|
474
|
+
pointers.push(parsed)
|
|
475
|
+
}
|
|
476
|
+
return pointers
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
export function findBlueprintPointer(
|
|
480
|
+
pointers: BlueprintPointer[],
|
|
481
|
+
kind: BlueprintPointerKind,
|
|
482
|
+
path: string,
|
|
483
|
+
name?: string,
|
|
484
|
+
) {
|
|
485
|
+
return pointers.some((item) =>
|
|
486
|
+
kind === 'file' || kind === 'folder'
|
|
487
|
+
? item.kind === kind && item.path === path
|
|
488
|
+
: item.kind === kind && item.path === path && item.name === name,
|
|
489
|
+
)
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
export function toggleBlueprintPointer(
|
|
493
|
+
pointers: BlueprintPointer[],
|
|
494
|
+
next: {
|
|
495
|
+
kind: BlueprintPointerKind
|
|
496
|
+
path: string
|
|
497
|
+
name?: string
|
|
498
|
+
},
|
|
499
|
+
): BlueprintPointer[] {
|
|
500
|
+
const path = next.path.trim()
|
|
501
|
+
if (!path || path.startsWith('draft:')) return pointers
|
|
502
|
+
const key = blueprintPointerKey({ ...next, path })
|
|
503
|
+
const without = pointers.filter((item) => blueprintPointerKey(item) !== key)
|
|
504
|
+
if (without.length !== pointers.length) return without
|
|
505
|
+
if (next.kind === 'file' || next.kind === 'folder') {
|
|
506
|
+
return [...without, { kind: next.kind, path }]
|
|
507
|
+
}
|
|
508
|
+
const name = (next.name ?? '').trim()
|
|
509
|
+
if (!name) return without
|
|
510
|
+
return [...without, { kind: next.kind, path, name }]
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
export function dropBlueprintFilePointers(
|
|
514
|
+
pointers: BlueprintPointer[],
|
|
515
|
+
fileIds: Iterable<string>,
|
|
516
|
+
folderPaths: Iterable<string> = [],
|
|
517
|
+
) {
|
|
518
|
+
const files = new Set(fileIds)
|
|
519
|
+
const folders = new Set(folderPaths)
|
|
520
|
+
return pointers.filter((item) =>
|
|
521
|
+
item.kind === 'folder' ? !folders.has(item.path) : !files.has(item.path),
|
|
522
|
+
)
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
export function dropBlueprintSymbolPointer(
|
|
526
|
+
pointers: BlueprintPointer[],
|
|
527
|
+
path: string,
|
|
528
|
+
kind: 'function' | 'variable',
|
|
529
|
+
name: string,
|
|
530
|
+
) {
|
|
531
|
+
return pointers.filter(
|
|
532
|
+
(item) =>
|
|
533
|
+
!(item.kind === kind && item.path === path && item.name === name),
|
|
534
|
+
)
|
|
535
|
+
}
|
|
536
|
+
|
|
440
537
|
export function parseBlueprintImport(
|
|
441
538
|
raw: string,
|
|
442
539
|
file: string,
|
|
@@ -114,6 +114,7 @@ function blueprintIntentFields() {
|
|
|
114
114
|
blueprintVariables: blueprint.addedVariables,
|
|
115
115
|
blueprintImports: blueprint.addedImports,
|
|
116
116
|
blueprintNotes: blueprint.notes,
|
|
117
|
+
blueprintPointers: blueprint.pointers,
|
|
117
118
|
}
|
|
118
119
|
}
|
|
119
120
|
|
|
@@ -267,6 +268,7 @@ async function decideIntent(req: IncomingMessage, res: ServerResponse) {
|
|
|
267
268
|
addedVariables?: unknown[]
|
|
268
269
|
addedImports?: unknown[]
|
|
269
270
|
notes?: unknown[]
|
|
271
|
+
pointers?: unknown[]
|
|
270
272
|
files?: unknown[]
|
|
271
273
|
fileId?: string
|
|
272
274
|
}
|
|
@@ -360,6 +362,7 @@ async function decideIntent(req: IncomingMessage, res: ServerResponse) {
|
|
|
360
362
|
addedVariables: body.addedVariables,
|
|
361
363
|
addedImports: body.addedImports,
|
|
362
364
|
notes: body.notes,
|
|
365
|
+
pointers: body.pointers,
|
|
363
366
|
})
|
|
364
367
|
} else if (action === 'blueprint_clear') {
|
|
365
368
|
clearBlueprint(dataDir)
|
|
@@ -375,6 +378,7 @@ async function decideIntent(req: IncomingMessage, res: ServerResponse) {
|
|
|
375
378
|
addedVariables: body.addedVariables,
|
|
376
379
|
addedImports: body.addedImports,
|
|
377
380
|
notes: body.notes,
|
|
381
|
+
pointers: body.pointers,
|
|
378
382
|
})
|
|
379
383
|
} else if (action === 'setup_session') {
|
|
380
384
|
const manifest = setupSession(dataDir, {
|
package/package.json
CHANGED
package/skill/inbase/SKILL.md
CHANGED
|
@@ -43,8 +43,8 @@ over the recorded diffs.
|
|
|
43
43
|
live project files with Write, StrReplace, and Delete for that step only. Then
|
|
44
44
|
run `inbase propose-patch` with no patch file. Inbase diffs the working tree
|
|
45
45
|
against the snapshot taken at invoke and stores that patch. A later instruction
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
updates that live proposal; edit those files, then propose-patch again. Wait
|
|
47
|
+
for **Accept proposal** before the next step. Do not write a unified diff yourself.
|
|
48
48
|
|
|
49
49
|
The visualizer stores immutable diffs under
|
|
50
50
|
`.inbase/diff-sessions/<session-id>/diffs/`. Inbase must already be running
|
|
@@ -180,11 +180,15 @@ npx inbase wait-for-approval --session "<session-id>"
|
|
|
180
180
|
12. Read the wait command output. Reply in chat with the `VISUAL_CODER_ACK`
|
|
181
181
|
line first, then:
|
|
182
182
|
|
|
183
|
-
- Exit `0` (`VISUAL_CODER_ACK execute` / `VISUAL_CODER_EXECUTE`):
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
183
|
+
- Exit `0` (`VISUAL_CODER_ACK execute` / `VISUAL_CODER_EXECUTE`): follow
|
|
184
|
+
the printed `VISUAL_CODER_EXECUTE` line. If it says **Update the current
|
|
185
|
+
proposal**, edit those live files, record with `inbase propose-patch` (no
|
|
186
|
+
patch file), then wait again for **Accept proposal**. Do not start the
|
|
187
|
+
next step and do not report a new plan. Otherwise the highlighted step
|
|
188
|
+
was invoked: implement that step now — do not explore, re-plan, or run
|
|
189
|
+
`wait-for-blueprint`. Re-read the shared `blueprint.json` if you need
|
|
190
|
+
placed files. Edit live files for that step only, record with
|
|
191
|
+
`inbase propose-patch` (no patch file), then wait again.
|
|
188
192
|
- Exit `6` (`VISUAL_CODER_ACK blueprint` / `VISUAL_CODER_BLUEPRINT`): the
|
|
189
193
|
shared blueprint changed. Follow the latest files, islands, functions,
|
|
190
194
|
variables, and imports. Do not omit, rename, relocate, or replace them.
|
|
@@ -195,19 +199,12 @@ npx inbase wait-for-approval --session "<session-id>"
|
|
|
195
199
|
stored session diffs. The shared blueprint remains. Optionally run
|
|
196
200
|
`--clear` if anything remains, tell the user the feature is done, and
|
|
197
201
|
**stop**. Do not propose another patch.
|
|
198
|
-
- Exit `4` (`VISUAL_CODER_ACK replan` / `VISUAL_CODER_REPLAN`):
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
`
|
|
203
|
-
|
|
204
|
-
`addedImports`). The blueprint stays leading. If the new instruction would
|
|
205
|
-
differ from it, ask the user before replacing the plan. Read
|
|
206
|
-
`user-context.json` (follow the viewpoint only if `followLook` is true),
|
|
207
|
-
replace the plan from the current step onward using `inbase report-plan`,
|
|
208
|
-
then wait for the next `VISUAL_CODER_EXECUTE` before editing again. The
|
|
209
|
-
replacement edits must sit on the accepted live files, not the withdrawn
|
|
210
|
-
proposal.
|
|
202
|
+
- Exit `4` (`VISUAL_CODER_ACK replan` / `VISUAL_CODER_REPLAN`): live files
|
|
203
|
+
still contain the current proposal. Do not reset them and do not report a
|
|
204
|
+
new plan. Follow the text between `VISUAL_CODER_INSTRUCTION_START` and
|
|
205
|
+
`VISUAL_CODER_INSTRUCTION_END`, edit those live files, then
|
|
206
|
+
`inbase propose-patch`. Wait for **Accept proposal**. Do not start the
|
|
207
|
+
next step.
|
|
211
208
|
- Exit `2` (`VISUAL_CODER_ACK stopped` / `VISUAL_CODER_STOPPED`) or `3`
|
|
212
209
|
(`VISUAL_CODER_ACK timeout`): make no further project changes.
|
|
213
210
|
|