@wingman-ai/gateway 0.5.4 → 0.6.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 (41) hide show
  1. package/dist/agent/backend/filtered-backend.cjs +130 -0
  2. package/dist/agent/backend/filtered-backend.d.ts +10 -0
  3. package/dist/agent/backend/filtered-backend.js +87 -0
  4. package/dist/agent/middleware/additional-messages.cjs +4 -1
  5. package/dist/agent/middleware/additional-messages.js +4 -1
  6. package/dist/agent/tools/browser_control.cjs +1 -1
  7. package/dist/agent/tools/browser_control.js +1 -1
  8. package/dist/agent/tools/browser_runtime.cjs +184 -15
  9. package/dist/agent/tools/browser_runtime.d.ts +59 -2
  10. package/dist/agent/tools/browser_runtime.js +182 -16
  11. package/dist/agent/tools/browser_session.cjs +44 -8
  12. package/dist/agent/tools/browser_session.d.ts +68 -123
  13. package/dist/agent/tools/browser_session.js +45 -9
  14. package/dist/agent/tools/browser_session_manager.cjs +15 -4
  15. package/dist/agent/tools/browser_session_manager.d.ts +8 -2
  16. package/dist/agent/tools/browser_session_manager.js +15 -4
  17. package/dist/cli/commands/init.cjs +80 -102
  18. package/dist/cli/commands/init.js +80 -102
  19. package/dist/cli/core/agentInvoker.cjs +4 -2
  20. package/dist/cli/core/agentInvoker.js +4 -2
  21. package/dist/cli/core/sessionManager.cjs +208 -41
  22. package/dist/cli/core/sessionManager.d.ts +20 -0
  23. package/dist/cli/core/sessionManager.js +208 -41
  24. package/dist/cli/index.cjs +16 -1
  25. package/dist/cli/index.js +16 -1
  26. package/dist/cli/services/updateCheck.cjs +212 -0
  27. package/dist/cli/services/updateCheck.d.ts +26 -0
  28. package/dist/cli/services/updateCheck.js +166 -0
  29. package/dist/gateway/server.cjs +7 -0
  30. package/dist/gateway/server.js +7 -0
  31. package/dist/webui/assets/index-D3x3G75t.css +11 -0
  32. package/dist/webui/assets/index-UpMmcU1f.js +215 -0
  33. package/dist/webui/index.html +2 -2
  34. package/package.json +3 -3
  35. package/templates/agents/README.md +1 -0
  36. package/templates/agents/game-dev/agent.md +1 -0
  37. package/templates/agents/main/agent.md +3 -3
  38. package/templates/agents/researcher/agent.md +5 -5
  39. package/dist/webui/assets/index-XrEnkZiq.css +0 -11
  40. package/dist/webui/assets/index-mDs6HbKM.js +0 -215
  41. package/dist/webui/assets/wingman_logo-Cogyt3qm.webp +0 -0
@@ -33,10 +33,11 @@ __webpack_require__.d(__webpack_exports__, {
33
33
  BrowserControlInputSchema: ()=>BrowserControlInputSchema,
34
34
  DEFAULT_ACTION_TIMEOUT_MS: ()=>DEFAULT_ACTION_TIMEOUT_MS,
35
35
  createBrowserDependencies: ()=>createBrowserDependencies,
36
+ BrowserSessionVideoRecordingSchema: ()=>BrowserSessionVideoRecordingSchema,
36
37
  executeBrowserSessionRuntime: ()=>executeBrowserSessionRuntime,
37
- closeBrowserSessionRuntime: ()=>closeBrowserSessionRuntime,
38
- BrowserActionSchema: ()=>BrowserActionSchema,
39
38
  clearStaleDevtoolsArtifacts: ()=>clearStaleDevtoolsArtifacts,
39
+ BrowserActionSchema: ()=>BrowserActionSchema,
40
+ closeBrowserSessionRuntime: ()=>closeBrowserSessionRuntime,
40
41
  BrowserTransportPreferenceSchema: ()=>BrowserTransportPreferenceSchema
41
42
  });
