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.
Files changed (45) hide show
  1. package/dist/agent/runner.js +23 -0
  2. package/dist/agent/session-handler.d.ts +1 -2
  3. package/dist/agent/session-handler.js +34 -79
  4. package/dist/agent/tmux-executor.d.ts +3 -33
  5. package/dist/agent/tmux-executor.js +3 -50
  6. package/dist/agent/tmux.d.ts +2 -6
  7. package/dist/agent/tmux.js +2 -9
  8. package/dist/agent/types.d.ts +0 -10
  9. package/dist/agent/websocket.d.ts +2 -21
  10. package/dist/agent/websocket.js +10 -46
  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
@@ -1,232 +0,0 @@
1
- "use strict";
2
- /**
3
- * MissionAnalyzer - LLM-based analysis of user prompts
4
- * Breaks down a single prompt into structured workflow steps
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.analyzeMission = analyzeMission;
8
- exports.analyzeQuick = analyzeQuick;
9
- /**
10
- * Analyze user prompt and generate mission breakdown
11
- */
12
- async function analyzeMission(prompt, context, llmClient) {
13
- const systemPrompt = buildSystemPrompt(context);
14
- const userPrompt = buildUserPrompt(prompt, context);
15
- try {
16
- const response = await llmClient.chat([
17
- { role: 'system', content: systemPrompt },
18
- { role: 'user', content: userPrompt }
19
- ]);
20
- return parseAnalysisResponse(response, prompt);
21
- }
22
- catch (error) {
23
- // Fallback to simple analysis if LLM fails
24
- return createFallbackAnalysis(prompt, context);
25
- }
26
- }
27
- /**
28
- * Build system prompt for mission analysis
29
- */
30
- function buildSystemPrompt(context) {
31
- return `You are a software development task analyzer for SessionCast.
32
- Your job is to analyze user requests and break them down into executable steps.
33
-
34
- Project Information:
35
- - Type: ${context.projectType}
36
- - Name: ${context.projectName}
37
- - Main Language: ${getMainLanguage(context.projectType)}
38
-
39
- Rules:
40
- 1. Break down the task into clear, independent steps
41
- 2. Each step should be achievable by a single AI agent
42
- 3. Consider dependencies between steps
43
- 4. Estimate complexity based on the scope of changes
44
- 5. Identify required agent types: frontend, backend, fullstack, mobile, infra, test
45
-
46
- Response Format (JSON):
47
- {
48
- "mission": "Brief summary of the mission",
49
- "complexity": "simple|medium|complex",
50
- "steps": [
51
- {
52
- "name": "Step name",
53
- "description": "What this step accomplishes",
54
- "type": "frontend|backend|fullstack|mobile|infra|test",
55
- "prompt": "Detailed prompt for the AI agent",
56
- "dependsOn": ["previous step names if any"]
57
- }
58
- ],
59
- "requiredAgents": ["agent types needed"],
60
- "estimatedFiles": ["likely files to be modified"]
61
- }`;
62
- }
63
- /**
64
- * Build user prompt with context
65
- */
66
- function buildUserPrompt(prompt, context) {
67
- let userContent = `Analyze this task and break it down into executable steps:
68
-
69
- USER REQUEST: ${prompt}
70
-
71
- PROJECT STRUCTURE:
72
- ${context.projectStructure}
73
-
74
- SOURCE FILES:
75
- ${context.sources.map(s => `- ${s.relativePath} (${s.type})`).join('\n')}`;
76
- if (context.keyFilesContent) {
77
- userContent += `\n\nKEY FILES CONTENT:\n${context.keyFilesContent}`;
78
- }
79
- return userContent;
80
- }
81
- /**
82
- * Parse LLM response into MissionAnalysis
83
- */
84
- function parseAnalysisResponse(response, originalPrompt) {
85
- try {
86
- // Extract JSON from response
87
- const jsonMatch = response.match(/\{[\s\S]*\}/);
88
- if (!jsonMatch) {
89
- throw new Error('No JSON found in response');
90
- }
91
- const parsed = JSON.parse(jsonMatch[0]);
92
- // Validate and normalize
93
- const analysis = {
94
- mission: parsed.mission || originalPrompt,
95
- complexity: validateComplexity(parsed.complexity),
96
- steps: normalizeSteps(parsed.steps || []),
97
- requiredAgents: parsed.requiredAgents || [],
98
- estimatedFiles: parsed.estimatedFiles || []
99
- };
100
- // Ensure at least one step
101
- if (analysis.steps.length === 0) {
102
- analysis.steps = [{
103
- name: 'Execute task',
104
- description: originalPrompt,
105
- type: 'fullstack',
106
- prompt: originalPrompt
107
- }];
108
- }
109
- return analysis;
110
- }
111
- catch (error) {
112
- // Return basic analysis if parsing fails
113
- return {
114
- mission: originalPrompt,
115
- complexity: 'simple',
116
- steps: [{
117
- name: 'Execute task',
118
- description: originalPrompt,
119
- type: 'fullstack',
120
- prompt: originalPrompt
121
- }],
122
- requiredAgents: ['fullstack'],
123
- estimatedFiles: []
124
- };
125
- }
126
- }
127
- /**
128
- * Validate complexity value
129
- */
130
- function validateComplexity(value) {
131
- const valid = ['simple', 'medium', 'complex'];
132
- return valid.includes(value) ? value : 'simple';
133
- }
134
- /**
135
- * Normalize steps array
136
- */
137
- function normalizeSteps(steps) {
138
- return steps.map((step, index) => ({
139
- name: step.name || `Step ${index + 1}`,
140
- description: step.description || '',
141
- type: validateStepType(step.type),
142
- prompt: step.prompt || step.description || '',
143
- dependsOn: Array.isArray(step.dependsOn) ? step.dependsOn : undefined
144
- }));
145
- }
146
- /**
147
- * Validate step type
148
- */
149
- function validateStepType(value) {
150
- const valid = ['frontend', 'backend', 'fullstack', 'mobile', 'infra', 'test'];
151
- return valid.includes(value) ? value : 'fullstack';
152
- }
153
- /**
154
- * Get main language for project type
155
- */
156
- function getMainLanguage(projectType) {
157
- const map = {
158
- android: 'Kotlin/Java',
159
- ios: 'Swift',
160
- react: 'TypeScript/React',
161
- next: 'TypeScript/Next.js',
162
- vue: 'TypeScript/Vue',
163
- node: 'JavaScript/Node.js',
164
- python: 'Python',
165
- spring: 'Java/Spring',
166
- go: 'Go',
167
- rust: 'Rust',
168
- unknown: 'Unknown'
169
- };
170
- return map[projectType];
171
- }
172
- /**
173
- * Create fallback analysis without LLM
174
- */
175
- function createFallbackAnalysis(prompt, context) {
176
- // Simple heuristic-based analysis
177
- const promptLower = prompt.toLowerCase();
178
- let type = 'fullstack';
179
- let complexity = 'simple';
180
- // Detect type from keywords
181
- if (promptLower.includes('ui') || promptLower.includes('화면') || promptLower.includes('button') || promptLower.includes('버튼')) {
182
- type = 'frontend';
183
- }
184
- else if (promptLower.includes('api') || promptLower.includes('database') || promptLower.includes('db') || promptLower.includes('서버')) {
185
- type = 'backend';
186
- }
187
- else if (promptLower.includes('test') || promptLower.includes('테스트')) {
188
- type = 'test';
189
- }
190
- else if (promptLower.includes('deploy') || promptLower.includes('docker') || promptLower.includes('배포')) {
191
- type = 'infra';
192
- }
193
- // Mobile detection based on project type
194
- if (context.projectType === 'android' || context.projectType === 'ios') {
195
- type = 'mobile';
196
- }
197
- // Detect complexity from keywords
198
- if (promptLower.includes('refactor') ||
199
- promptLower.includes('리팩토링') ||
200
- promptLower.includes('architecture') ||
201
- promptLower.includes('아키텍처') ||
202
- promptLower.includes('전체') ||
203
- promptLower.includes('모든')) {
204
- complexity = 'complex';
205
- }
206
- else if (promptLower.includes('add') ||
207
- promptLower.includes('추가') ||
208
- promptLower.includes('create') ||
209
- promptLower.includes('생성') ||
210
- promptLower.includes('implement') ||
211
- promptLower.includes('구현')) {
212
- complexity = 'medium';
213
- }
214
- return {
215
- mission: prompt,
216
- complexity,
217
- steps: [{
218
- name: 'Execute task',
219
- description: prompt,
220
- type,
221
- prompt
222
- }],
223
- requiredAgents: [type === 'mobile' ? 'mobile' : type],
224
- estimatedFiles: []
225
- };
226
- }
227
- /**
228
- * Analyze mission without LLM (for quick mode or when LLM is unavailable)
229
- */
230
- function analyzeQuick(prompt, context) {
231
- return createFallbackAnalysis(prompt, context);
232
- }
@@ -1,12 +0,0 @@
1
- /**
2
- * ProjectDetector - Auto-detect project type from directory
3
- */
4
- import { ProjectDetectionResult } from './types';
5
- /**
6
- * Detect project type from directory
7
- */
8
- export declare function detectProjectType(dir: string): Promise<ProjectDetectionResult>;
9
- /**
10
- * Get a summary of project structure for LLM context
11
- */
12
- export declare function getProjectStructure(dir: string, maxDepth?: number): string;
@@ -1,326 +0,0 @@
1
- "use strict";
2
- /**
3
- * ProjectDetector - Auto-detect project type from directory
4
- */
5
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
- if (k2 === undefined) k2 = k;
7
- var desc = Object.getOwnPropertyDescriptor(m, k);
8
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
- desc = { enumerable: true, get: function() { return m[k]; } };
10
- }
11
- Object.defineProperty(o, k2, desc);
12
- }) : (function(o, m, k, k2) {
13
- if (k2 === undefined) k2 = k;
14
- o[k2] = m[k];
15
- }));
16
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
- Object.defineProperty(o, "default", { enumerable: true, value: v });
18
- }) : function(o, v) {
19
- o["default"] = v;
20
- });
21
- var __importStar = (this && this.__importStar) || (function () {
22
- var ownKeys = function(o) {
23
- ownKeys = Object.getOwnPropertyNames || function (o) {
24
- var ar = [];
25
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
- return ar;
27
- };
28
- return ownKeys(o);
29
- };
30
- return function (mod) {
31
- if (mod && mod.__esModule) return mod;
32
- var result = {};
33
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
- __setModuleDefault(result, mod);
35
- return result;
36
- };
37
- })();
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.detectProjectType = detectProjectType;
40
- exports.getProjectStructure = getProjectStructure;
41
- const fs = __importStar(require("fs"));
42
- const path = __importStar(require("path"));
43
- const PROJECT_SIGNATURES = {
44
- android: {
45
- files: ['build.gradle', 'app/build.gradle', 'settings.gradle'],
46
- contentPatterns: [
47
- { file: 'build.gradle', pattern: /android\s*\{/ },
48
- { file: 'app/build.gradle', pattern: /android\s*\{/ }
49
- ],
50
- weight: 10
51
- },
52
- ios: {
53
- files: ['*.xcodeproj', '*.xcworkspace', 'Podfile', 'Package.swift'],
54
- weight: 10
55
- },
56
- react: {
57
- files: ['package.json'],
58
- contentPatterns: [
59
- { file: 'package.json', pattern: /"react":\s*"/ }
60
- ],
61
- weight: 8
62
- },
63
- next: {
64
- files: ['next.config.js', 'next.config.mjs', 'next.config.ts'],
65
- weight: 9
66
- },
67
- vue: {
68
- files: ['vue.config.js', 'vite.config.ts', 'vite.config.js'],
69
- contentPatterns: [
70
- { file: 'package.json', pattern: /"vue":\s*"/ }
71
- ],
72
- weight: 8
73
- },
74
- node: {
75
- files: ['package.json'],
76
- weight: 5
77
- },
78
- python: {
79
- files: ['requirements.txt', 'pyproject.toml', 'setup.py', 'Pipfile'],
80
- weight: 7
81
- },
82
- spring: {
83
- files: ['pom.xml', 'build.gradle'],
84
- contentPatterns: [
85
- { file: 'pom.xml', pattern: /spring-boot/ },
86
- { file: 'build.gradle', pattern: /spring-boot/ }
87
- ],
88
- weight: 9
89
- },
90
- go: {
91
- files: ['go.mod', 'go.sum'],
92
- weight: 8
93
- },
94
- rust: {
95
- files: ['Cargo.toml', 'Cargo.lock'],
96
- weight: 8
97
- },
98
- unknown: {
99
- files: [],
100
- weight: 0
101
- }
102
- };
103
- const LANGUAGE_MAP = {
104
- android: 'kotlin',
105
- ios: 'swift',
106
- react: 'typescript',
107
- next: 'typescript',
108
- vue: 'typescript',
109
- node: 'javascript',
110
- python: 'python',
111
- spring: 'java',
112
- go: 'go',
113
- rust: 'rust'
114
- };
115
- /**
116
- * Detect project type from directory
117
- */
118
- async function detectProjectType(dir) {
119
- const scores = new Map();
120
- const foundConfigFiles = [];
121
- // Initialize scores
122
- for (const type of Object.keys(PROJECT_SIGNATURES)) {
123
- scores.set(type, 0);
124
- }
125
- // Check file signatures
126
- for (const [type, signature] of Object.entries(PROJECT_SIGNATURES)) {
127
- for (const filePattern of signature.files) {
128
- const found = await findFiles(dir, filePattern);
129
- if (found.length > 0) {
130
- scores.set(type, (scores.get(type) || 0) + signature.weight);
131
- foundConfigFiles.push(...found);
132
- }
133
- }
134
- // Check content patterns
135
- if (signature.contentPatterns) {
136
- for (const { file, pattern } of signature.contentPatterns) {
137
- const filePath = path.join(dir, file);
138
- if (fs.existsSync(filePath)) {
139
- try {
140
- const content = fs.readFileSync(filePath, 'utf-8');
141
- if (pattern.test(content)) {
142
- scores.set(type, (scores.get(type) || 0) + 5);
143
- }
144
- }
145
- catch {
146
- // Ignore read errors
147
- }
148
- }
149
- }
150
- }
151
- }
152
- // Find the best match
153
- let bestType = 'unknown';
154
- let bestScore = 0;
155
- let totalScore = 0;
156
- for (const [type, score] of scores.entries()) {
157
- totalScore += score;
158
- if (score > bestScore) {
159
- bestScore = score;
160
- bestType = type;
161
- }
162
- }
163
- // Calculate confidence
164
- const confidence = totalScore > 0 ? Math.min(bestScore / (totalScore * 0.5), 1) : 0;
165
- // Get project name
166
- const projectName = await getProjectName(dir, bestType);
167
- return {
168
- type: bestType,
169
- name: projectName,
170
- confidence,
171
- configFiles: [...new Set(foundConfigFiles)],
172
- mainLanguage: LANGUAGE_MAP[bestType]
173
- };
174
- }
175
- /**
176
- * Find files matching pattern in directory
177
- */
178
- async function findFiles(dir, pattern) {
179
- const results = [];
180
- try {
181
- if (pattern.includes('*')) {
182
- // Glob pattern
183
- const ext = pattern.replace('*', '');
184
- const entries = fs.readdirSync(dir);
185
- for (const entry of entries) {
186
- if (entry.endsWith(ext)) {
187
- results.push(entry);
188
- }
189
- }
190
- }
191
- else if (pattern.includes('/')) {
192
- // Path pattern
193
- const fullPath = path.join(dir, pattern);
194
- if (fs.existsSync(fullPath)) {
195
- results.push(pattern);
196
- }
197
- }
198
- else {
199
- // Simple filename
200
- const fullPath = path.join(dir, pattern);
201
- if (fs.existsSync(fullPath)) {
202
- results.push(pattern);
203
- }
204
- }
205
- }
206
- catch {
207
- // Ignore errors
208
- }
209
- return results;
210
- }
211
- /**
212
- * Get project name from config files
213
- */
214
- async function getProjectName(dir, type) {
215
- // Try package.json
216
- const packageJsonPath = path.join(dir, 'package.json');
217
- if (fs.existsSync(packageJsonPath)) {
218
- try {
219
- const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
220
- if (pkg.name)
221
- return pkg.name;
222
- }
223
- catch {
224
- // Ignore
225
- }
226
- }
227
- // Try settings.gradle (Android)
228
- const settingsGradlePath = path.join(dir, 'settings.gradle');
229
- if (fs.existsSync(settingsGradlePath)) {
230
- try {
231
- const content = fs.readFileSync(settingsGradlePath, 'utf-8');
232
- const match = content.match(/rootProject\.name\s*=\s*['"](.+)['"]/);
233
- if (match)
234
- return match[1];
235
- }
236
- catch {
237
- // Ignore
238
- }
239
- }
240
- // Try pom.xml (Maven)
241
- const pomPath = path.join(dir, 'pom.xml');
242
- if (fs.existsSync(pomPath)) {
243
- try {
244
- const content = fs.readFileSync(pomPath, 'utf-8');
245
- const match = content.match(/<artifactId>(.+?)<\/artifactId>/);
246
- if (match)
247
- return match[1];
248
- }
249
- catch {
250
- // Ignore
251
- }
252
- }
253
- // Try Cargo.toml (Rust)
254
- const cargoPath = path.join(dir, 'Cargo.toml');
255
- if (fs.existsSync(cargoPath)) {
256
- try {
257
- const content = fs.readFileSync(cargoPath, 'utf-8');
258
- const match = content.match(/name\s*=\s*"(.+?)"/);
259
- if (match)
260
- return match[1];
261
- }
262
- catch {
263
- // Ignore
264
- }
265
- }
266
- // Try go.mod (Go)
267
- const goModPath = path.join(dir, 'go.mod');
268
- if (fs.existsSync(goModPath)) {
269
- try {
270
- const content = fs.readFileSync(goModPath, 'utf-8');
271
- const match = content.match(/module\s+(.+)/);
272
- if (match) {
273
- const parts = match[1].split('/');
274
- return parts[parts.length - 1];
275
- }
276
- }
277
- catch {
278
- // Ignore
279
- }
280
- }
281
- // Fallback to directory name
282
- return path.basename(dir);
283
- }
284
- /**
285
- * Get a summary of project structure for LLM context
286
- */
287
- function getProjectStructure(dir, maxDepth = 3) {
288
- const lines = [];
289
- function walk(currentDir, prefix, depth) {
290
- if (depth > maxDepth)
291
- return;
292
- try {
293
- const entries = fs.readdirSync(currentDir, { withFileTypes: true });
294
- // Sort: directories first, then files
295
- entries.sort((a, b) => {
296
- if (a.isDirectory() && !b.isDirectory())
297
- return -1;
298
- if (!a.isDirectory() && b.isDirectory())
299
- return 1;
300
- return a.name.localeCompare(b.name);
301
- });
302
- // Filter out common non-essential directories
303
- const filtered = entries.filter(e => !['node_modules', '.git', '.gradle', 'build', 'dist', '__pycache__',
304
- '.idea', '.vscode', 'target', '.next', 'venv', 'env'].includes(e.name));
305
- for (let i = 0; i < filtered.length; i++) {
306
- const entry = filtered[i];
307
- const isLast = i === filtered.length - 1;
308
- const connector = isLast ? '└── ' : '├── ';
309
- const newPrefix = prefix + (isLast ? ' ' : '│ ');
310
- if (entry.isDirectory()) {
311
- lines.push(`${prefix}${connector}${entry.name}/`);
312
- walk(path.join(currentDir, entry.name), newPrefix, depth + 1);
313
- }
314
- else {
315
- lines.push(`${prefix}${connector}${entry.name}`);
316
- }
317
- }
318
- }
319
- catch {
320
- // Ignore permission errors
321
- }
322
- }
323
- lines.push(path.basename(dir) + '/');
324
- walk(dir, '', 1);
325
- return lines.slice(0, 100).join('\n'); // Limit to 100 lines
326
- }
@@ -1,26 +0,0 @@
1
- /**
2
- * SourceScanner - Scan and collect relevant source files for context
3
- */
4
- import { SourceInfo, ProjectType } from './types';
5
- interface ScanOptions {
6
- maxFiles?: number;
7
- maxFileSize?: number;
8
- includeTests?: boolean;
9
- }
10
- /**
11
- * Scan directory for source files
12
- */
13
- export declare function scanSources(dir: string, projectType: ProjectType, options?: ScanOptions): Promise<SourceInfo[]>;
14
- /**
15
- * Read source file content (for LLM context)
16
- */
17
- export declare function readSourceContent(source: SourceInfo): string | null;
18
- /**
19
- * Get condensed context for LLM (file list with sizes)
20
- */
21
- export declare function getSourcesSummary(sources: SourceInfo[]): string;
22
- /**
23
- * Get key files content for deep analysis
24
- */
25
- export declare function getKeyFilesContent(sources: SourceInfo[], maxTotalSize?: number): string;
26
- export {};