@deepseek-insight/dsi 0.8.0 → 0.8.1
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/build/client/_app/immutable/assets/0.DBVVEjy9.css +2 -0
- package/build/client/_app/immutable/assets/2.BhBfHqja.css +1 -0
- package/build/client/_app/immutable/chunks/{Dk9aRp2m.js → 4B6J_kM2.js} +1 -1
- package/build/client/_app/immutable/chunks/{ANnPTMPF.js → 4cwyag_I.js} +1 -1
- package/build/client/_app/immutable/chunks/{D7-uGicP.js → 7FnrqGK9.js} +1 -1
- package/build/client/_app/immutable/chunks/{CIH5Juz4.js → AcmOeh2U.js} +1 -1
- package/build/client/_app/immutable/chunks/{BqX9BB0G.js → B2jrDnt8.js} +1 -1
- package/build/client/_app/immutable/chunks/{A5Iiq81h.js → B4F5liKq.js} +1 -1
- package/build/client/_app/immutable/chunks/{D3rUyYDm.js → B6bTO8_7.js} +1 -1
- package/build/client/_app/immutable/chunks/{2XtVrxH4.js → BBd0nTHG.js} +1 -1
- package/build/client/_app/immutable/chunks/BHDqH9nE.js +1 -0
- package/build/client/_app/immutable/chunks/{-izoh3h0.js → BO99LSSA.js} +1 -1
- package/build/client/_app/immutable/chunks/{BjafRUyA.js → BQC6O_RV.js} +1 -1
- package/build/client/_app/immutable/chunks/{BJsp4NMH.js → BWRXzjmQ.js} +1 -1
- package/build/client/_app/immutable/chunks/{crRp5OG4.js → BXKc4uuX.js} +1 -1
- package/build/client/_app/immutable/chunks/{j2lJ25s0.js → BenkQ_4r.js} +1 -1
- package/build/client/_app/immutable/chunks/{Dso_gKeU.js → BkYT72a1.js} +1 -1
- package/build/client/_app/immutable/chunks/{CCWXLdgd.js → BlwWx85l.js} +1 -1
- package/build/client/_app/immutable/chunks/{DCmONIPx.js → BmDADyfH.js} +1 -1
- package/build/client/_app/immutable/chunks/{DYfx-RRD.js → Bpd0I3U7.js} +1 -1
- package/build/client/_app/immutable/chunks/{B-V7Vlsz.js → Bqwvv7Vf.js} +4 -4
- package/build/client/_app/immutable/chunks/{CQTGR8fW.js → BsBBq-Qk.js} +1 -1
- package/build/client/_app/immutable/chunks/{IBXFCASw.js → Byu_teLA.js} +1 -1
- package/build/client/_app/immutable/chunks/{DpSjzsDs.js → C0tWPpc3.js} +2 -2
- package/build/client/_app/immutable/chunks/{Cx8YXmgi.js → C4gs6zoI.js} +1 -1
- package/build/client/_app/immutable/chunks/CAneZX4t.js +8 -0
- package/build/client/_app/immutable/chunks/{olUfRNXS.js → CB55Rp7-.js} +1 -1
- package/build/client/_app/immutable/chunks/{C1dC47iq.js → CH_bR_0j.js} +1 -1
- package/build/client/_app/immutable/chunks/{CvvYpRG9.js → CJ1fzlPC.js} +1 -1
- package/build/client/_app/immutable/chunks/{DfIqw6WM.js → CK5vhXvt.js} +1 -1
- package/build/client/_app/immutable/chunks/{0HT0ILkA.js → CRFuOqJI.js} +1 -1
- package/build/client/_app/immutable/chunks/{gXyYVhfn.js → CZoElI5B.js} +1 -1
- package/build/client/_app/immutable/chunks/{dcghWWmq.js → CajOZJDl.js} +1 -1
- package/build/client/_app/immutable/chunks/{BImoJlJo.js → CdaJvl_A.js} +1 -1
- package/build/client/_app/immutable/chunks/{CNJYmM8n.js → CeLBjOd9.js} +1 -1
- package/build/client/_app/immutable/chunks/{IoX9lmZK.js → CevKuuic.js} +1 -1
- package/build/client/_app/immutable/chunks/{B_Gknb5_.js → Cf0aMC4n.js} +1 -1
- package/build/client/_app/immutable/chunks/{C_MwBDNt.js → CnxoqrkQ.js} +1 -1
- package/build/client/_app/immutable/chunks/{ChC4viXw.js → Cr2ck_ss.js} +1 -1
- package/build/client/_app/immutable/chunks/{fJBuRi-A.js → Czc4_W7v.js} +1 -1
- package/build/client/_app/immutable/chunks/{CHYEvS-6.js → Czey8tDK.js} +1 -1
- package/build/client/_app/immutable/chunks/{bpkmZ_Dv.js → D0ChUnpi.js} +1 -1
- package/build/client/_app/immutable/chunks/{B5S0Wke9.js → D0uxHECr.js} +1 -1
- package/build/client/_app/immutable/chunks/{2M1KS72j.js → D6KenyiF.js} +1 -1
- package/build/client/_app/immutable/chunks/{DT1b6JaK.js → DBKMIEwD.js} +1 -1
- package/build/client/_app/immutable/chunks/{Bq4mG8qS.js → DEVxi5CK.js} +1 -1
- package/build/client/_app/immutable/chunks/{Bh_Z0-Fh.js → DFBKiA2Z.js} +1 -1
- package/build/client/_app/immutable/chunks/{DSqRqQNp.js → DIxy2USu.js} +1 -1
- package/build/client/_app/immutable/chunks/{D4I0Dqwh.js → DJQr4efH.js} +1 -1
- package/build/client/_app/immutable/chunks/DQXo7qdJ.js +1 -0
- package/build/client/_app/immutable/chunks/{3E8jbhSl.js → DU8C5thd.js} +1 -1
- package/build/client/_app/immutable/chunks/{D7eKc9ur.js → DUCaFYlx.js} +1 -1
- package/build/client/_app/immutable/chunks/{CbtU_GW3.js → DdI16loP.js} +1 -1
- package/build/client/_app/immutable/chunks/{DykTZ90H.js → DdJNsJBH.js} +1 -1
- package/build/client/_app/immutable/chunks/{C6zqVyWx.js → DfUgh5E_.js} +1 -1
- package/build/client/_app/immutable/chunks/{Ch7rc-L7.js → DmRY6FWm.js} +4 -4
- package/build/client/_app/immutable/chunks/{D7XrPGMK.js → DuRZnRVw.js} +1 -1
- package/build/client/_app/immutable/chunks/{Do0VAo0_.js → DuiFyTVb.js} +1 -1
- package/build/client/_app/immutable/chunks/{Ck2086Sr.js → DwcY-69G.js} +1 -1
- package/build/client/_app/immutable/chunks/K3xyLTzZ.js +1 -0
- package/build/client/_app/immutable/chunks/{GMyoOYdi.js → NcOjFWr3.js} +1 -1
- package/build/client/_app/immutable/chunks/{BZ6uvzU8.js → O6xxeEm8.js} +1 -1
- package/build/client/_app/immutable/chunks/{DrVddB75.js → OW5Q7tGb.js} +1 -1
- package/build/client/_app/immutable/chunks/{CW2uYEvb.js → SN3Efo-Q.js} +1 -1
- package/build/client/_app/immutable/chunks/{Bf1I5ROF.js → ap4GAVq-.js} +1 -1
- package/build/client/_app/immutable/chunks/{DWYSL4om.js → at6PQqQ4.js} +1 -1
- package/build/client/_app/immutable/chunks/cHj8EuyS.js +3 -0
- package/build/client/_app/immutable/chunks/{l3etNtOh.js → eFcFJ9Ld.js} +1 -1
- package/build/client/_app/immutable/chunks/gZFoJ-NI.js +1 -0
- package/build/client/_app/immutable/chunks/{Bx68-tOf.js → kzciT-3i.js} +1 -1
- package/build/client/_app/immutable/chunks/{DNf96C-O.js → lF8CNVOA.js} +1 -1
- package/build/client/_app/immutable/chunks/o7DVZODA.js +1 -0
- package/build/client/_app/immutable/chunks/pdYhlwhf.js +1 -0
- package/build/client/_app/immutable/chunks/{q1Yj7q99.js → q5PRaRZk.js} +1 -1
- package/build/client/_app/immutable/chunks/xkjLeSzJ.js +1 -0
- package/build/client/_app/immutable/chunks/{BKU5-8Td.js → zypfUZYM.js} +1 -1
- package/build/client/_app/immutable/entry/app.DP0oSUf-.js +2 -0
- package/build/client/_app/immutable/entry/start.mBp3LB6J.js +1 -0
- package/build/client/_app/immutable/nodes/0.Dm_ry-Pr.js +1 -0
- package/build/client/_app/immutable/nodes/1.UuScj-IS.js +1 -0
- package/build/client/_app/immutable/nodes/2.CJRPZhbe.js +340 -0
- package/build/client/_app/version.json +1 -1
- package/build/handler.js +6 -6
- package/build/index.js +6 -6
- package/build/server/chunks/chunks/{index-server.js-CV2lq-ha.js → index-server.js-DmIEbDVz.js} +2 -2
- package/build/server/chunks/chunks/{internal2.js-BtL7AFjQ.js → internal2.js-Pv5iygVN.js} +3 -3
- package/build/server/chunks/chunks/{server.js-DqHGsQU2.js → server.js-B1bDXhHu.js} +47 -2
- package/build/server/chunks/chunks/{state.js-D3ob-Gqa.js → state.js-BCaKzPy6.js} +4 -4
- package/build/server/chunks/entries/pages/{_error.svelte.js-9cKDDMkE.js → _error.svelte.js-BRyCyR0c.js} +5 -5
- package/build/server/chunks/entries/pages/{_page.svelte.js-hjZYZCe1.js → _page.svelte.js-CKY8hz9T.js} +962 -539
- package/build/server/chunks/{handler-B_azsHTz.js → handler-D1oqmwyy.js} +3 -3
- package/build/server/chunks/{index.js-3VY3QWe-.js → index.js-BZ8zP9wS.js} +4 -4
- package/build/server/chunks/{manifest.js-hHcXduh_.js → manifest.js-CA6PuZTD.js} +5 -5
- package/build/server/chunks/nodes/{0.js-B_LVBEe8.js → 0.js-DtkNHIFx.js} +3 -3
- package/build/server/chunks/nodes/1.js-Q6zZupRG.js +9 -0
- package/build/server/chunks/nodes/{2.js-bVRsbAhW.js → 2.js-P1boc94A.js} +4 -4
- package/package.json +1 -1
- package/template/.dsi/prompts.sqlite-shm +0 -0
- package/template/.dsi/prompts.sqlite-wal +0 -0
- package/build/client/_app/immutable/assets/0.c2dRYi3B.css +0 -2
- package/build/client/_app/immutable/assets/2.DBblYO_a.css +0 -1
- package/build/client/_app/immutable/chunks/BBDOLPkB.js +0 -1
- package/build/client/_app/immutable/chunks/BMgyB-Sy.js +0 -1
- package/build/client/_app/immutable/chunks/BYHxHjHc.js +0 -1
- package/build/client/_app/immutable/chunks/BwNsQhd8.js +0 -1
- package/build/client/_app/immutable/chunks/C0CuJuob.js +0 -1
- package/build/client/_app/immutable/chunks/CMByLjfJ.js +0 -1
- package/build/client/_app/immutable/chunks/DmLHHlla.js +0 -3
- package/build/client/_app/immutable/chunks/J_8-FdbR.js +0 -1
- package/build/client/_app/immutable/chunks/da2fibLv.js +0 -8
- package/build/client/_app/immutable/entry/app.GsYnI6xk.js +0 -2
- package/build/client/_app/immutable/entry/start.keNjq0dA.js +0 -1
- package/build/client/_app/immutable/nodes/0.BJVfjaPJ.js +0 -1
- package/build/client/_app/immutable/nodes/1.rhLd5ssJ.js +0 -1
- package/build/client/_app/immutable/nodes/2.DdzHBwFT.js +0 -340
- package/build/server/chunks/nodes/1.js-BRybp38b.js +0 -9
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { a as __exportAll, o as onDestroy } from '../../chunks/index-server.js-
|
|
2
|
-
import
|
|
1
|
+
import { a as __exportAll, o as onDestroy } from '../../chunks/index-server.js-DmIEbDVz.js';
|
|
2
|
+
import '../../chunks/exports.js-DH_tjtdv.js';
|
|
3
|
+
import { M as derived, V as head, T as writable, W as escape_html, X as attr, Y as bind_props, a as setContext, Z as attr_class, _ as attr_style, $ as store_get, a0 as spread_props, a1 as stringify, a2 as attributes, a3 as clsx, a4 as ensure_array_like, a5 as element, g as getContext, a6 as unsubscribe_stores, a7 as html, r as run, a8 as props_id } from '../../chunks/server.js-B1bDXhHu.js';
|
|
3
4
|
import { U as UI_LOCALES } from '../../chunks/config.js-vThvQeMn.js';
|
|
4
5
|
import { m as mergeEntries, c as collapseSystemPromptEntries, t as truncate } from '../../chunks/merge.js-yMwW440S.js';
|
|
5
6
|
import { p as parseA2aSignature, m as mintA2aId, b as buildDeliveredText } from '../../chunks/a2a-protocol.js-C77mVg2Q.js';
|
|
@@ -8,7 +9,7 @@ import { D as DEFAULT_IMAGE_LIMITS } from '../../chunks/image-limits.js-CUdJ0f7r
|
|
|
8
9
|
import { s as sanitizeWorkspaceProfile, d as dsiKey, t as themePrefs } from '../../chunks/theme-prefs.svelte.js-8CaWz46g.js';
|
|
9
10
|
import { a as appConfig, p as previewSegments, b as parseTagWords, i as isValidTagWord, s as shouldRecordPrompt, g as getTrigger, t as triggerMode, c as searchKey, d as textPreviewOf } from '../../chunks/app-config.svelte.js-BM4WbMFB.js';
|
|
10
11
|
import { c as getLocale } from '../../chunks/runtime.js-CCJi3XaY.js';
|
|
11
|
-
import { p as page, a as afterNavigate, t, c as currentLocale, e as replaceState, u as unexpectederror1, s as sessionnotfound2, r as reapednote1, d as dshunreachable1, b as backtoworkspace2 } from '../../chunks/state.js-
|
|
12
|
+
import { p as page, a as afterNavigate, t, c as currentLocale, e as replaceState, u as unexpectederror1, s as sessionnotfound2, r as reapednote1, d as dshunreachable1, b as backtoworkspace2 } from '../../chunks/state.js-BCaKzPy6.js';
|
|
12
13
|
import 'yaml';
|
|
13
14
|
import 'html-to-image';
|
|
14
15
|
import hljs from 'highlight.js/lib/core';
|
|
@@ -20,8 +21,7 @@ import xml from 'highlight.js/lib/languages/xml';
|
|
|
20
21
|
import css from 'highlight.js/lib/languages/css';
|
|
21
22
|
import '../../chunks/uneval.js-BJ9Qq2SF.js';
|
|
22
23
|
import '../../chunks/shared.js-HQ0rfhm4.js';
|
|
23
|
-
import '../../chunks/internal2.js-
|
|
24
|
-
import '../../chunks/exports.js-DH_tjtdv.js';
|
|
24
|
+
import '../../chunks/internal2.js-Pv5iygVN.js';
|
|
25
25
|
import '../../chunks/utils.js-CAdNO8Tu.js';
|
|
26
26
|
|
|
27
27
|
//#region src/lib/paraglide/messages/abort.js
|
|
@@ -17155,19 +17155,23 @@ function SessionStatus($$renderer, $$props) {
|
|
|
17155
17155
|
* plus the ×N badge), the replacement must be re-measured, never
|
|
17156
17156
|
* assumed.
|
|
17157
17157
|
*/
|
|
17158
|
-
let {
|
|
17158
|
+
let { delegated = false, count = 0, browser = false } = $$props;
|
|
17159
17159
|
/** Accessible name — four distinct states; the count rides along
|
|
17160
17160
|
* (WCAG 1.4.1: never color alone). */
|
|
17161
|
-
const label = derived(() =>
|
|
17161
|
+
const label = derived(() => browser ? "browser session, folded — click to open" : delegated ? count > 0 ? `running and delegating, ${count} running` : "running and delegating" : "running" );
|
|
17162
17162
|
$$renderer.push(`<span data-svelte="SessionStatus"${attr_class("status svelte-x2ntn8", void 0, {
|
|
17163
|
-
"run":
|
|
17164
|
-
"idle":
|
|
17163
|
+
"run": !browser,
|
|
17164
|
+
"idle": false,
|
|
17165
|
+
"browser": browser,
|
|
17165
17166
|
"delegated": delegated
|
|
17166
17167
|
})} role="img"${attr("aria-label", label())} data-testid="session-status">`);
|
|
17167
|
-
if (
|
|
17168
|
+
if (browser) {
|
|
17168
17169
|
$$renderer.push("<!--[0-->");
|
|
17170
|
+
$$renderer.push(`<span class="frame svelte-x2ntn8" aria-hidden="true"></span>`);
|
|
17171
|
+
} else {
|
|
17172
|
+
$$renderer.push("<!--[1-->");
|
|
17169
17173
|
$$renderer.push(`<span class="bar svelte-x2ntn8"></span><span class="bar svelte-x2ntn8"></span><span class="bar svelte-x2ntn8"></span>`);
|
|
17170
|
-
}
|
|
17174
|
+
}
|
|
17171
17175
|
$$renderer.push(`<!--]-->`);
|
|
17172
17176
|
if (count > 0) {
|
|
17173
17177
|
$$renderer.push("<!--[0-->");
|
|
@@ -17581,7 +17585,7 @@ function ThemeToggle($$renderer, $$props) {
|
|
|
17581
17585
|
}
|
|
17582
17586
|
//#endregion
|
|
17583
17587
|
//#region package.json
|
|
17584
|
-
var version = "0.8.
|
|
17588
|
+
var version = "0.8.1";
|
|
17585
17589
|
var dsh = { "webVersion": "0.2.1-rc.2" };
|
|
17586
17590
|
//#endregion
|
|
17587
17591
|
//#region src/lib/version.ts
|
|
@@ -19029,12 +19033,34 @@ function SidebarSessions($$renderer, $$props) {
|
|
|
19029
19033
|
* picker dialog). Blank never-prompted sessions hide by default
|
|
19030
19034
|
* (toggle in the filter row).
|
|
19031
19035
|
*/
|
|
19032
|
-
let { currentSessionId, filter, paneledSessionIds = [], onfilterchange } = $$props;
|
|
19036
|
+
let { currentSessionId, filter, paneledSessionIds = [], glassRows = [], onfilterchange } = $$props;
|
|
19033
19037
|
/** The host workspace registry — the AUTHORITY for chips/pills here. */
|
|
19034
19038
|
let workspaces = [];
|
|
19035
19039
|
/** The full host preset catalog — the agent pills list it entirely. */
|
|
19036
19040
|
let availablePresets = [];
|
|
19037
19041
|
const ready = derived(() => []);
|
|
19042
|
+
/** Folded-glass synthetic rows (2026-10-22): shaped as session
|
|
19043
|
+
* summaries so the WHOLE spine pipeline (lineage, family nesting,
|
|
19044
|
+
* filters) treats them as the opener's children. origin 'browser'
|
|
19045
|
+
* marks the row for RowSessionItem's summon click; workspace and
|
|
19046
|
+
* title ride the opener so filters keep the family whole. */
|
|
19047
|
+
const glassSummaries = derived(() => {
|
|
19048
|
+
return glassRows.map((g) => {
|
|
19049
|
+
const opener = ready().find((s) => s.sessionId === g.openedBy);
|
|
19050
|
+
return {
|
|
19051
|
+
sessionId: g.sessionId,
|
|
19052
|
+
title: g.title || "Browser",
|
|
19053
|
+
agentPreset: null,
|
|
19054
|
+
running: true,
|
|
19055
|
+
blank: false,
|
|
19056
|
+
updatedAt: opener?.updatedAt ?? 0,
|
|
19057
|
+
workspace: opener?.workspace ?? null,
|
|
19058
|
+
turns: null,
|
|
19059
|
+
parentSessionId: g.openedBy,
|
|
19060
|
+
origin: "browser"
|
|
19061
|
+
};
|
|
19062
|
+
});
|
|
19063
|
+
});
|
|
19038
19064
|
/** Current row — looked up from the RAW list (never filtered away). */
|
|
19039
19065
|
const current = derived(() => ready().find((s) => s.sessionId === currentSessionId) ?? null);
|
|
19040
19066
|
let spine = loadSpineGroupPrefs(null);
|
|
@@ -19044,8 +19070,8 @@ function SidebarSessions($$renderer, $$props) {
|
|
|
19044
19070
|
* generalized from 1 to N). */
|
|
19045
19071
|
const paneled = derived(() => new Set(paneledSessionIds));
|
|
19046
19072
|
const others = derived(() => ready().filter((s) => s.sessionId !== currentSessionId && !paneled().has(s.sessionId)));
|
|
19047
|
-
const lineage = derived(() => deriveLineage(ready(), []));
|
|
19048
|
-
const unsuppressed = derived(() => suppressFromSpine(others(), lineage(), paneled()));
|
|
19073
|
+
const lineage = derived(() => deriveLineage([...ready(), ...glassSummaries()], []));
|
|
19074
|
+
const unsuppressed = derived(() => suppressFromSpine([...others(), ...glassSummaries()], lineage(), paneled()));
|
|
19049
19075
|
const wsPills = derived(() => workspaceOptions(others(), workspaces));
|
|
19050
19076
|
const presets = derived(() => presetOptions(availablePresets, others()));
|
|
19051
19077
|
/** Self-healed filter — a persisted key no pill carries reads as All. */
|
|
@@ -19220,26 +19246,424 @@ function CanvasCopyButton($$renderer, $$props) {
|
|
|
19220
19246
|
});
|
|
19221
19247
|
}
|
|
19222
19248
|
//#endregion
|
|
19249
|
+
//#region src/lib/utils/panel-prefs.ts
|
|
19250
|
+
/** localStorage base key — one JSON blob `{ panels, selectedPanelId, panelWidth, zoom }`.
|
|
19251
|
+
* A workspace profile (`?profile=…` on the URL) suffixes EVERY dsi-* key
|
|
19252
|
+
* (see storage-profile.ts): the default desk lives under `dsi-panels`,
|
|
19253
|
+
* profile `widi` under `dsi-panels_widi`. */
|
|
19254
|
+
var PANEL_PREFS_KEY = "dsi-panels";
|
|
19255
|
+
/**
|
|
19256
|
+
* The storage key for a workspace profile.
|
|
19257
|
+
* @param profile sanitized profile segment, or null/undefined for the
|
|
19258
|
+
* default desk (`dsi-panels`).
|
|
19259
|
+
*/
|
|
19260
|
+
function panelPrefsKey(profile) {
|
|
19261
|
+
return dsiKey(PANEL_PREFS_KEY, profile);
|
|
19262
|
+
}
|
|
19263
|
+
var PANEL_WORKSPACE_FILE_MAX_WIDTH = 1436;
|
|
19264
|
+
/** The single treePct bound site — sanitize a stored or dragged value
|
|
19265
|
+
* into [TREE_PCT_MIN, TREE_PCT_MAX]; junk (non-finite) falls back to
|
|
19266
|
+
* TREE_PCT_DEFAULT. Mirrors clampPanelZoom's discipline. */
|
|
19267
|
+
function clampTreePct(pct) {
|
|
19268
|
+
if (typeof pct !== "number" || !Number.isFinite(pct)) return 30;
|
|
19269
|
+
return Math.max(15, Math.min(70, Math.round(pct)));
|
|
19270
|
+
}
|
|
19271
|
+
/**
|
|
19272
|
+
* The single panel-width bound site — load-side sanitizing, gutter drags,
|
|
19273
|
+
* and the width slider all route through here. Bounds read the config
|
|
19274
|
+
* store (layout load has landed them before any mount; defaults before).
|
|
19275
|
+
*/
|
|
19276
|
+
function clampPanelWidth(width, kind) {
|
|
19277
|
+
const { minWidth, maxWidth } = appConfig().panel;
|
|
19278
|
+
if (kind === "workspace-explorer") return Math.max(520, Math.min(PANEL_WORKSPACE_FILE_MAX_WIDTH, width));
|
|
19279
|
+
if (kind === "workspace-file") return Math.max(520, Math.min(PANEL_WORKSPACE_FILE_MAX_WIDTH, width));
|
|
19280
|
+
return Math.max(minWidth, Math.min(maxWidth, width));
|
|
19281
|
+
}
|
|
19282
|
+
/** The single zoom bound site — load-side sanitizing and the zoom slider. */
|
|
19283
|
+
function clampPanelZoom(zoom) {
|
|
19284
|
+
const { minZoom, maxZoom } = appConfig().panel;
|
|
19285
|
+
return Math.max(minZoom, Math.min(maxZoom, zoom));
|
|
19286
|
+
}
|
|
19287
|
+
/** Config-driven default width (clamped through the single bound site). */
|
|
19288
|
+
function defaultPanelWidth() {
|
|
19289
|
+
return clampPanelWidth(appConfig().panel.defaultWidth);
|
|
19290
|
+
}
|
|
19291
|
+
/**
|
|
19292
|
+
* The skill shelf's born width (The Shelf Chrome ADR, D5): a name list,
|
|
19293
|
+
* not a five-column table — the shelf pins 480 (DEFAULT_PANEL_MIN_WIDTH)
|
|
19294
|
+
* instead of the 730 conversation default, clamped through the single
|
|
19295
|
+
* bound site.
|
|
19296
|
+
*/
|
|
19297
|
+
function shelfPanelWidth() {
|
|
19298
|
+
return clampPanelWidth(480);
|
|
19299
|
+
}
|
|
19300
|
+
/**
|
|
19301
|
+
* Clamp a stored explorer `expanded` list to sane paths (Workspace
|
|
19302
|
+
* Explorer restore): non-string members drop and a repeated path keeps
|
|
19303
|
+
* its FIRST occurrence — the tree treats `expanded` as a set of
|
|
19304
|
+
* root-relative directories, and a duplicate would double-render a row.
|
|
19305
|
+
*/
|
|
19306
|
+
function clampExpanded(value) {
|
|
19307
|
+
if (!Array.isArray(value)) return [];
|
|
19308
|
+
const seen = /* @__PURE__ */ new Set();
|
|
19309
|
+
const out = [];
|
|
19310
|
+
for (const member of value) {
|
|
19311
|
+
if (typeof member !== "string" || seen.has(member)) continue;
|
|
19312
|
+
seen.add(member);
|
|
19313
|
+
out.push(member);
|
|
19314
|
+
}
|
|
19315
|
+
return out;
|
|
19316
|
+
}
|
|
19317
|
+
/** The terminal desk's structure clamp (Terminal Desk ADR D3, Wave 3):
|
|
19318
|
+
* sanitize a stored desk mirror into { tabs, selectedTab } or undefined.
|
|
19319
|
+
* Junk drops FIELD-WISE — non-string sessionIds drop, empty/junk tabs
|
|
19320
|
+
* drop, selectedTab clamps into range — so a stale blob degrades to
|
|
19321
|
+
* "fewer rows remembered", never a phantom row. All tabs dropped (or
|
|
19322
|
+
* junk at the top) ⇒ undefined: the desk falls back to one fresh row. */
|
|
19323
|
+
function clampDeskMirror(value) {
|
|
19324
|
+
if (value === null || typeof value !== "object") return void 0;
|
|
19325
|
+
const raw = value;
|
|
19326
|
+
if (!Array.isArray(raw.tabs)) return void 0;
|
|
19327
|
+
const tabs = [];
|
|
19328
|
+
for (const tab of raw.tabs) {
|
|
19329
|
+
if (tab === null || typeof tab !== "object") continue;
|
|
19330
|
+
const ids = tab.sessionIds;
|
|
19331
|
+
if (!Array.isArray(ids)) continue;
|
|
19332
|
+
const sessionIds = ids.filter((id) => typeof id === "string" && id.length > 0);
|
|
19333
|
+
if (sessionIds.length === 0) continue;
|
|
19334
|
+
tabs.push({ sessionIds });
|
|
19335
|
+
}
|
|
19336
|
+
const jobs = [];
|
|
19337
|
+
if (Array.isArray(raw.jobs)) for (const j of raw.jobs) {
|
|
19338
|
+
if (j === null || typeof j !== "object") continue;
|
|
19339
|
+
const owner = j.owner;
|
|
19340
|
+
const jobId = j.jobId;
|
|
19341
|
+
if (typeof owner !== "string" || typeof jobId !== "string") continue;
|
|
19342
|
+
if (owner.length === 0 || jobId.length === 0) continue;
|
|
19343
|
+
jobs.push({
|
|
19344
|
+
owner,
|
|
19345
|
+
jobId
|
|
19346
|
+
});
|
|
19347
|
+
}
|
|
19348
|
+
if (tabs.length === 0 && jobs.length === 0) return void 0;
|
|
19349
|
+
const maxIndex = tabs.length + jobs.length;
|
|
19350
|
+
return {
|
|
19351
|
+
tabs,
|
|
19352
|
+
selectedTab: typeof raw.selectedTab === "number" && Number.isFinite(raw.selectedTab) ? Math.max(0, Math.min(maxIndex, Math.round(raw.selectedTab))) : 0,
|
|
19353
|
+
...jobs.length > 0 ? { jobs } : {}
|
|
19354
|
+
};
|
|
19355
|
+
}
|
|
19356
|
+
/** Persisted defaults when nothing (usable) is stored. */
|
|
19357
|
+
function defaultPanelPrefs() {
|
|
19358
|
+
return {
|
|
19359
|
+
panels: [],
|
|
19360
|
+
selectedPanelId: null,
|
|
19361
|
+
panelWidth: defaultPanelWidth(),
|
|
19362
|
+
zoom: 1,
|
|
19363
|
+
treePct: 30
|
|
19364
|
+
};
|
|
19365
|
+
}
|
|
19366
|
+
/**
|
|
19367
|
+
* Hard shape check for a stored panel entry (the parse boundary).
|
|
19368
|
+
* KIND (2026-09-06, ADR D6): absent or 'conversation' is the legacy shape —
|
|
19369
|
+
* `sessionId` required; 'prompt-manager' carries no session fields;
|
|
19370
|
+
* 'injected-doc' (Loadinjected ADR D2) requires non-empty `sourceSessionId`
|
|
19371
|
+
* + `displayPath` — the dedupe key. Any other kind value is hard junk
|
|
19372
|
+
* (entry drops). `agentPreset` and `width`
|
|
19373
|
+
* may be absent (defaulted later); `agentPreset` when present must be
|
|
19374
|
+
* string|null, `width` when present must be a finite number. Unknown
|
|
19375
|
+
* extra keys are fine — they survive sanitizing.
|
|
19376
|
+
*/
|
|
19377
|
+
function isPanelEntry(value) {
|
|
19378
|
+
if (value === null || typeof value !== "object") return false;
|
|
19379
|
+
const entry = value;
|
|
19380
|
+
if (typeof entry.id !== "string" || entry.id.length === 0) return false;
|
|
19381
|
+
if (entry.kind !== void 0 && entry.kind !== "conversation" && entry.kind !== "prompt-manager" && entry.kind !== "settings-editor" && entry.kind !== "injected-doc" && entry.kind !== "skill-shelf" && entry.kind !== "plugin-rack" && entry.kind !== "workspace-explorer" && entry.kind !== "workspace-file" && entry.kind !== "terminal") return false;
|
|
19382
|
+
if (entry.kind === "settings-editor" && entry.target !== "dsi" && entry.target !== "dsh") return false;
|
|
19383
|
+
if (entry.kind === "workspace-explorer") {
|
|
19384
|
+
if (entry.sessionId !== null && (typeof entry.sessionId !== "string" || entry.sessionId.length === 0)) return false;
|
|
19385
|
+
if (entry.sessionId === null && entry.home !== "dsi" && entry.home !== "dsh") return false;
|
|
19386
|
+
}
|
|
19387
|
+
if (entry.kind === "workspace-file") {
|
|
19388
|
+
if (typeof entry.sessionId !== "string" || entry.sessionId.length === 0) return false;
|
|
19389
|
+
}
|
|
19390
|
+
if (entry.kind === "workspace-explorer" && typeof entry.root !== "string") return false;
|
|
19391
|
+
if (entry.kind === "workspace-file") {
|
|
19392
|
+
if (typeof entry.path !== "string" || entry.path.length === 0) return false;
|
|
19393
|
+
}
|
|
19394
|
+
if (entry.kind === "injected-doc") {
|
|
19395
|
+
if (typeof entry.sourceSessionId !== "string" || entry.sourceSessionId.length === 0) return false;
|
|
19396
|
+
if (typeof entry.displayPath !== "string" || entry.displayPath.length === 0) return false;
|
|
19397
|
+
}
|
|
19398
|
+
if (entry.kind !== "prompt-manager" && entry.kind !== "settings-editor" && entry.kind !== "skill-shelf" && entry.kind !== "plugin-rack" && entry.kind !== "injected-doc" && entry.kind !== "workspace-explorer" && entry.kind !== "workspace-file" && entry.kind !== "terminal") {
|
|
19399
|
+
if (typeof entry.sessionId !== "string" || entry.sessionId.length === 0) return false;
|
|
19400
|
+
if (entry.agentPreset !== void 0 && typeof entry.agentPreset !== "string" && entry.agentPreset !== null) return false;
|
|
19401
|
+
}
|
|
19402
|
+
if (entry.width !== void 0 && (typeof entry.width !== "number" || !Number.isFinite(entry.width))) return false;
|
|
19403
|
+
return true;
|
|
19404
|
+
}
|
|
19405
|
+
/** Drop hard-junk entries; default missing keys; clamp widths. Unknown
|
|
19406
|
+
* keys on surviving entries pass through untouched.
|
|
19407
|
+
*
|
|
19408
|
+
* Duplicate ids (2026-08-24 crash fix): a corrupted blob carrying the
|
|
19409
|
+
* same panel-N twice would reach the keyed each in SidebarOpenPanels
|
|
19410
|
+
* and crash Svelte (each_key_duplicate) at render — the each's key is
|
|
19411
|
+
* the panel id. Duplicates drop to the FIRST occurrence (order is the
|
|
19412
|
+
* floor's left-to-right truth); a selectedPanelId left dangling by the
|
|
19413
|
+
* dedupe re-sanitizes to the first panel in loadPanelPrefs. */
|
|
19414
|
+
function sanitizePanels(raw) {
|
|
19415
|
+
if (!Array.isArray(raw)) return [];
|
|
19416
|
+
const seen = /* @__PURE__ */ new Set();
|
|
19417
|
+
return raw.filter((entry) => isPanelEntry(entry)).map((entry) => {
|
|
19418
|
+
const kindDefault = entry.kind === "skill-shelf" ? shelfPanelWidth() : entry.kind === "plugin-rack" ? shelfPanelWidth() : entry.kind === "workspace-explorer" ? 850 : entry.kind === "workspace-file" ? 850 : defaultPanelWidth();
|
|
19419
|
+
const width = clampPanelWidth(typeof entry.width === "number" && Number.isFinite(entry.width) ? entry.width : kindDefault, entry.kind);
|
|
19420
|
+
if (entry.kind === "prompt-manager") return {
|
|
19421
|
+
id: entry.id,
|
|
19422
|
+
kind: "prompt-manager",
|
|
19423
|
+
width
|
|
19424
|
+
};
|
|
19425
|
+
if (entry.kind === "terminal") {
|
|
19426
|
+
const desk = clampDeskMirror(entry.desk);
|
|
19427
|
+
return {
|
|
19428
|
+
id: entry.id,
|
|
19429
|
+
kind: "terminal",
|
|
19430
|
+
...desk ? { desk } : {},
|
|
19431
|
+
width
|
|
19432
|
+
};
|
|
19433
|
+
}
|
|
19434
|
+
if (entry.kind === "settings-editor") return {
|
|
19435
|
+
id: entry.id,
|
|
19436
|
+
kind: "settings-editor",
|
|
19437
|
+
target: entry.target,
|
|
19438
|
+
width
|
|
19439
|
+
};
|
|
19440
|
+
if (entry.kind === "skill-shelf") {
|
|
19441
|
+
let reload = null;
|
|
19442
|
+
const r = entry.reload;
|
|
19443
|
+
if (r && r.phase === "loading" && typeof r.startedAt === "number") reload = {
|
|
19444
|
+
phase: "loading",
|
|
19445
|
+
startedAt: r.startedAt
|
|
19446
|
+
};
|
|
19447
|
+
else if (r && r.phase === "done" && typeof r.startedAt === "number" && typeof r.doneAt === "number" && r.doneAt > Date.now()) reload = {
|
|
19448
|
+
phase: "done",
|
|
19449
|
+
startedAt: r.startedAt,
|
|
19450
|
+
doneAt: r.doneAt
|
|
19451
|
+
};
|
|
19452
|
+
return {
|
|
19453
|
+
id: entry.id,
|
|
19454
|
+
kind: "skill-shelf",
|
|
19455
|
+
tab: entry.tab === "uninstall" ? "uninstall" : "install",
|
|
19456
|
+
collapsed: clampExpanded(entry.collapsed),
|
|
19457
|
+
searchQ: typeof entry.searchQ === "string" ? entry.searchQ : "",
|
|
19458
|
+
reload,
|
|
19459
|
+
width
|
|
19460
|
+
};
|
|
19461
|
+
}
|
|
19462
|
+
if (entry.kind === "plugin-rack") return {
|
|
19463
|
+
id: entry.id,
|
|
19464
|
+
kind: "plugin-rack",
|
|
19465
|
+
tab: entry.tab === "uninstall" ? "uninstall" : "install",
|
|
19466
|
+
width
|
|
19467
|
+
};
|
|
19468
|
+
if (entry.kind === "injected-doc") return {
|
|
19469
|
+
id: entry.id,
|
|
19470
|
+
kind: "injected-doc",
|
|
19471
|
+
sourceSessionId: entry.sourceSessionId,
|
|
19472
|
+
displayPath: entry.displayPath,
|
|
19473
|
+
width
|
|
19474
|
+
};
|
|
19475
|
+
if (entry.kind === "workspace-explorer") {
|
|
19476
|
+
const home = entry.home === "dsi" || entry.home === "dsh" ? entry.home : void 0;
|
|
19477
|
+
return {
|
|
19478
|
+
id: entry.id,
|
|
19479
|
+
kind: "workspace-explorer",
|
|
19480
|
+
sessionId: entry.sessionId ?? null,
|
|
19481
|
+
root: entry.root,
|
|
19482
|
+
...typeof entry.title === "string" && entry.title.length > 0 ? { title: entry.title } : {},
|
|
19483
|
+
...home !== void 0 ? { home } : {},
|
|
19484
|
+
expanded: clampExpanded(entry.expanded),
|
|
19485
|
+
tab: entry.tab === "changes" ? "changes" : "explorer",
|
|
19486
|
+
collapsedRepos: clampExpanded(entry.collapsedRepos),
|
|
19487
|
+
openTabs: clampExpanded(entry.openTabs),
|
|
19488
|
+
activeFile: typeof entry.activeFile === "string" ? entry.activeFile : null,
|
|
19489
|
+
width
|
|
19490
|
+
};
|
|
19491
|
+
}
|
|
19492
|
+
if (entry.kind === "workspace-file") return {
|
|
19493
|
+
id: entry.id,
|
|
19494
|
+
kind: "workspace-file",
|
|
19495
|
+
sessionId: entry.sessionId,
|
|
19496
|
+
path: entry.path,
|
|
19497
|
+
explorerPanelId: typeof entry.explorerPanelId === "string" && entry.explorerPanelId.length > 0 ? entry.explorerPanelId : null,
|
|
19498
|
+
view: entry.view === "diff" ? "diff" : "edit",
|
|
19499
|
+
width
|
|
19500
|
+
};
|
|
19501
|
+
return {
|
|
19502
|
+
...entry,
|
|
19503
|
+
id: entry.id,
|
|
19504
|
+
kind: "conversation",
|
|
19505
|
+
sessionId: entry.sessionId,
|
|
19506
|
+
agentPreset: entry.agentPreset ?? null,
|
|
19507
|
+
width
|
|
19508
|
+
};
|
|
19509
|
+
}).filter((entry) => {
|
|
19510
|
+
if (seen.has(entry.id)) return false;
|
|
19511
|
+
seen.add(entry.id);
|
|
19512
|
+
return true;
|
|
19513
|
+
});
|
|
19514
|
+
}
|
|
19515
|
+
/**
|
|
19516
|
+
* Read the workspace state from localStorage.
|
|
19517
|
+
* @param profile sanitized workspace profile (null/omitted = default desk).
|
|
19518
|
+
* @returns stored state when parseable (sanitized), defaults when absent,
|
|
19519
|
+
* junk, or SSR. A `selectedPanelId` pointing at a missing panel
|
|
19520
|
+
* sanitizes to the first panel's id (null when no panels remain).
|
|
19521
|
+
*/
|
|
19522
|
+
function loadPanelPrefs(profile) {
|
|
19523
|
+
if (typeof localStorage === "undefined") return defaultPanelPrefs();
|
|
19524
|
+
try {
|
|
19525
|
+
const raw = localStorage.getItem(panelPrefsKey(profile));
|
|
19526
|
+
if (!raw) return defaultPanelPrefs();
|
|
19527
|
+
const parsed = JSON.parse(raw);
|
|
19528
|
+
if (parsed === null || typeof parsed !== "object") return defaultPanelPrefs();
|
|
19529
|
+
if (!Array.isArray(parsed.panels)) return defaultPanelPrefs();
|
|
19530
|
+
const panels = sanitizePanels(parsed.panels);
|
|
19531
|
+
const panelWidth = typeof parsed.panelWidth === "number" && Number.isFinite(parsed.panelWidth) ? clampPanelWidth(parsed.panelWidth) : defaultPanelWidth();
|
|
19532
|
+
const zoom = typeof parsed.zoom === "number" && Number.isFinite(parsed.zoom) ? clampPanelZoom(parsed.zoom) : 1;
|
|
19533
|
+
const treePct = typeof parsed.treePct === "number" && Number.isFinite(parsed.treePct) ? clampTreePct(parsed.treePct) : 30;
|
|
19534
|
+
return {
|
|
19535
|
+
panels,
|
|
19536
|
+
selectedPanelId: typeof parsed.selectedPanelId === "string" && panels.some((panel) => panel.id === parsed.selectedPanelId) ? parsed.selectedPanelId : panels[0]?.id ?? null,
|
|
19537
|
+
panelWidth,
|
|
19538
|
+
zoom,
|
|
19539
|
+
treePct
|
|
19540
|
+
};
|
|
19541
|
+
} catch {
|
|
19542
|
+
return defaultPanelPrefs();
|
|
19543
|
+
}
|
|
19544
|
+
}
|
|
19545
|
+
//#endregion
|
|
19546
|
+
//#region src/lib/components/panels/control-bar/ControlBar.svelte
|
|
19547
|
+
function ControlBar($$renderer, $$props) {
|
|
19548
|
+
$$renderer.component(($$renderer) => {
|
|
19549
|
+
/**
|
|
19550
|
+
* ControlBar — the floor's hover tray (Panel Floor W5 task 5.1,
|
|
19551
|
+
* ADR-0006 R7; OCI ControlBar precedent, minus its orchestration
|
|
19552
|
+
* organs). Pinned top-right over the panels viewport; hovering the
|
|
19553
|
+
* gear trigger reveals the tray, leaving hides it after 250ms (the
|
|
19554
|
+
* timer clears on re-enter, so grazing the tray keeps it open).
|
|
19555
|
+
*
|
|
19556
|
+
* This file owns the trigger + the reveal/hide lifecycle; the tray
|
|
19557
|
+
* body — the floor controls + the action-button row — is
|
|
19558
|
+
* ControlBarTray:
|
|
19559
|
+
* - AddPanel — paste a sessionId → two verbs: Add appends a new
|
|
19560
|
+
* panel beside the focus, Rplc replaces the ACTIVE
|
|
19561
|
+
* panel in place (both registry actions)
|
|
19562
|
+
* - SliderWidth — uniform-width preset 480..860 (`onresizeall` sets
|
|
19563
|
+
* every panel + the preset LIVE per thumb move)
|
|
19564
|
+
* - SliderZoom — floor zoom 25%..125% step 5 ($bindable zoom)
|
|
19565
|
+
* - TrayButtons — the tray's button row (the floor canvas-capture:
|
|
19566
|
+
* `captureContainer` flows the page-owned floor
|
|
19567
|
+
* element down to its CanvasCopyButton)
|
|
19568
|
+
*
|
|
19569
|
+
* Deliberately ABSENT (ADR-0006 R7): RegisterFeature and a home link —
|
|
19570
|
+
* DSI has no orchestration backend for the former, and the sidebar
|
|
19571
|
+
* owns Home for the latter. The OCI tray ships both; this floor does not.
|
|
19572
|
+
*
|
|
19573
|
+
* Communication: AddPanel fires `addPanelFromSidebar` /
|
|
19574
|
+
* `replaceSelectedFromRegistry` through the panel registry — the
|
|
19575
|
+
* tray is a LEAF like a spine row, and the
|
|
19576
|
+
* registry is the only leaf→root action channel (commitment 2). Zoom
|
|
19577
|
+
* is a `$bindable` prop the route owns; every bound routes through
|
|
19578
|
+
* panel-prefs clamps (one clamp site, commitment 3). `onresizeall` is
|
|
19579
|
+
* a ControlBar-specific prop: the tray is a DIRECT child of the
|
|
19580
|
+
* workspace route (not a sidebar intermediate), so prop wiring here
|
|
19581
|
+
* breaks no commitment.
|
|
19582
|
+
*/
|
|
19583
|
+
let { panelWidth = 730, zoom = 1, onresizeall, captureContainer = null } = $$props;
|
|
19584
|
+
let open = false;
|
|
19585
|
+
let $$settled = true;
|
|
19586
|
+
let $$inner_renderer;
|
|
19587
|
+
function $$render_inner($$renderer) {
|
|
19588
|
+
$$renderer.push(`<div data-svelte="ControlBar"${attr_class("controlbar svelte-vs008k", void 0, { "open": open })} role="toolbar"${attr("aria-label", t(floorcontrols1))} aria-orientation="vertical" tabindex="-1" data-testid="controlbar"${attr("data-open", open)}><button type="button" class="trigger svelte-vs008k" data-testid="controlbar-trigger"${attr("aria-label", t(floorcontrols1))}${attr("aria-expanded", open)}>`);
|
|
19589
|
+
Settings($$renderer, {
|
|
19590
|
+
size: 14,
|
|
19591
|
+
"aria-hidden": "true"
|
|
19592
|
+
});
|
|
19593
|
+
$$renderer.push(`<!----></button> `);
|
|
19594
|
+
$$renderer.push("<!--[-1-->");
|
|
19595
|
+
$$renderer.push(`<!--]--></div>`);
|
|
19596
|
+
}
|
|
19597
|
+
do {
|
|
19598
|
+
$$settled = true;
|
|
19599
|
+
$$inner_renderer = $$renderer.copy();
|
|
19600
|
+
$$render_inner($$inner_renderer);
|
|
19601
|
+
} while (!$$settled);
|
|
19602
|
+
$$renderer.subsume($$inner_renderer);
|
|
19603
|
+
bind_props($$props, {
|
|
19604
|
+
panelWidth,
|
|
19605
|
+
zoom
|
|
19606
|
+
});
|
|
19607
|
+
});
|
|
19608
|
+
}
|
|
19609
|
+
//#endregion
|
|
19223
19610
|
//#region src/lib/components/common/layout/AppSidebarHeaderAction.svelte
|
|
19224
19611
|
function AppSidebarHeaderAction($$renderer, $$props) {
|
|
19225
19612
|
$$renderer.component(($$renderer) => {
|
|
19226
19613
|
/**
|
|
19227
19614
|
* AppSidebarHeaderAction — the expanded rail header's right-hand action
|
|
19228
19615
|
* cluster (extracted from AppSidebar, 2026-09): add-workspace, locale
|
|
19229
|
-
* switcher, canvas copy, and the collapse button.
|
|
19616
|
+
* switcher, canvas copy, and the collapse button. The floor ControlBar
|
|
19617
|
+
* (2026-10-22) rides the cluster's head — it self-positions fixed
|
|
19618
|
+
* top-right over the floor, so hosting it here is purely a mount-site
|
|
19619
|
+
* move; the page still owns panelWidth/zoom state and the resize-all
|
|
19620
|
+
* handler, threaded through the sidebar as $bindable props.
|
|
19230
19621
|
*/
|
|
19231
|
-
let { captureContainer = null} = $$props;
|
|
19232
|
-
$$
|
|
19233
|
-
|
|
19234
|
-
|
|
19235
|
-
|
|
19236
|
-
|
|
19237
|
-
|
|
19238
|
-
|
|
19622
|
+
let { captureContainer = null, trayContainer = null, panelWidth = 730, zoom = 1, onresizeall, onToggleCollapse } = $$props;
|
|
19623
|
+
let $$settled = true;
|
|
19624
|
+
let $$inner_renderer;
|
|
19625
|
+
function $$render_inner($$renderer) {
|
|
19626
|
+
$$renderer.push(`<div data-svelte="AppSidebarHeaderAction" class="rail-header-actions svelte-ijmtbh">`);
|
|
19627
|
+
CanvasCopyButton($$renderer, {
|
|
19628
|
+
container: captureContainer,
|
|
19629
|
+
mode: "visible",
|
|
19630
|
+
title: t(copypageimage2),
|
|
19631
|
+
size: 14,
|
|
19632
|
+
class: "inline-flex h-[22px] w-[22px] shrink-0 items-center justify-center rounded transition-colors hover:bg-surface-hover"
|
|
19633
|
+
});
|
|
19634
|
+
$$renderer.push(`<!----> <button type="button" class="icon-btn svelte-ijmtbh"${attr("aria-expanded", true)}${attr("aria-label", t(collapsesidebar1))}${attr("title", t(collapsesidebar1))}>`);
|
|
19635
|
+
Panel_left_close($$renderer, { size: 14 });
|
|
19636
|
+
$$renderer.push(`<!----></button> `);
|
|
19637
|
+
ControlBar($$renderer, {
|
|
19638
|
+
onresizeall: onresizeall ?? (() => {}),
|
|
19639
|
+
captureContainer: trayContainer,
|
|
19640
|
+
get panelWidth() {
|
|
19641
|
+
return panelWidth;
|
|
19642
|
+
},
|
|
19643
|
+
set panelWidth($$value) {
|
|
19644
|
+
panelWidth = $$value;
|
|
19645
|
+
$$settled = false;
|
|
19646
|
+
},
|
|
19647
|
+
get zoom() {
|
|
19648
|
+
return zoom;
|
|
19649
|
+
},
|
|
19650
|
+
set zoom($$value) {
|
|
19651
|
+
zoom = $$value;
|
|
19652
|
+
$$settled = false;
|
|
19653
|
+
}
|
|
19654
|
+
});
|
|
19655
|
+
$$renderer.push(`<!----></div>`);
|
|
19656
|
+
}
|
|
19657
|
+
do {
|
|
19658
|
+
$$settled = true;
|
|
19659
|
+
$$inner_renderer = $$renderer.copy();
|
|
19660
|
+
$$render_inner($$inner_renderer);
|
|
19661
|
+
} while (!$$settled);
|
|
19662
|
+
$$renderer.subsume($$inner_renderer);
|
|
19663
|
+
bind_props($$props, {
|
|
19664
|
+
panelWidth,
|
|
19665
|
+
zoom
|
|
19239
19666
|
});
|
|
19240
|
-
$$renderer.push(`<!----> <button type="button" class="icon-btn svelte-ijmtbh"${attr("aria-expanded", true)}${attr("aria-label", t(collapsesidebar1))}${attr("title", t(collapsesidebar1))}>`);
|
|
19241
|
-
Panel_left_close($$renderer, { size: 14 });
|
|
19242
|
-
$$renderer.push(`<!----></button></div>`);
|
|
19243
19667
|
});
|
|
19244
19668
|
}
|
|
19245
19669
|
//#endregion
|
|
@@ -19283,29 +19707,63 @@ function RestartButton($$renderer, $$props) {
|
|
|
19283
19707
|
//#endregion
|
|
19284
19708
|
//#region src/lib/components/common/layout/AppSidebarHeader.svelte
|
|
19285
19709
|
function AppSidebarHeader($$renderer, $$props) {
|
|
19286
|
-
|
|
19287
|
-
|
|
19288
|
-
|
|
19289
|
-
|
|
19290
|
-
|
|
19291
|
-
|
|
19292
|
-
|
|
19293
|
-
|
|
19294
|
-
|
|
19295
|
-
|
|
19296
|
-
|
|
19297
|
-
|
|
19298
|
-
|
|
19299
|
-
|
|
19300
|
-
|
|
19301
|
-
|
|
19302
|
-
|
|
19303
|
-
|
|
19304
|
-
|
|
19305
|
-
|
|
19306
|
-
|
|
19307
|
-
|
|
19308
|
-
|
|
19710
|
+
$$renderer.component(($$renderer) => {
|
|
19711
|
+
/**
|
|
19712
|
+
* AppSidebarHeader — the expanded rail header (extracted from
|
|
19713
|
+
* AppSidebar, 2026-09): the About prefix, the brand title, and the
|
|
19714
|
+
* right-hand action cluster, composed from AboutButton,
|
|
19715
|
+
* AppSidebarHeaderTitle, and AppSidebarHeaderAction. Owns the
|
|
19716
|
+
* animated gradient surface for the expanded state (the collapsed
|
|
19717
|
+
* stub keeps its copy in AppSidebar — Svelte styles are
|
|
19718
|
+
* component-scoped, so the shared rule had to be split; keep the two
|
|
19719
|
+
* gradients in sync).
|
|
19720
|
+
*
|
|
19721
|
+
* Presentational only — collapse flipping stays delegated upward.
|
|
19722
|
+
*/
|
|
19723
|
+
let { captureContainer = null, trayContainer = null, panelWidth = 730, zoom = 1, onresizeall, onToggleCollapse } = $$props;
|
|
19724
|
+
let $$settled = true;
|
|
19725
|
+
let $$inner_renderer;
|
|
19726
|
+
function $$render_inner($$renderer) {
|
|
19727
|
+
$$renderer.push(`<header data-svelte="AppSidebarHeader" class="rail-header svelte-184i93r">`);
|
|
19728
|
+
RestartButton($$renderer, { class: "rail-collapsed-label" });
|
|
19729
|
+
$$renderer.push(`<!----> `);
|
|
19730
|
+
AboutButton($$renderer, {});
|
|
19731
|
+
$$renderer.push(`<!----> `);
|
|
19732
|
+
AppSidebarHeaderTitle($$renderer);
|
|
19733
|
+
$$renderer.push(`<!----> `);
|
|
19734
|
+
AppSidebarHeaderAction($$renderer, {
|
|
19735
|
+
captureContainer,
|
|
19736
|
+
trayContainer,
|
|
19737
|
+
onresizeall,
|
|
19738
|
+
onToggleCollapse,
|
|
19739
|
+
get panelWidth() {
|
|
19740
|
+
return panelWidth;
|
|
19741
|
+
},
|
|
19742
|
+
set panelWidth($$value) {
|
|
19743
|
+
panelWidth = $$value;
|
|
19744
|
+
$$settled = false;
|
|
19745
|
+
},
|
|
19746
|
+
get zoom() {
|
|
19747
|
+
return zoom;
|
|
19748
|
+
},
|
|
19749
|
+
set zoom($$value) {
|
|
19750
|
+
zoom = $$value;
|
|
19751
|
+
$$settled = false;
|
|
19752
|
+
}
|
|
19753
|
+
});
|
|
19754
|
+
$$renderer.push(`<!----></header>`);
|
|
19755
|
+
}
|
|
19756
|
+
do {
|
|
19757
|
+
$$settled = true;
|
|
19758
|
+
$$inner_renderer = $$renderer.copy();
|
|
19759
|
+
$$render_inner($$inner_renderer);
|
|
19760
|
+
} while (!$$settled);
|
|
19761
|
+
$$renderer.subsume($$inner_renderer);
|
|
19762
|
+
bind_props($$props, {
|
|
19763
|
+
panelWidth,
|
|
19764
|
+
zoom
|
|
19765
|
+
});
|
|
19766
|
+
});
|
|
19309
19767
|
}
|
|
19310
19768
|
//#endregion
|
|
19311
19769
|
//#region src/lib/components/common/layout/AppSidebar.svelte
|
|
@@ -19341,52 +19799,118 @@ function AppSidebar($$renderer, $$props) {
|
|
|
19341
19799
|
* page (OCI ownership split); the gutter just reports mousedown, and the
|
|
19342
19800
|
* single width clamp lives in sidebar-prefs (clampSidebarWidth).
|
|
19343
19801
|
*/
|
|
19344
|
-
let { profile = null, collapsed = false, width = 400, embedded = false, currentSessionId, paneledSessionIds = [], captureContainer = null, onToggleCollapse} = $$props;
|
|
19802
|
+
let { profile = null, collapsed = false, width = 400, embedded = false, currentSessionId, paneledSessionIds = [], captureContainer = null, trayContainer = null, glassRows = [], panelWidth = 730, zoom = 1, onresizeall, onToggleCollapse, onResizeStart } = $$props;
|
|
19345
19803
|
let filter = loadSessionFilter(profile);
|
|
19346
|
-
|
|
19347
|
-
|
|
19348
|
-
|
|
19349
|
-
|
|
19350
|
-
|
|
19351
|
-
|
|
19352
|
-
|
|
19353
|
-
|
|
19354
|
-
|
|
19355
|
-
|
|
19356
|
-
|
|
19357
|
-
|
|
19358
|
-
|
|
19359
|
-
|
|
19360
|
-
|
|
19361
|
-
|
|
19362
|
-
|
|
19363
|
-
|
|
19364
|
-
|
|
19365
|
-
|
|
19366
|
-
|
|
19367
|
-
|
|
19368
|
-
|
|
19369
|
-
|
|
19370
|
-
|
|
19371
|
-
|
|
19372
|
-
|
|
19373
|
-
|
|
19374
|
-
|
|
19375
|
-
|
|
19376
|
-
|
|
19377
|
-
|
|
19378
|
-
|
|
19379
|
-
|
|
19380
|
-
|
|
19381
|
-
|
|
19382
|
-
|
|
19383
|
-
|
|
19384
|
-
|
|
19385
|
-
|
|
19386
|
-
|
|
19387
|
-
|
|
19804
|
+
let $$settled = true;
|
|
19805
|
+
let $$inner_renderer;
|
|
19806
|
+
function $$render_inner($$renderer) {
|
|
19807
|
+
if (collapsed) {
|
|
19808
|
+
$$renderer.push("<!--[0-->");
|
|
19809
|
+
$$renderer.push(`<div data-svelte="AppSidebar" class="rail-collapsed svelte-113gpvg" data-testid="app-sidebar-collapsed">`);
|
|
19810
|
+
ControlBar($$renderer, {
|
|
19811
|
+
onresizeall: onresizeall ?? (() => {}),
|
|
19812
|
+
captureContainer: trayContainer,
|
|
19813
|
+
get panelWidth() {
|
|
19814
|
+
return panelWidth;
|
|
19815
|
+
},
|
|
19816
|
+
set panelWidth($$value) {
|
|
19817
|
+
panelWidth = $$value;
|
|
19818
|
+
$$settled = false;
|
|
19819
|
+
},
|
|
19820
|
+
get zoom() {
|
|
19821
|
+
return zoom;
|
|
19822
|
+
},
|
|
19823
|
+
set zoom($$value) {
|
|
19824
|
+
zoom = $$value;
|
|
19825
|
+
$$settled = false;
|
|
19826
|
+
}
|
|
19827
|
+
});
|
|
19828
|
+
$$renderer.push(`<!----> `);
|
|
19829
|
+
RestartButton($$renderer, { class: "rail-collapsed-label" });
|
|
19830
|
+
$$renderer.push(`<!----> `);
|
|
19831
|
+
AboutButton($$renderer, { class: "rail-collapsed-label" });
|
|
19832
|
+
$$renderer.push(`<!----> <button type="button" class="stub-expand svelte-113gpvg"${attr("aria-expanded", false)}${attr("aria-label", t(expandsidebar1))}${attr("title", t(expandsidebar1))}>`);
|
|
19833
|
+
Panel_left_close($$renderer, {
|
|
19834
|
+
size: 14,
|
|
19835
|
+
class: "rotate-180"
|
|
19836
|
+
});
|
|
19837
|
+
$$renderer.push(`<!----> <span class="rail-collapsed-label svelte-113gpvg">Deepseek Insight</span></button></div>`);
|
|
19838
|
+
} else if (embedded) {
|
|
19839
|
+
$$renderer.push("<!--[1-->");
|
|
19840
|
+
$$renderer.push(`<aside data-svelte="AppSidebar" class="rail rail-embedded svelte-113gpvg" data-testid="app-sidebar">`);
|
|
19841
|
+
AppSidebarHeader($$renderer, {
|
|
19842
|
+
captureContainer,
|
|
19843
|
+
trayContainer,
|
|
19844
|
+
onresizeall,
|
|
19845
|
+
onToggleCollapse,
|
|
19846
|
+
get panelWidth() {
|
|
19847
|
+
return panelWidth;
|
|
19848
|
+
},
|
|
19849
|
+
set panelWidth($$value) {
|
|
19850
|
+
panelWidth = $$value;
|
|
19851
|
+
$$settled = false;
|
|
19852
|
+
},
|
|
19853
|
+
get zoom() {
|
|
19854
|
+
return zoom;
|
|
19855
|
+
},
|
|
19856
|
+
set zoom($$value) {
|
|
19857
|
+
zoom = $$value;
|
|
19858
|
+
$$settled = false;
|
|
19859
|
+
}
|
|
19860
|
+
});
|
|
19861
|
+
$$renderer.push(`<!----> `);
|
|
19862
|
+
SidebarSessions($$renderer, {
|
|
19863
|
+
currentSessionId,
|
|
19864
|
+
paneledSessionIds,
|
|
19865
|
+
filter,
|
|
19866
|
+
onfilterchange: (f) => filter = f
|
|
19867
|
+
});
|
|
19868
|
+
$$renderer.push(`<!----></aside>`);
|
|
19869
|
+
} else {
|
|
19870
|
+
$$renderer.push("<!--[-1-->");
|
|
19871
|
+
$$renderer.push(`<div data-svelte="AppSidebar" class="rail-wrap svelte-113gpvg" data-testid="app-sidebar"${attr_style(`width: ${stringify(width)}px`)}><aside class="rail svelte-113gpvg">`);
|
|
19872
|
+
AppSidebarHeader($$renderer, {
|
|
19873
|
+
captureContainer,
|
|
19874
|
+
trayContainer,
|
|
19875
|
+
onresizeall,
|
|
19876
|
+
onToggleCollapse,
|
|
19877
|
+
get panelWidth() {
|
|
19878
|
+
return panelWidth;
|
|
19879
|
+
},
|
|
19880
|
+
set panelWidth($$value) {
|
|
19881
|
+
panelWidth = $$value;
|
|
19882
|
+
$$settled = false;
|
|
19883
|
+
},
|
|
19884
|
+
get zoom() {
|
|
19885
|
+
return zoom;
|
|
19886
|
+
},
|
|
19887
|
+
set zoom($$value) {
|
|
19888
|
+
zoom = $$value;
|
|
19889
|
+
$$settled = false;
|
|
19890
|
+
}
|
|
19891
|
+
});
|
|
19892
|
+
$$renderer.push(`<!----> `);
|
|
19893
|
+
SidebarSessions($$renderer, {
|
|
19894
|
+
currentSessionId,
|
|
19895
|
+
paneledSessionIds,
|
|
19896
|
+
filter,
|
|
19897
|
+
glassRows,
|
|
19898
|
+
onfilterchange: (f) => filter = f
|
|
19899
|
+
});
|
|
19900
|
+
$$renderer.push(`<!----></aside> <div class="rail-gutter svelte-113gpvg" data-testid="sidebar-gutter" role="separator" aria-orientation="vertical"${attr("aria-label", t(resizesidebar1))}></div></div>`);
|
|
19901
|
+
}
|
|
19902
|
+
$$renderer.push(`<!--]-->`);
|
|
19388
19903
|
}
|
|
19389
|
-
|
|
19904
|
+
do {
|
|
19905
|
+
$$settled = true;
|
|
19906
|
+
$$inner_renderer = $$renderer.copy();
|
|
19907
|
+
$$render_inner($$inner_renderer);
|
|
19908
|
+
} while (!$$settled);
|
|
19909
|
+
$$renderer.subsume($$inner_renderer);
|
|
19910
|
+
bind_props($$props, {
|
|
19911
|
+
panelWidth,
|
|
19912
|
+
zoom
|
|
19913
|
+
});
|
|
19390
19914
|
});
|
|
19391
19915
|
}
|
|
19392
19916
|
//#endregion
|
|
@@ -22213,6 +22737,25 @@ function PromptManagerPanel($$renderer, $$props) {
|
|
|
22213
22737
|
function sessionOf(p) {
|
|
22214
22738
|
return p.kind === "conversation" ? p.sessionId : null;
|
|
22215
22739
|
}
|
|
22740
|
+
/**
|
|
22741
|
+
* The end index of the contiguous injected-doc tail following the index
|
|
22742
|
+
* "end" whose documents belong to "sourceSessionId" (Loadinjected ADR
|
|
22743
|
+
* D3, consolidated 2026-09-07). DOCUMENTS ONLY — deliberately NOT the
|
|
22744
|
+
* workspace tail (2026-09-10 order fix): a session child pinned under
|
|
22745
|
+
* this parent lands directly below it (the Lineage Pin) and pushes the
|
|
22746
|
+
* explorer/file pair right, keeping the floor order identical to the
|
|
22747
|
+
* sidebar's familyRenderOrder. The workspace pair stays contiguous via
|
|
22748
|
+
* unitOf/explorerUnit — it does not displace pinned children.
|
|
22749
|
+
*/
|
|
22750
|
+
function docTailEnd(panels, end, sourceSessionId) {
|
|
22751
|
+
let i = end;
|
|
22752
|
+
while (i + 1 < panels.length) {
|
|
22753
|
+
const p = panels[i + 1];
|
|
22754
|
+
if (p.kind !== "injected-doc" || p.sourceSessionId !== sourceSessionId) break;
|
|
22755
|
+
i++;
|
|
22756
|
+
}
|
|
22757
|
+
return i;
|
|
22758
|
+
}
|
|
22216
22759
|
/** Does the file panel's edge name this explorer — directly, or through
|
|
22217
22760
|
* the legacy null edge restored before the edge existed (then adjacency
|
|
22218
22761
|
* plus the shared session IS the edge; the dedupe keeps one explorer per
|
|
@@ -22343,13 +22886,31 @@ function blockBounds(panels, idx, facts) {
|
|
|
22343
22886
|
if (head !== void 0 && head.kind === "workspace-explorer" && fileBelongsTo(at, head)) return explorerUnit(panels, i - 1);
|
|
22344
22887
|
return [idx, idx];
|
|
22345
22888
|
}
|
|
22346
|
-
if (at.kind
|
|
22347
|
-
|
|
22348
|
-
|
|
22349
|
-
|
|
22350
|
-
|
|
22351
|
-
|
|
22352
|
-
|
|
22889
|
+
if (at.kind === "browser") {
|
|
22890
|
+
let i = idx;
|
|
22891
|
+
while (i > 0 && panels[i - 1].kind === "browser") i--;
|
|
22892
|
+
const head = panels[i - 1];
|
|
22893
|
+
const inFamily = (id, root) => {
|
|
22894
|
+
if (id === void 0) return false;
|
|
22895
|
+
let cur = id;
|
|
22896
|
+
for (let guard = 0; guard < panels.length + 1 && cur !== null; guard++) {
|
|
22897
|
+
if (cur === root) return true;
|
|
22898
|
+
cur = facts.parentOf.get(cur) ?? null;
|
|
22899
|
+
}
|
|
22900
|
+
return false;
|
|
22901
|
+
};
|
|
22902
|
+
if (head === void 0 || head.kind !== "conversation" || !inFamily(head.sessionId, at.openedBy)) return [idx, idx];
|
|
22903
|
+
sessionId = head.sessionId;
|
|
22904
|
+
}
|
|
22905
|
+
if (at.kind !== "injected-doc" && sessionId === null) return [idx, idx];
|
|
22906
|
+
if (at.kind === "injected-doc") {
|
|
22907
|
+
let i = idx;
|
|
22908
|
+
while (i > 0 && panels[i - 1].kind === "injected-doc") i--;
|
|
22909
|
+
const head = panels[i - 1];
|
|
22910
|
+
if (head === void 0 || head.kind !== "conversation") return [idx, idx];
|
|
22911
|
+
if (head.sessionId !== at.sourceSessionId) return [idx, idx];
|
|
22912
|
+
sessionId = head.sessionId;
|
|
22913
|
+
}
|
|
22353
22914
|
}
|
|
22354
22915
|
for (let guard = 0; guard < panels.length + 1; guard++) {
|
|
22355
22916
|
const parent = facts.parentOf.get(sessionId) ?? null;
|
|
@@ -22392,6 +22953,10 @@ function unitOf(panels, sessionId, facts) {
|
|
|
22392
22953
|
end = i;
|
|
22393
22954
|
continue;
|
|
22394
22955
|
}
|
|
22956
|
+
if (p.kind === "browser" && p.openedBy !== void 0 && familySessions.has(p.openedBy)) {
|
|
22957
|
+
end = i;
|
|
22958
|
+
continue;
|
|
22959
|
+
}
|
|
22395
22960
|
break;
|
|
22396
22961
|
}
|
|
22397
22962
|
return [start, end];
|
|
@@ -22660,7 +23225,27 @@ function panelRowsFor(input) {
|
|
|
22660
23225
|
const { panels, spineRows, coldCache, deadSessions, edgeCache, lineageFacts, moveFacts } = input;
|
|
22661
23226
|
const openSessionIds = openSessionIdsOf(panels);
|
|
22662
23227
|
return panels.map((p, index) => {
|
|
22663
|
-
if (p.kind === "
|
|
23228
|
+
if (p.kind === "browser") {
|
|
23229
|
+
const parentOpen = p.openedBy !== void 0 && openSessionIds.has(p.openedBy);
|
|
23230
|
+
const openerDepth = p.openedBy !== void 0 ? lineageFacts.depthById.get(p.openedBy) ?? 0 : 0;
|
|
23231
|
+
return {
|
|
23232
|
+
panel: p,
|
|
23233
|
+
title: "Browser",
|
|
23234
|
+
workspace: null,
|
|
23235
|
+
dead: false,
|
|
23236
|
+
running: false,
|
|
23237
|
+
depth: parentOpen ? openerDepth + 1 : 0,
|
|
23238
|
+
runningDescendants: 0,
|
|
23239
|
+
kind: "panel",
|
|
23240
|
+
parentSessionId: p.openedBy ?? null,
|
|
23241
|
+
fork: false,
|
|
23242
|
+
spawnerTitle: null,
|
|
23243
|
+
siblingIndex: -1,
|
|
23244
|
+
canMoveUp: false,
|
|
23245
|
+
canMoveDown: false
|
|
23246
|
+
};
|
|
23247
|
+
}
|
|
23248
|
+
if (p.kind === "terminal" || p.kind === "prompt-manager" || p.kind === "settings-editor" || p.kind === "skill-shelf" || p.kind === "plugin-rack") return {
|
|
22664
23249
|
panel: p,
|
|
22665
23250
|
title: p.kind === "terminal" ? "Terminal" : p.kind === "browser" ? "Browser" : p.kind === "prompt-manager" ? MANAGER_ROW_TITLE : p.kind === "skill-shelf" ? "Skill Shelf" : p.kind === "plugin-rack" ? "Plugin Rack" : p.kind === "settings-editor" ? SETTINGS_ROW_TITLE[p.target] : "",
|
|
22666
23251
|
workspace: null,
|
|
@@ -26047,9 +26632,10 @@ function hasDotDotSegment(path) {
|
|
|
26047
26632
|
function parseFileLinkHref(href) {
|
|
26048
26633
|
const value = stripAngleWrapper(href.trim());
|
|
26049
26634
|
const hash = value.indexOf("#");
|
|
26050
|
-
const raw = hash === -1 ? value : value.slice(0, hash);
|
|
26635
|
+
const raw = hash === -1 ? splitColonAnchor(value).path : value.slice(0, hash);
|
|
26051
26636
|
const anchor = hash === -1 ? "" : value.slice(hash + 1);
|
|
26052
26637
|
let lines = null;
|
|
26638
|
+
if (hash === -1) lines = splitColonAnchor(value).lines;
|
|
26053
26639
|
const single = anchor.match(/^L?(\d+)$/);
|
|
26054
26640
|
const range = anchor.match(/^L?(\d+)-L?(\d+)$/);
|
|
26055
26641
|
if (single) {
|
|
@@ -26074,6 +26660,48 @@ function parseFileLinkHref(href) {
|
|
|
26074
26660
|
/** CommonMark angle-bracket destinations (<path> and their %3C/%3E
|
|
26075
26661
|
* encodings) are destination syntax, never path bytes - renderers that
|
|
26076
26662
|
* hand the wrapper through must not have it reach the host read. */
|
|
26663
|
+
/**
|
|
26664
|
+
* The colon anchor arm (ADR-0028 The Colon Anchor): IDE-style :line
|
|
26665
|
+
* suffixes — path/file.ts:334, :10-20 — are the SAME fact as #L anchors
|
|
26666
|
+
* in IDE clothes, so they split into the display hint the same way.
|
|
26667
|
+
* Digits-only tail after the LAST colon; a malformed tail (:0, :20-10)
|
|
26668
|
+
* degrades to no hint and KEEPS the colon in the path (never guesses,
|
|
26669
|
+
* hash-grammar posture); any other colon stays path bytes (a:b/c.ts).
|
|
26670
|
+
*/
|
|
26671
|
+
function splitColonAnchor(value) {
|
|
26672
|
+
const colon = value.lastIndexOf(":");
|
|
26673
|
+
if (colon === -1) return {
|
|
26674
|
+
path: value,
|
|
26675
|
+
lines: null
|
|
26676
|
+
};
|
|
26677
|
+
const tail = value.slice(colon + 1);
|
|
26678
|
+
const single = tail.match(/^(\d+)$/);
|
|
26679
|
+
const range = tail.match(/^(\d+)-(\d+)$/);
|
|
26680
|
+
if (single) {
|
|
26681
|
+
const n = Number(single[1]);
|
|
26682
|
+
if (n >= 1) return {
|
|
26683
|
+
path: value.slice(0, colon),
|
|
26684
|
+
lines: {
|
|
26685
|
+
start: n,
|
|
26686
|
+
end: n
|
|
26687
|
+
}
|
|
26688
|
+
};
|
|
26689
|
+
} else if (range) {
|
|
26690
|
+
const s = Number(range[1]);
|
|
26691
|
+
const e = Number(range[2]);
|
|
26692
|
+
if (s >= 1 && e >= s) return {
|
|
26693
|
+
path: value.slice(0, colon),
|
|
26694
|
+
lines: {
|
|
26695
|
+
start: s,
|
|
26696
|
+
end: e
|
|
26697
|
+
}
|
|
26698
|
+
};
|
|
26699
|
+
}
|
|
26700
|
+
return {
|
|
26701
|
+
path: value,
|
|
26702
|
+
lines: null
|
|
26703
|
+
};
|
|
26704
|
+
}
|
|
26077
26705
|
function stripAngleWrapper(value) {
|
|
26078
26706
|
return value.replace(/^(?:%3C|<)/i, "").replace(/(?:%3E|>)$/i, "");
|
|
26079
26707
|
}
|
|
@@ -26081,6 +26709,7 @@ function normalizeFileLinkPath(href) {
|
|
|
26081
26709
|
let value = stripAngleWrapper(href.trim()).replace(/^\.\//, "").replace(/\/{2,}/g, "/");
|
|
26082
26710
|
const hash = value.indexOf("#");
|
|
26083
26711
|
if (hash !== -1) value = value.slice(0, hash);
|
|
26712
|
+
value = splitColonAnchor(value).path;
|
|
26084
26713
|
if (value.startsWith("/")) value = value.slice(1);
|
|
26085
26714
|
if (value === "" || hasDotDotSegment(value)) return null;
|
|
26086
26715
|
return value;
|
|
@@ -27484,7 +28113,7 @@ function ReasoningSection($$renderer, $$props) {
|
|
|
27484
28113
|
$$renderer.push(`<!--]--> <span class="text-[10px]">${escape_html(t(thinklabel1))}</span> `);
|
|
27485
28114
|
if (streaming) {
|
|
27486
28115
|
$$renderer.push("<!--[0-->");
|
|
27487
|
-
SessionStatus($$renderer, {
|
|
28116
|
+
SessionStatus($$renderer, { });
|
|
27488
28117
|
} else $$renderer.push("<!--[-1-->");
|
|
27489
28118
|
$$renderer.push(`<!--]--></button></div>`);
|
|
27490
28119
|
} else $$renderer.push("<!--[-1-->");
|
|
@@ -32155,18 +32784,6 @@ function TerminalDesk($$renderer, $$props) {
|
|
|
32155
32784
|
bind_props($$props, { applyAction });
|
|
32156
32785
|
});
|
|
32157
32786
|
}
|
|
32158
|
-
//#endregion
|
|
32159
|
-
//#region src/lib/services/panels/browser-session-resolver.ts
|
|
32160
|
-
/**
|
|
32161
|
-
* browser-session-resolver — the ONE re-bind-or-open seam (The Sticky Glass
|
|
32162
|
-
* spec Wave 2 task 2.1; ADR-0030 D1/D4). The chip, the floor placement, and
|
|
32163
|
-
* the panel's remount all ask here; none of them POSTs /api/browser open
|
|
32164
|
-
* directly. Policy: the persisted localStorage id wins if the registry still
|
|
32165
|
-
* lists it live (RE-BIND — reload survival); a dead id falls through to a
|
|
32166
|
-
* fresh open, never an error surface. The resolved id is persisted so the
|
|
32167
|
-
* NEXT reload re-binds too.
|
|
32168
|
-
*/
|
|
32169
|
-
var LS_KEY = "dsi.browser.sessionId";
|
|
32170
32787
|
/** localStorage guarded — SSR and privacy modes have no window.localStorage. */
|
|
32171
32788
|
function defaultStorage() {
|
|
32172
32789
|
try {
|
|
@@ -32175,23 +32792,62 @@ function defaultStorage() {
|
|
|
32175
32792
|
return null;
|
|
32176
32793
|
}
|
|
32177
32794
|
}
|
|
32178
|
-
function readPersistedId(storage = defaultStorage()) {
|
|
32179
|
-
try {
|
|
32180
|
-
return storage?.getItem(LS_KEY) ?? null;
|
|
32181
|
-
} catch {
|
|
32182
|
-
return null;
|
|
32183
|
-
}
|
|
32184
|
-
}
|
|
32185
32795
|
var IDX_KEY = "dsi.browser.panelIndex";
|
|
32186
|
-
|
|
32796
|
+
/** Read the persisted glass list; every legacy shape upgrades, junk
|
|
32797
|
+
* drops. Sorted by floor position (restore order = floor order). */
|
|
32798
|
+
function readBrowserSlots(storage = defaultStorage()) {
|
|
32187
32799
|
try {
|
|
32188
32800
|
const raw = storage?.getItem(IDX_KEY);
|
|
32189
|
-
|
|
32190
|
-
|
|
32801
|
+
if (raw === null || raw === void 0) return [];
|
|
32802
|
+
const parsed = JSON.parse(raw);
|
|
32803
|
+
const list = Array.isArray(parsed) ? parsed : parsed !== null && typeof parsed === "object" && Array.isArray(parsed.slots) ? parsed.slots : [parsed];
|
|
32804
|
+
const out = [];
|
|
32805
|
+
for (const item of list) {
|
|
32806
|
+
if (typeof item === "number") {
|
|
32807
|
+
if (Number.isInteger(item) && item >= 0) out.push({ index: item });
|
|
32808
|
+
continue;
|
|
32809
|
+
}
|
|
32810
|
+
if (item === null || typeof item !== "object") continue;
|
|
32811
|
+
const o = item;
|
|
32812
|
+
if (!Number.isInteger(o.index) || o.index < 0) continue;
|
|
32813
|
+
const slot = { index: o.index };
|
|
32814
|
+
if (typeof o.width === "number" && Number.isFinite(o.width) && o.width > 0) slot.width = o.width;
|
|
32815
|
+
if (typeof o.openedBy === "string" && o.openedBy.length > 0) slot.openedBy = o.openedBy;
|
|
32816
|
+
if (typeof o.sessionId === "string" && o.sessionId.length > 0) slot.sessionId = o.sessionId;
|
|
32817
|
+
if (o.folded === true) slot.folded = true;
|
|
32818
|
+
out.push(slot);
|
|
32819
|
+
}
|
|
32820
|
+
return out.sort((a, b) => a.index - b.index);
|
|
32191
32821
|
} catch {
|
|
32192
|
-
return
|
|
32822
|
+
return [];
|
|
32193
32823
|
}
|
|
32194
32824
|
}
|
|
32825
|
+
/** Write the whole glass list; an empty list clears the key. Also
|
|
32826
|
+
* mirrors the written list into the reactive store — the sidebar's
|
|
32827
|
+
* folded-glass rows derive from it (ADR-0037 D4). */
|
|
32828
|
+
function persistBrowserSlots(slots, storage = defaultStorage()) {
|
|
32829
|
+
try {
|
|
32830
|
+
if (slots.length > 0) storage?.setItem(IDX_KEY, JSON.stringify(slots));
|
|
32831
|
+
else storage?.removeItem(IDX_KEY);
|
|
32832
|
+
} catch {}
|
|
32833
|
+
browserSlotStore.set([...slots]);
|
|
32834
|
+
}
|
|
32835
|
+
/** Reactive mirror of the persisted glass list (Svelte store — the
|
|
32836
|
+
* plain .ts module stays rune-free). Rows and the route derive the
|
|
32837
|
+
* folded set from it; persistBrowserSlots is the only writer. */
|
|
32838
|
+
var browserSlotStore = writable([]);
|
|
32839
|
+
/** Seed the mirror from storage (boot). */
|
|
32840
|
+
function primeBrowserSlotStore(storage = defaultStorage()) {
|
|
32841
|
+
browserSlotStore.set(readBrowserSlots(storage));
|
|
32842
|
+
}
|
|
32843
|
+
//#endregion
|
|
32844
|
+
//#region src/lib/components/browser/BrowserClosed.svelte
|
|
32845
|
+
function BrowserClosed($$renderer, $$props) {
|
|
32846
|
+
$$renderer.component(($$renderer) => {
|
|
32847
|
+
let { closing = false} = $$props;
|
|
32848
|
+
$$renderer.push(`<button data-svelte="BrowserClosed" class="rounded px-1 hover:bg-surface-active" data-testid="browse-close"${attr("disabled", closing, true)}>✕</button>`);
|
|
32849
|
+
});
|
|
32850
|
+
}
|
|
32195
32851
|
//#endregion
|
|
32196
32852
|
//#region src/lib/components/browser/BrowserHeader.svelte
|
|
32197
32853
|
function BrowserHeader($$renderer, $$props) {
|
|
@@ -32209,7 +32865,10 @@ function BrowserHeader($$renderer, $$props) {
|
|
|
32209
32865
|
$$renderer.push("<!--[0-->");
|
|
32210
32866
|
$$renderer.push(`<span class="rounded-t-md border border-b-0 border-surface-border bg-surface-elevated px-2 py-0.5 font-mono text-[10px] opacity-80" data-testid="browser-session-tab">${escape_html(sessionId.slice(0, 8))}</span>`);
|
|
32211
32867
|
} else $$renderer.push("<!--[-1-->");
|
|
32212
|
-
$$renderer.push(`<!--]-->
|
|
32868
|
+
$$renderer.push(`<!--]--> `);
|
|
32869
|
+
BrowserClosed($$renderer, {
|
|
32870
|
+
closing});
|
|
32871
|
+
$$renderer.push(`<!----></span></div>`);
|
|
32213
32872
|
bind_props($$props, { clearInput });
|
|
32214
32873
|
});
|
|
32215
32874
|
}
|
|
@@ -32284,6 +32943,7 @@ function createMoveCoalescer(raf, fire) {
|
|
|
32284
32943
|
//#region src/lib/components/browser/BrowserPanel.svelte
|
|
32285
32944
|
function BrowserPanel($$renderer, $$props) {
|
|
32286
32945
|
$$renderer.component(($$renderer) => {
|
|
32946
|
+
let { onclose, openedBy = void 0, parentTitle = null, depth = 0} = $$props;
|
|
32287
32947
|
let sessionId = null;
|
|
32288
32948
|
/** True when mount re-bound to a surviving session (ADR-0030 D1) —
|
|
32289
32949
|
* surfaced in the status strip for the operator. */
|
|
@@ -32354,11 +33014,16 @@ function BrowserPanel($$renderer, $$props) {
|
|
|
32354
33014
|
function goHistory(dir) {
|
|
32355
33015
|
proxy();
|
|
32356
33016
|
}
|
|
32357
|
-
/**
|
|
32358
|
-
*
|
|
32359
|
-
* the
|
|
32360
|
-
*
|
|
32361
|
-
|
|
33017
|
+
/** The FOLD (ADR-0037 D1): the header close button only reports
|
|
33018
|
+
* upward - the route's onclose is removePanel, the panel leaves the
|
|
33019
|
+
* floor, and the SERVER SESSION STAYS ALIVE (the reaper is the
|
|
33020
|
+
* bound; the slot entry keeps the re-bind facts). The old
|
|
33021
|
+
* owner-release kill (POST /close on this click, ADR-0029 D8) is
|
|
33022
|
+
* retired from this surface: kills belong to the reaper and
|
|
33023
|
+
* cascade close now. */
|
|
33024
|
+
function fold() {
|
|
33025
|
+
onclose?.();
|
|
33026
|
+
}
|
|
32362
33027
|
onDestroy(() => {});
|
|
32363
33028
|
let $$settled = true;
|
|
32364
33029
|
let $$inner_renderer;
|
|
@@ -32372,12 +33037,22 @@ function BrowserPanel($$renderer, $$props) {
|
|
|
32372
33037
|
busy: proxyBusy,
|
|
32373
33038
|
canBack,
|
|
32374
33039
|
canForward,
|
|
32375
|
-
onclose: () =>
|
|
33040
|
+
onclose: () => fold(),
|
|
32376
33041
|
onnavigate: submitUrl,
|
|
32377
33042
|
onreload: () => void proxy(),
|
|
32378
33043
|
onhistory: goHistory
|
|
32379
33044
|
});
|
|
32380
33045
|
$$renderer.push(`<!----> `);
|
|
33046
|
+
if (openedBy) {
|
|
33047
|
+
$$renderer.push("<!--[0-->");
|
|
33048
|
+
$$renderer.push(`<div${attr_class("browser-provenance flex items-center gap-1 border-b border-surface-border px-2 py-0.5 text-[10px] text-surface-muted svelte-283365", void 0, { "depth-tinted": depth > 0 })} data-testid="browser-provenance"${attr("title", openedBy)}><span class="opacity-70">⌥</span> <span class="truncate">${escape_html(parentTitle ?? openedBy)}</span> `);
|
|
33049
|
+
if (depth > 0) {
|
|
33050
|
+
$$renderer.push("<!--[0-->");
|
|
33051
|
+
$$renderer.push(`<span class="opacity-60">·d${escape_html(depth)}</span>`);
|
|
33052
|
+
} else $$renderer.push("<!--[-1-->");
|
|
33053
|
+
$$renderer.push(`<!--]--></div>`);
|
|
33054
|
+
} else $$renderer.push("<!--[-1-->");
|
|
33055
|
+
$$renderer.push(`<!--]--> `);
|
|
32381
33056
|
BrowserContent($$renderer, {
|
|
32382
33057
|
status,
|
|
32383
33058
|
failReason,
|
|
@@ -32412,6 +33087,18 @@ function BrowserPanel($$renderer, $$props) {
|
|
|
32412
33087
|
});
|
|
32413
33088
|
}
|
|
32414
33089
|
//#endregion
|
|
33090
|
+
//#region src/lib/components/browser/BrowserManager.svelte
|
|
33091
|
+
function BrowserManager($$renderer, $$props) {
|
|
33092
|
+
let { onclose, openedBy = void 0, parentTitle = null, depth = 0} = $$props;
|
|
33093
|
+
$$renderer.push(`<div data-svelte="BrowserManager" class="panel-manager-body svelte-1qpx9ce" data-testid="panel-browser-slot">`);
|
|
33094
|
+
BrowserPanel($$renderer, {
|
|
33095
|
+
onclose,
|
|
33096
|
+
openedBy,
|
|
33097
|
+
parentTitle,
|
|
33098
|
+
depth});
|
|
33099
|
+
$$renderer.push(`<!----></div>`);
|
|
33100
|
+
}
|
|
33101
|
+
//#endregion
|
|
32415
33102
|
//#region src/lib/components/settings-skills/SettingsSkillsToolbar.svelte
|
|
32416
33103
|
function SettingsSkillsToolbar($$renderer, $$props) {
|
|
32417
33104
|
$$renderer.component(($$renderer) => {
|
|
@@ -32932,303 +33619,6 @@ function InjectedDocPanel($$renderer, $$props) {
|
|
|
32932
33619
|
});
|
|
32933
33620
|
}
|
|
32934
33621
|
//#endregion
|
|
32935
|
-
//#region src/lib/utils/panel-prefs.ts
|
|
32936
|
-
/** localStorage base key — one JSON blob `{ panels, selectedPanelId, panelWidth, zoom }`.
|
|
32937
|
-
* A workspace profile (`?profile=…` on the URL) suffixes EVERY dsi-* key
|
|
32938
|
-
* (see storage-profile.ts): the default desk lives under `dsi-panels`,
|
|
32939
|
-
* profile `widi` under `dsi-panels_widi`. */
|
|
32940
|
-
var PANEL_PREFS_KEY = "dsi-panels";
|
|
32941
|
-
/**
|
|
32942
|
-
* The storage key for a workspace profile.
|
|
32943
|
-
* @param profile sanitized profile segment, or null/undefined for the
|
|
32944
|
-
* default desk (`dsi-panels`).
|
|
32945
|
-
*/
|
|
32946
|
-
function panelPrefsKey(profile) {
|
|
32947
|
-
return dsiKey(PANEL_PREFS_KEY, profile);
|
|
32948
|
-
}
|
|
32949
|
-
var PANEL_WORKSPACE_FILE_MAX_WIDTH = 1436;
|
|
32950
|
-
/** The single treePct bound site — sanitize a stored or dragged value
|
|
32951
|
-
* into [TREE_PCT_MIN, TREE_PCT_MAX]; junk (non-finite) falls back to
|
|
32952
|
-
* TREE_PCT_DEFAULT. Mirrors clampPanelZoom's discipline. */
|
|
32953
|
-
function clampTreePct(pct) {
|
|
32954
|
-
if (typeof pct !== "number" || !Number.isFinite(pct)) return 30;
|
|
32955
|
-
return Math.max(15, Math.min(70, Math.round(pct)));
|
|
32956
|
-
}
|
|
32957
|
-
/**
|
|
32958
|
-
* The single panel-width bound site — load-side sanitizing, gutter drags,
|
|
32959
|
-
* and the width slider all route through here. Bounds read the config
|
|
32960
|
-
* store (layout load has landed them before any mount; defaults before).
|
|
32961
|
-
*/
|
|
32962
|
-
function clampPanelWidth(width, kind) {
|
|
32963
|
-
const { minWidth, maxWidth } = appConfig().panel;
|
|
32964
|
-
if (kind === "workspace-explorer") return Math.max(520, Math.min(PANEL_WORKSPACE_FILE_MAX_WIDTH, width));
|
|
32965
|
-
if (kind === "workspace-file") return Math.max(520, Math.min(PANEL_WORKSPACE_FILE_MAX_WIDTH, width));
|
|
32966
|
-
return Math.max(minWidth, Math.min(maxWidth, width));
|
|
32967
|
-
}
|
|
32968
|
-
/** The single zoom bound site — load-side sanitizing and the zoom slider. */
|
|
32969
|
-
function clampPanelZoom(zoom) {
|
|
32970
|
-
const { minZoom, maxZoom } = appConfig().panel;
|
|
32971
|
-
return Math.max(minZoom, Math.min(maxZoom, zoom));
|
|
32972
|
-
}
|
|
32973
|
-
/** Config-driven default width (clamped through the single bound site). */
|
|
32974
|
-
function defaultPanelWidth() {
|
|
32975
|
-
return clampPanelWidth(appConfig().panel.defaultWidth);
|
|
32976
|
-
}
|
|
32977
|
-
/**
|
|
32978
|
-
* The skill shelf's born width (The Shelf Chrome ADR, D5): a name list,
|
|
32979
|
-
* not a five-column table — the shelf pins 480 (DEFAULT_PANEL_MIN_WIDTH)
|
|
32980
|
-
* instead of the 730 conversation default, clamped through the single
|
|
32981
|
-
* bound site.
|
|
32982
|
-
*/
|
|
32983
|
-
function shelfPanelWidth() {
|
|
32984
|
-
return clampPanelWidth(480);
|
|
32985
|
-
}
|
|
32986
|
-
/**
|
|
32987
|
-
* Clamp a stored explorer `expanded` list to sane paths (Workspace
|
|
32988
|
-
* Explorer restore): non-string members drop and a repeated path keeps
|
|
32989
|
-
* its FIRST occurrence — the tree treats `expanded` as a set of
|
|
32990
|
-
* root-relative directories, and a duplicate would double-render a row.
|
|
32991
|
-
*/
|
|
32992
|
-
function clampExpanded(value) {
|
|
32993
|
-
if (!Array.isArray(value)) return [];
|
|
32994
|
-
const seen = /* @__PURE__ */ new Set();
|
|
32995
|
-
const out = [];
|
|
32996
|
-
for (const member of value) {
|
|
32997
|
-
if (typeof member !== "string" || seen.has(member)) continue;
|
|
32998
|
-
seen.add(member);
|
|
32999
|
-
out.push(member);
|
|
33000
|
-
}
|
|
33001
|
-
return out;
|
|
33002
|
-
}
|
|
33003
|
-
/** The terminal desk's structure clamp (Terminal Desk ADR D3, Wave 3):
|
|
33004
|
-
* sanitize a stored desk mirror into { tabs, selectedTab } or undefined.
|
|
33005
|
-
* Junk drops FIELD-WISE — non-string sessionIds drop, empty/junk tabs
|
|
33006
|
-
* drop, selectedTab clamps into range — so a stale blob degrades to
|
|
33007
|
-
* "fewer rows remembered", never a phantom row. All tabs dropped (or
|
|
33008
|
-
* junk at the top) ⇒ undefined: the desk falls back to one fresh row. */
|
|
33009
|
-
function clampDeskMirror(value) {
|
|
33010
|
-
if (value === null || typeof value !== "object") return void 0;
|
|
33011
|
-
const raw = value;
|
|
33012
|
-
if (!Array.isArray(raw.tabs)) return void 0;
|
|
33013
|
-
const tabs = [];
|
|
33014
|
-
for (const tab of raw.tabs) {
|
|
33015
|
-
if (tab === null || typeof tab !== "object") continue;
|
|
33016
|
-
const ids = tab.sessionIds;
|
|
33017
|
-
if (!Array.isArray(ids)) continue;
|
|
33018
|
-
const sessionIds = ids.filter((id) => typeof id === "string" && id.length > 0);
|
|
33019
|
-
if (sessionIds.length === 0) continue;
|
|
33020
|
-
tabs.push({ sessionIds });
|
|
33021
|
-
}
|
|
33022
|
-
const jobs = [];
|
|
33023
|
-
if (Array.isArray(raw.jobs)) for (const j of raw.jobs) {
|
|
33024
|
-
if (j === null || typeof j !== "object") continue;
|
|
33025
|
-
const owner = j.owner;
|
|
33026
|
-
const jobId = j.jobId;
|
|
33027
|
-
if (typeof owner !== "string" || typeof jobId !== "string") continue;
|
|
33028
|
-
if (owner.length === 0 || jobId.length === 0) continue;
|
|
33029
|
-
jobs.push({
|
|
33030
|
-
owner,
|
|
33031
|
-
jobId
|
|
33032
|
-
});
|
|
33033
|
-
}
|
|
33034
|
-
if (tabs.length === 0 && jobs.length === 0) return void 0;
|
|
33035
|
-
const maxIndex = tabs.length + jobs.length;
|
|
33036
|
-
return {
|
|
33037
|
-
tabs,
|
|
33038
|
-
selectedTab: typeof raw.selectedTab === "number" && Number.isFinite(raw.selectedTab) ? Math.max(0, Math.min(maxIndex, Math.round(raw.selectedTab))) : 0,
|
|
33039
|
-
...jobs.length > 0 ? { jobs } : {}
|
|
33040
|
-
};
|
|
33041
|
-
}
|
|
33042
|
-
/** Persisted defaults when nothing (usable) is stored. */
|
|
33043
|
-
function defaultPanelPrefs() {
|
|
33044
|
-
return {
|
|
33045
|
-
panels: [],
|
|
33046
|
-
selectedPanelId: null,
|
|
33047
|
-
panelWidth: defaultPanelWidth(),
|
|
33048
|
-
zoom: 1,
|
|
33049
|
-
treePct: 30
|
|
33050
|
-
};
|
|
33051
|
-
}
|
|
33052
|
-
/**
|
|
33053
|
-
* Hard shape check for a stored panel entry (the parse boundary).
|
|
33054
|
-
* KIND (2026-09-06, ADR D6): absent or 'conversation' is the legacy shape —
|
|
33055
|
-
* `sessionId` required; 'prompt-manager' carries no session fields;
|
|
33056
|
-
* 'injected-doc' (Loadinjected ADR D2) requires non-empty `sourceSessionId`
|
|
33057
|
-
* + `displayPath` — the dedupe key. Any other kind value is hard junk
|
|
33058
|
-
* (entry drops). `agentPreset` and `width`
|
|
33059
|
-
* may be absent (defaulted later); `agentPreset` when present must be
|
|
33060
|
-
* string|null, `width` when present must be a finite number. Unknown
|
|
33061
|
-
* extra keys are fine — they survive sanitizing.
|
|
33062
|
-
*/
|
|
33063
|
-
function isPanelEntry(value) {
|
|
33064
|
-
if (value === null || typeof value !== "object") return false;
|
|
33065
|
-
const entry = value;
|
|
33066
|
-
if (typeof entry.id !== "string" || entry.id.length === 0) return false;
|
|
33067
|
-
if (entry.kind !== void 0 && entry.kind !== "conversation" && entry.kind !== "prompt-manager" && entry.kind !== "settings-editor" && entry.kind !== "injected-doc" && entry.kind !== "skill-shelf" && entry.kind !== "plugin-rack" && entry.kind !== "workspace-explorer" && entry.kind !== "workspace-file" && entry.kind !== "terminal") return false;
|
|
33068
|
-
if (entry.kind === "settings-editor" && entry.target !== "dsi" && entry.target !== "dsh") return false;
|
|
33069
|
-
if (entry.kind === "workspace-explorer") {
|
|
33070
|
-
if (entry.sessionId !== null && (typeof entry.sessionId !== "string" || entry.sessionId.length === 0)) return false;
|
|
33071
|
-
if (entry.sessionId === null && entry.home !== "dsi" && entry.home !== "dsh") return false;
|
|
33072
|
-
}
|
|
33073
|
-
if (entry.kind === "workspace-file") {
|
|
33074
|
-
if (typeof entry.sessionId !== "string" || entry.sessionId.length === 0) return false;
|
|
33075
|
-
}
|
|
33076
|
-
if (entry.kind === "workspace-explorer" && typeof entry.root !== "string") return false;
|
|
33077
|
-
if (entry.kind === "workspace-file") {
|
|
33078
|
-
if (typeof entry.path !== "string" || entry.path.length === 0) return false;
|
|
33079
|
-
}
|
|
33080
|
-
if (entry.kind === "injected-doc") {
|
|
33081
|
-
if (typeof entry.sourceSessionId !== "string" || entry.sourceSessionId.length === 0) return false;
|
|
33082
|
-
if (typeof entry.displayPath !== "string" || entry.displayPath.length === 0) return false;
|
|
33083
|
-
}
|
|
33084
|
-
if (entry.kind !== "prompt-manager" && entry.kind !== "settings-editor" && entry.kind !== "skill-shelf" && entry.kind !== "plugin-rack" && entry.kind !== "injected-doc" && entry.kind !== "workspace-explorer" && entry.kind !== "workspace-file" && entry.kind !== "terminal") {
|
|
33085
|
-
if (typeof entry.sessionId !== "string" || entry.sessionId.length === 0) return false;
|
|
33086
|
-
if (entry.agentPreset !== void 0 && typeof entry.agentPreset !== "string" && entry.agentPreset !== null) return false;
|
|
33087
|
-
}
|
|
33088
|
-
if (entry.width !== void 0 && (typeof entry.width !== "number" || !Number.isFinite(entry.width))) return false;
|
|
33089
|
-
return true;
|
|
33090
|
-
}
|
|
33091
|
-
/** Drop hard-junk entries; default missing keys; clamp widths. Unknown
|
|
33092
|
-
* keys on surviving entries pass through untouched.
|
|
33093
|
-
*
|
|
33094
|
-
* Duplicate ids (2026-08-24 crash fix): a corrupted blob carrying the
|
|
33095
|
-
* same panel-N twice would reach the keyed each in SidebarOpenPanels
|
|
33096
|
-
* and crash Svelte (each_key_duplicate) at render — the each's key is
|
|
33097
|
-
* the panel id. Duplicates drop to the FIRST occurrence (order is the
|
|
33098
|
-
* floor's left-to-right truth); a selectedPanelId left dangling by the
|
|
33099
|
-
* dedupe re-sanitizes to the first panel in loadPanelPrefs. */
|
|
33100
|
-
function sanitizePanels(raw) {
|
|
33101
|
-
if (!Array.isArray(raw)) return [];
|
|
33102
|
-
const seen = /* @__PURE__ */ new Set();
|
|
33103
|
-
return raw.filter((entry) => isPanelEntry(entry)).map((entry) => {
|
|
33104
|
-
const kindDefault = entry.kind === "skill-shelf" ? shelfPanelWidth() : entry.kind === "plugin-rack" ? shelfPanelWidth() : entry.kind === "workspace-explorer" ? 850 : entry.kind === "workspace-file" ? 850 : defaultPanelWidth();
|
|
33105
|
-
const width = clampPanelWidth(typeof entry.width === "number" && Number.isFinite(entry.width) ? entry.width : kindDefault, entry.kind);
|
|
33106
|
-
if (entry.kind === "prompt-manager") return {
|
|
33107
|
-
id: entry.id,
|
|
33108
|
-
kind: "prompt-manager",
|
|
33109
|
-
width
|
|
33110
|
-
};
|
|
33111
|
-
if (entry.kind === "terminal") {
|
|
33112
|
-
const desk = clampDeskMirror(entry.desk);
|
|
33113
|
-
return {
|
|
33114
|
-
id: entry.id,
|
|
33115
|
-
kind: "terminal",
|
|
33116
|
-
...desk ? { desk } : {},
|
|
33117
|
-
width
|
|
33118
|
-
};
|
|
33119
|
-
}
|
|
33120
|
-
if (entry.kind === "settings-editor") return {
|
|
33121
|
-
id: entry.id,
|
|
33122
|
-
kind: "settings-editor",
|
|
33123
|
-
target: entry.target,
|
|
33124
|
-
width
|
|
33125
|
-
};
|
|
33126
|
-
if (entry.kind === "skill-shelf") {
|
|
33127
|
-
let reload = null;
|
|
33128
|
-
const r = entry.reload;
|
|
33129
|
-
if (r && r.phase === "loading" && typeof r.startedAt === "number") reload = {
|
|
33130
|
-
phase: "loading",
|
|
33131
|
-
startedAt: r.startedAt
|
|
33132
|
-
};
|
|
33133
|
-
else if (r && r.phase === "done" && typeof r.startedAt === "number" && typeof r.doneAt === "number" && r.doneAt > Date.now()) reload = {
|
|
33134
|
-
phase: "done",
|
|
33135
|
-
startedAt: r.startedAt,
|
|
33136
|
-
doneAt: r.doneAt
|
|
33137
|
-
};
|
|
33138
|
-
return {
|
|
33139
|
-
id: entry.id,
|
|
33140
|
-
kind: "skill-shelf",
|
|
33141
|
-
tab: entry.tab === "uninstall" ? "uninstall" : "install",
|
|
33142
|
-
collapsed: clampExpanded(entry.collapsed),
|
|
33143
|
-
searchQ: typeof entry.searchQ === "string" ? entry.searchQ : "",
|
|
33144
|
-
reload,
|
|
33145
|
-
width
|
|
33146
|
-
};
|
|
33147
|
-
}
|
|
33148
|
-
if (entry.kind === "plugin-rack") return {
|
|
33149
|
-
id: entry.id,
|
|
33150
|
-
kind: "plugin-rack",
|
|
33151
|
-
tab: entry.tab === "uninstall" ? "uninstall" : "install",
|
|
33152
|
-
width
|
|
33153
|
-
};
|
|
33154
|
-
if (entry.kind === "injected-doc") return {
|
|
33155
|
-
id: entry.id,
|
|
33156
|
-
kind: "injected-doc",
|
|
33157
|
-
sourceSessionId: entry.sourceSessionId,
|
|
33158
|
-
displayPath: entry.displayPath,
|
|
33159
|
-
width
|
|
33160
|
-
};
|
|
33161
|
-
if (entry.kind === "workspace-explorer") {
|
|
33162
|
-
const home = entry.home === "dsi" || entry.home === "dsh" ? entry.home : void 0;
|
|
33163
|
-
return {
|
|
33164
|
-
id: entry.id,
|
|
33165
|
-
kind: "workspace-explorer",
|
|
33166
|
-
sessionId: entry.sessionId ?? null,
|
|
33167
|
-
root: entry.root,
|
|
33168
|
-
...typeof entry.title === "string" && entry.title.length > 0 ? { title: entry.title } : {},
|
|
33169
|
-
...home !== void 0 ? { home } : {},
|
|
33170
|
-
expanded: clampExpanded(entry.expanded),
|
|
33171
|
-
tab: entry.tab === "changes" ? "changes" : "explorer",
|
|
33172
|
-
collapsedRepos: clampExpanded(entry.collapsedRepos),
|
|
33173
|
-
openTabs: clampExpanded(entry.openTabs),
|
|
33174
|
-
activeFile: typeof entry.activeFile === "string" ? entry.activeFile : null,
|
|
33175
|
-
width
|
|
33176
|
-
};
|
|
33177
|
-
}
|
|
33178
|
-
if (entry.kind === "workspace-file") return {
|
|
33179
|
-
id: entry.id,
|
|
33180
|
-
kind: "workspace-file",
|
|
33181
|
-
sessionId: entry.sessionId,
|
|
33182
|
-
path: entry.path,
|
|
33183
|
-
explorerPanelId: typeof entry.explorerPanelId === "string" && entry.explorerPanelId.length > 0 ? entry.explorerPanelId : null,
|
|
33184
|
-
view: entry.view === "diff" ? "diff" : "edit",
|
|
33185
|
-
width
|
|
33186
|
-
};
|
|
33187
|
-
return {
|
|
33188
|
-
...entry,
|
|
33189
|
-
id: entry.id,
|
|
33190
|
-
kind: "conversation",
|
|
33191
|
-
sessionId: entry.sessionId,
|
|
33192
|
-
agentPreset: entry.agentPreset ?? null,
|
|
33193
|
-
width
|
|
33194
|
-
};
|
|
33195
|
-
}).filter((entry) => {
|
|
33196
|
-
if (seen.has(entry.id)) return false;
|
|
33197
|
-
seen.add(entry.id);
|
|
33198
|
-
return true;
|
|
33199
|
-
});
|
|
33200
|
-
}
|
|
33201
|
-
/**
|
|
33202
|
-
* Read the workspace state from localStorage.
|
|
33203
|
-
* @param profile sanitized workspace profile (null/omitted = default desk).
|
|
33204
|
-
* @returns stored state when parseable (sanitized), defaults when absent,
|
|
33205
|
-
* junk, or SSR. A `selectedPanelId` pointing at a missing panel
|
|
33206
|
-
* sanitizes to the first panel's id (null when no panels remain).
|
|
33207
|
-
*/
|
|
33208
|
-
function loadPanelPrefs(profile) {
|
|
33209
|
-
if (typeof localStorage === "undefined") return defaultPanelPrefs();
|
|
33210
|
-
try {
|
|
33211
|
-
const raw = localStorage.getItem(panelPrefsKey(profile));
|
|
33212
|
-
if (!raw) return defaultPanelPrefs();
|
|
33213
|
-
const parsed = JSON.parse(raw);
|
|
33214
|
-
if (parsed === null || typeof parsed !== "object") return defaultPanelPrefs();
|
|
33215
|
-
if (!Array.isArray(parsed.panels)) return defaultPanelPrefs();
|
|
33216
|
-
const panels = sanitizePanels(parsed.panels);
|
|
33217
|
-
const panelWidth = typeof parsed.panelWidth === "number" && Number.isFinite(parsed.panelWidth) ? clampPanelWidth(parsed.panelWidth) : defaultPanelWidth();
|
|
33218
|
-
const zoom = typeof parsed.zoom === "number" && Number.isFinite(parsed.zoom) ? clampPanelZoom(parsed.zoom) : 1;
|
|
33219
|
-
const treePct = typeof parsed.treePct === "number" && Number.isFinite(parsed.treePct) ? clampTreePct(parsed.treePct) : 30;
|
|
33220
|
-
return {
|
|
33221
|
-
panels,
|
|
33222
|
-
selectedPanelId: typeof parsed.selectedPanelId === "string" && panels.some((panel) => panel.id === parsed.selectedPanelId) ? parsed.selectedPanelId : panels[0]?.id ?? null,
|
|
33223
|
-
panelWidth,
|
|
33224
|
-
zoom,
|
|
33225
|
-
treePct
|
|
33226
|
-
};
|
|
33227
|
-
} catch {
|
|
33228
|
-
return defaultPanelPrefs();
|
|
33229
|
-
}
|
|
33230
|
-
}
|
|
33231
|
-
//#endregion
|
|
33232
33622
|
//#region src/lib/components/workspace-explorer/WorkspaceExplorerButtons.svelte
|
|
33233
33623
|
function WorkspaceExplorerButtons($$renderer, $$props) {
|
|
33234
33624
|
$$renderer.component(($$renderer) => {
|
|
@@ -34134,6 +34524,19 @@ function PanelsZoom($$renderer, $$props) {
|
|
|
34134
34524
|
});
|
|
34135
34525
|
}
|
|
34136
34526
|
//#endregion
|
|
34527
|
+
//#region src/lib/components/panels/PanelClose.svelte
|
|
34528
|
+
function PanelClose($$renderer, $$props) {
|
|
34529
|
+
$$renderer.component(($$renderer) => {
|
|
34530
|
+
let { sessionId, lens = false} = $$props;
|
|
34531
|
+
$$renderer.push(`<button data-svelte="PanelClose" type="button" class="hdr-btn"${attr("disabled", lens, true)} data-testid="panel-close"${attr("aria-label", t(() => closepanelnamed2({ id: sessionId })))}${attr("title", t(closepanelhint2))}>`);
|
|
34532
|
+
X($$renderer, {
|
|
34533
|
+
size: 12,
|
|
34534
|
+
"aria-hidden": "true"
|
|
34535
|
+
});
|
|
34536
|
+
$$renderer.push(`<!----></button>`);
|
|
34537
|
+
});
|
|
34538
|
+
}
|
|
34539
|
+
//#endregion
|
|
34137
34540
|
//#region src/lib/components/panels/PanelHeader.svelte
|
|
34138
34541
|
function PanelHeader($$renderer, $$props) {
|
|
34139
34542
|
$$renderer.component(($$renderer) => {
|
|
@@ -34183,12 +34586,9 @@ function PanelHeader($$renderer, $$props) {
|
|
|
34183
34586
|
$$renderer.push(`<!--]--> `);
|
|
34184
34587
|
if (onremove || lens) {
|
|
34185
34588
|
$$renderer.push("<!--[0-->");
|
|
34186
|
-
$$renderer
|
|
34187
|
-
|
|
34188
|
-
|
|
34189
|
-
"aria-hidden": "true"
|
|
34190
|
-
});
|
|
34191
|
-
$$renderer.push(`<!----></button>`);
|
|
34589
|
+
PanelClose($$renderer, {
|
|
34590
|
+
sessionId,
|
|
34591
|
+
lens});
|
|
34192
34592
|
} else $$renderer.push("<!--[-1-->");
|
|
34193
34593
|
$$renderer.push(`<!--]--></span></div>`);
|
|
34194
34594
|
});
|
|
@@ -34329,70 +34729,6 @@ function EmptyFloor($$renderer, $$props) {
|
|
|
34329
34729
|
});
|
|
34330
34730
|
}
|
|
34331
34731
|
//#endregion
|
|
34332
|
-
//#region src/lib/components/panels/control-bar/ControlBar.svelte
|
|
34333
|
-
function ControlBar($$renderer, $$props) {
|
|
34334
|
-
$$renderer.component(($$renderer) => {
|
|
34335
|
-
/**
|
|
34336
|
-
* ControlBar — the floor's hover tray (Panel Floor W5 task 5.1,
|
|
34337
|
-
* ADR-0006 R7; OCI ControlBar precedent, minus its orchestration
|
|
34338
|
-
* organs). Pinned top-right over the panels viewport; hovering the
|
|
34339
|
-
* gear trigger reveals the tray, leaving hides it after 250ms (the
|
|
34340
|
-
* timer clears on re-enter, so grazing the tray keeps it open).
|
|
34341
|
-
*
|
|
34342
|
-
* This file owns the trigger + the reveal/hide lifecycle; the tray
|
|
34343
|
-
* body — the floor controls + the action-button row — is
|
|
34344
|
-
* ControlBarTray:
|
|
34345
|
-
* - AddPanel — paste a sessionId → two verbs: Add appends a new
|
|
34346
|
-
* panel beside the focus, Rplc replaces the ACTIVE
|
|
34347
|
-
* panel in place (both registry actions)
|
|
34348
|
-
* - SliderWidth — uniform-width preset 480..860 (`onresizeall` sets
|
|
34349
|
-
* every panel + the preset LIVE per thumb move)
|
|
34350
|
-
* - SliderZoom — floor zoom 25%..125% step 5 ($bindable zoom)
|
|
34351
|
-
* - TrayButtons — the tray's button row (the floor canvas-capture:
|
|
34352
|
-
* `captureContainer` flows the page-owned floor
|
|
34353
|
-
* element down to its CanvasCopyButton)
|
|
34354
|
-
*
|
|
34355
|
-
* Deliberately ABSENT (ADR-0006 R7): RegisterFeature and a home link —
|
|
34356
|
-
* DSI has no orchestration backend for the former, and the sidebar
|
|
34357
|
-
* owns Home for the latter. The OCI tray ships both; this floor does not.
|
|
34358
|
-
*
|
|
34359
|
-
* Communication: AddPanel fires `addPanelFromSidebar` /
|
|
34360
|
-
* `replaceSelectedFromRegistry` through the panel registry — the
|
|
34361
|
-
* tray is a LEAF like a spine row, and the
|
|
34362
|
-
* registry is the only leaf→root action channel (commitment 2). Zoom
|
|
34363
|
-
* is a `$bindable` prop the route owns; every bound routes through
|
|
34364
|
-
* panel-prefs clamps (one clamp site, commitment 3). `onresizeall` is
|
|
34365
|
-
* a ControlBar-specific prop: the tray is a DIRECT child of the
|
|
34366
|
-
* workspace route (not a sidebar intermediate), so prop wiring here
|
|
34367
|
-
* breaks no commitment.
|
|
34368
|
-
*/
|
|
34369
|
-
let { panelWidth = 730, zoom = 1, onresizeall, captureContainer = null } = $$props;
|
|
34370
|
-
let open = false;
|
|
34371
|
-
let $$settled = true;
|
|
34372
|
-
let $$inner_renderer;
|
|
34373
|
-
function $$render_inner($$renderer) {
|
|
34374
|
-
$$renderer.push(`<div data-svelte="ControlBar"${attr_class("controlbar svelte-vs008k", void 0, { "open": open })} role="toolbar"${attr("aria-label", t(floorcontrols1))} aria-orientation="vertical" tabindex="-1" data-testid="controlbar"${attr("data-open", open)}><button type="button" class="trigger svelte-vs008k" data-testid="controlbar-trigger"${attr("aria-label", t(floorcontrols1))}${attr("aria-expanded", open)}>`);
|
|
34375
|
-
Settings($$renderer, {
|
|
34376
|
-
size: 14,
|
|
34377
|
-
"aria-hidden": "true"
|
|
34378
|
-
});
|
|
34379
|
-
$$renderer.push(`<!----></button> `);
|
|
34380
|
-
$$renderer.push("<!--[-1-->");
|
|
34381
|
-
$$renderer.push(`<!--]--></div>`);
|
|
34382
|
-
}
|
|
34383
|
-
do {
|
|
34384
|
-
$$settled = true;
|
|
34385
|
-
$$inner_renderer = $$renderer.copy();
|
|
34386
|
-
$$render_inner($$inner_renderer);
|
|
34387
|
-
} while (!$$settled);
|
|
34388
|
-
$$renderer.subsume($$inner_renderer);
|
|
34389
|
-
bind_props($$props, {
|
|
34390
|
-
panelWidth,
|
|
34391
|
-
zoom
|
|
34392
|
-
});
|
|
34393
|
-
});
|
|
34394
|
-
}
|
|
34395
|
-
//#endregion
|
|
34396
34732
|
//#region src/lib/utils/sidebar-prefs.ts
|
|
34397
34733
|
/**
|
|
34398
34734
|
* Sidebar preferences — persisted layout state for the conversation page's
|
|
@@ -34617,6 +34953,34 @@ function focusedInsertionSlot(panels, selectedIndex, parentOf) {
|
|
|
34617
34953
|
const headIndex = panels.findIndex((p) => p.kind === "conversation" && p.sessionId === head);
|
|
34618
34954
|
return headIndex >= 0 ? Math.min(headIndex, focus) : focus;
|
|
34619
34955
|
}
|
|
34956
|
+
/**
|
|
34957
|
+
* Lineage-order slot below an OPEN spawner (operator spec, 2026-08-28):
|
|
34958
|
+
* after the spawner AND after every already-adopted sibling that PRECEDES
|
|
34959
|
+
* the child in wire order — plus those siblings' own panels (an adopted
|
|
34960
|
+
* subtree travels whole). Ghost clicks and sub-agent replacements keep the
|
|
34961
|
+
* family region in the ghost list's order regardless of arrival sequence:
|
|
34962
|
+
* adopting sub2 then sub3 lands |A|sub2|sub3|, a late sub1 slots back to
|
|
34963
|
+
* |A|sub1|sub2|sub3|.
|
|
34964
|
+
*/
|
|
34965
|
+
function lineagePinnedSlot(panels, childrenByParent, parentSessionId, childSessionId) {
|
|
34966
|
+
let base = panels.findIndex((p) => p.kind === "conversation" && p.sessionId === parentSessionId) + 1;
|
|
34967
|
+
base = docTailEnd(panels, base - 1, parentSessionId) + 1;
|
|
34968
|
+
const siblings = childrenByParent.get(parentSessionId) ?? [];
|
|
34969
|
+
const mine = siblings.findIndex((s) => s.sessionId === childSessionId);
|
|
34970
|
+
const closure = new Set(siblings.slice(0, mine < 0 ? siblings.length : mine).map((s) => s.sessionId));
|
|
34971
|
+
const stack = [...closure];
|
|
34972
|
+
while (stack.length > 0) for (const k of childrenByParent.get(stack.pop()) ?? []) if (!closure.has(k.sessionId)) {
|
|
34973
|
+
closure.add(k.sessionId);
|
|
34974
|
+
stack.push(k.sessionId);
|
|
34975
|
+
}
|
|
34976
|
+
let index = base;
|
|
34977
|
+
while (index < panels.length) {
|
|
34978
|
+
const at = panels[index];
|
|
34979
|
+
if (at.kind !== "conversation" || !closure.has(at.sessionId)) break;
|
|
34980
|
+
index++;
|
|
34981
|
+
}
|
|
34982
|
+
return index;
|
|
34983
|
+
}
|
|
34620
34984
|
//#endregion
|
|
34621
34985
|
//#region src/lib/services/panels/floor-registry/chrome.ts
|
|
34622
34986
|
/**
|
|
@@ -34650,14 +35014,15 @@ function openWorkspaceExplorer(sessionId, workspace) {
|
|
|
34650
35014
|
* browser panel across the floor — the terminal singleton rule (Terminal
|
|
34651
35015
|
* Desk ADR D2). A click on an open browser FOCUSES it; a miss inserts at
|
|
34652
35016
|
* the focused slot. */
|
|
34653
|
-
function openBrowserPanel(index, keepSelection = false) {
|
|
34654
|
-
const open = st.panels.find((p) => p.kind === "browser");
|
|
35017
|
+
function openBrowserPanel(index, keepSelection = false, width, openedBy, sessionId) {
|
|
35018
|
+
const open = st.panels.find((p) => p.kind === "browser" && p.openedBy === openedBy);
|
|
34655
35019
|
if (open) {
|
|
34656
35020
|
st.selectedPanelId = open.id;
|
|
34657
35021
|
return;
|
|
34658
35022
|
}
|
|
34659
35023
|
const prevSelected = st.selectedPanelId;
|
|
34660
|
-
|
|
35024
|
+
const slot = index !== void 0 ? Math.max(0, Math.min(index, st.panels.length)) : openedBy !== void 0 && d$4().getLineageFacts().childrenByParent ? pinnedSlotIndex(openedBy, "browser") : insertionSlot();
|
|
35025
|
+
insertPanel(makeBrowserPanel(width, openedBy, sessionId), slot);
|
|
34661
35026
|
if (keepSelection && prevSelected !== null && prevSelected !== void 0) {
|
|
34662
35027
|
if (st.panels.some((p) => p.id === prevSelected)) st.selectedPanelId = prevSelected;
|
|
34663
35028
|
}
|
|
@@ -34828,6 +35193,9 @@ function removePanel(panelId, opts = {}) {
|
|
|
34828
35193
|
}
|
|
34829
35194
|
}
|
|
34830
35195
|
const doomedPanelIds = new SvelteSet();
|
|
35196
|
+
if (opts.family !== false && rootSessionId !== null) {
|
|
35197
|
+
for (const p of st.panels) if (p.kind === "browser" && p.openedBy !== void 0 && doomed.has(p.openedBy)) doomedPanelIds.add(p.id);
|
|
35198
|
+
}
|
|
34831
35199
|
if (opts.family !== false && root.kind === "workspace-explorer") {
|
|
34832
35200
|
for (const p of st.panels) if (p.kind === "workspace-file" && (p.explorerPanelId === root.id || p.explorerPanelId === null && p.sessionId === root.sessionId)) doomedPanelIds.add(p.id);
|
|
34833
35201
|
}
|
|
@@ -34924,11 +35292,18 @@ function makePanel(sessionId, agentPreset) {
|
|
|
34924
35292
|
width: clampPanelWidth(d$1().getPanelWidth())
|
|
34925
35293
|
};
|
|
34926
35294
|
}
|
|
34927
|
-
|
|
35295
|
+
/** width: the reload-restored panel re-mints at the width the operator
|
|
35296
|
+
* dragged before (browser-slot persistence, RCA 2026-10-22); absent for
|
|
35297
|
+
* chip clicks and legacy slots — the honest-slider preset.
|
|
35298
|
+
* openedBy: the opener session's provenance, recorded ONCE at spawn and
|
|
35299
|
+
* never rewritten (ADR-0036 D1/D2); undefined = no conversation context. */
|
|
35300
|
+
function makeBrowserPanel(width, openedBy, sessionId) {
|
|
34928
35301
|
return {
|
|
34929
35302
|
id: nextPanelId(),
|
|
34930
35303
|
kind: "browser",
|
|
34931
|
-
width: clampPanelWidth(d$1().getPanelWidth())
|
|
35304
|
+
width: clampPanelWidth(width ?? d$1().getPanelWidth()),
|
|
35305
|
+
...openedBy !== void 0 ? { openedBy } : {},
|
|
35306
|
+
...sessionId !== void 0 ? { browserSessionId: sessionId } : {}
|
|
34932
35307
|
};
|
|
34933
35308
|
}
|
|
34934
35309
|
function makeWorkspaceExplorerPanel(sessionId, root) {
|
|
@@ -34950,6 +35325,9 @@ function insertPanel(entry, index) {
|
|
|
34950
35325
|
function insertionSlot() {
|
|
34951
35326
|
return focusedInsertionSlot(st.panels, selectedIndex_(), d$1().getMoveFacts().parentOf);
|
|
34952
35327
|
}
|
|
35328
|
+
function pinnedSlotIndex(parentSessionId, childSessionId) {
|
|
35329
|
+
return lineagePinnedSlot(st.panels, d$1().getLineageFacts().childrenByParent, parentSessionId, childSessionId);
|
|
35330
|
+
}
|
|
34953
35331
|
//#endregion
|
|
34954
35332
|
//#region src/lib/services/panels/floor-registry.svelte.ts
|
|
34955
35333
|
var deps = null;
|
|
@@ -35166,6 +35544,7 @@ function seedColdOf(data) {
|
|
|
35166
35544
|
//#region src/routes/+page.svelte
|
|
35167
35545
|
function _page($$renderer, $$props) {
|
|
35168
35546
|
$$renderer.component(($$renderer) => {
|
|
35547
|
+
var $$store_subs;
|
|
35169
35548
|
/**
|
|
35170
35549
|
* Workspace route — the floor SHELL (ADR-0019 W3): configure the
|
|
35171
35550
|
* floor-registry dep seam once, seed/restore through initFloor,
|
|
@@ -35199,16 +35578,30 @@ function _page($$renderer, $$props) {
|
|
|
35199
35578
|
initFloor(seededInitially ? [makePanel(seedSessionId(), seedCold?.agentPreset ?? null)] : initialPrefs.panels, seededInitially ? null : initialPrefs.selectedPanelId);
|
|
35200
35579
|
if (seededInitially) selectPanel(floor.panels[0]?.id ?? null);
|
|
35201
35580
|
if (seededInitially && seedCold !== void 0) pageFeeds.primeSeed(seedSessionId(), seedCold);
|
|
35202
|
-
|
|
35581
|
+
async function restoreBrowserGlasses() {
|
|
35203
35582
|
try {
|
|
35204
|
-
const persisted = readPersistedId();
|
|
35205
|
-
if (!persisted) return;
|
|
35206
35583
|
if (floor.panels.some((panel) => panel.kind === "browser")) return;
|
|
35207
35584
|
const res = await fetch("/api/browser");
|
|
35208
35585
|
if (!res.ok) return;
|
|
35209
|
-
|
|
35586
|
+
const body = await res.json();
|
|
35587
|
+
const live = new Set((body.sessions ?? []).map((s) => s.id));
|
|
35588
|
+
const slots = readBrowserSlots();
|
|
35589
|
+
const dead = slots.filter((s) => s.sessionId && !live.has(s.sessionId));
|
|
35590
|
+
if (dead.length > 0) persistBrowserSlots(slots.filter((s) => !dead.includes(s)));
|
|
35591
|
+
for (const slot of slots) {
|
|
35592
|
+
if (slot.folded) continue;
|
|
35593
|
+
if (!slot.sessionId || !live.has(slot.sessionId)) continue;
|
|
35594
|
+
summonGlass(slot);
|
|
35595
|
+
}
|
|
35210
35596
|
} catch {}
|
|
35211
|
-
}
|
|
35597
|
+
}
|
|
35598
|
+
/** Bring ONE folded glass back (the summon; the replace verb is the
|
|
35599
|
+
* same re-bind — the glass owns its slot identity, D4). */
|
|
35600
|
+
function summonGlass(glass) {
|
|
35601
|
+
openBrowserPanel(glass.index, true, glass.width, glass.openedBy, glass.sessionId);
|
|
35602
|
+
}
|
|
35603
|
+
primeBrowserSlotStore();
|
|
35604
|
+
restoreBrowserGlasses();
|
|
35212
35605
|
const panels = derived(() => floor.panels);
|
|
35213
35606
|
const selectedPanelId = derived(() => floor.selectedPanelId);
|
|
35214
35607
|
const selected = derived(() => floor.selected);
|
|
@@ -35221,6 +35614,29 @@ function _page($$renderer, $$props) {
|
|
|
35221
35614
|
const spineWorkspaces = derived(() => floorReads.spineWorkspaces);
|
|
35222
35615
|
const lineageFacts = derived(() => floorReads.lineageFacts);
|
|
35223
35616
|
const conversationPanels = derived(() => floorReads.conversationPanels);
|
|
35617
|
+
const allFoldedGlassRows = derived(() => store_get($$store_subs ??= {}, "$browserSlotStore", browserSlotStore).filter((s) => s.folded && s.sessionId && s.openedBy).map((s) => ({
|
|
35618
|
+
panel: {
|
|
35619
|
+
id: "glass-" + s.sessionId,
|
|
35620
|
+
kind: "conversation",
|
|
35621
|
+
sessionId: s.sessionId,
|
|
35622
|
+
agentPreset: null,
|
|
35623
|
+
width: 0
|
|
35624
|
+
},
|
|
35625
|
+
title: "Browser — " + (panelTitleFor(s.openedBy) ?? s.openedBy),
|
|
35626
|
+
workspace: null,
|
|
35627
|
+
dead: false,
|
|
35628
|
+
running: true,
|
|
35629
|
+
depth: (lineageFacts().depthById.get(s.openedBy) ?? 0) + 1,
|
|
35630
|
+
runningDescendants: 0,
|
|
35631
|
+
kind: "ghost",
|
|
35632
|
+
parentSessionId: s.openedBy,
|
|
35633
|
+
siblingIndex: -1
|
|
35634
|
+
})));
|
|
35635
|
+
const spineGlassRows = derived(() => allFoldedGlassRows().filter((g) => !conversationPanels().some((p) => p.sessionId === g.parentSessionId)).map((g) => ({
|
|
35636
|
+
sessionId: g.panel.sessionId,
|
|
35637
|
+
openedBy: g.parentSessionId,
|
|
35638
|
+
title: g.title ?? "Browser"
|
|
35639
|
+
})));
|
|
35224
35640
|
const sidebarPlacement = derived(() => appConfig().sidebar.placement);
|
|
35225
35641
|
const sidebarInZoom = derived(() => sidebarPlacement() === "panels-zoom" && !pagePrefs.sidebarCollapsed);
|
|
35226
35642
|
pageFeeds.installFeeds(() => conversationPanels().map((p) => p.sessionId));
|
|
@@ -35240,6 +35656,10 @@ function _page($$renderer, $$props) {
|
|
|
35240
35656
|
function toggleSidebar() {
|
|
35241
35657
|
pagePrefs.sidebarCollapsed = !pagePrefs.sidebarCollapsed;
|
|
35242
35658
|
}
|
|
35659
|
+
function startSidebarResize(e) {
|
|
35660
|
+
e.preventDefault();
|
|
35661
|
+
e.clientX, pagePrefs.sidebarWidth;
|
|
35662
|
+
}
|
|
35243
35663
|
function sidebarRail($$renderer) {
|
|
35244
35664
|
AppSidebar($$renderer, {
|
|
35245
35665
|
profile: activeProfile,
|
|
@@ -35249,7 +35669,26 @@ function _page($$renderer, $$props) {
|
|
|
35249
35669
|
currentSessionId: selected()?.kind === "conversation" ? selected().sessionId : "",
|
|
35250
35670
|
paneledSessionIds: conversationPanels().map((p) => p.sessionId),
|
|
35251
35671
|
captureContainer: pageRoot,
|
|
35252
|
-
|
|
35672
|
+
trayContainer: floorEl,
|
|
35673
|
+
glassRows: spineGlassRows(),
|
|
35674
|
+
onresizeall: resizeAll,
|
|
35675
|
+
onToggleCollapse: toggleSidebar,
|
|
35676
|
+
onResizeStart: startSidebarResize,
|
|
35677
|
+
get panelWidth() {
|
|
35678
|
+
return pagePrefs.panelWidth;
|
|
35679
|
+
},
|
|
35680
|
+
set panelWidth($$value) {
|
|
35681
|
+
pagePrefs.panelWidth = $$value;
|
|
35682
|
+
$$settled = false;
|
|
35683
|
+
},
|
|
35684
|
+
get zoom() {
|
|
35685
|
+
return pagePrefs.zoom;
|
|
35686
|
+
},
|
|
35687
|
+
set zoom($$value) {
|
|
35688
|
+
pagePrefs.zoom = $$value;
|
|
35689
|
+
$$settled = false;
|
|
35690
|
+
}
|
|
35691
|
+
});
|
|
35253
35692
|
}
|
|
35254
35693
|
function panelBody($$renderer, panel, floorPanelId, hostClose) {
|
|
35255
35694
|
if (panel.kind === "terminal") {
|
|
@@ -35263,10 +35702,12 @@ function _page($$renderer, $$props) {
|
|
|
35263
35702
|
$$renderer.push(`<!----></div>`);
|
|
35264
35703
|
} else if (panel.kind === "browser") {
|
|
35265
35704
|
$$renderer.push("<!--[1-->");
|
|
35266
|
-
$$renderer
|
|
35267
|
-
|
|
35268
|
-
|
|
35269
|
-
|
|
35705
|
+
BrowserManager($$renderer, {
|
|
35706
|
+
browserSessionId: "browserSessionId" in panel ? panel.browserSessionId : void 0,
|
|
35707
|
+
onclose: () => removePanel(panel.id),
|
|
35708
|
+
openedBy: panel.openedBy,
|
|
35709
|
+
parentTitle: panel.openedBy ? panelTitleFor(panel.openedBy) ?? panel.openedBy : null,
|
|
35710
|
+
depth: panel.openedBy ? lineageFacts().depthById.get(panel.openedBy) ?? 0 : 0});
|
|
35270
35711
|
} else if (panel.kind === "injected-doc") {
|
|
35271
35712
|
$$renderer.push("<!--[2-->");
|
|
35272
35713
|
$$renderer.push(`<div class="panel-manager-body svelte-1uha8ag">`);
|
|
@@ -35384,7 +35825,7 @@ function _page($$renderer, $$props) {
|
|
|
35384
35825
|
a2aRows: a2aRowsFor(p.sessionId),
|
|
35385
35826
|
a2aTitles: spineTitles(),
|
|
35386
35827
|
onOpenExplorer: openWorkspaceExplorer,
|
|
35387
|
-
onOpenBrowser: lineageFacts().subagentIds.has(p.sessionId) ? void 0 : () => openBrowserPanel(),
|
|
35828
|
+
onOpenBrowser: lineageFacts().subagentIds.has(p.sessionId) ? void 0 : () => openBrowserPanel(void 0, false, void 0, p.sessionId),
|
|
35388
35829
|
focusComposer: p.id === focusComposerId(),
|
|
35389
35830
|
oncomposerfocus: () => clearFocusComposer(),
|
|
35390
35831
|
focused: p.id === selectedPanelId()
|
|
@@ -35413,7 +35854,7 @@ function _page($$renderer, $$props) {
|
|
|
35413
35854
|
a2aTitles: spineTitles(),
|
|
35414
35855
|
onNeedCold: (sid) => void ensureCold(sid),
|
|
35415
35856
|
onOpenExplorer: openWorkspaceExplorer,
|
|
35416
|
-
onOpenBrowser: lineageFacts().subagentIds.has(p.sessionId) ? void 0 : () => openBrowserPanel(),
|
|
35857
|
+
onOpenBrowser: lineageFacts().subagentIds.has(p.sessionId) ? void 0 : () => openBrowserPanel(void 0, false, void 0, p.sessionId),
|
|
35417
35858
|
focusComposer: p.id === focusComposerId(),
|
|
35418
35859
|
oncomposerfocus: () => clearFocusComposer(),
|
|
35419
35860
|
focused: p.id === selectedPanelId()
|
|
@@ -35437,26 +35878,7 @@ function _page($$renderer, $$props) {
|
|
|
35437
35878
|
$$renderer.push("<!--[0-->");
|
|
35438
35879
|
sidebarRail($$renderer);
|
|
35439
35880
|
} else $$renderer.push("<!--[-1-->");
|
|
35440
|
-
$$renderer.push(`<!--]-->
|
|
35441
|
-
ControlBar($$renderer, {
|
|
35442
|
-
onresizeall: resizeAll,
|
|
35443
|
-
captureContainer: floorEl,
|
|
35444
|
-
get panelWidth() {
|
|
35445
|
-
return pagePrefs.panelWidth;
|
|
35446
|
-
},
|
|
35447
|
-
set panelWidth($$value) {
|
|
35448
|
-
pagePrefs.panelWidth = $$value;
|
|
35449
|
-
$$settled = false;
|
|
35450
|
-
},
|
|
35451
|
-
get zoom() {
|
|
35452
|
-
return pagePrefs.zoom;
|
|
35453
|
-
},
|
|
35454
|
-
set zoom($$value) {
|
|
35455
|
-
pagePrefs.zoom = $$value;
|
|
35456
|
-
$$settled = false;
|
|
35457
|
-
}
|
|
35458
|
-
});
|
|
35459
|
-
$$renderer.push(`<!----> <div class="floor svelte-1uha8ag">`);
|
|
35881
|
+
$$renderer.push(`<!--]--> <div class="floor svelte-1uha8ag">`);
|
|
35460
35882
|
PanelsZoom($$renderer, {
|
|
35461
35883
|
zoom: pagePrefs.zoom,
|
|
35462
35884
|
panels: panels(),
|
|
@@ -35515,8 +35937,9 @@ function _page($$renderer, $$props) {
|
|
|
35515
35937
|
$$render_inner($$inner_renderer);
|
|
35516
35938
|
} while (!$$settled);
|
|
35517
35939
|
$$renderer.subsume($$inner_renderer);
|
|
35940
|
+
if ($$store_subs) unsubscribe_stores($$store_subs);
|
|
35518
35941
|
});
|
|
35519
35942
|
}
|
|
35520
35943
|
|
|
35521
35944
|
export { _page as default };
|
|
35522
|
-
//# sourceMappingURL=_page.svelte.js-
|
|
35945
|
+
//# sourceMappingURL=_page.svelte.js-CKY8hz9T.js.map
|