pilotswarm 0.5.77 → 0.5.78

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 (71) hide show
  1. package/package.json +2 -2
  2. package/tui/src/embedded-workers.js +3 -0
  3. package/ui/react/src/web-app.js +73 -56
  4. package/web/dist/assets/{abnfDiagram-VRR7QNED-CKO_DwJV.js → abnfDiagram-VRR7QNED-C2HGSvvf.js} +1 -1
  5. package/web/dist/assets/{arc-DNYWrpvl.js → arc-C3faoYvN.js} +1 -1
  6. package/web/dist/assets/{architectureDiagram-ZJ3FMSHR-BuYVWnLH.js → architectureDiagram-ZJ3FMSHR-CQhrAa5t.js} +1 -1
  7. package/web/dist/assets/{blockDiagram-677ZJIJ3-Cl_IMZqi.js → blockDiagram-677ZJIJ3-CVGwBieB.js} +1 -1
  8. package/web/dist/assets/{c4Diagram-LMCZKHZV-Dp8EWK6S.js → c4Diagram-LMCZKHZV-CmdrEA77.js} +1 -1
  9. package/web/dist/assets/channel-CTmDTaW4.js +1 -0
  10. package/web/dist/assets/{chunk-2Q5K7J3B-Dja0nryh.js → chunk-2Q5K7J3B-Bm1hu4Hq.js} +1 -1
  11. package/web/dist/assets/{chunk-32BRIVSS-BfmHxlTO.js → chunk-32BRIVSS--_hODe_V.js} +1 -1
  12. package/web/dist/assets/{chunk-5VM5RSS4-DJ3zmwrq.js → chunk-5VM5RSS4-COI5t4m6.js} +1 -1
  13. package/web/dist/assets/{chunk-EX3LRPZG-B6SN8xEo.js → chunk-EX3LRPZG-BCFKy6tL.js} +1 -1
  14. package/web/dist/assets/{chunk-JWPE2WC7-Dlgqhr3G.js → chunk-JWPE2WC7-Ddh7J2Rp.js} +1 -1
  15. package/web/dist/assets/{chunk-MOJQB5TN-Dn-J2ayj.js → chunk-MOJQB5TN-DuIGV22R.js} +1 -1
  16. package/web/dist/assets/{chunk-RYQCIY6F-Af9a3V0M.js → chunk-RYQCIY6F-BNQbAlZV.js} +1 -1
  17. package/web/dist/assets/{chunk-V7JOEXUC-M3md4NxL.js → chunk-V7JOEXUC-DmoLjQx9.js} +1 -1
  18. package/web/dist/assets/{chunk-VR4S4FIN-ee4UcZX-.js → chunk-VR4S4FIN-BTOlqom4.js} +1 -1
  19. package/web/dist/assets/{chunk-XXDRQBXY-C1o9OH3_.js → chunk-XXDRQBXY-DTsc-Dgs.js} +1 -1
  20. package/web/dist/assets/classDiagram-OUVF2IWQ-0JetCpCm.js +1 -0
  21. package/web/dist/assets/classDiagram-v2-EOCWNBFH-0JetCpCm.js +1 -0
  22. package/web/dist/assets/{cose-bilkent-JH36ORCC-CRxjVQDN.js → cose-bilkent-JH36ORCC-QEqZLCny.js} +1 -1
  23. package/web/dist/assets/{cynefin-VYW2F7L2-MSAXYGkZ.js → cynefin-VYW2F7L2-Deleul8f.js} +1 -1
  24. package/web/dist/assets/{cynefinDiagram-TSTJHNR4-BPutBNN1.js → cynefinDiagram-TSTJHNR4-D0HrNQd4.js} +1 -1
  25. package/web/dist/assets/{dagre-VKFMJZFB-_W1WeW3E.js → dagre-VKFMJZFB-CLdKXtyZ.js} +1 -1
  26. package/web/dist/assets/{diagram-FQU43EPY-DT_0zQl9.js → diagram-FQU43EPY-C0DnCIiG.js} +1 -1
  27. package/web/dist/assets/{diagram-G47NLZAW-HBy_Ck1W.js → diagram-G47NLZAW-DzQa8iDK.js} +1 -1
  28. package/web/dist/assets/{diagram-NH7WQ7WH-DyQQlTUp.js → diagram-NH7WQ7WH-CazRIZg4.js} +1 -1
  29. package/web/dist/assets/{diagram-OA4YK3LP-LJ7WYOVk.js → diagram-OA4YK3LP-gZanfxjg.js} +1 -1
  30. package/web/dist/assets/{diagram-WEI45ONY-B83fa0oq.js → diagram-WEI45ONY-CHoHyTz-.js} +1 -1
  31. package/web/dist/assets/{ebnfDiagram-CCIWWBDH-ZbAvBv6c.js → ebnfDiagram-CCIWWBDH-CeHz2Jh9.js} +1 -1
  32. package/web/dist/assets/{erDiagram-Q63AITRT-BNe1kdom.js → erDiagram-Q63AITRT-C95MErio.js} +1 -1
  33. package/web/dist/assets/{flowDiagram-23GEKE2U-DDlbRR4H.js → flowDiagram-23GEKE2U-AdgXiTao.js} +1 -1
  34. package/web/dist/assets/{ganttDiagram-NO4QXBWP-DRvGvhmv.js → ganttDiagram-NO4QXBWP-D7Ltt8Pp.js} +1 -1
  35. package/web/dist/assets/{gitGraphDiagram-IHSO6WYX-Bj5CkOw6.js → gitGraphDiagram-IHSO6WYX-9Xi-xmei.js} +1 -1
  36. package/web/dist/assets/index-C7_15DMS.css +1 -0
  37. package/web/dist/assets/index-IxnOJbWb.js +24 -0
  38. package/web/dist/assets/{infoDiagram-FWYZ7A6U-BB-pO5BG.js → infoDiagram-FWYZ7A6U-fRlxZHtD.js} +1 -1
  39. package/web/dist/assets/{ishikawaDiagram-FXEZZL3T-fplKz6J9.js → ishikawaDiagram-FXEZZL3T-CEVSVKfj.js} +1 -1
  40. package/web/dist/assets/{journeyDiagram-5HDEW3XC-CZXJ9si6.js → journeyDiagram-5HDEW3XC-CJhad1Ay.js} +1 -1
  41. package/web/dist/assets/{kanban-definition-HUTT4EX6-CL9u5Pmv.js → kanban-definition-HUTT4EX6-CE6OFSTa.js} +1 -1
  42. package/web/dist/assets/{linear-WwQWwN2U.js → linear-BuexMwfW.js} +1 -1
  43. package/web/dist/assets/{mermaid.core-1gBc6FeB.js → mermaid.core-DWYsDHXh.js} +4 -4
  44. package/web/dist/assets/{mindmap-definition-LN4V7U3C-CtKgb3BP.js → mindmap-definition-LN4V7U3C-6_lFebqE.js} +1 -1
  45. package/web/dist/assets/{papaparse.min-Dk5F4KnO.js → papaparse.min-DjlrGi59.js} +1 -1
  46. package/web/dist/assets/{pegDiagram-2B236MQR-rkKhqRQO.js → pegDiagram-2B236MQR-B1fuWjDp.js} +1 -1
  47. package/web/dist/assets/{pieDiagram-ENE6RG2P-VfaXje3o.js → pieDiagram-ENE6RG2P-BWsDDxls.js} +1 -1
  48. package/web/dist/assets/pilotswarm-3GsGwA3r.js +109 -0
  49. package/web/dist/assets/{quadrantDiagram-ABIIQ3AL-Cw6aMTCy.js → quadrantDiagram-ABIIQ3AL-CxzBQxBX.js} +1 -1
  50. package/web/dist/assets/{railroadDiagram-RFXS5EU6-Dju0kwmP.js → railroadDiagram-RFXS5EU6-Coqs5FXi.js} +1 -1
  51. package/web/dist/assets/{requirementDiagram-TGXJPOKE-BbyvxgRb.js → requirementDiagram-TGXJPOKE-v1GaofBK.js} +1 -1
  52. package/web/dist/assets/{sankeyDiagram-HTMAVEWB-Do_VdVhS.js → sankeyDiagram-HTMAVEWB-DGaKjdrZ.js} +1 -1
  53. package/web/dist/assets/{sequenceDiagram-DBY2YBRQ-CKqDjXwf.js → sequenceDiagram-DBY2YBRQ-UD5oqT-Q.js} +1 -1
  54. package/web/dist/assets/{sizeCapture-X5ZJPWSS-sVG1J5D7.js → sizeCapture-X5ZJPWSS-ClCMN9Ry.js} +1 -1
  55. package/web/dist/assets/{stateDiagram-2N3HPSRC-CfjQilyb.js → stateDiagram-2N3HPSRC-CU96VzpK.js} +1 -1
  56. package/web/dist/assets/stateDiagram-v2-6OUMAXLB-TNMXnnTc.js +1 -0
  57. package/web/dist/assets/{swimlanes-5IMT3BWC-Csum4YeF.js → swimlanes-5IMT3BWC-5pw00Cr8.js} +2 -2
  58. package/web/dist/assets/swimlanesDiagram-G3AALYLV-BOvR3DN_.js +8 -0
  59. package/web/dist/assets/{timeline-definition-FHXFAJF6-Cw6UCQjz.js → timeline-definition-FHXFAJF6-Dfd6fPWH.js} +1 -1
  60. package/web/dist/assets/{vennDiagram-L72KCM5P-b_571af9.js → vennDiagram-L72KCM5P-CaJB0ZOh.js} +1 -1
  61. package/web/dist/assets/{wardleyDiagram-EHGQE667-DL_0-lVh.js → wardleyDiagram-EHGQE667-Cau_Q6Bk.js} +1 -1
  62. package/web/dist/assets/{xychartDiagram-FW5EYKEG-BqKYzu8y.js → xychartDiagram-FW5EYKEG-DTUEy024.js} +1 -1
  63. package/web/dist/index.html +3 -3
  64. package/web/dist/assets/channel-DTKy7mHi.js +0 -1
  65. package/web/dist/assets/classDiagram-OUVF2IWQ-MfqAYpCn.js +0 -1
  66. package/web/dist/assets/classDiagram-v2-EOCWNBFH-MfqAYpCn.js +0 -1
  67. package/web/dist/assets/index-CVQyeZNA.js +0 -24
  68. package/web/dist/assets/index-mtWlthKI.css +0 -1
  69. package/web/dist/assets/pilotswarm-BvFGjArK.js +0 -109
  70. package/web/dist/assets/stateDiagram-v2-6OUMAXLB-CYw2jLW6.js +0 -1
  71. package/web/dist/assets/swimlanesDiagram-G3AALYLV-CbG-9P20.js +0 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pilotswarm",
