luca 3.0.0 → 3.0.2
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 +1 -0
- package/CLAUDE.md +10 -2
- package/README.md +130 -112
- package/assistants/codingAssistant/CORE.md +6 -1
- package/assistants/codingAssistant/hooks.ts +1 -1
- package/assistants/inkbot/hooks.ts +1 -1
- package/assistants/inkbot/tools.ts +1 -1
- package/bun.lock +220 -322
- package/commands/audit-docs.ts +2 -2
- package/commands/build-bootstrap.ts +2 -3
- package/commands/build-python-bridge.ts +2 -3
- package/commands/build-scaffolds.ts +2 -3
- package/commands/bundle-consumer-project.ts +521 -0
- package/commands/generate-api-docs.ts +2 -2
- package/commands/inkbot.ts +2 -2
- package/commands/release.ts +2 -2
- package/commands/try-all-challenges.ts +3 -3
- package/commands/try-challenge.ts +3 -3
- package/dist/agi/container.server.d.ts +2 -2
- package/dist/agi/features/assistant.d.ts +2 -2
- package/dist/agi/features/assistants-manager.d.ts +1 -1
- package/dist/agi/features/autonomous-assistant.d.ts +1 -1
- package/dist/agi/features/browser-use.d.ts +1 -1
- package/dist/agi/features/claude-code.d.ts +1 -1
- package/dist/agi/features/conversation-history.d.ts +2 -2
- package/dist/agi/features/conversation.d.ts +1 -1
- package/dist/agi/features/docs-reader.d.ts +1 -1
- package/dist/agi/features/file-tools.d.ts +1 -1
- package/dist/agi/features/luca-coder.d.ts +1 -1
- package/dist/agi/features/openai-codex.d.ts +1 -1
- package/dist/agi/features/skills-library.d.ts +1 -1
- package/dist/clients/civitai/index.d.ts +4 -4
- package/dist/clients/client-template.d.ts +4 -4
- package/dist/clients/comfyui/index.d.ts +2 -2
- package/dist/clients/elevenlabs/index.d.ts +2 -2
- package/dist/clients/openai/index.d.ts +2 -2
- package/dist/clients/supabase/index.d.ts +3 -3
- package/dist/command.d.ts +1 -1
- package/dist/node/container.d.ts +1 -1
- package/dist/node/features/helpers.d.ts +3 -3
- package/dist/node/features/semantic-search.d.ts +1 -1
- package/dist/node/features/vm.d.ts +3 -3
- package/dist/node.d.ts +1 -1
- package/dist/scaffolds/generated.d.ts +1 -1
- package/dist/selector.d.ts +1 -1
- package/index.html +217 -190
- package/luca.console.ts +1 -1
- package/package.json +2 -2
- package/public/index.html +217 -190
- package/public/slides-ai-native.html +1 -1
- package/public/slides-intro.html +2 -2
- package/scripts/examples/ask-luca-expert.ts +1 -1
- package/scripts/examples/assistant-questions.ts +1 -1
- package/scripts/examples/excalidraw-expert.ts +1 -1
- package/scripts/examples/file-manager.ts +1 -1
- package/scripts/examples/ideas.ts +1 -1
- package/scripts/examples/interactive-chat.ts +1 -1
- package/scripts/examples/opening-a-web-browser.ts +1 -1
- package/scripts/examples/telegram-bot.ts +1 -1
- package/scripts/examples/using-assistant-with-mcp.ts +1 -1
- package/scripts/examples/using-claude-code.ts +1 -1
- package/scripts/examples/using-contentdb.ts +2 -2
- package/scripts/examples/using-conversations.ts +1 -1
- package/scripts/examples/using-disk-cache.ts +1 -1
- package/scripts/examples/using-docker-shell.ts +1 -1
- package/scripts/examples/using-elevenlabs.ts +1 -1
- package/scripts/examples/using-google-calendar.ts +1 -1
- package/scripts/examples/using-google-docs.ts +1 -1
- package/scripts/examples/using-google-drive.ts +1 -1
- package/scripts/examples/using-google-sheets.ts +1 -1
- package/scripts/examples/using-nlp.ts +1 -1
- package/scripts/examples/using-ollama.ts +1 -1
- package/scripts/examples/using-postgres.ts +1 -1
- package/scripts/examples/using-runpod.ts +1 -1
- package/scripts/examples/using-tts.ts +1 -1
- package/scripts/scaffold.ts +5 -5
- package/scripts/scratch.ts +1 -1
- package/scripts/test-assistant-hooks.ts +1 -1
- package/scripts/test-docs-reader.ts +1 -1
- package/src/agi/container.server.ts +6 -2
- package/src/agi/features/agent-memory.ts +25 -25
- package/src/agi/features/assistant.ts +34 -5
- package/src/agi/features/assistants-manager.ts +122 -6
- package/src/agi/features/autonomous-assistant.ts +1 -1
- package/src/agi/features/browser-use.ts +20 -1
- package/src/agi/features/claude-code.ts +51 -5
- package/src/agi/features/coding-tools.ts +1 -1
- package/src/agi/features/conversation-history.ts +181 -4
- package/src/agi/features/conversation.ts +186 -15
- package/src/agi/features/docs-reader.ts +2 -2
- package/src/agi/features/file-tools.ts +49 -2
- package/src/agi/features/luca-coder.ts +7 -5
- package/src/agi/features/mcp-bridge.ts +532 -0
- package/src/agi/features/openai-codex.ts +2 -2
- package/src/agi/features/skills-library.ts +131 -52
- package/src/agi/lib/token-counter.ts +80 -0
- package/src/bootstrap/generated.ts +56 -57
- package/src/browser.ts +1 -1
- package/src/cli/build-info.ts +2 -2
- package/src/cli/cli.ts +2 -2
- package/src/clients/civitai/index.ts +5 -5
- package/src/clients/client-template.ts +4 -4
- package/src/clients/comfyui/index.ts +4 -4
- package/src/clients/elevenlabs/index.ts +4 -4
- package/src/clients/openai/index.ts +7 -7
- package/src/clients/supabase/index.ts +4 -4
- package/src/clients/voicebox/index.ts +4 -4
- package/src/command.ts +2 -1
- package/src/commands/chat.ts +1 -0
- package/src/commands/eval.ts +2 -56
- package/src/commands/introspect.ts +1 -1
- package/src/commands/prompt.ts +41 -9
- package/src/container-describer.ts +8 -1
- package/src/container.ts +13 -0
- package/src/entity.ts +2 -2
- package/src/helper.ts +1 -1
- package/src/introspection/generated.agi.ts +28563 -27571
- package/src/introspection/generated.node.ts +20281 -20194
- package/src/introspection/generated.web.ts +605 -584
- package/src/introspection/scan.ts +11 -6
- package/src/node/container.ts +1 -1
- package/src/node/features/content-db.ts +39 -2
- package/src/node/features/display-result.ts +57 -0
- package/src/node/features/helpers.ts +42 -15
- package/src/node/features/python.ts +25 -19
- package/src/node/features/repl.ts +1 -1
- package/src/node/features/secure-shell.ts +11 -17
- package/src/node/features/semantic-search.ts +2 -2
- package/src/node/features/transpiler.ts +2 -3
- package/src/node/features/ui.ts +5 -0
- package/src/node/features/vm.ts +3 -3
- package/src/node.ts +3 -3
- package/src/python/generated.ts +0 -1
- package/src/scaffolds/generated.ts +82 -83
- package/src/selector.ts +1 -1
- package/src/servers/express.ts +1 -1
- package/src/web/features/helpers.ts +22 -0
- package/tsconfig.json +12 -12
- package/docs/CLI.md +0 -335
- package/docs/CNAME +0 -1
- package/docs/README.md +0 -60
- package/docs/TABLE-OF-CONTENTS.md +0 -183
- package/docs/apis/clients/elevenlabs.md +0 -308
- package/docs/apis/clients/graph.md +0 -107
- package/docs/apis/clients/openai.md +0 -429
- package/docs/apis/clients/rest.md +0 -161
- package/docs/apis/clients/websocket.md +0 -174
- package/docs/apis/features/agi/assistant.md +0 -625
- package/docs/apis/features/agi/assistants-manager.md +0 -282
- package/docs/apis/features/agi/auto-assistant.md +0 -279
- package/docs/apis/features/agi/browser-use.md +0 -802
- package/docs/apis/features/agi/claude-code.md +0 -884
- package/docs/apis/features/agi/conversation-history.md +0 -364
- package/docs/apis/features/agi/conversation.md +0 -548
- package/docs/apis/features/agi/docs-reader.md +0 -99
- package/docs/apis/features/agi/file-tools.md +0 -163
- package/docs/apis/features/agi/luca-coder.md +0 -407
- package/docs/apis/features/agi/openai-codex.md +0 -396
- package/docs/apis/features/agi/openapi.md +0 -138
- package/docs/apis/features/agi/semantic-search.md +0 -387
- package/docs/apis/features/agi/skills-library.md +0 -239
- package/docs/apis/features/node/container-link.md +0 -192
- package/docs/apis/features/node/content-db.md +0 -450
- package/docs/apis/features/node/disk-cache.md +0 -379
- package/docs/apis/features/node/dns.md +0 -652
- package/docs/apis/features/node/docker.md +0 -706
- package/docs/apis/features/node/downloader.md +0 -81
- package/docs/apis/features/node/esbuild.md +0 -60
- package/docs/apis/features/node/file-manager.md +0 -191
- package/docs/apis/features/node/fs.md +0 -1217
- package/docs/apis/features/node/git.md +0 -371
- package/docs/apis/features/node/google-auth.md +0 -193
- package/docs/apis/features/node/google-calendar.md +0 -202
- package/docs/apis/features/node/google-docs.md +0 -173
- package/docs/apis/features/node/google-drive.md +0 -246
- package/docs/apis/features/node/google-mail.md +0 -214
- package/docs/apis/features/node/google-sheets.md +0 -194
- package/docs/apis/features/node/grep.md +0 -292
- package/docs/apis/features/node/helpers.md +0 -164
- package/docs/apis/features/node/ink.md +0 -334
- package/docs/apis/features/node/ipc-socket.md +0 -249
- package/docs/apis/features/node/json-tree.md +0 -86
- package/docs/apis/features/node/networking.md +0 -316
- package/docs/apis/features/node/nlp.md +0 -133
- package/docs/apis/features/node/opener.md +0 -97
- package/docs/apis/features/node/os.md +0 -146
- package/docs/apis/features/node/package-finder.md +0 -392
- package/docs/apis/features/node/postgres.md +0 -234
- package/docs/apis/features/node/proc.md +0 -399
- package/docs/apis/features/node/process-manager.md +0 -305
- package/docs/apis/features/node/python.md +0 -604
- package/docs/apis/features/node/redis.md +0 -380
- package/docs/apis/features/node/repl.md +0 -88
- package/docs/apis/features/node/runpod.md +0 -674
- package/docs/apis/features/node/secure-shell.md +0 -176
- package/docs/apis/features/node/semantic-search.md +0 -408
- package/docs/apis/features/node/sqlite.md +0 -233
- package/docs/apis/features/node/telegram.md +0 -279
- package/docs/apis/features/node/transpiler.md +0 -74
- package/docs/apis/features/node/tts.md +0 -133
- package/docs/apis/features/node/ui.md +0 -701
- package/docs/apis/features/node/vault.md +0 -59
- package/docs/apis/features/node/vm.md +0 -75
- package/docs/apis/features/node/yaml-tree.md +0 -85
- package/docs/apis/features/node/yaml.md +0 -176
- package/docs/apis/features/web/asset-loader.md +0 -59
- package/docs/apis/features/web/container-link.md +0 -192
- package/docs/apis/features/web/esbuild.md +0 -54
- package/docs/apis/features/web/helpers.md +0 -164
- package/docs/apis/features/web/network.md +0 -44
- package/docs/apis/features/web/speech.md +0 -69
- package/docs/apis/features/web/vault.md +0 -59
- package/docs/apis/features/web/vm.md +0 -75
- package/docs/apis/features/web/voice.md +0 -84
- package/docs/apis/servers/express.md +0 -171
- package/docs/apis/servers/mcp.md +0 -238
- package/docs/apis/servers/websocket.md +0 -170
- package/docs/bootstrap/CLAUDE.md +0 -101
- package/docs/bootstrap/SKILL.md +0 -341
- package/docs/bootstrap/templates/about-command.ts +0 -41
- package/docs/bootstrap/templates/docs-models.ts +0 -22
- package/docs/bootstrap/templates/docs-readme.md +0 -43
- package/docs/bootstrap/templates/example-feature.ts +0 -53
- package/docs/bootstrap/templates/health-endpoint.ts +0 -15
- package/docs/bootstrap/templates/luca-cli.ts +0 -30
- package/docs/bootstrap/templates/runme.md +0 -54
- package/docs/challenges/caching-proxy.md +0 -16
- package/docs/challenges/content-db-round-trip.md +0 -14
- package/docs/challenges/custom-command.md +0 -9
- package/docs/challenges/file-watcher-pipeline.md +0 -11
- package/docs/challenges/grep-audit-report.md +0 -15
- package/docs/challenges/multi-feature-dashboard.md +0 -14
- package/docs/challenges/process-orchestrator.md +0 -17
- package/docs/challenges/rest-api-server-with-client.md +0 -12
- package/docs/challenges/script-runner-with-vm.md +0 -11
- package/docs/challenges/simple-rest-api.md +0 -15
- package/docs/challenges/websocket-serve-and-client.md +0 -11
- package/docs/challenges/yaml-config-system.md +0 -14
- package/docs/command-system-overhaul.md +0 -94
- package/docs/documentation-audit.md +0 -134
- package/docs/examples/assistant/CORE.md +0 -18
- package/docs/examples/assistant/hooks.ts +0 -3
- package/docs/examples/assistant/tools.ts +0 -10
- package/docs/examples/assistant-hooks-reference.ts +0 -171
- package/docs/examples/assistant-with-process-manager.md +0 -84
- package/docs/examples/content-db.md +0 -77
- package/docs/examples/disk-cache.md +0 -83
- package/docs/examples/docker.md +0 -101
- package/docs/examples/downloader.md +0 -70
- package/docs/examples/entity.md +0 -124
- package/docs/examples/esbuild.md +0 -80
- package/docs/examples/feature-as-tool-provider.md +0 -143
- package/docs/examples/file-manager.md +0 -82
- package/docs/examples/fs.md +0 -83
- package/docs/examples/git.md +0 -85
- package/docs/examples/google-auth.md +0 -88
- package/docs/examples/google-calendar.md +0 -94
- package/docs/examples/google-docs.md +0 -82
- package/docs/examples/google-drive.md +0 -96
- package/docs/examples/google-sheets.md +0 -95
- package/docs/examples/grep.md +0 -85
- package/docs/examples/ink-blocks.md +0 -75
- package/docs/examples/ink-renderer.md +0 -41
- package/docs/examples/ink.md +0 -103
- package/docs/examples/ipc-socket.md +0 -103
- package/docs/examples/json-tree.md +0 -91
- package/docs/examples/networking.md +0 -58
- package/docs/examples/nlp.md +0 -91
- package/docs/examples/opener.md +0 -78
- package/docs/examples/os.md +0 -72
- package/docs/examples/package-finder.md +0 -89
- package/docs/examples/postgres.md +0 -91
- package/docs/examples/proc.md +0 -81
- package/docs/examples/process-manager.md +0 -79
- package/docs/examples/python.md +0 -132
- package/docs/examples/repl.md +0 -93
- package/docs/examples/runpod.md +0 -119
- package/docs/examples/secure-shell.md +0 -92
- package/docs/examples/sqlite.md +0 -86
- package/docs/examples/structured-output-with-assistants.md +0 -144
- package/docs/examples/telegram.md +0 -77
- package/docs/examples/tts.md +0 -86
- package/docs/examples/ui.md +0 -80
- package/docs/examples/vault.md +0 -70
- package/docs/examples/vm.md +0 -86
- package/docs/examples/websocket-ask-and-reply-example.md +0 -128
- package/docs/examples/yaml-tree.md +0 -93
- package/docs/examples/yaml.md +0 -104
- package/docs/ideas/assistant-factory-pattern.md +0 -142
- package/docs/in-memory-fs.md +0 -4
- package/docs/introspection-audit.md +0 -49
- package/docs/introspection.md +0 -164
- package/docs/mcp/readme.md +0 -162
- package/docs/models.ts +0 -41
- package/docs/philosophy.md +0 -86
- package/docs/principles.md +0 -7
- package/docs/prompts/audit-codebase-for-failures-to-use-the-container.md +0 -34
- package/docs/prompts/check-for-undocumented-features.md +0 -27
- package/docs/prompts/mcp-test-easy-command.md +0 -27
- package/docs/scaffolds/client.md +0 -149
- package/docs/scaffolds/command.md +0 -120
- package/docs/scaffolds/endpoint.md +0 -171
- package/docs/scaffolds/feature.md +0 -158
- package/docs/scaffolds/selector.md +0 -91
- package/docs/scaffolds/server.md +0 -196
- package/docs/selectors.md +0 -115
- package/docs/sessions/custom-command/attempt-log-2.md +0 -195
- package/docs/sessions/file-watcher-pipeline/attempt-log-1.md +0 -728
- package/docs/sessions/file-watcher-pipeline/attempt-log-2.md +0 -555
- package/docs/sessions/grep-audit-report/attempt-log-1.md +0 -289
- package/docs/sessions/multi-feature-dashboard/attempt-log-2.md +0 -679
- package/docs/sessions/rest-api-server-with-client/attempt-log-1.md +0 -1
- package/docs/sessions/rest-api-server-with-client/attempt-log-3.md +0 -920
- package/docs/sessions/simple-rest-api/attempt-log-1.md +0 -593
- package/docs/sessions/websocket-serve-and-client/attempt-log-2.md +0 -995
- package/docs/tutorials/00-bootstrap.md +0 -166
- package/docs/tutorials/01-getting-started.md +0 -106
- package/docs/tutorials/02-container.md +0 -210
- package/docs/tutorials/03-scripts.md +0 -194
- package/docs/tutorials/04-features-overview.md +0 -196
- package/docs/tutorials/05-state-and-events.md +0 -171
- package/docs/tutorials/06-servers.md +0 -157
- package/docs/tutorials/07-endpoints.md +0 -198
- package/docs/tutorials/08-commands.md +0 -252
- package/docs/tutorials/09-clients.md +0 -162
- package/docs/tutorials/10-creating-features.md +0 -203
- package/docs/tutorials/11-contentbase.md +0 -191
- package/docs/tutorials/12-assistants.md +0 -215
- package/docs/tutorials/13-introspection.md +0 -157
- package/docs/tutorials/14-type-system.md +0 -174
- package/docs/tutorials/15-project-patterns.md +0 -222
- package/docs/tutorials/16-google-features.md +0 -534
- package/docs/tutorials/17-tui-blocks.md +0 -530
- package/docs/tutorials/18-semantic-search.md +0 -334
- package/docs/tutorials/19-python-sessions.md +0 -401
- package/docs/tutorials/20-browser-esm.md +0 -234
- package/src/agi/endpoints/ask.ts +0 -60
- package/src/agi/endpoints/conversations/[id].ts +0 -45
- package/src/agi/endpoints/conversations.ts +0 -31
- package/src/agi/endpoints/experts.ts +0 -37
- package/test/assistant-hooks.test.ts +0 -306
- package/test/assistant.test.ts +0 -81
- package/test/bus.test.ts +0 -134
- package/test/clients-servers.test.ts +0 -217
- package/test/command.test.ts +0 -267
- package/test/container-link.test.ts +0 -274
- package/test/conversation.test.ts +0 -220
- package/test/features.test.ts +0 -160
- package/test/fork-and-research.test.ts +0 -450
- package/test/integration.test.ts +0 -787
- package/test/interceptor-chain.test.ts +0 -61
- package/test/node-container.test.ts +0 -121
- package/test/python-session.test.ts +0 -105
- package/test/rate-limit.test.ts +0 -272
- package/test/semantic-search.test.ts +0 -550
- package/test/state.test.ts +0 -121
- package/test/vm-context.test.ts +0 -146
- package/test/vm-loadmodule.test.ts +0 -213
- package/test/websocket-ask.test.ts +0 -101
- package/test-integration/assistant.test.ts +0 -138
- package/test-integration/assistants-manager.test.ts +0 -113
- package/test-integration/claude-code.test.ts +0 -98
- package/test-integration/conversation-history.test.ts +0 -205
- package/test-integration/conversation.test.ts +0 -137
- package/test-integration/elevenlabs.test.ts +0 -55
- package/test-integration/google-services.test.ts +0 -80
- package/test-integration/helpers.ts +0 -89
- package/test-integration/memory.test.ts +0 -204
- package/test-integration/openai-codex.test.ts +0 -93
- package/test-integration/runpod.test.ts +0 -58
- package/test-integration/server-endpoints.test.ts +0 -97
- package/test-integration/telegram.test.ts +0 -46
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# Grep Audit Report
|
|
2
|
-
|
|
3
|
-
Build `luca audit <path>` that scans a codebase at the given path and finds:
|
|
4
|
-
|
|
5
|
-
- TODO and FIXME comments
|
|
6
|
-
- `console.log` statements
|
|
7
|
-
- Hardcoded secret patterns (strings that look like API keys, tokens, passwords in assignments)
|
|
8
|
-
|
|
9
|
-
Generate a markdown report at `docs/reports/audit-<timestamp>.md` summarizing the findings with file paths and line numbers.
|
|
10
|
-
|
|
11
|
-
Support `luca audit <path> --json` for machine-readable output instead of markdown.
|
|
12
|
-
|
|
13
|
-
## After you are done
|
|
14
|
-
|
|
15
|
-
Write a LESSONS.md in the attempt folder that describes what you learned, what you struggled with, and what you could have been supplied with up front either in the CLAUDE.md or in the skills that come with luca so you could achieve the goal quicker and with less trouble.
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# Build a Multi-Feature Dashboard
|
|
2
|
-
|
|
3
|
-
Create a `luca dashboard` command that displays a live-updating terminal UI showing:
|
|
4
|
-
|
|
5
|
-
- Git status: current branch, number of dirty files
|
|
6
|
-
- Cache stats: number of cached entries
|
|
7
|
-
- OS info: CPU usage, free memory
|
|
8
|
-
- Network: whether https://example.com is reachable
|
|
9
|
-
|
|
10
|
-
The dashboard should refresh every 2 seconds with a nice terminal layout.
|
|
11
|
-
|
|
12
|
-
## After you are done
|
|
13
|
-
|
|
14
|
-
Write a LESSONS.md in the attempt folder that describes what you learned, what you struggled with, and what you could have been supplied with up front either in the CLAUDE.md or in the skills that come with luca so you could achieve the goal quicker and with less trouble.
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# Process Orchestrator
|
|
2
|
-
|
|
3
|
-
Build `luca dev` that starts 3 processes simultaneously:
|
|
4
|
-
|
|
5
|
-
1. An HTTP API server on port 3000
|
|
6
|
-
2. A WebSocket server on port 3001
|
|
7
|
-
3. A file watcher that logs changes in the project directory
|
|
8
|
-
|
|
9
|
-
Multiplex their logs to stdout with color-coded prefixes (e.g. `[API]`, `[WS]`, `[WATCH]`). Gracefully shut down all processes on ctrl+c.
|
|
10
|
-
|
|
11
|
-
Support `luca dev --only api,ws` to start a subset of the processes.
|
|
12
|
-
|
|
13
|
-
Create a simple endpoint and websocket handler so there's something to actually hit when testing.
|
|
14
|
-
|
|
15
|
-
## After you are done
|
|
16
|
-
|
|
17
|
-
Write a LESSONS.md in the attempt folder that describes what you learned, what you struggled with, and what you could have been supplied with up front either in the CLAUDE.md or in the skills that come with luca so you could achieve the goal quicker and with less trouble.
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# Build a REST server with a matching REST Client
|
|
2
|
-
|
|
3
|
-
Create a command `luca start` which will use a custom luca express server you build and start it.
|
|
4
|
-
|
|
5
|
-
Also create a rest client that can call the methods it exposes.
|
|
6
|
-
|
|
7
|
-
The `luca connect` command should use the client and verify that all the servers endpoints work.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
## After you are done
|
|
11
|
-
|
|
12
|
-
Write a LESSONS.md in the attempt folder that describes what you learned, what you struggled with, and what you could have been supplied with up front either in the CLAUDE.md or in the skills that come with luca so you could achieve the goal quicker and with less trouble.
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# Script Runner with VM
|
|
2
|
-
|
|
3
|
-
Create a `scripts/` folder with a few `.ts` files that each export a `run()` function. These scripts should do simple things — format a date, generate a UUID, compute a hash of some input.
|
|
4
|
-
|
|
5
|
-
Build a `luca exec <scriptName>` command that loads and runs the named script in a sandboxed environment. The script should have access to the container but not direct filesystem access.
|
|
6
|
-
|
|
7
|
-
Add `luca exec --list` to show all available scripts with a short description parsed from a comment or export in each file.
|
|
8
|
-
|
|
9
|
-
## After you are done
|
|
10
|
-
|
|
11
|
-
Write a LESSONS.md in the attempt folder that describes what you learned, what you struggled with, and what you could have been supplied with up front either in the CLAUDE.md or in the skills that come with luca so you could achieve the goal quicker and with less trouble.
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
lastRanAt: 1773554828927
|
|
3
|
-
durationMs: 601701
|
|
4
|
-
outputTokens: 1646
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Build an API
|
|
8
|
-
|
|
9
|
-
I should be able to serve the api with `luca serve`
|
|
10
|
-
|
|
11
|
-
The API should use sqlite to serve an example api that lets me browse authors and books.
|
|
12
|
-
|
|
13
|
-
## After you are done
|
|
14
|
-
|
|
15
|
-
Write a LESSONS.md in the attempt folder that describes what you learned, what you struggled with, and what you could have been supplied with up front either in the CLAUDE.md or in the skills that come with luca so you could achieve the goal quicker and with less trouble.
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# Build a websocket server with a matching websocket client
|
|
2
|
-
|
|
3
|
-
Use the luca framework to build a websocket server you can start with a `luca start` command.
|
|
4
|
-
|
|
5
|
-
Also build a websocket based client that can connect to that server and speak the same language ( as opposed to just raw websocket calls )
|
|
6
|
-
|
|
7
|
-
Create a command called `luca connect` that uses this client and verifies that the server responds as expected.
|
|
8
|
-
|
|
9
|
-
## After you are done
|
|
10
|
-
|
|
11
|
-
Write a LESSONS.md in the attempt folder that describes what you learned, what you struggled with, and what you could have been supplied with up front either in the CLAUDE.md or in the skills that come with luca so you could achieve the goal quicker and with less trouble.
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# YAML Config System
|
|
2
|
-
|
|
3
|
-
Build a command suite for managing project configuration stored in `luca.config.yaml`:
|
|
4
|
-
|
|
5
|
-
- `luca config set <key> <value>` — set a config value (support nested keys like `server.port`)
|
|
6
|
-
- `luca config get <key>` — get a config value
|
|
7
|
-
- `luca config list` — print the full config as a formatted table
|
|
8
|
-
- `luca config delete <key>` — remove a key
|
|
9
|
-
|
|
10
|
-
Create the config file if it doesn't exist.
|
|
11
|
-
|
|
12
|
-
## After you are done
|
|
13
|
-
|
|
14
|
-
Write a LESSONS.md in the attempt folder that describes what you learned, what you struggled with, and what you could have been supplied with up front either in the CLAUDE.md or in the skills that come with luca so you could achieve the goal quicker and with less trouble.
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
# Command System Overhaul
|
|
2
|
-
|
|
3
|
-
The command system was pretty much 100% vibe coded and not reviewed. It was only until the first round of evals that I noticed some issues with it and dug into the code and noticed a few things with its implementation that are not consistent with the rest of the project.
|
|
4
|
-
|
|
5
|
-
My main issue is it doesn't actually use the luca Registry, the Command is not even a subclass of Helper, even though it is easily one of the most obvious examples, however there are quirks to it that let me empathize with the agent for its choices, so I want to resolve those conflicts so we can arrive at the correct design.
|
|
6
|
-
|
|
7
|
-
## Original Vision For Commands
|
|
8
|
-
|
|
9
|
-
1) For a user of the compiled `luca` binary, any `commands/:commandName.ts` will be available as `luca commandName`
|
|
10
|
-
2) The luca framework itself comes with core commands in `src/commands/*` that are bundled with the `luca` binary from bun
|
|
11
|
-
3) A user can also have `~/.luca/commands` folder which gets picked up
|
|
12
|
-
4) commands can export a zod schema that can be used for validation, documentation for CLI help screens
|
|
13
|
-
|
|
14
|
-
## Command Helper Options / State
|
|
15
|
-
|
|
16
|
-
A Command's constructor options are higher level things about the environment the command is being invoked in:
|
|
17
|
-
|
|
18
|
-
- target ( cli (output to stdout, stderr etc), headless (e.g. run through the js api in code, stdout, stderr needs to be captured and returned)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
## Developer Experience Requirements
|
|
22
|
-
|
|
23
|
-
Unlike features, clients, servers, which necessarily require a lot more forethought, a command should be very quick to author
|
|
24
|
-
|
|
25
|
-
for this reason, there needs to be a way that we can dynamically generate Command helper subclasses, without requiring the user to go through the ceremony of doing that.
|
|
26
|
-
|
|
27
|
-
Instead, a command module should be able to simply export a couple of expected named objects / types, and have the Command helper subclass generated and registered in the command registry at runtime.
|
|
28
|
-
|
|
29
|
-
## Idea for General Reusable DX Feature
|
|
30
|
-
|
|
31
|
-
This approach will allow us to accomplish the DX requirement for commands in a way that could make authoring every type of helper simpler as well, without having to modify the core class based implementation.
|
|
32
|
-
|
|
33
|
-
Given a typescript module called serve
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
```ts
|
|
37
|
-
import type { SimpleCommand } from '@soederpop/luca'
|
|
38
|
-
|
|
39
|
-
// SimpleCommand is a ts generic that makes it simpler to construct the actual class ServeCommand<CommandHelperOptions,COmmandHelperState> since all commands share the same base constructor options and have the same state, but we will need to capture
|
|
40
|
-
// the run options schema
|
|
41
|
-
declare module '@soederpop/luca' {
|
|
42
|
-
interface AvailableCommands {
|
|
43
|
-
serve: typeof Command
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
// container is gonna be global here if they don't import anything
|
|
49
|
-
// because this module will be run through the container's vm instead of being directly imported
|
|
50
|
-
const runOptionsSchema = z.object({
|
|
51
|
-
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
export type ServeRunOptions = z.infer<typeof runOptionsSchema>
|
|
55
|
-
|
|
56
|
-
export async function run(options: ServeRunOptions) {
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
This module could be grafted on to a subclass that gets generated at runtime and meets all the requirements
|
|
62
|
-
|
|
63
|
-
## CLI Internal Implementation idea
|
|
64
|
-
|
|
65
|
-
This is pseudocode, but will illustrate how I think we can accomplish the above.
|
|
66
|
-
|
|
67
|
-
The CLI would just call the execute method with whatever container.argv is as its input (container.argv is the result of minimist)
|
|
68
|
-
|
|
69
|
-
Any other kind of dispatcher that is using commands and wants to accept arbitrary subclasses can also use this execute method, and not have to worry about the simple command overriding the run method
|
|
70
|
-
|
|
71
|
-
```ts
|
|
72
|
-
type CommandOptions, CommandState etc ( zod schema inferred, make sure to follow feature, client, server implementations )
|
|
73
|
-
|
|
74
|
-
class Command extends Helper<CommandOptions,CommandState,COmmandEvents> {
|
|
75
|
-
// private, but we should allow the CLI to reach in and call this ?
|
|
76
|
-
private async execute(params) {
|
|
77
|
-
return this.run(params)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// NOTE: CommandRunOptions is not the same as the CommandOptions or HelperOptions passed to the constructor
|
|
81
|
-
// In fact the command options are more high level (e.g, is it running from the CLI? dispatched over RPC, an MCP call
|
|
82
|
-
// an agent tool? Commands are just atomic units of work that can be requested.
|
|
83
|
-
run(options: CommandRunOptions) {
|
|
84
|
-
// you don't need to super this ever, any subclass of command implements its own run
|
|
85
|
-
// SimpleCommands can export run and safely override this, because the CLI doesn't call run directly it calls execute
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
# Documentation Audit
|
|
2
|
-
|
|
3
|
-
Periodically do an audit of all Feature, Server, Client subclasses to make sure they are completely documented.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
## Files
|
|
7
|
-
|
|
8
|
-
- `src/node/features/*.ts` NodeContainer features
|
|
9
|
-
- `src/clients/*/index.ts` Client subclasses
|
|
10
|
-
- `src/agi/features.ts` AGIContainer features
|
|
11
|
-
|
|
12
|
-
## Generating Introspection Data for Runtime consumption
|
|
13
|
-
|
|
14
|
-
After any changes to the above files, make sure to run:
|
|
15
|
-
|
|
16
|
-
```shell
|
|
17
|
-
bun run build:introspection
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
## Documentation Guidelines
|
|
21
|
-
|
|
22
|
-
Here is a good example of a well documented feature, notice that:
|
|
23
|
-
|
|
24
|
-
- All of the Options, State, Event schema items have `describe()` calls
|
|
25
|
-
- There is a docblock above the class which uses a simple example with no imports, using the factory pattern
|
|
26
|
-
- getters are documented
|
|
27
|
-
- methods have jsdoc also with an example
|
|
28
|
-
- method options have jsdoc comments for typescript consumers
|
|
29
|
-
|
|
30
|
-
```ts
|
|
31
|
-
|
|
32
|
-
export const TTSOptionsSchema = FeatureOptionsSchema.extend({
|
|
33
|
-
apiKey: z.string().optional().describe('RunPod API key (falls back to RUNPOD_API_KEY env var)'),
|
|
34
|
-
voice: z.string().optional().describe('Default preset voice name'),
|
|
35
|
-
outputDir: z.string().optional().describe('Directory to save generated audio files'),
|
|
36
|
-
format: z.enum(['wav', 'flac', 'ogg']).default('wav').describe('Audio output format'),
|
|
37
|
-
})
|
|
38
|
-
export type TTSOptions = z.infer<typeof TTSOptionsSchema>
|
|
39
|
-
|
|
40
|
-
export const TTSStateSchema = FeatureStateSchema.extend({
|
|
41
|
-
lastFile: z.string().optional().describe('Path to the last generated audio file'),
|
|
42
|
-
lastText: z.string().optional().describe('Text of the last synthesis request'),
|
|
43
|
-
generating: z.boolean().default(false).describe('Whether audio is currently being generated'),
|
|
44
|
-
})
|
|
45
|
-
export type TTSState = z.infer<typeof TTSStateSchema>
|
|
46
|
-
|
|
47
|
-
export const TTSEventsSchema = FeatureEventsSchema.extend({
|
|
48
|
-
synthesized: z.tuple([
|
|
49
|
-
z.string().describe('The text that was synthesized'),
|
|
50
|
-
z.string().describe('Path to the generated audio file'),
|
|
51
|
-
z.string().describe('Voice used'),
|
|
52
|
-
z.number().describe('Duration of the API call in milliseconds'),
|
|
53
|
-
]).describe('Emitted when audio synthesis completes'),
|
|
54
|
-
error: z.tuple([
|
|
55
|
-
z.any().describe('The error'),
|
|
56
|
-
]).describe('Emitted when synthesis fails'),
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* TTS feature — synthesizes text to audio files via RunPod's Chatterbox Turbo endpoint.
|
|
61
|
-
*
|
|
62
|
-
* Generates high-quality speech audio by calling the Chatterbox Turbo public endpoint
|
|
63
|
-
* on RunPod, downloads the resulting audio, and saves it locally. Supports 20 preset
|
|
64
|
-
* voices and voice cloning via a reference audio URL.
|
|
65
|
-
*
|
|
66
|
-
* @example
|
|
67
|
-
* ```typescript
|
|
68
|
-
* const tts = container.feature('tts', { enable: true })
|
|
69
|
-
* const path = await tts.synthesize('Hello, how are you?', { voice: 'lucy' })
|
|
70
|
-
* console.log(`Audio saved to: ${path}`)
|
|
71
|
-
* ```
|
|
72
|
-
*/
|
|
73
|
-
export class TTS extends Feature<TTSState, TTSOptions> {
|
|
74
|
-
static override shortcut = 'features.tts' as const
|
|
75
|
-
static override envVars = ['RUNPOD_API_KEY']
|
|
76
|
-
static override stateSchema = TTSStateSchema
|
|
77
|
-
static override optionsSchema = TTSOptionsSchema
|
|
78
|
-
static override eventsSchema = TTSEventsSchema
|
|
79
|
-
|
|
80
|
-
/** RunPod API key from options or environment. */
|
|
81
|
-
get apiKey(): string {
|
|
82
|
-
return this.options.apiKey || process.env.RUNPOD_API_KEY || ''
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/** Directory where generated audio files are saved. */
|
|
86
|
-
get outputDir(): string {
|
|
87
|
-
return this.options.outputDir || join(homedir(), '.luca', 'tts-cache')
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/** The 20 preset voice names available in Chatterbox Turbo. */
|
|
91
|
-
get voices(): readonly string[] {
|
|
92
|
-
return PRESET_VOICES
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Synthesize text to an audio file using Chatterbox Turbo.
|
|
97
|
-
*
|
|
98
|
-
* Calls the RunPod public endpoint, downloads the generated audio,
|
|
99
|
-
* and saves it to the output directory.
|
|
100
|
-
*
|
|
101
|
-
* @param text - The text to synthesize into speech
|
|
102
|
-
* @param options - Override voice, format, or provide a voiceUrl for cloning
|
|
103
|
-
* @returns Absolute path to the generated audio file
|
|
104
|
-
*
|
|
105
|
-
* @example
|
|
106
|
-
* ```typescript
|
|
107
|
-
* // Use a preset voice
|
|
108
|
-
* const path = await tts.synthesize('Good morning!', { voice: 'ethan' })
|
|
109
|
-
*
|
|
110
|
-
* // Clone a voice from a reference audio URL
|
|
111
|
-
* const path = await tts.synthesize('Hello world', {
|
|
112
|
-
* voiceUrl: 'https://example.com/reference.wav'
|
|
113
|
-
* })
|
|
114
|
-
* ```
|
|
115
|
-
*/
|
|
116
|
-
async synthesize(text: string, options?: {
|
|
117
|
-
/* which voice to use */
|
|
118
|
-
voice?: string
|
|
119
|
-
/* which format to save the output in */
|
|
120
|
-
format?: 'wav' | 'flac' | 'ogg'
|
|
121
|
-
/* an optional url to use for voice cloning */
|
|
122
|
-
voiceUrl?: string
|
|
123
|
-
}): Promise<string> {
|
|
124
|
-
if (!this.apiKey) {
|
|
125
|
-
throw new Error('TTS requires a RunPod API key. Set RUNPOD_API_KEY or pass apiKey in options.')
|
|
126
|
-
}
|
|
127
|
-
// omitted
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
# Luca Assistant Example
|
|
2
|
-
|
|
3
|
-
You are currently an example / template "Assistant" provided by the Luca framework. ( You'll probably have no idea what that is, don't worry, it doesn't matter ).
|
|
4
|
-
|
|
5
|
-
You are what gets scaffolded when a user writes the `luca scaffold assistant` command.
|
|
6
|
-
|
|
7
|
-
In luca, an Assistant is backed by a folder which has a few components:
|
|
8
|
-
|
|
9
|
-
- CORE.md -- this is a markdown file that will get injected into the system prompt of a chat completion call
|
|
10
|
-
- tools.ts -- this file is expected to export functions, and a schemas object whose keys are the names of the functions that get exported, and whose values are zod v4 schemas that describe the parameters
|
|
11
|
-
- hooks.ts -- this file is expexted to export functions, whose names match the events emitted by the luca assistant helper
|
|
12
|
-
|
|
13
|
-
Currently, the user is chatting with you from the `luca chat` CLI.
|
|
14
|
-
|
|
15
|
-
You should tell them what each of these files is and how to edit them.
|
|
16
|
-
|
|
17
|
-
It is also important for them to know that the luca `container` is globally available for them in the context of the `tools.ts` and `hooks.ts` files.
|
|
18
|
-
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Example hooks.ts — showcases the assistant hook system.
|
|
3
|
-
*
|
|
4
|
-
* Every named export is a hook. Hooks are awaited via triggerHook(),
|
|
5
|
-
* so async work completes BEFORE the assistant proceeds.
|
|
6
|
-
*
|
|
7
|
-
* Available hooks:
|
|
8
|
-
*
|
|
9
|
-
* Lifecycle:
|
|
10
|
-
* created() — after prompt/tools/hooks load (before start)
|
|
11
|
-
* beforeStart() — before conversation wiring, blocks start()
|
|
12
|
-
* started() — conversation is ready, wire up tools here
|
|
13
|
-
* afterStart() — everything is live, blocks start() until done
|
|
14
|
-
* formatSystemPrompt(a, prompt) => string — rewrite the system prompt
|
|
15
|
-
*
|
|
16
|
-
* Ask flow:
|
|
17
|
-
* beforeInitialAsk(a, question, options) — first ask() only
|
|
18
|
-
* beforeAsk(a, question, options) => string? — every ask(), return rewrites question
|
|
19
|
-
* answered(a, result) — after response, before ask() returns
|
|
20
|
-
*
|
|
21
|
-
* Tool execution:
|
|
22
|
-
* beforeToolCall(a, ctx) — inspect/rewrite args, set ctx.skip to bypass
|
|
23
|
-
* afterToolCall(a, ctx) — inspect/rewrite result after execution
|
|
24
|
-
*
|
|
25
|
-
* Forwarded from conversation (awaited before the bus event):
|
|
26
|
-
* turnStart(a, info) turnEnd(a, info) chunk(a, delta)
|
|
27
|
-
* preview(a, text) response(a, text) toolCall(a, name, args)
|
|
28
|
-
* toolResult(a, name, result) toolError(a, name, error)
|
|
29
|
-
*
|
|
30
|
-
* The first argument is always the assistant instance.
|
|
31
|
-
* `assistant` and `container` are also available as globals (injected by the VM).
|
|
32
|
-
*/
|
|
33
|
-
import type { Assistant, AGIContainer } from '@soederpop/luca/agi'
|
|
34
|
-
|
|
35
|
-
declare global {
|
|
36
|
-
var assistant: Assistant
|
|
37
|
-
var container: AGIContainer
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// ─── Lifecycle ──────────────────────────────────────────────────
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Runs before the conversation is created. Good for async setup
|
|
44
|
-
* that needs to finish before the assistant is usable.
|
|
45
|
-
*/
|
|
46
|
-
export async function beforeStart() {
|
|
47
|
-
console.log(`[hooks] preparing ${assistant.assistantName}...`)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Conversation is wired — register tools, plugins, extensions.
|
|
52
|
-
* This is the most common hook: equivalent to the old bus-based pattern.
|
|
53
|
-
*/
|
|
54
|
-
export function started() {
|
|
55
|
-
// Give the assistant shell tools
|
|
56
|
-
assistant.use(container.feature('codingTools'))
|
|
57
|
-
|
|
58
|
-
// Add write operations from fileTools
|
|
59
|
-
const fileTools = container.feature('fileTools')
|
|
60
|
-
assistant.use(fileTools.toTools({ only: ['editFile', 'writeFile'] }))
|
|
61
|
-
fileTools.setupToolsConsumer(assistant)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Everything is live. Good for loading state that depends on
|
|
66
|
-
* the conversation being fully initialized. Blocks start().
|
|
67
|
-
*/
|
|
68
|
-
export async function afterStart() {
|
|
69
|
-
// e.g. load a knowledge base into the system prompt
|
|
70
|
-
const fs = container.feature('fs')
|
|
71
|
-
const notesPath = assistant.paths.resolve('notes.md')
|
|
72
|
-
|
|
73
|
-
if (await fs.exists(notesPath)) {
|
|
74
|
-
const notes = await fs.readFile(notesPath)
|
|
75
|
-
assistant.addSystemPromptExtension('notes', `\n## Your Notes\n${notes}`)
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Rewrite the system prompt before the conversation is created.
|
|
81
|
-
* Return the new prompt string.
|
|
82
|
-
*/
|
|
83
|
-
export async function formatSystemPrompt(_assistant: Assistant, prompt: string) {
|
|
84
|
-
const today = new Date().toLocaleDateString('en-US', {
|
|
85
|
-
weekday: 'long', year: 'numeric', month: 'long', day: 'numeric',
|
|
86
|
-
})
|
|
87
|
-
return `${prompt}\n\nToday is ${today}.`
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// ─── Ask Flow ───────────────────────────────────────────────────
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Runs only on the very first ask(). Good for one-time greetings
|
|
94
|
-
* or loading context that depends on the first user message.
|
|
95
|
-
*/
|
|
96
|
-
export async function beforeInitialAsk(_assistant: Assistant, question: string) {
|
|
97
|
-
console.log(`[hooks] first message from user: "${question}"`)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Runs before every ask(). Return a string to rewrite the question.
|
|
102
|
-
* Useful for injecting context the model should see but the user
|
|
103
|
-
* shouldn't have to type every time.
|
|
104
|
-
*/
|
|
105
|
-
export async function beforeAsk(_assistant: Assistant, question: string) {
|
|
106
|
-
// Example: inject recent git context into every question
|
|
107
|
-
const proc = container.feature('proc')
|
|
108
|
-
const { stdout } = await proc.exec('git log --oneline -5 2>/dev/null || true')
|
|
109
|
-
|
|
110
|
-
if (stdout.trim()) {
|
|
111
|
-
return `${question}\n\n<context>\nRecent commits:\n${stdout.trim()}\n</context>`
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Fires after the model responds, before ask() returns.
|
|
117
|
-
* Good for logging, analytics, or auto-saving.
|
|
118
|
-
*/
|
|
119
|
-
export async function answered(_assistant: Assistant, result: string) {
|
|
120
|
-
console.log(`[hooks] response length: ${result.length} chars`)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// ─── Tool Execution ─────────────────────────────────────────────
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Fires before every tool call. The ctx object is mutable:
|
|
127
|
-
* ctx.name — tool name
|
|
128
|
-
* ctx.args — arguments (rewrite to modify)
|
|
129
|
-
* ctx.skip — set true to bypass execution
|
|
130
|
-
* ctx.result — set when skipping to provide a result
|
|
131
|
-
*/
|
|
132
|
-
export async function beforeToolCall(_assistant: Assistant, ctx: any) {
|
|
133
|
-
console.log(`[hooks] tool call: ${ctx.name}(${JSON.stringify(ctx.args)})`)
|
|
134
|
-
|
|
135
|
-
// Example: block dangerous commands
|
|
136
|
-
if (ctx.name === 'runCommand' && ctx.args.command?.includes('rm -rf')) {
|
|
137
|
-
ctx.skip = true
|
|
138
|
-
ctx.result = JSON.stringify({ error: 'Blocked: destructive command not allowed' })
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Fires after every tool call. The ctx object contains:
|
|
144
|
-
* ctx.name — tool name
|
|
145
|
-
* ctx.args — original arguments
|
|
146
|
-
* ctx.result — the result string (rewrite to modify what the model sees)
|
|
147
|
-
* ctx.error — error object if the tool threw
|
|
148
|
-
*/
|
|
149
|
-
export async function afterToolCall(_assistant: Assistant, ctx: any) {
|
|
150
|
-
if (ctx.error) {
|
|
151
|
-
console.error(`[hooks] tool ${ctx.name} failed:`, ctx.error.message)
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// Example: truncate huge tool outputs so they don't blow the context
|
|
155
|
-
if (ctx.result && ctx.result.length > 10000) {
|
|
156
|
-
const truncated = ctx.result.slice(0, 10000)
|
|
157
|
-
ctx.result = `${truncated}\n\n... (truncated from ${ctx.result.length} chars)`
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// ─── Forwarded Conversation Events ──────────────────────────────
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Fires at the start of each completion turn. turn > 1 means
|
|
165
|
-
* the model is continuing after tool calls.
|
|
166
|
-
*/
|
|
167
|
-
export function turnStart(_assistant: Assistant, info: { turn: number; isFollowUp: boolean }) {
|
|
168
|
-
if (info.isFollowUp) {
|
|
169
|
-
console.log(`[hooks] follow-up turn ${info.turn}`)
|
|
170
|
-
}
|
|
171
|
-
}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Assistant with ProcessManager Tools"
|
|
3
|
-
tags: [assistant, processManager, tools, runtime, use]
|
|
4
|
-
lastTested: null
|
|
5
|
-
lastTestPassed: null
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Assistant with ProcessManager Tools
|
|
9
|
-
|
|
10
|
-
Create an assistant at runtime, give it processManager tools, and watch it orchestrate long-running processes — spawning ping and top, checking their output over time, running a quick command in between, then coming back to report.
|
|
11
|
-
|
|
12
|
-
## The Demo
|
|
13
|
-
|
|
14
|
-
```ts
|
|
15
|
-
const pm = container.feature('processManager', { enable: true, autoCleanup: true })
|
|
16
|
-
const ui = container.feature('ui')
|
|
17
|
-
|
|
18
|
-
const assistant = container.feature('assistant', {
|
|
19
|
-
systemPrompt: [
|
|
20
|
-
'You are a process management assistant with tools to spawn, monitor, inspect, and kill background processes.',
|
|
21
|
-
'When asked to check on processes, use getProcessOutput to read their latest output and summarize what you see.',
|
|
22
|
-
'For ping output, parse the lines and calculate the average response time yourself.',
|
|
23
|
-
'For top output, summarize CPU and memory usage from the header lines.',
|
|
24
|
-
'Always be concise — give the data, not a lecture.',
|
|
25
|
-
].join('\n'),
|
|
26
|
-
model: 'gpt-4.1-mini',
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
assistant.use(pm)
|
|
30
|
-
await assistant.start()
|
|
31
|
-
|
|
32
|
-
const tools = Object.keys(assistant.tools)
|
|
33
|
-
console.log(ui.colors.cyan('Tools registered:'), tools.join(', '))
|
|
34
|
-
console.log()
|
|
35
|
-
|
|
36
|
-
// ── Helper to print assistant responses ──────────────────────────────
|
|
37
|
-
const ask = async (label, question) => {
|
|
38
|
-
console.log(ui.colors.dim(`── ${label} ──`))
|
|
39
|
-
console.log(ui.colors.yellow('→'), question.split('\n')[0])
|
|
40
|
-
const response = await assistant.ask(question)
|
|
41
|
-
console.log(ui.markdown(response))
|
|
42
|
-
console.log()
|
|
43
|
-
return response
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Step 1: Spawn long-running processes
|
|
47
|
-
await ask('SPAWN',
|
|
48
|
-
'Spawn two background processes:\n' +
|
|
49
|
-
'1. Ping google.com with tag "ping-google" (use: ping -c 20 google.com)\n' +
|
|
50
|
-
'2. Run top in batch mode with tag "top-monitor" (use: top -l 5 -s 2)\n' +
|
|
51
|
-
'Confirm both are running.'
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
// Step 2: Wait, then check in on their output
|
|
55
|
-
await new Promise(r => setTimeout(r, 4000))
|
|
56
|
-
await ask('CHECK-IN #1',
|
|
57
|
-
'Check on both processes. For ping-google, read the stdout and tell me how many replies so far and the average response time. For top-monitor, read the stdout and tell me the current CPU usage summary.'
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
// Step 3: Quick one-shot command while the others keep going
|
|
61
|
-
await ask('QUICK COMMAND',
|
|
62
|
-
'Run a quick command: "uptime" — tell me the system load averages.'
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
// Step 4: Second check-in — more data should have accumulated
|
|
66
|
-
await new Promise(r => setTimeout(r, 4000))
|
|
67
|
-
await ask('CHECK-IN #2',
|
|
68
|
-
'Check on ping-google again. How many replies now vs last time? What is the average response time? Also list all tracked processes and their status.'
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
// Step 5: Kill everything
|
|
72
|
-
await ask('CLEANUP',
|
|
73
|
-
'Kill all running processes and confirm they are stopped.'
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
// Belt and suspenders
|
|
77
|
-
pm.killAll()
|
|
78
|
-
const remaining = pm.list().filter(h => h.status === 'running')
|
|
79
|
-
console.log(ui.colors.green('Running after cleanup:'), remaining.length)
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
## Summary
|
|
83
|
-
|
|
84
|
-
This example showed a runtime assistant orchestrating real background processes over multiple conversation turns — spawning long-running `ping` and `top` commands, checking in on their output as it accumulates, running a quick `uptime` in between, then coming back for a second check-in before cleaning everything up. The assistant parsed ping times, summarized CPU usage, and managed the full lifecycle without any hardcoded logic — just natural language and processManager tools.
|