@yolk_vat-y/dsh-project-memory 0.4.4 → 0.5.0

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/client/client.js CHANGED
@@ -49,7 +49,41 @@ window.__ModuleLoader__.load({
49
49
  "minibar.current": "当前任务",
50
50
  "minibar.click-expand": "点击展开并同步",
51
51
  "minibar.tasks": "个任务",
52
- "minibar.no-task": "暂无任务 · 点击查看"
52
+ "minibar.no-task": "暂无任务 · 点击查看",
53
+ "view.cycle": "切换视图:任务 / 项目记忆 / 全局记忆",
54
+ "view.task": "任务",
55
+ "view.project": "项目记忆",
56
+ "view.global": "全局记忆",
57
+ "mem.scope.task": "本任务草稿",
58
+ "mem.scope.project": "项目记忆",
59
+ "mem.scope.global": "全局记忆",
60
+ "mem.empty": "暂无记忆条目(反思或 save_lesson 后出现)",
61
+ "mem.confirm": "审核",
62
+ "mem.promote": "提升",
63
+ "mem.demote": "降级",
64
+ "mem.archive": "归档",
65
+ "mem.restore": "恢复",
66
+ "mem.delete": "删除",
67
+ "mem.draft": "草稿",
68
+ "mem.archived": "已归档",
69
+ "mem.loading": "加载中…",
70
+ "mem.error": "同步失败",
71
+ "mem.kind.lesson": "坑",
72
+ "mem.kind.decision": "权衡",
73
+ "mem.kind.procedure": "指南",
74
+ "mem.kind.experience": "经验",
75
+ "mem.needs-bound": "需绑定任务后可降级",
76
+ "mem.new": "新建",
77
+ "mem.save": "保存",
78
+ "mem.cancel": "取消",
79
+ "mem.f.title": "标题(教训模式/主题/指南名)",
80
+ "mem.f.kind": "类型",
81
+ "mem.f.body": "做法 / 理由 / 解法",
82
+ "mem.f.steps": "步骤(每行一步)",
83
+ "mem.f.trigger": "作为 Skill:触发关键词(逗号分隔)",
84
+ "mem.saved": "已保存",
85
+ "mem.edit": "编辑",
86
+ "mem.section-label": "任务记忆"
53
87
  };
54
88
  const en = {
55
89
  "panel.title": "Task Flow",
@@ -89,7 +123,41 @@ window.__ModuleLoader__.load({
89
123
  "minibar.current": "Current task",
90
124
  "minibar.click-expand": "Click to expand & sync",
91
125
  "minibar.tasks": "tasks",
92
- "minibar.no-task": "No tasks · click to view"
126
+ "minibar.no-task": "No tasks · click to view",
127
+ "view.cycle": "Switch view: tasks / project memory / global memory",
128
+ "view.task": "Tasks",
129
+ "view.project": "Project Memory",
130
+ "view.global": "Global Memory",
131
+ "mem.scope.task": "Task drafts",
132
+ "mem.scope.project": "Project memory",
133
+ "mem.scope.global": "Global memory",
134
+ "mem.empty": "No memory entries yet (created by reflection or save_lesson)",
135
+ "mem.confirm": "Approve",
136
+ "mem.promote": "Promote",
137
+ "mem.demote": "Demote",
138
+ "mem.archive": "Archive",
139
+ "mem.restore": "Restore",
140
+ "mem.delete": "Delete",
141
+ "mem.draft": "draft",
142
+ "mem.archived": "archived",
143
+ "mem.loading": "Loading…",
144
+ "mem.error": "Sync failed",
145
+ "mem.kind.lesson": "lesson",
146
+ "mem.kind.decision": "decision",
147
+ "mem.kind.procedure": "procedure",
148
+ "mem.kind.experience": "experience",
149
+ "mem.needs-bound": "Bind a task to demote",
150
+ "mem.new": "New",
151
+ "mem.save": "Save",
152
+ "mem.cancel": "Cancel",
153
+ "mem.f.title": "Title (pattern / topic / procedure name)",
154
+ "mem.f.kind": "Kind",
155
+ "mem.f.body": "Fix / reason / solution",
156
+ "mem.f.steps": "Steps (one per line)",
157
+ "mem.f.trigger": "As Skill: trigger keywords (comma separated)",
158
+ "mem.saved": "Saved",
159
+ "mem.edit": "Edit",
160
+ "mem.section-label": "Task memory"
93
161
  };
94
162
  function createTranslate(dict) {
95
163
  return (key, params) => {
@@ -136,7 +204,13 @@ window.__ModuleLoader__.load({
136
204
  };
137
205
  const dataListeners = /* @__PURE__ */ new Set();
138
206
  function setDataState(next) {
139
- dataState = next;
207
+ const patch = typeof next === "function" ? next(dataState) : next;
208
+ dataState = {
209
+ tasks: Array.isArray(patch?.tasks) ? patch.tasks : [],
210
+ boundTaskId: patch?.boundTaskId ?? null,
211
+ archivedCount: typeof patch?.archivedCount === "number" ? patch.archivedCount : 0,
212
+ lastUpdate: typeof patch?.lastUpdate === "number" ? patch.lastUpdate : 0
213
+ };
140
214
  for (const listener of dataListeners) listener();
141
215
  }
142
216
  function broadcastDataUpdate(tasks, archivedCount) {
@@ -144,7 +218,7 @@ window.__ModuleLoader__.load({
144
218
  SYNC_CHANNEL.postMessage({
145
219
  type: "PROJECT_TASKS_UPDATED",
146
220
  payload: {
147
- tasks,
221
+ tasks: Array.isArray(tasks) ? tasks : [],
148
222
  archivedCount
149
223
  }
150
224
  });
@@ -155,8 +229,8 @@ window.__ModuleLoader__.load({
155
229
  const { tasks, archivedCount } = msg.payload;
156
230
  setDataState((prev) => ({
157
231
  ...prev,
158
- tasks: tasks || [],
159
- archivedCount: archivedCount ?? 0,
232
+ tasks: Array.isArray(tasks) ? tasks : [],
233
+ archivedCount: typeof archivedCount === "number" ? archivedCount : prev.archivedCount,
160
234
  lastUpdate: Date.now()
161
235
  }));
162
236
  }
@@ -487,7 +561,7 @@ window.__ModuleLoader__.load({
487
561
  }
488
562
  //#endregion
489
563
  //#region \0dsh-css:/home/sxt/project/dsh-project-memory/src/client/TaskPanel.module.css.mjs
490
- const css$1 = ".vZSZnG_panel{pointer-events:auto;background:var(--dsw-alias-bg-layer-2,var(--dsw-alias-bg-base,#fff));border:1px solid var(--dsw-alias-border-l2,#7f7f7f4d);border-radius:14px;flex-direction:column;width:380px;max-width:calc(100vw - 24px);max-height:min(70vh,640px);font-family:inherit;animation:.18s ease-out vZSZnG_panelIn;display:flex;position:fixed;overflow:hidden;box-shadow:0 12px 32px #00000029,0 2px 8px #00000014}@keyframes vZSZnG_panelIn{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}.vZSZnG_dragHandle{cursor:grab;z-index:1;justify-content:center;align-items:center;height:12px;display:flex;position:absolute;top:0;left:0;right:0}.vZSZnG_dragHandle:active{cursor:grabbing}.vZSZnG_handleGrip{background:var(--dsw-alias-separator-primary,#7f7f7f59);opacity:.8;border-radius:2px;width:32px;height:3px}.vZSZnG_header{border-bottom:1px solid var(--dsw-alias-border-l1,#7f7f7f2e);-webkit-user-select:none;user-select:none;justify-content:space-between;align-items:center;gap:8px;padding:10px 10px 8px 14px;display:flex}.vZSZnG_headerLeft{align-items:center;gap:6px;min-width:0;display:flex}.vZSZnG_headerIcon{color:var(--dsw-alias-label-secondary);flex:none}.vZSZnG_headerTitle{color:var(--dsw-alias-label-primary);white-space:nowrap;margin:0;font-size:13px;font-weight:600;line-height:20px}.vZSZnG_headerRight{align-items:center;gap:2px;margin-left:auto;display:flex}.vZSZnG_counts{color:var(--dsw-alias-label-tertiary);white-space:nowrap;margin-right:4px;font-size:11px;line-height:16px}.vZSZnG_boundBadge{color:var(--dsw-alias-label-primary-foreground,#fff);background:var(--dsw-alias-button-primary-fill,#3a6ef5);white-space:nowrap;border-radius:7px;flex:none;padding:0 6px;font-size:10px;line-height:14px}.vZSZnG_notice{color:var(--dsw-alias-state-warn-label,#b7791f);background:var(--dsw-alias-interactive-bg-hover,#7f7f7f1a);word-break:break-all;border-radius:8px;margin:8px 12px 0;padding:6px 10px;font-size:12px;line-height:18px}.vZSZnG_taskList{scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,transparent) transparent;flex-direction:column;gap:6px;padding:8px;display:flex;overflow-y:auto}.vZSZnG_emptyState{text-align:center;color:var(--dsw-alias-label-secondary);padding:36px 24px 30px}.vZSZnG_emptyTitle{color:var(--dsw-alias-label-primary);margin:0 0 6px;font-size:13px;font-weight:600}.vZSZnG_emptyDesc{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:20px}.vZSZnG_syncHint{color:var(--dsw-alias-label-dimmed);justify-content:center;align-items:center;gap:6px;margin:10px 0 0;font-size:11px;display:flex}.vZSZnG_card{border:1px solid var(--dsw-alias-border-l1,#7f7f7f29);background:var(--dsw-alias-bg-base,transparent);border-radius:10px;transition:border-color .15s;overflow:hidden}.vZSZnG_cardBound{border-color:var(--dsw-alias-border-l3,#7f7f7f59);box-shadow:inset 0 0 0 .5px var(--dsw-alias-border-l3,transparent)}.vZSZnG_cardHead{cursor:pointer;text-align:left;background:0 0;border:none;justify-content:space-between;align-items:center;gap:8px;width:100%;padding:8px 10px 7px;display:flex}.vZSZnG_cardHead:hover{background:var(--dsw-alias-interactive-bg-hover,#7f7f7f14)}.vZSZnG_cardTitleRow{align-items:center;gap:6px;min-width:0;display:flex}.vZSZnG_cardTitle{color:var(--dsw-alias-label-primary);white-space:nowrap;text-overflow:ellipsis;font-size:13px;font-weight:500;line-height:20px;overflow:hidden}.vZSZnG_cardMeta{color:var(--dsw-alias-label-tertiary);flex:none;align-items:center;gap:8px;display:flex}.vZSZnG_progressText{font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-secondary);font-size:11px;line-height:16px}.vZSZnG_updated{color:var(--dsw-alias-label-dimmed);font-size:10px;line-height:14px}.vZSZnG_chevron{color:var(--dsw-alias-label-tertiary);display:inline-flex}.vZSZnG_track{background:var(--dsw-alias-interactive-bg-hover,#7f7f7f1f);border-radius:1px;height:2px;margin:0 10px 6px;overflow:hidden}.vZSZnG_trackFill{background:var(--dsw-alias-label-primary-bluish,var(--dsw-alias-button-primary-fill,#3a6ef5));border-radius:1px;height:100%;transition:width .2s}.vZSZnG_cardBody{border-top:1px solid var(--dsw-alias-border-l1,#7f7f7f24);overscroll-behavior:contain;max-height:300px;padding:8px 10px 10px;overflow-y:auto}.vZSZnG_section{margin-bottom:8px}.vZSZnG_section:last-child{margin-bottom:0}.vZSZnG_sectionLabel{color:var(--dsw-alias-label-secondary);align-items:center;gap:6px;margin-bottom:4px;font-size:11px;line-height:16px;display:flex}.vZSZnG_sectionCount{background:var(--dsw-alias-interactive-bg-hover,#7f7f7f1a);color:var(--dsw-alias-label-tertiary);border-radius:6px;padding:0 5px;font-size:10px;line-height:14px}.vZSZnG_stepsList{flex-direction:column;gap:1px;margin:0;padding:0;list-style:none;display:flex}.vZSZnG_stepRow{align-items:flex-start;gap:7px;padding:3px 2px;display:flex}.vZSZnG_stepRow>svg{flex:none;margin-top:2px}.vZSZnG_stepDone{color:var(--dsw-alias-label-dimmed)}.vZSZnG_stepRun{color:var(--dsw-alias-label-primary-bluish,#3a6ef5)}.vZSZnG_stepPending{background:var(--dsw-alias-border-l3,#7f7f7f80);border-radius:50%;flex:none;width:8px;height:8px;margin:5px 3px}.vZSZnG_stepContent{color:var(--dsw-alias-label-secondary);word-break:break-word;font-size:12px;line-height:20px}.vZSZnG_stepContentDone{color:var(--dsw-alias-label-dimmed);text-decoration:line-through}.vZSZnG_stepContentRun{color:var(--dsw-alias-label-primary)}.vZSZnG_muted{color:var(--dsw-alias-label-dimmed);font-size:11px;line-height:18px}.vZSZnG_filesList{flex-direction:column;margin:0;padding:0;list-style:none;display:flex}.vZSZnG_fileRow{cursor:pointer;text-align:left;background:0 0;border:none;border-radius:6px;align-items:center;gap:6px;width:100%;padding:3px 4px;display:flex}.vZSZnG_fileRow:hover{background:var(--dsw-alias-interactive-bg-hover,#7f7f7f14)}.vZSZnG_fileDot{background:var(--dsw-alias-border-l3,#7f7f7f80);border-radius:50%;flex:none;width:5px;height:5px}.vZSZnG_filePath{color:var(--dsw-alias-label-secondary);white-space:nowrap;text-overflow:ellipsis;text-align:left;direction:rtl;font-family:ui-monospace,SF Mono,Menlo,Consolas,monospace;font-size:11px;line-height:18px;overflow:hidden}.vZSZnG_fileLine{color:var(--dsw-alias-label-dimmed);flex:none;font-size:10px;line-height:18px}.vZSZnG_cardFooter{gap:6px;margin-top:8px;display:flex}@media (prefers-reduced-motion:reduce){.vZSZnG_panel{animation:none}.vZSZnG_trackFill,.vZSZnG_card{transition:none}}.vZSZnG_miniBar{border:1px solid var(--dsw-alias-border-l3,#7f7f7f4d);background:var(--dsw-alias-bg-layer-2,var(--dsw-alias-bg-base,#fff));max-width:min(46vw,340px);height:34px;color:var(--dsw-alias-label-primary);cursor:grab;-webkit-user-select:none;user-select:none;pointer-events:auto;border-radius:999px;align-items:center;gap:7px;padding:0 12px;font-size:12px;line-height:18px;transition:background .15s,border-color .15s;display:inline-flex;position:fixed;box-shadow:0 6px 20px #00000024,0 1px 4px #00000014}.vZSZnG_miniBar:active{cursor:grabbing}.vZSZnG_miniBar:hover{background:var(--dsw-alias-interactive-bg-hover,#7f7f7f14)}.vZSZnG_miniIcon{color:var(--dsw-alias-label-secondary);flex:none}.vZSZnG_miniText{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.vZSZnG_miniChevron{color:var(--dsw-alias-label-tertiary);flex:none}.vZSZnG_taskList{flex:auto;min-height:0}.vZSZnG_card{flex-direction:column;display:flex}.vZSZnG_boundaryFallback{border:1px solid var(--dsw-alias-border-l3,#7f7f7f4d);background:var(--dsw-alias-bg-layer-2,#fff);color:var(--dsw-alias-label-secondary);cursor:pointer;pointer-events:auto;border-radius:999px;padding:4px 10px;font-size:12px;line-height:18px;position:fixed;top:64px;right:16px}.vZSZnG_stepToggle{cursor:pointer;background:0 0;border:none;border-radius:4px;flex:none;align-items:center;margin-top:2px;padding:0;display:inline-flex}.vZSZnG_stepToggle:hover{background:var(--dsw-alias-interactive-bg-hover,#7f7f7f1f)}.vZSZnG_stepToggle:disabled{cursor:default;opacity:.5}.vZSZnG_stepEditable{cursor:text;border-radius:3px}.vZSZnG_stepEditable:hover{outline:1px dashed var(--dsw-alias-border-l3,#7f7f7f66);outline-offset:1px}.vZSZnG_stepInput{box-sizing:border-box;width:auto;min-width:0;font:inherit;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-base,transparent);border:1px solid var(--dsw-alias-border-l3,#7f7f7f73);border-radius:5px;flex:auto;padding:0 5px;font-size:12px;line-height:20px}.vZSZnG_stepDragging{opacity:.3;background:var(--dsw-alias-interactive-bg-hover,#7f7f7f14)}.vZSZnG_cardTitleEditable{cursor:text;border-radius:3px}.vZSZnG_cardTitleEditable:hover{outline:1px dashed var(--dsw-alias-border-l3,#7f7f7f66);outline-offset:1px}.vZSZnG_panel[data-theme=glass],.vZSZnG_miniBar[data-theme=glass]{background:color-mix(in srgb, var(--dsw-alias-bg-layer-2,#fff) 90%, transparent);-webkit-backdrop-filter:blur(18px)saturate(1.2);border:1px solid color-mix(in srgb, var(--dsw-alias-border-l2,#7f7f7f4d) 80%, transparent)}.vZSZnG_panel[data-theme=glass] .vZSZnG_card{background:color-mix(in srgb, var(--dsw-alias-bg-base,transparent) 84%, transparent);border-color:color-mix(in srgb, var(--dsw-alias-border-l1,#7f7f7f29) 60%, transparent)}.vZSZnG_panel[data-theme=glass] .vZSZnG_cardBody{border-top-color:color-mix(in srgb, var(--dsw-alias-border-l1,#7f7f7f24) 60%, transparent)}@media (prefers-reduced-transparency:reduce){.vZSZnG_panel[data-theme=glass],.vZSZnG_miniBar[data-theme=glass]{background:var(--dsw-alias-bg-layer-2,#fff);-webkit-backdrop-filter:none;backdrop-filter:none}.vZSZnG_panel[data-theme=glass] .vZSZnG_card{background:var(--dsw-alias-bg-base,transparent)}}@supports not ((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px))){.vZSZnG_panel[data-theme=glass],.vZSZnG_miniBar[data-theme=glass]{background:var(--dsw-alias-bg-layer-2,#fff)}}.vZSZnG_panel[data-theme=brutal]{box-shadow:none;border-width:1px;border-radius:6px}.vZSZnG_panel[data-theme=brutal] .vZSZnG_card{border:1px solid var(--dsw-alias-border-l3,#7f7f7f6b);background:var(--dsw-alias-bg-base,transparent);box-shadow:none;border-radius:3px}.vZSZnG_panel[data-theme=brutal] .vZSZnG_cardHead{padding:7px 10px 6px}.vZSZnG_panel[data-theme=brutal] .vZSZnG_cardTitle{letter-spacing:.01em;font-weight:650}.vZSZnG_panel[data-theme=brutal] .vZSZnG_headerTitle{letter-spacing:.03em}.vZSZnG_panel[data-theme=brutal] .vZSZnG_boundBadge{border-radius:2px}.vZSZnG_panel[data-theme=brutal] .vZSZnG_track{border-radius:0;height:3px}.vZSZnG_panel[data-theme=brutal] .vZSZnG_trackFill{border-radius:0}.vZSZnG_panel[data-theme=brutal] .vZSZnG_cardBody{border-top:1px solid var(--dsw-alias-border-l2,#7f7f7f3d)}.vZSZnG_panel[data-theme=mono] .vZSZnG_headerTitle,.vZSZnG_panel[data-theme=mono] .vZSZnG_counts,.vZSZnG_panel[data-theme=mono] .vZSZnG_cardTitle,.vZSZnG_panel[data-theme=mono] .vZSZnG_progressText,.vZSZnG_panel[data-theme=mono] .vZSZnG_stepContent,.vZSZnG_panel[data-theme=mono] .vZSZnG_filePath{font-family:ui-monospace,SF Mono,Menlo,Consolas,Liberation Mono,monospace}.vZSZnG_panel[data-theme=mono] .vZSZnG_cardTitle{font-size:12px}.vZSZnG_panel[data-theme=mono] .vZSZnG_stepContent{font-size:11.5px}.vZSZnG_panel[data-theme=mono] .vZSZnG_card{border-radius:5px}.vZSZnG_panel[data-theme=mono] .vZSZnG_trackFill{border-radius:0}.vZSZnG_panel[data-theme=mono] .vZSZnG_stepPending{border-radius:1px}.vZSZnG_panel[data-theme=mono] .vZSZnG_updated{letter-spacing:.02em}.vZSZnG_headerIconBtn{color:inherit;cursor:pointer;background:0 0;border:none;border-radius:0;flex:none;justify-content:center;align-items:center;margin:0;padding:0;display:inline-flex}.vZSZnG_headerIcon{color:var(--dsw-alias-label-secondary);flex:none;display:block}.vZSZnG_headerLeft{min-width:0}.vZSZnG_headerTitle{text-overflow:ellipsis;flex:0 auto;min-width:0;overflow:hidden}.vZSZnG_headerRight{min-width:0}.vZSZnG_counts{text-overflow:ellipsis;flex:none;max-width:45%;margin-left:auto;overflow:hidden}.vZSZnG_dragGhost{pointer-events:none;z-index:9999;transition:left 50ms,top 50ms;position:fixed;transform:translate(-50%,-50%)}.vZSZnG_dragGhostCard{background:var(--dsw-alias-bg-layer-2,var(--dsw-alias-bg-base,#fff));border:1px solid var(--dsw-alias-border-l3,#7f7f7f59);color:var(--dsw-alias-label-primary);white-space:nowrap;border-radius:8px;align-items:center;gap:8px;max-width:280px;padding:8px 12px;font-size:12px;line-height:20px;display:inline-flex;transform:scale(.9);box-shadow:0 8px 24px #0000002e,0 2px 8px #0000001a}.vZSZnG_dragGhostContent{text-overflow:ellipsis;word-break:break-word;flex:1;min-width:0;overflow:hidden}.vZSZnG_dragGhostClose{width:20px;height:20px;color:var(--dsw-alias-label-tertiary);cursor:pointer;opacity:.6;background:0 0;border:none;border-radius:4px;flex:none;justify-content:center;align-items:center;margin-left:8px;font-size:16px;line-height:1;transition:opacity .15s,background .15s,color .15s;display:inline-flex}.vZSZnG_dragGhostClose:hover{opacity:1;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-interactive-bg-hover,#7f7f7f1f)}.vZSZnG_dropTargetBefore{position:relative}.vZSZnG_dropTargetBefore:before{content:\"\";background:var(--dsw-alias-button-primary-fill,#3a6ef5);height:2px;box-shadow:0 0 4px var(--dsw-alias-button-primary-fill,#3a6ef5);border-radius:1px;animation:.8s ease-in-out infinite vZSZnG_dropPulse;position:absolute;top:-1px;left:0;right:0}.vZSZnG_dropTargetAfter{position:relative}.vZSZnG_dropTargetAfter:after{content:\"\";background:var(--dsw-alias-button-primary-fill,#3a6ef5);height:2px;box-shadow:0 0 4px var(--dsw-alias-button-primary-fill,#3a6ef5);border-radius:1px;animation:.8s ease-in-out infinite vZSZnG_dropPulse;position:absolute;bottom:-1px;left:0;right:0}@keyframes vZSZnG_dropPulse{0%,to{opacity:.6}50%{opacity:1}}";
564
+ const css$1 = ".vZSZnG_panel{pointer-events:auto;background:var(--dsw-alias-bg-layer-2,var(--dsw-alias-bg-base,#fff));border:1px solid var(--dsw-alias-border-l2,#7f7f7f4d);border-radius:14px;flex-direction:column;width:380px;max-width:calc(100vw - 24px);max-height:min(70vh,640px);font-family:inherit;animation:.18s ease-out vZSZnG_panelIn;display:flex;position:fixed;overflow:hidden;box-shadow:0 12px 32px #00000029,0 2px 8px #00000014}@keyframes vZSZnG_panelIn{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}.vZSZnG_dragHandle{cursor:grab;z-index:1;justify-content:center;align-items:center;height:12px;display:flex;position:absolute;top:0;left:0;right:0}.vZSZnG_dragHandle:active{cursor:grabbing}.vZSZnG_handleGrip{background:var(--dsw-alias-separator-primary,#7f7f7f59);opacity:.8;border-radius:2px;width:32px;height:3px}.vZSZnG_header{border-bottom:1px solid var(--dsw-alias-border-l1,#7f7f7f2e);-webkit-user-select:none;user-select:none;justify-content:space-between;align-items:center;gap:8px;padding:10px 10px 8px 14px;display:flex}.vZSZnG_headerLeft{align-items:center;gap:6px;min-width:0;display:flex}.vZSZnG_headerIcon{color:var(--dsw-alias-label-secondary);flex:none}.vZSZnG_headerTitle{color:var(--dsw-alias-label-primary);white-space:nowrap;margin:0;font-size:13px;font-weight:600;line-height:20px}.vZSZnG_headerRight{align-items:center;gap:2px;margin-left:auto;display:flex}.vZSZnG_counts{color:var(--dsw-alias-label-tertiary);white-space:nowrap;margin-right:4px;font-size:11px;line-height:16px}.vZSZnG_boundBadge{color:var(--dsw-alias-label-primary-foreground,#fff);background:var(--dsw-alias-button-primary-fill,#3a6ef5);white-space:nowrap;border-radius:7px;flex:none;padding:0 6px;font-size:10px;line-height:14px}.vZSZnG_notice{color:var(--dsw-alias-state-warn-label,#b7791f);background:var(--dsw-alias-interactive-bg-hover,#7f7f7f1a);word-break:break-all;border-radius:8px;margin:8px 12px 0;padding:6px 10px;font-size:12px;line-height:18px}.vZSZnG_taskList{scrollbar-width:thin;scrollbar-color:var(--dsw-alias-scrollbar-bg-l2,transparent) transparent;flex-direction:column;gap:6px;padding:8px;display:flex;overflow-y:auto}.vZSZnG_emptyState{text-align:center;color:var(--dsw-alias-label-secondary);padding:36px 24px 30px}.vZSZnG_emptyTitle{color:var(--dsw-alias-label-primary);margin:0 0 6px;font-size:13px;font-weight:600}.vZSZnG_emptyDesc{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:20px}.vZSZnG_syncHint{color:var(--dsw-alias-label-dimmed);justify-content:center;align-items:center;gap:6px;margin:10px 0 0;font-size:11px;display:flex}.vZSZnG_card{border:1px solid var(--dsw-alias-border-l1,#7f7f7f29);background:var(--dsw-alias-bg-base,transparent);border-radius:10px;transition:border-color .15s;overflow:hidden}.vZSZnG_cardBound{border-color:var(--dsw-alias-border-l3,#7f7f7f59);box-shadow:inset 0 0 0 .5px var(--dsw-alias-border-l3,transparent)}.vZSZnG_cardHead{cursor:pointer;text-align:left;background:0 0;border:none;justify-content:space-between;align-items:center;gap:8px;width:100%;padding:8px 10px 7px;display:flex}.vZSZnG_cardHead:hover{background:var(--dsw-alias-interactive-bg-hover,#7f7f7f14)}.vZSZnG_cardTitleRow{align-items:center;gap:6px;min-width:0;display:flex}.vZSZnG_cardTitle{color:var(--dsw-alias-label-primary);white-space:nowrap;text-overflow:ellipsis;font-size:13px;font-weight:500;line-height:20px;overflow:hidden}.vZSZnG_cardMeta{color:var(--dsw-alias-label-tertiary);flex:none;align-items:center;gap:8px;display:flex}.vZSZnG_progressText{font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-secondary);font-size:11px;line-height:16px}.vZSZnG_updated{color:var(--dsw-alias-label-dimmed);font-size:10px;line-height:14px}.vZSZnG_chevron{color:var(--dsw-alias-label-tertiary);display:inline-flex}.vZSZnG_track{background:var(--dsw-alias-interactive-bg-hover,#7f7f7f1f);border-radius:1px;height:2px;margin:0 10px 6px;overflow:hidden}.vZSZnG_trackFill{background:var(--dsw-alias-label-primary-bluish,var(--dsw-alias-button-primary-fill,#3a6ef5));border-radius:1px;height:100%;transition:width .2s}.vZSZnG_cardBody{border-top:1px solid var(--dsw-alias-border-l1,#7f7f7f24);overscroll-behavior:contain;max-height:300px;padding:8px 10px 10px;overflow-y:auto}.vZSZnG_section{margin-bottom:8px}.vZSZnG_section:last-child{margin-bottom:0}.vZSZnG_sectionLabel{color:var(--dsw-alias-label-secondary);align-items:center;gap:6px;margin-bottom:4px;font-size:11px;line-height:16px;display:flex}.vZSZnG_sectionCount{background:var(--dsw-alias-interactive-bg-hover,#7f7f7f1a);color:var(--dsw-alias-label-tertiary);border-radius:6px;padding:0 5px;font-size:10px;line-height:14px}.vZSZnG_stepsList{flex-direction:column;gap:1px;margin:0;padding:0;list-style:none;display:flex}.vZSZnG_stepRow{align-items:flex-start;gap:7px;padding:3px 2px;display:flex}.vZSZnG_stepRow>svg{flex:none;margin-top:2px}.vZSZnG_stepDone{color:var(--dsw-alias-label-dimmed)}.vZSZnG_stepRun{color:var(--dsw-alias-label-primary-bluish,#3a6ef5)}.vZSZnG_stepPending{background:var(--dsw-alias-border-l3,#7f7f7f80);border-radius:50%;flex:none;width:8px;height:8px;margin:5px 3px}.vZSZnG_stepContent{color:var(--dsw-alias-label-secondary);word-break:break-word;font-size:12px;line-height:20px}.vZSZnG_stepContentDone{color:var(--dsw-alias-label-dimmed);text-decoration:line-through}.vZSZnG_stepContentRun{color:var(--dsw-alias-label-primary)}.vZSZnG_muted{color:var(--dsw-alias-label-dimmed);font-size:11px;line-height:18px}.vZSZnG_filesList{flex-direction:column;margin:0;padding:0;list-style:none;display:flex}.vZSZnG_fileRow{cursor:pointer;text-align:left;background:0 0;border:none;border-radius:6px;align-items:center;gap:6px;width:100%;padding:3px 4px;display:flex}.vZSZnG_fileRow:hover{background:var(--dsw-alias-interactive-bg-hover,#7f7f7f14)}.vZSZnG_fileDot{background:var(--dsw-alias-border-l3,#7f7f7f80);border-radius:50%;flex:none;width:5px;height:5px}.vZSZnG_filePath{color:var(--dsw-alias-label-secondary);white-space:nowrap;text-overflow:ellipsis;text-align:left;direction:rtl;font-family:ui-monospace,SF Mono,Menlo,Consolas,monospace;font-size:11px;line-height:18px;overflow:hidden}.vZSZnG_fileLine{color:var(--dsw-alias-label-dimmed);flex:none;font-size:10px;line-height:18px}.vZSZnG_cardFooter{gap:6px;margin-top:8px;display:flex}@media (prefers-reduced-motion:reduce){.vZSZnG_panel{animation:none}.vZSZnG_trackFill,.vZSZnG_card{transition:none}}.vZSZnG_miniBar{border:1px solid var(--dsw-alias-border-l3,#7f7f7f4d);background:var(--dsw-alias-bg-layer-2,var(--dsw-alias-bg-base,#fff));max-width:min(46vw,340px);height:34px;color:var(--dsw-alias-label-primary);cursor:grab;-webkit-user-select:none;user-select:none;pointer-events:auto;border-radius:999px;align-items:center;gap:7px;padding:0 12px;font-size:12px;line-height:18px;transition:background .15s,border-color .15s;display:inline-flex;position:fixed;box-shadow:0 6px 20px #00000024,0 1px 4px #00000014}.vZSZnG_miniBar:active{cursor:grabbing}.vZSZnG_miniBar:hover{background:var(--dsw-alias-interactive-bg-hover,#7f7f7f14)}.vZSZnG_miniIcon{color:var(--dsw-alias-label-secondary);flex:none}.vZSZnG_miniText{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.vZSZnG_miniChevron{color:var(--dsw-alias-label-tertiary);flex:none}.vZSZnG_taskList{flex:auto;min-height:0}.vZSZnG_card{flex-direction:column;display:flex}.vZSZnG_boundaryFallback{border:1px solid var(--dsw-alias-border-l3,#7f7f7f4d);background:var(--dsw-alias-bg-layer-2,#fff);color:var(--dsw-alias-label-secondary);cursor:pointer;pointer-events:auto;border-radius:999px;padding:4px 10px;font-size:12px;line-height:18px;position:fixed;top:64px;right:16px}.vZSZnG_stepToggle{cursor:pointer;background:0 0;border:none;border-radius:4px;flex:none;align-items:center;margin-top:2px;padding:0;display:inline-flex}.vZSZnG_stepToggle:hover{background:var(--dsw-alias-interactive-bg-hover,#7f7f7f1f)}.vZSZnG_stepToggle:disabled{cursor:default;opacity:.5}.vZSZnG_stepEditable{cursor:text;border-radius:3px}.vZSZnG_stepEditable:hover{outline:1px dashed var(--dsw-alias-border-l3,#7f7f7f66);outline-offset:1px}.vZSZnG_stepInput{box-sizing:border-box;width:auto;min-width:0;font:inherit;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-base,transparent);border:1px solid var(--dsw-alias-border-l3,#7f7f7f73);border-radius:5px;flex:auto;padding:0 5px;font-size:12px;line-height:20px}.vZSZnG_stepDragging{opacity:.3;background:var(--dsw-alias-interactive-bg-hover,#7f7f7f14)}.vZSZnG_cardTitleEditable{cursor:text;border-radius:3px}.vZSZnG_cardTitleEditable:hover{outline:1px dashed var(--dsw-alias-border-l3,#7f7f7f66);outline-offset:1px}.vZSZnG_panel[data-theme=glass],.vZSZnG_miniBar[data-theme=glass]{background:color-mix(in srgb, var(--dsw-alias-bg-layer-2,#fff) 90%, transparent);-webkit-backdrop-filter:blur(18px)saturate(1.2);border:1px solid color-mix(in srgb, var(--dsw-alias-border-l2,#7f7f7f4d) 80%, transparent)}.vZSZnG_panel[data-theme=glass] .vZSZnG_card{background:color-mix(in srgb, var(--dsw-alias-bg-base,transparent) 84%, transparent);border-color:color-mix(in srgb, var(--dsw-alias-border-l1,#7f7f7f29) 60%, transparent)}.vZSZnG_panel[data-theme=glass] .vZSZnG_cardBody{border-top-color:color-mix(in srgb, var(--dsw-alias-border-l1,#7f7f7f24) 60%, transparent)}@media (prefers-reduced-transparency:reduce){.vZSZnG_panel[data-theme=glass],.vZSZnG_miniBar[data-theme=glass]{background:var(--dsw-alias-bg-layer-2,#fff);-webkit-backdrop-filter:none;backdrop-filter:none}.vZSZnG_panel[data-theme=glass] .vZSZnG_card{background:var(--dsw-alias-bg-base,transparent)}}@supports not ((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px))){.vZSZnG_panel[data-theme=glass],.vZSZnG_miniBar[data-theme=glass]{background:var(--dsw-alias-bg-layer-2,#fff)}}.vZSZnG_panel[data-theme=brutal]{box-shadow:none;border-width:1px;border-radius:6px}.vZSZnG_panel[data-theme=brutal] .vZSZnG_card{border:1px solid var(--dsw-alias-border-l3,#7f7f7f6b);background:var(--dsw-alias-bg-base,transparent);box-shadow:none;border-radius:3px}.vZSZnG_panel[data-theme=brutal] .vZSZnG_cardHead{padding:7px 10px 6px}.vZSZnG_panel[data-theme=brutal] .vZSZnG_cardTitle{letter-spacing:.01em;font-weight:650}.vZSZnG_panel[data-theme=brutal] .vZSZnG_headerTitle{letter-spacing:.03em}.vZSZnG_panel[data-theme=brutal] .vZSZnG_boundBadge{border-radius:2px}.vZSZnG_panel[data-theme=brutal] .vZSZnG_track{border-radius:0;height:3px}.vZSZnG_panel[data-theme=brutal] .vZSZnG_trackFill{border-radius:0}.vZSZnG_panel[data-theme=brutal] .vZSZnG_cardBody{border-top:1px solid var(--dsw-alias-border-l2,#7f7f7f3d)}.vZSZnG_panel[data-theme=mono] .vZSZnG_headerTitle,.vZSZnG_panel[data-theme=mono] .vZSZnG_counts,.vZSZnG_panel[data-theme=mono] .vZSZnG_cardTitle,.vZSZnG_panel[data-theme=mono] .vZSZnG_progressText,.vZSZnG_panel[data-theme=mono] .vZSZnG_stepContent,.vZSZnG_panel[data-theme=mono] .vZSZnG_filePath{font-family:ui-monospace,SF Mono,Menlo,Consolas,Liberation Mono,monospace}.vZSZnG_panel[data-theme=mono] .vZSZnG_cardTitle{font-size:12px}.vZSZnG_panel[data-theme=mono] .vZSZnG_stepContent{font-size:11.5px}.vZSZnG_panel[data-theme=mono] .vZSZnG_card{border-radius:5px}.vZSZnG_panel[data-theme=mono] .vZSZnG_trackFill{border-radius:0}.vZSZnG_panel[data-theme=mono] .vZSZnG_stepPending{border-radius:1px}.vZSZnG_panel[data-theme=mono] .vZSZnG_updated{letter-spacing:.02em}.vZSZnG_headerIconBtn{color:inherit;cursor:pointer;background:0 0;border:none;border-radius:0;flex:none;justify-content:center;align-items:center;margin:0;padding:0;display:inline-flex}.vZSZnG_headerIcon{color:var(--dsw-alias-label-secondary);flex:none;display:block}.vZSZnG_headerLeft{min-width:0}.vZSZnG_headerTitle{text-overflow:ellipsis;flex:0 auto;min-width:0;overflow:hidden}.vZSZnG_headerRight{min-width:0}.vZSZnG_counts{text-overflow:ellipsis;flex:none;max-width:45%;margin-left:auto;overflow:hidden}.vZSZnG_dragGhost{pointer-events:none;z-index:9999;transition:left 50ms,top 50ms;position:fixed;transform:translate(-50%,-50%)}.vZSZnG_dragGhostCard{background:var(--dsw-alias-bg-layer-2,var(--dsw-alias-bg-base,#fff));border:1px solid var(--dsw-alias-border-l3,#7f7f7f59);color:var(--dsw-alias-label-primary);white-space:nowrap;border-radius:8px;align-items:center;gap:8px;max-width:280px;padding:8px 12px;font-size:12px;line-height:20px;display:inline-flex;transform:scale(.9);box-shadow:0 8px 24px #0000002e,0 2px 8px #0000001a}.vZSZnG_dragGhostContent{text-overflow:ellipsis;word-break:break-word;flex:1;min-width:0;overflow:hidden}.vZSZnG_dragGhostClose{width:20px;height:20px;color:var(--dsw-alias-label-tertiary);cursor:pointer;opacity:.6;background:0 0;border:none;border-radius:4px;flex:none;justify-content:center;align-items:center;margin-left:8px;font-size:16px;line-height:1;transition:opacity .15s,background .15s,color .15s;display:inline-flex}.vZSZnG_dragGhostClose:hover{opacity:1;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-interactive-bg-hover,#7f7f7f1f)}.vZSZnG_dropTargetBefore{position:relative}.vZSZnG_dropTargetBefore:before{content:\"\";background:var(--dsw-alias-button-primary-fill,#3a6ef5);height:2px;box-shadow:0 0 4px var(--dsw-alias-button-primary-fill,#3a6ef5);border-radius:1px;animation:.8s ease-in-out infinite vZSZnG_dropPulse;position:absolute;top:-1px;left:0;right:0}.vZSZnG_dropTargetAfter{position:relative}.vZSZnG_dropTargetAfter:after{content:\"\";background:var(--dsw-alias-button-primary-fill,#3a6ef5);height:2px;box-shadow:0 0 4px var(--dsw-alias-button-primary-fill,#3a6ef5);border-radius:1px;animation:.8s ease-in-out infinite vZSZnG_dropPulse;position:absolute;bottom:-1px;left:0;right:0}@keyframes vZSZnG_dropPulse{0%,to{opacity:.6}50%{opacity:1}}.vZSZnG_memoryPane{flex-direction:column;gap:6px;max-height:480px;padding:8px 10px 10px;display:flex;overflow:auto}.vZSZnG_memToolbar{justify-content:space-between;align-items:center;gap:8px;display:flex}.vZSZnG_memCount{opacity:.75;font-size:12px;font-weight:600}.vZSZnG_memList{flex-direction:column;gap:6px;display:flex}.vZSZnG_memRow{border:1px solid var(--dsw-border-weak,#80808040);background:color-mix(in srgb, var(--dsw-bg-secondary,#f5f5f5) 45%, transparent);border-radius:6px;flex-direction:column;gap:4px;padding:6px 8px;display:flex}.vZSZnG_memRowArchived{opacity:.55}.vZSZnG_memRowMain{flex-direction:column;gap:2px;display:flex}.vZSZnG_memTitle{word-break:break-word;align-items:flex-start;gap:6px;font-size:13px;line-height:1.35;display:flex}.vZSZnG_kindBadge{background:var(--dsw-accent-soft,#5078ff26);color:var(--dsw-accent,#4d6bfe);border-radius:4px;flex:none;padding:0 5px;font-size:11px;line-height:1.5}.vZSZnG_memMeta{flex-wrap:wrap;align-items:center;gap:4px;display:flex}.vZSZnG_badge{background:color-mix(in srgb, var(--dsw-fg,#222) 8%, transparent);border-radius:4px;padding:0 5px;font-size:11px;line-height:1.5}.vZSZnG_badgeDraft{color:#b26a00;background:#ffb40029}.vZSZnG_badgeArchived{opacity:.8}.vZSZnG_memBody{opacity:.8;word-break:break-word;font-size:12px}.vZSZnG_memActs{flex-wrap:wrap;gap:4px;display:flex}.vZSZnG_memToolbarActs{align-items:center;gap:6px;display:flex}.vZSZnG_memNew{border:1px solid var(--dsw-border-weak,#80808040);border-radius:6px;flex-direction:column;gap:6px;padding:8px;display:flex}.vZSZnG_memNewRow{align-items:center;gap:8px;display:flex}.vZSZnG_memLabel{opacity:.8;align-items:center;gap:6px;font-size:12px;display:inline-flex}.vZSZnG_memNew select,.vZSZnG_memNew textarea{box-sizing:border-box;width:100%}";
491
565
  const tagId$1 = "@yolk_vat-y/dsh-project-memory/TaskPanel.module.css";
492
566
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
493
567
  const tag = document.createElement("style");
@@ -497,71 +571,90 @@ window.__ModuleLoader__.load({
497
571
  document.head.appendChild(tag);
498
572
  }
499
573
  var TaskPanel_module_css_default = {
500
- "headerLeft": "vZSZnG_headerLeft",
501
- "counts": "vZSZnG_counts",
502
- "card": "vZSZnG_card",
503
- "filePath": "vZSZnG_filePath",
504
- "headerIcon": "vZSZnG_headerIcon",
574
+ "cardTitleRow": "vZSZnG_cardTitleRow",
575
+ "memMeta": "vZSZnG_memMeta",
576
+ "cardTitle": "vZSZnG_cardTitle",
577
+ "dragGhostClose": "vZSZnG_dragGhostClose",
578
+ "syncHint": "vZSZnG_syncHint",
579
+ "updated": "vZSZnG_updated",
580
+ "section": "vZSZnG_section",
581
+ "emptyTitle": "vZSZnG_emptyTitle",
582
+ "stepRow": "vZSZnG_stepRow",
583
+ "sectionLabel": "vZSZnG_sectionLabel",
584
+ "emptyDesc": "vZSZnG_emptyDesc",
585
+ "fileLine": "vZSZnG_fileLine",
586
+ "boundaryFallback": "vZSZnG_boundaryFallback",
505
587
  "fileDot": "vZSZnG_fileDot",
506
- "dropPulse": "vZSZnG_dropPulse",
588
+ "memRow": "vZSZnG_memRow",
507
589
  "stepContent": "vZSZnG_stepContent",
508
- "stepInput": "vZSZnG_stepInput",
509
- "track": "vZSZnG_track",
510
- "muted": "vZSZnG_muted",
511
- "cardMeta": "vZSZnG_cardMeta",
512
- "miniChevron": "vZSZnG_miniChevron",
513
- "stepRun": "vZSZnG_stepRun",
514
- "stepEditable": "vZSZnG_stepEditable",
515
- "dragGhostContent": "vZSZnG_dragGhostContent",
516
- "chevron": "vZSZnG_chevron",
517
- "dragGhostCard": "vZSZnG_dragGhostCard",
518
- "cardBound": "vZSZnG_cardBound",
519
- "boundaryFallback": "vZSZnG_boundaryFallback",
520
- "headerTitle": "vZSZnG_headerTitle",
590
+ "fileRow": "vZSZnG_fileRow",
591
+ "cardHead": "vZSZnG_cardHead",
521
592
  "stepContentDone": "vZSZnG_stepContentDone",
522
- "fileLine": "vZSZnG_fileLine",
523
- "sectionLabel": "vZSZnG_sectionLabel",
524
- "emptyTitle": "vZSZnG_emptyTitle",
593
+ "dropTargetAfter": "vZSZnG_dropTargetAfter",
525
594
  "stepDragging": "vZSZnG_stepDragging",
595
+ "memNew": "vZSZnG_memNew",
596
+ "taskList": "vZSZnG_taskList",
597
+ "memCount": "vZSZnG_memCount",
598
+ "stepToggle": "vZSZnG_stepToggle",
526
599
  "trackFill": "vZSZnG_trackFill",
527
- "miniIcon": "vZSZnG_miniIcon",
528
- "progressText": "vZSZnG_progressText",
529
- "cardTitle": "vZSZnG_cardTitle",
530
- "cardFooter": "vZSZnG_cardFooter",
531
- "headerIconBtn": "vZSZnG_headerIconBtn",
600
+ "memToolbar": "vZSZnG_memToolbar",
601
+ "stepPending": "vZSZnG_stepPending",
602
+ "memBody": "vZSZnG_memBody",
603
+ "memRowMain": "vZSZnG_memRowMain",
604
+ "badgeArchived": "vZSZnG_badgeArchived",
532
605
  "header": "vZSZnG_header",
533
- "miniBar": "vZSZnG_miniBar",
534
- "dropTargetAfter": "vZSZnG_dropTargetAfter",
535
- "filesList": "vZSZnG_filesList",
536
- "boundBadge": "vZSZnG_boundBadge",
537
- "cardTitleEditable": "vZSZnG_cardTitleEditable",
538
- "fileRow": "vZSZnG_fileRow",
539
606
  "dragGhost": "vZSZnG_dragGhost",
540
- "cardTitleRow": "vZSZnG_cardTitleRow",
541
- "cardHead": "vZSZnG_cardHead",
542
- "panel": "vZSZnG_panel",
543
- "stepRow": "vZSZnG_stepRow",
544
- "headerRight": "vZSZnG_headerRight",
545
- "handleGrip": "vZSZnG_handleGrip",
607
+ "card": "vZSZnG_card",
608
+ "cardTitleEditable": "vZSZnG_cardTitleEditable",
546
609
  "panelIn": "vZSZnG_panelIn",
547
- "stepToggle": "vZSZnG_stepToggle",
548
- "notice": "vZSZnG_notice",
610
+ "headerRight": "vZSZnG_headerRight",
549
611
  "emptyState": "vZSZnG_emptyState",
550
- "miniText": "vZSZnG_miniText",
551
- "updated": "vZSZnG_updated",
612
+ "headerIconBtn": "vZSZnG_headerIconBtn",
613
+ "progressText": "vZSZnG_progressText",
614
+ "boundBadge": "vZSZnG_boundBadge",
615
+ "headerIcon": "vZSZnG_headerIcon",
616
+ "chevron": "vZSZnG_chevron",
617
+ "track": "vZSZnG_track",
618
+ "kindBadge": "vZSZnG_kindBadge",
619
+ "memLabel": "vZSZnG_memLabel",
620
+ "cardBound": "vZSZnG_cardBound",
552
621
  "stepsList": "vZSZnG_stepsList",
553
- "dragHandle": "vZSZnG_dragHandle",
554
- "taskList": "vZSZnG_taskList",
555
- "sectionCount": "vZSZnG_sectionCount",
622
+ "dragGhostContent": "vZSZnG_dragGhostContent",
623
+ "miniIcon": "vZSZnG_miniIcon",
624
+ "stepEditable": "vZSZnG_stepEditable",
625
+ "memNewRow": "vZSZnG_memNewRow",
626
+ "panel": "vZSZnG_panel",
627
+ "filePath": "vZSZnG_filePath",
628
+ "badge": "vZSZnG_badge",
629
+ "memTitle": "vZSZnG_memTitle",
630
+ "cardFooter": "vZSZnG_cardFooter",
631
+ "headerLeft": "vZSZnG_headerLeft",
632
+ "notice": "vZSZnG_notice",
633
+ "headerTitle": "vZSZnG_headerTitle",
634
+ "miniBar": "vZSZnG_miniBar",
556
635
  "stepDone": "vZSZnG_stepDone",
557
- "syncHint": "vZSZnG_syncHint",
558
- "section": "vZSZnG_section",
559
636
  "stepContentRun": "vZSZnG_stepContentRun",
560
- "dragGhostClose": "vZSZnG_dragGhostClose",
561
- "emptyDesc": "vZSZnG_emptyDesc",
637
+ "cardBody": "vZSZnG_cardBody",
638
+ "filesList": "vZSZnG_filesList",
639
+ "handleGrip": "vZSZnG_handleGrip",
640
+ "memoryPane": "vZSZnG_memoryPane",
641
+ "memRowArchived": "vZSZnG_memRowArchived",
642
+ "dragHandle": "vZSZnG_dragHandle",
643
+ "miniChevron": "vZSZnG_miniChevron",
644
+ "badgeDraft": "vZSZnG_badgeDraft",
645
+ "memList": "vZSZnG_memList",
646
+ "memActs": "vZSZnG_memActs",
647
+ "memToolbarActs": "vZSZnG_memToolbarActs",
648
+ "cardMeta": "vZSZnG_cardMeta",
649
+ "stepRun": "vZSZnG_stepRun",
650
+ "stepInput": "vZSZnG_stepInput",
651
+ "dragGhostCard": "vZSZnG_dragGhostCard",
652
+ "sectionCount": "vZSZnG_sectionCount",
653
+ "muted": "vZSZnG_muted",
654
+ "counts": "vZSZnG_counts",
562
655
  "dropTargetBefore": "vZSZnG_dropTargetBefore",
563
- "stepPending": "vZSZnG_stepPending",
564
- "cardBody": "vZSZnG_cardBody"
656
+ "dropPulse": "vZSZnG_dropPulse",
657
+ "miniText": "vZSZnG_miniText"
565
658
  };
566
659
  //#endregion
567
660
  //#region src/client/TaskComponents.tsx
@@ -569,6 +662,14 @@ window.__ModuleLoader__.load({
569
662
  * Task Panel Presentational 组件 — MiniBar(折叠迷你条)与 TaskCard(任务卡)。
570
663
  * 纯渲染 + 卡片局部行内编辑/拖拽状态,动作经 props 回调交给容器(TaskPanel.tsx)。
571
664
  */
665
+ function insightKindLabel(kind, t) {
666
+ return {
667
+ lesson: t("mem.kind.lesson"),
668
+ decision: t("mem.kind.decision"),
669
+ procedure: t("mem.kind.procedure"),
670
+ experience: t("mem.kind.experience")
671
+ }[kind] ?? kind;
672
+ }
572
673
  function timeAgo(iso) {
573
674
  if (!iso) return "";
574
675
  const diff = Date.now() - new Date(iso).getTime();
@@ -643,7 +744,7 @@ window.__ModuleLoader__.load({
643
744
  ]
644
745
  });
645
746
  }
646
- function TaskCard({ task, isBound, expanded, onToggleExpand, onSwitch, onUnbind, onArchive, onRename, onEditStep, onCycleStatus, onReorderSteps, showHints, syncing, t }) {
747
+ function TaskCard({ task, isBound, expanded, onToggleExpand, onSwitch, onUnbind, onArchive, onRename, onEditStep, onCycleStatus, onReorderSteps, onInsightAction, showHints, syncing, t }) {
647
748
  const steps = task.steps || [];
648
749
  const { dragState, dropTargetIndex, startDrag, cancelDrag } = useTaskDrag(task.id, steps, isBound, onReorderSteps);
649
750
  const [stepEdit, setStepEdit] = (0, react.useState)(null);
@@ -855,6 +956,60 @@ window.__ModuleLoader__.load({
855
956
  })]
856
957
  })]
857
958
  }),
959
+ onInsightAction && Array.isArray(task.insights) && task.insights.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
960
+ className: TaskPanel_module_css_default.section,
961
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
962
+ className: TaskPanel_module_css_default.sectionLabel,
963
+ children: [t("mem.section-label"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
964
+ className: TaskPanel_module_css_default.sectionCount,
965
+ children: task.insights.length
966
+ })]
967
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
968
+ className: TaskPanel_module_css_default.memList,
969
+ children: task.insights.map((ins) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
970
+ className: TaskPanel_module_css_default.memRow,
971
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
972
+ className: TaskPanel_module_css_default.memTitle,
973
+ children: [
974
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
975
+ className: TaskPanel_module_css_default.kindBadge,
976
+ children: insightKindLabel(ins.kind, t)
977
+ }),
978
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: ins.title || ins.id }),
979
+ ins.draft && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
980
+ className: `${TaskPanel_module_css_default.badge} ${TaskPanel_module_css_default.badgeDraft}`,
981
+ children: t("mem.draft")
982
+ })
983
+ ]
984
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
985
+ className: TaskPanel_module_css_default.memActs,
986
+ children: [
987
+ ins.draft && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
988
+ variant: "outline",
989
+ size: "sm",
990
+ disabled: syncing,
991
+ onClick: () => onInsightAction("confirm", ins.id),
992
+ children: t("mem.confirm")
993
+ }),
994
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
995
+ variant: "outline",
996
+ size: "sm",
997
+ disabled: syncing,
998
+ onClick: () => onInsightAction("promote", ins.id),
999
+ children: t("mem.promote")
1000
+ }),
1001
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1002
+ variant: "outline",
1003
+ size: "sm",
1004
+ disabled: syncing,
1005
+ onClick: () => onInsightAction("delete", ins.id),
1006
+ children: t("mem.delete")
1007
+ })
1008
+ ]
1009
+ })]
1010
+ }, ins.id))
1011
+ })]
1012
+ }),
858
1013
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
859
1014
  className: TaskPanel_module_css_default.cardFooter,
