@soederpop/luca 0.0.34 → 0.0.36
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 +2 -3
- 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 +1 -260
- 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.36",
|
|
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",
|
|
@@ -105,7 +104,7 @@
|
|
|
105
104
|
"chokidar": "^3.5.3",
|
|
106
105
|
"cli-markdown": "^3.5.0",
|
|
107
106
|
"compromise": "^14.14.5",
|
|
108
|
-
"contentbase": "^0.
|
|
107
|
+
"contentbase": "^0.2.0",
|
|
109
108
|
"cors": "^2.8.5",
|
|
110
109
|
"detect-port": "^1.5.1",
|
|
111
110
|
"dotenv": "^17.2.4",
|
|
@@ -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-28T00:36:31.608Z
|
|
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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { setBuildTimeData, setContainerBuildTimeData } from './index.js';
|
|
2
2
|
|
|
3
3
|
// Auto-generated introspection registry data
|
|
4
|
-
// Generated at: 2026-03-
|
|
4
|
+
// Generated at: 2026-03-28T00:36:29.946Z
|
|
5
5
|
|
|
6
6
|
setBuildTimeData('features.googleDocs', {
|
|
7
7
|
"id": "features.googleDocs",
|
|
@@ -8861,136 +8861,6 @@ setBuildTimeData('features.processManager', {
|
|
|
8861
8861
|
}
|
|
8862
8862
|
});
|
|
8863
8863
|
|
|
8864
|
-
setBuildTimeData('portExposer', {
|
|
8865
|
-
"id": "portExposer",
|
|
8866
|
-
"description": "Port Exposer Feature Exposes local HTTP services via ngrok with SSL-enabled public URLs. Perfect for development, testing, and sharing local services securely. Features: - SSL-enabled public URLs for local services - Custom subdomains and domains (with paid plans) - Authentication options (basic auth, OAuth) - Regional endpoint selection - Connection state management",
|
|
8867
|
-
"shortcut": "portExposer",
|
|
8868
|
-
"className": "PortExposer",
|
|
8869
|
-
"methods": {
|
|
8870
|
-
"expose": {
|
|
8871
|
-
"description": "Expose the local port via ngrok. Creates an ngrok tunnel to the specified local port and returns the SSL-enabled public URL. Emits `exposed` on success or `error` on failure.",
|
|
8872
|
-
"parameters": {
|
|
8873
|
-
"port": {
|
|
8874
|
-
"type": "number",
|
|
8875
|
-
"description": "Optional port override; falls back to `options.port`"
|
|
8876
|
-
}
|
|
8877
|
-
},
|
|
8878
|
-
"required": [],
|
|
8879
|
-
"returns": "Promise<string>",
|
|
8880
|
-
"examples": [
|
|
8881
|
-
{
|
|
8882
|
-
"language": "ts",
|
|
8883
|
-
"code": "const exposer = container.feature('portExposer', { port: 3000 })\nconst url = await exposer.expose()\nconsole.log(`Public URL: ${url}`)\n\n// Override port at call time\nconst url2 = await exposer.expose(8080)"
|
|
8884
|
-
}
|
|
8885
|
-
]
|
|
8886
|
-
},
|
|
8887
|
-
"close": {
|
|
8888
|
-
"description": "Stop exposing the port and close the ngrok tunnel. Tears down the ngrok listener, resets connection state, and emits `closed`. Safe to call when no tunnel is active (no-op).",
|
|
8889
|
-
"parameters": {},
|
|
8890
|
-
"required": [],
|
|
8891
|
-
"returns": "Promise<void>",
|
|
8892
|
-
"examples": [
|
|
8893
|
-
{
|
|
8894
|
-
"language": "ts",
|
|
8895
|
-
"code": "const exposer = container.feature('portExposer', { port: 3000 })\nawait exposer.expose()\n// ... later\nawait exposer.close()\nconsole.log(exposer.isConnected()) // false"
|
|
8896
|
-
}
|
|
8897
|
-
]
|
|
8898
|
-
},
|
|
8899
|
-
"getPublicUrl": {
|
|
8900
|
-
"description": "Get the current public URL if connected. Returns the live URL from the ngrok listener, or `undefined` if no tunnel is active.",
|
|
8901
|
-
"parameters": {},
|
|
8902
|
-
"required": [],
|
|
8903
|
-
"returns": "string | undefined",
|
|
8904
|
-
"examples": [
|
|
8905
|
-
{
|
|
8906
|
-
"language": "ts",
|
|
8907
|
-
"code": "const exposer = container.feature('portExposer', { port: 3000 })\nawait exposer.expose()\nconsole.log(exposer.getPublicUrl()) // 'https://abc123.ngrok.io'"
|
|
8908
|
-
}
|
|
8909
|
-
]
|
|
8910
|
-
},
|
|
8911
|
-
"isConnected": {
|
|
8912
|
-
"description": "Check if the ngrok tunnel is currently connected.",
|
|
8913
|
-
"parameters": {},
|
|
8914
|
-
"required": [],
|
|
8915
|
-
"returns": "boolean",
|
|
8916
|
-
"examples": [
|
|
8917
|
-
{
|
|
8918
|
-
"language": "ts",
|
|
8919
|
-
"code": "const exposer = container.feature('portExposer', { port: 3000 })\nconsole.log(exposer.isConnected()) // false\nawait exposer.expose()\nconsole.log(exposer.isConnected()) // true"
|
|
8920
|
-
}
|
|
8921
|
-
]
|
|
8922
|
-
},
|
|
8923
|
-
"getConnectionInfo": {
|
|
8924
|
-
"description": "Get a snapshot of the current connection information. Returns an object with the tunnel's connected status, public URL, local port, connection timestamp, and session metadata.",
|
|
8925
|
-
"parameters": {},
|
|
8926
|
-
"required": [],
|
|
8927
|
-
"returns": "void",
|
|
8928
|
-
"examples": [
|
|
8929
|
-
{
|
|
8930
|
-
"language": "ts",
|
|
8931
|
-
"code": "const exposer = container.feature('portExposer', { port: 3000 })\nawait exposer.expose()\nconst info = exposer.getConnectionInfo()\nconsole.log(info.publicUrl, info.localPort, info.connectedAt)"
|
|
8932
|
-
}
|
|
8933
|
-
]
|
|
8934
|
-
},
|
|
8935
|
-
"reconnect": {
|
|
8936
|
-
"description": "Close the existing tunnel and re-expose with optionally updated options. Calls `close()` first, merges any new options, then calls `expose()`.",
|
|
8937
|
-
"parameters": {
|
|
8938
|
-
"newOptions": {
|
|
8939
|
-
"type": "Partial<PortExposerOptions>",
|
|
8940
|
-
"description": "Optional partial options to merge before reconnecting"
|
|
8941
|
-
}
|
|
8942
|
-
},
|
|
8943
|
-
"required": [],
|
|
8944
|
-
"returns": "Promise<string>",
|
|
8945
|
-
"examples": [
|
|
8946
|
-
{
|
|
8947
|
-
"language": "ts",
|
|
8948
|
-
"code": "const exposer = container.feature('portExposer', { port: 3000 })\nawait exposer.expose()\n// Switch to a different port\nconst newUrl = await exposer.reconnect({ port: 8080 })"
|
|
8949
|
-
}
|
|
8950
|
-
]
|
|
8951
|
-
},
|
|
8952
|
-
"disable": {
|
|
8953
|
-
"description": "Disable the feature, ensuring the ngrok tunnel is closed first. Overrides the base `disable()` to guarantee that the tunnel is torn down before the feature is marked as disabled.",
|
|
8954
|
-
"parameters": {},
|
|
8955
|
-
"required": [],
|
|
8956
|
-
"returns": "Promise<this>",
|
|
8957
|
-
"examples": [
|
|
8958
|
-
{
|
|
8959
|
-
"language": "ts",
|
|
8960
|
-
"code": "const exposer = container.feature('portExposer', { port: 3000 })\nawait exposer.expose()\nawait exposer.disable()"
|
|
8961
|
-
}
|
|
8962
|
-
]
|
|
8963
|
-
}
|
|
8964
|
-
},
|
|
8965
|
-
"getters": {},
|
|
8966
|
-
"events": {
|
|
8967
|
-
"exposed": {
|
|
8968
|
-
"name": "exposed",
|
|
8969
|
-
"description": "Event emitted by PortExposer",
|
|
8970
|
-
"arguments": {}
|
|
8971
|
-
},
|
|
8972
|
-
"error": {
|
|
8973
|
-
"name": "error",
|
|
8974
|
-
"description": "Event emitted by PortExposer",
|
|
8975
|
-
"arguments": {}
|
|
8976
|
-
},
|
|
8977
|
-
"closed": {
|
|
8978
|
-
"name": "closed",
|
|
8979
|
-
"description": "Event emitted by PortExposer",
|
|
8980
|
-
"arguments": {}
|
|
8981
|
-
}
|
|
8982
|
-
},
|
|
8983
|
-
"state": {},
|
|
8984
|
-
"options": {},
|
|
8985
|
-
"envVars": [],
|
|
8986
|
-
"examples": [
|
|
8987
|
-
{
|
|
8988
|
-
"language": "ts",
|
|
8989
|
-
"code": "// Basic usage\nconst exposer = container.feature('portExposer', { port: 3000 })\nconst url = await exposer.expose()\nconsole.log(`Service available at: ${url}`)\n\n// With custom subdomain\nconst exposer = container.feature('portExposer', {\n port: 8080,\n subdomain: 'my-app',\n authToken: 'your-ngrok-token'\n})"
|
|
8990
|
-
}
|
|
8991
|
-
]
|
|
8992
|
-
});
|
|
8993
|
-
|
|
8994
8864
|
setBuildTimeData('features.googleSheets', {
|
|
8995
8865
|
"id": "features.googleSheets",
|
|
8996
8866
|
"description": "Google Sheets feature for reading spreadsheet data as JSON, CSV, or raw arrays. Depends on the googleAuth feature for authentication. Creates a Sheets v4 API client lazily and provides convenient methods for reading tabular data.",
|
|
@@ -27573,135 +27443,6 @@ export const introspectionData = [
|
|
|
27573
27443
|
}
|
|
27574
27444
|
}
|
|
27575
27445
|
},
|
|
27576
|
-
{
|
|
27577
|
-
"id": "portExposer",
|
|
27578
|
-
"description": "Port Exposer Feature Exposes local HTTP services via ngrok with SSL-enabled public URLs. Perfect for development, testing, and sharing local services securely. Features: - SSL-enabled public URLs for local services - Custom subdomains and domains (with paid plans) - Authentication options (basic auth, OAuth) - Regional endpoint selection - Connection state management",
|
|
27579
|
-
"shortcut": "portExposer",
|
|
27580
|
-
"className": "PortExposer",
|
|
27581
|
-
"methods": {
|
|
27582
|
-
"expose": {
|
|
27583
|
-
"description": "Expose the local port via ngrok. Creates an ngrok tunnel to the specified local port and returns the SSL-enabled public URL. Emits `exposed` on success or `error` on failure.",
|
|
27584
|
-
"parameters": {
|
|
27585
|
-
"port": {
|
|
27586
|
-
"type": "number",
|
|
27587
|
-
"description": "Optional port override; falls back to `options.port`"
|
|
27588
|
-
}
|
|
27589
|
-
},
|
|
27590
|
-
"required": [],
|
|
27591
|
-
"returns": "Promise<string>",
|
|
27592
|
-
"examples": [
|
|
27593
|
-
{
|
|
27594
|
-
"language": "ts",
|
|
27595
|
-
"code": "const exposer = container.feature('portExposer', { port: 3000 })\nconst url = await exposer.expose()\nconsole.log(`Public URL: ${url}`)\n\n// Override port at call time\nconst url2 = await exposer.expose(8080)"
|
|
27596
|
-
}
|
|
27597
|
-
]
|
|
27598
|
-
},
|
|
27599
|
-
"close": {
|
|
27600
|
-
"description": "Stop exposing the port and close the ngrok tunnel. Tears down the ngrok listener, resets connection state, and emits `closed`. Safe to call when no tunnel is active (no-op).",
|
|
27601
|
-
"parameters": {},
|
|
27602
|
-
"required": [],
|
|
27603
|
-
"returns": "Promise<void>",
|
|
27604
|
-
"examples": [
|
|
27605
|
-
{
|
|
27606
|
-
"language": "ts",
|
|
27607
|
-
"code": "const exposer = container.feature('portExposer', { port: 3000 })\nawait exposer.expose()\n// ... later\nawait exposer.close()\nconsole.log(exposer.isConnected()) // false"
|
|
27608
|
-
}
|
|
27609
|
-
]
|
|
27610
|
-
},
|
|
27611
|
-
"getPublicUrl": {
|
|
27612
|
-
"description": "Get the current public URL if connected. Returns the live URL from the ngrok listener, or `undefined` if no tunnel is active.",
|
|
27613
|
-
"parameters": {},
|
|
27614
|
-
"required": [],
|
|
27615
|
-
"returns": "string | undefined",
|
|
27616
|
-
"examples": [
|
|
27617
|
-
{
|
|
27618
|
-
"language": "ts",
|
|
27619
|
-
"code": "const exposer = container.feature('portExposer', { port: 3000 })\nawait exposer.expose()\nconsole.log(exposer.getPublicUrl()) // 'https://abc123.ngrok.io'"
|
|
27620
|
-
}
|
|
27621
|
-
]
|
|
27622
|
-
},
|
|
27623
|
-
"isConnected": {
|
|
27624
|
-
"description": "Check if the ngrok tunnel is currently connected.",
|
|
27625
|
-
"parameters": {},
|
|
27626
|
-
"required": [],
|
|
27627
|
-
"returns": "boolean",
|
|
27628
|
-
"examples": [
|
|
27629
|
-
{
|
|
27630
|
-
"language": "ts",
|
|
27631
|
-
"code": "const exposer = container.feature('portExposer', { port: 3000 })\nconsole.log(exposer.isConnected()) // false\nawait exposer.expose()\nconsole.log(exposer.isConnected()) // true"
|
|
27632
|
-
}
|
|
27633
|
-
]
|
|
27634
|
-
},
|
|
27635
|
-
"getConnectionInfo": {
|
|
27636
|
-
"description": "Get a snapshot of the current connection information. Returns an object with the tunnel's connected status, public URL, local port, connection timestamp, and session metadata.",
|
|
27637
|
-
"parameters": {},
|
|
27638
|
-
"required": [],
|
|
27639
|
-
"returns": "void",
|
|
27640
|
-
"examples": [
|
|
27641
|
-
{
|
|
27642
|
-
"language": "ts",
|
|
27643
|
-
"code": "const exposer = container.feature('portExposer', { port: 3000 })\nawait exposer.expose()\nconst info = exposer.getConnectionInfo()\nconsole.log(info.publicUrl, info.localPort, info.connectedAt)"
|
|
27644
|
-
}
|
|
27645
|
-
]
|
|
27646
|
-
},
|
|
27647
|
-
"reconnect": {
|
|
27648
|
-
"description": "Close the existing tunnel and re-expose with optionally updated options. Calls `close()` first, merges any new options, then calls `expose()`.",
|
|
27649
|
-
"parameters": {
|
|
27650
|
-
"newOptions": {
|
|
27651
|
-
"type": "Partial<PortExposerOptions>",
|
|
27652
|
-
"description": "Optional partial options to merge before reconnecting"
|
|
27653
|
-
}
|
|
27654
|
-
},
|
|
27655
|
-
"required": [],
|
|
27656
|
-
"returns": "Promise<string>",
|
|
27657
|
-
"examples": [
|
|
27658
|
-
{
|
|
27659
|
-
"language": "ts",
|
|
27660
|
-
"code": "const exposer = container.feature('portExposer', { port: 3000 })\nawait exposer.expose()\n// Switch to a different port\nconst newUrl = await exposer.reconnect({ port: 8080 })"
|
|
27661
|
-
}
|
|
27662
|
-
]
|
|
27663
|
-
},
|
|
27664
|
-
"disable": {
|
|
27665
|
-
"description": "Disable the feature, ensuring the ngrok tunnel is closed first. Overrides the base `disable()` to guarantee that the tunnel is torn down before the feature is marked as disabled.",
|
|
27666
|
-
"parameters": {},
|
|
27667
|
-
"required": [],
|
|
27668
|
-
"returns": "Promise<this>",
|
|
27669
|
-
"examples": [
|
|
27670
|
-
{
|
|
27671
|
-
"language": "ts",
|
|
27672
|
-
"code": "const exposer = container.feature('portExposer', { port: 3000 })\nawait exposer.expose()\nawait exposer.disable()"
|
|
27673
|
-
}
|
|
27674
|
-
]
|
|
27675
|
-
}
|
|
27676
|
-
},
|
|
27677
|
-
"getters": {},
|
|
27678
|
-
"events": {
|
|
27679
|
-
"exposed": {
|
|
27680
|
-
"name": "exposed",
|
|
27681
|
-
"description": "Event emitted by PortExposer",
|
|
27682
|
-
"arguments": {}
|
|
27683
|
-
},
|
|
27684
|
-
"error": {
|
|
27685
|
-
"name": "error",
|
|
27686
|
-
"description": "Event emitted by PortExposer",
|
|
27687
|
-
"arguments": {}
|
|
27688
|
-
},
|
|
27689
|
-
"closed": {
|
|
27690
|
-
"name": "closed",
|
|
27691
|
-
"description": "Event emitted by PortExposer",
|
|
27692
|
-
"arguments": {}
|
|
27693
|
-
}
|
|
27694
|
-
},
|
|
27695
|
-
"state": {},
|
|
27696
|
-
"options": {},
|
|
27697
|
-
"envVars": [],
|
|
27698
|
-
"examples": [
|
|
27699
|
-
{
|
|
27700
|
-
"language": "ts",
|
|
27701
|
-
"code": "// Basic usage\nconst exposer = container.feature('portExposer', { port: 3000 })\nconst url = await exposer.expose()\nconsole.log(`Service available at: ${url}`)\n\n// With custom subdomain\nconst exposer = container.feature('portExposer', {\n port: 8080,\n subdomain: 'my-app',\n authToken: 'your-ngrok-token'\n})"
|
|
27702
|
-
}
|
|
27703
|
-
]
|
|
27704
|
-
},
|
|
27705
27446
|
{
|
|
27706
27447
|
"id": "features.googleSheets",
|
|
27707
27448
|
"description": "Google Sheets feature for reading spreadsheet data as JSON, CSV, or raw arrays. Depends on the googleAuth feature for authentication. Creates a Sheets v4 API client lazily and provides convenient methods for reading tabular data.",
|