pilotswarm 0.5.61 → 0.5.63

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 (90) hide show
  1. package/mcp/dist/src/resources/models.d.ts.map +1 -1
  2. package/mcp/dist/src/resources/models.js +6 -1
  3. package/mcp/dist/src/resources/models.js.map +1 -1
  4. package/mcp/dist/src/tools/models.d.ts.map +1 -1
  5. package/mcp/dist/src/tools/models.js +11 -1
  6. package/mcp/dist/src/tools/models.js.map +1 -1
  7. package/mcp/dist/src/tools/sessions.d.ts.map +1 -1
  8. package/mcp/dist/src/tools/sessions.js +8 -2
  9. package/mcp/dist/src/tools/sessions.js.map +1 -1
  10. package/package.json +2 -2
  11. package/tui/src/node-sdk-transport.js +1 -1
  12. package/ui/core/src/chat-activity.js +94 -0
  13. package/ui/core/src/controller.js +87 -19
  14. package/ui/core/src/history.js +15 -0
  15. package/ui/core/src/moa.js +41 -11
  16. package/ui/core/src/reducer.js +25 -10
  17. package/ui/core/src/selectors.js +25 -5
  18. package/ui/core/src/session-errors.js +10 -2
  19. package/ui/core/src/state.js +6 -2
  20. package/ui/core/src/system-titles.js +2 -0
  21. package/ui/react/src/components.js +2 -1
  22. package/ui/react/src/web-app.js +110 -35
  23. package/web/dist/assets/{abnfDiagram-VRR7QNED-CCVkGWsr.js → abnfDiagram-VRR7QNED-C8iAmIqt.js} +1 -1
  24. package/web/dist/assets/{arc-y040btO3.js → arc-Cg8qs17j.js} +1 -1
  25. package/web/dist/assets/{architectureDiagram-ZJ3FMSHR-24Yt5esy.js → architectureDiagram-ZJ3FMSHR-fYr0dRm3.js} +1 -1
  26. package/web/dist/assets/{blockDiagram-677ZJIJ3-BlbS-_GI.js → blockDiagram-677ZJIJ3-Bpj79Dzq.js} +1 -1
  27. package/web/dist/assets/{c4Diagram-LMCZKHZV-_mamn0Fv.js → c4Diagram-LMCZKHZV-b26Lsm6m.js} +1 -1
  28. package/web/dist/assets/channel-C-ASbcRr.js +1 -0
  29. package/web/dist/assets/{chunk-2Q5K7J3B-TCbIB2Ni.js → chunk-2Q5K7J3B-VLYQfjgG.js} +1 -1
  30. package/web/dist/assets/{chunk-32BRIVSS-C9q5KNKG.js → chunk-32BRIVSS-mVx--2Hg.js} +1 -1
  31. package/web/dist/assets/{chunk-5VM5RSS4-BvoqfU8P.js → chunk-5VM5RSS4-jwnJmked.js} +1 -1
  32. package/web/dist/assets/{chunk-EX3LRPZG-zFJjZeNd.js → chunk-EX3LRPZG-DdfzAT1n.js} +1 -1
  33. package/web/dist/assets/{chunk-JWPE2WC7-Ce_6C5M-.js → chunk-JWPE2WC7-BHm6Udd8.js} +1 -1
  34. package/web/dist/assets/{chunk-MOJQB5TN-CPjpLM65.js → chunk-MOJQB5TN-Dn5qSVAS.js} +1 -1
  35. package/web/dist/assets/{chunk-RYQCIY6F-CsmVUSDH.js → chunk-RYQCIY6F-D4IKMROn.js} +1 -1
  36. package/web/dist/assets/{chunk-V7JOEXUC-CgrmPPOd.js → chunk-V7JOEXUC-BhME3pRf.js} +1 -1
  37. package/web/dist/assets/{chunk-VR4S4FIN-BxAHDR7h.js → chunk-VR4S4FIN-CHG_NBff.js} +1 -1
  38. package/web/dist/assets/{chunk-XXDRQBXY-BGfFoO5_.js → chunk-XXDRQBXY-yw4QCgiL.js} +1 -1
  39. package/web/dist/assets/classDiagram-OUVF2IWQ-D2vlJIb1.js +1 -0
  40. package/web/dist/assets/classDiagram-v2-EOCWNBFH-D2vlJIb1.js +1 -0
  41. package/web/dist/assets/{cose-bilkent-JH36ORCC-B6KcngJW.js → cose-bilkent-JH36ORCC-DqwPj9Kx.js} +1 -1
  42. package/web/dist/assets/{cynefin-VYW2F7L2-DaY7l4Ce.js → cynefin-VYW2F7L2-CVokaaE_.js} +1 -1
  43. package/web/dist/assets/{cynefinDiagram-TSTJHNR4-BldfGsoa.js → cynefinDiagram-TSTJHNR4-Bkhj9fuY.js} +1 -1
  44. package/web/dist/assets/{dagre-VKFMJZFB-C4T9X5Bs.js → dagre-VKFMJZFB-DVv-jnjb.js} +1 -1
  45. package/web/dist/assets/{diagram-FQU43EPY-DCVA_t-e.js → diagram-FQU43EPY-DDlZjkrF.js} +1 -1
  46. package/web/dist/assets/{diagram-G47NLZAW-pbTZGgE5.js → diagram-G47NLZAW-CNDUgqYa.js} +1 -1
  47. package/web/dist/assets/{diagram-NH7WQ7WH-P8Iks122.js → diagram-NH7WQ7WH-DywF8u8i.js} +1 -1
  48. package/web/dist/assets/{diagram-OA4YK3LP-hEjZPipp.js → diagram-OA4YK3LP-ZfN8nvLw.js} +1 -1
  49. package/web/dist/assets/{diagram-WEI45ONY-CVAzVCGu.js → diagram-WEI45ONY-S94A6Avm.js} +1 -1
  50. package/web/dist/assets/{ebnfDiagram-CCIWWBDH-BLL398qt.js → ebnfDiagram-CCIWWBDH-Mpt3QUnw.js} +1 -1
  51. package/web/dist/assets/{erDiagram-Q63AITRT-CLTADyUG.js → erDiagram-Q63AITRT-Bh-eWbdV.js} +1 -1
  52. package/web/dist/assets/{flowDiagram-23GEKE2U-BAdlWAt0.js → flowDiagram-23GEKE2U-BwRtDI6V.js} +1 -1
  53. package/web/dist/assets/{ganttDiagram-NO4QXBWP-C7Z2wavr.js → ganttDiagram-NO4QXBWP-CrZoBmcB.js} +1 -1
  54. package/web/dist/assets/{gitGraphDiagram-IHSO6WYX-BI546pYu.js → gitGraphDiagram-IHSO6WYX-giXv1ynk.js} +1 -1
  55. package/web/dist/assets/index-Br-gGWmc.js +24 -0
  56. package/web/dist/assets/{index-CvW-4eXF.css → index-DRFDn87d.css} +1 -1
  57. package/web/dist/assets/{infoDiagram-FWYZ7A6U-8C7iQydo.js → infoDiagram-FWYZ7A6U-H_5oc4-7.js} +1 -1
  58. package/web/dist/assets/{ishikawaDiagram-FXEZZL3T-Co4STVxQ.js → ishikawaDiagram-FXEZZL3T-BydiPDX0.js} +1 -1
  59. package/web/dist/assets/{journeyDiagram-5HDEW3XC-DbUt11q-.js → journeyDiagram-5HDEW3XC-DS1HXms0.js} +1 -1
  60. package/web/dist/assets/{kanban-definition-HUTT4EX6-DUNcFmme.js → kanban-definition-HUTT4EX6-BjY5SyYu.js} +1 -1
  61. package/web/dist/assets/{linear-Cjaxj94d.js → linear-BvOotjKL.js} +1 -1
  62. package/web/dist/assets/{mermaid.core-B3cPFf4f.js → mermaid.core-0iRu7sp-.js} +4 -4
  63. package/web/dist/assets/{mindmap-definition-LN4V7U3C-DaZtxB4N.js → mindmap-definition-LN4V7U3C-DB93zsvL.js} +1 -1
  64. package/web/dist/assets/{papaparse.min-vfdso2fs.js → papaparse.min-f5Xncedc.js} +1 -1
  65. package/web/dist/assets/{pegDiagram-2B236MQR-DkBpYV7m.js → pegDiagram-2B236MQR-Dh_U1cFA.js} +1 -1
  66. package/web/dist/assets/{pieDiagram-ENE6RG2P-By3tI-vc.js → pieDiagram-ENE6RG2P-Csv1qxMm.js} +1 -1
  67. package/web/dist/assets/pilotswarm-DQNSWfNK.js +105 -0
  68. package/web/dist/assets/{quadrantDiagram-ABIIQ3AL-DZmVm0xK.js → quadrantDiagram-ABIIQ3AL-Bo0pcrBM.js} +1 -1
  69. package/web/dist/assets/{railroadDiagram-RFXS5EU6-BC5Mbz7q.js → railroadDiagram-RFXS5EU6-CHPvHNWG.js} +1 -1
  70. package/web/dist/assets/{requirementDiagram-TGXJPOKE-CyZNX_O1.js → requirementDiagram-TGXJPOKE-DgX8l-6H.js} +1 -1
  71. package/web/dist/assets/{sankeyDiagram-HTMAVEWB-7603NEmu.js → sankeyDiagram-HTMAVEWB-xR6MTs5a.js} +1 -1
  72. package/web/dist/assets/{sequenceDiagram-DBY2YBRQ-CXJ-i2Xj.js → sequenceDiagram-DBY2YBRQ-CD_45diB.js} +1 -1
  73. package/web/dist/assets/{sizeCapture-X5ZJPWSS-CKT0ATnS.js → sizeCapture-X5ZJPWSS-BJVEXU0K.js} +1 -1
  74. package/web/dist/assets/{stateDiagram-2N3HPSRC-BIDPX4YU.js → stateDiagram-2N3HPSRC-Bwu6kd23.js} +1 -1
  75. package/web/dist/assets/stateDiagram-v2-6OUMAXLB-aypsN5jW.js +1 -0
  76. package/web/dist/assets/{swimlanes-5IMT3BWC-CPoy6vnO.js → swimlanes-5IMT3BWC-BmhEzevT.js} +2 -2
  77. package/web/dist/assets/swimlanesDiagram-G3AALYLV-Duf5C4YK.js +8 -0
  78. package/web/dist/assets/{timeline-definition-FHXFAJF6-BGdNkplk.js → timeline-definition-FHXFAJF6-DFPI_uTI.js} +1 -1
  79. package/web/dist/assets/{vennDiagram-L72KCM5P-ByFzarUb.js → vennDiagram-L72KCM5P-DDTpTkBC.js} +1 -1
  80. package/web/dist/assets/{wardleyDiagram-EHGQE667-CAk0SYuv.js → wardleyDiagram-EHGQE667-bV2_YVIL.js} +1 -1
  81. package/web/dist/assets/{xychartDiagram-FW5EYKEG-Np7h6_A0.js → xychartDiagram-FW5EYKEG-C7bDIXAV.js} +1 -1
  82. package/web/dist/index.html +3 -3
  83. package/web/runtime.js +1 -0
  84. package/web/dist/assets/channel-COFs9dqk.js +0 -1
  85. package/web/dist/assets/classDiagram-OUVF2IWQ-B5-KmsCx.js +0 -1
  86. package/web/dist/assets/classDiagram-v2-EOCWNBFH-B5-KmsCx.js +0 -1
  87. package/web/dist/assets/index-DsPaDrf9.js +0 -24
  88. package/web/dist/assets/pilotswarm-BL_NbZug.js +0 -98
  89. package/web/dist/assets/stateDiagram-v2-6OUMAXLB-Dr8oD9T6.js +0 -1
  90. package/web/dist/assets/swimlanesDiagram-G3AALYLV-BV0EQRlB.js +0 -8