860
1015
  children: [
@@ -888,6 +1043,469 @@ window.__ModuleLoader__.load({
888
1043
  });
889
1044
  }
890
1045
  //#endregion
1046
+ //#region src/client/MemoryView.tsx
1047
+ /**
1048
+ * Memory View — 记忆三作用域列表(Task 草稿 / Project / Global)
1049
+ * 数据通道与任务面板一致:remote.commands.execute 执行 /insight 命令,取 JSON 载荷。
1050
+ * 动作:confirm(草稿审核) / promote(向上提升) / demote(向下降级,需绑定任务) / archive / restore / delete
1051
+ */
1052
+ function parseInsightPayloadText(text) {
1053
+ if (!text) return null;
1054
+ let jsonBlock = null;
1055
+ const fenced = text.match(/```(?:json)?\s*\n([\s\S]*?)\n```/);
1056
+ if (fenced) jsonBlock = fenced[1];
1057
+ else {
1058
+ const lastBrace = text.lastIndexOf("{");
1059
+ if (lastBrace !== -1) jsonBlock = text.slice(lastBrace);
1060
+ }
1061
+ if (!jsonBlock) return null;
1062
+ try {
1063
+ const data = JSON.parse(jsonBlock);
1064
+ if (!Array.isArray(data.items)) return null;
1065
+ return {
1066
+ scope: data.scope ?? "project",
1067
+ count: data.count ?? data.items.length,
1068
+ items: data.items
1069
+ };
1070
+ } catch {
1071
+ return null;
1072
+ }
1073
+ }
1074
+ function kindText(kind, t) {
1075
+ return {
1076
+ lesson: t("mem.kind.lesson"),
1077
+ decision: t("mem.kind.decision"),
1078
+ procedure: t("mem.kind.procedure"),
1079
+ experience: t("mem.kind.experience")
1080
+ }[kind] ?? kind;
1081
+ }
1082
+ function MemoryView({ ctx, sessionId, scope, boundTaskId, t }) {
1083
+ const [payload, setPayload] = (0, react.useState)(null);
1084
+ const [error, setError] = (0, react.useState)(null);
1085
+ const [loading, setLoading] = (0, react.useState)(false);
1086
+ const [busy, setBusy] = (0, react.useState)(false);
1087
+ const [showNew, setShowNew] = (0, react.useState)(false);
1088
+ const [editingId, setEditingId] = (0, react.useState)(null);
1089
+ const [form, setForm] = (0, react.useState)({
1090
+ title: "",
1091
+ kind: "lesson",
1092
+ body: "",
1093
+ steps: "",
1094
+ trigger: ""
1095
+ });
1096
+ const [savedTip, setSavedTip] = (0, react.useState)(null);
1097
+ const runLine = (0, react.useCallback)(async (line) => {
1098
+ const commands = ctx?.remote?.commands;
1099
+ if (!sessionId || !commands || typeof commands.execute !== "function") return {
1100
+ ok: false,
1101
+ text: "no session / commands service"
1102
+ };
1103
+ try {
1104
+ const envelope = await commands.execute(sessionId, line, []);
1105
+ const execution = envelope && typeof envelope === "object" && "value" in envelope ? envelope.value : envelope;
1106
+ const result = execution?.result ?? execution;
1107
+ if (result?.kind === "error") return {
1108
+ ok: false,
1109
+ text: result.text ?? "command error"
1110
+ };
1111
+ return {
1112
+ ok: true,
1113
+ text: result?.text ?? ""
1114
+ };
1115
+ } catch (err) {
1116
+ return {
1117
+ ok: false,
1118
+ text: String(err?.message ?? err)
1119
+ };
1120
+ }
1121
+ }, [ctx, sessionId]);
1122
+ const inflightRef = (0, react.useRef)(false);
1123
+ const lastRunRef = (0, react.useRef)(0);
1124
+ const refresh = (0, react.useCallback)(async (force = false) => {
1125
+ if (inflightRef.current) return;
1126
+ const now = Date.now();
1127
+ if (!force && now - lastRunRef.current < 800) return;
1128
+ inflightRef.current = true;
1129
+ lastRunRef.current = now;
1130
+ setLoading(true);
1131
+ setError(null);
1132
+ try {
1133
+ const res = await runLine(`/insight list ${scope}`);
1134
+ if (!res.ok) {
1135
+ setError(res.text);
1136
+ setPayload(null);
1137
+ return;
1138
+ }
1139
+ const parsed = parseInsightPayloadText(res.text);
1140
+ setPayload(parsed);
1141
+ if (!parsed) setError("unparsable payload");
1142
+ } finally {
1143
+ inflightRef.current = false;
1144
+ setLoading(false);
1145
+ }
1146
+ }, [runLine, scope]);
1147
+ (0, react.useEffect)(() => {
1148
+ refresh();
1149
+ }, [refresh]);
1150
+ const act = async (action, id) => {
1151
+ if (busy) return;
1152
+ setBusy(true);
1153
+ setError(null);
1154
+ try {
1155
+ const line = `/insight ${action} ${scope} ${id}${action === "demote" && scope === "project" && boundTaskId ? ` ${boundTaskId}` : ""}`;
1156
+ const res = await runLine(line);
1157
+ if (!res.ok) setError(res.text);
1158
+ else refresh(true);
1159
+ } finally {
1160
+ setBusy(false);
1161
+ }
1162
+ };
1163
+ const rowToForm = (row) => {
1164
+ const main = row.kind === "lesson" ? row.fix : row.kind === "experience" ? row.solution : row.kind === "decision" ? row.reason : row.body;
1165
+ const body = main && main !== row.title ? main : "";
1166
+ return {
1167
+ title: row.title || "",
1168
+ kind: row.kind || "lesson",
1169
+ body,
1170
+ steps: Array.isArray(row.steps) ? row.steps.join("\n") : "",
1171
+ trigger: (row.trigger?.keywords || []).join(",")
1172
+ };
1173
+ };
1174
+ const startEdit = (row) => {
1175
+ setEditingId(row.id);
1176
+ setForm(rowToForm(row));
1177
+ setShowNew(true);
1178
+ setError(null);
1179
+ };
1180
+ const closeForm = () => {
1181
+ setShowNew(false);
1182
+ setEditingId(null);
1183
+ setForm({
1184
+ title: "",
1185
+ kind: "lesson",
1186
+ body: "",
1187
+ steps: "",
1188
+ trigger: ""
1189
+ });
1190
+ };
1191
+ const changeKind = (next) => {
1192
+ setForm((prev) => {
1193
+ if (prev.kind === next) return prev;
1194
+ const fromProc = prev.kind === "procedure";
1195
+ const toProc = next === "procedure";
1196
+ let body = prev.body;
1197
+ let steps = prev.steps;
1198
+ if (fromProc && !toProc && !body && steps.trim()) body = steps.trim();
1199
+ if (toProc && !fromProc && !steps.trim() && body.trim()) steps = body.trim();
1200
+ return {
1201
+ ...prev,
1202
+ kind: next,
1203
+ body,
1204
+ steps
1205
+ };
1206
+ });
1207
+ };
1208
+ const submitNew = async () => {
1209
+ if (scope === "task" && !editingId) return;
1210
+ if (busy) return;
1211
+ const title = form.title.trim();
1212
+ if (!title) return;
1213
+ setBusy(true);
1214
+ setError(null);
1215
+ try {
1216
+ const fields = {
1217
+ title,
1218
+ kind: form.kind
1219
+ };
1220
+ if (form.kind === "lesson") fields.pattern = title;
1221
+ if (form.kind === "decision") fields.choice = title;
1222
+ if (form.kind === "experience") fields.problem = title;
1223
+ if (form.body.trim()) {
1224
+ if (form.kind === "lesson") fields.fix = form.body.trim();
1225
+ else if (form.kind === "decision") fields.reason = form.body.trim();
1226
+ else if (form.kind === "experience") fields.solution = form.body.trim();
1227
+ else fields.body = form.body.trim();
1228
+ }
1229
+ if (form.kind === "procedure" && form.steps.trim()) fields.steps = form.steps.split("\n").map((s) => s.trim()).filter(Boolean);
1230
+ if (form.kind === "procedure" && form.trigger.trim()) fields.trigger = { keywords: form.trigger.split(/[,,]/).map((s) => s.trim()).filter(Boolean) };
1231
+ const line = editingId ? `/insight edit ${scope} ${editingId} ${JSON.stringify(fields)}` : `/insight save ${scope} ${JSON.stringify(fields)}`;
1232
+ const res = await runLine(line);
1233
+ if (!res.ok) setError(res.text);
1234
+ else {
1235
+ setSavedTip(t("mem.saved"));
1236
+ closeForm();
1237
+ window.setTimeout(() => setSavedTip(null), 2500);
1238
+ refresh(true);
1239
+ }
1240
+ } finally {
1241
+ setBusy(false);
1242
+ }
1243
+ };
1244
+ const items = payload?.items ?? [];
1245
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1246
+ className: TaskPanel_module_css_default.memoryPane,
1247
+ children: [
1248
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1249
+ className: TaskPanel_module_css_default.memToolbar,
1250
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1251
+ className: TaskPanel_module_css_default.memCount,
1252
+ children: [scope === "task" ? t("mem.scope.task") : scope === "global" ? t("mem.scope.global") : t("mem.scope.project"), payload ? ` · ${payload.count}` : ""]
1253
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1254
+ className: TaskPanel_module_css_default.memToolbarActs,
1255
+ children: [
1256
+ savedTip && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1257
+ className: TaskPanel_module_css_default.badge,
1258
+ children: savedTip
1259
+ }),
1260
+ scope !== "task" && !showNew && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1261
+ variant: "outline",
1262
+ size: "sm",
1263
+ disabled: busy,
1264
+ onClick: () => {
1265
+ setShowNew(true);
1266
+ setEditingId(null);
1267
+ setError(null);
1268
+ },
1269
+ children: t("mem.new")
1270
+ }),
1271
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1272
+ variant: "outline",
1273
+ size: "sm",
1274
+ onClick: () => void refresh(true),
1275
+ disabled: loading,
1276
+ title: t("panel.refresh"),
1277
+ "aria-label": t("panel.refresh"),
1278
+ children: "↻"
1279
+ })
1280
+ ]
1281
+ })]
1282
+ }),
1283
+ showNew && scope !== "task" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1284
+ className: TaskPanel_module_css_default.memNew,
1285
+ children: [
1286
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1287
+ className: TaskPanel_module_css_default.stepInput,
1288
+ placeholder: t("mem.f.title"),
1289
+ value: form.title,
1290
+ onChange: (e) => setForm({
1291
+ ...form,
1292
+ title: e.target.value
1293
+ }),
1294
+ autoFocus: true
1295
+ }),
1296
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1297
+ className: TaskPanel_module_css_default.memNewRow,
1298
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
1299
+ className: TaskPanel_module_css_default.memLabel,
1300
+ children: [t("mem.f.kind"), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
1301
+ className: TaskPanel_module_css_default.stepInput,
1302
+ value: form.kind,
1303
+ onChange: (e) => changeKind(e.target.value),
1304
+ children: [
1305
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1306
+ value: "lesson",
1307
+ children: "lesson"
1308
+ }),
1309
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1310
+ value: "decision",
1311
+ children: "decision"
1312
+ }),
1313
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1314
+ value: "procedure",
1315
+ children: "procedure"
1316
+ }),
1317
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1318
+ value: "experience",
1319
+ children: "experience"
1320
+ })
1321
+ ]
1322
+ })]
1323
+ })
1324
+ }),
1325
+ form.kind !== "procedure" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
1326
+ className: TaskPanel_module_css_default.stepInput,
1327
+ placeholder: t("mem.f.body"),
1328
+ rows: 2,
1329
+ value: form.body,
1330
+ onChange: (e) => setForm({
1331
+ ...form,
1332
+ body: e.target.value
1333
+ })
1334
+ }),
1335
+ form.kind === "procedure" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
1336
+ className: TaskPanel_module_css_default.stepInput,
1337
+ placeholder: t("mem.f.steps"),
1338
+ rows: 3,
1339
+ value: form.steps,
1340
+ onChange: (e) => setForm({
1341
+ ...form,
1342
+ steps: e.target.value
1343
+ })
1344
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1345
+ className: TaskPanel_module_css_default.stepInput,
1346
+ placeholder: t("mem.f.trigger"),
1347
+ value: form.trigger,
1348
+ onChange: (e) => setForm({
1349
+ ...form,
1350
+ trigger: e.target.value
1351
+ })
1352
+ })] }),
1353
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1354
+ className: TaskPanel_module_css_default.memActs,
1355
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1356
+ variant: "outline",
1357
+ size: "sm",
1358
+ disabled: busy || !form.title.trim(),
1359
+ onClick: () => void submitNew(),
1360
+ children: t("mem.save")
1361
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1362
+ variant: "outline",
1363
+ size: "sm",
1364
+ onClick: closeForm,
1365
+ children: t("mem.cancel")
1366
+ })]
1367
+ })
1368
+ ]
1369
+ }),
1370
+ error && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1371
+ className: TaskPanel_module_css_default.notice,
1372
+ children: [
1373
+ t("mem.error"),
1374
+ ": ",
1375
+ error
1376
+ ]
1377
+ }),
1378
+ loading && !items.length && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1379
+ className: TaskPanel_module_css_default.muted,
1380
+ children: t("mem.loading")
1381
+ }),
1382
+ !loading && !error && items.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1383
+ className: TaskPanel_module_css_default.muted,
1384
+ children: t("mem.empty")
1385
+ }),
1386
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1387
+ className: TaskPanel_module_css_default.memList,
1388
+ children: items.map((row) => {
1389
+ const canDemoteToTask = scope === "project" && !!boundTaskId;
1390
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1391
+ className: `${TaskPanel_module_css_default.memRow}${row.archived ? ` ${TaskPanel_module_css_default.memRowArchived}` : ""}`,
1392
+ children: [
1393
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1394
+ className: TaskPanel_module_css_default.memRowMain,
1395
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1396
+ className: TaskPanel_module_css_default.memTitle,
1397
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1398
+ className: TaskPanel_module_css_default.kindBadge,
1399
+ children: kindText(row.kind, t)
1400
+ }), row.title || row.body]
1401
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1402
+ className: TaskPanel_module_css_default.memMeta,
1403
+ children: [
1404
+ row.draft && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1405
+ className: `${TaskPanel_module_css_default.badge} ${TaskPanel_module_css_default.badgeDraft}`,
1406
+ children: t("mem.draft")
1407
+ }),
1408
+ row.archived && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1409
+ className: `${TaskPanel_module_css_default.badge} ${TaskPanel_module_css_default.badgeArchived}`,
1410
+ children: t("mem.archived")
1411
+ }),
1412
+ row.taskTitle && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1413
+ className: TaskPanel_module_css_default.badge,
1414
+ children: ["@", row.taskTitle]
1415
+ }),
1416
+ row.members !== void 0 && row.members > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1417
+ className: TaskPanel_module_css_default.badge,
1418
+ children: ["×", row.members]
1419
+ }),
1420
+ row.confidence != null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1421
+ className: TaskPanel_module_css_default.badge,
1422
+ children: [Math.round(row.confidence * 100), "%"]
1423
+ }),
1424
+ row.trigger && row.trigger.keywords.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1425
+ className: TaskPanel_module_css_default.badge,
1426
+ children: ["⚡", row.trigger.keywords.slice(0, 2).join(",")]
1427
+ })
1428
+ ]
1429
+ })]
1430
+ }),
1431
+ row.body && row.body !== row.title && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1432
+ className: TaskPanel_module_css_default.memBody,
1433
+ children: String(row.body).slice(0, 160)
1434
+ }),
1435
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1436
+ className: TaskPanel_module_css_default.memActs,
1437
+ children: [
1438
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1439
+ variant: "outline",
1440
+ size: "sm",
1441
+ disabled: busy,
1442
+ onClick: () => startEdit(row),
1443
+ children: t("mem.edit")
1444
+ }),
1445
+ scope === "task" && !row.archived && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [row.draft && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1446
+ variant: "outline",
1447
+ size: "sm",
1448
+ disabled: busy,
1449
+ onClick: () => void act("confirm", row.id),
1450
+ children: t("mem.confirm")
1451
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1452
+ variant: "outline",
1453
+ size: "sm",
1454
+ disabled: busy,
1455
+ onClick: () => void act("promote", row.id),
1456
+ children: t("mem.promote")
1457
+ })] }),
1458
+ scope === "project" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1459
+ variant: "outline",
1460
+ size: "sm",
1461
+ disabled: busy,
1462
+ onClick: () => void act("promote", row.id),
1463
+ children: t("mem.promote")
1464
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1465
+ variant: "outline",
1466
+ size: "sm",
1467
+ disabled: busy || !canDemoteToTask,
1468
+ title: !canDemoteToTask ? t("mem.needs-bound") : void 0,
1469
+ onClick: () => void act("demote", row.id),
1470
+ children: t("mem.demote")
1471
+ })] }),
1472
+ scope === "global" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1473
+ variant: "outline",
1474
+ size: "sm",
1475
+ disabled: busy,
1476
+ onClick: () => void act("demote", row.id),
1477
+ children: t("mem.demote")
1478
+ }),
1479
+ row.archived ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1480
+ variant: "outline",
1481
+ size: "sm",
1482
+ disabled: busy,
1483
+ onClick: () => void act("restore", row.id),
1484
+ children: t("mem.restore")
1485
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1486
+ variant: "outline",
1487
+ size: "sm",
1488
+ disabled: busy,
1489
+ onClick: () => void act("archive", row.id),
1490
+ children: t("mem.archive")
1491
+ }),
1492
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1493
+ variant: "outline",
1494
+ size: "sm",
1495
+ disabled: busy,
1496
+ onClick: () => void act("delete", row.id),
1497
+ children: t("mem.delete")
1498
+ })
1499
+ ]
1500
+ })
1501
+ ]
1502
+ }, row.id);
1503
+ })
1504
+ })
1505
+ ]
1506
+ });
1507
+ }
1508
+ //#endregion
891
1509
  //#region src/client/TaskPanel.tsx
