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,535 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { FeatureEventsSchema, FeatureStateSchema, FeatureOptionsSchema } from '../../schemas/base.js'
|
|
3
|
+
import { State } from "../../state.js";
|
|
4
|
+
import { Feature } from "../feature.js";
|
|
5
|
+
import { parse, relative, join as pathJoin } from "path";
|
|
6
|
+
import { statSync, readFileSync, existsSync, readdirSync, lstatSync } from "fs";
|
|
7
|
+
import micromatch from "micromatch";
|
|
8
|
+
import { castArray } from "lodash-es";
|
|
9
|
+
import chokidar from "chokidar";
|
|
10
|
+
import type { FSWatcher } from "chokidar";
|
|
11
|
+
|
|
12
|
+
type File = {
|
|
13
|
+
absolutePath: string;
|
|
14
|
+
relativePath: string;
|
|
15
|
+
relativeDirname: string;
|
|
16
|
+
dirname: string;
|
|
17
|
+
name: string;
|
|
18
|
+
extension: string;
|
|
19
|
+
size: number;
|
|
20
|
+
modifiedAt: Date;
|
|
21
|
+
createdAt: Date;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const FileManagerStateSchema = FeatureStateSchema.extend({
|
|
25
|
+
/** Whether the file manager has completed its initial scan */
|
|
26
|
+
started: z.boolean().optional().describe('Whether the file manager has completed its initial scan'),
|
|
27
|
+
/** Whether the file manager is currently scanning files */
|
|
28
|
+
starting: z.boolean().optional().describe('Whether the file manager is currently scanning files'),
|
|
29
|
+
/** Whether the file watcher is actively monitoring for changes */
|
|
30
|
+
watching: z.boolean().optional().describe('Whether the file watcher is actively monitoring for changes'),
|
|
31
|
+
/** Whether the initial scan failed */
|
|
32
|
+
failed: z.boolean().optional().describe('Whether the initial file scan failed'),
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
export const FileManagerOptionsSchema = FeatureOptionsSchema.extend({
|
|
36
|
+
/** Glob patterns to exclude from file scanning */
|
|
37
|
+
exclude: z.union([z.string(), z.array(z.string())]).optional().describe('Glob patterns to exclude from file scanning'),
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
export const FileManagerEventsSchema = FeatureEventsSchema.extend({
|
|
41
|
+
'file:change': z.tuple([
|
|
42
|
+
z.object({
|
|
43
|
+
type: z.enum(['add', 'change', 'delete']).describe('The type of file change'),
|
|
44
|
+
path: z.string().describe('Absolute path to the changed file'),
|
|
45
|
+
}).describe('File change event payload'),
|
|
46
|
+
]).describe('Emitted when a watched file is added, changed, or deleted'),
|
|
47
|
+
}).describe('FileManager events')
|
|
48
|
+
|
|
49
|
+
export type FileManagerState = z.infer<typeof FileManagerStateSchema>
|
|
50
|
+
export type FileManagerOptions = z.infer<typeof FileManagerOptionsSchema>
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The FileManager feature creates a database like index of all of the files in the project,
|
|
54
|
+
* and provides metadata about these files, and also provides a way to watch for changes to the files.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* const fileManager = container.feature('fileManager')
|
|
59
|
+
* await fileManager.start()
|
|
60
|
+
*
|
|
61
|
+
* const fileIds = fileManager.fileIds
|
|
62
|
+
* const typescriptFiles = fileManager.matchFiles("**ts")
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export class FileManager<
|
|
66
|
+
T extends FileManagerState = FileManagerState,
|
|
67
|
+
K extends FileManagerOptions = FileManagerOptions
|
|
68
|
+
> extends Feature<T, K> {
|
|
69
|
+
|
|
70
|
+
static override shortcut = 'features.fileManager' as const
|
|
71
|
+
static override stateSchema = FileManagerStateSchema
|
|
72
|
+
static override optionsSchema = FileManagerOptionsSchema
|
|
73
|
+
static override eventsSchema = FileManagerEventsSchema
|
|
74
|
+
static { Feature.register(this, 'fileManager') }
|
|
75
|
+
|
|
76
|
+
files: State<Record<string, File>> = new State<Record<string, File>>({
|
|
77
|
+
initialState: {},
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
/** Returns an array of all relative file paths indexed by the file manager. */
|
|
81
|
+
get fileIds(): string[] {
|
|
82
|
+
return Array.from(this.files.keys());
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Returns an array of all file metadata objects indexed by the file manager. */
|
|
86
|
+
get fileObjects(): File[] {
|
|
87
|
+
return Array.from(this.files.values());
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Matches the file IDs against the pattern(s) provided
|
|
92
|
+
* @param {string | string[]} patterns - The patterns to match against the file IDs
|
|
93
|
+
* @returns {string[]} The file IDs that match the patterns
|
|
94
|
+
*/
|
|
95
|
+
match(patterns: string | string[]): string[] {
|
|
96
|
+
return micromatch(this.files.keys(), patterns);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Matches the file IDs against the pattern(s) provided and returns the file objects for each.
|
|
101
|
+
*
|
|
102
|
+
* @param {string | string[]} patterns - The patterns to match against the file IDs
|
|
103
|
+
* @returns {File[]} The file objects that match the patterns
|
|
104
|
+
*/
|
|
105
|
+
matchFiles(patterns: string | string[]): (File | undefined)[] {
|
|
106
|
+
const fileIds = this.match(Array.isArray(patterns) ? patterns : [patterns]);
|
|
107
|
+
return fileIds.map((fileId) => this.files.get(fileId));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Returns the directory IDs for all of the files in the project.
|
|
112
|
+
*/
|
|
113
|
+
get directoryIds(): string[] {
|
|
114
|
+
return Array.from(
|
|
115
|
+
new Set(
|
|
116
|
+
this.files
|
|
117
|
+
.values()
|
|
118
|
+
.map((file) => this.container.paths.relative(file.dirname))
|
|
119
|
+
.filter(v => v.length)
|
|
120
|
+
)
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Returns an array of unique file extensions found across all indexed files. */
|
|
125
|
+
get uniqueExtensions(): string[] {
|
|
126
|
+
return Array.from(
|
|
127
|
+
new Set(
|
|
128
|
+
this.files.values().map((file) => file.extension)
|
|
129
|
+
)
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Whether the file manager has completed its initial scan. */
|
|
134
|
+
get isStarted(): boolean {
|
|
135
|
+
return !!this.state.get("started");
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Whether the file manager is currently performing its initial scan. */
|
|
139
|
+
get isStarting(): boolean {
|
|
140
|
+
return !!this.state.get("starting");
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Whether the file watcher is actively monitoring for changes. */
|
|
144
|
+
get isWatching(): boolean {
|
|
145
|
+
return !!this.state.get("watching");
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** Returns the list of directories currently being watched. */
|
|
149
|
+
get watchedPaths(): string[] {
|
|
150
|
+
return (this.state.get("watchedPaths") as string[] | undefined) || [];
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Starts the file manager and scans the files in the project.
|
|
155
|
+
* @param {object} [options={}] - Options for the file manager
|
|
156
|
+
* @param {string | string[]} [options.exclude] - The patterns to exclude from the scan
|
|
157
|
+
* @returns {Promise<FileManager>} The file manager instance
|
|
158
|
+
*/
|
|
159
|
+
async start(options: { exclude?: string | string[] } = {}): Promise<this> {
|
|
160
|
+
if (this.isStarted) {
|
|
161
|
+
return this;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (this.isStarting) {
|
|
165
|
+
await this.waitFor("started");
|
|
166
|
+
return this;
|
|
167
|
+
} else {
|
|
168
|
+
this.state.set("starting", true);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
try {
|
|
172
|
+
const loaded = await this.loadFromCache();
|
|
173
|
+
if (!loaded) {
|
|
174
|
+
await this.scanFiles(options);
|
|
175
|
+
await this.writeToCache();
|
|
176
|
+
}
|
|
177
|
+
} catch (error) {
|
|
178
|
+
console.error(error);
|
|
179
|
+
this.state.set("failed", true);
|
|
180
|
+
} finally {
|
|
181
|
+
this.state.set("started", true);
|
|
182
|
+
this.state.set("starting", false);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return this;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Attempts to load the file index from disk cache.
|
|
190
|
+
* Only uses cache when in a clean git repo (sha hasn't changed, no dirty files).
|
|
191
|
+
* @returns true if cache was loaded successfully, false otherwise
|
|
192
|
+
*/
|
|
193
|
+
/**
|
|
194
|
+
* Reads the current git SHA by reading .git/HEAD directly,
|
|
195
|
+
* avoiding the ~19ms cost of shelling out to `git rev-parse HEAD`.
|
|
196
|
+
*/
|
|
197
|
+
private readGitShaFast(): string | null {
|
|
198
|
+
try {
|
|
199
|
+
const { git } = this.container;
|
|
200
|
+
if (!git.isRepo) return null;
|
|
201
|
+
|
|
202
|
+
const gitDir = pathJoin(git.repoRoot!, '.git');
|
|
203
|
+
const head = readFileSync(pathJoin(gitDir, 'HEAD'), 'utf8').trim();
|
|
204
|
+
|
|
205
|
+
// Detached HEAD — already a sha
|
|
206
|
+
if (!head.startsWith('ref: ')) return head;
|
|
207
|
+
|
|
208
|
+
// Resolve the ref
|
|
209
|
+
const refPath = pathJoin(gitDir, head.slice(5));
|
|
210
|
+
if (existsSync(refPath)) {
|
|
211
|
+
return readFileSync(refPath, 'utf8').trim();
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Packed refs fallback
|
|
215
|
+
const packedRefsPath = pathJoin(gitDir, 'packed-refs');
|
|
216
|
+
if (existsSync(packedRefsPath)) {
|
|
217
|
+
const ref = head.slice(5);
|
|
218
|
+
const packed = readFileSync(packedRefsPath, 'utf8');
|
|
219
|
+
const match = packed.match(new RegExp(`^([0-9a-f]{40}) ${ref}`, 'm'));
|
|
220
|
+
if (match) return match[1] ?? null;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return null;
|
|
224
|
+
} catch {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
private async loadFromCache(): Promise<boolean> {
|
|
230
|
+
try {
|
|
231
|
+
const sha = this.readGitShaFast();
|
|
232
|
+
if (!sha) return false;
|
|
233
|
+
|
|
234
|
+
const cache = this.container.feature('diskCache') as any;
|
|
235
|
+
const cacheKey = `file-index:${sha}`;
|
|
236
|
+
|
|
237
|
+
if (!(await cache.has(cacheKey))) return false;
|
|
238
|
+
|
|
239
|
+
const cached = await cache.get(cacheKey, true) as { dirs: Record<string, number>, files: Record<string, any> };
|
|
240
|
+
if (!cached?.files || !cached?.dirs) return false;
|
|
241
|
+
|
|
242
|
+
// Check if any directory mtime has changed — catches new/deleted/renamed files
|
|
243
|
+
for (const [dir, cachedMtimeMs] of Object.entries(cached.dirs)) {
|
|
244
|
+
try {
|
|
245
|
+
const current = statSync(dir).mtimeMs;
|
|
246
|
+
if (current !== cachedMtimeMs) return false;
|
|
247
|
+
} catch {
|
|
248
|
+
// Directory no longer exists
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
for (const [relativePath, file] of Object.entries(cached.files)) {
|
|
254
|
+
this.files.set(relativePath, {
|
|
255
|
+
...file as File,
|
|
256
|
+
modifiedAt: new Date((file as any).modifiedAt),
|
|
257
|
+
createdAt: new Date((file as any).createdAt),
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return true;
|
|
262
|
+
} catch {
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Writes the current file index to disk cache, keyed by git sha.
|
|
269
|
+
* Stores directory mtimes alongside file data so the cache can be
|
|
270
|
+
* invalidated when files are added/removed without a new commit.
|
|
271
|
+
*/
|
|
272
|
+
private async writeToCache(): Promise<void> {
|
|
273
|
+
try {
|
|
274
|
+
const sha = this.readGitShaFast();
|
|
275
|
+
if (!sha) return;
|
|
276
|
+
|
|
277
|
+
const cache = this.container.feature('diskCache') as any;
|
|
278
|
+
const cacheKey = `file-index:${sha}`;
|
|
279
|
+
|
|
280
|
+
// Collect unique directories and their mtimes
|
|
281
|
+
const dirs: Record<string, number> = {};
|
|
282
|
+
const files: Record<string, any> = {};
|
|
283
|
+
|
|
284
|
+
for (const [key, file] of this.files.entries()) {
|
|
285
|
+
files[key] = file;
|
|
286
|
+
if (!dirs[file.dirname]) {
|
|
287
|
+
try {
|
|
288
|
+
dirs[file.dirname] = statSync(file.dirname).mtimeMs;
|
|
289
|
+
} catch {}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
await cache.set(cacheKey, { dirs, files });
|
|
294
|
+
} catch {
|
|
295
|
+
// Cache write failure is non-fatal
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Scans the files in the project and updates the file manager state.
|
|
301
|
+
* @param {object} [options={}] - Options for the file manager
|
|
302
|
+
* @param {string | string[]} [options.exclude] - The patterns to exclude from the scan
|
|
303
|
+
* @returns {Promise<FileManager>} The file manager instance
|
|
304
|
+
*/
|
|
305
|
+
async scanFiles(options: { exclude?: string | string[] } = {}): Promise<this> {
|
|
306
|
+
const { cwd, git, fs } = this.container;
|
|
307
|
+
|
|
308
|
+
const fileIds: string[] = [];
|
|
309
|
+
|
|
310
|
+
if (!Array.isArray(options.exclude)) {
|
|
311
|
+
options.exclude = [options.exclude!].filter((v) => v?.length);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const { exclude = ["dist", "node_modules", "out"] } = options;
|
|
315
|
+
|
|
316
|
+
exclude.push(...castArray(this.options.exclude!).filter((v) => v?.length));
|
|
317
|
+
|
|
318
|
+
exclude.push("node_modules");
|
|
319
|
+
exclude.push("out");
|
|
320
|
+
exclude.push("dist");
|
|
321
|
+
|
|
322
|
+
if (git.isRepo) {
|
|
323
|
+
const repoRoot = git.repoRoot;
|
|
324
|
+
const cwdRelative = repoRoot ? relative(repoRoot, cwd) : '';
|
|
325
|
+
const baseDir = cwdRelative || '';
|
|
326
|
+
|
|
327
|
+
const deleted = await git.lsFiles({ deleted: true, baseDir })
|
|
328
|
+
await git.lsFiles({ baseDir }).then((results) => fileIds.push(...results.filter((id:string) => !deleted.includes(id))));
|
|
329
|
+
await git
|
|
330
|
+
.lsFiles({ others: true, includeIgnored: true, exclude, baseDir })
|
|
331
|
+
.then((results) => fileIds.push(...results.filter((id:string) => !deleted.includes(id))));
|
|
332
|
+
|
|
333
|
+
// git ls-files returns paths relative to repo root; make them relative to cwd
|
|
334
|
+
if (cwdRelative) {
|
|
335
|
+
const prefix = cwdRelative + '/';
|
|
336
|
+
for (let i = 0; i < fileIds.length; i++) {
|
|
337
|
+
if (fileIds[i]!.startsWith(prefix)) {
|
|
338
|
+
fileIds[i] = fileIds[i]!.slice(prefix.length);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// git ls-files doesn't traverse symlinked directories — walk them via fs
|
|
344
|
+
// to pick up their contents. fs.walk now follows symlinks natively.
|
|
345
|
+
try {
|
|
346
|
+
const topEntries = readdirSync(cwd, { withFileTypes: true });
|
|
347
|
+
for (const entry of topEntries) {
|
|
348
|
+
if (entry.isSymbolicLink()) {
|
|
349
|
+
const fullPath = pathJoin(cwd, entry.name);
|
|
350
|
+
try {
|
|
351
|
+
const target = statSync(fullPath);
|
|
352
|
+
if (target.isDirectory()) {
|
|
353
|
+
const walked = await fs.walkAsync(fullPath, { exclude });
|
|
354
|
+
for (const absFile of walked.files) {
|
|
355
|
+
fileIds.push(relative(cwd, absFile));
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
} catch {}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
} catch {}
|
|
362
|
+
} else {
|
|
363
|
+
// fs.walkAsync follows symlinks, so non-git repos get symlink support for free
|
|
364
|
+
await fs.walkAsync(cwd).then(({ files } : { files: string[] }) => fileIds.push(...files));
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
fileIds.forEach((relativePath) => {
|
|
368
|
+
const absolutePath = this.container.paths.resolve(relativePath);
|
|
369
|
+
const { name, ext, dir } = parse(absolutePath);
|
|
370
|
+
|
|
371
|
+
let size = 0
|
|
372
|
+
let modifiedAt = new Date(0)
|
|
373
|
+
let createdAt = new Date(0)
|
|
374
|
+
|
|
375
|
+
try {
|
|
376
|
+
const stats = statSync(absolutePath);
|
|
377
|
+
size = stats.size;
|
|
378
|
+
modifiedAt = stats.mtime;
|
|
379
|
+
createdAt = stats.birthtime;
|
|
380
|
+
} catch (error) {
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
this.files.set(relativePath, {
|
|
384
|
+
dirname: dir,
|
|
385
|
+
absolutePath,
|
|
386
|
+
relativePath,
|
|
387
|
+
relativeDirname: this.container.paths.relative(dir),
|
|
388
|
+
name,
|
|
389
|
+
extension: ext,
|
|
390
|
+
size,
|
|
391
|
+
modifiedAt,
|
|
392
|
+
createdAt,
|
|
393
|
+
});
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
return this;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
watcher: FSWatcher | null = null;
|
|
400
|
+
|
|
401
|
+
/** Returns the directories and files currently being watched by chokidar. */
|
|
402
|
+
get watchedFiles(): Record<string, string[]> {
|
|
403
|
+
return this.watcher?.getWatched() || {};
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Watches directories for file changes. Can be called multiple times to add
|
|
408
|
+
* more directories to an existing watcher. Tracks all watched paths in state.
|
|
409
|
+
*
|
|
410
|
+
* When called without `paths`, watches the project's `directoryIds` (default behavior).
|
|
411
|
+
* When called with `paths`, watches only those specific directories/globs.
|
|
412
|
+
* Subsequent calls add to the existing watcher — they never replace what's already watched.
|
|
413
|
+
*
|
|
414
|
+
* @param {object} [options={}] - Options for the file manager
|
|
415
|
+
* @param {string | string[]} [options.paths] - Specific directories or globs to watch. Defaults to project directoryIds.
|
|
416
|
+
* @param {string | string[]} [options.exclude] - The patterns to exclude from the watch
|
|
417
|
+
* @returns {Promise<void>}
|
|
418
|
+
*/
|
|
419
|
+
async watch(options: { paths?: string | string[]; exclude?: string | string[] } = {}): Promise<void> {
|
|
420
|
+
const pathsToWatch = castArray(options.paths || this.directoryIds.map(id => this.container.paths.resolve(id)))
|
|
421
|
+
.map(p => this.container.paths.resolve(p));
|
|
422
|
+
|
|
423
|
+
// If already watching, just add the new paths
|
|
424
|
+
if (this.isWatching && this.watcher) {
|
|
425
|
+
const currentPaths: string[] = (this.state.get("watchedPaths") as string[] | undefined) || [];
|
|
426
|
+
const newPaths = pathsToWatch.filter(p => !currentPaths.includes(p));
|
|
427
|
+
|
|
428
|
+
if (newPaths.length) {
|
|
429
|
+
this.watcher.add(newPaths);
|
|
430
|
+
this.state.set("watchedPaths", [...currentPaths, ...newPaths] as any);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
if (!Array.isArray(options.exclude)) {
|
|
437
|
+
options.exclude = [options.exclude!].filter((v) => v?.length);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const {
|
|
441
|
+
exclude = [".git/**", "dist/**", "node_modules/**", "out/**", "build/**"],
|
|
442
|
+
} = options;
|
|
443
|
+
|
|
444
|
+
exclude.push(...castArray(this.options.exclude!).filter((v) => v?.length));
|
|
445
|
+
|
|
446
|
+
const watcher = chokidar.watch(pathsToWatch, {
|
|
447
|
+
ignoreInitial: true,
|
|
448
|
+
persistent: true,
|
|
449
|
+
ignored: [
|
|
450
|
+
'.git/**',
|
|
451
|
+
...[".git", "dist/**", "node_modules/**", "out/**", "build/**"],
|
|
452
|
+
...exclude,
|
|
453
|
+
].map((pattern) => micromatch.makeRe(pattern)).concat([
|
|
454
|
+
/\.git/,
|
|
455
|
+
/node_modules/
|
|
456
|
+
]),
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
watcher
|
|
460
|
+
.on("add", (path) => {
|
|
461
|
+
this.updateFile(path);
|
|
462
|
+
this.emit("file:change", {
|
|
463
|
+
type: "add",
|
|
464
|
+
path,
|
|
465
|
+
});
|
|
466
|
+
})
|
|
467
|
+
.on("change", (path) => {
|
|
468
|
+
this.updateFile(path);
|
|
469
|
+
this.emit("file:change", {
|
|
470
|
+
type: "change",
|
|
471
|
+
path,
|
|
472
|
+
});
|
|
473
|
+
})
|
|
474
|
+
.on("unlink", (path) => {
|
|
475
|
+
this.removeFile(path);
|
|
476
|
+
this.emit("file:change", {
|
|
477
|
+
type: "delete",
|
|
478
|
+
path,
|
|
479
|
+
});
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
watcher.on("ready", () => {
|
|
483
|
+
this.state.set("watching", true);
|
|
484
|
+
this.state.set("watchedPaths", pathsToWatch as any);
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
this.watcher = watcher;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
async stopWatching(): Promise<void> {
|
|
491
|
+
if (!this.isWatching) {
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
if (this.watcher) {
|
|
496
|
+
this.watcher.close();
|
|
497
|
+
this.state.set("watching", false);
|
|
498
|
+
this.state.set("watchedPaths", [] as any);
|
|
499
|
+
this.watcher = null;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
async updateFile(path: string): Promise<void> {
|
|
504
|
+
const absolutePath = this.container.paths.resolve(path);
|
|
505
|
+
const { name, ext, dir } = parse(absolutePath);
|
|
506
|
+
|
|
507
|
+
try {
|
|
508
|
+
const stats = statSync(absolutePath);
|
|
509
|
+
this.files.set(path, {
|
|
510
|
+
dirname: dir,
|
|
511
|
+
relativeDirname: this.container.paths.relative(dir),
|
|
512
|
+
absolutePath,
|
|
513
|
+
relativePath: path,
|
|
514
|
+
name,
|
|
515
|
+
extension: ext,
|
|
516
|
+
size: stats.size,
|
|
517
|
+
modifiedAt: stats.mtime,
|
|
518
|
+
createdAt: stats.birthtime,
|
|
519
|
+
});
|
|
520
|
+
} catch (err: any) {
|
|
521
|
+
// File may have been moved or deleted by an event handler — remove from index gracefully
|
|
522
|
+
if (err.code === 'ENOENT') {
|
|
523
|
+
this.files.delete(path);
|
|
524
|
+
} else {
|
|
525
|
+
throw err;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
async removeFile(path: string): Promise<void> {
|
|
531
|
+
this.files.delete(path);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
export default FileManager
|