@@ -354,6 +354,7 @@ const ChatPane = React.memo(function ChatPane({ controller, width, height, frame
354
354
  connectionError: state.connection.error,
355
355
  connectionMode: state.connection.mode,
356
356
  chatScroll: state.ui.scroll.chat,
357
+ followBottom: state.ui.followBottom?.chat !== false,
357
358
  focused: state.ui.focusRegion === "chat",
358
359
  };
359
360
  }, shallowEqualObject);
@@ -449,7 +450,7 @@ const ChatPane = React.memo(function ChatPane({ controller, width, height, frame
449
450
  lines: elements,
450
451
  bottomStickyLines,
451
452
  scrollOffset: chatView.chatScroll,
452
- scrollMode: "bottom",
453
+ scrollMode: chatView.followBottom ? "bottom" : "top",
453
454
  paneId: "chat",
454
455
  paneLabel: "Chat",
455
456
  frame,
@@ -607,12 +607,8 @@ function materializeProfileSettings(remoteSettings, defaults) {
607
607
  // synthesizing one here would let a poll clobber a fresh local toggle.
608
608
  ...(hasOwn(normalizedRemote, touchScaleKey())
609
609
  ? { touchScale: normalizedRemote[touchScaleKey()] }
610
- // Profiles written before the per-device split carry a single
611
- // `touchScale`, which IS the desktop key — so only a phone needs to
612
- // inherit it, and only until it saves a slot of its own.
613
- : (isNarrowViewport() && hasOwn(normalizedRemote, "touchScale")
614
- ? { touchScale: normalizedRemote.touchScale }
615
- : {})),
610
+ // Never inherit the other device class's preference.
611
+ : {}),
616
612
  // Read back for the same reason as touchScale above: written but never
617
613
  // merged means the fold state resets on every reload. No default here
618
614
  // either — absent must stay absent so a poll cannot overwrite a toggle
@@ -1079,6 +1075,18 @@ export function computeAnchoredScrollTop(
1079
1075
  : Math.min(maxScroll, offsetPixels);
1080
1076
  }
1081
1077
 
1078
+ function scrollLineIdentity(line) {
1079
+ if (!line) return "";
1080
+ if (line.kind === "runs") return line.runs?.map((run) => run?.text || "").join("") || "";
1081
+ if (line.kind === "assistantPreview") return `assistant:${line.previewKey || line.messageId || line.id || ""}`;
1082
+ return `${line.kind || "text"}:${line.text || line.value || line.id || ""}`;
1083
+ }
1084
+
1085
+ function scrollBoundaryIdentity(lines, fromEnd = false) {
1086
+ const boundary = fromEnd ? lines.slice(-8) : lines.slice(0, 8);
1087
+ return boundary.map(scrollLineIdentity).join("\u241e");
1088
+ }
1089
+
1082
1090
  function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller, { stickyBottom = false } = {}) {
1083
1091
  const normalizedLines = React.useMemo(() => normalizeLines(lines), [lines]);
1084
1092
  // Programmatic scrollTop assignments fire a 'scroll' event that would
@@ -1091,6 +1099,7 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1091
1099
  scrollMode,
1092
1100
  scrollOffset,
1093
1101
  });
1102
+ const previousContentRef = React.useRef(null);
1094
1103
  // Touch scrolling relies on native momentum for speed: a hard flick keeps
1095
1104
  // scrolling long after the finger lifts. Re-asserting scrollTop from state
1096
1105
  // on every render (live events, status updates) kills that momentum at the
@@ -1120,30 +1129,44 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1120
1129
  const node = ref.current;
1121
1130
  if (!node) return;
1122
1131
  const previousViewportState = previousViewportStateRef.current;
1132
+ const firstLine = scrollBoundaryIdentity(normalizedLines);
1133
+ const lastLine = scrollBoundaryIdentity(normalizedLines, true);
1134
+ const previousContent = previousContentRef.current;
1123
1135
  const interaction = userScrollRef.current;
1124
1136
  const now = typeof performance !== "undefined" ? performance.now() : Date.now();
1125
1137
  const interacting = interaction.touching
1126
1138
  || (now - (interaction.lastUserScrollAt || 0)) < TOUCH_MOMENTUM_GRACE_MS;
1127
1139
  const isEchoOffset = interaction.lastDispatchedOffset != null
1128
1140
  && Math.abs((Number(scrollOffset) || 0) - interaction.lastDispatchedOffset) < 2;
1141
+ const preservePausedStickyScroll = stickyBottom
1142
+ && scrollMode === "top"
1143
+ && previousViewportState?.scrollMode === "top"
1144
+ && previousViewportState?.scrollOffset === scrollOffset;
1145
+ // A backward page inserts DOM above the reader. Top-anchored paused
1146
+ // state normally preserves scrollTop, which would push the same visible
1147
+ // message down by the inserted height. Compensate with the measured DOM
1148
+ // height delta. Appended live text keeps the old scrollTop unchanged.
1149
+ const prependedWhilePaused = stickyBottom
1150
+ && previousContent?.lastLine === lastLine
1151
+ && previousContent?.firstLine !== firstLine
1152
+ && node.scrollHeight > previousContent.scrollHeight
1153
+ && (preservePausedStickyScroll || node.scrollTop <= PROGRAMMATIC_SCROLL_TOLERANCE_PX);
1129
1154
  if (
1130
- interacting
1155
+ !prependedWhilePaused
1156
+ && interacting
1131
1157
  && scrollMode === previousViewportState?.scrollMode
1132
1158
  && (scrollOffset === previousViewportState?.scrollOffset || isEchoOffset)
1133
1159
  ) {
1134
1160
  previousViewportStateRef.current = { scrollMode, scrollOffset };
1161
+ previousContentRef.current = { firstLine, lastLine, scrollHeight: node.scrollHeight };
1135
1162
  return;
1136
1163
  }
1137
- const preservePausedStickyScroll = stickyBottom
1138
- && scrollMode === "top"
1139
- && previousViewportState?.scrollMode === "top"
1140
- && previousViewportState?.scrollOffset === scrollOffset;
1141
- const nextScrollTop = computeAnchoredScrollTop(
1142
- node,
1143
- scrollOffset,
1144
- scrollMode,
1145
- preservePausedStickyScroll,
1146
- );
1164
+ const nextScrollTop = prependedWhilePaused
1165
+ ? Math.max(0, Math.min(
1166
+ node.scrollTop + (node.scrollHeight - previousContent.scrollHeight),
1167
+ node.scrollHeight - node.clientHeight,
1168
+ ))
1169
+ : computeAnchoredScrollTop(node, scrollOffset, scrollMode, preservePausedStickyScroll);
1147
1170
  if (Math.abs(node.scrollTop - nextScrollTop) > PROGRAMMATIC_SCROLL_TOLERANCE_PX) {
1148
1171
  const pendingProgrammaticScroll = { target: nextScrollTop };
1149
1172
  programmaticScrollRef.current = pendingProgrammaticScroll;
@@ -1156,10 +1179,20 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1156
1179
  }
1157
1180
  });
