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.
- package/README.md +27 -1
- package/dist/agent/runner.js +26 -23
- package/dist/agent/session-handler.d.ts +30 -1
- package/dist/agent/session-handler.js +166 -36
- package/dist/agent/tmux-executor.d.ts +6 -0
- package/dist/agent/tmux-executor.js +61 -2
- package/dist/agent/tmux.d.ts +8 -0
- package/dist/agent/tmux.js +14 -0
- package/dist/agent/websocket.d.ts +16 -2
- package/dist/agent/websocket.js +54 -70
- package/dist/api.js +2 -5
- package/dist/commands/login.js +7 -29
- package/dist/index.js +3 -3
- package/package.json +3 -3
- package/LICENSE +0 -21
- package/dist/autopilot/index.d.ts +0 -94
- package/dist/autopilot/index.js +0 -322
- package/dist/autopilot/mission-analyzer.d.ts +0 -27
- package/dist/autopilot/mission-analyzer.js +0 -232
- package/dist/autopilot/project-detector.d.ts +0 -12
- package/dist/autopilot/project-detector.js +0 -326
- package/dist/autopilot/source-scanner.d.ts +0 -26
- package/dist/autopilot/source-scanner.js +0 -285
- package/dist/autopilot/speckit-generator.d.ts +0 -60
- package/dist/autopilot/speckit-generator.js +0 -511
- package/dist/autopilot/types.d.ts +0 -110
- package/dist/autopilot/types.js +0 -6
- package/dist/autopilot/workflow-generator.d.ts +0 -33
- package/dist/autopilot/workflow-generator.js +0 -278
- package/dist/project/executor.d.ts +0 -73
- package/dist/project/executor.js +0 -437
- package/dist/project/index.d.ts +0 -4
- package/dist/project/index.js +0 -20
- package/dist/project/manager.d.ts +0 -66
- package/dist/project/manager.js +0 -290
- package/dist/project/relay-client.d.ts +0 -37
- package/dist/project/relay-client.js +0 -204
- package/dist/project/types.d.ts +0 -48
- package/dist/project/types.js +0 -3
package/dist/agent/websocket.js
CHANGED
|
@@ -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.
|
|
160
|
-
this.
|
|
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
|
-
|
|
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:
|
|
333
|
-
|
|
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
|
-
|
|
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 ${
|
|
16
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
20
17
|
'Content-Type': 'application/json'
|
|
21
18
|
};
|
|
22
19
|
}
|
package/dist/commands/login.js
CHANGED
|
@@ -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('
|
|
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('
|
|
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
|
|
201
|
-
console.log(chalk_1.default.gray('
|
|
202
|
-
console.log(chalk_1.default.
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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/
|
|
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": "
|
|
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": "
|
|
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>;
|