3
- "version": "0.5.77",
3
+ "version": "0.5.78",
4
4
  "description": "PilotSwarm application package: terminal UI, browser portal + Web API server, and MCP server — one install, three bins.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -81,7 +81,7 @@
81
81
  "ink": "^6.8.0",
82
82
  "jose": "^6.2.2",
83
83
  "mermaid": "^11.16.0",
84
- "pilotswarm-sdk": "0.5.77",
84
+ "pilotswarm-sdk": "0.5.78",
85
85
  "react": "^19.2.4",
86
86
  "react-dom": "^19.2.4",
87
87
  "ws": "^8.18.2"
@@ -44,6 +44,9 @@ export async function startEmbeddedWorkers({ count, store }) {
44
44
  useManagedIdentity: ["1", "true", "yes", "on"].includes(
45
45
  (process.env.PILOTSWARM_USE_MANAGED_IDENTITY || "").trim().toLowerCase(),
46
46
  ),
47
+ blobUseManagedIdentity: process.env.PILOTSWARM_BLOB_USE_MANAGED_IDENTITY?.trim()
48
+ ? ["1", "true", "yes", "on"].includes(process.env.PILOTSWARM_BLOB_USE_MANAGED_IDENTITY.trim().toLowerCase())
49
+ : undefined,
47
50
  cmsFactsDatabaseUrl: process.env.PILOTSWARM_CMS_FACTS_DATABASE_URL || undefined,
48
51
  aadDbUser: process.env.PILOTSWARM_DB_AAD_USER || undefined,
49
52
  blobAccountUrl: process.env.AZURE_STORAGE_ACCOUNT_URL || undefined,
@@ -1108,6 +1108,19 @@ function scrollBoundaryIdentity(lines, fromEnd = false) {
1108
1108
  return boundary.map(scrollLineIdentity).join("\u241e");
1109
1109
  }
1110
1110
 
1111
+ // History loading belongs to the outer transcript. Let a tool result, activity
1112
+ // log or agent update consume the gesture first when it still has room.
1113
+ function nestedViewportCanScroll(viewport, target, deltaY) {
1114
+ if (!deltaY) return false;
1115
+ for (let node = target?.nodeType === 1 ? target : target?.parentElement;
1116
+ node && node !== viewport; node = node.parentElement) {
1117
+ const maxScroll = node.scrollHeight - node.clientHeight;
1118
+ if (maxScroll <= 1 || !/^(auto|scroll)$/.test(getComputedStyle(node).overflowY)) continue;
1119
+ if (deltaY < 0 ? node.scrollTop > 1 : node.scrollTop < maxScroll - 1) return true;
1120
+ }
1121
+ return false;
1122
+ }
1123
+
1111
1124
  function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller, {
1112
1125
  stickyBottom = false,
1113
1126
  historyPullEnabled = false,
@@ -1343,6 +1356,7 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1343
1356
  const onWheel = React.useCallback((event) => {
1344
1357
  const node = ref.current;
1345
1358
  if (!node || paneKey !== "chat" || !event.deltaY || event.ctrlKey) return;
1359
+ if (nestedViewportCanScroll(node, event.target, event.deltaY)) return;
1346
1360
  const pending = historyScrollRef.current;
1347
1361
  if (pending && event.deltaY > 0) historyScrollRef.current = null;
1348
1362
  else if (pending) {
@@ -1364,15 +1378,16 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1364
1378
  // scroll events either — so mobile had no way to request older history.
1365
1379
  // A downward pull that starts while the pane is at (or near) the top fires
1366
1380
  // the same top-history intent, once per gesture.
1367
- const touchPullRef = React.useRef({ startY: null, distance: 0 });
1381
+ const touchPullRef = React.useRef({ startY: null, lastY: null, distance: 0 });
1368
1382
  const onTouchStart = React.useCallback((event) => {
1369
1383
  userScrollRef.current.touching = true;
1370
1384
  if (historyScrollRef.current?.applied) historyScrollRef.current = null;
1371
1385
  const node = ref.current;
1372
1386
  touchPullRef.current = {
1373
- startY: historyPullEnabled && loadingHistorySessionId !== historySessionId
1387
+ startY: event.touches?.length === 1 && historyPullEnabled && loadingHistorySessionId !== historySessionId
1374
1388
  && paneKey === "chat" && node?.scrollTop <= PROGRAMMATIC_SCROLL_TOLERANCE_PX
1375
1389
  ? event.touches?.[0]?.clientY ?? null : null,
1390
+ lastY: event.touches?.[0]?.clientY ?? null,
1376
1391
  distance: 0,
1377
1392
  };
1378
1393
  }, [historyPullEnabled, historySessionId, loadingHistorySessionId, paneKey, ref]);
@@ -1385,20 +1400,30 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1385
1400
  historyScrollRef.current.releaseAt = performance.now() + HISTORY_SCROLL_GESTURE_GAP_MS;
1386
1401
  }
1387
1402
  const distance = touchPullRef.current.distance;
1388
- touchPullRef.current = { startY: null, distance: 0 };
1403
+ touchPullRef.current = { startY: null, lastY: null, distance: 0 };
1389
1404
  setTopPullDistance(0);
1390
1405
  if (distance >= TOUCH_TOP_PULL_THRESHOLD_PX
1391
1406
  && ref.current?.scrollTop <= PROGRAMMATIC_SCROLL_TOLERANCE_PX) requestHistoryPage();
1392
1407
  }, [ref, requestHistoryPage]);
1393
1408
  const onTouchCancel = React.useCallback(() => {
1394
1409
  userScrollRef.current.touching = false;
1395
- touchPullRef.current = { startY: null, distance: 0 };
1410
+ touchPullRef.current = { startY: null, lastY: null, distance: 0 };
1396
1411
  setTopPullDistance(0);
1397
1412
  }, []);
1398
1413
  const onTouchMove = React.useCallback((event) => {
1399
1414
  const node = ref.current;
1400
1415
  const pull = touchPullRef.current;
1401
1416
  if (!node || paneKey !== "chat" || event.touches?.length !== 1) return;
1417
+ const y = event.touches[0].clientY;
1418
+ const deltaY = pull.lastY == null ? 0 : pull.lastY - y;
1419
+ pull.lastY = y;
1420
+ if (nestedViewportCanScroll(node, event.target, deltaY)) {
1421
+ // Movement within a box must not accumulate into a history pull.
1422
+ if (pull.startY != null) pull.startY = y;
1423
+ pull.distance = 0;
1424
+ setTopPullDistance(0);
1425
+ return;
1426
+ }
1402
1427
  if (historyScrollRef.current) {
1403
1428
  historyScrollRef.current.releaseAt = performance.now() + HISTORY_SCROLL_GESTURE_GAP_MS;
1404
1429
  event.preventDefault();
@@ -1406,8 +1431,6 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1406
1431
  }
1407
1432
  if (pull.startY == null) return;
1408
1433
  if (node.scrollTop > PROGRAMMATIC_SCROLL_TOLERANCE_PX) return;
1409
- const y = event.touches?.[0]?.clientY;
1410
- if (y == null) return;
1411
1434
  pull.distance = Math.min(TOUCH_TOP_PULL_MAX_PX, Math.max(0, y - pull.startY));
1412
1435
  setTopPullDistance(pull.distance);
1413
1436
  if (pull.distance > 0) event.preventDefault();
@@ -1552,15 +1575,11 @@ function ChatActivityRun({ calls }) {
1552
1575
  followRef.current = getScrollDistanceToBottom(event.currentTarget) <= 24;
1553
1576
  },
1554
1577
  onWheel: (event) => {
1555
- event.stopPropagation();
1556
1578
  if (event.deltaY < 0) followRef.current = false;
1557
1579
  },
1558
- onTouchStart: (event) => {
1559
- event.stopPropagation();
1580
+ onTouchStart: () => {
1560
1581
  followRef.current = false;
1561
1582
  },
1562
- onTouchMove: (event) => event.stopPropagation(),
1563
- onTouchEnd: (event) => event.stopPropagation(),
1564
1583
  }, calls.map((call) => React.createElement(ChatCallLine, { key: call.callKey, line: call }))),
1565
1584
  React.createElement("div", { className: "ps-activity-run-footer" },
1566
1585
  `Showing ${calls.length} ${calls.length === 1 ? "entry" : "entries"} · Scroll for earlier activity`));
@@ -3885,15 +3904,12 @@ const AssistantPreviewCard = React.memo(function AssistantPreviewCard({ line, th
3885
3904
  },
3886
3905
  onWheel: (event) => {
3887
3906
  if (!line.final) {
3888
- event.stopPropagation();
3889
3907
  if (event.deltaY < 0) followRef.current = false;
3890
3908
  }
3891
3909
  },
3892
- onTouchStart: (event) => {
3893
- if (!line.final) { event.stopPropagation(); followRef.current = false; }
3910
+ onTouchStart: () => {
3911
+ if (!line.final) followRef.current = false;
3894
3912
  },
3895
- onTouchMove: (event) => { if (!line.final) event.stopPropagation(); },
3896
- onTouchEnd: (event) => { if (!line.final) event.stopPropagation(); },
3897
3913
  onKeyDown: (event) => {
3898
3914
  if (!line.final && ["ArrowUp", "ArrowDown", "PageUp", "PageDown", "Home", "End", " "].includes(event.key)) {
3899
3915
  event.stopPropagation();
@@ -9318,13 +9334,21 @@ function PromptComposer({ controller, mobile, compact = false, active = true, on
9318
9334
  // A pane-splitter drag or a font-size change re-wraps the text with
9319
9335
  // no window resize; watch the box itself.
9320
9336
  const node = inputRef.current;
9337
+ let frame = 0;
9321
9338
  const observer = node && typeof ResizeObserver !== "undefined"
9322
- ? new ResizeObserver(() => growInput(true))
9339
+ ? new ResizeObserver(() => {
9340
+ // growInput writes the same box's height. Defer those writes
9341
+ // out of ResizeObserver delivery to prevent WebKit's resize
9342
+ // loop error when a narrow pane wraps the placeholder.
9343
+ cancelAnimationFrame(frame);
9344
+ frame = requestAnimationFrame(() => growInput(true));
9345
+ })
9323
9346
  : null;
9324
9347
  if (observer && node) observer.observe(node);
9325
9348
  return () => {
9326
9349
  window.removeEventListener("resize", onResize);
9327
9350
  observer?.disconnect();
9351
+ cancelAnimationFrame(frame);
9328
9352
  };
9329
9353
  }, [growInput]);
9330
9354
 
@@ -9787,7 +9811,7 @@ function IconButton({ icon, label, onClick, disabled = false, active = false, pr
9787
9811
  tooltipNode);
9788
9812
  }
9789
9813
 
9790
- function Toolbar({ controller, mobile, moa = null, canvasPaneOpen = false, onToggleCanvasPane = null, mobilePane = "workspace", onSelectMobilePane = null, mobileMainLayout = "split" }) {
9814
+ function Toolbar({ controller, mobile, moa = null, viewNavigation = null, canvasPaneOpen = false, onToggleCanvasPane = null, mobilePane = "workspace", onSelectMobilePane = null, mobileMainLayout = "split" }) {
9791
9815
  const [headerSlot, setHeaderSlot] = React.useState(null);
9792
9816
  React.useEffect(() => {
9793
9817
  if (typeof document === "undefined") return;
@@ -9941,6 +9965,15 @@ function Toolbar({ controller, mobile, moa = null, canvasPaneOpen = false, onTog
9941
9965
  },
9942
9966
  });
9943
9967
 
9968
+ if (!mobile && moa?.desktop !== false && viewNavigation) for (const direction of ["back", "forward"]) buttonDefs.push({
9969
+ key: direction,
9970
+ icon: React.createElement("svg", { viewBox: "0 0 20 20", width: 16, height: 16, fill: "none", stroke: "currentColor", strokeWidth: 1.7, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true },
9971
+ React.createElement("path", { d: direction === "back" ? "M16 10H4m5-5-5 5 5 5" : "M4 10h12m-5-5 5 5-5 5" })),
9972
+ label: viewNavigation[`${direction}Label`],
9973
+ disabled: !viewNavigation[direction === "back" ? "canBack" : "canForward"],
9974
+ onClick: viewNavigation[direction],
9975
+ });
9976
+
9944
9977
  const renderButton = (def) => {
9945
9978
  const button = React.createElement(IconButton, {
9946
9979
  key: def.badge ? undefined : def.key,
@@ -10009,18 +10042,11 @@ function Toolbar({ controller, mobile, moa = null, canvasPaneOpen = false, onTog
10009
10042
  );
10010
10043
  }
10011
10044
 
10012
- // Two kinds of button, two clusters (desktop only):
10013
- //
10014
- // left : the workspace's — new, filter, canvas, diagnostics
10015
- // right : modes [workspace, budget, admin] │ theme · sign-out
10016
- //
10017
- // The whole left cluster belongs to the workspace — new session, filter,
10018
- // canvas and diagnostics all act on it — so it exists only in Workspace
10019
- // mode. Budget and the Admin Console replace the workspace; nothing on
10020
- // the left applies there. Modes are exclusive (the controller closes one
10021
- // when the other opens) and the Workspace button is the way back.
10045
+ // Keep navigation in one permanent slot in every desktop mode. Context
10046
+ // controls occupy equal-width flanks; empty flanks still reserve space.
10022
10047
  const mode = moa?.active ? "moa" : adminVisible ? "admin" : (budgetOpen ? "budget" : "workspace");
10023
10048
  const ACTIONS = ["new", "filter"];
10049
+ const HISTORY = ["back", "forward"];
10024
10050
  const PANELS = ["canvas", "diagnostics"];
10025
10051
  const MODES = ["workspace", "moa", "budget", "admin"];
10026
10052
 
@@ -10030,7 +10056,7 @@ function Toolbar({ controller, mobile, moa = null, canvasPaneOpen = false, onTog
10030
10056
  // it — is the confusing half of every full-screen mode. The Canvas toggle
10031
10057
  // is exempt: it already means "put the canvas away", and closing drops
10032
10058
  // the flag in the reducer.
10033
- const withRestore = (def) => ((!canvasMaximized || def.key === "canvas") && !(moa?.active && ["workspace", "budget", "admin"].includes(def.key)) ? def : {
10059
+ const withRestore = (def) => (HISTORY.includes(def.key) || (!canvasMaximized || def.key === "canvas") && !(moa?.active && ["workspace", "budget", "admin"].includes(def.key)) ? def : {
10034
10060
  ...def,
10035
10061
  onClick: (...args) => {
10036
10062
  controller.dispatch({ type: "ui/canvasMaximized", on: false });
@@ -10045,10 +10071,6 @@ function Toolbar({ controller, mobile, moa = null, canvasPaneOpen = false, onTog
10045
10071
  .map(renderButton);
10046
10072
  const divider = (key) => React.createElement("span", { key, className: "ps-toolbar-divider", "aria-hidden": "true" });
10047
10073
 
10048
- // One run, no bar: all four act on the workspace.
10049
- const leftCluster = mode === "workspace"
10050
- ? [...pick(ACTIONS), ...pick(PANELS)]
10051
- : [];
10052
10074
  const rightCluster = [
10053
10075
  ...pick(MODES),
10054
10076
  divider("mode-divider"),
@@ -10056,28 +10078,21 @@ function Toolbar({ controller, mobile, moa = null, canvasPaneOpen = false, onTog
10056
10078
  ];
10057
10079
 
10058
10080
  const toolbar = React.createElement("div", { className: `ps-toolbar${moa?.active ? " is-moa" : ""}` },
10059
- // Three columns: left rail | main controls | right rail. Full-screen
10060
- // canvas uses the otherwise-empty left rail for the normal actions so
10061
- // they do not crowd the canvas metadata and controls across the top.
10062
10081
  React.createElement("div", { className: "ps-toolbar-side is-left" },
10063
- moa?.active ? React.createElement("div", { id: "ps-moa-status-slot" }) : canvasMaximized ? leftCluster : null),
10064
- React.createElement("div", { className: "ps-toolbar-actions" },
10065
- moa?.active ? React.createElement("div", { id: "ps-moa-header-slot" }) : canvasMaximized ? null : leftCluster),
10082
+ moa?.active ? React.createElement("div", { id: "ps-moa-status-slot" }) : null,
10083
+ // Canvas controls retain their state in CanvasPane. Their portal
10084
+ // gets the flexible rail, so names/revisions cannot move history.
10085
+ canvasMaximized && !moa?.active
10086
+ ? React.createElement("span", { className: "ps-toolbar-canvas-slot", id: "ps-toolbar-canvas-slot" })
10087
+ : null),
10088
+ React.createElement("div", { className: "ps-toolbar-actions ps-toolbar-navigation", role: "navigation", "aria-label": moa?.active ? "Master of Agents" : "View navigation" },
10089
+ React.createElement("div", { className: "ps-toolbar-context is-before", id: "ps-toolbar-before-history" },
10090
+ mode === "workspace" ? pick(ACTIONS) : null),
10091
+ React.createElement("div", { className: "ps-toolbar-history" }, pick(HISTORY)),
10092
+ React.createElement("div", { className: "ps-toolbar-context is-after", id: "ps-toolbar-after-history" },
10093
+ mode === "workspace" ? pick(PANELS) : null)),
10066
10094
  React.createElement("div", { className: "ps-toolbar-side is-right" },
10067
- // The portal header parks its version/status meta here, LEFT of
10068
- // the tool buttons, and its sign-out glyph in the slot after
10069
- // them — one right-aligned cluster: meta · mode · theme · out.
10070
10095
  React.createElement("span", { className: "ps-toolbar-meta-slot", id: "ps-toolbar-meta-slot" }),
10071
- // While the canvas is full screen its header controls (rev, zoom,
10072
- // zen, restore) portal INTO this slot from CanvasPane — zoom state
10073
- // lives there, so the controls come to the toolbar rather than
10074
- // their state moving out.
10075
- canvasMaximized
10076
- ? React.createElement("span", { className: "ps-toolbar-canvas-slot", id: "ps-toolbar-canvas-slot" })
10077
- : null,
10078
- canvasMaximized
10079
- ? React.createElement("span", { className: "ps-toolbar-divider", "aria-hidden": "true" })
10080
- : null,
10081
10096
  React.createElement("div", { className: "ps-toolbar-actions is-tools" }, rightCluster),
10082
10097
  React.createElement("span", { className: "ps-toolbar-signout-slot", id: "ps-toolbar-signout-slot" })),
10083
10098
  );
@@ -14842,7 +14857,7 @@ export function createWebPilotSwarmController({ transport, mode = "remote", bran
14842
14857
  return new PilotSwarmUiController({ store, transport });
14843
14858
  }
14844
14859
 
14845
- export function PilotSwarmWebApp({ controller, suspended = false, moa = null }) {
14860
+ export function PilotSwarmWebApp({ controller, suspended = false, moa = null, viewNavigation = null }) {
14846
14861
  const viewportRef = React.useRef(null);
14847
14862
  const mainGridRef = React.useRef(null);
14848
14863
  const viewport = useMeasuredViewport(viewportRef, suspended);
@@ -14978,7 +14993,9 @@ export function PilotSwarmWebApp({ controller, suspended = false, moa = null })
14978
14993
  const appliedProfileSettingsJsonRef = React.useRef(null);
14979
14994
  const defaultProfileSettingsRef = React.useRef(null);
14980
14995
  const [mobilePane, setMobilePane] = React.useState("workspace");
14981
- const mobile = (viewport.width || window.innerWidth || 0) < MOBILE_BREAKPOINT;
14996
+ // Match the CSS and MoA breakpoint. The padded shell is narrower than
14997
+ // the browser and otherwise flips to mobile while the header is desktop.
14998
+ const mobile = useMediaQuery(`(max-width: ${MOBILE_BREAKPOINT}px)`);
14982
14999
  const readOnlyChatPane = state.activeSessionIsGroup;
14983
15000
  const effectivePromptRows = readOnlyChatPane ? 0 : state.promptRows;
14984
15001
 
@@ -15606,7 +15623,7 @@ export function PilotSwarmWebApp({ controller, suspended = false, moa = null })
15606
15623
  : null;
15607
15624
 
15608
15625
  if (suspended) return React.createElement(ControllerContext.Provider, { value: controller },
15609
- React.createElement(Toolbar, { controller, mobile: false, moa }),
15626
+ React.createElement(Toolbar, { controller, mobile: false, moa, viewNavigation }),
15610
15627
  React.createElement(ModalLayer, { controller }));
15611
15628
  return React.createElement(ControllerContext.Provider, { value: controller },
15612
15629
  React.createElement("div", { ref: viewportRef, className: "ps-web-shell" },
@@ -15614,7 +15631,7 @@ export function PilotSwarmWebApp({ controller, suspended = false, moa = null })
15614
15631
  // plus the Main layout cycle), so it renders on every pane — hiding it
15615
15632
  // anywhere would trap the user with no way back.
15616
15633
  React.createElement(Toolbar, {
15617
- controller, moa,
15634
+ controller, moa, viewNavigation,
15618
15635
  mobile,
15619
15636
  canvasPaneOpen: mobileCanvasOpen,
15620
15637
  onToggleCanvasPane: toggleMobileCanvas,
@@ -1 +1 @@
1
- import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-Dn-J2ayj.js";import{p as f}from"./chunk-JWPE2WC7-Dlgqhr3G.js";import{_ as n,l as o}from"./mermaid.core-1gBc6FeB.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-MSAXYGkZ.js";import"./pilotswarm-BvFGjArK.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-DuIGV22R.js";import{p as f}from"./chunk-JWPE2WC7-Ddh7J2Rp.js";import{_ as n,l as o}from"./mermaid.core-DWYsDHXh.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-Deleul8f.js";import"./pilotswarm-3GsGwA3r.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-1gBc6FeB.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-DWYsDHXh.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};