clipqa-mcp 0.2.1

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 (61) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +152 -0
  3. package/build/artifacts.d.ts +4 -0
  4. package/build/artifacts.d.ts.map +1 -0
  5. package/build/artifacts.js +24 -0
  6. package/build/artifacts.js.map +1 -0
  7. package/build/backends.d.ts +16 -0
  8. package/build/backends.d.ts.map +1 -0
  9. package/build/backends.js +48 -0
  10. package/build/backends.js.map +1 -0
  11. package/build/config.d.ts +7 -0
  12. package/build/config.d.ts.map +1 -0
  13. package/build/config.js +15 -0
  14. package/build/config.js.map +1 -0
  15. package/build/index.d.ts +3 -0
  16. package/build/index.d.ts.map +1 -0
  17. package/build/index.js +25 -0
  18. package/build/index.js.map +1 -0
  19. package/build/media.d.ts +13 -0
  20. package/build/media.d.ts.map +1 -0
  21. package/build/media.js +139 -0
  22. package/build/media.js.map +1 -0
  23. package/build/process-runner.d.ts +9 -0
  24. package/build/process-runner.d.ts.map +1 -0
  25. package/build/process-runner.js +25 -0
  26. package/build/process-runner.js.map +1 -0
  27. package/build/recorder.d.ts +42 -0
  28. package/build/recorder.d.ts.map +1 -0
  29. package/build/recorder.js +272 -0
  30. package/build/recorder.js.map +1 -0
  31. package/build/replay.d.ts +10 -0
  32. package/build/replay.d.ts.map +1 -0
  33. package/build/replay.js +39 -0
  34. package/build/replay.js.map +1 -0
  35. package/build/sampling.d.ts +13 -0
  36. package/build/sampling.d.ts.map +1 -0
  37. package/build/sampling.js +52 -0
  38. package/build/sampling.js.map +1 -0
  39. package/build/server.d.ts +5 -0
  40. package/build/server.d.ts.map +1 -0
  41. package/build/server.js +360 -0
  42. package/build/server.js.map +1 -0
  43. package/build/session-store.d.ts +16 -0
  44. package/build/session-store.d.ts.map +1 -0
  45. package/build/session-store.js +93 -0
  46. package/build/session-store.js.map +1 -0
  47. package/build/types.d.ts +46 -0
  48. package/build/types.d.ts.map +1 -0
  49. package/build/types.js +2 -0
  50. package/build/types.js.map +1 -0
  51. package/build/visual.d.ts +62 -0
  52. package/build/visual.d.ts.map +1 -0
  53. package/build/visual.js +145 -0
  54. package/build/visual.js.map +1 -0
  55. package/build/windows.d.ts +4 -0
  56. package/build/windows.d.ts.map +1 -0
  57. package/build/windows.js +60 -0
  58. package/build/windows.js.map +1 -0
  59. package/docs/assets/banner.png +0 -0
  60. package/package.json +67 -0
  61. package/scripts/install-wgc.ps1 +40 -0
