feat: 自定义窗口两种模式——新建专属对话 / 发送到已有会话(默认当前会话,可下拉选择)

This commit is contained in:
Aisland
2026-08-18 02:22:09 +08:00
parent 42645f2f51
commit 02d4f20020
6 changed files with 111 additions and 30 deletions
+35 -3
View File
@@ -263,7 +263,7 @@ function findSidebar(start: HTMLElement | null): HTMLElement | null {
const registryStore: { ids: string[]; listeners: Set<() => void> } = { ids: [], listeners: new Set() }
/** 自定义窗口 → 宿主会话桥(apply 时注入;不可用时 CustomPane 降级提示) */
let sessionBridge: { sessions: any; conversation: any } | null = null
let sessionBridge: { sessions: any; conversation: any; list: any } | null = null
/** 自定义窗口任务:新建一个专属会话,注入工作台背景 + 用户需求,并打开该会话 */
export async function createCustomSession(projectId: string, projectName: string, requirement: string): Promise<void> {
@@ -291,6 +291,25 @@ export async function createCustomSession(projectId: string, projectName: string
if (!sent) await b.conversation?.send?.(text)
}
/** 把自定义需求直接发到用户选定的已有会话(默认当前会话) */
export async function sendCustomToSession(sessionId: string, projectName: string, requirement: string): Promise<void> {
const b = sessionBridge
if (!b) throw new Error('bridge unavailable')
const text = [
'【工作台自定义窗口任务】',
'以下内容由 dsh-worktable(工作台)插件发送:用户正在自定义「' + projectName + '」项目中的一个窗口。',
'1. dsh-worktable 是侧边栏底部的自建「工作台」插件(官方文档没有它的说明,不了解之处可向用户提问);',
'2. 用户需求:' + requirement,
'3. 请帮助完成该窗口的自定义设计(内容/页面/实现方案),该窗口位于「' + projectName + '」项目内。',
].join('\n')
let sent = false
if (typeof b.conversation?.sendSession === 'function') {
try { await b.conversation.sendSession(sessionId, text); sent = true } catch { sent = false }
}
try { b.sessions.open?.(sessionId) } catch {}
if (!sent) await b.conversation?.send?.(text)
}
/** 会话作用域快照(模块级;apply 里订阅 ctx.sessions.list 写入,组件与引擎只读) */
const sessionScopeStore: {
snapshot: { sessionId: string; cwd: string; jobs: any[]; subagents: any[] } | null
@@ -411,6 +430,19 @@ function WorktableSection(props: any) {
]
},
currentProjectId: () => (splitStore.active && splitStore.spec ? splitStore.spec.id : null),
getSessions: () => {
try {
const snap = sessionBridge?.list?.getSnapshot?.()
const items = Array.isArray(snap?.items) ? snap.items : []
const current = snap?.current ?? ''
return items.map((it: any) => ({
id: it?.sessionId ?? it?.id ?? '',
title: it?.title ?? it?.name ?? it?.summary?.title ?? (it?.sessionId ?? it?.id ?? ''),
isCurrent: (it?.sessionId ?? it?.id) === current,
}))
} catch { return [] }
},
sendToSession: (sessionId, projectName, requirement) => sendCustomToSession(sessionId, projectName, requirement),
submit: (projectId, projectName, requirement) => createCustomSession(projectId, projectName, requirement),
},
})
@@ -1325,8 +1357,8 @@ function WorktableSection(props: any) {
export const inject = ['slots', 'locale', 'sessions', 'conversation']
export function apply(ctx: any) {
// 自定义窗口 → 新建会话桥:保存宿主 sessions/conversation 服务引用(模块级)
sessionBridge = { sessions: ctx.sessions ?? null, conversation: ctx.conversation ?? null }
// 自定义窗口 → 宿主会话桥:保存 sessions/conversation/list 服务引用(模块级)
sessionBridge = { sessions: ctx.sessions ?? null, conversation: ctx.conversation ?? null, list: ctx.sessions?.list ?? null }
ctx.effect(() => {
const style = document.createElement('style')