@ellery/terminal-mcp 0.2.1 → 0.3.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 (115) hide show
  1. package/README.md +301 -9
  2. package/dist/client.d.ts.map +1 -1
  3. package/dist/client.js +2 -61
  4. package/dist/client.js.map +1 -1
  5. package/dist/index.js +286 -14
  6. package/dist/index.js.map +1 -1
  7. package/dist/prompts/index.d.ts.map +1 -1
  8. package/dist/prompts/index.js +8 -0
  9. package/dist/prompts/index.js.map +1 -1
  10. package/dist/recording/index.d.ts +4 -0
  11. package/dist/recording/index.d.ts.map +1 -0
  12. package/dist/recording/index.js +3 -0
  13. package/dist/recording/index.js.map +1 -0
  14. package/dist/recording/manager.d.ts +62 -0
  15. package/dist/recording/manager.d.ts.map +1 -0
  16. package/dist/recording/manager.js +123 -0
  17. package/dist/recording/manager.js.map +1 -0
  18. package/dist/recording/recorder.d.ts +95 -0
  19. package/dist/recording/recorder.d.ts.map +1 -0
  20. package/dist/recording/recorder.js +296 -0
  21. package/dist/recording/recorder.js.map +1 -0
  22. package/dist/recording/types.d.ts +65 -0
  23. package/dist/recording/types.d.ts.map +1 -0
  24. package/dist/recording/types.js +2 -0
  25. package/dist/recording/types.js.map +1 -0
  26. package/dist/sandbox/config.d.ts +46 -0
  27. package/dist/sandbox/config.d.ts.map +1 -0
  28. package/dist/sandbox/config.js +144 -0
  29. package/dist/sandbox/config.js.map +1 -0
  30. package/dist/sandbox/controller.d.ts +72 -0
  31. package/dist/sandbox/controller.d.ts.map +1 -0
  32. package/dist/sandbox/controller.js +208 -0
  33. package/dist/sandbox/controller.js.map +1 -0
  34. package/dist/sandbox/index.d.ts +6 -0
  35. package/dist/sandbox/index.d.ts.map +1 -0
  36. package/dist/sandbox/index.js +4 -0
  37. package/dist/sandbox/index.js.map +1 -0
  38. package/dist/sandbox/prompt.d.ts +10 -0
  39. package/dist/sandbox/prompt.d.ts.map +1 -0
  40. package/dist/sandbox/prompt.js +434 -0
  41. package/dist/sandbox/prompt.js.map +1 -0
  42. package/dist/server.d.ts +2 -3
  43. package/dist/server.d.ts.map +1 -1
  44. package/dist/server.js +21 -0
  45. package/dist/server.js.map +1 -1
  46. package/dist/terminal/index.d.ts +1 -0
  47. package/dist/terminal/index.d.ts.map +1 -1
  48. package/dist/terminal/manager.d.ts +89 -31
  49. package/dist/terminal/manager.d.ts.map +1 -1
  50. package/dist/terminal/manager.js +313 -44
  51. package/dist/terminal/manager.js.map +1 -1
  52. package/dist/terminal/session.d.ts +34 -1
  53. package/dist/terminal/session.d.ts.map +1 -1
  54. package/dist/terminal/session.js +160 -3
  55. package/dist/terminal/session.js.map +1 -1
  56. package/dist/tools/createSession.d.ts +44 -0
  57. package/dist/tools/createSession.d.ts.map +1 -0
  58. package/dist/tools/createSession.js +41 -0
  59. package/dist/tools/createSession.js.map +1 -0
  60. package/dist/tools/definitions.d.ts +18 -0
  61. package/dist/tools/definitions.d.ts.map +1 -0
  62. package/dist/tools/definitions.js +116 -0
  63. package/dist/tools/definitions.js.map +1 -0
  64. package/dist/tools/destroySession.d.ts +31 -0
  65. package/dist/tools/destroySession.d.ts.map +1 -0
  66. package/dist/tools/destroySession.js +32 -0
  67. package/dist/tools/destroySession.js.map +1 -0
  68. package/dist/tools/getContent.d.ts +7 -0
  69. package/dist/tools/getContent.d.ts.map +1 -1
  70. package/dist/tools/getContent.js +8 -3
  71. package/dist/tools/getContent.js.map +1 -1
  72. package/dist/tools/index.d.ts.map +1 -1
  73. package/dist/tools/index.js +26 -1
  74. package/dist/tools/index.js.map +1 -1
  75. package/dist/tools/listSessions.d.ts +19 -0
  76. package/dist/tools/listSessions.d.ts.map +1 -0
  77. package/dist/tools/listSessions.js +23 -0
  78. package/dist/tools/listSessions.js.map +1 -0
  79. package/dist/tools/screenshot.d.ts +26 -3
  80. package/dist/tools/screenshot.d.ts.map +1 -1
  81. package/dist/tools/screenshot.js +55 -5
  82. package/dist/tools/screenshot.js.map +1 -1
  83. package/dist/tools/sendKey.d.ts +7 -0
  84. package/dist/tools/sendKey.d.ts.map +1 -1
  85. package/dist/tools/sendKey.js +7 -2
  86. package/dist/tools/sendKey.js.map +1 -1
  87. package/dist/tools/startRecording.d.ts +68 -0
  88. package/dist/tools/startRecording.d.ts.map +1 -0
  89. package/dist/tools/startRecording.js +111 -0
  90. package/dist/tools/startRecording.js.map +1 -0
  91. package/dist/tools/stopRecording.d.ts +31 -0
  92. package/dist/tools/stopRecording.d.ts.map +1 -0
  93. package/dist/tools/stopRecording.js +76 -0
  94. package/dist/tools/stopRecording.js.map +1 -0
  95. package/dist/tools/type.d.ts +7 -0
  96. package/dist/tools/type.d.ts.map +1 -1
  97. package/dist/tools/type.js +7 -2
  98. package/dist/tools/type.js.map +1 -1
  99. package/dist/transport/socket.d.ts.map +1 -1
  100. package/dist/transport/socket.js +10 -0
  101. package/dist/transport/socket.js.map +1 -1
  102. package/dist/ui/index.d.ts +1 -0
  103. package/dist/ui/index.d.ts.map +1 -1
  104. package/dist/ui/index.js +17 -1
  105. package/dist/ui/index.js.map +1 -1
  106. package/dist/utils/platform.d.ts +6 -0
  107. package/dist/utils/platform.d.ts.map +1 -1
  108. package/dist/utils/platform.js +15 -0
  109. package/dist/utils/platform.js.map +1 -1
  110. package/dist/utils/render.d.ts +21 -0
  111. package/dist/utils/render.d.ts.map +1 -0
  112. package/dist/utils/render.js +162 -0
  113. package/dist/utils/render.js.map +1 -0
  114. package/package.json +6 -2
  115. package/sandbox-permissions.png +0 -0
