sessioncast-cli 1.0.0 → 1.1.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 (47) hide show
  1. package/README.md +65 -40
  2. package/dist/agent/session-handler.d.ts +1 -0
  3. package/dist/agent/session-handler.js +42 -0
  4. package/dist/agent/tmux-executor.d.ts +66 -0
  5. package/dist/agent/tmux-executor.js +368 -0
  6. package/dist/agent/tmux.d.ts +9 -1
  7. package/dist/agent/tmux.js +52 -76
  8. package/dist/agent/websocket.d.ts +2 -8
  9. package/dist/agent/websocket.js +78 -14
  10. package/dist/autopilot/index.d.ts +94 -0
  11. package/dist/autopilot/index.js +322 -0
  12. package/dist/autopilot/mission-analyzer.d.ts +27 -0
  13. package/dist/autopilot/mission-analyzer.js +232 -0
  14. package/dist/autopilot/project-detector.d.ts +12 -0
  15. package/dist/autopilot/project-detector.js +326 -0
  16. package/dist/autopilot/source-scanner.d.ts +26 -0
  17. package/dist/autopilot/source-scanner.js +285 -0
  18. package/dist/autopilot/speckit-generator.d.ts +60 -0
  19. package/dist/autopilot/speckit-generator.js +511 -0
  20. package/dist/autopilot/types.d.ts +110 -0
  21. package/dist/autopilot/types.js +6 -0
  22. package/dist/autopilot/workflow-generator.d.ts +33 -0
  23. package/dist/autopilot/workflow-generator.js +278 -0
  24. package/dist/commands/autopilot.d.ts +30 -0
  25. package/dist/commands/autopilot.js +262 -0
  26. package/dist/commands/login.d.ts +2 -1
  27. package/dist/commands/login.js +199 -8
  28. package/dist/commands/project.d.ts +1 -1
  29. package/dist/commands/project.js +4 -13
  30. package/dist/config.d.ts +20 -0
  31. package/dist/config.js +69 -2
  32. package/dist/index.js +7 -47
  33. package/dist/project/executor.d.ts +8 -53
  34. package/dist/project/executor.js +64 -520
  35. package/dist/project/manager.d.ts +0 -13
  36. package/dist/project/manager.js +0 -107
  37. package/dist/project/relay-client.d.ts +18 -68
  38. package/dist/project/relay-client.js +134 -130
  39. package/dist/project/types.d.ts +5 -0
  40. package/dist/utils/fileUtils.d.ts +28 -0
  41. package/dist/utils/fileUtils.js +159 -0
  42. package/dist/utils/oauthServer.d.ts +18 -0
  43. package/dist/utils/oauthServer.js +244 -0
  44. package/dist/utils/pkce.d.ts +16 -0
  45. package/dist/utils/pkce.js +73 -0
  46. package/package.json +5 -14
  47. package/LICENSE +0 -21
