@jkwd/inbase 0.1.21 → 0.1.23
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-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 +1073 -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 +874 -222
- 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 +1 -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 -795
- 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 +6 -4
- 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 -1069
|
@@ -1,11 +1,16 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
1
2
|
import path from 'node:path'
|
|
2
3
|
import { fileURLToPath } from 'node:url'
|
|
3
4
|
|
|
4
5
|
const here = path.dirname(fileURLToPath(import.meta.url))
|
|
5
6
|
const explorerRoot = path.resolve(here, '..')
|
|
6
7
|
const repoRoot = path.resolve(explorerRoot, '../..')
|
|
8
|
+
const appsDir = path.resolve(explorerRoot, '..')
|
|
7
9
|
const defaultTargetRoot = path.resolve(explorerRoot, '../example-target')
|
|
8
10
|
const defaultDataDir = path.resolve(explorerRoot, 'src/data')
|
|
11
|
+
const DEV_TARGET_FILE = 'dev-target.json'
|
|
12
|
+
const EXPLORER_APP_NAME = 'explorer'
|
|
13
|
+
const REPO_TARGET_ID = 'repo'
|
|
9
14
|
|
|
10
15
|
export function resolvePathValue(value, fallback) {
|
|
11
16
|
const raw = value?.trim()
|
|
@@ -21,9 +26,122 @@ export function resolveDataDir(value = process.env.INBASE_DATA_DIR) {
|
|
|
21
26
|
return resolvePathValue(value, defaultDataDir)
|
|
22
27
|
}
|
|
23
28
|
|
|
24
|
-
export const targetRoot = resolveTargetRoot()
|
|
25
29
|
export const dataDir = resolveDataDir()
|
|
26
|
-
|
|
30
|
+
|
|
31
|
+
function samePath(left, right) {
|
|
32
|
+
return path.resolve(left) === path.resolve(right)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function labelFromFolderName(name) {
|
|
36
|
+
if (name === 'example-target') return 'Example target'
|
|
37
|
+
return name
|
|
38
|
+
.split(/[-_]/)
|
|
39
|
+
.filter(Boolean)
|
|
40
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
41
|
+
.join(' ')
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function persistedTargetFile(dir = dataDir) {
|
|
45
|
+
return path.join(dir, DEV_TARGET_FILE)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function readPersistedTargetId(dir = dataDir) {
|
|
49
|
+
try {
|
|
50
|
+
const parsed = JSON.parse(fs.readFileSync(persistedTargetFile(dir), 'utf8'))
|
|
51
|
+
return typeof parsed?.id === 'string' && parsed.id.trim() ? parsed.id.trim() : null
|
|
52
|
+
} catch {
|
|
53
|
+
return null
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function writePersistedTargetId(id, dir = dataDir) {
|
|
58
|
+
fs.mkdirSync(dir, { recursive: true })
|
|
59
|
+
fs.writeFileSync(persistedTargetFile(dir), `${JSON.stringify({ id }, null, 2)}\n`)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* True when this checkout still has the bundled demo app and the explorer is
|
|
64
|
+
* using its own src/data dir — i.e. `npm run dev`, not `inbase run`.
|
|
65
|
+
*/
|
|
66
|
+
export function isWorkspaceDevSwitcherEnabled({
|
|
67
|
+
exampleTarget = defaultTargetRoot,
|
|
68
|
+
resolvedDataDir = dataDir,
|
|
69
|
+
explorerDataDir = defaultDataDir,
|
|
70
|
+
} = {}) {
|
|
71
|
+
return fs.existsSync(exampleTarget) && samePath(resolvedDataDir, explorerDataDir)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function listWorkspaceTargets({
|
|
75
|
+
appsRoot = appsDir,
|
|
76
|
+
repositoryRoot = repoRoot,
|
|
77
|
+
} = {}) {
|
|
78
|
+
const apps = []
|
|
79
|
+
try {
|
|
80
|
+
for (const entry of fs.readdirSync(appsRoot, { withFileTypes: true })) {
|
|
81
|
+
if (!entry.isDirectory()) continue
|
|
82
|
+
if (entry.name === EXPLORER_APP_NAME || entry.name.startsWith('.')) continue
|
|
83
|
+
apps.push({
|
|
84
|
+
id: entry.name,
|
|
85
|
+
label: labelFromFolderName(entry.name),
|
|
86
|
+
root: path.resolve(appsRoot, entry.name),
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
} catch {
|
|
90
|
+
// No apps directory in published layouts.
|
|
91
|
+
}
|
|
92
|
+
apps.sort((left, right) => {
|
|
93
|
+
if (left.id === 'example-target') return -1
|
|
94
|
+
if (right.id === 'example-target') return 1
|
|
95
|
+
return left.id.localeCompare(right.id)
|
|
96
|
+
})
|
|
97
|
+
return [
|
|
98
|
+
...apps,
|
|
99
|
+
{
|
|
100
|
+
id: REPO_TARGET_ID,
|
|
101
|
+
label: 'Complete repo',
|
|
102
|
+
root: path.resolve(repositoryRoot),
|
|
103
|
+
},
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function matchWorkspaceTargetId(root, targets = listWorkspaceTargets()) {
|
|
108
|
+
const resolved = path.resolve(root)
|
|
109
|
+
return targets.find((target) => samePath(target.root, resolved))?.id ?? null
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function resolveInitialTargetRoot({
|
|
113
|
+
envTarget = process.env.VISUAL_CODER_TARGET,
|
|
114
|
+
persistedId = null,
|
|
115
|
+
switcherEnabled = false,
|
|
116
|
+
targets = [],
|
|
117
|
+
fallback = defaultTargetRoot,
|
|
118
|
+
} = {}) {
|
|
119
|
+
const fromEnv = envTarget?.trim()
|
|
120
|
+
if (fromEnv) return resolveTargetRoot(fromEnv)
|
|
121
|
+
if (switcherEnabled && persistedId) {
|
|
122
|
+
const match = targets.find((target) => target.id === persistedId)
|
|
123
|
+
if (match) return match.root
|
|
124
|
+
}
|
|
125
|
+
return fallback
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function applyTargetRoot(root) {
|
|
129
|
+
targetRoot = path.resolve(root)
|
|
130
|
+
targetName = path.basename(targetRoot)
|
|
131
|
+
targetPathPrefix = resolveTargetPathPrefix(targetRoot)
|
|
132
|
+
process.env.VISUAL_CODER_TARGET = targetRoot
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const switcherEnabledAtBoot = isWorkspaceDevSwitcherEnabled()
|
|
136
|
+
const bootTargets = switcherEnabledAtBoot ? listWorkspaceTargets() : []
|
|
137
|
+
|
|
138
|
+
export let targetRoot = resolveInitialTargetRoot({
|
|
139
|
+
persistedId: switcherEnabledAtBoot ? readPersistedTargetId() : null,
|
|
140
|
+
switcherEnabled: switcherEnabledAtBoot,
|
|
141
|
+
targets: bootTargets,
|
|
142
|
+
})
|
|
143
|
+
export let targetName = path.basename(targetRoot)
|
|
144
|
+
export let targetPathPrefix = null
|
|
27
145
|
|
|
28
146
|
/**
|
|
29
147
|
* Agents write diffs against repo-relative paths, so a target that lives inside
|
|
@@ -39,4 +157,30 @@ export function resolveTargetPathPrefix(root = targetRoot) {
|
|
|
39
157
|
return `${relative.split(path.sep).join('/')}/`
|
|
40
158
|
}
|
|
41
159
|
|
|
42
|
-
|
|
160
|
+
targetPathPrefix = resolveTargetPathPrefix(targetRoot)
|
|
161
|
+
|
|
162
|
+
export function currentWorkspaceTargetId() {
|
|
163
|
+
return matchWorkspaceTargetId(targetRoot)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function workspaceDevTargetsState() {
|
|
167
|
+
if (!isWorkspaceDevSwitcherEnabled()) {
|
|
168
|
+
return { enabled: false, currentId: null, targets: [] }
|
|
169
|
+
}
|
|
170
|
+
const targets = listWorkspaceTargets()
|
|
171
|
+
const currentId = matchWorkspaceTargetId(targetRoot, targets) ?? 'custom'
|
|
172
|
+
const publicTargets = targets.map(({ id, label }) => ({ id, label }))
|
|
173
|
+
if (currentId === 'custom') {
|
|
174
|
+
publicTargets.push({ id: 'custom', label: targetName })
|
|
175
|
+
}
|
|
176
|
+
return { enabled: true, currentId, targets: publicTargets }
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function setWorkspaceTarget(id) {
|
|
180
|
+
const targets = listWorkspaceTargets()
|
|
181
|
+
const match = targets.find((target) => target.id === id)
|
|
182
|
+
if (!match) throw new Error(`Unknown workspace target: ${id}`)
|
|
183
|
+
applyTargetRoot(match.root)
|
|
184
|
+
writePersistedTargetId(match.id)
|
|
185
|
+
return match
|
|
186
|
+
}
|