@@ -0,0 +1,95 @@
1
+ import type { RecordingMode, RecordingFormat, RecordingMetadata, StopReason } from "./types.js";
2
+ /**
3
+ * Recorder handles writing asciicast v2 format recordings
4
+ *
5
+ * Asciicast v2 format:
6
+ * - First line: JSON header with version, dimensions, timestamp
7
+ * - Subsequent lines: JSON arrays [time, type, data]
8
+ * - time: seconds since start (float)
9
+ * - type: "o" for output, "r" for resize
10
+ * - data: string content
11
+ */
12
+ export declare class Recorder {
13
+ readonly id: string;
14
+ private mode;
15
+ private format;
16
+ private outputDir;
17
+ private tempPath;
18
+ private finalPath;
19
+ private writeStream;
20
+ private startTime;
21
+ private bytesWritten;
22
+ private finalized;
23
+ private idleTimeLimit;
24
+ private lastEventTime;
25
+ private adjustedElapsed;
26
+ private maxDuration;
27
+ private inactivityTimeout;
28
+ private maxDurationTimer;
29
+ private inactivityTimer;
30
+ private stopReason;
31
+ private onAutoFinalize?;
32
+ constructor(id: string, mode: RecordingMode, outputDir: string, format?: RecordingFormat, idleTimeLimit?: number, maxDuration?: number, // 60 minutes default
33
+ inactivityTimeout?: number);
34
+ /**
35
+ * Start the recording
36
+ * Writes the asciicast header to the temp file
37
+ */
38
+ start(width: number, height: number, env?: {
39
+ SHELL?: string;
40
+ TERM?: string;
41
+ }): void;
42
+ /**
43
+ * Record output data
44
+ */
45
+ recordOutput(data: string): void;
46
+ /**
47
+ * Record terminal resize event
48
+ */
49
+ recordResize(cols: number, rows: number): void;
50
+ /**
51
+ * Finalize the recording
52
+ * - For 'always' mode: move temp file to output dir
53
+ * - For 'on-failure' mode: move if exitCode !== 0, delete otherwise
54
+ *
55
+ * Returns metadata about the recording
56
+ */
57
+ finalize(exitCode: number | null, stopReason?: StopReason): Promise<RecordingMetadata>;
58
+ /**
59
+ * Check if recording is active
60
+ */
61
+ isActive(): boolean;
62
+ /**
63
+ * Get the temp file path (for debugging/testing)
64
+ */
65
+ getTempPath(): string;
66
+ /**
67
+ * Get the final file path
68
+ */
69
+ getFinalPath(): string;
70
+ private getElapsedSeconds;
71
+ private writeLine;
72
+ /**
73
+ * Clear all active timers
74
+ */
75
+ private clearTimers;
76
+ /**
77
+ * Auto-finalize the recording due to timeout
78
+ * Called internally when max duration or inactivity timeout is reached
79
+ */
80
+ private _autoFinalize;
81
+ /**
82
+ * Set callback for auto-finalize events (timeout triggered)
83
+ */
84
+ setOnAutoFinalize(callback: (metadata: RecordingMetadata) => void): void;
85
+ /**
86
+ * Get timeout configuration and remaining time
87
+ */
88
+ getTimeoutInfo(): {
89
+ maxDuration: number;
90
+ inactivityTimeout: number;
91
+ elapsedSeconds: number;
92
+ remainingMaxDuration: number;
93
+ };
94
+ }
95
+ //# sourceMappingURL=recorder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../src/recording/recorder.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EAGf,iBAAiB,EACjB,UAAU,EACX,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;GASG;AACH,qBAAa,QAAQ;IACnB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,IAAI,CAAgB;IAC5B,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,eAAe,CAAa;IAGpC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,gBAAgB,CAA8C;IACtE,OAAO,CAAC,eAAe,CAA8C;IACrE,OAAO,CAAC,UAAU,CAA0B;IAG5C,OAAO,CAAC,cAAc,CAAC,CAAwC;gBAG7D,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,aAAa,EACnB,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,eAAsB,EAC9B,aAAa,GAAE,MAAU,EACzB,WAAW,GAAE,MAAa,EAAS,qBAAqB;IACxD,iBAAiB,GAAE,MAAY;IAiBjC;;;OAGG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IA0CnF;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAkBhC;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAU9C;;;;;;OAMG;IACG,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,UAAU,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAiF5F;;OAEG;IACH,QAAQ,IAAI,OAAO;IAInB;;OAEG;IACH,WAAW,IAAI,MAAM;IAIrB;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB,OAAO,CAAC,iBAAiB;IA0BzB,OAAO,CAAC,SAAS;IAQjB;;OAEG;IACH,OAAO,CAAC,WAAW;IAWnB;;;OAGG;YACW,aAAa;IAc3B;;OAEG;IACH,iBAAiB,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,GAAG,IAAI;IAIxE;;OAEG;IACH,cAAc,IAAI;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,cAAc,EAAE,MAAM,CAAC;QACvB,oBAAoB,EAAE,MAAM,CAAC;KAC9B;CAWF"}
@@ -0,0 +1,296 @@
1
+ import * as fs from "fs";
2
+ import * as os from "os";
3
+ import * as path from "path";
4
+ /**
5
+ * Recorder handles writing asciicast v2 format recordings
6
+ *
7
+ * Asciicast v2 format:
8
+ * - First line: JSON header with version, dimensions, timestamp
9
+ * - Subsequent lines: JSON arrays [time, type, data]
10
+ * - time: seconds since start (float)
11
+ * - type: "o" for output, "r" for resize
12
+ * - data: string content
13
+ */
14
+ export class Recorder {
15
+ id;
16
+ mode;
17
+ format;
18
+ outputDir;
19
+ tempPath;
20
+ finalPath;
21
+ writeStream = null;
22
+ startTime = 0;
23
+ bytesWritten = 0;
24
+ finalized = false;
25
+ idleTimeLimit;
26
+ lastEventTime = 0;
27
+ adjustedElapsed = 0;
28
+ // Timeout settings
29
+ maxDuration;
30
+ inactivityTimeout;
31
+ maxDurationTimer = null;
32
+ inactivityTimer = null;
33
+ stopReason = 'explicit';
34
+ // Callback for auto-finalize events
35
+ onAutoFinalize;
36
+ constructor(id, mode, outputDir, format = 'v2', idleTimeLimit = 2, maxDuration = 3600, // 60 minutes default
37
+ inactivityTimeout = 600 // 10 minutes default
38
+ ) {
39
+ this.id = id;
40
+ this.mode = mode;
41
+ this.format = format;
42
+ this.outputDir = outputDir;
43
+ this.idleTimeLimit = idleTimeLimit;
44
+ this.maxDuration = maxDuration;
45
+ this.inactivityTimeout = inactivityTimeout;
46
+ // Generate temp and final paths
47
+ const timestamp = Date.now();
48
+ const filename = `terminal-${timestamp}-${id}.cast`;
49
+ this.tempPath = path.join(os.tmpdir(), `terminal-mcp-recording-${id}.cast`);
50
+ this.finalPath = path.join(outputDir, filename);
51
+ }
52
+ /**
53
+ * Start the recording
54
+ * Writes the asciicast header to the temp file
55
+ */
56
+ start(width, height, env) {
57
+ if (this.writeStream) {
58
+ throw new Error("Recording already started");
59
+ }
60
+ this.startTime = Date.now();
61
+ // Ensure output directory exists
62
+ fs.mkdirSync(this.outputDir, { recursive: true });
63
+ // Create write stream to temp file
64
+ this.writeStream = fs.createWriteStream(this.tempPath, { flags: 'w' });
65
+ // Write header
66
+ const header = {
67
+ version: 2,
68
+ width,
69
+ height,
70
+ timestamp: Math.floor(this.startTime / 1000),
71
+ };
72
+ if (env) {
73
+ header.env = env;
74
+ }
75
+ this.writeLine(JSON.stringify(header));
76
+ // Set up max duration timer
77
+ if (this.maxDuration > 0) {
78
+ this.maxDurationTimer = setTimeout(() => {
79
+ this._autoFinalize('max_duration');
80
+ }, this.maxDuration * 1000);
81
+ }
82
+ // Set up initial inactivity timer
83
+ if (this.inactivityTimeout > 0) {
84
+ this.inactivityTimer = setTimeout(() => {
85
+ this._autoFinalize('inactivity');
86
+ }, this.inactivityTimeout * 1000);
87
+ }
88
+ }
89
+ /**
90
+ * Record output data
91
+ */
92
+ recordOutput(data) {
93
+ if (!this.writeStream || this.finalized) {
94
+ return;
95
+ }
96
+ // Reset inactivity timer on each output event
97
+ if (this.inactivityTimeout > 0 && this.inactivityTimer) {
98
+ clearTimeout(this.inactivityTimer);
99
+ this.inactivityTimer = setTimeout(() => {
100
+ this._autoFinalize('inactivity');
101
+ }, this.inactivityTimeout * 1000);
102
+ }
103
+ const elapsed = this.getElapsedSeconds();
104
+ const event = [elapsed, 'o', data];
105
+ this.writeLine(JSON.stringify(event));
106
+ }
107
+ /**
108
+ * Record terminal resize event
109
+ */
110
+ recordResize(cols, rows) {
111
+ if (!this.writeStream || this.finalized) {
112
+ return;
113
+ }
114
+ const elapsed = this.getElapsedSeconds();
115
+ const event = [elapsed, 'r', `${cols}x${rows}`];
116
+ this.writeLine(JSON.stringify(event));
117
+ }
118
+ /**
119
+ * Finalize the recording
120
+ * - For 'always' mode: move temp file to output dir
121
+ * - For 'on-failure' mode: move if exitCode !== 0, delete otherwise
122
+ *
123
+ * Returns metadata about the recording
124
+ */
125
+ async finalize(exitCode, stopReason) {
126
+ if (this.finalized) {
127
+ throw new Error("Recording already finalized");
128
+ }
129
+ this.finalized = true;
130
+ const endTime = Date.now();
131
+ const durationMs = endTime - this.startTime;
132
+ // Clear any active timers
133
+ this.clearTimers();
134
+ // Use provided stopReason or the internally tracked one
135
+ const finalStopReason = stopReason ?? this.stopReason;
136
+ // Close the write stream
137
+ if (this.writeStream) {
138
+ await new Promise((resolve, reject) => {
139
+ this.writeStream.end((err) => {
140
+ if (err)
141
+ reject(err);
142
+ else
143
+ resolve();
144
+ });
145
+ });
146
+ }
147
+ let saved = false;
148
+ let finalPath = this.tempPath;
149
+ // Determine whether to save based on mode and exit code
150
+ const shouldSave = this.mode === 'always' ||
151
+ (this.mode === 'on-failure' && exitCode !== 0 && exitCode !== null);
152
+ if (shouldSave) {
153
+ // Move temp file to final location
154
+ try {
155
+ fs.renameSync(this.tempPath, this.finalPath);
156
+ finalPath = this.finalPath;
157
+ saved = true;
158
+ }
159
+ catch (err) {
160
+ // If rename fails (cross-device), copy and delete
161
+ fs.copyFileSync(this.tempPath, this.finalPath);
162
+ fs.unlinkSync(this.tempPath);
163
+ finalPath = this.finalPath;
164
+ saved = true;
165
+ }
166
+ // Write metadata sidecar file
167
+ const metaPath = this.finalPath.replace(/\.cast$/, '.meta.json');
168
+ const meta = {
169
+ exitCode,
170
+ durationMs,
171
+ startTime: this.startTime,
172
+ endTime,
173
+ bytesWritten: this.bytesWritten,
174
+ stopReason: finalStopReason,
175
+ };
176
+ fs.writeFileSync(metaPath, JSON.stringify(meta, null, 2));
177
+ }
178
+ else {
179
+ // Delete temp file
180
+ try {
181
+ fs.unlinkSync(this.tempPath);
182
+ }
183
+ catch {
184
+ // Ignore if already deleted
185
+ }
186
+ }
187
+ return {
188
+ id: this.id,
189
+ path: saved ? finalPath : '',
190
+ tempPath: this.tempPath,
191
+ startTime: this.startTime,
192
+ endTime,
193
+ durationMs,
194
+ bytesWritten: this.bytesWritten,
195
+ exitCode,
196
+ mode: this.mode,
197
+ saved,
198
+ stopReason: finalStopReason,
199
+ };
200
+ }
201
+ /**
202
+ * Check if recording is active
203
+ */
204
+ isActive() {
205
+ return this.writeStream !== null && !this.finalized;
206
+ }
207
+ /**
208
+ * Get the temp file path (for debugging/testing)
209
+ */
210
+ getTempPath() {
211
+ return this.tempPath;
212
+ }
213
+ /**
214
+ * Get the final file path
215
+ */
216
+ getFinalPath() {
217
+ return this.finalPath;
218
+ }
219
+ getElapsedSeconds() {
220
+ const now = Date.now();
221
+ if (this.lastEventTime === 0) {
222
+ // First event - just record the time
223
+ this.lastEventTime = now;
224
+ this.adjustedElapsed = (now - this.startTime) / 1000;
225
+ return this.adjustedElapsed;
226
+ }
227
+ // Calculate actual idle time since last event
228
+ const idleTime = (now - this.lastEventTime) / 1000;
229
+ // Cap idle time if limit is set and exceeded
230
+ if (this.idleTimeLimit > 0 && idleTime > this.idleTimeLimit) {
231
+ // Only add the capped idle time to our adjusted elapsed
232
+ this.adjustedElapsed += this.idleTimeLimit;
233
+ }
234
+ else {
235
+ // Add actual idle time
236
+ this.adjustedElapsed += idleTime;
237
+ }
238
+ this.lastEventTime = now;
239
+ return this.adjustedElapsed;
240
+ }
241
+ writeLine(line) {
242
+ if (this.writeStream) {
243
+ const data = line + '\n';
244
+ this.writeStream.write(data);
245
+ this.bytesWritten += Buffer.byteLength(data, 'utf8');
246
+ }
247
+ }
248
+ /**
249
+ * Clear all active timers
250
+ */
251
+ clearTimers() {
252
+ if (this.maxDurationTimer) {
253
+ clearTimeout(this.maxDurationTimer);
254
+ this.maxDurationTimer = null;
255
+ }
256
+ if (this.inactivityTimer) {
257
+ clearTimeout(this.inactivityTimer);
258
+ this.inactivityTimer = null;
259
+ }
260
+ }
261
+ /**
262
+ * Auto-finalize the recording due to timeout
263
+ * Called internally when max duration or inactivity timeout is reached
264
+ */
265
+ async _autoFinalize(reason) {
266
+ if (this.finalized) {
267
+ return;
268
+ }
269
+ this.stopReason = reason;
270
+ const metadata = await this.finalize(null, reason);
271
+ // Notify callback if registered
272
+ if (this.onAutoFinalize) {
273
+ this.onAutoFinalize(metadata);
274
+ }
275
+ }
276
+ /**
277
+ * Set callback for auto-finalize events (timeout triggered)
278
+ */
279
+ setOnAutoFinalize(callback) {
280
+ this.onAutoFinalize = callback;
281
+ }
282
+ /**
283
+ * Get timeout configuration and remaining time
284
+ */
285
+ getTimeoutInfo() {
286
+ const elapsedSeconds = this.startTime > 0 ? (Date.now() - this.startTime) / 1000 : 0;
287
+ const remainingMaxDuration = this.maxDuration > 0 ? Math.max(0, this.maxDuration - elapsedSeconds) : -1;
288
+ return {
289
+ maxDuration: this.maxDuration,
290
+ inactivityTimeout: this.inactivityTimeout,
291
+ elapsedSeconds,
292
+ remainingMaxDuration,
293
+ };
294
+ }
295
+ }
296
+ //# sourceMappingURL=recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recorder.js","sourceRoot":"","sources":["../../src/recording/recorder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Recording mode determines when recordings are saved
3
+ * - 'always': Save all recordings
4
+ * - 'on-failure': Only save recordings when the session exits with non-zero code
5
+ * - 'off': Disable recording
6
+ */
7
+ export type RecordingMode = 'always' | 'on-failure' | 'off';
8
+ /**
9
+ * Recording format (asciicast v2 is the only supported format)
10
+ */
11
+ export type RecordingFormat = 'v2';
12
+ /**
13
+ * Options for creating a recording
14
+ */
15
+ export interface RecordingOptions {
16
+ mode: RecordingMode;
17
+ format: RecordingFormat;
18
+ outputDir: string;
19
+ idleTimeLimit?: number;
20
+ maxDuration?: number;
21
+ inactivityTimeout?: number;
22
+ }
23
+ /**
24
+ * Asciicast v2 header (first line of the .cast file)
25
+ */
26
+ export interface AsciicastHeader {
27
+ version: 2;
28
+ width: number;
29
+ height: number;
30
+ timestamp: number;
31
+ env?: {
32
+ SHELL?: string;
33
+ TERM?: string;
34
+ };
35
+ title?: string;
36
+ }
37
+ /**
38
+ * Asciicast event types:
39
+ * - 'o': output (data written to terminal)
40
+ * - 'r': resize (terminal dimensions changed)
41
+ */
42
+ export type AsciicastOutputEvent = [number, 'o', string];
43
+ export type AsciicastResizeEvent = [number, 'r', string];
44
+ export type AsciicastEvent = AsciicastOutputEvent | AsciicastResizeEvent;
45
+ /**
46
+ * Reason why recording stopped
47
+ */
48
+ export type StopReason = 'explicit' | 'session_exit' | 'max_duration' | 'inactivity';
49
+ /**
50
+ * Metadata returned after finalizing a recording
51
+ */
52
+ export interface RecordingMetadata {
53
+ id: string;
54
+ path: string;
55
+ tempPath: string;
56
+ startTime: number;
57
+ endTime: number;
58
+ durationMs: number;
59
+ bytesWritten: number;
60
+ exitCode: number | null;
61
+ mode: RecordingMode;
62
+ saved: boolean;
63
+ stopReason?: StopReason;
64
+ }
65
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/recording/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,YAAY,GAAG,KAAK,CAAC;AAE5D;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC;AAEnC;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,CAAC,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE;QACJ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;AACzD,MAAM,MAAM,oBAAoB,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;AACzD,MAAM,MAAM,cAAc,GAAG,oBAAoB,GAAG,oBAAoB,CAAC;AAEzE;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,cAAc,GAAG,cAAc,GAAG,YAAY,CAAC;AAErF;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,aAAa,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/recording/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Sandbox filesystem permission configuration
3
+ */
4
+ export interface FilesystemPermissions {
5
+ /** Paths with full read/write access */
6
+ readWrite: string[];
7
+ /** Paths with read-only access */
8
+ readOnly: string[];
9
+ /** Paths completely blocked from access */
10
+ blocked: string[];
11
+ }
12
+ /**
13
+ * Sandbox network permission configuration
14
+ */
15
+ export interface NetworkPermissions {
16
+ /** Network access mode */
17
+ mode: "all" | "none" | "allowlist";
18
+ /** Allowed domains when mode is 'allowlist' */
19
+ allowedDomains?: string[];
20
+ }
21
+ /**
22
+ * Full sandbox permissions configuration
23
+ */
24
+ export interface SandboxPermissions {
25
+ filesystem: FilesystemPermissions;
26
+ network: NetworkPermissions;
27
+ }
28
+ /**
29
+ * Default permissions for sandbox mode
30
+ * Provides reasonable defaults while blocking sensitive directories
31
+ * Allows shell-related files to be writable for normal shell operation
32
+ */
33
+ export declare const DEFAULT_PERMISSIONS: SandboxPermissions;
34
+ /**
35
+ * Expand ~ to home directory in a path
36
+ */
37
+ export declare function expandPath(p: string): string;
38
+ /**
39
+ * Load sandbox configuration from a JSON file
40
+ */
41
+ export declare function loadConfigFromFile(filePath: string): SandboxPermissions;
42
+ /**
43
+ * Merge user selections with defaults
44
+ */
45
+ export declare function mergePermissions(base: SandboxPermissions, overrides: Partial<SandboxPermissions>): SandboxPermissions;
46
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/sandbox/config.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,wCAAwC;IACxC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,kCAAkC;IAClC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,2CAA2C;IAC3C,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,0BAA0B;IAC1B,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,WAAW,CAAC;IACnC,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,qBAAqB,CAAC;IAClC,OAAO,EAAE,kBAAkB,CAAC;CAC7B;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,kBA+CjC,CAAC;AAEF;;GAEG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAW5C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,CAiBvE;AA+DD;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,kBAAkB,EACxB,SAAS,EAAE,OAAO,CAAC,kBAAkB,CAAC,GACrC,kBAAkB,CAYpB"}
@@ -0,0 +1,144 @@
1
+ import * as fs from "fs";
2
+ import * as os from "os";
3
+ import * as path from "path";
4
+ /**
5
+ * Default permissions for sandbox mode
6
+ * Provides reasonable defaults while blocking sensitive directories
7
+ * Allows shell-related files to be writable for normal shell operation
8
+ */
9
+ export const DEFAULT_PERMISSIONS = {
10
+ filesystem: {
11
+ readWrite: [
12
+ // Core paths
13
+ ".", // Current working directory
14
+ "/tmp", // Temp files
15
+ // Shell operation
16
+ "~/.cache", // Cache files (oh-my-zsh, etc.)
17
+ "~/.local", // Local user data
18
+ "~/.zsh_history", // Zsh history
19
+ "~/.bash_history", // Bash history
20
+ "~/.node_repl_history", // Node REPL history
21
+ "~/.python_history", // Python history
22
+ // Package managers
23
+ "~/.npm",
24
+ "~/.yarn",
25
+ "~/.pnpm",
26
+ "~/.bun",
27
+ ],
28
+ readOnly: [
29
+ "~", // Home directory (general read access)
30
+ ],
31
+ blocked: [
32
+ // SSH/GPG
33
+ "~/.ssh",
34
+ "~/.gnupg",
35
+ // Cloud credentials
36
+ "~/.aws",
37
+ "~/.config/gcloud",
38
+ "~/.azure",
39
+ "~/.kube",
40
+ // CLI credentials
41
+ "~/.config/gh",
42
+ // Auth tokens
43
+ "~/.npmrc",
44
+ "~/.netrc",
45
+ "~/.docker/config.json",
46
+ ],
47
+ },
48
+ network: {
49
+ mode: "all",
50
+ },
51
+ };
52
+ /**
53
+ * Expand ~ to home directory in a path
54
+ */
55
+ export function expandPath(p) {
56
+ if (p.startsWith("~/")) {
57
+ return path.join(os.homedir(), p.slice(2));
58
+ }
59
+ if (p === "~") {
60
+ return os.homedir();
61
+ }
62
+ if (p === ".") {
63
+ return process.cwd();
64
+ }
65
+ return path.resolve(p);
66
+ }
67
+ /**
68
+ * Load sandbox configuration from a JSON file
69
+ */
70
+ export function loadConfigFromFile(filePath) {
71
+ const expandedPath = expandPath(filePath);
72
+ if (!fs.existsSync(expandedPath)) {
73
+ throw new Error(`Sandbox config file not found: ${expandedPath}`);
74
+ }
75
+ const content = fs.readFileSync(expandedPath, "utf-8");
76
+ let config;
77
+ try {
78
+ config = JSON.parse(content);
79
+ }
80
+ catch {
81
+ throw new Error(`Invalid JSON in sandbox config file: ${expandedPath}`);
82
+ }
83
+ return validateConfig(config);
84
+ }
85
+ /**
86
+ * Validate and normalize a config object
87
+ */
88
+ function validateConfig(config) {
89
+ if (typeof config !== "object" || config === null) {
90
+ throw new Error("Sandbox config must be an object");
91
+ }
92
+ const obj = config;
93
+ const result = {
94
+ filesystem: {
95
+ readWrite: [],
96
+ readOnly: [],
97
+ blocked: [],
98
+ },
99
+ network: {
100
+ mode: "all",
101
+ },
102
+ };
103
+ // Validate filesystem config
104
+ if (obj.filesystem && typeof obj.filesystem === "object") {
105
+ const fs = obj.filesystem;
106
+ if (Array.isArray(fs.readWrite)) {
107
+ result.filesystem.readWrite = fs.readWrite.filter((p) => typeof p === "string");
108
+ }
109
+ if (Array.isArray(fs.readOnly)) {
110
+ result.filesystem.readOnly = fs.readOnly.filter((p) => typeof p === "string");
111
+ }
112
+ if (Array.isArray(fs.blocked)) {
113
+ result.filesystem.blocked = fs.blocked.filter((p) => typeof p === "string");
114
+ }
115
+ }
116
+ // Validate network config
117
+ if (obj.network && typeof obj.network === "object") {
118
+ const net = obj.network;
119
+ if (net.mode === "all" || net.mode === "none" || net.mode === "allowlist") {
120
+ result.network.mode = net.mode;
121
+ }
122
+ if (Array.isArray(net.allowedDomains)) {
123
+ result.network.allowedDomains = net.allowedDomains.filter((d) => typeof d === "string");
124
+ }
125
+ }
126
+ return result;
127
+ }
128
+ /**
129
+ * Merge user selections with defaults
130
+ */
131
+ export function mergePermissions(base, overrides) {
132
+ return {
133
+ filesystem: {
134
+ readWrite: overrides.filesystem?.readWrite ?? base.filesystem.readWrite,
135
+ readOnly: overrides.filesystem?.readOnly ?? base.filesystem.readOnly,
136
+ blocked: overrides.filesystem?.blocked ?? base.filesystem.blocked,
137
+ },
138
+ network: {
139
+ mode: overrides.network?.mode ?? base.network.mode,
140
+ allowedDomains: overrides.network?.allowedDomains ?? base.network.allowedDomains,
141
+ },
142
+ };
143
+ }
144
+ //# sourceMappingURL=config.js.map