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.
Files changed (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +137 -0
  3. package/dist/agent/api-client.d.ts +27 -0
  4. package/dist/agent/api-client.js +295 -0
  5. package/dist/agent/exec-service.d.ts +6 -0
  6. package/dist/agent/exec-service.js +126 -0
  7. package/dist/agent/index.d.ts +8 -0
  8. package/dist/agent/index.js +24 -0
  9. package/dist/agent/llm-service.d.ts +9 -0
  10. package/dist/agent/llm-service.js +156 -0
  11. package/dist/agent/runner.d.ts +16 -0
  12. package/dist/agent/runner.js +187 -0
  13. package/dist/agent/session-handler.d.ts +28 -0
  14. package/dist/agent/session-handler.js +184 -0
  15. package/dist/agent/tmux.d.ts +29 -0
  16. package/dist/agent/tmux.js +157 -0
  17. package/dist/agent/types.d.ts +72 -0
  18. package/dist/agent/types.js +2 -0
  19. package/dist/agent/websocket.d.ts +45 -0
  20. package/dist/agent/websocket.js +288 -0
  21. package/dist/api.d.ts +31 -0
  22. package/dist/api.js +78 -0
  23. package/dist/commands/agent.d.ts +5 -0
  24. package/dist/commands/agent.js +19 -0
  25. package/dist/commands/agents.d.ts +1 -0
  26. package/dist/commands/agents.js +77 -0
  27. package/dist/commands/login.d.ts +5 -0
  28. package/dist/commands/login.js +41 -0
  29. package/dist/commands/project.d.ts +33 -0
  30. package/dist/commands/project.js +359 -0
  31. package/dist/commands/sendkeys.d.ts +3 -0
  32. package/dist/commands/sendkeys.js +66 -0
  33. package/dist/commands/sessions.d.ts +1 -0
  34. package/dist/commands/sessions.js +89 -0
  35. package/dist/config.d.ts +13 -0
  36. package/dist/config.js +37 -0
  37. package/dist/index.d.ts +2 -0
  38. package/dist/index.js +125 -0
  39. package/dist/project/executor.d.ts +118 -0
  40. package/dist/project/executor.js +893 -0
  41. package/dist/project/index.d.ts +4 -0
  42. package/dist/project/index.js +20 -0
  43. package/dist/project/manager.d.ts +79 -0
  44. package/dist/project/manager.js +397 -0
  45. package/dist/project/relay-client.d.ts +87 -0
  46. package/dist/project/relay-client.js +200 -0
  47. package/dist/project/types.d.ts +43 -0
  48. package/dist/project/types.js +3 -0
  49. package/package.json +59 -0
@@ -0,0 +1,89 @@
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.listSessions = listSessions;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const ora_1 = __importDefault(require("ora"));
9
+ const api_1 = require("../api");
10
+ const config_1 = require("../config");
11
+ async function listSessions(agentName) {
12
+ if (!(0, config_1.isLoggedIn)()) {
13
+ console.log(chalk_1.default.red('Not logged in. Run: sessioncast login <api-key>'));
14
+ process.exit(1);
15
+ }
16
+ const spinner = (0, ora_1.default)('Fetching sessions...').start();
17
+ try {
18
+ const agents = await api_1.api.listAgents();
19
+ const onlineAgents = agents.filter(a => a.isActive && a.apiEnabled);
20
+ if (onlineAgents.length === 0) {
21
+ spinner.stop();
22
+ console.log(chalk_1.default.yellow('No online agents with API enabled.'));
23
+ return;
24
+ }
25
+ // Filter by agent name if provided
26
+ let targetAgents = onlineAgents;
27
+ if (agentName) {
28
+ const found = onlineAgents.find(a => a.label?.toLowerCase() === agentName.toLowerCase() ||
29
+ a.machineId?.toLowerCase() === agentName.toLowerCase() ||
30
+ a.id.startsWith(agentName));
31
+ if (!found) {
32
+ spinner.stop();
33
+ console.log(chalk_1.default.red(`Agent not found: ${agentName}`));
34
+ console.log(chalk_1.default.gray('Run: sessioncast agents'));
35
+ process.exit(1);
36
+ }
37
+ targetAgents = [found];
38
+ }
39
+ // Fetch sessions from all target agents
40
+ const allSessions = [];
41
+ for (const agent of targetAgents) {
42
+ try {
43
+ const sessions = await api_1.api.listSessions(agent.id);
44
+ allSessions.push({ agent, sessions });
45
+ }
46
+ catch (error) {
47
+ // Skip failed agents
48
+ }
49
+ }
50
+ spinner.stop();
51
+ if (allSessions.every(as => as.sessions.length === 0)) {
52
+ console.log(chalk_1.default.yellow('No tmux sessions found.'));
53
+ return;
54
+ }
55
+ console.log(chalk_1.default.bold('\nTmux Sessions:\n'));
56
+ // Table header
57
+ console.log(chalk_1.default.gray(padRight('AGENT', 16) +
58
+ padRight('SESSION', 16) +
59
+ padRight('WINDOWS', 10) +
60
+ padRight('ATTACHED', 10) +
61
+ 'TARGET'));
62
+ console.log(chalk_1.default.gray('─'.repeat(70)));
63
+ // Table rows
64
+ for (const { agent, sessions } of allSessions) {
65
+ const agentName = agent.label || agent.machineId || agent.id.substring(0, 8);
66
+ for (const session of sessions) {
67
+ const attached = session.attached ? chalk_1.default.green('yes') : chalk_1.default.gray('no');
68
+ const target = `${agentName}:${session.name}`;
69
+ console.log(padRight(agentName, 16) +
70
+ padRight(session.name, 16) +
71
+ padRight(String(session.windows), 10) +
72
+ padRight(attached, 10) +
73
+ chalk_1.default.cyan(target));
74
+ }
75
+ }
76
+ console.log();
77
+ console.log(chalk_1.default.gray('Use: sessioncast send <target> "command"'));
78
+ }
79
+ catch (error) {
80
+ spinner.stop();
81
+ console.log(chalk_1.default.red(`Error: ${error.message}`));
82
+ process.exit(1);
83
+ }
84
+ }
85
+ function padRight(str, len) {
86
+ const plainStr = str.replace(/\x1b\[[0-9;]*m/g, '');
87
+ const padding = Math.max(0, len - plainStr.length);
88
+ return str + ' '.repeat(padding);
89
+ }
@@ -0,0 +1,13 @@
1
+ import Conf from 'conf';
2
+ interface ConfigSchema {
3
+ apiKey?: string;
4
+ apiUrl: string;
5
+ }
6
+ declare const config: Conf<ConfigSchema>;
7
+ export declare function getApiKey(): string | undefined;
8
+ export declare function setApiKey(key: string): void;
9
+ export declare function clearApiKey(): void;
10
+ export declare function getApiUrl(): string;
11
+ export declare function setApiUrl(url: string): void;
12
+ export declare function isLoggedIn(): boolean;
13
+ export default config;
package/dist/config.js ADDED
@@ -0,0 +1,37 @@
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.getApiKey = getApiKey;
7
+ exports.setApiKey = setApiKey;
8
+ exports.clearApiKey = clearApiKey;
9
+ exports.getApiUrl = getApiUrl;
10
+ exports.setApiUrl = setApiUrl;
11
+ exports.isLoggedIn = isLoggedIn;
12
+ const conf_1 = __importDefault(require("conf"));
13
+ const config = new conf_1.default({
14
+ projectName: 'sessioncast',
15
+ defaults: {
16
+ apiUrl: 'https://api.sessioncast.io'
17
+ }
18
+ });
19
+ function getApiKey() {
20
+ return config.get('apiKey');
21
+ }
22
+ function setApiKey(key) {
23
+ config.set('apiKey', key);
24
+ }
25
+ function clearApiKey() {
26
+ config.delete('apiKey');
27
+ }
28
+ function getApiUrl() {
29
+ return config.get('apiUrl');
30
+ }
31
+ function setApiUrl(url) {
32
+ config.set('apiUrl', url);
33
+ }
34
+ function isLoggedIn() {
35
+ return !!getApiKey();
36
+ }
37
+ exports.default = config;
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,125 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const commander_1 = require("commander");
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const login_1 = require("./commands/login");
10
+ const agents_1 = require("./commands/agents");
11
+ const sessions_1 = require("./commands/sessions");
12
+ const sendkeys_1 = require("./commands/sendkeys");
13
+ const agent_1 = require("./commands/agent");
14
+ const project_1 = require("./commands/project");
15
+ const program = new commander_1.Command();
16
+ program
17
+ .name('sessioncast')
18
+ .description('SessionCast CLI - Control your agents from anywhere')
19
+ .version('1.0.0');
20
+ // Login command
21
+ program
22
+ .command('login <api-key>')
23
+ .description('Login with your API key')
24
+ .option('-u, --url <url>', 'Custom API URL')
25
+ .action(login_1.login);
26
+ // Logout command
27
+ program
28
+ .command('logout')
29
+ .description('Clear stored credentials')
30
+ .action(login_1.logout);
31
+ // Status command
32
+ program
33
+ .command('status')
34
+ .description('Check login status')
35
+ .action(login_1.status);
36
+ // Agents command
37
+ program
38
+ .command('agents')
39
+ .description('List your agents')
40
+ .action(agents_1.listAgents);
41
+ // List/Sessions command
42
+ program
43
+ .command('list [agent]')
44
+ .alias('ls')
45
+ .description('List tmux sessions on agents')
46
+ .action(sessions_1.listSessions);
47
+ // Send keys command
48
+ program
49
+ .command('send <target> <keys>')
50
+ .alias('sendkeys')
51
+ .description('Send keys to a tmux session')
52
+ .option('--no-enter', 'Do not press Enter after keys')
53
+ .action(sendkeys_1.sendKeys);
54
+ // Agent command
55
+ program
56
+ .command('agent')
57
+ .description('Start the SessionCast agent')
58
+ .option('-c, --config <path>', 'Path to config file')
59
+ .action(agent_1.startAgent);
60
+ // Project commands
61
+ const project = program
62
+ .command('project')
63
+ .description('Project mode commands');
64
+ project
65
+ .command('init [path]')
66
+ .description('Initialize a new SessionCast project')
67
+ .option('-n, --name <name>', 'Project name')
68
+ .action(project_1.projectInit);
69
+ project
70
+ .command('run [path]')
71
+ .description('Run the workflow')
72
+ .option('-w, --watch', 'Watch mode - keep running after completion')
73
+ .option('--no-claude', 'Do not auto-launch Claude Code CLI')
74
+ .option('--relay-url <url>', 'Relay server WebSocket URL')
75
+ .option('--relay-token <token>', 'Relay server authentication token')
76
+ .action(project_1.projectRun);
77
+ project
78
+ .command('status [path]')
79
+ .description('Show project and workflow status')
80
+ .action(project_1.projectStatus);
81
+ project
82
+ .command('stop [path]')
83
+ .description('Stop all agent sessions')
84
+ .action(project_1.projectStop);
85
+ project
86
+ .command('send <path> <agent> <message>')
87
+ .description('Send a message to an agent')
88
+ .action(project_1.projectSend);
89
+ project
90
+ .command('workflow [path]')
91
+ .description('Create workflow from template')
92
+ .option('-t, --template <template>', 'Template: basic, android, fullstack')
93
+ .action(project_1.projectCreateWorkflow);
94
+ // Help examples
95
+ program.on('--help', () => {
96
+ console.log('');
97
+ console.log('Examples:');
98
+ console.log(' $ sessioncast login sk-xxx-xxx-xxx');
99
+ console.log(' $ sessioncast agents');
100
+ console.log(' $ sessioncast list');
101
+ console.log(' $ sessioncast list macbook');
102
+ console.log(' $ sessioncast send macbook:dev "ls -la"');
103
+ console.log(' $ sessioncast send server:main:0 "npm run build"');
104
+ console.log(' $ sessioncast agent # Start agent with default config');
105
+ console.log(' $ sessioncast agent -c ~/.sessioncast.yml # Start with custom config');
106
+ console.log('');
107
+ console.log('Project Mode:');
108
+ console.log(' $ sessioncast project init ./my-project # Initialize new project');
109
+ console.log(' $ sessioncast project workflow . -t android # Create workflow from template');
110
+ console.log(' $ sessioncast project run . # Run the workflow');
111
+ console.log(' $ sessioncast project status . # Check status');
112
+ console.log(' $ sessioncast project stop . # Stop all agents');
113
+ console.log('');
114
+ console.log('Target format:');
115
+ console.log(' <agent>:<session> - Send to session');
116
+ console.log(' <agent>:<session>:<window> - Send to specific window');
117
+ console.log('');
118
+ });
119
+ // Default action (no command)
120
+ program.action(() => {
121
+ console.log(chalk_1.default.bold('\n SessionCast CLI\n'));
122
+ console.log(' Control your agents from anywhere.\n');
123
+ console.log(chalk_1.default.gray(' Run `sessioncast --help` for usage.\n'));
124
+ });
125
+ program.parse();
@@ -0,0 +1,118 @@
1
+ import { EventEmitter } from 'events';
2
+ import { ProjectManager } from './manager';
3
+ export interface ExecutorOptions {
4
+ autoLaunchClaude?: boolean;
5
+ claudeCommand?: string;
6
+ relayUrl?: string;
7
+ relayToken?: string;
8
+ machineId?: string;
9
+ }
10
+ export declare class WorkflowExecutor extends EventEmitter {
11
+ private manager;
12
+ private workflow;
13
+ private running;
14
+ private pollTimer;
15
+ private options;
16
+ private relayClient;
17
+ constructor(manager: ProjectManager, options?: ExecutorOptions);
18
+ /**
19
+ * Start workflow execution
20
+ */
21
+ start(): Promise<void>;
22
+ /**
23
+ * Start PM Agent tmux session
24
+ */
25
+ private startPMAgent;
26
+ /**
27
+ * Start a work agent
28
+ */
29
+ private startAgent;
30
+ /**
31
+ * Build task prompt for agent
32
+ */
33
+ private buildTaskPrompt;
34
+ /**
35
+ * Launch Claude Code CLI in a tmux session
36
+ */
37
+ private launchClaudeInSession;
38
+ /**
39
+ * Sleep helper
40
+ */
41
+ private sleep;
42
+ /**
43
+ * Main execution loop
44
+ */
45
+ private runExecutionLoop;
46
+ /**
47
+ * Connect to relay server
48
+ */
49
+ private connectToRelay;
50
+ /**
51
+ * Handle incoming messages from relay server
52
+ */
53
+ private handleRelayMessage;
54
+ /**
55
+ * Handle mission analysis request - calls Claude Code to analyze
56
+ */
57
+ private handleAnalyzeMission;
58
+ /**
59
+ * Handle addSource request - clone/copy source into work folder
60
+ */
61
+ private handleAddSource;
62
+ /**
63
+ * Execute the source addition command
64
+ */
65
+ private executeAddSource;
66
+ /**
67
+ * Use Claude to interpret a natural language prompt and add source
68
+ */
69
+ private executeAddSourceWithAI;
70
+ /**
71
+ * Call Claude Code CLI to analyze mission and return steps and decisions
72
+ */
73
+ private callClaudeForAnalysis;
74
+ /**
75
+ * Read source file contents from context paths for Claude analysis
76
+ */
77
+ private readSourceContext;
78
+ /**
79
+ * Get key files from a source directory for context
80
+ */
81
+ private getKeyFilesFromDirectory;
82
+ /**
83
+ * Build the prompt for Claude Code to analyze the mission
84
+ */
85
+ private buildAnalysisPrompt;
86
+ /**
87
+ * Parse Claude's response to extract steps and decisions
88
+ */
89
+ private parseAnalysisResponse;
90
+ /**
91
+ * Get default steps when analysis fails
92
+ */
93
+ private getDefaultSteps;
94
+ /**
95
+ * Update relay with current status
96
+ */
97
+ private updateRelayStatus;
98
+ /**
99
+ * Stop workflow execution
100
+ */
101
+ stop(): void;
102
+ /**
103
+ * Kill all project tmux sessions
104
+ */
105
+ killAllSessions(): void;
106
+ /**
107
+ * Send keys to an agent session
108
+ */
109
+ sendToAgent(agentId: string, keys: string): boolean;
110
+ /**
111
+ * Capture agent terminal output
112
+ */
113
+ captureAgent(agentId: string): string | null;
114
+ /**
115
+ * List all agent sessions for this project
116
+ */
117
+ listSessions(): string[];
118
+ }