cosmoremote 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/README.md +44 -0
- package/dist/bridge.d.ts +6 -0
- package/dist/bridge.js +266 -0
- package/dist/bridge.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +23 -0
- package/dist/cli.js.map +1 -0
- package/dist/detect.d.ts +5 -0
- package/dist/detect.js +42 -0
- package/dist/detect.js.map +1 -0
- package/dist/session.d.ts +18 -0
- package/dist/session.js +104 -0
- package/dist/session.js.map +1 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# CosmoRemote Bridge
|
|
2
|
+
|
|
3
|
+
CLI daemon that runs on your Mac and connects Claude Code / Codex to the CosmoRemote app.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Run
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm run dev # Development
|
|
15
|
+
cosmoremote start # After global install
|
|
16
|
+
cosmoremote start --port 4422 # Custom port
|
|
17
|
+
cosmoremote start --backend wss://your-backend.com # Enable remote relay
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How it works
|
|
21
|
+
|
|
22
|
+
1. Detects which CLIs are available (Claude Code, Codex)
|
|
23
|
+
2. Starts a local WebSocket server on port 4422
|
|
24
|
+
3. Generates a pairing QR code
|
|
25
|
+
4. App scans QR → connects via WebSocket
|
|
26
|
+
5. App sends prompts → bridge spawns CLI process → streams output back
|
|
27
|
+
|
|
28
|
+
## WebSocket Protocol
|
|
29
|
+
|
|
30
|
+
All messages use JSON envelope:
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{ "type": "prompt|output|error|done|kill", "sessionId": "...", "content": "..." }
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Inbound (from app)
|
|
37
|
+
- `prompt` — send a prompt to the CLI (includes `cli`, `workingDir`)
|
|
38
|
+
- `kill` — kill a running session
|
|
39
|
+
|
|
40
|
+
### Outbound (to app)
|
|
41
|
+
- `paired` — pairing confirmed, includes `sessionToken`
|
|
42
|
+
- `output` — streaming output chunk
|
|
43
|
+
- `error` — error message
|
|
44
|
+
- `done` — session complete, includes full output
|
package/dist/bridge.d.ts
ADDED
package/dist/bridge.js
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.startBridge = startBridge;
|
|
7
|
+
const ws_1 = require("ws");
|
|
8
|
+
const uuid_1 = require("uuid");
|
|
9
|
+
const os_1 = require("os");
|
|
10
|
+
const qrcode_terminal_1 = __importDefault(require("qrcode-terminal"));
|
|
11
|
+
const detect_1 = require("./detect");
|
|
12
|
+
const session_1 = require("./session");
|
|
13
|
+
const sessions = new Map();
|
|
14
|
+
let pairToken;
|
|
15
|
+
let validatedTokens = new Set();
|
|
16
|
+
let clis;
|
|
17
|
+
// Local rate limiter: max 20 messages per day per session token
|
|
18
|
+
const localMessageCounts = new Map();
|
|
19
|
+
const LOCAL_DAILY_LIMIT = 20;
|
|
20
|
+
function checkLocalLimit(sessionToken) {
|
|
21
|
+
const now = Date.now();
|
|
22
|
+
let entry = localMessageCounts.get(sessionToken);
|
|
23
|
+
if (!entry || now > entry.resetAt) {
|
|
24
|
+
// Reset at midnight
|
|
25
|
+
const tomorrow = new Date();
|
|
26
|
+
tomorrow.setHours(24, 0, 0, 0);
|
|
27
|
+
entry = { count: 0, resetAt: tomorrow.getTime() };
|
|
28
|
+
localMessageCounts.set(sessionToken, entry);
|
|
29
|
+
}
|
|
30
|
+
if (entry.count >= LOCAL_DAILY_LIMIT) {
|
|
31
|
+
return { allowed: false, used: entry.count };
|
|
32
|
+
}
|
|
33
|
+
entry.count++;
|
|
34
|
+
return { allowed: true, used: entry.count };
|
|
35
|
+
}
|
|
36
|
+
function getLocalIP() {
|
|
37
|
+
const interfaces = (0, os_1.networkInterfaces)();
|
|
38
|
+
for (const name of Object.keys(interfaces)) {
|
|
39
|
+
for (const iface of interfaces[name] || []) {
|
|
40
|
+
if (iface.family === "IPv4" && !iface.internal) {
|
|
41
|
+
return iface.address;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return "127.0.0.1";
|
|
46
|
+
}
|
|
47
|
+
async function startBridge(opts) {
|
|
48
|
+
clis = (0, detect_1.detectCLIs)();
|
|
49
|
+
pairToken = (0, uuid_1.v4)();
|
|
50
|
+
const localIP = getLocalIP();
|
|
51
|
+
console.log("\n ╔══════════════════════════════════════╗");
|
|
52
|
+
console.log(" ║ CosmoRemote Bridge ║");
|
|
53
|
+
console.log(" ╚══════════════════════════════════════╝\n");
|
|
54
|
+
console.log(" Available CLIs:");
|
|
55
|
+
console.log(` Claude Code: ${clis.claude || "not found"}`);
|
|
56
|
+
console.log(` Codex: ${clis.codex || "not found"}`);
|
|
57
|
+
console.log();
|
|
58
|
+
if (!clis.claude && !clis.codex) {
|
|
59
|
+
console.error(" ✗ No supported CLIs found. Install Claude Code or Codex first.");
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
const wss = new ws_1.WebSocketServer({ port: opts.port });
|
|
63
|
+
console.log(` Local server: ws://${localIP}:${opts.port}`);
|
|
64
|
+
console.log(` Pair token: ${pairToken}\n`);
|
|
65
|
+
const qrData = `cosmoremote://pair?ip=${localIP}&port=${opts.port}&token=${pairToken}`;
|
|
66
|
+
console.log(" Scan this QR code with the CosmoRemote app:\n");
|
|
67
|
+
qrcode_terminal_1.default.generate(qrData, { small: true }, (code) => {
|
|
68
|
+
const indented = code
|
|
69
|
+
.split("\n")
|
|
70
|
+
.map((l) => " " + l)
|
|
71
|
+
.join("\n");
|
|
72
|
+
console.log(indented);
|
|
73
|
+
console.log();
|
|
74
|
+
console.log(" Waiting for connections...\n");
|
|
75
|
+
});
|
|
76
|
+
wss.on("connection", (ws, req) => {
|
|
77
|
+
const url = new URL(req.url || "/", `http://localhost:${opts.port}`);
|
|
78
|
+
const token = url.searchParams.get("token");
|
|
79
|
+
// Validate token
|
|
80
|
+
let connToken;
|
|
81
|
+
if (token === pairToken) {
|
|
82
|
+
// First connection with pair token — issue a session token
|
|
83
|
+
connToken = (0, uuid_1.v4)();
|
|
84
|
+
validatedTokens.add(connToken);
|
|
85
|
+
ws.send(JSON.stringify({ type: "paired", sessionToken: connToken }));
|
|
86
|
+
console.log(" ✓ New device paired");
|
|
87
|
+
}
|
|
88
|
+
else if (token && validatedTokens.has(token)) {
|
|
89
|
+
connToken = token;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
ws.close(4001, "Invalid token");
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
handleConnection(ws, connToken);
|
|
96
|
+
});
|
|
97
|
+
// Connect to backend relay if URL provided
|
|
98
|
+
if (opts.backendUrl) {
|
|
99
|
+
connectToBackendRelay(opts.backendUrl);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function handleConnection(ws, sessionToken) {
|
|
103
|
+
ws.on("message", (raw) => {
|
|
104
|
+
try {
|
|
105
|
+
const msg = JSON.parse(raw.toString());
|
|
106
|
+
if (msg.type === "prompt") {
|
|
107
|
+
const limit = checkLocalLimit(sessionToken);
|
|
108
|
+
if (!limit.allowed) {
|
|
109
|
+
ws.send(JSON.stringify({
|
|
110
|
+
type: "error",
|
|
111
|
+
sessionId: msg.sessionId,
|
|
112
|
+
content: `Daily message limit reached (${limit.used}/${LOCAL_DAILY_LIMIT}). Upgrade to Pro for unlimited.`,
|
|
113
|
+
}));
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
handlePrompt(ws, msg);
|
|
117
|
+
}
|
|
118
|
+
if (msg.type === "kill") {
|
|
119
|
+
const session = sessions.get(msg.sessionId);
|
|
120
|
+
if (session) {
|
|
121
|
+
session.kill();
|
|
122
|
+
ws.send(JSON.stringify({ type: "done", sessionId: msg.sessionId, content: "[killed]" }));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// ignore malformed
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
ws.on("close", () => {
|
|
131
|
+
console.log(" Client disconnected");
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
function handlePrompt(ws, msg) {
|
|
135
|
+
const cliType = msg.cli?.toUpperCase() === "CODEX" ? "codex" : "claude";
|
|
136
|
+
const binary = cliType === "codex" ? clis.codex : clis.claude;
|
|
137
|
+
if (!binary) {
|
|
138
|
+
ws.send(JSON.stringify({
|
|
139
|
+
type: "error",
|
|
140
|
+
sessionId: msg.sessionId,
|
|
141
|
+
content: `${cliType} CLI not found on this machine`,
|
|
142
|
+
}));
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
let session = sessions.get(msg.sessionId);
|
|
146
|
+
if (!session) {
|
|
147
|
+
session = new session_1.CLISession({
|
|
148
|
+
sessionId: msg.sessionId,
|
|
149
|
+
cliBinary: binary,
|
|
150
|
+
workingDir: msg.workingDir || process.cwd(),
|
|
151
|
+
});
|
|
152
|
+
sessions.set(msg.sessionId, session);
|
|
153
|
+
session.on("output", (text) => {
|
|
154
|
+
ws.send(JSON.stringify({ type: "output", sessionId: msg.sessionId, content: text }));
|
|
155
|
+
});
|
|
156
|
+
session.on("error", (text) => {
|
|
157
|
+
ws.send(JSON.stringify({ type: "error", sessionId: msg.sessionId, content: text }));
|
|
158
|
+
});
|
|
159
|
+
session.on("done", (result) => {
|
|
160
|
+
ws.send(JSON.stringify({
|
|
161
|
+
type: "done",
|
|
162
|
+
sessionId: msg.sessionId,
|
|
163
|
+
content: result.fullOutput,
|
|
164
|
+
}));
|
|
165
|
+
sessions.delete(msg.sessionId);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
session.sendPrompt(msg.content);
|
|
169
|
+
}
|
|
170
|
+
function connectToBackendRelay(backendUrl) {
|
|
171
|
+
const connect = () => {
|
|
172
|
+
const url = `${backendUrl}/relay/bridge?token=${pairToken}`;
|
|
173
|
+
const ws = new ws_1.WebSocket(url);
|
|
174
|
+
let pingInterval = null;
|
|
175
|
+
ws.on("open", () => {
|
|
176
|
+
console.log(" ✓ Connected to backend relay");
|
|
177
|
+
setRelayWs(ws);
|
|
178
|
+
// Send keepalive ping every 10s to prevent Azure idle timeout
|
|
179
|
+
pingInterval = setInterval(() => {
|
|
180
|
+
if (ws.readyState === ws_1.WebSocket.OPEN) {
|
|
181
|
+
ws.ping();
|
|
182
|
+
ws.send(JSON.stringify({ type: "ping" }));
|
|
183
|
+
}
|
|
184
|
+
}, 10_000);
|
|
185
|
+
});
|
|
186
|
+
ws.on("message", (raw) => {
|
|
187
|
+
try {
|
|
188
|
+
const msg = JSON.parse(raw.toString());
|
|
189
|
+
if (msg.type === "pong")
|
|
190
|
+
return; // keepalive response
|
|
191
|
+
if (msg.type === "prompt") {
|
|
192
|
+
handlePromptFromRelay(ws, msg);
|
|
193
|
+
}
|
|
194
|
+
if (msg.type === "kill") {
|
|
195
|
+
const session = sessions.get(msg.sessionId);
|
|
196
|
+
if (session)
|
|
197
|
+
session.kill();
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
// ignore
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
// Handle WebSocket protocol-level pings from server
|
|
205
|
+
ws.on("ping", () => {
|
|
206
|
+
ws.pong();
|
|
207
|
+
});
|
|
208
|
+
ws.on("close", () => {
|
|
209
|
+
if (pingInterval)
|
|
210
|
+
clearInterval(pingInterval);
|
|
211
|
+
console.log(" Backend relay disconnected. Reconnecting in 5s...");
|
|
212
|
+
setTimeout(connect, 5000);
|
|
213
|
+
});
|
|
214
|
+
ws.on("error", () => {
|
|
215
|
+
// will trigger close event
|
|
216
|
+
});
|
|
217
|
+
};
|
|
218
|
+
connect();
|
|
219
|
+
}
|
|
220
|
+
// Keep a reference to the current relay WebSocket that can be updated on reconnect
|
|
221
|
+
let currentRelayWs = null;
|
|
222
|
+
function setRelayWs(ws) {
|
|
223
|
+
currentRelayWs = ws;
|
|
224
|
+
}
|
|
225
|
+
function relaySend(data) {
|
|
226
|
+
if (currentRelayWs && currentRelayWs.readyState === ws_1.WebSocket.OPEN) {
|
|
227
|
+
currentRelayWs.send(JSON.stringify(data));
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
console.log(" ⚠ Relay not connected, cannot send:", data.type);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
function handlePromptFromRelay(_relayWs, msg) {
|
|
234
|
+
console.log(` → Received prompt for session ${msg.sessionId}: "${msg.content.substring(0, 50)}"`);
|
|
235
|
+
const cliType = msg.cli?.toUpperCase() === "CODEX" ? "codex" : "claude";
|
|
236
|
+
const binary = cliType === "codex" ? clis.codex : clis.claude;
|
|
237
|
+
if (!binary) {
|
|
238
|
+
console.log(` ✗ ${cliType} CLI not found`);
|
|
239
|
+
relaySend({ type: "error", sessionId: msg.sessionId, content: `${cliType} CLI not found on this machine` });
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
console.log(` → Spawning ${cliType} at ${binary} in ${msg.workingDir}`);
|
|
243
|
+
let session = sessions.get(msg.sessionId);
|
|
244
|
+
if (!session) {
|
|
245
|
+
session = new session_1.CLISession({
|
|
246
|
+
sessionId: msg.sessionId,
|
|
247
|
+
cliBinary: binary,
|
|
248
|
+
workingDir: msg.workingDir || process.cwd(),
|
|
249
|
+
});
|
|
250
|
+
sessions.set(msg.sessionId, session);
|
|
251
|
+
session.on("output", (text) => {
|
|
252
|
+
relaySend({ type: "output", sessionId: msg.sessionId, content: text });
|
|
253
|
+
});
|
|
254
|
+
session.on("error", (text) => {
|
|
255
|
+
console.log(` ✗ Session error: ${text.substring(0, 100)}`);
|
|
256
|
+
relaySend({ type: "error", sessionId: msg.sessionId, content: text });
|
|
257
|
+
});
|
|
258
|
+
session.on("done", (result) => {
|
|
259
|
+
console.log(` ✓ Session done (exit ${result.code}), output length: ${result.fullOutput.length}`);
|
|
260
|
+
relaySend({ type: "done", sessionId: msg.sessionId, content: result.fullOutput });
|
|
261
|
+
sessions.delete(msg.sessionId);
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
session.sendPrompt(msg.content);
|
|
265
|
+
}
|
|
266
|
+
//# sourceMappingURL=bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":";;;;;AAkDA,kCA8DC;AAhHD,2BAAgD;AAChD,+BAAkC;AAClC,2BAAuC;AACvC,sEAAqC;AACrC,qCAAqD;AACrD,uCAAuC;AAOvC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAsB,CAAC;AAC/C,IAAI,SAAiB,CAAC;AACtB,IAAI,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;AACxC,IAAI,IAAmB,CAAC;AAExB,gEAAgE;AAChE,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAA8C,CAAC;AACjF,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAE7B,SAAS,eAAe,CAAC,YAAoB;IAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,IAAI,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACjD,IAAI,CAAC,KAAK,IAAI,GAAG,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC;QAClC,oBAAoB;QACpB,MAAM,QAAQ,GAAG,IAAI,IAAI,EAAE,CAAC;QAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/B,KAAK,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;QAClD,kBAAkB,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,IAAI,iBAAiB,EAAE,CAAC;QACrC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;IAC/C,CAAC;IACD,KAAK,CAAC,KAAK,EAAE,CAAC;IACd,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;AAC9C,CAAC;AAED,SAAS,UAAU;IACjB,MAAM,UAAU,GAAG,IAAA,sBAAiB,GAAE,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3C,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YAC3C,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;gBAC/C,OAAO,KAAK,CAAC,OAAO,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAEM,KAAK,UAAU,WAAW,CAAC,IAAmB;IACnD,IAAI,GAAG,IAAA,mBAAU,GAAE,CAAC;IACpB,SAAS,GAAG,IAAA,SAAI,GAAE,CAAC;IACnB,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;IAE5D,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACjC,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,CAAC,MAAM,IAAI,WAAW,EAAE,CAAC,CAAC;IAC9D,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,CAAC,KAAK,IAAI,WAAW,EAAE,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAClF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,oBAAe,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAErD,OAAO,CAAC,GAAG,CAAC,wBAAwB,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC,mBAAmB,SAAS,IAAI,CAAC,CAAC;IAE9C,MAAM,MAAM,GAAG,yBAAyB,OAAO,SAAS,IAAI,CAAC,IAAI,UAAU,SAAS,EAAE,CAAC;IACvF,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;IAC/D,yBAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,IAAY,EAAE,EAAE;QACxD,MAAM,QAAQ,GAAG,IAAI;aAClB,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;aAC9B,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtB,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE;QAC/B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,oBAAoB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACrE,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAE5C,iBAAiB;QACjB,IAAI,SAAiB,CAAC;QACtB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,2DAA2D;YAC3D,SAAS,GAAG,IAAA,SAAI,GAAE,CAAC;YACnB,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC/B,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;YACrE,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QACvC,CAAC;aAAM,IAAI,KAAK,IAAI,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/C,SAAS,GAAG,KAAK,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;YAChC,OAAO;QACT,CAAC;QAED,gBAAgB,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,2CAA2C;IAC3C,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,qBAAqB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACzC,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,EAAa,EAAE,YAAoB;IAC3D,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,EAAE;QACvB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;YAEvC,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC1B,MAAM,KAAK,GAAG,eAAe,CAAC,YAAY,CAAC,CAAC;gBAC5C,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;oBACnB,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;wBACrB,IAAI,EAAE,OAAO;wBACb,SAAS,EAAE,GAAG,CAAC,SAAS;wBACxB,OAAO,EAAE,gCAAgC,KAAK,CAAC,IAAI,IAAI,iBAAiB,kCAAkC;qBAC3G,CAAC,CAAC,CAAC;oBACJ,OAAO;gBACT,CAAC;gBACD,YAAY,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YACxB,CAAC;YAED,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBACxB,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBAC5C,IAAI,OAAO,EAAE,CAAC;oBACZ,OAAO,CAAC,IAAI,EAAE,CAAC;oBACf,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;gBAC3F,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,mBAAmB;QACrB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QAClB,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,YAAY,CAAC,EAAa,EAAE,GAA4E;IAC/G,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC;IACxE,MAAM,MAAM,GAAG,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;IAE9D,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;YACrB,IAAI,EAAE,OAAO;YACb,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,OAAO,EAAE,GAAG,OAAO,gCAAgC;SACpD,CAAC,CAAC,CAAC;QACJ,OAAO;IACT,CAAC;IAED,IAAI,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC1C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,GAAG,IAAI,oBAAU,CAAC;YACvB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,SAAS,EAAE,MAAM;YACjB,UAAU,EAAE,GAAG,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,EAAE;SAC5C,CAAC,CAAC;QACH,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAErC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAY,EAAE,EAAE;YACpC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACvF,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAY,EAAE,EAAE;YACnC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACtF,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,MAA4C,EAAE,EAAE;YAClE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;gBACrB,IAAI,EAAE,MAAM;gBACZ,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,OAAO,EAAE,MAAM,CAAC,UAAU;aAC3B,CAAC,CAAC,CAAC;YACJ,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,qBAAqB,CAAC,UAAkB;IAC/C,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,MAAM,GAAG,GAAG,GAAG,UAAU,uBAAuB,SAAS,EAAE,CAAC;QAC5D,MAAM,EAAE,GAAG,IAAI,cAAS,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,YAAY,GAA0B,IAAI,CAAC;QAE/C,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;YACjB,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;YAC9C,UAAU,CAAC,EAAE,CAAC,CAAC;YACf,8DAA8D;YAC9D,YAAY,GAAG,WAAW,CAAC,GAAG,EAAE;gBAC9B,IAAI,EAAE,CAAC,UAAU,KAAK,cAAS,CAAC,IAAI,EAAE,CAAC;oBACrC,EAAE,CAAC,IAAI,EAAE,CAAC;oBACV,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;gBAC5C,CAAC;YACH,CAAC,EAAE,MAAM,CAAC,CAAC;QACb,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,EAAE;YACvB,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;gBACvC,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM;oBAAE,OAAO,CAAC,qBAAqB;gBACtD,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAC1B,qBAAqB,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;gBACjC,CAAC;gBACD,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;oBACxB,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;oBAC5C,IAAI,OAAO;wBAAE,OAAO,CAAC,IAAI,EAAE,CAAC;gBAC9B,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,oDAAoD;QACpD,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;YACjB,EAAE,CAAC,IAAI,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YAClB,IAAI,YAAY;gBAAE,aAAa,CAAC,YAAY,CAAC,CAAC;YAC9C,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;YACnE,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YAClB,2BAA2B;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,mFAAmF;AACnF,IAAI,cAAc,GAAqB,IAAI,CAAC;AAE5C,SAAS,UAAU,CAAC,EAAa;IAC/B,cAAc,GAAG,EAAE,CAAC;AACtB,CAAC;AAED,SAAS,SAAS,CAAC,IAA6B;IAC9C,IAAI,cAAc,IAAI,cAAc,CAAC,UAAU,KAAK,cAAS,CAAC,IAAI,EAAE,CAAC;QACnE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5C,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,uCAAuC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAClE,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAAC,QAAmB,EAAE,GAA4E;IAC9H,OAAO,CAAC,GAAG,CAAC,mCAAmC,GAAG,CAAC,SAAS,MAAM,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;IAEnG,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC;IACxE,MAAM,MAAM,GAAG,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;IAE9D,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,OAAO,OAAO,gBAAgB,CAAC,CAAC;QAC5C,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,OAAO,gCAAgC,EAAE,CAAC,CAAC;QAC5G,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,gBAAgB,OAAO,OAAO,MAAM,OAAO,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;IAEzE,IAAI,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC1C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,GAAG,IAAI,oBAAU,CAAC;YACvB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,SAAS,EAAE,MAAM;YACjB,UAAU,EAAE,GAAG,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,EAAE;SAC5C,CAAC,CAAC;QACH,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAErC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAY,EAAE,EAAE;YACpC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAY,EAAE,EAAE;YACnC,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YAC5D,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,MAA4C,EAAE,EAAE;YAClE,OAAO,CAAC,GAAG,CAAC,0BAA0B,MAAM,CAAC,IAAI,qBAAqB,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;YAClG,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;YAClF,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC"}
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const commander_1 = require("commander");
|
|
5
|
+
const bridge_1 = require("./bridge");
|
|
6
|
+
const program = new commander_1.Command();
|
|
7
|
+
program
|
|
8
|
+
.name("cosmoremote")
|
|
9
|
+
.description("CosmoRemote bridge — connect your Mac to the CosmoRemote app")
|
|
10
|
+
.version("1.0.0");
|
|
11
|
+
program
|
|
12
|
+
.command("start")
|
|
13
|
+
.description("Start the bridge daemon")
|
|
14
|
+
.option("-p, --port <port>", "WebSocket server port", "4422")
|
|
15
|
+
.option("--backend <url>", "Backend relay URL", process.env.BACKEND_URL)
|
|
16
|
+
.action(async (opts) => {
|
|
17
|
+
await (0, bridge_1.startBridge)({
|
|
18
|
+
port: parseInt(opts.port, 10),
|
|
19
|
+
backendUrl: opts.backend,
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
program.parse();
|
|
23
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,qCAAuC;AAEvC,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,aAAa,CAAC;KACnB,WAAW,CAAC,8DAA8D,CAAC;KAC3E,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,yBAAyB,CAAC;KACtC,MAAM,CAAC,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,CAAC;KAC5D,MAAM,CAAC,iBAAiB,EAAE,mBAAmB,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;KACvE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,MAAM,IAAA,oBAAW,EAAC;QAChB,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;QAC7B,UAAU,EAAE,IAAI,CAAC,OAAO;KACzB,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
package/dist/detect.d.ts
ADDED
package/dist/detect.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectCLIs = detectCLIs;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const fs_1 = require("fs");
|
|
6
|
+
function which(cmd) {
|
|
7
|
+
try {
|
|
8
|
+
return (0, child_process_1.execSync)(`which ${cmd}`, { encoding: "utf-8" }).trim() || null;
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function detectCLIs() {
|
|
15
|
+
// Claude Code — check known paths first, then PATH
|
|
16
|
+
let claude = null;
|
|
17
|
+
const claudePaths = [
|
|
18
|
+
"/Users/matheus/.local/bin/claude",
|
|
19
|
+
"/usr/local/bin/claude",
|
|
20
|
+
];
|
|
21
|
+
for (const p of claudePaths) {
|
|
22
|
+
if ((0, fs_1.existsSync)(p)) {
|
|
23
|
+
claude = p;
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (!claude)
|
|
28
|
+
claude = which("claude");
|
|
29
|
+
// Codex
|
|
30
|
+
let codex = which("codex");
|
|
31
|
+
if (!codex) {
|
|
32
|
+
const codexPaths = ["/usr/local/bin/codex", "/opt/homebrew/bin/codex"];
|
|
33
|
+
for (const p of codexPaths) {
|
|
34
|
+
if ((0, fs_1.existsSync)(p)) {
|
|
35
|
+
codex = p;
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return { claude, codex };
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.js","sourceRoot":"","sources":["../src/detect.ts"],"names":[],"mappings":";;AAgBA,gCA4BC;AA5CD,iDAAyC;AACzC,2BAAgC;AAOhC,SAAS,KAAK,CAAC,GAAW;IACxB,IAAI,CAAC;QACH,OAAO,IAAA,wBAAQ,EAAC,SAAS,GAAG,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;IACxE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAgB,UAAU;IACxB,mDAAmD;IACnD,IAAI,MAAM,GAAkB,IAAI,CAAC;IACjC,MAAM,WAAW,GAAG;QAClB,kCAAkC;QAClC,uBAAuB;KACxB,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,IAAI,IAAA,eAAU,EAAC,CAAC,CAAC,EAAE,CAAC;YAClB,MAAM,GAAG,CAAC,CAAC;YACX,MAAM;QACR,CAAC;IACH,CAAC;IACD,IAAI,CAAC,MAAM;QAAE,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;IAEtC,QAAQ;IACR,IAAI,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,UAAU,GAAG,CAAC,sBAAsB,EAAE,yBAAyB,CAAC,CAAC;QACvE,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;YAC3B,IAAI,IAAA,eAAU,EAAC,CAAC,CAAC,EAAE,CAAC;gBAClB,KAAK,GAAG,CAAC,CAAC;gBACV,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAC3B,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
export interface SessionOptions {
|
|
3
|
+
sessionId: string;
|
|
4
|
+
cliBinary: string;
|
|
5
|
+
workingDir: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class CLISession extends EventEmitter {
|
|
8
|
+
readonly sessionId: string;
|
|
9
|
+
private process;
|
|
10
|
+
private cliBinary;
|
|
11
|
+
private workingDir;
|
|
12
|
+
private fullOutput;
|
|
13
|
+
private cleanOutput;
|
|
14
|
+
constructor(opts: SessionOptions);
|
|
15
|
+
sendPrompt(content: string): void;
|
|
16
|
+
kill(): void;
|
|
17
|
+
get isRunning(): boolean;
|
|
18
|
+
}
|
package/dist/session.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CLISession = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const events_1 = require("events");
|
|
6
|
+
class CLISession extends events_1.EventEmitter {
|
|
7
|
+
sessionId;
|
|
8
|
+
process = null;
|
|
9
|
+
cliBinary;
|
|
10
|
+
workingDir;
|
|
11
|
+
fullOutput = "";
|
|
12
|
+
cleanOutput = "";
|
|
13
|
+
constructor(opts) {
|
|
14
|
+
super();
|
|
15
|
+
this.sessionId = opts.sessionId;
|
|
16
|
+
this.cliBinary = opts.cliBinary;
|
|
17
|
+
this.workingDir = opts.workingDir;
|
|
18
|
+
}
|
|
19
|
+
sendPrompt(content) {
|
|
20
|
+
if (this.process && !this.process.killed) {
|
|
21
|
+
// If process is running, write to stdin
|
|
22
|
+
this.process.stdin?.write(content + "\n");
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
this.fullOutput = "";
|
|
26
|
+
this.cleanOutput = "";
|
|
27
|
+
const isClaude = this.cliBinary.includes("claude");
|
|
28
|
+
const args = isClaude
|
|
29
|
+
? ["-p", content, "--output-format", "stream-json", "--verbose"]
|
|
30
|
+
: [content];
|
|
31
|
+
this.process = (0, child_process_1.spawn)(this.cliBinary, args, {
|
|
32
|
+
cwd: this.workingDir,
|
|
33
|
+
env: { ...process.env, FORCE_COLOR: "0" },
|
|
34
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
35
|
+
});
|
|
36
|
+
this.process.stdout?.on("data", (chunk) => {
|
|
37
|
+
const text = chunk.toString();
|
|
38
|
+
this.fullOutput += text;
|
|
39
|
+
if (isClaude) {
|
|
40
|
+
const lines = text.split("\n").filter(Boolean);
|
|
41
|
+
for (const line of lines) {
|
|
42
|
+
try {
|
|
43
|
+
const event = JSON.parse(line);
|
|
44
|
+
// assistant message with text content
|
|
45
|
+
if (event.type === "assistant" && event.message?.content) {
|
|
46
|
+
for (const block of event.message.content) {
|
|
47
|
+
if (block.type === "text" && block.text) {
|
|
48
|
+
this.cleanOutput += block.text;
|
|
49
|
+
this.emit("output", block.text);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// content_block_delta — streaming text chunks
|
|
54
|
+
if (event.type === "content_block_delta" && event.delta?.text) {
|
|
55
|
+
this.cleanOutput += event.delta.text;
|
|
56
|
+
this.emit("output", event.delta.text);
|
|
57
|
+
}
|
|
58
|
+
// result — final text
|
|
59
|
+
if (event.type === "result" && event.result) {
|
|
60
|
+
if (!this.cleanOutput) {
|
|
61
|
+
this.cleanOutput = event.result;
|
|
62
|
+
this.emit("output", event.result);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// ignore non-JSON lines
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
this.cleanOutput += text;
|
|
73
|
+
this.emit("output", text);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
this.process.stderr?.on("data", (chunk) => {
|
|
77
|
+
const text = chunk.toString();
|
|
78
|
+
this.emit("error", text);
|
|
79
|
+
});
|
|
80
|
+
this.process.on("close", (code) => {
|
|
81
|
+
this.emit("done", { code, fullOutput: this.cleanOutput || this.fullOutput });
|
|
82
|
+
this.process = null;
|
|
83
|
+
});
|
|
84
|
+
this.process.on("error", (err) => {
|
|
85
|
+
this.emit("error", err.message);
|
|
86
|
+
this.process = null;
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
kill() {
|
|
90
|
+
if (this.process && !this.process.killed) {
|
|
91
|
+
this.process.kill("SIGTERM");
|
|
92
|
+
setTimeout(() => {
|
|
93
|
+
if (this.process && !this.process.killed) {
|
|
94
|
+
this.process.kill("SIGKILL");
|
|
95
|
+
}
|
|
96
|
+
}, 3000);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
get isRunning() {
|
|
100
|
+
return this.process !== null && !this.process.killed;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
exports.CLISession = CLISession;
|
|
104
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cosmoremote",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CosmoRemote bridge — connect your Mac to the CosmoRemote iOS/Android app to control Claude Code and Codex remotely",
|
|
5
|
+
"author": "Matheus Weber",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/matheusjkweber/cosmoremote.git",
|
|
10
|
+
"directory": "bridge"
|
|
11
|
+
},
|
|
12
|
+
"keywords": ["claude", "codex", "remote", "terminal", "bridge", "cli"],
|
|
13
|
+
"bin": {
|
|
14
|
+
"cosmoremote": "./dist/cli.js"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"dev": "tsx src/cli.ts start",
|
|
21
|
+
"build": "tsc",
|
|
22
|
+
"prepublishOnly": "npm run build",
|
|
23
|
+
"start": "node dist/cli.js start"
|
|
24
|
+
},
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=18"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"commander": "^12.1.0",
|
|
30
|
+
"qrcode-terminal": "^0.12.0",
|
|
31
|
+
"uuid": "^10.0.0",
|
|
32
|
+
"ws": "^8.18.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^20.0.0",
|
|
36
|
+
"@types/uuid": "^10.0.0",
|
|
37
|
+
"@types/ws": "^8.5.12",
|
|
38
|
+
"tsx": "^4.19.0",
|
|
39
|
+
"typescript": "^5.6.0"
|
|
40
|
+
}
|
|
41
|
+
}
|