sessioncast-cli 1.1.5 → 2.0.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 (39) hide show
  1. package/README.md +27 -1
  2. package/dist/agent/runner.js +26 -23
  3. package/dist/agent/session-handler.d.ts +30 -1
  4. package/dist/agent/session-handler.js +166 -36
  5. package/dist/agent/tmux-executor.d.ts +6 -0
  6. package/dist/agent/tmux-executor.js +61 -2
  7. package/dist/agent/tmux.d.ts +8 -0
  8. package/dist/agent/tmux.js +14 -0
  9. package/dist/agent/websocket.d.ts +16 -2
  10. package/dist/agent/websocket.js +54 -70
  11. package/dist/api.js +2 -5
  12. package/dist/commands/login.js +7 -29
  13. package/dist/index.js +3 -3
  14. package/package.json +3 -3
  15. package/LICENSE +0 -21
  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/project/executor.d.ts +0 -73
  31. package/dist/project/executor.js +0 -437
  32. package/dist/project/index.d.ts +0 -4
  33. package/dist/project/index.js +0 -20
  34. package/dist/project/manager.d.ts +0 -66
  35. package/dist/project/manager.js +0 -290
  36. package/dist/project/relay-client.d.ts +0 -37
  37. package/dist/project/relay-client.js +0 -204
  38. package/dist/project/types.d.ts +0 -48
  39. package/dist/project/types.js +0 -3
@@ -40,7 +40,6 @@ 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 fileUtils_1 = require("../utils/fileUtils");
44
43
  const MAX_RECONNECT_ATTEMPTS = 5;
45
44
  const BASE_RECONNECT_DELAY_MS = 2000;
46
45
  const MAX_RECONNECT_DELAY_MS = 60000;
@@ -117,10 +116,6 @@ class RelayWebSocketClient extends events_1.EventEmitter {
117
116
  });
118
117
  }
