@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.
- package/dist/agent/backend/filtered-backend.cjs +130 -0
- package/dist/agent/backend/filtered-backend.d.ts +10 -0
- package/dist/agent/backend/filtered-backend.js +87 -0
- package/dist/agent/middleware/additional-messages.cjs +4 -1
- package/dist/agent/middleware/additional-messages.js +4 -1
- package/dist/agent/tools/browser_control.cjs +1 -1
- package/dist/agent/tools/browser_control.js +1 -1
- package/dist/agent/tools/browser_runtime.cjs +184 -15
- package/dist/agent/tools/browser_runtime.d.ts +59 -2
- package/dist/agent/tools/browser_runtime.js +182 -16
- package/dist/agent/tools/browser_session.cjs +44 -8
- package/dist/agent/tools/browser_session.d.ts +68 -123
- package/dist/agent/tools/browser_session.js +45 -9
- package/dist/agent/tools/browser_session_manager.cjs +15 -4
- package/dist/agent/tools/browser_session_manager.d.ts +8 -2
- package/dist/agent/tools/browser_session_manager.js +15 -4
- package/dist/cli/commands/init.cjs +80 -102
- package/dist/cli/commands/init.js +80 -102
- package/dist/cli/core/agentInvoker.cjs +4 -2
- package/dist/cli/core/agentInvoker.js +4 -2
- package/dist/cli/core/sessionManager.cjs +208 -41
- package/dist/cli/core/sessionManager.d.ts +20 -0
- package/dist/cli/core/sessionManager.js +208 -41
- package/dist/cli/index.cjs +16 -1
- package/dist/cli/index.js +16 -1
- package/dist/cli/services/updateCheck.cjs +212 -0
- package/dist/cli/services/updateCheck.d.ts +26 -0
- package/dist/cli/services/updateCheck.js +166 -0
- package/dist/gateway/server.cjs +7 -0
- package/dist/gateway/server.js +7 -0
- package/dist/webui/assets/index-D3x3G75t.css +11 -0
- package/dist/webui/assets/index-UpMmcU1f.js +215 -0
- package/dist/webui/index.html +2 -2
- package/package.json +3 -3
- package/templates/agents/README.md +1 -0
- package/templates/agents/game-dev/agent.md +1 -0
- package/templates/agents/main/agent.md +3 -3
- package/templates/agents/researcher/agent.md +5 -5
- package/dist/webui/assets/index-XrEnkZiq.css +0 -11
- package/dist/webui/assets/index-mDs6HbKM.js +0 -215
- 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 (
|
|
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
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
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
|
|
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<
|
|
613
|
+
export declare function closeBrowserSessionRuntime(runtime: BrowserSessionRuntime, dependencies?: Partial<BrowserControlDependencies>): Promise<{
|
|
614
|
+
media: BrowserGeneratedMedia[];
|
|
615
|
+
videoRecording: BrowserVideoRecordingSummary | null;
|
|
616
|
+
}>;
|
|
560
617
|
export {};
|