pilotswarm 0.5.62 → 0.5.64

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 (93) hide show
  1. package/mcp/dist/src/server.d.ts.map +1 -1
  2. package/mcp/dist/src/server.js +2 -0
  3. package/mcp/dist/src/server.js.map +1 -1
  4. package/mcp/dist/src/tools/features.d.ts +4 -0
  5. package/mcp/dist/src/tools/features.d.ts.map +1 -0
  6. package/mcp/dist/src/tools/features.js +35 -0
  7. package/mcp/dist/src/tools/features.js.map +1 -0
  8. package/package.json +2 -2
  9. package/tui/src/node-sdk-transport.js +13 -0
  10. package/ui/core/src/controller.js +330 -14
  11. package/ui/core/src/history.js +89 -14
  12. package/ui/core/src/moa.js +9 -0
  13. package/ui/core/src/native-tasks.js +197 -0
  14. package/ui/core/src/question-display.js +13 -0
  15. package/ui/core/src/reducer.js +31 -7
  16. package/ui/core/src/selectors.js +46 -13
  17. package/ui/core/src/session-errors.js +13 -6
  18. package/ui/core/src/session-warning.js +14 -0
  19. package/ui/core/src/state.js +7 -2
  20. package/ui/react/src/components.js +2 -1
  21. package/ui/react/src/feature-flags-panel.js +186 -0
  22. package/ui/react/src/native-task-card.js +59 -0
  23. package/ui/react/src/web-app.js +173 -33
  24. package/web/dist/assets/{abnfDiagram-VRR7QNED-DAiG41W-.js → abnfDiagram-VRR7QNED-gIPHF2gV.js} +1 -1
  25. package/web/dist/assets/{arc-CN_GY3DG.js → arc-DMW_q5Ml.js} +1 -1
  26. package/web/dist/assets/{architectureDiagram-ZJ3FMSHR-DD9qiBOj.js → architectureDiagram-ZJ3FMSHR-DAKsrxcB.js} +1 -1
  27. package/web/dist/assets/{blockDiagram-677ZJIJ3-CZg2R8i6.js → blockDiagram-677ZJIJ3-BUjSLpP3.js} +1 -1
  28. package/web/dist/assets/{c4Diagram-LMCZKHZV-DuZxUZYd.js → c4Diagram-LMCZKHZV-Dw2nPoes.js} +1 -1
  29. package/web/dist/assets/channel-CcOa1LtY.js +1 -0
  30. package/web/dist/assets/{chunk-2Q5K7J3B-BX7lDvmf.js → chunk-2Q5K7J3B-BAL28Rv0.js} +1 -1
  31. package/web/dist/assets/{chunk-32BRIVSS-COupwzAw.js → chunk-32BRIVSS-DDlt9K8s.js} +1 -1
  32. package/web/dist/assets/{chunk-5VM5RSS4-C_IyERib.js → chunk-5VM5RSS4-BLQGJGoP.js} +1 -1
  33. package/web/dist/assets/{chunk-EX3LRPZG-CyfIuYKn.js → chunk-EX3LRPZG-XFMb3HRy.js} +1 -1
  34. package/web/dist/assets/{chunk-JWPE2WC7-Cj5lvEfN.js → chunk-JWPE2WC7-DWnKTQ72.js} +1 -1
  35. package/web/dist/assets/{chunk-MOJQB5TN-l907LpMA.js → chunk-MOJQB5TN-MltzhnwP.js} +1 -1
  36. package/web/dist/assets/{chunk-RYQCIY6F-PLru1fOZ.js → chunk-RYQCIY6F-Ce3q0-mJ.js} +1 -1
  37. package/web/dist/assets/{chunk-V7JOEXUC-C6GCxiE5.js → chunk-V7JOEXUC-ThXLYY88.js} +1 -1
  38. package/web/dist/assets/{chunk-VR4S4FIN-BGelrIxQ.js → chunk-VR4S4FIN-DbhAykiW.js} +1 -1
  39. package/web/dist/assets/{chunk-XXDRQBXY-BmJstjEv.js → chunk-XXDRQBXY-BpkNB0mD.js} +1 -1
  40. package/web/dist/assets/classDiagram-OUVF2IWQ-B2VhHRSV.js +1 -0
  41. package/web/dist/assets/classDiagram-v2-EOCWNBFH-B2VhHRSV.js +1 -0
  42. package/web/dist/assets/{cose-bilkent-JH36ORCC-CRabxOOK.js → cose-bilkent-JH36ORCC-rctqAPvj.js} +1 -1
  43. package/web/dist/assets/{cynefin-VYW2F7L2-CminxBoG.js → cynefin-VYW2F7L2-Dg1cltg6.js} +1 -1
  44. package/web/dist/assets/{cynefinDiagram-TSTJHNR4-yBazsQf4.js → cynefinDiagram-TSTJHNR4-Ci23Sv4Z.js} +1 -1
  45. package/web/dist/assets/{dagre-VKFMJZFB-DcZuZV2n.js → dagre-VKFMJZFB-BpWTGhpv.js} +1 -1
  46. package/web/dist/assets/{diagram-FQU43EPY-CHoFzsw6.js → diagram-FQU43EPY-B69JpiAe.js} +1 -1
  47. package/web/dist/assets/{diagram-G47NLZAW-B8leqMRl.js → diagram-G47NLZAW-BHMk1TOO.js} +1 -1
  48. package/web/dist/assets/{diagram-NH7WQ7WH-DNoVxpa3.js → diagram-NH7WQ7WH-CtvZIIsk.js} +1 -1
  49. package/web/dist/assets/{diagram-OA4YK3LP-gC3Q2X6-.js → diagram-OA4YK3LP-BFvKh800.js} +1 -1
  50. package/web/dist/assets/{diagram-WEI45ONY-CABqyjDl.js → diagram-WEI45ONY-CgB8sWPe.js} +1 -1
  51. package/web/dist/assets/{ebnfDiagram-CCIWWBDH-cSguXaDC.js → ebnfDiagram-CCIWWBDH-DyqPNydM.js} +1 -1
  52. package/web/dist/assets/{erDiagram-Q63AITRT-CoWX37V3.js → erDiagram-Q63AITRT-CwpvZQ3Q.js} +1 -1
  53. package/web/dist/assets/{flowDiagram-23GEKE2U-I9DHYjhG.js → flowDiagram-23GEKE2U-EBKSKxfC.js} +1 -1
  54. package/web/dist/assets/{ganttDiagram-NO4QXBWP-DaFnfYTt.js → ganttDiagram-NO4QXBWP-q5tMPAuC.js} +1 -1
  55. package/web/dist/assets/{gitGraphDiagram-IHSO6WYX-CwiXVM_O.js → gitGraphDiagram-IHSO6WYX-DCRbi4KE.js} +1 -1
  56. package/web/dist/assets/index-BfF7e08d.js +24 -0
  57. package/web/dist/assets/index-uhc851H3.css +1 -0
  58. package/web/dist/assets/{infoDiagram-FWYZ7A6U-DtzIrIpW.js → infoDiagram-FWYZ7A6U-Bex5pSIX.js} +1 -1
  59. package/web/dist/assets/{ishikawaDiagram-FXEZZL3T-B9nk829n.js → ishikawaDiagram-FXEZZL3T-Dj0li_TY.js} +1 -1
  60. package/web/dist/assets/{journeyDiagram-5HDEW3XC-xLaPm-ow.js → journeyDiagram-5HDEW3XC-BtEGEeVr.js} +1 -1
  61. package/web/dist/assets/{kanban-definition-HUTT4EX6-BnDqLYLC.js → kanban-definition-HUTT4EX6-BTFfZvYt.js} +1 -1
  62. package/web/dist/assets/{linear-Djc7nVo8.js → linear-C3SQCsip.js} +1 -1
  63. package/web/dist/assets/{mermaid.core-B5elhUtV.js → mermaid.core-DALDJDu8.js} +4 -4
  64. package/web/dist/assets/{mindmap-definition-LN4V7U3C-N-B7EJGs.js → mindmap-definition-LN4V7U3C-BZf3uw0u.js} +1 -1
  65. package/web/dist/assets/{papaparse.min-BqM-LJkq.js → papaparse.min-Bh9MZ-fk.js} +1 -1
  66. package/web/dist/assets/{pegDiagram-2B236MQR-BIollSMB.js → pegDiagram-2B236MQR-PuOleiMg.js} +1 -1
  67. package/web/dist/assets/{pieDiagram-ENE6RG2P-DkZY6iCd.js → pieDiagram-ENE6RG2P-CcFORUaW.js} +1 -1
  68. package/web/dist/assets/pilotswarm-B9rLtXpI.js +109 -0
  69. package/web/dist/assets/{quadrantDiagram-ABIIQ3AL-iUDmQIyL.js → quadrantDiagram-ABIIQ3AL-CEm0mp4y.js} +1 -1
  70. package/web/dist/assets/{railroadDiagram-RFXS5EU6-BSCGJgV7.js → railroadDiagram-RFXS5EU6-DeH-uX0_.js} +1 -1
  71. package/web/dist/assets/{requirementDiagram-TGXJPOKE-9yqcGRUA.js → requirementDiagram-TGXJPOKE-CMbJVMc1.js} +1 -1
  72. package/web/dist/assets/{sankeyDiagram-HTMAVEWB-SPh1plT9.js → sankeyDiagram-HTMAVEWB-C9gL5w_b.js} +1 -1
  73. package/web/dist/assets/{sequenceDiagram-DBY2YBRQ-C0nv5x71.js → sequenceDiagram-DBY2YBRQ-BUo8TT74.js} +1 -1
  74. package/web/dist/assets/{sizeCapture-X5ZJPWSS-DMXfUt1o.js → sizeCapture-X5ZJPWSS-C5lqG0ei.js} +1 -1
  75. package/web/dist/assets/{stateDiagram-2N3HPSRC-vjhtquua.js → stateDiagram-2N3HPSRC-DyeISrEU.js} +1 -1
  76. package/web/dist/assets/stateDiagram-v2-6OUMAXLB-5FZbaloZ.js +1 -0
  77. package/web/dist/assets/{swimlanes-5IMT3BWC-Bqewmkt5.js → swimlanes-5IMT3BWC-DawuBk_a.js} +2 -2
  78. package/web/dist/assets/swimlanesDiagram-G3AALYLV-DL8PgtmM.js +8 -0
  79. package/web/dist/assets/{timeline-definition-FHXFAJF6-DYHsdXUL.js → timeline-definition-FHXFAJF6-BZJ2YJcm.js} +1 -1
  80. package/web/dist/assets/{vennDiagram-L72KCM5P-Cb7cOHSa.js → vennDiagram-L72KCM5P-BMXBVCfe.js} +1 -1
  81. package/web/dist/assets/{wardleyDiagram-EHGQE667-BHpO1byL.js → wardleyDiagram-EHGQE667-DWedKsrQ.js} +1 -1
  82. package/web/dist/assets/{xychartDiagram-FW5EYKEG-DHDvGPtH.js → xychartDiagram-FW5EYKEG--XdfYceC.js} +1 -1
  83. package/web/dist/index.html +3 -3
  84. package/web/runtime.js +19 -0
  85. package/web/server.js +2 -2
  86. package/web/dist/assets/channel-B50-C7oJ.js +0 -1
  87. package/web/dist/assets/classDiagram-OUVF2IWQ-CIJlKS0m.js +0 -1
  88. package/web/dist/assets/classDiagram-v2-EOCWNBFH-CIJlKS0m.js +0 -1
  89. package/web/dist/assets/index-CHlrgp0s.css +0 -1
  90. package/web/dist/assets/index-bf7RCrAf.js +0 -24
  91. package/web/dist/assets/pilotswarm-Di5s6c69.js +0 -105
  92. package/web/dist/assets/stateDiagram-v2-6OUMAXLB-CYIeYmPN.js +0 -1
  93. package/web/dist/assets/swimlanesDiagram-G3AALYLV-BeKhH9C9.js +0 -8