1158
1181
  }
1182
+ if (prependedWhilePaused && paneKey && typeof controller.updatePaneScrollFromViewport === "function") {
1183
+ // The measured DOM compensation above is the new durable paused
1184
+ // position. Persist it too: otherwise switching sessions and back
1185
+ // reapplies the pre-page offset and moves the reader by the full
1186
+ // height of the newly inserted history.
1187
+ const rowOffset = Math.max(0, nextScrollTop) / SCROLL_ROW_HEIGHT;
1188
+ userScrollRef.current.lastDispatchedOffset = rowOffset;
1189
+ controller.updatePaneScrollFromViewport(paneKey, rowOffset, { atBottom: false });
1190
+ }
1159
1191
  previousViewportStateRef.current = {
1160
1192
  scrollMode,
1161
1193
  scrollOffset,
1162
1194
  };
1195
+ previousContentRef.current = { firstLine, lastLine, scrollHeight: node.scrollHeight };
1163
1196
  }, [normalizedLines, ref, scrollMode, scrollOffset, stickyBottom, viewportRevision]);
1164
1197
 
1165
1198
  const dispatchScrollOffset = useFrameCoalescedCallback((offset) => {
@@ -1193,6 +1226,13 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1193
1226
  rowOffset,
1194
1227
  { atBottom: isScrollViewportAtBottom(node) },
1195
1228
  );
1229
+ // Pausing bottom-follow changes chat to top-anchored scroll state,
1230
+ // but reaching the DOM's actual top must still arm backward CMS
1231
+ // paging. Keep this next to the native measurement so the history
1232
+ // gate does not depend on which anchoring mode currently renders.
1233
+ if (paneKey === "chat" && node.scrollTop <= PROGRAMMATIC_SCROLL_TOLERANCE_PX) {
1234
+ controller.armChatTopHistoryLoad?.();
1235
+ }
1196
1236
  return;
1197
1237
  }
