@jkwd/inbase 0.1.10 → 0.1.12

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/bin/session.mjs CHANGED
@@ -26,81 +26,217 @@ function usage(name, example) {
26
26
  process.exit(1)
27
27
  }
28
28
 
29
- export async function startSession(args) {
30
- const { store, config } = await loadExplorer()
31
- const sessionId = takeFlagValue(args, '--session')
32
- const feature = takeFlagValue(args, '--feature')
33
- if (!sessionId) usage('start-session', '--session <cursor-chat-id> [--feature "name"]')
29
+ function printAck(kind, detail) {
30
+ console.log(`VISUAL_CODER_ACK ${kind}: ${detail}`)
31
+ }
32
+
33
+ export function createManifestGate(manifestPath, watch = fs.watch) {
34
+ const dir = path.dirname(manifestPath)
35
+ let wake = () => {}
36
+ let watcher = null
37
+
38
+ const dropWatcher = () => {
39
+ try {
40
+ watcher?.close()
41
+ } catch {
42
+ // Already closed after an error, or never opened.
43
+ }
44
+ watcher = null
45
+ }
46
+
47
+ try {
48
+ watcher = watch(dir, () => wake())
49
+ watcher?.on?.('error', () => {
50
+ // EMFILE and sandbox limits must not crash wait-for-approval. Poll instead.
51
+ dropWatcher()
52
+ wake()
53
+ })
54
+ } catch {
55
+ dropWatcher()
56
+ }
57
+
58
+ return {
59
+ wait(ms) {
60
+ return new Promise((resolve) => {
61
+ const timer = setTimeout(resolve, ms)
62
+ wake = () => {
63
+ clearTimeout(timer)
64
+ resolve()
65
+ }
66
+ })
67
+ },
68
+ close() {
69
+ dropWatcher()
70
+ },
71
+ }
72
+ }
73
+
74
+ function signalAck(store, dataDir, sessionId, kind, detail) {
75
+ printAck(kind, detail)
76
+ try {
77
+ store.recordSessionAck(dataDir, sessionId, kind, detail)
78
+ } catch {
79
+ // Session folder may already be gone.
80
+ }
81
+ }
82
+
83
+ function waitingMessage(sessionId, manifest) {
84
+ if (manifest.phase === 'plan_ready') {
85
+ return `Waiting for the user to invoke step ${manifest.currentStep}...`
86
+ }
87
+ if (manifest.phase === 'review' && manifest.diffs?.at(-1)) {
88
+ return manifest.stepByStep === false
89
+ ? `Waiting for the user to accept the proposal after ${manifest.diffs.at(-1).id}...`
90
+ : `Waiting for the user to accept the proposal on ${manifest.diffs.at(-1).id}...`
91
+ }
92
+ return `Waiting for the visual workflow in session ${sessionId}...`
93
+ }
94
+
95
+ function emitStopped(store, dataDir, sessionId) {
96
+ if (store && dataDir && sessionId) {
97
+ signalAck(store, dataDir, sessionId, 'stopped', 'the workflow was stopped')
98
+ } else {
99
+ printAck('stopped', 'the workflow was stopped')
100
+ }
101
+ console.error(
102
+ 'VISUAL_CODER_STOPPED The workflow was stopped. Do not modify project files.',
103
+ )
104
+ process.exit(2)
105
+ }
34
106
 
35
- const manifest = store.startSession(config.dataDir, { sessionId, feature })
36
- if (manifest.phase === 'blueprint_ask' || manifest.phase === 'blueprint') {
107
+ function emitApprovalHandshake(store, dataDir, sessionId, manifest, initialDiff) {
108
+ const current = initialDiff
109
+ ? manifest?.diffs.find((entry) => entry.id === initialDiff.id)
110
+ : null
111
+ if (!manifest || manifest.phase === 'stopped' || current?.status === 'rejected') {
112
+ emitStopped(store, dataDir, sessionId)
113
+ return
114
+ }
115
+ if (manifest.phase === 'finished') {
116
+ signalAck(store, dataDir, sessionId, 'finished', 'the final step was accepted')
37
117
  console.log(
38
- `VISUAL_CODER_BLUEPRINT_WAIT Session ${sessionId} is visible in the visualizer (${manifest.phase}). Wait with inbase wait-for-blueprint before drafting the plan.`,
118
+ `VISUAL_CODER_FINISHED The final step was applied. Feature is done. Run inbase propose-patch --session ${sessionId} --clear, then tell the user it is finished.`,
39
119
  )
40
- } else {
120
+ process.exit(5)
121
+ }
122
+ if (manifest.phase === 'working') {
123
+ const next = manifest.steps.find((step) => step.index === manifest.currentStep)
124
+ const title = next?.title
125
+ signalAck(
126
+ store,
127
+ dataDir,
128
+ sessionId,
129
+ 'execute',
130
+ title
131
+ ? `step ${manifest.currentStep} — ${title}`
132
+ : `step ${manifest.currentStep}`,
133
+ )
134
+ const continuing = (manifest.diffs?.length ?? 0) > 0
41
135
  console.log(
42
- `VISUAL_CODER_PREPARING Session ${sessionId} is visible in the visualizer (${manifest.phase}). Draft the plan next with inbase report-plan.`,
136
+ continuing
137
+ ? `VISUAL_CODER_EXECUTE Step ${manifest.currentStep} is invoked${title ? `: ${title}` : ''}. Continue immediately: edit live files for this step only, then inbase propose-patch --session ${sessionId} with no patch file. Do not explore, re-plan, or run wait-for-blueprint.`
138
+ : `VISUAL_CODER_EXECUTE Step ${manifest.currentStep} is invoked${title ? `: ${title}` : ''}. Re-read this session's blueprint.json before implementing; the user can place files and islands on any step. Edit the live project files for this step only (Write, StrReplace, Delete). Then record the step with inbase propose-patch --session ${sessionId} — no patch file. Inbase diffs those edits against the invoke snapshot and stores the patch. Do not write a unified diff yourself.`,
43
139
  )
140
+ process.exit(0)
141
+ }
142
+ if (manifest.phase === 'replanning') {
143
+ signalAck(
144
+ store,
145
+ dataDir,
146
+ sessionId,
147
+ 'replan',
148
+ `revise the plan from step ${manifest.currentStep}`,
149
+ )
150
+ const instruction = manifest.pendingInstruction
151
+ ? `\nVISUAL_CODER_INSTRUCTION_START\n${manifest.pendingInstruction}\nVISUAL_CODER_INSTRUCTION_END`
152
+ : ''
153
+ console.log(
154
+ `VISUAL_CODER_REPLAN Keep accepted patch files before step ${manifest.currentStep}. Disk is baseline + accepted patches. Do not edit project files until the next EXECUTE. The session blueprint remains leading; if this instruction would differ from it, ask the user before replacing the plan. Report the revised tail with inbase report-plan, then wait for invocation.${instruction}`,
155
+ )
156
+ process.exit(4)
44
157
  }
45
158
  }
46
159
 
160
+ export async function startSession(args) {
161
+ const { store, config } = await loadExplorer()
162
+ const sessionId = takeFlagValue(args, '--session')
163
+ const name = takeFlagValue(args, '--name') || takeFlagValue(args, '--feature')
164
+ const feature = takeFlagValue(args, '--feature')
165
+ if (!sessionId || !name) {
166
+ usage('start-session', '--session <cursor-chat-id> --name "short name"')
167
+ }
168
+
169
+ const manifest = store.startSession(config.dataDir, { sessionId, name, feature })
170
+ console.log(
171
+ `VISUAL_CODER_BLUEPRINT_WAIT Session ${manifest.name || sessionId} is visible in the visualizer (${manifest.phase}). Wait with inbase wait-for-blueprint before drafting the plan. A running visualizer does not skip this handshake.`,
172
+ )
173
+ }
174
+
175
+ export async function attachSession(args) {
176
+ const { store, config } = await loadExplorer()
177
+ const sessionId = takeFlagValue(args, '--session')
178
+ const manifest = store.attachSession(config.dataDir, sessionId)
179
+ console.log(`VISUAL_CODER_SESSION ${manifest.sessionId}`)
180
+ printAck('attached', manifest.name || manifest.sessionId)
181
+ console.log(
182
+ `VISUAL_CODER_ATTACHED Attached to the focused visualizer session ${manifest.name || manifest.sessionId} (${manifest.phase}). Use --session ${manifest.sessionId} for every later command. Run inbase wait-for-blueprint --session ${manifest.sessionId} to read the optional blueprint and instruction; it does not wait.`,
183
+ )
184
+ }
185
+
47
186
  export async function waitForBlueprint(args) {
48
187
  const { store, config } = await loadExplorer()
49
188
  const sessionId = takeFlagValue(args, '--session')
50
- const timeoutMs = Number(takeFlagValue(args, '--timeout') ?? 600000)
51
- if (!sessionId) usage('wait-for-blueprint', '--session <cursor-chat-id> [--timeout ms]')
189
+ if (!sessionId) usage('wait-for-blueprint', '--session <cursor-chat-id>')
52
190
 
53
- const started = Date.now()
54
- const initial = store.readManifest(config.dataDir, sessionId)
55
191
  if (store.isWorkflowStopped(config.dataDir, sessionId)) {
56
- console.error(
57
- 'VISUAL_CODER_STOPPED The workflow was stopped. Do not modify project files.',
58
- )
59
- process.exit(2)
192
+ emitStopped(store, config.dataDir, sessionId)
60
193
  }
194
+ const initial = store.readManifest(config.dataDir, sessionId)
61
195
  if (!initial) {
62
196
  console.error(`No workflow session found for ${sessionId}`)
63
197
  process.exit(1)
64
198
  }
65
199
 
66
- if (initial.phase === 'blueprint_ask' || initial.phase === 'blueprint') {
67
- console.log(
68
- initial.phase === 'blueprint_ask'
69
- ? 'Waiting for the user to choose Setup blueprint: Yes or No...'
70
- : 'Waiting for the user to send the blueprint...',
71
- )
72
- } else {
73
- console.log(`Blueprint handshake already finished for session ${sessionId}.`)
200
+ store.touchSessionConnection(config.dataDir, sessionId)
201
+ store.maybeStartVisualizerHandshake(config.dataDir, sessionId)
202
+ const manifest = store.readManifest(config.dataDir, sessionId)
203
+ if (!manifest || manifest.phase === 'stopped') {
204
+ emitStopped(store, config.dataDir, sessionId)
74
205
  }
75
206
 
76
- while (Date.now() - started < timeoutMs) {
77
- store.touchSessionConnection(config.dataDir, sessionId)
78
- const manifest = store.readManifest(config.dataDir, sessionId)
79
- if (!manifest || manifest.phase === 'stopped') {
80
- console.error(
81
- 'VISUAL_CODER_STOPPED The workflow was stopped. Do not modify project files.',
82
- )
83
- process.exit(2)
84
- }
85
- if (manifest.phase !== 'blueprint_ask' && manifest.phase !== 'blueprint') {
86
- const blueprint = store.readBlueprint(config.dataDir, sessionId)
87
- const blocks = blueprint.userCreatedBlocks ?? []
88
- const islands = blueprint.userCreatedIslands ?? []
89
- console.log(
90
- blueprint.enabled
91
- ? `VISUAL_CODER_BLUEPRINT_READY The user sent ${blocks.length} file(s) and ${islands.length} island(s) for this chat. The blueprint is leading: create those paths and honor addedFunctions, addedVariables, and addedImports even if they are not on disk. Do not omit, rename, relocate, or replace them. Extra new files not in the blueprint are a deviation. If you would differ from the blueprint, ask the user first; do not silently deviate. The user can still place files and islands on later steps; re-read this session's blueprint.json before each step.`
92
- : 'VISUAL_CODER_BLUEPRINT_READY The user skipped the initial blueprint. They can still place files and islands on later steps; re-read this session\'s blueprint.json before each step. Continue without user-placed files until that file is enabled.',
93
- )
94
- console.log('VISUAL_CODER_BLUEPRINT_START')
95
- console.log(JSON.stringify(blueprint, null, 2))
96
- console.log('VISUAL_CODER_BLUEPRINT_END')
97
- process.exit(0)
98
- }
99
- await new Promise((resolve) => setTimeout(resolve, 500))
207
+ const blueprint = store.readBlueprint(config.dataDir, sessionId)
208
+ const blocks = blueprint.userCreatedBlocks ?? []
209
+ const islands = blueprint.userCreatedIslands ?? []
210
+ signalAck(
211
+ store,
212
+ config.dataDir,
213
+ sessionId,
214
+ 'blueprint',
215
+ blueprint.enabled
216
+ ? `${blocks.length} file(s), ${islands.length} island(s)`
217
+ : 'none',
218
+ )
219
+ console.log(
220
+ blueprint.enabled
221
+ ? `VISUAL_CODER_BLUEPRINT_READY The session started with ${blocks.length} file(s) and ${islands.length} island(s). The blueprint is leading: create those paths and honor addedFunctions, addedVariables, and addedImports even if they are not on disk. Do not omit, rename, relocate, or replace them. Extra new files not in the blueprint are a deviation. If you would differ from the blueprint, ask the user first; do not silently deviate. The user can still place files and islands on later steps; re-read this session's blueprint.json before each step.`
222
+ : 'VISUAL_CODER_BLUEPRINT_READY The session started without a blueprint. They can still place files and islands on later steps; re-read this session\'s blueprint.json before each step. Continue without user-placed files until that file is enabled.',
223
+ )
224
+ console.log('VISUAL_CODER_BLUEPRINT_START')
225
+ console.log(JSON.stringify(blueprint, null, 2))
226
+ console.log('VISUAL_CODER_BLUEPRINT_END')
227
+ const instruction =
228
+ typeof manifest.initialInstruction === 'string'
229
+ ? manifest.initialInstruction.trim()
230
+ : ''
231
+ if (instruction) {
232
+ console.log(
233
+ 'Honor the user\'s initial instruction between VISUAL_CODER_INSTRUCTION_START and END together with the blueprint.',
234
+ )
235
+ console.log('VISUAL_CODER_INSTRUCTION_START')
236
+ console.log(instruction)
237
+ console.log('VISUAL_CODER_INSTRUCTION_END')
100
238
  }
101
-
102
- console.error('Timed out waiting for the blueprint handshake. Do not modify files.')
103
- process.exit(3)
239
+ process.exit(0)
104
240
  }
105
241
 
106
242
  export async function reportPlan(args) {
@@ -123,10 +259,11 @@ export async function reportPlan(args) {
123
259
  sessionId,
124
260
  feature,
125
261
  stepTitles: stepsParsed.values,
262
+ targetRoot: config.targetRoot,
126
263
  })
127
264
  console.log(
128
265
  manifest.phase === 'working'
129
- ? `VISUAL_CODER_PLAN_READY Reported ${manifest.steps.length} plan step(s) for session ${sessionId}. Step by step is off, so step ${manifest.currentStep} is already invoked. Implement it, then wait again.`
266
+ ? `VISUAL_CODER_PLAN_READY Reported ${manifest.steps.length} plan step(s) for session ${sessionId}. Step by step is off, so step ${manifest.currentStep} is already invoked. Edit the live files for that step, then inbase propose-patch --session ${sessionId} with no patch file.`
130
267
  : `VISUAL_CODER_PLAN_READY Reported ${manifest.steps.length} plan step(s) for session ${sessionId}. Wait for the user to invoke step ${manifest.currentStep}.`,
131
268
  )
132
269
  }
@@ -141,72 +278,36 @@ export async function waitForApproval(args) {
141
278
  const initial = store.readManifest(config.dataDir, sessionId)
142
279
  const initialDiff = initial?.diffs?.at(-1)
143
280
  if (store.isWorkflowStopped(config.dataDir, sessionId)) {
144
- console.error(
145
- 'VISUAL_CODER_STOPPED The workflow was stopped. Do not modify project files.',
146
- )
147
- process.exit(2)
281
+ emitStopped(store, config.dataDir, sessionId)
148
282
  }
149
283
  if (!initial) {
150
284
  console.error(`No workflow session found for ${sessionId}`)
151
285
  process.exit(1)
152
286
  }
153
287
  store.autoAdvance(config.dataDir, sessionId, config.targetRoot)
154
- const afterAdvance = store.readManifest(config.dataDir, sessionId) ?? initial
155
- console.log(
156
- afterAdvance.phase === 'plan_ready'
157
- ? `Waiting for the user to invoke step ${afterAdvance.currentStep}...`
158
- : afterAdvance.phase === 'review' && afterAdvance.diffs?.at(-1)
159
- ? afterAdvance.stepByStep === false
160
- ? `Waiting for the user to accept the proposal after ${afterAdvance.diffs.at(-1).id}...`
161
- : `Waiting for the user to accept the proposal on ${afterAdvance.diffs.at(-1).id}...`
162
- : `Waiting for the visual workflow in session ${sessionId}...`,
163
- )
164
288
 
165
- while (Date.now() - started < timeoutMs) {
166
- store.touchSessionConnection(config.dataDir, sessionId)
167
- store.autoAdvance(config.dataDir, sessionId, config.targetRoot)
168
- const manifest = store.readManifest(config.dataDir, sessionId)
169
- if (!manifest) {
170
- console.error(
171
- 'VISUAL_CODER_STOPPED The workflow was stopped. Do not modify project files.',
172
- )
173
- process.exit(2)
174
- }
175
- const current = initialDiff
176
- ? manifest.diffs.find((entry) => entry.id === initialDiff.id)
177
- : null
178
-
179
- if (manifest.phase === 'finished') {
180
- console.log(
181
- `VISUAL_CODER_FINISHED The final step was applied. Feature is done. Run inbase propose-patch --session ${sessionId} --clear, then tell the user it is finished.`,
182
- )
183
- process.exit(5)
184
- }
185
- if (manifest.phase === 'working') {
186
- const next = manifest.steps.find((step) => step.index === manifest.currentStep)
187
- console.log(
188
- `VISUAL_CODER_EXECUTE Step ${manifest.currentStep} is invoked${next ? `: ${next.title}` : ''}. Re-read this session's blueprint.json before implementing; the user can place files and islands on any step. Patch files are the source of truth: write only this step's unified diff against the current live files (baseline + accepted patches), publish it with inbase propose-patch --session ${sessionId}, then wait again. Do not Write, StrReplace, or Delete project files.`,
189
- )
190
- process.exit(0)
191
- }
192
- if (manifest.phase === 'replanning') {
193
- const instruction = manifest.pendingInstruction
194
- ? `\nVISUAL_CODER_INSTRUCTION_START\n${manifest.pendingInstruction}\nVISUAL_CODER_INSTRUCTION_END`
195
- : ''
196
- console.log(
197
- `VISUAL_CODER_REPLAN Keep accepted patch files before step ${manifest.currentStep}. Replace the withdrawn step with a new patch against those live files, not against the withdrawn proposal. Do not edit project files. The session blueprint remains leading; if this instruction would differ from it, ask the user before replacing the plan. Report the revised tail with inbase report-plan, then wait for invocation.${instruction}`,
198
- )
199
- process.exit(4)
289
+ const { manifest: manifestPath } = store.sessionPaths(config.dataDir, sessionId)
290
+ const gate = createManifestGate(manifestPath)
291
+ let lastWaiting = null
292
+ try {
293
+ while (Date.now() - started < timeoutMs) {
294
+ store.touchSessionConnection(config.dataDir, sessionId)
295
+ store.autoAdvance(config.dataDir, sessionId, config.targetRoot)
296
+ const manifest = store.readManifest(config.dataDir, sessionId)
297
+ emitApprovalHandshake(store, config.dataDir, sessionId, manifest, initialDiff)
298
+ if (!manifest) continue
299
+ const waiting = waitingMessage(sessionId, manifest)
300
+ if (waiting !== lastWaiting) {
301
+ console.log(waiting)
302
+ lastWaiting = waiting
303
+ }
304
+ await gate.wait(50)
200
305
  }
201
- if (manifest.phase === 'stopped' || current?.status === 'rejected') {
202
- console.error(
203
- 'VISUAL_CODER_STOPPED The workflow was stopped. Do not modify project files.',
204
- )
205
- process.exit(2)
206
- }
207
- await new Promise((resolve) => setTimeout(resolve, 500))
306
+ } finally {
307
+ gate.close()
208
308
  }
209
309
 
310
+ signalAck(store, config.dataDir, sessionId, 'timeout', 'no visualizer signal')
210
311
  console.error('Timed out waiting for visualizer review. Do not modify files.')
211
312
  process.exit(3)
212
313
  }
@@ -229,39 +330,44 @@ export async function proposePatch(args) {
229
330
  process.exit(0)
230
331
  }
231
332
 
232
- if (!sessionId || !patchFile) {
233
- usage('propose-patch', '--session <cursor-chat-id> <file.patch|->')
333
+ if (!sessionId) {
334
+ usage('propose-patch', '--session <cursor-chat-id> [file.patch|-]')
234
335
  }
235
336
 
236
- let patchText = ''
337
+ let patchText
237
338
  if (patchFile && patchFile !== '-') {
238
339
  patchText = fs.readFileSync(path.resolve(cwd, patchFile), 'utf8')
239
340
  } else if (patchFile === '-') {
240
341
  patchText = fs.readFileSync(0, 'utf8')
241
342
  }
242
343
 
243
- if (!patchText.trim()) {
244
- console.error('No unified diff provided. Pass a .patch file or use stdin.')
344
+ if (patchFile && !patchText.trim()) {
345
+ console.error('No unified diff provided. Pass a .patch file, use stdin, or omit the file to record live edits.')
245
346
  process.exit(1)
246
347
  }
247
348
 
248
- const parsed = patchLib.parseUnifiedPatch(patchText)
249
- if (parsed.entries.length === 0) {
250
- console.error('Patch did not contain any file changes.')
349
+ let recorded
350
+ try {
351
+ recorded = store.appendDiff(config.dataDir, config.targetRoot, {
352
+ sessionId,
353
+ ...(patchText !== undefined ? { patchText } : {}),
354
+ })
355
+ } catch (error) {
356
+ console.error(error instanceof Error ? error.message : error)
251
357
  process.exit(1)
252
358
  }
359
+ const { entry, manifest } = recorded
253
360
 
254
- const { entry, manifest } = store.appendDiff(config.dataDir, config.targetRoot, {
255
- sessionId,
256
- patchText,
257
- })
361
+ const parsed = patchLib.parseUnifiedPatch(
362
+ store.readDiff(config.dataDir, sessionId, entry),
363
+ )
258
364
 
259
365
  const last = entry.step >= manifest.steps.length
260
366
  console.log(
261
367
  manifest.phase === 'working'
262
- ? `VISUAL_CODER_STEP_READY Stored patch ${entry.id} for session ${sessionId}, step ${entry.step}/${manifest.steps.length}: ${parsed.files.length} changed, ${parsed.creates.length} added. Applied the live patch files. Do not edit project files. Step by step is off, so the next step is already invoked. Wait again.`
368
+ ? `VISUAL_CODER_STEP_READY Recorded live edits as patch ${entry.id} for session ${sessionId}, step ${entry.step}/${manifest.steps.length}: ${parsed.files.length} changed, ${parsed.creates.length} added. Do not keep editing until the next EXECUTE. Step by step is off, so the next step is already invoked. Wait again.`
263
369
  : last
264
- ? `VISUAL_CODER_STEP_READY Stored patch ${entry.id} for session ${sessionId}, step ${entry.step}/${manifest.steps.length}: ${parsed.files.length} changed, ${parsed.creates.length} added. Applied the live patch files. Do not edit project files. Walk the diffs, then Accept proposal to finish.`
265
- : `VISUAL_CODER_STEP_READY Stored patch ${entry.id} for session ${sessionId}, step ${entry.step}/${manifest.steps.length}: ${parsed.files.length} changed, ${parsed.creates.length} added. Applied the live patch files. Do not edit project files. Wait for Accept proposal or an alternative instruction.`,
370
+ ? `VISUAL_CODER_STEP_READY Recorded live edits as patch ${entry.id} for session ${sessionId}, step ${entry.step}/${manifest.steps.length}: ${parsed.files.length} changed, ${parsed.creates.length} added. Do not keep editing. Walk the diffs, then Accept proposal to finish.`
371
+ : `VISUAL_CODER_STEP_READY Recorded live edits as patch ${entry.id} for session ${sessionId}, step ${entry.step}/${manifest.steps.length}: ${parsed.files.length} changed, ${parsed.creates.length} added. Immediately run wait-for-approval. Do not explore or plan. Accept proposal invokes the next step; when EXECUTE returns, implement that step at once.`,
266
372
  )
267
373
  }
package/package.json CHANGED
@@ -1,7 +1,19 @@
1
1
  {
2
2
  "name": "@jkwd/inbase",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "A first-person 3D map of a codebase, with a visual coding workflow for Cursor.",
5
+ "license": "MIT",
6
+ "author": "Joris Kuijper",
7
+ "keywords": [
8
+ "inbase",
9
+ "codebase",
10
+ "visualization",
11
+ "3d",
12
+ "first-person",
13
+ "cursor",
14
+ "devtools",
15
+ "llm"
16
+ ],
5
17
  "repository": {
6
18
  "type": "git",
7
19
  "url": "https://github.com/jk-wd/inbase"
@@ -10,6 +22,9 @@
10
22
  "bugs": {
11
23
  "url": "https://github.com/jk-wd/inbase/issues"
12
24
  },
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
13
28
  "type": "module",
14
29
  "bin": {
15
30
  "inbase": "bin/inbase.mjs"
@@ -28,6 +43,8 @@
28
43
  "apps/explorer/src/*.css",
29
44
  "apps/explorer/src/scene",
30
45
  "apps/explorer/src/ui",
46
+ "apps/explorer/scripts/branch-changes.d.ts",
47
+ "apps/explorer/scripts/branch-changes.mjs",
31
48
  "apps/explorer/scripts/js-source.mjs",
32
49
  "apps/explorer/scripts/open-editor.d.ts",
33
50
  "apps/explorer/scripts/open-editor.mjs",
@@ -37,7 +54,8 @@
37
54
  "apps/explorer/scripts/session-store.d.ts",
38
55
  "apps/explorer/scripts/session-store.mjs",
39
56
  "apps/explorer/scripts/target-config.d.ts",
40
- "apps/explorer/scripts/target-config.mjs"
57
+ "apps/explorer/scripts/target-config.mjs",
58
+ "apps/explorer/scripts/tree-diff.mjs"
41
59
  ],
42
60
  "workspaces": [
43
61
  "apps/*"
@@ -0,0 +1,17 @@
1
+ ---
2
+ description: Attach this chat to the focused Inbase visualizer session
3
+ ---
4
+
5
+ The user invoked `/inbase`. This is how a chat joins the visualizer session that **Setup LLM session** already created.
6
+
7
+ Do **not** ask for a session id. Do **not** run `inbase start-session`. Do **not** print the "direct chat interaction not allowed" message.
8
+
9
+ 1. Attach to the focused visualizer session:
10
+
11
+ ```bash
12
+ npx inbase attach
13
+ ```
14
+
15
+ 2. Read `VISUAL_CODER_SESSION` from the output. That id is the session to use for every later `inbase` command.
16
+
17
+ 3. Continue the Inbase visual edits skill from `wait-for-blueprint` onward with that `--session` id. `/inbase` already started the session. `wait-for-blueprint` only reads the optional blueprint and instruction; it does not wait.
@@ -0,0 +1,9 @@
1
+ ---
2
+ description: Bypass Inbase and do the request directly in this chat
3
+ ---
4
+
5
+ The user invoked `/skipinbase`. Do **not** start or attach an Inbase visual session. Do **not** print the "direct chat interaction not allowed" message.
6
+
7
+ Fulfill this request directly, without the Inbase plan/patch loop:
8
+
9
+ $ARGUMENTS