@@ -1,4 +1,6 @@
1
1
  import React from "react";
2
+ import { FeatureFlagsPanel } from "./feature-flags-panel.js";
3
+ import { NativeTaskCard } from "./native-task-card.js";
2
4
  // createPortal is only invoked by browser-only surfaces (tooltips, toolbar
3
5
  // slots, and viewport-level dialogs); the import itself is side-effect-free
4
6
  // and react-dom is a dependency wherever this file loads, so it is safe in the
@@ -838,7 +840,14 @@ function normalizeLines(lines) {
838
840
  };
839
841
 
840
842
  for (const line of lines || []) {
841
- if (line?.kind === "assistantPreview") {
843
+ if (line?.kind === "chatCall" || line?.callPreview !== undefined) {
844
+ // A disclosure is one keyed record, even when its preview contains
845
+ // escaped newlines. Splitting it duplicates callKey and leaves
846
+ // orphaned React nodes behind when the session is replaced.
847
+ normalized.push(line);
848
+ continue;
849
+ }
850
+ if (line?.kind === "assistantPreview" || line?.kind === "nativeTasks") {
842
851
  // Preserve selector-cache identity so another stream's ticks don't
843
852
  // rerender every completed response or recreate its scroll observer.
844
853
  normalized.push(line);
@@ -1075,6 +1084,18 @@ export function computeAnchoredScrollTop(
1075
1084
  : Math.min(maxScroll, offsetPixels);
1076
1085
  }
1077
1086
 
1087
+ function scrollLineIdentity(line) {
1088
+ if (!line) return "";
1089
+ if (line.kind === "runs") return line.runs?.map((run) => run?.text || "").join("") || "";
1090
+ if (line.kind === "assistantPreview") return `assistant:${line.previewKey || line.messageId || line.id || ""}`;
1091
+ return `${line.kind || "text"}:${line.text || line.value || line.id || ""}`;
1092
+ }
1093
+
1094
+ function scrollBoundaryIdentity(lines, fromEnd = false) {
1095
+ const boundary = fromEnd ? lines.slice(-8) : lines.slice(0, 8);
1096
+ return boundary.map(scrollLineIdentity).join("\u241e");
1097
+ }
1098
+
1078
1099
  function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller, { stickyBottom = false } = {}) {
1079
1100
  const normalizedLines = React.useMemo(() => normalizeLines(lines), [lines]);
1080
1101
  // Programmatic scrollTop assignments fire a 'scroll' event that would
@@ -1087,6 +1108,7 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1087
1108
  scrollMode,
1088
1109
  scrollOffset,
1089
1110
  });
1111
+ const previousContentRef = React.useRef(null);
1090
1112
  // Touch scrolling relies on native momentum for speed: a hard flick keeps
1091
1113
  // scrolling long after the finger lifts. Re-asserting scrollTop from state
1092
1114
  // on every render (live events, status updates) kills that momentum at the
@@ -1116,30 +1138,44 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1116
1138
  const node = ref.current;
1117
1139
  if (!node) return;
1118
1140
  const previousViewportState = previousViewportStateRef.current;
1141
+ const firstLine = scrollBoundaryIdentity(normalizedLines);
1142
+ const lastLine = scrollBoundaryIdentity(normalizedLines, true);
1143
+ const previousContent = previousContentRef.current;
1119
1144
  const interaction = userScrollRef.current;
1120
1145
  const now = typeof performance !== "undefined" ? performance.now() : Date.now();
1121
1146
  const interacting = interaction.touching
1122
1147
  || (now - (interaction.lastUserScrollAt || 0)) < TOUCH_MOMENTUM_GRACE_MS;
1123
1148
  const isEchoOffset = interaction.lastDispatchedOffset != null
1124
1149
  && Math.abs((Number(scrollOffset) || 0) - interaction.lastDispatchedOffset) < 2;
1150
+ const preservePausedStickyScroll = stickyBottom
1151
+ && scrollMode === "top"
1152
+ && previousViewportState?.scrollMode === "top"
1153
+ && previousViewportState?.scrollOffset === scrollOffset;
1154
+ // A backward page inserts DOM above the reader. Top-anchored paused
1155
+ // state normally preserves scrollTop, which would push the same visible
1156
+ // message down by the inserted height. Compensate with the measured DOM
1157
+ // height delta. Appended live text keeps the old scrollTop unchanged.
1158
+ const prependedWhilePaused = stickyBottom
1159
+ && previousContent?.lastLine === lastLine
1160
+ && previousContent?.firstLine !== firstLine
1161
+ && node.scrollHeight > previousContent.scrollHeight
1162
+ && (preservePausedStickyScroll || node.scrollTop <= PROGRAMMATIC_SCROLL_TOLERANCE_PX);
1125
1163
  if (
1126
- interacting
1164
+ !prependedWhilePaused
1165
+ && interacting
1127
1166
  && scrollMode === previousViewportState?.scrollMode
1128
1167
  && (scrollOffset === previousViewportState?.scrollOffset || isEchoOffset)
1129
1168
  ) {
1130
1169
  previousViewportStateRef.current = { scrollMode, scrollOffset };
1170
+ previousContentRef.current = { firstLine, lastLine, scrollHeight: node.scrollHeight };
1131
1171
  return;
1132
1172
  }
1133
- const preservePausedStickyScroll = stickyBottom
1134
- && scrollMode === "top"
1135
- && previousViewportState?.scrollMode === "top"
1136
- && previousViewportState?.scrollOffset === scrollOffset;
1137
- const nextScrollTop = computeAnchoredScrollTop(
1138
- node,
1139
- scrollOffset,
1140
- scrollMode,
1141
- preservePausedStickyScroll,
1142
- );
1173
+ const nextScrollTop = prependedWhilePaused
1174
+ ? Math.max(0, Math.min(
1175
+ node.scrollTop + (node.scrollHeight - previousContent.scrollHeight),
1176
+ node.scrollHeight - node.clientHeight,
1177
+ ))
1178
+ : computeAnchoredScrollTop(node, scrollOffset, scrollMode, preservePausedStickyScroll);
1143
1179
  if (Math.abs(node.scrollTop - nextScrollTop) > PROGRAMMATIC_SCROLL_TOLERANCE_PX) {
1144
1180
  const pendingProgrammaticScroll = { target: nextScrollTop };
1145
1181
  programmaticScrollRef.current = pendingProgrammaticScroll;
@@ -1152,10 +1188,20 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1152
1188
  }
1153
1189
  });
