mirra-cc-bridge 0.1.2 → 0.1.4
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/dist/cli.js +18 -6
- package/dist/cli.js.map +1 -1
- package/dist/commands/configure.d.ts.map +1 -1
- package/dist/commands/configure.js +29 -23
- package/dist/commands/configure.js.map +1 -1
- package/dist/commands/hook.d.ts.map +1 -1
- package/dist/commands/hook.js +50 -22
- package/dist/commands/hook.js.map +1 -1
- package/dist/commands/index.d.ts +1 -1
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +2 -1
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/register.d.ts +9 -0
- package/dist/commands/register.d.ts.map +1 -1
- package/dist/commands/register.js +174 -0
- package/dist/commands/register.js.map +1 -1
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +98 -16
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +22 -2
- package/dist/commands/status.js.map +1 -1
- package/dist/session-manager.d.ts +0 -1
- package/dist/session-manager.d.ts.map +1 -1
- package/dist/session-manager.js +1 -2
- package/dist/session-manager.js.map +1 -1
- package/dist/tunnel.d.ts +34 -0
- package/dist/tunnel.d.ts.map +1 -0
- package/dist/tunnel.js +318 -0
- package/dist/tunnel.js.map +1 -0
- package/dist/types.d.ts +1 -3
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -4
- package/README.md +0 -62
package/dist/tunnel.js
ADDED
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Tunnel management - connects to Mirra's tunnel service for remote access
|
|
4
|
+
*
|
|
5
|
+
* Uses WebSocket connection to Mirra's server instead of ngrok.
|
|
6
|
+
* No external dependencies or account signup required.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
42
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
43
|
+
};
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.setRequestHandler = setRequestHandler;
|
|
46
|
+
exports.startTunnel = startTunnel;
|
|
47
|
+
exports.stopTunnel = stopTunnel;
|
|
48
|
+
exports.isTunnelActive = isTunnelActive;
|
|
49
|
+
exports.getTunnelUrl = getTunnelUrl;
|
|
50
|
+
exports.saveAuthToken = saveAuthToken;
|
|
51
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
52
|
+
const ws_1 = __importDefault(require("ws"));
|
|
53
|
+
const config_1 = require("./config");
|
|
54
|
+
// Tunnel message types (must match server)
|
|
55
|
+
var TunnelMessageType;
|
|
56
|
+
(function (TunnelMessageType) {
|
|
57
|
+
TunnelMessageType["CONNECT"] = "tunnel:connect";
|
|
58
|
+
TunnelMessageType["CONNECTED"] = "tunnel:connected";
|
|
59
|
+
TunnelMessageType["DISCONNECT"] = "tunnel:disconnect";
|
|
60
|
+
TunnelMessageType["PING"] = "tunnel:ping";
|
|
61
|
+
TunnelMessageType["PONG"] = "tunnel:pong";
|
|
62
|
+
TunnelMessageType["HTTP_REQUEST"] = "tunnel:http_request";
|
|
63
|
+
TunnelMessageType["HTTP_RESPONSE"] = "tunnel:http_response";
|
|
64
|
+
TunnelMessageType["ERROR"] = "tunnel:error";
|
|
65
|
+
})(TunnelMessageType || (TunnelMessageType = {}));
|
|
66
|
+
// Active WebSocket connection
|
|
67
|
+
let ws = null;
|
|
68
|
+
let tunnelUrl = null;
|
|
69
|
+
let reconnectTimeout = null;
|
|
70
|
+
let localPort = 3847;
|
|
71
|
+
let requestHandler = null;
|
|
72
|
+
/**
|
|
73
|
+
* Set the handler for incoming HTTP requests
|
|
74
|
+
*/
|
|
75
|
+
function setRequestHandler(handler) {
|
|
76
|
+
requestHandler = handler;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Connect to Mirra's tunnel service
|
|
80
|
+
*/
|
|
81
|
+
async function startTunnel(port) {
|
|
82
|
+
const config = (0, config_1.loadConfig)();
|
|
83
|
+
if (!config?.apiKey) {
|
|
84
|
+
throw new Error('API key not configured. Run `mirra-cc-bridge configure` first.');
|
|
85
|
+
}
|
|
86
|
+
localPort = port;
|
|
87
|
+
// Determine WebSocket URL
|
|
88
|
+
const baseUrl = process.env.MIRRA_API_URL || 'https://api.fxn.world';
|
|
89
|
+
const wsUrl = baseUrl.replace('https://', 'wss://').replace('http://', 'ws://') + '/tunnel/ws';
|
|
90
|
+
console.log(chalk_1.default.gray('Connecting to Mirra tunnel service...'));
|
|
91
|
+
return new Promise((resolve, reject) => {
|
|
92
|
+
try {
|
|
93
|
+
ws = new ws_1.default(wsUrl);
|
|
94
|
+
const connectionTimeout = setTimeout(() => {
|
|
95
|
+
if (ws) {
|
|
96
|
+
ws.close();
|
|
97
|
+
ws = null;
|
|
98
|
+
}
|
|
99
|
+
reject(new Error('Connection timeout'));
|
|
100
|
+
}, 30000);
|
|
101
|
+
ws.on('open', () => {
|
|
102
|
+
console.log(chalk_1.default.gray('WebSocket connected, authenticating...'));
|
|
103
|
+
// Send connect message with API key
|
|
104
|
+
const connectMsg = {
|
|
105
|
+
type: TunnelMessageType.CONNECT,
|
|
106
|
+
timestamp: Date.now(),
|
|
107
|
+
apiKey: config.apiKey,
|
|
108
|
+
};
|
|
109
|
+
ws.send(JSON.stringify(connectMsg));
|
|
110
|
+
});
|
|
111
|
+
ws.on('message', async (data) => {
|
|
112
|
+
try {
|
|
113
|
+
const message = JSON.parse(data.toString());
|
|
114
|
+
switch (message.type) {
|
|
115
|
+
case TunnelMessageType.CONNECTED: {
|
|
116
|
+
const connectedMsg = message;
|
|
117
|
+
tunnelUrl = connectedMsg.tunnelUrl;
|
|
118
|
+
clearTimeout(connectionTimeout);
|
|
119
|
+
console.log(chalk_1.default.green('[+] Tunnel connected'));
|
|
120
|
+
console.log(chalk_1.default.gray(` URL: ${tunnelUrl}`));
|
|
121
|
+
resolve(tunnelUrl);
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
case TunnelMessageType.PING: {
|
|
125
|
+
// Respond to keep-alive ping
|
|
126
|
+
const pongMsg = {
|
|
127
|
+
type: TunnelMessageType.PONG,
|
|
128
|
+
timestamp: Date.now(),
|
|
129
|
+
};
|
|
130
|
+
ws.send(JSON.stringify(pongMsg));
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
case TunnelMessageType.HTTP_REQUEST: {
|
|
134
|
+
await handleHttpRequest(message);
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
case TunnelMessageType.ERROR: {
|
|
138
|
+
const errorMsg = message;
|
|
139
|
+
console.error(chalk_1.default.red(`Tunnel error: ${errorMsg.message}`));
|
|
140
|
+
if (errorMsg.code === 'AUTH_FAILED') {
|
|
141
|
+
clearTimeout(connectionTimeout);
|
|
142
|
+
ws?.close();
|
|
143
|
+
reject(new Error('Authentication failed - check your API key'));
|
|
144
|
+
}
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
console.error('Error processing tunnel message:', error);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
ws.on('close', (code, reason) => {
|
|
154
|
+
console.log(chalk_1.default.gray(`Tunnel disconnected (${code})`));
|
|
155
|
+
tunnelUrl = null;
|
|
156
|
+
// Attempt reconnection if not intentionally closed
|
|
157
|
+
if (code !== 1000) {
|
|
158
|
+
scheduleReconnect();
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
ws.on('error', (error) => {
|
|
162
|
+
console.error(chalk_1.default.red('Tunnel WebSocket error:'), error.message);
|
|
163
|
+
clearTimeout(connectionTimeout);
|
|
164
|
+
reject(error);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
reject(error);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Handle an HTTP request coming through the tunnel
|
|
174
|
+
*/
|
|
175
|
+
async function handleHttpRequest(request) {
|
|
176
|
+
if (!ws)
|
|
177
|
+
return;
|
|
178
|
+
let response;
|
|
179
|
+
try {
|
|
180
|
+
// If we have a custom handler, use it
|
|
181
|
+
if (requestHandler) {
|
|
182
|
+
const result = await requestHandler(request.method, request.path, request.headers, request.body);
|
|
183
|
+
response = {
|
|
184
|
+
type: TunnelMessageType.HTTP_RESPONSE,
|
|
185
|
+
timestamp: Date.now(),
|
|
186
|
+
requestId: request.requestId,
|
|
187
|
+
statusCode: result.statusCode,
|
|
188
|
+
headers: result.headers,
|
|
189
|
+
body: result.body,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
// Default: proxy to local server
|
|
194
|
+
const result = await proxyToLocalServer(request);
|
|
195
|
+
response = {
|
|
196
|
+
type: TunnelMessageType.HTTP_RESPONSE,
|
|
197
|
+
timestamp: Date.now(),
|
|
198
|
+
requestId: request.requestId,
|
|
199
|
+
statusCode: result.statusCode,
|
|
200
|
+
headers: result.headers,
|
|
201
|
+
body: result.body,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
response = {
|
|
207
|
+
type: TunnelMessageType.HTTP_RESPONSE,
|
|
208
|
+
timestamp: Date.now(),
|
|
209
|
+
requestId: request.requestId,
|
|
210
|
+
statusCode: 502,
|
|
211
|
+
headers: { 'content-type': 'application/json' },
|
|
212
|
+
body: JSON.stringify({ error: 'Bad gateway', message: error.message }),
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
ws.send(JSON.stringify(response));
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Proxy request to local Express server
|
|
219
|
+
*/
|
|
220
|
+
async function proxyToLocalServer(request) {
|
|
221
|
+
const http = await Promise.resolve().then(() => __importStar(require('http')));
|
|
222
|
+
return new Promise((resolve, reject) => {
|
|
223
|
+
const options = {
|
|
224
|
+
hostname: 'localhost',
|
|
225
|
+
port: localPort,
|
|
226
|
+
path: request.path,
|
|
227
|
+
method: request.method,
|
|
228
|
+
headers: request.headers,
|
|
229
|
+
};
|
|
230
|
+
const req = http.request(options, (res) => {
|
|
231
|
+
let body = '';
|
|
232
|
+
res.on('data', (chunk) => {
|
|
233
|
+
body += chunk;
|
|
234
|
+
});
|
|
235
|
+
res.on('end', () => {
|
|
236
|
+
const headers = {};
|
|
237
|
+
for (const [key, value] of Object.entries(res.headers)) {
|
|
238
|
+
if (typeof value === 'string') {
|
|
239
|
+
headers[key] = value;
|
|
240
|
+
}
|
|
241
|
+
else if (Array.isArray(value)) {
|
|
242
|
+
headers[key] = value.join(', ');
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
resolve({
|
|
246
|
+
statusCode: res.statusCode || 500,
|
|
247
|
+
headers,
|
|
248
|
+
body,
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
req.on('error', reject);
|
|
253
|
+
req.setTimeout(30000, () => {
|
|
254
|
+
req.destroy();
|
|
255
|
+
reject(new Error('Request timeout'));
|
|
256
|
+
});
|
|
257
|
+
if (request.body) {
|
|
258
|
+
req.write(request.body);
|
|
259
|
+
}
|
|
260
|
+
req.end();
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Schedule a reconnection attempt
|
|
265
|
+
*/
|
|
266
|
+
function scheduleReconnect() {
|
|
267
|
+
if (reconnectTimeout)
|
|
268
|
+
return;
|
|
269
|
+
console.log(chalk_1.default.gray('Reconnecting in 5 seconds...'));
|
|
270
|
+
reconnectTimeout = setTimeout(async () => {
|
|
271
|
+
reconnectTimeout = null;
|
|
272
|
+
try {
|
|
273
|
+
await startTunnel(localPort);
|
|
274
|
+
}
|
|
275
|
+
catch (error) {
|
|
276
|
+
console.error(chalk_1.default.red('Reconnection failed:'), error.message);
|
|
277
|
+
scheduleReconnect();
|
|
278
|
+
}
|
|
279
|
+
}, 5000);
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Stop the tunnel connection
|
|
283
|
+
*/
|
|
284
|
+
async function stopTunnel() {
|
|
285
|
+
if (reconnectTimeout) {
|
|
286
|
+
clearTimeout(reconnectTimeout);
|
|
287
|
+
reconnectTimeout = null;
|
|
288
|
+
}
|
|
289
|
+
if (ws) {
|
|
290
|
+
try {
|
|
291
|
+
ws.close(1000, 'Client stopping');
|
|
292
|
+
ws = null;
|
|
293
|
+
tunnelUrl = null;
|
|
294
|
+
console.log(chalk_1.default.gray('Tunnel stopped'));
|
|
295
|
+
}
|
|
296
|
+
catch (error) {
|
|
297
|
+
console.error(chalk_1.default.yellow(`Warning: Could not stop tunnel: ${error.message}`));
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Check if tunnel is active
|
|
303
|
+
*/
|
|
304
|
+
function isTunnelActive() {
|
|
305
|
+
return ws !== null && ws.readyState === ws_1.default.OPEN;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Get the current tunnel URL
|
|
309
|
+
*/
|
|
310
|
+
function getTunnelUrl() {
|
|
311
|
+
return tunnelUrl;
|
|
312
|
+
}
|
|
313
|
+
// Legacy exports for compatibility (no longer needed with Mirra tunnel)
|
|
314
|
+
function saveAuthToken(_authToken) {
|
|
315
|
+
// No-op - Mirra tunnel uses the existing API key, no separate auth token needed
|
|
316
|
+
console.log(chalk_1.default.gray('Note: Mirra tunnel uses your API key for authentication'));
|
|
317
|
+
}
|
|
318
|
+
//# sourceMappingURL=tunnel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tunnel.js","sourceRoot":"","sources":["../src/tunnel.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
export interface BridgeConfig {
|
|
5
5
|
apiKey: string;
|
|
6
6
|
userId?: string;
|
|
7
|
-
|
|
7
|
+
groupId?: string;
|
|
8
8
|
defaultWorkDir?: string;
|
|
9
9
|
pcResourceId?: string;
|
|
10
10
|
hooksConfigured?: boolean;
|
|
@@ -23,7 +23,6 @@ export interface Session {
|
|
|
23
23
|
status: 'starting' | 'running' | 'stopped' | 'error';
|
|
24
24
|
createdAt: Date;
|
|
25
25
|
lastActivity: Date;
|
|
26
|
-
recipientId: string;
|
|
27
26
|
groupId: string;
|
|
28
27
|
flowId?: string;
|
|
29
28
|
pty?: any;
|
|
@@ -60,7 +59,6 @@ export interface ClaudeCodeStatus extends ClaudeCodeMessage {
|
|
|
60
59
|
export interface SpawnSessionRequest {
|
|
61
60
|
workingDir?: string;
|
|
62
61
|
initialPrompt: string;
|
|
63
|
-
recipientId: string;
|
|
64
62
|
groupId: string;
|
|
65
63
|
}
|
|
66
64
|
export interface SendInputRequest {
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,MAAM,CAAC,EAAE;QACP,QAAQ,EAAE,OAAO,GAAG,YAAY,CAAC;QACjC,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,MAAM,CAAC,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IACrD,SAAS,EAAE,IAAI,CAAC;IAChB,YAAY,EAAE,IAAI,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,GAAG,CAAC;CACX;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,oBAAoB,GAAG,kBAAkB,GAAG,oBAAoB,CAAC;IACvE,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,GAAG,CAAC;CACX;AAED,MAAM,WAAW,gBAAiB,SAAQ,iBAAiB;IACzD,IAAI,EAAE,oBAAoB,CAAC;IAC3B,IAAI,EAAE;QACJ,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;KAC7B,CAAC;CACH;AAED,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IAC1D,IAAI,EAAE,kBAAkB,CAAC;IACzB,IAAI,EAAE;QACJ,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,GAAG,CAAC;QACZ,MAAM,CAAC,EAAE,GAAG,CAAC;QACb,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;KAC3C,CAAC;CACH;AAED,MAAM,WAAW,gBAAiB,SAAQ,iBAAiB;IACzD,IAAI,EAAE,oBAAoB,CAAC;IAC3B,IAAI,EAAE;QACJ,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;QACpD,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mirra-cc-bridge",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Bridge Claude Code to Mirra Messenger on iOS or Android - control your coding sessions from text messages and voice calls",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"mirra-cc-bridge": "dist/cli.js"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
|
-
"build": "tsc",
|
|
11
|
+
"build": "npx tsc",
|
|
12
12
|
"dev": "ts-node src/cli.ts",
|
|
13
13
|
"start": "node dist/cli.js",
|
|
14
14
|
"clean": "rm -rf dist",
|
|
@@ -33,11 +33,12 @@
|
|
|
33
33
|
},
|
|
34
34
|
"homepage": "https://docs.getmirra.app/claude-code",
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@mirra-messenger/sdk": "^0.5.
|
|
36
|
+
"@mirra-messenger/sdk": "^0.5.3",
|
|
37
37
|
"chalk": "^4.1.2",
|
|
38
38
|
"commander": "^11.1.0",
|
|
39
39
|
"express": "^4.18.2",
|
|
40
|
-
"conf": "^10.2.0"
|
|
40
|
+
"conf": "^10.2.0",
|
|
41
|
+
"ws": "^8.18.0"
|
|
41
42
|
},
|
|
42
43
|
"optionalDependencies": {
|
|
43
44
|
"node-pty": "^1.0.0"
|
|
@@ -45,6 +46,7 @@
|
|
|
45
46
|
"devDependencies": {
|
|
46
47
|
"@types/express": "^4.17.21",
|
|
47
48
|
"@types/node": "^20.10.0",
|
|
49
|
+
"@types/ws": "^8.5.10",
|
|
48
50
|
"ts-node": "^10.9.2",
|
|
49
51
|
"typescript": "^5.3.2"
|
|
50
52
|
},
|
package/README.md
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
# mirra-cc-bridge
|
|
2
|
-
|
|
3
|
-
Bridge Claude Code to the Mirra mobile app - control your coding sessions from anywhere.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install -g mirra-cc-bridge
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Quick Start
|
|
12
|
-
|
|
13
|
-
Just run:
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
mirra-cc-bridge
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
That's it! The setup wizard will guide you through:
|
|
20
|
-
1. Entering your Mirra API key (get it from the Mirra app settings)
|
|
21
|
-
2. Configuring Claude Code hooks automatically
|
|
22
|
-
|
|
23
|
-
Once set up, Claude Code output will automatically appear in your Mirra mobile app.
|
|
24
|
-
|
|
25
|
-
## Remote Control (Optional)
|
|
26
|
-
|
|
27
|
-
To control Claude Code from your phone when away from your computer:
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
mirra-cc-bridge register
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
This registers your PC as a Mirra resource. You'll need a tunnel URL (ngrok or Cloudflare Tunnel) for your PC to be reachable remotely.
|
|
34
|
-
|
|
35
|
-
## Commands
|
|
36
|
-
|
|
37
|
-
| Command | Description |
|
|
38
|
-
|---------|-------------|
|
|
39
|
-
| `mirra-cc-bridge` | Run setup (first time) or start the bridge server |
|
|
40
|
-
| `mirra-cc-bridge setup` | Re-run the setup wizard |
|
|
41
|
-
| `mirra-cc-bridge start` | Start the bridge HTTP server |
|
|
42
|
-
| `mirra-cc-bridge register` | Register PC for remote control |
|
|
43
|
-
| `mirra-cc-bridge status` | Show bridge status |
|
|
44
|
-
| `mirra-cc-bridge config` | Display current configuration |
|
|
45
|
-
|
|
46
|
-
## How It Works
|
|
47
|
-
|
|
48
|
-
1. **Claude Code Hooks**: When you run Claude Code locally, hooks send output to your Mirra mobile app in real-time.
|
|
49
|
-
|
|
50
|
-
2. **PC Resource** (optional): By registering your PC, the Mirra LLM can spawn Claude Code sessions on your behalf when you're away.
|
|
51
|
-
|
|
52
|
-
3. **Flow-Based Routing**: Replies from your phone are automatically routed to the correct Claude Code session.
|
|
53
|
-
|
|
54
|
-
## Requirements
|
|
55
|
-
|
|
56
|
-
- Node.js 18+
|
|
57
|
-
- Claude Code CLI installed
|
|
58
|
-
- Mirra account and API key
|
|
59
|
-
|
|
60
|
-
## License
|
|
61
|
-
|
|
62
|
-
MIT
|