luca 1.1.2 → 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 -8
- 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 -0
- 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 -66
- 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/index.d.ts +0 -2
- package/dist/cli/index.js +0 -5
- package/dist/cli/run.d.ts +0 -12
- package/dist/cli/run.js +0 -42
- package/dist/config/consts.d.ts +0 -2
- package/dist/config/consts.js +0 -29
- package/dist/config/default.d.ts +0 -8
- package/dist/config/default.js +0 -15
- package/dist/config/initConfig.d.ts +0 -1
- package/dist/config/initConfig.js +0 -52
- package/dist/config/openConfig.d.ts +0 -2
- package/dist/config/openConfig.js +0 -24
- package/dist/config/runConfig.d.ts +0 -3
- package/dist/config/runConfig.js +0 -117
- package/dist/config/types.d.ts +0 -13
- package/dist/config/types.js +0 -2
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -5
- package/dist/utils/common.d.ts +0 -2
- package/dist/utils/common.js +0 -52
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/index.js +0 -17
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { FeatureStateSchema, FeatureOptionsSchema, FeatureEventsSchema } from '../../schemas/base.js'
|
|
3
|
+
import { Feature } from '../feature.js'
|
|
4
|
+
import { Client } from '../../client.js'
|
|
5
|
+
import type { Registry } from '../../registry.js'
|
|
6
|
+
import type { AssetLoader } from './asset-loader.js'
|
|
7
|
+
|
|
8
|
+
export const HelpersStateSchema = FeatureStateSchema.extend({
|
|
9
|
+
discovered: z.record(z.string(), z.boolean()).default({}).describe('Which registry types have been discovered'),
|
|
10
|
+
registered: z.array(z.string()).default([]).describe('Names of project-level helpers that were discovered (type.name)'),
|
|
11
|
+
manifestLoaded: z.boolean().default(false).describe('Whether the manifest has been fetched'),
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
export type HelpersState = z.infer<typeof HelpersStateSchema>
|
|
15
|
+
|
|
16
|
+
export const HelpersOptionsSchema = FeatureOptionsSchema.extend({
|
|
17
|
+
manifestURL: z.string().optional().describe('URL to fetch the helpers manifest from. Defaults to /.well-known/luca.manifest.json'),
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
export type HelpersOptions = z.infer<typeof HelpersOptionsSchema>
|
|
21
|
+
|
|
22
|
+
export const HelpersEventsSchema = FeatureEventsSchema.extend({
|
|
23
|
+
discovered: z.tuple([
|
|
24
|
+
z.string().describe('Registry type that was discovered'),
|
|
25
|
+
z.array(z.string()).describe('Names of newly registered helpers'),
|
|
26
|
+
]).describe('Emitted after a registry type has been discovered'),
|
|
27
|
+
registered: z.tuple([
|
|
28
|
+
z.string().describe('Registry type'),
|
|
29
|
+
z.string().describe('Helper name'),
|
|
30
|
+
]).describe('Emitted when a single helper is registered'),
|
|
31
|
+
manifestLoaded: z.tuple([
|
|
32
|
+
z.any().describe('The parsed manifest object'),
|
|
33
|
+
]).describe('Emitted when the manifest is successfully fetched'),
|
|
34
|
+
manifestError: z.tuple([
|
|
35
|
+
z.any().describe('The error that occurred'),
|
|
36
|
+
]).describe('Emitted when the manifest fetch fails'),
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
type RegistryType = 'features' | 'clients'
|
|
40
|
+
|
|
41
|
+
interface ManifestEntry {
|
|
42
|
+
id: string
|
|
43
|
+
description?: string
|
|
44
|
+
url: string
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface Manifest {
|
|
48
|
+
features?: Record<string, ManifestEntry>
|
|
49
|
+
clients?: Record<string, ManifestEntry>
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The Helpers feature discovers and loads project-level helpers from a JSON manifest
|
|
54
|
+
* served over HTTP. Scripts are injected via AssetLoader and self-register into
|
|
55
|
+
* the container's registries.
|
|
56
|
+
*
|
|
57
|
+
* This is the web equivalent of the node Helpers feature, which scans the filesystem.
|
|
58
|
+
* Instead of filesystem scanning, this feature fetches a manifest from a well-known URL
|
|
59
|
+
* and uses AssetLoader.loadScript() to inject each helper's script tag.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```typescript
|
|
63
|
+
* const helpers = container.feature('helpers', { enable: true })
|
|
64
|
+
*
|
|
65
|
+
* // Discover all helper types from the manifest
|
|
66
|
+
* await helpers.discoverAll()
|
|
67
|
+
*
|
|
68
|
+
* // Discover a specific type
|
|
69
|
+
* await helpers.discover('features')
|
|
70
|
+
*
|
|
71
|
+
* // Unified view of all available helpers
|
|
72
|
+
* console.log(helpers.available)
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export class Helpers extends Feature<HelpersState, HelpersOptions> {
|
|
76
|
+
static override shortcut = 'features.helpers' as const
|
|
77
|
+
static override description = 'Unified gateway for discovering and registering project-level helpers via HTTP manifest'
|
|
78
|
+
static override stateSchema = HelpersStateSchema
|
|
79
|
+
static override optionsSchema = HelpersOptionsSchema
|
|
80
|
+
static override eventsSchema = HelpersEventsSchema
|
|
81
|
+
|
|
82
|
+
static { Feature.register(this as any, 'helpers') }
|
|
83
|
+
|
|
84
|
+
private _manifest: Manifest | null = null
|
|
85
|
+
|
|
86
|
+
private get registryMap(): Record<RegistryType, { registry: Registry<any> }> {
|
|
87
|
+
return {
|
|
88
|
+
features: { registry: this.container.features as any },
|
|
89
|
+
clients: { registry: (this.container as any).clients as Registry<any> },
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** The URL to fetch the helpers manifest from. */
|
|
94
|
+
get manifestURL(): string {
|
|
95
|
+
return this.options.manifestURL || '/.well-known/luca.manifest.json'
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Set a new manifest URL. Invalidates any cached manifest.
|
|
100
|
+
*
|
|
101
|
+
* @param url - The new URL to fetch the manifest from
|
|
102
|
+
*/
|
|
103
|
+
setManifestURL(url: string) {
|
|
104
|
+
this.options.manifestURL = url
|
|
105
|
+
this._manifest = null
|
|
106
|
+
this.state.set('manifestLoaded', false)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Returns a unified view of all available helpers across all registries.
|
|
111
|
+
* Each key is a registry type, each value is the list of helper names in that registry.
|
|
112
|
+
*/
|
|
113
|
+
get available(): Record<string, string[]> {
|
|
114
|
+
const result: Record<string, string[]> = {}
|
|
115
|
+
for (const [type, { registry }] of Object.entries(this.registryMap)) {
|
|
116
|
+
result[type] = registry.available
|
|
117
|
+
}
|
|
118
|
+
return result
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Fetch and cache the manifest JSON. Returns cached version on subsequent calls
|
|
123
|
+
* unless invalidated by setManifestURL().
|
|
124
|
+
*/
|
|
125
|
+
private async fetchManifest(): Promise<Manifest> {
|
|
126
|
+
if (this._manifest) {
|
|
127
|
+
return this._manifest
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
const response = await fetch(this.manifestURL)
|
|
132
|
+
|
|
133
|
+
if (!response.ok) {
|
|
134
|
+
const err = new Error(`Manifest fetch failed: ${response.status} ${response.statusText}`)
|
|
135
|
+
this.emit('manifestError' as any, err)
|
|
136
|
+
return {}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const manifest = await response.json() as Manifest
|
|
140
|
+
this._manifest = manifest
|
|
141
|
+
this.state.set('manifestLoaded', true)
|
|
142
|
+
this.emit('manifestLoaded' as any, manifest)
|
|
143
|
+
return manifest
|
|
144
|
+
} catch (err: any) {
|
|
145
|
+
this.emit('manifestError' as any, err)
|
|
146
|
+
return {}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Get the AssetLoader instance from the container.
|
|
152
|
+
*/
|
|
153
|
+
private get assetLoader(): AssetLoader {
|
|
154
|
+
return this.container.feature('assetLoader') as unknown as AssetLoader
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Discover and register helpers of the given type from the manifest.
|
|
159
|
+
*
|
|
160
|
+
* Fetches the manifest, then for each entry of the requested type,
|
|
161
|
+
* loads the script via AssetLoader and checks what got newly registered.
|
|
162
|
+
*
|
|
163
|
+
* @param type - Which type of helpers to discover ('features' or 'clients')
|
|
164
|
+
* @returns Names of helpers that were discovered and registered
|
|
165
|
+
*/
|
|
166
|
+
async discover(type: RegistryType): Promise<string[]> {
|
|
167
|
+
const discovered = this.state.get('discovered') || {}
|
|
168
|
+
|
|
169
|
+
if (discovered[type]) {
|
|
170
|
+
return []
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const manifest = await this.fetchManifest()
|
|
174
|
+
const entries = manifest[type] || {}
|
|
175
|
+
const { registry } = this.registryMap[type]
|
|
176
|
+
const newNames: string[] = []
|
|
177
|
+
|
|
178
|
+
for (const [name, entry] of Object.entries(entries)) {
|
|
179
|
+
const beforeNames = new Set(registry.available)
|
|
180
|
+
|
|
181
|
+
try {
|
|
182
|
+
await this.assetLoader.loadScript(entry.url)
|
|
183
|
+
} catch (err: any) {
|
|
184
|
+
console.warn(`Helpers: failed to load ${type}/${name} from ${entry.url}: ${err.message}`)
|
|
185
|
+
continue
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const afterNames = registry.available
|
|
189
|
+
const added = afterNames.filter((n: string) => !beforeNames.has(n))
|
|
190
|
+
|
|
191
|
+
if (added.length > 0) {
|
|
192
|
+
for (const addedName of added) {
|
|
193
|
+
newNames.push(addedName)
|
|
194
|
+
this.emit('registered' as any, type, addedName)
|
|
195
|
+
}
|
|
196
|
+
} else if (registry.has(name)) {
|
|
197
|
+
// Script may have already been registered under the expected name
|
|
198
|
+
if (!beforeNames.has(name)) {
|
|
199
|
+
newNames.push(name)
|
|
200
|
+
this.emit('registered' as any, type, name)
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
this.state.set('discovered', { ...this.state.get('discovered'), [type]: true })
|
|
206
|
+
|
|
207
|
+
const existing = this.state.get('registered') || []
|
|
208
|
+
this.state.set('registered', [...existing, ...newNames.map(n => `${type}.${n}`)])
|
|
209
|
+
|
|
210
|
+
this.emit('discovered' as any, type, newNames)
|
|
211
|
+
|
|
212
|
+
return newNames
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Discover all helper types from the manifest.
|
|
217
|
+
*
|
|
218
|
+
* @returns Map of registry type to discovered helper names
|
|
219
|
+
*/
|
|
220
|
+
async discoverAll(): Promise<Record<string, string[]>> {
|
|
221
|
+
const results: Record<string, string[]> = {}
|
|
222
|
+
|
|
223
|
+
for (const type of ['features', 'clients'] as RegistryType[]) {
|
|
224
|
+
results[type] = await this.discover(type)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return results
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Convenience method to discover only features.
|
|
232
|
+
*/
|
|
233
|
+
async discoverFeatures(): Promise<string[]> {
|
|
234
|
+
return this.discover('features')
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Convenience method to discover only clients.
|
|
239
|
+
*/
|
|
240
|
+
async discoverClients(): Promise<string[]> {
|
|
241
|
+
return this.discover('clients')
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Look up a helper class by type and name.
|
|
246
|
+
*
|
|
247
|
+
* @param type - The registry type
|
|
248
|
+
* @param name - The helper name within that registry
|
|
249
|
+
* @returns The helper constructor
|
|
250
|
+
*/
|
|
251
|
+
lookup(type: RegistryType, name: string): any {
|
|
252
|
+
const { registry } = this.registryMap[type]
|
|
253
|
+
return registry.lookup(name)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Get the introspection description for a specific helper.
|
|
258
|
+
*
|
|
259
|
+
* @param type - The registry type
|
|
260
|
+
* @param name - The helper name
|
|
261
|
+
* @returns Markdown description of the helper's interface
|
|
262
|
+
*/
|
|
263
|
+
describe(type: RegistryType, name: string): string {
|
|
264
|
+
const { registry } = this.registryMap[type]
|
|
265
|
+
return registry.describe(name)
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export default Helpers
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
import { z } from 'zod'
|
|
3
|
+
import { FeatureStateSchema, FeatureOptionsSchema, FeatureEventsSchema } from '../../schemas/base.js'
|
|
4
|
+
import { Feature } from "../feature.js";
|
|
5
|
+
import type { ContainerContext } from "../container.js";
|
|
6
|
+
|
|
7
|
+
export const NetworkStateSchema = FeatureStateSchema.extend({
|
|
8
|
+
offline: z.boolean().describe('Whether the browser is currently offline'),
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
export const NetworkOptionsSchema = FeatureOptionsSchema.extend({})
|
|
12
|
+
|
|
13
|
+
export const NetworkEventsSchema = FeatureEventsSchema.extend({
|
|
14
|
+
online: z.tuple([]).describe('Fires when the browser regains network connectivity'),
|
|
15
|
+
offline: z.tuple([]).describe('Fires when the browser loses network connectivity'),
|
|
16
|
+
}).describe('Network events')
|
|
17
|
+
|
|
18
|
+
export type NetworkState = z.infer<typeof NetworkStateSchema>
|
|
19
|
+
export type NetworkOptions = z.infer<typeof NetworkOptionsSchema>
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Tracks browser online/offline connectivity state.
|
|
23
|
+
*
|
|
24
|
+
* Listens for the browser's `online` and `offline` events and keeps the
|
|
25
|
+
* feature state in sync. Other features can observe the `offline` state
|
|
26
|
+
* value or listen for change events to react to connectivity changes.
|
|
27
|
+
*
|
|
28
|
+
* @extends Feature
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* const network = container.feature('network')
|
|
33
|
+
* console.log(network.state.get('offline')) // false when online
|
|
34
|
+
*
|
|
35
|
+
* network.on('stateChanged', ({ offline }) => {
|
|
36
|
+
* console.log(offline ? 'Went offline' : 'Back online')
|
|
37
|
+
* })
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export class Network<
|
|
41
|
+
T extends NetworkState = NetworkState,
|
|
42
|
+
K extends NetworkOptions = NetworkOptions
|
|
43
|
+
> extends Feature<T, K> {
|
|
44
|
+
static override stateSchema = NetworkStateSchema
|
|
45
|
+
static override optionsSchema = NetworkOptionsSchema
|
|
46
|
+
static override eventsSchema = NetworkEventsSchema
|
|
47
|
+
static override shortcut = "features.network" as const
|
|
48
|
+
|
|
49
|
+
static { Feature.register(this as any, 'network') }
|
|
50
|
+
|
|
51
|
+
constructor(options: K, context: ContainerContext) {
|
|
52
|
+
super(options, context);
|
|
53
|
+
this.state.set("offline", !navigator.onLine);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Whether the browser is currently offline. */
|
|
57
|
+
get isOffline() {
|
|
58
|
+
return this.state.get("offline") === true;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Whether the browser is currently online. */
|
|
62
|
+
get isOnline() {
|
|
63
|
+
return this.state.get("offline") === false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private handleConnectionChange = () => {
|
|
67
|
+
const isOffline = !navigator.onLine;
|
|
68
|
+
this.state.set('offline', isOffline)
|
|
69
|
+
this.emit(isOffline ? "offline" : "online");
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
start() {
|
|
73
|
+
window.addEventListener("online", this.handleConnectionChange);
|
|
74
|
+
window.addEventListener("offline", this.handleConnectionChange);
|
|
75
|
+
return this
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
disable() {
|
|
79
|
+
window.removeEventListener("online", this.handleConnectionChange);
|
|
80
|
+
window.removeEventListener("offline", this.handleConnectionChange);
|
|
81
|
+
return this
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export default Network
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { FeatureStateSchema, FeatureOptionsSchema } from '../../schemas/base.js'
|
|
3
|
+
import { Feature } from "../feature.js";
|
|
4
|
+
import { type ContainerContext } from "../container.js";
|
|
5
|
+
|
|
6
|
+
export const SpeechOptionsSchema = FeatureOptionsSchema.extend({
|
|
7
|
+
voice: z.string().optional().describe('The voice to use for the speech'),
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
export const SpeechStateSchema = FeatureStateSchema.extend({
|
|
11
|
+
defaultVoice: z.string().describe('Name of the currently selected default voice'),
|
|
12
|
+
voices: z.array(z.any().describe('Voice object')).optional().describe('Available speech synthesis voices'),
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
export type SpeechOptions = z.infer<typeof SpeechOptionsSchema>
|
|
16
|
+
export type SpeechState = z.infer<typeof SpeechStateSchema>
|
|
17
|
+
|
|
18
|
+
type Voice = {
|
|
19
|
+
voiceURI: string;
|
|
20
|
+
name: string;
|
|
21
|
+
lang: string;
|
|
22
|
+
localService: boolean;
|
|
23
|
+
default: boolean;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Text-to-speech synthesis using the Web Speech API (SpeechSynthesis).
|
|
28
|
+
*
|
|
29
|
+
* Wraps the browser's built-in speech synthesis, providing voice selection,
|
|
30
|
+
* queue management, and state tracking. Voices are discovered on init and
|
|
31
|
+
* exposed via state for UI binding.
|
|
32
|
+
*
|
|
33
|
+
* @extends Feature
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* const speech = container.feature('speech')
|
|
38
|
+
* speech.say('Hello from the browser!')
|
|
39
|
+
*
|
|
40
|
+
* // Choose a specific voice
|
|
41
|
+
* const speech = container.feature('speech', { voice: 'Google UK English Female' })
|
|
42
|
+
* speech.say('Cheerio!')
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export class Speech<
|
|
46
|
+
T extends SpeechState = SpeechState,
|
|
47
|
+
K extends SpeechOptions = SpeechOptions
|
|
48
|
+
> extends Feature<T, K> {
|
|
49
|
+
|
|
50
|
+
static override stateSchema = SpeechStateSchema
|
|
51
|
+
static override optionsSchema = SpeechOptionsSchema
|
|
52
|
+
static override shortcut = "features.speech" as const
|
|
53
|
+
|
|
54
|
+
static { Feature.register(this as any, 'speech') }
|
|
55
|
+
|
|
56
|
+
constructor(options: K, context: ContainerContext) {
|
|
57
|
+
super(options,context)
|
|
58
|
+
|
|
59
|
+
if(options.voice) {
|
|
60
|
+
this.state.set("defaultVoice", options.voice)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
this.loadVoices()
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Returns the array of available speech synthesis voices. */
|
|
67
|
+
get voices() {
|
|
68
|
+
return this.state.get('voices') || []
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Returns the Voice object matching the currently selected default voice name. */
|
|
72
|
+
get defaultVoice() {
|
|
73
|
+
return this.voices.find(v => v.name === this.state.get("defaultVoice"))
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
loadVoices() {
|
|
77
|
+
const voices = speechSynthesis.getVoices();
|
|
78
|
+
this.state.set("voices", voices);
|
|
79
|
+
|
|
80
|
+
if (!this.state.get("defaultVoice") && voices.length > 0) {
|
|
81
|
+
const defaultVoice = voices.find(v => v.default)!
|
|
82
|
+
this.state.set("defaultVoice", defaultVoice.name);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
setDefaultVoice(name: string) {
|
|
87
|
+
const voice = this.voices.find(v => v.name === name)!
|
|
88
|
+
this.state.set("defaultVoice", voice.name);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
cancel() {
|
|
92
|
+
speechSynthesis.cancel()
|
|
93
|
+
return this
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
say(text: string, options: { voice?: Voice } = {}) {
|
|
97
|
+
const utterance = new SpeechSynthesisUtterance(text);
|
|
98
|
+
const voice = options.voice || this.defaultVoice
|
|
99
|
+
utterance.voice = voice || this.voices[0]!
|
|
100
|
+
speechSynthesis.speak(utterance);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export default Speech;
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { z } from 'zod'
|
|
3
|
+
import { FeatureStateSchema, FeatureOptionsSchema } from '../../schemas/base.js'
|
|
4
|
+
import { Feature } from '../feature.js'
|
|
5
|
+
|
|
6
|
+
export const WebVaultStateSchema = FeatureStateSchema.extend({
|
|
7
|
+
secret: z.string().optional().describe('Base64-encoded AES-GCM encryption secret key'),
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
export const WebVaultOptionsSchema = FeatureOptionsSchema.extend({
|
|
11
|
+
secret: z.string().optional().describe('Pre-existing base64-encoded secret key to use'),
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
export type WebVaultState = z.infer<typeof WebVaultStateSchema>
|
|
15
|
+
export type WebVaultOptions = z.infer<typeof WebVaultOptionsSchema>
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* AES-256-GCM encryption and decryption for the browser using the Web Crypto API.
|
|
19
|
+
*
|
|
20
|
+
* Generates or accepts a secret key and provides `encrypt()` / `decrypt()` methods
|
|
21
|
+
* that work entirely client-side. Keys are stored as base64-encoded state so they
|
|
22
|
+
* can persist across sessions when needed.
|
|
23
|
+
*
|
|
24
|
+
* @extends Feature
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const vault = container.feature('vault')
|
|
29
|
+
* const encrypted = await vault.encrypt('secret data')
|
|
30
|
+
* const decrypted = await vault.decrypt(encrypted)
|
|
31
|
+
* console.log(decrypted) // 'secret data'
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export class WebVault extends Feature<WebVaultState, WebVaultOptions> {
|
|
35
|
+
static override stateSchema = WebVaultStateSchema
|
|
36
|
+
static override optionsSchema = WebVaultOptionsSchema
|
|
37
|
+
static override shortcut = "features.vault" as const
|
|
38
|
+
|
|
39
|
+
static { Feature.register(this, 'vault') }
|
|
40
|
+
|
|
41
|
+
async secret({ refresh = false, set = true } = {}) : Promise<ArrayBuffer> {
|
|
42
|
+
if (!this.state.get('secret') && this.options.secret) {
|
|
43
|
+
this.state.set('secret', this.options.secret)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!refresh && this.state.get('secret')) {
|
|
47
|
+
return base64ToArrayBuffer(this.state.get('secret')!)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const val = await generateSecretKey()
|
|
51
|
+
const asString = arrayBufferToBase64(val)
|
|
52
|
+
|
|
53
|
+
if(set && !this.state.get('secret')) {
|
|
54
|
+
this.state.set('secret', asString)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return val
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async decrypt(payload: string) {
|
|
61
|
+
const parts = payload.split("\n------\n")
|
|
62
|
+
const iv = base64ToUint8Array(parts[1]!)
|
|
63
|
+
const ciphertext = base64ToArrayBuffer(parts[0]!)
|
|
64
|
+
const secret = await this.secret()
|
|
65
|
+
|
|
66
|
+
console.log(ciphertext, secret, iv)
|
|
67
|
+
return await decrypt(ciphertext, secret, iv)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async encrypt(payload: string) {
|
|
71
|
+
const secret = await this.secret()
|
|
72
|
+
console.log("encrypting", payload, secret)
|
|
73
|
+
const { iv, ciphertext, } = await encrypt(payload, secret)
|
|
74
|
+
|
|
75
|
+
return [
|
|
76
|
+
arrayBufferToBase64(ciphertext),
|
|
77
|
+
uint8ArrayToBase64(iv)
|
|
78
|
+
].join("\n------\n")
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
utils = {
|
|
82
|
+
arrayToString: arrayBufferToBase64,
|
|
83
|
+
stringToArray: base64ToArrayBuffer,
|
|
84
|
+
uintToString: uint8ArrayToBase64,
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export default WebVault
|
|
89
|
+
|
|
90
|
+
async function generateSecretKey(): Promise<ArrayBuffer> {
|
|
91
|
+
const key = await crypto.subtle.generateKey(
|
|
92
|
+
{ name: "AES-GCM", length: 256 },
|
|
93
|
+
true,
|
|
94
|
+
["encrypt", "decrypt"]
|
|
95
|
+
);
|
|
96
|
+
const secretKey = await crypto.subtle.exportKey("raw", key);
|
|
97
|
+
return secretKey;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async function encrypt(plaintext: string, secretKey: ArrayBuffer): Promise<{ iv: Uint8Array; ciphertext: ArrayBuffer }> {
|
|
101
|
+
const encoder = new TextEncoder();
|
|
102
|
+
const encodedText = encoder.encode(plaintext);
|
|
103
|
+
const key = await crypto.subtle.importKey(
|
|
104
|
+
"raw",
|
|
105
|
+
secretKey,
|
|
106
|
+
{ name: "AES-GCM" },
|
|
107
|
+
false,
|
|
108
|
+
["encrypt", "decrypt"]
|
|
109
|
+
);
|
|
110
|
+
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
111
|
+
const ciphertext = await crypto.subtle.encrypt(
|
|
112
|
+
{ name: "AES-GCM", iv },
|
|
113
|
+
key,
|
|
114
|
+
encodedText
|
|
115
|
+
);
|
|
116
|
+
return { iv, ciphertext };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async function decrypt(ciphertext: ArrayBuffer, secretKey: ArrayBuffer, iv: Uint8Array): Promise<string> {
|
|
120
|
+
const key = await crypto.subtle.importKey(
|
|
121
|
+
"raw",
|
|
122
|
+
secretKey,
|
|
123
|
+
{ name: "AES-GCM" },
|
|
124
|
+
false,
|
|
125
|
+
["encrypt", "decrypt"]
|
|
126
|
+
);
|
|
127
|
+
const plaintextArrayBuffer = await crypto.subtle.decrypt(
|
|
128
|
+
{ name: "AES-GCM", iv },
|
|
129
|
+
key,
|
|
130
|
+
ciphertext
|
|
131
|
+
);
|
|
132
|
+
const decoder = new TextDecoder();
|
|
133
|
+
const plaintext = decoder.decode(plaintextArrayBuffer);
|
|
134
|
+
return plaintext;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function arrayBufferToBase64(buffer: ArrayBuffer): string {
|
|
138
|
+
const bytes = new Uint8Array(buffer);
|
|
139
|
+
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
140
|
+
let base64 = "";
|
|
141
|
+
|
|
142
|
+
for (let i = 0; i < bytes.byteLength; i += 3) {
|
|
143
|
+
const a = bytes[i];
|
|
144
|
+
const b = bytes[i + 1];
|
|
145
|
+
const c = bytes[i + 2];
|
|
146
|
+
|
|
147
|
+
const index1 = a >> 2;
|
|
148
|
+
const index2 = ((a & 0x03) << 4) | (b >> 4);
|
|
149
|
+
const index3 = isNaN(b!) ? 64 : ((b & 0x0f) << 2) | (c >> 6);
|
|
150
|
+
const index4 = isNaN(b!) || isNaN(c!) ? 64 : c & 0x3f;
|
|
151
|
+
|
|
152
|
+
base64 += chars[index1] + chars[index2] + chars[index3] + chars[index4];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return base64.replace('undefined', '==');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function uint8ArrayToBase64(u: Uint8Array): string {
|
|
159
|
+
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
160
|
+
let base64 = "";
|
|
161
|
+
|
|
162
|
+
for (let i = 0; i < u.byteLength; i += 3) {
|
|
163
|
+
const a = u[i];
|
|
164
|
+
const b = u[i + 1];
|
|
165
|
+
const c = u[i + 2];
|
|
166
|
+
|
|
167
|
+
const index1 = a >> 2;
|
|
168
|
+
const index2 = ((a & 0x03) << 4) | (b >> 4);
|
|
169
|
+
const index3 = isNaN(b!) ? 64 : ((b & 0x0f) << 2) | (c >> 6);
|
|
170
|
+
const index4 = isNaN(b!) || isNaN(c!) ? 64 : c & 0x3f;
|
|
171
|
+
|
|
172
|
+
base64 += chars[index1]! + chars[index2]! + chars[index3]! + chars[index4]!;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return base64;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function base64ToArrayBuffer(base64: string): ArrayBuffer {
|
|
179
|
+
const uint8Array = base64ToUint8Array(base64)!;
|
|
180
|
+
return uint8Array.buffer as ArrayBuffer;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function base64ToUint8Array(base64: string): Uint8Array {
|
|
184
|
+
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
185
|
+
const lookup = new Uint8Array(256);
|
|
186
|
+
|
|
187
|
+
for (let i = 0; i < chars.length; i++) {
|
|
188
|
+
lookup[chars.charCodeAt(i)] = i;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const padding = base64.endsWith("==") ? 2 : base64.endsWith("=") ? 1 : 0;
|
|
192
|
+
const length = (base64.length * 3 / 4) - padding;
|
|
193
|
+
const bytes = new Uint8Array(length);
|
|
194
|
+
|
|
195
|
+
for (let i = 0, j = 0; i < base64.length; i += 4, j += 3) {
|
|
196
|
+
const index1 = lookup[base64.charCodeAt(i)];
|
|
197
|
+
const index2 = lookup[base64.charCodeAt(i + 1)];
|
|
198
|
+
const index3 = lookup[base64.charCodeAt(i + 2)];
|
|
199
|
+
const index4 = lookup[base64.charCodeAt(i + 3)];
|
|
200
|
+
|
|
201
|
+
bytes[j] = (index1 << 2) | (index2 >> 4);
|
|
202
|
+
if (j + 1 < length) bytes[j + 1] = ((index2 & 0x0f) << 4) | (index3 >> 2);
|
|
203
|
+
if (j + 2 < length) bytes[j + 2] = ((index3 & 0x03) << 6) | index4;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return bytes;
|
|
207
|
+
}
|