@soederpop/luca 0.1.2 → 0.2.1
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 +167 -0
- package/CLAUDE.md +2 -0
- package/README.md +3 -0
- package/assistants/codingAssistant/ABOUT.md +3 -0
- package/assistants/codingAssistant/CORE.md +22 -17
- package/assistants/codingAssistant/hooks.ts +17 -4
- package/assistants/codingAssistant/tools.ts +1 -106
- package/assistants/inkbot/ABOUT.md +5 -0
- package/assistants/inkbot/CORE.md +71 -0
- package/assistants/inkbot/hooks.ts +14 -0
- package/assistants/inkbot/tools.ts +47 -0
- package/bun.lock +20 -4
- package/commands/inkbot.ts +353 -0
- package/commands/release.ts +75 -181
- 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/apis/features/agi/assistant.md +1 -0
- package/docs/apis/features/agi/assistants-manager.md +62 -2
- package/docs/apis/features/agi/auto-assistant.md +11 -109
- package/docs/apis/features/agi/claude-code.md +138 -0
- package/docs/apis/features/agi/conversation.md +60 -31
- package/docs/apis/features/agi/luca-coder.md +407 -0
- package/docs/apis/features/agi/openapi.md +2 -2
- package/docs/apis/features/agi/skills-library.md +12 -0
- package/docs/apis/features/node/python.md +81 -11
- package/docs/apis/features/node/transpiler.md +74 -0
- package/docs/apis/features/web/esbuild.md +0 -6
- package/docs/apis/servers/mcp.md +2 -2
- package/docs/examples/entity.md +124 -0
- package/docs/ideas/assistant-factory-pattern.md +142 -0
- package/package.json +74 -21
- package/src/agi/container.server.ts +10 -0
- package/src/agi/feature.ts +13 -0
- package/src/agi/features/agent-memory.ts +694 -0
- package/src/agi/features/assistant.ts +37 -26
- package/src/agi/features/assistants-manager.ts +95 -5
- package/src/agi/features/autonomous-assistant.ts +1 -5
- package/src/agi/features/browser-use.ts +32 -2
- package/src/agi/features/claude-code.ts +165 -1
- package/src/agi/features/coding-tools.ts +175 -0
- package/src/agi/features/conversation-history.ts +2 -6
- package/src/agi/features/conversation.ts +95 -3
- package/src/agi/features/docs-reader.ts +2 -1
- package/src/agi/features/file-tools.ts +35 -28
- package/src/agi/features/luca-coder.ts +1 -5
- package/src/agi/features/openai-codex.ts +1 -1
- package/src/agi/features/openapi.ts +3 -3
- package/src/agi/features/skills-library.ts +111 -13
- package/src/agi/lib/interceptor-chain.ts +10 -0
- package/src/agi/lib/token-counter.ts +1 -1
- package/src/bootstrap/generated.ts +126 -1
- package/src/bus.ts +27 -5
- package/src/cli/build-info.ts +2 -2
- package/src/client.ts +2 -2
- package/src/clients/elevenlabs/index.ts +5 -0
- package/src/clients/voicebox/index.ts +300 -0
- package/src/commands/bootstrap.ts +2 -1
- package/src/commands/chat.ts +1 -0
- package/src/commands/code.ts +4 -2
- package/src/commands/prompt.ts +34 -34
- package/src/commands/sandbox-mcp.ts +69 -163
- package/src/commands/save-api-docs.ts +10 -8
- package/src/commands/select.ts +8 -3
- package/src/container-describer.ts +70 -84
- package/src/container.ts +93 -3
- package/src/endpoint.ts +1 -1
- package/src/entity.ts +173 -0
- package/src/feature.ts +3 -3
- package/src/helper.ts +8 -4
- package/src/introspection/generated.agi.ts +3012 -1356
- package/src/introspection/generated.node.ts +179 -33
- package/src/introspection/generated.web.ts +95 -3
- package/src/introspection/scan.ts +1 -1
- package/src/node/container.ts +1 -1
- package/src/node/features/content-db.ts +57 -30
- package/src/node/features/file-manager.ts +10 -9
- package/src/node/features/git.ts +5 -5
- package/src/node/features/helpers.ts +1 -1
- package/src/node/features/json-tree.ts +1 -1
- package/src/node/features/os.ts +3 -3
- package/src/node/features/package-finder.ts +1 -1
- package/src/node/features/process-manager.ts +51 -18
- package/src/node/features/python.ts +3 -3
- package/src/node/features/redis.ts +1 -1
- package/src/node/features/repl.ts +2 -2
- package/src/node/features/transpiler.ts +2 -2
- package/src/node/features/ui.ts +1 -1
- package/src/node/features/vm.ts +3 -3
- package/src/node/features/yaml-tree.ts +1 -1
- package/src/node.ts +1 -0
- package/src/python/generated.ts +1 -1
- package/src/scaffolds/generated.ts +1 -1
- package/src/selector.ts +74 -4
- package/src/server.ts +2 -2
- package/src/servers/mcp.ts +6 -6
- package/src/web/features/helpers.ts +1 -1
- package/src/web/features/network.ts +1 -0
- package/test/assistant.test.ts +14 -5
- package/test/conversation.test.ts +220 -0
- package/test-integration/memory.test.ts +204 -0
- package/tsconfig.build.json +12 -0
- package/tsconfig.json +1 -1
- package/scripts/examples/telegram-ink-ui.ts +0 -302
- package/scripts/examples/using-openai-codex.ts +0 -23
- package/scripts/examples/vm-loading-esm-modules.ts +0 -16
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { z } from 'zod'
|
|
2
2
|
import { FeatureStateSchema, FeatureOptionsSchema, FeatureEventsSchema } from '../../schemas/base.js'
|
|
3
|
-
import { type AvailableFeatures
|
|
3
|
+
import { type AvailableFeatures } from '@soederpop/luca/feature'
|
|
4
|
+
import { Feature } from '../feature.js'
|
|
4
5
|
import { parse } from 'contentbase'
|
|
5
6
|
import type { DocsReader } from './docs-reader.js'
|
|
6
|
-
import
|
|
7
|
+
import Assistant from './assistant.js'
|
|
7
8
|
|
|
8
9
|
declare module '@soederpop/luca/feature' {
|
|
9
10
|
interface AvailableFeatures {
|
|
@@ -72,22 +73,22 @@ export class SkillsLibrary extends Feature<SkillsLibraryState, SkillsLibraryOpti
|
|
|
72
73
|
static { Feature.register(this, 'skillsLibrary') }
|
|
73
74
|
|
|
74
75
|
/** Tools for assistant integration via assistant.use(skillsLibrary). */
|
|
75
|
-
static tools: Record<string, { schema: z.ZodType; handler?: Function }> = {
|
|
76
|
+
static override tools: Record<string, { schema: z.ZodType; handler?: Function }> = {
|
|
76
77
|
searchAvailableSkills: {
|
|
77
78
|
schema: z.object({
|
|
78
|
-
query: z.string().optional().describe('
|
|
79
|
-
}).describe('
|
|
79
|
+
query: z.string().optional().describe('A keyword or phrase to filter skills by name or description. Omit to list all available skills.'),
|
|
80
|
+
}).describe('Discover what skills are available. Call this first when you need specialized knowledge — skills are curated guides and reference material for specific domains (frameworks, tools, patterns). Returns skill names and descriptions so you can decide which to load.'),
|
|
80
81
|
},
|
|
81
82
|
loadSkill: {
|
|
82
83
|
schema: z.object({
|
|
83
|
-
skillName: z.string().describe('The name
|
|
84
|
-
}).describe('Load a skill
|
|
84
|
+
skillName: z.string().describe('The exact skill name as returned by searchAvailableSkills'),
|
|
85
|
+
}).describe('Load a skill\'s full reference content (SKILL.md). This gives you detailed guidance, examples, and best practices for that domain. Load a skill before attempting work in an unfamiliar area — the content is curated to prevent common mistakes.'),
|
|
85
86
|
},
|
|
86
87
|
askSkillBasedQuestion: {
|
|
87
88
|
schema: z.object({
|
|
88
|
-
skillName: z.string().describe('The
|
|
89
|
-
question: z.string().describe('
|
|
90
|
-
}).describe('Ask a question about a
|
|
89
|
+
skillName: z.string().describe('The exact skill name to query'),
|
|
90
|
+
question: z.string().describe('A specific question about the skill\'s domain. Be precise — "how do I add a new feature to the container?" is better than "tell me about features".'),
|
|
91
|
+
}).describe('Ask a focused question about a skill\'s domain using AI-assisted document reading. Use this when you need a specific answer from a skill rather than reading the whole thing. More efficient than loadSkill for targeted lookups.'),
|
|
91
92
|
},
|
|
92
93
|
}
|
|
93
94
|
|
|
@@ -102,9 +103,61 @@ export class SkillsLibrary extends Feature<SkillsLibraryState, SkillsLibraryOpti
|
|
|
102
103
|
}
|
|
103
104
|
}
|
|
104
105
|
|
|
105
|
-
override setupToolsConsumer(assistant:
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
override setupToolsConsumer(assistant: Feature) {
|
|
107
|
+
if (!(assistant instanceof Assistant)) {
|
|
108
|
+
throw new Error('Skills library tools require an Assistant instance (including subclasses).')
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const a : Assistant = assistant as Assistant
|
|
112
|
+
|
|
113
|
+
a.addSystemPromptExtension('skillsLibrary', [
|
|
114
|
+
'## Skills Library',
|
|
115
|
+
'',
|
|
116
|
+
'You have access to a library of curated skills — domain-specific reference guides with examples, patterns, and best practices.',
|
|
117
|
+
'',
|
|
118
|
+
'**When to use skills:**',
|
|
119
|
+
'- When working in an unfamiliar domain or framework — load the skill before writing code',
|
|
120
|
+
'- When the user asks about a topic that might have a matching skill — search first',
|
|
121
|
+
'- When you see "Required Skills" in a message — load those skills immediately with `loadSkill` before answering',
|
|
122
|
+
'',
|
|
123
|
+
'**Workflow:** `searchAvailableSkills` → find relevant skill → `loadSkill` to get the full guide → follow its patterns. Use `askSkillBasedQuestion` for targeted lookups when you don\'t need the whole guide.',
|
|
124
|
+
'',
|
|
125
|
+
'**Skills are authoritative.** When a loaded skill contradicts your general knowledge, follow the skill — it reflects project-specific conventions and decisions.',
|
|
126
|
+
].join('\n'))
|
|
127
|
+
|
|
128
|
+
const { container } = a
|
|
129
|
+
|
|
130
|
+
const skillsLibrary = this
|
|
131
|
+
|
|
132
|
+
const preloadSkills : string[] = []
|
|
133
|
+
if (a.meta.skills) {
|
|
134
|
+
if (Array.isArray(a.meta.skills)) {
|
|
135
|
+
preloadSkills.push(...a.meta.skills)
|
|
136
|
+
} else {
|
|
137
|
+
preloadSkills.push(a.meta.skills)
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async function beforeAskCheckIfWeNeedSkills(ctx: any, next: any) {
|
|
142
|
+
const { question } = ctx
|
|
143
|
+
const skills = await skillsLibrary.findRelevantSkillsForAssistant(a, question as string)
|
|
144
|
+
|
|
145
|
+
const allSkillsToLoad : string[] = container.utils.lodash.uniq([
|
|
146
|
+
...skills,
|
|
147
|
+
...preloadSkills,
|
|
148
|
+
])
|
|
149
|
+
|
|
150
|
+
if (allSkillsToLoad.length) {
|
|
151
|
+
ctx.question = `${ctx.question} \n\n## Required Skills\nYou will need to load the following skills to answer this question: ${skills.join(', ')}`
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
a.interceptors.beforeAsk.remove(beforeAskCheckIfWeNeedSkills)
|
|
155
|
+
|
|
156
|
+
await next()
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
assistant.intercept('beforeAsk', beforeAskCheckIfWeNeedSkills as any)
|
|
160
|
+
|
|
108
161
|
return assistant
|
|
109
162
|
}
|
|
110
163
|
|
|
@@ -375,6 +428,51 @@ export class SkillsLibrary extends Feature<SkillsLibraryState, SkillsLibraryOpti
|
|
|
375
428
|
const answer = await reader.ask(question)
|
|
376
429
|
return answer
|
|
377
430
|
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Fork the given assistant and ask it which skills (if any) are relevant
|
|
434
|
+
* to the user's query. Returns an array of skill names that should be loaded
|
|
435
|
+
* before the real question is answered.
|
|
436
|
+
*
|
|
437
|
+
* The fork is ephemeral (historyMode: 'none') and uses structured output so
|
|
438
|
+
* the result is always a clean string array — never free text.
|
|
439
|
+
*
|
|
440
|
+
* @param assistant - The assistant instance to fork
|
|
441
|
+
* @param userQuery - The user's original question
|
|
442
|
+
* @returns Array of skill names relevant to the query (may be empty)
|
|
443
|
+
*/
|
|
444
|
+
async findRelevantSkillsForAssistant(assistant: Assistant, userQuery: string): Promise<string[]> {
|
|
445
|
+
if (!this.isStarted) await this.start()
|
|
446
|
+
|
|
447
|
+
const skills = this.list()
|
|
448
|
+
if (skills.length === 0) return []
|
|
449
|
+
|
|
450
|
+
const responseSchema = z.object({
|
|
451
|
+
skills: z.array(z.string()).describe('Names of skills relevant to the query. Empty array if none apply.'),
|
|
452
|
+
})
|
|
453
|
+
|
|
454
|
+
const skillsDescription = Object.entries(this.skillsTable)
|
|
455
|
+
.map(([title,description]) => `- **${title}**: ${description}`)
|
|
456
|
+
.join("\n")
|
|
457
|
+
|
|
458
|
+
const prompt = this.container.ui.endent(`You are a routing assistant. Given a user query and a list of available skills, determine which skills (if any) should be loaded to help answer the query.
|
|
459
|
+
Available skills:
|
|
460
|
+
-------
|
|
461
|
+
${skillsDescription}
|
|
462
|
+
|
|
463
|
+
User query: ${userQuery}
|
|
464
|
+
|
|
465
|
+
Return only the skill names that are directly relevant. Return an empty array if none apply. Do not load skills speculatively — only include ones that would materially help answer this specific query.`)
|
|
466
|
+
|
|
467
|
+
const fork = assistant.conversation.fork()
|
|
468
|
+
const result = await fork.ask(prompt, { schema: responseSchema }) as unknown as { skills: string[] }
|
|
469
|
+
|
|
470
|
+
const found = result.skills.filter(name => this.find(name) !== undefined)
|
|
471
|
+
|
|
472
|
+
this.emit('foundSkills', found, assistant, userQuery)
|
|
473
|
+
|
|
474
|
+
return found
|
|
475
|
+
}
|
|
378
476
|
}
|
|
379
477
|
|
|
380
478
|
export default SkillsLibrary
|
|
@@ -26,6 +26,16 @@ export class InterceptorChain<T> {
|
|
|
26
26
|
return this.fns.length
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
clear(): void {
|
|
30
|
+
this.fns = []
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
clone(): InterceptorChain<T> {
|
|
34
|
+
const copy = new InterceptorChain<T>()
|
|
35
|
+
for (const fn of this.fns) copy.add(fn)
|
|
36
|
+
return copy
|
|
37
|
+
}
|
|
38
|
+
|
|
29
39
|
async run(ctx: T, final: () => Promise<void>): Promise<void> {
|
|
30
40
|
let index = 0
|
|
31
41
|
const fns = this.fns
|
|
@@ -39,7 +39,7 @@ export function getContextWindow(model: string): number {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
return best ? MODEL_CONTEXT_WINDOWS[best] : DEFAULT_CONTEXT_WINDOW
|
|
42
|
+
return best ? MODEL_CONTEXT_WINDOWS[best] ?? DEFAULT_CONTEXT_WINDOW : DEFAULT_CONTEXT_WINDOW
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/** Get a cached tiktoken encoder for a model (falls back to o200k_base). */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Auto-generated bootstrap content
|
|
2
|
-
// Generated at: 2026-
|
|
2
|
+
// Generated at: 2026-04-05T06:58:07.990Z
|
|
3
3
|
// Source: docs/bootstrap/*.md, docs/bootstrap/templates/*, docs/examples/*.md, docs/tutorials/*.md
|
|
4
4
|
//
|
|
5
5
|
// Do not edit manually. Run: luca build-bootstrap
|
|
@@ -1253,6 +1253,131 @@ console.log('Running after killAll:', remaining.length)
|
|
|
1253
1253
|
## Summary
|
|
1254
1254
|
|
|
1255
1255
|
This demo covered the \`processManager\` feature: spawning processes that return handles immediately, tracking them by ID or tag, listing all tracked processes, and killing them individually or all at once. It is the right tool for orchestrating background services, dev servers, and any scenario where you need non-blocking process management with lifecycle events.
|
|
1256
|
+
`,
|
|
1257
|
+
"entity.md": `---
|
|
1258
|
+
title: "Entity"
|
|
1259
|
+
tags: [entity, state, events, tools, core]
|
|
1260
|
+
lastTested: null
|
|
1261
|
+
lastTestPassed: null
|
|
1262
|
+
---
|
|
1263
|
+
|
|
1264
|
+
# entity
|
|
1265
|
+
|
|
1266
|
+
Lightweight, composable objects with observable state, a typed event bus, and an optional tool interface.
|
|
1267
|
+
|
|
1268
|
+
## Overview
|
|
1269
|
+
|
|
1270
|
+
An entity is a plain object — not a class — created via \`container.entity(id, options?)\`. Same id + options always returns the same underlying state and bus instance. Entities are designed to be extended with methods and getters via \`.extend()\`, and can expose those methods as AI tools via \`.expose()\`.
|
|
1271
|
+
|
|
1272
|
+
## Basic Entity with Observable State
|
|
1273
|
+
|
|
1274
|
+
Create an entity and read/write state through the observable \`state\` property.
|
|
1275
|
+
|
|
1276
|
+
\`\`\`ts
|
|
1277
|
+
const counter = container.entity<{ count: number }>('counter')
|
|
1278
|
+
counter.setState({ count: 0 })
|
|
1279
|
+
|
|
1280
|
+
counter.state.observe((next) => {
|
|
1281
|
+
console.log('count changed to', next.count)
|
|
1282
|
+
})
|
|
1283
|
+
|
|
1284
|
+
counter.setState(s => ({ count: s.count + 1 }))
|
|
1285
|
+
counter.setState(s => ({ count: s.count + 1 }))
|
|
1286
|
+
console.log('final count:', counter.state.get('count'))
|
|
1287
|
+
\`\`\`
|
|
1288
|
+
|
|
1289
|
+
\`setState\` accepts either a partial object or a function that receives the current state. Observers fire synchronously after each change.
|
|
1290
|
+
|
|
1291
|
+
## Typed Event Bus
|
|
1292
|
+
|
|
1293
|
+
Every entity has a built-in event bus. Declare the event map as the third type parameter.
|
|
1294
|
+
|
|
1295
|
+
\`\`\`ts
|
|
1296
|
+
type TimerEvents = {
|
|
1297
|
+
tick: [elapsed: number]
|
|
1298
|
+
done: []
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
const timer = container.entity<{}, {}, TimerEvents>('timer')
|
|
1302
|
+
|
|
1303
|
+
timer.on('tick', (elapsed) => {
|
|
1304
|
+
console.log('tick at', elapsed, 'ms')
|
|
1305
|
+
})
|
|
1306
|
+
|
|
1307
|
+
timer.once('done', () => {
|
|
1308
|
+
console.log('timer finished')
|
|
1309
|
+
})
|
|
1310
|
+
|
|
1311
|
+
timer.emit('tick', 100)
|
|
1312
|
+
timer.emit('tick', 200)
|
|
1313
|
+
timer.emit('done')
|
|
1314
|
+
\`\`\`
|
|
1315
|
+
|
|
1316
|
+
\`once\` auto-detaches after the first fire. \`waitFor\` returns a promise that resolves on the next emit of that event.
|
|
1317
|
+
|
|
1318
|
+
## Extending with Methods
|
|
1319
|
+
|
|
1320
|
+
Use \`.extend()\` to graft methods and getters onto an entity. All base properties — \`state\`, \`options\`, \`container\`, and the event methods — are available via \`this\`.
|
|
1321
|
+
|
|
1322
|
+
\`\`\`ts
|
|
1323
|
+
const session = container.entity('session', { userId: '42' })
|
|
1324
|
+
.extend({
|
|
1325
|
+
greet() {
|
|
1326
|
+
return \`Hello user \${this.options.userId}\`
|
|
1327
|
+
},
|
|
1328
|
+
get label() {
|
|
1329
|
+
return \`Session \${this.id} (user \${this.options.userId})\`
|
|
1330
|
+
},
|
|
1331
|
+
bump() {
|
|
1332
|
+
const visits = (this.state.get('visits') ?? 0) + 1
|
|
1333
|
+
this.setState({ visits })
|
|
1334
|
+
this.emit('visited', visits)
|
|
1335
|
+
return visits
|
|
1336
|
+
},
|
|
1337
|
+
})
|
|
1338
|
+
|
|
1339
|
+
console.log(session.greet())
|
|
1340
|
+
console.log(session.label)
|
|
1341
|
+
console.log('visits:', session.bump())
|
|
1342
|
+
console.log('visits:', session.bump())
|
|
1343
|
+
\`\`\`
|
|
1344
|
+
|
|
1345
|
+
Extensions are chained via prototype delegation — each layer can see everything below it.
|
|
1346
|
+
|
|
1347
|
+
## Exposing Methods as AI Tools
|
|
1348
|
+
|
|
1349
|
+
Use \`.expose(methodName, zodSchema)\` to register methods as tools. \`.toTools()\` returns \`{ schemas, handlers }\` compatible with \`assistant.addTools()\`.
|
|
1350
|
+
|
|
1351
|
+
\`\`\`ts
|
|
1352
|
+
const search = container.entity('search', {})
|
|
1353
|
+
.extend({
|
|
1354
|
+
async lookup({ query }: { query: string }) {
|
|
1355
|
+
return \`Results for: \${query}\`
|
|
1356
|
+
},
|
|
1357
|
+
async summarize({ text, maxWords }: { text: string; maxWords: number }) {
|
|
1358
|
+
return text.split(' ').slice(0, maxWords).join(' ')
|
|
1359
|
+
},
|
|
1360
|
+
})
|
|
1361
|
+
.expose('lookup', z.object({
|
|
1362
|
+
query: z.string().describe('The search query'),
|
|
1363
|
+
}))
|
|
1364
|
+
.expose('summarize', z.object({
|
|
1365
|
+
text: z.string().describe('Text to summarize'),
|
|
1366
|
+
maxWords: z.number().describe('Maximum words in summary'),
|
|
1367
|
+
}))
|
|
1368
|
+
|
|
1369
|
+
const { schemas, handlers } = search.toTools()
|
|
1370
|
+
console.log('registered tools:', Object.keys(schemas))
|
|
1371
|
+
|
|
1372
|
+
// Pass directly to an assistant
|
|
1373
|
+
// assistant.addTools(search)
|
|
1374
|
+
\`\`\`
|
|
1375
|
+
|
|
1376
|
+
\`.expose()\` is chainable and returns \`this\`, so you can stack as many as you need.
|
|
1377
|
+
|
|
1378
|
+
## Summary
|
|
1379
|
+
|
|
1380
|
+
Entities give you observable state, a typed event bus, and prototype-safe method extension — all as a plain object with no class overhead. The \`.expose()\` / \`.toTools()\` interface makes it straightforward to surface entity methods as AI tools.
|
|
1256
1381
|
`,
|
|
1257
1382
|
"assistant-with-process-manager.md": `---
|
|
1258
1383
|
title: "Assistant with ProcessManager Tools"
|
package/src/bus.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export type EventMap = Record<string, any[]>;
|
|
2
2
|
|
|
3
3
|
type Listener<Args extends any[] = any[]> = (...args: Args) => void;
|
|
4
|
+
type WildcardListener = (event: string, ...args: any[]) => void;
|
|
4
5
|
|
|
5
6
|
export interface EventStats {
|
|
6
7
|
event: string;
|
|
@@ -12,10 +13,12 @@ export interface EventStats {
|
|
|
12
13
|
|
|
13
14
|
export class Bus<T extends EventMap = EventMap> {
|
|
14
15
|
private events: Map<string, Listener[]>;
|
|
16
|
+
private wildcardListeners: WildcardListener[];
|
|
15
17
|
private stats: Map<string, { fireCount: number; lastFiredAt: number | null; timestamps: number[] }>;
|
|
16
18
|
|
|
17
19
|
constructor() {
|
|
18
20
|
this.events = new Map();
|
|
21
|
+
this.wildcardListeners = [];
|
|
19
22
|
this.stats = new Map();
|
|
20
23
|
}
|
|
21
24
|
|
|
@@ -64,12 +67,19 @@ export class Bus<T extends EventMap = EventMap> {
|
|
|
64
67
|
emit<E extends string & keyof T>(event: E, ...args: T[E]): void {
|
|
65
68
|
this.recordEmit(event);
|
|
66
69
|
const listeners = this.events.get(event);
|
|
67
|
-
if (
|
|
68
|
-
|
|
69
|
-
|
|
70
|
+
if (listeners) {
|
|
71
|
+
listeners.forEach(listener => listener(...args));
|
|
72
|
+
}
|
|
73
|
+
this.wildcardListeners.forEach(listener => listener(event, ...args));
|
|
70
74
|
}
|
|
71
75
|
|
|
72
|
-
on
|
|
76
|
+
on(event: '*', listener: WildcardListener): void
|
|
77
|
+
on<E extends string & keyof T>(event: E, listener: (...args: T[E]) => void): void
|
|
78
|
+
on<E extends string & keyof T>(event: E | '*', listener: any): void {
|
|
79
|
+
if (event === '*') {
|
|
80
|
+
this.wildcardListeners.push(listener);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
73
83
|
const listeners = this.events.get(event) || [];
|
|
74
84
|
listeners.push(listener as Listener);
|
|
75
85
|
this.events.set(event, listeners);
|
|
@@ -83,7 +93,19 @@ export class Bus<T extends EventMap = EventMap> {
|
|
|
83
93
|
this.on(event, onceListener as any);
|
|
84
94
|
}
|
|
85
95
|
|
|
86
|
-
off
|
|
96
|
+
off(event: '*', listener?: WildcardListener): void
|
|
97
|
+
off<E extends string & keyof T>(event: E, listener?: (...args: T[E]) => void): void
|
|
98
|
+
off<E extends string & keyof T>(event: E | '*', listener?: any): void {
|
|
99
|
+
if (event === '*') {
|
|
100
|
+
if (!listener) {
|
|
101
|
+
this.wildcardListeners = [];
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const index = this.wildcardListeners.indexOf(listener);
|
|
105
|
+
if (index !== -1) this.wildcardListeners.splice(index, 1);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
87
109
|
const listeners = this.events.get(event);
|
|
88
110
|
if (!listeners) return;
|
|
89
111
|
|
package/src/cli/build-info.ts
CHANGED
package/src/client.ts
CHANGED
|
@@ -46,7 +46,7 @@ export class Client<
|
|
|
46
46
|
static override eventsSchema = ClientEventsSchema
|
|
47
47
|
|
|
48
48
|
/** Self-register a Client subclass from a static initialization block. */
|
|
49
|
-
static register: (SubClass:
|
|
49
|
+
static register: (SubClass: abstract new (options: any, context: any) => Client, id?: string) => abstract new (options: any, context: any) => Client
|
|
50
50
|
|
|
51
51
|
static attach(container: Container & ClientsInterface): any {
|
|
52
52
|
Object.assign(container, {
|
|
@@ -141,7 +141,7 @@ export const helperCache = new Map();
|
|
|
141
141
|
* ```
|
|
142
142
|
*/
|
|
143
143
|
Client.register = function registerClient(
|
|
144
|
-
SubClass:
|
|
144
|
+
SubClass: abstract new (options: any, context: any) => Client,
|
|
145
145
|
id?: string,
|
|
146
146
|
) {
|
|
147
147
|
const registryId = id ?? SubClass.name[0]!.toLowerCase() + SubClass.name.slice(1)
|
|
@@ -3,6 +3,7 @@ import { ClientStateSchema, ClientOptionsSchema, ClientEventsSchema } from '@soe
|
|
|
3
3
|
import { Client } from "@soederpop/luca/client";
|
|
4
4
|
import { RestClient } from "../rest";
|
|
5
5
|
import type { ContainerContext } from "@soederpop/luca/container";
|
|
6
|
+
import type { NodeContainer } from "../../node/container.js";
|
|
6
7
|
import type { AxiosRequestConfig } from 'axios'
|
|
7
8
|
|
|
8
9
|
declare module "@soederpop/luca/client" {
|
|
@@ -92,6 +93,10 @@ export class ElevenLabsClient extends RestClient<ElevenLabsClientState, ElevenLa
|
|
|
92
93
|
super(options, context)
|
|
93
94
|
}
|
|
94
95
|
|
|
96
|
+
override get container(): NodeContainer {
|
|
97
|
+
return super.container as unknown as NodeContainer
|
|
98
|
+
}
|
|
99
|
+
|
|
95
100
|
/** The resolved API key from options or environment. */
|
|
96
101
|
get apiKey(): string {
|
|
97
102
|
return this.options.apiKey || process.env.ELEVENLABS_API_KEY || ''
|