sessioncast-cli 2.1.0 → 2.2.1

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.
@@ -184,7 +184,7 @@ class AgentRunner {
184
184
  const handler = new session_handler_1.TmuxSessionHandler({
185
185
  config: this.config,
186
186
  tmuxSession,
187
- onCreateSession: (name) => this.createTmuxSession(name)
187
+ onCreateSession: (name, workingDir) => this.createTmuxSession(name, workingDir)
188
188
  });
189
189
  this.handlers.set(tmuxSession, handler);
190
190
  handler.start();
@@ -199,7 +199,7 @@ class AgentRunner {
199
199
  console.log(`Stopped handler for session: ${this.config.machineId}/${tmuxSession}`);
200
200
  }
201
201
  }
202
- createTmuxSession(sessionName) {
202
+ createTmuxSession(sessionName, workingDir) {
203
203
  // Sanitize session name
204
204
  const sanitized = sessionName.replace(/[^a-zA-Z0-9_-]/g, '_');
205
205
  if (!sanitized) {
@@ -210,8 +210,8 @@ class AgentRunner {
210
210
  console.warn(`Session already exists: ${sanitized}`);
211
211
  return;
212
212
  }
213
- console.log(`Creating new tmux session: ${sanitized}`);
214
- if (tmux.createSession(sanitized)) {
213
+ console.log(`Creating new tmux session: ${sanitized}${workingDir ? ` (cwd: ${workingDir})` : ''}`);
214
+ if (tmux.createSession(sanitized, workingDir)) {
215
215
  console.log(`Successfully created tmux session: ${sanitized}`);
216
216
  // Force immediate scan
217
217
  this.scanAndUpdateSessions();
@@ -2,7 +2,7 @@ import { AgentConfig } from './types';
2
2
  interface SessionHandlerOptions {
3
3
  config: AgentConfig;
4
4
  tmuxSession: string;
5
- onCreateSession?: (name: string) => void;
5
+ onCreateSession?: (name: string, workingDir?: string) => void;
6
6
  }
7
7
  export declare class TmuxSessionHandler {
8
8
  private config;
@@ -52,6 +52,7 @@ export declare class TmuxSessionHandler {
52
52
  * Get content type from file extension
53
53
  */
54
54
  private getContentType;
55
+ private handleCreateWorktree;
55
56
  private startMetaTracking;
56
57
  private stopMetaTracking;
57
58
  private checkAndSendMeta;
@@ -38,6 +38,7 @@ const websocket_1 = require("./websocket");
38
38
  const tmux = __importStar(require("./tmux"));
39
39
  const fs = __importStar(require("fs"));
40
40
  const path = __importStar(require("path"));
41
+ const child_process_1 = require("child_process");
41
42
  const sentry_1 = require("../sentry");
42
43
  const debug_1 = require("./debug");
43
44
  // Capture intervals
@@ -92,6 +93,7 @@ class TmuxSessionHandler {
92
93
  });
93
94
  this.wsClient.on('connected', () => {
94
95
  console.log(`[${this.tmuxSession}] Connected to relay`);
96
+ this.currentMetaJson = ''; // Force resend meta on reconnect
95
97
  this.startScreenCapture();
96
98
  this.startMetaTracking();
97
99
  });
@@ -133,6 +135,9 @@ class TmuxSessionHandler {
133
135
  this.wsClient.on('uploadFile', (chunk) => {
134
136
  this.handleUploadChunk(chunk);
135
137
  });
138
+ this.wsClient.on('createWorktree', (branch) => {
139
+ this.handleCreateWorktree(branch);
140
+ });
136
141
  this.wsClient.on('error', (error) => {
137
142
  (0, sentry_1.captureException)(error);
138
143
  console.error(`[${this.tmuxSession}] WebSocket error:`, error.message);
@@ -300,6 +305,41 @@ class TmuxSessionHandler {
300
305
  };
301
306
  return types[ext] || 'application/octet-stream';
302
307
  }
308
+ handleCreateWorktree(branch) {
309
+ try {
310
+ const cwd = tmux.getPaneCwd(this.tmuxSession);
311
+ if (!cwd) {
312
+ console.error(`[${this.tmuxSession}] Cannot create worktree: no cwd`);
313
+ return;
314
+ }
315
+ // Check if it's a git repo
316
+ try {
317
+ (0, child_process_1.execSync)('git rev-parse --is-inside-work-tree', { cwd, stdio: 'pipe', timeout: 5000 });
318
+ }
319
+ catch {
320
+ console.error(`[${this.tmuxSession}] Cannot create worktree: not a git repo`);
321
+ return;
322
+ }
323
+ // Sanitize branch name
324
+ const safeBranch = branch.replace(/[^a-zA-Z0-9_\-/.]/g, '-');
325
+ const worktreeDir = path.join(cwd, '.worktrees', safeBranch.replace(/\//g, '-'));
326
+ console.log(`[${this.tmuxSession}] Creating worktree: branch=${safeBranch}, dir=${worktreeDir}`);
327
+ // git worktree add
328
+ (0, child_process_1.execSync)(`git worktree add -b "${safeBranch}" "${worktreeDir}"`, {
329
+ cwd, stdio: 'pipe', timeout: 10000
330
+ });
331
+ // Create new tmux session at worktree path
332
+ const sessionName = safeBranch.replace(/\//g, '-');
333
+ if (this.onCreateSession) {
334
+ this.onCreateSession(sessionName, worktreeDir);
335
+ }
336
+ console.log(`[${this.tmuxSession}] Worktree created: ${worktreeDir}`);
337
+ (0, debug_1.debugLog)(this.tmuxSession, 'Worktree created', { branch: safeBranch, dir: worktreeDir, session: sessionName });
338
+ }
339
+ catch (error) {
340
+ console.error(`[${this.tmuxSession}] Worktree creation failed:`, error.message);
341
+ }
342
+ }
303
343
  startMetaTracking() {
304
344
  this.checkAndSendMeta();
305
345
  this.metaCheckTimer = setInterval(() => this.checkAndSendMeta(), META_CHECK_INTERVAL_MS);
@@ -143,6 +143,11 @@ class RelayWebSocketClient extends events_1.EventEmitter {
143
143
  this.emit('killSession');
144
144
  }
145
145
  break;
146
+ case 'createWorktree':
147
+ if (message.session === this.sessionId && message.meta?.branch) {
148
+ this.emit('createWorktree', message.meta.branch);
149
+ }
150
+ break;
146
151
  case 'requestFileView':
147
152
  if (message.session === this.sessionId && message.meta?.filePath) {
148
153
  this.emit('requestFileView', message.meta.filePath);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sessioncast-cli",
3
- "version": "2.1.0",
3
+ "version": "2.2.1",
4
4
  "description": "SessionCast CLI - Control your agents from anywhere",
5
5
  "main": "dist/index.js",
6
6
  "bin": {