luca 3.0.0 → 3.1.0
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 +264 -321
- 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/social.ts +137 -0
- package/commands/try-all-challenges.ts +3 -3
- package/commands/try-challenge.ts +3 -3
- package/datasets/lora/agentic-loop-session-candidates.jsonl +91 -0
- package/datasets/lora/agentic-loop-session-curation-summary.json +123 -0
- package/datasets/lora/luca-session-candidates.jsonl +29 -0
- package/datasets/lora/luca-session-curation-summary.json +121 -0
- package/datasets/lora/review-batch-1.jsonl +30 -0
- package/datasets/lora/review-manifest.json +41 -0
- package/datasets/lora/review-queue.jsonl +120 -0
- package/datasets/lora/review-schema.json +134 -0
- package/datasets/lora/review-template.jsonl +2 -0
- package/datasets/lora/review-ui.html +725 -0
- 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/features/cipher-social.ts +493 -0
- package/index.html +217 -190
- package/luca.console.ts +1 -1
- package/package.json +7 -2
- package/public/index.html +217 -190
- package/public/slides-ai-native.html +1 -1
- package/public/slides-intro.html +2 -2
- package/scripts/curate-claude-sessions.ts +561 -0
- 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 +29596 -27654
- package/src/introspection/generated.node.ts +20284 -19247
- package/src/introspection/generated.web.ts +605 -584
- package/src/introspection/scan.ts +11 -6
- package/src/node/container.ts +9 -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 +46 -7
- 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/socket-repl.ts +336 -0
- package/src/node/features/telnyx-assistant-connector.ts +1206 -0
- package/src/node/features/transpiler.ts +2 -3
- package/src/node/features/ui.ts +5 -0
- package/src/node/features/vm.ts +20 -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/index.ts +0 -1
- 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
|
@@ -135,9 +135,10 @@ export class IntrospectionScannerFeature extends Feature<IntrospectionScannerSta
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
const pattern = path.join(srcPath, '**/*.ts');
|
|
138
|
-
|
|
138
|
+
const files = await glob(pattern, {
|
|
139
139
|
ignore: ['**/*.d.ts', '**/node_modules/**']
|
|
140
140
|
});
|
|
141
|
+
return files.sort();
|
|
141
142
|
}
|
|
142
143
|
|
|
143
144
|
private async analyzeFile(filePath: string): Promise<{ helpers: HelperIntrospection[], containers: Partial<ContainerIntrospection>[] }> {
|
|
@@ -1099,23 +1100,27 @@ export class IntrospectionScannerFeature extends Feature<IntrospectionScannerSta
|
|
|
1099
1100
|
}
|
|
1100
1101
|
imports += ` } from '${importSource}';\n\n`;
|
|
1101
1102
|
|
|
1102
|
-
|
|
1103
|
+
// Sort by id/className for deterministic output across runs
|
|
1104
|
+
const sortedResults = [...results].sort((a, b) => a.id.localeCompare(b.id));
|
|
1105
|
+
const sortedContainers = [...containerResults].sort((a, b) => (a.className || '').localeCompare(b.className || ''));
|
|
1106
|
+
|
|
1107
|
+
const registrations = sortedResults.map(result => {
|
|
1103
1108
|
const data = JSON.stringify(result, null, 2);
|
|
1104
1109
|
return `setBuildTimeData('${result.id}', ${data});`;
|
|
1105
1110
|
}).join('\n\n');
|
|
1106
1111
|
|
|
1107
1112
|
let containerRegistrations = '';
|
|
1108
1113
|
if (hasContainers) {
|
|
1109
|
-
containerRegistrations = '\n\n// Container introspection data\n' +
|
|
1114
|
+
containerRegistrations = '\n\n// Container introspection data\n' + sortedContainers.map(result => {
|
|
1110
1115
|
const data = JSON.stringify(result, null, 2);
|
|
1111
1116
|
return `setContainerBuildTimeData('${result.className}', ${data});`;
|
|
1112
1117
|
}).join('\n\n');
|
|
1113
1118
|
}
|
|
1114
1119
|
|
|
1115
|
-
const exportStatement = `\nexport const introspectionData = ${JSON.stringify(
|
|
1116
|
-
const containerExport = hasContainers ? `\nexport const containerIntrospectionData = ${JSON.stringify(
|
|
1120
|
+
const exportStatement = `\nexport const introspectionData = ${JSON.stringify(sortedResults, null, 2)};\n`;
|
|
1121
|
+
const containerExport = hasContainers ? `\nexport const containerIntrospectionData = ${JSON.stringify(sortedContainers, null, 2)};\n` : '';
|
|
1117
1122
|
|
|
1118
|
-
return `${imports}// Auto-generated introspection registry data\n
|
|
1123
|
+
return `${imports}// Auto-generated introspection registry data\n\n${registrations}${containerRegistrations}${exportStatement}${containerExport}`;
|
|
1119
1124
|
}
|
|
1120
1125
|
}
|
|
1121
1126
|
|
package/src/node/container.ts
CHANGED
|
@@ -64,6 +64,8 @@ import "./features/container-link";
|
|
|
64
64
|
import "./features/semantic-search";
|
|
65
65
|
import "./features/dns";
|
|
66
66
|
import "./features/redis";
|
|
67
|
+
import "./features/socket-repl";
|
|
68
|
+
import "./features/telnyx-assistant-connector";
|
|
67
69
|
|
|
68
70
|
import type { ChildProcess } from "./features/proc";
|
|
69
71
|
import type { DiskCache } from "./features/disk-cache";
|
|
@@ -108,6 +110,8 @@ import type { ContainerLink } from './features/container-link';
|
|
|
108
110
|
import type { SemanticSearch } from './features/semantic-search';
|
|
109
111
|
import type { Dns } from './features/dns';
|
|
110
112
|
import type { Redis } from './features/redis';
|
|
113
|
+
import type { SocketRepl } from './features/socket-repl';
|
|
114
|
+
import type { TelnyxAssistantConnector } from './features/telnyx-assistant-connector';
|
|
111
115
|
export { State };
|
|
112
116
|
|
|
113
117
|
export {
|
|
@@ -147,6 +151,8 @@ export {
|
|
|
147
151
|
type SemanticSearch,
|
|
148
152
|
type Dns,
|
|
149
153
|
type Redis,
|
|
154
|
+
type SocketRepl,
|
|
155
|
+
type TelnyxAssistantConnector,
|
|
150
156
|
type Transpiler,
|
|
151
157
|
};
|
|
152
158
|
|
|
@@ -213,6 +219,8 @@ export interface NodeFeatures extends AvailableFeatures {
|
|
|
213
219
|
semanticSearch: typeof SemanticSearch;
|
|
214
220
|
dns: typeof Dns;
|
|
215
221
|
redis: typeof Redis;
|
|
222
|
+
socketRepl: typeof SocketRepl;
|
|
223
|
+
telnyxAssistantConnector: typeof TelnyxAssistantConnector;
|
|
216
224
|
}
|
|
217
225
|
|
|
218
226
|
export type ClientsAndServersInterface = ClientsInterface & ServersInterface & CommandsInterface & EndpointsInterface & SelectorsInterface;
|
|
@@ -240,7 +248,7 @@ export interface NodeContainerState extends ContainerState {
|
|
|
240
248
|
*
|
|
241
249
|
* @example
|
|
242
250
|
* ```ts
|
|
243
|
-
* import container from '
|
|
251
|
+
* import container from 'luca/node'
|
|
244
252
|
*
|
|
245
253
|
* // File operations
|
|
246
254
|
* const content = container.fs.readFile('README.md')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Feature } from '../feature.js'
|
|
2
2
|
import * as contentbaseExports from 'contentbase'
|
|
3
|
-
import { parse, Collection, extractSections, type ModelDefinition } from 'contentbase'
|
|
3
|
+
import { parse, Collection, Document, extractSections, type ModelDefinition } from 'contentbase'
|
|
4
4
|
import { z } from 'zod'
|
|
5
5
|
import { FeatureStateSchema, FeatureOptionsSchema, FeatureEventsSchema } from '../../schemas/base.js'
|
|
6
6
|
import { realpathSync } from 'node:fs'
|
|
@@ -184,7 +184,7 @@ export class ContentDb extends Feature<ContentDbState, ContentDbOptions> {
|
|
|
184
184
|
|
|
185
185
|
const vm = this.container.feature('vm') as any
|
|
186
186
|
|
|
187
|
-
// Seed luca modules first (helpers does this for
|
|
187
|
+
// Seed luca modules first (helpers does this for luca)
|
|
188
188
|
const helpers = this.container.feature('helpers') as any
|
|
189
189
|
if (helpers?.seedVirtualModules) {
|
|
190
190
|
helpers.seedVirtualModules()
|
|
@@ -300,6 +300,43 @@ export class ContentDb extends Feature<ContentDbState, ContentDbOptions> {
|
|
|
300
300
|
return parse(path)
|
|
301
301
|
}
|
|
302
302
|
|
|
303
|
+
/**
|
|
304
|
+
* Get a document object by collection ID, file path, or inline markdown string.
|
|
305
|
+
* Exactly one of `id`, `path`, or `content` must be provided.
|
|
306
|
+
*
|
|
307
|
+
* @param options.id - Collection document ID (e.g. `'guides/intro'`); auto-loads the collection if needed
|
|
308
|
+
* @param options.path - Absolute or relative path to a markdown file on disk
|
|
309
|
+
* @param options.content - Raw markdown string; returned as an in-memory Document
|
|
310
|
+
* @returns The Document instance
|
|
311
|
+
* @example
|
|
312
|
+
* ```typescript
|
|
313
|
+
* // By collection document ID
|
|
314
|
+
* const doc = await contentDb.document({ id: 'guides/intro' })
|
|
315
|
+
*
|
|
316
|
+
* // By file path
|
|
317
|
+
* const doc = await contentDb.document({ path: '/absolute/path/to/file.md' })
|
|
318
|
+
*
|
|
319
|
+
* // In-memory from a markdown string
|
|
320
|
+
* const doc = contentDb.document({ content: '# Hello\n\nworld' })
|
|
321
|
+
* ```
|
|
322
|
+
*/
|
|
323
|
+
async document(options: { id: string; path?: never; content?: never } | { path: string; id?: never; content?: never } | { content: string; id?: never; path?: never }): Promise<Document> {
|
|
324
|
+
if ('content' in options && options.content != null) {
|
|
325
|
+
return new Document({ content: options.content, path: '/virtual/document.md' })
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if ('path' in options && options.path != null) {
|
|
329
|
+
return parse(options.path) as unknown as Document
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if ('id' in options && options.id != null) {
|
|
333
|
+
if (!this.isLoaded) await this.load()
|
|
334
|
+
return this.collection.document(options.id) as unknown as Document
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
throw new Error('document() requires exactly one of: id, path, or content')
|
|
338
|
+
}
|
|
339
|
+
|
|
303
340
|
/**
|
|
304
341
|
* Load the collection, discovering models from models.ts and parsing all documents.
|
|
305
342
|
*
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { inspect } from 'util'
|
|
2
|
+
|
|
3
|
+
const BUILTIN_TYPES = new Set(['Object', 'Array', 'Map', 'Set', 'Date', 'RegExp', 'Promise', 'Error', 'Number', 'String', 'Boolean'])
|
|
4
|
+
|
|
5
|
+
export function displayResult(value: any) {
|
|
6
|
+
if (typeof value !== 'object' || value === null) {
|
|
7
|
+
console.log(value)
|
|
8
|
+
return
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const hasCustomInspect = typeof value[Symbol.for('nodejs.util.inspect.custom')] === 'function'
|
|
12
|
+
const ctorName = value.constructor?.name
|
|
13
|
+
const isClassInstance = ctorName && !BUILTIN_TYPES.has(ctorName)
|
|
14
|
+
|
|
15
|
+
// Objects with custom inspect or builtins: use standard inspect
|
|
16
|
+
if (hasCustomInspect || !isClassInstance) {
|
|
17
|
+
console.log(inspect(value, { colors: true, depth: 4 }))
|
|
18
|
+
return
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Class instances: show clean data (no _ props, no functions)
|
|
22
|
+
const data: Record<string, any> = {}
|
|
23
|
+
for (const [k, v] of Object.entries(value)) {
|
|
24
|
+
if (k.startsWith('_') || typeof v === 'function') continue
|
|
25
|
+
data[k] = v
|
|
26
|
+
}
|
|
27
|
+
const body = inspect(data, { colors: true, depth: 3 })
|
|
28
|
+
console.log(`${ctorName} ${body}`)
|
|
29
|
+
|
|
30
|
+
// Collect methods and getters from own + prototype chain
|
|
31
|
+
const methods: string[] = []
|
|
32
|
+
const getters: string[] = []
|
|
33
|
+
|
|
34
|
+
for (const [k, v] of Object.entries(value)) {
|
|
35
|
+
if (k.startsWith('_')) continue
|
|
36
|
+
if (typeof v === 'function') methods.push(k)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let proto = Object.getPrototypeOf(value)
|
|
40
|
+
while (proto && proto !== Object.prototype) {
|
|
41
|
+
for (const k of Object.getOwnPropertyNames(proto)) {
|
|
42
|
+
if (k === 'constructor' || k.startsWith('_')) continue
|
|
43
|
+
const desc = Object.getOwnPropertyDescriptor(proto, k)
|
|
44
|
+
if (!desc) continue
|
|
45
|
+
if (desc.get && !getters.includes(k)) getters.push(k)
|
|
46
|
+
else if (typeof desc.value === 'function' && !methods.includes(k)) methods.push(k)
|
|
47
|
+
}
|
|
48
|
+
proto = Object.getPrototypeOf(proto)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (getters.length || methods.length) {
|
|
52
|
+
const parts: string[] = []
|
|
53
|
+
if (getters.length) parts.push(` \x1b[36mgetters:\x1b[0m ${getters.sort().join(', ')}`)
|
|
54
|
+
if (methods.length) parts.push(` \x1b[36mmethods:\x1b[0m ${methods.sort().map(m => m + '()').join(', ')}`)
|
|
55
|
+
console.log(parts.join('\n'))
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -3,6 +3,8 @@ import { FeatureStateSchema, FeatureOptionsSchema, FeatureEventsSchema } from '.
|
|
|
3
3
|
import { Feature } from '../feature.js'
|
|
4
4
|
import { Feature as UniversalFeature } from '../../feature.js'
|
|
5
5
|
import { Client, clients } from '../../client.js'
|
|
6
|
+
import { allHelperInstances } from '../../container.js'
|
|
7
|
+
import type { Helper } from '../../helper.js'
|
|
6
8
|
import { RestClient } from '../../clients/rest.js'
|
|
7
9
|
import { GraphClient } from '../../clients/graph.js'
|
|
8
10
|
import { WebSocketClient } from '../../clients/websocket.js'
|
|
@@ -108,14 +110,14 @@ export class Helpers extends Feature<HelpersState, HelpersOptions> {
|
|
|
108
110
|
|
|
109
111
|
/**
|
|
110
112
|
* Whether to use native `import()` for loading project helpers.
|
|
111
|
-
* True only if
|
|
113
|
+
* True only if `luca` is actually resolvable in `node_modules`.
|
|
112
114
|
* Warns when `node_modules` exists but the package is missing.
|
|
113
115
|
*/
|
|
114
116
|
get useNativeImport(): boolean {
|
|
115
117
|
const hasNodeModules = existsSync(resolve(this.rootDir, 'node_modules'))
|
|
116
118
|
const hasLuca = hasNodeModules && existsSync(resolve(this.rootDir, 'node_modules', '@soederpop', 'luca'))
|
|
117
119
|
|
|
118
|
-
// VM bundling handles missing
|
|
120
|
+
// VM bundling handles missing luca gracefully — no warning needed
|
|
119
121
|
|
|
120
122
|
return hasLuca
|
|
121
123
|
}
|
|
@@ -126,7 +128,7 @@ export class Helpers extends Feature<HelpersState, HelpersOptions> {
|
|
|
126
128
|
|
|
127
129
|
/**
|
|
128
130
|
* Seeds the VM feature with virtual modules so that project-level files
|
|
129
|
-
* can `import` / `require('
|
|
131
|
+
* can `import` / `require('luca')`, `zod`, etc. without
|
|
130
132
|
* needing them in `node_modules`.
|
|
131
133
|
*
|
|
132
134
|
* Called automatically when `useNativeImport` is false.
|
|
@@ -138,7 +140,7 @@ export class Helpers extends Feature<HelpersState, HelpersOptions> {
|
|
|
138
140
|
|
|
139
141
|
const vm = this.container.feature('vm') as unknown as VM
|
|
140
142
|
|
|
141
|
-
// Provide the full
|
|
143
|
+
// Provide the full luca barrel — everything node.ts exports
|
|
142
144
|
// We build the exports object from the already-loaded modules in memory
|
|
143
145
|
const lucaExports: Record<string, any> = {
|
|
144
146
|
// Core classes
|
|
@@ -208,11 +210,23 @@ export class Helpers extends Feature<HelpersState, HelpersOptions> {
|
|
|
208
210
|
schemasModule.FeatureEventsSchema = FeatureEventsSchema
|
|
209
211
|
}
|
|
210
212
|
|
|
213
|
+
vm.defineModule('luca', lucaExports)
|
|
214
|
+
vm.defineModule('luca/schemas', schemasModule)
|
|
215
|
+
vm.defineModule('luca/node', lucaExports)
|
|
216
|
+
|
|
217
|
+
// Deep import paths AIs and developers might reach for
|
|
218
|
+
vm.defineModule('luca/client', { Client, ClientsRegistry: clients.constructor, default: Client })
|
|
219
|
+
vm.defineModule('luca/server', { Server, ServersRegistry: servers.constructor, default: Server })
|
|
220
|
+
vm.defineModule('luca/clients/rest', { RestClient, default: RestClient })
|
|
221
|
+
vm.defineModule('luca/clients/graph', { GraphClient, default: GraphClient })
|
|
222
|
+
vm.defineModule('luca/clients/websocket', { WebSocketClient, default: WebSocketClient })
|
|
223
|
+
vm.defineModule('luca/servers/express', { ExpressServer, default: ExpressServer })
|
|
224
|
+
vm.defineModule('luca/servers/socket', { WebsocketServer, default: WebsocketServer })
|
|
225
|
+
|
|
226
|
+
// Legacy package name aliases for backwards compatibility
|
|
211
227
|
vm.defineModule('@soederpop/luca', lucaExports)
|
|
212
228
|
vm.defineModule('@soederpop/luca/schemas', schemasModule)
|
|
213
229
|
vm.defineModule('@soederpop/luca/node', lucaExports)
|
|
214
|
-
|
|
215
|
-
// Deep import paths AIs and developers might reach for
|
|
216
230
|
vm.defineModule('@soederpop/luca/client', { Client, ClientsRegistry: clients.constructor, default: Client })
|
|
217
231
|
vm.defineModule('@soederpop/luca/server', { Server, ServersRegistry: servers.constructor, default: Server })
|
|
218
232
|
vm.defineModule('@soederpop/luca/clients/rest', { RestClient, default: RestClient })
|
|
@@ -224,6 +238,26 @@ export class Helpers extends Feature<HelpersState, HelpersOptions> {
|
|
|
224
238
|
vm.defineModule('zod', { z, default: { z } })
|
|
225
239
|
}
|
|
226
240
|
|
|
241
|
+
/**
|
|
242
|
+
* Returns all instantiated helper instances across all types, optionally filtered by class.
|
|
243
|
+
*
|
|
244
|
+
* @param FilterClass - When provided, only instances of this class are returned.
|
|
245
|
+
*
|
|
246
|
+
* @example
|
|
247
|
+
* ```typescript
|
|
248
|
+
* // All instances of any type
|
|
249
|
+
* container.helpers.getInstances()
|
|
250
|
+
*
|
|
251
|
+
* // All Assistant instances
|
|
252
|
+
* const assistants = container.helpers.getInstances(Assistant)
|
|
253
|
+
* ```
|
|
254
|
+
*/
|
|
255
|
+
getInstances(): Helper[]
|
|
256
|
+
getInstances<T extends Helper>(FilterClass: new (...args: any[]) => T): T[]
|
|
257
|
+
getInstances<T extends Helper>(FilterClass?: new (...args: any[]) => T): Helper[] | T[] {
|
|
258
|
+
return FilterClass ? allHelperInstances(FilterClass) : allHelperInstances()
|
|
259
|
+
}
|
|
260
|
+
|
|
227
261
|
/**
|
|
228
262
|
* Returns a unified view of all available helpers across all registries.
|
|
229
263
|
* Each key is a registry type, each value is the list of helper names in that registry.
|
|
@@ -458,7 +492,11 @@ export class Helpers extends Feature<HelpersState, HelpersOptions> {
|
|
|
458
492
|
try {
|
|
459
493
|
const fm = await this.ensureFileManager()
|
|
460
494
|
const absPatterns = [`${dir}/*.ts`, `${dir}/**/*.ts`]
|
|
461
|
-
|
|
495
|
+
// Only use relative patterns when rootDir matches the container cwd,
|
|
496
|
+
// otherwise the fileManager (rooted in cwd) returns files from the
|
|
497
|
+
// wrong project which then get resolved against this.rootDir.
|
|
498
|
+
const useRelative = this.rootDir === this.container.cwd
|
|
499
|
+
const relPatterns = useRelative ? [`${type}/*.ts`, `${type}/**/*.ts`] : []
|
|
462
500
|
const matched = fm.match([...absPatterns, ...relPatterns])
|
|
463
501
|
files = matched.map((f: string) => f.startsWith('/') ? f : resolve(this.rootDir, f))
|
|
464
502
|
} catch {}
|
|
@@ -608,6 +646,7 @@ export class Helpers extends Feature<HelpersState, HelpersOptions> {
|
|
|
608
646
|
const Grafted = graftModule(Command as any, {
|
|
609
647
|
description: commandModule.description,
|
|
610
648
|
argsSchema: commandModule.argsSchema,
|
|
649
|
+
positionals: commandModule.positionals ?? mod.positionals,
|
|
611
650
|
handler: commandModule.handler,
|
|
612
651
|
}, name, 'commands')
|
|
613
652
|
commands.register(name, Grafted as any)
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod'
|
|
2
2
|
import { FeatureStateSchema, FeatureOptionsSchema, FeatureEventsSchema } from '../../schemas/base.js'
|
|
3
3
|
import { Feature } from "../feature.js";
|
|
4
|
-
import { existsSync } from 'fs';
|
|
5
|
-
import { join, resolve } from 'path';
|
|
6
4
|
import { tmpdir } from 'os';
|
|
7
5
|
import { bridgeScript } from '../../python/generated.js';
|
|
8
6
|
import type { ChildProcess } from 'child_process';
|
|
@@ -161,7 +159,7 @@ export class Python<
|
|
|
161
159
|
|
|
162
160
|
// Setup project directory
|
|
163
161
|
if (this.options.dir) {
|
|
164
|
-
this.state.set('projectDir', resolve(this.options.dir))
|
|
162
|
+
this.state.set('projectDir', this.container.paths.resolve(this.options.dir))
|
|
165
163
|
} else {
|
|
166
164
|
this.state.set('projectDir', this.container.cwd)
|
|
167
165
|
}
|
|
@@ -170,7 +168,7 @@ export class Python<
|
|
|
170
168
|
await this.detectEnvironment()
|
|
171
169
|
|
|
172
170
|
// Execute context script if provided
|
|
173
|
-
if (this.options.contextScript &&
|
|
171
|
+
if (this.options.contextScript && this.container.feature('fs').exists(this.options.contextScript)) {
|
|
174
172
|
await this.execute(`exec(open('${this.options.contextScript}').read())`)
|
|
175
173
|
}
|
|
176
174
|
|
|
@@ -217,6 +215,8 @@ export class Python<
|
|
|
217
215
|
let environmentType: PythonState['environmentType'] = null
|
|
218
216
|
|
|
219
217
|
const proc = this.container.feature('proc')
|
|
218
|
+
const fs = this.container.feature('fs')
|
|
219
|
+
const paths = this.container.paths
|
|
220
220
|
|
|
221
221
|
/** Resolve a binary to its full path via `which`, falling back to the bare name. */
|
|
222
222
|
const resolveBin = (name: string): string => {
|
|
@@ -228,12 +228,14 @@ export class Python<
|
|
|
228
228
|
pythonPath = this.options.pythonPath
|
|
229
229
|
environmentType = 'system'
|
|
230
230
|
}
|
|
231
|
-
|
|
232
|
-
|
|
231
|
+
|
|
232
|
+
// Check for uv — independent so a missing uv binary falls through to conda/venv
|
|
233
|
+
if (!pythonPath && (fs.exists(paths.resolve(projectDir, 'uv.lock')) || fs.exists(paths.resolve(projectDir, 'pyproject.toml')))) {
|
|
233
234
|
try {
|
|
234
235
|
const uvBin = resolveBin('uv')
|
|
235
236
|
const result = await proc.execAndCapture(`${uvBin} run python --version`)
|
|
236
|
-
|
|
237
|
+
// execAndCapture returns exitCode 0 on ENOENT — check result.error to confirm the binary actually ran
|
|
238
|
+
if (result.exitCode === 0 && !result.error) {
|
|
237
239
|
pythonPath = `${uvBin} run python`
|
|
238
240
|
environmentType = 'uv'
|
|
239
241
|
}
|
|
@@ -241,12 +243,13 @@ export class Python<
|
|
|
241
243
|
// Fall through to next detection method
|
|
242
244
|
}
|
|
243
245
|
}
|
|
246
|
+
|
|
244
247
|
// Check for conda
|
|
245
|
-
|
|
248
|
+
if (!pythonPath && (fs.exists(paths.resolve(projectDir, 'environment.yml')) || fs.exists(paths.resolve(projectDir, 'conda.yml')))) {
|
|
246
249
|
try {
|
|
247
250
|
const condaBin = resolveBin('conda')
|
|
248
251
|
const result = await proc.execAndCapture(`${condaBin} run python --version`)
|
|
249
|
-
if (result.exitCode === 0) {
|
|
252
|
+
if (result.exitCode === 0 && !result.error) {
|
|
250
253
|
pythonPath = `${condaBin} run python`
|
|
251
254
|
environmentType = 'conda'
|
|
252
255
|
}
|
|
@@ -254,14 +257,15 @@ export class Python<
|
|
|
254
257
|
// Fall through to next detection method
|
|
255
258
|
}
|
|
256
259
|
}
|
|
260
|
+
|
|
257
261
|
// Check for venv
|
|
258
|
-
|
|
259
|
-
const venvPath =
|
|
262
|
+
if (!pythonPath && (fs.exists(paths.resolve(projectDir, 'venv')) || fs.exists(paths.resolve(projectDir, '.venv')))) {
|
|
263
|
+
const venvPath = fs.exists(paths.resolve(projectDir, 'venv')) ? 'venv' : '.venv'
|
|
260
264
|
const venvPython = process.platform === 'win32'
|
|
261
|
-
?
|
|
262
|
-
:
|
|
265
|
+
? paths.resolve(projectDir, venvPath, 'Scripts', 'python.exe')
|
|
266
|
+
: paths.resolve(projectDir, venvPath, 'bin', 'python')
|
|
263
267
|
|
|
264
|
-
if (
|
|
268
|
+
if (fs.exists(venvPython)) {
|
|
265
269
|
pythonPath = venvPython
|
|
266
270
|
environmentType = 'venv'
|
|
267
271
|
}
|
|
@@ -317,6 +321,8 @@ export class Python<
|
|
|
317
321
|
*/
|
|
318
322
|
async installDependencies(): Promise<{ stdout: string; stderr: string; exitCode: number }> {
|
|
319
323
|
const proc = this.container.feature('proc')
|
|
324
|
+
const fs = this.container.feature('fs')
|
|
325
|
+
const paths = this.container.paths
|
|
320
326
|
const projectDir = this.state.get('projectDir')!
|
|
321
327
|
const environmentType = this.state.get('environmentType')
|
|
322
328
|
|
|
@@ -330,9 +336,9 @@ export class Python<
|
|
|
330
336
|
installCommand = 'uv sync'
|
|
331
337
|
break
|
|
332
338
|
case 'conda':
|
|
333
|
-
if (
|
|
339
|
+
if (fs.exists(paths.resolve(projectDir, 'environment.yml'))) {
|
|
334
340
|
installCommand = 'conda env update -f environment.yml'
|
|
335
|
-
} else if (
|
|
341
|
+
} else if (fs.exists(paths.resolve(projectDir, 'conda.yml'))) {
|
|
336
342
|
installCommand = 'conda env update -f conda.yml'
|
|
337
343
|
} else {
|
|
338
344
|
installCommand = 'conda install --file requirements.txt'
|
|
@@ -341,10 +347,10 @@ export class Python<
|
|
|
341
347
|
case 'venv':
|
|
342
348
|
case 'system':
|
|
343
349
|
default:
|
|
344
|
-
if (
|
|
350
|
+
if (fs.exists(paths.resolve(projectDir, 'requirements.txt'))) {
|
|
345
351
|
const pythonPath = this.state.get('pythonPath')!
|
|
346
352
|
installCommand = `${pythonPath} -m pip install -r requirements.txt`
|
|
347
|
-
} else if (
|
|
353
|
+
} else if (fs.exists(paths.resolve(projectDir, 'pyproject.toml'))) {
|
|
348
354
|
const pythonPath = this.state.get('pythonPath')!
|
|
349
355
|
installCommand = `${pythonPath} -m pip install -e .`
|
|
350
356
|
} else {
|
|
@@ -406,7 +412,7 @@ export class Python<
|
|
|
406
412
|
// Create temporary script in system temp dir (not inside the project)
|
|
407
413
|
const tempDir = `${tmpdir()}/luca-python-temp`
|
|
408
414
|
await fs.ensureFolder(tempDir)
|
|
409
|
-
const scriptPath =
|
|
415
|
+
const scriptPath = this.container.paths.resolve(tempDir, `script-${Date.now()}.py`)
|
|
410
416
|
|
|
411
417
|
// Build the Python script
|
|
412
418
|
let script = ''
|
|
@@ -3,7 +3,7 @@ import { FeatureStateSchema, FeatureOptionsSchema } from '../../schemas/base.js'
|
|
|
3
3
|
import { Feature } from "../feature.js";
|
|
4
4
|
import vm from 'vm'
|
|
5
5
|
import readline from 'readline'
|
|
6
|
-
import { displayResult } from '
|
|
6
|
+
import { displayResult } from './display-result.js'
|
|
7
7
|
|
|
8
8
|
export const ReplStateSchema = FeatureStateSchema.extend({
|
|
9
9
|
started: z.boolean().optional().describe('Whether the REPL server has been started'),
|
|
@@ -109,8 +109,8 @@ export class SecureShell extends Feature<SecureShellState, SecureShellOptions> {
|
|
|
109
109
|
sshCmd += ` -i "${key}"`
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
//
|
|
113
|
-
sshCmd += ` -o StrictHostKeyChecking=no`
|
|
112
|
+
// Batch mode fails immediately instead of hanging on interactive prompts
|
|
113
|
+
sshCmd += ` -o BatchMode=yes -o StrictHostKeyChecking=no`
|
|
114
114
|
|
|
115
115
|
sshCmd += ` ${username}@${host}`
|
|
116
116
|
|
|
@@ -129,8 +129,8 @@ export class SecureShell extends Feature<SecureShellState, SecureShellOptions> {
|
|
|
129
129
|
scpCmd += ` -i "${key}"`
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
//
|
|
133
|
-
scpCmd += ` -o StrictHostKeyChecking=no`
|
|
132
|
+
// Batch mode fails immediately instead of hanging on interactive prompts
|
|
133
|
+
scpCmd += ` -o BatchMode=yes -o StrictHostKeyChecking=no`
|
|
134
134
|
|
|
135
135
|
return scpCmd
|
|
136
136
|
}
|
|
@@ -150,18 +150,12 @@ export class SecureShell extends Feature<SecureShellState, SecureShellOptions> {
|
|
|
150
150
|
* ```
|
|
151
151
|
*/
|
|
152
152
|
async testConnection(): Promise<boolean> {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
return true
|
|
160
|
-
} else {
|
|
161
|
-
this.setState({ connected: false })
|
|
162
|
-
return false
|
|
163
|
-
}
|
|
164
|
-
} catch (error) {
|
|
153
|
+
const result = await this.exec(`echo 'connected'`).catch(e => '')
|
|
154
|
+
|
|
155
|
+
if (String(result).trim() === 'connected') {
|
|
156
|
+
this.setState({ connected: true })
|
|
157
|
+
return true
|
|
158
|
+
} else {
|
|
165
159
|
this.setState({ connected: false })
|
|
166
160
|
return false
|
|
167
161
|
}
|
|
@@ -264,4 +258,4 @@ export class SecureShell extends Feature<SecureShellState, SecureShellOptions> {
|
|
|
264
258
|
}
|
|
265
259
|
}
|
|
266
260
|
|
|
267
|
-
export default SecureShell
|
|
261
|
+
export default SecureShell
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod'
|
|
2
2
|
import { FeatureStateSchema, FeatureOptionsSchema, FeatureEventsSchema } from '../../schemas/base.js'
|
|
3
|
-
import { type AvailableFeatures } from '
|
|
3
|
+
import { type AvailableFeatures } from 'luca/feature'
|
|
4
4
|
import { Feature } from '../feature.js'
|
|
5
5
|
import { Database } from 'bun:sqlite'
|
|
6
6
|
import { createHash } from 'node:crypto'
|
|
@@ -8,7 +8,7 @@ import { mkdirSync, existsSync, statSync } from 'node:fs'
|
|
|
8
8
|
import { dirname, join } from 'node:path'
|
|
9
9
|
import { homedir } from 'node:os'
|
|
10
10
|
|
|
11
|
-
declare module '
|
|
11
|
+
declare module 'luca/feature' {
|
|
12
12
|
interface AvailableFeatures {
|
|
13
13
|
semanticSearch: typeof SemanticSearch
|
|
14
14
|
}
|