119
118
  handleMessage(message) {
120
- // Debug: log all incoming message types (except frequent ones)
121
- if (message.type !== 'pong' && message.type !== 'keys') {
122
- console.log(`[WS] Message received: type=${message.type}, session=${message.session}`);
123
- }
124
119
  switch (message.type) {
125
120
  case 'keys':
126
121
  if (message.session === this.sessionId && message.payload) {
@@ -147,17 +142,20 @@ class RelayWebSocketClient extends events_1.EventEmitter {
147
142
  }
148
143
  break;
149
144
  case 'requestFileView':
150
- console.log(`[WS] requestFileView received: session=${message.session}, mySession=${this.sessionId}, filePath=${message.meta?.filePath}`);
151
145
  if (message.session === this.sessionId && message.meta?.filePath) {
152
146
  this.emit('requestFileView', message.meta.filePath);
153
147
  }
154
- else {
155
- console.log(`[WS] requestFileView ignored: sessionMatch=${message.session === this.sessionId}, hasFilePath=${!!message.meta?.filePath}`);
156
- }
157
148
  break;
158
149
  case 'uploadFile':
159
- if (message.session === this.sessionId && message.meta && message.payload) {
160
- this.handleFileUpload(message);
150
+ if (message.session === this.sessionId && message.payload && message.meta) {
151
+ this.emit('uploadFile', {
152
+ filename: message.meta.filename,
153
+ size: parseInt(message.meta.size || '0', 10),
154
+ mimeType: message.meta.mimeType,
155
+ chunkIndex: parseInt(message.meta.chunkIndex || '0', 10),
156
+ totalChunks: parseInt(message.meta.totalChunks || '1', 10),
157
+ payload: message.payload
158
+ });
161
159
  }
162
160
  break;
163
161
  case 'error':
@@ -167,55 +165,6 @@ class RelayWebSocketClient extends events_1.EventEmitter {
167
165
  this.emit('message', message);
168
166
  }
169
167
  }
170
- async handleFileUpload(message) {
171
- const meta = message.meta;
172
- if (!meta || !message.payload)
173
- return;
174
- try {
175
- const result = await (0, fileUtils_1.handleUploadChunk)(this.sessionId, {
176
- filename: meta.filename || 'unknown',
177
- size: meta.size || '0',
178
- mimeType: meta.mimeType || 'application/octet-stream',
179
- chunkIndex: meta.chunkIndex || '0',
180
- totalChunks: meta.totalChunks || '1',
181
- }, message.payload);
182
- // Only send response when upload is complete (result is not null)
183
- if (result) {
184
- if (result.success) {
185
- this.send({
186
- type: 'uploadComplete',
187
- session: this.sessionId,
188
- meta: {
189
- filename: meta.filename || 'unknown',
190
- path: result.path || '',
191
- success: 'true',
192
- },
193
- });
194
- }
195
- else {
196
- this.send({
197
- type: 'uploadError',
198
- session: this.sessionId,
199
- meta: {
200
- filename: meta.filename || 'unknown',
201
- error: result.error || 'Upload failed',
202
- },
203
- });
204
- }
205
- }
206
- }
207
- catch (e) {
208
- console.error('[WS] File upload error:', e);
209
- this.send({
210
- type: 'uploadError',
211
- session: this.sessionId,
212
- meta: {
213
- filename: meta.filename || 'unknown',
214
- error: e instanceof Error ? e.message : 'Upload failed',
215
- },
216
- });
217
- }
218
- }
219
168
  handleError(message) {
220
169
  const meta = message.meta;
221
170
  if (!meta)
@@ -316,21 +265,56 @@ class RelayWebSocketClient extends events_1.EventEmitter {
316
265
  return this.sendScreen(data);
317
266
  }
318
267
  }
319
- sendFileView(filePath, content, language, error) {
268
+ /**
269
+ * Send file content to be displayed in the web FileViewer
270
+ * @param filename - The name of the file
271
+ * @param content - The file content (UTF-8 for text, base64 for images)
272
+ * @param contentType - MIME type (e.g., 'text/markdown', 'text/html', 'image/png')
273
+ * @param path - Optional file path
274
+ */
275
+ sendFileView(filename, content, contentType, path) {
320
276
  if (!this.isConnected)
321
277
  return false;
322
- const meta = {
323
- filePath: filePath,
324
- language: language
325
- };
326
- if (error) {
327
- meta.error = error;
328
- }
329
278
  return this.send({
330
279
  type: 'file_view',
331
280
  session: this.sessionId,
332
- meta: meta,
333
- payload: Buffer.from(content).toString('base64')
281
+ meta: {
282
+ filename,
283
+ contentType,
284
+ path: path || ''
285
+ },
286
+ payload: content
287
+ });
288
+ }
289
+ /**
290
+ * Send upload complete notification to web viewer
291
+ */
292
+ sendUploadComplete(filename, path) {
293
+ if (!this.isConnected)
294
+ return false;
295
+ return this.send({
296
+ type: 'uploadComplete',
297
+ session: this.sessionId,
298
+ meta: {
299
+ filename,
300
+ path,
301
+ success: 'true'
302
+ }
303
+ });
304
+ }
305
+ /**
306
+ * Send upload error notification to web viewer
307
+ */
308
+ sendUploadError(filename, error) {
309
+ if (!this.isConnected)
310
+ return false;
311
+ return this.send({
312
+ type: 'uploadError',
313
+ session: this.sessionId,
314
+ meta: {
315
+ filename,
316
+ error
317
+ }
334
318
  });
335
319
  }
336
320
  getConnected() {
package/dist/api.js CHANGED
@@ -9,14 +9,11 @@ const config_1 = require("./config");
9
9
  class ApiClient {
10
10
  getHeaders() {
11
11
  const apiKey = (0, config_1.getApiKey)();
12
- const accessToken = (0, config_1.getAccessToken)();
13
- const agentToken = (0, config_1.getAgentToken)();
14
- const token = accessToken || apiKey || agentToken;
15
- if (!token) {
12
+ if (!apiKey) {
16
13
  throw new Error('Not logged in. Run: sessioncast login');
17
14
  }
18
15
  return {
19
- 'Authorization': `Bearer ${token}`,
16
+ 'Authorization': `Bearer ${apiKey}`,
20
17
  'Content-Type': 'application/json'
21
18
  };
22
19
  }
@@ -69,11 +69,11 @@ async function manualLogin(apiKey, options) {
69
69
  }
70
70
  if (apiKey.startsWith('agt_')) {
71
71
  (0, config_1.setAgentToken)(apiKey);
72
- console.log(chalk_1.default.green(' Agent token saved!'));
72
+ console.log(chalk_1.default.green('\u2713 Agent token saved!'));
73
73
  }
74
74
  else {
75
75
  (0, config_1.setApiKey)(apiKey);
76
- console.log(chalk_1.default.green(' API key saved!'));
76
+ console.log(chalk_1.default.green('\u2713 API key saved!'));
77
77
  }
78
78
  }
79
79
  async function browserLogin(options = {}) {
@@ -197,15 +197,9 @@ async function browserLogin(options = {}) {
197
197
  (0, config_1.setMachineId)(agentData.machineId || os.hostname());
198
198
  }
199
199
  spinner.succeed('Login successful!');
200
- console.log(chalk_1.default.green('\n You are now logged in to SessionCast\n'));
201
- console.log(chalk_1.default.gray(' Start the agent:'));
202
- console.log(chalk_1.default.white(' sessioncast agent\n'));
203
- console.log(chalk_1.default.gray(' Run in background:'));
204
- console.log(chalk_1.default.white(' nohup sessioncast agent > agent.log 2>&1 &\n'));
205
- console.log(chalk_1.default.gray(' Check logs:'));
206
- console.log(chalk_1.default.white(' tail -f agent.log\n'));
207
- await checkForUpdates();
208
- process.exit(0);
200
+ console.log(chalk_1.default.green('\n\u2713 You are now logged in to SessionCast\n'));
201
+ console.log(chalk_1.default.gray(' Run `sessioncast agent` to start the agent'));
202
+ console.log(chalk_1.default.gray(' Run `sessioncast status` to check your login status\n'));
209
203
  }
210
204
  catch (err) {
211
205
  spinner.fail(`Login failed: ${err.message}`);
@@ -218,12 +212,12 @@ async function logout() {
218
212
  return;
219
213
  }
220
214
  (0, config_1.clearAuth)();
221
- console.log(chalk_1.default.green(' Logged out successfully!'));
215
+ console.log(chalk_1.default.green('\u2713 Logged out successfully!'));
222
216
  }
223
217
  function status() {
224
218
  const accessToken = (0, config_1.getAccessToken)();
225
219
  if ((0, config_1.isLoggedIn)()) {
226
- console.log(chalk_1.default.green(' Logged in'));
220
+ console.log(chalk_1.default.green('\u2713 Logged in'));
227
221
  if (accessToken) {
228
222
  console.log(chalk_1.default.gray(' Auth method: OAuth'));
229
223
  }
@@ -236,19 +230,3 @@ function status() {
236
230
  console.log(chalk_1.default.gray('Run: sessioncast login'));
237
231
  }
238
232
  }
239
- const CURRENT_VERSION = require('../../package.json').version;
240
- async function checkForUpdates() {
241
- try {
242
- const res = await (0, node_fetch_1.default)('https://registry.npmjs.org/sessioncast-cli/latest', { timeout: 3000 });
243
- if (!res.ok) return;
244
- const data = await res.json();
245
- const latest = data.version;
246
- if (latest && latest !== CURRENT_VERSION) {
247
- console.log(chalk_1.default.yellow(` ⬆ Update available: ${CURRENT_VERSION} → ${latest}`));
248
- console.log(chalk_1.default.white(` npm install -g sessioncast-cli@latest\n`));
249
- }
250
- }
251
- catch (_e) {
252
- // silently ignore - network errors shouldn't block login
253
- }
254
- }
package/dist/index.js CHANGED
@@ -85,12 +85,12 @@ function showWelcome() {
85
85
  return;
86
86
  const { available, isWindows } = checkTmux();
87
87
  console.log('');
88
- console.log(chalk_1.default.green.bold(' SessionCast CLI installed'));
88
+ console.log(chalk_1.default.green.bold('\u2713 SessionCast CLI installed'));
89
89
  console.log('');
90
90
  if (!available) {
91
- console.log(chalk_1.default.yellow(' tmux not found'));
91
+ console.log(chalk_1.default.yellow('\u26a0 tmux not found'));
92
92
  if (isWindows) {
93
- console.log(chalk_1.default.gray(' Install itmux: https://github.com/phayte/itmux'));
93
+ console.log(chalk_1.default.gray(' Install itmux: https://github.com/itefixnet/itmux'));
94
94
  console.log(chalk_1.default.gray(' Or: choco install itmux'));
95
95
  }
96
96
  else if (os.platform() === 'darwin') {
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "sessioncast-cli",
3
- "version": "1.1.5",
3
+ "version": "2.0.0",
4
4
  "description": "SessionCast CLI - Control your agents from anywhere",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
- "sessioncast": "dist/index.js"
7
+ "sessioncast": "./dist/index.js"
8
8
  },
9
9
  "scripts": {
10
10
  "build": "tsc",
11
11
  "dev": "ts-node src/index.ts",
12
12
  "start": "node dist/index.js",
13
- "prepublishOnly": "echo 'skip build'"
13
+ "prepublishOnly": "npm run build"
14
14
  },
15
15
  "keywords": [
16
16
  "sessioncast",
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 SessionCast
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
@@ -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>;