local-operator-ui 0.42.1 → 0.42.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/out/main/index.js +600 -35
  2. package/out/preload/index.js +39 -1
  3. package/out/renderer/assets/{_basePickBy-bSYERMaj.js → _basePickBy-C-uJ_4_H.js} +1 -1
  4. package/out/renderer/assets/{_baseUniq-XXFAU1GI.js → _baseUniq-DsbREs0d.js} +1 -1
  5. package/out/renderer/assets/{agent-details-page-FzlOCzmB.js → agent-details-page-DqircW79.js} +2 -2
  6. package/out/renderer/assets/{agent-hub-page-V0BSbGBu.js → agent-hub-page-DW0ykyen.js} +2 -2
  7. package/out/renderer/assets/agents-page-DfghpQsj.js +7 -0
  8. package/out/renderer/assets/approvalsOverlay-BBr6f98F.css +1 -0
  9. package/out/renderer/assets/approvalsOverlay-Bb-_GvbK.js +1 -0
  10. package/out/renderer/assets/{arc-DJDaWivU.js → arc-BQFx264l.js} +1 -1
  11. package/out/renderer/assets/architectureDiagram-IEHRJDOE-CwEdIQqF.js +36 -0
  12. package/out/renderer/assets/{blockDiagram-JOT3LUYC-BGcgINKS.js → blockDiagram-JOT3LUYC-D2fu5TLW.js} +2 -2
  13. package/out/renderer/assets/{book-open-CTVKA12r.js → book-open-CXRG7kmQ.js} +1 -1
  14. package/out/renderer/assets/browser-page-BbCJ4Kqg.js +1 -0
  15. package/out/renderer/assets/browser-webauthn-prompt-BG_diNFj.js +1 -0
  16. package/out/renderer/assets/{building-2-Bky--3rC.js → building-2-BSZ0T67J.js} +1 -1
  17. package/out/renderer/assets/{c4Diagram-VJAJSXHY-Dxg4lYU_.js → c4Diagram-VJAJSXHY-B4F6kAAa.js} +2 -2
  18. package/out/renderer/assets/channel-DlvTVSBZ.js +1 -0
  19. package/out/renderer/assets/{chunk-4BMEZGHF-Bbfr_o8o.js → chunk-4BMEZGHF-Gvas_grr.js} +1 -1
  20. package/out/renderer/assets/{chunk-A2AXSNBT-CnzwrRQc.js → chunk-A2AXSNBT-W3cPWgPw.js} +1 -1
  21. package/out/renderer/assets/{chunk-AEK57VVT-DIq6FzSQ.js → chunk-AEK57VVT-DzoSrMRs.js} +1 -1
  22. package/out/renderer/assets/{chunk-D6G4REZN-BhQgOD8q.js → chunk-D6G4REZN-BkZWDlS1.js} +1 -1
  23. package/out/renderer/assets/{chunk-RZ5BOZE2-1bt5bhUU.js → chunk-RZ5BOZE2-gmzFxQwc.js} +1 -1
  24. package/out/renderer/assets/{chunk-XZIHB7SX-BV47b5FV.js → chunk-XZIHB7SX-BrbU5SuY.js} +1 -1
  25. package/out/renderer/assets/classDiagram-GIVACNV2-D6tpardR.js +1 -0
  26. package/out/renderer/assets/classDiagram-v2-COTLJTTW-D6tpardR.js +1 -0
  27. package/out/renderer/assets/clone-DAFDyYLt.js +1 -0
  28. package/out/renderer/assets/{console-mirror-CfrfbIAp.js → console-mirror-EdmGKGTJ.js} +2 -2
  29. package/out/renderer/assets/consoleCapture-DxGNu1ME.js +1 -0
  30. package/out/renderer/assets/{conversation-input-sync-DKNOMiIp.js → conversation-input-sync-DwcHJyBH.js} +253 -253
  31. package/out/renderer/assets/dagre-OKDRZEBW-DYuthQOj.js +4 -0
  32. package/out/renderer/assets/diagram-SSKATNLV-BloU54ZK.js +43 -0
  33. package/out/renderer/assets/diagram-VNBRO52H-BGuheJEu.js +24 -0
  34. package/out/renderer/assets/{erDiagram-Q7BY3M3F-jChbtQ8s.js → erDiagram-Q7BY3M3F-COWp-n7n.js} +2 -2
  35. package/out/renderer/assets/{error-boundary-CQf4hj53.js → error-boundary-DRSRl09t.js} +3 -3
  36. package/out/renderer/assets/{flowDiagram-4HSFHLVR-C-ETkl-L.js → flowDiagram-4HSFHLVR-D3etxTbr.js} +2 -2
  37. package/out/renderer/assets/{ganttDiagram-APWFNJXF-D42KlmKC.js → ganttDiagram-APWFNJXF-C85T-bBk.js} +2 -2
  38. package/out/renderer/assets/gitGraphDiagram-7IBYFJ6S-DR8rSdMP.js +65 -0
  39. package/out/renderer/assets/{graph-BdWT-wGp.js → graph-9RwMEpzp.js} +1 -1
  40. package/out/renderer/assets/{hash-C5NRsgoq.js → hash-DyArWvVk.js} +1 -1
  41. package/out/renderer/assets/{heart-B_TWxEVI.js → heart-wR8xxfkl.js} +1 -1
  42. package/out/renderer/assets/index-B6JvVM0y.js +1 -0
  43. package/out/renderer/assets/index-C-q9Saz2.js +7 -0
  44. package/out/renderer/assets/index-C4JJ-uY-.js +55 -0
  45. package/out/renderer/assets/index-DH2Wdo12.css +1 -0
  46. package/out/renderer/assets/index-XnmeTeQi.js +830 -0
  47. package/out/renderer/assets/infoDiagram-PH2N3AL5-B0dF0UUr.js +2 -0
  48. package/out/renderer/assets/installer-DLt9j6P5.js +1 -0
  49. package/out/renderer/assets/{journeyDiagram-U35MCT3I-Dvj6m4R3.js → journeyDiagram-U35MCT3I-Bi5S21jG.js} +2 -2
  50. package/out/renderer/assets/{kanban-definition-NDS4AKOZ-Dcs6Y93q.js → kanban-definition-NDS4AKOZ-3yXRNVxM.js} +4 -4
  51. package/out/renderer/assets/{layout--rr1tBJG.js → layout-V9S6bEAP.js} +1 -1
  52. package/out/renderer/assets/{legacy-agents-page-bX8ZD1oF.js → legacy-agents-page-DlXcMI3d.js} +8 -8
  53. package/out/renderer/assets/library-page-Z2ycLLgX.js +157 -0
  54. package/out/renderer/assets/{mermaid.core-DlGo2U0C.js → mermaid.core-1ZZxL94e.js} +5 -5
  55. package/out/renderer/assets/mesh-page-VN5YlOig.js +1 -0
  56. package/out/renderer/assets/messages-UU62OcMx.js +3 -0
  57. package/out/renderer/assets/mindmap-definition-ALO5MXBD-BqNXJ5iP.js +95 -0
  58. package/out/renderer/assets/mini-BpZoZmwc.js +1 -0
  59. package/out/renderer/assets/{notebook-pen-BhmcgRiW.js → notebook-pen-BRGyo6qe.js} +1 -1
  60. package/out/renderer/assets/org-access-DL4sfC5o.js +1 -0
  61. package/out/renderer/assets/{org-surface-gate-BpVvnvxX.js → org-surface-gate-DzVZOCgc.js} +1 -1
  62. package/out/renderer/assets/{page-header-rgKs_qEp.js → page-header-CsJwSRXG.js} +1 -1
  63. package/out/renderer/assets/path-utils-Bslmu3x5.js +58 -0
  64. package/out/renderer/assets/pieDiagram-IB7DONF6-FSpbUZa3.js +30 -0
  65. package/out/renderer/assets/{projects-page-BQd1Mkfd.js → projects-page-CyfiN3pO.js} +2 -2
  66. package/out/renderer/assets/{publication-validation-DyFQAbl6.js → publication-validation-C5mxv51G.js} +1 -1
  67. package/out/renderer/assets/{quadrantDiagram-7GDLP6J5-wWLUIv_7.js → quadrantDiagram-7GDLP6J5-Dl1CxU0W.js} +2 -2
  68. package/out/renderer/assets/{radar-MK3ICKWK-DD77Iyne.js → radar-MK3ICKWK-BSuQo5KN.js} +1 -1
  69. package/out/renderer/assets/radient-auth-buttons-BZe_OZtZ.js +1 -0
  70. package/out/renderer/assets/{requirementDiagram-KVF5MWMF-Bu415aDm.js → requirementDiagram-KVF5MWMF-t8Dz-7Kp.js} +2 -2
  71. package/out/renderer/assets/sankeyDiagram-QLVOVGJD-q0DLuZVj.js +10 -0
  72. package/out/renderer/assets/{schedules-page-BbKsER5C.js → schedules-page-6TSgJ8gq.js} +2 -2
  73. package/out/renderer/assets/{sequenceDiagram-X6HHIX6F-BTO-WEKG.js → sequenceDiagram-X6HHIX6F-CXU3BFHj.js} +2 -2
  74. package/out/renderer/assets/{settings-page-qICF0iah.js → settings-page-Cr3wqA95.js} +3 -3
  75. package/out/renderer/assets/smartart-sc0B4J9V.js +1 -0
  76. package/out/renderer/assets/stateDiagram-DGXRK772-BSXJAxkU.js +1 -0
  77. package/out/renderer/assets/stateDiagram-v2-YXO3MK2T-TeEHL_JN.js +1 -0
  78. package/out/renderer/assets/{team-bridge-page-bhH2QlXH.js → team-bridge-page-1N2Nu5OI.js} +2 -2
  79. package/out/renderer/assets/{timeline-definition-BDJGKUSR-DcGupo97.js → timeline-definition-BDJGKUSR-BJBU8NFV.js} +2 -2
  80. package/out/renderer/assets/{use-download-agent-mutation-DFoPvSHB.js → use-download-agent-mutation-DSNRIoxY.js} +2 -2
  81. package/out/renderer/assets/{use-session-snapshot-BTmPQFBS.js → use-session-snapshot-Cv3MIHrU.js} +1 -1
  82. package/out/renderer/assets/{xychartDiagram-VJFVF3MP-Bqjodw42.js → xychartDiagram-VJFVF3MP-CFJkfmsL.js} +5 -5
  83. package/out/renderer/browser-approvals-overlay.html +40 -0
  84. package/out/renderer/console-capture.html +6 -5
  85. package/out/renderer/index.html +8 -7
  86. package/out/renderer/installer.html +5 -4
  87. package/out/renderer/mini.html +8 -7
  88. package/package.json +7 -5
  89. package/out/renderer/assets/agents-page-DHu2xkX8.js +0 -7
  90. package/out/renderer/assets/architectureDiagram-IEHRJDOE-BnQwEGXh.js +0 -36
  91. package/out/renderer/assets/browser-page-DFFwHX_q.js +0 -1
  92. package/out/renderer/assets/browser-webauthn-prompt-BWCI9wPS.js +0 -1
  93. package/out/renderer/assets/channel-EkPte-cJ.js +0 -1
  94. package/out/renderer/assets/classDiagram-GIVACNV2-CFmWhsn7.js +0 -1
  95. package/out/renderer/assets/classDiagram-v2-COTLJTTW-CFmWhsn7.js +0 -1
  96. package/out/renderer/assets/clone-kXBnCGzD.js +0 -1
  97. package/out/renderer/assets/consoleCapture-BFG3Xbps.js +0 -1
  98. package/out/renderer/assets/dagre-OKDRZEBW-DA1nw5sl.js +0 -4
  99. package/out/renderer/assets/diagram-SSKATNLV-CVVTgWt7.js +0 -43
  100. package/out/renderer/assets/diagram-VNBRO52H-DHTfzrp0.js +0 -24
  101. package/out/renderer/assets/gitGraphDiagram-7IBYFJ6S-P9nmqR2u.js +0 -65
  102. package/out/renderer/assets/index-CdcfcuWL.js +0 -7
  103. package/out/renderer/assets/index-CgLFXaCJ.js +0 -57
  104. package/out/renderer/assets/index-CjtdK8OG.css +0 -1
  105. package/out/renderer/assets/index-DiHe1x_2.js +0 -830
  106. package/out/renderer/assets/index-uHBz6pD4.js +0 -1
  107. package/out/renderer/assets/infoDiagram-PH2N3AL5-CGwg5naH.js +0 -2
  108. package/out/renderer/assets/installer-BPsqzY3G.js +0 -1
  109. package/out/renderer/assets/library-page-DeVhJsuP.js +0 -157
  110. package/out/renderer/assets/mesh-page-BOHX8DXw.js +0 -1
  111. package/out/renderer/assets/mindmap-definition-ALO5MXBD-D2k6gjX2.js +0 -95
  112. package/out/renderer/assets/mini-D58TB08i.js +0 -1
  113. package/out/renderer/assets/org-access-BIqG4bO9.js +0 -1
  114. package/out/renderer/assets/path-utils-Ch7GC1fh.js +0 -58
  115. package/out/renderer/assets/pieDiagram-IB7DONF6-TkoS-yEQ.js +0 -30
  116. package/out/renderer/assets/radient-auth-buttons-DOUeYctr.js +0 -1
  117. package/out/renderer/assets/sankeyDiagram-QLVOVGJD-DicsIJ4H.js +0 -10
  118. package/out/renderer/assets/smartart-drXgC4cZ.js +0 -1
  119. package/out/renderer/assets/stateDiagram-DGXRK772-DRBkBLBL.js +0 -1
  120. package/out/renderer/assets/stateDiagram-v2-YXO3MK2T-CCFNyg2W.js +0 -1