1154
1190
  }
1191
+ if (prependedWhilePaused && paneKey && typeof controller.updatePaneScrollFromViewport === "function") {
1192
+ // The measured DOM compensation above is the new durable paused
1193
+ // position. Persist it too: otherwise switching sessions and back
1194
+ // reapplies the pre-page offset and moves the reader by the full
1195
+ // height of the newly inserted history.
1196
+ const rowOffset = Math.max(0, nextScrollTop) / SCROLL_ROW_HEIGHT;
1197
+ userScrollRef.current.lastDispatchedOffset = rowOffset;
1198
+ controller.updatePaneScrollFromViewport(paneKey, rowOffset, { atBottom: false });
1199
+ }
1155
1200
  previousViewportStateRef.current = {
1156
1201
  scrollMode,
1157
1202
  scrollOffset,
1158
1203
  };
1204
+ previousContentRef.current = { firstLine, lastLine, scrollHeight: node.scrollHeight };
1159
1205
  }, [normalizedLines, ref, scrollMode, scrollOffset, stickyBottom, viewportRevision]);
1160
1206
 
1161
1207
  const dispatchScrollOffset = useFrameCoalescedCallback((offset) => {
@@ -1189,6 +1235,13 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1189
1235
  rowOffset,
1190
1236
  { atBottom: isScrollViewportAtBottom(node) },
1191
1237
  );
1238
+ // Pausing bottom-follow changes chat to top-anchored scroll state,
1239
+ // but reaching the DOM's actual top must still arm backward CMS
1240
+ // paging. Keep this next to the native measurement so the history
1241
+ // gate does not depend on which anchoring mode currently renders.
1242
+ if (paneKey === "chat" && node.scrollTop <= PROGRAMMATIC_SCROLL_TOLERANCE_PX) {
1243
+ controller.armChatTopHistoryLoad?.();
1244
+ }
1192
1245
  return;
1193
1246
  }
