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
|
@@ -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
|
@@ -240,7 +240,7 @@ export interface NodeContainerState extends ContainerState {
|
|
|
240
240
|
*
|
|
241
241
|
* @example
|
|
242
242
|
* ```ts
|
|
243
|
-
* import container from '
|
|
243
|
+
* import container from 'luca/node'
|
|
244
244
|
*
|
|
245
245
|
* // File operations
|
|
246
246
|
* 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,22 +210,42 @@ export class Helpers extends Feature<HelpersState, HelpersOptions> {
|
|
|
208
210
|
schemasModule.FeatureEventsSchema = FeatureEventsSchema
|
|
209
211
|
}
|
|
210
212
|
|
|
211
|
-
vm.defineModule('
|
|
212
|
-
vm.defineModule('
|
|
213
|
-
vm.defineModule('
|
|
213
|
+
vm.defineModule('luca', lucaExports)
|
|
214
|
+
vm.defineModule('luca/schemas', schemasModule)
|
|
215
|
+
vm.defineModule('luca/node', lucaExports)
|
|
214
216
|
|
|
215
217
|
// Deep import paths AIs and developers might reach for
|
|
216
|
-
vm.defineModule('
|
|
217
|
-
vm.defineModule('
|
|
218
|
-
vm.defineModule('
|
|
219
|
-
vm.defineModule('
|
|
220
|
-
vm.defineModule('
|
|
221
|
-
vm.defineModule('
|
|
222
|
-
vm.defineModule('
|
|
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 })
|
|
223
225
|
|
|
224
226
|
vm.defineModule('zod', { z, default: { z } })
|
|
225
227
|
}
|
|
226
228
|
|
|
229
|
+
/**
|
|
230
|
+
* Returns all instantiated helper instances across all types, optionally filtered by class.
|
|
231
|
+
*
|
|
232
|
+
* @param FilterClass - When provided, only instances of this class are returned.
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```typescript
|
|
236
|
+
* // All instances of any type
|
|
237
|
+
* container.helpers.getInstances()
|
|
238
|
+
*
|
|
239
|
+
* // All Assistant instances
|
|
240
|
+
* const assistants = container.helpers.getInstances(Assistant)
|
|
241
|
+
* ```
|
|
242
|
+
*/
|
|
243
|
+
getInstances(): Helper[]
|
|
244
|
+
getInstances<T extends Helper>(FilterClass: new (...args: any[]) => T): T[]
|
|
245
|
+
getInstances<T extends Helper>(FilterClass?: new (...args: any[]) => T): Helper[] | T[] {
|
|
246
|
+
return FilterClass ? allHelperInstances(FilterClass) : allHelperInstances()
|
|
247
|
+
}
|
|
248
|
+
|
|
227
249
|
/**
|
|
228
250
|
* Returns a unified view of all available helpers across all registries.
|
|
229
251
|
* Each key is a registry type, each value is the list of helper names in that registry.
|
|
@@ -458,7 +480,11 @@ export class Helpers extends Feature<HelpersState, HelpersOptions> {
|
|
|
458
480
|
try {
|
|
459
481
|
const fm = await this.ensureFileManager()
|
|
460
482
|
const absPatterns = [`${dir}/*.ts`, `${dir}/**/*.ts`]
|
|
461
|
-
|
|
483
|
+
// Only use relative patterns when rootDir matches the container cwd,
|
|
484
|
+
// otherwise the fileManager (rooted in cwd) returns files from the
|
|
485
|
+
// wrong project which then get resolved against this.rootDir.
|
|
486
|
+
const useRelative = this.rootDir === this.container.cwd
|
|
487
|
+
const relPatterns = useRelative ? [`${type}/*.ts`, `${type}/**/*.ts`] : []
|
|
462
488
|
const matched = fm.match([...absPatterns, ...relPatterns])
|
|
463
489
|
files = matched.map((f: string) => f.startsWith('/') ? f : resolve(this.rootDir, f))
|
|
464
490
|
} catch {}
|
|
@@ -608,6 +634,7 @@ export class Helpers extends Feature<HelpersState, HelpersOptions> {
|
|
|
608
634
|
const Grafted = graftModule(Command as any, {
|
|
609
635
|
description: commandModule.description,
|
|
610
636
|
argsSchema: commandModule.argsSchema,
|
|
637
|
+
positionals: commandModule.positionals ?? mod.positionals,
|
|
611
638
|
handler: commandModule.handler,
|
|
612
639
|
}, name, 'commands')
|
|
613
640
|
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
|
}
|
|
@@ -145,16 +145,15 @@ export class Transpiler extends Feature {
|
|
|
145
145
|
entrypoints: [filePath],
|
|
146
146
|
target: 'bun',
|
|
147
147
|
format: 'cjs',
|
|
148
|
-
bundle: true,
|
|
149
148
|
external,
|
|
150
|
-
})
|
|
149
|
+
} as any)
|
|
151
150
|
|
|
152
151
|
if (!result.success) {
|
|
153
152
|
const msgs = result.logs.map((l: any) => l.message || String(l)).join('\n')
|
|
154
153
|
throw new Error(`Bundle failed for ${filePath}:\n${msgs}`)
|
|
155
154
|
}
|
|
156
155
|
|
|
157
|
-
return await result.outputs[0]
|
|
156
|
+
return await result.outputs[0]!.text()
|
|
158
157
|
}
|
|
159
158
|
}
|
|
160
159
|
|
package/src/node/features/ui.ts
CHANGED
|
@@ -72,6 +72,11 @@ export class UI<T extends UIState = UIState> extends Feature<T> {
|
|
|
72
72
|
print: ColoredPrintFunction = Object.assign((...args: any[]) => {
|
|
73
73
|
return console.log(...args)
|
|
74
74
|
}, {
|
|
75
|
+
error: (text: string) => console.log(colors.red(text)),
|
|
76
|
+
info: (text: string) => console.log(text),
|
|
77
|
+
success: (text: string) => console.log(colors.green(text)),
|
|
78
|
+
warn: (text: string) => console.log(colors.yellow(text)),
|
|
79
|
+
warning: (text: string) => console.log(colors.yellow(text)),
|
|
75
80
|
red: (text: string) => console.log(colors.red(text)),
|
|
76
81
|
green: (text: string) => console.log(colors.green(text)),
|
|
77
82
|
blue: (text: string) => console.log(colors.blue(text)),
|
package/src/node/features/vm.ts
CHANGED
|
@@ -55,17 +55,17 @@ export class VM<
|
|
|
55
55
|
* Register a virtual module that will be available to `require()` inside VM-executed code.
|
|
56
56
|
* Modules registered here take precedence over Node's native resolution.
|
|
57
57
|
*
|
|
58
|
-
* @param id - The module specifier (e.g. `'
|
|
58
|
+
* @param id - The module specifier (e.g. `'luca'`, `'zod'`)
|
|
59
59
|
* @param exports - The module's exports object
|
|
60
60
|
*
|
|
61
61
|
* @example
|
|
62
62
|
* ```typescript
|
|
63
63
|
* const vm = container.feature('vm')
|
|
64
|
-
* vm.defineModule('
|
|
64
|
+
* vm.defineModule('luca', { Container, Feature, fs, proc })
|
|
65
65
|
* vm.defineModule('zod', { z })
|
|
66
66
|
*
|
|
67
67
|
* // Now loadModule can resolve these in user code:
|
|
68
|
-
* // import { Container } from '
|
|
68
|
+
* // import { Container } from 'luca' → works
|
|
69
69
|
* ```
|
|
70
70
|
*/
|
|
71
71
|
defineModule(id: string, exports: any): void {
|
package/src/node.ts
CHANGED
|
@@ -17,7 +17,7 @@ export default container as NodeContainer
|
|
|
17
17
|
export function createContainer() {
|
|
18
18
|
console.warn(
|
|
19
19
|
'[luca] createContainer() is unnecessary — import the default export instead.\n' +
|
|
20
|
-
' `import container from "
|
|
20
|
+
' `import container from "luca"`\n' +
|
|
21
21
|
' For a separate instance, use container.subcontainer().'
|
|
22
22
|
)
|
|
23
23
|
return container
|
|
@@ -45,7 +45,7 @@ export { Client, ClientsRegistry } from './client'
|
|
|
45
45
|
export { RestClient } from './clients/rest'
|
|
46
46
|
export { GraphClient } from './clients/graph'
|
|
47
47
|
export { WebSocketClient } from './clients/websocket'
|
|
48
|
-
export { Command, CommandsRegistry, commands } from './command'
|
|
48
|
+
export { Command, CommandsRegistry, commands, graftModule } from './command'
|
|
49
49
|
export { Endpoint, EndpointsRegistry, endpoints } from './endpoint'
|
|
50
50
|
export { Selector, SelectorsRegistry, selectors } from './selector'
|
|
51
51
|
export { Server, ServersRegistry } from './server'
|
|
@@ -69,7 +69,7 @@ export type { Entity } from './entity'
|
|
|
69
69
|
export type { EventMap } from './bus'
|
|
70
70
|
export type { SetStateValue, StateChangeType } from './state'
|
|
71
71
|
|
|
72
|
-
// Zod — so consumer code can `import { z } from '
|
|
72
|
+
// Zod — so consumer code can `import { z } from 'luca'`
|
|
73
73
|
export { z } from 'zod'
|
|
74
74
|
|
|
75
75
|
// Schemas
|