package/out/main/index.js CHANGED
@@ -317,7 +317,45 @@ const importRequestFields = {
317
317
  const modelSelection = zod.z.object({
318
318
  provider: zod.z.string().min(1).max(128),
319
319
  model_id: zod.z.string().min(1).max(512),
320
- reasoning_effort: zod.z.string().min(1).max(64).nullable()
320
+ reasoning_effort: zod.z.string().min(1).max(64).nullable(),
321
+ /*
322
+ * The FAST dial the conversation is born on (issue #1265), when the pane's
323
+ * `/fast` picker asked for one.
324
+ *
325
+ * OPTIONAL, so the three orders a request can carry stay distinguishable:
326
+ * an absent key is "nobody asked" - the body every caller sent before this
327
+ * field existed - `true` asks for the tier, and `false` is the user picking
328
+ * `Off` (the spec's own default, so it moves no byte on a backend that
329
+ * carries the field). It is not DERIVED from the resolved spec here: a
330
+ * renderer that copied the resolved dial onto every draft would assert a
331
+ * choice nobody made, and the authority for "may this model be served
332
+ * fast" is the backend's own `supports_fast_mode` clamp, which refuses
333
+ * `true` with a 422.
334
+ *
335
+ * THIS IS THE RENDERER HALF OF A TWO-REPO CHANGE. The backend half is
336
+ * `DraftModel.fast_mode` in `local-operator` (damianvtran/local-operator#2848,
337
+ * `server/routes/desktop_sessions.py`), published as the capability
338
+ * `features.draft_fast` (`server/features.py`) - the key this renderer reads
339
+ * before it offers `/fast` on a draft (`DesktopFeature` in
340
+ * `desktop-hooks.ts`, `draftSelectionRoute` in `picker-registry.tsx`).
341
+ * VERIFY IT THERE, NOT BY DATE: the core's draft model is
342
+ * `extra="forbid"`, so a backend that does not advertise `draft_fast`
343
+ * refuses the WHOLE body - `422 {"detail": "The request has invalid
344
+ * fields."}` against a core without the field - taking the model and the
345
+ * effort rung down with the dial. A draft pick on such a backend is
346
+ * prevented at the route rather than attempted, and a request that still
347
+ * fails is REFUSED OUT LOUD by `FastPicker` (see `fastPickFailure`) and
348
+ * nothing is recorded on the pane. The field stays declared here because
349
+ * the draft route's own round trip is the one the backend must answer, and
350
+ * a renderer that had to be rewritten for it would be the second spelling
351
+ * this contract exists to prevent.
352
+ *
353
+ * `null` is accepted because a backend that carries the field spells "no
354
+ * choice" that way (`fast_mode: bool | None`, the spelling this contract's
355
+ * `null` mirrors), and the two spellings must mean one thing to every
356
+ * reader.
357
+ */
358
+ fast_mode: zod.z.boolean().nullable().optional()
321
359
  }).strict();
322
360
  const profileFields = zod.z.object({
323
361
  kind: zod.z.enum(["role", "specialist"]).optional(),
@@ -30081,6 +30119,9 @@ class AddressOverlayController {
30081
30119
  lastSeq;
30082
30120
  shownSeq;
30083
30121
  lastProjection;
30122
+ /** A sanitized v2 projection whose anchor preceded the matching page rect.
30123
+ * It can resize a hidden reusable child on the next layout, never re-open it. */
30124
+ pendingResizeProjection;
30084
30125
  /** The rectangle last applied for a projection. `onLayout`'s unchanged-key
30085
30126
  * re-assert uses THIS, never the S1 top-strip rule: an S2 child sits at the
30086
30127
  * dock, and re-raising it with the S1 rectangle would move the list. */
@@ -30161,6 +30202,7 @@ class AddressOverlayController {
30161
30202
  this.lastSeq = 0;
30162
30203
  this.shownSeq = -1;
30163
30204
  this.lastProjection = null;
30205
+ this.pendingResizeProjection = null;
30164
30206
  this.lastAppliedBounds = null;
30165
30207
  this.lastMeasurement = null;
30166
30208
  this.themeFact = "absent";
@@ -30218,6 +30260,7 @@ class AddressOverlayController {
30218
30260
  else this.suspendPresentation();
30219
30261
  return;
30220
30262
  }
30263
+ this.resizeDeferredChild(next);
30221
30264
  this.hide("layout");
30222
30265
  if (this.product && previousKey !== "none") this.emitDismiss("layout");
30223
30266
  return;
@@ -30562,6 +30605,7 @@ class AddressOverlayController {
30562
30605
  const projection = parsed.projection;
30563
30606
  this.themeFact = projection.themeFact;
30564
30607
  if (!projection.visible) {
30608
+ this.pendingResizeProjection = null;
30565
30609
  if (projection.seq > this.lastSeq) this.lastSeq = projection.seq;
30566
30610
  this.hide("projection_hidden");
30567
30611
  return { accepted: true, shown: false, reason: null, bounds: null };
@@ -30615,10 +30659,14 @@ class AddressOverlayController {
30615
30659
  );
30616
30660
  if (bounds === null) {
30617
30661
  const tooNarrow = projection.v === 2 && projection.anchor.width < ADDRESS_LIST_MIN_WIDTH_DIP;
30662
+ if (projection.v === 2 && !tooNarrow) {
30663
+ this.pendingResizeProjection = projection;
30664
+ }
30618
30665
  return this.refuseProjection(
30619
30666
  tooNarrow ? "anchor_too_narrow" : "anchor_inconsistent"
30620
30667
  );
30621
30668
  }
30669
+ this.pendingResizeProjection = null;
30622
30670
  this.generation += 1;
30623
30671
  const generation = this.generation;
30624
30672
  this.boundTabId = projection.tabId;
@@ -30681,6 +30729,29 @@ class AddressOverlayController {
30681
30729
  this.hiddenReason = null;
30682
30730
  return { accepted: true, shown: true, reason: null, bounds };
30683
30731
  }
30732
+ resizeDeferredChild(snapshot2) {
30733
+ const projection = this.pendingResizeProjection;
30734
+ this.pendingResizeProjection = null;
30735
+ if (this.state === "shown" || projection === null || projection.v !== 2 || projection.tabId !== snapshot2.activeTabId || !snapshot2.presented || snapshot2.contentRect === null) {
30736
+ return;
30737
+ }
30738
+ const bounds = addressListBoundsV2For(
30739
+ projection.anchor,
30740
+ snapshot2.contentRect,
30741
+ projection.view,
30742
+ this.ownerSize()
30743
+ );
30744
+ const view = this.view;
30745
+ if (bounds === null || !view || !this.viewUsable(view)) return;
30746
+ try {
30747
+ const wasVisible = view.getVisible();
30748
+ if (!wasVisible) view.setVisible(true);
30749
+ view.setBounds(bounds);
30750
+ if (!wasVisible) view.setVisible(false);
30751
+ } catch (error) {
30752
+ this.releaseChild(`layout_error:${String(error)}`);
30753
+ }
30754
+ }
30684
30755
  refuseProjection(reason, bounds = null) {
30685
30756
  this.lastRejected = reason;
30686
30757
  this.drop(reason);
@@ -32054,6 +32125,408 @@ class ApprovalStore {
32054
32125
  );
32055
32126
  }
32056
32127
  }
32128
+ const APPROVALS_CARD_MAX_WIDTH = 352;
32129
+ const APPROVALS_CARD_MAX_HEIGHT = 480;
32130
+ const APPROVALS_CARD_MIN_HEIGHT = 96;
32131
+ const APPROVALS_CARD_INSET = 8;
32132
+ const APPROVALS_CARD_PAD = 8;
32133
+ function integer(value) {
32134
+ return Math.round(value);
32135
+ }
32136
+ function approvalsCardBoundsFor(input) {
32137
+ const pad = input.opaque === true ? 0 : APPROVALS_CARD_PAD;
32138
+ const inset = input.opaque === true ? 0 : APPROVALS_CARD_INSET;
32139
+ const content = input.contentRect;
32140
+ if (!Number.isFinite(content.x) || !Number.isFinite(content.y) || !Number.isFinite(content.width) || !Number.isFinite(content.height) || content.width <= 0 || content.height <= 0) {
32141
+ return null;
32142
+ }
32143
+ const width = Math.min(
32144
+ APPROVALS_CARD_MAX_WIDTH,
32145
+ Math.floor(content.width - 2 * pad)
32146
+ );
32147
+ if (width <= 0) return null;
32148
+ const ceiling = Math.min(
32149
+ APPROVALS_CARD_MAX_HEIGHT,
32150
+ Math.floor(content.height - 2 * pad)
32151
+ );
32152
+ if (ceiling < APPROVALS_CARD_MIN_HEIGHT) return null;
32153
+ const natural = Number.isFinite(input.naturalHeight) ? input.naturalHeight : APPROVALS_CARD_MIN_HEIGHT;
32154
+ const height = Math.min(
32155
+ ceiling,
32156
+ Math.max(APPROVALS_CARD_MIN_HEIGHT, Math.ceil(natural))
32157
+ );
32158
+ const viewWidth = width + 2 * pad;
32159
+ const viewHeight = height + 2 * pad;
32160
+ const viewX = integer(content.x + content.width - inset - width - pad);
32161
+ const viewY = integer(content.y + content.height - inset - height - pad);
32162
+ const view = {
32163
+ x: viewX,
32164
+ y: viewY,
32165
+ width: viewWidth,
32166
+ height: viewHeight
32167
+ };
32168
+ if (view.x < content.x || view.y < content.y || view.x + view.width > content.x + content.width || view.y + view.height > content.y + content.height) {
32169
+ return null;
32170
+ }
32171
+ return {
32172
+ view,
32173
+ card: {
32174
+ x: view.x + pad,
32175
+ y: view.y + pad,
32176
+ width,
32177
+ height
32178
+ },
32179
+ width,
32180
+ height,
32181
+ pad
32182
+ };
32183
+ }
32184
+ const APPROVALS_OVERLAY_S6A_ENV = "LOCAL_OPERATOR_UI_BROWSER_APPROVALS_OVERLAY_S6A";
32185
+ const TRANSPARENT = "#00000000";
32186
+ const OPAQUE = "#1b1f24";
32187
+ function approvalsOverlayEnabled(env) {
32188
+ return env[APPROVALS_OVERLAY_S6A_ENV] === "1";
32189
+ }
32190
+ function approvalsExpiryDelay(entries, now = Date.now()) {
32191
+ if (entries.length === 0) return null;
32192
+ return Math.max(
32193
+ 0,
32194
+ Math.min(...entries.map((entry) => entry.expiresAt)) - now
32195
+ );
32196
+ }
32197
+ function approvalsDocumentUrl(documentUrl, count, theme, opaque) {
32198
+ try {
32199
+ const url = new URL(documentUrl);
32200
+ if (count > 0) url.searchParams.set("count", String(count));
32201
+ url.searchParams.set("theme", theme);
32202
+ if (opaque) url.searchParams.set("opaque", "1");
32203
+ return url.toString();
32204
+ } catch {
32205
+ return documentUrl;
32206
+ }
32207
+ }
32208
+ class ApprovalsOverlayController {
32209
+ window;
32210
+ documentUrl;
32211
+ opaque;
32212
+ theme;
32213
+ log;
32214
+ view;
32215
+ childListeners;
32216
+ pending;
32217
+ ready;
32218
+ visible;
32219
+ failedReason;
32220
+ disposed;
32221
+ naturalHeight;
32222
+ layout;
32223
+ bounds;
32224
+ constructor(deps) {
32225
+ this.window = deps.window;
32226
+ this.documentUrl = deps.documentUrl;
32227
+ this.opaque = deps.opaque === true;
32228
+ this.theme = deps.theme ?? "dark";
32229
+ this.log = deps.log ?? (() => {
32230
+ });
32231
+ this.view = null;
32232
+ this.childListeners = [];
32233
+ this.pending = 0;
32234
+ this.ready = false;
32235
+ this.visible = false;
32236
+ this.failedReason = null;
32237
+ this.disposed = false;
32238
+ this.naturalHeight = APPROVALS_CARD_MIN_HEIGHT;
32239
+ this.layout = {
32240
+ presented: false,
32241
+ contentRect: null,
32242
+ revision: 0
32243
+ };
32244
+ this.bounds = null;
32245
+ this.ensureChild();
32246
+ }
32247
+ /** The live queue's count. Zero hides; a positive count auto-presents. */
32248
+ setPending(count) {
32249
+ if (this.disposed) return;
32250
+ this.pending = Math.max(0, Math.floor(Number.isFinite(count) ? count : 0));
32251
+ if (this.pending === 0) {
32252
+ this.hide();
32253
+ return;
32254
+ }
32255
+ this.updateCount();
32256
+ this.maybeShow();
32257
+ }
32258
+ /** The registry's copied layout snapshot, after every page layout pass. */
32259
+ onLayout(snapshot2) {
32260
+ if (this.disposed) return;
32261
+ this.layout = {
32262
+ presented: snapshot2.presented,
32263
+ contentRect: snapshot2.contentRect ? { ...snapshot2.contentRect } : null,
32264
+ revision: snapshot2.revision
32265
+ };
32266
+ if (!snapshot2.presented || !snapshot2.contentRect) {
32267
+ this.hide();
32268
+ return;
32269
+ }
32270
+ if (this.pending > 0) this.maybeShow();
32271
+ }
32272
+ facts() {
32273
+ const view = this.view;
32274
+ const children = this.window.isDestroyed() ? [] : this.window.contentView.children;
32275
+ const index = view ? children.indexOf(view) : -1;
32276
+ let focused = null;
32277
+ try {
32278
+ focused = electron.webContents.getFocusedWebContents()?.id ?? null;
32279
+ } catch {
32280
+ focused = null;
32281
+ }
32282
+ return {
32283
+ pending: this.pending,
32284
+ presented: this.layout.presented,
32285
+ contentRect: this.layout.contentRect,
32286
+ ready: this.ready,
32287
+ visible: this.visible,
32288
+ failedReason: this.failedReason,
32289
+ bounds: this.bounds,
32290
+ childIndex: index,
32291
+ childCount: children.length,
32292
+ childWebContentsId: view ? view.webContents.id : null,
32293
+ focusedWebContentsId: focused,
32294
+ documentUrl: this.documentUrl,
32295
+ opaque: this.opaque
32296
+ };
32297
+ }
32298
+ dispose(reason = "dispose") {
32299
+ if (this.disposed) return;
32300
+ this.disposed = true;
32301
+ this.visible = false;
32302
+ this.ready = false;
32303
+ this.releaseView(reason);
32304
+ }
32305
+ ensureChild() {
32306
+ if (this.view || this.failedReason !== null || this.disposed) return;
32307
+ this.createChild();
32308
+ }
32309
+ maybeShow() {
32310
+ if (this.disposed || this.failedReason !== null || this.pending <= 0 || !this.layout.presented || !this.layout.contentRect) {
32311
+ this.hide();
32312
+ return;
32313
+ }
32314
+ this.ensureChild();
32315
+ if (!this.view || !this.ready) return;
32316
+ this.applyBounds();
32317
+ }
32318
+ applyBounds() {
32319
+ const view = this.view;
32320
+ if (!view || !this.layout.contentRect) return;
32321
+ const bounds = approvalsCardBoundsFor({
32322
+ contentRect: this.layout.contentRect,
32323
+ naturalHeight: this.naturalHeight,
32324
+ opaque: this.opaque
32325
+ });
32326
+ this.bounds = bounds;
32327
+ if (!bounds) {
32328
+ this.hide();
32329
+ return;
32330
+ }
32331
+ try {
32332
+ const current = view.getBounds();
32333
+ if (current.width !== bounds.view.width || current.height !== bounds.view.height) {
32334
+ this.rebuildAt(bounds);
32335
+ return;
32336
+ }
32337
+ view.setBounds(bounds.view);
32338
+ const children = this.window.contentView.children;
32339
+ if (children[children.length - 1] !== view) {
32340
+ this.window.contentView.addChildView(view);
32341
+ }
32342
+ view.setVisible(true);
32343
+ this.visible = true;
32344
+ } catch (error) {
32345
+ this.fail(`bounds_apply_failed:${String(error)}`);
32346
+ }
32347
+ }
32348
+ rebuildAt(bounds) {
32349
+ this.releaseView("resize");
32350
+ this.visible = false;
32351
+ this.ready = false;
32352
+ this.bounds = bounds;
32353
+ this.createChild();
32354
+ const view = this.view;
32355
+ if (!view) return;
32356
+ view.setBounds(bounds.view);
32357
+ view.setVisible(true);
32358
+ this.visible = true;
32359
+ }
32360
+ releaseView(reason) {
32361
+ const view = this.view;
32362
+ this.view = null;
32363
+ for (const remove of this.childListeners.splice(0)) remove();
32364
+ if (!view) return;
32365
+ try {
32366
+ if (!view.webContents.isDestroyed()) view.webContents.close();
32367
+ } catch {
32368
+ }
32369
+ try {
32370
+ this.window.contentView.removeChildView(view);
32371
+ } catch {
32372
+ }
32373
+ this.log(`[browser] approvals overlay child released: ${reason}`);
32374
+ }
32375
+ createChild() {
32376
+ let view;
32377
+ try {
32378
+ const partition = `approvals-overlay-${node_crypto.randomUUID()}`;
32379
+ const childSession = electron.session.fromPartition(partition);
32380
+ childSession.setPermissionRequestHandler(
32381
+ (_contents, _permission, callback) => callback(false)
32382
+ );
32383
+ childSession.setPermissionCheckHandler(() => false);
32384
+ childSession.on("will-download", (event) => {
32385
+ event.preventDefault();
32386
+ });
32387
+ view = new electron.WebContentsView({
32388
+ webPreferences: {
32389
+ partition,
32390
+ sandbox: true,
32391
+ contextIsolation: true,
32392
+ nodeIntegration: false,
32393
+ webSecurity: true,
32394
+ allowRunningInsecureContent: false,
32395
+ // The document's own module measures itself and paints the count;
32396
+ // there is still no preload, no exposed IPC and no focus path.
32397
+ javascript: true,
32398
+ backgroundThrottling: false
32399
+ }
32400
+ });
32401
+ view.webContents.setWindowOpenHandler(() => ({ action: "deny" }));
32402
+ const allow = approvalsDocumentUrl(
32403
+ this.documentUrl,
32404
+ this.pending,
32405
+ this.theme,
32406
+ this.opaque
32407
+ );
32408
+ const base = (() => {
32409
+ try {
32410
+ const url = new URL(allow);
32411
+ url.search = "";
32412
+ return url.toString();
32413
+ } catch {
32414
+ return allow;
32415
+ }
32416
+ })();
32417
+ view.webContents.on("will-navigate", (event, url) => {
32418
+ const target2 = url.split("?")[0];
32419
+ if (target2 !== base) event.preventDefault();
32420
+ });
32421
+ view.webContents.on("will-redirect", (event, url) => {
32422
+ const target2 = url.split("?")[0];
32423
+ if (target2 !== base) event.preventDefault();
32424
+ });
32425
+ view.setBackgroundColor(this.opaque ? OPAQUE : TRANSPARENT);
32426
+ this.window.contentView.addChildView(view);
32427
+ const initial = this.bounds?.view ?? {
32428
+ x: 0,
32429
+ y: 0,
32430
+ width: 0,
32431
+ height: 0
32432
+ };
32433
+ view.setBounds(initial);
32434
+ view.setVisible(this.bounds !== null);
32435
+ this.view = view;
32436
+ this.ready = false;
32437
+ const onFinish = () => {
32438
+ this.ready = true;
32439
+ this.measureAndShow();
32440
+ };
32441
+ const onFail = (_event, code, description) => {
32442
+ this.fail(`load_failed:${code}:${description}`);
32443
+ };
32444
+ view.webContents.on("did-finish-load", onFinish);
32445
+ view.webContents.on("did-fail-load", onFail);
32446
+ this.childListeners.push(
32447
+ () => view.webContents.removeListener("did-finish-load", onFinish)
32448
+ );
32449
+ this.childListeners.push(
32450
+ () => view.webContents.removeListener("did-fail-load", onFail)
32451
+ );
32452
+ void view.webContents.loadURL(allow).catch((error) => {
32453
+ this.fail(`load_rejected:${String(error)}`);
32454
+ });
32455
+ } catch (error) {
32456
+ this.fail(`child_create_failed:${String(error)}`);
32457
+ return;
32458
+ }
32459
+ }
32460
+ measureAndShow() {
32461
+ const view = this.view;
32462
+ if (!view || view.webContents.isDestroyed()) return;
32463
+ if (view.getBounds().width <= 0) {
32464
+ this.updateCount();
32465
+ this.maybeShow();
32466
+ return;
32467
+ }
32468
+ const measured = view.webContents.executeJavaScript(
32469
+ `new Promise((resolve) => {
32470
+ const read = () => {
32471
+ const el = document.getElementById('approvals-card');
32472
+ if (!el) { resolve(0); return; }
32473
+ /*
32474
+ * Read the UNCLAMPED height. The card's own max-height is the
32475
+ * viewport minus its insets, so measuring the clamped box would
32476
+ * return the provisional 96 DIP view's ceiling forever: a
32477
+ * circular size that never reaches the card's real height.
32478
+ */
32479
+ const previous = el.style.maxHeight;
32480
+ el.style.maxHeight = 'none';
32481
+ const height = el.getBoundingClientRect().height;
32482
+ el.style.maxHeight = previous;
32483
+ resolve(height);
32484
+ };
32485
+ if (document.readyState === 'complete') read();
32486
+ else addEventListener('load', read, { once: true });
32487
+ })`
32488
+ );
32489
+ const timer = new Promise((resolve) => {
32490
+ setTimeout(() => resolve(0), 1500);
32491
+ });
32492
+ void Promise.race([measured, timer]).then((height) => {
32493
+ if (this.view !== view) return;
32494
+ if (typeof height === "number" && Number.isFinite(height) && height > 0) {
32495
+ this.naturalHeight = height;
32496
+ }
32497
+ this.maybeShow();
32498
+ }).catch((error) => {
32499
+ if (this.view !== view) return;
32500
+ this.fail(`measure_failed:${String(error)}`);
32501
+ });
32502
+ this.updateCount();
32503
+ this.maybeShow();
32504
+ }
32505
+ updateCount() {
32506
+ const view = this.view;
32507
+ if (!view || view.webContents.isDestroyed()) return;
32508
+ void view.webContents.executeJavaScript(
32509
+ `(() => { window.__approvalsCard?.setCount(${this.pending}); })()`
32510
+ ).catch(() => {
32511
+ });
32512
+ }
32513
+ hide() {
32514
+ if (this.view) {
32515
+ try {
32516
+ this.view.setVisible(false);
32517
+ } catch {
32518
+ }
32519
+ }
32520
+ this.visible = false;
32521
+ }
32522
+ fail(reason) {
32523
+ if (this.failedReason !== null) return;
32524
+ this.failedReason = reason;
32525
+ this.hide();
32526
+ this.dispose("failed");
32527
+ this.log(`[browser] approvals overlay latched off: ${reason}`);
32528
+ }
32529
+ }
32057
32530
  function browserWindowForeground(window) {
32058
32531
  return !window.isDestroyed() && window.isVisible() && window.isFocused();
32059
32532
  }
@@ -35925,7 +36398,9 @@ const enUiBrowser = {
35925
36398
  "ui.browser.page_context_menu.cut": "Cut",
35926
36399
  "ui.browser.page_context_menu.open_link_in_new_tab": "Open link in new tab",
35927
36400
  "ui.browser.page_context_menu.paste": "Paste",
36401
+ "ui.browser.page_context_menu.redo": "Redo",
35928
36402
  "ui.browser.page_context_menu.select_all": "Select all",
36403
+ "ui.browser.page_context_menu.undo": "Undo",
35929
36404
  "ui.browser.use_browser_chrome.downloads_folder_failed": "Could not open the downloads folder. {message}",
35930
36405
  "ui.browser.use_consent_attention_lifetime.that_request_is_no_longer_waiting": "That request is no longer waiting.",
35931
36406
  "ui.browser.webauthn_chooser.a_site": "A site",
@@ -36096,6 +36571,8 @@ const enUiChatComposer = {
36096
36571
  "ui.chat.composer.starting_recording": "Starting recording",
36097
36572
  "ui.chat.composer.start_recording_hint": "Start recording ({shortcut} or hold {pushToTalk})",
36098
36573
  "ui.chat.composer.processing_audio": "Processing audio",
36574
+ "ui.chat.composer.dictation_failed_transient": "Dictation failed: the transcription service had a temporary fault. Try again.",
36575
+ "ui.chat.composer.dictation_failed_transient_take_kept": "Dictation failed: the transcription service had a temporary fault. Your recording is kept — Retry sends it again.",
36099
36576
  "ui.chat.composer.welcome": "What can I help you with today?",
36100
36577
  "ui.chat.composer.delivery_remedies_hint": "The message that could not be delivered has Send again and Edit controls in the conversation above this box: press Shift+Tab to reach them.",
36101
36578
  "ui.chat.composer.secret_ask_notice": "The agent is asking for a secret. Enter it in the asks panel — you can keep chatting meanwhile.",
@@ -37217,6 +37694,7 @@ const enUiLibrary = {
37217
37694
  "ui.library.page.loaded_count": "{loaded} of {total} assets",
37218
37695
  "ui.library.page.preview": "Asset preview",
37219
37696
  "ui.library.page.results": "Library results",
37697
+ "ui.library.page.resize_preview": "Resize details drawer. Double-click to reset.",
37220
37698
  "ui.library.preview.unavailable": "This asset isn't available",
37221
37699
  "ui.library.preview.unavailable_detail": "It may no longer be in the catalog.",
37222
37700
  "ui.library.preview.pptx_preparing": "Preparing presentation…",
@@ -37350,11 +37828,9 @@ const enUiMesh = {
37350
37828
  "ui.mesh.mesh_card.move_to": "Move to {device}",
37351
37829
  "ui.mesh.mesh_card.copy_to": "Copy to {device}",
37352
37830
  "ui.mesh.mesh_card.conversation_count": "{count, plural, one {{count, number, ::group-off} conversation} other {{count, number, ::group-off} conversations}}",
37353
- "ui.mesh.mesh_card.revoked_membership": "revoked membership",
37354
37831
  "ui.mesh.mesh_card.shown_of": "{shown, number, ::group-off} of {total, number, ::group-off}",
37355
37832
  "ui.mesh.mesh_card.device_details": "{device} details",
37356
37833
  "ui.mesh.mesh_card.memberships": "Memberships",
37357
- "ui.mesh.mesh_card.revoked": " · revoked",
37358
37834
  "ui.mesh.mesh_card.remove_from": "Remove from ",
37359
37835
  "ui.mesh.mesh_card.conversations": "Conversations ",
37360
37836
  "ui.mesh.mesh_card.this_device_did_not_report_its_conversations": "This device did not report its conversations.",
@@ -37413,8 +37889,8 @@ const enUiMesh = {
37413
37889
  "ui.mesh.mesh_list.on_device_no_answer": "on {device} (not answering)",
37414
37890
  "ui.mesh.mesh_list.sort_devices_by": "Sort devices by",
37415
37891
  "ui.mesh.mesh_list.epoch": "epoch {epoch, number, ::group-off}",
37416
- "ui.mesh.mesh_list.revoked_count": " · {count, plural, other {{count, number, ::group-off} revoked}}",
37417
- "ui.mesh.mesh_list.revoked": "revoked",
37892
+ "ui.mesh.mesh_list.revoked_count": "{count, plural, other {{count, number, ::group-off} revoked}}",
37893
+ "ui.mesh.mesh_list.revoked_toggle_label": "Show revoked memberships",
37418
37894
  "ui.mesh.mesh_list.member": "member",
37419
37895
  "ui.mesh.mesh_list.move_conversation": "Move {conversation}",
37420
37896
  "ui.mesh.mesh_list.show_all_panel": "show all {count, plural, other {{count, number, ::group-off} in the panel}}",
@@ -39720,6 +40196,8 @@ const esUiBrowser = {
39720
40196
  "ui.browser.page_context_menu.copy": "Copiar",
39721
40197
  "ui.browser.page_context_menu.paste": "Pegar",
39722
40198
  "ui.browser.page_context_menu.select_all": "Seleccionar todo",
40199
+ "ui.browser.page_context_menu.redo": "Rehacer",
40200
+ "ui.browser.page_context_menu.undo": "Deshacer",
39723
40201
  "ui.browser.page_context_menu.copy_page_address": "Copiar dirección de la página",
39724
40202
  "ui.browser.browser_url_bar.home": "Inicio",
39725
40203
  "ui.browser.browser_url_bar.site_secure": "Conexión segura con {origin}",
@@ -39869,6 +40347,8 @@ const esUiChatComposer = {
39869
40347
  "ui.chat.composer.starting_recording": "Iniciando grabación",
39870
40348
  "ui.chat.composer.start_recording_hint": "Iniciar grabación ({shortcut} o mantén {pushToTalk})",
39871
40349
  "ui.chat.composer.processing_audio": "Procesando audio",
40350
+ "ui.chat.composer.dictation_failed_transient": "Error de dictado: el servicio de transcripción sufrió un fallo temporal. Vuelve a intentarlo.",
40351
+ "ui.chat.composer.dictation_failed_transient_take_kept": "Error de dictado: el servicio de transcripción sufrió un fallo temporal. Tu grabación se conserva: Reintentar la envía de nuevo.",
39872
40352
  "ui.chat.composer.welcome": "¿En qué puedo ayudarte hoy?",
39873
40353
  "ui.chat.composer.delivery_remedies_hint": "El mensaje que no se pudo entregar tiene los controles Enviar de nuevo y Editar en la conversación, encima de este cuadro: pulsa Mayús+Tab para llegar a ellos.",
39874
40354
  "ui.chat.composer.secret_ask_notice": "El agente está pidiendo un secreto. Escríbelo en el panel de consultas; puedes seguir chateando mientras tanto.",
@@ -40886,6 +41366,7 @@ const esUiLibrary = {
40886
41366
  "ui.library.page.loaded_count": "{loaded} de {total} recursos",
40887
41367
  "ui.library.page.preview": "Vista previa del recurso",
40888
41368
  "ui.library.page.results": "Resultados de la Biblioteca",
41369
+ "ui.library.page.resize_preview": "Cambiar el tamaño del panel de detalles. Doble clic para restablecer.",
40889
41370
  "ui.library.preview.unavailable": "Este recurso no está disponible",
40890
41371
  "ui.library.preview.unavailable_detail": "Puede que ya no esté en el catálogo.",
40891
41372
  "ui.library.preview.pptx_preparing": "Preparando la presentación…",
@@ -41019,11 +41500,9 @@ const esUiMesh = {
41019
41500
  "ui.mesh.mesh_card.move_to": "Mover a {device}",
41020
41501
  "ui.mesh.mesh_card.copy_to": "Copiar a {device}",
41021
41502
  "ui.mesh.mesh_card.conversation_count": "{count, plural, one {{count, number, ::group-off} conversación} many {{count, number, ::group-off} de conversaciones} other {{count, number, ::group-off} conversaciones}}",
41022
- "ui.mesh.mesh_card.revoked_membership": "membresía revocada",
41023
41503
  "ui.mesh.mesh_card.shown_of": "{shown, number, ::group-off} de {total, number, ::group-off}",
41024
41504
  "ui.mesh.mesh_card.device_details": "Detalles de {device}",
41025
41505
  "ui.mesh.mesh_card.memberships": "Membresías",
41026
- "ui.mesh.mesh_card.revoked": " · revocada",
41027
41506
  "ui.mesh.mesh_card.remove_from": "Quitar de ",
41028
41507
  "ui.mesh.mesh_card.conversations": "Conversaciones ",
41029
41508
  "ui.mesh.mesh_card.this_device_did_not_report_its_conversations": "Este dispositivo no informó de sus conversaciones.",
@@ -41082,8 +41561,8 @@ const esUiMesh = {
41082
41561
  "ui.mesh.mesh_list.on_device_no_answer": "en {device} (sin respuesta)",
41083
41562
  "ui.mesh.mesh_list.sort_devices_by": "Ordenar dispositivos por",
41084
41563
  "ui.mesh.mesh_list.epoch": "época {epoch, number, ::group-off}",
41085
- "ui.mesh.mesh_list.revoked_count": " · {count, plural, other {{count, number, ::group-off} revocados}}",
41086
- "ui.mesh.mesh_list.revoked": "revocado",
41564
+ "ui.mesh.mesh_list.revoked_count": "{count, plural, other {{count, number, ::group-off} revocados}}",
41565
+ "ui.mesh.mesh_list.revoked_toggle_label": "Mostrar las membresías revocadas",
41087
41566
  "ui.mesh.mesh_list.member": "miembro",
41088
41567
  "ui.mesh.mesh_list.move_conversation": "Mover {conversation}",
41089
41568
  "ui.mesh.mesh_list.show_all_panel": "mostrar los {count, plural, other {{count, number, ::group-off} del panel}}",
@@ -43389,6 +43868,8 @@ const frUiBrowser = {
43389
43868
  "ui.browser.page_context_menu.copy": "Copier",
43390
43869
  "ui.browser.page_context_menu.paste": "Coller",
43391
43870
  "ui.browser.page_context_menu.select_all": "Tout sélectionner",
43871
+ "ui.browser.page_context_menu.redo": "Rétablir",
43872
+ "ui.browser.page_context_menu.undo": "Annuler",
43392
43873
  "ui.browser.page_context_menu.copy_page_address": "Copier l’adresse de la page",
43393
43874
  "ui.browser.browser_url_bar.home": "Accueil",
43394
43875
  "ui.browser.browser_url_bar.site_secure": "Connexion sécurisée à {origin}",
@@ -43538,6 +44019,8 @@ const frUiChatComposer = {
43538
44019
  "ui.chat.composer.starting_recording": "Démarrage de l’enregistrement",
43539
44020
  "ui.chat.composer.start_recording_hint": "Démarrer l’enregistrement ({shortcut} ou maintenir {pushToTalk})",
43540
44021
  "ui.chat.composer.processing_audio": "Traitement de l’audio",
44022
+ "ui.chat.composer.dictation_failed_transient": "Échec de la dictée : le service de transcription a subi une panne temporaire. Réessayez.",
44023
+ "ui.chat.composer.dictation_failed_transient_take_kept": "Échec de la dictée : le service de transcription a subi une panne temporaire. Votre enregistrement est conservé — Réessayer l’envoie à nouveau.",
43541
44024
  "ui.chat.composer.welcome": "Comment puis-je vous aider aujourd’hui ?",
43542
44025
  "ui.chat.composer.delivery_remedies_hint": "Le message qui n’a pas pu être délivré dispose des commandes Renvoyer et Modifier dans la conversation, au-dessus de ce champ : appuyez sur Maj+Tab pour les atteindre.",
43543
44026
  "ui.chat.composer.secret_ask_notice": "L’agent demande un secret. Saisissez-le dans le panneau des demandes — vous pouvez continuer à discuter entre-temps.",
@@ -44555,6 +45038,7 @@ const frUiLibrary = {
44555
45038
  "ui.library.page.loaded_count": "{loaded} éléments sur {total}",
44556
45039
  "ui.library.page.preview": "Aperçu de l’élément",
44557
45040
  "ui.library.page.results": "Résultats de la Bibliothèque",
45041
+ "ui.library.page.resize_preview": "Redimensionner le panneau de détails. Double-cliquer pour réinitialiser.",
44558
45042
  "ui.library.preview.unavailable": "Cet élément n’est pas disponible",
44559
45043
  "ui.library.preview.unavailable_detail": "Il n’est peut-être plus dans le catalogue.",
44560
45044
  "ui.library.preview.pptx_preparing": "Préparation de la présentation…",
@@ -44688,11 +45172,9 @@ const frUiMesh = {
44688
45172
  "ui.mesh.mesh_card.move_to": "Déplacer vers {device}",
44689
45173
  "ui.mesh.mesh_card.copy_to": "Copier vers {device}",
44690
45174
  "ui.mesh.mesh_card.conversation_count": "{count, plural, one {{count, number, ::group-off} conversation} many {{count, number, ::group-off} de conversations} other {{count, number, ::group-off} conversations}}",
44691
- "ui.mesh.mesh_card.revoked_membership": "appartenance révoquée",
44692
45175
  "ui.mesh.mesh_card.shown_of": "{shown, number, ::group-off} sur {total, number, ::group-off}",
44693
45176
  "ui.mesh.mesh_card.device_details": "Détails de {device}",
44694
45177
  "ui.mesh.mesh_card.memberships": "Appartenances",
44695
- "ui.mesh.mesh_card.revoked": " · révoquée",
44696
45178
  "ui.mesh.mesh_card.remove_from": "Supprimer de ",
44697
45179
  "ui.mesh.mesh_card.conversations": "Conversations ",
44698
45180
  "ui.mesh.mesh_card.this_device_did_not_report_its_conversations": "Cet appareil n’a pas signalé ses conversations.",
@@ -44751,8 +45233,8 @@ const frUiMesh = {
44751
45233
  "ui.mesh.mesh_list.on_device_no_answer": "sur {device} (sans réponse)",
44752
45234
  "ui.mesh.mesh_list.sort_devices_by": "Trier les appareils par",
44753
45235
  "ui.mesh.mesh_list.epoch": "époque {epoch, number, ::group-off}",
44754
- "ui.mesh.mesh_list.revoked_count": " · {count, plural, one {{count, number, ::group-off} révoqué} many {{count, number, ::group-off} révoqués} other {{count, number, ::group-off} révoqués}}",
44755
- "ui.mesh.mesh_list.revoked": "révoqué",
45236
+ "ui.mesh.mesh_list.revoked_count": "{count, plural, one {{count, number, ::group-off} révoqué} many {{count, number, ::group-off} révoqués} other {{count, number, ::group-off} révoqués}}",
45237
+ "ui.mesh.mesh_list.revoked_toggle_label": "Afficher les appartenances révoquées",
44756
45238
  "ui.mesh.mesh_list.member": "membre",
44757
45239
  "ui.mesh.mesh_list.move_conversation": "Déplacer {conversation}",
44758
45240
  "ui.mesh.mesh_list.show_all_panel": "afficher {count, plural, one {{count, number, ::group-off} conversation dans le panneau} many {les {count, number, ::group-off} conversations dans le panneau} other {les {count, number, ::group-off} conversations dans le panneau}}",
@@ -47085,6 +47567,8 @@ const hiUiBrowser = {
47085
47567
  "ui.browser.page_context_menu.open_link_in_new_tab": "लिंक नए टैब में खोलें",
47086
47568
  "ui.browser.page_context_menu.paste": "पेस्ट करें",
47087
47569
  "ui.browser.page_context_menu.select_all": "सभी चुनें",
47570
+ "ui.browser.page_context_menu.redo": "फिर से करें",
47571
+ "ui.browser.page_context_menu.undo": "पूर्ववत करें",
47088
47572
  "ui.browser.use_browser_chrome.downloads_folder_failed": "डाउनलोड फ़ोल्डर नहीं खुल सका। {message}",
47089
47573
  "ui.browser.use_consent_attention_lifetime.that_request_is_no_longer_waiting": "वह अनुरोध अब इंतज़ार में नहीं है।",
47090
47574
  "ui.browser.webauthn_chooser.a_site": "एक साइट",
@@ -47207,6 +47691,8 @@ const hiUiChatComposer = {
47207
47691
  "ui.chat.composer.starting_recording": "रिकॉर्डिंग शुरू हो रही है",
47208
47692
  "ui.chat.composer.start_recording_hint": "रिकॉर्डिंग शुरू करें ({shortcut} या {pushToTalk} दबाए रखें)",
47209
47693
  "ui.chat.composer.processing_audio": "ऑडियो प्रोसेस हो रहा है",
47694
+ "ui.chat.composer.dictation_failed_transient": "डिक्टेशन विफल: ट्रांसक्रिप्शन सेवा में अस्थायी खराबी आई। फिर कोशिश करें।",
47695
+ "ui.chat.composer.dictation_failed_transient_take_kept": "डिक्टेशन विफल: ट्रांसक्रिप्शन सेवा में अस्थायी खराबी आई। आपकी रिकॉर्डिंग सुरक्षित है — “फिर कोशिश करें” उसे दोबारा भेज देता है।",
47210
47696
  "ui.chat.composer.welcome": "आज मैं आपकी किस काम में मदद करूँ?",
47211
47697
  "ui.chat.composer.delivery_remedies_hint": "जो संदेश नहीं पहुँचा, उसके फिर भेजें और संपादित करें बटन इस बॉक्स के ऊपर बातचीत में हैं: उन तक पहुँचने के लिए Shift+Tab दबाएँ।",
47212
47698
  "ui.chat.composer.secret_ask_notice": "एजेंट कोई गोपनीय जानकारी माँग रहा है। इसे सवालों के पैनल में दर्ज करें — इस बीच आप चैट जारी रख सकते हैं।",
@@ -48193,6 +48679,7 @@ const hiUiLibrary = {
48193
48679
  "ui.library.page.loaded_count": "{loaded} एसेट कुल {total} में से",
48194
48680
  "ui.library.page.preview": "एसेट का प्रीव्यू",
48195
48681
  "ui.library.page.results": "लाइब्रेरी के नतीजे",
48682
+ "ui.library.page.resize_preview": "विवरण ड्रॉअर का आकार बदलें। रीसेट करने के लिए दो बार क्लिक करें।",
48196
48683
  "ui.library.preview.unavailable": "यह एसेट उपलब्ध नहीं है",
48197
48684
  "ui.library.preview.unavailable_detail": "हो सकता है यह अब कैटलॉग में न हो।",
48198
48685
  "ui.library.preview.pptx_preparing": "प्रस्तुति तैयार हो रही है…",
@@ -48326,11 +48813,9 @@ const hiUiMesh = {
48326
48813
  "ui.mesh.mesh_card.move_to": "{device} पर ले जाएँ",
48327
48814
  "ui.mesh.mesh_card.copy_to": "{device} पर कॉपी करें",
48328
48815
  "ui.mesh.mesh_card.conversation_count": "{count, plural, one {{count, number, ::group-off} बातचीत} other {{count, number, ::group-off} बातचीतें}}",
48329
- "ui.mesh.mesh_card.revoked_membership": "सदस्यता रद्द",
48330
48816
  "ui.mesh.mesh_card.shown_of": "{shown, number, ::group-off}, कुल {total, number, ::group-off}",
48331
48817
  "ui.mesh.mesh_card.device_details": "{device} का विवरण",
48332
48818
  "ui.mesh.mesh_card.memberships": "सदस्यताएँ",
48333
- "ui.mesh.mesh_card.revoked": " · रद्द",
48334
48819
  "ui.mesh.mesh_card.remove_from": "नेटवर्क से हटाएँ: ",
48335
48820
  "ui.mesh.mesh_card.conversations": "बातचीतें ",
48336
48821
  "ui.mesh.mesh_card.this_device_did_not_report_its_conversations": "इस डिवाइस ने अपनी बातचीतों की जानकारी नहीं दी।",
@@ -48389,8 +48874,8 @@ const hiUiMesh = {
48389
48874
  "ui.mesh.mesh_list.on_device_no_answer": "{device} पर (जवाब नहीं दे रहा)",
48390
48875
  "ui.mesh.mesh_list.sort_devices_by": "डिवाइस का क्रम तय करें",
48391
48876
  "ui.mesh.mesh_list.epoch": "सदस्यता epoch {epoch, number, ::group-off}",
48392
- "ui.mesh.mesh_list.revoked_count": " · {count, plural, other {{count, number, ::group-off} रद्द}}",
48393
- "ui.mesh.mesh_list.revoked": "रद्द",
48877
+ "ui.mesh.mesh_list.revoked_count": "{count, plural, other {{count, number, ::group-off} रद्द}}",
48878
+ "ui.mesh.mesh_list.revoked_toggle_label": "रद्द की गई सदस्यताएँ दिखाएँ",
48394
48879
  "ui.mesh.mesh_list.member": "सदस्य",
48395
48880
  "ui.mesh.mesh_list.move_conversation": "{conversation} को ले जाएँ",
48396
48881
  "ui.mesh.mesh_list.show_all_panel": "पैनल में सभी {count, plural, other {{count, number, ::group-off} दिखाएँ}}",
@@ -50712,6 +51197,8 @@ const ruUiBrowser = {
50712
51197
  "ui.browser.page_context_menu.open_link_in_new_tab": "Открыть ссылку в новой вкладке",
50713
51198
  "ui.browser.page_context_menu.paste": "Вставить",
50714
51199
  "ui.browser.page_context_menu.select_all": "Выделить всё",
51200
+ "ui.browser.page_context_menu.redo": "Повторить",
51201
+ "ui.browser.page_context_menu.undo": "Отменить",
50715
51202
  "ui.browser.use_browser_chrome.downloads_folder_failed": "Не удалось открыть папку загрузок. {message}",
50716
51203
  "ui.browser.use_consent_attention_lifetime.that_request_is_no_longer_waiting": "Этот запрос больше не ожидает.",
50717
51204
  "ui.browser.webauthn_chooser.a_site": "Сайт",
@@ -50827,6 +51314,8 @@ const ruUiChatComposer = {
50827
51314
  "ui.chat.composer.delivery_remedies_hint": "У недоставленного сообщения есть кнопки «Отправить снова» и «Изменить» в разговоре над этим полем: нажмите Shift+Tab, чтобы перейти к ним.",
50828
51315
  "ui.chat.composer.message": "Сообщение",
50829
51316
  "ui.chat.composer.processing_audio": "Обработка аудио",
51317
+ "ui.chat.composer.dictation_failed_transient": "Диктовка не удалась: служба транскрипции временно дала сбой. Повторите попытку.",
51318
+ "ui.chat.composer.dictation_failed_transient_take_kept": "Диктовка не удалась: служба транскрипции временно дала сбой. Запись сохранена — «Повторить» отправит её снова.",
50830
51319
  "ui.chat.composer.secret_ask_notice": "Агент запрашивает секрет. Введите его на панели запросов — общаться можно параллельно.",
50831
51320
  "ui.chat.composer.secret_ask_open": "Открыть запросы",
50832
51321
  "ui.chat.composer.secret_confirm_cancel": "Отмена",
@@ -51840,6 +52329,7 @@ const ruUiLibrary = {
51840
52329
  "ui.library.page.loaded_count": "Файлы: {loaded} из {total}",
51841
52330
  "ui.library.page.preview": "Предпросмотр файла",
51842
52331
  "ui.library.page.results": "Результаты Библиотеки",
52332
+ "ui.library.page.resize_preview": "Изменить ширину панели сведений. Дважды щёлкните, чтобы сбросить её.",
51843
52333
  "ui.library.preview.unavailable": "Этот файл недоступен",
51844
52334
  "ui.library.preview.unavailable_detail": "Возможно, его больше нет в каталоге.",
51845
52335
  "ui.library.preview.pptx_preparing": "Подготовка презентации…",
@@ -51998,8 +52488,6 @@ const ruUiMesh = {
51998
52488
  "ui.mesh.mesh_card.reach": "Доступность",
51999
52489
  "ui.mesh.mesh_card.recall_to_this_device": "Вернуть на это устройство",
52000
52490
  "ui.mesh.mesh_card.remove_from": "Удалить из ",
52001
- "ui.mesh.mesh_card.revoked": " · отозвано",
52002
- "ui.mesh.mesh_card.revoked_membership": "членство отозвано",
52003
52491
  "ui.mesh.mesh_card.show_in_list": "Показать в списке",
52004
52492
  "ui.mesh.mesh_card.shown_of": "{shown, number, ::group-off} из {total, number, ::group-off}",
52005
52493
  "ui.mesh.mesh_card.status": "Статус",
@@ -52054,8 +52542,8 @@ const ruUiMesh = {
52054
52542
  "ui.mesh.mesh_list.name": "Название",
52055
52543
  "ui.mesh.mesh_list.on_device_no_answer": "на {device} (не отвечает)",
52056
52544
  "ui.mesh.mesh_list.on_device_state": "на {device}{state}",
52057
- "ui.mesh.mesh_list.revoked": "отозвано",
52058
- "ui.mesh.mesh_list.revoked_count": " · {count, plural, one {отозвано: {count, number, ::group-off}} few {отозвано: {count, number, ::group-off}} many {отозвано: {count, number, ::group-off}} other {отозвано: {count, number, ::group-off}}}",
52545
+ "ui.mesh.mesh_list.revoked_toggle_label": "Показать отозванные участия",
52546
+ "ui.mesh.mesh_list.revoked_count": "{count, plural, one {отозвано: {count, number, ::group-off}} few {отозвано: {count, number, ::group-off}} many {отозвано: {count, number, ::group-off}} other {отозвано: {count, number, ::group-off}}}",
52059
52547
  "ui.mesh.mesh_list.show_all_panel": "показать {count, plural, one {{count, number, ::group-off} в панели} few {все {count, number, ::group-off} в панели} many {все {count, number, ::group-off} в панели} other {{count, number, ::group-off} в панели}}",
52060
52548
  "ui.mesh.mesh_list.sort_conversations": "Разговоры",
52061
52549
  "ui.mesh.mesh_list.sort_devices_by": "Сортировать устройства по",
@@ -54359,6 +54847,8 @@ const urUiBrowser = {
54359
54847
  "ui.browser.page_context_menu.open_link_in_new_tab": "لنک نئے ٹیب میں کھولیں",
54360
54848
  "ui.browser.page_context_menu.paste": "چسپاں کریں",
54361
54849
  "ui.browser.page_context_menu.select_all": "سب منتخب کریں",
54850
+ "ui.browser.page_context_menu.redo": "دوبارہ کریں",
54851
+ "ui.browser.page_context_menu.undo": "کالعدم کریں",
54362
54852
  "ui.browser.use_browser_chrome.downloads_folder_failed": "ڈاؤن لوڈ فولڈر نہیں کھل سکا۔ {message}",
54363
54853
  "ui.browser.use_consent_attention_lifetime.that_request_is_no_longer_waiting": "وہ درخواست اب منتظر نہیں ہے۔",
54364
54854
  "ui.browser.webauthn_chooser.a_site": "ایک سائٹ",
@@ -54481,6 +54971,8 @@ const urUiChatComposer = {
54481
54971
  "ui.chat.composer.starting_recording": "ریکارڈنگ شروع ہو رہی ہے",
54482
54972
  "ui.chat.composer.start_recording_hint": "ریکارڈنگ شروع کریں ({shortcut} یا {pushToTalk} دبائے رکھیں)",
54483
54973
  "ui.chat.composer.processing_audio": "آڈیو پر کارروائی جاری ہے",
54974
+ "ui.chat.composer.dictation_failed_transient": "ڈکٹیشن ناکام: ٹرانسکرپشن سروس کو عارضی خرابی پیش آئی۔ دوبارہ کوشش کریں۔",
54975
+ "ui.chat.composer.dictation_failed_transient_take_kept": "ڈکٹیشن ناکام: ٹرانسکرپشن سروس کو عارضی خرابی پیش آئی۔ آپ کی ریکارڈنگ محفوظ ہے — “دوبارہ کوشش کریں” اسے دوبارہ بھیج دے گا۔",
54484
54976
  "ui.chat.composer.welcome": "آج میں آپ کی کیا مدد کروں؟",
54485
54977
  "ui.chat.composer.delivery_remedies_hint": "جو پیغام نہیں پہنچ سکا اس کے دوبارہ بھیجیں اور ترمیم کریں کے کنٹرول اس خانے کے اوپر گفتگو میں ہیں؛ ان تک پہنچنے کے لیے Shift+Tab دبائیں۔",
54486
54978
  "ui.chat.composer.secret_ask_notice": "ایجنٹ ایک راز مانگ رہا ہے۔ اسے سوالات کے پینل میں درج کریں — اس دوران آپ چیٹ جاری رکھ سکتے ہیں۔",
@@ -55487,6 +55979,7 @@ const urUiLibrary = {
55487
55979
  "ui.library.page.loaded_count": "{total} اثاثوں میں سے {loaded}",
55488
55980
  "ui.library.page.preview": "اثاثے کا پیش منظر",
55489
55981
  "ui.library.page.results": "لائبریری کے نتائج",
55982
+ "ui.library.page.resize_preview": "تفصیلات کے پینل کی چوڑائی بدلیں۔ ڈبل کلک کر کے ری سیٹ کریں۔",
55490
55983
  "ui.library.preview.unavailable": "یہ اثاثہ دستیاب نہیں",
55491
55984
  "ui.library.preview.unavailable_detail": "ممکن ہے اب یہ کیٹلاگ میں نہ ہو۔",
55492
55985
  "ui.library.preview.pptx_preparing": "پریزنٹیشن تیار ہو رہی ہے…",
@@ -55620,11 +56113,9 @@ const urUiMesh = {
55620
56113
  "ui.mesh.mesh_card.move_to": "{device} پر منتقل کریں",
55621
56114
  "ui.mesh.mesh_card.copy_to": "{device} پر نقل بنائیں",
55622
56115
  "ui.mesh.mesh_card.conversation_count": "{count, plural, one {{count, number, ::group-off} گفتگو} other {{count, number, ::group-off} گفتگوئیں}}",
55623
- "ui.mesh.mesh_card.revoked_membership": "منسوخ شدہ رکنیت",
55624
56116
  "ui.mesh.mesh_card.shown_of": "{total, number, ::group-off} میں سے {shown, number, ::group-off}",
55625
56117
  "ui.mesh.mesh_card.device_details": "{device} کی تفصیلات",
55626
56118
  "ui.mesh.mesh_card.memberships": "رکنیتیں",
55627
- "ui.mesh.mesh_card.revoked": " · منسوخ شدہ",
55628
56119
  "ui.mesh.mesh_card.remove_from": "اس نیٹ ورک سے ہٹائیں: ",
55629
56120
  "ui.mesh.mesh_card.conversations": "گفتگوئیں ",
55630
56121
  "ui.mesh.mesh_card.this_device_did_not_report_its_conversations": "اس ڈیوائس نے اپنی گفتگوؤں کی اطلاع نہیں دی۔",
@@ -55683,8 +56174,8 @@ const urUiMesh = {
55683
56174
  "ui.mesh.mesh_list.on_device_no_answer": "{device} پر — جواب نہیں دے رہی",
55684
56175
  "ui.mesh.mesh_list.sort_devices_by": "ڈیوائسز کی ترتیب کی بنیاد",
55685
56176
  "ui.mesh.mesh_list.epoch": "دور {epoch, number, ::group-off}",
55686
- "ui.mesh.mesh_list.revoked_count": " · {count, plural, other {{count, number, ::group-off} منسوخ شدہ}}",
55687
- "ui.mesh.mesh_list.revoked": "منسوخ شدہ",
56177
+ "ui.mesh.mesh_list.revoked_count": "{count, plural, other {{count, number, ::group-off} منسوخ شدہ}}",
56178
+ "ui.mesh.mesh_list.revoked_toggle_label": "منسوخ شدہ رکنیتیں دکھائیں",
55688
56179
  "ui.mesh.mesh_list.member": "رکن",
55689
56180
  "ui.mesh.mesh_list.move_conversation": "{conversation} منتقل کریں",
55690
56181
  "ui.mesh.mesh_list.show_all_panel": "{count, plural, other {سبھی {count, number, ::group-off} پینل میں دکھائیں}}",
@@ -58006,6 +58497,8 @@ const viUiBrowser = {
58006
58497
  "ui.browser.page_context_menu.open_link_in_new_tab": "Mở liên kết trong tab mới",
58007
58498
  "ui.browser.page_context_menu.paste": "Dán",
58008
58499
  "ui.browser.page_context_menu.select_all": "Chọn tất cả",
58500
+ "ui.browser.page_context_menu.redo": "Làm lại",
58501
+ "ui.browser.page_context_menu.undo": "Hoàn tác",
58009
58502
  "ui.browser.use_browser_chrome.downloads_folder_failed": "Không thể mở thư mục tải xuống. {message}",
58010
58503
  "ui.browser.use_consent_attention_lifetime.that_request_is_no_longer_waiting": "Yêu cầu đó không còn chờ xử lý.",
58011
58504
  "ui.browser.webauthn_chooser.a_site": "Một trang web",
@@ -58128,6 +58621,8 @@ const viUiChatComposer = {
58128
58621
  "ui.chat.composer.starting_recording": "Đang bắt đầu ghi âm",
58129
58622
  "ui.chat.composer.start_recording_hint": "Bắt đầu ghi âm ({shortcut} hoặc giữ {pushToTalk})",
58130
58623
  "ui.chat.composer.processing_audio": "Đang xử lý âm thanh",
58624
+ "ui.chat.composer.dictation_failed_transient": "Đọc chính tả thất bại: dịch vụ chuyển giọng nói thành văn bản gặp sự cố tạm thời. Hãy thử lại.",
58625
+ "ui.chat.composer.dictation_failed_transient_take_kept": "Đọc chính tả thất bại: dịch vụ chuyển giọng nói thành văn bản gặp sự cố tạm thời. Bản ghi âm của bạn được giữ lại — Thử lại sẽ gửi bản ghi âm đi.",
58131
58626
  "ui.chat.composer.welcome": "Hôm nay tôi có thể giúp gì cho bạn?",
58132
58627
  "ui.chat.composer.delivery_remedies_hint": "Tin nhắn chưa gửi được có nút Gửi lại và Sửa trong cuộc trò chuyện phía trên ô này: nhấn Shift+Tab để đến các nút đó.",
58133
58628
  "ui.chat.composer.secret_ask_notice": "Tác nhân đang yêu cầu thông tin bí mật. Hãy nhập vào bảng câu hỏi — bạn vẫn có thể trò chuyện trong lúc này.",
@@ -59134,6 +59629,7 @@ const viUiLibrary = {
59134
59629
  "ui.library.page.loaded_count": "{loaded}/{total} tệp",
59135
59630
  "ui.library.page.preview": "Xem trước tệp",
59136
59631
  "ui.library.page.results": "Kết quả Thư viện",
59632
+ "ui.library.page.resize_preview": "Điều chỉnh kích thước ngăn chi tiết. Nhấp đúp để đặt lại.",
59137
59633
  "ui.library.preview.unavailable": "Tệp này không khả dụng",
59138
59634
  "ui.library.preview.unavailable_detail": "Có thể tệp không còn trong thư viện.",
59139
59635
  "ui.library.preview.pptx_preparing": "Đang chuẩn bị bản trình bày…",
@@ -59267,11 +59763,9 @@ const viUiMesh = {
59267
59763
  "ui.mesh.mesh_card.move_to": "Chuyển đến {device}",
59268
59764
  "ui.mesh.mesh_card.copy_to": "Sao chép đến {device}",
59269
59765
  "ui.mesh.mesh_card.conversation_count": "{count, plural, other {{count, number, ::group-off} cuộc trò chuyện}}",
59270
- "ui.mesh.mesh_card.revoked_membership": "tư cách thành viên đã bị thu hồi",
59271
59766
  "ui.mesh.mesh_card.shown_of": "{shown, number, ::group-off} trên {total, number, ::group-off}",
59272
59767
  "ui.mesh.mesh_card.device_details": "Chi tiết {device}",
59273
59768
  "ui.mesh.mesh_card.memberships": "Tư cách thành viên",
59274
- "ui.mesh.mesh_card.revoked": " · đã thu hồi",
59275
59769
  "ui.mesh.mesh_card.remove_from": "Xóa khỏi ",
59276
59770
  "ui.mesh.mesh_card.conversations": "Cuộc trò chuyện ",
59277
59771
  "ui.mesh.mesh_card.this_device_did_not_report_its_conversations": "Thiết bị này không báo cáo các cuộc trò chuyện.",
@@ -59330,8 +59824,8 @@ const viUiMesh = {
59330
59824
  "ui.mesh.mesh_list.on_device_no_answer": "trên {device} (không phản hồi)",
59331
59825
  "ui.mesh.mesh_list.sort_devices_by": "Sắp xếp thiết bị theo",
59332
59826
  "ui.mesh.mesh_list.epoch": "phiên bản {epoch, number, ::group-off}",
59333
- "ui.mesh.mesh_list.revoked_count": " · {count, plural, other {{count, number, ::group-off} đã thu hồi}}",
59334
- "ui.mesh.mesh_list.revoked": "đã thu hồi",
59827
+ "ui.mesh.mesh_list.revoked_count": "{count, plural, other {{count, number, ::group-off} đã thu hồi}}",
59828
+ "ui.mesh.mesh_list.revoked_toggle_label": "Hiện các tư cách thành viên đã thu hồi",
59335
59829
  "ui.mesh.mesh_list.member": "thành viên",
59336
59830
  "ui.mesh.mesh_list.move_conversation": "Chuyển {conversation}",
59337
59831
  "ui.mesh.mesh_list.show_all_panel": "hiện toàn bộ {count, plural, other {{count, number, ::group-off} trong bảng}}",
@@ -61462,6 +61956,8 @@ const zhCNUiBrowser = {
61462
61956
  "ui.browser.page_context_menu.open_link_in_new_tab": "在新标签页中打开链接",
61463
61957
  "ui.browser.page_context_menu.paste": "粘贴",
61464
61958
  "ui.browser.page_context_menu.select_all": "全选",
61959
+ "ui.browser.page_context_menu.redo": "重做",
61960
+ "ui.browser.page_context_menu.undo": "撤销",
61465
61961
  "ui.browser.use_browser_chrome.downloads_folder_failed": "无法打开下载文件夹。{message}",
61466
61962
  "ui.browser.use_consent_attention_lifetime.that_request_is_no_longer_waiting": "此请求已不再等待处理。",
61467
61963
  "ui.browser.webauthn_chooser.a_site": "某个网站",
@@ -61584,6 +62080,8 @@ const zhCNUiChatComposer = {
61584
62080
  "ui.chat.composer.starting_recording": "正在启动录音",
61585
62081
  "ui.chat.composer.start_recording_hint": "开始录音({shortcut},或按住{pushToTalk})",
61586
62082
  "ui.chat.composer.processing_audio": "正在处理音频",
62083
+ "ui.chat.composer.dictation_failed_transient": "听写失败:转写服务出现临时故障。请重试。",
62084
+ "ui.chat.composer.dictation_failed_transient_take_kept": "听写失败:转写服务出现临时故障。录音已保留,“重试”即可重新发送。",
61587
62085
  "ui.chat.composer.welcome": "今天有什么需要帮忙的?",
61588
62086
  "ui.chat.composer.delivery_remedies_hint": "未能送达的消息位于输入框上方的对话中,可选择“重新发送”或“编辑”;按Shift+Tab可移至这些控件。",
61589
62087
  "ui.chat.composer.secret_ask_notice": "智能体需要你提供敏感信息。请在请求面板中输入,期间仍可继续聊天。",
@@ -62601,6 +63099,7 @@ const zhCNUiLibrary = {
62601
63099
  "ui.library.page.loaded_count": "{loaded}/{total}个资源",
62602
63100
  "ui.library.page.preview": "资源预览",
62603
63101
  "ui.library.page.results": "资源库结果",
63102
+ "ui.library.page.resize_preview": "调整详情抽屉宽度。双击可重置。",
62604
63103
  "ui.library.preview.unavailable": "此资源不可用",
62605
63104
  "ui.library.preview.unavailable_detail": "该资源可能已不在目录中。",
62606
63105
  "ui.library.preview.pptx_preparing": "正在准备演示文稿……",
@@ -62734,11 +63233,9 @@ const zhCNUiMesh = {
62734
63233
  "ui.mesh.mesh_card.move_to": "移至{device}",
62735
63234
  "ui.mesh.mesh_card.copy_to": "复制到{device}",
62736
63235
  "ui.mesh.mesh_card.conversation_count": "{count, plural, other {{count, number, ::group-off}个对话}}",
62737
- "ui.mesh.mesh_card.revoked_membership": "成员资格已撤销",
62738
63236
  "ui.mesh.mesh_card.shown_of": "{shown, number, ::group-off}/{total, number, ::group-off}",
62739
63237
  "ui.mesh.mesh_card.device_details": "{device}的详情",
62740
63238
  "ui.mesh.mesh_card.memberships": "所属网络",
62741
- "ui.mesh.mesh_card.revoked": "· 已撤销",
62742
63239
  "ui.mesh.mesh_card.remove_from": "从网络中移除:",
62743
63240
  "ui.mesh.mesh_card.conversations": "对话",
62744
63241
  "ui.mesh.mesh_card.this_device_did_not_report_its_conversations": "此设备未报告对话信息。",
@@ -62797,8 +63294,8 @@ const zhCNUiMesh = {
62797
63294
  "ui.mesh.mesh_list.on_device_no_answer": "位于{device}(未响应)",
62798
63295
  "ui.mesh.mesh_list.sort_devices_by": "设备排序依据",
62799
63296
  "ui.mesh.mesh_list.epoch": "成员版本{epoch, number, ::group-off}",
62800
- "ui.mesh.mesh_list.revoked_count": "· {count, plural, other {{count, number, ::group-off}项已撤销}}",
62801
- "ui.mesh.mesh_list.revoked": "已撤销",
63297
+ "ui.mesh.mesh_list.revoked_count": "{count, plural, other {{count, number, ::group-off}项已撤销}}",
63298
+ "ui.mesh.mesh_list.revoked_toggle_label": "显示已撤销的成员资格",
62802
63299
  "ui.mesh.mesh_list.member": "成员",
62803
63300
  "ui.mesh.mesh_list.move_conversation": "移动{conversation}",
62804
63301
  "ui.mesh.mesh_list.show_all_panel": "在面板中显示全部{count, plural, other {{count, number, ::group-off}个}}",
@@ -69045,6 +69542,10 @@ function withTimeout(work, ms) {
69045
69542
  function isReportableLoadFailure(code) {
69046
69543
  return code !== 0 && code !== -3;
69047
69544
  }
69545
+ function isSupersededRestore(error) {
69546
+ const message = error instanceof Error ? error.message : String(error);
69547
+ return message.includes("ERR_ABORTED (-3)");
69548
+ }
69048
69549
  function sessionRequesterOf(requester) {
69049
69550
  if (!requester.startsWith("session:")) return null;
69050
69551
  const id2 = requester.slice("session:".length);
@@ -69941,7 +70442,7 @@ class BrowserHost {
69941
70442
  if (started) await withTimeout(started, RESTORE_TAB_TIMEOUT_MS);
69942
70443
  } catch (error) {
69943
70444
  this.log(`[browser] could not restore tab ${tabId}: ${String(error)}`);
69944
- if (!committed && !this.loadFailures.has(tabId) && this.registry.get(tabId) && !contents.isDestroyed()) {
70445
+ if (!committed && !isSupersededRestore(error) && !this.loadFailures.has(tabId) && this.registry.get(tabId) && !contents.isDestroyed()) {
69945
70446
  const entry = recorded.entries[recorded.activeIndex];
69946
70447
  this.recordLoadFailure(tabId, {
69947
70448
  code: -2,
@@ -71899,6 +72400,17 @@ function buildPageContextMenuItems(input) {
71899
72400
  if (input.isEditable) {
71900
72401
  const flags = input.editFlags ?? {};
71901
72402
  return [
72403
+ {
72404
+ id: "undo",
72405
+ label: t("ui.browser.page_context_menu.undo"),
72406
+ enabled: flags.canUndo ?? true
72407
+ },
72408
+ {
72409
+ id: "redo",
72410
+ label: t("ui.browser.page_context_menu.redo"),
72411
+ enabled: flags.canRedo ?? true
72412
+ },
72413
+ SEPARATOR,
71902
72414
  {
71903
72415
  id: "cut",
71904
72416
  label: t("ui.browser.page_context_menu.cut"),
@@ -71938,6 +72450,13 @@ function buildPageContextMenuItems(input) {
71938
72450
  enabled: true
71939
72451
  }
71940
72452
  ];
72453
+ if (input.selectionText) {
72454
+ items.push(SEPARATOR, {
72455
+ id: "copy",
72456
+ label: t("ui.browser.page_context_menu.copy"),
72457
+ enabled: true
72458
+ });
72459
+ }
71941
72460
  if (input.linkUrl) {
71942
72461
  items.push(
71943
72462
  SEPARATOR,
@@ -73686,6 +74205,7 @@ async function initializeBrowserHost(options, bindings) {
73686
74205
  canGoBack: navigation ? navigation.canGoBack() : false,
73687
74206
  canGoForward: navigation ? navigation.canGoForward() : false,
73688
74207
  isEditable: params.isEditable,
74208
+ selectionText: params.selectionText ?? "",
73689
74209
  editFlags: params.editFlags
73690
74210
  });
73691
74211
  const menu = electron.Menu.buildFromTemplate(
@@ -73702,6 +74222,8 @@ async function initializeBrowserHost(options, bindings) {
73702
74222
  electron.clipboard.writeText(params.linkURL ?? "");
73703
74223
  else if (item.id === "copy-page")
73704
74224
  electron.clipboard.writeText(contents.getURL());
74225
+ else if (item.id === "undo") contents.undo();
74226
+ else if (item.id === "redo") contents.redo();
73705
74227
  else if (item.id === "cut") contents.cut();
73706
74228
  else if (item.id === "copy") contents.copy();
73707
74229
  else if (item.id === "paste") contents.paste();
@@ -73961,6 +74483,12 @@ async function initializeBrowserHost(options, bindings) {
73961
74483
  type: metric.type
73962
74484
  }))
73963
74485
  }) : null;
74486
+ const approvalsOverlay = options.approvalsOverlay?.enabled === true && approvalsOverlayEnabled(process.env) ? new ApprovalsOverlayController({
74487
+ window: options.window,
74488
+ documentUrl: options.approvalsOverlay.documentUrl,
74489
+ opaque: process.platform !== "darwin",
74490
+ log: log2
74491
+ }) : null;
73964
74492
  const sessionStore = new BrowserSessionStore({
73965
74493
  dir: path$1.join(options.userDataDir, "browser"),
73966
74494
  log: log2
@@ -74016,7 +74544,10 @@ async function initializeBrowserHost(options, bindings) {
74016
74544
  },
74017
74545
  releaseTab,
74018
74546
  notifyChanged,
74019
- (snapshot2) => addressOverlay?.onLayout(snapshot2)
74547
+ (snapshot2) => {
74548
+ addressOverlay?.onLayout(snapshot2);
74549
+ approvalsOverlay?.onLayout(snapshot2);
74550
+ }
74020
74551
  );
74021
74552
  registryForDownloads = registry;
74022
74553
  rollback.add(async () => {
@@ -74026,6 +74557,7 @@ async function initializeBrowserHost(options, bindings) {
74026
74557
  await Promise.allSettled([...releases]);
74027
74558
  });
74028
74559
  rollback.add(() => addressOverlay?.dispose("startup-rollback"));
74560
+ rollback.add(() => approvalsOverlay?.dispose("startup-rollback"));
74029
74561
  const ownership = new OwnershipLedger({
74030
74562
  mayAdopt: (token, requester) => {
74031
74563
  const record = registry.requireSurface(token);
@@ -74049,6 +74581,9 @@ async function initializeBrowserHost(options, bindings) {
74049
74581
  }
74050
74582
  }
74051
74583
  });
74584
+ let approvalsExpiryTimer = null;
74585
+ let syncApprovalsOverlay = () => {
74586
+ };
74052
74587
  const approvals = new ApprovalStore({
74053
74588
  dir: path$1.join(options.userDataDir, "browser"),
74054
74589
  onChanged: () => {
@@ -74056,9 +74591,26 @@ async function initializeBrowserHost(options, bindings) {
74056
74591
  options.window.webContents.send("browser-consent-changed");
74057
74592
  }
74058
74593
  consentNotifier.announce(approvals.pendingEntries());
74594
+ syncApprovalsOverlay();
74059
74595
  },
74060
74596
  log: log2
74061
74597
  });
74598
+ syncApprovalsOverlay = () => {
74599
+ if (!approvalsOverlay) return;
74600
+ if (approvalsExpiryTimer) {
74601
+ clearTimeout(approvalsExpiryTimer);
74602
+ approvalsExpiryTimer = null;
74603
+ }
74604
+ const entries = approvals.pendingEntries();
74605
+ approvalsOverlay?.setPending(entries.length);
74606
+ if (entries.length === 0) return;
74607
+ const delay2 = approvalsExpiryDelay(entries);
74608
+ if (delay2 !== null) {
74609
+ approvalsExpiryTimer = setTimeout(syncApprovalsOverlay, delay2 + 25);
74610
+ approvalsExpiryTimer.unref?.();
74611
+ }
74612
+ };
74613
+ syncApprovalsOverlay();
74062
74614
  const profileDir = browserStoragePath(browserSession) ?? "";
74063
74615
  const facts = {
74064
74616
  proto: 1,
@@ -74349,6 +74901,11 @@ async function initializeBrowserHost(options, bindings) {
74349
74901
  }
74350
74902
  sessionStore.flush();
74351
74903
  addressOverlay?.dispose("host-stop");
74904
+ if (approvalsExpiryTimer) {
74905
+ clearTimeout(approvalsExpiryTimer);
74906
+ approvalsExpiryTimer = null;
74907
+ }
74908
+ approvalsOverlay?.dispose("host-stop");
74352
74909
  registry.destroyAll();
74353
74910
  await Promise.allSettled([...releases]);
74354
74911
  await cdp.close();
@@ -86189,6 +86746,8 @@ electron.app.whenReady().then(async () => {
86189
86746
  const rendererUrl = rendererDocumentUrl();
86190
86747
  const consoleCaptureUrl = consoleCaptureUrlFor(rendererUrl);
86191
86748
  const addressOverlayDocumentUrl = addressOverlayGate.list || addressOverlayProduct ? addressListDocumentUrlFor(rendererUrl) : addressOverlayDocumentUrlFor(rendererUrl);
86749
+ const approvalsOverlayS6a = process.env[APPROVALS_OVERLAY_S6A_ENV] === "1";
86750
+ const approvalsOverlayDocumentUrl = approvalsOverlayS6a ? documentUrlFor(rendererUrl, "browser-approvals-overlay.html") : null;
86192
86751
  backendService.observeDesktopFeed(
86193
86752
  (frame) => {
86194
86753
  if (frame.type === "notification") {
@@ -87041,6 +87600,12 @@ electron.app.whenReady().then(async () => {
87041
87600
  documentUrl: addressOverlayDocumentUrl
87042
87601
  }
87043
87602
  } : {},
87603
+ ...approvalsOverlayS6a && approvalsOverlayDocumentUrl ? {
87604
+ approvalsOverlay: {
87605
+ enabled: true,
87606
+ documentUrl: approvalsOverlayDocumentUrl
87607
+ }
87608
+ } : {},
87044
87609
  preloadPath: path$1.join(__dirname, "../preload/index.js"),
87045
87610
  /*
87046
87611
  * The console's surfaces are handed the user's own PATH, from the same