@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/src/client/task-store.ts
DELETED
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Task Panel Client Store(自包含:不依赖宿主 store 包)
|
|
3
|
-
* Reactive store for task list, bound task, UI state.
|
|
4
|
-
* 数据由 /tasks、/task 命令执行结果(JSON 载荷)写入,localStorage 持久化 UI 状态。
|
|
5
|
-
*/
|
|
6
|
-
import { useSyncExternalStore } from 'react'
|
|
7
|
-
|
|
8
|
-
export interface TaskStep {
|
|
9
|
-
content: string
|
|
10
|
-
status: 'pending' | 'in_progress' | 'completed'
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface TaskFile {
|
|
14
|
-
path: string
|
|
15
|
-
line?: number
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface Task {
|
|
19
|
-
id: string
|
|
20
|
-
title: string
|
|
21
|
-
steps: TaskStep[]
|
|
22
|
-
files: TaskFile[]
|
|
23
|
-
lastActiveAt: string
|
|
24
|
-
updatedAt: string
|
|
25
|
-
archived?: boolean
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface TaskPanelState {
|
|
29
|
-
tasks: Task[]
|
|
30
|
-
boundTaskId: string | null
|
|
31
|
-
archivedCount: number
|
|
32
|
-
// UI state
|
|
33
|
-
expandedTaskIds: string[]
|
|
34
|
-
panelPosition: { x: number; y: number }
|
|
35
|
-
/** true = 折叠成顶部迷你条(仍可见、可拖拽)。 */
|
|
36
|
-
minimized: boolean
|
|
37
|
-
/** true = 彻底隐藏(无迷你条),仅可通过 /task /tasks 或重新加载唤起。 */
|
|
38
|
-
closed: boolean
|
|
39
|
-
/** 卡片强调色主题:native 或 accent 名(azure/violet/teal/rose)。 */
|
|
40
|
-
theme: string
|
|
41
|
-
lastUpdate: number
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/** /tasks 命令响应(text)里夹带的 JSON 载荷结构。 */
|
|
45
|
-
export interface TaskPayload {
|
|
46
|
-
tasks: Task[]
|
|
47
|
-
boundId: string | null
|
|
48
|
-
archived: number
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/** 从命令输出文本中解析任务快照 JSON(支持 fenced ```json 块或尾部对象)。 */
|
|
52
|
-
export function parseTaskPayloadText(text?: string | null): TaskPayload | null {
|
|
53
|
-
if (!text) return null
|
|
54
|
-
let jsonBlock: string | null = null
|
|
55
|
-
const fenced = text.match(/```(?:json)?\s*\n([\s\S]*?)\n```/)
|
|
56
|
-
if (fenced) jsonBlock = fenced[1]
|
|
57
|
-
else {
|
|
58
|
-
const lastBrace = text.lastIndexOf('{')
|
|
59
|
-
if (lastBrace !== -1) jsonBlock = text.slice(lastBrace)
|
|
60
|
-
}
|
|
61
|
-
if (!jsonBlock) return null
|
|
62
|
-
try {
|
|
63
|
-
const data = JSON.parse(jsonBlock)
|
|
64
|
-
if (!Array.isArray(data.tasks)) return null
|
|
65
|
-
return { tasks: data.tasks, boundId: data.boundId ?? null, archived: data.archived ?? 0 }
|
|
66
|
-
} catch {
|
|
67
|
-
return null
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const STORAGE_KEY = 'dsh-pm-task-panel-state'
|
|
72
|
-
|
|
73
|
-
function defaultPosition(): { x: number; y: number } {
|
|
74
|
-
if (typeof window !== 'undefined') {
|
|
75
|
-
return { x: Math.max(16, window.innerWidth - 408), y: 72 }
|
|
76
|
-
}
|
|
77
|
-
return { x: 0, y: 0 }
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function getDefaultState(): TaskPanelState {
|
|
81
|
-
if (typeof window !== 'undefined') {
|
|
82
|
-
try {
|
|
83
|
-
const saved = localStorage.getItem(STORAGE_KEY)
|
|
84
|
-
if (saved) {
|
|
85
|
-
const parsed = JSON.parse(saved)
|
|
86
|
-
return {
|
|
87
|
-
tasks: Array.isArray(parsed.tasks) ? parsed.tasks : [],
|
|
88
|
-
boundTaskId: parsed.boundTaskId ?? null,
|
|
89
|
-
archivedCount: parsed.archivedCount ?? 0,
|
|
90
|
-
expandedTaskIds: Array.isArray(parsed.expandedTaskIds) ? parsed.expandedTaskIds : [],
|
|
91
|
-
panelPosition: parsed.panelPosition ?? defaultPosition(),
|
|
92
|
-
minimized: parsed.minimized !== false, // 默认折叠成迷你条
|
|
93
|
-
theme: typeof parsed.theme === 'string' ? parsed.theme : 'native',
|
|
94
|
-
closed: !!parsed.closed,
|
|
95
|
-
lastUpdate: parsed.lastUpdate ?? 0,
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
} catch { /* corrupt state — fall through to defaults */ }
|
|
99
|
-
}
|
|
100
|
-
return {
|
|
101
|
-
tasks: [],
|
|
102
|
-
boundTaskId: null,
|
|
103
|
-
archivedCount: 0,
|
|
104
|
-
expandedTaskIds: [],
|
|
105
|
-
panelPosition: defaultPosition(),
|
|
106
|
-
minimized: true, // 默认折叠,不打扰
|
|
107
|
-
closed: false,
|
|
108
|
-
theme: 'native',
|
|
109
|
-
lastUpdate: 0,
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function persist(state: TaskPanelState): void {
|
|
114
|
-
if (typeof window === 'undefined') return
|
|
115
|
-
try {
|
|
116
|
-
localStorage.setItem(STORAGE_KEY, JSON.stringify(state))
|
|
117
|
-
} catch { /* storage full/unavailable — non-fatal */ }
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
let state: TaskPanelState = getDefaultState()
|
|
121
|
-
const listeners = new Set<() => void>()
|
|
122
|
-
|
|
123
|
-
function setState(next: TaskPanelState): void {
|
|
124
|
-
state = next
|
|
125
|
-
persist(next)
|
|
126
|
-
for (const listener of listeners) listener()
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export const taskStore = {
|
|
130
|
-
subscribe(listener: () => void): () => void {
|
|
131
|
-
listeners.add(listener)
|
|
132
|
-
return () => { listeners.delete(listener) }
|
|
133
|
-
},
|
|
134
|
-
getSnapshot(): TaskPanelState {
|
|
135
|
-
return state
|
|
136
|
-
},
|
|
137
|
-
actions: {
|
|
138
|
-
setTasks(payload: { tasks: Task[]; boundTaskId: string | null; archivedCount: number }): void {
|
|
139
|
-
const prev = state
|
|
140
|
-
setState({
|
|
141
|
-
...prev,
|
|
142
|
-
tasks: payload.tasks || [],
|
|
143
|
-
boundTaskId: payload.boundTaskId ?? null,
|
|
144
|
-
archivedCount: payload.archivedCount ?? 0,
|
|
145
|
-
lastUpdate: Date.now(),
|
|
146
|
-
})
|
|
147
|
-
},
|
|
148
|
-
toggleTaskExpanded(taskId: string): void {
|
|
149
|
-
const prev = state
|
|
150
|
-
const ids = prev.expandedTaskIds.includes(taskId)
|
|
151
|
-
? prev.expandedTaskIds.filter((id) => id !== taskId)
|
|
152
|
-
: [...prev.expandedTaskIds, taskId]
|
|
153
|
-
setState({ ...prev, expandedTaskIds: ids })
|
|
154
|
-
},
|
|
155
|
-
expandAll(): void {
|
|
156
|
-
const prev = state
|
|
157
|
-
setState({ ...prev, expandedTaskIds: prev.tasks.map((t) => t.id) })
|
|
158
|
-
},
|
|
159
|
-
setPanelPosition(pos: { x: number; y: number }): void {
|
|
160
|
-
setState({ ...state, panelPosition: pos })
|
|
161
|
-
},
|
|
162
|
-
/** 展开面板(同时解除隐藏/折叠)。 */
|
|
163
|
-
open(): void {
|
|
164
|
-
setState({ ...state, minimized: false, closed: false })
|
|
165
|
-
},
|
|
166
|
-
/** 折叠成顶部迷你条(仍可见)。 */
|
|
167
|
-
minimize(): void {
|
|
168
|
-
setState({ ...state, minimized: true, closed: false })
|
|
169
|
-
},
|
|
170
|
-
/** 彻底隐藏(无迷你条);仅能通过 /task、/tasks 或重新加载唤起。 */
|
|
171
|
-
close(): void {
|
|
172
|
-
setState({ ...state, minimized: true, closed: true })
|
|
173
|
-
},
|
|
174
|
-
setTheme(theme: string): void {
|
|
175
|
-
setState({ ...state, theme })
|
|
176
|
-
},
|
|
177
|
-
setMinimized(minimized: boolean): void {
|
|
178
|
-
setState({ ...state, minimized, closed: minimized ? state.closed : false })
|
|
179
|
-
},
|
|
180
|
-
reset(): void {
|
|
181
|
-
setState(getDefaultState())
|
|
182
|
-
},
|
|
183
|
-
},
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
export function useTaskStore(): TaskPanelState {
|
|
187
|
-
return useSyncExternalStore(taskStore.subscribe, taskStore.getSnapshot, taskStore.getSnapshot)
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
export function useTaskActions() {
|
|
191
|
-
return taskStore.actions
|
|
192
|
-
}
|