pilotswarm 0.5.72 → 0.5.74

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 (75) hide show
  1. package/README.md +6 -0
  2. package/package.json +2 -2
  3. package/ui/core/src/controller.js +17 -3
  4. package/ui/core/src/reducer.js +1 -1
  5. package/ui/core/src/selectors.js +6 -6
  6. package/ui/react/src/components.js +5 -5
  7. package/ui/react/src/feature-flags-panel.js +2 -0
  8. package/ui/react/src/web-app.js +118 -23
  9. package/web/dist/assets/{abnfDiagram-VRR7QNED-D__RWhK7.js → abnfDiagram-VRR7QNED-NbU-sJuP.js} +1 -1
  10. package/web/dist/assets/{arc-CjtcEiTR.js → arc-CTgrgDMZ.js} +1 -1
  11. package/web/dist/assets/{architectureDiagram-ZJ3FMSHR-BDI8FioV.js → architectureDiagram-ZJ3FMSHR-ChQoZV9O.js} +1 -1
  12. package/web/dist/assets/{blockDiagram-677ZJIJ3-D62iIbEl.js → blockDiagram-677ZJIJ3-5PYV29Px.js} +1 -1
  13. package/web/dist/assets/{c4Diagram-LMCZKHZV-BlJ596a2.js → c4Diagram-LMCZKHZV-Ck0NT3vh.js} +1 -1
  14. package/web/dist/assets/channel-ClSHF2hk.js +1 -0
  15. package/web/dist/assets/{chunk-2Q5K7J3B-CnVtHjtN.js → chunk-2Q5K7J3B-c_yhgLFt.js} +1 -1
  16. package/web/dist/assets/{chunk-32BRIVSS-g8IU-e70.js → chunk-32BRIVSS-C8dmvIWk.js} +1 -1
  17. package/web/dist/assets/{chunk-5VM5RSS4-KKxfFv2y.js → chunk-5VM5RSS4-gU_WpVuN.js} +1 -1
  18. package/web/dist/assets/{chunk-EX3LRPZG-C0eEpQtc.js → chunk-EX3LRPZG-BUI-N5DT.js} +1 -1
  19. package/web/dist/assets/{chunk-JWPE2WC7-ZfmDblU2.js → chunk-JWPE2WC7-B1dxrl_8.js} +1 -1
  20. package/web/dist/assets/{chunk-MOJQB5TN-BOfHzBMe.js → chunk-MOJQB5TN-i6IlESZJ.js} +1 -1
  21. package/web/dist/assets/{chunk-RYQCIY6F-GvY7zGfa.js → chunk-RYQCIY6F-Dyjo-7_E.js} +1 -1
  22. package/web/dist/assets/{chunk-V7JOEXUC-Bi28CvqE.js → chunk-V7JOEXUC-WKUXg6Wl.js} +1 -1
  23. package/web/dist/assets/{chunk-VR4S4FIN-H1DY3Xw7.js → chunk-VR4S4FIN-B0I7PCCm.js} +1 -1
  24. package/web/dist/assets/{chunk-XXDRQBXY-JMwCi2he.js → chunk-XXDRQBXY-CB7eqrC9.js} +1 -1
  25. package/web/dist/assets/classDiagram-OUVF2IWQ-2Il7FbX1.js +1 -0
  26. package/web/dist/assets/classDiagram-v2-EOCWNBFH-2Il7FbX1.js +1 -0
  27. package/web/dist/assets/{cose-bilkent-JH36ORCC-DfFOvDA3.js → cose-bilkent-JH36ORCC-CRcAifyt.js} +1 -1
  28. package/web/dist/assets/{cynefin-VYW2F7L2-CD5a_UMt.js → cynefin-VYW2F7L2-KpsZYLz7.js} +1 -1
  29. package/web/dist/assets/{cynefinDiagram-TSTJHNR4-CRsYXGC9.js → cynefinDiagram-TSTJHNR4-CUOwCgQT.js} +1 -1
  30. package/web/dist/assets/{dagre-VKFMJZFB-BuPdi3xA.js → dagre-VKFMJZFB-CDmvCqlf.js} +1 -1
  31. package/web/dist/assets/{diagram-FQU43EPY-MIVIpIBC.js → diagram-FQU43EPY-Bd-9Pin4.js} +1 -1
  32. package/web/dist/assets/{diagram-G47NLZAW-D7-s_wbT.js → diagram-G47NLZAW-C928DZyw.js} +1 -1
  33. package/web/dist/assets/{diagram-NH7WQ7WH-fmSlDjpy.js → diagram-NH7WQ7WH-CA9dPxkC.js} +1 -1
  34. package/web/dist/assets/{diagram-OA4YK3LP-DwEwWIum.js → diagram-OA4YK3LP-DTa7sqVK.js} +1 -1
  35. package/web/dist/assets/{diagram-WEI45ONY-Gvb_KdCz.js → diagram-WEI45ONY-BJBIP-D1.js} +1 -1
  36. package/web/dist/assets/{ebnfDiagram-CCIWWBDH-BOWGc2OC.js → ebnfDiagram-CCIWWBDH-Bt5TMBFP.js} +1 -1
  37. package/web/dist/assets/{erDiagram-Q63AITRT-CrigFfDY.js → erDiagram-Q63AITRT-CGCT386q.js} +1 -1
  38. package/web/dist/assets/{flowDiagram-23GEKE2U-618PQgNe.js → flowDiagram-23GEKE2U-piGmqFTD.js} +1 -1
  39. package/web/dist/assets/{ganttDiagram-NO4QXBWP-lHe8_OHE.js → ganttDiagram-NO4QXBWP-sTZX4MDv.js} +1 -1
  40. package/web/dist/assets/{gitGraphDiagram-IHSO6WYX-CM3Jo1NF.js → gitGraphDiagram-IHSO6WYX-CIX_plag.js} +1 -1
  41. package/web/dist/assets/index-CSMHeAhZ.css +1 -0
  42. package/web/dist/assets/{index-G-9aAxKP.js → index-DJdpW65K.js} +2 -2
  43. package/web/dist/assets/{infoDiagram-FWYZ7A6U-CtDt5Yg1.js → infoDiagram-FWYZ7A6U-BY6RX8Bs.js} +1 -1
  44. package/web/dist/assets/{ishikawaDiagram-FXEZZL3T-DMDXe5yy.js → ishikawaDiagram-FXEZZL3T-B4g65LaR.js} +1 -1
  45. package/web/dist/assets/{journeyDiagram-5HDEW3XC-BxUjwmwF.js → journeyDiagram-5HDEW3XC-DiwwLX0E.js} +1 -1
  46. package/web/dist/assets/{kanban-definition-HUTT4EX6-Cey1IRnt.js → kanban-definition-HUTT4EX6-PV3grfRZ.js} +1 -1
  47. package/web/dist/assets/{linear-BAaF8u7Q.js → linear-iVmwVooP.js} +1 -1
  48. package/web/dist/assets/{mermaid.core-D7ywN4EU.js → mermaid.core-DA6LjVrx.js} +4 -4
  49. package/web/dist/assets/{mindmap-definition-LN4V7U3C-BTSESh2V.js → mindmap-definition-LN4V7U3C-B8DdylnB.js} +1 -1
  50. package/web/dist/assets/{papaparse.min-BhnWt-zK.js → papaparse.min-Di5Rv4lz.js} +1 -1
  51. package/web/dist/assets/{pegDiagram-2B236MQR-BTWzwmna.js → pegDiagram-2B236MQR-DK6ek_Cq.js} +1 -1
  52. package/web/dist/assets/{pieDiagram-ENE6RG2P-qI9jL2eV.js → pieDiagram-ENE6RG2P-CwWXjXa0.js} +1 -1
  53. package/web/dist/assets/pilotswarm-O-aSs9ka.js +109 -0
  54. package/web/dist/assets/{quadrantDiagram-ABIIQ3AL-B54Va5N3.js → quadrantDiagram-ABIIQ3AL-MuZAfQD9.js} +1 -1
  55. package/web/dist/assets/{railroadDiagram-RFXS5EU6-CVXDflXo.js → railroadDiagram-RFXS5EU6-YzlcnUR9.js} +1 -1
  56. package/web/dist/assets/{requirementDiagram-TGXJPOKE-C7abNeEc.js → requirementDiagram-TGXJPOKE-DXaoYkWC.js} +1 -1
  57. package/web/dist/assets/{sankeyDiagram-HTMAVEWB-ND6Feq2w.js → sankeyDiagram-HTMAVEWB-e01Ywh1-.js} +1 -1
  58. package/web/dist/assets/{sequenceDiagram-DBY2YBRQ-DXGwvQdf.js → sequenceDiagram-DBY2YBRQ-Bejd9pkv.js} +1 -1
  59. package/web/dist/assets/{sizeCapture-X5ZJPWSS-CrXKKsBI.js → sizeCapture-X5ZJPWSS-BH28GjqM.js} +1 -1
  60. package/web/dist/assets/{stateDiagram-2N3HPSRC-BJWpN6s6.js → stateDiagram-2N3HPSRC-BLxFqrZK.js} +1 -1
  61. package/web/dist/assets/stateDiagram-v2-6OUMAXLB-DRVfj4NC.js +1 -0
  62. package/web/dist/assets/{swimlanes-5IMT3BWC-Cy67JyBd.js → swimlanes-5IMT3BWC-DeRawRPH.js} +2 -2
  63. package/web/dist/assets/swimlanesDiagram-G3AALYLV-CqI_LiFE.js +8 -0
  64. package/web/dist/assets/{timeline-definition-FHXFAJF6-CeDd4R0u.js → timeline-definition-FHXFAJF6-DebMYWDr.js} +1 -1
  65. package/web/dist/assets/{vennDiagram-L72KCM5P-BDrPrK0B.js → vennDiagram-L72KCM5P-BNzkPXmx.js} +1 -1
  66. package/web/dist/assets/{wardleyDiagram-EHGQE667-Bp9PEqNv.js → wardleyDiagram-EHGQE667-Bd1oZn0h.js} +1 -1
  67. package/web/dist/assets/{xychartDiagram-FW5EYKEG-DI_8u8T1.js → xychartDiagram-FW5EYKEG-BoBQQKWe.js} +1 -1
  68. package/web/dist/index.html +3 -3
  69. package/web/dist/assets/channel-CF_IY6bX.js +0 -1
  70. package/web/dist/assets/classDiagram-OUVF2IWQ-BoTycRRp.js +0 -1
  71. package/web/dist/assets/classDiagram-v2-EOCWNBFH-BoTycRRp.js +0 -1
  72. package/web/dist/assets/index-DHFBzAwY.css +0 -1
  73. package/web/dist/assets/pilotswarm-Dccv5YRO.js +0 -109
  74. package/web/dist/assets/stateDiagram-v2-6OUMAXLB-BQY9l8FM.js +0 -1
  75. package/web/dist/assets/swimlanesDiagram-G3AALYLV-DZ0Jn4Gp.js +0 -8
