local-operator-ui 0.38.0 → 0.39.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/out/main/index.js +1014 -58
- package/out/preload/index.js +36 -1
- package/out/renderer/assets/{_basePickBy-DhcDqJuW.js → _basePickBy-CBn_dsaM.js} +1 -1
- package/out/renderer/assets/{_baseUniq-DlAVpNmp.js → _baseUniq-B-kmAdKj.js} +1 -1
- package/out/renderer/assets/{agent-details-page-ydYZH4Kq.js → agent-details-page-CjksC_ZM.js} +2 -2
- package/out/renderer/assets/{agent-hub-page-C46GCUT2.js → agent-hub-page-D3y5dujt.js} +2 -2
- package/out/renderer/assets/{agents-page-BaARss9y.js → agents-page-vmm4VKcI.js} +3 -3
- package/out/renderer/assets/{arc-C-BSLMbh.js → arc-BSYPx6kR.js} +1 -1
- package/out/renderer/assets/{architectureDiagram-IEHRJDOE-nDfnCWAM.js → architectureDiagram-IEHRJDOE-C-dAuUYf.js} +1 -1
- package/out/renderer/assets/{arrow-up-JQ86w8h2.js → arrow-up-BaHSg-fV.js} +1 -1
- package/out/renderer/assets/{blockDiagram-JOT3LUYC-BJgd2uGT.js → blockDiagram-JOT3LUYC-Dw9X_Asu.js} +1 -1
- package/out/renderer/assets/{book-open-yjstLkVS.js → book-open-CwoTuMOa.js} +1 -1
- package/out/renderer/assets/browser-page-DmYAxbWu.js +1 -0
- package/out/renderer/assets/{browser-webauthn-prompt-Ch0P_oH9.js → browser-webauthn-prompt-CFEuJXkX.js} +1 -1
- package/out/renderer/assets/{building-2-Cupv31tS.js → building-2-D06wTZQj.js} +1 -1
- package/out/renderer/assets/{c4Diagram-VJAJSXHY-lIXnBLZ5.js → c4Diagram-VJAJSXHY-Bz93LlZc.js} +1 -1
- package/out/renderer/assets/channel-BJdem-Qj.js +1 -0
- package/out/renderer/assets/{chunk-4BMEZGHF-DF2ktHZp.js → chunk-4BMEZGHF-H3mECOID.js} +1 -1
- package/out/renderer/assets/{chunk-A2AXSNBT-CNRON9Qy.js → chunk-A2AXSNBT-BNJGDJK2.js} +1 -1
- package/out/renderer/assets/{chunk-AEK57VVT-BGXI1SR5.js → chunk-AEK57VVT-Baj26p0I.js} +1 -1
- package/out/renderer/assets/{chunk-D6G4REZN-CW_SyuGg.js → chunk-D6G4REZN-B5inAuRK.js} +1 -1
- package/out/renderer/assets/{chunk-RZ5BOZE2-gU0oYsA6.js → chunk-RZ5BOZE2-BK_F-zoT.js} +1 -1
- package/out/renderer/assets/{chunk-XZIHB7SX-BrVtbfMc.js → chunk-XZIHB7SX-DipW3oXc.js} +1 -1
- package/out/renderer/assets/classDiagram-GIVACNV2-BQLeT9Qk.js +1 -0
- package/out/renderer/assets/classDiagram-v2-COTLJTTW-BQLeT9Qk.js +1 -0
- package/out/renderer/assets/clone-BaxJyMvd.js +1 -0
- package/out/renderer/assets/{console-mirror-CkCxHgcU.js → console-mirror-DB5yXAr9.js} +1 -1
- package/out/renderer/assets/{consoleCapture-EZYleEWx.js → consoleCapture-Bz69ju0Z.js} +1 -1
- package/out/renderer/assets/{conversation-input-sync-bgD4kyw3.js → conversation-input-sync-BVPZQjhD.js} +183 -183
- package/out/renderer/assets/{dagre-OKDRZEBW-BDR0956-.js → dagre-OKDRZEBW-3ECMKEeo.js} +1 -1
- package/out/renderer/assets/{diagram-SSKATNLV-DbCZDtm7.js → diagram-SSKATNLV-CmAf5Fvk.js} +1 -1
- package/out/renderer/assets/{diagram-VNBRO52H-BpXb_OjM.js → diagram-VNBRO52H-D_21NrT-.js} +1 -1
- package/out/renderer/assets/{erDiagram-Q7BY3M3F-CZukR1Y4.js → erDiagram-Q7BY3M3F-CaUQ9PtP.js} +1 -1
- package/out/renderer/assets/{error-boundary-DJAF_aYL.js → error-boundary-h9802RBt.js} +1 -1
- package/out/renderer/assets/{flowDiagram-4HSFHLVR-CqKOnXAd.js → flowDiagram-4HSFHLVR-CVLxJB7Y.js} +1 -1
- package/out/renderer/assets/{ganttDiagram-APWFNJXF-B9I0smi4.js → ganttDiagram-APWFNJXF-Dt6KPnJQ.js} +1 -1
- package/out/renderer/assets/{gitGraphDiagram-7IBYFJ6S-Bj6-u-5w.js → gitGraphDiagram-7IBYFJ6S-D1BdvS2j.js} +1 -1
- package/out/renderer/assets/{graph-BsgoQZc2.js → graph-wsNGWWCD.js} +1 -1
- package/out/renderer/assets/{hash-BLfEUuGg.js → hash-C32vAdag.js} +1 -1
- package/out/renderer/assets/index-3RPijdn_.css +1 -0
- package/out/renderer/assets/{index-lMi7GI2V.js → index-6JB-jSFn.js} +1 -1
- package/out/renderer/assets/index-COgOH-4N.js +57 -0
- package/out/renderer/assets/index-CiOOz1tp.js +825 -0
- package/out/renderer/assets/{index-D7pJoOu_.js → index-CvofVM43.js} +1 -1
- package/out/renderer/assets/{infoDiagram-PH2N3AL5-DQ3aMjor.js → infoDiagram-PH2N3AL5-CWPf3FZn.js} +1 -1
- package/out/renderer/assets/{installer-Ch3nb3kq.js → installer-DKAnScPb.js} +1 -1
- package/out/renderer/assets/{journeyDiagram-U35MCT3I-B_RccO_x.js → journeyDiagram-U35MCT3I-B5eLtG46.js} +1 -1
- package/out/renderer/assets/{kanban-definition-NDS4AKOZ-BvVJZaiy.js → kanban-definition-NDS4AKOZ-BtJFd9zq.js} +1 -1
- package/out/renderer/assets/{layout-DCACUDHF.js → layout-B3W_M4xE.js} +1 -1
- package/out/renderer/assets/{legacy-agents-page-BovdqsXe.js → legacy-agents-page-aqbs_qcV.js} +5 -5
- package/out/renderer/assets/{library-page-Cm-o3Z-q.js → library-page-BIa8sD1w.js} +3 -3
- package/out/renderer/assets/{mermaid.core-BXcegHmP.js → mermaid.core-DzmjLSHb.js} +5 -5
- package/out/renderer/assets/{mesh-page-ChyvMUoR.js → mesh-page-De8Abvyb.js} +1 -1
- package/out/renderer/assets/{mindmap-definition-ALO5MXBD-Bx_gU6ka.js → mindmap-definition-ALO5MXBD-C1aylJ0P.js} +1 -1
- package/out/renderer/assets/{mini-DRt4PdyG.js → mini-mPtvVJCT.js} +1 -1
- package/out/renderer/assets/{notebook-pen-CKr2WSrK.js → notebook-pen-CvyIerwZ.js} +1 -1
- package/out/renderer/assets/{org-access-CU1oOVqv.js → org-access-Cpt-vs-I.js} +1 -1
- package/out/renderer/assets/{org-surface-gate-C86b758Z.js → org-surface-gate-C8Gs3DNG.js} +1 -1
- package/out/renderer/assets/{page-header-CZcbRwLy.js → page-header-DBIgQcaM.js} +1 -1
- package/out/renderer/assets/{pieDiagram-IB7DONF6-jEzs31M9.js → pieDiagram-IB7DONF6-CjnobVYZ.js} +1 -1
- package/out/renderer/assets/{projects-page-BSvdM2gY.js → projects-page-041auzXW.js} +4 -4
- package/out/renderer/assets/{publication-validation-g2Kk53C8.js → publication-validation-JvAtW-AY.js} +1 -1
- package/out/renderer/assets/{quadrantDiagram-7GDLP6J5-C07DLJe_.js → quadrantDiagram-7GDLP6J5-B0TLJJFL.js} +1 -1
- package/out/renderer/assets/{radar-MK3ICKWK-DFqDL3G4.js → radar-MK3ICKWK-D6MZmkB6.js} +1 -1
- package/out/renderer/assets/{radient-auth-buttons-DP81yj6b.js → radient-auth-buttons-quggTTqK.js} +1 -1
- package/out/renderer/assets/{requirementDiagram-KVF5MWMF-DZVSGDrD.js → requirementDiagram-KVF5MWMF-BSAJQlo8.js} +1 -1
- package/out/renderer/assets/{sankeyDiagram-QLVOVGJD-Efyu9UfS.js → sankeyDiagram-QLVOVGJD-CQqGLTr_.js} +1 -1
- package/out/renderer/assets/{schedules-page-CNIApkVt.js → schedules-page-B51F-ADQ.js} +1 -1
- package/out/renderer/assets/{sequenceDiagram-X6HHIX6F-C5QQ4cH3.js → sequenceDiagram-X6HHIX6F-B0LPyEfC.js} +1 -1
- package/out/renderer/assets/{settings-page-Cd8GUEn_.js → settings-page-BpTAK-RZ.js} +1 -1
- package/out/renderer/assets/{smartart-DAuiyto3.js → smartart-B1Hg0uN6.js} +1 -1
- package/out/renderer/assets/{stateDiagram-DGXRK772-DlvSEVs4.js → stateDiagram-DGXRK772-hL4-Mzxx.js} +1 -1
- package/out/renderer/assets/stateDiagram-v2-YXO3MK2T-Bczp9bth.js +1 -0
- package/out/renderer/assets/team-bridge-page-xhQelITo.js +11 -0
- package/out/renderer/assets/{timeline-definition-BDJGKUSR-XgOjVv3O.js → timeline-definition-BDJGKUSR-BOE8E_XE.js} +1 -1
- package/out/renderer/assets/ui-preferences-store-Cws2cozv.js +1 -0
- package/out/renderer/assets/{use-download-agent-mutation-B-kxWpF6.js → use-download-agent-mutation-HcVu2YgL.js} +2 -2
- package/out/renderer/assets/{use-session-snapshot-BiiULlsj.js → use-session-snapshot-CMQBHevf.js} +1 -1
- package/out/renderer/assets/{xychartDiagram-VJFVF3MP-B0CsPCbY.js → xychartDiagram-VJFVF3MP-D3cI5mnO.js} +1 -1
- package/out/renderer/browser-address-overlay.html +43 -0
- package/out/renderer/console-capture.html +5 -5
- package/out/renderer/index.html +7 -7
- package/out/renderer/installer.html +4 -4
- package/out/renderer/mini.html +7 -7
- package/package.json +2 -2
- package/out/renderer/assets/browser-page-BVFs2_w9.js +0 -1
- package/out/renderer/assets/channel-BqEnrEwi.js +0 -1
- package/out/renderer/assets/classDiagram-GIVACNV2-DNUqXdeF.js +0 -1
- package/out/renderer/assets/classDiagram-v2-COTLJTTW-DNUqXdeF.js +0 -1
- package/out/renderer/assets/clone-_PvxPvQz.js +0 -1
- package/out/renderer/assets/index-CL2MVLxd.css +0 -1
- package/out/renderer/assets/index-N0lyyVVo.js +0 -57
- package/out/renderer/assets/index-jVCAPb0a.js +0 -825
- package/out/renderer/assets/stateDiagram-v2-YXO3MK2T-CCLt0TcZ.js +0 -1
- package/out/renderer/assets/team-bridge-page-CosfhCZV.js +0 -11
- package/out/renderer/assets/ui-preferences-store-C91RrpgH.js +0 -1
package/out/main/index.js
CHANGED
|
@@ -190,6 +190,17 @@ zod.z.object({
|
|
|
190
190
|
}).passthrough()
|
|
191
191
|
}).passthrough()
|
|
192
192
|
}).passthrough();
|
|
193
|
+
const SIDEBAR_DESTINATION_IDS = [
|
|
194
|
+
"aida",
|
|
195
|
+
"library",
|
|
196
|
+
"projects",
|
|
197
|
+
"agents",
|
|
198
|
+
"schedules",
|
|
199
|
+
"browser",
|
|
200
|
+
"team-bridge",
|
|
201
|
+
"agent-hub",
|
|
202
|
+
"mesh"
|
|
203
|
+
];
|
|
193
204
|
const JOURNAL_ORDER_QUERY_BYTES = 6 * 1024;
|
|
194
205
|
const JOURNAL_ORDER_ID_LIMIT = 512;
|
|
195
206
|
function appendJournalOrderIds(query, path2, ids) {
|
|
@@ -488,6 +499,11 @@ const PROJECTS_SEARCH_MAX_CHARS = 256;
|
|
|
488
499
|
const PROJECTS_SEARCH_DEFAULT_LIMIT = 100;
|
|
489
500
|
const PROJECTS_SEARCH_MAX_LIMIT = 200;
|
|
490
501
|
const hubItemKind = zod.z.enum(["agent", "team", "skill"]);
|
|
502
|
+
const sidebarDestinationId = zod.z.enum(SIDEBAR_DESTINATION_IDS);
|
|
503
|
+
const sidebarLayoutSchema = zod.z.object({
|
|
504
|
+
visible: zod.z.array(sidebarDestinationId).max(SIDEBAR_DESTINATION_IDS.length),
|
|
505
|
+
more: zod.z.array(sidebarDestinationId).max(SIDEBAR_DESTINATION_IDS.length)
|
|
506
|
+
}).strict();
|
|
491
507
|
const desktopRequestUnion = zod.z.discriminatedUnion("op", [
|
|
492
508
|
zod.z.object({ op: zod.z.literal("capabilities") }).strict(),
|
|
493
509
|
/*
|
|
@@ -2989,6 +3005,23 @@ const desktopRequestUnion = zod.z.discriminatedUnion("op", [
|
|
|
2989
3005
|
op: zod.z.literal("library.librarian"),
|
|
2990
3006
|
/** `status` is the read's own op; the other four are the writes. */
|
|
2991
3007
|
action: zod.z.enum(["status", "open", "pause", "resume", "run"]).optional()
|
|
3008
|
+
}).strict(),
|
|
3009
|
+
/*
|
|
3010
|
+
* THE SIDEBAR LAYOUT RESOURCE (design contract § 2, § 4). One read and one
|
|
3011
|
+
* write, mirroring the two HTTP verbs: the resource is a single document, and
|
|
3012
|
+
* a patch vocabulary over a nine-entry ordered list would have to invent
|
|
3013
|
+
* operations for moves the client already knows how to compute.
|
|
3014
|
+
*
|
|
3015
|
+
* The write carries the WHOLE layout rather than a delta because the route
|
|
3016
|
+
* normalises and persists a complete document (last writer wins, atomic file
|
|
3017
|
+
* replace). Sending the full list is also what makes an optimistic write
|
|
3018
|
+
* self-describing on the retry path: the body a retry replays is the layout
|
|
3019
|
+
* the user saw, not a move that could be applied twice.
|
|
3020
|
+
*/
|
|
3021
|
+
zod.z.object({ op: zod.z.literal("sidebar_layout.get") }).strict(),
|
|
3022
|
+
zod.z.object({
|
|
3023
|
+
op: zod.z.literal("sidebar_layout.set"),
|
|
3024
|
+
layout: sidebarLayoutSchema
|
|
2992
3025
|
}).strict()
|
|
2993
3026
|
]);
|
|
2994
3027
|
const desktopRequestSchema = desktopRequestUnion.superRefine(
|
|
@@ -5387,6 +5420,22 @@ function desktopEndpoint(request) {
|
|
|
5387
5420
|
ttl_s: request.ttlS
|
|
5388
5421
|
}
|
|
5389
5422
|
};
|
|
5423
|
+
/*
|
|
5424
|
+
* The sidebar customisation resource (design contract § 4). A GET/PUT pair
|
|
5425
|
+
* on one route, with the layout in an envelope rather than as the bare body:
|
|
5426
|
+
* the route answers `{layout}` and accepts `{layout}`, so a future field
|
|
5427
|
+
* beside it is additive instead of a breaking shape change. The PUT sends
|
|
5428
|
+
* the stored ids verbatim - the client owns the order, the route owns
|
|
5429
|
+
* validation and the default fill - so nothing is re-sorted in transit.
|
|
5430
|
+
*/
|
|
5431
|
+
case "sidebar_layout.get":
|
|
5432
|
+
return { path: "/v1/desktop/sidebar-layout", method: "GET" };
|
|
5433
|
+
case "sidebar_layout.set":
|
|
5434
|
+
return {
|
|
5435
|
+
path: "/v1/desktop/sidebar-layout",
|
|
5436
|
+
method: "PUT",
|
|
5437
|
+
body: { layout: request.layout }
|
|
5438
|
+
};
|
|
5390
5439
|
}
|
|
5391
5440
|
}
|
|
5392
5441
|
const MAX_PROBE_PATHS = 64;
|
|
@@ -28714,6 +28763,661 @@ function labelOf(account) {
|
|
|
28714
28763
|
if (!account) return "an unnamed passkey";
|
|
28715
28764
|
return account.displayName || account.name || "an unnamed passkey";
|
|
28716
28765
|
}
|
|
28766
|
+
const ADDRESS_OVERLAY_S1_ENV = "LOCAL_OPERATOR_UI_BROWSER_ADDRESS_OVERLAY_S1";
|
|
28767
|
+
const ADDRESS_OVERLAY_DOCUMENT = "browser-address-overlay.html";
|
|
28768
|
+
const ADDRESS_OVERLAY_MAX_HEIGHT_DIP = 160;
|
|
28769
|
+
const ADDRESS_OVERLAY_READY_TIMEOUT_MS = 5e3;
|
|
28770
|
+
const DIP_INT32_MAX = 2 ** 31 - 1;
|
|
28771
|
+
const INDEX_DOCUMENT_SUFFIX$2 = /\/?index\.html(\?.*)?$/;
|
|
28772
|
+
const TRAILING_SLASH$1 = /\/$/;
|
|
28773
|
+
function addressOverlayDocumentUrlFor(rendererUrl) {
|
|
28774
|
+
return INDEX_DOCUMENT_SUFFIX$2.test(rendererUrl) ? rendererUrl.replace(INDEX_DOCUMENT_SUFFIX$2, `/${ADDRESS_OVERLAY_DOCUMENT}`) : `${rendererUrl.replace(TRAILING_SLASH$1, "")}/${ADDRESS_OVERLAY_DOCUMENT}`;
|
|
28775
|
+
}
|
|
28776
|
+
function resolveAddressOverlayGate(input) {
|
|
28777
|
+
const raw = input.env[ADDRESS_OVERLAY_S1_ENV];
|
|
28778
|
+
if (raw === void 0 || raw.trim() === "") {
|
|
28779
|
+
return { asked: false, enabled: false, reason: null };
|
|
28780
|
+
}
|
|
28781
|
+
const asked = true;
|
|
28782
|
+
if (raw.trim() !== "1") {
|
|
28783
|
+
return {
|
|
28784
|
+
asked,
|
|
28785
|
+
enabled: false,
|
|
28786
|
+
reason: `${ADDRESS_OVERLAY_S1_ENV}=${raw.trim()} is not an opt-in (accepted: 1); the address overlay stayed off`
|
|
28787
|
+
};
|
|
28788
|
+
}
|
|
28789
|
+
if (!input.devDriverArmed) {
|
|
28790
|
+
return {
|
|
28791
|
+
asked,
|
|
28792
|
+
enabled: false,
|
|
28793
|
+
reason: "the address overlay needs the armed renderer dev driver; it has no user-facing trigger in S1"
|
|
28794
|
+
};
|
|
28795
|
+
}
|
|
28796
|
+
if (input.windowMode !== "headless") {
|
|
28797
|
+
return {
|
|
28798
|
+
asked,
|
|
28799
|
+
enabled: false,
|
|
28800
|
+
reason: `the address overlay refused to arm in a "${input.windowMode}" window; S1 has no user-facing path, so use --window-mode=headless`
|
|
28801
|
+
};
|
|
28802
|
+
}
|
|
28803
|
+
return { asked, enabled: true, reason: null };
|
|
28804
|
+
}
|
|
28805
|
+
function int32(value) {
|
|
28806
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return null;
|
|
28807
|
+
const rounded = Math.round(value);
|
|
28808
|
+
return Math.abs(rounded) > DIP_INT32_MAX ? null : rounded;
|
|
28809
|
+
}
|
|
28810
|
+
function overlayBoundsFor(contentRect, owner) {
|
|
28811
|
+
if (contentRect === null) return null;
|
|
28812
|
+
const x = int32(contentRect.x);
|
|
28813
|
+
const y = int32(contentRect.y);
|
|
28814
|
+
const width = int32(contentRect.width);
|
|
28815
|
+
const height = int32(contentRect.height);
|
|
28816
|
+
const ownerWidth = int32(owner.width);
|
|
28817
|
+
const ownerHeight = int32(owner.height);
|
|
28818
|
+
if (x === null || y === null || width === null || height === null || ownerWidth === null || ownerHeight === null)
|
|
28819
|
+
return null;
|
|
28820
|
+
if (width <= 0 || height <= 0 || ownerWidth <= 0 || ownerHeight <= 0) {
|
|
28821
|
+
return null;
|
|
28822
|
+
}
|
|
28823
|
+
const left = Math.max(0, x);
|
|
28824
|
+
const top = Math.max(0, y);
|
|
28825
|
+
const right = Math.min(ownerWidth, x + width);
|
|
28826
|
+
const bottom = Math.min(
|
|
28827
|
+
ownerHeight,
|
|
28828
|
+
y + Math.min(height, ADDRESS_OVERLAY_MAX_HEIGHT_DIP)
|
|
28829
|
+
);
|
|
28830
|
+
if (right <= left || bottom <= top) return null;
|
|
28831
|
+
return { x: left, y: top, width: right - left, height: bottom - top };
|
|
28832
|
+
}
|
|
28833
|
+
function copyLayout(snapshot2) {
|
|
28834
|
+
return {
|
|
28835
|
+
activeTabId: snapshot2.activeTabId,
|
|
28836
|
+
presented: snapshot2.presented,
|
|
28837
|
+
contentRect: snapshot2.contentRect ? {
|
|
28838
|
+
x: snapshot2.contentRect.x,
|
|
28839
|
+
y: snapshot2.contentRect.y,
|
|
28840
|
+
width: snapshot2.contentRect.width,
|
|
28841
|
+
height: snapshot2.contentRect.height
|
|
28842
|
+
} : null,
|
|
28843
|
+
revision: snapshot2.revision
|
|
28844
|
+
};
|
|
28845
|
+
}
|
|
28846
|
+
function layoutKeyOf(snapshot2) {
|
|
28847
|
+
const rect = snapshot2.contentRect;
|
|
28848
|
+
return `${snapshot2.activeTabId}:${snapshot2.presented ? 1 : 0}:${rect ? `${rect.x},${rect.y},${rect.width},${rect.height}` : "null"}`;
|
|
28849
|
+
}
|
|
28850
|
+
const OVERLAY_BACKGROUND = "#1b1f24";
|
|
28851
|
+
function createHardenedView() {
|
|
28852
|
+
const partition = `address-overlay-${node_crypto.randomUUID()}`;
|
|
28853
|
+
const childSession = electron.session.fromPartition(partition);
|
|
28854
|
+
childSession.setPermissionRequestHandler(
|
|
28855
|
+
(_contents, _permission, callback) => {
|
|
28856
|
+
callback(false);
|
|
28857
|
+
}
|
|
28858
|
+
);
|
|
28859
|
+
childSession.setPermissionCheckHandler(() => false);
|
|
28860
|
+
childSession.on("will-download", (event) => {
|
|
28861
|
+
event.preventDefault();
|
|
28862
|
+
});
|
|
28863
|
+
const view = new electron.WebContentsView({
|
|
28864
|
+
webPreferences: {
|
|
28865
|
+
partition,
|
|
28866
|
+
sandbox: true,
|
|
28867
|
+
contextIsolation: true,
|
|
28868
|
+
nodeIntegration: false,
|
|
28869
|
+
webSecurity: true,
|
|
28870
|
+
allowRunningInsecureContent: false,
|
|
28871
|
+
// No `preload`, and no script in the document: nothing can ask for a
|
|
28872
|
+
// bridge, and the renderer never runs JavaScript even if the document
|
|
28873
|
+
// changes by accident.
|
|
28874
|
+
javascript: false
|
|
28875
|
+
}
|
|
28876
|
+
});
|
|
28877
|
+
view.webContents.setWindowOpenHandler(() => ({ action: "deny" }));
|
|
28878
|
+
view.setBackgroundColor(OVERLAY_BACKGROUND);
|
|
28879
|
+
return view;
|
|
28880
|
+
}
|
|
28881
|
+
class AddressOverlayController {
|
|
28882
|
+
window;
|
|
28883
|
+
documentUrl;
|
|
28884
|
+
createView;
|
|
28885
|
+
readinessTimeoutMs;
|
|
28886
|
+
log;
|
|
28887
|
+
now;
|
|
28888
|
+
appMetrics;
|
|
28889
|
+
view;
|
|
28890
|
+
childWebContentsId;
|
|
28891
|
+
state;
|
|
28892
|
+
failedReason;
|
|
28893
|
+
hiddenReason;
|
|
28894
|
+
generation;
|
|
28895
|
+
childCreatedCount;
|
|
28896
|
+
shownCount;
|
|
28897
|
+
lastShow;
|
|
28898
|
+
layout;
|
|
28899
|
+
layoutKey;
|
|
28900
|
+
boundTabId;
|
|
28901
|
+
domReady;
|
|
28902
|
+
finished;
|
|
28903
|
+
loadStartedAt;
|
|
28904
|
+
loadMs;
|
|
28905
|
+
readyWaiter;
|
|
28906
|
+
readinessTimer;
|
|
28907
|
+
showInFlight;
|
|
28908
|
+
disposingChild;
|
|
28909
|
+
disposed;
|
|
28910
|
+
ownerListeners;
|
|
28911
|
+
childListeners;
|
|
28912
|
+
constructor(deps) {
|
|
28913
|
+
this.window = deps.window;
|
|
28914
|
+
this.documentUrl = deps.documentUrl;
|
|
28915
|
+
this.createView = deps.createView ?? createHardenedView;
|
|
28916
|
+
this.readinessTimeoutMs = deps.readinessTimeoutMs ?? ADDRESS_OVERLAY_READY_TIMEOUT_MS;
|
|
28917
|
+
this.log = deps.log ?? (() => {
|
|
28918
|
+
});
|
|
28919
|
+
this.now = deps.now ?? (() => Date.now());
|
|
28920
|
+
this.appMetrics = deps.appMetrics ?? null;
|
|
28921
|
+
this.view = null;
|
|
28922
|
+
this.childWebContentsId = null;
|
|
28923
|
+
this.state = "absent";
|
|
28924
|
+
this.failedReason = null;
|
|
28925
|
+
this.hiddenReason = null;
|
|
28926
|
+
this.generation = 0;
|
|
28927
|
+
this.childCreatedCount = 0;
|
|
28928
|
+
this.shownCount = 0;
|
|
28929
|
+
this.lastShow = null;
|
|
28930
|
+
this.layout = {
|
|
28931
|
+
activeTabId: null,
|
|
28932
|
+
presented: false,
|
|
28933
|
+
contentRect: null,
|
|
28934
|
+
revision: 0
|
|
28935
|
+
};
|
|
28936
|
+
this.layoutKey = "none";
|
|
28937
|
+
this.boundTabId = null;
|
|
28938
|
+
this.domReady = false;
|
|
28939
|
+
this.finished = false;
|
|
28940
|
+
this.loadStartedAt = null;
|
|
28941
|
+
this.loadMs = null;
|
|
28942
|
+
this.readyWaiter = null;
|
|
28943
|
+
this.readinessTimer = null;
|
|
28944
|
+
this.showInFlight = null;
|
|
28945
|
+
this.disposingChild = false;
|
|
28946
|
+
this.disposed = false;
|
|
28947
|
+
this.ownerListeners = [];
|
|
28948
|
+
this.childListeners = [];
|
|
28949
|
+
this.attachOwnerListeners();
|
|
28950
|
+
}
|
|
28951
|
+
// ---- observer hooks ------------------------------------------------------
|
|
28952
|
+
/**
|
|
28953
|
+
* The registry's post-layout hook. Called after every page layout pass,
|
|
28954
|
+
* including null and suppressed ones.
|
|
28955
|
+
*
|
|
28956
|
+
* A changed key (tab, presentation or rectangle) hides and invalidates first:
|
|
28957
|
+
* a moved page must never keep a stale rectangle floating over it, and a
|
|
28958
|
+
* resized window invalidates old geometry until a fresh renderer rect
|
|
28959
|
+
* arrives. An unchanged key is the background-page-creation case: the layout
|
|
28960
|
+
* pass may have added a page above the child, so the child is re-added last
|
|
28961
|
+
* and given the same rectangle. It never re-opens by itself; showing again is
|
|
28962
|
+
* always an explicit probe call.
|
|
28963
|
+
*/
|
|
28964
|
+
onLayout(snapshot2) {
|
|
28965
|
+
if (this.disposed) return;
|
|
28966
|
+
const next = copyLayout(snapshot2);
|
|
28967
|
+
const nextKey = layoutKeyOf(next);
|
|
28968
|
+
const previousKey = this.layoutKey;
|
|
28969
|
+
this.layout = next;
|
|
28970
|
+
this.layoutKey = nextKey;
|
|
28971
|
+
if (previousKey !== nextKey) {
|
|
28972
|
+
this.hide("layout");
|
|
28973
|
+
return;
|
|
28974
|
+
}
|
|
28975
|
+
if (this.state !== "shown") return;
|
|
28976
|
+
const view = this.view;
|
|
28977
|
+
if (!view || this.viewUsable(view) === false) return;
|
|
28978
|
+
const bounds = overlayBoundsFor(next.contentRect, this.ownerSize());
|
|
28979
|
+
if (bounds === null || !next.presented) {
|
|
28980
|
+
this.hide("layout_invalid");
|
|
28981
|
+
return;
|
|
28982
|
+
}
|
|
28983
|
+
try {
|
|
28984
|
+
view.setBounds(bounds);
|
|
28985
|
+
this.raiseChild(view);
|
|
28986
|
+
} catch (error) {
|
|
28987
|
+
this.releaseChild("layout_error");
|
|
28988
|
+
this.log(`[browser] address overlay layout failed: ${String(error)}`);
|
|
28989
|
+
}
|
|
28990
|
+
}
|
|
28991
|
+
/** The bound page is going away. Dispose the child before the page release. */
|
|
28992
|
+
onTabReleased(tabId) {
|
|
28993
|
+
if (this.disposed) return;
|
|
28994
|
+
if (this.boundTabId !== tabId) return;
|
|
28995
|
+
this.releaseChild("bound-tab-released");
|
|
28996
|
+
}
|
|
28997
|
+
/** The bound page's renderer died but its webContents survives (a crashed tab).
|
|
28998
|
+
* The child is bound to that page's rectangle, so it goes with the renderer; a
|
|
28999
|
+
* later explicit show may create a fresh one. */
|
|
29000
|
+
onPageGone(tabId) {
|
|
29001
|
+
if (this.disposed) return;
|
|
29002
|
+
if (this.boundTabId !== tabId) return;
|
|
29003
|
+
this.releaseChild("page-crash");
|
|
29004
|
+
}
|
|
29005
|
+
// ---- probe surface ------------------------------------------------------
|
|
29006
|
+
async showOverlay() {
|
|
29007
|
+
if (this.showInFlight) return this.showInFlight;
|
|
29008
|
+
const pending = this.showOnce();
|
|
29009
|
+
this.showInFlight = pending;
|
|
29010
|
+
void pending.then(
|
|
29011
|
+
() => {
|
|
29012
|
+
if (this.showInFlight === pending) this.showInFlight = null;
|
|
29013
|
+
},
|
|
29014
|
+
() => {
|
|
29015
|
+
if (this.showInFlight === pending) this.showInFlight = null;
|
|
29016
|
+
}
|
|
29017
|
+
);
|
|
29018
|
+
return pending;
|
|
29019
|
+
}
|
|
29020
|
+
hide(reason = "hide") {
|
|
29021
|
+
if (this.disposed) return;
|
|
29022
|
+
this.generation += 1;
|
|
29023
|
+
this.settleReady(false);
|
|
29024
|
+
this.hiddenReason = reason;
|
|
29025
|
+
const view = this.view;
|
|
29026
|
+
if (view && this.viewUsable(view)) {
|
|
29027
|
+
try {
|
|
29028
|
+
view.setVisible(false);
|
|
29029
|
+
} catch {
|
|
29030
|
+
}
|
|
29031
|
+
}
|
|
29032
|
+
if (this.state === "shown") {
|
|
29033
|
+
this.state = this.failedReason ? "failed" : this.domReady && this.finished ? "ready" : "loading";
|
|
29034
|
+
}
|
|
29035
|
+
this.log(`[browser] address overlay hidden: ${reason}`);
|
|
29036
|
+
}
|
|
29037
|
+
/** Facts only: identifiers, geometry and counters. No page content. */
|
|
29038
|
+
facts() {
|
|
29039
|
+
const view = this.view;
|
|
29040
|
+
let child = null;
|
|
29041
|
+
if (view) {
|
|
29042
|
+
let visible = false;
|
|
29043
|
+
let bounds = null;
|
|
29044
|
+
let order = -1;
|
|
29045
|
+
let childCount = 0;
|
|
29046
|
+
try {
|
|
29047
|
+
visible = view.getVisible();
|
|
29048
|
+
bounds = view.getBounds();
|
|
29049
|
+
const children = this.window.contentView.children;
|
|
29050
|
+
childCount = children.length;
|
|
29051
|
+
order = children.indexOf(view);
|
|
29052
|
+
} catch {
|
|
29053
|
+
}
|
|
29054
|
+
child = {
|
|
29055
|
+
webContentsId: this.childWebContentsId ?? view.webContents.id,
|
|
29056
|
+
visible,
|
|
29057
|
+
bounds,
|
|
29058
|
+
order,
|
|
29059
|
+
childCount
|
|
29060
|
+
};
|
|
29061
|
+
}
|
|
29062
|
+
let ownerDestroyed = true;
|
|
29063
|
+
let contentBounds = null;
|
|
29064
|
+
try {
|
|
29065
|
+
ownerDestroyed = this.window.isDestroyed();
|
|
29066
|
+
if (!ownerDestroyed) contentBounds = this.ownerSize();
|
|
29067
|
+
} catch {
|
|
29068
|
+
ownerDestroyed = true;
|
|
29069
|
+
}
|
|
29070
|
+
return {
|
|
29071
|
+
documentUrl: this.documentUrl,
|
|
29072
|
+
state: this.state,
|
|
29073
|
+
failedReason: this.failedReason,
|
|
29074
|
+
hiddenReason: this.hiddenReason,
|
|
29075
|
+
generation: this.generation,
|
|
29076
|
+
childCreatedCount: this.childCreatedCount,
|
|
29077
|
+
shownCount: this.shownCount,
|
|
29078
|
+
lastShow: this.lastShow,
|
|
29079
|
+
readiness: {
|
|
29080
|
+
domReady: this.domReady,
|
|
29081
|
+
finished: this.finished,
|
|
29082
|
+
loadMs: this.loadMs
|
|
29083
|
+
},
|
|
29084
|
+
child,
|
|
29085
|
+
owner: {
|
|
29086
|
+
windowId: typeof this.window.id === "number" ? this.window.id : null,
|
|
29087
|
+
destroyed: ownerDestroyed,
|
|
29088
|
+
contentBounds
|
|
29089
|
+
},
|
|
29090
|
+
layout: copyLayout(this.layout),
|
|
29091
|
+
listeners: {
|
|
29092
|
+
owner: this.ownerListeners.length,
|
|
29093
|
+
child: this.childListeners.length
|
|
29094
|
+
},
|
|
29095
|
+
pendingShow: this.showInFlight !== null,
|
|
29096
|
+
readinessTimer: this.readinessTimer !== null,
|
|
29097
|
+
metrics: this.appMetrics ? this.appMetrics() : null
|
|
29098
|
+
};
|
|
29099
|
+
}
|
|
29100
|
+
async probe(action) {
|
|
29101
|
+
if (action === "show") {
|
|
29102
|
+
await this.showOverlay();
|
|
29103
|
+
return this.facts();
|
|
29104
|
+
}
|
|
29105
|
+
if (action === "hide") {
|
|
29106
|
+
this.hide("probe");
|
|
29107
|
+
return this.facts();
|
|
29108
|
+
}
|
|
29109
|
+
return this.facts();
|
|
29110
|
+
}
|
|
29111
|
+
/**
|
|
29112
|
+
* Idempotent teardown for the host's stop/rollback/window-close paths.
|
|
29113
|
+
* Closing the webContents before detaching is required: removing a
|
|
29114
|
+
* `WebContentsView` does not release its renderer.
|
|
29115
|
+
*/
|
|
29116
|
+
dispose(reason) {
|
|
29117
|
+
if (this.disposed) return;
|
|
29118
|
+
this.disposed = true;
|
|
29119
|
+
this.generation += 1;
|
|
29120
|
+
this.settleReady(false);
|
|
29121
|
+
this.detachOwnerListeners();
|
|
29122
|
+
this.destroyChild();
|
|
29123
|
+
this.state = "disposed";
|
|
29124
|
+
this.hiddenReason = reason;
|
|
29125
|
+
this.log(`[browser] address overlay disposed: ${reason}`);
|
|
29126
|
+
}
|
|
29127
|
+
get isDisposed() {
|
|
29128
|
+
return this.disposed;
|
|
29129
|
+
}
|
|
29130
|
+
// ---- show path ----------------------------------------------------------
|
|
29131
|
+
async showOnce() {
|
|
29132
|
+
const refuse = (reason) => {
|
|
29133
|
+
this.lastShow = { shown: false, reason, bounds: null, at: this.now() };
|
|
29134
|
+
return { shown: false, reason, bounds: null };
|
|
29135
|
+
};
|
|
29136
|
+
try {
|
|
29137
|
+
if (this.disposed) return refuse("disposed");
|
|
29138
|
+
if (this.failedReason) return refuse(this.failedReason);
|
|
29139
|
+
if (this.ownerUnavailable()) {
|
|
29140
|
+
this.releaseChild("owner_unavailable");
|
|
29141
|
+
return refuse("owner_unavailable");
|
|
29142
|
+
}
|
|
29143
|
+
const snapshot2 = this.layout;
|
|
29144
|
+
const bounds = overlayBoundsFor(snapshot2.contentRect, this.ownerSize());
|
|
29145
|
+
if (snapshot2.activeTabId === null || !snapshot2.presented || bounds === null) {
|
|
29146
|
+
return refuse("no_layout");
|
|
29147
|
+
}
|
|
29148
|
+
this.generation += 1;
|
|
29149
|
+
const generation = this.generation;
|
|
29150
|
+
this.boundTabId = snapshot2.activeTabId;
|
|
29151
|
+
if (!this.view) {
|
|
29152
|
+
const created = this.createChild(bounds);
|
|
29153
|
+
if (!created) return refuse(this.failedReason ?? "child_create_failed");
|
|
29154
|
+
}
|
|
29155
|
+
if (!(this.domReady && this.finished)) {
|
|
29156
|
+
this.state = "loading";
|
|
29157
|
+
const ready = await this.waitForReady();
|
|
29158
|
+
if (!ready) return refuse(this.failedReason ?? "invalidated");
|
|
29159
|
+
}
|
|
29160
|
+
if (this.disposed || generation !== this.generation) {
|
|
29161
|
+
return refuse("invalidated");
|
|
29162
|
+
}
|
|
29163
|
+
if (this.ownerUnavailable()) {
|
|
29164
|
+
this.releaseChild("owner_unavailable");
|
|
29165
|
+
return refuse("owner_unavailable");
|
|
29166
|
+
}
|
|
29167
|
+
const view = this.view;
|
|
29168
|
+
if (!view) return refuse("child_missing");
|
|
29169
|
+
const finalBounds = overlayBoundsFor(
|
|
29170
|
+
this.layout.contentRect,
|
|
29171
|
+
this.ownerSize()
|
|
29172
|
+
);
|
|
29173
|
+
if (finalBounds === null || this.layout.activeTabId === null || !this.layout.presented || this.layout.activeTabId !== this.boundTabId) {
|
|
29174
|
+
return refuse("invalidated");
|
|
29175
|
+
}
|
|
29176
|
+
view.setBounds(finalBounds);
|
|
29177
|
+
this.raiseChild(view);
|
|
29178
|
+
view.setVisible(true);
|
|
29179
|
+
this.state = "shown";
|
|
29180
|
+
this.hiddenReason = null;
|
|
29181
|
+
this.shownCount += 1;
|
|
29182
|
+
this.lastShow = {
|
|
29183
|
+
shown: true,
|
|
29184
|
+
reason: null,
|
|
29185
|
+
bounds: finalBounds,
|
|
29186
|
+
at: this.now()
|
|
29187
|
+
};
|
|
29188
|
+
this.log(
|
|
29189
|
+
`[browser] address overlay shown tab=${this.boundTabId} bounds=${finalBounds.x},${finalBounds.y},${finalBounds.width},${finalBounds.height} generation=${generation}`
|
|
29190
|
+
);
|
|
29191
|
+
return { shown: true, reason: null, bounds: finalBounds };
|
|
29192
|
+
} catch (error) {
|
|
29193
|
+
this.failChild(`show_error:${String(error)}`);
|
|
29194
|
+
return refuse("child_error");
|
|
29195
|
+
}
|
|
29196
|
+
}
|
|
29197
|
+
createChild(bounds) {
|
|
29198
|
+
let view;
|
|
29199
|
+
try {
|
|
29200
|
+
view = this.createView();
|
|
29201
|
+
} catch (error) {
|
|
29202
|
+
this.failChild(`child_create_failed:${String(error)}`);
|
|
29203
|
+
return false;
|
|
29204
|
+
}
|
|
29205
|
+
this.view = view;
|
|
29206
|
+
this.childWebContentsId = view.webContents.id;
|
|
29207
|
+
this.childCreatedCount += 1;
|
|
29208
|
+
this.domReady = false;
|
|
29209
|
+
this.finished = false;
|
|
29210
|
+
this.loadMs = null;
|
|
29211
|
+
this.loadStartedAt = null;
|
|
29212
|
+
try {
|
|
29213
|
+
this.window.contentView.addChildView(view);
|
|
29214
|
+
view.setBounds(bounds);
|
|
29215
|
+
view.setVisible(false);
|
|
29216
|
+
} catch (error) {
|
|
29217
|
+
this.failChild(`child_attach_failed:${String(error)}`);
|
|
29218
|
+
return false;
|
|
29219
|
+
}
|
|
29220
|
+
this.wireChild(view);
|
|
29221
|
+
this.loadStartedAt = this.now();
|
|
29222
|
+
try {
|
|
29223
|
+
const loading = view.webContents.loadURL(this.documentUrl);
|
|
29224
|
+
void Promise.resolve(loading).catch((error) => {
|
|
29225
|
+
if (this.disposed || this.view !== view) return;
|
|
29226
|
+
this.failChild(`load_failed:${String(error)}`);
|
|
29227
|
+
});
|
|
29228
|
+
} catch (error) {
|
|
29229
|
+
this.failChild(`load_failed:${String(error)}`);
|
|
29230
|
+
return false;
|
|
29231
|
+
}
|
|
29232
|
+
this.log(
|
|
29233
|
+
`[browser] address overlay child created wc=${view.webContents.id}`
|
|
29234
|
+
);
|
|
29235
|
+
return true;
|
|
29236
|
+
}
|
|
29237
|
+
waitForReady() {
|
|
29238
|
+
if (this.domReady && this.finished) return Promise.resolve(true);
|
|
29239
|
+
if (this.readyWaiter) {
|
|
29240
|
+
return Promise.resolve(false);
|
|
29241
|
+
}
|
|
29242
|
+
return new Promise((resolve) => {
|
|
29243
|
+
this.readyWaiter = resolve;
|
|
29244
|
+
this.readinessTimer = setTimeout(() => {
|
|
29245
|
+
this.readinessTimer = null;
|
|
29246
|
+
if (this.readyWaiter) this.failChild("load_timeout");
|
|
29247
|
+
}, this.readinessTimeoutMs);
|
|
29248
|
+
});
|
|
29249
|
+
}
|
|
29250
|
+
settleReady(ok) {
|
|
29251
|
+
if (this.readinessTimer !== null) {
|
|
29252
|
+
clearTimeout(this.readinessTimer);
|
|
29253
|
+
this.readinessTimer = null;
|
|
29254
|
+
}
|
|
29255
|
+
const waiter = this.readyWaiter;
|
|
29256
|
+
this.readyWaiter = null;
|
|
29257
|
+
if (waiter) waiter(ok);
|
|
29258
|
+
}
|
|
29259
|
+
maybeReady() {
|
|
29260
|
+
if (!(this.domReady && this.finished)) return;
|
|
29261
|
+
if (this.loadStartedAt !== null && this.loadMs === null) {
|
|
29262
|
+
this.loadMs = this.now() - this.loadStartedAt;
|
|
29263
|
+
}
|
|
29264
|
+
if (this.state === "loading" || this.state === "absent") {
|
|
29265
|
+
this.state = this.readyWaiter ? this.state : "ready";
|
|
29266
|
+
}
|
|
29267
|
+
this.settleReady(true);
|
|
29268
|
+
}
|
|
29269
|
+
// ---- child wiring -------------------------------------------------------
|
|
29270
|
+
wireChild(view) {
|
|
29271
|
+
const contents = view.webContents;
|
|
29272
|
+
const on = (target2, event, listener) => {
|
|
29273
|
+
const emitter = target2;
|
|
29274
|
+
emitter.on(event, listener);
|
|
29275
|
+
this.childListeners.push(() => {
|
|
29276
|
+
try {
|
|
29277
|
+
emitter.removeListener(event, listener);
|
|
29278
|
+
} catch {
|
|
29279
|
+
}
|
|
29280
|
+
});
|
|
29281
|
+
};
|
|
29282
|
+
on(contents, "dom-ready", () => {
|
|
29283
|
+
if (this.view !== view) return;
|
|
29284
|
+
this.domReady = true;
|
|
29285
|
+
this.maybeReady();
|
|
29286
|
+
});
|
|
29287
|
+
on(contents, "did-finish-load", () => {
|
|
29288
|
+
if (this.view !== view) return;
|
|
29289
|
+
this.finished = true;
|
|
29290
|
+
this.maybeReady();
|
|
29291
|
+
});
|
|
29292
|
+
on(contents, "did-fail-load", (...args) => {
|
|
29293
|
+
if (this.view !== view) return;
|
|
29294
|
+
const code = typeof args[1] === "number" ? args[1] : 0;
|
|
29295
|
+
const isMainFrame = args[4] !== false;
|
|
29296
|
+
if (!isMainFrame || code === -3) return;
|
|
29297
|
+
this.failChild(`load_failed:${code}`);
|
|
29298
|
+
});
|
|
29299
|
+
on(contents, "render-process-gone", () => {
|
|
29300
|
+
if (this.view !== view) return;
|
|
29301
|
+
this.failChild("child_crash");
|
|
29302
|
+
});
|
|
29303
|
+
on(contents, "destroyed", () => {
|
|
29304
|
+
if (this.view !== view) return;
|
|
29305
|
+
if (this.disposingChild) return;
|
|
29306
|
+
this.failChild("child_destroyed");
|
|
29307
|
+
});
|
|
29308
|
+
on(contents, "will-navigate", (...args) => {
|
|
29309
|
+
const url = typeof args[1] === "string" ? args[1] : "";
|
|
29310
|
+
const event = args[0];
|
|
29311
|
+
if (url === this.documentUrl) return;
|
|
29312
|
+
event?.preventDefault?.();
|
|
29313
|
+
this.log(`[browser] address overlay refused navigation to ${url}`);
|
|
29314
|
+
});
|
|
29315
|
+
on(contents, "will-redirect", (...args) => {
|
|
29316
|
+
const url = typeof args[1] === "string" ? args[1] : "";
|
|
29317
|
+
const event = args[0];
|
|
29318
|
+
if (url === this.documentUrl) return;
|
|
29319
|
+
event?.preventDefault?.();
|
|
29320
|
+
this.log(`[browser] address overlay refused redirect to ${url}`);
|
|
29321
|
+
});
|
|
29322
|
+
}
|
|
29323
|
+
/** Terminal for this host lifetime: a broken document must not be retried. */
|
|
29324
|
+
failChild(reason) {
|
|
29325
|
+
if (this.failedReason) return;
|
|
29326
|
+
this.failedReason = reason;
|
|
29327
|
+
this.state = "failed";
|
|
29328
|
+
this.settleReady(false);
|
|
29329
|
+
this.destroyChild();
|
|
29330
|
+
this.log(`[browser] address overlay failed: ${reason}`);
|
|
29331
|
+
}
|
|
29332
|
+
/** Recoverable: the child goes, a later explicit show may lazily recreate one. */
|
|
29333
|
+
releaseChild(reason) {
|
|
29334
|
+
this.generation += 1;
|
|
29335
|
+
this.settleReady(false);
|
|
29336
|
+
this.destroyChild();
|
|
29337
|
+
if (!this.failedReason) this.state = "absent";
|
|
29338
|
+
this.boundTabId = null;
|
|
29339
|
+
this.domReady = false;
|
|
29340
|
+
this.finished = false;
|
|
29341
|
+
this.loadStartedAt = null;
|
|
29342
|
+
this.log(`[browser] address overlay child released: ${reason}`);
|
|
29343
|
+
}
|
|
29344
|
+
destroyChild() {
|
|
29345
|
+
const view = this.view;
|
|
29346
|
+
if (!view) return;
|
|
29347
|
+
this.view = null;
|
|
29348
|
+
this.childWebContentsId = null;
|
|
29349
|
+
this.disposingChild = true;
|
|
29350
|
+
for (const remove of this.childListeners.splice(0)) remove();
|
|
29351
|
+
try {
|
|
29352
|
+
if (!view.webContents.isDestroyed()) view.webContents.close();
|
|
29353
|
+
} catch {
|
|
29354
|
+
}
|
|
29355
|
+
try {
|
|
29356
|
+
this.window.contentView.removeChildView(view);
|
|
29357
|
+
} catch {
|
|
29358
|
+
}
|
|
29359
|
+
this.disposingChild = false;
|
|
29360
|
+
}
|
|
29361
|
+
raiseChild(view) {
|
|
29362
|
+
this.window.contentView.addChildView(view);
|
|
29363
|
+
}
|
|
29364
|
+
viewUsable(view) {
|
|
29365
|
+
try {
|
|
29366
|
+
return !view.webContents.isDestroyed();
|
|
29367
|
+
} catch {
|
|
29368
|
+
return false;
|
|
29369
|
+
}
|
|
29370
|
+
}
|
|
29371
|
+
// ---- owner wiring -------------------------------------------------------
|
|
29372
|
+
attachOwnerListeners() {
|
|
29373
|
+
const on = (target2, event, listener) => {
|
|
29374
|
+
const emitter = target2;
|
|
29375
|
+
emitter.on(event, listener);
|
|
29376
|
+
this.ownerListeners.push(() => {
|
|
29377
|
+
try {
|
|
29378
|
+
emitter.removeListener(event, listener);
|
|
29379
|
+
} catch {
|
|
29380
|
+
}
|
|
29381
|
+
});
|
|
29382
|
+
};
|
|
29383
|
+
on(this.window, "blur", () => {
|
|
29384
|
+
this.hide("window_blur");
|
|
29385
|
+
});
|
|
29386
|
+
on(this.window, "minimize", () => {
|
|
29387
|
+
this.hide("window_minimize");
|
|
29388
|
+
});
|
|
29389
|
+
on(this.window, "closed", () => {
|
|
29390
|
+
this.dispose("window_closed");
|
|
29391
|
+
});
|
|
29392
|
+
const contents = this.window.webContents;
|
|
29393
|
+
on(contents, "render-process-gone", () => {
|
|
29394
|
+
this.releaseChild("owner_crash");
|
|
29395
|
+
});
|
|
29396
|
+
on(contents, "destroyed", () => {
|
|
29397
|
+
this.dispose("owner_destroyed");
|
|
29398
|
+
});
|
|
29399
|
+
on(contents, "did-start-navigation", (...args) => {
|
|
29400
|
+
const details = args[0];
|
|
29401
|
+
if (details?.isMainFrame && details.isSameDocument !== true) {
|
|
29402
|
+
this.releaseChild("owner_navigation");
|
|
29403
|
+
}
|
|
29404
|
+
});
|
|
29405
|
+
}
|
|
29406
|
+
detachOwnerListeners() {
|
|
29407
|
+
for (const remove of this.ownerListeners.splice(0)) remove();
|
|
29408
|
+
}
|
|
29409
|
+
ownerSize() {
|
|
29410
|
+
const bounds = this.window.getContentBounds();
|
|
29411
|
+
return { width: bounds.width, height: bounds.height };
|
|
29412
|
+
}
|
|
29413
|
+
ownerUnavailable() {
|
|
29414
|
+
try {
|
|
29415
|
+
return this.window.isDestroyed() || this.window.webContents.isDestroyed();
|
|
29416
|
+
} catch {
|
|
29417
|
+
return true;
|
|
29418
|
+
}
|
|
29419
|
+
}
|
|
29420
|
+
}
|
|
28717
29421
|
const PRIVATE_FILE_MODE = 384;
|
|
28718
29422
|
const PRIVATE_DIR_MODE = 448;
|
|
28719
29423
|
function writeJsonAtomic(path2, value) {
|
|
@@ -34003,7 +34707,7 @@ const enUiCommandPalette = {
|
|
|
34003
34707
|
"ui.command_palette.palette_search.unread": "Unread",
|
|
34004
34708
|
"ui.command_palette.palette_search.untitled_chat": "Untitled chat",
|
|
34005
34709
|
"ui.command_palette.use_palette_sources.agent_chat": "Agent chat",
|
|
34006
|
-
"ui.command_palette.use_palette_sources.agent_hub": "Agent
|
|
34710
|
+
"ui.command_palette.use_palette_sources.agent_hub": "Agent Hub",
|
|
34007
34711
|
"ui.command_palette.use_palette_sources.agent_settings": "Agent settings",
|
|
34008
34712
|
"ui.command_palette.use_palette_sources.analytics": "Analytics",
|
|
34009
34713
|
"ui.command_palette.use_palette_sources.app_backend_and_environment": "App, backend and environment",
|
|
@@ -36509,7 +37213,7 @@ const enUiSettingsUpdates = {
|
|
|
36509
37213
|
const enUiShell = {
|
|
36510
37214
|
"ui.shell.collapsible_app_logo.local_operator": "Local Operator",
|
|
36511
37215
|
"ui.shell.panel_rail.panels": "Panels",
|
|
36512
|
-
"ui.shell.sidebar_navigation.agent_hub": "Agent
|
|
37216
|
+
"ui.shell.sidebar_navigation.agent_hub": "Agent Hub",
|
|
36513
37217
|
"ui.shell.sidebar_navigation.agents": "Agents",
|
|
36514
37218
|
"ui.shell.sidebar_navigation.aida_missed": "{name}, {count, plural, one {{count, number, ::group-off} missed message} other {{count, number, ::group-off} missed messages}}",
|
|
36515
37219
|
"ui.shell.sidebar_navigation.aida_working": "{name}, working",
|
|
@@ -36517,17 +37221,31 @@ const enUiShell = {
|
|
|
36517
37221
|
"ui.shell.sidebar_navigation.browser_waiting": "Browser, {count, plural, one {{countText} waiting} other {{countText} waiting}}",
|
|
36518
37222
|
"ui.shell.sidebar_navigation.close_sidebar": "Close sidebar",
|
|
36519
37223
|
"ui.shell.sidebar_navigation.collapse_sidebar": "Collapse sidebar",
|
|
37224
|
+
"ui.shell.sidebar_navigation.drag_armed": "Moving {name}. Press Escape to cancel.",
|
|
36520
37225
|
"ui.shell.sidebar_navigation.expand_sidebar": "Expand sidebar",
|
|
36521
37226
|
"ui.shell.sidebar_navigation.mesh": "Mesh",
|
|
36522
37227
|
"ui.shell.sidebar_navigation.mesh_waiting": "Mesh, {count, plural, one {{countText} waiting} other {{countText} waiting}}",
|
|
37228
|
+
"ui.shell.sidebar_navigation.more_waiting": "More, {count, plural, one {{countText} waiting} other {{countText} waiting}}",
|
|
37229
|
+
"ui.shell.sidebar_navigation.more_working": "More, working",
|
|
37230
|
+
"ui.shell.sidebar_navigation.move_down": "Move down",
|
|
37231
|
+
"ui.shell.sidebar_navigation.move_note": "Moved {name} to position {position} of {total}.",
|
|
37232
|
+
"ui.shell.sidebar_navigation.move_to_more": "Move to More",
|
|
37233
|
+
"ui.shell.sidebar_navigation.move_to_more_note": "{name} moved to More.",
|
|
37234
|
+
"ui.shell.sidebar_navigation.move_up": "Move up",
|
|
36523
37235
|
"ui.shell.sidebar_navigation.new_chat": "New chat",
|
|
36524
37236
|
"ui.shell.sidebar_navigation.new_chat_shortcut": "New chat ({shortcut})",
|
|
36525
37237
|
"ui.shell.sidebar_navigation.projects": "Projects",
|
|
37238
|
+
"ui.shell.sidebar_navigation.reset_layout": "Reset sidebar layout",
|
|
37239
|
+
"ui.shell.sidebar_navigation.reset_note": "Sidebar layout reset.",
|
|
37240
|
+
"ui.shell.sidebar_navigation.row_actions": "Actions for {name}",
|
|
37241
|
+
"ui.shell.sidebar_navigation.save_failed": "Could not save the sidebar layout.",
|
|
36526
37242
|
"ui.shell.sidebar_navigation.schedules": "Schedules",
|
|
36527
37243
|
"ui.shell.sidebar_navigation.search": "Search",
|
|
36528
37244
|
"ui.shell.sidebar_navigation.search_accessible": "Search ({everything}) — chats ({chats})",
|
|
36529
37245
|
"ui.shell.sidebar_navigation.search_tooltip": "Search everything ({everything}) · your chats ({chats})",
|
|
36530
37246
|
"ui.shell.sidebar_navigation.settings": "Settings",
|
|
37247
|
+
"ui.shell.sidebar_navigation.show_in_sidebar": "Show in sidebar",
|
|
37248
|
+
"ui.shell.sidebar_navigation.show_in_sidebar_note": "{name} shown in the sidebar.",
|
|
36531
37249
|
"ui.shell.user_profile_sidebar.account_settings": "Account settings",
|
|
36532
37250
|
"ui.shell.user_profile_sidebar.account_unavailable": "Account unavailable",
|
|
36533
37251
|
"ui.shell.user_profile_sidebar.checking_account": "Checking account…",
|
|
@@ -40081,17 +40799,31 @@ const esUiShell = {
|
|
|
40081
40799
|
"ui.shell.sidebar_navigation.browser_waiting": "Navegador, {count, plural, one {{countText} en espera} many {{countText} en espera} other {{countText} en espera}}",
|
|
40082
40800
|
"ui.shell.sidebar_navigation.close_sidebar": "Cerrar barra lateral",
|
|
40083
40801
|
"ui.shell.sidebar_navigation.collapse_sidebar": "Contraer barra lateral",
|
|
40802
|
+
"ui.shell.sidebar_navigation.drag_armed": "Moviendo {name}. Pulsa Esc para cancelar.",
|
|
40084
40803
|
"ui.shell.sidebar_navigation.expand_sidebar": "Expandir barra lateral",
|
|
40085
40804
|
"ui.shell.sidebar_navigation.mesh": "Mesh",
|
|
40086
40805
|
"ui.shell.sidebar_navigation.mesh_waiting": "Mesh, {count, plural, one {{countText} en espera} many {{countText} en espera} other {{countText} en espera}}",
|
|
40806
|
+
"ui.shell.sidebar_navigation.more_waiting": "Más, {count, plural, one {{countText} en espera} many {{countText} en espera} other {{countText} en espera}}",
|
|
40807
|
+
"ui.shell.sidebar_navigation.more_working": "Más, trabajando",
|
|
40808
|
+
"ui.shell.sidebar_navigation.move_down": "Bajar",
|
|
40809
|
+
"ui.shell.sidebar_navigation.move_note": "Se movió {name} a la posición {position} de {total}.",
|
|
40810
|
+
"ui.shell.sidebar_navigation.move_to_more": "Mover a Más",
|
|
40811
|
+
"ui.shell.sidebar_navigation.move_to_more_note": "{name} se movió a Más.",
|
|
40812
|
+
"ui.shell.sidebar_navigation.move_up": "Subir",
|
|
40087
40813
|
"ui.shell.sidebar_navigation.new_chat": "Nuevo chat",
|
|
40088
40814
|
"ui.shell.sidebar_navigation.new_chat_shortcut": "Nuevo chat ({shortcut})",
|
|
40089
40815
|
"ui.shell.sidebar_navigation.projects": "Proyectos",
|
|
40816
|
+
"ui.shell.sidebar_navigation.reset_layout": "Restablecer la disposición",
|
|
40817
|
+
"ui.shell.sidebar_navigation.reset_note": "Disposición de la barra lateral restablecida.",
|
|
40818
|
+
"ui.shell.sidebar_navigation.row_actions": "Acciones para {name}",
|
|
40819
|
+
"ui.shell.sidebar_navigation.save_failed": "No se pudo guardar la disposición de la barra lateral.",
|
|
40090
40820
|
"ui.shell.sidebar_navigation.schedules": "Programaciones",
|
|
40091
40821
|
"ui.shell.sidebar_navigation.search": "Buscar",
|
|
40092
40822
|
"ui.shell.sidebar_navigation.search_accessible": "Buscar en todo ({everything}) — chats ({chats})",
|
|
40093
40823
|
"ui.shell.sidebar_navigation.search_tooltip": "Buscar en todo ({everything}) · tus chats ({chats})",
|
|
40094
40824
|
"ui.shell.sidebar_navigation.settings": "Ajustes",
|
|
40825
|
+
"ui.shell.sidebar_navigation.show_in_sidebar": "Mostrar en la barra lateral",
|
|
40826
|
+
"ui.shell.sidebar_navigation.show_in_sidebar_note": "{name} ahora aparece en la barra lateral.",
|
|
40095
40827
|
"ui.shell.user_profile_sidebar.account_settings": "Ajustes de cuenta",
|
|
40096
40828
|
"ui.shell.user_profile_sidebar.account_unavailable": "Cuenta no disponible",
|
|
40097
40829
|
"ui.shell.user_profile_sidebar.checking_account": "Comprobando la cuenta…",
|
|
@@ -43645,17 +44377,31 @@ const frUiShell = {
|
|
|
43645
44377
|
"ui.shell.sidebar_navigation.browser_waiting": "Navigateur, {count, plural, one {{countText} approbation en attente} many {{countText} d’approbations en attente} other {{countText} approbations en attente}}",
|
|
43646
44378
|
"ui.shell.sidebar_navigation.close_sidebar": "Fermer la barre latérale",
|
|
43647
44379
|
"ui.shell.sidebar_navigation.collapse_sidebar": "Réduire la barre latérale",
|
|
44380
|
+
"ui.shell.sidebar_navigation.drag_armed": "Déplacement de {name}. Appuyez sur Esc pour annuler.",
|
|
43648
44381
|
"ui.shell.sidebar_navigation.expand_sidebar": "Développer la barre latérale",
|
|
43649
44382
|
"ui.shell.sidebar_navigation.mesh": "Maillage",
|
|
43650
44383
|
"ui.shell.sidebar_navigation.mesh_waiting": "Mesh, {count, plural, one {{countText} demande en attente} many {{countText} de demandes en attente} other {{countText} demandes en attente}}",
|
|
44384
|
+
"ui.shell.sidebar_navigation.more_waiting": "Plus, {count, plural, one {{countText} en attente} many {{countText} en attente} other {{countText} en attente}}",
|
|
44385
|
+
"ui.shell.sidebar_navigation.more_working": "Plus, en cours",
|
|
44386
|
+
"ui.shell.sidebar_navigation.move_down": "Déplacer vers le bas",
|
|
44387
|
+
"ui.shell.sidebar_navigation.move_note": "{name} est maintenant en position {position} sur {total}.",
|
|
44388
|
+
"ui.shell.sidebar_navigation.move_to_more": "Déplacer vers Plus",
|
|
44389
|
+
"ui.shell.sidebar_navigation.move_to_more_note": "{name} fait maintenant partie de Plus.",
|
|
44390
|
+
"ui.shell.sidebar_navigation.move_up": "Déplacer vers le haut",
|
|
43651
44391
|
"ui.shell.sidebar_navigation.new_chat": "Nouvelle conversation",
|
|
43652
44392
|
"ui.shell.sidebar_navigation.new_chat_shortcut": "Nouvelle conversation ({shortcut})",
|
|
43653
44393
|
"ui.shell.sidebar_navigation.projects": "Projets",
|
|
44394
|
+
"ui.shell.sidebar_navigation.reset_layout": "Réinitialiser la disposition",
|
|
44395
|
+
"ui.shell.sidebar_navigation.reset_note": "Disposition de la barre latérale réinitialisée.",
|
|
44396
|
+
"ui.shell.sidebar_navigation.row_actions": "Actions pour {name}",
|
|
44397
|
+
"ui.shell.sidebar_navigation.save_failed": "Impossible d’enregistrer la disposition de la barre latérale.",
|
|
43654
44398
|
"ui.shell.sidebar_navigation.schedules": "Planifications",
|
|
43655
44399
|
"ui.shell.sidebar_navigation.search": "Rechercher",
|
|
43656
44400
|
"ui.shell.sidebar_navigation.search_accessible": "Rechercher ({everything}) — conversations ({chats})",
|
|
43657
44401
|
"ui.shell.sidebar_navigation.search_tooltip": "Tout rechercher ({everything}) · vos conversations ({chats})",
|
|
43658
44402
|
"ui.shell.sidebar_navigation.settings": "Paramètres",
|
|
44403
|
+
"ui.shell.sidebar_navigation.show_in_sidebar": "Afficher dans la barre latérale",
|
|
44404
|
+
"ui.shell.sidebar_navigation.show_in_sidebar_note": "{name} apparaît maintenant dans la barre latérale.",
|
|
43659
44405
|
"ui.shell.user_profile_sidebar.account_settings": "Paramètres du compte",
|
|
43660
44406
|
"ui.shell.user_profile_sidebar.account_unavailable": "Compte indisponible",
|
|
43661
44407
|
"ui.shell.user_profile_sidebar.checking_account": "Vérification du compte…",
|
|
@@ -47167,17 +47913,31 @@ const hiUiShell = {
|
|
|
47167
47913
|
"ui.shell.sidebar_navigation.browser_waiting": "ब्राउज़र, {count, plural, one {{countText} इंतज़ार में} other {{countText} इंतज़ार में}}",
|
|
47168
47914
|
"ui.shell.sidebar_navigation.close_sidebar": "साइडबार बंद करें",
|
|
47169
47915
|
"ui.shell.sidebar_navigation.collapse_sidebar": "साइडबार समेटें",
|
|
47916
|
+
"ui.shell.sidebar_navigation.drag_armed": "{name} को ले जाया जा रहा है। रद्द करने के लिए Esc दबाएँ।",
|
|
47170
47917
|
"ui.shell.sidebar_navigation.expand_sidebar": "साइडबार फैलाएँ",
|
|
47171
47918
|
"ui.shell.sidebar_navigation.mesh": "मेश",
|
|
47172
47919
|
"ui.shell.sidebar_navigation.mesh_waiting": "मेश, {count, plural, one {{countText} इंतज़ार में} other {{countText} इंतज़ार में}}",
|
|
47920
|
+
"ui.shell.sidebar_navigation.more_waiting": "और, {count, plural, one {{countText} इंतज़ार में} other {{countText} इंतज़ार में}}",
|
|
47921
|
+
"ui.shell.sidebar_navigation.more_working": "और, काम जारी है",
|
|
47922
|
+
"ui.shell.sidebar_navigation.move_down": "नीचे ले जाएँ",
|
|
47923
|
+
"ui.shell.sidebar_navigation.move_note": "{name} को कुल {total} में से स्थान {position} पर ले जाया गया।",
|
|
47924
|
+
"ui.shell.sidebar_navigation.move_to_more": "और सेक्शन में ले जाएँ",
|
|
47925
|
+
"ui.shell.sidebar_navigation.move_to_more_note": "{name} को और सेक्शन में ले जाया गया।",
|
|
47926
|
+
"ui.shell.sidebar_navigation.move_up": "ऊपर ले जाएँ",
|
|
47173
47927
|
"ui.shell.sidebar_navigation.new_chat": "नई चैट",
|
|
47174
47928
|
"ui.shell.sidebar_navigation.new_chat_shortcut": "नई चैट ({shortcut})",
|
|
47175
47929
|
"ui.shell.sidebar_navigation.projects": "प्रोजेक्ट",
|
|
47930
|
+
"ui.shell.sidebar_navigation.reset_layout": "साइडबार लेआउट रीसेट करें",
|
|
47931
|
+
"ui.shell.sidebar_navigation.reset_note": "साइडबार लेआउट रीसेट हो गया।",
|
|
47932
|
+
"ui.shell.sidebar_navigation.row_actions": "{name} की कार्रवाइयाँ",
|
|
47933
|
+
"ui.shell.sidebar_navigation.save_failed": "साइडबार लेआउट सहेजा नहीं जा सका।",
|
|
47176
47934
|
"ui.shell.sidebar_navigation.schedules": "शेड्यूल",
|
|
47177
47935
|
"ui.shell.sidebar_navigation.search": "खोजें",
|
|
47178
47936
|
"ui.shell.sidebar_navigation.search_accessible": "खोजें ({everything}) — चैट ({chats})",
|
|
47179
47937
|
"ui.shell.sidebar_navigation.search_tooltip": "सब कुछ खोजें ({everything}) · आपकी चैट ({chats})",
|
|
47180
47938
|
"ui.shell.sidebar_navigation.settings": "सेटिंग्स",
|
|
47939
|
+
"ui.shell.sidebar_navigation.show_in_sidebar": "साइडबार में दिखाएँ",
|
|
47940
|
+
"ui.shell.sidebar_navigation.show_in_sidebar_note": "{name} अब साइडबार में है।",
|
|
47181
47941
|
"ui.shell.user_profile_sidebar.account_settings": "खाते की सेटिंग्स",
|
|
47182
47942
|
"ui.shell.user_profile_sidebar.account_unavailable": "खाता उपलब्ध नहीं",
|
|
47183
47943
|
"ui.shell.user_profile_sidebar.checking_account": "खाता जाँचा जा रहा है…",
|
|
@@ -50528,17 +51288,31 @@ const ruUiShell = {
|
|
|
50528
51288
|
"ui.shell.sidebar_navigation.browser_waiting": "Браузер, {count, plural, one {ожидает {countText}} few {ожидают {countText}} many {ожидают {countText}} other {ожидают {countText}}}",
|
|
50529
51289
|
"ui.shell.sidebar_navigation.close_sidebar": "Закрыть боковую панель",
|
|
50530
51290
|
"ui.shell.sidebar_navigation.collapse_sidebar": "Свернуть боковую панель",
|
|
51291
|
+
"ui.shell.sidebar_navigation.drag_armed": "Перемещение: {name}. Нажмите Esc, чтобы отменить.",
|
|
50531
51292
|
"ui.shell.sidebar_navigation.expand_sidebar": "Развернуть боковую панель",
|
|
50532
51293
|
"ui.shell.sidebar_navigation.mesh": "Меш-сеть",
|
|
50533
51294
|
"ui.shell.sidebar_navigation.mesh_waiting": "Меш-сеть, {count, plural, one {ожидает {countText}} few {ожидают {countText}} many {ожидают {countText}} other {ожидают {countText}}}",
|
|
51295
|
+
"ui.shell.sidebar_navigation.more_waiting": "Ещё, {count, plural, one {ожидает {countText}} few {ожидают {countText}} many {ожидают {countText}} other {ожидают {countText}}}",
|
|
51296
|
+
"ui.shell.sidebar_navigation.more_working": "Ещё, идёт работа",
|
|
51297
|
+
"ui.shell.sidebar_navigation.move_down": "Переместить ниже",
|
|
51298
|
+
"ui.shell.sidebar_navigation.move_note": "{name} теперь на позиции {position} из {total}.",
|
|
51299
|
+
"ui.shell.sidebar_navigation.move_to_more": "Переместить в «Ещё»",
|
|
51300
|
+
"ui.shell.sidebar_navigation.move_to_more_note": "{name} теперь в «Ещё».",
|
|
51301
|
+
"ui.shell.sidebar_navigation.move_up": "Переместить выше",
|
|
50534
51302
|
"ui.shell.sidebar_navigation.new_chat": "Новый чат",
|
|
50535
51303
|
"ui.shell.sidebar_navigation.new_chat_shortcut": "Новый чат ({shortcut})",
|
|
50536
51304
|
"ui.shell.sidebar_navigation.projects": "Проекты",
|
|
51305
|
+
"ui.shell.sidebar_navigation.reset_layout": "Сбросить расположение боковой панели",
|
|
51306
|
+
"ui.shell.sidebar_navigation.reset_note": "Расположение боковой панели сброшено.",
|
|
51307
|
+
"ui.shell.sidebar_navigation.row_actions": "Действия для {name}",
|
|
51308
|
+
"ui.shell.sidebar_navigation.save_failed": "Не удалось сохранить расположение боковой панели.",
|
|
50537
51309
|
"ui.shell.sidebar_navigation.schedules": "Расписания",
|
|
50538
51310
|
"ui.shell.sidebar_navigation.search": "Поиск",
|
|
50539
51311
|
"ui.shell.sidebar_navigation.search_accessible": "Поиск ({everything}) — чаты ({chats})",
|
|
50540
51312
|
"ui.shell.sidebar_navigation.search_tooltip": "Поиск по всему ({everything}) · ваши чаты ({chats})",
|
|
50541
51313
|
"ui.shell.sidebar_navigation.settings": "Настройки",
|
|
51314
|
+
"ui.shell.sidebar_navigation.show_in_sidebar": "Показать на боковой панели",
|
|
51315
|
+
"ui.shell.sidebar_navigation.show_in_sidebar_note": "{name} теперь отображается на боковой панели.",
|
|
50542
51316
|
"ui.shell.user_profile_sidebar.account_settings": "Настройки учётной записи",
|
|
50543
51317
|
"ui.shell.user_profile_sidebar.account_unavailable": "Учётная запись недоступна",
|
|
50544
51318
|
"ui.shell.user_profile_sidebar.checking_account": "Проверка учётной записи…",
|
|
@@ -53975,17 +54749,31 @@ const urUiShell = {
|
|
|
53975
54749
|
"ui.shell.sidebar_navigation.browser_waiting": "براؤزر، {count, plural, one {{countText} منتظر} other {{countText} منتظر}}",
|
|
53976
54750
|
"ui.shell.sidebar_navigation.close_sidebar": "سائیڈ بار بند کریں",
|
|
53977
54751
|
"ui.shell.sidebar_navigation.collapse_sidebar": "سائیڈ بار سمیٹیں",
|
|
54752
|
+
"ui.shell.sidebar_navigation.drag_armed": "{name} منتقل کیا جا رہا ہے۔ منسوخ کرنے کے لیے Esc دبائیں۔",
|
|
53978
54753
|
"ui.shell.sidebar_navigation.expand_sidebar": "سائیڈ بار پھیلائیں",
|
|
53979
54754
|
"ui.shell.sidebar_navigation.mesh": "Mesh",
|
|
53980
54755
|
"ui.shell.sidebar_navigation.mesh_waiting": "Mesh، {count, plural, one {{countText} منتظر} other {{countText} منتظر}}",
|
|
54756
|
+
"ui.shell.sidebar_navigation.more_waiting": "مزید، {count, plural, one {{countText} منتظر} other {{countText} منتظر}}",
|
|
54757
|
+
"ui.shell.sidebar_navigation.more_working": "مزید، کام جاری ہے",
|
|
54758
|
+
"ui.shell.sidebar_navigation.move_down": "نیچے کریں",
|
|
54759
|
+
"ui.shell.sidebar_navigation.move_note": "{name} کو {total} میں سے {position} مقام پر منتقل کر دیا گیا۔",
|
|
54760
|
+
"ui.shell.sidebar_navigation.move_to_more": "مزید حصے میں منتقل کریں",
|
|
54761
|
+
"ui.shell.sidebar_navigation.move_to_more_note": "{name} کو مزید حصے میں منتقل کر دیا گیا۔",
|
|
54762
|
+
"ui.shell.sidebar_navigation.move_up": "اوپر کریں",
|
|
53981
54763
|
"ui.shell.sidebar_navigation.new_chat": "نئی چیٹ",
|
|
53982
54764
|
"ui.shell.sidebar_navigation.new_chat_shortcut": "نئی چیٹ — {shortcut}",
|
|
53983
54765
|
"ui.shell.sidebar_navigation.projects": "پروجیکٹس",
|
|
54766
|
+
"ui.shell.sidebar_navigation.reset_layout": "سائیڈ بار کا لے آؤٹ ری سیٹ کریں",
|
|
54767
|
+
"ui.shell.sidebar_navigation.reset_note": "سائیڈ بار کا لے آؤٹ ری سیٹ ہو گیا۔",
|
|
54768
|
+
"ui.shell.sidebar_navigation.row_actions": "{name} کے لیے اقدامات",
|
|
54769
|
+
"ui.shell.sidebar_navigation.save_failed": "سائیڈ بار کا لے آؤٹ محفوظ نہیں ہو سکا۔",
|
|
53984
54770
|
"ui.shell.sidebar_navigation.schedules": "شیڈول",
|
|
53985
54771
|
"ui.shell.sidebar_navigation.search": "تلاش کریں",
|
|
53986
54772
|
"ui.shell.sidebar_navigation.search_accessible": "تلاش — {everything} — چیٹس — {chats}",
|
|
53987
54773
|
"ui.shell.sidebar_navigation.search_tooltip": "سب کچھ تلاش کریں — {everything} · آپ کی چیٹس — {chats}",
|
|
53988
54774
|
"ui.shell.sidebar_navigation.settings": "ترتیبات",
|
|
54775
|
+
"ui.shell.sidebar_navigation.show_in_sidebar": "سائیڈ بار میں دکھائیں",
|
|
54776
|
+
"ui.shell.sidebar_navigation.show_in_sidebar_note": "{name} اب سائیڈ بار میں ہے۔",
|
|
53989
54777
|
"ui.shell.user_profile_sidebar.account_settings": "اکاؤنٹ کی ترتیبات",
|
|
53990
54778
|
"ui.shell.user_profile_sidebar.account_unavailable": "اکاؤنٹ دستیاب نہیں",
|
|
53991
54779
|
"ui.shell.user_profile_sidebar.checking_account": "اکاؤنٹ کی جانچ ہو رہی ہے…",
|
|
@@ -57145,17 +57933,31 @@ const viUiShell = {
|
|
|
57145
57933
|
"ui.shell.sidebar_navigation.browser_waiting": "Trình duyệt, {count, plural, other {{countText} đang chờ}}",
|
|
57146
57934
|
"ui.shell.sidebar_navigation.close_sidebar": "Đóng thanh bên",
|
|
57147
57935
|
"ui.shell.sidebar_navigation.collapse_sidebar": "Thu gọn thanh bên",
|
|
57936
|
+
"ui.shell.sidebar_navigation.drag_armed": "Đang chuyển {name}. Nhấn Esc để hủy.",
|
|
57148
57937
|
"ui.shell.sidebar_navigation.expand_sidebar": "Mở rộng thanh bên",
|
|
57149
57938
|
"ui.shell.sidebar_navigation.mesh": "Mạng lưới",
|
|
57150
57939
|
"ui.shell.sidebar_navigation.mesh_waiting": "Mạng lưới, {count, plural, other {{countText} đang chờ}}",
|
|
57940
|
+
"ui.shell.sidebar_navigation.more_waiting": "Khác, {count, plural, other {{countText} đang chờ}}",
|
|
57941
|
+
"ui.shell.sidebar_navigation.more_working": "Khác, đang làm việc",
|
|
57942
|
+
"ui.shell.sidebar_navigation.move_down": "Chuyển xuống",
|
|
57943
|
+
"ui.shell.sidebar_navigation.move_note": "Đã chuyển {name} đến vị trí {position} trên {total}.",
|
|
57944
|
+
"ui.shell.sidebar_navigation.move_to_more": "Chuyển vào mục Khác",
|
|
57945
|
+
"ui.shell.sidebar_navigation.move_to_more_note": "Đã chuyển {name} vào mục Khác.",
|
|
57946
|
+
"ui.shell.sidebar_navigation.move_up": "Chuyển lên",
|
|
57151
57947
|
"ui.shell.sidebar_navigation.new_chat": "Cuộc trò chuyện mới",
|
|
57152
57948
|
"ui.shell.sidebar_navigation.new_chat_shortcut": "Cuộc trò chuyện mới ({shortcut})",
|
|
57153
57949
|
"ui.shell.sidebar_navigation.projects": "Dự án",
|
|
57950
|
+
"ui.shell.sidebar_navigation.reset_layout": "Đặt lại bố cục thanh bên",
|
|
57951
|
+
"ui.shell.sidebar_navigation.reset_note": "Đã đặt lại bố cục thanh bên.",
|
|
57952
|
+
"ui.shell.sidebar_navigation.row_actions": "Thao tác cho {name}",
|
|
57953
|
+
"ui.shell.sidebar_navigation.save_failed": "Không lưu được bố cục thanh bên.",
|
|
57154
57954
|
"ui.shell.sidebar_navigation.schedules": "Lịch chạy",
|
|
57155
57955
|
"ui.shell.sidebar_navigation.search": "Tìm kiếm",
|
|
57156
57956
|
"ui.shell.sidebar_navigation.search_accessible": "Tìm kiếm ({everything}) — cuộc trò chuyện ({chats})",
|
|
57157
57957
|
"ui.shell.sidebar_navigation.search_tooltip": "Tìm mọi thứ ({everything}) · cuộc trò chuyện của bạn ({chats})",
|
|
57158
57958
|
"ui.shell.sidebar_navigation.settings": "Cài đặt",
|
|
57959
|
+
"ui.shell.sidebar_navigation.show_in_sidebar": "Hiện trong thanh bên",
|
|
57960
|
+
"ui.shell.sidebar_navigation.show_in_sidebar_note": "{name} đã được hiển thị trong thanh bên.",
|
|
57159
57961
|
"ui.shell.user_profile_sidebar.account_settings": "Cài đặt tài khoản",
|
|
57160
57962
|
"ui.shell.user_profile_sidebar.account_unavailable": "Không truy cập được tài khoản",
|
|
57161
57963
|
"ui.shell.user_profile_sidebar.checking_account": "Đang kiểm tra tài khoản…",
|
|
@@ -60614,17 +61416,31 @@ const zhCNUiShell = {
|
|
|
60614
61416
|
"ui.shell.sidebar_navigation.browser_waiting": "浏览器,{count, plural, other {{countText}项待处理}}",
|
|
60615
61417
|
"ui.shell.sidebar_navigation.close_sidebar": "关闭侧边栏",
|
|
60616
61418
|
"ui.shell.sidebar_navigation.collapse_sidebar": "收起侧边栏",
|
|
61419
|
+
"ui.shell.sidebar_navigation.drag_armed": "正在移动{name}。按Esc取消。",
|
|
60617
61420
|
"ui.shell.sidebar_navigation.expand_sidebar": "展开侧边栏",
|
|
60618
61421
|
"ui.shell.sidebar_navigation.mesh": "网格",
|
|
60619
61422
|
"ui.shell.sidebar_navigation.mesh_waiting": "网格,{count, plural, other {{countText}项待处理}}",
|
|
61423
|
+
"ui.shell.sidebar_navigation.more_waiting": "更多,{count, plural, other {{countText}项待处理}}",
|
|
61424
|
+
"ui.shell.sidebar_navigation.more_working": "更多,工作中",
|
|
61425
|
+
"ui.shell.sidebar_navigation.move_down": "下移",
|
|
61426
|
+
"ui.shell.sidebar_navigation.move_note": "已将{name}移至第{position}位,共{total}个。",
|
|
61427
|
+
"ui.shell.sidebar_navigation.move_to_more": "移至更多",
|
|
61428
|
+
"ui.shell.sidebar_navigation.move_to_more_note": "{name}已移至更多。",
|
|
61429
|
+
"ui.shell.sidebar_navigation.move_up": "上移",
|
|
60620
61430
|
"ui.shell.sidebar_navigation.new_chat": "新建对话",
|
|
60621
61431
|
"ui.shell.sidebar_navigation.new_chat_shortcut": "新建对话({shortcut})",
|
|
60622
61432
|
"ui.shell.sidebar_navigation.projects": "项目",
|
|
61433
|
+
"ui.shell.sidebar_navigation.reset_layout": "重置侧边栏布局",
|
|
61434
|
+
"ui.shell.sidebar_navigation.reset_note": "侧边栏布局已重置。",
|
|
61435
|
+
"ui.shell.sidebar_navigation.row_actions": "{name}的操作",
|
|
61436
|
+
"ui.shell.sidebar_navigation.save_failed": "无法保存侧边栏布局。",
|
|
60623
61437
|
"ui.shell.sidebar_navigation.schedules": "定时任务",
|
|
60624
61438
|
"ui.shell.sidebar_navigation.search": "搜索",
|
|
60625
61439
|
"ui.shell.sidebar_navigation.search_accessible": "搜索({everything})—对话({chats})",
|
|
60626
61440
|
"ui.shell.sidebar_navigation.search_tooltip": "搜索全部内容({everything})·搜索对话({chats})",
|
|
60627
61441
|
"ui.shell.sidebar_navigation.settings": "设置",
|
|
61442
|
+
"ui.shell.sidebar_navigation.show_in_sidebar": "在侧边栏中显示",
|
|
61443
|
+
"ui.shell.sidebar_navigation.show_in_sidebar_note": "{name}已显示在侧边栏中。",
|
|
60628
61444
|
"ui.shell.user_profile_sidebar.account_settings": "账户设置",
|
|
60629
61445
|
"ui.shell.user_profile_sidebar.account_unavailable": "账户不可用",
|
|
60630
61446
|
"ui.shell.user_profile_sidebar.checking_account": "正在检查账户……",
|
|
@@ -62955,10 +63771,29 @@ function mintNonce() {
|
|
|
62955
63771
|
return node_crypto.randomBytes(16).toString("hex");
|
|
62956
63772
|
}
|
|
62957
63773
|
class TabRegistry {
|
|
62958
|
-
|
|
63774
|
+
/**
|
|
63775
|
+
* The fourth callback is a post-layout observer, optional and defaulted so
|
|
63776
|
+
* every existing three-argument construction is unchanged.
|
|
63777
|
+
*
|
|
63778
|
+
* WHY IT EXISTS: a native child positioned over a page has to know that the
|
|
63779
|
+
* presented tab, its presentation bit or the content rectangle moved. Polling
|
|
63780
|
+
* the registry would read a rectangle that is already stale, and `onChanged`
|
|
63781
|
+
* is deliberately NOT that signal (`setContentRect` does not call it). The
|
|
63782
|
+
* snapshot is copied and delivered after every pass — including null and
|
|
63783
|
+
* suppressed layouts — because "nothing is presented now" is exactly when a
|
|
63784
|
+
* stale overlay must hide.
|
|
63785
|
+
*
|
|
63786
|
+
* WHY IT CANNOT FAIL THE LAYOUT: page geometry is the product's behaviour and
|
|
63787
|
+
* an observer is infrastructure around it. A throwing observer is swallowed
|
|
63788
|
+
* here (the controller logs its own failure) so one experimental child can
|
|
63789
|
+
* never leave pages unlaid-out.
|
|
63790
|
+
*/
|
|
63791
|
+
constructor(viewFactory, onRemove, onChanged, onLayout = () => {
|
|
63792
|
+
}) {
|
|
62959
63793
|
this.viewFactory = viewFactory;
|
|
62960
63794
|
this.onRemove = onRemove;
|
|
62961
63795
|
this.onChanged = onChanged;
|
|
63796
|
+
this.onLayout = onLayout;
|
|
62962
63797
|
}
|
|
62963
63798
|
tabs = /* @__PURE__ */ new Map();
|
|
62964
63799
|
nextTabId = 1;
|
|
@@ -62968,6 +63803,9 @@ class TabRegistry {
|
|
|
62968
63803
|
/** Tabs with a command in flight, keyed by tabId. See `lane`. */
|
|
62969
63804
|
busy = /* @__PURE__ */ new Set();
|
|
62970
63805
|
epochListeners = [];
|
|
63806
|
+
/** Monotone count of layout passes, for an observer that needs identity, not
|
|
63807
|
+
* just values (S1's address overlay). */
|
|
63808
|
+
layoutRevision = 0;
|
|
62971
63809
|
// ---- creation, addressing, listing ---------------------------------------
|
|
62972
63810
|
/**
|
|
62973
63811
|
* Create a tab. A user tab becomes active (the user asked for it); an AGENT
|
|
@@ -63270,6 +64108,22 @@ class TabRegistry {
|
|
|
63270
64108
|
);
|
|
63271
64109
|
record.view.setVisible(record.presented);
|
|
63272
64110
|
}
|
|
64111
|
+
this.layoutRevision += 1;
|
|
64112
|
+
const rect = this.contentRect;
|
|
64113
|
+
try {
|
|
64114
|
+
this.onLayout({
|
|
64115
|
+
activeTabId: this.activeTabId,
|
|
64116
|
+
presented: active?.presented === true,
|
|
64117
|
+
contentRect: rect ? {
|
|
64118
|
+
x: rect.x,
|
|
64119
|
+
y: rect.y,
|
|
64120
|
+
width: rect.width,
|
|
64121
|
+
height: rect.height
|
|
64122
|
+
} : null,
|
|
64123
|
+
revision: this.layoutRevision
|
|
64124
|
+
});
|
|
64125
|
+
} catch {
|
|
64126
|
+
}
|
|
63273
64127
|
}
|
|
63274
64128
|
// ---- removal -------------------------------------------------------------
|
|
63275
64129
|
/**
|
|
@@ -66365,6 +67219,58 @@ function restrictMode(path2, log2) {
|
|
|
66365
67219
|
);
|
|
66366
67220
|
}
|
|
66367
67221
|
}
|
|
67222
|
+
const DEV_DRIVER_ENV = "LOCAL_OPERATOR_UI_DEV_DRIVER";
|
|
67223
|
+
const DEV_DRIVER_OUT_ENV = "LOCAL_OPERATOR_UI_DEV_DRIVER_OUT";
|
|
67224
|
+
const DEV_DRIVER_ARG = "--lo-dev-driver";
|
|
67225
|
+
const DEV_DRIVER_CAPTURE = "dev-driver-capture";
|
|
67226
|
+
const DEV_DRIVER_FACTS = "dev-driver-facts";
|
|
67227
|
+
const DEV_DRIVER_ADDRESS_OVERLAY = "dev-driver-address-overlay";
|
|
67228
|
+
const TRUTHY = /* @__PURE__ */ new Set(["1", "true"]);
|
|
67229
|
+
function readOptIn(env) {
|
|
67230
|
+
const raw = env[DEV_DRIVER_ENV];
|
|
67231
|
+
if (raw === void 0 || raw.trim() === "")
|
|
67232
|
+
return { asked: false, value: null };
|
|
67233
|
+
return { asked: true, value: raw.trim() };
|
|
67234
|
+
}
|
|
67235
|
+
function resolveDevDriverArming(input) {
|
|
67236
|
+
const off = (problems = []) => ({
|
|
67237
|
+
armed: false,
|
|
67238
|
+
outDir: null,
|
|
67239
|
+
problems
|
|
67240
|
+
});
|
|
67241
|
+
const optIn = readOptIn(input.env);
|
|
67242
|
+
if (!optIn.asked) return off();
|
|
67243
|
+
if (!TRUTHY.has(optIn.value.toLowerCase())) {
|
|
67244
|
+
return off([
|
|
67245
|
+
`${DEV_DRIVER_ENV}=${optIn.value} is not an opt-in (accepted: 1, true); the renderer dev driver stayed off`
|
|
67246
|
+
]);
|
|
67247
|
+
}
|
|
67248
|
+
if (input.windowMode !== "headless" && input.windowMode !== "inactive") {
|
|
67249
|
+
return off([
|
|
67250
|
+
`the renderer dev driver refused to arm in a "${input.windowMode}" window; it never raises one, so use --window-mode=headless (or inactive)`
|
|
67251
|
+
]);
|
|
67252
|
+
}
|
|
67253
|
+
const outDir = input.env[DEV_DRIVER_OUT_ENV]?.trim() ?? "";
|
|
67254
|
+
if (outDir === "" || !outDir.startsWith("/")) {
|
|
67255
|
+
return off([
|
|
67256
|
+
`${DEV_DRIVER_ENV} was set but ${DEV_DRIVER_OUT_ENV} is ${outDir === "" ? "missing" : `"${outDir}"`}; an absolute frames directory is required, so the driver did not arm`
|
|
67257
|
+
]);
|
|
67258
|
+
}
|
|
67259
|
+
return { armed: true, outDir, problems: [] };
|
|
67260
|
+
}
|
|
67261
|
+
function headlessExerciserAllowed(input) {
|
|
67262
|
+
return input.arming.armed && input.windowMode === "headless";
|
|
67263
|
+
}
|
|
67264
|
+
function devDriverArgument(outDir) {
|
|
67265
|
+
return `${DEV_DRIVER_ARG}=${outDir}`;
|
|
67266
|
+
}
|
|
67267
|
+
function describeDevDriverArming(arming) {
|
|
67268
|
+
if (arming.armed) {
|
|
67269
|
+
return `[dev-driver] ARMED; frames are written to ${arming.outDir}`;
|
|
67270
|
+
}
|
|
67271
|
+
if (arming.problems.length === 0) return null;
|
|
67272
|
+
return `[dev-driver] not armed: ${arming.problems.join("; ")}`;
|
|
67273
|
+
}
|
|
66368
67274
|
class StartupRollback {
|
|
66369
67275
|
owners = [];
|
|
66370
67276
|
add(cleanup) {
|
|
@@ -66460,7 +67366,14 @@ const BROWSER_IPC_CHANNELS = [
|
|
|
66460
67366
|
"browser-reveal-downloads",
|
|
66461
67367
|
/** The user's own recovery click on the `unavailable` state (round 1, D1a).
|
|
66462
67368
|
* Named here so the namespace stays the one place that lists its channels. */
|
|
66463
|
-
"browser-retry"
|
|
67369
|
+
"browser-retry",
|
|
67370
|
+
/**
|
|
67371
|
+
* S1's probe-only channel. Listed here for unregistration only: the handler
|
|
67372
|
+
* below is registered only when the launch gate passed, and this entry makes
|
|
67373
|
+
* `unregisterBrowserIpc` remove it on a stop/retry like every other channel
|
|
67374
|
+
* (removing an unregistered handler is a no-op).
|
|
67375
|
+
*/
|
|
67376
|
+
DEV_DRIVER_ADDRESS_OVERLAY
|
|
66464
67377
|
];
|
|
66465
67378
|
function registerBrowserIpc(options) {
|
|
66466
67379
|
function authorizeSender(event) {
|
|
@@ -66706,6 +67619,23 @@ function registerBrowserIpc(options) {
|
|
|
66706
67619
|
await options.retry();
|
|
66707
67620
|
return { retried: true };
|
|
66708
67621
|
});
|
|
67622
|
+
if (options.addressOverlayProbe) {
|
|
67623
|
+
electron.ipcMain.handle(DEV_DRIVER_ADDRESS_OVERLAY, (event, action) => {
|
|
67624
|
+
authorizeSender(event);
|
|
67625
|
+
if (action !== "show" && action !== "hide" && action !== "facts") {
|
|
67626
|
+
throw new Error(
|
|
67627
|
+
"address_overlay_invalid_action: expected 'show', 'hide' or 'facts'."
|
|
67628
|
+
);
|
|
67629
|
+
}
|
|
67630
|
+
const probe = options.addressOverlayProbe;
|
|
67631
|
+
if (!probe) {
|
|
67632
|
+
throw new Error(
|
|
67633
|
+
"address_overlay_unavailable: the overlay probe is not running."
|
|
67634
|
+
);
|
|
67635
|
+
}
|
|
67636
|
+
return probe(action);
|
|
67637
|
+
});
|
|
67638
|
+
}
|
|
66709
67639
|
}
|
|
66710
67640
|
function unregisterBrowserIpc() {
|
|
66711
67641
|
for (const channel of BROWSER_IPC_CHANNELS) electron.ipcMain.removeHandler(channel);
|
|
@@ -68683,6 +69613,22 @@ function startBrowserHost(options) {
|
|
|
68683
69613
|
await startBrowserHost(options).catch(() => {
|
|
68684
69614
|
});
|
|
68685
69615
|
},
|
|
69616
|
+
/*
|
|
69617
|
+
* S1's probe channel is registered ONLY when this launch's gate passed, and
|
|
69618
|
+
* then it reads the current attempt's callback through `bindings` (a retry
|
|
69619
|
+
* replaces it) rather than capturing a controller here.
|
|
69620
|
+
*/
|
|
69621
|
+
...options.addressOverlay?.enabled ? {
|
|
69622
|
+
addressOverlayProbe: (action) => {
|
|
69623
|
+
const probe = bindings.addressOverlayProbe;
|
|
69624
|
+
if (!probe) {
|
|
69625
|
+
throw new Error(
|
|
69626
|
+
"address_overlay_unavailable: the overlay controller is not running."
|
|
69627
|
+
);
|
|
69628
|
+
}
|
|
69629
|
+
return probe(action);
|
|
69630
|
+
}
|
|
69631
|
+
} : {},
|
|
68686
69632
|
log: options.log
|
|
68687
69633
|
});
|
|
68688
69634
|
starting = startWithRetries({
|
|
@@ -68719,6 +69665,7 @@ async function initializeBrowserHost(options, bindings) {
|
|
|
68719
69665
|
};
|
|
68720
69666
|
try {
|
|
68721
69667
|
let releaseTab = function(tabId, webContentsId) {
|
|
69668
|
+
addressOverlay?.onTabReleased(tabId);
|
|
68722
69669
|
const view = views.get(tabId);
|
|
68723
69670
|
views.delete(tabId);
|
|
68724
69671
|
downloads.forget(tabId);
|
|
@@ -68870,6 +69817,9 @@ async function initializeBrowserHost(options, bindings) {
|
|
|
68870
69817
|
});
|
|
68871
69818
|
contents.on("did-stop-loading", notifyChrome);
|
|
68872
69819
|
contents.on("page-title-updated", notifyChrome);
|
|
69820
|
+
contents.on("render-process-gone", () => {
|
|
69821
|
+
addressOverlay?.onPageGone(tabId);
|
|
69822
|
+
});
|
|
68873
69823
|
contents.on(
|
|
68874
69824
|
"did-fail-load",
|
|
68875
69825
|
(_event, code, description, url, isMainFrame) => {
|
|
@@ -69064,6 +70014,15 @@ async function initializeBrowserHost(options, bindings) {
|
|
|
69064
70014
|
const views = /* @__PURE__ */ new Map();
|
|
69065
70015
|
const releases = /* @__PURE__ */ new Set();
|
|
69066
70016
|
let stateWriter = null;
|
|
70017
|
+
const addressOverlay = options.addressOverlay?.enabled === true ? new AddressOverlayController({
|
|
70018
|
+
window: options.window,
|
|
70019
|
+
documentUrl: options.addressOverlay.documentUrl,
|
|
70020
|
+
log: log2,
|
|
70021
|
+
appMetrics: () => electron.app.getAppMetrics().map((metric) => ({
|
|
70022
|
+
pid: metric.pid,
|
|
70023
|
+
type: metric.type
|
|
70024
|
+
}))
|
|
70025
|
+
}) : null;
|
|
69067
70026
|
const sessionStore = new BrowserSessionStore({
|
|
69068
70027
|
dir: path$1.join(options.userDataDir, "browser"),
|
|
69069
70028
|
log: log2
|
|
@@ -69104,7 +70063,9 @@ async function initializeBrowserHost(options, bindings) {
|
|
|
69104
70063
|
};
|
|
69105
70064
|
const notifyChanged = () => {
|
|
69106
70065
|
stateWriter?.publishNow();
|
|
69107
|
-
options.window.webContents.
|
|
70066
|
+
if (!options.window.isDestroyed() && !options.window.webContents.isDestroyed()) {
|
|
70067
|
+
options.window.webContents.send("browser-state-changed");
|
|
70068
|
+
}
|
|
69108
70069
|
captureSession();
|
|
69109
70070
|
};
|
|
69110
70071
|
const registry = new TabRegistry(
|
|
@@ -69115,7 +70076,8 @@ async function initializeBrowserHost(options, bindings) {
|
|
|
69115
70076
|
return view;
|
|
69116
70077
|
},
|
|
69117
70078
|
releaseTab,
|
|
69118
|
-
notifyChanged
|
|
70079
|
+
notifyChanged,
|
|
70080
|
+
(snapshot2) => addressOverlay?.onLayout(snapshot2)
|
|
69119
70081
|
);
|
|
69120
70082
|
registryForDownloads = registry;
|
|
69121
70083
|
rollback.add(async () => {
|
|
@@ -69124,6 +70086,7 @@ async function initializeBrowserHost(options, bindings) {
|
|
|
69124
70086
|
registry.destroyAll();
|
|
69125
70087
|
await Promise.allSettled([...releases]);
|
|
69126
70088
|
});
|
|
70089
|
+
rollback.add(() => addressOverlay?.dispose("startup-rollback"));
|
|
69127
70090
|
const ownership = new OwnershipLedger({
|
|
69128
70091
|
mayAdopt: (token, requester) => {
|
|
69129
70092
|
const record = registry.requireSurface(token);
|
|
@@ -69150,7 +70113,9 @@ async function initializeBrowserHost(options, bindings) {
|
|
|
69150
70113
|
const approvals = new ApprovalStore({
|
|
69151
70114
|
dir: path$1.join(options.userDataDir, "browser"),
|
|
69152
70115
|
onChanged: () => {
|
|
69153
|
-
options.window.webContents.
|
|
70116
|
+
if (!options.window.isDestroyed() && !options.window.webContents.isDestroyed()) {
|
|
70117
|
+
options.window.webContents.send("browser-consent-changed");
|
|
70118
|
+
}
|
|
69154
70119
|
consentNotifier.announce(approvals.pendingEntries());
|
|
69155
70120
|
},
|
|
69156
70121
|
log: log2
|
|
@@ -69232,6 +70197,7 @@ async function initializeBrowserHost(options, bindings) {
|
|
|
69232
70197
|
host.clearPageFocus();
|
|
69233
70198
|
};
|
|
69234
70199
|
const resetMenuShortcutSuppression = () => {
|
|
70200
|
+
if (options.window.isDestroyed()) return;
|
|
69235
70201
|
if (!options.window.webContents.isDestroyed())
|
|
69236
70202
|
options.window.webContents.setIgnoreMenuShortcuts(false);
|
|
69237
70203
|
};
|
|
@@ -69249,6 +70215,7 @@ async function initializeBrowserHost(options, bindings) {
|
|
|
69249
70215
|
options.window.webContents.on("render-process-gone", resetChordFocus);
|
|
69250
70216
|
const detachChords = () => {
|
|
69251
70217
|
host.clearChordState();
|
|
70218
|
+
if (options.window.isDestroyed()) return;
|
|
69252
70219
|
options.window.webContents.removeListener(
|
|
69253
70220
|
"before-input-event",
|
|
69254
70221
|
onChromeInput
|
|
@@ -69358,6 +70325,25 @@ async function initializeBrowserHost(options, bindings) {
|
|
|
69358
70325
|
);
|
|
69359
70326
|
rollback.add(() => stateWriter?.clear());
|
|
69360
70327
|
stateWriter.start(server.port, sessionKey);
|
|
70328
|
+
const probeAddressOverlay = async (action) => {
|
|
70329
|
+
if (!addressOverlay) {
|
|
70330
|
+
throw new Error(
|
|
70331
|
+
"address_overlay_unavailable: this host owns no controller."
|
|
70332
|
+
);
|
|
70333
|
+
}
|
|
70334
|
+
const facts2 = await addressOverlay.probe(action);
|
|
70335
|
+
const record = registry.activeTab;
|
|
70336
|
+
const page = record ? {
|
|
70337
|
+
tabId: record.tabId,
|
|
70338
|
+
presented: record.presented,
|
|
70339
|
+
bounds: record.view.getBounds?.() ?? null,
|
|
70340
|
+
visible: record.view.getVisible?.() ?? false
|
|
70341
|
+
} : null;
|
|
70342
|
+
return { ...facts2, page };
|
|
70343
|
+
};
|
|
70344
|
+
if (addressOverlay) {
|
|
70345
|
+
bindings.addressOverlayProbe = probeAddressOverlay;
|
|
70346
|
+
}
|
|
69361
70347
|
Object.assign(bindings, {
|
|
69362
70348
|
window: () => options.window,
|
|
69363
70349
|
expectedUrl: options.expectedUrl,
|
|
@@ -69387,6 +70373,7 @@ async function initializeBrowserHost(options, bindings) {
|
|
|
69387
70373
|
profileDir,
|
|
69388
70374
|
agentTabs: () => registry.agentTabCount(),
|
|
69389
70375
|
sessionCookies: () => restoreReport,
|
|
70376
|
+
...addressOverlay ? { addressOverlay: probeAddressOverlay } : {},
|
|
69390
70377
|
stop: async () => {
|
|
69391
70378
|
detachChords();
|
|
69392
70379
|
const atStop = captureTabs(
|
|
@@ -69401,6 +70388,7 @@ async function initializeBrowserHost(options, bindings) {
|
|
|
69401
70388
|
);
|
|
69402
70389
|
}
|
|
69403
70390
|
sessionStore.flush();
|
|
70391
|
+
addressOverlay?.dispose("host-stop");
|
|
69404
70392
|
registry.destroyAll();
|
|
69405
70393
|
await Promise.allSettled([...releases]);
|
|
69406
70394
|
await cdp.close();
|
|
@@ -70419,57 +71407,6 @@ class DesktopNotifier {
|
|
|
70419
71407
|
notification.show();
|
|
70420
71408
|
}
|
|
70421
71409
|
}
|
|
70422
|
-
const DEV_DRIVER_ENV = "LOCAL_OPERATOR_UI_DEV_DRIVER";
|
|
70423
|
-
const DEV_DRIVER_OUT_ENV = "LOCAL_OPERATOR_UI_DEV_DRIVER_OUT";
|
|
70424
|
-
const DEV_DRIVER_ARG = "--lo-dev-driver";
|
|
70425
|
-
const DEV_DRIVER_CAPTURE = "dev-driver-capture";
|
|
70426
|
-
const DEV_DRIVER_FACTS = "dev-driver-facts";
|
|
70427
|
-
const TRUTHY = /* @__PURE__ */ new Set(["1", "true"]);
|
|
70428
|
-
function readOptIn(env) {
|
|
70429
|
-
const raw = env[DEV_DRIVER_ENV];
|
|
70430
|
-
if (raw === void 0 || raw.trim() === "")
|
|
70431
|
-
return { asked: false, value: null };
|
|
70432
|
-
return { asked: true, value: raw.trim() };
|
|
70433
|
-
}
|
|
70434
|
-
function resolveDevDriverArming(input) {
|
|
70435
|
-
const off = (problems = []) => ({
|
|
70436
|
-
armed: false,
|
|
70437
|
-
outDir: null,
|
|
70438
|
-
problems
|
|
70439
|
-
});
|
|
70440
|
-
const optIn = readOptIn(input.env);
|
|
70441
|
-
if (!optIn.asked) return off();
|
|
70442
|
-
if (!TRUTHY.has(optIn.value.toLowerCase())) {
|
|
70443
|
-
return off([
|
|
70444
|
-
`${DEV_DRIVER_ENV}=${optIn.value} is not an opt-in (accepted: 1, true); the renderer dev driver stayed off`
|
|
70445
|
-
]);
|
|
70446
|
-
}
|
|
70447
|
-
if (input.windowMode !== "headless" && input.windowMode !== "inactive") {
|
|
70448
|
-
return off([
|
|
70449
|
-
`the renderer dev driver refused to arm in a "${input.windowMode}" window; it never raises one, so use --window-mode=headless (or inactive)`
|
|
70450
|
-
]);
|
|
70451
|
-
}
|
|
70452
|
-
const outDir = input.env[DEV_DRIVER_OUT_ENV]?.trim() ?? "";
|
|
70453
|
-
if (outDir === "" || !outDir.startsWith("/")) {
|
|
70454
|
-
return off([
|
|
70455
|
-
`${DEV_DRIVER_ENV} was set but ${DEV_DRIVER_OUT_ENV} is ${outDir === "" ? "missing" : `"${outDir}"`}; an absolute frames directory is required, so the driver did not arm`
|
|
70456
|
-
]);
|
|
70457
|
-
}
|
|
70458
|
-
return { armed: true, outDir, problems: [] };
|
|
70459
|
-
}
|
|
70460
|
-
function headlessExerciserAllowed(input) {
|
|
70461
|
-
return input.arming.armed && input.windowMode === "headless";
|
|
70462
|
-
}
|
|
70463
|
-
function devDriverArgument(outDir) {
|
|
70464
|
-
return `${DEV_DRIVER_ARG}=${outDir}`;
|
|
70465
|
-
}
|
|
70466
|
-
function describeDevDriverArming(arming) {
|
|
70467
|
-
if (arming.armed) {
|
|
70468
|
-
return `[dev-driver] ARMED; frames are written to ${arming.outDir}`;
|
|
70469
|
-
}
|
|
70470
|
-
if (arming.problems.length === 0) return null;
|
|
70471
|
-
return `[dev-driver] not armed: ${arming.problems.join("; ")}`;
|
|
70472
|
-
}
|
|
70473
71410
|
const FRAME_LABEL = /^[a-z0-9][a-z0-9_-]{0,63}$/;
|
|
70474
71411
|
function registerDevDriverIPC(options) {
|
|
70475
71412
|
const { window, expectedUrl, outDir, identity: identity2 } = options;
|
|
@@ -80764,6 +81701,16 @@ const devDriverArming = resolveDevDriverArming({
|
|
|
80764
81701
|
});
|
|
80765
81702
|
const devDriverLine = describeDevDriverArming(devDriverArming);
|
|
80766
81703
|
if (devDriverLine) console.log(devDriverLine);
|
|
81704
|
+
const addressOverlayGate = resolveAddressOverlayGate({
|
|
81705
|
+
env: launchEnv,
|
|
81706
|
+
devDriverArmed: devDriverArming.armed,
|
|
81707
|
+
windowMode: windowLaunch.mode
|
|
81708
|
+
});
|
|
81709
|
+
if (addressOverlayGate.asked) {
|
|
81710
|
+
console.log(
|
|
81711
|
+
addressOverlayGate.enabled ? "[address-overlay] ARMED (S1 probe: native child, no product path)" : `[address-overlay] not armed: ${addressOverlayGate.reason}`
|
|
81712
|
+
);
|
|
81713
|
+
}
|
|
80767
81714
|
const devDriverWebPreferences = devDriverArming.armed && devDriverArming.outDir ? { additionalArguments: [devDriverArgument(devDriverArming.outDir)] } : {};
|
|
80768
81715
|
const telemetryWebPreferences = {
|
|
80769
81716
|
additionalArguments: [telemetryArgument(telemetryLaunch.enabled)]
|
|
@@ -81167,6 +82114,7 @@ electron.app.whenReady().then(async () => {
|
|
|
81167
82114
|
});
|
|
81168
82115
|
const rendererUrl = rendererDocumentUrl();
|
|
81169
82116
|
const consoleCaptureUrl = consoleCaptureUrlFor(rendererUrl);
|
|
82117
|
+
const addressOverlayDocumentUrl = addressOverlayDocumentUrlFor(rendererUrl);
|
|
81170
82118
|
backendService.observeDesktopFeed(
|
|
81171
82119
|
(frame) => {
|
|
81172
82120
|
if (frame.type === "notification") {
|
|
@@ -81975,6 +82923,14 @@ electron.app.whenReady().then(async () => {
|
|
|
81975
82923
|
// document, and the preload every renderer in this app gets, which is what
|
|
81976
82924
|
// lets main feed the reconstruction to it.
|
|
81977
82925
|
consoleCaptureUrl,
|
|
82926
|
+
// S1: only a gated headless probe arm gets this option at all. The
|
|
82927
|
+
// URL is this app's own packaged document, not a caller's string.
|
|
82928
|
+
...addressOverlayGate.enabled ? {
|
|
82929
|
+
addressOverlay: {
|
|
82930
|
+
enabled: true,
|
|
82931
|
+
documentUrl: addressOverlayDocumentUrl
|
|
82932
|
+
}
|
|
82933
|
+
} : {},
|
|
81978
82934
|
preloadPath: path$1.join(__dirname, "../preload/index.js"),
|
|
81979
82935
|
/*
|
|
81980
82936
|
* The console's surfaces are handed the user's own PATH, from the same
|