local-operator-ui 0.34.44 → 0.34.46
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 +1051 -66
- package/out/preload/index.js +305 -18
- package/out/renderer/assets/{_basePickBy-C-GwcPo5.js → _basePickBy-hPi3fEQr.js} +1 -1
- package/out/renderer/assets/{_baseUniq-whkmDW6w.js → _baseUniq-BH6SqqsG.js} +1 -1
- package/out/renderer/assets/{agent-details-page-DpCpkTfN.js → agent-details-page-D6Sf3QUC.js} +2 -2
- package/out/renderer/assets/agent-hub-page-geh3R5Uy.js +11 -0
- package/out/renderer/assets/agents-page-CFjl9C1o.js +7 -0
- package/out/renderer/assets/arc-hK5DqZTp.js +1 -0
- package/out/renderer/assets/architectureDiagram-IEHRJDOE-Od2Y7WJh.js +36 -0
- package/out/renderer/assets/{blockDiagram-JOT3LUYC-Dp4G8uLX.js → blockDiagram-JOT3LUYC-Ctc7-wAT.js} +6 -6
- package/out/renderer/assets/{book-open-C9onOH1C.js → book-open-BWUyDXVa.js} +1 -1
- package/out/renderer/assets/browser-page-KrEaCKVz.js +1 -0
- package/out/renderer/assets/browser-webauthn-prompt-CKqDqDU5.js +1 -0
- package/out/renderer/assets/{c4Diagram-VJAJSXHY-CnX5ELGv.js → c4Diagram-VJAJSXHY-KjhfyGml.js} +1 -1
- package/out/renderer/assets/channel-Bs-Xt2ih.js +1 -0
- package/out/renderer/assets/{chunk-4BMEZGHF-DYgqjjvg.js → chunk-4BMEZGHF-DUs-A7ex.js} +1 -1
- package/out/renderer/assets/{chunk-A2AXSNBT-3DoU7E6Y.js → chunk-A2AXSNBT-LbRRk1xd.js} +1 -1
- package/out/renderer/assets/{chunk-AEK57VVT-OX8UcnIV.js → chunk-AEK57VVT-Ddc0Dk4L.js} +1 -1
- package/out/renderer/assets/{chunk-D6G4REZN-Dbt1r37J.js → chunk-D6G4REZN-Cj8PtGTg.js} +1 -1
- package/out/renderer/assets/{chunk-RZ5BOZE2-CdLKa5S8.js → chunk-RZ5BOZE2-KXGjmJKN.js} +1 -1
- package/out/renderer/assets/{chunk-XZIHB7SX-B_CjCOio.js → chunk-XZIHB7SX-B8dmznR7.js} +1 -1
- package/out/renderer/assets/classDiagram-GIVACNV2-BrkzW__m.js +1 -0
- package/out/renderer/assets/classDiagram-v2-COTLJTTW-BrkzW__m.js +1 -0
- package/out/renderer/assets/clone-CnlBeott.js +1 -0
- package/out/renderer/assets/{console-mirror-D1YYJxrt.js → console-mirror-cPzOwzR9.js} +14 -14
- package/out/renderer/assets/consoleCapture-ComgYGzq.js +1 -0
- package/out/renderer/assets/{conversation-input-sync-BbbcfWqh.js → conversation-input-sync-B5HfvhyR.js} +259 -261
- package/out/renderer/assets/dagre-OKDRZEBW-BaeP_npI.js +4 -0
- package/out/renderer/assets/diagram-SSKATNLV-BDwSJBgs.js +43 -0
- package/out/renderer/assets/diagram-VNBRO52H-Ce2_qnEd.js +24 -0
- package/out/renderer/assets/{erDiagram-Q7BY3M3F-Cs4yDA7g.js → erDiagram-Q7BY3M3F-DUpyMDtK.js} +1 -1
- package/out/renderer/assets/{error-boundary-YxH9ow-2.js → error-boundary-B4K6A3dS.js} +2 -2
- package/out/renderer/assets/{flowDiagram-4HSFHLVR-BofJ9_8f.js → flowDiagram-4HSFHLVR-Twa-e-xh.js} +1 -1
- package/out/renderer/assets/ganttDiagram-APWFNJXF-6IcdZzTN.js +257 -0
- package/out/renderer/assets/gitGraphDiagram-7IBYFJ6S-BHwjqSB2.js +65 -0
- package/out/renderer/assets/{graph-D3WT1lJS.js → graph-CjSBt2SL.js} +1 -1
- package/out/renderer/assets/index-BDqI882o.js +7 -0
- package/out/renderer/assets/index-C7mMgpwT.css +1 -0
- package/out/renderer/assets/index-fKRRIb8a.js +1 -0
- package/out/renderer/assets/index-o-e57W52.js +804 -0
- package/out/renderer/assets/infoDiagram-PH2N3AL5-DusuxGWy.js +2 -0
- package/out/renderer/assets/{installer-BzSW3GXd.js → installer-B4Bd2pBF.js} +1 -1
- package/out/renderer/assets/{journeyDiagram-U35MCT3I-DVmD515J.js → journeyDiagram-U35MCT3I-ouPHBWbW.js} +1 -1
- package/out/renderer/assets/{kanban-definition-NDS4AKOZ-DpiJ7P3i.js → kanban-definition-NDS4AKOZ-BpfzQ_cF.js} +1 -1
- package/out/renderer/assets/{layout-BFA2wwh_.js → layout-DWM2xDwq.js} +1 -1
- package/out/renderer/assets/legacy-agents-page-DMWtT-nK.js +33 -0
- package/out/renderer/assets/{mermaid.core-C7iGmYcY.js → mermaid.core-C2AhDEdD.js} +5 -5
- package/out/renderer/assets/mesh-page-DI_FXBTf.js +1 -0
- package/out/renderer/assets/messages-Bf6oXWsi.js +3 -0
- package/out/renderer/assets/mindmap-definition-ALO5MXBD-CWFoHd9r.js +95 -0
- package/out/renderer/assets/mini-BVxX6iDv.js +1 -0
- package/out/renderer/assets/{notebook-pen-rCh1XFso.js → notebook-pen-CKFoYavJ.js} +1 -1
- package/out/renderer/assets/org-access-Cj7MYYx3.js +1 -0
- package/out/renderer/assets/org-surface-gate-B61_V5sH.js +1 -0
- package/out/renderer/assets/{page-header-DWR3DkBt.js → page-header-D90TvAM5.js} +1 -1
- package/out/renderer/assets/pieDiagram-IB7DONF6-C4p49jAq.js +30 -0
- package/out/renderer/assets/projects-page-D0OgNUWf.js +45 -0
- package/out/renderer/assets/publication-validation-DLHcjuJy.js +1 -0
- package/out/renderer/assets/{quadrantDiagram-7GDLP6J5-u3qKyomE.js → quadrantDiagram-7GDLP6J5-By3GJSI3.js} +1 -1
- package/out/renderer/assets/{radar-MK3ICKWK-DTXBXOd-.js → radar-MK3ICKWK-n8dqb_zt.js} +1 -1
- package/out/renderer/assets/radient-auth-buttons-p_Axd8pX.js +1 -0
- package/out/renderer/assets/{requirementDiagram-KVF5MWMF-CIyOJzHO.js → requirementDiagram-KVF5MWMF-CQ7JllrS.js} +1 -1
- package/out/renderer/assets/sankeyDiagram-QLVOVGJD-DNyPn5zx.js +10 -0
- package/out/renderer/assets/{schedules-page-DHwzeRvF.js → schedules-page-R7SXiFmi.js} +1 -1
- package/out/renderer/assets/{sequenceDiagram-X6HHIX6F-DCj3Ke6W.js → sequenceDiagram-X6HHIX6F-CUHeYZkr.js} +1 -1
- package/out/renderer/assets/{settings-page-Br0K0YLW.js → settings-page-BZ_HPCkT.js} +60 -60
- package/out/renderer/assets/stateDiagram-DGXRK772-CL_twVvQ.js +1 -0
- package/out/renderer/assets/stateDiagram-v2-YXO3MK2T-ruz5Lapk.js +1 -0
- package/out/renderer/assets/{timeline-definition-BDJGKUSR-C4cCAtD2.js → timeline-definition-BDJGKUSR-BCcBGH9R.js} +1 -1
- package/out/renderer/assets/{use-download-agent-mutation-CRmN4Z4O.js → use-download-agent-mutation-B87MG4sW.js} +4 -4
- package/out/renderer/assets/use-memberships-query-DCEm9yOI.js +1 -0
- package/out/renderer/assets/{use-session-snapshot-DZAAvDEa.js → use-session-snapshot-CChKOZqb.js} +1 -1
- package/out/renderer/assets/{xychartDiagram-VJFVF3MP-DG9g8Bz_.js → xychartDiagram-VJFVF3MP-CvHda-UX.js} +1 -1
- 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/agent-hub-page-CUIy_Kx2.js +0 -11
- package/out/renderer/assets/agents-page-2HbuAEbx.js +0 -7
- package/out/renderer/assets/arc-DDs-mKBJ.js +0 -1
- package/out/renderer/assets/architectureDiagram-IEHRJDOE-CPUUDGvU.js +0 -36
- package/out/renderer/assets/browser-page-DYIlDoNt.js +0 -1
- package/out/renderer/assets/browser-webauthn-prompt-BCVHqXb0.js +0 -1
- package/out/renderer/assets/channel-DMF6TPjP.js +0 -1
- package/out/renderer/assets/classDiagram-GIVACNV2-B0EbOHV0.js +0 -1
- package/out/renderer/assets/classDiagram-v2-COTLJTTW-B0EbOHV0.js +0 -1
- package/out/renderer/assets/clone-D1pjaXDr.js +0 -1
- package/out/renderer/assets/consoleCapture-B-w56zDU.js +0 -1
- package/out/renderer/assets/dagre-OKDRZEBW-Di-XleTu.js +0 -4
- package/out/renderer/assets/diagram-SSKATNLV-HX5Tirdq.js +0 -43
- package/out/renderer/assets/diagram-VNBRO52H-BkGCdAFk.js +0 -24
- package/out/renderer/assets/ganttDiagram-APWFNJXF-B8-HoTDC.js +0 -257
- package/out/renderer/assets/gitGraphDiagram-7IBYFJ6S-B72gxYgp.js +0 -65
- package/out/renderer/assets/index-B7VSZn2a.css +0 -1
- package/out/renderer/assets/index-Bo-U0L08.js +0 -804
- package/out/renderer/assets/index-BwwNZ8BB.js +0 -1
- package/out/renderer/assets/index-StPsU3lP.js +0 -7
- package/out/renderer/assets/infoDiagram-PH2N3AL5-ChbJv-y5.js +0 -2
- package/out/renderer/assets/legacy-agents-page-C_w_SC0A.js +0 -33
- package/out/renderer/assets/mesh-page-DMSyd0cL.js +0 -1
- package/out/renderer/assets/mindmap-definition-ALO5MXBD-FgYmOkcR.js +0 -95
- package/out/renderer/assets/mini-B9yZoGaU.js +0 -1
- package/out/renderer/assets/org-surface-gate-CDIyXoCz.js +0 -1
- package/out/renderer/assets/pieDiagram-IB7DONF6-Ahxca-lE.js +0 -30
- package/out/renderer/assets/projects-page-BclfcCc4.js +0 -50
- package/out/renderer/assets/radient-auth-buttons-D6EcW_pf.js +0 -1
- package/out/renderer/assets/sankeyDiagram-QLVOVGJD-DPL4XBFG.js +0 -10
- package/out/renderer/assets/stateDiagram-DGXRK772-C_ILyKXn.js +0 -1
- package/out/renderer/assets/stateDiagram-v2-YXO3MK2T-DgnGm7tu.js +0 -1
- package/out/renderer/assets/ui-preferences-store-lljzccwU.js +0 -1
- package/out/renderer/assets/use-memberships-query-DIOIcGCQ.js +0 -1
- /package/out/renderer/assets/{index-CzjIMcYW.js → index-B-uibf5k.js} +0 -0
package/out/main/index.js
CHANGED
|
@@ -92,6 +92,7 @@ const mcpCatalogCwdPattern = /^(\/|[A-Za-z]:[\\/])/;
|
|
|
92
92
|
const mcpCatalogCwd = zod.z.string().min(1).max(4096).regex(mcpCatalogCwdPattern);
|
|
93
93
|
const SUBSCRIPTION_ID_PATTERN = /^[a-f0-9]{32}$/;
|
|
94
94
|
const requestId = zod.z.string().regex(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/);
|
|
95
|
+
const definitionRevision = zod.z.string().min(1).max(512).nullish();
|
|
95
96
|
const meshId = zod.z.string().regex(/^[A-Za-z0-9_-]{1,128}$/);
|
|
96
97
|
const approvalId = zod.z.string().regex(/^ap_[0-9a-hjkmnp-tv-z]{1,64}$/);
|
|
97
98
|
const sessionImage = zod.z.object({
|
|
@@ -262,6 +263,12 @@ const publicationDescription = zod.z.string().refine((description) => publicatio
|
|
|
262
263
|
const publicationTools = zod.z.array(zod.z.string()).refine((tools) => publicationToolsRule(tools) === null, {
|
|
263
264
|
message: "That tool list cannot be published."
|
|
264
265
|
});
|
|
266
|
+
const publicationPolicyFields = {
|
|
267
|
+
requestId: requestId.optional(),
|
|
268
|
+
subscribe: zod.z.boolean().optional(),
|
|
269
|
+
autoPush: zod.z.boolean().optional(),
|
|
270
|
+
confirmPublicEgress: zod.z.boolean().optional()
|
|
271
|
+
};
|
|
265
272
|
const publicationDocument = zod.z.object({
|
|
266
273
|
name: publicationName,
|
|
267
274
|
description: publicationDescription,
|
|
@@ -325,6 +332,21 @@ const desktopRequestUnion = zod.z.discriminatedUnion("op", [
|
|
|
325
332
|
zod.z.object({ op: zod.z.literal("runtimes.list") }).strict(),
|
|
326
333
|
zod.z.object({ op: zod.z.literal("profiles.list") }).strict(),
|
|
327
334
|
zod.z.object({ op: zod.z.literal("profiles.get"), name: profileName }).strict(),
|
|
335
|
+
/*
|
|
336
|
+
* Definition CAS (proposed additive wire, b-wire-receipt-definition-cas-and-adopt).
|
|
337
|
+
* `expectedDefinitionRevision` is an opaque echo of the `definition_revision` the
|
|
338
|
+
* editor was opened with; absent/null is the LEGACY unconditional write and is
|
|
339
|
+
* NOT a protected dirty-edit guarantee, so a caller that wants CAS protection
|
|
340
|
+
* must send it. Strict like every field here: a typo must 400, not silently
|
|
341
|
+
* become an unconditional write.
|
|
342
|
+
*/
|
|
343
|
+
zod.z.object({
|
|
344
|
+
op: zod.z.literal("profiles.update"),
|
|
345
|
+
name: profileName,
|
|
346
|
+
requestId,
|
|
347
|
+
fields: profileFields,
|
|
348
|
+
expectedDefinitionRevision: definitionRevision.optional()
|
|
349
|
+
}).strict(),
|
|
328
350
|
zod.z.object({ op: zod.z.literal("profiles.install"), name: profileName, requestId }).strict(),
|
|
329
351
|
zod.z.object({
|
|
330
352
|
op: zod.z.literal("profiles.create"),
|
|
@@ -335,12 +357,6 @@ const desktopRequestUnion = zod.z.discriminatedUnion("op", [
|
|
|
335
357
|
instructions: zod.z.string().min(1).max(8e3)
|
|
336
358
|
})
|
|
337
359
|
}).strict(),
|
|
338
|
-
zod.z.object({
|
|
339
|
-
op: zod.z.literal("profiles.update"),
|
|
340
|
-
name: profileName,
|
|
341
|
-
requestId,
|
|
342
|
-
fields: profileFields
|
|
343
|
-
}).strict(),
|
|
344
360
|
/*
|
|
345
361
|
* THE HUB AUTO-UPDATE PLANE (backend `server/routes/desktop_hub.py`, gated by
|
|
346
362
|
* the `hub_updates` capability). `hub.updates` is a STORE READ on the backend
|
|
@@ -356,20 +372,83 @@ const desktopRequestUnion = zod.z.discriminatedUnion("op", [
|
|
|
356
372
|
* apply-all schema does not offer it.
|
|
357
373
|
*/
|
|
358
374
|
zod.z.object({ op: zod.z.literal("hub.updates") }).strict(),
|
|
375
|
+
// Initial skill publication uses an actual discovered source and managed
|
|
376
|
+
// alias, never a synthetic link ID or a private-directory clone.
|
|
377
|
+
zod.z.object({
|
|
378
|
+
op: zod.z.literal("hub.skillPull"),
|
|
379
|
+
requestId,
|
|
380
|
+
hubId: id$1,
|
|
381
|
+
hubSource: zod.z.string().min(1).max(2048),
|
|
382
|
+
visibility: zod.z.enum(["public", "org"]),
|
|
383
|
+
tenantId: id$1.nullable(),
|
|
384
|
+
localAlias: profileName,
|
|
385
|
+
subscribe: zod.z.boolean().optional(),
|
|
386
|
+
autoPush: zod.z.boolean().optional(),
|
|
387
|
+
confirmPublicEgress: zod.z.boolean().optional()
|
|
388
|
+
}).strict(),
|
|
389
|
+
zod.z.object({
|
|
390
|
+
op: zod.z.literal("hub.skillPublish"),
|
|
391
|
+
requestId,
|
|
392
|
+
dryRun: zod.z.boolean(),
|
|
393
|
+
sourceSkill: profileName,
|
|
394
|
+
localAlias: profileName,
|
|
395
|
+
visibility: zod.z.enum(["public", "org"]),
|
|
396
|
+
tenantId: id$1.nullable(),
|
|
397
|
+
subscribe: zod.z.boolean(),
|
|
398
|
+
autoPush: zod.z.boolean(),
|
|
399
|
+
confirmPublicEgress: zod.z.boolean(),
|
|
400
|
+
previewReceipt: zod.z.string().min(1).max(4096).optional(),
|
|
401
|
+
confirmPublish: zod.z.literal(true).optional()
|
|
402
|
+
}).strict(),
|
|
403
|
+
// Full inventory is additive: old callers still receive pending agents/teams
|
|
404
|
+
// only. Policy revision is required even for a single independent toggle so
|
|
405
|
+
// an intervening direct config edit cannot be silently overwritten.
|
|
406
|
+
zod.z.object({
|
|
407
|
+
op: zod.z.literal("hub.links"),
|
|
408
|
+
kind: zod.z.enum(["agent", "team", "skill"]).optional()
|
|
409
|
+
}).strict(),
|
|
410
|
+
zod.z.object({
|
|
411
|
+
op: zod.z.literal("hub.policy"),
|
|
412
|
+
requestId,
|
|
413
|
+
linkId: zod.z.string().min(1).max(256),
|
|
414
|
+
expectedPolicyRevision: zod.z.string().min(1).max(256),
|
|
415
|
+
subscribe: zod.z.boolean().optional(),
|
|
416
|
+
autoPush: zod.z.boolean().optional(),
|
|
417
|
+
confirmPublicEgress: zod.z.boolean().optional()
|
|
418
|
+
}).strict(),
|
|
359
419
|
zod.z.object({
|
|
360
420
|
op: zod.z.literal("hub.check"),
|
|
361
421
|
requestId,
|
|
422
|
+
linkId: zod.z.string().min(1).max(256).optional(),
|
|
423
|
+
direction: zod.z.enum(["pull", "push"]).optional(),
|
|
362
424
|
kind: hubItemKind.optional(),
|
|
363
425
|
name: profileName.optional()
|
|
364
426
|
}).strict(),
|
|
365
427
|
zod.z.object({
|
|
366
428
|
op: zod.z.literal("hub.apply"),
|
|
367
429
|
requestId,
|
|
368
|
-
|
|
369
|
-
|
|
430
|
+
previewReceipt: zod.z.string().min(1).max(4096).optional(),
|
|
431
|
+
confirmApply: zod.z.literal(true).optional(),
|
|
432
|
+
linkId: zod.z.string().min(1).max(256).optional(),
|
|
433
|
+
direction: zod.z.literal("pull").optional(),
|
|
434
|
+
kind: hubItemKind.optional(),
|
|
435
|
+
name: profileName.optional(),
|
|
370
436
|
prefer: zod.z.enum(["local", "remote"]).optional(),
|
|
371
437
|
acknowledgeUnknownBaseline: zod.z.boolean().optional(),
|
|
372
|
-
dryRun: zod.z.boolean().optional()
|
|
438
|
+
dryRun: zod.z.boolean().optional(),
|
|
439
|
+
/*
|
|
440
|
+
* LEGACY UNKNOWN-ORIGIN SOURCE CONFIRMATION (proposed additive wire,
|
|
441
|
+
* b-wire-receipt §Part 2). An EXPLICIT act that states a destination the
|
|
442
|
+
* caller asserts: it materializes the real baseline identity and scope,
|
|
443
|
+
* it never infers Public or the active organization. `resolve_source`
|
|
444
|
+
* selects the branch; the source/scope triple is REQUIRED with it so a
|
|
445
|
+
* half-stated destination cannot compose a guessed origin. The service
|
|
446
|
+
* refuses a conflicting known scope with `origin-conflict`.
|
|
447
|
+
*/
|
|
448
|
+
resolveSource: zod.z.literal(true).optional(),
|
|
449
|
+
hubSource: zod.z.string().min(1).max(2048).optional(),
|
|
450
|
+
visibility: zod.z.enum(["public", "org"]).optional(),
|
|
451
|
+
tenantId: zod.z.string().min(1).max(128).nullable().optional()
|
|
373
452
|
}).strict(),
|
|
374
453
|
zod.z.object({
|
|
375
454
|
op: zod.z.literal("hub.applyAll"),
|
|
@@ -379,21 +458,38 @@ const desktopRequestUnion = zod.z.discriminatedUnion("op", [
|
|
|
379
458
|
zod.z.object({
|
|
380
459
|
op: zod.z.literal("hub.retry"),
|
|
381
460
|
requestId,
|
|
382
|
-
|
|
383
|
-
|
|
461
|
+
linkId: zod.z.string().min(1).max(256).optional(),
|
|
462
|
+
direction: zod.z.enum(["pull", "push"]).optional(),
|
|
463
|
+
kind: hubItemKind.optional(),
|
|
464
|
+
name: profileName.optional()
|
|
384
465
|
}).strict(),
|
|
385
|
-
zod.z.object({ op: zod.z.literal("teams.list") }).strict(),
|
|
386
|
-
zod.z.object({ op: zod.z.literal("teams.get"), name: profileName }).strict(),
|
|
387
466
|
zod.z.object({
|
|
388
|
-
op: zod.z.literal("
|
|
467
|
+
op: zod.z.literal("hub.push"),
|
|
389
468
|
requestId,
|
|
390
|
-
|
|
469
|
+
linkId: zod.z.string().min(1).max(256),
|
|
470
|
+
direction: zod.z.literal("push"),
|
|
471
|
+
dryRun: zod.z.boolean(),
|
|
472
|
+
previewReceipt: zod.z.string().min(1).max(4096).optional(),
|
|
473
|
+
confirmPublish: zod.z.literal(true).optional()
|
|
391
474
|
}).strict(),
|
|
475
|
+
zod.z.object({ op: zod.z.literal("teams.list") }).strict(),
|
|
476
|
+
zod.z.object({ op: zod.z.literal("teams.get"), name: profileName }).strict(),
|
|
477
|
+
/*
|
|
478
|
+
* Team CAS is the same optional opaque echo as the profile arm: absent/null is
|
|
479
|
+
* the legacy unconditional write, a supplied stale/malformed value is refused
|
|
480
|
+
* 409 `local-concurrent-edit` before any write under the definition lock.
|
|
481
|
+
*/
|
|
392
482
|
zod.z.object({
|
|
393
483
|
op: zod.z.literal("teams.update"),
|
|
394
484
|
name: profileName,
|
|
395
485
|
requestId,
|
|
396
|
-
fields: teamFields
|
|
486
|
+
fields: teamFields,
|
|
487
|
+
expectedDefinitionRevision: definitionRevision.optional()
|
|
488
|
+
}).strict(),
|
|
489
|
+
zod.z.object({
|
|
490
|
+
op: zod.z.literal("teams.create"),
|
|
491
|
+
requestId,
|
|
492
|
+
fields: teamFields.extend({ name: zod.z.string().min(1).max(64) })
|
|
397
493
|
}).strict(),
|
|
398
494
|
zod.z.object({
|
|
399
495
|
op: zod.z.literal("sessions.list"),
|
|
@@ -702,6 +798,24 @@ const desktopRequestUnion = zod.z.discriminatedUnion("op", [
|
|
|
702
798
|
*/
|
|
703
799
|
peerJournalSource: zod.z.boolean().optional()
|
|
704
800
|
}).strict(),
|
|
801
|
+
// The inventory belongs to the backend, not to a renderer filesystem walk.
|
|
802
|
+
// Keep the cursor opaque: its query/revision binding is the service's decision.
|
|
803
|
+
zod.z.object({
|
|
804
|
+
op: zod.z.literal("sessions.files"),
|
|
805
|
+
sessionId,
|
|
806
|
+
scope: zod.z.enum(["family", "self"]).optional(),
|
|
807
|
+
kind: zod.z.string().max(256).optional(),
|
|
808
|
+
q: zod.z.string().max(256).optional(),
|
|
809
|
+
sort: zod.z.enum(["recent", "name", "kind", "modified", "created", "size"]).optional(),
|
|
810
|
+
order: zod.z.enum(["asc", "desc"]).optional(),
|
|
811
|
+
limit: zod.z.number().int().min(1).max(200).optional(),
|
|
812
|
+
cursor: zod.z.string().max(8192).optional()
|
|
813
|
+
}).strict(),
|
|
814
|
+
zod.z.object({
|
|
815
|
+
op: zod.z.literal("sessions.files.materialise"),
|
|
816
|
+
sessionId,
|
|
817
|
+
fileId: zod.z.string().regex(/^[a-f0-9]{16}$/)
|
|
818
|
+
}).strict(),
|
|
705
819
|
zod.z.object({
|
|
706
820
|
op: zod.z.literal("sessions.history"),
|
|
707
821
|
sessionId,
|
|
@@ -1204,6 +1318,7 @@ const desktopRequestUnion = zod.z.discriminatedUnion("op", [
|
|
|
1204
1318
|
op: zod.z.literal("agent.publish"),
|
|
1205
1319
|
agentId: id$1,
|
|
1206
1320
|
document: publicationDocument.optional(),
|
|
1321
|
+
...publicationPolicyFields,
|
|
1207
1322
|
/*
|
|
1208
1323
|
* The publication TARGET (§4.4/§4.7). Both travel together or neither does,
|
|
1209
1324
|
* and the rule is a `superRefine` on the whole UNION (below) rather than a
|
|
@@ -1235,11 +1350,20 @@ const desktopRequestUnion = zod.z.discriminatedUnion("op", [
|
|
|
1235
1350
|
// republish that did not name one would have to guess which public row to
|
|
1236
1351
|
// overwrite — and guessing here overwrites somebody's listing.
|
|
1237
1352
|
hubAgentId: id$1,
|
|
1353
|
+
expectedRemoteRevision: zod.z.string().min(1).max(512).optional(),
|
|
1238
1354
|
document: publicationDocument.optional(),
|
|
1355
|
+
...publicationPolicyFields,
|
|
1239
1356
|
/** The publication target, on the same terms as `agent.publish` above. */
|
|
1240
1357
|
visibility: zod.z.literal("org").optional(),
|
|
1241
1358
|
tenantId: id$1.optional()
|
|
1242
1359
|
}).strict(),
|
|
1360
|
+
zod.z.object({
|
|
1361
|
+
op: zod.z.literal("team.publish"),
|
|
1362
|
+
teamId: id$1,
|
|
1363
|
+
...publicationPolicyFields,
|
|
1364
|
+
visibility: zod.z.literal("org").optional(),
|
|
1365
|
+
tenantId: id$1.optional()
|
|
1366
|
+
}).strict(),
|
|
1243
1367
|
/*
|
|
1244
1368
|
* Pulling a published organization team into this machine's local registry
|
|
1245
1369
|
* (§4.5/§8.4's "list + pull action").
|
|
@@ -1837,6 +1961,8 @@ const desktopRequestUnion = zod.z.discriminatedUnion("op", [
|
|
|
1837
1961
|
"org_agents.list",
|
|
1838
1962
|
"org_team.get",
|
|
1839
1963
|
"org_teams.list",
|
|
1964
|
+
"org_skills.list",
|
|
1965
|
+
"org_skill.get",
|
|
1840
1966
|
/*
|
|
1841
1967
|
* The verification-email resend (core PR2,
|
|
1842
1968
|
* `feat/quota-notice-resend`): it maps to the upstream's JWT-only
|
|
@@ -1854,6 +1980,7 @@ const desktopRequestUnion = zod.z.discriminatedUnion("op", [
|
|
|
1854
1980
|
agent_id: id$1.optional(),
|
|
1855
1981
|
comment_id: id$1.optional(),
|
|
1856
1982
|
team_id: id$1.optional(),
|
|
1983
|
+
skill_id: id$1.optional(),
|
|
1857
1984
|
query: zod.z.record(zod.z.union([zod.z.string().max(1024), zod.z.number().int()])).optional(),
|
|
1858
1985
|
payload: zod.z.record(zod.z.unknown()).optional(),
|
|
1859
1986
|
confirmed: zod.z.boolean().optional()
|
|
@@ -1866,6 +1993,39 @@ const desktopRequestUnion = zod.z.discriminatedUnion("op", [
|
|
|
1866
1993
|
accountId: zod.z.number().int().positive(),
|
|
1867
1994
|
confirmed: zod.z.literal(true)
|
|
1868
1995
|
}).strict(),
|
|
1996
|
+
/*
|
|
1997
|
+
* PHONE ACCESS SETUP (`features.tunnel_setup`, local-operator
|
|
1998
|
+
* `docs/DESKTOP_API.md` "Explicit phone setup"). Three ops over ONE route,
|
|
1999
|
+
* split by authority so a caller cannot mutate by accident:
|
|
2000
|
+
*
|
|
2001
|
+
* - `tunnel.setup.read`: GET, local metadata only. No upstream read, no token
|
|
2002
|
+
* refresh, never `verified` and never a quote - the cheap poll that rebuilds
|
|
2003
|
+
* the block after a window close or a lost response.
|
|
2004
|
+
* - `tunnel.setup.plan`: POST `{action:"plan"}`, a FRESH account/quote/
|
|
2005
|
+
* preparation observation that changes nothing.
|
|
2006
|
+
* - `tunnel.setup.run`: POST `{action:"run"}`, the only op that can write. The
|
|
2007
|
+
* backend REFUSES it without an explicit owner (422), so `credentialId` is
|
|
2008
|
+
* required here rather than defaulted: an account is never picked for the
|
|
2009
|
+
* user. `acceptMonthlyPrice` is a STRING, the exact fresh amount the user
|
|
2010
|
+
* saw, because the backend compares it to a fresh quote and a number would
|
|
2011
|
+
* round-trip through float formatting.
|
|
2012
|
+
*
|
|
2013
|
+
* ONLY the capability gates these. An older backend 404s the route, so the
|
|
2014
|
+
* renderer asks `features.tunnel_setup` first and sends nothing without it.
|
|
2015
|
+
*/
|
|
2016
|
+
zod.z.object({
|
|
2017
|
+
op: zod.z.literal("tunnel.setup.read"),
|
|
2018
|
+
credentialId: zod.z.number().int().positive().optional()
|
|
2019
|
+
}).strict(),
|
|
2020
|
+
zod.z.object({
|
|
2021
|
+
op: zod.z.literal("tunnel.setup.plan"),
|
|
2022
|
+
credentialId: zod.z.number().int().positive().optional()
|
|
2023
|
+
}).strict(),
|
|
2024
|
+
zod.z.object({
|
|
2025
|
+
op: zod.z.literal("tunnel.setup.run"),
|
|
2026
|
+
credentialId: zod.z.number().int().positive(),
|
|
2027
|
+
acceptMonthlyPrice: zod.z.string().min(1).max(64).optional()
|
|
2028
|
+
}).strict(),
|
|
1869
2029
|
zod.z.object({ op: zod.z.literal("auth.start"), provider: id$1 }).strict(),
|
|
1870
2030
|
zod.z.object({ op: zod.z.literal("auth.status"), id: id$1 }).strict(),
|
|
1871
2031
|
zod.z.object({ op: zod.z.literal("auth.input"), id: id$1, promptId: id$1, value: secret }).strict(),
|
|
@@ -2239,6 +2399,71 @@ const desktopRequestUnion = zod.z.discriminatedUnion("op", [
|
|
|
2239
2399
|
]);
|
|
2240
2400
|
const desktopRequestSchema = desktopRequestUnion.superRefine(
|
|
2241
2401
|
(request, ctx) => {
|
|
2402
|
+
if (request.op === "hub.skillPull" || request.op === "hub.skillPublish") {
|
|
2403
|
+
if (request.visibility === "public" && request.tenantId !== null || request.visibility === "org" && !request.tenantId) {
|
|
2404
|
+
ctx.addIssue({
|
|
2405
|
+
code: zod.z.ZodIssueCode.custom,
|
|
2406
|
+
message: "A skill destination requires explicit paired scope",
|
|
2407
|
+
path: ["tenantId"]
|
|
2408
|
+
});
|
|
2409
|
+
return;
|
|
2410
|
+
}
|
|
2411
|
+
if (request.op === "hub.skillPublish" && (request.dryRun ? request.previewReceipt !== void 0 || request.confirmPublish !== void 0 : !request.previewReceipt || request.confirmPublish !== true)) {
|
|
2412
|
+
ctx.addIssue({
|
|
2413
|
+
code: zod.z.ZodIssueCode.custom,
|
|
2414
|
+
message: "An initial skill publication requires its reviewed draft receipt",
|
|
2415
|
+
path: ["previewReceipt"]
|
|
2416
|
+
});
|
|
2417
|
+
return;
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
if (request.op === "hub.check" || request.op === "hub.apply" || request.op === "hub.retry") {
|
|
2421
|
+
const hasLink = request.linkId !== void 0;
|
|
2422
|
+
const hasLegacy = request.kind !== void 0 || request.name !== void 0;
|
|
2423
|
+
if (hasLink && hasLegacy || request.op !== "hub.check" && !hasLink && (!request.kind || !request.name) || request.op === "hub.retry" && hasLink && !request.direction || request.direction === "push" && !hasLink) {
|
|
2424
|
+
ctx.addIssue({
|
|
2425
|
+
code: zod.z.ZodIssueCode.custom,
|
|
2426
|
+
message: "A hub action requires one unambiguous selector and an explicit retry direction",
|
|
2427
|
+
path: ["linkId"]
|
|
2428
|
+
});
|
|
2429
|
+
return;
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2432
|
+
if (request.op === "hub.apply" && (request.previewReceipt !== void 0 || request.confirmApply !== void 0) && (!request.linkId || request.dryRun || !request.previewReceipt || request.confirmApply !== true)) {
|
|
2433
|
+
ctx.addIssue({
|
|
2434
|
+
code: zod.z.ZodIssueCode.custom,
|
|
2435
|
+
message: "A viewed incoming application requires its scoped preview receipt and confirmation",
|
|
2436
|
+
path: ["previewReceipt"]
|
|
2437
|
+
});
|
|
2438
|
+
return;
|
|
2439
|
+
}
|
|
2440
|
+
if (request.op === "hub.apply" && request.resolveSource === true) {
|
|
2441
|
+
const scopePaired = request.visibility === "public" && request.tenantId === null || request.visibility === "org" && typeof request.tenantId === "string" && request.tenantId.length > 0;
|
|
2442
|
+
if (!request.hubSource || !scopePaired || request.acknowledgeUnknownBaseline !== true || request.linkId !== void 0 || request.previewReceipt !== void 0 || request.confirmApply !== void 0 || request.prefer !== void 0) {
|
|
2443
|
+
ctx.addIssue({
|
|
2444
|
+
code: zod.z.ZodIssueCode.custom,
|
|
2445
|
+
message: "Confirming a source requires its exact stated destination and the unknown-baseline acknowledgement, with no link, preview or preference",
|
|
2446
|
+
path: ["hubSource"]
|
|
2447
|
+
});
|
|
2448
|
+
return;
|
|
2449
|
+
}
|
|
2450
|
+
}
|
|
2451
|
+
if (request.op === "hub.push" && (request.dryRun ? request.previewReceipt !== void 0 || request.confirmPublish !== void 0 : !request.previewReceipt || request.confirmPublish !== true)) {
|
|
2452
|
+
ctx.addIssue({
|
|
2453
|
+
code: zod.z.ZodIssueCode.custom,
|
|
2454
|
+
message: "A confirmed publication requires its reviewed preview receipt",
|
|
2455
|
+
path: ["previewReceipt"]
|
|
2456
|
+
});
|
|
2457
|
+
return;
|
|
2458
|
+
}
|
|
2459
|
+
if (request.op === "hub.policy" && request.subscribe === void 0 && request.autoPush === void 0) {
|
|
2460
|
+
ctx.addIssue({
|
|
2461
|
+
code: zod.z.ZodIssueCode.custom,
|
|
2462
|
+
message: "A hub policy change must name subscribe or autoPush",
|
|
2463
|
+
path: ["subscribe"]
|
|
2464
|
+
});
|
|
2465
|
+
return;
|
|
2466
|
+
}
|
|
2242
2467
|
if (request.op === "sessions.answer") {
|
|
2243
2468
|
if (request.askId !== void 0) {
|
|
2244
2469
|
if (!request.askId)
|
|
@@ -2314,7 +2539,15 @@ const desktopRequestSchema = desktopRequestUnion.superRefine(
|
|
|
2314
2539
|
}
|
|
2315
2540
|
return;
|
|
2316
2541
|
}
|
|
2317
|
-
if (request.op !== "agent.publish" && request.op !== "agent.republish") {
|
|
2542
|
+
if (request.op !== "agent.publish" && request.op !== "agent.republish" && request.op !== "team.publish") {
|
|
2543
|
+
return;
|
|
2544
|
+
}
|
|
2545
|
+
if ((request.subscribe !== void 0 || request.autoPush !== void 0 || request.confirmPublicEgress !== void 0) && !request.requestId) {
|
|
2546
|
+
ctx.addIssue({
|
|
2547
|
+
code: zod.z.ZodIssueCode.custom,
|
|
2548
|
+
message: "Initial link policy needs a durable publication request ID",
|
|
2549
|
+
path: ["requestId"]
|
|
2550
|
+
});
|
|
2318
2551
|
return;
|
|
2319
2552
|
}
|
|
2320
2553
|
if (Boolean(request.visibility === "org") !== Boolean(request.tenantId)) {
|
|
@@ -2373,6 +2606,44 @@ function desktopRefusalCodeForStatus(path2, status2) {
|
|
|
2373
2606
|
if (status2 === 503) return DESKTOP_REFUSAL_CODE.planeClosed;
|
|
2374
2607
|
return void 0;
|
|
2375
2608
|
}
|
|
2609
|
+
zod.z.object({
|
|
2610
|
+
step: zod.z.string(),
|
|
2611
|
+
blocked_on: zod.z.string(),
|
|
2612
|
+
configured: zod.z.boolean(),
|
|
2613
|
+
ready: zod.z.boolean(),
|
|
2614
|
+
verified: zod.z.boolean(),
|
|
2615
|
+
url: zod.z.string().nullable(),
|
|
2616
|
+
credential_id: zod.z.number().int().positive().nullable(),
|
|
2617
|
+
identity_label: zod.z.string().nullable(),
|
|
2618
|
+
credential_choices: zod.z.array(
|
|
2619
|
+
zod.z.object({
|
|
2620
|
+
id: zod.z.number().int().positive(),
|
|
2621
|
+
identity_label: zod.z.string().nullable().optional()
|
|
2622
|
+
}).passthrough()
|
|
2623
|
+
).default([]),
|
|
2624
|
+
quote: zod.z.object({
|
|
2625
|
+
monthly_price_usd: zod.z.string().nullable(),
|
|
2626
|
+
positive_balance: zod.z.boolean(),
|
|
2627
|
+
eligible: zod.z.boolean(),
|
|
2628
|
+
account_valid: zod.z.boolean()
|
|
2629
|
+
}).passthrough().nullable(),
|
|
2630
|
+
receipts: zod.z.array(zod.z.object({ step: zod.z.string(), ok: zod.z.boolean(), text: zod.z.string() })).default([]),
|
|
2631
|
+
remedy: zod.z.object({
|
|
2632
|
+
kind: zod.z.string(),
|
|
2633
|
+
text: zod.z.string(),
|
|
2634
|
+
command: zod.z.string().nullable().optional(),
|
|
2635
|
+
url: zod.z.string().nullable().optional()
|
|
2636
|
+
}).nullable(),
|
|
2637
|
+
source: zod.z.string(),
|
|
2638
|
+
in_progress: zod.z.boolean().default(false),
|
|
2639
|
+
progress: zod.z.array(zod.z.string()).default([]),
|
|
2640
|
+
active_credential_id: zod.z.number().int().positive().nullable().default(null),
|
|
2641
|
+
// Backend facts, separate from receipts: an emitted receipt does not prove
|
|
2642
|
+
// an ambiguous activation succeeded or was rolled back.
|
|
2643
|
+
billing_outcome: zod.z.string().optional(),
|
|
2644
|
+
reservation_outcome: zod.z.string().optional(),
|
|
2645
|
+
failure_stage: zod.z.string().optional()
|
|
2646
|
+
}).passthrough();
|
|
2376
2647
|
const DESKTOP_MESSAGE_BYTE_BUDGET = 88e4;
|
|
2377
2648
|
const DESKTOP_CONTROL_BYTE_BUDGET = 262144;
|
|
2378
2649
|
const DESKTOP_SYSTEM_PROMPT_BYTE_BUDGET = 11e5;
|
|
@@ -2430,12 +2701,17 @@ function moveClientBoundMs(shape) {
|
|
|
2430
2701
|
const PRESENCE_GESTURE_DEADLINE_MS = 18e4;
|
|
2431
2702
|
const APPROVAL_APPROVE_DEADLINE_MS = PRESENCE_GESTURE_DEADLINE_MS + 15e3;
|
|
2432
2703
|
const HUB_ITEM_MERGE_S = 120;
|
|
2704
|
+
const PHONE_SETUP_PLAN_DEADLINE_MS = 135e3;
|
|
2705
|
+
const PHONE_SETUP_RUN_DEADLINE_MS = 93e4;
|
|
2433
2706
|
const HUB_ITEM_WRITE_DEADLINE_MS = (HUB_ITEM_MERGE_S + 30 + MOVE_CLIENT_MARGIN_S) * 1e3;
|
|
2434
2707
|
const HUB_CHECK_DEADLINE_MS = 6e4;
|
|
2435
2708
|
const HUB_APPLY_ALL_DEADLINE_MS = 5 * HUB_ITEM_WRITE_DEADLINE_MS;
|
|
2436
2709
|
const HUB_WRITE_OPS = /* @__PURE__ */ new Set([
|
|
2437
2710
|
"hub.apply",
|
|
2438
2711
|
"hub.retry",
|
|
2712
|
+
"hub.push",
|
|
2713
|
+
"hub.skillPublish",
|
|
2714
|
+
"hub.skillPull",
|
|
2439
2715
|
"hub.check",
|
|
2440
2716
|
"hub.applyAll"
|
|
2441
2717
|
]);
|
|
@@ -2443,6 +2719,9 @@ function hubWriteDeadlineMs(op) {
|
|
|
2443
2719
|
switch (op) {
|
|
2444
2720
|
case "hub.apply":
|
|
2445
2721
|
case "hub.retry":
|
|
2722
|
+
case "hub.push":
|
|
2723
|
+
case "hub.skillPublish":
|
|
2724
|
+
case "hub.skillPull":
|
|
2446
2725
|
return HUB_ITEM_WRITE_DEADLINE_MS;
|
|
2447
2726
|
case "hub.check":
|
|
2448
2727
|
return HUB_CHECK_DEADLINE_MS;
|
|
@@ -2458,6 +2737,8 @@ function desktopRequestDeadlineMs(request) {
|
|
|
2458
2737
|
}
|
|
2459
2738
|
const op = typeof request === "string" ? request : request.op;
|
|
2460
2739
|
if (op === "approvals.approve") return APPROVAL_APPROVE_DEADLINE_MS;
|
|
2740
|
+
if (op === "tunnel.setup.run") return PHONE_SETUP_RUN_DEADLINE_MS;
|
|
2741
|
+
if (op === "tunnel.setup.plan") return PHONE_SETUP_PLAN_DEADLINE_MS;
|
|
2461
2742
|
const hub = hubWriteDeadlineMs(op);
|
|
2462
2743
|
if (hub !== null) return hub;
|
|
2463
2744
|
return LONG_READ_OPS.has(op) ? DESKTOP_LONG_READ_DEADLINE_MS : DESKTOP_CONTROL_DEADLINE_MS;
|
|
@@ -2475,6 +2756,7 @@ const READ_ONLY_OPS = /* @__PURE__ */ new Set([
|
|
|
2475
2756
|
"config.get",
|
|
2476
2757
|
"credentials.list",
|
|
2477
2758
|
"hub.updates",
|
|
2759
|
+
"hub.links",
|
|
2478
2760
|
"info.get",
|
|
2479
2761
|
"instructions.get",
|
|
2480
2762
|
"legacy.agent.get",
|
|
@@ -2511,6 +2793,7 @@ const READ_ONLY_OPS = /* @__PURE__ */ new Set([
|
|
|
2511
2793
|
"sessions.find",
|
|
2512
2794
|
"sessions.get",
|
|
2513
2795
|
"sessions.history",
|
|
2796
|
+
"sessions.files",
|
|
2514
2797
|
"sessions.list",
|
|
2515
2798
|
"sessions.preview",
|
|
2516
2799
|
"sessions.report",
|
|
@@ -2520,6 +2803,10 @@ const READ_ONLY_OPS = /* @__PURE__ */ new Set([
|
|
|
2520
2803
|
"subagents.transcript",
|
|
2521
2804
|
"teams.get",
|
|
2522
2805
|
"teams.list",
|
|
2806
|
+
// The two phone-setup observations change nothing on the server; `tunnel.setup.run`
|
|
2807
|
+
// is deliberately absent so a run that ran out of time gets the cautious sentence.
|
|
2808
|
+
"tunnel.setup.plan",
|
|
2809
|
+
"tunnel.setup.read",
|
|
2523
2810
|
"usage.get"
|
|
2524
2811
|
]);
|
|
2525
2812
|
const PANEL_READ_OPS = /* @__PURE__ */ new Set([
|
|
@@ -2617,6 +2904,14 @@ function wakeTiming(request) {
|
|
|
2617
2904
|
...request.limit !== void 0 ? { limit: request.limit } : {}
|
|
2618
2905
|
};
|
|
2619
2906
|
}
|
|
2907
|
+
function publicationPolicyBody(request) {
|
|
2908
|
+
return {
|
|
2909
|
+
...request.requestId ? { request_id: request.requestId } : {},
|
|
2910
|
+
...request.subscribe !== void 0 ? { subscribe: request.subscribe } : {},
|
|
2911
|
+
...request.autoPush !== void 0 ? { auto_push: request.autoPush } : {},
|
|
2912
|
+
...request.confirmPublicEgress !== void 0 ? { confirm_public_egress: request.confirmPublicEgress } : {}
|
|
2913
|
+
};
|
|
2914
|
+
}
|
|
2620
2915
|
function assertPairedPublicationTarget(request) {
|
|
2621
2916
|
if (Boolean(request.visibility === "org") !== Boolean(request.tenantId)) {
|
|
2622
2917
|
throw new Error(
|
|
@@ -2733,16 +3028,81 @@ function desktopEndpoint(request) {
|
|
|
2733
3028
|
return {
|
|
2734
3029
|
path: `/v1/desktop/profiles/${encodeURIComponent(request.name)}`,
|
|
2735
3030
|
method: "PATCH",
|
|
2736
|
-
body: {
|
|
3031
|
+
body: {
|
|
3032
|
+
request_id: request.requestId,
|
|
3033
|
+
...request.fields,
|
|
3034
|
+
/*
|
|
3035
|
+
* The opaque echo travels ALONGSIDE the fields, never inside them: the
|
|
3036
|
+
* edit body is `exclude_unset`-merged on the backend, so a revision
|
|
3037
|
+
* nested in `fields` could be mistaken for an editable property. Sent
|
|
3038
|
+
* only when present, so absence stays the legacy unconditional write.
|
|
3039
|
+
*/
|
|
3040
|
+
...request.expectedDefinitionRevision !== void 0 && request.expectedDefinitionRevision !== null ? {
|
|
3041
|
+
expected_definition_revision: request.expectedDefinitionRevision
|
|
3042
|
+
} : {}
|
|
3043
|
+
}
|
|
2737
3044
|
};
|
|
2738
3045
|
case "hub.updates":
|
|
2739
3046
|
return { path: "/v1/desktop/hub/updates", method: "GET" };
|
|
3047
|
+
case "hub.skillPull":
|
|
3048
|
+
return {
|
|
3049
|
+
path: "/v1/desktop/hub/skills/pull",
|
|
3050
|
+
method: "POST",
|
|
3051
|
+
body: {
|
|
3052
|
+
request_id: request.requestId,
|
|
3053
|
+
hub_id: request.hubId,
|
|
3054
|
+
hub_source: request.hubSource,
|
|
3055
|
+
visibility: request.visibility,
|
|
3056
|
+
tenant_id: request.tenantId,
|
|
3057
|
+
local_alias: request.localAlias,
|
|
3058
|
+
...request.subscribe !== void 0 ? { subscribe: request.subscribe } : {},
|
|
3059
|
+
...request.autoPush !== void 0 ? { auto_push: request.autoPush } : {},
|
|
3060
|
+
...request.confirmPublicEgress !== void 0 ? { confirm_public_egress: request.confirmPublicEgress } : {}
|
|
3061
|
+
}
|
|
3062
|
+
};
|
|
3063
|
+
case "hub.skillPublish":
|
|
3064
|
+
return {
|
|
3065
|
+
path: "/v1/desktop/hub/skills/publish",
|
|
3066
|
+
method: "POST",
|
|
3067
|
+
body: {
|
|
3068
|
+
request_id: request.requestId,
|
|
3069
|
+
dry_run: request.dryRun,
|
|
3070
|
+
source_skill: request.sourceSkill,
|
|
3071
|
+
local_alias: request.localAlias,
|
|
3072
|
+
visibility: request.visibility,
|
|
3073
|
+
tenant_id: request.tenantId,
|
|
3074
|
+
subscribe: request.subscribe,
|
|
3075
|
+
auto_push: request.autoPush,
|
|
3076
|
+
confirm_public_egress: request.confirmPublicEgress,
|
|
3077
|
+
...request.previewReceipt ? { preview_receipt: request.previewReceipt } : {},
|
|
3078
|
+
...request.confirmPublish ? { confirm_publish: true } : {}
|
|
3079
|
+
}
|
|
3080
|
+
};
|
|
3081
|
+
case "hub.links":
|
|
3082
|
+
return {
|
|
3083
|
+
path: `/v1/desktop/hub/links${request.kind ? `?kind=${request.kind}` : ""}`,
|
|
3084
|
+
method: "GET"
|
|
3085
|
+
};
|
|
3086
|
+
case "hub.policy":
|
|
3087
|
+
return {
|
|
3088
|
+
path: `/v1/desktop/hub/links/${encodeURIComponent(request.linkId)}`,
|
|
3089
|
+
method: "PATCH",
|
|
3090
|
+
body: {
|
|
3091
|
+
request_id: request.requestId,
|
|
3092
|
+
expected_policy_revision: request.expectedPolicyRevision,
|
|
3093
|
+
...request.subscribe !== void 0 ? { subscribe: request.subscribe } : {},
|
|
3094
|
+
...request.autoPush !== void 0 ? { auto_push: request.autoPush } : {},
|
|
3095
|
+
...request.confirmPublicEgress !== void 0 ? { confirm_public_egress: request.confirmPublicEgress } : {}
|
|
3096
|
+
}
|
|
3097
|
+
};
|
|
2740
3098
|
case "hub.check":
|
|
2741
3099
|
return {
|
|
2742
3100
|
path: "/v1/desktop/hub/updates/check",
|
|
2743
3101
|
method: "POST",
|
|
2744
3102
|
body: {
|
|
2745
3103
|
request_id: request.requestId,
|
|
3104
|
+
...request.linkId ? { link_id: request.linkId } : {},
|
|
3105
|
+
...request.direction ? { direction: request.direction } : {},
|
|
2746
3106
|
...request.kind ? { kind: request.kind } : {},
|
|
2747
3107
|
...request.name ? { name: request.name } : {}
|
|
2748
3108
|
}
|
|
@@ -2753,13 +3113,30 @@ function desktopEndpoint(request) {
|
|
|
2753
3113
|
method: "POST",
|
|
2754
3114
|
body: {
|
|
2755
3115
|
request_id: request.requestId,
|
|
2756
|
-
|
|
2757
|
-
|
|
3116
|
+
...request.previewReceipt ? { preview_receipt: request.previewReceipt } : {},
|
|
3117
|
+
...request.confirmApply ? { confirm_apply: true } : {},
|
|
3118
|
+
...request.linkId ? { link_id: request.linkId } : {},
|
|
3119
|
+
...request.direction ? { direction: request.direction } : {},
|
|
3120
|
+
...request.kind ? { kind: request.kind } : {},
|
|
3121
|
+
...request.name ? { name: request.name } : {},
|
|
2758
3122
|
...request.prefer ? { prefer: request.prefer } : {},
|
|
2759
3123
|
...request.acknowledgeUnknownBaseline !== void 0 ? {
|
|
2760
3124
|
acknowledge_unknown_baseline: request.acknowledgeUnknownBaseline
|
|
2761
3125
|
} : {},
|
|
2762
|
-
...request.dryRun !== void 0 ? { dry_run: request.dryRun } : {}
|
|
3126
|
+
...request.dryRun !== void 0 ? { dry_run: request.dryRun } : {},
|
|
3127
|
+
/*
|
|
3128
|
+
* The source-confirmation branch travels on the SAME apply route with an
|
|
3129
|
+
* explicit flag, never a new endpoint. `resolve_source:true` plus the
|
|
3130
|
+
* stated scope triple is the whole act; the service materializes the
|
|
3131
|
+
* real identity/link and preserves any known scope (refusing a conflict
|
|
3132
|
+
* with `origin-conflict`), so nothing here infers Public or an org.
|
|
3133
|
+
*/
|
|
3134
|
+
...request.resolveSource === true ? {
|
|
3135
|
+
resolve_source: true,
|
|
3136
|
+
hub_source: request.hubSource,
|
|
3137
|
+
visibility: request.visibility,
|
|
3138
|
+
tenant_id: request.tenantId ?? null
|
|
3139
|
+
} : {}
|
|
2763
3140
|
}
|
|
2764
3141
|
};
|
|
2765
3142
|
case "hub.applyAll":
|
|
@@ -2777,8 +3154,23 @@ function desktopEndpoint(request) {
|
|
|
2777
3154
|
method: "POST",
|
|
2778
3155
|
body: {
|
|
2779
3156
|
request_id: request.requestId,
|
|
2780
|
-
|
|
2781
|
-
|
|
3157
|
+
...request.linkId ? { link_id: request.linkId } : {},
|
|
3158
|
+
...request.direction ? { direction: request.direction } : {},
|
|
3159
|
+
...request.kind ? { kind: request.kind } : {},
|
|
3160
|
+
...request.name ? { name: request.name } : {}
|
|
3161
|
+
}
|
|
3162
|
+
};
|
|
3163
|
+
case "hub.push":
|
|
3164
|
+
return {
|
|
3165
|
+
path: "/v1/desktop/hub/updates/push",
|
|
3166
|
+
method: "POST",
|
|
3167
|
+
body: {
|
|
3168
|
+
request_id: request.requestId,
|
|
3169
|
+
link_id: request.linkId,
|
|
3170
|
+
direction: request.direction,
|
|
3171
|
+
dry_run: request.dryRun,
|
|
3172
|
+
...request.previewReceipt ? { preview_receipt: request.previewReceipt } : {},
|
|
3173
|
+
...request.confirmPublish ? { confirm_publish: true } : {}
|
|
2782
3174
|
}
|
|
2783
3175
|
};
|
|
2784
3176
|
case "teams.list":
|
|
@@ -2798,7 +3190,14 @@ function desktopEndpoint(request) {
|
|
|
2798
3190
|
return {
|
|
2799
3191
|
path: `/v1/desktop/teams/${encodeURIComponent(request.name)}`,
|
|
2800
3192
|
method: "PATCH",
|
|
2801
|
-
body: {
|
|
3193
|
+
body: {
|
|
3194
|
+
request_id: request.requestId,
|
|
3195
|
+
...request.fields,
|
|
3196
|
+
/* Opaque echo beside the fields; absent/null = legacy unconditional. */
|
|
3197
|
+
...request.expectedDefinitionRevision !== void 0 && request.expectedDefinitionRevision !== null ? {
|
|
3198
|
+
expected_definition_revision: request.expectedDefinitionRevision
|
|
3199
|
+
} : {}
|
|
3200
|
+
}
|
|
2802
3201
|
};
|
|
2803
3202
|
case "sessions.list": {
|
|
2804
3203
|
const params = new URLSearchParams();
|
|
@@ -2927,6 +3326,31 @@ function desktopEndpoint(request) {
|
|
|
2927
3326
|
method: "GET"
|
|
2928
3327
|
};
|
|
2929
3328
|
}
|
|
3329
|
+
case "sessions.files": {
|
|
3330
|
+
const query = new URLSearchParams({
|
|
3331
|
+
limit: String(request.limit ?? 200)
|
|
3332
|
+
});
|
|
3333
|
+
for (const key of [
|
|
3334
|
+
"scope",
|
|
3335
|
+
"kind",
|
|
3336
|
+
"q",
|
|
3337
|
+
"sort",
|
|
3338
|
+
"order",
|
|
3339
|
+
"cursor"
|
|
3340
|
+
]) {
|
|
3341
|
+
const value = request[key];
|
|
3342
|
+
if (value !== void 0) query.set(key, value);
|
|
3343
|
+
}
|
|
3344
|
+
return {
|
|
3345
|
+
path: `/v1/desktop/sessions/${encodeURIComponent(request.sessionId)}/files?${query}`,
|
|
3346
|
+
method: "GET"
|
|
3347
|
+
};
|
|
3348
|
+
}
|
|
3349
|
+
case "sessions.files.materialise":
|
|
3350
|
+
return {
|
|
3351
|
+
path: `/v1/desktop/sessions/${encodeURIComponent(request.sessionId)}/files/${encodeURIComponent(request.fileId)}/materialise`,
|
|
3352
|
+
method: "POST"
|
|
3353
|
+
};
|
|
2930
3354
|
case "sessions.history": {
|
|
2931
3355
|
const query = new URLSearchParams({
|
|
2932
3356
|
limit: String(request.limit ?? 100)
|
|
@@ -3241,7 +3665,10 @@ function desktopEndpoint(request) {
|
|
|
3241
3665
|
// there is no override, because the route's input model forbids extras
|
|
3242
3666
|
// and still wants a JSON OBJECT — an omitted body makes a legal call
|
|
3243
3667
|
// answer 422.
|
|
3244
|
-
body: {
|
|
3668
|
+
body: {
|
|
3669
|
+
document: request.document ?? {},
|
|
3670
|
+
...publicationPolicyBody(request)
|
|
3671
|
+
}
|
|
3245
3672
|
};
|
|
3246
3673
|
}
|
|
3247
3674
|
case "agent.republish": {
|
|
@@ -3257,10 +3684,25 @@ function desktopEndpoint(request) {
|
|
|
3257
3684
|
method: "PUT",
|
|
3258
3685
|
body: {
|
|
3259
3686
|
hub_agent_id: request.hubAgentId,
|
|
3260
|
-
document: request.document ?? {}
|
|
3687
|
+
document: request.document ?? {},
|
|
3688
|
+
...publicationPolicyBody(request),
|
|
3689
|
+
...request.expectedRemoteRevision ? { expected_remote_revision: request.expectedRemoteRevision } : {}
|
|
3261
3690
|
}
|
|
3262
3691
|
};
|
|
3263
3692
|
}
|
|
3693
|
+
case "team.publish": {
|
|
3694
|
+
assertPairedPublicationTarget(request);
|
|
3695
|
+
const query = new URLSearchParams();
|
|
3696
|
+
if (request.visibility === "org" && request.tenantId) {
|
|
3697
|
+
query.set("visibility", "org");
|
|
3698
|
+
query.set("tenant_id", request.tenantId);
|
|
3699
|
+
}
|
|
3700
|
+
return {
|
|
3701
|
+
path: `/v1/teams/${request.teamId}/publish${query.size ? `?${query}` : ""}`,
|
|
3702
|
+
method: "POST",
|
|
3703
|
+
body: publicationPolicyBody(request)
|
|
3704
|
+
};
|
|
3705
|
+
}
|
|
3264
3706
|
case "team.pull": {
|
|
3265
3707
|
const query = new URLSearchParams();
|
|
3266
3708
|
if (request.tenantId) query.set("tenant_id", request.tenantId);
|
|
@@ -3660,6 +4102,30 @@ function desktopEndpoint(request) {
|
|
|
3660
4102
|
path: `/v1/auth/accounts/${request.accountId}`,
|
|
3661
4103
|
method: "DELETE"
|
|
3662
4104
|
};
|
|
4105
|
+
case "tunnel.setup.read":
|
|
4106
|
+
return {
|
|
4107
|
+
path: request.credentialId === void 0 ? "/v1/desktop/tunnel/setup" : `/v1/desktop/tunnel/setup?credential_id=${request.credentialId}`,
|
|
4108
|
+
method: "GET"
|
|
4109
|
+
};
|
|
4110
|
+
case "tunnel.setup.plan":
|
|
4111
|
+
return {
|
|
4112
|
+
path: "/v1/desktop/tunnel/setup",
|
|
4113
|
+
method: "POST",
|
|
4114
|
+
body: {
|
|
4115
|
+
action: "plan",
|
|
4116
|
+
...request.credentialId !== void 0 ? { credential_id: request.credentialId } : {}
|
|
4117
|
+
}
|
|
4118
|
+
};
|
|
4119
|
+
case "tunnel.setup.run":
|
|
4120
|
+
return {
|
|
4121
|
+
path: "/v1/desktop/tunnel/setup",
|
|
4122
|
+
method: "POST",
|
|
4123
|
+
body: {
|
|
4124
|
+
action: "run",
|
|
4125
|
+
credential_id: request.credentialId,
|
|
4126
|
+
...request.acceptMonthlyPrice !== void 0 ? { accept_monthly_price: request.acceptMonthlyPrice } : {}
|
|
4127
|
+
}
|
|
4128
|
+
};
|
|
3663
4129
|
case "auth.start":
|
|
3664
4130
|
return {
|
|
3665
4131
|
path: "/v1/auth/login",
|
|
@@ -13252,6 +13718,11 @@ function describeWindowLaunch(plan, platform = process.platform) {
|
|
|
13252
13718
|
const suffix = extras.length === 0 ? "" : `, ${extras.join(", ")}`;
|
|
13253
13719
|
return `window mode ${plan.mode}: ${plan.width}x${plan.height}, ${behaviour}, page throttling ${plan.backgroundThrottling ? "on" : "off"}${suffix}${assumption}`;
|
|
13254
13720
|
}
|
|
13721
|
+
function focusBrowserChordTarget(window, target2, show) {
|
|
13722
|
+
if (show !== "focus" || window.isDestroyed() || !window.isFocused() || target2.isDestroyed())
|
|
13723
|
+
return;
|
|
13724
|
+
target2.focus();
|
|
13725
|
+
}
|
|
13255
13726
|
const MODE_OF_SHOW = {
|
|
13256
13727
|
focus: "normal",
|
|
13257
13728
|
inactive: "inactive",
|
|
@@ -14766,6 +15237,38 @@ ${result.stdout}`,
|
|
|
14766
15237
|
});
|
|
14767
15238
|
}
|
|
14768
15239
|
}
|
|
15240
|
+
const DIGIT_KEY$1 = /^[1-9]$/;
|
|
15241
|
+
const DIGIT_CODE = /^Digit([1-9])$/;
|
|
15242
|
+
function browserChordIntent(input, platform) {
|
|
15243
|
+
if (input.type !== "keyDown" || input.alt || input.isComposing) return null;
|
|
15244
|
+
const key = input.key.toLowerCase();
|
|
15245
|
+
let intent = null;
|
|
15246
|
+
if (key === "tab" && input.control && !input.meta) {
|
|
15247
|
+
intent = input.shift ? "prev-tab" : "next-tab";
|
|
15248
|
+
} else {
|
|
15249
|
+
const primary = platform === "darwin" ? input.meta && !input.control : input.control && !input.meta;
|
|
15250
|
+
if (!primary) return null;
|
|
15251
|
+
if (key === "+" || key === "=") intent = "zoom-in";
|
|
15252
|
+
else if (key === "-" && !input.shift) intent = "zoom-out";
|
|
15253
|
+
else if (key === "0" && !input.shift) intent = "zoom-reset";
|
|
15254
|
+
else if (platform === "darwin" && input.shift && ["[", "]", "{", "}"].includes(key)) {
|
|
15255
|
+
intent = key === "[" || key === "{" ? "prev-tab" : "next-tab";
|
|
15256
|
+
} else if (key === "r") intent = input.shift ? "hard-reload" : "reload";
|
|
15257
|
+
else if (key === "t") intent = input.shift ? "reopen-tab" : "new-tab";
|
|
15258
|
+
else if (!input.shift) {
|
|
15259
|
+
if (key === "f") intent = "find-page";
|
|
15260
|
+
else if (key === "l") intent = "focus-address";
|
|
15261
|
+
else if (key === "w") intent = "close-tab";
|
|
15262
|
+
else if (key === "[") intent = "back";
|
|
15263
|
+
else if (key === "]") intent = "forward";
|
|
15264
|
+
else {
|
|
15265
|
+
const digit = DIGIT_KEY$1.test(key) ? key : DIGIT_CODE.exec(input.code ?? "")?.[1];
|
|
15266
|
+
if (digit) intent = `tab-${digit}`;
|
|
15267
|
+
}
|
|
15268
|
+
}
|
|
15269
|
+
}
|
|
15270
|
+
return input.isAutoRepeat && intent !== "next-tab" && intent !== "prev-tab" ? null : intent;
|
|
15271
|
+
}
|
|
14769
15272
|
const CONSOLE_METHODS = [
|
|
14770
15273
|
"console_list",
|
|
14771
15274
|
"console_resources",
|
|
@@ -27844,6 +28347,53 @@ class ApprovalStore {
|
|
|
27844
28347
|
);
|
|
27845
28348
|
}
|
|
27846
28349
|
}
|
|
28350
|
+
function runBrowserMenuAction(intent, target2, owner, route) {
|
|
28351
|
+
if (!target2) return;
|
|
28352
|
+
if (target2 === owner && route(intent)) return;
|
|
28353
|
+
if (intent === "reload") target2.webContents?.reload();
|
|
28354
|
+
else if (intent === "hard-reload") target2.webContents?.reloadIgnoringCache();
|
|
28355
|
+
else target2.close();
|
|
28356
|
+
}
|
|
28357
|
+
function createBrowserChordRouter(options) {
|
|
28358
|
+
function dispatch(intent, origin) {
|
|
28359
|
+
if (intent === "reload" || intent === "hard-reload")
|
|
28360
|
+
options.reload(intent === "hard-reload");
|
|
28361
|
+
else if (intent === "back" || intent === "forward") options.history(intent);
|
|
28362
|
+
else if (intent.startsWith("zoom-") && options.zoom) {
|
|
28363
|
+
options.zoom(
|
|
28364
|
+
intent === "zoom-in" ? "in" : intent === "zoom-out" ? "out" : "reset"
|
|
28365
|
+
);
|
|
28366
|
+
} else {
|
|
28367
|
+
options.focusChrome();
|
|
28368
|
+
options.send({ intent, origin });
|
|
28369
|
+
}
|
|
28370
|
+
}
|
|
28371
|
+
return {
|
|
28372
|
+
input(event, input, origin, owns) {
|
|
28373
|
+
const intent = owns ? browserChordIntent(input, options.platform) : null;
|
|
28374
|
+
if (!intent) {
|
|
28375
|
+
const rejected = owns && input.type === "keyDown" && (input.isAutoRepeat || input.isComposing) && browserChordIntent(
|
|
28376
|
+
{ ...input, isAutoRepeat: false, isComposing: false },
|
|
28377
|
+
options.platform
|
|
28378
|
+
);
|
|
28379
|
+
if (rejected) {
|
|
28380
|
+
event.preventDefault();
|
|
28381
|
+
return true;
|
|
28382
|
+
}
|
|
28383
|
+
return false;
|
|
28384
|
+
}
|
|
28385
|
+
event.preventDefault();
|
|
28386
|
+
dispatch(intent, origin);
|
|
28387
|
+
return true;
|
|
28388
|
+
},
|
|
28389
|
+
menu(intent) {
|
|
28390
|
+
const page = options.ownsPage();
|
|
28391
|
+
if (!page && !options.ownsChrome()) return false;
|
|
28392
|
+
dispatch(intent, page ? "page" : "chrome");
|
|
28393
|
+
return true;
|
|
28394
|
+
}
|
|
28395
|
+
};
|
|
28396
|
+
}
|
|
27847
28397
|
const MAX_ENTRIES = 200;
|
|
27848
28398
|
const MAX_BYTES = 256 * 1024;
|
|
27849
28399
|
const MAX_ARG_CHARS = 2e3;
|
|
@@ -30881,6 +31431,168 @@ function factOf(path2) {
|
|
|
30881
31431
|
sha256: ""
|
|
30882
31432
|
};
|
|
30883
31433
|
}
|
|
31434
|
+
const PAGE_ZOOM_STEPS = [
|
|
31435
|
+
0.25,
|
|
31436
|
+
0.33,
|
|
31437
|
+
0.5,
|
|
31438
|
+
0.67,
|
|
31439
|
+
0.75,
|
|
31440
|
+
0.8,
|
|
31441
|
+
0.9,
|
|
31442
|
+
1,
|
|
31443
|
+
1.1,
|
|
31444
|
+
1.25,
|
|
31445
|
+
1.5,
|
|
31446
|
+
1.75,
|
|
31447
|
+
2,
|
|
31448
|
+
2.5,
|
|
31449
|
+
3,
|
|
31450
|
+
4,
|
|
31451
|
+
5
|
|
31452
|
+
];
|
|
31453
|
+
class PageControls {
|
|
31454
|
+
constructor(changed, resultTimeoutMs = 5e3) {
|
|
31455
|
+
this.changed = changed;
|
|
31456
|
+
this.resultTimeoutMs = resultTimeoutMs;
|
|
31457
|
+
}
|
|
31458
|
+
find = null;
|
|
31459
|
+
record = null;
|
|
31460
|
+
epoch = -1;
|
|
31461
|
+
requestId = null;
|
|
31462
|
+
listener = null;
|
|
31463
|
+
notice = null;
|
|
31464
|
+
noticeTabId = null;
|
|
31465
|
+
timer = null;
|
|
31466
|
+
stopTimer() {
|
|
31467
|
+
if (this.timer) clearTimeout(this.timer);
|
|
31468
|
+
this.timer = null;
|
|
31469
|
+
}
|
|
31470
|
+
reconcile(active) {
|
|
31471
|
+
if (this.record && (active !== this.record || !active.presented || active.documentEpoch !== this.epoch || active.view.webContents.isDestroyed()))
|
|
31472
|
+
this.clear();
|
|
31473
|
+
}
|
|
31474
|
+
state(active) {
|
|
31475
|
+
this.reconcile(active);
|
|
31476
|
+
if (active?.tabId !== this.noticeTabId || !active?.presented)
|
|
31477
|
+
this.notice = null;
|
|
31478
|
+
return {
|
|
31479
|
+
find: this.find ? { ...this.find } : null,
|
|
31480
|
+
zoom: active?.view.webContents.getZoomFactor?.() ?? 1,
|
|
31481
|
+
zoomAllowed: active?.owner === "user" && !active.handedTo,
|
|
31482
|
+
notice: this.notice
|
|
31483
|
+
};
|
|
31484
|
+
}
|
|
31485
|
+
clear() {
|
|
31486
|
+
this.stopTimer();
|
|
31487
|
+
const old = this.record;
|
|
31488
|
+
const listener = this.listener;
|
|
31489
|
+
this.record = null;
|
|
31490
|
+
this.find = null;
|
|
31491
|
+
this.requestId = null;
|
|
31492
|
+
this.listener = null;
|
|
31493
|
+
if (old && listener)
|
|
31494
|
+
old.view.webContents.removeListener("found-in-page", listener);
|
|
31495
|
+
if (old && !old.view.webContents.isDestroyed())
|
|
31496
|
+
old.view.webContents.stopFindInPage?.("clearSelection");
|
|
31497
|
+
}
|
|
31498
|
+
open(active) {
|
|
31499
|
+
this.reconcile(active);
|
|
31500
|
+
if (!active.presented) return;
|
|
31501
|
+
if (this.record === active) return;
|
|
31502
|
+
this.clear();
|
|
31503
|
+
this.record = active;
|
|
31504
|
+
this.epoch = active.documentEpoch;
|
|
31505
|
+
this.find = {
|
|
31506
|
+
tabId: active.tabId,
|
|
31507
|
+
query: "",
|
|
31508
|
+
ordinal: 0,
|
|
31509
|
+
matches: 0,
|
|
31510
|
+
pending: false,
|
|
31511
|
+
unreported: false
|
|
31512
|
+
};
|
|
31513
|
+
this.listener = (_event, result) => {
|
|
31514
|
+
if (this.record !== active || !active.presented || active.documentEpoch !== this.epoch || result.requestId !== this.requestId || !this.find)
|
|
31515
|
+
return;
|
|
31516
|
+
if (result.finalUpdate !== false) this.stopTimer();
|
|
31517
|
+
this.find = {
|
|
31518
|
+
...this.find,
|
|
31519
|
+
unreported: false,
|
|
31520
|
+
ordinal: result.activeMatchOrdinal,
|
|
31521
|
+
matches: result.matches,
|
|
31522
|
+
pending: result.finalUpdate === false
|
|
31523
|
+
};
|
|
31524
|
+
this.changed();
|
|
31525
|
+
};
|
|
31526
|
+
active.view.webContents.on("found-in-page", this.listener);
|
|
31527
|
+
}
|
|
31528
|
+
search(active, query, forward, next) {
|
|
31529
|
+
this.open(active);
|
|
31530
|
+
if (!this.find || this.record !== active) return;
|
|
31531
|
+
this.stopTimer();
|
|
31532
|
+
const same = this.find.query === query;
|
|
31533
|
+
const continuing = same && next && this.requestId !== null && !this.find.unreported;
|
|
31534
|
+
this.requestId = null;
|
|
31535
|
+
this.find = {
|
|
31536
|
+
...this.find,
|
|
31537
|
+
query,
|
|
31538
|
+
pending: query.length > 0,
|
|
31539
|
+
unreported: false,
|
|
31540
|
+
...same ? {} : { ordinal: 0, matches: 0 }
|
|
31541
|
+
};
|
|
31542
|
+
if (!query) {
|
|
31543
|
+
active.view.webContents.stopFindInPage?.("clearSelection");
|
|
31544
|
+
return;
|
|
31545
|
+
}
|
|
31546
|
+
this.requestId = active.view.webContents.findInPage?.(query, {
|
|
31547
|
+
forward,
|
|
31548
|
+
// Electron's misleading name means NEW SESSION (44.3 native maps
|
|
31549
|
+
// it to options->new_session), not "advance". Initial/changed/retry
|
|
31550
|
+
// must be true; an existing query's next/previous must be false.
|
|
31551
|
+
findNext: !continuing
|
|
31552
|
+
}) ?? null;
|
|
31553
|
+
const request = this.requestId;
|
|
31554
|
+
this.timer = setTimeout(() => {
|
|
31555
|
+
this.timer = null;
|
|
31556
|
+
if (this.record !== active || !active.presented || active.documentEpoch !== this.epoch || this.requestId !== request || !this.find)
|
|
31557
|
+
return;
|
|
31558
|
+
this.requestId = null;
|
|
31559
|
+
if (active.view.webContents.isDestroyed()) {
|
|
31560
|
+
this.clear();
|
|
31561
|
+
this.changed();
|
|
31562
|
+
return;
|
|
31563
|
+
}
|
|
31564
|
+
active.view.webContents.stopFindInPage?.("clearSelection");
|
|
31565
|
+
this.find = {
|
|
31566
|
+
...this.find,
|
|
31567
|
+
pending: false,
|
|
31568
|
+
unreported: true,
|
|
31569
|
+
ordinal: 0,
|
|
31570
|
+
matches: 0
|
|
31571
|
+
};
|
|
31572
|
+
this.changed();
|
|
31573
|
+
}, this.resultTimeoutMs);
|
|
31574
|
+
this.timer.unref?.();
|
|
31575
|
+
}
|
|
31576
|
+
zoom(active, command) {
|
|
31577
|
+
if (active.owner !== "user" || active.handedTo) {
|
|
31578
|
+
this.notice = "Zoom is off for tabs an agent is driving";
|
|
31579
|
+
this.noticeTabId = active.tabId;
|
|
31580
|
+
return;
|
|
31581
|
+
}
|
|
31582
|
+
this.notice = null;
|
|
31583
|
+
const current = active.view.webContents.getZoomFactor?.() ?? 1;
|
|
31584
|
+
const factor = command === "reset" ? 1 : command === "in" ? PAGE_ZOOM_STEPS.find((step) => step > current + 1e-3) ?? 5 : [...PAGE_ZOOM_STEPS].reverse().find((step) => step < current - 1e-3) ?? 0.25;
|
|
31585
|
+
active.view.webContents.setZoomFactor?.(factor);
|
|
31586
|
+
}
|
|
31587
|
+
/** Call BEFORE a capability transfer. Isolated per-WebContents zoom means
|
|
31588
|
+
* resetting this tab cannot alter another tab at the same origin. */
|
|
31589
|
+
prepareAgent(record) {
|
|
31590
|
+
const changed = this.record === record || (record.view.webContents.getZoomFactor?.() ?? 1) !== 1;
|
|
31591
|
+
if (this.record === record) this.clear();
|
|
31592
|
+
record.view.webContents.setZoomFactor?.(1);
|
|
31593
|
+
if (changed) this.changed();
|
|
31594
|
+
}
|
|
31595
|
+
}
|
|
30884
31596
|
const DOCUMENT_SCOPED = /* @__PURE__ */ new Set([
|
|
30885
31597
|
"read",
|
|
30886
31598
|
// The structured reads (`styles`, `hit_test`, `ancestors`) describe the
|
|
@@ -30967,6 +31679,7 @@ function sessionRequesterOf(requester) {
|
|
|
30967
31679
|
}
|
|
30968
31680
|
class BrowserHost {
|
|
30969
31681
|
registry;
|
|
31682
|
+
pageControls;
|
|
30970
31683
|
cdp;
|
|
30971
31684
|
approvals;
|
|
30972
31685
|
ownership;
|
|
@@ -30991,6 +31704,7 @@ class BrowserHost {
|
|
|
30991
31704
|
hydration = Promise.resolve();
|
|
30992
31705
|
constructor(options) {
|
|
30993
31706
|
this.registry = options.registry;
|
|
31707
|
+
this.pageControls = new PageControls(() => this.onChanged());
|
|
30994
31708
|
this.cdp = options.cdp;
|
|
30995
31709
|
this.approvals = options.approvals;
|
|
30996
31710
|
this.ownership = options.ownership;
|
|
@@ -31014,6 +31728,10 @@ class BrowserHost {
|
|
|
31014
31728
|
return run();
|
|
31015
31729
|
}
|
|
31016
31730
|
async authorizedPerform(method, params, requestId2) {
|
|
31731
|
+
if (typeof params.tab === "string" && TAB_SCOPED.has(method)) {
|
|
31732
|
+
const record2 = this.registry.requireSurface(params.tab);
|
|
31733
|
+
this.pageControls.prepareAgent(record2);
|
|
31734
|
+
}
|
|
31017
31735
|
if (!DOCUMENT_SCOPED.has(method))
|
|
31018
31736
|
return this.perform(method, params, requestId2);
|
|
31019
31737
|
const token = String(params.tab ?? "");
|
|
@@ -31272,6 +31990,7 @@ class BrowserHost {
|
|
|
31272
31990
|
const active = activeRecord && !activeRecord.view.webContents.isDestroyed() ? activeRecord : null;
|
|
31273
31991
|
const navigation = active?.view.webContents.navigationHistory;
|
|
31274
31992
|
return {
|
|
31993
|
+
pageControls: this.pageControls.state(active),
|
|
31275
31994
|
tabs: this.registry.snapshot().map((entry) => ({
|
|
31276
31995
|
tabId: entry.tabId,
|
|
31277
31996
|
title: this.titleForChrome(entry.title) || "New tab",
|
|
@@ -31389,16 +32108,94 @@ class BrowserHost {
|
|
|
31389
32108
|
* one field.
|
|
31390
32109
|
*/
|
|
31391
32110
|
async newTab(sessionId2) {
|
|
32111
|
+
await this.createUserTab(sessionId2 ?? null);
|
|
32112
|
+
return this.chromeState();
|
|
32113
|
+
}
|
|
32114
|
+
/** `newTab`'s body, returning the record so `reopenClosed` can navigate the tab
|
|
32115
|
+
* it created rather than whichever tab is active by the time the await ends. */
|
|
32116
|
+
async createUserTab(sessionId2) {
|
|
31392
32117
|
const record = this.registry.create({
|
|
31393
32118
|
owner: "user",
|
|
31394
|
-
sessionId: sessionId2
|
|
32119
|
+
sessionId: sessionId2
|
|
31395
32120
|
});
|
|
31396
32121
|
await record.view.webContents.loadURL("about:blank");
|
|
31397
32122
|
await this.cdp.attach(record.view.webContents);
|
|
31398
32123
|
this.onChanged();
|
|
32124
|
+
return record;
|
|
32125
|
+
}
|
|
32126
|
+
/** Main owns this short-lived UI focus fact; it conveys no page capability. */
|
|
32127
|
+
chordFocus = false;
|
|
32128
|
+
onChordFocusChanged;
|
|
32129
|
+
/** An explicit tab id fences queued chrome intents: a switch between key
|
|
32130
|
+
* delivery and IPC must never search/zoom the newly active tab instead. */
|
|
32131
|
+
async controlPage(tabId, action, query = "", forward = true, next = false) {
|
|
32132
|
+
return this.registry.lane(tabId, async () => {
|
|
32133
|
+
const active = this.registry.activeTab;
|
|
32134
|
+
if (!active || active.tabId !== tabId || !active.presented || active.view.webContents.isDestroyed())
|
|
32135
|
+
throw new Error("The browser tab is no longer presented.");
|
|
32136
|
+
if (action === "open") this.pageControls.open(active);
|
|
32137
|
+
else if (action === "close") this.pageControls.clear();
|
|
32138
|
+
else if (action === "search")
|
|
32139
|
+
this.pageControls.search(active, query, forward, next);
|
|
32140
|
+
else this.pageControls.zoom(active, action);
|
|
32141
|
+
this.onChanged();
|
|
32142
|
+
return this.chromeState();
|
|
32143
|
+
});
|
|
32144
|
+
}
|
|
32145
|
+
setChordFocus(focused) {
|
|
32146
|
+
this.chordFocus = focused;
|
|
32147
|
+
this.onChordFocusChanged?.(focused);
|
|
32148
|
+
}
|
|
32149
|
+
/** Only user URLs survive a close, never a capability, page state or nonce.
|
|
32150
|
+
* Conversation attribution is retained only to find the appropriate scope. */
|
|
32151
|
+
closedUserTabs = [];
|
|
32152
|
+
rememberClosed(tabId) {
|
|
32153
|
+
const record = this.registry.get(tabId);
|
|
32154
|
+
if (!record || record.owner !== "user" || record.handedTo !== null) return;
|
|
32155
|
+
const url = record.view.webContents.getURL();
|
|
32156
|
+
try {
|
|
32157
|
+
if (!permittedScheme(new URL(url))) return;
|
|
32158
|
+
} catch {
|
|
32159
|
+
return;
|
|
32160
|
+
}
|
|
32161
|
+
this.closedUserTabs.push({ url, sessionId: record.homeSessionId });
|
|
32162
|
+
if (this.closedUserTabs.length > 10) this.closedUserTabs.shift();
|
|
32163
|
+
}
|
|
32164
|
+
clearChordState() {
|
|
32165
|
+
this.pageControls.clear();
|
|
32166
|
+
this.setChordFocus(false);
|
|
32167
|
+
this.closedUserTabs = [];
|
|
32168
|
+
}
|
|
32169
|
+
/**
|
|
32170
|
+
* Forget remembered closes. Called when the user clears browsing data or forgets
|
|
32171
|
+
* a site, because a closed tab's URL can carry a one-time token or name a page
|
|
32172
|
+
* the user just asked this app to erase: Cmd+Shift+T must not resurrect it
|
|
32173
|
+
* (review R3). `origin` filters to one site; omitted forgets every entry. Clearing
|
|
32174
|
+
* only cookies or only the cache leaves the stack alone: neither erases what the
|
|
32175
|
+
* user visited, and a logged-out reopen simply lands on the site's own login.
|
|
32176
|
+
*/
|
|
32177
|
+
forgetClosedTabs(origin) {
|
|
32178
|
+
this.closedUserTabs = origin ? this.closedUserTabs.filter((entry) => {
|
|
32179
|
+
try {
|
|
32180
|
+
return new URL(entry.url).origin !== origin;
|
|
32181
|
+
} catch {
|
|
32182
|
+
return false;
|
|
32183
|
+
}
|
|
32184
|
+
}) : [];
|
|
32185
|
+
}
|
|
32186
|
+
async reopenClosed(sessionId2) {
|
|
32187
|
+
const index = this.closedUserTabs.findLastIndex(
|
|
32188
|
+
(entry2) => sessionId2 === null || entry2.sessionId === sessionId2
|
|
32189
|
+
);
|
|
32190
|
+
if (index < 0) return this.chromeState();
|
|
32191
|
+
const [entry] = this.closedUserTabs.splice(index, 1);
|
|
32192
|
+
const record = await this.createUserTab(sessionId2 ?? entry.sessionId);
|
|
32193
|
+
await record.view.webContents.loadURL(entry.url);
|
|
32194
|
+
this.onChanged();
|
|
31399
32195
|
return this.chromeState();
|
|
31400
32196
|
}
|
|
31401
32197
|
closeTab(tabId) {
|
|
32198
|
+
this.rememberClosed(tabId);
|
|
31402
32199
|
this.dropReceipt(tabId);
|
|
31403
32200
|
this.loadFailures.delete(tabId);
|
|
31404
32201
|
this.registry.destroy(tabId);
|
|
@@ -31425,6 +32222,7 @@ class BrowserHost {
|
|
|
31425
32222
|
closeTabs(intent) {
|
|
31426
32223
|
const tabIds = intent.mode === "ids" ? intent.tabIds : this.registry.list().filter((record) => record.sessionId === intent.sessionId).map((record) => record.tabId);
|
|
31427
32224
|
for (const tabId of tabIds) {
|
|
32225
|
+
this.rememberClosed(tabId);
|
|
31428
32226
|
this.dropReceipt(tabId);
|
|
31429
32227
|
this.loadFailures.delete(tabId);
|
|
31430
32228
|
}
|
|
@@ -31689,8 +32487,10 @@ class BrowserHost {
|
|
|
31689
32487
|
this.onChanged();
|
|
31690
32488
|
return this.chromeState();
|
|
31691
32489
|
}
|
|
31692
|
-
reloadActive() {
|
|
31693
|
-
this.registry.activeTab?.view.webContents
|
|
32490
|
+
reloadActive(hard = false) {
|
|
32491
|
+
const contents = this.registry.activeTab?.view.webContents;
|
|
32492
|
+
if (hard && contents?.reloadIgnoringCache) contents.reloadIgnoringCache();
|
|
32493
|
+
else contents?.reload();
|
|
31694
32494
|
return this.chromeState();
|
|
31695
32495
|
}
|
|
31696
32496
|
stopActive() {
|
|
@@ -31721,6 +32521,8 @@ class BrowserHost {
|
|
|
31721
32521
|
* sees the nonce: it travels to the session through `tabs`, which is what keeps
|
|
31722
32522
|
* this the one authority transfer rather than an exposure (design 6.3, 11.7). */
|
|
31723
32523
|
handOver(tabId, sessionId2) {
|
|
32524
|
+
const record = this.registry.get(tabId);
|
|
32525
|
+
if (record) this.pageControls.prepareAgent(record);
|
|
31724
32526
|
this.dropReceipt(tabId);
|
|
31725
32527
|
this.registry.handOver(tabId, sessionId2);
|
|
31726
32528
|
this.onChanged();
|
|
@@ -31784,6 +32586,7 @@ class BrowserHost {
|
|
|
31784
32586
|
const origin = safeHttpUrl(rawOrigin).origin;
|
|
31785
32587
|
const removed = this.approvals.revokeOrigin(origin);
|
|
31786
32588
|
await this.forgetSiteData(origin);
|
|
32589
|
+
this.forgetClosedTabs(origin);
|
|
31787
32590
|
this.log(`[browser] forgot ${origin}: ${removed} approval(s) revoked`);
|
|
31788
32591
|
this.onChanged();
|
|
31789
32592
|
return { origin, removed, ...this.chromeState() };
|
|
@@ -32624,6 +33427,10 @@ async function startWithRetries(options) {
|
|
|
32624
33427
|
}
|
|
32625
33428
|
const BROWSER_IPC_CHANNELS = [
|
|
32626
33429
|
"browser-state",
|
|
33430
|
+
"browser-set-chord-focus",
|
|
33431
|
+
"browser-page-control",
|
|
33432
|
+
"browser-reopen-tab",
|
|
33433
|
+
"browser-focus-page",
|
|
32627
33434
|
"browser-new-tab",
|
|
32628
33435
|
"browser-close-tab",
|
|
32629
33436
|
"browser-close-tabs",
|
|
@@ -32713,7 +33520,43 @@ function registerBrowserIpc(options) {
|
|
|
32713
33520
|
}
|
|
32714
33521
|
return host.navigateActive(url.trim());
|
|
32715
33522
|
});
|
|
32716
|
-
electron.ipcMain.handle(
|
|
33523
|
+
electron.ipcMain.handle(
|
|
33524
|
+
"browser-page-control",
|
|
33525
|
+
(event, tabId, action, query, forward, next) => {
|
|
33526
|
+
const host = authorize(event);
|
|
33527
|
+
if (typeof action !== "string" || !["open", "close", "search", "in", "out", "reset"].includes(action))
|
|
33528
|
+
throw new Error("Invalid page control action.");
|
|
33529
|
+
if (typeof query !== "string" || query.length > 4096 || typeof forward !== "boolean" || typeof next !== "boolean")
|
|
33530
|
+
throw new Error("Invalid page search input.");
|
|
33531
|
+
return host.controlPage(
|
|
33532
|
+
numberOrThrow(tabId, "tabId"),
|
|
33533
|
+
action,
|
|
33534
|
+
query,
|
|
33535
|
+
forward,
|
|
33536
|
+
next
|
|
33537
|
+
);
|
|
33538
|
+
}
|
|
33539
|
+
);
|
|
33540
|
+
electron.ipcMain.handle("browser-set-chord-focus", (event, focused) => {
|
|
33541
|
+
const host = authorize(event);
|
|
33542
|
+
if (typeof focused !== "boolean")
|
|
33543
|
+
throw new Error("Browser focus must be a boolean.");
|
|
33544
|
+
host.setChordFocus(focused);
|
|
33545
|
+
});
|
|
33546
|
+
electron.ipcMain.handle(
|
|
33547
|
+
"browser-reopen-tab",
|
|
33548
|
+
(event, sessionId2) => authorize(event).reopenClosed(optionalConversationOrThrow(sessionId2))
|
|
33549
|
+
);
|
|
33550
|
+
electron.ipcMain.handle("browser-focus-page", (event) => {
|
|
33551
|
+
authorize(event);
|
|
33552
|
+
options.focusPage?.();
|
|
33553
|
+
});
|
|
33554
|
+
electron.ipcMain.handle("browser-reload", (event, hard) => {
|
|
33555
|
+
const host = authorize(event);
|
|
33556
|
+
if (hard !== void 0 && typeof hard !== "boolean")
|
|
33557
|
+
throw new Error("Hard reload must be a boolean.");
|
|
33558
|
+
return host.reloadActive(hard === true);
|
|
33559
|
+
});
|
|
32717
33560
|
electron.ipcMain.handle("browser-stop", (event) => authorize(event).stopActive());
|
|
32718
33561
|
electron.ipcMain.handle("browser-history", (event, direction) => {
|
|
32719
33562
|
const host = authorize(event);
|
|
@@ -32798,11 +33641,12 @@ function registerBrowserIpc(options) {
|
|
|
32798
33641
|
return host.forgetSite(origin.trim());
|
|
32799
33642
|
});
|
|
32800
33643
|
electron.ipcMain.handle("browser-clear-data", async (event, what) => {
|
|
32801
|
-
authorize(event);
|
|
33644
|
+
const host = authorize(event);
|
|
32802
33645
|
if (what !== "cookies" && what !== "cache" && what !== "everything") {
|
|
32803
33646
|
throw new Error("Unsupported clear-data request.");
|
|
32804
33647
|
}
|
|
32805
33648
|
await options.clearData(what);
|
|
33649
|
+
if (what === "everything") host.forgetClosedTabs();
|
|
32806
33650
|
options.log(`[browser] cleared browsing data: ${what}`);
|
|
32807
33651
|
return { cleared: what };
|
|
32808
33652
|
});
|
|
@@ -34595,6 +35439,22 @@ function refusesNavigation(rawUrl) {
|
|
|
34595
35439
|
}
|
|
34596
35440
|
}
|
|
34597
35441
|
let activeHost = null;
|
|
35442
|
+
function routeBrowserZoomInput(event, input) {
|
|
35443
|
+
const candidate = browserChordIntent(
|
|
35444
|
+
{ ...input, isAutoRepeat: false, isComposing: false },
|
|
35445
|
+
process.platform
|
|
35446
|
+
);
|
|
35447
|
+
if (!candidate?.startsWith("zoom-") || !activeHost) return false;
|
|
35448
|
+
return activeHost.chords.input(
|
|
35449
|
+
event,
|
|
35450
|
+
input,
|
|
35451
|
+
"chrome",
|
|
35452
|
+
activeHost.host.chordFocus
|
|
35453
|
+
);
|
|
35454
|
+
}
|
|
35455
|
+
function routeBrowserMenu(intent) {
|
|
35456
|
+
return activeHost?.chords.menu(intent) ?? false;
|
|
35457
|
+
}
|
|
34598
35458
|
let stopping = null;
|
|
34599
35459
|
function browserHostStopPending() {
|
|
34600
35460
|
return activeHost !== null || stopping !== null || starting !== null;
|
|
@@ -34662,6 +35522,12 @@ function startBrowserHost(options) {
|
|
|
34662
35522
|
expectedUrl: options.expectedUrl,
|
|
34663
35523
|
host: () => bindings.host?.() ?? null,
|
|
34664
35524
|
webauthn: () => bindings.webauthn?.() ?? null,
|
|
35525
|
+
focusPage: () => {
|
|
35526
|
+
const record = bindings.host?.()?.registry.activeTab;
|
|
35527
|
+
const target2 = record?.presented ? electron.webContents.fromId(record.view.webContents.id) : null;
|
|
35528
|
+
if (target2)
|
|
35529
|
+
focusBrowserChordTarget(options.window, target2, options.windowShow);
|
|
35530
|
+
},
|
|
34665
35531
|
availability: () => availability,
|
|
34666
35532
|
clearData: async (what) => {
|
|
34667
35533
|
if (!bindings.clearData)
|
|
@@ -34741,6 +35607,8 @@ async function initializeBrowserHost(options, bindings) {
|
|
|
34741
35607
|
// No `preload`: a driven page has no bridge to anything.
|
|
34742
35608
|
}
|
|
34743
35609
|
});
|
|
35610
|
+
view.webContents.setZoomMode("isolated");
|
|
35611
|
+
view.webContents.setZoomFactor(1);
|
|
34744
35612
|
window.contentView.addChildView(view);
|
|
34745
35613
|
view.setBounds(BACKGROUND_VIEWPORT);
|
|
34746
35614
|
view.setVisible(false);
|
|
@@ -34818,10 +35686,10 @@ async function initializeBrowserHost(options, bindings) {
|
|
|
34818
35686
|
contents.on("will-navigate", onWillNavigate);
|
|
34819
35687
|
contents.on("will-redirect", onWillNavigate);
|
|
34820
35688
|
contents.on("before-input-event", (event, input) => {
|
|
34821
|
-
const
|
|
34822
|
-
|
|
34823
|
-
|
|
34824
|
-
|
|
35689
|
+
const record = registry.get(tabId);
|
|
35690
|
+
const owns = record === registry.activeTab && record?.presented === true;
|
|
35691
|
+
const handled = chords.input(event, input, "page", owns);
|
|
35692
|
+
contents.setIgnoreMenuShortcuts(handled);
|
|
34825
35693
|
});
|
|
34826
35694
|
const notifyChrome = () => {
|
|
34827
35695
|
options.window.webContents.send("browser-state-changed");
|
|
@@ -35125,6 +35993,75 @@ async function initializeBrowserHost(options, bindings) {
|
|
|
35125
35993
|
facts: () => facts,
|
|
35126
35994
|
forgetSiteData: (origin) => clearOriginData(browserSession, origin)
|
|
35127
35995
|
});
|
|
35996
|
+
const chords = createBrowserChordRouter({
|
|
35997
|
+
platform: process.platform,
|
|
35998
|
+
ownsChrome: () => host.chordFocus,
|
|
35999
|
+
ownsPage: () => {
|
|
36000
|
+
const record = registry.activeTab;
|
|
36001
|
+
return Boolean(
|
|
36002
|
+
record?.presented && electron.webContents.getFocusedWebContents()?.id === record.view.webContents.id
|
|
36003
|
+
);
|
|
36004
|
+
},
|
|
36005
|
+
reload: (hard) => {
|
|
36006
|
+
host.reloadActive(hard);
|
|
36007
|
+
},
|
|
36008
|
+
zoom: (command) => {
|
|
36009
|
+
const tabId = registry.activeTab?.tabId;
|
|
36010
|
+
if (tabId !== void 0)
|
|
36011
|
+
void host.controlPage(tabId, command).catch(
|
|
36012
|
+
(error) => log2(
|
|
36013
|
+
`Page zoom refused: ${error instanceof Error ? error.message : "unavailable"}`
|
|
36014
|
+
)
|
|
36015
|
+
);
|
|
36016
|
+
},
|
|
36017
|
+
history: (direction) => {
|
|
36018
|
+
host.historyActive(direction);
|
|
36019
|
+
},
|
|
36020
|
+
send: (message) => options.window.webContents.send("browser-chord", message),
|
|
36021
|
+
focusChrome: () => focusBrowserChordTarget(
|
|
36022
|
+
options.window,
|
|
36023
|
+
options.window.webContents,
|
|
36024
|
+
options.windowShow
|
|
36025
|
+
)
|
|
36026
|
+
});
|
|
36027
|
+
const onChromeInput = (event, input) => {
|
|
36028
|
+
if (event.defaultPrevented) return;
|
|
36029
|
+
const handled = chords.input(event, input, "chrome", host.chordFocus);
|
|
36030
|
+
options.window.webContents.setIgnoreMenuShortcuts(handled);
|
|
36031
|
+
};
|
|
36032
|
+
const resetChordFocus = () => {
|
|
36033
|
+
host.setChordFocus(false);
|
|
36034
|
+
};
|
|
36035
|
+
host.onChordFocusChanged = (focused) => {
|
|
36036
|
+
if (!focused && !options.window.webContents.isDestroyed())
|
|
36037
|
+
options.window.webContents.setIgnoreMenuShortcuts(false);
|
|
36038
|
+
};
|
|
36039
|
+
options.window.webContents.on("before-input-event", onChromeInput);
|
|
36040
|
+
options.window.on("blur", resetChordFocus);
|
|
36041
|
+
options.window.on("closed", resetChordFocus);
|
|
36042
|
+
const resetOnNavigation = (details) => {
|
|
36043
|
+
if (details.isMainFrame && !details.isSameDocument) resetChordFocus();
|
|
36044
|
+
};
|
|
36045
|
+
options.window.webContents.on("did-start-navigation", resetOnNavigation);
|
|
36046
|
+
options.window.webContents.on("render-process-gone", resetChordFocus);
|
|
36047
|
+
const detachChords = () => {
|
|
36048
|
+
host.clearChordState();
|
|
36049
|
+
options.window.webContents.removeListener(
|
|
36050
|
+
"before-input-event",
|
|
36051
|
+
onChromeInput
|
|
36052
|
+
);
|
|
36053
|
+
options.window.removeListener("blur", resetChordFocus);
|
|
36054
|
+
options.window.removeListener("closed", resetChordFocus);
|
|
36055
|
+
options.window.webContents.removeListener(
|
|
36056
|
+
"did-start-navigation",
|
|
36057
|
+
resetOnNavigation
|
|
36058
|
+
);
|
|
36059
|
+
options.window.webContents.removeListener(
|
|
36060
|
+
"render-process-gone",
|
|
36061
|
+
resetChordFocus
|
|
36062
|
+
);
|
|
36063
|
+
};
|
|
36064
|
+
rollback.add(detachChords);
|
|
35128
36065
|
const recorded = readSession(sessionStore.filePath, log2);
|
|
35129
36066
|
host.restoreTabs(recorded);
|
|
35130
36067
|
if (recorded.length) {
|
|
@@ -35240,12 +36177,14 @@ async function initializeBrowserHost(options, bindings) {
|
|
|
35240
36177
|
`[browser] host on ${server.address}:${server.port} (proto ${facts.proto}), profile ${profileDir || "(in-memory)"}, agent tabs ${registry.agentTabCount()}/${8}, console ${consoleStartup.ok ? `on (${consoleStartup.counts().total} surface(s))` : `off (${consoleStartup.reason})`}`
|
|
35241
36178
|
);
|
|
35242
36179
|
const handle2 = {
|
|
36180
|
+
chords,
|
|
35243
36181
|
host,
|
|
35244
36182
|
port: server.port,
|
|
35245
36183
|
profileDir,
|
|
35246
36184
|
agentTabs: () => registry.agentTabCount(),
|
|
35247
36185
|
sessionCookies: () => restoreReport,
|
|
35248
36186
|
stop: async () => {
|
|
36187
|
+
detachChords();
|
|
35249
36188
|
const atStop = captureTabs(
|
|
35250
36189
|
registry.list(),
|
|
35251
36190
|
registry.activeTab?.tabId ?? null,
|
|
@@ -45492,25 +46431,6 @@ function configureAboutPanel() {
|
|
|
45492
46431
|
}
|
|
45493
46432
|
function createApplicationMenu() {
|
|
45494
46433
|
const isDev = Boolean(process.env.ELECTRON_RENDERER_URL);
|
|
45495
|
-
const zoomInHandler = () => {
|
|
45496
|
-
if (mainWindow) {
|
|
45497
|
-
const webContents2 = mainWindow.webContents;
|
|
45498
|
-
const currentZoom = webContents2.getZoomFactor();
|
|
45499
|
-
webContents2.setZoomFactor(currentZoom + 0.1);
|
|
45500
|
-
}
|
|
45501
|
-
};
|
|
45502
|
-
const zoomOutHandler = () => {
|
|
45503
|
-
if (mainWindow) {
|
|
45504
|
-
const webContents2 = mainWindow.webContents;
|
|
45505
|
-
const currentZoom = webContents2.getZoomFactor();
|
|
45506
|
-
webContents2.setZoomFactor(currentZoom - 0.1);
|
|
45507
|
-
}
|
|
45508
|
-
};
|
|
45509
|
-
const actualSizeHandler = () => {
|
|
45510
|
-
if (mainWindow) {
|
|
45511
|
-
mainWindow.webContents.setZoomFactor(1);
|
|
45512
|
-
}
|
|
45513
|
-
};
|
|
45514
46434
|
const template = [
|
|
45515
46435
|
{
|
|
45516
46436
|
label: "File",
|
|
@@ -45534,29 +46454,62 @@ function createApplicationMenu() {
|
|
|
45534
46454
|
label: "View",
|
|
45535
46455
|
submenu: [
|
|
45536
46456
|
{
|
|
45537
|
-
|
|
45538
|
-
|
|
46457
|
+
id: "app-reload",
|
|
46458
|
+
label: "Reload",
|
|
46459
|
+
accelerator: "CmdOrCtrl+R",
|
|
46460
|
+
click: (_item, target2) => runBrowserMenuAction(
|
|
46461
|
+
"reload",
|
|
46462
|
+
target2,
|
|
46463
|
+
mainWindow,
|
|
46464
|
+
routeBrowserMenu
|
|
46465
|
+
)
|
|
45539
46466
|
},
|
|
45540
46467
|
{
|
|
45541
|
-
|
|
45542
|
-
|
|
46468
|
+
id: "app-force-reload",
|
|
46469
|
+
label: "Force Reload",
|
|
46470
|
+
accelerator: "CmdOrCtrl+Shift+R",
|
|
46471
|
+
click: (_item, target2) => runBrowserMenuAction(
|
|
46472
|
+
"hard-reload",
|
|
46473
|
+
target2,
|
|
46474
|
+
mainWindow,
|
|
46475
|
+
routeBrowserMenu
|
|
46476
|
+
)
|
|
45543
46477
|
},
|
|
45544
46478
|
{ type: "separator" },
|
|
45545
46479
|
{
|
|
46480
|
+
id: "app-actual-size",
|
|
45546
46481
|
label: "Actual Size",
|
|
45547
|
-
accelerator: "CmdOrCtrl+
|
|
45548
|
-
click:
|
|
46482
|
+
accelerator: "CmdOrCtrl+0",
|
|
46483
|
+
click: (_item, target2) => {
|
|
46484
|
+
if (!(target2 instanceof electron.BrowserWindow)) return;
|
|
46485
|
+
if (target2 === mainWindow && routeBrowserMenu("zoom-reset")) return;
|
|
46486
|
+
target2.webContents.setZoomFactor(1);
|
|
46487
|
+
}
|
|
45549
46488
|
},
|
|
45550
46489
|
{
|
|
46490
|
+
id: "app-zoom-in",
|
|
45551
46491
|
label: "Zoom In",
|
|
45552
46492
|
accelerator: "CmdOrCtrl+Plus",
|
|
45553
46493
|
// On macOS, this often requires Shift as well (Cmd+Shift+=)
|
|
45554
|
-
click:
|
|
46494
|
+
click: (_item, target2) => {
|
|
46495
|
+
if (!(target2 instanceof electron.BrowserWindow)) return;
|
|
46496
|
+
if (target2 === mainWindow && routeBrowserMenu("zoom-in")) return;
|
|
46497
|
+
target2.webContents.setZoomFactor(
|
|
46498
|
+
target2.webContents.getZoomFactor() + 0.1
|
|
46499
|
+
);
|
|
46500
|
+
}
|
|
45555
46501
|
},
|
|
45556
46502
|
{
|
|
46503
|
+
id: "app-zoom-out",
|
|
45557
46504
|
label: "Zoom Out",
|
|
45558
46505
|
accelerator: "CmdOrCtrl+-",
|
|
45559
|
-
click:
|
|
46506
|
+
click: (_item, target2) => {
|
|
46507
|
+
if (!(target2 instanceof electron.BrowserWindow)) return;
|
|
46508
|
+
if (target2 === mainWindow && routeBrowserMenu("zoom-out")) return;
|
|
46509
|
+
target2.webContents.setZoomFactor(
|
|
46510
|
+
target2.webContents.getZoomFactor() - 0.1
|
|
46511
|
+
);
|
|
46512
|
+
}
|
|
45560
46513
|
},
|
|
45561
46514
|
{ type: "separator" },
|
|
45562
46515
|
{ role: "togglefullscreen" }
|
|
@@ -45582,10 +46535,40 @@ function createApplicationMenu() {
|
|
|
45582
46535
|
* `window-all-closed` path the red button takes, which is the one
|
|
45583
46536
|
* this change made safe for an install in flight.
|
|
45584
46537
|
*/
|
|
45585
|
-
{
|
|
46538
|
+
{
|
|
46539
|
+
id: "app-close",
|
|
46540
|
+
// One honest label for both owners: the SAME accelerator closes a
|
|
46541
|
+
// browser TAB while the browser has focus and the WINDOW elsewhere,
|
|
46542
|
+
// and a menu label cannot follow focus that lives in a page view
|
|
46543
|
+
// (UX r1 U4). The roles it replaced were "Close Window"/"Close".
|
|
46544
|
+
label: "Close Tab or Window",
|
|
46545
|
+
accelerator: "CmdOrCtrl+W",
|
|
46546
|
+
click: (_item, target2) => runBrowserMenuAction(
|
|
46547
|
+
"close-tab",
|
|
46548
|
+
target2,
|
|
46549
|
+
mainWindow,
|
|
46550
|
+
routeBrowserMenu
|
|
46551
|
+
)
|
|
46552
|
+
},
|
|
45586
46553
|
{ type: "separator" },
|
|
45587
46554
|
{ role: "window" }
|
|
45588
|
-
] : [
|
|
46555
|
+
] : [
|
|
46556
|
+
{
|
|
46557
|
+
id: "app-close",
|
|
46558
|
+
// One honest label for both owners: the SAME accelerator closes a
|
|
46559
|
+
// browser TAB while the browser has focus and the WINDOW elsewhere,
|
|
46560
|
+
// and a menu label cannot follow focus that lives in a page view
|
|
46561
|
+
// (UX r1 U4). The roles it replaced were "Close Window"/"Close".
|
|
46562
|
+
label: "Close Tab or Window",
|
|
46563
|
+
accelerator: "CmdOrCtrl+W",
|
|
46564
|
+
click: (_item, target2) => runBrowserMenuAction(
|
|
46565
|
+
"close-tab",
|
|
46566
|
+
target2,
|
|
46567
|
+
mainWindow,
|
|
46568
|
+
routeBrowserMenu
|
|
46569
|
+
)
|
|
46570
|
+
}
|
|
46571
|
+
]
|
|
45589
46572
|
]
|
|
45590
46573
|
},
|
|
45591
46574
|
{
|
|
@@ -46966,14 +47949,16 @@ electron.app.whenReady().then(async () => {
|
|
|
46966
47949
|
if (mainWindow) {
|
|
46967
47950
|
mainWindow.webContents.on("before-input-event", (event, input) => {
|
|
46968
47951
|
const isCmdOrCtrl = input.control || input.meta;
|
|
46969
|
-
if (
|
|
47952
|
+
if (event.defaultPrevented) return;
|
|
47953
|
+
if (routeBrowserZoomInput(event, input)) return;
|
|
47954
|
+
if (isCmdOrCtrl && input.type === "keyDown" && !input.alt && !input.isComposing) {
|
|
46970
47955
|
if (input.key === "+" || input.key === "=") {
|
|
46971
47956
|
zoomInFromEvent();
|
|
46972
47957
|
event.preventDefault();
|
|
46973
47958
|
} else if (input.key === "-") {
|
|
46974
47959
|
zoomOutFromEvent();
|
|
46975
47960
|
event.preventDefault();
|
|
46976
|
-
} else if (input.key === "
|
|
47961
|
+
} else if (input.key === "0") {
|
|
46977
47962
|
actualSizeFromEvent();
|
|
46978
47963
|
event.preventDefault();
|
|
46979
47964
|
}
|