pilotswarm 0.5.38 → 0.5.39

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 (77) hide show
  1. package/mcp/dist/src/tools/agent-packages.d.ts.map +1 -1
  2. package/mcp/dist/src/tools/agent-packages.js +34 -14
  3. package/mcp/dist/src/tools/agent-packages.js.map +1 -1
  4. package/package.json +2 -2
  5. package/tui/src/node-sdk-transport.js +113 -18
  6. package/ui/core/src/controller.js +99 -29
  7. package/ui/core/src/layout.js +10 -0
  8. package/ui/core/src/reducer.js +52 -5
  9. package/ui/core/src/selectors.js +49 -7
  10. package/ui/react/src/web-app.js +76 -19
  11. package/web/dist/assets/{abnfDiagram-VRR7QNED-DrJhXhSQ.js → abnfDiagram-VRR7QNED-Hsly1fgf.js} +1 -1
  12. package/web/dist/assets/{arc-BEaG9DWd.js → arc-DiQLL9vM.js} +1 -1
  13. package/web/dist/assets/{architectureDiagram-ZJ3FMSHR-D9fc1Imx.js → architectureDiagram-ZJ3FMSHR-B8ry8WNZ.js} +1 -1
  14. package/web/dist/assets/{blockDiagram-677ZJIJ3-rS5Eikvt.js → blockDiagram-677ZJIJ3-Z4PcukIo.js} +1 -1
  15. package/web/dist/assets/{c4Diagram-LMCZKHZV-HKLlX5cR.js → c4Diagram-LMCZKHZV-Cahkc0gc.js} +1 -1
  16. package/web/dist/assets/channel-BHLBPE50.js +1 -0
  17. package/web/dist/assets/{chunk-2Q5K7J3B-kq0TyLSB.js → chunk-2Q5K7J3B-CtZuWH4J.js} +1 -1
  18. package/web/dist/assets/{chunk-32BRIVSS-O-LMarT5.js → chunk-32BRIVSS-C0M390-k.js} +1 -1
  19. package/web/dist/assets/{chunk-5VM5RSS4-Di4h0CAu.js → chunk-5VM5RSS4-ClvX9u5j.js} +1 -1
  20. package/web/dist/assets/{chunk-EX3LRPZG-C8rgqUOt.js → chunk-EX3LRPZG-BVAet5KG.js} +1 -1
  21. package/web/dist/assets/{chunk-JWPE2WC7-BSH41q4T.js → chunk-JWPE2WC7-BccmZmrr.js} +1 -1
  22. package/web/dist/assets/{chunk-MOJQB5TN-BAFuQHAC.js → chunk-MOJQB5TN-BN5MKe94.js} +1 -1
  23. package/web/dist/assets/{chunk-RYQCIY6F-DAg6JOs7.js → chunk-RYQCIY6F-DfWw-ACP.js} +1 -1
  24. package/web/dist/assets/{chunk-V7JOEXUC-DbVrT8BG.js → chunk-V7JOEXUC-BgUEoLnN.js} +1 -1
  25. package/web/dist/assets/{chunk-VR4S4FIN-C6f5_Grp.js → chunk-VR4S4FIN-k1eKfFNA.js} +1 -1
  26. package/web/dist/assets/{chunk-XXDRQBXY-CqcCYpqA.js → chunk-XXDRQBXY-DPyV10yR.js} +1 -1
  27. package/web/dist/assets/classDiagram-OUVF2IWQ-rj9D2TSL.js +1 -0
  28. package/web/dist/assets/classDiagram-v2-EOCWNBFH-rj9D2TSL.js +1 -0
  29. package/web/dist/assets/{cose-bilkent-JH36ORCC-DJw04eFh.js → cose-bilkent-JH36ORCC-Bt_rpukK.js} +1 -1
  30. package/web/dist/assets/{cynefin-VYW2F7L2-CpjwdEIU.js → cynefin-VYW2F7L2-Z8eMzFMv.js} +1 -1
  31. package/web/dist/assets/{cynefinDiagram-TSTJHNR4-RqEIWoT0.js → cynefinDiagram-TSTJHNR4-BJSNawFi.js} +1 -1
  32. package/web/dist/assets/{dagre-VKFMJZFB-C1eGQNK2.js → dagre-VKFMJZFB-D6dNl8jc.js} +1 -1
  33. package/web/dist/assets/{diagram-FQU43EPY-BODLQ7dz.js → diagram-FQU43EPY-Cy1nbGsU.js} +1 -1
  34. package/web/dist/assets/{diagram-G47NLZAW-DlhmukMC.js → diagram-G47NLZAW-CmrbuA_d.js} +1 -1
  35. package/web/dist/assets/{diagram-NH7WQ7WH-Ba_jZoCN.js → diagram-NH7WQ7WH-PoLNQE2j.js} +1 -1
  36. package/web/dist/assets/{diagram-OA4YK3LP-DnSiAJBG.js → diagram-OA4YK3LP-BZwNFcSV.js} +1 -1
  37. package/web/dist/assets/{diagram-WEI45ONY-B3KoQ7_W.js → diagram-WEI45ONY-pKw0b_fN.js} +1 -1
  38. package/web/dist/assets/{ebnfDiagram-CCIWWBDH-ChnFc5gf.js → ebnfDiagram-CCIWWBDH-UNctuQCV.js} +1 -1
  39. package/web/dist/assets/{erDiagram-Q63AITRT-D2KkJXLZ.js → erDiagram-Q63AITRT-DxIETMif.js} +1 -1
  40. package/web/dist/assets/{flowDiagram-23GEKE2U-CmybZufj.js → flowDiagram-23GEKE2U-C06IdNKV.js} +1 -1
  41. package/web/dist/assets/{ganttDiagram-NO4QXBWP-BzPurW_v.js → ganttDiagram-NO4QXBWP-fU7aGyP1.js} +1 -1
  42. package/web/dist/assets/{gitGraphDiagram-IHSO6WYX-DAbXl4gO.js → gitGraphDiagram-IHSO6WYX-9UKkPJm6.js} +1 -1
  43. package/web/dist/assets/index-B8nGlHwb.js +24 -0
  44. package/web/dist/assets/{infoDiagram-FWYZ7A6U-C6qGjNA1.js → infoDiagram-FWYZ7A6U-C6F06SQJ.js} +1 -1
  45. package/web/dist/assets/{ishikawaDiagram-FXEZZL3T-D2d1tO-9.js → ishikawaDiagram-FXEZZL3T-CB-O9NfO.js} +1 -1
  46. package/web/dist/assets/{journeyDiagram-5HDEW3XC-fP13w1b7.js → journeyDiagram-5HDEW3XC-B-8MOf-H.js} +1 -1
  47. package/web/dist/assets/{kanban-definition-HUTT4EX6-BJfWAXZ0.js → kanban-definition-HUTT4EX6-DX0XA3hI.js} +1 -1
  48. package/web/dist/assets/{linear-CltApkHf.js → linear-D60PrjTW.js} +1 -1
  49. package/web/dist/assets/{mermaid.core-B1Dwetk3.js → mermaid.core-bonzwapf.js} +4 -4
  50. package/web/dist/assets/{mindmap-definition-LN4V7U3C-CdRUD7LF.js → mindmap-definition-LN4V7U3C-Y-6Dum33.js} +1 -1
  51. package/web/dist/assets/{papaparse.min-C1y3wBH1.js → papaparse.min-Cas1JfRG.js} +1 -1
  52. package/web/dist/assets/{pegDiagram-2B236MQR-CeQkqN6Q.js → pegDiagram-2B236MQR-_paO0yDw.js} +1 -1
  53. package/web/dist/assets/{pieDiagram-ENE6RG2P-Dqgc87jA.js → pieDiagram-ENE6RG2P-xT1_Gpn4.js} +1 -1
  54. package/web/dist/assets/pilotswarm-BT6tOknQ.js +96 -0
  55. package/web/dist/assets/{quadrantDiagram-ABIIQ3AL-CD7f-w6m.js → quadrantDiagram-ABIIQ3AL-1usdLFOF.js} +1 -1
  56. package/web/dist/assets/{railroadDiagram-RFXS5EU6-CcsAijSC.js → railroadDiagram-RFXS5EU6-R3lwHOz9.js} +1 -1
  57. package/web/dist/assets/{requirementDiagram-TGXJPOKE-BkzF80pL.js → requirementDiagram-TGXJPOKE-BL8J1__Z.js} +1 -1
  58. package/web/dist/assets/{sankeyDiagram-HTMAVEWB-D9XOFw7Y.js → sankeyDiagram-HTMAVEWB-Dz6--0pl.js} +1 -1
  59. package/web/dist/assets/{sequenceDiagram-DBY2YBRQ-BFfaS_Sz.js → sequenceDiagram-DBY2YBRQ-CG2Xpkct.js} +1 -1
  60. package/web/dist/assets/{sizeCapture-X5ZJPWSS-CDJV16tP.js → sizeCapture-X5ZJPWSS-BPbYfjxj.js} +1 -1
  61. package/web/dist/assets/{stateDiagram-2N3HPSRC-C0E-MPXO.js → stateDiagram-2N3HPSRC-46x_y_aA.js} +1 -1
  62. package/web/dist/assets/stateDiagram-v2-6OUMAXLB-C2tnolSo.js +1 -0
  63. package/web/dist/assets/{swimlanes-5IMT3BWC-n5Vsv7n9.js → swimlanes-5IMT3BWC-SXdMo4zJ.js} +2 -2
  64. package/web/dist/assets/swimlanesDiagram-G3AALYLV-Dh6Sn__t.js +8 -0
  65. package/web/dist/assets/{timeline-definition-FHXFAJF6-DW2gV8-n.js → timeline-definition-FHXFAJF6-CGgT-b38.js} +1 -1
  66. package/web/dist/assets/{vennDiagram-L72KCM5P-D9dbDm08.js → vennDiagram-L72KCM5P-BGS3xBa_.js} +1 -1
  67. package/web/dist/assets/{wardleyDiagram-EHGQE667-CIcG7fiC.js → wardleyDiagram-EHGQE667-m2U3wEZJ.js} +1 -1
  68. package/web/dist/assets/{xychartDiagram-FW5EYKEG-elEIFsc9.js → xychartDiagram-FW5EYKEG-DI6tQysg.js} +1 -1
  69. package/web/dist/index.html +2 -2
  70. package/web/runtime.js +30 -7
  71. package/web/dist/assets/channel-DRy7FvyF.js +0 -1
  72. package/web/dist/assets/classDiagram-OUVF2IWQ-C35RhB8X.js +0 -1
  73. package/web/dist/assets/classDiagram-v2-EOCWNBFH-C35RhB8X.js +0 -1
  74. package/web/dist/assets/index-CRY94nFp.js +0 -24
  75. package/web/dist/assets/pilotswarm-DayYdi39.js +0 -96
  76. package/web/dist/assets/stateDiagram-v2-6OUMAXLB-BMqXeMJu.js +0 -1
  77. package/web/dist/assets/swimlanesDiagram-G3AALYLV-CGl4gRnH.js +0 -8
