sessioncast-cli 2.0.2 → 2.0.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.
Files changed (45) hide show
  1. package/dist/agent/runner.js +24 -2
  2. package/dist/agent/session-handler.d.ts +3 -2
  3. package/dist/agent/session-handler.js +60 -53
  4. package/dist/agent/tmux-executor.d.ts +19 -33
  5. package/dist/agent/tmux-executor.js +51 -38
  6. package/dist/agent/tmux.d.ts +12 -6
  7. package/dist/agent/tmux.js +16 -9
  8. package/dist/agent/types.d.ts +0 -10
  9. package/dist/agent/websocket.d.ts +6 -13
  10. package/dist/agent/websocket.js +36 -37
  11. package/dist/commands/agent.js +3 -0
  12. package/dist/index.js +14 -0
  13. package/dist/sentry.d.ts +4 -0
  14. package/dist/sentry.js +87 -0
  15. package/package.json +2 -1
  16. package/dist/autopilot/index.d.ts +0 -94
  17. package/dist/autopilot/index.js +0 -322
  18. package/dist/autopilot/mission-analyzer.d.ts +0 -27
  19. package/dist/autopilot/mission-analyzer.js +0 -232
  20. package/dist/autopilot/project-detector.d.ts +0 -12
  21. package/dist/autopilot/project-detector.js +0 -326
  22. package/dist/autopilot/source-scanner.d.ts +0 -26
  23. package/dist/autopilot/source-scanner.js +0 -285
  24. package/dist/autopilot/speckit-generator.d.ts +0 -60
  25. package/dist/autopilot/speckit-generator.js +0 -511
  26. package/dist/autopilot/types.d.ts +0 -110
  27. package/dist/autopilot/types.js +0 -6
  28. package/dist/autopilot/workflow-generator.d.ts +0 -33
  29. package/dist/autopilot/workflow-generator.js +0 -278
  30. package/dist/commands/autopilot.d.ts +0 -30
  31. package/dist/commands/autopilot.js +0 -262
  32. package/dist/commands/project.d.ts +0 -33
  33. package/dist/commands/project.js +0 -350
  34. package/dist/project/executor.d.ts +0 -73
  35. package/dist/project/executor.js +0 -437
  36. package/dist/project/index.d.ts +0 -4
  37. package/dist/project/index.js +0 -20
  38. package/dist/project/manager.d.ts +0 -66
  39. package/dist/project/manager.js +0 -290
  40. package/dist/project/relay-client.d.ts +0 -37
  41. package/dist/project/relay-client.js +0 -204
  42. package/dist/project/types.d.ts +0 -48
  43. package/dist/project/types.js +0 -3
  44. package/dist/utils/fileUtils.d.ts +0 -28
  45. package/dist/utils/fileUtils.js +0 -159
@@ -40,11 +40,10 @@ exports.RelayWebSocketClient = void 0;
40
40
  const ws_1 = __importDefault(require("ws"));
41
41
  const events_1 = require("events");
42
42
  const zlib = __importStar(require("zlib"));
43
- const MAX_RECONNECT_ATTEMPTS = 50;
43
+ const MAX_RECONNECT_ATTEMPTS = 5;
44
44
  const BASE_RECONNECT_DELAY_MS = 2000;
45
45
  const MAX_RECONNECT_DELAY_MS = 60000;
46
46
  const CIRCUIT_BREAKER_DURATION_MS = 120000;
