@yolk_vat-y/dsh-project-memory 0.4.0 → 0.4.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.
@@ -0,0 +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":";;;;;;;;;;;;;EAGA,MAAa,KAAK;GAChB,eAAe;GACf,gBAAgB;GAChB,eAAe;GACf,kBAAkB;GAClB,eAAe;GACb,iBAAiB;GACnB,eAAe;GACf,gBAAgB;GAChB,eAAe;GACf,gBAAgB;GAChB,cAAc;GACd,iBAAiB;GACjB,qBAAqB;GACrB,eAAe;GACf,oBAAoB;GAClB,oBAAoB;GACtB,iBAAiB;GACjB,cAAc;GACd,cAAc;GACZ,gBAAgB;GAClB,mBAAmB;GACnB,eAAe;GACf,eAAe;GACf,gBAAgB;GACd,aAAa;GACf,kBAAkB;GAClB,oBAAoB;GACpB,gBAAgB;GAChB,kBAAkB;GAChB,aAAa;GACf,eAAe;GACf,mBAAmB;GACnB,wBAAwB;GACxB,iBAAiB;GACjB,mBAAmB;EACrB;EAEA,MAAa,KAAK;GAChB,eAAe;GACf,gBAAgB;GAChB,eAAe;GACf,kBAAkB;GAClB,eAAe;GACb,iBAAiB;GACnB,eAAe;GACf,gBAAgB;GAChB,eAAe;GACf,gBAAgB;GAChB,cAAc;GACd,iBAAiB;GACjB,qBAAqB;GACrB,eAAe;GACf,oBAAoB;GAClB,oBAAoB;GACtB,iBAAiB;GACjB,cAAc;GACd,cAAc;GACZ,gBAAgB;GAClB,mBAAmB;GACnB,eAAe;GACf,eAAe;GACf,gBAAgB;GACd,aAAa;GACf,kBAAkB;GAClB,oBAAoB;GACpB,gBAAgB;GAChB,kBAAkB;GAChB,aAAa;GACf,eAAe;GACf,mBAAmB;GACnB,wBAAwB;GACxB,iBAAiB;GACjB,mBAAmB;EACrB;EAIA,SAAgB,gBAAgB,MAAkB;GAChD,QAAQ,KAAuB,WAA6C;IAC1E,IAAI,OAAO,KAAK,QAAQ;IACxB,IAAI,QACF,KAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,MAAM,GACxC,OAAO,KAAK,QAAQ,IAAI,OAAO,MAAM,EAAE,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC;IAGhE,OAAO;GACT;EACF;;;;;;;;;ECxCA,SAAgB,qBAAqB,MAA0C;GAC7E,IAAI,CAAC,MAAM,OAAO;GAClB,IAAI,YAA2B;GAC/B,MAAM,SAAS,KAAK,MAAM,kCAAkC;GAC5D,IAAI,QAAQ,YAAY,OAAO;QAC1B;IACH,MAAM,YAAY,KAAK,YAAY,GAAG;IACtC,IAAI,cAAc,IAAI,YAAY,KAAK,MAAM,SAAS;GACxD;GACA,IAAI,CAAC,WAAW,OAAO;GACvB,IAAI;IACF,MAAM,OAAO,KAAK,MAAM,SAAS;IACjC,IAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,GAAG,OAAO;IACvC,OAAO;KAAE,OAAO,KAAK;KAAO,SAAS,KAAK,WAAW;KAAM,UAAU,KAAK,YAAY;IAAE;GAC1F,QAAQ;IACN,OAAO;GACT;EACF;EAEA,MAAM,cAAc;EAEpB,SAAS,kBAA4C;GACnD,IAAI,OAAO,WAAW,aACpB,OAAO;IAAE,GAAG,KAAK,IAAI,IAAI,OAAO,aAAa,GAAG;IAAG,GAAG;GAAG;GAE3D,OAAO;IAAE,GAAG;IAAG,GAAG;GAAE;EACtB;EAEA,SAAS,kBAAkC;GACzC,IAAI,OAAO,WAAW,aACpB,IAAI;IACF,MAAM,QAAQ,aAAa,QAAQ,WAAW;IAC9C,IAAI,OAAO;KACT,MAAM,SAAS,KAAK,MAAM,KAAK;KAC/B,OAAO;MACL,OAAO,MAAM,QAAQ,OAAO,KAAK,IAAI,OAAO,QAAQ,CAAC;MACrD,aAAa,OAAO,eAAe;MACnC,eAAe,OAAO,iBAAiB;MACvC,iBAAiB,MAAM,QAAQ,OAAO,eAAe,IAAI,OAAO,kBAAkB,CAAC;MACnF,eAAe,OAAO,iBAAiB,gBAAgB;MACvD,WAAW,OAAO,cAAc;MAChC,OAAO,OAAO,OAAO,UAAU,WAAW,OAAO,QAAQ;MACzD,QAAQ,CAAC,CAAC,OAAO;MACjB,YAAY,OAAO,cAAc;KACnC;IACF;GACF,QAAQ,CAAiD;GAE3D,OAAO;IACL,OAAO,CAAC;IACR,aAAa;IACb,eAAe;IACf,iBAAiB,CAAC;IAClB,eAAe,gBAAgB;IAC/B,WAAW;IACX,QAAQ;IACR,OAAO;IACP,YAAY;GACd;EACF;EAEA,SAAS,QAAQ,OAA6B;GAC5C,IAAI,OAAO,WAAW,aAAa;GACnC,IAAI;IACF,aAAa,QAAQ,aAAa,KAAK,UAAU,KAAK,CAAC;GACzD,QAAQ,CAA6C;EACvD;EAEA,IAAI,QAAwB,gBAAgB;EAC5C,MAAM,4BAAY,IAAI,IAAgB;EAEtC,SAAS,SAAS,MAA4B;GAC5C,QAAQ;GACR,QAAQ,IAAI;GACZ,KAAK,MAAM,YAAY,WAAW,SAAS;EAC7C;EAEA,MAAa,YAAY;GACvB,UAAU,UAAkC;IAC1C,UAAU,IAAI,QAAQ;IACtB,aAAa;KAAE,UAAU,OAAO,QAAQ;IAAE;GAC5C;GACA,cAA8B;IAC5B,OAAO;GACT;GACA,SAAS;IACP,SAAS,SAAqF;KAE5F,SAAS;MACP,GAAGA;MACH,OAAO,QAAQ,SAAS,CAAC;MACzB,aAAa,QAAQ,eAAe;MACpC,eAAe,QAAQ,iBAAiB;MACxC,YAAY,KAAK,IAAI;KACvB,CAAC;IACH;IACA,mBAAmB,QAAsB;KACvC,MAAM,OAAO;KACb,MAAM,MAAM,KAAK,gBAAgB,SAAS,MAAM,IAC5C,KAAK,gBAAgB,QAAQ,OAAO,OAAO,MAAM,IACjD,CAAC,GAAG,KAAK,iBAAiB,MAAM;KACpC,SAAS;MAAE,GAAG;MAAM,iBAAiB;KAAI,CAAC;IAC5C;IACA,YAAkB;KAChB,MAAM,OAAO;KACb,SAAS;MAAE,GAAG;MAAM,iBAAiB,KAAK,MAAM,KAAK,MAAM,EAAE,EAAE;KAAE,CAAC;IACpE;IACA,iBAAiB,KAAqC;KACpD,SAAS;MAAE,GAAG;MAAO,eAAe;KAAI,CAAC;IAC3C;;IAEA,OAAa;KACX,SAAS;MAAE,GAAG;MAAO,WAAW;MAAO,QAAQ;KAAM,CAAC;IACxD;;IAEA,WAAiB;KACf,SAAS;MAAE,GAAG;MAAO,WAAW;MAAM,QAAQ;KAAM,CAAC;IACvD;;IAEA,QAAc;KACZ,SAAS;MAAE,GAAG;MAAO,WAAW;MAAM,QAAQ;KAAK,CAAC;IACtD;IACA,SAAS,OAAqB;KAC5B,SAAS;MAAE,GAAG;MAAO;KAAM,CAAC;IAC9B;IACA,aAAa,WAA0B;KACrC,SAAS;MAAE,GAAG;MAAO;MAAW,QAAQ,YAAY,MAAM,SAAS;KAAM,CAAC;IAC5E;IACA,QAAc;KACZ,SAAS,gBAAgB,CAAC;IAC5B;GACF;EACF;EAEA,SAAgB,eAA+B;GAC7C,QAAA,GAAOC,MAAAA,qBAAAA,CAAqB,UAAU,WAAW,UAAU,aAAa,UAAU,WAAW;EAC/F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EC7JA,SAAS,OAAO;GAEd,OAAO,gBADS,OAAO,cAAc,eAAe,UAAU,SAAS,WAAW,IAAI,IAAK,KAAK,EACnE;EAC/B;EAEA,SAAS,QAAQ,KAAc;GAC7B,IAAI,CAAC,KAAK,OAAO;GACjB,MAAM,OAAO,KAAK,IAAI,IAAI,IAAI,KAAK,GAAG,CAAC,CAAC,QAAQ;GAChD,MAAM,IAAI,KAAK,MAAM,OAAO,GAAK;GACjC,IAAI,IAAI,GAAG,OAAO;GAClB,IAAI,IAAI,IAAI,OAAO,GAAG,EAAE;GACxB,MAAM,IAAI,KAAK,MAAM,IAAI,EAAE;GAC3B,IAAI,IAAI,IAAI,OAAO,GAAG,EAAE;GACxB,OAAO,GAAG,KAAK,MAAM,IAAI,EAAE,EAAE;EAC/B;EAEA,SAAS,SAAS,EAAE,UAA0C;GAC5D,IAAI,WAAW,aAAa,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,oBAAD,EAAoB,WAAWC,6BAAI,SAAW,CAAA;GACjF,IAAI,WAAW,eAAe,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,mBAAD,EAAmB,WAAWD,6BAAI,QAAU,CAAA;GACjF,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,WAAWA,6BAAI,YAAc,CAAA;EAC5C;EAEA,SAAS,aAAa,KAAyB;GAC7C,MAAM,GAAG,UAAA,GAASE,MAAAA,SAAAA,CAAS,CAAC;GAC5B,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,MAAM,OAAO,KAAK,UAAU;IAC5B,IAAI,CAAC,QAAQ,OAAO,KAAK,cAAc,YAAY;IACnD,OAAO,KAAK,gBAAgB,OAAO,MAAM,IAAI,CAAC,CAAC;GACjD,GAAG,CAAC,GAAG,CAAC;GACR,MAAM,OAAO,KAAK,UAAU,MAAM,cAAc;GAChD,IAAI,CAAC,MAAM,OAAO;GAClB,IAAI,KAAK,SAAS,OAAO,KAAK;GAE9B,QADc,MAAM,QAAQ,KAAK,KAAK,IAAI,KAAK,MAAM,MAAM,MAAW,CAAC,EAAE,KAAK,KAAK,KAAK,MAAM,KAAK,KAAA,EAAA,EACrF,aAAa;EAC7B;;EAGA,SAAS,SAAS,EAAE,OAAO,UAAU,UAAU,cAK5C;GACD,MAAM,CAAC,MAAM,YAAA,GAAWA,MAAAA,SAAAA,CAAS,KAAK;GACtC,MAAM,OAAA,GAAMC,MAAAA,OAAAA,CAA4B,IAAI;GAC5C,MAAM,WAAA,GAAUA,MAAAA,OAAAA,CAAO,KAAK;GAC5B,MAAM,QAAQ,OAAmB;IAC/B,IAAI,QAAQ,SAAS;IACrB,QAAQ,UAAU;IAClB,GAAG;GACL;GAEA,MAAM,eAAe;IACnB,MAAM,KAAK,IAAI;IACf,IAAI,CAAC,IAAI;IACT,GAAG,MAAM,SAAS;IAClB,GAAG,MAAM,SAAS,GAAG,KAAK,IAAI,GAAG,cAAc,GAAG,EAAE;GACtD;GAEA,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,OAAO;IACP,MAAM,KAAK,IAAI;IACf,IAAI,MAAM;IACV,IAAI,OAAO;GACb,GAAG,CAAC,CAAC;GAEL,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,YAAD;IACO;IACL,WAAWH,6BAAI;IACf,MAAM;IACN,OAAO;IACP,WAAW,MAAM;KAAE,QAAQ,EAAE,OAAO,KAAK;KAAG,OAAO;IAAE;IACrD,cAAc,WAAW,SAAS,IAAI,CAAC;IACvC,YAAY,MAAM;KAChB,IAAI,EAAE,QAAQ,UAAU;MACtB,EAAE,eAAe;MACjB,WAAW,SAAS,CAAC;KACvB,OAAO,IAAI,EAAE,QAAQ,YAAY,cAAc,CAAC,EAAE,WAAW;MAC3D,EAAE,eAAe;MACjB,WAAW,SAAS,IAAI,CAAC;KAC3B;IACF;GACD,CAAA;EAEL;;EAGA,SAAS,QAAQ,EAAE,OAAO,MAAM,UAAU,OAAO,QAAQ,QAOtD;GACD,MAAM,UAAA,GAASG,MAAAA,OAAAA,CAAuB,IAAI;GAC1C,MAAM,QAAA,GAAOA,MAAAA,OAAAA,CAAkF,IAAI;GAEnG,MAAM,eAAe,MAAwB;IAC3C,IAAI,EAAE,WAAW,GAAG;IACpB,MAAM,OAAO,OAAO,SAAS,sBAAsB;IACnD,IAAI,CAAC,MAAM;IACX,KAAK,UAAU;KAAE,IAAI,EAAE,UAAU,KAAK;KAAM,IAAI,EAAE,UAAU,KAAK;KAAK,IAAI,EAAE;KAAS,IAAI,EAAE;KAAS,OAAO;IAAM;IACjH,MAAM,YAAY,OAAmB;KACnC,MAAM,IAAI,KAAK;KACf,IAAI,CAAC,GAAG;KACR,IAAI,CAAC,EAAE,SAAS,KAAK,IAAI,GAAG,UAAU,EAAE,EAAE,IAAI,KAAK,IAAI,GAAG,UAAU,EAAE,EAAE,IAAI,GAAG,EAAE,QAAQ;KACzF,IAAI,EAAE,OAAO;MACX,MAAM,IAAI,OAAO,SAAS,eAAe;MACzC,MAAM,IAAI,OAAO,SAAS,gBAAgB;MAG1C,OAAO;OAAE,GAFC,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,aAAa,IAAI,GAAG,GAAG,UAAU,EAAE,EAAE,CAElE;OAAG,GADF,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,cAAc,IAAI,GAAG,GAAG,UAAU,EAAE,EAAE,CAChE;MAAE,CAAC;KACjB;IACF;IACA,MAAM,eAAe;KACnB,MAAM,IAAI,KAAK;KACf,KAAK,UAAU;KACf,OAAO,oBAAoB,aAAa,QAAQ;KAChD,OAAO,oBAAoB,WAAW,MAAM;KAC5C,IAAI,KAAK,CAAC,EAAE,OAAO,KAAK;IAC1B;IACA,OAAO,iBAAiB,aAAa,QAAQ;IAC7C,OAAO,iBAAiB,WAAW,MAAM;GAC3C;GAEA,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IACE,KAAK;IACL,WAAWH,6BAAI;IACf,OAAO;KAAE,MAAM,SAAS;KAAG,KAAK,SAAS;IAAE;IAC3C,cAAY,UAAU,WAAW,KAAA,IAAY;IAChC;IACb,MAAK;IACL,OAAO;IACP,cAAY;IARd,UAAA;KAUE,iBAAA,GAAA,kBAAA,IAAA,CAACI,sCAAAA,yBAAD,EAAyB,WAAWJ,6BAAI,SAAW,CAAA;KACnD,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;MAAM,WAAWA,6BAAI;MAAW,UAAA;KAAY,CAAA;KAC5C,iBAAA,GAAA,kBAAA,IAAA,CAACK,sCAAAA,wBAAD,EAAwB,WAAWL,6BAAI,YAAc,CAAA;IAClD;;EAET;;;;;;EAOA,IAAM,qBAAN,cAAiCM,MAAAA,UAAwD;GACvF,QAAQ,EAAE,QAAQ,MAAM;GAExB,OAAO,2BAA2B;IAChC,OAAO,EAAE,QAAQ,KAAK;GACxB;GAEA,kBAAkB,OAAgB;IAChC,QAAQ,KAAK,2EAA2E,KAAK;GAC/F;GAEA,SAAS;IACP,IAAI,CAAC,KAAK,MAAM,QAAQ,OAAO,KAAK,MAAM;IAC1C,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;KACE,WAAWN,6BAAI;KACf,eAAe,KAAK,SAAS,EAAE,QAAQ,MAAM,CAAC;KAC9C,OAAM;KACP,UAAA;IAEO,CAAA;GAEZ;EACF;EAEA,SAAgB,eAAe,EAAE,OAAqB;GACpD,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,oBAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,eAAD,EAAoB,IAAM,CAAA,EACR,CAAA;EAExB;EAEA,SAAS,cAAc,EAAE,OAAqB;GAC5C,MAAM,IAAI,KAAK;GACf,MAAM,QAAQ,aAAa;GAC3B,MAAM,YAAY,aAAa,GAAG;GAClC,MAAM,CAAC,SAAS,eAAA,GAAcE,MAAAA,SAAAA,CAAS,KAAK;GAC5C,MAAM,CAAC,UAAU,gBAAA,GAAeA,MAAAA,SAAAA,CAAS,CAAC;GAC1C,MAAM,CAAC,YAAY,kBAAA,GAAiBA,MAAAA,SAAAA,CAAwB,IAAI;GAChE,MAAM,CAAC,WAAW,iBAAA,GAAgBA,MAAAA,SAAAA,CAAwB,IAAI;GAC9D,MAAM,YAAA,GAAWC,MAAAA,OAAAA,CAAuB,IAAI;GAC5C,MAAM,QAAA,GAAOA,MAAAA,OAAAA,CAA0C,IAAI;GAC3D,MAAM,aAAA,GAAYA,MAAAA,OAAAA,CAA2B,KAAA,CAAS;GAEtD,MAAM,UAAU,UAAU;GAE1B,MAAM,cAAc,MAAM,MAAM,QAAQ,SAAS,CAAC,KAAK,QAAQ;GAC/D,MAAM,YAAY,MAAM,cAAc,MAAM,MAAM,MAAM,SAAS,KAAK,OAAO,MAAM,WAAW,KAAK,OAAO;GAE1G,MAAM,gBAAgB,SAA2B;IAC/C,MAAM,SAAS,qBAAqB,IAAI;IACxC,IAAI,CAAC,QAAQ,OAAO;IACpB,QAAQ,SAAS;KAAE,OAAO,OAAO;KAAO,aAAa,OAAO;KAAS,eAAe,OAAO;IAAS,CAAC;IACrG,YAAY,KAAK,IAAI,CAAC;IACtB,aAAa,IAAI;IACjB,OAAO;GACT;GAEA,MAAM,UAAU,OAAO,SAAmC;IACxD,MAAM,WAAW,KAAK,QAAQ;IAC9B,IAAI,CAAC,aAAa,CAAC,YAAY,OAAO,SAAS,YAAY,YAAY;KACrE,aAAa,+BAA+B;KAC5C,OAAO;IACT;IACA,IAAI;IACJ,IAAI;KACF,WAAW,MAAM,SAAS,QAAQ,WAAW,MAAM,CAAC,CAAC;IACvD,SAAS,KAAK;KACZ,aAAa,OAAO,KAAK,WAAW,GAAG,CAAC;KACxC,OAAO;IACT;IACA,MAAM,WAAW;IACjB,MAAM,YAAY,YAAY,OAAO,aAAa,YAAY,WAAW,WAAW,SAAS,QAAQ;IACrG,MAAM,SAAS,WAAW,UAAU;IACpC,IAAI,QAAQ,SAAS,SAAS;KAC5B,aAAa,OAAO,QAAQ,eAAe;KAC3C,OAAO;IACT;IACA,OAAO,aAAa,QAAQ,IAAI;GAClC;GAEA,MAAM,UAAU,YAA2B;IACzC,IAAI,SAAS;IACb,WAAW,IAAI;IACf,IAAI;KACF,MAAM,QAAQ,QAAQ;IACxB,UAAU;KACR,WAAW,KAAK;IAClB;GACF;GAEA,MAAM,eAAe,OAAO,MAA4B,WAAkC;IACxF,IAAI,SAAS;IACb,WAAW,IAAI;IACf,IAAI;KACF,MAAM,QAAQ,SAAS,KAAK,GAAG,QAAQ;IACzC,UAAU;KACR,WAAW,KAAK;IAClB;GACF;GAGA,MAAM,CAAC,SAAS,eAAA,GAAcD,MAAAA,SAAAA,CAAkE,IAAI;GACpG,MAAM,eAAe;IAAC;IAAW;IAAe;GAAW;GAC3D,MAAM,aAAa,QAAgB,UAA4B;IAC7D,QAAa,eAAe,KAAK,UAAU,MAAM,KAAK,OAAO;KAAE,SAAS,EAAE;KAAS,QAAQ,EAAE;IAAO,EAAE,CAAC,GAAG;GAC5G;GACA,MAAM,eAAe,QAAgB,UAAkB;IACrD,MAAM,OAAO,MAAM,MAAM,MAAM,OAAO,GAAG,OAAO,MAAM;IACtD,IAAI,CAAC,MAAM;IAEX,MAAM,QADQ,KAAK,SAAS,CAAC,EAAA,CACV,KAAK,GAAG,MAAM;KAC/B,IAAI,MAAM,OAAO,OAAO;KACxB,MAAM,MAAM,aAAa,QAAQ,EAAE,MAAM;KACzC,OAAO;MAAE,GAAG;MAAG,QAAQ,cAAc,MAAM,KAAK,aAAa;KAAQ;IACvE,CAAC;IACD,UAAU,QAAQ,IAAI;GACxB;GACA,MAAM,kBAAkB,QAAgB,OAAe,UAAkB;IACvE,MAAM,OAAO,MAAM,MAAM,MAAM,OAAO,GAAG,OAAO,MAAM;IACtD,MAAM,UAAU,MAAM,KAAK;IAC3B,IAAI,CAAC,MAAM;KAAE,WAAW,IAAI;KAAG;IAAO;IACtC,MAAM,QAAQ,KAAK,SAAS,CAAC,EAAA,CAAG,MAAM,EAAE,YAAY;IACpD,WAAW,IAAI;IACf,IAAI,QAAQ,CAAC,SAAS;IACtB,MAAM,QAAQ,KAAK,SAAS,CAAC,EAAA,CAAG,KAAK,GAAG,MAAO,MAAM,QAAQ;KAAE,GAAG;KAAG,SAAS;IAAQ,IAAI,CAAE;IAC5F,UAAU,QAAQ,IAAI;GACxB;GAGA,MAAM,CAAC,cAAc,oBAAA,GAAmBA,MAAAA,SAAAA,CAAmD,IAAI;GAC/F,MAAM,eAAe,QAAgB,UAAkB;IACrD,MAAM,OAAO,MAAM,MAAM,MAAM,OAAO,GAAG,OAAO,MAAM;IACtD,MAAM,UAAU,MAAM,KAAK;IAC3B,IAAI,CAAC,MAAM;KAAE,gBAAgB,IAAI;KAAG;IAAO;IAC3C,MAAM,OAAO,KAAK,UAAU;IAC5B,gBAAgB,IAAI;IACpB,IAAI,QAAQ,CAAC,SAAS;IACtB,QAAa,gBAAgB,OAAO,GAAG,KAAK,UAAU,OAAO,GAAG;GAClE;GAEA,MAAM,eAAe;IACnB,QAAQ,KAAK;IAEb,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,MAAM,YAAY,QAAQ,IAAI,KACtD,QAAa;GAEjB;GAEA,MAAM,SAAS;IAAC;IAAU;IAAS;IAAU;GAAM;GACnD,MAAM,QAAS,OAA6B,SAAS,MAAM,KAAK,IAAI,MAAM,QAAQ;GAClF,MAAM,aAAa,EAAE,SAAS,OAA0B;GACxD,MAAM,mBAAmB;IACvB,MAAM,IAAI,OAAO,QAAQ,KAAgC;IACzD,QAAQ,SAAS,QAAQ,IAAI,KAAK,OAAO,OAAO;GAClD;GAEA,MAAM,mBAAmB,MAAwB;IAC/C,IAAI,EAAE,WAAW,EAAE,eAAe;IAClC,MAAM,OAAO,SAAS,SAAS,sBAAsB;IACrD,IAAI,CAAC,MAAM;IACX,KAAK,UAAU;KAAE,IAAI,EAAE,UAAU,KAAK;KAAM,IAAI,EAAE,UAAU,KAAK;IAAI;IACrE,MAAM,UAAU,OAAmB;KACjC,IAAI,CAAC,KAAK,SAAS;KACnB,MAAM,QAAQ,SAAS,SAAS,eAAe;KAChC,SAAS,SAAS;KACjC,MAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,aAAa,QAAQ,GAAG,GAAG,UAAU,KAAK,QAAQ,EAAE,CAAC;KAC3F,MAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,cAAc,IAAI,GAAG,UAAU,KAAK,QAAQ,EAAE,CAAC;KACrF,QAAQ,iBAAiB;MAAE;MAAG;KAAE,CAAC;IACnC;IACA,MAAM,aAAa;KACjB,KAAK,UAAU;KACf,OAAO,oBAAoB,aAAa,MAAM;KAC9C,OAAO,oBAAoB,WAAW,IAAI;IAC5C;IACA,OAAO,iBAAiB,aAAa,MAAM;IAC3C,OAAO,iBAAiB,WAAW,IAAI;GACzC;GAEA,MAAM,YAAY,SAAiB;IACjC,IAAI,eAAe,MAAM;IACzB,UAAe,WAAW,UAAU,IAAI,CAAC,CAAC,YAAY,KAAA,CAAS;IAC/D,cAAc,IAAI;IAClB,OAAO,aAAa,UAAU,OAAO;IACrC,UAAU,UAAU,OAAO,iBAAiB,cAAc,IAAI,GAAG,IAAI;GACvE;GAEA,CAAA,GAAA,MAAA,UAAA,aAAsB,OAAO,aAAa,UAAU,OAAO,GAAG,CAAC,CAAC;GAGhE,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,IAAI,CAAC,WAAW;IAChB,MAAM,OAAO,UAAU,YAAY;IACnC,IAAI,KAAK,eAAe,KAAK,CAAC,KAAK,QAAQ;KACzC,MAAM,QAAQ,OAAO,iBAAiB,KAAK,QAAQ,GAAG,GAAG;KACzD,aAAa,OAAO,aAAa,KAAK;IACxC;GAGF,GAAG,CAAC,SAAS,CAAC;GAGd,IAAI,MAAM,QACR,OAAO;GAIT,IAAI,MAAM,WAAW;IACnB,MAAM,QAAQ,YACV,GAAG,EAAE,iBAAiB,EAAE,IAAI,UAAU,UACtC,YAAY,SAAS,IACnB,GAAG,EAAE,iBAAiB,EAAE,IAAI,YAAY,OAAO,GAAG,EAAE,eAAe,MACnE,EAAE,iBAAiB;IACzB,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;KACS;KACP,MAAM,EAAE,sBAAsB;KAC9B,UAAU,MAAM;KAChB,OAAO;KACP,SAAS,QAAQ,QAAQ,iBAAiB,GAAG;KAC7C,MAAM;IACP,CAAA;GAEL;GAEA,MAAM,YAAY,YAAY,QAAQ,SAAS;IAC7C,MAAM,QAAQ,KAAK,SAAS,CAAC;IAC7B,OAAO,MAAM,SAAS,KAAK,MAAM,OAAO,MAAM,EAAE,WAAW,WAAW;GACxE,CAAC,CAAC,CAAC;GAEH,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IACE,WAAWF,6BAAI;IACf,KAAK;IACL,OAAO;KAAE,MAAM,MAAM,cAAc;KAAG,KAAK,MAAM,cAAc;IAAE;IACjE,cAAY,UAAU,WAAW,KAAA,IAAY;IAJ/C,UAAA;KAME,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;MAAK,WAAWA,6BAAI;MAAY,aAAa;MAAiB,OAAO,EAAE,WAAW;MAChF,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD,EAAK,WAAWA,6BAAI,WAAa,CAAA;KAC9B,CAAA;KACL,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;MAAQ,WAAWA,6BAAI;MAAvB,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;OAAK,WAAWA,6BAAI;OAApB,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QACE,MAAK;QACL,WAAWA,6BAAI;QACf,SAAS;QACT,OAAO;QACP,cAAY;QAEZ,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACI,sCAAAA,yBAAD,EAAyB,WAAWJ,6BAAI,WAAa,CAAA;OAC/C,CAAA,GACR,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;QAAI,WAAWA,6BAAI;QAAc,UAAA,EAAE,aAAa;OAAM,CAAA,CACnD;MACL,CAAA,GAAA,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;OAAK,WAAWA,6BAAI;OAApB,UAAA;QACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;SAAM,WAAWA,6BAAI;SAClB,UAAA,YAAY,SAAS,IAClB,GAAG,EAAE,cAAc,EAAE,GAAG,YAAY,OAAO,KAAK,UAAU,GAAG,YAAY,WACzE;QACA,CAAA;QACN,iBAAA,GAAA,kBAAA,IAAA,CAACO,sCAAAA,QAAD;SACE,SAAQ;SACR,MAAK;SACL,WAAW,UAAUP,6BAAI,WAAW,KAAA;SACpC,eAAe,KAAK,QAAQ;SAC5B,UAAU;SACV,cAAY,EAAE,eAAe;SAC7B,OAAO,EAAE,eAAe;SAExB,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACQ,sCAAAA,sBAAD,CAAuB,CAAA;QACjB,CAAA;QACR,iBAAA,GAAA,kBAAA,IAAA,CAACD,sCAAAA,QAAD;SACE,SAAQ;SACR,MAAK;SACL,eAAe,QAAQ,SAAS;SAChC,cAAY,EAAE,gBAAgB;SAC9B,OAAO,EAAE,gBAAgB;SAEzB,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACE,sCAAAA,0BAAD,CAA2B,CAAA;QACrB,CAAA;QACR,iBAAA,GAAA,kBAAA,IAAA,CAACF,sCAAAA,QAAD;SACE,SAAQ;SACR,MAAK;SACL,eAAe,QAAQ,MAAM;SAC7B,cAAY,EAAE,aAAa;SAC3B,OAAO,EAAE,aAAa;SAEtB,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACG,sCAAAA,oBAAD,CAAqB,CAAA;QACf,CAAA;OACL;MACC,CAAA,CAAA;;KAEP,CAAC,aAAa,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;MAAK,WAAWV,6BAAI;MAAS,UAAA,EAAE,kBAAkB;KAAO,CAAA;KACtE,aAAa,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAWA,6BAAI;MAApB,UAAA;OAA6B,EAAE,mBAAmB;OAAE;OAAG;MAAe;;KAEnF,YAAY,WAAW,IACtB,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAWA,6BAAI;MAApB,UAAA;OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;QAAG,WAAWA,6BAAI;QAAa,UAAA,EAAE,aAAa;OAAK,CAAA;OACnD,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;QAAG,WAAWA,6BAAI;QAAY,UAAA,EAAE,kBAAkB;OAAK,CAAA;OACtD,WAAW,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;QAAG,WAAWA,6BAAI;QAAW,UAAA,EAAE,eAAe;OAAK,CAAA;MAC5D;KAEL,CAAA,IAAA,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAWA,6BAAI;MAApB,UAAA,CACG,YAAY,KAAK,SAAS;OACzB,MAAM,QAAQ,KAAK,SAAS,CAAC;OAC7B,MAAM,OAAO,MAAM,QAAQ,MAAM,EAAE,WAAW,WAAW,CAAC,CAAC;OAC3D,MAAM,WAAW,MAAM,gBAAgB,SAAS,KAAK,EAAE;OACvD,MAAM,UAAU,MAAM,gBAAgB,KAAK;OAC3C,MAAM,MAAM,MAAM,SAAS,IAAI,KAAK,MAAO,OAAO,MAAM,SAAU,GAAG,IAAI;OACzE,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,WAAD;QAAuB,WAAW,GAAGA,6BAAI,OAAO,UAAU,IAAIA,6BAAI,cAAc;QAAhF,UAAA;SACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;UACE,WAAWA,6BAAI;UACf,eAAe;WAAE,IAAI,cAAc,WAAW,KAAK,IAAI;WAAQ,QAAQ,mBAAmB,KAAK,EAAE;UAAE;UACnG,iBAAe;UAHjB,UAAA,CAKE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;WAAK,WAAWA,6BAAI;WAApB,UAAA,CACG,WAAW,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;YAAM,WAAWA,6BAAI;YAAa,UAAA,EAAE,cAAc;WAAQ,CAAA,GACrE,WAAW,cAAc,WAAW,KAAK,KACxC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;YACE,OAAO,aAAa;YACpB,YAAA;YACA,WAAW,MAAM,YAAY,KAAK,IAAI,CAAC;YACvC,gBAAgB,gBAAgB,IAAI;WACrC,CAAA,IAED,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;YACE,WAAW,GAAGA,6BAAI,YAAY,UAAU,IAAIA,6BAAI,sBAAsB;YACtE,OAAO,UAAU,EAAE,iBAAiB,IAAI,KAAA;YACxC,gBAAgB,MAAM;aACpB,EAAE,eAAe;aACjB,EAAE,gBAAgB;aAClB,IAAI,SAAS,gBAAgB;cAAE,QAAQ,KAAK;cAAI,OAAO,KAAK;aAAM,CAAC;YACrE;YAEC,UAAA,KAAK;WACF,CAAA,CAEL;UACL,CAAA,GAAA,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;WAAK,WAAWA,6BAAI;WAApB,UAAA;YACG,MAAM,SAAS,KACd,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;aAAM,WAAWA,6BAAI;aAArB,UAAA;cACG;cAAK;cAAE,MAAM;aACV;;YAER,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;aAAM,WAAWA,6BAAI;aAAU,UAAA,QAAQ,KAAK,aAAa,KAAK,YAAY;YAAQ,CAAA;YAClF,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;aAAM,WAAWA,6BAAI;aAClB,UAAA,WAAW,iBAAA,GAAA,kBAAA,IAAA,CAACK,sCAAAA,wBAAD,CAAyB,CAAA,IAAI,iBAAA,GAAA,kBAAA,IAAA,CAACI,sCAAAA,0BAAD,CAA2B,CAAA;YAChE,CAAA;WACH;UACC,CAAA,CAAA;;SACP,MAAM,SAAS,KACd,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;UAAK,WAAWT,6BAAI;UAClB,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;WAAK,WAAWA,6BAAI;WAAW,OAAO,EAAE,OAAO,GAAG,IAAI,GAAG;UAAI,CAAA;SAC1D,CAAA;SAEN,YACC,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;UAAK,WAAWA,6BAAI;UAApB,UAAA;WACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;YAAK,WAAWA,6BAAI;YAApB,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;aAAK,WAAWA,6BAAI;aAApB,UAAA,CACG,EAAE,YAAY,GACd,MAAM,SAAS,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;cAAM,WAAWA,6BAAI;cAAe,UAAA,MAAM;aAAa,CAAA,CACzE;YACJ,CAAA,GAAA,MAAM,SAAS,IACd,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;aAAI,WAAWA,6BAAI;aAChB,UAAA,MAAM,KAAK,MAAM,MAAM;cACtB,MAAM,YAAY,WAAW,SAAS,WAAW,KAAK,MAAM,QAAQ,UAAU;cAC9E,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,MAAD;eAAY,WAAWA,6BAAI;eAA3B,UAAA,CACG,UACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;gBACE,MAAK;gBACL,WAAWA,6BAAI;gBACf,UAAU;gBACV,eAAe,YAAY,KAAK,IAAI,CAAC;gBACrC,OAAO,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,cAAc,EAAE;gBAE5E,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD,EAAU,QAAQ,KAAK,OAAS,CAAA;eAC1B,CAAA,IAER,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD,EAAU,QAAQ,KAAK,OAAS,CAAA,GAEjC,YACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;gBACE,OAAO,QAAS;gBAChB,WAAW,MAAM,eAAe,KAAK,IAAI,GAAG,CAAC;gBAC7C,gBAAgB,WAAW,IAAI;eAChC,CAAA,IAED,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;gBACE,WAAW,GAAGA,6BAAI,cAAc,KAAK,WAAW,cAAc,IAAIA,6BAAI,oBAAoB,KAAK,KAAK,WAAW,gBAAgB,IAAIA,6BAAI,mBAAmB,KAAK,UAAU,IAAIA,6BAAI,iBAAiB;gBAClM,OAAO,UAAU,EAAE,gBAAgB,IAAI,KAAA;gBACvC,qBAAqB;iBACnB,IAAI,SAAS,WAAW;kBAAE,QAAQ,KAAK;kBAAI,OAAO;kBAAG,OAAO,OAAO,KAAK,WAAW,EAAE;iBAAE,CAAC;gBAC1F;gBAEC,UAAA,KAAK;eACF,CAAA,CAEN;cA/BK,GAAA,CA+BL;aAER,CAAC;YACC,CAAA,IAEJ,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;aAAK,WAAWA,6BAAI;aAAQ,UAAA,EAAE,kBAAkB;YAAO,CAAA,CAEtD;;YAEH,KAAK,OAAO,UAAU,KAAK,KAC3B,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;YAAK,WAAWA,6BAAI;YAApB,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;aAAK,WAAWA,6BAAI;aAApB,UAAA,CACG,EAAE,YAAY,GACf,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;cAAM,WAAWA,6BAAI;cAAe,UAAA,KAAK,MAAM;aAAa,CAAA,CACzD;YACL,CAAA,GAAA,iBAAA,GAAA,kBAAA,KAAA,CAAC,MAAD;aAAI,WAAWA,6BAAI;aAAnB,UAAA,CACG,KAAK,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC,KAAK,MAAM,MAClC,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;cACE,WAAWA,6BAAI;cACf,eAAe,SAAS,KAAK,IAAI;cACjC,OAAO,GAAG,EAAE,eAAe,KAAK,OAAO,gBAAgB,WAAW,EAAE,IAAI,KAAK,OAAO,KAAK,OAAO,IAAI,KAAK,SAAS;cAHpH,UAAA;eAKE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,WAAWA,6BAAI,QAAU,CAAA;eAC/B,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;gBAAM,WAAWA,6BAAI;gBAAW,UAAA,KAAK;eAAW,CAAA;eAC/C,KAAK,QAAQ,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;gBAAM,WAAWA,6BAAI;gBAArB,UAAA,CAA+B,KAAE,KAAK,IAAW;;cACzD;aACN,CAAA,EAAA,GAVK,CAUL,CACL,IACC,KAAK,OAAO,UAAU,KAAK,MAC3B,iBAAA,GAAA,kBAAA,KAAA,CAAC,MAAD;cAAI,WAAWA,6BAAI;cAAnB,UAAA;eAA0B;eAAK,KAAK,MAAM;eAAO;cAAM;aAEvD,CAAA,CAAA;YACD,CAAA,CAAA;;WAGP,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;YAAK,WAAWA,6BAAI;YAApB,UAAA;aACE,iBAAA,GAAA,kBAAA,IAAA,CAACO,sCAAAA,QAAD;cACE,SAAQ;cACR,MAAK;cACL,UAAU,WAAW;cACrB,eAAe,KAAK,aAAa,UAAU,KAAK,EAAE;cAEjD,UAAA,EAAE,aAAa;aACV,CAAA;aACP,WACC,iBAAA,GAAA,kBAAA,IAAA,CAACA,sCAAAA,QAAD;cACE,SAAQ;cACR,MAAK;cACL,UAAU;cACV,eAAe,KAAK,QAAQ,cAAc;cAC1C,OAAO,EAAE,aAAa;cAErB,UAAA,EAAE,aAAa;aACV,CAAA;aAEV,iBAAA,GAAA,kBAAA,IAAA,CAACA,sCAAAA,QAAD;cACE,SAAQ;cACR,MAAK;cACL,UAAU;cACV,eAAe,KAAK,aAAa,WAAW,KAAK,EAAE;cAElD,UAAA,EAAE,cAAc;aACX,CAAA;YACL;;UACF;;QAEA;OA5JK,GAAA,KAAK,EA4JV;MAEb,CAAC,GACA,WAAW,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;OAAK,WAAWP,6BAAI;OAAW,UAAA,EAAE,eAAe;MAAO,CAAA,CAChE;;IAEJ;;EAET;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EC9nBA,SAAgB,gBAAgB,EAAE,QAAwB;GACxD,MAAM,OAAO,MAAM,QAAQ;GAC3B,MAAM,UAAU,MAAM,WAAW;GAEjC,MAAM,QADO,OAAO,MAAM,SAAS,WAAW,KAAK,OAAO,GAAA,CACxC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;GAC5C,MAAM,SAAS,SAAS,WAAW,CAAC;GACpC,MAAM,OAAO,SAAS,QAAQ;GAE9B,MAAM,SAAS,qBAAqB,IAAI;GAKxC,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,IAAI,CAAC,QAAQ;IACb,UAAU,QAAQ,SAAS;KACzB,OAAO,OAAO;KACd,aAAa,OAAO;KACpB,eAAe,OAAO;IACxB,CAAC;IACD,IAAI,QAAQ,UAAU,QAAQ,KAAK;GAErC,GAAG,CAAC,IAAI,CAAC;GAGT,IAAI,YAAY,MACd,OAAO,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAWW,mCAAI;IAAK,gBAAa;IAAtC,UAAA;KAAgD;KAAE;KAAK;IAAU;;GAI1E,IAAI,QAAQ,SAAS,SAAS;IAC5B,MAAM,QAAQ,OAAO,QAAQ,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC,MAAM,GAAG,GAAG;IAC5D,OAAO,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;KAAK,WAAWA,mCAAI;KAAK,gBAAa;KAAtC,UAAA;MAA8C;MAAE;MAAK;MAAI,QAAQ,IAAI,UAAU;KAAQ;;GAChG;GAGA,IAAI,CAAC,QAAQ;IACX,MAAM,OAAO,OAAO,QAAQ,EAAE,CAAC,CAC5B,MAAM,QAAQ,CAAC,CAAC,EAAE,CAClB,QAAQ,WAAW,EAAE,CAAC,CACtB,KAAK,CAAC,CACN,MAAM,GAAG,GAAG;IACf,OAAO,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;KAAK,WAAWA,mCAAI;KAAK,gBAAa;KAAtC,UAAA;MAA2C;MAAE;MAAK;MAAE,QAAQ;KAAW;;GAChF;GAGA,MAAM,QAAQ,SAAS,OAAO,MAAM,SAAS;GAC7C,MAAM,WAAW,SAAS,OAAO,WAAW;GAC5C,MAAM,QAAQ,SACV,MAAM,MAAM,IAAI,WAAW,OAAO,SAAS,KAAK,GAAG,eACnD,IAAI,KAAK;GACb,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAWA,mCAAI;IAAK,gBAAa;IAAtC,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,yBAAD,EAAyB,WAAWD,mCAAI,KAAO,CAAA,GAC/C,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,MAAY,CAAA,CAChB;;EAET;;;;;;;;;;;;;;;;ECxDA,MAAM,KAAK;EAEX,MAAa,OAAO;;EAGpB,MAAa,SAAS;GAAC;GAAS;GAAY;GAAU;EAAiB;EAEvE,SAAgB,MAAM,KAAgB;GACpC,MAAM,QAAQ,KAAK;GACnB,IAAI,CAAC,SAAS,OAAO,MAAM,WAAW,YAAY;IAChD,QAAQ,KAAK,IAAI,GAAG,kDAAkD;IACtE;GACF;GACA,IAAI;IACF,MAAM,OAAO,uBAAuB,MAAM,SACxC;KACE,MAAM;KACN,IAAI;KACJ,OAAO;IACT,UAAA,GACME,MAAAA,cAAAA,CAAc,gBAAgB,EAAE,IAAI,CAAC,CAC7C,CAAC;IAKD,KAAK,MAAM,OAAO,CADA,SAAS,MACF,GACvB,MAAM,OAAO,uCAAuC,MAAM,SACxD;KAAE,MAAM;KAAiC;IAAI,GAC7C,eACF,CAAC;GAEL,SAAS,KAAK;IACZ,QAAQ,KAAK,IAAI,GAAG,oCAAoC,GAAG;GAC7D;EACF"}
@@ -0,0 +1,395 @@
1
+ .vZSZnG_panel {
2
+ z-index: 1000;
3
+ background: var(--dsw-surface-elevated);
4
+ border: 1px solid var(--dsw-border-subtle);
5
+ width: 420px;
6
+ max-height: 560px;
7
+ box-shadow: var(--dsw-shadow-elevated);
8
+ font-family: var(--dsw-font-family);
9
+ color: var(--dsw-text-primary);
10
+ user-select: none;
11
+ border-radius: 12px;
12
+ flex-direction: column;
13
+ display: flex;
14
+ position: fixed;
15
+ overflow: hidden;
16
+ }
17
+
18
+ .vZSZnG_dragHandle {
19
+ cursor: grab;
20
+ background: none;
21
+ height: 8px;
22
+ position: absolute;
23
+ top: 0;
24
+ left: 0;
25
+ right: 0;
26
+ }
27
+
28
+ .vZSZnG_dragHandle:active {
29
+ cursor: grabbing;
30
+ }
31
+
32
+ .vZSZnG_header {
33
+ border-bottom: 1px solid var(--dsw-border-subtle);
34
+ background: var(--dsw-surface);
35
+ flex-shrink: 0;
36
+ justify-content: space-between;
37
+ align-items: center;
38
+ padding: 12px 16px;
39
+ display: flex;
40
+ }
41
+
42
+ .vZSZnG_headerLeft {
43
+ align-items: center;
44
+ gap: 8px;
45
+ display: flex;
46
+ }
47
+
48
+ .vZSZnG_headerIcon {
49
+ color: var(--dsw-accent);
50
+ flex-shrink: 0;
51
+ }
52
+
53
+ .vZSZnG_headerTitle {
54
+ color: var(--dsw-text-primary);
55
+ margin: 0;
56
+ font-size: 14px;
57
+ font-weight: 600;
58
+ line-height: 1.3;
59
+ }
60
+
61
+ .vZSZnG_badge {
62
+ color: var(--dsw-text-muted);
63
+ background: var(--dsw-surface-hover);
64
+ border-radius: 10px;
65
+ padding: 2px 8px;
66
+ font-size: 11px;
67
+ font-weight: 500;
68
+ }
69
+
70
+ .vZSZnG_headerRight {
71
+ gap: 4px;
72
+ display: flex;
73
+ }
74
+
75
+ .vZSZnG_taskList {
76
+ flex-direction: column;
77
+ flex: 1;
78
+ gap: 8px;
79
+ padding: 8px;
80
+ display: flex;
81
+ overflow-y: auto;
82
+ }
83
+
84
+ .vZSZnG_taskItem {
85
+ background: var(--dsw-surface);
86
+ border: 1px solid var(--dsw-border-subtle);
87
+ border-radius: 8px;
88
+ overflow: hidden;
89
+ }
90
+
91
+ .vZSZnG_taskHeader {
92
+ cursor: pointer;
93
+ text-align: left;
94
+ width: 100%;
95
+ color: inherit;
96
+ background: none;
97
+ border: none;
98
+ justify-content: space-between;
99
+ align-items: center;
100
+ gap: 12px;
101
+ padding: 12px;
102
+ display: flex;
103
+ }
104
+
105
+ .vZSZnG_taskHeader:hover {
106
+ background: var(--dsw-surface-hover);
107
+ }
108
+
109
+ .vZSZnG_taskMain {
110
+ flex: 1;
111
+ align-items: center;
112
+ gap: 8px;
113
+ min-width: 0;
114
+ display: flex;
115
+ }
116
+
117
+ .vZSZnG_boundBadge {
118
+ color: var(--dsw-accent);
119
+ background: var(--dsw-accent-bg);
120
+ text-transform: uppercase;
121
+ letter-spacing: .3px;
122
+ border-radius: 4px;
123
+ padding: 2px 6px;
124
+ font-size: 10px;
125
+ font-weight: 600;
126
+ }
127
+
128
+ .vZSZnG_taskTitle {
129
+ color: var(--dsw-text-primary);
130
+ white-space: nowrap;
131
+ text-overflow: ellipsis;
132
+ font-size: 13px;
133
+ font-weight: 500;
134
+ line-height: 1.4;
135
+ overflow: hidden;
136
+ }
137
+
138
+ .vZSZnG_taskProgress {
139
+ color: var(--dsw-text-secondary);
140
+ font-variant-numeric: tabular-nums;
141
+ font-size: 11px;
142
+ }
143
+
144
+ .vZSZnG_taskActions {
145
+ align-items: center;
146
+ gap: 8px;
147
+ display: flex;
148
+ }
149
+
150
+ .vZSZnG_progressRing {
151
+ flex-shrink: 0;
152
+ width: 28px;
153
+ height: 28px;
154
+ }
155
+
156
+ .vZSZnG_progressBg {
157
+ stroke: var(--dsw-border-subtle);
158
+ }
159
+
160
+ .vZSZnG_progressFg {
161
+ stroke: var(--dsw-accent);
162
+ stroke-linecap: round;
163
+ transform-origin: center;
164
+ transition: stroke-dasharray .3s ease-out;
165
+ transform: rotate(-90deg);
166
+ }
167
+
168
+ .vZSZnG_chevron {
169
+ color: var(--dsw-text-muted);
170
+ flex-shrink: 0;
171
+ }
172
+
173
+ .vZSZnG_taskExpanded {
174
+ border-top: 1px solid var(--dsw-border-subtle);
175
+ padding: 0 12px 12px;
176
+ animation: .2s ease-out vZSZnG_expandIn;
177
+ }
178
+
179
+ @keyframes vZSZnG_expandIn {
180
+ from {
181
+ opacity: 0;
182
+ transform: translateY(-4px);
183
+ }
184
+
185
+ to {
186
+ opacity: 1;
187
+ transform: translateY(0);
188
+ }
189
+ }
190
+
191
+ .vZSZnG_sectionLabel {
192
+ color: var(--dsw-text-muted);
193
+ text-transform: uppercase;
194
+ letter-spacing: .5px;
195
+ margin-bottom: 8px;
196
+ font-size: 11px;
197
+ font-weight: 600;
198
+ }
199
+
200
+ .vZSZnG_stepsList {
201
+ flex-direction: column;
202
+ gap: 6px;
203
+ display: flex;
204
+ }
205
+
206
+ .vZSZnG_stepRow {
207
+ background: var(--dsw-surface);
208
+ border: 1px solid var(--dsw-border-subtle);
209
+ border-radius: 6px;
210
+ align-items: center;
211
+ gap: 8px;
212
+ padding: 6px 8px;
213
+ display: flex;
214
+ }
215
+
216
+ .vZSZnG_stepIconCompleted {
217
+ color: var(--dsw-success);
218
+ }
219
+
220
+ .vZSZnG_stepIconProgress {
221
+ color: var(--dsw-accent);
222
+ animation: 1.5s ease-in-out infinite vZSZnG_pulse;
223
+ }
224
+
225
+ .vZSZnG_stepIconPending {
226
+ color: var(--dsw-text-muted);
227
+ }
228
+
229
+ @keyframes vZSZnG_pulse {
230
+ 0%, 100% {
231
+ opacity: .6;
232
+ }
233
+
234
+ 50% {
235
+ opacity: 1;
236
+ }
237
+ }
238
+
239
+ .vZSZnG_stepContent {
240
+ color: var(--dsw-text-primary);
241
+ flex: 1;
242
+ font-size: 12px;
243
+ line-height: 1.45;
244
+ }
245
+
246
+ .vZSZnG_stepCompleted {
247
+ color: var(--dsw-text-muted);
248
+ text-decoration: line-through;
249
+ }
250
+
251
+ .vZSZnG_section {
252
+ margin-top: 12px;
253
+ }
254
+
255
+ .vZSZnG_filesList {
256
+ flex-direction: column;
257
+ gap: 4px;
258
+ display: flex;
259
+ }
260
+
261
+ .vZSZnG_fileRow {
262
+ background: var(--dsw-surface);
263
+ border: 1px solid var(--dsw-border-subtle);
264
+ cursor: pointer;
265
+ text-align: left;
266
+ color: var(--dsw-text-primary);
267
+ border-radius: 6px;
268
+ align-items: center;
269
+ gap: 8px;
270
+ width: 100%;
271
+ padding: 6px 8px;
272
+ font-size: 12px;
273
+ display: flex;
274
+ }
275
+
276
+ .vZSZnG_fileRow:hover {
277
+ background: var(--dsw-surface-hover);
278
+ border-color: var(--dsw-accent);
279
+ }
280
+
281
+ .vZSZnG_fileIcon {
282
+ color: var(--dsw-text-muted);
283
+ flex-shrink: 0;
284
+ }
285
+
286
+ .vZSZnG_filePath {
287
+ white-space: nowrap;
288
+ text-overflow: ellipsis;
289
+ flex: 1;
290
+ font-size: 12px;
291
+ overflow: hidden;
292
+ }
293
+
294
+ .vZSZnG_fileLine {
295
+ color: var(--dsw-text-muted);
296
+ font-variant-numeric: tabular-nums;
297
+ font-size: 11px;
298
+ }
299
+
300
+ .vZSZnG_moreFiles {
301
+ color: var(--dsw-text-muted);
302
+ padding: 4px 8px;
303
+ font-size: 11px;
304
+ }
305
+
306
+ .vZSZnG_taskFooter {
307
+ border-top: 1px solid var(--dsw-border-subtle);
308
+ gap: 8px;
309
+ margin-top: 12px;
310
+ padding-top: 12px;
311
+ display: flex;
312
+ }
313
+
314
+ .vZSZnG_taskFooter button {
315
+ flex: 1;
316
+ }
317
+
318
+ .vZSZnG_emptyState {
319
+ text-align: center;
320
+ color: var(--dsw-text-muted);
321
+ flex-direction: column;
322
+ flex: 1;
323
+ justify-content: center;
324
+ align-items: center;
325
+ padding: 32px 24px;
326
+ display: flex;
327
+ }
328
+
329
+ .vZSZnG_emptyIcon {
330
+ color: var(--dsw-text-muted);
331
+ opacity: .5;
332
+ margin-bottom: 16px;
333
+ }
334
+
335
+ .vZSZnG_emptyState p {
336
+ color: var(--dsw-text-secondary);
337
+ margin: 0 0 8px;
338
+ font-size: 13px;
339
+ }
340
+
341
+ .vZSZnG_emptyDesc {
342
+ max-width: 280px;
343
+ font-size: 11px !important;
344
+ }
345
+
346
+ .vZSZnG_miniBar {
347
+ z-index: 1000;
348
+ background: var(--dsw-surface-elevated);
349
+ border: 1px solid var(--dsw-border-subtle);
350
+ box-shadow: var(--dsw-shadow-elevated);
351
+ cursor: pointer;
352
+ border-radius: 8px;
353
+ align-items: center;
354
+ gap: 8px;
355
+ padding: 8px 12px;
356
+ transition: transform .15s, box-shadow .15s;
357
+ display: flex;
358
+ position: fixed;
359
+ bottom: 16px;
360
+ right: 16px;
361
+ }
362
+
363
+ .vZSZnG_miniBar:hover {
364
+ box-shadow: var(--dsw-shadow-dragging);
365
+ transform: translateY(-2px);
366
+ }
367
+
368
+ .vZSZnG_miniIcon {
369
+ color: var(--dsw-accent);
370
+ }
371
+
372
+ .vZSZnG_miniTitle {
373
+ color: var(--dsw-text-primary);
374
+ white-space: nowrap;
375
+ font-size: 12px;
376
+ font-weight: 500;
377
+ }
378
+
379
+ .vZSZnG_miniChevron {
380
+ color: var(--dsw-text-muted);
381
+ }
382
+
383
+ @media (width <= 600px) {
384
+ .vZSZnG_panel {
385
+ width: calc(100vw - 32px);
386
+ max-width: 420px;
387
+ }
388
+ }
389
+
390
+ @media (prefers-reduced-motion: reduce) {
391
+ .vZSZnG_taskExpanded, .vZSZnG_progressFg, .vZSZnG_miniBar, .vZSZnG_stepIconProgress {
392
+ transition: none !important;
393
+ animation: none !important;
394
+ }
395
+ }
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@yolk_vat-y/dsh-project-memory",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
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",
7
7
  "files": [
8
8
  "src",
9
+ "client",
9
10
  "cordis.patch.yml",
10
11
  "README.md",
11
12
  "README.zh-CN.md",
@@ -16,7 +17,8 @@
16
17
  "url": "https://github.com/00080000/dsh-project-memory.git"
17
18
  },
