@leverageaiapps/leverageai-agent 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +175 -0
  3. package/dist/capture.d.ts +3 -0
  4. package/dist/capture.d.ts.map +1 -0
  5. package/dist/capture.js +134 -0
  6. package/dist/capture.js.map +1 -0
  7. package/dist/cloudflare-tunnel.d.ts +9 -0
  8. package/dist/cloudflare-tunnel.d.ts.map +1 -0
  9. package/dist/cloudflare-tunnel.js +218 -0
  10. package/dist/cloudflare-tunnel.js.map +1 -0
  11. package/dist/config.d.ts +7 -0
  12. package/dist/config.d.ts.map +1 -0
  13. package/dist/config.js +84 -0
  14. package/dist/config.js.map +1 -0
  15. package/dist/context-extractor.d.ts +17 -0
  16. package/dist/context-extractor.d.ts.map +1 -0
  17. package/dist/context-extractor.js +118 -0
  18. package/dist/context-extractor.js.map +1 -0
  19. package/dist/index.d.ts +3 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +85 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/pty.d.ts +20 -0
  24. package/dist/pty.d.ts.map +1 -0
  25. package/dist/pty.js +148 -0
  26. package/dist/pty.js.map +1 -0
  27. package/dist/relay.d.ts +5 -0
  28. package/dist/relay.d.ts.map +1 -0
  29. package/dist/relay.js +131 -0
  30. package/dist/relay.js.map +1 -0
  31. package/dist/session.d.ts +5 -0
  32. package/dist/session.d.ts.map +1 -0
  33. package/dist/session.js +250 -0
  34. package/dist/session.js.map +1 -0
  35. package/dist/voice-recognition-modelscope.d.ts +50 -0
  36. package/dist/voice-recognition-modelscope.d.ts.map +1 -0
  37. package/dist/voice-recognition-modelscope.js +171 -0
  38. package/dist/voice-recognition-modelscope.js.map +1 -0
  39. package/dist/web-server.d.ts +6 -0
  40. package/dist/web-server.d.ts.map +1 -0
  41. package/dist/web-server.js +1981 -0
  42. package/dist/web-server.js.map +1 -0
  43. package/package.json +66 -0
  44. package/public/index.html +639 -0
  45. package/public/js/terminal-asr.js +435 -0
  46. package/public/js/terminal.js +514 -0
  47. package/public/js/voice-input.js +422 -0
  48. package/scripts/postinstall.js +66 -0
  49. package/scripts/verify-install.js +124 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 LeverageAI Apps
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,175 @@
1
+ # LeverageAI Agent
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@leverageaiapps/leverageai-agent.svg)](https://www.npmjs.com/package/@leverageaiapps/leverageai-agent)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ CLI tool to forward terminal sessions to your mobile device via Cloudflare Tunnel. **Code anywhere from your pocket.**
7
+
8
+ <p align="center">
9
+ <img src="https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen" alt="Node.js">
10
+ <img src="https://img.shields.io/badge/platform-macOS%20%7C%20Linux-blue" alt="Platform">
11
+ </p>
12
+
13
+ ## Features
14
+
15
+ - 🚀 **Instant Setup** - One command to start forwarding your terminal
16
+ - 📱 **Mobile Access** - Access your terminal from any device with a browser
17
+ - 🎙️ **Voice Input** - Built-in voice recognition for hands-free coding
18
+ - 🔒 **Secure** - PIN-protected sessions with automatic IP blocking
19
+ - 🌐 **No Port Forwarding** - Uses Cloudflare Quick Tunnel (no account needed)
20
+ - ⚡ **Real-time** - WebSocket-based communication for instant feedback
21
+ - 🎯 **PTY Support** - Full terminal emulation with node-pty
22
+
23
+ ## Prerequisites
24
+
25
+ ### Install cloudflared
26
+
27
+ LeverageAI Agent requires `cloudflared` to create secure tunnels:
28
+
29
+ **macOS:**
30
+ ```bash
31
+ brew install cloudflared
32
+ ```
33
+
34
+ **Ubuntu/Debian:**
35
+ ```bash
36
+ sudo mkdir -p --mode=0755 /usr/share/keyrings
37
+ curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
38
+ echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared any main' | sudo tee /etc/apt/sources.list.d/cloudflared.list
39
+ sudo apt-get update && sudo apt-get install cloudflared
40
+ ```
41
+
42
+ **Arch Linux:**
43
+ ```bash
44
+ sudo pacman -S cloudflared
45
+ ```
46
+
47
+ For other systems, see the [official installation guide](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation/).
48
+
49
+ ## Installation
50
+
51
+ ```bash
52
+ npm install -g @leverageaiapps/leverageai-agent
53
+ ```
54
+
55
+ **Verify Installation:**
56
+ ```bash
57
+ leverageaiagent --version
58
+ ```
59
+
60
+ ## Quick Start
61
+
62
+ ```bash
63
+ # Start a terminal session
64
+ leverageaiagent start
65
+
66
+ # Start with a specific command
67
+ leverageaiagent start claude
68
+ leverageaiagent start python
69
+ leverageaiagent start vim
70
+ ```
71
+
72
+ A QR code will appear - scan it with your phone and enter the 6-digit PIN to access your terminal!
73
+
74
+ ## Usage
75
+
76
+ ### Basic Commands
77
+
78
+ ```bash
79
+ # Start a terminal session
80
+ leverageaiagent start
81
+
82
+ # Start with a custom PIN
83
+ leverageaiagent start --pin 123456
84
+
85
+ # Start with a machine name
86
+ leverageaiagent start --name "My Laptop"
87
+
88
+ # Start a specific command
89
+ leverageaiagent start claude --pin 123456
90
+ ```
91
+
92
+ ### Options
93
+
94
+ | Option | Short | Description |
95
+ |--------|-------|-------------|
96
+ | `--name <name>` | `-n` | Set a custom machine name |
97
+ | `--pin <pin>` | `-p` | Set a custom 6-digit PIN |
98
+ | `--debug-asr` | | Enable verbose ASR logging |
99
+
100
+ ### Configuration
101
+
102
+ ```bash
103
+ # Show current configuration
104
+ leverageaiagent config --show
105
+ ```
106
+
107
+ ## How It Works
108
+
109
+ 1. Run `leverageaiagent start [command]` in your terminal
110
+ 2. LeverageAI Agent starts a local web server and creates a Cloudflare tunnel
111
+ 3. A QR code appears with your unique URL
112
+ 4. Scan the QR code with your phone
113
+ 5. Enter the 6-digit PIN to access your terminal
114
+ 6. Your terminal is now accessible from your mobile device!
115
+
116
+ ### Exiting
117
+
118
+ To exit LeverageAI Agent, you can:
119
+ - Type `exit` in the terminal (or the command to exit your current program)
120
+ - Press `Ctrl+C` in the terminal where you ran `leverageaiagent start`
121
+ - Close the terminal window
122
+
123
+ When you see **"Terminal session ended."**, the session has been successfully closed.
124
+
125
+ ## Security
126
+
127
+ - **PIN Protection**: Each session requires a 6-digit PIN
128
+ - **Rate Limiting**: Max 10 failed login attempts per IP
129
+ - **Auto-blocking**: IPs are temporarily blocked after too many failures
130
+ - **Session Cookies**: Authentication persists for 24 hours
131
+
132
+ ## Troubleshooting
133
+
134
+ ### Error: posix_spawnp failed
135
+
136
+ Fix permissions on the node-pty spawn-helper:
137
+
138
+ ```bash
139
+ # macOS ARM (M1/M2/M3)
140
+ chmod +x node_modules/node-pty/prebuilds/darwin-arm64/spawn-helper
141
+
142
+ # macOS Intel
143
+ chmod +x node_modules/node-pty/prebuilds/darwin-x64/spawn-helper
144
+
145
+ # Linux x64
146
+ chmod +x node_modules/node-pty/prebuilds/linux-x64/spawn-helper
147
+ ```
148
+
149
+ ### cloudflared not found
150
+
151
+ Install cloudflared following the [Prerequisites](#prerequisites) section, then verify:
152
+
153
+ ```bash
154
+ cloudflared --version
155
+ ```
156
+
157
+ ## Contributing
158
+
159
+ Contributions are welcome! Please feel free to submit a Pull Request.
160
+
161
+ 1. Fork the repository
162
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
163
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
164
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
165
+ 5. Open a Pull Request
166
+
167
+ ## License
168
+
169
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
170
+
171
+ ## Acknowledgments
172
+
173
+ - [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/) for secure tunneling
174
+ - [node-pty](https://github.com/microsoft/node-pty) for PTY support
175
+ - [xterm.js](https://xtermjs.org/) for terminal emulation in the browser
@@ -0,0 +1,3 @@
1
+ export declare function startCapture(sessionId: string, serverUrl: string): void;
2
+ export declare function stopCapture(): void;
3
+ //# sourceMappingURL=capture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"AASA,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAuCvE;AAED,wBAAgB,WAAW,IAAI,IAAI,CASlC"}
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.startCapture = startCapture;
40
+ exports.stopCapture = stopCapture;
41
+ const axios_1 = __importDefault(require("axios"));
42
+ const readline = __importStar(require("readline"));
43
+ // Buffer for accumulating partial lines
44
+ let lineBuffer = '';
45
+ let debounceTimer = null;
46
+ const DEBOUNCE_MS = 100;
47
+ let rl = null;
48
+ function startCapture(sessionId, serverUrl) {
49
+ // Only set up stdin capture if we're receiving piped input
50
+ if (process.stdin.isTTY) {
51
+ // Running interactively (not piped), don't capture stdin
52
+ console.log(' [Capture] Running in interactive mode');
53
+ return;
54
+ }
55
+ // Create readline interface for stdin (for piped input)
56
+ rl = readline.createInterface({
57
+ input: process.stdin,
58
+ output: process.stdout,
59
+ terminal: false,
60
+ });
61
+ // Listen for lines from Claude Code (piped input)
62
+ rl.on('line', (line) => {
63
+ // Accumulate lines and debounce sending
64
+ lineBuffer += line + '\n';
65
+ if (debounceTimer) {
66
+ clearTimeout(debounceTimer);
67
+ }
68
+ debounceTimer = setTimeout(() => {
69
+ sendMessage(sessionId, serverUrl, lineBuffer.trim());
70
+ lineBuffer = '';
71
+ }, DEBOUNCE_MS);
72
+ });
73
+ rl.on('close', () => {
74
+ // Send any remaining buffer
75
+ if (lineBuffer.trim()) {
76
+ sendMessage(sessionId, serverUrl, lineBuffer.trim());
77
+ }
78
+ console.log(' Input stream closed.');
79
+ });
80
+ console.log(' [Capture] Listening for piped input...');
81
+ }
82
+ function stopCapture() {
83
+ if (rl) {
84
+ rl.close();
85
+ rl = null;
86
+ }
87
+ if (debounceTimer) {
88
+ clearTimeout(debounceTimer);
89
+ debounceTimer = null;
90
+ }
91
+ }
92
+ async function sendMessage(sessionId, serverUrl, text) {
93
+ if (!text)
94
+ return;
95
+ try {
96
+ // Try to parse as Claude Code message format
97
+ const content = parseClaudeCodeMessage(text);
98
+ await axios_1.default.post(`${serverUrl}/api/sessions/${sessionId}/messages`, {
99
+ role: 'agent',
100
+ content,
101
+ });
102
+ }
103
+ catch (error) {
104
+ // Silently fail - we don't want to interrupt the user
105
+ if (process.env.DEBUG) {
106
+ console.error('Failed to send message:', error);
107
+ }
108
+ }
109
+ }
110
+ // Parse Claude Code output into structured format
111
+ function parseClaudeCodeMessage(text) {
112
+ // Check for tool use patterns
113
+ const toolUseMatch = text.match(/^(?:Using|Running|Executing|Calling)\s+(\w+)/i);
114
+ if (toolUseMatch) {
115
+ return {
116
+ type: 'tool-call',
117
+ name: toolUseMatch[1],
118
+ input: { description: text },
119
+ };
120
+ }
121
+ // Check for code blocks
122
+ if (text.includes('```')) {
123
+ return {
124
+ type: 'text',
125
+ text,
126
+ };
127
+ }
128
+ // Default to text
129
+ return {
130
+ type: 'text',
131
+ text,
132
+ };
133
+ }
134
+ //# sourceMappingURL=capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Start Cloudflare Quick Tunnel
3
+ * Returns the generated tunnel URL
4
+ */
5
+ export declare function startTunnel(localPort?: number): Promise<string>;
6
+ export declare function stopTunnel(): void;
7
+ export declare function getTunnelUrl(): string | null;
8
+ export declare function isTunnelRunning(): boolean;
9
+ //# sourceMappingURL=cloudflare-tunnel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare-tunnel.d.ts","sourceRoot":"","sources":["../src/cloudflare-tunnel.ts"],"names":[],"mappings":"AAmFA;;;GAGG;AACH,wBAAgB,WAAW,CAAC,SAAS,GAAE,MAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAcrE;AAqFD,wBAAgB,UAAU,IAAI,IAAI,CAMjC;AAED,wBAAgB,YAAY,IAAI,MAAM,GAAG,IAAI,CAE5C;AAED,wBAAgB,eAAe,IAAI,OAAO,CAEzC"}
@@ -0,0 +1,218 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.startTunnel = startTunnel;
37
+ exports.stopTunnel = stopTunnel;
38
+ exports.getTunnelUrl = getTunnelUrl;
39
+ exports.isTunnelRunning = isTunnelRunning;
40
+ const child_process_1 = require("child_process");
41
+ const os = __importStar(require("os"));
42
+ let tunnelProcess = null;
43
+ let tunnelUrl = null;
44
+ /**
45
+ * Get platform-specific installation instructions for cloudflared
46
+ */
47
+ function getInstallationInstructions() {
48
+ const platform = os.platform();
49
+ switch (platform) {
50
+ case 'darwin': // macOS
51
+ return `cloudflared is required for LeverageAI Agent to work. Please install it using Homebrew:
52
+
53
+ brew install cloudflared
54
+
55
+ Alternatively, you can download it from: https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation/`;
56
+ case 'linux':
57
+ // Detect Linux distribution
58
+ const fs = require('fs');
59
+ let distroInstructions = '';
60
+ try {
61
+ // Check for common package managers
62
+ if (fs.existsSync('/usr/bin/apt') || fs.existsSync('/usr/bin/apt-get')) {
63
+ // Debian/Ubuntu
64
+ distroInstructions = ` # Add Cloudflare GPG key
65
+ sudo mkdir -p --mode=0755 /usr/share/keyrings
66
+ curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
67
+
68
+ # Add Cloudflare repository
69
+ echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared any main' | sudo tee /etc/apt/sources.list.d/cloudflared.list
70
+
71
+ # Install cloudflared
72
+ sudo apt-get update && sudo apt-get install cloudflared`;
73
+ }
74
+ else if (fs.existsSync('/usr/bin/yum')) {
75
+ // CentOS/RHEL
76
+ distroInstructions = ` # Add Cloudflare repository
77
+ curl -fsSl https://pkg.cloudflare.com/cloudflared.repo | sudo tee /etc/yum.repos.d/cloudflared.repo
78
+
79
+ # Install cloudflared
80
+ sudo yum update && sudo yum install cloudflared`;
81
+ }
82
+ else if (fs.existsSync('/usr/bin/dnf')) {
83
+ // Fedora
84
+ distroInstructions = ` # Add Cloudflare repository
85
+ sudo dnf config-manager --add-repo https://pkg.cloudflare.com/cloudflared.repo
86
+
87
+ # Install cloudflared
88
+ sudo dnf install cloudflared`;
89
+ }
90
+ else if (fs.existsSync('/usr/bin/pacman')) {
91
+ // Arch Linux
92
+ distroInstructions = ` # Install from community repository
93
+ sudo pacman -S cloudflared`;
94
+ }
95
+ else {
96
+ // Generic Linux
97
+ distroInstructions = ` # Download and install manually
98
+ curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o cloudflared
99
+ chmod +x cloudflared
100
+ sudo mv cloudflared /usr/local/bin/`;
101
+ }
102
+ }
103
+ catch (error) {
104
+ // Fallback to generic instructions
105
+ distroInstructions = ` # Download and install manually
106
+ curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o cloudflared
107
+ chmod +x cloudflared
108
+ sudo mv cloudflared /usr/local/bin/`;
109
+ }
110
+ return `cloudflared is required for LeverageAI Agent to work. Please install it:
111
+
112
+ ${distroInstructions}
113
+
114
+ For other distributions, see: https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation/`;
115
+ default:
116
+ return `cloudflared is required for LeverageAI Agent to work. Please install it from:
117
+ https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation/`;
118
+ }
119
+ }
120
+ /**
121
+ * Start Cloudflare Quick Tunnel
122
+ * Returns the generated tunnel URL
123
+ */
124
+ function startTunnel(localPort = 4020) {
125
+ return new Promise((resolve, reject) => {
126
+ // Check if cloudflared is installed
127
+ const which = (0, child_process_1.spawn)('which', ['cloudflared']);
128
+ which.on('close', (code) => {
129
+ if (code !== 0) {
130
+ reject(new Error(getInstallationInstructions()));
131
+ return;
132
+ }
133
+ startTunnelProcess(localPort, resolve, reject);
134
+ });
135
+ });
136
+ }
137
+ function startTunnelProcess(localPort, resolve, reject) {
138
+ // Create environment without proxy settings for cloudflared
139
+ const env = { ...process.env };
140
+ delete env.HTTP_PROXY;
141
+ delete env.HTTPS_PROXY;
142
+ delete env.http_proxy;
143
+ delete env.https_proxy;
144
+ delete env.ALL_PROXY;
145
+ delete env.all_proxy;
146
+ // Ensure localhost bypasses proxy
147
+ env.NO_PROXY = 'localhost,127.0.0.1,*.local';
148
+ env.no_proxy = env.NO_PROXY;
149
+ // Use --url for quick tunnel (no account needed)
150
+ // Bypass proxy to avoid TLS handshake issues
151
+ tunnelProcess = (0, child_process_1.spawn)('cloudflared', ['tunnel', '--url', `http://localhost:${localPort}`], {
152
+ stdio: ['ignore', 'pipe', 'pipe'],
153
+ env: env,
154
+ });
155
+ let urlFound = false;
156
+ const timeout = setTimeout(() => {
157
+ if (!urlFound) {
158
+ reject(new Error('Timeout waiting for tunnel URL'));
159
+ stopTunnel();
160
+ }
161
+ }, 30000); // 30 second timeout
162
+ // cloudflared outputs the URL to stderr
163
+ tunnelProcess.stderr?.on('data', (data) => {
164
+ const output = data.toString();
165
+ // Debug output
166
+ if (process.env.DEBUG) {
167
+ }
168
+ // Look for the tunnel URL in the output
169
+ // Format: "https://xxx-yyy-zzz.trycloudflare.com"
170
+ const urlMatch = output.match(/https:\/\/[a-z0-9-]+\.trycloudflare\.com/);
171
+ if (urlMatch && !urlFound) {
172
+ urlFound = true;
173
+ clearTimeout(timeout);
174
+ tunnelUrl = urlMatch[0];
175
+ resolve(tunnelUrl);
176
+ }
177
+ });
178
+ tunnelProcess.stdout?.on('data', (data) => {
179
+ const output = data.toString();
180
+ if (process.env.DEBUG) {
181
+ }
182
+ // Also check stdout for URL
183
+ const urlMatch = output.match(/https:\/\/[a-z0-9-]+\.trycloudflare\.com/);
184
+ if (urlMatch && !urlFound) {
185
+ urlFound = true;
186
+ clearTimeout(timeout);
187
+ tunnelUrl = urlMatch[0];
188
+ resolve(tunnelUrl);
189
+ }
190
+ });
191
+ tunnelProcess.on('error', (err) => {
192
+ clearTimeout(timeout);
193
+ console.error(' [Tunnel] Failed to start:', err);
194
+ reject(err);
195
+ });
196
+ tunnelProcess.on('close', (code) => {
197
+ if (!urlFound) {
198
+ clearTimeout(timeout);
199
+ reject(new Error(`cloudflared exited with code ${code}`));
200
+ }
201
+ tunnelProcess = null;
202
+ tunnelUrl = null;
203
+ });
204
+ }
205
+ function stopTunnel() {
206
+ if (tunnelProcess) {
207
+ tunnelProcess.kill('SIGTERM');
208
+ tunnelProcess = null;
209
+ tunnelUrl = null;
210
+ }
211
+ }
212
+ function getTunnelUrl() {
213
+ return tunnelUrl;
214
+ }
215
+ function isTunnelRunning() {
216
+ return tunnelProcess !== null && !tunnelProcess.killed;
217
+ }
218
+ //# sourceMappingURL=cloudflare-tunnel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare-tunnel.js","sourceRoot":"","sources":["../src/cloudflare-tunnel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface Config {
2
+ serverUrl: string;
3
+ machineId: string;
4
+ }
5
+ export declare function getConfig(): Config;
6
+ export declare function setConfig(updates: Partial<Config>): void;
7
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,MAAM;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACrB;AAgBD,wBAAgB,SAAS,IAAI,MAAM,CAalC;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI,CAexD"}