@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,353 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { commands, CommandOptionsSchema } from '@soederpop/luca'
|
|
3
|
+
import type { ContainerContext } from '@soederpop/luca'
|
|
4
|
+
import { AGIContainer } from '../src/agi/container.server.js'
|
|
5
|
+
import { tmpdir } from 'os'
|
|
6
|
+
|
|
7
|
+
export const argsSchema = CommandOptionsSchema.extend({
|
|
8
|
+
model: z.string().optional().describe('OpenAI model to use'),
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
export async function inkbot(options: z.infer<typeof argsSchema>, context: ContainerContext) {
|
|
12
|
+
const container = new AGIContainer()
|
|
13
|
+
|
|
14
|
+
// ─── Load Ink ────────────────────────────────────────────────────────
|
|
15
|
+
const ink = container.feature('ink', { enable: true, patchConsole: true })
|
|
16
|
+
await ink.loadModules()
|
|
17
|
+
const React = ink.React
|
|
18
|
+
const h = React.createElement
|
|
19
|
+
const { Box, Text } = ink.components
|
|
20
|
+
const { useInput, useApp, useStdout } = ink.hooks
|
|
21
|
+
const { useState, useEffect } = React
|
|
22
|
+
|
|
23
|
+
// ─── Scene Runner ────────────────────────────────────────────────────
|
|
24
|
+
// Scenes are code strings run as bun subprocesses.
|
|
25
|
+
// The stage entity tracks which scenes exist and which is active.
|
|
26
|
+
// Scene entities track individual code, output, error, status.
|
|
27
|
+
|
|
28
|
+
const stage = container.entity('inkbot:stage')
|
|
29
|
+
stage.setState({ activeSceneId: null, sceneIds: [] as string[], tick: 0 })
|
|
30
|
+
|
|
31
|
+
const sceneMap: Record<string, ReturnType<typeof container.entity>> = {}
|
|
32
|
+
|
|
33
|
+
function bumpStage() {
|
|
34
|
+
stage.setState({ tick: ((stage.state.get('tick') as number) || 0) + 1 })
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function getOrCreateScene(id: string, code: string) {
|
|
38
|
+
if (sceneMap[id]) {
|
|
39
|
+
sceneMap[id].setState({ code })
|
|
40
|
+
return sceneMap[id]
|
|
41
|
+
}
|
|
42
|
+
const scene = container.entity(`inkbot:scene:${id}`)
|
|
43
|
+
scene.setState({ code, output: '', error: '', status: 'idle', exitCode: null })
|
|
44
|
+
sceneMap[id] = scene
|
|
45
|
+
const ids = [...((stage.state.get('sceneIds') || []) as string[])]
|
|
46
|
+
if (!ids.includes(id)) ids.push(id)
|
|
47
|
+
stage.setState({ sceneIds: ids })
|
|
48
|
+
if (!stage.state.get('activeSceneId')) stage.setState({ activeSceneId: id })
|
|
49
|
+
return scene
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const proc = container.feature('proc')
|
|
53
|
+
const fs = container.feature('fs')
|
|
54
|
+
const sceneTmpDir = `${tmpdir()}/inkbot-scenes`
|
|
55
|
+
fs.ensureFolder(sceneTmpDir)
|
|
56
|
+
|
|
57
|
+
async function runScene(id: string): Promise<{ output: string; error: string; exitCode: number }> {
|
|
58
|
+
const scene = sceneMap[id]
|
|
59
|
+
if (!scene) throw new Error(`Scene "${id}" not found`)
|
|
60
|
+
|
|
61
|
+
const code = scene.state.get('code') as string
|
|
62
|
+
scene.setState({ status: 'running', output: '', error: '' })
|
|
63
|
+
bumpStage()
|
|
64
|
+
|
|
65
|
+
// Write to tmpdir, shell out to `luca run` — gets full container context + process isolation
|
|
66
|
+
const file = `${sceneTmpDir}/${id.replace(/[^a-zA-Z0-9-]/g, '_')}_${Date.now()}.ts`
|
|
67
|
+
fs.writeFile(file, code)
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
const result = await proc.spawnAndCapture('luca', ['run', file], {
|
|
71
|
+
cwd: container.cwd,
|
|
72
|
+
onOutput(data: string) {
|
|
73
|
+
scene.setState({ output: ((scene.state.get('output') || '') as string) + data })
|
|
74
|
+
bumpStage()
|
|
75
|
+
},
|
|
76
|
+
onError(data: string) {
|
|
77
|
+
scene.setState({ error: ((scene.state.get('error') || '') as string) + data })
|
|
78
|
+
bumpStage()
|
|
79
|
+
},
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
const status = result.exitCode === 0 ? 'complete' : 'failed'
|
|
83
|
+
scene.setState({ status, exitCode: result.exitCode })
|
|
84
|
+
bumpStage()
|
|
85
|
+
try { fs.unlink(file) } catch {}
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
output: (scene.state.get('output') || '') as string,
|
|
89
|
+
error: (scene.state.get('error') || '') as string,
|
|
90
|
+
exitCode: result.exitCode ?? 1,
|
|
91
|
+
}
|
|
92
|
+
} catch (err: any) {
|
|
93
|
+
scene.setState({ status: 'failed', error: err.message, exitCode: 1 })
|
|
94
|
+
bumpStage()
|
|
95
|
+
try { fs.unlink(file) } catch {}
|
|
96
|
+
return { output: '', error: err.message, exitCode: 1 }
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ─── Assistant ───────────────────────────────────────────────────────
|
|
101
|
+
const mgr = container.feature('assistantsManager')
|
|
102
|
+
await mgr.discover()
|
|
103
|
+
const assistant = mgr.create('inkbot', { model: options.model })
|
|
104
|
+
|
|
105
|
+
// Scene completion → inject result into conversation so the assistant sees it
|
|
106
|
+
stage.on('sceneComplete' as any, (id: string, output: string) => {
|
|
107
|
+
const msg = output.trim()
|
|
108
|
+
? `[Scene "${id}" completed]\n${output.trim()}`
|
|
109
|
+
: `[Scene "${id}" completed with no output]`
|
|
110
|
+
assistant.conversation?.pushMessage({ role: 'developer', content: msg })
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
stage.on('sceneFailed' as any, (id: string, error: string) => {
|
|
114
|
+
const msg = `[Scene "${id}" failed]\n${error.trim()}`
|
|
115
|
+
assistant.conversation?.pushMessage({ role: 'developer', content: msg })
|
|
116
|
+
// Auto-ask the assistant to fix it
|
|
117
|
+
assistant.ask(msg).catch(() => {})
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
// Canvas tools — registered directly so they close over stage/sceneMap
|
|
121
|
+
assistant.addTool(
|
|
122
|
+
'draw',
|
|
123
|
+
async (args: { code: string; sceneId?: string }) => {
|
|
124
|
+
const id = args.sceneId || 'default'
|
|
125
|
+
getOrCreateScene(id, args.code)
|
|
126
|
+
stage.setState({ activeSceneId: id })
|
|
127
|
+
bumpStage()
|
|
128
|
+
// Fire and forget — result feeds back via stage events
|
|
129
|
+
runScene(id).then(result => {
|
|
130
|
+
if (result.exitCode === 0) {
|
|
131
|
+
stage.emit('sceneComplete' as any, id, result.output)
|
|
132
|
+
} else {
|
|
133
|
+
stage.emit('sceneFailed' as any, id, result.error)
|
|
134
|
+
}
|
|
135
|
+
})
|
|
136
|
+
return { status: 'running', sceneId: id }
|
|
137
|
+
},
|
|
138
|
+
z.object({
|
|
139
|
+
code: z.string().describe('TypeScript code to execute. Use console.log() for visible output.'),
|
|
140
|
+
sceneId: z.string().optional().describe('Scene id (defaults to "default").'),
|
|
141
|
+
}).describe('Draw or redraw the canvas. Returns immediately — output streams to the canvas. If the scene fails, you will be notified automatically.'),
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
assistant.addTool(
|
|
145
|
+
'create_scene',
|
|
146
|
+
async (args: { id: string; code: string }) => {
|
|
147
|
+
getOrCreateScene(args.id, args.code)
|
|
148
|
+
return { created: args.id, allScenes: stage.state.get('sceneIds') }
|
|
149
|
+
},
|
|
150
|
+
z.object({
|
|
151
|
+
id: z.string().describe('Unique scene identifier'),
|
|
152
|
+
code: z.string().describe('TypeScript code for this scene'),
|
|
153
|
+
}).describe('Create a named scene without running it yet.'),
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
assistant.addTool(
|
|
157
|
+
'run_scene',
|
|
158
|
+
async (args: { id: string }) => runScene(args.id),
|
|
159
|
+
z.object({
|
|
160
|
+
id: z.string().describe('Scene id to run'),
|
|
161
|
+
}).describe('Run a specific scene by its id.'),
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
assistant.addTool(
|
|
165
|
+
'run_all',
|
|
166
|
+
async () => {
|
|
167
|
+
const ids = (stage.state.get('sceneIds') || []) as string[]
|
|
168
|
+
const results: any[] = []
|
|
169
|
+
for (const id of ids) results.push({ id, ...(await runScene(id)) })
|
|
170
|
+
return results
|
|
171
|
+
},
|
|
172
|
+
z.object({}).describe('Run every scene in order and return all results.'),
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
assistant.addTool(
|
|
176
|
+
'get_canvas',
|
|
177
|
+
async () => {
|
|
178
|
+
const activeId = stage.state.get('activeSceneId') as string | null
|
|
179
|
+
if (!activeId || !sceneMap[activeId]) return { status: 'empty', allScenes: [] }
|
|
180
|
+
const s = sceneMap[activeId]
|
|
181
|
+
return {
|
|
182
|
+
sceneId: activeId,
|
|
183
|
+
status: s.state.get('status'),
|
|
184
|
+
output: s.state.get('output'),
|
|
185
|
+
error: s.state.get('error'),
|
|
186
|
+
code: s.state.get('code'),
|
|
187
|
+
allScenes: stage.state.get('sceneIds'),
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
z.object({}).describe('Inspect the current canvas: active scene output, error, code, status.'),
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
assistant.addTool(
|
|
194
|
+
'activate_scene',
|
|
195
|
+
async (args: { id: string }) => {
|
|
196
|
+
if (!sceneMap[args.id]) return { error: `Scene "${args.id}" not found` }
|
|
197
|
+
stage.setState({ activeSceneId: args.id })
|
|
198
|
+
bumpStage()
|
|
199
|
+
return { activeSceneId: args.id }
|
|
200
|
+
},
|
|
201
|
+
z.object({
|
|
202
|
+
id: z.string().describe('Scene id to make active in the canvas'),
|
|
203
|
+
}).describe('Switch the canvas to display a different scene.'),
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
// ─── Ink App ─────────────────────────────────────────────────────────
|
|
207
|
+
|
|
208
|
+
type Msg = { role: 'user' | 'assistant' | 'system'; content: string }
|
|
209
|
+
|
|
210
|
+
function App() {
|
|
211
|
+
const [messages, setMessages] = useState<Msg[]>([])
|
|
212
|
+
const [input, setInput] = useState('')
|
|
213
|
+
const [streaming, setStreaming] = useState('')
|
|
214
|
+
const [thinking, setThinking] = useState(false)
|
|
215
|
+
const [activity, setActivity] = useState('')
|
|
216
|
+
const [canvas, setCanvas] = useState({ output: '', error: '', status: 'empty' })
|
|
217
|
+
const { exit } = useApp()
|
|
218
|
+
const { stdout } = useStdout()
|
|
219
|
+
const rows = stdout?.rows ?? 24
|
|
220
|
+
|
|
221
|
+
// --- assistant events ---
|
|
222
|
+
useEffect(() => {
|
|
223
|
+
const onPreview = (text: string) => setStreaming(text)
|
|
224
|
+
const onResponse = (text: string) => {
|
|
225
|
+
setStreaming('')
|
|
226
|
+
setThinking(false)
|
|
227
|
+
setActivity('')
|
|
228
|
+
setMessages(prev => [...prev, { role: 'assistant', content: text }])
|
|
229
|
+
}
|
|
230
|
+
const onToolCall = (name: string) => setActivity(`${name}`)
|
|
231
|
+
const onToolResult = () => setActivity('')
|
|
232
|
+
|
|
233
|
+
assistant.on('preview', onPreview)
|
|
234
|
+
assistant.on('response', onResponse)
|
|
235
|
+
assistant.on('toolCall', onToolCall)
|
|
236
|
+
assistant.on('toolResult', onToolResult)
|
|
237
|
+
return () => {
|
|
238
|
+
assistant.off('preview', onPreview)
|
|
239
|
+
assistant.off('response', onResponse)
|
|
240
|
+
assistant.off('toolCall', onToolCall)
|
|
241
|
+
assistant.off('toolResult', onToolResult)
|
|
242
|
+
}
|
|
243
|
+
}, [])
|
|
244
|
+
|
|
245
|
+
// --- stage entity ticks → canvas state ---
|
|
246
|
+
useEffect(() => {
|
|
247
|
+
const unsub = stage.state.observe((_changeType: any, key: any) => {
|
|
248
|
+
if (key !== 'tick') return
|
|
249
|
+
const activeId = stage.state.get('activeSceneId') as string | null
|
|
250
|
+
if (!activeId || !sceneMap[activeId]) {
|
|
251
|
+
setCanvas({ output: '', error: '', status: 'empty' })
|
|
252
|
+
return
|
|
253
|
+
}
|
|
254
|
+
const s = sceneMap[activeId]
|
|
255
|
+
setCanvas({
|
|
256
|
+
output: (s.state.get('output') || '') as string,
|
|
257
|
+
error: (s.state.get('error') || '') as string,
|
|
258
|
+
status: (s.state.get('status') || 'idle') as string,
|
|
259
|
+
})
|
|
260
|
+
})
|
|
261
|
+
return unsub
|
|
262
|
+
}, [])
|
|
263
|
+
|
|
264
|
+
// --- keyboard ---
|
|
265
|
+
useInput((ch, key) => {
|
|
266
|
+
if (key.escape) { exit(); return }
|
|
267
|
+
|
|
268
|
+
if (key.return) {
|
|
269
|
+
if (thinking) return
|
|
270
|
+
const msg = input.trim()
|
|
271
|
+
if (!msg) return
|
|
272
|
+
setInput('')
|
|
273
|
+
setMessages(prev => [...prev, { role: 'user', content: msg }])
|
|
274
|
+
setThinking(true)
|
|
275
|
+
assistant.ask(msg).catch((err: any) => {
|
|
276
|
+
setMessages(prev => [...prev, { role: 'system', content: `error: ${err.message}` }])
|
|
277
|
+
setThinking(false)
|
|
278
|
+
})
|
|
279
|
+
return
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (key.backspace || key.delete) {
|
|
283
|
+
setInput(prev => prev.slice(0, -1))
|
|
284
|
+
return
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (ch && !key.ctrl && !key.meta) {
|
|
288
|
+
setInput(prev => prev + ch)
|
|
289
|
+
}
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
// --- render ---
|
|
293
|
+
const visible = messages.slice(-30)
|
|
294
|
+
const sceneIds = (stage.state.get('sceneIds') || []) as string[]
|
|
295
|
+
const activeId = (stage.state.get('activeSceneId') || '') as string
|
|
296
|
+
|
|
297
|
+
const chatChildren: any[] = []
|
|
298
|
+
|
|
299
|
+
visible.forEach((m, i) => {
|
|
300
|
+
const color = m.role === 'user' ? 'green' : m.role === 'system' ? 'red' : 'white'
|
|
301
|
+
const prefix = m.role === 'user' ? '> ' : ' '
|
|
302
|
+
chatChildren.push(h(Text, { key: `msg-${i}`, wrap: 'wrap', color }, `${prefix}${m.content}`))
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
if (streaming) chatChildren.push(h(Text, { key: 'chat-stream', wrap: 'wrap', dimColor: true }, ` ${streaming}`))
|
|
306
|
+
if (thinking && !streaming) chatChildren.push(h(Text, { key: 'chat-think', color: 'yellow' }, ' thinking...'))
|
|
307
|
+
if (activity) chatChildren.push(h(Text, { key: 'chat-act', color: 'blue' }, ` [${activity}]`))
|
|
308
|
+
|
|
309
|
+
const canvasBody = canvas.output
|
|
310
|
+
? h(Text, { key: 'cvs-out', wrap: 'wrap' }, canvas.output)
|
|
311
|
+
: canvas.status === 'empty'
|
|
312
|
+
? h(Text, { key: 'cvs-empty', dimColor: true }, ' ask inkbot to draw something')
|
|
313
|
+
: null
|
|
314
|
+
|
|
315
|
+
// border + header + status = 4 rows overhead per panel
|
|
316
|
+
const panelHeight = rows - 2
|
|
317
|
+
|
|
318
|
+
return h(Box, { flexDirection: 'row', width: '100%', height: rows },
|
|
319
|
+
// ── Chat ──
|
|
320
|
+
h(Box, { key: 'chat', flexDirection: 'column', width: '50%', height: rows, borderStyle: 'round', borderColor: 'cyan', paddingX: 1 },
|
|
321
|
+
h(Text, { bold: true, color: 'cyan' }, ' inkbot '),
|
|
322
|
+
h(Box, { flexDirection: 'column', flexGrow: 1, overflow: 'hidden' }, ...chatChildren),
|
|
323
|
+
h(Box, { borderStyle: 'single', borderColor: 'gray', paddingX: 1 },
|
|
324
|
+
h(Text, { color: 'green' }, '> '),
|
|
325
|
+
h(Text, null, input),
|
|
326
|
+
h(Text, { dimColor: true }, '\u2588'),
|
|
327
|
+
),
|
|
328
|
+
),
|
|
329
|
+
// ── Canvas ──
|
|
330
|
+
h(Box, { key: 'canvas', flexDirection: 'column', width: '50%', height: rows, borderStyle: 'round', borderColor: 'magenta', paddingX: 1 },
|
|
331
|
+
h(Text, { bold: true, color: 'magenta' }, ' canvas '),
|
|
332
|
+
h(Box, { flexDirection: 'column', height: panelHeight - 4, overflow: 'hidden' },
|
|
333
|
+
canvasBody,
|
|
334
|
+
canvas.error ? h(Text, { key: 'cvs-err', color: 'red', wrap: 'wrap' }, canvas.error) : null,
|
|
335
|
+
),
|
|
336
|
+
h(Box, null,
|
|
337
|
+
h(Text, { dimColor: true }, ` ${canvas.status}`),
|
|
338
|
+
sceneIds.length > 1 ? h(Text, { dimColor: true }, ` scenes: ${sceneIds.join(', ')} active: ${activeId}`) : null,
|
|
339
|
+
),
|
|
340
|
+
),
|
|
341
|
+
)
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Mount and hold
|
|
345
|
+
await ink.render(h(App))
|
|
346
|
+
await ink.waitUntilExit()
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
export default {
|
|
350
|
+
description: 'Launch the Inkbot split-pane assistant with a live canvas.',
|
|
351
|
+
argsSchema,
|
|
352
|
+
handler: inkbot,
|
|
353
|
+
}
|
package/commands/release.ts
CHANGED
|
@@ -1,186 +1,80 @@
|
|
|
1
|
-
import { z } from
|
|
2
|
-
import type { ContainerContext } from
|
|
3
|
-
import { CommandOptionsSchema } from
|
|
4
|
-
|
|
5
|
-
const TARGETS = [
|
|
6
|
-
{ name: 'linux-x64', bunTarget: 'bun-linux-x64', suffix: 'linux-x64' },
|
|
7
|
-
{ name: 'linux-arm64', bunTarget: 'bun-linux-arm64', suffix: 'linux-arm64' },
|
|
8
|
-
{ name: 'darwin-x64', bunTarget: 'bun-darwin-x64', suffix: 'darwin-x64' },
|
|
9
|
-
{ name: 'darwin-arm64', bunTarget: 'bun-darwin-arm64', suffix: 'darwin-arm64' },
|
|
10
|
-
{ name: 'windows-x64', bunTarget: 'bun-windows-x64', suffix: 'windows-x64', ext: '.exe' },
|
|
11
|
-
]
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { ContainerContext } from "@soederpop/luca";
|
|
3
|
+
import { CommandOptionsSchema } from "@soederpop/luca/schemas";
|
|
12
4
|
|
|
13
5
|
export const argsSchema = CommandOptionsSchema.extend({
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
console.log(` ${target.name}...`)
|
|
83
|
-
const result = await proc.execAndCapture(cmd, { silent: true })
|
|
84
|
-
if (result.exitCode !== 0) {
|
|
85
|
-
console.error(` Failed to compile for ${target.name}:\n${result.stderr}`)
|
|
86
|
-
return
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const sizeBytes = proc.exec(`stat -f%z ${container.paths.resolve(outfile)}`)
|
|
90
|
-
const sizeMB = (parseInt(sizeBytes, 10) / 1024 / 1024).toFixed(1)
|
|
91
|
-
console.log(` ✓ ${outfile} (${sizeMB} MB)`)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (options.dryRun) {
|
|
95
|
-
console.log(`\n→ Dry run complete. Binaries are in ${distDir}/`)
|
|
96
|
-
console.log(' Skipping git tag and GitHub release.')
|
|
97
|
-
return
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// 4. Check if tag already exists
|
|
101
|
-
const tagCheck = await proc.execAndCapture(`git tag -l "${tag}"`, { silent: true })
|
|
102
|
-
if (tagCheck.stdout.trim() === tag) {
|
|
103
|
-
console.error(`\nTag ${tag} already exists. Bump the version in package.json first.`)
|
|
104
|
-
return
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// 5. Check for clean working tree (allow untracked)
|
|
108
|
-
const statusCheck = await proc.execAndCapture('git status --porcelain', { silent: true })
|
|
109
|
-
const dirtyFiles = statusCheck.stdout.trim().split('\n').filter((l: string) => l && !l.startsWith('??'))
|
|
110
|
-
if (dirtyFiles.length > 0) {
|
|
111
|
-
console.error('\nWorking tree has uncommitted changes. Commit or stash them first.')
|
|
112
|
-
console.error(dirtyFiles.join('\n'))
|
|
113
|
-
return
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// 6. Create git tag
|
|
117
|
-
console.log(`\n→ Creating tag ${tag}...`)
|
|
118
|
-
const tagResult = await proc.execAndCapture(`git tag -a "${tag}" -m "Release ${tag}"`, { silent: true })
|
|
119
|
-
if (tagResult.exitCode !== 0) {
|
|
120
|
-
console.error(`Failed to create tag:\n${tagResult.stderr}`)
|
|
121
|
-
return
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// 7. Push tag
|
|
125
|
-
console.log(`→ Pushing tag ${tag}...`)
|
|
126
|
-
const pushResult = await proc.execAndCapture(`git push origin "${tag}"`, { silent: true })
|
|
127
|
-
if (pushResult.exitCode !== 0) {
|
|
128
|
-
console.error(`Failed to push tag:\n${pushResult.stderr}`)
|
|
129
|
-
return
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// 8. Create GitHub release and upload binaries
|
|
133
|
-
const assetPaths = selectedTargets
|
|
134
|
-
.map(t => container.paths.resolve(`${distDir}/luca-${t.suffix}${t.ext || ''}`))
|
|
135
|
-
|
|
136
|
-
const releaseTitle = `Luca ${tag}`
|
|
137
|
-
const releaseNotes = await generateReleaseNotes(proc, tag)
|
|
138
|
-
|
|
139
|
-
// Write notes to a temp file so gh doesn't need shell quoting
|
|
140
|
-
const notesFile = container.paths.resolve(distDir, 'release-notes.md')
|
|
141
|
-
await fileSystem.writeFileAsync(notesFile, releaseNotes)
|
|
142
|
-
|
|
143
|
-
console.log(`\n→ Creating GitHub release ${tag}...`)
|
|
144
|
-
const ghArgs = [
|
|
145
|
-
'release', 'create', tag,
|
|
146
|
-
...assetPaths,
|
|
147
|
-
'--title', releaseTitle,
|
|
148
|
-
'--notes-file', notesFile,
|
|
149
|
-
...(options.draft ? ['--draft'] : []),
|
|
150
|
-
]
|
|
151
|
-
const ghResult = await proc.spawnAndCapture('gh', ghArgs)
|
|
152
|
-
|
|
153
|
-
if (ghResult.exitCode !== 0) {
|
|
154
|
-
console.error(`Failed to create GitHub release:\n${ghResult.stderr}`)
|
|
155
|
-
console.log('The tag was pushed. You can manually create the release with:')
|
|
156
|
-
console.log(` gh release create ${tag} ${assetPaths.join(' ')}`)
|
|
157
|
-
return
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
console.log(`\n✓ Released ${tag} successfully!`)
|
|
161
|
-
console.log(` https://github.com/soederpop/luca/releases/tag/${tag}`)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
async function generateReleaseNotes(proc: any, tag: string): Promise<string> {
|
|
165
|
-
// Get commits since last tag
|
|
166
|
-
const lastTag = await proc.execAndCapture('git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo ""', { silent: true })
|
|
167
|
-
const since = lastTag.stdout.trim()
|
|
168
|
-
|
|
169
|
-
let logCmd: string
|
|
170
|
-
if (since) {
|
|
171
|
-
logCmd = `git log ${since}..HEAD --oneline --no-decorate`
|
|
172
|
-
} else {
|
|
173
|
-
logCmd = 'git log --oneline --no-decorate -20'
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const log = await proc.execAndCapture(logCmd, { silent: true })
|
|
177
|
-
const commits = log.stdout.trim()
|
|
178
|
-
|
|
179
|
-
return `## What's Changed\n\n${commits ? commits.split('\n').map((c: string) => `- ${c}`).join('\n') : 'Initial release'}\n\n## Platforms\n\n- Linux x64\n- Linux ARM64\n- macOS x64 (Intel)\n- macOS ARM64 (Apple Silicon)\n- Windows x64`
|
|
6
|
+
skipTests: z
|
|
7
|
+
.boolean()
|
|
8
|
+
.optional()
|
|
9
|
+
.describe("Skip running tests before release"),
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
async function release(
|
|
13
|
+
options: z.infer<typeof argsSchema>,
|
|
14
|
+
context: ContainerContext,
|
|
15
|
+
) {
|
|
16
|
+
const container = context.container as any;
|
|
17
|
+
const proc = container.feature("proc");
|
|
18
|
+
const fileSystem = container.feature("fs");
|
|
19
|
+
const ui = container.feature("ui");
|
|
20
|
+
|
|
21
|
+
const pkg = JSON.parse(await fileSystem.readFileAsync("package.json"));
|
|
22
|
+
const version = pkg.version;
|
|
23
|
+
const tag = `v${version}`;
|
|
24
|
+
|
|
25
|
+
ui.banner(`Luca Release ${tag}`);
|
|
26
|
+
|
|
27
|
+
// Check if tag already exists
|
|
28
|
+
const tagCheck = await proc.execAndCapture(`git tag -l "${tag}"`, {
|
|
29
|
+
silent: true,
|
|
30
|
+
});
|
|
31
|
+
if (tagCheck.stdout.trim() === tag) {
|
|
32
|
+
console.error(
|
|
33
|
+
`\nTag ${tag} already exists. Bump the version in package.json first.`,
|
|
34
|
+
);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Run tests
|
|
39
|
+
if (!options.skipTests) {
|
|
40
|
+
console.log("\n→ Running tests...");
|
|
41
|
+
const testResult = await proc.execAndCapture("bun test test/*.test.ts", {
|
|
42
|
+
silent: false,
|
|
43
|
+
});
|
|
44
|
+
if (testResult.exitCode !== 0) {
|
|
45
|
+
console.error("Tests failed. Fix them before releasing.");
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Create and push git tag — triggers the GitHub Actions release workflow
|
|
51
|
+
console.log(`\n→ Creating tag ${tag}...`);
|
|
52
|
+
const tagResult = await proc.execAndCapture(
|
|
53
|
+
`git tag -a "${tag}" -m "Release ${tag}"`,
|
|
54
|
+
{ silent: true },
|
|
55
|
+
);
|
|
56
|
+
if (tagResult.exitCode !== 0) {
|
|
57
|
+
console.error(`Failed to create tag:\n${tagResult.stderr}`);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
console.log(`→ Pushing tag ${tag}...`);
|
|
62
|
+
const pushResult = await proc.execAndCapture(`git push origin "${tag}"`, {
|
|
63
|
+
silent: true,
|
|
64
|
+
});
|
|
65
|
+
if (pushResult.exitCode !== 0) {
|
|
66
|
+
console.error(`Failed to push tag:\n${pushResult.stderr}`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
console.log(
|
|
71
|
+
`\n✓ Tag ${tag} pushed. GitHub Actions will build, sign, and create the draft release.`,
|
|
72
|
+
);
|
|
73
|
+
console.log(` https://github.com/soederpop/luca/actions`);
|
|
180
74
|
}
|
|
181
75
|
|
|
182
76
|
export default {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}
|
|
77
|
+
description: "Run tests and trigger a GitHub Actions release via git tag",
|
|
78
|
+
argsSchema,
|
|
79
|
+
handler: release,
|
|
80
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { ContainerState } from '../container';
|
|
2
|
+
import { type NodeFeatures, NodeContainer } from '../node/container';
|
|
3
|
+
import '@/introspection/generated.agi.js';
|
|
4
|
+
import { OpenAIClient } from '../clients/openai';
|
|
5
|
+
import { ElevenLabsClient } from '../clients/elevenlabs';
|
|
6
|
+
import { ClaudeCode } from './features/claude-code';
|
|
7
|
+
import { OpenAICodex } from './features/openai-codex';
|
|
8
|
+
import { Conversation } from './features/conversation';
|
|
9
|
+
import { ConversationHistory } from './features/conversation-history';
|
|
10
|
+
import { Assistant } from './features/assistant';
|
|
11
|
+
import { AssistantsManager } from './features/assistants-manager';
|
|
12
|
+
import { DocsReader } from './features/docs-reader';
|
|
13
|
+
import { SkillsLibrary } from './features/skills-library';
|
|
14
|
+
import { BrowserUse } from './features/browser-use';
|
|
15
|
+
import { SemanticSearch } from '@soederpop/luca/node/features/semantic-search';
|
|
16
|
+
import { ContentDb } from '@soederpop/luca/node/features/content-db';
|
|
17
|
+
import { FileTools } from './features/file-tools';
|
|
18
|
+
import { LucaCoder } from './features/luca-coder';
|
|
19
|
+
import type { ConversationTool } from './features/conversation';
|
|
20
|
+
import type { ZodType } from 'zod';
|
|
21
|
+
export { ClaudeCode, OpenAICodex, Conversation, ConversationHistory, Assistant, AssistantsManager, DocsReader, SkillsLibrary, BrowserUse, FileTools, LucaCoder, SemanticSearch, ContentDb, NodeContainer, OpenAIClient, ElevenLabsClient, };
|
|
22
|
+
export type { ConversationTool, ZodType, ContainerState, NodeFeatures, };
|
|
23
|
+
export interface AGIFeatures extends NodeFeatures {
|
|
24
|
+
conversation: typeof Conversation;
|
|
25
|
+
claudeCode: typeof ClaudeCode;
|
|
26
|
+
openaiCodex: typeof OpenAICodex;
|
|
27
|
+
conversationHistory: typeof ConversationHistory;
|
|
28
|
+
assistant: typeof Assistant;
|
|
29
|
+
assistantsManager: typeof AssistantsManager;
|
|
30
|
+
docsReader: typeof DocsReader;
|
|
31
|
+
skillsLibrary: typeof SkillsLibrary;
|
|
32
|
+
browserUse: typeof BrowserUse;
|
|
33
|
+
fileTools: typeof FileTools;
|
|
34
|
+
lucaCoder: typeof LucaCoder;
|
|
35
|
+
}
|
|
36
|
+
export interface ConversationFactoryOptions {
|
|
37
|
+
tools?: {
|
|
38
|
+
handlers: Record<string, ConversationTool['handler']>;
|
|
39
|
+
schemas: Record<string, ZodType>;
|
|
40
|
+
};
|
|
41
|
+
systemPrompt?: string;
|
|
42
|
+
model?: string;
|
|
43
|
+
id?: string;
|
|
44
|
+
title?: string;
|
|
45
|
+
thread?: string;
|
|
46
|
+
tags?: string[];
|
|
47
|
+
metadata?: Record<string, any>;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* AGI-specific container that extends NodeContainer with AI capabilities including
|
|
51
|
+
* OpenAI conversations, code generation, and self-modifying agent features.
|
|
52
|
+
*/
|
|
53
|
+
export declare class AGIContainer<Features extends AGIFeatures = AGIFeatures, K extends ContainerState = ContainerState> extends NodeContainer<Features, K> {
|
|
54
|
+
openai: OpenAIClient;
|
|
55
|
+
claudeCode?: ClaudeCode;
|
|
56
|
+
openaiCodex?: OpenAICodex;
|
|
57
|
+
conversationHistory?: ConversationHistory;
|
|
58
|
+
docs: ContentDb;
|
|
59
|
+
conversation(options?: ConversationFactoryOptions): Promise<InstanceType<Features["conversation"]>>;
|
|
60
|
+
}
|
|
61
|
+
declare const container: any;
|
|
62
|
+
export default container;
|
|
63
|
+
//# sourceMappingURL=container.server.d.ts.map
|