@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
|
@@ -5,6 +5,7 @@ import { z } from 'zod'
|
|
|
5
5
|
import { FeatureStateSchema, FeatureOptionsSchema, FeatureEventsSchema } from '../../schemas/base.js'
|
|
6
6
|
import { realpathSync } from 'node:fs'
|
|
7
7
|
import type { GrepOptions } from './grep.js'
|
|
8
|
+
import type { Helper } from '../../helper.js'
|
|
8
9
|
|
|
9
10
|
export const ContentDbStateSchema = FeatureStateSchema.extend({
|
|
10
11
|
loaded: z.boolean().default(false).describe('Whether the content collection has been loaded and parsed'),
|
|
@@ -46,70 +47,96 @@ export class ContentDb extends Feature<ContentDbState, ContentDbOptions> {
|
|
|
46
47
|
static { Feature.register(this, 'contentDb') }
|
|
47
48
|
|
|
48
49
|
/** Tools that any assistant can use to progressively explore this collection. */
|
|
49
|
-
static tools: Record<string, { schema: z.ZodType; handler?: Function }> = {
|
|
50
|
+
static override tools: Record<string, { schema: z.ZodType; handler?: Function }> = {
|
|
50
51
|
getCollectionOverview: {
|
|
51
52
|
schema: z.object({}).describe(
|
|
52
|
-
'Get a high-level overview of the document collection: models,
|
|
53
|
+
'Get a high-level overview of the document collection: what models exist, how many documents each has, the directory tree, and search index status. Call this FIRST to understand the collection before exploring individual documents.'
|
|
53
54
|
),
|
|
54
55
|
},
|
|
55
56
|
listDocuments: {
|
|
56
57
|
schema: z.object({
|
|
57
|
-
model: z.string().optional().describe('Filter to documents
|
|
58
|
-
glob: z.string().optional().describe('Glob pattern to filter document path
|
|
58
|
+
model: z.string().optional().describe('Filter to documents of this model type (e.g. "Plan", "Task"). Get model names from getCollectionOverview.'),
|
|
59
|
+
glob: z.string().optional().describe('Glob pattern to filter by document path (e.g. "guides/*", "apis/**/*.md")'),
|
|
59
60
|
}).describe(
|
|
60
|
-
'List
|
|
61
|
+
'List document IDs in the collection. Use this to browse what\'s available before reading. Filter by model or glob to narrow results.'
|
|
61
62
|
),
|
|
62
63
|
},
|
|
63
64
|
readDocument: {
|
|
64
65
|
schema: z.object({
|
|
65
|
-
id: z.string().describe('The document path ID
|
|
66
|
-
include: z.array(z.string()).optional().describe('Only return these
|
|
67
|
-
exclude: z.array(z.string()).optional().describe('
|
|
68
|
-
meta: z.boolean().optional().describe('Include YAML frontmatter in the output'),
|
|
66
|
+
id: z.string().describe('The document path ID (e.g. "guides/intro", "apis/auth"). Get valid IDs from listDocuments.'),
|
|
67
|
+
include: z.array(z.string()).optional().describe('Only return sections with these headings. Use to read specific parts of long documents without loading everything.'),
|
|
68
|
+
exclude: z.array(z.string()).optional().describe('Skip sections with these headings. Use to filter out irrelevant parts.'),
|
|
69
|
+
meta: z.boolean().optional().describe('Include the YAML frontmatter (title, status, tags, etc.) in the output. Useful for understanding document metadata.'),
|
|
69
70
|
}).describe(
|
|
70
|
-
'Read a
|
|
71
|
+
'Read a document by its path ID. Use include/exclude to request only the sections you need — don\'t load an entire document when you only need one section.'
|
|
71
72
|
),
|
|
72
73
|
},
|
|
73
74
|
readMultipleDocuments: {
|
|
74
75
|
schema: z.object({
|
|
75
|
-
ids: z.array(z.string()).describe('Array of document path IDs to read'),
|
|
76
|
-
include: z.array(z.string()).optional().describe('Only return these
|
|
77
|
-
exclude: z.array(z.string()).optional().describe('
|
|
78
|
-
meta: z.boolean().optional().describe('Include YAML frontmatter
|
|
76
|
+
ids: z.array(z.string()).describe('Array of document path IDs to read. Get valid IDs from listDocuments.'),
|
|
77
|
+
include: z.array(z.string()).optional().describe('Only return sections with these headings from each document.'),
|
|
78
|
+
exclude: z.array(z.string()).optional().describe('Skip sections with these headings from each document.'),
|
|
79
|
+
meta: z.boolean().optional().describe('Include YAML frontmatter for each document.'),
|
|
79
80
|
}).describe(
|
|
80
|
-
'Read multiple documents
|
|
81
|
+
'Read multiple documents in one call. More efficient than calling readDocument in a loop. Returns documents concatenated with dividers.'
|
|
81
82
|
),
|
|
82
83
|
},
|
|
83
84
|
queryDocuments: {
|
|
84
85
|
schema: z.object({
|
|
85
|
-
model: z.string().describe('The model name to query (e.g. "Plan", "Task")'),
|
|
86
|
-
where: z.string().optional().describe('
|
|
87
|
-
sort: z.string().optional().describe('Sort
|
|
88
|
-
limit: z.number().optional().describe('Maximum number of results
|
|
89
|
-
offset: z.number().optional().describe('
|
|
90
|
-
select: z.array(z.string()).optional().describe('
|
|
86
|
+
model: z.string().describe('The model name to query (e.g. "Plan", "Task", "Guide"). Must match a model defined in the collection — check getCollectionOverview.'),
|
|
87
|
+
where: z.string().optional().describe('MongoDB-style filter as a JSON string. Dot notation for nested fields. Examples: \'{"meta.status": "approved"}\', \'{"meta.priority": {"$gt": 3}}\', \'{"meta.tags": {"$in": ["urgent"]}}\''),
|
|
88
|
+
sort: z.string().optional().describe('Sort as a JSON string. Example: \'{"meta.priority": "desc"}\', \'{"meta.createdAt": "asc"}\''),
|
|
89
|
+
limit: z.number().optional().describe('Maximum number of results. Default: all matching documents.'),
|
|
90
|
+
offset: z.number().optional().describe('Skip this many results (for pagination).'),
|
|
91
|
+
select: z.array(z.string()).optional().describe('Only include these fields in output (e.g. ["id", "title", "meta.status"]). Reduces noise when you only need specific metadata.'),
|
|
91
92
|
}).describe(
|
|
92
|
-
'Query documents by model with
|
|
93
|
+
'Query documents by model with filtering, sorting, and pagination. Use this when you need to find documents matching specific criteria (status, priority, tags, dates) rather than browsing by name.'
|
|
93
94
|
),
|
|
94
95
|
},
|
|
95
96
|
searchContent: {
|
|
96
97
|
schema: z.object({
|
|
97
|
-
pattern: z.string().describe('Regex pattern to search for across all
|
|
98
|
-
caseSensitive: z.boolean().optional().describe('
|
|
98
|
+
pattern: z.string().describe('Regex pattern to search for across all document content. Examples: "TODO|FIXME", "authentication", "def.*handler"'),
|
|
99
|
+
caseSensitive: z.boolean().optional().describe('Case-sensitive search. Default: false (case insensitive).'),
|
|
99
100
|
}).describe(
|
|
100
|
-
'Text/regex search (grep) across all documents
|
|
101
|
+
'Text/regex search (grep) across all documents. Use for exact pattern matching, code references, or finding specific terms. Returns matching lines with file context. For natural language questions, use semanticSearch instead.'
|
|
101
102
|
),
|
|
102
103
|
},
|
|
103
104
|
semanticSearch: {
|
|
104
105
|
schema: z.object({
|
|
105
|
-
query: z.string().describe('
|
|
106
|
-
limit: z.number().optional().describe('Maximum
|
|
106
|
+
query: z.string().describe('A natural language question or topic description. Example: "how does the authentication flow work?" or "deployment configuration options"'),
|
|
107
|
+
limit: z.number().optional().describe('Maximum results to return. Default: 10.'),
|
|
107
108
|
}).describe(
|
|
108
|
-
'
|
|
109
|
+
'Search documents using natural language — combines keyword matching with semantic similarity. Best for questions and topic exploration. Falls back to text search if no vector index exists. For exact pattern matching, use searchContent instead.'
|
|
109
110
|
),
|
|
110
111
|
},
|
|
111
112
|
}
|
|
112
113
|
|
|
114
|
+
/**
|
|
115
|
+
* When an assistant uses contentDb, inject system prompt guidance
|
|
116
|
+
* about progressive document exploration.
|
|
117
|
+
*/
|
|
118
|
+
override setupToolsConsumer(consumer: Helper) {
|
|
119
|
+
if (typeof (consumer as any).addSystemPromptExtension === 'function') {
|
|
120
|
+
(consumer as any).addSystemPromptExtension('contentDb', [
|
|
121
|
+
'## Document Collection',
|
|
122
|
+
'',
|
|
123
|
+
'You have access to a structured document collection (markdown files with frontmatter, organized by model/type).',
|
|
124
|
+
'',
|
|
125
|
+
'**Progressive exploration — go broad to narrow:**',
|
|
126
|
+
'1. `getCollectionOverview` — start here. Shows models, document counts, and directory structure.',
|
|
127
|
+
'2. `listDocuments` — browse document IDs, optionally filtered by model or glob.',
|
|
128
|
+
'3. `readDocument` — read a specific document. Use `include`/`exclude` to skip irrelevant sections.',
|
|
129
|
+
'4. `queryDocuments` — filter documents by metadata (status, priority, tags, etc.) with MongoDB-style queries.',
|
|
130
|
+
'',
|
|
131
|
+
'**Searching:**',
|
|
132
|
+
'- `semanticSearch` — best for natural language questions ("how does authentication work?")',
|
|
133
|
+
'- `searchContent` — best for exact patterns, code references, or regex across all documents',
|
|
134
|
+
'',
|
|
135
|
+
'**Efficiency:** Don\'t read entire documents when you only need one section. Use `include` to request specific headings. Use `readMultipleDocuments` to batch reads instead of calling `readDocument` in a loop.',
|
|
136
|
+
].join('\n'))
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
113
140
|
override get initialState(): ContentDbState {
|
|
114
141
|
return {
|
|
115
142
|
...super.initialState,
|
|
@@ -460,7 +487,7 @@ export class ContentDb extends Feature<ContentDbState, ContentDbOptions> {
|
|
|
460
487
|
// Dynamically import and attach SemanticSearch if not already registered
|
|
461
488
|
const { SemanticSearch } = await import('./semantic-search.js')
|
|
462
489
|
if (!this.container.features.available.includes('semanticSearch')) {
|
|
463
|
-
SemanticSearch.attach(this.container as any)
|
|
490
|
+
;(SemanticSearch as any).attach(this.container as any)
|
|
464
491
|
}
|
|
465
492
|
|
|
466
493
|
// Store search index in ~/.luca/contentbase/{hash}/ keyed by the real (symlink-resolved) collection path
|
|
@@ -660,7 +687,7 @@ export class ContentDb extends Feature<ContentDbState, ContentDbOptions> {
|
|
|
660
687
|
get queries(): Record<string, ReturnType<typeof this.query>> {
|
|
661
688
|
const queryChains: [string, ReturnType<typeof this.query>][] = []
|
|
662
689
|
for (const modelName of this.modelNames) {
|
|
663
|
-
const queryChain = this.query(this.models[modelName])
|
|
690
|
+
const queryChain = this.query(this.models[modelName]!)
|
|
664
691
|
const pluralized = this.container.utils.stringUtils.pluralize(modelName).toLowerCase()
|
|
665
692
|
queryChains.push([modelName.toLowerCase(), queryChain])
|
|
666
693
|
queryChains.push([pluralized, queryChain])
|
|
@@ -147,7 +147,7 @@ export class FileManager<
|
|
|
147
147
|
|
|
148
148
|
/** Returns the list of directories currently being watched. */
|
|
149
149
|
get watchedPaths(): string[] {
|
|
150
|
-
return this.state.get("watchedPaths") || [];
|
|
150
|
+
return (this.state.get("watchedPaths") as string[] | undefined) || [];
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
/**
|
|
@@ -199,7 +199,7 @@ export class FileManager<
|
|
|
199
199
|
const { git } = this.container;
|
|
200
200
|
if (!git.isRepo) return null;
|
|
201
201
|
|
|
202
|
-
const gitDir = pathJoin(git.repoRoot
|
|
202
|
+
const gitDir = pathJoin(git.repoRoot!, '.git');
|
|
203
203
|
const head = readFileSync(pathJoin(gitDir, 'HEAD'), 'utf8').trim();
|
|
204
204
|
|
|
205
205
|
// Detached HEAD — already a sha
|
|
@@ -217,7 +217,7 @@ export class FileManager<
|
|
|
217
217
|
const ref = head.slice(5);
|
|
218
218
|
const packed = readFileSync(packedRefsPath, 'utf8');
|
|
219
219
|
const match = packed.match(new RegExp(`^([0-9a-f]{40}) ${ref}`, 'm'));
|
|
220
|
-
if (match) return match[1];
|
|
220
|
+
if (match) return match[1] ?? null;
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
return null;
|
|
@@ -334,8 +334,8 @@ export class FileManager<
|
|
|
334
334
|
if (cwdRelative) {
|
|
335
335
|
const prefix = cwdRelative + '/';
|
|
336
336
|
for (let i = 0; i < fileIds.length; i++) {
|
|
337
|
-
if (fileIds[i]
|
|
338
|
-
fileIds[i] = fileIds[i]
|
|
337
|
+
if (fileIds[i]!.startsWith(prefix)) {
|
|
338
|
+
fileIds[i] = fileIds[i]!.slice(prefix.length);
|
|
339
339
|
}
|
|
340
340
|
}
|
|
341
341
|
}
|
|
@@ -422,12 +422,12 @@ export class FileManager<
|
|
|
422
422
|
|
|
423
423
|
// If already watching, just add the new paths
|
|
424
424
|
if (this.isWatching && this.watcher) {
|
|
425
|
-
const currentPaths: string[] = this.state.get("watchedPaths") || [];
|
|
425
|
+
const currentPaths: string[] = (this.state.get("watchedPaths") as string[] | undefined) || [];
|
|
426
426
|
const newPaths = pathsToWatch.filter(p => !currentPaths.includes(p));
|
|
427
427
|
|
|
428
428
|
if (newPaths.length) {
|
|
429
429
|
this.watcher.add(newPaths);
|
|
430
|
-
this.state.set("watchedPaths", [...currentPaths, ...newPaths]);
|
|
430
|
+
this.state.set("watchedPaths", [...currentPaths, ...newPaths] as any);
|
|
431
431
|
}
|
|
432
432
|
|
|
433
433
|
return;
|
|
@@ -481,7 +481,7 @@ export class FileManager<
|
|
|
481
481
|
|
|
482
482
|
watcher.on("ready", () => {
|
|
483
483
|
this.state.set("watching", true);
|
|
484
|
-
this.state.set("watchedPaths", pathsToWatch);
|
|
484
|
+
this.state.set("watchedPaths", pathsToWatch as any);
|
|
485
485
|
});
|
|
486
486
|
|
|
487
487
|
this.watcher = watcher;
|
|
@@ -495,7 +495,7 @@ export class FileManager<
|
|
|
495
495
|
if (this.watcher) {
|
|
496
496
|
this.watcher.close();
|
|
497
497
|
this.state.set("watching", false);
|
|
498
|
-
this.state.set("watchedPaths", []);
|
|
498
|
+
this.state.set("watchedPaths", [] as any);
|
|
499
499
|
this.watcher = null;
|
|
500
500
|
}
|
|
501
501
|
}
|
|
@@ -508,6 +508,7 @@ export class FileManager<
|
|
|
508
508
|
const stats = statSync(absolutePath);
|
|
509
509
|
this.files.set(path, {
|
|
510
510
|
dirname: dir,
|
|
511
|
+
relativeDirname: this.container.paths.relative(dir),
|
|
511
512
|
absolutePath,
|
|
512
513
|
relativePath: path,
|
|
513
514
|
name,
|
package/src/node/features/git.ts
CHANGED
|
@@ -155,7 +155,7 @@ export class Git extends Feature {
|
|
|
155
155
|
*/
|
|
156
156
|
get branch(): string | null {
|
|
157
157
|
if(!this.isRepo) { return null }
|
|
158
|
-
return this.container.feature('proc').exec(`${this.gitPath} branch`).split("\n").filter(line => line.startsWith('*')).map(line => line.replace('*', '').trim()).pop()
|
|
158
|
+
return this.container.feature('proc').exec(`${this.gitPath} branch`).split("\n").filter(line => line.startsWith('*')).map(line => line.replace('*', '').trim()).pop() ?? null
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
/**
|
|
@@ -230,7 +230,7 @@ export class Git extends Feature {
|
|
|
230
230
|
*/
|
|
231
231
|
get repoRoot(): string | null {
|
|
232
232
|
if (this.state.has('repoRoot')) {
|
|
233
|
-
return this.state.get('repoRoot')
|
|
233
|
+
return this.state.get('repoRoot') ?? null
|
|
234
234
|
}
|
|
235
235
|
|
|
236
236
|
const repoRoot = this.container.fs.findUp('.git')
|
|
@@ -507,12 +507,12 @@ export class Git extends Feature {
|
|
|
507
507
|
if (str.startsWith('github.com/')) str = str.replace('github.com/', '')
|
|
508
508
|
if (str.includes('#')) {
|
|
509
509
|
const parts = str.split('#')
|
|
510
|
-
str = parts[0]
|
|
511
|
-
ref = parts[1]
|
|
510
|
+
str = parts[0] ?? str
|
|
511
|
+
ref = parts[1] ?? ref
|
|
512
512
|
}
|
|
513
513
|
|
|
514
514
|
const parts = str.split('/')
|
|
515
|
-
return { user: parts[0], repo: parts[1], ref, subdir: parts.slice(2).join('/') }
|
|
515
|
+
return { user: parts[0] ?? '', repo: parts[1] ?? '', ref, subdir: parts.slice(2).join('/') }
|
|
516
516
|
}
|
|
517
517
|
|
|
518
518
|
/**
|
|
@@ -201,7 +201,7 @@ export class Helpers extends Feature<HelpersState, HelpersOptions> {
|
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
// Schemas
|
|
204
|
-
const schemasModule = { CommandOptionsSchema: commands.baseClass?.optionsSchema || z.object({}) }
|
|
204
|
+
const schemasModule: Record<string, any> = { CommandOptionsSchema: commands.baseClass?.optionsSchema || z.object({}) }
|
|
205
205
|
try {
|
|
206
206
|
// Pull all base schemas from the already-loaded schemas/base module
|
|
207
207
|
const baseSchemas = require('../../schemas/base.js')
|
|
@@ -121,7 +121,7 @@ export class JsonTree<T extends JsonTreeState = JsonTreeState> extends Feature<T
|
|
|
121
121
|
for (const file of jsonFiles.filter(Boolean)) {
|
|
122
122
|
if (file?.relativePath) {
|
|
123
123
|
const fileContent = fileSystem.readFile(file.relativePath);
|
|
124
|
-
const fileData = JSON.parse(fileContent);
|
|
124
|
+
const fileData = JSON.parse(String(fileContent));
|
|
125
125
|
const path = file.relativePath
|
|
126
126
|
.replace(/\.json$/, "")
|
|
127
127
|
.replace(basePath + "/", "")
|
package/src/node/features/os.ts
CHANGED
|
@@ -207,12 +207,12 @@ export class OS extends Feature {
|
|
|
207
207
|
displays.push({
|
|
208
208
|
name: d._name ?? 'Unknown',
|
|
209
209
|
resolution: {
|
|
210
|
-
width: resMatch ? parseInt(resMatch[1], 10) : 0,
|
|
211
|
-
height: resMatch ? parseInt(resMatch[2], 10) : 0,
|
|
210
|
+
width: resMatch ? parseInt(resMatch[1] ?? '0', 10) : 0,
|
|
211
|
+
height: resMatch ? parseInt(resMatch[2] ?? '0', 10) : 0,
|
|
212
212
|
},
|
|
213
213
|
retina: /retina/i.test(d._spdisplays_resolution ?? '') || /retina/i.test(d.spdisplays_display_type ?? ''),
|
|
214
214
|
main: d.spdisplays_main === 'spdisplays_yes' || /yes/i.test(d.spdisplays_main ?? ''),
|
|
215
|
-
refreshRate: hzMatch ? parseFloat(hzMatch[1]) : undefined,
|
|
215
|
+
refreshRate: hzMatch ? parseFloat(hzMatch[1] ?? '0') : undefined,
|
|
216
216
|
connectionType: d.spdisplays_connection_type ?? undefined,
|
|
217
217
|
})
|
|
218
218
|
}
|
|
@@ -296,7 +296,7 @@ export class PackageFinder<
|
|
|
296
296
|
*/
|
|
297
297
|
get scopes(): string[] {
|
|
298
298
|
return Array.from(
|
|
299
|
-
new Set(this.packageNames.filter(p => p.startsWith('@')).map(p => p.split('/')[0]))
|
|
299
|
+
new Set(this.packageNames.filter(p => p.startsWith('@')).map(p => p.split('/')[0]).filter((s): s is string => s !== undefined))
|
|
300
300
|
)
|
|
301
301
|
}
|
|
302
302
|
|
|
@@ -4,6 +4,7 @@ import { Feature } from '../feature.js'
|
|
|
4
4
|
import { State } from '../../state.js'
|
|
5
5
|
import { Bus, type EventMap } from '../../bus.js'
|
|
6
6
|
import type { ChildProcess } from './proc.js'
|
|
7
|
+
import type { Helper } from '../../helper.js'
|
|
7
8
|
|
|
8
9
|
// ─── Output Buffer ─────────────────────────────────────────────────────────
|
|
9
10
|
|
|
@@ -436,46 +437,46 @@ export class ProcessManager extends Feature {
|
|
|
436
437
|
static { Feature.register(this, 'processManager') }
|
|
437
438
|
|
|
438
439
|
/** Tools that an assistant can use to spawn and manage processes. */
|
|
439
|
-
static tools: Record<string, { schema: z.ZodType; handler?: Function }> = {
|
|
440
|
+
static override tools: Record<string, { schema: z.ZodType; handler?: Function }> = {
|
|
440
441
|
spawnProcess: {
|
|
441
442
|
schema: z.object({
|
|
442
|
-
command: z.string().describe('The
|
|
443
|
-
args: z.string().optional().describe('
|
|
444
|
-
tag: z.string().optional().describe('A label for this process
|
|
445
|
-
cwd: z.string().optional().describe('Working directory for the process'),
|
|
443
|
+
command: z.string().describe('The executable to run (e.g. "node", "bun", "python"). NOT a shell command — use runCommand for shell syntax like pipes or &&.'),
|
|
444
|
+
args: z.string().optional().describe('Arguments as a single space-separated string. WARNING: spaces are used to split args, so paths with spaces will break. For complex argument quoting, prefer runCommand instead.'),
|
|
445
|
+
tag: z.string().optional().describe('A short, descriptive label for this process (e.g. "api-server", "file-watcher"). Always set a tag — it makes the process easy to find later with getProcessOutput and killProcess.'),
|
|
446
|
+
cwd: z.string().optional().describe('Working directory for the process. Defaults to the project root.'),
|
|
446
447
|
}).describe(
|
|
447
|
-
'
|
|
448
|
+
'Start a long-running background process (server, watcher, daemon). Returns immediately with a process ID — the process keeps running. Use this for anything that runs indefinitely. After spawning, call getProcessOutput to check if it started successfully. Always set a tag.'
|
|
448
449
|
),
|
|
449
450
|
},
|
|
450
451
|
runCommand: {
|
|
451
452
|
schema: z.object({
|
|
452
|
-
command: z.string().describe('
|
|
453
|
-
cwd: z.string().optional().describe('Working directory for the command'),
|
|
453
|
+
command: z.string().describe('A full shell command string (executed via sh -c). Supports pipes, &&, redirects, env vars, globs — anything you can type in a terminal. Examples: "bun test", "npm install && npm run build", "cat logs/*.txt | grep ERROR"'),
|
|
454
|
+
cwd: z.string().optional().describe('Working directory for the command. Defaults to the project root.'),
|
|
454
455
|
}).describe(
|
|
455
|
-
'Run a command and wait for it to complete. Returns
|
|
456
|
+
'Run a shell command and wait for it to complete. Returns stdout, stderr, and exit code. Use this for commands that finish on their own — builds, installs, tests, one-off scripts. For anything that runs forever (servers, watchers), use spawnProcess instead.'
|
|
456
457
|
),
|
|
457
458
|
},
|
|
458
459
|
listProcesses: {
|
|
459
460
|
schema: z.object({}).describe(
|
|
460
|
-
'List all tracked processes with their status, PID, command, uptime, and
|
|
461
|
+
'List all tracked background processes with their status, PID, command, uptime, and the last few lines of output. Call this to get an overview before deciding which process to inspect or kill.'
|
|
461
462
|
),
|
|
462
463
|
},
|
|
463
464
|
getProcessOutput: {
|
|
464
465
|
schema: z.object({
|
|
465
|
-
id: z.string().optional().describe('The process ID
|
|
466
|
-
tag: z.string().optional().describe('The tag
|
|
467
|
-
stream: z.string().optional().describe('
|
|
466
|
+
id: z.string().optional().describe('The process ID (returned by spawnProcess). Provide either id or tag, not both.'),
|
|
467
|
+
tag: z.string().optional().describe('The tag you assigned when spawning the process. Provide either id or tag, not both.'),
|
|
468
|
+
stream: z.string().optional().describe('"stdout" (default) or "stderr". Check stderr when a process crashes or behaves unexpectedly.'),
|
|
468
469
|
}).describe(
|
|
469
|
-
'
|
|
470
|
+
'Read a background process\'s buffered output — the first 20 lines (startup) and last 50 lines (recent activity). Call this after spawning to verify the process started correctly, and periodically to monitor its health.'
|
|
470
471
|
),
|
|
471
472
|
},
|
|
472
473
|
killProcess: {
|
|
473
474
|
schema: z.object({
|
|
474
|
-
id: z.string().optional().describe('The process ID to kill'),
|
|
475
|
-
tag: z.string().optional().describe('The tag of the process to kill'),
|
|
476
|
-
signal: z.string().optional().describe('
|
|
475
|
+
id: z.string().optional().describe('The process ID to kill. Provide either id or tag, not both.'),
|
|
476
|
+
tag: z.string().optional().describe('The tag of the process to kill. Provide either id or tag, not both.'),
|
|
477
|
+
signal: z.string().optional().describe('"SIGTERM" (default) for graceful shutdown, "SIGKILL" to force-kill a stuck process. Try SIGTERM first.'),
|
|
477
478
|
}).describe(
|
|
478
|
-
'
|
|
479
|
+
'Stop a running background process. Use SIGTERM (default) for graceful shutdown. If a process doesn\'t respond, follow up with SIGKILL. Always clean up processes you spawned when they\'re no longer needed.'
|
|
479
480
|
),
|
|
480
481
|
},
|
|
481
482
|
}
|
|
@@ -593,6 +594,38 @@ export class ProcessManager extends Feature {
|
|
|
593
594
|
return { id: handler.id, status: handler.status, signal, message: 'Process killed.' }
|
|
594
595
|
}
|
|
595
596
|
|
|
597
|
+
/**
|
|
598
|
+
* When an assistant uses processManager, inject system prompt guidance
|
|
599
|
+
* about how to manage processes safely and effectively.
|
|
600
|
+
*/
|
|
601
|
+
override setupToolsConsumer(consumer: Helper) {
|
|
602
|
+
if (typeof (consumer as any).addSystemPromptExtension === 'function') {
|
|
603
|
+
(consumer as any).addSystemPromptExtension('processManager', [
|
|
604
|
+
'## Process Management',
|
|
605
|
+
'',
|
|
606
|
+
'**Choosing the right tool:**',
|
|
607
|
+
'- `runCommand` — for anything that finishes on its own (builds, tests, installs, queries). Blocks until done.',
|
|
608
|
+
'- `spawnProcess` — for anything that runs indefinitely (servers, watchers, tails). Returns immediately.',
|
|
609
|
+
'- When in doubt: if you\'d press Ctrl-C to stop it, use `spawnProcess`. If you\'d wait for it, use `runCommand`.',
|
|
610
|
+
'',
|
|
611
|
+
'**After spawning a process:**',
|
|
612
|
+
'1. Always assign a descriptive `tag` so you can reference it later',
|
|
613
|
+
'2. Call `getProcessOutput` within a few seconds to verify it started correctly',
|
|
614
|
+
'3. Check `stderr` if the process crashes or output looks wrong',
|
|
615
|
+
'',
|
|
616
|
+
'**Monitoring:**',
|
|
617
|
+
'- Call `listProcesses` to see all running and finished processes at a glance',
|
|
618
|
+
'- Call `getProcessOutput` to read recent output — it keeps the first 20 and last 50 lines',
|
|
619
|
+
'- A process with status "crashed" exited with a non-zero code — check its stderr for the error',
|
|
620
|
+
'',
|
|
621
|
+
'**Cleanup:**',
|
|
622
|
+
'- Always `killProcess` background processes when they\'re no longer needed',
|
|
623
|
+
'- Use SIGTERM (default) first for graceful shutdown. Only use SIGKILL if SIGTERM doesn\'t work.',
|
|
624
|
+
'- If you spawned it, you\'re responsible for killing it',
|
|
625
|
+
].join('\n'))
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
596
629
|
// ─── Core API ───────────────────────────────────────────────────────────
|
|
597
630
|
|
|
598
631
|
/**
|
|
@@ -59,7 +59,7 @@ export const PythonEventsSchema = FeatureEventsSchema.extend({
|
|
|
59
59
|
}).describe('Install result')]).describe('When dependency installation fails'),
|
|
60
60
|
codeExecuted: z.tuple([z.object({
|
|
61
61
|
code: z.string().describe('The Python code that was executed'),
|
|
62
|
-
variables: z.record(z.any()).describe('Variables passed to the execution'),
|
|
62
|
+
variables: z.record(z.string(), z.any()).describe('Variables passed to the execution'),
|
|
63
63
|
result: z.object({
|
|
64
64
|
stdout: z.string().describe('Standard output'),
|
|
65
65
|
stderr: z.string().describe('Standard error'),
|
|
@@ -68,7 +68,7 @@ export const PythonEventsSchema = FeatureEventsSchema.extend({
|
|
|
68
68
|
}).describe('Code execution details')]).describe('When Python code finishes executing'),
|
|
69
69
|
fileExecuted: z.tuple([z.object({
|
|
70
70
|
filePath: z.string().describe('Path to the executed Python file'),
|
|
71
|
-
variables: z.record(z.any()).describe('Variables passed as arguments'),
|
|
71
|
+
variables: z.record(z.string(), z.any()).describe('Variables passed as arguments'),
|
|
72
72
|
result: z.object({
|
|
73
73
|
stdout: z.string().describe('Standard output'),
|
|
74
74
|
stderr: z.string().describe('Standard error'),
|
|
@@ -532,7 +532,7 @@ export class Python<
|
|
|
532
532
|
*/
|
|
533
533
|
private _parsePythonCommand(extraArgs: string[]): { command: string, args: string[] } {
|
|
534
534
|
const parts = this.pythonPath.split(/\s+/)
|
|
535
|
-
return { command: parts[0], args: [...parts.slice(1), ...extraArgs] }
|
|
535
|
+
return { command: parts[0] ?? 'python', args: [...parts.slice(1), ...extraArgs] }
|
|
536
536
|
}
|
|
537
537
|
|
|
538
538
|
/**
|
|
@@ -101,7 +101,7 @@ export class Repl<
|
|
|
101
101
|
|
|
102
102
|
// Load existing history
|
|
103
103
|
try {
|
|
104
|
-
const content = fs.readFile(this._historyPath, 'utf-8')
|
|
104
|
+
const content = this.container.fs.readFile(this._historyPath, 'utf-8') as string
|
|
105
105
|
this._history = content.split('\n').filter(Boolean).reverse()
|
|
106
106
|
} catch {}
|
|
107
107
|
|
|
@@ -204,7 +204,7 @@ export class Repl<
|
|
|
204
204
|
private _saveHistory(line: string) {
|
|
205
205
|
if (!this._historyPath || !line.trim()) return
|
|
206
206
|
try {
|
|
207
|
-
fs.
|
|
207
|
+
this.container.fs.appendFile(this._historyPath, line + '\n')
|
|
208
208
|
} catch {}
|
|
209
209
|
}
|
|
210
210
|
}
|
|
@@ -45,8 +45,8 @@ function esmToCjs(code: string): string {
|
|
|
45
45
|
.replace(/^export\s+\{([^}]*)\}\s*;?$/gm, (_match, body: string) => {
|
|
46
46
|
return body.split(',').map(s => {
|
|
47
47
|
const parts = s.trim().split(/\s+as\s+/)
|
|
48
|
-
const local = parts[0].trim()
|
|
49
|
-
const exported = (parts[1]
|
|
48
|
+
const local = (parts[0] ?? '').trim()
|
|
49
|
+
const exported = (parts[1] ?? parts[0] ?? '').trim()
|
|
50
50
|
return local ? `exports['${exported}'] = ${local};` : ''
|
|
51
51
|
}).filter(Boolean).join(' ')
|
|
52
52
|
})
|
package/src/node/features/ui.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { z } from 'zod'
|
|
|
2
2
|
import { FeatureStateSchema } from '../../schemas/base.js'
|
|
3
3
|
import { Feature } from "../feature.js";
|
|
4
4
|
import colors from "chalk";
|
|
5
|
-
import type { Fonts } from "figlet";
|
|
5
|
+
import type { FontName as Fonts } from "figlet";
|
|
6
6
|
import { figlet, fontNames } from "./figlet-fonts.js";
|
|
7
7
|
import inquirer from "inquirer";
|
|
8
8
|
import { marked } from 'marked';
|
package/src/node/features/vm.ts
CHANGED
|
@@ -219,9 +219,9 @@ export class VM<
|
|
|
219
219
|
|
|
220
220
|
// Find the last non-empty line
|
|
221
221
|
let lastIdx = lines.length - 1
|
|
222
|
-
while (lastIdx > 0 && !lines[lastIdx].trim()) lastIdx--
|
|
222
|
+
while (lastIdx > 0 && !(lines[lastIdx] ?? '').trim()) lastIdx--
|
|
223
223
|
|
|
224
|
-
let lastLine = lines[lastIdx]
|
|
224
|
+
let lastLine = lines[lastIdx] ?? ''
|
|
225
225
|
|
|
226
226
|
// For single-line code with semicolons (e.g. CLI eval), split the last line
|
|
227
227
|
// into statements and only try to return the final statement.
|
|
@@ -390,7 +390,7 @@ export class VM<
|
|
|
390
390
|
if (!fs.exists(filePath)) return {}
|
|
391
391
|
|
|
392
392
|
const raw = fs.readFile(filePath)
|
|
393
|
-
const { code } = this.container.feature('transpiler').transformSync(raw, { format: 'cjs' })
|
|
393
|
+
const { code } = this.container.feature('transpiler').transformSync(String(raw), { format: 'cjs' })
|
|
394
394
|
|
|
395
395
|
const sharedExports = {}
|
|
396
396
|
const { context } = this.performSync(code, {
|
|
@@ -113,7 +113,7 @@ export class YamlTree<T extends YamlTreeState = YamlTreeState> extends Feature<T
|
|
|
113
113
|
for (const file of yamlFiles.filter(Boolean)) {
|
|
114
114
|
if(file?.relativePath) {
|
|
115
115
|
const fileContent = fileSystem.readFile(file.relativePath);
|
|
116
|
-
const fileData = yamlFeature.parse(fileContent);
|
|
116
|
+
const fileData = yamlFeature.parse(String(fileContent));
|
|
117
117
|
const path = file.relativePath.replace(/\.ya?ml$/, "").replace(basePath + "/", "").split("/").filter(v => v?.length).map(p => camelCase(p));
|
|
118
118
|
set(tree, path, fileData)
|
|
119
119
|
}
|
package/src/node.ts
CHANGED
|
@@ -65,6 +65,7 @@ export type { AvailableFeatures, FeatureOptions, FeatureState } from './feature'
|
|
|
65
65
|
export type { NodeContainer, NodeFeatures } from './node/container'
|
|
66
66
|
export type { AvailableServers, StartOptions, ServersInterface } from './server'
|
|
67
67
|
export type { HelperState, HelperOptions } from './helper'
|
|
68
|
+
export type { Entity } from './entity'
|
|
68
69
|
export type { EventMap } from './bus'
|
|
69
70
|
export type { SetStateValue, StateChangeType } from './state'
|
|
70
71
|
|
package/src/python/generated.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Auto-generated scaffold and MCP readme content
|
|
2
|
-
// Generated at: 2026-
|
|
2
|
+
// Generated at: 2026-04-05T06:58:07.148Z
|
|
3
3
|
// Source: docs/scaffolds/*.md, docs/examples/assistant/, and docs/mcp/readme.md
|
|
4
4
|
//
|
|
5
5
|
// Do not edit manually. Run: luca build-scaffolds
|