@roaming-ai/dsh-group-chat 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cordis.patch.yml +1 -1
- package/lib/client.js +2 -2
- package/lib/client.js.map +1 -1
- package/package.json +1 -1
- package/src/client/lib/styles.ts +1 -1
package/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["h","createElement","P","useState","P","P","P","useState","P","useState","P","P","memo","P","useState","P","P","P","useState","useRef","useCallback","createRoot","createElement","FileTypeIcon","useCallback","useState","useMemo","useState","useCallback","P","useState","P","h"],"sources":["../src/client/lib/styles.ts","../src/client/lib/ui.ts","../src/core/status.ts","../src/client/lib/model.ts","../src/client/lib/api.ts","../src/client/components/RoleDrawer.tsx","../src/client/components/NavPanel.tsx","../src/client/components/AsidePanel.tsx","../src/client/components/ThinkRow.tsx","../src/client/components/ToolRow.tsx","../src/client/components/Bubble.tsx","../src/client/components/MessageFlow.tsx","../src/core/types.ts","../src/client/components/PermissionSelect.tsx","../src/client/components/Composer.tsx","../src/client/components/ChatPanel.tsx","../src/client/hooks/useGroupChatState.ts","../src/shared/file-mention-grammar.ts","../src/client/utils/utils.ts","../src/client/hooks/useComposer.ts","../src/client/hooks/useFileSearch.ts","../src/client/hooks/useMentionState.ts","../src/client/GroupChatPanel.tsx","../src/client/components/GroupChatSettingsSection.tsx","../src/client/components/Glyph.tsx","../src/client/index.ts"],"sourcesContent":["/**\n * 浏览器半样式:CSS 以内联字符串承载(刻意不迁移 CSS Modules 管线——\n * 类名需保持原样,侧栏入口的 “newSession” 类名是任务看板等 DOM 注入式\n * 面板识别“侧边栏导航点击”的跨插件标记,哈希化会破坏该约定)。\n * 工厂执行时幂等注入 <style>,loader 卸载时按 data-plugin 摘除标签。\n * @module dsh-group-chat/client/styles\n */\n\n/** 注入标签的唯一 id。 */\nconst TAG_ID = 'dsh-group-chat/styles.css'\n\nexport const CSS = [\n /* ===== 布局骨架:三区工作台;卡片只用于内容单元,导航用平铺行 ===== */\n '.dsgc-root{display:flex;height:100%;min-height:0;background:var(--dsw-alias-bg-base,transparent);color:var(--dsw-alias-label-primary,inherit);font-size:var(--dsh-content-font-size,14px);container-type:inline-size;position:relative}',\n '.dsgc-loading{padding:24px;color:var(--dsw-alias-label-tertiary,inherit);display:flex;gap:8px;align-items:center;opacity:0;animation:dsgc-loading-in .18s ease-out .15s forwards}',\n /* 首开加载态延迟 150ms 淡入:本机回路通常数毫秒内数据即达并卸载本元素,\n 快路径完全不可见(无闪现,等同移除);慢路径才出现反馈,空白面板不再是唯一信号 */\n '@keyframes dsgc-loading-in{to{opacity:1}}',\n '.dsgc-loading svg{animation:dsgc-spin 1s linear infinite}',\n '@keyframes dsgc-spin{to{transform:rotate(360deg)}}',\n /* ===== 左导航栏(可收起,收合动画与右栏同款配方) ===== */\n '.dsgc-nav{width:232px;flex:none;display:flex;flex-direction:column;gap:8px;border-right:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.2));padding:12px 10px;min-height:0;min-width:0;transition:width .28s cubic-bezier(.16,1,.3,1),opacity .18s ease,padding .28s cubic-bezier(.16,1,.3,1),border-right-width .28s cubic-bezier(.16,1,.3,1)}',\n /* 子元素经 flex 列默认 stretch 填满内容区(不写死宽度:内容区实宽 232px——\n 宿主无全局 border-box,面板为 content-box,旧版写死 212px 曾致右侧多出\n 20px 死区、左右内距失衡);收合动画期间内容随面板收缩,行内 ellipsis\n 渐进截断 + visibility 0.22s 切断,无溢出涂抹 */\n '.dsgc-nav>*{flex:none}',\n '.dsgc-nav.closed{width:0;opacity:0;padding-left:0;padding-right:0;border-right-width:0;visibility:hidden;transition:width .24s ease-in,opacity .16s ease-in,padding .24s ease-in,border-right-width .24s ease-in,visibility 0s .22s}',\n '.dsgc-search{flex:none}',\n '.dsgc-search input{font-size:13px}',\n '.dsgc-search:focus-within{border-color:var(--dsw-alias-state-business-primary,#4f6ef7)}',\n '.dsgc-tree{display:flex;flex-direction:column;gap:6px;flex:1;overflow-y:auto;min-height:0;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent}',\n '.dsgc-grow-row{display:flex;align-items:center;gap:2px;min-width:0;border:none;background:none;border-radius:6px;padding:5px 6px;color:var(--dsw-alias-label-secondary,inherit);transition:background-color .12s,color .12s;cursor:pointer;font:inherit;text-align:left}',\n '.dsgc-grow-row:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.12));color:var(--dsw-alias-label-primary,inherit)}',\n '.dsgc-grow-row.on{color:var(--dsw-alias-label-primary,inherit);font-weight:600}',\n '.dsgc-twist{flex:none;width:16px;height:16px;border:none;background:none;color:inherit;cursor:pointer;padding:0;display:inline-flex;align-items:center;justify-content:center}',\n '.dsgc-twist svg{transition:transform .16s ease}',\n '.dsgc-twist.closed svg{transform:rotate(-90deg)}',\n '.dsgc-gname{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',\n '.dsgc-nodeops{display:none;gap:2px;flex:none}',\n '.dsgc-grow-row:hover .dsgc-nodeops,.dsgc-sess-row:hover .dsgc-nodeops{display:inline-flex}',\n '.dsgc-opbtn{border:none;background:none;color:var(--dsw-alias-label-tertiary,inherit);cursor:pointer;padding:2px;border-radius:4px;line-height:0;transition:background-color .12s,color .12s}',\n '.dsgc-opbtn:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.15));color:var(--dsw-alias-label-primary,inherit)}',\n '.dsgc-opbtn.danger{color:var(--dsw-alias-state-error-primary,#e5484d)}',\n '.dsgc-sess-list{display:flex;flex-direction:column;gap:2px;margin:4px 0 2px 4px;padding-left:12px;border-left:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.15))}',\n '.dsgc-sess-row{display:flex;align-items:center;gap:6px;min-width:0;border:none;background:none;border-radius:6px;padding:6px 8px;font-size:12.5px;line-height:1.5;color:var(--dsw-alias-label-secondary,inherit);transition:background-color .12s,color .12s;cursor:pointer;text-align:left;font-family:inherit}',\n '.dsgc-sess-row:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.12));color:var(--dsw-alias-label-primary,inherit)}',\n '.dsgc-sess-row.on{background:var(--dsw-alias-interactive-bg-active,rgba(128,128,128,.2));color:var(--dsw-alias-label-primary,inherit);font-weight:600}',\n '.dsgc-sess-status{flex:none;width:8px;height:8px;display:inline-flex;justify-content:center;align-items:center}',\n '.dsgc-sess-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',\n '.dsgc-addsess{border:none;background:none;color:var(--dsw-alias-label-tertiary,inherit);cursor:pointer;text-align:left;font-size:12px;line-height:1.5;padding:5px 8px;border-radius:6px;transition:background-color .12s,color .12s;font-family:inherit;display:flex;align-items:center;gap:5px;white-space:nowrap;overflow:hidden}',\n '.dsgc-addsess:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.12));color:var(--dsw-alias-label-primary,inherit)}',\n '.dsgc-rename{font:inherit;font-size:12.5px;min-width:0;flex:1;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));background:var(--dsw-specific-input-major,var(--dsw-alias-bg-layer-3,transparent));color:inherit;border-radius:6px;padding:1px 6px;outline:none;transition:border-color .16s}',\n '.dsgc-rename:focus{border-color:var(--dsw-alias-state-business-primary,#4f6ef7)}',\n '.dsgc-hint{font-size:12px;color:var(--dsw-alias-label-tertiary,inherit);line-height:1.5;text-wrap:balance}',\n /* ===== 中央会话区 ===== */\n '.dsgc-chat{flex:1;display:flex;flex-direction:column;min-width:0;min-height:0;position:relative}',\n /* 接缝收合钮:钉在会话区两缘、垂直居中、各控其侧(图标方向相反的 chevron)。\n 宽模式下面板宽度过渡 → 中栏连续变宽,绝对定位的钮贴缘自动随接缝滑行(布局驱动);\n 窄模式右栏为覆盖层,钮用同曲线 right 过渡跟踪其左缘。浮层配方:实底 + border-l2 + 轻方向性软影 */\n '.dsgc-seambtn{position:absolute;top:50%;transform:translateY(-50%);z-index:14;width:24px;height:56px;display:flex;align-items:center;justify-content:center;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));background:var(--dsw-alias-bg-layer-3,#fff);color:var(--dsw-alias-label-secondary,inherit);cursor:pointer;transition:background-color .12s,color .12s,border-color .12s,right .3s cubic-bezier(.16,1,.3,1)}',\n '.dsgc-seambtn:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.15));color:var(--dsw-alias-label-primary,inherit);border-color:var(--dsw-alias-border-l3,rgba(128,128,128,.4))}',\n '.dsgc-seambtn.left{left:0;border-left:none;border-radius:0 8px 8px 0;box-shadow:3px 0 10px rgba(0,0,0,.07)}',\n '.dsgc-seambtn.right{right:0;border-right:none;border-radius:8px 0 0 8px;box-shadow:-3px 0 10px rgba(0,0,0,.07)}',\n '.dsgc-chathead{display:flex;gap:10px;align-items:center;padding:12px 16px;border-bottom:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.2))}',\n '.dsgc-sess-title{flex:none;font-weight:600;font-size:14px;color:var(--dsw-alias-label-primary,inherit);max-width:30%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',\n '.dsgc-topic{flex:1;background:transparent;border:none;border-bottom:1px solid transparent;padding:2px;min-height:20px;color:var(--dsw-alias-label-secondary,inherit);font:inherit;outline:none;min-width:0;transition:color .12s,border-color .12s}',\n '.dsgc-topic:hover{border-bottom-color:var(--dsw-alias-border-l2,rgba(128,128,128,.3))}',\n '.dsgc-topic:focus{color:var(--dsw-alias-label-primary,inherit);border-bottom-color:var(--dsw-alias-state-business-primary,#4f6ef7)}',\n '.dsgc-topic::placeholder{color:var(--dsw-alias-label-tertiary,inherit)}',\n /* 清空按钮:破坏性操作的 hover/active 反馈——宿主 ghost hover 是低强度灰底(在本\n 面板底色上近透明、无感知),改为 danger 色文字 + 淡红底,与弹窗内 danger 确认\n 按钮同语言;特异性高于原语 .ghost:hover:not(:disabled) */\n '.dsgc-chathead .dsgc-clearbtn{transition:background-color .12s,color .12s}',\n '.dsgc-chathead .dsgc-clearbtn:hover:not(:disabled){background:color-mix(in srgb,var(--dsw-alias-state-error-primary,#e5484d) 10%,transparent);color:var(--dsw-alias-state-error-primary,#e5484d)}',\n '.dsgc-chathead .dsgc-clearbtn:active:not(:disabled){background:color-mix(in srgb,var(--dsw-alias-state-error-primary,#e5484d) 16%,transparent)}',\n '.dsgc-msgs{flex:1;overflow-y:auto;padding:20px 24px 16px;display:flex;flex-direction:column;gap:16px;min-height:0;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent}',\n '.dsgc-msg{display:flex;gap:10px;align-items:flex-start;max-width:100%;animation:dsgc-msg-in .22s cubic-bezier(.16,1,.3,1)}',\n '.dsgc-msg.mine{flex-direction:row-reverse}',\n '.dsgc-avatar{width:28px;height:28px;box-sizing:border-box;border:2px solid var(--dsw-alias-border-l3,rgba(128,128,128,.4));border-radius:50%;background:var(--dsw-alias-bg-module-platform,rgba(128,128,128,.12));color:var(--dsw-alias-label-primary,inherit);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:600;flex:none;margin-top:1px}',\n '.dsgc-avatar.mine{border-color:transparent;background:var(--dsw-alias-button-info-fill,#4f6ef7);color:var(--dsw-alias-label-primary-foreground,#fff)}',\n '.dsgc-msgbody{max-width:76%;min-width:0;display:flex;flex-direction:column;gap:5px}',\n '.dsgc-msg.mine .dsgc-msgbody{align-items:flex-end}',\n '.dsgc-msghead{display:flex;gap:6px;align-items:center;min-width:0;font-size:12px;color:var(--dsw-alias-label-secondary,inherit)}',\n '.dsgc-msgname{font-weight:600;color:var(--dsw-alias-label-primary,inherit);white-space:nowrap}',\n '.dsgc-msgmodel{background:var(--dsw-alias-bg-module-platform,rgba(128,128,128,.12));border-radius:999px;padding:0 7px;font-size:10.5px;font-weight:500;line-height:16px;color:var(--dsw-alias-label-secondary,inherit);white-space:nowrap;max-width:100%;overflow:hidden;text-overflow:ellipsis}',\n '.dsgc-msgtime{font-size:10.5px;color:var(--dsw-alias-label-tertiary,inherit);white-space:nowrap}',\n /* 流式「深度求索...」(对标宿主 TurnStatus「深度求索中...」签名动画):DeepSeek\n 品牌蓝渐变带扫过文字的微光——background-clip:text + background-position\n 1.8s linear 无限扫动;令牌取宿主静态品牌色 --dsw-static-deepseek-*(非主题\n 别名,回退为品牌字面值),贯穿首轮 token 前与流式全程 */\n '.dsgc-typing{background:linear-gradient(90deg,var(--dsw-static-deepseek-500,#4176e6) 0%,var(--dsw-static-deepseek-500,#4176e6) 40%,var(--dsw-static-deepseek-200,#d3e2ff) 50%,var(--dsw-static-deepseek-500,#4176e6) 60%,var(--dsw-static-deepseek-500,#4176e6) 100%);color:#0000;-webkit-text-fill-color:transparent;background-position:100% 0;background-size:250% 100%;-webkit-background-clip:text;background-clip:text;font-weight:600;animation:dsgc-typing-shimmer 1.2s linear infinite}',\n '@keyframes dsgc-typing-shimmer{to{background-position:0 0}}',\n '.dsgc-msgtext{background:var(--dsw-alias-bg-layer-3,rgba(128,128,128,.06));border:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.15));padding:10px 14px;border-radius:12px;line-height:1.6;text-align:left;color:var(--dsw-alias-label-primary,inherit);min-width:0;overflow-wrap:anywhere}',\n '.dsgc-msg.mine .dsgc-msgtext{background:var(--dsw-alias-button-info-fill,#4f6ef7);border-color:transparent;color:var(--dsw-alias-label-primary-foreground,#fff);white-space:pre-wrap;word-break:break-word}',\n '.dsgc-msgtext.live{opacity:.92}',\n '.dsgc-msg.live .dsgc-avatar{--presence-ring:color-mix(in srgb,var(--role-color,#4f6ef7) 22%,transparent);animation:dsgc-presence 1.8s ease-in-out infinite}',\n '.dsgc-think{margin:2px 0}',\n '.dsgc-think .dsgc-thinkrow{font-size:12px;color:var(--dsw-alias-label-secondary,inherit);border-radius:8px;padding:3px 8px;transition:background-color .12s}',\n '.dsgc-think .dsgc-thinkrow:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.1))}',\n '.dsgc-think .dsgc-thinksummary{color:var(--dsw-alias-label-tertiary,inherit);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:44ch;font-size:11.5px;margin-left:6px}',\n '.dsgc-think .dsgc-thinkbody{font-size:12.5px;line-height:1.7;color:var(--dsw-alias-label-secondary,inherit);white-space:pre-wrap;word-break:break-word;border-left:2px solid var(--dsw-alias-border-l2,rgba(128,128,128,.25));margin:2px 0 4px;padding:2px 0 2px 10px;max-height:320px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent;animation:dsgc-think-in .2s ease-out}',\n /* 首 delta 前的「思考中」占位行:ThinkRow 同语言(思考图标 + 次要色 12px 小字)\n + 三点交错呼吸动画——深度思考模型首字节可能等数秒到数十秒,空白气泡会被\n 感知为卡死;delta 到达后被真实思考行/正文自然替换 */\n '.dsgc-pending{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--dsw-alias-label-secondary,inherit)}',\n '.dsgc-pending svg{flex:none}',\n '.dsgc-pendingdots{display:inline-flex;gap:2px;align-items:center}',\n '.dsgc-pendingdots i{width:3px;height:3px;border-radius:50%;background:currentColor;opacity:.3;animation:dsgc-dot-breathe 1.2s ease-in-out infinite}',\n '.dsgc-pendingdots i:nth-child(2){animation-delay:.2s}',\n '.dsgc-pendingdots i:nth-child(3){animation-delay:.4s}',\n '@keyframes dsgc-dot-breathe{0%,100%{opacity:.25}50%{opacity:1}}',\n '.dsgc-sysmsg{align-self:center;font-size:11.5px;color:var(--dsw-alias-label-secondary,inherit);background:var(--dsw-alias-bg-module-platform,rgba(128,128,128,.1));border-radius:999px;padding:2px 10px;text-align:center;max-width:90%;animation:dsgc-sys-in .24s ease-out}',\n /* ===== 工具调用行 / 确认卡片(对标思考折叠语言) ===== */\n '.dsgc-tool{margin:2px 0}',\n '.dsgc-tool .dsgc-toolrow{font-size:12px;color:var(--dsw-alias-label-secondary,inherit);border-radius:8px;padding:3px 8px;transition:background-color .12s}',\n '.dsgc-tool .dsgc-toolrow:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.1))}',\n '.dsgc-tool .dsgc-toolsummary{color:var(--dsw-alias-label-tertiary,inherit);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:40ch;font-size:11.5px;margin-left:6px}',\n '.dsgc-tool .dsgc-toolbody{font-size:12px;line-height:1.6;color:var(--dsw-alias-label-secondary,inherit);white-space:pre-wrap;word-break:break-word;border-left:2px solid var(--dsw-alias-border-l2,rgba(128,128,128,.25));margin:2px 0 4px;padding:2px 0 2px 10px;max-height:260px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent}',\n '.dsgc-confirm{border:1px solid var(--dsw-alias-state-business-primary,#4f6ef7);border-radius:12px;background:var(--dsw-alias-bg-layer-3,rgba(128,128,128,.06));padding:10px 12px;display:flex;flex-direction:column;gap:8px;max-width:76%;animation:dsgc-fade-in .18s ease-out}',\n '.dsgc-confirmtitle{font-size:12px;font-weight:600;color:var(--dsw-alias-label-primary,inherit);display:flex;align-items:center;gap:6px}',\n '.dsgc-confirmcmd{font-size:12px;line-height:1.6;white-space:pre-wrap;word-break:break-word;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));border-radius:8px;padding:8px 10px;background:var(--dsw-alias-bg-layer-2,transparent);color:var(--dsw-alias-label-primary,inherit);max-height:240px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent}',\n '.dsgc-confirmops{display:flex;gap:8px;justify-content:flex-end}',\n '.dsgc-sysmsg.err{color:var(--dsw-alias-state-error-primary,#e5484d)}',\n /* 清空确认弹窗内的说明列表 */\n '.dsgc-clearnotes{margin:0;padding-left:18px;font-size:13px;line-height:1.8;color:var(--dsw-alias-label-secondary,inherit);display:flex;flex-direction:column;gap:2px}',\n '.dsgc-err{font-size:12px;color:var(--dsw-alias-state-error-primary,#e5484d);animation:dsgc-fade-in .18s ease-out}',\n '.dsgc-empty{margin:auto;display:flex;flex-direction:column;align-items:center;gap:10px;color:var(--dsw-alias-label-tertiary,inherit);text-align:center;max-width:40ch;padding:24px;animation:dsgc-fade-in .3s ease-out}',\n '.dsgc-empty svg{opacity:.5}',\n '.dsgc-empty .dsgc-emptytitle{font-size:13px;font-weight:600;color:var(--dsw-alias-label-secondary,inherit)}',\n '.dsgc-empty .dsgc-hint{text-wrap:balance}',\n '.dsgc-tobottom{position:absolute;bottom:calc(100% + 8px);left:50%;transform:translateX(-50%);z-index:12;animation:dsgc-rise-in .18s cubic-bezier(.16,1,.3,1)}',\n /* 回到底部:实底浮动胶囊(@弹层同款浮层配方——实底 + border-l2 + shadow-lv3),不与消息内容相互透底 */\n '.dsgc-tobtn{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));background:var(--dsw-alias-bg-layer-3,#fff);color:var(--dsw-alias-label-secondary,inherit);border-radius:999px;padding:5px 12px;font:inherit;font-size:12px;line-height:1.4;cursor:pointer;box-shadow:var(--dsw-shadow-lv3,0 8px 24px rgba(0,0,0,.18));transition:color .12s,border-color .12s}',\n '.dsgc-tobtn:hover{color:var(--dsw-alias-label-primary,inherit);border-color:var(--dsw-alias-border-l3,rgba(128,128,128,.4))}',\n /* ===== composer ===== */\n '.dsgc-composer{padding:12px 16px 14px;display:flex;flex-direction:column;gap:10px;position:relative}',\n /* 输入卡(对标主会话 composer 卡):22px 圆角独立卡、input-major 实底、\n elevation-soft 软影(DESIGN.md 输入面豁免——输入面遵循宿主输入面语言,\n 其余静止表面仍零阴影);chips 等配置行留卡外 */\n '.dsgc-card{background:var(--dsw-specific-input-major,var(--dsw-alias-bg-layer-3,transparent));--dsw-elevation-stroke-color:var(--dsw-alias-border-l2,rgba(128,128,128,.3));box-shadow:var(--dsw-elevation-soft,0 1px 3px rgba(0,0,0,.08));border-radius:22px;padding:8px 0 0;display:flex;flex-direction:column;gap:8px;position:relative}',\n /* 输入区:非受控 contenteditable(React 不管子节点);白空间与换行规则\n 与序列化契约对齐(pre-wrap + <br>→\\n) */\n '.dsgc-edit{display:block;box-sizing:border-box;width:100%;min-height:36px;max-height:180px;overflow-y:auto;outline:none;white-space:pre-wrap;word-break:break-word;overflow-wrap:anywhere;font:inherit;font-size:13px;line-height:24px;color:var(--dsw-alias-label-primary,inherit);caret-color:var(--dsw-alias-state-business-primary,#4f6ef7);scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent;position:relative;z-index:1}',\n '.dsgc-card .dsgc-edit{padding:6px 8px 0 14px}',\n /* 占位符 = 独立覆盖层(对齐主会话):不用 ::before——生成内容会把聚焦光标\n 顶到占位文字之后;覆盖层 pointer-events:none 不参与光标布局,\n 与输入区同 padding 基准(左 14 / 上 6) */\n '.dsgc-ph{position:absolute;left:14px;top:6px;max-width:calc(100% - 22px);color:var(--dsw-alias-label-tertiary,inherit);pointer-events:none;user-select:none;font-size:13px;line-height:24px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}',\n /* @提及芯片(输入区内原子元素):色点 + 角色色淡底胶囊——弹层候选行同语言 */\n '.dsgc-chipin{display:inline-flex;align-items:center;gap:4px;background:color-mix(in srgb,var(--role-color,#888) 15%,transparent);border-radius:999px;padding:1px 7px 1px 5px;margin:0 1px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-primary,inherit);white-space:nowrap;user-select:all}',\n '.dsgc-card .dsgc-sendrow{padding:0 12px 10px}',\n '.dsgc-stopbtn{background:var(--dsw-alias-state-error-primary,#e5484d);border-color:transparent;color:#fff;font-weight:600}',\n '.dsgc-stopbtn:hover:not(:disabled){filter:brightness(1.08);color:#fff}',\n '.dsgc-parts{display:flex;gap:6px;flex-wrap:wrap;align-items:center;row-gap:4px;height:24px}',\n '.dsgc-partslabel{font-size:12px;color:var(--dsw-alias-label-tertiary,inherit);flex:none}',\n '.dsgc-partchip{display:inline-flex;gap:6px;align-items:center;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));background:transparent;color:var(--dsw-alias-label-secondary,inherit);border-radius:999px;padding:2px 10px;font-size:12px;line-height:1.5;cursor:pointer;transition:background-color .12s,color .12s,border-color .12s;font-family:inherit}',\n '.dsgc-partchip:hover{color:var(--dsw-alias-label-primary,inherit)}',\n '.dsgc-partchip.on{background:var(--dsw-alias-interactive-bg-active,rgba(128,128,128,.18));color:var(--dsw-alias-label-primary,inherit);border-color:var(--dsw-alias-border-l2,rgba(128,128,128,.3))}',\n '.dsgc-partchip:disabled{opacity:.5;cursor:default}',\n '.dsgc-chipdot{width:8px;height:8px;border-radius:50%;flex:none;display:inline-block}',\n '.dsgc-sendrow{display:flex;gap:8px;align-items:center;justify-content:flex-end}',\n '.dsgc-sendrow button{white-space:nowrap}',\n /* ===== 权限档位选择器(对齐主会话 composer 左下角芯片) ===== */\n '.dsgc-permtrigger{min-width:0;max-width:220px;height:28px;color:var(--dsw-alias-label-secondary,inherit);cursor:pointer;background:transparent;border:none;border-radius:999px;outline:none;align-items:center;gap:4px;padding:0 4px 0 8px;font-size:13px;font-weight:500;line-height:20px;display:inline-flex;font-family:inherit;transition:background-color .12s,color .12s}',\n '.dsgc-permtrigger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.15));color:var(--dsw-alias-label-primary,inherit)}',\n '.dsgc-permtrigger:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3,rgba(128,128,128,.4))}',\n '.dsgc-permtrigger:disabled{color:var(--dsw-alias-label-dimmed,inherit);cursor:default}',\n '.dsgc-permicon{flex:none;display:inline-flex}',\n '.dsgc-permicon svg{width:14px;height:14px}',\n '.dsgc-permlabel{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}',\n '.dsgc-permchevron{color:var(--dsw-alias-label-caption,inherit);flex:none;transition:transform .12s;display:inline-flex}',\n '.dsgc-permchevron.open{transform:rotate(180deg)}',\n '.dsgc-rounds{display:flex;gap:2px;align-items:center;font-size:12px;color:var(--dsw-alias-label-secondary,inherit);flex:none;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));border-radius:8px;padding:2px}',\n '.dsgc-rounds .dsgc-roundbtn{border:none;background:none;color:var(--dsw-alias-label-secondary,inherit);cursor:pointer;padding:3px;border-radius:5px;line-height:0;transition:background-color .12s,color .12s}',\n '.dsgc-rounds .dsgc-roundbtn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.15));color:var(--dsw-alias-label-primary,inherit)}',\n '.dsgc-rounds .dsgc-roundbtn:disabled{opacity:.4;cursor:default}',\n '.dsgc-rounds .dsgc-roundnum{width:26px;text-align:center;font-variant-numeric:tabular-nums;font-weight:600;color:var(--dsw-alias-label-primary,inherit)}',\n /* ===== @成员 / @文件弹层 ===== */\n '.dsgc-mentionwrap{position:relative}',\n '.dsgc-mention{animation:dsgc-pop-in .16s cubic-bezier(.16,1,.3,1);position:absolute;left:0;right:0;bottom:calc(100% + 6px);background:var(--dsw-alias-bg-layer-3,#fff);border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));border-radius:10px;box-shadow:var(--dsw-shadow-lv3,0 8px 24px rgba(0,0,0,.18));max-height:220px;overflow-y:auto;padding:4px;z-index:30;display:flex;flex-direction:column;gap:2px;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent}',\n '.dsgc-mentionitem{display:flex;align-items:center;gap:8px;border:none;background:none;color:var(--dsw-alias-label-secondary,inherit);font:inherit;font-size:12.5px;text-align:left;cursor:pointer;padding:6px 8px;border-radius:6px;transition:background-color .12s,color .12s}',\n '.dsgc-mentionitem.on,.dsgc-mentionitem:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.15));color:var(--dsw-alias-label-primary,inherit)}',\n '.dsgc-mentionname{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:500}',\n '.dsgc-mentionmodel{font-size:11px;color:var(--dsw-alias-label-tertiary,inherit)}',\n '.dsgc-mentionhint{font-size:11px;color:var(--dsw-alias-label-tertiary,inherit);padding:2px 8px 1px}',\n '.dsgc-mention-file .dsgc-mentionitem.dsgc-hint{cursor:default;color:var(--dsw-alias-label-tertiary,inherit);justify-content:center}',\n '.dsgc-mention-file .dsgc-mentionitem.dsgc-hint:hover{background:none}',\n /* 文件检索:宿主 FileTypeIcon 分色字形 + 井位底,文件夹/文件扫一眼可分 */\n '.dsgc-fileglyph{flex:none;width:22px;height:22px;display:inline-flex;align-items:center;justify-content:center;border-radius:5px}',\n '.dsgc-fileglyph.dir{background:color-mix(in srgb,var(--dsw-static-amber-400,#e8912d) 16%,transparent)}',\n '.dsgc-fileglyph.file{background:var(--dsw-alias-bg-module-platform,rgba(128,128,128,.12))}',\n '.dsgc-filedrill{flex:none;display:inline-flex;color:var(--dsw-alias-label-tertiary,inherit)}',\n '.dsgc-mentionitem.on .dsgc-filedrill,.dsgc-mentionitem:hover .dsgc-filedrill{color:var(--dsw-alias-label-secondary,inherit)}',\n '.dsgc-chipin-file{background:color-mix(in srgb,var(--dsw-static-neutral-bluish-300,rgba(128,128,128,.55)) 18%,transparent)}',\n '.dsgc-chipin-file[data-dir=\"1\"]{background:color-mix(in srgb,var(--dsw-static-amber-400,#e8912d) 18%,transparent)}',\n '.dsgc-chipglyph{flex:none;width:14px;height:14px;display:inline-flex;align-items:center;justify-content:center;overflow:hidden}',\n '.dsgc-chipglyph svg{display:block}',\n /* ===== 右上下文栏 ===== */\n '.dsgc-aside{width:304px;flex:none;display:flex;flex-direction:column;gap:10px;border-left:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.2));padding:12px;min-height:0;overflow-y:auto;overflow-x:hidden;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent;transition:width .28s cubic-bezier(.16,1,.3,1),opacity .18s ease,padding .28s cubic-bezier(.16,1,.3,1),border-left-width .28s cubic-bezier(.16,1,.3,1)}',\n /* 子元素经 flex 列默认 stretch 填满内容区(面板为 content-box、内容区实宽\n 304px;旧版写死 280px 曾致右侧多出 24px 死区) */\n '.dsgc-aside>*{flex:none}',\n '.dsgc-aside.closed{width:0;opacity:0;padding-left:0;padding-right:0;border-left-width:0;visibility:hidden;transition:width .24s ease-in,opacity .16s ease-in,padding .24s ease-in,border-left-width .24s ease-in,visibility 0s .22s}',\n '.dsgc-sec{display:flex;flex-direction:column;gap:8px;flex:none}',\n '.dsgc-sechead{display:flex;align-items:center;gap:6px;font-weight:600;font-size:12px;color:var(--dsw-alias-label-tertiary,inherit);padding-top:2px}',\n '.dsgc-sechead .dsgc-secspacer{flex:1}',\n '.dsgc-seccount{font-weight:500;color:var(--dsw-alias-label-tertiary,inherit)}',\n '.dsgc-roles{display:flex;flex-direction:column;gap:8px}',\n '.dsgc-role{border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));background:var(--dsw-alias-bg-layer-3,transparent);border-radius:12px;padding:10px 12px;display:flex;flex-direction:column;gap:7px;transition:border-color .16s,background-color .16s;list-style:none;text-align:left;font:inherit;cursor:pointer;color:inherit}',\n '.dsgc-role:hover{border-color:var(--dsw-alias-label-dimmed,rgba(128,128,128,.5))}',\n '.dsgc-rolehead{display:flex;gap:8px;align-items:center}',\n '.dsgc-roledot{width:10px;height:10px;border-radius:50%;flex:none}',\n '.dsgc-rolename{font-weight:600;font-size:13px;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-primary,inherit)}',\n '.dsgc-role.off .dsgc-rolename{color:var(--dsw-alias-label-tertiary,inherit)}',\n '.dsgc-rolepersona{font-size:11.5px;color:var(--dsw-alias-label-tertiary,inherit);line-height:1.5;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;min-height:0}',\n '.dsgc-rolemodel{width:fit-content;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;background:var(--dsw-alias-bg-module-platform,rgba(128,128,128,.12));border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px;color:var(--dsw-alias-label-secondary,inherit)}',\n '.dsgc-roleops{display:flex;gap:2px;flex:none;opacity:0;transition:opacity .12s}',\n '.dsgc-role:hover .dsgc-roleops,.dsgc-role:focus-within .dsgc-roleops{opacity:1}',\n '.dsgc-rolemenu{display:flex;align-items:center;justify-content:space-between;gap:8px}',\n /* ===== 表单与控件(角色抽屉内) ===== */\n '.dsgc-field{display:flex;flex-direction:column;gap:5px}',\n '.dsgc-field>label{font-size:12px;font-weight:500;color:var(--dsw-alias-label-secondary,inherit)}',\n '.dsgc-input,.dsgc-select,.dsgc-textarea{background:var(--dsw-specific-input-major,var(--dsw-alias-bg-layer-3,transparent));border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));color:var(--dsw-alias-label-primary,inherit);font:inherit;font-size:13px;border-radius:8px;padding:6px 10px;width:100%;box-sizing:border-box;outline:none;transition:border-color .16s,background-color .16s}',\n '.dsgc-input:focus,.dsgc-select:focus,.dsgc-textarea:focus{border-color:var(--dsw-alias-state-business-primary,#4f6ef7)}',\n '.dsgc-input::placeholder,.dsgc-textarea::placeholder{color:var(--dsw-alias-label-tertiary,inherit)}',\n '.dsgc-textarea{resize:vertical;min-height:76px}',\n '.dsgc-palette{display:flex;gap:6px;flex-wrap:wrap}',\n '.dsgc-dot{width:18px;height:18px;border-radius:50%;border:2px solid transparent;cursor:pointer;padding:0;transition:transform .12s}',\n '.dsgc-dot:hover{transform:scale(1.12)}',\n '.dsgc-dot.on{border-color:var(--dsw-alias-label-primary,#fff)}',\n '.dsgc-form{display:flex;flex-direction:column;gap:12px}',\n '.dsgc-formerr{font-size:12px;color:var(--dsw-alias-state-error-primary,#e5484d);line-height:1.5}',\n '.dsgc-selhint{font-size:12px;color:var(--dsw-alias-label-tertiary,inherit);line-height:1.5;display:flex;gap:6px;align-items:center;flex-wrap:wrap}',\n /* ===== 角色编辑抽屉(右侧滑出) ===== */\n '.dsgc-drawer{position:absolute;top:0;right:0;bottom:0;width:380px;max-width:calc(100% - 40px);z-index:20;background:var(--dsw-alias-bg-layer-2,var(--dsw-alias-bg-base,#fff));border-left:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));box-shadow:-12px 0 32px rgba(0,0,0,.14);display:flex;flex-direction:column;animation:dsgc-drawer-in .22s cubic-bezier(.16,1,.3,1)}',\n '.dsgc-drawer.closing{animation:dsgc-drawer-out .14s ease-in forwards;pointer-events:none}',\n '@keyframes dsgc-drawer-in{from{transform:translateX(32px);opacity:0}to{transform:none;opacity:1}}',\n '@keyframes dsgc-drawer-out{to{transform:translateX(32px);opacity:0}}',\n '@keyframes dsgc-msg-in{from{opacity:0;transform:translateY(6px)}}',\n '@keyframes dsgc-sys-in{from{opacity:0;transform:scale(.96)}}',\n '@keyframes dsgc-think-in{from{opacity:0;transform:translateY(-3px)}}',\n '@keyframes dsgc-pop-in{from{opacity:0;transform:translateY(4px)}}',\n '@keyframes dsgc-rise-in{from{opacity:0;transform:translate(-50%,6px)}}',\n '@keyframes dsgc-fade-in{from{opacity:0}}',\n '@keyframes dsgc-presence{0%,100%{box-shadow:0 0 0 0 color-mix(in srgb,var(--role-color,#4f6ef7) 0%,transparent)}50%{box-shadow:0 0 0 4px var(--presence-ring)}}',\n '.dsgc-drawerhead{display:flex;align-items:center;gap:8px;padding:14px 16px;border-bottom:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.2));flex:none}',\n '.dsgc-drawertitle{flex:1;font-size:14px;font-weight:600;color:var(--dsw-alias-label-primary,inherit)}',\n '.dsgc-drawerbody{flex:1;overflow-y:auto;padding:16px;min-height:0;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent}',\n '.dsgc-drawerfoot{display:flex;gap:8px;justify-content:flex-end;padding:12px 16px;border-top:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.2));flex:none}',\n /* ===== 文件浏览器(目录选择) ===== */\n '.dsgc-fb{border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));background:var(--dsw-alias-bg-layer-2,transparent);border-radius:8px;display:flex;flex-direction:column;gap:6px;padding:8px;animation:dsgc-fade-in .2s ease-out}',\n '.dsgc-fbhead{display:flex;align-items:center;justify-content:space-between;gap:8px;min-width:0}',\n '.dsgc-fbhead button{flex:none;white-space:nowrap}',\n '.dsgc-wsrow{display:flex;gap:6px;align-items:center;min-width:0}',\n '.dsgc-wsrow .dsgc-input{width:auto;flex:1;min-width:0}',\n '.dsgc-wsrow>button{flex:none;white-space:nowrap}',\n '.dsgc-nav>button{white-space:nowrap;overflow:hidden}',\n '.dsgc-fbpath{flex:1;min-width:0;font-size:11px;color:var(--dsw-alias-label-secondary,inherit);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',\n '.dsgc-fblist{display:flex;flex-direction:column;gap:1px;max-height:220px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent}',\n '.dsgc-fbrow{display:flex;align-items:center;gap:7px;width:100%;border:none;background:none;color:var(--dsw-alias-label-primary,inherit);font:inherit;font-size:12.5px;text-align:left;cursor:pointer;padding:3px 8px;border-radius:6px;transition:background-color .12s}',\n '.dsgc-fbrow:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.15))}',\n '.dsgc-fbrow.dim{opacity:.55}',\n '.dsgc-fbrow.file{cursor:default}',\n '.dsgc-fbrow.file:hover{background:none}',\n '.dsgc-fbname{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',\n '.dsgc-fbsize{flex:none;font-size:10.5px;color:var(--dsw-alias-label-tertiary,inherit)}',\n /* ===== 键盘焦点 ===== */\n '.dsgc-partchip:focus-visible,.dsgc-mentionitem:focus-visible,.dsgc-dot:focus-visible,.dsgc-opbtn:focus-visible,.dsgc-twist:focus-visible,.dsgc-addsess:focus-visible,.dsgc-grow-row:focus-visible,.dsgc-sess-row:focus-visible,.dsgc-rename:focus-visible,.dsgc-fbrow:focus-visible,.dsgc-role:focus-visible,.dsgc-roundbtn:focus-visible,.dsgc-tobtn:focus-visible,.dsgc-seambtn:focus-visible{outline:2px solid var(--dsw-alias-brand-primary,var(--dsw-alias-state-business-primary,#4f6ef7));outline-offset:1px}',\n /* ===== 窄容器:右栏覆盖式呈现 ===== */\n '@container (max-width: 880px){.dsgc-aside{position:absolute;top:0;right:0;bottom:0;z-index:15;width:min(304px,88%);box-shadow:-12px 0 32px rgba(0,0,0,.16);border-left:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));transition:transform .3s cubic-bezier(.16,1,.3,1),opacity .2s ease}.dsgc-aside.closed{width:min(304px,88%);padding-left:12px;padding-right:12px;border-left-width:1px;transform:translateX(calc(100% + 14px));opacity:0;transition:transform .26s ease-in,opacity .18s ease-in,visibility 0s .24s}.dsgc-seambtn.right:not(.closed){right:min(304px,88%)}}',\n '@container (max-width: 640px){.dsgc-nav{width:200px}.dsgc-msgbody{max-width:88%}}',\n /* ===== 侧边栏入口对齐(外壳将插槽内容包在 panelGlyph span 内,必须用后代 :has) ===== */\n '[class*=\"panelList\"]:has(.dsgc-entryOverlay){margin-top:4px}',\n '[class*=\"panelRow\"]:has(.dsgc-entryOverlay){position:relative;box-sizing:border-box;height:36px;min-height:36px;padding:0 10px;font-size:13px;transition:background-color .12s,color .12s}',\n '[class*=\"panelRow\"][class*=\"panelActive\"]:has(.dsgc-entryOverlay){font-weight:600}',\n /* 入口 hover:宿主 panelRow:hover 只给灰底、不变文字色(低强度到近无感);\n 对齐任务看板入口行——hover 灰底 + 文字/图标转 label-primary */\n '[class*=\"panelRow\"]:has(.dsgc-entryOverlay):hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.12));color:var(--dsw-alias-label-primary,inherit)}',\n /* DOM 注入式全幅视图(任务看板 data-dsh-taskboard-active / SSH data-dsh-ssh-active)\n 激活时接管中央列:外壳面板状态机未变(activePanelId 仍指向群聊),但视图已被\n 覆盖——群聊入口随之视觉复位,避免停留“激活”态误导当前所在视图。两行特异性\n 相同(0,4,1),hover 行在后,复位不吞 hover 反馈 */\n 'html[data-dsh-taskboard-active] [class*=\"panelRow\"][class*=\"panelActive\"]:has(.dsgc-entryOverlay),html[data-dsh-ssh-active] [class*=\"panelRow\"][class*=\"panelActive\"]:has(.dsgc-entryOverlay){background:transparent;color:var(--dsw-alias-label-secondary,inherit);font-weight:400}',\n 'html[data-dsh-taskboard-active] [class*=\"panelRow\"]:has(.dsgc-entryOverlay):hover,html[data-dsh-ssh-active] [class*=\"panelRow\"]:has(.dsgc-entryOverlay):hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.12));color:var(--dsw-alias-label-primary,inherit)}',\n /* 收起态例外:外壳把收起栏所有面板图标统一为 primary 色(激活与否不由颜色表达),\n 复位规则不得把群聊图标调暗成 secondary;仅去掉激活底色即可 */\n 'html[data-dsh-taskboard-active] [data-sidebar-collapsed] [class*=\"panelRow\"]:has(.dsgc-entryOverlay),html[data-dsh-ssh-active] [data-sidebar-collapsed] [class*=\"panelRow\"]:has(.dsgc-entryOverlay),html[data-dsh-taskboard-active] [class*=\"collapsed\"] [class*=\"panelRow\"]:has(.dsgc-entryOverlay),html[data-dsh-ssh-active] [class*=\"collapsed\"] [class*=\"panelRow\"]:has(.dsgc-entryOverlay){color:var(--dsw-alias-label-primary,inherit)}',\n '[class*=\"panelRow\"]:has(.dsgc-entryOverlay) > [class*=\"panelTitle\"]{padding-left:24px}',\n '.dsgc-entryOverlay{position:absolute;inset:0;display:flex;align-items:center;padding:0 10px;box-sizing:border-box}',\n '.dsgc-entryIcon{flex:none;width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center}',\n '.dsgc-entryIcon svg{width:18px;height:18px;display:block}',\n '[data-sidebar-collapsed] .dsgc-entryOverlay,[class*=\"collapsed\"] .dsgc-entryOverlay{justify-content:center;padding:0}',\n '[data-sidebar-collapsed] [class*=\"panelRow\"]:has(.dsgc-entryOverlay),[class*=\"collapsed\"] [class*=\"panelRow\"]:has(.dsgc-entryOverlay){margin:0 auto}',\n '@media (prefers-reduced-motion:reduce){.dsgc-dot,.dsgc-partchip,.dsgc-mentionitem,.dsgc-grow-row,.dsgc-sess-row,.dsgc-opbtn,.dsgc-addsess,.dsgc-topic,.dsgc-role,.dsgc-rename,.dsgc-input,.dsgc-select,.dsgc-textarea,.dsgc-fbrow,.dsgc-twist svg,.dsgc-roleops,.dsgc-roundbtn,.dsgc-permtrigger,.dsgc-permchevron,.dsgc-tobtn,.dsgc-seambtn,.dsgc-aside,.dsgc-aside.closed,.dsgc-nav,.dsgc-nav.closed,.dsgc-clearbtn,[class*=\"panelRow\"]:has(.dsgc-entryOverlay){transition:none}.dsgc-dot:hover{transform:none}.dsgc-drawer,.dsgc-msg,.dsgc-sysmsg,.dsgc-mention,.dsgc-tobottom,.dsgc-err,.dsgc-empty,.dsgc-fb,.dsgc-think .dsgc-thinkbody,.dsgc-msg.live .dsgc-avatar,.dsgc-loading svg,.dsgc-pendingdots i,.dsgc-typing{animation:none}.dsgc-typing{background-position:0 0;background-size:100% 100%}}',\n /* ===== 设置页(同一卡片语言) ===== */\n '.dgcs-page{display:flex;flex-direction:column;gap:14px;padding:4px 0}',\n '.dgcs-head{display:flex;flex-direction:column;gap:6px}',\n '.dgcs-title{margin:0;font-size:15px;font-weight:600;line-height:1.4;color:var(--dsw-alias-label-primary,inherit)}',\n '.dgcs-desc{margin:0;font-size:13px;line-height:1.6;color:var(--dsw-alias-label-secondary,inherit)}',\n '.dgcs-card{display:flex;align-items:center;justify-content:space-between;gap:12px;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));background:var(--dsw-alias-bg-layer-3,transparent);border-radius:12px;padding:14px 16px;transition:border-color .16s}',\n '.dgcs-cardtext{display:flex;flex-direction:column;gap:3px;min-width:0}',\n '.dgcs-cardtitle{font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary,inherit)}',\n '.dgcs-cardhint{font-size:12px;color:var(--dsw-alias-label-tertiary,inherit)}',\n].join('\\n')\n\n/** 工厂执行时幂等注入样式标签(loader 卸载时按 data-plugin 摘除)。 */\nexport function injectStyles(): void {\n if (typeof document === 'undefined') return\n if (document.querySelector('style[data-plugin-css=' + JSON.stringify(TAG_ID) + ']') === null) {\n const tag = document.createElement('style')\n tag.dataset.plugin = 'dsh-group-chat'\n tag.dataset.pluginCss = TAG_ID\n tag.textContent = CSS\n document.head.appendChild(tag)\n }\n}\n","/**\n * 浏览器半 UI 基座:DSW 原语(shell 静态种子模块,loader 模块表 external)\n * 与动态图标 / 命令式 createElement 辅助。组件主体已 JSX 化(.tsx);此处\n * 仅保留 slot 注册回调与动态图标表需要的少量命令式辅助。\n * @module dsh-group-chat/client/ui\n */\n\nimport { createElement, type ReactNode } from 'react'\nimport * as P from '@deepseek-ai/dsh-client-ui-primitives'\n\nexport { P }\n\n/** 命令式 createElement(仅 slot 注册回调用)。 */\nexport const h = createElement as unknown as (type: unknown, props?: Record<string, unknown> | null, ...children: unknown[]) => ReactNode\n\n/** 图标组件的调用形态。 */\nexport type IconComponent = (props: Record<string, unknown>) => ReactNode\n\n/** 按名取 DSW 原语(图标表驱动)。 */\nexport function pickPrimitive(name: string): IconComponent {\n return (P as unknown as Record<string, IconComponent>)[name]\n}\n\n/** 以统一 size 包装图标组件调用(放在 JSX 子元素位)。 */\nexport function Icon(comp: unknown, size: number, extra?: Record<string, unknown>): ReactNode {\n return h(comp as never, Object.assign({ size }, extra || {}))\n}\n","/**\n * 会话状态派生(纯函数):从快照 run 派生单个会话的列表状态,\n * 语义对齐 DSH 主会话列表(StateDot 五态取四)。\n *\n * 优先级:等待确认 > 进行中 > 已完成/已出错 > 默认(无点)。\n * - ongoing:run 进行中(含用户已点停止但未停完的 stopping 窗口)\n * - warning:run_command 确认闸门挂起(仅工作区内修改档)\n * - done/error:run 结束后的「输出完毕」标记(正常/停止 → done,发言失败 → error)\n * - idle:无任何活动(不渲染状态点,对齐主 GUI idle 隐藏)\n * @module dsh-group-chat/core/status\n */\n\nimport type { Snapshot } from './types.ts'\n\n/** 会话列表状态(取值即 StateDotState 的渲染态)。 */\nexport type SessStatus = 'idle' | 'ongoing' | 'warning' | 'done' | 'error'\n\n/** 状态点悬停/读屏文案(idle 不渲染点,无文案)。 */\nexport const SESS_STATUS_LABEL: Record<SessStatus, string> = {\n idle: '',\n ongoing: '进行中',\n warning: '等待确认',\n done: '已完成',\n error: '已出错',\n}\n\n/** 派生单个会话的列表状态(run 为快照的 run 视图)。 */\nexport function sessStatus(run: Snapshot['run'], sessionId: string): SessStatus {\n if (run.running && run.sessionId === sessionId) return run.pendingConfirm ? 'warning' : 'ongoing'\n const f = run.finished\n if (f && f.sessionId === sessionId) return f.reason === 'error' ? 'error' : 'done'\n return 'idle'\n}\n","/**\n * 浏览器半共享常量与小工具(纯函数,无 React 依赖)。\n * @module dsh-group-chat/client/model\n */\n\nimport type { RoleRecord, Snapshot, ToolCallRecord } from '../../core/types.ts'\n\n/** 会话列表状态派生与文案(core 纯函数,供 NavPanel 渲染)。 */\nexport { sessStatus, SESS_STATUS_LABEL, type SessStatus } from '../../core/status.ts'\n\n/** 角色标识色调色板(与宿主半一致)。 */\nexport const PALETTE = ['#5b8def', '#22a06b', '#e8912d', '#c678dd', '#e05661', '#56b6c2', '#98c379', '#d19a66']\n\n/** Host HTTP API 前缀。 */\nexport const API_PREFIX = '/api/group-chat'\n\n/** MarkdownText 渲染文案。 */\nexport const MD_LABELS = Object.freeze({ code: { copyLabel: '复制', copiedLabel: '已复制' }, footnotes: '脚注' })\n\n/** 快照的 wire 形态(响应里带 ok 标记)。 */\nexport type ClientSnapshot = Snapshot & { ok: boolean }\n\n/** models action 的响应形态。 */\nexport interface ModelsResponse {\n ok: boolean\n providers?: { id: string, name?: string }[]\n modelsByProvider?: Record<string, { id: string, name?: string }[]>\n error?: string\n}\n\n/** efforts action 的响应形态。 */\nexport interface EffortsResponse {\n ok: boolean\n efforts?: { id: string, name: string, description?: string }[]\n defaultEffort?: string\n error?: string\n}\n\n/** 快照内的角色/会话/群组视图行。 */\nexport type SnapshotRole = Snapshot['roles'][number]\nexport type SnapshotSession = Snapshot['sessions'][number]\nexport type SnapshotGroup = Snapshot['groups'][number]\nexport type SnapshotMessage = Snapshot['messages'][number]\n\nexport function roleById(s: ClientSnapshot, id: string | null): SnapshotRole | null {\n for (const r of s.roles) if (r.id === id) return r\n return null\n}\n\nexport function sessById(s: ClientSnapshot, id: string): SnapshotSession | null {\n for (const x of s.sessions) if (x.id === id) return x\n return null\n}\n\nexport function groupById(s: ClientSnapshot, id: string): SnapshotGroup | null {\n for (const g of s.groups) if (g.id === id) return g\n return null\n}\n\nexport function escapeRegExp(v: string): string {\n return String(v).replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\nexport function firstLine(text: string): string {\n const i = text.indexOf('\\n')\n return i === -1 ? text : text.slice(0, i)\n}\n\nexport function latestLine(text: string): string {\n const visible = text.trimEnd()\n const i = visible.lastIndexOf('\\n')\n return i === -1 ? visible : visible.slice(i + 1)\n}\n\nexport function fmtTime(ts: number): string {\n const delta = Math.max(0, Date.now() - ts)\n if (delta < 60000) return '刚刚'\n if (delta < 3600000) return Math.floor(delta / 60000) + ' 分钟前'\n if (delta < 86400000) return Math.floor(delta / 3600000) + ' 小时前'\n const d = new Date(ts)\n const sameYear = d.getFullYear() === new Date().getFullYear()\n const pad = (n: number): string => (n < 10 ? '0' + n : '' + n)\n return sameYear ? (d.getMonth() + 1) + '月' + d.getDate() + '日' : d.getFullYear() + '/' + (d.getMonth() + 1) + '/' + d.getDate()\n}\n\n/** 角色编辑抽屉的草稿形态(编辑与新建共用)。 */\nexport interface RoleDraft {\n id?: string\n name: string\n color: string | null\n persona: string\n provider: string\n model: string\n temperature?: number\n reasoningEffort: string\n enabled?: boolean\n thinking: boolean\n}\n\nexport function draftFromRole(role: SnapshotRole): RoleDraft {\n return { id: role.id, name: role.name, color: role.color ?? null, persona: role.persona, provider: role.provider, model: role.model, temperature: role.temperature, reasoningEffort: role.reasoningEffort || 'default', enabled: role.enabled, thinking: role.thinking === true }\n}\n\nexport function blankDraft(): RoleDraft {\n return { name: '', color: null, persona: '', provider: '', model: '', temperature: undefined, reasoningEffort: 'default', enabled: true, thinking: false }\n}\n\n/** 工具调用行的展示参数。 */\nexport type ToolCallView = ToolCallRecord\n\n/** 草稿是否可作为角色落库(宿主侧再校验一次)。 */\nexport function draftMissing(draft: RoleDraft): string {\n if (!draft.name.trim()) return '角色名称不能为空'\n if (!draft.provider || !draft.model) return '请选择角色绑定的模型'\n return ''\n}\n\n/** RoleRecord 兼容视图(快照角色行即其展示子集)。 */\nexport type RoleView = RoleRecord\n","/**\n * 浏览器半 transport:/api/group-chat/* 同源 JSON 端点。\n * @module dsh-group-chat/client/api\n */\n\nimport { API_PREFIX } from './model.ts'\n\nasync function readJson<T>(fetchPromise: Promise<Response>): Promise<T> {\n const response = await fetchPromise\n const body = await response.json() as { error?: string }\n if (!response.ok) throw new Error(body && body.error ? body.error : '请求失败(HTTP ' + response.status + '),请稍后重试')\n return body as unknown as T\n}\n\nexport const api = {\n state: (): Promise<unknown> => readJson(fetch(API_PREFIX + '/state', { cache: 'no-store' })),\n action: (payload: Record<string, unknown>, signal?: AbortSignal): Promise<unknown> => readJson(fetch(API_PREFIX + '/action', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n signal,\n })),\n}\n","/**\n * 角色编辑抽屉(右侧滑出,不遮挡会话流阅读)。\n * @module dsh-group-chat/client/drawer\n */\n\nimport { useEffect, useState, type ReactNode } from 'react'\nimport { Icon, P } from '../lib/ui.ts'\nimport { api } from '../lib/api.ts'\nimport { PALETTE, type EffortsResponse, type ModelsResponse, type RoleDraft } from '../lib/model.ts'\n\nexport interface RoleDrawerProps {\n draft: RoleDraft\n set: (draft: RoleDraft) => void\n models: ModelsResponse | null\n modelsError: string | null\n onRetryModels: () => void\n onSave: () => void\n onCancel: () => void\n formError: string\n}\n\nexport function RoleDrawer(props: RoleDrawerProps): ReactNode {\n const { draft, set } = props\n const models = props.models\n const providers = (models && models.providers) || []\n const modelsOf = (models && models.modelsByProvider && models.modelsByProvider[draft.provider]) || []\n const [closing, setClosing] = useState(false)\n const [effortsInfo, setEffortsInfo] = useState<EffortsResponse | null>(null)\n const close = (): void => {\n if (closing) return\n setClosing(true)\n window.setTimeout(() => props.onCancel(), 140)\n }\n const onProvider = (e: { target: { value: string } }): void => {\n const p = e.target.value\n const list = (models && models.modelsByProvider && models.modelsByProvider[p]) || []\n // 换模型路线后旧推理级别失效,重置为默认\n set(Object.assign({}, draft, { provider: p, model: list.length ? list[0].id : '', reasoningEffort: 'default' }))\n }\n useEffect(() => {\n const onKey = (e: KeyboardEvent): void => { if (e.key === 'Escape') close() }\n document.addEventListener('keydown', onKey)\n return () => document.removeEventListener('keydown', onKey)\n }, [])\n // 推理级别选项:跟随抽屉内 provider/model 变化重新查询(Host 60s 缓存)\n useEffect(() => {\n let live = true\n setEffortsInfo(null)\n if (!draft.provider || !draft.model) return\n api.action({ kind: 'efforts', provider: draft.provider, model: draft.model }).then((res) => {\n if (!live) return\n const r = res as EffortsResponse\n if (r && r.ok) setEffortsInfo({ ok: true, efforts: r.efforts || [], defaultEffort: r.defaultEffort })\n else setEffortsInfo({ ok: false, efforts: [], defaultEffort: undefined, error: (r && r.error) || '查询失败' })\n }).catch((e: unknown) => { if (live) setEffortsInfo({ ok: false, efforts: [], defaultEffort: undefined, error: String((e && (e as Error).message) || e) }) })\n return () => { live = false }\n }, [draft.provider, draft.model])\n return (\n <div className={'dsgc-drawer' + (closing ? ' closing' : '')} role=\"dialog\" aria-modal=\"false\" aria-label={draft.id ? '编辑角色' : '添加角色'}>\n <div className=\"dsgc-drawerhead\">\n {Icon(P.IconUserOutline16, 16)}\n <span className=\"dsgc-drawertitle\">{draft.id ? '编辑角色' : '添加角色'}</span>\n <P.Button variant=\"ghost\" size=\"sm\" onClick={close} aria-label=\"关闭\">{Icon(P.IconCloseOutline16, 16)}</P.Button>\n </div>\n <div className=\"dsgc-drawerbody\">\n <div className=\"dsgc-form\">\n <div className=\"dsgc-field\">\n <label>名称</label>\n <input\n className=\"dsgc-input\"\n value={draft.name}\n autoFocus={!draft.id}\n onChange={(e) => { set(Object.assign({}, draft, { name: e.target.value })) }}\n placeholder=\"例如:产品经理\"\n />\n </div>\n <div className=\"dsgc-field\">\n <label>标识色</label>\n <div className=\"dsgc-palette\">\n {PALETTE.map((c) => (\n <button\n key={c}\n type=\"button\"\n className={'dsgc-dot' + (draft.color === c ? ' on' : '')}\n style={{ background: c }}\n onClick={() => { set(Object.assign({}, draft, { color: c })) }}\n aria-label={'选择标识色 ' + c}\n />\n ))}\n </div>\n </div>\n <div className=\"dsgc-field\">\n <label>人设 / 角色设定</label>\n <textarea\n className=\"dsgc-textarea\"\n rows={4}\n value={draft.persona}\n onChange={(e) => { set(Object.assign({}, draft, { persona: e.target.value })) }}\n placeholder=\"性格、立场、说话风格、专业背景……\"\n />\n </div>\n <div className=\"dsgc-field\">\n <label>模型提供方</label>\n {providers.length\n ? (\n <select className=\"dsgc-select\" value={draft.provider} onChange={onProvider}>\n <option value=\"\">选择提供方…</option>\n {providers.map((p) => <option key={p.id} value={p.id}>{p.name || p.id}</option>)}\n </select>\n )\n : (\n <div className=\"dsgc-selhint\">\n {(props.modelsError ? '模型目录加载失败:' + props.modelsError : '暂无可用 provider') + ' '}\n <P.Button variant=\"outline\" size=\"sm\" onClick={props.onRetryModels}>重试</P.Button>\n </div>\n )}\n </div>\n <div className=\"dsgc-field\">\n <label>模型</label>\n {modelsOf.length\n ? (\n <select\n className=\"dsgc-select\"\n value={draft.model}\n onChange={(e) => { set(Object.assign({}, draft, { model: e.target.value, reasoningEffort: 'default' })) }}\n >\n {modelsOf.map((m) => <option key={m.id} value={m.id}>{m.name || m.id}</option>)}\n </select>\n )\n : <div className=\"dsgc-selhint\">请先选择有可用模型的提供方</div>}\n </div>\n <div className=\"dsgc-field\">\n <label>温度(可选)</label>\n <input\n className=\"dsgc-input\"\n type=\"number\"\n step=\"0.1\"\n min=\"0\"\n max=\"2\"\n value={draft.temperature == null ? '' : String(draft.temperature)}\n onChange={(e) => { set(Object.assign({}, draft, { temperature: e.target.value === '' ? undefined : Number(e.target.value) })) }}\n />\n </div>\n <div className=\"dsgc-field\">\n <label>深度思考</label>\n <div style={{ display: 'flex', gap: 10, alignItems: 'center' }}>\n <P.Switch checked={draft.thinking === true} onChange={(v: boolean) => { set(Object.assign({}, draft, { thinking: v })) }} label=\"深度思考\" />\n <span className=\"dsgc-hint\">开启后角色发言前先思考(支持思考的模型)</span>\n </div>\n </div>\n {draft.thinking === true\n ? (\n <div className=\"dsgc-field\">\n <label>推理级别</label>\n {effortsInfo === null\n ? <div className=\"dsgc-selhint\">查询推理级别…</div>\n : !effortsInfo.ok\n ? <div className=\"dsgc-selhint\">推理级别查询失败:{effortsInfo.error}(若刚更新插件,请重启 dsh web 使 host 半生效)</div>\n : (effortsInfo.efforts || []).length\n ? (\n <select\n className=\"dsgc-select\"\n value={draft.reasoningEffort && draft.reasoningEffort !== 'default' ? draft.reasoningEffort : 'default'}\n onChange={(e) => { set(Object.assign({}, draft, { reasoningEffort: e.target.value })) }}\n title=\"取自当前模型设置中的推理选项;默认 = 使用该模型的默认推理级别\"\n >\n <option value=\"default\">\n 默认{effortsInfo.defaultEffort ? '(当前默认:' + ((effortsInfo.efforts || []).find((x) => x.id === effortsInfo.defaultEffort) || { name: '' }).name + ')' : ''}\n </option>\n {(effortsInfo.efforts || []).map((e) => <option key={e.id} value={e.id} title={e.description || ''}>{e.name || e.id}</option>)}\n </select>\n )\n : <div className=\"dsgc-selhint\">当前模型未提供推理等级,将使用默认</div>}\n </div>\n )\n : null}\n {props.formError ? <div className=\"dsgc-formerr\">{props.formError}</div> : null}\n </div>\n </div>\n <div className=\"dsgc-drawerfoot\">\n <P.Button variant=\"outline\" onClick={close}>取消</P.Button>\n <P.Button variant=\"primary\" onClick={props.onSave}>{draft.id ? '保存' : '添加'}</P.Button>\n </div>\n </div>\n )\n}\n","/**\n * 左侧导航栏组件\n * @module dsh-group-chat/client/components\n */\n\nimport type { ReactNode, KeyboardEvent as ReactKeyboardEvent } from 'react'\nimport { Icon, P } from '../lib/ui.ts'\nimport { groupById, sessById, sessStatus, SESS_STATUS_LABEL, type ClientSnapshot } from '../lib/model.ts'\n\ninterface NavPanelProps {\n snap: ClientSnapshot\n search: string\n setSearch: (val: string) => void\n collapsedGroups: Set<string>\n setCollapsedGroups: (fn: (prev: Set<string>) => Set<string>) => void\n gid: string | null\n sid: string | null\n setGid: (val: string) => void\n setSid: (val: string) => void\n setPartsSel: (val: string[] | null) => void\n renameDraft: { kind: 'group' | 'session', id: string, value: string } | null\n setRenameDraft: (val: { kind: 'group' | 'session', id: string, value: string } | null) => void\n confirmDel: { kind: 'group' | 'session', id: string } | null\n setConfirmDel: (val: { kind: 'group' | 'session', id: string } | null) => void\n mutate: (args: Record<string, unknown>) => Promise<unknown>\n navOpen: boolean\n}\n\nexport function NavPanel(props: NavPanelProps): ReactNode {\n const { snap, search, setSearch, collapsedGroups, setCollapsedGroups, gid, sid, setGid, setSid, setPartsSel, renameDraft, setRenameDraft, confirmDel, setConfirmDel, mutate, navOpen } = props\n\n const commitRename = async (): Promise<void> => {\n if (!renameDraft) return\n const d = renameDraft\n setRenameDraft(null)\n const value = String(d.value || '').trim()\n if (!value) return\n if (d.kind === 'group') await mutate({ op: 'renameGroup', groupId: d.id, name: value })\n else await mutate({ op: 'renameSession', sessionId: d.id, name: value })\n }\n\n const renameKeyDown = (e: ReactKeyboardEvent<HTMLInputElement>): void => {\n if (e.key === 'Enter') {\n e.preventDefault()\n void commitRename()\n } else if (e.key === 'Escape') {\n e.preventDefault()\n setRenameDraft(null)\n }\n }\n\n const doDelete = async (): Promise<void> => {\n if (!confirmDel) return\n const d = confirmDel\n setConfirmDel(null)\n if (d.kind === 'group') await mutate({ op: 'deleteGroup', groupId: d.id })\n else await mutate({ op: 'deleteSession', sessionId: d.id })\n }\n\n const q = search.trim().toLowerCase()\n const groupMatches = (g: ClientSnapshot['groups'][number]): { show: boolean, filterSessions: boolean } => {\n if (!q) return { show: true, filterSessions: false }\n if (g.name.toLowerCase().includes(q)) return { show: true, filterSessions: false }\n const hitSessions = g.sessionIds.map((id) => sessById(snap, id)).filter((s) => s && s.name.toLowerCase().includes(q))\n return { show: hitSessions.length > 0, filterSessions: true }\n }\n\n const group = gid ? groupById(snap, gid) : null\n\n const treeNodes: ReactNode[] = []\n for (const g of snap.groups) {\n const match = groupMatches(g)\n if (!match.show) continue\n const expanded = q ? true : !collapsedGroups.has(g.id)\n const isRenameGroup = renameDraft && renameDraft.kind === 'group' && renameDraft.id === g.id\n const isConfirmGroup = confirmDel && confirmDel.kind === 'group' && confirmDel.id === g.id\n const groupChildren: ReactNode[] = []\n \n if (expanded) {\n for (const sessionId of g.sessionIds) {\n const s = sessById(snap, sessionId)\n if (!s) continue\n if (match.filterSessions && !s.name.toLowerCase().includes(q)) continue\n const sess = sid ? sessById(snap, sid) : null\n const isActive = sess && s.id === sess.id && g.id === group?.id\n const isRenameSess = renameDraft && renameDraft.kind === 'session' && renameDraft.id === s.id\n const isConfirm = confirmDel && confirmDel.kind === 'session' && confirmDel.id === s.id\n // 会话状态(对齐主 GUI StateDot:idle 不渲染点)\n const st = sessStatus(snap.run, s.id)\n\n groupChildren.push(\n <div\n key={s.id}\n className={'dsgc-sess-row' + (isActive ? ' on' : '')}\n role=\"button\"\n tabIndex={0}\n onClick={() => { setGid(g.id); setSid(s.id); setPartsSel(null); setConfirmDel(null); setRenameDraft(null) }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n setGid(g.id); setSid(s.id); setPartsSel(null); setConfirmDel(null); setRenameDraft(null)\n }\n }}\n >\n {/* 固定宽度状态槽(对齐主 GUI:槽恒在、点按状态渲染——行间文案对齐) */}\n <span className=\"dsgc-sess-status\">\n {st !== 'idle'\n ? (\n <span role=\"img\" title={SESS_STATUS_LABEL[st]} aria-label={SESS_STATUS_LABEL[st]}>\n <P.StateDot state={st} size={8} />\n </span>\n )\n : null}\n </span>\n {isRenameSess\n ? (\n <input\n className=\"dsgc-rename\"\n value={renameDraft!.value}\n autoFocus\n onChange={(e) => { setRenameDraft({ kind: 'session', id: s.id, value: e.target.value }) }}\n onBlur={() => { void commitRename() }}\n onKeyDown={renameKeyDown}\n onClick={(e) => { e.stopPropagation() }}\n />\n )\n : <span className=\"dsgc-sess-name\">{s.name}</span>}\n <span className=\"dsgc-nodeops\">\n <button\n className=\"dsgc-opbtn\"\n title=\"重命名会话\"\n aria-label=\"重命名会话\"\n onClick={(e) => { e.stopPropagation(); setRenameDraft({ kind: 'session', id: s.id, value: s.name }) }}\n >\n {Icon(P.IconEditOutline16, 14)}\n </button>\n <button\n className={'dsgc-opbtn' + (isConfirm ? ' danger' : '')}\n title={isConfirm ? '再次点击确认删除' : '删除会话'}\n aria-label=\"删除会话\"\n onClick={(e) => {\n e.stopPropagation()\n if (isConfirm) void doDelete()\n else setConfirmDel({ kind: 'session', id: s.id })\n }}\n >\n {Icon(P.IconTrashOutline16, 14)}\n </button>\n </span>\n </div>,\n )\n }\n \n groupChildren.push(\n <button key=\"__add\" className=\"dsgc-addsess\" onClick={() => { void mutate({ op: 'createSession', groupId: g.id }) }}>\n {Icon(P.IconPlusOutline16, 14)}新会话\n </button>,\n )\n }\n \n treeNodes.push(\n <div key={g.id} className=\"dsgc-gnode\">\n <div\n className={'dsgc-grow-row' + (g.id === group?.id ? ' on' : '')}\n role=\"button\"\n tabIndex={0}\n onClick={() => { setGid(g.id); setPartsSel(null); setConfirmDel(null); setRenameDraft(null) }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n setGid(g.id); setPartsSel(null); setConfirmDel(null); setRenameDraft(null)\n }\n }}\n >\n <button\n className={'dsgc-twist' + (expanded ? '' : ' closed')}\n title={expanded ? '收起' : '展开'}\n aria-label={expanded ? '收起' : '展开'}\n onClick={(e) => {\n e.stopPropagation()\n setCollapsedGroups((prev) => {\n const next = new Set(prev)\n if (next.has(g.id)) next.delete(g.id)\n else next.add(g.id)\n return next\n })\n }}\n >\n {Icon(P.IconChevronDownOutline14, 14)}\n </button>\n {isRenameGroup\n ? (\n <input\n className=\"dsgc-rename\"\n value={renameDraft!.value}\n autoFocus\n onChange={(e) => { setRenameDraft({ kind: 'group', id: g.id, value: e.target.value }) }}\n onBlur={() => { void commitRename() }}\n onKeyDown={renameKeyDown}\n onClick={(e) => { e.stopPropagation() }}\n />\n )\n : <span className=\"dsgc-gname\">{g.name}</span>}\n <span className=\"dsgc-nodeops\">\n <button\n className=\"dsgc-opbtn\"\n title=\"重命名群组\"\n aria-label=\"重命名群组\"\n onClick={(e) => { e.stopPropagation(); setRenameDraft({ kind: 'group', id: g.id, value: g.name }) }}\n >\n {Icon(P.IconEditOutline16, 14)}\n </button>\n <button\n className={'dsgc-opbtn' + (isConfirmGroup ? ' danger' : '')}\n title={isConfirmGroup ? '再次点击确认删除' : '删除群组'}\n aria-label=\"删除群组\"\n onClick={(e) => {\n e.stopPropagation()\n if (isConfirmGroup) void doDelete()\n else setConfirmDel({ kind: 'group', id: g.id })\n }}\n >\n {Icon(P.IconTrashOutline16, 14)}\n </button>\n </span>\n </div>\n {expanded ? <div className=\"dsgc-sess-list\">{groupChildren}</div> : null}\n </div>,\n )\n }\n\n return (\n <div className={'dsgc-nav' + (navOpen ? '' : ' closed')} aria-hidden={navOpen ? undefined : 'true'}>\n <P.Input\n icon={Icon(P.IconSearchOutline16, 16)}\n className=\"dsgc-search\"\n placeholder=\"搜索群组与会话…\"\n value={search}\n onChange={(e: { target: { value: string } }) => setSearch(e.target.value)}\n />\n {treeNodes.length\n ? <div className=\"dsgc-tree\">{treeNodes}</div>\n : <div className=\"dsgc-hint\">{q ? '没有匹配「' + search.trim() + '」的群组或会话' : '暂无群组'}</div>}\n <P.Button variant=\"outline\" onClick={() => { void mutate({ op: 'createGroup' }) }}>\n {Icon(P.IconPlusOutline16, 16)}新建群组\n </P.Button>\n </div>\n )\n}\n","/**\n * 右侧成员与工作区栏组件\n * @module dsh-group-chat/client/components\n */\n\nimport type { ReactNode } from 'react'\nimport { Icon, P } from '../lib/ui.ts'\nimport { roleById, type ClientSnapshot, type ModelsResponse, type RoleDraft, type SnapshotRole } from '../lib/model.ts'\n\ninterface AsidePanelProps {\n snap: ClientSnapshot\n group: ClientSnapshot['groups'][number]\n asideOpen: boolean\n wsDraft: string | null\n setWsDraft: (val: string | null) => void\n fileBrowser: { open: boolean, loading: boolean, list: import('../../core/types.ts').BrowseResult | null, error: string } | null\n setFileBrowser: (val: { open: boolean, loading: boolean, list: import('../../core/types.ts').BrowseResult | null, error: string } | null) => void\n mutate: (args: Record<string, unknown>) => Promise<unknown>\n openRoleEditor: (role: SnapshotRole | null) => Promise<void>\n openBrowser: (path: string | undefined) => Promise<void>\n selectCurrentDir: () => void\n}\n\nexport function AsidePanel(props: AsidePanelProps): ReactNode {\n const { snap, group, asideOpen, wsDraft, setWsDraft, fileBrowser, setFileBrowser, mutate, openRoleEditor, openBrowser, selectCurrentDir } = props\n\n const commitWsDir = (): void => {\n if (wsDraft !== null && group && wsDraft !== (group.workspaceDir || '')) {\n void mutate({ op: 'setWorkspaceDir', groupId: group.id, path: wsDraft })\n }\n setWsDraft(null)\n }\n\n return (\n <div className={'dsgc-aside' + (asideOpen ? '' : ' closed')} aria-hidden={asideOpen ? undefined : 'true'}>\n <div className=\"dsgc-sec\">\n <div className=\"dsgc-sechead\">\n 群成员\n <span className=\"dsgc-secspacer\" />\n <span className=\"dsgc-seccount\">{group.roleIds.length ? group.roleIds.length + ' 个' : ''}</span>\n <P.Button variant=\"ghost\" size=\"sm\" onClick={() => { void openRoleEditor(null) }} aria-label=\"添加角色\">\n {Icon(P.IconPlusOutline16, 14)}添加\n </P.Button>\n </div>\n {group.roleIds.length\n ? (\n <div className=\"dsgc-roles\">\n {group.roleIds.map((rid) => {\n const r = roleById(snap, rid)\n if (!r) return null\n return (\n <div\n key={r.id}\n className={'dsgc-role' + (r.enabled ? '' : ' off')}\n role=\"button\"\n tabIndex={0}\n onClick={() => { void openRoleEditor(r) }}\n onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); void openRoleEditor(r) } }}\n title=\"点击编辑角色\"\n >\n <div className=\"dsgc-rolehead\">\n <span className=\"dsgc-roledot\" style={{ background: r.color || '#888' }} />\n <span className=\"dsgc-rolename\">{r.name}</span>\n <P.Tooltip label={r.enabled ? '停用该角色' : '启用该角色'} side=\"top\" delayMs={300}>\n <span\n onClick={(e) => { e.stopPropagation() }}\n onKeyDown={(e) => { e.stopPropagation() }}\n style={{ display: 'inline-flex', flex: 'none' }}\n >\n <P.Switch\n checked={r.enabled}\n onChange={() => { void mutate({ op: 'setRoleEnabled', roleId: r.id, enabled: !r.enabled }) }}\n label={r.enabled ? '停用该角色' : '启用该角色'}\n aria-label={(r.enabled ? '停用' : '启用') + '角色 ' + r.name}\n />\n </span>\n </P.Tooltip>\n </div>\n {r.persona ? <div className=\"dsgc-rolepersona\" title={r.persona}>{r.persona}</div> : null}\n <div className=\"dsgc-rolemenu\">\n <span\n className=\"dsgc-rolemodel\"\n title={r.provider + ' / ' + r.model + (r.thinking ? ' · 深度思考' + (r.reasoningEffort && r.reasoningEffort !== 'default' ? '(' + r.reasoningEffort + ')' : '') : '')}\n >\n {r.provider} / {r.model}\n </span>\n {r.thinking\n ? <span title=\"深度思考\" style={{ display: 'inline-flex', alignItems: 'center', color: 'var(--dsw-alias-label-tertiary,inherit)' }}>{Icon(P.IconThinkOutline14, 14)}</span>\n : null}\n <span className=\"dsgc-roleops\">\n <button\n className=\"dsgc-opbtn\"\n title=\"编辑角色\"\n aria-label=\"编辑角色\"\n onClick={(e) => { e.stopPropagation(); void openRoleEditor(r) }}\n >\n {Icon(P.IconEditOutline16, 14)}\n </button>\n <button\n className=\"dsgc-opbtn danger\"\n title=\"移除角色\"\n aria-label=\"移除角色\"\n onClick={(e) => { e.stopPropagation(); void mutate({ op: 'deleteRole', roleId: r.id }) }}\n >\n {Icon(P.IconTrashOutline16, 14)}\n </button>\n </span>\n </div>\n </div>\n )\n })}\n </div>\n )\n : <div className=\"dsgc-hint\">还没有角色。每个角色可绑定不同的 provider/model,在群内以独立身份发言。</div>}\n </div>\n <div className=\"dsgc-sec\">\n <div className=\"dsgc-sechead\">工作区目录</div>\n <div className=\"dsgc-field\">\n <div className=\"dsgc-wsrow\">\n <input\n className=\"dsgc-input\"\n value={wsDraft === null ? (group.workspaceDir || '') : wsDraft}\n placeholder=\"~/docs 或 /abs/dir\"\n onChange={(e) => { setWsDraft(e.target.value) }}\n onBlur={commitWsDir}\n onKeyDown={(e) => { if (e.key === 'Enter') (e.target as HTMLInputElement).blur() }}\n />\n <P.Button variant=\"outline\" size=\"sm\" onClick={() => { void openBrowser(wsDraft === null ? group.workspaceDir : wsDraft) }}>\n {Icon(P.IconFolderOpenOutline16, 14)}浏览\n </P.Button>\n </div>\n <div className=\"dsgc-hint\">发送时读取目录内文本文件,注入本群全体角色上下文;角色也可用工具主动查看</div>\n {group.workspaceDir === '~' || group.workspaceDir === '/'\n ? <div className=\"dsgc-err\">工作区指向整个主目录/根目录:角色的只读工具将可读取该范围下的所有文件,请谨慎</div>\n : null}\n </div>\n {fileBrowser && fileBrowser.open\n ? (\n <div className=\"dsgc-fb\">\n <div className=\"dsgc-fbhead\">\n <span className=\"dsgc-fbpath\" title={fileBrowser.list ? fileBrowser.list.path : ''}>\n {fileBrowser.loading ? '读取中…' : (fileBrowser.list ? fileBrowser.list.path : '')}\n </span>\n <span style={{ display: 'flex', gap: 4, alignItems: 'center' }}>\n <P.Button variant=\"primary\" size=\"sm\" disabled={!fileBrowser.list} onClick={selectCurrentDir}>选定此目录</P.Button>\n {fileBrowser.list\n ? <P.Button variant=\"outline\" size=\"sm\" title=\"上一级\" aria-label=\"上一级\" onClick={() => { void openBrowser(fileBrowser.list!.parent) }}>{Icon(P.IconChevronUpOutline14, 14)}</P.Button>\n : null}\n {fileBrowser.list\n ? <P.Button variant=\"outline\" size=\"sm\" title=\"主目录\" aria-label=\"主目录\" onClick={() => { void openBrowser(fileBrowser.list!.home) }}>{Icon(P.IconFolderClose16, 14)}</P.Button>\n : null}\n <P.Button variant=\"ghost\" size=\"sm\" onClick={() => { setFileBrowser(null) }} aria-label=\"关闭浏览器\">{Icon(P.IconCloseOutline16, 14)}</P.Button>\n </span>\n </div>\n {fileBrowser.error ? <div className=\"dsgc-err\">{fileBrowser.error}</div> : null}\n {fileBrowser.list\n ? (\n <div className=\"dsgc-fblist\">\n {(fileBrowser.list.entries || []).length\n ? (fileBrowser.list.entries || []).map((e) => e.type === 'directory'\n ? (\n <button\n key={e.path}\n type=\"button\"\n className={'dsgc-fbrow' + (e.hidden ? ' dim' : '') + ' dir'}\n onClick={() => { void openBrowser(e.path) }}\n >\n {Icon(e.hidden ? P.IconFolderClose16 : P.IconFolderOpenOutline16, 14)}\n <span className=\"dsgc-fbname\">{e.name}/</span>\n </button>\n )\n : (\n <div key={e.path} className=\"dsgc-fbrow dim file\">\n <span className=\"dsgc-fbname\">{e.name}</span>\n {e.size !== undefined ? <span className=\"dsgc-fbsize\">{(P as unknown as { fileSizeText: (n: number) => string }).fileSizeText(e.size)}</span> : null}\n </div>\n ))\n : <div className=\"dsgc-hint\">空目录</div>}\n </div>\n )\n : null}\n </div>\n )\n : null}\n </div>\n </div>\n )\n}\n","/**\n * 思考折叠行(对标宿主 ReasoningRow:折叠摘要 / 展开全文)。\n * @module dsh-group-chat/client/ThinkRow\n */\n\nimport { useState, type ReactNode } from 'react'\nimport { P } from '../lib/ui.ts'\nimport { firstLine, latestLine } from '../lib/model.ts'\n\nexport function ThinkRow(props: { text: string, running?: boolean }): ReactNode {\n const text = props.text || ''\n const running = !!props.running\n const [expanded, setExpanded] = useState(false)\n const plain = (line: string): string => line.replace(/^(\\s*#{1,6}\\s+|\\s*[-*+]\\s+|\\s*>\\s*)+/, '').replace(/[*`_~]/g, '').replace(/\\s+/g, ' ').trim()\n const summary = plain(running ? latestLine(text) : firstLine(text))\n return (\n <div className=\"dsgc-think\">\n <P.DisclosureRow\n rowClassName=\"dsgc-thinkrow\"\n icon={<P.IconThinkOutline14 size={14} />}\n title=\"思考\"\n open={expanded}\n expandable\n expandOnRowClick\n onToggle={() => { setExpanded((v) => !v) }}\n collapsedContent={text ? <span className=\"dsgc-thinksummary\">{summary}</span> : null}\n >\n <div className=\"dsgc-thinkbody\">{text}</div>\n </P.DisclosureRow>\n </div>\n )\n}\n","/**\n * 工具调用折叠行(对标思考折叠:摘要行 / 展开输出)。\n * @module dsh-group-chat/client/ToolRow\n */\n\nimport { useState, type ReactNode } from 'react'\nimport { Icon, P, pickPrimitive } from '../lib/ui.ts'\nimport type { ToolCallView } from '../lib/model.ts'\n\nconst TOOL_ICONS: Record<string, string> = { read_file: 'IconBrowseOutline16', list_dir: 'IconFolderOpenOutline16', run_command: 'IconCodeOutline16' }\n\nexport function ToolRow(props: { c: ToolCallView }): ReactNode {\n const c = props.c\n const [expanded, setExpanded] = useState(false)\n let brief = ''\n try {\n brief = JSON.stringify(c.args) || ''\n } catch {\n brief = ''\n }\n if (brief.length > 40) brief = brief.slice(0, 40) + '…'\n const IconOf = pickPrimitive(TOOL_ICONS[c.tool] || 'IconCodeOutline16')\n const statusText = c.status === 'ok' ? '成功' : c.status === 'denied' ? '用户拒绝' : '失败'\n const StatusIcon = c.status === 'ok' ? P.IconCheckOutline14 : c.status === 'denied' ? P.IconCloseOutline16 : P.IconWarningOutline16\n const dur = c.durationMs ? (c.durationMs >= 1000 ? (c.durationMs / 1000).toFixed(1) + 's' : c.durationMs + 'ms') : ''\n return (\n <div className=\"dsgc-tool\">\n <P.DisclosureRow\n rowClassName=\"dsgc-toolrow\"\n icon={<IconOf size={14} />}\n title={c.tool + (brief ? ' ' + brief : '')}\n open={expanded}\n expandable\n expandOnRowClick\n onToggle={() => { setExpanded((v) => !v) }}\n collapsedContent={\n <span className=\"dsgc-toolsummary\">\n {Icon(StatusIcon, 12, {\n verticalAlign: '-2px',\n marginRight: 4,\n color: c.status === 'ok' ? 'var(--dsw-alias-label-tertiary,inherit)' : 'var(--dsw-alias-state-error-primary,#e5484d)',\n })}\n {statusText + (dur ? ' · ' + dur : '')}\n </span>\n }\n >\n <div className=\"dsgc-toolbody\">{c.output || '(无输出)'}</div>\n </P.DisclosureRow>\n </div>\n )\n}\n","/**\n * 聊天消息气泡(user / system / 角色发言)。\n *\n * 帧稳定 memo:SSE 全量快照(~65KB × 7fps)每帧重建全部消息对象 identity,\n * 但已完成消息在 host 侧 append 后不可变——按渲染相关字段做值比较,流式\n * 期间跳过已完成消息的重渲(每帧仅 live 行与派生列表变化),避免全量\n * MarkdownText 重新解析打满主线程导致「卡死后一次性蹦出」。\n * @module dsh-group-chat/client/Bubble\n */\n\nimport { memo, type ReactNode } from 'react'\nimport { P } from '../lib/ui.ts'\nimport { fmtTime, MD_LABELS, type ClientSnapshot, type SnapshotRole } from '../lib/model.ts'\nimport { ThinkRow } from './ThinkRow.tsx'\nimport { ToolRow } from './ToolRow.tsx'\n\nexport interface BubbleProps {\n m: ClientSnapshot['messages'][number]\n /** 父级解析好的发言角色(user/system 消息为 null)——避免 Bubble 依赖 snap identity。 */\n role: SnapshotRole | null\n}\n\nfunction BubbleInner({ m, role }: BubbleProps): ReactNode {\n const isUser = m.speaker === 'user'\n const isSys = m.speaker === 'system'\n const name = isUser ? '我' : isSys ? '系统' : role ? role.name : '成员'\n if (isSys) return <div className={'dsgc-sysmsg' + (m.error ? ' err' : '')}>{m.text}</div>\n return (\n <div className={'dsgc-msg' + (isUser ? ' mine' : '')}>\n <div\n className={'dsgc-avatar' + (isUser ? ' mine' : '')}\n style={isUser || !role ? undefined : { border: '2px solid ' + (role.color || '#888') }}\n >\n {name.slice(0, 1)}\n </div>\n <div className=\"dsgc-msgbody\">\n <div className=\"dsgc-msghead\">\n <span className=\"dsgc-msgname\">{name}</span>\n {m.model ? <span className=\"dsgc-msgmodel\" title={m.model}>{m.model}</span> : null}\n {m.ts ? <span className=\"dsgc-msgtime\">{fmtTime(m.ts)}</span> : null}\n </div>\n {isUser\n ? <div className=\"dsgc-msgtext\">{m.text}</div>\n : (\n <div className=\"dsgc-msgtext\">\n {m.reasoning ? <ThinkRow text={m.reasoning} /> : null}\n {(Array.isArray(m.toolCalls) ? m.toolCalls : []).map((c, i) => <ToolRow key={'tc' + i} c={c} />)}\n <P.MarkdownText text={m.text || '(无内容)'} labels={MD_LABELS} />\n </div>\n )}\n </div>\n </div>\n )\n}\n\n/** 渲染相关字段的值比较(消息不可变;角色仅名/色参与渲染)。 */\nfunction bubblePropsEqual(a: BubbleProps, b: BubbleProps): boolean {\n const x = a.m\n const y = b.m\n if (x !== y) {\n if (x.id !== y.id || x.speaker !== y.speaker || x.text !== y.text || x.reasoning !== y.reasoning || x.model !== y.model || x.error !== y.error || x.ts !== y.ts) return false\n const ta = Array.isArray(x.toolCalls) ? x.toolCalls : []\n const tb = Array.isArray(y.toolCalls) ? y.toolCalls : []\n if (ta.length !== tb.length) return false\n for (let i = 0; i < ta.length; i++) {\n const ca = ta[i]\n const cb = tb[i]\n if (ca !== cb && (ca.tool !== cb.tool || ca.status !== cb.status || ca.output !== cb.output || ca.durationMs !== cb.durationMs || JSON.stringify(ca.args) !== JSON.stringify(cb.args))) return false\n }\n }\n const ra = a.role\n const rb = b.role\n return (ra ? ra.name + '\\u0000' + (ra.color || '') : '') === (rb ? rb.name + '\\u0000' + (rb.color || '') : '')\n}\n\nexport const Bubble = memo(BubbleInner, bubblePropsEqual)\n","/**\n * 消息流显示组件\n * @module dsh-group-chat/client/components\n */\n\nimport type { ReactNode, CSSProperties } from 'react'\nimport { Icon, P } from '../lib/ui.ts'\nimport { Bubble } from './Bubble.tsx'\nimport { ThinkRow } from './ThinkRow.tsx'\nimport { roleById, type ClientSnapshot } from '../lib/model.ts'\nimport { MD_LABELS } from '../lib/model.ts'\n\ninterface MessageFlowProps {\n snap: ClientSnapshot\n sess: ClientSnapshot['sessions'][number] | null\n busyNow: boolean\n msgById: Record<string, ClientSnapshot['messages'][number]>\n action: (payload: Record<string, unknown>) => Promise<unknown>\n}\n\nexport function MessageFlow(props: MessageFlowProps): ReactNode {\n const { snap, sess, busyNow, msgById, action } = props\n\n const bubbles: ReactNode[] = []\n \n if (sess) {\n for (const mid of sess.messageIds) {\n const m = msgById[mid]\n if (!m) continue\n // 角色在父级解析:Bubble 按值 memo(不依赖 snap identity),流式帧\n // 不再触发已完成消息的全量重渲(每帧仅 live 行与派生列表变化)\n const role = m.speaker !== 'user' && m.speaker !== 'system' ? roleById(snap, m.speaker) : null\n bubbles.push(<Bubble key={m.id} m={m} role={role} />)\n }\n }\n \n // 流式尾巴\n if (busyNow && snap.run.currentRoleId) {\n const lr = roleById(snap, snap.run.currentRoleId)\n if (lr) {\n bubbles.push(\n <div key=\"__live\" className=\"dsgc-msg live\">\n <div\n className=\"dsgc-avatar\"\n style={{ border: '2px solid ' + (lr.color || '#888'), '--role-color': lr.color || '#888' } as CSSProperties}\n >\n {lr.name.slice(0, 1)}\n </div>\n <div className=\"dsgc-msgbody\">\n <div className=\"dsgc-msghead\">\n <span className=\"dsgc-msgname\">{lr.name}</span>\n <span className=\"dsgc-msgmodel\">{lr.provider} / {lr.model}</span>\n <span className=\"dsgc-msgtime dsgc-typing\">深度求索...</span>\n </div>\n <div className=\"dsgc-msgtext live\">\n {snap.run.partialReasoning ? <ThinkRow text={snap.run.partialReasoning} running /> : null}\n {snap.run.partial ? <P.MarkdownText text={snap.run.partial} streaming labels={MD_LABELS} /> : null}\n {/* 首 delta 前的「思考中」占位(深度思考模型首字节可能等数秒到数十秒,\n 空白气泡会被感知为卡死);delta 到达后被真实思考行/正文自然替换 */}\n {!snap.run.partial && !snap.run.partialReasoning\n ? (\n <div className=\"dsgc-pending\">\n {Icon(P.IconThinkOutline14, 14)}\n <span>思考中</span>\n <span className=\"dsgc-pendingdots\" aria-hidden=\"true\"><i /><i /><i /></span>\n </div>\n )\n : null}\n </div>\n </div>\n </div>,\n )\n }\n }\n \n // 命令确认卡片\n const pc = busyNow && snap.run.pendingConfirm && sess && snap.run.sessionId === sess.id ? snap.run.pendingConfirm : null\n if (pc) {\n const lr = roleById(snap, snap.run.currentRoleId)\n bubbles.push(\n <div key=\"__confirm\" className=\"dsgc-confirm\">\n <div className=\"dsgc-confirmtitle\">\n {Icon(P.IconWarningOutline16, 14)}\n {(lr ? lr.name : '角色') + ' 请求执行命令(工作区内)'}\n </div>\n <div className=\"dsgc-confirmcmd\">{String((pc.args && pc.args.command) || '')}</div>\n <div className=\"dsgc-hint\">允许后将在工作区目录执行;拒绝后角色将继续纯文本讨论</div>\n <div className=\"dsgc-confirmops\">\n <P.Button variant=\"primary\" size=\"sm\" onClick={() => { void action({ kind: 'confirmCommand', toolCallId: pc.toolCallId, allow: true }) }}>允许</P.Button>\n <P.Button variant=\"outline\" size=\"sm\" onClick={() => { void action({ kind: 'confirmCommand', toolCallId: pc.toolCallId, allow: false }) }}>拒绝</P.Button>\n </div>\n </div>,\n )\n }\n\n return <>{bubbles}</>\n}\n","/**\n * 群聊数据模型(core 层,无 cordis 依赖)。\n * 数据模型:Group 1..N Session,消息挂在会话上;角色与工作区目录挂在群组上。\n * @module dsh-group-chat/core/types\n */\n\n/**\n * 群组权限档位(对齐主会话 /permission 三档):\n * - view_only 仅可查看:只保留 read_file/list_dir,run_command 从 schema 剔除\n * - workspace_write 工作区内修改:run_command 可用,每条命令逐条确认\n * - full_access 完全权限:run_command 免确认直接执行\n */\nexport type PermissionTier = 'view_only' | 'workspace_write' | 'full_access'\n\n/** 全部合法档位(展示顺序)。 */\nexport const PERMISSION_TIERS: readonly PermissionTier[] = ['view_only', 'workspace_write', 'full_access']\n\n/** 档位安全化:合法字符串原样,其余 undefined。 */\nexport function asPermissionTier(value: unknown): PermissionTier | undefined {\n return typeof value === 'string' && (PERMISSION_TIERS as readonly string[]).includes(value) ? value as PermissionTier : undefined\n}\n\n/**\n * ledger 行档位归一(v2→v3 兼容):显式 permissionTier 优先;\n * 缺失时按旧布尔迁移——allowCommands=true → workspace_write(今日语义即\n * 「可执行命令但逐条确认」),false/无字段 → view_only。\n */\nexport function migrateTier(permissionTier: unknown, allowCommands: unknown): PermissionTier {\n const tier = asPermissionTier(permissionTier)\n if (tier !== undefined) return tier\n return allowCommands === true ? 'workspace_write' : 'view_only'\n}\n\n/** 群组:角色与工作区目录的宿主。 */\nexport interface GroupRecord {\n id: string\n name: string\n workspaceDir: string\n permissionTier: PermissionTier\n roleIds: string[]\n sessionIds: string[]\n}\n\n/** 会话:消息挂在会话上。 */\nexport interface SessionRecord {\n id: string\n groupId: string\n name: string\n topic: string\n /** 名称已被手动编辑:自动命名永久跳过(隐式固定)。 */\n namePinned?: boolean\n /** 主题已被手动编辑:自动整理永久跳过(隐式固定)。 */\n topicPinned?: boolean\n messageIds: string[]\n createdAt: number\n}\n\n/** 角色:绑定 provider/model 的群成员身份。 */\nexport interface RoleRecord {\n id: string\n groupId: string\n name: string\n color?: string\n persona: string\n provider: string\n model: string\n temperature?: number\n reasoningEffort?: string\n enabled: boolean\n thinking: boolean\n}\n\n/** 一次工具调用的落盘/快照形态(TOOLS.md §3.3 回注契约的展示面)。 */\nexport interface ToolCallRecord {\n tool: string\n args: unknown\n status: string\n output: string\n durationMs?: number\n}\n\n/** 消息(user / system / 角色发言共用一条记录)。 */\nexport interface MessageRecord {\n id: string\n sessionId: string\n seq: number\n speaker: string\n text: string\n reasoning?: string\n reasoningFull?: string\n thinkingSummary?: string\n model?: string\n error?: boolean\n toolCalls?: ToolCallRecord[]\n ts: number\n}\n\n/** run_command 确认闸门的待确认载荷。 */\nexport interface PendingConfirm {\n toolCallId: string\n tool: string\n args: { command?: string } & Record<string, unknown>\n}\n\n/** 最近一次创建的群组/会话,供客户端定位选中项。 */\nexport interface LastCreated {\n kind: 'group' | 'session'\n groupId: string\n sessionId: string\n}\n\n/** run 结束后的「输出完毕」标记(内存态不持久化,重启即清;reason 取 ok/error)。 */\nexport interface RunFinished {\n sessionId: string\n reason: 'ok' | 'error'\n}\n\n/** 对话进行时状态(run)。 */\nexport interface RunState {\n running: boolean\n sessionId: string | null\n currentRoleId: string | null\n partial: string\n partialReasoning: string\n stopping: boolean\n queue: string[]\n pendingConfirm: PendingConfirm | null\n confirmSignal: { resolve: (allowed: boolean) => void } | null\n childProc: import('node:child_process').ChildProcess | null\n /** 最近一次 run 的结束标记:会话列表「已完成/已出错」状态的数据源。 */\n finished: RunFinished | null\n}\n\n/** 角色发言的引擎产物。 */\nexport interface SpeakResult {\n text: string\n reasoning: string | undefined\n toolCalls: ToolCallRecord[]\n}\n\n/** 工具执行结果(host 内部约定)。 */\nexport interface ToolExecution {\n status: 'ok' | 'error' | 'denied'\n output: string\n args: Record<string, unknown>\n durationMs: number\n}\n\n/** 模型目录(models action 的缓存载荷)。 */\nexport interface ModelCatalog {\n at: number\n providers: { id: string, name: string }[]\n modelsByProvider: Record<string, { id: string, name?: string }[]>\n}\n\n/** 推理级别选项(efforts action 的载荷)。 */\nexport interface EffortOptions {\n efforts: { id: string, name: string, description?: string }[]\n defaultEffort: string | undefined\n error?: string\n}\n\n/** 目录浏览结果(browse action 的载荷)。 */\nexport interface BrowseResult {\n ok: boolean\n path?: string\n home?: string\n parent?: string\n entries?: { name: string, type: string, path: string, size?: number, hidden: boolean }[]\n error?: string\n}\n\n/** 群工作区 @ 文件检索结果(fileSearch action 的载荷)。 */\nexport interface FileSearchResult {\n ok: boolean\n candidates?: { path: string, isDir: boolean }[]\n error?: string\n}\n\n/** 发到客户端的全量快照(wire 形态)。 */\nexport interface Snapshot {\n revision: number\n run: { running: boolean, sessionId: string | null, currentRoleId: string | null, partial: string, partialReasoning: string, pendingConfirm: PendingConfirm | null, finished: RunFinished | null }\n lastCreated: LastCreated | null\n groups: { id: string, name: string, workspaceDir: string, permissionTier: PermissionTier, roleIds: string[], sessionIds: string[] }[]\n sessions: { id: string, groupId: string, name: string, topic: string, messageIds: string[], createdAt: number }[]\n roles: { id: string, groupId: string, name: string, color?: string, persona: string, provider: string, model: string, temperature?: number, reasoningEffort?: string, enabled: boolean, thinking: boolean }[]\n messages: { id: string, sessionId: string, seq: number, speaker: string, text: string, reasoning?: string, model?: string, error?: boolean, toolCalls?: ToolCallRecord[], ts: number }[]\n error?: string\n}\n\n/** mutate 动作的参数形态(op 分发见 host/service)。 */\nexport interface MutateArgs {\n op: string\n groupId?: string\n sessionId?: string\n roleId?: string\n role?: Partial<RoleRecord>\n name?: string\n topic?: string\n path?: string\n tier?: string\n enabled?: boolean\n}\n\n/** send 动作的参数形态。 */\nexport interface SendArgs {\n sessionId: string\n text?: string\n participantRoleIds?: string[]\n rounds?: number\n}\n\n/** 可选数值参数安全化:数字则原样,否则 undefined。 */\nexport function asNumber(value: unknown): number | undefined {\n return typeof value === 'number' && !Number.isNaN(value) ? value : undefined\n}\n\n/** 可选字符串参数安全化:非 default 的非空字符串则原样,否则 undefined。 */\nexport function asEffort(value: unknown): string | undefined {\n return typeof value === 'string' && value && value !== 'default' ? value : undefined\n}\n","/**\n * 群组权限档位选择器(对齐主会话 composer 左下角的 /permission 选择器):\n * 触发芯片(盾形图标 + 档位名 + chevron)+ Menu 上弹三档 + 完全权限风险\n * 确认弹窗(与主会话同款 RiskConfirmation 原语与文案)。\n * @module dsh-group-chat/client/permission-select\n */\n\nimport { useEffect, useState, type ReactNode } from 'react'\nimport { Icon, P } from '../lib/ui.ts'\nimport type { PermissionTier } from '../../core/types.ts'\nimport { asPermissionTier, PERMISSION_TIERS } from '../../core/types.ts'\n\nexport interface PermissionSelectProps {\n tier: PermissionTier\n onSelect: (tier: PermissionTier) => void\n}\n\n/** 档位展示名(与主会话中文标签一致)。 */\nconst TIER_LABELS: Record<PermissionTier, string> = {\n view_only: '仅可查看',\n workspace_write: '工作区内修改',\n full_access: '完全权限',\n}\n\n/** 档位悬停说明(群聊语境下的真实约束)。 */\nconst TIER_DESCRIPTIONS: Record<PermissionTier, string> = {\n view_only: '角色只能读取工作区文件,不能执行命令',\n workspace_write: '角色可执行命令(cwd 固定在工作区),每条命令需你在会话中确认',\n full_access: '角色可免确认直接执行命令,存在风险',\n}\n\n/** 完全权限风险确认文案(与主会话逐字一致)。 */\nconst CONFIRM_TEXT = {\n title: '确认启用完全权限?',\n description: '启用完全权限后,智能体将减少确认步骤,并且可以直接执行更多操作,包括敏感操作、文件修改或外部命令。仅建议在你信任当前任务时使用。',\n acknowledge: '我已了解风险,并愿意继续',\n cancel: '取消',\n enable: '启用完全权限',\n} as const\n\n// ---- 盾形图标(路径取自主会话 PermissionSelect 的设计稿字形) ----\n\nconst SHIELD_OUTLINE = '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'\n\nfunction GlyphViewOnly(): ReactNode {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden>\n <path d={SHIELD_OUTLINE} stroke=\"currentColor\" strokeWidth=\"1.31831\" strokeLinejoin=\"round\" />\n <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\" />\n </svg>\n )\n}\n\nfunction GlyphWorkspaceWrite(): ReactNode {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden>\n <path d=\"M8.08887 0.251709C8.20479 0.23085 8.32486 0.241168 8.43652 0.282959L15.0215 2.75171C15.2787 2.84819 15.4492 3.09414 15.4492 3.3689V7.0105C15.4492 7.10986 15.4441 7.2081 15.4414 7.30542C15.0285 7.07175 14.5905 6.87695 14.1309 6.73022V3.82495L8.20508 1.60327L2.2793 3.82495V7.0105C2.27936 9.7171 3.4745 11.5379 5.02734 12.7947C5.01025 12.9942 5 13.1962 5 13.4001C5.00001 13.7617 5.02722 14.1169 5.08008 14.4636C2.91555 13.0393 0.961014 10.752 0.960938 7.0105V3.3689C0.960938 3.09417 1.13146 2.84821 1.38867 2.75171L7.97461 0.282959L8.08887 0.251709Z\" fill=\"currentColor\" />\n <path d=\"M11.3525 5.64688V6.85688H5V5.64688H11.3525Z\" fill=\"currentColor\" />\n <path d=\"M9.5824 8.29376V9.50376H5V8.29376H9.5824Z\" fill=\"currentColor\" />\n <path d=\"M14.6647 15.6852H10.0338C10.3878 15.3751 10.7567 15.0517 11.0772 14.7706C11.2531 14.6164 11.4144 14.4746 11.5511 14.3547H14.6647V15.6852Z\" fill=\"currentColor\" />\n <path d=\"M8.14852 14.1308L7.33925 15.4976C7.22458 15.6912 7.42245 15.9194 7.63037 15.8333L9.09785 15.2254L15.0399 10.0719L14.0905 8.97733L8.14852 14.1308Z\" fill=\"currentColor\" />\n </svg>\n )\n}\n\nfunction GlyphFullAccess(): ReactNode {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden>\n <path d={SHIELD_OUTLINE} stroke=\"currentColor\" strokeWidth=\"1.31831\" strokeLinejoin=\"round\" />\n <path d=\"M9.10094 4.5V8.75939H7.59888V4.5H9.10094Z\" fill=\"currentColor\" />\n <path d=\"M9.10094 9.8114V11.5H7.59888V9.8114Z\" fill=\"currentColor\" />\n </svg>\n )\n}\n\nconst TIER_GLYPHS: Record<PermissionTier, () => ReactNode> = {\n view_only: GlyphViewOnly,\n workspace_write: GlyphWorkspaceWrite,\n full_access: GlyphFullAccess,\n}\n\nexport function PermissionSelect(props: PermissionSelectProps): ReactNode {\n const [open, setOpen] = useState(false)\n const [confirming, setConfirming] = useState(false)\n const [acknowledged, setAcknowledged] = useState(false)\n // 版本错位兜底:旧 host 快照无 permissionTier(或值非法)时按最安全的仅可查看呈现,\n // 不让面板整体崩溃\n const tier = asPermissionTier(props.tier) ?? 'view_only'\n\n // 档位被外部改回(如迁移/其他端变更)时收起弹层与确认态\n useEffect(() => {\n setOpen(false)\n setAcknowledged(false)\n setConfirming(false)\n }, [tier])\n\n const choose = (id: string): void => {\n setOpen(false)\n if (id === tier) return\n if (id === 'full_access') {\n setAcknowledged(false)\n setConfirming(true)\n return\n }\n props.onSelect(id as PermissionTier)\n }\n const closeConfirm = (): void => {\n setAcknowledged(false)\n setConfirming(false)\n }\n const confirmFullAccess = (): void => {\n if (!acknowledged) return\n closeConfirm()\n props.onSelect('full_access')\n }\n\n const items = PERMISSION_TIERS.map((t) => ({ id: t, label: TIER_LABELS[t], icon: TIER_GLYPHS[t]() }))\n const Glyph = TIER_GLYPHS[tier] ?? GlyphViewOnly\n\n return (\n <>\n <P.Menu\n open={open}\n items={items}\n selectedId={tier}\n onSelect={choose}\n onClose={() => { setOpen(false) }}\n side=\"top\"\n anchor={(\n <button\n type=\"button\"\n className=\"dsgc-permtrigger\"\n aria-label={'权限模式:' + TIER_LABELS[tier]}\n title={TIER_DESCRIPTIONS[tier]}\n disabled={confirming}\n onClick={() => { setOpen(!open) }}\n >\n <span className=\"dsgc-permicon\" aria-hidden>{Glyph()}</span>\n <span className=\"dsgc-permlabel\">{TIER_LABELS[tier]}</span>\n <span className={'dsgc-permchevron' + (open ? ' open' : '')} aria-hidden>{Icon(P.IconChevronDownOutline14, 14)}</span>\n </button>\n )}\n />\n <P.RiskConfirmation\n open={confirming}\n title={CONFIRM_TEXT.title}\n description={CONFIRM_TEXT.description}\n acknowledgeLabel={CONFIRM_TEXT.acknowledge}\n cancelLabel={CONFIRM_TEXT.cancel}\n closeLabel=\"关闭\"\n confirmLabel={CONFIRM_TEXT.enable}\n acknowledged={acknowledged}\n onAcknowledgedChange={setAcknowledged}\n onCancel={closeConfirm}\n onConfirm={confirmFullAccess}\n />\n </>\n )\n}\n","/**\n * 消息输入编辑器组件\n * @module dsh-group-chat/client/components\n */\n\nimport type { ReactNode, KeyboardEvent as ReactKeyboardEvent, ClipboardEvent as ReactClipboardEvent, DragEvent as ReactDragEvent } from 'react'\nimport { Icon, P } from '../lib/ui.ts'\nimport { PermissionSelect } from './PermissionSelect.tsx'\nimport { escapeRegExp, type ClientSnapshot, type SnapshotRole } from '../lib/model.ts'\nimport type { AtToken } from '../../shared/file-mention-grammar.ts'\n\ninterface ComposerProps {\n snap: ClientSnapshot\n sess: ClientSnapshot['sessions'][number] | null\n group: ClientSnapshot['groups'][number]\n enabledRoles: SnapshotRole[]\n participants: string[]\n mentionedRoles: SnapshotRole[]\n busyNow: boolean\n input: string\n mention: AtToken | null\n mentionCandidates: SnapshotRole[]\n mentionIdxC: number\n fileCandidates: Array<{ path: string, isDir: boolean }>\n fileSearchError: string | null\n fileSearchLoading: boolean\n rounds: number\n err: string\n atBottom: boolean\n bubblesLength: number\n inputRef: React.RefObject<HTMLDivElement>\n scrollRef: React.RefObject<HTMLDivElement>\n setMentionIdx: (val: number) => void\n setRounds: (val: number) => void\n togglePart: (rid: string) => void\n onInputCE: () => void\n onInputKeyDown: (e: ReactKeyboardEvent<HTMLDivElement>) => void\n onPasteCE: (e: ReactClipboardEvent<HTMLDivElement>) => void\n onDropCE: (e: ReactDragEvent<HTMLDivElement>) => void\n onDragOverCE: (e: ReactDragEvent<HTMLDivElement>) => void\n insertChip: (role: SnapshotRole) => void\n insertFileChip: (path: string, kind: 'file' | 'directory') => void\n sendMsg: () => Promise<void>\n stopRun: () => Promise<void>\n mutate: (args: Record<string, unknown>) => Promise<unknown>\n setMention: (val: AtToken | null) => void\n}\n\nexport function Composer(props: ComposerProps): ReactNode {\n const {\n snap,\n sess,\n group,\n enabledRoles,\n participants,\n mentionedRoles,\n busyNow,\n input,\n mention,\n mentionCandidates,\n mentionIdxC,\n fileCandidates,\n fileSearchError,\n fileSearchLoading,\n rounds,\n err,\n atBottom,\n bubblesLength,\n inputRef,\n scrollRef,\n setMentionIdx,\n setRounds,\n togglePart,\n onInputCE,\n onInputKeyDown,\n onPasteCE,\n onDropCE,\n onDragOverCE,\n insertChip,\n insertFileChip,\n sendMsg,\n stopRun,\n mutate,\n setMention,\n } = props\n\n return (\n <div className=\"dsgc-composer\">\n {!atBottom && bubblesLength\n ? (\n <div className=\"dsgc-tobottom\">\n <button\n type=\"button\"\n className=\"dsgc-tobtn\"\n onClick={() => { const el = scrollRef.current; if (el) el.scrollTo({ top: el.scrollHeight, behavior: 'smooth' }) }}\n >\n {Icon(P.IconChevronDownOutline14, 14)}回到底部\n </button>\n </div>\n )\n : null}\n {err ? <div className=\"dsgc-err\">{err}</div> : null}\n <div className=\"dsgc-parts\">\n <span className=\"dsgc-partslabel\">参与角色</span>\n {mentionedRoles.length\n ? <span className=\"dsgc-partslabel\">已 @ {mentionedRoles.map((r) => r.name).join('、')}(本轮仅被点名成员发言)</span>\n : enabledRoles.length\n ? enabledRoles.map((r) => (\n <button\n key={r.id}\n type=\"button\"\n className={'dsgc-partchip' + (participants.includes(r.id) ? ' on' : '')}\n onClick={() => togglePart(r.id)}\n disabled={busyNow}\n title={busyNow ? '对话进行中,暂停调整' : '点击切换本轮是否参与'}\n >\n <span className=\"dsgc-chipdot\" style={{ background: r.color || '#888' }} />\n {r.name}\n </button>\n ))\n : <span className=\"dsgc-hint\">还没有启用的角色,请在右侧添加</span>}\n </div>\n <div className=\"dsgc-card\">\n <div className=\"dsgc-mentionwrap\">\n {mention !== null && mention.query === '' && mentionCandidates.length > 0\n ? (\n <div className=\"dsgc-mention\" role=\"listbox\">\n {mentionCandidates.map((r, i) => (\n <button\n key={r.id}\n type=\"button\"\n className={'dsgc-mentionitem' + (i === mentionIdxC ? ' on' : '')}\n role=\"option\"\n aria-selected={i === mentionIdxC ? 'true' : 'false'}\n onMouseDown={(e) => { e.preventDefault() }}\n onClick={() => { insertChip(r) }}\n onMouseEnter={() => setMentionIdx(i)}\n >\n <span className=\"dsgc-chipdot\" style={{ background: r.color || '#888' }} />\n <span className=\"dsgc-mentionname\">{r.name}</span>\n <span className=\"dsgc-mentionmodel\">{r.provider} / {r.model}</span>\n </button>\n ))}\n <span className=\"dsgc-mentionhint\">↑↓ 选择 · Enter/Tab 插入</span>\n </div>\n )\n : mention !== null && mention.query !== ''\n ? (\n <div className=\"dsgc-mention dsgc-mention-file\" role=\"listbox\">\n {fileCandidates.length\n ? fileCandidates.map((item, i) => (\n <button\n key={item.path}\n type=\"button\"\n className={'dsgc-mentionitem' + (i === mentionIdxC ? ' on' : '')}\n role=\"option\"\n aria-selected={i === mentionIdxC ? 'true' : 'false'}\n onMouseDown={(e) => { e.preventDefault() }}\n onClick={() => {\n insertFileChip(item.path, item.isDir ? 'directory' : 'file')\n }}\n onMouseEnter={() => setMentionIdx(i)}\n >\n <span className={'dsgc-fileglyph' + (item.isDir ? ' dir' : ' file')} aria-hidden=\"true\">\n {item.isDir\n ? <P.FileTypeIcon kind=\"folder\" size={16} />\n : <P.FileTypeIcon path={item.path} size={16} />}\n </span>\n <span className=\"dsgc-mentionname\">{item.path}</span>\n {item.isDir ? <span className=\"dsgc-filedrill\">{Icon(P.IconChevronRightOutline14, 12)}</span> : null}\n </button>\n ))\n : fileSearchLoading\n ? <div className=\"dsgc-mentionitem dsgc-hint\">检索中…</div>\n : fileSearchError\n ? <div className=\"dsgc-mentionitem dsgc-hint\">{fileSearchError}</div>\n : <div className=\"dsgc-mentionitem dsgc-hint\">无匹配文件</div>}\n <span className=\"dsgc-mentionhint\">\n {fileSearchLoading && fileCandidates.length\n ? '检索中…'\n : fileCandidates.some((f) => f.isDir)\n ? '↑↓ 选择 · Enter 插入 · Tab 进入目录 · Esc 关闭'\n : '↑↓ 选择 · Enter 插入 · Esc 关闭'}\n </span>\n </div>\n )\n : null}\n {!input.trim()\n ? <div className=\"dsgc-ph\" aria-hidden=\"true\">发消息给全群,@成员 点名让其回应(留空则让角色自由讨论)…</div>\n : null}\n <div\n className=\"dsgc-edit\"\n ref={inputRef}\n contentEditable\n suppressContentEditableWarning\n role=\"textbox\"\n aria-multiline=\"true\"\n aria-label=\"群聊消息输入框\"\n onInput={onInputCE}\n onKeyDown={onInputKeyDown}\n onPaste={onPasteCE}\n onDrop={onDropCE}\n onDragOver={onDragOverCE}\n onBlur={() => { setMention(null) }}\n />\n </div>\n <div className=\"dsgc-sendrow\">\n <PermissionSelect\n tier={group.permissionTier}\n onSelect={(tier) => { void mutate({ op: 'setPermissionTier', groupId: group.id, tier }) }}\n />\n <span style={{ flex: 1 }} />\n <div className=\"dsgc-rounds\" title=\"自由讨论的轮数(1–10):一轮 = 全体参与角色按顺序各发言一次\">\n <button type=\"button\" className=\"dsgc-roundbtn\" aria-label=\"减少轮数\" disabled={rounds <= 1} onClick={() => { setRounds(Math.max(1, rounds - 1)) }}>\n {Icon(P.IconChevronLeftOutline14, 12)}\n </button>\n <span className=\"dsgc-roundnum\" title=\"轮数\">{rounds}</span>\n <button type=\"button\" className=\"dsgc-roundbtn\" aria-label=\"增加轮数\" disabled={rounds >= 10} onClick={() => { setRounds(Math.min(10, rounds + 1)) }}>\n {Icon(P.IconChevronRightOutline14, 12)}\n </button>\n <span style={{ padding: '0 6px 0 2px' }}>轮</span>\n </div>\n {busyNow\n ? (\n <P.Button variant=\"outline\" className=\"dsgc-stopbtn\" onClick={() => { void stopRun() }}>\n {Icon(P.IconStopFill16, 16)}停止\n </P.Button>\n )\n : (\n <P.Button variant=\"primary\" onClick={() => { void sendMsg() }} disabled={(!participants.length && !mentionedRoles.length) || !sess}>\n {Icon(P.IconSendOutline16, 16)}发送\n </P.Button>\n )}\n </div>\n </div>\n </div>\n )\n}\n","/**\n * 中央会话面板组件\n * @module dsh-group-chat/client/components\n */\n\nimport type { ReactNode } from 'react'\nimport { Icon, P } from '../lib/ui.ts'\nimport { MessageFlow } from './MessageFlow.tsx'\nimport { Composer } from './Composer.tsx'\nimport type { ClientSnapshot, SnapshotRole } from '../lib/model.ts'\nimport type { AtToken } from '../../shared/file-mention-grammar.ts'\n\ninterface ChatPanelProps {\n snap: ClientSnapshot\n sess: ClientSnapshot['sessions'][number] | null\n group: ClientSnapshot['groups'][number]\n enabledRoles: SnapshotRole[]\n participants: string[]\n mentionedRoles: SnapshotRole[]\n busyNow: boolean\n input: string\n mention: AtToken | null\n mentionCandidates: SnapshotRole[]\n mentionIdxC: number\n fileCandidates: Array<{ path: string, isDir: boolean }>\n fileSearchError: string | null\n fileSearchLoading: boolean\n rounds: number\n err: string\n atBottom: boolean\n topicDraft: string | null\n msgById: Record<string, ClientSnapshot['messages'][number]>\n navOpen: boolean\n asideOpen: boolean\n inputRef: React.RefObject<HTMLDivElement>\n scrollRef: React.RefObject<HTMLDivElement>\n setTopicDraft: (val: string | null) => void\n setConfirmClear: (val: boolean) => void\n setMentionIdx: (val: number) => void\n setRounds: (val: number) => void\n setNavOpen: (val: boolean) => void\n setAsideOpen: (val: boolean) => void\n togglePart: (rid: string) => void\n onMsgsScroll: () => void\n onInputCE: () => void\n onInputKeyDown: (e: React.KeyboardEvent<HTMLDivElement>) => void\n onPasteCE: (e: React.ClipboardEvent<HTMLDivElement>) => void\n onDropCE: (e: React.DragEvent<HTMLDivElement>) => void\n onDragOverCE: (e: React.DragEvent<HTMLDivElement>) => void\n insertChip: (role: SnapshotRole) => void\n insertFileChip: (path: string, kind: 'file' | 'directory') => void\n sendMsg: () => Promise<void>\n stopRun: () => Promise<void>\n action: (payload: Record<string, unknown>) => Promise<unknown>\n mutate: (args: Record<string, unknown>) => Promise<unknown>\n setMention: (val: AtToken | null) => void\n}\n\nexport function ChatPanel(props: ChatPanelProps): ReactNode {\n const {\n snap,\n sess,\n group,\n enabledRoles,\n participants,\n mentionedRoles,\n busyNow,\n input,\n mention,\n mentionCandidates,\n mentionIdxC,\n fileCandidates,\n fileSearchError,\n fileSearchLoading,\n rounds,\n err,\n atBottom,\n topicDraft,\n msgById,\n navOpen,\n asideOpen,\n inputRef,\n scrollRef,\n setTopicDraft,\n setConfirmClear,\n setMentionIdx,\n setRounds,\n setNavOpen,\n setAsideOpen,\n togglePart,\n onMsgsScroll,\n onInputCE,\n onInputKeyDown,\n onPasteCE,\n onDropCE,\n onDragOverCE,\n insertChip,\n insertFileChip,\n sendMsg,\n stopRun,\n action,\n mutate,\n setMention,\n } = props\n\n const commitTopic = (): void => {\n if (topicDraft !== null && sess && topicDraft !== sess.topic) void mutate({ op: 'setTopic', sessionId: sess.id, topic: topicDraft })\n setTopicDraft(null)\n }\n\n const bubbles = (\n <MessageFlow\n snap={snap}\n sess={sess}\n busyNow={busyNow}\n msgById={msgById}\n action={action}\n />\n )\n\n return (\n <section className=\"dsgc-chat\">\n {/* 接缝收合钮 */}\n <button\n type=\"button\"\n className={'dsgc-seambtn left' + (navOpen ? '' : ' closed')}\n aria-label={navOpen ? '收起群组导航栏' : '展开群组导航栏'}\n title={navOpen ? '收起群组导航栏' : '展开群组导航栏'}\n aria-expanded={navOpen}\n onClick={() => { setNavOpen(!navOpen) }}\n >\n {Icon(P.IconChevronLeftOutline14, 16)}\n </button>\n <button\n type=\"button\"\n className={'dsgc-seambtn right' + (asideOpen ? '' : ' closed')}\n aria-label={asideOpen ? '收起成员与工作区栏' : '展开成员与工作区栏'}\n title={asideOpen ? '收起成员与工作区栏' : '展开成员与工作区栏'}\n aria-expanded={asideOpen}\n onClick={() => { setAsideOpen(!asideOpen) }}\n >\n {Icon(P.IconChevronRightOutline14, 16)}\n </button>\n \n <div className=\"dsgc-chathead\">\n {sess ? <span className=\"dsgc-sess-title\" title={'当前会话:' + sess.name}>{sess.name}</span> : null}\n <input\n className=\"dsgc-topic\"\n value={topicDraft === null ? (sess ? sess.topic : '') : topicDraft}\n placeholder=\"设置本会话主题(可选)…\"\n onChange={(e) => { setTopicDraft(e.target.value) }}\n onBlur={commitTopic}\n onKeyDown={(e) => { if (e.key === 'Enter') (e.target as HTMLInputElement).blur() }}\n />\n <P.Button variant=\"ghost\" size=\"sm\" className=\"dsgc-clearbtn\" title=\"清空当前会话的消息记录\" onClick={() => { if (sess) setConfirmClear(true) }}>\n 清空\n </P.Button>\n </div>\n \n <div className=\"dsgc-msgs\" ref={scrollRef} onScroll={onMsgsScroll}>\n {sess && sess.messageIds.length > 0\n ? bubbles\n : (\n <div className=\"dsgc-empty\">\n {Icon(P.IconSparkle16, 20)}\n <div className=\"dsgc-emptytitle\">{sess && sess.topic ? '「' + sess.topic + '」' : '会话已就绪'}</div>\n <div className=\"dsgc-hint\">\n {enabledRoles.length\n ? '发送消息开始讨论;@成员 点名让其优先回应;留空直接发送可让角色自由讨论——每轮全体参与角色按顺序各发言一次,可用右下角轮数控制(1–10 轮)'\n : '先在右侧添加角色(每个角色可绑定不同模型),再回到这里发起讨论。'}\n </div>\n </div>\n )}\n </div>\n \n <Composer\n snap={snap}\n sess={sess}\n group={group}\n enabledRoles={enabledRoles}\n participants={participants}\n mentionedRoles={mentionedRoles}\n busyNow={busyNow}\n input={input}\n mention={mention}\n mentionCandidates={mentionCandidates}\n mentionIdxC={mentionIdxC}\n fileCandidates={fileCandidates}\n fileSearchError={fileSearchError}\n fileSearchLoading={fileSearchLoading}\n rounds={rounds}\n err={err}\n atBottom={atBottom}\n bubblesLength={sess?.messageIds.length || 0}\n inputRef={inputRef}\n scrollRef={scrollRef}\n setMentionIdx={setMentionIdx}\n setRounds={setRounds}\n togglePart={togglePart}\n onInputCE={onInputCE}\n onInputKeyDown={onInputKeyDown}\n onPasteCE={onPasteCE}\n onDropCE={onDropCE}\n onDragOverCE={onDragOverCE}\n insertChip={insertChip}\n insertFileChip={insertFileChip}\n sendMsg={sendMsg}\n stopRun={stopRun}\n mutate={mutate}\n setMention={setMention}\n />\n </section>\n )\n}\n","/**\n * 群聊面板核心状态管理 hook\n * @module dsh-group-chat/client/hooks\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { api } from '../lib/api.ts'\nimport type { ClientSnapshot, ModelsResponse, RoleDraft } from '../lib/model.ts'\nimport type { AtToken } from '../../shared/file-mention-grammar.ts'\n\nexport interface MutateResponse {\n ok: boolean\n snapshot?: ClientSnapshot\n lastCreated?: ClientSnapshot['lastCreated']\n error?: string\n}\n\nexport interface ActionOk {\n ok: boolean\n error?: string\n}\n\n/**\n * 面板切换缓存(模块级,跨挂载存活):main 为 keyed 槽,主会话⇄群聊切换会\n * 整体卸载重挂面板组件;缓存最近快照与选中项让重挂载瞬时恢复上次视图,\n * 挂载后的 state 拉取 / SSE 首帧再行校正(本机回路往返仅数毫秒)。\n */\nlet cachedSnap: ClientSnapshot | null = null\nlet cachedGid: string | null = null\nlet cachedSid: string | null = null\n\nexport function useGroupChatState() {\n // 核心数据快照(重挂载时从缓存瞬时恢复,消除切换闪现的加载态)\n const [snap, setSnap] = useState<ClientSnapshot | null>(() => cachedSnap)\n\n // 选中状态\n const [gid, setGid] = useState<string | null>(() => cachedGid)\n const [sid, setSid] = useState<string | null>(() => cachedSid)\n\n /** 已应用过的 lastCreated 会话标记:只在标记变化(真正的新建)时跟随选中,\n 而不是每帧都把视图拽回「最近创建的会话」(流式期间每 120ms 一帧)。 */\n const appliedCreatedRef = useRef<string | null>(cachedSnap?.lastCreated?.sessionId ?? null)\n\n /** 快照落地统一口:写状态 + 写切换缓存。 */\n const applySnap = useCallback((s: ClientSnapshot): void => {\n cachedSnap = s\n setSnap(s)\n }, [])\n\n /** 选中项统一口:写状态 + 写切换缓存(重挂载恢复到用户离开时的位置)。 */\n const selectGroup = useCallback((v: string): void => {\n cachedGid = v\n setGid(v)\n }, [])\n const selectSession = useCallback((v: string): void => {\n cachedSid = v\n setSid(v)\n }, [])\n \n // UI 状态\n const [search, setSearch] = useState('')\n const [collapsedGroups, setCollapsedGroups] = useState<Set<string>>(() => new Set())\n const [asideOpen, setAsideOpen] = useState(true)\n const [navOpen, setNavOpen] = useState(true)\n const [atBottom, setAtBottom] = useState(true)\n \n // 编辑态\n const [renameDraft, setRenameDraft] = useState<{ kind: 'group' | 'session', id: string, value: string } | null>(null)\n const [confirmDel, setConfirmDel] = useState<{ kind: 'group' | 'session', id: string } | null>(null)\n const [confirmClear, setConfirmClear] = useState(false)\n const [topicDraft, setTopicDraft] = useState<string | null>(null)\n const [wsDraft, setWsDraft] = useState<string | null>(null)\n \n // 角色编辑\n const [roleDraft, setRoleDraft] = useState<RoleDraft | null>(null)\n const [roleFormError, setRoleFormError] = useState('')\n const [models, setModels] = useState<ModelsResponse | null>(null)\n const [modelsError, setModelsError] = useState<string | null>(null)\n \n // 文件浏览器\n const [fileBrowser, setFileBrowser] = useState<{ open: boolean, loading: boolean, list: import('../../core/types.ts').BrowseResult | null, error: string } | null>(null)\n \n // 参与角色选择\n const [partsSel, setPartsSel] = useState<string[] | null>(null)\n const [rounds, setRounds] = useState(1)\n \n // 输入与 @提及\n const [input, setInput] = useState('')\n const [mention, setMention] = useState<AtToken | null>(null)\n const [mentionIdx, setMentionIdx] = useState(0)\n \n // 错误提示\n const [err, setErr] = useState('')\n \n // Refs\n const inputRef = useRef<HTMLDivElement | null>(null)\n const sendingRef = useRef(false)\n const scrollRef = useRef<HTMLDivElement | null>(null)\n\n // 初始加载 + SSE 订阅\n useEffect(() => {\n let live = true\n api.state().then((s) => {\n if (live && s && (s as ClientSnapshot).ok) applySnap(s as ClientSnapshot)\n }).catch(() => { /* SSE 会重试 */ })\n const events = new EventSource('/api/group-chat/events')\n events.onmessage = (message) => {\n try {\n const s = JSON.parse(message.data) as ClientSnapshot\n if (!live || !s || !s.ok) return\n // lastCreated 仅在变化时跟随选中(新建群组/会话的定位信号);\n // 帧里重复携带的旧标记不再反复重置视图\n if (s.lastCreated && s.lastCreated.sessionId && s.lastCreated.sessionId !== appliedCreatedRef.current) {\n appliedCreatedRef.current = s.lastCreated.sessionId\n selectGroup(s.lastCreated.groupId)\n selectSession(s.lastCreated.sessionId)\n setPartsSel(null)\n }\n applySnap(s)\n } catch { /* ignore malformed frame */ }\n }\n return () => {\n live = false\n events.close()\n }\n }, [applySnap, selectGroup, selectSession])\n\n // API 操作封装\n const action = useCallback(async (payload: Record<string, unknown>): Promise<unknown> => {\n try {\n return await api.action(payload)\n } catch (e) {\n setErr(String((e && (e as Error).message) || e))\n return null\n }\n }, [])\n\n const mutate = async (args: Record<string, unknown>): Promise<MutateResponse | null> => {\n setErr('')\n const res = await action(Object.assign({ kind: 'mutate' }, args)) as MutateResponse | null\n if (res && res.ok && res.snapshot) {\n // 响应里的 lastCreated 是服务端当前值(未必由本次调用产生)——同样只在\n // 变化时跟随选中,避免改名/改配置等普通 mutate 把视图拽走\n if (res.lastCreated && res.lastCreated.sessionId && res.lastCreated.sessionId !== appliedCreatedRef.current) {\n appliedCreatedRef.current = res.lastCreated.sessionId\n selectGroup(res.lastCreated.groupId)\n selectSession(res.lastCreated.sessionId)\n setPartsSel(null)\n }\n applySnap(res.snapshot)\n if (res.snapshot.error) setErr(res.snapshot.error)\n }\n return res\n }\n\n return {\n // 状态\n snap,\n setSnap: applySnap,\n gid,\n setGid: selectGroup,\n sid,\n setSid: selectSession,\n search,\n setSearch,\n collapsedGroups,\n setCollapsedGroups,\n renameDraft,\n setRenameDraft,\n confirmDel,\n setConfirmDel,\n confirmClear,\n setConfirmClear,\n roleDraft,\n setRoleDraft,\n roleFormError,\n setRoleFormError,\n models,\n setModels,\n modelsError,\n setModelsError,\n fileBrowser,\n setFileBrowser,\n wsDraft,\n setWsDraft,\n partsSel,\n setPartsSel,\n rounds,\n setRounds,\n input,\n setInput,\n err,\n setErr,\n topicDraft,\n setTopicDraft,\n mention,\n setMention,\n mentionIdx,\n setMentionIdx,\n asideOpen,\n setAsideOpen,\n navOpen,\n setNavOpen,\n atBottom,\n setAtBottom,\n // Refs\n inputRef,\n sendingRef,\n scrollRef,\n // 方法\n action,\n mutate,\n }\n}\n","/**\n * Vendored @file token grammar from dsh-file-reference (browser-safe, zero Node API).\n * \n * Sourced from @deepseek-ai/dsh-file-reference/lib/types/grammar.js\n * Cannot import directly due to client bundle purity gate (dsh-client-bundle-purity).\n * \n * @module dsh-group-chat/shared\n */\n\nexport interface AtToken {\n /** Full matched prefix including @ and optional quotes */\n prefix: string\n /** Query fragment after @ (unquoted content) */\n query: string\n /** Whether the token uses quoted form @\"...\" */\n quoted: boolean\n}\n\nexport interface FileCandidate {\n kind: 'file' | 'directory'\n path: string\n}\n\n/**\n * Extract active @token at cursor position.\n * Matches @ at word boundary (line start or after whitespace).\n * \n * @param line - Current line text\n * @param cursor - Cursor offset in line\n * @returns Token or undefined if no active @token at cursor\n */\nexport function activeAtToken(line: string, cursor: number): AtToken | undefined {\n const before = line.slice(0, cursor)\n \n // Try quoted @\"... first (more specific)\n const quotedMatch = /(?:^|\\s)@\"([^\"]*)$/.exec(before)\n if (quotedMatch) {\n const prefix = quotedMatch[0].trimStart()\n return {\n prefix,\n query: quotedMatch[1],\n quoted: true,\n }\n }\n\n // Then try plain @...\n const plainMatch = /(?:^|\\s)@([^\\s@]*)$/.exec(before)\n if (plainMatch) {\n const prefix = plainMatch[0].trimStart()\n return {\n prefix,\n query: plainMatch[1],\n quoted: false,\n }\n }\n\n return undefined\n}\n\n/**\n * Format file/directory candidate as @mention text.\n * \n * @param candidate - File or directory to format\n * @param preserveQuote - Keep quotes even when unnecessary (for drill-down continuity)\n * @returns Formatted @path or undefined for invalid paths\n */\nexport function formatFileMention(candidate: FileCandidate, preserveQuote: boolean): string | undefined {\n const { path } = candidate\n\n // Reject control characters and embedded quotes\n if (/[\\x00-\\x1F\"]/.test(path)) return undefined\n\n const needsQuote = /\\s/.test(path)\n const useQuote = needsQuote || preserveQuote\n\n if (candidate.kind === 'file') {\n return useQuote ? `@\"${path}\"` : `@${path}`\n } else {\n // Directory: trailing slash, quote stays open for drill-down\n return useQuote ? `@\"${path}/` : `@${path}/`\n }\n}\n","/**\n * 通用工具函数\n * @module dsh-group-chat/client/utils\n */\n\nimport { createElement } from 'react'\nimport { flushSync } from 'react-dom'\nimport { createRoot } from 'react-dom/client'\nimport { FileTypeIcon } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { activeAtToken, type AtToken } from '../../shared/file-mention-grammar.ts'\n\n/** HTML 转义(芯片以 execCommand('insertHTML') 注入,角色名需转义)。 */\nexport function escapeHtml(v: string): string {\n return String(v).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"')\n}\n\n/**\n * execCommand 集中封装。它已被 Web 平台标记 @deprecated(ts 6387 编辑器提示),\n * 但仍是唯一能让 contenteditable 的 DOM 编辑进入浏览器原生 undo 栈的同步 API\n * (自研 undo 栈或引入 Lexical/ProseMirror 类框架代价更大;取舍见 DESIGN.md\n * Composer 契约)。经中间别名擦除废弃标记,全部调用走本封装,不在调用处散布提示。\n */\ntype ExecCommandFn = (commandId: string, showUI?: boolean, value?: string) => boolean\nlet execCommandFn: ExecCommandFn | undefined\nexport function execCommand(commandId: 'delete' | 'insertHTML' | 'insertText' | 'insertLineBreak', value?: string): boolean {\n execCommandFn ??= (document as unknown as { execCommand: ExecCommandFn }).execCommand\n return execCommandFn.call(document, commandId, false, value)\n}\n\n/**\n * contenteditable 输入区 → 纯文本序列化(发送/参与判定的唯一事实源):\n * 文本节点原样;<br> → 换行;角色芯片(.dsgc-chipin[data-role-id])展开回「@名字␠」;\n * 文件芯片(.dsgc-chipin[data-kind=file])展开回「@path」或「@\"path with spaces\"」;\n * DIV/P 块前补换行(防粘贴残留的块级包裹)。\n */\nexport function serializeInput(root: HTMLElement): string {\n const walk = (node: Node): string => {\n if (node.nodeType === Node.TEXT_NODE) return node.nodeValue || ''\n if (node.nodeType !== Node.ELEMENT_NODE) return ''\n const el = node as HTMLElement\n if (el.tagName === 'BR') return '\\n'\n if (el.classList.contains('dsgc-chipin')) {\n // 角色芯片\n if (el.dataset.roleId) {\n return '@' + (el.dataset.name || '') + ' '\n }\n // 文件芯片\n if (el.dataset.kind === 'file') {\n const path = el.dataset.path || ''\n const needsQuote = /\\s/.test(path)\n return needsQuote ? `@\"${path}\"` : `@${path}`\n }\n }\n const sep = /^(DIV|P)$/.test(el.tagName) ? '\\n' : ''\n return sep + Array.from(el.childNodes).map(walk).join('')\n }\n return Array.from(root.childNodes).map(walk).join('')\n}\n\n/** @角色芯片的 HTML(原子元素:contenteditable=false + draggable,退格整删)。 */\nexport function chipHtml(role: { id: string, name: string, color?: string }): string {\n const c = escapeHtml(role.color || '#888')\n return '<span class=\"dsgc-chipin\" data-role-id=\"' + escapeHtml(role.id) + '\" data-name=\"' + escapeHtml(role.name) + '\" style=\"--role-color:' + c + '\" contenteditable=\"false\" draggable=\"true\">' +\n '<span class=\"dsgc-chipdot\" style=\"background:' + c + '\"></span>' + escapeHtml(role.name) + '</span>'\n}\n\n/** 把宿主 FileTypeIcon 渲成静态 SVG,再塞进 insertHTML(与检索列表同一套字形)。 */\nfunction fileTypeIconMarkup(path: string, kind: 'file' | 'directory'): string {\n if (typeof document === 'undefined') return ''\n const host = document.createElement('span')\n const root = createRoot(host)\n try {\n flushSync(() => {\n root.render(kind === 'directory'\n ? createElement(FileTypeIcon, { kind: 'folder', size: 14 })\n : createElement(FileTypeIcon, { path, size: 14 }))\n })\n return host.innerHTML\n } finally {\n root.unmount()\n }\n}\n\n/** @文件芯片的 HTML(原子元素:contenteditable=false + draggable,退格整删)。 */\nexport function fileChipHtml(path: string, kind: 'file' | 'directory'): string {\n const basename = path.split('/').pop() || path\n const dir = kind === 'directory'\n return '<span class=\"dsgc-chipin dsgc-chipin-file\" data-kind=\"file\"' + (dir ? ' data-dir=\"1\"' : '') + ' data-path=\"' + escapeHtml(path) + '\" contenteditable=\"false\" draggable=\"true\">' +\n '<span class=\"dsgc-chipglyph\" aria-hidden=\"true\">' + fileTypeIconMarkup(path, kind) + '</span>' + escapeHtml(basename) + '</span>'\n}\n\n/**\n * 光标前的活跃 @token(角色或文件弹层触发判定)。\n * \n * @returns AtToken 对象,包含 prefix/query/quoted;无返回 null\n */\nexport function queryAtCaret(): AtToken | null {\n const sel = window.getSelection()\n if (!sel || !sel.isCollapsed || sel.rangeCount === 0) return null\n const node = sel.anchorNode\n if (!node || node.nodeType !== Node.TEXT_NODE) return null\n const before = (node.nodeValue || '').slice(0, sel.anchorOffset)\n return activeAtToken(before, before.length) || null\n}\n","/**\n * 消息输入相关 hooks\n * @module dsh-group-chat/client/hooks\n */\n\nimport { useCallback, useEffect, type ClipboardEvent as ReactClipboardEvent, type DragEvent as ReactDragEvent, type KeyboardEvent as ReactKeyboardEvent } from 'react'\nimport { execCommand, queryAtCaret, serializeInput, chipHtml, fileChipHtml } from '../utils/utils.ts'\nimport type { AtToken } from '../../shared/file-mention-grammar.ts'\nimport type { SnapshotRole } from '../lib/model.ts'\n\nexport function useComposerEffects(\n inputRef: React.RefObject<HTMLDivElement>,\n scrollRef: React.RefObject<HTMLDivElement>,\n input: string,\n atBottom: boolean,\n snap: unknown,\n) {\n // 贴底时新内容自动跟随滚动\n const onMsgsScroll = useCallback(() => {\n const el = scrollRef.current\n if (!el) return\n const isAtBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 60\n return isAtBottom\n }, [scrollRef])\n\n useEffect(() => {\n const el = scrollRef.current\n if (el && atBottom) el.scrollTop = el.scrollHeight\n }, [snap, atBottom, scrollRef])\n\n // composer 输入框随内容自适应高度\n useEffect(() => {\n const el = inputRef.current\n if (!el) return\n el.style.height = 'auto'\n el.style.height = Math.min(180, Math.max(36, el.scrollHeight)) + 'px'\n }, [input, inputRef])\n\n return { onMsgsScroll }\n}\n\nexport function useComposerInput(\n inputRef: React.RefObject<HTMLDivElement>,\n setInput: (val: string) => void,\n setMention: (val: AtToken | null) => void,\n setMentionIdx: (val: number) => void,\n) {\n /** 从 DOM 同步 input 状态(序列化) */\n const syncFromDOM = useCallback((): void => {\n const el = inputRef.current\n if (!el) return\n setInput(serializeInput(el))\n }, [inputRef, setInput])\n\n const onInputCE = useCallback((): void => {\n syncFromDOM()\n setMention(queryAtCaret())\n setMentionIdx(0)\n }, [syncFromDOM, setMention, setMentionIdx])\n\n /** 粘贴/拖放强制纯文本 */\n const onPasteCE = useCallback((e: ReactClipboardEvent<HTMLDivElement>): void => {\n e.preventDefault()\n const text = e.clipboardData.getData('text/plain')\n if (text) execCommand('insertText', text)\n }, [])\n\n const onDragOverCE = useCallback((e: ReactDragEvent<HTMLDivElement>): void => {\n e.preventDefault()\n }, [])\n\n const onDropCE = useCallback((e: ReactDragEvent<HTMLDivElement>): void => {\n e.preventDefault()\n const text = e.dataTransfer.getData('text/plain')\n if (text) execCommand('insertText', text)\n }, [])\n\n return {\n syncFromDOM,\n onInputCE,\n onPasteCE,\n onDragOverCE,\n onDropCE,\n }\n}\n\nexport function useMentionChip(\n inputRef: React.RefObject<HTMLDivElement>,\n setMention: (val: AtToken | null) => void,\n setMentionIdx: (val: number) => void,\n syncFromDOM: () => void,\n) {\n /** 弹层候选 → 删掉光标前的 @词、插入原子芯片 + 尾随空格 */\n const insertChip = useCallback((role: SnapshotRole): void => {\n const el = inputRef.current\n const sel = window.getSelection()\n if (!el || !sel) return\n if (!sel.anchorNode || !el.contains(sel.anchorNode)) return\n el.focus({ preventScroll: true })\n \n // 1. 删除光标前的 @token(包括引号)\n const node = sel.anchorNode\n if (node.nodeType === Node.TEXT_NODE) {\n const text = node.nodeValue || ''\n const off = sel.anchorOffset\n const before = text.slice(0, off)\n // 匹配 @词 或 @\"词\n const m = /(?:^|\\s)@(\"?)([^\"\\s@]*)$/.exec(before)\n if (m) {\n const prefixLen = m[1] ? 2 : 1 // @\" 或 @\n const queryLen = m[2].length\n const start = off - prefixLen - queryLen\n if (start >= 0) {\n const range = document.createRange()\n range.setStart(node, start)\n range.setEnd(node, off)\n sel.removeAllRanges()\n sel.addRange(range)\n execCommand('delete')\n }\n }\n }\n \n // 2. 插入芯片\n execCommand('insertHTML', chipHtml(role).replace('class=\"dsgc-chipin\"', 'class=\"dsgc-chipin\" data-new=\"\"'))\n const chip = el.querySelector<HTMLElement>('.dsgc-chipin[data-new]')\n if (!chip) return\n \n // 3. 选区显式钉到芯片之后,再补尾随空格\n const after = document.createRange()\n after.setStartAfter(chip)\n after.collapse(true)\n sel.removeAllRanges()\n sel.addRange(after)\n execCommand('insertText', ' ')\n chip.removeAttribute('data-new')\n setMention(null)\n setMentionIdx(0)\n syncFromDOM()\n }, [inputRef, setMention, setMentionIdx, syncFromDOM])\n\n const insertFileChip = useCallback((path: string, kind: 'file' | 'directory'): void => {\n const el = inputRef.current\n const sel = window.getSelection()\n if (!el || !sel) return\n if (!sel.anchorNode || !el.contains(sel.anchorNode)) return\n el.focus({ preventScroll: true })\n \n // 1. 删除光标前的 @token(包括引号)\n const node = sel.anchorNode\n if (node.nodeType === Node.TEXT_NODE) {\n const text = node.nodeValue || ''\n const off = sel.anchorOffset\n const before = text.slice(0, off)\n // 匹配 @词 或 @\"词\n const m = /(?:^|\\s)@(\"?)([^\"\\s@]*)$/.exec(before)\n if (m) {\n const prefixLen = m[1] ? 2 : 1 // @\" 或 @\n const queryLen = m[2].length\n const start = off - prefixLen - queryLen\n if (start >= 0) {\n const range = document.createRange()\n range.setStart(node, start)\n range.setEnd(node, off)\n sel.removeAllRanges()\n sel.addRange(range)\n execCommand('delete')\n }\n }\n }\n \n // 2. 插入文件芯片\n execCommand('insertHTML', fileChipHtml(path, kind).replace('class=\"dsgc-chipin dsgc-chipin-file\"', 'class=\"dsgc-chipin dsgc-chipin-file\" data-new=\"\"'))\n const chip = el.querySelector<HTMLElement>('.dsgc-chipin[data-new]')\n if (!chip) return\n \n // 3. 选区显式钉到芯片之后,再补尾随空格\n const after = document.createRange()\n after.setStartAfter(chip)\n after.collapse(true)\n sel.removeAllRanges()\n sel.addRange(after)\n execCommand('insertText', ' ')\n chip.removeAttribute('data-new')\n setMention(null)\n setMentionIdx(0)\n syncFromDOM()\n }, [inputRef, setMention, setMentionIdx, syncFromDOM])\n\n return { insertChip, insertFileChip }\n}\n\nexport function useInputKeyboard(\n mention: AtToken | null,\n mentionCandidates: SnapshotRole[],\n mentionIdxC: number,\n setMentionIdx: (val: number | ((prev: number) => number)) => void,\n insertChip: (role: SnapshotRole) => void,\n insertFileChip: (path: string, kind: 'file' | 'directory') => void,\n fileCandidates: Array<{ path: string; isDir: boolean }>,\n setMention: (val: AtToken | null) => void,\n sendMsg: () => Promise<void>,\n) {\n const onInputKeyDown = useCallback((e: ReactKeyboardEvent<HTMLDivElement>): void => {\n // IME 组合中的按键不参与任何快捷逻辑\n if (e.nativeEvent.isComposing || e.keyCode === 229) return\n \n // 角色模式(裸 @):Enter/Tab 插入角色芯片\n if (mention !== null && mention.query === '' && mentionCandidates.length) {\n if (e.key === 'ArrowDown') {\n e.preventDefault()\n setMentionIdx((mentionIdxC + 1) % mentionCandidates.length)\n return\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault()\n setMentionIdx((mentionIdxC - 1 + mentionCandidates.length) % mentionCandidates.length)\n return\n }\n if ((e.key === 'Enter' && !e.shiftKey) || e.key === 'Tab') {\n e.preventDefault()\n insertChip(mentionCandidates[mentionIdxC])\n return\n }\n }\n \n // 文件模式(@ + query):Enter 插入文件/Tab 钻入目录/Esc 关闭\n if (mention !== null && mention.query !== '' && fileCandidates.length) {\n if (e.key === 'ArrowDown') {\n e.preventDefault()\n setMentionIdx((mentionIdxC + 1) % fileCandidates.length)\n return\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault()\n setMentionIdx((mentionIdxC - 1 + fileCandidates.length) % fileCandidates.length)\n return\n }\n const selectedItem = fileCandidates[mentionIdxC]\n if (selectedItem) {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n insertFileChip(selectedItem.path, selectedItem.isDir ? 'directory' : 'file')\n return\n }\n if (e.key === 'Tab' && selectedItem.isDir) {\n e.preventDefault()\n insertFileChip(selectedItem.path, 'directory')\n return\n }\n }\n if (e.key === 'Escape') {\n e.preventDefault()\n setMention(null)\n return\n }\n }\n \n if (e.key === 'Enter' && e.shiftKey) {\n e.preventDefault()\n execCommand('insertLineBreak')\n return\n }\n \n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n void sendMsg()\n }\n }, [mention, mentionCandidates, mentionIdxC, fileCandidates, setMentionIdx, insertChip, insertFileChip, setMention, sendMsg])\n\n return { onInputKeyDown }\n}\n","/**\n * 文件搜索 hook:防抖 + 取消过期请求 + 短缓存。\n * @module dsh-group-chat/client/hooks\n */\n\nimport { useEffect, useState } from 'react'\nimport { api } from '../lib/api.ts'\nimport type { AtToken } from '../../shared/file-mention-grammar.ts'\n\nexport interface FileCandidate {\n path: string\n isDir: boolean\n}\n\nexport interface FileSearchResult {\n fileCandidates: FileCandidate[]\n fileSearchError: string | null\n fileSearchLoading: boolean\n}\n\nconst DEBOUNCE_MS = 180\nconst CACHE_LIMIT = 20\nconst cache = new Map<string, FileCandidate[]>()\n\nfunction cacheGet(key: string): FileCandidate[] | undefined {\n const hit = cache.get(key)\n if (!hit) return undefined\n cache.delete(key)\n cache.set(key, hit)\n return hit\n}\n\nfunction cacheSet(key: string, value: FileCandidate[]): void {\n cache.delete(key)\n cache.set(key, value)\n if (cache.size > CACHE_LIMIT) {\n const oldest = cache.keys().next().value\n if (oldest !== undefined) cache.delete(oldest)\n }\n}\n\nfunction isAbort(err: unknown): boolean {\n return !!err && typeof err === 'object' && 'name' in err && (err as { name: string }).name === 'AbortError'\n}\n\n/**\n * 文件搜索:query 变化 180ms 内合并;过期 fetch 真正 abort;\n * 命中短缓存立刻出结果。离开文件模式才清空列表,避免每个按键闪「检索中」。\n */\nexport function useFileSearch(\n mention: AtToken | null,\n groupId: string | undefined,\n): FileSearchResult {\n const [fileCandidates, setFileCandidates] = useState<FileCandidate[]>([])\n const [fileSearchError, setFileSearchError] = useState<string | null>(null)\n const [fileSearchLoading, setFileSearchLoading] = useState(false)\n\n const query = mention && mention.query !== '' ? mention.query : null\n\n useEffect(() => {\n if (query === null || !groupId) {\n setFileCandidates([])\n setFileSearchError(null)\n setFileSearchLoading(false)\n return\n }\n\n const key = groupId + '\\0' + query\n const hit = cacheGet(key)\n if (hit) {\n setFileCandidates(hit)\n setFileSearchError(null)\n setFileSearchLoading(false)\n return\n }\n\n const controller = new AbortController()\n setFileSearchLoading(true)\n const timer = window.setTimeout(() => {\n void (async () => {\n try {\n const res = await api.action({\n kind: 'fileSearch',\n groupId,\n query,\n }, controller.signal) as { ok: true, candidates?: FileCandidate[] } | { ok: false, error?: string }\n\n if (controller.signal.aborted) return\n if (res.ok) {\n const next = res.candidates || []\n cacheSet(key, next)\n setFileCandidates(next)\n setFileSearchError(null)\n } else {\n setFileCandidates([])\n setFileSearchError(res.error || '文件检索失败')\n }\n } catch (err) {\n if (controller.signal.aborted || isAbort(err)) return\n setFileCandidates([])\n setFileSearchError(String(err))\n } finally {\n if (!controller.signal.aborted) setFileSearchLoading(false)\n }\n })()\n }, DEBOUNCE_MS)\n\n return () => {\n window.clearTimeout(timer)\n controller.abort()\n }\n }, [query, groupId])\n\n return { fileCandidates, fileSearchError, fileSearchLoading }\n}\n","/**\n * 提及状态 hook:封装角色/文件提及相关的派生状态计算\n * @module dsh-group-chat/client/hooks\n */\n\nimport { useMemo } from 'react'\nimport { escapeRegExp, type SnapshotRole } from '../lib/model.ts'\nimport type { AtToken } from '../../shared/file-mention-grammar.ts'\n\n/**\n * 计算角色提及候选列表\n * @param mention - 当前 @ token 状态\n * @param enabledRoles - 启用的角色列表\n * @returns 角色候选列表(仅在角色模式且 query 为空时返回)\n */\nexport function useMentionCandidates(\n mention: AtToken | null,\n enabledRoles: SnapshotRole[],\n): SnapshotRole[] {\n return useMemo(() => {\n // 角色模式:仅当 mention 存在且 query 为空时显示全部启用角色\n return mention !== null && mention.query === '' ? enabledRoles : []\n }, [mention, enabledRoles])\n}\n\n/**\n * 检测输入文本中被 @ 的角色\n * @param input - 输入文本\n * @param enabledRoles - 启用的角色列表\n * @returns 被提及的角色列表\n */\nexport function useMentionedRoles(\n input: string,\n enabledRoles: SnapshotRole[],\n): SnapshotRole[] {\n return useMemo(() => {\n return enabledRoles.filter((r) =>\n new RegExp('(^|\\\\s)@' + escapeRegExp(r.name) + '(?=\\\\s|$)').test(input)\n )\n }, [input, enabledRoles])\n}\n\n/**\n * 计算安全的候选索引(确保不越界)\n * @param candidatesLength - 候选列表长度\n * @param currentIndex - 当前索引\n * @returns 安全的索引值\n */\nexport function useSafeMentionIndex(\n candidatesLength: number,\n currentIndex: number,\n): number {\n return useMemo(() => {\n return candidatesLength ? Math.min(currentIndex, candidatesLength - 1) : 0\n }, [candidatesLength, currentIndex])\n}\n","/**\n * 主面板:三区工作台——左导航栏(搜索 + 群组→会话目录树)、中央会话流\n * (@成员 点名 + markdown 渲染 + 思考折叠)、右上下文栏(群成员角色卡 +\n * 工作区目录),右栏可收起,角色编辑走右侧滑出抽屉。\n *\n * 面板数据走 /api/group-chat/*(fetch + SSE),Host 半持有全部状态。\n * @module dsh-group-chat/client/panel\n */\n\nimport { useCallback, useEffect, useState, type ReactNode } from 'react'\nimport { Icon, P } from './lib/ui.ts'\nimport { api } from './lib/api.ts'\nimport { RoleDrawer } from './components/RoleDrawer.tsx'\nimport { NavPanel } from './components/NavPanel.tsx'\nimport { AsidePanel } from './components/AsidePanel.tsx'\nimport { ChatPanel } from './components/ChatPanel.tsx'\nimport { useGroupChatState, type ActionOk } from './hooks/useGroupChatState.ts'\nimport { useComposerEffects, useComposerInput, useMentionChip, useInputKeyboard } from './hooks/useComposer.ts'\nimport { useFileSearch } from './hooks/useFileSearch.ts'\nimport { useMentionCandidates, useMentionedRoles, useSafeMentionIndex } from './hooks/useMentionState.ts'\nimport { draftFromRole, blankDraft, groupById, roleById, sessById, type ClientSnapshot, type ModelsResponse, type SnapshotRole } from './lib/model.ts'\n\nexport function GroupChatPanel(): ReactNode {\n const state = useGroupChatState()\n const {\n snap,\n gid,\n setGid,\n sid,\n setSid,\n search,\n setSearch,\n collapsedGroups,\n setCollapsedGroups,\n renameDraft,\n setRenameDraft,\n confirmDel,\n setConfirmDel,\n confirmClear,\n setConfirmClear,\n roleDraft,\n setRoleDraft,\n roleFormError,\n setRoleFormError,\n models,\n setModels,\n modelsError,\n setModelsError,\n fileBrowser,\n setFileBrowser,\n wsDraft,\n setWsDraft,\n partsSel,\n setPartsSel,\n rounds,\n setRounds,\n input,\n setInput,\n err,\n setErr,\n topicDraft,\n setTopicDraft,\n mention,\n setMention,\n mentionIdx,\n setMentionIdx,\n asideOpen,\n setAsideOpen,\n navOpen,\n setNavOpen,\n atBottom,\n setAtBottom,\n inputRef,\n sendingRef,\n scrollRef,\n action,\n mutate,\n } = state\n\n // 瞬时通知(toast):key 为展示序号,同文案重复触发也会重启动画\n const [toast, setToast] = useState<{ text: string, seq: number } | null>(null)\n\n // ---- 所有 Hooks 必须在条件返回之前调用 ----\n // Composer effects\n const { onMsgsScroll } = useComposerEffects(inputRef, scrollRef, input, atBottom, snap)\n const { syncFromDOM, onInputCE, onPasteCE, onDragOverCE, onDropCE } = useComposerInput(inputRef, setInput, setMention, setMentionIdx)\n\n // 选中群组/会话解析(用于 hooks 依赖)\n let group = snap && gid ? groupById(snap, gid) : null\n if (!group && snap && snap.groups.length) group = snap.groups[0]\n let sess = snap && sid ? sessById(snap, sid) : null\n // 有效会话统一兜底(与渲染体一致):sid 未建立/未命中/跨群不匹配时取当前群组\n // 最后一个会话——必须在 busyNow 等 run 派生值之前完成,否则流式行/停止按钮\n // 在兜底视图(典型:host 重启后 lastCreated 为空、选中态从未建立)下永远失活\n if ((!sess || sess.groupId !== group?.id) && group && snap) {\n sess = group.sessionIds.length ? sessById(snap, group.sessionIds[group.sessionIds.length - 1]) : null\n }\n\n const enabledRoles = group ? group.roleIds.map((id) => roleById(snap!, id)).filter((r): r is SnapshotRole => !!r && r.enabled) : []\n const participants = partsSel || enabledRoles.map((r) => r.id)\n const busyNow = !!(sess && snap && snap.run.running && snap.run.sessionId === sess.id)\n\n // 查看即清:当前选中会话即 run.finished 所指会话 → 发 ackFinish 确认已读\n // (host 幂等清除 + 广播;覆盖点击/键盘/重挂恢复/lastCreated 定位全部选中路径)\n const finishedRun = snap ? snap.run.finished : null\n useEffect(() => {\n if (finishedRun && sess && finishedRun.sessionId === sess.id) void mutate({ op: 'ackFinish' })\n }, [finishedRun, sess])\n\n // 提及状态:角色候选、文件搜索、索引安全化\n const mentionCandidates = useMentionCandidates(mention, enabledRoles)\n const { fileCandidates, fileSearchError, fileSearchLoading } = useFileSearch(\n mention,\n group?.id,\n )\n const mentionIdxC = useSafeMentionIndex(\n mentionCandidates.length || fileCandidates.length,\n mentionIdx\n )\n \n const mentionedRoles = useMentionedRoles(input, enabledRoles)\n\n const { insertChip, insertFileChip } = useMentionChip(inputRef, setMention, setMentionIdx, syncFromDOM)\n\n const sendMsg = useCallback(async (): Promise<void> => {\n if (busyNow || !sess || sendingRef.current) return\n sendingRef.current = true\n try {\n const parts = mentionedRoles.length ? mentionedRoles.map((r) => r.id) : participants\n if (!parts.length) {\n setErr(mentionedRoles.length ? '' : '请至少选择一个参与角色(或在消息中 @成员)')\n if (!mentionedRoles.length) return\n }\n const res = await action({ kind: 'send', sessionId: sess.id, text: input, participantRoleIds: parts, rounds }) as ActionOk | null\n if (res && !res.ok && res.error) setErr(res.error)\n else if (res && res.ok) {\n const el = inputRef.current\n if (el) el.innerHTML = ''\n setInput('')\n setMention(null)\n setErr('')\n setAtBottom(true)\n syncFromDOM()\n }\n } finally {\n sendingRef.current = false\n }\n }, [busyNow, sess, sendingRef, mentionedRoles, participants, action, rounds, input, inputRef, setInput, setMention, setErr, setAtBottom, syncFromDOM])\n\n const { onInputKeyDown } = useInputKeyboard(mention, mentionCandidates, mentionIdxC, setMentionIdx, insertChip, insertFileChip, fileCandidates, setMention, sendMsg)\n\n // ---- 条件性早期返回 ----\n if (!snap) {\n return (\n <div className=\"dsgc-root\">\n <div className=\"dsgc-loading\">{Icon(P.IconLoadingOutline16, 16)}加载中…</div>\n </div>\n )\n }\n\n if (!group) {\n return (\n <div className=\"dsgc-root\">\n <div className=\"dsgc-loading\">暂无群组</div>\n </div>\n )\n }\n\n const msgById: Record<string, ClientSnapshot['messages'][number]> = {}\n for (const m of snap.messages) msgById[m.id] = m\n\n const togglePart = (rid: string): void => {\n const has = participants.includes(rid)\n setPartsSel(has ? participants.filter((x) => x !== rid) : participants.concat([rid]))\n }\n\n // 清空确认:不可清空(对话进行中)走 toast 提示,不再落到输入框上方的红字\n const doClear = async (): Promise<void> => {\n if (!sess) return\n if (busyNow) {\n setToast({ text: '对话进行中,需先停止才能清空', seq: Date.now() })\n return\n }\n const res = await mutate({ op: 'clearMessages', sessionId: sess.id })\n if (res && res.ok && res.snapshot && !res.snapshot.error) setConfirmClear(false)\n else if (res && res.snapshot && res.snapshot.error) {\n setErr('')\n setToast({ text: res.snapshot.error, seq: Date.now() })\n }\n }\n\n // ---- 动作 ----\n const fetchModels = async (): Promise<void> => {\n try {\n const m = await api.action({ kind: 'models' }) as ModelsResponse\n if (m && m.ok && Array.isArray(m.providers)) {\n setModels(m)\n setModelsError(null)\n return\n }\n setModelsError(m && m.error ? String(m.error) : '响应异常')\n } catch (e) {\n setModelsError(String((e && (e as Error).message) || e))\n }\n }\n\n const openRoleEditor = async (role: SnapshotRole | null): Promise<void> => {\n setErr('')\n setRoleFormError('')\n if (!models || modelsError) await fetchModels()\n setRoleDraft(role ? draftFromRole(role) : blankDraft())\n }\n\n const saveRole = async (): Promise<void> => {\n if (!roleDraft) return\n if (!roleDraft.name.trim()) {\n setRoleFormError('角色名称不能为空')\n return\n }\n if (!roleDraft.provider || !roleDraft.model) {\n setRoleFormError('请选择角色绑定的模型')\n return\n }\n const res = await mutate({ op: 'upsertRole', groupId: group.id, role: roleDraft })\n if (res && res.ok && res.snapshot && !res.snapshot.error) {\n setRoleDraft(null)\n setRoleFormError('')\n }\n }\n\n const stopRun = async (): Promise<void> => {\n await action({ kind: 'stop', sessionId: sess!.id })\n }\n\n const openBrowser = async (path: string | undefined): Promise<void> => {\n setFileBrowser({ open: true, loading: true, list: null, error: '' })\n try {\n const res = await api.action({ kind: 'browse', path: path || '' }) as import('../core/types.ts').BrowseResult\n if (res && res.ok) setFileBrowser({ open: true, loading: false, list: res, error: '' })\n else setFileBrowser({ open: true, loading: false, list: null, error: (res && res.error) || '浏览失败' })\n } catch (e) {\n setFileBrowser({ open: true, loading: false, list: null, error: String((e && (e as Error).message) || e) })\n }\n }\n\n const selectCurrentDir = (): void => {\n if (!fileBrowser || !fileBrowser.list || !group) return\n const path = fileBrowser.list.path!\n void mutate({ op: 'setWorkspaceDir', groupId: group.id, path })\n setWsDraft(null)\n setFileBrowser(null)\n }\n\n return (\n <div className=\"dsgc-root\">\n <NavPanel\n snap={snap}\n search={search}\n setSearch={setSearch}\n collapsedGroups={collapsedGroups}\n setCollapsedGroups={setCollapsedGroups}\n gid={group.id}\n sid={sess ? sess.id : sid}\n setGid={setGid}\n setSid={setSid}\n setPartsSel={setPartsSel}\n renameDraft={renameDraft}\n setRenameDraft={setRenameDraft}\n confirmDel={confirmDel}\n setConfirmDel={setConfirmDel}\n mutate={mutate}\n navOpen={navOpen}\n />\n <ChatPanel\n snap={snap}\n sess={sess}\n group={group}\n enabledRoles={enabledRoles}\n participants={participants}\n mentionedRoles={mentionedRoles}\n busyNow={busyNow}\n input={input}\n mention={mention}\n mentionCandidates={mentionCandidates}\n mentionIdxC={mentionIdxC}\n fileCandidates={fileCandidates}\n fileSearchError={fileSearchError}\n fileSearchLoading={fileSearchLoading}\n rounds={rounds}\n err={err}\n atBottom={atBottom}\n topicDraft={topicDraft}\n msgById={msgById}\n navOpen={navOpen}\n asideOpen={asideOpen}\n inputRef={inputRef}\n scrollRef={scrollRef}\n setTopicDraft={setTopicDraft}\n setConfirmClear={setConfirmClear}\n setMentionIdx={setMentionIdx}\n setRounds={setRounds}\n setNavOpen={setNavOpen}\n setAsideOpen={setAsideOpen}\n togglePart={togglePart}\n onMsgsScroll={() => {\n const isBottom = onMsgsScroll()\n if (isBottom !== undefined) setAtBottom(isBottom)\n }}\n onInputCE={onInputCE}\n onInputKeyDown={onInputKeyDown}\n onPasteCE={onPasteCE}\n onDropCE={onDropCE}\n onDragOverCE={onDragOverCE}\n insertChip={insertChip}\n insertFileChip={insertFileChip}\n sendMsg={sendMsg}\n stopRun={stopRun}\n action={action}\n mutate={mutate}\n setMention={setMention}\n />\n <AsidePanel\n snap={snap}\n group={group}\n asideOpen={asideOpen}\n wsDraft={wsDraft}\n setWsDraft={setWsDraft}\n fileBrowser={fileBrowser}\n setFileBrowser={setFileBrowser}\n mutate={mutate}\n openRoleEditor={openRoleEditor}\n openBrowser={openBrowser}\n selectCurrentDir={selectCurrentDir}\n />\n {sess && confirmClear\n ? (\n <P.Modal\n open\n onClose={() => { setConfirmClear(false) }}\n title=\"清空本会话的消息记录?\"\n closeLabel=\"关闭\"\n description={'会话「' + sess.name + '」的全部 ' + sess.messageIds.length + ' 条消息将被永久删除'}\n footer={(\n <>\n <P.Button variant=\"outline\" size=\"sm\" onClick={() => { setConfirmClear(false) }}>取消</P.Button>\n <P.Button variant=\"outline\" size=\"sm\" className=\"dsgc-stopbtn\" onClick={() => { void doClear() }}>清空</P.Button>\n </>\n )}\n >\n <ul className=\"dsgc-clearnotes\">\n <li>删除内容:本会话的用户消息与角色发言(含思考、工具调用记录),确认后立即落盘</li>\n <li>不可恢复:此操作没有回收站,也没有撤销</li>\n <li>不受影响:会话本身与主题、群成员角色、工作区目录、权限档位</li>\n </ul>\n </P.Modal>\n )\n : null}\n {toast\n ? (\n <P.Toast\n key={toast.seq}\n text={toast.text}\n icon={Icon(P.IconWarningOutline16, 16)}\n anchor={inputRef.current}\n onDone={() => { setToast(null) }}\n />\n )\n : null}\n {roleDraft\n ? (\n <RoleDrawer\n draft={roleDraft}\n set={setRoleDraft}\n models={models}\n modelsError={modelsError}\n onRetryModels={() => { void fetchModels() }}\n onSave={() => { void saveRole() }}\n onCancel={() => { setRoleDraft(null); setRoleFormError('') }}\n formError={roleFormError}\n />\n )\n : null}\n </div>\n )\n}\n","/**\n * 设置页:启停开关(settings.section 插槽)。写 host 的 group-chat 设置\n * 命名空间(settings.yaml 持久化)。\n * @module dsh-group-chat/client/settings\n */\n\nimport { useEffect, useState, type ReactNode } from 'react'\nimport type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client'\nimport { P } from '../lib/ui.ts'\n\n/** Host 侧注册的设置命名空间 shape。 */\ninterface GroupChatSettings {\n enabled?: boolean\n}\n\nexport function GroupChatSettingsSection(props: { settingsScope: SettingsScope<GroupChatSettings> }): ReactNode {\n const scope = props.settingsScope\n const [snap, setSnap] = useState<ReturnType<SettingsScope<GroupChatSettings>['getSnapshot']> | null>(null)\n const [pending, setPending] = useState(false)\n\n useEffect(() => {\n let live = true\n const read = (): void => {\n if (!live) return\n try {\n setSnap(scope.getSnapshot())\n } catch { /* ignore */ }\n }\n read()\n const off = scope.subscribe(read)\n return () => {\n live = false\n off()\n }\n }, [])\n\n const ready = snap !== null && snap.status === 'ready'\n const writable = ready ? snap.writable !== false : false\n const enabled = ready ? (snap.value && snap.value.enabled) !== false : true\n\n const toggle = async (): Promise<void> => {\n if (!writable || pending) return\n setPending(true)\n try {\n await scope.set('enabled', !enabled)\n } catch (e) {\n console.error('[dsh-group-chat] settings write failed', e)\n } finally {\n setPending(false)\n }\n }\n\n return (\n <div className=\"dgcs-page\">\n <div className=\"dgcs-head\">\n <h3 className=\"dgcs-title\">模型群聊</h3>\n <p className=\"dgcs-desc\">多模型角色群组对话面板:每个角色绑定不同的 provider/model;群组内多会话目录树管理,群内共享对话记录与工作区目录;消息以 markdown 渲染、支持思考折叠;输入框支持 @成员 / @文件。数据持久化于 ~/.dsh/storages/group-chat/,重启 dsh web 后恢复。</p>\n </div>\n <div className=\"dgcs-card\">\n <div className=\"dgcs-cardtext\">\n <div className=\"dgcs-cardtitle\">{enabled ? '已启用' : '已停用'}</div>\n <div className=\"dgcs-cardhint\">{writable ? (enabled ? '关闭后侧边栏将不再显示「群聊」入口,进行中的对话会被中止。' : '开启后侧边栏显示「群聊」入口。') : '当前设置不可写(可能被配置文件覆盖)。'}</div>\n </div>\n <P.Switch\n checked={enabled}\n onChange={() => { void toggle() }}\n disabled={!writable || pending}\n label=\"模型群聊启停\"\n title={pending ? '正在写入…' : enabled ? '点击停用' : '点击启用'}\n />\n </div>\n </div>\n )\n}\n","/**\n * 侧边栏入口图标。\n *\n * 整行命中层携带 “newSession” 类名:任务看板等 DOM 注入式面板用\n * [class*=\"newSession\"] 识别“侧边栏导航点击”并自动收起自己,与点击\n * “新建会话”行为一致——类名不可哈希化。\n * @module dsh-group-chat/client/glyph\n */\n\nimport type { ReactNode } from 'react'\n\nexport function Glyph(props: { size?: number }): ReactNode {\n const size = (props && props.size) || 18\n return (\n <span className=\"dsgc-entryOverlay newSession\">\n <span className=\"dsgc-entryIcon\">\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\n strokeWidth={1.8} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2\" />\n <circle cx={9} cy={7} r={4} />\n <path d=\"M23 21v-2a4 4 0 0 0-3-3.87\" />\n <path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\n </svg>\n </span>\n </span>\n )\n}\n","/**\n * dsh-group-chat — 浏览器半(web 客户端模块)。\n *\n * 经 window.__ModuleLoader__.load 注册(由 tsdown 预设的 banner/footer 闭包\n * 工厂外壳生成);factory 返回 Cordis 客户端插件:\n * - 「模型群聊」设置页(settings.section):启停开关,写 host 的 group-chat\n * 设置命名空间(settings.yaml 持久化)\n * - 启用时挂载:侧边栏「群聊」入口(sidebar.panellist)+ 中央主面板(main)\n * - 面板数据走 /api/group-chat/*(fetch + SSE),Host 半持有全部状态\n * - DSW 原语(@deepseek-ai/dsh-client-ui-primitives,shell 静态种子模块)\n * 提供按钮/输入/开关/菜单/图标与 MarkdownText 渲染器\n *\n * 设计契约(impeccable direction contract;seed key 76db9e37,surface roll\n * 第 4/6/1 手中用户锁定 C「三区工作台」,代码先行):\n * THESIS 三区工作台;FIRST VIEWPORT 左 232px 导航 + 中央会话流 + 右 304px\n * 上下文栏(窄容器覆盖式、可收起)。完整契约见 docs/DESIGN.md。\n *\n * @module dsh-group-chat/client\n */\n\nimport type { Context as ClientContext } from '@deepseek-ai/cordis'\nimport type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client'\n// Type-only:拉入浏览器面的 Context 合并(ctx.settingsScope)。\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\n// Type-only:拉入 ctx.slots 合并(renderer 自 0.1.2 起拥有槽位注册表)。\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\nimport { createElement as h } from 'react'\nimport { injectStyles } from './lib/styles.ts'\nimport { GroupChatPanel } from './GroupChatPanel.tsx'\nimport { GroupChatSettingsSection } from './components/GroupChatSettingsSection.tsx'\nimport { Glyph } from './components/Glyph.tsx'\n\n/** Host 侧注册的设置命名空间 shape 与命名名(与宿主半拼写同一值,两边不共享代码)。 */\ninterface GroupChatSettings {\n enabled?: boolean\n}\nconst SETTINGS_NAMESPACE = 'group-chat'\n\n/** Client plugin id. */\nexport const name = 'group-chat-client'\n\n/** Required services. */\nexport const inject = ['slots', 'settingsScope']\n\n/**\n * Shell 布局槽位的类型声明镜像(运行时由外壳的 layout/sidebar 包声明):\n * 中央主面板为 keyed 槽(按 key 挂载),侧边栏面板列表为 list 槽\n * (id + order + label)。参照 dsh-web 家族外部包的自声明模式。\n */\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface SlotMap {\n /** 中央主面板:按 key 挂载一个面板组件。 */\n 'main': { kind: 'keyed', scope: 'root', owner: Record<string, never> }\n /** 侧边栏面板列表行:图标 + 标签入口。 */\n 'sidebar.panellist': { kind: 'list', scope: 'root', owner: { size?: number } }\n }\n}\n\n/**\n * 客户端插件体:设置页常驻注册 + 启用门控挂载侧边栏入口与主面板。\n * @param ctx - client root context.\n */\nexport function apply(ctx: ClientContext): void {\n injectStyles()\n\n const scope: SettingsScope<GroupChatSettings> = ctx.settingsScope.bind({ namespace: SETTINGS_NAMESPACE })\n\n // 设置页常驻注册(禁用时也保留入口,便于重新启用)\n ctx.slots.inject('settings.section', () =>\n ctx.slots.register(\n {\n name: 'settings.section',\n id: 'dsh-group-chat',\n order: 60,\n label: () => '模型群聊',\n inject: () => ({ settingsScope: scope }),\n },\n (props: { settingsScope: SettingsScope<GroupChatSettings> }) => h(GroupChatSettingsSection, props),\n ),\n )\n\n // 启用门控:enabled 为 false 时卸载侧边栏入口与主面板\n let uiDisposer: (() => void) | undefined\n const mountUi = (): void => {\n if (uiDisposer !== undefined) return\n const disposers: (() => void)[] = []\n try {\n disposers.push(ctx.slots.inject('main', () =>\n ctx.slots.register({ name: 'main', key: 'group-chat' }, () => h(GroupChatPanel, null))))\n disposers.push(ctx.slots.inject('sidebar.panellist', () =>\n ctx.slots.register({ name: 'sidebar.panellist', id: 'group-chat', order: 50, label: '群聊' }, (props: { size?: number }) => h(Glyph, props))))\n } catch (e) {\n console.error('[dsh-group-chat] mount failed:', e)\n }\n uiDisposer = () => {\n uiDisposer = undefined\n for (const dispose of disposers.splice(0)) dispose()\n }\n }\n const syncEnabled = (): void => {\n const snapshot = scope.getSnapshot()\n const on = snapshot.status === 'ready'\n ? (snapshot.value && snapshot.value.enabled) !== false\n : snapshot.status === 'unavailable'\n if (on) mountUi()\n else if (uiDisposer !== undefined) uiDisposer()\n }\n scope.subscribe(syncEnabled)\n syncEnabled()\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASA,MAAM,SAAS;EAEf,MAAa,MAAM;GAEjB;GACA;GAGA;GACA;GACA;GAEA;GAKA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GAIA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAIA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAKA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAIA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GACA;GAEA;GAIA;GAGA;GACA;GAIA;GAEA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GAGA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GAEA;GACA;GAEA;GACA;GACA;GAGA;GAKA;GACA;GAGA;GACA;GACA;GACA;GACA;G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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["h","createElement","P","useState","P","P","P","useState","P","useState","P","P","memo","P","useState","P","P","P","useState","useRef","useCallback","createRoot","createElement","FileTypeIcon","useCallback","useState","useMemo","useState","useCallback","P","useState","P","h"],"sources":["../src/client/lib/styles.ts","../src/client/lib/ui.ts","../src/core/status.ts","../src/client/lib/model.ts","../src/client/lib/api.ts","../src/client/components/RoleDrawer.tsx","../src/client/components/NavPanel.tsx","../src/client/components/AsidePanel.tsx","../src/client/components/ThinkRow.tsx","../src/client/components/ToolRow.tsx","../src/client/components/Bubble.tsx","../src/client/components/MessageFlow.tsx","../src/core/types.ts","../src/client/components/PermissionSelect.tsx","../src/client/components/Composer.tsx","../src/client/components/ChatPanel.tsx","../src/client/hooks/useGroupChatState.ts","../src/shared/file-mention-grammar.ts","../src/client/utils/utils.ts","../src/client/hooks/useComposer.ts","../src/client/hooks/useFileSearch.ts","../src/client/hooks/useMentionState.ts","../src/client/GroupChatPanel.tsx","../src/client/components/GroupChatSettingsSection.tsx","../src/client/components/Glyph.tsx","../src/client/index.ts"],"sourcesContent":["/**\n * 浏览器半样式:CSS 以内联字符串承载(刻意不迁移 CSS Modules 管线——\n * 类名需保持原样,侧栏入口的 “newSession” 类名是任务看板等 DOM 注入式\n * 面板识别“侧边栏导航点击”的跨插件标记,哈希化会破坏该约定)。\n * 工厂执行时幂等注入 <style>,loader 卸载时按 data-plugin 摘除标签。\n * @module dsh-group-chat/client/styles\n */\n\n/** 注入标签的唯一 id。 */\nconst TAG_ID = 'dsh-group-chat/styles.css'\n\nexport const CSS = [\n /* ===== 布局骨架:三区工作台;卡片只用于内容单元,导航用平铺行 ===== */\n '.dsgc-root{display:flex;height:100%;min-height:0;background:var(--dsw-alias-bg-base,transparent);color:var(--dsw-alias-label-primary,inherit);font-size:var(--dsh-content-font-size,14px);container-type:inline-size;position:relative}',\n '.dsgc-loading{padding:24px;color:var(--dsw-alias-label-tertiary,inherit);display:flex;gap:8px;align-items:center;opacity:0;animation:dsgc-loading-in .18s ease-out .15s forwards}',\n /* 首开加载态延迟 150ms 淡入:本机回路通常数毫秒内数据即达并卸载本元素,\n 快路径完全不可见(无闪现,等同移除);慢路径才出现反馈,空白面板不再是唯一信号 */\n '@keyframes dsgc-loading-in{to{opacity:1}}',\n '.dsgc-loading svg{animation:dsgc-spin 1s linear infinite}',\n '@keyframes dsgc-spin{to{transform:rotate(360deg)}}',\n /* ===== 左导航栏(可收起,收合动画与右栏同款配方) ===== */\n '.dsgc-nav{width:232px;flex:none;display:flex;flex-direction:column;gap:8px;border-right:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.2));padding:12px 10px;min-height:0;min-width:0;transition:width .28s cubic-bezier(.16,1,.3,1),opacity .18s ease,padding .28s cubic-bezier(.16,1,.3,1),border-right-width .28s cubic-bezier(.16,1,.3,1)}',\n /* 子元素经 flex 列默认 stretch 填满内容区(不写死宽度:内容区实宽 232px——\n 宿主无全局 border-box,面板为 content-box,旧版写死 212px 曾致右侧多出\n 20px 死区、左右内距失衡);收合动画期间内容随面板收缩,行内 ellipsis\n 渐进截断 + visibility 0.22s 切断,无溢出涂抹 */\n '.dsgc-nav>*{flex:none}',\n '.dsgc-nav.closed{width:0;opacity:0;padding-left:0;padding-right:0;border-right-width:0;visibility:hidden;transition:width .24s ease-in,opacity .16s ease-in,padding .24s ease-in,border-right-width .24s ease-in,visibility 0s .22s}',\n '.dsgc-search{flex:none}',\n '.dsgc-search input{font-size:13px}',\n '.dsgc-search:focus-within{border-color:var(--dsw-alias-state-business-primary,#4f6ef7)}',\n '.dsgc-tree{display:flex;flex-direction:column;gap:6px;flex:1;overflow-y:auto;min-height:0;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent}',\n '.dsgc-grow-row{display:flex;align-items:center;gap:2px;min-width:0;border:none;background:none;border-radius:6px;padding:5px 6px;color:var(--dsw-alias-label-secondary,inherit);transition:background-color .12s,color .12s;cursor:pointer;font:inherit;text-align:left}',\n '.dsgc-grow-row:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.12));color:var(--dsw-alias-label-primary,inherit)}',\n '.dsgc-grow-row.on{color:var(--dsw-alias-label-primary,inherit);font-weight:600}',\n '.dsgc-twist{flex:none;width:16px;height:16px;border:none;background:none;color:inherit;cursor:pointer;padding:0;display:inline-flex;align-items:center;justify-content:center}',\n '.dsgc-twist svg{transition:transform .16s ease}',\n '.dsgc-twist.closed svg{transform:rotate(-90deg)}',\n '.dsgc-gname{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',\n '.dsgc-nodeops{display:none;gap:2px;flex:none}',\n '.dsgc-grow-row:hover .dsgc-nodeops,.dsgc-sess-row:hover .dsgc-nodeops{display:inline-flex}',\n '.dsgc-opbtn{border:none;background:none;color:var(--dsw-alias-label-tertiary,inherit);cursor:pointer;padding:2px;border-radius:4px;line-height:0;transition:background-color .12s,color .12s}',\n '.dsgc-opbtn:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.15));color:var(--dsw-alias-label-primary,inherit)}',\n '.dsgc-opbtn.danger{color:var(--dsw-alias-state-error-primary,#e5484d)}',\n '.dsgc-sess-list{display:flex;flex-direction:column;gap:2px;margin:4px 0 2px 4px;padding-left:12px;border-left:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.15))}',\n '.dsgc-sess-row{display:flex;align-items:center;gap:6px;min-width:0;border:none;background:none;border-radius:6px;padding:6px 8px;font-size:12.5px;line-height:1.5;color:var(--dsw-alias-label-secondary,inherit);transition:background-color .12s,color .12s;cursor:pointer;text-align:left;font-family:inherit}',\n '.dsgc-sess-row:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.12));color:var(--dsw-alias-label-primary,inherit)}',\n '.dsgc-sess-row.on{background:var(--dsw-alias-interactive-bg-active,rgba(128,128,128,.2));color:var(--dsw-alias-label-primary,inherit);font-weight:600}',\n '.dsgc-sess-status{flex:none;width:8px;height:8px;display:inline-flex;justify-content:center;align-items:center}',\n '.dsgc-sess-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',\n '.dsgc-addsess{border:none;background:none;color:var(--dsw-alias-label-tertiary,inherit);cursor:pointer;text-align:left;font-size:12px;line-height:1.5;padding:5px 8px;border-radius:6px;transition:background-color .12s,color .12s;font-family:inherit;display:flex;align-items:center;gap:5px;white-space:nowrap;overflow:hidden}',\n '.dsgc-addsess:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.12));color:var(--dsw-alias-label-primary,inherit)}',\n '.dsgc-rename{font:inherit;font-size:12.5px;min-width:0;flex:1;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));background:var(--dsw-specific-input-major,var(--dsw-alias-bg-layer-3,transparent));color:inherit;border-radius:6px;padding:1px 6px;outline:none;transition:border-color .16s}',\n '.dsgc-rename:focus{border-color:var(--dsw-alias-state-business-primary,#4f6ef7)}',\n '.dsgc-hint{font-size:12px;color:var(--dsw-alias-label-tertiary,inherit);line-height:1.5;text-wrap:balance}',\n /* ===== 中央会话区 ===== */\n '.dsgc-chat{flex:1;display:flex;flex-direction:column;min-width:0;min-height:0;position:relative}',\n /* 接缝收合钮:钉在会话区两缘、垂直居中、各控其侧(图标方向相反的 chevron)。\n 宽模式下面板宽度过渡 → 中栏连续变宽,绝对定位的钮贴缘自动随接缝滑行(布局驱动);\n 窄模式右栏为覆盖层,钮用同曲线 right 过渡跟踪其左缘。浮层配方:实底 + border-l2 + 轻方向性软影 */\n '.dsgc-seambtn{position:absolute;top:50%;transform:translateY(-50%);z-index:14;width:24px;height:56px;display:flex;align-items:center;justify-content:center;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));background:var(--dsw-alias-bg-layer-3,#fff);color:var(--dsw-alias-label-secondary,inherit);cursor:pointer;transition:background-color .12s,color .12s,border-color .12s,right .3s cubic-bezier(.16,1,.3,1)}',\n '.dsgc-seambtn:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.15));color:var(--dsw-alias-label-primary,inherit);border-color:var(--dsw-alias-border-l3,rgba(128,128,128,.4))}',\n '.dsgc-seambtn.left{left:0;border-left:none;border-radius:0 8px 8px 0;box-shadow:3px 0 10px rgba(0,0,0,.07)}',\n '.dsgc-seambtn.right{right:0;border-right:none;border-radius:8px 0 0 8px;box-shadow:-3px 0 10px rgba(0,0,0,.07)}',\n '.dsgc-chathead{display:flex;gap:10px;align-items:center;padding:12px 16px;border-bottom:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.2))}',\n '.dsgc-sess-title{flex:none;font-weight:600;font-size:14px;color:var(--dsw-alias-label-primary,inherit);max-width:30%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',\n '.dsgc-topic{flex:1;background:transparent;border:none;border-bottom:1px solid transparent;padding:2px;min-height:20px;color:var(--dsw-alias-label-secondary,inherit);font:inherit;outline:none;min-width:0;transition:color .12s,border-color .12s}',\n '.dsgc-topic:hover{border-bottom-color:var(--dsw-alias-border-l2,rgba(128,128,128,.3))}',\n '.dsgc-topic:focus{color:var(--dsw-alias-label-primary,inherit);border-bottom-color:var(--dsw-alias-state-business-primary,#4f6ef7)}',\n '.dsgc-topic::placeholder{color:var(--dsw-alias-label-tertiary,inherit)}',\n /* 清空按钮:破坏性操作的 hover/active 反馈——宿主 ghost hover 是低强度灰底(在本\n 面板底色上近透明、无感知),改为 danger 色文字 + 淡红底,与弹窗内 danger 确认\n 按钮同语言;特异性高于原语 .ghost:hover:not(:disabled) */\n '.dsgc-chathead .dsgc-clearbtn{transition:background-color .12s,color .12s}',\n '.dsgc-chathead .dsgc-clearbtn:hover:not(:disabled){background:color-mix(in srgb,var(--dsw-alias-state-error-primary,#e5484d) 10%,transparent);color:var(--dsw-alias-state-error-primary,#e5484d)}',\n '.dsgc-chathead .dsgc-clearbtn:active:not(:disabled){background:color-mix(in srgb,var(--dsw-alias-state-error-primary,#e5484d) 16%,transparent)}',\n '.dsgc-msgs{flex:1;overflow-y:auto;padding:20px 24px 16px;display:flex;flex-direction:column;gap:16px;min-height:0;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent}',\n '.dsgc-msg{display:flex;gap:10px;align-items:flex-start;max-width:100%;animation:dsgc-msg-in .22s cubic-bezier(.16,1,.3,1)}',\n '.dsgc-msg.mine{flex-direction:row-reverse}',\n '.dsgc-avatar{width:28px;height:28px;box-sizing:border-box;border:2px solid var(--dsw-alias-border-l3,rgba(128,128,128,.4));border-radius:50%;background:var(--dsw-alias-bg-module-platform,rgba(128,128,128,.12));color:var(--dsw-alias-label-primary,inherit);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:600;flex:none;margin-top:1px}',\n '.dsgc-avatar.mine{border-color:transparent;background:var(--dsw-alias-button-info-fill,#4f6ef7);color:var(--dsw-alias-label-primary-foreground,#fff)}',\n '.dsgc-msgbody{max-width:76%;min-width:0;display:flex;flex-direction:column;gap:5px}',\n '.dsgc-msg.mine .dsgc-msgbody{align-items:flex-end}',\n '.dsgc-msghead{display:flex;gap:6px;align-items:center;min-width:0;font-size:12px;color:var(--dsw-alias-label-secondary,inherit)}',\n '.dsgc-msgname{font-weight:600;color:var(--dsw-alias-label-primary,inherit);white-space:nowrap}',\n '.dsgc-msgmodel{background:var(--dsw-alias-bg-module-platform,rgba(128,128,128,.12));border-radius:999px;padding:0 7px;font-size:10.5px;font-weight:500;line-height:16px;color:var(--dsw-alias-label-secondary,inherit);white-space:nowrap;max-width:100%;overflow:hidden;text-overflow:ellipsis}',\n '.dsgc-msgtime{font-size:10.5px;color:var(--dsw-alias-label-tertiary,inherit);white-space:nowrap}',\n /* 流式「深度求索...」(对标宿主 TurnStatus「深度求索中...」签名动画):DeepSeek\n 品牌蓝渐变带扫过文字的微光——background-clip:text + background-position\n 1.8s linear 无限扫动;令牌取宿主静态品牌色 --dsw-static-deepseek-*(非主题\n 别名,回退为品牌字面值),贯穿首轮 token 前与流式全程 */\n '.dsgc-typing{background:linear-gradient(90deg,var(--dsw-static-deepseek-500,#4176e6) 0%,var(--dsw-static-deepseek-500,#4176e6) 40%,var(--dsw-static-deepseek-200,#d3e2ff) 50%,var(--dsw-static-deepseek-500,#4176e6) 60%,var(--dsw-static-deepseek-500,#4176e6) 100%);color:#0000;-webkit-text-fill-color:transparent;background-position:100% 0;background-size:250% 100%;-webkit-background-clip:text;background-clip:text;font-weight:600;animation:dsgc-typing-shimmer 1.2s linear infinite}',\n '@keyframes dsgc-typing-shimmer{to{background-position:0 0}}',\n '.dsgc-msgtext{background:var(--dsw-alias-bg-layer-3,rgba(128,128,128,.06));border:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.15));padding:10px 14px;border-radius:12px;line-height:1.6;text-align:left;color:var(--dsw-alias-label-primary,inherit);min-width:0;overflow-wrap:anywhere}',\n '.dsgc-msg.mine .dsgc-msgtext{background:var(--dsw-alias-button-info-fill,#4f6ef7);border-color:transparent;color:var(--dsw-alias-label-primary-foreground,#fff);white-space:pre-wrap;word-break:break-word}',\n '.dsgc-msgtext.live{opacity:.92}',\n '.dsgc-msg.live .dsgc-avatar{--presence-ring:color-mix(in srgb,var(--role-color,#4f6ef7) 22%,transparent);animation:dsgc-presence 1.8s ease-in-out infinite}',\n '.dsgc-think{margin:2px 0}',\n '.dsgc-think .dsgc-thinkrow{font-size:12px;color:var(--dsw-alias-label-secondary,inherit);border-radius:8px;padding:3px 8px;transition:background-color .12s}',\n '.dsgc-think .dsgc-thinkrow:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.1))}',\n '.dsgc-think .dsgc-thinksummary{color:var(--dsw-alias-label-tertiary,inherit);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:44ch;font-size:11.5px;margin-left:6px}',\n '.dsgc-think .dsgc-thinkbody{font-size:12.5px;line-height:1.7;color:var(--dsw-alias-label-secondary,inherit);white-space:pre-wrap;word-break:break-word;border-left:2px solid var(--dsw-alias-border-l2,rgba(128,128,128,.25));margin:2px 0 4px;padding:2px 0 2px 10px;max-height:320px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent;animation:dsgc-think-in .2s ease-out}',\n /* 首 delta 前的「思考中」占位行:ThinkRow 同语言(思考图标 + 次要色 12px 小字)\n + 三点交错呼吸动画——深度思考模型首字节可能等数秒到数十秒,空白气泡会被\n 感知为卡死;delta 到达后被真实思考行/正文自然替换 */\n '.dsgc-pending{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--dsw-alias-label-secondary,inherit)}',\n '.dsgc-pending svg{flex:none}',\n '.dsgc-pendingdots{display:inline-flex;gap:2px;align-items:center}',\n '.dsgc-pendingdots i{width:3px;height:3px;border-radius:50%;background:currentColor;opacity:.3;animation:dsgc-dot-breathe 1.2s ease-in-out infinite}',\n '.dsgc-pendingdots i:nth-child(2){animation-delay:.2s}',\n '.dsgc-pendingdots i:nth-child(3){animation-delay:.4s}',\n '@keyframes dsgc-dot-breathe{0%,100%{opacity:.25}50%{opacity:1}}',\n '.dsgc-sysmsg{align-self:center;font-size:11.5px;color:var(--dsw-alias-label-secondary,inherit);background:var(--dsw-alias-bg-module-platform,rgba(128,128,128,.1));border-radius:999px;padding:2px 10px;text-align:center;max-width:90%;animation:dsgc-sys-in .24s ease-out}',\n /* ===== 工具调用行 / 确认卡片(对标思考折叠语言) ===== */\n '.dsgc-tool{margin:2px 0}',\n '.dsgc-tool .dsgc-toolrow{font-size:12px;color:var(--dsw-alias-label-secondary,inherit);border-radius:8px;padding:3px 8px;transition:background-color .12s}',\n '.dsgc-tool .dsgc-toolrow:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.1))}',\n '.dsgc-tool .dsgc-toolsummary{color:var(--dsw-alias-label-tertiary,inherit);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:40ch;font-size:11.5px;margin-left:6px}',\n '.dsgc-tool .dsgc-toolbody{font-size:12px;line-height:1.6;color:var(--dsw-alias-label-secondary,inherit);white-space:pre-wrap;word-break:break-word;border-left:2px solid var(--dsw-alias-border-l2,rgba(128,128,128,.25));margin:2px 0 4px;padding:2px 0 2px 10px;max-height:260px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent}',\n '.dsgc-confirm{border:1px solid var(--dsw-alias-state-business-primary,#4f6ef7);border-radius:12px;background:var(--dsw-alias-bg-layer-3,rgba(128,128,128,.06));padding:10px 12px;display:flex;flex-direction:column;gap:8px;max-width:76%;animation:dsgc-fade-in .18s ease-out}',\n '.dsgc-confirmtitle{font-size:12px;font-weight:600;color:var(--dsw-alias-label-primary,inherit);display:flex;align-items:center;gap:6px}',\n '.dsgc-confirmcmd{font-size:12px;line-height:1.6;white-space:pre-wrap;word-break:break-word;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));border-radius:8px;padding:8px 10px;background:var(--dsw-alias-bg-layer-2,transparent);color:var(--dsw-alias-label-primary,inherit);max-height:240px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent}',\n '.dsgc-confirmops{display:flex;gap:8px;justify-content:flex-end}',\n '.dsgc-sysmsg.err{color:var(--dsw-alias-state-error-primary,#e5484d)}',\n /* 清空确认弹窗内的说明列表 */\n '.dsgc-clearnotes{margin:0;padding-left:18px;font-size:13px;line-height:1.8;color:var(--dsw-alias-label-secondary,inherit);display:flex;flex-direction:column;gap:2px}',\n '.dsgc-err{font-size:12px;color:var(--dsw-alias-state-error-primary,#e5484d);animation:dsgc-fade-in .18s ease-out}',\n '.dsgc-empty{margin:auto;display:flex;flex-direction:column;align-items:center;gap:10px;color:var(--dsw-alias-label-tertiary,inherit);text-align:center;max-width:40ch;padding:24px;animation:dsgc-fade-in .3s ease-out}',\n '.dsgc-empty svg{opacity:.5}',\n '.dsgc-empty .dsgc-emptytitle{font-size:13px;font-weight:600;color:var(--dsw-alias-label-secondary,inherit)}',\n '.dsgc-empty .dsgc-hint{text-wrap:balance}',\n '.dsgc-tobottom{position:absolute;bottom:calc(100% + 8px);left:50%;transform:translateX(-50%);z-index:12;animation:dsgc-rise-in .18s cubic-bezier(.16,1,.3,1)}',\n /* 回到底部:实底浮动胶囊(@弹层同款浮层配方——实底 + border-l2 + shadow-lv3),不与消息内容相互透底 */\n '.dsgc-tobtn{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));background:var(--dsw-alias-bg-layer-3,#fff);color:var(--dsw-alias-label-secondary,inherit);border-radius:999px;padding:5px 12px;font:inherit;font-size:12px;line-height:1.4;cursor:pointer;box-shadow:var(--dsw-shadow-lv3,0 8px 24px rgba(0,0,0,.18));transition:color .12s,border-color .12s}',\n '.dsgc-tobtn:hover{color:var(--dsw-alias-label-primary,inherit);border-color:var(--dsw-alias-border-l3,rgba(128,128,128,.4))}',\n /* ===== composer ===== */\n '.dsgc-composer{padding:12px 16px 14px;display:flex;flex-direction:column;gap:10px;position:relative}',\n /* 输入卡(对标主会话 composer 卡):22px 圆角独立卡、input-major 实底、\n elevation-soft 软影(DESIGN.md 输入面豁免——输入面遵循宿主输入面语言,\n 其余静止表面仍零阴影);chips 等配置行留卡外 */\n '.dsgc-card{background:var(--dsw-specific-input-major,var(--dsw-alias-bg-layer-3,transparent));--dsw-elevation-stroke-color:var(--dsw-alias-border-l2,rgba(128,128,128,.3));box-shadow:var(--dsw-elevation-soft,0 1px 3px rgba(0,0,0,.08));border-radius:22px;padding:8px 0 0;display:flex;flex-direction:column;gap:8px;position:relative}',\n /* 输入区:非受控 contenteditable(React 不管子节点);白空间与换行规则\n 与序列化契约对齐(pre-wrap + <br>→\\n) */\n '.dsgc-edit{display:block;box-sizing:border-box;width:100%;min-height:36px;max-height:180px;overflow-y:auto;outline:none;white-space:pre-wrap;word-break:break-word;overflow-wrap:anywhere;font:inherit;font-size:13px;line-height:24px;color:var(--dsw-alias-label-primary,inherit);caret-color:var(--dsw-alias-state-business-primary,#4f6ef7);scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent;position:relative;z-index:1}',\n '.dsgc-card .dsgc-edit{padding:6px 8px 0 14px}',\n /* 占位符 = 独立覆盖层(对齐主会话):不用 ::before——生成内容会把聚焦光标\n 顶到占位文字之后;覆盖层 pointer-events:none 不参与光标布局,\n 与输入区同 padding 基准(左 14 / 上 6) */\n '.dsgc-ph{position:absolute;left:14px;top:6px;max-width:calc(100% - 22px);color:var(--dsw-alias-label-tertiary,inherit);pointer-events:none;user-select:none;font-size:13px;line-height:24px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}',\n /* @提及芯片(输入区内原子元素):色点 + 角色色淡底胶囊——弹层候选行同语言 */\n '.dsgc-chipin{display:inline-flex;align-items:center;gap:4px;background:color-mix(in srgb,var(--role-color,#888) 15%,transparent);border-radius:999px;padding:1px 7px 1px 5px;margin:0 1px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-primary,inherit);white-space:nowrap;user-select:all}',\n '.dsgc-card .dsgc-sendrow{padding:0 12px 10px}',\n '.dsgc-stopbtn{background:var(--dsw-alias-state-error-primary,#e5484d);border-color:transparent;color:#fff;font-weight:600}',\n '.dsgc-stopbtn:hover:not(:disabled){filter:brightness(1.08);color:#fff}',\n '.dsgc-parts{display:flex;gap:6px;flex-wrap:wrap;align-items:center;row-gap:4px;height:24px}',\n '.dsgc-partslabel{font-size:12px;color:var(--dsw-alias-label-tertiary,inherit);flex:none}',\n '.dsgc-partchip{display:inline-flex;gap:6px;align-items:center;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));background:transparent;color:var(--dsw-alias-label-secondary,inherit);border-radius:999px;padding:2px 10px;font-size:12px;line-height:1.5;cursor:pointer;transition:background-color .12s,color .12s,border-color .12s;font-family:inherit}',\n '.dsgc-partchip:hover{color:var(--dsw-alias-label-primary,inherit)}',\n '.dsgc-partchip.on{background:var(--dsw-alias-interactive-bg-active,rgba(128,128,128,.18));color:var(--dsw-alias-label-primary,inherit);border-color:var(--dsw-alias-border-l2,rgba(128,128,128,.3))}',\n '.dsgc-partchip:disabled{opacity:.5;cursor:default}',\n '.dsgc-chipdot{width:8px;height:8px;border-radius:50%;flex:none;display:inline-block}',\n '.dsgc-sendrow{display:flex;gap:8px;align-items:center;justify-content:flex-end}',\n '.dsgc-sendrow button{white-space:nowrap}',\n /* ===== 权限档位选择器(对齐主会话 composer 左下角芯片) ===== */\n '.dsgc-permtrigger{min-width:0;max-width:220px;height:28px;color:var(--dsw-alias-label-secondary,inherit);cursor:pointer;background:transparent;border:none;border-radius:999px;outline:none;align-items:center;gap:4px;padding:0 4px 0 8px;font-size:13px;font-weight:500;line-height:20px;display:inline-flex;font-family:inherit;transition:background-color .12s,color .12s}',\n '.dsgc-permtrigger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.15));color:var(--dsw-alias-label-primary,inherit)}',\n '.dsgc-permtrigger:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3,rgba(128,128,128,.4))}',\n '.dsgc-permtrigger:disabled{color:var(--dsw-alias-label-dimmed,inherit);cursor:default}',\n '.dsgc-permicon{flex:none;display:inline-flex}',\n '.dsgc-permicon svg{width:14px;height:14px}',\n '.dsgc-permlabel{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}',\n '.dsgc-permchevron{color:var(--dsw-alias-label-caption,inherit);flex:none;transition:transform .12s;display:inline-flex}',\n '.dsgc-permchevron.open{transform:rotate(180deg)}',\n '.dsgc-rounds{display:flex;gap:2px;align-items:center;font-size:12px;color:var(--dsw-alias-label-secondary,inherit);flex:none;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));border-radius:8px;padding:2px}',\n '.dsgc-rounds .dsgc-roundbtn{border:none;background:none;color:var(--dsw-alias-label-secondary,inherit);cursor:pointer;padding:3px;border-radius:5px;line-height:0;transition:background-color .12s,color .12s}',\n '.dsgc-rounds .dsgc-roundbtn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.15));color:var(--dsw-alias-label-primary,inherit)}',\n '.dsgc-rounds .dsgc-roundbtn:disabled{opacity:.4;cursor:default}',\n '.dsgc-rounds .dsgc-roundnum{width:26px;text-align:center;font-variant-numeric:tabular-nums;font-weight:600;color:var(--dsw-alias-label-primary,inherit)}',\n /* ===== @成员 / @文件弹层 ===== */\n '.dsgc-mentionwrap{position:relative}',\n '.dsgc-mention{animation:dsgc-pop-in .16s cubic-bezier(.16,1,.3,1);position:absolute;left:0;right:0;bottom:calc(100% + 6px);background:var(--dsw-alias-bg-layer-3,#fff);border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));border-radius:10px;box-shadow:var(--dsw-shadow-lv3,0 8px 24px rgba(0,0,0,.18));max-height:220px;overflow-y:auto;padding:4px;z-index:30;display:flex;flex-direction:column;gap:2px;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent}',\n '.dsgc-mentionitem{display:flex;align-items:center;gap:8px;border:none;background:none;color:var(--dsw-alias-label-secondary,inherit);font:inherit;font-size:12.5px;text-align:left;cursor:pointer;padding:6px 8px;border-radius:6px;transition:background-color .12s,color .12s}',\n '.dsgc-mentionitem.on,.dsgc-mentionitem:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.15));color:var(--dsw-alias-label-primary,inherit)}',\n '.dsgc-mentionname{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:500}',\n '.dsgc-mentionmodel{font-size:11px;color:var(--dsw-alias-label-tertiary,inherit)}',\n '.dsgc-mentionhint{font-size:11px;color:var(--dsw-alias-label-tertiary,inherit);padding:2px 8px 1px}',\n '.dsgc-mention-file .dsgc-mentionitem.dsgc-hint{cursor:default;color:var(--dsw-alias-label-tertiary,inherit);justify-content:center}',\n '.dsgc-mention-file .dsgc-mentionitem.dsgc-hint:hover{background:none}',\n /* 文件检索:宿主 FileTypeIcon 分色字形 + 井位底,文件夹/文件扫一眼可分 */\n '.dsgc-fileglyph{flex:none;width:22px;height:22px;display:inline-flex;align-items:center;justify-content:center;border-radius:5px}',\n '.dsgc-fileglyph.dir{background:color-mix(in srgb,var(--dsw-static-amber-400,#e8912d) 16%,transparent)}',\n '.dsgc-fileglyph.file{background:var(--dsw-alias-bg-module-platform,rgba(128,128,128,.12))}',\n '.dsgc-filedrill{flex:none;display:inline-flex;color:var(--dsw-alias-label-tertiary,inherit)}',\n '.dsgc-mentionitem.on .dsgc-filedrill,.dsgc-mentionitem:hover .dsgc-filedrill{color:var(--dsw-alias-label-secondary,inherit)}',\n '.dsgc-chipin-file{background:color-mix(in srgb,var(--dsw-static-neutral-bluish-300,rgba(128,128,128,.55)) 18%,transparent)}',\n '.dsgc-chipin-file[data-dir=\"1\"]{background:color-mix(in srgb,var(--dsw-static-amber-400,#e8912d) 18%,transparent)}',\n '.dsgc-chipglyph{flex:none;width:14px;height:14px;display:inline-flex;align-items:center;justify-content:center;overflow:hidden}',\n '.dsgc-chipglyph svg{display:block}',\n /* ===== 右上下文栏 ===== */\n '.dsgc-aside{width:304px;flex:none;display:flex;flex-direction:column;gap:10px;border-left:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.2));padding:12px;min-height:0;overflow-y:auto;overflow-x:hidden;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent;transition:width .28s cubic-bezier(.16,1,.3,1),opacity .18s ease,padding .28s cubic-bezier(.16,1,.3,1),border-left-width .28s cubic-bezier(.16,1,.3,1)}',\n /* 子元素经 flex 列默认 stretch 填满内容区(面板为 content-box、内容区实宽\n 304px;旧版写死 280px 曾致右侧多出 24px 死区) */\n '.dsgc-aside>*{flex:none}',\n '.dsgc-aside.closed{width:0;opacity:0;padding-left:0;padding-right:0;border-left-width:0;visibility:hidden;transition:width .24s ease-in,opacity .16s ease-in,padding .24s ease-in,border-left-width .24s ease-in,visibility 0s .22s}',\n '.dsgc-sec{display:flex;flex-direction:column;gap:8px;flex:none}',\n '.dsgc-sechead{display:flex;align-items:center;gap:6px;font-weight:600;font-size:12px;color:var(--dsw-alias-label-tertiary,inherit);padding-top:2px}',\n '.dsgc-sechead .dsgc-secspacer{flex:1}',\n '.dsgc-seccount{font-weight:500;color:var(--dsw-alias-label-tertiary,inherit)}',\n '.dsgc-roles{display:flex;flex-direction:column;gap:8px}',\n '.dsgc-role{border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));background:var(--dsw-alias-bg-layer-3,transparent);border-radius:12px;padding:10px 12px;display:flex;flex-direction:column;gap:7px;transition:border-color .16s,background-color .16s;list-style:none;text-align:left;font:inherit;cursor:pointer;color:inherit}',\n '.dsgc-role:hover{border-color:var(--dsw-alias-label-dimmed,rgba(128,128,128,.5))}',\n '.dsgc-rolehead{display:flex;gap:8px;align-items:center}',\n '.dsgc-roledot{width:10px;height:10px;border-radius:50%;flex:none}',\n '.dsgc-rolename{font-weight:600;font-size:13px;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-primary,inherit)}',\n '.dsgc-role.off .dsgc-rolename{color:var(--dsw-alias-label-tertiary,inherit)}',\n '.dsgc-rolepersona{font-size:11.5px;color:var(--dsw-alias-label-tertiary,inherit);line-height:1.5;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;min-height:0}',\n '.dsgc-rolemodel{width:fit-content;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;background:var(--dsw-alias-bg-module-platform,rgba(128,128,128,.12));border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px;color:var(--dsw-alias-label-secondary,inherit)}',\n '.dsgc-roleops{display:flex;gap:2px;flex:none;opacity:0;transition:opacity .12s}',\n '.dsgc-role:hover .dsgc-roleops,.dsgc-role:focus-within .dsgc-roleops{opacity:1}',\n '.dsgc-rolemenu{display:flex;align-items:center;justify-content:space-between;gap:8px}',\n /* ===== 表单与控件(角色抽屉内) ===== */\n '.dsgc-field{display:flex;flex-direction:column;gap:5px}',\n '.dsgc-field>label{font-size:12px;font-weight:500;color:var(--dsw-alias-label-secondary,inherit)}',\n '.dsgc-input,.dsgc-select,.dsgc-textarea{background:var(--dsw-specific-input-major,var(--dsw-alias-bg-layer-3,transparent));border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));color:var(--dsw-alias-label-primary,inherit);font:inherit;font-size:13px;border-radius:8px;padding:6px 10px;width:100%;box-sizing:border-box;outline:none;transition:border-color .16s,background-color .16s}',\n '.dsgc-input:focus,.dsgc-select:focus,.dsgc-textarea:focus{border-color:var(--dsw-alias-state-business-primary,#4f6ef7)}',\n '.dsgc-input::placeholder,.dsgc-textarea::placeholder{color:var(--dsw-alias-label-tertiary,inherit)}',\n '.dsgc-textarea{resize:vertical;min-height:76px}',\n '.dsgc-palette{display:flex;gap:6px;flex-wrap:wrap}',\n '.dsgc-dot{width:18px;height:18px;border-radius:50%;border:2px solid transparent;cursor:pointer;padding:0;transition:transform .12s}',\n '.dsgc-dot:hover{transform:scale(1.12)}',\n '.dsgc-dot.on{border-color:var(--dsw-alias-label-primary,#fff)}',\n '.dsgc-form{display:flex;flex-direction:column;gap:12px}',\n '.dsgc-formerr{font-size:12px;color:var(--dsw-alias-state-error-primary,#e5484d);line-height:1.5}',\n '.dsgc-selhint{font-size:12px;color:var(--dsw-alias-label-tertiary,inherit);line-height:1.5;display:flex;gap:6px;align-items:center;flex-wrap:wrap}',\n /* ===== 角色编辑抽屉(右侧滑出) ===== */\n '.dsgc-drawer{position:absolute;top:0;right:0;bottom:0;width:380px;max-width:calc(100% - 40px);z-index:20;background:var(--dsw-alias-bg-layer-2,var(--dsw-alias-bg-base,#fff));border-left:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));box-shadow:-12px 0 32px rgba(0,0,0,.14);display:flex;flex-direction:column;animation:dsgc-drawer-in .22s cubic-bezier(.16,1,.3,1)}',\n '.dsgc-drawer.closing{animation:dsgc-drawer-out .14s ease-in forwards;pointer-events:none}',\n '@keyframes dsgc-drawer-in{from{transform:translateX(32px);opacity:0}to{transform:none;opacity:1}}',\n '@keyframes dsgc-drawer-out{to{transform:translateX(32px);opacity:0}}',\n '@keyframes dsgc-msg-in{from{opacity:0;transform:translateY(6px)}}',\n '@keyframes dsgc-sys-in{from{opacity:0;transform:scale(.96)}}',\n '@keyframes dsgc-think-in{from{opacity:0;transform:translateY(-3px)}}',\n '@keyframes dsgc-pop-in{from{opacity:0;transform:translateY(4px)}}',\n '@keyframes dsgc-rise-in{from{opacity:0;transform:translate(-50%,6px)}}',\n '@keyframes dsgc-fade-in{from{opacity:0}}',\n '@keyframes dsgc-presence{0%,100%{box-shadow:0 0 0 0 color-mix(in srgb,var(--role-color,#4f6ef7) 0%,transparent)}50%{box-shadow:0 0 0 4px var(--presence-ring)}}',\n '.dsgc-drawerhead{display:flex;align-items:center;gap:8px;padding:14px 16px;border-bottom:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.2));flex:none}',\n '.dsgc-drawertitle{flex:1;font-size:14px;font-weight:600;color:var(--dsw-alias-label-primary,inherit)}',\n '.dsgc-drawerbody{flex:1;overflow-y:auto;padding:16px;min-height:0;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent}',\n '.dsgc-drawerfoot{display:flex;gap:8px;justify-content:flex-end;padding:12px 16px;border-top:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.2));flex:none}',\n /* ===== 文件浏览器(目录选择) ===== */\n '.dsgc-fb{border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));background:var(--dsw-alias-bg-layer-2,transparent);border-radius:8px;display:flex;flex-direction:column;gap:6px;padding:8px;animation:dsgc-fade-in .2s ease-out}',\n '.dsgc-fbhead{display:flex;align-items:center;justify-content:space-between;gap:8px;min-width:0}',\n '.dsgc-fbhead button{flex:none;white-space:nowrap}',\n '.dsgc-wsrow{display:flex;gap:6px;align-items:center;min-width:0}',\n '.dsgc-wsrow .dsgc-input{width:auto;flex:1;min-width:0}',\n '.dsgc-wsrow>button{flex:none;white-space:nowrap}',\n '.dsgc-nav>button{white-space:nowrap;overflow:hidden}',\n '.dsgc-fbpath{flex:1;min-width:0;font-size:11px;color:var(--dsw-alias-label-secondary,inherit);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',\n '.dsgc-fblist{display:flex;flex-direction:column;gap:1px;max-height:220px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,rgba(128,128,128,.35)) transparent}',\n '.dsgc-fbrow{display:flex;align-items:center;gap:7px;width:100%;border:none;background:none;color:var(--dsw-alias-label-primary,inherit);font:inherit;font-size:12.5px;text-align:left;cursor:pointer;padding:3px 8px;border-radius:6px;transition:background-color .12s}',\n '.dsgc-fbrow:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.15))}',\n '.dsgc-fbrow.dim{opacity:.55}',\n '.dsgc-fbrow.file{cursor:default}',\n '.dsgc-fbrow.file:hover{background:none}',\n '.dsgc-fbname{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',\n '.dsgc-fbsize{flex:none;font-size:10.5px;color:var(--dsw-alias-label-tertiary,inherit)}',\n /* ===== 键盘焦点 ===== */\n '.dsgc-partchip:focus-visible,.dsgc-mentionitem:focus-visible,.dsgc-dot:focus-visible,.dsgc-opbtn:focus-visible,.dsgc-twist:focus-visible,.dsgc-addsess:focus-visible,.dsgc-grow-row:focus-visible,.dsgc-sess-row:focus-visible,.dsgc-rename:focus-visible,.dsgc-fbrow:focus-visible,.dsgc-role:focus-visible,.dsgc-roundbtn:focus-visible,.dsgc-tobtn:focus-visible,.dsgc-seambtn:focus-visible{outline:2px solid var(--dsw-alias-brand-primary,var(--dsw-alias-state-business-primary,#4f6ef7));outline-offset:1px}',\n /* ===== 窄容器:右栏覆盖式呈现 ===== */\n '@container (max-width: 880px){.dsgc-aside{position:absolute;top:0;right:0;bottom:0;z-index:15;width:min(304px,88%);box-shadow:-12px 0 32px rgba(0,0,0,.16);border-left:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));transition:transform .3s cubic-bezier(.16,1,.3,1),opacity .2s ease}.dsgc-aside.closed{width:min(304px,88%);padding-left:12px;padding-right:12px;border-left-width:1px;transform:translateX(calc(100% + 14px));opacity:0;transition:transform .26s ease-in,opacity .18s ease-in,visibility 0s .24s}.dsgc-seambtn.right:not(.closed){right:min(304px,88%)}}',\n '@container (max-width: 640px){.dsgc-nav{width:200px}.dsgc-msgbody{max-width:88%}}',\n /* ===== 侧边栏入口对齐(外壳将插槽内容包在 panelGlyph span 内,必须用后代 :has) ===== */\n '[class*=\"panelList\"]:has(.dsgc-entryOverlay){margin-top:4px}',\n '[class*=\"panelRow\"]:has(.dsgc-entryOverlay){position:relative;box-sizing:border-box;height:36px;min-height:36px;padding:0 10px;font-size:13px;transition:background-color .12s,color .12s}',\n '[class*=\"panelRow\"][class*=\"panelActive\"]:has(.dsgc-entryOverlay){font-weight:600}',\n /* 入口 hover:宿主 panelRow:hover 只给灰底、不变文字色(低强度到近无感);\n 对齐任务看板入口行——hover 灰底 + 文字/图标转 label-primary */\n '[class*=\"panelRow\"]:has(.dsgc-entryOverlay):hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.12));color:var(--dsw-alias-label-primary,inherit)}',\n /* DOM 注入式全幅视图(任务看板 data-dsh-taskboard-active / SSH data-dsh-ssh-active)\n 激活时接管中央列:外壳面板状态机未变(activePanelId 仍指向群聊),但视图已被\n 覆盖——群聊入口随之视觉复位,避免停留“激活”态误导当前所在视图。两行特异性\n 相同(0,4,1),hover 行在后,复位不吞 hover 反馈 */\n 'html[data-dsh-taskboard-active] [class*=\"panelRow\"][class*=\"panelActive\"]:has(.dsgc-entryOverlay),html[data-dsh-ssh-active] [class*=\"panelRow\"][class*=\"panelActive\"]:has(.dsgc-entryOverlay){background:transparent;color:var(--dsw-alias-label-secondary,inherit);font-weight:400}',\n 'html[data-dsh-taskboard-active] [class*=\"panelRow\"]:has(.dsgc-entryOverlay):hover,html[data-dsh-ssh-active] [class*=\"panelRow\"]:has(.dsgc-entryOverlay):hover{background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.12));color:var(--dsw-alias-label-primary,inherit)}',\n /* 收起态例外:外壳把收起栏所有面板图标统一为 primary 色(激活与否不由颜色表达),\n 复位规则不得把群聊图标调暗成 secondary;仅去掉激活底色即可 */\n 'html[data-dsh-taskboard-active] [data-sidebar-collapsed] [class*=\"panelRow\"]:has(.dsgc-entryOverlay),html[data-dsh-ssh-active] [data-sidebar-collapsed] [class*=\"panelRow\"]:has(.dsgc-entryOverlay),html[data-dsh-taskboard-active] [class*=\"collapsed\"] [class*=\"panelRow\"]:has(.dsgc-entryOverlay),html[data-dsh-ssh-active] [class*=\"collapsed\"] [class*=\"panelRow\"]:has(.dsgc-entryOverlay){color:var(--dsw-alias-label-primary,inherit)}',\n '[class*=\"panelRow\"]:has(.dsgc-entryOverlay) > [class*=\"panelTitle\"]{padding-left:24px}',\n '.dsgc-entryOverlay{position:absolute;inset:0;display:flex;align-items:center;padding:0 10px;box-sizing:border-box}',\n '.dsgc-entryIcon{flex:none;width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center}',\n '.dsgc-entryIcon svg{width:18px;height:18px;display:block}',\n '[data-sidebar-collapsed] .dsgc-entryOverlay,[class*=\"collapsed\"] .dsgc-entryOverlay{justify-content:center;padding:0}',\n '[data-sidebar-collapsed] [class*=\"panelRow\"]:has(.dsgc-entryOverlay),[class*=\"collapsed\"] [class*=\"panelRow\"]:has(.dsgc-entryOverlay){margin:0 auto}',\n '@media (prefers-reduced-motion:reduce){.dsgc-dot,.dsgc-partchip,.dsgc-mentionitem,.dsgc-grow-row,.dsgc-sess-row,.dsgc-opbtn,.dsgc-addsess,.dsgc-topic,.dsgc-role,.dsgc-rename,.dsgc-input,.dsgc-select,.dsgc-textarea,.dsgc-fbrow,.dsgc-twist svg,.dsgc-roleops,.dsgc-roundbtn,.dsgc-permtrigger,.dsgc-permchevron,.dsgc-tobtn,.dsgc-seambtn,.dsgc-aside,.dsgc-aside.closed,.dsgc-nav,.dsgc-nav.closed,.dsgc-clearbtn,[class*=\"panelRow\"]:has(.dsgc-entryOverlay){transition:none}.dsgc-dot:hover{transform:none}.dsgc-drawer,.dsgc-msg,.dsgc-sysmsg,.dsgc-mention,.dsgc-tobottom,.dsgc-err,.dsgc-empty,.dsgc-fb,.dsgc-think .dsgc-thinkbody,.dsgc-msg.live .dsgc-avatar,.dsgc-loading svg,.dsgc-pendingdots i,.dsgc-typing{animation:none}.dsgc-typing{background-position:0 0;background-size:100% 100%}}',\n /* ===== 设置页(同一卡片语言) ===== */\n '.dgcs-page{display:flex;flex-direction:column;gap:14px;padding:4px 0}',\n '.dgcs-head{display:flex;flex-direction:column;gap:6px}',\n '.dgcs-title{margin:0;font-size:15px;font-weight:600;line-height:1.4;color:var(--dsw-alias-label-primary,inherit)}',\n '.dgcs-desc{margin:0;font-size:13px;line-height:1.6;color:var(--dsw-alias-label-secondary,inherit)}',\n '.dgcs-card{display:flex;align-items:center;justify-content:space-between;gap:12px;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3));background:var(--dsw-alias-bg-layer-3,transparent);border-radius:12px;padding:14px 16px;transition:border-color .16s}',\n '.dgcs-cardtext{display:flex;flex-direction:column;gap:3px;min-width:0}',\n '.dgcs-cardtitle{font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary,inherit)}',\n '.dgcs-cardhint{font-size:12px;color:var(--dsw-alias-label-tertiary,inherit)}',\n].join('\\n')\n\n/** 工厂执行时幂等注入样式标签(loader 卸载时按 data-plugin 摘除)。 */\nexport function injectStyles(): void {\n if (typeof document === 'undefined') return\n if (document.querySelector('style[data-plugin-css=' + JSON.stringify(TAG_ID) + ']') === null) {\n const tag = document.createElement('style')\n tag.dataset.plugin = '@roaming-ai/dsh-group-chat'\n tag.dataset.pluginCss = TAG_ID\n tag.textContent = CSS\n document.head.appendChild(tag)\n }\n}\n","/**\n * 浏览器半 UI 基座:DSW 原语(shell 静态种子模块,loader 模块表 external)\n * 与动态图标 / 命令式 createElement 辅助。组件主体已 JSX 化(.tsx);此处\n * 仅保留 slot 注册回调与动态图标表需要的少量命令式辅助。\n * @module dsh-group-chat/client/ui\n */\n\nimport { createElement, type ReactNode } from 'react'\nimport * as P from '@deepseek-ai/dsh-client-ui-primitives'\n\nexport { P }\n\n/** 命令式 createElement(仅 slot 注册回调用)。 */\nexport const h = createElement as unknown as (type: unknown, props?: Record<string, unknown> | null, ...children: unknown[]) => ReactNode\n\n/** 图标组件的调用形态。 */\nexport type IconComponent = (props: Record<string, unknown>) => ReactNode\n\n/** 按名取 DSW 原语(图标表驱动)。 */\nexport function pickPrimitive(name: string): IconComponent {\n return (P as unknown as Record<string, IconComponent>)[name]\n}\n\n/** 以统一 size 包装图标组件调用(放在 JSX 子元素位)。 */\nexport function Icon(comp: unknown, size: number, extra?: Record<string, unknown>): ReactNode {\n return h(comp as never, Object.assign({ size }, extra || {}))\n}\n","/**\n * 会话状态派生(纯函数):从快照 run 派生单个会话的列表状态,\n * 语义对齐 DSH 主会话列表(StateDot 五态取四)。\n *\n * 优先级:等待确认 > 进行中 > 已完成/已出错 > 默认(无点)。\n * - ongoing:run 进行中(含用户已点停止但未停完的 stopping 窗口)\n * - warning:run_command 确认闸门挂起(仅工作区内修改档)\n * - done/error:run 结束后的「输出完毕」标记(正常/停止 → done,发言失败 → error)\n * - idle:无任何活动(不渲染状态点,对齐主 GUI idle 隐藏)\n * @module dsh-group-chat/core/status\n */\n\nimport type { Snapshot } from './types.ts'\n\n/** 会话列表状态(取值即 StateDotState 的渲染态)。 */\nexport type SessStatus = 'idle' | 'ongoing' | 'warning' | 'done' | 'error'\n\n/** 状态点悬停/读屏文案(idle 不渲染点,无文案)。 */\nexport const SESS_STATUS_LABEL: Record<SessStatus, string> = {\n idle: '',\n ongoing: '进行中',\n warning: '等待确认',\n done: '已完成',\n error: '已出错',\n}\n\n/** 派生单个会话的列表状态(run 为快照的 run 视图)。 */\nexport function sessStatus(run: Snapshot['run'], sessionId: string): SessStatus {\n if (run.running && run.sessionId === sessionId) return run.pendingConfirm ? 'warning' : 'ongoing'\n const f = run.finished\n if (f && f.sessionId === sessionId) return f.reason === 'error' ? 'error' : 'done'\n return 'idle'\n}\n","/**\n * 浏览器半共享常量与小工具(纯函数,无 React 依赖)。\n * @module dsh-group-chat/client/model\n */\n\nimport type { RoleRecord, Snapshot, ToolCallRecord } from '../../core/types.ts'\n\n/** 会话列表状态派生与文案(core 纯函数,供 NavPanel 渲染)。 */\nexport { sessStatus, SESS_STATUS_LABEL, type SessStatus } from '../../core/status.ts'\n\n/** 角色标识色调色板(与宿主半一致)。 */\nexport const PALETTE = ['#5b8def', '#22a06b', '#e8912d', '#c678dd', '#e05661', '#56b6c2', '#98c379', '#d19a66']\n\n/** Host HTTP API 前缀。 */\nexport const API_PREFIX = '/api/group-chat'\n\n/** MarkdownText 渲染文案。 */\nexport const MD_LABELS = Object.freeze({ code: { copyLabel: '复制', copiedLabel: '已复制' }, footnotes: '脚注' })\n\n/** 快照的 wire 形态(响应里带 ok 标记)。 */\nexport type ClientSnapshot = Snapshot & { ok: boolean }\n\n/** models action 的响应形态。 */\nexport interface ModelsResponse {\n ok: boolean\n providers?: { id: string, name?: string }[]\n modelsByProvider?: Record<string, { id: string, name?: string }[]>\n error?: string\n}\n\n/** efforts action 的响应形态。 */\nexport interface EffortsResponse {\n ok: boolean\n efforts?: { id: string, name: string, description?: string }[]\n defaultEffort?: string\n error?: string\n}\n\n/** 快照内的角色/会话/群组视图行。 */\nexport type SnapshotRole = Snapshot['roles'][number]\nexport type SnapshotSession = Snapshot['sessions'][number]\nexport type SnapshotGroup = Snapshot['groups'][number]\nexport type SnapshotMessage = Snapshot['messages'][number]\n\nexport function roleById(s: ClientSnapshot, id: string | null): SnapshotRole | null {\n for (const r of s.roles) if (r.id === id) return r\n return null\n}\n\nexport function sessById(s: ClientSnapshot, id: string): SnapshotSession | null {\n for (const x of s.sessions) if (x.id === id) return x\n return null\n}\n\nexport function groupById(s: ClientSnapshot, id: string): SnapshotGroup | null {\n for (const g of s.groups) if (g.id === id) return g\n return null\n}\n\nexport function escapeRegExp(v: string): string {\n return String(v).replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\nexport function firstLine(text: string): string {\n const i = text.indexOf('\\n')\n return i === -1 ? text : text.slice(0, i)\n}\n\nexport function latestLine(text: string): string {\n const visible = text.trimEnd()\n const i = visible.lastIndexOf('\\n')\n return i === -1 ? visible : visible.slice(i + 1)\n}\n\nexport function fmtTime(ts: number): string {\n const delta = Math.max(0, Date.now() - ts)\n if (delta < 60000) return '刚刚'\n if (delta < 3600000) return Math.floor(delta / 60000) + ' 分钟前'\n if (delta < 86400000) return Math.floor(delta / 3600000) + ' 小时前'\n const d = new Date(ts)\n const sameYear = d.getFullYear() === new Date().getFullYear()\n const pad = (n: number): string => (n < 10 ? '0' + n : '' + n)\n return sameYear ? (d.getMonth() + 1) + '月' + d.getDate() + '日' : d.getFullYear() + '/' + (d.getMonth() + 1) + '/' + d.getDate()\n}\n\n/** 角色编辑抽屉的草稿形态(编辑与新建共用)。 */\nexport interface RoleDraft {\n id?: string\n name: string\n color: string | null\n persona: string\n provider: string\n model: string\n temperature?: number\n reasoningEffort: string\n enabled?: boolean\n thinking: boolean\n}\n\nexport function draftFromRole(role: SnapshotRole): RoleDraft {\n return { id: role.id, name: role.name, color: role.color ?? null, persona: role.persona, provider: role.provider, model: role.model, temperature: role.temperature, reasoningEffort: role.reasoningEffort || 'default', enabled: role.enabled, thinking: role.thinking === true }\n}\n\nexport function blankDraft(): RoleDraft {\n return { name: '', color: null, persona: '', provider: '', model: '', temperature: undefined, reasoningEffort: 'default', enabled: true, thinking: false }\n}\n\n/** 工具调用行的展示参数。 */\nexport type ToolCallView = ToolCallRecord\n\n/** 草稿是否可作为角色落库(宿主侧再校验一次)。 */\nexport function draftMissing(draft: RoleDraft): string {\n if (!draft.name.trim()) return '角色名称不能为空'\n if (!draft.provider || !draft.model) return '请选择角色绑定的模型'\n return ''\n}\n\n/** RoleRecord 兼容视图(快照角色行即其展示子集)。 */\nexport type RoleView = RoleRecord\n","/**\n * 浏览器半 transport:/api/group-chat/* 同源 JSON 端点。\n * @module dsh-group-chat/client/api\n */\n\nimport { API_PREFIX } from './model.ts'\n\nasync function readJson<T>(fetchPromise: Promise<Response>): Promise<T> {\n const response = await fetchPromise\n const body = await response.json() as { error?: string }\n if (!response.ok) throw new Error(body && body.error ? body.error : '请求失败(HTTP ' + response.status + '),请稍后重试')\n return body as unknown as T\n}\n\nexport const api = {\n state: (): Promise<unknown> => readJson(fetch(API_PREFIX + '/state', { cache: 'no-store' })),\n action: (payload: Record<string, unknown>, signal?: AbortSignal): Promise<unknown> => readJson(fetch(API_PREFIX + '/action', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n signal,\n })),\n}\n","/**\n * 角色编辑抽屉(右侧滑出,不遮挡会话流阅读)。\n * @module dsh-group-chat/client/drawer\n */\n\nimport { useEffect, useState, type ReactNode } from 'react'\nimport { Icon, P } from '../lib/ui.ts'\nimport { api } from '../lib/api.ts'\nimport { PALETTE, type EffortsResponse, type ModelsResponse, type RoleDraft } from '../lib/model.ts'\n\nexport interface RoleDrawerProps {\n draft: RoleDraft\n set: (draft: RoleDraft) => void\n models: ModelsResponse | null\n modelsError: string | null\n onRetryModels: () => void\n onSave: () => void\n onCancel: () => void\n formError: string\n}\n\nexport function RoleDrawer(props: RoleDrawerProps): ReactNode {\n const { draft, set } = props\n const models = props.models\n const providers = (models && models.providers) || []\n const modelsOf = (models && models.modelsByProvider && models.modelsByProvider[draft.provider]) || []\n const [closing, setClosing] = useState(false)\n const [effortsInfo, setEffortsInfo] = useState<EffortsResponse | null>(null)\n const close = (): void => {\n if (closing) return\n setClosing(true)\n window.setTimeout(() => props.onCancel(), 140)\n }\n const onProvider = (e: { target: { value: string } }): void => {\n const p = e.target.value\n const list = (models && models.modelsByProvider && models.modelsByProvider[p]) || []\n // 换模型路线后旧推理级别失效,重置为默认\n set(Object.assign({}, draft, { provider: p, model: list.length ? list[0].id : '', reasoningEffort: 'default' }))\n }\n useEffect(() => {\n const onKey = (e: KeyboardEvent): void => { if (e.key === 'Escape') close() }\n document.addEventListener('keydown', onKey)\n return () => document.removeEventListener('keydown', onKey)\n }, [])\n // 推理级别选项:跟随抽屉内 provider/model 变化重新查询(Host 60s 缓存)\n useEffect(() => {\n let live = true\n setEffortsInfo(null)\n if (!draft.provider || !draft.model) return\n api.action({ kind: 'efforts', provider: draft.provider, model: draft.model }).then((res) => {\n if (!live) return\n const r = res as EffortsResponse\n if (r && r.ok) setEffortsInfo({ ok: true, efforts: r.efforts || [], defaultEffort: r.defaultEffort })\n else setEffortsInfo({ ok: false, efforts: [], defaultEffort: undefined, error: (r && r.error) || '查询失败' })\n }).catch((e: unknown) => { if (live) setEffortsInfo({ ok: false, efforts: [], defaultEffort: undefined, error: String((e && (e as Error).message) || e) }) })\n return () => { live = false }\n }, [draft.provider, draft.model])\n return (\n <div className={'dsgc-drawer' + (closing ? ' closing' : '')} role=\"dialog\" aria-modal=\"false\" aria-label={draft.id ? '编辑角色' : '添加角色'}>\n <div className=\"dsgc-drawerhead\">\n {Icon(P.IconUserOutline16, 16)}\n <span className=\"dsgc-drawertitle\">{draft.id ? '编辑角色' : '添加角色'}</span>\n <P.Button variant=\"ghost\" size=\"sm\" onClick={close} aria-label=\"关闭\">{Icon(P.IconCloseOutline16, 16)}</P.Button>\n </div>\n <div className=\"dsgc-drawerbody\">\n <div className=\"dsgc-form\">\n <div className=\"dsgc-field\">\n <label>名称</label>\n <input\n className=\"dsgc-input\"\n value={draft.name}\n autoFocus={!draft.id}\n onChange={(e) => { set(Object.assign({}, draft, { name: e.target.value })) }}\n placeholder=\"例如:产品经理\"\n />\n </div>\n <div className=\"dsgc-field\">\n <label>标识色</label>\n <div className=\"dsgc-palette\">\n {PALETTE.map((c) => (\n <button\n key={c}\n type=\"button\"\n className={'dsgc-dot' + (draft.color === c ? ' on' : '')}\n style={{ background: c }}\n onClick={() => { set(Object.assign({}, draft, { color: c })) }}\n aria-label={'选择标识色 ' + c}\n />\n ))}\n </div>\n </div>\n <div className=\"dsgc-field\">\n <label>人设 / 角色设定</label>\n <textarea\n className=\"dsgc-textarea\"\n rows={4}\n value={draft.persona}\n onChange={(e) => { set(Object.assign({}, draft, { persona: e.target.value })) }}\n placeholder=\"性格、立场、说话风格、专业背景……\"\n />\n </div>\n <div className=\"dsgc-field\">\n <label>模型提供方</label>\n {providers.length\n ? (\n <select className=\"dsgc-select\" value={draft.provider} onChange={onProvider}>\n <option value=\"\">选择提供方…</option>\n {providers.map((p) => <option key={p.id} value={p.id}>{p.name || p.id}</option>)}\n </select>\n )\n : (\n <div className=\"dsgc-selhint\">\n {(props.modelsError ? '模型目录加载失败:' + props.modelsError : '暂无可用 provider') + ' '}\n <P.Button variant=\"outline\" size=\"sm\" onClick={props.onRetryModels}>重试</P.Button>\n </div>\n )}\n </div>\n <div className=\"dsgc-field\">\n <label>模型</label>\n {modelsOf.length\n ? (\n <select\n className=\"dsgc-select\"\n value={draft.model}\n onChange={(e) => { set(Object.assign({}, draft, { model: e.target.value, reasoningEffort: 'default' })) }}\n >\n {modelsOf.map((m) => <option key={m.id} value={m.id}>{m.name || m.id}</option>)}\n </select>\n )\n : <div className=\"dsgc-selhint\">请先选择有可用模型的提供方</div>}\n </div>\n <div className=\"dsgc-field\">\n <label>温度(可选)</label>\n <input\n className=\"dsgc-input\"\n type=\"number\"\n step=\"0.1\"\n min=\"0\"\n max=\"2\"\n value={draft.temperature == null ? '' : String(draft.temperature)}\n onChange={(e) => { set(Object.assign({}, draft, { temperature: e.target.value === '' ? undefined : Number(e.target.value) })) }}\n />\n </div>\n <div className=\"dsgc-field\">\n <label>深度思考</label>\n <div style={{ display: 'flex', gap: 10, alignItems: 'center' }}>\n <P.Switch checked={draft.thinking === true} onChange={(v: boolean) => { set(Object.assign({}, draft, { thinking: v })) }} label=\"深度思考\" />\n <span className=\"dsgc-hint\">开启后角色发言前先思考(支持思考的模型)</span>\n </div>\n </div>\n {draft.thinking === true\n ? (\n <div className=\"dsgc-field\">\n <label>推理级别</label>\n {effortsInfo === null\n ? <div className=\"dsgc-selhint\">查询推理级别…</div>\n : !effortsInfo.ok\n ? <div className=\"dsgc-selhint\">推理级别查询失败:{effortsInfo.error}(若刚更新插件,请重启 dsh web 使 host 半生效)</div>\n : (effortsInfo.efforts || []).length\n ? (\n <select\n className=\"dsgc-select\"\n value={draft.reasoningEffort && draft.reasoningEffort !== 'default' ? draft.reasoningEffort : 'default'}\n onChange={(e) => { set(Object.assign({}, draft, { reasoningEffort: e.target.value })) }}\n title=\"取自当前模型设置中的推理选项;默认 = 使用该模型的默认推理级别\"\n >\n <option value=\"default\">\n 默认{effortsInfo.defaultEffort ? '(当前默认:' + ((effortsInfo.efforts || []).find((x) => x.id === effortsInfo.defaultEffort) || { name: '' }).name + ')' : ''}\n </option>\n {(effortsInfo.efforts || []).map((e) => <option key={e.id} value={e.id} title={e.description || ''}>{e.name || e.id}</option>)}\n </select>\n )\n : <div className=\"dsgc-selhint\">当前模型未提供推理等级,将使用默认</div>}\n </div>\n )\n : null}\n {props.formError ? <div className=\"dsgc-formerr\">{props.formError}</div> : null}\n </div>\n </div>\n <div className=\"dsgc-drawerfoot\">\n <P.Button variant=\"outline\" onClick={close}>取消</P.Button>\n <P.Button variant=\"primary\" onClick={props.onSave}>{draft.id ? '保存' : '添加'}</P.Button>\n </div>\n </div>\n )\n}\n","/**\n * 左侧导航栏组件\n * @module dsh-group-chat/client/components\n */\n\nimport type { ReactNode, KeyboardEvent as ReactKeyboardEvent } from 'react'\nimport { Icon, P } from '../lib/ui.ts'\nimport { groupById, sessById, sessStatus, SESS_STATUS_LABEL, type ClientSnapshot } from '../lib/model.ts'\n\ninterface NavPanelProps {\n snap: ClientSnapshot\n search: string\n setSearch: (val: string) => void\n collapsedGroups: Set<string>\n setCollapsedGroups: (fn: (prev: Set<string>) => Set<string>) => void\n gid: string | null\n sid: string | null\n setGid: (val: string) => void\n setSid: (val: string) => void\n setPartsSel: (val: string[] | null) => void\n renameDraft: { kind: 'group' | 'session', id: string, value: string } | null\n setRenameDraft: (val: { kind: 'group' | 'session', id: string, value: string } | null) => void\n confirmDel: { kind: 'group' | 'session', id: string } | null\n setConfirmDel: (val: { kind: 'group' | 'session', id: string } | null) => void\n mutate: (args: Record<string, unknown>) => Promise<unknown>\n navOpen: boolean\n}\n\nexport function NavPanel(props: NavPanelProps): ReactNode {\n const { snap, search, setSearch, collapsedGroups, setCollapsedGroups, gid, sid, setGid, setSid, setPartsSel, renameDraft, setRenameDraft, confirmDel, setConfirmDel, mutate, navOpen } = props\n\n const commitRename = async (): Promise<void> => {\n if (!renameDraft) return\n const d = renameDraft\n setRenameDraft(null)\n const value = String(d.value || '').trim()\n if (!value) return\n if (d.kind === 'group') await mutate({ op: 'renameGroup', groupId: d.id, name: value })\n else await mutate({ op: 'renameSession', sessionId: d.id, name: value })\n }\n\n const renameKeyDown = (e: ReactKeyboardEvent<HTMLInputElement>): void => {\n if (e.key === 'Enter') {\n e.preventDefault()\n void commitRename()\n } else if (e.key === 'Escape') {\n e.preventDefault()\n setRenameDraft(null)\n }\n }\n\n const doDelete = async (): Promise<void> => {\n if (!confirmDel) return\n const d = confirmDel\n setConfirmDel(null)\n if (d.kind === 'group') await mutate({ op: 'deleteGroup', groupId: d.id })\n else await mutate({ op: 'deleteSession', sessionId: d.id })\n }\n\n const q = search.trim().toLowerCase()\n const groupMatches = (g: ClientSnapshot['groups'][number]): { show: boolean, filterSessions: boolean } => {\n if (!q) return { show: true, filterSessions: false }\n if (g.name.toLowerCase().includes(q)) return { show: true, filterSessions: false }\n const hitSessions = g.sessionIds.map((id) => sessById(snap, id)).filter((s) => s && s.name.toLowerCase().includes(q))\n return { show: hitSessions.length > 0, filterSessions: true }\n }\n\n const group = gid ? groupById(snap, gid) : null\n\n const treeNodes: ReactNode[] = []\n for (const g of snap.groups) {\n const match = groupMatches(g)\n if (!match.show) continue\n const expanded = q ? true : !collapsedGroups.has(g.id)\n const isRenameGroup = renameDraft && renameDraft.kind === 'group' && renameDraft.id === g.id\n const isConfirmGroup = confirmDel && confirmDel.kind === 'group' && confirmDel.id === g.id\n const groupChildren: ReactNode[] = []\n \n if (expanded) {\n for (const sessionId of g.sessionIds) {\n const s = sessById(snap, sessionId)\n if (!s) continue\n if (match.filterSessions && !s.name.toLowerCase().includes(q)) continue\n const sess = sid ? sessById(snap, sid) : null\n const isActive = sess && s.id === sess.id && g.id === group?.id\n const isRenameSess = renameDraft && renameDraft.kind === 'session' && renameDraft.id === s.id\n const isConfirm = confirmDel && confirmDel.kind === 'session' && confirmDel.id === s.id\n // 会话状态(对齐主 GUI StateDot:idle 不渲染点)\n const st = sessStatus(snap.run, s.id)\n\n groupChildren.push(\n <div\n key={s.id}\n className={'dsgc-sess-row' + (isActive ? ' on' : '')}\n role=\"button\"\n tabIndex={0}\n onClick={() => { setGid(g.id); setSid(s.id); setPartsSel(null); setConfirmDel(null); setRenameDraft(null) }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n setGid(g.id); setSid(s.id); setPartsSel(null); setConfirmDel(null); setRenameDraft(null)\n }\n }}\n >\n {/* 固定宽度状态槽(对齐主 GUI:槽恒在、点按状态渲染——行间文案对齐) */}\n <span className=\"dsgc-sess-status\">\n {st !== 'idle'\n ? (\n <span role=\"img\" title={SESS_STATUS_LABEL[st]} aria-label={SESS_STATUS_LABEL[st]}>\n <P.StateDot state={st} size={8} />\n </span>\n )\n : null}\n </span>\n {isRenameSess\n ? (\n <input\n className=\"dsgc-rename\"\n value={renameDraft!.value}\n autoFocus\n onChange={(e) => { setRenameDraft({ kind: 'session', id: s.id, value: e.target.value }) }}\n onBlur={() => { void commitRename() }}\n onKeyDown={renameKeyDown}\n onClick={(e) => { e.stopPropagation() }}\n />\n )\n : <span className=\"dsgc-sess-name\">{s.name}</span>}\n <span className=\"dsgc-nodeops\">\n <button\n className=\"dsgc-opbtn\"\n title=\"重命名会话\"\n aria-label=\"重命名会话\"\n onClick={(e) => { e.stopPropagation(); setRenameDraft({ kind: 'session', id: s.id, value: s.name }) }}\n >\n {Icon(P.IconEditOutline16, 14)}\n </button>\n <button\n className={'dsgc-opbtn' + (isConfirm ? ' danger' : '')}\n title={isConfirm ? '再次点击确认删除' : '删除会话'}\n aria-label=\"删除会话\"\n onClick={(e) => {\n e.stopPropagation()\n if (isConfirm) void doDelete()\n else setConfirmDel({ kind: 'session', id: s.id })\n }}\n >\n {Icon(P.IconTrashOutline16, 14)}\n </button>\n </span>\n </div>,\n )\n }\n \n groupChildren.push(\n <button key=\"__add\" className=\"dsgc-addsess\" onClick={() => { void mutate({ op: 'createSession', groupId: g.id }) }}>\n {Icon(P.IconPlusOutline16, 14)}新会话\n </button>,\n )\n }\n \n treeNodes.push(\n <div key={g.id} className=\"dsgc-gnode\">\n <div\n className={'dsgc-grow-row' + (g.id === group?.id ? ' on' : '')}\n role=\"button\"\n tabIndex={0}\n onClick={() => { setGid(g.id); setPartsSel(null); setConfirmDel(null); setRenameDraft(null) }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n setGid(g.id); setPartsSel(null); setConfirmDel(null); setRenameDraft(null)\n }\n }}\n >\n <button\n className={'dsgc-twist' + (expanded ? '' : ' closed')}\n title={expanded ? '收起' : '展开'}\n aria-label={expanded ? '收起' : '展开'}\n onClick={(e) => {\n e.stopPropagation()\n setCollapsedGroups((prev) => {\n const next = new Set(prev)\n if (next.has(g.id)) next.delete(g.id)\n else next.add(g.id)\n return next\n })\n }}\n >\n {Icon(P.IconChevronDownOutline14, 14)}\n </button>\n {isRenameGroup\n ? (\n <input\n className=\"dsgc-rename\"\n value={renameDraft!.value}\n autoFocus\n onChange={(e) => { setRenameDraft({ kind: 'group', id: g.id, value: e.target.value }) }}\n onBlur={() => { void commitRename() }}\n onKeyDown={renameKeyDown}\n onClick={(e) => { e.stopPropagation() }}\n />\n )\n : <span className=\"dsgc-gname\">{g.name}</span>}\n <span className=\"dsgc-nodeops\">\n <button\n className=\"dsgc-opbtn\"\n title=\"重命名群组\"\n aria-label=\"重命名群组\"\n onClick={(e) => { e.stopPropagation(); setRenameDraft({ kind: 'group', id: g.id, value: g.name }) }}\n >\n {Icon(P.IconEditOutline16, 14)}\n </button>\n <button\n className={'dsgc-opbtn' + (isConfirmGroup ? ' danger' : '')}\n title={isConfirmGroup ? '再次点击确认删除' : '删除群组'}\n aria-label=\"删除群组\"\n onClick={(e) => {\n e.stopPropagation()\n if (isConfirmGroup) void doDelete()\n else setConfirmDel({ kind: 'group', id: g.id })\n }}\n >\n {Icon(P.IconTrashOutline16, 14)}\n </button>\n </span>\n </div>\n {expanded ? <div className=\"dsgc-sess-list\">{groupChildren}</div> : null}\n </div>,\n )\n }\n\n return (\n <div className={'dsgc-nav' + (navOpen ? '' : ' closed')} aria-hidden={navOpen ? undefined : 'true'}>\n <P.Input\n icon={Icon(P.IconSearchOutline16, 16)}\n className=\"dsgc-search\"\n placeholder=\"搜索群组与会话…\"\n value={search}\n onChange={(e: { target: { value: string } }) => setSearch(e.target.value)}\n />\n {treeNodes.length\n ? <div className=\"dsgc-tree\">{treeNodes}</div>\n : <div className=\"dsgc-hint\">{q ? '没有匹配「' + search.trim() + '」的群组或会话' : '暂无群组'}</div>}\n <P.Button variant=\"outline\" onClick={() => { void mutate({ op: 'createGroup' }) }}>\n {Icon(P.IconPlusOutline16, 16)}新建群组\n </P.Button>\n </div>\n )\n}\n","/**\n * 右侧成员与工作区栏组件\n * @module dsh-group-chat/client/components\n */\n\nimport type { ReactNode } from 'react'\nimport { Icon, P } from '../lib/ui.ts'\nimport { roleById, type ClientSnapshot, type ModelsResponse, type RoleDraft, type SnapshotRole } from '../lib/model.ts'\n\ninterface AsidePanelProps {\n snap: ClientSnapshot\n group: ClientSnapshot['groups'][number]\n asideOpen: boolean\n wsDraft: string | null\n setWsDraft: (val: string | null) => void\n fileBrowser: { open: boolean, loading: boolean, list: import('../../core/types.ts').BrowseResult | null, error: string } | null\n setFileBrowser: (val: { open: boolean, loading: boolean, list: import('../../core/types.ts').BrowseResult | null, error: string } | null) => void\n mutate: (args: Record<string, unknown>) => Promise<unknown>\n openRoleEditor: (role: SnapshotRole | null) => Promise<void>\n openBrowser: (path: string | undefined) => Promise<void>\n selectCurrentDir: () => void\n}\n\nexport function AsidePanel(props: AsidePanelProps): ReactNode {\n const { snap, group, asideOpen, wsDraft, setWsDraft, fileBrowser, setFileBrowser, mutate, openRoleEditor, openBrowser, selectCurrentDir } = props\n\n const commitWsDir = (): void => {\n if (wsDraft !== null && group && wsDraft !== (group.workspaceDir || '')) {\n void mutate({ op: 'setWorkspaceDir', groupId: group.id, path: wsDraft })\n }\n setWsDraft(null)\n }\n\n return (\n <div className={'dsgc-aside' + (asideOpen ? '' : ' closed')} aria-hidden={asideOpen ? undefined : 'true'}>\n <div className=\"dsgc-sec\">\n <div className=\"dsgc-sechead\">\n 群成员\n <span className=\"dsgc-secspacer\" />\n <span className=\"dsgc-seccount\">{group.roleIds.length ? group.roleIds.length + ' 个' : ''}</span>\n <P.Button variant=\"ghost\" size=\"sm\" onClick={() => { void openRoleEditor(null) }} aria-label=\"添加角色\">\n {Icon(P.IconPlusOutline16, 14)}添加\n </P.Button>\n </div>\n {group.roleIds.length\n ? (\n <div className=\"dsgc-roles\">\n {group.roleIds.map((rid) => {\n const r = roleById(snap, rid)\n if (!r) return null\n return (\n <div\n key={r.id}\n className={'dsgc-role' + (r.enabled ? '' : ' off')}\n role=\"button\"\n tabIndex={0}\n onClick={() => { void openRoleEditor(r) }}\n onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); void openRoleEditor(r) } }}\n title=\"点击编辑角色\"\n >\n <div className=\"dsgc-rolehead\">\n <span className=\"dsgc-roledot\" style={{ background: r.color || '#888' }} />\n <span className=\"dsgc-rolename\">{r.name}</span>\n <P.Tooltip label={r.enabled ? '停用该角色' : '启用该角色'} side=\"top\" delayMs={300}>\n <span\n onClick={(e) => { e.stopPropagation() }}\n onKeyDown={(e) => { e.stopPropagation() }}\n style={{ display: 'inline-flex', flex: 'none' }}\n >\n <P.Switch\n checked={r.enabled}\n onChange={() => { void mutate({ op: 'setRoleEnabled', roleId: r.id, enabled: !r.enabled }) }}\n label={r.enabled ? '停用该角色' : '启用该角色'}\n aria-label={(r.enabled ? '停用' : '启用') + '角色 ' + r.name}\n />\n </span>\n </P.Tooltip>\n </div>\n {r.persona ? <div className=\"dsgc-rolepersona\" title={r.persona}>{r.persona}</div> : null}\n <div className=\"dsgc-rolemenu\">\n <span\n className=\"dsgc-rolemodel\"\n title={r.provider + ' / ' + r.model + (r.thinking ? ' · 深度思考' + (r.reasoningEffort && r.reasoningEffort !== 'default' ? '(' + r.reasoningEffort + ')' : '') : '')}\n >\n {r.provider} / {r.model}\n </span>\n {r.thinking\n ? <span title=\"深度思考\" style={{ display: 'inline-flex', alignItems: 'center', color: 'var(--dsw-alias-label-tertiary,inherit)' }}>{Icon(P.IconThinkOutline14, 14)}</span>\n : null}\n <span className=\"dsgc-roleops\">\n <button\n className=\"dsgc-opbtn\"\n title=\"编辑角色\"\n aria-label=\"编辑角色\"\n onClick={(e) => { e.stopPropagation(); void openRoleEditor(r) }}\n >\n {Icon(P.IconEditOutline16, 14)}\n </button>\n <button\n className=\"dsgc-opbtn danger\"\n title=\"移除角色\"\n aria-label=\"移除角色\"\n onClick={(e) => { e.stopPropagation(); void mutate({ op: 'deleteRole', roleId: r.id }) }}\n >\n {Icon(P.IconTrashOutline16, 14)}\n </button>\n </span>\n </div>\n </div>\n )\n })}\n </div>\n )\n : <div className=\"dsgc-hint\">还没有角色。每个角色可绑定不同的 provider/model,在群内以独立身份发言。</div>}\n </div>\n <div className=\"dsgc-sec\">\n <div className=\"dsgc-sechead\">工作区目录</div>\n <div className=\"dsgc-field\">\n <div className=\"dsgc-wsrow\">\n <input\n className=\"dsgc-input\"\n value={wsDraft === null ? (group.workspaceDir || '') : wsDraft}\n placeholder=\"~/docs 或 /abs/dir\"\n onChange={(e) => { setWsDraft(e.target.value) }}\n onBlur={commitWsDir}\n onKeyDown={(e) => { if (e.key === 'Enter') (e.target as HTMLInputElement).blur() }}\n />\n <P.Button variant=\"outline\" size=\"sm\" onClick={() => { void openBrowser(wsDraft === null ? group.workspaceDir : wsDraft) }}>\n {Icon(P.IconFolderOpenOutline16, 14)}浏览\n </P.Button>\n </div>\n <div className=\"dsgc-hint\">发送时读取目录内文本文件,注入本群全体角色上下文;角色也可用工具主动查看</div>\n {group.workspaceDir === '~' || group.workspaceDir === '/'\n ? <div className=\"dsgc-err\">工作区指向整个主目录/根目录:角色的只读工具将可读取该范围下的所有文件,请谨慎</div>\n : null}\n </div>\n {fileBrowser && fileBrowser.open\n ? (\n <div className=\"dsgc-fb\">\n <div className=\"dsgc-fbhead\">\n <span className=\"dsgc-fbpath\" title={fileBrowser.list ? fileBrowser.list.path : ''}>\n {fileBrowser.loading ? '读取中…' : (fileBrowser.list ? fileBrowser.list.path : '')}\n </span>\n <span style={{ display: 'flex', gap: 4, alignItems: 'center' }}>\n <P.Button variant=\"primary\" size=\"sm\" disabled={!fileBrowser.list} onClick={selectCurrentDir}>选定此目录</P.Button>\n {fileBrowser.list\n ? <P.Button variant=\"outline\" size=\"sm\" title=\"上一级\" aria-label=\"上一级\" onClick={() => { void openBrowser(fileBrowser.list!.parent) }}>{Icon(P.IconChevronUpOutline14, 14)}</P.Button>\n : null}\n {fileBrowser.list\n ? <P.Button variant=\"outline\" size=\"sm\" title=\"主目录\" aria-label=\"主目录\" onClick={() => { void openBrowser(fileBrowser.list!.home) }}>{Icon(P.IconFolderClose16, 14)}</P.Button>\n : null}\n <P.Button variant=\"ghost\" size=\"sm\" onClick={() => { setFileBrowser(null) }} aria-label=\"关闭浏览器\">{Icon(P.IconCloseOutline16, 14)}</P.Button>\n </span>\n </div>\n {fileBrowser.error ? <div className=\"dsgc-err\">{fileBrowser.error}</div> : null}\n {fileBrowser.list\n ? (\n <div className=\"dsgc-fblist\">\n {(fileBrowser.list.entries || []).length\n ? (fileBrowser.list.entries || []).map((e) => e.type === 'directory'\n ? (\n <button\n key={e.path}\n type=\"button\"\n className={'dsgc-fbrow' + (e.hidden ? ' dim' : '') + ' dir'}\n onClick={() => { void openBrowser(e.path) }}\n >\n {Icon(e.hidden ? P.IconFolderClose16 : P.IconFolderOpenOutline16, 14)}\n <span className=\"dsgc-fbname\">{e.name}/</span>\n </button>\n )\n : (\n <div key={e.path} className=\"dsgc-fbrow dim file\">\n <span className=\"dsgc-fbname\">{e.name}</span>\n {e.size !== undefined ? <span className=\"dsgc-fbsize\">{(P as unknown as { fileSizeText: (n: number) => string }).fileSizeText(e.size)}</span> : null}\n </div>\n ))\n : <div className=\"dsgc-hint\">空目录</div>}\n </div>\n )\n : null}\n </div>\n )\n : null}\n </div>\n </div>\n )\n}\n","/**\n * 思考折叠行(对标宿主 ReasoningRow:折叠摘要 / 展开全文)。\n * @module dsh-group-chat/client/ThinkRow\n */\n\nimport { useState, type ReactNode } from 'react'\nimport { P } from '../lib/ui.ts'\nimport { firstLine, latestLine } from '../lib/model.ts'\n\nexport function ThinkRow(props: { text: string, running?: boolean }): ReactNode {\n const text = props.text || ''\n const running = !!props.running\n const [expanded, setExpanded] = useState(false)\n const plain = (line: string): string => line.replace(/^(\\s*#{1,6}\\s+|\\s*[-*+]\\s+|\\s*>\\s*)+/, '').replace(/[*`_~]/g, '').replace(/\\s+/g, ' ').trim()\n const summary = plain(running ? latestLine(text) : firstLine(text))\n return (\n <div className=\"dsgc-think\">\n <P.DisclosureRow\n rowClassName=\"dsgc-thinkrow\"\n icon={<P.IconThinkOutline14 size={14} />}\n title=\"思考\"\n open={expanded}\n expandable\n expandOnRowClick\n onToggle={() => { setExpanded((v) => !v) }}\n collapsedContent={text ? <span className=\"dsgc-thinksummary\">{summary}</span> : null}\n >\n <div className=\"dsgc-thinkbody\">{text}</div>\n </P.DisclosureRow>\n </div>\n )\n}\n","/**\n * 工具调用折叠行(对标思考折叠:摘要行 / 展开输出)。\n * @module dsh-group-chat/client/ToolRow\n */\n\nimport { useState, type ReactNode } from 'react'\nimport { Icon, P, pickPrimitive } from '../lib/ui.ts'\nimport type { ToolCallView } from '../lib/model.ts'\n\nconst TOOL_ICONS: Record<string, string> = { read_file: 'IconBrowseOutline16', list_dir: 'IconFolderOpenOutline16', run_command: 'IconCodeOutline16' }\n\nexport function ToolRow(props: { c: ToolCallView }): ReactNode {\n const c = props.c\n const [expanded, setExpanded] = useState(false)\n let brief = ''\n try {\n brief = JSON.stringify(c.args) || ''\n } catch {\n brief = ''\n }\n if (brief.length > 40) brief = brief.slice(0, 40) + '…'\n const IconOf = pickPrimitive(TOOL_ICONS[c.tool] || 'IconCodeOutline16')\n const statusText = c.status === 'ok' ? '成功' : c.status === 'denied' ? '用户拒绝' : '失败'\n const StatusIcon = c.status === 'ok' ? P.IconCheckOutline14 : c.status === 'denied' ? P.IconCloseOutline16 : P.IconWarningOutline16\n const dur = c.durationMs ? (c.durationMs >= 1000 ? (c.durationMs / 1000).toFixed(1) + 's' : c.durationMs + 'ms') : ''\n return (\n <div className=\"dsgc-tool\">\n <P.DisclosureRow\n rowClassName=\"dsgc-toolrow\"\n icon={<IconOf size={14} />}\n title={c.tool + (brief ? ' ' + brief : '')}\n open={expanded}\n expandable\n expandOnRowClick\n onToggle={() => { setExpanded((v) => !v) }}\n collapsedContent={\n <span className=\"dsgc-toolsummary\">\n {Icon(StatusIcon, 12, {\n verticalAlign: '-2px',\n marginRight: 4,\n color: c.status === 'ok' ? 'var(--dsw-alias-label-tertiary,inherit)' : 'var(--dsw-alias-state-error-primary,#e5484d)',\n })}\n {statusText + (dur ? ' · ' + dur : '')}\n </span>\n }\n >\n <div className=\"dsgc-toolbody\">{c.output || '(无输出)'}</div>\n </P.DisclosureRow>\n </div>\n )\n}\n","/**\n * 聊天消息气泡(user / system / 角色发言)。\n *\n * 帧稳定 memo:SSE 全量快照(~65KB × 7fps)每帧重建全部消息对象 identity,\n * 但已完成消息在 host 侧 append 后不可变——按渲染相关字段做值比较,流式\n * 期间跳过已完成消息的重渲(每帧仅 live 行与派生列表变化),避免全量\n * MarkdownText 重新解析打满主线程导致「卡死后一次性蹦出」。\n * @module dsh-group-chat/client/Bubble\n */\n\nimport { memo, type ReactNode } from 'react'\nimport { P } from '../lib/ui.ts'\nimport { fmtTime, MD_LABELS, type ClientSnapshot, type SnapshotRole } from '../lib/model.ts'\nimport { ThinkRow } from './ThinkRow.tsx'\nimport { ToolRow } from './ToolRow.tsx'\n\nexport interface BubbleProps {\n m: ClientSnapshot['messages'][number]\n /** 父级解析好的发言角色(user/system 消息为 null)——避免 Bubble 依赖 snap identity。 */\n role: SnapshotRole | null\n}\n\nfunction BubbleInner({ m, role }: BubbleProps): ReactNode {\n const isUser = m.speaker === 'user'\n const isSys = m.speaker === 'system'\n const name = isUser ? '我' : isSys ? '系统' : role ? role.name : '成员'\n if (isSys) return <div className={'dsgc-sysmsg' + (m.error ? ' err' : '')}>{m.text}</div>\n return (\n <div className={'dsgc-msg' + (isUser ? ' mine' : '')}>\n <div\n className={'dsgc-avatar' + (isUser ? ' mine' : '')}\n style={isUser || !role ? undefined : { border: '2px solid ' + (role.color || '#888') }}\n >\n {name.slice(0, 1)}\n </div>\n <div className=\"dsgc-msgbody\">\n <div className=\"dsgc-msghead\">\n <span className=\"dsgc-msgname\">{name}</span>\n {m.model ? <span className=\"dsgc-msgmodel\" title={m.model}>{m.model}</span> : null}\n {m.ts ? <span className=\"dsgc-msgtime\">{fmtTime(m.ts)}</span> : null}\n </div>\n {isUser\n ? <div className=\"dsgc-msgtext\">{m.text}</div>\n : (\n <div className=\"dsgc-msgtext\">\n {m.reasoning ? <ThinkRow text={m.reasoning} /> : null}\n {(Array.isArray(m.toolCalls) ? m.toolCalls : []).map((c, i) => <ToolRow key={'tc' + i} c={c} />)}\n <P.MarkdownText text={m.text || '(无内容)'} labels={MD_LABELS} />\n </div>\n )}\n </div>\n </div>\n )\n}\n\n/** 渲染相关字段的值比较(消息不可变;角色仅名/色参与渲染)。 */\nfunction bubblePropsEqual(a: BubbleProps, b: BubbleProps): boolean {\n const x = a.m\n const y = b.m\n if (x !== y) {\n if (x.id !== y.id || x.speaker !== y.speaker || x.text !== y.text || x.reasoning !== y.reasoning || x.model !== y.model || x.error !== y.error || x.ts !== y.ts) return false\n const ta = Array.isArray(x.toolCalls) ? x.toolCalls : []\n const tb = Array.isArray(y.toolCalls) ? y.toolCalls : []\n if (ta.length !== tb.length) return false\n for (let i = 0; i < ta.length; i++) {\n const ca = ta[i]\n const cb = tb[i]\n if (ca !== cb && (ca.tool !== cb.tool || ca.status !== cb.status || ca.output !== cb.output || ca.durationMs !== cb.durationMs || JSON.stringify(ca.args) !== JSON.stringify(cb.args))) return false\n }\n }\n const ra = a.role\n const rb = b.role\n return (ra ? ra.name + '\\u0000' + (ra.color || '') : '') === (rb ? rb.name + '\\u0000' + (rb.color || '') : '')\n}\n\nexport const Bubble = memo(BubbleInner, bubblePropsEqual)\n","/**\n * 消息流显示组件\n * @module dsh-group-chat/client/components\n */\n\nimport type { ReactNode, CSSProperties } from 'react'\nimport { Icon, P } from '../lib/ui.ts'\nimport { Bubble } from './Bubble.tsx'\nimport { ThinkRow } from './ThinkRow.tsx'\nimport { roleById, type ClientSnapshot } from '../lib/model.ts'\nimport { MD_LABELS } from '../lib/model.ts'\n\ninterface MessageFlowProps {\n snap: ClientSnapshot\n sess: ClientSnapshot['sessions'][number] | null\n busyNow: boolean\n msgById: Record<string, ClientSnapshot['messages'][number]>\n action: (payload: Record<string, unknown>) => Promise<unknown>\n}\n\nexport function MessageFlow(props: MessageFlowProps): ReactNode {\n const { snap, sess, busyNow, msgById, action } = props\n\n const bubbles: ReactNode[] = []\n \n if (sess) {\n for (const mid of sess.messageIds) {\n const m = msgById[mid]\n if (!m) continue\n // 角色在父级解析:Bubble 按值 memo(不依赖 snap identity),流式帧\n // 不再触发已完成消息的全量重渲(每帧仅 live 行与派生列表变化)\n const role = m.speaker !== 'user' && m.speaker !== 'system' ? roleById(snap, m.speaker) : null\n bubbles.push(<Bubble key={m.id} m={m} role={role} />)\n }\n }\n \n // 流式尾巴\n if (busyNow && snap.run.currentRoleId) {\n const lr = roleById(snap, snap.run.currentRoleId)\n if (lr) {\n bubbles.push(\n <div key=\"__live\" className=\"dsgc-msg live\">\n <div\n className=\"dsgc-avatar\"\n style={{ border: '2px solid ' + (lr.color || '#888'), '--role-color': lr.color || '#888' } as CSSProperties}\n >\n {lr.name.slice(0, 1)}\n </div>\n <div className=\"dsgc-msgbody\">\n <div className=\"dsgc-msghead\">\n <span className=\"dsgc-msgname\">{lr.name}</span>\n <span className=\"dsgc-msgmodel\">{lr.provider} / {lr.model}</span>\n <span className=\"dsgc-msgtime dsgc-typing\">深度求索...</span>\n </div>\n <div className=\"dsgc-msgtext live\">\n {snap.run.partialReasoning ? <ThinkRow text={snap.run.partialReasoning} running /> : null}\n {snap.run.partial ? <P.MarkdownText text={snap.run.partial} streaming labels={MD_LABELS} /> : null}\n {/* 首 delta 前的「思考中」占位(深度思考模型首字节可能等数秒到数十秒,\n 空白气泡会被感知为卡死);delta 到达后被真实思考行/正文自然替换 */}\n {!snap.run.partial && !snap.run.partialReasoning\n ? (\n <div className=\"dsgc-pending\">\n {Icon(P.IconThinkOutline14, 14)}\n <span>思考中</span>\n <span className=\"dsgc-pendingdots\" aria-hidden=\"true\"><i /><i /><i /></span>\n </div>\n )\n : null}\n </div>\n </div>\n </div>,\n )\n }\n }\n \n // 命令确认卡片\n const pc = busyNow && snap.run.pendingConfirm && sess && snap.run.sessionId === sess.id ? snap.run.pendingConfirm : null\n if (pc) {\n const lr = roleById(snap, snap.run.currentRoleId)\n bubbles.push(\n <div key=\"__confirm\" className=\"dsgc-confirm\">\n <div className=\"dsgc-confirmtitle\">\n {Icon(P.IconWarningOutline16, 14)}\n {(lr ? lr.name : '角色') + ' 请求执行命令(工作区内)'}\n </div>\n <div className=\"dsgc-confirmcmd\">{String((pc.args && pc.args.command) || '')}</div>\n <div className=\"dsgc-hint\">允许后将在工作区目录执行;拒绝后角色将继续纯文本讨论</div>\n <div className=\"dsgc-confirmops\">\n <P.Button variant=\"primary\" size=\"sm\" onClick={() => { void action({ kind: 'confirmCommand', toolCallId: pc.toolCallId, allow: true }) }}>允许</P.Button>\n <P.Button variant=\"outline\" size=\"sm\" onClick={() => { void action({ kind: 'confirmCommand', toolCallId: pc.toolCallId, allow: false }) }}>拒绝</P.Button>\n </div>\n </div>,\n )\n }\n\n return <>{bubbles}</>\n}\n","/**\n * 群聊数据模型(core 层,无 cordis 依赖)。\n * 数据模型:Group 1..N Session,消息挂在会话上;角色与工作区目录挂在群组上。\n * @module dsh-group-chat/core/types\n */\n\n/**\n * 群组权限档位(对齐主会话 /permission 三档):\n * - view_only 仅可查看:只保留 read_file/list_dir,run_command 从 schema 剔除\n * - workspace_write 工作区内修改:run_command 可用,每条命令逐条确认\n * - full_access 完全权限:run_command 免确认直接执行\n */\nexport type PermissionTier = 'view_only' | 'workspace_write' | 'full_access'\n\n/** 全部合法档位(展示顺序)。 */\nexport const PERMISSION_TIERS: readonly PermissionTier[] = ['view_only', 'workspace_write', 'full_access']\n\n/** 档位安全化:合法字符串原样,其余 undefined。 */\nexport function asPermissionTier(value: unknown): PermissionTier | undefined {\n return typeof value === 'string' && (PERMISSION_TIERS as readonly string[]).includes(value) ? value as PermissionTier : undefined\n}\n\n/**\n * ledger 行档位归一(v2→v3 兼容):显式 permissionTier 优先;\n * 缺失时按旧布尔迁移——allowCommands=true → workspace_write(今日语义即\n * 「可执行命令但逐条确认」),false/无字段 → view_only。\n */\nexport function migrateTier(permissionTier: unknown, allowCommands: unknown): PermissionTier {\n const tier = asPermissionTier(permissionTier)\n if (tier !== undefined) return tier\n return allowCommands === true ? 'workspace_write' : 'view_only'\n}\n\n/** 群组:角色与工作区目录的宿主。 */\nexport interface GroupRecord {\n id: string\n name: string\n workspaceDir: string\n permissionTier: PermissionTier\n roleIds: string[]\n sessionIds: string[]\n}\n\n/** 会话:消息挂在会话上。 */\nexport interface SessionRecord {\n id: string\n groupId: string\n name: string\n topic: string\n /** 名称已被手动编辑:自动命名永久跳过(隐式固定)。 */\n namePinned?: boolean\n /** 主题已被手动编辑:自动整理永久跳过(隐式固定)。 */\n topicPinned?: boolean\n messageIds: string[]\n createdAt: number\n}\n\n/** 角色:绑定 provider/model 的群成员身份。 */\nexport interface RoleRecord {\n id: string\n groupId: string\n name: string\n color?: string\n persona: string\n provider: string\n model: string\n temperature?: number\n reasoningEffort?: string\n enabled: boolean\n thinking: boolean\n}\n\n/** 一次工具调用的落盘/快照形态(TOOLS.md §3.3 回注契约的展示面)。 */\nexport interface ToolCallRecord {\n tool: string\n args: unknown\n status: string\n output: string\n durationMs?: number\n}\n\n/** 消息(user / system / 角色发言共用一条记录)。 */\nexport interface MessageRecord {\n id: string\n sessionId: string\n seq: number\n speaker: string\n text: string\n reasoning?: string\n reasoningFull?: string\n thinkingSummary?: string\n model?: string\n error?: boolean\n toolCalls?: ToolCallRecord[]\n ts: number\n}\n\n/** run_command 确认闸门的待确认载荷。 */\nexport interface PendingConfirm {\n toolCallId: string\n tool: string\n args: { command?: string } & Record<string, unknown>\n}\n\n/** 最近一次创建的群组/会话,供客户端定位选中项。 */\nexport interface LastCreated {\n kind: 'group' | 'session'\n groupId: string\n sessionId: string\n}\n\n/** run 结束后的「输出完毕」标记(内存态不持久化,重启即清;reason 取 ok/error)。 */\nexport interface RunFinished {\n sessionId: string\n reason: 'ok' | 'error'\n}\n\n/** 对话进行时状态(run)。 */\nexport interface RunState {\n running: boolean\n sessionId: string | null\n currentRoleId: string | null\n partial: string\n partialReasoning: string\n stopping: boolean\n queue: string[]\n pendingConfirm: PendingConfirm | null\n confirmSignal: { resolve: (allowed: boolean) => void } | null\n childProc: import('node:child_process').ChildProcess | null\n /** 最近一次 run 的结束标记:会话列表「已完成/已出错」状态的数据源。 */\n finished: RunFinished | null\n}\n\n/** 角色发言的引擎产物。 */\nexport interface SpeakResult {\n text: string\n reasoning: string | undefined\n toolCalls: ToolCallRecord[]\n}\n\n/** 工具执行结果(host 内部约定)。 */\nexport interface ToolExecution {\n status: 'ok' | 'error' | 'denied'\n output: string\n args: Record<string, unknown>\n durationMs: number\n}\n\n/** 模型目录(models action 的缓存载荷)。 */\nexport interface ModelCatalog {\n at: number\n providers: { id: string, name: string }[]\n modelsByProvider: Record<string, { id: string, name?: string }[]>\n}\n\n/** 推理级别选项(efforts action 的载荷)。 */\nexport interface EffortOptions {\n efforts: { id: string, name: string, description?: string }[]\n defaultEffort: string | undefined\n error?: string\n}\n\n/** 目录浏览结果(browse action 的载荷)。 */\nexport interface BrowseResult {\n ok: boolean\n path?: string\n home?: string\n parent?: string\n entries?: { name: string, type: string, path: string, size?: number, hidden: boolean }[]\n error?: string\n}\n\n/** 群工作区 @ 文件检索结果(fileSearch action 的载荷)。 */\nexport interface FileSearchResult {\n ok: boolean\n candidates?: { path: string, isDir: boolean }[]\n error?: string\n}\n\n/** 发到客户端的全量快照(wire 形态)。 */\nexport interface Snapshot {\n revision: number\n run: { running: boolean, sessionId: string | null, currentRoleId: string | null, partial: string, partialReasoning: string, pendingConfirm: PendingConfirm | null, finished: RunFinished | null }\n lastCreated: LastCreated | null\n groups: { id: string, name: string, workspaceDir: string, permissionTier: PermissionTier, roleIds: string[], sessionIds: string[] }[]\n sessions: { id: string, groupId: string, name: string, topic: string, messageIds: string[], createdAt: number }[]\n roles: { id: string, groupId: string, name: string, color?: string, persona: string, provider: string, model: string, temperature?: number, reasoningEffort?: string, enabled: boolean, thinking: boolean }[]\n messages: { id: string, sessionId: string, seq: number, speaker: string, text: string, reasoning?: string, model?: string, error?: boolean, toolCalls?: ToolCallRecord[], ts: number }[]\n error?: string\n}\n\n/** mutate 动作的参数形态(op 分发见 host/service)。 */\nexport interface MutateArgs {\n op: string\n groupId?: string\n sessionId?: string\n roleId?: string\n role?: Partial<RoleRecord>\n name?: string\n topic?: string\n path?: string\n tier?: string\n enabled?: boolean\n}\n\n/** send 动作的参数形态。 */\nexport interface SendArgs {\n sessionId: string\n text?: string\n participantRoleIds?: string[]\n rounds?: number\n}\n\n/** 可选数值参数安全化:数字则原样,否则 undefined。 */\nexport function asNumber(value: unknown): number | undefined {\n return typeof value === 'number' && !Number.isNaN(value) ? value : undefined\n}\n\n/** 可选字符串参数安全化:非 default 的非空字符串则原样,否则 undefined。 */\nexport function asEffort(value: unknown): string | undefined {\n return typeof value === 'string' && value && value !== 'default' ? value : undefined\n}\n","/**\n * 群组权限档位选择器(对齐主会话 composer 左下角的 /permission 选择器):\n * 触发芯片(盾形图标 + 档位名 + chevron)+ Menu 上弹三档 + 完全权限风险\n * 确认弹窗(与主会话同款 RiskConfirmation 原语与文案)。\n * @module dsh-group-chat/client/permission-select\n */\n\nimport { useEffect, useState, type ReactNode } from 'react'\nimport { Icon, P } from '../lib/ui.ts'\nimport type { PermissionTier } from '../../core/types.ts'\nimport { asPermissionTier, PERMISSION_TIERS } from '../../core/types.ts'\n\nexport interface PermissionSelectProps {\n tier: PermissionTier\n onSelect: (tier: PermissionTier) => void\n}\n\n/** 档位展示名(与主会话中文标签一致)。 */\nconst TIER_LABELS: Record<PermissionTier, string> = {\n view_only: '仅可查看',\n workspace_write: '工作区内修改',\n full_access: '完全权限',\n}\n\n/** 档位悬停说明(群聊语境下的真实约束)。 */\nconst TIER_DESCRIPTIONS: Record<PermissionTier, string> = {\n view_only: '角色只能读取工作区文件,不能执行命令',\n workspace_write: '角色可执行命令(cwd 固定在工作区),每条命令需你在会话中确认',\n full_access: '角色可免确认直接执行命令,存在风险',\n}\n\n/** 完全权限风险确认文案(与主会话逐字一致)。 */\nconst CONFIRM_TEXT = {\n title: '确认启用完全权限?',\n description: '启用完全权限后,智能体将减少确认步骤,并且可以直接执行更多操作,包括敏感操作、文件修改或外部命令。仅建议在你信任当前任务时使用。',\n acknowledge: '我已了解风险,并愿意继续',\n cancel: '取消',\n enable: '启用完全权限',\n} as const\n\n// ---- 盾形图标(路径取自主会话 PermissionSelect 的设计稿字形) ----\n\nconst SHIELD_OUTLINE = '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'\n\nfunction GlyphViewOnly(): ReactNode {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden>\n <path d={SHIELD_OUTLINE} stroke=\"currentColor\" strokeWidth=\"1.31831\" strokeLinejoin=\"round\" />\n <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\" />\n </svg>\n )\n}\n\nfunction GlyphWorkspaceWrite(): ReactNode {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden>\n <path d=\"M8.08887 0.251709C8.20479 0.23085 8.32486 0.241168 8.43652 0.282959L15.0215 2.75171C15.2787 2.84819 15.4492 3.09414 15.4492 3.3689V7.0105C15.4492 7.10986 15.4441 7.2081 15.4414 7.30542C15.0285 7.07175 14.5905 6.87695 14.1309 6.73022V3.82495L8.20508 1.60327L2.2793 3.82495V7.0105C2.27936 9.7171 3.4745 11.5379 5.02734 12.7947C5.01025 12.9942 5 13.1962 5 13.4001C5.00001 13.7617 5.02722 14.1169 5.08008 14.4636C2.91555 13.0393 0.961014 10.752 0.960938 7.0105V3.3689C0.960938 3.09417 1.13146 2.84821 1.38867 2.75171L7.97461 0.282959L8.08887 0.251709Z\" fill=\"currentColor\" />\n <path d=\"M11.3525 5.64688V6.85688H5V5.64688H11.3525Z\" fill=\"currentColor\" />\n <path d=\"M9.5824 8.29376V9.50376H5V8.29376H9.5824Z\" fill=\"currentColor\" />\n <path d=\"M14.6647 15.6852H10.0338C10.3878 15.3751 10.7567 15.0517 11.0772 14.7706C11.2531 14.6164 11.4144 14.4746 11.5511 14.3547H14.6647V15.6852Z\" fill=\"currentColor\" />\n <path d=\"M8.14852 14.1308L7.33925 15.4976C7.22458 15.6912 7.42245 15.9194 7.63037 15.8333L9.09785 15.2254L15.0399 10.0719L14.0905 8.97733L8.14852 14.1308Z\" fill=\"currentColor\" />\n </svg>\n )\n}\n\nfunction GlyphFullAccess(): ReactNode {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden>\n <path d={SHIELD_OUTLINE} stroke=\"currentColor\" strokeWidth=\"1.31831\" strokeLinejoin=\"round\" />\n <path d=\"M9.10094 4.5V8.75939H7.59888V4.5H9.10094Z\" fill=\"currentColor\" />\n <path d=\"M9.10094 9.8114V11.5H7.59888V9.8114Z\" fill=\"currentColor\" />\n </svg>\n )\n}\n\nconst TIER_GLYPHS: Record<PermissionTier, () => ReactNode> = {\n view_only: GlyphViewOnly,\n workspace_write: GlyphWorkspaceWrite,\n full_access: GlyphFullAccess,\n}\n\nexport function PermissionSelect(props: PermissionSelectProps): ReactNode {\n const [open, setOpen] = useState(false)\n const [confirming, setConfirming] = useState(false)\n const [acknowledged, setAcknowledged] = useState(false)\n // 版本错位兜底:旧 host 快照无 permissionTier(或值非法)时按最安全的仅可查看呈现,\n // 不让面板整体崩溃\n const tier = asPermissionTier(props.tier) ?? 'view_only'\n\n // 档位被外部改回(如迁移/其他端变更)时收起弹层与确认态\n useEffect(() => {\n setOpen(false)\n setAcknowledged(false)\n setConfirming(false)\n }, [tier])\n\n const choose = (id: string): void => {\n setOpen(false)\n if (id === tier) return\n if (id === 'full_access') {\n setAcknowledged(false)\n setConfirming(true)\n return\n }\n props.onSelect(id as PermissionTier)\n }\n const closeConfirm = (): void => {\n setAcknowledged(false)\n setConfirming(false)\n }\n const confirmFullAccess = (): void => {\n if (!acknowledged) return\n closeConfirm()\n props.onSelect('full_access')\n }\n\n const items = PERMISSION_TIERS.map((t) => ({ id: t, label: TIER_LABELS[t], icon: TIER_GLYPHS[t]() }))\n const Glyph = TIER_GLYPHS[tier] ?? GlyphViewOnly\n\n return (\n <>\n <P.Menu\n open={open}\n items={items}\n selectedId={tier}\n onSelect={choose}\n onClose={() => { setOpen(false) }}\n side=\"top\"\n anchor={(\n <button\n type=\"button\"\n className=\"dsgc-permtrigger\"\n aria-label={'权限模式:' + TIER_LABELS[tier]}\n title={TIER_DESCRIPTIONS[tier]}\n disabled={confirming}\n onClick={() => { setOpen(!open) }}\n >\n <span className=\"dsgc-permicon\" aria-hidden>{Glyph()}</span>\n <span className=\"dsgc-permlabel\">{TIER_LABELS[tier]}</span>\n <span className={'dsgc-permchevron' + (open ? ' open' : '')} aria-hidden>{Icon(P.IconChevronDownOutline14, 14)}</span>\n </button>\n )}\n />\n <P.RiskConfirmation\n open={confirming}\n title={CONFIRM_TEXT.title}\n description={CONFIRM_TEXT.description}\n acknowledgeLabel={CONFIRM_TEXT.acknowledge}\n cancelLabel={CONFIRM_TEXT.cancel}\n closeLabel=\"关闭\"\n confirmLabel={CONFIRM_TEXT.enable}\n acknowledged={acknowledged}\n onAcknowledgedChange={setAcknowledged}\n onCancel={closeConfirm}\n onConfirm={confirmFullAccess}\n />\n </>\n )\n}\n","/**\n * 消息输入编辑器组件\n * @module dsh-group-chat/client/components\n */\n\nimport type { ReactNode, KeyboardEvent as ReactKeyboardEvent, ClipboardEvent as ReactClipboardEvent, DragEvent as ReactDragEvent } from 'react'\nimport { Icon, P } from '../lib/ui.ts'\nimport { PermissionSelect } from './PermissionSelect.tsx'\nimport { escapeRegExp, type ClientSnapshot, type SnapshotRole } from '../lib/model.ts'\nimport type { AtToken } from '../../shared/file-mention-grammar.ts'\n\ninterface ComposerProps {\n snap: ClientSnapshot\n sess: ClientSnapshot['sessions'][number] | null\n group: ClientSnapshot['groups'][number]\n enabledRoles: SnapshotRole[]\n participants: string[]\n mentionedRoles: SnapshotRole[]\n busyNow: boolean\n input: string\n mention: AtToken | null\n mentionCandidates: SnapshotRole[]\n mentionIdxC: number\n fileCandidates: Array<{ path: string, isDir: boolean }>\n fileSearchError: string | null\n fileSearchLoading: boolean\n rounds: number\n err: string\n atBottom: boolean\n bubblesLength: number\n inputRef: React.RefObject<HTMLDivElement>\n scrollRef: React.RefObject<HTMLDivElement>\n setMentionIdx: (val: number) => void\n setRounds: (val: number) => void\n togglePart: (rid: string) => void\n onInputCE: () => void\n onInputKeyDown: (e: ReactKeyboardEvent<HTMLDivElement>) => void\n onPasteCE: (e: ReactClipboardEvent<HTMLDivElement>) => void\n onDropCE: (e: ReactDragEvent<HTMLDivElement>) => void\n onDragOverCE: (e: ReactDragEvent<HTMLDivElement>) => void\n insertChip: (role: SnapshotRole) => void\n insertFileChip: (path: string, kind: 'file' | 'directory') => void\n sendMsg: () => Promise<void>\n stopRun: () => Promise<void>\n mutate: (args: Record<string, unknown>) => Promise<unknown>\n setMention: (val: AtToken | null) => void\n}\n\nexport function Composer(props: ComposerProps): ReactNode {\n const {\n snap,\n sess,\n group,\n enabledRoles,\n participants,\n mentionedRoles,\n busyNow,\n input,\n mention,\n mentionCandidates,\n mentionIdxC,\n fileCandidates,\n fileSearchError,\n fileSearchLoading,\n rounds,\n err,\n atBottom,\n bubblesLength,\n inputRef,\n scrollRef,\n setMentionIdx,\n setRounds,\n togglePart,\n onInputCE,\n onInputKeyDown,\n onPasteCE,\n onDropCE,\n onDragOverCE,\n insertChip,\n insertFileChip,\n sendMsg,\n stopRun,\n mutate,\n setMention,\n } = props\n\n return (\n <div className=\"dsgc-composer\">\n {!atBottom && bubblesLength\n ? (\n <div className=\"dsgc-tobottom\">\n <button\n type=\"button\"\n className=\"dsgc-tobtn\"\n onClick={() => { const el = scrollRef.current; if (el) el.scrollTo({ top: el.scrollHeight, behavior: 'smooth' }) }}\n >\n {Icon(P.IconChevronDownOutline14, 14)}回到底部\n </button>\n </div>\n )\n : null}\n {err ? <div className=\"dsgc-err\">{err}</div> : null}\n <div className=\"dsgc-parts\">\n <span className=\"dsgc-partslabel\">参与角色</span>\n {mentionedRoles.length\n ? <span className=\"dsgc-partslabel\">已 @ {mentionedRoles.map((r) => r.name).join('、')}(本轮仅被点名成员发言)</span>\n : enabledRoles.length\n ? enabledRoles.map((r) => (\n <button\n key={r.id}\n type=\"button\"\n className={'dsgc-partchip' + (participants.includes(r.id) ? ' on' : '')}\n onClick={() => togglePart(r.id)}\n disabled={busyNow}\n title={busyNow ? '对话进行中,暂停调整' : '点击切换本轮是否参与'}\n >\n <span className=\"dsgc-chipdot\" style={{ background: r.color || '#888' }} />\n {r.name}\n </button>\n ))\n : <span className=\"dsgc-hint\">还没有启用的角色,请在右侧添加</span>}\n </div>\n <div className=\"dsgc-card\">\n <div className=\"dsgc-mentionwrap\">\n {mention !== null && mention.query === '' && mentionCandidates.length > 0\n ? (\n <div className=\"dsgc-mention\" role=\"listbox\">\n {mentionCandidates.map((r, i) => (\n <button\n key={r.id}\n type=\"button\"\n className={'dsgc-mentionitem' + (i === mentionIdxC ? ' on' : '')}\n role=\"option\"\n aria-selected={i === mentionIdxC ? 'true' : 'false'}\n onMouseDown={(e) => { e.preventDefault() }}\n onClick={() => { insertChip(r) }}\n onMouseEnter={() => setMentionIdx(i)}\n >\n <span className=\"dsgc-chipdot\" style={{ background: r.color || '#888' }} />\n <span className=\"dsgc-mentionname\">{r.name}</span>\n <span className=\"dsgc-mentionmodel\">{r.provider} / {r.model}</span>\n </button>\n ))}\n <span className=\"dsgc-mentionhint\">↑↓ 选择 · Enter/Tab 插入</span>\n </div>\n )\n : mention !== null && mention.query !== ''\n ? (\n <div className=\"dsgc-mention dsgc-mention-file\" role=\"listbox\">\n {fileCandidates.length\n ? fileCandidates.map((item, i) => (\n <button\n key={item.path}\n type=\"button\"\n className={'dsgc-mentionitem' + (i === mentionIdxC ? ' on' : '')}\n role=\"option\"\n aria-selected={i === mentionIdxC ? 'true' : 'false'}\n onMouseDown={(e) => { e.preventDefault() }}\n onClick={() => {\n insertFileChip(item.path, item.isDir ? 'directory' : 'file')\n }}\n onMouseEnter={() => setMentionIdx(i)}\n >\n <span className={'dsgc-fileglyph' + (item.isDir ? ' dir' : ' file')} aria-hidden=\"true\">\n {item.isDir\n ? <P.FileTypeIcon kind=\"folder\" size={16} />\n : <P.FileTypeIcon path={item.path} size={16} />}\n </span>\n <span className=\"dsgc-mentionname\">{item.path}</span>\n {item.isDir ? <span className=\"dsgc-filedrill\">{Icon(P.IconChevronRightOutline14, 12)}</span> : null}\n </button>\n ))\n : fileSearchLoading\n ? <div className=\"dsgc-mentionitem dsgc-hint\">检索中…</div>\n : fileSearchError\n ? <div className=\"dsgc-mentionitem dsgc-hint\">{fileSearchError}</div>\n : <div className=\"dsgc-mentionitem dsgc-hint\">无匹配文件</div>}\n <span className=\"dsgc-mentionhint\">\n {fileSearchLoading && fileCandidates.length\n ? '检索中…'\n : fileCandidates.some((f) => f.isDir)\n ? '↑↓ 选择 · Enter 插入 · Tab 进入目录 · Esc 关闭'\n : '↑↓ 选择 · Enter 插入 · Esc 关闭'}\n </span>\n </div>\n )\n : null}\n {!input.trim()\n ? <div className=\"dsgc-ph\" aria-hidden=\"true\">发消息给全群,@成员 点名让其回应(留空则让角色自由讨论)…</div>\n : null}\n <div\n className=\"dsgc-edit\"\n ref={inputRef}\n contentEditable\n suppressContentEditableWarning\n role=\"textbox\"\n aria-multiline=\"true\"\n aria-label=\"群聊消息输入框\"\n onInput={onInputCE}\n onKeyDown={onInputKeyDown}\n onPaste={onPasteCE}\n onDrop={onDropCE}\n onDragOver={onDragOverCE}\n onBlur={() => { setMention(null) }}\n />\n </div>\n <div className=\"dsgc-sendrow\">\n <PermissionSelect\n tier={group.permissionTier}\n onSelect={(tier) => { void mutate({ op: 'setPermissionTier', groupId: group.id, tier }) }}\n />\n <span style={{ flex: 1 }} />\n <div className=\"dsgc-rounds\" title=\"自由讨论的轮数(1–10):一轮 = 全体参与角色按顺序各发言一次\">\n <button type=\"button\" className=\"dsgc-roundbtn\" aria-label=\"减少轮数\" disabled={rounds <= 1} onClick={() => { setRounds(Math.max(1, rounds - 1)) }}>\n {Icon(P.IconChevronLeftOutline14, 12)}\n </button>\n <span className=\"dsgc-roundnum\" title=\"轮数\">{rounds}</span>\n <button type=\"button\" className=\"dsgc-roundbtn\" aria-label=\"增加轮数\" disabled={rounds >= 10} onClick={() => { setRounds(Math.min(10, rounds + 1)) }}>\n {Icon(P.IconChevronRightOutline14, 12)}\n </button>\n <span style={{ padding: '0 6px 0 2px' }}>轮</span>\n </div>\n {busyNow\n ? (\n <P.Button variant=\"outline\" className=\"dsgc-stopbtn\" onClick={() => { void stopRun() }}>\n {Icon(P.IconStopFill16, 16)}停止\n </P.Button>\n )\n : (\n <P.Button variant=\"primary\" onClick={() => { void sendMsg() }} disabled={(!participants.length && !mentionedRoles.length) || !sess}>\n {Icon(P.IconSendOutline16, 16)}发送\n </P.Button>\n )}\n </div>\n </div>\n </div>\n )\n}\n","/**\n * 中央会话面板组件\n * @module dsh-group-chat/client/components\n */\n\nimport type { ReactNode } from 'react'\nimport { Icon, P } from '../lib/ui.ts'\nimport { MessageFlow } from './MessageFlow.tsx'\nimport { Composer } from './Composer.tsx'\nimport type { ClientSnapshot, SnapshotRole } from '../lib/model.ts'\nimport type { AtToken } from '../../shared/file-mention-grammar.ts'\n\ninterface ChatPanelProps {\n snap: ClientSnapshot\n sess: ClientSnapshot['sessions'][number] | null\n group: ClientSnapshot['groups'][number]\n enabledRoles: SnapshotRole[]\n participants: string[]\n mentionedRoles: SnapshotRole[]\n busyNow: boolean\n input: string\n mention: AtToken | null\n mentionCandidates: SnapshotRole[]\n mentionIdxC: number\n fileCandidates: Array<{ path: string, isDir: boolean }>\n fileSearchError: string | null\n fileSearchLoading: boolean\n rounds: number\n err: string\n atBottom: boolean\n topicDraft: string | null\n msgById: Record<string, ClientSnapshot['messages'][number]>\n navOpen: boolean\n asideOpen: boolean\n inputRef: React.RefObject<HTMLDivElement>\n scrollRef: React.RefObject<HTMLDivElement>\n setTopicDraft: (val: string | null) => void\n setConfirmClear: (val: boolean) => void\n setMentionIdx: (val: number) => void\n setRounds: (val: number) => void\n setNavOpen: (val: boolean) => void\n setAsideOpen: (val: boolean) => void\n togglePart: (rid: string) => void\n onMsgsScroll: () => void\n onInputCE: () => void\n onInputKeyDown: (e: React.KeyboardEvent<HTMLDivElement>) => void\n onPasteCE: (e: React.ClipboardEvent<HTMLDivElement>) => void\n onDropCE: (e: React.DragEvent<HTMLDivElement>) => void\n onDragOverCE: (e: React.DragEvent<HTMLDivElement>) => void\n insertChip: (role: SnapshotRole) => void\n insertFileChip: (path: string, kind: 'file' | 'directory') => void\n sendMsg: () => Promise<void>\n stopRun: () => Promise<void>\n action: (payload: Record<string, unknown>) => Promise<unknown>\n mutate: (args: Record<string, unknown>) => Promise<unknown>\n setMention: (val: AtToken | null) => void\n}\n\nexport function ChatPanel(props: ChatPanelProps): ReactNode {\n const {\n snap,\n sess,\n group,\n enabledRoles,\n participants,\n mentionedRoles,\n busyNow,\n input,\n mention,\n mentionCandidates,\n mentionIdxC,\n fileCandidates,\n fileSearchError,\n fileSearchLoading,\n rounds,\n err,\n atBottom,\n topicDraft,\n msgById,\n navOpen,\n asideOpen,\n inputRef,\n scrollRef,\n setTopicDraft,\n setConfirmClear,\n setMentionIdx,\n setRounds,\n setNavOpen,\n setAsideOpen,\n togglePart,\n onMsgsScroll,\n onInputCE,\n onInputKeyDown,\n onPasteCE,\n onDropCE,\n onDragOverCE,\n insertChip,\n insertFileChip,\n sendMsg,\n stopRun,\n action,\n mutate,\n setMention,\n } = props\n\n const commitTopic = (): void => {\n if (topicDraft !== null && sess && topicDraft !== sess.topic) void mutate({ op: 'setTopic', sessionId: sess.id, topic: topicDraft })\n setTopicDraft(null)\n }\n\n const bubbles = (\n <MessageFlow\n snap={snap}\n sess={sess}\n busyNow={busyNow}\n msgById={msgById}\n action={action}\n />\n )\n\n return (\n <section className=\"dsgc-chat\">\n {/* 接缝收合钮 */}\n <button\n type=\"button\"\n className={'dsgc-seambtn left' + (navOpen ? '' : ' closed')}\n aria-label={navOpen ? '收起群组导航栏' : '展开群组导航栏'}\n title={navOpen ? '收起群组导航栏' : '展开群组导航栏'}\n aria-expanded={navOpen}\n onClick={() => { setNavOpen(!navOpen) }}\n >\n {Icon(P.IconChevronLeftOutline14, 16)}\n </button>\n <button\n type=\"button\"\n className={'dsgc-seambtn right' + (asideOpen ? '' : ' closed')}\n aria-label={asideOpen ? '收起成员与工作区栏' : '展开成员与工作区栏'}\n title={asideOpen ? '收起成员与工作区栏' : '展开成员与工作区栏'}\n aria-expanded={asideOpen}\n onClick={() => { setAsideOpen(!asideOpen) }}\n >\n {Icon(P.IconChevronRightOutline14, 16)}\n </button>\n \n <div className=\"dsgc-chathead\">\n {sess ? <span className=\"dsgc-sess-title\" title={'当前会话:' + sess.name}>{sess.name}</span> : null}\n <input\n className=\"dsgc-topic\"\n value={topicDraft === null ? (sess ? sess.topic : '') : topicDraft}\n placeholder=\"设置本会话主题(可选)…\"\n onChange={(e) => { setTopicDraft(e.target.value) }}\n onBlur={commitTopic}\n onKeyDown={(e) => { if (e.key === 'Enter') (e.target as HTMLInputElement).blur() }}\n />\n <P.Button variant=\"ghost\" size=\"sm\" className=\"dsgc-clearbtn\" title=\"清空当前会话的消息记录\" onClick={() => { if (sess) setConfirmClear(true) }}>\n 清空\n </P.Button>\n </div>\n \n <div className=\"dsgc-msgs\" ref={scrollRef} onScroll={onMsgsScroll}>\n {sess && sess.messageIds.length > 0\n ? bubbles\n : (\n <div className=\"dsgc-empty\">\n {Icon(P.IconSparkle16, 20)}\n <div className=\"dsgc-emptytitle\">{sess && sess.topic ? '「' + sess.topic + '」' : '会话已就绪'}</div>\n <div className=\"dsgc-hint\">\n {enabledRoles.length\n ? '发送消息开始讨论;@成员 点名让其优先回应;留空直接发送可让角色自由讨论——每轮全体参与角色按顺序各发言一次,可用右下角轮数控制(1–10 轮)'\n : '先在右侧添加角色(每个角色可绑定不同模型),再回到这里发起讨论。'}\n </div>\n </div>\n )}\n </div>\n \n <Composer\n snap={snap}\n sess={sess}\n group={group}\n enabledRoles={enabledRoles}\n participants={participants}\n mentionedRoles={mentionedRoles}\n busyNow={busyNow}\n input={input}\n mention={mention}\n mentionCandidates={mentionCandidates}\n mentionIdxC={mentionIdxC}\n fileCandidates={fileCandidates}\n fileSearchError={fileSearchError}\n fileSearchLoading={fileSearchLoading}\n rounds={rounds}\n err={err}\n atBottom={atBottom}\n bubblesLength={sess?.messageIds.length || 0}\n inputRef={inputRef}\n scrollRef={scrollRef}\n setMentionIdx={setMentionIdx}\n setRounds={setRounds}\n togglePart={togglePart}\n onInputCE={onInputCE}\n onInputKeyDown={onInputKeyDown}\n onPasteCE={onPasteCE}\n onDropCE={onDropCE}\n onDragOverCE={onDragOverCE}\n insertChip={insertChip}\n insertFileChip={insertFileChip}\n sendMsg={sendMsg}\n stopRun={stopRun}\n mutate={mutate}\n setMention={setMention}\n />\n </section>\n )\n}\n","/**\n * 群聊面板核心状态管理 hook\n * @module dsh-group-chat/client/hooks\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { api } from '../lib/api.ts'\nimport type { ClientSnapshot, ModelsResponse, RoleDraft } from '../lib/model.ts'\nimport type { AtToken } from '../../shared/file-mention-grammar.ts'\n\nexport interface MutateResponse {\n ok: boolean\n snapshot?: ClientSnapshot\n lastCreated?: ClientSnapshot['lastCreated']\n error?: string\n}\n\nexport interface ActionOk {\n ok: boolean\n error?: string\n}\n\n/**\n * 面板切换缓存(模块级,跨挂载存活):main 为 keyed 槽,主会话⇄群聊切换会\n * 整体卸载重挂面板组件;缓存最近快照与选中项让重挂载瞬时恢复上次视图,\n * 挂载后的 state 拉取 / SSE 首帧再行校正(本机回路往返仅数毫秒)。\n */\nlet cachedSnap: ClientSnapshot | null = null\nlet cachedGid: string | null = null\nlet cachedSid: string | null = null\n\nexport function useGroupChatState() {\n // 核心数据快照(重挂载时从缓存瞬时恢复,消除切换闪现的加载态)\n const [snap, setSnap] = useState<ClientSnapshot | null>(() => cachedSnap)\n\n // 选中状态\n const [gid, setGid] = useState<string | null>(() => cachedGid)\n const [sid, setSid] = useState<string | null>(() => cachedSid)\n\n /** 已应用过的 lastCreated 会话标记:只在标记变化(真正的新建)时跟随选中,\n 而不是每帧都把视图拽回「最近创建的会话」(流式期间每 120ms 一帧)。 */\n const appliedCreatedRef = useRef<string | null>(cachedSnap?.lastCreated?.sessionId ?? null)\n\n /** 快照落地统一口:写状态 + 写切换缓存。 */\n const applySnap = useCallback((s: ClientSnapshot): void => {\n cachedSnap = s\n setSnap(s)\n }, [])\n\n /** 选中项统一口:写状态 + 写切换缓存(重挂载恢复到用户离开时的位置)。 */\n const selectGroup = useCallback((v: string): void => {\n cachedGid = v\n setGid(v)\n }, [])\n const selectSession = useCallback((v: string): void => {\n cachedSid = v\n setSid(v)\n }, [])\n \n // UI 状态\n const [search, setSearch] = useState('')\n const [collapsedGroups, setCollapsedGroups] = useState<Set<string>>(() => new Set())\n const [asideOpen, setAsideOpen] = useState(true)\n const [navOpen, setNavOpen] = useState(true)\n const [atBottom, setAtBottom] = useState(true)\n \n // 编辑态\n const [renameDraft, setRenameDraft] = useState<{ kind: 'group' | 'session', id: string, value: string } | null>(null)\n const [confirmDel, setConfirmDel] = useState<{ kind: 'group' | 'session', id: string } | null>(null)\n const [confirmClear, setConfirmClear] = useState(false)\n const [topicDraft, setTopicDraft] = useState<string | null>(null)\n const [wsDraft, setWsDraft] = useState<string | null>(null)\n \n // 角色编辑\n const [roleDraft, setRoleDraft] = useState<RoleDraft | null>(null)\n const [roleFormError, setRoleFormError] = useState('')\n const [models, setModels] = useState<ModelsResponse | null>(null)\n const [modelsError, setModelsError] = useState<string | null>(null)\n \n // 文件浏览器\n const [fileBrowser, setFileBrowser] = useState<{ open: boolean, loading: boolean, list: import('../../core/types.ts').BrowseResult | null, error: string } | null>(null)\n \n // 参与角色选择\n const [partsSel, setPartsSel] = useState<string[] | null>(null)\n const [rounds, setRounds] = useState(1)\n \n // 输入与 @提及\n const [input, setInput] = useState('')\n const [mention, setMention] = useState<AtToken | null>(null)\n const [mentionIdx, setMentionIdx] = useState(0)\n \n // 错误提示\n const [err, setErr] = useState('')\n \n // Refs\n const inputRef = useRef<HTMLDivElement | null>(null)\n const sendingRef = useRef(false)\n const scrollRef = useRef<HTMLDivElement | null>(null)\n\n // 初始加载 + SSE 订阅\n useEffect(() => {\n let live = true\n api.state().then((s) => {\n if (live && s && (s as ClientSnapshot).ok) applySnap(s as ClientSnapshot)\n }).catch(() => { /* SSE 会重试 */ })\n const events = new EventSource('/api/group-chat/events')\n events.onmessage = (message) => {\n try {\n const s = JSON.parse(message.data) as ClientSnapshot\n if (!live || !s || !s.ok) return\n // lastCreated 仅在变化时跟随选中(新建群组/会话的定位信号);\n // 帧里重复携带的旧标记不再反复重置视图\n if (s.lastCreated && s.lastCreated.sessionId && s.lastCreated.sessionId !== appliedCreatedRef.current) {\n appliedCreatedRef.current = s.lastCreated.sessionId\n selectGroup(s.lastCreated.groupId)\n selectSession(s.lastCreated.sessionId)\n setPartsSel(null)\n }\n applySnap(s)\n } catch { /* ignore malformed frame */ }\n }\n return () => {\n live = false\n events.close()\n }\n }, [applySnap, selectGroup, selectSession])\n\n // API 操作封装\n const action = useCallback(async (payload: Record<string, unknown>): Promise<unknown> => {\n try {\n return await api.action(payload)\n } catch (e) {\n setErr(String((e && (e as Error).message) || e))\n return null\n }\n }, [])\n\n const mutate = async (args: Record<string, unknown>): Promise<MutateResponse | null> => {\n setErr('')\n const res = await action(Object.assign({ kind: 'mutate' }, args)) as MutateResponse | null\n if (res && res.ok && res.snapshot) {\n // 响应里的 lastCreated 是服务端当前值(未必由本次调用产生)——同样只在\n // 变化时跟随选中,避免改名/改配置等普通 mutate 把视图拽走\n if (res.lastCreated && res.lastCreated.sessionId && res.lastCreated.sessionId !== appliedCreatedRef.current) {\n appliedCreatedRef.current = res.lastCreated.sessionId\n selectGroup(res.lastCreated.groupId)\n selectSession(res.lastCreated.sessionId)\n setPartsSel(null)\n }\n applySnap(res.snapshot)\n if (res.snapshot.error) setErr(res.snapshot.error)\n }\n return res\n }\n\n return {\n // 状态\n snap,\n setSnap: applySnap,\n gid,\n setGid: selectGroup,\n sid,\n setSid: selectSession,\n search,\n setSearch,\n collapsedGroups,\n setCollapsedGroups,\n renameDraft,\n setRenameDraft,\n confirmDel,\n setConfirmDel,\n confirmClear,\n setConfirmClear,\n roleDraft,\n setRoleDraft,\n roleFormError,\n setRoleFormError,\n models,\n setModels,\n modelsError,\n setModelsError,\n fileBrowser,\n setFileBrowser,\n wsDraft,\n setWsDraft,\n partsSel,\n setPartsSel,\n rounds,\n setRounds,\n input,\n setInput,\n err,\n setErr,\n topicDraft,\n setTopicDraft,\n mention,\n setMention,\n mentionIdx,\n setMentionIdx,\n asideOpen,\n setAsideOpen,\n navOpen,\n setNavOpen,\n atBottom,\n setAtBottom,\n // Refs\n inputRef,\n sendingRef,\n scrollRef,\n // 方法\n action,\n mutate,\n }\n}\n","/**\n * Vendored @file token grammar from dsh-file-reference (browser-safe, zero Node API).\n * \n * Sourced from @deepseek-ai/dsh-file-reference/lib/types/grammar.js\n * Cannot import directly due to client bundle purity gate (dsh-client-bundle-purity).\n * \n * @module dsh-group-chat/shared\n */\n\nexport interface AtToken {\n /** Full matched prefix including @ and optional quotes */\n prefix: string\n /** Query fragment after @ (unquoted content) */\n query: string\n /** Whether the token uses quoted form @\"...\" */\n quoted: boolean\n}\n\nexport interface FileCandidate {\n kind: 'file' | 'directory'\n path: string\n}\n\n/**\n * Extract active @token at cursor position.\n * Matches @ at word boundary (line start or after whitespace).\n * \n * @param line - Current line text\n * @param cursor - Cursor offset in line\n * @returns Token or undefined if no active @token at cursor\n */\nexport function activeAtToken(line: string, cursor: number): AtToken | undefined {\n const before = line.slice(0, cursor)\n \n // Try quoted @\"... first (more specific)\n const quotedMatch = /(?:^|\\s)@\"([^\"]*)$/.exec(before)\n if (quotedMatch) {\n const prefix = quotedMatch[0].trimStart()\n return {\n prefix,\n query: quotedMatch[1],\n quoted: true,\n }\n }\n\n // Then try plain @...\n const plainMatch = /(?:^|\\s)@([^\\s@]*)$/.exec(before)\n if (plainMatch) {\n const prefix = plainMatch[0].trimStart()\n return {\n prefix,\n query: plainMatch[1],\n quoted: false,\n }\n }\n\n return undefined\n}\n\n/**\n * Format file/directory candidate as @mention text.\n * \n * @param candidate - File or directory to format\n * @param preserveQuote - Keep quotes even when unnecessary (for drill-down continuity)\n * @returns Formatted @path or undefined for invalid paths\n */\nexport function formatFileMention(candidate: FileCandidate, preserveQuote: boolean): string | undefined {\n const { path } = candidate\n\n // Reject control characters and embedded quotes\n if (/[\\x00-\\x1F\"]/.test(path)) return undefined\n\n const needsQuote = /\\s/.test(path)\n const useQuote = needsQuote || preserveQuote\n\n if (candidate.kind === 'file') {\n return useQuote ? `@\"${path}\"` : `@${path}`\n } else {\n // Directory: trailing slash, quote stays open for drill-down\n return useQuote ? `@\"${path}/` : `@${path}/`\n }\n}\n","/**\n * 通用工具函数\n * @module dsh-group-chat/client/utils\n */\n\nimport { createElement } from 'react'\nimport { flushSync } from 'react-dom'\nimport { createRoot } from 'react-dom/client'\nimport { FileTypeIcon } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { activeAtToken, type AtToken } from '../../shared/file-mention-grammar.ts'\n\n/** HTML 转义(芯片以 execCommand('insertHTML') 注入,角色名需转义)。 */\nexport function escapeHtml(v: string): string {\n return String(v).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"')\n}\n\n/**\n * execCommand 集中封装。它已被 Web 平台标记 @deprecated(ts 6387 编辑器提示),\n * 但仍是唯一能让 contenteditable 的 DOM 编辑进入浏览器原生 undo 栈的同步 API\n * (自研 undo 栈或引入 Lexical/ProseMirror 类框架代价更大;取舍见 DESIGN.md\n * Composer 契约)。经中间别名擦除废弃标记,全部调用走本封装,不在调用处散布提示。\n */\ntype ExecCommandFn = (commandId: string, showUI?: boolean, value?: string) => boolean\nlet execCommandFn: ExecCommandFn | undefined\nexport function execCommand(commandId: 'delete' | 'insertHTML' | 'insertText' | 'insertLineBreak', value?: string): boolean {\n execCommandFn ??= (document as unknown as { execCommand: ExecCommandFn }).execCommand\n return execCommandFn.call(document, commandId, false, value)\n}\n\n/**\n * contenteditable 输入区 → 纯文本序列化(发送/参与判定的唯一事实源):\n * 文本节点原样;<br> → 换行;角色芯片(.dsgc-chipin[data-role-id])展开回「@名字␠」;\n * 文件芯片(.dsgc-chipin[data-kind=file])展开回「@path」或「@\"path with spaces\"」;\n * DIV/P 块前补换行(防粘贴残留的块级包裹)。\n */\nexport function serializeInput(root: HTMLElement): string {\n const walk = (node: Node): string => {\n if (node.nodeType === Node.TEXT_NODE) return node.nodeValue || ''\n if (node.nodeType !== Node.ELEMENT_NODE) return ''\n const el = node as HTMLElement\n if (el.tagName === 'BR') return '\\n'\n if (el.classList.contains('dsgc-chipin')) {\n // 角色芯片\n if (el.dataset.roleId) {\n return '@' + (el.dataset.name || '') + ' '\n }\n // 文件芯片\n if (el.dataset.kind === 'file') {\n const path = el.dataset.path || ''\n const needsQuote = /\\s/.test(path)\n return needsQuote ? `@\"${path}\"` : `@${path}`\n }\n }\n const sep = /^(DIV|P)$/.test(el.tagName) ? '\\n' : ''\n return sep + Array.from(el.childNodes).map(walk).join('')\n }\n return Array.from(root.childNodes).map(walk).join('')\n}\n\n/** @角色芯片的 HTML(原子元素:contenteditable=false + draggable,退格整删)。 */\nexport function chipHtml(role: { id: string, name: string, color?: string }): string {\n const c = escapeHtml(role.color || '#888')\n return '<span class=\"dsgc-chipin\" data-role-id=\"' + escapeHtml(role.id) + '\" data-name=\"' + escapeHtml(role.name) + '\" style=\"--role-color:' + c + '\" contenteditable=\"false\" draggable=\"true\">' +\n '<span class=\"dsgc-chipdot\" style=\"background:' + c + '\"></span>' + escapeHtml(role.name) + '</span>'\n}\n\n/** 把宿主 FileTypeIcon 渲成静态 SVG,再塞进 insertHTML(与检索列表同一套字形)。 */\nfunction fileTypeIconMarkup(path: string, kind: 'file' | 'directory'): string {\n if (typeof document === 'undefined') return ''\n const host = document.createElement('span')\n const root = createRoot(host)\n try {\n flushSync(() => {\n root.render(kind === 'directory'\n ? createElement(FileTypeIcon, { kind: 'folder', size: 14 })\n : createElement(FileTypeIcon, { path, size: 14 }))\n })\n return host.innerHTML\n } finally {\n root.unmount()\n }\n}\n\n/** @文件芯片的 HTML(原子元素:contenteditable=false + draggable,退格整删)。 */\nexport function fileChipHtml(path: string, kind: 'file' | 'directory'): string {\n const basename = path.split('/').pop() || path\n const dir = kind === 'directory'\n return '<span class=\"dsgc-chipin dsgc-chipin-file\" data-kind=\"file\"' + (dir ? ' data-dir=\"1\"' : '') + ' data-path=\"' + escapeHtml(path) + '\" contenteditable=\"false\" draggable=\"true\">' +\n '<span class=\"dsgc-chipglyph\" aria-hidden=\"true\">' + fileTypeIconMarkup(path, kind) + '</span>' + escapeHtml(basename) + '</span>'\n}\n\n/**\n * 光标前的活跃 @token(角色或文件弹层触发判定)。\n * \n * @returns AtToken 对象,包含 prefix/query/quoted;无返回 null\n */\nexport function queryAtCaret(): AtToken | null {\n const sel = window.getSelection()\n if (!sel || !sel.isCollapsed || sel.rangeCount === 0) return null\n const node = sel.anchorNode\n if (!node || node.nodeType !== Node.TEXT_NODE) return null\n const before = (node.nodeValue || '').slice(0, sel.anchorOffset)\n return activeAtToken(before, before.length) || null\n}\n","/**\n * 消息输入相关 hooks\n * @module dsh-group-chat/client/hooks\n */\n\nimport { useCallback, useEffect, type ClipboardEvent as ReactClipboardEvent, type DragEvent as ReactDragEvent, type KeyboardEvent as ReactKeyboardEvent } from 'react'\nimport { execCommand, queryAtCaret, serializeInput, chipHtml, fileChipHtml } from '../utils/utils.ts'\nimport type { AtToken } from '../../shared/file-mention-grammar.ts'\nimport type { SnapshotRole } from '../lib/model.ts'\n\nexport function useComposerEffects(\n inputRef: React.RefObject<HTMLDivElement>,\n scrollRef: React.RefObject<HTMLDivElement>,\n input: string,\n atBottom: boolean,\n snap: unknown,\n) {\n // 贴底时新内容自动跟随滚动\n const onMsgsScroll = useCallback(() => {\n const el = scrollRef.current\n if (!el) return\n const isAtBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 60\n return isAtBottom\n }, [scrollRef])\n\n useEffect(() => {\n const el = scrollRef.current\n if (el && atBottom) el.scrollTop = el.scrollHeight\n }, [snap, atBottom, scrollRef])\n\n // composer 输入框随内容自适应高度\n useEffect(() => {\n const el = inputRef.current\n if (!el) return\n el.style.height = 'auto'\n el.style.height = Math.min(180, Math.max(36, el.scrollHeight)) + 'px'\n }, [input, inputRef])\n\n return { onMsgsScroll }\n}\n\nexport function useComposerInput(\n inputRef: React.RefObject<HTMLDivElement>,\n setInput: (val: string) => void,\n setMention: (val: AtToken | null) => void,\n setMentionIdx: (val: number) => void,\n) {\n /** 从 DOM 同步 input 状态(序列化) */\n const syncFromDOM = useCallback((): void => {\n const el = inputRef.current\n if (!el) return\n setInput(serializeInput(el))\n }, [inputRef, setInput])\n\n const onInputCE = useCallback((): void => {\n syncFromDOM()\n setMention(queryAtCaret())\n setMentionIdx(0)\n }, [syncFromDOM, setMention, setMentionIdx])\n\n /** 粘贴/拖放强制纯文本 */\n const onPasteCE = useCallback((e: ReactClipboardEvent<HTMLDivElement>): void => {\n e.preventDefault()\n const text = e.clipboardData.getData('text/plain')\n if (text) execCommand('insertText', text)\n }, [])\n\n const onDragOverCE = useCallback((e: ReactDragEvent<HTMLDivElement>): void => {\n e.preventDefault()\n }, [])\n\n const onDropCE = useCallback((e: ReactDragEvent<HTMLDivElement>): void => {\n e.preventDefault()\n const text = e.dataTransfer.getData('text/plain')\n if (text) execCommand('insertText', text)\n }, [])\n\n return {\n syncFromDOM,\n onInputCE,\n onPasteCE,\n onDragOverCE,\n onDropCE,\n }\n}\n\nexport function useMentionChip(\n inputRef: React.RefObject<HTMLDivElement>,\n setMention: (val: AtToken | null) => void,\n setMentionIdx: (val: number) => void,\n syncFromDOM: () => void,\n) {\n /** 弹层候选 → 删掉光标前的 @词、插入原子芯片 + 尾随空格 */\n const insertChip = useCallback((role: SnapshotRole): void => {\n const el = inputRef.current\n const sel = window.getSelection()\n if (!el || !sel) return\n if (!sel.anchorNode || !el.contains(sel.anchorNode)) return\n el.focus({ preventScroll: true })\n \n // 1. 删除光标前的 @token(包括引号)\n const node = sel.anchorNode\n if (node.nodeType === Node.TEXT_NODE) {\n const text = node.nodeValue || ''\n const off = sel.anchorOffset\n const before = text.slice(0, off)\n // 匹配 @词 或 @\"词\n const m = /(?:^|\\s)@(\"?)([^\"\\s@]*)$/.exec(before)\n if (m) {\n const prefixLen = m[1] ? 2 : 1 // @\" 或 @\n const queryLen = m[2].length\n const start = off - prefixLen - queryLen\n if (start >= 0) {\n const range = document.createRange()\n range.setStart(node, start)\n range.setEnd(node, off)\n sel.removeAllRanges()\n sel.addRange(range)\n execCommand('delete')\n }\n }\n }\n \n // 2. 插入芯片\n execCommand('insertHTML', chipHtml(role).replace('class=\"dsgc-chipin\"', 'class=\"dsgc-chipin\" data-new=\"\"'))\n const chip = el.querySelector<HTMLElement>('.dsgc-chipin[data-new]')\n if (!chip) return\n \n // 3. 选区显式钉到芯片之后,再补尾随空格\n const after = document.createRange()\n after.setStartAfter(chip)\n after.collapse(true)\n sel.removeAllRanges()\n sel.addRange(after)\n execCommand('insertText', ' ')\n chip.removeAttribute('data-new')\n setMention(null)\n setMentionIdx(0)\n syncFromDOM()\n }, [inputRef, setMention, setMentionIdx, syncFromDOM])\n\n const insertFileChip = useCallback((path: string, kind: 'file' | 'directory'): void => {\n const el = inputRef.current\n const sel = window.getSelection()\n if (!el || !sel) return\n if (!sel.anchorNode || !el.contains(sel.anchorNode)) return\n el.focus({ preventScroll: true })\n \n // 1. 删除光标前的 @token(包括引号)\n const node = sel.anchorNode\n if (node.nodeType === Node.TEXT_NODE) {\n const text = node.nodeValue || ''\n const off = sel.anchorOffset\n const before = text.slice(0, off)\n // 匹配 @词 或 @\"词\n const m = /(?:^|\\s)@(\"?)([^\"\\s@]*)$/.exec(before)\n if (m) {\n const prefixLen = m[1] ? 2 : 1 // @\" 或 @\n const queryLen = m[2].length\n const start = off - prefixLen - queryLen\n if (start >= 0) {\n const range = document.createRange()\n range.setStart(node, start)\n range.setEnd(node, off)\n sel.removeAllRanges()\n sel.addRange(range)\n execCommand('delete')\n }\n }\n }\n \n // 2. 插入文件芯片\n execCommand('insertHTML', fileChipHtml(path, kind).replace('class=\"dsgc-chipin dsgc-chipin-file\"', 'class=\"dsgc-chipin dsgc-chipin-file\" data-new=\"\"'))\n const chip = el.querySelector<HTMLElement>('.dsgc-chipin[data-new]')\n if (!chip) return\n \n // 3. 选区显式钉到芯片之后,再补尾随空格\n const after = document.createRange()\n after.setStartAfter(chip)\n after.collapse(true)\n sel.removeAllRanges()\n sel.addRange(after)\n execCommand('insertText', ' ')\n chip.removeAttribute('data-new')\n setMention(null)\n setMentionIdx(0)\n syncFromDOM()\n }, [inputRef, setMention, setMentionIdx, syncFromDOM])\n\n return { insertChip, insertFileChip }\n}\n\nexport function useInputKeyboard(\n mention: AtToken | null,\n mentionCandidates: SnapshotRole[],\n mentionIdxC: number,\n setMentionIdx: (val: number | ((prev: number) => number)) => void,\n insertChip: (role: SnapshotRole) => void,\n insertFileChip: (path: string, kind: 'file' | 'directory') => void,\n fileCandidates: Array<{ path: string; isDir: boolean }>,\n setMention: (val: AtToken | null) => void,\n sendMsg: () => Promise<void>,\n) {\n const onInputKeyDown = useCallback((e: ReactKeyboardEvent<HTMLDivElement>): void => {\n // IME 组合中的按键不参与任何快捷逻辑\n if (e.nativeEvent.isComposing || e.keyCode === 229) return\n \n // 角色模式(裸 @):Enter/Tab 插入角色芯片\n if (mention !== null && mention.query === '' && mentionCandidates.length) {\n if (e.key === 'ArrowDown') {\n e.preventDefault()\n setMentionIdx((mentionIdxC + 1) % mentionCandidates.length)\n return\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault()\n setMentionIdx((mentionIdxC - 1 + mentionCandidates.length) % mentionCandidates.length)\n return\n }\n if ((e.key === 'Enter' && !e.shiftKey) || e.key === 'Tab') {\n e.preventDefault()\n insertChip(mentionCandidates[mentionIdxC])\n return\n }\n }\n \n // 文件模式(@ + query):Enter 插入文件/Tab 钻入目录/Esc 关闭\n if (mention !== null && mention.query !== '' && fileCandidates.length) {\n if (e.key === 'ArrowDown') {\n e.preventDefault()\n setMentionIdx((mentionIdxC + 1) % fileCandidates.length)\n return\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault()\n setMentionIdx((mentionIdxC - 1 + fileCandidates.length) % fileCandidates.length)\n return\n }\n const selectedItem = fileCandidates[mentionIdxC]\n if (selectedItem) {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n insertFileChip(selectedItem.path, selectedItem.isDir ? 'directory' : 'file')\n return\n }\n if (e.key === 'Tab' && selectedItem.isDir) {\n e.preventDefault()\n insertFileChip(selectedItem.path, 'directory')\n return\n }\n }\n if (e.key === 'Escape') {\n e.preventDefault()\n setMention(null)\n return\n }\n }\n \n if (e.key === 'Enter' && e.shiftKey) {\n e.preventDefault()\n execCommand('insertLineBreak')\n return\n }\n \n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n void sendMsg()\n }\n }, [mention, mentionCandidates, mentionIdxC, fileCandidates, setMentionIdx, insertChip, insertFileChip, setMention, sendMsg])\n\n return { onInputKeyDown }\n}\n","/**\n * 文件搜索 hook:防抖 + 取消过期请求 + 短缓存。\n * @module dsh-group-chat/client/hooks\n */\n\nimport { useEffect, useState } from 'react'\nimport { api } from '../lib/api.ts'\nimport type { AtToken } from '../../shared/file-mention-grammar.ts'\n\nexport interface FileCandidate {\n path: string\n isDir: boolean\n}\n\nexport interface FileSearchResult {\n fileCandidates: FileCandidate[]\n fileSearchError: string | null\n fileSearchLoading: boolean\n}\n\nconst DEBOUNCE_MS = 180\nconst CACHE_LIMIT = 20\nconst cache = new Map<string, FileCandidate[]>()\n\nfunction cacheGet(key: string): FileCandidate[] | undefined {\n const hit = cache.get(key)\n if (!hit) return undefined\n cache.delete(key)\n cache.set(key, hit)\n return hit\n}\n\nfunction cacheSet(key: string, value: FileCandidate[]): void {\n cache.delete(key)\n cache.set(key, value)\n if (cache.size > CACHE_LIMIT) {\n const oldest = cache.keys().next().value\n if (oldest !== undefined) cache.delete(oldest)\n }\n}\n\nfunction isAbort(err: unknown): boolean {\n return !!err && typeof err === 'object' && 'name' in err && (err as { name: string }).name === 'AbortError'\n}\n\n/**\n * 文件搜索:query 变化 180ms 内合并;过期 fetch 真正 abort;\n * 命中短缓存立刻出结果。离开文件模式才清空列表,避免每个按键闪「检索中」。\n */\nexport function useFileSearch(\n mention: AtToken | null,\n groupId: string | undefined,\n): FileSearchResult {\n const [fileCandidates, setFileCandidates] = useState<FileCandidate[]>([])\n const [fileSearchError, setFileSearchError] = useState<string | null>(null)\n const [fileSearchLoading, setFileSearchLoading] = useState(false)\n\n const query = mention && mention.query !== '' ? mention.query : null\n\n useEffect(() => {\n if (query === null || !groupId) {\n setFileCandidates([])\n setFileSearchError(null)\n setFileSearchLoading(false)\n return\n }\n\n const key = groupId + '\\0' + query\n const hit = cacheGet(key)\n if (hit) {\n setFileCandidates(hit)\n setFileSearchError(null)\n setFileSearchLoading(false)\n return\n }\n\n const controller = new AbortController()\n setFileSearchLoading(true)\n const timer = window.setTimeout(() => {\n void (async () => {\n try {\n const res = await api.action({\n kind: 'fileSearch',\n groupId,\n query,\n }, controller.signal) as { ok: true, candidates?: FileCandidate[] } | { ok: false, error?: string }\n\n if (controller.signal.aborted) return\n if (res.ok) {\n const next = res.candidates || []\n cacheSet(key, next)\n setFileCandidates(next)\n setFileSearchError(null)\n } else {\n setFileCandidates([])\n setFileSearchError(res.error || '文件检索失败')\n }\n } catch (err) {\n if (controller.signal.aborted || isAbort(err)) return\n setFileCandidates([])\n setFileSearchError(String(err))\n } finally {\n if (!controller.signal.aborted) setFileSearchLoading(false)\n }\n })()\n }, DEBOUNCE_MS)\n\n return () => {\n window.clearTimeout(timer)\n controller.abort()\n }\n }, [query, groupId])\n\n return { fileCandidates, fileSearchError, fileSearchLoading }\n}\n","/**\n * 提及状态 hook:封装角色/文件提及相关的派生状态计算\n * @module dsh-group-chat/client/hooks\n */\n\nimport { useMemo } from 'react'\nimport { escapeRegExp, type SnapshotRole } from '../lib/model.ts'\nimport type { AtToken } from '../../shared/file-mention-grammar.ts'\n\n/**\n * 计算角色提及候选列表\n * @param mention - 当前 @ token 状态\n * @param enabledRoles - 启用的角色列表\n * @returns 角色候选列表(仅在角色模式且 query 为空时返回)\n */\nexport function useMentionCandidates(\n mention: AtToken | null,\n enabledRoles: SnapshotRole[],\n): SnapshotRole[] {\n return useMemo(() => {\n // 角色模式:仅当 mention 存在且 query 为空时显示全部启用角色\n return mention !== null && mention.query === '' ? enabledRoles : []\n }, [mention, enabledRoles])\n}\n\n/**\n * 检测输入文本中被 @ 的角色\n * @param input - 输入文本\n * @param enabledRoles - 启用的角色列表\n * @returns 被提及的角色列表\n */\nexport function useMentionedRoles(\n input: string,\n enabledRoles: SnapshotRole[],\n): SnapshotRole[] {\n return useMemo(() => {\n return enabledRoles.filter((r) =>\n new RegExp('(^|\\\\s)@' + escapeRegExp(r.name) + '(?=\\\\s|$)').test(input)\n )\n }, [input, enabledRoles])\n}\n\n/**\n * 计算安全的候选索引(确保不越界)\n * @param candidatesLength - 候选列表长度\n * @param currentIndex - 当前索引\n * @returns 安全的索引值\n */\nexport function useSafeMentionIndex(\n candidatesLength: number,\n currentIndex: number,\n): number {\n return useMemo(() => {\n return candidatesLength ? Math.min(currentIndex, candidatesLength - 1) : 0\n }, [candidatesLength, currentIndex])\n}\n","/**\n * 主面板:三区工作台——左导航栏(搜索 + 群组→会话目录树)、中央会话流\n * (@成员 点名 + markdown 渲染 + 思考折叠)、右上下文栏(群成员角色卡 +\n * 工作区目录),右栏可收起,角色编辑走右侧滑出抽屉。\n *\n * 面板数据走 /api/group-chat/*(fetch + SSE),Host 半持有全部状态。\n * @module dsh-group-chat/client/panel\n */\n\nimport { useCallback, useEffect, useState, type ReactNode } from 'react'\nimport { Icon, P } from './lib/ui.ts'\nimport { api } from './lib/api.ts'\nimport { RoleDrawer } from './components/RoleDrawer.tsx'\nimport { NavPanel } from './components/NavPanel.tsx'\nimport { AsidePanel } from './components/AsidePanel.tsx'\nimport { ChatPanel } from './components/ChatPanel.tsx'\nimport { useGroupChatState, type ActionOk } from './hooks/useGroupChatState.ts'\nimport { useComposerEffects, useComposerInput, useMentionChip, useInputKeyboard } from './hooks/useComposer.ts'\nimport { useFileSearch } from './hooks/useFileSearch.ts'\nimport { useMentionCandidates, useMentionedRoles, useSafeMentionIndex } from './hooks/useMentionState.ts'\nimport { draftFromRole, blankDraft, groupById, roleById, sessById, type ClientSnapshot, type ModelsResponse, type SnapshotRole } from './lib/model.ts'\n\nexport function GroupChatPanel(): ReactNode {\n const state = useGroupChatState()\n const {\n snap,\n gid,\n setGid,\n sid,\n setSid,\n search,\n setSearch,\n collapsedGroups,\n setCollapsedGroups,\n renameDraft,\n setRenameDraft,\n confirmDel,\n setConfirmDel,\n confirmClear,\n setConfirmClear,\n roleDraft,\n setRoleDraft,\n roleFormError,\n setRoleFormError,\n models,\n setModels,\n modelsError,\n setModelsError,\n fileBrowser,\n setFileBrowser,\n wsDraft,\n setWsDraft,\n partsSel,\n setPartsSel,\n rounds,\n setRounds,\n input,\n setInput,\n err,\n setErr,\n topicDraft,\n setTopicDraft,\n mention,\n setMention,\n mentionIdx,\n setMentionIdx,\n asideOpen,\n setAsideOpen,\n navOpen,\n setNavOpen,\n atBottom,\n setAtBottom,\n inputRef,\n sendingRef,\n scrollRef,\n action,\n mutate,\n } = state\n\n // 瞬时通知(toast):key 为展示序号,同文案重复触发也会重启动画\n const [toast, setToast] = useState<{ text: string, seq: number } | null>(null)\n\n // ---- 所有 Hooks 必须在条件返回之前调用 ----\n // Composer effects\n const { onMsgsScroll } = useComposerEffects(inputRef, scrollRef, input, atBottom, snap)\n const { syncFromDOM, onInputCE, onPasteCE, onDragOverCE, onDropCE } = useComposerInput(inputRef, setInput, setMention, setMentionIdx)\n\n // 选中群组/会话解析(用于 hooks 依赖)\n let group = snap && gid ? groupById(snap, gid) : null\n if (!group && snap && snap.groups.length) group = snap.groups[0]\n let sess = snap && sid ? sessById(snap, sid) : null\n // 有效会话统一兜底(与渲染体一致):sid 未建立/未命中/跨群不匹配时取当前群组\n // 最后一个会话——必须在 busyNow 等 run 派生值之前完成,否则流式行/停止按钮\n // 在兜底视图(典型:host 重启后 lastCreated 为空、选中态从未建立)下永远失活\n if ((!sess || sess.groupId !== group?.id) && group && snap) {\n sess = group.sessionIds.length ? sessById(snap, group.sessionIds[group.sessionIds.length - 1]) : null\n }\n\n const enabledRoles = group ? group.roleIds.map((id) => roleById(snap!, id)).filter((r): r is SnapshotRole => !!r && r.enabled) : []\n const participants = partsSel || enabledRoles.map((r) => r.id)\n const busyNow = !!(sess && snap && snap.run.running && snap.run.sessionId === sess.id)\n\n // 查看即清:当前选中会话即 run.finished 所指会话 → 发 ackFinish 确认已读\n // (host 幂等清除 + 广播;覆盖点击/键盘/重挂恢复/lastCreated 定位全部选中路径)\n const finishedRun = snap ? snap.run.finished : null\n useEffect(() => {\n if (finishedRun && sess && finishedRun.sessionId === sess.id) void mutate({ op: 'ackFinish' })\n }, [finishedRun, sess])\n\n // 提及状态:角色候选、文件搜索、索引安全化\n const mentionCandidates = useMentionCandidates(mention, enabledRoles)\n const { fileCandidates, fileSearchError, fileSearchLoading } = useFileSearch(\n mention,\n group?.id,\n )\n const mentionIdxC = useSafeMentionIndex(\n mentionCandidates.length || fileCandidates.length,\n mentionIdx\n )\n \n const mentionedRoles = useMentionedRoles(input, enabledRoles)\n\n const { insertChip, insertFileChip } = useMentionChip(inputRef, setMention, setMentionIdx, syncFromDOM)\n\n const sendMsg = useCallback(async (): Promise<void> => {\n if (busyNow || !sess || sendingRef.current) return\n sendingRef.current = true\n try {\n const parts = mentionedRoles.length ? mentionedRoles.map((r) => r.id) : participants\n if (!parts.length) {\n setErr(mentionedRoles.length ? '' : '请至少选择一个参与角色(或在消息中 @成员)')\n if (!mentionedRoles.length) return\n }\n const res = await action({ kind: 'send', sessionId: sess.id, text: input, participantRoleIds: parts, rounds }) as ActionOk | null\n if (res && !res.ok && res.error) setErr(res.error)\n else if (res && res.ok) {\n const el = inputRef.current\n if (el) el.innerHTML = ''\n setInput('')\n setMention(null)\n setErr('')\n setAtBottom(true)\n syncFromDOM()\n }\n } finally {\n sendingRef.current = false\n }\n }, [busyNow, sess, sendingRef, mentionedRoles, participants, action, rounds, input, inputRef, setInput, setMention, setErr, setAtBottom, syncFromDOM])\n\n const { onInputKeyDown } = useInputKeyboard(mention, mentionCandidates, mentionIdxC, setMentionIdx, insertChip, insertFileChip, fileCandidates, setMention, sendMsg)\n\n // ---- 条件性早期返回 ----\n if (!snap) {\n return (\n <div className=\"dsgc-root\">\n <div className=\"dsgc-loading\">{Icon(P.IconLoadingOutline16, 16)}加载中…</div>\n </div>\n )\n }\n\n if (!group) {\n return (\n <div className=\"dsgc-root\">\n <div className=\"dsgc-loading\">暂无群组</div>\n </div>\n )\n }\n\n const msgById: Record<string, ClientSnapshot['messages'][number]> = {}\n for (const m of snap.messages) msgById[m.id] = m\n\n const togglePart = (rid: string): void => {\n const has = participants.includes(rid)\n setPartsSel(has ? participants.filter((x) => x !== rid) : participants.concat([rid]))\n }\n\n // 清空确认:不可清空(对话进行中)走 toast 提示,不再落到输入框上方的红字\n const doClear = async (): Promise<void> => {\n if (!sess) return\n if (busyNow) {\n setToast({ text: '对话进行中,需先停止才能清空', seq: Date.now() })\n return\n }\n const res = await mutate({ op: 'clearMessages', sessionId: sess.id })\n if (res && res.ok && res.snapshot && !res.snapshot.error) setConfirmClear(false)\n else if (res && res.snapshot && res.snapshot.error) {\n setErr('')\n setToast({ text: res.snapshot.error, seq: Date.now() })\n }\n }\n\n // ---- 动作 ----\n const fetchModels = async (): Promise<void> => {\n try {\n const m = await api.action({ kind: 'models' }) as ModelsResponse\n if (m && m.ok && Array.isArray(m.providers)) {\n setModels(m)\n setModelsError(null)\n return\n }\n setModelsError(m && m.error ? String(m.error) : '响应异常')\n } catch (e) {\n setModelsError(String((e && (e as Error).message) || e))\n }\n }\n\n const openRoleEditor = async (role: SnapshotRole | null): Promise<void> => {\n setErr('')\n setRoleFormError('')\n if (!models || modelsError) await fetchModels()\n setRoleDraft(role ? draftFromRole(role) : blankDraft())\n }\n\n const saveRole = async (): Promise<void> => {\n if (!roleDraft) return\n if (!roleDraft.name.trim()) {\n setRoleFormError('角色名称不能为空')\n return\n }\n if (!roleDraft.provider || !roleDraft.model) {\n setRoleFormError('请选择角色绑定的模型')\n return\n }\n const res = await mutate({ op: 'upsertRole', groupId: group.id, role: roleDraft })\n if (res && res.ok && res.snapshot && !res.snapshot.error) {\n setRoleDraft(null)\n setRoleFormError('')\n }\n }\n\n const stopRun = async (): Promise<void> => {\n await action({ kind: 'stop', sessionId: sess!.id })\n }\n\n const openBrowser = async (path: string | undefined): Promise<void> => {\n setFileBrowser({ open: true, loading: true, list: null, error: '' })\n try {\n const res = await api.action({ kind: 'browse', path: path || '' }) as import('../core/types.ts').BrowseResult\n if (res && res.ok) setFileBrowser({ open: true, loading: false, list: res, error: '' })\n else setFileBrowser({ open: true, loading: false, list: null, error: (res && res.error) || '浏览失败' })\n } catch (e) {\n setFileBrowser({ open: true, loading: false, list: null, error: String((e && (e as Error).message) || e) })\n }\n }\n\n const selectCurrentDir = (): void => {\n if (!fileBrowser || !fileBrowser.list || !group) return\n const path = fileBrowser.list.path!\n void mutate({ op: 'setWorkspaceDir', groupId: group.id, path })\n setWsDraft(null)\n setFileBrowser(null)\n }\n\n return (\n <div className=\"dsgc-root\">\n <NavPanel\n snap={snap}\n search={search}\n setSearch={setSearch}\n collapsedGroups={collapsedGroups}\n setCollapsedGroups={setCollapsedGroups}\n gid={group.id}\n sid={sess ? sess.id : sid}\n setGid={setGid}\n setSid={setSid}\n setPartsSel={setPartsSel}\n renameDraft={renameDraft}\n setRenameDraft={setRenameDraft}\n confirmDel={confirmDel}\n setConfirmDel={setConfirmDel}\n mutate={mutate}\n navOpen={navOpen}\n />\n <ChatPanel\n snap={snap}\n sess={sess}\n group={group}\n enabledRoles={enabledRoles}\n participants={participants}\n mentionedRoles={mentionedRoles}\n busyNow={busyNow}\n input={input}\n mention={mention}\n mentionCandidates={mentionCandidates}\n mentionIdxC={mentionIdxC}\n fileCandidates={fileCandidates}\n fileSearchError={fileSearchError}\n fileSearchLoading={fileSearchLoading}\n rounds={rounds}\n err={err}\n atBottom={atBottom}\n topicDraft={topicDraft}\n msgById={msgById}\n navOpen={navOpen}\n asideOpen={asideOpen}\n inputRef={inputRef}\n scrollRef={scrollRef}\n setTopicDraft={setTopicDraft}\n setConfirmClear={setConfirmClear}\n setMentionIdx={setMentionIdx}\n setRounds={setRounds}\n setNavOpen={setNavOpen}\n setAsideOpen={setAsideOpen}\n togglePart={togglePart}\n onMsgsScroll={() => {\n const isBottom = onMsgsScroll()\n if (isBottom !== undefined) setAtBottom(isBottom)\n }}\n onInputCE={onInputCE}\n onInputKeyDown={onInputKeyDown}\n onPasteCE={onPasteCE}\n onDropCE={onDropCE}\n onDragOverCE={onDragOverCE}\n insertChip={insertChip}\n insertFileChip={insertFileChip}\n sendMsg={sendMsg}\n stopRun={stopRun}\n action={action}\n mutate={mutate}\n setMention={setMention}\n />\n <AsidePanel\n snap={snap}\n group={group}\n asideOpen={asideOpen}\n wsDraft={wsDraft}\n setWsDraft={setWsDraft}\n fileBrowser={fileBrowser}\n setFileBrowser={setFileBrowser}\n mutate={mutate}\n openRoleEditor={openRoleEditor}\n openBrowser={openBrowser}\n selectCurrentDir={selectCurrentDir}\n />\n {sess && confirmClear\n ? (\n <P.Modal\n open\n onClose={() => { setConfirmClear(false) }}\n title=\"清空本会话的消息记录?\"\n closeLabel=\"关闭\"\n description={'会话「' + sess.name + '」的全部 ' + sess.messageIds.length + ' 条消息将被永久删除'}\n footer={(\n <>\n <P.Button variant=\"outline\" size=\"sm\" onClick={() => { setConfirmClear(false) }}>取消</P.Button>\n <P.Button variant=\"outline\" size=\"sm\" className=\"dsgc-stopbtn\" onClick={() => { void doClear() }}>清空</P.Button>\n </>\n )}\n >\n <ul className=\"dsgc-clearnotes\">\n <li>删除内容:本会话的用户消息与角色发言(含思考、工具调用记录),确认后立即落盘</li>\n <li>不可恢复:此操作没有回收站,也没有撤销</li>\n <li>不受影响:会话本身与主题、群成员角色、工作区目录、权限档位</li>\n </ul>\n </P.Modal>\n )\n : null}\n {toast\n ? (\n <P.Toast\n key={toast.seq}\n text={toast.text}\n icon={Icon(P.IconWarningOutline16, 16)}\n anchor={inputRef.current}\n onDone={() => { setToast(null) }}\n />\n )\n : null}\n {roleDraft\n ? (\n <RoleDrawer\n draft={roleDraft}\n set={setRoleDraft}\n models={models}\n modelsError={modelsError}\n onRetryModels={() => { void fetchModels() }}\n onSave={() => { void saveRole() }}\n onCancel={() => { setRoleDraft(null); setRoleFormError('') }}\n formError={roleFormError}\n />\n )\n : null}\n </div>\n )\n}\n","/**\n * 设置页:启停开关(settings.section 插槽)。写 host 的 group-chat 设置\n * 命名空间(settings.yaml 持久化)。\n * @module dsh-group-chat/client/settings\n */\n\nimport { useEffect, useState, type ReactNode } from 'react'\nimport type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client'\nimport { P } from '../lib/ui.ts'\n\n/** Host 侧注册的设置命名空间 shape。 */\ninterface GroupChatSettings {\n enabled?: boolean\n}\n\nexport function GroupChatSettingsSection(props: { settingsScope: SettingsScope<GroupChatSettings> }): ReactNode {\n const scope = props.settingsScope\n const [snap, setSnap] = useState<ReturnType<SettingsScope<GroupChatSettings>['getSnapshot']> | null>(null)\n const [pending, setPending] = useState(false)\n\n useEffect(() => {\n let live = true\n const read = (): void => {\n if (!live) return\n try {\n setSnap(scope.getSnapshot())\n } catch { /* ignore */ }\n }\n read()\n const off = scope.subscribe(read)\n return () => {\n live = false\n off()\n }\n }, [])\n\n const ready = snap !== null && snap.status === 'ready'\n const writable = ready ? snap.writable !== false : false\n const enabled = ready ? (snap.value && snap.value.enabled) !== false : true\n\n const toggle = async (): Promise<void> => {\n if (!writable || pending) return\n setPending(true)\n try {\n await scope.set('enabled', !enabled)\n } catch (e) {\n console.error('[dsh-group-chat] settings write failed', e)\n } finally {\n setPending(false)\n }\n }\n\n return (\n <div className=\"dgcs-page\">\n <div className=\"dgcs-head\">\n <h3 className=\"dgcs-title\">模型群聊</h3>\n <p className=\"dgcs-desc\">多模型角色群组对话面板:每个角色绑定不同的 provider/model;群组内多会话目录树管理,群内共享对话记录与工作区目录;消息以 markdown 渲染、支持思考折叠;输入框支持 @成员 / @文件。数据持久化于 ~/.dsh/storages/group-chat/,重启 dsh web 后恢复。</p>\n </div>\n <div className=\"dgcs-card\">\n <div className=\"dgcs-cardtext\">\n <div className=\"dgcs-cardtitle\">{enabled ? '已启用' : '已停用'}</div>\n <div className=\"dgcs-cardhint\">{writable ? (enabled ? '关闭后侧边栏将不再显示「群聊」入口,进行中的对话会被中止。' : '开启后侧边栏显示「群聊」入口。') : '当前设置不可写(可能被配置文件覆盖)。'}</div>\n </div>\n <P.Switch\n checked={enabled}\n onChange={() => { void toggle() }}\n disabled={!writable || pending}\n label=\"模型群聊启停\"\n title={pending ? '正在写入…' : enabled ? '点击停用' : '点击启用'}\n />\n </div>\n </div>\n )\n}\n","/**\n * 侧边栏入口图标。\n *\n * 整行命中层携带 “newSession” 类名:任务看板等 DOM 注入式面板用\n * [class*=\"newSession\"] 识别“侧边栏导航点击”并自动收起自己,与点击\n * “新建会话”行为一致——类名不可哈希化。\n * @module dsh-group-chat/client/glyph\n */\n\nimport type { ReactNode } from 'react'\n\nexport function Glyph(props: { size?: number }): ReactNode {\n const size = (props && props.size) || 18\n return (\n <span className=\"dsgc-entryOverlay newSession\">\n <span className=\"dsgc-entryIcon\">\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\n strokeWidth={1.8} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2\" />\n <circle cx={9} cy={7} r={4} />\n <path d=\"M23 21v-2a4 4 0 0 0-3-3.87\" />\n <path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\n </svg>\n </span>\n </span>\n )\n}\n","/**\n * dsh-group-chat — 浏览器半(web 客户端模块)。\n *\n * 经 window.__ModuleLoader__.load 注册(由 tsdown 预设的 banner/footer 闭包\n * 工厂外壳生成);factory 返回 Cordis 客户端插件:\n * - 「模型群聊」设置页(settings.section):启停开关,写 host 的 group-chat\n * 设置命名空间(settings.yaml 持久化)\n * - 启用时挂载:侧边栏「群聊」入口(sidebar.panellist)+ 中央主面板(main)\n * - 面板数据走 /api/group-chat/*(fetch + SSE),Host 半持有全部状态\n * - DSW 原语(@deepseek-ai/dsh-client-ui-primitives,shell 静态种子模块)\n * 提供按钮/输入/开关/菜单/图标与 MarkdownText 渲染器\n *\n * 设计契约(impeccable direction contract;seed key 76db9e37,surface roll\n * 第 4/6/1 手中用户锁定 C「三区工作台」,代码先行):\n * THESIS 三区工作台;FIRST VIEWPORT 左 232px 导航 + 中央会话流 + 右 304px\n * 上下文栏(窄容器覆盖式、可收起)。完整契约见 docs/DESIGN.md。\n *\n * @module dsh-group-chat/client\n */\n\nimport type { Context as ClientContext } from '@deepseek-ai/cordis'\nimport type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client'\n// Type-only:拉入浏览器面的 Context 合并(ctx.settingsScope)。\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\n// Type-only:拉入 ctx.slots 合并(renderer 自 0.1.2 起拥有槽位注册表)。\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\nimport { createElement as h } from 'react'\nimport { injectStyles } from './lib/styles.ts'\nimport { GroupChatPanel } from './GroupChatPanel.tsx'\nimport { GroupChatSettingsSection } from './components/GroupChatSettingsSection.tsx'\nimport { Glyph } from './components/Glyph.tsx'\n\n/** Host 侧注册的设置命名空间 shape 与命名名(与宿主半拼写同一值,两边不共享代码)。 */\ninterface GroupChatSettings {\n enabled?: boolean\n}\nconst SETTINGS_NAMESPACE = 'group-chat'\n\n/** Client plugin id. */\nexport const name = 'group-chat-client'\n\n/** Required services. */\nexport const inject = ['slots', 'settingsScope']\n\n/**\n * Shell 布局槽位的类型声明镜像(运行时由外壳的 layout/sidebar 包声明):\n * 中央主面板为 keyed 槽(按 key 挂载),侧边栏面板列表为 list 槽\n * (id + order + label)。参照 dsh-web 家族外部包的自声明模式。\n */\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface SlotMap {\n /** 中央主面板:按 key 挂载一个面板组件。 */\n 'main': { kind: 'keyed', scope: 'root', owner: Record<string, never> }\n /** 侧边栏面板列表行:图标 + 标签入口。 */\n 'sidebar.panellist': { kind: 'list', scope: 'root', owner: { size?: number } }\n }\n}\n\n/**\n * 客户端插件体:设置页常驻注册 + 启用门控挂载侧边栏入口与主面板。\n * @param ctx - client root context.\n */\nexport function apply(ctx: ClientContext): void {\n injectStyles()\n\n const scope: SettingsScope<GroupChatSettings> = ctx.settingsScope.bind({ namespace: SETTINGS_NAMESPACE })\n\n // 设置页常驻注册(禁用时也保留入口,便于重新启用)\n ctx.slots.inject('settings.section', () =>\n ctx.slots.register(\n {\n name: 'settings.section',\n id: 'dsh-group-chat',\n order: 60,\n label: () => '模型群聊',\n inject: () => ({ settingsScope: scope }),\n },\n (props: { settingsScope: SettingsScope<GroupChatSettings> }) => h(GroupChatSettingsSection, props),\n ),\n )\n\n // 启用门控:enabled 为 false 时卸载侧边栏入口与主面板\n let uiDisposer: (() => void) | undefined\n const mountUi = (): void => {\n if (uiDisposer !== undefined) return\n const disposers: (() => void)[] = []\n try {\n disposers.push(ctx.slots.inject('main', () =>\n ctx.slots.register({ name: 'main', key: 'group-chat' }, () => h(GroupChatPanel, null))))\n disposers.push(ctx.slots.inject('sidebar.panellist', () =>\n ctx.slots.register({ name: 'sidebar.panellist', id: 'group-chat', order: 50, label: '群聊' }, (props: { size?: number }) => h(Glyph, props))))\n } catch (e) {\n console.error('[dsh-group-chat] mount failed:', e)\n }\n uiDisposer = () => {\n uiDisposer = undefined\n for (const dispose of disposers.splice(0)) dispose()\n }\n }\n const syncEnabled = (): void => {\n const snapshot = scope.getSnapshot()\n const on = snapshot.status === 'ready'\n ? (snapshot.value && snapshot.value.enabled) !== false\n : snapshot.status === 'unavailable'\n if (on) mountUi()\n else if (uiDisposer !== undefined) uiDisposer()\n }\n scope.subscribe(syncEnabled)\n syncEnabled()\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASA,MAAM,SAAS;EAEf,MAAa,MAAM;GAEjB;GACA;GAGA;GACA;GACA;GAEA;GAKA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GAIA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAIA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAKA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAIA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GACA;GAEA;GAIA;GAGA;GACA;GAIA;GAEA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GAGA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GAEA;GAEA;GACA;GAEA;GACA;GACA;GAGA;GAKA;GACA;GAGA;GACA;GACA;GACA;GACA;G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"}
|