local-operator-ui 0.31.18 → 0.31.20

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 (103) hide show
  1. package/README.md +24 -0
  2. package/out/main/index.js +233 -106
  3. package/out/renderer/assets/{_basePickBy-D1XXNWdy.js → _basePickBy-_G13yD_N.js} +1 -1
  4. package/out/renderer/assets/{_baseUniq-DD_DKvaU.js → _baseUniq-cZFY6WR-.js} +1 -1
  5. package/out/renderer/assets/{agent-details-page-Q8dgdQp2.js → agent-details-page-DohUpAW5.js} +1 -1
  6. package/out/renderer/assets/{agent-hub-page-CBHsotVj.js → agent-hub-page-D2Wo_RcW.js} +2 -2
  7. package/out/renderer/assets/agents-page-Bme3mW2i.js +2 -0
  8. package/out/renderer/assets/{renderer-platform-RsXXlY5x.js → aida-control-DVTI-DZP.js} +19 -19
  9. package/out/renderer/assets/{arc-BII0LAll.js → arc-_ZSLPSD3.js} +1 -1
  10. package/out/renderer/assets/architectureDiagram-IEHRJDOE-BMozIO-d.js +36 -0
  11. package/out/renderer/assets/{blockDiagram-JOT3LUYC-BsfIO03o.js → blockDiagram-JOT3LUYC-CnCGGby6.js} +6 -6
  12. package/out/renderer/assets/{book-open-Bau36KjM.js → book-open-BWKY7M9P.js} +1 -1
  13. package/out/renderer/assets/browser-page-Ca86jJVo.js +1 -0
  14. package/out/renderer/assets/browser-webauthn-prompt-Zq7Sensn.js +1 -0
  15. package/out/renderer/assets/{c4Diagram-VJAJSXHY-CHKu8u4B.js → c4Diagram-VJAJSXHY-D6vlxi2G.js} +1 -1
  16. package/out/renderer/assets/channel-DBxTgGZs.js +1 -0
  17. package/out/renderer/assets/{chunk-4BMEZGHF-Do_SeY3I.js → chunk-4BMEZGHF-CgxwmKpR.js} +1 -1
  18. package/out/renderer/assets/{chunk-A2AXSNBT-C7_NoYUm.js → chunk-A2AXSNBT-DL4YbfpC.js} +1 -1
  19. package/out/renderer/assets/{chunk-AEK57VVT-C3I1E4qy.js → chunk-AEK57VVT-C7STzYq2.js} +1 -1
  20. package/out/renderer/assets/{chunk-D6G4REZN-BEkTCb-4.js → chunk-D6G4REZN-BiGlWxbN.js} +1 -1
  21. package/out/renderer/assets/{chunk-RZ5BOZE2-Ccs-Kaym.js → chunk-RZ5BOZE2-FPI-zkVi.js} +1 -1
  22. package/out/renderer/assets/{chunk-XZIHB7SX-Db28vmME.js → chunk-XZIHB7SX-pQtxBw7K.js} +1 -1
  23. package/out/renderer/assets/classDiagram-GIVACNV2-oRXPz12L.js +1 -0
  24. package/out/renderer/assets/classDiagram-v2-COTLJTTW-oRXPz12L.js +1 -0
  25. package/out/renderer/assets/clone-CWgQ1AK5.js +1 -0
  26. package/out/renderer/assets/{console-mirror-CUQyeXIE.js → console-mirror-CG9RcMIb.js} +1 -1
  27. package/out/renderer/assets/{consoleCapture-emgU7WyW.js → consoleCapture-CpTo2RAv.js} +1 -1
  28. package/out/renderer/assets/dagre-OKDRZEBW-BoM7akd9.js +4 -0
  29. package/out/renderer/assets/diagram-SSKATNLV-D9w1aNay.js +43 -0
  30. package/out/renderer/assets/diagram-VNBRO52H-D6xO4h26.js +24 -0
  31. package/out/renderer/assets/{erDiagram-Q7BY3M3F-BYRglvp5.js → erDiagram-Q7BY3M3F-lgEC_hRU.js} +1 -1
  32. package/out/renderer/assets/{error-boundary-BFYdHP26.js → error-boundary-DVk48CIF.js} +1 -1
  33. package/out/renderer/assets/{flowDiagram-4HSFHLVR-C6ReCJC9.js → flowDiagram-4HSFHLVR-B8gXHejR.js} +1 -1
  34. package/out/renderer/assets/{ganttDiagram-APWFNJXF-CMDShfzg.js → ganttDiagram-APWFNJXF-Ds8ML93J.js} +3 -3
  35. package/out/renderer/assets/gitGraphDiagram-7IBYFJ6S-D5gdmSVh.js +65 -0
  36. package/out/renderer/assets/{graph-BK-Vf19N.js → graph-DNi4FjaS.js} +1 -1
  37. package/out/renderer/assets/index-40tBsZ9r.js +7 -0
  38. package/out/renderer/assets/{index-BDPyvriR.js → index-BhRzR-VW.js} +391 -376
  39. package/out/renderer/assets/index-BlalL3ro.js +1 -0
  40. package/out/renderer/assets/index-FjyWTJXV.css +1 -0
  41. package/out/renderer/assets/infoDiagram-PH2N3AL5-BDTgzxhS.js +2 -0
  42. package/out/renderer/assets/{installer-DfFRjYBs.js → installer-BgW1Tkr8.js} +1 -1
  43. package/out/renderer/assets/{journeyDiagram-U35MCT3I-CeBVrNEA.js → journeyDiagram-U35MCT3I-BdnGNrZc.js} +1 -1
  44. package/out/renderer/assets/{kanban-definition-NDS4AKOZ-DnIH3R0V.js → kanban-definition-NDS4AKOZ-BuQLa1-R.js} +1 -1
  45. package/out/renderer/assets/{layout-IqcTjCQI.js → layout-Pvac8TnM.js} +1 -1
  46. package/out/renderer/assets/{legacy-agents-page-DbLTVwq0.js → legacy-agents-page-BR_oPhtA.js} +3 -3
  47. package/out/renderer/assets/{mermaid.core-BrRc254F.js → mermaid.core-Dol6F2oY.js} +5 -5
  48. package/out/renderer/assets/mesh-page-CcSpUIcL.js +2 -0
  49. package/out/renderer/assets/mindmap-definition-ALO5MXBD-DDnWPtbR.js +95 -0
  50. package/out/renderer/assets/mini-D1QQjR0V.js +1 -0
  51. package/out/renderer/assets/org-surface-gate-_kP5Dpsg.js +1 -0
  52. package/out/renderer/assets/{page-header-BtO13sx8.js → page-header-B3RA2AMB.js} +1 -1
  53. package/out/renderer/assets/{pieDiagram-IB7DONF6-CnRMxjLj.js → pieDiagram-IB7DONF6-Dc1zeStB.js} +1 -1
  54. package/out/renderer/assets/{projects-page-BgRRDkEz.js → projects-page-Cb7bJ1ue.js} +1 -1
  55. package/out/renderer/assets/{quadrantDiagram-7GDLP6J5-bRLUBm5r.js → quadrantDiagram-7GDLP6J5-AlzvyKPw.js} +1 -1
  56. package/out/renderer/assets/{radar-MK3ICKWK-BV3WfB2Y.js → radar-MK3ICKWK-BLuijs-X.js} +1 -1
  57. package/out/renderer/assets/radient-auth-buttons-gtgUk3ts.js +1 -0
  58. package/out/renderer/assets/{requirementDiagram-KVF5MWMF-Bzqys165.js → requirementDiagram-KVF5MWMF-CfgMH9Xy.js} +1 -1
  59. package/out/renderer/assets/sankeyDiagram-QLVOVGJD-CGSaFjvZ.js +10 -0
  60. package/out/renderer/assets/{schedules-page-CbOATI1U.js → schedules-page-yCFUUqqb.js} +1 -1
  61. package/out/renderer/assets/{sequenceDiagram-X6HHIX6F-bfcEv3LN.js → sequenceDiagram-X6HHIX6F-BKLpPHnF.js} +1 -1
  62. package/out/renderer/assets/settings-page-6S9zTaN7.js +297 -0
  63. package/out/renderer/assets/{settings-section-BXGO9Lv0.js → settings-section-D3WEX0WK.js} +1 -1
  64. package/out/renderer/assets/stateDiagram-DGXRK772-CukEj5Ge.js +1 -0
  65. package/out/renderer/assets/stateDiagram-v2-YXO3MK2T-CaoB6DdD.js +1 -0
  66. package/out/renderer/assets/{textarea-B83uQCj2.js → textarea-BX6EeK34.js} +1 -1
  67. package/out/renderer/assets/{timeline-definition-BDJGKUSR-BlN_DgVS.js → timeline-definition-BDJGKUSR-ZSpHRGCR.js} +1 -1
  68. package/out/renderer/assets/{ui-preferences-store-DzXZGWGz.js → ui-preferences-store-DjUQd2R7.js} +1 -1
  69. package/out/renderer/assets/{use-download-agent-mutation-DrENBWNa.js → use-download-agent-mutation-BwZi8Zfx.js} +2 -2
  70. package/out/renderer/assets/use-memberships-query-CSOmeH29.js +1 -0
  71. package/out/renderer/assets/{xychartDiagram-VJFVF3MP-C1DOS4ES.js → xychartDiagram-VJFVF3MP-B4P41D_W.js} +1 -1
  72. package/out/renderer/console-capture.html +5 -5
  73. package/out/renderer/index.html +8 -8
  74. package/out/renderer/installer.html +5 -5
  75. package/out/renderer/mini.html +6 -6
  76. package/package.json +2 -2
  77. package/out/renderer/assets/agents-page-9zkhLfa8.js +0 -2
  78. package/out/renderer/assets/architectureDiagram-IEHRJDOE-Yh4i0oDy.js +0 -36
  79. package/out/renderer/assets/browser-page-CrHmmBk0.js +0 -1
  80. package/out/renderer/assets/browser-webauthn-prompt-_nNd3iSK.js +0 -1
  81. package/out/renderer/assets/channel-DXiH5yDB.js +0 -1
  82. package/out/renderer/assets/classDiagram-GIVACNV2-D2MG4USX.js +0 -1
  83. package/out/renderer/assets/classDiagram-v2-COTLJTTW-D2MG4USX.js +0 -1
  84. package/out/renderer/assets/clone-BDi6ICAs.js +0 -1
  85. package/out/renderer/assets/dagre-OKDRZEBW-k4D1AM8X.js +0 -4
  86. package/out/renderer/assets/diagram-SSKATNLV-B0DOtyf9.js +0 -43
  87. package/out/renderer/assets/diagram-VNBRO52H-BmzuI3Lr.js +0 -24
  88. package/out/renderer/assets/gitGraphDiagram-7IBYFJ6S-pvPc8CHP.js +0 -65
  89. package/out/renderer/assets/index-B5DwqFlK.js +0 -7
  90. package/out/renderer/assets/index-DITdBETY.css +0 -1
  91. package/out/renderer/assets/index-_oyU7kmX.js +0 -1
  92. package/out/renderer/assets/infoDiagram-PH2N3AL5-COePE42k.js +0 -2
  93. package/out/renderer/assets/mesh-page-W9oV_bPF.js +0 -2
  94. package/out/renderer/assets/mindmap-definition-ALO5MXBD-BMHndK7E.js +0 -95
  95. package/out/renderer/assets/mini-CbmMlUkq.js +0 -1
  96. package/out/renderer/assets/org-surface-gate-BgtTWHt3.js +0 -1
  97. package/out/renderer/assets/radient-auth-buttons-Briy2cZb.js +0 -1
  98. package/out/renderer/assets/sankeyDiagram-QLVOVGJD--IgSaXgN.js +0 -10
  99. package/out/renderer/assets/settings-page-Bn87mGZ1.js +0 -307
  100. package/out/renderer/assets/stateDiagram-DGXRK772-CDJAoYUf.js +0 -1
  101. package/out/renderer/assets/stateDiagram-v2-YXO3MK2T-Di7PMVrt.js +0 -1
  102. package/out/renderer/assets/use-memberships-query-C2Yus1QJ.js +0 -1
  103. /package/out/renderer/assets/{index-CDaH3A1m.js → index-VKe88JN9.js} +0 -0
