@jkwd/inbase 0.1.13 → 0.1.16
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 +2 -2
- package/apps/explorer/scripts/branch-changes.mjs +2 -19
- package/apps/explorer/scripts/patch-lib.d.ts +3 -0
- package/apps/explorer/scripts/patch-lib.mjs +3 -0
- package/apps/explorer/scripts/scan-ignore.mjs +156 -0
- package/apps/explorer/scripts/scan-target.mjs +67 -29
- package/apps/explorer/scripts/session-store.d.ts +24 -3
- package/apps/explorer/scripts/session-store.mjs +180 -74
- package/apps/explorer/src/App.tsx +258 -147
- package/apps/explorer/src/agentIntent.ts +87 -5
- package/apps/explorer/src/index.css +106 -5
- package/apps/explorer/src/keyboard.ts +26 -0
- package/apps/explorer/src/scene/BlockPlacer.tsx +2 -11
- package/apps/explorer/src/scene/FileBlock.tsx +12 -4
- package/apps/explorer/src/scene/FolderArea.tsx +20 -0
- package/apps/explorer/src/scene/IslandPlacer.tsx +2 -11
- package/apps/explorer/src/scene/MapView.tsx +74 -37
- package/apps/explorer/src/scene/Player.tsx +9 -9
- package/apps/explorer/src/scene/SelectionThumbnail.tsx +2 -0
- package/apps/explorer/src/scene/World.tsx +46 -1
- package/apps/explorer/src/types.ts +28 -0
- package/apps/explorer/src/ui/CanvasErrorBoundary.tsx +4 -0
- package/apps/explorer/src/ui/HUD.tsx +435 -99
- package/apps/explorer/src/ui/MapContextMenu.tsx +2 -0
- package/apps/explorer/src/userCreated.ts +98 -0
- package/apps/explorer/vite.config.ts +71 -5
- package/bin/session.mjs +40 -12
- package/package.json +2 -1
- package/skill/commands/inbase.md +1 -1
- package/skill/inbase/SKILL.md +24 -22
|
@@ -390,7 +390,6 @@ export function listAttachQueue(dataDir) {
|
|
|
390
390
|
missing.push(sessionId)
|
|
391
391
|
}
|
|
392
392
|
}
|
|
393
|
-
missing.reverse()
|
|
394
393
|
const next = [...queued, ...missing]
|
|
395
394
|
const unchanged =
|
|
396
395
|
next.length === recorded.length &&
|
|
@@ -406,15 +405,11 @@ export function nextAttachSessionId(dataDir) {
|
|
|
406
405
|
function enqueueAttachSession(dataDir, sessionId) {
|
|
407
406
|
const safeId = assertSessionId(sessionId)
|
|
408
407
|
const rest = listAttachQueue(dataDir).filter((id) => id !== safeId)
|
|
409
|
-
writeAttachQueue(dataDir, [
|
|
408
|
+
writeAttachQueue(dataDir, [...rest, safeId])
|
|
410
409
|
}
|
|
411
410
|
|
|
412
|
-
function
|
|
413
|
-
return (
|
|
414
|
-
manifest.phase !== 'blueprint_ask' &&
|
|
415
|
-
manifest.phase !== 'finished' &&
|
|
416
|
-
manifest.phase !== 'stopped'
|
|
417
|
-
)
|
|
411
|
+
function blueprintFile(dataDir) {
|
|
412
|
+
return path.join(dataDir, 'blueprint.json')
|
|
418
413
|
}
|
|
419
414
|
|
|
420
415
|
function blueprintHasContent(blueprint) {
|
|
@@ -423,7 +418,8 @@ function blueprintHasContent(blueprint) {
|
|
|
423
418
|
(blueprint.userCreatedIslands?.length ?? 0) > 0 ||
|
|
424
419
|
(blueprint.addedFunctions?.length ?? 0) > 0 ||
|
|
425
420
|
(blueprint.addedVariables?.length ?? 0) > 0 ||
|
|
426
|
-
(blueprint.addedImports?.length ?? 0) > 0
|
|
421
|
+
(blueprint.addedImports?.length ?? 0) > 0 ||
|
|
422
|
+
(blueprint.notes?.length ?? 0) > 0
|
|
427
423
|
)
|
|
428
424
|
}
|
|
429
425
|
|
|
@@ -660,8 +656,10 @@ export function sessionIntent(
|
|
|
660
656
|
!isSessionConnected(dataDir, sessionId, waiterIds),
|
|
661
657
|
listening: waiterIds.has(sessionId),
|
|
662
658
|
lastAck: readSessionAck(dataDir, sessionId),
|
|
663
|
-
creationMode:
|
|
659
|
+
creationMode: true,
|
|
664
660
|
canEnterBlueprint,
|
|
661
|
+
blueprintHidden: Boolean(blueprint.hidden),
|
|
662
|
+
blueprintRevision: blueprint.revision,
|
|
665
663
|
blueprintSessionId: null,
|
|
666
664
|
userCreatedBlocks: blueprint.userCreatedBlocks,
|
|
667
665
|
userCreatedIslands: blueprint.userCreatedIslands,
|
|
@@ -669,6 +667,7 @@ export function sessionIntent(
|
|
|
669
667
|
blueprintFunctions: blueprint.addedFunctions,
|
|
670
668
|
blueprintVariables: blueprint.addedVariables,
|
|
671
669
|
blueprintImports: blueprint.addedImports,
|
|
670
|
+
blueprintNotes: blueprint.notes,
|
|
672
671
|
}
|
|
673
672
|
}
|
|
674
673
|
|
|
@@ -935,7 +934,6 @@ export function startSession(dataDir, input) {
|
|
|
935
934
|
diffs: [],
|
|
936
935
|
}
|
|
937
936
|
writeManifest(dataDir, manifest)
|
|
938
|
-
writeBlueprint(dataDir, sessionId, emptyBlueprint())
|
|
939
937
|
focusSession(dataDir, sessionId)
|
|
940
938
|
return manifest
|
|
941
939
|
}
|
|
@@ -974,11 +972,6 @@ export function setupSession(dataDir, input = {}) {
|
|
|
974
972
|
diffs: [],
|
|
975
973
|
}
|
|
976
974
|
writeManifest(dataDir, manifest)
|
|
977
|
-
writeBlueprint(dataDir, sessionId, {
|
|
978
|
-
...emptyBlueprint(),
|
|
979
|
-
enabled: true,
|
|
980
|
-
sent: false,
|
|
981
|
-
})
|
|
982
975
|
focusSession(dataDir, sessionId)
|
|
983
976
|
enqueueAttachSession(dataDir, sessionId)
|
|
984
977
|
return manifest
|
|
@@ -1047,25 +1040,14 @@ export function answerBlueprint(dataDir, sessionId, enabled) {
|
|
|
1047
1040
|
if (manifest.phase !== 'blueprint_ask') {
|
|
1048
1041
|
throw new Error(`Session ${sessionId} is not asking for a blueprint`)
|
|
1049
1042
|
}
|
|
1050
|
-
const blueprint = {
|
|
1051
|
-
...emptyBlueprint(),
|
|
1052
|
-
enabled: Boolean(enabled),
|
|
1053
|
-
sent: !enabled,
|
|
1054
|
-
}
|
|
1055
|
-
writeBlueprint(dataDir, sessionId, blueprint)
|
|
1056
1043
|
manifest.phase = enabled ? 'blueprint' : 'preparing'
|
|
1057
1044
|
if (!enabled) manifest.workStartedAt = new Date().toISOString()
|
|
1058
1045
|
writeManifest(dataDir, manifest)
|
|
1059
1046
|
return manifest
|
|
1060
1047
|
}
|
|
1061
1048
|
|
|
1062
|
-
export function updateBlueprint(dataDir,
|
|
1063
|
-
const
|
|
1064
|
-
const manifest = requireManifest(dataDir, safeId)
|
|
1065
|
-
if (!sessionAllowsPlacement(manifest)) {
|
|
1066
|
-
throw new Error(`Session ${safeId} is not accepting blueprint edits`)
|
|
1067
|
-
}
|
|
1068
|
-
const current = readBlueprint(dataDir, safeId)
|
|
1049
|
+
export function updateBlueprint(dataDir, _sessionId, input = {}) {
|
|
1050
|
+
const current = readBlueprint(dataDir)
|
|
1069
1051
|
const next = {
|
|
1070
1052
|
...current,
|
|
1071
1053
|
userCreatedBlocks: input.userCreatedBlocks ?? current.userCreatedBlocks,
|
|
@@ -1073,13 +1055,9 @@ export function updateBlueprint(dataDir, sessionId, input = {}) {
|
|
|
1073
1055
|
addedFunctions: input.addedFunctions ?? current.addedFunctions,
|
|
1074
1056
|
addedVariables: input.addedVariables ?? current.addedVariables,
|
|
1075
1057
|
addedImports: input.addedImports ?? current.addedImports,
|
|
1058
|
+
notes: input.notes ?? current.notes,
|
|
1076
1059
|
}
|
|
1077
|
-
writeBlueprint(dataDir,
|
|
1078
|
-
...next,
|
|
1079
|
-
enabled: current.enabled || blueprintHasContent(next),
|
|
1080
|
-
sent: manifest.phase === 'blueprint' ? false : current.sent,
|
|
1081
|
-
})
|
|
1082
|
-
return readBlueprint(dataDir, safeId)
|
|
1060
|
+
return writeBlueprint(dataDir, next)
|
|
1083
1061
|
}
|
|
1084
1062
|
|
|
1085
1063
|
export function sendBlueprint(dataDir, sessionId, input = {}) {
|
|
@@ -1088,19 +1066,16 @@ export function sendBlueprint(dataDir, sessionId, input = {}) {
|
|
|
1088
1066
|
if (manifest.phase !== 'blueprint') {
|
|
1089
1067
|
throw new Error(`Session ${safeId} is not in blueprint mode`)
|
|
1090
1068
|
}
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1069
|
+
if (
|
|
1070
|
+
input.userCreatedBlocks ||
|
|
1071
|
+
input.userCreatedIslands ||
|
|
1072
|
+
input.addedFunctions ||
|
|
1073
|
+
input.addedVariables ||
|
|
1074
|
+
input.addedImports ||
|
|
1075
|
+
input.notes
|
|
1076
|
+
) {
|
|
1077
|
+
updateBlueprint(dataDir, safeId, input)
|
|
1098
1078
|
}
|
|
1099
|
-
writeBlueprint(dataDir, safeId, {
|
|
1100
|
-
...next,
|
|
1101
|
-
enabled: blueprintHasContent(next),
|
|
1102
|
-
sent: true,
|
|
1103
|
-
})
|
|
1104
1079
|
manifest.phase = 'preparing'
|
|
1105
1080
|
manifest.workStartedAt = new Date().toISOString()
|
|
1106
1081
|
writeManifest(dataDir, manifest)
|
|
@@ -1114,12 +1089,6 @@ export function maybeStartVisualizerHandshake(dataDir, sessionId) {
|
|
|
1114
1089
|
if (manifest.phase !== 'blueprint_ask' && manifest.phase !== 'blueprint') {
|
|
1115
1090
|
return manifest
|
|
1116
1091
|
}
|
|
1117
|
-
const current = readBlueprint(dataDir, safeId)
|
|
1118
|
-
writeBlueprint(dataDir, safeId, {
|
|
1119
|
-
...current,
|
|
1120
|
-
enabled: blueprintHasContent(current),
|
|
1121
|
-
sent: true,
|
|
1122
|
-
})
|
|
1123
1092
|
manifest.phase = 'preparing'
|
|
1124
1093
|
manifest.workStartedAt = new Date().toISOString()
|
|
1125
1094
|
writeManifest(dataDir, manifest)
|
|
@@ -1552,13 +1521,16 @@ export function finalizeFinishedSession(dataDir, sessionId) {
|
|
|
1552
1521
|
|
|
1553
1522
|
export function emptyBlueprint() {
|
|
1554
1523
|
return {
|
|
1524
|
+
hidden: false,
|
|
1525
|
+
revision: 0,
|
|
1555
1526
|
enabled: false,
|
|
1556
|
-
sent:
|
|
1527
|
+
sent: true,
|
|
1557
1528
|
userCreatedBlocks: [],
|
|
1558
1529
|
userCreatedIslands: [],
|
|
1559
1530
|
addedFunctions: [],
|
|
1560
1531
|
addedVariables: [],
|
|
1561
1532
|
addedImports: [],
|
|
1533
|
+
notes: [],
|
|
1562
1534
|
}
|
|
1563
1535
|
}
|
|
1564
1536
|
|
|
@@ -1622,36 +1594,170 @@ function namedBlueprintImportAdditions(value) {
|
|
|
1622
1594
|
})
|
|
1623
1595
|
}
|
|
1624
1596
|
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
const
|
|
1597
|
+
function namedBlueprintNotes(value) {
|
|
1598
|
+
if (!Array.isArray(value)) return []
|
|
1599
|
+
const seen = new Set()
|
|
1600
|
+
const notes = []
|
|
1601
|
+
for (const item of value) {
|
|
1602
|
+
if (!item || typeof item !== 'object') continue
|
|
1603
|
+
const file = typeof item.file === 'string' ? item.file.trim() : ''
|
|
1604
|
+
const note = typeof item.note === 'string' ? item.note : ''
|
|
1605
|
+
if (!file || !note.trim()) continue
|
|
1606
|
+
let stored = null
|
|
1607
|
+
if (item.kind === 'file') {
|
|
1608
|
+
stored = { file, kind: 'file', note }
|
|
1609
|
+
} else if (
|
|
1610
|
+
(item.kind === 'function' || item.kind === 'variable') &&
|
|
1611
|
+
typeof item.name === 'string' &&
|
|
1612
|
+
item.name.trim() !== ''
|
|
1613
|
+
) {
|
|
1614
|
+
stored = { file, kind: item.kind, name: item.name.trim(), note }
|
|
1615
|
+
}
|
|
1616
|
+
if (!stored) continue
|
|
1617
|
+
const key =
|
|
1618
|
+
stored.kind === 'file'
|
|
1619
|
+
? `file:${stored.file}`
|
|
1620
|
+
: `${stored.kind}:${stored.file}:${stored.name}`
|
|
1621
|
+
if (seen.has(key)) continue
|
|
1622
|
+
seen.add(key)
|
|
1623
|
+
notes.push(stored)
|
|
1624
|
+
}
|
|
1625
|
+
return notes
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1628
|
+
function blueprintContentEqual(left, right) {
|
|
1629
|
+
return (
|
|
1630
|
+
JSON.stringify({
|
|
1631
|
+
userCreatedBlocks: left.userCreatedBlocks,
|
|
1632
|
+
userCreatedIslands: left.userCreatedIslands,
|
|
1633
|
+
addedFunctions: left.addedFunctions,
|
|
1634
|
+
addedVariables: left.addedVariables,
|
|
1635
|
+
addedImports: left.addedImports,
|
|
1636
|
+
notes: left.notes,
|
|
1637
|
+
}) ===
|
|
1638
|
+
JSON.stringify({
|
|
1639
|
+
userCreatedBlocks: right.userCreatedBlocks,
|
|
1640
|
+
userCreatedIslands: right.userCreatedIslands,
|
|
1641
|
+
addedFunctions: right.addedFunctions,
|
|
1642
|
+
addedVariables: right.addedVariables,
|
|
1643
|
+
addedImports: right.addedImports,
|
|
1644
|
+
notes: right.notes,
|
|
1645
|
+
})
|
|
1646
|
+
)
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1649
|
+
function normalizeBlueprint(value) {
|
|
1650
|
+
const userCreatedBlocks = namedBlueprintBlocks(value?.userCreatedBlocks)
|
|
1651
|
+
const userCreatedIslands = namedBlueprintIslands(value?.userCreatedIslands)
|
|
1652
|
+
const addedFunctions = namedBlueprintSymbols(value?.addedFunctions)
|
|
1653
|
+
const addedVariables = namedBlueprintSymbols(value?.addedVariables)
|
|
1654
|
+
const addedImports = namedBlueprintImportAdditions(value?.addedImports)
|
|
1655
|
+
const notes = namedBlueprintNotes(value?.notes)
|
|
1656
|
+
const revision =
|
|
1657
|
+
Number.isInteger(value?.revision) && value.revision >= 0 ? value.revision : 0
|
|
1628
1658
|
return {
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1659
|
+
hidden: Boolean(value?.hidden),
|
|
1660
|
+
revision,
|
|
1661
|
+
enabled: blueprintHasContent({
|
|
1662
|
+
userCreatedBlocks,
|
|
1663
|
+
userCreatedIslands,
|
|
1664
|
+
addedFunctions,
|
|
1665
|
+
addedVariables,
|
|
1666
|
+
addedImports,
|
|
1667
|
+
notes,
|
|
1668
|
+
}),
|
|
1669
|
+
sent: true,
|
|
1670
|
+
userCreatedBlocks,
|
|
1671
|
+
userCreatedIslands,
|
|
1672
|
+
addedFunctions,
|
|
1673
|
+
addedVariables,
|
|
1674
|
+
addedImports,
|
|
1675
|
+
notes,
|
|
1636
1676
|
}
|
|
1637
1677
|
}
|
|
1638
1678
|
|
|
1639
|
-
export function
|
|
1640
|
-
|
|
1679
|
+
export function readBlueprint(dataDir, _sessionId) {
|
|
1680
|
+
return normalizeBlueprint(readJson(blueprintFile(dataDir), emptyBlueprint()))
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
export function writeBlueprint(dataDir, sessionIdOrBlueprint, maybeBlueprint) {
|
|
1684
|
+
const current = readBlueprint(dataDir)
|
|
1685
|
+
const incoming =
|
|
1686
|
+
maybeBlueprint === undefined ? sessionIdOrBlueprint : maybeBlueprint
|
|
1687
|
+
const next = normalizeBlueprint({
|
|
1688
|
+
...current,
|
|
1689
|
+
...incoming,
|
|
1690
|
+
hidden:
|
|
1691
|
+
incoming?.hidden !== undefined ? incoming.hidden : current.hidden,
|
|
1692
|
+
})
|
|
1693
|
+
if (!blueprintContentEqual(current, next)) {
|
|
1694
|
+
next.revision = current.revision + 1
|
|
1695
|
+
} else {
|
|
1696
|
+
next.revision = current.revision
|
|
1697
|
+
}
|
|
1698
|
+
next.enabled = blueprintHasContent(next)
|
|
1699
|
+
next.sent = true
|
|
1641
1700
|
atomicWrite(
|
|
1642
|
-
|
|
1701
|
+
blueprintFile(dataDir),
|
|
1643
1702
|
`${JSON.stringify(
|
|
1644
1703
|
{
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1704
|
+
hidden: Boolean(next.hidden),
|
|
1705
|
+
revision: next.revision,
|
|
1706
|
+
enabled: next.enabled,
|
|
1707
|
+
sent: true,
|
|
1708
|
+
userCreatedBlocks: namedBlueprintBlocks(next.userCreatedBlocks),
|
|
1709
|
+
userCreatedIslands: namedBlueprintIslands(next.userCreatedIslands),
|
|
1710
|
+
addedFunctions: namedBlueprintSymbols(next.addedFunctions),
|
|
1711
|
+
addedVariables: namedBlueprintSymbols(next.addedVariables),
|
|
1712
|
+
addedImports: namedBlueprintImportAdditions(next.addedImports),
|
|
1713
|
+
notes: namedBlueprintNotes(next.notes),
|
|
1652
1714
|
},
|
|
1653
1715
|
null,
|
|
1654
1716
|
2,
|
|
1655
1717
|
)}\n`,
|
|
1656
1718
|
)
|
|
1719
|
+
return readBlueprint(dataDir)
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
export function setBlueprintHidden(dataDir, hidden) {
|
|
1723
|
+
return writeBlueprint(dataDir, { ...readBlueprint(dataDir), hidden: Boolean(hidden) })
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
export function clearBlueprint(dataDir) {
|
|
1727
|
+
const current = readBlueprint(dataDir)
|
|
1728
|
+
return writeBlueprint(dataDir, {
|
|
1729
|
+
...emptyBlueprint(),
|
|
1730
|
+
hidden: current.hidden,
|
|
1731
|
+
revision: current.revision,
|
|
1732
|
+
})
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1735
|
+
export function cleanupBlueprint(dataDir, knownFileIds = [], knownFolderPaths = []) {
|
|
1736
|
+
const current = readBlueprint(dataDir)
|
|
1737
|
+
const files = new Set(knownFileIds)
|
|
1738
|
+
const folders = new Set(knownFolderPaths)
|
|
1739
|
+
const removedFiles = new Set(
|
|
1740
|
+
current.userCreatedBlocks.filter((block) => files.has(block.id)).map((block) => block.id),
|
|
1741
|
+
)
|
|
1742
|
+
const next = {
|
|
1743
|
+
...current,
|
|
1744
|
+
userCreatedBlocks: current.userCreatedBlocks.filter((block) => !files.has(block.id)),
|
|
1745
|
+
userCreatedIslands: current.userCreatedIslands.filter(
|
|
1746
|
+
(island) => !folders.has(island.path),
|
|
1747
|
+
),
|
|
1748
|
+
addedFunctions: current.addedFunctions.filter((item) => !removedFiles.has(item.file)),
|
|
1749
|
+
addedVariables: current.addedVariables.filter((item) => !removedFiles.has(item.file)),
|
|
1750
|
+
addedImports: current.addedImports.filter((item) => !removedFiles.has(item.file)),
|
|
1751
|
+
notes: current.notes.filter((item) => !removedFiles.has(item.file)),
|
|
1752
|
+
}
|
|
1753
|
+
return writeBlueprint(dataDir, next)
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
export function markBlueprintSeen(dataDir, sessionId, revision) {
|
|
1757
|
+
const manifest = readManifest(dataDir, sessionId)
|
|
1758
|
+
if (!manifest) return null
|
|
1759
|
+
if (manifest.blueprintRevision === revision) return manifest
|
|
1760
|
+
manifest.blueprintRevision = revision
|
|
1761
|
+
writeManifest(dataDir, manifest)
|
|
1762
|
+
return manifest
|
|
1657
1763
|
}
|