@@ -19,6 +19,20 @@ import {
19
19
  createInitialState,
20
20
  } from "./state.js";
21
21
 
22
+ /**
23
+ * Is this package detail/tree/changelog response for a selection the user has
24
+ * already left? Responses carry the selectionSeq captured when their fetch
25
+ * started; the NAME alone cannot tell two copies of a shadowed name apart
26
+ * (scope shadowing: one name, two packages), so a name-only guard let a slow
27
+ * response for one copy land on top of the other. Name-only actions (older
28
+ * hosts) keep the historical name compare.
29
+ */
30
+ function packageResponseIsStale(packages, action) {
31
+ if (packages.selectedName !== action.name) return true;
32
+ if (typeof action.seq === "number") return (packages.selectionSeq ?? 0) !== action.seq;
33
+ return false;
34
+ }
35
+
22
36
  function cloneHistoryMap(historyMap) {
23
37
  return new Map(historyMap);
24
38
  }
@@ -619,6 +633,7 @@ function applyVisibleSessionSelection(state, nextSessions) {
619
633
  sessions = {
620
634
  ...sessions,
621
635
  activeSessionId: intentTargetId,
636
+ listDeselected: false,
622
637
  navigationIntent: intent.status === "resolved"
623
638
  ? intent
624
639
  : { sessionId: intent.sessionId, status: "resolved" },
@@ -1026,6 +1041,15 @@ export function appReducer(state, action) {
1026
1041
  ui: {
1027
1042
  ...state.ui,
1028
1043
  focusRegion: action.focusRegion,
1044
+ // The RAW region the caller asked for, before layout
1045
+ // normalization. A workspace region (sessions/chat) with no
1046
+ // slot in the current layout normalizes to the first
1047
+ // focusable pane — inspector, on a phone — so the normalized
1048
+ // value alone cannot tell "focus the inspector" from
1049
+ // "sessions got rewritten to inspector". The mobile
1050
+ // follow-focus pane switch reads this to avoid opening
1051
+ // diagnostics when the user only asked for the workspace.
1052
+ requestedFocusRegion: action.requestedFocusRegion ?? action.focusRegion,
1029
1053
  },
1030
1054
  };
1031
1055
 
@@ -1087,6 +1111,10 @@ export function appReducer(state, action) {
1087
1111
  if (!sessionId) return state;
1088
1112
  const nextSessions = {
1089
1113
  ...state.sessions,
1114
+ // A deep link is explicit navigation. Keep the list highlight
1115
+ // aligned with the linked chat even if empty-space click had
1116
+ // previously deselected the session row.
1117
+ listDeselected: false,
1090
1118
  navigationIntent: { sessionId, status: "pending" },
1091
1119
  filterExceptionId: null,
1092
1120
  };
@@ -2319,6 +2347,7 @@ export function appReducer(state, action) {
2319
2347
  workerState: Array.isArray(action.workerState) ? action.workerState : [],
2320
2348
  fetchedAt: Date.now(),
2321
2349
  selectedName: stillThere ? previous.selectedName : null,
2350
+ selectedSelector: stillThere ? (previous.selectedSelector ?? null) : null,
2322
2351
  ...(stillThere ? {} : { detail: null, workspace: { ...previous.workspace, tree: null, selectedPath: null, file: null } }),
2323
2352
  },
2324
2353
  },
@@ -2336,6 +2365,18 @@ export function appReducer(state, action) {
2336
2365
  packages: {
2337
2366
  ...state.admin.packages,
2338
2367
  selectedName: action.name || null,
2368
+ // WHICH copy of the name: {scope, owner} from the row
2369
+ // the user clicked. One name can be two packages
2370
+ // (scope shadowing) — without this every read and
2371
+ // action fell back to "own copy first" and could
2372
+ // target the row the user was NOT looking at.
2373
+ selectedSelector: action.selector || null,
2374
+ // Monotonic selection token. The stale-response guards
2375
+ // below compare it, because comparing the NAME alone
2376
+ // cannot tell two copies of a shadowed name apart — a
2377
+ // slow response for the user copy could land on top of
2378
+ // the shared copy the user just clicked.
2379
+ selectionSeq: (state.admin.packages.selectionSeq ?? 0) + 1,
2339
2380
  detail: null,
2340
2381
  detailLoading: Boolean(action.name),
2341
2382
  detailError: null,
@@ -2354,17 +2395,17 @@ export function appReducer(state, action) {
2354
2395
  };
2355
2396
  }
2356
2397
  case "admin/packages/detail/loaded": {
2357
- if (state.admin.packages.selectedName !== action.name) return state;
2398
+ if (packageResponseIsStale(state.admin.packages, action)) return state;
2358
2399
  return { ...state, admin: { ...state.admin, packages: { ...state.admin.packages, detail: action.detail, detailLoading: false, detailError: null } } };
2359
2400
  }
2360
2401
  case "admin/packages/detail/loadFailed": {
2361
- if (state.admin.packages.selectedName !== action.name) return state;
2402
+ if (packageResponseIsStale(state.admin.packages, action)) return state;
2362
2403
  return { ...state, admin: { ...state.admin, packages: { ...state.admin.packages, detail: null, detailLoading: false, detailError: action.error || "Failed to load package" } } };
2363
2404
  }
2364
2405
  case "admin/packages/changelog/loaded": {
2365
2406
  // Stale-response guard, same as the tree: a slow changelog for a
2366
2407
  // previously-selected package must not surface under the current one.
2367
- if (state.admin.packages.selectedName !== action.name) return state;
2408
+ if (packageResponseIsStale(state.admin.packages, action)) return state;
2368
2409
  return {
2369
2410
  ...state,
2370
2411
  admin: {
@@ -2377,7 +2418,7 @@ export function appReducer(state, action) {
2377
2418
  };
2378
2419
  }
2379
2420
  case "admin/packages/tree/loaded": {
2380
- if (state.admin.packages.selectedName !== action.name) return state;
2421
+ if (packageResponseIsStale(state.admin.packages, action)) return state;
2381
2422
  const topDirs = Array.isArray(action.tree?.dirs)
2382
2423
  ? action.tree.dirs.filter((dir) => !dir.includes("/"))
2383
2424
  : [];
@@ -2400,7 +2441,7 @@ export function appReducer(state, action) {
2400
2441
  };
2401
2442
  }
2402
2443
  case "admin/packages/tree/loadFailed": {
2403
- if (state.admin.packages.selectedName !== action.name) return state;
2444
+ if (packageResponseIsStale(state.admin.packages, action)) return state;
2404
2445
  return { ...state, admin: { ...state.admin, packages: { ...state.admin.packages, workspace: { ...state.admin.packages.workspace, treeLoading: false, treeError: action.error || "Failed to load package files" } } } };
2405
2446
  }
2406
2447
  case "admin/packages/toggleDir": {
@@ -2414,11 +2455,17 @@ export function appReducer(state, action) {
2414
2455
  return { ...state, admin: { ...state.admin, packages: { ...state.admin.packages, workspace: { ...state.admin.packages.workspace, selectedPath: action.path, file: null, fileLoading: true, fileError: null } } } };
2415
2456
  }
2416
2457
  case "admin/packages/file/loaded": {
2458
+ // Path AND selection token: two copies of a shadowed name have the
2459
+ // SAME file paths (both ship plugin.json), so a slow preview for
2460
+ // the previously-selected copy would otherwise land under the
2461
+ // current one. The seq check tells the two copies apart.
2417
2462
  if (state.admin.packages.workspace.selectedPath !== action.file?.path) return state;
2463
+ if (typeof action.seq === "number" && (state.admin.packages.selectionSeq ?? 0) !== action.seq) return state;
2418
2464
  return { ...state, admin: { ...state.admin, packages: { ...state.admin.packages, workspace: { ...state.admin.packages.workspace, file: action.file, fileLoading: false, fileError: null } } } };
2419
2465
  }
2420
2466
  case "admin/packages/file/loadFailed": {
2421
2467
  if (state.admin.packages.workspace.selectedPath !== action.path) return state;
2468
+ if (typeof action.seq === "number" && (state.admin.packages.selectionSeq ?? 0) !== action.seq) return state;
2422
2469
  return { ...state, admin: { ...state.admin, packages: { ...state.admin.packages, workspace: { ...state.admin.packages.workspace, fileLoading: false, fileError: action.error || "Failed to load file" } } } };
2423
2470
  }
2424
2471
  case "admin/packages/action/pending": {
@@ -3724,9 +3724,29 @@ export function selectAdminConsole(state) {
3724
3724
  distinctPackageOwners.add(key);
3725
3725
  }
3726
3726
  const decoratePackageOwners = distinctPackageOwners.size > 1;
3727
+ // Copy-identity helpers: one NAME can be two packages (scope shadowing),
3728
+ // so row selection and highlighting key on (name, scope, owner) — never
3729
+ // the bare name.
3730
+ const packageCopyKey = (name, scope, owner) =>
3731
+ `${name}\u0001${scope === "shared" ? "shared" : "user"}\u0001${scope === "shared" ? "" : (owner?.subject ?? "")}`;
3732
+ const selectedCopyKey = pkgState.selectedName
3733
+ ? packageCopyKey(
3734
+ pkgState.selectedName,
3735
+ pkgState.selectedSelector?.scope ?? null,
3736
+ pkgState.selectedSelector?.owner ?? principal ?? null,
3737
+ )
3738
+ : null;
3739
+ const rowMatchesSelection = (pkg) => {
3740
+ if (admin.section !== "packages" || pkgState.selectedName !== pkg.name) return false;
3741
+ // Legacy selection with no selector: fall back to name-only so an
3742
+ // in-flight selection from an older host still highlights something.
3743
+ if (!pkgState.selectedSelector?.scope) return true;
3744
+ return packageCopyKey(pkg.name, pkg.scope, pkg.owner) === selectedCopyKey;
3745
+ };
3727
3746
  const packageRow = (pkg) => ({
3728
3747
  name: pkg.name,
3729
3748
  scope: pkg.scope === "shared" ? "shared" : "user",
3749
+ owner: pkg.owner ?? null,
3730
3750
  enabled: Boolean(pkg.enabled),
3731
3751
  semver: pkg.active?.semver || null,
3732
3752
  sha7: pkg.active?.sha256 ? String(pkg.active.sha256).slice(0, 7) : null,
@@ -3742,7 +3762,7 @@ export function selectAdminConsole(state) {
3742
3762
  : ownerBadgeFor(resolvePackageOwner(pkg, ownerDirectory)),
3743
3763
  // Highlight only while the Agents section is active — otherwise the
3744
3764
  // GitHub Keys screen shows a double selection.
3745
- selected: admin.section === "packages" && pkgState.selectedName === pkg.name,
3765
+ selected: rowMatchesSelection(pkg),
3746
3766
  });
3747
3767
  // Admins are served every user-scope package, but another person's private
3748
3768
  // agents are not part of YOUR workspace — keep them out of the main tree
@@ -3787,13 +3807,13 @@ export function selectAdminConsole(state) {
3787
3807
  { id: "ghcp", kind: "section", depth: 0, label: "GitHub Keys", selected: section === "ghcp" },
3788
3808
  { id: "agents", kind: "section", depth: 0, label: "Agents", selected: section === "packages" && !pkgState.selectedName },
3789
3809
  { id: "group:shared", kind: "group", depth: 1, label: "Shared", count: sharedRows.length },
3790
- ...sharedRows.map((row) => ({ id: `pkg:${row.name}`, kind: "package", depth: 2, label: row.name, ...row })),
3810
+ ...sharedRows.map((row) => ({ id: `pkg:shared:${row.name}`, kind: "package", depth: 2, label: row.name, ...row })),
3791
3811
  { id: "group:user", kind: "group", depth: 1, label: "User", count: userRows.length },
3792
- ...userRows.map((row) => ({ id: `pkg:${row.name}`, kind: "package", depth: 2, label: row.name, ...row })),
3812
+ ...userRows.map((row) => ({ id: `pkg:user:${row.name}`, kind: "package", depth: 2, label: row.name, ...row })),
3793
3813
  ...(otherUserRows.length > 0
3794
3814
  ? [
3795
3815
  { id: "group:others", kind: "group", depth: 1, label: "Other users", count: otherUserRows.length },
3796
- ...otherUserRows.map((row) => ({ id: `pkg:${row.name}`, kind: "package", depth: 2, label: row.name, ...row })),
3816
+ ...otherUserRows.map((row) => ({ id: `pkg:user:${row.owner?.subject ?? "?"}:${row.name}`, kind: "package", depth: 2, label: row.name, ...row })),
3797
3817
  ]
3798
3818
  : []),
3799
3819
  // The worker registry is a hard-gated admin read; hide the section
@@ -3805,7 +3825,10 @@ export function selectAdminConsole(state) {
3805
3825
  const detail = pkgState.detail || null;
3806
3826
  let packageDetail = null;
3807
3827
  if (pkgState.selectedName) {
3808
- const summary = pkgList.find((pkg) => pkg.name === pkgState.selectedName) || null;
3828
+ const sameName = pkgList.filter((pkg) => pkg.name === pkgState.selectedName);
3829
+ const summary = (pkgState.selectedSelector?.scope
3830
+ ? sameName.find((pkg) => packageCopyKey(pkg.name, pkg.scope, pkg.owner) === selectedCopyKey)
3831
+ : sameName[0]) ?? sameName[0] ?? null;
3809
3832
  const activeVersion = detail?.versions?.find((v) => v.versionId === detail.activeVersionId) || null;
3810
3833
  const manifest = activeVersion?.manifest || summary?.active?.manifest || {};
3811
3834
  // Workers are ephemeral pods: rows for retired pod names linger until
@@ -3819,9 +3842,22 @@ export function selectAdminConsole(state) {
3819
3842
  return !Number.isNaN(at.getTime()) && at.getTime() >= liveCutoff;
3820
3843
  });
3821
3844
  const fleetTotal = workerRows.length;
3845
+ // Workers report installed state by bare name — except when two
3846
+ // same-named copies are installed at once, where each row gets a
3847
+ // qualified key (name#scope[:owner8]) so the collision stays visible.
3848
+ // Read whichever key this copy answers to.
3849
+ const installedRowFor = (worker) => {
3850
+ const installed = worker.installed || {};
3851
+ const scope = detail?.scope || summary?.scope || pkgState.selectedSelector?.scope || null;
3852
+ const ownerSubject = (detail?.owner?.subject || summary?.owner?.subject || pkgState.selectedSelector?.owner?.subject || "");
3853
+ const qualified = scope === "user"
3854
+ ? `${pkgState.selectedName}#user${ownerSubject ? `:${ownerSubject.slice(0, 8)}` : ""}`
3855
+ : `${pkgState.selectedName}#shared`;
3856
+ return installed[qualified] ?? installed[pkgState.selectedName];
3857
+ };
3822
3858
  const fleetCurrent = activeVersion
3823
- ? workerRows.filter((worker) => worker.installed?.[pkgState.selectedName]?.semver === activeVersion.semver
3824
- && worker.installed?.[pkgState.selectedName]?.status === "ok").length
3859
+ ? workerRows.filter((worker) => installedRowFor(worker)?.semver === activeVersion.semver
3860
+ && installedRowFor(worker)?.status === "ok").length
3825
3861
  : 0;
3826
3862
  const canManage = detail ? ownsPackage(detail) : (summary ? ownsPackage(summary) : false);
3827
3863
  packageDetail = {
@@ -3856,6 +3892,12 @@ export function selectAdminConsole(state) {
3856
3892
  : null,
3857
3893
  actionPending: pkgState.action?.pending || null,
3858
3894
  actionError: pkgState.action?.error || null,
3895
+ // Which same-named copies exist, for the republish affordance and
3896
+ // the shadowing note. Counterparts the caller can SEE only —
3897
+ // exactly what the list already enforces.
3898
+ hasSharedCounterpart: sameName.some((pkg) => pkg.scope === "shared"),
3899
+ hasOwnUserCounterpart: sameName.some((pkg) => pkg.scope !== "shared" && isMinePackage(pkg)),
3900
+ copyCount: sameName.length,
3859
3901
  };
3860
3902
  }
3861
3903
 
@@ -17,6 +17,7 @@ import {
17
17
  formatCompactNumber,
18
18
  formatCronTimestampForClient,
19
19
  formatHumanDurationSeconds,
20
+ getDiagnosticsSplitAdjustBounds,
20
21
  getPromptInputRows,
21
22
  getTheme,
22
23
  isThemeLight,
@@ -3925,6 +3926,7 @@ function SessionDetailBox({ session, childCount = 0 }) {
3925
3926
  // used, so the box height still cannot move with the selection.
3926
3927
  field("Title", session?.title, "is-title"),
3927
3928
  field("ID", session?.sessionId, "is-id"),
3929
+ field("Owner", session?.owner ? formatAdminPrincipalLabel(session.owner) : null),
3928
3930
  field("Model", model),
3929
3931
  field("Context", context, percent != null && percent >= 85 ? "is-hot" : percent != null && percent >= 70 ? "is-warm" : ""),
3930
3932
  field("Cron", cron, session?.cronActive === true ? "is-armed" : ""),
@@ -8194,12 +8196,13 @@ function Toolbar({ controller, mobile, canvasPaneOpen = false, onToggleCanvasPan
8194
8196
  const leftButtons = buttonDefs.filter((d) => !RIGHT_GROUP.has(d.key)).map(withRestore);
8195
8197
  const rightButtons = buttonDefs.filter((d) => RIGHT_GROUP.has(d.key)).map(withRestore);
8196
8198
  const toolbar = React.createElement("div", { className: "ps-toolbar" },
8197
- // Three columns: spacer | main controls | right rail. The main group
8198
- // sits in the CENTER column, so it stays dead-centre in every mode —
8199
- // an auto margin only centres in leftover space, and the full-screen
8200
- // strip was shoving it sideways.
8201
- React.createElement("div", { className: "ps-toolbar-side is-left", "aria-hidden": "true" }),
8202
- React.createElement("div", { className: "ps-toolbar-actions" }, leftButtons.map(renderButton)),
8199
+ // Three columns: left rail | main controls | right rail. Full-screen
8200
+ // canvas uses the otherwise-empty left rail for the normal actions so
8201
+ // they do not crowd the canvas metadata and controls across the top.
8202
+ React.createElement("div", { className: "ps-toolbar-side is-left" },
8203
+ canvasMaximized ? leftButtons.map(renderButton) : null),
8204
+ React.createElement("div", { className: "ps-toolbar-actions" },
8205
+ canvasMaximized ? null : leftButtons.map(renderButton)),
8203
8206
  React.createElement("div", { className: "ps-toolbar-side is-right" },
8204
8207
  // The portal header parks its version/status meta here, LEFT of
8205
8208
  // the tool buttons, and its sign-out glyph in the slot after
@@ -8749,11 +8752,11 @@ function DiagnosticsSplitResizeHandle({ controller, splitAdjust = 0 }) {
8749
8752
  const onMove = (event) => {
8750
8753
  const st = dragStateRef.current;
8751
8754
  if (!st) return;
8752
- // Clamped to the half-height each side can actually give. Without
8753
- // this the stored value keeps counting past the edge while the
8754
- // bar stops and the pointer leads the seam by the overshoot on
8755
- // the way back.
8756
- const next = Math.max(-st.half, Math.min(st.half, st.start + (event.clientY - st.startY)));
8755
+ // The first grid track is `50% + adjust`, while the divider takes
8756
+ // real space between the two panes. Its bounds are asymmetric:
8757
+ // -column/2 makes Inspector 0px; column/2-divider makes Activity
8758
+ // 0px. Using one symmetric half-range left an 8-9px pane remnant.
8759
+ const next = clamp(st.start + (event.clientY - st.startY), st.minAdjust, st.maxAdjust);
8757
8760
  controller.dispatch({ type: "ui/diagnosticsSplitAdjust", diagnosticsSplitAdjust: next });
8758
8761
  };
8759
8762
  const onUp = () => {
@@ -8781,8 +8784,15 @@ function DiagnosticsSplitResizeHandle({ controller, splitAdjust = 0 }) {
8781
8784
  event.preventDefault();
8782
8785
  capturePointerForDrag(event);
8783
8786
  const col = event.currentTarget.closest(".ps-workspace-column");
8784
- const half = Math.max(0, ((col?.getBoundingClientRect?.().height || 0) - 16) / 2);
8785
- dragStateRef.current = { startY: event.clientY, start: Number(splitAdjust) || 0, half };
8787
+ const columnHeight = Math.max(0, col?.getBoundingClientRect?.().height || 0);
8788
+ const dividerHeight = Math.max(0, event.currentTarget.getBoundingClientRect().height || 0);
8789
+ const { minAdjust, maxAdjust } = getDiagnosticsSplitAdjustBounds(columnHeight, dividerHeight);
8790
+ dragStateRef.current = {
8791
+ startY: event.clientY,
8792
+ start: clamp(Number(splitAdjust) || 0, minAdjust, maxAdjust),
8793
+ minAdjust,
8794
+ maxAdjust,
8795
+ };
8786
8796
  setDragging(true);
8787
8797
  document.body.classList.add("is-resizing-pane-y");
8788
8798
  },
@@ -8790,9 +8800,17 @@ function DiagnosticsSplitResizeHandle({ controller, splitAdjust = 0 }) {
8790
8800
  onKeyDown: (event) => {
8791
8801
  if (event.key !== "ArrowUp" && event.key !== "ArrowDown") return;
8792
8802
  event.preventDefault();
8803
+ const col = event.currentTarget.closest(".ps-workspace-column");
8804
+ const columnHeight = Math.max(0, col?.getBoundingClientRect?.().height || 0);
8805
+ const dividerHeight = Math.max(0, event.currentTarget.getBoundingClientRect().height || 0);
8806
+ const { minAdjust, maxAdjust } = getDiagnosticsSplitAdjustBounds(columnHeight, dividerHeight);
8793
8807
  controller.dispatch({
8794
8808
  type: "ui/diagnosticsSplitAdjust",
8795
- diagnosticsSplitAdjust: (Number(splitAdjust) || 0) + (event.key === "ArrowDown" ? 16 : -16),
8809
+ diagnosticsSplitAdjust: clamp(
8810
+ (Number(splitAdjust) || 0) + (event.key === "ArrowDown" ? dividerHeight : -dividerHeight),
8811
+ minAdjust,
8812
+ maxAdjust,
8813
+ ),
8796
8814
  });
8797
8815
  },
8798
8816
  },
@@ -9984,7 +10002,14 @@ function AdminSettingsTree({ controller, view }) {
9984
10002
  `${row.label}`, React.createElement("span", { className: "ps-admin-tree__count" }, String(row.count ?? 0)));
9985
10003
  }
9986
10004
  const onClick = row.kind === "package"
9987
- ? () => controller.selectAdminPackage(row.name)
10005
+ // The selector says WHICH copy this row is — one name can be a
10006
+ // shared package and a user copy at once (scope shadowing).
10007
+ ? () => controller.selectAdminPackage(row.name, {
10008
+ scope: row.scope === "shared" ? "shared" : "user",
10009
+ ...(row.scope !== "shared" && row.owner?.provider && row.owner?.subject
10010
+ ? { owner: { provider: row.owner.provider, subject: row.owner.subject } }
10011
+ : {}),
10012
+ })
9988
10013
  : () => controller.setAdminSection(row.id === "agents" ? "packages" : row.id === "workers" ? "workers" : "ghcp");
9989
10014
  return React.createElement("button", {
9990
10015
  key: row.id,
@@ -10100,8 +10125,29 @@ function AdminPackageDetailPane({ controller, view }) {
10100
10125
  disabled: Boolean(pending),
10101
10126
  title: `Publish a new version of ${detail.name} from a repo folder`,
10102
10127
  }, "Update"),
10103
- React.createElement("button", { type: "button", className: "ps-mini-button", onClick: act(detail.scope === "shared" ? "demote" : "promote"), disabled: Boolean(pending) },
10104
- detail.scope === "shared" ? "Demote to user" : "Promote to shared"),
10128
+ // Promote MOVES this row to shared scope, so it only works
10129
+ // while the shared name is free. Once a shared copy exists,
10130
+ // the update path is republish: this version's exact bytes
10131
+ // become a new version of the existing shared package.
10132
+ detail.scope === "user" && detail.hasSharedCounterpart
10133
+ ? React.createElement("button", {
10134
+ type: "button",
10135
+ className: "ps-mini-button",
10136
+ onClick: act("republish", detail.activeSemver),
10137
+ disabled: Boolean(pending) || !detail.activeSemver,
10138
+ title: `Publish ${detail.name}@${detail.activeSemver ?? "?"} into the existing shared package`,
10139
+ }, pending === "republish" ? "Publishing…" : `Publish ${detail.activeSemver ?? ""} to shared`)
10140
+ : React.createElement("button", { type: "button", className: "ps-mini-button", onClick: act(detail.scope === "shared" ? "demote" : "promote"), disabled: Boolean(pending) },
10141
+ detail.scope === "shared" ? "Demote to user" : "Promote to shared"),
10142
+ detail.scope === "shared" && !detail.hasOwnUserCounterpart
10143
+ ? React.createElement("button", {
10144
+ type: "button",
10145
+ className: "ps-mini-button",
10146
+ onClick: act("republish", detail.activeSemver),
10147
+ disabled: Boolean(pending) || !detail.activeSemver,
10148
+ title: "Copy the active version into your user scope as a private test bench",
10149
+ }, pending === "republish" ? "Copying…" : "Copy to my user scope")
10150
+ : null,
10105
10151
  React.createElement("button", { type: "button", className: "ps-mini-button", onClick: act(detail.enabled ? "disable" : "enable"), disabled: Boolean(pending) },
10106
10152
  detail.enabled ? "Disable" : "Enable"),
10107
10153
  React.createElement("button", { type: "button", className: "ps-mini-button is-danger", onClick: confirmDelete, disabled: Boolean(pending) }, "Delete"))
@@ -10593,6 +10639,7 @@ export function PilotSwarmWebApp({ controller }) {
10593
10639
  diagnosticsPaneAdjust: rootState.ui.layout?.diagnosticsPaneAdjust ?? 0,
10594
10640
  diagnosticsSplitAdjust: rootState.ui.layout?.diagnosticsSplitAdjust ?? 0,
10595
10641
  focusRegion: rootState.ui.focusRegion,
10642
+ requestedFocusRegion: rootState.ui.requestedFocusRegion,
10596
10643
  inspectorTab: rootState.ui.inspectorTab,
10597
10644
  filesFullscreen: Boolean(rootState.files.fullscreen),
10598
10645
  selectedArtifactId: rootState.files.selectedArtifactId || null,
@@ -10881,10 +10928,20 @@ export function PilotSwarmWebApp({ controller }) {
10881
10928
  // toolbar: the sessions-only layout's list reclaims focus, which
10882
10929
  // bounced the user out of Inspector the instant they tapped it.
10883
10930
  // Returning to Main is the Main button's job now.
10884
- if (mobile && (state.focusRegion === "inspector" || state.focusRegion === "activity")) {
10931
+ //
10932
+ // Gate on the RAW request, not the normalized region: on a phone a
10933
+ // workspace region (sessions/chat) normalizes to inspector, so the
10934
+ // Main button's own setFocus("chat") would otherwise land here as an
10935
+ // "inspector" focus and yank the user into diagnostics the instant
10936
+ // they asked for the workspace. Only a focus the caller genuinely
10937
+ // aimed at inspector/activity switches the pane.
10938
+ const requested = state.requestedFocusRegion;
10939
+ if (mobile
10940
+ && (state.focusRegion === "inspector" || state.focusRegion === "activity")
10941
+ && (requested === "inspector" || requested === "activity")) {
10885
10942
  setMobilePane(state.focusRegion);
10886
10943
  }
10887
- }, [mobile, state.focusRegion]);
10944
+ }, [mobile, state.focusRegion, state.requestedFocusRegion]);
10888
10945
 
10889
10946
  React.useEffect(() => {
10890
10947
  const visibleTabs = getVisibleInspectorTabs(controller);
@@ -1 +1 @@
1
- import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-BAFuQHAC.js";import{p as f}from"./chunk-JWPE2WC7-BSH41q4T.js";import{_ as n,l as o}from"./mermaid.core-B1Dwetk3.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-CpjwdEIU.js";import"./pilotswarm-DayYdi39.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-BN5MKe94.js";import{p as f}from"./chunk-JWPE2WC7-BccmZmrr.js";import{_ as n,l as o}from"./mermaid.core-bonzwapf.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-Z8eMzFMv.js";import"./pilotswarm-BT6tOknQ.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-B1Dwetk3.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-bonzwapf.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};