luca 2.0.0 → 3.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/.github/workflows/release.yaml +170 -0
- package/AGENTS.md +99 -0
- package/CLAUDE.md +123 -0
- package/CNAME +1 -0
- package/README.md +275 -9
- package/RUNME.md +56 -0
- package/assistants/codingAssistant/ABOUT.md +5 -0
- package/assistants/codingAssistant/CORE.md +33 -0
- package/assistants/codingAssistant/hooks.ts +21 -0
- package/assistants/codingAssistant/tools.ts +12 -0
- package/assistants/inkbot/ABOUT.md +16 -0
- package/assistants/inkbot/CORE.md +330 -0
- package/assistants/inkbot/hooks.ts +6 -0
- package/assistants/inkbot/tools.ts +53 -0
- package/assistants/researcher/ABOUT.md +5 -0
- package/assistants/researcher/CORE.md +46 -0
- package/assistants/researcher/hooks.ts +16 -0
- package/assistants/researcher/tools.ts +237 -0
- package/bun.lock +2667 -0
- package/bunfig.toml +3 -0
- package/commands/audit-docs.ts +740 -0
- package/commands/build-bootstrap.ts +117 -0
- package/commands/build-python-bridge.ts +42 -0
- package/commands/build-scaffolds.ts +175 -0
- package/commands/bundle-consumer-project.ts +521 -0
- package/commands/generate-api-docs.ts +114 -0
- package/commands/inkbot.ts +874 -0
- package/commands/release.ts +80 -0
- package/commands/try-all-challenges.ts +543 -0
- package/commands/try-challenge.ts +100 -0
- package/dist/agi/container.server.d.ts +63 -0
- package/dist/agi/container.server.d.ts.map +1 -0
- package/dist/agi/endpoints/ask.d.ts +20 -0
- package/dist/agi/endpoints/ask.d.ts.map +1 -0
- package/dist/agi/endpoints/conversations/[id].d.ts +27 -0
- package/dist/agi/endpoints/conversations/[id].d.ts.map +1 -0
- package/dist/agi/endpoints/conversations.d.ts +18 -0
- package/dist/agi/endpoints/conversations.d.ts.map +1 -0
- package/dist/agi/endpoints/experts.d.ts +8 -0
- package/dist/agi/endpoints/experts.d.ts.map +1 -0
- package/dist/agi/feature.d.ts +9 -0
- package/dist/agi/feature.d.ts.map +1 -0
- package/dist/agi/features/assistant.d.ts +509 -0
- package/dist/agi/features/assistant.d.ts.map +1 -0
- package/dist/agi/features/assistants-manager.d.ts +236 -0
- package/dist/agi/features/assistants-manager.d.ts.map +1 -0
- package/dist/agi/features/autonomous-assistant.d.ts +281 -0
- package/dist/agi/features/autonomous-assistant.d.ts.map +1 -0
- package/dist/agi/features/browser-use.d.ts +479 -0
- package/dist/agi/features/browser-use.d.ts.map +1 -0
- package/dist/agi/features/claude-code.d.ts +824 -0
- package/dist/agi/features/claude-code.d.ts.map +1 -0
- package/dist/agi/features/conversation-history.d.ts +245 -0
- package/dist/agi/features/conversation-history.d.ts.map +1 -0
- package/dist/agi/features/conversation.d.ts +464 -0
- package/dist/agi/features/conversation.d.ts.map +1 -0
- package/dist/agi/features/docs-reader.d.ts +72 -0
- package/dist/agi/features/docs-reader.d.ts.map +1 -0
- package/dist/agi/features/file-tools.d.ts +110 -0
- package/dist/agi/features/file-tools.d.ts.map +1 -0
- package/dist/agi/features/luca-coder.d.ts +323 -0
- package/dist/agi/features/luca-coder.d.ts.map +1 -0
- package/dist/agi/features/openai-codex.d.ts +381 -0
- package/dist/agi/features/openai-codex.d.ts.map +1 -0
- package/dist/agi/features/openapi.d.ts +200 -0
- package/dist/agi/features/openapi.d.ts.map +1 -0
- package/dist/agi/features/skills-library.d.ts +167 -0
- package/dist/agi/features/skills-library.d.ts.map +1 -0
- package/dist/agi/index.d.ts +5 -0
- package/dist/agi/index.d.ts.map +1 -0
- package/dist/agi/lib/interceptor-chain.d.ts +44 -0
- package/dist/agi/lib/interceptor-chain.d.ts.map +1 -0
- package/dist/agi/lib/token-counter.d.ts +13 -0
- package/dist/agi/lib/token-counter.d.ts.map +1 -0
- package/dist/bootstrap/generated.d.ts +5 -0
- package/dist/bootstrap/generated.d.ts.map +1 -0
- package/dist/browser.d.ts +12 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/bus.d.ts +29 -0
- package/dist/bus.d.ts.map +1 -0
- package/dist/cli/build-info.d.ts +4 -0
- package/dist/cli/build-info.d.ts.map +1 -0
- package/dist/cli/cli.d.ts +3 -12
- package/dist/cli/cli.d.ts.map +1 -0
- package/dist/client.d.ts +60 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/clients/civitai/index.d.ts +472 -0
- package/dist/clients/civitai/index.d.ts.map +1 -0
- package/dist/clients/client-template.d.ts +30 -0
- package/dist/clients/client-template.d.ts.map +1 -0
- package/dist/clients/comfyui/index.d.ts +281 -0
- package/dist/clients/comfyui/index.d.ts.map +1 -0
- package/dist/clients/elevenlabs/index.d.ts +197 -0
- package/dist/clients/elevenlabs/index.d.ts.map +1 -0
- package/dist/clients/graph.d.ts +64 -0
- package/dist/clients/graph.d.ts.map +1 -0
- package/dist/clients/openai/index.d.ts +247 -0
- package/dist/clients/openai/index.d.ts.map +1 -0
- package/dist/clients/rest.d.ts +92 -0
- package/dist/clients/rest.d.ts.map +1 -0
- package/dist/clients/supabase/index.d.ts +176 -0
- package/dist/clients/supabase/index.d.ts.map +1 -0
- package/dist/clients/websocket.d.ts +127 -0
- package/dist/clients/websocket.d.ts.map +1 -0
- package/dist/command.d.ts +163 -0
- package/dist/command.d.ts.map +1 -0
- package/dist/commands/bootstrap.d.ts +20 -0
- package/dist/commands/bootstrap.d.ts.map +1 -0
- package/dist/commands/chat.d.ts +37 -0
- package/dist/commands/chat.d.ts.map +1 -0
- package/dist/commands/code.d.ts +28 -0
- package/dist/commands/code.d.ts.map +1 -0
- package/dist/commands/console.d.ts +22 -0
- package/dist/commands/console.d.ts.map +1 -0
- package/dist/commands/describe.d.ts +50 -0
- package/dist/commands/describe.d.ts.map +1 -0
- package/dist/commands/eval.d.ts +23 -0
- package/dist/commands/eval.d.ts.map +1 -0
- package/dist/commands/help.d.ts +25 -0
- package/dist/commands/help.d.ts.map +1 -0
- package/dist/commands/index.d.ts +18 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/introspect.d.ts +24 -0
- package/dist/commands/introspect.d.ts.map +1 -0
- package/dist/commands/mcp.d.ts +35 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/prompt.d.ts +38 -0
- package/dist/commands/prompt.d.ts.map +1 -0
- package/dist/commands/run.d.ts +24 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/sandbox-mcp.d.ts +34 -0
- package/dist/commands/sandbox-mcp.d.ts.map +1 -0
- package/dist/commands/save-api-docs.d.ts +21 -0
- package/dist/commands/save-api-docs.d.ts.map +1 -0
- package/dist/commands/scaffold.d.ts +24 -0
- package/dist/commands/scaffold.d.ts.map +1 -0
- package/dist/commands/select.d.ts +22 -0
- package/dist/commands/select.d.ts.map +1 -0
- package/dist/commands/serve.d.ts +29 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/container-describer.d.ts +144 -0
- package/dist/container-describer.d.ts.map +1 -0
- package/dist/container.d.ts +451 -0
- package/dist/container.d.ts.map +1 -0
- package/dist/endpoint.d.ts +113 -0
- package/dist/endpoint.d.ts.map +1 -0
- package/dist/feature.d.ts +47 -0
- package/dist/feature.d.ts.map +1 -0
- package/dist/graft.d.ts +29 -0
- package/dist/graft.d.ts.map +1 -0
- package/dist/hash-object.d.ts +8 -0
- package/dist/hash-object.d.ts.map +1 -0
- package/dist/helper.d.ts +209 -0
- package/dist/helper.d.ts.map +1 -0
- package/dist/introspection/generated.node.d.ts +44623 -0
- package/dist/introspection/generated.node.d.ts.map +1 -0
- package/dist/introspection/generated.web.d.ts +1412 -0
- package/dist/introspection/generated.web.d.ts.map +1 -0
- package/dist/introspection/index.d.ts +156 -0
- package/dist/introspection/index.d.ts.map +1 -0
- package/dist/introspection/scan.d.ts +147 -0
- package/dist/introspection/scan.d.ts.map +1 -0
- package/dist/node/container.d.ts +256 -0
- package/dist/node/container.d.ts.map +1 -0
- package/dist/node/feature.d.ts +9 -0
- package/dist/node/feature.d.ts.map +1 -0
- package/dist/node/features/container-link.d.ts +213 -0
- package/dist/node/features/container-link.d.ts.map +1 -0
- package/dist/node/features/content-db.d.ts +354 -0
- package/dist/node/features/content-db.d.ts.map +1 -0
- package/dist/node/features/disk-cache.d.ts +236 -0
- package/dist/node/features/disk-cache.d.ts.map +1 -0
- package/dist/node/features/dns.d.ts +511 -0
- package/dist/node/features/dns.d.ts.map +1 -0
- package/dist/node/features/docker.d.ts +485 -0
- package/dist/node/features/docker.d.ts.map +1 -0
- package/dist/node/features/downloader.d.ts +73 -0
- package/dist/node/features/downloader.d.ts.map +1 -0
- package/dist/node/features/figlet-fonts.d.ts +4 -0
- package/dist/node/features/figlet-fonts.d.ts.map +1 -0
- package/dist/node/features/file-manager.d.ts +177 -0
- package/dist/node/features/file-manager.d.ts.map +1 -0
- package/dist/node/features/fs.d.ts +635 -0
- package/dist/node/features/fs.d.ts.map +1 -0
- package/dist/node/features/git.d.ts +329 -0
- package/dist/node/features/git.d.ts.map +1 -0
- package/dist/node/features/google-auth.d.ts +200 -0
- package/dist/node/features/google-auth.d.ts.map +1 -0
- package/dist/node/features/google-calendar.d.ts +194 -0
- package/dist/node/features/google-calendar.d.ts.map +1 -0
- package/dist/node/features/google-docs.d.ts +138 -0
- package/dist/node/features/google-docs.d.ts.map +1 -0
- package/dist/node/features/google-drive.d.ts +202 -0
- package/dist/node/features/google-drive.d.ts.map +1 -0
- package/dist/node/features/google-mail.d.ts +221 -0
- package/dist/node/features/google-mail.d.ts.map +1 -0
- package/dist/node/features/google-sheets.d.ts +157 -0
- package/dist/node/features/google-sheets.d.ts.map +1 -0
- package/dist/node/features/grep.d.ts +207 -0
- package/dist/node/features/grep.d.ts.map +1 -0
- package/dist/node/features/helpers.d.ts +236 -0
- package/dist/node/features/helpers.d.ts.map +1 -0
- package/dist/node/features/ink.d.ts +332 -0
- package/dist/node/features/ink.d.ts.map +1 -0
- package/dist/node/features/ipc-socket.d.ts +298 -0
- package/dist/node/features/ipc-socket.d.ts.map +1 -0
- package/dist/node/features/json-tree.d.ts +140 -0
- package/dist/node/features/json-tree.d.ts.map +1 -0
- package/dist/node/features/networking.d.ts +373 -0
- package/dist/node/features/networking.d.ts.map +1 -0
- package/dist/node/features/nlp.d.ts +125 -0
- package/dist/node/features/nlp.d.ts.map +1 -0
- package/dist/node/features/opener.d.ts +93 -0
- package/dist/node/features/opener.d.ts.map +1 -0
- package/dist/node/features/os.d.ts +168 -0
- package/dist/node/features/os.d.ts.map +1 -0
- package/dist/node/features/package-finder.d.ts +419 -0
- package/dist/node/features/package-finder.d.ts.map +1 -0
- package/dist/node/features/postgres.d.ts +173 -0
- package/dist/node/features/postgres.d.ts.map +1 -0
- package/dist/node/features/proc.d.ts +285 -0
- package/dist/node/features/proc.d.ts.map +1 -0
- package/dist/node/features/process-manager.d.ts +427 -0
- package/dist/node/features/process-manager.d.ts.map +1 -0
- package/dist/node/features/python.d.ts +477 -0
- package/dist/node/features/python.d.ts.map +1 -0
- package/dist/node/features/redis.d.ts +247 -0
- package/dist/node/features/redis.d.ts.map +1 -0
- package/dist/node/features/repl.d.ts +84 -0
- package/dist/node/features/repl.d.ts.map +1 -0
- package/dist/node/features/runpod.d.ts +527 -0
- package/dist/node/features/runpod.d.ts.map +1 -0
- package/dist/node/features/secure-shell.d.ts +145 -0
- package/dist/node/features/secure-shell.d.ts.map +1 -0
- package/dist/node/features/semantic-search.d.ts +207 -0
- package/dist/node/features/semantic-search.d.ts.map +1 -0
- package/dist/node/features/sqlite.d.ts +180 -0
- package/dist/node/features/sqlite.d.ts.map +1 -0
- package/dist/node/features/telegram.d.ts +173 -0
- package/dist/node/features/telegram.d.ts.map +1 -0
- package/dist/node/features/transpiler.d.ts +51 -0
- package/dist/node/features/transpiler.d.ts.map +1 -0
- package/dist/node/features/tts.d.ts +108 -0
- package/dist/node/features/tts.d.ts.map +1 -0
- package/dist/node/features/ui.d.ts +562 -0
- package/dist/node/features/ui.d.ts.map +1 -0
- package/dist/node/features/vault.d.ts +90 -0
- package/dist/node/features/vault.d.ts.map +1 -0
- package/dist/node/features/vm.d.ts +285 -0
- package/dist/node/features/vm.d.ts.map +1 -0
- package/dist/node/features/yaml-tree.d.ts +118 -0
- package/dist/node/features/yaml-tree.d.ts.map +1 -0
- package/dist/node/features/yaml.d.ts +127 -0
- package/dist/node/features/yaml.d.ts.map +1 -0
- package/dist/node.d.ts +67 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/python/generated.d.ts +2 -0
- package/dist/python/generated.d.ts.map +1 -0
- package/dist/react/index.d.ts +36 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/registry.d.ts +97 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/scaffolds/generated.d.ts +13 -0
- package/dist/scaffolds/generated.d.ts.map +1 -0
- package/dist/scaffolds/template.d.ts +11 -0
- package/dist/scaffolds/template.d.ts.map +1 -0
- package/dist/schemas/base.d.ts +254 -0
- package/dist/schemas/base.d.ts.map +1 -0
- package/dist/selector.d.ts +130 -0
- package/dist/selector.d.ts.map +1 -0
- package/dist/server.d.ts +89 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/servers/express.d.ts +104 -0
- package/dist/servers/express.d.ts.map +1 -0
- package/dist/servers/mcp.d.ts +201 -0
- package/dist/servers/mcp.d.ts.map +1 -0
- package/dist/servers/socket.d.ts +121 -0
- package/dist/servers/socket.d.ts.map +1 -0
- package/dist/state.d.ts +24 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/web/clients/socket.d.ts +37 -0
- package/dist/web/clients/socket.d.ts.map +1 -0
- package/dist/web/container.d.ts +55 -0
- package/dist/web/container.d.ts.map +1 -0
- package/dist/web/extension.d.ts +4 -0
- package/dist/web/extension.d.ts.map +1 -0
- package/dist/web/feature.d.ts +8 -0
- package/dist/web/feature.d.ts.map +1 -0
- package/dist/web/features/asset-loader.d.ts +35 -0
- package/dist/web/features/asset-loader.d.ts.map +1 -0
- package/dist/web/features/container-link.d.ts +167 -0
- package/dist/web/features/container-link.d.ts.map +1 -0
- package/dist/web/features/esbuild.d.ts +51 -0
- package/dist/web/features/esbuild.d.ts.map +1 -0
- package/dist/web/features/helpers.d.ts +140 -0
- package/dist/web/features/helpers.d.ts.map +1 -0
- package/dist/web/features/network.d.ts +69 -0
- package/dist/web/features/network.d.ts.map +1 -0
- package/dist/web/features/speech.d.ts +71 -0
- package/dist/web/features/speech.d.ts.map +1 -0
- package/dist/web/features/vault.d.ts +62 -0
- package/dist/web/features/vault.d.ts.map +1 -0
- package/dist/web/features/vm.d.ts +48 -0
- package/dist/web/features/vm.d.ts.map +1 -0
- package/dist/web/features/voice-recognition.d.ts +96 -0
- package/dist/web/features/voice-recognition.d.ts.map +1 -0
- package/dist/web/shims/isomorphic-vm.d.ts +22 -0
- package/dist/web/shims/isomorphic-vm.d.ts.map +1 -0
- package/index.html +1457 -0
- package/index.ts +1 -0
- package/install.sh +84 -0
- package/luca.cli.ts +16 -0
- package/luca.console.ts +9 -0
- package/main.py +6 -0
- package/package.json +219 -58
- package/public/index.html +1457 -0
- package/public/slides-ai-native.html +902 -0
- package/public/slides-intro.html +974 -0
- package/pyproject.toml +7 -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/using-assistant-with-mcp.ts +555 -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 +11 -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/scaffold.ts +391 -0
- package/scripts/scratch.ts +15 -0
- package/scripts/stamp-build.sh +12 -0
- package/scripts/test-assistant-hooks.ts +13 -0
- package/scripts/test-docs-reader.ts +10 -0
- package/scripts/test-linux-binary.sh +80 -0
- package/scripts/update-introspection-data.ts +58 -0
- package/src/agi/README.md +14 -0
- package/src/agi/container.server.ts +156 -0
- package/src/agi/feature.ts +13 -0
- package/src/agi/features/agent-memory.ts +694 -0
- package/src/agi/features/assistant.ts +1653 -0
- package/src/agi/features/assistants-manager.ts +534 -0
- package/src/agi/features/autonomous-assistant.ts +431 -0
- package/src/agi/features/browser-use.ts +672 -0
- package/src/agi/features/claude-code.ts +1584 -0
- package/src/agi/features/coding-tools.ts +175 -0
- package/src/agi/features/conversation-history.ts +672 -0
- package/src/agi/features/conversation.ts +1494 -0
- package/src/agi/features/docs-reader.ts +167 -0
- package/src/agi/features/file-tools.ts +340 -0
- package/src/agi/features/luca-coder.ts +641 -0
- package/src/agi/features/mcp-bridge.ts +532 -0
- package/src/agi/features/openai-codex.ts +651 -0
- package/src/agi/features/openapi.ts +445 -0
- package/src/agi/features/skills-library.ts +557 -0
- package/src/agi/index.ts +6 -0
- package/src/agi/lib/interceptor-chain.ts +89 -0
- package/src/agi/lib/token-counter.ts +202 -0
- package/src/bootstrap/generated.ts +9791 -0
- package/src/browser.ts +25 -0
- package/src/bus.ts +122 -0
- package/src/cli/build-info.ts +4 -0
- package/src/cli/cli.ts +355 -0
- package/src/client.ts +170 -0
- package/src/clients/civitai/index.ts +537 -0
- package/src/clients/client-template.ts +41 -0
- package/src/clients/comfyui/index.ts +604 -0
- package/src/clients/elevenlabs/index.ts +317 -0
- package/src/clients/graph.ts +87 -0
- package/src/clients/openai/index.ts +456 -0
- package/src/clients/rest.ts +207 -0
- package/src/clients/supabase/index.ts +357 -0
- package/src/clients/voicebox/index.ts +300 -0
- package/src/clients/websocket.ts +251 -0
- package/src/command.ts +506 -0
- package/src/commands/bootstrap.ts +244 -0
- package/src/commands/chat.ts +309 -0
- package/src/commands/code.ts +371 -0
- package/src/commands/console.ts +189 -0
- package/src/commands/describe.ts +243 -0
- package/src/commands/eval.ts +67 -0
- package/src/commands/help.ts +240 -0
- package/src/commands/index.ts +19 -0
- package/src/commands/introspect.ts +218 -0
- package/src/commands/mcp.ts +64 -0
- package/src/commands/prompt.ts +1014 -0
- package/src/commands/run.ts +278 -0
- package/src/commands/sandbox-mcp.ts +343 -0
- package/src/commands/save-api-docs.ts +51 -0
- package/src/commands/scaffold.ts +225 -0
- package/src/commands/select.ts +99 -0
- package/src/commands/serve.ts +208 -0
- package/src/container-describer.ts +1091 -0
- package/src/container.ts +1199 -0
- package/src/endpoint.ts +365 -0
- package/src/entity.ts +173 -0
- package/src/feature.ts +118 -0
- package/src/graft.ts +181 -0
- package/src/hash-object.ts +97 -0
- package/src/helper.ts +849 -0
- package/src/introspection/generated.agi.ts +41200 -0
- package/src/introspection/generated.node.ts +28773 -0
- package/src/introspection/generated.web.ts +2272 -0
- package/src/introspection/index.ts +296 -0
- package/src/introspection/scan.ts +1136 -0
- package/src/node/container.ts +409 -0
- package/src/node/feature.ts +13 -0
- package/src/node/features/container-link.ts +559 -0
- package/src/node/features/content-db.ts +849 -0
- package/src/node/features/disk-cache.ts +388 -0
- package/src/node/features/display-result.ts +57 -0
- package/src/node/features/dns.ts +669 -0
- package/src/node/features/docker.ts +921 -0
- package/src/node/features/downloader.ts +79 -0
- package/src/node/features/figlet-fonts.ts +600 -0
- package/src/node/features/file-manager.ts +535 -0
- package/src/node/features/fs.ts +1050 -0
- package/src/node/features/git.ts +592 -0
- package/src/node/features/google-auth.ts +504 -0
- package/src/node/features/google-calendar.ts +306 -0
- package/src/node/features/google-docs.ts +412 -0
- package/src/node/features/google-drive.ts +346 -0
- package/src/node/features/google-mail.ts +540 -0
- package/src/node/features/google-sheets.ts +286 -0
- package/src/node/features/grep.ts +427 -0
- package/src/node/features/helpers.ts +762 -0
- package/src/node/features/ink.ts +490 -0
- package/src/node/features/ipc-socket.ts +649 -0
- package/src/node/features/json-tree.ts +170 -0
- package/src/node/features/networking.ts +961 -0
- package/src/node/features/nlp.ts +212 -0
- package/src/node/features/opener.ts +180 -0
- package/src/node/features/os.ts +403 -0
- package/src/node/features/package-finder.ts +540 -0
- package/src/node/features/postgres.ts +289 -0
- package/src/node/features/proc.ts +503 -0
- package/src/node/features/process-manager.ts +844 -0
- package/src/node/features/python.ts +912 -0
- package/src/node/features/redis.ts +446 -0
- package/src/node/features/repl.ts +212 -0
- package/src/node/features/runpod.ts +811 -0
- package/src/node/features/secure-shell.ts +261 -0
- package/src/node/features/semantic-search.ts +935 -0
- package/src/node/features/sqlite.ts +289 -0
- package/src/node/features/telegram.ts +343 -0
- package/src/node/features/transpiler.ts +160 -0
- package/src/node/features/tts.ts +185 -0
- package/src/node/features/ui.ts +791 -0
- package/src/node/features/vault.ts +153 -0
- package/src/node/features/vm.ts +462 -0
- package/src/node/features/yaml-tree.ts +148 -0
- package/src/node/features/yaml.ts +133 -0
- package/src/node.ts +76 -0
- package/src/python/bridge.py +220 -0
- package/src/python/generated.ts +226 -0
- package/src/react/index.ts +175 -0
- package/src/registry.ts +210 -0
- package/src/scaffolds/generated.ts +1814 -0
- package/src/scaffolds/template.ts +46 -0
- package/src/schemas/base.ts +296 -0
- package/src/selector.ts +352 -0
- package/src/server.ts +229 -0
- package/src/servers/express.ts +283 -0
- package/src/servers/mcp.ts +802 -0
- package/src/servers/socket.ts +258 -0
- package/src/state.ts +101 -0
- package/src/web/clients/socket.ts +99 -0
- package/src/web/container.ts +75 -0
- package/src/web/extension.ts +30 -0
- package/src/web/feature.ts +12 -0
- package/src/web/features/asset-loader.ts +72 -0
- package/src/web/features/container-link.ts +382 -0
- package/src/web/features/esbuild.ts +93 -0
- package/src/web/features/helpers.ts +291 -0
- package/src/web/features/network.ts +85 -0
- package/src/web/features/speech.ts +104 -0
- package/src/web/features/vault.ts +207 -0
- package/src/web/features/vm.ts +85 -0
- package/src/web/features/voice-recognition.ts +161 -0
- package/src/web/shims/isomorphic-vm.ts +149 -0
- package/tsconfig.build.json +12 -0
- package/tsconfig.json +58 -0
- package/uv.lock +8 -0
- package/LICENSE +0 -21
- package/dist/cli/cli.js +0 -48
- package/dist/cli/common.d.ts +0 -2
- package/dist/cli/common.js +0 -6
- package/dist/cli/index.d.ts +0 -2
- package/dist/cli/index.js +0 -5
- package/dist/cli/run.d.ts +0 -1
- package/dist/cli/run.js +0 -38
- package/dist/core/index.d.ts +0 -4
- package/dist/core/index.js +0 -32
- package/dist/core/read.d.ts +0 -2
- package/dist/core/read.js +0 -29
- package/dist/core/request.d.ts +0 -1
- package/dist/core/request.js +0 -2
- package/dist/core/write.d.ts +0 -2
- package/dist/core/write.js +0 -21
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -5
- package/dist/utils/common.d.ts +0 -9
- package/dist/utils/common.js +0 -57
- package/dist/utils/consts.d.ts +0 -3
- package/dist/utils/consts.js +0 -11
- package/dist/utils/dict.d.ts +0 -1
- package/dist/utils/dict.js +0 -7
- package/dist/utils/index.d.ts +0 -5
- package/dist/utils/index.js +0 -21
- package/dist/utils/log.d.ts +0 -1
- package/dist/utils/log.js +0 -5
- package/dist/utils/types.d.ts +0 -1
- package/dist/utils/types.js +0 -2
- package/dist/utils/utils.test.d.ts +0 -1
- package/dist/utils/utils.test.js +0 -7
package/src/browser.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export * from './web/container.js'
|
|
2
|
+
import { WebContainer } from './web/container.js'
|
|
3
|
+
import './introspection/generated.web.js'
|
|
4
|
+
|
|
5
|
+
const container = new WebContainer({})
|
|
6
|
+
|
|
7
|
+
if (typeof window !== 'undefined') {
|
|
8
|
+
;(window as any).luca = container
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default container
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Returns the singleton container instance.
|
|
15
|
+
* LLMs love to hallucinate this function — so we provide it, but warn.
|
|
16
|
+
* If you need a separate container, use `container.subcontainer()`.
|
|
17
|
+
*/
|
|
18
|
+
export function createContainer() {
|
|
19
|
+
console.warn(
|
|
20
|
+
'[luca] createContainer() is unnecessary — import the default export instead.\n' +
|
|
21
|
+
' `import container from "luca"`\n' +
|
|
22
|
+
' For a separate instance, use container.subcontainer().'
|
|
23
|
+
)
|
|
24
|
+
return container
|
|
25
|
+
}
|
package/src/bus.ts
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
export type EventMap = Record<string, any[]>;
|
|
2
|
+
|
|
3
|
+
type Listener<Args extends any[] = any[]> = (...args: Args) => void;
|
|
4
|
+
type WildcardListener = (event: string, ...args: any[]) => void;
|
|
5
|
+
|
|
6
|
+
export interface EventStats {
|
|
7
|
+
event: string;
|
|
8
|
+
fireCount: number;
|
|
9
|
+
lastFiredAt: number | null;
|
|
10
|
+
timestamps: number[];
|
|
11
|
+
firesPerMinute: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class Bus<T extends EventMap = EventMap> {
|
|
15
|
+
private events: Map<string, Listener[]>;
|
|
16
|
+
private wildcardListeners: WildcardListener[];
|
|
17
|
+
private stats: Map<string, { fireCount: number; lastFiredAt: number | null; timestamps: number[] }>;
|
|
18
|
+
|
|
19
|
+
constructor() {
|
|
20
|
+
this.events = new Map();
|
|
21
|
+
this.wildcardListeners = [];
|
|
22
|
+
this.stats = new Map();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private recordEmit(event: string): void {
|
|
26
|
+
const now = Date.now();
|
|
27
|
+
const existing = this.stats.get(event) || { fireCount: 0, lastFiredAt: null, timestamps: [] };
|
|
28
|
+
existing.fireCount++;
|
|
29
|
+
existing.lastFiredAt = now;
|
|
30
|
+
existing.timestamps.push(now);
|
|
31
|
+
this.stats.set(event, existing);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private computeFiresPerMinute(timestamps: number[]): number {
|
|
35
|
+
if (timestamps.length < 2) return 0;
|
|
36
|
+
const now = Date.now();
|
|
37
|
+
const oneMinuteAgo = now - 60_000;
|
|
38
|
+
const recent = timestamps.filter(t => t >= oneMinuteAgo);
|
|
39
|
+
return recent.length;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
getEventStats<E extends string & keyof T>(event: E): EventStats {
|
|
43
|
+
const raw = this.stats.get(event) || { fireCount: 0, lastFiredAt: null, timestamps: [] };
|
|
44
|
+
return {
|
|
45
|
+
event,
|
|
46
|
+
fireCount: raw.fireCount,
|
|
47
|
+
lastFiredAt: raw.lastFiredAt,
|
|
48
|
+
timestamps: raw.timestamps,
|
|
49
|
+
firesPerMinute: this.computeFiresPerMinute(raw.timestamps),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
get history(): EventStats[] {
|
|
54
|
+
return Array.from(this.stats.keys()).map(event => this.getEventStats(event as any));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
get firedEvents(): string[] {
|
|
58
|
+
return Array.from(this.stats.keys());
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async waitFor<E extends string & keyof T>(event: E): Promise<T[E]> {
|
|
62
|
+
return new Promise(resolve => {
|
|
63
|
+
this.once(event, resolve as any);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
emit<E extends string & keyof T>(event: E, ...args: T[E]): void {
|
|
68
|
+
this.recordEmit(event);
|
|
69
|
+
const listeners = this.events.get(event);
|
|
70
|
+
if (listeners) {
|
|
71
|
+
listeners.forEach(listener => listener(...args));
|
|
72
|
+
}
|
|
73
|
+
this.wildcardListeners.forEach(listener => listener(event, ...args));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
on(event: '*', listener: WildcardListener): void
|
|
77
|
+
on<E extends string & keyof T>(event: E, listener: (...args: T[E]) => void): void
|
|
78
|
+
on<E extends string & keyof T>(event: E | '*', listener: any): void {
|
|
79
|
+
if (event === '*') {
|
|
80
|
+
this.wildcardListeners.push(listener);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const listeners = this.events.get(event) || [];
|
|
84
|
+
listeners.push(listener as Listener);
|
|
85
|
+
this.events.set(event, listeners);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
once<E extends string & keyof T>(event: E, listener: (...args: T[E]) => void): void {
|
|
89
|
+
const onceListener: Listener = (...args: any[]) => {
|
|
90
|
+
(listener as Listener)(...args);
|
|
91
|
+
this.off(event, onceListener as any);
|
|
92
|
+
};
|
|
93
|
+
this.on(event, onceListener as any);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
off(event: '*', listener?: WildcardListener): void
|
|
97
|
+
off<E extends string & keyof T>(event: E, listener?: (...args: T[E]) => void): void
|
|
98
|
+
off<E extends string & keyof T>(event: E | '*', listener?: any): void {
|
|
99
|
+
if (event === '*') {
|
|
100
|
+
if (!listener) {
|
|
101
|
+
this.wildcardListeners = [];
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const index = this.wildcardListeners.indexOf(listener);
|
|
105
|
+
if (index !== -1) this.wildcardListeners.splice(index, 1);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const listeners = this.events.get(event);
|
|
110
|
+
if (!listeners) return;
|
|
111
|
+
|
|
112
|
+
if (!listener) {
|
|
113
|
+
this.events.delete(event);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const index = listeners.indexOf(listener as Listener);
|
|
118
|
+
if (index !== -1) {
|
|
119
|
+
listeners.splice(index, 1);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
package/src/cli/cli.ts
ADDED
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
// @ts-ignore — bun resolves JSON imports at bundle time
|
|
3
|
+
import pkg from '../../package.json'
|
|
4
|
+
import { BUILD_SHA, BUILD_BRANCH, BUILD_DATE } from './build-info'
|
|
5
|
+
|
|
6
|
+
// Fast-path flags that don't need the container
|
|
7
|
+
const args = process.argv.slice(2)
|
|
8
|
+
if (args.includes('--version') || args.includes('-v')) {
|
|
9
|
+
console.log(`luca v${pkg.version} (${BUILD_BRANCH}@${BUILD_SHA}) built ${BUILD_DATE}`)
|
|
10
|
+
console.log(` npm: https://www.npmjs.com/package/luca`)
|
|
11
|
+
console.log(` git: https://github.com/soederpop/luca`)
|
|
12
|
+
process.exit(0)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
import container from 'luca/agi'
|
|
16
|
+
import '@/commands/index.js'
|
|
17
|
+
import { homedir } from 'os'
|
|
18
|
+
import { join } from 'path'
|
|
19
|
+
|
|
20
|
+
async function main() {
|
|
21
|
+
const profile = process.env.LUCA_PROFILE === '1'
|
|
22
|
+
const t = (label?: string) => {
|
|
23
|
+
if (!profile) return () => { }
|
|
24
|
+
const start = performance.now()
|
|
25
|
+
return (suffix?: string) => {
|
|
26
|
+
const ms = (performance.now() - start).toFixed(1)
|
|
27
|
+
console.error(`[profile] ${label}${suffix ? ` ${suffix}` : ''}: ${ms}ms`)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const tTotal = t('total boot')
|
|
32
|
+
|
|
33
|
+
// LUCA_COMMAND_DISCOVERY: "disable" skips all, "no-local" skips project, "no-home" skips user
|
|
34
|
+
const discovery = process.env.LUCA_COMMAND_DISCOVERY || ''
|
|
35
|
+
|
|
36
|
+
// Snapshot built-in commands BEFORE loadCliModule — luca.cli.ts may call
|
|
37
|
+
// helpers.discoverAll() which registers project commands early
|
|
38
|
+
const builtinCommands = new Set(container.commands.available as string[])
|
|
39
|
+
|
|
40
|
+
// Load global CLI module (~/.luca/luca.cli.ts) before project-level —
|
|
41
|
+
// lets users set up global helpers, discovery roots, etc.
|
|
42
|
+
let done = t('loadGlobalCliModule')
|
|
43
|
+
await loadCliModule(join(homedir(), '.luca', 'luca.cli.ts'))
|
|
44
|
+
done()
|
|
45
|
+
|
|
46
|
+
// Load project-level CLI module (luca.cli.ts) for container customization
|
|
47
|
+
done = t('loadCliModule')
|
|
48
|
+
await loadCliModule(container.paths.resolve('luca.cli.ts'))
|
|
49
|
+
done()
|
|
50
|
+
|
|
51
|
+
// Discover project-local commands (commands/ or src/commands/)
|
|
52
|
+
done = t('discoverProjectCommands')
|
|
53
|
+
if (discovery !== 'disable' && discovery !== 'no-local') {
|
|
54
|
+
await discoverProjectCommands()
|
|
55
|
+
}
|
|
56
|
+
done()
|
|
57
|
+
const afterProject = new Set(container.commands.available as string[])
|
|
58
|
+
const projectCommands = new Set([...afterProject].filter((n) => !builtinCommands.has(n)))
|
|
59
|
+
|
|
60
|
+
// Discover user-level helpers (~/.luca/{features,clients,servers,commands,selectors}/)
|
|
61
|
+
done = t('discoverUserHelpers')
|
|
62
|
+
if (discovery !== 'disable' && discovery !== 'no-home') {
|
|
63
|
+
await discoverUserHelpers()
|
|
64
|
+
}
|
|
65
|
+
done()
|
|
66
|
+
const afterUser = new Set(container.commands.available as string[])
|
|
67
|
+
const userCommands = new Set([...afterUser].filter((n) => !builtinCommands.has(n) && !projectCommands.has(n)))
|
|
68
|
+
|
|
69
|
+
// Store command sources for help display
|
|
70
|
+
; (container as any)._commandSources = { builtinCommands, projectCommands, userCommands }
|
|
71
|
+
|
|
72
|
+
// Load generated introspection data if present
|
|
73
|
+
done = t('loadProjectIntrospection')
|
|
74
|
+
await loadProjectIntrospection()
|
|
75
|
+
done()
|
|
76
|
+
|
|
77
|
+
const commandName = container.argv._[0] as string
|
|
78
|
+
|
|
79
|
+
done = t('dispatch')
|
|
80
|
+
if (container.argv.help && !commandName) {
|
|
81
|
+
// --help with no command is the same as `luca` with no args
|
|
82
|
+
// Clear the help flag so the help command's handler runs (not the --help intercept)
|
|
83
|
+
delete container.argv.help
|
|
84
|
+
container.argv._.splice(0, 0, 'help')
|
|
85
|
+
const cmd = container.command('help' as any)
|
|
86
|
+
await cmd.dispatch()
|
|
87
|
+
} else if (commandName && container.commands.has(commandName)) {
|
|
88
|
+
const cmd = container.command(commandName as any)
|
|
89
|
+
await cmd.dispatch()
|
|
90
|
+
} else if (commandName) {
|
|
91
|
+
// not a known command — treat as implicit `run`
|
|
92
|
+
//
|
|
93
|
+
if (resolveScript(commandName, container)) {
|
|
94
|
+
container.argv._.splice(0, 0, 'run')
|
|
95
|
+
const cmd = container.command('run' as any)
|
|
96
|
+
await cmd.dispatch()
|
|
97
|
+
} else {
|
|
98
|
+
const phrase = container.argv._.join(' ')
|
|
99
|
+
|
|
100
|
+
// easter egg
|
|
101
|
+
if (phrase === 'get loopy') {
|
|
102
|
+
await getLoopy(container)
|
|
103
|
+
// @ts-ignore TODO come up with a typesafe way to do this
|
|
104
|
+
} else if (container.state.get('missingCommandHandler')) {
|
|
105
|
+
// @ts-ignore TODO come up with a typesafe way to do this
|
|
106
|
+
const missingCommandHandler = container.state.get('missingCommandHandler') as any
|
|
107
|
+
|
|
108
|
+
if (typeof missingCommandHandler === 'function') {
|
|
109
|
+
await missingCommandHandler({
|
|
110
|
+
words: container.argv._,
|
|
111
|
+
phrase,
|
|
112
|
+
}).catch((err: any) => {
|
|
113
|
+
console.error(`Missing command handler error: ${err.message}`, err)
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
} else {
|
|
117
|
+
container.argv._.splice(0, 0, 'help')
|
|
118
|
+
const cmd = container.command('help' as any)
|
|
119
|
+
await cmd.dispatch()
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
} else {
|
|
124
|
+
container.argv._.splice(0, 0, 'help')
|
|
125
|
+
const cmd = container.command('help' as any)
|
|
126
|
+
await cmd.dispatch()
|
|
127
|
+
}
|
|
128
|
+
done()
|
|
129
|
+
tTotal()
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function resolveScript(ref: string, container: any) {
|
|
133
|
+
const candidates = [
|
|
134
|
+
ref,
|
|
135
|
+
`${ref}.ts`,
|
|
136
|
+
`${ref}.js`,
|
|
137
|
+
`${ref}.md`,
|
|
138
|
+
]
|
|
139
|
+
|
|
140
|
+
for (const candidate of candidates) {
|
|
141
|
+
const resolved = container.paths.resolve(candidate)
|
|
142
|
+
if (container.fs.exists(resolved)) return resolved
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return null
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async function loadCliModule(modulePath: string) {
|
|
149
|
+
if (!container.fs.exists(modulePath)) return
|
|
150
|
+
|
|
151
|
+
// Use the helpers feature to load the module — it handles the native import
|
|
152
|
+
// vs VM decision using the same useNativeImport check as discovery
|
|
153
|
+
const helpers = container.feature('helpers') as any
|
|
154
|
+
const exports = await helpers.loadModuleExports(modulePath)
|
|
155
|
+
|
|
156
|
+
if (typeof exports?.main === 'function') {
|
|
157
|
+
await exports.main(container)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (typeof exports?.onStart === 'function') {
|
|
161
|
+
container.once('started', () => exports.onStart(container))
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async function discoverProjectCommands() {
|
|
166
|
+
// Always route through the helpers feature — it handles native import vs VM
|
|
167
|
+
// internally, and deduplicates concurrent/repeated discovery via promise caching.
|
|
168
|
+
// If luca.cli.ts already called helpers.discoverAll(), this resolves instantly.
|
|
169
|
+
const helpers = container.feature('helpers') as any
|
|
170
|
+
await helpers.discover('commands')
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
async function loadProjectIntrospection() {
|
|
174
|
+
const candidates = [
|
|
175
|
+
'features/introspection.generated.ts',
|
|
176
|
+
'src/introspection.generated.ts',
|
|
177
|
+
'introspection.generated.ts',
|
|
178
|
+
]
|
|
179
|
+
|
|
180
|
+
for (const candidate of candidates) {
|
|
181
|
+
const filePath = container.paths.resolve(candidate)
|
|
182
|
+
if (container.fs.exists(filePath)) {
|
|
183
|
+
try {
|
|
184
|
+
await import(filePath)
|
|
185
|
+
} catch {
|
|
186
|
+
// Generated file may be stale or malformed — skip silently
|
|
187
|
+
}
|
|
188
|
+
return
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const DISCOVERABLE_TYPES = ['features', 'clients', 'servers', 'commands', 'selectors'] as const
|
|
194
|
+
|
|
195
|
+
async function discoverUserHelpers() {
|
|
196
|
+
const lucaHome = join(homedir(), '.luca')
|
|
197
|
+
const helpers = container.feature('helpers') as any
|
|
198
|
+
|
|
199
|
+
for (const type of DISCOVERABLE_TYPES) {
|
|
200
|
+
const dir = join(lucaHome, type)
|
|
201
|
+
if (container.fs.exists(dir)) {
|
|
202
|
+
await helpers.discover(type, { directory: dir })
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async function getLoopy(container: any) {
|
|
208
|
+
const fs = container.feature('fs')
|
|
209
|
+
const ui = container.feature('ui')
|
|
210
|
+
const os = container.feature('os')
|
|
211
|
+
const proc = container.feature('proc')
|
|
212
|
+
|
|
213
|
+
const repoUrl = 'https://github.com/soederpop/agentic-loop.git'
|
|
214
|
+
const appDir = container.paths.resolve(os.homedir, '.luca', 'apps', 'agentic-loop')
|
|
215
|
+
|
|
216
|
+
console.log(ui.colors.cyan('Getting loopy...'))
|
|
217
|
+
|
|
218
|
+
// Clone (or pull) the agentic-loop repo into ~/.luca/apps/agentic-loop
|
|
219
|
+
fs.ensureFolder(container.paths.resolve(os.homedir, '.luca', 'apps'))
|
|
220
|
+
|
|
221
|
+
if (fs.existsSync(container.paths.resolve(appDir, '.git'))) {
|
|
222
|
+
console.log(ui.colors.cyan(' Updating agentic-loop repo...'))
|
|
223
|
+
await proc.exec('git pull', { cwd: appDir })
|
|
224
|
+
} else {
|
|
225
|
+
// Clean out any stale non-git copy
|
|
226
|
+
if (fs.existsSync(appDir)) {
|
|
227
|
+
await proc.exec(`rm -rf ${appDir}`)
|
|
228
|
+
}
|
|
229
|
+
console.log(ui.colors.cyan(' Cloning agentic-loop repo...'))
|
|
230
|
+
await proc.exec(`git clone ${repoUrl} ${appDir}`)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Install dependencies
|
|
234
|
+
console.log(ui.colors.cyan(' Installing dependencies...'))
|
|
235
|
+
await proc.exec('bun install', { cwd: appDir })
|
|
236
|
+
|
|
237
|
+
// Copy assistants into the local project
|
|
238
|
+
console.log(ui.colors.cyan(' Setting up assistants...'))
|
|
239
|
+
const assistantsDir = container.paths.resolve('assistants')
|
|
240
|
+
fs.ensureFolder(assistantsDir)
|
|
241
|
+
for (const assistant of ['lucaCoder', 'chiefOfStaff', 'rocket', 'researcher']) {
|
|
242
|
+
const src = container.paths.resolve(appDir, 'assistants', assistant)
|
|
243
|
+
const dest = container.paths.resolve(assistantsDir, assistant)
|
|
244
|
+
if (fs.existsSync(src) && !fs.existsSync(dest)) {
|
|
245
|
+
fs.copy(src, dest)
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Copy scripts into the local project
|
|
250
|
+
console.log(ui.colors.cyan(' Setting up scripts...'))
|
|
251
|
+
const scriptsSrc = container.paths.resolve(appDir, 'scripts')
|
|
252
|
+
const scriptsDest = container.paths.resolve('scripts')
|
|
253
|
+
if (fs.existsSync(scriptsSrc)) {
|
|
254
|
+
fs.copy(scriptsSrc, scriptsDest)
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Copy apps (native swift app) into the local project
|
|
258
|
+
console.log(ui.colors.cyan(' Setting up apps...'))
|
|
259
|
+
const appsSrc = container.paths.resolve(appDir, 'apps')
|
|
260
|
+
const appsDest = container.paths.resolve('apps')
|
|
261
|
+
if (fs.existsSync(appsSrc) && !fs.existsSync(appsDest)) {
|
|
262
|
+
fs.copy(appsSrc, appsDest)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Copy config.example.yml as config.yml
|
|
266
|
+
const configSrc = container.paths.resolve(appDir, 'config.example.yml')
|
|
267
|
+
const configDest = container.paths.resolve('config.yml')
|
|
268
|
+
if (fs.existsSync(configSrc) && !fs.existsSync(configDest)) {
|
|
269
|
+
console.log(ui.colors.cyan(' Setting up config.yml...'))
|
|
270
|
+
fs.copy(configSrc, configDest)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Set up the docs folder structure
|
|
274
|
+
console.log(ui.colors.cyan(' Setting up docs...'))
|
|
275
|
+
const docsDir = container.paths.resolve('docs')
|
|
276
|
+
fs.ensureFolder(docsDir)
|
|
277
|
+
|
|
278
|
+
for (const sub of ['goals', 'ideas', 'projects', 'plans', 'plays', 'prompts', 'tasks', 'reports']) {
|
|
279
|
+
fs.ensureFolder(container.paths.resolve(docsDir, sub))
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Copy docs/models.ts
|
|
283
|
+
const modelsSrc = container.paths.resolve(appDir, 'docs', 'models.ts')
|
|
284
|
+
if (fs.existsSync(modelsSrc)) {
|
|
285
|
+
fs.copy(modelsSrc, container.paths.resolve(docsDir, 'models.ts'))
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Copy docs/templates
|
|
289
|
+
const templatesSrc = container.paths.resolve(appDir, 'docs', 'templates')
|
|
290
|
+
const templatesDest = container.paths.resolve(docsDir, 'templates')
|
|
291
|
+
if (fs.existsSync(templatesSrc)) {
|
|
292
|
+
fs.copy(templatesSrc, templatesDest)
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Copy starter docs (VISION.md, memories/)
|
|
296
|
+
const visionSrc = container.paths.resolve(appDir, 'docs', 'templates', 'starter-docs', 'VISION.md')
|
|
297
|
+
const visionDest = container.paths.resolve(docsDir, 'VISION.md')
|
|
298
|
+
if (fs.existsSync(visionSrc) && !fs.existsSync(visionDest)) {
|
|
299
|
+
fs.copy(visionSrc, visionDest)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const memoriesSrc = container.paths.resolve(appDir, 'docs', 'templates', 'starter-docs', 'memories')
|
|
303
|
+
const memoriesDest = container.paths.resolve(docsDir, 'memories')
|
|
304
|
+
if (fs.existsSync(memoriesSrc) && !fs.existsSync(memoriesDest)) {
|
|
305
|
+
fs.copy(memoriesSrc, memoriesDest)
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Replace the project's luca.cli.ts with the agentic-loop version
|
|
309
|
+
const loopyCli = [
|
|
310
|
+
'/**',
|
|
311
|
+
' * luca.cli.ts — Agentic Loop project customization',
|
|
312
|
+
' *',
|
|
313
|
+
' * Automatically loaded by the luca CLI before any command runs.',
|
|
314
|
+
' * Discovers local helpers and loads agentic-loop shared resources.',
|
|
315
|
+
' */',
|
|
316
|
+
'',
|
|
317
|
+
'export async function main(container: any) {',
|
|
318
|
+
' // Discover project-level helpers (commands/, features/, endpoints/)',
|
|
319
|
+
' await container.helpers.discoverAll()',
|
|
320
|
+
'',
|
|
321
|
+
' await loadAgenticLoop(container)',
|
|
322
|
+
'',
|
|
323
|
+
' // Handle unknown commands gracefully instead of silently failing',
|
|
324
|
+
' container.onMissingCommand(async ({ phrase }: { phrase: string }) => {',
|
|
325
|
+
" container.command('help').dispatch()",
|
|
326
|
+
' })',
|
|
327
|
+
'}',
|
|
328
|
+
'',
|
|
329
|
+
'async function loadAgenticLoop(container) {',
|
|
330
|
+
' try {',
|
|
331
|
+
" const agenticLoopRoot = container.paths.resolve(container.os.homedir, '.luca', 'apps', 'agentic-loop')",
|
|
332
|
+
'',
|
|
333
|
+
' // use the agentic loop commands, etc',
|
|
334
|
+
" await container.feature('helpers', { rootDir: agenticLoopRoot }).discoverAll()",
|
|
335
|
+
'',
|
|
336
|
+
" if (container.features.has('workflowLibrary')) {",
|
|
337
|
+
" const workflowLibrary = container.feature('workflowLibrary')",
|
|
338
|
+
" workflowLibrary.addWorkflowsDir(container.paths.resolve(agenticLoopRoot, 'workflows'))",
|
|
339
|
+
' }',
|
|
340
|
+
'',
|
|
341
|
+
' } catch(error) {',
|
|
342
|
+
' console.error("Error loading the agentic loop helpers", error.message)',
|
|
343
|
+
' }',
|
|
344
|
+
'}',
|
|
345
|
+
'',
|
|
346
|
+
].join('\n')
|
|
347
|
+
|
|
348
|
+
fs.writeFile(container.paths.resolve('luca.cli.ts'), loopyCli)
|
|
349
|
+
|
|
350
|
+
console.log(ui.colors.green('Loopy installed! You now have agentic-loop commands, features, workflows, and assistants.'))
|
|
351
|
+
console.log('')
|
|
352
|
+
console.log(ui.colors.cyan(' Next step: run scripts/install.sh to finish setup'))
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
main()
|
package/src/client.ts
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { Helper } from "./helper.js";
|
|
2
|
+
import type { Container, ContainerContext } from "./container.js";
|
|
3
|
+
import { Registry } from "./registry.js";
|
|
4
|
+
import { z } from 'zod'
|
|
5
|
+
import {
|
|
6
|
+
ClientStateSchema, ClientOptionsSchema, ClientEventsSchema,
|
|
7
|
+
} from './schemas/base.js'
|
|
8
|
+
|
|
9
|
+
export type ClientOptions = z.infer<typeof ClientOptionsSchema>
|
|
10
|
+
export type ClientState = z.infer<typeof ClientStateSchema>
|
|
11
|
+
|
|
12
|
+
// Subclass types re-exported for backward compatibility.
|
|
13
|
+
// Import the concrete classes from their individual files:
|
|
14
|
+
// import { RestClient } from './clients/rest'
|
|
15
|
+
// import { GraphClient } from './clients/graph'
|
|
16
|
+
// import { WebSocketClient } from './clients/websocket'
|
|
17
|
+
export type { WebSocketClientState, WebSocketClientOptions } from './clients/websocket.js'
|
|
18
|
+
export type { GraphClientOptions } from './clients/graph.js'
|
|
19
|
+
|
|
20
|
+
// AvailableClients is an open interface — subclasses augment it via `declare module`
|
|
21
|
+
export interface AvailableClients {}
|
|
22
|
+
|
|
23
|
+
export interface ClientsInterface {
|
|
24
|
+
clients: ClientsRegistry;
|
|
25
|
+
client<T extends keyof AvailableClients>(
|
|
26
|
+
key: T,
|
|
27
|
+
options?: ConstructorParameters<AvailableClients[T]>[0]
|
|
28
|
+
): InstanceType<AvailableClients[T]>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Base client class for all Luca network clients. Provides connection state
|
|
33
|
+
* tracking, configuration, and the registry/factory infrastructure for
|
|
34
|
+
* creating typed client instances via `container.client('rest')`.
|
|
35
|
+
*
|
|
36
|
+
* Subclasses should override `connect()` and add protocol-specific methods.
|
|
37
|
+
* Register subclasses using `Client.register(this, 'myClient')` in a static block.
|
|
38
|
+
*/
|
|
39
|
+
export class Client<
|
|
40
|
+
T extends ClientState = ClientState,
|
|
41
|
+
K extends ClientOptions = ClientOptions
|
|
42
|
+
> extends Helper<T, K> {
|
|
43
|
+
static override shortcut = "clients.base"
|
|
44
|
+
static override stateSchema = ClientStateSchema
|
|
45
|
+
static override optionsSchema = ClientOptionsSchema
|
|
46
|
+
static override eventsSchema = ClientEventsSchema
|
|
47
|
+
|
|
48
|
+
/** Self-register a Client subclass from a static initialization block. */
|
|
49
|
+
static register: (SubClass: abstract new (options: any, context: any) => Client, id?: string) => abstract new (options: any, context: any) => Client
|
|
50
|
+
|
|
51
|
+
static attach(container: Container & ClientsInterface): any {
|
|
52
|
+
Object.assign(container, {
|
|
53
|
+
get clients() {
|
|
54
|
+
return clients;
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
client<T extends keyof AvailableClients>(
|
|
58
|
+
id: T,
|
|
59
|
+
options?: ConstructorParameters<AvailableClients[T]>[0]
|
|
60
|
+
): InstanceType<AvailableClients[T]> {
|
|
61
|
+
const BaseClass = clients.lookup(
|
|
62
|
+
id as keyof AvailableClients
|
|
63
|
+
) as AvailableClients[T];
|
|
64
|
+
|
|
65
|
+
return container.createHelperInstance({
|
|
66
|
+
cache: helperCache,
|
|
67
|
+
type: 'client',
|
|
68
|
+
id: String(id),
|
|
69
|
+
BaseClass,
|
|
70
|
+
options,
|
|
71
|
+
fallbackName: String(id),
|
|
72
|
+
}) as InstanceType<AvailableClients[T]>;
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
container.registerHelperType('clients', 'client');
|
|
77
|
+
|
|
78
|
+
return container;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
constructor(options?: K, context?: ContainerContext) {
|
|
82
|
+
if (typeof context !== "object") {
|
|
83
|
+
throw new Error("Client must be instantiated with a context object");
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
super((options as K) || {}, context);
|
|
87
|
+
|
|
88
|
+
this.state.set("connected", false);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** The base URL for this client's connections/requests. */
|
|
92
|
+
get baseURL() {
|
|
93
|
+
return this.options.baseURL || ''
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
override get options() {
|
|
97
|
+
return this._options as K;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Configure this client instance with additional options. */
|
|
101
|
+
configure(options?: any): this {
|
|
102
|
+
return this;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Whether the client is currently connected. */
|
|
106
|
+
get isConnected() {
|
|
107
|
+
return !!this.state.get("connected");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Establish a connection. Subclasses should override with protocol-specific logic. */
|
|
111
|
+
async connect(): Promise<this> {
|
|
112
|
+
this.state.set("connected", true);
|
|
113
|
+
return this;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// --- Registry and Client.register must be defined BEFORE subclasses ---
|
|
118
|
+
// because static blocks in subclass files run at class declaration time.
|
|
119
|
+
|
|
120
|
+
export class ClientsRegistry extends Registry<Client<any>> {
|
|
121
|
+
override scope = "clients"
|
|
122
|
+
override baseClass = Client
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export const clients = new ClientsRegistry();
|
|
126
|
+
|
|
127
|
+
export const helperCache = new Map();
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Self-register a Client subclass from a static initialization block.
|
|
131
|
+
* IMPORTANT: Place the static block AFTER all static override declarations
|
|
132
|
+
* so schemas, envVars, and other metadata are set before interceptRegistration fires.
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* ```typescript
|
|
136
|
+
* export class OpenAIClient extends Client {
|
|
137
|
+
* static override stateSchema = OpenAIClientStateSchema
|
|
138
|
+
* static override optionsSchema = OpenAIClientOptionsSchema
|
|
139
|
+
* static { Client.register(this, 'openai') } // must come last
|
|
140
|
+
* }
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
Client.register = function registerClient(
|
|
144
|
+
SubClass: abstract new (options: any, context: any) => Client,
|
|
145
|
+
id?: string,
|
|
146
|
+
) {
|
|
147
|
+
const registryId = id ?? SubClass.name[0]!.toLowerCase() + SubClass.name.slice(1)
|
|
148
|
+
|
|
149
|
+
// Auto-set shortcut if not explicitly overridden on this class
|
|
150
|
+
if (!Object.getOwnPropertyDescriptor(SubClass, 'shortcut')?.value ||
|
|
151
|
+
(SubClass as any).shortcut === 'unspecified' ||
|
|
152
|
+
(SubClass as any).shortcut === 'clients.base') {
|
|
153
|
+
;(SubClass as any).shortcut = `clients.${registryId}` as const
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Register in the clients registry (interceptRegistration sees all statics above)
|
|
157
|
+
clients.register(registryId, SubClass as any)
|
|
158
|
+
|
|
159
|
+
// Generate default attach() if not explicitly overridden on this class
|
|
160
|
+
if (!Object.getOwnPropertyDescriptor(SubClass, 'attach')) {
|
|
161
|
+
;(SubClass as any).attach = (container: any) => {
|
|
162
|
+
clients.register(registryId, SubClass as any)
|
|
163
|
+
return container
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return SubClass
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export default Client;
|