@deepseek-insight/dsi 0.5.36 → 0.5.37

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.
Files changed (33) hide show
  1. package/build/client/_app/immutable/assets/2.wkCizmHE.css +1 -0
  2. package/build/client/_app/immutable/chunks/{CPbUcKPc.js → 5to-0Ltw.js} +1 -1
  3. package/build/client/_app/immutable/chunks/{CpX84bXa.js → B0CA3e3Z.js} +1 -1
  4. package/build/client/_app/immutable/chunks/{ZwJo3zrp.js → BU9ifoPD.js} +1 -1
  5. package/build/client/_app/immutable/chunks/{Cvfdkz5B.js → BcZpqAlr.js} +1 -1
  6. package/build/client/_app/immutable/chunks/{BKYpDGvC.js → C7P-gdkj.js} +1 -1
  7. package/build/client/_app/immutable/chunks/{ZTD3u9Qg.js → CFiKepbv.js} +2 -2
  8. package/build/client/_app/immutable/chunks/CvmmO6Nf.js +1 -0
  9. package/build/client/_app/immutable/chunks/DJFafwzv.js +1 -0
  10. package/build/client/_app/immutable/chunks/{C1rk31qs.js → DvS_5Vf1.js} +1 -1
  11. package/build/client/_app/immutable/chunks/{GhVfcgWW.js → p4deE-02.js} +4 -4
  12. package/build/client/_app/immutable/entry/{app.DM-WIZa8.js → app.BMMDW9V6.js} +2 -2
  13. package/build/client/_app/immutable/entry/start.DtTcmsS3.js +1 -0
  14. package/build/client/_app/immutable/nodes/{1.CSG0CVRN.js → 1.DRcBeFDO.js} +1 -1
  15. package/build/client/_app/immutable/nodes/{2.CWJBqz9q.js → 2.BPKwz9rT.js} +190 -190
  16. package/build/client/_app/version.json +1 -1
  17. package/build/handler.js +4 -4
  18. package/build/index.js +4 -4
  19. package/build/server/chunks/chunks/{internal.js-D8oISUTm.js → internal.js-zSbVSi1k.js} +2 -2
  20. package/build/server/chunks/chunks/{state.js-D6nZd_zN.js → state.js-CVT5zkGX.js} +2 -2
  21. package/build/server/chunks/entries/pages/{_error.svelte.js-yH59g5II.js → _error.svelte.js-D3no0GMB.js} +3 -3
  22. package/build/server/chunks/entries/pages/{_page.svelte.js-Be_p_N6K.js → _page.svelte.js-Cl5dMg9t.js} +208 -159
  23. package/build/server/chunks/{handler-DjgkfjqU.js → handler-BH_Ab7-s.js} +3 -3
  24. package/build/server/chunks/{index.js-DAuFLIFQ.js → index.js-Bl10UnJ7.js} +2 -2
  25. package/build/server/chunks/{manifest.js-9-1nxrAa.js → manifest.js-OSsDUUGX.js} +4 -4
  26. package/build/server/chunks/nodes/1.js-gC97MpHD.js +9 -0
  27. package/build/server/chunks/nodes/{2.js-C8rwGPl3.js → 2.js-CoaWEE88.js} +4 -4
  28. package/package.json +1 -1
  29. package/build/client/_app/immutable/assets/2.B2TMGoNC.css +0 -1
  30. package/build/client/_app/immutable/chunks/B8475bbs.js +0 -1
  31. package/build/client/_app/immutable/chunks/b-tPv4uU.js +0 -1
  32. package/build/client/_app/immutable/entry/start.DsdVwQ2P.js +0 -1
  33. package/build/server/chunks/nodes/1.js-CBSPs58f.js +0 -9
@@ -1,4 +1,4 @@
1
- import { c as onDestroy, d as __exportAll } from '../../chunks/internal.js-D8oISUTm.js';
1
+ import { c as onDestroy, d as __exportAll } from '../../chunks/internal.js-zSbVSi1k.js';
2
2
  import { V as head, y as derived, X as bind_props, W as escape_html, Y as attr, Z as attr_style, _ as attr_class, x as setContext, $ as spread_props, a0 as attributes, a1 as clsx, a2 as ensure_array_like, a3 as element, J as getContext, a4 as stringify, a5 as html, F as run, a6 as props_id } from '../../chunks/server.js-11-pxAWV.js';
3
3
  import { U as UI_LOCALES } from '../../chunks/config.js-B0w1-uCA.js';
4
4
  import { m as mergeEntries, c as collapseSystemPromptEntries, t as truncate } from '../../chunks/dsh-events.js-CyvSb4O3.js';
@@ -7,7 +7,7 @@ import { b as applyKnobEvent, E as EMPTY_KNOBS, r as resolvePermission, l as loc
7
7
  import { D as DEFAULT_IMAGE_LIMITS } from '../../chunks/image-limits.js-CUdJ0f7r.js';
8
8
  import { a as appConfig, t as triggerMode, g as getTrigger, p as previewSegments, i as isValidTagWord, b as textPreviewOf, s as searchKey, c as shouldRecordPrompt, d as parseTagWords } from '../../chunks/app-config.svelte.js-BBPHOX4N.js';
9
9
  import { c as getLocale } from '../../chunks/runtime.js-CCJi3XaY.js';
10
- import { p as page, a as afterNavigate, t, c as replaceState, e as currentLocale, u as unexpectederror1, s as sessionnotfound2, r as reapednote1, d as dshunreachable1, b as backtoworkspace2 } from '../../chunks/state.js-D6nZd_zN.js';
10
+ import { p as page, a as afterNavigate, t, c as replaceState, e as currentLocale, u as unexpectederror1, s as sessionnotfound2, r as reapednote1, d as dshunreachable1, b as backtoworkspace2 } from '../../chunks/state.js-CVT5zkGX.js';
11
11
  import 'yaml';
12
12
  import 'html-to-image';
13
13
  import hljs from 'highlight.js/lib/core';
@@ -14675,12 +14675,12 @@ function ClearIconButton($$renderer, $$props) {
14675
14675
  });
14676
14676
  }
14677
14677
  //#endregion
