@deepseek-insight/dsi 0.8.4 → 0.8.5
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/.agents/skills/dsi-gb-verifier/SKILL.md +143 -0
- package/build/client/_app/immutable/assets/0.C6AGVUc8.css +2 -0
- package/build/client/_app/immutable/assets/{2.BPprd30B.css → 2.gXzZuuwh.css} +1 -1
- package/build/client/_app/immutable/chunks/BFOY8uwF.js +1 -0
- package/build/client/_app/immutable/chunks/CrTRqozz.js +1 -0
- package/build/client/_app/immutable/chunks/DxGYLnDH.js +1 -0
- package/build/client/_app/immutable/chunks/HD-mJtOS.js +6 -0
- package/build/client/_app/immutable/chunks/{CnzmIbjr.js → b4-Ro8NH.js} +1 -1
- package/build/client/_app/immutable/chunks/hC0DBYN6.js +2 -0
- package/build/client/_app/immutable/entry/{app.DYNedUxy.js → app.DHewwbUQ.js} +2 -2
- package/build/client/_app/immutable/entry/start.C0PcwkeZ.js +1 -0
- package/build/client/_app/immutable/nodes/{0.DQYP6BCS.js → 0.CP10wY64.js} +1 -1
- package/build/client/_app/immutable/nodes/{1.CHB5qqQ9.js → 1.qWvE0DiU.js} +1 -1
- package/build/client/_app/immutable/nodes/{2.C6No1310.js → 2.Nw7iFtoh.js} +224 -223
- package/build/client/_app/version.json +1 -1
- package/build/handler.js +4 -4
- package/build/index.js +4 -4
- package/build/server/chunks/chunks/{app-config.svelte.js-BM4WbMFB.js → app-config.svelte.js-DCc9d7A4.js} +6 -2
- package/build/server/chunks/chunks/{config.js-vThvQeMn.js → config.js-s6iKwHD7.js} +3 -2
- package/build/server/chunks/chunks/{db.js-DQm6CZ_r.js → db.js-CxxWK5sn.js} +2 -2
- package/build/server/chunks/chunks/{db2.js-DUhFxA3a.js → db2.js-DwJ9lySe.js} +2 -2
- package/build/server/chunks/chunks/{dsh-connection.js-BgeraFA2.js → dsh-connection.js-Chtudg1p.js} +3 -3
- package/build/server/chunks/chunks/{dsh-events.js-BUkLR6ZV.js → dsh-events.js-BUdvZQmd.js} +6 -3
- package/build/server/chunks/chunks/{git-probe.js-CLF37SRh.js → git-probe.js-BX9FPnet.js} +3 -3
- package/build/server/chunks/chunks/{insight-config.js-Dp_2gB5J.js → insight-config.js-Db5fe5Df.js} +9 -5
- package/build/server/chunks/chunks/{internal2.js-J3h-US64.js → internal2.js-CaZaz-a9.js} +3 -3
- package/build/server/chunks/chunks/ledger-stats.js-BWACyDPg.js +72 -0
- package/build/server/chunks/chunks/{registry.js-CZNJZ0C-.js → registry.js-syaTZ_-A.js} +341 -21
- package/build/server/chunks/chunks/{settings-document.js-Gw1puaik.js → settings-document.js-BHESJ7im.js} +2 -2
- package/build/server/chunks/chunks/{state.js-8RBD56dL.js → state.js-oYjf745s.js} +3 -3
- package/build/server/chunks/chunks/{watcher.js-BVKnoQUw.js → watcher.js-Ci9jsM5l.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/a2a/_id_/{_server.ts.js-BjzdVwdY.js → _server.ts.js-CHaYhzjy.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/a2a/{_server.ts.js-3kQCQuHT.js → _server.ts.js-CdyqA85c.js} +8 -8
- package/build/server/chunks/entries/endpoints/api/a2a/register/{_server.ts.js-BUBTCLFn.js → _server.ts.js-DO_FS5b4.js} +8 -8
- package/build/server/chunks/entries/endpoints/api/browser/_id_/activate/{_server.ts.js-BdMJzENm.js → _server.ts.js-D7Be4JUf.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/browser/_id_/close/{_server.ts.js-B5z9-N8Y.js → _server.ts.js-CGkm2H-U.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/browser/_id_/closetab/{_server.ts.js-CnZHun5r.js → _server.ts.js-D7SLUfOo.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/browser/_id_/element/{_server.ts.js-C1oM2Ihf.js → _server.ts.js-C3d_JV-q.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/browser/_id_/input/{_server.ts.js-DmbqGRMg.js → _server.ts.js-DW0hyVML.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/browser/_id_/mcp/{_server.ts.js-Cj80T1yH.js → _server.ts.js-Ev-hdBlf.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/browser/_id_/navigate/{_server.ts.js-6gi1UYTJ.js → _server.ts.js-DZ8-wocV.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/browser/_id_/opentab/{_server.ts.js-Bhx_J7ot.js → _server.ts.js-aapPrIQK.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/browser/_id_/page/{_server.ts.js-DvQXNnX9.js → _server.ts.js-DANA_hMd.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/browser/_id_/stream/{_server.ts.js-MflkVWUn.js → _server.ts.js-BqfseXFy.js} +26 -9
- package/build/server/chunks/entries/endpoints/api/browser/_id_/tabs/{_server.ts.js-CoUSlLcP.js → _server.ts.js-DFFF9qe-.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/browser/_id_/viewport/{_server.ts.js-DNk4EgjJ.js → _server.ts.js-ek6-D4Zm.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/browser/{_server.ts.js-CECKap7O.js → _server.ts.js-CPjKy3ma.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/config/{_server.ts.js-C8XDnDwe.js → _server.ts.js-CWE9NP6g.js} +12 -5
- package/build/server/chunks/entries/endpoints/api/dsh/directory/{_server.ts.js-BFmWshpv.js → _server.ts.js-D-raYQon.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/jobs/{_server.ts.js-DATWy5mQ.js → _server.ts.js-CI4dEHFY.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/jobs/follow/{_server.ts.js-CugOD1Zd.js → _server.ts.js-cnjoSLtY.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/pick-directory/{_server.ts.js-DCupM4da.js → _server.ts.js-0UUtapX5.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/presets/{_server.ts.js-Bh1btvr9.js → _server.ts.js-MK5ezU8u.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/attachment/{_server.ts.js-Cb8SBWVw.js → _server.ts.js-CEiMgzjC.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/cancel/{_server.ts.js-WI9yH2iG.js → _server.ts.js-wGEl1fuF.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/catalog/{_server.ts.js-bN9adUqz.js → _server.ts.js-Bz7u2BlD.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/changes/{_server.ts.js-Bxlm966G.js → _server.ts.js-yue5aEjr.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/command/{_server.ts.js-CM-raN_Q.js → _server.ts.js-BFSs5T2m.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/events/{_server.ts.js-BzP30TXW.js → _server.ts.js-C2i85wQy.js} +7 -70
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/fork/{_server.ts.js-DvNkrTaY.js → _server.ts.js-_toO4f4W.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/goal/{_server.ts.js-DXbCrefw.js → _server.ts.js-BGJnDV85.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/history/{_server.ts.js-B7YRQhuJ.js → _server.ts.js-CQCJg8U8.js} +6 -6
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/models/{_server.ts.js-C_AEaLLJ.js → _server.ts.js-0ADvdE79.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/path/{_server.ts.js-Dj-pF5ik.js → _server.ts.js-DyO4T1Ro.js} +4 -4
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/permission/{_server.ts.js-BX9FWJ6g.js → _server.ts.js-CIY7oimw.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/prompt/{_server.ts.js-CQ2Bmtu4.js → _server.ts.js-B-9faNHX.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/rename/{_server.ts.js-Ha7xjnKW.js → _server.ts.js-E7-0zfiH.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/respond/{_server.ts.js-BOg6llHk.js → _server.ts.js-CODtLQ3Q.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/session/_sessionId_/select-model/{_server.ts.js-DBqGALzZ.js → _server.ts.js-BiSxsU-j.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/sessions/{_server.ts.js-CvA8WDDb.js → _server.ts.js-C0WJnv2b.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/subagents/_server.ts.js-D5bc4xg4.js +72 -0
- package/build/server/chunks/entries/endpoints/api/dsh/workspace-file/{_server.ts.js-BfjNH40j.js → _server.ts.js-23ycAyUg.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/workspace-tree/{_server.ts.js-De_qumyr.js → _server.ts.js-B4w5Jh7f.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/workspaces/{_server.ts.js-tFpJJHCb.js → _server.ts.js-VQLxDbFE.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/workspaces/_workspaceId_/delete/{_server.ts.js-DVx5GGA_.js → _server.ts.js-vs5N5Cya.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/dsh/workspaces/_workspaceId_/rename/{_server.ts.js-DuKT-aZp.js → _server.ts.js-BOWhoBHV.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/prompts/_id_/{_server.ts.js-DsWFidFY.js → _server.ts.js-aDEAGfJe.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/prompts/{_server.ts.js-C6j0adQs.js → _server.ts.js-BZ-nRrTp.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/prompts/use/{_server.ts.js-BChAg4hm.js → _server.ts.js-CkDY1PQ7.js} +5 -5
- package/build/server/chunks/entries/endpoints/api/settings/{_server.ts.js-BPSHqbZN.js → _server.ts.js-CHvgF47Y.js} +4 -4
- package/build/server/chunks/entries/endpoints/api/terminal/{_server.ts.js-D5CbUe5k.js → _server.ts.js-CbRT4vBo.js} +4 -4
- package/build/server/chunks/entries/endpoints/api/workspace/file-write/{_server.ts.js-B-5YihUA.js → _server.ts.js-BwD0KaXy.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/workspace/git-events/{_server.ts.js-DT5jRZFE.js → _server.ts.js-DgbMRh3d.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/workspace/git-file-head/{_server.ts.js-DtW-utrd.js → _server.ts.js-DRqZawic.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/workspace/git-map/{_server.ts.js-8AIAo9jX.js → _server.ts.js-CTXwwwB1.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/workspace/git-status/{_server.ts.js-CMw96vjY.js → _server.ts.js-B4aJBY2w.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/workspace/write-gate/{_server.ts.js-DKufa14_.js → _server.ts.js-CDJJA18L.js} +7 -7
- package/build/server/chunks/entries/{hooks.server.js-B-e4_ekh.js → hooks.server.js-Iel6oE7w.js} +3 -3
- package/build/server/chunks/entries/pages/{_error.svelte.js-DRPduJdP.js → _error.svelte.js-B-wdFjVG.js} +4 -4
- package/build/server/chunks/entries/pages/{_page.server.ts.js-7x6ZfGoB.js → _page.server.ts.js-CaoeQzem.js} +3 -3
- package/build/server/chunks/entries/pages/{_page.svelte.js-Dek8Q1_v.js → _page.svelte.js-CY7zcWr4.js} +1480 -1062
- package/build/server/chunks/{handler-DUyvzXsb.js → handler-DYk4NJto.js} +3 -3
- package/build/server/chunks/{index.js-BrP1SRzN.js → index.js-kL9MZ99b.js} +2 -2
- package/build/server/chunks/{manifest.js-C4z6aoYx.js → manifest.js-BrMLQqec.js} +67 -60
- package/build/server/chunks/nodes/{0.js-BuB3t8Br.js → 0.js-BembYTTr.js} +3 -3
- package/build/server/chunks/nodes/1.js-CKJjyWGZ.js +9 -0
- package/build/server/chunks/nodes/{2.js-C-o9KF10.js → 2.js-BezA2RPm.js} +10 -10
- package/package.json +1 -1
- package/skills/{dsi-kb-scenario → dsi-fc-scenario}/SKILL.md +11 -6
- package/template/.dsi/prompts.sqlite-shm +0 -0
- package/template/.dsi/prompts.sqlite-wal +0 -0
- package/build/client/_app/immutable/assets/0.cswkTiBk.css +0 -2
- package/build/client/_app/immutable/chunks/C7Sg_49n.js +0 -1
- package/build/client/_app/immutable/chunks/D-Rolhzs.js +0 -1
- package/build/client/_app/immutable/chunks/DY0MQ1mO.js +0 -1
- package/build/client/_app/immutable/chunks/GKkjunMm.js +0 -2
- package/build/client/_app/immutable/chunks/NcOjFWr3.js +0 -6
- package/build/client/_app/immutable/entry/start.BzyrBssE.js +0 -1
- package/build/server/chunks/nodes/1.js-CW4V8ni8.js +0 -9
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { a as __exportAll, o as onDestroy } from '../../chunks/index-server.js-DmIEbDVz.js';
|
|
2
2
|
import '../../chunks/exports.js-DH_tjtdv.js';
|
|
3
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';
|
|
4
|
-
import { U as UI_LOCALES } from '../../chunks/config.js-
|
|
4
|
+
import { U as UI_LOCALES } from '../../chunks/config.js-s6iKwHD7.js';
|
|
5
5
|
import { m as mergeEntries, c as collapseSystemPromptEntries, t as truncate } from '../../chunks/merge.js-yMwW440S.js';
|
|
6
6
|
import { p as parseA2aSignature, m as mintA2aId, b as buildDeliveredText } from '../../chunks/a2a-protocol.js-C77mVg2Q.js';
|
|
7
7
|
import { b as applyKnobEvent, E as EMPTY_KNOBS, r as resolvePermission, l as localPermission, c as presetLabel, d as presetDescription, C as CUSTOM_PRESET, F as FULL_ACCESS_PRESET } from '../../chunks/permission-state.js-B7UpAHBv.js';
|
|
8
8
|
import { D as DEFAULT_IMAGE_LIMITS } from '../../chunks/image-limits.js-CUdJ0f7r.js';
|
|
9
9
|
import { s as sanitizeWorkspaceProfile, d as dsiKey, t as themePrefs } from '../../chunks/theme-prefs.svelte.js-8CaWz46g.js';
|
|
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-
|
|
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-DCc9d7A4.js';
|
|
11
11
|
import { c as getLocale } from '../../chunks/runtime.js-CCJi3XaY.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-
|
|
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-oYjf745s.js';
|
|
13
13
|
import 'yaml';
|
|
14
14
|
import 'html-to-image';
|
|
15
15
|
import hljs from 'highlight.js/lib/core';
|
|
@@ -21,7 +21,7 @@ import xml from 'highlight.js/lib/languages/xml';
|
|
|
21
21
|
import css from 'highlight.js/lib/languages/css';
|
|
22
22
|
import '../../chunks/uneval.js-BJ9Qq2SF.js';
|
|
23
23
|
import '../../chunks/shared.js-HQ0rfhm4.js';
|
|
24
|
-
import '../../chunks/internal2.js-
|
|
24
|
+
import '../../chunks/internal2.js-CaZaz-a9.js';
|
|
25
25
|
import '../../chunks/utils.js-CAdNO8Tu.js';
|
|
26
26
|
|
|
27
27
|
//#region src/lib/paraglide/messages/abort.js
|
|
@@ -1208,6 +1208,38 @@ var browserlaunching1 = ((inputs = {}, options = {}) => {
|
|
|
1208
1208
|
return en_browserlaunching1();
|
|
1209
1209
|
});
|
|
1210
1210
|
//#endregion
|
|
1211
|
+
//#region src/lib/paraglide/messages/browsernewtab2.js
|
|
1212
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
1213
|
+
/** @typedef {{}} Browsernewtab2Inputs */
|
|
1214
|
+
var en_browsernewtab2 = () => {
|
|
1215
|
+
return `New tab`;
|
|
1216
|
+
};
|
|
1217
|
+
var zh_browsernewtab2 = () => {
|
|
1218
|
+
return `新标签页`;
|
|
1219
|
+
};
|
|
1220
|
+
var id_browsernewtab2 = () => {
|
|
1221
|
+
return `Tab baru`;
|
|
1222
|
+
};
|
|
1223
|
+
var es_browsernewtab2 = () => {
|
|
1224
|
+
return `Nueva pestaña`;
|
|
1225
|
+
};
|
|
1226
|
+
/**
|
|
1227
|
+
* | output |
|
|
1228
|
+
* | --- |
|
|
1229
|
+
* | "New tab" |
|
|
1230
|
+
*
|
|
1231
|
+
* @param {Browsernewtab2Inputs} inputs
|
|
1232
|
+
* @param {{ locale?: "en" | "zh" | "id" | "es" }} options
|
|
1233
|
+
* @returns {LocalizedString}
|
|
1234
|
+
*/
|
|
1235
|
+
var browsernewtab2 = ((inputs = {}, options = {}) => {
|
|
1236
|
+
const locale = options.locale ?? getLocale();
|
|
1237
|
+
if (locale === "zh") return zh_browsernewtab2();
|
|
1238
|
+
if (locale === "id") return id_browsernewtab2();
|
|
1239
|
+
if (locale === "es") return es_browsernewtab2();
|
|
1240
|
+
return en_browsernewtab2();
|
|
1241
|
+
});
|
|
1242
|
+
//#endregion
|
|
1211
1243
|
//#region src/lib/paraglide/messages/browseropentitle2.js
|
|
1212
1244
|
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
1213
1245
|
/** @typedef {{}} Browseropentitle2Inputs */
|
|
@@ -12568,6 +12600,70 @@ var streaming = ((inputs = {}, options = {}) => {
|
|
|
12568
12600
|
return en_streaming();
|
|
12569
12601
|
});
|
|
12570
12602
|
//#endregion
|
|
12603
|
+
//#region src/lib/paraglide/messages/subagentanchorlabel2.js
|
|
12604
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
12605
|
+
/** @typedef {{}} Subagentanchorlabel2Inputs */
|
|
12606
|
+
var en_subagentanchorlabel2 = () => {
|
|
12607
|
+
return `Subagents`;
|
|
12608
|
+
};
|
|
12609
|
+
var zh_subagentanchorlabel2 = () => {
|
|
12610
|
+
return `子代理`;
|
|
12611
|
+
};
|
|
12612
|
+
var id_subagentanchorlabel2 = () => {
|
|
12613
|
+
return `Subagen`;
|
|
12614
|
+
};
|
|
12615
|
+
var es_subagentanchorlabel2 = () => {
|
|
12616
|
+
return `Subagentes`;
|
|
12617
|
+
};
|
|
12618
|
+
/**
|
|
12619
|
+
* | output |
|
|
12620
|
+
* | --- |
|
|
12621
|
+
* | "Subagents" |
|
|
12622
|
+
*
|
|
12623
|
+
* @param {Subagentanchorlabel2Inputs} inputs
|
|
12624
|
+
* @param {{ locale?: "en" | "zh" | "id" | "es" }} options
|
|
12625
|
+
* @returns {LocalizedString}
|
|
12626
|
+
*/
|
|
12627
|
+
var subagentanchorlabel2 = ((inputs = {}, options = {}) => {
|
|
12628
|
+
const locale = options.locale ?? getLocale();
|
|
12629
|
+
if (locale === "zh") return zh_subagentanchorlabel2();
|
|
12630
|
+
if (locale === "id") return id_subagentanchorlabel2();
|
|
12631
|
+
if (locale === "es") return es_subagentanchorlabel2();
|
|
12632
|
+
return en_subagentanchorlabel2();
|
|
12633
|
+
});
|
|
12634
|
+
//#endregion
|
|
12635
|
+
//#region src/lib/paraglide/messages/subagentcloseallpanels3.js
|
|
12636
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
12637
|
+
/** @typedef {{}} Subagentcloseallpanels3Inputs */
|
|
12638
|
+
var en_subagentcloseallpanels3 = () => {
|
|
12639
|
+
return `del panel(s)`;
|
|
12640
|
+
};
|
|
12641
|
+
var zh_subagentcloseallpanels3 = () => {
|
|
12642
|
+
return `删除面板`;
|
|
12643
|
+
};
|
|
12644
|
+
var id_subagentcloseallpanels3 = () => {
|
|
12645
|
+
return `hapus panel`;
|
|
12646
|
+
};
|
|
12647
|
+
var es_subagentcloseallpanels3 = () => {
|
|
12648
|
+
return `eliminar panel(es)`;
|
|
12649
|
+
};
|
|
12650
|
+
/**
|
|
12651
|
+
* | output |
|
|
12652
|
+
* | --- |
|
|
12653
|
+
* | "del panel(s)" |
|
|
12654
|
+
*
|
|
12655
|
+
* @param {Subagentcloseallpanels3Inputs} inputs
|
|
12656
|
+
* @param {{ locale?: "en" | "zh" | "id" | "es" }} options
|
|
12657
|
+
* @returns {LocalizedString}
|
|
12658
|
+
*/
|
|
12659
|
+
var subagentcloseallpanels3 = ((inputs = {}, options = {}) => {
|
|
12660
|
+
const locale = options.locale ?? getLocale();
|
|
12661
|
+
if (locale === "zh") return zh_subagentcloseallpanels3();
|
|
12662
|
+
if (locale === "id") return id_subagentcloseallpanels3();
|
|
12663
|
+
if (locale === "es") return es_subagentcloseallpanels3();
|
|
12664
|
+
return en_subagentcloseallpanels3();
|
|
12665
|
+
});
|
|
12666
|
+
//#endregion
|
|
12571
12667
|
//#region src/lib/paraglide/messages/subagentmany1.js
|
|
12572
12668
|
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
12573
12669
|
/** @typedef {{ n: NonNullable<unknown> }} Subagentmany1Inputs */
|
|
@@ -13688,6 +13784,38 @@ var tooltitlewrite2 = ((inputs = {}, options = {}) => {
|
|
|
13688
13784
|
return en_tooltitlewrite2();
|
|
13689
13785
|
});
|
|
13690
13786
|
//#endregion
|
|
13787
|
+
//#region src/lib/paraglide/messages/totaltokens1.js
|
|
13788
|
+
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
13789
|
+
/** @typedef {{}} Totaltokens1Inputs */
|
|
13790
|
+
var en_totaltokens1 = () => {
|
|
13791
|
+
return `Total tokens`;
|
|
13792
|
+
};
|
|
13793
|
+
var zh_totaltokens1 = () => {
|
|
13794
|
+
return `总 Token 数`;
|
|
13795
|
+
};
|
|
13796
|
+
var id_totaltokens1 = () => {
|
|
13797
|
+
return `Total token`;
|
|
13798
|
+
};
|
|
13799
|
+
var es_totaltokens1 = () => {
|
|
13800
|
+
return `Tokens totales`;
|
|
13801
|
+
};
|
|
13802
|
+
/**
|
|
13803
|
+
* | output |
|
|
13804
|
+
* | --- |
|
|
13805
|
+
* | "Total tokens" |
|
|
13806
|
+
*
|
|
13807
|
+
* @param {Totaltokens1Inputs} inputs
|
|
13808
|
+
* @param {{ locale?: "en" | "zh" | "id" | "es" }} options
|
|
13809
|
+
* @returns {LocalizedString}
|
|
13810
|
+
*/
|
|
13811
|
+
var totaltokens1 = ((inputs = {}, options = {}) => {
|
|
13812
|
+
const locale = options.locale ?? getLocale();
|
|
13813
|
+
if (locale === "zh") return zh_totaltokens1();
|
|
13814
|
+
if (locale === "id") return id_totaltokens1();
|
|
13815
|
+
if (locale === "es") return es_totaltokens1();
|
|
13816
|
+
return en_totaltokens1();
|
|
13817
|
+
});
|
|
13818
|
+
//#endregion
|
|
13691
13819
|
//#region src/lib/paraglide/messages/turnfailed1.js
|
|
13692
13820
|
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
|
13693
13821
|
/** @typedef {{}} Turnfailed1Inputs */
|
|
@@ -15072,6 +15200,7 @@ var _index_exports = /* @__PURE__ */ __exportAll({
|
|
|
15072
15200
|
browserCtxSendRightClick: () => browserctxsendrightclick4,
|
|
15073
15201
|
browserForward: () => browserforward1,
|
|
15074
15202
|
browserLaunching: () => browserlaunching1,
|
|
15203
|
+
browserNewTab: () => browsernewtab2,
|
|
15075
15204
|
browserOpenTitle: () => browseropentitle2,
|
|
15076
15205
|
browserPanelTitle: () => browserpaneltitle2,
|
|
15077
15206
|
browserReload: () => browserreload1,
|
|
@@ -15430,6 +15559,8 @@ var _index_exports = /* @__PURE__ */ __exportAll({
|
|
|
15430
15559
|
stop: () => stop,
|
|
15431
15560
|
stopStreaming: () => stopstreaming1,
|
|
15432
15561
|
streaming: () => streaming,
|
|
15562
|
+
subagentAnchorLabel: () => subagentanchorlabel2,
|
|
15563
|
+
subagentCloseAllPanels: () => subagentcloseallpanels3,
|
|
15433
15564
|
subagentMany: () => subagentmany1,
|
|
15434
15565
|
subagentOne: () => subagentone1,
|
|
15435
15566
|
subagentTitleOwns: () => subagenttitleowns2,
|
|
@@ -15465,6 +15596,7 @@ var _index_exports = /* @__PURE__ */ __exportAll({
|
|
|
15465
15596
|
toolTitleSearch: () => tooltitlesearch2,
|
|
15466
15597
|
toolTitleToolCall: () => tooltitletoolcall3,
|
|
15467
15598
|
toolTitleWrite: () => tooltitlewrite2,
|
|
15599
|
+
totalTokens: () => totaltokens1,
|
|
15468
15600
|
turnFailed: () => turnfailed1,
|
|
15469
15601
|
turnInFlight: () => turninflight2,
|
|
15470
15602
|
turnStopped: () => turnstopped1,
|
|
@@ -15550,6 +15682,7 @@ var messages_exports = /* @__PURE__ */ __exportAll({
|
|
|
15550
15682
|
browserCtxSendRightClick: () => browserctxsendrightclick4,
|
|
15551
15683
|
browserForward: () => browserforward1,
|
|
15552
15684
|
browserLaunching: () => browserlaunching1,
|
|
15685
|
+
browserNewTab: () => browsernewtab2,
|
|
15553
15686
|
browserOpenTitle: () => browseropentitle2,
|
|
15554
15687
|
browserPanelTitle: () => browserpaneltitle2,
|
|
15555
15688
|
browserReload: () => browserreload1,
|
|
@@ -15909,6 +16042,8 @@ var messages_exports = /* @__PURE__ */ __exportAll({
|
|
|
15909
16042
|
stop: () => stop,
|
|
15910
16043
|
stopStreaming: () => stopstreaming1,
|
|
15911
16044
|
streaming: () => streaming,
|
|
16045
|
+
subagentAnchorLabel: () => subagentanchorlabel2,
|
|
16046
|
+
subagentCloseAllPanels: () => subagentcloseallpanels3,
|
|
15912
16047
|
subagentMany: () => subagentmany1,
|
|
15913
16048
|
subagentOne: () => subagentone1,
|
|
15914
16049
|
subagentTitleOwns: () => subagenttitleowns2,
|
|
@@ -15944,6 +16079,7 @@ var messages_exports = /* @__PURE__ */ __exportAll({
|
|
|
15944
16079
|
toolTitleSearch: () => tooltitlesearch2,
|
|
15945
16080
|
toolTitleToolCall: () => tooltitletoolcall3,
|
|
15946
16081
|
toolTitleWrite: () => tooltitlewrite2,
|
|
16082
|
+
totalTokens: () => totaltokens1,
|
|
15947
16083
|
turnFailed: () => turnfailed1,
|
|
15948
16084
|
turnInFlight: () => turninflight2,
|
|
15949
16085
|
turnStopped: () => turnstopped1,
|
|
@@ -16756,6 +16892,22 @@ function Target($$renderer, $$props) {
|
|
|
16756
16892
|
]));
|
|
16757
16893
|
}
|
|
16758
16894
|
//#endregion
|
|
16895
|
+
//#region node_modules/.pnpm/@lucide+svelte@1.35.0_svelte@5.56.10/node_modules/@lucide/svelte/dist/icons/trash-2.svelte
|
|
16896
|
+
function Trash_2($$renderer, $$props) {
|
|
16897
|
+
let { $$slots, $$events, ...props } = $$props;
|
|
16898
|
+
Icon($$renderer, spread_props([
|
|
16899
|
+
{ name: "trash-2" },
|
|
16900
|
+
props,
|
|
16901
|
+
{ iconNode: [
|
|
16902
|
+
["path", { "d": "M10 11v6" }],
|
|
16903
|
+
["path", { "d": "M14 11v6" }],
|
|
16904
|
+
["path", { "d": "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" }],
|
|
16905
|
+
["path", { "d": "M3 6h18" }],
|
|
16906
|
+
["path", { "d": "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }]
|
|
16907
|
+
] }
|
|
16908
|
+
]));
|
|
16909
|
+
}
|
|
16910
|
+
//#endregion
|
|
16759
16911
|
//#region node_modules/.pnpm/@lucide+svelte@1.35.0_svelte@5.56.10/node_modules/@lucide/svelte/dist/icons/wrench.svelte
|
|
16760
16912
|
function Wrench($$renderer, $$props) {
|
|
16761
16913
|
let { $$slots, $$events, ...props } = $$props;
|
|
@@ -17823,7 +17975,7 @@ function ThemeToggle($$renderer, $$props) {
|
|
|
17823
17975
|
}
|
|
17824
17976
|
//#endregion
|
|
17825
17977
|
//#region package.json
|
|
17826
|
-
var version = "0.8.
|
|
17978
|
+
var version = "0.8.5";
|
|
17827
17979
|
var dsh = { "webVersion": "0.2.1-rc.3" };
|
|
17828
17980
|
//#endregion
|
|
17829
17981
|
//#region src/lib/version.ts
|
|
@@ -19515,6 +19667,10 @@ function clampPanelWidth(width, kind) {
|
|
|
19515
19667
|
const { minWidth, maxWidth } = appConfig().panel;
|
|
19516
19668
|
if (kind === "workspace-explorer") return Math.max(520, Math.min(PANEL_WORKSPACE_FILE_MAX_WIDTH, width));
|
|
19517
19669
|
if (kind === "workspace-file") return Math.max(520, Math.min(PANEL_WORKSPACE_FILE_MAX_WIDTH, width));
|
|
19670
|
+
if (kind === "browser") {
|
|
19671
|
+
const { maxWidth: browserMax } = appConfig().browserWidths;
|
|
19672
|
+
return Math.max(minWidth, Math.min(browserMax, width));
|
|
19673
|
+
}
|
|
19518
19674
|
return Math.max(minWidth, Math.min(maxWidth, width));
|
|
19519
19675
|
}
|
|
19520
19676
|
/** The single zoom bound site — load-side sanitizing and the zoom slider. */
|
|
@@ -19526,6 +19682,11 @@ function clampPanelZoom(zoom) {
|
|
|
19526
19682
|
function defaultPanelWidth() {
|
|
19527
19683
|
return clampPanelWidth(appConfig().panel.defaultWidth);
|
|
19528
19684
|
}
|
|
19685
|
+
/** The glass panel's config-driven default (browser.defaultWidth, clamped
|
|
19686
|
+
* through the browser band) — chip-spawned glasses mint at this width. */
|
|
19687
|
+
function browserPanelWidth() {
|
|
19688
|
+
return clampPanelWidth(appConfig().browserWidths.defaultWidth, "browser");
|
|
19689
|
+
}
|
|
19529
19690
|
/**
|
|
19530
19691
|
* The skill shelf's born width (The Shelf Chrome ADR, D5): a name list,
|
|
19531
19692
|
* not a five-column table — the shelf pins 480 (DEFAULT_PANEL_MIN_WIDTH)
|
|
@@ -23129,7 +23290,7 @@ function blockBounds(panels, idx, facts) {
|
|
|
23129
23290
|
while (i > 0 && panels[i - 1].kind === "browser") i--;
|
|
23130
23291
|
const head = panels[i - 1];
|
|
23131
23292
|
const inFamily = (id, root) => {
|
|
23132
|
-
if (id === void 0) return false;
|
|
23293
|
+
if (id === void 0 || root === void 0) return false;
|
|
23133
23294
|
let cur = id;
|
|
23134
23295
|
for (let guard = 0; guard < panels.length + 1 && cur !== null; guard++) {
|
|
23135
23296
|
if (cur === root) return true;
|
|
@@ -23150,6 +23311,7 @@ function blockBounds(panels, idx, facts) {
|
|
|
23150
23311
|
sessionId = head.sessionId;
|
|
23151
23312
|
}
|
|
23152
23313
|
}
|
|
23314
|
+
if (sessionId === null) return [idx, idx];
|
|
23153
23315
|
for (let guard = 0; guard < panels.length + 1; guard++) {
|
|
23154
23316
|
const parent = facts.parentOf.get(sessionId) ?? null;
|
|
23155
23317
|
if (parent === null) break;
|
|
@@ -23485,7 +23647,7 @@ function panelRowsFor(input) {
|
|
|
23485
23647
|
}
|
|
23486
23648
|
if (p.kind === "terminal" || p.kind === "prompt-manager" || p.kind === "settings-editor" || p.kind === "skill-shelf" || p.kind === "plugin-rack") return {
|
|
23487
23649
|
panel: p,
|
|
23488
|
-
title: p.kind === "terminal" ? "Terminal" : p.kind === "
|
|
23650
|
+
title: p.kind === "terminal" ? "Terminal" : 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] : "",
|
|
23489
23651
|
workspace: null,
|
|
23490
23652
|
dead: false,
|
|
23491
23653
|
running: false,
|
|
@@ -24928,7 +25090,7 @@ function ConversationHeader($$renderer, $$props) {
|
|
|
24928
25090
|
* upward.
|
|
24929
25091
|
*/
|
|
24930
25092
|
let { sessionId, title, workspace = null, workspaces = [], access = null, agent, agentId = null, isStreaming, transcript = null, subagent = false, plan = null, parentSessionId = null, focused = false, onOpenExplorer = void 0, onOpenBrowser = void 0 } = $$props;
|
|
24931
|
-
$$renderer.push(`<header data-svelte="ConversationHeader"${attr_class(`flex items-center gap-
|
|
25093
|
+
$$renderer.push(`<header data-svelte="ConversationHeader"${attr_class(`flex items-center gap-1 border-b border-surface-border px-2 py-1 ${focused ? "bg-header-wash" : "bg-surface-elevated"}`)} data-testid="conversation-header"${attr("data-focused", focused ? "true" : "false")}>`);
|
|
24932
25094
|
SessionIdAndName($$renderer, {
|
|
24933
25095
|
sessionId,
|
|
24934
25096
|
title,
|
|
@@ -31031,13 +31193,13 @@ function FloatingAnchorContainerPopup($$renderer, $$props) {
|
|
|
31031
31193
|
* `titleTestId` exists because the header's data-testid is part of
|
|
31032
31194
|
* each leaf's pinned surface (plan-popup-header, user-message-jumper-header).
|
|
31033
31195
|
*/
|
|
31034
|
-
let { open = false, triggerEl = void 0, title = void 0, titleTestId = void 0, popupTestId = "floating-anchor-popup", fitWidth = false, children } = $$props;
|
|
31196
|
+
let { open = false, triggerEl = void 0, title = void 0, titleTestId = void 0, popupTestId = "floating-anchor-popup", fitWidth = false, placement = "left", children } = $$props;
|
|
31035
31197
|
/** Focus the box — leaves call it through bind:this when an action
|
|
31036
31198
|
* must hand focus back (the jumper's stay-open jump). */
|
|
31037
31199
|
function focus() {}
|
|
31038
31200
|
if (open) {
|
|
31039
31201
|
$$renderer.push("<!--[0-->");
|
|
31040
|
-
$$renderer.push(`<div data-svelte="FloatingAnchorContainerPopup" tabindex="-1"${attr_class(`pointer-events-auto absolute right-full top-1/2 z-50
|
|
31202
|
+
$$renderer.push(`<div data-svelte="FloatingAnchorContainerPopup" tabindex="-1"${attr_class(`pointer-events-auto absolute ${placement === "right" ? "left-full ml-2" : placement === "below" ? "right-0 top-full mt-2" : "right-full mr-2"} ${placement === "below" ? "" : "top-1/2 -translate-y-1/2"} z-50 max-h-[60vh] max-w-[80vw] overflow-y-auto rounded-lg border border-surface-border bg-surface-elevated py-1 shadow-xl outline-none focus:outline-none ${fitWidth ? "w-fit" : "w-96"}`)}${attr("data-testid", popupTestId)}>`);
|
|
31041
31203
|
if (title !== void 0) {
|
|
31042
31204
|
$$renderer.push("<!--[0-->");
|
|
31043
31205
|
$$renderer.push(`<div class="border-b border-surface-border px-2.5 py-1.5 text-[10px] font-medium uppercase tracking-wider text-text-muted"${attr("data-testid", titleTestId)}>${escape_html(title)}</div>`);
|
|
@@ -31653,346 +31815,1101 @@ function InjectedShelfButton($$renderer, $$props) {
|
|
|
31653
31815
|
});
|
|
31654
31816
|
}
|
|
31655
31817
|
//#endregion
|
|
31656
|
-
//#region src/lib/
|
|
31657
|
-
|
|
31658
|
-
/**
|
|
31659
|
-
|
|
31660
|
-
|
|
31661
|
-
|
|
31662
|
-
|
|
31663
|
-
|
|
31664
|
-
|
|
31665
|
-
*
|
|
31666
|
-
*/
|
|
31667
|
-
|
|
31668
|
-
|
|
31669
|
-
|
|
31670
|
-
|
|
31671
|
-
|
|
31672
|
-
|
|
31673
|
-
|
|
31674
|
-
DeliverablesButton($$renderer, {
|
|
31675
|
-
deliveries: deliverables,
|
|
31676
|
-
onfileopen
|
|
31677
|
-
});
|
|
31678
|
-
$$renderer.push(`<!----> `);
|
|
31679
|
-
JobsButton($$renderer, { sessionId: jobsessionid });
|
|
31680
|
-
$$renderer.push(`<!----> `);
|
|
31681
|
-
if (shelfentries !== void 0) {
|
|
31682
|
-
$$renderer.push("<!--[0-->");
|
|
31683
|
-
InjectedShelfButton($$renderer, {
|
|
31684
|
-
entries: shelfentries,
|
|
31685
|
-
sessionId: shelfsessionid,
|
|
31686
|
-
workspace: shelfworkspace,
|
|
31687
|
-
panelId: shelfpanelid,
|
|
31688
|
-
onnote: onshelfnote
|
|
31689
|
-
});
|
|
31690
|
-
} else $$renderer.push("<!--[-1-->");
|
|
31691
|
-
$$renderer.push(`<!--]--> `);
|
|
31692
|
-
UserMessagesButton($$renderer, {
|
|
31693
|
-
groups,
|
|
31694
|
-
container
|
|
31695
|
-
});
|
|
31696
|
-
$$renderer.push(`<!----> `);
|
|
31697
|
-
BackToTheEdgeButton($$renderer);
|
|
31698
|
-
$$renderer.push(`<!---->`);
|
|
31699
|
-
}});
|
|
31700
|
-
} else $$renderer.push("<!--[-1-->");
|
|
31701
|
-
$$renderer.push(`<!--]-->`);
|
|
31702
|
-
}
|
|
31703
|
-
//#endregion
|
|
31704
|
-
//#region src/lib/components/conversation/panel/A2aChipStack.svelte
|
|
31705
|
-
function A2aChipStack($$renderer, $$props) {
|
|
31706
|
-
$$renderer.component(($$renderer) => {
|
|
31707
|
-
/**
|
|
31708
|
-
* A2aChipStack — the sender panel's read-only delegation-ledger join
|
|
31709
|
-
* (W4 4.2): one floating chip per recent exchange THIS panel sent,
|
|
31710
|
-
* rendered beside the transcript on the floating-anchor pattern
|
|
31711
|
-
* (right-middle stack, per-panel via the embedded anchor host).
|
|
31712
|
-
*
|
|
31713
|
-
* Honesty contract (PRD risk "Attribution overclaim in UI" + spec-check
|
|
31714
|
-
* GAP-5): chip text derives from the row's `state` VERBATIM, all six
|
|
31715
|
-
* states distinguished — `replied_approx` renders "may have replied",
|
|
31716
|
-
* NEVER the confident "replied" string. The ledger is the truth; this
|
|
31717
|
-
* component claims nothing the row does not say.
|
|
31718
|
-
*
|
|
31719
|
-
* Read-only by construction (BC-2): rows arrive as a prop from the
|
|
31720
|
-
* page's EXISTING spine-cadence poll of GET /api/a2a?from= — the chip
|
|
31721
|
-
* owns NO fetch, NO timer. Click = the existing panel doorway
|
|
31722
|
-
* (addPanelFromSidebar dedupe→select). Dismiss is LOCAL-ONLY visual:
|
|
31723
|
-
* rows are durable; the next poll brings a dismissed chip back only
|
|
31724
|
-
* when it is still in the page's fetched window.
|
|
31725
|
-
*/
|
|
31726
|
-
let { rows, titles } = $$props;
|
|
31727
|
-
/** Local-only visual dismissal — rows are durable; the ledger is truth. */
|
|
31728
|
-
let dismissed = /* @__PURE__ */ new Set();
|
|
31729
|
-
/** The cap: newest 3 visible + one overflow indicator (spec 4.2). */
|
|
31730
|
-
const CHIP_CAP = 3;
|
|
31731
|
-
const visible = derived(() => rows.filter((r) => !dismissed.has(r.id)));
|
|
31732
|
-
const capped = derived(() => visible().slice(0, CHIP_CAP));
|
|
31733
|
-
const overflow = derived(() => Math.max(visible().length - CHIP_CAP, 0));
|
|
31734
|
-
/**
|
|
31735
|
-
* Chip text derives from the state VERBATIM (spec-check GAP-5): every
|
|
31736
|
-
* state distinguished, `replied_approx` hedged as "may have replied" —
|
|
31737
|
-
* never a confident claim the row cannot support.
|
|
31738
|
-
*/
|
|
31739
|
-
function labelFor(state) {
|
|
31740
|
-
switch (state) {
|
|
31741
|
-
case "waiting": return "waiting";
|
|
31742
|
-
case "replied_exact": return "replied (exact)";
|
|
31743
|
-
case "replied": return "replied";
|
|
31744
|
-
case "replied_approx": return "may have replied";
|
|
31745
|
-
case "timeout": return "no reply (timeout)";
|
|
31746
|
-
case "gone": return "target gone";
|
|
31747
|
-
}
|
|
31748
|
-
}
|
|
31749
|
-
/** The target's display title — the spine title, else the id prefix. */
|
|
31750
|
-
function titleFor(toSession) {
|
|
31751
|
-
return titles[toSession] ?? toSession.replace(/^session-/, "").slice(0, 8);
|
|
31752
|
-
}
|
|
31753
|
-
if (visible().length > 0) {
|
|
31754
|
-
$$renderer.push("<!--[0-->");
|
|
31755
|
-
FloatingAnchor($$renderer, {
|
|
31756
|
-
children: ($$renderer) => {
|
|
31757
|
-
$$renderer.push(`<!--[-->`);
|
|
31758
|
-
const each_array = ensure_array_like(capped());
|
|
31759
|
-
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
|
|
31760
|
-
let row = each_array[$$index];
|
|
31761
|
-
$$renderer.push(`<div class="a2a-chip-wrap" data-testid="a2a-chip"${attr("data-a2a-state", row.state)}${attr("data-a2a-id", row.id)}><button type="button"${attr_class("a2a-chip", void 0, {
|
|
31762
|
-
"tone-waiting": row.state === "waiting",
|
|
31763
|
-
"tone-replied-exact": row.state === "replied_exact",
|
|
31764
|
-
"tone-replied": row.state === "replied",
|
|
31765
|
-
"tone-replied-approx": row.state === "replied_approx",
|
|
31766
|
-
"tone-timeout": row.state === "timeout",
|
|
31767
|
-
"tone-gone": row.state === "gone"
|
|
31768
|
-
})} data-testid="a2a-chip-button"${attr("title", `${stringify(titleFor(row.toSession))} — ${stringify(labelFor(row.state))}`)}>`);
|
|
31769
|
-
if (row.state === "waiting") {
|
|
31770
|
-
$$renderer.push("<!--[0-->");
|
|
31771
|
-
Hourglass($$renderer, { size: 13 });
|
|
31772
|
-
} else if (row.state === "replied_exact" || row.state === "replied") {
|
|
31773
|
-
$$renderer.push("<!--[1-->");
|
|
31774
|
-
Check($$renderer, { size: 13 });
|
|
31775
|
-
} else $$renderer.push("<!--[-1-->");
|
|
31776
|
-
$$renderer.push(`<!--]--> <span class="a2a-chip-label">${escape_html(labelFor(row.state))}</span></button> <button type="button" class="a2a-dismiss" data-testid="a2a-chip-dismiss" title="hide this chip (the ledger row stays)">`);
|
|
31777
|
-
X($$renderer, { size: 11 });
|
|
31778
|
-
$$renderer.push(`<!----></button></div>`);
|
|
31779
|
-
}
|
|
31780
|
-
$$renderer.push(`<!--]--> `);
|
|
31781
|
-
if (overflow() > 0) {
|
|
31782
|
-
$$renderer.push("<!--[0-->");
|
|
31783
|
-
$$renderer.push(`<div class="a2a-chip-overflow" data-testid="a2a-chip-overflow">+${escape_html(overflow())} more</div>`);
|
|
31784
|
-
} else $$renderer.push("<!--[-1-->");
|
|
31785
|
-
$$renderer.push(`<!--]-->`);
|
|
31786
|
-
}});
|
|
31787
|
-
} else $$renderer.push("<!--[-1-->");
|
|
31788
|
-
$$renderer.push(`<!--]-->`);
|
|
31789
|
-
});
|
|
31790
|
-
}
|
|
31791
|
-
//#endregion
|
|
31792
|
-
//#region src/lib/components/conversation/panel/ConversationStatsBar.svelte
|
|
31793
|
-
function ConversationStatsBar($$renderer, $$props) {
|
|
31794
|
-
$$renderer.component(($$renderer) => {
|
|
31795
|
-
/**
|
|
31796
|
-
* ConversationStatsBar — the panel's session baseline (ADR 2026-09-08
|
|
31797
|
-
* "The Stats Bar", D1/D3/D5): one fixed-height line under the transcript
|
|
31798
|
-
* showing what the ledger already proves — turns, steps, tool time,
|
|
31799
|
-
* token totals, cache hit. Pure presentation: the panel derives the
|
|
31800
|
-
* stats and hands them down; segments whose inputs never reached DSI
|
|
31801
|
-
* are omitted, never approximated. Renders nothing before the first
|
|
31802
|
-
* assistant message (D5 gate lives in the derive's null return).
|
|
31803
|
-
*/
|
|
31804
|
-
let { stats } = $$props;
|
|
31805
|
-
/** 85000 -> "1m25s"; 2400000 -> "40m"; 5400000 -> "1h30m"; 250 -> "250ms". */
|
|
31806
|
-
function formatDuration(ms) {
|
|
31807
|
-
if (ms < 1e3) return `${ms}ms`;
|
|
31808
|
-
const totalSec = Math.floor(ms / 1e3);
|
|
31809
|
-
const h = Math.floor(totalSec / 3600);
|
|
31810
|
-
const m = Math.floor(totalSec % 3600 / 60);
|
|
31811
|
-
const s = totalSec % 60;
|
|
31812
|
-
if (h > 0) return `${h}h${m}m`;
|
|
31813
|
-
if (m > 0) return s > 0 ? `${m}m${s}s` : `${m}m`;
|
|
31814
|
-
return `${s}s`;
|
|
31818
|
+
//#region src/lib/services/conversation/subagent-clock.svelte.ts
|
|
31819
|
+
var SubagentClock = class {
|
|
31820
|
+
/** sessionId → first-sight epoch ms (running rows only). */
|
|
31821
|
+
firstSeen = {};
|
|
31822
|
+
/** sessionId → frozen elapsed ms, set once at the settle observation. */
|
|
31823
|
+
frozen = {};
|
|
31824
|
+
/** The tick's reading — read by elapsedMs so a live tick re-renders. */
|
|
31825
|
+
now = Date.now();
|
|
31826
|
+
/** Feed one spine tick: register unseen running ids, freeze settled
|
|
31827
|
+
* ones, expire ids gone from the feed. Call on every fetch (the
|
|
31828
|
+
* button's poll cadence), not on a timer — this IS the sighting lane. */
|
|
31829
|
+
observe(rows) {
|
|
31830
|
+
const t = Date.now();
|
|
31831
|
+
const seen = /* @__PURE__ */ new Set();
|
|
31832
|
+
for (const row of rows) {
|
|
31833
|
+
seen.add(row.sessionId);
|
|
31834
|
+
if (row.running && this.firstSeen[row.sessionId] === void 0) this.firstSeen[row.sessionId] = t;
|
|
31835
|
+
if (!row.running && this.firstSeen[row.sessionId] !== void 0 && this.frozen[row.sessionId] === void 0) this.frozen[row.sessionId] = t - this.firstSeen[row.sessionId];
|
|
31815
31836
|
}
|
|
31816
|
-
|
|
31817
|
-
|
|
31818
|
-
|
|
31819
|
-
if (n >= 1e3) return `${(n / 1e3).toFixed(1).replace(/\.0$/, "")}K`;
|
|
31820
|
-
return String(n);
|
|
31837
|
+
for (const id of Object.keys(this.firstSeen)) if (!seen.has(id)) {
|
|
31838
|
+
delete this.firstSeen[id];
|
|
31839
|
+
delete this.frozen[id];
|
|
31821
31840
|
}
|
|
31822
|
-
|
|
31823
|
-
if (stats === null) return [];
|
|
31824
|
-
const parts = [`${stats.turns} turns · ${stats.steps} steps`];
|
|
31825
|
-
const durations = [];
|
|
31826
|
-
if (stats.llmMs !== void 0 && stats.llmMs > 0) durations.push(`LLM ${formatDuration(stats.llmMs)}`);
|
|
31827
|
-
if (stats.toolMs > 0) durations.push(`Tool ${formatDuration(stats.toolMs)}`);
|
|
31828
|
-
if (durations.length > 0) parts.push(durations.join(" · "));
|
|
31829
|
-
const speeds = [];
|
|
31830
|
-
if (stats.ttftSteps !== void 0 && stats.ttftSteps > 0 && stats.ttftMs !== void 0) speeds.push(`TTFT avg ${formatDuration(stats.ttftMs / stats.ttftSteps)}`);
|
|
31831
|
-
if (stats.decodeMs !== void 0 && stats.decodeMs > 0 && stats.decodeTokens !== void 0) speeds.push(`${Math.max(1, Math.round(stats.decodeTokens / (stats.decodeMs / 1e3)))} tok/s`);
|
|
31832
|
-
if (speeds.length > 0) parts.push(speeds.join(" · "));
|
|
31833
|
-
const inputTotal = stats.billedInputTokens ?? stats.inputTokens;
|
|
31834
|
-
if (inputTotal !== void 0) parts.push(`Input ${formatTokens(inputTotal)} tok · Output ${formatTokens(stats.outputTokens ?? 0)} tok`);
|
|
31835
|
-
if (stats.cacheHitPercent !== void 0) parts.push(`Cache hit ${stats.cacheHitPercent}%`);
|
|
31836
|
-
return parts;
|
|
31837
|
-
});
|
|
31838
|
-
if (stats !== null) {
|
|
31839
|
-
$$renderer.push("<!--[0-->");
|
|
31840
|
-
$$renderer.push(`<div data-svelte="ConversationStatsBar" class="stats-bar svelte-hnxn10" data-testid="conversation-stats-bar"${attr("title", segments().join(" | "))}><!--[-->`);
|
|
31841
|
-
const each_array = ensure_array_like(segments());
|
|
31842
|
-
for (let i = 0, $$length = each_array.length; i < $$length; i++) {
|
|
31843
|
-
let segment = each_array[i];
|
|
31844
|
-
if (i > 0) {
|
|
31845
|
-
$$renderer.push("<!--[0-->");
|
|
31846
|
-
$$renderer.push(`<span class="sep svelte-hnxn10" aria-hidden="true">|</span>`);
|
|
31847
|
-
} else $$renderer.push("<!--[-1-->");
|
|
31848
|
-
$$renderer.push(`<!--]--> <span class="segment svelte-hnxn10" data-testid="stats-segment">${escape_html(segment)}</span>`);
|
|
31849
|
-
}
|
|
31850
|
-
$$renderer.push(`<!--]--></div>`);
|
|
31851
|
-
} else $$renderer.push("<!--[-1-->");
|
|
31852
|
-
$$renderer.push(`<!--]-->`);
|
|
31853
|
-
});
|
|
31854
|
-
}
|
|
31855
|
-
//#endregion
|
|
31856
|
-
//#region src/lib/components/conversation/panel/submit-ladder.svelte.ts
|
|
31857
|
-
var SubmitLadder = class {
|
|
31858
|
-
deps;
|
|
31859
|
-
/** True while the plain-send rung is in flight — the footer's sending flag. */
|
|
31860
|
-
submitted = false;
|
|
31861
|
-
/** Inline command feedback (role=status, auto-dismiss 5s) — the ONLY
|
|
31862
|
-
* command UI surface; the input has already cleared by intercept time.
|
|
31863
|
-
* The wire work lives in command-executor (Prompt Macro W1 1.2): the
|
|
31864
|
-
* /new create+swap, /permission route, and mention delivery are the
|
|
31865
|
-
* SAME bytes the typed path always sent — the panel now renders
|
|
31866
|
-
* outcomes only (banner kind from result.ok). */
|
|
31867
|
-
commandNote = null;
|
|
31868
|
-
commandNoteTimer;
|
|
31869
|
-
constructor(deps) {
|
|
31870
|
-
this.deps = deps;
|
|
31871
|
-
}
|
|
31872
|
-
/** Inline command feedback — every rung banners through here. */
|
|
31873
|
-
noteCommand(kind, text) {
|
|
31874
|
-
this.commandNote = {
|
|
31875
|
-
kind,
|
|
31876
|
-
text
|
|
31877
|
-
};
|
|
31878
|
-
if (this.commandNoteTimer !== void 0) clearTimeout(this.commandNoteTimer);
|
|
31879
|
-
this.commandNoteTimer = setTimeout(() => this.commandNote = null, 5e3);
|
|
31841
|
+
this.now = t;
|
|
31880
31842
|
}
|
|
31881
|
-
|
|
31882
|
-
|
|
31883
|
-
|
|
31884
|
-
|
|
31885
|
-
id: -1
|
|
31886
|
-
}, false);
|
|
31887
|
-
return true;
|
|
31888
|
-
}
|
|
31889
|
-
const command = parseCommand(text);
|
|
31890
|
-
if (command !== null) {
|
|
31891
|
-
let bannered = false;
|
|
31892
|
-
const result = await executeCommand(command, this.deps.ctx(), (ok, note) => {
|
|
31893
|
-
bannered = true;
|
|
31894
|
-
this.noteCommand(ok ? "ok" : "error", note);
|
|
31895
|
-
});
|
|
31896
|
-
if (!bannered && result.note !== void 0) this.noteCommand(result.ok ? "ok" : "error", result.note);
|
|
31897
|
-
return true;
|
|
31898
|
-
}
|
|
31899
|
-
if (text.trim().length === 0 && images.length === 0) return false;
|
|
31900
|
-
const slashCatalog = this.deps.slashCatalog;
|
|
31901
|
-
if (slashCatalog?.state === "ready") {
|
|
31902
|
-
if (resolveHostCommand(text, slashCatalog.commands) !== null) return (await executeHostCommand(text, this.deps.ctx(), (ok, note) => this.noteCommand(ok ? "ok" : "error", note))).ok;
|
|
31903
|
-
}
|
|
31904
|
-
this.submitted = true;
|
|
31905
|
-
try {
|
|
31906
|
-
return (await sendPrompt(text, this.deps.ctx(), (t) => this.deps.orchestrator.submit(t, images))).ok;
|
|
31907
|
-
} finally {
|
|
31908
|
-
this.submitted = false;
|
|
31909
|
-
}
|
|
31843
|
+
/** Live tick — the open popup calls this on its 1s interval so a
|
|
31844
|
+
* running row's elapsed advances between polls. */
|
|
31845
|
+
tick() {
|
|
31846
|
+
this.now = Date.now();
|
|
31910
31847
|
}
|
|
31911
|
-
|
|
31912
|
-
|
|
31848
|
+
/** Elapsed ms for one id: the frozen settle delta, or now − firstSeen
|
|
31849
|
+
* for a running row, or null when there is NO honest sample (never
|
|
31850
|
+
* sighted running, or first seen already settled). */
|
|
31851
|
+
elapsedMs(id) {
|
|
31852
|
+
const frozen = this.frozen[id];
|
|
31853
|
+
if (frozen !== void 0) return frozen;
|
|
31854
|
+
const t0 = this.firstSeen[id];
|
|
31855
|
+
if (t0 === void 0) return null;
|
|
31856
|
+
return Math.max(0, this.now - t0);
|
|
31913
31857
|
}
|
|
31914
|
-
/**
|
|
31915
|
-
|
|
31916
|
-
|
|
31917
|
-
async onpickcommand(line) {
|
|
31918
|
-
return (await executeHostCommand(line, this.deps.ctx(), (ok, note) => this.noteCommand(ok ? "ok" : "error", note))).ok;
|
|
31858
|
+
/** Does the id carry any sample at all (frozen or live)? */
|
|
31859
|
+
sighted(id) {
|
|
31860
|
+
return this.frozen[id] !== void 0 || this.firstSeen[id] !== void 0;
|
|
31919
31861
|
}
|
|
31920
31862
|
};
|
|
31921
|
-
|
|
31922
|
-
|
|
31923
|
-
/**
|
|
31924
|
-
*
|
|
31925
|
-
*
|
|
31926
|
-
|
|
31927
|
-
|
|
31928
|
-
|
|
31929
|
-
|
|
31930
|
-
|
|
31931
|
-
|
|
31863
|
+
/** The desk-lifetime singleton — one registry per page visit (ADR D3). */
|
|
31864
|
+
var subagentClock = new SubagentClock();
|
|
31865
|
+
/**
|
|
31866
|
+
* The open workspace explorer for a workspace ROOT — The Shared Tree ADR
|
|
31867
|
+
* (2026-09-17) D1's dedupe key: ONE explorer per ROOT across ALL sessions,
|
|
31868
|
+
* so a chip click on any session sharing the root FOCUSES instead of
|
|
31869
|
+
* adding (a duplicate is a bug, not a feature). The retired per-session
|
|
31870
|
+
* key ("two sessions sharing one workspace hold distinct explorers",
|
|
31871
|
+
* Workspace Explorer D4) produced N byte-identical trees for N sessions.
|
|
31872
|
+
*/
|
|
31873
|
+
function findWorkspaceExplorerPanel(panels, root) {
|
|
31874
|
+
return panels.find((p) => p.kind === "workspace-explorer" && p.root === root);
|
|
31932
31875
|
}
|
|
31933
|
-
/**
|
|
31934
|
-
*
|
|
31935
|
-
|
|
31936
|
-
|
|
31876
|
+
/**
|
|
31877
|
+
* The explorer's slot (The Shared Tree ADR 2026-09-17, D3): the FOCUSED
|
|
31878
|
+
* slot — the explorer is NOT a lineage child; a workspace tree has no
|
|
31879
|
+
* parent session, only an opener. The retired after-source rule
|
|
31880
|
+
* (Workspace Explorer D3, "Parent → explorer → file") interposed the
|
|
31881
|
+
* panel inside a conversation's family unit — the family clamp inside
|
|
31882
|
+
* focusedInsertionSlot still keeps any real family unsplit.
|
|
31883
|
+
*/
|
|
31884
|
+
function workspaceExplorerSlot(panels, selectedIndex, facts) {
|
|
31885
|
+
return focusedInsertionSlot(panels, selectedIndex, facts.parentOf);
|
|
31937
31886
|
}
|
|
31938
|
-
|
|
31939
|
-
|
|
31940
|
-
|
|
31941
|
-
|
|
31942
|
-
|
|
31943
|
-
|
|
31944
|
-
|
|
31945
|
-
|
|
31946
|
-
|
|
31947
|
-
|
|
31948
|
-
|
|
31949
|
-
|
|
31950
|
-
|
|
31951
|
-
|
|
31952
|
-
|
|
31953
|
-
|
|
31954
|
-
|
|
31955
|
-
|
|
31956
|
-
|
|
31957
|
-
|
|
31958
|
-
|
|
31959
|
-
|
|
31960
|
-
|
|
31961
|
-
|
|
31962
|
-
|
|
31963
|
-
|
|
31964
|
-
|
|
31965
|
-
|
|
31966
|
-
|
|
31967
|
-
|
|
31968
|
-
|
|
31969
|
-
|
|
31887
|
+
/**
|
|
31888
|
+
* The glass FIRST slot under its opener (operator ruling 2026-10-24):
|
|
31889
|
+
* a summoned/spawned glass lands DIRECTLY below its opener - past the
|
|
31890
|
+
* opener document tail, BEFORE every adopted child - matching the
|
|
31891
|
+
* spine tree wire order -1 (the ghost always reads as the first
|
|
31892
|
+
* child). Supersedes the region-end placement for the glass only.
|
|
31893
|
+
*/
|
|
31894
|
+
function glassFirstSlot(panels, openedBy) {
|
|
31895
|
+
const openerIdx = panels.findIndex((p) => p.kind === "conversation" && p.sessionId === openedBy);
|
|
31896
|
+
if (openerIdx === -1) return panels.length;
|
|
31897
|
+
return docTailEnd(panels, openerIdx, openedBy) + 1;
|
|
31898
|
+
}
|
|
31899
|
+
/**
|
|
31900
|
+
* Insert-before-focused slot (operator spec, 2026-08-31): a fresh panel
|
|
31901
|
+
* lands at the FOCUSED panel's index — immediately before it — and takes
|
|
31902
|
+
* focus (the route selects it). 0 when nothing is focused (empty floor,
|
|
31903
|
+
* stale selection) — the old front-add stays the fallback. Math.max keeps
|
|
31904
|
+
* splice's negative-index semantics out of the no-selection case.
|
|
31905
|
+
*
|
|
31906
|
+
* Family clamp (lineage I2): a slot strictly inside a family would wedge
|
|
31907
|
+
* the newcomer between a spawner and its pinned child — unitOf/blockBounds,
|
|
31908
|
+
* the sidebar's familyRenderOrder, and the adoption slot walk all assume
|
|
31909
|
+
* families stay contiguous on the floor. When the focus is a family CHILD,
|
|
31910
|
+
* the slot climbs to the family head — the nearest non-splitting slot left
|
|
31911
|
+
* of the focus (parentOf only carries on-floor parents, so an orphan child
|
|
31912
|
+
* is a root here, its own unit). A lone panel or a family head keeps the
|
|
31913
|
+
* exact focus slot.
|
|
31914
|
+
*
|
|
31915
|
+
* Manager focus (ADR D6): no session, no family — the slot is the focus
|
|
31916
|
+
* itself.
|
|
31917
|
+
*
|
|
31918
|
+
* Workspace member focus (2026-09-10): the explorer/file pair is a family
|
|
31919
|
+
* unit in the SAME block math (blockBounds — the Loadinjected D3 walk-back
|
|
31920
|
+
* grammar), so the clamp is the SAME one: insert at the unit head — the
|
|
31921
|
+
* PARENT position, left of the block — never between explorer and file.
|
|
31922
|
+
*/
|
|
31923
|
+
function focusedInsertionSlot(panels, selectedIndex, parentOf) {
|
|
31924
|
+
const focus = Math.max(0, selectedIndex);
|
|
31925
|
+
const focused = panels[focus];
|
|
31926
|
+
if (focused === void 0) return 0;
|
|
31927
|
+
if (focused.kind === "workspace-explorer" || focused.kind === "workspace-file" || focused.kind === "browser") {
|
|
31928
|
+
const block = blockBounds(panels, focus, { parentOf });
|
|
31929
|
+
return block === null ? focus : block[0];
|
|
31970
31930
|
}
|
|
31971
|
-
|
|
31972
|
-
|
|
31973
|
-
|
|
31974
|
-
|
|
31931
|
+
if (focused.kind !== "conversation") return focus;
|
|
31932
|
+
let head = focused.sessionId;
|
|
31933
|
+
for (;;) {
|
|
31934
|
+
const parent = parentOf.get(head) ?? null;
|
|
31935
|
+
if (parent === null) break;
|
|
31936
|
+
head = parent;
|
|
31975
31937
|
}
|
|
31976
|
-
|
|
31977
|
-
|
|
31978
|
-
|
|
31938
|
+
if (head === focused.sessionId) return focus;
|
|
31939
|
+
const headIndex = panels.findIndex((p) => p.kind === "conversation" && p.sessionId === head);
|
|
31940
|
+
return headIndex >= 0 ? Math.min(headIndex, focus) : focus;
|
|
31941
|
+
}
|
|
31942
|
+
//#endregion
|
|
31943
|
+
//#region src/lib/services/panels/floor-registry/chrome.ts
|
|
31944
|
+
/**
|
|
31945
|
+
* floor-registry/chrome — panel chrome intents + explorer + file-intent
|
|
31946
|
+
* mailbox + removal (ADR-0022 W3).
|
|
31947
|
+
*
|
|
31948
|
+
* Moved WHOLE from the state home (floor-registry.svelte.ts): the
|
|
31949
|
+
* skill-shelf / plugin-rack chrome setters, the ONE-explorer-per-workspace
|
|
31950
|
+
* open grammar, the explorer tree/tab/git intents, the file-intent
|
|
31951
|
+
* publish/consume mailbox, and family-close removal. Plain module: every
|
|
31952
|
+
* write goes through the state home's reactive `st` hub and its
|
|
31953
|
+
* primitives (ADR-0019 D2: exactly ONE writer home for floor state).
|
|
31954
|
+
* Sibling rule: factories/slots are reached through the state home's
|
|
31955
|
+
* re-export hub, never by importing another sibling directly.
|
|
31956
|
+
*/
|
|
31957
|
+
var d$4 = floorSeam;
|
|
31958
|
+
/** Chip click action: ONE explorer per WORKSPACE root across ALL
|
|
31959
|
+
* sessions — a click on any session sharing the root FOCUSES the open
|
|
31960
|
+
* explorer (dedupe key = root, D1); a fresh root lands at the focused
|
|
31961
|
+
* slot (D3, non-lineage — the explorer is not a lineage child).
|
|
31962
|
+
* sessionId rides the fresh panel as PROVENANCE (D4), never identity. */
|
|
31963
|
+
function openWorkspaceExplorer(sessionId, workspace) {
|
|
31964
|
+
const open = findWorkspaceExplorerPanel(st.panels, workspace);
|
|
31965
|
+
if (open) {
|
|
31966
|
+
st.selectedPanelId = open.id;
|
|
31967
|
+
return;
|
|
31979
31968
|
}
|
|
31980
|
-
|
|
31981
|
-
|
|
31982
|
-
|
|
31983
|
-
|
|
31984
|
-
|
|
31985
|
-
|
|
31986
|
-
|
|
31987
|
-
|
|
31969
|
+
insertPanel(makeWorkspaceExplorerPanel(sessionId, workspace), workspaceExplorerSlot(st.panels, selectedIndex_(), d$4().getMoveFacts()));
|
|
31970
|
+
}
|
|
31971
|
+
/** Chip click action (The Glass Browser spec W2, ADR-0029 D4): ONE live
|
|
31972
|
+
* browser panel across the floor — the terminal singleton rule (Terminal
|
|
31973
|
+
* Desk ADR D2). A click on an open browser FOCUSES it; a miss inserts at
|
|
31974
|
+
* the focused slot. */
|
|
31975
|
+
function openBrowserPanel(index, keepSelection = false, width, openedBy, sessionId) {
|
|
31976
|
+
const open = st.panels.find((p) => p.kind === "browser" && p.openedBy === openedBy);
|
|
31977
|
+
if (open) {
|
|
31978
|
+
st.selectedPanelId = open.id;
|
|
31979
|
+
return;
|
|
31988
31980
|
}
|
|
31989
|
-
|
|
31990
|
-
|
|
31991
|
-
|
|
31981
|
+
const prevSelected = st.selectedPanelId;
|
|
31982
|
+
const slot = index !== void 0 ? Math.max(0, Math.min(index, st.panels.length)) : openedBy !== void 0 ? glassFirstSlot(st.panels, openedBy) : insertionSlot();
|
|
31983
|
+
insertPanel(makeBrowserPanel(width, openedBy, sessionId), slot);
|
|
31984
|
+
if (keepSelection && prevSelected !== null && prevSelected !== void 0) {
|
|
31985
|
+
if (st.panels.some((p) => p.id === prevSelected)) st.selectedPanelId = prevSelected;
|
|
31992
31986
|
}
|
|
31993
|
-
}
|
|
31994
|
-
|
|
31995
|
-
|
|
31987
|
+
}
|
|
31988
|
+
/** The open explorer for a session's workspace (The Shared Tree D1):
|
|
31989
|
+
* matched by ROOT across sessions — the panel's provenance sessionId
|
|
31990
|
+
* is not the key. */
|
|
31991
|
+
function sessionWorkspaceExplorer(sessionId) {
|
|
31992
|
+
const root = d$4().getWorkspaceFor(sessionId);
|
|
31993
|
+
return root === null ? void 0 : findWorkspaceExplorerPanel(st.panels, root);
|
|
31994
|
+
}
|
|
31995
|
+
/** Explorer tree intents: the panel emits toggle/open-file; the owner
|
|
31996
|
+
* mutates expanded (the persisted part) — the levels cache stays
|
|
31997
|
+
* component-local. */
|
|
31998
|
+
function toggleExplorerPath(panelId, path) {
|
|
31999
|
+
const idx = st.panels.findIndex((p) => p.id === panelId);
|
|
32000
|
+
if (idx < 0 || st.panels[idx].kind !== "workspace-explorer") return;
|
|
32001
|
+
const explorer = st.panels[idx];
|
|
32002
|
+
const next = explorer.expanded.includes(path) ? explorer.expanded.filter((p) => p !== path) : [...explorer.expanded, path];
|
|
32003
|
+
st.panels = st.panels.with(idx, {
|
|
32004
|
+
...explorer,
|
|
32005
|
+
expanded: next
|
|
32006
|
+
});
|
|
32007
|
+
}
|
|
32008
|
+
/** Explorer collapse-all intent: the panel emits; the owner empties the
|
|
32009
|
+
* expanded list (the persisted part). */
|
|
32010
|
+
function collapseExplorerPaths(panelId) {
|
|
32011
|
+
const idx = st.panels.findIndex((p) => p.id === panelId);
|
|
32012
|
+
if (idx < 0 || st.panels[idx].kind !== "workspace-explorer") return;
|
|
32013
|
+
st.panels = st.panels.with(idx, {
|
|
32014
|
+
...st.panels[idx],
|
|
32015
|
+
expanded: []
|
|
32016
|
+
});
|
|
32017
|
+
}
|
|
32018
|
+
/** Git Eye tab intent (2026-09-12): the active tab is PERSISTED on the
|
|
32019
|
+
* entry — a hard reload restores it. */
|
|
32020
|
+
function setExplorerTab(panelId, tab) {
|
|
32021
|
+
const idx = st.panels.findIndex((p) => p.id === panelId);
|
|
32022
|
+
if (idx < 0 || st.panels[idx].kind !== "workspace-explorer") return;
|
|
32023
|
+
st.panels = st.panels.with(idx, {
|
|
32024
|
+
...st.panels[idx],
|
|
32025
|
+
tab
|
|
32026
|
+
});
|
|
32027
|
+
}
|
|
32028
|
+
/** Explorer Layout tabs (amendment 2026-09-16): the tab list and the
|
|
32029
|
+
* active tab are OWNER-PERSISTED entry facts. The file tabs die with
|
|
32030
|
+
* the panel (D5). */
|
|
32031
|
+
function openExplorerTab(panelId, path) {
|
|
32032
|
+
const idx = st.panels.findIndex((p) => p.id === panelId);
|
|
32033
|
+
if (idx < 0 || st.panels[idx].kind !== "workspace-explorer") return;
|
|
32034
|
+
const ex = st.panels[idx];
|
|
32035
|
+
const tabs = ex.openTabs ?? [];
|
|
32036
|
+
const openTabs = tabs.includes(path) ? tabs : [...tabs, path];
|
|
32037
|
+
st.panels = st.panels.with(idx, {
|
|
32038
|
+
...ex,
|
|
32039
|
+
openTabs,
|
|
32040
|
+
activeFile: path
|
|
32041
|
+
});
|
|
32042
|
+
}
|
|
32043
|
+
function closeExplorerTab(panelId, path) {
|
|
32044
|
+
const idx = st.panels.findIndex((p) => p.id === panelId);
|
|
32045
|
+
if (idx < 0 || st.panels[idx].kind !== "workspace-explorer") return;
|
|
32046
|
+
const ex = st.panels[idx];
|
|
32047
|
+
const tabs = ex.openTabs ?? [];
|
|
32048
|
+
const closedAt = tabs.indexOf(path);
|
|
32049
|
+
if (closedAt === -1) return;
|
|
32050
|
+
const openTabs = tabs.filter((p) => p !== path);
|
|
32051
|
+
const activeFile = ex.activeFile === path ? openTabs.length === 0 ? null : openTabs[Math.max(0, closedAt - 1)] : ex.activeFile ?? null;
|
|
32052
|
+
st.panels = st.panels.with(idx, {
|
|
32053
|
+
...ex,
|
|
32054
|
+
openTabs,
|
|
32055
|
+
activeFile
|
|
32056
|
+
});
|
|
32057
|
+
}
|
|
32058
|
+
function activateExplorerTab(panelId, path) {
|
|
32059
|
+
const idx = st.panels.findIndex((p) => p.id === panelId);
|
|
32060
|
+
if (idx < 0 || st.panels[idx].kind !== "workspace-explorer") return;
|
|
32061
|
+
const ex = st.panels[idx];
|
|
32062
|
+
if (!(ex.openTabs ?? []).includes(path)) return;
|
|
32063
|
+
st.panels = st.panels.with(idx, {
|
|
32064
|
+
...ex,
|
|
32065
|
+
activeFile: path
|
|
32066
|
+
});
|
|
32067
|
+
}
|
|
32068
|
+
/** The Explorer Layout drag settle (ADR D4): one DESK fact — the split
|
|
32069
|
+
* is desk state, persisted with the floor blob, NOT per entry. The
|
|
32070
|
+
* panel already clamped; clamp again at the single bound site. */
|
|
32071
|
+
function setExplorerTreePct(_panelId, pct) {
|
|
32072
|
+
d$4().setTreePct(clampTreePct(pct));
|
|
32073
|
+
}
|
|
32074
|
+
/** Git Eye repo-collapse intent (2026-09-13): the collapsed repo set is
|
|
32075
|
+
* PERSISTED on the entry. Default is EXPANDED. */
|
|
32076
|
+
function toggleExplorerRepo(panelId, repoRel) {
|
|
32077
|
+
const idx = st.panels.findIndex((p) => p.id === panelId);
|
|
32078
|
+
if (idx < 0 || st.panels[idx].kind !== "workspace-explorer") return;
|
|
32079
|
+
const explorer = st.panels[idx];
|
|
32080
|
+
const prev = explorer.collapsedRepos ?? [];
|
|
32081
|
+
const next = prev.includes(repoRel) ? prev.filter((r) => r !== repoRel) : [...prev, repoRel];
|
|
32082
|
+
st.panels = st.panels.with(idx, {
|
|
32083
|
+
...explorer,
|
|
32084
|
+
collapsedRepos: next
|
|
32085
|
+
});
|
|
32086
|
+
}
|
|
32087
|
+
/** Git Eye collapse-all-repos intent (2026-09-13): collapses EVERY known
|
|
32088
|
+
* repo — persisted like the single-repo toggle. */
|
|
32089
|
+
function collapseExplorerRepos(panelId, repos) {
|
|
32090
|
+
const idx = st.panels.findIndex((p) => p.id === panelId);
|
|
32091
|
+
if (idx < 0 || st.panels[idx].kind !== "workspace-explorer") return;
|
|
32092
|
+
const explorer = st.panels[idx];
|
|
32093
|
+
const prev = explorer.collapsedRepos ?? [];
|
|
32094
|
+
const next = [...prev, ...repos.filter((r) => !prev.includes(r))];
|
|
32095
|
+
st.panels = st.panels.with(idx, {
|
|
32096
|
+
...explorer,
|
|
32097
|
+
collapsedRepos: next
|
|
32098
|
+
});
|
|
32099
|
+
}
|
|
32100
|
+
/** File Eye view intent (2026-09-13): diff vs edit is PERSISTED on the
|
|
32101
|
+
* entry. */
|
|
32102
|
+
function setFileView(panelId, view) {
|
|
32103
|
+
const idx = st.panels.findIndex((p) => p.id === panelId);
|
|
32104
|
+
if (idx < 0 || st.panels[idx].kind !== "workspace-file") return;
|
|
32105
|
+
st.panels = st.panels.with(idx, {
|
|
32106
|
+
...st.panels[idx],
|
|
32107
|
+
view
|
|
32108
|
+
});
|
|
32109
|
+
}
|
|
32110
|
+
/** Tree file-click action (The Settings Tree ADR 2026-09-18 D1): the
|
|
32111
|
+
* intent publishes to the session's explorer, which opens/focuses a
|
|
32112
|
+
* tab. No open explorer ⇒ the intent drops. */
|
|
32113
|
+
function openWorkspaceFile(sessionId, path, lines) {
|
|
32114
|
+
const host = sessionWorkspaceExplorer(sessionId);
|
|
32115
|
+
if (host) publishFileIntent(host.id, path, lines);
|
|
32116
|
+
}
|
|
32117
|
+
/** Publish a file intent to an explorer panel and focus it. `lines` is
|
|
32118
|
+
* the optional #L anchor target — display metadata, not persisted. */
|
|
32119
|
+
function publishFileIntent(explorerId, path, lines) {
|
|
32120
|
+
st.pendingFileIntents[explorerId] = {
|
|
32121
|
+
path,
|
|
32122
|
+
nonce: ++st.fileIntentSeq,
|
|
32123
|
+
lines: lines ?? null
|
|
32124
|
+
};
|
|
32125
|
+
st.selectedPanelId = explorerId;
|
|
32126
|
+
}
|
|
32127
|
+
/** The panel consumed intent nonce N — clear exactly that publish. */
|
|
32128
|
+
function consumeFileIntent(explorerId, nonce) {
|
|
32129
|
+
if (st.pendingFileIntents[explorerId]?.nonce === nonce) st.pendingFileIntents[explorerId] = null;
|
|
32130
|
+
}
|
|
32131
|
+
/** Remove a panel; family close walks the wire lineage transitively
|
|
32132
|
+
* (every descendant sub-agent goes with it, nested included). The
|
|
32133
|
+
* Shift+Click amendment (2026-09-01): family === false opts OUT — only
|
|
32134
|
+
* THAT panel drops, the children re-root as orphan family heads.
|
|
32135
|
+
*
|
|
32136
|
+
* The session's workspace pair closes with it (2026-09-10); closing an
|
|
32137
|
+
* EXPLORER dooms its file children BY PANEL ID — the stored
|
|
32138
|
+
* explorerPanelId edge, with the legacy null-edge fallback. A
|
|
32139
|
+
* settings-home explorer (sessionId null) dies with the close. */
|
|
32140
|
+
function removePanel(panelId, opts = {}) {
|
|
32141
|
+
const idx = st.panels.findIndex((p) => p.id === panelId);
|
|
32142
|
+
if (idx < 0) return;
|
|
32143
|
+
const root = st.panels[idx];
|
|
32144
|
+
const rootSessionId = root.kind === "conversation" ? root.sessionId : null;
|
|
32145
|
+
const doomed = new SvelteSet(rootSessionId !== null ? [rootSessionId] : []);
|
|
32146
|
+
if (opts.family !== false && rootSessionId !== null) {
|
|
32147
|
+
const stack = [rootSessionId];
|
|
32148
|
+
while (stack.length > 0) for (const kid of d$4().getLineageFacts().childrenByParent.get(stack.pop()) ?? []) if (!doomed.has(kid.sessionId)) {
|
|
32149
|
+
doomed.add(kid.sessionId);
|
|
32150
|
+
stack.push(kid.sessionId);
|
|
32151
|
+
}
|
|
32152
|
+
}
|
|
32153
|
+
const doomedPanelIds = new SvelteSet();
|
|
32154
|
+
if (opts.family !== false && rootSessionId !== null) {
|
|
32155
|
+
for (const p of st.panels) if (p.kind === "browser" && p.openedBy !== void 0 && doomed.has(p.openedBy)) doomedPanelIds.add(p.id);
|
|
32156
|
+
}
|
|
32157
|
+
if (opts.family !== false && root.kind === "workspace-explorer") {
|
|
32158
|
+
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);
|
|
32159
|
+
}
|
|
32160
|
+
st.panels = st.panels.filter((p) => p.id !== root.id && !doomedPanelIds.has(p.id) && (p.kind === "conversation" ? !doomed.has(p.sessionId) : !("sessionId" in p) || p.sessionId === null || opts.family !== false && !doomed.has(p.sessionId)));
|
|
32161
|
+
if (st.selectedPanelId !== null && !st.panels.some((p) => p.id === st.selectedPanelId)) st.selectedPanelId = st.panels[Math.min(idx, st.panels.length - 1)]?.id ?? null;
|
|
32162
|
+
clearLoupeIfGone();
|
|
32163
|
+
}
|
|
32164
|
+
//#endregion
|
|
32165
|
+
//#region src/lib/services/panels/floor-registry/drag.svelte.ts
|
|
32166
|
+
var d$2 = floorSeam;
|
|
32167
|
+
/** Honest-slider's "slider sets all panels" leg (REALTIME, 2026-08-27):
|
|
32168
|
+
* one width for every CONVERSATION column + the uniform preset.
|
|
32169
|
+
* 2026-09-13: the workspace kinds are FIXED lanes — the explorer and
|
|
32170
|
+
* file panels keep their own widths. */
|
|
32171
|
+
function resizeAll(width) {
|
|
32172
|
+
const w = clampPanelWidth(width);
|
|
32173
|
+
d$2().setPanelWidthPreset(w);
|
|
32174
|
+
st.panels = st.panels.map((p) => p.kind === "conversation" ? {
|
|
32175
|
+
...p,
|
|
32176
|
+
width: w
|
|
32177
|
+
} : p);
|
|
32178
|
+
}
|
|
32179
|
+
/** A transcript file link publishes ONLY after the tree route proves
|
|
32180
|
+
* the file exists inside the session's workspace — the gate lives in
|
|
32181
|
+
* the shared util; anything else drops the click. No navigation ever
|
|
32182
|
+
* happens. No explorer yet ⇒ OPEN ONE (amendment 2026-09-25): the link
|
|
32183
|
+
* itself opens the panel; without a workspace root there is nothing to
|
|
32184
|
+
* open. W2 (T2.3): moved wholesale from the route — pure machine over
|
|
32185
|
+
* the deps seam + the shared utils. */
|
|
32186
|
+
async function openFileLinkFromMarkdown(sessionId, rawHref) {
|
|
32187
|
+
const { path, lines } = parseFileLinkHref(rawHref);
|
|
32188
|
+
if (path === "") return;
|
|
32189
|
+
const target = await resolveFileLinkTarget(sessionId, path, d$2().getWorkspaceFor(sessionId), void 0, workspaceRootDirs);
|
|
32190
|
+
if (target === null) return;
|
|
32191
|
+
if (!sessionWorkspaceExplorer(sessionId)) {
|
|
32192
|
+
const root = d$2().getWorkspaceFor(sessionId);
|
|
32193
|
+
if (!root) return;
|
|
32194
|
+
openWorkspaceExplorer(sessionId, root);
|
|
32195
|
+
}
|
|
32196
|
+
openWorkspaceFile(sessionId, target, lines);
|
|
32197
|
+
}
|
|
32198
|
+
/** /events?full=1 carries entries+lastSeq+running+pending/settled
|
|
32199
|
+
* answers (the ledger-tail resync surface); /history carries hasMore.
|
|
32200
|
+
* Its beforeSeq anchor needs the tail's lastSeq, so the events response
|
|
32201
|
+
* resolves first — the only serialization. W2 (T2.6): moved wholesale
|
|
32202
|
+
* from the route — a pure wire read over the global fetch. */
|
|
32203
|
+
async function fetchColdFromWire(sessionId) {
|
|
32204
|
+
const eventsRes = await fetch(`/api/dsh/session/${encodeURIComponent(sessionId)}/events?full=1`);
|
|
32205
|
+
if (!eventsRes.ok) return null;
|
|
32206
|
+
const events = await eventsRes.json();
|
|
32207
|
+
if (!events.ok) return null;
|
|
32208
|
+
const lastSeq = events.lastSeq ?? -1;
|
|
32209
|
+
let hasMore = false;
|
|
32210
|
+
const historyRes = await fetch(`/api/dsh/session/${encodeURIComponent(sessionId)}/history?beforeSeq=${lastSeq + 1}`);
|
|
32211
|
+
if (historyRes.ok) {
|
|
32212
|
+
const history = await historyRes.json();
|
|
32213
|
+
if (history.ok) hasMore = (history.entries?.length ?? 0) > 0 || history.hasMore === true;
|
|
32214
|
+
}
|
|
32215
|
+
return {
|
|
32216
|
+
title: null,
|
|
32217
|
+
workspace: null,
|
|
32218
|
+
agentPreset: null,
|
|
32219
|
+
entries: events.entries ?? [],
|
|
32220
|
+
lastSeq,
|
|
32221
|
+
running: events.running ?? false,
|
|
32222
|
+
hasMore,
|
|
32223
|
+
pendingAnswers: events.pendingAnswers ?? [],
|
|
32224
|
+
settledAnswers: events.settledAnswers ?? [],
|
|
32225
|
+
permission: events.permission ?? null,
|
|
32226
|
+
imageLimits: events.imageLimits ?? null,
|
|
32227
|
+
knobEvents: events.knobEvents ?? [],
|
|
32228
|
+
deliverables: events.deliverables ?? []
|
|
32229
|
+
};
|
|
32230
|
+
}
|
|
32231
|
+
//#endregion
|
|
32232
|
+
//#region src/lib/services/panels/floor-registry/factories.ts
|
|
32233
|
+
/**
|
|
32234
|
+
* floor-registry/factories — panel factories + placement slots (ADR-0022 W2).
|
|
32235
|
+
*
|
|
32236
|
+
* Moved WHOLE from the state home (floor-registry.svelte.ts): the eight
|
|
32237
|
+
* make* panel factories and the slot grammar (insertPanel, insertionSlot,
|
|
32238
|
+
* pinnedSlotIndex). Plain module: no runes here — every write goes through
|
|
32239
|
+
* the state home's reactive `st` hub and its primitives (ADR-0019 D2:
|
|
32240
|
+
* exactly ONE writer home for floor state). Sibling rule: this file never
|
|
32241
|
+
* imports another sibling; shared needs come from the state home.
|
|
32242
|
+
*/
|
|
32243
|
+
var d$1 = floorSeam;
|
|
32244
|
+
function makePanel(sessionId, agentPreset) {
|
|
32245
|
+
return {
|
|
32246
|
+
id: nextPanelId(),
|
|
32247
|
+
kind: "conversation",
|
|
32248
|
+
sessionId,
|
|
32249
|
+
agentPreset,
|
|
32250
|
+
width: clampPanelWidth(d$1().getPanelWidth())
|
|
32251
|
+
};
|
|
32252
|
+
}
|
|
32253
|
+
/** width: the reload-restored panel re-mints at the width the operator
|
|
32254
|
+
* dragged before (browser-slot persistence, RCA 2026-10-22); absent for
|
|
32255
|
+
* chip clicks and legacy slots — the honest-slider preset.
|
|
32256
|
+
* openedBy: the opener session's provenance, recorded ONCE at spawn and
|
|
32257
|
+
* never rewritten (ADR-0036 D1/D2); undefined = no conversation context. */
|
|
32258
|
+
function makeBrowserPanel(width, openedBy, sessionId) {
|
|
32259
|
+
return {
|
|
32260
|
+
id: nextPanelId(),
|
|
32261
|
+
kind: "browser",
|
|
32262
|
+
width: clampPanelWidth(width ?? browserPanelWidth(), "browser"),
|
|
32263
|
+
...openedBy !== void 0 ? { openedBy } : {},
|
|
32264
|
+
...sessionId !== void 0 ? { browserSessionId: sessionId } : {}
|
|
32265
|
+
};
|
|
32266
|
+
}
|
|
32267
|
+
function makeWorkspaceExplorerPanel(sessionId, root) {
|
|
32268
|
+
return {
|
|
32269
|
+
id: nextPanelId(),
|
|
32270
|
+
kind: "workspace-explorer",
|
|
32271
|
+
sessionId,
|
|
32272
|
+
root,
|
|
32273
|
+
expanded: [],
|
|
32274
|
+
width: clampPanelWidth(850, "workspace-explorer")
|
|
32275
|
+
};
|
|
32276
|
+
}
|
|
32277
|
+
function insertPanel(entry, index) {
|
|
32278
|
+
const next = [...st.panels];
|
|
32279
|
+
next.splice(Math.min(index, next.length), 0, entry);
|
|
32280
|
+
st.panels = next;
|
|
32281
|
+
st.selectedPanelId = entry.id;
|
|
32282
|
+
}
|
|
32283
|
+
function insertionSlot() {
|
|
32284
|
+
return focusedInsertionSlot(st.panels, selectedIndex_(), d$1().getMoveFacts().parentOf);
|
|
32285
|
+
}
|
|
32286
|
+
//#endregion
|
|
32287
|
+
//#region src/lib/services/panels/floor-registry.svelte.ts
|
|
32288
|
+
var deps = null;
|
|
32289
|
+
function configureFloorRegistry(d0) {
|
|
32290
|
+
deps = d0;
|
|
32291
|
+
}
|
|
32292
|
+
function d() {
|
|
32293
|
+
if (deps === null) throw new Error("floor-registry: configureFloorRegistry() was never called");
|
|
32294
|
+
return deps;
|
|
32295
|
+
}
|
|
32296
|
+
/** Sibling-module access to the dep seam (ADR-0022 W2): the ONE outside-reads
|
|
32297
|
+
* channel; siblings never open their own config channel. */
|
|
32298
|
+
function floorSeam() {
|
|
32299
|
+
return d();
|
|
32300
|
+
}
|
|
32301
|
+
var st = {
|
|
32302
|
+
panels: [],
|
|
32303
|
+
selectedPanelId: null,
|
|
32304
|
+
loupePanelId: null,
|
|
32305
|
+
focusComposerId: null,
|
|
32306
|
+
panelIdSeq: 0,
|
|
32307
|
+
terminalDeskMirrors: {},
|
|
32308
|
+
pendingFileIntents: {},
|
|
32309
|
+
fileIntentSeq: 0,
|
|
32310
|
+
drag: null,
|
|
32311
|
+
widthBadgeFading: false
|
|
32312
|
+
};
|
|
32313
|
+
/** Non-reactive gesture refs (drag start index, fade timer, badge ids) —
|
|
32314
|
+
* written by floor-registry/drag.svelte.ts; the ids set is a live
|
|
32315
|
+
* SvelteSet so badge visibility stays reactive. */
|
|
32316
|
+
var dragRefs = {
|
|
32317
|
+
ids: new SvelteSet()
|
|
32318
|
+
};
|
|
32319
|
+
var floor = {
|
|
32320
|
+
get panels() {
|
|
32321
|
+
return st.panels;
|
|
32322
|
+
},
|
|
32323
|
+
get selectedPanelId() {
|
|
32324
|
+
return st.selectedPanelId;
|
|
32325
|
+
},
|
|
32326
|
+
get loupePanelId() {
|
|
32327
|
+
return st.loupePanelId;
|
|
32328
|
+
},
|
|
32329
|
+
get focusComposerId() {
|
|
32330
|
+
return st.focusComposerId;
|
|
32331
|
+
},
|
|
32332
|
+
get terminalDeskMirrors() {
|
|
32333
|
+
return st.terminalDeskMirrors;
|
|
32334
|
+
},
|
|
32335
|
+
get pendingFileIntents() {
|
|
32336
|
+
return st.pendingFileIntents;
|
|
32337
|
+
},
|
|
32338
|
+
get drag() {
|
|
32339
|
+
return st.drag;
|
|
32340
|
+
},
|
|
32341
|
+
get widthBadgeFading() {
|
|
32342
|
+
return st.widthBadgeFading;
|
|
32343
|
+
},
|
|
32344
|
+
get widthBadgeIds() {
|
|
32345
|
+
return dragRefs.ids;
|
|
32346
|
+
},
|
|
32347
|
+
get selected() {
|
|
32348
|
+
return st.panels.find((p) => p.id === st.selectedPanelId) ?? null;
|
|
32349
|
+
},
|
|
32350
|
+
get loupePanel() {
|
|
32351
|
+
return st.panels.find((p) => p.id === st.loupePanelId) ?? null;
|
|
32352
|
+
}
|
|
32353
|
+
};
|
|
32354
|
+
function nextPanelId() {
|
|
32355
|
+
st.panelIdSeq += 1;
|
|
32356
|
+
return "panel-" + st.panelIdSeq;
|
|
32357
|
+
}
|
|
32358
|
+
function syncPanelIdSeq(entries) {
|
|
32359
|
+
for (const p of entries) {
|
|
32360
|
+
const m = /^panel-(\d+)$/.exec(p.id);
|
|
32361
|
+
if (m) st.panelIdSeq = Math.max(st.panelIdSeq, Number(m[1]));
|
|
32362
|
+
}
|
|
32363
|
+
}
|
|
32364
|
+
function initFloor(entries, selectedId) {
|
|
32365
|
+
st.panels = entries;
|
|
32366
|
+
st.selectedPanelId = selectedId;
|
|
32367
|
+
syncPanelIdSeq(entries);
|
|
32368
|
+
}
|
|
32369
|
+
/** The fresh panel mounted and its composer took focus — clear the
|
|
32370
|
+
* swap-focus marker (a marker whose panel never mounts stays inert:
|
|
32371
|
+
* panel ids are unique and never remount). */
|
|
32372
|
+
function clearFocusComposer() {
|
|
32373
|
+
st.focusComposerId = null;
|
|
32374
|
+
}
|
|
32375
|
+
function selectPanel(panelId) {
|
|
32376
|
+
if (st.panels.some((p) => p.id === panelId)) st.selectedPanelId = panelId;
|
|
32377
|
+
}
|
|
32378
|
+
function closeLoupe() {
|
|
32379
|
+
st.loupePanelId = null;
|
|
32380
|
+
}
|
|
32381
|
+
function clearLoupeIfGone() {
|
|
32382
|
+
if (st.loupePanelId !== null && !st.panels.some((p) => p.id === st.loupePanelId)) st.loupePanelId = null;
|
|
32383
|
+
}
|
|
32384
|
+
function selectedIndex_() {
|
|
32385
|
+
return st.panels.findIndex((p) => p.id === st.selectedPanelId);
|
|
32386
|
+
}
|
|
32387
|
+
//#endregion
|
|
32388
|
+
//#region src/lib/utils/compact-number.ts
|
|
32389
|
+
/** Compact number formatting for narrow UI badges: 1829 -> '1.8K',
|
|
32390
|
+
* 4200000 -> '4.2M'. Locale-stable ('en') so rack rows keep their width. */
|
|
32391
|
+
var compact = new Intl.NumberFormat("en", {
|
|
32392
|
+
notation: "compact",
|
|
32393
|
+
maximumFractionDigits: 1
|
|
32394
|
+
});
|
|
32395
|
+
function formatCompact(n) {
|
|
32396
|
+
return compact.format(n);
|
|
32397
|
+
}
|
|
32398
|
+
//#endregion
|
|
32399
|
+
//#region src/lib/components/anchor/subagent-anchor/SubagentPopup.svelte
|
|
32400
|
+
function SubagentPopup($$renderer, $$props) {
|
|
32401
|
+
$$renderer.component(($$renderer) => {
|
|
32402
|
+
/**
|
|
32403
|
+
* SubagentPopup — the ledger half of the Subagent Anchor (Subagent
|
|
32404
|
+
* Anchor ADR D1/D5, amendment D6/D7): every spawned session as ONE flat
|
|
32405
|
+
* row — title · tokens · elapsed — inside the house popup shell (Esc /
|
|
32406
|
+
* outside close, right-full placement, width cap). The popup owns NO
|
|
32407
|
+
* state: rows arrive as props from the anchor button's poll; elapsed
|
|
32408
|
+
* lives only in the subagent-clock registry; lineage is re-derived
|
|
32409
|
+
* per fetch upstream, never written here.
|
|
32410
|
+
*
|
|
32411
|
+
* D6 header: shell title row + the count chip (N helpers, M running).
|
|
32412
|
+
* D5 sort: running first, then token spend descending (nulls last).
|
|
32413
|
+
* D7 footer: Σ over EXACTLY the header's rows; any null-degraded row
|
|
32414
|
+
* flips it to the honest Σ-incomplete marker — a partial sum must never
|
|
32415
|
+
* read as whole. Elapsed is NOT summed (concurrent wall-clocks add to
|
|
32416
|
+
* nothing). The footnote states the one-tick first-sight bias.
|
|
32417
|
+
*/
|
|
32418
|
+
let { open = false, triggerEl = void 0, rows, onopenrow } = $$props;
|
|
32419
|
+
const spend = (row) => row.tokens === null ? -1 : row.tokens.input + row.tokens.output;
|
|
32420
|
+
/** D5: running first, then token spend desc (unknown spends last),
|
|
32421
|
+
* then session id for a stable tiebreak. */
|
|
32422
|
+
const sorted = derived(() => [...rows].sort((a, b) => Number(b.running) - Number(a.running) || spend(b) - spend(a) || a.sessionId.localeCompare(b.sessionId)));
|
|
32423
|
+
const runningCount = derived(() => rows.filter((r) => r.running).length);
|
|
32424
|
+
const anyUnknown = derived(() => rows.some((r) => r.tokens === null));
|
|
32425
|
+
const totalTokens = derived(() => rows.reduce((acc, r) => r.tokens === null ? acc : acc + r.tokens.input + r.tokens.output, 0));
|
|
32426
|
+
/** True when this helper's panel is already open on the floor — the
|
|
32427
|
+
* row tints so the operator sees which helpers live in the zoom. */
|
|
32428
|
+
function onFloor(sessionId) {
|
|
32429
|
+
return floorPanelId(sessionId) !== null;
|
|
32430
|
+
}
|
|
32431
|
+
/** The floor panel id hosting this helper, null when not open. */
|
|
32432
|
+
function floorPanelId(sessionId) {
|
|
32433
|
+
return floor.panels.find((panel) => "sessionId" in panel && panel.sessionId === sessionId)?.id ?? null;
|
|
32434
|
+
}
|
|
32435
|
+
/** Any helper live on the floor — the close-all X's visibility. */
|
|
32436
|
+
const anyOnFloor = derived(() => rows.some((r) => onFloor(r.sessionId)));
|
|
32437
|
+
/** Compact ledger form, DSH GUI parity — null renders the dash (never 0). */
|
|
32438
|
+
function tokensLabel(row) {
|
|
32439
|
+
if (row.tokens === null) return "—";
|
|
32440
|
+
return `${formatCompact(row.tokens.input + row.tokens.output)} tok`;
|
|
32441
|
+
}
|
|
32442
|
+
/** Elapsed label — the ledger's operate time (llmMs, the stats bar's
|
|
32443
|
+
* own 'LLM …' number, settled rows included). The first-sight clock is
|
|
32444
|
+
* the FALLBACK for rows the host cannot date; null renders the dash
|
|
32445
|
+
* (never a guess). */
|
|
32446
|
+
function elapsedLabel(row) {
|
|
32447
|
+
let ms;
|
|
32448
|
+
if (typeof row.operateMs === "number") ms = row.operateMs;
|
|
32449
|
+
else ms = subagentClock.elapsedMs(row.sessionId);
|
|
32450
|
+
if (ms === null) return "—";
|
|
32451
|
+
const s = Math.floor(ms / 1e3);
|
|
32452
|
+
if (s < 60) return `${s}s`;
|
|
32453
|
+
const m = Math.floor(s / 60);
|
|
32454
|
+
if (m < 60) return `${m}m ${s % 60}s`;
|
|
32455
|
+
return `${Math.floor(m / 60)}h ${m % 60}m`;
|
|
32456
|
+
}
|
|
32457
|
+
let $$settled = true;
|
|
32458
|
+
let $$inner_renderer;
|
|
32459
|
+
function $$render_inner($$renderer) {
|
|
32460
|
+
FloatingAnchorContainerPopup($$renderer, {
|
|
32461
|
+
triggerEl,
|
|
32462
|
+
popupTestId: "subagent-popup",
|
|
32463
|
+
get open() {
|
|
32464
|
+
return open;
|
|
32465
|
+
},
|
|
32466
|
+
set open($$value) {
|
|
32467
|
+
open = $$value;
|
|
32468
|
+
$$settled = false;
|
|
32469
|
+
},
|
|
32470
|
+
children: ($$renderer) => {
|
|
32471
|
+
$$renderer.push(`<div class="flex items-center border-b border-surface-border px-2.5 py-1 text-[10px] uppercase tracking-wider text-text-muted" data-testid="subagent-popup-chip"><span class="flex-1">${escape_html(rows.length)}
|
|
32472
|
+
${escape_html(rows.length === 1 ? "subagent" : "subagents")} · ${escape_html(runningCount())} running</span> `);
|
|
32473
|
+
if (anyOnFloor()) {
|
|
32474
|
+
$$renderer.push("<!--[0-->");
|
|
32475
|
+
$$renderer.push(`<button type="button" class="shrink-0 transition-colors"${attr("title", t(subagentcloseallpanels3))}${attr("aria-label", t(subagentcloseallpanels3))} data-testid="subagent-popup-close-all">`);
|
|
32476
|
+
Trash_2($$renderer, {
|
|
32477
|
+
size: 14,
|
|
32478
|
+
"aria-hidden": "true",
|
|
32479
|
+
style: "stroke: red;"
|
|
32480
|
+
});
|
|
32481
|
+
$$renderer.push(`<!----></button>`);
|
|
32482
|
+
} else $$renderer.push("<!--[-1-->");
|
|
32483
|
+
$$renderer.push(`<!--]--></div> <!--[-->`);
|
|
32484
|
+
const each_array = ensure_array_like(sorted());
|
|
32485
|
+
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
|
|
32486
|
+
let row = each_array[$$index];
|
|
32487
|
+
$$renderer.push(`<button type="button"${attr_class(`flex w-full items-center gap-2 px-2.5 py-1.5 text-left text-xs transition-colors hover:bg-surface-hover ${onFloor(row.sessionId) ? "row-on-floor" : ""}`, "svelte-1lupp7r")} data-testid="subagent-row"><span${attr_class(`flex shrink-0 items-center ${row.running ? "text-amber-500" : "text-text-muted"}`)} data-testid="subagent-row-glyph">`);
|
|
32488
|
+
if (row.running) {
|
|
32489
|
+
$$renderer.push("<!--[0-->");
|
|
32490
|
+
Loader_circle($$renderer, {
|
|
32491
|
+
size: 11,
|
|
32492
|
+
class: "animate-spin"
|
|
32493
|
+
});
|
|
32494
|
+
} else {
|
|
32495
|
+
$$renderer.push("<!--[-1-->");
|
|
32496
|
+
Circle_dashed($$renderer, { size: 11 });
|
|
32497
|
+
}
|
|
32498
|
+
$$renderer.push(`<!--]--></span> <span class="min-w-0 flex-1 truncate">${escape_html(row.title ?? "—")}</span> <span class="w-20 shrink-0 text-right font-variant-numeric tabular-nums" data-testid="subagent-row-tokens">${escape_html(tokensLabel(row))}</span> <span class="w-14 shrink-0 text-right text-text-muted tabular-nums" data-testid="subagent-row-elapsed">${escape_html(elapsedLabel(row))}</span></button>`);
|
|
32499
|
+
}
|
|
32500
|
+
$$renderer.push(`<!--]--> <div${attr_class(`sticky bottom-0 flex items-center border-t border-surface-border bg-surface-elevated px-2.5 py-1.5 text-[12px] font-medium tracking-wider ${anyUnknown() ? "text-text-muted" : "text-text-primary"}`)} data-testid="subagent-popup-footer" style="padding-right: 6em;"><span class="flex-1 text-right">${escape_html(t(() => totaltokens1()))}</span> <span class="w-20 shrink-0 text-right font-variant-numeric tabular-nums" data-testid="subagent-popup-footer-tokens">${escape_html(anyUnknown() ? "—" : `${formatCompact(totalTokens())} tok`)}</span></div>`);
|
|
32501
|
+
},
|
|
32502
|
+
$$slots: { default: true }
|
|
32503
|
+
});
|
|
32504
|
+
}
|
|
32505
|
+
do {
|
|
32506
|
+
$$settled = true;
|
|
32507
|
+
$$inner_renderer = $$renderer.copy();
|
|
32508
|
+
$$render_inner($$inner_renderer);
|
|
32509
|
+
} while (!$$settled);
|
|
32510
|
+
$$renderer.subsume($$inner_renderer);
|
|
32511
|
+
bind_props($$props, { open });
|
|
32512
|
+
});
|
|
32513
|
+
}
|
|
32514
|
+
//#endregion
|
|
32515
|
+
//#region src/lib/components/anchor/subagent-anchor/SubagentAnchorButton.svelte
|
|
32516
|
+
function SubagentAnchorButton($$renderer, $$props) {
|
|
32517
|
+
$$renderer.component(($$renderer) => {
|
|
32518
|
+
/**
|
|
32519
|
+
* SubagentAnchorButton — the ledger leaf of the conversation page's
|
|
32520
|
+
* FloatingAnchor stack (Subagent Anchor ADR D1, placement REVISED
|
|
32521
|
+
* 2026-10-26: the operator's 'anchor' means the right-edge icon
|
|
32522
|
+
* column beside the transcript — JobsButton's seat — NOT the sidebar
|
|
32523
|
+
* header). Lists THIS conversation's sub-agents only (the ?parent
|
|
32524
|
+
* scoping, DSH dropdown parity) — one click: title, tokens, elapsed.
|
|
32525
|
+
* Hidden at zero rows so the stack keeps its shape. Owns the poll:
|
|
32526
|
+
* one GET per few seconds while mounted, each answer fed to the
|
|
32527
|
+
* subagent-clock registry as its spine tick (ADR D3).
|
|
32528
|
+
*/
|
|
32529
|
+
let { onopensession = void 0} = $$props;
|
|
32530
|
+
let rows = [];
|
|
32531
|
+
let open = false;
|
|
32532
|
+
/** The toggle's wrapper — the shell's close-contract exclusion. */
|
|
32533
|
+
let triggerEl = void 0;
|
|
32534
|
+
const runningCount = derived(() => rows.filter((r) => r.running).length);
|
|
32535
|
+
let $$settled = true;
|
|
32536
|
+
let $$inner_renderer;
|
|
32537
|
+
function $$render_inner($$renderer) {
|
|
32538
|
+
if (rows.length > 0) {
|
|
32539
|
+
$$renderer.push("<!--[0-->");
|
|
32540
|
+
$$renderer.push(`<div data-svelte="SubagentAnchorButton" class="relative" data-testid="subagent-anchor-button"><button type="button"${attr_class(`floating-anchor-btn ${runningCount() > 0 ? "tone-purple" : "tone-idle"}`, "svelte-1vxt4fg", { "active": open })}${attr("title", t(subagentanchorlabel2))}${attr("aria-label", t(subagentanchorlabel2))} data-testid="subagent-anchor-trigger">`);
|
|
32541
|
+
Bot($$renderer, {
|
|
32542
|
+
size: 13,
|
|
32543
|
+
"aria-hidden": "true"
|
|
32544
|
+
});
|
|
32545
|
+
$$renderer.push(`<!----> <span data-testid="subagent-anchor-badge">${escape_html(runningCount() > 0 ? runningCount() : rows.length)}</span></button> `);
|
|
32546
|
+
SubagentPopup($$renderer, {
|
|
32547
|
+
triggerEl,
|
|
32548
|
+
rows,
|
|
32549
|
+
onopenrow: onopensession,
|
|
32550
|
+
get open() {
|
|
32551
|
+
return open;
|
|
32552
|
+
},
|
|
32553
|
+
set open($$value) {
|
|
32554
|
+
open = $$value;
|
|
32555
|
+
$$settled = false;
|
|
32556
|
+
}
|
|
32557
|
+
});
|
|
32558
|
+
$$renderer.push(`<!----></div>`);
|
|
32559
|
+
} else $$renderer.push("<!--[-1-->");
|
|
32560
|
+
$$renderer.push(`<!--]-->`);
|
|
32561
|
+
}
|
|
32562
|
+
do {
|
|
32563
|
+
$$settled = true;
|
|
32564
|
+
$$inner_renderer = $$renderer.copy();
|
|
32565
|
+
$$render_inner($$inner_renderer);
|
|
32566
|
+
} while (!$$settled);
|
|
32567
|
+
$$renderer.subsume($$inner_renderer);
|
|
32568
|
+
});
|
|
32569
|
+
}
|
|
32570
|
+
//#endregion
|
|
32571
|
+
//#region src/lib/components/conversation/panel/ConversationFloatingAnchor.svelte
|
|
32572
|
+
function ConversationFloatingAnchor($$renderer, $$props) {
|
|
32573
|
+
/**
|
|
32574
|
+
* ConversationFloatingAnchor — the conversation page's floating action
|
|
32575
|
+
* stack (OCI Floating Host port, 2026-08-23; extracted from the page
|
|
32576
|
+
* 2026-08-24): jump and scroll actions beside the transcript they act
|
|
32577
|
+
* on — the User Messages button (self-contained with its popup jumper
|
|
32578
|
+
* since 2026-08-26; renders only when prompt groups exist) and the
|
|
32579
|
+
* far-edge jump. Purely presentational — the viewport and turn groups
|
|
32580
|
+
* arrive as props.
|
|
32581
|
+
*/
|
|
32582
|
+
let { groups, container, todos = null, deliverables = null, onfileopen = void 0, jobsessionid = "", shelfentries = void 0, shelfsessionid = "", shelfworkspace = null, shelfpanelid = null, onshelfnote } = $$props;
|
|
32583
|
+
if (container !== void 0) {
|
|
32584
|
+
$$renderer.push("<!--[0-->");
|
|
32585
|
+
FloatingAnchor($$renderer, {
|
|
32586
|
+
children: ($$renderer) => {
|
|
32587
|
+
PlanButton($$renderer, { todos: todos ?? [] });
|
|
32588
|
+
$$renderer.push(`<!----> `);
|
|
32589
|
+
DeliverablesButton($$renderer, {
|
|
32590
|
+
deliveries: deliverables,
|
|
32591
|
+
onfileopen
|
|
32592
|
+
});
|
|
32593
|
+
$$renderer.push(`<!----> `);
|
|
32594
|
+
JobsButton($$renderer, { sessionId: jobsessionid });
|
|
32595
|
+
$$renderer.push(`<!----> `);
|
|
32596
|
+
SubagentAnchorButton($$renderer, { });
|
|
32597
|
+
$$renderer.push(`<!----> `);
|
|
32598
|
+
if (shelfentries !== void 0) {
|
|
32599
|
+
$$renderer.push("<!--[0-->");
|
|
32600
|
+
InjectedShelfButton($$renderer, {
|
|
32601
|
+
entries: shelfentries,
|
|
32602
|
+
sessionId: shelfsessionid,
|
|
32603
|
+
workspace: shelfworkspace,
|
|
32604
|
+
panelId: shelfpanelid,
|
|
32605
|
+
onnote: onshelfnote
|
|
32606
|
+
});
|
|
32607
|
+
} else $$renderer.push("<!--[-1-->");
|
|
32608
|
+
$$renderer.push(`<!--]--> `);
|
|
32609
|
+
UserMessagesButton($$renderer, {
|
|
32610
|
+
groups,
|
|
32611
|
+
container
|
|
32612
|
+
});
|
|
32613
|
+
$$renderer.push(`<!----> `);
|
|
32614
|
+
BackToTheEdgeButton($$renderer);
|
|
32615
|
+
$$renderer.push(`<!---->`);
|
|
32616
|
+
}});
|
|
32617
|
+
} else $$renderer.push("<!--[-1-->");
|
|
32618
|
+
$$renderer.push(`<!--]-->`);
|
|
32619
|
+
}
|
|
32620
|
+
//#endregion
|
|
32621
|
+
//#region src/lib/components/conversation/panel/A2aChipStack.svelte
|
|
32622
|
+
function A2aChipStack($$renderer, $$props) {
|
|
32623
|
+
$$renderer.component(($$renderer) => {
|
|
32624
|
+
/**
|
|
32625
|
+
* A2aChipStack — the sender panel's read-only delegation-ledger join
|
|
32626
|
+
* (W4 4.2): one floating chip per recent exchange THIS panel sent,
|
|
32627
|
+
* rendered beside the transcript on the floating-anchor pattern
|
|
32628
|
+
* (right-middle stack, per-panel via the embedded anchor host).
|
|
32629
|
+
*
|
|
32630
|
+
* Honesty contract (PRD risk "Attribution overclaim in UI" + spec-check
|
|
32631
|
+
* GAP-5): chip text derives from the row's `state` VERBATIM, all six
|
|
32632
|
+
* states distinguished — `replied_approx` renders "may have replied",
|
|
32633
|
+
* NEVER the confident "replied" string. The ledger is the truth; this
|
|
32634
|
+
* component claims nothing the row does not say.
|
|
32635
|
+
*
|
|
32636
|
+
* Read-only by construction (BC-2): rows arrive as a prop from the
|
|
32637
|
+
* page's EXISTING spine-cadence poll of GET /api/a2a?from= — the chip
|
|
32638
|
+
* owns NO fetch, NO timer. Click = the existing panel doorway
|
|
32639
|
+
* (addPanelFromSidebar dedupe→select). Dismiss is LOCAL-ONLY visual:
|
|
32640
|
+
* rows are durable; the next poll brings a dismissed chip back only
|
|
32641
|
+
* when it is still in the page's fetched window.
|
|
32642
|
+
*/
|
|
32643
|
+
let { rows, titles } = $$props;
|
|
32644
|
+
/** Local-only visual dismissal — rows are durable; the ledger is truth. */
|
|
32645
|
+
let dismissed = /* @__PURE__ */ new Set();
|
|
32646
|
+
/** The cap: newest 3 visible + one overflow indicator (spec 4.2). */
|
|
32647
|
+
const CHIP_CAP = 3;
|
|
32648
|
+
const visible = derived(() => rows.filter((r) => !dismissed.has(r.id)));
|
|
32649
|
+
const capped = derived(() => visible().slice(0, CHIP_CAP));
|
|
32650
|
+
const overflow = derived(() => Math.max(visible().length - CHIP_CAP, 0));
|
|
32651
|
+
/**
|
|
32652
|
+
* Chip text derives from the state VERBATIM (spec-check GAP-5): every
|
|
32653
|
+
* state distinguished, `replied_approx` hedged as "may have replied" —
|
|
32654
|
+
* never a confident claim the row cannot support.
|
|
32655
|
+
*/
|
|
32656
|
+
function labelFor(state) {
|
|
32657
|
+
switch (state) {
|
|
32658
|
+
case "waiting": return "waiting";
|
|
32659
|
+
case "replied_exact": return "replied (exact)";
|
|
32660
|
+
case "replied": return "replied";
|
|
32661
|
+
case "replied_approx": return "may have replied";
|
|
32662
|
+
case "timeout": return "no reply (timeout)";
|
|
32663
|
+
case "gone": return "target gone";
|
|
32664
|
+
}
|
|
32665
|
+
}
|
|
32666
|
+
/** The target's display title — the spine title, else the id prefix. */
|
|
32667
|
+
function titleFor(toSession) {
|
|
32668
|
+
return titles[toSession] ?? toSession.replace(/^session-/, "").slice(0, 8);
|
|
32669
|
+
}
|
|
32670
|
+
if (visible().length > 0) {
|
|
32671
|
+
$$renderer.push("<!--[0-->");
|
|
32672
|
+
FloatingAnchor($$renderer, {
|
|
32673
|
+
children: ($$renderer) => {
|
|
32674
|
+
$$renderer.push(`<!--[-->`);
|
|
32675
|
+
const each_array = ensure_array_like(capped());
|
|
32676
|
+
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
|
|
32677
|
+
let row = each_array[$$index];
|
|
32678
|
+
$$renderer.push(`<div class="a2a-chip-wrap" data-testid="a2a-chip"${attr("data-a2a-state", row.state)}${attr("data-a2a-id", row.id)}><button type="button"${attr_class("a2a-chip", void 0, {
|
|
32679
|
+
"tone-waiting": row.state === "waiting",
|
|
32680
|
+
"tone-replied-exact": row.state === "replied_exact",
|
|
32681
|
+
"tone-replied": row.state === "replied",
|
|
32682
|
+
"tone-replied-approx": row.state === "replied_approx",
|
|
32683
|
+
"tone-timeout": row.state === "timeout",
|
|
32684
|
+
"tone-gone": row.state === "gone"
|
|
32685
|
+
})} data-testid="a2a-chip-button"${attr("title", `${stringify(titleFor(row.toSession))} — ${stringify(labelFor(row.state))}`)}>`);
|
|
32686
|
+
if (row.state === "waiting") {
|
|
32687
|
+
$$renderer.push("<!--[0-->");
|
|
32688
|
+
Hourglass($$renderer, { size: 13 });
|
|
32689
|
+
} else if (row.state === "replied_exact" || row.state === "replied") {
|
|
32690
|
+
$$renderer.push("<!--[1-->");
|
|
32691
|
+
Check($$renderer, { size: 13 });
|
|
32692
|
+
} else $$renderer.push("<!--[-1-->");
|
|
32693
|
+
$$renderer.push(`<!--]--> <span class="a2a-chip-label">${escape_html(labelFor(row.state))}</span></button> <button type="button" class="a2a-dismiss" data-testid="a2a-chip-dismiss" title="hide this chip (the ledger row stays)">`);
|
|
32694
|
+
X($$renderer, { size: 11 });
|
|
32695
|
+
$$renderer.push(`<!----></button></div>`);
|
|
32696
|
+
}
|
|
32697
|
+
$$renderer.push(`<!--]--> `);
|
|
32698
|
+
if (overflow() > 0) {
|
|
32699
|
+
$$renderer.push("<!--[0-->");
|
|
32700
|
+
$$renderer.push(`<div class="a2a-chip-overflow" data-testid="a2a-chip-overflow">+${escape_html(overflow())} more</div>`);
|
|
32701
|
+
} else $$renderer.push("<!--[-1-->");
|
|
32702
|
+
$$renderer.push(`<!--]-->`);
|
|
32703
|
+
}});
|
|
32704
|
+
} else $$renderer.push("<!--[-1-->");
|
|
32705
|
+
$$renderer.push(`<!--]-->`);
|
|
32706
|
+
});
|
|
32707
|
+
}
|
|
32708
|
+
//#endregion
|
|
32709
|
+
//#region src/lib/components/conversation/panel/ConversationStatsBar.svelte
|
|
32710
|
+
function ConversationStatsBar($$renderer, $$props) {
|
|
32711
|
+
$$renderer.component(($$renderer) => {
|
|
32712
|
+
/**
|
|
32713
|
+
* ConversationStatsBar — the panel's session baseline (ADR 2026-09-08
|
|
32714
|
+
* "The Stats Bar", D1/D3/D5): one fixed-height line under the transcript
|
|
32715
|
+
* showing what the ledger already proves — turns, steps, tool time,
|
|
32716
|
+
* token totals, cache hit. Pure presentation: the panel derives the
|
|
32717
|
+
* stats and hands them down; segments whose inputs never reached DSI
|
|
32718
|
+
* are omitted, never approximated. Renders nothing before the first
|
|
32719
|
+
* assistant message (D5 gate lives in the derive's null return).
|
|
32720
|
+
*/
|
|
32721
|
+
let { stats } = $$props;
|
|
32722
|
+
/** 85000 -> "1m25s"; 2400000 -> "40m"; 5400000 -> "1h30m"; 250 -> "250ms". */
|
|
32723
|
+
function formatDuration(ms) {
|
|
32724
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
32725
|
+
const totalSec = Math.floor(ms / 1e3);
|
|
32726
|
+
const h = Math.floor(totalSec / 3600);
|
|
32727
|
+
const m = Math.floor(totalSec % 3600 / 60);
|
|
32728
|
+
const s = totalSec % 60;
|
|
32729
|
+
if (h > 0) return `${h}h${m}m`;
|
|
32730
|
+
if (m > 0) return s > 0 ? `${m}m${s}s` : `${m}m`;
|
|
32731
|
+
return `${s}s`;
|
|
32732
|
+
}
|
|
32733
|
+
/** 15800 -> "15.8K"; 56300 -> "56.3K"; 15800000 -> "15.8M"; 108000 -> "108K"; 999 -> "999". */
|
|
32734
|
+
function formatTokens(n) {
|
|
32735
|
+
if (n >= 1e6) return `${(n / 1e6).toFixed(1).replace(/\.0$/, "")}M`;
|
|
32736
|
+
if (n >= 1e3) return `${(n / 1e3).toFixed(1).replace(/\.0$/, "")}K`;
|
|
32737
|
+
return String(n);
|
|
32738
|
+
}
|
|
32739
|
+
const segments = derived(() => {
|
|
32740
|
+
if (stats === null) return [];
|
|
32741
|
+
const parts = [`${stats.turns} turns · ${stats.steps} steps`];
|
|
32742
|
+
const durations = [];
|
|
32743
|
+
if (stats.llmMs !== void 0 && stats.llmMs > 0) durations.push(`LLM ${formatDuration(stats.llmMs)}`);
|
|
32744
|
+
if (stats.toolMs > 0) durations.push(`Tool ${formatDuration(stats.toolMs)}`);
|
|
32745
|
+
if (durations.length > 0) parts.push(durations.join(" · "));
|
|
32746
|
+
const speeds = [];
|
|
32747
|
+
if (stats.ttftSteps !== void 0 && stats.ttftSteps > 0 && stats.ttftMs !== void 0) speeds.push(`TTFT avg ${formatDuration(stats.ttftMs / stats.ttftSteps)}`);
|
|
32748
|
+
if (stats.decodeMs !== void 0 && stats.decodeMs > 0 && stats.decodeTokens !== void 0) speeds.push(`${Math.max(1, Math.round(stats.decodeTokens / (stats.decodeMs / 1e3)))} tok/s`);
|
|
32749
|
+
if (speeds.length > 0) parts.push(speeds.join(" · "));
|
|
32750
|
+
const inputTotal = stats.billedInputTokens ?? stats.inputTokens;
|
|
32751
|
+
if (inputTotal !== void 0) parts.push(`Input ${formatTokens(inputTotal)} tok · Output ${formatTokens(stats.outputTokens ?? 0)} tok`);
|
|
32752
|
+
if (stats.cacheHitPercent !== void 0) parts.push(`Cache hit ${stats.cacheHitPercent}%`);
|
|
32753
|
+
return parts;
|
|
32754
|
+
});
|
|
32755
|
+
if (stats !== null) {
|
|
32756
|
+
$$renderer.push("<!--[0-->");
|
|
32757
|
+
$$renderer.push(`<div data-svelte="ConversationStatsBar" class="stats-bar svelte-hnxn10" data-testid="conversation-stats-bar"${attr("title", segments().join(" | "))}><!--[-->`);
|
|
32758
|
+
const each_array = ensure_array_like(segments());
|
|
32759
|
+
for (let i = 0, $$length = each_array.length; i < $$length; i++) {
|
|
32760
|
+
let segment = each_array[i];
|
|
32761
|
+
if (i > 0) {
|
|
32762
|
+
$$renderer.push("<!--[0-->");
|
|
32763
|
+
$$renderer.push(`<span class="sep svelte-hnxn10" aria-hidden="true">|</span>`);
|
|
32764
|
+
} else $$renderer.push("<!--[-1-->");
|
|
32765
|
+
$$renderer.push(`<!--]--> <span class="segment svelte-hnxn10" data-testid="stats-segment">${escape_html(segment)}</span>`);
|
|
32766
|
+
}
|
|
32767
|
+
$$renderer.push(`<!--]--></div>`);
|
|
32768
|
+
} else $$renderer.push("<!--[-1-->");
|
|
32769
|
+
$$renderer.push(`<!--]-->`);
|
|
32770
|
+
});
|
|
32771
|
+
}
|
|
32772
|
+
//#endregion
|
|
32773
|
+
//#region src/lib/components/conversation/panel/submit-ladder.svelte.ts
|
|
32774
|
+
var SubmitLadder = class {
|
|
32775
|
+
deps;
|
|
32776
|
+
/** True while the plain-send rung is in flight — the footer's sending flag. */
|
|
32777
|
+
submitted = false;
|
|
32778
|
+
/** Inline command feedback (role=status, auto-dismiss 5s) — the ONLY
|
|
32779
|
+
* command UI surface; the input has already cleared by intercept time.
|
|
32780
|
+
* The wire work lives in command-executor (Prompt Macro W1 1.2): the
|
|
32781
|
+
* /new create+swap, /permission route, and mention delivery are the
|
|
32782
|
+
* SAME bytes the typed path always sent — the panel now renders
|
|
32783
|
+
* outcomes only (banner kind from result.ok). */
|
|
32784
|
+
commandNote = null;
|
|
32785
|
+
commandNoteTimer;
|
|
32786
|
+
constructor(deps) {
|
|
32787
|
+
this.deps = deps;
|
|
32788
|
+
}
|
|
32789
|
+
/** Inline command feedback — every rung banners through here. */
|
|
32790
|
+
noteCommand(kind, text) {
|
|
32791
|
+
this.commandNote = {
|
|
32792
|
+
kind,
|
|
32793
|
+
text
|
|
32794
|
+
};
|
|
32795
|
+
if (this.commandNoteTimer !== void 0) clearTimeout(this.commandNoteTimer);
|
|
32796
|
+
this.commandNoteTimer = setTimeout(() => this.commandNote = null, 5e3);
|
|
32797
|
+
}
|
|
32798
|
+
async onsubmit(text, images) {
|
|
32799
|
+
if (isTypedRun(text)) {
|
|
32800
|
+
this.deps.startMacro({
|
|
32801
|
+
text,
|
|
32802
|
+
id: -1
|
|
32803
|
+
}, false);
|
|
32804
|
+
return true;
|
|
32805
|
+
}
|
|
32806
|
+
const command = parseCommand(text);
|
|
32807
|
+
if (command !== null) {
|
|
32808
|
+
let bannered = false;
|
|
32809
|
+
const result = await executeCommand(command, this.deps.ctx(), (ok, note) => {
|
|
32810
|
+
bannered = true;
|
|
32811
|
+
this.noteCommand(ok ? "ok" : "error", note);
|
|
32812
|
+
});
|
|
32813
|
+
if (!bannered && result.note !== void 0) this.noteCommand(result.ok ? "ok" : "error", result.note);
|
|
32814
|
+
return true;
|
|
32815
|
+
}
|
|
32816
|
+
if (text.trim().length === 0 && images.length === 0) return false;
|
|
32817
|
+
const slashCatalog = this.deps.slashCatalog;
|
|
32818
|
+
if (slashCatalog?.state === "ready") {
|
|
32819
|
+
if (resolveHostCommand(text, slashCatalog.commands) !== null) return (await executeHostCommand(text, this.deps.ctx(), (ok, note) => this.noteCommand(ok ? "ok" : "error", note))).ok;
|
|
32820
|
+
}
|
|
32821
|
+
this.submitted = true;
|
|
32822
|
+
try {
|
|
32823
|
+
return (await sendPrompt(text, this.deps.ctx(), (t) => this.deps.orchestrator.submit(t, images))).ok;
|
|
32824
|
+
} finally {
|
|
32825
|
+
this.submitted = false;
|
|
32826
|
+
}
|
|
32827
|
+
}
|
|
32828
|
+
async oncancel() {
|
|
32829
|
+
await this.deps.orchestrator.cancel();
|
|
32830
|
+
}
|
|
32831
|
+
/** Menu command pick: the SAME rung the ladder uses (one execution
|
|
32832
|
+
* surface, D2), banner notes through the shared note path; the
|
|
32833
|
+
* boolean admits the composer's draft clearing (BC-A3). */
|
|
32834
|
+
async onpickcommand(line) {
|
|
32835
|
+
return (await executeHostCommand(line, this.deps.ctx(), (ok, note) => this.noteCommand(ok ? "ok" : "error", note))).ok;
|
|
32836
|
+
}
|
|
32837
|
+
};
|
|
32838
|
+
//#endregion
|
|
32839
|
+
//#region src/lib/utils/auto-open-slots.ts
|
|
32840
|
+
/** The newest reasoning entry's id (wire order), else null — the
|
|
32841
|
+
* transient think target. Empty reasoning strings do not count (the
|
|
32842
|
+
* chip renders nothing to open). */
|
|
32843
|
+
function newestReasoningId(entries) {
|
|
32844
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
32845
|
+
const e = entries[i];
|
|
32846
|
+
if (e.kind === "assistant-message" && e.reasoning !== void 0 && e.reasoning !== "") return e.id;
|
|
32847
|
+
}
|
|
32848
|
+
return null;
|
|
32849
|
+
}
|
|
32850
|
+
/** Suppression-aware view of a raw target: null while the user kept THIS
|
|
32851
|
+
* id collapsed (a newer target id simply stops matching). */
|
|
32852
|
+
function suppressed(targetId, suppressedId) {
|
|
32853
|
+
return targetId !== null && suppressedId === targetId ? null : targetId;
|
|
32854
|
+
}
|
|
32855
|
+
//#endregion
|
|
32856
|
+
//#region src/lib/components/conversation/panel/popups.svelte.ts
|
|
32857
|
+
var Popups = class {
|
|
32858
|
+
/** Chip popup state (2026-08-22, OCI pattern): ONE open chip at a time —
|
|
32859
|
+
* the id of the expanded entry; detail renders AFTER the chip row.
|
|
32860
|
+
* Per-panel by construction (moved here with the block). */
|
|
32861
|
+
openChipId = null;
|
|
32862
|
+
/** Peek popup state (ToolPeekButton port, 2026-08-22): the run key whose
|
|
32863
|
+
* chip row has its list popup open — ONE at a time, and never while a
|
|
32864
|
+
* chip detail popup is open (OCI mutual-exclusion contract). */
|
|
32865
|
+
peekOpenRunKey = null;
|
|
32866
|
+
thinkSuppressedId = null;
|
|
32867
|
+
planSuppressedId = null;
|
|
32868
|
+
/** The newest todo_write entry's id, STICKY: adopted only while
|
|
32869
|
+
* streaming AND stuck (the detection window), then kept across newer
|
|
32870
|
+
* thinks, turn end, and scroll-away — the plan stays on screen until
|
|
32871
|
+
* a newer todo_write supersedes it or the user collapses it. */
|
|
32872
|
+
autoPlanIdRaw = null;
|
|
32873
|
+
deps;
|
|
32874
|
+
stopPlanEffect;
|
|
32875
|
+
constructor(deps) {
|
|
32876
|
+
this.deps = deps;
|
|
32877
|
+
this.stopPlanEffect = () => {};
|
|
32878
|
+
}
|
|
32879
|
+
destroy() {
|
|
32880
|
+
this.stopPlanEffect();
|
|
32881
|
+
}
|
|
32882
|
+
/** The newest reasoning entry's id (wire order) while streaming AND
|
|
32883
|
+
* stuck to the live end, else null — the transient think target. */
|
|
32884
|
+
get autoThinkTargetId() {
|
|
32885
|
+
if (!this.deps.store.isStreaming || !this.deps.stick) return null;
|
|
32886
|
+
return newestReasoningId(this.deps.store.renderEntries);
|
|
32887
|
+
}
|
|
32888
|
+
/** Suppression-aware think target: null while the user kept THIS think
|
|
32889
|
+
* collapsed (a newer think id simply stops matching). */
|
|
32890
|
+
get autoThinkId() {
|
|
32891
|
+
return suppressed(this.autoThinkTargetId, this.thinkSuppressedId);
|
|
32892
|
+
}
|
|
32893
|
+
/** Suppression-aware plan target (same id-tied rule as the think). */
|
|
32894
|
+
get autoPlanId() {
|
|
32895
|
+
return suppressed(this.autoPlanIdRaw, this.planSuppressedId);
|
|
32896
|
+
}
|
|
32897
|
+
toggleChip(id, autoOpen = false) {
|
|
32898
|
+
if (autoOpen) {
|
|
32899
|
+
if (id === this.autoPlanId) this.planSuppressedId = id;
|
|
32900
|
+
else if (this.autoThinkId !== null && id === `r:${this.autoThinkId}`) this.thinkSuppressedId = this.autoThinkId;
|
|
32901
|
+
return;
|
|
32902
|
+
}
|
|
32903
|
+
this.openChipId = this.openChipId === id ? null : id;
|
|
32904
|
+
this.peekOpenRunKey = null;
|
|
32905
|
+
}
|
|
32906
|
+
togglePeek(runKey) {
|
|
32907
|
+
this.peekOpenRunKey = this.peekOpenRunKey === runKey ? null : runKey;
|
|
32908
|
+
if (this.peekOpenRunKey !== null) this.openChipId = null;
|
|
32909
|
+
}
|
|
32910
|
+
};
|
|
32911
|
+
//#endregion
|
|
32912
|
+
//#region src/lib/components/conversation/panel/paging.svelte.ts
|
|
31996
32913
|
var Paging = class {
|
|
31997
32914
|
hasOlder = false;
|
|
31998
32915
|
loadingOlder = false;
|
|
@@ -33541,7 +34458,7 @@ function BrowserPanel($$renderer, $$props) {
|
|
|
33541
34458
|
tab: t,
|
|
33542
34459
|
disabled: switching});
|
|
33543
34460
|
}
|
|
33544
|
-
$$renderer.push(`<!--]--> <button type="button" class="shrink-0 rounded px-1.5 leading-none text-zinc-500 hover:bg-zinc-100 disabled:opacity-40"
|
|
34461
|
+
$$renderer.push(`<!--]--> <button type="button" class="shrink-0 rounded px-1.5 leading-none text-zinc-500 hover:bg-zinc-100 disabled:opacity-40"${attr("title", t(browsernewtab2))}${attr("aria-label", t(browsernewtab2))} data-testid="browser-tab-new"${attr("disabled", true, true)}>+</button></div>`);
|
|
33545
34462
|
} else $$renderer.push("<!--[-1-->");
|
|
33546
34463
|
$$renderer.push(`<!--]--> `);
|
|
33547
34464
|
BrowserContent($$renderer, {
|
|
@@ -34427,9 +35344,13 @@ function WorkspaceFileTabGroup($$renderer, $$props) {
|
|
|
34427
35344
|
//#region src/lib/components/workspace-file/WorkspaceFileToolbar.svelte
|
|
34428
35345
|
function WorkspaceFileToolbar($$renderer, $$props) {
|
|
34429
35346
|
$$renderer.component(($$renderer) => {
|
|
35347
|
+
/** The reload icon's feedback state — the CanvasCopyButton machine
|
|
35348
|
+
* (idle → busy spinner → done check → idle), mirrored per the 2026-10-27
|
|
35349
|
+
* UX-parity operator request: a click that shows nothing happening "sucks". */
|
|
35350
|
+
let reloadState = "idle";
|
|
34430
35351
|
let columnEl = null;
|
|
34431
|
-
let { dirty, saveState = "idle", stale = false, staleNote = "", hasTabs = false, tab = "preview", view = "edit", showToggle = false, diffDisabled = false, readonly = false, onviewchange, onsave, path } = $$props;
|
|
34432
|
-
$$renderer.push(`<div data-svelte="WorkspaceFileToolbar" class="file-toolbar svelte-1vsjf39"><span class="path svelte-1vsjf39"${attr("title", path)}>${escape_html(path)}</span> `);
|
|
35352
|
+
let { dirty, saveState = "idle", stale = false, staleNote = "", hasTabs = false, tab = "preview", view = "edit", showToggle = false, diffDisabled = false, readonly = false, onviewchange, onsave, onreload, path } = $$props;
|
|
35353
|
+
$$renderer.push(`<div data-svelte="WorkspaceFileToolbar" class="file-toolbar svelte-1vsjf39" data-testid="file-toolbar"><span class="path svelte-1vsjf39"${attr("title", path)}>${escape_html(path)}</span> `);
|
|
34433
35354
|
if (showToggle) {
|
|
34434
35355
|
$$renderer.push("<!--[0-->");
|
|
34435
35356
|
WorkspaceFileTabGroup($$renderer, {
|
|
@@ -34461,6 +35382,14 @@ function WorkspaceFileToolbar($$renderer, $$props) {
|
|
|
34461
35382
|
$$renderer.push("<!--[0-->");
|
|
34462
35383
|
$$renderer.push(`<div class="tabs svelte-1vsjf39" role="tablist"><button role="tab"${attr("aria-selected", tab === "preview")} data-testid="tab-preview"${attr_class("svelte-1vsjf39", void 0, { "active": tab === "preview" })}>${escape_html(t(workspacefilepreview2))}</button> <button role="tab"${attr("aria-selected", tab === "edit")} data-testid="tab-edit"${attr_class("svelte-1vsjf39", void 0, { "active": tab === "edit" })}>${escape_html(t(workspacefileedit2))}</button></div>`);
|
|
34463
35384
|
} else $$renderer.push("<!--[-1-->");
|
|
35385
|
+
$$renderer.push(`<!--]--> `);
|
|
35386
|
+
if (onreload) {
|
|
35387
|
+
$$renderer.push("<!--[0-->");
|
|
35388
|
+
$$renderer.push(`<button type="button" class="reload-btn svelte-1vsjf39" data-testid="file-reload"${attr("data-state", reloadState)}${attr("title", t(refresh))}${attr("aria-label", t(refresh))}>`);
|
|
35389
|
+
$$renderer.push("<!--[-1-->");
|
|
35390
|
+
Rotate_cw($$renderer, { size: 14 });
|
|
35391
|
+
$$renderer.push(`<!--]--></button>`);
|
|
35392
|
+
} else $$renderer.push("<!--[-1-->");
|
|
34464
35393
|
$$renderer.push(`<!--]--> <span class="copy-slot svelte-1vsjf39">`);
|
|
34465
35394
|
CanvasCopyButton($$renderer, {
|
|
34466
35395
|
container: columnEl,
|
|
@@ -34492,7 +35421,7 @@ function WorkspaceFile($$renderer, $$props) {
|
|
|
34492
35421
|
* old overflow:auto container made the hosts content-sized and the
|
|
34493
35422
|
* page-level scrollbar stole the height.
|
|
34494
35423
|
*/
|
|
34495
|
-
let { tab = void 0, dirty, fullPath, saveState, fileStale, staleNote, hasTabs, activeView, showToggle, diffDisabled, readonly, onViewChange, onSave, saveError, saveFailedNote, loadingNote, loadFailedNote, truncatedNote, newFileNote, phase, errorCode, title, isImage, bytesSrc, isHtml, text, isMarkdown, noHead, eof, editorHost = null, diffHost = null } = $$props;
|
|
35424
|
+
let { tab = void 0, dirty, fullPath, saveState, fileStale, staleNote, hasTabs, activeView, showToggle, diffDisabled, readonly, onViewChange, onSave, onReload, saveError, saveFailedNote, loadingNote, loadFailedNote, truncatedNote, newFileNote, phase, errorCode, title, isImage, bytesSrc, isHtml, text, isMarkdown, noHead, eof, editorHost = null, diffHost = null } = $$props;
|
|
34496
35425
|
let $$settled = true;
|
|
34497
35426
|
let $$inner_renderer;
|
|
34498
35427
|
function $$render_inner($$renderer) {
|
|
@@ -34510,6 +35439,7 @@ function WorkspaceFile($$renderer, $$props) {
|
|
|
34510
35439
|
readonly,
|
|
34511
35440
|
onviewchange: onViewChange,
|
|
34512
35441
|
onsave: onSave,
|
|
35442
|
+
onreload: onReload,
|
|
34513
35443
|
get tab() {
|
|
34514
35444
|
return tab;
|
|
34515
35445
|
},
|
|
@@ -34661,6 +35591,13 @@ function WorkspaceFilePanel($$renderer, $$props) {
|
|
|
34661
35591
|
const homeDir = marker > 0 ? dsi.slice(0, marker) : null;
|
|
34662
35592
|
return homeDir !== null && full.startsWith(homeDir + "/") ? "~" + full.slice(homeDir.length) : full;
|
|
34663
35593
|
});
|
|
35594
|
+
/** Silent external refetch (Index Pulse): when the buffer holds no
|
|
35595
|
+
* draft, the fetched text/baseline advance to the disk truth and the
|
|
35596
|
+
* editor follows; when a draft exists, the panel only raises the
|
|
35597
|
+
* visible stale note - a draft is never clobbered. */
|
|
35598
|
+
async function refreshFile() {
|
|
35599
|
+
if (isImage() || true) return;
|
|
35600
|
+
}
|
|
34664
35601
|
/** The DIRECT save (The File Eye ADR D4): POST the buffer to the
|
|
34665
35602
|
* gated write route; the written receipt advances the baseline so
|
|
34666
35603
|
* dirty clears — bytes on disk, not an agent's promise. */
|
|
@@ -34682,6 +35619,7 @@ function WorkspaceFilePanel($$renderer, $$props) {
|
|
|
34682
35619
|
readonly: false,
|
|
34683
35620
|
onViewChange: setView,
|
|
34684
35621
|
onSave: save,
|
|
35622
|
+
onReload: refreshFile,
|
|
34685
35623
|
saveError,
|
|
34686
35624
|
saveFailedNote: t(workspacefilesavefailed3),
|
|
34687
35625
|
loadingNote: t(workspaceexplorerloading2),
|
|
@@ -34925,8 +35863,10 @@ function WorkspaceExplorerPanel($$renderer, $$props) {
|
|
|
34925
35863
|
* the active file panel and cleared once it reports the highlight done. */
|
|
34926
35864
|
let lineTarget = null;
|
|
34927
35865
|
function startSplitDrag(event) {}
|
|
34928
|
-
|
|
34929
|
-
|
|
35866
|
+
/** The rendered tree lane: the settled px, or the narrow-lane default
|
|
35867
|
+
* before the first measurement. Percent lives only in treePct. */
|
|
35868
|
+
const treeBasis = derived(() => 280);
|
|
35869
|
+
$$renderer.push(`<div data-svelte="WorkspaceExplorerPanel" data-testid="workspace-explorer" class="split svelte-ldghfc"${attr_style(`--tree-basis: ${stringify(treeBasis())}px`)}>`);
|
|
34930
35870
|
WorkspaceExplorer($$renderer, {
|
|
34931
35871
|
activeFile,
|
|
34932
35872
|
root,
|
|
@@ -35078,740 +36018,218 @@ function PanelHeader($$renderer, $$props) {
|
|
|
35078
36018
|
class: "inline-flex h-[22px] w-[22px] shrink-0 items-center justify-center rounded transition-colors hover:bg-surface-hover"
|
|
35079
36019
|
});
|
|
35080
36020
|
} else $$renderer.push("<!--[-1-->");
|
|
35081
|
-
$$renderer.push(`<!--]--> `);
|
|
35082
|
-
if (onremove || lens) {
|
|
35083
|
-
$$renderer.push("<!--[0-->");
|
|
35084
|
-
PanelClose($$renderer, {
|
|
35085
|
-
sessionId,
|
|
35086
|
-
lens});
|
|
35087
|
-
} else $$renderer.push("<!--[-1-->");
|
|
35088
|
-
$$renderer.push(`<!--]--></span></div>`);
|
|
35089
|
-
});
|
|
35090
|
-
}
|
|
35091
|
-
//#endregion
|
|
35092
|
-
//#region src/lib/components/panels/PanelColumn.svelte
|
|
35093
|
-
function PanelColumn($$renderer, $$props) {
|
|
35094
|
-
$$renderer.component(($$renderer) => {
|
|
35095
|
-
/**
|
|
35096
|
-
* PanelColumn — one panel's fixed-width column shell (Panel Floor W3
|
|
35097
|
-
* task 3.2, ADR-0006): PanelHeader (floor chrome) + the conversation
|
|
35098
|
-
* body (ConversationPanel, keyed by sessionId INSIDE the route's each
|
|
35099
|
-
* — remount locality) + the 6px ResizeGutter after every panel.
|
|
35100
|
-
*
|
|
35101
|
-
* Presentational shell only: width and selection arrive as props
|
|
35102
|
-
* (bound up to the route); the body arrives as a snippet so the ROUTE
|
|
35103
|
-
* owns the {#key panel.sessionId} remount and the per-panel cold data.
|
|
35104
|
-
*
|
|
35105
|
-
* Width badge (2026-08-28): a `widthBadge` phase prop ('live' during
|
|
35106
|
-
* a gutter drag that moves this panel's width, 'fading' through the
|
|
35107
|
-
* 10s afterglow) floats the CURRENT width at the column's top right,
|
|
35108
|
-
* below the header's controls, pointer-transparent — the route owns
|
|
35109
|
-
* the membership rule (changed-from-snapshot) and the fade timer.
|
|
35110
|
-
*/
|
|
35111
|
-
let { panel, index, selected, widthBadge = null, copyValue, canMoveLeft = false, canMoveRight = false, onremove, children } = $$props;
|
|
35112
|
-
$$renderer.push(`<div data-svelte="PanelColumn"${attr_class("column svelte-1cuodug", void 0, { "selected": selected })} data-testid="panel-column"${attr("data-panel-id", panel.id)}${attr("data-session-id", panel.kind === "conversation" ? panel.sessionId : null)}${attr_style(`width: ${stringify(panel.width)}px; min-width: ${stringify(panel.width)}px; max-width: ${stringify(panel.width)}px;`)}>`);
|
|
35113
|
-
PanelHeader($$renderer, {
|
|
35114
|
-
panelId: panel.id,
|
|
35115
|
-
sessionId: panel.kind === "conversation" ? panel.sessionId : "",
|
|
35116
|
-
label: panelHeaderLabel(panel),
|
|
35117
|
-
copyValue: panel.kind === "workspace-explorer" ? panel.root : panel.kind === "workspace-file" ? copyValue : void 0,
|
|
35118
|
-
copyLabel: panel.kind === "workspace-explorer" ? t(workspaceexplorercopyworkspace3) : panel.kind === "workspace-file" ? t(workspacefilecopyfilename3) : void 0,
|
|
35119
|
-
labelTestId: panel.kind === "workspace-explorer" ? "explorer-title" : panel.kind === "workspace-file" ? "file-title" : void 0,
|
|
35120
|
-
selected,
|
|
35121
|
-
canMoveLeft,
|
|
35122
|
-
canMoveRight,
|
|
35123
|
-
onremove
|
|
35124
|
-
});
|
|
35125
|
-
$$renderer.push(`<!----> `);
|
|
35126
|
-
if (widthBadge !== null) {
|
|
35127
|
-
$$renderer.push("<!--[0-->");
|
|
35128
|
-
$$renderer.push(`<span${attr_class("width-badge svelte-1cuodug", void 0, { "fading": widthBadge === "fading" })} data-testid="panel-width-badge"${attr("data-badge-phase", widthBadge)} aria-hidden="true">${escape_html(Math.round(panel.width))}px</span>`);
|
|
35129
|
-
} else $$renderer.push("<!--[-1-->");
|
|
35130
|
-
$$renderer.push(`<!--]--> <div class="body svelte-1cuodug">`);
|
|
35131
|
-
children($$renderer);
|
|
35132
|
-
$$renderer.push(`<!----></div></div> `);
|
|
35133
|
-
ResizeGutter($$renderer, { index });
|
|
35134
|
-
$$renderer.push(`<!---->`);
|
|
35135
|
-
});
|
|
35136
|
-
}
|
|
35137
|
-
//#endregion
|
|
35138
|
-
//#region src/lib/components/panels/PanelLoupe.svelte
|
|
35139
|
-
function PanelLoupe($$renderer, $$props) {
|
|
35140
|
-
$$renderer.component(($$renderer) => {
|
|
35141
|
-
/**
|
|
35142
|
-
* PanelLoupe — the reading lens over one floor panel (The Panel Loupe
|
|
35143
|
-
* ADR D2/D5, 2026-09-04): a body-portaled modal dialog that renders
|
|
35144
|
-
* one panel's content at reading size while the floor keeps its
|
|
35145
|
-
* zoom. ANY kind lenses (The Loupe for Every Panel, 2026-09-08): the
|
|
35146
|
-
* route feeds the SAME body snippet the column renders (D7 — one
|
|
35147
|
-
* ladder, two sites) and the header rides the panel's label variant;
|
|
35148
|
-
* the loupe itself carries no conversation logic.
|
|
35149
|
-
*
|
|
35150
|
-
* Contract donor: ImageLightbox (2026-08-28) — the portal, the fixed
|
|
35151
|
-
* inset-0 z-[1000] layer, role="dialog" aria-modal, the mask's
|
|
35152
|
-
* mousedown close, Escape, the × control, focus to the × on open and
|
|
35153
|
-
* back to the opener on close. The portal is load-bearing: the floor
|
|
35154
|
-
* row carries transform: scale(), and a fixed backdrop inside a
|
|
35155
|
-
* transformed ancestor is trapped in that ancestor's box instead of
|
|
35156
|
-
* covering the viewport (ADR D2). The action is inlined here by
|
|
35157
|
-
* decision — the donor is cited, not modified or refactored.
|
|
35158
|
-
*
|
|
35159
|
-
* Lens flag (D8): setLensMode(true) during init, BEFORE children
|
|
35160
|
-
* render — every floor-verb control inside the body snippet reads the
|
|
35161
|
-
* flag at its own init and renders visible-disabled. Context follows
|
|
35162
|
-
* the component tree, so the flag reaches snippet content even after
|
|
35163
|
-
* the portal moves the DOM under document.body (asserted by the loupe
|
|
35164
|
-
* unit tests).
|
|
35165
|
-
*
|
|
35166
|
-
* The lens × and this header's copy-id are the loupe's live controls;
|
|
35167
|
-
* the header's move/close render visible-disabled (the floor verbs).
|
|
35168
|
-
* Openness is the route's session-local state — never persisted (D5).
|
|
35169
|
-
*/
|
|
35170
|
-
let { panelId, sessionId, label = void 0, children } = $$props;
|
|
35171
|
-
setLensMode(true);
|
|
35172
|
-
$$renderer.push(`<div data-svelte="PanelLoupe" class="fixed inset-0 z-[1000] grid place-items-center p-10" role="dialog" aria-modal="true"${attr("aria-label", t(panelloupe1))} data-testid="panel-loupe"${attr("data-panel-id", panelId)}${attr("data-session-id", sessionId)}><div class="absolute inset-0 bg-black/60" aria-hidden="true" data-testid="panel-loupe-mask"></div> <div class="relative" style="width: min(100vw - 4rem, 850px); height: min(95vh, calc(100vh - 5rem));" data-testid="panel-loupe-sheet"><div class="flex h-full w-full flex-col overflow-hidden rounded-xl shadow-2xl" style="background: var(--color-surface-primary, var(--color-surface-elevated));">`);
|
|
35173
|
-
PanelHeader($$renderer, {
|
|
35174
|
-
panelId,
|
|
35175
|
-
sessionId,
|
|
35176
|
-
label,
|
|
35177
|
-
lens: true
|
|
35178
|
-
});
|
|
35179
|
-
$$renderer.push(`<!----> <div class="flex min-h-0 flex-1 flex-col overflow-hidden">`);
|
|
35180
|
-
children($$renderer);
|
|
35181
|
-
$$renderer.push(`<!----></div></div> <button type="button"${attr("aria-label", t(closeloupe1))} data-testid="panel-loupe-close" class="absolute -top-3 -right-3 z-10 flex h-9 w-9 cursor-pointer items-center justify-center rounded-full border border-surface-border bg-surface-elevated text-lg leading-none text-text-primary shadow-md hover:bg-surface-hover">×</button></div></div>`);
|
|
35182
|
-
});
|
|
35183
|
-
}
|
|
35184
|
-
//#endregion
|
|
35185
|
-
//#region src/lib/components/panels/StickyColumnContainer.svelte
|
|
35186
|
-
function StickyColumnContainer($$renderer, $$props) {
|
|
35187
|
-
$$renderer.component(($$renderer) => {
|
|
35188
|
-
/**
|
|
35189
|
-
* StickyColumnContainer — a fixed-width LEADING column inside the zoom
|
|
35190
|
-
* row (OCI StickyColumnContainer port, 2026-08-26; hosts the embedded
|
|
35191
|
-
* AppSidebar the way OCI's hosts ControlRail).
|
|
35192
|
-
*
|
|
35193
|
-
* "Sticky" = the width is TRIPLE-LOCKED (width/min/max all the same
|
|
35194
|
-
* px), unlike panel columns whose widths live in [MIN, MAX]: the rail
|
|
35195
|
-
* never flexes when the row measures itself at max-content. The
|
|
35196
|
-
* column's background paints the full column height — the rail inside
|
|
35197
|
-
* fills it (align-items: stretch).
|
|
35198
|
-
*
|
|
35199
|
-
* The trailing ResizeGutter is included BY DEFAULT (OCI parity) but
|
|
35200
|
-
* only when panel columns actually follow (showGutter) — a rail alone
|
|
35201
|
-
* on the floor has nothing to resize against. The gutter is the
|
|
35202
|
-
* column's flex SIBLING (the rail's overflow must never clip its hit
|
|
35203
|
-
* area) and reports mousedown through onResizeStart — the page owns
|
|
35204
|
-
* the drag math and the single clamp (AppSidebar ownership split;
|
|
35205
|
-
* ControlBar.onresizeall precedent: layout chrome is a DIRECT child
|
|
35206
|
-
* of the route, so prop wiring here breaks no commitment).
|
|
35207
|
-
*/
|
|
35208
|
-
let { width, showGutter = true, children } = $$props;
|
|
35209
|
-
$$renderer.push(`<div data-svelte="StickyColumnContainer" class="rail-column svelte-s09nms" data-testid="sidebar-column"${attr_style(`width: ${stringify(width)}px; min-width: ${stringify(width)}px; max-width: ${stringify(width)}px;`)}>`);
|
|
35210
|
-
children($$renderer);
|
|
35211
|
-
$$renderer.push(`<!----></div> `);
|
|
35212
|
-
if (showGutter) {
|
|
35213
|
-
$$renderer.push("<!--[0-->");
|
|
35214
|
-
$$renderer.push(`<div data-svelte="StickyColumnContainer" class="rail-gutter svelte-s09nms" data-testid="sidebar-gutter" role="separator" aria-orientation="vertical"${attr("aria-label", t(resizesidebar1))}></div>`);
|
|
35215
|
-
} else $$renderer.push("<!--[-1-->");
|
|
35216
|
-
$$renderer.push(`<!--]-->`);
|
|
35217
|
-
});
|
|
35218
|
-
}
|
|
35219
|
-
//#endregion
|
|
35220
|
-
//#region src/lib/components/panels/EmptyFloor.svelte
|
|
35221
|
-
function EmptyFloor($$renderer, $$props) {
|
|
35222
|
-
$$renderer.component(($$renderer) => {
|
|
35223
|
-
$$renderer.push(`<div data-svelte="EmptyFloor" class="empty-floor svelte-z8g5d9" data-testid="workspace-empty"><p>${escape_html(t(noconversations1))}</p> <p class="hint svelte-z8g5d9">${escape_html(t(picksession1))}</p></div>`);
|
|
35224
|
-
});
|
|
35225
|
-
}
|
|
35226
|
-
//#endregion
|
|
35227
|
-
//#region src/lib/services/conversation/spine-feed.svelte.ts
|
|
35228
|
-
var spineFeed = {
|
|
35229
|
-
rows: [],
|
|
35230
|
-
presets: [],
|
|
35231
|
-
a2aRows: [],
|
|
35232
|
-
workspaces: []
|
|
35233
|
-
};
|
|
35234
|
-
//#endregion
|
|
35235
|
-
//#region src/lib/services/workspace/page-feeds.svelte.ts
|
|
35236
|
-
var PageFeeds = class {
|
|
35237
|
-
coldCache = {};
|
|
35238
|
-
coldInFlight = new SvelteSet();
|
|
35239
|
-
deadSessions = {};
|
|
35240
|
-
edgeCache = {};
|
|
35241
|
-
/** Seed-arrival prime: the seed panel mounts with full cold props on
|
|
35242
|
-
* paint one (SSR parity for the seed path). Load-time constant. */
|
|
35243
|
-
primeSeed(sessionId, cold) {
|
|
35244
|
-
this.coldCache = {
|
|
35245
|
-
...this.coldCache,
|
|
35246
|
-
[sessionId]: cold
|
|
35247
|
-
};
|
|
35248
|
-
}
|
|
35249
|
-
/** Record an ADD-time parent edge (the route's doAdd fork path). */
|
|
35250
|
-
rememberEdge(childSessionId, parentSessionId) {
|
|
35251
|
-
this.edgeCache = {
|
|
35252
|
-
...this.edgeCache,
|
|
35253
|
-
[childSessionId]: parentSessionId
|
|
35254
|
-
};
|
|
35255
|
-
}
|
|
35256
|
-
/** One dual fetch, registries kept honest (in-flight guard, dead
|
|
35257
|
-
* session card, loader clear in `finally`). The fetcher is injected:
|
|
35258
|
-
* the wire call stays the route's (`fetchCold` reads the host
|
|
35259
|
-
* config); the bookkeeping lives here. */
|
|
35260
|
-
async runCold(sessionId, fetchCold) {
|
|
35261
|
-
if (this.coldCache[sessionId] !== void 0 || this.coldInFlight.has(sessionId)) return;
|
|
35262
|
-
this.coldInFlight = new SvelteSet(this.coldInFlight).add(sessionId);
|
|
35263
|
-
try {
|
|
35264
|
-
const cold = await fetchCold(sessionId);
|
|
35265
|
-
if (cold !== null) this.coldCache = {
|
|
35266
|
-
...this.coldCache,
|
|
35267
|
-
[sessionId]: cold
|
|
35268
|
-
};
|
|
35269
|
-
else this.deadSessions = {
|
|
35270
|
-
...this.deadSessions,
|
|
35271
|
-
[sessionId]: `Session ${sessionId} not found on the DSH host. It may have been reaped.`
|
|
35272
|
-
};
|
|
35273
|
-
} finally {
|
|
35274
|
-
const next = new SvelteSet(this.coldInFlight);
|
|
35275
|
-
next.delete(sessionId);
|
|
35276
|
-
this.coldInFlight = next;
|
|
35277
|
-
}
|
|
35278
|
-
}
|
|
35279
|
-
/** The floor's two lifecycle feeds (call during component init —
|
|
35280
|
-
* `$effect` needs an owner):
|
|
35281
|
-
* - Prompt Sync hygiene (ADR "The Prompt Sync" D1/D6): a session
|
|
35282
|
-
* that left the floor holds no check and no snapshot; count 0
|
|
35283
|
-
* clears the broadcast. Conversation sessions only (D6).
|
|
35284
|
-
* - Spine feed lifecycle (W8): ref-counted single timer started on
|
|
35285
|
-
* mount, stopped on destroy; the a2a window rides the floor's
|
|
35286
|
-
* conversation senders (first sender per tick, never per panel).
|
|
35287
|
-
* Returns the spine subscription's cleanup. */
|
|
35288
|
-
installFeeds(getConversationSessionIds) {
|
|
35289
|
-
return () => {};
|
|
35290
|
-
}
|
|
35291
|
-
};
|
|
35292
|
-
var pageFeeds = new PageFeeds();
|
|
35293
|
-
/**
|
|
35294
|
-
* The open workspace explorer for a workspace ROOT — The Shared Tree ADR
|
|
35295
|
-
* (2026-09-17) D1's dedupe key: ONE explorer per ROOT across ALL sessions,
|
|
35296
|
-
* so a chip click on any session sharing the root FOCUSES instead of
|
|
35297
|
-
* adding (a duplicate is a bug, not a feature). The retired per-session
|
|
35298
|
-
* key ("two sessions sharing one workspace hold distinct explorers",
|
|
35299
|
-
* Workspace Explorer D4) produced N byte-identical trees for N sessions.
|
|
35300
|
-
*/
|
|
35301
|
-
function findWorkspaceExplorerPanel(panels, root) {
|
|
35302
|
-
return panels.find((p) => p.kind === "workspace-explorer" && p.root === root);
|
|
35303
|
-
}
|
|
35304
|
-
/**
|
|
35305
|
-
* The explorer's slot (The Shared Tree ADR 2026-09-17, D3): the FOCUSED
|
|
35306
|
-
* slot — the explorer is NOT a lineage child; a workspace tree has no
|
|
35307
|
-
* parent session, only an opener. The retired after-source rule
|
|
35308
|
-
* (Workspace Explorer D3, "Parent → explorer → file") interposed the
|
|
35309
|
-
* panel inside a conversation's family unit — the family clamp inside
|
|
35310
|
-
* focusedInsertionSlot still keeps any real family unsplit.
|
|
35311
|
-
*/
|
|
35312
|
-
function workspaceExplorerSlot(panels, selectedIndex, facts) {
|
|
35313
|
-
return focusedInsertionSlot(panels, selectedIndex, facts.parentOf);
|
|
35314
|
-
}
|
|
35315
|
-
/**
|
|
35316
|
-
* The glass FIRST slot under its opener (operator ruling 2026-10-24):
|
|
35317
|
-
* a summoned/spawned glass lands DIRECTLY below its opener - past the
|
|
35318
|
-
* opener document tail, BEFORE every adopted child - matching the
|
|
35319
|
-
* spine tree wire order -1 (the ghost always reads as the first
|
|
35320
|
-
* child). Supersedes the region-end placement for the glass only.
|
|
35321
|
-
*/
|
|
35322
|
-
function glassFirstSlot(panels, openedBy) {
|
|
35323
|
-
const openerIdx = panels.findIndex((p) => p.kind === "conversation" && p.sessionId === openedBy);
|
|
35324
|
-
if (openerIdx === -1) return panels.length;
|
|
35325
|
-
return docTailEnd(panels, openerIdx, openedBy) + 1;
|
|
35326
|
-
}
|
|
35327
|
-
/**
|
|
35328
|
-
* Insert-before-focused slot (operator spec, 2026-08-31): a fresh panel
|
|
35329
|
-
* lands at the FOCUSED panel's index — immediately before it — and takes
|
|
35330
|
-
* focus (the route selects it). 0 when nothing is focused (empty floor,
|
|
35331
|
-
* stale selection) — the old front-add stays the fallback. Math.max keeps
|
|
35332
|
-
* splice's negative-index semantics out of the no-selection case.
|
|
35333
|
-
*
|
|
35334
|
-
* Family clamp (lineage I2): a slot strictly inside a family would wedge
|
|
35335
|
-
* the newcomer between a spawner and its pinned child — unitOf/blockBounds,
|
|
35336
|
-
* the sidebar's familyRenderOrder, and the adoption slot walk all assume
|
|
35337
|
-
* families stay contiguous on the floor. When the focus is a family CHILD,
|
|
35338
|
-
* the slot climbs to the family head — the nearest non-splitting slot left
|
|
35339
|
-
* of the focus (parentOf only carries on-floor parents, so an orphan child
|
|
35340
|
-
* is a root here, its own unit). A lone panel or a family head keeps the
|
|
35341
|
-
* exact focus slot.
|
|
35342
|
-
*
|
|
35343
|
-
* Manager focus (ADR D6): no session, no family — the slot is the focus
|
|
35344
|
-
* itself.
|
|
35345
|
-
*
|
|
35346
|
-
* Workspace member focus (2026-09-10): the explorer/file pair is a family
|
|
35347
|
-
* unit in the SAME block math (blockBounds — the Loadinjected D3 walk-back
|
|
35348
|
-
* grammar), so the clamp is the SAME one: insert at the unit head — the
|
|
35349
|
-
* PARENT position, left of the block — never between explorer and file.
|
|
35350
|
-
*/
|
|
35351
|
-
function focusedInsertionSlot(panels, selectedIndex, parentOf) {
|
|
35352
|
-
const focus = Math.max(0, selectedIndex);
|
|
35353
|
-
const focused = panels[focus];
|
|
35354
|
-
if (focused === void 0) return 0;
|
|
35355
|
-
if (focused.kind === "workspace-explorer" || focused.kind === "workspace-file" || focused.kind === "browser") {
|
|
35356
|
-
const block = blockBounds(panels, focus, { parentOf });
|
|
35357
|
-
return block === null ? focus : block[0];
|
|
35358
|
-
}
|
|
35359
|
-
if (focused.kind !== "conversation") return focus;
|
|
35360
|
-
let head = focused.sessionId;
|
|
35361
|
-
for (;;) {
|
|
35362
|
-
const parent = parentOf.get(head) ?? null;
|
|
35363
|
-
if (parent === null) break;
|
|
35364
|
-
head = parent;
|
|
35365
|
-
}
|
|
35366
|
-
if (head === focused.sessionId) return focus;
|
|
35367
|
-
const headIndex = panels.findIndex((p) => p.kind === "conversation" && p.sessionId === head);
|
|
35368
|
-
return headIndex >= 0 ? Math.min(headIndex, focus) : focus;
|
|
35369
|
-
}
|
|
35370
|
-
//#endregion
|
|
35371
|
-
//#region src/lib/services/panels/floor-registry/chrome.ts
|
|
35372
|
-
/**
|
|
35373
|
-
* floor-registry/chrome — panel chrome intents + explorer + file-intent
|
|
35374
|
-
* mailbox + removal (ADR-0022 W3).
|
|
35375
|
-
*
|
|
35376
|
-
* Moved WHOLE from the state home (floor-registry.svelte.ts): the
|
|
35377
|
-
* skill-shelf / plugin-rack chrome setters, the ONE-explorer-per-workspace
|
|
35378
|
-
* open grammar, the explorer tree/tab/git intents, the file-intent
|
|
35379
|
-
* publish/consume mailbox, and family-close removal. Plain module: every
|
|
35380
|
-
* write goes through the state home's reactive `st` hub and its
|
|
35381
|
-
* primitives (ADR-0019 D2: exactly ONE writer home for floor state).
|
|
35382
|
-
* Sibling rule: factories/slots are reached through the state home's
|
|
35383
|
-
* re-export hub, never by importing another sibling directly.
|
|
35384
|
-
*/
|
|
35385
|
-
var d$4 = floorSeam;
|
|
35386
|
-
/** Chip click action: ONE explorer per WORKSPACE root across ALL
|
|
35387
|
-
* sessions — a click on any session sharing the root FOCUSES the open
|
|
35388
|
-
* explorer (dedupe key = root, D1); a fresh root lands at the focused
|
|
35389
|
-
* slot (D3, non-lineage — the explorer is not a lineage child).
|
|
35390
|
-
* sessionId rides the fresh panel as PROVENANCE (D4), never identity. */
|
|
35391
|
-
function openWorkspaceExplorer(sessionId, workspace) {
|
|
35392
|
-
const open = findWorkspaceExplorerPanel(st.panels, workspace);
|
|
35393
|
-
if (open) {
|
|
35394
|
-
st.selectedPanelId = open.id;
|
|
35395
|
-
return;
|
|
35396
|
-
}
|
|
35397
|
-
insertPanel(makeWorkspaceExplorerPanel(sessionId, workspace), workspaceExplorerSlot(st.panels, selectedIndex_(), d$4().getMoveFacts()));
|
|
35398
|
-
}
|
|
35399
|
-
/** Chip click action (The Glass Browser spec W2, ADR-0029 D4): ONE live
|
|
35400
|
-
* browser panel across the floor — the terminal singleton rule (Terminal
|
|
35401
|
-
* Desk ADR D2). A click on an open browser FOCUSES it; a miss inserts at
|
|
35402
|
-
* the focused slot. */
|
|
35403
|
-
function openBrowserPanel(index, keepSelection = false, width, openedBy, sessionId) {
|
|
35404
|
-
const open = st.panels.find((p) => p.kind === "browser" && p.openedBy === openedBy);
|
|
35405
|
-
if (open) {
|
|
35406
|
-
st.selectedPanelId = open.id;
|
|
35407
|
-
return;
|
|
35408
|
-
}
|
|
35409
|
-
const prevSelected = st.selectedPanelId;
|
|
35410
|
-
const slot = index !== void 0 ? Math.max(0, Math.min(index, st.panels.length)) : openedBy !== void 0 ? glassFirstSlot(st.panels, openedBy) : insertionSlot();
|
|
35411
|
-
insertPanel(makeBrowserPanel(width, openedBy, sessionId), slot);
|
|
35412
|
-
if (keepSelection && prevSelected !== null && prevSelected !== void 0) {
|
|
35413
|
-
if (st.panels.some((p) => p.id === prevSelected)) st.selectedPanelId = prevSelected;
|
|
35414
|
-
}
|
|
35415
|
-
}
|
|
35416
|
-
/** The open explorer for a session's workspace (The Shared Tree D1):
|
|
35417
|
-
* matched by ROOT across sessions — the panel's provenance sessionId
|
|
35418
|
-
* is not the key. */
|
|
35419
|
-
function sessionWorkspaceExplorer(sessionId) {
|
|
35420
|
-
const root = d$4().getWorkspaceFor(sessionId);
|
|
35421
|
-
return root === null ? void 0 : findWorkspaceExplorerPanel(st.panels, root);
|
|
35422
|
-
}
|
|
35423
|
-
/** Explorer tree intents: the panel emits toggle/open-file; the owner
|
|
35424
|
-
* mutates expanded (the persisted part) — the levels cache stays
|
|
35425
|
-
* component-local. */
|
|
35426
|
-
function toggleExplorerPath(panelId, path) {
|
|
35427
|
-
const idx = st.panels.findIndex((p) => p.id === panelId);
|
|
35428
|
-
if (idx < 0 || st.panels[idx].kind !== "workspace-explorer") return;
|
|
35429
|
-
const explorer = st.panels[idx];
|
|
35430
|
-
const next = explorer.expanded.includes(path) ? explorer.expanded.filter((p) => p !== path) : [...explorer.expanded, path];
|
|
35431
|
-
st.panels = st.panels.with(idx, {
|
|
35432
|
-
...explorer,
|
|
35433
|
-
expanded: next
|
|
35434
|
-
});
|
|
35435
|
-
}
|
|
35436
|
-
/** Explorer collapse-all intent: the panel emits; the owner empties the
|
|
35437
|
-
* expanded list (the persisted part). */
|
|
35438
|
-
function collapseExplorerPaths(panelId) {
|
|
35439
|
-
const idx = st.panels.findIndex((p) => p.id === panelId);
|
|
35440
|
-
if (idx < 0 || st.panels[idx].kind !== "workspace-explorer") return;
|
|
35441
|
-
st.panels = st.panels.with(idx, {
|
|
35442
|
-
...st.panels[idx],
|
|
35443
|
-
expanded: []
|
|
35444
|
-
});
|
|
35445
|
-
}
|
|
35446
|
-
/** Git Eye tab intent (2026-09-12): the active tab is PERSISTED on the
|
|
35447
|
-
* entry — a hard reload restores it. */
|
|
35448
|
-
function setExplorerTab(panelId, tab) {
|
|
35449
|
-
const idx = st.panels.findIndex((p) => p.id === panelId);
|
|
35450
|
-
if (idx < 0 || st.panels[idx].kind !== "workspace-explorer") return;
|
|
35451
|
-
st.panels = st.panels.with(idx, {
|
|
35452
|
-
...st.panels[idx],
|
|
35453
|
-
tab
|
|
35454
|
-
});
|
|
35455
|
-
}
|
|
35456
|
-
/** Explorer Layout tabs (amendment 2026-09-16): the tab list and the
|
|
35457
|
-
* active tab are OWNER-PERSISTED entry facts. The file tabs die with
|
|
35458
|
-
* the panel (D5). */
|
|
35459
|
-
function openExplorerTab(panelId, path) {
|
|
35460
|
-
const idx = st.panels.findIndex((p) => p.id === panelId);
|
|
35461
|
-
if (idx < 0 || st.panels[idx].kind !== "workspace-explorer") return;
|
|
35462
|
-
const ex = st.panels[idx];
|
|
35463
|
-
const tabs = ex.openTabs ?? [];
|
|
35464
|
-
const openTabs = tabs.includes(path) ? tabs : [...tabs, path];
|
|
35465
|
-
st.panels = st.panels.with(idx, {
|
|
35466
|
-
...ex,
|
|
35467
|
-
openTabs,
|
|
35468
|
-
activeFile: path
|
|
35469
|
-
});
|
|
35470
|
-
}
|
|
35471
|
-
function closeExplorerTab(panelId, path) {
|
|
35472
|
-
const idx = st.panels.findIndex((p) => p.id === panelId);
|
|
35473
|
-
if (idx < 0 || st.panels[idx].kind !== "workspace-explorer") return;
|
|
35474
|
-
const ex = st.panels[idx];
|
|
35475
|
-
const tabs = ex.openTabs ?? [];
|
|
35476
|
-
const closedAt = tabs.indexOf(path);
|
|
35477
|
-
if (closedAt === -1) return;
|
|
35478
|
-
const openTabs = tabs.filter((p) => p !== path);
|
|
35479
|
-
const activeFile = ex.activeFile === path ? openTabs.length === 0 ? null : openTabs[Math.max(0, closedAt - 1)] : ex.activeFile ?? null;
|
|
35480
|
-
st.panels = st.panels.with(idx, {
|
|
35481
|
-
...ex,
|
|
35482
|
-
openTabs,
|
|
35483
|
-
activeFile
|
|
36021
|
+
$$renderer.push(`<!--]--> `);
|
|
36022
|
+
if (onremove || lens) {
|
|
36023
|
+
$$renderer.push("<!--[0-->");
|
|
36024
|
+
PanelClose($$renderer, {
|
|
36025
|
+
sessionId,
|
|
36026
|
+
lens});
|
|
36027
|
+
} else $$renderer.push("<!--[-1-->");
|
|
36028
|
+
$$renderer.push(`<!--]--></span></div>`);
|
|
35484
36029
|
});
|
|
35485
36030
|
}
|
|
35486
|
-
|
|
35487
|
-
|
|
35488
|
-
|
|
35489
|
-
|
|
35490
|
-
|
|
35491
|
-
|
|
35492
|
-
|
|
35493
|
-
|
|
36031
|
+
//#endregion
|
|
36032
|
+
//#region src/lib/components/panels/PanelColumn.svelte
|
|
36033
|
+
function PanelColumn($$renderer, $$props) {
|
|
36034
|
+
$$renderer.component(($$renderer) => {
|
|
36035
|
+
/**
|
|
36036
|
+
* PanelColumn — one panel's fixed-width column shell (Panel Floor W3
|
|
36037
|
+
* task 3.2, ADR-0006): PanelHeader (floor chrome) + the conversation
|
|
36038
|
+
* body (ConversationPanel, keyed by sessionId INSIDE the route's each
|
|
36039
|
+
* — remount locality) + the 6px ResizeGutter after every panel.
|
|
36040
|
+
*
|
|
36041
|
+
* Presentational shell only: width and selection arrive as props
|
|
36042
|
+
* (bound up to the route); the body arrives as a snippet so the ROUTE
|
|
36043
|
+
* owns the {#key panel.sessionId} remount and the per-panel cold data.
|
|
36044
|
+
*
|
|
36045
|
+
* Width badge (2026-08-28): a `widthBadge` phase prop ('live' during
|
|
36046
|
+
* a gutter drag that moves this panel's width, 'fading' through the
|
|
36047
|
+
* 10s afterglow) floats the CURRENT width at the column's top right,
|
|
36048
|
+
* below the header's controls, pointer-transparent — the route owns
|
|
36049
|
+
* the membership rule (changed-from-snapshot) and the fade timer.
|
|
36050
|
+
*/
|
|
36051
|
+
let { panel, index, selected, widthBadge = null, copyValue, canMoveLeft = false, canMoveRight = false, onremove, children } = $$props;
|
|
36052
|
+
$$renderer.push(`<div data-svelte="PanelColumn"${attr_class("column svelte-1cuodug", void 0, { "selected": selected })} data-testid="panel-column"${attr("data-panel-id", panel.id)}${attr("data-session-id", panel.kind === "conversation" ? panel.sessionId : null)}${attr_style(`width: ${stringify(panel.width)}px; min-width: ${stringify(panel.width)}px; max-width: ${stringify(panel.width)}px;`)}>`);
|
|
36053
|
+
PanelHeader($$renderer, {
|
|
36054
|
+
panelId: panel.id,
|
|
36055
|
+
sessionId: panel.kind === "conversation" ? panel.sessionId : "",
|
|
36056
|
+
label: panelHeaderLabel(panel),
|
|
36057
|
+
copyValue: panel.kind === "workspace-explorer" ? panel.root : panel.kind === "workspace-file" ? copyValue : void 0,
|
|
36058
|
+
copyLabel: panel.kind === "workspace-explorer" ? t(workspaceexplorercopyworkspace3) : panel.kind === "workspace-file" ? t(workspacefilecopyfilename3) : void 0,
|
|
36059
|
+
labelTestId: panel.kind === "workspace-explorer" ? "explorer-title" : panel.kind === "workspace-file" ? "file-title" : void 0,
|
|
36060
|
+
selected,
|
|
36061
|
+
canMoveLeft,
|
|
36062
|
+
canMoveRight,
|
|
36063
|
+
onremove
|
|
36064
|
+
});
|
|
36065
|
+
$$renderer.push(`<!----> `);
|
|
36066
|
+
if (widthBadge !== null) {
|
|
36067
|
+
$$renderer.push("<!--[0-->");
|
|
36068
|
+
$$renderer.push(`<span${attr_class("width-badge svelte-1cuodug", void 0, { "fading": widthBadge === "fading" })} data-testid="panel-width-badge"${attr("data-badge-phase", widthBadge)} aria-hidden="true">${escape_html(Math.round(panel.width))}px</span>`);
|
|
36069
|
+
} else $$renderer.push("<!--[-1-->");
|
|
36070
|
+
$$renderer.push(`<!--]--> <div class="body svelte-1cuodug">`);
|
|
36071
|
+
children($$renderer);
|
|
36072
|
+
$$renderer.push(`<!----></div></div> `);
|
|
36073
|
+
ResizeGutter($$renderer, { index });
|
|
36074
|
+
$$renderer.push(`<!---->`);
|
|
35494
36075
|
});
|
|
35495
36076
|
}
|
|
35496
|
-
|
|
35497
|
-
|
|
35498
|
-
|
|
35499
|
-
|
|
35500
|
-
|
|
35501
|
-
|
|
35502
|
-
|
|
35503
|
-
*
|
|
35504
|
-
|
|
35505
|
-
|
|
35506
|
-
|
|
35507
|
-
|
|
35508
|
-
|
|
35509
|
-
|
|
35510
|
-
|
|
35511
|
-
|
|
35512
|
-
|
|
36077
|
+
//#endregion
|
|
36078
|
+
//#region src/lib/components/panels/PanelLoupe.svelte
|
|
36079
|
+
function PanelLoupe($$renderer, $$props) {
|
|
36080
|
+
$$renderer.component(($$renderer) => {
|
|
36081
|
+
/**
|
|
36082
|
+
* PanelLoupe — the reading lens over one floor panel (The Panel Loupe
|
|
36083
|
+
* ADR D2/D5, 2026-09-04): a body-portaled modal dialog that renders
|
|
36084
|
+
* one panel's content at reading size while the floor keeps its
|
|
36085
|
+
* zoom. ANY kind lenses (The Loupe for Every Panel, 2026-09-08): the
|
|
36086
|
+
* route feeds the SAME body snippet the column renders (D7 — one
|
|
36087
|
+
* ladder, two sites) and the header rides the panel's label variant;
|
|
36088
|
+
* the loupe itself carries no conversation logic.
|
|
36089
|
+
*
|
|
36090
|
+
* Contract donor: ImageLightbox (2026-08-28) — the portal, the fixed
|
|
36091
|
+
* inset-0 z-[1000] layer, role="dialog" aria-modal, the mask's
|
|
36092
|
+
* mousedown close, Escape, the × control, focus to the × on open and
|
|
36093
|
+
* back to the opener on close. The portal is load-bearing: the floor
|
|
36094
|
+
* row carries transform: scale(), and a fixed backdrop inside a
|
|
36095
|
+
* transformed ancestor is trapped in that ancestor's box instead of
|
|
36096
|
+
* covering the viewport (ADR D2). The action is inlined here by
|
|
36097
|
+
* decision — the donor is cited, not modified or refactored.
|
|
36098
|
+
*
|
|
36099
|
+
* Lens flag (D8): setLensMode(true) during init, BEFORE children
|
|
36100
|
+
* render — every floor-verb control inside the body snippet reads the
|
|
36101
|
+
* flag at its own init and renders visible-disabled. Context follows
|
|
36102
|
+
* the component tree, so the flag reaches snippet content even after
|
|
36103
|
+
* the portal moves the DOM under document.body (asserted by the loupe
|
|
36104
|
+
* unit tests).
|
|
36105
|
+
*
|
|
36106
|
+
* The lens × and this header's copy-id are the loupe's live controls;
|
|
36107
|
+
* the header's move/close render visible-disabled (the floor verbs).
|
|
36108
|
+
* Openness is the route's session-local state — never persisted (D5).
|
|
36109
|
+
*/
|
|
36110
|
+
let { panelId, sessionId, label = void 0, children } = $$props;
|
|
36111
|
+
setLensMode(true);
|
|
36112
|
+
$$renderer.push(`<div data-svelte="PanelLoupe" class="fixed inset-0 z-[1000] grid place-items-center p-10" role="dialog" aria-modal="true"${attr("aria-label", t(panelloupe1))} data-testid="panel-loupe"${attr("data-panel-id", panelId)}${attr("data-session-id", sessionId)}><div class="absolute inset-0 bg-black/60" aria-hidden="true" data-testid="panel-loupe-mask"></div> <div class="relative" style="width: min(100vw - 4rem, 850px); height: min(95vh, calc(100vh - 5rem));" data-testid="panel-loupe-sheet"><div class="flex h-full w-full flex-col overflow-hidden rounded-xl shadow-2xl" style="background: var(--color-surface-primary, var(--color-surface-elevated));">`);
|
|
36113
|
+
PanelHeader($$renderer, {
|
|
36114
|
+
panelId,
|
|
36115
|
+
sessionId,
|
|
36116
|
+
label,
|
|
36117
|
+
lens: true
|
|
36118
|
+
});
|
|
36119
|
+
$$renderer.push(`<!----> <div class="flex min-h-0 flex-1 flex-col overflow-hidden">`);
|
|
36120
|
+
children($$renderer);
|
|
36121
|
+
$$renderer.push(`<!----></div></div> <button type="button"${attr("aria-label", t(closeloupe1))} data-testid="panel-loupe-close" class="absolute -top-3 -right-3 z-10 flex h-9 w-9 cursor-pointer items-center justify-center rounded-full border border-surface-border bg-surface-elevated text-lg leading-none text-text-primary shadow-md hover:bg-surface-hover">×</button></div></div>`);
|
|
35513
36122
|
});
|
|
35514
36123
|
}
|
|
35515
|
-
|
|
35516
|
-
|
|
35517
|
-
function
|
|
35518
|
-
|
|
35519
|
-
|
|
35520
|
-
|
|
35521
|
-
|
|
35522
|
-
|
|
35523
|
-
|
|
35524
|
-
|
|
35525
|
-
|
|
36124
|
+
//#endregion
|
|
36125
|
+
//#region src/lib/components/panels/StickyColumnContainer.svelte
|
|
36126
|
+
function StickyColumnContainer($$renderer, $$props) {
|
|
36127
|
+
$$renderer.component(($$renderer) => {
|
|
36128
|
+
/**
|
|
36129
|
+
* StickyColumnContainer — a fixed-width LEADING column inside the zoom
|
|
36130
|
+
* row (OCI StickyColumnContainer port, 2026-08-26; hosts the embedded
|
|
36131
|
+
* AppSidebar the way OCI's hosts ControlRail).
|
|
36132
|
+
*
|
|
36133
|
+
* "Sticky" = the width is TRIPLE-LOCKED (width/min/max all the same
|
|
36134
|
+
* px), unlike panel columns whose widths live in [MIN, MAX]: the rail
|
|
36135
|
+
* never flexes when the row measures itself at max-content. The
|
|
36136
|
+
* column's background paints the full column height — the rail inside
|
|
36137
|
+
* fills it (align-items: stretch).
|
|
36138
|
+
*
|
|
36139
|
+
* The trailing ResizeGutter is included BY DEFAULT (OCI parity) but
|
|
36140
|
+
* only when panel columns actually follow (showGutter) — a rail alone
|
|
36141
|
+
* on the floor has nothing to resize against. The gutter is the
|
|
36142
|
+
* column's flex SIBLING (the rail's overflow must never clip its hit
|
|
36143
|
+
* area) and reports mousedown through onResizeStart — the page owns
|
|
36144
|
+
* the drag math and the single clamp (AppSidebar ownership split;
|
|
36145
|
+
* ControlBar.onresizeall precedent: layout chrome is a DIRECT child
|
|
36146
|
+
* of the route, so prop wiring here breaks no commitment).
|
|
36147
|
+
*/
|
|
36148
|
+
let { width, showGutter = true, children } = $$props;
|
|
36149
|
+
$$renderer.push(`<div data-svelte="StickyColumnContainer" class="rail-column svelte-s09nms" data-testid="sidebar-column"${attr_style(`width: ${stringify(width)}px; min-width: ${stringify(width)}px; max-width: ${stringify(width)}px;`)}>`);
|
|
36150
|
+
children($$renderer);
|
|
36151
|
+
$$renderer.push(`<!----></div> `);
|
|
36152
|
+
if (showGutter) {
|
|
36153
|
+
$$renderer.push("<!--[0-->");
|
|
36154
|
+
$$renderer.push(`<div data-svelte="StickyColumnContainer" class="rail-gutter svelte-s09nms" data-testid="sidebar-gutter" role="separator" aria-orientation="vertical"${attr("aria-label", t(resizesidebar1))}></div>`);
|
|
36155
|
+
} else $$renderer.push("<!--[-1-->");
|
|
36156
|
+
$$renderer.push(`<!--]-->`);
|
|
35526
36157
|
});
|
|
35527
36158
|
}
|
|
35528
|
-
|
|
35529
|
-
|
|
35530
|
-
function
|
|
35531
|
-
|
|
35532
|
-
|
|
35533
|
-
st.panels = st.panels.with(idx, {
|
|
35534
|
-
...st.panels[idx],
|
|
35535
|
-
view
|
|
36159
|
+
//#endregion
|
|
36160
|
+
//#region src/lib/components/panels/EmptyFloor.svelte
|
|
36161
|
+
function EmptyFloor($$renderer, $$props) {
|
|
36162
|
+
$$renderer.component(($$renderer) => {
|
|
36163
|
+
$$renderer.push(`<div data-svelte="EmptyFloor" class="empty-floor svelte-z8g5d9" data-testid="workspace-empty"><p>${escape_html(t(noconversations1))}</p> <p class="hint svelte-z8g5d9">${escape_html(t(picksession1))}</p></div>`);
|
|
35536
36164
|
});
|
|
35537
36165
|
}
|
|
35538
|
-
/** Tree file-click action (The Settings Tree ADR 2026-09-18 D1): the
|
|
35539
|
-
* intent publishes to the session's explorer, which opens/focuses a
|
|
35540
|
-
* tab. No open explorer ⇒ the intent drops. */
|
|
35541
|
-
function openWorkspaceFile(sessionId, path, lines) {
|
|
35542
|
-
const host = sessionWorkspaceExplorer(sessionId);
|
|
35543
|
-
if (host) publishFileIntent(host.id, path, lines);
|
|
35544
|
-
}
|
|
35545
|
-
/** Publish a file intent to an explorer panel and focus it. `lines` is
|
|
35546
|
-
* the optional #L anchor target — display metadata, not persisted. */
|
|
35547
|
-
function publishFileIntent(explorerId, path, lines) {
|
|
35548
|
-
st.pendingFileIntents[explorerId] = {
|
|
35549
|
-
path,
|
|
35550
|
-
nonce: ++st.fileIntentSeq,
|
|
35551
|
-
lines: lines ?? null
|
|
35552
|
-
};
|
|
35553
|
-
st.selectedPanelId = explorerId;
|
|
35554
|
-
}
|
|
35555
|
-
/** The panel consumed intent nonce N — clear exactly that publish. */
|
|
35556
|
-
function consumeFileIntent(explorerId, nonce) {
|
|
35557
|
-
if (st.pendingFileIntents[explorerId]?.nonce === nonce) st.pendingFileIntents[explorerId] = null;
|
|
35558
|
-
}
|
|
35559
|
-
/** Remove a panel; family close walks the wire lineage transitively
|
|
35560
|
-
* (every descendant sub-agent goes with it, nested included). The
|
|
35561
|
-
* Shift+Click amendment (2026-09-01): family === false opts OUT — only
|
|
35562
|
-
* THAT panel drops, the children re-root as orphan family heads.
|
|
35563
|
-
*
|
|
35564
|
-
* The session's workspace pair closes with it (2026-09-10); closing an
|
|
35565
|
-
* EXPLORER dooms its file children BY PANEL ID — the stored
|
|
35566
|
-
* explorerPanelId edge, with the legacy null-edge fallback. A
|
|
35567
|
-
* settings-home explorer (sessionId null) dies with the close. */
|
|
35568
|
-
function removePanel(panelId, opts = {}) {
|
|
35569
|
-
const idx = st.panels.findIndex((p) => p.id === panelId);
|
|
35570
|
-
if (idx < 0) return;
|
|
35571
|
-
const root = st.panels[idx];
|
|
35572
|
-
const rootSessionId = root.kind === "conversation" ? root.sessionId : null;
|
|
35573
|
-
const doomed = new SvelteSet(rootSessionId !== null ? [rootSessionId] : []);
|
|
35574
|
-
if (opts.family !== false && rootSessionId !== null) {
|
|
35575
|
-
const stack = [rootSessionId];
|
|
35576
|
-
while (stack.length > 0) for (const kid of d$4().getLineageFacts().childrenByParent.get(stack.pop()) ?? []) if (!doomed.has(kid.sessionId)) {
|
|
35577
|
-
doomed.add(kid.sessionId);
|
|
35578
|
-
stack.push(kid.sessionId);
|
|
35579
|
-
}
|
|
35580
|
-
}
|
|
35581
|
-
const doomedPanelIds = new SvelteSet();
|
|
35582
|
-
if (opts.family !== false && rootSessionId !== null) {
|
|
35583
|
-
for (const p of st.panels) if (p.kind === "browser" && p.openedBy !== void 0 && doomed.has(p.openedBy)) doomedPanelIds.add(p.id);
|
|
35584
|
-
}
|
|
35585
|
-
if (opts.family !== false && root.kind === "workspace-explorer") {
|
|
35586
|
-
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);
|
|
35587
|
-
}
|
|
35588
|
-
st.panels = st.panels.filter((p) => p.id !== root.id && !doomedPanelIds.has(p.id) && (p.kind === "conversation" ? !doomed.has(p.sessionId) : !("sessionId" in p) || p.sessionId === null || opts.family !== false && !doomed.has(p.sessionId)));
|
|
35589
|
-
if (st.selectedPanelId !== null && !st.panels.some((p) => p.id === st.selectedPanelId)) st.selectedPanelId = st.panels[Math.min(idx, st.panels.length - 1)]?.id ?? null;
|
|
35590
|
-
clearLoupeIfGone();
|
|
35591
|
-
}
|
|
35592
36166
|
//#endregion
|
|
35593
|
-
//#region src/lib/services/
|
|
35594
|
-
var
|
|
35595
|
-
|
|
35596
|
-
|
|
35597
|
-
|
|
35598
|
-
|
|
35599
|
-
|
|
35600
|
-
|
|
35601
|
-
|
|
35602
|
-
|
|
35603
|
-
|
|
35604
|
-
|
|
35605
|
-
|
|
35606
|
-
}
|
|
35607
|
-
/**
|
|
35608
|
-
*
|
|
35609
|
-
|
|
35610
|
-
|
|
35611
|
-
|
|
35612
|
-
|
|
35613
|
-
|
|
35614
|
-
async function openFileLinkFromMarkdown(sessionId, rawHref) {
|
|
35615
|
-
const { path, lines } = parseFileLinkHref(rawHref);
|
|
35616
|
-
if (path === "") return;
|
|
35617
|
-
const target = await resolveFileLinkTarget(sessionId, path, d$2().getWorkspaceFor(sessionId), void 0, workspaceRootDirs);
|
|
35618
|
-
if (target === null) return;
|
|
35619
|
-
if (!sessionWorkspaceExplorer(sessionId)) {
|
|
35620
|
-
const root = d$2().getWorkspaceFor(sessionId);
|
|
35621
|
-
if (!root) return;
|
|
35622
|
-
openWorkspaceExplorer(sessionId, root);
|
|
36167
|
+
//#region src/lib/services/conversation/spine-feed.svelte.ts
|
|
36168
|
+
var spineFeed = {
|
|
36169
|
+
rows: [],
|
|
36170
|
+
presets: [],
|
|
36171
|
+
a2aRows: [],
|
|
36172
|
+
workspaces: []
|
|
36173
|
+
};
|
|
36174
|
+
//#endregion
|
|
36175
|
+
//#region src/lib/services/workspace/page-feeds.svelte.ts
|
|
36176
|
+
var PageFeeds = class {
|
|
36177
|
+
coldCache = {};
|
|
36178
|
+
coldInFlight = new SvelteSet();
|
|
36179
|
+
deadSessions = {};
|
|
36180
|
+
edgeCache = {};
|
|
36181
|
+
/** Seed-arrival prime: the seed panel mounts with full cold props on
|
|
36182
|
+
* paint one (SSR parity for the seed path). Load-time constant. */
|
|
36183
|
+
primeSeed(sessionId, cold) {
|
|
36184
|
+
this.coldCache = {
|
|
36185
|
+
...this.coldCache,
|
|
36186
|
+
[sessionId]: cold
|
|
36187
|
+
};
|
|
35623
36188
|
}
|
|
35624
|
-
|
|
35625
|
-
|
|
35626
|
-
|
|
35627
|
-
|
|
35628
|
-
|
|
35629
|
-
|
|
35630
|
-
* from the route — a pure wire read over the global fetch. */
|
|
35631
|
-
async function fetchColdFromWire(sessionId) {
|
|
35632
|
-
const eventsRes = await fetch(`/api/dsh/session/${encodeURIComponent(sessionId)}/events?full=1`);
|
|
35633
|
-
if (!eventsRes.ok) return null;
|
|
35634
|
-
const events = await eventsRes.json();
|
|
35635
|
-
if (!events.ok) return null;
|
|
35636
|
-
const lastSeq = events.lastSeq ?? -1;
|
|
35637
|
-
let hasMore = false;
|
|
35638
|
-
const historyRes = await fetch(`/api/dsh/session/${encodeURIComponent(sessionId)}/history?beforeSeq=${lastSeq + 1}`);
|
|
35639
|
-
if (historyRes.ok) {
|
|
35640
|
-
const history = await historyRes.json();
|
|
35641
|
-
if (history.ok) hasMore = (history.entries?.length ?? 0) > 0 || history.hasMore === true;
|
|
36189
|
+
/** Record an ADD-time parent edge (the route's doAdd fork path). */
|
|
36190
|
+
rememberEdge(childSessionId, parentSessionId) {
|
|
36191
|
+
this.edgeCache = {
|
|
36192
|
+
...this.edgeCache,
|
|
36193
|
+
[childSessionId]: parentSessionId
|
|
36194
|
+
};
|
|
35642
36195
|
}
|
|
35643
|
-
|
|
35644
|
-
|
|
35645
|
-
|
|
35646
|
-
|
|
35647
|
-
|
|
35648
|
-
|
|
35649
|
-
|
|
35650
|
-
|
|
35651
|
-
|
|
35652
|
-
|
|
35653
|
-
|
|
35654
|
-
|
|
35655
|
-
|
|
35656
|
-
|
|
35657
|
-
|
|
35658
|
-
}
|
|
35659
|
-
|
|
35660
|
-
|
|
35661
|
-
|
|
35662
|
-
|
|
35663
|
-
|
|
35664
|
-
|
|
35665
|
-
* make* panel factories and the slot grammar (insertPanel, insertionSlot,
|
|
35666
|
-
* pinnedSlotIndex). Plain module: no runes here — every write goes through
|
|
35667
|
-
* the state home's reactive `st` hub and its primitives (ADR-0019 D2:
|
|
35668
|
-
* exactly ONE writer home for floor state). Sibling rule: this file never
|
|
35669
|
-
* imports another sibling; shared needs come from the state home.
|
|
35670
|
-
*/
|
|
35671
|
-
var d$1 = floorSeam;
|
|
35672
|
-
function makePanel(sessionId, agentPreset) {
|
|
35673
|
-
return {
|
|
35674
|
-
id: nextPanelId(),
|
|
35675
|
-
kind: "conversation",
|
|
35676
|
-
sessionId,
|
|
35677
|
-
agentPreset,
|
|
35678
|
-
width: clampPanelWidth(d$1().getPanelWidth())
|
|
35679
|
-
};
|
|
35680
|
-
}
|
|
35681
|
-
/** width: the reload-restored panel re-mints at the width the operator
|
|
35682
|
-
* dragged before (browser-slot persistence, RCA 2026-10-22); absent for
|
|
35683
|
-
* chip clicks and legacy slots — the honest-slider preset.
|
|
35684
|
-
* openedBy: the opener session's provenance, recorded ONCE at spawn and
|
|
35685
|
-
* never rewritten (ADR-0036 D1/D2); undefined = no conversation context. */
|
|
35686
|
-
function makeBrowserPanel(width, openedBy, sessionId) {
|
|
35687
|
-
return {
|
|
35688
|
-
id: nextPanelId(),
|
|
35689
|
-
kind: "browser",
|
|
35690
|
-
width: clampPanelWidth(width ?? d$1().getPanelWidth()),
|
|
35691
|
-
...openedBy !== void 0 ? { openedBy } : {},
|
|
35692
|
-
...sessionId !== void 0 ? { browserSessionId: sessionId } : {}
|
|
35693
|
-
};
|
|
35694
|
-
}
|
|
35695
|
-
function makeWorkspaceExplorerPanel(sessionId, root) {
|
|
35696
|
-
return {
|
|
35697
|
-
id: nextPanelId(),
|
|
35698
|
-
kind: "workspace-explorer",
|
|
35699
|
-
sessionId,
|
|
35700
|
-
root,
|
|
35701
|
-
expanded: [],
|
|
35702
|
-
width: clampPanelWidth(850, "workspace-explorer")
|
|
35703
|
-
};
|
|
35704
|
-
}
|
|
35705
|
-
function insertPanel(entry, index) {
|
|
35706
|
-
const next = [...st.panels];
|
|
35707
|
-
next.splice(Math.min(index, next.length), 0, entry);
|
|
35708
|
-
st.panels = next;
|
|
35709
|
-
st.selectedPanelId = entry.id;
|
|
35710
|
-
}
|
|
35711
|
-
function insertionSlot() {
|
|
35712
|
-
return focusedInsertionSlot(st.panels, selectedIndex_(), d$1().getMoveFacts().parentOf);
|
|
35713
|
-
}
|
|
35714
|
-
//#endregion
|
|
35715
|
-
//#region src/lib/services/panels/floor-registry.svelte.ts
|
|
35716
|
-
var deps = null;
|
|
35717
|
-
function configureFloorRegistry(d0) {
|
|
35718
|
-
deps = d0;
|
|
35719
|
-
}
|
|
35720
|
-
function d() {
|
|
35721
|
-
if (deps === null) throw new Error("floor-registry: configureFloorRegistry() was never called");
|
|
35722
|
-
return deps;
|
|
35723
|
-
}
|
|
35724
|
-
/** Sibling-module access to the dep seam (ADR-0022 W2): the ONE outside-reads
|
|
35725
|
-
* channel; siblings never open their own config channel. */
|
|
35726
|
-
function floorSeam() {
|
|
35727
|
-
return d();
|
|
35728
|
-
}
|
|
35729
|
-
var st = {
|
|
35730
|
-
panels: [],
|
|
35731
|
-
selectedPanelId: null,
|
|
35732
|
-
loupePanelId: null,
|
|
35733
|
-
focusComposerId: null,
|
|
35734
|
-
panelIdSeq: 0,
|
|
35735
|
-
terminalDeskMirrors: {},
|
|
35736
|
-
pendingFileIntents: {},
|
|
35737
|
-
fileIntentSeq: 0,
|
|
35738
|
-
drag: null,
|
|
35739
|
-
widthBadgeFading: false
|
|
35740
|
-
};
|
|
35741
|
-
/** Non-reactive gesture refs (drag start index, fade timer, badge ids) —
|
|
35742
|
-
* written by floor-registry/drag.svelte.ts; the ids set is a live
|
|
35743
|
-
* SvelteSet so badge visibility stays reactive. */
|
|
35744
|
-
var dragRefs = {
|
|
35745
|
-
ids: new SvelteSet()
|
|
35746
|
-
};
|
|
35747
|
-
var floor = {
|
|
35748
|
-
get panels() {
|
|
35749
|
-
return st.panels;
|
|
35750
|
-
},
|
|
35751
|
-
get selectedPanelId() {
|
|
35752
|
-
return st.selectedPanelId;
|
|
35753
|
-
},
|
|
35754
|
-
get loupePanelId() {
|
|
35755
|
-
return st.loupePanelId;
|
|
35756
|
-
},
|
|
35757
|
-
get focusComposerId() {
|
|
35758
|
-
return st.focusComposerId;
|
|
35759
|
-
},
|
|
35760
|
-
get terminalDeskMirrors() {
|
|
35761
|
-
return st.terminalDeskMirrors;
|
|
35762
|
-
},
|
|
35763
|
-
get pendingFileIntents() {
|
|
35764
|
-
return st.pendingFileIntents;
|
|
35765
|
-
},
|
|
35766
|
-
get drag() {
|
|
35767
|
-
return st.drag;
|
|
35768
|
-
},
|
|
35769
|
-
get widthBadgeFading() {
|
|
35770
|
-
return st.widthBadgeFading;
|
|
35771
|
-
},
|
|
35772
|
-
get widthBadgeIds() {
|
|
35773
|
-
return dragRefs.ids;
|
|
35774
|
-
},
|
|
35775
|
-
get selected() {
|
|
35776
|
-
return st.panels.find((p) => p.id === st.selectedPanelId) ?? null;
|
|
35777
|
-
},
|
|
35778
|
-
get loupePanel() {
|
|
35779
|
-
return st.panels.find((p) => p.id === st.loupePanelId) ?? null;
|
|
36196
|
+
/** One dual fetch, registries kept honest (in-flight guard, dead
|
|
36197
|
+
* session card, loader clear in `finally`). The fetcher is injected:
|
|
36198
|
+
* the wire call stays the route's (`fetchCold` reads the host
|
|
36199
|
+
* config); the bookkeeping lives here. */
|
|
36200
|
+
async runCold(sessionId, fetchCold) {
|
|
36201
|
+
if (this.coldCache[sessionId] !== void 0 || this.coldInFlight.has(sessionId)) return;
|
|
36202
|
+
this.coldInFlight = new SvelteSet(this.coldInFlight).add(sessionId);
|
|
36203
|
+
try {
|
|
36204
|
+
const cold = await fetchCold(sessionId);
|
|
36205
|
+
if (cold !== null) this.coldCache = {
|
|
36206
|
+
...this.coldCache,
|
|
36207
|
+
[sessionId]: cold
|
|
36208
|
+
};
|
|
36209
|
+
else this.deadSessions = {
|
|
36210
|
+
...this.deadSessions,
|
|
36211
|
+
[sessionId]: `Session ${sessionId} not found on the DSH host. It may have been reaped.`
|
|
36212
|
+
};
|
|
36213
|
+
} finally {
|
|
36214
|
+
const next = new SvelteSet(this.coldInFlight);
|
|
36215
|
+
next.delete(sessionId);
|
|
36216
|
+
this.coldInFlight = next;
|
|
36217
|
+
}
|
|
35780
36218
|
}
|
|
35781
|
-
|
|
35782
|
-
|
|
35783
|
-
|
|
35784
|
-
|
|
35785
|
-
|
|
35786
|
-
|
|
35787
|
-
|
|
35788
|
-
|
|
35789
|
-
|
|
36219
|
+
/** The floor's two lifecycle feeds (call during component init —
|
|
36220
|
+
* `$effect` needs an owner):
|
|
36221
|
+
* - Prompt Sync hygiene (ADR "The Prompt Sync" D1/D6): a session
|
|
36222
|
+
* that left the floor holds no check and no snapshot; count 0
|
|
36223
|
+
* clears the broadcast. Conversation sessions only (D6).
|
|
36224
|
+
* - Spine feed lifecycle (W8): ref-counted single timer started on
|
|
36225
|
+
* mount, stopped on destroy; the a2a window rides the floor's
|
|
36226
|
+
* conversation senders (first sender per tick, never per panel).
|
|
36227
|
+
* Returns the spine subscription's cleanup. */
|
|
36228
|
+
installFeeds(getConversationSessionIds) {
|
|
36229
|
+
return () => {};
|
|
35790
36230
|
}
|
|
35791
|
-
}
|
|
35792
|
-
|
|
35793
|
-
st.panels = entries;
|
|
35794
|
-
st.selectedPanelId = selectedId;
|
|
35795
|
-
syncPanelIdSeq(entries);
|
|
35796
|
-
}
|
|
35797
|
-
/** The fresh panel mounted and its composer took focus — clear the
|
|
35798
|
-
* swap-focus marker (a marker whose panel never mounts stays inert:
|
|
35799
|
-
* panel ids are unique and never remount). */
|
|
35800
|
-
function clearFocusComposer() {
|
|
35801
|
-
st.focusComposerId = null;
|
|
35802
|
-
}
|
|
35803
|
-
function selectPanel(panelId) {
|
|
35804
|
-
if (st.panels.some((p) => p.id === panelId)) st.selectedPanelId = panelId;
|
|
35805
|
-
}
|
|
35806
|
-
function closeLoupe() {
|
|
35807
|
-
st.loupePanelId = null;
|
|
35808
|
-
}
|
|
35809
|
-
function clearLoupeIfGone() {
|
|
35810
|
-
if (st.loupePanelId !== null && !st.panels.some((p) => p.id === st.loupePanelId)) st.loupePanelId = null;
|
|
35811
|
-
}
|
|
35812
|
-
function selectedIndex_() {
|
|
35813
|
-
return st.panels.findIndex((p) => p.id === st.selectedPanelId);
|
|
35814
|
-
}
|
|
36231
|
+
};
|
|
36232
|
+
var pageFeeds = new PageFeeds();
|
|
35815
36233
|
//#endregion
|
|
35816
36234
|
//#region src/lib/services/panels/glass-release.ts
|
|
35817
36235
|
/**
|
|
@@ -36335,4 +36753,4 @@ function _page($$renderer, $$props) {
|
|
|
36335
36753
|
}
|
|
36336
36754
|
|
|
36337
36755
|
export { _page as default };
|
|
36338
|
-
//# sourceMappingURL=_page.svelte.js-
|
|
36756
|
+
//# sourceMappingURL=_page.svelte.js-CY7zcWr4.js.map
|