@@ -0,0 +1,159 @@
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.sanitizeFilename = sanitizeFilename;
37
+ exports.getUploadDirectory = getUploadDirectory;
38
+ exports.handleUploadChunk = handleUploadChunk;
39
+ exports.cleanupStaleUploads = cleanupStaleUploads;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ // Track ongoing uploads
43
+ const pendingUploads = new Map();
44
+ // Cleanup stale uploads after 5 minutes
45
+ const UPLOAD_TIMEOUT_MS = 5 * 60 * 1000;
46
+ /**
47
+ * Sanitize filename to prevent path traversal attacks
48
+ */
49
+ function sanitizeFilename(filename) {
50
+ // Remove any path components
51
+ const basename = path.basename(filename);
52
+ // Remove potentially dangerous characters
53
+ return basename.replace(/[<>:"/\\|?*\x00-\x1f]/g, '_');
54
+ }
55
+ /**
56
+ * Get the working directory for file uploads
57
+ * Priority: SESSIONCAST_UPLOAD_DIR env var > current working directory
58
+ */
59
+ function getUploadDirectory() {
60
+ return process.env.SESSIONCAST_UPLOAD_DIR || process.cwd();
61
+ }
62
+ /**
63
+ * Handle file upload chunk
64
+ * Returns upload result when all chunks are received, null otherwise
65
+ */
66
+ async function handleUploadChunk(sessionId, meta, payload) {
67
+ const filename = sanitizeFilename(meta.filename);
68
+ const uploadKey = `${sessionId}:${filename}`;
69
+ const chunkIndex = parseInt(meta.chunkIndex, 10);
70
+ const totalChunks = parseInt(meta.totalChunks, 10);
71
+ const size = parseInt(meta.size, 10);
72
+ // Validate parameters
73
+ if (isNaN(chunkIndex) || isNaN(totalChunks) || isNaN(size)) {
74
+ return { success: false, error: 'Invalid upload metadata' };
75
+ }
76
+ // Check file size limit (10MB)
77
+ const MAX_FILE_SIZE = 10 * 1024 * 1024;
78
+ if (size > MAX_FILE_SIZE) {
79
+ return { success: false, error: `File too large. Max size: ${MAX_FILE_SIZE / 1024 / 1024}MB` };
80
+ }
81
+ // Get or create upload state
82
+ let state = pendingUploads.get(uploadKey);
83
+ if (!state) {
84
+ state = {
85
+ filename,
86
+ totalChunks,
87
+ receivedChunks: new Map(),
88
+ size,
89
+ mimeType: meta.mimeType,
90
+ createdAt: Date.now(),
91
+ };
92
+ pendingUploads.set(uploadKey, state);
93
+ }
94
+ // Decode and store chunk
95
+ try {
96
+ const chunkBuffer = Buffer.from(payload, 'base64');
97
+ state.receivedChunks.set(chunkIndex, chunkBuffer);
98
+ console.log(`[FileUpload] Received chunk ${chunkIndex + 1}/${totalChunks} for ${filename}`);
99
+ }
100
+ catch (e) {
101
+ pendingUploads.delete(uploadKey);
102
+ return { success: false, error: 'Failed to decode chunk data' };
103
+ }
104
+ // Check if all chunks received
105
+ if (state.receivedChunks.size === totalChunks) {
106
+ try {
107
+ // Assemble file from chunks
108
+ const chunks = [];
109
+ for (let i = 0; i < totalChunks; i++) {
110
+ const chunk = state.receivedChunks.get(i);
111
+ if (!chunk) {
112
+ throw new Error(`Missing chunk ${i}`);
113
+ }
114
+ chunks.push(chunk);
115
+ }
116
+ const fileBuffer = Buffer.concat(chunks);
117
+ // Determine save path
118
+ const uploadDir = getUploadDirectory();
119
+ let savePath = path.join(uploadDir, filename);
120
+ // Handle filename collision
121
+ if (fs.existsSync(savePath)) {
122
+ const ext = path.extname(filename);
123
+ const basename = path.basename(filename, ext);
124
+ let counter = 1;
125
+ while (fs.existsSync(savePath)) {
126
+ savePath = path.join(uploadDir, `${basename}_${counter}${ext}`);
127
+ counter++;
128
+ }
129
+ }
130
+ // Write file
131
+ fs.writeFileSync(savePath, fileBuffer);
132
+ console.log(`[FileUpload] File saved: ${savePath}`);
133
+ // Cleanup
134
+ pendingUploads.delete(uploadKey);
135
+ return { success: true, path: savePath };
136
+ }
137
+ catch (e) {
138
+ pendingUploads.delete(uploadKey);
139
+ const errorMsg = e instanceof Error ? e.message : 'Unknown error';
140
+ return { success: false, error: `Failed to save file: ${errorMsg}` };
141
+ }
142
+ }
143
+ // Not all chunks received yet
144
+ return null;
145
+ }
146
+ /**
147
+ * Cleanup stale uploads periodically
148
+ */
149
+ function cleanupStaleUploads() {
150
+ const now = Date.now();
151
+ for (const [key, state] of pendingUploads.entries()) {
152
+ if (now - state.createdAt > UPLOAD_TIMEOUT_MS) {
153
+ console.log(`[FileUpload] Cleaning up stale upload: ${state.filename}`);
154
+ pendingUploads.delete(key);
155
+ }
156
+ }
157
+ }
158
+ // Run cleanup every minute
159
+ setInterval(cleanupStaleUploads, 60 * 1000);
@@ -0,0 +1,18 @@
1
+ interface CallbackResult {
2
+ code?: string;
3
+ state?: string;
4
+ error?: string;
5
+ errorDescription?: string;
6
+ }
7
+ /**
8
+ * Start a temporary local HTTP server to receive OAuth callback
9
+ * @param port Port number to listen on
10
+ * @param timeoutMs Timeout in milliseconds (default: 5 minutes)
11
+ * @returns Promise that resolves with the authorization code
12
+ */
13
+ export declare function startCallbackServer(port?: number, timeoutMs?: number): Promise<CallbackResult>;
14
+ /**
15
+ * Find an available port
16
+ */
17
+ export declare function findAvailablePort(startPort?: number): Promise<number>;
18
+ export {};
@@ -0,0 +1,244 @@
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.startCallbackServer = startCallbackServer;
37
+ exports.findAvailablePort = findAvailablePort;
38
+ const http = __importStar(require("http"));
39
+ const url = __importStar(require("url"));
40
+ /**
41
+ * Start a temporary local HTTP server to receive OAuth callback
42
+ * @param port Port number to listen on
43
+ * @param timeoutMs Timeout in milliseconds (default: 5 minutes)
44
+ * @returns Promise that resolves with the authorization code
45
+ */
46
+ function startCallbackServer(port = 9876, timeoutMs = 300000) {
47
+ return new Promise((resolve, reject) => {
48
+ const server = http.createServer((req, res) => {
49
+ const parsedUrl = url.parse(req.url || '', true);
50
+ if (parsedUrl.pathname === '/callback') {
51
+ const query = parsedUrl.query;
52
+ // Build result
53
+ const result = {
54
+ code: query.code,
55
+ state: query.state,
56
+ error: query.error,
57
+ errorDescription: query.error_description,
58
+ };
59
+ // Send response to browser
60
+ if (result.error) {
61
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
62
+ res.end(getErrorPage(result.error, result.errorDescription));
63
+ }
64
+ else if (result.code) {
65
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
66
+ res.end(getSuccessPage());
67
+ }
68
+ else {
69
+ res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
70
+ res.end(getErrorPage('missing_code', 'No authorization code received'));
71
+ }
72
+ // Close server and resolve
73
+ server.close();
74
+ resolve(result);
75
+ }
76
+ else {
77
+ res.writeHead(404);
78
+ res.end('Not Found');
79
+ }
80
+ });
81
+ // Handle server errors
82
+ server.on('error', (err) => {
83
+ if (err.code === 'EADDRINUSE') {
84
+ reject(new Error(`Port ${port} is already in use. Please try again.`));
85
+ }
86
+ else {
87
+ reject(err);
88
+ }
89
+ });
90
+ // Start listening
91
+ server.listen(port, '127.0.0.1', () => {
92
+ // console.log(`OAuth callback server listening on http://127.0.0.1:${port}/callback`);
93
+ });
94
+ // Set timeout
95
+ const timeout = setTimeout(() => {
96
+ server.close();
97
+ reject(new Error('Login timed out. Please try again.'));
98
+ }, timeoutMs);
99
+ // Clear timeout on successful resolution
100
+ server.on('close', () => {
101
+ clearTimeout(timeout);
102
+ });
103
+ });
104
+ }
105
+ /**
106
+ * Find an available port
107
+ */
108
+ async function findAvailablePort(startPort = 9876) {
109
+ return new Promise((resolve, reject) => {
110
+ const server = http.createServer();
111
+ server.on('error', (err) => {
112
+ if (err.code === 'EADDRINUSE') {
113
+ // Try next port
114
+ server.close();
115
+ resolve(findAvailablePort(startPort + 1));
116
+ }
117
+ else {
118
+ reject(err);
119
+ }
120
+ });
121
+ server.listen(startPort, '127.0.0.1', () => {
122
+ server.close(() => {
123
+ resolve(startPort);
124
+ });
125
+ });
126
+ });
127
+ }
128
+ function getSuccessPage() {
129
+ return `
130
+ <!DOCTYPE html>
131
+ <html>
132
+ <head>
133
+ <meta charset="utf-8">
134
+ <title>SessionCast - Login Successful</title>
135
+ <style>
136
+ * { margin: 0; padding: 0; box-sizing: border-box; }
137
+ body {
138
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
139
+ background: linear-gradient(135deg, #0f0f23 0%, #1a1a3e 100%);
140
+ color: #fff;
141
+ min-height: 100vh;
142
+ display: flex;
143
+ align-items: center;
144
+ justify-content: center;
145
+ }
146
+ .container {
147
+ text-align: center;
148
+ padding: 40px;
149
+ }
150
+ .icon {
151
+ font-size: 64px;
152
+ margin-bottom: 24px;
153
+ }
154
+ h1 {
155
+ font-size: 28px;
156
+ margin-bottom: 16px;
157
+ color: #22c55e;
158
+ }
159
+ p {
160
+ color: #a1a1aa;
161
+ font-size: 16px;
162
+ margin-bottom: 24px;
163
+ }
164
+ .hint {
165
+ background: rgba(255,255,255,0.1);
166
+ padding: 12px 24px;
167
+ border-radius: 8px;
168
+ font-family: monospace;
169
+ font-size: 14px;
170
+ }
171
+ </style>
172
+ </head>
173
+ <body>
174
+ <div class="container">
175
+ <div class="icon">✅</div>
176
+ <h1>Login Successful!</h1>
177
+ <p>You can close this window and return to your terminal.</p>
178
+ <div class="hint">sessioncast agent</div>
179
+ </div>
180
+ <script>
181
+ // Auto-close after 3 seconds
182
+ setTimeout(() => window.close(), 3000);
183
+ </script>
184
+ </body>
185
+ </html>
186
+ `;
187
+ }
188
+ function getErrorPage(error, description) {
189
+ return `
190
+ <!DOCTYPE html>
191
+ <html>
192
+ <head>
193
+ <meta charset="utf-8">
194
+ <title>SessionCast - Login Failed</title>
195
+ <style>
196
+ * { margin: 0; padding: 0; box-sizing: border-box; }
197
+ body {
198
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
199
+ background: linear-gradient(135deg, #0f0f23 0%, #1a1a3e 100%);
200
+ color: #fff;
201
+ min-height: 100vh;
202
+ display: flex;
203
+ align-items: center;
204
+ justify-content: center;
205
+ }
206
+ .container {
207
+ text-align: center;
208
+ padding: 40px;
209
+ }
210
+ .icon {
211
+ font-size: 64px;
212
+ margin-bottom: 24px;
213
+ }
214
+ h1 {
215
+ font-size: 28px;
216
+ margin-bottom: 16px;
217
+ color: #ef4444;
218
+ }
219
+ p {
220
+ color: #a1a1aa;
221
+ font-size: 16px;
222
+ margin-bottom: 16px;
223
+ }
224
+ .error-detail {
225
+ background: rgba(239, 68, 68, 0.1);
226
+ padding: 12px 24px;
227
+ border-radius: 8px;
228
+ font-family: monospace;
229
+ font-size: 14px;
230
+ color: #fca5a5;
231
+ }
232
+ </style>
233
+ </head>
234
+ <body>
235
+ <div class="container">
236
+ <div class="icon">❌</div>
237
+ <h1>Login Failed</h1>
238
+ <p>${description || 'An error occurred during authentication.'}</p>
239
+ <div class="error-detail">${error}</div>
240
+ </div>
241
+ </body>
242
+ </html>
243
+ `;
244
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Generate a cryptographically random code verifier for PKCE
3
+ * @returns Base64URL encoded random string (43-128 characters)
4
+ */
5
+ export declare function generateCodeVerifier(): string;
6
+ /**
7
+ * Generate code challenge from code verifier using SHA-256
8
+ * @param codeVerifier The code verifier string
9
+ * @returns Base64URL encoded SHA-256 hash
10
+ */
11
+ export declare function generateCodeChallenge(codeVerifier: string): string;
12
+ /**
13
+ * Generate a random state parameter for OAuth
14
+ * @returns Random hex string
15
+ */
16
+ export declare function generateState(): string;
@@ -0,0 +1,73 @@
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.generateCodeVerifier = generateCodeVerifier;
37
+ exports.generateCodeChallenge = generateCodeChallenge;
38
+ exports.generateState = generateState;
39
+ const crypto = __importStar(require("crypto"));
40
+ /**
41
+ * Generate a cryptographically random code verifier for PKCE
42
+ * @returns Base64URL encoded random string (43-128 characters)
43
+ */
44
+ function generateCodeVerifier() {
45
+ const buffer = crypto.randomBytes(32);
46
+ return base64URLEncode(buffer);
47
+ }
48
+ /**
49
+ * Generate code challenge from code verifier using SHA-256
50
+ * @param codeVerifier The code verifier string
51
+ * @returns Base64URL encoded SHA-256 hash
52
+ */
53
+ function generateCodeChallenge(codeVerifier) {
54
+ const hash = crypto.createHash('sha256').update(codeVerifier).digest();
55
+ return base64URLEncode(hash);
56
+ }
57
+ /**
58
+ * Generate a random state parameter for OAuth
59
+ * @returns Random hex string
60
+ */
61
+ function generateState() {
62
+ return crypto.randomBytes(16).toString('hex');
63
+ }
64
+ /**
65
+ * Base64URL encode a buffer (RFC 4648)
66
+ */
67
+ function base64URLEncode(buffer) {
68
+ return buffer
69
+ .toString('base64')
70
+ .replace(/\+/g, '-')
71
+ .replace(/\//g, '_')
72
+ .replace(/=/g, '');
73
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sessioncast-cli",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "SessionCast CLI - Control your agents from anywhere",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -17,23 +17,13 @@
17
17
  "tmux",
18
18
  "cli",
19
19
  "terminal",
20
- "remote",
21
- "agent",
22
- "websocket"
20
+ "remote"
23
21
  ],
24
- "author": {
25
- "name": "SessionCast",
26
- "email": "devload@sessioncast.io"
27
- },
22
+ "author": "SessionCast",
28
23
  "license": "MIT",
29
- "homepage": "https://sessioncast.io",
30
- "bugs": {
31
- "email": "devload@sessioncast.io"
32
- },
33
24
  "type": "commonjs",
34
25
  "files": [
35
- "dist",
36
- "README.md"
26
+ "dist"
37
27
  ],
38
28
  "dependencies": {
39
29
  "chalk": "^4.1.2",
@@ -50,6 +40,7 @@
50
40
  "@types/node": "^22.10.2",
51
41
  "@types/node-fetch": "^2.6.13",
52
42
  "@types/ws": "^8.5.13",
43
+ "puppeteer": "^24.34.0",
53
44
  "ts-node": "^10.9.2",
54
45
  "typescript": "^5.7.2"
55
46
  },
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.