1194
1247
 
@@ -1207,11 +1260,11 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1207
1260
 
1208
1261
  const onWheel = React.useCallback((event) => {
1209
1262
  const node = ref.current;
1210
- if (!node || paneKey !== "chat" || scrollMode !== "bottom" || event.deltaY >= 0) return;
1263
+ if (!node || paneKey !== "chat" || event.deltaY >= 0) return;
1211
1264
  if (node.scrollTop > PROGRAMMATIC_SCROLL_TOLERANCE_PX) return;
1212
1265
  const maxScroll = Math.max(0, node.scrollHeight - node.clientHeight);
1213
- controller.handleChatTopHistoryScrollIntent?.(maxScroll / SCROLL_ROW_HEIGHT);
1214
- }, [controller, paneKey, ref, scrollMode]);
1266
+ controller.handleChatTopHistoryScrollIntent?.(maxScroll / SCROLL_ROW_HEIGHT, { preserveDomAnchor: true });
1267
+ }, [controller, paneKey, ref]);
1215
1268
 
1216
1269
  // Touch equivalent of the wheel-at-top gesture: touch devices never fire
1217
1270
  // wheel events, and once scrollTop sits at 0 a further swipe-down emits no
@@ -1221,9 +1274,9 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1221
1274
  const touchPullRef = React.useRef({ startY: null, fired: false });
