@yolk_vat-y/dsh-project-memory 0.4.2 → 0.4.4
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/CHANGELOG.md +34 -0
- package/README.md +33 -4
- package/README.zh-CN.md +34 -6
- package/client/client.js +709 -451
- package/client/client.js.map +1 -1
- package/package.json +9 -9
- package/src/client/TaskCommandNode.tsx +14 -22
- package/src/client/TaskComponents.tsx +341 -0
- package/src/client/TaskPanel.module.css +103 -40
- package/src/client/TaskPanel.tsx +104 -381
- package/src/client/locales.ts +6 -0
- package/src/client/task-data-store.ts +136 -0
- package/src/client/task-hooks.ts +169 -0
- package/src/client/task-ui-store.ts +118 -0
- package/src/commands/task-actions.js +9 -7
- package/src/commands/tasks.js +5 -3
- package/src/index.js +4 -3
- package/src/tools/task-tools.js +19 -0
- package/src/client/task-store.ts +0 -192
package/client/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["prev","useSyncExternalStore","IconCheckOutline16","css","IconPlayOutline16","useState","useRef","IconFolderOpenOutline16","IconChevronUpOutline14","Component","Button","IconRefreshOutline16","IconChevronDownOutline14","IconCloseOutline16","css","IconFolderOpenOutline16","createElement"],"sources":["../src/client/locales.ts","../src/client/task-store.ts","../src/client/TaskPanel.tsx","../src/client/TaskCommandNode.tsx","../src/client/client.ts"],"sourcesContent":["/**\n * Locale dictionaries for Task Panel\n */\nexport const zh = {\n 'panel.title': '工作流任务',\n 'panel.active': '进行中',\n 'panel.total': '总计',\n 'panel.minimize': '收起为顶部迷你条',\n 'panel.close': '关闭面板(隐藏,/task 可唤起)',\n 'panel.refresh': '同步最新任务',\n 'panel.style': '切换面板风格',\n 'style.native': '原生',\n 'style.glass': '玻璃',\n 'style.brutal': '粗野',\n 'style.mono': '终端',\n 'panel.syncing': '同步中…',\n 'panel.sync-failed': '同步失败',\n 'panel.empty': '暂无任务',\n 'panel.empty-desc': '让模型开始工作并维护 todo 清单后会自动建档',\n 'panel.no-session': '还没有会话',\n 'task.progress': '进度',\n 'task.steps': '步骤',\n 'task.files': '文件',\n 'task.current': '当前',\n 'task.title-edit': '双击修改标题',\n 'task.switch': '切换到此任务',\n 'task.unbind': '取消当前任务',\n 'task.archive': '归档',\n 'task.drag': '拖拽移动',\n 'step.completed': '已完成',\n 'step.in-progress': '进行中',\n 'step.pending': '待办',\n 'step.edit-hint': '双击编辑步骤文案;点击图标循环 待办/进行中/已完成',\n 'file.copy': '复制路径',\n 'file.copied': '已复制路径',\n 'minibar.current': '当前任务',\n 'minibar.click-expand': '点击展开并同步',\n 'minibar.tasks': '个任务',\n 'minibar.no-task': '暂无任务 · 点击查看',\n}\n\nexport const en = {\n 'panel.title': 'Task Flow',\n 'panel.active': 'Active',\n 'panel.total': 'Total',\n 'panel.minimize': 'Collapse to mini bar',\n 'panel.close': 'Close panel (hidden; /task reopens)',\n 'panel.refresh': 'Sync latest tasks',\n 'panel.style': 'Panel style',\n 'style.native': 'Native',\n 'style.glass': 'Glass',\n 'style.brutal': 'Brutal',\n 'style.mono': 'Mono',\n 'panel.syncing': 'Syncing…',\n 'panel.sync-failed': 'Sync failed',\n 'panel.empty': 'No Tasks',\n 'panel.empty-desc': 'Tasks are created automatically when the model maintains a todo list',\n 'panel.no-session': 'No session yet',\n 'task.progress': 'Progress',\n 'task.steps': 'Steps',\n 'task.files': 'Files',\n 'task.current': 'Current',\n 'task.title-edit': 'Double-click to rename',\n 'task.switch': 'Switch to this task',\n 'task.unbind': 'Unbind current task',\n 'task.archive': 'Archive',\n 'task.drag': 'Drag to move',\n 'step.completed': 'Completed',\n 'step.in-progress': 'In Progress',\n 'step.pending': 'Pending',\n 'step.edit-hint': 'Double-click to edit; click the icon to cycle status',\n 'file.copy': 'Copy path',\n 'file.copied': 'Path copied',\n 'minibar.current': 'Current task',\n 'minibar.click-expand': 'Click to expand & sync',\n 'minibar.tasks': 'tasks',\n 'minibar.no-task': 'No tasks · click to view',\n}\n\nexport type LocaleDict = typeof zh\n\nexport function createTranslate(dict: LocaleDict) {\n return (key: keyof LocaleDict, params?: Record<string, string | number>) => {\n let text = dict[key] ?? key\n if (params) {\n for (const [k, v] of Object.entries(params)) {\n text = text.replace(new RegExp(`\\\\{${k}\\\\}`, 'g'), String(v))\n }\n }\n return text\n }\n}\n","/**\n * Task Panel Client Store(自包含:不依赖宿主 store 包)\n * Reactive store for task list, bound task, UI state.\n * 数据由 /tasks、/task 命令执行结果(JSON 载荷)写入,localStorage 持久化 UI 状态。\n */\nimport { useSyncExternalStore } from 'react'\n\nexport interface TaskStep {\n content: string\n status: 'pending' | 'in_progress' | 'completed'\n}\n\nexport interface TaskFile {\n path: string\n line?: number\n}\n\nexport interface Task {\n id: string\n title: string\n steps: TaskStep[]\n files: TaskFile[]\n lastActiveAt: string\n updatedAt: string\n archived?: boolean\n}\n\nexport interface TaskPanelState {\n tasks: Task[]\n boundTaskId: string | null\n archivedCount: number\n // UI state\n expandedTaskIds: string[]\n panelPosition: { x: number; y: number }\n /** true = 折叠成顶部迷你条(仍可见、可拖拽)。 */\n minimized: boolean\n /** true = 彻底隐藏(无迷你条),仅可通过 /task /tasks 或重新加载唤起。 */\n closed: boolean\n /** 卡片强调色主题:native 或 accent 名(azure/violet/teal/rose)。 */\n theme: string\n lastUpdate: number\n}\n\n/** /tasks 命令响应(text)里夹带的 JSON 载荷结构。 */\nexport interface TaskPayload {\n tasks: Task[]\n boundId: string | null\n archived: number\n}\n\n/** 从命令输出文本中解析任务快照 JSON(支持 fenced ```json 块或尾部对象)。 */\nexport function parseTaskPayloadText(text?: string | null): TaskPayload | null {\n if (!text) return null\n let jsonBlock: string | null = null\n const fenced = text.match(/```(?:json)?\\s*\\n([\\s\\S]*?)\\n```/)\n if (fenced) jsonBlock = fenced[1]\n else {\n const lastBrace = text.lastIndexOf('{')\n if (lastBrace !== -1) jsonBlock = text.slice(lastBrace)\n }\n if (!jsonBlock) return null\n try {\n const data = JSON.parse(jsonBlock)\n if (!Array.isArray(data.tasks)) return null\n return { tasks: data.tasks, boundId: data.boundId ?? null, archived: data.archived ?? 0 }\n } catch {\n return null\n }\n}\n\nconst STORAGE_KEY = 'dsh-pm-task-panel-state'\n\nfunction defaultPosition(): { x: number; y: number } {\n if (typeof window !== 'undefined') {\n return { x: Math.max(16, window.innerWidth - 408), y: 72 }\n }\n return { x: 0, y: 0 }\n}\n\nfunction getDefaultState(): TaskPanelState {\n if (typeof window !== 'undefined') {\n try {\n const saved = localStorage.getItem(STORAGE_KEY)\n if (saved) {\n const parsed = JSON.parse(saved)\n return {\n tasks: Array.isArray(parsed.tasks) ? parsed.tasks : [],\n boundTaskId: parsed.boundTaskId ?? null,\n archivedCount: parsed.archivedCount ?? 0,\n expandedTaskIds: Array.isArray(parsed.expandedTaskIds) ? parsed.expandedTaskIds : [],\n panelPosition: parsed.panelPosition ?? defaultPosition(),\n minimized: parsed.minimized !== false, // 默认折叠成迷你条\n theme: typeof parsed.theme === 'string' ? parsed.theme : 'native',\n closed: !!parsed.closed,\n lastUpdate: parsed.lastUpdate ?? 0,\n }\n }\n } catch { /* corrupt state — fall through to defaults */ }\n }\n return {\n tasks: [],\n boundTaskId: null,\n archivedCount: 0,\n expandedTaskIds: [],\n panelPosition: defaultPosition(),\n minimized: true, // 默认折叠,不打扰\n closed: false,\n theme: 'native',\n lastUpdate: 0,\n }\n}\n\nfunction persist(state: TaskPanelState): void {\n if (typeof window === 'undefined') return\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(state))\n } catch { /* storage full/unavailable — non-fatal */ }\n}\n\nlet state: TaskPanelState = getDefaultState()\nconst listeners = new Set<() => void>()\n\nfunction setState(next: TaskPanelState): void {\n state = next\n persist(next)\n for (const listener of listeners) listener()\n}\n\nexport const taskStore = {\n subscribe(listener: () => void): () => void {\n listeners.add(listener)\n return () => { listeners.delete(listener) }\n },\n getSnapshot(): TaskPanelState {\n return state\n },\n actions: {\n setTasks(payload: { tasks: Task[]; boundTaskId: string | null; archivedCount: number }): void {\n const prev = state\n setState({\n ...prev,\n tasks: payload.tasks || [],\n boundTaskId: payload.boundTaskId ?? null,\n archivedCount: payload.archivedCount ?? 0,\n lastUpdate: Date.now(),\n })\n },\n toggleTaskExpanded(taskId: string): void {\n const prev = state\n const ids = prev.expandedTaskIds.includes(taskId)\n ? prev.expandedTaskIds.filter((id) => id !== taskId)\n : [...prev.expandedTaskIds, taskId]\n setState({ ...prev, expandedTaskIds: ids })\n },\n expandAll(): void {\n const prev = state\n setState({ ...prev, expandedTaskIds: prev.tasks.map((t) => t.id) })\n },\n setPanelPosition(pos: { x: number; y: number }): void {\n setState({ ...state, panelPosition: pos })\n },\n /** 展开面板(同时解除隐藏/折叠)。 */\n open(): void {\n setState({ ...state, minimized: false, closed: false })\n },\n /** 折叠成顶部迷你条(仍可见)。 */\n minimize(): void {\n setState({ ...state, minimized: true, closed: false })\n },\n /** 彻底隐藏(无迷你条);仅能通过 /task、/tasks 或重新加载唤起。 */\n close(): void {\n setState({ ...state, minimized: true, closed: true })\n },\n setTheme(theme: string): void {\n setState({ ...state, theme })\n },\n setMinimized(minimized: boolean): void {\n setState({ ...state, minimized, closed: minimized ? state.closed : false })\n },\n reset(): void {\n setState(getDefaultState())\n },\n },\n}\n\nexport function useTaskStore(): TaskPanelState {\n return useSyncExternalStore(taskStore.subscribe, taskStore.getSnapshot, taskStore.getSnapshot)\n}\n\nexport function useTaskActions() {\n return taskStore.actions\n}\n","/**\n * Task Panel — dsh web `shell.overlay` 浮动任务面板。\n *\n * 升级原 `/tasks` 文本输出为可交互卡片:\n * - 默认收成右侧浮标(不影响用户操作/不挡对话);\n * - 展开时通过宿主 `remote.commands.execute(sessionId, '/tasks')` 拉取最新快照\n * (命令只读,走 /tasks 同一数据源 = tasks.json,因此与模型维护的 todo 双向一致);\n * - 卡片内「切换 / 归档」执行 `/task switch|archive <id>`,服务端返回新快照 JSON,\n * 面板即时刷新,无需再跑一次 /tasks;\n * - 可拖拽(仅头部把手),位置持久化 localStorage。\n *\n * 依赖仅 react + @deepseek-ai/dsh-client-ui-primitives(宿主 seed 模块)。\n */\nimport { Component, useEffect, useRef, useState, type ReactNode } from 'react'\nimport {\n Button,\n IconChevronDownOutline14,\n IconChevronUpOutline14,\n IconCloseOutline16,\n IconRefreshOutline16,\n IconCheckOutline16,\n IconPlayOutline16,\n IconFolderOpenOutline16,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport { createTranslate, zh, en } from './locales.ts'\nimport { taskStore, useTaskStore, parseTaskPayloadText, type TaskStep } from './task-store.ts'\nimport css from './TaskPanel.module.css'\n\nconst NS = 'dsh-project-memory'\n\nfunction getT() {\n const locale = (typeof navigator !== 'undefined' && navigator.language.startsWith('zh')) ? zh : en\n return createTranslate(locale)\n}\n\nfunction timeAgo(iso?: string) {\n if (!iso) return ''\n const diff = Date.now() - new Date(iso).getTime()\n const m = Math.floor(diff / 60000)\n if (m < 1) return '刚刚'\n if (m < 60) return `${m}分钟前`\n const h = Math.floor(m / 60)\n if (h < 24) return `${h}小时前`\n return `${Math.floor(h / 24)}天前`\n}\n\nfunction StepIcon({ status }: { status: TaskStep['status'] }) {\n if (status === 'completed') return <IconCheckOutline16 className={css.stepDone} />\n if (status === 'in_progress') return <IconPlayOutline16 className={css.stepRun} />\n return <span className={css.stepPending} />\n}\n\nfunction useSessionId(ctx: any): string | null {\n const [, force] = useState(0)\n useEffect(() => {\n const list = ctx?.sessions?.list\n if (!list || typeof list.subscribe !== 'function') return\n return list.subscribe(() => force((n) => n + 1))\n }, [ctx])\n const snap = ctx?.sessions?.list?.getSnapshot?.()\n if (!snap) return null\n if (snap.current) return snap.current\n const first = Array.isArray(snap.items) ? snap.items.find((s: any) => !s.blank) ?? snap.items[0] : undefined\n return first?.sessionId ?? null\n}\n\n/** 行内编辑框:自动按内容增高(最多 160px),Enter 提交、Shift+Enter 换行、Esc 取消、失焦提交。 */\nfunction AutoEdit({ value, onCommit, onCancel, singleLine }: {\n value: string\n onCommit: (value: string) => void\n onCancel: () => void\n singleLine?: boolean\n}) {\n const [text, setText] = useState(value)\n const ref = useRef<HTMLTextAreaElement>(null)\n const settled = useRef(false)\n const once = (fn: () => void) => {\n if (settled.current) return\n settled.current = true\n fn()\n }\n\n const adjust = () => {\n const el = ref.current\n if (!el) return\n el.style.height = 'auto'\n el.style.height = `${Math.min(el.scrollHeight, 160)}px`\n }\n\n useEffect(() => {\n adjust()\n const el = ref.current\n el?.focus()\n el?.select()\n }, [])\n\n return (\n <textarea\n ref={ref}\n className={css.stepInput}\n rows={1}\n value={text}\n onChange={(e) => { setText(e.target.value); adjust() }}\n onBlur={() => once(() => onCommit(text))}\n onKeyDown={(e) => {\n if (e.key === 'Escape') {\n e.preventDefault()\n once(() => onCancel())\n } else if (e.key === 'Enter' && (singleLine || !e.shiftKey)) {\n e.preventDefault()\n once(() => onCommit(text))\n }\n }}\n />\n )\n}\n\n/** 折叠迷你条:可拖拽(按住拖动,轻点展开)。 */\nfunction MiniBar({ label, hint, position, theme, onMove, open }: {\n label: string\n hint: string\n position: { x: number; y: number }\n theme: string\n onMove: (pos: { x: number; y: number }) => void\n open: () => void\n}) {\n const barRef = useRef<HTMLDivElement>(null)\n const down = useRef<{ dx: number; dy: number; sx: number; sy: number; moved: boolean } | null>(null)\n\n const onMouseDown = (e: React.MouseEvent) => {\n if (e.button !== 0) return\n const rect = barRef.current?.getBoundingClientRect()\n if (!rect) return\n down.current = { dx: e.clientX - rect.left, dy: e.clientY - rect.top, sx: e.clientX, sy: e.clientY, moved: false }\n const onMoveEv = (ev: MouseEvent) => {\n const d = down.current\n if (!d) return\n if (!d.moved && Math.abs(ev.clientX - d.sx) + Math.abs(ev.clientY - d.sy) > 4) d.moved = true\n if (d.moved) {\n const w = barRef.current?.offsetWidth ?? 260\n const h = barRef.current?.offsetHeight ?? 34\n const x = Math.max(8, Math.min(window.innerWidth - w - 8, ev.clientX - d.dx))\n const y = Math.max(8, Math.min(window.innerHeight - h - 8, ev.clientY - d.dy))\n onMove({ x, y })\n }\n }\n const onUpEv = () => {\n const d = down.current\n down.current = null\n window.removeEventListener('mousemove', onMoveEv)\n window.removeEventListener('mouseup', onUpEv)\n if (d && !d.moved) open()\n }\n window.addEventListener('mousemove', onMoveEv)\n window.addEventListener('mouseup', onUpEv)\n }\n\n return (\n <div\n ref={barRef}\n className={css.miniBar}\n style={{ left: position.x, top: position.y }}\n data-theme={theme === 'native' ? undefined : theme}\n onMouseDown={onMouseDown}\n role=\"button\"\n title={hint}\n aria-label={hint}\n >\n <IconFolderOpenOutline16 className={css.miniIcon} />\n <span className={css.miniText}>{label}</span>\n <IconChevronUpOutline14 className={css.miniChevron} />\n </div>\n )\n}\n\n/**\n * 错误边界:任务面板渲染一旦抛错,不再让 shell.overlay 把整条条目退休\n * (宿主对崩溃条目会永久移除直到重载页面)。捕获后显示一个纯文本兜底,\n * 点击重新渲染。\n */\nclass PanelErrorBoundary extends Component<{ children: ReactNode }, { failed: boolean }> {\n state = { failed: false }\n\n static getDerivedStateFromError() {\n return { failed: true }\n }\n\n componentDidCatch(error: unknown) {\n console.warn('[dsh-project-memory] task panel render crashed (contained by boundary):', error)\n }\n\n render() {\n if (!this.state.failed) return this.props.children\n return (\n <button\n className={css.boundaryFallback}\n onClick={() => this.setState({ failed: false })}\n title=\"重新渲染任务面板\"\n >\n 任务面板(点击重试)\n </button>\n )\n }\n}\n\nexport function TaskPanelEntry({ ctx }: { ctx: any }) {\n return (\n <PanelErrorBoundary>\n <TaskPanelView ctx={ctx} />\n </PanelErrorBoundary>\n )\n}\n\nfunction TaskPanelView({ ctx }: { ctx: any }) {\n const t = getT()\n const state = useTaskStore()\n const sessionId = useSessionId(ctx)\n const [syncing, setSyncing] = useState(false)\n const [syncedAt, setSyncedAt] = useState(0)\n const [copiedPath, setCopiedPath] = useState<string | null>(null)\n const [syncError, setSyncError] = useState<string | null>(null)\n const panelRef = useRef<HTMLDivElement>(null)\n const drag = useRef<{ dx: number; dy: number } | null>(null)\n const copyTimer = useRef<number | undefined>(undefined)\n\n const actions = taskStore.actions\n\n const activeTasks = state.tasks.filter((task) => !task.archived)\n const boundTask = state.boundTaskId ? state.tasks.find((task) => task.id === state.boundTaskId) ?? null : null\n\n const applyPayload = (text?: string): boolean => {\n const parsed = parseTaskPayloadText(text)\n if (!parsed) return false\n actions.setTasks({ tasks: parsed.tasks, boundTaskId: parsed.boundId, archivedCount: parsed.archived })\n setSyncedAt(Date.now())\n setSyncError(null)\n return true\n }\n\n const runLine = async (line: string): Promise<boolean> => {\n const commands = ctx?.remote?.commands\n if (!sessionId || !commands || typeof commands.execute !== 'function') {\n setSyncError('no session / commands service')\n return false\n }\n let response: any\n try {\n response = await commands.execute(sessionId, line, [])\n } catch (err) {\n setSyncError(String(err?.message ?? err))\n return false\n }\n const envelope = response as { ok?: boolean; value?: any } | null | undefined\n const execution = envelope && typeof envelope === 'object' && 'value' in envelope ? envelope.value : envelope\n const result = execution?.result ?? execution\n if (result?.kind === 'error') {\n setSyncError(result.text ?? 'command error')\n return false\n }\n return applyPayload(result?.text)\n }\n\n const refresh = async (): Promise<void> => {\n if (syncing) return\n setSyncing(true)\n try {\n await runLine('/tasks')\n } finally {\n setSyncing(false)\n }\n }\n\n const handleAction = async (verb: 'switch' | 'archive', taskId: string): Promise<void> => {\n if (syncing) return\n setSyncing(true)\n try {\n await runLine(`/task ${verb} ${taskId}`)\n } finally {\n setSyncing(false)\n }\n }\n\n // —— 绑定卡片步骤编辑(双击改文案 / 点状态图标循环),与模型 todo_write 走同一数据 ——\n const [editing, setEditing] = useState<{ taskId: string; index: number; value: string } | null>(null)\n const STATUS_CYCLE = ['pending', 'in_progress', 'completed'] as const\n const pushSteps = (taskId: string, steps: TaskStep[]): void => {\n void runLine(`/task todos ${JSON.stringify(steps.map((s) => ({ content: s.content, status: s.status })))}`)\n }\n const cycleStatus = (taskId: string, index: number) => {\n const task = state.tasks.find((tt) => tt.id === taskId)\n if (!task) return\n const steps = task.steps || []\n const next = steps.map((s, i) => {\n if (i !== index) return s\n const cur = STATUS_CYCLE.indexOf(s.status)\n return { ...s, status: STATUS_CYCLE[(cur + 1) % STATUS_CYCLE.length] }\n })\n pushSteps(taskId, next)\n }\n const commitStepText = (taskId: string, index: number, value: string) => {\n const task = state.tasks.find((tt) => tt.id === taskId)\n const trimmed = value.trim()\n if (!task) { setEditing(null); return }\n const same = (task.steps || [])[index]?.content === trimmed\n setEditing(null)\n if (same || !trimmed) return\n const next = (task.steps || []).map((s, i) => (i === index ? { ...s, content: trimmed } : s))\n pushSteps(taskId, next)\n }\n\n // 绑定卡片标题双击改名\n const [editingTitle, setEditingTitle] = useState<{ taskId: string; value: string } | null>(null)\n const commitTitle = (taskId: string, value: string) => {\n const task = state.tasks.find((tt) => tt.id === taskId)\n const trimmed = value.trim()\n if (!task) { setEditingTitle(null); return }\n const same = task.title === trimmed\n setEditingTitle(null)\n if (same || !trimmed) return\n void runLine(`/task rename ${taskId} ${JSON.stringify(trimmed)}`)\n }\n\n const expand = () => {\n actions.open()\n // 已有 30s 内的快照就不重复执行 /tasks(避免会话里堆命令节点)\n if (Date.now() - Math.max(state.lastUpdate, syncedAt) > 30_000) {\n void refresh()\n }\n }\n\n const THEMES = ['native', 'glass', 'brutal', 'mono'] as const\n const style = (THEMES as readonly string[]).includes(state.theme) ? state.theme : 'native'\n const styleLabel = t(`style.${style}` as keyof typeof zh)\n const cycleTheme = () => {\n const i = THEMES.indexOf(style as (typeof THEMES)[number])\n actions.setTheme(THEMES[(i + 1) % THEMES.length])\n }\n\n const handleDragStart = (e: React.MouseEvent) => {\n if (e.target !== e.currentTarget) return\n const rect = panelRef.current?.getBoundingClientRect()\n if (!rect) return\n drag.current = { dx: e.clientX - rect.left, dy: e.clientY - rect.top }\n const onMove = (ev: MouseEvent) => {\n if (!drag.current) return\n const width = panelRef.current?.offsetWidth ?? 380\n const height = panelRef.current?.offsetHeight ?? 480\n const x = Math.max(8, Math.min(window.innerWidth - width - 8, ev.clientX - drag.current.dx))\n const y = Math.max(8, Math.min(window.innerHeight - 64, ev.clientY - drag.current.dy))\n actions.setPanelPosition({ x, y })\n }\n const onUp = () => {\n drag.current = null\n window.removeEventListener('mousemove', onMove)\n window.removeEventListener('mouseup', onUp)\n }\n window.addEventListener('mousemove', onMove)\n window.addEventListener('mouseup', onUp)\n }\n\n const copyPath = (path: string) => {\n if (copiedPath === path) return\n void navigator.clipboard?.writeText(path).catch(() => undefined)\n setCopiedPath(path)\n window.clearTimeout(copyTimer.current)\n copyTimer.current = window.setTimeout(() => setCopiedPath(null), 1200)\n }\n\n useEffect(() => () => window.clearTimeout(copyTimer.current), [])\n\n // 首次(store 从未同步过)自动拉一次快照(无论是否折叠,折叠条也要显示计数)\n useEffect(() => {\n if (!sessionId) return\n const snap = taskStore.getSnapshot()\n if (snap.lastUpdate === 0 && !snap.closed) {\n const timer = window.setTimeout(() => void refresh(), 300)\n return () => window.clearTimeout(timer)\n }\n return undefined\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [sessionId])\n\n // 彻底隐藏(关闭):不渲染任何东西;输入 /task、/tasks 会重新打开\n if (state.closed) {\n return null\n }\n\n // 折叠态:可拖拽的顶部迷你条(点击展开,点开即同步)\n if (state.minimized) {\n const label = boundTask\n ? `${t('minibar.current')}: ${boundTask.title}`\n : activeTasks.length > 0\n ? `${t('minibar.current')}: ${activeTasks.length} ${t('minibar.tasks')}`\n : t('minibar.no-task')\n return (\n <MiniBar\n label={label}\n hint={t('minibar.click-expand')}\n position={state.panelPosition}\n theme={style}\n onMove={(pos) => actions.setPanelPosition(pos)}\n open={expand}\n />\n )\n }\n\n const doneCount = activeTasks.filter((task) => {\n const steps = task.steps || []\n return steps.length > 0 && steps.every((s) => s.status === 'completed')\n }).length\n\n return (\n <div\n className={css.panel}\n ref={panelRef}\n style={{ left: state.panelPosition.x, top: state.panelPosition.y }}\n data-theme={style === 'native' ? undefined : style}\n >\n <div className={css.dragHandle} onMouseDown={handleDragStart} title={t('task.drag')}>\n <div className={css.handleGrip} />\n </div>\n <header className={css.header}>\n <div className={css.headerLeft}>\n <button\n type=\"button\"\n className={css.headerIconBtn}\n onClick={cycleTheme}\n title={styleLabel}\n aria-label={styleLabel}\n >\n <IconFolderOpenOutline16 className={css.headerIcon} />\n </button>\n <h2 className={css.headerTitle}>{t('panel.title')}</h2>\n </div>\n <div className={css.headerRight}>\n <span className={css.counts}>\n {activeTasks.length > 0\n ? `${t('panel.active')} ${activeTasks.length} · ${doneCount}/${activeTasks.length}`\n : ''}\n </span>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className={syncing ? css.spinning : undefined}\n onClick={() => void refresh()}\n disabled={syncing}\n aria-label={t('panel.refresh')}\n title={t('panel.refresh')}\n >\n <IconRefreshOutline16 />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => actions.minimize()}\n aria-label={t('panel.minimize')}\n title={t('panel.minimize')}\n >\n <IconChevronDownOutline14 />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => actions.close()}\n aria-label={t('panel.close')}\n title={t('panel.close')}\n >\n <IconCloseOutline16 />\n </Button>\n </div>\n </header>\n\n {!sessionId && <div className={css.notice}>{t('panel.no-session')}</div>}\n {syncError && <div className={css.notice}>{t('panel.sync-failed')}: {syncError}</div>}\n\n {activeTasks.length === 0 ? (\n <div className={css.emptyState}>\n <p className={css.emptyTitle}>{t('panel.empty')}</p>\n <p className={css.emptyDesc}>{t('panel.empty-desc')}</p>\n {syncing && <p className={css.syncHint}>{t('panel.syncing')}</p>}\n </div>\n ) : (\n <div className={css.taskList}>\n {activeTasks.map((task) => {\n const steps = task.steps || []\n const done = steps.filter((s) => s.status === 'completed').length\n const expanded = state.expandedTaskIds.includes(task.id)\n const isBound = state.boundTaskId === task.id\n const pct = steps.length > 0 ? Math.round((done / steps.length) * 100) : 0\n return (\n <article key={task.id} className={`${css.card}${isBound ? ` ${css.cardBound}` : ''}`}>\n <button\n className={css.cardHead}\n onClick={() => { if (editingTitle?.taskId === task.id) return; actions.toggleTaskExpanded(task.id) }}\n aria-expanded={expanded}\n >\n <div className={css.cardTitleRow}>\n {isBound && <span className={css.boundBadge}>{t('task.current')}</span>}\n {isBound && editingTitle?.taskId === task.id ? (\n <AutoEdit\n value={editingTitle.value}\n singleLine\n onCommit={(v) => commitTitle(task.id, v)}\n onCancel={() => setEditingTitle(null)}\n />\n ) : (\n <span\n className={`${css.cardTitle}${isBound ? ` ${css.cardTitleEditable}` : ''}`}\n title={isBound ? t('task.title-edit') : undefined}\n onDoubleClick={(e) => {\n e.preventDefault()\n e.stopPropagation()\n if (isBound) setEditingTitle({ taskId: task.id, value: task.title })\n }}\n >\n {task.title}\n </span>\n )}\n </div>\n <div className={css.cardMeta}>\n {steps.length > 0 && (\n <span className={css.progressText}>\n {done}/{steps.length}\n </span>\n )}\n <span className={css.updated}>{timeAgo(task.updatedAt || task.lastActiveAt)}</span>\n <span className={css.chevron}>\n {expanded ? <IconChevronUpOutline14 /> : <IconChevronDownOutline14 />}\n </span>\n </div>\n </button>\n {steps.length > 0 && (\n <div className={css.track}>\n <div className={css.trackFill} style={{ width: `${pct}%` }} />\n </div>\n )}\n {expanded && (\n <div className={css.cardBody}>\n <div className={css.section}>\n <div className={css.sectionLabel}>\n {t('task.steps')}\n {steps.length > 0 && <span className={css.sectionCount}>{steps.length}</span>}\n </div>\n {steps.length > 0 ? (\n <ol className={css.stepsList}>\n {steps.map((step, i) => {\n const isEditing = isBound && editing?.taskId === task.id && editing.index === i\n return (\n <li key={i} className={css.stepRow}>\n {isBound ? (\n <button\n type=\"button\"\n className={css.stepToggle}\n disabled={syncing}\n onClick={() => cycleStatus(task.id, i)}\n title={`${t('step.completed')}/${t('step.in-progress')}/${t('step.pending')}(点击切换)`}\n >\n <StepIcon status={step.status} />\n </button>\n ) : (\n <StepIcon status={step.status} />\n )}\n {isEditing ? (\n <AutoEdit\n value={editing!.value}\n onCommit={(v) => commitStepText(task.id, i, v)}\n onCancel={() => setEditing(null)}\n />\n ) : (\n <span\n className={`${css.stepContent}${step.status === 'completed' ? ` ${css.stepContentDone}` : ''}${step.status === 'in_progress' ? ` ${css.stepContentRun}` : ''}${isBound ? ` ${css.stepEditable}` : ''}`}\n title={isBound ? t('step.edit-hint') : undefined}\n onDoubleClick={() => {\n if (isBound) setEditing({ taskId: task.id, index: i, value: String(step.content ?? '') })\n }}\n >\n {step.content}\n </span>\n )}\n </li>\n )\n })}\n </ol>\n ) : (\n <div className={css.muted}>{t('panel.empty-desc')}</div>\n )}\n </div>\n\n {(task.files?.length ?? 0) > 0 && (\n <div className={css.section}>\n <div className={css.sectionLabel}>\n {t('task.files')}\n <span className={css.sectionCount}>{task.files.length}</span>\n </div>\n <ul className={css.filesList}>\n {task.files.slice(0, 12).map((file, i) => (\n <li key={i}>\n <button\n className={css.fileRow}\n onClick={() => copyPath(file.path)}\n title={`${t(copiedPath === file.path ? 'file.copied' : 'file.copy')}: ${file.path}${file.line ? `:${file.line}` : ''}`}\n >\n <span className={css.fileDot} />\n <span className={css.filePath}>{file.path}</span>\n {file.line && <span className={css.fileLine}>:{file.line}</span>}\n </button>\n </li>\n ))}\n {(task.files?.length ?? 0) > 12 && (\n <li className={css.muted}>… 共 {task.files.length} 个</li>\n )}\n </ul>\n </div>\n )}\n\n <div className={css.cardFooter}>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={isBound || syncing}\n onClick={() => void handleAction('switch', task.id)}\n >\n {t('task.switch')}\n </Button>\n {isBound && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={syncing}\n onClick={() => void runLine('/task unbind')}\n title={t('task.unbind')}\n >\n {t('task.unbind')}\n </Button>\n )}\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={syncing}\n onClick={() => void handleAction('archive', task.id)}\n >\n {t('task.archive')}\n </Button>\n </div>\n </div>\n )}\n </article>\n )\n })}\n {syncing && <div className={css.syncHint}>{t('panel.syncing')}</div>}\n </div>\n )}\n </div>\n )\n}\n","/**\n * /tasks、/task 命令在会话中的节点渲染器(conversation.chat.commandview,按命令名 key)。\n *\n * 目标:不再让大段文本+JSON 出现在会话里——\n * - 列表型(/tasks、无动词的 /task):只渲染一行极简“已同步 N 套”状态;\n * 同时把节点文本里的 JSON 载荷解析进浮动面板(侧边卡片由它驱动),\n * 面板若被收起则自动展开(等价“输入 /task 就看到卡片”)。\n * - 动作型(/task switch|archive):渲染一行操作结果(切换/归档反馈)。\n * - 错误/执行中:一行极简状态,不倾倒原文。\n */\nimport { useEffect } from 'react'\nimport { IconFolderOpenOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { parseTaskPayloadText, taskStore } from './task-store.ts'\nimport css from './TaskCommandNode.module.css'\n\n/** node = CommandRowOwnerProps.node(CommandNode: name / args / outcome{kind,text}) */\nexport function TaskCommandNode({ node }: { node?: any }) {\n const name = node?.name ?? 'task'\n const outcome = node?.outcome ?? null\n const args = typeof node?.args === 'string' ? node.args : ''\n const verb = args.trim().split(/\\s+/)[0] ?? ''\n const isList = name === 'tasks' || !verb\n const text = outcome?.text ?? ''\n\n const parsed = parseTaskPayloadText(text)\n\n // 载荷进面板 + 列表型自动展开面板。\n // 注意:命令节点先以“执行中”创建、完成后原地更新(同一组件实例),\n // 所以 effect 必须在结果文本变化时重跑,而不是只在挂载时跑一次。\n useEffect(() => {\n if (!parsed) return\n taskStore.actions.setTasks({\n tasks: parsed.tasks,\n boundTaskId: parsed.boundId,\n archivedCount: parsed.archived,\n })\n if (isList) taskStore.actions.open()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [text])\n\n // 执行中\n if (outcome === null) {\n return <div className={css.row} data-variant=\"running\">/{name} 执行中…</div>\n }\n\n // 失败:一行极简,不含大段原文\n if (outcome.kind === 'error') {\n const brief = String(text ?? '').split('\\n')[0].slice(0, 120)\n return <div className={css.row} data-variant=\"error\">/{name} 失败{brief ? `:${brief}` : ''}</div>\n }\n\n // 动作型:取第一段(操作反馈),不带 JSON\n if (!isList) {\n const note = String(text ?? '')\n .split(/\\n{2,}/)[0]\n .replace(/```.*$/s, '')\n .trim()\n .slice(0, 200)\n return <div className={css.row} data-variant=\"ok\">/{name} {note || '已完成'}</div>\n }\n\n // 列表型:一行极简状态\n const count = parsed ? parsed.tasks.length : 0\n const archived = parsed ? parsed.archived : 0\n const label = parsed\n ? `任务 ${count} 套${archived ? `(归档 ${archived})` : ''} · 已同步到任务面板`\n : `/${name} 已执行`\n return (\n <div className={css.row} data-variant=\"ok\">\n <IconFolderOpenOutline16 className={css.icon} />\n <span>{label}</span>\n </div>\n )\n}\n","/**\n * dsh-project-memory Client Entry\n *\n * dsh web (rc.1) 的 client 插件契约为 cordis client plugin:\n * export const inject = [<client 服务名>...]\n * export function apply(ctx) { ... }\n * 面板注册进 `shell.overlay`(Frame 级浮动层,additive 列表槽):\n * 该槽由 ui-layout 的 AppFrame 声明渲染(scope root,独立于滚动容器),\n * 默认 click-through,条目自身需开启 pointer-events。\n *\n * 只依赖宿主 seed 提供的模块(react / dsh-client-ui-primitives),\n * 数据经 remote.commands.execute 执行 /tasks 命令获取 JSON 快照。\n */\nimport { createElement } from 'react'\nimport { TaskPanelEntry } from './TaskPanel.tsx'\nimport { TaskCommandNode } from './TaskCommandNode.tsx'\n\nconst NS = 'dsh-project-memory'\n\nexport const name = NS\n\n/** Required client services: slots registry, session scopes, commands remote (data 通道). */\nexport const inject = ['slots', 'sessions', 'remote', 'remote.commands']\n\nexport function apply(ctx: any): void {\n const slots = ctx?.slots\n if (!slots || typeof slots.inject !== 'function') {\n console.warn(`[${NS}] host has no slots service — task panel disabled`)\n return\n }\n try {\n slots.inject('shell.overlay', () => slots.register(\n {\n name: 'shell.overlay',\n id: 'dsh-project-memory-task-panel',\n order: 100, // 浮层顺序:低于 toast/弹窗即可,越高越靠后渲染\n },\n () => createElement(TaskPanelEntry, { ctx })\n ))\n\n // 会话内 /tasks、/task 命令节点:按命令名 key 接管渲染,\n // 替换内置大段文本卡片(文本含 JSON 载荷,只有面板需要它)。\n const nodeKeys = ['tasks', 'task']\n for (const key of nodeKeys) {\n slots.inject('conversation.chat.commandview', () => slots.register(\n { name: 'conversation.chat.commandview', key },\n TaskCommandNode\n ))\n }\n } catch (err) {\n console.warn(`[${NS}] task panel registration failed:`, err)\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["useSyncExternalStore","useSyncExternalStore","useState","useRef","useCallback","IconCheckOutline16","css","IconPlayOutline16","useRef","IconFolderOpenOutline16","IconChevronUpOutline14","useState","IconChevronDownOutline14","Button","useState","Component","css","useRef","Button","IconFolderOpenOutline16","IconQuestionOutline14","IconChevronDownOutline14","IconCloseOutline16","useRef","css","IconFolderOpenOutline16","createElement"],"sources":["../src/client/locales.ts","../src/client/task-data-store.ts","../src/client/task-ui-store.ts","../src/client/task-hooks.ts","../src/client/TaskComponents.tsx","../src/client/TaskPanel.tsx","../src/client/TaskCommandNode.tsx","../src/client/client.ts"],"sourcesContent":["/**\n * Locale dictionaries for Task Panel\n */\nexport const zh = {\n 'panel.title': '工作流任务',\n 'panel.active': '进行中',\n 'panel.total': '总计',\n 'panel.minimize': '收起为顶部迷你条',\n 'panel.close': '关闭面板(隐藏,/task 可唤起)',\n 'panel.refresh': '同步最新任务',\n 'panel.style': '切换面板风格',\n 'style.native': '原生',\n 'style.glass': '玻璃',\n 'style.brutal': '粗野',\n 'style.mono': '终端',\n 'panel.syncing': '同步中…',\n 'panel.sync-failed': '同步失败',\n 'panel.hints-on': '显示提示信息',\n 'panel.hints-off': '隐藏提示信息',\n 'drag.cancel': '取消拖拽',\n 'panel.empty': '暂无任务',\n 'panel.empty-desc': '让模型开始工作并维护 todo 清单后会自动建档',\n 'panel.no-session': '还没有会话',\n 'task.progress': '进度',\n 'task.steps': '步骤',\n 'task.files': '文件',\n 'task.current': '当前',\n 'task.title-edit': '双击修改标题',\n 'task.switch': '切换到此任务',\n 'task.unbind': '取消当前任务',\n 'task.archive': '归档',\n 'task.drag': '拖拽移动',\n 'step.completed': '已完成',\n 'step.in-progress': '进行中',\n 'step.pending': '待办',\n 'step.edit-hint': '双击编辑步骤文案;点击图标循环 待办/进行中/已完成',\n 'file.copy': '复制路径',\n 'file.copied': '已复制路径',\n 'minibar.current': '当前任务',\n 'minibar.click-expand': '点击展开并同步',\n 'minibar.tasks': '个任务',\n 'minibar.no-task': '暂无任务 · 点击查看',\n}\n\nexport const en = {\n 'panel.title': 'Task Flow',\n 'panel.active': 'Active',\n 'panel.total': 'Total',\n 'panel.minimize': 'Collapse to mini bar',\n 'panel.close': 'Close panel (hidden; /task reopens)',\n 'panel.refresh': 'Sync latest tasks',\n 'panel.style': 'Panel style',\n 'style.native': 'Native',\n 'style.glass': 'Glass',\n 'style.brutal': 'Brutal',\n 'style.mono': 'Mono',\n 'panel.syncing': 'Syncing…',\n 'panel.sync-failed': 'Sync failed',\n 'panel.hints-on': 'Show hints',\n 'panel.hints-off': 'Hide hints',\n 'drag.cancel': 'Cancel drag',\n 'panel.empty': 'No Tasks',\n 'panel.empty-desc': 'Tasks are created automatically when the model maintains a todo list',\n 'panel.no-session': 'No session yet',\n 'task.progress': 'Progress',\n 'task.steps': 'Steps',\n 'task.files': 'Files',\n 'task.current': 'Current',\n 'task.title-edit': 'Double-click to rename',\n 'task.switch': 'Switch to this task',\n 'task.unbind': 'Unbind current task',\n 'task.archive': 'Archive',\n 'task.drag': 'Drag to move',\n 'step.completed': 'Completed',\n 'step.in-progress': 'In Progress',\n 'step.pending': 'Pending',\n 'step.edit-hint': 'Double-click to edit; click the icon to cycle status',\n 'file.copy': 'Copy path',\n 'file.copied': 'Path copied',\n 'minibar.current': 'Current task',\n 'minibar.click-expand': 'Click to expand & sync',\n 'minibar.tasks': 'tasks',\n 'minibar.no-task': 'No tasks · click to view',\n}\n\nexport type LocaleDict = typeof zh\n\nexport function createTranslate(dict: LocaleDict) {\n return (key: keyof LocaleDict, params?: Record<string, string | number>) => {\n let text = dict[key] ?? key\n if (params) {\n for (const [k, v] of Object.entries(params)) {\n text = text.replace(new RegExp(`\\\\{${k}\\\\}`, 'g'), String(v))\n }\n }\n return text\n }\n}\n","/**\n * Task Data Store — 仅管服务端同步的数据(tasks、boundTaskId、archivedCount)\n * - 单向数据流:命令执行结果 → setTasks → 广播给其他标签页\n * - 无 UI 状态,无 localStorage,纯内存 + BroadcastChannel 同步\n */\nimport { useSyncExternalStore } from 'react'\n\nexport interface TaskStep {\n content: string\n status: 'pending' | 'in_progress' | 'completed'\n}\n\nexport interface TaskFile {\n path: string\n line?: number\n}\n\nexport interface Task {\n id: string\n title: string\n steps: TaskStep[]\n files: TaskFile[]\n lastActiveAt: string\n updatedAt: string\n archived?: boolean\n}\n\nexport interface TaskPayload {\n tasks: Task[]\n boundId: string | null\n archived: number\n}\n\nexport function parseTaskPayloadText(text?: string | null): TaskPayload | null {\n if (!text) return null\n let jsonBlock: string | null = null\n const fenced = text.match(/```(?:json)?\\s*\\n([\\s\\S]*?)\\n```/)\n if (fenced) jsonBlock = fenced[1]\n else {\n const lastBrace = text.lastIndexOf('{')\n if (lastBrace !== -1) jsonBlock = text.slice(lastBrace)\n }\n if (!jsonBlock) return null\n try {\n const data = JSON.parse(jsonBlock)\n if (!Array.isArray(data.tasks)) return null\n return { tasks: data.tasks, boundId: data.boundId ?? null, archived: data.archived ?? 0 }\n } catch {\n return null\n }\n}\n\ninterface TaskDataState {\n tasks: Task[]\n boundTaskId: string | null\n archivedCount: number\n lastUpdate: number\n}\n\nconst SYNC_CHANNEL = typeof window !== 'undefined' ? new BroadcastChannel('dsh-pm-tasks-data') : null\n\nlet dataState: TaskDataState = {\n tasks: [],\n boundTaskId: null,\n archivedCount: 0,\n lastUpdate: 0,\n}\n\nconst dataListeners = new Set<() => void>()\n\nfunction setDataState(next: TaskDataState): void {\n dataState = next\n for (const listener of dataListeners) listener()\n}\n\nfunction broadcastDataUpdate(tasks: Task[], archivedCount: number): void {\n if (!SYNC_CHANNEL) return\n SYNC_CHANNEL.postMessage({\n type: 'PROJECT_TASKS_UPDATED',\n payload: { tasks, archivedCount },\n })\n}\n\nif (SYNC_CHANNEL) {\n SYNC_CHANNEL.onmessage = (event) => {\n const msg = event.data\n if (msg?.type === 'PROJECT_TASKS_UPDATED' && msg.payload) {\n const { tasks, archivedCount } = msg.payload\n setDataState(prev => ({\n ...prev,\n tasks: tasks || [],\n archivedCount: archivedCount ?? 0,\n lastUpdate: Date.now(),\n }))\n }\n }\n}\n\nexport const taskDataStore = {\n subscribe(listener: () => void): () => void {\n dataListeners.add(listener)\n return () => { dataListeners.delete(listener) }\n },\n getSnapshot(): TaskDataState {\n return dataState\n },\n actions: {\n setTasks(payload: { tasks: Task[]; boundTaskId: string | null; archivedCount: number }): void {\n const nextTasks = payload.tasks || []\n const nextArchived = payload.archivedCount ?? 0\n setDataState({\n tasks: nextTasks,\n boundTaskId: payload.boundTaskId ?? null,\n archivedCount: nextArchived,\n lastUpdate: Date.now(),\n })\n broadcastDataUpdate(nextTasks, nextArchived)\n },\n reset(): void {\n setDataState({\n tasks: [],\n boundTaskId: null,\n archivedCount: 0,\n lastUpdate: 0,\n })\n },\n },\n}\n\nexport function useTaskData(): TaskDataState {\n return useSyncExternalStore(taskDataStore.subscribe, taskDataStore.getSnapshot, taskDataStore.getSnapshot)\n}\n\nexport function useTaskDataActions() {\n return taskDataStore.actions\n}","/**\n * Task UI Store — 仅管本地 UI 状态(closed、minimized、position、expandedIds、theme)\n * - 持久化到 localStorage(key: dsh-pm-task-panel-ui)\n * - 不跨标签页同步(每个标签页独立)\n * - 启动/刷新强制 closed: true,面板默认不显示\n */\nimport { useSyncExternalStore } from 'react'\n\nconst STORAGE_KEY = 'dsh-pm-task-panel-ui'\n\ninterface TaskUIState {\n expandedTaskIds: string[]\n panelPosition: { x: number; y: number }\n minimized: boolean\n closed: boolean\n theme: string\n}\n\nfunction defaultPosition(): { x: number; y: number } {\n if (typeof window !== 'undefined') {\n return { x: Math.max(16, window.innerWidth - 408), y: 72 }\n }\n return { x: 0, y: 0 }\n}\n\n/**\n * 启动时的初始状态:\n * - closed 恒为 true(不读取 localStorage 的 closed),刷新后面板隐藏;\n * - 其余(展开项/位置/主题)可恢复上次会话偏好,minimized 默认折叠成迷你条。\n */\nfunction getDefaultUIState(): TaskUIState {\n if (typeof window !== 'undefined') {\n try {\n const saved = localStorage.getItem(STORAGE_KEY)\n if (saved) {\n const parsed = JSON.parse(saved)\n return {\n expandedTaskIds: Array.isArray(parsed.expandedTaskIds) ? parsed.expandedTaskIds : [],\n panelPosition: parsed.panelPosition ?? defaultPosition(),\n minimized: parsed.minimized !== false,\n closed: true,\n theme: typeof parsed.theme === 'string' ? parsed.theme : 'native',\n }\n }\n } catch { /* corrupt state — fall through to defaults */ }\n }\n return {\n expandedTaskIds: [],\n panelPosition: defaultPosition(),\n minimized: true,\n closed: true,\n theme: 'native',\n }\n}\n\nfunction persistUI(state: TaskUIState): void {\n if (typeof window === 'undefined') return\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(state))\n } catch { /* storage full/unavailable — non-fatal */ }\n}\n\nlet uiState: TaskUIState = getDefaultUIState()\nconst uiListeners = new Set<() => void>()\n\nfunction setUIState(next: TaskUIState): void {\n uiState = next\n persistUI(next)\n for (const listener of uiListeners) listener()\n}\n\nexport const taskUIStore = {\n subscribe(listener: () => void): () => void {\n uiListeners.add(listener)\n return () => { uiListeners.delete(listener) }\n },\n getSnapshot(): TaskUIState {\n return uiState\n },\n actions: {\n toggleTaskExpanded(taskId: string): void {\n const prev = uiState\n const ids = prev.expandedTaskIds.includes(taskId)\n ? prev.expandedTaskIds.filter((id) => id !== taskId)\n : [...prev.expandedTaskIds, taskId]\n setUIState({ ...prev, expandedTaskIds: ids })\n },\n expandAll(taskIds: string[]): void {\n setUIState({ ...uiState, expandedTaskIds: taskIds })\n },\n setPanelPosition(pos: { x: number; y: number }): void {\n setUIState({ ...uiState, panelPosition: pos })\n },\n open(): void {\n setUIState({ ...uiState, minimized: false, closed: false })\n },\n minimize(): void {\n setUIState({ ...uiState, minimized: true, closed: false })\n },\n close(): void {\n setUIState({ ...uiState, minimized: true, closed: true })\n },\n setTheme(theme: string): void {\n setUIState({ ...uiState, theme })\n },\n reset(): void {\n setUIState(getDefaultUIState())\n },\n },\n}\n\nexport function useTaskUI(): TaskUIState {\n return useSyncExternalStore(taskUIStore.subscribe, taskUIStore.getSnapshot, taskUIStore.getSnapshot)\n}\n\nexport function useTaskUIActions() {\n return taskUIStore.actions\n}\n","/**\n * Task Panel Hooks — 步骤拖拽交互逻辑(useTaskDrag)。\n * 只依赖 react + task-data-store 类型,不碰数据/UI store。\n */\nimport { useEffect, useRef, useState, useCallback } from 'react'\nimport { TaskStep } from './task-data-store.ts'\n\ninterface DragState {\n fromIndex: number\n stepContent: string\n clientX: number\n clientY: number\n dragging: boolean\n}\n\n/**\n * useTaskDrag — 步骤拖拽重排(绑定任务内,同一任务卡的步骤行间移动)。\n *\n * 交互模型(拖动全程按住鼠标):\n * - 步骤行上按下(左键、非按钮/输入区域)→ 进入预览;\n * - 按住 350ms 不松,或按住后移动超过 6px → 唤起跟随鼠标的浮动幽灵卡片;\n * - 幽灵悬停到本任务卡内的步骤行时显示蓝色插入线(上半=插到该行前,下半=插到该行后);\n * - 松手(mouseup):落在有效位置 → onReorder 落子;落在卡外/别的任务卡/原行\n * (插入自身前后)/按钮输入等控件上 → 取消;\n * - 350ms 内原地松手 = 普通点击,不产生幽灵;Esc → 取消。\n */\nexport function useTaskDrag(\n taskId: string,\n steps: TaskStep[],\n isBound: boolean,\n onReorder: (fromIndex: number, toIndex: number) => void\n) {\n const [dragState, setDragState] = useState<DragState | null>(null)\n const [dropTargetIndex, setDropTargetIndex] = useState<number | null>(null)\n\n // 最新值镜像:拖拽期间 window 监听只在“会话开始/结束”时挂载/卸载,\n // 避免每次 mousemove 更新状态导致监听器重挂、连 350ms 定时器都被清掉。\n const dragRef = useRef(dragState)\n dragRef.current = dragState\n const longPressTimer = useRef<number | undefined>(undefined)\n const dragOrigin = useRef<{ x: number; y: number } | null>(null)\n\n const clearTimer = useCallback(() => {\n if (longPressTimer.current !== undefined) {\n window.clearTimeout(longPressTimer.current)\n longPressTimer.current = undefined\n }\n }, [])\n\n const cancelDrag = useCallback(() => {\n clearTimer()\n dragOrigin.current = null\n document.body.style.userSelect = ''\n setDropTargetIndex(null)\n setDragState(null)\n }, [clearTimer])\n\n const startDrag = useCallback((\n fromIndex: number,\n stepContent: string,\n e: React.MouseEvent\n ) => {\n if (!isBound || e.button !== 0) return\n if (dragRef.current) return // 已有预览/拖拽会话\n e.preventDefault()\n e.stopPropagation()\n document.body.style.userSelect = 'none'\n dragOrigin.current = { x: e.clientX, y: e.clientY }\n setDropTargetIndex(null)\n setDragState({ fromIndex, stepContent, clientX: e.clientX, clientY: e.clientY, dragging: false })\n clearTimer()\n longPressTimer.current = window.setTimeout(() => {\n longPressTimer.current = undefined\n // 350ms 长按 → 唤起幽灵卡片\n setDragState(prev => (prev ? { ...prev, dragging: true } : null))\n }, 350)\n }, [isBound, clearTimer])\n\n /** 计算某行上 y 坐标对应的插入位(行数下标:上半=该行前,下半=该行后);非本任务卡返回 null */\n const dropIndexAt = useCallback((row: Element, clientY: number): number | null => {\n const parentOl = row.closest('ol')\n if (!parentOl || !parentOl.closest(`article[data-task-id=\"${taskId}\"]`)) return null\n const index = Array.from(parentOl.children).indexOf(row)\n const rect = row.getBoundingClientRect()\n return clientY < rect.top + rect.height / 2 ? index : index + 1\n }, [taskId])\n\n /** 在 (x,y) 处结算:命中有效落点则重排,否则取消;并结束本次拖拽 */\n const commitDrop = useCallback((x: number, y: number) => {\n const cur = dragRef.current\n if (!cur || !cur.dragging) return\n const el = document.elementFromPoint(x, y) as HTMLElement | null\n // 松手点在按钮/输入等交互控件上:不落子,直接取消\n if (el && !el.closest('button, input, textarea, a')) {\n const row = el.closest('[data-step-row]')\n if (row) {\n const drop = dropIndexAt(row, y)\n if (drop !== null) {\n // 行下标形式的落点:插到目标行前/后;落在自身原位视为取消(不产生空推送)\n const effective = drop > cur.fromIndex ? drop - 1 : drop\n if (effective !== cur.fromIndex) onReorder(cur.fromIndex, drop)\n }\n }\n }\n cancelDrag()\n }, [dropIndexAt, onReorder, cancelDrag])\n\n const active = dragState !== null\n\n useEffect(() => {\n if (!active) return\n\n const onMouseMove = (e: MouseEvent) => {\n const cur = dragRef.current\n if (!cur) return\n if (!cur.dragging) {\n // 未到 350ms:移动超过阈值视为拖拽开始(不必死等长按)\n const origin = dragOrigin.current\n if (!origin) return\n if (Math.hypot(e.clientX - origin.x, e.clientY - origin.y) < 6) return\n clearTimer()\n setDragState(prev => (prev ? { ...prev, dragging: true, clientX: e.clientX, clientY: e.clientY } : null))\n } else {\n setDragState(prev => (prev ? { ...prev, clientX: e.clientX, clientY: e.clientY } : null))\n }\n const row = document.elementFromPoint(e.clientX, e.clientY)?.closest('[data-step-row]')\n setDropTargetIndex(row ? dropIndexAt(row, e.clientY) : null)\n }\n\n const onMouseUp = (e: MouseEvent) => {\n const cur = dragRef.current\n if (!cur) return\n if (cur.dragging) {\n // 拖拽中松手 = 落子/取消\n commitDrop(e.clientX, e.clientY)\n } else {\n // 350ms 内原地松手 = 普通点击\n cancelDrag()\n }\n }\n\n const onClick = (e: MouseEvent) => {\n // 兜底:mouseup 发生在窗口外等情况时,下一次点击直接结算\n const cur = dragRef.current\n if (!cur || !cur.dragging) return\n commitDrop(e.clientX, e.clientY)\n }\n\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') cancelDrag()\n }\n\n window.addEventListener('mousemove', onMouseMove)\n window.addEventListener('mouseup', onMouseUp)\n window.addEventListener('click', onClick, true)\n window.addEventListener('keydown', onKeyDown)\n return () => {\n window.removeEventListener('mousemove', onMouseMove)\n window.removeEventListener('mouseup', onMouseUp)\n window.removeEventListener('click', onClick, true)\n window.removeEventListener('keydown', onKeyDown)\n document.body.style.userSelect = ''\n }\n }, [active, taskId, dropIndexAt, onReorder, cancelDrag, commitDrop])\n\n useEffect(() => () => clearTimer(), [clearTimer])\n\n return { dragState, dropTargetIndex, startDrag, cancelDrag }\n}\n","/**\n * Task Panel Presentational 组件 — MiniBar(折叠迷你条)与 TaskCard(任务卡)。\n * 纯渲染 + 卡片局部行内编辑/拖拽状态,动作经 props 回调交给容器(TaskPanel.tsx)。\n */\nimport { useRef, useState } from 'react'\nimport {\n Button,\n IconChevronDownOutline14,\n IconChevronUpOutline14,\n IconCheckOutline16,\n IconPlayOutline16,\n IconFolderOpenOutline16,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport { createTranslate } from './locales.ts'\nimport { useTaskDrag } from './task-hooks.ts'\nimport { type Task, type TaskStep } from './task-data-store.ts'\nimport css from './TaskPanel.module.css'\n\nfunction timeAgo(iso?: string) {\n if (!iso) return ''\n const diff = Date.now() - new Date(iso).getTime()\n const m = Math.floor(diff / 60000)\n if (m < 1) return '刚刚'\n if (m < 60) return `${m}分钟前`\n const h = Math.floor(m / 60)\n if (h < 24) return `${h}小时前`\n return `${Math.floor(h / 24)}天前`\n}\n\nfunction StepIcon({ status }: { status: TaskStep['status'] }) {\n if (status === 'completed') return <IconCheckOutline16 className={css.stepDone} />\n if (status === 'in_progress') return <IconPlayOutline16 className={css.stepRun} />\n return <span className={css.stepPending} />\n}\n\ninterface MiniBarProps {\n label: string\n hint: string\n position: { x: number; y: number }\n theme: string\n onMove: (pos: { x: number; y: number }) => void\n open: () => void\n}\n\nexport function MiniBar({ label, hint, position, theme, onMove, open }: MiniBarProps) {\n const barRef = useRef<HTMLDivElement>(null)\n const down = useRef<{ dx: number; dy: number; sx: number; sy: number; moved: boolean } | null>(null)\n\n const onMouseDown = (e: React.MouseEvent) => {\n if (e.button !== 0) return\n const rect = barRef.current?.getBoundingClientRect()\n if (!rect) return\n down.current = { dx: e.clientX - rect.left, dy: e.clientY - rect.top, sx: e.clientX, sy: e.clientY, moved: false }\n const onMoveEv = (ev: MouseEvent) => {\n const d = down.current\n if (!d) return\n if (!d.moved && Math.abs(ev.clientX - d.sx) + Math.abs(ev.clientY - d.sy) > 4) d.moved = true\n if (d.moved) {\n const w = barRef.current?.offsetWidth ?? 260\n const h = barRef.current?.offsetHeight ?? 34\n const x = Math.max(8, Math.min(window.innerWidth - w - 8, ev.clientX - d.dx))\n const y = Math.max(8, Math.min(window.innerHeight - h - 8, ev.clientY - d.dy))\n onMove({ x, y })\n }\n }\n const onUpEv = () => {\n const d = down.current\n down.current = null\n window.removeEventListener('mousemove', onMoveEv)\n window.removeEventListener('mouseup', onUpEv)\n if (d && !d.moved) open()\n }\n window.addEventListener('mousemove', onMoveEv)\n window.addEventListener('mouseup', onUpEv)\n }\n\n return (\n <div\n ref={barRef}\n className={css.miniBar}\n style={{ left: position.x, top: position.y }}\n data-theme={theme === 'native' ? undefined : theme}\n onMouseDown={onMouseDown}\n role=\"button\"\n title={hint}\n aria-label={hint}\n >\n <IconFolderOpenOutline16 className={css.miniIcon} />\n <span className={css.miniText}>{label}</span>\n <IconChevronUpOutline14 className={css.miniChevron} />\n </div>\n )\n}\n\ninterface TaskCardProps {\n task: Task\n isBound: boolean\n expanded: boolean\n onToggleExpand: () => void\n onSwitch: () => void\n onUnbind: () => void\n onArchive: () => void\n onRename: (value: string) => void\n onEditStep: (index: number, value: string) => void\n onCycleStatus: (index: number) => void\n onReorderSteps: (fromIndex: number, toIndex: number) => void\n showHints: boolean\n syncing: boolean\n t: ReturnType<typeof createTranslate>\n}\n\nexport function TaskCard({\n task,\n isBound,\n expanded,\n onToggleExpand,\n onSwitch,\n onUnbind,\n onArchive,\n onRename,\n onEditStep,\n onCycleStatus,\n onReorderSteps,\n showHints,\n syncing,\n t,\n}: TaskCardProps) {\n const steps = task.steps || []\n const { dragState, dropTargetIndex, startDrag, cancelDrag } = useTaskDrag(task.id, steps, isBound, onReorderSteps)\n\n // 行内编辑状态(本卡片局部):双击进入,Enter/失焦提交,Esc 取消。\n const [stepEdit, setStepEdit] = useState<{ index: number; value: string } | null>(null)\n const [titleEdit, setTitleEdit] = useState<{ value: string } | null>(null)\n\n const done = steps.filter((s) => s.status === 'completed').length\n const pct = steps.length > 0 ? Math.round((done / steps.length) * 100) : 0\n\n const commitStepEdit = (index: number) => {\n if (!stepEdit || stepEdit.index !== index) return\n const value = stepEdit.value\n setStepEdit(null)\n onEditStep(index, value)\n }\n\n const commitTitleEdit = () => {\n if (titleEdit === null) return\n const value = titleEdit.value\n setTitleEdit(null)\n onRename(value)\n }\n\n return (\n <article data-task-id={task.id} className={`${css.card}${isBound ? ` ${css.cardBound}` : ''}`}>\n <button\n className={css.cardHead}\n onClick={() => { if (titleEdit !== null) return; onToggleExpand() }}\n aria-expanded={expanded}\n >\n <div className={css.cardTitleRow}>\n {isBound && <span className={css.boundBadge}>{t('task.current')}</span>}\n {isBound && titleEdit !== null ? (\n <input\n className={css.stepInput}\n value={titleEdit.value}\n autoFocus\n onChange={(e) => setTitleEdit({ value: e.target.value })}\n onBlur={commitTitleEdit}\n onKeyDown={(e) => {\n if (e.key === 'Enter') commitTitleEdit()\n else if (e.key === 'Escape') setTitleEdit(null)\n }}\n />\n ) : (\n <span\n className={`${css.cardTitle}${isBound ? ` ${css.cardTitleEditable}` : ''}`}\n title={isBound ? t('task.title-edit') : undefined}\n onDoubleClick={(e) => {\n e.preventDefault()\n e.stopPropagation()\n if (isBound) setTitleEdit({ value: String(task.title ?? '') })\n }}\n >\n {task.title}\n </span>\n )}\n </div>\n <div className={css.cardMeta}>\n {steps.length > 0 && <span className={css.progressText}>{done}/{steps.length}</span>}\n <span className={css.updated}>{timeAgo(task.updatedAt || task.lastActiveAt)}</span>\n <span className={css.chevron}>{expanded ? <IconChevronUpOutline14 /> : <IconChevronDownOutline14 />}</span>\n </div>\n </button>\n {steps.length > 0 && (\n <div className={css.track}>\n <div className={css.trackFill} style={{ width: `${pct}%` }} />\n </div>\n )}\n {expanded && (\n <div className={css.cardBody}>\n <div className={css.section}>\n <div className={css.sectionLabel}>\n {t('task.steps')}\n {steps.length > 0 && <span className={css.sectionCount}>{steps.length}</span>}\n </div>\n {steps.length > 0 ? (\n <>\n <ol className={css.stepsList}>\n {steps.map((step, i) => {\n const stepIsEditing = stepEdit !== null && stepEdit.index === i\n const stepIsDragging = dragState?.dragging && dragState.fromIndex === i\n const isDropTarget = dropTargetIndex === i\n const isDropTargetAfter = dropTargetIndex === i + 1\n return (\n <li\n key={i}\n data-step-row\n className={`${css.stepRow}${stepIsDragging ? ` ${css.stepDragging}` : ''}${isDropTarget ? ` ${css.dropTargetBefore}` : ''}${isDropTargetAfter ? ` ${css.dropTargetAfter}` : ''}`}\n onMouseDown={(e) => {\n if (e.button !== 0) return\n if (!isBound || syncing) return\n // 交互控件(状态图标、编辑输入框等)上不进入拖拽\n const el = e.target as HTMLElement\n if (el.closest('button, input, textarea, a')) return\n startDrag(i, step.content, e)\n }}\n >\n {isBound ? (\n <button\n type=\"button\"\n className={css.stepToggle}\n disabled={syncing}\n onClick={(e) => { e.stopPropagation(); onCycleStatus(i) }}\n title={`${t('step.completed')}/${t('step.in-progress')}/${t('step.pending')}`}\n >\n <StepIcon status={step.status} />\n </button>\n ) : (\n <StepIcon status={step.status} />\n )}\n {stepIsEditing ? (\n <input\n className={css.stepInput}\n value={stepEdit!.value}\n autoFocus\n onChange={(e) => setStepEdit({ index: i, value: e.target.value })}\n onBlur={() => commitStepEdit(i)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') commitStepEdit(i)\n else if (e.key === 'Escape') setStepEdit(null)\n }}\n />\n ) : (\n <span\n className={`${css.stepContent}${step.status === 'completed' ? ` ${css.stepContentDone}` : ''}${step.status === 'in_progress' ? ` ${css.stepContentRun}` : ''}${isBound ? ` ${css.stepEditable}` : ''}`}\n title={isBound && showHints ? t('step.edit-hint') : undefined}\n onDoubleClick={(e) => {\n e.stopPropagation()\n if (isBound) setStepEdit({ index: i, value: String(step.content ?? '') })\n }}\n >\n {step.content}\n </span>\n )}\n </li>\n )\n })}\n </ol>\n {dragState && dragState.dragging && (\n <div\n className={css.dragGhost}\n style={{\n left: dragState.clientX + 12,\n top: dragState.clientY - 20,\n }}\n >\n <div className={css.dragGhostCard}>\n <span className={css.dragGhostContent}>{dragState.stepContent}</span>\n <button\n type=\"button\"\n className={css.dragGhostClose}\n style={{ pointerEvents: 'auto' }}\n onClick={(e) => { e.stopPropagation(); cancelDrag() }}\n title={showHints ? t('drag.cancel') : undefined}\n aria-label={t('drag.cancel')}\n >\n ×\n </button>\n </div>\n </div>\n )}\n </>\n ) : (\n <div className={css.muted}>{t('panel.empty-desc')}</div>\n )}\n </div>\n\n {(task.files?.length ?? 0) > 0 && (\n <div className={css.section}>\n <div className={css.sectionLabel}>\n {t('task.files')}\n <span className={css.sectionCount}>{task.files.length}</span>\n </div>\n <ul className={css.filesList}>\n {task.files.slice(0, 12).map((file, i) => (\n <li key={i}>\n <button\n className={css.fileRow}\n onClick={() => navigator.clipboard?.writeText(file.path)}\n title={`${t('file.copy')}: ${file.path}${file.line ? `:${file.line}` : ''}`}\n >\n <span className={css.fileDot} />\n <span className={css.filePath}>{file.path}</span>\n {file.line && <span className={css.fileLine}>:{file.line}</span>}\n </button>\n </li>\n ))}\n {(task.files?.length ?? 0) > 12 && (\n <li className={css.muted}>… 共 {task.files.length} 个</li>\n )}\n </ul>\n </div>\n )}\n\n <div className={css.cardFooter}>\n <Button variant=\"outline\" size=\"sm\" disabled={isBound || syncing} onClick={onSwitch}>\n {t('task.switch')}\n </Button>\n {isBound && (\n <Button variant=\"outline\" size=\"sm\" disabled={syncing} onClick={onUnbind} title={t('task.unbind')}>\n {t('task.unbind')}\n </Button>\n )}\n <Button variant=\"outline\" size=\"sm\" disabled={syncing} onClick={onArchive}>\n {t('task.archive')}\n </Button>\n </div>\n </div>\n )}\n </article>\n )\n}\n","/**\n * Task Panel — dsh web `shell.overlay` 浮动任务面板。\n * Container 组件:负责数据获取、命令桥接、状态协调\n * Presentational 组件在 TaskComponents.tsx\n */\nimport { Component, useEffect, useRef, useState, type ReactNode } from 'react'\nimport {\n Button,\n IconChevronDownOutline14,\n IconCloseOutline16,\n IconFolderOpenOutline16,\n IconQuestionOutline14,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport { createTranslate, zh, en } from './locales.ts'\nimport { useTaskData, useTaskDataActions, parseTaskPayloadText, type TaskStep } from './task-data-store.ts'\nimport { useTaskUI, useTaskUIActions } from './task-ui-store.ts'\nimport { MiniBar, TaskCard } from './TaskComponents.tsx'\nimport css from './TaskPanel.module.css'\n\nconst NS = 'dsh-project-memory'\n\nconst STATUS_CYCLE = ['pending', 'in_progress', 'completed'] as const\n\nfunction getT() {\n const locale = (typeof navigator !== 'undefined' && navigator.language.startsWith('zh')) ? zh : en\n return createTranslate(locale)\n}\n\nfunction useSessionId(ctx: any): string | null {\n const [, force] = useState(0)\n useEffect(() => {\n const list = ctx?.sessions?.list\n if (!list || typeof list.subscribe !== 'function') return\n return list.subscribe(() => force((n) => n + 1))\n }, [ctx])\n const snap = ctx?.sessions?.list?.getSnapshot?.()\n if (!snap) return null\n if (snap.current) return snap.current\n const first = Array.isArray(snap.items) ? snap.items.find((s: any) => !s.blank) ?? snap.items[0] : undefined\n return first?.sessionId ?? null\n}\n\nclass PanelErrorBoundary extends Component<{ children: ReactNode }, { failed: boolean }> {\n state = { failed: false }\n static getDerivedStateFromError() { return { failed: true } }\n componentDidCatch(error: unknown) {\n console.warn('[dsh-project-memory] task panel render crashed:', error)\n }\n render() {\n if (!this.state.failed) return this.props.children\n return (\n <button className={css.boundaryFallback} onClick={() => this.setState({ failed: false })} title=\"重新渲染任务面板\">\n 任务面板(点击重试)\n </button>\n )\n }\n}\n\nexport function TaskPanelEntry({ ctx }: { ctx: any }) {\n return (\n <PanelErrorBoundary>\n <TaskPanelView ctx={ctx} />\n </PanelErrorBoundary>\n )\n}\n\nfunction TaskPanelView({ ctx }: { ctx: any }) {\n const t = getT()\n const data = useTaskData()\n const ui = useTaskUI()\n const sessionId = useSessionId(ctx)\n const [syncing, setSyncing] = useState(false)\n const [syncedAt, setSyncedAt] = useState(0)\n const [syncError, setSyncError] = useState<string | null>(null)\n const [showHints, setShowHints] = useState(true)\n\n const dataActions = useTaskDataActions()\n const uiActions = useTaskUIActions()\n\n const activeTasks = data.tasks.filter((task) => !task.archived)\n const boundTask = data.boundTaskId ? data.tasks.find((task) => task.id === data.boundTaskId) ?? null : null\n\n const applyPayload = (text?: string): boolean => {\n const parsed = parseTaskPayloadText(text)\n if (!parsed) return false\n dataActions.setTasks({ tasks: parsed.tasks, boundTaskId: parsed.boundId, archivedCount: parsed.archived })\n setSyncedAt(Date.now())\n setSyncError(null)\n return true\n }\n\n const runLine = async (line: string): Promise<boolean> => {\n const commands = ctx?.remote?.commands\n if (!sessionId || !commands || typeof commands.execute !== 'function') {\n setSyncError('no session / commands service')\n return false\n }\n let response: any\n try {\n response = await commands.execute(sessionId, line, [])\n } catch (err) {\n setSyncError(String(err?.message ?? err))\n return false\n }\n const envelope = response as { ok?: boolean; value?: any } | null | undefined\n const execution = envelope && typeof envelope === 'object' && 'value' in envelope ? envelope.value : envelope\n const result = execution?.result ?? execution\n if (result?.kind === 'error') {\n setSyncError(result.text ?? 'command error')\n return false\n }\n return applyPayload(result?.text)\n }\n\n const refresh = async (): Promise<void> => {\n if (syncing) return\n setSyncing(true)\n try {\n const prevBoundId = data.boundTaskId\n await runLine('/tasks')\n const newBoundId = useTaskData.getSnapshot().boundTaskId\n if (newBoundId && newBoundId !== prevBoundId) {\n await runLine(`/task switch ${newBoundId}`)\n }\n } finally {\n setSyncing(false)\n }\n }\n\n const handleAction = async (verb: 'switch' | 'archive', taskId: string): Promise<void> => {\n if (syncing) return\n setSyncing(true)\n try {\n await runLine(`/task ${verb} ${taskId}`)\n } finally {\n setSyncing(false)\n }\n }\n\n const pushSteps = (taskId: string, steps: TaskStep[]): void => {\n void runLine(`/task todos ${JSON.stringify(steps.map((s) => ({ content: s.content, status: s.status })))}`)\n }\n\n const cycleStatus = (taskId: string, index: number) => {\n const task = data.tasks.find((tt) => tt.id === taskId)\n if (!task) return\n const steps = task.steps || []\n const next = steps.map((s, i) => {\n if (i !== index) return s\n const cur = STATUS_CYCLE.indexOf(s.status)\n return { ...s, status: STATUS_CYCLE[(cur + 1) % STATUS_CYCLE.length] }\n })\n pushSteps(taskId, next)\n }\n\n const commitStepText = (taskId: string, index: number, value: string) => {\n const task = data.tasks.find((tt) => tt.id === taskId)\n const trimmed = value.trim()\n if (!task) return\n const same = (task.steps || [])[index]?.content === trimmed\n if (same || !trimmed) return\n const next = (task.steps || []).map((s, i) => (i === index ? { ...s, content: trimmed } : s))\n pushSteps(taskId, next)\n }\n\n const reorderSteps = (taskId: string, fromIndex: number, toIndex: number) => {\n if (fromIndex === toIndex) return\n const task = data.tasks.find((tt) => tt.id === taskId)\n if (!task) return\n const steps = [...(task.steps || [])]\n const [moved] = steps.splice(fromIndex, 1)\n const targetIndex = toIndex > fromIndex ? toIndex - 1 : toIndex\n steps.splice(targetIndex, 0, moved)\n pushSteps(taskId, steps)\n }\n\n const commitTitle = (taskId: string, value: string) => {\n const task = data.tasks.find((tt) => tt.id === taskId)\n const trimmed = value.trim()\n if (!task) return\n const same = task.title === trimmed\n if (same || !trimmed) return\n void runLine(`/task rename ${taskId} ${JSON.stringify(trimmed)}`)\n }\n\n const expand = () => {\n uiActions.open()\n if (Date.now() - Math.max(data.lastUpdate, syncedAt) > 30_000) {\n void refresh()\n }\n }\n\n const THEMES = ['native', 'glass', 'brutal', 'mono'] as const\n const style = (THEMES as readonly string[]).includes(ui.theme) ? ui.theme : 'native'\n const styleLabel = t(`style.${style}` as keyof typeof zh)\n const cycleTheme = () => {\n const i = THEMES.indexOf(style as (typeof THEMES)[number])\n uiActions.setTheme(THEMES[(i + 1) % THEMES.length])\n }\n\n const panelRef = useRef<HTMLDivElement>(null)\n const drag = useRef<{ dx: number; dy: number } | null>(null)\n\n const handleDragStart = (e: React.MouseEvent) => {\n if (e.target !== e.currentTarget) return\n const rect = panelRef.current?.getBoundingClientRect()\n if (!rect) return\n drag.current = { dx: e.clientX - rect.left, dy: e.clientY - rect.top }\n const onMove = (ev: MouseEvent) => {\n if (!drag.current) return\n const width = panelRef.current?.offsetWidth ?? 380\n const height = panelRef.current?.offsetHeight ?? 480\n const x = Math.max(8, Math.min(window.innerWidth - width - 8, ev.clientX - drag.current.dx))\n const y = Math.max(8, Math.min(window.innerHeight - 64, ev.clientY - drag.current.dy))\n uiActions.setPanelPosition({ x, y })\n }\n const onUp = () => {\n drag.current = null\n window.removeEventListener('mousemove', onMove)\n window.removeEventListener('mouseup', onUp)\n }\n window.addEventListener('mousemove', onMove)\n window.addEventListener('mouseup', onUp)\n }\n\n // 会话切换时仅同步数据,不自动打开面板\n useEffect(() => {\n if (!sessionId) return\n // 仅当面板已打开时才自动刷新\n if (!ui.closed) {\n void refresh()\n }\n }, [sessionId])\n\n // 监听模型工具请求打开面板\n useEffect(() => {\n const ctxWithEvents = ctx\n const handler = () => {\n uiActions.open()\n if (Date.now() - Math.max(data.lastUpdate, syncedAt) > 30_000) {\n void refresh()\n }\n }\n ctxWithEvents?.events?.on?.('dsh:task-panel:show', handler)\n return () => {\n ctxWithEvents?.events?.off?.('dsh:task-panel:show', handler)\n }\n }, [ctx, uiActions, data.lastUpdate, syncedAt, refresh])\n\n // 彻底隐藏:不渲染任何东西\n if (ui.closed) {\n return null\n }\n\n // 折叠态:迷你条\n if (ui.minimized) {\n const label = boundTask\n ? `${t('minibar.current')}: ${boundTask.title}`\n : activeTasks.length > 0\n ? `${t('minibar.current')}: ${activeTasks.length} ${t('minibar.tasks')}`\n : t('minibar.no-task')\n return (\n <MiniBar\n label={label}\n hint={t('minibar.click-expand')}\n position={ui.panelPosition}\n theme={style}\n onMove={uiActions.setPanelPosition}\n open={expand}\n />\n )\n }\n\n const doneCount = activeTasks.filter((task) => {\n const steps = task.steps || []\n return steps.length > 0 && steps.every((s) => s.status === 'completed')\n }).length\n\n return (\n <div\n className={css.panel}\n ref={panelRef}\n style={{ left: ui.panelPosition.x, top: ui.panelPosition.y }}\n data-theme={style === 'native' ? undefined : style}\n >\n <div className={css.dragHandle} onMouseDown={handleDragStart} title={t('task.drag')}>\n <div className={css.handleGrip} />\n </div>\n <header className={css.header}>\n <div className={css.headerLeft}>\n <Button\n type=\"button\"\n className={css.headerIconBtn}\n onClick={cycleTheme}\n title={styleLabel}\n aria-label={styleLabel}\n >\n <IconFolderOpenOutline16 className={css.headerIcon} />\n </Button>\n <h2 className={css.headerTitle}>{t('panel.title')}</h2>\n </div>\n <div className={css.headerRight}>\n <span className={css.counts}>\n {activeTasks.length > 0\n ? `${t('panel.active')} ${activeTasks.length} · ${doneCount}/${activeTasks.length}`\n : ''}\n </span>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setShowHints(!showHints)}\n aria-label={showHints ? t('panel.hints-off') : t('panel.hints-on')}\n title={showHints ? t('panel.hints-off') : t('panel.hints-on')}\n >\n <IconQuestionOutline14 size={16} />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => uiActions.minimize()}\n aria-label={t('panel.minimize')}\n title={t('panel.minimize')}\n >\n <IconChevronDownOutline14 />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => uiActions.close()}\n aria-label={t('panel.close')}\n title={t('panel.close')}\n >\n <IconCloseOutline16 />\n </Button>\n </div>\n </header>\n\n {!sessionId && <div className={css.notice}>{t('panel.no-session')}</div>}\n {syncError && <div className={css.notice}>{t('panel.sync-failed')}: {syncError}</div>}\n\n {activeTasks.length === 0 ? (\n <div className={css.emptyState}>\n <p className={css.emptyTitle}>{t('panel.empty')}</p>\n <p className={css.emptyDesc}>{t('panel.empty-desc')}</p>\n {syncing && <p className={css.syncHint}>{t('panel.syncing')}</p>}\n </div>\n ) : (\n <div className={css.taskList}>\n {activeTasks.map((task) => {\n const steps = task.steps || []\n const expanded = ui.expandedTaskIds.includes(task.id)\n const isBound = data.boundTaskId === task.id\n return (\n <TaskCard\n key={task.id}\n task={task}\n isBound={isBound}\n expanded={expanded}\n onToggleExpand={() => uiActions.toggleTaskExpanded(task.id)}\n onSwitch={() => handleAction('switch', task.id)}\n onUnbind={() => runLine('/task unbind')}\n onArchive={() => handleAction('archive', task.id)}\n onRename={(value) => commitTitle(task.id, value)}\n onEditStep={(index, value) => commitStepText(task.id, index, value)}\n onCycleStatus={(index) => cycleStatus(task.id, index)}\n onReorderSteps={(from, to) => reorderSteps(task.id, from, to)}\n showHints={showHints}\n syncing={syncing}\n t={t}\n />\n )\n })}\n {syncing && <div className={css.syncHint}>{t('panel.syncing')}</div>}\n </div>\n )}\n </div>\n )\n}","/**\n * /tasks、/task 命令在会话中的节点渲染器(conversation.chat.commandview,按命令名 key)。\n * 列表型命令(/tasks、无动词 /task)同步数据并打开面板。\n */\nimport { useEffect, useRef } from 'react'\nimport { IconFolderOpenOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { parseTaskPayloadText, taskDataStore } from './task-data-store.ts'\nimport { taskUIStore } from './task-ui-store.ts'\nimport css from './TaskCommandNode.module.css'\n\nexport function TaskCommandNode({ node }: { node?: any }) {\n const name = node?.name ?? 'task'\n const outcome = node?.outcome ?? null\n const args = typeof node?.args === 'string' ? node.args : ''\n const verb = args.trim().split(/\\s+/)[0] ?? ''\n const isList = name === 'tasks' || !verb\n const text = outcome?.text ?? ''\n\n const parsed = parseTaskPayloadText(text)\n\n // 该节点是否“现场执行”(挂载时处于执行中):为 true 说明是用户当场输入的命令,\n // 完成后同步数据并打开面板。刷新/切换会话后历史节点以完成态重挂载,\n // 此时只做展示、不再写数据/开面板(面板保持关闭,与“刷新后不显示”一致)。\n const live = useRef(outcome === null)\n\n // 载荷进数据 store;列表型命令(/tasks、无动词 /task)同步数据并打开面板\n useEffect(() => {\n if (!parsed || !live.current) return\n taskDataStore.actions.setTasks({\n tasks: parsed.tasks,\n boundTaskId: parsed.boundId,\n archivedCount: parsed.archived,\n })\n if (isList) taskUIStore.actions.open()\n }, [text])\n\n if (outcome === null) {\n return <div className={css.row} data-variant=\"running\">/{name} 执行中…</div>\n }\n\n if (outcome.kind === 'error') {\n const brief = String(text ?? '').split('\\n')[0].slice(0, 120)\n return <div className={css.row} data-variant=\"error\">/{name} 失败{brief ? `:${brief}` : ''}</div>\n }\n\n if (!isList) {\n const note = String(text ?? '')\n .split(/\\n{2,}/)[0]\n .replace(/```.*$/s, '')\n .trim()\n .slice(0, 200)\n return <div className={css.row} data-variant=\"ok\">/{name} {note || '已完成'}</div>\n }\n\n const count = parsed ? parsed.tasks.length : 0\n const archived = parsed ? parsed.archived : 0\n const label = parsed\n ? `任务 ${count} 套${archived ? `(归档 ${archived})` : ''} · 已同步到任务面板`\n : `/${name} 已执行`\n return (\n <div className={css.row} data-variant=\"ok\">\n <IconFolderOpenOutline16 className={css.icon} />\n <span>{label}</span>\n </div>\n )\n}","/**\n * dsh-project-memory Client Entry\n *\n * dsh web (rc.1) 的 client 插件契约为 cordis client plugin:\n * export const inject = [<client 服务名>...]\n * export function apply(ctx) { ... }\n * 面板注册进 `shell.overlay`(Frame 级浮动层,additive 列表槽):\n * 该槽由 ui-layout 的 AppFrame 声明渲染(scope root,独立于滚动容器),\n * 默认 click-through,条目自身需开启 pointer-events。\n *\n * 只依赖宿主 seed 提供的模块(react / dsh-client-ui-primitives),\n * 数据经 remote.commands.execute 执行 /tasks 命令获取 JSON 快照。\n */\nimport { createElement } from 'react'\nimport { TaskPanelEntry } from './TaskPanel.tsx'\nimport { TaskCommandNode } from './TaskCommandNode.tsx'\n\nconst NS = 'dsh-project-memory'\n\nexport const name = NS\n\n/** Required client services: slots registry, session scopes, commands remote (data 通道). */\nexport const inject = ['slots', 'sessions', 'remote', 'remote.commands']\n\nexport function apply(ctx: any): void {\n const slots = ctx?.slots\n if (!slots || typeof slots.inject !== 'function') {\n console.warn(`[${NS}] host has no slots service — task panel disabled`)\n return\n }\n try {\n slots.inject('shell.overlay', () => slots.register(\n {\n name: 'shell.overlay',\n id: 'dsh-project-memory-task-panel',\n order: 100, // 浮层顺序:低于 toast/弹窗即可,越高越靠后渲染\n },\n () => createElement(TaskPanelEntry, { ctx })\n ))\n\n // 会话内 /tasks、/task 命令节点:按命令名 key 接管渲染,\n // 替换内置大段文本卡片(文本含 JSON 载荷,只有面板需要它)。\n const nodeKeys = ['tasks', 'task']\n for (const key of nodeKeys) {\n slots.inject('conversation.chat.commandview', () => slots.register(\n { name: 'conversation.chat.commandview', key },\n TaskCommandNode\n ))\n }\n } catch (err) {\n console.warn(`[${NS}] task panel registration failed:`, err)\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yolk_vat-y/dsh-project-memory",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.4",
|
|
4
4
|
"description": "Persistent project memory for dsh agents: index docs (PDF/Markdown/text) and code symbols into a searchable per-workspace store, recall them with cited sources, and keep experience entries (problems -> solutions) searchable on demand.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -43,15 +43,15 @@
|
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
46
|
-
"@deepseek-ai/dsh-client-locale": "
|
|
47
|
-
"@deepseek-ai/dsh-client-runtime": "
|
|
48
|
-
"@deepseek-ai/dsh-client-store": "
|
|
49
|
-
"@deepseek-ai/dsh-client-ui-primitives": "
|
|
50
|
-
"@deepseek-ai/dsh-client-ui-slots": "
|
|
51
|
-
"@deepseek-ai/dsh-llm": "
|
|
52
|
-
"@deepseek-ai/dsh-tools": "
|
|
46
|
+
"@deepseek-ai/dsh-client-locale": "0.1.2-rc.1",
|
|
47
|
+
"@deepseek-ai/dsh-client-runtime": "0.1.1-rc.2",
|
|
48
|
+
"@deepseek-ai/dsh-client-store": "0.1.2-rc.1",
|
|
49
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.2-rc.1",
|
|
50
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.2-rc.1",
|
|
51
|
+
"@deepseek-ai/dsh-llm": "0.1.1-rc.2",
|
|
52
|
+
"@deepseek-ai/dsh-tools": "0.1.1-rc.2",
|
|
53
53
|
"@deepseek-ai/schemastery": "^3.18.2",
|
|
54
|
-
"@tsdown/css": "
|
|
54
|
+
"@tsdown/css": "0.22.14",
|
|
55
55
|
"lightningcss": "^1.33.0",
|
|
56
56
|
"tsdown": "^0.22.14",
|
|
57
57
|
"typescript": "^5.6.3"
|
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* /tasks、/task 命令在会话中的节点渲染器(conversation.chat.commandview,按命令名 key)。
|
|
3
|
-
*
|
|
4
|
-
* 目标:不再让大段文本+JSON 出现在会话里——
|
|
5
|
-
* - 列表型(/tasks、无动词的 /task):只渲染一行极简“已同步 N 套”状态;
|
|
6
|
-
* 同时把节点文本里的 JSON 载荷解析进浮动面板(侧边卡片由它驱动),
|
|
7
|
-
* 面板若被收起则自动展开(等价“输入 /task 就看到卡片”)。
|
|
8
|
-
* - 动作型(/task switch|archive):渲染一行操作结果(切换/归档反馈)。
|
|
9
|
-
* - 错误/执行中:一行极简状态,不倾倒原文。
|
|
3
|
+
* 列表型命令(/tasks、无动词 /task)同步数据并打开面板。
|
|
10
4
|
*/
|
|
11
|
-
import { useEffect } from 'react'
|
|
5
|
+
import { useEffect, useRef } from 'react'
|
|
12
6
|
import { IconFolderOpenOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'
|
|
13
|
-
import { parseTaskPayloadText,
|
|
7
|
+
import { parseTaskPayloadText, taskDataStore } from './task-data-store.ts'
|
|
8
|
+
import { taskUIStore } from './task-ui-store.ts'
|
|
14
9
|
import css from './TaskCommandNode.module.css'
|
|
15
10
|
|
|
16
|
-
/** node = CommandRowOwnerProps.node(CommandNode: name / args / outcome{kind,text}) */
|
|
17
11
|
export function TaskCommandNode({ node }: { node?: any }) {
|
|
18
12
|
const name = node?.name ?? 'task'
|
|
19
13
|
const outcome = node?.outcome ?? null
|
|
@@ -24,32 +18,31 @@ export function TaskCommandNode({ node }: { node?: any }) {
|
|
|
24
18
|
|
|
25
19
|
const parsed = parseTaskPayloadText(text)
|
|
26
20
|
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
//
|
|
21
|
+
// 该节点是否“现场执行”(挂载时处于执行中):为 true 说明是用户当场输入的命令,
|
|
22
|
+
// 完成后同步数据并打开面板。刷新/切换会话后历史节点以完成态重挂载,
|
|
23
|
+
// 此时只做展示、不再写数据/开面板(面板保持关闭,与“刷新后不显示”一致)。
|
|
24
|
+
const live = useRef(outcome === null)
|
|
25
|
+
|
|
26
|
+
// 载荷进数据 store;列表型命令(/tasks、无动词 /task)同步数据并打开面板
|
|
30
27
|
useEffect(() => {
|
|
31
|
-
if (!parsed) return
|
|
32
|
-
|
|
28
|
+
if (!parsed || !live.current) return
|
|
29
|
+
taskDataStore.actions.setTasks({
|
|
33
30
|
tasks: parsed.tasks,
|
|
34
31
|
boundTaskId: parsed.boundId,
|
|
35
32
|
archivedCount: parsed.archived,
|
|
36
33
|
})
|
|
37
|
-
if (isList)
|
|
38
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
34
|
+
if (isList) taskUIStore.actions.open()
|
|
39
35
|
}, [text])
|
|
40
36
|
|
|
41
|
-
// 执行中
|
|
42
37
|
if (outcome === null) {
|
|
43
38
|
return <div className={css.row} data-variant="running">/{name} 执行中…</div>
|
|
44
39
|
}
|
|
45
40
|
|
|
46
|
-
// 失败:一行极简,不含大段原文
|
|
47
41
|
if (outcome.kind === 'error') {
|
|
48
42
|
const brief = String(text ?? '').split('\n')[0].slice(0, 120)
|
|
49
43
|
return <div className={css.row} data-variant="error">/{name} 失败{brief ? `:${brief}` : ''}</div>
|
|
50
44
|
}
|
|
51
45
|
|
|
52
|
-
// 动作型:取第一段(操作反馈),不带 JSON
|
|
53
46
|
if (!isList) {
|
|
54
47
|
const note = String(text ?? '')
|
|
55
48
|
.split(/\n{2,}/)[0]
|
|
@@ -59,7 +52,6 @@ export function TaskCommandNode({ node }: { node?: any }) {
|
|
|
59
52
|
return <div className={css.row} data-variant="ok">/{name} {note || '已完成'}</div>
|
|
60
53
|
}
|
|
61
54
|
|
|
62
|
-
// 列表型:一行极简状态
|
|
63
55
|
const count = parsed ? parsed.tasks.length : 0
|
|
64
56
|
const archived = parsed ? parsed.archived : 0
|
|
65
57
|
const label = parsed
|
|
@@ -71,4 +63,4 @@ export function TaskCommandNode({ node }: { node?: any }) {
|
|
|
71
63
|
<span>{label}</span>
|
|
72
64
|
</div>
|
|
73
65
|
)
|
|
74
|
-
}
|
|
66
|
+
}
|