892
1510
  /**
893
1511
  * Task Panel — dsh web `shell.overlay` 浮动任务面板。
@@ -899,8 +1517,13 @@ window.__ModuleLoader__.load({
899
1517
  "in_progress",
900
1518
  "completed"
901
1519
  ];
902
- function getT() {
903
- return createTranslate(typeof navigator !== "undefined" && navigator.language.startsWith("zh") ? zh : en);
1520
+ const VIEW_CYCLE = [
1521
+ "task",
1522
+ "project",
1523
+ "global"
1524
+ ];
1525
+ function getT(ctx) {
1526
+ return createTranslate(ctx?.locale?.getSnapshot?.()?.active === "zh" ? zh : en);
904
1527
  }
905
1528
  function useSessionId(ctx) {
906
1529
  const [, force] = (0, react.useState)(0);
@@ -936,7 +1559,7 @@ window.__ModuleLoader__.load({
936
1559
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PanelErrorBoundary, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TaskPanelView, { ctx }) });
937
1560
  }
938
1561
  function TaskPanelView({ ctx }) {
939
- const t = getT();
1562
+ const t = getT(ctx);
940
1563
  const data = useTaskData();
941
1564
  const ui = useTaskUI();
942
1565
  const sessionId = useSessionId(ctx);
@@ -944,10 +1567,17 @@ window.__ModuleLoader__.load({
944
1567
  const [syncedAt, setSyncedAt] = (0, react.useState)(0);
945
1568
  const [syncError, setSyncError] = (0, react.useState)(null);
946
1569
  const [showHints, setShowHints] = (0, react.useState)(true);
1570
+ const [view, setView] = (0, react.useState)("task");
1571
+ const cycleView = () => {
1572
+ const i = VIEW_CYCLE.indexOf(view);
1573
+ setView(VIEW_CYCLE[(i + 1) % VIEW_CYCLE.length]);
1574
+ };
1575
+ const viewTitle = view === "task" ? t("panel.title") : view === "global" ? t("view.global") : t("view.project");
947
1576
  const dataActions = useTaskDataActions();
948
1577
  const uiActions = useTaskUIActions();
949
- const activeTasks = data.tasks.filter((task) => !task.archived);
950
- const boundTask = data.boundTaskId ? data.tasks.find((task) => task.id === data.boundTaskId) ?? null : null;
1578
+ const tasks = Array.isArray(data.tasks) ? data.tasks : [];
1579
+ const activeTasks = tasks.filter((task) => !task.archived);
1580
+ const boundTask = data.boundTaskId ? tasks.find((task) => task.id === data.boundTaskId) ?? null : null;
951
1581
  const applyPayload = (text) => {
952
1582
  const parsed = parseTaskPayloadText(text);
953
1583
  if (!parsed) return false;
@@ -988,7 +1618,7 @@ window.__ModuleLoader__.load({
988
1618
  try {
989
1619
  const prevBoundId = data.boundTaskId;
990
1620
  await runLine("/tasks");
991
- const newBoundId = useTaskData.getSnapshot().boundTaskId;
1621
+ const newBoundId = taskDataStore.getSnapshot().boundTaskId;
992
1622
  if (newBoundId && newBoundId !== prevBoundId) await runLine(`/task switch ${newBoundId}`);
993
1623
  } finally {
994
1624
  setSyncing(false);
@@ -1003,6 +1633,16 @@ window.__ModuleLoader__.load({
1003
1633
  setSyncing(false);
1004
1634
  }
1005
1635
  };
1636
+ const handleInsightTask = async (action, id) => {
1637
+ if (syncing) return;
1638
+ setSyncing(true);
1639
+ try {
1640
+ await runLine(`/insight ${action} task ${id}`);
1641
+ await refresh();
1642
+ } finally {
1643
+ setSyncing(false);
1644
+ }
1645
+ };
1006
1646
  const pushSteps = (taskId, steps) => {
1007
1647
  runLine(`/task todos ${JSON.stringify(steps.map((s) => ({
1008
1648
  content: s.content,
@@ -1160,12 +1800,47 @@ window.__ModuleLoader__.load({
1160
1800
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderOpenOutline16, { className: TaskPanel_module_css_default.headerIcon })
1161
1801
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
1162
1802
  className: TaskPanel_module_css_default.headerTitle,
1163
- children: t("panel.title")
1803
+ children: viewTitle
1164
1804
  })]
1165
1805
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1166
1806
  className: TaskPanel_module_css_default.headerRight,
1167
1807
  children: [
1168
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1808
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1809
+ variant: "ghost",
1810
+ size: "sm",
1811
+ onClick: cycleView,
1812
+ "aria-label": t("view.cycle"),
1813
+ title: `${t("view.cycle")}(${view} → ${VIEW_CYCLE[(VIEW_CYCLE.indexOf(view) + 1) % VIEW_CYCLE.length]})`,
1814
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
1815
+ width: "16",
1816
+ height: "16",
1817
+ viewBox: "0 0 24 24",
1818
+ fill: "none",
1819
+ stroke: "currentColor",
1820
+ strokeWidth: "2",
1821
+ strokeLinecap: "round",
1822
+ strokeLinejoin: "round",
1823
+ "aria-hidden": "true",
1824
+ children: [
1825
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M2 6h4" }),
1826
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M2 10h4" }),
1827
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M2 14h4" }),
1828
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M2 18h4" }),
1829
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
1830
+ width: "16",
1831
+ height: "20",
1832
+ x: "4",
1833
+ y: "2",
1834
+ rx: "2"
1835
+ }),
1836
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M15 2v20" }),
1837
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M15 7h5" }),
1838
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M15 12h5" }),
1839
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M15 17h5" })
1840
+ ]
1841
+ })
1842
+ }),
1843
+ view === "task" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1169
1844
  className: TaskPanel_module_css_default.counts,
1170
1845
  children: activeTasks.length > 0 ? `${t("panel.active")} ${activeTasks.length} · ${doneCount}/${activeTasks.length}` : ""
1171
1846
  }),
@@ -1208,7 +1883,13 @@ window.__ModuleLoader__.load({
1208
1883
  syncError
1209
1884
  ]
1210
1885
  }),
1211
- activeTasks.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1886
+ view !== "task" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoryView, {
1887
+ ctx,
1888
+ sessionId,
1889
+ scope: view,
1890
+ boundTaskId: data.boundTaskId,
1891
+ t
1892
+ }) : activeTasks.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1212
1893
  className: TaskPanel_module_css_default.emptyState,
1213
1894
  children: [
1214
1895
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
@@ -1242,6 +1923,7 @@ window.__ModuleLoader__.load({
1242
1923
  onEditStep: (index, value) => commitStepText(task.id, index, value),
1243
1924
  onCycleStatus: (index) => cycleStatus(task.id, index),
1244
1925
  onReorderSteps: (from, to) => reorderSteps(task.id, from, to),
1926
+ onInsightAction: (action, id) => void handleInsightTask(action, id),
1245
1927
  showHints,
1246
1928
  syncing,
1247
1929
  t
@@ -1272,8 +1954,9 @@ window.__ModuleLoader__.load({
1272
1954
  //#endregion
1273
1955
  //#region src/client/TaskCommandNode.tsx
1274
1956
  /**
1275
- * /tasks、/task 命令在会话中的节点渲染器(conversation.chat.commandview,按命令名 key)。
1276
- * 列表型命令(/tasks、无动词 /task)同步数据并打开面板。
1957
+ * /tasks、/task、/insight 命令在会话中的节点渲染器(conversation.chat.commandview,按命令名 key)。
1958
+ * 列表型命令(/tasks、无动词 /task、/insight list)只显示一行摘要;/insight 的动作类只显示一句结果——
1959
+ * 目的:大 JSON 载荷绝不整段渲染进对话(否则切视图会刷屏)。
1277
1960
  */
