mirra-cc-bridge 0.1.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 +62 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +213 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/configure.d.ts +13 -0
- package/dist/commands/configure.d.ts.map +1 -0
- package/dist/commands/configure.js +101 -0
- package/dist/commands/configure.js.map +1 -0
- package/dist/commands/hook.d.ts +15 -0
- package/dist/commands/hook.d.ts.map +1 -0
- package/dist/commands/hook.js +181 -0
- package/dist/commands/hook.js.map +1 -0
- package/dist/commands/index.d.ts +10 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +19 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/register.d.ts +13 -0
- package/dist/commands/register.d.ts.map +1 -0
- package/dist/commands/register.js +383 -0
- package/dist/commands/register.js.map +1 -0
- package/dist/commands/setup-hooks.d.ts +8 -0
- package/dist/commands/setup-hooks.d.ts.map +1 -0
- package/dist/commands/setup-hooks.js +114 -0
- package/dist/commands/setup-hooks.js.map +1 -0
- package/dist/commands/start.d.ts +16 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +168 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/status.d.ts +8 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +156 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/config.d.ts +37 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +88 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/session-manager.d.ts +72 -0
- package/dist/session-manager.d.ts.map +1 -0
- package/dist/session-manager.js +315 -0
- package/dist/session-manager.js.map +1 -0
- package/dist/types.d.ts +76 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Session Manager - manages Claude Code terminal sessions
|
|
4
|
+
*
|
|
5
|
+
* Handles the full lifecycle including:
|
|
6
|
+
* - Spawning Claude Code processes
|
|
7
|
+
* - Creating Flow automations for reply routing
|
|
8
|
+
* - Cleaning up Flows when sessions end
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.SessionManager = void 0;
|
|
12
|
+
const child_process_1 = require("child_process");
|
|
13
|
+
const sdk_1 = require("@mirra-messenger/sdk");
|
|
14
|
+
const config_1 = require("./config");
|
|
15
|
+
// Try to load node-pty, fall back to child_process if not available
|
|
16
|
+
let pty = null;
|
|
17
|
+
try {
|
|
18
|
+
pty = require('node-pty');
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// node-pty not available, will use child_process
|
|
22
|
+
}
|
|
23
|
+
class SessionManager {
|
|
24
|
+
constructor(apiKey, pcResourceId) {
|
|
25
|
+
this.sessions = new Map();
|
|
26
|
+
this.maxSessions = 5;
|
|
27
|
+
this.apiKey = apiKey;
|
|
28
|
+
this.pcResourceId = pcResourceId;
|
|
29
|
+
this.sdk = new sdk_1.MirraSDK({ apiKey });
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get the Claude Code router script ID from the server
|
|
33
|
+
* Caches the result for subsequent calls
|
|
34
|
+
*/
|
|
35
|
+
async getRouterScriptId() {
|
|
36
|
+
// Return cached script ID if available
|
|
37
|
+
if (this.routerScriptId) {
|
|
38
|
+
return this.routerScriptId;
|
|
39
|
+
}
|
|
40
|
+
// If a fetch is already in progress, wait for it
|
|
41
|
+
if (this.routerScriptIdPromise) {
|
|
42
|
+
return this.routerScriptIdPromise;
|
|
43
|
+
}
|
|
44
|
+
// Fetch the script ID from the server
|
|
45
|
+
this.routerScriptIdPromise = (async () => {
|
|
46
|
+
try {
|
|
47
|
+
const result = await this.sdk.scripts.getSystemScript('claude-code-router');
|
|
48
|
+
this.routerScriptId = result.scriptId;
|
|
49
|
+
console.log(`Fetched Claude Code router script ID: ${result.scriptId}`);
|
|
50
|
+
return result.scriptId;
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
this.routerScriptIdPromise = undefined;
|
|
54
|
+
}
|
|
55
|
+
})();
|
|
56
|
+
return this.routerScriptIdPromise;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Generate a unique session ID
|
|
60
|
+
*/
|
|
61
|
+
generateSessionId() {
|
|
62
|
+
return `cc_session_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Create a Flow for routing replies back to this session
|
|
66
|
+
*/
|
|
67
|
+
async createSessionFlow(sessionId, groupId) {
|
|
68
|
+
try {
|
|
69
|
+
// Get pcResourceId from config if not provided
|
|
70
|
+
const resourceId = this.pcResourceId || (0, config_1.loadConfig)()?.pcResourceId;
|
|
71
|
+
if (!resourceId) {
|
|
72
|
+
console.warn('No pcResourceId configured - Flow-based routing will not work. ' +
|
|
73
|
+
'Run `mirra-cc-bridge register` to register this PC as a resource.');
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
// Get the router script ID from the server
|
|
77
|
+
const routerScriptId = await this.getRouterScriptId();
|
|
78
|
+
const flow = await this.sdk.flows.createEventFlow({
|
|
79
|
+
title: `Claude Code Session ${sessionId}`,
|
|
80
|
+
description: 'Routes mobile replies to Claude Code terminal',
|
|
81
|
+
status: 'active',
|
|
82
|
+
trigger: {
|
|
83
|
+
type: 'event',
|
|
84
|
+
config: {
|
|
85
|
+
eventSource: 'mirra',
|
|
86
|
+
rootCondition: {
|
|
87
|
+
operator: 'and',
|
|
88
|
+
conditions: [
|
|
89
|
+
{
|
|
90
|
+
// Match replies to messages from this session
|
|
91
|
+
field: 'mirra.replyTo.automation.sessionId',
|
|
92
|
+
operator: 'equals',
|
|
93
|
+
value: sessionId,
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
// Only in the specified group
|
|
97
|
+
field: 'mirra.groupId',
|
|
98
|
+
operator: 'equals',
|
|
99
|
+
value: groupId,
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
scriptId: routerScriptId,
|
|
106
|
+
scriptInput: {
|
|
107
|
+
sessionId,
|
|
108
|
+
pcResourceId: resourceId,
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
console.log(`Created routing Flow ${flow.id} for session ${sessionId}`);
|
|
112
|
+
return flow.id;
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
console.error('Failed to create session Flow:', error);
|
|
116
|
+
// Don't fail the session spawn - Flow routing is optional
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Delete the Flow for a session
|
|
122
|
+
*/
|
|
123
|
+
async deleteSessionFlow(flowId) {
|
|
124
|
+
try {
|
|
125
|
+
await this.sdk.flows.delete(flowId);
|
|
126
|
+
console.log(`Deleted routing Flow ${flowId}`);
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
console.error(`Failed to delete Flow ${flowId}:`, error);
|
|
130
|
+
// Don't throw - cleanup errors shouldn't prevent session cleanup
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Spawn a new Claude Code session
|
|
135
|
+
*/
|
|
136
|
+
async spawnSession(options) {
|
|
137
|
+
if (this.sessions.size >= this.maxSessions) {
|
|
138
|
+
throw new Error(`Maximum sessions (${this.maxSessions}) reached. Kill an existing session first.`);
|
|
139
|
+
}
|
|
140
|
+
const sessionId = this.generateSessionId();
|
|
141
|
+
// Create the routing Flow first
|
|
142
|
+
const flowId = await this.createSessionFlow(sessionId, options.groupId);
|
|
143
|
+
const session = {
|
|
144
|
+
id: sessionId,
|
|
145
|
+
workingDir: options.workingDir,
|
|
146
|
+
status: 'starting',
|
|
147
|
+
createdAt: new Date(),
|
|
148
|
+
lastActivity: new Date(),
|
|
149
|
+
recipientId: options.recipientId,
|
|
150
|
+
groupId: options.groupId,
|
|
151
|
+
flowId,
|
|
152
|
+
};
|
|
153
|
+
this.sessions.set(sessionId, session);
|
|
154
|
+
try {
|
|
155
|
+
// Environment variables for the Claude Code process
|
|
156
|
+
// These are read by the hooks to know where to send output
|
|
157
|
+
const env = {
|
|
158
|
+
...process.env,
|
|
159
|
+
MIRRA_API_KEY: this.apiKey,
|
|
160
|
+
MIRRA_RECIPIENT_ID: options.groupId, // Send to group, not user directly
|
|
161
|
+
MIRRA_SESSION_ID: sessionId,
|
|
162
|
+
};
|
|
163
|
+
if (pty) {
|
|
164
|
+
// Use node-pty for full terminal emulation
|
|
165
|
+
const ptyProcess = pty.spawn('claude', [options.initialPrompt], {
|
|
166
|
+
name: 'xterm-256color',
|
|
167
|
+
cols: 120,
|
|
168
|
+
rows: 40,
|
|
169
|
+
cwd: options.workingDir,
|
|
170
|
+
env,
|
|
171
|
+
});
|
|
172
|
+
session.pty = ptyProcess;
|
|
173
|
+
ptyProcess.onData((data) => {
|
|
174
|
+
session.lastActivity = new Date();
|
|
175
|
+
// Output is handled by hooks, not here
|
|
176
|
+
});
|
|
177
|
+
ptyProcess.onExit(async ({ exitCode }) => {
|
|
178
|
+
session.status = 'stopped';
|
|
179
|
+
// Clean up Flow when session exits
|
|
180
|
+
if (session.flowId) {
|
|
181
|
+
await this.deleteSessionFlow(session.flowId);
|
|
182
|
+
}
|
|
183
|
+
this.sessions.delete(sessionId);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
// Fallback to child_process
|
|
188
|
+
const childProcess = (0, child_process_1.spawn)('claude', [options.initialPrompt], {
|
|
189
|
+
cwd: options.workingDir,
|
|
190
|
+
env,
|
|
191
|
+
shell: true,
|
|
192
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
193
|
+
});
|
|
194
|
+
session.pty = childProcess;
|
|
195
|
+
childProcess.stdout?.on('data', () => {
|
|
196
|
+
session.lastActivity = new Date();
|
|
197
|
+
});
|
|
198
|
+
childProcess.stderr?.on('data', () => {
|
|
199
|
+
session.lastActivity = new Date();
|
|
200
|
+
});
|
|
201
|
+
childProcess.on('exit', async () => {
|
|
202
|
+
session.status = 'stopped';
|
|
203
|
+
// Clean up Flow when session exits
|
|
204
|
+
if (session.flowId) {
|
|
205
|
+
await this.deleteSessionFlow(session.flowId);
|
|
206
|
+
}
|
|
207
|
+
this.sessions.delete(sessionId);
|
|
208
|
+
});
|
|
209
|
+
childProcess.on('error', (error) => {
|
|
210
|
+
console.error(`Session ${sessionId} error:`, error.message);
|
|
211
|
+
session.status = 'error';
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
session.status = 'running';
|
|
215
|
+
return session;
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
session.status = 'error';
|
|
219
|
+
// Clean up Flow if session spawn failed
|
|
220
|
+
if (session.flowId) {
|
|
221
|
+
await this.deleteSessionFlow(session.flowId);
|
|
222
|
+
}
|
|
223
|
+
this.sessions.delete(sessionId);
|
|
224
|
+
throw error;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Send input to a session
|
|
229
|
+
*/
|
|
230
|
+
sendInput(sessionId, input) {
|
|
231
|
+
const session = this.sessions.get(sessionId);
|
|
232
|
+
if (!session) {
|
|
233
|
+
throw new Error(`Session ${sessionId} not found`);
|
|
234
|
+
}
|
|
235
|
+
if (session.status !== 'running') {
|
|
236
|
+
throw new Error(`Session ${sessionId} is not running (status: ${session.status})`);
|
|
237
|
+
}
|
|
238
|
+
if (!session.pty) {
|
|
239
|
+
throw new Error(`Session ${sessionId} has no process attached`);
|
|
240
|
+
}
|
|
241
|
+
session.lastActivity = new Date();
|
|
242
|
+
if (pty && typeof session.pty.write === 'function') {
|
|
243
|
+
// node-pty
|
|
244
|
+
session.pty.write(input + '\n');
|
|
245
|
+
}
|
|
246
|
+
else if (session.pty.stdin) {
|
|
247
|
+
// child_process
|
|
248
|
+
session.pty.stdin.write(input + '\n');
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Kill a session
|
|
253
|
+
*/
|
|
254
|
+
async killSession(sessionId) {
|
|
255
|
+
const session = this.sessions.get(sessionId);
|
|
256
|
+
if (!session) {
|
|
257
|
+
throw new Error(`Session ${sessionId} not found`);
|
|
258
|
+
}
|
|
259
|
+
// Clean up the routing Flow
|
|
260
|
+
if (session.flowId) {
|
|
261
|
+
await this.deleteSessionFlow(session.flowId);
|
|
262
|
+
}
|
|
263
|
+
// Kill the process
|
|
264
|
+
if (session.pty) {
|
|
265
|
+
if (pty && typeof session.pty.kill === 'function') {
|
|
266
|
+
session.pty.kill();
|
|
267
|
+
}
|
|
268
|
+
else if (typeof session.pty.kill === 'function') {
|
|
269
|
+
session.pty.kill('SIGTERM');
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
session.status = 'stopped';
|
|
273
|
+
this.sessions.delete(sessionId);
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Get a session by ID
|
|
277
|
+
*/
|
|
278
|
+
getSession(sessionId) {
|
|
279
|
+
return this.sessions.get(sessionId);
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* List all sessions
|
|
283
|
+
*/
|
|
284
|
+
listSessions() {
|
|
285
|
+
return Array.from(this.sessions.values()).map((session) => ({
|
|
286
|
+
id: session.id,
|
|
287
|
+
workingDir: session.workingDir,
|
|
288
|
+
status: session.status,
|
|
289
|
+
createdAt: session.createdAt.toISOString(),
|
|
290
|
+
lastActivity: session.lastActivity.toISOString(),
|
|
291
|
+
flowId: session.flowId,
|
|
292
|
+
}));
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Kill all sessions
|
|
296
|
+
*/
|
|
297
|
+
async killAllSessions() {
|
|
298
|
+
for (const sessionId of this.sessions.keys()) {
|
|
299
|
+
try {
|
|
300
|
+
await this.killSession(sessionId);
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
// Ignore errors during cleanup
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Get count of active sessions
|
|
309
|
+
*/
|
|
310
|
+
getActiveCount() {
|
|
311
|
+
return this.sessions.size;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
exports.SessionManager = SessionManager;
|
|
315
|
+
//# sourceMappingURL=session-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../src/session-manager.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for Mirra Claude Code Bridge
|
|
3
|
+
*/
|
|
4
|
+
export interface BridgeConfig {
|
|
5
|
+
apiKey: string;
|
|
6
|
+
userId?: string;
|
|
7
|
+
defaultWorkDir?: string;
|
|
8
|
+
pcResourceId?: string;
|
|
9
|
+
hooksConfigured?: boolean;
|
|
10
|
+
setupComplete?: boolean;
|
|
11
|
+
tunnel?: {
|
|
12
|
+
provider: 'ngrok' | 'cloudflare';
|
|
13
|
+
authToken?: string;
|
|
14
|
+
};
|
|
15
|
+
server?: {
|
|
16
|
+
port: number;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export interface Session {
|
|
20
|
+
id: string;
|
|
21
|
+
workingDir: string;
|
|
22
|
+
status: 'starting' | 'running' | 'stopped' | 'error';
|
|
23
|
+
createdAt: Date;
|
|
24
|
+
lastActivity: Date;
|
|
25
|
+
recipientId: string;
|
|
26
|
+
groupId: string;
|
|
27
|
+
flowId?: string;
|
|
28
|
+
pty?: any;
|
|
29
|
+
}
|
|
30
|
+
export interface ClaudeCodeMessage {
|
|
31
|
+
type: 'claude_code_output' | 'claude_code_tool' | 'claude_code_status';
|
|
32
|
+
sessionId: string;
|
|
33
|
+
timestamp: string;
|
|
34
|
+
data: any;
|
|
35
|
+
}
|
|
36
|
+
export interface ClaudeCodeOutput extends ClaudeCodeMessage {
|
|
37
|
+
type: 'claude_code_output';
|
|
38
|
+
data: {
|
|
39
|
+
content: string;
|
|
40
|
+
role?: 'assistant' | 'user';
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export interface ClaudeCodeToolUse extends ClaudeCodeMessage {
|
|
44
|
+
type: 'claude_code_tool';
|
|
45
|
+
data: {
|
|
46
|
+
toolName: string;
|
|
47
|
+
input?: any;
|
|
48
|
+
output?: any;
|
|
49
|
+
status: 'started' | 'completed' | 'error';
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export interface ClaudeCodeStatus extends ClaudeCodeMessage {
|
|
53
|
+
type: 'claude_code_status';
|
|
54
|
+
data: {
|
|
55
|
+
status: 'started' | 'running' | 'stopped' | 'error';
|
|
56
|
+
message?: string;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export interface SpawnSessionRequest {
|
|
60
|
+
workingDir?: string;
|
|
61
|
+
initialPrompt: string;
|
|
62
|
+
recipientId: string;
|
|
63
|
+
groupId: string;
|
|
64
|
+
}
|
|
65
|
+
export interface SendInputRequest {
|
|
66
|
+
input: string;
|
|
67
|
+
}
|
|
68
|
+
export interface SessionResponse {
|
|
69
|
+
id: string;
|
|
70
|
+
workingDir: string;
|
|
71
|
+
status: string;
|
|
72
|
+
createdAt: string;
|
|
73
|
+
lastActivity: string;
|
|
74
|
+
flowId?: string;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +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,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,WAAW,EAAE,MAAM,CAAC;IACpB,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,WAAW,EAAE,MAAM,CAAC;IACpB,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/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;GAEG"}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mirra-cc-bridge",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Bridge Claude Code to Mirra mobile app - control your coding sessions from anywhere",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"mirra-cc-bridge": "dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "ts-node src/cli.ts",
|
|
13
|
+
"start": "node dist/cli.js",
|
|
14
|
+
"clean": "rm -rf dist",
|
|
15
|
+
"prepublishOnly": "npm run build"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"claude-code",
|
|
19
|
+
"claude",
|
|
20
|
+
"mirra",
|
|
21
|
+
"mobile",
|
|
22
|
+
"remote-coding",
|
|
23
|
+
"ai-coding",
|
|
24
|
+
"terminal",
|
|
25
|
+
"cli"
|
|
26
|
+
],
|
|
27
|
+
"author": "Mirra",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "git+https://github.com/anthropics/claude-code.git",
|
|
32
|
+
"directory": "packages/mirra-cc-bridge"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://docs.getmirra.app/claude-code",
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@mirra-messenger/sdk": "^0.5.0",
|
|
37
|
+
"chalk": "^4.1.2",
|
|
38
|
+
"commander": "^11.1.0",
|
|
39
|
+
"express": "^4.18.2",
|
|
40
|
+
"conf": "^10.2.0"
|
|
41
|
+
},
|
|
42
|
+
"optionalDependencies": {
|
|
43
|
+
"node-pty": "^1.0.0"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/express": "^4.17.21",
|
|
47
|
+
"@types/node": "^20.10.0",
|
|
48
|
+
"ts-node": "^10.9.2",
|
|
49
|
+
"typescript": "^5.3.2"
|
|
50
|
+
},
|
|
51
|
+
"engines": {
|
|
52
|
+
"node": ">=18.0.0"
|
|
53
|
+
},
|
|
54
|
+
"files": [
|
|
55
|
+
"dist",
|
|
56
|
+
"README.md"
|
|
57
|
+
]
|
|
58
|
+
}
|