sessioncast-cli 1.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/LICENSE +21 -0
- package/README.md +137 -0
- package/dist/agent/api-client.d.ts +27 -0
- package/dist/agent/api-client.js +295 -0
- package/dist/agent/exec-service.d.ts +6 -0
- package/dist/agent/exec-service.js +126 -0
- package/dist/agent/index.d.ts +8 -0
- package/dist/agent/index.js +24 -0
- package/dist/agent/llm-service.d.ts +9 -0
- package/dist/agent/llm-service.js +156 -0
- package/dist/agent/runner.d.ts +16 -0
- package/dist/agent/runner.js +187 -0
- package/dist/agent/session-handler.d.ts +28 -0
- package/dist/agent/session-handler.js +184 -0
- package/dist/agent/tmux.d.ts +29 -0
- package/dist/agent/tmux.js +157 -0
- package/dist/agent/types.d.ts +72 -0
- package/dist/agent/types.js +2 -0
- package/dist/agent/websocket.d.ts +45 -0
- package/dist/agent/websocket.js +288 -0
- package/dist/api.d.ts +31 -0
- package/dist/api.js +78 -0
- package/dist/commands/agent.d.ts +5 -0
- package/dist/commands/agent.js +19 -0
- package/dist/commands/agents.d.ts +1 -0
- package/dist/commands/agents.js +77 -0
- package/dist/commands/login.d.ts +5 -0
- package/dist/commands/login.js +41 -0
- package/dist/commands/project.d.ts +33 -0
- package/dist/commands/project.js +359 -0
- package/dist/commands/sendkeys.d.ts +3 -0
- package/dist/commands/sendkeys.js +66 -0
- package/dist/commands/sessions.d.ts +1 -0
- package/dist/commands/sessions.js +89 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.js +37 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +125 -0
- package/dist/project/executor.d.ts +118 -0
- package/dist/project/executor.js +893 -0
- package/dist/project/index.d.ts +4 -0
- package/dist/project/index.js +20 -0
- package/dist/project/manager.d.ts +79 -0
- package/dist/project/manager.js +397 -0
- package/dist/project/relay-client.d.ts +87 -0
- package/dist/project/relay-client.js +200 -0
- package/dist/project/types.d.ts +43 -0
- package/dist/project/types.js +3 -0
- package/package.json +59 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ProjectRelayClient = void 0;
|
|
7
|
+
const ws_1 = __importDefault(require("ws"));
|
|
8
|
+
const events_1 = require("events");
|
|
9
|
+
const PING_INTERVAL_MS = 15000; // Send ping every 15 seconds to keep connection alive
|
|
10
|
+
class ProjectRelayClient extends events_1.EventEmitter {
|
|
11
|
+
constructor(options) {
|
|
12
|
+
super();
|
|
13
|
+
this.ws = null;
|
|
14
|
+
this.isConnected = false;
|
|
15
|
+
this.destroyed = false;
|
|
16
|
+
this.reconnectTimer = null;
|
|
17
|
+
this.pingTimer = null;
|
|
18
|
+
this.options = options;
|
|
19
|
+
}
|
|
20
|
+
startPingInterval() {
|
|
21
|
+
this.stopPingInterval();
|
|
22
|
+
this.pingTimer = setInterval(() => {
|
|
23
|
+
if (this.ws?.readyState === ws_1.default.OPEN) {
|
|
24
|
+
this.send({ type: 'ping' });
|
|
25
|
+
}
|
|
26
|
+
}, PING_INTERVAL_MS);
|
|
27
|
+
}
|
|
28
|
+
stopPingInterval() {
|
|
29
|
+
if (this.pingTimer) {
|
|
30
|
+
clearInterval(this.pingTimer);
|
|
31
|
+
this.pingTimer = null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
connect() {
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
if (this.destroyed) {
|
|
37
|
+
reject(new Error('Client destroyed'));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
this.ws = new ws_1.default(this.options.url);
|
|
42
|
+
this.ws.on('open', () => {
|
|
43
|
+
this.isConnected = true;
|
|
44
|
+
this.registerProject();
|
|
45
|
+
this.startPingInterval();
|
|
46
|
+
this.emit('connected');
|
|
47
|
+
resolve();
|
|
48
|
+
});
|
|
49
|
+
this.ws.on('message', (data) => {
|
|
50
|
+
try {
|
|
51
|
+
const message = JSON.parse(data.toString());
|
|
52
|
+
this.handleMessage(message);
|
|
53
|
+
}
|
|
54
|
+
catch (e) {
|
|
55
|
+
console.error('Failed to parse message:', e);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
this.ws.on('close', () => {
|
|
59
|
+
this.isConnected = false;
|
|
60
|
+
this.stopPingInterval();
|
|
61
|
+
this.emit('disconnected');
|
|
62
|
+
if (!this.destroyed) {
|
|
63
|
+
this.scheduleReconnect();
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
this.ws.on('error', (error) => {
|
|
67
|
+
this.emit('error', error);
|
|
68
|
+
if (!this.isConnected) {
|
|
69
|
+
reject(error);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
reject(error);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
registerProject() {
|
|
79
|
+
this.send({
|
|
80
|
+
type: 'registerProject',
|
|
81
|
+
meta: {
|
|
82
|
+
projectId: this.options.projectId,
|
|
83
|
+
name: this.options.projectName,
|
|
84
|
+
mission: this.options.mission || '',
|
|
85
|
+
machineId: this.options.machineId,
|
|
86
|
+
token: this.options.token,
|
|
87
|
+
},
|
|
88
|
+
payload: this.options.sources ? JSON.stringify(this.options.sources) : undefined,
|
|
89
|
+
});
|
|
90
|
+
console.log(`Registered project with relay: ${this.options.projectId}`);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Update sources list on server
|
|
94
|
+
*/
|
|
95
|
+
updateSources(sources) {
|
|
96
|
+
this.send({
|
|
97
|
+
type: 'updateSources',
|
|
98
|
+
meta: {
|
|
99
|
+
projectId: this.options.projectId,
|
|
100
|
+
},
|
|
101
|
+
payload: JSON.stringify(sources),
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
handleMessage(message) {
|
|
105
|
+
this.emit('message', message);
|
|
106
|
+
}
|
|
107
|
+
scheduleReconnect() {
|
|
108
|
+
if (this.destroyed)
|
|
109
|
+
return;
|
|
110
|
+
this.reconnectTimer = setTimeout(() => {
|
|
111
|
+
if (!this.isConnected && !this.destroyed) {
|
|
112
|
+
console.log('Reconnecting to relay...');
|
|
113
|
+
this.connect().catch(err => {
|
|
114
|
+
console.error('Reconnection failed:', err.message);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}, 5000);
|
|
118
|
+
}
|
|
119
|
+
send(message) {
|
|
120
|
+
if (!this.ws || this.ws.readyState !== ws_1.default.OPEN) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
this.ws.send(JSON.stringify(message));
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
updateStatus(status, agents) {
|
|
132
|
+
const meta = {
|
|
133
|
+
projectId: this.options.projectId,
|
|
134
|
+
status,
|
|
135
|
+
};
|
|
136
|
+
this.send({
|
|
137
|
+
type: 'projectStatus',
|
|
138
|
+
meta,
|
|
139
|
+
payload: agents ? JSON.stringify(agents) : undefined,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Send mission analysis response back to server
|
|
144
|
+
*/
|
|
145
|
+
sendAnalysisResponse(requestId, steps, decisions = []) {
|
|
146
|
+
this.send({
|
|
147
|
+
type: 'missionAnalysis',
|
|
148
|
+
requestId,
|
|
149
|
+
steps,
|
|
150
|
+
decisions,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Send mission analysis error back to server
|
|
155
|
+
*/
|
|
156
|
+
sendAnalysisError(requestId, error) {
|
|
157
|
+
this.send({
|
|
158
|
+
type: 'missionAnalysis',
|
|
159
|
+
requestId,
|
|
160
|
+
error,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Send addSource result back to server
|
|
165
|
+
*/
|
|
166
|
+
sendAddSourceResult(requestId, result) {
|
|
167
|
+
this.send({
|
|
168
|
+
type: 'addSourceResult',
|
|
169
|
+
requestId,
|
|
170
|
+
meta: {
|
|
171
|
+
folder: result.folder,
|
|
172
|
+
fileCount: String(result.files.length),
|
|
173
|
+
},
|
|
174
|
+
payload: result.files.join('\n'),
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Send addSource error back to server
|
|
179
|
+
*/
|
|
180
|
+
sendAddSourceError(requestId, error) {
|
|
181
|
+
this.send({
|
|
182
|
+
type: 'addSourceResult',
|
|
183
|
+
requestId,
|
|
184
|
+
error,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
destroy() {
|
|
188
|
+
this.destroyed = true;
|
|
189
|
+
this.stopPingInterval();
|
|
190
|
+
if (this.reconnectTimer) {
|
|
191
|
+
clearTimeout(this.reconnectTimer);
|
|
192
|
+
this.reconnectTimer = null;
|
|
193
|
+
}
|
|
194
|
+
if (this.ws) {
|
|
195
|
+
this.ws.close();
|
|
196
|
+
this.ws = null;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
exports.ProjectRelayClient = ProjectRelayClient;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface Project {
|
|
2
|
+
name: string;
|
|
3
|
+
path: string;
|
|
4
|
+
createdAt: string;
|
|
5
|
+
status: ProjectStatus;
|
|
6
|
+
}
|
|
7
|
+
export type ProjectStatus = 'initializing' | 'ready' | 'running' | 'completed' | 'failed';
|
|
8
|
+
export interface Workflow {
|
|
9
|
+
name: string;
|
|
10
|
+
mission: string;
|
|
11
|
+
created: string;
|
|
12
|
+
agents: WorkflowAgent[];
|
|
13
|
+
}
|
|
14
|
+
export interface WorkflowAgent {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
workDir: string;
|
|
18
|
+
tasks: string[];
|
|
19
|
+
dependsOn: string[];
|
|
20
|
+
}
|
|
21
|
+
export interface WorkflowStatus {
|
|
22
|
+
workflow: string;
|
|
23
|
+
startedAt: string;
|
|
24
|
+
status: 'pending' | 'running' | 'completed' | 'failed';
|
|
25
|
+
agents: Record<string, AgentStatus>;
|
|
26
|
+
}
|
|
27
|
+
export interface AgentStatus {
|
|
28
|
+
status: 'pending' | 'running' | 'completed' | 'failed';
|
|
29
|
+
startedAt?: string;
|
|
30
|
+
completedAt?: string;
|
|
31
|
+
progress?: string;
|
|
32
|
+
currentTask?: string;
|
|
33
|
+
output?: string;
|
|
34
|
+
error?: string;
|
|
35
|
+
retryCount?: number;
|
|
36
|
+
}
|
|
37
|
+
export interface ProjectConfig {
|
|
38
|
+
projectId: string;
|
|
39
|
+
projectPath: string;
|
|
40
|
+
machineId: string;
|
|
41
|
+
relay: string;
|
|
42
|
+
token: string;
|
|
43
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sessioncast-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "SessionCast CLI - Control your agents from anywhere",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"sessioncast": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"dev": "ts-node src/index.ts",
|
|
12
|
+
"start": "node dist/index.js",
|
|
13
|
+
"prepublishOnly": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"sessioncast",
|
|
17
|
+
"tmux",
|
|
18
|
+
"cli",
|
|
19
|
+
"terminal",
|
|
20
|
+
"remote",
|
|
21
|
+
"agent",
|
|
22
|
+
"websocket"
|
|
23
|
+
],
|
|
24
|
+
"author": {
|
|
25
|
+
"name": "SessionCast",
|
|
26
|
+
"email": "devload@sessioncast.io"
|
|
27
|
+
},
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"homepage": "https://sessioncast.io",
|
|
30
|
+
"bugs": {
|
|
31
|
+
"email": "devload@sessioncast.io"
|
|
32
|
+
},
|
|
33
|
+
"type": "commonjs",
|
|
34
|
+
"files": [
|
|
35
|
+
"dist",
|
|
36
|
+
"README.md"
|
|
37
|
+
],
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"chalk": "^4.1.2",
|
|
40
|
+
"commander": "^12.1.0",
|
|
41
|
+
"conf": "^10.2.0",
|
|
42
|
+
"js-yaml": "^4.1.0",
|
|
43
|
+
"node-fetch": "^2.7.0",
|
|
44
|
+
"open": "^8.4.2",
|
|
45
|
+
"ora": "^5.4.1",
|
|
46
|
+
"ws": "^8.18.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/js-yaml": "^4.0.9",
|
|
50
|
+
"@types/node": "^22.10.2",
|
|
51
|
+
"@types/node-fetch": "^2.6.13",
|
|
52
|
+
"@types/ws": "^8.5.13",
|
|
53
|
+
"ts-node": "^10.9.2",
|
|
54
|
+
"typescript": "^5.7.2"
|
|
55
|
+
},
|
|
56
|
+
"engines": {
|
|
57
|
+
"node": ">=18"
|
|
58
|
+
}
|
|
59
|
+
}
|