1222
1275
  const onTouchStart = React.useCallback((event) => {
1223
1276
  userScrollRef.current.touching = true;
1224
- if (paneKey !== "chat" || scrollMode !== "bottom") return;
1277
+ if (paneKey !== "chat") return;
1225
1278
  touchPullRef.current = { startY: event.touches?.[0]?.clientY ?? null, fired: false };
1226
- }, [paneKey, scrollMode]);
1279
+ }, [paneKey]);
1227
1280
  const onTouchEnd = React.useCallback(() => {
1228
1281
  userScrollRef.current.touching = false;
1229
1282
  // Momentum continues past the finger lift; onScroll keeps refreshing
@@ -1233,7 +1286,7 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1233
1286
  const onTouchMove = React.useCallback((event) => {
1234
1287
  const node = ref.current;
1235
1288
  const pull = touchPullRef.current;
1236
- if (!node || paneKey !== "chat" || scrollMode !== "bottom") return;
1289
+ if (!node || paneKey !== "chat") return;
1237
1290
  if (pull.fired || pull.startY == null) return;
1238
1291
  if (node.scrollTop > PROGRAMMATIC_SCROLL_TOLERANCE_PX) return;
1239
1292
  const y = event.touches?.[0]?.clientY;
@@ -1245,8 +1298,8 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1245
1298
  // on narrow viewports). The wheel path keeps the handshake — one
1246
1299
  // physical scroll emits MANY wheel events, so it needs debouncing.
1247
1300
  const maxScroll = Math.max(0, node.scrollHeight - node.clientHeight);
1248
- controller.handleChatTopHistoryScrollIntent?.(maxScroll / SCROLL_ROW_HEIGHT + 1, { force: true });
1249
- }, [controller, paneKey, ref, scrollMode]);
1301
+ controller.handleChatTopHistoryScrollIntent?.(maxScroll / SCROLL_ROW_HEIGHT + 1, { force: true, preserveDomAnchor: true });
1302
+ }, [controller, paneKey, ref]);
1250
1303
 
