pilotswarm 0.5.37 → 0.5.38
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 +3 -3
- package/ui/core/src/controller.js +97 -20
- package/ui/core/src/reducer.js +213 -15
- package/ui/core/src/selectors.js +83 -3
- package/ui/core/src/state.js +90 -2
- package/ui/core/src/themes/index.js +1 -1
- package/ui/react/src/web-app.js +1038 -218
- package/web/auth/config.js +3 -0
- package/web/auth/index.js +8 -1
- package/web/auth/normalize/proxy.js +48 -0
- package/web/auth/providers/proxy.js +141 -0
- package/web/dist/assets/{abnfDiagram-VRR7QNED-DlvPH-8O.js → abnfDiagram-VRR7QNED-DrJhXhSQ.js} +1 -1
- package/web/dist/assets/{arc-r1liz5e5.js → arc-BEaG9DWd.js} +1 -1
- package/web/dist/assets/{architectureDiagram-ZJ3FMSHR-Bci5dNH3.js → architectureDiagram-ZJ3FMSHR-D9fc1Imx.js} +1 -1
- package/web/dist/assets/{blockDiagram-677ZJIJ3-Bug32AXp.js → blockDiagram-677ZJIJ3-rS5Eikvt.js} +1 -1
- package/web/dist/assets/{c4Diagram-LMCZKHZV-DwxSFqgE.js → c4Diagram-LMCZKHZV-HKLlX5cR.js} +1 -1
- package/web/dist/assets/channel-DRy7FvyF.js +1 -0
- package/web/dist/assets/{chunk-2Q5K7J3B-B_dbI_xg.js → chunk-2Q5K7J3B-kq0TyLSB.js} +1 -1
- package/web/dist/assets/{chunk-32BRIVSS-BkF68W-R.js → chunk-32BRIVSS-O-LMarT5.js} +1 -1
- package/web/dist/assets/{chunk-5VM5RSS4-BSbNIbJu.js → chunk-5VM5RSS4-Di4h0CAu.js} +1 -1
- package/web/dist/assets/{chunk-EX3LRPZG-Blv_Iqa2.js → chunk-EX3LRPZG-C8rgqUOt.js} +1 -1
- package/web/dist/assets/{chunk-JWPE2WC7-Dk_dBFKd.js → chunk-JWPE2WC7-BSH41q4T.js} +1 -1
- package/web/dist/assets/{chunk-MOJQB5TN-DqNFBrfw.js → chunk-MOJQB5TN-BAFuQHAC.js} +1 -1
- package/web/dist/assets/{chunk-RYQCIY6F-Dlv7Svpb.js → chunk-RYQCIY6F-DAg6JOs7.js} +1 -1
- package/web/dist/assets/{chunk-V7JOEXUC-DozGikwu.js → chunk-V7JOEXUC-DbVrT8BG.js} +1 -1
- package/web/dist/assets/{chunk-VR4S4FIN-CmkqvGT4.js → chunk-VR4S4FIN-C6f5_Grp.js} +1 -1
- package/web/dist/assets/{chunk-XXDRQBXY-DyByai5N.js → chunk-XXDRQBXY-CqcCYpqA.js} +1 -1
- package/web/dist/assets/classDiagram-OUVF2IWQ-C35RhB8X.js +1 -0
- package/web/dist/assets/classDiagram-v2-EOCWNBFH-C35RhB8X.js +1 -0
- package/web/dist/assets/{cose-bilkent-JH36ORCC-Bv-gRVvA.js → cose-bilkent-JH36ORCC-DJw04eFh.js} +1 -1
- package/web/dist/assets/{cynefin-VYW2F7L2-DRnAsyZU.js → cynefin-VYW2F7L2-CpjwdEIU.js} +1 -1
- package/web/dist/assets/{cynefinDiagram-TSTJHNR4-B1fnUtjo.js → cynefinDiagram-TSTJHNR4-RqEIWoT0.js} +1 -1
- package/web/dist/assets/{dagre-VKFMJZFB-DM6-QENB.js → dagre-VKFMJZFB-C1eGQNK2.js} +1 -1
- package/web/dist/assets/{diagram-FQU43EPY-BPxxnLdU.js → diagram-FQU43EPY-BODLQ7dz.js} +1 -1
- package/web/dist/assets/{diagram-G47NLZAW-BgtJT3qF.js → diagram-G47NLZAW-DlhmukMC.js} +1 -1
- package/web/dist/assets/{diagram-NH7WQ7WH-uekeIzsy.js → diagram-NH7WQ7WH-Ba_jZoCN.js} +1 -1
- package/web/dist/assets/{diagram-OA4YK3LP-BVy3JZWE.js → diagram-OA4YK3LP-DnSiAJBG.js} +1 -1
- package/web/dist/assets/{diagram-WEI45ONY-BWdjUr32.js → diagram-WEI45ONY-B3KoQ7_W.js} +1 -1
- package/web/dist/assets/{ebnfDiagram-CCIWWBDH-DD4fwhNK.js → ebnfDiagram-CCIWWBDH-ChnFc5gf.js} +1 -1
- package/web/dist/assets/{erDiagram-Q63AITRT-BllD_6Kh.js → erDiagram-Q63AITRT-D2KkJXLZ.js} +1 -1
- package/web/dist/assets/{flowDiagram-23GEKE2U-QEYKkAUN.js → flowDiagram-23GEKE2U-CmybZufj.js} +1 -1
- package/web/dist/assets/{ganttDiagram-NO4QXBWP-uZcfKTSW.js → ganttDiagram-NO4QXBWP-BzPurW_v.js} +1 -1
- package/web/dist/assets/{gitGraphDiagram-IHSO6WYX-XPdbPaH-.js → gitGraphDiagram-IHSO6WYX-DAbXl4gO.js} +1 -1
- package/web/dist/assets/{index-D1itTxvB.js → index-CRY94nFp.js} +6 -6
- package/web/dist/assets/index-DtL0lbis.css +1 -0
- package/web/dist/assets/{infoDiagram-FWYZ7A6U-DXCnQOJs.js → infoDiagram-FWYZ7A6U-C6qGjNA1.js} +1 -1
- package/web/dist/assets/{ishikawaDiagram-FXEZZL3T-687_4FBy.js → ishikawaDiagram-FXEZZL3T-D2d1tO-9.js} +1 -1
- package/web/dist/assets/{journeyDiagram-5HDEW3XC-GXlKuda8.js → journeyDiagram-5HDEW3XC-fP13w1b7.js} +1 -1
- package/web/dist/assets/{kanban-definition-HUTT4EX6-C38-2DvN.js → kanban-definition-HUTT4EX6-BJfWAXZ0.js} +1 -1
- package/web/dist/assets/{linear-lGPXiBcz.js → linear-CltApkHf.js} +1 -1
- package/web/dist/assets/{mermaid.core-C_neEtab.js → mermaid.core-B1Dwetk3.js} +4 -4
- package/web/dist/assets/{mindmap-definition-LN4V7U3C-BaJ9tpEG.js → mindmap-definition-LN4V7U3C-CdRUD7LF.js} +1 -1
- package/web/dist/assets/{papaparse.min-rDwKYbBf.js → papaparse.min-C1y3wBH1.js} +1 -1
- package/web/dist/assets/{pegDiagram-2B236MQR-BdXJLYgY.js → pegDiagram-2B236MQR-CeQkqN6Q.js} +1 -1
- package/web/dist/assets/{pieDiagram-ENE6RG2P-DU19t6fM.js → pieDiagram-ENE6RG2P-Dqgc87jA.js} +1 -1
- package/web/dist/assets/pilotswarm-DayYdi39.js +96 -0
- package/web/dist/assets/{quadrantDiagram-ABIIQ3AL-CBkOdPp0.js → quadrantDiagram-ABIIQ3AL-CD7f-w6m.js} +1 -1
- package/web/dist/assets/{railroadDiagram-RFXS5EU6-D2DMcGDw.js → railroadDiagram-RFXS5EU6-CcsAijSC.js} +1 -1
- package/web/dist/assets/{requirementDiagram-TGXJPOKE-Bx9tF1pr.js → requirementDiagram-TGXJPOKE-BkzF80pL.js} +1 -1
- package/web/dist/assets/{sankeyDiagram-HTMAVEWB-DcLlRfsi.js → sankeyDiagram-HTMAVEWB-D9XOFw7Y.js} +1 -1
- package/web/dist/assets/{sequenceDiagram-DBY2YBRQ-xr6UVRBO.js → sequenceDiagram-DBY2YBRQ-BFfaS_Sz.js} +1 -1
- package/web/dist/assets/{sizeCapture-X5ZJPWSS-0fUkSXmg.js → sizeCapture-X5ZJPWSS-CDJV16tP.js} +1 -1
- package/web/dist/assets/{stateDiagram-2N3HPSRC-BWgJGGpg.js → stateDiagram-2N3HPSRC-C0E-MPXO.js} +1 -1
- package/web/dist/assets/stateDiagram-v2-6OUMAXLB-BMqXeMJu.js +1 -0
- package/web/dist/assets/{swimlanes-5IMT3BWC-CZKya4_i.js → swimlanes-5IMT3BWC-n5Vsv7n9.js} +2 -2
- package/web/dist/assets/swimlanesDiagram-G3AALYLV-CGl4gRnH.js +8 -0
- package/web/dist/assets/{timeline-definition-FHXFAJF6-Df8BpeAu.js → timeline-definition-FHXFAJF6-DW2gV8-n.js} +1 -1
- package/web/dist/assets/{vennDiagram-L72KCM5P-ChX5bjT6.js → vennDiagram-L72KCM5P-D9dbDm08.js} +1 -1
- package/web/dist/assets/{wardleyDiagram-EHGQE667-Dr48BgaJ.js → wardleyDiagram-EHGQE667-CIcG7fiC.js} +1 -1
- package/web/dist/assets/{xychartDiagram-FW5EYKEG-Cia_MFfc.js → xychartDiagram-FW5EYKEG-elEIFsc9.js} +1 -1
- package/web/dist/index.html +3 -3
- package/web/dist/assets/channel-jVpSYat3.js +0 -1
- package/web/dist/assets/classDiagram-OUVF2IWQ-C78zSajE.js +0 -1
- package/web/dist/assets/classDiagram-v2-EOCWNBFH-C78zSajE.js +0 -1
- package/web/dist/assets/index-BuDSoRIL.css +0 -1
- package/web/dist/assets/pilotswarm-BNKGG936.js +0 -96
- package/web/dist/assets/stateDiagram-v2-6OUMAXLB-DmAC8DdB.js +0 -1
- package/web/dist/assets/swimlanesDiagram-G3AALYLV-CVYx20_X.js +0 -8
package/ui/core/src/selectors.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { INSPECTOR_TABS, FOCUS_REGIONS } from "./commands.js";
|
|
2
|
+
import { canvasKey as canvasSlotKey, parseCanvasKey } from "./state.js";
|
|
2
3
|
import { isManuallyOrderableSession } from "./session-tree.js";
|
|
3
4
|
import {
|
|
4
5
|
createSplashCard,
|
|
@@ -1125,6 +1126,10 @@ export function selectSessionRows(state) {
|
|
|
1125
1126
|
// built under one branding to a caller using another, and the root
|
|
1126
1127
|
// session's name would flip between them.
|
|
1127
1128
|
state.branding?.title,
|
|
1129
|
+
// The canvas marker below reads these. Without them the memo hands
|
|
1130
|
+
// back a row built before the draw and the marker never appears.
|
|
1131
|
+
state.canvas?.bySessionId?.[entry.sessionId],
|
|
1132
|
+
state.canvas?.prefs?.[entry.sessionId],
|
|
1128
1133
|
];
|
|
1129
1134
|
const cached = memo.get(entry.sessionId);
|
|
1130
1135
|
if (cached && sameRowDeps(cached.deps, deps)) return cached.row;
|
|
@@ -1160,6 +1165,15 @@ export function selectSessionRows(state) {
|
|
|
1160
1165
|
: null,
|
|
1161
1166
|
orderable: isManuallyOrderableSession(session),
|
|
1162
1167
|
orderContainer: manualOrderContainerKey(session, pinned),
|
|
1168
|
+
// Canvas state for THIS row. The toolbar badge answers the same
|
|
1169
|
+
// question for the active session only; the list has to answer it
|
|
1170
|
+
// for every session at once, which is the point — a canvas drawn
|
|
1171
|
+
// in a session you are not looking at is otherwise invisible.
|
|
1172
|
+
//
|
|
1173
|
+
// null no canvas, or one that was cleared
|
|
1174
|
+
// "canvas" a canvas exists and nothing is new
|
|
1175
|
+
// "unseen" it changed since this user last looked at it
|
|
1176
|
+
canvasMark: sessionCanvasMark(state, entry.sessionId),
|
|
1163
1177
|
};
|
|
1164
1178
|
memo.set(entry.sessionId, { deps, row });
|
|
1165
1179
|
return row;
|
|
@@ -2661,21 +2675,87 @@ export function selectChatLines(state, maxWidth = 80, options = {}) {
|
|
|
2661
2675
|
* whether the yellow unseen-changes badge should light
|
|
2662
2676
|
* (latestRev > lastViewedRev, and only while the canvas is not on screen).
|
|
2663
2677
|
*/
|
|
2678
|
+
/**
|
|
2679
|
+
* The canvas marker for one session row.
|
|
2680
|
+
*
|
|
2681
|
+
* Same rules selectCanvasView applies to the active session, minus the
|
|
2682
|
+
* on-screen check: a row's marker describes the SESSION, not the layout, so it
|
|
2683
|
+
* does not care which column happens to be open.
|
|
2684
|
+
*
|
|
2685
|
+
* A cleared canvas (draw_canvas("") -> sizeBytes 0) no longer exists. Unknown
|
|
2686
|
+
* size (null, from a degraded snapshot) is presumed drawn — a marker that is
|
|
2687
|
+
* occasionally early beats one that silently never shows.
|
|
2688
|
+
*/
|
|
2689
|
+
export function sessionCanvasMark(state, sessionId) {
|
|
2690
|
+
if (!sessionId) return null;
|
|
2691
|
+
// Aggregate across the session's slots: ANY unseen slot lights the dot;
|
|
2692
|
+
// any drawn slot at all marks the row. Slot 1 is the bare id key.
|
|
2693
|
+
let mark = null;
|
|
2694
|
+
for (let slot = 1; slot <= 5; slot += 1) {
|
|
2695
|
+
const key = canvasSlotKey(sessionId, slot);
|
|
2696
|
+
const entry = state?.canvas?.bySessionId?.[key];
|
|
2697
|
+
const prefs = state?.canvas?.prefs?.[key];
|
|
2698
|
+
if (!entry) {
|
|
2699
|
+
// No live state loaded (cold page). canvasPrefs persist per user,
|
|
2700
|
+
// so a slot this user has ever VIEWED still marks — plain, never
|
|
2701
|
+
// "unseen": whether it changed since is unknowable client-side.
|
|
2702
|
+
if ((prefs?.lastViewedRev || 0) > 0) mark = mark || "canvas";
|
|
2703
|
+
continue;
|
|
2704
|
+
}
|
|
2705
|
+
const latestRev = entry.latestRev || 0;
|
|
2706
|
+
if (latestRev <= 0 || entry.sizeBytes === 0) continue;
|
|
2707
|
+
const unseen = latestRev > (prefs?.lastViewedRev || 0)
|
|
2708
|
+
|| (entry.latestDataRev || 0) > (prefs?.lastViewedDataRev || 0);
|
|
2709
|
+
if (unseen) return "unseen";
|
|
2710
|
+
mark = "canvas";
|
|
2711
|
+
}
|
|
2712
|
+
return mark;
|
|
2713
|
+
}
|
|
2714
|
+
|
|
2664
2715
|
export function selectCanvasView(state) {
|
|
2665
2716
|
const sessionId = state?.sessions?.activeSessionId || null;
|
|
2666
|
-
|
|
2667
|
-
|
|
2717
|
+
// The pane shows ONE slot at a time. An out-of-range or never-drawn slot
|
|
2718
|
+
// falls back to 1 so a stale selection can never strand the pane.
|
|
2719
|
+
const wantedSlot = Number(state?.ui?.canvasSlot) || 1;
|
|
2720
|
+
const bySessionId = state?.canvas?.bySessionId || {};
|
|
2721
|
+
// Every drawn slot of the active session, for the selector and arrows.
|
|
2722
|
+
const slots = [];
|
|
2723
|
+
if (sessionId) {
|
|
2724
|
+
for (let slot = 1; slot <= 5; slot += 1) {
|
|
2725
|
+
const e = bySessionId[canvasSlotKey(sessionId, slot)];
|
|
2726
|
+
if (!e || (e.latestRev || 0) <= 0 || e.sizeBytes === 0) continue;
|
|
2727
|
+
const p = state?.canvas?.prefs?.[canvasSlotKey(sessionId, slot)];
|
|
2728
|
+
slots.push({
|
|
2729
|
+
slot,
|
|
2730
|
+
name: typeof e.name === "string" ? e.name : "",
|
|
2731
|
+
latestRev: e.latestRev || 0,
|
|
2732
|
+
unseen: (e.latestRev || 0) > (p?.lastViewedRev || 0)
|
|
2733
|
+
|| (e.latestDataRev || 0) > (p?.lastViewedDataRev || 0),
|
|
2734
|
+
});
|
|
2735
|
+
}
|
|
2736
|
+
}
|
|
2737
|
+
const slot = slots.some((s2) => s2.slot === wantedSlot) ? wantedSlot : 1;
|
|
2738
|
+
const key = sessionId ? canvasSlotKey(sessionId, slot) : null;
|
|
2739
|
+
const entry = key ? bySessionId[key] : null;
|
|
2740
|
+
const prefs = key ? state?.canvas?.prefs?.[key] : null;
|
|
2668
2741
|
const latestRev = entry?.latestRev || 0;
|
|
2669
2742
|
const lastViewedRev = prefs?.lastViewedRev || 0;
|
|
2670
2743
|
const latestDataRev = entry?.latestDataRev || 0;
|
|
2671
2744
|
const lastViewedDataRev = prefs?.lastViewedDataRev || 0;
|
|
2672
|
-
|
|
2745
|
+
// Read from canvasOpen, not the retired rightPaneMode enum. Diagnostics
|
|
2746
|
+
// moving to its own column means "not canvas" no longer implies "panes",
|
|
2747
|
+
// and this drives the unseen badge, which must light whenever the canvas
|
|
2748
|
+
// is off screen.
|
|
2749
|
+
const mode = state?.ui?.canvasOpen ? "canvas" : "panes";
|
|
2673
2750
|
// A cleared canvas (draw_canvas("") → sizeBytes 0) no longer exists for
|
|
2674
2751
|
// affordance purposes: no phone tab, no badge, blank teaching state.
|
|
2675
2752
|
// Unknown size (null — snapshot degrade) is presumed drawn.
|
|
2676
2753
|
const exists = latestRev > 0 && entry?.sizeBytes !== 0;
|
|
2677
2754
|
return {
|
|
2678
2755
|
sessionId,
|
|
2756
|
+
slot,
|
|
2757
|
+
slots,
|
|
2758
|
+
name: typeof entry?.name === "string" ? entry.name : "",
|
|
2679
2759
|
mode,
|
|
2680
2760
|
exists,
|
|
2681
2761
|
latestRev,
|
package/ui/core/src/state.js
CHANGED
|
@@ -73,11 +73,23 @@ export function normalizeStoredLayoutAdjustments(layoutAdjustments) {
|
|
|
73
73
|
const sessionPaneAdjust = Number(candidate.sessionPaneAdjust);
|
|
74
74
|
const portalSessionColumnAdjust = Number(candidate.portalSessionColumnAdjust);
|
|
75
75
|
const activityPaneAdjust = Number(candidate.activityPaneAdjust);
|
|
76
|
+
// Canvas is a column of its own now rather than a face the right column
|
|
77
|
+
// wears, so it needs its own remembered width. Same mechanism as the rest:
|
|
78
|
+
// a pixel delta from the computed base, persisted per user.
|
|
79
|
+
const canvasPaneAdjust = Number(candidate.canvasPaneAdjust);
|
|
80
|
+
const diagnosticsPaneAdjust = Number(candidate.diagnosticsPaneAdjust);
|
|
81
|
+
const diagnosticsSplitAdjust = Number(candidate.diagnosticsSplitAdjust);
|
|
76
82
|
return {
|
|
77
83
|
paneAdjust: Number.isFinite(paneAdjust) ? Math.trunc(paneAdjust) : 0,
|
|
78
84
|
sessionPaneAdjust: Number.isFinite(sessionPaneAdjust) ? Math.trunc(sessionPaneAdjust) : 0,
|
|
79
85
|
portalSessionColumnAdjust: Number.isFinite(portalSessionColumnAdjust) ? Math.trunc(portalSessionColumnAdjust) : 0,
|
|
80
86
|
activityPaneAdjust: Number.isFinite(activityPaneAdjust) ? Math.trunc(activityPaneAdjust) : 0,
|
|
87
|
+
canvasPaneAdjust: Number.isFinite(canvasPaneAdjust) ? Math.trunc(canvasPaneAdjust) : 0,
|
|
88
|
+
diagnosticsPaneAdjust: Number.isFinite(diagnosticsPaneAdjust) ? Math.trunc(diagnosticsPaneAdjust) : 0,
|
|
89
|
+
// The inspector/activity seam inside Diagnostics, in PIXELS from an
|
|
90
|
+
// even split. The old row-quantized TUI adjust made browser drags
|
|
91
|
+
// jump in ~20px notches.
|
|
92
|
+
diagnosticsSplitAdjust: Number.isFinite(diagnosticsSplitAdjust) ? Math.trunc(diagnosticsSplitAdjust) : 0,
|
|
81
93
|
};
|
|
82
94
|
}
|
|
83
95
|
|
|
@@ -132,11 +144,66 @@ export function normalizeStoredCollapsedSessionIds(value) {
|
|
|
132
144
|
* Right-column mode: the inspector/activity split, or the session canvas.
|
|
133
145
|
* Anything unrecognized falls back to panes — a stored value from a newer
|
|
134
146
|
* build must not strand an older portal in a mode it cannot render.
|
|
147
|
+
*
|
|
148
|
+
* @deprecated Superseded by the independent `canvasOpen` / `diagnosticsOpen`
|
|
149
|
+
* booleans. Kept only to migrate a value written by an older build — see
|
|
150
|
+
* normalizeStoredDesktopPanes.
|
|
135
151
|
*/
|
|
136
152
|
export function normalizeStoredRightPaneMode(value) {
|
|
137
153
|
return value === "canvas" ? "canvas" : "panes";
|
|
138
154
|
}
|
|
139
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Which of the two optional desktop columns are on screen.
|
|
158
|
+
*
|
|
159
|
+
* Canvas and Diagnostics used to be one enum (`rightPaneMode`), so the right
|
|
160
|
+
* column could only ever wear one face. They are independent now: either, both,
|
|
161
|
+
* or neither. Diagnostics is the old inspector/activity split, moved out of the
|
|
162
|
+
* chat pane and travelling as one unit.
|
|
163
|
+
*
|
|
164
|
+
* Both default to OFF. A pane that is off has no width and no resizer — it is
|
|
165
|
+
* absent, not collapsed to nothing.
|
|
166
|
+
*
|
|
167
|
+
* Migrating a stored `rightPaneMode`:
|
|
168
|
+
* "canvas" -> canvas on. That was a deliberate choice, so it is honored.
|
|
169
|
+
* "panes" -> both off. "panes" was the default value rather than a choice,
|
|
170
|
+
* and the new default is a clean two-column workspace.
|
|
171
|
+
*/
|
|
172
|
+
export function normalizeStoredDesktopPanes(value, legacyRightPaneMode) {
|
|
173
|
+
const candidate = value && typeof value === "object" ? value : null;
|
|
174
|
+
if (candidate && (typeof candidate.canvasOpen === "boolean" || typeof candidate.diagnosticsOpen === "boolean")) {
|
|
175
|
+
return {
|
|
176
|
+
canvasOpen: candidate.canvasOpen === true,
|
|
177
|
+
diagnosticsOpen: candidate.diagnosticsOpen === true,
|
|
178
|
+
// Zen: chat as a narrow rail, canvas as the workbench. Only
|
|
179
|
+
// meaningful with the canvas open.
|
|
180
|
+
zen: candidate.zen === true && candidate.canvasOpen === true,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
canvasOpen: legacyRightPaneMode === "canvas",
|
|
185
|
+
diagnosticsOpen: false,
|
|
186
|
+
zen: false,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* The store key for one canvas surface. Slot 1 keeps the bare session id so
|
|
192
|
+
* every reader written before slots existed keeps working untouched; slots
|
|
193
|
+
* 2-5 append "#<slot>". Used for canvas.bySessionId AND canvas.prefs.
|
|
194
|
+
*/
|
|
195
|
+
export function canvasKey(sessionId, slot) {
|
|
196
|
+
const id = String(sessionId || "");
|
|
197
|
+
const n = Number(slot);
|
|
198
|
+
return Number.isInteger(n) && n >= 2 && n <= 5 ? `${id}#${n}` : id;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** The inverse: `sessionId#3` -> { sessionId, slot: 3 }; bare id -> slot 1. */
|
|
202
|
+
export function parseCanvasKey(key) {
|
|
203
|
+
const m = /^(.*)#([2-5])$/.exec(String(key || ""));
|
|
204
|
+
return m ? { sessionId: m[1], slot: Number(m[2]) } : { sessionId: String(key || ""), slot: 1 };
|
|
205
|
+
}
|
|
206
|
+
|
|
140
207
|
/**
|
|
141
208
|
* Per-session canvas preferences: what this user has chosen and seen.
|
|
142
209
|
*
|
|
@@ -154,10 +221,13 @@ export function normalizeStoredCanvasPrefs(value) {
|
|
|
154
221
|
if (!id || !entry || typeof entry !== "object") continue;
|
|
155
222
|
const lastViewedRev = Number(entry.lastViewedRev);
|
|
156
223
|
const lastViewedDataRev = Number(entry.lastViewedDataRev);
|
|
224
|
+
const zenRailPx = Number(entry.zenRailPx);
|
|
157
225
|
out[id] = {
|
|
158
226
|
optedOut: entry.optedOut === true,
|
|
159
227
|
lastViewedRev: Number.isFinite(lastViewedRev) && lastViewedRev > 0 ? Math.floor(lastViewedRev) : 0,
|
|
160
228
|
lastViewedDataRev: Number.isFinite(lastViewedDataRev) && lastViewedDataRev > 0 ? Math.floor(lastViewedDataRev) : 0,
|
|
229
|
+
// Zen chat-rail width, remembered for THIS session only.
|
|
230
|
+
...(Number.isFinite(zenRailPx) && zenRailPx > 0 ? { zenRailPx: Math.floor(zenRailPx) } : {}),
|
|
161
231
|
};
|
|
162
232
|
}
|
|
163
233
|
return out;
|
|
@@ -169,7 +239,11 @@ export function normalizeStoredActiveSessionId(value) {
|
|
|
169
239
|
return id ? id : null;
|
|
170
240
|
}
|
|
171
241
|
|
|
172
|
-
export function createInitialState({ mode = "local", branding = null, docs = null, themeId = null, sessionOwnerFilter = null, layoutAdjustments = null, pinnedSessionIds = null, collapsedSessionIds = null, activeSessionId = null, sessionOrder = null, rightPaneMode = null, canvasPrefs = null } = {}) {
|
|
242
|
+
export function createInitialState({ mode = "local", branding = null, docs = null, themeId = null, sessionOwnerFilter = null, layoutAdjustments = null, pinnedSessionIds = null, collapsedSessionIds = null, activeSessionId = null, sessionOrder = null, rightPaneMode = null, desktopPanes: storedDesktopPanes = null, canvasPrefs = null } = {}) {
|
|
243
|
+
const desktopPanes = normalizeStoredDesktopPanes(
|
|
244
|
+
storedDesktopPanes,
|
|
245
|
+
normalizeStoredRightPaneMode(rightPaneMode),
|
|
246
|
+
);
|
|
173
247
|
const hasStoredSessionOwnerFilter = sessionOwnerFilter != null;
|
|
174
248
|
const hasStoredCollapsedSessionIds = collapsedSessionIds != null;
|
|
175
249
|
const initialLayoutAdjustments = normalizeStoredLayoutAdjustments(layoutAdjustments);
|
|
@@ -201,7 +275,21 @@ export function createInitialState({ mode = "local", branding = null, docs = nul
|
|
|
201
275
|
// through to the transcript.
|
|
202
276
|
// Which face the right column wears: the inspector/activity panes
|
|
203
277
|
// or the session canvas. Persisted.
|
|
204
|
-
|
|
278
|
+
//
|
|
279
|
+
// @deprecated Read by nothing that decides layout any more — the
|
|
280
|
+
// two booleans below do that. Still derived so a build that rolls
|
|
281
|
+
// back, and anything still reading the old key, sees a sane value.
|
|
282
|
+
rightPaneMode: desktopPanes.canvasOpen ? "canvas" : "panes",
|
|
283
|
+
// The two optional desktop columns, independent of each other.
|
|
284
|
+
// Both off is the default workspace: sessions and chat only.
|
|
285
|
+
canvasOpen: desktopPanes.canvasOpen,
|
|
286
|
+
diagnosticsOpen: desktopPanes.diagnosticsOpen,
|
|
287
|
+
// Chat-rail + canvas-workbench mode. Persisted with the columns.
|
|
288
|
+
canvasZen: desktopPanes.zen,
|
|
289
|
+
// Canvas filling the workspace. Deliberately NOT persisted: it is
|
|
290
|
+
// a "look at this now" gesture, and returning to a portal with no
|
|
291
|
+
// chat and no session list would read as a broken app.
|
|
292
|
+
canvasMaximized: false,
|
|
205
293
|
statsViewMode: "session",
|
|
206
294
|
prompt: "",
|
|
207
295
|
promptCursor: 0,
|
|
@@ -61,7 +61,7 @@ const THEMES = Object.freeze([
|
|
|
61
61
|
|
|
62
62
|
const THEME_MAP = new Map(THEMES.map((theme) => [theme.id, theme]));
|
|
63
63
|
|
|
64
|
-
export const DEFAULT_THEME_ID =
|
|
64
|
+
export const DEFAULT_THEME_ID = workspaceDarkTheme.id;
|
|
65
65
|
|
|
66
66
|
export { THEME_GROUP_ORDER } from "./helpers.js";
|
|
67
67
|
|