14678
- //#region src/lib/components/chat/PromptInputText.svelte
14678
+ //#region src/lib/components/composer/sibling/PromptInputText.svelte
14679
14679
  function PromptInputText($$renderer, $$props) {
14680
14680
  $$renderer.component(($$renderer) => {
14681
14681
  /**
14682
14682
  * PromptInputText — the composer's textarea (extracted from
14683
- * PromptInput 2026-09-04). Pure wiring, no logic: every handler
14683
+ * Composer 2026-09-04). Pure wiring, no logic: every handler
14684
14684
  * reports upward and the two bindables carry the state back — the
14685
14685
  * owner keeps everything.
14686
14686
  *
@@ -14776,7 +14776,7 @@ function voicedSkillRow(row) {
14776
14776
  };
14777
14777
  }
14778
14778
  //#endregion
14779
- //#region src/lib/components/chat/SlashMenu.svelte
14779
+ //#region src/lib/components/composer/menu/SlashMenu.svelte
14780
14780
  function slashMenuMatches(row, query) {
14781
14781
  const terms = query.slice(1).toLowerCase().split(/[;\s]+/).filter(Boolean);
14782
14782
  if (terms.length === 0) return true;
@@ -14794,7 +14794,7 @@ function SlashMenu($$renderer, $$props) {
14794
14794
  *
14795
14795
  * Presentational (the MacroRunSheet rule): rows + filter query +
14796
14796
  * lifecycle state in; kind-aware pick events out. No fetch, no store
14797
- * import — the HOST (PromptInput) owns the draft, the trigger, the
14797
+ * import — the HOST (Composer) owns the draft, the trigger, the
14798
14798
  * catalog state, and the keyboard lifecycle. This component renders;
14799
14799
  * it never listens for keys itself.
14800
14800
  *
@@ -14820,7 +14820,7 @@ function SlashMenu($$renderer, $$props) {
14820
14820
  * matched rows (same matcher, exported above) is ≥1 — otherwise
14821
14821
  * Enter falls through to submit and the host closes the menu (the
14822
14822
  * strip's shipped guard `triggerActive && rows.length > 0`,
14823
- * PromptInput.svelte — row-gated interception). Tab accepts exactly
14823
+ * Composer.svelte — row-gated interception). Tab accepts exactly
14824
14824
  * like Enter (strip parity); Shift+Tab cycles back. The menu owns no
14825
14825
  * key listener and no fall-through branch — the contract is
14826
14826
  * structural. Loading/idle/failed render status rows that never
@@ -14856,45 +14856,45 @@ function SlashMenu($$renderer, $$props) {
14856
14856
  * in both catalogs resolves to the COMMAND) is the ladder's, not the
14857
14857
  * menu's — the menu lists every matched row it was given. */
14858
14858
  const matchedSkills = derived(() => skills$1.filter((row) => slashMenuMatches(row, query)).map(voicedSkillRow));
14859
- $$renderer.push(`<div data-svelte="SlashMenu" class="slash-menu svelte-hiff6x" role="listbox"${attr("aria-label", t(slashmenu1))} data-testid="slash-menu">`);
14859
+ $$renderer.push(`<div data-svelte="SlashMenu" class="slash-menu svelte-1uzg2at" role="listbox"${attr("aria-label", t(slashmenu1))} data-testid="slash-menu">`);
14860
14860
  if (catalogState === "loading" || catalogState === "idle") {
14861
14861
  $$renderer.push("<!--[0-->");
14862
- $$renderer.push(`<div class="slash-status svelte-hiff6x" data-testid="slash-menu-loading">${escape_html(t(loadingsessioncommands2))}</div>`);
14862
+ $$renderer.push(`<div class="slash-status svelte-1uzg2at" data-testid="slash-menu-loading">${escape_html(t(loadingsessioncommands2))}</div>`);
14863
14863
  } else if (catalogState === "failed") {
14864
14864
  $$renderer.push("<!--[1-->");
14865
- $$renderer.push(`<div class="slash-status slash-error svelte-hiff6x" data-testid="slash-menu-error">${escape_html(t(catalogunavailable1))}</div>`);
14865
+ $$renderer.push(`<div class="slash-status slash-error svelte-1uzg2at" data-testid="slash-menu-error">${escape_html(t(catalogunavailable1))}</div>`);
14866
14866
  } else {
14867
14867
  $$renderer.push("<!--[-1-->");
14868
- $$renderer.push(`<div class="slash-section-label svelte-hiff6x" data-testid="slash-gestures-label">${escape_html(t(dsigestures1))} <span class="slash-section-kind svelte-hiff6x">${escape_html(t(gestureskind1))}</span></div> <!--[-->`);
14868
+ $$renderer.push(`<div class="slash-section-label svelte-1uzg2at" data-testid="slash-gestures-label">${escape_html(t(dsigestures1))} <span class="slash-section-kind svelte-1uzg2at">${escape_html(t(gestureskind1))}</span></div> <!--[-->`);
14869
14869
  const each_array = ensure_array_like(matchedGestures());
14870
14870
  for (let i = 0, $$length = each_array.length; i < $$length; i++) {
14871
14871
  let row = each_array[i];
14872
- $$renderer.push(`<button type="button"${attr_class("slash-row svelte-hiff6x", void 0, { "active": i === activeIndex })} role="option"${attr("aria-selected", i === activeIndex)} data-testid="slash-gesture-row"${attr("data-name", row.name)}><span class="slash-name svelte-hiff6x">${escape_html(row.display)}</span> <span class="slash-desc svelte-hiff6x">${escape_html(row.description)}</span></button>`);
14872
+ $$renderer.push(`<button type="button"${attr_class("slash-row svelte-1uzg2at", void 0, { "active": i === activeIndex })} role="option"${attr("aria-selected", i === activeIndex)} data-testid="slash-gesture-row"${attr("data-name", row.name)}><span class="slash-name svelte-1uzg2at">${escape_html(row.display)}</span> <span class="slash-desc svelte-1uzg2at">${escape_html(row.description)}</span></button>`);
14873
14873
  }
14874
- $$renderer.push(`<!--]--> <div class="slash-section-label svelte-hiff6x" data-testid="slash-commands-label">${escape_html(t(commands))} <span class="slash-section-kind svelte-hiff6x">${escape_html(t(commandskind1))}</span></div> <!--[-->`);
14874
+ $$renderer.push(`<!--]--> <div class="slash-section-label svelte-1uzg2at" data-testid="slash-commands-label">${escape_html(t(commands))} <span class="slash-section-kind svelte-1uzg2at">${escape_html(t(commandskind1))}</span></div> <!--[-->`);
14875
14875
  const each_array_1 = ensure_array_like(matchedCommands());
14876
14876
  for (let i = 0, $$length = each_array_1.length; i < $$length; i++) {
14877
14877
  let row = each_array_1[i];
14878
- $$renderer.push(`<button type="button"${attr_class("slash-row svelte-hiff6x", void 0, { "active": matchedGestures().length + i === activeIndex })} role="option"${attr("aria-selected", matchedGestures().length + i === activeIndex)} data-testid="slash-command-row"${attr("data-name", row.name)}><span class="slash-name svelte-hiff6x">/${escape_html(row.name)}</span> <span class="slash-desc svelte-hiff6x">${escape_html(row.description)}</span> `);
14878
+ $$renderer.push(`<button type="button"${attr_class("slash-row svelte-1uzg2at", void 0, { "active": matchedGestures().length + i === activeIndex })} role="option"${attr("aria-selected", matchedGestures().length + i === activeIndex)} data-testid="slash-command-row"${attr("data-name", row.name)}><span class="slash-name svelte-1uzg2at">/${escape_html(row.name)}</span> <span class="slash-desc svelte-1uzg2at">${escape_html(row.description)}</span> `);
14879
14879
  if (row.input?.hint !== void 0) {
14880
14880
  $$renderer.push("<!--[0-->");
14881
- $$renderer.push(`<span class="slash-hint svelte-hiff6x" data-testid="slash-hint">${escape_html(row.input.hint)}</span>`);
14881
+ $$renderer.push(`<span class="slash-hint svelte-1uzg2at" data-testid="slash-hint">${escape_html(row.input.hint)}</span>`);
14882
14882
  } else $$renderer.push("<!--[-1-->");
14883
14883
  $$renderer.push(`<!--]--></button>`);
14884
14884
  }
14885
- $$renderer.push(`<!--]--> <div class="slash-section-label svelte-hiff6x" data-testid="slash-skills-label">${escape_html(t(skills))} <span class="slash-section-kind svelte-hiff6x">${escape_html(t(skillskind1))}</span></div> <!--[-->`);
14885
+ $$renderer.push(`<!--]--> <div class="slash-section-label svelte-1uzg2at" data-testid="slash-skills-label">${escape_html(t(skills))} <span class="slash-section-kind svelte-1uzg2at">${escape_html(t(skillskind1))}</span></div> <!--[-->`);
14886
14886
  const each_array_2 = ensure_array_like(matchedSkills());
14887
14887
  for (let j = 0, $$length = each_array_2.length; j < $$length; j++) {
14888
14888
  let row = each_array_2[j];
14889
- $$renderer.push(`<button type="button"${attr_class("slash-row svelte-hiff6x", void 0, { "active": matchedGestures().length + matchedCommands().length + j === activeIndex })} role="option"${attr("aria-selected", matchedGestures().length + matchedCommands().length + j === activeIndex)} data-testid="slash-skill-row"${attr("data-name", row.name)}><span class="slash-name svelte-hiff6x">/${escape_html(row.name)}</span> <span class="slash-desc svelte-hiff6x">${escape_html(row.description)}</span> `);
14889
+ $$renderer.push(`<button type="button"${attr_class("slash-row svelte-1uzg2at", void 0, { "active": matchedGestures().length + matchedCommands().length + j === activeIndex })} role="option"${attr("aria-selected", matchedGestures().length + matchedCommands().length + j === activeIndex)} data-testid="slash-skill-row"${attr("data-name", row.name)}><span class="slash-name svelte-1uzg2at">/${escape_html(row.name)}</span> <span class="slash-desc svelte-1uzg2at">${escape_html(row.description)}</span> `);
14890
14890
  if (row.modelInvocable === false) {
14891
14891
  $$renderer.push("<!--[0-->");
14892
- $$renderer.push(`<span class="slash-badge svelte-hiff6x" title="Only you can invoke this skill — the model cannot call it">you</span>`);
14892
+ $$renderer.push(`<span class="slash-badge svelte-1uzg2at" title="Only you can invoke this skill — the model cannot call it">you</span>`);
14893
14893
  } else $$renderer.push("<!--[-1-->");
14894
14894
  $$renderer.push(`<!--]--> `);
14895
14895
  if (row.whenToUse !== void 0 && row.whenToUse !== "") {
14896
14896
  $$renderer.push("<!--[0-->");
14897
- $$renderer.push(`<span class="slash-hint svelte-hiff6x" data-testid="slash-hint">${escape_html(row.whenToUse)}</span>`);
14897
+ $$renderer.push(`<span class="slash-hint svelte-1uzg2at" data-testid="slash-hint">${escape_html(row.whenToUse)}</span>`);
14898
14898
  } else $$renderer.push("<!--[-1-->");
14899
14899
  $$renderer.push(`<!--]--></button>`);
14900
14900
  }
@@ -14903,7 +14903,7 @@ function SlashMenu($$renderer, $$props) {
14903
14903
  $$renderer.push("<!--[0-->");
14904
14904
  if (gestures.length + commands$1.length + skills$1.length > 0) {
14905
14905
  $$renderer.push("<!--[0-->");
14906
- $$renderer.push(`<div class="slash-status svelte-hiff6x" data-testid="slash-menu-nomatch">${escape_html(t(nomatchingcommands2))}</div>`);
14906
+ $$renderer.push(`<div class="slash-status svelte-1uzg2at" data-testid="slash-menu-nomatch">${escape_html(t(nomatchingcommands2))}</div>`);
14907
14907
  } else $$renderer.push("<!--[-1-->");
14908
14908
  $$renderer.push(`<!--]-->`);
14909
14909
  } else $$renderer.push("<!--[-1-->");
@@ -15189,7 +15189,7 @@ function links(text) {
15189
15189
  });
15190
15190
  }
15191
15191
  //#endregion
15192
- //#region src/lib/components/chat/suggest-strip/StripTip.svelte
15192
+ //#region src/lib/components/composer/menu/suggest-strip/StripTip.svelte
15193
15193
  function StripTip($$renderer, $$props) {
15194
15194
  $$renderer.component(($$renderer) => {
15195
15195
  /**
@@ -15212,7 +15212,7 @@ function StripTip($$renderer, $$props) {
15212
15212
  });
15213
15213
  }
15214
15214
  //#endregion
15215
- //#region src/lib/components/chat/suggest-strip/StripChip.svelte
15215
+ //#region src/lib/components/composer/menu/suggest-strip/StripChip.svelte
15216
15216
  function StripChip($$renderer, $$props) {
15217
15217
  $$renderer.component(($$renderer) => {
15218
15218
  /**
@@ -15243,13 +15243,13 @@ function StripChip($$renderer, $$props) {
15243
15243
  let editLabel = row.label ?? "";
15244
15244
  let editUses = String(row.use_count);
15245
15245
  let editText = row.text;
15246
- $$renderer.push(`<div data-svelte="StripChip"${attr_class("strip-chip svelte-exwam9", void 0, { "active": active })}><button type="button" class="strip-pick svelte-exwam9" role="option"${attr("aria-selected", active)}${attr("title", row.text)}><span class="strip-label svelte-exwam9" role="presentation"><!--[-->`);
15246
+ $$renderer.push(`<div data-svelte="StripChip"${attr_class("strip-chip svelte-1k19r0d", void 0, { "active": active })}><button type="button" class="strip-pick svelte-1k19r0d" role="option"${attr("aria-selected", active)}${attr("title", row.text)}><span class="strip-label svelte-1k19r0d" role="presentation"><!--[-->`);
15247
15247
  const each_array = ensure_array_like(segments());
15248
15248
  for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
15249
15249
  let seg = each_array[$$index];
15250
15250
  if (seg.hit) {
15251
15251
  $$renderer.push("<!--[0-->");
15252
- $$renderer.push(`<span class="hl svelte-exwam9">${escape_html(seg.text)}</span>`);
15252
+ $$renderer.push(`<span class="hl svelte-1k19r0d">${escape_html(seg.text)}</span>`);
15253
15253
  } else {
15254
15254
  $$renderer.push("<!--[-1-->");
15255
15255
  $$renderer.push(`${escape_html(seg.text)}`);
@@ -15259,17 +15259,17 @@ function StripChip($$renderer, $$props) {
15259
15259
  $$renderer.push(`<!--]--></span> `);
15260
15260
  if (row.text.includes("\n")) {
15261
15261
  $$renderer.push("<!--[0-->");
15262
- $$renderer.push(`<span class="strip-ml svelte-exwam9">⏎</span>`);
15262
+ $$renderer.push(`<span class="strip-ml svelte-1k19r0d">⏎</span>`);
15263
15263
  } else $$renderer.push("<!--[-1-->");
15264
- $$renderer.push(`<!--]--> <span class="strip-count svelte-exwam9">×${escape_html(row.use_count)}</span></button> `);
15264
+ $$renderer.push(`<!--]--> <span class="strip-count svelte-1k19r0d">×${escape_html(row.use_count)}</span></button> `);
15265
15265
  if (mode === "run" && onstep !== void 0) {
15266
15266
  $$renderer.push("<!--[0-->");
15267
- $$renderer.push(`<div class="strip-step svelte-exwam9"><button type="button" class="strip-step-btn svelte-exwam9"${attr("aria-label", t(stepthismacro2))}${attr("title", t(stepheldtitle2))}>⏯</button></div>`);
15267
+ $$renderer.push(`<div class="strip-step svelte-1k19r0d"><button type="button" class="strip-step-btn svelte-1k19r0d"${attr("aria-label", t(stepthismacro2))}${attr("title", t(stepheldtitle2))}>⏯</button></div>`);
15268
15268
  } else $$renderer.push("<!--[-1-->");
15269
15269
  $$renderer.push(`<!--]--> `);
15270
15270
  if (hasMenu()) {
15271
15271
  $$renderer.push("<!--[0-->");
15272
- $$renderer.push(`<div class="strip-menu svelte-exwam9"><button type="button" class="strip-menu-btn svelte-exwam9"${attr("aria-label", t(promptoptions1))}>⋯</button></div>`);
15272
+ $$renderer.push(`<div class="strip-menu svelte-1k19r0d"><button type="button" class="strip-menu-btn svelte-1k19r0d"${attr("aria-label", t(promptoptions1))}>⋯</button></div>`);
15273
15273
  } else $$renderer.push("<!--[-1-->");
15274
15274
  $$renderer.push(`<!--]--> `);
15275
15275
  StripTip($$renderer, {
@@ -15280,16 +15280,16 @@ function StripChip($$renderer, $$props) {
15280
15280
  $$renderer.push(`<!----> `);
15281
15281
  if (menuOpen && onrename !== void 0 && ondelete !== void 0) {
15282
15282
  $$renderer.push("<!--[0-->");
15283
- $$renderer.push(`<div class="strip-menu-pop svelte-exwam9" role="menu" tabindex="-1"${attr_style("")}><div class="strip-menu-form svelte-exwam9"><label class="strip-menu-field svelte-exwam9"><span>${escape_html(t(uses))}</span> <input type="number" class="strip-menu-input strip-menu-uses svelte-exwam9"${attr("value", editUses)} min="1"${attr("aria-label", t(uses))}/></label> <label class="strip-menu-field svelte-exwam9"><span>${escape_html(t(label))}</span> <input type="text" class="strip-menu-input svelte-exwam9"${attr("value", editLabel)}${attr("placeholder", t(label))} maxlength="60"${attr("aria-label", t(promptlabelaria2))}/></label> <label class="strip-menu-field svelte-exwam9"><span>${escape_html(t(text))}</span> <textarea class="strip-menu-text svelte-exwam9"${attr("aria-label", t(prompttextaria2))}>`);
15283
+ $$renderer.push(`<div class="strip-menu-pop svelte-1k19r0d" role="menu" tabindex="-1"${attr_style("")}><div class="strip-menu-form svelte-1k19r0d"><label class="strip-menu-field svelte-1k19r0d"><span>${escape_html(t(uses))}</span> <input type="number" class="strip-menu-input strip-menu-uses svelte-1k19r0d"${attr("value", editUses)} min="1"${attr("aria-label", t(uses))}/></label> <label class="strip-menu-field svelte-1k19r0d"><span>${escape_html(t(label))}</span> <input type="text" class="strip-menu-input svelte-1k19r0d"${attr("value", editLabel)}${attr("placeholder", t(label))} maxlength="60"${attr("aria-label", t(promptlabelaria2))}/></label> <label class="strip-menu-field svelte-1k19r0d"><span>${escape_html(t(text))}</span> <textarea class="strip-menu-text svelte-1k19r0d"${attr("aria-label", t(prompttextaria2))}>`);
15284
15284
  const $$body = escape_html(editText);
15285
15285
  if ($$body) $$renderer.push(`${$$body}`);
15286
- $$renderer.push(`</textarea></label></div> <div class="strip-menu-actions svelte-exwam9"><button type="button" class="strip-menu-save svelte-exwam9">${escape_html(t(save))}</button> <button type="button" class="strip-menu-delete svelte-exwam9">${escape_html(t(_delete))}</button></div></div>`);
15286
+ $$renderer.push(`</textarea></label></div> <div class="strip-menu-actions svelte-1k19r0d"><button type="button" class="strip-menu-save svelte-1k19r0d">${escape_html(t(save))}</button> <button type="button" class="strip-menu-delete svelte-1k19r0d">${escape_html(t(_delete))}</button></div></div>`);
15287
15287
  } else $$renderer.push("<!--[-1-->");
15288
15288
  $$renderer.push(`<!--]--></div>`);
15289
15289
  });
15290
15290
  }
15291
15291
  //#endregion
15292
- //#region src/lib/components/chat/suggest-strip/SuggestLine.svelte
15292
+ //#region src/lib/components/composer/menu/suggest-strip/SuggestLine.svelte
15293
15293
  function SuggestLine($$renderer, $$props) {
15294
15294
  $$renderer.component(($$renderer) => {
15295
15295
  /**
@@ -15301,13 +15301,13 @@ function SuggestLine($$renderer, $$props) {
15301
15301
  let { onmanage } = $$props;
15302
15302
  if (onmanage) {
15303
15303
  $$renderer.push("<!--[0-->");
15304
- $$renderer.push(`<button data-svelte="SuggestLine" type="button" class="strip-manage svelte-pzs55x">${escape_html(t(manageprompts1))}</button>`);
15304
+ $$renderer.push(`<button data-svelte="SuggestLine" type="button" class="strip-manage svelte-1b31rll">${escape_html(t(manageprompts1))}</button>`);
15305
15305
  } else $$renderer.push("<!--[-1-->");
15306
15306
  $$renderer.push(`<!--]-->`);
15307
15307
  });
15308
15308
  }
15309
15309
  //#endregion
15310
- //#region src/lib/components/chat/suggest-strip/StripTagChips.svelte
15310
+ //#region src/lib/components/composer/menu/suggest-strip/StripTagChips.svelte
15311
15311
  function StripTagChips($$renderer, $$props) {
15312
15312
  $$renderer.component(($$renderer) => {
15313
15313
  /**
@@ -15320,11 +15320,11 @@ function StripTagChips($$renderer, $$props) {
15320
15320
  let { recTags, checked} = $$props;
15321
15321
  if (recTags.length > 0) {
15322
15322
  $$renderer.push("<!--[0-->");
15323
- $$renderer.push(`<div data-svelte="StripTagChips" class="strip-tag-chips svelte-1kzzzu2" role="group"${attr("aria-label", t(filterbytags2))}><!--[-->`);
15323
+ $$renderer.push(`<div data-svelte="StripTagChips" class="strip-tag-chips svelte-rq6z6w" role="group"${attr("aria-label", t(filterbytags2))}><!--[-->`);
15324
15324
  const each_array = ensure_array_like(recTags);
15325
15325
  for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
15326
15326
  let word = each_array[$$index];
15327
- $$renderer.push(`<label${attr_class("strip-tag-chip svelte-1kzzzu2", void 0, { "on": checked.includes(word) })}><input type="checkbox"${attr("checked", checked.includes(word), true)} class="svelte-1kzzzu2"/> ${escape_html(word)}</label>`);
15327
+ $$renderer.push(`<label${attr_class("strip-tag-chip svelte-rq6z6w", void 0, { "on": checked.includes(word) })}><input type="checkbox"${attr("checked", checked.includes(word), true)} class="svelte-rq6z6w"/> ${escape_html(word)}</label>`);
15328
15328
  }
15329
15329
  $$renderer.push(`<!--]--></div>`);
15330
15330
  } else $$renderer.push("<!--[-1-->");
@@ -15339,7 +15339,7 @@ function saveTagFilter(base, words, profile) {
15339
15339
  } catch {}
15340
15340
  }
15341
15341
  //#endregion
15342
- //#region src/lib/components/chat/suggest-strip/SuggestStrip.svelte
15342
+ //#region src/lib/components/composer/menu/suggest-strip/SuggestStrip.svelte
15343
15343
  function SuggestStrip($$renderer, $$props) {
15344
15344
  $$renderer.component(($$renderer) => {
15345
15345
  /**
@@ -15351,7 +15351,7 @@ function SuggestStrip($$renderer, $$props) {
15351
15351
  * coordination (one popup at a time, menuForId); each row renders a
15352
15352
  * StripChip that owns its own popup state (the multiline preview
15353
15353
  * tooltip lives in that chip's StripTip).
15354
- * PromptInput owns the textarea, query, and prompt refresh. Renders
15354
+ * Composer owns the textarea, query, and prompt refresh. Renders
15355
15355
  * nothing while rows is empty ({#if rows.length > 0}).
15356
15356
  *
15357
15357
  * Floating geometry (BC-1): absolute above the textarea wrapper
@@ -15398,7 +15398,7 @@ function SuggestStrip($$renderer, $$props) {
15398
15398
  });
15399
15399
  if (rows.length > 0) {
15400
15400
  $$renderer.push("<!--[0-->");
15401
- $$renderer.push(`<div data-svelte="SuggestStrip" class="suggest-strip svelte-172t8ad" role="listbox"${attr("aria-label", t(promptsuggestions1))} data-testid="suggest-strip"><!--[-->`);
15401
+ $$renderer.push(`<div data-svelte="SuggestStrip" class="suggest-strip svelte-1u1dnex" role="listbox"${attr("aria-label", t(promptsuggestions1))} data-testid="suggest-strip"><!--[-->`);
15402
15402
  const each_array = ensure_array_like(visibleItems());
15403
15403
  for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
15404
15404
  let { row, index } = each_array[$$index];
@@ -16547,14 +16547,14 @@ function ConversationError($$renderer, $$props) {
16547
16547
  });
16548
16548
  }
16549
16549
  //#endregion
16550
- //#region src/lib/components/chat/StickToBottomToggle.svelte
16550
+ //#region src/lib/components/composer/sibling/StickToBottomToggle.svelte
16551
16551
  function StickToBottomToggle($$renderer, $$props) {
16552
16552
  $$renderer.component(($$renderer) => {
16553
16553
  /**
16554
16554
  * StickToBottomToggle — the composer's stick-to-bottom indicator and
16555
16555
  * switch (2026-08-26): maroon while the transcript follows the live
16556
16556
  * bottom, grey once the reader scrolled away — click flips it. Sits
16557
- * directly above the submit button (PromptInput's send column).
16557
+ * directly above the submit button (Composer's send column).
16558
16558
  *
16559
16559
  * Icon: ArrowDownToLine (user-picked, 2026-08-26) — the lucide set
16560
16560
  * pinned here (1.0.1) has no layers-arrow-down; the arrow-onto-a-line
@@ -16573,7 +16573,7 @@ function StickToBottomToggle($$renderer, $$props) {
16573
16573
  */
16574
16574
  let { stick, ontoggle } = $$props;
16575
16575
  const title = derived(() => stick ? "Stick to bottom: on — new output follows the live end (click to release)" : "Stick to bottom: off — the transcript stays where you scrolled (click to follow the live end)");
16576
- $$renderer.push(`<button data-svelte="StickToBottomToggle" type="button"${attr_class("stick-toggle svelte-fe1hyx", void 0, { "on": stick })}${attr("aria-pressed", stick)}${attr("aria-label", t(sticktobottom2))}${attr("title", title())} data-testid="stick-toggle"${attr("data-active", stick)}>`);
16576
+ $$renderer.push(`<button data-svelte="StickToBottomToggle" type="button"${attr_class("stick-toggle svelte-1n070ge", void 0, { "on": stick })}${attr("aria-pressed", stick)}${attr("aria-label", t(sticktobottom2))}${attr("title", title())} data-testid="stick-toggle"${attr("data-active", stick)}>`);
16577
16577
  Arrow_down_to_line($$renderer, {
16578
16578
  size: 14,
16579
16579
  "aria-hidden": "true"
@@ -16600,7 +16600,7 @@ function estimateTokens(text) {
16600
16600
  return Math.ceil(text.length / 4);
16601
16601
  }
16602
16602
  //#endregion
16603
- //#region src/lib/components/chat/TokenCounter.svelte
16603
+ //#region src/lib/components/composer/sibling/TokenCounter.svelte
16604
16604
  function TokenCounter($$renderer, $$props) {
16605
16605
  $$renderer.component(($$renderer) => {
16606
16606
  /**
@@ -16615,7 +16615,57 @@ function TokenCounter($$renderer, $$props) {
16615
16615
  });
16616
16616
  }
16617
16617
  //#endregion
16618
- //#region src/lib/components/chat/ContextConsumption.svelte
16618
+ //#region src/lib/components/composer/sibling/ModelSelector.svelte
16619
+ function ModelSelector($$renderer, $$props) {
16620
+ $$renderer.component(($$renderer) => {
16621
+ /**
16622
+ * ModelSelector — the header dropdown for the session's model (POC-3 W3, 3.2).
16623
+ *
16624
+ * GET /api/dsh/session/{id}/models on open (the directory's only source of
16625
+ * truth); picking a model POSTs /select-model ONCE (in-flight lock) and
16626
+ * adopts the host's normalized selection. The current selection renders
16627
+ * even when the catalog is empty/garbage (normalize is the connection's
16628
+ * job — garbage-safe, never throws). BC-1/BC-2: browser API only, no
16629
+ * server imports; the selection takes effect on the NEXT assembled step.
16630
+ */
16631
+ let { disabled = false} = $$props;
16632
+ let open = false;
16633
+ /** Label for the closed state: current model, or "model —". */
16634
+ const currentLabel = derived(() => {
16635
+ return "model —";
16636
+ });
16637
+ $$renderer.push(`<div data-svelte="ModelSelector" class="relative"><button type="button" class="inline-flex items-center gap-1 rounded-md border border-[#7c3aed] px-2 py-1 text-xs font-medium text-[#7c3aed] hover:bg-slate-100 disabled:opacity-50"${attr("disabled", disabled, true)} aria-haspopup="listbox"${attr("aria-expanded", open)} data-testid="model-selector-button">${escape_html(currentLabel())} <span class="text-[#7c3aed]" aria-hidden="true"><svg width="12" height="12" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M4 6l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg></span></button> `);
16638
+ $$renderer.push("<!--[-1-->");
16639
+ $$renderer.push(`<!--]--></div>`);
16640
+ });
16641
+ }
16642
+ //#endregion
16643
+ //#region src/lib/components/composer/sibling/StreamingIndicator.svelte
16644
+ function StreamingIndicator($$renderer, $$props) {
16645
+ $$renderer.component(($$renderer) => {
16646
+ /**
16647
+ * StreamingIndicator — three bouncing dots (OCI Composer port,
16648
+ * 2026-08-24). Presentational: title in, dots out.
16649
+ *
16650
+ * Default anchor is the OCI textarea overlay, DSI-tuned: absolute
16651
+ * against the host's RELATIVE wrapper — right edge, vertically
16652
+ * centered on the host's ACTION BUTTON (bottom-anchored at half the
16653
+ * button height, so the dots stay put when the textarea auto-grows;
16654
+ * the row is items-end, wrapper bottom = button bottom). Streaming
16655
+ * red, pointer-events none. `center` switches to inline flow for
16656
+ * hosts that place the dots in the transcript themselves (e.g. the
16657
+ * snippet-passing fixture).
16658
+ *
16659
+ * Contract pins (chat-components tests): the testid element carries
16660
+ * role=status + aria-label and holds EXACTLY the three dot spans —
16661
+ * no wrapper element.
16662
+ */
16663
+ let { title = "streaming", center = false } = $$props;
16664
+ $$renderer.push(`<span data-svelte="StreamingIndicator"${attr_class("streaming-indicator svelte-1sd3euh", void 0, { "centered": center })} role="status"${attr("aria-label", t(streaming))} data-testid="streaming-indicator"${attr("title", title)}><span class="dot dot-1 svelte-1sd3euh"></span> <span class="dot dot-2 svelte-1sd3euh"></span> <span class="dot dot-3 svelte-1sd3euh"></span></span>`);
16665
+ });
16666
+ }
16667
+ //#endregion
16668
+ //#region src/lib/components/composer/sibling/ContextConsumption.svelte
16619
16669
  function ContextConsumption($$renderer, $$props) {
16620
16670
  $$renderer.component(($$renderer) => {
16621
16671
  /**
@@ -16657,32 +16707,7 @@ function ContextConsumption($$renderer, $$props) {
16657
16707
  });
16658
16708
  }
16659
16709
  //#endregion
16660
- //#region src/lib/components/chat/ModelSelector.svelte
16661
- function ModelSelector($$renderer, $$props) {
16662
- $$renderer.component(($$renderer) => {
16663
- /**
16664
- * ModelSelector — the header dropdown for the session's model (POC-3 W3, 3.2).
16665
- *
16666
- * GET /api/dsh/session/{id}/models on open (the directory's only source of
16667
- * truth); picking a model POSTs /select-model ONCE (in-flight lock) and
16668
- * adopts the host's normalized selection. The current selection renders
16669
- * even when the catalog is empty/garbage (normalize is the connection's
16670
- * job — garbage-safe, never throws). BC-1/BC-2: browser API only, no
16671
- * server imports; the selection takes effect on the NEXT assembled step.
16672
- */
16673
- let { disabled = false} = $$props;
16674
- let open = false;
16675
- /** Label for the closed state: current model, or "model —". */
16676
- const currentLabel = derived(() => {
16677
- return "model —";
16678
- });
16679
- $$renderer.push(`<div data-svelte="ModelSelector" class="relative"><button type="button" class="inline-flex items-center gap-1 rounded-md border border-[#7c3aed] px-2 py-1 text-xs font-medium text-[#7c3aed] hover:bg-slate-100 disabled:opacity-50"${attr("disabled", disabled, true)} aria-haspopup="listbox"${attr("aria-expanded", open)} data-testid="model-selector-button">${escape_html(currentLabel())} <span class="text-[#7c3aed]" aria-hidden="true"><svg width="12" height="12" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M4 6l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg></span></button> `);
16680
- $$renderer.push("<!--[-1-->");
16681
- $$renderer.push(`<!--]--></div>`);
16682
- });
16683
- }
16684
- //#endregion
16685
- //#region src/lib/components/chat/AccessModeChip.svelte
16710
+ //#region src/lib/components/composer/access-mode/AccessModeChip.svelte
16686
16711
  function AccessModeChip($$renderer, $$props) {
16687
16712
  $$renderer.component(($$renderer) => {
16688
16713
  /**
@@ -16713,6 +16738,8 @@ function AccessModeChip($$renderer, $$props) {
16713
16738
  */
16714
16739
  let { permission, disabled = false} = $$props;
16715
16740
  let open = false;
16741
+ /** Optimistic pick awaiting its poll confirmation (trigger label + lock). */
16742
+ let picking = null;
16716
16743
  const PRESET_LABELS = {
16717
16744
  "read-only": presetreadonly2,
16718
16745
  "workspace-write": presetworkspacewrite2,
@@ -16743,11 +16770,11 @@ function AccessModeChip($$renderer, $$props) {
16743
16770
  });
16744
16771
  if (permission !== null) {
16745
16772
  $$renderer.push("<!--[0-->");
16746
- $$renderer.push(`<div data-svelte="AccessModeChip" class="relative"><button type="button" class="inline-flex items-center gap-1 rounded-md border border-[#7c3aed] px-2 py-1 text-xs font-medium text-[#7c3aed] hover:bg-slate-100 disabled:opacity-50"${attr("disabled", disabled || false, true)} aria-haspopup="listbox"${attr("aria-expanded", open)}${attr("aria-label", t(() => accessmodecurrent2({ label: currentLabel() })))}${attr("title", currentDescription())} data-testid="access-mode-chip"><span class="text-[#7c3aed]" aria-hidden="true">`);
16747
- if (permission.current === "read-only") {
16773
+ $$renderer.push(`<div data-svelte="AccessModeChip" class="relative"><button type="button" class="inline-flex items-center gap-1 rounded-md border border-[#7c3aed] px-2 py-1 text-xs font-medium text-[#7c3aed] hover:bg-slate-100 disabled:opacity-50"${attr("disabled", disabled || picking !== null, true)} aria-haspopup="listbox"${attr("aria-expanded", open)}${attr("aria-label", t(() => accessmodecurrent2({ label: currentLabel() })))}${attr("title", currentDescription())} data-testid="access-mode-chip"><span class="text-[#7c3aed]" aria-hidden="true">`);
16774
+ if ((permission.current) === "read-only") {
16748
16775
  $$renderer.push("<!--[0-->");
16749
16776
  $$renderer.push(`<svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M8.20554 0.899994L14.7901 3.36857V7.01026C14.7901 12 11.0466 14.2103 8.20554 15.3C5.36446 14.2103 1.62012 12 1.62012 7.01026V3.36857L8.20554 0.899994Z" stroke="currentColor" stroke-width="1.31831" stroke-linejoin="round"></path><path d="M12.1654 5.7552L8.9447 9.41475C8.73044 9.65816 8.53628 9.8804 8.35774 10.0423C8.1713 10.2114 7.94235 10.3717 7.64016 10.4254C7.48207 10.4535 7.32 10.4552 7.16151 10.4294C6.85843 10.3801 6.62728 10.2223 6.43836 10.0559C6.25752 9.89653 6.06037 9.67732 5.84264 9.43705L4.72925 8.20897L5.63557 7.38707L6.74897 8.61594C6.98603 8.87755 7.12974 9.03533 7.24673 9.13839C7.31033 9.19443 7.34485 9.21476 7.35823 9.22122C7.38068 9.22484 7.40352 9.22515 7.42593 9.22122C7.40522 9.22502 7.42893 9.23294 7.53583 9.136C7.65132 9.03126 7.79316 8.87139 8.02643 8.60638L11.2479 4.94763L12.1654 5.7552Z" fill="currentColor"></path></svg>`);
16750
- } else if (permission.current === "danger-full-access" || permission.current === "custom") {
16777
+ } else if ((permission.current) === "danger-full-access" || (permission.current) === "custom") {
16751
16778
  $$renderer.push("<!--[1-->");
16752
16779
  $$renderer.push(`<svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M8.20554 0.899994L14.7901 3.36857V7.01026C14.7901 12 11.0466 14.2103 8.20554 15.3C5.36446 14.2103 1.62012 12 1.62012 7.01026V3.36857L8.20554 0.899994Z" stroke="currentColor" stroke-width="1.31831" stroke-linejoin="round"></path><path d="M9.10094 4.5V8.75939H7.59888V4.5H9.10094Z" fill="currentColor"></path><path d="M9.10094 9.8114V11.5H7.59888V9.8114H9.10094Z" fill="currentColor"></path></svg>`);
16753
16780
  } else {
@@ -16768,28 +16795,39 @@ function AccessModeChip($$renderer, $$props) {
16768
16795
  });
16769
16796
  }
16770
16797
  //#endregion
16771
- //#region src/lib/components/chat/StreamingIndicator.svelte
16772
- function StreamingIndicator($$renderer, $$props) {
16798
+ //#region src/lib/components/composer/attachment/AttachmentChips.svelte
16799
+ function AttachmentChips($$renderer, $$props) {
16773
16800
  $$renderer.component(($$renderer) => {
16774
16801
  /**
16775
- * StreamingIndicator — three bouncing dots (OCI PromptInput port,
16776
- * 2026-08-24). Presentational: title in, dots out.
16777
- *
16778
- * Default anchor is the OCI textarea overlay, DSI-tuned: absolute
16779
- * against the host's RELATIVE wrapper — right edge, vertically
16780
- * centered on the host's ACTION BUTTON (bottom-anchored at half the
16781
- * button height, so the dots stay put when the textarea auto-grows;
16782
- * the row is items-end, wrapper bottom = button bottom). Streaming
16783
- * red, pointer-events none. `center` switches to inline flow for
16784
- * hosts that place the dots in the transcript themselves (e.g. the
16785
- * snippet-passing fixture).
16802
+ * AttachmentChips (task 1.4) — the pending-draft shelf. Pure
16803
+ * presentation: one chip per draft rendered above the input row. All
16804
+ * lifecycle stays in the AttachmentManager's service — removal leaves
16805
+ * as an id callback.
16786
16806
  *
16787
- * Contract pins (chat-components tests): the testid element carries
16788
- * role=status + aria-label and holds EXACTLY the three dot spans —
16789
- * no wrapper element.
16807
+ * DSH rail parity (2026-08-28, ui-attachment AttachmentRail): the
16808
+ * chip IS the draft image — a 62×62 rounded card, no name/size
16809
+ * labels (the file name survives as the img alt / lightbox alt) —
16810
+ * with a zoom-in cursor and a "Show original" tooltip; a single
16811
+ * click opens the ORIGINAL image in the ImageLightbox
16812
+ * (document-level — the floor's zoom transform would trap a fixed
16813
+ * backdrop); the remove control sits INSIDE the card's top-right
16814
+ * corner and reveals on hover/focus, staying always visible on
16815
+ * coarse pointers (touch has no hover).
16790
16816
  */
16791
- let { title = "streaming", center = false } = $$props;
16792
- $$renderer.push(`<span data-svelte="StreamingIndicator"${attr_class("streaming-indicator svelte-5t6kwy", void 0, { "centered": center })} role="status"${attr("aria-label", t(streaming))} data-testid="streaming-indicator"${attr("title", title)}><span class="dot dot-1 svelte-5t6kwy"></span> <span class="dot dot-2 svelte-5t6kwy"></span> <span class="dot dot-3 svelte-5t6kwy"></span></span>`);
16817
+ let { drafts = []} = $$props;
16818
+ if (drafts.length > 0) {
16819
+ $$renderer.push("<!--[0-->");
16820
+ $$renderer.push(`<div data-svelte="AttachmentChips" class="flex flex-wrap gap-1.5" data-testid="attachment-chips" role="list"${attr("aria-label", t(pendingattachments1))}><!--[-->`);
16821
+ const each_array = ensure_array_like(drafts);
16822
+ for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
16823
+ let draft = each_array[$$index];
16824
+ $$renderer.push(`<div class="group relative" role="listitem" data-testid="attachment-chip"><button type="button" class="block h-[62px] w-[62px] cursor-zoom-in overflow-hidden rounded-[16px] border border-slate-200 bg-white" title="Show original" data-testid="attachment-chip-open"><img${attr("src", draft.previewUrl)}${attr("alt", draft.file.name || "image draft")} class="h-full w-full object-cover" data-testid="attachment-chip-thumb"/></button> <button type="button"${attr("aria-label", `Remove attachment ${stringify(draft.file.name || "image")}`)} data-testid="attachment-chip-remove" class="pointer-coarse:opacity-100 absolute top-1 right-1 z-10 flex h-[18px] w-[18px] items-center justify-center rounded-full bg-slate-800/90 text-[10px] leading-none text-white opacity-0 transition-opacity duration-200 group-hover:opacity-100 focus-visible:opacity-100">×</button></div>`);
16825
+ }
16826
+ $$renderer.push(`<!--]--></div>`);
16827
+ } else $$renderer.push("<!--[-1-->");
16828
+ $$renderer.push(`<!--]--> `);
16829
+ $$renderer.push("<!--[-1-->");
16830
+ $$renderer.push(`<!--]-->`);
16793
16831
  });
16794
16832
  }
16795
16833
  //#endregion
@@ -16910,7 +16948,7 @@ function createAttachmentService(limits = DEFAULT_IMAGE_LIMITS) {
16910
16948
  };
16911
16949
  }
16912
16950
  //#endregion
16913
- //#region src/lib/components/chat/AttachmentManager.svelte
16951
+ //#region src/lib/components/composer/attachment/AttachmentManager.svelte
16914
16952
  function AttachmentManager($$renderer, $$props) {
16915
16953
  $$renderer.component(($$renderer) => {
16916
16954
  /**
@@ -16981,42 +17019,6 @@ function AttachmentManager($$renderer, $$props) {
16981
17019
  });
16982
17020
  }
16983
17021
  //#endregion
16984
- //#region src/lib/components/chat/AttachmentChips.svelte
16985
- function AttachmentChips($$renderer, $$props) {
16986
- $$renderer.component(($$renderer) => {
16987
- /**
16988
- * AttachmentChips (task 1.4) — the pending-draft shelf. Pure
16989
- * presentation: one chip per draft rendered above the input row. All
16990
- * lifecycle stays in the AttachmentManager's service — removal leaves
16991
- * as an id callback.
16992
- *
16993
- * DSH rail parity (2026-08-28, ui-attachment AttachmentRail): the
16994
- * chip IS the draft image — a 62×62 rounded card, no name/size
16995
- * labels (the file name survives as the img alt / lightbox alt) —
16996
- * with a zoom-in cursor and a "Show original" tooltip; a single
16997
- * click opens the ORIGINAL image in the ImageLightbox
16998
- * (document-level — the floor's zoom transform would trap a fixed
16999
- * backdrop); the remove control sits INSIDE the card's top-right
17000
- * corner and reveals on hover/focus, staying always visible on
17001
- * coarse pointers (touch has no hover).
17002
- */
17003
- let { drafts = []} = $$props;
17004
- if (drafts.length > 0) {
17005
- $$renderer.push("<!--[0-->");
17006
- $$renderer.push(`<div data-svelte="AttachmentChips" class="flex flex-wrap gap-1.5" data-testid="attachment-chips" role="list"${attr("aria-label", t(pendingattachments1))}><!--[-->`);
17007
- const each_array = ensure_array_like(drafts);
17008
- for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
17009
- let draft = each_array[$$index];
17010
- $$renderer.push(`<div class="group relative" role="listitem" data-testid="attachment-chip"><button type="button" class="block h-[62px] w-[62px] cursor-zoom-in overflow-hidden rounded-[16px] border border-slate-200 bg-white" title="Show original" data-testid="attachment-chip-open"><img${attr("src", draft.previewUrl)}${attr("alt", draft.file.name || "image draft")} class="h-full w-full object-cover" data-testid="attachment-chip-thumb"/></button> <button type="button"${attr("aria-label", `Remove attachment ${stringify(draft.file.name || "image")}`)} data-testid="attachment-chip-remove" class="pointer-coarse:opacity-100 absolute top-1 right-1 z-10 flex h-[18px] w-[18px] items-center justify-center rounded-full bg-slate-800/90 text-[10px] leading-none text-white opacity-0 transition-opacity duration-200 group-hover:opacity-100 focus-visible:opacity-100">×</button></div>`);
17011
- }
17012
- $$renderer.push(`<!--]--></div>`);
17013
- } else $$renderer.push("<!--[-1-->");
17014
- $$renderer.push(`<!--]--> `);
17015
- $$renderer.push("<!--[-1-->");
17016
- $$renderer.push(`<!--]-->`);
17017
- });
17018
- }
17019
- //#endregion
17020
17022
  //#region src/lib/components/card/CommandHelpCard.svelte
17021
17023
  function CommandHelpCard($$renderer, $$props) {
17022
17024
  $$renderer.component(($$renderer) => {
@@ -17029,7 +17031,7 @@ function CommandHelpCard($$renderer, $$props) {
17029
17031
  * COMMAND_HELP copy) and host vocabulary (`/plan ?`, `/dsh-doc ?` —
17030
17032
  * the catalog row's own description/hint/whenToUse, nothing invented).
17031
17033
  *
17032
- * Presentational: the view in, nothing out — PromptInput owns the
17034
+ * Presentational: the view in, nothing out — Composer owns the
17033
17035
  * detection (command-help.ts), the Esc dismiss, and the Enter guard.
17034
17036
  *
17035
17037
  * Floating geometry (SuggestStrip parity): absolute above the textarea
@@ -18226,7 +18228,7 @@ function PromptsManagerDialog($$renderer, $$props) {
18226
18228
  * the next trigger).
18227
18229
  *
18228
18230
  * Portal contract (BC-7): the whole modal mounts in a host div that
18229
- * PromptInput portals to document.body — the panel floor's CSS zoom
18231
+ * Composer portals to document.body — the panel floor's CSS zoom
18230
18232
  * becomes the containing block for position:fixed, so any fixed UI
18231
18233
  * rendered inside the scaled panel canvas is trapped (ADR: "fixed UI
18232
18234
  * escapes the zoom trap"). The host renders this component inside a
@@ -18384,8 +18386,8 @@ function parseCommand(text) {
18384
18386
  * /new ? /permission ? @<session-id> ?
18385
18387
  *
18386
18388
  * Pure detection + the per-command help copy; the popup is
18387
- * CommandHelpCard.svelte, hosted by PromptInput beside the Suggest Strip.
18388
- * Submit is guarded upstream (PromptInput): a `?` help line never reaches
18389
+ * CommandHelpCard.svelte, hosted by Composer beside the Suggest Strip.
18390
+ * Submit is guarded upstream (Composer): a `?` help line never reaches
18389
18391
  * parseCommand's execute path, so `/permission ?` can never hit the host
18390
18392
  * wire as a bogus preset and `/new foo` keeps its existing usage error.
18391
18393
  *
@@ -18723,7 +18725,7 @@ function hostHelpCardView(text, commands, skills) {
18723
18725
  //#region src/lib/utils/draft-prefs.ts
18724
18726
  /**
18725
18727
  * Composer draft persistence — the per-session prompt draft survives HMR
18726
- * strikes and full reloads (2026-08-30): PromptInput saves here debounced
18728
+ * strikes and full reloads (2026-08-30): Composer saves here debounced
18727
18729
  * while the operator types, restores at mount with the caret at the end,
18728
18730
  * and clears the moment the draft empties (send, macro run-accept) so a
18729
18731
  * sent prompt never resurrects.
@@ -18836,11 +18838,11 @@ function getLensMode() {
18836
18838
  return getContext(PANEL_LENS_KEY) ?? false;
18837
18839
  }
18838
18840
  //#endregion
18839
- //#region src/lib/components/chat/PromptInput.svelte
18840
- function PromptInput($$renderer, $$props) {
18841
+ //#region src/lib/components/composer/Composer.svelte
18842
+ function Composer($$renderer, $$props) {
18841
18843
  $$renderer.component(($$renderer) => {
18842
18844
  /**
18843
- * PromptInput — the send surface (PRD §3.4: input → Cancel/dots UX).
18845
+ * Composer — the send surface (PRD §3.4: input → Cancel/dots UX).
18844
18846
  *
18845
18847
  * Contract (BC-3 + rapid double-submit lock):
18846
18848
  * - Enter submits, Shift+Enter newlines
@@ -19376,13 +19378,13 @@ function PromptInput($$renderer, $$props) {
19376
19378
  let $$settled = true;
19377
19379
  let $$inner_renderer;
19378
19380
  function $$render_inner($$renderer) {
19379
- $$renderer.push(`<div data-svelte="PromptInput" class="flex flex-col gap-1.5" data-testid="prompt-input">`);
19381
+ $$renderer.push(`<div data-svelte="Composer" class="flex flex-col gap-1.5" data-testid="prompt-input">`);
19380
19382
  AttachmentChips($$renderer, {
19381
19383
  drafts});
19382
19384
  $$renderer.push(`<!----> <div class="flex items-end gap-2"><div class="flex shrink-0 flex-col items-center gap-1">`);
19383
19385
  if (sessionId !== void 0) {
19384
19386
  $$renderer.push("<!--[0-->");
19385
- $$renderer.push(`<button type="button" data-testid="prompt-sync-check"${attr("aria-pressed", syncChecked())}${attr("title", t(synccomposer1))}${attr_class("prompt-sync-check flex h-8 w-8 items-center justify-center rounded-md text-slate-400 transition-colors hover:bg-slate-100 hover:text-slate-600 disabled:cursor-not-allowed disabled:opacity-50 svelte-1gevkmd", void 0, { "on": syncChecked() })}${attr("disabled", lens, true)}>`);
19387
+ $$renderer.push(`<button type="button" data-testid="prompt-sync-check"${attr("aria-pressed", syncChecked())}${attr("title", t(synccomposer1))}${attr_class("prompt-sync-check flex h-8 w-8 items-center justify-center rounded-md text-slate-400 transition-colors hover:bg-slate-100 hover:text-slate-600 disabled:cursor-not-allowed disabled:opacity-50 svelte-1rspv9d", void 0, { "on": syncChecked() })}${attr("disabled", lens, true)}>`);
19386
19388
  if (syncChecked()) {
19387
19389
  $$renderer.push("<!--[0-->");
19388
19390
  Square_check($$renderer, { size: 16 });
@@ -19479,7 +19481,7 @@ function PromptInput($$renderer, $$props) {
19479
19481
  $$renderer.push(`<!--]--></div> <div class="flex shrink-0 flex-col items-center justify-end gap-1">`);
19480
19482
  if (isStreaming) {
19481
19483
  $$renderer.push("<!--[0-->");
19482
- $$renderer.push(`<button type="button" data-testid="cancel-button" class="cancel-btn flex h-8 w-8 shrink-0 items-center justify-center rounded-md bg-red-500 text-white transition-[background-color,transform] hover:bg-red-600 hover:scale-105 disabled:cursor-not-allowed disabled:opacity-30 svelte-1gevkmd"${attr("disabled", locked(), true)}${attr("title", t(stopstreaming1))}${attr("aria-label", t(stopstreaming1))}>`);
19484
+ $$renderer.push(`<button type="button" data-testid="cancel-button" class="cancel-btn flex h-8 w-8 shrink-0 items-center justify-center rounded-md bg-red-500 text-white transition-[background-color,transform] hover:bg-red-600 hover:scale-105 disabled:cursor-not-allowed disabled:opacity-30 svelte-1rspv9d"${attr("disabled", locked(), true)}${attr("title", t(stopstreaming1))}${attr("aria-label", t(stopstreaming1))}>`);
19483
19485
  Square($$renderer, {
19484
19486
  size: 14,
19485
19487
  fill: "currentColor"
@@ -19487,7 +19489,7 @@ function PromptInput($$renderer, $$props) {
19487
19489
  $$renderer.push(`<!----></button>`);
19488
19490
  } else {
19489
19491
  $$renderer.push("<!--[-1-->");
19490
- $$renderer.push(`<button type="button"${attr("disabled", disabled(), true)} data-testid="send-button" class="send-btn flex h-8 w-8 shrink-0 items-center justify-center rounded-md bg-blue-600 text-white transition-colors hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-30 svelte-1gevkmd"${attr("title", t(sendmessage1))}${attr("aria-label", t(sendmessage1))}>`);
19492
+ $$renderer.push(`<button type="button"${attr("disabled", disabled(), true)} data-testid="send-button" class="send-btn flex h-8 w-8 shrink-0 items-center justify-center rounded-md bg-blue-600 text-white transition-colors hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-30 svelte-1rspv9d"${attr("title", t(sendmessage1))}${attr("aria-label", t(sendmessage1))}>`);
19491
19493
  Arrow_up($$renderer, { size: 18 });
19492
19494
  $$renderer.push(`<!----></button>`);
19493
19495
  }
@@ -19546,7 +19548,7 @@ function ConversationFooter($$renderer, $$props) {
19546
19548
  /**
19547
19549
  * ConversationFooter — the conversation page's send surface wrapper
19548
19550
  * (extracted from the page, 2026-08-23): the bottom bar hosting
19549
- * PromptInput. Pure layout shell — every input prop passes through
19551
+ * Composer. Pure layout shell — every input prop passes through
19550
19552
  * unchanged; the send/cancel intents and page state stay page-owned.
19551
19553
  *
19552
19554
  * Focus tint (2026-08-28): on the panel floor the focused panel's
@@ -19565,7 +19567,7 @@ function ConversationFooter($$renderer, $$props) {
19565
19567
  * hold: membership is the more specific "aimed at" signal. */
19566
19568
  const tintClass = derived(() => isSyncChecked(sessionId) ? "bg-[linear-gradient(90deg,#E6F4D7,#FDF5E6_65%,#FEF9EF)]" : focused ? "bg-[#FDF5E6]" : "bg-white");
19567
19569
  $$renderer.push(`<footer data-svelte="ConversationFooter"${attr_class(`border-t border-slate-200 px-1 py-1 ${tintClass()}`)} data-testid="conversation-footer"${attr("data-focused", focused ? "true" : "false")}><div class="mx-auto max-w-3xl">`);
19568
- PromptInput($$renderer, {
19570
+ Composer($$renderer, {
19569
19571
  onsubmit,
19570
19572
  isStreaming,
19571
19573
  sending,
@@ -20043,8 +20045,45 @@ function hasDotDotSegment(path) {
20043
20045
  * Returns null when the path escapes the workspace ('..' anywhere) or
20044
20046
  * normalizes to empty.
20045
20047
  */
20048
+ /**
20049
+ * Split a line anchor (#L139, #L139-L150) off a file-link href. The
20050
+ * anchor is a DISPLAY hint for the file panel, never part of the path —
20051
+ * letting it ride made the host read 404 (workspace-file/not-found,
20052
+ * RCA 2026-09-26). Returns the bare path plus the parsed 1-based range
20053
+ * (null when absent or malformed — a bad anchor degrades to no target,
20054
+ * it never breaks the open).
20055
+ */
20056
+ function parseFileLinkHref(href) {
20057
+ const value = href.trim();
20058
+ const hash = value.indexOf("#");
20059
+ const raw = hash === -1 ? value : value.slice(0, hash);
20060
+ const anchor = hash === -1 ? "" : value.slice(hash + 1);
20061
+ let lines = null;
20062
+ const single = anchor.match(/^L?(\d+)$/);
20063
+ const range = anchor.match(/^L?(\d+)-L?(\d+)$/);
20064
+ if (single) {
20065
+ const n = Number(single[1]);
20066
+ if (n >= 1) lines = {
20067
+ start: n,
20068
+ end: n
20069
+ };
20070
+ } else if (range) {
20071
+ const s = Number(range[1]);
20072
+ const e = Number(range[2]);
20073
+ if (s >= 1 && e >= s) lines = {
20074
+ start: s,
20075
+ end: e
20076
+ };
20077
+ }
20078
+ return {
20079
+ path: normalizeFileLinkPath(raw) ?? "",
20080
+ lines
20081
+ };
20082
+ }
20046
20083
  function normalizeFileLinkPath(href) {
20047
20084
  let value = href.trim().replace(/^\.\//, "").replace(/\/{2,}/g, "/");
20085
+ const hash = value.indexOf("#");
20086
+ if (hash !== -1) value = value.slice(0, hash);
20048
20087
  if (value.startsWith("/")) value = value.slice(1);
20049
20088
  if (value === "" || hasDotDotSegment(value)) return null;
20050
20089
  return value;
@@ -20057,7 +20096,7 @@ function normalizeFileLinkPath(href) {
20057
20096
  */
20058
20097
  async function workspaceFileExists(sessionId, path, fetchImpl = fetch) {
20059
20098
  const clean = path.split("#")[0];
20060
- if (clean === "") return false;
20099
+ if (clean === "" || hasDotDotSegment(clean)) return false;
20061
20100
  const slash = clean.lastIndexOf("/");
20062
20101
  const dir = slash === -1 ? "" : clean.slice(0, slash);
20063
20102
  const base = slash === -1 ? clean : clean.slice(slash + 1);
@@ -20363,7 +20402,7 @@ function MessageBubble($$renderer, $$props) {
20363
20402
  * stamp mount at the content edge (hover-reveal family, OCI
20364
20403
  * placement); children-only mounts (context chips) get neither.
20365
20404
  */
20366
- let { role, skin, text, time, showSave = true, children } = $$props;
20405
+ let { role, skin, text, time, showSave = true, children, onFileLink } = $$props;
20367
20406
  /** Raw ⇄ rendered flip state — owned here, wired to ToolsMessage. */
20368
20407
  let showRaw = false;
20369
20408
  /** Bubble element ref — capture target for the canvas copy button. */
@@ -20382,7 +20421,8 @@ function MessageBubble($$renderer, $$props) {
20382
20421
  $$renderer.push("<!--[-1-->");
20383
20422
  MarkdownContent($$renderer, {
20384
20423
  content: text,
20385
- hideToggle: true
20424
+ hideToggle: true,
20425
+ onFileLink
20386
20426
  });
20387
20427
  }
20388
20428
  $$renderer.push(`<!--]-->`);
@@ -20508,7 +20548,7 @@ function PromptBubble($$renderer, $$props) {
20508
20548
  * the row, OCI placement). Assistant responses live in AssistantTurn —
20509
20549
  * this bubble is user-side only.
20510
20550
  */
20511
- let { text, time, tone = "prompt", imageRefs = [], sessionId, children } = $$props;
20551
+ let { text, time, tone = "prompt", imageRefs = [], sessionId, children, onFileLink } = $$props;
20512
20552
  const skin = derived(() => tone === "context" ? "bg-accent-blue/10 border-accent-blue/20" : "bg-accent-blue/15 border-accent-blue/20");
20513
20553
  $$renderer.push(`<div data-svelte="PromptBubble" class="flex w-full min-w-0 flex-col items-end gap-1.5">`);
20514
20554
  if (imageRefs.length > 0 && sessionId !== void 0) {
@@ -20524,6 +20564,7 @@ function PromptBubble($$renderer, $$props) {
20524
20564
  skin: skin(),
20525
20565
  text,
20526
20566
  time,
20567
+ onFileLink,
20527
20568
  children: ($$renderer) => {
20528
20569
  if (children) {
20529
20570
  $$renderer.push("<!--[0-->");
@@ -23441,6 +23482,7 @@ function ConversationScrollArea($$renderer, $$props) {
23441
23482
  tone: group.kind === "prompt" ? "prompt" : "context",
23442
23483
  imageRefs: group.kind === "prompt" ? group.entry.imageRefs : void 0,
23443
23484
  sessionId,
23485
+ onFileLink,
23444
23486
  children: ($$renderer) => {
23445
23487
  if (group.kind === "prompt") {
23446
23488
  $$renderer.push("<!--[0-->");
@@ -25907,10 +25949,10 @@ function ConversationPanel($$renderer, $$props) {
25907
25949
  olderInFlight = null;
25908
25950
  }
25909
25951
  }
25910
- /** Wave 2: images arrive serialized from the composer (PromptInput owns
25952
+ /** Wave 2: images arrive serialized from the composer (Composer owns
25911
25953
  * the only base64 moment — serialize-at-submit, BC-A2) and ride the
25912
25954
  * widened submit; the boolean admits/denies draft clearing (BC-A3). */
25913
- /** Wave 2: images arrive serialized from the composer (PromptInput owns
25955
+ /** Wave 2: images arrive serialized from the composer (Composer owns
25914
25956
  * the only base64 moment — serialize-at-submit, BC-A2) and ride the
25915
25957
  * widened submit; the boolean admits/denies draft clearing (BC-A3).
25916
25958
  * Commands delegate to the shared executor (Prompt Macro W1 1.2 — one
@@ -26130,7 +26172,7 @@ function ConversationPanel($$renderer, $$props) {
26130
26172
  if (!row) return;
26131
26173
  startMacro(row, true);
26132
26174
  }
26133
- /** Mirror of the composer's strip rows — refreshed via PromptInput's
26175
+ /** Mirror of the composer's strip rows — refreshed via Composer's
26134
26176
  * onrows callback (props-only contract kept: the panel never reaches
26135
26177
  * into the component's internals). The accepted index resolves
26136
26178
  * against the rows the strip showed at accept time. */
@@ -27857,7 +27899,7 @@ function WorkspaceFilePanel($$renderer, $$props) {
27857
27899
  * outside-workspace, too-large, not-text, not-regular-file.
27858
27900
  */
27859
27901
  /** The read receipt (api/dsh/workspace-file body, DshWorkspaceFileText). */
27860
- let { sessionId, path, root, view = "edit", onviewchange, onclose } = $$props;
27902
+ let { sessionId, path, root, view = "edit", onviewchange, onclose, highlightLines = null, onhighlightdone } = $$props;
27861
27903
  let viewOverride = null;
27862
27904
  const activeView = derived(() => viewOverride ?? view);
27863
27905
  let tab = "preview";
@@ -28456,6 +28498,9 @@ function WorkspaceExplorerPanel($$renderer, $$props) {
28456
28498
  pulseSource = null;
28457
28499
  }
28458
28500
  onDestroy(closePulse);
28501
+ /** The parked #L anchor target (transient, never persisted) — handed to
28502
+ * the active file panel and cleared once it reports the highlight done. */
28503
+ let lineTarget = null;
28459
28504
  function startSplitDrag(event) {}
28460
28505
  const splitPct = derived(() => clampTreePct(treePct));
28461
28506
  $$renderer.push(`<div data-svelte="WorkspaceExplorerPanel" data-testid="workspace-explorer" class="split svelte-v4uero"${attr_style(`--tree-basis: ${stringify(splitPct())}%; --file-basis: ${stringify(100 - splitPct())}%`)}>`);
@@ -28495,6 +28540,8 @@ function WorkspaceExplorerPanel($$renderer, $$props) {
28495
28540
  sessionId,
28496
28541
  path: activeFile,
28497
28542
  root,
28543
+ highlightLines: lineTarget,
28544
+ onhighlightdone: () => lineTarget = null,
28498
28545
  onclose: () => {}
28499
28546
  });
28500
28547
  } else $$renderer.push("<!--[-1-->");
@@ -29206,18 +29253,18 @@ function _page($$renderer, $$props) {
29206
29253
  * session's explorer, which opens/focuses a tab. No open explorer
29207
29254
  * ⇒ the intent drops (the browsing surface that opens files IS the
29208
29255
  * explorer; the floor keeps conversations only). */
29209
- function openWorkspaceFile(sessionId, path) {
29256
+ function openWorkspaceFile(sessionId, path, lines) {
29210
29257
  const host = sessionWorkspaceExplorer(sessionId);
29211
- if (host) publishFileIntent(host.id, path);
29258
+ if (host) publishFileIntent(host.id, path, lines);
29212
29259
  }
29213
29260
  /** File Link Intent (ADR 2026-09-25 D3): a transcript file link publishes
29214
29261
  * ONLY after the tree route proves the file exists inside the session's
29215
29262
  * workspace — the gate lives in the shared util; anything else drops the
29216
29263
  * click. No navigation ever happens. */
29217
29264
  async function openFileLinkFromMarkdown(sessionId, rawHref) {
29218
- const path = normalizeFileLinkPath(rawHref);
29219
- console.log("[FLINK] click", sessionId, rawHref, "->", path);
29220
- if (path === null) return;
29265
+ const { path, lines } = parseFileLinkHref(rawHref);
29266
+ console.log("[FLINK] click", sessionId, rawHref, "->", path, lines);
29267
+ if (path === "") return;
29221
29268
  const exists = await workspaceFileExists(sessionId, path);
29222
29269
  console.log("[FLINK] exists:", exists);
29223
29270
  if (!exists) return;
@@ -29226,7 +29273,7 @@ function _page($$renderer, $$props) {
29226
29273
  if (!root) return;
29227
29274
  openWorkspaceExplorer(sessionId, root);
29228
29275
  }
29229
- openWorkspaceFile(sessionId, path);
29276
+ openWorkspaceFile(sessionId, path, lines);
29230
29277
  }
29231
29278
  const seedData = page.data;
29232
29279
  const seedCold = seedData && typeof seedData.sessionId === "string" && Array.isArray(seedData.entries) ? {
@@ -29269,11 +29316,13 @@ function _page($$renderer, $$props) {
29269
29316
  let coldCache = {};
29270
29317
  let pendingFileIntents = {};
29271
29318
  let fileIntentSeq = 0;
29272
- /** Publish a file intent to an explorer panel and focus it. */
29273
- function publishFileIntent(explorerId, path) {
29319
+ /** Publish a file intent to an explorer panel and focus it. `lines` is
29320
+ * the optional #L anchor target — display metadata, not persisted. */
29321
+ function publishFileIntent(explorerId, path, lines) {
29274
29322
  pendingFileIntents[explorerId] = {
29275
29323
  path,
29276
- nonce: ++fileIntentSeq
29324
+ nonce: ++fileIntentSeq,
29325
+ lines: lines ?? null
29277
29326
  };
29278
29327
  selectedPanelId = explorerId;
29279
29328
  }
@@ -29809,4 +29858,4 @@ function _page($$renderer, $$props) {
29809
29858
  }
29810
29859
 
29811
29860
  export { _page as default };
29812
- //# sourceMappingURL=_page.svelte.js-Be_p_N6K.js.map
29861
+ //# sourceMappingURL=_page.svelte.js-Cl5dMg9t.js.map