@@ -0,0 +1,360 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { randomUUID } from "node:crypto";
4
+ import { pathToFileURL } from "node:url";
5
+ import { McpServer } from "@modelcontextprotocol/server";
6
+ import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
7
+ import * as z from "zod/v4";
8
+ import { MediaProcessor } from "./media.js";
9
+ import { NodeCommandRunner } from "./process-runner.js";
10
+ import { Recorder } from "./recorder.js";
11
+ import { SessionStore } from "./session-store.js";
12
+ import { chooseBoundedInspectionTimestamps } from "./sampling.js";
13
+ import { listWindows } from "./windows.js";
14
+ import { capabilities, listScreens } from "./backends.js";
15
+ import { compareVideos, indexVideo } from "./visual.js";
16
+ import { directoryBytes, deleteSession } from "./artifacts.js";
17
+ const textResult = (value) => ({
18
+ content: [{ type: "text", text: JSON.stringify(value, null, 2) }],
19
+ });
20
+ const errorResult = (error) => ({
21
+ isError: true,
22
+ content: [{ type: "text", text: error instanceof Error ? error.message : String(error) }],
23
+ });
24
+ export async function createServer(config) {
25
+ const runner = new NodeCommandRunner();
26
+ const store = new SessionStore(config.dataDir);
27
+ await store.initialize();
28
+ await store.recoverInterrupted();
29
+ const recorder = new Recorder(store, config.ffmpegPath, runner, config.ffprobePath);
30
+ const media = new MediaProcessor(config.ffmpegPath, config.ffprobePath, runner);
31
+ const server = new McpServer({ name: "clipqa-mcp", version: "0.2.1" });
32
+ const close = server.close.bind(server);
33
+ server.close = async () => { await recorder.shutdown(); await close(); };
34
+ server.server.onclose = () => { void recorder.shutdown(); };
35
+ server.registerTool("capture_status", {
36
+ description: "Check installed capture backends and platform requirements before recording.", inputSchema: z.object({}),
37
+ }, async () => { try {
38
+ return textResult(await capabilities(config.ffmpegPath, runner));
39
+ }
40
+ catch (e) {
41
+ return errorResult(e);
42
+ } });
43
+ server.registerTool("list_sources", {
44
+ description: "List recordable windows on Windows/X11 or display sources on macOS. macOS capture includes the selected display, not just one app.", inputSchema: z.object({}),
45
+ }, async () => { try {
46
+ return textResult(process.platform === "darwin" ? await listScreens(config.ffmpegPath, runner) : await listWindows(runner));
47
+ }
48
+ catch (e) {
49
+ return errorResult(e);
50
+ } });
51
+ const videoLink = (file) => ({ type: "resource_link", uri: pathToFileURL(file).href, name: path.basename(file), mimeType: { ".mp4": "video/mp4", ".m4v": "video/mp4", ".mov": "video/quicktime", ".webm": "video/webm", ".mkv": "video/x-matroska", ".avi": "video/x-msvideo" }[path.extname(file).toLowerCase()] ?? "application/octet-stream", description: "Local video. Clients that support local media can display this file inline." });
52
+ server.registerTool("recording_progress", {
53
+ description: "Show recording status and a screenshot from the latest completed video segment. Optionally return a playable local preview without stopping recording. Live previews lag by about two seconds; saved previews persist until cleanup.",
54
+ inputSchema: z.object({ sessionId: z.string().uuid(), includeVideo: z.boolean().default(false), lastSeconds: z.number().int().min(1).max(30).default(5) }),
55
+ }, async ({ sessionId, includeVideo, lastSeconds }) => {
56
+ try {
57
+ const session = await store.read(sessionId);
58
+ const preview = await recorder.preview(sessionId, includeVideo ? lastSeconds : 1);
59
+ const elapsedSeconds = Math.max(0, (Date.parse(session.stoppedAt ?? new Date().toISOString()) - Date.parse(session.startedAt)) / 1000);
60
+ const status = { sessionId, state: session.state, elapsedSeconds, maxSeconds: session.maxSeconds, bufferSeconds: session.bufferSeconds, bytesOnDisk: await directoryBytes(store.sessionDir(sessionId)), previewReady: Boolean(preview), note: "Saved recordings, previews and reports remain local until delete_session or cleanup_sessions removes them." };
61
+ if (!preview)
62
+ return textResult({ ...status, note: "No completed video segment yet. Retry in about two seconds." });
63
+ const duration = await media.duration(preview.videoPath);
64
+ const timestamp = Math.max(0, Math.floor((duration - 1 / await media.frameRate(preview.videoPath)) * 1000) / 1000);
65
+ const screenshotPath = path.join(path.dirname(preview.videoPath), `progress-${randomUUID()}.jpg`);
66
+ await media.extractFrame(preview.videoPath, timestamp, screenshotPath);
67
+ const data = (await fs.readFile(screenshotPath)).toString("base64");
68
+ return { content: [...textResult({ ...status, screenshotPath, screenshotRecordingSeconds: preview.offset + timestamp, ...(includeVideo ? { videoPath: preview.videoPath, videoDuration: duration, videoStartRecordingSeconds: preview.offset } : {}) }).content, { type: "image", mimeType: "image/jpeg", data }, ...(includeVideo ? [videoLink(preview.videoPath)] : [])] };
69
+ }
70
+ catch (error) {
71
+ return errorResult(error);
72
+ }
73
+ });
74
+ server.registerTool("get_clip", {
75
+ description: "Return the local path and video resource link for a saved recording. For an active recording, request recording_progress with includeVideo instead. Ask the client to render the absolute path inline when supported.",
76
+ inputSchema: z.object({ sessionId: z.string().uuid() }),
77
+ }, async ({ sessionId }) => {
78
+ try {
79
+ const session = await store.read(sessionId);
80
+ if (session.state !== "stopped")
81
+ throw new Error("The recording must be stopped successfully before accessing its saved video.");
82
+ return { content: [...textResult({ sessionId, videoPath: session.videoPath, duration: await media.duration(session.videoPath), bytes: (await fs.stat(session.videoPath)).size, retention: "Kept until explicitly deleted." }).content, videoLink(session.videoPath)] };
83
+ }
84
+ catch (error) {
85
+ return errorResult(error);
86
+ }
87
+ });
88
+ server.registerTool("delete_session", {
89
+ description: "Permanently delete one stopped session and its video, screenshots, previews, indexes and reports. Use only when the user is done with the artifacts.",
90
+ inputSchema: z.object({ sessionId: z.string().uuid() }),
91
+ annotations: { destructiveHint: true },
92
+ }, async ({ sessionId }) => { try {
93
+ await deleteSession(store, sessionId);
94
+ return textResult({ deleted: sessionId });
95
+ }
96
+ catch (error) {
97
+ return errorResult(error);
98
+ } });
99
+ server.registerTool("cleanup_sessions", {
100
+ description: "Preview or delete completed sessions older than a chosen age. Defaults to dryRun=true so retained videos can be reviewed before deletion. Active recordings are excluded.",
101
+ inputSchema: z.object({ olderThanHours: z.number().min(1).max(87600).default(24), dryRun: z.boolean().default(true) }),
102
+ annotations: { destructiveHint: true },
103
+ }, async ({ olderThanHours, dryRun }) => {
104
+ try {
105
+ const cutoff = Date.now() - olderThanHours * 3600000;
106
+ const sessions = (await store.list()).filter(s => s.state !== "recording" && Date.parse(s.stoppedAt ?? s.startedAt) < cutoff);
107
+ const selected = [];
108
+ for (const session of sessions) {
109
+ const bytes = await directoryBytes(store.sessionDir(session.id));
110
+ if (!dryRun)
111
+ await deleteSession(store, session.id);
112
+ selected.push({ sessionId: session.id, bytes });
113
+ }
114
+ return textResult({ dryRun, sessions: selected, totalBytes: selected.reduce((sum, s) => sum + s.bytes, 0) });
115
+ }
116
+ catch (error) {
117
+ return errorResult(error);
118
+ }
119
+ });
120
+ server.registerTool("list_windows", {
121
+ description: "List Windows or X11 application windows that can be recorded. On macOS use list_sources.",
122
+ inputSchema: z.object({}),
123
+ }, async () => {
124
+ try {
125
+ return textResult(await listWindows(runner));
126
+ }
127
+ catch (error) {
128
+ return errorResult(error);
129
+ }
130
+ });
131
+ server.registerTool("start_recording", {
132
+ description: "Record a selected Windows/X11 window or explicitly selected macOS display. Optional bufferSeconds keeps only recent video. No input control or audio.",
133
+ inputSchema: z.object({
134
+ windowTitle: z.string().min(1).optional(),
135
+ hwnd: z.string().regex(/^\d+$/).optional(),
136
+ windowId: z.string().regex(/^(0x[\da-fA-F]+|[1-9]\d*)$/).optional(),
137
+ display: z.string().max(200).optional(),
138
+ screenIndex: z.number().int().min(0).optional(),
139
+ backend: z.enum(["auto", "gfxcapture", "gdigrab", "x11grab", "avfoundation"]).default("auto"),
140
+ bufferSeconds: z.number().int().min(5).max(600).optional(),
141
+ maxWidth: z.number().int().min(320).max(3840).optional(),
142
+ fps: z.number().int().min(1).max(60).default(30),
143
+ maxSeconds: z.number().int().min(5).max(3600).default(120),
144
+ drawMouse: z.boolean().default(false),
145
+ encoder: z.enum(["auto", "libx264", "h264_nvenc", "h264_qsv", "h264_amf"]).default("auto"),
146
+ }).refine((value) => Boolean(value.windowTitle || value.hwnd || value.windowId || value.screenIndex !== undefined), {
147
+ message: "Provide windowTitle, hwnd, windowId, or screenIndex.",
148
+ }),
149
+ }, async ({ windowTitle, hwnd, windowId, display, screenIndex, backend, bufferSeconds, maxWidth, fps, maxSeconds, drawMouse, encoder }) => {
150
+ try {
151
+ const target = {
152
+ ...(windowTitle ? { title: windowTitle } : {}),
153
+ ...(hwnd ? { hwnd } : {}),
154
+ ...(windowId ? { windowId } : {}),
155
+ ...(display ? { display } : {}),
156
+ ...(screenIndex !== undefined ? { screenIndex } : {}),
157
+ };
158
+ const session = await recorder.start({ target, fps, maxSeconds, drawMouse, encoder, backend, ...(bufferSeconds ? { bufferSeconds } : {}), ...(maxWidth ? { maxWidth } : {}) });
159
+ return textResult({
160
+ ...session,
161
+ note: "Recording runs in a hidden background process and does not control the mouse or keyboard.",
162
+ });
163
+ }
164
+ catch (error) {
165
+ return errorResult(error);
166
+ }
167
+ });
168
+ server.registerTool("mark_event", {
169
+ description: "Add an app-agnostic event or log entry. Supply timestampSeconds for recorded/imported clips; omitted timestamps use elapsed recording time.",
170
+ inputSchema: z.object({
171
+ sessionId: z.string().uuid(),
172
+ label: z.string().min(1).max(500),
173
+ kind: z.enum(["action", "assertion", "error", "note"]).default("note"),
174
+ data: z.record(z.string(), z.unknown()).optional(),
175
+ timestampSeconds: z.number().min(0).optional(),
176
+ }),
177
+ }, async ({ sessionId, label, kind, data, timestampSeconds }) => {
178
+ try {
179
+ const before = await store.read(sessionId);
180
+ if (before.state === "recording" && before.ownerPid && before.ownerPid !== process.pid)
181
+ throw new Error("Annotate active recordings through their owning MCP process.");
182
+ if (before.state !== "recording") {
183
+ if (timestampSeconds === undefined)
184
+ throw new Error("Completed clips require timestampSeconds.");
185
+ if (timestampSeconds >= await media.duration(before.videoPath))
186
+ throw new Error("Event timestamp must be inside the clip.");
187
+ }
188
+ const session = await store.update(sessionId, (current) => {
189
+ if (current.state !== before.state)
190
+ throw new Error("Recording state changed while adding the event. Retry with a timestamp relative to the saved clip.");
191
+ if (current.events.length >= 10000)
192
+ throw new Error("Session event limit reached (10,000).");
193
+ const timestampMs = timestampSeconds === undefined ? Math.max(0, Date.now() - Date.parse(current.startedAt)) : timestampSeconds * 1000;
194
+ return {
195
+ ...current,
196
+ events: [...current.events, { timestampMs, label, kind, ...(data ? { data } : {}) }],
197
+ };
198
+ });
199
+ return textResult(session.events.at(-1));
200
+ }
201
+ catch (error) {
202
+ return errorResult(error);
203
+ }
204
+ });
205
+ server.registerTool("stop_recording", {
206
+ description: "Stop recording and finalize the clip. In rolling mode saves only the last bufferSeconds and rebases retained event timestamps.",
207
+ inputSchema: z.object({ sessionId: z.string().uuid() }),
208
+ }, async ({ sessionId }) => {
209
+ try {
210
+ return textResult(await recorder.stop(sessionId));
211
+ }
212
+ catch (error) {
213
+ return errorResult(error);
214
+ }
215
+ });
216
+ server.registerTool("import_clip", {
217
+ description: "Copy a local video into a QA session for inspection and comparison on any platform. Does not record the screen.",
218
+ inputSchema: z.object({ filePath: z.string().min(1), label: z.string().max(200).default("Imported clip") }),
219
+ }, async ({ filePath, label }) => {
220
+ try {
221
+ if (!path.isAbsolute(filePath))
222
+ throw new Error("Provide an absolute local video path.");
223
+ const stat = await fs.stat(filePath);
224
+ if (!stat.isFile() || stat.size > 2 * 1024 ** 3)
225
+ throw new Error("Import a regular video file up to 2 GiB.");
226
+ const duration = await media.duration(filePath);
227
+ if (duration <= 0 || duration > 3600)
228
+ throw new Error("Import a clip up to one hour long.");
229
+ const extension = path.extname(filePath).toLowerCase();
230
+ const id = randomUUID(), videoPath = path.join(store.sessionDir(id), `recording${/^\.[a-z0-9]{1,8}$/.test(extension) ? extension : ".bin"}`);
231
+ const session = { id, state: "stopped", target: { title: label }, startedAt: new Date().toISOString(), stoppedAt: new Date().toISOString(), fps: 0, encoder: "imported", drawMouse: false, maxSeconds: duration, videoPath, events: [] };
232
+ await store.create(session);
233
+ try {
234
+ await fs.copyFile(filePath, videoPath);
235
+ }
236
+ catch (error) {
237
+ await store.update(id, s => ({ ...s, state: "failed", error: String(error) }));
238
+ throw error;
239
+ }
240
+ return textResult({ ...session, duration, note: "Imported video may contain audio or other content from its original recorder. ClipQA image tools return visual frames only." });
241
+ }
242
+ catch (error) {
243
+ return errorResult(error);
244
+ }
245
+ });
246
+ const region = z.object({ x: z.number().min(0).max(1), y: z.number().min(0).max(1), width: z.number().positive().max(1), height: z.number().positive().max(1) }).refine(r => r.x + r.width <= 1 && r.y + r.height <= 1, "Regions must fit inside the frame.");
247
+ server.registerTool("compare_clips", {
248
+ description: "Compare completed before/after clips at aligned timestamps. Writes local HTML/JSON reports with paired frames and difference maps. Changes are review candidates, not automatic bug diagnoses.",
249
+ inputSchema: z.object({ beforeSessionId: z.string().uuid(), afterSessionId: z.string().uuid(), beforeStart: z.number().min(0).default(0), afterStart: z.number().min(0).default(0), seconds: z.number().positive().max(600).optional(), samples: z.number().int().min(2).max(60).default(12), threshold: z.number().positive().max(1).default(.08), ignoreRegions: z.array(region).max(20).default([]) }),
250
+ }, async ({ beforeSessionId, afterSessionId, beforeStart, afterStart, seconds, samples, threshold, ignoreRegions }) => {
251
+ try {
252
+ const [before, after] = await Promise.all([store.read(beforeSessionId), store.read(afterSessionId)]);
253
+ if (before.state !== "stopped" || after.state !== "stopped")
254
+ throw new Error("Both comparison sessions must be completed.");
255
+ const [a, b] = await Promise.all([media.duration(before.videoPath), media.duration(after.videoPath)]);
256
+ const duration = Math.min(seconds ?? 600, a - beforeStart, b - afterStart);
257
+ if (duration <= 0)
258
+ throw new Error("The requested comparison ranges do not contain video.");
259
+ const directory = path.join(store.sessionDir(afterSessionId), "comparisons", randomUUID());
260
+ const report = await compareVideos(media, before.videoPath, after.videoPath, directory, { beforeStart, afterStart, seconds: duration, samples, threshold, ignore: ignoreRegions });
261
+ return { content: [...textResult(report).content, { type: "text", text: "Highest-scoring sample: before | after | difference. Timestamps are in previewSample." }, { type: "image", mimeType: "image/jpeg", data: (await fs.readFile(report.previewPath)).toString("base64") }] };
262
+ }
263
+ catch (error) {
264
+ return errorResult(error);
265
+ }
266
+ });
267
+ server.registerTool("list_sessions", {
268
+ description: "List recorded QA sessions and their status.",
269
+ inputSchema: z.object({ limit: z.number().int().min(1).max(100).default(20) }),
270
+ }, async ({ limit }) => textResult((await store.list()).slice(0, limit)));
271
+ server.registerTool("inspect_clip", {
272
+ description: "Create and return a timestamped contact sheet for a completed recording.",
273
+ inputSchema: z.object({
274
+ sessionId: z.string().uuid(),
275
+ startSeconds: z.number().min(0).default(0),
276
+ endSeconds: z.number().positive().optional(),
277
+ samples: z.number().int().min(2).max(24).default(12),
278
+ indexFps: z.number().int().min(1).max(60).default(15),
279
+ }),
280
+ }, async ({ sessionId, startSeconds, endSeconds, samples, indexFps }) => {
281
+ try {
282
+ const session = await store.read(sessionId);
283
+ if (session.state === "recording")
284
+ throw new Error("Stop the recording before inspecting it.");
285
+ const duration = await media.duration(session.videoPath);
286
+ const lastFrame = Math.max(0, Math.floor((duration - 1 / await media.frameRate(session.videoPath)) * 1000) / 1000);
287
+ const end = Math.min(endSeconds ?? lastFrame, lastFrame);
288
+ if (startSeconds >= end)
289
+ throw new Error("startSeconds must be before the end of the clip.");
290
+ const index = await indexVideo(config.ffmpegPath, session.videoPath, startSeconds, end, indexFps);
291
+ const visualChanges = index.changes.map(change => change.timestamp);
292
+ const eventTimes = session.events.map((event) => event.timestampMs / 1000);
293
+ const timestamps = chooseBoundedInspectionTimestamps({
294
+ startSeconds,
295
+ endSeconds: end,
296
+ eventTimesSeconds: eventTimes,
297
+ visualChangeTimesSeconds: visualChanges,
298
+ }, samples);
299
+ const outputPath = path.join(store.sessionDir(sessionId), "inspections", randomUUID(), "overview.jpg");
300
+ await media.createContactSheet(session.videoPath, outputPath, timestamps);
301
+ const data = await fs.readFile(outputPath);
302
+ return {
303
+ content: [
304
+ {
305
+ type: "text",
306
+ text: JSON.stringify({
307
+ sessionId,
308
+ duration,
309
+ timestamps,
310
+ visualChanges,
311
+ eventTimes,
312
+ outputPath,
313
+ index,
314
+ }, null, 2),
315
+ },
316
+ { type: "image", data: data.toString("base64"), mimeType: "image/jpeg" },
317
+ ],
318
+ };
319
+ }
320
+ catch (error) {
321
+ return errorResult(error);
322
+ }
323
+ });
324
+ server.registerTool("get_frames", {
325
+ description: "Return frames from exact timestamps, resized to maxWidth (default 1280).",
326
+ inputSchema: z.object({
327
+ sessionId: z.string().uuid(),
328
+ timestamps: z.array(z.number().min(0)).min(1).max(16),
329
+ maxWidth: z.number().int().min(320).max(3840).default(1280),
330
+ }),
331
+ }, async ({ sessionId, timestamps, maxWidth }) => {
332
+ try {
333
+ const session = await store.read(sessionId);
334
+ if (session.state === "recording")
335
+ throw new Error("Stop the recording before extracting frames.");
336
+ const duration = await media.duration(session.videoPath);
337
+ const content = [{ type: "text", text: JSON.stringify({ sessionId, duration, timestamps }, null, 2) }];
338
+ const requestId = randomUUID();
339
+ for (const timestamp of timestamps) {
340
+ if (timestamp >= duration)
341
+ throw new Error(`Timestamp ${timestamp}s must be before clip duration ${duration}s.`);
342
+ const file = path.join(store.sessionDir(sessionId), "frames", requestId, `${Math.round(timestamp * 1000)}ms.jpg`);
343
+ await media.extractFrame(session.videoPath, timestamp, file, maxWidth);
344
+ const data = await fs.readFile(file);
345
+ content.push({ type: "text", text: `Frame at ${timestamp.toFixed(3)} seconds` });
346
+ content.push({ type: "image", data: data.toString("base64"), mimeType: "image/jpeg" });
347
+ }
348
+ return { content };
349
+ }
350
+ catch (error) {
351
+ return errorResult(error);
352
+ }
353
+ });
354
+ return server;
355
+ }
356
+ export async function serve(config) {
357
+ const server = await createServer(config);
358
+ await server.connect(new StdioServerTransport());
359
+ }
360
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { RecordingSession } from "./types.js";
2
+ export declare class SessionStore {
3
+ readonly rootDir: string;
4
+ private readonly updates;
5
+ constructor(rootDir: string);
6
+ sessionDir(id: string): string;
7
+ manifestPath(id: string): string;
8
+ initialize(): Promise<void>;
9
+ create(session: RecordingSession): Promise<void>;
10
+ read(id: string): Promise<RecordingSession>;
11
+ write(session: RecordingSession): Promise<void>;
12
+ update(id: string, change: (session: RecordingSession) => RecordingSession): Promise<RecordingSession>;
13
+ list(): Promise<RecordingSession[]>;
14
+ recoverInterrupted(): Promise<number>;
15
+ }
16
+ //# sourceMappingURL=session-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-store.d.ts","sourceRoot":"","sources":["../src/session-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,qBAAa,YAAY;IAEX,QAAQ,CAAC,OAAO,EAAE,MAAM;IADpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAC/D,YAAqB,OAAO,EAAE,MAAM,EAAI;IAExC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAG7B;IAED,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE/B;IAEK,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAEhC;IAEK,MAAM,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrD;IAEK,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAGhD;IAEK,KAAK,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAKpD;IAEK,MAAM,CACV,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,gBAAgB,GACtD,OAAO,CAAC,gBAAgB,CAAC,CAS3B;IAEK,IAAI,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAiBxC;IAEK,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAmB1C;CACF"}
@@ -0,0 +1,93 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ export class SessionStore {
4
+ rootDir;
5
+ updates = new Map();
6
+ constructor(rootDir) {
7
+ this.rootDir = rootDir;
8
+ }
9
+ sessionDir(id) {
10
+ if (!/^[a-zA-Z0-9-]+$/.test(id))
11
+ throw new Error("Invalid session id.");
12
+ return path.join(this.rootDir, id);
13
+ }
14
+ manifestPath(id) {
15
+ return path.join(this.sessionDir(id), "session.json");
16
+ }
17
+ async initialize() {
18
+ await fs.mkdir(this.rootDir, { recursive: true });
19
+ }
20
+ async create(session) {
21
+ await fs.mkdir(this.sessionDir(session.id), { recursive: false });
22
+ await this.write(session);
23
+ }
24
+ async read(id) {
25
+ const raw = await fs.readFile(this.manifestPath(id), "utf8");
26
+ return JSON.parse(raw);
27
+ }
28
+ async write(session) {
29
+ const target = this.manifestPath(session.id);
30
+ const temporary = `${target}.tmp`;
31
+ await fs.writeFile(temporary, `${JSON.stringify(session, null, 2)}\n`, "utf8");
32
+ await fs.rename(temporary, target);
33
+ }
34
+ async update(id, change) {
35
+ const pending = (this.updates.get(id) ?? Promise.resolve()).catch(() => undefined).then(async () => {
36
+ const next = change(await this.read(id));
37
+ await this.write(next);
38
+ return next;
39
+ });
40
+ this.updates.set(id, pending);
41
+ try {
42
+ return await pending;
43
+ }
44
+ finally {
45
+ if (this.updates.get(id) === pending)
46
+ this.updates.delete(id);
47
+ }
48
+ }
49
+ async list() {
50
+ await this.initialize();
51
+ const entries = await fs.readdir(this.rootDir, { withFileTypes: true });
52
+ const sessions = await Promise.all(entries
53
+ .filter((entry) => entry.isDirectory())
54
+ .map(async (entry) => {
55
+ try {
56
+ return await this.read(entry.name);
57
+ }
58
+ catch {
59
+ return undefined;
60
+ }
61
+ }));
62
+ return sessions
63
+ .filter((session) => Boolean(session))
64
+ .sort((a, b) => b.startedAt.localeCompare(a.startedAt));
65
+ }
66
+ async recoverInterrupted() {
67
+ const sessions = await this.list();
68
+ let recovered = 0;
69
+ for (const session of sessions) {
70
+ if (session.state === "recording") {
71
+ if (session.ownerPid) {
72
+ try {
73
+ process.kill(session.ownerPid, 0);
74
+ continue;
75
+ }
76
+ catch (error) {
77
+ if (error.code === "EPERM")
78
+ continue;
79
+ }
80
+ }
81
+ await this.write({
82
+ ...session,
83
+ state: "interrupted",
84
+ stoppedAt: new Date().toISOString(),
85
+ error: "The MCP process ended before the recording was stopped.",
86
+ });
87
+ recovered += 1;
88
+ }
89
+ }
90
+ return recovered;
91
+ }
92
+ }
93
+ //# sourceMappingURL=session-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-store.js","sourceRoot":"","sources":["../src/session-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ export type SessionState = "recording" | "stopped" | "failed" | "interrupted";
2
+ export interface CaptureTarget {
3
+ title?: string;
4
+ hwnd?: string;
5
+ windowId?: string;
6
+ display?: string;
7
+ screenIndex?: number;
8
+ }
9
+ export interface QaEvent {
10
+ timestampMs: number;
11
+ label: string;
12
+ kind: "action" | "assertion" | "error" | "note";
13
+ data?: Record<string, unknown>;
14
+ }
15
+ export interface RecordingSession {
16
+ id: string;
17
+ state: SessionState;
18
+ target: CaptureTarget;
19
+ startedAt: string;
20
+ stoppedAt?: string;
21
+ fps: number;
22
+ encoder: string;
23
+ drawMouse: boolean;
24
+ maxSeconds: number;
25
+ videoPath: string;
26
+ events: QaEvent[];
27
+ error?: string;
28
+ backend?: string;
29
+ bufferSeconds?: number;
30
+ timelineOffsetSeconds?: number;
31
+ warnings?: string[];
32
+ ownerPid?: number;
33
+ }
34
+ export interface WindowInfo {
35
+ title: string;
36
+ hwnd: string;
37
+ process: string;
38
+ pid: number;
39
+ minimized?: boolean;
40
+ }
41
+ export interface ProcessResult {
42
+ code: number;
43
+ stdout: string;
44
+ stderr: string;
45
+ }
46
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,aAAa,CAAC;AAE9E,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,OAAO;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,aAAa,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB"}
package/build/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}