package/README.md CHANGED
@@ -12,6 +12,12 @@ surface of a [PilotSwarm](https://github.com/affandar/pilotswarm) deployment:
12
12
  Requires **Node 24+**. Everything below assumes you already have a deployment's
13
13
  portal URL — that URL is the only thing you need to configure.
14
14
 
15
+ PilotSwarm packages can distribute skills, worker tools, MCP servers, and
16
+ optional authored agent workflows. In deployments with Base Agent V2 enabled,
17
+ generic sessions discover these capabilities progressively and attach only the
18
+ ones needed for the current task. Named agents remain useful for complex,
19
+ prepackaged workflows and independent durable entry points.
20
+
15
21
  ---
16
22
 
17
23
  ## Quickstart
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pilotswarm",
3
- "version": "0.5.72",
3
+ "version": "0.5.74",
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.72",
84
+ "pilotswarm-sdk": "0.5.74",
85
85
  "react": "^19.2.4",
86
86
  "react-dom": "^19.2.4",
87
87
  "ws": "^8.18.2"
@@ -3745,7 +3745,7 @@ export class PilotSwarmUiController {
3745
3745
  : this.clearAdminSystemAgentModel(route.agentId);
3746
3746
  }
3747
3747
 
3748
- // ── Agent packages (Admin → Agents) ──────────────────────────
3748
+ // ── Packages (Admin → Packages) ──────────────────────────────
3749
3749
 
3750
3750
  setAdminSection(section) {
3751
3751
  this.dispatch({ type: "admin/section", section });
@@ -3978,8 +3978,22 @@ export class PilotSwarmUiController {
3978
3978
  updated.source = allowUser && updated.user ? "user" : updated.cluster ? "cluster" : "default";
3979
3979
  updated.userOverrideIgnored = Boolean(updated.user && !allowUser);
3980
3980
  const data = this.getState().admin.features.data;
3981
+ const flags = data.flags.map(flag => flag.featureKey === featureKey ? updated : flag);
3982
+ // Preserve independent saved preferences, but do not display
3983
+ // Base V2 as active when the native prerequisite is Off.
3984
+ // Recompute both when either setting changes; the following
3985
+ // refresh may fail after a successfully saved mutation.
3986
+ const nativeEnabled = flags.find(flag => flag.featureKey === "copilot.native_tasks")?.effective === true;
3987
+ const effectiveFlags = flags.map(flag => {
3988
+ if (flag.featureKey !== "agents.base_v2") return flag;
3989
+ const { reason: _reason, ...baseFlag } = flag;
3990
+ const allowPersonal = flag.cluster?.allowUserOverride ?? flag.defaultAllowUserOverride;
3991
+ const configured = allowPersonal && flag.user ? flag.user.enabled : flag.cluster?.enabled ?? flag.defaultEnabled;
3992
+ return { ...baseFlag, effective: configured && nativeEnabled,
3993
+ ...(configured && !nativeEnabled ? { reason: "requires_native_tasks" } : {}) };
3994
+ });
3981
3995
  this.dispatch({ type: "admin/features", patch: { data: { ...data,
3982
- flags: data.flags.map(flag => flag.featureKey === featureKey ? updated : flag) } } });
3996
+ flags: effectiveFlags } } });
3983
3997
  }
