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,175 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { FeatureStateSchema, FeatureOptionsSchema } from '../../schemas/base.js'
|
|
3
|
+
import { Feature } from '../feature.js'
|
|
4
|
+
import type { Helper } from '../../helper.js'
|
|
5
|
+
import type { ChildProcess } from '../../node/features/proc.js'
|
|
6
|
+
|
|
7
|
+
declare module '@soederpop/luca/feature' {
|
|
8
|
+
interface AvailableFeatures {
|
|
9
|
+
codingTools: typeof CodingTools
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const CodingToolsStateSchema = FeatureStateSchema.extend({})
|
|
14
|
+
export const CodingToolsOptionsSchema = FeatureOptionsSchema.extend({})
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Shell primitives for AI coding assistants: rg, ls, cat, sed, awk.
|
|
18
|
+
*
|
|
19
|
+
* Wraps standard Unix tools into the assistant tool surface with
|
|
20
|
+
* LLM-optimized descriptions and system prompt guidance. These are
|
|
21
|
+
* the raw, flexible tools for reading, searching, and exploring code.
|
|
22
|
+
*
|
|
23
|
+
* Compose with other features (fileTools, processManager, skillsLibrary)
|
|
24
|
+
* in assistant hooks for a complete coding tool surface.
|
|
25
|
+
*
|
|
26
|
+
* Usage:
|
|
27
|
+
* ```typescript
|
|
28
|
+
* assistant.use(container.feature('codingTools'))
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @extends Feature
|
|
32
|
+
*/
|
|
33
|
+
export class CodingTools extends Feature {
|
|
34
|
+
static override shortcut = 'features.codingTools' as const
|
|
35
|
+
static override stateSchema = CodingToolsStateSchema
|
|
36
|
+
static override optionsSchema = CodingToolsOptionsSchema
|
|
37
|
+
|
|
38
|
+
static { Feature.register(this, 'codingTools') }
|
|
39
|
+
|
|
40
|
+
static override tools: Record<string, { schema: z.ZodType; description?: string }> = {
|
|
41
|
+
rg: {
|
|
42
|
+
description: 'ripgrep — fast content search across files. The fastest way to find where something is defined, referenced, or used. Supports regex, file type filtering, context lines, and everything ripgrep supports.',
|
|
43
|
+
schema: z.object({
|
|
44
|
+
args: z.string().describe(
|
|
45
|
+
'Arguments to pass to rg, exactly as you would on the command line. ' +
|
|
46
|
+
'Examples: "TODO --type ts", "-n "function handleAuth" src/", ' +
|
|
47
|
+
'"import.*lodash -g "*.ts" --count", "-C 3 "class User" src/models/"'
|
|
48
|
+
),
|
|
49
|
+
cwd: z.string().optional().describe('Working directory. Defaults to project root.'),
|
|
50
|
+
}).describe('ripgrep — fast content search across files. Supports regex, file type filtering, context lines. Use this as your primary search tool for finding code.'),
|
|
51
|
+
},
|
|
52
|
+
ls: {
|
|
53
|
+
description: 'List files and directories. Use to orient yourself in the project structure, check what exists in a directory, or verify paths before operating on them.',
|
|
54
|
+
schema: z.object({
|
|
55
|
+
args: z.string().optional().describe(
|
|
56
|
+
'Arguments to pass to ls. Examples: "-la src/", "-R --color=never commands/", "-1 *.ts". ' +
|
|
57
|
+
'Defaults to listing the project root.'
|
|
58
|
+
),
|
|
59
|
+
cwd: z.string().optional().describe('Working directory. Defaults to project root.'),
|
|
60
|
+
}).describe('List files and directories. Use to orient yourself, check directory contents, or verify paths.'),
|
|
61
|
+
},
|
|
62
|
+
cat: {
|
|
63
|
+
description: 'Read file contents. Use for reading entire files or specific line ranges. For large files, prefer reading specific ranges with sed or use rg to find the relevant section first.',
|
|
64
|
+
schema: z.object({
|
|
65
|
+
args: z.string().describe(
|
|
66
|
+
'Arguments to pass to cat. Typically just a file path. ' +
|
|
67
|
+
'Examples: "src/index.ts", "-n src/index.ts" (with line numbers). ' +
|
|
68
|
+
'For line ranges, use sed instead: sed -n "10,20p" file.ts'
|
|
69
|
+
),
|
|
70
|
+
cwd: z.string().optional().describe('Working directory. Defaults to project root.'),
|
|
71
|
+
}).describe('Read file contents. Best for reading entire files or viewing file content with line numbers.'),
|
|
72
|
+
},
|
|
73
|
+
sed: {
|
|
74
|
+
description: 'Stream editor for extracting or transforming text. Use for reading specific line ranges from files, or performing find-and-replace operations.',
|
|
75
|
+
schema: z.object({
|
|
76
|
+
args: z.string().describe(
|
|
77
|
+
'Arguments to pass to sed. Examples: ' +
|
|
78
|
+
'"-n \\"10,30p\\" src/index.ts" (print lines 10-30), ' +
|
|
79
|
+
'"-n \\"1,5p\\" package.json" (first 5 lines), ' +
|
|
80
|
+
'"s/oldName/newName/g src/config.ts" (find-and-replace)'
|
|
81
|
+
),
|
|
82
|
+
cwd: z.string().optional().describe('Working directory. Defaults to project root.'),
|
|
83
|
+
}).describe('Stream editor for extracting line ranges or transforming text in files.'),
|
|
84
|
+
},
|
|
85
|
+
awk: {
|
|
86
|
+
description: 'Pattern scanning and text processing. Use for extracting specific fields from structured output, summarizing data, or complex text transformations.',
|
|
87
|
+
schema: z.object({
|
|
88
|
+
args: z.string().describe(
|
|
89
|
+
'Arguments to pass to awk. Examples: ' +
|
|
90
|
+
'"\'{print $1}\' file.txt" (first column), ' +
|
|
91
|
+
'"-F: \'{print $1, $3}\' /etc/passwd" (colon-delimited fields), ' +
|
|
92
|
+
'"\'/pattern/ {print}\' file.txt" (lines matching pattern)'
|
|
93
|
+
),
|
|
94
|
+
cwd: z.string().optional().describe('Working directory. Defaults to project root.'),
|
|
95
|
+
}).describe('Pattern scanning and text processing. Extract fields, summarize data, or perform complex text transformations.'),
|
|
96
|
+
},
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private get proc(): ChildProcess {
|
|
100
|
+
return this.container.feature('proc') as unknown as ChildProcess
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// -------------------------------------------------------------------------
|
|
104
|
+
// Shell tool implementations
|
|
105
|
+
// -------------------------------------------------------------------------
|
|
106
|
+
|
|
107
|
+
private async _exec(command: string, args: string, cwd?: string): Promise<string> {
|
|
108
|
+
const fullCommand = args ? `${command} ${args}` : command
|
|
109
|
+
const result = await this.proc.execAndCapture(fullCommand, {
|
|
110
|
+
cwd: cwd ?? this.container.cwd,
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
if (result.exitCode !== 0) {
|
|
114
|
+
const parts: string[] = []
|
|
115
|
+
if (result.stdout?.trim()) parts.push(result.stdout.trim())
|
|
116
|
+
if (result.stderr?.trim()) parts.push(`[stderr] ${result.stderr.trim()}`)
|
|
117
|
+
parts.push(`[exit code: ${result.exitCode}]`)
|
|
118
|
+
return parts.join('\n')
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return result.stdout || '(no output)'
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async rg(args: { args: string; cwd?: string }): Promise<string> {
|
|
125
|
+
return this._exec('rg', args.args, args.cwd)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async ls(args: { args?: string; cwd?: string }): Promise<string> {
|
|
129
|
+
return this._exec('ls', args.args || '', args.cwd)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async cat(args: { args: string; cwd?: string }): Promise<string> {
|
|
133
|
+
return this._exec('cat', args.args, args.cwd)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async sed(args: { args: string; cwd?: string }): Promise<string> {
|
|
137
|
+
return this._exec('sed', args.args, args.cwd)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async awk(args: { args: string; cwd?: string }): Promise<string> {
|
|
141
|
+
return this._exec('awk', args.args, args.cwd)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
override setupToolsConsumer(consumer: Helper) {
|
|
145
|
+
if (typeof (consumer as any).addSystemPromptExtension === 'function') {
|
|
146
|
+
(consumer as any).addSystemPromptExtension('codingTools', SYSTEM_PROMPT_EXTENSION)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// ─── System Prompt Extension ──────────────────────────────────────────────────
|
|
152
|
+
|
|
153
|
+
const SYSTEM_PROMPT_EXTENSION = [
|
|
154
|
+
'## Shell Tools',
|
|
155
|
+
'',
|
|
156
|
+
'You have direct access to standard Unix tools. These are your primary read/search/explore tools:',
|
|
157
|
+
'',
|
|
158
|
+
'**`rg` (ripgrep) — your most important tool.** Use it before guessing where anything is.',
|
|
159
|
+
'- `rg -n "pattern" --type ts` — search TypeScript files with line numbers',
|
|
160
|
+
'- `rg -C 3 "pattern"` — show 3 lines of context around matches',
|
|
161
|
+
'- `rg -l "pattern"` — list only filenames that match',
|
|
162
|
+
'- `rg "TODO|FIXME" --type ts --count` — count matches per file',
|
|
163
|
+
'',
|
|
164
|
+
'**`cat` — read files.** Use `cat -n` for line numbers. For large files, use `sed -n "10,30p"` to read a range.',
|
|
165
|
+
'',
|
|
166
|
+
'**`ls` — orient yourself.** `ls -la src/` for details, `ls -R` for recursive listing.',
|
|
167
|
+
'',
|
|
168
|
+
'**`sed` — extract line ranges.** `sed -n "50,80p" file.ts` reads lines 50-80.',
|
|
169
|
+
'',
|
|
170
|
+
'**`awk` — structured text processing.** Extract columns, summarize, transform.',
|
|
171
|
+
'',
|
|
172
|
+
'**Workflow:** `rg` to find → `cat -n` to read → `editFile` to change → `runCommand` to verify.',
|
|
173
|
+
].join('\n')
|
|
174
|
+
|
|
175
|
+
export default CodingTools
|
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { FeatureStateSchema, FeatureOptionsSchema, FeatureEventsSchema } from '../../schemas/base.js'
|
|
3
|
+
import { type AvailableFeatures } from '@soederpop/luca/feature'
|
|
4
|
+
import { Feature } from '../feature.js'
|
|
5
|
+
import type { DiskCache } from '@soederpop/luca/node/container'
|
|
6
|
+
import type { Message } from './conversation'
|
|
7
|
+
|
|
8
|
+
declare module '@soederpop/luca/feature' {
|
|
9
|
+
interface AvailableFeatures {
|
|
10
|
+
conversationHistory: typeof ConversationHistory
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface ConversationRecord {
|
|
15
|
+
id: string
|
|
16
|
+
title: string
|
|
17
|
+
model: string
|
|
18
|
+
messages: Message[]
|
|
19
|
+
tags: string[]
|
|
20
|
+
thread: string
|
|
21
|
+
createdAt: string
|
|
22
|
+
updatedAt: string
|
|
23
|
+
messageCount: number
|
|
24
|
+
metadata: Record<string, any>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type ConversationMeta = Omit<ConversationRecord, 'messages'>
|
|
28
|
+
|
|
29
|
+
export interface SearchOptions {
|
|
30
|
+
tag?: string
|
|
31
|
+
tags?: string[]
|
|
32
|
+
thread?: string
|
|
33
|
+
model?: string
|
|
34
|
+
before?: string | Date
|
|
35
|
+
after?: string | Date
|
|
36
|
+
query?: string
|
|
37
|
+
limit?: number
|
|
38
|
+
offset?: number
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const ConversationHistoryOptionsSchema = FeatureOptionsSchema.extend({
|
|
42
|
+
cachePath: z.string().optional().describe('Custom cache directory for conversation storage'),
|
|
43
|
+
namespace: z.string().optional().describe('Namespace prefix for cache keys to isolate datasets'),
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
export const ConversationHistoryStateSchema = FeatureStateSchema.extend({
|
|
47
|
+
conversationCount: z.number().describe('Total number of stored conversations'),
|
|
48
|
+
lastSaved: z.string().optional().describe('ISO timestamp of the last save operation'),
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
export const ConversationHistoryEventsSchema = FeatureEventsSchema.extend({
|
|
52
|
+
saved: z.tuple([z.string().describe('The conversation ID that was saved')]).describe('Fired after a conversation record is persisted'),
|
|
53
|
+
deleted: z.tuple([z.string().describe('The conversation ID that was deleted')]).describe('Fired after a conversation record is deleted'),
|
|
54
|
+
}).describe('ConversationHistory events')
|
|
55
|
+
|
|
56
|
+
export type ConversationHistoryOptions = z.infer<typeof ConversationHistoryOptionsSchema>
|
|
57
|
+
export type ConversationHistoryState = z.infer<typeof ConversationHistoryStateSchema>
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Persists conversations to disk using the diskCache feature (cacache).
|
|
61
|
+
* Each conversation is stored as a JSON blob keyed by ID, with metadata
|
|
62
|
+
* stored alongside for efficient listing and search without loading full message arrays.
|
|
63
|
+
*
|
|
64
|
+
* @extends Feature
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* const history = container.feature('conversationHistory', {
|
|
69
|
+
* namespace: 'my-app',
|
|
70
|
+
* cachePath: '/tmp/conversations'
|
|
71
|
+
* })
|
|
72
|
+
*
|
|
73
|
+
* // Create and retrieve conversations
|
|
74
|
+
* const record = await history.create({ messages, title: 'My Chat' })
|
|
75
|
+
* const loaded = await history.load(record.id)
|
|
76
|
+
*
|
|
77
|
+
* // Search and filter
|
|
78
|
+
* const results = await history.search({ tag: 'important', limit: 10 })
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export class ConversationHistory extends Feature<ConversationHistoryState, ConversationHistoryOptions> {
|
|
82
|
+
static override stateSchema = ConversationHistoryStateSchema
|
|
83
|
+
static override optionsSchema = ConversationHistoryOptionsSchema
|
|
84
|
+
static override eventsSchema = ConversationHistoryEventsSchema
|
|
85
|
+
static override shortcut = 'features.conversationHistory' as const
|
|
86
|
+
|
|
87
|
+
static { Feature.register(this, 'conversationHistory') }
|
|
88
|
+
|
|
89
|
+
/** @returns Default state with zero conversations and no last-saved timestamp. */
|
|
90
|
+
override get initialState(): ConversationHistoryState {
|
|
91
|
+
return {
|
|
92
|
+
...super.initialState,
|
|
93
|
+
conversationCount: 0,
|
|
94
|
+
lastSaved: undefined,
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
/** @returns The diskCache feature instance used for persistence, configured with the optional cachePath. */
|
|
100
|
+
get diskCache(): DiskCache {
|
|
101
|
+
const opts: Record<string, any> = {}
|
|
102
|
+
if (this.options.cachePath) {
|
|
103
|
+
opts.path = this.options.cachePath
|
|
104
|
+
}
|
|
105
|
+
return this.container.feature('diskCache', opts) as DiskCache
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** @returns The namespace prefix used for all cache keys, defaults to 'conversation-history'. */
|
|
109
|
+
get namespace(): string {
|
|
110
|
+
return this.options.namespace || 'conversation-history'
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private buildCacheKey(id: string): string {
|
|
114
|
+
return `${this.namespace}:${id}`
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
private metaKey(id: string): string {
|
|
118
|
+
return `${this.namespace}:meta:${id}`
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private indexKey(): string {
|
|
122
|
+
return `${this.namespace}:__index__`
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Save a conversation. Creates or overwrites by ID.
|
|
127
|
+
*
|
|
128
|
+
* @param {ConversationRecord} record - The full conversation record to persist
|
|
129
|
+
* @returns {Promise<void>}
|
|
130
|
+
*/
|
|
131
|
+
async save(record: ConversationRecord): Promise<void> {
|
|
132
|
+
record.updatedAt = new Date().toISOString()
|
|
133
|
+
record.messageCount = record.messages.length
|
|
134
|
+
|
|
135
|
+
// store the full conversation (messages included)
|
|
136
|
+
await this.diskCache.set(this.buildCacheKey(record.id), record)
|
|
137
|
+
|
|
138
|
+
// store lightweight metadata separately for fast listing
|
|
139
|
+
const meta: ConversationMeta = { ...record }
|
|
140
|
+
delete (meta as any).messages
|
|
141
|
+
await this.diskCache.set(this.metaKey(record.id), meta)
|
|
142
|
+
|
|
143
|
+
// update the index
|
|
144
|
+
await this.addToIndex(record.id)
|
|
145
|
+
|
|
146
|
+
this.state.set('lastSaved', record.updatedAt)
|
|
147
|
+
this.emit('saved', record.id)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Create a new conversation from messages, returning the saved record.
|
|
152
|
+
*
|
|
153
|
+
* @param {object} opts - Creation options including messages, optional title, model, tags, thread, and metadata
|
|
154
|
+
* @returns {Promise<ConversationRecord>} The newly created and persisted conversation record
|
|
155
|
+
*/
|
|
156
|
+
async create(opts: {
|
|
157
|
+
id?: string
|
|
158
|
+
title?: string
|
|
159
|
+
model?: string
|
|
160
|
+
messages: Message[]
|
|
161
|
+
tags?: string[]
|
|
162
|
+
thread?: string
|
|
163
|
+
metadata?: Record<string, any>
|
|
164
|
+
}): Promise<ConversationRecord> {
|
|
165
|
+
const now = new Date().toISOString()
|
|
166
|
+
const record: ConversationRecord = {
|
|
167
|
+
id: opts.id || crypto.randomUUID(),
|
|
168
|
+
title: opts.title || 'Untitled',
|
|
169
|
+
model: opts.model || 'unknown',
|
|
170
|
+
messages: opts.messages,
|
|
171
|
+
tags: opts.tags || [],
|
|
172
|
+
thread: opts.thread || 'default',
|
|
173
|
+
createdAt: now,
|
|
174
|
+
updatedAt: now,
|
|
175
|
+
messageCount: opts.messages.length,
|
|
176
|
+
metadata: opts.metadata || {},
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
await this.save(record)
|
|
180
|
+
return record
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Load a full conversation by ID, including all messages.
|
|
185
|
+
*
|
|
186
|
+
* @param {string} id - The conversation ID
|
|
187
|
+
* @returns {Promise<ConversationRecord | null>} The full record, or null if not found
|
|
188
|
+
*/
|
|
189
|
+
async load(id: string): Promise<ConversationRecord | null> {
|
|
190
|
+
const exists = await this.diskCache.has(this.buildCacheKey(id))
|
|
191
|
+
if (!exists) return null
|
|
192
|
+
return this.diskCache.get(this.buildCacheKey(id), true)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Load just the metadata for a conversation (no messages).
|
|
197
|
+
*
|
|
198
|
+
* @param {string} id - The conversation ID
|
|
199
|
+
* @returns {Promise<ConversationMeta | null>} The lightweight metadata record, or null if not found
|
|
200
|
+
*/
|
|
201
|
+
async getMeta(id: string): Promise<ConversationMeta | null> {
|
|
202
|
+
const exists = await this.diskCache.has(this.metaKey(id))
|
|
203
|
+
if (!exists) return null
|
|
204
|
+
return this.diskCache.get(this.metaKey(id), true)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Append messages to an existing conversation.
|
|
209
|
+
*
|
|
210
|
+
* @param {string} id - The conversation ID to append to
|
|
211
|
+
* @param {Message[]} messages - The messages to append
|
|
212
|
+
* @returns {Promise<ConversationRecord | null>} The updated record, or null if the conversation was not found
|
|
213
|
+
*/
|
|
214
|
+
async append(id: string, messages: Message[]): Promise<ConversationRecord | null> {
|
|
215
|
+
const record = await this.load(id)
|
|
216
|
+
if (!record) return null
|
|
217
|
+
|
|
218
|
+
record.messages.push(...messages)
|
|
219
|
+
await this.save(record)
|
|
220
|
+
return record
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Delete a conversation by ID.
|
|
225
|
+
*
|
|
226
|
+
* @param {string} id - The conversation ID to delete
|
|
227
|
+
* @returns {Promise<boolean>} True if the conversation existed and was deleted
|
|
228
|
+
*/
|
|
229
|
+
async delete(id: string): Promise<boolean> {
|
|
230
|
+
const exists = await this.diskCache.has(this.buildCacheKey(id))
|
|
231
|
+
if (!exists) return false
|
|
232
|
+
|
|
233
|
+
await this.diskCache.rm(this.buildCacheKey(id))
|
|
234
|
+
await this.diskCache.rm(this.metaKey(id)).catch(() => {})
|
|
235
|
+
await this.removeFromIndex(id)
|
|
236
|
+
|
|
237
|
+
this.emit('deleted', id)
|
|
238
|
+
return true
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* List all conversation metadata, with optional search/filter.
|
|
243
|
+
* Loads only the lightweight meta records, never the full messages.
|
|
244
|
+
*
|
|
245
|
+
* @param {SearchOptions} [options] - Optional filters for tag, thread, model, date range, and text query
|
|
246
|
+
* @returns {Promise<ConversationMeta[]>} Filtered and sorted metadata records (newest first)
|
|
247
|
+
*/
|
|
248
|
+
async list(options?: SearchOptions): Promise<ConversationMeta[]> {
|
|
249
|
+
const ids = await this.getIndex()
|
|
250
|
+
const metas: ConversationMeta[] = []
|
|
251
|
+
|
|
252
|
+
for (const id of ids) {
|
|
253
|
+
const meta = await this.getMeta(id)
|
|
254
|
+
if (meta) metas.push(meta)
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return this.applyFilters(metas, options)
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Search conversations by text query across titles, tags, and metadata.
|
|
262
|
+
* Also supports filtering by tag, thread, model, and date range.
|
|
263
|
+
*
|
|
264
|
+
* @param {SearchOptions} options - Search and filter criteria
|
|
265
|
+
* @returns {Promise<ConversationMeta[]>} Matching metadata records (newest first)
|
|
266
|
+
*/
|
|
267
|
+
async search(options: SearchOptions): Promise<ConversationMeta[]> {
|
|
268
|
+
return this.list(options)
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Get all unique tags across all conversations.
|
|
273
|
+
*
|
|
274
|
+
* @returns {Promise<string[]>} Sorted array of unique tag strings
|
|
275
|
+
*/
|
|
276
|
+
async allTags(): Promise<string[]> {
|
|
277
|
+
const metas = await this.list()
|
|
278
|
+
const tags = new Set<string>()
|
|
279
|
+
for (const meta of metas) {
|
|
280
|
+
for (const tag of meta.tags) {
|
|
281
|
+
tags.add(tag)
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return [...tags].sort()
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Get all unique threads across all conversations.
|
|
289
|
+
*
|
|
290
|
+
* @returns {Promise<string[]>} Sorted array of unique thread identifiers
|
|
291
|
+
*/
|
|
292
|
+
async allThreads(): Promise<string[]> {
|
|
293
|
+
const metas = await this.list()
|
|
294
|
+
const threads = new Set<string>()
|
|
295
|
+
for (const meta of metas) {
|
|
296
|
+
threads.add(meta.thread)
|
|
297
|
+
}
|
|
298
|
+
return [...threads].sort()
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Tag a conversation. Adds tags without duplicates.
|
|
303
|
+
*
|
|
304
|
+
* @param {string} id - The conversation ID
|
|
305
|
+
* @param {...string} tags - One or more tags to add
|
|
306
|
+
* @returns {Promise<boolean>} True if the conversation was found and updated
|
|
307
|
+
*/
|
|
308
|
+
async tag(id: string, ...tags: string[]): Promise<boolean> {
|
|
309
|
+
const record = await this.load(id)
|
|
310
|
+
if (!record) return false
|
|
311
|
+
|
|
312
|
+
const tagSet = new Set(record.tags)
|
|
313
|
+
for (const t of tags) tagSet.add(t)
|
|
314
|
+
record.tags = [...tagSet]
|
|
315
|
+
|
|
316
|
+
await this.save(record)
|
|
317
|
+
return true
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Remove tags from a conversation.
|
|
322
|
+
*
|
|
323
|
+
* @param {string} id - The conversation ID
|
|
324
|
+
* @param {...string} tags - One or more tags to remove
|
|
325
|
+
* @returns {Promise<boolean>} True if the conversation was found and updated
|
|
326
|
+
*/
|
|
327
|
+
async untag(id: string, ...tags: string[]): Promise<boolean> {
|
|
328
|
+
const record = await this.load(id)
|
|
329
|
+
if (!record) return false
|
|
330
|
+
|
|
331
|
+
const removeSet = new Set(tags)
|
|
332
|
+
record.tags = record.tags.filter(t => !removeSet.has(t))
|
|
333
|
+
|
|
334
|
+
await this.save(record)
|
|
335
|
+
return true
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Update metadata on a conversation without touching messages.
|
|
340
|
+
*
|
|
341
|
+
* @param {string} id - The conversation ID
|
|
342
|
+
* @param {object} updates - Partial updates for title, tags, thread, and/or metadata
|
|
343
|
+
* @returns {Promise<boolean>} True if the conversation was found and updated
|
|
344
|
+
*/
|
|
345
|
+
async updateMeta(id: string, updates: Partial<Pick<ConversationRecord, 'title' | 'tags' | 'thread' | 'metadata'>>): Promise<boolean> {
|
|
346
|
+
const record = await this.load(id)
|
|
347
|
+
if (!record) return false
|
|
348
|
+
|
|
349
|
+
if (updates.title !== undefined) record.title = updates.title
|
|
350
|
+
if (updates.tags !== undefined) record.tags = updates.tags
|
|
351
|
+
if (updates.thread !== undefined) record.thread = updates.thread
|
|
352
|
+
if (updates.metadata !== undefined) record.metadata = { ...record.metadata, ...updates.metadata }
|
|
353
|
+
|
|
354
|
+
await this.save(record)
|
|
355
|
+
return true
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Find the most recent conversation for an exact thread ID.
|
|
360
|
+
*
|
|
361
|
+
* @param {string} thread - The exact thread ID to match
|
|
362
|
+
* @returns {Promise<ConversationRecord | null>} The full record with messages, or null if none found
|
|
363
|
+
*/
|
|
364
|
+
async findByThread(thread: string): Promise<ConversationRecord | null> {
|
|
365
|
+
const metas = await this.list({ thread })
|
|
366
|
+
if (!metas.length) return null
|
|
367
|
+
return this.load(metas[0]!.id)
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Find all conversations whose thread starts with a prefix.
|
|
372
|
+
*
|
|
373
|
+
* @param {string} prefix - The thread prefix to match
|
|
374
|
+
* @returns {Promise<ConversationMeta[]>} Matching metadata records (newest first)
|
|
375
|
+
*/
|
|
376
|
+
async findByThreadPrefix(prefix: string): Promise<ConversationMeta[]> {
|
|
377
|
+
const all = await this.list()
|
|
378
|
+
return all.filter(m => m.thread.startsWith(prefix))
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Delete all conversations for an exact thread.
|
|
383
|
+
*
|
|
384
|
+
* @param {string} thread - The exact thread ID
|
|
385
|
+
* @returns {Promise<number>} Number of conversations deleted
|
|
386
|
+
*/
|
|
387
|
+
async deleteThread(thread: string): Promise<number> {
|
|
388
|
+
const metas = await this.list({ thread })
|
|
389
|
+
let count = 0
|
|
390
|
+
for (const meta of metas) {
|
|
391
|
+
if (await this.delete(meta.id)) count++
|
|
392
|
+
}
|
|
393
|
+
return count
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Delete all conversations matching a thread prefix.
|
|
398
|
+
*
|
|
399
|
+
* @param {string} prefix - The thread prefix to match
|
|
400
|
+
* @returns {Promise<number>} Number of conversations deleted
|
|
401
|
+
*/
|
|
402
|
+
async deleteByThreadPrefix(prefix: string): Promise<number> {
|
|
403
|
+
const metas = await this.findByThreadPrefix(prefix)
|
|
404
|
+
let count = 0
|
|
405
|
+
for (const meta of metas) {
|
|
406
|
+
if (await this.delete(meta.id)) count++
|
|
407
|
+
}
|
|
408
|
+
return count
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// -- index management --
|
|
412
|
+
|
|
413
|
+
private async getIndex(): Promise<string[]> {
|
|
414
|
+
const exists = await this.diskCache.has(this.indexKey())
|
|
415
|
+
if (!exists) return []
|
|
416
|
+
return this.diskCache.get(this.indexKey(), true)
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
private async setIndex(ids: string[]): Promise<void> {
|
|
420
|
+
await this.diskCache.set(this.indexKey(), ids)
|
|
421
|
+
this.state.set('conversationCount', ids.length)
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
private async addToIndex(id: string): Promise<void> {
|
|
425
|
+
const ids = await this.getIndex()
|
|
426
|
+
if (!ids.includes(id)) {
|
|
427
|
+
ids.push(id)
|
|
428
|
+
await this.setIndex(ids)
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
private async removeFromIndex(id: string): Promise<void> {
|
|
433
|
+
const ids = await this.getIndex()
|
|
434
|
+
await this.setIndex(ids.filter(i => i !== id))
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// -- filtering --
|
|
438
|
+
|
|
439
|
+
private applyFilters(metas: ConversationMeta[], options?: SearchOptions): ConversationMeta[] {
|
|
440
|
+
if (!options) return metas
|
|
441
|
+
|
|
442
|
+
let results = metas
|
|
443
|
+
|
|
444
|
+
if (options.tag) {
|
|
445
|
+
results = results.filter(m => m.tags.includes(options.tag!))
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
if (options.tags && options.tags.length) {
|
|
449
|
+
results = results.filter(m => options.tags!.every(t => m.tags.includes(t)))
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
if (options.thread) {
|
|
453
|
+
results = results.filter(m => m.thread === options.thread)
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
if (options.model) {
|
|
457
|
+
results = results.filter(m => m.model === options.model)
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
if (options.after) {
|
|
461
|
+
const after = new Date(options.after).getTime()
|
|
462
|
+
results = results.filter(m => new Date(m.createdAt).getTime() >= after)
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
if (options.before) {
|
|
466
|
+
const before = new Date(options.before).getTime()
|
|
467
|
+
results = results.filter(m => new Date(m.createdAt).getTime() <= before)
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
if (options.query) {
|
|
471
|
+
const q = options.query.toLowerCase()
|
|
472
|
+
results = results.filter(m =>
|
|
473
|
+
m.title.toLowerCase().includes(q) ||
|
|
474
|
+
m.tags.some(t => t.toLowerCase().includes(q)) ||
|
|
475
|
+
m.thread.toLowerCase().includes(q) ||
|
|
476
|
+
JSON.stringify(m.metadata).toLowerCase().includes(q)
|
|
477
|
+
)
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// sort newest first
|
|
481
|
+
results.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime())
|
|
482
|
+
|
|
483
|
+
if (options.offset) {
|
|
484
|
+
results = results.slice(options.offset)
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
if (options.limit) {
|
|
488
|
+
results = results.slice(0, options.limit)
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
return results
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
export default ConversationHistory
|