18
19
  "scripts": {
19
- "test": "node test/run-test.mjs"
20
+ "test": "node test/run-test.mjs",
21
+ "build:client": "tsdown"
20
22
  },
21
23
  "keywords": [
22
24
  "dsh",
@@ -30,7 +32,8 @@
30
32
  ],
31
33
  "license": "MIT",
32
34
  "publishConfig": {
33
- "access": "public"
35
+ "access": "public",
36
+ "registry": "https://registry.npmjs.org"
34
37
  },
35
38
  "engines": {
36
39
  "node": ">=18"
@@ -40,9 +43,17 @@
40
43
  },
41
44
  "devDependencies": {
42
45
  "@deepseek-ai/cordis": "^4.0.2",
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",
43
51
  "@deepseek-ai/dsh-llm": "^0.1.2-alpha.2",
44
52
  "@deepseek-ai/dsh-tools": "^0.1.2-alpha.2",
45
53
  "@deepseek-ai/schemastery": "^3.18.2",
54
+ "@tsdown/css": "^0.23.0",
55
+ "lightningcss": "^1.33.0",
56
+ "tsdown": "^0.22.14",
46
57
  "typescript": "^5.6.3"
47
58
  },
48
59
  "peerDependencies": {
@@ -50,7 +61,7 @@
50
61
  "@deepseek-ai/dsh-llm": ">=0.0.1-rc.1 <0.1.0 || >=0.1.0-rc.1 <0.2.0-0 || >=0.1.1-rc.1 <0.2.0-0",
51
62
  "@deepseek-ai/dsh-tools": ">=0.0.1-rc.1 <0.1.0 || >=0.1.0-rc.1 <0.2.0-0 || >=0.1.1-rc.1 <0.2.0-0",
52
63
  "@deepseek-ai/schemastery": "^3.18.1",
53
- "typescript": "^5.0.0"
64
+ "typescript": "^5.0.0 || ^6.0.0"
54
65
  },