42
43
  const external_node_child_process_namespaceObject = require("node:child_process");
@@ -59,6 +60,7 @@ const MAX_EXTRACT_CHARS = 1000000;
59
60
  const MAX_ACTIONS = 25;
60
61
  const DEFAULT_PROFILES_ROOT = ".wingman/browser-profiles";
61
62
  const DEFAULT_EXTENSIONS_ROOT = ".wingman/browser-extensions";
63
+ const DEFAULT_BROWSER_VIDEO_ROOT = ".wingman/browser/videos";
62
64
  const DEFAULT_BUNDLED_EXTENSION_ID = "wingman";
63
65
  const BUNDLED_EXTENSION_RELATIVE_PATH = "../../../extensions/wingman-browser-extension";
64
66
  const PERSISTENT_PROFILE_IGNORE_DEFAULT_ARGS = [
@@ -83,6 +85,17 @@ const BrowserTransportPreferenceSchema = external_zod_namespaceObject["enum"]([
83
85
  "playwright",
84
86
  "relay"
85
87
  ]);
88
+ const BrowserVideoSizeSchema = external_zod_namespaceObject.object({
89
+ width: external_zod_namespaceObject.number().int().min(1).max(3840).describe("Video width in pixels"),
90
+ height: external_zod_namespaceObject.number().int().min(1).max(3840).describe("Video height in pixels")
91
+ });
92
+ const BrowserSessionVideoRecordingSchema = external_zod_namespaceObject.union([
93
+ external_zod_namespaceObject.boolean(),
94
+ external_zod_namespaceObject.object({
95
+ dir: external_zod_namespaceObject.string().min(1).optional().describe("Relative output directory within the workspace for videos"),
96
+ size: BrowserVideoSizeSchema.optional().describe("Optional recorded video dimensions")
97
+ })
98
+ ]);
86
99
  const NavigateActionSchema = external_zod_namespaceObject.object({
87
100
  type: external_zod_namespaceObject.literal("navigate"),
88
101
  url: external_zod_namespaceObject.string().url().describe("Destination URL")
@@ -516,14 +529,22 @@ function selectContext(contexts) {
516
529
  ].reverse();
517
530
  return reversed.find((candidate)=>candidate.pages().length > 0) || reversed[0];
518
531
  }
519
- async function launchPersistentContext(playwright, userDataDir, executablePath, headless, startupTimeoutMs, chromeArgs) {
532
+ async function launchPersistentContext(playwright, userDataDir, executablePath, headless, startupTimeoutMs, chromeArgs, videoRecording) {
520
533
  if ("function" != typeof playwright.chromium.launchPersistentContext) throw new Error("playwright-core runtime does not support launchPersistentContext.");
521
534
  return playwright.chromium.launchPersistentContext(userDataDir, {
522
535
  executablePath: resolveChromeExecutablePath(executablePath),
523
536
  headless,
524
537
  timeout: startupTimeoutMs,
525
538
  args: chromeArgs,
526
- ignoreDefaultArgs: PERSISTENT_PROFILE_IGNORE_DEFAULT_ARGS
539
+ ignoreDefaultArgs: PERSISTENT_PROFILE_IGNORE_DEFAULT_ARGS,
540
+ ...videoRecording ? {
541
+ recordVideo: {
542
+ dir: videoRecording.dirAbsolute,
543
+ ...videoRecording.size ? {
544
+ size: videoRecording.size
545
+ } : {}
546
+ }
547
+ } : {}
527
548
  });
528
549
  }
529
550
  function validateExtensionId(extensionId) {
@@ -701,6 +722,102 @@ function resolveScreenshotPath(workspace, requestedPath, now, actionIndex) {
701
722
  relative: (0, external_node_path_namespaceObject.relative)(workspace, absoluteOutputPath).split("\\").join("/")
702
723
  };
703
724
  }
725
+ function toGatewayFileUrl(absolutePath) {
726
+ return `/api/fs/file?path=${encodeURIComponent(absolutePath)}`;
727
+ }
728
+ function resolveVideoOutputDir(workspace, requested, now) {
729
+ if (!requested) return null;
730
+ const dir = "object" == typeof requested && requested.dir?.trim() ? requested.dir.trim() : (0, external_node_path_namespaceObject.join)(DEFAULT_BROWSER_VIDEO_ROOT, `recording-${now()}`);
731
+ if ((0, external_node_path_namespaceObject.isAbsolute)(dir)) throw new Error("Video recording directory must be relative to the workspace.");
732
+ const dirAbsolute = resolveWorkspaceRelativePath(workspace, dir);
733
+ (0, external_node_fs_namespaceObject.mkdirSync)(dirAbsolute, {
734
+ recursive: true
735
+ });
736
+ return {
737
+ dirAbsolute,
738
+ dirRelative: (0, external_node_path_namespaceObject.relative)(workspace, dirAbsolute).split("\\").join("/"),
739
+ ..."object" == typeof requested && requested.size ? {
740
+ size: requested.size
741
+ } : {}
742
+ };
743
+ }
744
+ function resolveVideoMimeType(pathname) {
745
+ const extension = (0, external_node_path_namespaceObject.extname)(pathname).trim().toLowerCase();
746
+ switch(extension){
747
+ case ".mp4":
748
+ return "video/mp4";
749
+ case ".mov":
750
+ return "video/quicktime";
751
+ case ".webm":
752
+ default:
753
+ return "video/webm";
754
+ }
755
+ }
756
+ function buildScreenshotMedia(workspace, actionResults) {
757
+ return actionResults.flatMap((result, index)=>{
758
+ if ("screenshot" !== result.type || "string" != typeof result.path || !result.path.trim()) return [];
759
+ const relativePath = result.path.trim();
760
+ const absolutePath = "string" == typeof result.absolutePath && result.absolutePath.trim() ? result.absolutePath.trim() : resolveWorkspaceRelativePath(workspace, relativePath);
761
+ const uri = "string" == typeof result.uri && result.uri.trim() ? result.uri.trim() : toGatewayFileUrl(absolutePath);
762
+ return [
763
+ {
764
+ kind: "image",
765
+ source: "screenshot",
766
+ path: absolutePath,
767
+ relativePath,
768
+ uri,
769
+ url: uri,
770
+ mimeType: "image/png",
771
+ name: (0, external_node_path_namespaceObject.basename)(absolutePath),
772
+ ..."boolean" == typeof result.fullPage ? {
773
+ fullPage: result.fullPage
774
+ } : {},
775
+ actionIndex: index
776
+ }
777
+ ];
778
+ });
779
+ }
780
+ function summarizeVideoRecording(recording, state, videoCount = 0) {
781
+ if (!recording) return null;
782
+ return {
783
+ enabled: true,
784
+ state,
785
+ dir: recording.dirRelative,
786
+ size: recording.size || null,
787
+ videoCount
788
+ };
789
+ }
790
+ async function registerPageVideoHandle(runtime, page) {
791
+ if (!runtime.videoRecording || "function" != typeof page.video) return;
792
+ try {
793
+ const video = page.video();
794
+ if (video) runtime.videoRecording.handles.add(video);
795
+ } catch {}
796
+ }
797
+ async function finalizeRecordedVideos(runtime) {
798
+ if (!runtime.videoRecording || 0 === runtime.videoRecording.handles.size) return [];
799
+ const seen = new Set();
800
+ const media = [];
801
+ for (const handle of runtime.videoRecording.handles)try {
802
+ const absolutePath = (await handle.path()).trim();
803
+ if (!absolutePath) continue;
804
+ const relativePath = (0, external_node_path_namespaceObject.relative)(runtime.workspace, absolutePath).split("\\").join("/");
805
+ if (!relativePath || relativePath.startsWith("..") || (0, external_node_path_namespaceObject.isAbsolute)(relativePath) || seen.has(relativePath)) continue;
806
+ seen.add(relativePath);
807
+ const uri = toGatewayFileUrl(absolutePath);
808
+ media.push({
809
+ kind: "video",
810
+ source: "video-recording",
811
+ path: absolutePath,
812
+ relativePath,
813
+ uri,
814
+ url: uri,
815
+ mimeType: resolveVideoMimeType(absolutePath),
816
+ name: (0, external_node_path_namespaceObject.basename)(absolutePath)
817
+ });
818
+ } catch {}
819
+ return media;
820
+ }
704
821
  function serializeEvaluation(value) {
705
822
  if ("string" == typeof value || "number" == typeof value || "boolean" == typeof value || null === value) return value;
706
823
  try {
@@ -888,6 +1005,8 @@ async function runBrowserAction(page, action, timeoutMs, workspace, now, actionI
888
1005
  return {
889
1006
  type: "screenshot",
890
1007
  path: screenshotPath.relative,
1008
+ absolutePath: screenshotPath.absolute,
1009
+ uri: toGatewayFileUrl(screenshotPath.absolute),
891
1010
  fullPage: Boolean(action.fullPage)
892
1011
  };
893
1012
  }
@@ -929,6 +1048,7 @@ async function openBrowserSessionRuntime(options = {}, dependencies = {}, input
929
1048
  let transportFallbackReason = null;
930
1049
  let reusedExistingCdpSession = false;
931
1050
  let context = null;
1051
+ let videoRecording = null;
932
1052
  try {
933
1053
  userDataDirSelection = resolveUserDataDir(configWorkspace, resolvedOptions, deps);
934
1054
  const selectedUserDataDir = userDataDirSelection;
@@ -940,8 +1060,15 @@ async function openBrowserSessionRuntime(options = {}, dependencies = {}, input
940
1060
  const executablePath = input.executablePath || resolvedOptions.defaultExecutablePath;
941
1061
  const { extensionIds, extensionDirs } = resolveEnabledExtensions(configWorkspace, resolvedOptions);
942
1062
  const chromeArgs = buildChromeArgs(extensionDirs);
1063
+ const requestedVideoRecording = resolveVideoOutputDir(workspace, input.recordVideo, deps.now);
943
1064
  const usePersistentLaunch = preferPersistentLaunch(resolvedOptions, selectedUserDataDir.persistentProfile);
1065
+ const effectivePersistentLaunch = usePersistentLaunch || Boolean(requestedVideoRecording);
944
1066
  const transportRequested = resolveBrowserTransportPreference(input.transport || resolvedOptions.browserTransport);
1067
+ if (requestedVideoRecording && "relay" === transportRequested) throw new Error("Video recording is only supported with Playwright persistent launch sessions.");
1068
+ if (requestedVideoRecording) videoRecording = {
1069
+ ...requestedVideoRecording,
1070
+ handles: new Set()
1071
+ };
945
1072
  const closeTransientSessions = async ()=>{
946
1073
  if (launchedContext?.close) {
947
1074
  try {
@@ -975,8 +1102,8 @@ async function openBrowserSessionRuntime(options = {}, dependencies = {}, input
975
1102
  reusedExistingCdpSession = false;
976
1103
  };
977
1104
  const initializeViaPlaywright = async ()=>{
978
- if (usePersistentLaunch) {
979
- launchedContext = await launchPersistentContext(playwright, selectedUserDataDir.userDataDir, executablePath, headless, startupTimeoutMs, chromeArgs);
1105
+ if (effectivePersistentLaunch) {
1106
+ launchedContext = await launchPersistentContext(playwright, selectedUserDataDir.userDataDir, executablePath, headless, startupTimeoutMs, chromeArgs, videoRecording);
980
1107
  context = launchedContext;
981
1108
  browserTransport = "persistent-context";
982
1109
  return;
@@ -1057,7 +1184,7 @@ async function openBrowserSessionRuntime(options = {}, dependencies = {}, input
1057
1184
  const launchPersistent = playwright.chromium.launchPersistentContext;
1058
1185
  if ("function" != typeof launchPersistent) throw new Error(`CDP connection failed for persistent profile after retry. Initial error: ${cdpMessage}. Retry error: ${retryMessage}`);
1059
1186
  logger.warn(`browser_control CDP retry failed for persistent profile, falling back to persistent launch: ${retryMessage}`);
1060
- launchedContext = await launchPersistentContext(playwright, selectedUserDataDir.userDataDir, executablePath, headless, startupTimeoutMs, chromeArgs);
1187
+ launchedContext = await launchPersistentContext(playwright, selectedUserDataDir.userDataDir, executablePath, headless, startupTimeoutMs, chromeArgs, videoRecording);
1061
1188
  context = launchedContext;
1062
1189
  browserTransport = "persistent-context";
1063
1190
  }
@@ -1065,7 +1192,7 @@ async function openBrowserSessionRuntime(options = {}, dependencies = {}, input
1065
1192
  const launchPersistent = playwright.chromium.launchPersistentContext;
1066
1193
  if ("function" != typeof launchPersistent) throw cdpError;
1067
1194
  logger.warn(`browser_control CDP connection failed, retrying with persistent launch: ${cdpMessage}`);
1068
- launchedContext = await launchPersistentContext(playwright, selectedUserDataDir.userDataDir, executablePath, headless, startupTimeoutMs, chromeArgs);
1195
+ launchedContext = await launchPersistentContext(playwright, selectedUserDataDir.userDataDir, executablePath, headless, startupTimeoutMs, chromeArgs, videoRecording);
1069
1196
  context = launchedContext;
1070
1197
  browserTransport = "persistent-context";
1071
1198
  }
@@ -1076,7 +1203,7 @@ async function openBrowserSessionRuntime(options = {}, dependencies = {}, input
1076
1203
  else try {
1077
1204
  await initializeViaPlaywright();
1078
1205
  } catch (playwrightError) {
1079
- if ("auto" !== transportRequested || !relayConfig) throw playwrightError;
1206
+ if ("auto" !== transportRequested || !relayConfig || requestedVideoRecording) throw playwrightError;
1080
1207
  await closeTransientSessions();
1081
1208
  const relayTimeoutMs = Math.min(startupTimeoutMs, DEFAULT_RELAY_CONNECT_TIMEOUT_MS);
1082
1209
  const playwrightMessage = playwrightError instanceof Error ? playwrightError.message : String(playwrightError);
@@ -1092,6 +1219,7 @@ async function openBrowserSessionRuntime(options = {}, dependencies = {}, input
1092
1219
  now: deps.now,
1093
1220
  headless,
1094
1221
  context: resolvedContext,
1222
+ activePage: null,
1095
1223
  userDataDirSelection: selectedUserDataDir,
1096
1224
  browserTransport,
1097
1225
  transportRequested,
@@ -1101,6 +1229,7 @@ async function openBrowserSessionRuntime(options = {}, dependencies = {}, input
1101
1229
  launchedContext,
1102
1230
  browser,
1103
1231
  chromeSession,
1232
+ videoRecording,
1104
1233
  closed: false
1105
1234
  };
1106
1235
  } catch (error) {
@@ -1112,16 +1241,42 @@ async function openBrowserSessionRuntime(options = {}, dependencies = {}, input
1112
1241
  throw error;
1113
1242
  }
1114
1243
  }
1115
- async function selectActivePage(context) {
1116
- let page = context.pages().at(-1);
1117
- if (!page) page = await context.newPage();
1244
+ function getPageUrl(page) {
1245
+ try {
1246
+ return page.url().trim();
1247
+ } catch {
1248
+ return "";
1249
+ }
1250
+ }
1251
+ function isBrowserInternalPageUrl(url) {
1252
+ const normalized = url.trim().toLowerCase();
1253
+ if (!normalized) return true;
1254
+ return normalized.startsWith("about:blank") || normalized.startsWith("chrome://") || normalized.startsWith("chrome-extension://") || normalized.startsWith("devtools://") || normalized.startsWith("edge://") || normalized.startsWith("extension://") || normalized.startsWith("moz-extension://");
1255
+ }
1256
+ function selectPreferredPage(pages) {
1257
+ for(let index = pages.length - 1; index >= 0; index -= 1){
1258
+ const candidate = pages[index];
1259
+ if (candidate) {
1260
+ if (!isBrowserInternalPageUrl(getPageUrl(candidate))) return candidate;
1261
+ }
1262
+ }
1263
+ return pages.at(-1) || null;
1264
+ }
1265
+ async function selectActivePage(runtime) {
1266
+ const pages = runtime.context.pages();
1267
+ const preferredPage = selectPreferredPage(pages);
1268
+ let page = runtime.activePage && pages.includes(runtime.activePage) ? runtime.activePage : null;
1269
+ if (preferredPage && (!page || isBrowserInternalPageUrl(getPageUrl(page)))) page = preferredPage;
1270
+ if (!page) page = await runtime.context.newPage();
1271
+ runtime.activePage = page;
1118
1272
  if ("function" == typeof page.bringToFront) await page.bringToFront();
1119
1273
  return page;
1120
1274
  }
1121
1275
  async function executeBrowserSessionRuntime(runtime, input = {}) {
1122
1276
  if (runtime.closed) throw new Error("Browser session is already closed.");
1123
1277
  const timeoutMs = input.timeoutMs ?? DEFAULT_ACTION_TIMEOUT_MS;
1124
- const page = await selectActivePage(runtime.context);
1278
+ const page = await selectActivePage(runtime);
1279
+ await registerPageVideoHandle(runtime, page);
1125
1280
  if (input.url) await page.goto(input.url, {
1126
1281
  waitUntil: "domcontentloaded",
1127
1282
  timeout: timeoutMs
@@ -1131,6 +1286,7 @@ async function executeBrowserSessionRuntime(runtime, input = {}) {
1131
1286
  const result = await runBrowserAction(page, action, timeoutMs, runtime.workspace, runtime.now, index);
1132
1287
  actionResults.push(result);
1133
1288
  }
1289
+ const media = buildScreenshotMedia(runtime.workspace, actionResults);
1134
1290
  return {
1135
1291
  browser: "cdp" === runtime.browserTransport ? "chrome-cdp" : "persistent-context" === runtime.browserTransport ? "chrome-playwright" : "chrome-relay",
1136
1292
  transport: runtime.browserTransport,
@@ -1147,22 +1303,34 @@ async function executeBrowserSessionRuntime(runtime, input = {}) {
1147
1303
  extensions: runtime.extensionIds,
1148
1304
  finalUrl: page.url(),
1149
1305
  title: await page.title(),
1150
- actionResults
1306
+ actionResults,
1307
+ media,
1308
+ videoRecording: summarizeVideoRecording(runtime.videoRecording, runtime.videoRecording ? "recording" : "inactive", 0)
1151
1309
  };
1152
1310
  }
1153
1311
  async function closeBrowserSessionRuntime(runtime, dependencies = {}) {
1154
- if (runtime.closed) return;
1312
+ if (runtime.closed) return {
1313
+ media: [],
1314
+ videoRecording: summarizeVideoRecording(runtime.videoRecording, "inactive", 0)
1315
+ };
1155
1316
  runtime.closed = true;
1156
1317
  const deps = createBrowserDependencies(dependencies);
1318
+ const recording = runtime.videoRecording;
1157
1319
  await closeOptionalHandle(runtime.launchedContext);
1320
+ const media = await finalizeRecordedVideos(runtime);
1158
1321
  if (runtime.browser && !runtime.reusedExistingCdpSession) await closeHandle(runtime.browser);
1159
1322
  await closeHandle(runtime.chromeSession);
1160
1323
  if (runtime.userDataDirSelection.releaseLock) runtime.userDataDirSelection.releaseLock();
1161
1324
  if (!runtime.userDataDirSelection.persistentProfile) deps.removeDir(runtime.userDataDirSelection.userDataDir);
1325
+ return {
1326
+ media,
1327
+ videoRecording: summarizeVideoRecording(recording, recording ? "saved" : "inactive", media.length)
1328
+ };
1162
1329
  }
1163
1330
  exports.BrowserActionSchema = __webpack_exports__.BrowserActionSchema;
1164
1331
  exports.BrowserControlInputSchema = __webpack_exports__.BrowserControlInputSchema;
1165
1332
  exports.BrowserSessionActionInputSchema = __webpack_exports__.BrowserSessionActionInputSchema;
1333
+ exports.BrowserSessionVideoRecordingSchema = __webpack_exports__.BrowserSessionVideoRecordingSchema;
1166
1334
  exports.BrowserTransportPreferenceSchema = __webpack_exports__.BrowserTransportPreferenceSchema;
1167
1335
  exports.DEFAULT_ACTION_TIMEOUT_MS = __webpack_exports__.DEFAULT_ACTION_TIMEOUT_MS;
1168
1336
  exports.clearStaleDevtoolsArtifacts = __webpack_exports__.clearStaleDevtoolsArtifacts;
@@ -1175,6 +1343,7 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
1175
1343
  "BrowserActionSchema",
1176
1344
  "BrowserControlInputSchema",
1177
1345
  "BrowserSessionActionInputSchema",
1346
+ "BrowserSessionVideoRecordingSchema",
1178
1347
  "BrowserTransportPreferenceSchema",
1179
1348
  "DEFAULT_ACTION_TIMEOUT_MS",
1180
1349
  "clearStaleDevtoolsArtifacts",
@@ -5,6 +5,17 @@ export declare const BrowserTransportPreferenceSchema: z.ZodEnum<{
5
5
  playwright: "playwright";
6
6
  relay: "relay";
7
7
  }>;
8
+ declare const BrowserVideoSizeSchema: z.ZodObject<{
9
+ width: z.ZodNumber;
10
+ height: z.ZodNumber;
11
+ }, z.core.$strip>;
12
+ export declare const BrowserSessionVideoRecordingSchema: z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
13
+ dir: z.ZodOptional<z.ZodString>;
14
+ size: z.ZodOptional<z.ZodObject<{
15
+ width: z.ZodNumber;
16
+ height: z.ZodNumber;
17
+ }, z.core.$strip>>;
18
+ }, z.core.$strip>]>;
8
19
  export declare const BrowserActionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
9
20
  type: z.ZodLiteral<"navigate">;
10
21
  url: z.ZodString;
@@ -391,9 +402,14 @@ export declare const BrowserSessionActionInputSchema: z.ZodObject<{
391
402
  timeoutMs: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
392
403
  }, z.core.$strip>;
393
404
  export type BrowserControlInput = z.infer<typeof BrowserControlInputSchema>;
405
+ export type BrowserSessionVideoRecordingInput = z.infer<typeof BrowserSessionVideoRecordingSchema>;
394
406
  export type BrowserSessionActionInput = z.infer<typeof BrowserSessionActionInputSchema>;
395
407
  export type BrowserAction = z.infer<typeof BrowserActionSchema>;
396
408
  export type BrowserTransportPreference = z.infer<typeof BrowserTransportPreferenceSchema>;
409
+ export type BrowserVideoSize = z.infer<typeof BrowserVideoSizeSchema>;
410
+ type BrowserVideoLike = {
411
+ path: () => Promise<string>;
412
+ };
397
413
  export type BrowserPageLike = {
398
414
  goto: (url: string, options?: {
399
415
  waitUntil?: "domcontentloaded";
@@ -432,6 +448,7 @@ export type BrowserPageLike = {
432
448
  path: string;
433
449
  fullPage?: boolean;
434
450
  }) => Promise<unknown>;
451
+ video?: () => BrowserVideoLike | null;
435
452
  title: () => Promise<string>;
436
453
  url: () => string;
437
454
  };
@@ -450,6 +467,10 @@ type LaunchPersistentContextOptions = {
450
467
  timeout?: number;
451
468
  args?: string[];
452
469
  ignoreDefaultArgs?: string[];
470
+ recordVideo?: {
471
+ dir: string;
472
+ size?: BrowserVideoSize;
473
+ };
453
474
  };
454
475
  type PlaywrightLike = {
455
476
  chromium: {
@@ -514,12 +535,40 @@ export type BrowserUserDataDirSelection = {
514
535
  profileId?: string;
515
536
  releaseLock?: () => void;
516
537
  };
538
+ type BrowserVideoRecordingSelection = {
539
+ dirAbsolute: string;
540
+ dirRelative: string;
541
+ size?: BrowserVideoSize;
542
+ };
543
+ type BrowserVideoRecordingRuntime = BrowserVideoRecordingSelection & {
544
+ handles: Set<BrowserVideoLike>;
545
+ };
546
+ export interface BrowserGeneratedMedia {
547
+ kind: "image" | "video";
548
+ source: "screenshot" | "video-recording";
549
+ path: string;
550
+ relativePath: string;
551
+ uri: string;
552
+ url: string;
553
+ mimeType: string;
554
+ name: string;
555
+ fullPage?: boolean;
556
+ actionIndex?: number | null;
557
+ }
558
+ export interface BrowserVideoRecordingSummary {
559
+ enabled: boolean;
560
+ state: "inactive" | "recording" | "saved";
561
+ dir: string | null;
562
+ size: BrowserVideoSize | null;
563
+ videoCount: number;
564
+ }
517
565
  export interface BrowserSessionRuntime {
518
566
  workspace: string;
519
567
  configWorkspace: string;
520
568
  now: () => number;
521
569
  headless: boolean;
522
570
  context: BrowserContextLike;
571
+ activePage: BrowserPageLike | null;
523
572
  userDataDirSelection: BrowserUserDataDirSelection;
524
573
  browserTransport: BrowserRuntimeTransport;
525
574
  transportRequested: BrowserTransportPreference;
@@ -529,6 +578,7 @@ export interface BrowserSessionRuntime {
529
578
  launchedContext: BrowserContextLike | null;
530
579
  browser: BrowserLike | null;
531
580
  chromeSession: StartedChromeSession | null;
581
+ videoRecording: BrowserVideoRecordingRuntime | null;
532
582
  closed: boolean;
533
583
  }
534
584
  export interface BrowserExecutionSummary {
@@ -548,13 +598,20 @@ export interface BrowserExecutionSummary {
548
598
  finalUrl: string;
549
599
  title: string;
550
600
  actionResults: Record<string, unknown>[];
601
+ media: BrowserGeneratedMedia[];
602
+ videoRecording: BrowserVideoRecordingSummary | null;
551
603
  }
552
- type BrowserSessionOpenInput = Partial<Pick<BrowserControlInput, "headless" | "timeoutMs" | "executablePath" | "transport">>;
604
+ type BrowserSessionOpenInput = Partial<Pick<BrowserControlInput, "headless" | "timeoutMs" | "executablePath" | "transport">> & {
605
+ recordVideo?: BrowserSessionVideoRecordingInput;
606
+ };
553
607
  type BrowserSessionExecutionInput = Partial<Pick<BrowserControlInput, "url" | "actions" | "timeoutMs">>;
554
608
  export declare const createBrowserDependencies: (dependencies?: Partial<BrowserControlDependencies>) => BrowserControlDependencies;
555
609
  export declare function clearStaleDevtoolsArtifacts(userDataDir: string): void;
556
610
  export declare function runBrowserAction(page: BrowserPageLike, action: BrowserAction, timeoutMs: number, workspace: string, now: () => number, actionIndex: number): Promise<Record<string, unknown>>;
557
611
  export declare function openBrowserSessionRuntime(options?: BrowserControlToolOptions, dependencies?: Partial<BrowserControlDependencies>, input?: BrowserSessionOpenInput): Promise<BrowserSessionRuntime>;
558
612
  export declare function executeBrowserSessionRuntime(runtime: BrowserSessionRuntime, input?: BrowserSessionExecutionInput): Promise<BrowserExecutionSummary>;
559
- export declare function closeBrowserSessionRuntime(runtime: BrowserSessionRuntime, dependencies?: Partial<BrowserControlDependencies>): Promise<void>;
613
+ export declare function closeBrowserSessionRuntime(runtime: BrowserSessionRuntime, dependencies?: Partial<BrowserControlDependencies>): Promise<{
614
+ media: BrowserGeneratedMedia[];
615
+ videoRecording: BrowserVideoRecordingSummary | null;
616
+ }>;
560
617
  export {};