1198
1238
 
@@ -1211,11 +1251,11 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1211
1251
 
1212
1252
  const onWheel = React.useCallback((event) => {
1213
1253
  const node = ref.current;
1214
- if (!node || paneKey !== "chat" || scrollMode !== "bottom" || event.deltaY >= 0) return;
1254
+ if (!node || paneKey !== "chat" || event.deltaY >= 0) return;
1215
1255
  if (node.scrollTop > PROGRAMMATIC_SCROLL_TOLERANCE_PX) return;
1216
1256
  const maxScroll = Math.max(0, node.scrollHeight - node.clientHeight);
1217
- controller.handleChatTopHistoryScrollIntent?.(maxScroll / SCROLL_ROW_HEIGHT);
1218
- }, [controller, paneKey, ref, scrollMode]);
1257
+ controller.handleChatTopHistoryScrollIntent?.(maxScroll / SCROLL_ROW_HEIGHT, { preserveDomAnchor: true });
1258
+ }, [controller, paneKey, ref]);
1219
1259
 
1220
1260
  // Touch equivalent of the wheel-at-top gesture: touch devices never fire
1221
1261
  // wheel events, and once scrollTop sits at 0 a further swipe-down emits no
@@ -1225,9 +1265,9 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1225
1265
  const touchPullRef = React.useRef({ startY: null, fired: false });