1251
1304
  return { normalizedLines, onScroll, onWheel, onTouchStart, onTouchMove, onTouchEnd };
1252
1305
  }
@@ -1343,6 +1396,65 @@ function ChatCallLine({ line }) {
1343
1396
  React.createElement("pre", { className: "ps-chat-call-payload" }, line.body)) : null);
1344
1397
  }
1345
1398
 
1399
+ function ChatActivityRun({ calls }) {
1400
+ const latest = calls[calls.length - 1] || {};
1401
+ const active = latest.status === "Called" || latest.status === "Started";
1402
+ const failed = calls.some((call) => call.status === "Failed");
1403
+ const [open, setOpen] = React.useState(active);
1404
+ const viewportRef = React.useRef(null);
1405
+ const followRef = React.useRef(true);
1406
+ const categories = new Set(calls.map((call) => call.category || "Tool"));
1407
+ const countLabel = categories.size === 1 && categories.has("Tool")
1408
+ ? `${calls.length} tool ${calls.length === 1 ? "call" : "calls"}`
1409
+ : categories.size === 1 && categories.has("Agent")
1410
+ ? `${calls.length} agent ${calls.length === 1 ? "activity" : "activities"}`
1411
+ : `${calls.length} activities`;
1412
+ const latestName = String(latest.text || latest.category || "activity").split(" — ")[0];
1413
+ const status = active ? "Working" : failed ? "Failed" : "Done";
1414
+ const updateKey = `${latest.callKey || ""}:${latest.status || ""}:${String(latest.body || "").length}`;
1415
+
1416
+ React.useLayoutEffect(() => {
1417
+ const viewport = viewportRef.current;
1418
+ if (open && viewport && followRef.current) viewport.scrollTop = viewport.scrollHeight;
1419
+ }, [open, calls.length, updateKey]);
1420
+
1421
+ return React.createElement("details", {
1422
+ className: "ps-native-tasks ps-activity-run",
1423
+ open,
1424
+ onToggle: (event) => setOpen(event.currentTarget.open),
1425
+ },
1426
+ React.createElement("summary", { className: "ps-native-tasks-header ps-activity-run-summary" },
1427
+ React.createElement("span", { className: "ps-native-tasks-title" },
1428
+ React.createElement("span", { className: "ps-native-task-branch", "aria-hidden": true }, "⌘"),
1429
+ countLabel),
1430
+ React.createElement("span", { className: "ps-activity-run-latest", title: latest.text || "" }, `latest: ${latestName}`),
1431
+ React.createElement("span", { className: `ps-activity-run-status${failed ? " is-failed" : ""}` }, status),
1432
+ React.createElement("span", { className: "ps-activity-run-chevron", "aria-hidden": true }, "›")),
1433
+ React.createElement("div", {
1434
+ ref: viewportRef,
1435
+ className: "ps-activity-run-viewport",
1436
+ role: "region",
1437
+ "aria-label": `${countLabel} activity log`,
1438
+ tabIndex: 0,
1439
+ onScroll: (event) => {
1440
+ event.stopPropagation();
1441
+ followRef.current = getScrollDistanceToBottom(event.currentTarget) <= 24;
1442
+ },
1443
+ onWheel: (event) => {
1444
+ event.stopPropagation();
1445
+ if (event.deltaY < 0) followRef.current = false;
1446
+ },
1447
+ onTouchStart: (event) => {
1448
+ event.stopPropagation();
1449
+ followRef.current = false;
1450
+ },
1451
+ onTouchMove: (event) => event.stopPropagation(),
1452
+ onTouchEnd: (event) => event.stopPropagation(),
1453
+ }, calls.map((call) => React.createElement(ChatCallLine, { key: call.callKey, line: call }))),
1454
+ React.createElement("div", { className: "ps-activity-run-footer" },
1455
+ `Showing ${calls.length} ${calls.length === 1 ? "entry" : "entries"} · Scroll for earlier activity`));
1456
+ }
1457
+
1346
1458
  /**
1347
1459
  * A canvas action is a button press inside the drawn page, not something the
1348
1460
  * viewer typed. Printing the raw `[canvas-action] {…}` JSON as a chat message
@@ -3242,12 +3354,24 @@ function parseStructuredChatBlocks(lines = []) {
3242
3354
  for (let index = 0; index < lines.length;) {
3243
3355
  const currentLine = lines[index];
3244
3356
 
3245
- if (currentLine?.kind === "chatCall" || currentLine?.callPreview !== undefined) {
3246
- blocks.push({ type: "chatCall", line: currentLine.callPreview !== undefined
3247
- ? { ...currentLine, text: currentLine.callPreview, category: "Agent" } : currentLine });
3357
+ if (currentLine?.kind === "nativeTasks") {
3358
+ blocks.push({ type: "nativeTasks", group: currentLine.group });
3248
3359
  index += 1;
3249
3360
  continue;
3250
3361
  }
3362
+ if (currentLine?.kind === "chatCall" || currentLine?.callPreview !== undefined) {
3363
+ const calls = [];
3364
+ while (index < lines.length) {
3365
+ const line = lines[index];
3366
+ if (line?.kind !== "chatCall" && line?.callPreview === undefined) break;
3367
+ calls.push(line.callPreview !== undefined
3368
+ ? { ...line, text: line.callPreview, category: "Agent" }
3369
+ : line);
3370
+ index += 1;
3371
+ }
3372
+ blocks.push({ type: "chatCallGroup", groupKey: calls[0]?.callKey, calls });
3373
+ continue;
3374
+ }
3251
3375
 
3252
3376
  if (currentLine?.kind === "assistantPreview") {
3253
3377
  blocks.push({ type: "assistantPreview", line: currentLine });
@@ -3674,8 +3798,14 @@ const AssistantPreviewCard = React.memo(function AssistantPreviewCard({ line, th
3674
3798
  function StructuredBlockList({ blocks, theme, controller = null }) {
3675
3799
  return React.createElement(React.Fragment, null,
3676
3800
  (blocks || []).map((block, index) => {
3677
- if (block.type === "chatCall") {
3678
- return React.createElement(ChatCallLine, { key: block.line.callKey, line: block.line });
3801
+ if (block.type === "nativeTasks") {
3802
+ return React.createElement(NativeTaskCard, { key: block.group.id, group: block.group,
3803
+ colors: { starting: resolveColor(theme, "cyan"), running: resolveColor(theme, "cyan"),
3804
+ waiting: resolveColor(theme, "yellow"), completed: resolveColor(theme, "green"),
3805
+ failed: resolveColor(theme, "red"), cancelled: resolveColor(theme, "gray"), interrupted: resolveColor(theme, "yellow") } });
3806
+ }
3807
+ if (block.type === "chatCallGroup") {
3808
+ return React.createElement(ChatActivityRun, { key: block.groupKey, calls: block.calls });
3679
3809
  }
3680
3810
  if (block.type === "assistantPreview") {
3681
3811
  return React.createElement(AssistantPreviewCard, {
@@ -5555,8 +5685,8 @@ function SessionPane({ controller, actions = null, panelClassName = "", structur
5555
5685
  // shortcut handler decides "am I editable?" from the event target, the
5556
5686
  // rest of what the user typed ran as commands (d = complete,
5557
5687
  // D = delete). Scrolling on every refresh has a milder failure but the
5558
- // same shape: the list yanks back to the active row while the user is
5559
- // deliberately scrolled away browsing older sessions.
5688
+ // same shape. Selection must never alter the list's scroll position;
5689
+ // only the user's own scroll gestures move it.
5560
5690
  if (revealedRowKeyRef.current === activeRowRevealKey) return;
5561
5691
  revealedRowKeyRef.current = activeRowRevealKey;
5562
5692
 
@@ -5570,10 +5700,9 @@ function SessionPane({ controller, actions = null, panelClassName = "", structur
5570
5700
  || focused.tagName === "SELECT"
5571
5701
  || focused.isContentEditable
5572
5702
  ));
5573
- if (focused !== activeButton && !isTypingTarget) {
5703
+ if (viewState.focused && focused !== activeButton && !isTypingTarget) {
5574
5704
  activeButton.focus({ preventScroll: true });
5575
5705
  }
5576
- activeButton.scrollIntoView({ block: "nearest" });
5577
5706
  }, [activeRowRevealKey, viewState.activeSessionId, viewState.focused, viewState.modalOpen, viewState.sessionsFlat]);
5578
5707
 
5579
5708
  const panelActions = React.createElement(React.Fragment, null,
@@ -6492,6 +6621,7 @@ function ChatPane({ controller, mobile = false, fullWidth = false, showComposer
6492
6621
  activeSessionStatus: activeSessionId ? String(state.sessions.byId[activeSessionId]?.status || "").toLowerCase() : "",
6493
6622
  focused: state.ui.focusRegion === "chat",
6494
6623
  scroll: state.ui.scroll.chat,
6624
+ followBottom: state.ui.followBottom?.chat !== false,
6495
6625
  // Viewer identity — so the transcript can say "You" for the viewer's
6496
6626
  // own messages and name others (with an "(owner)" tag).
6497
6627
  authPrincipal: state.auth?.principal || null,
@@ -6641,7 +6771,8 @@ function ChatPane({ controller, mobile = false, fullWidth = false, showComposer
6641
6771
  bottomStickyLines: activityInHeader ? EMPTY_ARRAY : stickyBottom,
6642
6772
  reserveBottomSticky: !activityInHeader,
6643
6773
  scrollOffset: viewState.scroll,
6644
- scrollMode: "bottom",
6774
+ scrollMode: viewState.followBottom ? "bottom" : "top",
6775
+ stickyBottom: true,
6645
6776
  paneKey: "chat",
6646
6777
  ariaLive: "polite",
6647
6778
  className: "is-wrapped",
@@ -9086,7 +9217,7 @@ function PromptComposer({ controller, mobile, compact = false, active = true, on
9086
9217
  onClick: cancelPending,
9087
9218
  }, selectedQueued ? "Delete" : "Cancel")
9088
9219
  : null,
9089
- !compact && (promptState.canStopTurn || stoppingTurn)
9220
+ (promptState.canStopTurn || stoppingTurn)
9090
9221
  ? React.createElement("button", {
9091
9222
  type: "button",
9092
9223
  className: `ps-stop-button${stoppingTurn ? " is-stopping" : ""}`,
@@ -13143,9 +13274,16 @@ function formatAdminPrincipalLabel(principal) {
13143
13274
 
13144
13275
  function AdminConsolePanel({ controller, mobile = false }) {
13145
13276
  const view = useControllerSelector(controller, selectAdminConsole, shallowEqualObject);
13277
+ const features = useControllerSelector(controller, state => state.admin.features);
13278
+ const featureWorkers = useControllerSelector(controller, state => state.admin.workers);
13279
+ const featureRole = useControllerSelector(controller, state => state.auth?.authorization?.role);
13146
13280
  const packages = view.packages || {};
13147
13281
  const showPackages = view.section === "packages";
13148
13282
  const showWorkers = view.section === "workers";
13283
+ const showFeatures = view.section === "features";
13284
+ const featureSection = React.createElement(FeatureFlagsPanel, { controller, features,
13285
+ workers: featureWorkers?.list || [], workersError: featureWorkers?.error,
13286
+ isAdmin: view.isAdmin && (!featureRole || featureRole === "admin" || featureRole === "anonymous") });
13149
13287
  const [providerSheet, setProviderSheet] = React.useState(null);
13150
13288
  const [providerSheetBusy, setProviderSheetBusy] = React.useState(false);
13151
13289
  const [providerSheetError, setProviderSheetError] = React.useState(null);
@@ -13294,7 +13432,7 @@ function AdminConsolePanel({ controller, mobile = false }) {
13294
13432
  body = React.createElement("div", { className: "ps-admin-mobile-stack" }, tree,
13295
13433
  React.createElement(AdminWorkersPane, { controller, view }));
13296
13434
  } else {
13297
- body = React.createElement("div", { className: "ps-admin-mobile-stack" }, tree, providerSection);
13435
+ body = React.createElement("div", { className: "ps-admin-mobile-stack" }, tree, showFeatures ? featureSection : providerSection);
13298
13436
  }
13299
13437
  return React.createElement("div", { className: "ps-admin-console is-mobile" },
13300
13438
  header,
@@ -13323,7 +13461,7 @@ function AdminConsolePanel({ controller, mobile = false }) {
13323
13461
  "aria-label": "Resize settings column",
13324
13462
  })),
13325
13463
  React.createElement("div", { className: "ps-admin-main" },
13326
- showPackages ? detail : showWorkers ? React.createElement(AdminWorkersPane, { controller, view }) : providerSection),
13464
+ showPackages ? detail : showWorkers ? React.createElement(AdminWorkersPane, { controller, view }) : showFeatures ? featureSection : providerSection),
13327
13465
  workspacePane),
13328
13466
  dialog,
13329
13467
  createProviderDialog);
@@ -13417,6 +13555,8 @@ function AdminSettingsTree({ controller, view }) {
13417
13555
  } else if (row.id === "sharedProviders") {
13418
13556
  controller.setAdminSection("providers");
13419
13557
  controller.setAdminModelProviderPage("shared");
13558
+ } else if (row.id === "features") {
13559
+ controller.setAdminSection("features");
13420
13560
  } else {
13421
13561
  controller.setAdminSection(row.id === "agents" ? "packages" : "workers");
13422
13562
  }
@@ -1 +1 @@
1
- import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-l907LpMA.js";import{p as f}from"./chunk-JWPE2WC7-Cj5lvEfN.js";import{_ as n,l as o}from"./mermaid.core-B5elhUtV.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-CminxBoG.js";import"./pilotswarm-Di5s6c69.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-MltzhnwP.js";import{p as f}from"./chunk-JWPE2WC7-DWnKTQ72.js";import{_ as n,l as o}from"./mermaid.core-DALDJDu8.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-Dg1cltg6.js";import"./pilotswarm-B9rLtXpI.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-B5elhUtV.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-DALDJDu8.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};