pilotswarm 0.5.69 → 0.5.71

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 (80) hide show
  1. package/package.json +2 -2
  2. package/ui/core/src/controller.js +3 -1
  3. package/ui/core/src/history.js +3 -1
  4. package/ui/core/src/moa.js +2 -2
  5. package/ui/core/src/native-tasks.js +46 -2
  6. package/ui/core/src/reducer.js +14 -2
  7. package/ui/core/src/selectors.js +41 -16
  8. package/ui/core/src/session-sort.js +45 -0
  9. package/ui/core/src/state.js +3 -0
  10. package/ui/react/src/chat-call-line.js +17 -0
  11. package/ui/react/src/native-task-card.js +53 -23
  12. package/ui/react/src/web-app.js +100 -48
  13. package/web/dist/assets/{abnfDiagram-VRR7QNED-DCEEpIGf.js → abnfDiagram-VRR7QNED-C1caNr4U.js} +1 -1
  14. package/web/dist/assets/{arc-_RJw0dJ3.js → arc-BufdFJYK.js} +1 -1
  15. package/web/dist/assets/{architectureDiagram-ZJ3FMSHR-Bze_PsYG.js → architectureDiagram-ZJ3FMSHR-C0vQblUK.js} +1 -1
  16. package/web/dist/assets/{blockDiagram-677ZJIJ3-CZaMO9H-.js → blockDiagram-677ZJIJ3-B6PYWI9u.js} +1 -1
  17. package/web/dist/assets/{c4Diagram-LMCZKHZV-Dzr58V1d.js → c4Diagram-LMCZKHZV-DFoaVeMm.js} +1 -1
  18. package/web/dist/assets/channel-CDzPwSI9.js +1 -0
  19. package/web/dist/assets/{chunk-2Q5K7J3B-1IO7uTFx.js → chunk-2Q5K7J3B-CxFBb-8y.js} +1 -1
  20. package/web/dist/assets/{chunk-32BRIVSS-DKdpRP0l.js → chunk-32BRIVSS-DO1G8AVc.js} +1 -1
  21. package/web/dist/assets/{chunk-5VM5RSS4-CxyhZOh5.js → chunk-5VM5RSS4-spE4bKSd.js} +1 -1
  22. package/web/dist/assets/{chunk-EX3LRPZG-DWY7moCs.js → chunk-EX3LRPZG-Bc_eUP5F.js} +1 -1
  23. package/web/dist/assets/{chunk-JWPE2WC7-By7oiTbd.js → chunk-JWPE2WC7-CGM2GAMX.js} +1 -1
  24. package/web/dist/assets/{chunk-MOJQB5TN-CS-m-Pv3.js → chunk-MOJQB5TN-CHdrVT1z.js} +1 -1
  25. package/web/dist/assets/{chunk-RYQCIY6F-Cxykz4-E.js → chunk-RYQCIY6F-BWJK7-AW.js} +1 -1
  26. package/web/dist/assets/{chunk-V7JOEXUC-Dwl0aU9m.js → chunk-V7JOEXUC-D8tgpQwK.js} +1 -1
  27. package/web/dist/assets/{chunk-VR4S4FIN-BERWiLR7.js → chunk-VR4S4FIN-BP86JfVu.js} +1 -1
  28. package/web/dist/assets/{chunk-XXDRQBXY-CZ0e721z.js → chunk-XXDRQBXY-Ctq_LUrs.js} +1 -1
  29. package/web/dist/assets/classDiagram-OUVF2IWQ-DdcABn-U.js +1 -0
  30. package/web/dist/assets/classDiagram-v2-EOCWNBFH-DdcABn-U.js +1 -0
  31. package/web/dist/assets/{cose-bilkent-JH36ORCC-RLgoKX1J.js → cose-bilkent-JH36ORCC-DNvC4thT.js} +1 -1
  32. package/web/dist/assets/{cynefin-VYW2F7L2-CUvcvCFo.js → cynefin-VYW2F7L2-3zVj2GvI.js} +1 -1
  33. package/web/dist/assets/{cynefinDiagram-TSTJHNR4-D2ML_npa.js → cynefinDiagram-TSTJHNR4-DQbITfsJ.js} +1 -1
  34. package/web/dist/assets/{dagre-VKFMJZFB-BHG6-avE.js → dagre-VKFMJZFB-BkGAcDyj.js} +1 -1
  35. package/web/dist/assets/{diagram-FQU43EPY-ynOb8q0h.js → diagram-FQU43EPY-D3lsgelm.js} +1 -1
  36. package/web/dist/assets/{diagram-G47NLZAW-BLHAADd0.js → diagram-G47NLZAW-C2rO9e3d.js} +1 -1
  37. package/web/dist/assets/{diagram-NH7WQ7WH-DwOMd4DW.js → diagram-NH7WQ7WH-DJBwtT8q.js} +1 -1
  38. package/web/dist/assets/{diagram-OA4YK3LP-DZWnpqT9.js → diagram-OA4YK3LP-C-SAwEHZ.js} +1 -1
  39. package/web/dist/assets/{diagram-WEI45ONY-BMcvO3Pf.js → diagram-WEI45ONY-BpXMlmKz.js} +1 -1
  40. package/web/dist/assets/{ebnfDiagram-CCIWWBDH-CRX9h0gP.js → ebnfDiagram-CCIWWBDH-DwxUgEmE.js} +1 -1
  41. package/web/dist/assets/{erDiagram-Q63AITRT-Con2S52S.js → erDiagram-Q63AITRT-DNZMCmYz.js} +1 -1
  42. package/web/dist/assets/{flowDiagram-23GEKE2U-wg4unvdR.js → flowDiagram-23GEKE2U-CUlGtnWV.js} +1 -1
  43. package/web/dist/assets/{ganttDiagram-NO4QXBWP-CAg65Xfj.js → ganttDiagram-NO4QXBWP-DCj6zkyt.js} +1 -1
  44. package/web/dist/assets/{gitGraphDiagram-IHSO6WYX-5u02gmfN.js → gitGraphDiagram-IHSO6WYX-Q6UP_dgi.js} +1 -1
  45. package/web/dist/assets/index-23y0f1it.js +24 -0
  46. package/web/dist/assets/index-BXR-II2L.css +1 -0
  47. package/web/dist/assets/{infoDiagram-FWYZ7A6U-DW830L4J.js → infoDiagram-FWYZ7A6U-Cwn8XNQT.js} +1 -1
  48. package/web/dist/assets/{ishikawaDiagram-FXEZZL3T-6Qr30UBj.js → ishikawaDiagram-FXEZZL3T-BaMvGBAo.js} +1 -1
  49. package/web/dist/assets/{journeyDiagram-5HDEW3XC-BHCjdAv1.js → journeyDiagram-5HDEW3XC-DK95FJ0t.js} +1 -1
  50. package/web/dist/assets/{kanban-definition-HUTT4EX6-PGpXvhY7.js → kanban-definition-HUTT4EX6-C6W6RJLm.js} +1 -1
  51. package/web/dist/assets/{linear-CuN5Qi_I.js → linear-Un37Oyxr.js} +1 -1
  52. package/web/dist/assets/{mermaid.core-BEG_GOf7.js → mermaid.core-i8uqvLPa.js} +4 -4
  53. package/web/dist/assets/{mindmap-definition-LN4V7U3C-Bbi2gb0f.js → mindmap-definition-LN4V7U3C-d_cgq1KW.js} +1 -1
  54. package/web/dist/assets/{papaparse.min-LDhOsJ62.js → papaparse.min-BiJEkQ8f.js} +1 -1
  55. package/web/dist/assets/{pegDiagram-2B236MQR-IZ3AowOt.js → pegDiagram-2B236MQR-5QRWM5AP.js} +1 -1
  56. package/web/dist/assets/{pieDiagram-ENE6RG2P-QnG3Rlhe.js → pieDiagram-ENE6RG2P-VIZXsjFV.js} +1 -1
  57. package/web/dist/assets/pilotswarm-D7Q48waO.js +109 -0
  58. package/web/dist/assets/{quadrantDiagram-ABIIQ3AL-BIB7xhGf.js → quadrantDiagram-ABIIQ3AL-DMOx841b.js} +1 -1
  59. package/web/dist/assets/{railroadDiagram-RFXS5EU6-CHbggWfd.js → railroadDiagram-RFXS5EU6-lTWzjdcd.js} +1 -1
  60. package/web/dist/assets/{requirementDiagram-TGXJPOKE-CgNGJVBn.js → requirementDiagram-TGXJPOKE-BE5SpiNy.js} +1 -1
  61. package/web/dist/assets/{sankeyDiagram-HTMAVEWB-B1GfGCwn.js → sankeyDiagram-HTMAVEWB-C3LYWQTA.js} +1 -1
  62. package/web/dist/assets/{sequenceDiagram-DBY2YBRQ-D-Bfj-RU.js → sequenceDiagram-DBY2YBRQ-BTCp88tQ.js} +1 -1
  63. package/web/dist/assets/{sizeCapture-X5ZJPWSS-Ca-mVfMN.js → sizeCapture-X5ZJPWSS-Ppzj8n5l.js} +1 -1
  64. package/web/dist/assets/{stateDiagram-2N3HPSRC-5gIoJ_8A.js → stateDiagram-2N3HPSRC-Ch_iZ_cQ.js} +1 -1
  65. package/web/dist/assets/stateDiagram-v2-6OUMAXLB-BbJN7t8_.js +1 -0
  66. package/web/dist/assets/{swimlanes-5IMT3BWC-HxN6_3nA.js → swimlanes-5IMT3BWC-BX4-Oeby.js} +2 -2
  67. package/web/dist/assets/swimlanesDiagram-G3AALYLV-0UA1VebA.js +8 -0
  68. package/web/dist/assets/{timeline-definition-FHXFAJF6-CSkNwYwY.js → timeline-definition-FHXFAJF6-B1l-6l6u.js} +1 -1
  69. package/web/dist/assets/{vennDiagram-L72KCM5P-o6qvAiNl.js → vennDiagram-L72KCM5P-Grpa6wFZ.js} +1 -1
  70. package/web/dist/assets/{wardleyDiagram-EHGQE667-HcUO3YZZ.js → wardleyDiagram-EHGQE667-B5bXnFlL.js} +1 -1
  71. package/web/dist/assets/{xychartDiagram-FW5EYKEG-DmNJJPi3.js → xychartDiagram-FW5EYKEG-BkELQtgc.js} +1 -1
  72. package/web/dist/index.html +3 -3
  73. package/web/dist/assets/channel-CHAZ3LVB.js +0 -1
  74. package/web/dist/assets/classDiagram-OUVF2IWQ-CXv3ioyD.js +0 -1
  75. package/web/dist/assets/classDiagram-v2-EOCWNBFH-CXv3ioyD.js +0 -1
  76. package/web/dist/assets/index-BT3MiUPE.css +0 -1
  77. package/web/dist/assets/index-DzjecAo8.js +0 -24
  78. package/web/dist/assets/pilotswarm-BNTnbu9f.js +0 -109
  79. package/web/dist/assets/stateDiagram-v2-6OUMAXLB-C_IKdqOV.js +0 -1
  80. package/web/dist/assets/swimlanesDiagram-G3AALYLV-B8jNOz1z.js +0 -8