1226
1266
  const onTouchStart = React.useCallback((event) => {
1227
1267
  userScrollRef.current.touching = true;
1228
- if (paneKey !== "chat" || scrollMode !== "bottom") return;
1268
+ if (paneKey !== "chat") return;
1229
1269
  touchPullRef.current = { startY: event.touches?.[0]?.clientY ?? null, fired: false };
1230
- }, [paneKey, scrollMode]);
1270
+ }, [paneKey]);
1231
1271
  const onTouchEnd = React.useCallback(() => {
1232
1272
  userScrollRef.current.touching = false;
1233
1273
  // Momentum continues past the finger lift; onScroll keeps refreshing
@@ -1237,7 +1277,7 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1237
1277
  const onTouchMove = React.useCallback((event) => {
1238
1278
  const node = ref.current;
1239
1279
  const pull = touchPullRef.current;
1240
- if (!node || paneKey !== "chat" || scrollMode !== "bottom") return;
1280
+ if (!node || paneKey !== "chat") return;
1241
1281
  if (pull.fired || pull.startY == null) return;
1242
1282
  if (node.scrollTop > PROGRAMMATIC_SCROLL_TOLERANCE_PX) return;
1243
1283
  const y = event.touches?.[0]?.clientY;
@@ -1249,8 +1289,8 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1249
1289
  // on narrow viewports). The wheel path keeps the handshake — one
1250
1290
  // physical scroll emits MANY wheel events, so it needs debouncing.
1251
1291
  const maxScroll = Math.max(0, node.scrollHeight - node.clientHeight);
1252
- controller.handleChatTopHistoryScrollIntent?.(maxScroll / SCROLL_ROW_HEIGHT + 1, { force: true });
1253
- }, [controller, paneKey, ref, scrollMode]);
1292
+ controller.handleChatTopHistoryScrollIntent?.(maxScroll / SCROLL_ROW_HEIGHT + 1, { force: true, preserveDomAnchor: true });
1293
+ }, [controller, paneKey, ref]);
1254
1294
 