package/out/main/index.js CHANGED
@@ -78,6 +78,9 @@ const DESKTOP_MESSAGE_MAX_CHARS = 2e5;
78
78
  const SESSION_SEARCH_MAX_CHARS = 256;
79
79
  const SESSION_SEARCH_DEFAULT_LIMIT = 100;
80
80
  const CHECKPOINT_WARM_MAX_IDS = 16;
81
+ const THREAD_FIND_MAX_CHARS = 256;
82
+ const THREAD_FIND_DEFAULT_LIMIT = 100;
83
+ const THREAD_FIND_MAX_LIMIT = 200;
81
84
  const DESKTOP_SYSTEM_PROMPT_MAX_CHARS = 1e6;
82
85
  const profileName = zod.z.string().min(1).max(128).refine(
83
86
  (name) => name !== "." && name !== ".." && !name.includes("/") && !name.includes("\\") && [...name].every(
@@ -561,6 +564,30 @@ const desktopRequestUnion = zod.z.discriminatedUnion("op", [
561
564
  ids: zod.z.array(id$1).max(CHECKPOINT_WARM_MAX_IDS).optional(),
562
565
  limit: zod.z.number().int().min(1).max(CHECKPOINT_WARM_MAX_IDS).optional()
563
566
  }).strict(),
567
+ /*
568
+ * In-thread find (D9): messages of ONE conversation matching `q`, best
569
+ * first, served from the per-session transcript index.
570
+ *
571
+ * A READ like `history` and `checkpoints` beside it. The answer's `state` is
572
+ * the checkpoint manifest's own ladder: a cold or stale index answers
573
+ * `building` inside the first-paint budget (with hits ranked from the
574
+ * previous scan marked `partial`) while the background refresh runs, so the
575
+ * overlay's first paint is immediate; `unsupported` is a peer conversation
576
+ * whose journal is not on this device; `error` is a failed refresh inside
577
+ * its cooldown. The overlay renders both tiers (`exact`/`soft`) and treats
578
+ * `ranges` as snippet-relative — empty on a soft hit, which has no literal
579
+ * occurrence of the query by construction.
580
+ */
581
+ zod.z.object({
582
+ op: zod.z.literal("sessions.find"),
583
+ sessionId,
584
+ // `.min(1)`: an empty query is not a search. The overlay's client never
585
+ // sends one — it answers an empty query locally, without a request — so
586
+ // refusing it by name keeps the vocabulary closed rather than paying a
587
+ // round trip for an answer the box already knows.
588
+ q: zod.z.string().min(1).max(THREAD_FIND_MAX_CHARS),
589
+ limit: zod.z.number().int().min(1).max(THREAD_FIND_MAX_LIMIT).optional()
590
+ }).strict(),
564
591
  /*
565
592
  * One child's durable transcript, for the run panel's reader
566
593
  * (`docs/run-sidebar.md` § 10.1, § 10.3).
@@ -1794,6 +1821,7 @@ const READ_ONLY_OPS = /* @__PURE__ */ new Set([
1794
1821
  "sessions.aside.get",
1795
1822
  "sessions.checkpoints",
1796
1823
  "sessions.failovers",
1824
+ "sessions.find",
1797
1825
  "sessions.get",
1798
1826
  "sessions.history",
1799
1827
  "sessions.list",
@@ -2086,6 +2114,16 @@ function desktopEndpoint(request) {
2086
2114
  ...request.limit !== void 0 ? { limit: request.limit } : {}
2087
2115
  }
2088
2116
  };
2117
+ case "sessions.find": {
2118
+ const query = new URLSearchParams({
2119
+ q: request.q,
2120
+ limit: String(request.limit ?? THREAD_FIND_DEFAULT_LIMIT)
2121
+ });
2122
+ return {
2123
+ path: `/v1/desktop/sessions/${request.sessionId}/find?${query}`,
2124
+ method: "GET"
2125
+ };
2126
+ }
2089
2127
  case "subagents.transcript": {
2090
2128
  const query = new URLSearchParams({
2091
2129
  limit: String(request.limit ?? 100)
@@ -2827,7 +2865,7 @@ function isMiniViewDismissReason(value) {
2827
2865
  }
2828
2866
  const MINI_VIEW_WIDTH = 640;
2829
2867
  const MINI_VIEW_HEIGHT = 168;
2830
- const DEFAULT_QUICK_SEND_VALUE = "primary+alt+space";
2868
+ const DEFAULT_QUICK_SEND_VALUE = "primary+alt+shift+space";
2831
2869
  const FUNCTION_KEY_TOKEN = /^f([1-9]|1[0-9]|2[0-4])$/;
2832
2870
  function isFunctionKeyToken(token) {
2833
2871
  return FUNCTION_KEY_TOKEN.test(token);
@@ -11742,6 +11780,11 @@ const REFUSABLE_DELIVERY = {
11742
11780
  // THE ONE REFUSAL. The residual above says what it rests on and what it cannot
11743
11781
  // see.
11744
11782
  "second-instance": "when-its-plan-is-silent",
11783
+ // A Dock click carries no conversation and installs nothing: it only ever
11784
+ // opens this process's own window, so there is no delivery here to refuse or
11785
+ // to park. (The refusal a QUITTING process answers it with is not this gate's;
11786
+ // it has a line of its own, `applied=skipped+quitting`.)
11787
+ activate: "never",
11745
11788
  // A person clicked a real banner, so refusing it and applying it must not
11746
11789
  // differ — and with a window up it does not even reach this gate.
11747
11790
  "banner-click": "never",
@@ -11810,6 +11853,17 @@ function reportParksAtQuit(sessions, report) {
11810
11853
  ].join(" ")
11811
11854
  );
11812
11855
  }
11856
+ function reportSkippedWhileQuitting(context, requested) {
11857
+ context.report?.(
11858
+ [
11859
+ `trigger=${context.trigger}`,
11860
+ `mode=${MODE_OF_SHOW[requested]}`,
11861
+ `requested=${requested}`,
11862
+ ...requesterFields(context),
11863
+ "applied=skipped+quitting"
11864
+ ].join(" ")
11865
+ );
11866
+ }
11813
11867
  function raiseWindow(window, show, context) {
11814
11868
  if (show === "never") return;
11815
11869
  const applied = [];
@@ -11848,6 +11902,17 @@ function readSecondLaunchRequest(input) {
11848
11902
  };
11849
11903
  }
11850
11904
  function applySecondLaunch(request, target2) {
11905
+ if (target2.quitting) {
11906
+ reportSkippedWhileQuitting(
11907
+ {
11908
+ trigger: "second-instance",
11909
+ requester: request.requester ?? void 0,
11910
+ report: target2.report
11911
+ },
11912
+ request.show
11913
+ );
11914
+ return;
11915
+ }
11851
11916
  if (request.session !== null) {
11852
11917
  if (target2.openConversation) {
11853
11918
  target2.openConversation(request.session, request);
@@ -12092,6 +12157,23 @@ class BackendInstaller {
12092
12157
  * and never resolves at all.
12093
12158
  */
12094
12159
  settleUserDecision = null;
12160
+ /**
12161
+ * What to tell the app when THIS window's question cancels a running quit.
12162
+ *
12163
+ * WHY THE INSTALLER CARRIES IT AND `index.ts` OWNS IT (round-1 review,
12164
+ * F-1). The declined "Quit without setup?" - `cancelId: 0`, the default -
12165
+ * lets a quit abort and leaves the process serving, which means any quit
12166
+ * that was in flight is now CANCELLED and the app must stop claiming
12167
+ * otherwise: without a release, `index.ts`'s quit state stays set and every
12168
+ * later second launch and Dock click is refused for the process's life
12169
+ * although the app is running normally. The dialog is the ONE cancellation
12170
+ * a running quit has (see `../quit-state` for the sweep); this module never
12171
+ * reaches for the app's state itself, so the installer stays drivable in a
12172
+ * test and the single release site stays greppable. Optional because the
12173
+ * harness constructs installers with no app around them, and a release that
12174
+ * fires where no quit exists clears an already-false state.
12175
+ */
12176
+ onQuitCancelled;
12095
12177
  /*
12096
12178
  * The last phase announced to the setup window, and whether a failure is
12097
12179
  * currently on screen with nobody's answer yet.
@@ -12203,8 +12285,14 @@ ${error instanceof Error ? error.message : String(error ?? "")}`;
12203
12285
  }
12204
12286
  /**
12205
12287
  * Constructor
12288
+ *
12289
+ * `options.onQuitCancelled` is `index.ts`'s one release for the app's quit
12290
+ * state (see the field's own note); it is handed in rather than imported so
12291
+ * this module never depends on the app's lifecycle and its test can drive
12292
+ * the declined answer with a spy.
12206
12293
  */
12207
- constructor() {
12294
+ constructor(options = {}) {
12295
+ this.onQuitCancelled = options.onQuitCancelled;
12208
12296
  this.venvPath = managedVenvPath({
12209
12297
  platform: process.platform,
12210
12298
  home: electron.app.getPath("home"),
@@ -12851,6 +12939,7 @@ ${result.stdout}`,
12851
12939
  "Setup quit declined from the setup window",
12852
12940
  LogFileType.INSTALLER
12853
12941
  );
12942
+ this.onQuitCancelled?.();
12854
12943
  return;
12855
12944
  }
12856
12945
  this.attemptCancelled = inFlight;
@@ -32512,8 +32601,8 @@ function createMiniView(options) {
32512
32601
  backgroundThrottling: false,
32513
32602
  /*
32514
32603
  * The argv the preload reads SYNCHRONOUSLY, and both entries are
32515
- * deliberate: the chrome facts because the keycap's spelling (⌘⌥
32516
- * against Ctrl+Alt) is a first-frame fact with no IPC round trip to
32604
+ * deliberate: the chrome facts because the keycap's spelling (⌘⌥⇧
32605
+ * against Ctrl+Alt+Shift) is a first-frame fact with no IPC round trip to
32517
32606
  * wait for — the main window composes the same entry through
32518
32607
  * `windowChromeArgumentFor` — and an EXPLICIT telemetry `off` because
32519
32608
  * this window mounts no telemetry surface at all (§D.1), and the
@@ -32613,6 +32702,18 @@ function rememberPickedDirectory(kind, filePaths, directoryPicked = false) {
32613
32702
  if (!first) return;
32614
32703
  lastPickedDirectory.set(kind, directoryPicked ? first : path$1.dirname(first));
32615
32704
  }
32705
+ function createQuitState() {
32706
+ let quitting = false;
32707
+ return {
32708
+ begin: () => {
32709
+ quitting = true;
32710
+ },
32711
+ cancel: () => {
32712
+ quitting = false;
32713
+ },
32714
+ isQuitting: () => quitting
32715
+ };
32716
+ }
32616
32717
  function titlebarOptions(platform, chrome) {
32617
32718
  if (platform === "darwin") {
32618
32719
  return { titleBarStyle: "hidden" };
@@ -32803,10 +32904,10 @@ async function waitForFleetIdle(input) {
32803
32904
  fleet: (await input.readRoster())?.length ?? 0
32804
32905
  };
32805
32906
  }
32806
- function fleetDrainRefusalSentence(outcome, installLanded = false) {
32907
+ function fleetDrainRefusalSentence(outcome) {
32807
32908
  const minutes = Math.max(1, Math.round(outcome.waitedMs / 6e4));
32808
32909
  const waited = `${minutes} minute${minutes === 1 ? "" : "s"}`;
32809
- const closing = installLanded ? "The install itself has landed, and the server keeps running the build it loaded until it can restart onto it; the app will offer this update again." : "Nothing was installed and the server keeps running the build it loaded; the app will offer this update again.";
32910
+ const closing = "Nothing was installed and the server keeps running the build it loaded; the app will offer this update again.";
32810
32911
  if (outcome.because === "unknown") {
32811
32912
  const lead2 = outcome.credentialsRefused ? "The server refused this app's credentials, so the app could not read which sessions are running on this machine." : "The app could not read which sessions are running on this machine, so it did not update the server.";
32812
32913
  return `${lead2}
@@ -32876,7 +32977,10 @@ async function reengageDisplacedSessions(input) {
32876
32977
  const finalRead = await input.readRoster();
32877
32978
  if (finalRead !== null) after = finalRead;
32878
32979
  const displaced = displacedSessions(input.before, after);
32879
- const stillResident = snapshot2.filter((row) => stillLive.has(row.sessionId));
32980
+ const stillLiveAtEnd = stillLiveIn(finalRead) ?? stillLive;
32981
+ const stillResident = snapshot2.filter(
32982
+ (row) => stillLiveAtEnd.has(row.sessionId)
32983
+ );
32880
32984
  const engaged = [];
32881
32985
  const failed = [];
32882
32986
  for (const row of displaced) {
@@ -34179,15 +34283,17 @@ class UpdateService {
34179
34283
  */
34180
34284
  installPreflightInFlight = false;
34181
34285
  /**
34182
- * How long an update press may hold back for the fleet, and how often it
34183
- * re-reads it.
34286
+ * How long the rebuild install leg may hold back for the fleet, and how often
34287
+ * it re-reads it.
34184
34288
  *
34185
- * FIELDS rather than the module's constants read in place, because both halves
34186
- * are waited on inside one press and the harness has to be able to drive a wait
34187
- * in milliseconds instead of ten minutes (`scripts/update-robustness.test.mjs`,
34188
- * the same lever `waitForBackendVersion` and the install budgets already are).
34189
- * The values they start at are the host tool's own, in
34190
- * `backend/fleet-drain.ts`, where the reasoning for the ten minutes lives.
34289
+ * FIELDS rather than the module's constants read in place, because the wait has
34290
+ * to be drivable in milliseconds instead of ten minutes
34291
+ * (`scripts/update-robustness.test.mjs`, the same lever `waitForBackendVersion`
34292
+ * and the install budgets already are). The values they start at are the host
34293
+ * tool's own, in `backend/fleet-drain.ts`, where the reasoning for the ten
34294
+ * minutes lives - and where the module head records that the press reaching
34295
+ * this pair is now only the REBUILD route's install leg (the operator's
34296
+ * directive removed the restart-leg drains).
34191
34297
  */
34192
34298
  fleetDrainBudgetMs = FLEET_DRAIN_BUDGET_MS;
34193
34299
  fleetDrainPollMs = FLEET_DRAIN_POLL_MS;
@@ -34216,13 +34322,17 @@ class UpdateService {
34216
34322
  sessionEngageBeatMs = SESSION_ENGAGE_BEAT_MS;
34217
34323
  sessionEngageHoldMs = SESSION_ENGAGE_HOLD_MS;
34218
34324
  /**
34219
- * How long the press IN FLIGHT has already spent waiting for the fleet.
34325
+ * How long the rebuild press IN FLIGHT has already spent waiting for the fleet.
34220
34326
  *
34221
- * The budget above is the press's, not each drain's (review round 1, m2): a
34222
- * rebuild press drains twice - once before the install and once before the
34223
- * restart - so a per-drain budget let one press hold the button for twenty
34224
- * minutes while the panel promised ten. Reset at the top of every press, in
34225
- * `updateBackend`, because the guarantee is about one press.
34327
+ * The budget above belongs to the PRESS, not to each drain (review round 1,
34328
+ * m2): when the restart legs still drained, a rebuild press drained twice -
34329
+ * once before the install and once before the restart - so a per-drain budget
34330
+ * let one press hold the button for twenty minutes while the panel promised
34331
+ * ten. The restart-leg drains are gone (2026-09-29 directive), so the ledger
34332
+ * now carries at most one leg's spend; it is kept because the promise the
34333
+ * draining copy makes is about the press, and because it is the seam the wait
34334
+ * is driven through. Reset at the top of every press, in `updateBackend`,
34335
+ * because the guarantee is about one press.
34226
34336
  */
34227
34337
  fleetDrainSpentMs = 0;
34228
34338
  /**
@@ -36980,13 +37090,16 @@ ${heal.removed.join("\n")}`,
36980
37090
  * publishes a generation and restarts a daemon. It is the managed global
36981
37091
  * arm's own wording, aimed at this arm's mechanism.
36982
37092
  *
36983
- * AND IT NO LONGER PROMISES A DROPPED TURN. It did, because it described
36984
- * what the press used to do; the press now waits for the running turns to
36985
- * finish before it moves the server (`drainFleetForUpdate`), so the honest
36986
- * consequence is the wait and the sequence, with the cost stated as the
36987
- * time it takes rather than as work it destroys.
37093
+ * AND IT NO LONGER PROMISES A DROPPED TURN - AND NO LONGER PRICES A WAIT. It
37094
+ * did both at different times, because it described what the press used to
37095
+ * do; the operator's directive of 2026-09-29 removed the fleet wait from the
37096
+ * restart legs ("we don't need to wait for all sessions to drain and turn
37097
+ * over... on idle they should switch over"), so the honest consequence names
37098
+ * the sequence, the promised absence of dropped work, and the fleet effect
37099
+ * that remains - sessions still working move onto the new build when they
37100
+ * next stop or go idle - with the cost stated as the time it takes.
36988
37101
  */
36989
- remedy: "The app publishes the new build beside the one the server is using, waits for the turns already running on this machine to finish, and then moves the server onto it, so nothing in flight is cut off. This can take a minute or two.",
37102
+ remedy: "The app publishes the new build beside the one the server is using and then moves the server onto it, so nothing in flight is cut off. Sessions that are still working move onto the new build when they next stop or go idle. This can take a minute or two.",
36990
37103
  detail: `The app started this server itself (${startupMode}).`,
36991
37104
  sourceBuild: false,
36992
37105
  /*
@@ -37660,15 +37773,19 @@ ${heal.removed.join("\n")}`,
37660
37773
  return this.backendService?.servingInstall().owned.owned ?? false;
37661
37774
  }
37662
37775
  /**
37663
- * Wait for the fleet this app can see to go idle, or refuse the update.
37776
+ * Wait for the fleet this app can see to go idle, or refuse the rebuild.
37664
37777
  *
37665
- * THE ONE GATE EVERY RESTART AND EVERY IN-PLACE INSTALL GOES THROUGH. A
37666
- * restart of the server serving this app is `stop(true)` - SIGTERM, ten
37667
- * seconds, SIGKILL - and the daemon's own `retire.py` declines that exit for
37668
- * exactly this reason: its shutdown cancels work it owns. The operator's rule
37669
- * is that nothing kills runtimes en masse, so the app waits for the fleet to
37670
- * drain before it touches anything, and REFUSES with a remedy at the end of
37671
- * its budget rather than cutting off a turn on a timer.
37778
+ * THE ONE REMAINING GATE, AND IT GUARDS THE ONE ROUTE THAT CAN CUT A TURN. This
37779
+ * used to stand in front of every restart and every in-place install. The
37780
+ * operator's directive of 2026-09-29 removed it from the RESTART legs - a
37781
+ * daemon bounce cuts no turns, because session runtimes are detached and
37782
+ * converge onto the new build at their own next idle (see the module head in
37783
+ * `backend/fleet-drain.ts`) - so what is left is the route it still has to
37784
+ * guard: the checkout REBUILD's install leg, which rewrites a tree a live
37785
+ * runtime is reading (`update-install.ts`). There the operator's rule stands:
37786
+ * nothing kills runtimes en masse, so the app waits for the fleet to drain
37787
+ * before the rebuild starts, and REFUSES with a remedy at the end of its
37788
+ * budget rather than cutting off a turn on a timer.
37672
37789
  *
37673
37790
  * WHY THE MANAGER'S OWN READERS. `servingWorkState` is the app's existing
37674
37791
  * busy signal (see `servingWorkStateFromSessions`) and `servingSessionFleet`
@@ -37683,7 +37800,7 @@ ${heal.removed.join("\n")}`,
37683
37800
  * when the update was refused and the caller must not proceed
37684
37801
  */
37685
37802
  async drainFleetForUpdate(input) {
37686
- const { backend, what } = input;
37803
+ const { backend } = input;
37687
37804
  const spentMs = this.fleetDrainSpentMs;
37688
37805
  const remainingMs = Math.max(0, this.fleetDrainBudgetMs - spentMs);
37689
37806
  const outcome = await waitForFleetIdle({
@@ -37710,7 +37827,7 @@ ${heal.removed.join("\n")}`,
37710
37827
  waitedMs: spentMs + elapsedMs
37711
37828
  });
37712
37829
  logger.info(
37713
- `Update waiting for the fleet to drain before it may ${what} (${Math.round(elapsedMs / 1e3)}s so far)`,
37830
+ `Update waiting for the fleet to drain before the rebuild may start (${Math.round(elapsedMs / 1e3)}s so far)`,
37714
37831
  LogFileType.UPDATE_SERVICE
37715
37832
  );
37716
37833
  }
@@ -37718,19 +37835,16 @@ ${heal.removed.join("\n")}`,
37718
37835
  this.fleetDrainSpentMs = spentMs + outcome.waitedMs;
37719
37836
  if (outcome.kind === "drained") {
37720
37837
  logger.info(
37721
- `The fleet is idle (${outcome.fleet} session(s) on the roster, ${outcome.waitedMs}ms waited); the update may ${what}`,
37838
+ `The fleet is idle (${outcome.fleet} session(s) on the roster, ${outcome.waitedMs}ms waited); the rebuild may start`,
37722
37839
  LogFileType.UPDATE_SERVICE
37723
37840
  );
37724
37841
  return true;
37725
37842
  }
37726
- const message = fleetDrainRefusalSentence(
37727
- outcome,
37728
- input.installLanded === true
37729
- );
37843
+ const message = fleetDrainRefusalSentence(outcome);
37730
37844
  const command = input.command ?? null;
37731
37845
  const pressWaitedMs = spentMs + outcome.waitedMs;
37732
37846
  logger.warn(
37733
- `Refusing to ${what}: the fleet did not drain in ${pressWaitedMs}ms (${outcome.because}, ${outcome.busy.length} mid-turn, this leg spent ${outcome.waitedMs}ms). ${message}${command ? ` By hand: ${command}` : ""}`,
37847
+ `Refusing to install: the fleet did not drain in ${pressWaitedMs}ms (${outcome.because}, ${outcome.busy.length} mid-turn, this leg spent ${outcome.waitedMs}ms). ${message}${command ? ` By hand: ${command}` : ""}`,
37734
37848
  LogFileType.UPDATE_SERVICE
37735
37849
  );
37736
37850
  this.sendToRenderer("backend-update-error", {
@@ -37747,17 +37861,7 @@ ${heal.removed.join("\n")}`,
37747
37861
  because: outcome.because,
37748
37862
  waitedMs: pressWaitedMs,
37749
37863
  command,
37750
- credentialsRefused: outcome.credentialsRefused === true,
37751
- /*
37752
- * WHICH REFUSAL THIS IS (design round 2, D6). The heading is the reader's
37753
- * takeaway from a panel they have been looking at for ten minutes, and the
37754
- * three refusal sites are not the same event: the install leg's refusal left
37755
- * nothing on disk, while the two restart-leg refusals happen AFTER the build
37756
- * landed. "The update didn't start" is false on the second pair - the
37757
- * producer's own doc for `installLanded` says so - so the fact travels with
37758
- * the report and the panel keys its heading on it.
37759
- */
37760
- installLanded: input.installLanded === true
37864
+ credentialsRefused: outcome.credentialsRefused === true
37761
37865
  }
37762
37866
  });
37763
37867
  return false;
@@ -37766,15 +37870,22 @@ ${heal.removed.join("\n")}`,
37766
37870
  * Put back the runtimes a restart displaced, and say what came back.
37767
37871
  *
37768
37872
  * Step 5 of the host tool's own order (`~/tools/lop-fleet-update`): the app
37769
- * snapshots the fleet, drains it, moves the server, and then re-engages what
37770
- * the move displaced - the unwatched `daemon`-kind sessions in particular,
37771
- * which nothing else revives. `reengageDisplacedSessions` owns the retire wait
37772
- * and the ordering rules.
37773
- *
37774
- * BEST EFFORT AND NEVER A BLOCKER: this runs after the server is healthy and
37775
- * the update has already been reported, so a displace list that will not come
37776
- * back is a logged fact rather than a failed update. That is deliberate - a
37777
- * `warm` the daemon refuses must not turn a landed update into an error panel.
37873
+ * snapshots the fleet, moves the server, and then re-engages what the move
37874
+ * displaced - the unwatched `daemon`-kind sessions in particular, which nothing
37875
+ * else revives. `reengageDisplacedSessions` owns the retire wait and the
37876
+ * ordering rules.
37877
+ *
37878
+ * BEST EFFORT AND NEVER A BLOCKER: a displace list that will not come back is a
37879
+ * logged fact rather than a failed update. That is deliberate - a `warm` the
37880
+ * daemon refuses must not turn a landed update into an error panel.
37881
+ *
37882
+ * THE RESULT IS RETURNED FOR THE COMPLETION'S COUNT (2026-09-29): the caller
37883
+ * reads `stillResident` - the pre-swap runtimes still resident in the freshest
37884
+ * read at the wait's end, which in the ordinary flow are the sessions still on
37885
+ * the old build - into `sessionsOnOldBuild`. It is a liveness reading rather
37886
+ * than a build read (the field's own docblock names the one narrow over-count).
37887
+ * A failure here answers null and the count is reported as not measured, so
37888
+ * the notice degrades to the numberless sentence rather than inventing a zero.
37778
37889
  */
37779
37890
  async reengageFleetAfterRestart(backend, before) {
37780
37891
  try {
@@ -37796,7 +37907,7 @@ ${heal.removed.join("\n")}`,
37796
37907
  LogFileType.UPDATE_SERVICE
37797
37908
  );
37798
37909
  }
37799
- return;
37910
+ return result;
37800
37911
  }
37801
37912
  if (result.failed.length > 0) {
37802
37913
  logger.warn(
@@ -37804,11 +37915,13 @@ ${heal.removed.join("\n")}`,
37804
37915
  LogFileType.UPDATE_SERVICE
37805
37916
  );
37806
37917
  }
37918
+ return result;
37807
37919
  } catch (error) {
37808
37920
  logger.warn(
37809
37921
  `Could not re-engage the sessions a restart displaced: ${error instanceof Error ? error.message : String(error)}`,
37810
37922
  LogFileType.UPDATE_SERVICE
37811
37923
  );
37924
+ return null;
37812
37925
  }
37813
37926
  }
37814
37927
  /**
@@ -37857,9 +37970,11 @@ ${heal.removed.join("\n")}`,
37857
37970
  *
37858
37971
  * NOT `sessions.message`, deliberately: a message would admit a turn in every
37859
37972
  * conversation this machine holds, which is work and spend the user did not ask
37860
- * for, and the drain that ran before the restart is what makes a notice about
37861
- * interrupted work unnecessary - by construction nothing was mid-turn when the
37862
- * server moved.
37973
+ * for - and since the operator's directive removed the restart-leg drains
37974
+ * (2026-09-29), a re-engaged session may legitimately have been mid-turn when
37975
+ * the server moved: a daemon bounce cuts no turns, and the session's own turn
37976
+ * kept running in its detached runtime. This call starts a runtime; it never
37977
+ * touches a turn.
37863
37978
  */
37864
37979
  async engageSessionRuntime(backend, row) {
37865
37980
  const relay = backend.getStreamRelay();
@@ -38318,8 +38433,7 @@ ${heal.removed.join("\n")}`,
38318
38433
  const fleetBeforeInstall = rebuildRoute ? await this.readFleetSnapshot(backend) : null;
38319
38434
  if (rebuildRoute && !await this.drainFleetForUpdate({
38320
38435
  backend,
38321
- command: freshPlan.updateCommand ?? null,
38322
- what: "install"
38436
+ command: freshPlan.updateCommand ?? null
38323
38437
  })) {
38324
38438
  return false;
38325
38439
  }
@@ -38438,23 +38552,6 @@ ${heal.removed.join("\n")}`,
38438
38552
  });
38439
38553
  return true;
38440
38554
  }
38441
- if (!await this.drainFleetForUpdate({
38442
- backend,
38443
- command: freshPlan.updateCommand ?? null,
38444
- what: "restart",
38445
- /*
38446
- * A press with nothing left to install has no install to report as
38447
- * landed, and saying one was would be the one false thing in the
38448
- * refusal.
38449
- */
38450
- installLanded: !installAlreadyCurrent
38451
- })) {
38452
- logger.info(
38453
- installAlreadyCurrent ? "Nothing was left to install; the restart was refused because the fleet did not drain. The daemon keeps serving the build it loaded." : "The install landed; the restart was refused because the fleet did not drain. The daemon keeps serving the build it loaded.",
38454
- LogFileType.UPDATE_SERVICE
38455
- );
38456
- return false;
38457
- }
38458
38555
  logger.info(
38459
38556
  "Restarting backend service onto the updated install...",
38460
38557
  LogFileType.UPDATE_SERVICE
@@ -38518,13 +38615,12 @@ ${heal.removed.join("\n")}`,
38518
38615
  fleetBeforeInstall,
38519
38616
  fleetBeforeRestart
38520
38617
  );
38521
- if (reengageSnapshot !== null) {
38522
- await this.reengageFleetAfterRestart(backend, reengageSnapshot);
38523
- }
38618
+ const reengage = reengageSnapshot !== null ? await this.reengageFleetAfterRestart(backend, reengageSnapshot) : null;
38524
38619
  this.sendToRenderer("backend-update-completed", {
38525
38620
  installVersion: after,
38526
38621
  runningVersion: reported,
38527
- restarted: true
38622
+ restarted: true,
38623
+ sessionsOnOldBuild: reengage?.stillResident.length ?? null
38528
38624
  });
38529
38625
  return true;
38530
38626
  }
@@ -38873,14 +38969,6 @@ ${reason}` : ""}`,
38873
38969
  return true;
38874
38970
  }
38875
38971
  const fleetAfterPublish = await this.readFleetSnapshot(backend);
38876
- if (!await this.drainFleetForUpdate({
38877
- backend,
38878
- command: null,
38879
- what: "restart",
38880
- installLanded: outcome.replaced
38881
- })) {
38882
- return false;
38883
- }
38884
38972
  logger.info(
38885
38973
  "Restarting backend service onto the published environment...",
38886
38974
  LogFileType.UPDATE_SERVICE
@@ -38969,13 +39057,12 @@ ${reason}` : ""}`,
38969
39057
  fleetAfterPublish,
38970
39058
  fleetBeforeRestart
38971
39059
  );
38972
- if (reengageSnapshot !== null) {
38973
- await this.reengageFleetAfterRestart(backend, reengageSnapshot);
38974
- }
39060
+ const reengage = reengageSnapshot !== null ? await this.reengageFleetAfterRestart(backend, reengageSnapshot) : null;
38975
39061
  this.sendToRenderer("backend-update-completed", {
38976
39062
  installVersion,
38977
39063
  runningVersion: running,
38978
- restarted: true
39064
+ restarted: true,
39065
+ sessionsOnOldBuild: reengage?.stillResident.length ?? null
38979
39066
  });
38980
39067
  return true;
38981
39068
  }
@@ -40166,7 +40253,12 @@ const userShellPath = createUserShellPath({
40166
40253
  log: (message) => logger.info(message, LogFileType.BACKEND)
40167
40254
  });
40168
40255
  const backendService = new BackendServiceManager({ userShellPath });
40169
- const backendInstaller = new BackendInstaller();
40256
+ const quitState = createQuitState();
40257
+ const backendInstaller = new BackendInstaller({
40258
+ // The installer's one route back from a cancelled quit: the declined dialog
40259
+ // answer (`./quit-state` owns why there is exactly one such site).
40260
+ onQuitCancelled: () => quitState.cancel()
40261
+ });
40170
40262
  const reportBackendFailure = (message, fileType) => {
40171
40263
  if (backendService.isShuttingDown()) {
40172
40264
  logger.error(
@@ -40380,6 +40472,16 @@ if (!gotTheLock) {
40380
40472
  }),
40381
40473
  {
40382
40474
  window: mainWindow,
40475
+ /*
40476
+ * Read PER REQUEST rather than captured once: this handler outlives every
40477
+ * window, and the state is LIVE — set at each quit's first `before-quit`
40478
+ * entry, released when the setup dialog declines to stop a run — so a
40479
+ * request that arrives during a quit is refused instead of answered with
40480
+ * a window the shutdown would take down, and a request after a CANCELLED
40481
+ * quit is answered normally (`./quit-state` owns the transitions;
40482
+ * `window-raise.ts` owns the refusal and its line).
40483
+ */
40484
+ quitting: quitState.isQuitting(),
40383
40485
  openConversation: openConversationInWindow ? (session, request) => openConversationInWindow?.(
40384
40486
  session,
40385
40487
  secondInstanceRequest(request)
@@ -40559,7 +40661,10 @@ electron.app.whenReady().then(async () => {
40559
40661
  });
40560
40662
  return "raised the window";
40561
40663
  }
40562
- setupMainWindowWithUpdateService();
40664
+ setupMainWindowWithUpdateService(null, false, {
40665
+ show: windowLaunch.show,
40666
+ trigger: "viewer-focus"
40667
+ });
40563
40668
  return "opened a window";
40564
40669
  }
40565
40670
  },
@@ -40609,7 +40714,7 @@ electron.app.whenReady().then(async () => {
40609
40714
  * this feature's slice for a value that is a launch fact (argv, the
40610
40715
  * launch env, the persisted file) and cannot differ between the two
40611
40716
  * calls. The mini view's visible consumer of it is the platform
40612
- * half: the header's keycap spells ⌘⌥Space against Ctrl+Alt+Space
40717
+ * half: the header's keycap spells ⌘⌥⇧Space against Ctrl+Alt+Shift+Space
40613
40718
  * from exactly this entry.
40614
40719
  */
40615
40720
  chromeMode: resolveLaunchWindowChrome({
@@ -41151,6 +41256,10 @@ electron.app.whenReady().then(async () => {
41151
41256
  });
41152
41257
  }
41153
41258
  function setupMainWindowWithUpdateService(initialSession = null, openCatalogue = false, request = ownLaunchRequest()) {
41259
+ if (quitState.isQuitting()) {
41260
+ reportSkippedWhileQuitting(request, request.show);
41261
+ return;
41262
+ }
41154
41263
  const parked = initialSession === null && !openCatalogue ? parkedLaunches[0] : void 0;
41155
41264
  mainWindow = createWindow(
41156
41265
  parked?.session ?? initialSession,
@@ -41314,6 +41423,10 @@ electron.app.whenReady().then(async () => {
41314
41423
  });
41315
41424
  return;
41316
41425
  }
41426
+ if (quitState.isQuitting()) {
41427
+ reportSkippedWhileQuitting(request, request.show);
41428
+ return;
41429
+ }
41317
41430
  if (!canCreateWindowFor(request.show)) {
41318
41431
  if (sessionId2 !== null) parkLaunch(sessionId2, request);
41319
41432
  return;
@@ -41328,9 +41441,22 @@ electron.app.whenReady().then(async () => {
41328
41441
  setupMainWindowWithUpdateService(launchSession, launchCatalogue);
41329
41442
  electron.app.on("activate", () => {
41330
41443
  if (electron.BrowserWindow.getAllWindows().length === 0) {
41444
+ if (quitState.isQuitting()) {
41445
+ reportSkippedWhileQuitting(
41446
+ { trigger: "activate", report: reportRaise },
41447
+ OPERATOR_SHOW
41448
+ );
41449
+ return;
41450
+ }
41331
41451
  setupMainWindowWithUpdateService(null, false, {
41332
41452
  show: OPERATOR_SHOW,
41333
- trigger: "initial-present"
41453
+ /*
41454
+ * The request names itself on its raise line. It used to present as
41455
+ * `initial-present` — this process's own launch — which is what a Dock
41456
+ * click is not, and the log's whole job is attribution; the refusal
41457
+ * above is the same request and must carry the same name.
41458
+ */
41459
+ trigger: "activate"
41334
41460
  });
41335
41461
  }
41336
41462
  });
@@ -41410,6 +41536,7 @@ const holdQuitForSessionCookieSnapshot = createSessionCookieQuitHold({
41410
41536
  log: (message) => logger.warn(message, LogFileType.BACKEND)
41411
41537
  });
41412
41538
  electron.app.on("before-quit", async (event) => {
41539
+ quitState.begin();
41413
41540
  if (await holdQuitForSessionCookieSnapshot(event)) return;
41414
41541
  logger.info("App is about to quit", LogFileType.BACKEND);
41415
41542
  if (parkedLaunches.length > 0) {
@@ -1 +1 @@
1
- import{e as o,c as b,g as v,k as O,h as P,j as p,l as w,m as A,n as x,t as c,o as N}from"./_baseUniq-DD_DKvaU.js";import{as as g,aa as y,at as E,au as F,av as M,aw as I,ax as _,ay as $,az as B,aA as T}from"./mermaid.core-BrRc254F.js";var S=/\s/;function z(n){for(var r=n.length;r--&&S.test(n.charAt(r)););return r}var G=/^\s+/;function H(n){return n&&n.slice(0,z(n)+1).replace(G,"")}var m=NaN,L=/^[-+]0x[0-9a-f]+$/i,R=/^0b[01]+$/i,q=/^0o[0-7]+$/i,C=parseInt;function K(n){if(typeof n=="number")return n;if(o(n))return m;if(g(n)){var r=typeof n.valueOf=="function"?n.valueOf():n;n=g(r)?r+"":r}if(typeof n!="string")return n===0?n:+n;n=H(n);var t=R.test(n);return t||q.test(n)?C(n.slice(2),t?2:8):L.test(n)?m:+n}var W=1/0,X=17976931348623157e292;function Y(n){if(!n)return n===0?n:0;if(n=K(n),n===W||n===-1/0){var r=n<0?-1:1;return r*X}return n===n?n:0}function D(n){var r=Y(n),t=r%1;return r===r?t?r-t:r:0}function fn(n){var r=n==null?0:n.length;return r?b(n):[]}var l=Object.prototype,J=l.hasOwnProperty,dn=y(function(n,r){n=Object(n);var t=-1,e=r.length,a=e>2?r[2]:void 0;for(a&&E(r[0],r[1],a)&&(e=1);++t<e;)for(var f=r[t],i=F(f),s=-1,d=i.length;++s<d;){var u=i[s],h=n[u];(h===void 0||M(h,l[u])&&!J.call(n,u))&&(n[u]=f[u])}return n});function un(n){var r=n==null?0:n.length;return r?n[r-1]:void 0}function Q(n){return function(r,t,e){var a=Object(r);if(!I(r)){var f=v(t);r=O(r),t=function(s){return f(a[s],s,a)}}var i=n(r,t,e);return i>-1?a[f?r[i]:i]:void 0}}var U=Math.max;function Z(n,r,t){var e=n==null?0:n.length;if(!e)return-1;var a=t==null?0:D(t);return a<0&&(a=U(e+a,0)),P(n,v(r),a)}var hn=Q(Z);function V(n,r){var t=-1,e=I(n)?Array(n.length):[];return p(n,function(a,f,i){e[++t]=r(a,f,i)}),e}function gn(n,r){var t=_(n)?w:V;return t(n,v(r))}var j=Object.prototype,k=j.hasOwnProperty;function nn(n,r){return n!=null&&k.call(n,r)}function vn(n,r){return n!=null&&A(n,r,nn)}function rn(n,r){return n<r}function tn(n,r,t){for(var e=-1,a=n.length;++e<a;){var f=n[e],i=r(f);if(i!=null&&(s===void 0?i===i&&!o(i):t(i,s)))var s=i,d=f}return d}function mn(n){return n&&n.length?tn(n,$,rn):void 0}function an(n,r,t,e){if(!g(n))return n;r=x(r,n);for(var a=-1,f=r.length,i=f-1,s=n;s!=null&&++a<f;){var d=c(r[a]),u=t;if(d==="__proto__"||d==="constructor"||d==="prototype")return n;if(a!=i){var h=s[d];u=void 0,u===void 0&&(u=g(h)?h:B(r[a+1])?[]:{})}T(s,d,u),s=s[d]}return n}function on(n,r,t){for(var e=-1,a=r.length,f={};++e<a;){var i=r[e],s=N(n,i);t(s,i)&&an(f,x(i,n),s)}return f}export{rn as a,tn as b,V as c,on as d,mn as e,fn as f,hn as g,vn as h,dn as i,D as j,un as l,gn as m,Y as t};
1
+ import{e as o,c as b,g as v,k as O,h as P,j as p,l as w,m as A,n as x,t as c,o as N}from"./_baseUniq-cZFY6WR-.js";import{as as g,aa as y,at as E,au as F,av as M,aw as I,ax as _,ay as $,az as B,aA as T}from"./mermaid.core-Dol6F2oY.js";var S=/\s/;function z(n){for(var r=n.length;r--&&S.test(n.charAt(r)););return r}var G=/^\s+/;function H(n){return n&&n.slice(0,z(n)+1).replace(G,"")}var m=NaN,L=/^[-+]0x[0-9a-f]+$/i,R=/^0b[01]+$/i,q=/^0o[0-7]+$/i,C=parseInt;function K(n){if(typeof n=="number")return n;if(o(n))return m;if(g(n)){var r=typeof n.valueOf=="function"?n.valueOf():n;n=g(r)?r+"":r}if(typeof n!="string")return n===0?n:+n;n=H(n);var t=R.test(n);return t||q.test(n)?C(n.slice(2),t?2:8):L.test(n)?m:+n}var W=1/0,X=17976931348623157e292;function Y(n){if(!n)return n===0?n:0;if(n=K(n),n===W||n===-1/0){var r=n<0?-1:1;return r*X}return n===n?n:0}function D(n){var r=Y(n),t=r%1;return r===r?t?r-t:r:0}function fn(n){var r=n==null?0:n.length;return r?b(n):[]}var l=Object.prototype,J=l.hasOwnProperty,dn=y(function(n,r){n=Object(n);var t=-1,e=r.length,a=e>2?r[2]:void 0;for(a&&E(r[0],r[1],a)&&(e=1);++t<e;)for(var f=r[t],i=F(f),s=-1,d=i.length;++s<d;){var u=i[s],h=n[u];(h===void 0||M(h,l[u])&&!J.call(n,u))&&(n[u]=f[u])}return n});function un(n){var r=n==null?0:n.length;return r?n[r-1]:void 0}function Q(n){return function(r,t,e){var a=Object(r);if(!I(r)){var f=v(t);r=O(r),t=function(s){return f(a[s],s,a)}}var i=n(r,t,e);return i>-1?a[f?r[i]:i]:void 0}}var U=Math.max;function Z(n,r,t){var e=n==null?0:n.length;if(!e)return-1;var a=t==null?0:D(t);return a<0&&(a=U(e+a,0)),P(n,v(r),a)}var hn=Q(Z);function V(n,r){var t=-1,e=I(n)?Array(n.length):[];return p(n,function(a,f,i){e[++t]=r(a,f,i)}),e}function gn(n,r){var t=_(n)?w:V;return t(n,v(r))}var j=Object.prototype,k=j.hasOwnProperty;function nn(n,r){return n!=null&&k.call(n,r)}function vn(n,r){return n!=null&&A(n,r,nn)}function rn(n,r){return n<r}function tn(n,r,t){for(var e=-1,a=n.length;++e<a;){var f=n[e],i=r(f);if(i!=null&&(s===void 0?i===i&&!o(i):t(i,s)))var s=i,d=f}return d}function mn(n){return n&&n.length?tn(n,$,rn):void 0}function an(n,r,t,e){if(!g(n))return n;r=x(r,n);for(var a=-1,f=r.length,i=f-1,s=n;s!=null&&++a<f;){var d=c(r[a]),u=t;if(d==="__proto__"||d==="constructor"||d==="prototype")return n;if(a!=i){var h=s[d];u=void 0,u===void 0&&(u=g(h)?h:B(r[a+1])?[]:{})}T(s,d,u),s=s[d]}return n}function on(n,r,t){for(var e=-1,a=r.length,f={};++e<a;){var i=r[e],s=N(n,i);t(s,i)&&an(f,x(i,n),s)}return f}export{rn as a,tn as b,V as c,on as d,mn as e,fn as f,hn as g,vn as h,dn as i,D as j,un as l,gn as m,Y as t};