1278
1961
  function TaskCommandNode({ node }) {
1279
1962
  const name = node?.name ?? "task";
@@ -1281,14 +1964,15 @@ window.__ModuleLoader__.load({
1281
1964
  const verb = (typeof node?.args === "string" ? node.args : "").trim().split(/\s+/)[0] ?? "";
1282
1965
  const isList = name === "tasks" || !verb;
1283
1966
  const text = outcome?.text ?? "";
1284
- const parsed = parseTaskPayloadText(text);
1967
+ const parsedTasks = name !== "insight" ? parseTaskPayloadText(text) : null;
1968
+ const parsedInsights = name === "insight" ? parseInsightPayloadText(text) : null;
1285
1969
  const live = (0, react.useRef)(outcome === null);
1286
1970
  (0, react.useEffect)(() => {
1287
- if (!parsed || !live.current) return;
1971
+ if (!parsedTasks || !live.current) return;
1288
1972
  taskDataStore.actions.setTasks({
1289
- tasks: parsed.tasks,
1290
- boundTaskId: parsed.boundId,
1291
- archivedCount: parsed.archived
1973
+ tasks: parsedTasks.tasks,
1974
+ boundTaskId: parsedTasks.boundId,
1975
+ archivedCount: parsedTasks.archived
1292
1976
  });
1293
1977
  if (isList) taskUIStore.actions.open();
1294
1978
  }, [text]);
@@ -1314,6 +1998,34 @@ window.__ModuleLoader__.load({
1314
1998
  ]
1315
1999
  });
1316
2000
  }
2001
+ if (name === "insight") {
2002
+ if (verb === "list" && parsedInsights) {
2003
+ const scope = parsedInsights.scope;
2004
+ const count = parsedInsights.count ?? parsedInsights.items.length;
2005
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2006
+ className: TaskCommandNode_module_css_default.row,
2007
+ "data-variant": "ok",
2008
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderOpenOutline16, { className: TaskCommandNode_module_css_default.icon }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
2009
+ "记忆 ",
2010
+ scope,
2011
+ " · ",
2012
+ count,
2013
+ " 条 · 已同步到记忆视图"
2014
+ ] })]
2015
+ });
2016
+ }
2017
+ const note = String(text ?? "").split("\n")[0].slice(0, 120);
2018
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2019
+ className: TaskCommandNode_module_css_default.row,
2020
+ "data-variant": "ok",
2021
+ children: [
2022
+ "/insight ",
2023
+ verb,
2024
+ " ",
2025
+ note || "已完成"
2026
+ ]
2027
+ });
2028
+ }
1317
2029
  if (!isList) {
1318
2030
  const note = String(text ?? "").split(/\n{2,}/)[0].replace(/```.*$/s, "").trim().slice(0, 200);
1319
2031
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -1327,9 +2039,9 @@ window.__ModuleLoader__.load({
1327
2039
  ]
1328
2040
  });
1329
2041
  }
1330
- const count = parsed ? parsed.tasks.length : 0;
1331
- const archived = parsed ? parsed.archived : 0;
1332
- const label = parsed ? `任务 ${count} 套${archived ? `(归档 ${archived})` : ""} · 已同步到任务面板` : `/${name} 已执行`;
2042
+ const count = parsedTasks ? parsedTasks.tasks.length : 0;
2043
+ const archived = parsedTasks ? parsedTasks.archived : 0;
2044
+ const label = parsedTasks ? `任务 ${count} 套${archived ? `(归档 ${archived})` : ""} · 已同步到任务面板` : `/${name} 已执行`;
1333
2045
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1334
2046
  className: TaskCommandNode_module_css_default.row,
1335
2047
  "data-variant": "ok",
@@ -1358,7 +2070,8 @@ window.__ModuleLoader__.load({
1358
2070
  "slots",
1359
2071
  "sessions",
1360
2072
  "remote",
1361
- "remote.commands"
2073
+ "remote.commands",
2074
+ "locale"
1362
2075
  ];
1363
2076
  function apply(ctx) {
1364
2077
  const slots = ctx?.slots;
@@ -1372,7 +2085,11 @@ window.__ModuleLoader__.load({
1372
2085
  id: "dsh-project-memory-task-panel",
1373
2086
  order: 100
1374
2087
  }, () => (0, react.createElement)(TaskPanelEntry, { ctx })));
1375
- for (const key of ["tasks", "task"]) slots.inject("conversation.chat.commandview", () => slots.register({
2088
+ for (const key of [
2089
+ "tasks",
2090
+ "task",
2091
+ "insight"
2092
+ ]) slots.inject("conversation.chat.commandview", () => slots.register({
1376
2093
  name: "conversation.chat.commandview",
1377
2094
  key
1378
2095
  }, TaskCommandNode));