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
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
// Auto-generated Python bridge script
|
|
2
|
+
// Source: src/python/bridge.py
|
|
3
|
+
//
|
|
4
|
+
// Do not edit manually. Run: luca build-python-bridge
|
|
5
|
+
|
|
6
|
+
export const bridgeScript = `#!/usr/bin/env python3
|
|
7
|
+
"""Luca Python Bridge - persistent interactive Python session.
|
|
8
|
+
|
|
9
|
+
Communicates via JSON lines over stdin/stdout. Each request is a single
|
|
10
|
+
JSON object per line on stdin; each response is a single JSON object per
|
|
11
|
+
line on stdout. User print() output is captured per-execution via
|
|
12
|
+
io.StringIO so it never corrupts the protocol.
|
|
13
|
+
|
|
14
|
+
Python 3.8+ compatible (stdlib only).
|
|
15
|
+
"""
|
|
16
|
+
import sys
|
|
17
|
+
import json
|
|
18
|
+
import io
|
|
19
|
+
import traceback
|
|
20
|
+
import os
|
|
21
|
+
|
|
22
|
+
# Persistent namespace shared across all exec/eval calls
|
|
23
|
+
_namespace = {"__builtins__": __builtins__}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def setup_sys_path(project_dir):
|
|
27
|
+
"""Insert project_dir and common sub-paths into sys.path."""
|
|
28
|
+
paths_to_add = [project_dir]
|
|
29
|
+
|
|
30
|
+
# src/ layout (PEP 621 / setuptools)
|
|
31
|
+
src_dir = os.path.join(project_dir, "src")
|
|
32
|
+
if os.path.isdir(src_dir):
|
|
33
|
+
paths_to_add.append(src_dir)
|
|
34
|
+
|
|
35
|
+
# lib/ layout (less common but exists)
|
|
36
|
+
lib_dir = os.path.join(project_dir, "lib")
|
|
37
|
+
if os.path.isdir(lib_dir):
|
|
38
|
+
paths_to_add.append(lib_dir)
|
|
39
|
+
|
|
40
|
+
for p in reversed(paths_to_add):
|
|
41
|
+
if p not in sys.path:
|
|
42
|
+
sys.path.insert(0, p)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _safe_serialize(value):
|
|
46
|
+
"""Attempt JSON serialization; fall back to repr()."""
|
|
47
|
+
try:
|
|
48
|
+
json.dumps(value, default=str)
|
|
49
|
+
return value
|
|
50
|
+
except (TypeError, ValueError, OverflowError):
|
|
51
|
+
return repr(value)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def handle_exec(req):
|
|
55
|
+
"""Execute code in the persistent namespace."""
|
|
56
|
+
code = req.get("code", "")
|
|
57
|
+
variables = req.get("variables", {})
|
|
58
|
+
_namespace.update(variables)
|
|
59
|
+
|
|
60
|
+
old_stdout = sys.stdout
|
|
61
|
+
captured = io.StringIO()
|
|
62
|
+
sys.stdout = captured
|
|
63
|
+
try:
|
|
64
|
+
exec(code, _namespace)
|
|
65
|
+
sys.stdout = old_stdout
|
|
66
|
+
return {"ok": True, "stdout": captured.getvalue(), "result": None}
|
|
67
|
+
except Exception as e:
|
|
68
|
+
sys.stdout = old_stdout
|
|
69
|
+
return {
|
|
70
|
+
"ok": False,
|
|
71
|
+
"error": str(e),
|
|
72
|
+
"traceback": traceback.format_exc(),
|
|
73
|
+
"stdout": captured.getvalue(),
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def handle_eval(req):
|
|
78
|
+
"""Evaluate an expression and return its value."""
|
|
79
|
+
expression = req.get("expression", "")
|
|
80
|
+
|
|
81
|
+
old_stdout = sys.stdout
|
|
82
|
+
captured = io.StringIO()
|
|
83
|
+
sys.stdout = captured
|
|
84
|
+
try:
|
|
85
|
+
result = eval(expression, _namespace)
|
|
86
|
+
sys.stdout = old_stdout
|
|
87
|
+
return {
|
|
88
|
+
"ok": True,
|
|
89
|
+
"result": _safe_serialize(result),
|
|
90
|
+
"stdout": captured.getvalue(),
|
|
91
|
+
}
|
|
92
|
+
except Exception as e:
|
|
93
|
+
sys.stdout = old_stdout
|
|
94
|
+
return {
|
|
95
|
+
"ok": False,
|
|
96
|
+
"error": str(e),
|
|
97
|
+
"traceback": traceback.format_exc(),
|
|
98
|
+
"stdout": captured.getvalue(),
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def handle_import(req):
|
|
103
|
+
"""Import a module into the namespace."""
|
|
104
|
+
module_name = req.get("module", "")
|
|
105
|
+
alias = req.get("alias", module_name.split(".")[-1])
|
|
106
|
+
try:
|
|
107
|
+
mod = __import__(
|
|
108
|
+
module_name,
|
|
109
|
+
fromlist=[module_name.split(".")[-1]] if "." in module_name else [],
|
|
110
|
+
)
|
|
111
|
+
_namespace[alias] = mod
|
|
112
|
+
return {"ok": True, "result": "Imported {} as {}".format(module_name, alias)}
|
|
113
|
+
except Exception as e:
|
|
114
|
+
return {
|
|
115
|
+
"ok": False,
|
|
116
|
+
"error": str(e),
|
|
117
|
+
"traceback": traceback.format_exc(),
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def handle_call(req):
|
|
122
|
+
"""Call a function by dotted path in the namespace."""
|
|
123
|
+
func_path = req.get("function", "")
|
|
124
|
+
args = req.get("args", [])
|
|
125
|
+
kwargs = req.get("kwargs", {})
|
|
126
|
+
|
|
127
|
+
old_stdout = sys.stdout
|
|
128
|
+
captured = io.StringIO()
|
|
129
|
+
sys.stdout = captured
|
|
130
|
+
try:
|
|
131
|
+
parts = func_path.split(".")
|
|
132
|
+
obj = _namespace[parts[0]]
|
|
133
|
+
for part in parts[1:]:
|
|
134
|
+
obj = getattr(obj, part)
|
|
135
|
+
result = obj(*args, **kwargs)
|
|
136
|
+
sys.stdout = old_stdout
|
|
137
|
+
return {
|
|
138
|
+
"ok": True,
|
|
139
|
+
"result": _safe_serialize(result),
|
|
140
|
+
"stdout": captured.getvalue(),
|
|
141
|
+
}
|
|
142
|
+
except Exception as e:
|
|
143
|
+
sys.stdout = old_stdout
|
|
144
|
+
return {
|
|
145
|
+
"ok": False,
|
|
146
|
+
"error": str(e),
|
|
147
|
+
"traceback": traceback.format_exc(),
|
|
148
|
+
"stdout": captured.getvalue(),
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def handle_get_locals(req):
|
|
153
|
+
"""Return all non-dunder keys from the namespace."""
|
|
154
|
+
safe = {}
|
|
155
|
+
for k, v in _namespace.items():
|
|
156
|
+
if k.startswith("__"):
|
|
157
|
+
continue
|
|
158
|
+
safe[k] = _safe_serialize(v)
|
|
159
|
+
return {"ok": True, "result": safe}
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def handle_reset(req):
|
|
163
|
+
"""Clear the namespace."""
|
|
164
|
+
_namespace.clear()
|
|
165
|
+
_namespace["__builtins__"] = __builtins__
|
|
166
|
+
return {"ok": True, "result": "Session reset"}
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
HANDLERS = {
|
|
170
|
+
"exec": handle_exec,
|
|
171
|
+
"eval": handle_eval,
|
|
172
|
+
"import": handle_import,
|
|
173
|
+
"call": handle_call,
|
|
174
|
+
"get_locals": handle_get_locals,
|
|
175
|
+
"reset": handle_reset,
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def main():
|
|
180
|
+
# First line from stdin is the init handshake with project_dir
|
|
181
|
+
init_line = sys.stdin.readline().strip()
|
|
182
|
+
if init_line:
|
|
183
|
+
try:
|
|
184
|
+
init = json.loads(init_line)
|
|
185
|
+
if "project_dir" in init:
|
|
186
|
+
setup_sys_path(init["project_dir"])
|
|
187
|
+
except json.JSONDecodeError:
|
|
188
|
+
pass
|
|
189
|
+
|
|
190
|
+
# Signal ready
|
|
191
|
+
sys.stdout.write(json.dumps({"ok": True, "type": "ready"}) + "\\n")
|
|
192
|
+
sys.stdout.flush()
|
|
193
|
+
|
|
194
|
+
# Main loop: read JSON commands, execute, respond
|
|
195
|
+
for line in sys.stdin:
|
|
196
|
+
line = line.strip()
|
|
197
|
+
if not line:
|
|
198
|
+
continue
|
|
199
|
+
|
|
200
|
+
try:
|
|
201
|
+
req = json.loads(line)
|
|
202
|
+
except json.JSONDecodeError as e:
|
|
203
|
+
resp = {"ok": False, "error": "Invalid JSON: {}".format(e)}
|
|
204
|
+
sys.stdout.write(json.dumps(resp) + "\\n")
|
|
205
|
+
sys.stdout.flush()
|
|
206
|
+
continue
|
|
207
|
+
|
|
208
|
+
req_id = req.get("id")
|
|
209
|
+
req_type = req.get("type", "exec")
|
|
210
|
+
handler = HANDLERS.get(req_type)
|
|
211
|
+
|
|
212
|
+
if not handler:
|
|
213
|
+
resp = {"ok": False, "error": "Unknown request type: {}".format(req_type)}
|
|
214
|
+
else:
|
|
215
|
+
resp = handler(req)
|
|
216
|
+
|
|
217
|
+
if req_id:
|
|
218
|
+
resp["id"] = req_id
|
|
219
|
+
|
|
220
|
+
sys.stdout.write(json.dumps(resp, default=str) + "\\n")
|
|
221
|
+
sys.stdout.flush()
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
if __name__ == "__main__":
|
|
225
|
+
main()
|
|
226
|
+
`
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { createContext, useContext, useRef, useState, useEffect, useCallback, useMemo, createElement } from 'react'
|
|
2
|
+
import type { ReactNode } from 'react'
|
|
3
|
+
import type { Container, AvailableFeatures } from '../container'
|
|
4
|
+
import type { Helper } from '../helper'
|
|
5
|
+
import type { StateChangeType } from '../state'
|
|
6
|
+
|
|
7
|
+
// ── Context & Provider ──────────────────────────────────────────────
|
|
8
|
+
|
|
9
|
+
const ContainerContext = createContext<Container | null>(null)
|
|
10
|
+
|
|
11
|
+
function ContainerProvider({ container, children }: { container: Container; children: ReactNode }) {
|
|
12
|
+
return createElement(ContainerContext.Provider, { value: container }, children)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function useContainer<T extends Container = Container>(): T {
|
|
16
|
+
const container = useContext(ContainerContext)
|
|
17
|
+
if (!container) {
|
|
18
|
+
throw new Error('useContainer must be used within a <ContainerProvider>')
|
|
19
|
+
}
|
|
20
|
+
return container as T
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// ── State Hooks ─────────────────────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
type HasState = { state: { current: any; version: number; observe: (cb: (changeType: StateChangeType, key: any, value?: any) => void) => () => void } }
|
|
26
|
+
|
|
27
|
+
function useContainerState<T extends object = any>(target?: HasState): T {
|
|
28
|
+
const container = useContext(ContainerContext)
|
|
29
|
+
const resolved = target ?? container
|
|
30
|
+
if (!resolved) {
|
|
31
|
+
throw new Error('useContainerState requires a target or a ContainerProvider')
|
|
32
|
+
}
|
|
33
|
+
const [snapshot, setSnapshot] = useState<T>(() => ({ ...resolved.state.current }))
|
|
34
|
+
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
setSnapshot({ ...resolved.state.current })
|
|
37
|
+
const unsub = resolved.state.observe(() => {
|
|
38
|
+
setSnapshot({ ...resolved.state.current })
|
|
39
|
+
})
|
|
40
|
+
return unsub
|
|
41
|
+
}, [resolved])
|
|
42
|
+
|
|
43
|
+
return snapshot
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function useStateValue<V = any>(target: HasState, key: string): V | undefined {
|
|
47
|
+
const [value, setValue] = useState<V | undefined>(() => target.state.current[key])
|
|
48
|
+
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
setValue(target.state.current[key])
|
|
51
|
+
const unsub = target.state.observe((_changeType: StateChangeType, changedKey: any, newValue?: any) => {
|
|
52
|
+
if (changedKey === key) {
|
|
53
|
+
setValue(newValue as V)
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
return unsub
|
|
57
|
+
}, [target, key])
|
|
58
|
+
|
|
59
|
+
return value
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function useStateVersion(target?: HasState): number {
|
|
63
|
+
const container = useContext(ContainerContext)
|
|
64
|
+
const resolved = target ?? container
|
|
65
|
+
if (!resolved) {
|
|
66
|
+
throw new Error('useStateVersion requires a target or a ContainerProvider')
|
|
67
|
+
}
|
|
68
|
+
const [version, setVersion] = useState(() => resolved.state.version)
|
|
69
|
+
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
setVersion(resolved.state.version)
|
|
72
|
+
const unsub = resolved.state.observe(() => {
|
|
73
|
+
setVersion(resolved.state.version)
|
|
74
|
+
})
|
|
75
|
+
return unsub
|
|
76
|
+
}, [resolved])
|
|
77
|
+
|
|
78
|
+
return version
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ── Event Hooks ─────────────────────────────────────────────────────
|
|
82
|
+
|
|
83
|
+
type HasEvents = { on: (event: string, listener: (...args: any[]) => void) => any; off: (event: string, listener?: (...args: any[]) => void) => any }
|
|
84
|
+
|
|
85
|
+
function useEvent(target: HasEvents, event: string, handler: (...args: any[]) => void): void {
|
|
86
|
+
const handlerRef = useRef(handler)
|
|
87
|
+
handlerRef.current = handler
|
|
88
|
+
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
const listener = (...args: any[]) => handlerRef.current(...args)
|
|
91
|
+
target.on(event, listener)
|
|
92
|
+
return () => { target.off(event, listener) }
|
|
93
|
+
}, [target, event])
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function useWaitFor<T = any>(target: HasEvents & { waitFor: (event: string) => Promise<any> }, event: string): { data: T | undefined; pending: boolean; error: Error | undefined } {
|
|
97
|
+
const [data, setData] = useState<T | undefined>(undefined)
|
|
98
|
+
const [pending, setPending] = useState(true)
|
|
99
|
+
const [error, setError] = useState<Error | undefined>(undefined)
|
|
100
|
+
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
let cancelled = false
|
|
103
|
+
setPending(true)
|
|
104
|
+
setData(undefined)
|
|
105
|
+
setError(undefined)
|
|
106
|
+
|
|
107
|
+
target.waitFor(event).then(
|
|
108
|
+
(result) => {
|
|
109
|
+
if (!cancelled) {
|
|
110
|
+
setData(result as T)
|
|
111
|
+
setPending(false)
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
(err) => {
|
|
115
|
+
if (!cancelled) {
|
|
116
|
+
setError(err instanceof Error ? err : new Error(String(err)))
|
|
117
|
+
setPending(false)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
return () => { cancelled = true }
|
|
123
|
+
}, [target, event])
|
|
124
|
+
|
|
125
|
+
return { data, pending, error }
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// ── Feature Hook ────────────────────────────────────────────────────
|
|
129
|
+
|
|
130
|
+
function useFeature<K extends keyof AvailableFeatures>(
|
|
131
|
+
name: K,
|
|
132
|
+
options?: ConstructorParameters<AvailableFeatures[K]>[0]
|
|
133
|
+
): InstanceType<AvailableFeatures[K]> {
|
|
134
|
+
const container = useContainer()
|
|
135
|
+
return useMemo(
|
|
136
|
+
() => container.feature(name, options),
|
|
137
|
+
[container, name]
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// ── Helper State Hook ───────────────────────────────────────────────
|
|
142
|
+
|
|
143
|
+
function useHelperState<T extends object = any>(helper: Helper): [T, (value: any) => void] {
|
|
144
|
+
const [snapshot, setSnapshot] = useState<T>(() => ({ ...helper.state.current } as T))
|
|
145
|
+
|
|
146
|
+
useEffect(() => {
|
|
147
|
+
setSnapshot({ ...helper.state.current } as T)
|
|
148
|
+
const unsub = helper.state.observe(() => {
|
|
149
|
+
setSnapshot({ ...helper.state.current } as T)
|
|
150
|
+
})
|
|
151
|
+
return unsub
|
|
152
|
+
}, [helper])
|
|
153
|
+
|
|
154
|
+
const setState = useCallback(
|
|
155
|
+
(value: any) => helper.setState(value),
|
|
156
|
+
[helper]
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
return [snapshot, setState]
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// ── Exports ─────────────────────────────────────────────────────────
|
|
163
|
+
|
|
164
|
+
export {
|
|
165
|
+
ContainerContext,
|
|
166
|
+
ContainerProvider,
|
|
167
|
+
useContainer,
|
|
168
|
+
useContainerState,
|
|
169
|
+
useStateValue,
|
|
170
|
+
useStateVersion,
|
|
171
|
+
useEvent,
|
|
172
|
+
useWaitFor,
|
|
173
|
+
useFeature,
|
|
174
|
+
useHelperState,
|
|
175
|
+
}
|
package/src/registry.ts
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import type { Helper } from './helper.js';
|
|
2
|
+
import type { ContainerContext } from './container.js';
|
|
3
|
+
import { Bus } from './bus.js';
|
|
4
|
+
import { inspect } from 'util';
|
|
5
|
+
|
|
6
|
+
import { introspect, interceptRegistration } from './introspection/index.js';
|
|
7
|
+
import type { HelperIntrospection } from './introspection/index.js';
|
|
8
|
+
|
|
9
|
+
export type { HelperIntrospection }
|
|
10
|
+
|
|
11
|
+
abstract class Registry<T extends Helper> {
|
|
12
|
+
scope: string = "unspecified"
|
|
13
|
+
|
|
14
|
+
baseClass?: new (options: any, context: ContainerContext) => T
|
|
15
|
+
|
|
16
|
+
private readonly members! : Map<string, new (options: any, context: ContainerContext) => T>
|
|
17
|
+
|
|
18
|
+
private readonly _events! : Bus
|
|
19
|
+
|
|
20
|
+
constructor() {
|
|
21
|
+
Object.defineProperty(this, 'members', { enumerable: false, value: new Map<string, new (options: any, context: ContainerContext) => T>() })
|
|
22
|
+
Object.defineProperty(this, '_events', { enumerable: false, value: new Bus() })
|
|
23
|
+
Object.defineProperty(this, 'scope', { enumerable: false })
|
|
24
|
+
Object.defineProperty(this, 'baseClass', { enumerable: false })
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
[Symbol.for('nodejs.util.inspect.custom')]() {
|
|
28
|
+
const helpers = this.available
|
|
29
|
+
const methods: string[] = []
|
|
30
|
+
const getters: string[] = []
|
|
31
|
+
|
|
32
|
+
let proto = Object.getPrototypeOf(this)
|
|
33
|
+
while (proto && proto !== Object.prototype) {
|
|
34
|
+
for (const k of Object.getOwnPropertyNames(proto)) {
|
|
35
|
+
if (k === 'constructor' || k.startsWith('_')) continue
|
|
36
|
+
const desc = Object.getOwnPropertyDescriptor(proto, k)
|
|
37
|
+
if (!desc) continue
|
|
38
|
+
if (desc.get && !getters.includes(k)) getters.push(k)
|
|
39
|
+
else if (typeof desc.value === 'function' && !methods.includes(k)) methods.push(k)
|
|
40
|
+
}
|
|
41
|
+
proto = Object.getPrototypeOf(proto)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const parts = [`${this.constructor.name} [${this.scope}]`]
|
|
45
|
+
if (getters.length) parts.push(` getters: ${getters.sort().join(', ')}`)
|
|
46
|
+
if (methods.length) parts.push(` methods: ${methods.sort().map(m => m + '()').join(', ')}`)
|
|
47
|
+
parts.push(` registered: ${helpers.join(', ')}`)
|
|
48
|
+
return parts.join('\n')
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Lists the keys of all available helpers in this registry.
|
|
53
|
+
*/
|
|
54
|
+
get available() : string[] {
|
|
55
|
+
return Array.from(this.members.keys()).map(r => r.replace(`${this.scope}.`, '')).sort()
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Register a new helper in this registry.
|
|
60
|
+
*
|
|
61
|
+
* @param id - The id of the helper to register.
|
|
62
|
+
* @param constructor - The constructor for the helper.
|
|
63
|
+
* @returns The constructor for the helper.
|
|
64
|
+
*/
|
|
65
|
+
register(id: string, constructor: new (options: any, context: ContainerContext) => T) {
|
|
66
|
+
this.members.set(id.replace(`${this.scope}.`, ''), constructor);
|
|
67
|
+
interceptRegistration(this, constructor)
|
|
68
|
+
this.emit('helperRegistered', id, constructor)
|
|
69
|
+
return constructor
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Remove a helper from this registry.
|
|
74
|
+
*
|
|
75
|
+
* @param id - The id of the helper to unregister.
|
|
76
|
+
* @returns True if the helper was removed, false if it wasn't registered.
|
|
77
|
+
*/
|
|
78
|
+
unregister(id: string) : boolean {
|
|
79
|
+
const key = id.replace(`${this.scope}.`, '')
|
|
80
|
+
return this.members.delete(key)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Check if a helper is registered in this registry.
|
|
85
|
+
*
|
|
86
|
+
* @param id - The id of the helper to check.
|
|
87
|
+
* @returns True if the helper is registered, false otherwise.
|
|
88
|
+
*/
|
|
89
|
+
has(id: string) : boolean {
|
|
90
|
+
return this.members.has(id) || this.members.has([this.scope, id].join('.'))
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Lookup a helper by id.
|
|
95
|
+
*
|
|
96
|
+
* @param id - The id of the helper to lookup.
|
|
97
|
+
* @returns The constructor for the helper.
|
|
98
|
+
*/
|
|
99
|
+
lookup(id: string) : new (options: any, context: ContainerContext) => T {
|
|
100
|
+
if (!this.members.has(id) && this.members.has([this.scope, id].join('.'))) {
|
|
101
|
+
id = [this.scope, id].join(".")
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const Constructor = this.members.get(id);
|
|
105
|
+
|
|
106
|
+
if (!Constructor) {
|
|
107
|
+
const available = this.available
|
|
108
|
+
const suggestion = available.length > 0
|
|
109
|
+
? `\n\nAvailable ${this.scope}: ${available.join(', ')}`
|
|
110
|
+
: `\n\nNo ${this.scope} are registered. Make sure the module is imported or .use()'d on the container.`
|
|
111
|
+
|
|
112
|
+
throw new Error(
|
|
113
|
+
`${this.scope} "${id}" is not registered.${suggestion}\n\n` +
|
|
114
|
+
`To fix this, ensure the module that defines "${id}" is imported (e.g. import './${this.scope}/${id}') ` +
|
|
115
|
+
`or registered on the container (e.g. container.use(${id ? id[0]!.toUpperCase() + id.slice(1) : 'MyHelper'})).`
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return Constructor;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* View data about the interface for a particular Helper. Will tell you about the options
|
|
124
|
+
* to create one, the state it maintains, the methods and properties it has, and the events it emits.
|
|
125
|
+
*/
|
|
126
|
+
introspect(id: string) : HelperIntrospection | undefined {
|
|
127
|
+
return introspect(id)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Learn about the interface for a particular Helper. Will tell you about the options
|
|
132
|
+
* to create one, the state it maintains, the methods and properties it has, and the events it emits.
|
|
133
|
+
*
|
|
134
|
+
* Will return information as a markdown string.
|
|
135
|
+
*/
|
|
136
|
+
describe(id: string) : string {
|
|
137
|
+
const Constructor = this.lookup(id) as any
|
|
138
|
+
return Constructor.introspectAsText()
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Returns a condensed overview of all available helpers in this registry.
|
|
144
|
+
* Shows each helper's name and description, without the full introspection details.
|
|
145
|
+
*
|
|
146
|
+
* Use `describe(id)` to get the full details for a specific helper.
|
|
147
|
+
*/
|
|
148
|
+
describeAll() : string {
|
|
149
|
+
const sections: string[] = [`# Available ${this.scope}\n`]
|
|
150
|
+
|
|
151
|
+
for (const id of this.available) {
|
|
152
|
+
const Constructor = this.lookup(id) as any
|
|
153
|
+
const introspection = Constructor.introspect?.()
|
|
154
|
+
const description = introspection?.description || Constructor.description || 'No description provided'
|
|
155
|
+
sections.push(`## ${id}\n\n${description}\n`)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return sections.join('\n')
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Emit an event on the registry's event bus.
|
|
163
|
+
*
|
|
164
|
+
* @param event - The event to emit.
|
|
165
|
+
* @param args - The arguments to pass to the event listener.
|
|
166
|
+
* @returns The registry instance.
|
|
167
|
+
*/
|
|
168
|
+
emit(event: string, ...args: any[]) {
|
|
169
|
+
this._events.emit(event, ...args)
|
|
170
|
+
return this
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Subscribe to an event on the registry's event bus.
|
|
175
|
+
*
|
|
176
|
+
* @param event - The event to subscribe to.
|
|
177
|
+
* @param listener - The listener to call when the event is emitted.
|
|
178
|
+
* @returns The registry instance.
|
|
179
|
+
*/
|
|
180
|
+
on(event: string, listener: (...args: any[]) => void) {
|
|
181
|
+
this._events.on(event, listener)
|
|
182
|
+
return this
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Unsubscribe a listener from an event on the registry's event bus.
|
|
187
|
+
*
|
|
188
|
+
* @param event - The event to unsubscribe from.
|
|
189
|
+
* @param listener - The listener to unsubscribe.
|
|
190
|
+
* @returns The registry instance.
|
|
191
|
+
*/
|
|
192
|
+
off(event: string, listener: (...args: any[]) => void) {
|
|
193
|
+
this._events.off(event, listener)
|
|
194
|
+
return this
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Subscribe to an event on the registry's event bus, but only fire once.
|
|
199
|
+
*
|
|
200
|
+
* @param event - The event to subscribe to.
|
|
201
|
+
* @param listener - The listener to call when the event is emitted.
|
|
202
|
+
* @returns The registry instance.
|
|
203
|
+
*/
|
|
204
|
+
once(event: string, listener: (...args: any[]) => void) {
|
|
205
|
+
this._events.once(event, listener)
|
|
206
|
+
return this
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export { Registry }
|