3984
3998
  if (draft && this.getState().admin.features.drafts?.[draftKey] === draft) {
3985
3999
  const drafts = { ...this.getState().admin.features.drafts };
@@ -4046,7 +4060,7 @@ export class PilotSwarmUiController {
4046
4060
  /** Reload the package list + sources (+ fleet state when permitted). */
4047
4061
  async refreshAdminAgentPackages() {
4048
4062
  if (typeof this.transport.listAgentPackages !== "function") {
4049
- this.dispatch({ type: "admin/packages/loadFailed", error: "Agent packages are not available on this deployment." });
4063
+ this.dispatch({ type: "admin/packages/loadFailed", error: "Packages are not available on this deployment." });
4050
4064
  return;
4051
4065
  }
4052
4066
  this.dispatch({ type: "admin/packages/loading" });
@@ -3067,7 +3067,7 @@ function baseReducer(state, action) {
3067
3067
  };
3068
3068
  }
3069
3069
  case "admin/packages/loadFailed": {
3070
- return { ...state, admin: { ...state.admin, packages: { ...state.admin.packages, loading: false, error: action.error || "Failed to load agent packages" } } };
3070
+ return { ...state, admin: { ...state.admin, packages: { ...state.admin.packages, loading: false, error: action.error || "Failed to load packages" } } };
3071
3071
  }
3072
3072
  case "admin/packages/select": {
3073
3073
  return {
@@ -4520,7 +4520,7 @@ export function selectAdminConsole(state) {
4520
4520
  ? "Configured (overrides env GITHUB_TOKEN for this user)"
4521
4521
  : "Not configured (using env GITHUB_TOKEN fallback)");
4522
4522
 
4523
- // ── Agent packages view-model (Admin → Agents) ───────────────
4523
+ // ── Package view-model (Admin → Packages) ────────────────────
4524
4524
  const pkgState = admin.packages || {};
4525
4525
  const pkgList = Array.isArray(pkgState.list) ? pkgState.list : [];
4526
4526
  const ownsPackage = (pkg) => Boolean(
@@ -4634,7 +4634,7 @@ export function selectAdminConsole(state) {
4634
4634
  { id: "myProviders", kind: "subsection", depth: 1, label: "My Providers", selected: section === "providers" && providerPage === "mine" },
4635
4635
  ...(isAdmin ? [{ id: "sharedProviders", kind: "subsection", depth: 1, label: "Shared Providers", selected: section === "providers" && providerPage === "shared" }] : []),
4636
4636
  { id: "features", kind: "section", depth: 0, label: "Feature flags", selected: section === "features" },
4637
- { id: "agents", kind: "section", depth: 0, label: "Agents", selected: section === "packages" && !pkgState.selectedName },
4637
+ { id: "agents", kind: "section", depth: 0, label: "Packages", selected: section === "packages" && !pkgState.selectedName },
4638
4638
  { id: "group:shared", kind: "group", depth: 1, label: "Shared", count: sharedRows.length },
4639
4639
  ...sharedRows.map((row) => ({ id: `pkg:shared:${row.name}`, kind: "package", depth: 2, label: row.name, ...row })),
4640
4640
  { id: "group:user", kind: "group", depth: 1, label: "User", count: userRows.length },
@@ -4910,7 +4910,7 @@ export function selectAdminConsole(state) {
4910
4910
  const actions = [];
4911
4911
  if (section === "workers") {
4912
4912
  actions.push({ id: "workersRefresh", label: "Refresh workers", key: "r" });
4913
- actions.push({ id: "showPackages", label: "Agents", key: "a" });
4913
+ actions.push({ id: "showPackages", label: "Packages", key: "a" });
4914
4914
  actions.push({ id: "showProviders", label: "Model Providers", key: "m" });
4915
4915
  actions.push({ id: "close", label: "Close console", key: "Esc" });
4916
4916
  return {
@@ -4999,7 +4999,7 @@ export function selectAdminConsole(state) {
4999
4999
  actions.push({ id: "cycleSystemOverride", label: "Cycle system-agent override", key: "o" });
5000
5000
  }
5001
5001
  actions.push({ id: "refreshProviders", label: "Refresh", key: "r" });
5002
- actions.push({ id: "showPackages", label: "Agents", key: "a" });
5002
+ actions.push({ id: "showPackages", label: "Packages", key: "a" });
5003
5003
  actions.push({ id: "close", label: "Close console", key: "Esc" });
5004
5004
  return {
5005
5005
  visible: Boolean(admin.visible),
@@ -5049,7 +5049,7 @@ export function selectAdminConsole(state) {
5049
5049
  actions.push({ id: "close", label: "Close console", key: ghcpKey.editing ? "Ctrl+Esc" : "Esc" });
5050
5050
 
5051
5051
  if (section === "ghcp") {
5052
- actions.splice(actions.length - 1, 0, { id: "showPackages", label: "Agents", key: "a" });
5052
+ actions.splice(actions.length - 1, 0, { id: "showPackages", label: "Packages", key: "a" });
5053
5053
  }
5054
5054
  return {
5055
5055
  visible: Boolean(admin.visible),
@@ -7255,7 +7255,7 @@ export function selectSessionAgentPickerModal(state, maxWidth = 76) {
7255
7255
  : [[{
7256
7256
  text: selectedItem.sectionKind === "builtin"
7257
7257
  ? "Agents baked into this deployment."
7258
- : "Agent packages installed on this deployment.",
7258
+ : "Packages installed on this deployment.",
7259
7259
  color: "gray",
7260
7260
  }]]),
7261
7261
  [{ text: "", color: "gray" }],
@@ -1922,7 +1922,7 @@ function formatAdminPrincipalLabelTui(principal) {
1922
1922
  }
1923
1923
 
1924
1924
  function buildAdminPackagesLines(view) {
1925
- // TUI parity for Admin → Agents: the same selector view-model the web
1925
+ // TUI parity for Admin → Packages: the same selector view-model the web
1926
1926
  // workspace renders, as text — settings tree, selected package detail,
1927
1927
  // files, and a preview head. Keys: a/g switch sections, j/k select,
1928
1928
  // r refresh (wired via the ADMIN_* commands).
@@ -2029,7 +2029,7 @@ function buildAdminPackagesLines(view) {
2029
2029
  }
2030
2030
  } else {
2031
2031
  lines.push([{ text: packages.empty
2032
- ? "No agent packages yet — add one in the portal or `pilotswarm agents push ./dir`."
2032
+ ? "No packages yet — add skills, tools, MCP integrations, or agents in the portal or `pilotswarm agents push ./dir`."
2033
2033
  : "Select a package (j/k) to see detail and files.", color: "gray" }]);
2034
2034
  }
2035
2035
  lines.push([{ text: "", color: "gray" }]);
@@ -2083,7 +2083,7 @@ function buildAdminWorkersLines(view) {
2083
2083
  lines.push([{ text: "Actions", color: "cyan", bold: true }]);
2084
2084
  lines.push([
2085
2085
  { text: " r ", color: "cyan", bold: true }, { text: "refresh ", color: "gray" },
2086
- { text: "a ", color: "yellow", bold: true }, { text: "Agents ", color: "gray" },
2086
+ { text: "a ", color: "yellow", bold: true }, { text: "Packages ", color: "gray" },
2087
2087
  { text: "m ", color: "yellow", bold: true }, { text: "Model Providers ", color: "gray" },
2088
2088
  { text: "Esc ", color: "red", bold: true }, { text: "close", color: "gray" },
2089
2089
  ]);
@@ -2173,7 +2173,7 @@ function buildAdminModelProviderLines(view) {
2173
2173
  lines.push([
2174
2174
  { text: " r ", color: "cyan", bold: true }, { text: "refresh ", color: "gray" },
2175
2175
  { text: "m/M ", color: "cyan", bold: true }, { text: "my/shared ", color: "gray" },
2176
- { text: "a ", color: "yellow", bold: true }, { text: "Agents ", color: "gray" },
2176
+ { text: "a ", color: "yellow", bold: true }, { text: "Packages ", color: "gray" },
2177
2177
  { text: "Esc ", color: "red", bold: true }, { text: "close", color: "gray" },
2178
2178
  ]);
2179
2179
  return lines;
@@ -2248,7 +2248,7 @@ function buildAdminConsoleLines(view) {
2248
2248
  ]);
2249
2249
  lines.push([
2250
2250
  { text: " a ", color: "cyan", bold: true },
2251
- { text: "Agents (packages) ", color: "gray" },
2251
+ { text: "Packages ", color: "gray" },
2252
2252
  { text: "Esc ", color: "red", bold: true },
2253
2253
  { text: "close console and return to workspace", color: "gray" },
2254
2254
  ]);
@@ -103,6 +103,8 @@ function FeatureFlagRow({ flag, mode, busy, saving, controller, workers, workers
103
103
  mode !== "cluster" ? h("p", { className: "ps-feature-context" }, `Cluster setting: ${onOff(storedEnabled)}. Personal settings ${storedOverride ? "allowed" : "not allowed"}.`) : null,
104
104
  locked ? h("p", { className: "ps-feature-retained" }, `Saved future preference: ${savedChoice === "inherit" ? "Use cluster setting" : onOff(flag.user.enabled)}. This will apply if personal settings are allowed again.`) : null),
105
105
  !flag.supported ? h("p", { role: "status" }, "This server does not support changing this feature.") : null,
106
+ flag.reason === "requires_native_tasks" ? h("p", { className: "ps-feature-blocker", role: "status" },
107
+ "Base Agent V2 is currently Off because it requires Native Copilot tasks. The Base V2 preference is saved and will apply when native tasks are enabled for the same scope.") : null,
106
108
  knownBlocked ? h("p", { className: "ps-feature-blocker", role: "status" }, `The saved setting is On, but none of the ${status.eligible} reporting workers is configured for native tasks. Native tasks cannot run on those workers.`) : null,
107
109
  h("div", { className: "ps-feature-editor" }, mode === "cluster" ? [
108
110
  h(RadioChoices, { key: "enabled", legend: "Cluster setting", name: `${id}-cluster`, value: String(clusterDraft.enabled), disabled: editDisabled,
@@ -89,6 +89,7 @@ const PORTAL_MIN_CHAT_COLUMN_PX = 224;
89
89
  const PORTAL_SESSION_COMPACT_COLUMN_PX = 190;
90
90
  const PORTAL_SESSION_HIDDEN_COLUMN_PX = 48;
91
91
  const SCROLL_ROW_HEIGHT = 16;
92
+ const HISTORY_SCROLL_GESTURE_GAP_MS = 200;
92
93
  const SCROLL_BOTTOM_EPSILON_PX = 0.5;
93
94
  const PROGRAMMATIC_SCROLL_TOLERANCE_PX = SCROLL_BOTTOM_EPSILON_PX;
94
95
  // Minimum downward finger travel (px) while at the top of the chat pane before
@@ -1119,6 +1120,8 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1119
1120
  scrollOffset,
1120
1121
  });
1121
1122
  const previousContentRef = React.useRef(null);
1123
+ const historyScrollRef = React.useRef(null);
1124
+ React.useEffect(() => () => { historyScrollRef.current = null; }, []);
1122
1125
  // Touch scrolling relies on native momentum for speed: a hard flick keeps
1123
1126
  // scrolling long after the finger lifts. Re-asserting scrollTop from state
1124
1127
  // on every render (live events, status updates) kills that momentum at the
@@ -1151,6 +1154,31 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1151
1154
  const firstLine = scrollBoundaryIdentity(normalizedLines);
1152
1155
  const lastLine = scrollBoundaryIdentity(normalizedLines, true);
1153
1156
  const previousContent = previousContentRef.current;
1157
+ let historyScroll = historyScrollRef.current;
1158
+ const activeSessionId = controller.getState().sessions.activeSessionId;
1159
+ if (historyScroll && historyScroll.sessionId !== activeSessionId) {
1160
+ historyScrollRef.current = null;
1161
+ historyScroll = null;
1162
+ }
1163
+ const oldestSeq = controller.getState().history.bySessionId.get(activeSessionId)?.events?.[0]?.seq;
1164
+ const pageArrived = historyScroll && !historyScroll.applied && oldestSeq < historyScroll.oldestSeq;
1165
+ let pageScrollTop = null;
1166
+ if (pageArrived) {
1167
+ // Measure the same visible block, not the total transcript height:
1168
+ // live content can also grow at the bottom while a page is loading.
1169
+ const anchor = historyScroll.anchor;
1170
+ const element = anchor?.element.isConnected && anchor.element.textContent === anchor.text
1171
+ ? anchor.element
1172
+ : [...node.children].find(child => child.textContent === anchor?.text);
1173
+ const delta = element
1174
+ ? element.getBoundingClientRect().top - anchor.top
1175
+ : node.scrollHeight - historyScroll.height;
1176
+ pageScrollTop = Math.max(0, Math.min(node.scrollHeight - node.clientHeight,
1177
+ node.scrollTop + delta - SCROLL_ROW_HEIGHT));
1178
+ historyScroll.applied = true;
1179
+ historyScroll.target = pageScrollTop;
1180
+ historyScroll.releaseAt = performance.now() + HISTORY_SCROLL_GESTURE_GAP_MS;
1181
+ }
1154
1182
  const interaction = userScrollRef.current;
1155
1183
  const now = typeof performance !== "undefined" ? performance.now() : Date.now();
1156
1184
  const interacting = interaction.touching
@@ -1165,13 +1193,13 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1165
1193
  // state normally preserves scrollTop, which would push the same visible
1166
1194
  // message down by the inserted height. Compensate with the measured DOM
1167
1195
  // height delta. Appended live text keeps the old scrollTop unchanged.
1168
- const prependedWhilePaused = stickyBottom
1196
+ const prependedWhilePaused = !historyScroll && stickyBottom
1169
1197
  && previousContent?.lastLine === lastLine
1170
1198
  && previousContent?.firstLine !== firstLine
1171
1199
  && node.scrollHeight > previousContent.scrollHeight
1172
1200
  && (preservePausedStickyScroll || node.scrollTop <= PROGRAMMATIC_SCROLL_TOLERANCE_PX);
1173
1201
  if (
1174
- !prependedWhilePaused
1202
+ !pageArrived && !prependedWhilePaused
1175
1203
  && interacting
1176
1204
  && scrollMode === previousViewportState?.scrollMode
1177
1205
  && (scrollOffset === previousViewportState?.scrollOffset || isEchoOffset)
@@ -1180,7 +1208,7 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1180
1208
  previousContentRef.current = { firstLine, lastLine, scrollHeight: node.scrollHeight };
1181
1209
  return;
1182
1210
  }
1183
- const nextScrollTop = prependedWhilePaused
1211
+ const nextScrollTop = pageArrived ? pageScrollTop : prependedWhilePaused
1184
1212
  ? Math.max(0, Math.min(
1185
1213
  node.scrollTop + (node.scrollHeight - previousContent.scrollHeight),
1186
1214
  node.scrollHeight - node.clientHeight,
@@ -1198,7 +1226,7 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1198
1226
  }
1199
1227
  });
1200
1228
  }
1201
- if (prependedWhilePaused && paneKey && typeof controller.updatePaneScrollFromViewport === "function") {
1229
+ if ((pageArrived || prependedWhilePaused) && paneKey && typeof controller.updatePaneScrollFromViewport === "function") {
1202
1230
  // The measured DOM compensation above is the new durable paused
1203
1231
  // position. Persist it too: otherwise switching sessions and back
1204
1232
  // reapplies the pre-page offset and moves the reader by the full
@@ -1221,6 +1249,15 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1221
1249
  const onScroll = React.useCallback(() => {
1222
1250
  const node = ref.current;
1223
1251
  if (!node || !paneKey) return;
1252
+ const historyScroll = historyScrollRef.current;
1253
+ if (historyScroll?.applied && performance.now() <= historyScroll.releaseAt
1254
+ && node.scrollTop < historyScroll.target) {
1255
+ // Native touch momentum may continue without another touchmove.
1256
+ node.scrollTop = historyScroll.target;
1257
+ historyScroll.releaseAt = performance.now() + HISTORY_SCROLL_GESTURE_GAP_MS;
1258
+ return;
1259
+ }
1260
+ if (historyScroll?.applied && performance.now() > historyScroll.releaseAt) historyScrollRef.current = null;
1224
1261
  const pendingProgrammatic = programmaticScrollRef.current;
1225
1262
  if (pendingProgrammatic) {
1226
1263
  if (Math.abs(node.scrollTop - pendingProgrammatic.target) <= PROGRAMMATIC_SCROLL_TOLERANCE_PX) {
@@ -1268,13 +1305,49 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1268
1305
  }
1269
1306
  }, [controller, dispatchScrollOffset, paneKey, ref, scrollMode, stickyBottom]);
1270
1307
 
1308
+ const requestHistoryPage = React.useCallback(() => {
1309
+ const node = ref.current;
1310
+ const state = controller.getState();
1311
+ const sessionId = state.sessions.activeSessionId;
1312
+ if (!node || !sessionId || historyScrollRef.current) return;
1313
+ const top = node.getBoundingClientRect().top;
1314
+ const element = [...node.children].find(child => child.textContent?.trim() && child.getBoundingClientRect().bottom > top + 6);
1315
+ const pending = {
1316
+ sessionId, oldestSeq: state.history.bySessionId.get(sessionId)?.events?.[0]?.seq,
1317
+ height: node.scrollHeight, applied: false,
1318
+ anchor: element ? { element, text: element.textContent, top: element.getBoundingClientRect().top } : null,
1319
+ };
1320
+ historyScrollRef.current = pending;
1321
+ const load = controller.handleChatTopHistoryScrollIntent?.(
1322
+ (node.scrollHeight - node.clientHeight) / SCROLL_ROW_HEIGHT,
1323
+ { force: true, preserveDomAnchor: true },
1324
+ );
1325
+ Promise.resolve(load).catch(() => {}).finally(() => {
1326
+ if (historyScrollRef.current !== pending) return;
1327
+ const oldest = controller.getState().history.bySessionId.get(sessionId)?.events?.[0]?.seq;
1328
+ if (!(oldest < pending.oldestSeq)) historyScrollRef.current = null;
1329
+ else setViewportRevision(revision => revision + 1);
1330
+ });
1331
+ }, [controller, ref]);
1332
+
1271
1333
  const onWheel = React.useCallback((event) => {
1272
1334
  const node = ref.current;
1273
- if (!node || paneKey !== "chat" || event.deltaY >= 0) return;
1335
+ if (!node || paneKey !== "chat" || !event.deltaY || event.ctrlKey) return;
1336
+ const pending = historyScrollRef.current;
1337
+ if (pending && event.deltaY > 0) historyScrollRef.current = null;
1338
+ else if (pending) {
1339
+ if (!pending.applied || performance.now() <= pending.releaseAt) {
1340
+ pending.releaseAt = performance.now() + HISTORY_SCROLL_GESTURE_GAP_MS;
1341
+ event.preventDefault();
1342
+ return;
1343
+ }
1344
+ historyScrollRef.current = null;
1345
+ }
1346
+ if (event.deltaY >= 0) return;
1274
1347
  if (node.scrollTop > PROGRAMMATIC_SCROLL_TOLERANCE_PX) return;
1275
- const maxScroll = Math.max(0, node.scrollHeight - node.clientHeight);
1276
- controller.handleChatTopHistoryScrollIntent?.(maxScroll / SCROLL_ROW_HEIGHT, { preserveDomAnchor: true });
1277
- }, [controller, paneKey, ref]);
1348
+ event.preventDefault();
1349
+ requestHistoryPage();
1350
+ }, [paneKey, ref, requestHistoryPage]);
1278
1351
 
1279
1352
  // Touch equivalent of the wheel-at-top gesture: touch devices never fire
1280
1353
  // wheel events, and once scrollTop sits at 0 a further swipe-down emits no
@@ -1284,6 +1357,7 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1284
1357
  const touchPullRef = React.useRef({ startY: null, fired: false });
1285
1358
  const onTouchStart = React.useCallback((event) => {
1286
1359
  userScrollRef.current.touching = true;
1360
+ if (historyScrollRef.current?.applied) historyScrollRef.current = null;
1287
1361
  if (paneKey !== "chat") return;
1288
1362
  touchPullRef.current = { startY: event.touches?.[0]?.clientY ?? null, fired: false };
1289
1363
  }, [paneKey]);
@@ -1292,26 +1366,45 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
1292
1366
  // Momentum continues past the finger lift; onScroll keeps refreshing
1293
1367
  // lastUserScrollAt for as long as the glide emits scroll events.
1294
1368
  userScrollRef.current.lastUserScrollAt = typeof performance !== "undefined" ? performance.now() : Date.now();
1369
+ if (historyScrollRef.current?.applied) {
1370
+ historyScrollRef.current.releaseAt = performance.now() + HISTORY_SCROLL_GESTURE_GAP_MS;
1371
+ }
1295
1372
  }, []);
1296
1373
  const onTouchMove = React.useCallback((event) => {
1297
1374
  const node = ref.current;
1298
1375
  const pull = touchPullRef.current;
1299
- if (!node || paneKey !== "chat") return;
1376
+ if (!node || paneKey !== "chat" || event.touches?.length !== 1) return;
1377
+ if (historyScrollRef.current) {
1378
+ historyScrollRef.current.releaseAt = performance.now() + HISTORY_SCROLL_GESTURE_GAP_MS;
1379
+ event.preventDefault();
1380
+ return;
1381
+ }
1300
1382
  if (pull.fired || pull.startY == null) return;
1301
1383
  if (node.scrollTop > PROGRAMMATIC_SCROLL_TOLERANCE_PX) return;
1302
1384
  const y = event.touches?.[0]?.clientY;
1303
1385
  if (y == null || y - pull.startY < TOUCH_TOP_PULL_THRESHOLD_PX) return;
1304
1386
  pull.fired = true;
1305
1387
  // A deliberate pull at the top of the pane is an unambiguous request:
1306
- // force the load, bypassing both the arm/load two-stage handshake and
1307
- // the DOM-vs-render-metric offset gate (the two measurements disagree
1308
- // on narrow viewports). The wheel path keeps the handshake — one
1309
- // physical scroll emits MANY wheel events, so it needs debouncing.
1310
- const maxScroll = Math.max(0, node.scrollHeight - node.clientHeight);
1311
- controller.handleChatTopHistoryScrollIntent?.(maxScroll / SCROLL_ROW_HEIGHT + 1, { force: true, preserveDomAnchor: true });
1312
- }, [controller, paneKey, ref]);
1388
+ // Request one page at the measured DOM boundary. The shared gesture
1389
+ // guard absorbs repeated wheel events and the remainder of this pull.
1390
+ event.preventDefault();
1391
+ requestHistoryPage();
1392
+ }, [paneKey, ref, requestHistoryPage]);
1313
1393
 
1314
- return { normalizedLines, onScroll, onWheel, onTouchStart, onTouchMove, onTouchEnd };
1394
+ React.useEffect(() => {
1395
+ const node = ref.current;
1396
+ if (!node) return;
1397
+ // React's delegated wheel/touch listeners are passive. These must be
1398
+ // cancellable so one in-flight gesture cannot consume the new page.
1399
+ node.addEventListener("wheel", onWheel, { passive: false });
1400
+ node.addEventListener("touchmove", onTouchMove, { passive: false });
1401
+ return () => {
1402
+ node.removeEventListener("wheel", onWheel);
1403
+ node.removeEventListener("touchmove", onTouchMove);
1404
+ };
1405
+ }, [ref, onWheel, onTouchMove]);
1406
+
1407
+ return { normalizedLines, onScroll, onTouchStart, onTouchEnd };
1315
1408
  }
1316
1409
 
1317
1410
  function Runs({ runs, theme }) {
@@ -4144,7 +4237,7 @@ function ScrollLinesPanel({ title, titleRight = null, color, focused, actions, l
4144
4237
  }, [panelRef]);
4145
4238
  const stickyRef = React.useRef(null);
4146
4239
  const syncingHorizontalRef = React.useRef(false);
4147
- const { normalizedLines, onScroll, onWheel, onTouchStart, onTouchMove, onTouchEnd } = useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller, { stickyBottom });
4240
+ const { normalizedLines, onScroll, onTouchStart, onTouchEnd } = useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller, { stickyBottom });
4148
4241
  const normalizedSticky = React.useMemo(() => normalizeLines(stickyLines), [stickyLines]);
4149
4242
  const normalizedBottomSticky = React.useMemo(() => normalizeLines(bottomStickyLines), [bottomStickyLines]);
4150
4243
  const preserveHorizontalScroll = className.includes("is-preserve") && panelClassName.includes("has-preserved-sticky");
@@ -4243,7 +4336,7 @@ function ScrollLinesPanel({ title, titleRight = null, color, focused, actions, l
4243
4336
  normalizedSticky.map((line, index) => React.createElement(Line, { key: `sticky:${index}`, line, theme })),
4244
4337
  )
4245
4338
  : null,
4246
- React.createElement("div", { ref: setPanelNode, className: `ps-scroll-panel ${className}${scrollShadow.down ? " is-scrolled-down" : ""}${scrollShadow.up ? " is-scrolled-up" : ""}`.trim(), "data-session-scroll": focusRegion === "sessions" ? "1" : undefined, "aria-live": ariaLive || undefined, "aria-atomic": ariaLive ? "false" : undefined, onScroll: handleBodyScroll, onMouseDown: claimFocus, onTouchStart, onWheel, onTouchMove, onTouchEnd, onTouchCancel: onTouchEnd },
4339
+ React.createElement("div", { ref: setPanelNode, className: `ps-scroll-panel ${className}${scrollShadow.down ? " is-scrolled-down" : ""}${scrollShadow.up ? " is-scrolled-up" : ""}`.trim(), "data-session-scroll": focusRegion === "sessions" ? "1" : undefined, "aria-live": ariaLive || undefined, "aria-atomic": ariaLive ? "false" : undefined, onScroll: handleBodyScroll, onMouseDown: claimFocus, onTouchStart, onTouchEnd, onTouchCancel: onTouchEnd },
4247
4340
  typeof renderBody === "function"
4248
4341
  ? renderBody(normalizedLines, theme)
4249
4342
  : structuredBlocks
@@ -13811,10 +13904,10 @@ function AdminPackageDetailPane({ controller, view }) {
13811
13904
  const detail = packages.detail;
13812
13905
  if (!packages.selectedName) {
13813
13906
  return React.createElement("div", { className: "ps-admin-detail is-empty" },
13814
- React.createElement("h3", null, "Agents"),
13907
+ React.createElement("h3", null, "Packages"),
13815
13908
  React.createElement("p", { className: "ps-admin-console__hint" },
13816
13909
  packages.empty
13817
- ? "No agent packages yet. Add one from a GitHub/ADO repo, a tarball URL, or upload a folder — or push from a terminal with `pilotswarm agents push ./my-agents`."
13910
+ ? "No packages yet. Add reusable skills, tools, MCP integrations, or authored agent workflows from a repo or folder — or use `pilotswarm agents push ./my-kit`."
13818
13911
  : "Select a package from the tree to see its detail, versions, and files."));
13819
13912
  }
13820
13913
  const confirmDelete = () => {
@@ -14256,9 +14349,11 @@ function AdminAddPackageDialog({ controller, dialog }) {
14256
14349
  onSubmit,
14257
14350
  },
14258
14351
  React.createElement("div", { className: "ps-modal-header" },
14259
- React.createElement("span", null, dialog.updateName ? `Update ${dialog.updateName}` : "Add agent package"),
14352
+ React.createElement("span", null, dialog.updateName ? `Update ${dialog.updateName}` : "Add package"),
14260
14353
  React.createElement("button", { type: "button", className: "ps-mini-button", onClick: () => controller.closeAdminAddPackage() }, "✕")),
14261
14354
  React.createElement("div", { className: "ps-admin-add__body" },
14355
+ React.createElement("p", { className: "ps-admin-console__hint" },
14356
+ "Packages can contain reusable skills, tools, MCP integrations, and authored agent workflows. No agent is required."),
14262
14357
  React.createElement("div", { className: "ps-admin-add__tabs" },
14263
14358
  kinds.map(([kind, label]) => React.createElement("button", {
14264
14359
  key: kind,
@@ -14325,7 +14420,7 @@ function AdminAddPackageDialog({ controller, dialog }) {
14325
14420
  href: guideUrl,
14326
14421
  target: "_blank",
14327
14422
  rel: "noreferrer noopener",
14328
- }, "How to build an agent package"),
14423
+ }, "How to build a package"),
14329
14424
  " — a complete guide you can also hand straight to Claude or Copilot.")
14330
14425
  : null,
14331
14426
  React.createElement("p", { className: "ps-admin-console__hint" },
@@ -1 +1 @@
1
- import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-BOfHzBMe.js";import{p as f}from"./chunk-JWPE2WC7-ZfmDblU2.js";import{_ as n,l as o}from"./mermaid.core-D7ywN4EU.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-CD5a_UMt.js";import"./pilotswarm-Dccv5YRO.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-i6IlESZJ.js";import{p as f}from"./chunk-JWPE2WC7-B1dxrl_8.js";import{_ as n,l as o}from"./mermaid.core-DA6LjVrx.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-KpsZYLz7.js";import"./pilotswarm-O-aSs9ka.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-D7ywN4EU.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-DA6LjVrx.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};