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,534 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { FeatureStateSchema, FeatureOptionsSchema, FeatureEventsSchema } from '../../schemas/base.js'
|
|
3
|
+
import { type AvailableFeatures } from 'luca/feature'
|
|
4
|
+
import { Feature } from '../feature.js'
|
|
5
|
+
import type { Assistant } from './assistant.js'
|
|
6
|
+
import type { ConversationHistory, ConversationMeta, ConversationRecord } from './conversation-history.js'
|
|
7
|
+
import type { InterceptorFn, InterceptorPoint, InterceptorPoints } from '../lib/interceptor-chain.js'
|
|
8
|
+
import hashObject from '../../hash-object.js'
|
|
9
|
+
|
|
10
|
+
declare module 'luca/feature' {
|
|
11
|
+
interface AvailableFeatures {
|
|
12
|
+
assistantsManager: typeof AssistantsManager
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Metadata for a discovered assistant subdirectory.
|
|
18
|
+
*/
|
|
19
|
+
export interface AssistantEntry {
|
|
20
|
+
/** The subdirectory name, used as the assistant identifier. */
|
|
21
|
+
name: string
|
|
22
|
+
/** Absolute path to the assistant folder. */
|
|
23
|
+
folder: string
|
|
24
|
+
/** Whether a CORE.md system prompt file exists. */
|
|
25
|
+
hasCorePrompt: boolean
|
|
26
|
+
/** Whether a tools.ts file exists. */
|
|
27
|
+
hasTools: boolean
|
|
28
|
+
/** Whether a hooks.ts file exists. */
|
|
29
|
+
hasHooks: boolean
|
|
30
|
+
/** Whether a voice.yaml configuration file exists. */
|
|
31
|
+
hasVoice: boolean
|
|
32
|
+
/** Contents of ABOUT.md if present, undefined otherwise. */
|
|
33
|
+
about?: string
|
|
34
|
+
/** Frontmatter metadata parsed from CORE.md. */
|
|
35
|
+
meta?: Record<string, any>
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const AssistantsManagerEventsSchema = FeatureEventsSchema.extend({
|
|
39
|
+
discovered: z.tuple([]).describe('Emitted when assistant discovery scan completes'),
|
|
40
|
+
assistantCreated: z.tuple([
|
|
41
|
+
z.string().describe('The assistant name'),
|
|
42
|
+
z.any().describe('The assistant instance'),
|
|
43
|
+
]).describe('Emitted when a new assistant instance is created'),
|
|
44
|
+
assistantRegistered: z.tuple([
|
|
45
|
+
z.string().describe('The assistant id'),
|
|
46
|
+
]).describe('Emitted when an assistant factory is registered at runtime'),
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
export const AssistantsManagerStateSchema = FeatureStateSchema.extend({
|
|
50
|
+
discovered: z.boolean().describe('Whether discovery has been run'),
|
|
51
|
+
assistantCount: z.number().describe('Number of discovered assistant definitions'),
|
|
52
|
+
activeCount: z.number().describe('Number of currently instantiated assistants'),
|
|
53
|
+
entries: z.record(z.string(), z.any()).describe('Discovered assistant entries keyed by name'),
|
|
54
|
+
instances: z.record(z.string(), z.any()).describe('Active assistant instances keyed by name'),
|
|
55
|
+
factories: z.record(z.string(), z.any()).describe('Registered factory functions keyed by name'),
|
|
56
|
+
extraFolders: z.array(z.string()).describe('Additional folders to scan during discovery'),
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
export const AssistantsManagerOptionsSchema = FeatureOptionsSchema.extend({})
|
|
60
|
+
|
|
61
|
+
export type AssistantsManagerState = z.infer<typeof AssistantsManagerStateSchema>
|
|
62
|
+
export type AssistantsManagerOptions = z.infer<typeof AssistantsManagerOptionsSchema>
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Discovers and manages assistant definitions by looking for subdirectories
|
|
66
|
+
* in two locations: ~/.luca/assistants/ and cwd/assistants/. Each subdirectory
|
|
67
|
+
* containing a CORE.md is treated as an assistant definition.
|
|
68
|
+
*
|
|
69
|
+
* Use `discover()` to scan for available assistants, `list()` to enumerate them,
|
|
70
|
+
* and `create(name)` to instantiate one as a running Assistant feature.
|
|
71
|
+
*
|
|
72
|
+
* @extends Feature
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* const manager = container.feature('assistantsManager')
|
|
77
|
+
* manager.discover()
|
|
78
|
+
* console.log(manager.list()) // [{ name: 'chief-of-staff', folder: '...', ... }]
|
|
79
|
+
* const assistant = manager.create('chief-of-staff')
|
|
80
|
+
* const answer = await assistant.ask('Hello!')
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export class AssistantsManager extends Feature<AssistantsManagerState, AssistantsManagerOptions> {
|
|
84
|
+
static override stateSchema = AssistantsManagerStateSchema
|
|
85
|
+
static override optionsSchema = AssistantsManagerOptionsSchema
|
|
86
|
+
static override eventsSchema = AssistantsManagerEventsSchema
|
|
87
|
+
static override shortcut = 'features.assistantsManager' as const
|
|
88
|
+
|
|
89
|
+
static { Feature.register(this, 'assistantsManager') }
|
|
90
|
+
|
|
91
|
+
/** @returns Default state with discovery not yet run and zero counts. */
|
|
92
|
+
override get initialState(): AssistantsManagerState {
|
|
93
|
+
return {
|
|
94
|
+
...super.initialState,
|
|
95
|
+
discovered: false,
|
|
96
|
+
assistantCount: 0,
|
|
97
|
+
activeCount: 0,
|
|
98
|
+
entries: {},
|
|
99
|
+
instances: {},
|
|
100
|
+
factories: {},
|
|
101
|
+
extraFolders: [],
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
/** Discovered assistant entries keyed by name. */
|
|
107
|
+
get entries(): Record<string, AssistantEntry> {
|
|
108
|
+
return (this.state.get('entries') || {}) as Record<string, AssistantEntry>
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** Active assistant instances keyed by name. */
|
|
112
|
+
get instances(): Record<string, Assistant> {
|
|
113
|
+
return (this.state.get('instances') || {}) as Record<string, Assistant>
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** Registered factory functions keyed by name. */
|
|
117
|
+
get factories(): Record<string, (options: Record<string, any>) => Assistant> {
|
|
118
|
+
return (this.state.get('factories') || {}) as Record<string, (options: Record<string, any>) => Assistant>
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** Interceptor registrations to be applied to every assistant this manager creates. */
|
|
122
|
+
private _interceptors: Array<{ point: InterceptorPoint; fn: InterceptorFn<any> }> = []
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Registers a pipeline interceptor that is applied to every assistant created by this manager.
|
|
126
|
+
* Interceptors are applied at the given interception point on each assistant at creation time.
|
|
127
|
+
* This mirrors the per-assistant `assistant.intercept(point, fn)` API, but scopes it globally
|
|
128
|
+
* across all assistants managed here — useful for cross-cutting concerns like logging, tracing,
|
|
129
|
+
* or policy enforcement.
|
|
130
|
+
*
|
|
131
|
+
* @param {InterceptorPoint} point - The interception point (beforeAsk, beforeTurn, beforeToolCall, afterToolCall, beforeResponse)
|
|
132
|
+
* @param {InterceptorFn<InterceptorPoints[K]>} fn - Middleware function receiving (ctx, next)
|
|
133
|
+
* @returns {this} This instance, for chaining
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```typescript
|
|
137
|
+
* manager.intercept('beforeAsk', async (ctx, next) => {
|
|
138
|
+
* console.log(`[${ctx.assistant.name}] asking: ${ctx.message}`)
|
|
139
|
+
* await next()
|
|
140
|
+
* })
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
intercept<K extends InterceptorPoint>(point: K, fn: InterceptorFn<InterceptorPoints[K]>): this {
|
|
144
|
+
this._interceptors.push({ point, fn })
|
|
145
|
+
return this
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Discovers assistants by listing subdirectories in ~/.luca/assistants/
|
|
150
|
+
* and cwd/assistants/. Each subdirectory containing a CORE.md is an assistant.
|
|
151
|
+
*
|
|
152
|
+
* @returns {Promise<this>} This instance, for chaining
|
|
153
|
+
*/
|
|
154
|
+
/**
|
|
155
|
+
* Registers an additional folder to scan during assistant discovery and
|
|
156
|
+
* immediately triggers a new discovery pass.
|
|
157
|
+
*
|
|
158
|
+
* @param {string} folderPath - Absolute path to a folder containing assistant subdirectories
|
|
159
|
+
* @returns {Promise<this>} This instance, for chaining
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```typescript
|
|
163
|
+
* await manager.addDiscoveryFolder('/path/to/more/assistants')
|
|
164
|
+
* console.log(manager.available) // includes assistants from the new folder
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
async addDiscoveryFolder(folderPath: string): Promise<this> {
|
|
168
|
+
const current = this.state.get('extraFolders') as string[]
|
|
169
|
+
if (!current.includes(folderPath)) {
|
|
170
|
+
this.state.set('extraFolders', [...current, folderPath])
|
|
171
|
+
}
|
|
172
|
+
return this.discover()
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
async discover(): Promise<this> {
|
|
176
|
+
const { fs, paths, os } = this.container
|
|
177
|
+
|
|
178
|
+
const discovered: Record<string, AssistantEntry> = {}
|
|
179
|
+
|
|
180
|
+
const locations = [
|
|
181
|
+
`${os.homedir}/.luca/assistants`,
|
|
182
|
+
paths.resolve('assistants'),
|
|
183
|
+
...(this.state.get('extraFolders') as string[]),
|
|
184
|
+
]
|
|
185
|
+
|
|
186
|
+
for (const location of locations) {
|
|
187
|
+
if (!fs.exists(location)) continue
|
|
188
|
+
|
|
189
|
+
const dirEntries = fs.readdirSync(location)
|
|
190
|
+
|
|
191
|
+
for (const entry of dirEntries) {
|
|
192
|
+
const folder = `${location}/${entry}`
|
|
193
|
+
if (!fs.isDirectory(folder)) continue
|
|
194
|
+
|
|
195
|
+
const hasCorePrompt = fs.exists(`${folder}/CORE.md`)
|
|
196
|
+
if (!hasCorePrompt) continue
|
|
197
|
+
|
|
198
|
+
// Don't overwrite earlier entries (home takes precedence for same name)
|
|
199
|
+
if (!discovered[entry]) {
|
|
200
|
+
const hasAbout = fs.exists(`${folder}/ABOUT.md`)
|
|
201
|
+
let about: string | undefined
|
|
202
|
+
let meta: Record<string, any> | undefined
|
|
203
|
+
|
|
204
|
+
if (hasAbout) {
|
|
205
|
+
about = fs.readFileSync(`${folder}/ABOUT.md`, 'utf8') as string
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
try {
|
|
209
|
+
const coreContent = fs.readFileSync(`${folder}/CORE.md`, 'utf8') as string
|
|
210
|
+
const fmMatch = coreContent.match(/^---\r?\n([\s\S]*?)\r?\n---/)
|
|
211
|
+
if (fmMatch) {
|
|
212
|
+
const yaml = this.container.feature('yaml')
|
|
213
|
+
meta = yaml.parse(fmMatch[1]!)
|
|
214
|
+
}
|
|
215
|
+
} catch {
|
|
216
|
+
// CORE.md exists but couldn't be parsed — skip meta
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
discovered[entry] = {
|
|
220
|
+
name: entry,
|
|
221
|
+
folder,
|
|
222
|
+
hasCorePrompt: true,
|
|
223
|
+
hasTools: fs.exists(`${folder}/tools.ts`),
|
|
224
|
+
hasHooks: fs.exists(`${folder}/hooks.ts`),
|
|
225
|
+
hasVoice: fs.exists(`${folder}/voice.yaml`),
|
|
226
|
+
...(about != null && { about }),
|
|
227
|
+
...(meta != null && { meta }),
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
this.state.setState({
|
|
234
|
+
entries: discovered,
|
|
235
|
+
discovered: true,
|
|
236
|
+
assistantCount: Object.keys(discovered).length,
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
this.emit('discovered')
|
|
240
|
+
return this
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Downloads the core assistants that ship with luca from GitHub
|
|
245
|
+
* into ~/.luca/assistants.
|
|
246
|
+
*
|
|
247
|
+
* @returns {Promise<{ files: string[] }>} The files extracted
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```typescript
|
|
251
|
+
* const manager = container.feature('assistantsManager')
|
|
252
|
+
* await manager.downloadLucaCoreAssistants()
|
|
253
|
+
* await manager.discover()
|
|
254
|
+
* console.log(manager.available)
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
257
|
+
async downloadLucaCoreAssistants() {
|
|
258
|
+
const { os, paths } = this.container
|
|
259
|
+
const dest = `${os.homedir}/.luca/assistants`
|
|
260
|
+
const git = this.container.feature('git') as any
|
|
261
|
+
|
|
262
|
+
return await git.extractFolder({
|
|
263
|
+
source: 'soederpop/luca/assistants',
|
|
264
|
+
destination: dest,
|
|
265
|
+
})
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
get available() {
|
|
269
|
+
const entryKeys = Object.keys(this.entries)
|
|
270
|
+
const factoryKeys = Object.keys(this.factories)
|
|
271
|
+
return [...new Set([...entryKeys, ...factoryKeys])]
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Returns all discovered assistant entries as an array.
|
|
276
|
+
*
|
|
277
|
+
* @returns {AssistantEntry[]} All discovered entries
|
|
278
|
+
*/
|
|
279
|
+
list(): AssistantEntry[] {
|
|
280
|
+
const discovered = Object.values(this.entries)
|
|
281
|
+
const discoveredNames = new Set(discovered.map((e) => e.name))
|
|
282
|
+
|
|
283
|
+
// Include registered factories that weren't discovered on disk
|
|
284
|
+
const registeredOnly = Object.keys(this.factories)
|
|
285
|
+
.filter((name) => !discoveredNames.has(name))
|
|
286
|
+
.map((name): AssistantEntry => ({
|
|
287
|
+
name,
|
|
288
|
+
folder: '',
|
|
289
|
+
hasCorePrompt: false,
|
|
290
|
+
hasTools: false,
|
|
291
|
+
hasHooks: false,
|
|
292
|
+
hasVoice: false,
|
|
293
|
+
}))
|
|
294
|
+
|
|
295
|
+
return [...discovered, ...registeredOnly]
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Looks up a single assistant entry by name.
|
|
300
|
+
*
|
|
301
|
+
* @param {string} name - The assistant name (e.g. 'chief-of-staff')
|
|
302
|
+
* @returns {AssistantEntry | undefined} The entry, or undefined if not found
|
|
303
|
+
*/
|
|
304
|
+
get(name: string): AssistantEntry | undefined {
|
|
305
|
+
return this.entries[name]
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Registers a factory function that creates an assistant at runtime.
|
|
310
|
+
* Registered factories take precedence over discovered entries when
|
|
311
|
+
* calling `create()`.
|
|
312
|
+
*
|
|
313
|
+
* @param {string} id - The assistant identifier
|
|
314
|
+
* @param {(options: Record<string, any>) => Assistant} factory - Factory function that receives create options and returns an Assistant
|
|
315
|
+
* @returns {this} This instance, for chaining
|
|
316
|
+
*
|
|
317
|
+
* @example
|
|
318
|
+
* ```typescript
|
|
319
|
+
* manager.register('custom-bot', (options) => {
|
|
320
|
+
* return container.feature('assistant', {
|
|
321
|
+
* systemPrompt: 'You are a custom bot.',
|
|
322
|
+
* ...options,
|
|
323
|
+
* })
|
|
324
|
+
* })
|
|
325
|
+
* const bot = manager.create('custom-bot')
|
|
326
|
+
* ```
|
|
327
|
+
*/
|
|
328
|
+
register(id: string, factory: (options: Record<string, any>) => Assistant): this {
|
|
329
|
+
this.state.set('factories', { ...this.factories, [id]: factory })
|
|
330
|
+
this.emit('assistantRegistered', id)
|
|
331
|
+
return this
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Creates and returns a new Assistant feature instance for the given name.
|
|
336
|
+
* Checks runtime-registered factories first, then falls back to discovered entries.
|
|
337
|
+
* The assistant is configured with the discovered folder path. Any additional
|
|
338
|
+
* options are merged in.
|
|
339
|
+
*
|
|
340
|
+
* @param {string} name - The assistant name (must match a registered factory or discovered entry)
|
|
341
|
+
* @param {Record<string, any>} options - Additional options to pass to the Assistant constructor
|
|
342
|
+
* @returns {Assistant} The created assistant instance
|
|
343
|
+
* @throws {Error} If the name is not found among registered factories or discovered assistants
|
|
344
|
+
*
|
|
345
|
+
* @example
|
|
346
|
+
* ```typescript
|
|
347
|
+
* const assistant = manager.create('chief-of-staff', { model: 'gpt-4.1' })
|
|
348
|
+
* ```
|
|
349
|
+
*/
|
|
350
|
+
create(name: string, options: Record<string, any> = {}): Assistant {
|
|
351
|
+
// Check registered factories first
|
|
352
|
+
const factory = this.factories[name]
|
|
353
|
+
if (factory) {
|
|
354
|
+
const instance = factory(options)
|
|
355
|
+
this._bindAssistant(instance)
|
|
356
|
+
const updated = { ...this.instances, [name]: instance }
|
|
357
|
+
this.state.setState({ instances: updated, activeCount: Object.keys(updated).length })
|
|
358
|
+
this.emit('assistantCreated', name, instance)
|
|
359
|
+
return instance
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
const entry = this.get(name)
|
|
363
|
+
|
|
364
|
+
if (!entry) {
|
|
365
|
+
throw new Error(
|
|
366
|
+
`Assistant "${name}" not found. Available assistants: ${this.available.join(', ') || '(none — run discover() first)'}`
|
|
367
|
+
)
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
const instance = this.container.feature('assistant', {
|
|
371
|
+
folder: entry.folder,
|
|
372
|
+
...options,
|
|
373
|
+
})
|
|
374
|
+
|
|
375
|
+
this._bindAssistant(instance)
|
|
376
|
+
const updated = { ...this.instances, [name]: instance }
|
|
377
|
+
this.state.setState({ instances: updated, activeCount: Object.keys(updated).length })
|
|
378
|
+
this.emit('assistantCreated', name, instance)
|
|
379
|
+
|
|
380
|
+
return instance
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Wires an assistant into the manager: bridges all assistant events up to the manager
|
|
385
|
+
* as `assistantEvent:<eventName>` with (assistant, ...originalArgs), and applies any
|
|
386
|
+
* globally registered interceptors.
|
|
387
|
+
*/
|
|
388
|
+
private _bindAssistant(instance: Assistant): void {
|
|
389
|
+
instance.on('*', (event: string, ...args: any[]) => {
|
|
390
|
+
this.emit(`assistantEvent:${event}` as any, instance, ...args)
|
|
391
|
+
})
|
|
392
|
+
|
|
393
|
+
for (const { point, fn } of this._interceptors) {
|
|
394
|
+
instance.intercept(point, fn)
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Reload tools, hooks, and system prompt from disk for active assistants.
|
|
400
|
+
* When called with a name, reloads only that assistant. When called without
|
|
401
|
+
* arguments, reloads all active instances.
|
|
402
|
+
*
|
|
403
|
+
* @param {string} [name] - Optional assistant name to reload. Omit to reload all.
|
|
404
|
+
* @returns {{ reloaded: string[] }} Names of assistants that were reloaded
|
|
405
|
+
* @throws {Error} If a specific name is given but no active instance exists for it
|
|
406
|
+
*
|
|
407
|
+
* @example
|
|
408
|
+
* ```typescript
|
|
409
|
+
* manager.reload('researcher') // reload one
|
|
410
|
+
* manager.reload() // reload all active
|
|
411
|
+
* ```
|
|
412
|
+
*/
|
|
413
|
+
reload(name?: string): { reloaded: string[] } {
|
|
414
|
+
const reloaded: string[] = []
|
|
415
|
+
|
|
416
|
+
if (name) {
|
|
417
|
+
const instance = this.instances[name]
|
|
418
|
+
if (!instance) {
|
|
419
|
+
throw new Error(
|
|
420
|
+
`No active assistant "${name}" to reload. Active: ${Object.keys(this.instances).join(', ') || '(none)'}`
|
|
421
|
+
)
|
|
422
|
+
}
|
|
423
|
+
instance.reload()
|
|
424
|
+
reloaded.push(name)
|
|
425
|
+
} else {
|
|
426
|
+
for (const [key, instance] of Object.entries(this.instances)) {
|
|
427
|
+
instance.reload()
|
|
428
|
+
reloaded.push(key)
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
return { reloaded }
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Build the thread prefix for a given assistant name, matching the
|
|
437
|
+
* convention used by the Assistant class: `name:cwdHash:`.
|
|
438
|
+
* This allows history lookups without an active instance.
|
|
439
|
+
*
|
|
440
|
+
* @param {string} assistantId - The assistant name
|
|
441
|
+
* @returns {string} The thread prefix
|
|
442
|
+
*/
|
|
443
|
+
threadPrefixFor(assistantId: string): string {
|
|
444
|
+
const cwdHash = hashObject(this.container.cwd).slice(0, 8)
|
|
445
|
+
return `${assistantId}:${cwdHash}:`
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Load conversation history for an assistant. Works whether or not the
|
|
450
|
+
* assistant is currently instantiated — uses the thread prefix convention
|
|
451
|
+
* to query the conversationHistory feature directly.
|
|
452
|
+
*
|
|
453
|
+
* @param {string} assistantId - The assistant name (e.g. 'researcher')
|
|
454
|
+
* @param {object} [options] - Query options
|
|
455
|
+
* @param {number} [options.limit] - Maximum number of records to return
|
|
456
|
+
* @param {boolean} [options.includeMessages] - Load full records with messages (default: false, returns metadata only)
|
|
457
|
+
* @param {string} [options.thread] - Load a specific thread ID instead of all threads for this assistant
|
|
458
|
+
* @returns {Promise<ConversationMeta[] | ConversationRecord[]>} Metadata or full records, newest first
|
|
459
|
+
*
|
|
460
|
+
* @example
|
|
461
|
+
* ```typescript
|
|
462
|
+
* // List recent sessions (metadata only)
|
|
463
|
+
* const sessions = await manager.loadAssistantHistory('researcher', { limit: 5 })
|
|
464
|
+
*
|
|
465
|
+
* // Load full records with messages
|
|
466
|
+
* const full = await manager.loadAssistantHistory('researcher', { includeMessages: true, limit: 3 })
|
|
467
|
+
*
|
|
468
|
+
* // Load a specific thread
|
|
469
|
+
* const thread = await manager.loadAssistantHistory('researcher', { thread: 'researcher:abc12345:2026-04-12' })
|
|
470
|
+
* ```
|
|
471
|
+
*/
|
|
472
|
+
async loadAssistantHistory(
|
|
473
|
+
assistantId: string,
|
|
474
|
+
options?: { limit?: number; includeMessages?: boolean; thread?: string },
|
|
475
|
+
): Promise<ConversationMeta[] | ConversationRecord[]> {
|
|
476
|
+
const history = this.container.feature('conversationHistory') as ConversationHistory
|
|
477
|
+
|
|
478
|
+
if (options?.thread) {
|
|
479
|
+
const record = await history.findByThread(options.thread)
|
|
480
|
+
return record ? [record] : []
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
const prefix = this.threadPrefixFor(assistantId)
|
|
484
|
+
const metas = await history.findByThreadPrefix(prefix)
|
|
485
|
+
const limited = options?.limit ? metas.slice(0, options.limit) : metas
|
|
486
|
+
|
|
487
|
+
if (!options?.includeMessages) return limited
|
|
488
|
+
|
|
489
|
+
const records: ConversationRecord[] = []
|
|
490
|
+
for (const meta of limited) {
|
|
491
|
+
const record = await history.load(meta.id)
|
|
492
|
+
if (record) records.push(record)
|
|
493
|
+
}
|
|
494
|
+
return records
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* Returns a previously created assistant instance by name.
|
|
499
|
+
*
|
|
500
|
+
* @param {string} name - The assistant name
|
|
501
|
+
* @returns {Assistant | undefined} The instance, or undefined if not yet created
|
|
502
|
+
*/
|
|
503
|
+
getInstance(name: string): Assistant | undefined {
|
|
504
|
+
return this.instances[name]
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Generates a markdown summary of all discovered assistants,
|
|
509
|
+
* listing their names and which definition files are present.
|
|
510
|
+
*
|
|
511
|
+
* @returns {string} Markdown-formatted summary
|
|
512
|
+
*/
|
|
513
|
+
toSummary(): string {
|
|
514
|
+
const entries = this.list()
|
|
515
|
+
|
|
516
|
+
if (entries.length === 0) {
|
|
517
|
+
return '## Assistants\n\nNo assistants discovered.'
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
const lines = entries.map((e) => {
|
|
521
|
+
const files = [
|
|
522
|
+
e.hasCorePrompt && 'CORE.md',
|
|
523
|
+
e.hasTools && 'tools.ts',
|
|
524
|
+
e.hasHooks && 'hooks.ts',
|
|
525
|
+
].filter(Boolean)
|
|
526
|
+
|
|
527
|
+
return `- **${e.name}** — ${files.join(', ')}`
|
|
528
|
+
})
|
|
529
|
+
|
|
530
|
+
return `## Assistants\n\n${lines.join('\n')}`
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
export default AssistantsManager
|