sessioncast-cli 2.0.2 → 2.0.3
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/dist/agent/runner.js +23 -0
- package/dist/agent/session-handler.d.ts +1 -2
- package/dist/agent/session-handler.js +34 -79
- package/dist/agent/tmux-executor.d.ts +3 -33
- package/dist/agent/tmux-executor.js +3 -50
- package/dist/agent/tmux.d.ts +2 -6
- package/dist/agent/tmux.js +2 -9
- package/dist/agent/types.d.ts +0 -10
- package/dist/agent/websocket.d.ts +2 -21
- package/dist/agent/websocket.js +10 -46
- package/dist/commands/agent.js +3 -0
- package/dist/index.js +14 -0
- package/dist/sentry.d.ts +4 -0
- package/dist/sentry.js +87 -0
- package/package.json +2 -1
- 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/commands/autopilot.d.ts +0 -30
- package/dist/commands/autopilot.js +0 -262
- package/dist/commands/project.d.ts +0 -33
- package/dist/commands/project.js +0 -350
- 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/utils/fileUtils.d.ts +0 -28
- package/dist/utils/fileUtils.js +0 -159
package/dist/project/manager.js
DELETED
|
@@ -1,290 +0,0 @@
|
|
|
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.ProjectManager = void 0;
|
|
37
|
-
const fs = __importStar(require("fs"));
|
|
38
|
-
const path = __importStar(require("path"));
|
|
39
|
-
const yaml = __importStar(require("js-yaml"));
|
|
40
|
-
class ProjectManager {
|
|
41
|
-
constructor(projectPath, config = {}) {
|
|
42
|
-
this.projectPath = path.resolve(projectPath);
|
|
43
|
-
this.config = {
|
|
44
|
-
projectId: path.basename(this.projectPath),
|
|
45
|
-
projectPath: this.projectPath,
|
|
46
|
-
machineId: config.machineId || 'local',
|
|
47
|
-
relay: config.relay || '',
|
|
48
|
-
token: config.token || ''
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Initialize a new project with folder structure
|
|
53
|
-
*/
|
|
54
|
-
init(projectName) {
|
|
55
|
-
const name = projectName || path.basename(this.projectPath);
|
|
56
|
-
// Create folder structure
|
|
57
|
-
const folders = [
|
|
58
|
-
'mission',
|
|
59
|
-
'flow',
|
|
60
|
-
'shared',
|
|
61
|
-
'tools/mission-refiner',
|
|
62
|
-
'tools/pm-agent',
|
|
63
|
-
'work'
|
|
64
|
-
];
|
|
65
|
-
for (const folder of folders) {
|
|
66
|
-
const folderPath = path.join(this.projectPath, folder);
|
|
67
|
-
if (!fs.existsSync(folderPath)) {
|
|
68
|
-
fs.mkdirSync(folderPath, { recursive: true });
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
// Copy template CLAUDE.md files
|
|
72
|
-
this.copyTemplateClaude('mission-refiner');
|
|
73
|
-
this.copyTemplateClaude('pm-agent');
|
|
74
|
-
// Create initial files
|
|
75
|
-
this.createInitialFiles(name);
|
|
76
|
-
const project = {
|
|
77
|
-
name,
|
|
78
|
-
path: this.projectPath,
|
|
79
|
-
createdAt: new Date().toISOString(),
|
|
80
|
-
status: 'initializing'
|
|
81
|
-
};
|
|
82
|
-
// Save project config
|
|
83
|
-
this.saveProjectConfig(project);
|
|
84
|
-
return project;
|
|
85
|
-
}
|
|
86
|
-
copyTemplateClaude(agent) {
|
|
87
|
-
const templateDir = path.join(__dirname, '../../sample-project/tools', agent);
|
|
88
|
-
const targetDir = path.join(this.projectPath, 'tools', agent);
|
|
89
|
-
const claudePath = path.join(templateDir, 'CLAUDE.md');
|
|
90
|
-
if (fs.existsSync(claudePath)) {
|
|
91
|
-
fs.copyFileSync(claudePath, path.join(targetDir, 'CLAUDE.md'));
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
createInitialFiles(projectName) {
|
|
95
|
-
// Create mission/README.md
|
|
96
|
-
const missionReadme = `# Mission
|
|
97
|
-
|
|
98
|
-
Project: ${projectName}
|
|
99
|
-
|
|
100
|
-
## Current Mission
|
|
101
|
-
(미션이 정제되면 여기에 기록됩니다)
|
|
102
|
-
|
|
103
|
-
## History
|
|
104
|
-
(대화 히스토리가 여기에 기록됩니다)
|
|
105
|
-
`;
|
|
106
|
-
fs.writeFileSync(path.join(this.projectPath, 'mission', 'README.md'), missionReadme);
|
|
107
|
-
// Create shared/context.md
|
|
108
|
-
const sharedContext = `# Shared Context
|
|
109
|
-
|
|
110
|
-
이 파일은 에이전트 간 공유되는 컨텍스트를 저장합니다.
|
|
111
|
-
|
|
112
|
-
## Project Info
|
|
113
|
-
- Name: ${projectName}
|
|
114
|
-
- Created: ${new Date().toISOString()}
|
|
115
|
-
|
|
116
|
-
## Agent Outputs
|
|
117
|
-
(각 에이전트의 결과가 여기에 추가됩니다)
|
|
118
|
-
`;
|
|
119
|
-
fs.writeFileSync(path.join(this.projectPath, 'shared', 'context.md'), sharedContext);
|
|
120
|
-
// Create .gitignore
|
|
121
|
-
const gitignore = `# Node
|
|
122
|
-
node_modules/
|
|
123
|
-
|
|
124
|
-
# Temp files
|
|
125
|
-
*.log
|
|
126
|
-
.DS_Store
|
|
127
|
-
|
|
128
|
-
# Agent state
|
|
129
|
-
work/**/DONE
|
|
130
|
-
flow/status.yml
|
|
131
|
-
`;
|
|
132
|
-
fs.writeFileSync(path.join(this.projectPath, '.gitignore'), gitignore);
|
|
133
|
-
}
|
|
134
|
-
saveProjectConfig(project) {
|
|
135
|
-
const configPath = path.join(this.projectPath, '.sessioncast-project.yml');
|
|
136
|
-
fs.writeFileSync(configPath, yaml.dump(project));
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Load existing project
|
|
140
|
-
*/
|
|
141
|
-
load() {
|
|
142
|
-
const configPath = path.join(this.projectPath, '.sessioncast-project.yml');
|
|
143
|
-
if (!fs.existsSync(configPath)) {
|
|
144
|
-
return null;
|
|
145
|
-
}
|
|
146
|
-
return yaml.load(fs.readFileSync(configPath, 'utf-8'));
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Load workflow definition
|
|
150
|
-
*/
|
|
151
|
-
loadWorkflow() {
|
|
152
|
-
const workflowPath = path.join(this.projectPath, 'flow', 'workflow.yml');
|
|
153
|
-
if (!fs.existsSync(workflowPath)) {
|
|
154
|
-
return null;
|
|
155
|
-
}
|
|
156
|
-
return yaml.load(fs.readFileSync(workflowPath, 'utf-8'));
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Save workflow definition
|
|
160
|
-
*/
|
|
161
|
-
saveWorkflow(workflow) {
|
|
162
|
-
const workflowPath = path.join(this.projectPath, 'flow', 'workflow.yml');
|
|
163
|
-
fs.writeFileSync(workflowPath, yaml.dump(workflow));
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Load workflow status
|
|
167
|
-
*/
|
|
168
|
-
loadStatus() {
|
|
169
|
-
const statusPath = path.join(this.projectPath, 'flow', 'status.yml');
|
|
170
|
-
if (!fs.existsSync(statusPath)) {
|
|
171
|
-
return null;
|
|
172
|
-
}
|
|
173
|
-
return yaml.load(fs.readFileSync(statusPath, 'utf-8'));
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* Save workflow status
|
|
177
|
-
*/
|
|
178
|
-
saveStatus(status) {
|
|
179
|
-
const statusPath = path.join(this.projectPath, 'flow', 'status.yml');
|
|
180
|
-
fs.writeFileSync(statusPath, yaml.dump(status));
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* Update agent status
|
|
184
|
-
*/
|
|
185
|
-
updateAgentStatus(agentId, agentStatus) {
|
|
186
|
-
let status = this.loadStatus();
|
|
187
|
-
if (!status) {
|
|
188
|
-
const workflow = this.loadWorkflow();
|
|
189
|
-
status = {
|
|
190
|
-
workflow: workflow?.name || 'unknown',
|
|
191
|
-
startedAt: new Date().toISOString(),
|
|
192
|
-
status: 'running',
|
|
193
|
-
agents: {}
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
status.agents[agentId] = {
|
|
197
|
-
...status.agents[agentId],
|
|
198
|
-
...agentStatus
|
|
199
|
-
};
|
|
200
|
-
// Update overall status
|
|
201
|
-
const agentStatuses = Object.values(status.agents);
|
|
202
|
-
if (agentStatuses.every(a => a.status === 'completed')) {
|
|
203
|
-
status.status = 'completed';
|
|
204
|
-
}
|
|
205
|
-
else if (agentStatuses.some(a => a.status === 'failed')) {
|
|
206
|
-
status.status = 'failed';
|
|
207
|
-
}
|
|
208
|
-
else if (agentStatuses.some(a => a.status === 'running')) {
|
|
209
|
-
status.status = 'running';
|
|
210
|
-
}
|
|
211
|
-
this.saveStatus(status);
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* Create work agent folder with CLAUDE.md
|
|
215
|
-
*/
|
|
216
|
-
createWorkAgent(agentId, agentName, tasks) {
|
|
217
|
-
const agentPath = path.join(this.projectPath, 'work', agentId);
|
|
218
|
-
if (!fs.existsSync(agentPath)) {
|
|
219
|
-
fs.mkdirSync(agentPath, { recursive: true });
|
|
220
|
-
}
|
|
221
|
-
const claudeContent = `# ${agentName}
|
|
222
|
-
|
|
223
|
-
## Role
|
|
224
|
-
${agentName} 작업을 수행합니다.
|
|
225
|
-
|
|
226
|
-
## Tasks
|
|
227
|
-
${tasks.map(t => `- ${t}`).join('\n')}
|
|
228
|
-
|
|
229
|
-
## Context
|
|
230
|
-
- 프로젝트 경로: ${this.projectPath}
|
|
231
|
-
- 공유 컨텍스트: ../shared/context.md
|
|
232
|
-
|
|
233
|
-
## Completion
|
|
234
|
-
작업 완료 시:
|
|
235
|
-
1. 결과를 output.md에 기록
|
|
236
|
-
2. DONE 파일 생성: \`touch DONE\`
|
|
237
|
-
|
|
238
|
-
## Important
|
|
239
|
-
- 모든 작업은 이 폴더 내에서 수행
|
|
240
|
-
- 다른 에이전트의 결과는 ../shared/context.md 참조
|
|
241
|
-
- 에러 발생 시 error.log에 기록
|
|
242
|
-
`;
|
|
243
|
-
fs.writeFileSync(path.join(agentPath, 'CLAUDE.md'), claudeContent);
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* Get tmux session name for an agent
|
|
247
|
-
* Note: tmux doesn't allow colons in session names, so we use underscores
|
|
248
|
-
*/
|
|
249
|
-
getTmuxSessionName(agentId) {
|
|
250
|
-
const sanitizedProjectId = this.config.projectId.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
251
|
-
return `proj_${sanitizedProjectId}_${agentId}`;
|
|
252
|
-
}
|
|
253
|
-
/**
|
|
254
|
-
* Check if agent is completed (DONE file exists)
|
|
255
|
-
*/
|
|
256
|
-
isAgentCompleted(agentId) {
|
|
257
|
-
const donePath = path.join(this.projectPath, 'work', agentId, 'DONE');
|
|
258
|
-
return fs.existsSync(donePath);
|
|
259
|
-
}
|
|
260
|
-
/**
|
|
261
|
-
* Get agent output
|
|
262
|
-
*/
|
|
263
|
-
getAgentOutput(agentId) {
|
|
264
|
-
const outputPath = path.join(this.projectPath, 'work', agentId, 'output.md');
|
|
265
|
-
if (fs.existsSync(outputPath)) {
|
|
266
|
-
return fs.readFileSync(outputPath, 'utf-8');
|
|
267
|
-
}
|
|
268
|
-
return null;
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
* Append to shared context
|
|
272
|
-
*/
|
|
273
|
-
appendToContext(content) {
|
|
274
|
-
const contextPath = path.join(this.projectPath, 'shared', 'context.md');
|
|
275
|
-
fs.appendFileSync(contextPath, '\n' + content);
|
|
276
|
-
}
|
|
277
|
-
/**
|
|
278
|
-
* Get project path
|
|
279
|
-
*/
|
|
280
|
-
getProjectPath() {
|
|
281
|
-
return this.projectPath;
|
|
282
|
-
}
|
|
283
|
-
/**
|
|
284
|
-
* Get project ID
|
|
285
|
-
*/
|
|
286
|
-
getProjectId() {
|
|
287
|
-
return this.config.projectId;
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
exports.ProjectManager = ProjectManager;
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { EventEmitter } from 'events';
|
|
2
|
-
import { AgentInfo } from './types';
|
|
3
|
-
interface ProjectRelayClientOptions {
|
|
4
|
-
relayUrl: string;
|
|
5
|
-
token: string;
|
|
6
|
-
projectId: string;
|
|
7
|
-
projectName: string;
|
|
8
|
-
projectPath: string;
|
|
9
|
-
autoReconnect?: boolean;
|
|
10
|
-
}
|
|
11
|
-
interface SourceInfo {
|
|
12
|
-
folder: string;
|
|
13
|
-
fileCount: number;
|
|
14
|
-
}
|
|
15
|
-
export declare class ProjectRelayClient extends EventEmitter {
|
|
16
|
-
private ws;
|
|
17
|
-
private options;
|
|
18
|
-
private isConnected;
|
|
19
|
-
private reconnectAttempts;
|
|
20
|
-
private maxReconnectAttempts;
|
|
21
|
-
private reconnectTimer;
|
|
22
|
-
private destroyed;
|
|
23
|
-
constructor(options: ProjectRelayClientOptions);
|
|
24
|
-
connect(): void;
|
|
25
|
-
private scheduleReconnect;
|
|
26
|
-
private registerProject;
|
|
27
|
-
private handleMessage;
|
|
28
|
-
private send;
|
|
29
|
-
updateStatus(status: string, meta?: Record<string, any>): boolean;
|
|
30
|
-
updateSources(sources: SourceInfo[]): boolean;
|
|
31
|
-
updateAgents(agents: AgentInfo[]): boolean;
|
|
32
|
-
sendSourceAdded(folder: string, fileCount: number, files?: string[]): boolean;
|
|
33
|
-
sendAnalysisResult(viewerSessionId: string, steps: any[], decisions: any[]): boolean;
|
|
34
|
-
getConnected(): boolean;
|
|
35
|
-
destroy(): void;
|
|
36
|
-
}
|
|
37
|
-
export {};
|
|
@@ -1,204 +0,0 @@
|
|
|
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
|
-
class ProjectRelayClient extends events_1.EventEmitter {
|
|
10
|
-
constructor(options) {
|
|
11
|
-
super();
|
|
12
|
-
this.ws = null;
|
|
13
|
-
this.isConnected = false;
|
|
14
|
-
this.reconnectAttempts = 0;
|
|
15
|
-
this.maxReconnectAttempts = 5;
|
|
16
|
-
this.reconnectTimer = null;
|
|
17
|
-
this.destroyed = false;
|
|
18
|
-
this.options = options;
|
|
19
|
-
}
|
|
20
|
-
connect() {
|
|
21
|
-
if (this.destroyed)
|
|
22
|
-
return;
|
|
23
|
-
try {
|
|
24
|
-
// Add token to URL for authentication
|
|
25
|
-
const url = new URL(this.options.relayUrl);
|
|
26
|
-
url.searchParams.set('token', this.options.token);
|
|
27
|
-
this.ws = new ws_1.default(url.toString());
|
|
28
|
-
this.ws.on('open', () => {
|
|
29
|
-
this.isConnected = true;
|
|
30
|
-
this.reconnectAttempts = 0;
|
|
31
|
-
console.log('[ProjectRelay] Connected to relay');
|
|
32
|
-
this.registerProject();
|
|
33
|
-
this.emit('connected');
|
|
34
|
-
});
|
|
35
|
-
this.ws.on('message', (data) => {
|
|
36
|
-
try {
|
|
37
|
-
const message = JSON.parse(data.toString());
|
|
38
|
-
this.handleMessage(message);
|
|
39
|
-
}
|
|
40
|
-
catch (e) {
|
|
41
|
-
console.error('[ProjectRelay] Failed to parse message:', e);
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
this.ws.on('close', (code, reason) => {
|
|
45
|
-
this.isConnected = false;
|
|
46
|
-
console.log(`[ProjectRelay] Disconnected: code=${code}, reason=${reason.toString()}`);
|
|
47
|
-
this.emit('disconnected', { code, reason: reason.toString() });
|
|
48
|
-
if (this.options.autoReconnect !== false && !this.destroyed) {
|
|
49
|
-
this.scheduleReconnect();
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
this.ws.on('error', (error) => {
|
|
53
|
-
console.error('[ProjectRelay] WebSocket error:', error.message);
|
|
54
|
-
this.emit('error', error);
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
catch (error) {
|
|
58
|
-
console.error('[ProjectRelay] Connection error:', error);
|
|
59
|
-
this.emit('error', error);
|
|
60
|
-
if (this.options.autoReconnect !== false && !this.destroyed) {
|
|
61
|
-
this.scheduleReconnect();
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
scheduleReconnect() {
|
|
66
|
-
if (this.destroyed)
|
|
67
|
-
return;
|
|
68
|
-
this.reconnectAttempts++;
|
|
69
|
-
if (this.reconnectAttempts > this.maxReconnectAttempts) {
|
|
70
|
-
console.log('[ProjectRelay] Max reconnect attempts reached');
|
|
71
|
-
this.emit('maxReconnectAttempts');
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
const delay = Math.min(2000 * Math.pow(2, this.reconnectAttempts - 1), 30000);
|
|
75
|
-
console.log(`[ProjectRelay] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);
|
|
76
|
-
this.reconnectTimer = setTimeout(() => {
|
|
77
|
-
if (!this.isConnected && !this.destroyed) {
|
|
78
|
-
this.connect();
|
|
79
|
-
}
|
|
80
|
-
}, delay);
|
|
81
|
-
}
|
|
82
|
-
registerProject() {
|
|
83
|
-
this.send({
|
|
84
|
-
type: 'registerProject',
|
|
85
|
-
meta: {
|
|
86
|
-
projectId: this.options.projectId,
|
|
87
|
-
name: this.options.projectName,
|
|
88
|
-
path: this.options.projectPath,
|
|
89
|
-
token: this.options.token,
|
|
90
|
-
status: 'pending',
|
|
91
|
-
createdAt: new Date().toISOString()
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
handleMessage(message) {
|
|
96
|
-
switch (message.type) {
|
|
97
|
-
case 'addSource':
|
|
98
|
-
// Web UI requesting to add a source
|
|
99
|
-
this.emit('addSource', message.meta);
|
|
100
|
-
break;
|
|
101
|
-
case 'analyzeMission':
|
|
102
|
-
// Web UI requesting mission analysis
|
|
103
|
-
this.emit('analyzeMission', message.meta);
|
|
104
|
-
break;
|
|
105
|
-
case 'startWorkflow':
|
|
106
|
-
// Web UI requesting to start workflow
|
|
107
|
-
this.emit('startWorkflow', message.meta);
|
|
108
|
-
break;
|
|
109
|
-
case 'projectList':
|
|
110
|
-
// Server sent project list (acknowledgment)
|
|
111
|
-
console.log('[ProjectRelay] Project registered successfully');
|
|
112
|
-
break;
|
|
113
|
-
case 'error':
|
|
114
|
-
console.error('[ProjectRelay] Server error:', message.meta);
|
|
115
|
-
this.emit('serverError', message.meta);
|
|
116
|
-
break;
|
|
117
|
-
default:
|
|
118
|
-
console.log('[ProjectRelay] Unknown message type:', message.type);
|
|
119
|
-
this.emit('message', message);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
send(message) {
|
|
123
|
-
if (!this.ws || this.ws.readyState !== ws_1.default.OPEN) {
|
|
124
|
-
return false;
|
|
125
|
-
}
|
|
126
|
-
try {
|
|
127
|
-
this.ws.send(JSON.stringify(message));
|
|
128
|
-
return true;
|
|
129
|
-
}
|
|
130
|
-
catch {
|
|
131
|
-
return false;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
// Update project status
|
|
135
|
-
updateStatus(status, meta) {
|
|
136
|
-
return this.send({
|
|
137
|
-
type: 'projectStatus',
|
|
138
|
-
meta: {
|
|
139
|
-
projectId: this.options.projectId,
|
|
140
|
-
status,
|
|
141
|
-
...meta
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
// Update sources list
|
|
146
|
-
updateSources(sources) {
|
|
147
|
-
return this.send({
|
|
148
|
-
type: 'projectStatus',
|
|
149
|
-
meta: {
|
|
150
|
-
projectId: this.options.projectId,
|
|
151
|
-
sources: JSON.stringify(sources)
|
|
152
|
-
}
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
// Update agents list
|
|
156
|
-
updateAgents(agents) {
|
|
157
|
-
return this.send({
|
|
158
|
-
type: 'projectStatus',
|
|
159
|
-
meta: {
|
|
160
|
-
projectId: this.options.projectId,
|
|
161
|
-
agents: JSON.stringify(agents)
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
// Send source added result back to web
|
|
166
|
-
sendSourceAdded(folder, fileCount, files) {
|
|
167
|
-
return this.send({
|
|
168
|
-
type: 'sourceAdded',
|
|
169
|
-
meta: {
|
|
170
|
-
projectId: this.options.projectId,
|
|
171
|
-
folder,
|
|
172
|
-
fileCount: String(fileCount)
|
|
173
|
-
},
|
|
174
|
-
payload: files ? files.join('\n') : ''
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
// Send analysis result back to web
|
|
178
|
-
sendAnalysisResult(viewerSessionId, steps, decisions) {
|
|
179
|
-
return this.send({
|
|
180
|
-
type: 'missionAnalysis',
|
|
181
|
-
meta: {
|
|
182
|
-
projectId: this.options.projectId,
|
|
183
|
-
viewerSessionId
|
|
184
|
-
},
|
|
185
|
-
steps,
|
|
186
|
-
decisions
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
getConnected() {
|
|
190
|
-
return this.isConnected;
|
|
191
|
-
}
|
|
192
|
-
destroy() {
|
|
193
|
-
this.destroyed = true;
|
|
194
|
-
if (this.reconnectTimer) {
|
|
195
|
-
clearTimeout(this.reconnectTimer);
|
|
196
|
-
this.reconnectTimer = null;
|
|
197
|
-
}
|
|
198
|
-
if (this.ws) {
|
|
199
|
-
this.ws.close();
|
|
200
|
-
this.ws = null;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
exports.ProjectRelayClient = ProjectRelayClient;
|
package/dist/project/types.d.ts
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
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
|
-
}
|
|
44
|
-
export interface AgentInfo {
|
|
45
|
-
id: string;
|
|
46
|
-
name: string;
|
|
47
|
-
status: 'pending' | 'running' | 'completed' | 'failed';
|
|
48
|
-
}
|
package/dist/project/types.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sanitize filename to prevent path traversal attacks
|
|
3
|
-
*/
|
|
4
|
-
export declare function sanitizeFilename(filename: string): string;
|
|
5
|
-
/**
|
|
6
|
-
* Get the working directory for file uploads
|
|
7
|
-
* Priority: SESSIONCAST_UPLOAD_DIR env var > current working directory
|
|
8
|
-
*/
|
|
9
|
-
export declare function getUploadDirectory(): string;
|
|
10
|
-
/**
|
|
11
|
-
* Handle file upload chunk
|
|
12
|
-
* Returns upload result when all chunks are received, null otherwise
|
|
13
|
-
*/
|
|
14
|
-
export declare function handleUploadChunk(sessionId: string, meta: {
|
|
15
|
-
filename: string;
|
|
16
|
-
size: string;
|
|
17
|
-
mimeType: string;
|
|
18
|
-
chunkIndex: string;
|
|
19
|
-
totalChunks: string;
|
|
20
|
-
}, payload: string): Promise<{
|
|
21
|
-
success: boolean;
|
|
22
|
-
path?: string;
|
|
23
|
-
error?: string;
|
|
24
|
-
} | null>;
|
|
25
|
-
/**
|
|
26
|
-
* Cleanup stale uploads periodically
|
|
27
|
-
*/
|
|
28
|
-
export declare function cleanupStaleUploads(): void;
|