@soederpop/luca 0.0.34 → 0.0.35
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/bun.lock +0 -1
- package/docs/README.md +1 -1
- package/docs/TABLE-OF-CONTENTS.md +0 -1
- package/docs/bootstrap/SKILL.md +1 -1
- package/package.json +1 -2
- package/scripts/examples/using-assistant-with-mcp.ts +2 -7
- package/scripts/test-linux-binary.sh +80 -0
- package/src/bootstrap/generated.ts +2 -92
- package/src/cli/build-info.ts +2 -2
- package/src/introspection/generated.agi.ts +628 -887
- package/src/introspection/generated.node.ts +780 -1039
- package/src/introspection/generated.web.ts +1 -1
- package/src/node/container.ts +0 -5
- package/src/python/generated.ts +1 -1
- package/src/scaffolds/generated.ts +1 -1
- package/docs/examples/port-exposer.md +0 -89
- package/src/node/features/port-exposer.ts +0 -351
package/bun.lock
CHANGED
package/docs/README.md
CHANGED
|
@@ -25,7 +25,7 @@ Items: 169
|
|
|
25
25
|
Sections: (none)
|
|
26
26
|
Relationships: (none)
|
|
27
27
|
Documents: 43
|
|
28
|
-
IDs: examples/postgres, examples/yaml-tree, examples/grep, examples/ink, examples/git, examples/ink-renderer, examples/esbuild, examples/window-manager, examples/process-manager, examples/runpod, examples/google-auth, examples/
|
|
28
|
+
IDs: examples/postgres, examples/yaml-tree, examples/grep, examples/ink, examples/git, examples/ink-renderer, examples/esbuild, examples/window-manager, examples/process-manager, examples/runpod, examples/google-auth, examples/downloader, examples/secure-shell, examples/vault, examples/window-manager-layouts, examples/ipc-socket, examples/google-sheets, examples/fs, examples/networking, examples/ink-blocks, examples/ui, examples/opener, examples/nlp, examples/disk-cache, examples/assistant/CORE, examples/vm, examples/google-docs, examples/google-calendar, examples/content-db, examples/yaml, examples/package-finder, examples/os, examples/json-tree, examples/google-drive, examples/telegram, examples/file-manager, examples/repl, examples/python, examples/sqlite, examples/tts, examples/docker, examples/proc
|
|
29
29
|
|
|
30
30
|
Model: Idea
|
|
31
31
|
Prefix: ideas
|
|
@@ -43,7 +43,6 @@
|
|
|
43
43
|
- [Opener](./examples/opener.md)
|
|
44
44
|
- [os](./examples/os.md)
|
|
45
45
|
- [Package Finder](./examples/package-finder.md)
|
|
46
|
-
- [Port Exposer](./examples/port-exposer.md)
|
|
47
46
|
- [PostgreSQL](./examples/postgres.md)
|
|
48
47
|
- [proc](./examples/proc.md)
|
|
49
48
|
- [Process Manager](./examples/process-manager.md)
|
package/docs/bootstrap/SKILL.md
CHANGED
|
@@ -275,7 +275,7 @@ A table of contents for the container. **Run `luca describe <name>` for full doc
|
|
|
275
275
|
| **AI Assistants** | `assistant`, `assistantsManager`, `conversation`, `conversationHistory`, `fileTools` | Build AI assistants, manage conversations, tool calling. `fileTools` composes lower-level features (`fs`, `grep`) into an assistant-ready tool surface — a good example of how features can define tools for assistants (see `references/examples/feature-as-tool-provider.md`). |
|
|
276
276
|
| **AI Agent Wrappers** | `claudeCode`, `openaiCodex`, `lucaCoder` | Spawn and manage external AI agent CLIs as subprocesses |
|
|
277
277
|
| **Data & Storage** | `sqlite`, `postgres`, `diskCache`, `contentDb`, `redis` | Databases, caching, document management |
|
|
278
|
-
| **Networking** | `networking`, `dns
|
|
278
|
+
| **Networking** | `networking`, `dns` | Network utilities, DNS |
|
|
279
279
|
| **Google Workspace** | `googleAuth`, `googleDrive`, `googleDocs`, `googleSheets`, `googleCalendar`, `googleMail` | OAuth and Google service wrappers |
|
|
280
280
|
| **Dev Tools** | `git`, `docker`, `esbuild`, `vm`, `python`, `packageFinder` | Version control, containers, bundling, sandboxed execution |
|
|
281
281
|
| **Content & NLP** | `docsReader`, `nlp`, `semanticSearch`, `skillsLibrary`, `jsonTree`, `yamlTree` | Document Q&A, text analysis, semantic search, skills, structured file ingestion |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soederpop/luca",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.35",
|
|
4
4
|
"website": "https://luca.soederpop.com",
|
|
5
5
|
"description": "lightweight universal conversational architecture AKA Le Ultimate Component Architecture AKA Last Universal Common Ancestor, part AI part Human",
|
|
6
6
|
"author": "jon soeder aka the people's champ <jon@soederpop.com>",
|
|
@@ -92,7 +92,6 @@
|
|
|
92
92
|
},
|
|
93
93
|
"dependencies": {
|
|
94
94
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
95
|
-
"@ngrok/ngrok": "^1.5.1",
|
|
96
95
|
"@openai/codex": "^0.99.0",
|
|
97
96
|
"@resvg/resvg-js": "^2.6.2",
|
|
98
97
|
"@supabase/supabase-js": "^2.95.3",
|
|
@@ -129,19 +129,16 @@ async function main() {
|
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
// ── Phase 1b:
|
|
132
|
+
// ── Phase 1b: Build local MCP Server URLs ──────────────────────────────
|
|
133
133
|
|
|
134
134
|
const publicUrls: Record<string, string> = {}
|
|
135
|
-
const exposers: Array<{ close(): Promise<void> }> = []
|
|
136
135
|
|
|
137
136
|
for (const def of MCP_SERVERS) {
|
|
138
137
|
const entry = serverMap[def.tag]!
|
|
139
138
|
if (entry.status === 'running' || entry.status === 'external') {
|
|
140
|
-
const
|
|
141
|
-
const url = await exposer.expose()
|
|
139
|
+
const url = `http://localhost:${def.port}`
|
|
142
140
|
publicUrls[def.tag] = `${url}/mcp`
|
|
143
141
|
entry.publicUrl = url
|
|
144
|
-
exposers.push(exposer)
|
|
145
142
|
}
|
|
146
143
|
}
|
|
147
144
|
|
|
@@ -496,7 +493,6 @@ async function main() {
|
|
|
496
493
|
useInput(
|
|
497
494
|
(input, key) => {
|
|
498
495
|
if (key.ctrl && input === 'c') {
|
|
499
|
-
for (const e of exposers) e.close().catch(() => {})
|
|
500
496
|
pm.killAll()
|
|
501
497
|
exit()
|
|
502
498
|
}
|
|
@@ -553,7 +549,6 @@ async function main() {
|
|
|
553
549
|
await ink.render(h(App))
|
|
554
550
|
await ink.waitUntilExit()
|
|
555
551
|
|
|
556
|
-
for (const e of exposers) await e.close().catch(() => {})
|
|
557
552
|
pm.killAll()
|
|
558
553
|
}
|
|
559
554
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# CI-style test: cross-compile luca for Linux and verify it runs in a Docker container
|
|
5
|
+
# Usage: bash scripts/test-linux-binary.sh
|
|
6
|
+
|
|
7
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
8
|
+
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
9
|
+
DIST_DIR="$PROJECT_DIR/dist"
|
|
10
|
+
LINUX_BINARY="$DIST_DIR/luca-linux"
|
|
11
|
+
|
|
12
|
+
echo "=== Cross-compiling luca for linux-arm64 ==="
|
|
13
|
+
cd "$PROJECT_DIR"
|
|
14
|
+
|
|
15
|
+
# Run the pre-compile build steps (introspection, scaffolds, etc.)
|
|
16
|
+
bun run build:introspection
|
|
17
|
+
bun run build:scaffolds
|
|
18
|
+
bun run build:bootstrap
|
|
19
|
+
bun run build:python-bridge
|
|
20
|
+
bash scripts/stamp-build.sh
|
|
21
|
+
|
|
22
|
+
# Cross-compile for linux arm64 (matches Docker on Apple Silicon)
|
|
23
|
+
bun build ./src/cli/cli.ts --compile --target=bun-linux-arm64 --outfile "$LINUX_BINARY" --external node-llama-cpp
|
|
24
|
+
|
|
25
|
+
echo ""
|
|
26
|
+
echo "=== Built linux binary: $(file "$LINUX_BINARY") ==="
|
|
27
|
+
echo ""
|
|
28
|
+
|
|
29
|
+
# Create a minimal Dockerfile inline
|
|
30
|
+
DOCKER_TAG="luca-linux-test"
|
|
31
|
+
|
|
32
|
+
docker build -t "$DOCKER_TAG" -f - "$DIST_DIR" <<'DOCKERFILE'
|
|
33
|
+
FROM debian:bookworm-slim
|
|
34
|
+
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates && rm -rf /var/lib/apt/lists/*
|
|
35
|
+
WORKDIR /app
|
|
36
|
+
COPY luca-linux /usr/local/bin/luca
|
|
37
|
+
RUN chmod +x /usr/local/bin/luca
|
|
38
|
+
DOCKERFILE
|
|
39
|
+
|
|
40
|
+
echo ""
|
|
41
|
+
echo "=== Running smoke tests in Docker container ==="
|
|
42
|
+
echo ""
|
|
43
|
+
|
|
44
|
+
PASS=0
|
|
45
|
+
FAIL=0
|
|
46
|
+
|
|
47
|
+
run_test() {
|
|
48
|
+
local description="$1"
|
|
49
|
+
shift
|
|
50
|
+
echo -n " TEST: $description ... "
|
|
51
|
+
if output=$(docker run --rm "$DOCKER_TAG" "$@" 2>&1); then
|
|
52
|
+
echo "PASS"
|
|
53
|
+
PASS=$((PASS + 1))
|
|
54
|
+
else
|
|
55
|
+
echo "FAIL"
|
|
56
|
+
echo " Output: $output"
|
|
57
|
+
FAIL=$((FAIL + 1))
|
|
58
|
+
fi
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
# Basic smoke tests
|
|
62
|
+
run_test "binary executes" luca --version
|
|
63
|
+
run_test "help flag works" luca --help
|
|
64
|
+
run_test "eval runs JS expression" luca eval "1 + 1"
|
|
65
|
+
run_test "describe features" luca describe features
|
|
66
|
+
run_test "container basics via eval" luca eval "container.uuid"
|
|
67
|
+
|
|
68
|
+
echo ""
|
|
69
|
+
echo "=== Results: $PASS passed, $FAIL failed ==="
|
|
70
|
+
|
|
71
|
+
# Cleanup
|
|
72
|
+
docker rmi "$DOCKER_TAG" > /dev/null 2>&1 || true
|
|
73
|
+
rm -f "$LINUX_BINARY"
|
|
74
|
+
|
|
75
|
+
if [ "$FAIL" -gt 0 ]; then
|
|
76
|
+
echo "FAILED"
|
|
77
|
+
exit 1
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
echo "ALL TESTS PASSED"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Auto-generated bootstrap content
|
|
2
|
-
// Generated at: 2026-03-
|
|
2
|
+
// Generated at: 2026-03-27T03:29:28.307Z
|
|
3
3
|
// Source: docs/bootstrap/*.md, docs/bootstrap/templates/*, docs/examples/*.md, docs/tutorials/*.md
|
|
4
4
|
//
|
|
5
5
|
// Do not edit manually. Run: luca build-bootstrap
|
|
@@ -282,7 +282,7 @@ A table of contents for the container. **Run \`luca describe <name>\` for full d
|
|
|
282
282
|
| **AI Assistants** | \`assistant\`, \`assistantsManager\`, \`conversation\`, \`conversationHistory\`, \`fileTools\` | Build AI assistants, manage conversations, tool calling. \`fileTools\` composes lower-level features (\`fs\`, \`grep\`) into an assistant-ready tool surface — a good example of how features can define tools for assistants (see \`references/examples/feature-as-tool-provider.md\`). |
|
|
283
283
|
| **AI Agent Wrappers** | \`claudeCode\`, \`openaiCodex\`, \`lucaCoder\` | Spawn and manage external AI agent CLIs as subprocesses |
|
|
284
284
|
| **Data & Storage** | \`sqlite\`, \`postgres\`, \`diskCache\`, \`contentDb\`, \`redis\` | Databases, caching, document management |
|
|
285
|
-
| **Networking** | \`networking\`, \`dns
|
|
285
|
+
| **Networking** | \`networking\`, \`dns\` | Network utilities, DNS |
|
|
286
286
|
| **Google Workspace** | \`googleAuth\`, \`googleDrive\`, \`googleDocs\`, \`googleSheets\`, \`googleCalendar\`, \`googleMail\` | OAuth and Google service wrappers |
|
|
287
287
|
| **Dev Tools** | \`git\`, \`docker\`, \`esbuild\`, \`vm\`, \`python\`, \`packageFinder\` | Version control, containers, bundling, sandboxed execution |
|
|
288
288
|
| **Content & NLP** | \`docsReader\`, \`nlp\`, \`semanticSearch\`, \`skillsLibrary\`, \`jsonTree\`, \`yamlTree\` | Document Q&A, text analysis, semantic search, skills, structured file ingestion |
|
|
@@ -2684,96 +2684,6 @@ console.log('Done')
|
|
|
2684
2684
|
## Summary
|
|
2685
2685
|
|
|
2686
2686
|
The ask/reply protocol gives you awaitable request/response over WebSocket without leaving the Luca helper API. The client calls \`ask(type, data)\` and gets back a promise. The server's message handler gets \`reply()\` and \`replyError()\` injected on any message that carries a \`requestId\`. The server can also \`ask()\` a specific client. Timeouts, error propagation, and cleanup of pending requests on disconnect are all handled automatically.
|
|
2687
|
-
`,
|
|
2688
|
-
"port-exposer.md": `---
|
|
2689
|
-
title: "Port Exposer"
|
|
2690
|
-
tags: [portExposer, ngrok, networking, tunnel]
|
|
2691
|
-
lastTested: null
|
|
2692
|
-
lastTestPassed: null
|
|
2693
|
-
---
|
|
2694
|
-
|
|
2695
|
-
# portExposer
|
|
2696
|
-
|
|
2697
|
-
Exposes local HTTP services via ngrok with SSL-enabled public URLs. Useful for development, testing webhooks, and sharing local services with external consumers.
|
|
2698
|
-
|
|
2699
|
-
## Overview
|
|
2700
|
-
|
|
2701
|
-
The \`portExposer\` feature creates an ngrok tunnel from a local port to a public HTTPS URL. It supports custom subdomains, regional endpoints, basic auth, and OAuth (features that require a paid ngrok plan). Requires ngrok to be installed or available as a dependency, and optionally an auth token for premium features.
|
|
2702
|
-
|
|
2703
|
-
## Enabling the Feature
|
|
2704
|
-
|
|
2705
|
-
\`\`\`ts
|
|
2706
|
-
const exposer = container.feature('portExposer', {
|
|
2707
|
-
port: 3000,
|
|
2708
|
-
enable: true
|
|
2709
|
-
})
|
|
2710
|
-
console.log('Port Exposer enabled:', exposer.state.get('enabled'))
|
|
2711
|
-
\`\`\`
|
|
2712
|
-
|
|
2713
|
-
## Exploring the API
|
|
2714
|
-
|
|
2715
|
-
\`\`\`ts
|
|
2716
|
-
const docs = container.features.describe('portExposer')
|
|
2717
|
-
console.log(docs)
|
|
2718
|
-
\`\`\`
|
|
2719
|
-
|
|
2720
|
-
## Checking Connection State
|
|
2721
|
-
|
|
2722
|
-
\`\`\`ts
|
|
2723
|
-
const exposer = container.feature('portExposer', { port: 3000 })
|
|
2724
|
-
console.log('Connected:', exposer.isConnected())
|
|
2725
|
-
\`\`\`
|
|
2726
|
-
|
|
2727
|
-
## Exposing a Port
|
|
2728
|
-
|
|
2729
|
-
Create a tunnel and get the public URL.
|
|
2730
|
-
|
|
2731
|
-
\`\`\`ts skip
|
|
2732
|
-
const url = await exposer.expose()
|
|
2733
|
-
console.log('Public URL:', url)
|
|
2734
|
-
console.log('Connected:', exposer.isConnected())
|
|
2735
|
-
\`\`\`
|
|
2736
|
-
|
|
2737
|
-
The returned URL is an HTTPS endpoint that forwards traffic to \`localhost:3000\`. The tunnel remains active until \`close()\` is called or the process exits.
|
|
2738
|
-
|
|
2739
|
-
## Getting Connection Info
|
|
2740
|
-
|
|
2741
|
-
Retrieve a snapshot of the current tunnel state.
|
|
2742
|
-
|
|
2743
|
-
\`\`\`ts skip
|
|
2744
|
-
await exposer.expose()
|
|
2745
|
-
const info = exposer.getConnectionInfo()
|
|
2746
|
-
console.log('Public URL:', info.publicUrl)
|
|
2747
|
-
console.log('Local port:', info.localPort)
|
|
2748
|
-
console.log('Connected at:', info.connectedAt)
|
|
2749
|
-
\`\`\`
|
|
2750
|
-
|
|
2751
|
-
## Reconnecting with New Options
|
|
2752
|
-
|
|
2753
|
-
Close the existing tunnel and re-expose with different settings.
|
|
2754
|
-
|
|
2755
|
-
\`\`\`ts skip
|
|
2756
|
-
const url1 = await exposer.expose()
|
|
2757
|
-
console.log('First URL:', url1)
|
|
2758
|
-
|
|
2759
|
-
const url2 = await exposer.reconnect({ port: 8080 })
|
|
2760
|
-
console.log('New URL (port 8080):', url2)
|
|
2761
|
-
\`\`\`
|
|
2762
|
-
|
|
2763
|
-
The \`reconnect\` method calls \`close()\` internally, merges the new options, then calls \`expose()\` again.
|
|
2764
|
-
|
|
2765
|
-
## Closing the Tunnel
|
|
2766
|
-
|
|
2767
|
-
\`\`\`ts skip
|
|
2768
|
-
await exposer.close()
|
|
2769
|
-
console.log('Tunnel closed:', !exposer.isConnected())
|
|
2770
|
-
\`\`\`
|
|
2771
|
-
|
|
2772
|
-
Calling \`close()\` when no tunnel is active is a safe no-op. The \`disable()\` method also closes the tunnel before disabling the feature.
|
|
2773
|
-
|
|
2774
|
-
## Summary
|
|
2775
|
-
|
|
2776
|
-
The \`portExposer\` feature wraps ngrok to expose local ports as public HTTPS endpoints. It supports connection lifecycle management, reconnection with new options, and event-driven notifications for tunnel state changes. Requires ngrok to be installed.
|
|
2777
2687
|
`,
|
|
2778
2688
|
"secure-shell.md": `---
|
|
2779
2689
|
title: "Secure Shell"
|
package/src/cli/build-info.ts
CHANGED