@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
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Entity"
|
|
3
|
+
tags: [entity, state, events, tools, core]
|
|
4
|
+
lastTested: null
|
|
5
|
+
lastTestPassed: null
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# entity
|
|
9
|
+
|
|
10
|
+
Lightweight, composable objects with observable state, a typed event bus, and an optional tool interface.
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
|
|
14
|
+
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()`.
|
|
15
|
+
|
|
16
|
+
## Basic Entity with Observable State
|
|
17
|
+
|
|
18
|
+
Create an entity and read/write state through the observable `state` property.
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
const counter = container.entity<{ count: number }>('counter')
|
|
22
|
+
counter.setState({ count: 0 })
|
|
23
|
+
|
|
24
|
+
counter.state.observe((next) => {
|
|
25
|
+
console.log('count changed to', next.count)
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
counter.setState(s => ({ count: s.count + 1 }))
|
|
29
|
+
counter.setState(s => ({ count: s.count + 1 }))
|
|
30
|
+
console.log('final count:', counter.state.get('count'))
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`setState` accepts either a partial object or a function that receives the current state. Observers fire synchronously after each change.
|
|
34
|
+
|
|
35
|
+
## Typed Event Bus
|
|
36
|
+
|
|
37
|
+
Every entity has a built-in event bus. Declare the event map as the third type parameter.
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
type TimerEvents = {
|
|
41
|
+
tick: [elapsed: number]
|
|
42
|
+
done: []
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const timer = container.entity<{}, {}, TimerEvents>('timer')
|
|
46
|
+
|
|
47
|
+
timer.on('tick', (elapsed) => {
|
|
48
|
+
console.log('tick at', elapsed, 'ms')
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
timer.once('done', () => {
|
|
52
|
+
console.log('timer finished')
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
timer.emit('tick', 100)
|
|
56
|
+
timer.emit('tick', 200)
|
|
57
|
+
timer.emit('done')
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
`once` auto-detaches after the first fire. `waitFor` returns a promise that resolves on the next emit of that event.
|
|
61
|
+
|
|
62
|
+
## Extending with Methods
|
|
63
|
+
|
|
64
|
+
Use `.extend()` to graft methods and getters onto an entity. All base properties — `state`, `options`, `container`, and the event methods — are available via `this`.
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
const session = container.entity('session', { userId: '42' })
|
|
68
|
+
.extend({
|
|
69
|
+
greet() {
|
|
70
|
+
return `Hello user ${this.options.userId}`
|
|
71
|
+
},
|
|
72
|
+
get label() {
|
|
73
|
+
return `Session ${this.id} (user ${this.options.userId})`
|
|
74
|
+
},
|
|
75
|
+
bump() {
|
|
76
|
+
const visits = (this.state.get('visits') ?? 0) + 1
|
|
77
|
+
this.setState({ visits })
|
|
78
|
+
this.emit('visited', visits)
|
|
79
|
+
return visits
|
|
80
|
+
},
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
console.log(session.greet())
|
|
84
|
+
console.log(session.label)
|
|
85
|
+
console.log('visits:', session.bump())
|
|
86
|
+
console.log('visits:', session.bump())
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Extensions are chained via prototype delegation — each layer can see everything below it.
|
|
90
|
+
|
|
91
|
+
## Exposing Methods as AI Tools
|
|
92
|
+
|
|
93
|
+
Use `.expose(methodName, zodSchema)` to register methods as tools. `.toTools()` returns `{ schemas, handlers }` compatible with `assistant.addTools()`.
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
const search = container.entity('search', {})
|
|
97
|
+
.extend({
|
|
98
|
+
async lookup({ query }: { query: string }) {
|
|
99
|
+
return `Results for: ${query}`
|
|
100
|
+
},
|
|
101
|
+
async summarize({ text, maxWords }: { text: string; maxWords: number }) {
|
|
102
|
+
return text.split(' ').slice(0, maxWords).join(' ')
|
|
103
|
+
},
|
|
104
|
+
})
|
|
105
|
+
.expose('lookup', z.object({
|
|
106
|
+
query: z.string().describe('The search query'),
|
|
107
|
+
}))
|
|
108
|
+
.expose('summarize', z.object({
|
|
109
|
+
text: z.string().describe('Text to summarize'),
|
|
110
|
+
maxWords: z.number().describe('Maximum words in summary'),
|
|
111
|
+
}))
|
|
112
|
+
|
|
113
|
+
const { schemas, handlers } = search.toTools()
|
|
114
|
+
console.log('registered tools:', Object.keys(schemas))
|
|
115
|
+
|
|
116
|
+
// Pass directly to an assistant
|
|
117
|
+
// assistant.addTools(search)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
`.expose()` is chainable and returns `this`, so you can stack as many as you need.
|
|
121
|
+
|
|
122
|
+
## Summary
|
|
123
|
+
|
|
124
|
+
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.
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Assistant Factory Pattern — Eliminate Wrapper Duplication
|
|
3
|
+
status: idea
|
|
4
|
+
tags: [agi, assistant, refactor, lucaCoder, autonomousAssistant]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Assistant Factory Pattern
|
|
8
|
+
|
|
9
|
+
## Problem
|
|
10
|
+
|
|
11
|
+
`LucaCoder` and `AutonomousAssistant` both duplicate the same pattern: create an inner `Assistant`, stack tool bundles, wire a permission interceptor, forward events. The permission system, approval flow, and event forwarding are copy-pasted between them. `LucaCoder` is just `AutonomousAssistant` + coding opinions (bash tool, skill loading, project instructions).
|
|
12
|
+
|
|
13
|
+
Both features **wrap** an assistant rather than **composing** one. This means every method on `Assistant` (ask, tools, messages, conversation) has to be proxied through the wrapper.
|
|
14
|
+
|
|
15
|
+
## Proposal
|
|
16
|
+
|
|
17
|
+
### 1. Extract the permission layer into a `use()`-able plugin
|
|
18
|
+
|
|
19
|
+
The permission system (allow/ask/deny per tool, pending approvals, approval history) is just a `beforeToolCall` interceptor. It doesn't need to be a feature — it's a plugin function.
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import type { Assistant } from './assistant'
|
|
23
|
+
|
|
24
|
+
interface PermissionConfig {
|
|
25
|
+
permissions?: Record<string, 'allow' | 'ask' | 'deny'>
|
|
26
|
+
defaultPermission?: 'allow' | 'ask' | 'deny'
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function withPermissions(config: PermissionConfig = {}) {
|
|
30
|
+
return (assistant: Assistant) => {
|
|
31
|
+
const perms = config.permissions || {}
|
|
32
|
+
const defaultPerm = config.defaultPermission || 'ask'
|
|
33
|
+
const pendingResolvers = new Map<string, (d: 'approve' | 'deny') => void>()
|
|
34
|
+
|
|
35
|
+
assistant.intercept('beforeToolCall', async (ctx, next) => {
|
|
36
|
+
const policy = perms[ctx.name] || defaultPerm
|
|
37
|
+
|
|
38
|
+
if (policy === 'deny') {
|
|
39
|
+
ctx.skip = true
|
|
40
|
+
ctx.result = JSON.stringify({ blocked: true, tool: ctx.name, reason: 'Permission denied.' })
|
|
41
|
+
assistant.emit('toolBlocked', ctx.name, 'deny policy')
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (policy === 'allow') {
|
|
46
|
+
await next()
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// 'ask' — emit event and block until resolved
|
|
51
|
+
const id = assistant.container.utils.uuid()
|
|
52
|
+
const decision = await new Promise<'approve' | 'deny'>((resolve) => {
|
|
53
|
+
pendingResolvers.set(id, resolve)
|
|
54
|
+
assistant.emit('permissionRequest', { id, toolName: ctx.name, args: ctx.args })
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
pendingResolvers.delete(id)
|
|
58
|
+
|
|
59
|
+
if (decision === 'approve') {
|
|
60
|
+
await next()
|
|
61
|
+
} else {
|
|
62
|
+
ctx.skip = true
|
|
63
|
+
ctx.result = JSON.stringify({ blocked: true, tool: ctx.name, reason: 'User denied.' })
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
// Expose approve/deny on the assistant instance
|
|
68
|
+
;(assistant as any).approve = (id: string) => pendingResolvers.get(id)?.('approve')
|
|
69
|
+
;(assistant as any).deny = (id: string) => pendingResolvers.get(id)?.('deny')
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 2. LucaCoder becomes an assistant factory, not a wrapper
|
|
75
|
+
|
|
76
|
+
Instead of owning an inner assistant and proxying everything, `LucaCoder` creates and returns a configured `Assistant`:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
export class LucaCoder extends Feature {
|
|
80
|
+
createAssistant(overrides?: Partial<AssistantOptions>): Assistant {
|
|
81
|
+
const assistant = this.container.feature('assistant', {
|
|
82
|
+
systemPrompt: this.buildSystemPrompt(),
|
|
83
|
+
...overrides,
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
// This is the runtime equivalent of hooks.ts started()
|
|
87
|
+
assistant.use(this.container.feature('codingTools'))
|
|
88
|
+
|
|
89
|
+
const fileTools = this.container.feature('fileTools')
|
|
90
|
+
assistant.use(fileTools.toTools({ only: ['editFile', 'writeFile', 'deleteFile'] }))
|
|
91
|
+
fileTools.setupToolsConsumer(assistant)
|
|
92
|
+
|
|
93
|
+
assistant.use(this.container.feature('processManager'))
|
|
94
|
+
assistant.use(this.container.feature('skillsLibrary'))
|
|
95
|
+
|
|
96
|
+
// Permission layer as a plugin
|
|
97
|
+
if (this.options.permissions || this.options.defaultPermission) {
|
|
98
|
+
assistant.use(withPermissions({
|
|
99
|
+
permissions: this.options.permissions,
|
|
100
|
+
defaultPermission: this.options.defaultPermission,
|
|
101
|
+
}))
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return assistant
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 3. Usage
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
// Runtime — no disk files, works in compiled binary
|
|
113
|
+
const coder = container.feature('lucaCoder')
|
|
114
|
+
const assistant = await coder.createAssistant()
|
|
115
|
+
await assistant.ask('refactor the auth module')
|
|
116
|
+
|
|
117
|
+
// With permission gating
|
|
118
|
+
const coder = container.feature('lucaCoder', {
|
|
119
|
+
permissions: { editFile: 'ask', writeFile: 'ask', deleteFile: 'ask' },
|
|
120
|
+
defaultPermission: 'allow',
|
|
121
|
+
})
|
|
122
|
+
const assistant = await coder.createAssistant()
|
|
123
|
+
assistant.on('permissionRequest', ({ id }) => assistant.approve(id))
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 4. AutonomousAssistant collapses
|
|
127
|
+
|
|
128
|
+
`AutonomousAssistant` becomes either:
|
|
129
|
+
- Deleted entirely (replaced by `withPermissions` plugin on any assistant)
|
|
130
|
+
- Or a thin factory like LucaCoder but with no coding opinions — just `createAssistant()` + permissions
|
|
131
|
+
|
|
132
|
+
## What This Achieves
|
|
133
|
+
|
|
134
|
+
- **No duplication** — permission logic lives in one place (the plugin)
|
|
135
|
+
- **No proxying** — you get back a real `Assistant`, not a wrapper that forwards `.ask()`, `.tools`, `.messages`, `.conversation`
|
|
136
|
+
- **Binary-compatible** — the factory pattern doesn't need disk files, so it works in the compiled `luca` binary
|
|
137
|
+
- **Composable** — `assistants/codingAssistant/hooks.ts` and `LucaCoder.createAssistant()` produce the exact same result through the same mechanism (`assistant.use()`)
|
|
138
|
+
- **The folder-based assistant becomes the reference implementation** of what the factory does programmatically
|
|
139
|
+
|
|
140
|
+
## Relationship to assistants/codingAssistant
|
|
141
|
+
|
|
142
|
+
The disk-based `assistants/codingAssistant/` (CORE.md + hooks.ts + tools.ts) is the "editable" version. `LucaCoder.createAssistant()` is the "compiled" version. Same tools, same prompt, same behavior — one loads from files, the other is baked in code.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soederpop/luca",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"website": "https://luca.soederpop.com",
|
|
5
5
|
"description": "lightweight universal conversational architecture AKA Le Ultimate Component Architecture AKA Last Universal Common Ancestor, part AI part Human",
|
|
6
6
|
"author": "jon soeder aka the people's champ <jon@soederpop.com>",
|
|
@@ -19,26 +19,77 @@
|
|
|
19
19
|
"coding assistant"
|
|
20
20
|
],
|
|
21
21
|
"main": "./src/node.ts",
|
|
22
|
-
"types": "./
|
|
22
|
+
"types": "./dist/node.d.ts",
|
|
23
23
|
"browser": "./src/browser.ts",
|
|
24
24
|
"exports": {
|
|
25
|
-
".":
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"./
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"./
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"./
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"./
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/node.d.ts",
|
|
27
|
+
"default": "./src/node.ts"
|
|
28
|
+
},
|
|
29
|
+
"./node": {
|
|
30
|
+
"types": "./dist/node.d.ts",
|
|
31
|
+
"default": "./src/node.ts"
|
|
32
|
+
},
|
|
33
|
+
"./node/*": {
|
|
34
|
+
"types": "./dist/node/*.d.ts",
|
|
35
|
+
"default": "./src/node/*"
|
|
36
|
+
},
|
|
37
|
+
"./web": {
|
|
38
|
+
"types": "./dist/browser.d.ts",
|
|
39
|
+
"default": "./src/browser.ts"
|
|
40
|
+
},
|
|
41
|
+
"./web/*": {
|
|
42
|
+
"types": "./dist/web/*.d.ts",
|
|
43
|
+
"default": "./src/web/*"
|
|
44
|
+
},
|
|
45
|
+
"./agi": {
|
|
46
|
+
"types": "./dist/agi/index.d.ts",
|
|
47
|
+
"default": "./src/agi/index.ts"
|
|
48
|
+
},
|
|
49
|
+
"./agi/*": {
|
|
50
|
+
"types": "./dist/agi/*.d.ts",
|
|
51
|
+
"default": "./src/agi/*"
|
|
52
|
+
},
|
|
53
|
+
"./schemas": {
|
|
54
|
+
"types": "./dist/schemas/base.d.ts",
|
|
55
|
+
"default": "./src/schemas/base.ts"
|
|
56
|
+
},
|
|
57
|
+
"./schemas/*": {
|
|
58
|
+
"types": "./dist/schemas/*.d.ts",
|
|
59
|
+
"default": "./src/schemas/*"
|
|
60
|
+
},
|
|
61
|
+
"./container": {
|
|
62
|
+
"types": "./dist/container.d.ts",
|
|
63
|
+
"default": "./src/container.ts"
|
|
64
|
+
},
|
|
65
|
+
"./client": {
|
|
66
|
+
"types": "./dist/client.d.ts",
|
|
67
|
+
"default": "./src/client.ts"
|
|
68
|
+
},
|
|
69
|
+
"./clients/*": {
|
|
70
|
+
"types": "./dist/clients/*.d.ts",
|
|
71
|
+
"default": "./src/clients/*"
|
|
72
|
+
},
|
|
73
|
+
"./server": {
|
|
74
|
+
"types": "./dist/server.d.ts",
|
|
75
|
+
"default": "./src/server.ts"
|
|
76
|
+
},
|
|
77
|
+
"./servers/*": {
|
|
78
|
+
"types": "./dist/servers/*.d.ts",
|
|
79
|
+
"default": "./src/servers/*"
|
|
80
|
+
},
|
|
81
|
+
"./feature": {
|
|
82
|
+
"types": "./dist/feature.d.ts",
|
|
83
|
+
"default": "./src/feature.ts"
|
|
84
|
+
},
|
|
85
|
+
"./react": {
|
|
86
|
+
"types": "./dist/react/index.d.ts",
|
|
87
|
+
"default": "./src/react/index.ts"
|
|
88
|
+
},
|
|
89
|
+
"./introspection": {
|
|
90
|
+
"types": "./dist/introspection/index.d.ts",
|
|
91
|
+
"default": "./src/introspection/index.ts"
|
|
92
|
+
}
|
|
42
93
|
},
|
|
43
94
|
"bin": {
|
|
44
95
|
"luca": "./src/cli/cli.ts"
|
|
@@ -51,13 +102,15 @@
|
|
|
51
102
|
"build:web": "bun run scripts/build-web.ts",
|
|
52
103
|
"build:introspection": "bun run src/cli/cli.ts introspect",
|
|
53
104
|
"compile": "bun run build:introspection && bun run build:scaffolds && bun run build:bootstrap && bun run build:python-bridge && bash scripts/stamp-build.sh && bun build ./src/cli/cli.ts --compile --outfile dist/luca --external node-llama-cpp",
|
|
105
|
+
"build:types": "tsc -p tsconfig.build.json",
|
|
54
106
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
55
107
|
"build:scaffolds": "bun run src/cli/cli.ts build-scaffolds",
|
|
56
108
|
"build:bootstrap": "bun run src/cli/cli.ts build-bootstrap",
|
|
57
109
|
"build:python-bridge": "bun run src/cli/cli.ts build-python-bridge",
|
|
58
110
|
"test": "bun test test/*.test.ts",
|
|
59
111
|
"update-all-docs": "bun run test && bun run build:introspection && bun run src/cli/cli.ts generate-api-docs && bun run build:scaffolds && bun run build:bootstrap && bun run build:python-bridge",
|
|
60
|
-
"
|
|
112
|
+
"setup": "git update-index --skip-worktree src/introspection/generated.node.ts src/introspection/generated.web.ts src/introspection/generated.agi.ts src/scaffolds/generated.ts src/bootstrap/generated.ts src/python/generated.ts",
|
|
113
|
+
"precommit": "bun run typecheck && bun run update-all-docs && git add docs/apis/ && bun compile",
|
|
61
114
|
"test:integration": "bun test ./test-integration/"
|
|
62
115
|
},
|
|
63
116
|
"devDependencies": {
|
|
@@ -97,7 +150,7 @@
|
|
|
97
150
|
"@supabase/supabase-js": "^2.95.3",
|
|
98
151
|
"@types/marked": "^6.0.0",
|
|
99
152
|
"@types/marked-terminal": "^6.1.1",
|
|
100
|
-
"axios": "
|
|
153
|
+
"axios": "1.13.6",
|
|
101
154
|
"cacache": "^17.0.7",
|
|
102
155
|
"chalk": "^5.2.0",
|
|
103
156
|
"child-process-promise": "^2.2.1",
|
|
@@ -3,6 +3,7 @@ import { type NodeFeatures, NodeContainer } from '../node/container'
|
|
|
3
3
|
import '@/introspection/generated.agi.js'
|
|
4
4
|
import { OpenAIClient } from '../clients/openai'
|
|
5
5
|
import { ElevenLabsClient } from '../clients/elevenlabs'
|
|
6
|
+
import { VoiceBoxClient } from '../clients/voicebox'
|
|
6
7
|
import { ClaudeCode } from './features/claude-code'
|
|
7
8
|
import { OpenAICodex } from './features/openai-codex'
|
|
8
9
|
import { Conversation } from './features/conversation'
|
|
@@ -16,6 +17,8 @@ import { SemanticSearch } from '@soederpop/luca/node/features/semantic-search'
|
|
|
16
17
|
import { ContentDb } from '@soederpop/luca/node/features/content-db'
|
|
17
18
|
import { FileTools } from './features/file-tools'
|
|
18
19
|
import { LucaCoder } from './features/luca-coder'
|
|
20
|
+
import { Memory } from './features/agent-memory'
|
|
21
|
+
import { CodingTools } from './features/coding-tools'
|
|
19
22
|
|
|
20
23
|
import type { ConversationTool } from './features/conversation'
|
|
21
24
|
import type { ZodType } from 'zod'
|
|
@@ -32,6 +35,8 @@ export {
|
|
|
32
35
|
BrowserUse,
|
|
33
36
|
FileTools,
|
|
34
37
|
LucaCoder,
|
|
38
|
+
Memory,
|
|
39
|
+
CodingTools,
|
|
35
40
|
SemanticSearch,
|
|
36
41
|
ContentDb,
|
|
37
42
|
NodeContainer,
|
|
@@ -58,6 +63,8 @@ export interface AGIFeatures extends NodeFeatures {
|
|
|
58
63
|
browserUse: typeof BrowserUse
|
|
59
64
|
fileTools: typeof FileTools
|
|
60
65
|
lucaCoder: typeof LucaCoder
|
|
66
|
+
memory: typeof Memory
|
|
67
|
+
codingTools: typeof CodingTools
|
|
61
68
|
}
|
|
62
69
|
|
|
63
70
|
export interface ConversationFactoryOptions {
|
|
@@ -122,6 +129,7 @@ export class AGIContainer<
|
|
|
122
129
|
const container = new AGIContainer()
|
|
123
130
|
.use(OpenAIClient)
|
|
124
131
|
.use(ElevenLabsClient)
|
|
132
|
+
.use(VoiceBoxClient)
|
|
125
133
|
.use(ClaudeCode)
|
|
126
134
|
.use(OpenAICodex)
|
|
127
135
|
.use(Conversation)
|
|
@@ -133,6 +141,8 @@ const container = new AGIContainer()
|
|
|
133
141
|
.use(BrowserUse)
|
|
134
142
|
.use(FileTools)
|
|
135
143
|
.use(LucaCoder)
|
|
144
|
+
.use(Memory)
|
|
145
|
+
.use(CodingTools)
|
|
136
146
|
.use(SemanticSearch)
|
|
137
147
|
|
|
138
148
|
container.docs = container.feature('contentDb', {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AGIFeatures, AGIContainer } from './container.server.js'
|
|
2
|
+
import type { FeatureOptions, FeatureState } from '../feature.ts'
|
|
3
|
+
import { features, Feature as NodeFeature } from '../node/feature.ts'
|
|
4
|
+
|
|
5
|
+
export { features }
|
|
6
|
+
|
|
7
|
+
export type { FeatureState, FeatureOptions }
|
|
8
|
+
|
|
9
|
+
export class Feature<T extends FeatureState = FeatureState, K extends FeatureOptions = FeatureOptions> extends NodeFeature<T, K> {
|
|
10
|
+
override get container(): AGIContainer<AGIFeatures> {
|
|
11
|
+
return super.container as AGIContainer<AGIFeatures>
|
|
12
|
+
}
|
|
13
|
+
}
|