pilotswarm 0.5.41 → 0.5.42
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/history.js +25 -1
- package/ui/core/src/selectors.js +15 -0
- package/ui/react/src/web-app.js +211 -75
- package/web/dist/assets/{abnfDiagram-VRR7QNED-kpxu_PEa.js → abnfDiagram-VRR7QNED-Jh9nLlRI.js} +1 -1
- package/web/dist/assets/{arc-BnVQmtB5.js → arc-CmN4jFMW.js} +1 -1
- package/web/dist/assets/{architectureDiagram-ZJ3FMSHR-CDynQ_6_.js → architectureDiagram-ZJ3FMSHR-DgUSVwl7.js} +1 -1
- package/web/dist/assets/{blockDiagram-677ZJIJ3-BUpYaSDb.js → blockDiagram-677ZJIJ3-CCJEXNgp.js} +1 -1
- package/web/dist/assets/{c4Diagram-LMCZKHZV-ZL8eskDB.js → c4Diagram-LMCZKHZV-DG11zUre.js} +1 -1
- package/web/dist/assets/channel-BQBGhjIw.js +1 -0
- package/web/dist/assets/{chunk-2Q5K7J3B-o0Nsyp1T.js → chunk-2Q5K7J3B-Cl8MUWGh.js} +1 -1
- package/web/dist/assets/{chunk-32BRIVSS-CH5CSNRP.js → chunk-32BRIVSS-BaLutEQY.js} +1 -1
- package/web/dist/assets/{chunk-5VM5RSS4-C9wwtPWL.js → chunk-5VM5RSS4-BOPcnMeW.js} +1 -1
- package/web/dist/assets/{chunk-EX3LRPZG--F9yFbhA.js → chunk-EX3LRPZG-bY2tdfJ2.js} +1 -1
- package/web/dist/assets/{chunk-JWPE2WC7-BPIstyWL.js → chunk-JWPE2WC7-CASBfQW6.js} +1 -1
- package/web/dist/assets/{chunk-MOJQB5TN-5Dm2u-0k.js → chunk-MOJQB5TN-WrEHfiAj.js} +1 -1
- package/web/dist/assets/{chunk-RYQCIY6F-Dbtf9iQK.js → chunk-RYQCIY6F-XQoZii_K.js} +1 -1
- package/web/dist/assets/{chunk-V7JOEXUC-DrZEBJ5l.js → chunk-V7JOEXUC-BvA5V7VF.js} +1 -1
- package/web/dist/assets/{chunk-VR4S4FIN-AqAUynqK.js → chunk-VR4S4FIN-SK_jCKYo.js} +1 -1
- package/web/dist/assets/{chunk-XXDRQBXY-DQlFaqCy.js → chunk-XXDRQBXY-CtZZImS8.js} +1 -1
- package/web/dist/assets/classDiagram-OUVF2IWQ-BIr20mVO.js +1 -0
- package/web/dist/assets/classDiagram-v2-EOCWNBFH-BIr20mVO.js +1 -0
- package/web/dist/assets/{cose-bilkent-JH36ORCC-RAtPG1Ou.js → cose-bilkent-JH36ORCC-PRXhsdiX.js} +1 -1
- package/web/dist/assets/{cynefin-VYW2F7L2-CbeHaUWZ.js → cynefin-VYW2F7L2-CzUocqvb.js} +1 -1
- package/web/dist/assets/{cynefinDiagram-TSTJHNR4-B6paqF5Y.js → cynefinDiagram-TSTJHNR4-DYGEqQ23.js} +1 -1
- package/web/dist/assets/{dagre-VKFMJZFB-DziTBO2K.js → dagre-VKFMJZFB-CAyb_zBo.js} +1 -1
- package/web/dist/assets/{diagram-FQU43EPY-CPRUiLcr.js → diagram-FQU43EPY-CvpXMmL-.js} +1 -1
- package/web/dist/assets/{diagram-G47NLZAW-CIMVdcL1.js → diagram-G47NLZAW-DBQRZJS0.js} +1 -1
- package/web/dist/assets/{diagram-NH7WQ7WH-CHPFllxR.js → diagram-NH7WQ7WH-BGzD61gL.js} +1 -1
- package/web/dist/assets/{diagram-OA4YK3LP-DwS6unBJ.js → diagram-OA4YK3LP-DqQf4oMW.js} +1 -1
- package/web/dist/assets/{diagram-WEI45ONY-DKWgkObI.js → diagram-WEI45ONY-CYHoWtg7.js} +1 -1
- package/web/dist/assets/{ebnfDiagram-CCIWWBDH-zAVWV6-D.js → ebnfDiagram-CCIWWBDH-oMOMgcs8.js} +1 -1
- package/web/dist/assets/{erDiagram-Q63AITRT-D0tYX4h0.js → erDiagram-Q63AITRT-DaZaseAH.js} +1 -1
- package/web/dist/assets/{flowDiagram-23GEKE2U-Cfq4I7R0.js → flowDiagram-23GEKE2U-BIe9TtAL.js} +1 -1
- package/web/dist/assets/{ganttDiagram-NO4QXBWP-wgBAHr5I.js → ganttDiagram-NO4QXBWP-DitrY3hM.js} +1 -1
- package/web/dist/assets/{gitGraphDiagram-IHSO6WYX-BTIPX5PR.js → gitGraphDiagram-IHSO6WYX-DRjIH_99.js} +1 -1
- package/web/dist/assets/{index-OHj-gGHp.js → index-Cl6-pI9g.js} +2 -2
- package/web/dist/assets/index-DRLA5aNR.css +1 -0
- package/web/dist/assets/{infoDiagram-FWYZ7A6U-CRLiQ87D.js → infoDiagram-FWYZ7A6U-BJCx4g9_.js} +1 -1
- package/web/dist/assets/{ishikawaDiagram-FXEZZL3T-CwzwUis1.js → ishikawaDiagram-FXEZZL3T-CLxmaTWp.js} +1 -1
- package/web/dist/assets/{journeyDiagram-5HDEW3XC-B9pqMeFw.js → journeyDiagram-5HDEW3XC-D2_VI8CC.js} +1 -1
- package/web/dist/assets/{kanban-definition-HUTT4EX6-CZ5Xky4p.js → kanban-definition-HUTT4EX6-DnUq9E7I.js} +1 -1
- package/web/dist/assets/{linear-BLZ2eH4a.js → linear-mKMwWrAB.js} +1 -1
- package/web/dist/assets/{mermaid.core-CPN1IVjz.js → mermaid.core-CApAWULn.js} +4 -4
- package/web/dist/assets/{mindmap-definition-LN4V7U3C-MdC8d2tc.js → mindmap-definition-LN4V7U3C-D2twxIMO.js} +1 -1
- package/web/dist/assets/{papaparse.min-CtrVJupf.js → papaparse.min-BhDLFNak.js} +1 -1
- package/web/dist/assets/{pegDiagram-2B236MQR-B2DqAc-A.js → pegDiagram-2B236MQR-D2RtIeDP.js} +1 -1
- package/web/dist/assets/{pieDiagram-ENE6RG2P-C3QAoXZh.js → pieDiagram-ENE6RG2P-vonumKaj.js} +1 -1
- package/web/dist/assets/{pilotswarm-CF1nmpMy.js → pilotswarm-DETFHWYc.js} +61 -61
- package/web/dist/assets/{quadrantDiagram-ABIIQ3AL-BoUr5qFH.js → quadrantDiagram-ABIIQ3AL-CAZL1kJH.js} +1 -1
- package/web/dist/assets/{railroadDiagram-RFXS5EU6-bZzE4KFN.js → railroadDiagram-RFXS5EU6-CgpDomFp.js} +1 -1
- package/web/dist/assets/{requirementDiagram-TGXJPOKE-B2ENAqLS.js → requirementDiagram-TGXJPOKE-9B6yfsXV.js} +1 -1
- package/web/dist/assets/{sankeyDiagram-HTMAVEWB-AJZ3h46Z.js → sankeyDiagram-HTMAVEWB-B_FAnwxi.js} +1 -1
- package/web/dist/assets/{sequenceDiagram-DBY2YBRQ-QUf0VVE7.js → sequenceDiagram-DBY2YBRQ-BbL6OCms.js} +1 -1
- package/web/dist/assets/{sizeCapture-X5ZJPWSS-Cv9RcUy6.js → sizeCapture-X5ZJPWSS-DIRKFU8M.js} +1 -1
- package/web/dist/assets/{stateDiagram-2N3HPSRC-hDiye45t.js → stateDiagram-2N3HPSRC-pUX5NF32.js} +1 -1
- package/web/dist/assets/stateDiagram-v2-6OUMAXLB-J_okbpZN.js +1 -0
- package/web/dist/assets/{swimlanes-5IMT3BWC-hSk_OF85.js → swimlanes-5IMT3BWC-DO7BjQ4-.js} +2 -2
- package/web/dist/assets/swimlanesDiagram-G3AALYLV-gTxQyRZa.js +8 -0
- package/web/dist/assets/{timeline-definition-FHXFAJF6-ccOZEJ5e.js → timeline-definition-FHXFAJF6-BcbYRQ7s.js} +1 -1
- package/web/dist/assets/{vennDiagram-L72KCM5P-Bk5DLH_V.js → vennDiagram-L72KCM5P-CUt_orN5.js} +1 -1
- package/web/dist/assets/{wardleyDiagram-EHGQE667-C20AX8ot.js → wardleyDiagram-EHGQE667-BlUPWQdi.js} +1 -1
- package/web/dist/assets/{xychartDiagram-FW5EYKEG-DaHqmi-R.js → xychartDiagram-FW5EYKEG-CDW7A5_U.js} +1 -1
- package/web/dist/index.html +3 -3
- package/web/dist/assets/channel-Bi5A6sHR.js +0 -1
- package/web/dist/assets/classDiagram-OUVF2IWQ-D8dCxI54.js +0 -1
- package/web/dist/assets/classDiagram-v2-EOCWNBFH-D8dCxI54.js +0 -1
- package/web/dist/assets/index-eTH1FBtN.css +0 -1
- package/web/dist/assets/stateDiagram-v2-6OUMAXLB-Bu4ufvaU.js +0 -1
- package/web/dist/assets/swimlanesDiagram-G3AALYLV-BTFePb1Y.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.42",
|
|
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.42",
|
|
85
85
|
"react": "^19.2.4",
|
|
86
86
|
"react-dom": "^19.2.4",
|
|
87
87
|
"ws": "^8.18.2"
|
package/ui/core/src/history.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { formatHumanDurationSeconds, formatTimestamp, shortSessionId, stripTerminalMarkupTags, summarizeJson } from "./formatting.js";
|
|
1
|
+
import { formatHumanDurationSeconds, formatTimestamp, shortModelName, shortSessionId, stripTerminalMarkupTags, summarizeJson } from "./formatting.js";
|
|
2
2
|
import { isCanvasActionContent, parseCanvasActionContent } from "./canvas-actions.js";
|
|
3
3
|
import { formatCompactionActivityRuns } from "./context-usage.js";
|
|
4
4
|
import { canonicalSystemTitle } from "./system-titles.js";
|
|
@@ -692,6 +692,7 @@ function formatEventSnippet(event, maxLen = 96) {
|
|
|
692
692
|
return body || "";
|
|
693
693
|
}
|
|
694
694
|
|
|
695
|
+
|
|
695
696
|
function formatToolActivityRuns(time, event, phase = "start") {
|
|
696
697
|
const toolCallId = typeof event?.data?.toolCallId === "string" ? event.data.toolCallId : "";
|
|
697
698
|
const requestId = typeof event?.data?.requestId === "string" ? event.data.requestId : "";
|
|
@@ -947,6 +948,29 @@ function formatActivity(event) {
|
|
|
947
948
|
);
|
|
948
949
|
break;
|
|
949
950
|
|
|
951
|
+
case "session.model_changed": {
|
|
952
|
+
// Structured data only — messageTextFromEvent finds nothing, so
|
|
953
|
+
// without this case the generic fallback printed a bare
|
|
954
|
+
// "[session.model_changed]" that named neither model.
|
|
955
|
+
const from = shortModelName(event?.data?.oldModel) || "default";
|
|
956
|
+
const to = shortModelName(event?.data?.newModel) || "default";
|
|
957
|
+
const effort = event?.data?.newReasoningEffort;
|
|
958
|
+
const effortChanged = effort && effort !== event?.data?.oldReasoningEffort;
|
|
959
|
+
const tier = event?.data?.newContextTier;
|
|
960
|
+
const tierChanged = tier && tier !== event?.data?.oldContextTier && tier !== "default";
|
|
961
|
+
const extras = [
|
|
962
|
+
...(effortChanged ? [`effort ${effort}`] : []),
|
|
963
|
+
...(tierChanged ? [`context ${tier}`] : []),
|
|
964
|
+
];
|
|
965
|
+
runs = buildLabeledActivityRuns(
|
|
966
|
+
time,
|
|
967
|
+
"[model]",
|
|
968
|
+
"cyan",
|
|
969
|
+
`${from} → ${to}${extras.length ? ` (${extras.join(", ")})` : ""}`,
|
|
970
|
+
);
|
|
971
|
+
break;
|
|
972
|
+
}
|
|
973
|
+
|
|
950
974
|
case "session.compaction_start":
|
|
951
975
|
case "session.compaction_complete":
|
|
952
976
|
runs = formatCompactionActivityRuns(time, event.eventType, event.data || {});
|
package/ui/core/src/selectors.js
CHANGED
|
@@ -4590,6 +4590,7 @@ const SEQUENCE_ORCHESTRATOR_TYPES = new Set([
|
|
|
4590
4590
|
"spawn",
|
|
4591
4591
|
"cmd_recv",
|
|
4592
4592
|
"cmd_done",
|
|
4593
|
+
"model",
|
|
4593
4594
|
]);
|
|
4594
4595
|
|
|
4595
4596
|
function isSequenceOrchestratorType(type) {
|
|
@@ -4723,6 +4724,20 @@ function mapEventToSequenceEntry(event) {
|
|
|
4723
4724
|
return { ...base, type: "compaction", color: "gray", detail: "compaction…" };
|
|
4724
4725
|
case "session.compaction_complete":
|
|
4725
4726
|
return { ...base, type: "compaction", color: "gray", detail: "compacted" };
|
|
4727
|
+
case "session.model_changed": {
|
|
4728
|
+
// The switch itself already appears as /set_model command rows;
|
|
4729
|
+
// this row is the one that says what actually changed.
|
|
4730
|
+
const from = shortModelName(event?.data?.oldModel) || "default";
|
|
4731
|
+
const to = shortModelName(event?.data?.newModel) || "default";
|
|
4732
|
+
const effort = event?.data?.newReasoningEffort;
|
|
4733
|
+
const effortChanged = effort && effort !== event?.data?.oldReasoningEffort;
|
|
4734
|
+
return {
|
|
4735
|
+
...base,
|
|
4736
|
+
type: "model",
|
|
4737
|
+
color: "cyan",
|
|
4738
|
+
detail: `model ${from} → ${to}${effortChanged ? `:${effort}` : ""}`,
|
|
4739
|
+
};
|
|
4740
|
+
}
|
|
4726
4741
|
case "session.error":
|
|
4727
4742
|
return { ...base, type: "error", color: "red", detail: preview || "error" };
|
|
4728
4743
|
default:
|
package/ui/react/src/web-app.js
CHANGED
|
@@ -193,6 +193,53 @@ function copySessionLinkText(url) {
|
|
|
193
193
|
if (navigator?.clipboard?.writeText) navigator.clipboard.writeText(text).catch(() => {});
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
+
/**
|
|
197
|
+
* One box per entry point, each independently copyable, plus a "Copy all"
|
|
198
|
+
* that takes every labeled line at once.
|
|
199
|
+
*
|
|
200
|
+
* The single shared textarea this replaced forced the sender to hand over
|
|
201
|
+
* both URLs even when they knew which network the recipient was on, and a
|
|
202
|
+
* partial selection out of a monospace blob is fiddly. A sender who knows
|
|
203
|
+
* copies one; a sender who doesn't copies all.
|
|
204
|
+
*
|
|
205
|
+
* Single-origin deployments render exactly one unlabeled row — no labels, no
|
|
206
|
+
* Copy all, nothing to explain.
|
|
207
|
+
*/
|
|
208
|
+
function MultiOriginLinkRows({ url, keyPrefix, copied, onCopy }) {
|
|
209
|
+
const links = buildPortalLinks(url, portalLinkOrigins);
|
|
210
|
+
const selectOnFocus = (event) => event.currentTarget.select();
|
|
211
|
+
if (links.length <= 1) {
|
|
212
|
+
return React.createElement("div", { className: "ps-link-row" },
|
|
213
|
+
React.createElement("input", {
|
|
214
|
+
className: "ps-link-input", readOnly: true, value: url, onFocus: selectOnFocus,
|
|
215
|
+
}),
|
|
216
|
+
React.createElement("button", {
|
|
217
|
+
type: "button", className: "ps-mini-button", onClick: () => onCopy(keyPrefix, url),
|
|
218
|
+
}, copied === keyPrefix ? "Copied" : "Copy"));
|
|
219
|
+
}
|
|
220
|
+
const allKey = `${keyPrefix}:all`;
|
|
221
|
+
return React.createElement("div", { className: "ps-link-origins" },
|
|
222
|
+
links.map((link, index) => {
|
|
223
|
+
const key = `${keyPrefix}:${index}`;
|
|
224
|
+
return React.createElement("div", { className: "ps-link-origin", key },
|
|
225
|
+
React.createElement("div", { className: "ps-link-origin-label" }, link.label),
|
|
226
|
+
React.createElement("div", { className: "ps-link-row" },
|
|
227
|
+
React.createElement("input", {
|
|
228
|
+
className: "ps-link-input", readOnly: true, value: link.url,
|
|
229
|
+
"aria-label": `${link.label} link`, onFocus: selectOnFocus,
|
|
230
|
+
}),
|
|
231
|
+
React.createElement("button", {
|
|
232
|
+
type: "button", className: "ps-mini-button",
|
|
233
|
+
onClick: () => onCopy(key, link.url),
|
|
234
|
+
}, copied === key ? "Copied" : "Copy")));
|
|
235
|
+
}),
|
|
236
|
+
React.createElement("div", { className: "ps-link-copy-all" },
|
|
237
|
+
React.createElement("button", {
|
|
238
|
+
type: "button", className: "ps-mini-button",
|
|
239
|
+
onClick: () => onCopy(allKey, formatPortalLinksForCopy(links)),
|
|
240
|
+
}, copied === allKey ? "Copied all" : "Copy all")));
|
|
241
|
+
}
|
|
242
|
+
|
|
196
243
|
// Best-effort probe: is this session's deep link openable only by the owner/
|
|
197
244
|
// admins right now (private, with no targeted grants)? Used to warn in the
|
|
198
245
|
// copy-link dialog. Failure resolves false (no warning).
|
|
@@ -5222,34 +5269,27 @@ function SessionPane({ controller, actions = null, panelClassName = "", structur
|
|
|
5222
5269
|
// (selectable), confirms the copy, and warns when the link points at a private
|
|
5223
5270
|
// session no one else can open yet.
|
|
5224
5271
|
function SessionLinkModal({ url, warn, onCopyAgain, onClose }) {
|
|
5225
|
-
const
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
5272
|
+
const [copied, setCopied] = React.useState("");
|
|
5273
|
+
const multi = buildPortalLinks(url, portalLinkOrigins).length > 1;
|
|
5274
|
+
const copy = React.useCallback((key, text) => {
|
|
5275
|
+
// onCopyAgain owns the single-origin clipboard write (and its status
|
|
5276
|
+
// line); the per-origin buttons write their own one URL.
|
|
5277
|
+
if (key === "session" && !multi) { onCopyAgain?.(); }
|
|
5278
|
+
else if (navigator?.clipboard?.writeText) navigator.clipboard.writeText(text).catch(() => {});
|
|
5279
|
+
setCopied(key);
|
|
5280
|
+
window.setTimeout(() => setCopied(""), 1500);
|
|
5281
|
+
}, [multi, onCopyAgain]);
|
|
5230
5282
|
const stop = (e) => e.stopPropagation();
|
|
5231
5283
|
return React.createElement("div", { className: "ps-share-overlay", onClick: onClose },
|
|
5232
5284
|
React.createElement("div", { className: "ps-link-modal", onClick: stop },
|
|
5233
5285
|
React.createElement("div", { className: "ps-share-modal-head" },
|
|
5234
|
-
React.createElement("span", null,
|
|
5286
|
+
React.createElement("span", null, multi ? "Session links copied" : "Link copied"),
|
|
5235
5287
|
React.createElement("button", { className: "ps-modal-close", onClick: onClose, "aria-label": "Close", title: "Close" }, "✕")),
|
|
5236
5288
|
React.createElement("div", { className: "ps-share-section-sub" },
|
|
5237
|
-
|
|
5238
|
-
? "All entry-point links were copied
|
|
5289
|
+
multi
|
|
5290
|
+
? "All entry-point links were copied. Copy just the one your recipient's network can reach, or take both."
|
|
5239
5291
|
: "Copied to your clipboard — anyone with access can open the session from this link."),
|
|
5240
|
-
React.createElement(
|
|
5241
|
-
portalLinkOrigins.length >= 2
|
|
5242
|
-
? React.createElement("textarea", {
|
|
5243
|
-
ref: inputRef, className: "ps-link-input", readOnly: true,
|
|
5244
|
-
rows: buildPortalLinks(url, portalLinkOrigins).length,
|
|
5245
|
-
value: formatPortalLinksForCopy(buildPortalLinks(url, portalLinkOrigins)),
|
|
5246
|
-
onFocus: () => inputRef.current?.select(),
|
|
5247
|
-
})
|
|
5248
|
-
: React.createElement("input", {
|
|
5249
|
-
ref: inputRef, className: "ps-link-input", readOnly: true, value: url,
|
|
5250
|
-
onFocus: () => inputRef.current?.select(),
|
|
5251
|
-
}),
|
|
5252
|
-
React.createElement("button", { className: "ps-mini-button", onClick: onCopyAgain }, "Copy")),
|
|
5292
|
+
React.createElement(MultiOriginLinkRows, { url, keyPrefix: "session", copied, onCopy: copy }),
|
|
5253
5293
|
warn
|
|
5254
5294
|
? React.createElement("div", { className: "ps-link-warn" }, SESSION_LINK_PRIVATE_WARNING)
|
|
5255
5295
|
: null));
|
|
@@ -6273,6 +6313,71 @@ function MobileArtifactOverlay({ controller }) {
|
|
|
6273
6313
|
})));
|
|
6274
6314
|
}
|
|
6275
6315
|
|
|
6316
|
+
// How much visual-viewport height must vanish before we call it a keyboard.
|
|
6317
|
+
// Smaller drops (URL-bar churn, iOS toolbars settling) stay under this.
|
|
6318
|
+
const KEYBOARD_TAKEOVER_MIN_SHRINK_PX = 140;
|
|
6319
|
+
|
|
6320
|
+
/**
|
|
6321
|
+
* Pure decision for the keyboard takeover, split out for tests. Returns the
|
|
6322
|
+
* next {baseline, takeover}. The keyboard signal is a visual-viewport height
|
|
6323
|
+
* drop from the tallest height seen at the current width; a width change is
|
|
6324
|
+
* a rotation and resets the baseline. window.innerHeight is NOT a usable
|
|
6325
|
+
* baseline: Android's interactive-widget=resizes-content shrinks it together
|
|
6326
|
+
* with the keyboard, which would read as "no shrink".
|
|
6327
|
+
*/
|
|
6328
|
+
export function evaluateKeyboardTakeover(baseline, viewportWidth, viewportHeight, composerFocused) {
|
|
6329
|
+
let nextBaseline = baseline;
|
|
6330
|
+
if (!baseline || Math.abs(viewportWidth - baseline.width) > 2) {
|
|
6331
|
+
nextBaseline = { width: viewportWidth, height: viewportHeight };
|
|
6332
|
+
} else if (viewportHeight > baseline.height) {
|
|
6333
|
+
nextBaseline = { width: baseline.width, height: viewportHeight };
|
|
6334
|
+
}
|
|
6335
|
+
const shrunk = viewportHeight <= nextBaseline.height - KEYBOARD_TAKEOVER_MIN_SHRINK_PX;
|
|
6336
|
+
return { baseline: nextBaseline, takeover: shrunk && composerFocused };
|
|
6337
|
+
}
|
|
6338
|
+
|
|
6339
|
+
/**
|
|
6340
|
+
* True while the on-screen keyboard is up AND the chat composer summoned it.
|
|
6341
|
+
* Both conditions matter: height alone would fire for a modal's text field
|
|
6342
|
+
* and collapse the workspace behind the modal; focus alone would fire for
|
|
6343
|
+
* hardware keyboards that shrink nothing. State-driven on the keyboard
|
|
6344
|
+
* itself, so it reverts the moment the keyboard goes away — including the
|
|
6345
|
+
* iOS swipe-dismiss that closes the keyboard without blurring the input.
|
|
6346
|
+
*/
|
|
6347
|
+
function useKeyboardTakeover(enabled) {
|
|
6348
|
+
const [takeover, setTakeover] = React.useState(false);
|
|
6349
|
+
React.useEffect(() => {
|
|
6350
|
+
if (!enabled || typeof window === "undefined" || !window.visualViewport) {
|
|
6351
|
+
setTakeover(false);
|
|
6352
|
+
return undefined;
|
|
6353
|
+
}
|
|
6354
|
+
const viewport = window.visualViewport;
|
|
6355
|
+
let baseline = { width: viewport.width, height: viewport.height };
|
|
6356
|
+
let frame = 0;
|
|
6357
|
+
const evaluate = () => {
|
|
6358
|
+
frame = 0;
|
|
6359
|
+
const composerFocused = Boolean(document.activeElement?.classList?.contains("ps-prompt-input"));
|
|
6360
|
+
const next = evaluateKeyboardTakeover(baseline, viewport.width, viewport.height, composerFocused);
|
|
6361
|
+
baseline = next.baseline;
|
|
6362
|
+
setTakeover(next.takeover);
|
|
6363
|
+
};
|
|
6364
|
+
// rAF-deferred: focusout fires while activeElement is mid-transition,
|
|
6365
|
+
// and visualViewport resize storms during the keyboard animation.
|
|
6366
|
+
const schedule = () => { if (!frame) frame = requestAnimationFrame(evaluate); };
|
|
6367
|
+
evaluate();
|
|
6368
|
+
viewport.addEventListener("resize", schedule);
|
|
6369
|
+
window.addEventListener("focusin", schedule);
|
|
6370
|
+
window.addEventListener("focusout", schedule);
|
|
6371
|
+
return () => {
|
|
6372
|
+
if (frame) cancelAnimationFrame(frame);
|
|
6373
|
+
viewport.removeEventListener("resize", schedule);
|
|
6374
|
+
window.removeEventListener("focusin", schedule);
|
|
6375
|
+
window.removeEventListener("focusout", schedule);
|
|
6376
|
+
};
|
|
6377
|
+
}, [enabled]);
|
|
6378
|
+
return enabled ? takeover : false;
|
|
6379
|
+
}
|
|
6380
|
+
|
|
6276
6381
|
/**
|
|
6277
6382
|
* The phone's Main pane, in one of three layouts cycled by the Main toolbar
|
|
6278
6383
|
* button: split (sessions + chat), chat only, sessions only (list + the
|
|
@@ -6386,6 +6491,13 @@ function CanvasLinkGlyph() {
|
|
|
6386
6491
|
* Link management is a session:manage operation server-side; anyone else
|
|
6387
6492
|
* sees the server's refusal inline.
|
|
6388
6493
|
*/
|
|
6494
|
+
// Tab labels name the AUDIENCE, not the mechanism — the sharer is choosing
|
|
6495
|
+
// who should be able to open this, not which token scheme to use.
|
|
6496
|
+
const CANVAS_SHARE_TABS = [
|
|
6497
|
+
{ id: "session", label: "Session access" },
|
|
6498
|
+
{ id: "public", label: "Anyone with link" },
|
|
6499
|
+
];
|
|
6500
|
+
|
|
6389
6501
|
function CanvasShareDialog({ controller, sessionId, slot, onClose }) {
|
|
6390
6502
|
const [info, setInfo] = React.useState(null); // { exists, createdAt } | null while loading
|
|
6391
6503
|
const [freshLink, setFreshLink] = React.useState(null); // the just-minted URL, shown once
|
|
@@ -6393,37 +6505,19 @@ function CanvasShareDialog({ controller, sessionId, slot, onClose }) {
|
|
|
6393
6505
|
const [error, setError] = React.useState("");
|
|
6394
6506
|
const [copied, setCopied] = React.useState("");
|
|
6395
6507
|
|
|
6508
|
+
// Which kind of link the dialog is showing. Two tabs rather than two
|
|
6509
|
+
// stacked sections: the choice between "people who already have session
|
|
6510
|
+
// access" and "anyone holding this token" is the decision the sharer is
|
|
6511
|
+
// making, and stacking them put a destructive Reset next to an innocuous
|
|
6512
|
+
// deep link. Mirrors the Manage-session dialog's General/Access tabs.
|
|
6513
|
+
const [tab, setTab] = React.useState("session");
|
|
6396
6514
|
const transport = controller.transport;
|
|
6397
6515
|
const sessionLink = `${window.location.origin}/?session=${encodeURIComponent(sessionId)}&view=canvas&slot=${slot}&max=1`;
|
|
6398
|
-
//
|
|
6399
|
-
// variant, ONE copy that takes all of them — the sender does not know
|
|
6400
|
-
// which entry point the recipient can reach, so they paste both. The
|
|
6401
|
-
// token variants all resolve the same hashed row: one token, N doors,
|
|
6516
|
+
// The token variants all resolve the same hashed row: one token, N doors,
|
|
6402
6517
|
// single-switch revocation whichever door the bearer uses.
|
|
6403
|
-
const linkRows = (url, keyPrefix) => {
|
|
6404
|
-
|
|
6405
|
-
|
|
6406
|
-
return React.createElement("div", { className: "ps-canvas-share-row" },
|
|
6407
|
-
React.createElement("code", { className: "ps-canvas-share-url" }, url),
|
|
6408
|
-
React.createElement("button", {
|
|
6409
|
-
type: "button", className: "ps-mini-button",
|
|
6410
|
-
onClick: () => copy(keyPrefix, url),
|
|
6411
|
-
}, copied === keyPrefix ? "Copied" : "Copy"));
|
|
6412
|
-
}
|
|
6413
|
-
const text = formatPortalLinksForCopy(links);
|
|
6414
|
-
return React.createElement("div", { className: "ps-canvas-share-row" },
|
|
6415
|
-
React.createElement("textarea", {
|
|
6416
|
-
className: "ps-link-input",
|
|
6417
|
-
readOnly: true,
|
|
6418
|
-
rows: links.length,
|
|
6419
|
-
value: text,
|
|
6420
|
-
onFocus: (event) => event.currentTarget.select(),
|
|
6421
|
-
}),
|
|
6422
|
-
React.createElement("button", {
|
|
6423
|
-
type: "button", className: "ps-mini-button",
|
|
6424
|
-
onClick: () => copy(keyPrefix, text),
|
|
6425
|
-
}, copied === keyPrefix ? "Copied" : "Copy"));
|
|
6426
|
-
};
|
|
6518
|
+
const linkRows = (url, keyPrefix) => React.createElement(MultiOriginLinkRows, {
|
|
6519
|
+
url, keyPrefix, copied, onCopy: copy,
|
|
6520
|
+
});
|
|
6427
6521
|
|
|
6428
6522
|
const refresh = React.useCallback(() => {
|
|
6429
6523
|
transport.getCanvasShareLink?.(sessionId, slot)
|
|
@@ -6464,32 +6558,55 @@ function CanvasShareDialog({ controller, sessionId, slot, onClose }) {
|
|
|
6464
6558
|
"Share this canvas",
|
|
6465
6559
|
React.createElement("button", { type: "button", className: "ps-mini-button", onClick: onClose, "aria-label": "Close" }, "✕")),
|
|
6466
6560
|
|
|
6467
|
-
React.createElement("div", { className: "ps-
|
|
6468
|
-
React.createElement("
|
|
6469
|
-
|
|
6470
|
-
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
|
|
6474
|
-
|
|
6475
|
-
|
|
6476
|
-
|
|
6477
|
-
|
|
6478
|
-
|
|
6479
|
-
|
|
6480
|
-
|
|
6481
|
-
|
|
6482
|
-
|
|
6483
|
-
|
|
6484
|
-
|
|
6485
|
-
|
|
6486
|
-
|
|
6487
|
-
React.createElement("div", {
|
|
6488
|
-
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6492
|
-
|
|
6561
|
+
React.createElement("div", { className: "ps-manage-tabs", role: "tablist" },
|
|
6562
|
+
CANVAS_SHARE_TABS.map((t) => React.createElement("button", {
|
|
6563
|
+
key: t.id,
|
|
6564
|
+
type: "button",
|
|
6565
|
+
role: "tab",
|
|
6566
|
+
"aria-selected": tab === t.id ? "true" : "false",
|
|
6567
|
+
className: `ps-manage-tab${tab === t.id ? " is-active" : ""}`,
|
|
6568
|
+
onClick: () => setTab(t.id),
|
|
6569
|
+
}, t.label))),
|
|
6570
|
+
|
|
6571
|
+
// Both panels are always rendered, stacked in one grid cell, with
|
|
6572
|
+
// the inactive one held at visibility:hidden. It still occupies
|
|
6573
|
+
// its space, so the dialog is always as tall as the TALLER tab and
|
|
6574
|
+
// switching tabs never resizes the box. Sizing this way (rather
|
|
6575
|
+
// than a min-height guess) also stays correct when the panels grow:
|
|
6576
|
+
// one link box on a single-origin deployment, two plus Copy all on
|
|
6577
|
+
// a multi-origin one. visibility:hidden also takes the hidden
|
|
6578
|
+
// panel's inputs and buttons out of the tab order and the
|
|
6579
|
+
// accessibility tree, so nothing offscreen is reachable.
|
|
6580
|
+
React.createElement("div", { className: "ps-canvas-share-panels" },
|
|
6581
|
+
React.createElement("div", {
|
|
6582
|
+
className: `ps-canvas-share-panel${tab === "session" ? " is-active" : ""}`,
|
|
6583
|
+
role: "tabpanel", "aria-hidden": tab === "session" ? undefined : "true",
|
|
6584
|
+
},
|
|
6585
|
+
React.createElement("div", { className: "ps-canvas-share-sub" }, "Opens the portal signed in, canvas full screen. Session visibility rules apply."),
|
|
6586
|
+
linkRows(sessionLink, "session")),
|
|
6587
|
+
React.createElement("div", {
|
|
6588
|
+
className: `ps-canvas-share-panel${tab === "public" ? " is-active" : ""}`,
|
|
6589
|
+
role: "tabpanel", "aria-hidden": tab === "public" ? undefined : "true",
|
|
6590
|
+
},
|
|
6591
|
+
React.createElement("div", { className: "ps-canvas-share-sub" },
|
|
6592
|
+
"View only, live, no sign-in. One link at a time — resetting makes the previous link stop working immediately."),
|
|
6593
|
+
info === null
|
|
6594
|
+
? React.createElement("div", { className: "ps-canvas-share-sub" }, "Checking…")
|
|
6595
|
+
: freshLink
|
|
6596
|
+
? React.createElement(React.Fragment, null,
|
|
6597
|
+
linkRows(freshLink, "public"),
|
|
6598
|
+
React.createElement("div", { className: "ps-canvas-share-sub is-warn" },
|
|
6599
|
+
"Copy it now — the link is shown only this once."))
|
|
6600
|
+
: info.exists
|
|
6601
|
+
? React.createElement("div", { className: "ps-canvas-share-sub" },
|
|
6602
|
+
`A link exists${info.createdAt ? ` (created ${new Date(info.createdAt).toLocaleString()})` : ""}. For safety it cannot be re-shown — Reset to get a new one.`)
|
|
6603
|
+
: React.createElement("div", { className: "ps-canvas-share-sub" }, "No public link yet."),
|
|
6604
|
+
React.createElement("div", { className: "ps-canvas-share-actions" },
|
|
6605
|
+
React.createElement("button", { type: "button", className: "ps-mini-button", disabled: busy, onClick: () => mint(info?.exists) },
|
|
6606
|
+
info?.exists ? "Reset link" : "Create link"),
|
|
6607
|
+
info?.exists
|
|
6608
|
+
? React.createElement("button", { type: "button", className: "ps-mini-button", disabled: busy, onClick: remove }, "Remove link")
|
|
6609
|
+
: null))),
|
|
6493
6610
|
error ? React.createElement("div", { className: "ps-canvas-share-error" }, error) : null));
|
|
6494
6611
|
}
|
|
6495
6612
|
|
|
@@ -10993,6 +11110,25 @@ export function PilotSwarmWebApp({ controller }) {
|
|
|
10993
11110
|
|
|
10994
11111
|
useKeyboardShortcuts(controller, mobile);
|
|
10995
11112
|
|
|
11113
|
+
// Keyboard takeover (phone): while the on-screen keyboard is up and the
|
|
11114
|
+
// composer summoned it, the conversation owns the visual viewport — the
|
|
11115
|
+
// portal header, toolbar and session list fold away via a body class and
|
|
11116
|
+
// the transcript snaps to newest. The chat pane's own header stays as the
|
|
11117
|
+
// context strip (session title · status · model), and tapping anywhere
|
|
11118
|
+
// outside the composer dismisses the keyboard and restores everything.
|
|
11119
|
+
const keyboardTakeover = useKeyboardTakeover(mobile && mobilePane === "workspace" && !state.adminVisible);
|
|
11120
|
+
React.useEffect(() => {
|
|
11121
|
+
if (typeof document === "undefined") return undefined;
|
|
11122
|
+
document.body.classList.toggle("ps-kb-takeover", keyboardTakeover);
|
|
11123
|
+
return () => document.body.classList.remove("ps-kb-takeover");
|
|
11124
|
+
}, [keyboardTakeover]);
|
|
11125
|
+
React.useEffect(() => {
|
|
11126
|
+
if (!keyboardTakeover) return;
|
|
11127
|
+
// Typing means replying to the newest message; a transcript left
|
|
11128
|
+
// scrolled to last week would have the user typing blind.
|
|
11129
|
+
controller.applyPaneVisualScrollOffset?.("chat", 0, { followBottom: true });
|
|
11130
|
+
}, [keyboardTakeover, controller]);
|
|
11131
|
+
|
|
10996
11132
|
// The agent-driven canvas flip, phone edition. The desktop column follows
|
|
10997
11133
|
// ui.rightPaneMode by itself; the phone's pane lives in local tab state,
|
|
10998
11134
|
// so it follows the flip TICK instead (which fires even when the mode was
|
package/web/dist/assets/{abnfDiagram-VRR7QNED-kpxu_PEa.js → abnfDiagram-VRR7QNED-Jh9nLlRI.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-WrEHfiAj.js";import{p as f}from"./chunk-JWPE2WC7-CASBfQW6.js";import{_ as n,l as o}from"./mermaid.core-CApAWULn.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-CzUocqvb.js";import"./pilotswarm-DETFHWYc.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-CApAWULn.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};
|