1255
1295
  return { normalizedLines, onScroll, onWheel, onTouchStart, onTouchMove, onTouchEnd };
1256
1296
  }
@@ -1331,6 +1371,22 @@ function SystemNoticeLine({ line, theme }) {
1331
1371
  : null);
1332
1372
  }
1333
1373
 
1374
+ function ChatCallLine({ line }) {
1375
+ const [open, setOpen] = React.useState(false);
1376
+ return React.createElement("details", {
1377
+ className: "ps-system-notice ps-chat-call",
1378
+ "data-call-id": line.callKey,
1379
+ onToggle: event => setOpen(event.currentTarget.open),
1380
+ },
1381
+ React.createElement("summary", { className: "ps-system-notice-summary ps-chat-call-summary" },
1382
+ React.createElement("span", { className: "ps-chat-call-tag" }, line.category || "Tool"),
1383
+ React.createElement("span", { className: "ps-system-notice-summary-text" }, line.text),
1384
+ line.status ? React.createElement("span", { className: `ps-chat-call-status${line.status === "Failed" ? " is-failed" : ""}` }, line.status) : null),
1385
+ open ? React.createElement("div", { className: "ps-system-notice-body" },
1386
+ line.time ? React.createElement("div", { className: "ps-chat-call-time" }, line.time) : null,
1387
+ React.createElement("pre", { className: "ps-chat-call-payload" }, line.body)) : null);
1388
+ }
1389
+
1334
1390
  /**
1335
1391
  * A canvas action is a button press inside the drawn page, not something the
1336
1392
  * viewer typed. Printing the raw `[canvas-action] {…}` JSON as a chat message
@@ -3230,6 +3286,13 @@ function parseStructuredChatBlocks(lines = []) {
3230
3286
  for (let index = 0; index < lines.length;) {
3231
3287
  const currentLine = lines[index];
3232
3288
 
3289
+ if (currentLine?.kind === "chatCall" || currentLine?.callPreview !== undefined) {
3290
+ blocks.push({ type: "chatCall", line: currentLine.callPreview !== undefined
3291
+ ? { ...currentLine, text: currentLine.callPreview, category: "Agent" } : currentLine });
3292
+ index += 1;
3293
+ continue;
3294
+ }
3295
+
3233
3296
  if (currentLine?.kind === "assistantPreview") {
3234
3297
  blocks.push({ type: "assistantPreview", line: currentLine });
3235
3298
  index += 1;
@@ -3655,6 +3718,9 @@ const AssistantPreviewCard = React.memo(function AssistantPreviewCard({ line, th
3655
3718
  function StructuredBlockList({ blocks, theme, controller = null }) {
3656
3719
  return React.createElement(React.Fragment, null,
3657
3720
  (blocks || []).map((block, index) => {
3721
+ if (block.type === "chatCall") {
3722
+ return React.createElement(ChatCallLine, { key: block.line.callKey, line: block.line });
3723
+ }
3658
3724
  if (block.type === "assistantPreview") {
3659
3725
  return React.createElement(AssistantPreviewCard, {
3660
3726
  key: block.line.previewKey,
@@ -4216,7 +4282,7 @@ export function waitReasonLabel(session) {
4216
4282
  return session?.cronActive === true ? "On wake" : "Waiting";
4217
4283
  }
4218
4284
 
4219
- function SessionDetailBox({ session, childCount = 0, pause = null, controller = null, collapsed = false, onToggle = null }) {
4285
+ function SessionDetailBox({ session, childCount = 0, pause = null, controller = null, collapsed = false, onToggle = null, onOpenBudget = null }) {
4220
4286
  // EVERY field renders on EVERY selection, empty ones as an em dash. The box
4221
4287
  // is a fixed grid of rows, so moving through the list cannot change its
4222
4288
  // height — a box that grew and shrank would shove the list under the
@@ -4313,12 +4379,12 @@ function SessionDetailBox({ session, childCount = 0, pause = null, controller =
4313
4379
  pause && pause.clears
4314
4380
  ? React.createElement("span", { className: "ps-session-detail-clears" }, pause.clears)
4315
4381
  : null,
4316
- pause && controller ? React.createElement("button", {
4382
+ pause && (controller || onOpenBudget) ? React.createElement("button", {
4317
4383
  type: "button", className: "ps-budget-link",
4318
4384
  title: pause.provider
4319
4385
  ? `Open ${pause.provider} in Providers & Budgets`
4320
4386
  : "Open providers and budgets",
4321
- onClick: () => controller.openBudget(
4387
+ onClick: () => (onOpenBudget || (options => controller.openBudget(options)))(
4322
4388
  pause.provider ? { provider: pause.provider } : {},
4323
4389
  ).catch(() => {}),
4324
4390
  }, pause.provider ? `Open ${pause.provider}` : "Open providers and budgets") : null));
@@ -5548,10 +5614,14 @@ function SessionPane({ controller, actions = null, panelClassName = "", structur
5548
5614
  || focused.tagName === "SELECT"
5549
5615
  || focused.isContentEditable
5550
5616
  ));
5551
- if (focused !== activeButton && !isTypingTarget) {
5617
+ if (viewState.focused && focused !== activeButton && !isTypingTarget) {
5552
5618
  activeButton.focus({ preventScroll: true });
5553
5619
  }
5554
- activeButton.scrollIntoView({ block: "nearest" });
5620
+ // Selection can change from outside this pane (deep links, newly
5621
+ // created sessions, MoA focus and other navigation surfaces). Center
5622
+ // the row once for that selection so its surrounding sessions remain
5623
+ // visible, without re-centering on routine status/catalog refreshes.
5624
+ activeButton.scrollIntoView({ block: "center" });
5555
5625
  }, [activeRowRevealKey, viewState.activeSessionId, viewState.focused, viewState.modalOpen, viewState.sessionsFlat]);
5556
5626
 
5557
5627
  const panelActions = React.createElement(React.Fragment, null,
@@ -6408,7 +6478,7 @@ function SessionModifyModal({ controller, sessionId, initialTitle, currentModel,
6408
6478
  error ? React.createElement("div", { className: "ps-share-error" }, error) : null));
6409
6479
  }
6410
6480
 
6411
- function SessionComposer({ controller, onReadOnlyFocus = null, mobile = false, compact = false }) {
6481
+ function SessionComposer({ controller, onReadOnlyFocus = null, mobile = false, compact = false, autoFocus = !mobile }) {
6412
6482
  const modal = useControllerSelector(controller, state => state.ui.modal);
6413
6483
  const session = useControllerSelector(controller, state => state.sessions.byId[state.sessions.activeSessionId]);
6414
6484
  const { access } = useActiveSessionAccess(controller, session?.sessionId, session?.isGroup);
@@ -6419,7 +6489,7 @@ function SessionComposer({ controller, onReadOnlyFocus = null, mobile = false, c
6419
6489
  ? React.createElement("div", { className: "ps-composer-readonly" }, session.serviceKind
6420
6490
  ? "⚗ Service session — runtime machinery. Its transcript is a read-only trace; it does not accept messages."
6421
6491
  : `You have view access to this session. Ask ${access.owner?.displayName || access.owner?.email || "the owner"} for write access to participate.`)
6422
- : React.createElement(PromptComposer, { controller, mobile, compact, autoFocus: !mobile, active: true }));
6492
+ : React.createElement(PromptComposer, { controller, mobile, compact, autoFocus, active: true }));
6423
6493
  }
6424
6494
 
6425
6495
  // The compact focus views use their existing header for activity. The same
@@ -6470,6 +6540,7 @@ function ChatPane({ controller, mobile = false, fullWidth = false, showComposer
6470
6540
  activeSessionStatus: activeSessionId ? String(state.sessions.byId[activeSessionId]?.status || "").toLowerCase() : "",
6471
6541
  focused: state.ui.focusRegion === "chat",
6472
6542
  scroll: state.ui.scroll.chat,
6543
+ followBottom: state.ui.followBottom?.chat !== false,
6473
6544
  // Viewer identity — so the transcript can say "You" for the viewer's
6474
6545
  // own messages and name others (with an "(owner)" tag).
6475
6546
  authPrincipal: state.auth?.principal || null,
@@ -6619,7 +6690,8 @@ function ChatPane({ controller, mobile = false, fullWidth = false, showComposer
6619
6690
  bottomStickyLines: activityInHeader ? EMPTY_ARRAY : stickyBottom,
6620
6691
  reserveBottomSticky: !activityInHeader,
6621
6692
  scrollOffset: viewState.scroll,
6622
- scrollMode: "bottom",
6693
+ scrollMode: viewState.followBottom ? "bottom" : "top",
6694
+ stickyBottom: true,
6623
6695
  paneKey: "chat",
6624
6696
  ariaLive: "polite",
6625
6697
  className: "is-wrapped",
@@ -8850,7 +8922,7 @@ function PromptComposer({ controller, mobile, compact = false, active = true, on
8850
8922
  const inputNode = inputRef.current;
8851
8923
  if (!active || promptState.modalOpen || !promptState.focused || !inputNode) return;
8852
8924
  if (document.activeElement !== inputNode) {
8853
- if (!autoFocus) return;
8925
+ if (!autoFocus || (typeof autoFocus === "function" && !autoFocus())) return;
8854
8926
  // Programmatic focus pops the on-screen keyboard on touch devices;
8855
8927
  // there, focus only ever comes from the user's own tap.
8856
8928
  if (mobile) return;
@@ -9064,7 +9136,7 @@ function PromptComposer({ controller, mobile, compact = false, active = true, on
9064
9136
  onClick: cancelPending,
9065
9137
  }, selectedQueued ? "Delete" : "Cancel")
9066
9138
  : null,
9067
- !compact && (promptState.canStopTurn || stoppingTurn)
9139
+ (promptState.canStopTurn || stoppingTurn)
9068
9140
  ? React.createElement("button", {
9069
9141
  type: "button",
9070
9142
  className: `ps-stop-button${stoppingTurn ? " is-stopping" : ""}`,
@@ -14302,6 +14374,9 @@ export function createWebPilotSwarmController({ transport, mode = "remote", bran
14302
14374
  branding,
14303
14375
  docs,
14304
14376
  }));
14377
+ // Only the initial device default. A saved value for this device wins
14378
+ // when the profile loads, including an explicit mobile opt-out.
14379
+ store.dispatch({ type: "ui/touchScale", enabled: isNarrowViewport });
14305
14380
  return new PilotSwarmUiController({ store, transport });
14306
14381
  }
14307
14382
 
@@ -1 +1 @@
1
- import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-CPjpLM65.js";import{p as f}from"./chunk-JWPE2WC7-Ce_6C5M-.js";import{_ as n,l as o}from"./mermaid.core-B3cPFf4f.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-DaY7l4Ce.js";import"./pilotswarm-BL_NbZug.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-Dn5qSVAS.js";import{p as f}from"./chunk-JWPE2WC7-BHm6Udd8.js";import{_ as n,l as o}from"./mermaid.core-0iRu7sp-.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-CVokaaE_.js";import"./pilotswarm-DQNSWfNK.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-B3cPFf4f.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-0iRu7sp-.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};