@soederpop/luca 0.0.2
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/CLAUDE.md +71 -0
- package/README.md +78 -0
- package/bun.lock +2928 -0
- package/bunfig.toml +3 -0
- package/commands/audit-docs.ts +740 -0
- package/commands/build-scaffolds.ts +154 -0
- package/commands/generate-api-docs.ts +114 -0
- package/commands/update-introspection.ts +67 -0
- package/docs/CLI.md +335 -0
- package/docs/README.md +88 -0
- package/docs/TABLE-OF-CONTENTS.md +157 -0
- package/docs/apis/clients/elevenlabs.md +84 -0
- package/docs/apis/clients/graph.md +56 -0
- package/docs/apis/clients/openai.md +69 -0
- package/docs/apis/clients/rest.md +41 -0
- package/docs/apis/clients/websocket.md +107 -0
- package/docs/apis/features/agi/assistant.md +471 -0
- package/docs/apis/features/agi/assistants-manager.md +154 -0
- package/docs/apis/features/agi/claude-code.md +602 -0
- package/docs/apis/features/agi/conversation-history.md +352 -0
- package/docs/apis/features/agi/conversation.md +333 -0
- package/docs/apis/features/agi/docs-reader.md +121 -0
- package/docs/apis/features/agi/openai-codex.md +318 -0
- package/docs/apis/features/agi/openapi.md +138 -0
- package/docs/apis/features/agi/semantic-search.md +387 -0
- package/docs/apis/features/agi/skills-library.md +216 -0
- package/docs/apis/features/node/container-link.md +133 -0
- package/docs/apis/features/node/content-db.md +313 -0
- package/docs/apis/features/node/disk-cache.md +379 -0
- package/docs/apis/features/node/dns.md +651 -0
- package/docs/apis/features/node/docker.md +705 -0
- package/docs/apis/features/node/downloader.md +81 -0
- package/docs/apis/features/node/esbuild.md +59 -0
- package/docs/apis/features/node/file-manager.md +182 -0
- package/docs/apis/features/node/fs.md +581 -0
- package/docs/apis/features/node/git.md +330 -0
- package/docs/apis/features/node/google-auth.md +174 -0
- package/docs/apis/features/node/google-calendar.md +187 -0
- package/docs/apis/features/node/google-docs.md +151 -0
- package/docs/apis/features/node/google-drive.md +225 -0
- package/docs/apis/features/node/google-sheets.md +179 -0
- package/docs/apis/features/node/grep.md +290 -0
- package/docs/apis/features/node/helpers.md +135 -0
- package/docs/apis/features/node/ink.md +334 -0
- package/docs/apis/features/node/ipc-socket.md +260 -0
- package/docs/apis/features/node/json-tree.md +86 -0
- package/docs/apis/features/node/launcher-app-command-listener.md +145 -0
- package/docs/apis/features/node/networking.md +281 -0
- package/docs/apis/features/node/nlp.md +133 -0
- package/docs/apis/features/node/opener.md +97 -0
- package/docs/apis/features/node/os.md +118 -0
- package/docs/apis/features/node/package-finder.md +402 -0
- package/docs/apis/features/node/postgres.md +212 -0
- package/docs/apis/features/node/proc.md +430 -0
- package/docs/apis/features/node/process-manager.md +210 -0
- package/docs/apis/features/node/python.md +278 -0
- package/docs/apis/features/node/repl.md +88 -0
- package/docs/apis/features/node/runpod.md +673 -0
- package/docs/apis/features/node/secure-shell.md +169 -0
- package/docs/apis/features/node/semantic-search.md +401 -0
- package/docs/apis/features/node/sqlite.md +211 -0
- package/docs/apis/features/node/telegram.md +254 -0
- package/docs/apis/features/node/tts.md +118 -0
- package/docs/apis/features/node/ui.md +703 -0
- package/docs/apis/features/node/vault.md +64 -0
- package/docs/apis/features/node/vm.md +84 -0
- package/docs/apis/features/node/window-manager.md +337 -0
- package/docs/apis/features/node/yaml-tree.md +85 -0
- package/docs/apis/features/node/yaml.md +176 -0
- package/docs/apis/features/web/asset-loader.md +47 -0
- package/docs/apis/features/web/container-link.md +133 -0
- package/docs/apis/features/web/esbuild.md +59 -0
- package/docs/apis/features/web/helpers.md +135 -0
- package/docs/apis/features/web/network.md +30 -0
- package/docs/apis/features/web/speech.md +55 -0
- package/docs/apis/features/web/vault.md +64 -0
- package/docs/apis/features/web/vm.md +84 -0
- package/docs/apis/features/web/voice.md +67 -0
- package/docs/apis/servers/express.md +127 -0
- package/docs/apis/servers/mcp.md +213 -0
- package/docs/apis/servers/websocket.md +99 -0
- package/docs/documentation-audit.md +134 -0
- package/docs/examples/content-db.md +77 -0
- package/docs/examples/disk-cache.md +83 -0
- package/docs/examples/docker.md +101 -0
- package/docs/examples/downloader.md +70 -0
- package/docs/examples/esbuild.md +80 -0
- package/docs/examples/file-manager.md +82 -0
- package/docs/examples/fs.md +83 -0
- package/docs/examples/git.md +85 -0
- package/docs/examples/google-auth.md +88 -0
- package/docs/examples/google-calendar.md +94 -0
- package/docs/examples/google-docs.md +82 -0
- package/docs/examples/google-drive.md +96 -0
- package/docs/examples/google-sheets.md +95 -0
- package/docs/examples/grep.md +85 -0
- package/docs/examples/ink-blocks.md +75 -0
- package/docs/examples/ink-renderer.md +41 -0
- package/docs/examples/ink.md +103 -0
- package/docs/examples/ipc-socket.md +103 -0
- package/docs/examples/json-tree.md +91 -0
- package/docs/examples/launcher-app-command-listener.md +120 -0
- package/docs/examples/networking.md +58 -0
- package/docs/examples/nlp.md +91 -0
- package/docs/examples/opener.md +78 -0
- package/docs/examples/os.md +72 -0
- package/docs/examples/package-finder.md +89 -0
- package/docs/examples/port-exposer.md +89 -0
- package/docs/examples/postgres.md +91 -0
- package/docs/examples/proc.md +81 -0
- package/docs/examples/process-manager.md +79 -0
- package/docs/examples/python.md +91 -0
- package/docs/examples/repl.md +93 -0
- package/docs/examples/runpod.md +119 -0
- package/docs/examples/secure-shell.md +92 -0
- package/docs/examples/sqlite.md +86 -0
- package/docs/examples/telegram.md +77 -0
- package/docs/examples/tts.md +86 -0
- package/docs/examples/ui.md +80 -0
- package/docs/examples/vault.md +70 -0
- package/docs/examples/vm.md +86 -0
- package/docs/examples/window-manager.md +125 -0
- package/docs/examples/yaml-tree.md +93 -0
- package/docs/examples/yaml.md +104 -0
- package/docs/ideas/class-registration-refactor-possibilities.md +197 -0
- package/docs/ideas/container-use-api.md +9 -0
- package/docs/ideas/easy-auth-for-express-servers-and-luca-serve.md +0 -0
- package/docs/ideas/feature-stacks.md +22 -0
- package/docs/ideas/luca-cli-self-sufficiency-demo.md +23 -0
- package/docs/ideas/mcp-design.md +9 -0
- package/docs/ideas/web-container-debugging-feature.md +13 -0
- package/docs/introspection-audit.md +49 -0
- package/docs/introspection.md +154 -0
- package/docs/mcp/readme.md +162 -0
- package/docs/models.ts +38 -0
- package/docs/philosophy.md +85 -0
- package/docs/principles.md +7 -0
- package/docs/prompts/audit-codebase-for-failures-to-use-the-container.md +34 -0
- package/docs/prompts/mcp-test-easy-command.md +27 -0
- package/docs/reports/assistant-bugs.md +38 -0
- package/docs/reports/attach-pattern-usage.md +18 -0
- package/docs/reports/code-audit-results.md +391 -0
- package/docs/reports/introspection-audit-tasks.md +378 -0
- package/docs/reports/luca-mcp-improvements.md +128 -0
- package/docs/scaffolds/client.md +140 -0
- package/docs/scaffolds/command.md +106 -0
- package/docs/scaffolds/endpoint.md +176 -0
- package/docs/scaffolds/feature.md +148 -0
- package/docs/scaffolds/server.md +187 -0
- package/docs/tasks/web-container-helper-discovery.md +71 -0
- package/docs/todos.md +1 -0
- package/docs/tutorials/01-getting-started.md +106 -0
- package/docs/tutorials/02-container.md +210 -0
- package/docs/tutorials/03-scripts.md +194 -0
- package/docs/tutorials/04-features-overview.md +196 -0
- package/docs/tutorials/05-state-and-events.md +171 -0
- package/docs/tutorials/06-servers.md +157 -0
- package/docs/tutorials/07-endpoints.md +198 -0
- package/docs/tutorials/08-commands.md +171 -0
- package/docs/tutorials/09-clients.md +162 -0
- package/docs/tutorials/10-creating-features.md +198 -0
- package/docs/tutorials/11-contentbase.md +191 -0
- package/docs/tutorials/12-assistants.md +215 -0
- package/docs/tutorials/13-introspection.md +147 -0
- package/docs/tutorials/14-type-system.md +174 -0
- package/docs/tutorials/15-project-patterns.md +222 -0
- package/docs/tutorials/16-google-features.md +534 -0
- package/docs/tutorials/17-tui-blocks.md +530 -0
- package/docs/tutorials/18-semantic-search.md +334 -0
- package/index.ts +1 -0
- package/luca.console.ts +9 -0
- package/main.py +6 -0
- package/package.json +154 -0
- package/pyproject.toml +7 -0
- package/scripts/animations/chrome-glitch.ts +55 -0
- package/scripts/animations/index.ts +16 -0
- package/scripts/animations/neon-pulse.ts +64 -0
- package/scripts/animations/types.ts +6 -0
- package/scripts/build-web.ts +28 -0
- package/scripts/examples/ask-luca-expert.ts +42 -0
- package/scripts/examples/assistant-questions.ts +12 -0
- package/scripts/examples/excalidraw-expert.ts +75 -0
- package/scripts/examples/expert-chat.ts +0 -0
- package/scripts/examples/file-manager.ts +14 -0
- package/scripts/examples/ideas.ts +12 -0
- package/scripts/examples/interactive-chat.ts +20 -0
- package/scripts/examples/openai-tool-calls.ts +113 -0
- package/scripts/examples/opening-a-web-browser.ts +5 -0
- package/scripts/examples/telegram-bot.ts +79 -0
- package/scripts/examples/telegram-ink-ui.ts +302 -0
- package/scripts/examples/using-assistant-with-mcp.ts +560 -0
- package/scripts/examples/using-claude-code.ts +10 -0
- package/scripts/examples/using-contentdb.ts +35 -0
- package/scripts/examples/using-conversations.ts +35 -0
- package/scripts/examples/using-disk-cache.ts +10 -0
- package/scripts/examples/using-docker-shell.ts +75 -0
- package/scripts/examples/using-elevenlabs.ts +25 -0
- package/scripts/examples/using-google-calendar.ts +57 -0
- package/scripts/examples/using-google-docs.ts +74 -0
- package/scripts/examples/using-google-drive.ts +74 -0
- package/scripts/examples/using-google-sheets.ts +89 -0
- package/scripts/examples/using-nlp.ts +55 -0
- package/scripts/examples/using-ollama.ts +10 -0
- package/scripts/examples/using-openai-codex.ts +23 -0
- package/scripts/examples/using-postgres.ts +55 -0
- package/scripts/examples/using-runpod.ts +32 -0
- package/scripts/examples/using-tts.ts +40 -0
- package/scripts/examples/vm-loading-esm-modules.ts +16 -0
- package/scripts/scaffold.ts +391 -0
- package/scripts/scratch.ts +15 -0
- package/scripts/test-command-listener.ts +123 -0
- package/scripts/test-window-manager-lifecycle.ts +86 -0
- package/scripts/test-window-manager.ts +43 -0
- package/scripts/update-introspection-data.ts +58 -0
- package/src/agi/README.md +14 -0
- package/src/agi/container.server.ts +114 -0
- package/src/agi/endpoints/ask.ts +60 -0
- package/src/agi/endpoints/conversations/[id].ts +45 -0
- package/src/agi/endpoints/conversations.ts +31 -0
- package/src/agi/endpoints/experts.ts +37 -0
- package/src/agi/features/assistant.ts +767 -0
- package/src/agi/features/assistants-manager.ts +260 -0
- package/src/agi/features/claude-code.ts +1111 -0
- package/src/agi/features/conversation-history.ts +497 -0
- package/src/agi/features/conversation.ts +799 -0
- package/src/agi/features/openai-codex.ts +631 -0
- package/src/agi/features/openapi.ts +438 -0
- package/src/agi/features/skills-library.ts +425 -0
- package/src/agi/index.ts +6 -0
- package/src/agi/lib/token-counter.ts +122 -0
- package/src/browser.ts +25 -0
- package/src/bus.ts +100 -0
- package/src/cli/cli.ts +70 -0
- package/src/client.ts +461 -0
- package/src/clients/civitai/index.ts +541 -0
- package/src/clients/client-template.ts +41 -0
- package/src/clients/comfyui/index.ts +597 -0
- package/src/clients/elevenlabs/index.ts +291 -0
- package/src/clients/openai/index.ts +451 -0
- package/src/clients/supabase/index.ts +366 -0
- package/src/command.ts +164 -0
- package/src/commands/chat.ts +182 -0
- package/src/commands/console.ts +192 -0
- package/src/commands/describe.ts +433 -0
- package/src/commands/eval.ts +116 -0
- package/src/commands/help.ts +214 -0
- package/src/commands/index.ts +14 -0
- package/src/commands/mcp.ts +64 -0
- package/src/commands/prompt.ts +807 -0
- package/src/commands/run.ts +257 -0
- package/src/commands/sandbox-mcp.ts +439 -0
- package/src/commands/scaffold.ts +79 -0
- package/src/commands/serve.ts +172 -0
- package/src/container.ts +781 -0
- package/src/endpoint.ts +340 -0
- package/src/feature.ts +75 -0
- package/src/hash-object.ts +97 -0
- package/src/helper.ts +543 -0
- package/src/introspection/generated.agi.ts +23388 -0
- package/src/introspection/generated.node.ts +18899 -0
- package/src/introspection/generated.web.ts +2021 -0
- package/src/introspection/index.ts +256 -0
- package/src/introspection/scan.ts +912 -0
- package/src/node/container.ts +354 -0
- package/src/node/feature.ts +13 -0
- package/src/node/features/container-link.ts +558 -0
- package/src/node/features/content-db.ts +475 -0
- package/src/node/features/disk-cache.ts +382 -0
- package/src/node/features/dns.ts +655 -0
- package/src/node/features/docker.ts +912 -0
- package/src/node/features/downloader.ts +92 -0
- package/src/node/features/esbuild.ts +68 -0
- package/src/node/features/file-manager.ts +357 -0
- package/src/node/features/fs.ts +534 -0
- package/src/node/features/git.ts +492 -0
- package/src/node/features/google-auth.ts +502 -0
- package/src/node/features/google-calendar.ts +300 -0
- package/src/node/features/google-docs.ts +404 -0
- package/src/node/features/google-drive.ts +339 -0
- package/src/node/features/google-sheets.ts +279 -0
- package/src/node/features/grep.ts +406 -0
- package/src/node/features/helpers.ts +374 -0
- package/src/node/features/ink.ts +490 -0
- package/src/node/features/ipc-socket.ts +459 -0
- package/src/node/features/json-tree.ts +188 -0
- package/src/node/features/launcher-app-command-listener.ts +388 -0
- package/src/node/features/networking.ts +925 -0
- package/src/node/features/nlp.ts +211 -0
- package/src/node/features/opener.ts +166 -0
- package/src/node/features/os.ts +157 -0
- package/src/node/features/package-finder.ts +539 -0
- package/src/node/features/port-exposer.ts +342 -0
- package/src/node/features/postgres.ts +273 -0
- package/src/node/features/proc.ts +502 -0
- package/src/node/features/process-manager.ts +542 -0
- package/src/node/features/python.ts +444 -0
- package/src/node/features/repl.ts +194 -0
- package/src/node/features/runpod.ts +802 -0
- package/src/node/features/secure-shell.ts +248 -0
- package/src/node/features/semantic-search.ts +924 -0
- package/src/node/features/sqlite.ts +289 -0
- package/src/node/features/telegram.ts +342 -0
- package/src/node/features/tts.ts +184 -0
- package/src/node/features/ui.ts +857 -0
- package/src/node/features/vault.ts +164 -0
- package/src/node/features/vm.ts +312 -0
- package/src/node/features/window-manager.ts +804 -0
- package/src/node/features/yaml-tree.ts +149 -0
- package/src/node/features/yaml.ts +132 -0
- package/src/node.ts +70 -0
- package/src/react/index.ts +175 -0
- package/src/registry.ts +199 -0
- package/src/scaffolds/generated.ts +1613 -0
- package/src/scaffolds/template.ts +37 -0
- package/src/schemas/base.ts +255 -0
- package/src/server.ts +135 -0
- package/src/servers/express.ts +209 -0
- package/src/servers/mcp.ts +805 -0
- package/src/servers/socket.ts +120 -0
- package/src/state.ts +101 -0
- package/src/web/clients/socket.ts +82 -0
- package/src/web/container.ts +74 -0
- package/src/web/extension.ts +30 -0
- package/src/web/feature.ts +12 -0
- package/src/web/features/asset-loader.ts +64 -0
- package/src/web/features/container-link.ts +385 -0
- package/src/web/features/esbuild.ts +79 -0
- package/src/web/features/helpers.ts +267 -0
- package/src/web/features/network.ts +61 -0
- package/src/web/features/speech.ts +87 -0
- package/src/web/features/vault.ts +189 -0
- package/src/web/features/vm.ts +78 -0
- package/src/web/features/voice-recognition.ts +129 -0
- package/src/web/shims/isomorphic-vm.ts +149 -0
- package/test/bus.test.ts +134 -0
- package/test/clients-servers.test.ts +216 -0
- package/test/container-link.test.ts +274 -0
- package/test/features.test.ts +160 -0
- package/test/integration.test.ts +787 -0
- package/test/node-container.test.ts +121 -0
- package/test/rate-limit.test.ts +272 -0
- package/test/semantic-search.test.ts +550 -0
- package/test/state.test.ts +121 -0
- package/test-integration/assistant.test.ts +138 -0
- package/test-integration/assistants-manager.test.ts +123 -0
- package/test-integration/claude-code.test.ts +98 -0
- package/test-integration/conversation-history.test.ts +205 -0
- package/test-integration/conversation.test.ts +137 -0
- package/test-integration/elevenlabs.test.ts +55 -0
- package/test-integration/google-services.test.ts +80 -0
- package/test-integration/helpers.ts +89 -0
- package/test-integration/openai-codex.test.ts +93 -0
- package/test-integration/runpod.test.ts +58 -0
- package/test-integration/server-endpoints.test.ts +97 -0
- package/test-integration/skills-library.test.ts +157 -0
- package/test-integration/telegram.test.ts +46 -0
- package/tsconfig.json +58 -0
- package/uv.lock +8 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Luca's Philosophy
|
|
2
|
+
|
|
3
|
+
> LUCA - Lightweight Universal Conversational Architecture
|
|
4
|
+
|
|
5
|
+
If you open up a Developer console on a blank HTML page, you have the `window` object and the `document` object, and from those objects you have everything you need to build every web application you've ever interacted with, IN THEORY, without ever reloading the page.
|
|
6
|
+
|
|
7
|
+
Obviously nobody builds applications this way in a single REPL, but in 2026 developers are people and Agent AIs collaborating on the same codebase in a bigger Read, Eval, Print, Loop that takes place across more computers and brains.
|
|
8
|
+
|
|
9
|
+
Luca aims to provide a `container` object that gets you 60% of the way there before you write a line of application code. As the types of applications you build and who you build them for further narrow, the container grows to cover 95%.
|
|
10
|
+
|
|
11
|
+
How? By layering, the way you layer dockerfiles. The things which change least frequently are solved once and cached. The things which change more frequently live in their own isolated layer. That loop is smaller, quicker — the difference between a dockerfile that reinstalls the OS every time you change the HTML file, and one that doesn't.
|
|
12
|
+
|
|
13
|
+
## The Layer Model
|
|
14
|
+
|
|
15
|
+
Think of it like docker layers:
|
|
16
|
+
|
|
17
|
+
**Layer 1: Platform** — `NodeContainer`, `WebContainer`. Features that are universally applicable to any application in that runtime. Filesystem, networking, process management, event buses, observable state. You solve this once.
|
|
18
|
+
|
|
19
|
+
**Layer 2: Domain** — `AGIContainer`, or imagine a `RestaurantContainer`, `FinanceContainer`. Features, clients, servers specific to that category of application. You solve this rarely.
|
|
20
|
+
|
|
21
|
+
**Layer 3: The Actual Work** — The specific thing you're building for the specific person who needs it. This is what changes every day.
|
|
22
|
+
|
|
23
|
+
Layer 1 and Layer 2 you solve once and almost never again. When you get to Layer 3, everything is so specific that it changes constantly. The entire point is to spend all of your energy on Layer 3. If you fix something in Layer 1, every project that uses it benefits immediately — just like every docker image based on alpine benefits when alpine patches something.
|
|
24
|
+
|
|
25
|
+
The `container` is the central piece. You build it in layers with components that are stable enough to be reused across tasks, use cases, projects, and clients. And since it's JavaScript, it works in the browser or the server. Build a GitHub client in one project, add it to the container, start a brand new project with that same container, and the GitHub client is already there.
|
|
26
|
+
|
|
27
|
+
## Helpers and Registries: Conversational Dependency Injection
|
|
28
|
+
|
|
29
|
+
The `container` provides `Registries` of `Helpers`. A `Helper` is a formal, consistent interface for a category of thing. Features can be enabled. Servers can be started and stopped. Clients can be connected. Commands can be run. These "things" share common lifecycles (state) and emit similar events (started, connected, enabled). Clients, servers, features are part of almost every application I've built for 20 years, but every domain has its own categories too — Helpers can be customized to represent those.
|
|
30
|
+
|
|
31
|
+
`Registries` are a central place for storing the various implementations and being able to discover which ones are available.
|
|
32
|
+
|
|
33
|
+
The `container` provides factory functions — `feature()`, `server()`, `client()` — to create instances. Every helper instance has its own event bus, its own observable state, can be `introspected()` at runtime, and has fully typed interfaces that light up your IDE.
|
|
34
|
+
|
|
35
|
+
## Why "Conversational"?
|
|
36
|
+
|
|
37
|
+
The name means two things at once.
|
|
38
|
+
|
|
39
|
+
First, you can literally talk to the container. Give an LLM access to the container object and tool calls, and it can discover what's available, learn how to use it, and build with it — all at runtime. The introspection system means nothing is hidden. Every feature, every method signature, every event, every state shape is discoverable programmatically.
|
|
40
|
+
|
|
41
|
+
Second, the components talk to each other. Observable state, event buses, and well-documented typed interfaces mean that everything in the system can react to everything else through formal, predictable channels. Not magic strings and implicit coupling — actual typed contracts with build-time autocomplete and runtime introspection of the same.
|
|
42
|
+
|
|
43
|
+
## A Shared Mental Model
|
|
44
|
+
|
|
45
|
+
This is the real thesis.
|
|
46
|
+
|
|
47
|
+
The human and the AI share the same mental model of how the code should be organized and structured. The human isn't just directing the AI — they're collaborating inside the same architecture, speaking the same language about the same things.
|
|
48
|
+
|
|
49
|
+
A human defines the Helper — the interface, the lifecycle, the state shape, the events it emits. They decide *what* a thing is, *how* it behaves from the outside, and *where* it lives in the system. The AI understands that same structure and works within it. When the human says "make a client for Stripe," the AI already knows what a Client is, where it goes, what interface it needs to satisfy, and what lifecycle it follows. They're not negotiating from scratch every time — they're both operating from the same map.
|
|
50
|
+
|
|
51
|
+
This matters because as AI builds more and more of the internals, the human still feels at home. The organization of the code is still theirs. The names are theirs. The architecture is theirs. The folder structure, the class hierarchy, the way things relate to each other — that's their map, and the AI respects it because the AI shares it.
|
|
52
|
+
|
|
53
|
+
Defining Helpers is how a human says "in my world, these are the categories of things that exist, and this is how they work." The AI doesn't need to understand *why* those categories make sense for the business or the domain — it just needs the interface contract and it can implement anything that satisfies it.
|
|
54
|
+
|
|
55
|
+
## Trust Through Composition
|
|
56
|
+
|
|
57
|
+
Here's where it gets really interesting.
|
|
58
|
+
|
|
59
|
+
Because everything is captured as Helpers with formal interfaces, every component can be reviewed, audited, and secured independently. You can track provenance — who wrote it, when, what it depends on. A Helper that's been vetted is a Helper you can trust.
|
|
60
|
+
|
|
61
|
+
Over time, the AI generates less and less net-new code. Instead, it composes with existing Helpers — calling their interfaces, subscribing to their events, reading their state. The new code it does write gets captured into new Helpers that go through the same review cycle. The codebase becomes a growing library of trusted, audited building blocks.
|
|
62
|
+
|
|
63
|
+
This flips the usual fear about AI-generated code on its head. Normally, the more an AI writes, the less confident you feel about what's in there. With Luca, the more an AI writes, the more it's using components you've already reviewed. The codebase gets *more* trustworthy as it grows, not less. The surface area of unreviewed code shrinks because the AI is reaching for existing Helpers instead of generating raw implementations from scratch every time.
|
|
64
|
+
|
|
65
|
+
This also constrains the AI in a productive way. Instead of generating sprawling, unstructured code that the human has to reverse-engineer, the AI is given a clear place to put things and a clear shape they need to be. The result is a codebase that grows but stays navigable, because the human designed the map and the AI respects it.
|
|
66
|
+
|
|
67
|
+
## The Agent Runtime
|
|
68
|
+
|
|
69
|
+
Take this one step further.
|
|
70
|
+
|
|
71
|
+
Imagine an Agent that already knows JavaScript like a master. Give it a `container` object. Through introspection alone, it can learn about every feature, server, client, and command available to it. It can discover their options, their observable state, the events they emit, and the signatures for all of these things. It can write code against them. It can modify itself at runtime. You can watch the thing being built, interact with it, steer it.
|
|
72
|
+
|
|
73
|
+
This is not theoretical. The AGI container layer already does this — it wraps tools like Claude Code and OpenAI into the same Helper pattern, gives them the same observable state and event buses, and lets agents use the full container to build and extend themselves.
|
|
74
|
+
|
|
75
|
+
The REPL-driven development style that Luca was originally designed for maps perfectly onto this. The same properties that make something nice to work with in a REPL — discoverability, introspection, observable state, immediate feedback — are exactly the properties that make something nice for an AI agent to work with.
|
|
76
|
+
|
|
77
|
+
## Why This Architecture Specifically?
|
|
78
|
+
|
|
79
|
+
Observable state, events, and well-documented APIs aren't arbitrary choices. They're specifically what makes things *conversational* in both senses:
|
|
80
|
+
|
|
81
|
+
- **Observable state** means anything can watch anything else and react. Debugging, analytics, reporting, reactive UI patterns, data providers for React — all fall out naturally. An AI agent can monitor state to understand what's happening.
|
|
82
|
+
- **Events** are the necessary primitive for JavaScript's async event loop, and they're also how components announce things to the rest of the system without needing to know who's listening. An AI agent can subscribe to events to understand what just happened.
|
|
83
|
+
- **Introspection** means you never have to remember the specifics. You only need to know the philosophy, and the container will teach you the rest. This is true whether "you" is a human in a REPL or an AI agent with tool access.
|
|
84
|
+
|
|
85
|
+
The fact that you can start from a single `container` object and learn everything it provides — how to interact with it, how to use it, what to expect from it — means the philosophy *is* the documentation. Know the pattern, and the system reveals itself.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Random Principles
|
|
2
|
+
|
|
3
|
+
- I've built so many different client / server applications with JavaScript ( and many other languages ). I've reinvented way too many things that could have been solved once. The clearest example of this pain is a poorly structured dockerfile, e.g. one that reinstalls core os dependencies when you change an html file.
|
|
4
|
+
|
|
5
|
+
- Nearly every application, I've structured as a "boss with liuetenants" so to speak, that everything else talked to. The boss, the liuetenants, had some kind of state. Events occur during their operations. Sometimes these events need to be triggered. Overtime, core patterns emerged, somewhat encouraged by popular frameworks in the shape they took or names I gave them.
|
|
6
|
+
|
|
7
|
+
- In building Luca, we want to provide ways to ultimately narrow the range of possible outputs a first time developer, or AI assistant, might produce when asked to build something using a Luca `container` and its components. The names themselves of the helpers, `clients`, `servers`, `features` already begin to describe their shape, purpose, where their code should live, etc. By going through the extra effort of building essentially a wrapper class, with descriptive interfaces, the developer will ultimately be delivering code that is easier to work with, and re-use in future efforts.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
reusable: true
|
|
3
|
+
lastRanAt: 1772162827313
|
|
4
|
+
durationMs: 278913
|
|
5
|
+
outputTokens: 552
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# Code Audit
|
|
10
|
+
|
|
11
|
+
Do an audit of the code in the following folders:
|
|
12
|
+
|
|
13
|
+
- src/**/features/**
|
|
14
|
+
- src/**/clients/**
|
|
15
|
+
- src/clients/**
|
|
16
|
+
- src/servers/**
|
|
17
|
+
- src/commands/**
|
|
18
|
+
|
|
19
|
+
Ignore the fs, proc, git features in src/node/features. These are a core abstraction that wraps the underlying ones provided by node or bun, so it is expected they would use child_process, fs, etc. In general, if the feature you're looking at is intended to be wrapping a core runtime / os primitive, it is probably ok ( that's the point of the feature )
|
|
20
|
+
|
|
21
|
+
if a completely unrelated feature is using the fs or path module, or Bun unguarded, then that's probably an issue.
|
|
22
|
+
|
|
23
|
+
Look for instances of the following, but don't fix them yet.
|
|
24
|
+
|
|
25
|
+
- using file system directly, instead of this.container.fs ( except the file system feature itself )
|
|
26
|
+
- using the path module functions instead of this.container.paths.resolve ( with the exception of fileManager, where it is ok )
|
|
27
|
+
- reinventing the wheel in general instead of using functionality already provided by the container
|
|
28
|
+
- anything that would break compatibility with node.js instead of Bun. make sure you wrap it in a guard (if this.container.isBun)
|
|
29
|
+
|
|
30
|
+
Save the results of your audit in docs/reports/code-audit-results.md
|
|
31
|
+
|
|
32
|
+
If this file already exists, read it first, and note cases where items persist.
|
|
33
|
+
|
|
34
|
+
The next step will be me reviewing the audit, providing commentary, and advising you what to fix
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
target: claude
|
|
3
|
+
reusable: true
|
|
4
|
+
repeatable: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# MCP Test: Build a Command
|
|
8
|
+
|
|
9
|
+
You are in an empty luca project. The `luca` CLI is available and you have a `luca-sandbox` MCP server connected.
|
|
10
|
+
|
|
11
|
+
## Task
|
|
12
|
+
|
|
13
|
+
Create a luca command called `greet` in `commands/greet.ts` that:
|
|
14
|
+
|
|
15
|
+
1. Accepts a `--name` flag (string, defaults to "world")
|
|
16
|
+
2. Accepts a `--shout` flag (boolean, defaults to false)
|
|
17
|
+
3. Prints "Hello, {name}!" to stdout
|
|
18
|
+
4. If `--shout` is true, uppercases the entire message
|
|
19
|
+
|
|
20
|
+
The command should be runnable via `luca greet --name Jon --shout`.
|
|
21
|
+
|
|
22
|
+
## Rules
|
|
23
|
+
|
|
24
|
+
- Do not install any npm packages
|
|
25
|
+
- Import only from `@soederpop/luca`
|
|
26
|
+
- Use the MCP tools to learn the command pattern before writing code
|
|
27
|
+
- After creating the file, verify it works by running `luca greet --name Test`
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Assistant systemPrompt Bug Fix Verification
|
|
2
|
+
|
|
3
|
+
The bug: class field initializers (`private _systemPrompt: string = ''`) on Feature subclasses
|
|
4
|
+
overwrite values set during `afterInitialize()` because ES2022 field initializers run AFTER `super()` returns.
|
|
5
|
+
|
|
6
|
+
Fix: use `declare private _systemPrompt: string` which emits no JavaScript, so afterInitialize values persist.
|
|
7
|
+
|
|
8
|
+
## Test
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
const assistant = container.feature('assistant', {
|
|
12
|
+
folder: '/Users/jon/@soederpop/commands/voice/assistant'
|
|
13
|
+
})
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
systemPrompt should contain the CORE.md content (not be empty):
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
console.log("systemPrompt length:", assistant.systemPrompt.length)
|
|
20
|
+
console.log("contains omar:", assistant.systemPrompt.toLowerCase().includes("omar"))
|
|
21
|
+
console.log("first 80 chars:", assistant.systemPrompt.slice(0, 80))
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Tools should have been loaded from tools.ts:
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
console.log("tools loaded:", Object.keys(assistant.tools))
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Starting the assistant should pass the systemPrompt into the conversation:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
await assistant.start()
|
|
34
|
+
const systemMsg = assistant.conversation.messages[0]
|
|
35
|
+
console.log("conversation has system message:", systemMsg.role === "system")
|
|
36
|
+
console.log("system message has content:", systemMsg.content.length > 0)
|
|
37
|
+
console.log("system message contains omar:", systemMsg.content.toLowerCase().includes("omar"))
|
|
38
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Attach Pattern
|
|
2
|
+
|
|
3
|
+
Here is some problematic code:
|
|
4
|
+
|
|
5
|
+
```ts skip
|
|
6
|
+
const { container } = context
|
|
7
|
+
const { VoiceRouter } = await import(resolve(import.meta.dir, 'voice/router.ts'))
|
|
8
|
+
container.features.register('voiceRouter', VoiceRouter as any)
|
|
9
|
+
const router = container.feature('voiceRouter' as any, { enable: true }) as InstanceType<typeof VoiceRouter>
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
I'd rather see
|
|
13
|
+
|
|
14
|
+
```ts skip
|
|
15
|
+
// we know since we're inside a command this has to be our path anyway, relative to the container's cwd is how we're discovered
|
|
16
|
+
await import(container.paths.resolve('commands','voice','router.ts')).then(({ VoiceRouter }) => container.use(VoiceRouter))
|
|
17
|
+
```
|
|
18
|
+
|
|
@@ -0,0 +1,391 @@
|
|
|
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')`
|