pilotswarm 0.5.62 → 0.5.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/ui/core/src/controller.js +54 -14
- package/ui/core/src/moa.js +9 -0
- package/ui/core/src/reducer.js +13 -6
- package/ui/core/src/state.js +6 -2
- package/ui/react/src/components.js +2 -1
- package/ui/react/src/web-app.js +73 -23
- package/web/dist/assets/{abnfDiagram-VRR7QNED-DAiG41W-.js → abnfDiagram-VRR7QNED-C8iAmIqt.js} +1 -1
- package/web/dist/assets/{arc-CN_GY3DG.js → arc-Cg8qs17j.js} +1 -1
- package/web/dist/assets/{architectureDiagram-ZJ3FMSHR-DD9qiBOj.js → architectureDiagram-ZJ3FMSHR-fYr0dRm3.js} +1 -1
- package/web/dist/assets/{blockDiagram-677ZJIJ3-CZg2R8i6.js → blockDiagram-677ZJIJ3-Bpj79Dzq.js} +1 -1
- package/web/dist/assets/{c4Diagram-LMCZKHZV-DuZxUZYd.js → c4Diagram-LMCZKHZV-b26Lsm6m.js} +1 -1
- package/web/dist/assets/channel-C-ASbcRr.js +1 -0
- package/web/dist/assets/{chunk-2Q5K7J3B-BX7lDvmf.js → chunk-2Q5K7J3B-VLYQfjgG.js} +1 -1
- package/web/dist/assets/{chunk-32BRIVSS-COupwzAw.js → chunk-32BRIVSS-mVx--2Hg.js} +1 -1
- package/web/dist/assets/{chunk-5VM5RSS4-C_IyERib.js → chunk-5VM5RSS4-jwnJmked.js} +1 -1
- package/web/dist/assets/{chunk-EX3LRPZG-CyfIuYKn.js → chunk-EX3LRPZG-DdfzAT1n.js} +1 -1
- package/web/dist/assets/{chunk-JWPE2WC7-Cj5lvEfN.js → chunk-JWPE2WC7-BHm6Udd8.js} +1 -1
- package/web/dist/assets/{chunk-MOJQB5TN-l907LpMA.js → chunk-MOJQB5TN-Dn5qSVAS.js} +1 -1
- package/web/dist/assets/{chunk-RYQCIY6F-PLru1fOZ.js → chunk-RYQCIY6F-D4IKMROn.js} +1 -1
- package/web/dist/assets/{chunk-V7JOEXUC-C6GCxiE5.js → chunk-V7JOEXUC-BhME3pRf.js} +1 -1
- package/web/dist/assets/{chunk-VR4S4FIN-BGelrIxQ.js → chunk-VR4S4FIN-CHG_NBff.js} +1 -1
- package/web/dist/assets/{chunk-XXDRQBXY-BmJstjEv.js → chunk-XXDRQBXY-yw4QCgiL.js} +1 -1
- package/web/dist/assets/classDiagram-OUVF2IWQ-D2vlJIb1.js +1 -0
- package/web/dist/assets/classDiagram-v2-EOCWNBFH-D2vlJIb1.js +1 -0
- package/web/dist/assets/{cose-bilkent-JH36ORCC-CRabxOOK.js → cose-bilkent-JH36ORCC-DqwPj9Kx.js} +1 -1
- package/web/dist/assets/{cynefin-VYW2F7L2-CminxBoG.js → cynefin-VYW2F7L2-CVokaaE_.js} +1 -1
- package/web/dist/assets/{cynefinDiagram-TSTJHNR4-yBazsQf4.js → cynefinDiagram-TSTJHNR4-Bkhj9fuY.js} +1 -1
- package/web/dist/assets/{dagre-VKFMJZFB-DcZuZV2n.js → dagre-VKFMJZFB-DVv-jnjb.js} +1 -1
- package/web/dist/assets/{diagram-FQU43EPY-CHoFzsw6.js → diagram-FQU43EPY-DDlZjkrF.js} +1 -1
- package/web/dist/assets/{diagram-G47NLZAW-B8leqMRl.js → diagram-G47NLZAW-CNDUgqYa.js} +1 -1
- package/web/dist/assets/{diagram-NH7WQ7WH-DNoVxpa3.js → diagram-NH7WQ7WH-DywF8u8i.js} +1 -1
- package/web/dist/assets/{diagram-OA4YK3LP-gC3Q2X6-.js → diagram-OA4YK3LP-ZfN8nvLw.js} +1 -1
- package/web/dist/assets/{diagram-WEI45ONY-CABqyjDl.js → diagram-WEI45ONY-S94A6Avm.js} +1 -1
- package/web/dist/assets/{ebnfDiagram-CCIWWBDH-cSguXaDC.js → ebnfDiagram-CCIWWBDH-Mpt3QUnw.js} +1 -1
- package/web/dist/assets/{erDiagram-Q63AITRT-CoWX37V3.js → erDiagram-Q63AITRT-Bh-eWbdV.js} +1 -1
- package/web/dist/assets/{flowDiagram-23GEKE2U-I9DHYjhG.js → flowDiagram-23GEKE2U-BwRtDI6V.js} +1 -1
- package/web/dist/assets/{ganttDiagram-NO4QXBWP-DaFnfYTt.js → ganttDiagram-NO4QXBWP-CrZoBmcB.js} +1 -1
- package/web/dist/assets/{gitGraphDiagram-IHSO6WYX-CwiXVM_O.js → gitGraphDiagram-IHSO6WYX-giXv1ynk.js} +1 -1
- package/web/dist/assets/index-Br-gGWmc.js +24 -0
- package/web/dist/assets/{index-CHlrgp0s.css → index-DRFDn87d.css} +1 -1
- package/web/dist/assets/{infoDiagram-FWYZ7A6U-DtzIrIpW.js → infoDiagram-FWYZ7A6U-H_5oc4-7.js} +1 -1
- package/web/dist/assets/{ishikawaDiagram-FXEZZL3T-B9nk829n.js → ishikawaDiagram-FXEZZL3T-BydiPDX0.js} +1 -1
- package/web/dist/assets/{journeyDiagram-5HDEW3XC-xLaPm-ow.js → journeyDiagram-5HDEW3XC-DS1HXms0.js} +1 -1
- package/web/dist/assets/{kanban-definition-HUTT4EX6-BnDqLYLC.js → kanban-definition-HUTT4EX6-BjY5SyYu.js} +1 -1
- package/web/dist/assets/{linear-Djc7nVo8.js → linear-BvOotjKL.js} +1 -1
- package/web/dist/assets/{mermaid.core-B5elhUtV.js → mermaid.core-0iRu7sp-.js} +4 -4
- package/web/dist/assets/{mindmap-definition-LN4V7U3C-N-B7EJGs.js → mindmap-definition-LN4V7U3C-DB93zsvL.js} +1 -1
- package/web/dist/assets/{papaparse.min-BqM-LJkq.js → papaparse.min-f5Xncedc.js} +1 -1
- package/web/dist/assets/{pegDiagram-2B236MQR-BIollSMB.js → pegDiagram-2B236MQR-Dh_U1cFA.js} +1 -1
- package/web/dist/assets/{pieDiagram-ENE6RG2P-DkZY6iCd.js → pieDiagram-ENE6RG2P-Csv1qxMm.js} +1 -1
- package/web/dist/assets/pilotswarm-DQNSWfNK.js +105 -0
- package/web/dist/assets/{quadrantDiagram-ABIIQ3AL-iUDmQIyL.js → quadrantDiagram-ABIIQ3AL-Bo0pcrBM.js} +1 -1
- package/web/dist/assets/{railroadDiagram-RFXS5EU6-BSCGJgV7.js → railroadDiagram-RFXS5EU6-CHPvHNWG.js} +1 -1
- package/web/dist/assets/{requirementDiagram-TGXJPOKE-9yqcGRUA.js → requirementDiagram-TGXJPOKE-DgX8l-6H.js} +1 -1
- package/web/dist/assets/{sankeyDiagram-HTMAVEWB-SPh1plT9.js → sankeyDiagram-HTMAVEWB-xR6MTs5a.js} +1 -1
- package/web/dist/assets/{sequenceDiagram-DBY2YBRQ-C0nv5x71.js → sequenceDiagram-DBY2YBRQ-CD_45diB.js} +1 -1
- package/web/dist/assets/{sizeCapture-X5ZJPWSS-DMXfUt1o.js → sizeCapture-X5ZJPWSS-BJVEXU0K.js} +1 -1
- package/web/dist/assets/{stateDiagram-2N3HPSRC-vjhtquua.js → stateDiagram-2N3HPSRC-Bwu6kd23.js} +1 -1
- package/web/dist/assets/stateDiagram-v2-6OUMAXLB-aypsN5jW.js +1 -0
- package/web/dist/assets/{swimlanes-5IMT3BWC-Bqewmkt5.js → swimlanes-5IMT3BWC-BmhEzevT.js} +2 -2
- package/web/dist/assets/swimlanesDiagram-G3AALYLV-Duf5C4YK.js +8 -0
- package/web/dist/assets/{timeline-definition-FHXFAJF6-DYHsdXUL.js → timeline-definition-FHXFAJF6-DFPI_uTI.js} +1 -1
- package/web/dist/assets/{vennDiagram-L72KCM5P-Cb7cOHSa.js → vennDiagram-L72KCM5P-DDTpTkBC.js} +1 -1
- package/web/dist/assets/{wardleyDiagram-EHGQE667-BHpO1byL.js → wardleyDiagram-EHGQE667-bV2_YVIL.js} +1 -1
- package/web/dist/assets/{xychartDiagram-FW5EYKEG-DHDvGPtH.js → xychartDiagram-FW5EYKEG-C7bDIXAV.js} +1 -1
- package/web/dist/index.html +3 -3
- package/web/dist/assets/channel-B50-C7oJ.js +0 -1
- package/web/dist/assets/classDiagram-OUVF2IWQ-CIJlKS0m.js +0 -1
- package/web/dist/assets/classDiagram-v2-EOCWNBFH-CIJlKS0m.js +0 -1
- package/web/dist/assets/index-bf7RCrAf.js +0 -24
- package/web/dist/assets/pilotswarm-Di5s6c69.js +0 -105
- package/web/dist/assets/stateDiagram-v2-6OUMAXLB-CYIeYmPN.js +0 -1
- package/web/dist/assets/swimlanesDiagram-G3AALYLV-BeKhH9C9.js +0 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pilotswarm",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.63",
|
|
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.
|
|
84
|
+
"pilotswarm-sdk": "0.5.63",
|
|
85
85
|
"react": "^19.2.4",
|
|
86
86
|
"react-dom": "^19.2.4",
|
|
87
87
|
"ws": "^8.18.2"
|
|
@@ -5838,10 +5838,11 @@ export class PilotSwarmUiController {
|
|
|
5838
5838
|
}
|
|
5839
5839
|
const existing = this.getState().history.bySessionId.get(sessionId)
|
|
5840
5840
|
|| { chat: [], activity: [], events: [], lastSeq: 0 };
|
|
5841
|
+
const liveHistory = this.preservePausedChatWindow(sessionId, existing);
|
|
5841
5842
|
this.dispatch({
|
|
5842
5843
|
type: "history/set",
|
|
5843
5844
|
sessionId,
|
|
5844
|
-
history: applyLiveTurnToHistory(
|
|
5845
|
+
history: applyLiveTurnToHistory(liveHistory, event.data, {
|
|
5845
5846
|
sessionId,
|
|
5846
5847
|
seq: event.liveSeq,
|
|
5847
5848
|
createdAt: Date.now(),
|
|
@@ -5878,7 +5879,10 @@ export class PilotSwarmUiController {
|
|
|
5878
5879
|
this._liveTurnIdleTimers.delete(sessionId);
|
|
5879
5880
|
}
|
|
5880
5881
|
const state = this.getState();
|
|
5881
|
-
const existing =
|
|
5882
|
+
const existing = this.preservePausedChatWindow(
|
|
5883
|
+
sessionId,
|
|
5884
|
+
state.history.bySessionId.get(sessionId) || { chat: [], activity: [], events: [], lastSeq: 0 },
|
|
5885
|
+
);
|
|
5882
5886
|
if (event.seq <= (existing.lastSeq || 0)) return false;
|
|
5883
5887
|
this.dispatch({
|
|
5884
5888
|
type: "history/set",
|
|
@@ -5979,6 +5983,31 @@ export class PilotSwarmUiController {
|
|
|
5979
5983
|
return true;
|
|
5980
5984
|
}
|
|
5981
5985
|
|
|
5986
|
+
/**
|
|
5987
|
+
* Do not evict the first rendered item while its active chat is paused.
|
|
5988
|
+
* A fixed-size history window normally drops one old item for each live
|
|
5989
|
+
* append. Keeping the same numeric scrollTop then moves the actual text the
|
|
5990
|
+
* user is reading. Grow the in-memory window just enough for arrivals made
|
|
5991
|
+
* during that pause; normal bottom-follow appends resume bounded trimming.
|
|
5992
|
+
*/
|
|
5993
|
+
preservePausedChatWindow(sessionId, history) {
|
|
5994
|
+
const state = this.getState();
|
|
5995
|
+
if (state.sessions.activeSessionId !== sessionId || state.ui.followBottom?.chat !== false) {
|
|
5996
|
+
return history;
|
|
5997
|
+
}
|
|
5998
|
+
const currentLimit = Math.max(
|
|
5999
|
+
DEFAULT_HISTORY_EVENT_LIMIT,
|
|
6000
|
+
Number(history?.loadedEventLimit ?? DEFAULT_HISTORY_EVENT_LIMIT) || DEFAULT_HISTORY_EVENT_LIMIT,
|
|
6001
|
+
);
|
|
6002
|
+
const requiredLimit = Math.max(
|
|
6003
|
+
currentLimit,
|
|
6004
|
+
(Array.isArray(history?.events) ? history.events.length : 0) + 1,
|
|
6005
|
+
(Array.isArray(history?.chat) ? history.chat.length : 0) + 4,
|
|
6006
|
+
(Array.isArray(history?.activity) ? history.activity.length : 0) + 1,
|
|
6007
|
+
);
|
|
6008
|
+
return requiredLimit === currentLimit ? history : { ...history, loadedEventLimit: requiredLimit };
|
|
6009
|
+
}
|
|
6010
|
+
|
|
5982
6011
|
async syncSessionEvents(sessionId) {
|
|
5983
6012
|
if (!sessionId || typeof this.transport.getSessionEvents !== "function") return;
|
|
5984
6013
|
const existing = this.getState().history.bySessionId.get(sessionId);
|
|
@@ -9178,6 +9207,7 @@ export class PilotSwarmUiController {
|
|
|
9178
9207
|
}
|
|
9179
9208
|
|
|
9180
9209
|
paneUsesStickyBottomFollow(pane, state = this.getState()) {
|
|
9210
|
+
if (pane === "chat") return true;
|
|
9181
9211
|
if (pane === "activity") return true;
|
|
9182
9212
|
if (pane === "inspector") return state.ui.inspectorTab === "logs";
|
|
9183
9213
|
return false;
|
|
@@ -9251,6 +9281,15 @@ export class PilotSwarmUiController {
|
|
|
9251
9281
|
const current = this.getPaneVisualScrollOffset(pane, state);
|
|
9252
9282
|
const nextOffset = Math.max(0, Math.min(current - delta, maxOffset));
|
|
9253
9283
|
this.applyPaneVisualScrollOffset(pane, nextOffset, { followBottom: nextOffset >= maxOffset }, state);
|
|
9284
|
+
if (pane === "chat" && delta > 0) {
|
|
9285
|
+
if (current <= 0) {
|
|
9286
|
+
this.handleChatTopHistoryScrollIntent(nextOffset).catch(() => {});
|
|
9287
|
+
} else if (nextOffset <= 0) {
|
|
9288
|
+
this.armChatTopHistoryLoad();
|
|
9289
|
+
}
|
|
9290
|
+
} else if (pane === "chat" && delta < 0) {
|
|
9291
|
+
this.disarmChatTopHistoryLoad();
|
|
9292
|
+
}
|
|
9254
9293
|
return;
|
|
9255
9294
|
}
|
|
9256
9295
|
const current = Math.max(0, Math.min(Number(state.ui.scroll?.[pane]) || 0, maxOffset));
|
|
@@ -9273,6 +9312,10 @@ export class PilotSwarmUiController {
|
|
|
9273
9312
|
const nextOffset = Math.max(0, Math.min(Number(offset) || 0, maxOffset));
|
|
9274
9313
|
if (this.paneUsesStickyBottomFollow(pane, state)) {
|
|
9275
9314
|
this.applyPaneVisualScrollOffset(pane, nextOffset, { followBottom: nextOffset >= maxOffset }, state);
|
|
9315
|
+
if (pane === "chat") {
|
|
9316
|
+
if (maxOffset > 0 && nextOffset <= 0) this.armChatTopHistoryLoad();
|
|
9317
|
+
else this.disarmChatTopHistoryLoad();
|
|
9318
|
+
}
|
|
9276
9319
|
return;
|
|
9277
9320
|
}
|
|
9278
9321
|
this.dispatch({ type: "ui/scroll", pane, offset: nextOffset });
|
|
@@ -9308,6 +9351,7 @@ export class PilotSwarmUiController {
|
|
|
9308
9351
|
|
|
9309
9352
|
await this.maybeAutoExpandActiveHistory(requestedScrollOffset, {
|
|
9310
9353
|
pages: AUTO_HISTORY_SCROLL_PAGE_COUNT,
|
|
9354
|
+
preserveDomAnchor: options.preserveDomAnchor === true,
|
|
9311
9355
|
// Always bypass the offset gate. Every caller of this method fires
|
|
9312
9356
|
// only when the DOM scroller is already AT the top — a direct
|
|
9313
9357
|
// measurement. The gate is a second, weaker guess that compares a
|
|
@@ -9369,7 +9413,7 @@ export class PilotSwarmUiController {
|
|
|
9369
9413
|
const pane = this.getScrollablePaneForFocus();
|
|
9370
9414
|
if (!pane) return;
|
|
9371
9415
|
if (this.paneUsesStickyBottomFollow(pane)) {
|
|
9372
|
-
this.
|
|
9416
|
+
this.scrollPaneTo(pane, 0);
|
|
9373
9417
|
return;
|
|
9374
9418
|
}
|
|
9375
9419
|
const inspectorUsesBottomScroll = pane === "inspector" && this.inspectorUsesBottomScroll();
|
|
@@ -9649,6 +9693,7 @@ export class PilotSwarmUiController {
|
|
|
9649
9693
|
requestedScrollOffset: targetOffset,
|
|
9650
9694
|
autoTriggered: true,
|
|
9651
9695
|
pages: options.pages,
|
|
9696
|
+
preserveDomAnchor: options.preserveDomAnchor === true,
|
|
9652
9697
|
// Chat-driven pull: page backward over renderable message types
|
|
9653
9698
|
// only, so each page is transcript instead of raw event noise.
|
|
9654
9699
|
eventTypes: CHAT_HISTORY_EVENT_TYPES,
|
|
@@ -9785,9 +9830,12 @@ export class PilotSwarmUiController {
|
|
|
9785
9830
|
pane: "chat",
|
|
9786
9831
|
offset: 0,
|
|
9787
9832
|
});
|
|
9788
|
-
} else if (preserveChatView &&
|
|
9789
|
-
//
|
|
9790
|
-
//
|
|
9833
|
+
} else if (preserveChatView && options.autoTriggered && !options.preserveDomAnchor) {
|
|
9834
|
+
// Terminal panes store paused chat as a top offset. Prepending
|
|
9835
|
+
// must advance that offset by the rendered rows inserted above
|
|
9836
|
+
// it, preserving the same visible message. Browser panes use
|
|
9837
|
+
// measured DOM height because rich cards and wrapping do not
|
|
9838
|
+
// match terminal row metrics.
|
|
9791
9839
|
const nextState = this.getState();
|
|
9792
9840
|
const nextRenderedLines = this.getActiveChatRenderMetrics(nextState).totalLines;
|
|
9793
9841
|
const addedLines = Math.max(0, nextRenderedLines - previousRenderedLines);
|
|
@@ -9799,14 +9847,6 @@ export class PilotSwarmUiController {
|
|
|
9799
9847
|
});
|
|
9800
9848
|
}
|
|
9801
9849
|
}
|
|
9802
|
-
// AUTO-triggered (scrolling reached the top): change NOTHING. The
|
|
9803
|
-
// offset is distance-from-BOTTOM, which prepended content cannot
|
|
9804
|
-
// move — leaving it alone keeps the viewport glued to the exact
|
|
9805
|
-
// messages the user was reading, and they scroll on into the new
|
|
9806
|
-
// page naturally. Adding the delta here teleported the view to
|
|
9807
|
-
// the TOP of a 3.3x-larger window — observed as "loading history
|
|
9808
|
-
// takes you way back instead of a few pages up".
|
|
9809
|
-
|
|
9810
9850
|
const stateLabel = history.hasOlderEvents
|
|
9811
9851
|
? options.autoTriggered
|
|
9812
9852
|
? `Loaded older history page from CMS (${history.loadedEventCount} events loaded)`
|
package/ui/core/src/moa.js
CHANGED
|
@@ -57,6 +57,15 @@ export const activeMoaDashboard = value => value.dashboards.find(d => d.id === v
|
|
|
57
57
|
export function updateMoaDashboard(value, dashboardId, patch) {
|
|
58
58
|
return normalizeMoa({ ...value, dashboards: value.dashboards.map(d => d.id === dashboardId ? { ...d, ...patch } : d) });
|
|
59
59
|
}
|
|
60
|
+
export function moveMoaDashboard(value, dashboardId, toIndex) {
|
|
61
|
+
const normalized = normalizeMoa(value);
|
|
62
|
+
const fromIndex = normalized.dashboards.findIndex(d => d.id === dashboardId);
|
|
63
|
+
if (fromIndex < 0 || !Number.isInteger(toIndex)) return normalized;
|
|
64
|
+
const dashboards = [...normalized.dashboards];
|
|
65
|
+
const [dashboard] = dashboards.splice(fromIndex, 1);
|
|
66
|
+
dashboards.splice(Math.max(0, Math.min(dashboards.length, toIndex)), 0, dashboard);
|
|
67
|
+
return { ...normalized, dashboards };
|
|
68
|
+
}
|
|
60
69
|
export function replaceMoaNode(tree, nodeId, next) {
|
|
61
70
|
if (!tree) return null;
|
|
62
71
|
if (tree.id === nodeId) return next;
|
package/ui/core/src/reducer.js
CHANGED
|
@@ -646,6 +646,7 @@ function updateUiForSessionSelection(state, nextActiveSessionId) {
|
|
|
646
646
|
},
|
|
647
647
|
followBottom: {
|
|
648
648
|
...(state.ui.followBottom || {}),
|
|
649
|
+
chat: true,
|
|
649
650
|
inspector: true,
|
|
650
651
|
activity: true,
|
|
651
652
|
},
|
|
@@ -1481,7 +1482,7 @@ function baseReducer(state, action) {
|
|
|
1481
1482
|
};
|
|
1482
1483
|
|
|
1483
1484
|
case "ui/followBottom": {
|
|
1484
|
-
if (action.pane !== "inspector" && action.pane !== "activity") {
|
|
1485
|
+
if (action.pane !== "chat" && action.pane !== "inspector" && action.pane !== "activity") {
|
|
1485
1486
|
return state;
|
|
1486
1487
|
}
|
|
1487
1488
|
const nextFollowBottom = Boolean(action.followBottom);
|
|
@@ -1876,14 +1877,15 @@ function baseReducer(state, action) {
|
|
|
1876
1877
|
|
|
1877
1878
|
case "sessions/selected": {
|
|
1878
1879
|
state = { ...state, sessions: { ...state.sessions, listDeselected: false } };
|
|
1879
|
-
// Per-session chat scroll memory: stash the outgoing
|
|
1880
|
-
//
|
|
1881
|
-
//
|
|
1882
|
-
// latest — "latest chat, or where you left it".
|
|
1880
|
+
// Per-session chat scroll memory: stash both the outgoing offset
|
|
1881
|
+
// and whether it follows the bottom. A paused reading position
|
|
1882
|
+
// stays paused as new messages arrive and across session switches.
|
|
1883
1883
|
const previousActiveId = state.sessions.activeSessionId;
|
|
1884
1884
|
const savedChatScroll = { ...(state.ui.chatScrollBySession || {}) };
|
|
1885
|
+
const savedChatFollowBottom = { ...(state.ui.chatFollowBottomBySession || {}) };
|
|
1885
1886
|
if (previousActiveId && previousActiveId !== action.sessionId) {
|
|
1886
1887
|
savedChatScroll[previousActiveId] = Number(state.ui.scroll?.chat) || 0;
|
|
1888
|
+
savedChatFollowBottom[previousActiveId] = state.ui.followBottom?.chat !== false;
|
|
1887
1889
|
}
|
|
1888
1890
|
// Per-session prompt drafts: a half-written message belongs to the
|
|
1889
1891
|
// session it was written in. Stash the outgoing draft (text +
|
|
@@ -1936,6 +1938,7 @@ function baseReducer(state, action) {
|
|
|
1936
1938
|
ui: {
|
|
1937
1939
|
...state.ui,
|
|
1938
1940
|
chatScrollBySession: savedChatScroll,
|
|
1941
|
+
chatFollowBottomBySession: savedChatFollowBottom,
|
|
1939
1942
|
promptDraftBySession: savedDrafts,
|
|
1940
1943
|
prompt: nextPrompt,
|
|
1941
1944
|
promptCursor: nextPromptCursor,
|
|
@@ -1954,6 +1957,7 @@ function baseReducer(state, action) {
|
|
|
1954
1957
|
},
|
|
1955
1958
|
followBottom: {
|
|
1956
1959
|
...(state.ui.followBottom || {}),
|
|
1960
|
+
chat: savedChatFollowBottom[action.sessionId] !== false,
|
|
1957
1961
|
inspector: true,
|
|
1958
1962
|
activity: true,
|
|
1959
1963
|
},
|
|
@@ -2201,7 +2205,7 @@ function baseReducer(state, action) {
|
|
|
2201
2205
|
...state.history,
|
|
2202
2206
|
bySessionId: nextHistory,
|
|
2203
2207
|
},
|
|
2204
|
-
ui: activeChatUpdated
|
|
2208
|
+
ui: activeChatUpdated && state.ui.followBottom?.chat !== false
|
|
2205
2209
|
? {
|
|
2206
2210
|
...state.ui,
|
|
2207
2211
|
scroll: {
|
|
@@ -2222,6 +2226,8 @@ function baseReducer(state, action) {
|
|
|
2222
2226
|
for (const id of ids) delete nextOutbox[id];
|
|
2223
2227
|
const nextChatScroll = { ...(state.ui.chatScrollBySession || {}) };
|
|
2224
2228
|
for (const id of ids) delete nextChatScroll[id];
|
|
2229
|
+
const nextChatFollowBottom = { ...(state.ui.chatFollowBottomBySession || {}) };
|
|
2230
|
+
for (const id of ids) delete nextChatFollowBottom[id];
|
|
2225
2231
|
const nextDrafts = { ...(state.ui.promptDraftBySession || {}) };
|
|
2226
2232
|
for (const id of ids) delete nextDrafts[id];
|
|
2227
2233
|
return {
|
|
@@ -2237,6 +2243,7 @@ function baseReducer(state, action) {
|
|
|
2237
2243
|
ui: {
|
|
2238
2244
|
...state.ui,
|
|
2239
2245
|
chatScrollBySession: nextChatScroll,
|
|
2246
|
+
chatFollowBottomBySession: nextChatFollowBottom,
|
|
2240
2247
|
promptDraftBySession: nextDrafts,
|
|
2241
2248
|
},
|
|
2242
2249
|
};
|
package/ui/core/src/state.js
CHANGED
|
@@ -448,10 +448,14 @@ export function createInitialState({ mode = "local", branding = null, docs = nul
|
|
|
448
448
|
activity: 0,
|
|
449
449
|
filePreview: 0,
|
|
450
450
|
},
|
|
451
|
-
// Per-session chat scroll memory
|
|
452
|
-
//
|
|
451
|
+
// Per-session chat scroll memory. While following, the offset is
|
|
452
|
+
// distance from the bottom; once the reader scrolls up it becomes
|
|
453
|
+
// a stable viewport offset from the top. The paired follow flag
|
|
454
|
+
// disambiguates the two modes across session switches.
|
|
453
455
|
chatScrollBySession: {},
|
|
456
|
+
chatFollowBottomBySession: {},
|
|
454
457
|
followBottom: {
|
|
458
|
+
chat: true,
|
|
455
459
|
inspector: true,
|
|
456
460
|
activity: true,
|
|
457
461
|
},
|
|
@@ -354,6 +354,7 @@ const ChatPane = React.memo(function ChatPane({ controller, width, height, frame
|
|
|
354
354
|
connectionError: state.connection.error,
|
|
355
355
|
connectionMode: state.connection.mode,
|
|
356
356
|
chatScroll: state.ui.scroll.chat,
|
|
357
|
+
followBottom: state.ui.followBottom?.chat !== false,
|
|
357
358
|
focused: state.ui.focusRegion === "chat",
|
|
358
359
|
};
|
|
359
360
|
}, shallowEqualObject);
|
|
@@ -449,7 +450,7 @@ const ChatPane = React.memo(function ChatPane({ controller, width, height, frame
|
|
|
449
450
|
lines: elements,
|
|
450
451
|
bottomStickyLines,
|
|
451
452
|
scrollOffset: chatView.chatScroll,
|
|
452
|
-
scrollMode: "bottom",
|
|
453
|
+
scrollMode: chatView.followBottom ? "bottom" : "top",
|
|
453
454
|
paneId: "chat",
|
|
454
455
|
paneLabel: "Chat",
|
|
455
456
|
frame,
|
package/ui/react/src/web-app.js
CHANGED
|
@@ -1075,6 +1075,18 @@ export function computeAnchoredScrollTop(
|
|
|
1075
1075
|
: Math.min(maxScroll, offsetPixels);
|
|
1076
1076
|
}
|
|
1077
1077
|
|
|
1078
|
+
function scrollLineIdentity(line) {
|
|
1079
|
+
if (!line) return "";
|
|
1080
|
+
if (line.kind === "runs") return line.runs?.map((run) => run?.text || "").join("") || "";
|
|
1081
|
+
if (line.kind === "assistantPreview") return `assistant:${line.previewKey || line.messageId || line.id || ""}`;
|
|
1082
|
+
return `${line.kind || "text"}:${line.text || line.value || line.id || ""}`;
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
function scrollBoundaryIdentity(lines, fromEnd = false) {
|
|
1086
|
+
const boundary = fromEnd ? lines.slice(-8) : lines.slice(0, 8);
|
|
1087
|
+
return boundary.map(scrollLineIdentity).join("\u241e");
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1078
1090
|
function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller, { stickyBottom = false } = {}) {
|
|
1079
1091
|
const normalizedLines = React.useMemo(() => normalizeLines(lines), [lines]);
|
|
1080
1092
|
// Programmatic scrollTop assignments fire a 'scroll' event that would
|
|
@@ -1087,6 +1099,7 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
|
|
|
1087
1099
|
scrollMode,
|
|
1088
1100
|
scrollOffset,
|
|
1089
1101
|
});
|
|
1102
|
+
const previousContentRef = React.useRef(null);
|
|
1090
1103
|
// Touch scrolling relies on native momentum for speed: a hard flick keeps
|
|
1091
1104
|
// scrolling long after the finger lifts. Re-asserting scrollTop from state
|
|
1092
1105
|
// on every render (live events, status updates) kills that momentum at the
|
|
@@ -1116,30 +1129,44 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
|
|
|
1116
1129
|
const node = ref.current;
|
|
1117
1130
|
if (!node) return;
|
|
1118
1131
|
const previousViewportState = previousViewportStateRef.current;
|
|
1132
|
+
const firstLine = scrollBoundaryIdentity(normalizedLines);
|
|
1133
|
+
const lastLine = scrollBoundaryIdentity(normalizedLines, true);
|
|
1134
|
+
const previousContent = previousContentRef.current;
|
|
1119
1135
|
const interaction = userScrollRef.current;
|
|
1120
1136
|
const now = typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
1121
1137
|
const interacting = interaction.touching
|
|
1122
1138
|
|| (now - (interaction.lastUserScrollAt || 0)) < TOUCH_MOMENTUM_GRACE_MS;
|
|
1123
1139
|
const isEchoOffset = interaction.lastDispatchedOffset != null
|
|
1124
1140
|
&& Math.abs((Number(scrollOffset) || 0) - interaction.lastDispatchedOffset) < 2;
|
|
1141
|
+
const preservePausedStickyScroll = stickyBottom
|
|
1142
|
+
&& scrollMode === "top"
|
|
1143
|
+
&& previousViewportState?.scrollMode === "top"
|
|
1144
|
+
&& previousViewportState?.scrollOffset === scrollOffset;
|
|
1145
|
+
// A backward page inserts DOM above the reader. Top-anchored paused
|
|
1146
|
+
// state normally preserves scrollTop, which would push the same visible
|
|
1147
|
+
// message down by the inserted height. Compensate with the measured DOM
|
|
1148
|
+
// height delta. Appended live text keeps the old scrollTop unchanged.
|
|
1149
|
+
const prependedWhilePaused = stickyBottom
|
|
1150
|
+
&& previousContent?.lastLine === lastLine
|
|
1151
|
+
&& previousContent?.firstLine !== firstLine
|
|
1152
|
+
&& node.scrollHeight > previousContent.scrollHeight
|
|
1153
|
+
&& (preservePausedStickyScroll || node.scrollTop <= PROGRAMMATIC_SCROLL_TOLERANCE_PX);
|
|
1125
1154
|
if (
|
|
1126
|
-
|
|
1155
|
+
!prependedWhilePaused
|
|
1156
|
+
&& interacting
|
|
1127
1157
|
&& scrollMode === previousViewportState?.scrollMode
|
|
1128
1158
|
&& (scrollOffset === previousViewportState?.scrollOffset || isEchoOffset)
|
|
1129
1159
|
) {
|
|
1130
1160
|
previousViewportStateRef.current = { scrollMode, scrollOffset };
|
|
1161
|
+
previousContentRef.current = { firstLine, lastLine, scrollHeight: node.scrollHeight };
|
|
1131
1162
|
return;
|
|
1132
1163
|
}
|
|
1133
|
-
const
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
node,
|
|
1139
|
-
scrollOffset,
|
|
1140
|
-
scrollMode,
|
|
1141
|
-
preservePausedStickyScroll,
|
|
1142
|
-
);
|
|
1164
|
+
const nextScrollTop = prependedWhilePaused
|
|
1165
|
+
? Math.max(0, Math.min(
|
|
1166
|
+
node.scrollTop + (node.scrollHeight - previousContent.scrollHeight),
|
|
1167
|
+
node.scrollHeight - node.clientHeight,
|
|
1168
|
+
))
|
|
1169
|
+
: computeAnchoredScrollTop(node, scrollOffset, scrollMode, preservePausedStickyScroll);
|
|
1143
1170
|
if (Math.abs(node.scrollTop - nextScrollTop) > PROGRAMMATIC_SCROLL_TOLERANCE_PX) {
|
|
1144
1171
|
const pendingProgrammaticScroll = { target: nextScrollTop };
|
|
1145
1172
|
programmaticScrollRef.current = pendingProgrammaticScroll;
|
|
@@ -1152,10 +1179,20 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
|
|
|
1152
1179
|
}
|
|
1153
1180
|
});
|
|
1154
1181
|
}
|
|
1182
|
+
if (prependedWhilePaused && paneKey && typeof controller.updatePaneScrollFromViewport === "function") {
|
|
1183
|
+
// The measured DOM compensation above is the new durable paused
|
|
1184
|
+
// position. Persist it too: otherwise switching sessions and back
|
|
1185
|
+
// reapplies the pre-page offset and moves the reader by the full
|
|
1186
|
+
// height of the newly inserted history.
|
|
1187
|
+
const rowOffset = Math.max(0, nextScrollTop) / SCROLL_ROW_HEIGHT;
|
|
1188
|
+
userScrollRef.current.lastDispatchedOffset = rowOffset;
|
|
1189
|
+
controller.updatePaneScrollFromViewport(paneKey, rowOffset, { atBottom: false });
|
|
1190
|
+
}
|
|
1155
1191
|
previousViewportStateRef.current = {
|
|
1156
1192
|
scrollMode,
|
|
1157
1193
|
scrollOffset,
|
|
1158
1194
|
};
|
|
1195
|
+
previousContentRef.current = { firstLine, lastLine, scrollHeight: node.scrollHeight };
|
|
1159
1196
|
}, [normalizedLines, ref, scrollMode, scrollOffset, stickyBottom, viewportRevision]);
|
|
1160
1197
|
|
|
1161
1198
|
const dispatchScrollOffset = useFrameCoalescedCallback((offset) => {
|
|
@@ -1189,6 +1226,13 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
|
|
|
1189
1226
|
rowOffset,
|
|
1190
1227
|
{ atBottom: isScrollViewportAtBottom(node) },
|
|
1191
1228
|
);
|
|
1229
|
+
// Pausing bottom-follow changes chat to top-anchored scroll state,
|
|
1230
|
+
// but reaching the DOM's actual top must still arm backward CMS
|
|
1231
|
+
// paging. Keep this next to the native measurement so the history
|
|
1232
|
+
// gate does not depend on which anchoring mode currently renders.
|
|
1233
|
+
if (paneKey === "chat" && node.scrollTop <= PROGRAMMATIC_SCROLL_TOLERANCE_PX) {
|
|
1234
|
+
controller.armChatTopHistoryLoad?.();
|
|
1235
|
+
}
|
|
1192
1236
|
return;
|
|
1193
1237
|
}
|
|
1194
1238
|
|
|
@@ -1207,11 +1251,11 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
|
|
|
1207
1251
|
|
|
1208
1252
|
const onWheel = React.useCallback((event) => {
|
|
1209
1253
|
const node = ref.current;
|
|
1210
|
-
if (!node || paneKey !== "chat" ||
|
|
1254
|
+
if (!node || paneKey !== "chat" || event.deltaY >= 0) return;
|
|
1211
1255
|
if (node.scrollTop > PROGRAMMATIC_SCROLL_TOLERANCE_PX) return;
|
|
1212
1256
|
const maxScroll = Math.max(0, node.scrollHeight - node.clientHeight);
|
|
1213
|
-
controller.handleChatTopHistoryScrollIntent?.(maxScroll / SCROLL_ROW_HEIGHT);
|
|
1214
|
-
}, [controller, paneKey, ref
|
|
1257
|
+
controller.handleChatTopHistoryScrollIntent?.(maxScroll / SCROLL_ROW_HEIGHT, { preserveDomAnchor: true });
|
|
1258
|
+
}, [controller, paneKey, ref]);
|
|
1215
1259
|
|
|
1216
1260
|
// Touch equivalent of the wheel-at-top gesture: touch devices never fire
|
|
1217
1261
|
// wheel events, and once scrollTop sits at 0 a further swipe-down emits no
|
|
@@ -1221,9 +1265,9 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
|
|
|
1221
1265
|
const touchPullRef = React.useRef({ startY: null, fired: false });
|
|
1222
1266
|
const onTouchStart = React.useCallback((event) => {
|
|
1223
1267
|
userScrollRef.current.touching = true;
|
|
1224
|
-
if (paneKey !== "chat"
|
|
1268
|
+
if (paneKey !== "chat") return;
|
|
1225
1269
|
touchPullRef.current = { startY: event.touches?.[0]?.clientY ?? null, fired: false };
|
|
1226
|
-
}, [paneKey
|
|
1270
|
+
}, [paneKey]);
|
|
1227
1271
|
const onTouchEnd = React.useCallback(() => {
|
|
1228
1272
|
userScrollRef.current.touching = false;
|
|
1229
1273
|
// Momentum continues past the finger lift; onScroll keeps refreshing
|
|
@@ -1233,7 +1277,7 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
|
|
|
1233
1277
|
const onTouchMove = React.useCallback((event) => {
|
|
1234
1278
|
const node = ref.current;
|
|
1235
1279
|
const pull = touchPullRef.current;
|
|
1236
|
-
if (!node || paneKey !== "chat"
|
|
1280
|
+
if (!node || paneKey !== "chat") return;
|
|
1237
1281
|
if (pull.fired || pull.startY == null) return;
|
|
1238
1282
|
if (node.scrollTop > PROGRAMMATIC_SCROLL_TOLERANCE_PX) return;
|
|
1239
1283
|
const y = event.touches?.[0]?.clientY;
|
|
@@ -1245,8 +1289,8 @@ function useScrollSync(ref, lines, scrollOffset, scrollMode, paneKey, controller
|
|
|
1245
1289
|
// on narrow viewports). The wheel path keeps the handshake — one
|
|
1246
1290
|
// physical scroll emits MANY wheel events, so it needs debouncing.
|
|
1247
1291
|
const maxScroll = Math.max(0, node.scrollHeight - node.clientHeight);
|
|
1248
|
-
controller.handleChatTopHistoryScrollIntent?.(maxScroll / SCROLL_ROW_HEIGHT + 1, { force: true });
|
|
1249
|
-
}, [controller, paneKey, ref
|
|
1292
|
+
controller.handleChatTopHistoryScrollIntent?.(maxScroll / SCROLL_ROW_HEIGHT + 1, { force: true, preserveDomAnchor: true });
|
|
1293
|
+
}, [controller, paneKey, ref]);
|
|
1250
1294
|
|
|
1251
1295
|
return { normalizedLines, onScroll, onWheel, onTouchStart, onTouchMove, onTouchEnd };
|
|
1252
1296
|
}
|
|
@@ -5570,10 +5614,14 @@ function SessionPane({ controller, actions = null, panelClassName = "", structur
|
|
|
5570
5614
|
|| focused.tagName === "SELECT"
|
|
5571
5615
|
|| focused.isContentEditable
|
|
5572
5616
|
));
|
|
5573
|
-
if (focused !== activeButton && !isTypingTarget) {
|
|
5617
|
+
if (viewState.focused && focused !== activeButton && !isTypingTarget) {
|
|
5574
5618
|
activeButton.focus({ preventScroll: true });
|
|
5575
5619
|
}
|
|
5576
|
-
|
|
5620
|
+
// Selection can change from outside this pane (deep links, newly
|
|
5621
|
+
// created sessions, MoA focus and other navigation surfaces). Center
|
|
5622
|
+
// the row once for that selection so its surrounding sessions remain
|
|
5623
|
+
// visible, without re-centering on routine status/catalog refreshes.
|
|
5624
|
+
activeButton.scrollIntoView({ block: "center" });
|
|
5577
5625
|
}, [activeRowRevealKey, viewState.activeSessionId, viewState.focused, viewState.modalOpen, viewState.sessionsFlat]);
|
|
5578
5626
|
|
|
5579
5627
|
const panelActions = React.createElement(React.Fragment, null,
|
|
@@ -6492,6 +6540,7 @@ function ChatPane({ controller, mobile = false, fullWidth = false, showComposer
|
|
|
6492
6540
|
activeSessionStatus: activeSessionId ? String(state.sessions.byId[activeSessionId]?.status || "").toLowerCase() : "",
|
|
6493
6541
|
focused: state.ui.focusRegion === "chat",
|
|
6494
6542
|
scroll: state.ui.scroll.chat,
|
|
6543
|
+
followBottom: state.ui.followBottom?.chat !== false,
|
|
6495
6544
|
// Viewer identity — so the transcript can say "You" for the viewer's
|
|
6496
6545
|
// own messages and name others (with an "(owner)" tag).
|
|
6497
6546
|
authPrincipal: state.auth?.principal || null,
|
|
@@ -6641,7 +6690,8 @@ function ChatPane({ controller, mobile = false, fullWidth = false, showComposer
|
|
|
6641
6690
|
bottomStickyLines: activityInHeader ? EMPTY_ARRAY : stickyBottom,
|
|
6642
6691
|
reserveBottomSticky: !activityInHeader,
|
|
6643
6692
|
scrollOffset: viewState.scroll,
|
|
6644
|
-
scrollMode: "bottom",
|
|
6693
|
+
scrollMode: viewState.followBottom ? "bottom" : "top",
|
|
6694
|
+
stickyBottom: true,
|
|
6645
6695
|
paneKey: "chat",
|
|
6646
6696
|
ariaLive: "polite",
|
|
6647
6697
|
className: "is-wrapped",
|
|
@@ -9086,7 +9136,7 @@ function PromptComposer({ controller, mobile, compact = false, active = true, on
|
|
|
9086
9136
|
onClick: cancelPending,
|
|
9087
9137
|
}, selectedQueued ? "Delete" : "Cancel")
|
|
9088
9138
|
: null,
|
|
9089
|
-
|
|
9139
|
+
(promptState.canStopTurn || stoppingTurn)
|
|
9090
9140
|
? React.createElement("button", {
|
|
9091
9141
|
type: "button",
|
|
9092
9142
|
className: `ps-stop-button${stoppingTurn ? " is-stopping" : ""}`,
|
package/web/dist/assets/{abnfDiagram-VRR7QNED-DAiG41W-.js → abnfDiagram-VRR7QNED-C8iAmIqt.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-
|
|
1
|
+
import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-Dn5qSVAS.js";import{p as f}from"./chunk-JWPE2WC7-BHm6Udd8.js";import{_ as n,l as o}from"./mermaid.core-0iRu7sp-.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-CVokaaE_.js";import"./pilotswarm-DQNSWfNK.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-
|
|
1
|
+
import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-0iRu7sp-.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};
|