@soederpop/luca 0.0.23 → 0.0.26
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/AGENTS.md +1 -1
- package/CLAUDE.md +6 -1
- package/assistants/codingAssistant/hooks.ts +0 -1
- package/assistants/lucaExpert/CORE.md +37 -0
- package/assistants/lucaExpert/hooks.ts +9 -0
- package/assistants/lucaExpert/tools.ts +177 -0
- package/commands/build-bootstrap.ts +41 -1
- package/docs/TABLE-OF-CONTENTS.md +0 -1
- package/docs/apis/clients/rest.md +5 -5
- package/docs/apis/features/agi/assistant.md +1 -1
- package/docs/apis/features/agi/conversation-history.md +6 -7
- package/docs/apis/features/agi/conversation.md +1 -1
- package/docs/apis/features/agi/semantic-search.md +1 -1
- package/docs/bootstrap/CLAUDE.md +1 -1
- package/docs/bootstrap/SKILL.md +7 -3
- package/docs/bootstrap/templates/luca-cli.ts +5 -0
- package/docs/mcp/readme.md +1 -1
- package/docs/tutorials/00-bootstrap.md +18 -0
- package/package.json +2 -2
- package/scripts/stamp-build.sh +12 -0
- package/scripts/test-docs-reader.ts +10 -0
- package/src/agi/container.server.ts +8 -5
- package/src/agi/features/assistant.ts +210 -55
- package/src/agi/features/assistants-manager.ts +138 -66
- package/src/agi/features/conversation.ts +46 -14
- package/src/agi/features/docs-reader.ts +166 -0
- package/src/agi/features/openapi.ts +1 -1
- package/src/agi/features/skills-library.ts +257 -313
- package/src/bootstrap/generated.ts +8163 -6
- package/src/cli/build-info.ts +4 -0
- package/src/cli/cli.ts +2 -1
- package/src/command.ts +75 -0
- package/src/commands/bootstrap.ts +16 -1
- package/src/commands/describe.ts +29 -1089
- package/src/commands/eval.ts +6 -1
- package/src/commands/sandbox-mcp.ts +17 -7
- package/src/container-describer.ts +1098 -0
- package/src/container.ts +11 -0
- package/src/helper.ts +56 -2
- package/src/introspection/generated.agi.ts +1684 -799
- package/src/introspection/generated.node.ts +964 -572
- package/src/introspection/generated.web.ts +9 -1
- package/src/node/container.ts +1 -1
- package/src/node/features/content-db.ts +268 -13
- package/src/node/features/fs.ts +18 -0
- package/src/node/features/git.ts +90 -0
- package/src/node/features/grep.ts +1 -1
- package/src/node/features/proc.ts +1 -0
- package/src/node/features/tts.ts +1 -1
- package/src/node/features/vm.ts +48 -0
- package/src/scaffolds/generated.ts +2 -2
- package/src/server.ts +40 -0
- package/src/servers/express.ts +2 -0
- package/src/servers/mcp.ts +1 -0
- package/src/servers/socket.ts +2 -0
- package/assistants/architect/CORE.md +0 -3
- package/assistants/architect/hooks.ts +0 -3
- package/assistants/architect/tools.ts +0 -10
- package/docs/apis/features/agi/skills-library.md +0 -234
- package/docs/reports/assistant-bugs.md +0 -38
- package/docs/reports/attach-pattern-usage.md +0 -18
- package/docs/reports/code-audit-results.md +0 -391
- package/docs/reports/console-hmr-design.md +0 -170
- package/docs/reports/helper-semantic-search.md +0 -72
- package/docs/reports/introspection-audit-tasks.md +0 -378
- package/docs/reports/luca-mcp-improvements.md +0 -128
- package/test-integration/skills-library.test.ts +0 -157
|
@@ -1,391 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Code Audit - Container Abstraction Violations
|
|
3
|
-
status: active
|
|
4
|
-
type: report
|
|
5
|
-
createdAt: 2026-02-26
|
|
6
|
-
updatedAt: 2026-02-26
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Code Audit: Container Abstraction Violations
|
|
10
|
-
|
|
11
|
-
Audit of `src/**/features/**`, `src/**/clients/**`, `src/clients/**`, `src/servers/**`, and `src/commands/**` for violations of the container abstraction pattern.
|
|
12
|
-
|
|
13
|
-
**Excluded from audit**: `fs.ts`, `proc.ts`, `git.ts`, `os.ts` — these are core wrappers that intentionally import Node builtins. `file-manager.ts` is allowed to use `path` directly.
|
|
14
|
-
|
|
15
|
-
## Severity Legend
|
|
16
|
-
|
|
17
|
-
- **HIGH**: Breaks Node.js compatibility, or completely bypasses container when equivalent exists
|
|
18
|
-
- **MEDIUM**: Uses builtins/process.env when container provides an alternative
|
|
19
|
-
- **LOW**: Minor style issue, or acceptable edge case
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
## Summary
|
|
24
|
-
|
|
25
|
-
| Category | Files Audited | Files with Violations | HIGH | MEDIUM | LOW |
|
|
26
|
-
|----------|--------------|----------------------|------|--------|-----|
|
|
27
|
-
| Node Features | 14 | 11 | 19 | 14 | 6 |
|
|
28
|
-
| AGI Features | 10 | 3 | 12 | 4 | 0 |
|
|
29
|
-
| Clients | 7 | 3 | 3 | 2 | 0 |
|
|
30
|
-
| Servers | 3 | 2 | 1 | 1 | 0 |
|
|
31
|
-
| Commands | 11 | 5 | 3 | 5 | 2 |
|
|
32
|
-
| **Total** | **45** | **24** | **38** | **26** | **8** |
|
|
33
|
-
|
|
34
|
-
### Top Offenders (by violation count)
|
|
35
|
-
|
|
36
|
-
1. **`skills-library.ts`** — 7 HIGH (imports `path`, `os`, `fs/promises` and uses throughout)
|
|
37
|
-
2. **`claude-code.ts`** — 8 violations (3x `Bun.spawn`, 1x `Bun.write`, 2x dynamic `fs/promises`, 2x `process.env`)
|
|
38
|
-
3. **`launcher-app-command-listener.ts`** — 7 HIGH (fs, path, os at module top-level)
|
|
39
|
-
4. **`window-manager.ts`** — 7 HIGH (same pattern as launcher-app)
|
|
40
|
-
5. **`python.ts`** — 9+ uses of `existsSync`/`join` from builtins
|
|
41
|
-
6. **`package-finder.ts`** — 5 violations (partially migrated, inconsistent)
|
|
42
|
-
7. **`comfyui/index.ts`** — 5 violations in one method (dynamic imports + `Bun.write`)
|
|
43
|
-
8. **`openai-codex.ts`** — 4 violations (3x `Bun.spawn`, 2x `process.env`)
|
|
44
|
-
|
|
45
|
-
### Bug Found
|
|
46
|
-
|
|
47
|
-
**`repl.ts` lines 92, 192** — Uses `fs.readFileSync` and `fs.appendFileSync` but **never imports `fs`**. This will throw `ReferenceError` at runtime when history persistence is used.
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
## Detailed Findings
|
|
52
|
-
|
|
53
|
-
### Node Features (`src/node/features/`)
|
|
54
|
-
|
|
55
|
-
#### `package-finder.ts`
|
|
56
|
-
|
|
57
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
58
|
-
|---------|-----------|-----------|----------|
|
|
59
|
-
| 4 | `import { readdir, readFile } from 'fs/promises'` | `this.container.fs` | HIGH |
|
|
60
|
-
| 5 | `import { resolve, join, basename } from 'path'` | `this.container.paths` | MEDIUM |
|
|
61
|
-
| 242 | `readFile(path)` direct usage | `this.container.fs.readFileAsync()` | HIGH |
|
|
62
|
-
| 471, 477 | `readdir(...)` direct usage | `this.container.fs.readdirAsync()` | HIGH |
|
|
63
|
-
| 475, 477 | `join(...)` direct usage | `this.container.paths.join()` | MEDIUM |
|
|
64
|
-
|
|
65
|
-
Note: Line 523 correctly uses `this.container.fs.findUpAsync` — file is partially migrated but inconsistent.
|
|
66
|
-
|
|
67
|
-
#### `python.ts`
|
|
68
|
-
|
|
69
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
70
|
-
|---------|-----------|-----------|----------|
|
|
71
|
-
| 4 | `import { existsSync } from 'fs'` | `this.container.fs.exists()` | HIGH |
|
|
72
|
-
| 5 | `import { join, resolve } from 'path'` | `this.container.paths` | MEDIUM |
|
|
73
|
-
| 84 | `resolve(this.options.dir)` | `this.container.paths.resolve()` | MEDIUM |
|
|
74
|
-
| 93, 145, 158, 171-172, 177, 245-246, 256, 259 | 9+ calls to `existsSync()` | `this.container.fs.exists()` | HIGH |
|
|
75
|
-
| 145, 158, 171+ | `join(...)` throughout `detectEnvironment()` | `this.container.paths.join()` | MEDIUM |
|
|
76
|
-
|
|
77
|
-
Note: `execute()` method (line 313+) correctly uses container features — only `detectEnvironment()` and `enable()` are violating.
|
|
78
|
-
|
|
79
|
-
#### `launcher-app-command-listener.ts`
|
|
80
|
-
|
|
81
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
82
|
-
|---------|-----------|-----------|----------|
|
|
83
|
-
| 5 | `import { homedir } from 'os'` | `this.container.feature('os').homedir` | MEDIUM |
|
|
84
|
-
| 6 | `import { join, dirname } from 'path'` | `this.container.paths` | MEDIUM |
|
|
85
|
-
| 7 | `import { existsSync, unlinkSync, mkdirSync } from 'fs'` | `this.container.fs` | HIGH |
|
|
86
|
-
| 9-15 | `homedir()`, `join(...)` at module top-level (before container exists) | Must defer to runtime (`enable()` or getter) | HIGH |
|
|
87
|
-
| 250-253 | `dirname()`, `existsSync()`, `mkdirSync()` | `this.container.paths`/`this.container.fs` | HIGH |
|
|
88
|
-
| 260-263 | `existsSync()`, `unlinkSync()` | `this.container.fs` | HIGH |
|
|
89
|
-
| 307-308 | `existsSync()`, `unlinkSync()` | `this.container.fs` | HIGH |
|
|
90
|
-
|
|
91
|
-
#### `window-manager.ts`
|
|
92
|
-
|
|
93
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
94
|
-
|---------|-----------|-----------|----------|
|
|
95
|
-
| 5 | `import { homedir } from 'os'` | `this.container.feature('os').homedir` | MEDIUM |
|
|
96
|
-
| 6 | `import { join, dirname } from 'path'` | `this.container.paths` | MEDIUM |
|
|
97
|
-
| 8 | `import { existsSync, unlinkSync, mkdirSync } from 'fs'` | `this.container.fs` | HIGH |
|
|
98
|
-
| 10-16 | `homedir()`, `join(...)` at module top-level | Must defer to runtime | HIGH |
|
|
99
|
-
| 354-372 | `dirname()`, `existsSync()`, `mkdirSync()`, `unlinkSync()` | Container equivalents | HIGH |
|
|
100
|
-
| 420-421 | `existsSync()`, `unlinkSync()` | `this.container.fs` | HIGH |
|
|
101
|
-
|
|
102
|
-
#### `helpers.ts`
|
|
103
|
-
|
|
104
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
105
|
-
|---------|-----------|-----------|----------|
|
|
106
|
-
| 11 | `import { resolve, parse } from 'path'` | `this.container.paths` | MEDIUM |
|
|
107
|
-
| 134, 258 | `resolve(this.rootDir, ...)` | `this.container.paths.resolve()` | MEDIUM |
|
|
108
|
-
| 324 | `const { Glob } = globalThis.Bun \|\| (await import('bun'))` — unguarded `Bun.Glob` | Guard with `this.container.isBun` or use container glob | HIGH |
|
|
109
|
-
|
|
110
|
-
#### `tmux.ts`
|
|
111
|
-
|
|
112
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
113
|
-
|---------|-----------|-----------|----------|
|
|
114
|
-
| 479, 531 | `process.env.TMUX` | Container environment handling | MEDIUM |
|
|
115
|
-
| 505-509 | `process.platform === 'darwin'` / `'linux'` | `this.container.feature('os').platform` | LOW |
|
|
116
|
-
| 543-544 | `process.argv` direct access | Container equivalent | LOW |
|
|
117
|
-
| 546 | `import('child_process')` then `execSync(...)` | `this.container.feature('proc')` | HIGH |
|
|
118
|
-
|
|
119
|
-
#### `process-manager.ts`
|
|
120
|
-
|
|
121
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
122
|
-
|---------|-----------|-----------|----------|
|
|
123
|
-
| 104 | `ReturnType<typeof Bun.spawn>` — type depends on Bun | Runtime-agnostic type or guard | HIGH |
|
|
124
|
-
| 164 | `Bun.spawn(...)` — unguarded | `this.container.feature('proc')` or guard with `isBun` | HIGH |
|
|
125
|
-
| 166 | `{ ...process.env, ...spawnOptions.env }` | Container environment | MEDIUM |
|
|
126
|
-
| 508-530 | `process.on('exit')`, `process.on('SIGINT')`, etc. | Container lifecycle hooks | MEDIUM |
|
|
127
|
-
|
|
128
|
-
#### `google-auth.ts`
|
|
129
|
-
|
|
130
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
131
|
-
|---------|-----------|-----------|----------|
|
|
132
|
-
| 108, 115, 123, 147, 486 | `process.env.GOOGLE_*` (5 occurrences) | Container env handling (already declares `static envVars`) | MEDIUM |
|
|
133
|
-
| 247 | `Bun.serve({...})` — unguarded | Guard with `isBun` or use container server | HIGH |
|
|
134
|
-
|
|
135
|
-
#### `repl.ts`
|
|
136
|
-
|
|
137
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
138
|
-
|---------|-----------|-----------|----------|
|
|
139
|
-
| 92 | `fs.readFileSync(...)` — **`fs` is NOT imported** | `this.container.fs.readFileSync()` | **HIGH (BUG)** |
|
|
140
|
-
| 172 | `Bun.inspect(result, ...)` — unguarded | Guard with `this.container.isBun` | MEDIUM |
|
|
141
|
-
| 192 | `fs.appendFileSync(...)` — **`fs` is NOT imported** | `this.container.fs` | **HIGH (BUG)** |
|
|
142
|
-
|
|
143
|
-
#### `tts.ts`
|
|
144
|
-
|
|
145
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
146
|
-
|---------|-----------|-----------|----------|
|
|
147
|
-
| 67 | `process.env.RUNPOD_API_KEY` | Container env handling | MEDIUM |
|
|
148
|
-
|
|
149
|
-
Otherwise clean — correctly uses `this.container.paths`, `this.container.fs`, `this.container.feature('os')`.
|
|
150
|
-
|
|
151
|
-
#### `downloader.ts`
|
|
152
|
-
|
|
153
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
154
|
-
|---------|-----------|-----------|----------|
|
|
155
|
-
| 3 | `import fetch from 'cross-fetch'` | Global `fetch` (available in Bun and Node 18+) or container REST client | HIGH |
|
|
156
|
-
|
|
157
|
-
Otherwise clean — correctly uses `this.container.fs.writeFileAsync` and `this.container.paths.resolve`.
|
|
158
|
-
|
|
159
|
-
#### `runpod.ts`
|
|
160
|
-
|
|
161
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
162
|
-
|---------|-----------|-----------|----------|
|
|
163
|
-
| 4 | `import axios from 'axios'` | `this.container.client('rest')` or global `fetch` | HIGH |
|
|
164
|
-
| 46 | `process.env.RUNPOD_API_KEY` | Container env handling | MEDIUM |
|
|
165
|
-
|
|
166
|
-
#### `telegram.ts`
|
|
167
|
-
|
|
168
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
169
|
-
|---------|-----------|-----------|----------|
|
|
170
|
-
| 97 | `process.env.TELEGRAM_BOT_TOKEN` | Container env handling | MEDIUM |
|
|
171
|
-
|
|
172
|
-
Otherwise clean — properly uses `container.server('express')` and `container.feature('ui')`.
|
|
173
|
-
|
|
174
|
-
---
|
|
175
|
-
|
|
176
|
-
### AGI Features (`src/agi/features/`)
|
|
177
|
-
|
|
178
|
-
#### `skills-library.ts`
|
|
179
|
-
|
|
180
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
181
|
-
|---------|-----------|-----------|----------|
|
|
182
|
-
| 2 | `import path from 'path'` | `this.container.paths` | HIGH |
|
|
183
|
-
| 3 | `import os from 'os'` | `this.container.paths.homedir` or container os feature | HIGH |
|
|
184
|
-
| 4 | `import fs from 'fs/promises'` | `this.container.fs` | HIGH |
|
|
185
|
-
| 131 | `path.resolve(os.homedir(), '.luca', 'skills')` | `this.container.paths.resolve(...)` | HIGH |
|
|
186
|
-
| 250 | `await fs.mkdir(..., { recursive: true })` | `this.container.fs.mkdirp()` or `ensureFolder()` | HIGH |
|
|
187
|
-
| 330-331 | `path.resolve(...)` in `remove()` | `this.container.paths.resolve()` | HIGH |
|
|
188
|
-
| 335 | `await fs.rm(skillDir, { recursive: true })` | `this.container.fs.rm()` | HIGH |
|
|
189
|
-
|
|
190
|
-
Worst AGI offender — three Node builtin imports at top level used throughout.
|
|
191
|
-
|
|
192
|
-
#### `claude-code.ts`
|
|
193
|
-
|
|
194
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
195
|
-
|---------|-----------|-----------|----------|
|
|
196
|
-
| 7 | `import type { Subprocess } from 'bun'` | Runtime-agnostic type | MEDIUM |
|
|
197
|
-
| 275 | `Bun.spawn([this.claudePath, '--version'], ...)` | Container `proc` feature | HIGH |
|
|
198
|
-
| 334 | `const { appendFile } = await import('node:fs/promises')` | `this.container.fs` | HIGH |
|
|
199
|
-
| 382 | `process.env.TMPDIR` | Container temp dir handling | MEDIUM |
|
|
200
|
-
| 384 | `await Bun.write(tmpPath, ...)` | Container fs write | HIGH |
|
|
201
|
-
| 619-624 | `Bun.spawn(...)` + `{ ...process.env }` | Container `proc` + env | HIGH |
|
|
202
|
-
| 750-755 | `Bun.spawn(...)` + `{ ...process.env }` | Same | HIGH |
|
|
203
|
-
| 920 | `const { unlink } = await import('node:fs/promises')` | `this.container.fs` | HIGH |
|
|
204
|
-
|
|
205
|
-
Completely Bun-locked. Three `Bun.spawn` call sites, one `Bun.write`, two dynamic `fs/promises` imports.
|
|
206
|
-
|
|
207
|
-
#### `openai-codex.ts`
|
|
208
|
-
|
|
209
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
210
|
-
|---------|-----------|-----------|----------|
|
|
211
|
-
| 7 | `import type { Subprocess } from 'bun'` | Runtime-agnostic type | MEDIUM |
|
|
212
|
-
| 174 | `Bun.spawn([this.codexPath, '--version'], ...)` | Container `proc` feature | HIGH |
|
|
213
|
-
| 375-379 | `Bun.spawn(...)` + `{ ...process.env }` | Container `proc` + env | HIGH |
|
|
214
|
-
| 502-507 | `Bun.spawn(...)` + `{ ...process.env }` | Same | HIGH |
|
|
215
|
-
|
|
216
|
-
Same pattern as `claude-code.ts`.
|
|
217
|
-
|
|
218
|
-
#### Clean AGI Files
|
|
219
|
-
|
|
220
|
-
- `conversation.ts` — Clean
|
|
221
|
-
- `conversation-history.ts` — Clean (uses `container.feature('diskCache')`)
|
|
222
|
-
- `assistant.ts` — Exemplary (uses `container.fs`, `container.paths`, `container.feature('vm')`)
|
|
223
|
-
- `assistants-manager.ts` — Clean (uses `container.paths`, `container.fs`)
|
|
224
|
-
- `docs-reader.ts` — Clean
|
|
225
|
-
- `openapi.ts` — Clean (uses global `fetch`)
|
|
226
|
-
- `heartbeat.ts` — Clean (uses `container.feature('proc')`, `container.feature('vm')`, etc.)
|
|
227
|
-
|
|
228
|
-
---
|
|
229
|
-
|
|
230
|
-
### Clients (`src/clients/`, `src/web/clients/`)
|
|
231
|
-
|
|
232
|
-
#### `comfyui/index.ts`
|
|
233
|
-
|
|
234
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
235
|
-
|---------|-----------|-----------|----------|
|
|
236
|
-
| 531 | `const { mkdir } = await import("fs/promises")` | `this.container.fs.ensureFolder()` | HIGH |
|
|
237
|
-
| 532 | `const { join } = await import("path")` | `this.container.paths.join()` | MEDIUM |
|
|
238
|
-
| 533 | `await mkdir(options.outputDir, { recursive: true })` | `this.container.fs.ensureFolder()` | HIGH |
|
|
239
|
-
| 537 | `const localPath = join(...)` | `this.container.paths.join()` | MEDIUM |
|
|
240
|
-
| 538 | `await Bun.write(localPath, buf)` — unguarded | `this.container.fs.writeFileAsync()` | HIGH |
|
|
241
|
-
|
|
242
|
-
All 5 violations are in the `runWorkflow` method (lines 530-541).
|
|
243
|
-
|
|
244
|
-
#### `openai/index.ts`
|
|
245
|
-
|
|
246
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
247
|
-
|---------|-----------|-----------|----------|
|
|
248
|
-
| 76 | `process.env.OPENAI_API_KEY` | Container env (already declares `static envVars`) | MEDIUM |
|
|
249
|
-
|
|
250
|
-
#### `elevenlabs/index.ts`
|
|
251
|
-
|
|
252
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
253
|
-
|---------|-----------|-----------|----------|
|
|
254
|
-
| 100 | `process.env.ELEVENLABS_API_KEY` | Container env (already declares `static envVars`) | MEDIUM |
|
|
255
|
-
|
|
256
|
-
#### Clean Client Files
|
|
257
|
-
|
|
258
|
-
- `civitai/index.ts` — Exemplary (uses `container.fs`, `container.paths`, `container.feature("downloader")`)
|
|
259
|
-
- `supabase/index.ts` — Clean
|
|
260
|
-
- `client-template.ts` — Clean
|
|
261
|
-
- `web/clients/socket.ts` — Clean
|
|
262
|
-
|
|
263
|
-
---
|
|
264
|
-
|
|
265
|
-
### Servers (`src/servers/`)
|
|
266
|
-
|
|
267
|
-
#### `express.ts`
|
|
268
|
-
|
|
269
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
270
|
-
|---------|-----------|-----------|----------|
|
|
271
|
-
| 123 | `new Bun.Glob('**/*.ts')` — unguarded | Container glob/fs.walk or guard with `isBun` | HIGH |
|
|
272
|
-
|
|
273
|
-
The entire `useEndpoints` method (lines 123-146) depends on `Bun.Glob`.
|
|
274
|
-
|
|
275
|
-
#### `mcp.ts`
|
|
276
|
-
|
|
277
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
278
|
-
|---------|-----------|-----------|----------|
|
|
279
|
-
| 440 | `const { randomUUID } = await import('node:crypto')` | `crypto.randomUUID()` (global Web Crypto) or `this.container.utils.uuid()` | MEDIUM |
|
|
280
|
-
|
|
281
|
-
#### Clean Server Files
|
|
282
|
-
|
|
283
|
-
- `socket.ts` — Clean
|
|
284
|
-
|
|
285
|
-
---
|
|
286
|
-
|
|
287
|
-
### Commands (`src/commands/`)
|
|
288
|
-
|
|
289
|
-
#### `prompt.ts`
|
|
290
|
-
|
|
291
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
292
|
-
|---------|-----------|-----------|----------|
|
|
293
|
-
| 250 | `await Bun.write(resolvedPath, updated)` — unguarded | `container.fs.writeFileAsync()` (already destructures `fs` on line 205!) | HIGH |
|
|
294
|
-
| 256 | `await Bun.write(outPath, markdown)` — unguarded | `container.fs.writeFileAsync()` | HIGH |
|
|
295
|
-
| 85, 88, 118, 147-179 | Extensive `process.stdout.write()` for streaming | Container `ui` feature | MEDIUM |
|
|
296
|
-
|
|
297
|
-
Inconsistent — lines 205+ use `container.fs` properly, but lines 250/256 use `Bun.write`.
|
|
298
|
-
|
|
299
|
-
#### `chat.ts`
|
|
300
|
-
|
|
301
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
302
|
-
|---------|-----------|-----------|----------|
|
|
303
|
-
| 2 | `import * as readline from 'readline'` | Container `repl` feature or `ui.askQuestion()` | HIGH |
|
|
304
|
-
| 94-97 | `readline.createInterface({ input: process.stdin, output: process.stdout })` | Container input abstraction | HIGH |
|
|
305
|
-
| 68-69, 76, 81, 86, 90 | `process.stdout.write(...)` | Container `ui` feature | MEDIUM |
|
|
306
|
-
|
|
307
|
-
The `console` command demonstrates the correct pattern using `container.feature('repl')`.
|
|
308
|
-
|
|
309
|
-
#### `console.ts`
|
|
310
|
-
|
|
311
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
312
|
-
|---------|-----------|-----------|----------|
|
|
313
|
-
| 67 | `Bun` injected into REPL context without guard | Guard with `container.isBun` | MEDIUM |
|
|
314
|
-
|
|
315
|
-
#### `sandbox-mcp.ts`
|
|
316
|
-
|
|
317
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
318
|
-
|---------|-----------|-----------|----------|
|
|
319
|
-
| 42 | `Bun` injected into VM context without guard | Guard with `container.isBun` | MEDIUM |
|
|
320
|
-
|
|
321
|
-
#### `run.ts`
|
|
322
|
-
|
|
323
|
-
| Line(s) | Violation | Should Use | Severity |
|
|
324
|
-
|---------|-----------|-----------|----------|
|
|
325
|
-
| 218 | `Bun` injected into REPL context without guard | Guard with `container.isBun` | MEDIUM |
|
|
326
|
-
|
|
327
|
-
#### Clean Command Files
|
|
328
|
-
|
|
329
|
-
- `eval.ts` — Clean
|
|
330
|
-
- `describe.ts` — Exemplary
|
|
331
|
-
- `help.ts` — Clean
|
|
332
|
-
- `index.ts` — Clean (barrel file)
|
|
333
|
-
- `serve.ts` — Clean (uses container throughout)
|
|
334
|
-
- `mcp.ts` — Clean
|
|
335
|
-
|
|
336
|
-
---
|
|
337
|
-
|
|
338
|
-
## Recurring Patterns
|
|
339
|
-
|
|
340
|
-
### 1. `process.env` for API Keys (MEDIUM, 10+ files)
|
|
341
|
-
Many features/clients declare `static envVars = [...]` but then read `process.env.KEY` directly in getters. The container should mediate this. Affected: `google-auth.ts`, `tts.ts`, `runpod.ts`, `telegram.ts`, `openai/index.ts`, `elevenlabs/index.ts`.
|
|
342
|
-
|
|
343
|
-
### 2. Unguarded `Bun.spawn` (HIGH, 5 files)
|
|
344
|
-
`claude-code.ts`, `openai-codex.ts`, `process-manager.ts` all call `Bun.spawn` without checking `container.isBun`. These need either proc feature usage or runtime guards.
|
|
345
|
-
|
|
346
|
-
### 3. Unguarded `Bun.write` (HIGH, 3 files)
|
|
347
|
-
`prompt.ts`, `claude-code.ts`, `comfyui/index.ts` use `Bun.write` when `container.fs.writeFileAsync()` is available.
|
|
348
|
-
|
|
349
|
-
### 4. Module-level `homedir()`/`join()` (HIGH, 2 files)
|
|
350
|
-
`launcher-app-command-listener.ts` and `window-manager.ts` compute paths at import time using `os.homedir()` and `path.join()`, before any container exists. These must be deferred to `enable()` or computed lazily.
|
|
351
|
-
|
|
352
|
-
### 5. Third-party HTTP imports (HIGH, 2 files)
|
|
353
|
-
`downloader.ts` imports `cross-fetch` and `runpod.ts` imports `axios` when global `fetch` and `container.client('rest')` are available.
|
|
354
|
-
|
|
355
|
-
### 6. Unguarded `Bun.Glob` (HIGH, 2 files)
|
|
356
|
-
`helpers.ts` and `express.ts` use `Bun.Glob` without runtime guards. The container's fs feature provides glob/walk capabilities.
|
|
357
|
-
|
|
358
|
-
---
|
|
359
|
-
|
|
360
|
-
## Recommended Fix Priority
|
|
361
|
-
|
|
362
|
-
### Priority 1 — Bugs
|
|
363
|
-
- [ ] `repl.ts` — Fix missing `fs` import (lines 92, 192). Use `this.container.fs` instead.
|
|
364
|
-
|
|
365
|
-
### Priority 2 — Bun-only code (breaks Node compatibility)
|
|
366
|
-
- [ ] `claude-code.ts` — Replace `Bun.spawn` with proc feature or add `isBun` guards
|
|
367
|
-
- [ ] `openai-codex.ts` — Same pattern as claude-code
|
|
368
|
-
- [ ] `process-manager.ts` — Replace `Bun.spawn` with proc feature or guard
|
|
369
|
-
- [ ] `google-auth.ts` — Replace `Bun.serve` with guard or container server
|
|
370
|
-
- [ ] `express.ts` — Replace `Bun.Glob` with container glob or guard
|
|
371
|
-
- [ ] `helpers.ts` — Replace `Bun.Glob` with container glob or guard
|
|
372
|
-
- [ ] `prompt.ts` — Replace `Bun.write` with `container.fs.writeFileAsync`
|
|
373
|
-
- [ ] `comfyui/index.ts` — Replace `Bun.write` + dynamic imports with container equivalents
|
|
374
|
-
|
|
375
|
-
### Priority 3 — Direct builtin imports (bypasses container)
|
|
376
|
-
- [ ] `skills-library.ts` — Replace all `path`, `os`, `fs/promises` with container equivalents
|
|
377
|
-
- [ ] `package-finder.ts` — Complete migration to container fs/paths
|
|
378
|
-
- [ ] `python.ts` — Replace `existsSync`/`join` with container equivalents
|
|
379
|
-
- [ ] `launcher-app-command-listener.ts` — Replace fs/path/os with container, defer module-level computations
|
|
380
|
-
- [ ] `window-manager.ts` — Same as launcher-app
|
|
381
|
-
- [ ] `downloader.ts` — Remove `cross-fetch`, use global `fetch`
|
|
382
|
-
- [ ] `runpod.ts` — Remove `axios`, use global `fetch` or container REST client
|
|
383
|
-
- [ ] `chat.ts` — Replace `readline` with container `repl` feature
|
|
384
|
-
|
|
385
|
-
### Priority 4 — `process.env` standardization
|
|
386
|
-
- [ ] Create or document a standard pattern for env var access across features/clients
|
|
387
|
-
- [ ] Update `google-auth.ts`, `tts.ts`, `runpod.ts`, `telegram.ts`, `openai/index.ts`, `elevenlabs/index.ts`
|
|
388
|
-
|
|
389
|
-
### Priority 5 — Minor guards
|
|
390
|
-
- [ ] `console.ts`, `sandbox-mcp.ts`, `run.ts` — Guard `Bun` global injection with `container.isBun`
|
|
391
|
-
- [ ] `tmux.ts` — Replace `execSync` dynamic import with `container.feature('proc')`
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
tags:
|
|
3
|
-
- console
|
|
4
|
-
- hmr
|
|
5
|
-
- repl
|
|
6
|
-
- design
|
|
7
|
-
---
|
|
8
|
-
# Console HMR Design Research
|
|
9
|
-
|
|
10
|
-
Add a `--hmr` flag to `luca console` that watches source files and hot-swaps feature instances in the live REPL session, preserving state where possible.
|
|
11
|
-
|
|
12
|
-
## How the Console Works Today
|
|
13
|
-
|
|
14
|
-
The `luca console` command (`src/commands/console.ts`) creates a REPL that:
|
|
15
|
-
|
|
16
|
-
1. Calls `container.helpers.discoverAll()` to load all features, commands, endpoints
|
|
17
|
-
2. Snapshots every available feature into a `featureContext` object via `container.feature(name)` for each name
|
|
18
|
-
3. Optionally loads a `luca.console.ts` project module and merges its exports
|
|
19
|
-
4. Optionally runs `--eval` code/script/markdown before the REPL starts
|
|
20
|
-
5. Creates a `Repl` feature instance with a `vm.Context` built from the snapshot
|
|
21
|
-
6. Enters a hand-rolled readline loop (`repl.ts`) that evaluates expressions in that VM context
|
|
22
|
-
|
|
23
|
-
The REPL's `_vmContext` is a **mutable plain object** — variables can be reassigned at runtime (`ctx.featureName = newInstance`). Tab completion reads from `Object.keys(ctx)` dynamically, so new/replaced bindings are immediately visible.
|
|
24
|
-
|
|
25
|
-
## Architectural Facts Relevant to HMR
|
|
26
|
-
|
|
27
|
-
### helperCache is module-private
|
|
28
|
-
|
|
29
|
-
`container.ts:618` — `const helperCache = new Map()`. There is no public API to evict or replace a cached feature instance. Calling `container.feature('fs')` with the same options always returns the same object. Any HMR implementation needs either:
|
|
30
|
-
- A new `container.evictHelper(cacheKey)` method
|
|
31
|
-
- A bypass that creates instances outside the cache
|
|
32
|
-
|
|
33
|
-
### attachToContainer uses configurable: true
|
|
34
|
-
|
|
35
|
-
`feature.ts` — `Object.defineProperty(this.container, shortcutName, { get: () => this, configurable: true })`. The property descriptor **can** be redefined, which is the only existing affordance for swapping a feature on the container object.
|
|
36
|
-
|
|
37
|
-
### vm.loadModule() always reads fresh from disk
|
|
38
|
-
|
|
39
|
-
`vm.ts` — reads file content via `container.fs.readFile()`, transpiles with esbuild `transformSync`, runs in a `vm.Script` context. No module cache to bust. But this runs in a CJS-like VM sandbox — real ES `import` statements inside the file won't work.
|
|
40
|
-
|
|
41
|
-
### Bun import() cache busting
|
|
42
|
-
|
|
43
|
-
The only cache-busting pattern in the codebase is `Endpoint.reload()` (`endpoint.ts:176`): `import(\`${path}?t=${Date.now()}\`)`. This works for Bun's native module loader and preserves real ES module semantics.
|
|
44
|
-
|
|
45
|
-
### State has no serialize/deserialize
|
|
46
|
-
|
|
47
|
-
`State` (`state.ts`) is an in-memory observable key-value bag with `set()`, `setState()`, `clear()`, and observer callbacks. There is no `toJSON()`/`fromSnapshot()` API. Transferring state between instances requires manually reading `state.current` from old and calling `state.setState()` on new.
|
|
48
|
-
|
|
49
|
-
### FileManager has chokidar file watching
|
|
50
|
-
|
|
51
|
-
`file-manager.ts` — `fileManager.watch()` uses chokidar and emits `"file:change"` events with `{ type, path }`. Currently not wired to anything automatically. This is the primitive we'd compose for watching source files.
|
|
52
|
-
|
|
53
|
-
### Feature self-registration is a static side effect
|
|
54
|
-
|
|
55
|
-
Features register via `static { Feature.register(this, 'name') }` which stores the **class constructor** in a module-level `FeaturesRegistry` Map. Re-importing a module would call `register()` again with a new constructor — the registry would need to handle overwrites.
|
|
56
|
-
|
|
57
|
-
## The HMR Flow (Conceptual)
|
|
58
|
-
|
|
59
|
-
```
|
|
60
|
-
[file change detected]
|
|
61
|
-
→ identify which feature(s) the file maps to
|
|
62
|
-
→ re-import the module (cache-busted)
|
|
63
|
-
→ new class constructor registers over old one
|
|
64
|
-
→ snapshot old instance state: state.current + any serializable instance data
|
|
65
|
-
→ evict old instance from helperCache
|
|
66
|
-
→ create new instance via container.feature(name)
|
|
67
|
-
→ transfer state: newInstance.state.setState(oldState)
|
|
68
|
-
→ patch REPL vm context: ctx[featureName] = newInstance
|
|
69
|
-
→ re-define container shortcut property to point to new instance
|
|
70
|
-
→ print "[HMR] Reloaded: featureName" in REPL
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
## Open Design Questions
|
|
74
|
-
|
|
75
|
-
### 1. Scope — which files trigger a reload?
|
|
76
|
-
|
|
77
|
-
- Just feature source files (`src/node/features/*.ts`)?
|
|
78
|
-
- Also command files, `luca.console.ts`, endpoint files?
|
|
79
|
-
- Or anything under `src/`?
|
|
80
|
-
|
|
81
|
-
Recommendation: Start with feature files only. Commands and endpoints are less stateful and easier to add later.
|
|
82
|
-
|
|
83
|
-
### 2. State transfer strategy
|
|
84
|
-
|
|
85
|
-
- **Best-effort `state.current` transfer**: Read `oldInstance.state.current`, call `newInstance.state.setState(snapshot)`. Simple, covers most cases.
|
|
86
|
-
- **Opt-in hooks**: Features declare `serialize()` / `deserialize()` methods for fine-grained control (e.g., FileManager could note which directories it was watching but not try to transfer the chokidar FSWatcher handle).
|
|
87
|
-
- **Hybrid**: Always transfer `state.current`, and if the feature has a `hmrSerialize()` hook, use that for additional instance data.
|
|
88
|
-
|
|
89
|
-
Non-state instance data (open file handles, chokidar watchers, readline interfaces, cached esbuild services) cannot be naively transferred. Features with complex resources would need explicit HMR support or accept that those resources restart fresh.
|
|
90
|
-
|
|
91
|
-
### 3. Module re-import strategy
|
|
92
|
-
|
|
93
|
-
Two options:
|
|
94
|
-
|
|
95
|
-
**Option A — Bun `import()` with `?t=` cache busting**: Real ES module semantics, `import` statements inside the feature file work. The new module's `static {}` block re-registers the class. This is what `Endpoint.reload()` already does.
|
|
96
|
-
|
|
97
|
-
**Option B — `vm.loadModule()`**: Always reads fresh from disk, no cache issues. But runs in a CJS sandbox — internal `import` statements won't resolve. Feature files heavily use `import`, so this likely won't work.
|
|
98
|
-
|
|
99
|
-
Recommendation: Option A. It's proven in the codebase and preserves full module semantics.
|
|
100
|
-
|
|
101
|
-
### 4. Registry re-registration
|
|
102
|
-
|
|
103
|
-
`Feature.register()` currently does `features.register(id, SubClass)` which calls `registry.members.set(id, SubClass)`. A re-import with a new class constructor would overwrite the old entry. This actually works — `Map.set` overwrites silently. But we should verify there are no side effects in `interceptRegistration` hooks or other registration logic that would break.
|
|
104
|
-
|
|
105
|
-
### 5. REPL context patching — automatic vs explicit
|
|
106
|
-
|
|
107
|
-
- **Automatic**: FileManager watches, detects change, swaps feature, patches `ctx[name]`, prints HMR message. User sees updated behavior on next expression.
|
|
108
|
-
- **Explicit**: User types `hmr.reload('fs')` or similar in the REPL to trigger a reload manually.
|
|
109
|
-
- **Both**: Auto-reload on file change, plus a manual `hmr.reload('name')` for forcing reloads or reloading things that aren't file-backed.
|
|
110
|
-
|
|
111
|
-
Recommendation: Both. Auto is the main UX, manual is the escape hatch.
|
|
112
|
-
|
|
113
|
-
### 6. Feedback in the REPL
|
|
114
|
-
|
|
115
|
-
Print a colored message when a feature reloads:
|
|
116
|
-
```
|
|
117
|
-
[HMR] Reloaded: fs (state transferred)
|
|
118
|
-
[HMR] Reloaded: diskCache (fresh — no prior state)
|
|
119
|
-
[HMR] Error reloading vm: SyntaxError: Unexpected token (kept old instance)
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
This should be non-intrusive — printed above the prompt line if possible.
|
|
123
|
-
|
|
124
|
-
### 7. Failure mode
|
|
125
|
-
|
|
126
|
-
If the new code has a syntax error or the constructor throws:
|
|
127
|
-
- Keep the old instance alive
|
|
128
|
-
- Print the error in the REPL
|
|
129
|
-
- Do not crash the session
|
|
130
|
-
|
|
131
|
-
This is the only sane approach for a dev tool.
|
|
132
|
-
|
|
133
|
-
## Implementation Sketch
|
|
134
|
-
|
|
135
|
-
### New infrastructure needed
|
|
136
|
-
|
|
137
|
-
1. **`container.evictHelper(type, id, options?)`** — public method on Container that deletes from `helperCache` and cleans up `featureIdToHelperCacheKeyMap` and `contextMap`
|
|
138
|
-
2. **`Feature.prototype.hmrSerialize?()` / `hmrDeserialize?(data)`** — optional hooks for features that need custom state transfer beyond `state.current`
|
|
139
|
-
3. **`registry.register()` handling overwrites** — verify this works cleanly, add a `"re-registered"` event if useful
|
|
140
|
-
4. **File-to-feature mapping** — a way to know that `src/node/features/disk-cache.ts` corresponds to the `diskCache` feature ID
|
|
141
|
-
|
|
142
|
-
### Changes to existing code
|
|
143
|
-
|
|
144
|
-
1. **`src/commands/console.ts`** — add `--hmr` flag to `argsSchema`, wire up file watching and the reload loop when enabled
|
|
145
|
-
2. **`src/container.ts`** — expose `evictHelper()` (or a more targeted `replaceFeature()`)
|
|
146
|
-
3. **`src/node/features/repl.ts`** — expose a method to patch the VM context (or just expose `_vmContext` which is already accessible)
|
|
147
|
-
|
|
148
|
-
### Rough dependency graph
|
|
149
|
-
|
|
150
|
-
```
|
|
151
|
-
argsSchema adds --hmr flag
|
|
152
|
-
→ console handler checks for --hmr
|
|
153
|
-
→ starts FileManager.watch() on src/ directory
|
|
154
|
-
→ subscribes to "file:change" events
|
|
155
|
-
→ on change: resolveFeatureFromPath(changedFile)
|
|
156
|
-
→ cache-bust import the module
|
|
157
|
-
→ container.evictHelper('feature', featureId)
|
|
158
|
-
→ newInstance = container.feature(featureId, { enable: wasEnabled })
|
|
159
|
-
→ transfer state from old → new
|
|
160
|
-
→ patch repl._vmContext[featureId] = newInstance
|
|
161
|
-
→ print HMR message
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
## Risks and Unknowns
|
|
165
|
-
|
|
166
|
-
- **Circular dependency during re-import**: If feature A imports feature B at module level, and both are being reloaded, the order matters. May need to batch reloads or do a dependency-aware reload order.
|
|
167
|
-
- **Event listener cleanup**: Old feature instances may have registered listeners on the container event bus. Need to remove those or they'll fire on stale instances.
|
|
168
|
-
- **Observer cleanup**: State observers from the old instance need to be unsubscribed or they'll leak.
|
|
169
|
-
- **Features that modify globals**: Some features might set up global state (process event handlers, etc.) that won't be cleaned up by replacing the instance.
|
|
170
|
-
- **The `?t=` trick and TypeScript**: Bun handles `import('./foo.ts?t=123')` but we should verify this works for all feature files, especially those with complex re-exports.
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
tags:
|
|
3
|
-
- feature-design
|
|
4
|
-
- semantic-search
|
|
5
|
-
- introspection
|
|
6
|
-
status: draft
|
|
7
|
-
---
|
|
8
|
-
# Helper Semantic Search Feature
|
|
9
|
-
|
|
10
|
-
Build semantic search over all describable luca helpers so AI assistants can find the right feature/client/server by describing what they need.
|
|
11
|
-
|
|
12
|
-
## Motivation
|
|
13
|
-
|
|
14
|
-
The `luca describe` system produces rich markdown for every helper (features, clients, servers, commands, endpoints, selectors). An AI assistant working with luca currently has to know the exact name of a helper to look it up. Semantic search would let it say "I need to run shell commands" and find `proc`, or "I need to cache things to disk" and find `diskCache`.
|
|
15
|
-
|
|
16
|
-
Storage location: `~/.luca/embeddings/`
|
|
17
|
-
|
|
18
|
-
## What Already Exists
|
|
19
|
-
|
|
20
|
-
Two systems that combine perfectly:
|
|
21
|
-
|
|
22
|
-
1. **SemanticSearch feature** (`src/node/features/semantic-search.ts`) — SQLite-backed embedding engine with OpenAI/local GGUF providers, section-based chunking, BM25 + vector + hybrid search with RRF fusion.
|
|
23
|
-
|
|
24
|
-
2. **Introspection system** (`src/introspection/`) — Every helper produces structured `HelperIntrospection` JSON and rendered markdown via `Helper.introspectAsText()`. Build-time AST scanning (JSDoc) + runtime Zod schema reflection. The `__INTROSPECTION__` map holds everything.
|
|
25
|
-
|
|
26
|
-
## Proposed Design
|
|
27
|
-
|
|
28
|
-
### Approach
|
|
29
|
-
|
|
30
|
-
Reuse the existing `SemanticSearch` feature directly. Create a new feature (e.g. `helperSearch`) that:
|
|
31
|
-
|
|
32
|
-
1. Iterates all registries, calls `introspectAsText()` on each helper to get markdown
|
|
33
|
-
2. Structures the markdown as `DocumentInput` objects with sections (methods, getters, events, state, options)
|
|
34
|
-
3. Feeds them to SemanticSearch for embedding and indexing
|
|
35
|
-
4. Exposes a `search(query)` method that delegates to hybridSearch
|
|
36
|
-
|
|
37
|
-
### Storage
|
|
38
|
-
|
|
39
|
-
DB stored at `~/.luca/embeddings/helpers.<provider>-<model>.sqlite`, scoped by provider+model like contentbase does.
|
|
40
|
-
|
|
41
|
-
### When to Build Index
|
|
42
|
-
|
|
43
|
-
- Lazy on first search if no index exists or if stale
|
|
44
|
-
- Explicit rebuild via `luca search --rebuild`
|
|
45
|
-
- Content hash gating from SemanticSearch handles incremental updates automatically
|
|
46
|
-
|
|
47
|
-
### CLI Surface
|
|
48
|
-
|
|
49
|
-
`luca search "file operations"` — returns ranked helpers with snippets showing why they matched.
|
|
50
|
-
|
|
51
|
-
### MCP / AI Assistant Surface
|
|
52
|
-
|
|
53
|
-
Expose as a tool in the luca-sandbox MCP so AI assistants can search for helpers by describing what they need.
|
|
54
|
-
|
|
55
|
-
## Open Questions
|
|
56
|
-
|
|
57
|
-
1. **Scope** — Index just core luca helpers, or also project-level commands/endpoints/selectors discovered at runtime? Suggestion: core always, project-level optionally.
|
|
58
|
-
|
|
59
|
-
2. **Granularity** — One document per helper (full describe output) vs chunked by section (methods, events, state). Suggestion: chunk by section so "run shell commands" matches `proc.exec` specifically.
|
|
60
|
-
|
|
61
|
-
3. **Primary consumer** — MCP tool for AI assistants, CLI for humans, or both? Suggestion: both.
|
|
62
|
-
|
|
63
|
-
4. **Embedding provider default** — OpenAI (higher quality, needs API key) or local GGUF (works offline, lower quality)? Suggestion: OpenAI default with local fallback.
|
|
64
|
-
|
|
65
|
-
## Key Files
|
|
66
|
-
|
|
67
|
-
- `src/node/features/semantic-search.ts` — The embedding engine to reuse
|
|
68
|
-
- `src/introspection/index.ts` — `__INTROSPECTION__` map, `HelperIntrospection` type
|
|
69
|
-
- `src/helper.ts` — `Helper.introspect()`, `Helper.introspectAsText()`, markdown renderers
|
|
70
|
-
- `src/registry.ts` — Registry base class, `describe()`, `describeAll()`
|
|
71
|
-
- `src/commands/describe.ts` — Current describe command (target resolution, rendering)
|
|
72
|
-
- `src/node/features/content-db.ts` — Reference for how contentDb wraps SemanticSearch
|