47
- const PING_INTERVAL_MS = 30000;
48
47
  class RelayWebSocketClient extends events_1.EventEmitter {
49
48
  constructor(options) {
50
49
  super();
@@ -54,7 +53,6 @@ class RelayWebSocketClient extends events_1.EventEmitter {
54
53
  this.circuitBreakerOpen = false;
55
54
  this.circuitBreakerResetTime = 0;
56
55
  this.reconnectTimer = null;
57
- this.pingTimer = null;
58
56
  this.destroyed = false;
59
57
  this.url = options.url;
60
58
  this.sessionId = options.sessionId;
@@ -72,9 +70,8 @@ class RelayWebSocketClient extends events_1.EventEmitter {
72
70
  this.isConnected = true;
73
71
  this.reconnectAttempts = 0;
74
72
  this.circuitBreakerOpen = false;
75
- this.registerAsHost();
76
- this.startPing();
77
73
  this.emit('connected');
74
+ this.registerAsHost();
78
75
  });
79
76
  this.ws.on('message', (data) => {
80
77
  try {
@@ -87,7 +84,6 @@ class RelayWebSocketClient extends events_1.EventEmitter {
87
84
  });
88
85
  this.ws.on('close', (code, reason) => {
89
86
  this.isConnected = false;
90
- this.stopPing();
91
87
  this.emit('disconnected', { code, reason: reason.toString() });
92
88
  if (this.autoReconnect && !this.destroyed) {
93
89
  this.scheduleReconnect();
@@ -123,7 +119,7 @@ class RelayWebSocketClient extends events_1.EventEmitter {
123
119
  switch (message.type) {
124
120
  case 'keys':
125
121
  if (message.session === this.sessionId && message.payload) {
126
- this.emit('keys', message.payload, message.meta);
122
+ this.emit('keys', message.payload, message.meta?.pane);
127
123
  }
128
124
  break;
129
125
  case 'resize':
@@ -192,20 +188,6 @@ class RelayWebSocketClient extends events_1.EventEmitter {
192
188
  console.error(`Error: code=${meta.code}, message=${meta.messageEn}`);
193
189
  }
194
190
  }
195
- startPing() {
196
- this.stopPing();
197
- this.pingTimer = setInterval(() => {
198
- if (this.ws && this.ws.readyState === ws_1.default.OPEN) {
199
- this.ws.ping();
200
- }
201
- }, PING_INTERVAL_MS);
202
- }
203
- stopPing() {
204
- if (this.pingTimer) {
205
- clearInterval(this.pingTimer);
206
- this.pingTimer = null;
207
- }
208
- }
209
191
  scheduleReconnect() {
210
192
  if (this.destroyed)
211
193
  return;
@@ -257,38 +239,56 @@ class RelayWebSocketClient extends events_1.EventEmitter {
257
239
  return false;
258
240
  }
259
241
  }
260
- sendScreen(data, paneMeta) {
242
+ sendScreen(data) {
261
243
  if (!this.isConnected)
262
244
  return false;
263
245
  const base64Data = data.toString('base64');
264
- const msg = {
246
+ return this.send({
265
247
  type: 'screen',
266
248
  session: this.sessionId,
267
249
  payload: base64Data
268
- };
269
- if (paneMeta) {
270
- msg.meta = { pane: paneMeta.pane, index: String(paneMeta.index) };
271
- }
272
- return this.send(msg);
250
+ });
273
251
  }
274
- sendScreenCompressed(data, paneMeta) {
252
+ sendScreenWithMeta(data, meta) {
253
+ if (!this.isConnected)
254
+ return false;
255
+ return this.send({
256
+ type: 'screen',
257
+ session: this.sessionId,
258
+ payload: data.toString('base64'),
259
+ meta
260
+ });
261
+ }
262
+ sendScreenCompressed(data) {
275
263
  if (!this.isConnected)
276
264
  return false;
277
265
  try {
278
266
  const compressed = zlib.gzipSync(data);
279
267
  const base64Data = compressed.toString('base64');
280
- const msg = {
268
+ return this.send({
281
269
  type: 'screenGz',
282
270
  session: this.sessionId,
283
271
  payload: base64Data
284
- };
285
- if (paneMeta) {
286
- msg.meta = { pane: paneMeta.pane, index: String(paneMeta.index) };
287
- }
288
- return this.send(msg);
272
+ });
273
+ }
274
+ catch {
275
+ return this.sendScreen(data);
276
+ }
277
+ }
278
+ sendScreenCompressedWithMeta(data, meta) {
279
+ if (!this.isConnected)
280
+ return false;
281
+ try {
282
+ const compressed = zlib.gzipSync(data);
283
+ return this.send({
284
+ type: 'screenGz',
285
+ session: this.sessionId,
286
+ payload: compressed.toString('base64'),
287
+ meta
288
+ });
289
289
  }
290
290
  catch {
291
- return this.sendScreen(data, paneMeta);
291
+ return this.sendScreenWithMeta(data, meta);
292
292
  }
293
293
  }
294
294
  sendPaneLayout(panes) {
@@ -358,7 +358,6 @@ class RelayWebSocketClient extends events_1.EventEmitter {
358
358
  destroy() {
359
359
  this.destroyed = true;
360
360
  this.autoReconnect = false;
361
- this.stopPing();
362
361
  if (this.reconnectTimer) {
363
362
  clearTimeout(this.reconnectTimer);
364
363
  this.reconnectTimer = null;
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.startAgent = startAgent;
7
7
  const chalk_1 = __importDefault(require("chalk"));
8
8
  const runner_1 = require("../agent/runner");
9
+ const sentry_1 = require("../sentry");
9
10
  async function startAgent(options) {
10
11
  try {
11
12
  const config = runner_1.AgentRunner.loadConfig(options.config);
@@ -13,6 +14,8 @@ async function startAgent(options) {
13
14
  await runner.start();
14
15
  }
15
16
  catch (error) {
17
+ (0, sentry_1.captureException)(error);
18
+ await (0, sentry_1.flush)();
16
19
  console.error(chalk_1.default.red(`Error: ${error.message}`));
17
20
  process.exit(1);
18
21
  }
package/dist/index.js CHANGED
@@ -47,6 +47,20 @@ const sessions_1 = require("./commands/sessions");
47
47
  const sendkeys_1 = require("./commands/sendkeys");
48
48
  const agent_1 = require("./commands/agent");
49
49
  const config_1 = require("./config");
50
+ const sentry_1 = require("./sentry");
51
+ // Initialize Sentry as early as possible
52
+ (0, sentry_1.initSentry)();
53
+ // Catch unhandled errors globally
54
+ process.on('uncaughtException', async (error) => {
55
+ (0, sentry_1.captureException)(error);
56
+ await (0, sentry_1.flush)();
57
+ console.error(chalk_1.default.red(`Fatal error: ${error.message}`));
58
+ process.exit(1);
59
+ });
60
+ process.on('unhandledRejection', async (reason) => {
61
+ (0, sentry_1.captureException)(reason);
62
+ await (0, sentry_1.flush)();
63
+ });
50
64
  // Check if tmux/itmux is available
51
65
  function checkTmux() {
52
66
  const isWindows = os.platform() === 'win32';
@@ -0,0 +1,4 @@
1
+ export declare function initSentry(): void;
2
+ export declare function captureException(error: unknown): void;
3
+ export declare function setUser(email: string): void;
4
+ export declare function flush(): Promise<void>;
package/dist/sentry.js ADDED
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.initSentry = initSentry;
37
+ exports.captureException = captureException;
38
+ exports.setUser = setUser;
39
+ exports.flush = flush;
40
+ const Sentry = __importStar(require("@sentry/node"));
41
+ const os = __importStar(require("os"));
42
+ const SENTRY_DSN = process.env.SESSIONCAST_SENTRY_DSN || 'https://ee8894c0f54e651031b49f21a5bf8dc4@o4510832077701120.ingest.us.sentry.io/4510861067681792';
43
+ let initialized = false;
44
+ function initSentry() {
45
+ if (initialized || !SENTRY_DSN)
46
+ return;
47
+ Sentry.init({
48
+ dsn: SENTRY_DSN,
49
+ environment: process.env.NODE_ENV || 'production',
50
+ release: `sessioncast-cli@${getVersion()}`,
51
+ beforeSend(event) {
52
+ // Strip sensitive data: tokens, paths with usernames
53
+ if (event.extra) {
54
+ delete event.extra['token'];
55
+ delete event.extra['apiKey'];
56
+ }
57
+ return event;
58
+ },
59
+ });
60
+ Sentry.setTag('platform', os.platform());
61
+ Sentry.setTag('arch', os.arch());
62
+ Sentry.setTag('node', process.version);
63
+ initialized = true;
64
+ }
65
+ function captureException(error) {
66
+ if (!initialized)
67
+ return;
68
+ Sentry.captureException(error);
69
+ }
70
+ function setUser(email) {
71
+ if (!initialized)
72
+ return;
73
+ Sentry.setUser({ email });
74
+ }
75
+ async function flush() {
76
+ if (!initialized)
77
+ return;
78
+ await Sentry.flush(2000);
79
+ }
80
+ function getVersion() {
81
+ try {
82
+ return require('../package.json').version;
83
+ }
84
+ catch {
85
+ return 'unknown';
86
+ }
87
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sessioncast-cli",
3
- "version": "2.0.2",
3
+ "version": "2.0.4",
4
4
  "description": "SessionCast CLI - Control your agents from anywhere",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -26,6 +26,7 @@
26
26
  "dist"
27
27
  ],
28
28
  "dependencies": {
29
+ "@sentry/node": "^10.38.0",
29
30
  "chalk": "^4.1.2",
30
31
  "commander": "^12.1.0",
31
32
  "conf": "^10.2.0",
@@ -1,94 +0,0 @@
1
- /**
2
- * AutoPilot - Single-prompt execution layer for SessionCast
3
- *
4
- * Enables opencode-style experience: one prompt → auto-detect → auto-analyze → auto-execute
5
- */
6
- import { EventEmitter } from 'events';
7
- import { AutoPilotContext, AutoPilotOptions, GeneratedWorkflow } from './types';
8
- import { toExecutableWorkflow } from './workflow-generator';
9
- import { generateSpeckit } from './speckit-generator';
10
- export * from './types';
11
- export { generateSpeckit, generateQuickSpeckit, saveSpeckit } from './speckit-generator';
12
- export type { SpeckitOutput } from './speckit-generator';
13
- export declare class AutoPilot extends EventEmitter {
14
- private options;
15
- private context;
16
- private llmClient?;
17
- constructor(options: AutoPilotOptions);
18
- /**
19
- * Create initial context
20
- */
21
- private createInitialContext;
22
- /**
23
- * Set LLM client for mission analysis
24
- */
25
- setLlmClient(client: {
26
- chat: (messages: {
27
- role: string;
28
- content: string;
29
- }[]) => Promise<string>;
30
- }): void;
31
- /**
32
- * Get current context
33
- */
34
- getContext(): AutoPilotContext;
35
- /**
36
- * Main entry point: execute a single prompt
37
- */
38
- execute(prompt: string): Promise<GeneratedWorkflow>;
39
- /**
40
- * Quick execute without LLM analysis
41
- */
42
- quickExecute(prompt: string): Promise<GeneratedWorkflow>;
43
- /**
44
- * Phase 1: Detect project type
45
- */
46
- private detectProject;
47
- /**
48
- * Phase 2: Scan sources
49
- */
50
- private scanProject;
51
- /**
52
- * Phase 3: Analyze mission
53
- */
54
- private analyzeMission;
55
- /**
56
- * Phase 4: Generate workflow
57
- */
58
- private generateWorkflow;
59
- /**
60
- * Convert to executable workflow format (compatible with existing ProjectManager)
61
- */
62
- toExecutableFormat(): ReturnType<typeof toExecutableWorkflow> | null;
63
- /**
64
- * Convert to Speckit format (plan.md + tasks.md)
65
- */
66
- toSpeckit(): ReturnType<typeof generateSpeckit>;
67
- /**
68
- * Generate and save Speckit files
69
- */
70
- saveSpeckit(outputDir?: string): {
71
- planPath: string;
72
- tasksPath: string;
73
- };
74
- /**
75
- * Update status and emit event
76
- */
77
- private updateStatus;
78
- /**
79
- * Get a summary of the analysis for display
80
- */
81
- getSummary(): string;
82
- /**
83
- * Save workflow to file
84
- */
85
- saveWorkflow(outputPath?: string): Promise<string>;
86
- }
87
- /**
88
- * Convenience function for one-shot execution
89
- */
90
- export declare function autoPilot(prompt: string, options: AutoPilotOptions): Promise<GeneratedWorkflow>;
91
- /**
92
- * Quick version without LLM
93
- */
94
- export declare function autoPilotQuick(prompt: string, options: AutoPilotOptions): Promise<GeneratedWorkflow>;