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.
Files changed (50) hide show
  1. package/README.md +62 -0
  2. package/dist/cli.d.ts +8 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +213 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/configure.d.ts +13 -0
  7. package/dist/commands/configure.d.ts.map +1 -0
  8. package/dist/commands/configure.js +101 -0
  9. package/dist/commands/configure.js.map +1 -0
  10. package/dist/commands/hook.d.ts +15 -0
  11. package/dist/commands/hook.d.ts.map +1 -0
  12. package/dist/commands/hook.js +181 -0
  13. package/dist/commands/hook.js.map +1 -0
  14. package/dist/commands/index.d.ts +10 -0
  15. package/dist/commands/index.d.ts.map +1 -0
  16. package/dist/commands/index.js +19 -0
  17. package/dist/commands/index.js.map +1 -0
  18. package/dist/commands/register.d.ts +13 -0
  19. package/dist/commands/register.d.ts.map +1 -0
  20. package/dist/commands/register.js +383 -0
  21. package/dist/commands/register.js.map +1 -0
  22. package/dist/commands/setup-hooks.d.ts +8 -0
  23. package/dist/commands/setup-hooks.d.ts.map +1 -0
  24. package/dist/commands/setup-hooks.js +114 -0
  25. package/dist/commands/setup-hooks.js.map +1 -0
  26. package/dist/commands/start.d.ts +16 -0
  27. package/dist/commands/start.d.ts.map +1 -0
  28. package/dist/commands/start.js +168 -0
  29. package/dist/commands/start.js.map +1 -0
  30. package/dist/commands/status.d.ts +8 -0
  31. package/dist/commands/status.d.ts.map +1 -0
  32. package/dist/commands/status.js +156 -0
  33. package/dist/commands/status.js.map +1 -0
  34. package/dist/config.d.ts +37 -0
  35. package/dist/config.d.ts.map +1 -0
  36. package/dist/config.js +88 -0
  37. package/dist/config.js.map +1 -0
  38. package/dist/index.d.ts +15 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +40 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/session-manager.d.ts +72 -0
  43. package/dist/session-manager.d.ts.map +1 -0
  44. package/dist/session-manager.js +315 -0
  45. package/dist/session-manager.js.map +1 -0
  46. package/dist/types.d.ts +76 -0
  47. package/dist/types.d.ts.map +1 -0
  48. package/dist/types.js +6 -0
  49. package/dist/types.js.map +1 -0
  50. 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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"}
@@ -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,6 @@
1
+ "use strict";
2
+ /**
3
+ * Types for Mirra Claude Code Bridge
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ //# sourceMappingURL=types.js.map
@@ -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
+ }