@leverageaiapps/theseus-server 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.
- package/LICENSE +21 -0
- package/README.md +165 -0
- package/dist/capture.d.ts +3 -0
- package/dist/capture.d.ts.map +1 -0
- package/dist/capture.js +134 -0
- package/dist/capture.js.map +1 -0
- package/dist/cloudflare-tunnel.d.ts +9 -0
- package/dist/cloudflare-tunnel.d.ts.map +1 -0
- package/dist/cloudflare-tunnel.js +218 -0
- package/dist/cloudflare-tunnel.js.map +1 -0
- package/dist/config.d.ts +7 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +84 -0
- package/dist/config.js.map +1 -0
- package/dist/context-extractor.d.ts +17 -0
- package/dist/context-extractor.d.ts.map +1 -0
- package/dist/context-extractor.js +118 -0
- package/dist/context-extractor.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/pty.d.ts +20 -0
- package/dist/pty.d.ts.map +1 -0
- package/dist/pty.js +148 -0
- package/dist/pty.js.map +1 -0
- package/dist/relay.d.ts +5 -0
- package/dist/relay.d.ts.map +1 -0
- package/dist/relay.js +131 -0
- package/dist/relay.js.map +1 -0
- package/dist/session.d.ts +5 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +257 -0
- package/dist/session.js.map +1 -0
- package/dist/voice-recognition-modelscope.d.ts +50 -0
- package/dist/voice-recognition-modelscope.d.ts.map +1 -0
- package/dist/voice-recognition-modelscope.js +171 -0
- package/dist/voice-recognition-modelscope.js.map +1 -0
- package/dist/web-server.d.ts +6 -0
- package/dist/web-server.d.ts.map +1 -0
- package/dist/web-server.js +1971 -0
- package/dist/web-server.js.map +1 -0
- package/package.json +66 -0
- package/public/index.html +639 -0
- package/public/js/terminal-asr.js +508 -0
- package/public/js/terminal.js +514 -0
- package/public/js/voice-input.js +422 -0
- package/scripts/postinstall.js +66 -0
- 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,165 @@
|
|
|
1
|
+
# Theseus Server
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@leverageaiapps/theseus-server)
|
|
4
|
+
[](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
|
+
- 🔒 **Secure** - PIN-protected sessions with automatic IP blocking
|
|
18
|
+
- 🌐 **No Port Forwarding** - Uses Cloudflare Quick Tunnel (no account needed)
|
|
19
|
+
- ⚡ **Real-time** - WebSocket-based communication for instant feedback
|
|
20
|
+
- 🎯 **PTY Support** - Full terminal emulation with node-pty
|
|
21
|
+
|
|
22
|
+
## Prerequisites
|
|
23
|
+
|
|
24
|
+
### Install cloudflared
|
|
25
|
+
|
|
26
|
+
Theseus requires `cloudflared` to create secure tunnels:
|
|
27
|
+
|
|
28
|
+
**macOS:**
|
|
29
|
+
```bash
|
|
30
|
+
brew install cloudflared
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Ubuntu/Debian:**
|
|
34
|
+
```bash
|
|
35
|
+
sudo mkdir -p --mode=0755 /usr/share/keyrings
|
|
36
|
+
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
|
|
37
|
+
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
|
|
38
|
+
sudo apt-get update && sudo apt-get install cloudflared
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Arch Linux:**
|
|
42
|
+
```bash
|
|
43
|
+
sudo pacman -S cloudflared
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
For other systems, see the [official installation guide](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation/).
|
|
47
|
+
|
|
48
|
+
## Installation
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npm install -g @leverageaiapps/theseus-server
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Verify Installation:**
|
|
55
|
+
```bash
|
|
56
|
+
theseus --version
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Quick Start
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# Start a terminal session
|
|
63
|
+
theseus start
|
|
64
|
+
|
|
65
|
+
# Start with a specific command
|
|
66
|
+
theseus start claude
|
|
67
|
+
theseus start python
|
|
68
|
+
theseus start vim
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
A QR code will appear - scan it with your phone and enter the 6-digit PIN to access your terminal!
|
|
72
|
+
|
|
73
|
+
## Usage
|
|
74
|
+
|
|
75
|
+
### Basic Commands
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Start a terminal session
|
|
79
|
+
theseus start
|
|
80
|
+
|
|
81
|
+
# Start with a custom PIN
|
|
82
|
+
theseus start --pin 123456
|
|
83
|
+
|
|
84
|
+
# Start with a machine name
|
|
85
|
+
theseus start --name "My Laptop"
|
|
86
|
+
|
|
87
|
+
# Start a specific command
|
|
88
|
+
theseus start claude --pin 123456
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Options
|
|
92
|
+
|
|
93
|
+
| Option | Short | Description |
|
|
94
|
+
|--------|-------|-------------|
|
|
95
|
+
| `--name <name>` | `-n` | Set a custom machine name |
|
|
96
|
+
| `--pin <pin>` | `-p` | Set a custom 6-digit PIN |
|
|
97
|
+
| `--debug-asr` | | Enable verbose ASR logging |
|
|
98
|
+
|
|
99
|
+
### Configuration
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Show current configuration
|
|
103
|
+
theseus config --show
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## How It Works
|
|
107
|
+
|
|
108
|
+
1. Run `theseus start [command]` in your terminal
|
|
109
|
+
2. Theseus starts a local web server and creates a Cloudflare tunnel
|
|
110
|
+
3. A QR code appears with your unique URL
|
|
111
|
+
4. Scan the QR code with your phone
|
|
112
|
+
5. Enter the 6-digit PIN to access your terminal
|
|
113
|
+
6. Your terminal is now accessible from your mobile device!
|
|
114
|
+
|
|
115
|
+
## Security
|
|
116
|
+
|
|
117
|
+
- **PIN Protection**: Each session requires a 6-digit PIN
|
|
118
|
+
- **Rate Limiting**: Max 10 failed login attempts per IP
|
|
119
|
+
- **Auto-blocking**: IPs are temporarily blocked after too many failures
|
|
120
|
+
- **Session Cookies**: Authentication persists for 24 hours
|
|
121
|
+
|
|
122
|
+
## Troubleshooting
|
|
123
|
+
|
|
124
|
+
### Error: posix_spawnp failed
|
|
125
|
+
|
|
126
|
+
Fix permissions on the node-pty spawn-helper:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
# macOS ARM (M1/M2/M3)
|
|
130
|
+
chmod +x node_modules/node-pty/prebuilds/darwin-arm64/spawn-helper
|
|
131
|
+
|
|
132
|
+
# macOS Intel
|
|
133
|
+
chmod +x node_modules/node-pty/prebuilds/darwin-x64/spawn-helper
|
|
134
|
+
|
|
135
|
+
# Linux x64
|
|
136
|
+
chmod +x node_modules/node-pty/prebuilds/linux-x64/spawn-helper
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### cloudflared not found
|
|
140
|
+
|
|
141
|
+
Install cloudflared following the [Prerequisites](#prerequisites) section, then verify:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
cloudflared --version
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Contributing
|
|
148
|
+
|
|
149
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
150
|
+
|
|
151
|
+
1. Fork the repository
|
|
152
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
153
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
154
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
155
|
+
5. Open a Pull Request
|
|
156
|
+
|
|
157
|
+
## License
|
|
158
|
+
|
|
159
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
160
|
+
|
|
161
|
+
## Acknowledgments
|
|
162
|
+
|
|
163
|
+
- [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/) for secure tunneling
|
|
164
|
+
- [node-pty](https://github.com/microsoft/node-pty) for PTY support
|
|
165
|
+
- [xterm.js](https://xtermjs.org/) for terminal emulation in the browser
|
|
@@ -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"}
|
package/dist/capture.js
ADDED
|
@@ -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 Theseus 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 Theseus 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 Theseus 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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"}
|
package/dist/config.d.ts
ADDED
|
@@ -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"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
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.getConfig = getConfig;
|
|
37
|
+
exports.setConfig = setConfig;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const os = __importStar(require("os"));
|
|
41
|
+
const CONFIG_DIR = path.join(os.homedir(), '.codingin');
|
|
42
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
43
|
+
const DEFAULT_CONFIG = {
|
|
44
|
+
serverUrl: process.env.CODINGIN_SERVER_URL || 'https://codingin.futuretech.social',
|
|
45
|
+
machineId: generateMachineId(),
|
|
46
|
+
};
|
|
47
|
+
function generateMachineId() {
|
|
48
|
+
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
|
49
|
+
let result = '';
|
|
50
|
+
for (let i = 0; i < 16; i++) {
|
|
51
|
+
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
52
|
+
}
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
function getConfig() {
|
|
56
|
+
try {
|
|
57
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
58
|
+
const data = fs.readFileSync(CONFIG_FILE, 'utf-8');
|
|
59
|
+
return { ...DEFAULT_CONFIG, ...JSON.parse(data) };
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
console.error('Error reading config:', error);
|
|
64
|
+
}
|
|
65
|
+
// Create default config
|
|
66
|
+
setConfig(DEFAULT_CONFIG);
|
|
67
|
+
return DEFAULT_CONFIG;
|
|
68
|
+
}
|
|
69
|
+
function setConfig(updates) {
|
|
70
|
+
try {
|
|
71
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
72
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
73
|
+
}
|
|
74
|
+
const current = fs.existsSync(CONFIG_FILE)
|
|
75
|
+
? JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf-8'))
|
|
76
|
+
: DEFAULT_CONFIG;
|
|
77
|
+
const newConfig = { ...current, ...updates };
|
|
78
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(newConfig, null, 2));
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
console.error('Error writing config:', error);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=config.js.map
|