// Copyright (c) 2026 Zimeng-Luo. MIT License. // Generated by scripts/build.cjs. Browser artifact: DSH classic-script module factory. window.__ModuleLoader__.load({ id: "dsh-source-fold", factory: function (require) { "use strict"; const React = require("react"); const ReactDOM = require("react-dom"); function effortChoices(model) { const levels = model?.reasoning?.efforts; if (!Array.isArray(levels)) return []; const seen = new Set(); const supported = levels.filter(level => { if (!level || typeof level.id !== "string" || !level.id || seen.has(level.id)) return false; seen.add(level.id); return true; }).map(level => ({ id: level.id, name: level.name || level.id })); return supported.length ? [{ id: null, name: "Default" }, ...supported] : []; } function routeKey(selection) { return selection ? JSON.stringify([selection.provider, selection.model]) : ""; } function currentModel(state) { const group = (state.groups || []).find(group => group.id === state.current?.provider); const model = group?.models.find(model => model.id === state.current?.model); return model ? { group, model } : null; } function effortIndex(model, current, preference) { const choices = effortChoices(model); if (!choices.length) return 0; const effective = current?.reasoningEffort ?? model.reasoning.defaultEffort; if (preference?.key === routeKey(current)) { const preferred = preference.id ?? model.reasoning.defaultEffort; if (preferred === effective) { const index = choices.findIndex(choice => choice.id === preference.id); if (index >= 0) return index; } } if (current?.reasoningEffort === undefined) return 0; return Math.max(0, choices.findIndex(choice => choice.id === current.reasoningEffort)); } function selectionForEffort(current, choice) { if (!current || !choice) throw new Error("没有可用的模型或思考档位"); const selection = { provider: current.provider, model: current.model }; if (choice.id !== null) selection.reasoningEffort = choice.id; return selection; } function matchesQuery(query, values) { const tokens = query.trim().toLocaleLowerCase().split(/\s+/).filter(Boolean); const text = values.filter(Boolean).join(" ").toLocaleLowerCase(); return tokens.every(token => text.includes(token)); } function panelMetrics(page, count, adjustable, anchor, viewport, noticeCount = 0) { const scale = Math.max(.85, Math.min(1.15, Number(viewport.uiScale) || 1)); const margin = Math.min(12, Math.max(0, viewport.width / 8)); const originLeft = Number(viewport.left) || 0; const originTop = Number(viewport.top) || 0; const availableWidth = Math.max(1, viewport.width - 2 * margin); const preferredWidth = (page === 0 ? 240 : 304) * scale; const composerLimit = viewport.composerWidth > 0 ? Math.max((page === 0 ? 208 : 248) * scale, viewport.composerWidth * (page === 0 ? .48 : .70)) : preferredWidth; const width = Math.min(preferredWidth, composerLimit, availableWidth); const wanted = (page === 0 ? (adjustable ? 116 : 86) + Math.min(1, noticeCount) * 44 : 100 + Math.max(1, count) * (page === 1 ? 60 : 48) + Math.min(2, noticeCount) * 44) * scale; const gap = 8 * scale; const bottomEdge = originTop + viewport.height; const anchorTop = Math.max(originTop + margin + gap, Math.min(anchor.top, bottomEdge - margin - gap)); const anchorBottom = Math.max(originTop + margin + gap, Math.min(anchor.bottom, bottomEdge - margin - gap)); const above = Math.max(0, anchorTop - originTop - margin - gap); const below = Math.max(0, bottomEdge - anchorBottom - margin - gap); const side = above >= Math.min(wanted, 210 * scale) || above >= below ? "above" : "below"; const heightLimit = page === 0 ? 230 * scale : Math.min(420 * scale, viewport.height * .62); const height = Math.max(1, Math.min(wanted, heightLimit, side === "above" ? above : below)); const left = Math.max(originLeft + margin, Math.min(anchor.right - width, originLeft + viewport.width - width - margin)); return { width, height, left, side, scale, ...(side === "above" ? { bottom: (viewport.layoutHeight || viewport.height) - anchorTop + gap } : { top: anchorBottom + gap }) }; } const PINNED_SOURCES_KEY = "dsh-source-fold:pinned-sources:v1"; function normalizePinnedSources(value) { return Array.isArray(value) ? [...new Set(value.filter(id => typeof id === "string" && id.length > 0))] : []; } function pinnedSourcesFirst(groups, ids) { const pinned = new Set(ids); return [...groups.filter(group => pinned.has(group.id)), ...groups.filter(group => !pinned.has(group.id))]; } function createPinnedSourcesStore() { function read() { try { const raw = window.localStorage.getItem(PINNED_SOURCES_KEY); try { return normalizePinnedSources(raw === null ? [] : JSON.parse(raw)); } catch { return []; } } catch { return null; } } let snapshot = { ids: read() || [], persisted: true }; const listeners = new Set(); const emit = () => { for (const listener of listeners) listener(); }; function refresh(event) { if (event.key !== null && event.key !== PINNED_SOURCES_KEY) return; const ids = read(); if (ids === null || (snapshot.persisted && JSON.stringify(ids) === JSON.stringify(snapshot.ids))) return; snapshot = { ids, persisted: true }; emit(); } return { getSnapshot: () => snapshot, subscribe(listener) { if (!listeners.size) { window.addEventListener("storage", refresh); refresh({ key: PINNED_SOURCES_KEY }); } listeners.add(listener); return () => { listeners.delete(listener); if (!listeners.size) window.removeEventListener("storage", refresh); }; }, toggle(id) { if (typeof id !== "string" || !id) return; const previous = snapshot.persisted ? (read() || snapshot.ids) : snapshot.ids; const ids = previous.includes(id) ? previous.filter(value => value !== id) : [...previous, id]; let persisted = false; try { window.localStorage.setItem(PINNED_SOURCES_KEY, JSON.stringify(ids)); persisted = true; } catch {} snapshot = { ids, persisted }; emit(); } }; } function createIsland(React, ReactDOM) { const { createElement: h, useState, useRef, useEffect, useLayoutEffect, useSyncExternalStore, useId } = React; const pinnedSourcesStore = createPinnedSourcesStore(); function Icon({ kind, size = 18, className = "" }) { const paths = { chevron: "m9 5 7 7-7 7", back: "m15 5-7 7 7 7", check: "m5 12 4 4L19 6", models: "M4 4h6v6H4zM14 4h6v6h-6zM4 14h6v6H4zM14 14h6v6h-6z", search: "m20 20-4.5-4.5M17 10a7 7 0 1 1-14 0 7 7 0 0 1 14 0Z", close: "m6 6 12 12M18 6 6 18", pin: "M8 3h8l-1 5 3 3v2H6v-2l3-3-1-5ZM12 13v8" }; return h("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.7, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, className, style: { "--dsf-icon-size": size + "px" } }, h("path", { d: paths[kind] || paths.models })); } function ModelIsland({ controller, locked, sessionKey }) { const state = useSyncExternalStore( listener => controller.store.subscribe(listener), () => controller.store.getSnapshot() ); const pins = useSyncExternalStore(pinnedSourcesStore.subscribe, pinnedSourcesStore.getSnapshot); const [stage, setStage] = useState("closed"); const [page, setPage] = useState(0); const [sourceId, setSourceId] = useState(null); const [sourceQuery, setSourceQuery] = useState(""); const [modelQuery, setModelQuery] = useState(""); const [localError, setLocalError] = useState(""); const [saving, setSaving] = useState(false); const [draft, setDraft] = useState(null); const [preference, setPreference] = useState(null); const [position, setPosition] = useState(null); const rootRef = useRef(null); const triggerRef = useRef(null); const panelRef = useRef(null); const draftRef = useRef(null); const sendingRef = useRef(false); const aliveRef = useRef(true); const restoreRef = useRef(false); const previousPageRef = useRef(0); const id = useId(); const present = stage !== "closed"; const found = currentModel(state); const choices = effortChoices(found?.model); const adjustable = choices.length > 1; const currentKey = routeKey(state.current); const confirmedIndex = effortIndex(found?.model, state.current, preference); const sliderIndex = draft?.key === currentKey ? draft.index : confirmedIndex; const activeChoice = choices[sliderIndex] || choices[0]; const modelName = found?.model.name || (state.status === "loading" ? "加载模型…" : "选择模型"); const busy = Boolean(locked || saving || state.pending); const error = localError || state.error; const groups = state.groups || []; const source = groups.find(group => group.id === sourceId); const sources = pinnedSourcesFirst(groups.filter(group => matchesQuery(sourceQuery, [group.name, group.id, ...group.models.map(model => model.name)]) ), pins.ids); const models = (source?.models || []).filter(model => matchesQuery(modelQuery, [model.name, model.id]) ); const failures = state.failures || []; const load = () => { setLocalError(""); Promise.resolve().then(() => controller.load()).catch(reason => { if (aliveRef.current) setLocalError(reason?.message || String(reason)); }); }; const close = (restoreFocus = false) => { if (!present) return; restoreRef.current = restoreFocus; setStage("closing"); draftRef.current = null; setDraft(null); }; const navigate = next => { if (next === 1 && page === 0) setSourceQuery(""); if (next === 2) setModelQuery(""); setPage(next); }; const back = () => { if (page === 2) navigate(1); else if (page === 1) navigate(0); else close(true); }; const open = () => { if (stage !== "closed" && stage !== "closing") { close(true); return; } setPage(0); setSourceId(null); setSourceQuery(""); setModelQuery(""); setLocalError(""); setStage("opening"); load(); }; useEffect(() => { aliveRef.current = true; load(); return () => { aliveRef.current = false; }; }, [controller]); useEffect(() => { if (stage === "opening") { const frame = requestAnimationFrame(() => setStage("open")); return () => cancelAnimationFrame(frame); } if (stage === "closing") { const timer = setTimeout(() => { setStage("closed"); setPosition(null); if (restoreRef.current) triggerRef.current?.focus({ preventScroll: true }); }, 240); return () => clearTimeout(timer); } }, [stage]); useEffect(() => { draftRef.current = null; setDraft(null); setLocalError(""); }, [currentKey]); useEffect(() => { if (page === 2 && !source && state.status !== "loading") setPage(1); }, [page, source, state.status]); useEffect(() => { if (locked && present) close(false); }, [locked]); useEffect(() => { if (!present) return; const outside = event => { if (!rootRef.current?.contains(event.target) && !panelRef.current?.contains(event.target)) close(false); }; document.addEventListener("pointerdown", outside, true); return () => document.removeEventListener("pointerdown", outside, true); }, [present]); const count = page === 1 ? sources.length : models.length; useLayoutEffect(() => { if (!present) return; const place = () => { const anchor = triggerRef.current?.getBoundingClientRect(); if (!anchor) return; const visible = window.visualViewport; const composer = rootRef.current?.closest("[data-composer-card]"); const fontSize = parseFloat(window.getComputedStyle(triggerRef.current).fontSize) || 13; const next = panelMetrics(page, count, adjustable, anchor, { width: visible?.width || window.innerWidth, height: visible?.height || window.innerHeight, left: visible?.offsetLeft || 0, top: visible?.offsetTop || 0, layoutHeight: window.innerHeight, composerWidth: composer?.getBoundingClientRect().width, uiScale: fontSize / 13 }, (error ? 1 : 0) + (page === 1 ? failures.length + (pins.persisted ? 0 : 1) : 0)); setPosition(previous => JSON.stringify(previous) === JSON.stringify(next) ? previous : next); }; place(); window.addEventListener("resize", place); window.addEventListener("scroll", place, true); const visible = window.visualViewport; visible?.addEventListener("resize", place); visible?.addEventListener("scroll", place); const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(place); if (triggerRef.current) observer?.observe(triggerRef.current); const composer = rootRef.current?.closest("[data-composer-card]"); if (composer) observer?.observe(composer); return () => { observer?.disconnect(); window.removeEventListener("resize", place); window.removeEventListener("scroll", place, true); visible?.removeEventListener("resize", place); visible?.removeEventListener("scroll", place); }; }, [present, page, count, adjustable, error, failures.length, pins.persisted]); useLayoutEffect(() => { if (stage !== "open") return; const activePage = panelRef.current?.querySelector('[data-page="' + page + '"]'); const backwards = page < previousPageRef.current; previousPageRef.current = page; const rows = activePage?.querySelectorAll("[data-source-id]"); const returnSource = backwards && page === 1 ? [...(rows || [])].find(row => row.getAttribute("data-source-id") === sourceId) : null; const target = returnSource || activePage?.querySelector(page === 0 ? ".dsf-model-title" : "input"); target?.focus({ preventScroll: true }); }, [stage, page]); async function submit(selection, nextPreference, onSuccess) { if (busy || sendingRef.current) return; sendingRef.current = true; setSaving(true); setLocalError(""); try { const result = await controller.select(selection); if (!aliveRef.current) return; if (!result || !result.ok) { const reason = result?.error; throw new Error(reason ? (reason.message || reason.code || String(reason)) : "当前会话无法切换模型"); } setPreference(nextPreference); onSuccess?.(); } catch (reason) { if (aliveRef.current) setLocalError(reason?.message || String(reason)); } finally { sendingRef.current = false; if (aliveRef.current) { setSaving(false); draftRef.current = null; setDraft(null); } } } function chooseModel(group, model) { if (!group || busy) return; const selection = { provider: group.id, model: model.id }; if (routeKey(selection) === currentKey) { setPage(0); return; } return submit(selection, { key: routeKey(selection), id: null }, () => setPage(0)); } function setSlider(index) { const value = { key: currentKey, index: Math.max(0, Math.min(choices.length - 1, index)) }; draftRef.current = value; setDraft(value); } function commitSlider(explicitIndex) { const pending = explicitIndex === undefined ? draftRef.current : { key: currentKey, index: explicitIndex }; if (!pending || pending.key !== currentKey || !adjustable || busy) return; const choice = choices[pending.index]; if (!choice) return; draftRef.current = null; if (pending.index === confirmedIndex) { setDraft(null); return; } return submit(selectionForEffort(state.current, choice), { key: currentKey, id: choice.id }); } function panelKeys(event) { if (event.nativeEvent?.isComposing) return; if (event.key === "Escape") { event.preventDefault(); event.stopPropagation(); back(); return; } const target = event.target; const isInput = target.tagName === "INPUT"; if (event.key === "ArrowLeft" && !isInput && page > 0) { event.preventDefault(); back(); return; } if (isInput && target.type === "range" && event.key !== "Tab") return; const activePage = panelRef.current?.querySelector('[data-page="' + page + '"]'); if (!activePage) return; if (["ArrowDown", "ArrowUp"].includes(event.key)) { const rows = [...activePage.querySelectorAll(".dsf-row:not(:disabled)")]; if (!rows.length) return; event.preventDefault(); const index = rows.indexOf(document.activeElement); const next = index < 0 ? (event.key === "ArrowDown" ? 0 : rows.length - 1) : (index + (event.key === "ArrowDown" ? 1 : -1) + rows.length) % rows.length; rows[next].focus(); return; } if (event.key === "Tab") { const focusable = [...activePage.querySelectorAll("button:not(:disabled), input:not(:disabled)")]; if (!focusable.length) { event.preventDefault(); panelRef.current?.focus(); return; } const at = focusable.indexOf(document.activeElement); if (event.shiftKey && at <= 0) { event.preventDefault(); focusable.at(-1).focus(); } else if (!event.shiftKey && (at === focusable.length - 1 || at < 0)) { event.preventDefault(); focusable[0].focus(); } } } function pageHeader(title, subtitle) { return h("header", { className: "dsf-page-header" }, h("button", { type: "button", className: "dsf-back", "aria-label": page === 2 ? "返回来源列表" : "返回思考强度", onClick: back }, h(Icon, { kind: "back", size: 16 })), h("div", { className: "dsf-heading-copy" }, h("div", { className: "dsf-page-title", title }, title), h("div", { className: "dsf-subtitle" }, subtitle)), h("button", { type: "button", className: "dsf-icon-button", "aria-label": "关闭模型面板", onClick: () => close(true) }, h(Icon, { kind: "close", size: 15 }))); } function searchBox(value, setValue, placeholder) { return h("div", { className: "dsf-search" }, h(Icon, { kind: "search", size: 15 }), h("input", { type: "search", value, placeholder, "aria-label": placeholder, onChange: event => setValue(event.target.value) })); } function notice(text, retry = true) { return h("div", { className: "dsf-notice", role: "status" }, h("span", null, text), retry && h("button", { type: "button", disabled: busy, onClick: load }, "重试")); } const progress = choices.length > 1 ? sliderIndex / (choices.length - 1) : 0; const panelStyle = position ? { width: position.width, height: position.height, left: position.left, "--dsf-unit": position.scale, top: position.top ?? "auto", bottom: position.bottom ?? "auto", "--dsf-origin": position.side === "above" ? "bottom right" : "top right", "--dsf-close-y": position.side === "above" ? "12px" : "-12px" } : { width: 240, height: 116, left: 0, top: 0, visibility: "hidden" }; const controls = h("section", { className: "dsf-page dsf-controls", "data-page": 0, "aria-hidden": page !== 0, inert: page === 0 ? undefined : "" }, h("div", { className: "dsf-control-top" }, h("div", { className: "dsf-effort-label", "aria-live": "polite" }, adjustable ? activeChoice?.name : "模型")), h("button", { type: "button", className: "dsf-model-title", disabled: busy, "aria-label": "切换模型,选择来源", onClick: () => navigate(1) }, h("span", { title: modelName }, modelName), h(Icon, { kind: "chevron", size: 17 })), adjustable && h("div", { className: "dsf-slider-area", "data-dragging": Boolean(draft) }, h("div", { className: "dsf-rail" }, h("div", { className: "dsf-fill", style: { width: "calc(" + (progress * 100) + "% + " + ((17 - 34 * progress) * (position?.scale || 1)) + "px)" } }), h("div", { className: "dsf-track-core" }, choices.map((choice, index) => h("span", { className: "dsf-tick", key: choice.id ?? "__default", "data-past": index <= sliderIndex, style: { left: (100 * index / (choices.length - 1)) + "%" } })), h("span", { className: "dsf-thumb", style: { left: (100 * progress) + "%" } })), h("input", { className: "dsf-slider-input", type: "range", min: 0, max: choices.length - 1, step: 1, value: sliderIndex, disabled: busy, "aria-label": "思考强度", "aria-valuetext": activeChoice?.name || "Default", onChange: event => setSlider(Number(event.target.value)), onPointerUp: () => commitSlider(), onKeyUp: event => { if (["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", "Home", "End", "PageUp", "PageDown"].includes(event.key)) commitSlider(); }, onBlur: () => commitSlider(), onPointerCancel: () => { draftRef.current = null; setDraft(null); } })), null), error && h("div", { className: "dsf-control-error", role: "alert" }, error)); const sourcePage = h("section", { className: "dsf-page", "data-page": 1, "aria-hidden": page !== 1, inert: page === 1 ? undefined : "" }, pageHeader("选择来源", groups.length + " 个来源"), searchBox(sourceQuery, setSourceQuery, "搜索来源或模型"), h("div", { className: "dsf-list", "aria-label": "模型来源" }, error && notice(error), state.status === "loading" && !groups.length && notice("正在加载来源…", false), failures.map(failure => h("div", { key: "failure:" + failure.id }, notice( (failure.name || failure.id) + ":" + (failure.message || "加载失败") ))), !pins.persisted && notice("置顶暂未保存到本机,当前窗口内仍可使用;再次点击可重试保存。", false), sources.map(group => { const current = group.id === state.current?.provider; const pinned = pins.ids.includes(group.id); const pinLabel = (pinned ? "取消置顶来源:" : "置顶来源:") + group.name; return h("div", { key: group.id, className: "dsf-source-item", "data-pinned": pinned }, h("button", { type: "button", className: "dsf-row dsf-source-row", "data-source-id": group.id, "data-selected": current, disabled: busy || !group.models.length, onClick: () => { setSourceId(group.id); navigate(2); } }, h("span", { className: "dsf-source-icon" }, h(Icon, { kind: "models", size: 18 })), h("span", { className: "dsf-row-copy" }, h("span", { className: "dsf-row-title", title: group.name }, group.name), h("span", { className: "dsf-subtitle" }, current ? "当前 · " + (found?.model.name || "模型暂不可用") : group.models.length + " 个模型")), current && h("span", { className: "dsf-current-badge" }, "当前"), h(Icon, { kind: "chevron", size: 17 })), h("button", { type: "button", className: "dsf-source-pin", title: pinLabel, "aria-label": pinLabel, "aria-pressed": pinned, "data-pin-source-id": group.id, onClick: () => pinnedSourcesStore.toggle(group.id) }, h(Icon, { kind: "pin", size: 16 }))); }), !sources.length && state.status !== "loading" && notice(sourceQuery ? "没有匹配的来源" : "暂无可用来源", false))); const modelPage = h("section", { className: "dsf-page", "data-page": 2, "aria-hidden": page !== 2, inert: page === 2 ? undefined : "" }, pageHeader(source?.name || "选择模型", (source?.models.length || 0) + " 个模型 · 返回选择其他来源"), searchBox(modelQuery, setModelQuery, "搜索该来源的模型"), h("div", { className: "dsf-list", "aria-label": "可选模型" }, error && notice(error), models.map(model => { const selected = state.current?.provider === sourceId && state.current?.model === model.id; return h("button", { key: model.id, type: "button", className: "dsf-row dsf-model-row", "data-selected": selected, "aria-pressed": selected, disabled: busy, onClick: () => chooseModel(source, model) }, h("span", { className: "dsf-row-title", title: model.name }, model.name), selected && h(Icon, { kind: "check", size: 18 })); }), !models.length && notice(modelQuery ? "没有匹配的模型" : "此来源暂无可用模型", false))); return h("div", { className: "dsf-seat", ref: rootRef }, h("button", { type: "button", ref: triggerRef, className: "dsf-trigger", disabled: Boolean(locked), "aria-haspopup": "dialog", "aria-expanded": present, "aria-controls": present ? id + "-island" : undefined, "aria-label": modelName + (adjustable ? " · " + (activeChoice?.name || "Default") : "") + ",打开模型与思考强度", title: modelName, onClick: open }, h(Icon, { kind: "models", size: 16 }), h("span", { className: "dsf-trigger-caption" }, modelName), adjustable && h("span", { className: "dsf-trigger-effort" }, activeChoice?.name), saving ? h("span", { className: "dsf-spinner", "aria-label": "正在切换" }) : h(Icon, { kind: "chevron", size: 13 })), present && ReactDOM.createPortal(h("div", { id: id + "-island", ref: panelRef, role: "dialog", "aria-label": "模型与思考强度", "aria-busy": busy, tabIndex: -1, className: "dsf-island", "data-stage": stage, "data-view": page, style: panelStyle, onKeyDown: panelKeys }, h("div", { className: "dsf-pages", style: { transform: "translate3d(-" + (page * 100) + "%,0,0)" } }, controls, sourcePage, modelPage), saving && h("div", { className: "dsf-saving", role: "status" }, h("span", { className: "dsf-spinner" }), "正在应用…") ), document.body)); } return function ModelSeat(props) { return props.available ? h(ModelIsland, { ...props, key: props.sessionKey }) : null; }; } const CSS = ".dsf-seat{position:relative;min-width:0}\n.dsf-trigger{display:flex;align-items:center;gap:6px;height:30px;max-width:min(330px,44cqw);padding:0 7px 0 8px;border:0;border-radius:10px;background:transparent;color:var(--dsw-alias-label-secondary,inherit);font:inherit;font-size:13px;cursor:pointer}\n.dsf-trigger:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.12))}\n.dsf-trigger-caption{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:var(--dsh-composer-model-text-display,block)}\n.dsf-trigger-effort{flex-shrink:0;font-size:12px;opacity:.6;display:var(--dsh-composer-model-text-display,block)}\n.dsf-trigger svg{flex-shrink:0}\n.dsf-trigger:disabled{opacity:.45;cursor:default}\n.dsf-island{\n --dsf-bg:var(--dsw-alias-bg-module-platform,#2d2d30);\n --dsf-ink:var(--dsw-alias-label-primary,#ededf0);\n --dsf-muted:var(--dsw-alias-label-caption,#a4a4ac);\n --dsf-accent:var(--dsw-alias-state-business-primary,#3787ff);\n --dsf-spring:cubic-bezier(.22,1.12,.36,1);\n position:fixed;z-index:1200;box-sizing:border-box;overflow:hidden;isolation:isolate;\n border:calc(1px * var(--dsf-unit,1)) solid color-mix(in srgb,var(--dsf-ink) 10%,transparent);border-radius:calc(22px * var(--dsf-unit,1));\n background:color-mix(in srgb,var(--dsf-bg) 96%,transparent);color:var(--dsf-ink);\n box-shadow:0 calc(24px * var(--dsf-unit,1)) calc(70px * var(--dsf-unit,1)) rgba(0,0,0,.26),0 calc(5px * var(--dsf-unit,1)) calc(16px * var(--dsf-unit,1)) rgba(0,0,0,.14),inset 0 calc(1px * var(--dsf-unit,1)) 0 rgba(255,255,255,.06);\n backdrop-filter:blur(calc(28px * var(--dsf-unit,1))) saturate(1.3);-webkit-backdrop-filter:blur(calc(28px * var(--dsf-unit,1))) saturate(1.3);\n transform-origin:var(--dsf-origin,bottom right);opacity:1;transform:translateY(0) scale(1);filter:blur(0);\n font-family:inherit;\n transition:width .44s cubic-bezier(.22,.82,.25,1),height .44s cubic-bezier(.22,.82,.25,1),left .44s cubic-bezier(.22,.82,.25,1),border-radius .44s ease,transform .44s var(--dsf-spring),opacity .2s ease,filter .25s ease;\n}\n.dsf-island[data-view=\"0\"]{border-radius:calc(24px * var(--dsf-unit,1))}\n.dsf-island[data-stage=\"closing\"]{opacity:0;transform:translateY(var(--dsf-close-y,calc(12px * var(--dsf-unit,1)))) scale(.84);filter:blur(calc(4px * var(--dsf-unit,1)))}\n.dsf-island[data-stage=\"closing\"]{pointer-events:none;transition-duration:.24s}\n.dsf-island[data-stage=\"opening\"]{opacity:0;transform:translateY(calc(10px * var(--dsf-unit,1)));filter:none;transition:none}\n.dsf-island[data-stage=\"open\"]{transition:width .44s cubic-bezier(.22,.82,.25,1),height .44s cubic-bezier(.22,.82,.25,1),left .44s cubic-bezier(.22,.82,.25,1),border-radius .44s ease;animation:dsf-enter .2s cubic-bezier(.16,1,.3,1) both}\n@keyframes dsf-enter{from{opacity:0;transform:translateY(calc(10px * var(--dsf-unit,1)))}to{opacity:1;transform:translateY(0)}}\n\n.dsf-island *{box-sizing:border-box}\n.dsf-island button,.dsf-island input{font-family:inherit}\n.dsf-island button{color:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent}\n.dsf-island button:disabled{cursor:default;opacity:.42}\n.dsf-island button:focus-visible,.dsf-trigger:focus-visible{outline:calc(2px * var(--dsf-unit,1)) solid var(--dsw-focus-ring-color,#3787ff);outline-offset:calc(-2px * var(--dsf-unit,1))}\n.dsf-pages{display:flex;width:100%;height:100%;transition:transform .46s cubic-bezier(.22,.88,.25,1);will-change:transform}\n.dsf-page{display:flex;flex:0 0 100%;flex-direction:column;min-width:0;height:100%;padding:calc(8px * var(--dsf-unit,1));overflow:hidden}\n.dsf-page[aria-hidden=\"true\"]{pointer-events:none}\n.dsf-controls{padding:calc(10px * var(--dsf-unit,1)) calc(12px * var(--dsf-unit,1)) calc(10px * var(--dsf-unit,1));align-items:center}\n.dsf-control-top{display:flex;align-items:center;justify-content:center;width:100%;min-height:calc(24px * var(--dsf-unit,1));color:var(--dsf-muted)}\n.dsf-effort-label{font-size:calc(16px * var(--dsf-unit,1));line-height:calc(24px * var(--dsf-unit,1));font-weight:600;color:var(--dsf-accent);letter-spacing:.02em}\n.dsf-icon-button,.dsf-back{display:grid;place-items:center;flex-shrink:0;width:calc(30px * var(--dsf-unit,1));height:calc(30px * var(--dsf-unit,1));border:0;border-radius:50%;background:transparent}\n.dsf-icon-button:hover:not(:disabled),.dsf-back:hover:not(:disabled){background:color-mix(in srgb,var(--dsf-ink) 7%,transparent)}\n.dsf-model-title{display:flex;align-items:center;justify-content:center;gap:calc(4px * var(--dsf-unit,1));max-width:100%;min-height:calc(28px * var(--dsf-unit,1));margin:0 0 calc(8px * var(--dsf-unit,1));padding:calc(2px * var(--dsf-unit,1)) calc(8px * var(--dsf-unit,1));border:0;border-radius:calc(12px * var(--dsf-unit,1));background:transparent;font-size:calc(14px * var(--dsf-unit,1));line-height:calc(22px * var(--dsf-unit,1));font-weight:500}\n.dsf-model-title span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.dsf-model-title svg{opacity:.55;flex-shrink:0;transition:transform .25s var(--dsf-spring)}\n.dsf-model-title:hover svg{transform:translateX(calc(3px * var(--dsf-unit,1)))}\n.dsf-slider-area{width:100%;margin-top:0;flex-shrink:0}\n.dsf-rail{position:relative;height:calc(28px * var(--dsf-unit,1));border-radius:calc(18px * var(--dsf-unit,1));background:color-mix(in srgb,var(--dsf-ink) 9%,transparent);border:calc(1px * var(--dsf-unit,1)) solid color-mix(in srgb,var(--dsf-ink) 14%,transparent);isolation:isolate}\n.dsf-fill{position:absolute;inset:calc(-1px * var(--dsf-unit,1)) auto calc(-1px * var(--dsf-unit,1)) calc(-1px * var(--dsf-unit,1));border-radius:calc(18px * var(--dsf-unit,1));background:#3787ff;transition:width .25s var(--dsf-spring);pointer-events:none}\n.dsf-track-core{position:absolute;inset:0 calc(17px * var(--dsf-unit,1));pointer-events:none}\n.dsf-tick{position:absolute;top:50%;width:calc(4px * var(--dsf-unit,1));height:calc(4px * var(--dsf-unit,1));border-radius:50%;background:color-mix(in srgb,var(--dsf-ink) 32%,transparent);transform:translate(-50%,-50%)}\n.dsf-tick[data-past=\"true\"]{background:rgba(255,255,255,.45)}\n.dsf-thumb{position:absolute;top:50%;width:calc(34px * var(--dsf-unit,1));height:calc(34px * var(--dsf-unit,1));border-radius:50%;background:#fff;box-shadow:0 calc(2px * var(--dsf-unit,1)) calc(6px * var(--dsf-unit,1)) rgba(0,0,0,.2),0 0 0 calc(.5px * var(--dsf-unit,1)) rgba(0,0,0,.08);transform:translate(-50%,-50%);transition:left .25s var(--dsf-spring),width .2s var(--dsf-spring),height .2s var(--dsf-spring)}\n.dsf-slider-area[data-dragging=\"true\"] .dsf-thumb{width:calc(36px * var(--dsf-unit,1));height:calc(36px * var(--dsf-unit,1));transition:left .035s linear,width .18s ease,height .18s ease}\n.dsf-slider-area[data-dragging=\"true\"] .dsf-fill{transition:width .035s linear}\n.dsf-slider-input{position:absolute;inset:calc(-8px * var(--dsf-unit,1)) calc(-1px * var(--dsf-unit,1));width:calc(100% + calc(2px * var(--dsf-unit,1)));height:calc(44px * var(--dsf-unit,1));margin:0;appearance:none;-webkit-appearance:none;opacity:0;cursor:ew-resize;touch-action:pan-y}\n.dsf-slider-input::-webkit-slider-thumb{appearance:none;-webkit-appearance:none;width:calc(34px * var(--dsf-unit,1));height:calc(44px * var(--dsf-unit,1))}\n.dsf-slider-input::-moz-range-thumb{width:calc(34px * var(--dsf-unit,1));height:calc(44px * var(--dsf-unit,1));border:0}\n.dsf-rail:focus-within{outline:calc(2px * var(--dsf-unit,1)) solid var(--dsw-focus-ring-color,#3787ff);outline-offset:calc(3px * var(--dsf-unit,1))}\n.dsf-page-header{display:flex;align-items:center;gap:calc(5px * var(--dsf-unit,1));flex-shrink:0;min-height:calc(44px * var(--dsf-unit,1));padding:0 calc(2px * var(--dsf-unit,1)) calc(6px * var(--dsf-unit,1))}\n.dsf-heading-copy{flex:1;min-width:0}\n.dsf-page-title{font-size:calc(15px * var(--dsf-unit,1));line-height:calc(22px * var(--dsf-unit,1));font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.dsf-subtitle{display:block;color:var(--dsf-muted);font-size:calc(11px * var(--dsf-unit,1));line-height:calc(16px * var(--dsf-unit,1));font-weight:400;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.dsf-search{display:flex;align-items:center;gap:calc(8px * var(--dsf-unit,1));flex-shrink:0;min-height:calc(32px * var(--dsf-unit,1));margin:calc(1px * var(--dsf-unit,1)) calc(4px * var(--dsf-unit,1)) calc(6px * var(--dsf-unit,1));padding:0 calc(11px * var(--dsf-unit,1));border-radius:calc(13px * var(--dsf-unit,1));background:color-mix(in srgb,var(--dsf-ink) 5%,transparent);color:var(--dsf-muted)}\n.dsf-search input{min-width:0;flex:1;border:0;outline:0;background:transparent;color:var(--dsf-ink);font-size:calc(13px * var(--dsf-unit,1));line-height:calc(24px * var(--dsf-unit,1))}\n.dsf-search input::placeholder{color:var(--dsf-muted)}\n.dsf-list{flex:1;min-height:0;overflow:auto;overscroll-behavior:contain;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--dsf-ink) 20%,transparent) transparent;padding:0 calc(3px * var(--dsf-unit,1)) calc(3px * var(--dsf-unit,1))}\n.dsf-row{display:flex;align-items:center;gap:calc(10px * var(--dsf-unit,1));width:100%;margin:calc(2px * var(--dsf-unit,1)) 0;border:0;border-radius:calc(17px * var(--dsf-unit,1));background:transparent;text-align:left;transition:background .16s ease,transform .22s var(--dsf-spring)}\n.dsf-row:hover:not(:disabled){background:color-mix(in srgb,var(--dsf-ink) 7%,transparent)}\n.dsf-row:active:not(:disabled){transform:scale(.98)}\n.dsf-row[data-selected=\"true\"]{background:color-mix(in srgb,var(--dsf-ink) 10%,transparent)}\n.dsf-source-row{min-height:calc(56px * var(--dsf-unit,1));padding:calc(8px * var(--dsf-unit,1)) calc(9px * var(--dsf-unit,1))}\n.dsf-model-row{min-height:calc(44px * var(--dsf-unit,1));padding:calc(10px * var(--dsf-unit,1)) calc(12px * var(--dsf-unit,1));justify-content:space-between}\n.dsf-source-icon{display:grid;place-items:center;flex-shrink:0;width:calc(30px * var(--dsf-unit,1));height:calc(30px * var(--dsf-unit,1));border-radius:calc(10px * var(--dsf-unit,1));background:color-mix(in srgb,var(--dsf-ink) 6%,transparent);color:var(--dsf-muted)}\n.dsf-row-copy{display:flex;flex-direction:column;flex:1;min-width:0;gap:calc(2px * var(--dsf-unit,1))}\n.dsf-row-title{display:block;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:calc(16px * var(--dsf-unit,1));font-weight:500;line-height:calc(22px * var(--dsf-unit,1))}\n.dsf-model-row .dsf-row-title{font-size:calc(16px * var(--dsf-unit,1));font-weight:400}\n.dsf-model-row>svg,.dsf-source-row>svg{flex-shrink:0}\n.dsf-current-badge{font-size:calc(10px * var(--dsf-unit,1));line-height:calc(20px * var(--dsf-unit,1));padding:0 calc(6px * var(--dsf-unit,1));flex-shrink:0;border-radius:calc(7px * var(--dsf-unit,1));color:var(--dsf-accent);background:color-mix(in srgb,var(--dsf-accent) 10%,transparent)}\n.dsf-notice{display:flex;align-items:center;gap:calc(8px * var(--dsf-unit,1));justify-content:space-between;padding:calc(12px * var(--dsf-unit,1)) calc(10px * var(--dsf-unit,1));color:var(--dsf-muted);font-size:calc(12px * var(--dsf-unit,1));line-height:calc(19px * var(--dsf-unit,1));overflow-wrap:anywhere}\n.dsf-notice button{flex-shrink:0;border:0;border-radius:calc(8px * var(--dsf-unit,1));background:color-mix(in srgb,var(--dsf-ink) 7%,transparent);padding:calc(6px * var(--dsf-unit,1)) calc(9px * var(--dsf-unit,1));font-size:calc(12px * var(--dsf-unit,1))}\n.dsf-control-error{width:100%;flex-shrink:0;max-height:calc(50px * var(--dsf-unit,1));overflow:auto;margin-top:calc(8px * var(--dsf-unit,1));color:var(--dsw-alias-state-error-primary,#ed7777);font-size:calc(11px * var(--dsf-unit,1));line-height:calc(16px * var(--dsf-unit,1));overflow-wrap:anywhere}\n.dsf-saving{position:absolute;right:calc(15px * var(--dsf-unit,1));bottom:calc(10px * var(--dsf-unit,1));display:flex;align-items:center;gap:calc(6px * var(--dsf-unit,1));border-radius:calc(12px * var(--dsf-unit,1));padding:calc(5px * var(--dsf-unit,1)) calc(9px * var(--dsf-unit,1));background:var(--dsf-bg);font-size:calc(11px * var(--dsf-unit,1));color:var(--dsf-muted);pointer-events:none}\n.dsf-spinner{display:inline-block;flex-shrink:0;width:calc(13px * var(--dsf-unit,1));height:calc(13px * var(--dsf-unit,1));border:calc(1.5px * var(--dsf-unit,1)) solid currentColor;border-right-color:transparent;border-radius:50%;animation:dsf-spin .7s linear infinite}\n@keyframes dsf-spin{to{transform:rotate(360deg)}}\n@media(prefers-reduced-motion:reduce){.dsf-island,.dsf-island[data-stage=\"closing\"],.dsf-pages,.dsf-row,.dsf-thumb,.dsf-fill,.dsf-island[data-stage=\"opening\"],.dsf-island[data-stage=\"closing\"]{transform:none;filter:none}.dsf-spinner{animation-duration:1.4s}}\n@media(max-width:480px){.dsf-trigger{max-width:170px}.dsf-trigger-effort{display:none}}\n\n.dsf-island svg{width:calc(var(--dsf-icon-size,18px) * var(--dsf-unit,1));height:calc(var(--dsf-icon-size,18px) * var(--dsf-unit,1));flex-shrink:0}\n.dsf-island .dsf-slider-input{opacity:0!important}\n.dsf-island .dsf-thumb{border-radius:50%!important;aspect-ratio:1/1}\n.dsf-island .dsf-slider-input{padding:0;border:0;background:transparent;box-sizing:border-box;min-width:0}\n\n@media(prefers-reduced-motion:reduce){.dsf-island[data-stage=\"open\"]{animation:none}}\n\n.dsf-source-item{position:relative;display:flow-root}\n.dsf-source-item .dsf-source-row{padding-right:calc(46px * var(--dsf-unit,1))}\n.dsf-island .dsf-source-pin{position:absolute;right:calc(3px * var(--dsf-unit,1));top:50%;transform:translateY(-50%);display:grid;place-items:center;width:calc(36px * var(--dsf-unit,1));height:calc(40px * var(--dsf-unit,1));padding:0;border:0;border-radius:calc(11px * var(--dsf-unit,1));background:transparent;color:var(--dsf-muted)}\n.dsf-island .dsf-source-pin:hover{background:color-mix(in srgb,var(--dsf-ink) 8%,transparent)}\n.dsf-island .dsf-source-pin[aria-pressed=\"true\"]{color:var(--dsf-accent)}\n.dsf-source-pin[aria-pressed=\"true\"] svg{fill:color-mix(in srgb,var(--dsf-accent) 18%,transparent)}\n"; const ModelSeat = createIsland(React, ReactDOM); function apply(ctx) { const SEAT = "conversation.input.model"; ctx.effect(() => { const style = document.createElement("style"); style.dataset.plugin = "dsh-source-fold"; style.textContent = CSS; let active = true; const install = () => { document.removeEventListener("DOMContentLoaded", install); if (active) document.head?.append(style); }; if (document.head) install(); else document.addEventListener("DOMContentLoaded", install, { once: true }); return () => { active = false; document.removeEventListener("DOMContentLoaded", install); style.remove(); }; }, "dsh-source-fold: island styles"); ctx.slots.inject(SEAT, () => { const entries = ctx.slots.entries(SEAT); const priority = Math.min(-1000, ...entries.map(entry => entry.options.priority ?? 0)) - 1; return ctx.slots.register({ name: SEAT, priority, inject: sessionId => { const available = ctx.sessions.subagentAddress(sessionId) === undefined; return { sessionKey: sessionId, available, controller: available ? ctx.modelDirectories.directoryFor(sessionId) : null }; } }, ModelSeat); }); } return { name: "dsh-source-fold", inject: ["slots", "modelDirectories", "sessions", "remote", "remote.session"], apply }; } });