@quanta-intellect/vessel-browser 0.1.146 → 0.1.147
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/out/main/index.js
CHANGED
|
@@ -175,12 +175,32 @@ function sanitizeSidebarDetachedBounds(value) {
|
|
|
175
175
|
height: Math.max(DETACHED_SIDEBAR_MIN_HEIGHT, Math.round(height))
|
|
176
176
|
};
|
|
177
177
|
}
|
|
178
|
+
const DETACHED_DEVTOOLS_DEFAULT_WIDTH = 920;
|
|
179
|
+
const DETACHED_DEVTOOLS_DEFAULT_HEIGHT = 560;
|
|
180
|
+
const DETACHED_DEVTOOLS_MIN_WIDTH = 520;
|
|
181
|
+
const DETACHED_DEVTOOLS_MIN_HEIGHT = 320;
|
|
182
|
+
function sanitizeDevToolsDetachedBounds(value) {
|
|
183
|
+
if (!value || typeof value !== "object") return null;
|
|
184
|
+
const bounds = value;
|
|
185
|
+
const width = Number(bounds.width);
|
|
186
|
+
const height = Number(bounds.height);
|
|
187
|
+
if (!Number.isFinite(width) || !Number.isFinite(height)) return null;
|
|
188
|
+
const x = Number(bounds.x);
|
|
189
|
+
const y = Number(bounds.y);
|
|
190
|
+
return {
|
|
191
|
+
...Number.isFinite(x) ? { x: Math.round(x) } : {},
|
|
192
|
+
...Number.isFinite(y) ? { y: Math.round(y) } : {},
|
|
193
|
+
width: Math.max(DETACHED_DEVTOOLS_MIN_WIDTH, Math.round(width)),
|
|
194
|
+
height: Math.max(DETACHED_DEVTOOLS_MIN_HEIGHT, Math.round(height))
|
|
195
|
+
};
|
|
196
|
+
}
|
|
178
197
|
const defaults = {
|
|
179
198
|
defaultUrl: "https://start.duckduckgo.com",
|
|
180
199
|
theme: "dark",
|
|
181
200
|
sidebarPanelMode: "docked",
|
|
182
201
|
sidebarWidth: 400,
|
|
183
202
|
sidebarDetachedBounds: null,
|
|
203
|
+
devtoolsPanelDetachedBounds: null,
|
|
184
204
|
mcpPort: 3100,
|
|
185
205
|
autoRestoreSession: true,
|
|
186
206
|
clearBookmarksOnLaunch: false,
|
|
@@ -222,6 +242,15 @@ const SettingsValueSchemas = {
|
|
|
222
242
|
height: zod.z.number().int().min(DETACHED_SIDEBAR_MIN_HEIGHT)
|
|
223
243
|
})
|
|
224
244
|
]),
|
|
245
|
+
devtoolsPanelDetachedBounds: zod.z.union([
|
|
246
|
+
zod.z.null(),
|
|
247
|
+
zod.z.object({
|
|
248
|
+
x: zod.z.number().optional(),
|
|
249
|
+
y: zod.z.number().optional(),
|
|
250
|
+
width: zod.z.number().int().min(DETACHED_DEVTOOLS_MIN_WIDTH),
|
|
251
|
+
height: zod.z.number().int().min(DETACHED_DEVTOOLS_MIN_HEIGHT)
|
|
252
|
+
})
|
|
253
|
+
]),
|
|
225
254
|
mcpPort: zod.z.number().int().min(1).max(65535),
|
|
226
255
|
autoRestoreSession: zod.z.boolean(),
|
|
227
256
|
clearBookmarksOnLaunch: zod.z.boolean(),
|
|
@@ -477,6 +506,9 @@ function loadSettings() {
|
|
|
477
506
|
sidebarDetachedBounds: sanitizeSidebarDetachedBounds(
|
|
478
507
|
parsed.sidebarDetachedBounds
|
|
479
508
|
),
|
|
509
|
+
devtoolsPanelDetachedBounds: sanitizeDevToolsDetachedBounds(
|
|
510
|
+
parsed.devtoolsPanelDetachedBounds
|
|
511
|
+
),
|
|
480
512
|
sourceDoNotAllowList: sanitizeStringList(
|
|
481
513
|
parsed.sourceDoNotAllowList ?? defaults.sourceDoNotAllowList
|
|
482
514
|
),
|
|
@@ -530,6 +562,8 @@ function setSetting(key2, value) {
|
|
|
530
562
|
settings.sidebarPanelMode = sanitizeSidebarPanelMode(value);
|
|
531
563
|
} else if (key2 === "sidebarDetachedBounds") {
|
|
532
564
|
settings.sidebarDetachedBounds = sanitizeSidebarDetachedBounds(value);
|
|
565
|
+
} else if (key2 === "devtoolsPanelDetachedBounds") {
|
|
566
|
+
settings.devtoolsPanelDetachedBounds = sanitizeDevToolsDetachedBounds(value);
|
|
533
567
|
} else if (key2 === "sourceDoNotAllowList") {
|
|
534
568
|
settings.sourceDoNotAllowList = sanitizeStringList(value);
|
|
535
569
|
} else if (key2 === "chatProvider") {
|
|
@@ -2589,6 +2623,9 @@ class DevToolsSession {
|
|
|
2589
2623
|
entryCounter = 0;
|
|
2590
2624
|
// Track in-flight network requests for matching response data
|
|
2591
2625
|
pendingRequests = /* @__PURE__ */ new Map();
|
|
2626
|
+
// Notified whenever a captured buffer mutates so the DevTools panel can
|
|
2627
|
+
// refresh independent of agent actions (e.g. while a user browses).
|
|
2628
|
+
onCaptureChange = null;
|
|
2592
2629
|
// Named handlers so we can remove them on detach/destroy (fixes listener leak)
|
|
2593
2630
|
onDetach = () => {
|
|
2594
2631
|
this.attached = false;
|
|
@@ -2604,6 +2641,27 @@ class DevToolsSession {
|
|
|
2604
2641
|
get isAttached() {
|
|
2605
2642
|
return this.attached;
|
|
2606
2643
|
}
|
|
2644
|
+
/**
|
|
2645
|
+
* Register a callback invoked whenever a captured console/network/error
|
|
2646
|
+
* entry is added or updated. Used to push live updates to the DevTools
|
|
2647
|
+
* panel while a user browses (not just when an agent acts).
|
|
2648
|
+
*/
|
|
2649
|
+
setOnCaptureChange(cb) {
|
|
2650
|
+
this.onCaptureChange = cb;
|
|
2651
|
+
}
|
|
2652
|
+
/**
|
|
2653
|
+
* Enable all capture domains (console, network, errors) in one call.
|
|
2654
|
+
* Idempotent per-domain. Used by the panel-open path so manual browsing is
|
|
2655
|
+
* captured without requiring an agent tool invocation.
|
|
2656
|
+
*/
|
|
2657
|
+
async enableCapture() {
|
|
2658
|
+
await this.ensureConsoleDomain();
|
|
2659
|
+
await this.ensureNetworkDomain();
|
|
2660
|
+
await this.ensureErrorCapture();
|
|
2661
|
+
}
|
|
2662
|
+
notifyCaptureChange() {
|
|
2663
|
+
this.onCaptureChange?.();
|
|
2664
|
+
}
|
|
2607
2665
|
async ensureAttached() {
|
|
2608
2666
|
if (this.attached) return;
|
|
2609
2667
|
if (this.attachingPromise) return this.attachingPromise;
|
|
@@ -2654,6 +2712,7 @@ class DevToolsSession {
|
|
|
2654
2712
|
}
|
|
2655
2713
|
destroy() {
|
|
2656
2714
|
this.detach();
|
|
2715
|
+
this.onCaptureChange = null;
|
|
2657
2716
|
this.consoleBuffer = [];
|
|
2658
2717
|
this.networkBuffer = [];
|
|
2659
2718
|
this.errorBuffer = [];
|
|
@@ -3111,6 +3170,7 @@ class DevToolsSession {
|
|
|
3111
3170
|
if (this.consoleBuffer.length > MAX_CONSOLE_ENTRIES) {
|
|
3112
3171
|
this.consoleBuffer = this.consoleBuffer.slice(-MAX_CONSOLE_ENTRIES);
|
|
3113
3172
|
}
|
|
3173
|
+
this.notifyCaptureChange();
|
|
3114
3174
|
}
|
|
3115
3175
|
// --- Network events ---
|
|
3116
3176
|
onNetworkRequest(params) {
|
|
@@ -3139,6 +3199,7 @@ class DevToolsSession {
|
|
|
3139
3199
|
if (oldest !== void 0) this.pendingRequests.delete(oldest);
|
|
3140
3200
|
}
|
|
3141
3201
|
this.pendingRequests.set(requestId, { entry });
|
|
3202
|
+
this.notifyCaptureChange();
|
|
3142
3203
|
}
|
|
3143
3204
|
onNetworkResponse(params) {
|
|
3144
3205
|
const requestId = params.requestId;
|
|
@@ -3154,6 +3215,7 @@ class DevToolsSession {
|
|
|
3154
3215
|
if (contentLength) {
|
|
3155
3216
|
pending.entry.contentLength = parseInt(contentLength, 10) || void 0;
|
|
3156
3217
|
}
|
|
3218
|
+
this.notifyCaptureChange();
|
|
3157
3219
|
}
|
|
3158
3220
|
onNetworkFinished(params) {
|
|
3159
3221
|
const requestId = params.requestId;
|
|
@@ -3168,6 +3230,7 @@ class DevToolsSession {
|
|
|
3168
3230
|
}
|
|
3169
3231
|
pending.entry.contentLength = pending.entry.contentLength ?? (params.encodedDataLength || void 0);
|
|
3170
3232
|
this.pendingRequests.delete(requestId);
|
|
3233
|
+
this.notifyCaptureChange();
|
|
3171
3234
|
}
|
|
3172
3235
|
onNetworkFailed(params) {
|
|
3173
3236
|
const requestId = params.requestId;
|
|
@@ -3182,6 +3245,7 @@ class DevToolsSession {
|
|
|
3182
3245
|
);
|
|
3183
3246
|
}
|
|
3184
3247
|
this.pendingRequests.delete(requestId);
|
|
3248
|
+
this.notifyCaptureChange();
|
|
3185
3249
|
}
|
|
3186
3250
|
// --- Error events ---
|
|
3187
3251
|
onExceptionThrown(params) {
|
|
@@ -3208,6 +3272,7 @@ class DevToolsSession {
|
|
|
3208
3272
|
if (this.errorBuffer.length > MAX_ERROR_ENTRIES) {
|
|
3209
3273
|
this.errorBuffer = this.errorBuffer.slice(-MAX_ERROR_ENTRIES);
|
|
3210
3274
|
}
|
|
3275
|
+
this.notifyCaptureChange();
|
|
3211
3276
|
}
|
|
3212
3277
|
}
|
|
3213
3278
|
function mapConsoleLevel(level) {
|
|
@@ -3931,8 +3996,19 @@ const ContentChannels = {
|
|
|
3931
3996
|
};
|
|
3932
3997
|
const DevToolsChannels = {
|
|
3933
3998
|
DEVTOOLS_PANEL_TOGGLE: "devtools-panel:toggle",
|
|
3999
|
+
DEVTOOLS_PANEL_CLOSE: "devtools-panel:close",
|
|
4000
|
+
DEVTOOLS_PANEL_OPEN_TAB: "devtools-panel:open-tab",
|
|
4001
|
+
DEVTOOLS_PANEL_SELECT_TAB: "devtools-panel:select-tab",
|
|
4002
|
+
DEVTOOLS_PANEL_STATE_GET: "devtools-panel:state-get",
|
|
3934
4003
|
DEVTOOLS_PANEL_STATE: "devtools-panel:state",
|
|
3935
|
-
|
|
4004
|
+
DEVTOOLS_PANEL_RESIZE_START: "devtools-panel:resize-start",
|
|
4005
|
+
DEVTOOLS_PANEL_RESIZE: "devtools-panel:resize",
|
|
4006
|
+
DEVTOOLS_PANEL_RESIZE_COMMIT: "devtools-panel:resize-commit",
|
|
4007
|
+
DEVTOOLS_PANEL_POPOUT: "devtools-panel:popout",
|
|
4008
|
+
DEVTOOLS_PANEL_DOCK: "devtools-panel:dock",
|
|
4009
|
+
DEVTOOLS_PANEL_HOST_STATE_GET: "devtools-panel:host-state-get",
|
|
4010
|
+
DEVTOOLS_PANEL_HOST_STATE: "devtools-panel:host-state",
|
|
4011
|
+
DEVTOOLS_PAGE_MAP_REVEAL: "devtools-panel:page-map:reveal"
|
|
3936
4012
|
};
|
|
3937
4013
|
const DownloadChannels = {
|
|
3938
4014
|
DOWNLOAD_STARTED: "download:started",
|
|
@@ -7206,6 +7282,236 @@ function sendSafe(wc, channel, ...args) {
|
|
|
7206
7282
|
}
|
|
7207
7283
|
}
|
|
7208
7284
|
}
|
|
7285
|
+
function closeDetachedViewWindow(state2, host) {
|
|
7286
|
+
const detachedWindow = host.getWindow(state2);
|
|
7287
|
+
if (!detachedWindow) return false;
|
|
7288
|
+
host.setWindow(state2, null);
|
|
7289
|
+
host.setClosing(state2, true);
|
|
7290
|
+
detachedWindow.once("closed", () => {
|
|
7291
|
+
host.setClosing(state2, false);
|
|
7292
|
+
});
|
|
7293
|
+
detachedWindow.close();
|
|
7294
|
+
return true;
|
|
7295
|
+
}
|
|
7296
|
+
function moveDetachedViewToMainWindow(state2, host) {
|
|
7297
|
+
const view = host.getView(state2);
|
|
7298
|
+
host.getWindow(state2)?.contentView.removeChildView(view);
|
|
7299
|
+
state2.mainWindow.contentView.addChildView(view);
|
|
7300
|
+
}
|
|
7301
|
+
function createDetachedViewWindow(state2, host) {
|
|
7302
|
+
const detachedWindow = new electron.BaseWindow(host.createWindowOptions(state2));
|
|
7303
|
+
const view = host.getView(state2);
|
|
7304
|
+
state2.mainWindow.contentView.removeChildView(view);
|
|
7305
|
+
detachedWindow.contentView.addChildView(view);
|
|
7306
|
+
host.setWindow(state2, detachedWindow);
|
|
7307
|
+
detachedWindow.on("resize", () => {
|
|
7308
|
+
host.layoutView(state2);
|
|
7309
|
+
host.persistBounds(state2);
|
|
7310
|
+
});
|
|
7311
|
+
detachedWindow.on("move", () => host.persistBounds(state2));
|
|
7312
|
+
detachedWindow.on("close", (event) => {
|
|
7313
|
+
if (host.isClosing(state2)) return;
|
|
7314
|
+
event.preventDefault();
|
|
7315
|
+
host.onNativeClose(state2);
|
|
7316
|
+
});
|
|
7317
|
+
detachedWindow.on("closed", () => {
|
|
7318
|
+
if (host.getWindow(state2) !== detachedWindow) return;
|
|
7319
|
+
host.onUnexpectedClosed(state2, detachedWindow);
|
|
7320
|
+
});
|
|
7321
|
+
return detachedWindow;
|
|
7322
|
+
}
|
|
7323
|
+
const devToolsDetachedHost = {
|
|
7324
|
+
getWindow: (state2) => state2.devtoolsPanelWindow,
|
|
7325
|
+
setWindow: (state2, window2) => {
|
|
7326
|
+
state2.devtoolsPanelWindow = window2;
|
|
7327
|
+
},
|
|
7328
|
+
isClosing: (state2) => state2.devtoolsPanelWindowClosing,
|
|
7329
|
+
setClosing: (state2, closing) => {
|
|
7330
|
+
state2.devtoolsPanelWindowClosing = closing;
|
|
7331
|
+
},
|
|
7332
|
+
getView: (state2) => state2.devtoolsPanelView
|
|
7333
|
+
};
|
|
7334
|
+
function setDevToolsPanelMode(state2, mode) {
|
|
7335
|
+
state2.uiState.devtoolsPanelMode = mode;
|
|
7336
|
+
}
|
|
7337
|
+
function persistDetachedBounds$1(state2) {
|
|
7338
|
+
const devtoolsWindow = state2.devtoolsPanelWindow;
|
|
7339
|
+
if (!devtoolsWindow || devtoolsWindow.isDestroyed()) return;
|
|
7340
|
+
const bounds = devtoolsWindow.getBounds();
|
|
7341
|
+
state2.uiState.devtoolsPanelDetachedBounds = {
|
|
7342
|
+
x: bounds.x,
|
|
7343
|
+
y: bounds.y,
|
|
7344
|
+
width: bounds.width,
|
|
7345
|
+
height: bounds.height
|
|
7346
|
+
};
|
|
7347
|
+
setSetting(
|
|
7348
|
+
"devtoolsPanelDetachedBounds",
|
|
7349
|
+
state2.uiState.devtoolsPanelDetachedBounds
|
|
7350
|
+
);
|
|
7351
|
+
}
|
|
7352
|
+
function moveDevToolsToMainWindow(state2) {
|
|
7353
|
+
moveDetachedViewToMainWindow(state2, devToolsDetachedHost);
|
|
7354
|
+
}
|
|
7355
|
+
function isDevToolsPanelDocked(state2) {
|
|
7356
|
+
return state2.uiState.devtoolsPanelMode === "docked";
|
|
7357
|
+
}
|
|
7358
|
+
function isDevToolsPanelDetached(state2) {
|
|
7359
|
+
return state2.uiState.devtoolsPanelMode === "detached";
|
|
7360
|
+
}
|
|
7361
|
+
function getDevToolsPanelHostState(state2) {
|
|
7362
|
+
return {
|
|
7363
|
+
open: state2.uiState.devtoolsPanelMode !== "closed",
|
|
7364
|
+
detached: isDevToolsPanelDetached(state2),
|
|
7365
|
+
height: state2.uiState.devtoolsPanelHeight
|
|
7366
|
+
};
|
|
7367
|
+
}
|
|
7368
|
+
function emitDevToolsPanelHostState(state2) {
|
|
7369
|
+
const panelState = getDevToolsPanelHostState(state2);
|
|
7370
|
+
sendSafe(
|
|
7371
|
+
state2.chromeView.webContents,
|
|
7372
|
+
Channels.DEVTOOLS_PANEL_HOST_STATE,
|
|
7373
|
+
panelState
|
|
7374
|
+
);
|
|
7375
|
+
sendSafe(
|
|
7376
|
+
state2.devtoolsPanelView.webContents,
|
|
7377
|
+
Channels.DEVTOOLS_PANEL_HOST_STATE,
|
|
7378
|
+
panelState
|
|
7379
|
+
);
|
|
7380
|
+
return panelState;
|
|
7381
|
+
}
|
|
7382
|
+
function closeDetachedDevToolsPanelWindow(state2) {
|
|
7383
|
+
return closeDetachedViewWindow(state2, devToolsDetachedHost);
|
|
7384
|
+
}
|
|
7385
|
+
function layoutDetachedDevToolsPanel(state2) {
|
|
7386
|
+
if (!state2.devtoolsPanelWindow) return;
|
|
7387
|
+
const [width, height] = state2.devtoolsPanelWindow.getContentSize();
|
|
7388
|
+
state2.devtoolsPanelView.setBounds({ x: 0, y: 0, width, height });
|
|
7389
|
+
}
|
|
7390
|
+
function toggleDockedDevToolsPanel(state2, hooks) {
|
|
7391
|
+
if (isDevToolsPanelDetached(state2)) {
|
|
7392
|
+
state2.devtoolsPanelWindow?.focus();
|
|
7393
|
+
return getDevToolsPanelHostState(state2);
|
|
7394
|
+
}
|
|
7395
|
+
setDevToolsPanelMode(
|
|
7396
|
+
state2,
|
|
7397
|
+
isDevToolsPanelDocked(state2) ? "closed" : "docked"
|
|
7398
|
+
);
|
|
7399
|
+
hooks.relayout();
|
|
7400
|
+
return emitDevToolsPanelHostState(state2);
|
|
7401
|
+
}
|
|
7402
|
+
function resizeDockedDevToolsPanel(state2, height, relayout) {
|
|
7403
|
+
state2.uiState.devtoolsPanelHeight = Math.round(height);
|
|
7404
|
+
if (isDevToolsPanelDocked(state2)) {
|
|
7405
|
+
relayout();
|
|
7406
|
+
}
|
|
7407
|
+
return emitDevToolsPanelHostState(state2);
|
|
7408
|
+
}
|
|
7409
|
+
function detachDevToolsPanel(state2, hooks) {
|
|
7410
|
+
if (state2.devtoolsPanelWindow) {
|
|
7411
|
+
state2.devtoolsPanelWindow.focus();
|
|
7412
|
+
return getDevToolsPanelHostState(state2);
|
|
7413
|
+
}
|
|
7414
|
+
const detachedBounds = state2.uiState.devtoolsPanelDetachedBounds;
|
|
7415
|
+
const devtoolsWindow = createDetachedViewWindow(state2, {
|
|
7416
|
+
...devToolsDetachedHost,
|
|
7417
|
+
createWindowOptions: () => ({
|
|
7418
|
+
...typeof detachedBounds?.x === "number" ? { x: detachedBounds.x } : {},
|
|
7419
|
+
...typeof detachedBounds?.y === "number" ? { y: detachedBounds.y } : {},
|
|
7420
|
+
width: Math.max(
|
|
7421
|
+
DETACHED_DEVTOOLS_MIN_WIDTH,
|
|
7422
|
+
Math.round(detachedBounds?.width ?? DETACHED_DEVTOOLS_DEFAULT_WIDTH)
|
|
7423
|
+
),
|
|
7424
|
+
height: Math.max(
|
|
7425
|
+
DETACHED_DEVTOOLS_MIN_HEIGHT,
|
|
7426
|
+
Math.round(detachedBounds?.height ?? DETACHED_DEVTOOLS_DEFAULT_HEIGHT)
|
|
7427
|
+
),
|
|
7428
|
+
minWidth: DETACHED_DEVTOOLS_MIN_WIDTH,
|
|
7429
|
+
minHeight: DETACHED_DEVTOOLS_MIN_HEIGHT,
|
|
7430
|
+
frame: true,
|
|
7431
|
+
show: false,
|
|
7432
|
+
backgroundColor: "#1a1a1e",
|
|
7433
|
+
title: "Vessel DevTools",
|
|
7434
|
+
icon: hooks.getWindowIconPath()
|
|
7435
|
+
}),
|
|
7436
|
+
layoutView: layoutDetachedDevToolsPanel,
|
|
7437
|
+
persistBounds: persistDetachedBounds$1,
|
|
7438
|
+
onNativeClose: () => dockDevToolsPanel(state2, hooks),
|
|
7439
|
+
onUnexpectedClosed: () => {
|
|
7440
|
+
state2.devtoolsPanelWindow = null;
|
|
7441
|
+
setDevToolsPanelMode(state2, "docked");
|
|
7442
|
+
state2.mainWindow.contentView.addChildView(state2.devtoolsPanelView);
|
|
7443
|
+
hooks.relayout();
|
|
7444
|
+
emitDevToolsPanelHostState(state2);
|
|
7445
|
+
}
|
|
7446
|
+
});
|
|
7447
|
+
setDevToolsPanelMode(state2, "detached");
|
|
7448
|
+
hooks.relayout();
|
|
7449
|
+
layoutDetachedDevToolsPanel(state2);
|
|
7450
|
+
devtoolsWindow.show();
|
|
7451
|
+
devtoolsWindow.focus();
|
|
7452
|
+
return emitDevToolsPanelHostState(state2);
|
|
7453
|
+
}
|
|
7454
|
+
function dockDevToolsPanel(state2, hooks) {
|
|
7455
|
+
const devtoolsWindow = state2.devtoolsPanelWindow;
|
|
7456
|
+
setDevToolsPanelMode(state2, "docked");
|
|
7457
|
+
if (devtoolsWindow) {
|
|
7458
|
+
moveDevToolsToMainWindow(state2);
|
|
7459
|
+
hooks.relayout();
|
|
7460
|
+
closeDetachedDevToolsPanelWindow(state2);
|
|
7461
|
+
state2.mainWindow.focus();
|
|
7462
|
+
} else {
|
|
7463
|
+
hooks.relayout();
|
|
7464
|
+
}
|
|
7465
|
+
return emitDevToolsPanelHostState(state2);
|
|
7466
|
+
}
|
|
7467
|
+
function closeDevToolsPanel(state2, hooks) {
|
|
7468
|
+
if (state2.devtoolsPanelWindow) {
|
|
7469
|
+
moveDevToolsToMainWindow(state2);
|
|
7470
|
+
closeDetachedDevToolsPanelWindow(state2);
|
|
7471
|
+
}
|
|
7472
|
+
setDevToolsPanelMode(state2, "closed");
|
|
7473
|
+
hooks.relayout();
|
|
7474
|
+
return emitDevToolsPanelHostState(state2);
|
|
7475
|
+
}
|
|
7476
|
+
function registerDisabledDevToolsPanelHandlers(ipc) {
|
|
7477
|
+
const disabledDevToolsState = {
|
|
7478
|
+
open: false,
|
|
7479
|
+
detached: false,
|
|
7480
|
+
height: 0
|
|
7481
|
+
};
|
|
7482
|
+
const disabledPanelState = {
|
|
7483
|
+
console: [],
|
|
7484
|
+
network: [],
|
|
7485
|
+
errors: [],
|
|
7486
|
+
activity: [],
|
|
7487
|
+
agentTrace: [],
|
|
7488
|
+
pageMap: null
|
|
7489
|
+
};
|
|
7490
|
+
ipc.handle(Channels.DEVTOOLS_PANEL_TOGGLE, () => disabledDevToolsState);
|
|
7491
|
+
ipc.handle(Channels.DEVTOOLS_PANEL_CLOSE, () => disabledDevToolsState);
|
|
7492
|
+
ipc.handle(Channels.DEVTOOLS_PANEL_OPEN_TAB, () => disabledDevToolsState);
|
|
7493
|
+
ipc.handle(Channels.DEVTOOLS_PANEL_STATE_GET, () => disabledPanelState);
|
|
7494
|
+
ipc.handle(Channels.DEVTOOLS_PANEL_RESIZE_START, () => void 0);
|
|
7495
|
+
ipc.handle(Channels.DEVTOOLS_PANEL_RESIZE, () => 0);
|
|
7496
|
+
ipc.handle(Channels.DEVTOOLS_PANEL_RESIZE_COMMIT, () => void 0);
|
|
7497
|
+
ipc.handle(Channels.DEVTOOLS_PANEL_POPOUT, () => disabledDevToolsState);
|
|
7498
|
+
ipc.handle(Channels.DEVTOOLS_PANEL_DOCK, () => disabledDevToolsState);
|
|
7499
|
+
ipc.handle(
|
|
7500
|
+
Channels.DEVTOOLS_PANEL_HOST_STATE_GET,
|
|
7501
|
+
() => disabledDevToolsState
|
|
7502
|
+
);
|
|
7503
|
+
}
|
|
7504
|
+
const sidebarDetachedHost = {
|
|
7505
|
+
getWindow: (state2) => state2.sidebarWindow,
|
|
7506
|
+
setWindow: (state2, window2) => {
|
|
7507
|
+
state2.sidebarWindow = window2;
|
|
7508
|
+
},
|
|
7509
|
+
isClosing: (state2) => state2.sidebarWindowClosing,
|
|
7510
|
+
setClosing: (state2, closing) => {
|
|
7511
|
+
state2.sidebarWindowClosing = closing;
|
|
7512
|
+
},
|
|
7513
|
+
getView: (state2) => state2.sidebarView
|
|
7514
|
+
};
|
|
7209
7515
|
function setSidebarPanelMode(state2, mode, reason = "user") {
|
|
7210
7516
|
state2.uiState.sidebarPanelMode = mode;
|
|
7211
7517
|
if (reason === "user") {
|
|
@@ -7225,19 +7531,10 @@ function persistDetachedBounds(state2) {
|
|
|
7225
7531
|
setSetting("sidebarDetachedBounds", state2.uiState.sidebarDetachedBounds);
|
|
7226
7532
|
}
|
|
7227
7533
|
function closeDetachedSidebarWindow(state2) {
|
|
7228
|
-
|
|
7229
|
-
if (!sidebarWindow) return false;
|
|
7230
|
-
state2.sidebarWindow = null;
|
|
7231
|
-
state2.sidebarWindowClosing = true;
|
|
7232
|
-
sidebarWindow.once("closed", () => {
|
|
7233
|
-
state2.sidebarWindowClosing = false;
|
|
7234
|
-
});
|
|
7235
|
-
sidebarWindow.close();
|
|
7236
|
-
return true;
|
|
7534
|
+
return closeDetachedViewWindow(state2, sidebarDetachedHost);
|
|
7237
7535
|
}
|
|
7238
7536
|
function moveSidebarToMainWindow(state2) {
|
|
7239
|
-
|
|
7240
|
-
state2.mainWindow.contentView.addChildView(state2.sidebarView);
|
|
7537
|
+
moveDetachedViewToMainWindow(state2, sidebarDetachedHost);
|
|
7241
7538
|
}
|
|
7242
7539
|
function getSidebarPanelState(state2) {
|
|
7243
7540
|
return {
|
|
@@ -7297,41 +7594,33 @@ function detachSidebar(state2, hooks) {
|
|
|
7297
7594
|
const detachedBounds = state2.uiState.sidebarDetachedBounds;
|
|
7298
7595
|
const detachedWidth = detachedBounds?.width ?? Math.max(DETACHED_SIDEBAR_DEFAULT_WIDTH, state2.uiState.sidebarWidth);
|
|
7299
7596
|
const detachedHeight = detachedBounds?.height ?? DETACHED_SIDEBAR_DEFAULT_HEIGHT;
|
|
7300
|
-
const sidebarWindow =
|
|
7301
|
-
...
|
|
7302
|
-
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
|
|
7308
|
-
|
|
7309
|
-
|
|
7310
|
-
|
|
7311
|
-
|
|
7597
|
+
const sidebarWindow = createDetachedViewWindow(state2, {
|
|
7598
|
+
...sidebarDetachedHost,
|
|
7599
|
+
createWindowOptions: () => ({
|
|
7600
|
+
...typeof detachedBounds?.x === "number" ? { x: detachedBounds.x } : {},
|
|
7601
|
+
...typeof detachedBounds?.y === "number" ? { y: detachedBounds.y } : {},
|
|
7602
|
+
width: Math.max(DETACHED_SIDEBAR_MIN_WIDTH, Math.round(detachedWidth)),
|
|
7603
|
+
height: Math.max(DETACHED_SIDEBAR_MIN_HEIGHT, Math.round(detachedHeight)),
|
|
7604
|
+
minWidth: DETACHED_SIDEBAR_MIN_WIDTH,
|
|
7605
|
+
minHeight: DETACHED_SIDEBAR_MIN_HEIGHT,
|
|
7606
|
+
frame: true,
|
|
7607
|
+
show: false,
|
|
7608
|
+
backgroundColor: "#1a1a1e",
|
|
7609
|
+
title: "Vessel Agent",
|
|
7610
|
+
icon: hooks.getWindowIconPath()
|
|
7611
|
+
}),
|
|
7612
|
+
layoutView: layoutDetachedSidebar,
|
|
7613
|
+
persistBounds: persistDetachedBounds,
|
|
7614
|
+
onNativeClose: () => dockSidebar(state2, hooks),
|
|
7615
|
+
onUnexpectedClosed: () => {
|
|
7616
|
+
state2.sidebarWindow = null;
|
|
7617
|
+
setSidebarPanelMode(state2, "docked");
|
|
7618
|
+
state2.mainWindow.contentView.addChildView(state2.sidebarView);
|
|
7619
|
+
hooks.relayout();
|
|
7620
|
+
emitSidebarPanelState(state2);
|
|
7621
|
+
}
|
|
7312
7622
|
});
|
|
7313
|
-
state2.mainWindow.contentView.removeChildView(state2.sidebarView);
|
|
7314
|
-
sidebarWindow.contentView.addChildView(state2.sidebarView);
|
|
7315
|
-
state2.sidebarWindow = sidebarWindow;
|
|
7316
7623
|
setSidebarPanelMode(state2, "detached");
|
|
7317
|
-
sidebarWindow.on("resize", () => {
|
|
7318
|
-
layoutDetachedSidebar(state2);
|
|
7319
|
-
persistDetachedBounds(state2);
|
|
7320
|
-
});
|
|
7321
|
-
sidebarWindow.on("move", () => persistDetachedBounds(state2));
|
|
7322
|
-
sidebarWindow.on("close", (event) => {
|
|
7323
|
-
if (state2.sidebarWindowClosing) return;
|
|
7324
|
-
event.preventDefault();
|
|
7325
|
-
dockSidebar(state2, hooks);
|
|
7326
|
-
});
|
|
7327
|
-
sidebarWindow.on("closed", () => {
|
|
7328
|
-
if (state2.sidebarWindow !== sidebarWindow) return;
|
|
7329
|
-
state2.sidebarWindow = null;
|
|
7330
|
-
setSidebarPanelMode(state2, "docked");
|
|
7331
|
-
state2.mainWindow.contentView.addChildView(state2.sidebarView);
|
|
7332
|
-
hooks.relayout();
|
|
7333
|
-
emitSidebarPanelState(state2);
|
|
7334
|
-
});
|
|
7335
7624
|
hooks.relayout();
|
|
7336
7625
|
layoutDetachedSidebar(state2);
|
|
7337
7626
|
sidebarWindow.show();
|
|
@@ -7554,8 +7843,9 @@ function createMainWindow(onTabStateChange) {
|
|
|
7554
7843
|
sidebarDetachedBounds: settings2.sidebarDetachedBounds,
|
|
7555
7844
|
focusMode: false,
|
|
7556
7845
|
settingsOpen: false,
|
|
7557
|
-
|
|
7558
|
-
devtoolsPanelHeight: DEFAULT_DEVTOOLS_PANEL_HEIGHT
|
|
7846
|
+
devtoolsPanelMode: "closed",
|
|
7847
|
+
devtoolsPanelHeight: DEFAULT_DEVTOOLS_PANEL_HEIGHT,
|
|
7848
|
+
devtoolsPanelDetachedBounds: settings2.devtoolsPanelDetachedBounds
|
|
7559
7849
|
};
|
|
7560
7850
|
const tabManager = new TabManager(mainWindow, onTabStateChange);
|
|
7561
7851
|
const sendToRendererViews = (channel, ...args) => {
|
|
@@ -7571,6 +7861,8 @@ function createMainWindow(onTabStateChange) {
|
|
|
7571
7861
|
mainWindow,
|
|
7572
7862
|
sidebarWindow: null,
|
|
7573
7863
|
sidebarWindowClosing: false,
|
|
7864
|
+
devtoolsPanelWindow: null,
|
|
7865
|
+
devtoolsPanelWindowClosing: false,
|
|
7574
7866
|
chromeView,
|
|
7575
7867
|
sidebarView,
|
|
7576
7868
|
devtoolsPanelView,
|
|
@@ -7582,6 +7874,7 @@ function createMainWindow(onTabStateChange) {
|
|
|
7582
7874
|
mainWindow.on("focus", () => layoutViews(state2));
|
|
7583
7875
|
mainWindow.on("closed", () => {
|
|
7584
7876
|
closeDetachedSidebarWindow(state2);
|
|
7877
|
+
closeDetachedDevToolsPanelWindow(state2);
|
|
7585
7878
|
});
|
|
7586
7879
|
sidebarView.webContents.on("context-menu", (event, params) => {
|
|
7587
7880
|
event.preventDefault();
|
|
@@ -7610,7 +7903,9 @@ function layoutViews(state2) {
|
|
|
7610
7903
|
const chromeHeight = uiState.focusMode ? 0 : CHROME_HEIGHT;
|
|
7611
7904
|
const sidebarAttached = isSidebarAttached(state2);
|
|
7612
7905
|
const sidebarWidth = sidebarAttached ? uiState.sidebarWidth : 0;
|
|
7613
|
-
const
|
|
7906
|
+
const devtoolsDocked = isDevToolsPanelDocked(state2);
|
|
7907
|
+
const devtoolsDetached = isDevToolsPanelDetached(state2);
|
|
7908
|
+
const devtoolsHeight = devtoolsDocked ? uiState.devtoolsPanelHeight : 0;
|
|
7614
7909
|
const chromeNeedsFullHeight = uiState.settingsOpen;
|
|
7615
7910
|
if (chromeNeedsFullHeight) {
|
|
7616
7911
|
chromeView.setBounds({ x: 0, y: 0, width, height });
|
|
@@ -7628,14 +7923,14 @@ function layoutViews(state2) {
|
|
|
7628
7923
|
sidebarView.setBounds({ x: width, y: 0, width: 0, height: 0 });
|
|
7629
7924
|
}
|
|
7630
7925
|
const contentWidth = width - sidebarWidth;
|
|
7631
|
-
if (
|
|
7926
|
+
if (devtoolsDocked) {
|
|
7632
7927
|
devtoolsPanelView.setBounds({
|
|
7633
7928
|
x: 0,
|
|
7634
7929
|
y: height - devtoolsHeight,
|
|
7635
7930
|
width: contentWidth,
|
|
7636
7931
|
height: devtoolsHeight
|
|
7637
7932
|
});
|
|
7638
|
-
} else {
|
|
7933
|
+
} else if (!devtoolsDetached) {
|
|
7639
7934
|
devtoolsPanelView.setBounds({ x: 0, y: height, width: 0, height: 0 });
|
|
7640
7935
|
}
|
|
7641
7936
|
mainWindow.contentView.removeChildView(chromeView);
|
|
@@ -7644,8 +7939,10 @@ function layoutViews(state2) {
|
|
|
7644
7939
|
mainWindow.contentView.removeChildView(sidebarView);
|
|
7645
7940
|
mainWindow.contentView.addChildView(sidebarView);
|
|
7646
7941
|
}
|
|
7647
|
-
|
|
7648
|
-
|
|
7942
|
+
if (!devtoolsDetached) {
|
|
7943
|
+
mainWindow.contentView.removeChildView(devtoolsPanelView);
|
|
7944
|
+
mainWindow.contentView.addChildView(devtoolsPanelView);
|
|
7945
|
+
}
|
|
7649
7946
|
const activeTab = tabManager.getActiveTab();
|
|
7650
7947
|
if (activeTab) {
|
|
7651
7948
|
activeTab.view.setBounds({
|
|
@@ -7661,7 +7958,8 @@ function resizeSidebarViews(state2) {
|
|
|
7661
7958
|
const [width, height] = mainWindow.getContentSize();
|
|
7662
7959
|
const chromeHeight = uiState.focusMode ? 0 : CHROME_HEIGHT;
|
|
7663
7960
|
const sidebarWidth = isSidebarAttached(state2) ? uiState.sidebarWidth : 0;
|
|
7664
|
-
const
|
|
7961
|
+
const devtoolsDocked = isDevToolsPanelDocked(state2);
|
|
7962
|
+
const devtoolsHeight = devtoolsDocked ? uiState.devtoolsPanelHeight : 0;
|
|
7665
7963
|
const contentWidth = width - sidebarWidth;
|
|
7666
7964
|
if (uiState.sidebarPanelMode !== "detached") {
|
|
7667
7965
|
sidebarView.setBounds({
|
|
@@ -7671,7 +7969,7 @@ function resizeSidebarViews(state2) {
|
|
|
7671
7969
|
height: height - chromeHeight
|
|
7672
7970
|
});
|
|
7673
7971
|
}
|
|
7674
|
-
if (
|
|
7972
|
+
if (devtoolsDocked) {
|
|
7675
7973
|
devtoolsPanelView.setBounds({
|
|
7676
7974
|
x: 0,
|
|
7677
7975
|
y: height - devtoolsHeight,
|
|
@@ -10295,9 +10593,18 @@ function summarizeToolArg(args) {
|
|
|
10295
10593
|
function normalizeCodexText(text) {
|
|
10296
10594
|
return text.trim().toLowerCase().replace(/[‘’]/g, "'").replace(/[“”]/g, '"');
|
|
10297
10595
|
}
|
|
10298
|
-
function looksLikeFailedToolOutput(output) {
|
|
10596
|
+
function looksLikeFailedToolOutput(output, toolName) {
|
|
10299
10597
|
const normalized = normalizeCodexText(output);
|
|
10300
|
-
|
|
10598
|
+
const firstLine = normalized.split(/\n+/).map((line) => line.trim()).find(Boolean) ?? "";
|
|
10599
|
+
if (/^(?:error\b|error\[|blocked\b|warning\b|target\b|no active tab\b|cannot\b|can't\b)/.test(
|
|
10600
|
+
firstLine
|
|
10601
|
+
)) {
|
|
10602
|
+
return true;
|
|
10603
|
+
}
|
|
10604
|
+
if (toolName === "click" && (normalized.includes("page did not change after click") || normalized.includes("element may need a different interaction method"))) {
|
|
10605
|
+
return true;
|
|
10606
|
+
}
|
|
10607
|
+
return toolName === "type_text" && /^(?:could not|did not|no focused|no visible)/.test(firstLine);
|
|
10301
10608
|
}
|
|
10302
10609
|
function looksLikeTravelFareContext(text) {
|
|
10303
10610
|
const normalized = normalizeCodexText(text);
|
|
@@ -10305,7 +10612,7 @@ function looksLikeTravelFareContext(text) {
|
|
|
10305
10612
|
}
|
|
10306
10613
|
function emitCodexToolChunk(onChunk, name, args, output) {
|
|
10307
10614
|
const summary = summarizeToolArg(args);
|
|
10308
|
-
const argSummary = looksLikeFailedToolOutput(output) ? ["⚠ failed", summary].filter(Boolean).join(" ") : summary;
|
|
10615
|
+
const argSummary = looksLikeFailedToolOutput(output, name) ? ["⚠ failed", summary].filter(Boolean).join(" ") : summary;
|
|
10309
10616
|
onChunk(`
|
|
10310
10617
|
<<tool:${name}${argSummary ? ":" + argSummary : ""}>>
|
|
10311
10618
|
`);
|
|
@@ -10970,7 +11277,10 @@ ${latestToolResultPreview || ""}`
|
|
|
10970
11277
|
toolHistoryCount += 1;
|
|
10971
11278
|
latestToolResultPreview = previewToolResult(output.output);
|
|
10972
11279
|
const outputText = toolResultTextContent(output.output);
|
|
10973
|
-
const toolSucceeded = !looksLikeFailedToolOutput(
|
|
11280
|
+
const toolSucceeded = !looksLikeFailedToolOutput(
|
|
11281
|
+
outputText,
|
|
11282
|
+
prepared.prepared.name
|
|
11283
|
+
);
|
|
10974
11284
|
if (toolSucceeded && isRealProgressTool(prepared.prepared.name)) {
|
|
10975
11285
|
failedClickCountSinceProgress = 0;
|
|
10976
11286
|
}
|
|
@@ -10979,7 +11289,7 @@ ${latestToolResultPreview || ""}`
|
|
|
10979
11289
|
searchToolQuery,
|
|
10980
11290
|
toolSucceeded
|
|
10981
11291
|
);
|
|
10982
|
-
if (prepared.prepared.name === "click" && looksLikeFailedToolOutput(outputText)) {
|
|
11292
|
+
if (prepared.prepared.name === "click" && looksLikeFailedToolOutput(outputText, prepared.prepared.name)) {
|
|
10983
11293
|
failedClickCountSinceProgress += 1;
|
|
10984
11294
|
currentInput.push(
|
|
10985
11295
|
buildCodexFailedClickRecoveryInput(
|
|
@@ -22978,7 +23288,7 @@ function registerPrivateIpcHandlers(state2) {
|
|
|
22978
23288
|
});
|
|
22979
23289
|
ipc.handle(Channels.FOCUS_MODE_TOGGLE, () => false);
|
|
22980
23290
|
ipc.handle(Channels.SIDEBAR_TOGGLE, () => ({ open: false, width: 0 }));
|
|
22981
|
-
ipc
|
|
23291
|
+
registerDisabledDevToolsPanelHandlers(ipc);
|
|
22982
23292
|
ipc.handle(
|
|
22983
23293
|
Channels.FIND_IN_PAGE_START,
|
|
22984
23294
|
(_e, text, options) => {
|
|
@@ -23242,7 +23552,7 @@ function registerSecondaryIpcHandlers(state2) {
|
|
|
23242
23552
|
ipc.handle(Channels.SETTINGS_VISIBILITY, () => false);
|
|
23243
23553
|
ipc.handle(Channels.FOCUS_MODE_TOGGLE, () => false);
|
|
23244
23554
|
ipc.handle(Channels.SIDEBAR_TOGGLE, () => ({ open: false, width: 0 }));
|
|
23245
|
-
ipc
|
|
23555
|
+
registerDisabledDevToolsPanelHandlers(ipc);
|
|
23246
23556
|
ipc.handle(
|
|
23247
23557
|
Channels.FIND_IN_PAGE_START,
|
|
23248
23558
|
(_e, text, options) => {
|
|
@@ -24775,8 +25085,14 @@ const DANGEROUS_DEVTOOLS_ACTIONS = /* @__PURE__ */ new Set([
|
|
|
24775
25085
|
]);
|
|
24776
25086
|
let stateListener = null;
|
|
24777
25087
|
const activityLog = [];
|
|
25088
|
+
const agentTraceLog = [];
|
|
24778
25089
|
const MAX_ACTIVITY_ENTRIES = 100;
|
|
25090
|
+
const MAX_TRACE_ENTRIES = 200;
|
|
24779
25091
|
let activityCounter = 0;
|
|
25092
|
+
let traceCounter = 0;
|
|
25093
|
+
let latestPageMap = null;
|
|
25094
|
+
let pageMapRefreshInFlight = false;
|
|
25095
|
+
const traceEntriesByActionId = /* @__PURE__ */ new Map();
|
|
24780
25096
|
function setDevToolsPanelListener(listener) {
|
|
24781
25097
|
stateListener = listener;
|
|
24782
25098
|
}
|
|
@@ -24786,14 +25102,325 @@ function getDevToolsPanelState(tabId) {
|
|
|
24786
25102
|
console: session?.getConsoleLogs() ?? [],
|
|
24787
25103
|
network: session?.getNetworkLog() ?? [],
|
|
24788
25104
|
errors: session?.getErrors() ?? [],
|
|
24789
|
-
activity: activityLog
|
|
25105
|
+
activity: activityLog,
|
|
25106
|
+
agentTrace: agentTraceLog,
|
|
25107
|
+
pageMap: latestPageMap
|
|
24790
25108
|
};
|
|
24791
25109
|
}
|
|
24792
|
-
function
|
|
25110
|
+
function broadcastDevToolsPanelState(tabManager) {
|
|
24793
25111
|
if (!stateListener) return;
|
|
24794
25112
|
const tabId = tabManager.getActiveTabId();
|
|
24795
25113
|
stateListener(getDevToolsPanelState(tabId));
|
|
24796
25114
|
}
|
|
25115
|
+
let panelBroadcastScheduled = false;
|
|
25116
|
+
let panelBroadcastTabManager = null;
|
|
25117
|
+
let panelCapturedTabId = null;
|
|
25118
|
+
const panelOwnedCaptureTabs = /* @__PURE__ */ new Set();
|
|
25119
|
+
function schedulePanelBroadcast(tabManager) {
|
|
25120
|
+
panelBroadcastTabManager = tabManager;
|
|
25121
|
+
if (panelBroadcastScheduled) return;
|
|
25122
|
+
panelBroadcastScheduled = true;
|
|
25123
|
+
queueMicrotask(() => {
|
|
25124
|
+
panelBroadcastScheduled = false;
|
|
25125
|
+
if (panelBroadcastTabManager) {
|
|
25126
|
+
broadcastDevToolsPanelState(panelBroadcastTabManager);
|
|
25127
|
+
}
|
|
25128
|
+
});
|
|
25129
|
+
}
|
|
25130
|
+
function releasePanelCaptureForTab(tabId) {
|
|
25131
|
+
const session = getSession(tabId);
|
|
25132
|
+
session?.setOnCaptureChange(null);
|
|
25133
|
+
if (panelCapturedTabId === tabId) {
|
|
25134
|
+
panelCapturedTabId = null;
|
|
25135
|
+
}
|
|
25136
|
+
if (panelOwnedCaptureTabs.delete(tabId)) {
|
|
25137
|
+
destroySession(tabId);
|
|
25138
|
+
}
|
|
25139
|
+
}
|
|
25140
|
+
function markActiveSessionToolOwned(tabManager) {
|
|
25141
|
+
const tabId = tabManager.getActiveTabId();
|
|
25142
|
+
if (tabId) {
|
|
25143
|
+
panelOwnedCaptureTabs.delete(tabId);
|
|
25144
|
+
}
|
|
25145
|
+
}
|
|
25146
|
+
async function enableCaptureForTab(tabManager) {
|
|
25147
|
+
const tabId = tabManager.getActiveTabId();
|
|
25148
|
+
if (!tabId) return;
|
|
25149
|
+
if (panelCapturedTabId && panelCapturedTabId !== tabId) {
|
|
25150
|
+
releasePanelCaptureForTab(panelCapturedTabId);
|
|
25151
|
+
}
|
|
25152
|
+
let session = getSession(tabId);
|
|
25153
|
+
const panelCreatedSession = !session;
|
|
25154
|
+
session ??= getOrCreateSession(tabManager);
|
|
25155
|
+
if (panelCreatedSession) {
|
|
25156
|
+
panelOwnedCaptureTabs.add(tabId);
|
|
25157
|
+
}
|
|
25158
|
+
panelCapturedTabId = tabId;
|
|
25159
|
+
session.setOnCaptureChange(() => {
|
|
25160
|
+
if (panelCapturedTabId === tabId) {
|
|
25161
|
+
schedulePanelBroadcast(tabManager);
|
|
25162
|
+
}
|
|
25163
|
+
});
|
|
25164
|
+
await session.enableCapture();
|
|
25165
|
+
if (panelCapturedTabId === tabId) {
|
|
25166
|
+
broadcastDevToolsPanelState(tabManager);
|
|
25167
|
+
}
|
|
25168
|
+
}
|
|
25169
|
+
function disableCaptureForTab(tabId) {
|
|
25170
|
+
const targetTabId = panelCapturedTabId;
|
|
25171
|
+
if (targetTabId) {
|
|
25172
|
+
releasePanelCaptureForTab(targetTabId);
|
|
25173
|
+
}
|
|
25174
|
+
{
|
|
25175
|
+
for (const ownedTabId of [...panelOwnedCaptureTabs]) {
|
|
25176
|
+
releasePanelCaptureForTab(ownedTabId);
|
|
25177
|
+
}
|
|
25178
|
+
panelBroadcastTabManager = null;
|
|
25179
|
+
}
|
|
25180
|
+
}
|
|
25181
|
+
function pushTrace(entry) {
|
|
25182
|
+
const traceEntry = {
|
|
25183
|
+
id: ++traceCounter,
|
|
25184
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
25185
|
+
...entry
|
|
25186
|
+
};
|
|
25187
|
+
agentTraceLog.push(traceEntry);
|
|
25188
|
+
if (agentTraceLog.length > MAX_TRACE_ENTRIES) {
|
|
25189
|
+
const removed = agentTraceLog.splice(
|
|
25190
|
+
0,
|
|
25191
|
+
agentTraceLog.length - MAX_TRACE_ENTRIES
|
|
25192
|
+
);
|
|
25193
|
+
for (const trace of removed) {
|
|
25194
|
+
if (trace.actionId) traceEntriesByActionId.delete(trace.actionId);
|
|
25195
|
+
}
|
|
25196
|
+
}
|
|
25197
|
+
return traceEntry;
|
|
25198
|
+
}
|
|
25199
|
+
function formatTraceActionName(name) {
|
|
25200
|
+
return name.replace(/^devtools_/, "").split(/[_-]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
25201
|
+
}
|
|
25202
|
+
function traceDetail(event) {
|
|
25203
|
+
const sourcePrefix = event.source === "ai" ? "Agent" : event.source.toUpperCase();
|
|
25204
|
+
return [sourcePrefix, event.detail].filter(Boolean).join(": ").slice(0, 240);
|
|
25205
|
+
}
|
|
25206
|
+
function recordDevToolsAgentAction(event, tabManager) {
|
|
25207
|
+
const actionName = formatTraceActionName(event.name);
|
|
25208
|
+
if (event.phase === "started") {
|
|
25209
|
+
const entry = pushTrace({
|
|
25210
|
+
actionId: event.actionId,
|
|
25211
|
+
kind: "tool-start",
|
|
25212
|
+
title: `Started ${actionName}`,
|
|
25213
|
+
detail: traceDetail(event),
|
|
25214
|
+
status: "running",
|
|
25215
|
+
tool: event.name
|
|
25216
|
+
});
|
|
25217
|
+
traceEntriesByActionId.set(event.actionId, entry);
|
|
25218
|
+
broadcastDevToolsPanelState(tabManager);
|
|
25219
|
+
return;
|
|
25220
|
+
}
|
|
25221
|
+
const startEntry = traceEntriesByActionId.get(event.actionId);
|
|
25222
|
+
if (startEntry) {
|
|
25223
|
+
startEntry.status = event.phase === "completed" ? "completed" : "failed";
|
|
25224
|
+
startEntry.durationMs = event.durationMs;
|
|
25225
|
+
if (event.phase === "waiting-approval") {
|
|
25226
|
+
startEntry.status = "running";
|
|
25227
|
+
startEntry.detail = traceDetail(event);
|
|
25228
|
+
}
|
|
25229
|
+
}
|
|
25230
|
+
if (event.phase === "waiting-approval") {
|
|
25231
|
+
broadcastDevToolsPanelState(tabManager);
|
|
25232
|
+
return;
|
|
25233
|
+
}
|
|
25234
|
+
pushTrace({
|
|
25235
|
+
actionId: event.actionId,
|
|
25236
|
+
kind: event.phase === "completed" ? "tool-complete" : "tool-error",
|
|
25237
|
+
title: event.phase === "completed" ? `Completed ${actionName}` : `${event.phase === "rejected" ? "Rejected" : "Failed"} ${actionName}`,
|
|
25238
|
+
detail: traceDetail(event),
|
|
25239
|
+
status: event.phase === "completed" ? "completed" : "failed",
|
|
25240
|
+
tool: event.name,
|
|
25241
|
+
durationMs: event.durationMs
|
|
25242
|
+
});
|
|
25243
|
+
traceEntriesByActionId.delete(event.actionId);
|
|
25244
|
+
broadcastDevToolsPanelState(tabManager);
|
|
25245
|
+
}
|
|
25246
|
+
const PAGE_MAP_SCRIPT = `
|
|
25247
|
+
(() => {
|
|
25248
|
+
const INTERACTIVE_SELECTOR = [
|
|
25249
|
+
"a[href]",
|
|
25250
|
+
"button",
|
|
25251
|
+
"input",
|
|
25252
|
+
"select",
|
|
25253
|
+
"textarea",
|
|
25254
|
+
"summary",
|
|
25255
|
+
"[role='button']",
|
|
25256
|
+
"[role='link']",
|
|
25257
|
+
"[role='checkbox']",
|
|
25258
|
+
"[role='radio']",
|
|
25259
|
+
"[role='switch']",
|
|
25260
|
+
"[role='tab']",
|
|
25261
|
+
"[role='menuitem']",
|
|
25262
|
+
"[contenteditable='true']",
|
|
25263
|
+
"[tabindex]:not([tabindex='-1'])"
|
|
25264
|
+
].join(",");
|
|
25265
|
+
|
|
25266
|
+
function round(value) {
|
|
25267
|
+
return Math.round(value * 10) / 10;
|
|
25268
|
+
}
|
|
25269
|
+
|
|
25270
|
+
function textFor(el) {
|
|
25271
|
+
const direct =
|
|
25272
|
+
el.getAttribute("aria-label") ||
|
|
25273
|
+
el.getAttribute("title") ||
|
|
25274
|
+
el.getAttribute("placeholder") ||
|
|
25275
|
+
el.getAttribute("alt") ||
|
|
25276
|
+
el.value ||
|
|
25277
|
+
el.innerText ||
|
|
25278
|
+
el.textContent ||
|
|
25279
|
+
"";
|
|
25280
|
+
return String(direct).replace(/\\s+/g, " ").trim().slice(0, 140);
|
|
25281
|
+
}
|
|
25282
|
+
|
|
25283
|
+
function selectorFor(el) {
|
|
25284
|
+
if (el.id) return "#" + CSS.escape(el.id);
|
|
25285
|
+
const parts = [];
|
|
25286
|
+
let node = el;
|
|
25287
|
+
while (node && node.nodeType === Node.ELEMENT_NODE && parts.length < 4) {
|
|
25288
|
+
let part = node.localName;
|
|
25289
|
+
const classes = Array.from(node.classList || []).slice(0, 2);
|
|
25290
|
+
if (classes.length) part += "." + classes.map((c) => CSS.escape(c)).join(".");
|
|
25291
|
+
const parent = node.parentElement;
|
|
25292
|
+
if (parent) {
|
|
25293
|
+
const siblings = Array.from(parent.children).filter((child) => child.localName === node.localName);
|
|
25294
|
+
if (siblings.length > 1) part += ":nth-of-type(" + (siblings.indexOf(node) + 1) + ")";
|
|
25295
|
+
}
|
|
25296
|
+
parts.unshift(part);
|
|
25297
|
+
node = parent;
|
|
25298
|
+
}
|
|
25299
|
+
return parts.join(" > ");
|
|
25300
|
+
}
|
|
25301
|
+
|
|
25302
|
+
function isVisible(el, style, rect) {
|
|
25303
|
+
return rect.width > 0 &&
|
|
25304
|
+
rect.height > 0 &&
|
|
25305
|
+
style.display !== "none" &&
|
|
25306
|
+
style.visibility !== "hidden" &&
|
|
25307
|
+
Number(style.opacity || "1") > 0.01;
|
|
25308
|
+
}
|
|
25309
|
+
|
|
25310
|
+
const viewport = {
|
|
25311
|
+
width: window.innerWidth,
|
|
25312
|
+
height: window.innerHeight,
|
|
25313
|
+
scrollX: window.scrollX,
|
|
25314
|
+
scrollY: window.scrollY,
|
|
25315
|
+
};
|
|
25316
|
+
|
|
25317
|
+
const candidates = Array.from(document.querySelectorAll(INTERACTIVE_SELECTOR));
|
|
25318
|
+
const elements = candidates.slice(0, 120).map((el, index) => {
|
|
25319
|
+
const style = window.getComputedStyle(el);
|
|
25320
|
+
const rect = el.getBoundingClientRect();
|
|
25321
|
+
const visible = isVisible(el, style, rect);
|
|
25322
|
+
const disabled = Boolean(el.disabled) || el.getAttribute("aria-disabled") === "true";
|
|
25323
|
+
const inViewport = rect.bottom >= 0 && rect.right >= 0 && rect.top <= viewport.height && rect.left <= viewport.width;
|
|
25324
|
+
let issue = "";
|
|
25325
|
+
let blocked = false;
|
|
25326
|
+
if (!visible) issue = "hidden";
|
|
25327
|
+
else if (!inViewport) issue = "offscreen";
|
|
25328
|
+
else {
|
|
25329
|
+
const centerX = Math.min(Math.max(rect.left + rect.width / 2, 0), viewport.width - 1);
|
|
25330
|
+
const centerY = Math.min(Math.max(rect.top + rect.height / 2, 0), viewport.height - 1);
|
|
25331
|
+
const top = document.elementFromPoint(centerX, centerY);
|
|
25332
|
+
if (top && top !== el && !el.contains(top)) {
|
|
25333
|
+
blocked = true;
|
|
25334
|
+
issue = "covered by " + top.localName;
|
|
25335
|
+
}
|
|
25336
|
+
}
|
|
25337
|
+
return {
|
|
25338
|
+
id: index + 1,
|
|
25339
|
+
tag: el.localName,
|
|
25340
|
+
role: el.getAttribute("role") || undefined,
|
|
25341
|
+
label: textFor(el) || "(unlabeled)",
|
|
25342
|
+
selector: selectorFor(el),
|
|
25343
|
+
href: el.href || undefined,
|
|
25344
|
+
type: el.type || undefined,
|
|
25345
|
+
visible,
|
|
25346
|
+
interactable: visible && inViewport && !disabled && !blocked,
|
|
25347
|
+
disabled,
|
|
25348
|
+
issue: issue || undefined,
|
|
25349
|
+
bounds: {
|
|
25350
|
+
x: round(rect.x),
|
|
25351
|
+
y: round(rect.y),
|
|
25352
|
+
width: round(rect.width),
|
|
25353
|
+
height: round(rect.height),
|
|
25354
|
+
},
|
|
25355
|
+
};
|
|
25356
|
+
});
|
|
25357
|
+
|
|
25358
|
+
const counts = elements.reduce((acc, element) => {
|
|
25359
|
+
acc.total += 1;
|
|
25360
|
+
if (element.visible) acc.visible += 1;
|
|
25361
|
+
if (element.interactable) acc.interactable += 1;
|
|
25362
|
+
if (element.disabled) acc.disabled += 1;
|
|
25363
|
+
if (element.issue && element.issue.startsWith("covered")) acc.blocked += 1;
|
|
25364
|
+
return acc;
|
|
25365
|
+
}, { total: 0, visible: 0, interactable: 0, disabled: 0, blocked: 0 });
|
|
25366
|
+
|
|
25367
|
+
return {
|
|
25368
|
+
timestamp: new Date().toISOString(),
|
|
25369
|
+
pageUrl: location.href,
|
|
25370
|
+
title: document.title || "",
|
|
25371
|
+
viewport,
|
|
25372
|
+
counts,
|
|
25373
|
+
elements,
|
|
25374
|
+
accessIssues: elements.length === 0 ? ["No obvious interactive elements found."] : [],
|
|
25375
|
+
};
|
|
25376
|
+
})()
|
|
25377
|
+
`;
|
|
25378
|
+
async function capturePageMapSnapshot(tabManager) {
|
|
25379
|
+
const tab = tabManager.getActiveTab();
|
|
25380
|
+
if (!tab || tab.view.webContents.isDestroyed()) {
|
|
25381
|
+
return {
|
|
25382
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
25383
|
+
pageUrl: "",
|
|
25384
|
+
title: "No active tab",
|
|
25385
|
+
viewport: { width: 0, height: 0, scrollX: 0, scrollY: 0 },
|
|
25386
|
+
counts: { total: 0, visible: 0, interactable: 0, disabled: 0, blocked: 0 },
|
|
25387
|
+
elements: [],
|
|
25388
|
+
accessIssues: ["No active tab is available."]
|
|
25389
|
+
};
|
|
25390
|
+
}
|
|
25391
|
+
try {
|
|
25392
|
+
return await tab.view.webContents.executeJavaScript(PAGE_MAP_SCRIPT, true);
|
|
25393
|
+
} catch (error) {
|
|
25394
|
+
return {
|
|
25395
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
25396
|
+
pageUrl: tab.view.webContents.getURL(),
|
|
25397
|
+
title: "Page map unavailable",
|
|
25398
|
+
viewport: { width: 0, height: 0, scrollX: 0, scrollY: 0 },
|
|
25399
|
+
counts: { total: 0, visible: 0, interactable: 0, disabled: 0, blocked: 0 },
|
|
25400
|
+
elements: [],
|
|
25401
|
+
accessIssues: [
|
|
25402
|
+
error instanceof Error ? error.message : "Could not inspect active page."
|
|
25403
|
+
]
|
|
25404
|
+
};
|
|
25405
|
+
}
|
|
25406
|
+
}
|
|
25407
|
+
async function refreshDevToolsPageMap(tabManager) {
|
|
25408
|
+
if (pageMapRefreshInFlight) {
|
|
25409
|
+
return getDevToolsPanelState(tabManager.getActiveTabId());
|
|
25410
|
+
}
|
|
25411
|
+
pageMapRefreshInFlight = true;
|
|
25412
|
+
try {
|
|
25413
|
+
latestPageMap = await capturePageMapSnapshot(tabManager);
|
|
25414
|
+
} finally {
|
|
25415
|
+
pageMapRefreshInFlight = false;
|
|
25416
|
+
}
|
|
25417
|
+
broadcastDevToolsPanelState(tabManager);
|
|
25418
|
+
return getDevToolsPanelState(tabManager.getActiveTabId());
|
|
25419
|
+
}
|
|
25420
|
+
function broadcastState(tabManager) {
|
|
25421
|
+
broadcastDevToolsPanelState(tabManager);
|
|
25422
|
+
void refreshDevToolsPageMap(tabManager);
|
|
25423
|
+
}
|
|
24797
25424
|
async function withDevToolsAction(runtime2, tabManager, name, args, executor) {
|
|
24798
25425
|
try {
|
|
24799
25426
|
assertFeatureUnlocked("devtools", "DevTools");
|
|
@@ -24802,6 +25429,7 @@ async function withDevToolsAction(runtime2, tabManager, name, args, executor) {
|
|
|
24802
25429
|
`Error: ${error instanceof Error ? error.message : "DevTools require Vessel Premium."}`
|
|
24803
25430
|
);
|
|
24804
25431
|
}
|
|
25432
|
+
markActiveSessionToolOwned(tabManager);
|
|
24805
25433
|
const activityEntry = {
|
|
24806
25434
|
id: ++activityCounter,
|
|
24807
25435
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -30420,6 +31048,76 @@ async function togglePictureInPicture(tabManager) {
|
|
|
30420
31048
|
return false;
|
|
30421
31049
|
}
|
|
30422
31050
|
}
|
|
31051
|
+
const REVEAL_SCRIPT = `
|
|
31052
|
+
(function () {
|
|
31053
|
+
var selector = __SELECTOR_JSON__;
|
|
31054
|
+
try {
|
|
31055
|
+
var el = document.querySelector(selector);
|
|
31056
|
+
} catch (e) {
|
|
31057
|
+
return "invalid-selector";
|
|
31058
|
+
}
|
|
31059
|
+
if (!el) return "not-found";
|
|
31060
|
+
try {
|
|
31061
|
+
el.scrollIntoView({ block: "center", behavior: "smooth" });
|
|
31062
|
+
} catch (e) {}
|
|
31063
|
+
var rect = el.getBoundingClientRect();
|
|
31064
|
+
var overlay = document.createElement("div");
|
|
31065
|
+
overlay.setAttribute("data-vessel-devtools-reveal", "");
|
|
31066
|
+
overlay.style.cssText = [
|
|
31067
|
+
"position: fixed",
|
|
31068
|
+
"left: " + rect.left + "px",
|
|
31069
|
+
"top: " + rect.top + "px",
|
|
31070
|
+
"width: " + rect.width + "px",
|
|
31071
|
+
"height: " + rect.height + "px",
|
|
31072
|
+
"box-sizing: border-box",
|
|
31073
|
+
"border: 2px solid #4f8cff",
|
|
31074
|
+
"background: rgba(79, 140, 255, 0.18)",
|
|
31075
|
+
"border-radius: 4px",
|
|
31076
|
+
"pointer-events: none",
|
|
31077
|
+
"z-index: 2147483647",
|
|
31078
|
+
"transition: opacity 250ms ease-out",
|
|
31079
|
+
"opacity: 1",
|
|
31080
|
+
].join("; ");
|
|
31081
|
+
document.documentElement.appendChild(overlay);
|
|
31082
|
+
var start = performance.now();
|
|
31083
|
+
function track(now) {
|
|
31084
|
+
var r = el.getBoundingClientRect();
|
|
31085
|
+
overlay.style.left = r.left + "px";
|
|
31086
|
+
overlay.style.top = r.top + "px";
|
|
31087
|
+
overlay.style.width = r.width + "px";
|
|
31088
|
+
overlay.style.height = r.height + "px";
|
|
31089
|
+
if (now - start < 1000) {
|
|
31090
|
+
requestAnimationFrame(track);
|
|
31091
|
+
} else {
|
|
31092
|
+
overlay.style.opacity = "0";
|
|
31093
|
+
setTimeout(function () {
|
|
31094
|
+
if (overlay.parentNode) overlay.parentNode.removeChild(overlay);
|
|
31095
|
+
}, 300);
|
|
31096
|
+
}
|
|
31097
|
+
}
|
|
31098
|
+
requestAnimationFrame(track);
|
|
31099
|
+
return "revealed";
|
|
31100
|
+
})();
|
|
31101
|
+
`;
|
|
31102
|
+
async function revealPageMapElement(tabManager, selector) {
|
|
31103
|
+
const tab = tabManager.getActiveTab();
|
|
31104
|
+
if (!tab || tab.view.webContents.isDestroyed()) {
|
|
31105
|
+
return "no-active-tab";
|
|
31106
|
+
}
|
|
31107
|
+
try {
|
|
31108
|
+
const script = REVEAL_SCRIPT.replace(
|
|
31109
|
+
"__SELECTOR_JSON__",
|
|
31110
|
+
JSON.stringify(selector)
|
|
31111
|
+
);
|
|
31112
|
+
const result = await tab.view.webContents.executeJavaScript(script, true);
|
|
31113
|
+
if (result === "revealed" || result === "not-found" || result === "invalid-selector") {
|
|
31114
|
+
return result;
|
|
31115
|
+
}
|
|
31116
|
+
return "revealed";
|
|
31117
|
+
} catch {
|
|
31118
|
+
return "invalid-selector";
|
|
31119
|
+
}
|
|
31120
|
+
}
|
|
30423
31121
|
const VALID_KIT_CATEGORIES = /* @__PURE__ */ new Set([
|
|
30424
31122
|
"research",
|
|
30425
31123
|
"shopping",
|
|
@@ -30940,21 +31638,177 @@ function stopScheduler() {
|
|
|
30940
31638
|
const KitIdSchema = zod.z.string().min(1);
|
|
30941
31639
|
const SkillSourceSchema = zod.z.string().min(1).max(1e5);
|
|
30942
31640
|
const OriginSchema = zod.z.string().min(1);
|
|
31641
|
+
const DevToolsHeightSchema = zod.z.number().finite().min(0).max(2e3);
|
|
31642
|
+
const DevToolsPageMapRevealSchema = zod.z.object({
|
|
31643
|
+
selector: zod.z.string().min(1)
|
|
31644
|
+
});
|
|
31645
|
+
const DevToolsPanelTabSchema = zod.z.enum([
|
|
31646
|
+
"console",
|
|
31647
|
+
"network",
|
|
31648
|
+
"activity",
|
|
31649
|
+
"agentTrace",
|
|
31650
|
+
"pageMap"
|
|
31651
|
+
]);
|
|
31652
|
+
const RendererViewSchema = zod.z.enum(["chrome", "sidebar", "devtools"]);
|
|
30943
31653
|
function registerSystemHandlers(windowState, sendToRendererViews) {
|
|
30944
31654
|
const { tabManager } = windowState;
|
|
31655
|
+
let devToolsResizeRecoveryTimer = null;
|
|
31656
|
+
let devToolsResizeActive = false;
|
|
31657
|
+
const relayout = () => layoutViews(windowState);
|
|
31658
|
+
const clearDevToolsResizeRecoveryTimer = () => {
|
|
31659
|
+
if (!devToolsResizeRecoveryTimer) return;
|
|
31660
|
+
clearTimeout(devToolsResizeRecoveryTimer);
|
|
31661
|
+
devToolsResizeRecoveryTimer = null;
|
|
31662
|
+
};
|
|
31663
|
+
const stopDevToolsResize = () => {
|
|
31664
|
+
devToolsResizeActive = false;
|
|
31665
|
+
clearDevToolsResizeRecoveryTimer();
|
|
31666
|
+
};
|
|
31667
|
+
const restoreDevToolsLayoutAfterResize = () => {
|
|
31668
|
+
clearDevToolsResizeRecoveryTimer();
|
|
31669
|
+
if (!devToolsResizeActive) return;
|
|
31670
|
+
devToolsResizeActive = false;
|
|
31671
|
+
relayout();
|
|
31672
|
+
};
|
|
31673
|
+
const scheduleDevToolsResizeRecovery = () => {
|
|
31674
|
+
clearDevToolsResizeRecoveryTimer();
|
|
31675
|
+
devToolsResizeRecoveryTimer = setTimeout(() => {
|
|
31676
|
+
restoreDevToolsLayoutAfterResize();
|
|
31677
|
+
}, 1200);
|
|
31678
|
+
};
|
|
31679
|
+
const maxDockedDevToolsHeight = () => {
|
|
31680
|
+
const [, windowHeight] = windowState.mainWindow.getContentSize();
|
|
31681
|
+
const chromeHeight = windowState.uiState.focusMode ? 0 : CHROME_HEIGHT;
|
|
31682
|
+
return Math.max(
|
|
31683
|
+
MIN_DEVTOOLS_PANEL,
|
|
31684
|
+
Math.min(MAX_DEVTOOLS_PANEL, windowHeight - chromeHeight - 80)
|
|
31685
|
+
);
|
|
31686
|
+
};
|
|
31687
|
+
windowState.mainWindow.once("closed", stopDevToolsResize);
|
|
30945
31688
|
electron.ipcMain.handle(Channels.DEVTOOLS_PANEL_TOGGLE, (event) => {
|
|
30946
31689
|
assertTrustedIpcSender(event);
|
|
30947
|
-
|
|
30948
|
-
|
|
30949
|
-
|
|
31690
|
+
stopDevToolsResize();
|
|
31691
|
+
const hostState = toggleDockedDevToolsPanel(windowState, { relayout });
|
|
31692
|
+
if (hostState.open) {
|
|
31693
|
+
void enableCaptureForTab(tabManager);
|
|
31694
|
+
} else {
|
|
31695
|
+
disableCaptureForTab();
|
|
31696
|
+
}
|
|
31697
|
+
return hostState;
|
|
31698
|
+
});
|
|
31699
|
+
electron.ipcMain.handle(Channels.DEVTOOLS_PANEL_CLOSE, (event) => {
|
|
31700
|
+
assertTrustedIpcSender(event);
|
|
31701
|
+
stopDevToolsResize();
|
|
31702
|
+
const hostState = closeDevToolsPanel(windowState, { relayout });
|
|
31703
|
+
disableCaptureForTab();
|
|
31704
|
+
return hostState;
|
|
31705
|
+
});
|
|
31706
|
+
electron.ipcMain.handle(Channels.DEVTOOLS_PANEL_OPEN_TAB, (event, tab) => {
|
|
31707
|
+
assertTrustedIpcSender(event);
|
|
31708
|
+
const selectedTab = parseIpc(DevToolsPanelTabSchema, tab, "tab");
|
|
31709
|
+
stopDevToolsResize();
|
|
31710
|
+
const wasOpen = getDevToolsPanelHostState(windowState).open;
|
|
31711
|
+
if (!wasOpen) {
|
|
31712
|
+
toggleDockedDevToolsPanel(windowState, { relayout });
|
|
31713
|
+
void enableCaptureForTab(tabManager);
|
|
31714
|
+
} else if (getDevToolsPanelHostState(windowState).detached) {
|
|
31715
|
+
windowState.devtoolsPanelWindow?.focus();
|
|
31716
|
+
}
|
|
31717
|
+
emitDevToolsPanelHostState(windowState);
|
|
31718
|
+
sendSafe(
|
|
31719
|
+
windowState.devtoolsPanelView.webContents,
|
|
31720
|
+
Channels.DEVTOOLS_PANEL_SELECT_TAB,
|
|
31721
|
+
selectedTab
|
|
31722
|
+
);
|
|
31723
|
+
if (selectedTab === "pageMap") {
|
|
31724
|
+
void refreshDevToolsPageMap(tabManager);
|
|
31725
|
+
}
|
|
31726
|
+
return getDevToolsPanelHostState(windowState);
|
|
31727
|
+
});
|
|
31728
|
+
electron.ipcMain.handle(Channels.DEVTOOLS_PANEL_RESIZE_START, (event) => {
|
|
31729
|
+
assertTrustedIpcSender(event);
|
|
31730
|
+
if (!getDevToolsPanelHostState(windowState).open) return;
|
|
31731
|
+
if (getDevToolsPanelHostState(windowState).detached) return;
|
|
31732
|
+
devToolsResizeActive = true;
|
|
31733
|
+
clearDevToolsResizeRecoveryTimer();
|
|
31734
|
+
const [windowWidth, windowHeight] = windowState.mainWindow.getContentSize();
|
|
31735
|
+
const chromeHeight = windowState.uiState.focusMode ? 0 : CHROME_HEIGHT;
|
|
31736
|
+
const sidebarWidth = isSidebarAttached(windowState) ? windowState.uiState.sidebarWidth : 0;
|
|
31737
|
+
windowState.devtoolsPanelView.setBounds({
|
|
31738
|
+
x: 0,
|
|
31739
|
+
y: chromeHeight,
|
|
31740
|
+
width: windowWidth - sidebarWidth,
|
|
31741
|
+
height: windowHeight - chromeHeight
|
|
31742
|
+
});
|
|
31743
|
+
scheduleDevToolsResizeRecovery();
|
|
30950
31744
|
});
|
|
30951
31745
|
electron.ipcMain.handle(Channels.DEVTOOLS_PANEL_RESIZE, (event, height) => {
|
|
30952
31746
|
assertTrustedIpcSender(event);
|
|
30953
|
-
const
|
|
30954
|
-
|
|
30955
|
-
|
|
31747
|
+
const validatedHeight = parseIpc(DevToolsHeightSchema, height, "height");
|
|
31748
|
+
const clamped = Math.max(
|
|
31749
|
+
MIN_DEVTOOLS_PANEL,
|
|
31750
|
+
Math.min(maxDockedDevToolsHeight(), Math.round(validatedHeight))
|
|
31751
|
+
);
|
|
31752
|
+
if (devToolsResizeActive) {
|
|
31753
|
+
windowState.uiState.devtoolsPanelHeight = clamped;
|
|
31754
|
+
scheduleDevToolsResizeRecovery();
|
|
31755
|
+
emitDevToolsPanelHostState(windowState);
|
|
31756
|
+
return clamped;
|
|
31757
|
+
}
|
|
31758
|
+
resizeDockedDevToolsPanel(windowState, clamped, relayout);
|
|
30956
31759
|
return clamped;
|
|
30957
31760
|
});
|
|
31761
|
+
electron.ipcMain.handle(Channels.DEVTOOLS_PANEL_RESIZE_COMMIT, (event) => {
|
|
31762
|
+
assertTrustedIpcSender(event);
|
|
31763
|
+
stopDevToolsResize();
|
|
31764
|
+
relayout();
|
|
31765
|
+
});
|
|
31766
|
+
electron.ipcMain.handle(Channels.DEVTOOLS_PANEL_POPOUT, (event) => {
|
|
31767
|
+
assertTrustedIpcSender(event);
|
|
31768
|
+
stopDevToolsResize();
|
|
31769
|
+
return detachDevToolsPanel(windowState, {
|
|
31770
|
+
relayout,
|
|
31771
|
+
getWindowIconPath
|
|
31772
|
+
});
|
|
31773
|
+
});
|
|
31774
|
+
electron.ipcMain.handle(Channels.DEVTOOLS_PANEL_DOCK, (event) => {
|
|
31775
|
+
assertTrustedIpcSender(event);
|
|
31776
|
+
stopDevToolsResize();
|
|
31777
|
+
return dockDevToolsPanel(windowState, { relayout });
|
|
31778
|
+
});
|
|
31779
|
+
electron.ipcMain.handle(Channels.DEVTOOLS_PANEL_STATE_GET, async (event) => {
|
|
31780
|
+
assertTrustedIpcSender(event);
|
|
31781
|
+
if (getDevToolsPanelHostState(windowState).open) {
|
|
31782
|
+
void enableCaptureForTab(tabManager);
|
|
31783
|
+
}
|
|
31784
|
+
return await refreshDevToolsPageMap(tabManager);
|
|
31785
|
+
});
|
|
31786
|
+
electron.ipcMain.handle(
|
|
31787
|
+
Channels.DEVTOOLS_PAGE_MAP_REVEAL,
|
|
31788
|
+
async (event, payload) => {
|
|
31789
|
+
assertTrustedIpcSender(event);
|
|
31790
|
+
const { selector } = parseIpc(
|
|
31791
|
+
DevToolsPageMapRevealSchema,
|
|
31792
|
+
payload,
|
|
31793
|
+
"payload"
|
|
31794
|
+
);
|
|
31795
|
+
return await revealPageMapElement(tabManager, selector);
|
|
31796
|
+
}
|
|
31797
|
+
);
|
|
31798
|
+
electron.ipcMain.handle(Channels.DEVTOOLS_PANEL_HOST_STATE_GET, (event) => {
|
|
31799
|
+
assertTrustedIpcSender(event);
|
|
31800
|
+
return getDevToolsPanelHostState(windowState);
|
|
31801
|
+
});
|
|
31802
|
+
electron.ipcMain.on(Channels.RENDERER_VIEW_READY, (event, view) => {
|
|
31803
|
+
assertTrustedIpcSender(event);
|
|
31804
|
+
const readyView = parseIpc(RendererViewSchema, view, "view");
|
|
31805
|
+
if (readyView !== "devtools") return;
|
|
31806
|
+
emitDevToolsPanelHostState(windowState);
|
|
31807
|
+
void refreshDevToolsPageMap(tabManager);
|
|
31808
|
+
if (getDevToolsPanelHostState(windowState).open) {
|
|
31809
|
+
void enableCaptureForTab(tabManager);
|
|
31810
|
+
}
|
|
31811
|
+
});
|
|
30958
31812
|
electron.ipcMain.handle(Channels.AUTOMATION_GET_INSTALLED, async (event) => {
|
|
30959
31813
|
assertTrustedIpcSender(event);
|
|
30960
31814
|
assertFeatureUnlocked("automation_kits", "Skills");
|
|
@@ -33344,6 +34198,7 @@ class AgentRuntime {
|
|
|
33344
34198
|
tabManager;
|
|
33345
34199
|
state;
|
|
33346
34200
|
updateListener = null;
|
|
34201
|
+
actionLifecycleListener = null;
|
|
33347
34202
|
pendingResolvers = /* @__PURE__ */ new Map();
|
|
33348
34203
|
undoSnapshots = [];
|
|
33349
34204
|
mcpUnsubscribe = null;
|
|
@@ -33353,6 +34208,9 @@ class AgentRuntime {
|
|
|
33353
34208
|
listener(this.getState());
|
|
33354
34209
|
}
|
|
33355
34210
|
}
|
|
34211
|
+
setActionLifecycleListener(listener) {
|
|
34212
|
+
this.actionLifecycleListener = listener;
|
|
34213
|
+
}
|
|
33356
34214
|
/**
|
|
33357
34215
|
* Release all resources, listeners, and pending promises.
|
|
33358
34216
|
* Call when the window is closing to prevent memory leaks.
|
|
@@ -33371,6 +34229,7 @@ class AgentRuntime {
|
|
|
33371
34229
|
this.state.flowState = null;
|
|
33372
34230
|
this.state.taskTracker = null;
|
|
33373
34231
|
this.updateListener = null;
|
|
34232
|
+
this.actionLifecycleListener = null;
|
|
33374
34233
|
}
|
|
33375
34234
|
getState() {
|
|
33376
34235
|
const snapshot2 = clone(this.state);
|
|
@@ -33675,8 +34534,18 @@ ${progress}
|
|
|
33675
34534
|
args,
|
|
33676
34535
|
tabId
|
|
33677
34536
|
});
|
|
34537
|
+
const actionStartedAt = Date.now();
|
|
33678
34538
|
const transcriptStreamId = `action:${action.id}`;
|
|
33679
34539
|
const transcriptTitle = humanizeActionName(name);
|
|
34540
|
+
this.emitActionLifecycle({
|
|
34541
|
+
actionId: action.id,
|
|
34542
|
+
source,
|
|
34543
|
+
name,
|
|
34544
|
+
args,
|
|
34545
|
+
tabId,
|
|
34546
|
+
phase: "started",
|
|
34547
|
+
detail: summarizeArgs(args)
|
|
34548
|
+
});
|
|
33680
34549
|
this.publishTranscript({
|
|
33681
34550
|
source,
|
|
33682
34551
|
kind: "status",
|
|
@@ -33687,6 +34556,16 @@ ${progress}
|
|
|
33687
34556
|
});
|
|
33688
34557
|
const approvalReason = this.getApprovalReason(dangerous, requiresApproval);
|
|
33689
34558
|
if (approvalReason) {
|
|
34559
|
+
this.emitActionLifecycle({
|
|
34560
|
+
actionId: action.id,
|
|
34561
|
+
source,
|
|
34562
|
+
name,
|
|
34563
|
+
args,
|
|
34564
|
+
tabId,
|
|
34565
|
+
phase: "waiting-approval",
|
|
34566
|
+
detail: approvalReason,
|
|
34567
|
+
durationMs: Date.now() - actionStartedAt
|
|
34568
|
+
});
|
|
33690
34569
|
this.publishTranscript({
|
|
33691
34570
|
source,
|
|
33692
34571
|
kind: "status",
|
|
@@ -33697,6 +34576,16 @@ ${progress}
|
|
|
33697
34576
|
});
|
|
33698
34577
|
const approved = await this.awaitApproval(action, approvalReason);
|
|
33699
34578
|
if (!approved) {
|
|
34579
|
+
this.emitActionLifecycle({
|
|
34580
|
+
actionId: action.id,
|
|
34581
|
+
source,
|
|
34582
|
+
name,
|
|
34583
|
+
args,
|
|
34584
|
+
tabId,
|
|
34585
|
+
phase: "rejected",
|
|
34586
|
+
detail: approvalReason,
|
|
34587
|
+
durationMs: Date.now() - actionStartedAt
|
|
34588
|
+
});
|
|
33700
34589
|
this.publishTranscript({
|
|
33701
34590
|
source,
|
|
33702
34591
|
kind: "status",
|
|
@@ -33728,6 +34617,16 @@ ${progress}
|
|
|
33728
34617
|
this.pushUndoSnapshot(undoSnapshot);
|
|
33729
34618
|
}
|
|
33730
34619
|
this.finishAction(action.id, "completed", summarizeText(result));
|
|
34620
|
+
this.emitActionLifecycle({
|
|
34621
|
+
actionId: action.id,
|
|
34622
|
+
source,
|
|
34623
|
+
name,
|
|
34624
|
+
args,
|
|
34625
|
+
tabId,
|
|
34626
|
+
phase: "completed",
|
|
34627
|
+
detail: summarizeText(result),
|
|
34628
|
+
durationMs: Date.now() - actionStartedAt
|
|
34629
|
+
});
|
|
33731
34630
|
this.publishTranscript({
|
|
33732
34631
|
source,
|
|
33733
34632
|
kind: "status",
|
|
@@ -33742,6 +34641,16 @@ ${progress}
|
|
|
33742
34641
|
const message = error instanceof Error ? error.message : "Unknown action failure";
|
|
33743
34642
|
this.state.supervisor.lastError = message;
|
|
33744
34643
|
this.finishAction(action.id, "failed", void 0, message);
|
|
34644
|
+
this.emitActionLifecycle({
|
|
34645
|
+
actionId: action.id,
|
|
34646
|
+
source,
|
|
34647
|
+
name,
|
|
34648
|
+
args,
|
|
34649
|
+
tabId,
|
|
34650
|
+
phase: "failed",
|
|
34651
|
+
detail: summarizeText(message),
|
|
34652
|
+
durationMs: Date.now() - actionStartedAt
|
|
34653
|
+
});
|
|
33745
34654
|
this.publishTranscript({
|
|
33746
34655
|
source,
|
|
33747
34656
|
kind: "status",
|
|
@@ -33753,6 +34662,15 @@ ${progress}
|
|
|
33753
34662
|
throw error;
|
|
33754
34663
|
}
|
|
33755
34664
|
}
|
|
34665
|
+
emitActionLifecycle(event) {
|
|
34666
|
+
try {
|
|
34667
|
+
this.actionLifecycleListener?.(event);
|
|
34668
|
+
} catch (error) {
|
|
34669
|
+
logger$3.warn("Action lifecycle listener failed", {
|
|
34670
|
+
error: error instanceof Error ? error.message : String(error)
|
|
34671
|
+
});
|
|
34672
|
+
}
|
|
34673
|
+
}
|
|
33756
34674
|
createUndoSnapshot(name) {
|
|
33757
34675
|
return {
|
|
33758
34676
|
id: crypto$1.randomUUID(),
|
|
@@ -34326,6 +35244,10 @@ async function bootstrap() {
|
|
|
34326
35244
|
if (meta.persistSession) {
|
|
34327
35245
|
runtime?.onTabStateChanged();
|
|
34328
35246
|
}
|
|
35247
|
+
if (windowState.uiState.devtoolsPanelMode !== "closed") {
|
|
35248
|
+
void enableCaptureForTab(windowState.tabManager);
|
|
35249
|
+
void refreshDevToolsPageMap(windowState.tabManager);
|
|
35250
|
+
}
|
|
34329
35251
|
});
|
|
34330
35252
|
windowStateForShutdown = windowState;
|
|
34331
35253
|
let didRevealMainWindow = false;
|
|
@@ -34342,6 +35264,9 @@ async function bootstrap() {
|
|
|
34342
35264
|
}, 8e3);
|
|
34343
35265
|
const { chromeView, sidebarView, devtoolsPanelView, tabManager } = windowState;
|
|
34344
35266
|
runtime = new AgentRuntime(tabManager);
|
|
35267
|
+
runtime.setActionLifecycleListener((event) => {
|
|
35268
|
+
recordDevToolsAgentAction(event, tabManager);
|
|
35269
|
+
});
|
|
34345
35270
|
installAdBlocking(tabManager);
|
|
34346
35271
|
setDevToolsPanelListener((state2) => {
|
|
34347
35272
|
sendSafe(devtoolsPanelView.webContents, Channels.DEVTOOLS_PANEL_STATE, state2);
|