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.
- package/mcp/dist/src/server.d.ts.map +1 -1
- package/mcp/dist/src/server.js +2 -0
- package/mcp/dist/src/server.js.map +1 -1
- package/mcp/dist/src/tools/features.d.ts +4 -0
- package/mcp/dist/src/tools/features.d.ts.map +1 -0
- package/mcp/dist/src/tools/features.js +35 -0
- package/mcp/dist/src/tools/features.js.map +1 -0
- package/package.json +2 -2
- package/tui/src/node-sdk-transport.js +13 -0
- package/ui/core/src/controller.js +330 -14
- package/ui/core/src/history.js +89 -14
- package/ui/core/src/moa.js +9 -0
- package/ui/core/src/native-tasks.js +197 -0
- package/ui/core/src/question-display.js +13 -0
- package/ui/core/src/reducer.js +31 -7
- package/ui/core/src/selectors.js +46 -13
- package/ui/core/src/session-errors.js +13 -6
- package/ui/core/src/session-warning.js +14 -0
- package/ui/core/src/state.js +7 -2
- package/ui/react/src/components.js +2 -1
- package/ui/react/src/feature-flags-panel.js +186 -0
- package/ui/react/src/native-task-card.js +59 -0
- package/ui/react/src/web-app.js +173 -33
- package/web/dist/assets/{abnfDiagram-VRR7QNED-DAiG41W-.js → abnfDiagram-VRR7QNED-gIPHF2gV.js} +1 -1
- package/web/dist/assets/{arc-CN_GY3DG.js → arc-DMW_q5Ml.js} +1 -1
- package/web/dist/assets/{architectureDiagram-ZJ3FMSHR-DD9qiBOj.js → architectureDiagram-ZJ3FMSHR-DAKsrxcB.js} +1 -1
- package/web/dist/assets/{blockDiagram-677ZJIJ3-CZg2R8i6.js → blockDiagram-677ZJIJ3-BUjSLpP3.js} +1 -1
- package/web/dist/assets/{c4Diagram-LMCZKHZV-DuZxUZYd.js → c4Diagram-LMCZKHZV-Dw2nPoes.js} +1 -1
- package/web/dist/assets/channel-CcOa1LtY.js +1 -0
- package/web/dist/assets/{chunk-2Q5K7J3B-BX7lDvmf.js → chunk-2Q5K7J3B-BAL28Rv0.js} +1 -1
- package/web/dist/assets/{chunk-32BRIVSS-COupwzAw.js → chunk-32BRIVSS-DDlt9K8s.js} +1 -1
- package/web/dist/assets/{chunk-5VM5RSS4-C_IyERib.js → chunk-5VM5RSS4-BLQGJGoP.js} +1 -1
- package/web/dist/assets/{chunk-EX3LRPZG-CyfIuYKn.js → chunk-EX3LRPZG-XFMb3HRy.js} +1 -1
- package/web/dist/assets/{chunk-JWPE2WC7-Cj5lvEfN.js → chunk-JWPE2WC7-DWnKTQ72.js} +1 -1
- package/web/dist/assets/{chunk-MOJQB5TN-l907LpMA.js → chunk-MOJQB5TN-MltzhnwP.js} +1 -1
- package/web/dist/assets/{chunk-RYQCIY6F-PLru1fOZ.js → chunk-RYQCIY6F-Ce3q0-mJ.js} +1 -1
- package/web/dist/assets/{chunk-V7JOEXUC-C6GCxiE5.js → chunk-V7JOEXUC-ThXLYY88.js} +1 -1
- package/web/dist/assets/{chunk-VR4S4FIN-BGelrIxQ.js → chunk-VR4S4FIN-DbhAykiW.js} +1 -1
- package/web/dist/assets/{chunk-XXDRQBXY-BmJstjEv.js → chunk-XXDRQBXY-BpkNB0mD.js} +1 -1
- package/web/dist/assets/classDiagram-OUVF2IWQ-B2VhHRSV.js +1 -0
- package/web/dist/assets/classDiagram-v2-EOCWNBFH-B2VhHRSV.js +1 -0
- package/web/dist/assets/{cose-bilkent-JH36ORCC-CRabxOOK.js → cose-bilkent-JH36ORCC-rctqAPvj.js} +1 -1
- package/web/dist/assets/{cynefin-VYW2F7L2-CminxBoG.js → cynefin-VYW2F7L2-Dg1cltg6.js} +1 -1
- package/web/dist/assets/{cynefinDiagram-TSTJHNR4-yBazsQf4.js → cynefinDiagram-TSTJHNR4-Ci23Sv4Z.js} +1 -1
- package/web/dist/assets/{dagre-VKFMJZFB-DcZuZV2n.js → dagre-VKFMJZFB-BpWTGhpv.js} +1 -1
- package/web/dist/assets/{diagram-FQU43EPY-CHoFzsw6.js → diagram-FQU43EPY-B69JpiAe.js} +1 -1
- package/web/dist/assets/{diagram-G47NLZAW-B8leqMRl.js → diagram-G47NLZAW-BHMk1TOO.js} +1 -1
- package/web/dist/assets/{diagram-NH7WQ7WH-DNoVxpa3.js → diagram-NH7WQ7WH-CtvZIIsk.js} +1 -1
- package/web/dist/assets/{diagram-OA4YK3LP-gC3Q2X6-.js → diagram-OA4YK3LP-BFvKh800.js} +1 -1
- package/web/dist/assets/{diagram-WEI45ONY-CABqyjDl.js → diagram-WEI45ONY-CgB8sWPe.js} +1 -1
- package/web/dist/assets/{ebnfDiagram-CCIWWBDH-cSguXaDC.js → ebnfDiagram-CCIWWBDH-DyqPNydM.js} +1 -1
- package/web/dist/assets/{erDiagram-Q63AITRT-CoWX37V3.js → erDiagram-Q63AITRT-CwpvZQ3Q.js} +1 -1
- package/web/dist/assets/{flowDiagram-23GEKE2U-I9DHYjhG.js → flowDiagram-23GEKE2U-EBKSKxfC.js} +1 -1
- package/web/dist/assets/{ganttDiagram-NO4QXBWP-DaFnfYTt.js → ganttDiagram-NO4QXBWP-q5tMPAuC.js} +1 -1
- package/web/dist/assets/{gitGraphDiagram-IHSO6WYX-CwiXVM_O.js → gitGraphDiagram-IHSO6WYX-DCRbi4KE.js} +1 -1
- package/web/dist/assets/index-BfF7e08d.js +24 -0
- package/web/dist/assets/index-uhc851H3.css +1 -0
- package/web/dist/assets/{infoDiagram-FWYZ7A6U-DtzIrIpW.js → infoDiagram-FWYZ7A6U-Bex5pSIX.js} +1 -1
- package/web/dist/assets/{ishikawaDiagram-FXEZZL3T-B9nk829n.js → ishikawaDiagram-FXEZZL3T-Dj0li_TY.js} +1 -1
- package/web/dist/assets/{journeyDiagram-5HDEW3XC-xLaPm-ow.js → journeyDiagram-5HDEW3XC-BtEGEeVr.js} +1 -1
- package/web/dist/assets/{kanban-definition-HUTT4EX6-BnDqLYLC.js → kanban-definition-HUTT4EX6-BTFfZvYt.js} +1 -1
- package/web/dist/assets/{linear-Djc7nVo8.js → linear-C3SQCsip.js} +1 -1
- package/web/dist/assets/{mermaid.core-B5elhUtV.js → mermaid.core-DALDJDu8.js} +4 -4
- package/web/dist/assets/{mindmap-definition-LN4V7U3C-N-B7EJGs.js → mindmap-definition-LN4V7U3C-BZf3uw0u.js} +1 -1
- package/web/dist/assets/{papaparse.min-BqM-LJkq.js → papaparse.min-Bh9MZ-fk.js} +1 -1
- package/web/dist/assets/{pegDiagram-2B236MQR-BIollSMB.js → pegDiagram-2B236MQR-PuOleiMg.js} +1 -1
- package/web/dist/assets/{pieDiagram-ENE6RG2P-DkZY6iCd.js → pieDiagram-ENE6RG2P-CcFORUaW.js} +1 -1
- package/web/dist/assets/pilotswarm-B9rLtXpI.js +109 -0
- package/web/dist/assets/{quadrantDiagram-ABIIQ3AL-iUDmQIyL.js → quadrantDiagram-ABIIQ3AL-CEm0mp4y.js} +1 -1
- package/web/dist/assets/{railroadDiagram-RFXS5EU6-BSCGJgV7.js → railroadDiagram-RFXS5EU6-DeH-uX0_.js} +1 -1
- package/web/dist/assets/{requirementDiagram-TGXJPOKE-9yqcGRUA.js → requirementDiagram-TGXJPOKE-CMbJVMc1.js} +1 -1
- package/web/dist/assets/{sankeyDiagram-HTMAVEWB-SPh1plT9.js → sankeyDiagram-HTMAVEWB-C9gL5w_b.js} +1 -1
- package/web/dist/assets/{sequenceDiagram-DBY2YBRQ-C0nv5x71.js → sequenceDiagram-DBY2YBRQ-BUo8TT74.js} +1 -1
- package/web/dist/assets/{sizeCapture-X5ZJPWSS-DMXfUt1o.js → sizeCapture-X5ZJPWSS-C5lqG0ei.js} +1 -1
- package/web/dist/assets/{stateDiagram-2N3HPSRC-vjhtquua.js → stateDiagram-2N3HPSRC-DyeISrEU.js} +1 -1
- package/web/dist/assets/stateDiagram-v2-6OUMAXLB-5FZbaloZ.js +1 -0
- package/web/dist/assets/{swimlanes-5IMT3BWC-Bqewmkt5.js → swimlanes-5IMT3BWC-DawuBk_a.js} +2 -2
- package/web/dist/assets/swimlanesDiagram-G3AALYLV-DL8PgtmM.js +8 -0
- package/web/dist/assets/{timeline-definition-FHXFAJF6-DYHsdXUL.js → timeline-definition-FHXFAJF6-BZJ2YJcm.js} +1 -1
- package/web/dist/assets/{vennDiagram-L72KCM5P-Cb7cOHSa.js → vennDiagram-L72KCM5P-BMXBVCfe.js} +1 -1
- package/web/dist/assets/{wardleyDiagram-EHGQE667-BHpO1byL.js → wardleyDiagram-EHGQE667-DWedKsrQ.js} +1 -1
- package/web/dist/assets/{xychartDiagram-FW5EYKEG-DHDvGPtH.js → xychartDiagram-FW5EYKEG--XdfYceC.js} +1 -1
- package/web/dist/index.html +3 -3
- package/web/runtime.js +19 -0
- package/web/server.js +2 -2
- package/web/dist/assets/channel-B50-C7oJ.js +0 -1
- package/web/dist/assets/classDiagram-OUVF2IWQ-CIJlKS0m.js +0 -1
- package/web/dist/assets/classDiagram-v2-EOCWNBFH-CIJlKS0m.js +0 -1
- package/web/dist/assets/index-CHlrgp0s.css +0 -1
- package/web/dist/assets/index-bf7RCrAf.js +0 -24
- package/web/dist/assets/pilotswarm-Di5s6c69.js +0 -105
- package/web/dist/assets/stateDiagram-v2-6OUMAXLB-CYIeYmPN.js +0 -1
- package/web/dist/assets/swimlanesDiagram-G3AALYLV-BeKhH9C9.js +0 -8
package/ui/react/src/web-app.js
CHANGED
|
@@ -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 === "
|
|
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
|
-
|
|
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
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
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" ||
|
|
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
|
|
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"
|
|
1277
|
+
if (paneKey !== "chat") return;
|
|
1225
1278
|
touchPullRef.current = { startY: event.touches?.[0]?.clientY ?? null, fired: false };
|
|
1226
|
-
}, [paneKey
|
|
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"
|
|
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
|
|
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 === "
|
|
3246
|
-
blocks.push({ type: "
|
|
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 === "
|
|
3678
|
-
return React.createElement(
|
|
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
|
|
5559
|
-
//
|
|
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
|
-
|
|
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
|
}
|
package/web/dist/assets/{abnfDiagram-VRR7QNED-DAiG41W-.js → abnfDiagram-VRR7QNED-gIPHF2gV.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-
|
|
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-
|
|
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};
|