luca 2.0.0 → 3.0.0
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 +169 -0
- package/AGENTS.md +99 -0
- package/CLAUDE.md +115 -0
- package/CNAME +1 -0
- package/README.md +257 -9
- package/RUNME.md +56 -0
- package/assistants/codingAssistant/ABOUT.md +5 -0
- package/assistants/codingAssistant/CORE.md +28 -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 +2769 -0
- package/bunfig.toml +3 -0
- package/commands/audit-docs.ts +740 -0
- package/commands/build-bootstrap.ts +118 -0
- package/commands/build-python-bridge.ts +43 -0
- package/commands/build-scaffolds.ts +176 -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/docs/CLI.md +335 -0
- package/docs/CNAME +1 -0
- package/docs/README.md +60 -0
- package/docs/TABLE-OF-CONTENTS.md +183 -0
- package/docs/apis/clients/elevenlabs.md +308 -0
- package/docs/apis/clients/graph.md +107 -0
- package/docs/apis/clients/openai.md +429 -0
- package/docs/apis/clients/rest.md +161 -0
- package/docs/apis/clients/websocket.md +174 -0
- package/docs/apis/features/agi/assistant.md +625 -0
- package/docs/apis/features/agi/assistants-manager.md +282 -0
- package/docs/apis/features/agi/auto-assistant.md +279 -0
- package/docs/apis/features/agi/browser-use.md +802 -0
- package/docs/apis/features/agi/claude-code.md +884 -0
- package/docs/apis/features/agi/conversation-history.md +364 -0
- package/docs/apis/features/agi/conversation.md +548 -0
- package/docs/apis/features/agi/docs-reader.md +99 -0
- package/docs/apis/features/agi/file-tools.md +163 -0
- package/docs/apis/features/agi/luca-coder.md +407 -0
- package/docs/apis/features/agi/openai-codex.md +396 -0
- package/docs/apis/features/agi/openapi.md +138 -0
- package/docs/apis/features/agi/semantic-search.md +387 -0
- package/docs/apis/features/agi/skills-library.md +239 -0
- package/docs/apis/features/node/container-link.md +192 -0
- package/docs/apis/features/node/content-db.md +450 -0
- package/docs/apis/features/node/disk-cache.md +379 -0
- package/docs/apis/features/node/dns.md +652 -0
- package/docs/apis/features/node/docker.md +706 -0
- package/docs/apis/features/node/downloader.md +81 -0
- package/docs/apis/features/node/esbuild.md +60 -0
- package/docs/apis/features/node/file-manager.md +191 -0
- package/docs/apis/features/node/fs.md +1217 -0
- package/docs/apis/features/node/git.md +371 -0
- package/docs/apis/features/node/google-auth.md +193 -0
- package/docs/apis/features/node/google-calendar.md +202 -0
- package/docs/apis/features/node/google-docs.md +173 -0
- package/docs/apis/features/node/google-drive.md +246 -0
- package/docs/apis/features/node/google-mail.md +214 -0
- package/docs/apis/features/node/google-sheets.md +194 -0
- package/docs/apis/features/node/grep.md +292 -0
- package/docs/apis/features/node/helpers.md +164 -0
- package/docs/apis/features/node/ink.md +334 -0
- package/docs/apis/features/node/ipc-socket.md +249 -0
- package/docs/apis/features/node/json-tree.md +86 -0
- package/docs/apis/features/node/networking.md +316 -0
- package/docs/apis/features/node/nlp.md +133 -0
- package/docs/apis/features/node/opener.md +97 -0
- package/docs/apis/features/node/os.md +146 -0
- package/docs/apis/features/node/package-finder.md +392 -0
- package/docs/apis/features/node/postgres.md +234 -0
- package/docs/apis/features/node/proc.md +399 -0
- package/docs/apis/features/node/process-manager.md +305 -0
- package/docs/apis/features/node/python.md +604 -0
- package/docs/apis/features/node/redis.md +380 -0
- package/docs/apis/features/node/repl.md +88 -0
- package/docs/apis/features/node/runpod.md +674 -0
- package/docs/apis/features/node/secure-shell.md +176 -0
- package/docs/apis/features/node/semantic-search.md +408 -0
- package/docs/apis/features/node/sqlite.md +233 -0
- package/docs/apis/features/node/telegram.md +279 -0
- package/docs/apis/features/node/transpiler.md +74 -0
- package/docs/apis/features/node/tts.md +133 -0
- package/docs/apis/features/node/ui.md +701 -0
- package/docs/apis/features/node/vault.md +59 -0
- package/docs/apis/features/node/vm.md +75 -0
- package/docs/apis/features/node/yaml-tree.md +85 -0
- package/docs/apis/features/node/yaml.md +176 -0
- package/docs/apis/features/web/asset-loader.md +59 -0
- package/docs/apis/features/web/container-link.md +192 -0
- package/docs/apis/features/web/esbuild.md +54 -0
- package/docs/apis/features/web/helpers.md +164 -0
- package/docs/apis/features/web/network.md +44 -0
- package/docs/apis/features/web/speech.md +69 -0
- package/docs/apis/features/web/vault.md +59 -0
- package/docs/apis/features/web/vm.md +75 -0
- package/docs/apis/features/web/voice.md +84 -0
- package/docs/apis/servers/express.md +171 -0
- package/docs/apis/servers/mcp.md +238 -0
- package/docs/apis/servers/websocket.md +170 -0
- package/docs/bootstrap/CLAUDE.md +101 -0
- package/docs/bootstrap/SKILL.md +341 -0
- package/docs/bootstrap/templates/about-command.ts +41 -0
- package/docs/bootstrap/templates/docs-models.ts +22 -0
- package/docs/bootstrap/templates/docs-readme.md +43 -0
- package/docs/bootstrap/templates/example-feature.ts +53 -0
- package/docs/bootstrap/templates/health-endpoint.ts +15 -0
- package/docs/bootstrap/templates/luca-cli.ts +30 -0
- package/docs/bootstrap/templates/runme.md +54 -0
- package/docs/challenges/caching-proxy.md +16 -0
- package/docs/challenges/content-db-round-trip.md +14 -0
- package/docs/challenges/custom-command.md +9 -0
- package/docs/challenges/file-watcher-pipeline.md +11 -0
- package/docs/challenges/grep-audit-report.md +15 -0
- package/docs/challenges/multi-feature-dashboard.md +14 -0
- package/docs/challenges/process-orchestrator.md +17 -0
- package/docs/challenges/rest-api-server-with-client.md +12 -0
- package/docs/challenges/script-runner-with-vm.md +11 -0
- package/docs/challenges/simple-rest-api.md +15 -0
- package/docs/challenges/websocket-serve-and-client.md +11 -0
- package/docs/challenges/yaml-config-system.md +14 -0
- package/docs/command-system-overhaul.md +94 -0
- package/docs/documentation-audit.md +134 -0
- package/docs/examples/assistant/CORE.md +18 -0
- package/docs/examples/assistant/hooks.ts +3 -0
- package/docs/examples/assistant/tools.ts +10 -0
- package/docs/examples/assistant-hooks-reference.ts +171 -0
- package/docs/examples/assistant-with-process-manager.md +84 -0
- package/docs/examples/content-db.md +77 -0
- package/docs/examples/disk-cache.md +83 -0
- package/docs/examples/docker.md +101 -0
- package/docs/examples/downloader.md +70 -0
- package/docs/examples/entity.md +124 -0
- package/docs/examples/esbuild.md +80 -0
- package/docs/examples/feature-as-tool-provider.md +143 -0
- package/docs/examples/file-manager.md +82 -0
- package/docs/examples/fs.md +83 -0
- package/docs/examples/git.md +85 -0
- package/docs/examples/google-auth.md +88 -0
- package/docs/examples/google-calendar.md +94 -0
- package/docs/examples/google-docs.md +82 -0
- package/docs/examples/google-drive.md +96 -0
- package/docs/examples/google-sheets.md +95 -0
- package/docs/examples/grep.md +85 -0
- package/docs/examples/ink-blocks.md +75 -0
- package/docs/examples/ink-renderer.md +41 -0
- package/docs/examples/ink.md +103 -0
- package/docs/examples/ipc-socket.md +103 -0
- package/docs/examples/json-tree.md +91 -0
- package/docs/examples/networking.md +58 -0
- package/docs/examples/nlp.md +91 -0
- package/docs/examples/opener.md +78 -0
- package/docs/examples/os.md +72 -0
- package/docs/examples/package-finder.md +89 -0
- package/docs/examples/postgres.md +91 -0
- package/docs/examples/proc.md +81 -0
- package/docs/examples/process-manager.md +79 -0
- package/docs/examples/python.md +132 -0
- package/docs/examples/repl.md +93 -0
- package/docs/examples/runpod.md +119 -0
- package/docs/examples/secure-shell.md +92 -0
- package/docs/examples/sqlite.md +86 -0
- package/docs/examples/structured-output-with-assistants.md +144 -0
- package/docs/examples/telegram.md +77 -0
- package/docs/examples/tts.md +86 -0
- package/docs/examples/ui.md +80 -0
- package/docs/examples/vault.md +70 -0
- package/docs/examples/vm.md +86 -0
- package/docs/examples/websocket-ask-and-reply-example.md +128 -0
- package/docs/examples/yaml-tree.md +93 -0
- package/docs/examples/yaml.md +104 -0
- package/docs/ideas/assistant-factory-pattern.md +142 -0
- package/docs/in-memory-fs.md +4 -0
- package/docs/introspection-audit.md +49 -0
- package/docs/introspection.md +164 -0
- package/docs/mcp/readme.md +162 -0
- package/docs/models.ts +41 -0
- package/docs/philosophy.md +86 -0
- package/docs/principles.md +7 -0
- package/docs/prompts/audit-codebase-for-failures-to-use-the-container.md +34 -0
- package/docs/prompts/check-for-undocumented-features.md +27 -0
- package/docs/prompts/mcp-test-easy-command.md +27 -0
- package/docs/scaffolds/client.md +149 -0
- package/docs/scaffolds/command.md +120 -0
- package/docs/scaffolds/endpoint.md +171 -0
- package/docs/scaffolds/feature.md +158 -0
- package/docs/scaffolds/selector.md +91 -0
- package/docs/scaffolds/server.md +196 -0
- package/docs/selectors.md +115 -0
- package/docs/sessions/custom-command/attempt-log-2.md +195 -0
- package/docs/sessions/file-watcher-pipeline/attempt-log-1.md +728 -0
- package/docs/sessions/file-watcher-pipeline/attempt-log-2.md +555 -0
- package/docs/sessions/grep-audit-report/attempt-log-1.md +289 -0
- package/docs/sessions/multi-feature-dashboard/attempt-log-2.md +679 -0
- package/docs/sessions/rest-api-server-with-client/attempt-log-1.md +1 -0
- package/docs/sessions/rest-api-server-with-client/attempt-log-3.md +920 -0
- package/docs/sessions/simple-rest-api/attempt-log-1.md +593 -0
- package/docs/sessions/websocket-serve-and-client/attempt-log-2.md +995 -0
- package/docs/tutorials/00-bootstrap.md +166 -0
- package/docs/tutorials/01-getting-started.md +106 -0
- package/docs/tutorials/02-container.md +210 -0
- package/docs/tutorials/03-scripts.md +194 -0
- package/docs/tutorials/04-features-overview.md +196 -0
- package/docs/tutorials/05-state-and-events.md +171 -0
- package/docs/tutorials/06-servers.md +157 -0
- package/docs/tutorials/07-endpoints.md +198 -0
- package/docs/tutorials/08-commands.md +252 -0
- package/docs/tutorials/09-clients.md +162 -0
- package/docs/tutorials/10-creating-features.md +203 -0
- package/docs/tutorials/11-contentbase.md +191 -0
- package/docs/tutorials/12-assistants.md +215 -0
- package/docs/tutorials/13-introspection.md +157 -0
- package/docs/tutorials/14-type-system.md +174 -0
- package/docs/tutorials/15-project-patterns.md +222 -0
- package/docs/tutorials/16-google-features.md +534 -0
- package/docs/tutorials/17-tui-blocks.md +530 -0
- package/docs/tutorials/18-semantic-search.md +334 -0
- package/docs/tutorials/19-python-sessions.md +401 -0
- package/docs/tutorials/20-browser-esm.md +234 -0
- package/index.html +1430 -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 +1430 -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 +152 -0
- package/src/agi/endpoints/ask.ts +60 -0
- package/src/agi/endpoints/conversations/[id].ts +45 -0
- package/src/agi/endpoints/conversations.ts +31 -0
- package/src/agi/endpoints/experts.ts +37 -0
- package/src/agi/feature.ts +13 -0
- package/src/agi/features/agent-memory.ts +694 -0
- package/src/agi/features/assistant.ts +1624 -0
- package/src/agi/features/assistants-manager.ts +418 -0
- package/src/agi/features/autonomous-assistant.ts +431 -0
- package/src/agi/features/browser-use.ts +653 -0
- package/src/agi/features/claude-code.ts +1538 -0
- package/src/agi/features/coding-tools.ts +175 -0
- package/src/agi/features/conversation-history.ts +495 -0
- package/src/agi/features/conversation.ts +1323 -0
- package/src/agi/features/docs-reader.ts +167 -0
- package/src/agi/features/file-tools.ts +293 -0
- package/src/agi/features/luca-coder.ts +639 -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 +478 -0
- package/src/agi/index.ts +6 -0
- package/src/agi/lib/interceptor-chain.ts +89 -0
- package/src/agi/lib/token-counter.ts +122 -0
- package/src/bootstrap/generated.ts +9792 -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 +505 -0
- package/src/commands/bootstrap.ts +244 -0
- package/src/commands/chat.ts +308 -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 +121 -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 +982 -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 +1084 -0
- package/src/container.ts +1186 -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 +40208 -0
- package/src/introspection/generated.node.ts +28686 -0
- package/src/introspection/generated.web.ts +2251 -0
- package/src/introspection/index.ts +296 -0
- package/src/introspection/scan.ts +1131 -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 +812 -0
- package/src/node/features/disk-cache.ts +388 -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 +735 -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 +906 -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 +267 -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 +161 -0
- package/src/node/features/tts.ts +185 -0
- package/src/node/features/ui.ts +786 -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 +227 -0
- package/src/react/index.ts +175 -0
- package/src/registry.ts +210 -0
- package/src/scaffolds/generated.ts +1815 -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 +269 -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/test/assistant-hooks.test.ts +306 -0
- package/test/assistant.test.ts +81 -0
- package/test/bus.test.ts +134 -0
- package/test/clients-servers.test.ts +217 -0
- package/test/command.test.ts +267 -0
- package/test/container-link.test.ts +274 -0
- package/test/conversation.test.ts +220 -0
- package/test/features.test.ts +160 -0
- package/test/fork-and-research.test.ts +450 -0
- package/test/integration.test.ts +787 -0
- package/test/interceptor-chain.test.ts +61 -0
- package/test/node-container.test.ts +121 -0
- package/test/python-session.test.ts +105 -0
- package/test/rate-limit.test.ts +272 -0
- package/test/semantic-search.test.ts +550 -0
- package/test/state.test.ts +121 -0
- package/test/vm-context.test.ts +146 -0
- package/test/vm-loadmodule.test.ts +213 -0
- package/test/websocket-ask.test.ts +101 -0
- package/test-integration/assistant.test.ts +138 -0
- package/test-integration/assistants-manager.test.ts +113 -0
- package/test-integration/claude-code.test.ts +98 -0
- package/test-integration/conversation-history.test.ts +205 -0
- package/test-integration/conversation.test.ts +137 -0
- package/test-integration/elevenlabs.test.ts +55 -0
- package/test-integration/google-services.test.ts +80 -0
- package/test-integration/helpers.ts +89 -0
- package/test-integration/memory.test.ts +204 -0
- package/test-integration/openai-codex.test.ts +93 -0
- package/test-integration/runpod.test.ts +58 -0
- package/test-integration/server-endpoints.test.ts +97 -0
- package/test-integration/telegram.test.ts +46 -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,258 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { ServerStateSchema, ServerOptionsSchema, ServerEventsSchema } from '../schemas/base.js'
|
|
3
|
+
import { type StartOptions, Server, type ServerState } from '../server.js';
|
|
4
|
+
import { WebSocketServer as BaseServer } from 'ws'
|
|
5
|
+
import type { PendingRequest } from '../clients/websocket.js'
|
|
6
|
+
|
|
7
|
+
declare module '../server' {
|
|
8
|
+
interface AvailableServers {
|
|
9
|
+
websocket: typeof WebsocketServer
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const SocketServerOptionsSchema = ServerOptionsSchema.extend({
|
|
14
|
+
json: z.boolean().optional().describe('When enabled, incoming messages are automatically JSON-parsed before emitting the message event, and outgoing send/broadcast calls JSON-stringify the payload'),
|
|
15
|
+
})
|
|
16
|
+
export type SocketServerOptions = z.infer<typeof SocketServerOptionsSchema>
|
|
17
|
+
|
|
18
|
+
export const SocketServerEventsSchema = ServerEventsSchema.extend({
|
|
19
|
+
connection: z.tuple([z.any().describe('The raw WebSocket client instance from the ws library')]).describe('Fires when a new client connects'),
|
|
20
|
+
message: z.tuple([z.any().describe('The message data (JSON-parsed object when json option is enabled, raw Buffer/string otherwise)'), z.any().describe('The WebSocket client that sent the message — use with server.send(ws, data) to reply')]).describe('Fires when a message is received from a client. Handler signature: (data, ws)'),
|
|
21
|
+
}).describe('WebSocket server events')
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* WebSocket server built on the `ws` library with optional JSON message framing.
|
|
25
|
+
*
|
|
26
|
+
* Manages WebSocket connections, tracks connected clients, and bridges
|
|
27
|
+
* messages to Luca's event bus. When `json` mode is enabled, incoming
|
|
28
|
+
* messages are automatically JSON-parsed (with `.toString()` for Buffer data)
|
|
29
|
+
* and outgoing messages via `send()` / `broadcast()` are JSON-stringified.
|
|
30
|
+
* When `json` mode is disabled, raw message data is emitted as-is and
|
|
31
|
+
* `send()` / `broadcast()` still JSON-stringify for safety.
|
|
32
|
+
*
|
|
33
|
+
* Supports ask/reply semantics when paired with the Luca WebSocket client.
|
|
34
|
+
* The server can `ask(ws, type, data)` a connected client and await a typed
|
|
35
|
+
* response, or handle incoming asks from clients by listening for messages
|
|
36
|
+
* with a `requestId` and replying via `send(ws, { replyTo, data })`.
|
|
37
|
+
* Requests time out if no reply arrives within the configurable window.
|
|
38
|
+
*
|
|
39
|
+
* @extends Server
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* const ws = container.server('websocket', { json: true })
|
|
44
|
+
* await ws.start({ port: 8080 })
|
|
45
|
+
*
|
|
46
|
+
* ws.on('message', (data, client) => {
|
|
47
|
+
* console.log('Received:', data)
|
|
48
|
+
* ws.broadcast({ echo: data })
|
|
49
|
+
* })
|
|
50
|
+
*
|
|
51
|
+
* // ask/reply: request info from a connected client
|
|
52
|
+
* ws.on('connection', async (client) => {
|
|
53
|
+
* const info = await ws.ask(client, 'identify')
|
|
54
|
+
* console.log('Client says:', info)
|
|
55
|
+
* })
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export class WebsocketServer<T extends ServerState = ServerState, K extends SocketServerOptions = SocketServerOptions> extends Server<T,K> {
|
|
59
|
+
static override shortcut = 'servers.websocket' as const
|
|
60
|
+
static override stateSchema = ServerStateSchema
|
|
61
|
+
static override optionsSchema = SocketServerOptionsSchema
|
|
62
|
+
static override eventsSchema = SocketServerEventsSchema
|
|
63
|
+
|
|
64
|
+
static { Server.register(this, 'websocket') }
|
|
65
|
+
|
|
66
|
+
_wss?: BaseServer
|
|
67
|
+
|
|
68
|
+
get wss(): BaseServer {
|
|
69
|
+
if (this._wss) {
|
|
70
|
+
return this._wss
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return this._wss = new BaseServer({
|
|
74
|
+
port: this.port
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
connections : Set<any> = new Set()
|
|
79
|
+
_pending = new Map<string, PendingRequest>()
|
|
80
|
+
|
|
81
|
+
async broadcast(message: any): Promise<this> {
|
|
82
|
+
for(const ws of this.connections) {
|
|
83
|
+
await ws.send(JSON.stringify(message))
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return this
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async send(ws: any, message: any): Promise<this> {
|
|
90
|
+
await ws.send(JSON.stringify(message))
|
|
91
|
+
return this
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Send a request to a specific client and wait for a correlated response.
|
|
96
|
+
* The client is expected to reply with a message whose `replyTo` matches
|
|
97
|
+
* the `requestId` of this message.
|
|
98
|
+
*
|
|
99
|
+
* @param ws - The WebSocket client to ask
|
|
100
|
+
* @param type - A string identifying the request type
|
|
101
|
+
* @param data - Optional payload
|
|
102
|
+
* @param timeout - How long to wait (default 10 000 ms)
|
|
103
|
+
* @returns The `data` field of the response
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```typescript
|
|
107
|
+
* ws.on('connection', async (client) => {
|
|
108
|
+
* const info = await ws.ask(client, 'identify')
|
|
109
|
+
* console.log('Client says:', info)
|
|
110
|
+
* })
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
async ask<R = any>(ws: any, type: string, data?: any, timeout = 10000): Promise<R> {
|
|
114
|
+
const requestId = this.container.utils.uuid()
|
|
115
|
+
|
|
116
|
+
return new Promise<R>((resolve, reject) => {
|
|
117
|
+
const timer = setTimeout(() => {
|
|
118
|
+
this._pending.delete(requestId)
|
|
119
|
+
reject(new Error(`ask("${type}") timed out after ${timeout}ms`))
|
|
120
|
+
}, timeout)
|
|
121
|
+
|
|
122
|
+
this._pending.set(requestId, { resolve, reject, timer })
|
|
123
|
+
this.send(ws, { type, data, requestId })
|
|
124
|
+
})
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** @internal Resolve a pending ask() if the incoming message has a replyTo field. Returns true if handled. */
|
|
128
|
+
_handleReply(message: any): boolean {
|
|
129
|
+
if (!message || !message.replyTo) return false
|
|
130
|
+
|
|
131
|
+
const pending = this._pending.get(message.replyTo)
|
|
132
|
+
if (!pending) return false
|
|
133
|
+
|
|
134
|
+
this._pending.delete(message.replyTo)
|
|
135
|
+
clearTimeout(pending.timer)
|
|
136
|
+
|
|
137
|
+
if (message.error) {
|
|
138
|
+
pending.reject(new Error(message.error))
|
|
139
|
+
} else {
|
|
140
|
+
pending.resolve(message.data)
|
|
141
|
+
}
|
|
142
|
+
return true
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** @internal Reject all pending ask() calls — used on stop. */
|
|
146
|
+
_rejectAllPending(reason: string) {
|
|
147
|
+
for (const [id, pending] of this._pending) {
|
|
148
|
+
clearTimeout(pending.timer)
|
|
149
|
+
pending.reject(new Error(reason))
|
|
150
|
+
}
|
|
151
|
+
this._pending.clear()
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Start the WebSocket server. A runtime `port` overrides the constructor
|
|
156
|
+
* option and is written to state before the underlying `ws.Server` is created,
|
|
157
|
+
* so the server binds to the correct port.
|
|
158
|
+
*
|
|
159
|
+
* @param options - Optional runtime overrides for port and host
|
|
160
|
+
*/
|
|
161
|
+
override async start(options?: StartOptions): Promise<this> {
|
|
162
|
+
if (this.isListening) {
|
|
163
|
+
return this
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
await this._drainPendingPlugins()
|
|
167
|
+
|
|
168
|
+
// Apply runtime port to state before configure/wss touches it
|
|
169
|
+
if (options?.port) {
|
|
170
|
+
this.state.set('port', options.port)
|
|
171
|
+
// Reset cached wss so it rebinds to the new port
|
|
172
|
+
this._wss = undefined
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if(!this.isConfigured || options?.port) {
|
|
176
|
+
await this.configure()
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const { wss } = this
|
|
180
|
+
|
|
181
|
+
wss.on('connection', (ws) => {
|
|
182
|
+
this.connections.add(ws)
|
|
183
|
+
this.emit('connection', ws)
|
|
184
|
+
|
|
185
|
+
ws.on('message', (raw) => {
|
|
186
|
+
let data: any = raw
|
|
187
|
+
if (this.options.json) {
|
|
188
|
+
try {
|
|
189
|
+
data = JSON.parse(typeof raw === 'string' ? raw : raw.toString())
|
|
190
|
+
} catch {}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Route reply messages to pending ask() calls
|
|
194
|
+
if (this._handleReply(data)) return
|
|
195
|
+
|
|
196
|
+
// If this message is a request (has requestId), provide a reply helper
|
|
197
|
+
if (data && data.requestId) {
|
|
198
|
+
const requestId = data.requestId
|
|
199
|
+
data.reply = (responseData: any) => this.send(ws, { replyTo: requestId, data: responseData })
|
|
200
|
+
data.replyError = (error: string) => this.send(ws, { replyTo: requestId, error })
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
this.emit('message', data, ws)
|
|
204
|
+
})
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
this.state.set('listening', true)
|
|
208
|
+
|
|
209
|
+
return this
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
override async stop(): Promise<this> {
|
|
213
|
+
if (this.isStopped) {
|
|
214
|
+
return this
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
this._rejectAllPending('WebSocket server stopped')
|
|
218
|
+
|
|
219
|
+
await Promise.race([
|
|
220
|
+
new Promise<void>((resolve) => {
|
|
221
|
+
if (!this._wss) {
|
|
222
|
+
resolve()
|
|
223
|
+
return
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
for (const ws of this.connections) {
|
|
227
|
+
try {
|
|
228
|
+
ws.terminate?.()
|
|
229
|
+
ws.close?.()
|
|
230
|
+
} catch {}
|
|
231
|
+
}
|
|
232
|
+
this.connections.clear()
|
|
233
|
+
|
|
234
|
+
try {
|
|
235
|
+
this._wss.close(() => {
|
|
236
|
+
this._wss = undefined
|
|
237
|
+
resolve()
|
|
238
|
+
})
|
|
239
|
+
} catch {
|
|
240
|
+
this._wss = undefined
|
|
241
|
+
resolve()
|
|
242
|
+
}
|
|
243
|
+
}),
|
|
244
|
+
new Promise<void>((resolve) => setTimeout(resolve, 500)),
|
|
245
|
+
])
|
|
246
|
+
|
|
247
|
+
this.state.set('listening', false)
|
|
248
|
+
this.state.set('stopped', true)
|
|
249
|
+
return this
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/** The port this server will bind to. Defaults to 8081 if not set via constructor options or start(). */
|
|
253
|
+
override get port(): number {
|
|
254
|
+
return this.state.get('port') || this.options.port || 8081
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export default WebsocketServer
|
package/src/state.ts
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
export type StateChangeType = 'add' | 'update' | 'delete';
|
|
2
|
+
export type StateChangeCallback<K extends keyof any, V> = (changeType: StateChangeType, key: K, value?: V) => void;
|
|
3
|
+
export type SetStateValue<T extends object> = Partial<T> | ((current: T, state: State<T>) => Partial<T>);
|
|
4
|
+
|
|
5
|
+
export class State<T extends object = any> {
|
|
6
|
+
private state: Partial<T>;
|
|
7
|
+
private observers: StateChangeCallback<keyof T, T[keyof T]>[];
|
|
8
|
+
private _version = 0
|
|
9
|
+
|
|
10
|
+
constructor(options?: { initialState: Partial<T>}) {
|
|
11
|
+
this.state = {
|
|
12
|
+
...(options?.initialState || {}) as Partial<T>
|
|
13
|
+
};
|
|
14
|
+
this.observers = [];
|
|
15
|
+
|
|
16
|
+
Object.defineProperty(this, 'state', { enumerable: false });
|
|
17
|
+
Object.defineProperty(this, '_version', { enumerable: false });
|
|
18
|
+
Object.defineProperty(this, 'observers', { enumerable: false });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get version() {
|
|
22
|
+
return this._version
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
observe(callback: StateChangeCallback<keyof T, T[keyof T]>): () => void {
|
|
26
|
+
this.observers.push(callback);
|
|
27
|
+
|
|
28
|
+
return () => {
|
|
29
|
+
const index = this.observers.indexOf(callback);
|
|
30
|
+
if (index !== -1) {
|
|
31
|
+
this.observers.splice(index, 1);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
keys() : string[] {
|
|
37
|
+
return Object.keys(this.state);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get<K extends keyof T>(key: K): T[K] | undefined {
|
|
41
|
+
return this.state[key];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
set<K extends keyof T>(key: K, value: T[K]): this {
|
|
45
|
+
if(value === this.state[key]) {
|
|
46
|
+
return this
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const changeType: StateChangeType = this.state.hasOwnProperty(key) ? 'update' : 'add';
|
|
50
|
+
this.state[key] = value;
|
|
51
|
+
this._version++
|
|
52
|
+
this.observers.forEach(callback => callback(changeType, key, value));
|
|
53
|
+
return this
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
delete<K extends keyof T>(key: K): this {
|
|
57
|
+
if (this.state.hasOwnProperty(key)) {
|
|
58
|
+
const value = this.state[key];
|
|
59
|
+
delete this.state[key];
|
|
60
|
+
this._version++
|
|
61
|
+
this.observers.forEach(callback => callback('delete', key, value));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return this
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
has<K extends keyof T>(key: K): boolean {
|
|
68
|
+
return this.state.hasOwnProperty(key);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
get current(): T {
|
|
72
|
+
return this.state as T;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
clear(): void {
|
|
76
|
+
const keys = Object.keys(this.state);
|
|
77
|
+
this.state = {};
|
|
78
|
+
this._version++
|
|
79
|
+
keys.forEach(key => {
|
|
80
|
+
this.observers.forEach(callback => callback('delete', key as keyof T));
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
entries() : [keyof T, T[keyof T]][] {
|
|
85
|
+
return Object.entries(this.state) as [keyof T, T[keyof T]][];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
values() : T[keyof T][] {
|
|
89
|
+
return Object.values(this.state);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
setState(value: SetStateValue<T>): void {
|
|
93
|
+
const newState = typeof value === 'function' ? value(this.current, this) : value;
|
|
94
|
+
for (const key in newState) {
|
|
95
|
+
if (Object.prototype.hasOwnProperty.call(newState, key)) {
|
|
96
|
+
// @ts-ignore-next-line
|
|
97
|
+
this.set(key as keyof T, newState[key as keyof T]);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import Websocket from 'isomorphic-ws'
|
|
2
|
+
import { Client } from '../../client'
|
|
3
|
+
import { WebSocketClient, type WebSocketClientState, type WebSocketClientOptions } from '../../clients/websocket'
|
|
4
|
+
import { WebSocketClientEventsSchema } from '../../schemas/base.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Web-specific WebSocket client implementation using isomorphic-ws.
|
|
8
|
+
* Extends the base WebSocketClient with platform-specific transport and
|
|
9
|
+
* an envelope format that wraps sent data with a unique ID. Inherits
|
|
10
|
+
* ask/reply semantics from the base WebSocketClient — protocol messages
|
|
11
|
+
* (those with `requestId` or `replyTo`) bypass the envelope wrapper to
|
|
12
|
+
* maintain compatibility with the Luca WebSocket server's ask/reply flow.
|
|
13
|
+
*/
|
|
14
|
+
export class SocketClient<T extends WebSocketClientState = WebSocketClientState, K extends WebSocketClientOptions = WebSocketClientOptions> extends WebSocketClient<T,K> {
|
|
15
|
+
// @ts-expect-error widening ws type for isomorphic-ws compatibility
|
|
16
|
+
declare ws: Websocket | WebSocket
|
|
17
|
+
|
|
18
|
+
static override shortcut = 'clients.websocket' as const
|
|
19
|
+
static override eventsSchema = WebSocketClientEventsSchema
|
|
20
|
+
|
|
21
|
+
static { Client.register(this, 'websocket') }
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Send data over the WebSocket with an ID envelope.
|
|
25
|
+
* Wraps the payload in { id, data } before JSON serialization.
|
|
26
|
+
* Messages with a `requestId` or `replyTo` are sent as-is to
|
|
27
|
+
* preserve the ask/reply protocol.
|
|
28
|
+
*/
|
|
29
|
+
override async send(data: any) {
|
|
30
|
+
if(!this.isConnected && !this.hasError) {
|
|
31
|
+
await this.connect()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if(typeof this.ws === 'undefined') {
|
|
35
|
+
throw new Error(`Missing websocket instance`)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Protocol messages (ask/reply) bypass the envelope
|
|
39
|
+
if (data && (data.requestId || data.replyTo)) {
|
|
40
|
+
this.ws.send(JSON.stringify(data))
|
|
41
|
+
} else {
|
|
42
|
+
this.ws.send(JSON.stringify({
|
|
43
|
+
id: this.container.utils.uuid(),
|
|
44
|
+
data
|
|
45
|
+
}))
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Establish a WebSocket connection using isomorphic-ws.
|
|
51
|
+
* Bridges raw WebSocket events to the Helper event bus and tracks connection state.
|
|
52
|
+
*/
|
|
53
|
+
override async connect() {
|
|
54
|
+
if(this.isConnected) {
|
|
55
|
+
return this
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const ws = this.ws = new Websocket(this.options.baseURL!)
|
|
59
|
+
const state = this.state as any
|
|
60
|
+
|
|
61
|
+
await new Promise<void>((resolve, reject) => {
|
|
62
|
+
ws.onopen = () => {
|
|
63
|
+
state.set('connected', true)
|
|
64
|
+
state.set('connectionError', undefined)
|
|
65
|
+
state.set('reconnectAttempts', 0)
|
|
66
|
+
this.emit('open')
|
|
67
|
+
resolve()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
ws.onerror = (event: any) => {
|
|
71
|
+
state.set('connectionError', event)
|
|
72
|
+
this.emit('error', event)
|
|
73
|
+
reject(event)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
ws.onmessage = (event: any) => {
|
|
77
|
+
let data = event?.data ?? event
|
|
78
|
+
try {
|
|
79
|
+
data = JSON.parse(typeof data === 'string' ? data : data.toString())
|
|
80
|
+
} catch {}
|
|
81
|
+
if (!this._handleReply(data)) {
|
|
82
|
+
this.emit('message', data)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
ws.onclose = (event: any) => {
|
|
87
|
+
state.set('connected', false)
|
|
88
|
+
this.emit('close', event?.code, event?.reason)
|
|
89
|
+
}
|
|
90
|
+
}).catch((error) => {
|
|
91
|
+
state.set('connectionError', error)
|
|
92
|
+
throw error
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
return this
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export default SocketClient
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
export * from '../container.js'
|
|
2
|
+
import { Container } from '../container.js'
|
|
3
|
+
import { Client } from '../client.js'
|
|
4
|
+
import { RestClient } from '../clients/rest.js'
|
|
5
|
+
import { SocketClient } from './clients/socket.js'
|
|
6
|
+
import type { AvailableFeatures } from '../feature.js'
|
|
7
|
+
import type { ContainerState, ContainerArgv } from '../container.js'
|
|
8
|
+
import type { ClientsInterface } from '../client.js'
|
|
9
|
+
import type { AssetLoader } from './features/asset-loader.js'
|
|
10
|
+
import type { VoiceRecognition } from './features/voice-recognition.js'
|
|
11
|
+
import type { Speech } from './features/speech.js'
|
|
12
|
+
import type { Network } from './features/network.js'
|
|
13
|
+
import type { WebVault } from './features/vault.js'
|
|
14
|
+
import type { VM } from './features/vm.js'
|
|
15
|
+
import type { Esbuild } from './features/esbuild.js'
|
|
16
|
+
import type { Helpers } from './features/helpers.js'
|
|
17
|
+
import type { ContainerLink } from './features/container-link.js'
|
|
18
|
+
|
|
19
|
+
import * as WebContainerExtensions from './extension.js'
|
|
20
|
+
|
|
21
|
+
export { Client, RestClient, SocketClient }
|
|
22
|
+
|
|
23
|
+
export interface WebFeatures extends AvailableFeatures {
|
|
24
|
+
assetLoader: typeof AssetLoader
|
|
25
|
+
voice: typeof VoiceRecognition
|
|
26
|
+
speech: typeof Speech
|
|
27
|
+
vault: typeof WebVault
|
|
28
|
+
vm: typeof VM;
|
|
29
|
+
esbuild: typeof Esbuild
|
|
30
|
+
helpers: typeof Helpers
|
|
31
|
+
containerLink: typeof ContainerLink
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface WebContainer extends ClientsInterface {
|
|
35
|
+
assetLoader?: AssetLoader
|
|
36
|
+
voice?: VoiceRecognition
|
|
37
|
+
speech?: Speech
|
|
38
|
+
network?: Network
|
|
39
|
+
vault?: WebVault
|
|
40
|
+
helpers?: Helpers
|
|
41
|
+
containerLink?: ContainerLink
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface WebContainerState extends ContainerState { }
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Browser-specific container that extends the base Container with web client support
|
|
48
|
+
* and browser-specific features like speech, voice recognition, and asset loading.
|
|
49
|
+
*/
|
|
50
|
+
export class WebContainer<Features extends WebFeatures = WebFeatures, K extends WebContainerState = WebContainerState> extends Container<Features, K> {
|
|
51
|
+
/** Returns the base Client class for creating custom clients. */
|
|
52
|
+
get Client() {
|
|
53
|
+
return Client
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Returns the SocketClient class for WebSocket connections. */
|
|
57
|
+
get SocketClient() {
|
|
58
|
+
return SocketClient
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Returns the RestClient class for HTTP REST API connections. */
|
|
62
|
+
get RestClient() {
|
|
63
|
+
return RestClient
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
useHelpers: any[] = [WebContainerExtensions]
|
|
67
|
+
|
|
68
|
+
constructor(options: any = {}) {
|
|
69
|
+
super(options)
|
|
70
|
+
this.use(WebContainerExtensions as any)
|
|
71
|
+
this.feature("helpers" as any, { enable: true })
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export const helperCache = new Map()
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Container } from '../container'
|
|
2
|
+
|
|
3
|
+
import { Client, type ClientsInterface } from '../client.js'
|
|
4
|
+
import { AssetLoader } from './features/asset-loader.js'
|
|
5
|
+
import { Helpers } from './features/helpers.js'
|
|
6
|
+
import { VoiceRecognition } from './features/voice-recognition.js'
|
|
7
|
+
import { Speech } from './features/speech.js'
|
|
8
|
+
import { SocketClient } from './clients/socket.js'
|
|
9
|
+
import { Network } from './features/network.js'
|
|
10
|
+
import { WebVault } from './features/vault.js'
|
|
11
|
+
import { VM } from './features/vm.js'
|
|
12
|
+
import { Esbuild } from './features/esbuild.js'
|
|
13
|
+
import { ContainerLink } from './features/container-link.js'
|
|
14
|
+
|
|
15
|
+
export function attach<K extends Container & ClientsInterface>(container: K, options?: any) : Container & ClientsInterface {
|
|
16
|
+
container
|
|
17
|
+
.use(Client)
|
|
18
|
+
.use(AssetLoader)
|
|
19
|
+
.use(Helpers)
|
|
20
|
+
.use(VoiceRecognition)
|
|
21
|
+
.use(Speech)
|
|
22
|
+
.use(SocketClient)
|
|
23
|
+
.use(Network)
|
|
24
|
+
.use(VM)
|
|
25
|
+
.use(WebVault)
|
|
26
|
+
.use(Esbuild)
|
|
27
|
+
.use(ContainerLink)
|
|
28
|
+
|
|
29
|
+
return container
|
|
30
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { WebContainer } from './container.js'
|
|
2
|
+
import { type FeatureOptions, type FeatureState, type AvailableFeatures, features, Feature as UniversalFeature } from '../feature.js'
|
|
3
|
+
|
|
4
|
+
export { features }
|
|
5
|
+
|
|
6
|
+
export type { AvailableFeatures, FeatureState, FeatureOptions }
|
|
7
|
+
|
|
8
|
+
export class Feature<T extends FeatureState = FeatureState, K extends FeatureOptions = FeatureOptions> extends UniversalFeature<T, K> {
|
|
9
|
+
override get container() : WebContainer {
|
|
10
|
+
return super.container as WebContainer
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { FeatureStateSchema, FeatureOptionsSchema } from '../../schemas/base.js'
|
|
2
|
+
import { Feature } from "../feature.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Injects scripts and stylesheets into the page at runtime.
|
|
6
|
+
*
|
|
7
|
+
* Provides helpers for loading external libraries from unpkg.com,
|
|
8
|
+
* injecting arbitrary script/link tags, and managing load state.
|
|
9
|
+
* Used by other web features (e.g. Esbuild) to pull in dependencies on demand.
|
|
10
|
+
*
|
|
11
|
+
* @extends Feature
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const loader = container.feature('assetLoader')
|
|
16
|
+
* await loader.loadScript('https://unpkg.com/lodash')
|
|
17
|
+
* await AssetLoader.loadStylesheet('https://unpkg.com/normalize.css')
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export class AssetLoader extends Feature {
|
|
21
|
+
static override stateSchema = FeatureStateSchema
|
|
22
|
+
static override optionsSchema = FeatureOptionsSchema
|
|
23
|
+
static override shortcut = "features.assetLoader" as const
|
|
24
|
+
|
|
25
|
+
static { Feature.register(this, 'assetLoader') }
|
|
26
|
+
|
|
27
|
+
static loadStylesheet(href: string) {
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
const link = document.createElement("link");
|
|
30
|
+
link.rel = "stylesheet";
|
|
31
|
+
link.href = href;
|
|
32
|
+
link.onload = () => resolve(link);
|
|
33
|
+
link.onerror = () => reject(new Error(`Failed to load stylesheet: ${href}`));
|
|
34
|
+
|
|
35
|
+
document.head.appendChild(link);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
removeStylesheet(href:string) {
|
|
40
|
+
const links = document.querySelectorAll(`link[href="${href}"]`);
|
|
41
|
+
|
|
42
|
+
links.forEach((link) => {
|
|
43
|
+
document.head.removeChild(link);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async loadScript(url: string): Promise<void> {
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
const script = document.createElement("script");
|
|
50
|
+
script.src = url;
|
|
51
|
+
script.async = true;
|
|
52
|
+
|
|
53
|
+
script.onload = () => {
|
|
54
|
+
resolve();
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
script.onerror = () => {
|
|
58
|
+
reject(new Error(`Failed to load script: ${url}`));
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
document.head.appendChild(script);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async unpkg(packageName: string, globalName: string): Promise<any> {
|
|
66
|
+
const url = `https://unpkg.com/${packageName}`;
|
|
67
|
+
await this.loadScript(url);
|
|
68
|
+
return (window as any)[globalName];
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export default AssetLoader;
|