55
66
  "peerDependenciesMeta": {
56
67
  "@deepseek-ai/cordis": {
@@ -72,6 +83,21 @@
72
83
  "dsh": {
73
84
  "bundle": {
74
85
  "patch": "./cordis.patch.yml"
86
+ },
87
+ "client": {
88
+ "inject": [
89
+ "@deepseek-ai/dsh-client-runtime",
90
+ "@deepseek-ai/dsh-client-locale",
91
+ "@deepseek-ai/dsh-client-ui-primitives",
92
+ "@deepseek-ai/dsh-client-ui-slots",
93
+ "@deepseek-ai/dsh-client-store"
94
+ ],
95
+ "platform": "web"
75
96
  }
97
+ },
98
+ "exports": {
99
+ ".": "./src/index.js",
100
+ "./client": "./client/client.js",
101
+ "./cordis.patch.yml": "./cordis.patch.yml"
76
102
  }
77
103
  }
@@ -0,0 +1,27 @@
1
+ /* /tasks、/task 命令节点渲染:极简单行,替换原大段文本+JSON。 */
2
+ .row {
3
+ display: inline-flex;
4
+ align-items: center;
5
+ gap: 6px;
6
+ max-width: 100%;
7
+ font-size: 12px;
8
+ line-height: 20px;
9
+ padding: 2px 0;
10
+ color: var(--dsw-alias-label-tertiary);
11
+ white-space: nowrap;
12
+ overflow: hidden;
13
+ text-overflow: ellipsis;
14
+ }
15
+ .row[data-variant='ok'] {
16
+ color: var(--dsw-alias-label-secondary);
17
+ }
18
+ .row[data-variant='error'] {
19
+ color: var(--dsw-alias-state-warn-label, #b7791f);
20
+ }
21
+ .row[data-variant='running'] {
22
+ color: var(--dsw-alias-label-dimmed);
23
+ }
24
+ .icon {
25
+ flex: none;
26
+ color: var(--dsw-alias-label-tertiary);
27
+ }