@@ -1,3 +1,5 @@
1
+ import { normalizeSessionSortMode, normalizeSessionUsage } from "../../core/src/session-sort.js";
2
+ import { ChatCallLine } from "./chat-call-line.js";
1
3
  import React from "react";
2
4
  import { FeatureFlagsPanel } from "./feature-flags-panel.js";
3
5
  import { NativeTaskCard } from "./native-task-card.js";
@@ -290,6 +292,8 @@ function clearBrowserPreferenceCache() {
290
292
  function normalizeProfileSettings(settings) {
291
293
  const candidate = settings && typeof settings === "object" && !Array.isArray(settings) ? settings : {};
292
294
  const normalized = {};
295
+ if (hasOwn(candidate, "sessionSortMode")) normalized.sessionSortMode = normalizeSessionSortMode(candidate.sessionSortMode);
296
+ if (hasOwn(candidate, "sessionUsedAt")) normalized.sessionUsedAt = normalizeSessionUsage(candidate.sessionUsedAt);
293
297
  if (hasOwn(candidate, "moa")) normalized.moa = normalizeMoa(candidate.moa);
294
298
  if (typeof candidate.themeId === "string" && candidate.themeId.trim()) {
295
299
  normalized.themeId = candidate.themeId.trim();
@@ -440,7 +444,7 @@ function profileViewState(root) {
440
444
  return {
441
445
  ...root.ui, ...root.ui.layout,
442
446
  ownerFilter: root.sessions.ownerFilter, pinnedIds: root.sessions.pinnedIds,
443
- manualOrder: root.sessions.manualOrder, collapsedSessionIds: root.sessions.collapsedIds,
447
+ manualOrder: root.sessions.manualOrder, sessionSortMode: root.sessions.sortMode, sessionUsedAt: root.sessions.usedAt, collapsedSessionIds: root.sessions.collapsedIds,
444
448
  activeSessionId: root.sessions.activeSessionId, canvasPrefs: root.canvas?.prefs,
445
449
  };
446
450
  }
@@ -463,6 +467,8 @@ function profileSettingsFromViewState(state, preservedOtherTouchScale = null, pr
463
467
  },
464
468
  pinnedSessionIds: state.pinnedIds,
465
469
  sessionOrder: state.manualOrder,
470
+ sessionSortMode: state.sessionSortMode,
471
+ sessionUsedAt: state.sessionUsedAt,
466
472
  collapsedSessionIds: state.collapsedSessionIds,
467
473
  activeSessionId: state.activeSessionId,
468
474
  // rightPaneMode describes the DESKTOP right column; a phone has no
@@ -527,6 +533,8 @@ function buildDefaultProfileSettingsFromState(state, preservedOtherTouchScale =
527
533
  layoutAdjustments: state?.ui?.layout,
528
534
  pinnedSessionIds: state?.sessions?.pinnedIds,
529
535
  sessionOrder: state?.sessions?.manualOrder,
536
+ sessionSortMode: state?.sessions?.sortMode,
537
+ sessionUsedAt: state?.sessions?.usedAt,
530
538
  collapsedSessionIds: state?.sessions?.collapsedIds,
531
539
  activeSessionId: state?.sessions?.activeSessionId,
532
540
  ...(isNarrowViewport()
@@ -574,6 +582,8 @@ function materializeProfileSettings(remoteSettings, defaults) {
574
582
  // here is DROPPED at startup — and the save effect then writes the
575
583
  // empty value straight back over the stored one. Leaving sessionOrder
576
584
  // out made every placement survive exactly until the next reload.
585
+ sessionSortMode: normalizedRemote.sessionSortMode ?? normalizedDefaults.sessionSortMode,
586
+ sessionUsedAt: normalizedRemote.sessionUsedAt ?? normalizedDefaults.sessionUsedAt,
577
587
  sessionOrder: hasOwn(normalizedRemote, "sessionOrder")
578
588
  ? normalizedRemote.sessionOrder
579
589
  : normalizedDefaults.sessionOrder,
@@ -1380,21 +1390,6 @@ function SystemNoticeLine({ line, theme }) {
1380
1390
  : null);
1381
1391
  }
1382
1392
 
1383
- function ChatCallLine({ line }) {
1384
- const [open, setOpen] = React.useState(false);
1385
- return React.createElement("details", {
1386
- className: "ps-system-notice ps-chat-call",
1387
- "data-call-id": line.callKey,
1388
- onToggle: event => setOpen(event.currentTarget.open),
1389
- },
1390
- React.createElement("summary", { className: "ps-system-notice-summary ps-chat-call-summary" },
1391
- React.createElement("span", { className: "ps-chat-call-tag" }, line.category || "Tool"),
1392
- React.createElement("span", { className: "ps-system-notice-summary-text" }, line.text),
1393
- line.status ? React.createElement("span", { className: `ps-chat-call-status${line.status === "Failed" ? " is-failed" : ""}` }, line.status) : null),
1394
- open ? React.createElement("div", { className: "ps-system-notice-body" },
1395
- line.time ? React.createElement("div", { className: "ps-chat-call-time" }, line.time) : null,
1396
- React.createElement("pre", { className: "ps-chat-call-payload" }, line.body)) : null);
1397
- }
1398
1393
 
1399
1394
  function ChatActivityRun({ calls }) {
1400
1395
  const latest = calls[calls.length - 1] || {};
@@ -2044,6 +2039,10 @@ function ArtifactLink({ artifactRef }) {
2044
2039
  */
2045
2040
  function openArtifactFromChat(controller, sessionId, filename) {
2046
2041
  if (!controller?.revealArtifact) return;
2042
+ if (controller.openChatArtifact) {
2043
+ Promise.resolve(controller.openChatArtifact(sessionId, filename)).catch(() => {});
2044
+ return;
2045
+ }
2047
2046
  const isPhone = typeof window !== "undefined"
2048
2047
  && typeof window.matchMedia === "function"
2049
2048
  && window.matchMedia("(max-width: 920px)").matches;
@@ -5053,8 +5052,28 @@ function useAxisLockedPan(ref, enabled = true) {
5053
5052
  }, [ref, enabled]);
5054
5053
  }
5055
5054
 
5056
- function SessionSearchControl({ query = "", onQuery, matchCount = 0, mobile = false, listRef = null }) {
5055
+ const SessionSearchControl = React.memo(function SessionSearchControl({ query = "", onQuery, matchCount = 0, mobile = false, listRef = null }) {
5056
+ // Keep typing local: expensive list filtering and external-store updates
5057
+ // must never be part of the input's immediate render path.
5058
+ const [draft, setDraft] = React.useState(query);
5057
5059
  const [mobileOpen, setMobileOpen] = React.useState(Boolean(query));
5060
+ const timer = React.useRef(null);
5061
+ const published = React.useRef(query);
5062
+ const composing = React.useRef(false);
5063
+ const onQueryRef = React.useRef(onQuery);
5064
+ onQueryRef.current = onQuery;
5065
+ const cancel = () => { clearTimeout(timer.current); timer.current = null; };
5066
+ const publish = value => { cancel(); published.current = value; onQueryRef.current?.(value); };
5067
+ const schedule = value => {
5068
+ cancel();
5069
+ if (!composing.current) timer.current = setTimeout(() => publish(value), 150);
5070
+ };
5071
+ React.useEffect(() => () => clearTimeout(timer.current), []);
5072
+ React.useEffect(() => {
5073
+ // An acknowledgement of our prior edit must not erase newer typing.
5074
+ if (query === published.current) return;
5075
+ cancel(); published.current = query; setDraft(query);
5076
+ }, [query]);
5058
5077
  const inputRef = React.useRef(null);
5059
5078
  React.useEffect(() => {
5060
5079
  if (query) setMobileOpen(true);
@@ -5064,12 +5083,11 @@ function SessionSearchControl({ query = "", onQuery, matchCount = 0, mobile = fa
5064
5083
  requestAnimationFrame(() => inputRef.current?.focus({ preventScroll: true }));
5065
5084
  };
5066
5085
  const closeOrClear = () => {
5067
- if (query) onQuery?.("");
5086
+ if (draft || query) { setDraft(""); publish(""); }
5068
5087
  else setMobileOpen(false);
5069
5088
  };
5070
- const resultLabel = query
5071
- ? `${matchCount} ${matchCount === 1 ? "match" : "matches"}`
5072
- : "";
5089
+ const resultLabel = draft !== query ? "Searching…" : draft
5090
+ ? `${matchCount} ${matchCount === 1 ? "match" : "matches"}` : "";
5073
5091
  return React.createElement("div", {
5074
5092
  className: `ps-session-search${mobileOpen ? " is-open" : ""}`,
5075
5093
  "data-session-search": "true",
@@ -5089,8 +5107,10 @@ function SessionSearchControl({ query = "", onQuery, matchCount = 0, mobile = fa
5089
5107
  inputMode: "search",
5090
5108
  "aria-label": "Find a session",
5091
5109
  placeholder: "Find a session…",
5092
- value: query,
5093
- onChange: (event) => onQuery?.(event.target.value),
5110
+ value: draft,
5111
+ onChange: event => { const value = event.target.value; setDraft(value); schedule(value); },
5112
+ onCompositionStart: () => { composing.current = true; cancel(); },
5113
+ onCompositionEnd: event => { composing.current = false; schedule(event.currentTarget.value); },
5094
5114
  onKeyDown: (event) => {
5095
5115
  if (event.key === "Escape") {
5096
5116
  event.preventDefault();
@@ -5098,10 +5118,9 @@ function SessionSearchControl({ query = "", onQuery, matchCount = 0, mobile = fa
5098
5118
  return;
5099
5119
  }
5100
5120
  if (event.key !== "ArrowDown") return;
5101
- const first = listRef?.current?.querySelector?.(".ps-session-list-button");
5102
- if (!first) return;
5103
5121
  event.preventDefault();
5104
- first.focus({ preventScroll: true });
5122
+ if (draft !== query) publish(draft);
5123
+ requestAnimationFrame(() => listRef?.current?.querySelector?.(".ps-session-list-button")?.focus({ preventScroll: true }));
5105
5124
  },
5106
5125
  }),
5107
5126
  resultLabel ? React.createElement("span", {
@@ -5109,14 +5128,16 @@ function SessionSearchControl({ query = "", onQuery, matchCount = 0, mobile = fa
5109
5128
  role: "status",
5110
5129
  "aria-live": "polite",
5111
5130
  }, resultLabel) : null,
5112
- (query || mobile) ? React.createElement("button", {
5131
+ (draft || mobile) ? React.createElement("button", {
5113
5132
  type: "button",
5114
5133
  className: "ps-session-search-clear",
5115
- "aria-label": query ? "Clear session search" : "Close session search",
5116
- title: query ? "Clear" : "Close",
5134
+ "aria-label": draft ? "Clear session search" : "Close session search",
5135
+ title: draft ? "Clear" : "Close",
5117
5136
  onClick: closeOrClear,
5118
5137
  }, "×") : null));
5119
- }
5138
+ });
5139
+
5140
+ const EMPTY_PICKER_SELECTION = Object.freeze([]);
5120
5141
 
5121
5142
  function SessionPane({ controller, actions = null, panelClassName = "", structuredRows = false, showDetailBox = null, selection = null, actionsOnly = false, actionsHost = null, onAction = null, onDialogChange = null }) {
5122
5143
  // Mobile keeps its inline detail line and normally gets no detail box — a
@@ -5142,25 +5163,27 @@ function SessionPane({ controller, actions = null, panelClassName = "", structur
5142
5163
  (state) => Boolean(state.ui.sessionDetailCollapsed),
5143
5164
  );
5144
5165
  const sessionButtonRefs = React.useRef(new Map());
5145
- const viewState = useControllerSelector(controller, (state) => ({
5166
+ const controllerViewState = useControllerSelector(controller, (state) => ({
5146
5167
  branding: state.branding,
5147
- activeSessionId: selection ? selection.sessionId : state.sessions.activeSessionId,
5168
+ activeSessionId: state.sessions.activeSessionId,
5148
5169
  sessionsById: state.sessions.byId,
5149
5170
  sessionsFlat: state.sessions.flat,
5150
- filterQuery: selection ? selection.query || "" : state.sessions.filterQuery || "",
5171
+ filterQuery: state.sessions.filterQuery || "",
5151
5172
  ownerFilter: state.sessions.ownerFilter,
5152
5173
  pinnedIds: state.sessions.pinnedIds,
5153
5174
  manualOrder: state.sessions.manualOrder,
5154
- selectedIds: selection ? [] : state.sessions.selectedIds,
5155
- selectMode: selection ? false : state.sessions.selectMode,
5175
+ sortMode: state.sessions.sortMode,
5176
+ sortSnapshot: state.sessions.sortSnapshot,
5177
+ selectedIds: state.sessions.selectedIds,
5178
+ selectMode: state.sessions.selectMode,
5156
5179
  auth: state.auth,
5157
5180
  connectionMode: state.connection?.mode || "local",
5158
5181
  modalOpen: Boolean(state.ui.modal),
5159
- focused: selection ? true : state.ui.focusRegion === "sessions",
5182
+ focused: state.ui.focusRegion === "sessions",
5160
5183
  // Clicking empty space clears the list highlight; the row VM reads it,
5161
5184
  // so the reconstruction below must carry it or the click does nothing
5162
5185
  // visible (the same omission that blinded the Node Map).
5163
- listDeselected: selection ? !selection.sessionId : Boolean(state.sessions.listDeselected),
5186
+ listDeselected: Boolean(state.sessions.listDeselected),
5164
5187
  // The canvas markers read these. This synthetic state is exactly the
5165
5188
  // trap the branding comment below describes: omit a slice here and
5166
5189
  // every row computes as if it were empty — the markers were null on
@@ -5173,6 +5196,14 @@ function SessionPane({ controller, actions = null, panelClassName = "", structur
5173
5196
  // "waiting".
5174
5197
  budgetPaused: state.budget?.paused,
5175
5198
  }), shallowEqualObject);
5199
+ // Picker state is local React state, not controller state. Reading these
5200
+ // props inside the subscription selector delays changes until the next
5201
+ // unrelated store notification (sometimes seconds later).
5202
+ const viewState = selection ? { ...controllerViewState,
5203
+ activeSessionId: selection.sessionId, filterQuery: selection.query || "",
5204
+ selectedIds: EMPTY_PICKER_SELECTION, selectMode: false, focused: true,
5205
+ listDeselected: !selection.sessionId,
5206
+ } : controllerViewState;
5176
5207
  const computedRows = React.useMemo(() => selectSessionRows({
5177
5208
  sessions: {
5178
5209
  activeSessionId: viewState.activeSessionId,
@@ -5182,6 +5213,8 @@ function SessionPane({ controller, actions = null, panelClassName = "", structur
5182
5213
  ownerFilter: viewState.ownerFilter,
5183
5214
  pinnedIds: viewState.pinnedIds,
5184
5215
  manualOrder: viewState.manualOrder,
5216
+ sortMode: viewState.sortMode,
5217
+ sortSnapshot: viewState.sortSnapshot,
5185
5218
  selectedIds: viewState.selectedIds,
5186
5219
  selectMode: viewState.selectMode,
5187
5220
  listDeselected: viewState.listDeselected,
@@ -5200,7 +5233,7 @@ function SessionPane({ controller, actions = null, panelClassName = "", structur
5200
5233
  prefs: viewState.canvasPrefs,
5201
5234
  },
5202
5235
  budget: { paused: viewState.budgetPaused },
5203
- }), [viewState.activeSessionId, viewState.auth, viewState.branding, viewState.budgetPaused, viewState.canvasBySessionId, viewState.canvasPrefs, viewState.connectionMode, viewState.filterQuery, viewState.listDeselected, viewState.ownerFilter, viewState.pinnedIds, viewState.manualOrder, viewState.selectedIds, viewState.selectMode, viewState.sessionsById, viewState.sessionsFlat]);
5236
+ }), [viewState.activeSessionId, viewState.auth, viewState.branding, viewState.budgetPaused, viewState.canvasBySessionId, viewState.canvasPrefs, viewState.connectionMode, viewState.filterQuery, viewState.listDeselected, viewState.ownerFilter, viewState.pinnedIds, viewState.manualOrder, viewState.sortMode, viewState.sortSnapshot, viewState.selectedIds, viewState.selectMode, viewState.sessionsById, viewState.sessionsFlat]);
5204
5237
  // Hold the previous rows when a poll produced identical output.
5205
5238
  const rows = useStableValue(computedRows);
5206
5239
  const searchScrollRef = React.useRef({ top: 0, left: 0, restore: false });
@@ -5975,15 +6008,31 @@ function SessionPane({ controller, actions = null, panelClassName = "", structur
5975
6008
  setRef: setSessionButtonRef,
5976
6009
  // Drag-to-folder is a fine-pointer gesture: arming it on
5977
6010
  // touch hijacks the finger that should be scrolling the list.
5978
- drag: selection || touchInput ? null : dragHandlers,
6011
+ drag: selection || touchInput || viewState.sortMode !== "saved" ? null : dragHandlers,
5979
6012
  }))),
5980
- React.createElement(SessionSearchControl, {
5981
- query: viewState.filterQuery,
5982
- onQuery: setSearchQuery,
5983
- matchCount: searchMatchCount,
5984
- mobile: isMobilePane,
5985
- listRef: sessionListRef,
5986
- }),
6013
+ React.createElement("div", { className: "ps-session-find-controls" },
6014
+ React.createElement("div", { className: "ps-session-sort-controls" },
6015
+ React.createElement("div", { className: "ps-session-sort-modes", role: "group", "aria-label": "Session sort order" },
6016
+ ...[["used", "Recently used", "M12 8v4l3 2", true], ["updated", "Recently updated", "M3 12h4l3-7 4 14 3-7h4"], ["saved", "Saved order", "M6 3h12v18l-6-4-6 4Z"]].map(([mode, label, path, clock]) => React.createElement(IconButton, {
6017
+ key: mode, label, className: "ps-session-sort-button", active: (viewState.sortMode || "saved") === mode, pressed: (viewState.sortMode || "saved") === mode,
6018
+ icon: React.createElement("svg", { viewBox: "0 0 24 24", width: 18, height: 18, fill: "none", stroke: "currentColor", strokeWidth: 1.8, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true }, clock ? React.createElement("circle", { cx: 12, cy: 12, r: 9 }) : null, React.createElement("path", { d: path })),
6019
+ onClick: () => controller.dispatch({ type: "sessions/sortMode", mode }),
6020
+ }))),
6021
+ React.createElement(IconButton, {
6022
+ label: "Refresh session order", className: "ps-session-sort-refresh",
6023
+ icon: React.createElement("svg", { viewBox: "0 0 24 24", width: 18, height: 18, fill: "none", stroke: "currentColor", strokeWidth: 1.8, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true }, React.createElement("path", { d: "M20 7v5h-5M20 12a8 8 0 1 0-2 5M20 7v5" })),
6024
+ onClick: async () => {
6025
+ try { await controller.refreshSessions(); controller.dispatch({ type: "sessions/refreshSort" }); }
6026
+ catch { controller.dispatch({ type: "ui/status", text: "Could not refresh sessions. Try again." }); }
6027
+ },
6028
+ })),
6029
+ React.createElement(SessionSearchControl, {
6030
+ query: viewState.filterQuery,
6031
+ onQuery: setSearchQuery,
6032
+ matchCount: searchMatchCount,
6033
+ mobile: isMobilePane,
6034
+ listRef: sessionListRef,
6035
+ })),
5987
6036
  (showDetailBox === null ? !isMobilePane : showDetailBox)
5988
6037
  ? React.createElement(SessionDetailBox, {
5989
6038
  session: activeSession,
@@ -9365,7 +9414,7 @@ function StatusStrip({ controller }) {
9365
9414
  // (hold ~450ms to see the label, release to dismiss — the long-press does not
9366
9415
  // fire onClick). aria-label carries the meaning for assistive tech.
9367
9416
  const ICON_HOVER_TOOLTIP_MS = 1000;
9368
- function IconButton({ icon, label, onClick, disabled = false, active = false, className = "ps-toolbar-button" }) {
9417
+ function IconButton({ icon, label, onClick, disabled = false, active = false, pressed = undefined, className = "ps-toolbar-button" }) {
9369
9418
  // The tooltip is portaled to <body> so it escapes the toolbar/pane
9370
9419
  // overflow-clipping and stacking contexts (nested tooltips were hidden
9371
9420
  // behind, or bled through by, the panes). Coordinates are computed from
@@ -9508,6 +9557,7 @@ function IconButton({ icon, label, onClick, disabled = false, active = false, cl
9508
9557
  onClick: handleClick,
9509
9558
  disabled,
9510
9559
  "aria-label": label,
9560
+ "aria-pressed": pressed,
9511
9561
  onPointerEnter: startHover,
9512
9562
  onPointerLeave: endHover,
9513
9563
  onPointerDown: startPress,
@@ -14650,6 +14700,8 @@ export function PilotSwarmWebApp({ controller, suspended = false, moa = null })
14650
14700
  // never persists — the reducer would reorder the list correctly and
14651
14701
  // the placement would vanish on reload.
14652
14702
  manualOrder: rootState.sessions.manualOrder,
14703
+ sessionSortMode: rootState.sessions.sortMode,
14704
+ sessionUsedAt: rootState.sessions.usedAt,
14653
14705
  // Pass the live Set reference here so shallow-equal sees the same
14654
14706
  // identity across renders (a fresh array would break memoization).
14655
14707
  // Conversion to a sorted array happens inside `normalizeProfileSettings`.
@@ -14991,7 +15043,7 @@ export function PilotSwarmWebApp({ controller, suspended = false, moa = null })
14991
15043
  });
14992
15044
  }, 400);
14993
15045
  return undefined;
14994
- }, [controller, state.moa, state.activeSessionId, state.activityPaneAdjust, state.agentPickerUsage, state.canvasOpen, state.canvasPaneAdjust, state.canvasPrefs, state.canvasZen, state.collapsedSessionIds, state.diagnosticsOpen, state.diagnosticsPaneAdjust, state.diagnosticsSplitAdjust, state.ownerFilter, state.paneAdjust, state.manualOrder, state.pinnedIds, state.portalSessionColumnAdjust, state.rightPaneMode, state.sessionDetailCollapsed, state.sessionPaneAdjust, state.sessionViews, state.themeId, state.touchScale]);
15046
+ }, [controller, state.moa, state.activeSessionId, state.activityPaneAdjust, state.agentPickerUsage, state.canvasOpen, state.canvasPaneAdjust, state.canvasPrefs, state.canvasZen, state.collapsedSessionIds, state.diagnosticsOpen, state.diagnosticsPaneAdjust, state.diagnosticsSplitAdjust, state.ownerFilter, state.paneAdjust, state.manualOrder, state.sessionSortMode, state.sessionUsedAt, state.pinnedIds, state.portalSessionColumnAdjust, state.rightPaneMode, state.sessionDetailCollapsed, state.sessionPaneAdjust, state.sessionViews, state.themeId, state.touchScale]);
14995
15047
 
14996
15048
  React.useEffect(() => {
14997
15049
  applyDocumentTheme(state.themeId);
@@ -1 +1 @@
1
- import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-CS-m-Pv3.js";import{p as f}from"./chunk-JWPE2WC7-By7oiTbd.js";import{_ as n,l as o}from"./mermaid.core-BEG_GOf7.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-CUvcvCFo.js";import"./pilotswarm-BNTnbu9f.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
1
+ import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-CHdrVT1z.js";import{p as f}from"./chunk-JWPE2WC7-CGM2GAMX.js";import{_ as n,l as o}from"./mermaid.core-i8uqvLPa.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-3zVj2GvI.js";import"./pilotswarm-D7Q48waO.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
@@ -1 +1 @@
1
- import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-BEG_GOf7.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,z,a){var O=I-l,i=D-h,n=z-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function U(l,h,I,D,v,A,z){var a=l-I,O=h-D,i=(z?A:-A)/J(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,B=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*J(on(0,T*T*R-P*P)),Y=(P*g-m*S)/R,$=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=Y-B,e=$-t,r=w-B,C=p-t;return x*x+e*e>r*r+C*C&&(Y=w,$=p),{cx:Y,cy:$,x01:-n,y01:-d,x11:Y*(v/T-1),y11:$*(v/T-1)}}function hn(){var l=cn,h=yn,I=j(0),D=null,v=gn,A=dn,z=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,B=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(B>tn-y)a.moveTo(s*F(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*F(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=B,S=B,Y=z.apply(this,arguments)/2,$=Y>y&&(D?+D.apply(this,arguments):J(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if($>y){var C=sn($/u*q(Y)),K=sn($/s*q(Y));(P-=C*2)>y?(C*=t?1:-1,R+=C,T-=C):(P=0,R=T=(f+c)/2),(S-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(S=0,m=g=(f+c)/2)}var G=s*F(m),H=s*q(m),L=u*F(T),M=u*q(T);if(w>y){var N=s*F(g),Q=s*q(g),V=u*F(R),W=u*q(R),E;if(B<an)if(E=pn(G,H,V,W,N,Q,L,M)){var X=G-E[0],Z=H-E[1],b=N-E[0],k=Q-E[1],nn=1/q(fn((X*b+Z*k)/(J(X*X+Z*Z)*J(b*b+k*k)))/2),en=J(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=U(V,W,G,H,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(G,H),a.arc(0,0,s,m,g,!t)):a.moveTo(G,H),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(G,H,V,W,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[F(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:j(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:j(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:j(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:j(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:j(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:j(+n),i):A},i.padAngle=function(n){return arguments.length?(z=typeof n=="function"?n:j(+n),i):z},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
1
+ import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-i8uqvLPa.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,z,a){var O=I-l,i=D-h,n=z-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function U(l,h,I,D,v,A,z){var a=l-I,O=h-D,i=(z?A:-A)/J(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,B=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*J(on(0,T*T*R-P*P)),Y=(P*g-m*S)/R,$=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=Y-B,e=$-t,r=w-B,C=p-t;return x*x+e*e>r*r+C*C&&(Y=w,$=p),{cx:Y,cy:$,x01:-n,y01:-d,x11:Y*(v/T-1),y11:$*(v/T-1)}}function hn(){var l=cn,h=yn,I=j(0),D=null,v=gn,A=dn,z=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,B=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(B>tn-y)a.moveTo(s*F(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*F(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=B,S=B,Y=z.apply(this,arguments)/2,$=Y>y&&(D?+D.apply(this,arguments):J(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if($>y){var C=sn($/u*q(Y)),K=sn($/s*q(Y));(P-=C*2)>y?(C*=t?1:-1,R+=C,T-=C):(P=0,R=T=(f+c)/2),(S-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(S=0,m=g=(f+c)/2)}var G=s*F(m),H=s*q(m),L=u*F(T),M=u*q(T);if(w>y){var N=s*F(g),Q=s*q(g),V=u*F(R),W=u*q(R),E;if(B<an)if(E=pn(G,H,V,W,N,Q,L,M)){var X=G-E[0],Z=H-E[1],b=N-E[0],k=Q-E[1],nn=1/q(fn((X*b+Z*k)/(J(X*X+Z*Z)*J(b*b+k*k)))/2),en=J(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=U(V,W,G,H,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(G,H),a.arc(0,0,s,m,g,!t)):a.moveTo(G,H),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(G,H,V,W,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[F(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:j(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:j(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:j(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:j(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:j(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:j(+n),i):A},i.padAngle=function(n){return arguments.length?(z=typeof n=="function"?n:j(+n),i):z},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};