@a9i5k4/dsh-auto-memory 0.1.8 → 0.1.10
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/README.md +173 -17
- package/README.zh-CN.md +171 -15
- package/lib/client.js +402 -51
- package/lib/index.js +1341 -72
- package/package.json +2 -2
package/lib/client.js
CHANGED
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
* 3. settings.section — 自动记忆设置页(存储位置、注入、反思风格)
|
|
8
8
|
* Data flows over /api/dsh-auto-memory/* (loopback-only host routes).
|
|
9
9
|
*/
|
|
10
|
+
console.log('[dsh-auto-memory] client v0.1.9 fingerprint: drawer-summary-ok')
|
|
10
11
|
window.__ModuleLoader__.load({
|
|
11
|
-
id: '@
|
|
12
|
+
id: '@deepseek-ai/dsh-auto-memory',
|
|
12
13
|
factory: (require) => {
|
|
13
14
|
var module = { exports: {} }
|
|
14
15
|
var exports = module.exports
|
|
@@ -97,12 +98,24 @@ window.__ModuleLoader__.load({
|
|
|
97
98
|
memoryPanel: '记忆面板',
|
|
98
99
|
memory: '记忆',
|
|
99
100
|
autoMemory: '自动记忆',
|
|
100
|
-
overview: '概览', logs: '日志', notes: '笔记', reflections: '反思', connect: '接续', search: '检索',
|
|
101
|
-
|
|
101
|
+
overview: '概览', logs: '日志', notes: '笔记', reflections: '反思', connect: '接续', calendar: '日历', search: '检索', workspaces: '工作区',
|
|
102
|
+
wsGenerating: '正在生成各工作区总结(每个工作区一次 AI 调用,可能稍慢)…', wsNone: '未发现带记忆的工作区', wsNoSummary: '(无总结)', wsOverview: '工作区总结(跨工作区)',
|
|
103
|
+
debugCenter: '调试中心', dbgLoading: '加载诊断信息…', dbgRefresh: '刷新', dbgRefreshing: '刷新中…',
|
|
104
|
+
fMemoryRoot: '记忆根目录', fMemoryRootHint: '集中式存储:所有工作区记忆统一放在此目录下(每工作区一个子目录),旧版分散的记忆会自动迁移。',
|
|
105
|
+
fBrowse: '浏览…', browseTitle: '选择记忆根目录', fUp: '上级', fSelectDir: '选择此目录',
|
|
106
|
+
pickedDir: '已选择目录:', rememberSave: '(点击「保存设置」后生效)', pickerUnavailable: '系统文件夹选择器不可用,改用内嵌浏览。',
|
|
107
|
+
fDayBoundary: '日界(分钟)', fDayBoundaryHint: '从 0 点起算:凌晨在此之前的活儿归前一天。默认 450=早上 7:30 进入新一天;改 480=8:00;0=按午夜切日。',
|
|
108
|
+
fVersion: '插件版本', checkUpdate: '检查更新', checking: '检查中…', upToDate: '(已是最新)', hasUpdate: '(有新版本)', versionError: '版本检查失败: ', versionCmdHint: '更新命令: cd ~/.dsh/profiles/web && pnpm up @a9i5k4/dsh-auto-memory,然后重启 dsh web 生效。',
|
|
109
|
+
updateNow: '一键更新', updating: '更新中…', updateDone: '更新完成,请重启 dsh web 生效。', updateFailed: '更新失败: ', devLinkHint: '(当前为本地开发链接,请直接同步开发源码)', noProfileHint: '(未找到 dsh profile,无法自动更新)',
|
|
110
|
+
refresh: '刷新', refreshing: '刷新中…', close: '关闭', dragMove: '拖动移动', dragResize: '拖动调整大小', resetPos: '恢复默认位置',
|
|
102
111
|
generated: '已生成', failed: '失败: ',
|
|
112
|
+
generatedAt: '生成于 ',
|
|
113
|
+
pointsCount: ' 项', summarizing: 'AI 总结生成中…', summaryFailed: 'AI 总结生成失败,点 ⟳ 重试',
|
|
103
114
|
pendingReflection: '待生成反思: ',
|
|
104
115
|
pendingReflectionHint: ' —— 可点下方「一键反思」立即生成。',
|
|
105
116
|
todayWork: '今日工作', logEntries: ' 条日志',
|
|
117
|
+
autoSettledToday: '今日已自动沉淀 ', autoSettledSuffix: ' 条要点',
|
|
118
|
+
autoSettledRecent: '最近: ', autoSettledNone: '本轮对话暂无自动沉淀',
|
|
106
119
|
dailyReflection: '每日反思', notYet: '(还没有)',
|
|
107
120
|
workspace: '工作区',
|
|
108
121
|
reflecting: '反思生成中…', oneClickReflect: '一键反思',
|
|
@@ -121,6 +134,7 @@ window.__ModuleLoader__.load({
|
|
|
121
134
|
reflectAutoHint: '自动用最近日志生成反思草稿(便于测试)',
|
|
122
135
|
noReflection: '还没有反思。每天第一次会话时,agent 会主动呈现前一天的工作反思。',
|
|
123
136
|
searchFailed: '检索失败: ', searchPlaceholder: '搜记忆:关键词或自包含描述…', searchBtn: '检索', resultTitle: '结果',
|
|
137
|
+
smartSearch: '智能检索', smartAnswer: '智能回答', keywordsLabel: '关键词: ',
|
|
124
138
|
projectFiles: '项目文件', aiAssistant: 'AI 助手',
|
|
125
139
|
imported: '接入完成', importing: '正在接入 ', importingSuffix: ' 个源…', allImported: '全部接入完成',
|
|
126
140
|
noExternal: '未检测到其他 AI 工具的记忆文件(CodeBuddy/Claude Code/Codex 等)。',
|
|
@@ -134,6 +148,7 @@ window.__ModuleLoader__.load({
|
|
|
134
148
|
yesterdayTimeline: '昨天(', pendingReflectionShort: '昨天的工作还没复盘(',
|
|
135
149
|
saved: '已保存',
|
|
136
150
|
settingsHeader: '记忆存储与行为设置(保存到 DSH 主目录 dsh-auto-memory.json):',
|
|
151
|
+
fFontSize: '界面字号', fFontSizeHint: '记忆面板文字大小(立即生效,仅本机)', fsSm: '小', fsMd: '标准', fsLg: '大', fsXl: '特大',
|
|
137
152
|
fUserDir: '用户记忆目录', fUserDirHint: '跨项目规则存放处,支持 ~ 开头;需有文件写权限。',
|
|
138
153
|
fProjectDir: '项目记忆目录', fProjectDirHint: '相对各工作区的目录名(默认 .dsh-memory)。',
|
|
139
154
|
fInject: '注入记忆上下文', fInjectHint: '每次组装提示词时自动注入 <memory_system> 块。',
|
|
@@ -158,12 +173,24 @@ window.__ModuleLoader__.load({
|
|
|
158
173
|
memoryPanel: 'Memory Panel',
|
|
159
174
|
memory: 'Memory',
|
|
160
175
|
autoMemory: 'Auto Memory',
|
|
161
|
-
overview: 'Overview', logs: 'Logs', notes: 'Notes', reflections: 'Reflections', connect: 'Connect', search: 'Search',
|
|
162
|
-
|
|
176
|
+
overview: 'Overview', logs: 'Logs', notes: 'Notes', reflections: 'Reflections', connect: 'Connect', calendar: 'Calendar', search: 'Search', workspaces: 'Workspaces',
|
|
177
|
+
wsGenerating: 'Generating per-workspace summaries (one AI call each, may take a while)…', wsNone: 'No workspace with memory found', wsNoSummary: '(no summary)', wsOverview: 'Workspace summaries (all workspaces)',
|
|
178
|
+
debugCenter: 'Debug Center', dbgLoading: 'Loading diagnostics…', dbgRefresh: 'Refresh', dbgRefreshing: 'Refreshing…',
|
|
179
|
+
fMemoryRoot: 'Memory root', fMemoryRootHint: 'Centralized storage: all workspace memories live here (one subdir per workspace); legacy memories are auto-migrated.',
|
|
180
|
+
fBrowse: 'Browse…', browseTitle: 'Choose memory root', fUp: 'Up', fSelectDir: 'Select this folder',
|
|
181
|
+
pickedDir: 'Selected folder:', rememberSave: '(click Save to apply)', pickerUnavailable: 'Native folder picker unavailable, falling back to in-app browser.',
|
|
182
|
+
fDayBoundary: 'Day boundary (minutes)', fDayBoundaryHint: 'Minutes from midnight: work before it counts as the previous day. Default 450 = 7:30 AM starts the new day; 480 = 8:00; 0 = midnight cut.',
|
|
183
|
+
fVersion: 'Plugin version', checkUpdate: 'Check for updates', checking: 'Checking…', upToDate: '(up to date)', hasUpdate: '(update available)', versionError: 'Version check failed: ', versionCmdHint: 'Update: cd ~/.dsh/profiles/web && pnpm up @a9i5k4/dsh-auto-memory, then restart dsh web.',
|
|
184
|
+
updateNow: 'Update now', updating: 'Updating…', updateDone: 'Update finished, restart dsh web to apply.', updateFailed: 'Update failed: ', devLinkHint: '(local dev link, sync source instead)', noProfileHint: '(no dsh profile found, cannot auto-update)',
|
|
185
|
+
refresh: 'Refresh', refreshing: 'Refreshing…', close: 'Close', dragMove: 'Drag to move', dragResize: 'Drag to resize', resetPos: 'Reset position',
|
|
163
186
|
generated: 'Generated', failed: 'Failed: ',
|
|
187
|
+
generatedAt: 'Generated ',
|
|
188
|
+
pointsCount: ' items', summarizing: 'AI summary generating…', summaryFailed: 'Summary failed, press refresh to retry',
|
|
164
189
|
pendingReflection: 'Pending reflection: ',
|
|
165
190
|
pendingReflectionHint: ' — click "One-click Reflect" below to generate now.',
|
|
166
191
|
todayWork: 'Today', logEntries: ' log entries',
|
|
192
|
+
autoSettledToday: 'Auto-consolidated ', autoSettledSuffix: ' points today',
|
|
193
|
+
autoSettledRecent: 'Latest: ', autoSettledNone: 'Nothing auto-consolidated this turn',
|
|
167
194
|
dailyReflection: 'Daily reflection', notYet: '(none yet)',
|
|
168
195
|
workspace: 'Workspace',
|
|
169
196
|
reflecting: 'Generating…', oneClickReflect: 'One-click Reflect',
|
|
@@ -182,6 +209,7 @@ window.__ModuleLoader__.load({
|
|
|
182
209
|
reflectAutoHint: 'Auto-generate a reflection draft from recent logs (for testing)',
|
|
183
210
|
noReflection: "No reflections yet. On the first session each day, the agent presents the previous day's reflection.",
|
|
184
211
|
searchFailed: 'Search failed: ', searchPlaceholder: 'Search memory: keyword or self-contained description…', searchBtn: 'Search', resultTitle: 'Results',
|
|
212
|
+
smartSearch: 'Smart search', smartAnswer: 'AI Answer', keywordsLabel: 'Keywords: ',
|
|
185
213
|
projectFiles: 'Project files', aiAssistant: 'AI Assistant',
|
|
186
214
|
imported: 'Imported', importing: 'Importing ', importingSuffix: ' sources…', allImported: 'All imported',
|
|
187
215
|
noExternal: 'No memory files found from other AI tools (CodeBuddy/Claude Code/Codex etc.).',
|
|
@@ -195,6 +223,7 @@ window.__ModuleLoader__.load({
|
|
|
195
223
|
yesterdayTimeline: 'Yesterday (', pendingReflectionShort: 'Yesterday\'s work not reviewed (',
|
|
196
224
|
saved: 'Saved',
|
|
197
225
|
settingsHeader: 'Memory storage & behavior (saved to ~/.dsh/dsh-auto-memory.json):',
|
|
226
|
+
fFontSize: 'Panel font size', fFontSizeHint: 'Memory panel text size (applies immediately, this device only)', fsSm: 'Small', fsMd: 'Normal', fsLg: 'Large', fsXl: 'Extra large',
|
|
198
227
|
fUserDir: 'User memory dir', fUserDirHint: 'Cross-project rules; supports ~ prefix; needs write permission.',
|
|
199
228
|
fProjectDir: 'Project memory dir', fProjectDirHint: 'Directory name relative to each workspace (default .dsh-memory).',
|
|
200
229
|
fInject: 'Inject memory context', fInjectHint: 'Auto-inject <memory_system> block into every prompt.',
|
|
@@ -216,6 +245,21 @@ window.__ModuleLoader__.load({
|
|
|
216
245
|
}
|
|
217
246
|
}
|
|
218
247
|
var locale = 'zh'
|
|
248
|
+
var sessions = null
|
|
249
|
+
// 当前会话工作区(跟随 GUI 切换工作区):从 sessions 服务拿,供 state/summarize/greet 请求使用
|
|
250
|
+
function currentWs() {
|
|
251
|
+
try {
|
|
252
|
+
var snap = sessions && sessions.list && sessions.list.getSnapshot()
|
|
253
|
+
if (!snap) return ''
|
|
254
|
+
var id = snap.current
|
|
255
|
+
if (id === undefined || id === null) return ''
|
|
256
|
+
var s = snap.byId && snap.byId[id]
|
|
257
|
+
return (s && typeof s.cwd === 'string') ? s.cwd : ''
|
|
258
|
+
} catch (e) { return '' }
|
|
259
|
+
}
|
|
260
|
+
var fontScale = 'lg'
|
|
261
|
+
var FONT_SCALES = { sm: '小', md: '标准', lg: '大', xl: '特大' }
|
|
262
|
+
var FONT_SCALE_VALUES = { sm: '0.9', md: '1', lg: '1.15', xl: '1.3' }
|
|
219
263
|
var localeListeners = new Set()
|
|
220
264
|
function t(key) { return (I18N[locale] && I18N[locale][key]) || I18N.zh[key] || key }
|
|
221
265
|
function setLocale(l) { if (l !== 'zh' && l !== 'en') return; if (l === locale) return; locale = l; localeListeners.forEach(function (fn) { try { fn(l) } catch (e) {} }) }
|
|
@@ -227,6 +271,13 @@ window.__ModuleLoader__.load({
|
|
|
227
271
|
list: '/api/dsh-auto-memory/list',
|
|
228
272
|
file: '/api/dsh-auto-memory/file',
|
|
229
273
|
recall: '/api/dsh-auto-memory/recall',
|
|
274
|
+
smartRecall: '/api/dsh-auto-memory/smart-recall',
|
|
275
|
+
workspaces: '/api/dsh-auto-memory/workspaces',
|
|
276
|
+
debug: '/api/dsh-auto-memory/debug',
|
|
277
|
+
browseDir: '/api/dsh-auto-memory/browse-dir',
|
|
278
|
+
pickDir: '/api/dsh-auto-memory/pick-dir',
|
|
279
|
+
updateCheck: '/api/dsh-auto-memory/update-check',
|
|
280
|
+
update: '/api/dsh-auto-memory/update',
|
|
230
281
|
config: '/api/dsh-auto-memory/config',
|
|
231
282
|
reflect: '/api/dsh-auto-memory/reflect',
|
|
232
283
|
reflectAuto: '/api/dsh-auto-memory/reflect-auto',
|
|
@@ -234,6 +285,7 @@ window.__ModuleLoader__.load({
|
|
|
234
285
|
external: '/api/dsh-auto-memory/external',
|
|
235
286
|
externalImport: '/api/dsh-auto-memory/external-import',
|
|
236
287
|
summarize: '/api/dsh-auto-memory/summarize',
|
|
288
|
+
greet: '/api/dsh-auto-memory/greet',
|
|
237
289
|
}
|
|
238
290
|
function query(params) {
|
|
239
291
|
var search = new URLSearchParams()
|
|
@@ -258,7 +310,7 @@ window.__ModuleLoader__.load({
|
|
|
258
310
|
// 视觉:液态玻璃(毛玻璃)—— backdrop-filter + DSH 主题令牌(--dsw-alias-*),
|
|
259
311
|
// 跟随亮/暗主题与页面背景自适应;位置/尺寸由 JS 几何状态驱动(可拖动、可缩放)。
|
|
260
312
|
var CSS = [
|
|
261
|
-
'[data-dam-panel] { position: fixed; left: 16px; width: 440px; height: 560px;',
|
|
313
|
+
'[data-dam-panel] { position: fixed; left: 16px; width: 440px; height: 560px; --dam-scale: 1;',
|
|
262
314
|
' max-width: calc(100vw - 32px); max-height: calc(100vh - 32px);',
|
|
263
315
|
' display: flex; flex-direction: column; overflow: hidden; z-index: 3000; pointer-events: auto;',
|
|
264
316
|
' border-radius: 16px; font: 13px/1.55 system-ui, "Segoe UI", sans-serif;',
|
|
@@ -271,36 +323,39 @@ window.__ModuleLoader__.load({
|
|
|
271
323
|
'@keyframes dam-in { from { opacity: 0; transform: scale(.92) translateY(10px); } to { opacity: 1; transform: none; } }',
|
|
272
324
|
'@keyframes dam-out { from { opacity: 1; transform: none; } to { opacity: 0; transform: scale(.95) translateY(6px); } }',
|
|
273
325
|
'[data-dam-panel][data-closing="true"] { animation: dam-out .16s ease-in both; }',
|
|
326
|
+
'[data-dam-panel][data-scale="sm"] { --dam-scale: .9; }',
|
|
327
|
+
'[data-dam-panel][data-scale="lg"] { --dam-scale: 1.15; }',
|
|
328
|
+
'[data-dam-panel][data-scale="xl"] { --dam-scale: 1.3; }',
|
|
274
329
|
'[data-dam-panel]::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 64%; pointer-events: none;',
|
|
275
330
|
' background: linear-gradient(180deg, rgba(255,255,255,.13), rgba(255,255,255,0) 70%); border-radius: 16px 16px 0 0; }',
|
|
276
331
|
'[data-dam-panel][data-dragging="true"] { user-select: none; }',
|
|
277
332
|
'[data-dam-panel] header { display: flex; align-items: center; gap: 8px; padding: 10px 14px; cursor: grab;',
|
|
278
333
|
' border-bottom: 1px solid color-mix(in srgb, var(--dsw-alias-border-l1, rgba(128,128,128,.25)) 55%, transparent); }',
|
|
279
334
|
'[data-dam-panel][data-dragging="true"] header { cursor: grabbing; }',
|
|
280
|
-
'[data-dam-panel] header strong { font-size: 14px; }',
|
|
335
|
+
'[data-dam-panel] header strong { font-size: calc(14px * var(--dam-scale)); }',
|
|
281
336
|
'[data-dam-panel] header .dam-spacer { flex: 1; }',
|
|
282
337
|
'[data-dam-resize] { position: absolute; right: 0; bottom: 0; width: 22px; height: 22px; cursor: nwse-resize;',
|
|
283
338
|
' opacity: .55; z-index: 2; border-radius: 0 0 16px 0;',
|
|
284
339
|
' background: linear-gradient(135deg, transparent 50%, color-mix(in srgb, var(--dsw-alias-label-secondary, #666) 45%, transparent) 50%); }',
|
|
285
340
|
'[data-dam-resize]:hover { opacity: 1; }',
|
|
286
|
-
'[data-dam-btn] { border: none; background: transparent; cursor: pointer; color: inherit; opacity: .75; font-size: 13px; padding: 4px 8px; border-radius: 6px; }',
|
|
341
|
+
'[data-dam-btn] { border: none; background: transparent; cursor: pointer; color: inherit; opacity: .75; font-size: calc(13px * var(--dam-scale)); padding: 4px 8px; border-radius: 6px; }',
|
|
287
342
|
'[data-dam-btn]:hover { opacity: 1; background: color-mix(in srgb, var(--dsw-alias-label-secondary, #666) 16%, transparent); }',
|
|
288
343
|
'[data-dam-tabs] { display: flex; gap: 2px; padding: 6px 10px; border-bottom: 1px solid color-mix(in srgb, var(--dsw-alias-border-l1, rgba(128,128,128,.2)) 55%, transparent); }',
|
|
289
|
-
'[data-dam-tab] { border: none; background: transparent; cursor: pointer; color: inherit; opacity: .6; padding: 5px 10px; border-radius: 7px; font-size: 12.5px; }',
|
|
344
|
+
'[data-dam-tab] { border: none; background: transparent; cursor: pointer; color: inherit; opacity: .6; padding: 5px 10px; border-radius: 7px; font-size: calc(12.5px * var(--dam-scale)); }',
|
|
290
345
|
'[data-dam-tab][data-active="true"] { opacity: 1; background: color-mix(in srgb, var(--dsw-alias-label-secondary, #666) 18%, transparent); font-weight: 600; }',
|
|
291
346
|
'[data-dam-body] { flex: 1; overflow: auto; padding: 12px 14px; }',
|
|
292
|
-
'[data-dam-kv] { display: grid; grid-template-columns: auto 1fr; gap: 4px 12px; font-size: 12.5px; }',
|
|
347
|
+
'[data-dam-kv] { display: grid; grid-template-columns: auto 1fr; gap: 4px 12px; font-size: calc(12.5px * var(--dam-scale)); }',
|
|
293
348
|
'[data-dam-kv] b { opacity: .55; font-weight: 500; }',
|
|
294
|
-
'[data-dam-card] { border: 1px solid color-mix(in srgb, var(--dsw-alias-border-l1, rgba(128,128,128,.22)) 60%, transparent); border-radius: 9px; padding: 8px 10px; margin-bottom: 8px; font-size: 12.5px;',
|
|
349
|
+
'[data-dam-card] { border: 1px solid color-mix(in srgb, var(--dsw-alias-border-l1, rgba(128,128,128,.22)) 60%, transparent); border-radius: 9px; padding: 8px 10px; margin-bottom: 8px; font-size: calc(12.5px * var(--dam-scale));',
|
|
295
350
|
' background: color-mix(in srgb, var(--dsw-alias-bg-layer-1, rgba(128,128,128,.06)) 40%, transparent); }',
|
|
296
351
|
'[data-dam-card] .dam-date { font-weight: 600; margin-bottom: 4px; }',
|
|
297
352
|
'[data-dam-card] .dam-content { white-space: pre-wrap; word-break: break-word; max-height: 220px; overflow: auto; }',
|
|
298
353
|
'[data-dam-banner] { border: 1px solid color-mix(in srgb, var(--dsw-alias-state-warn-primary, #e6a23c) 55%, transparent);',
|
|
299
|
-
' background: color-mix(in srgb, var(--dsw-alias-state-warn-primary, #e6a23c) 13%, transparent); border-radius: 9px; padding: 8px 10px; margin-bottom: 10px; font-size: 12.5px; }',
|
|
354
|
+
' background: color-mix(in srgb, var(--dsw-alias-state-warn-primary, #e6a23c) 13%, transparent); border-radius: 9px; padding: 8px 10px; margin-bottom: 10px; font-size: calc(12.5px * var(--dam-scale)); }',
|
|
300
355
|
'[data-dam-input], [data-dam-select] { width: 100%; box-sizing: border-box; background: color-mix(in srgb, var(--dsw-alias-bg-layer-1, rgba(128,128,128,.08)) 45%, transparent); color: inherit; border: 1px solid color-mix(in srgb, var(--dsw-alias-border-l1, rgba(128,128,128,.3)) 60%, transparent); border-radius: 7px; padding: 6px 8px; font: inherit; }',
|
|
301
356
|
'[data-dam-row] { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }',
|
|
302
|
-
'[data-dam-row] label { flex: 0 0 110px; opacity: .8; font-size: 12.5px; }',
|
|
303
|
-
'[data-dam-hint] { opacity: .5; font-size: 11.5px; margin-top: 2px; }',
|
|
357
|
+
'[data-dam-row] label { flex: 0 0 110px; opacity: .8; font-size: calc(12.5px * var(--dam-scale)); }',
|
|
358
|
+
'[data-dam-hint] { opacity: .5; font-size: calc(11.5px * var(--dam-scale)); margin-top: 2px; }',
|
|
304
359
|
'[data-dam-sidebar-btn] { display: flex; align-items: center; gap: 6px; width: 100%; border: none; background: transparent; color: inherit; cursor: pointer; padding: 6px 10px; border-radius: 8px; font: inherit; font-size: 13px; opacity: .8; }',
|
|
305
360
|
'[data-dam-sidebar-btn]:hover { background: color-mix(in srgb, var(--dsw-alias-label-secondary, #666) 14%, transparent); opacity: 1; }',
|
|
306
361
|
'[data-dam-sidebar-btn][data-active="true"] { opacity: 1; background: color-mix(in srgb, var(--dsw-alias-brand-primary, #4f7cff) 16%, transparent); color: var(--dsw-alias-brand-primary, #4f7cff); }',
|
|
@@ -314,7 +369,7 @@ window.__ModuleLoader__.load({
|
|
|
314
369
|
if (document.getElementById(STYLE_ID)) return
|
|
315
370
|
var tag = document.createElement('style')
|
|
316
371
|
tag.id = STYLE_ID
|
|
317
|
-
tag.dataset.plugin = '@
|
|
372
|
+
tag.dataset.plugin = '@deepseek-ai/dsh-auto-memory'
|
|
318
373
|
tag.textContent = CSS
|
|
319
374
|
document.head.appendChild(tag)
|
|
320
375
|
}
|
|
@@ -360,6 +415,9 @@ window.__ModuleLoader__.load({
|
|
|
360
415
|
var openPair = useState({})
|
|
361
416
|
var openMap = openPair[0]
|
|
362
417
|
var setOpenMap = openPair[1]
|
|
418
|
+
var subOpenPair = useState({})
|
|
419
|
+
var subOpenMap = subOpenPair[0]
|
|
420
|
+
var setSubOpenMap = subOpenPair[1]
|
|
363
421
|
// 智能时段判定
|
|
364
422
|
var hour = new Date().getHours()
|
|
365
423
|
var seg = hour < 9 ? 'morning' : hour < 12 ? 'forenoon' : hour < 14 ? 'noon' : hour < 18 ? 'afternoon' : 'evening'
|
|
@@ -369,7 +427,7 @@ window.__ModuleLoader__.load({
|
|
|
369
427
|
var curSegName = { morning: '早晨', forenoon: '上午', noon: '中午', afternoon: '下午', evening: '晚上' }[seg]
|
|
370
428
|
// 昨天抽屉(早晨显示)
|
|
371
429
|
if (seg === 'morning' && g.entries.length) {
|
|
372
|
-
drawers.push({ key: 'yesterday', label: t('yesterdayDrawer') + (g.yesterdayDate || ''), hint: '', items: g.entries, withTime: true, defaultOpen: true })
|
|
430
|
+
drawers.push({ key: 'yesterday', label: t('yesterdayDrawer') + (g.yesterdayDate || ''), hint: '', items: g.entries, withTime: true, defaultOpen: true, period: '昨天' })
|
|
373
431
|
}
|
|
374
432
|
// 今天各时段抽屉(已过的时段)
|
|
375
433
|
var seenSeg = { '早晨': seg !== 'morning', '上午': (seg === 'forenoon' || seg === 'noon' || seg === 'afternoon' || seg === 'evening'), '中午': (seg === 'noon' || seg === 'afternoon' || seg === 'evening'), '下午': (seg === 'afternoon' || seg === 'evening'), '晚上': seg === 'evening' }
|
|
@@ -379,7 +437,7 @@ window.__ModuleLoader__.load({
|
|
|
379
437
|
if (!seenSeg[sname]) continue
|
|
380
438
|
var items = (ps && ps.groups && ps.groups[sname]) || []
|
|
381
439
|
if (!items.length) continue
|
|
382
|
-
drawers.push({ key: 'seg-' + sname, label: t('segPrefix') + sname, hint: '', items: items.map(function (x) { return { time: '', text: x } }), withTime: false, defaultOpen: sname === curSegName })
|
|
440
|
+
drawers.push({ key: 'seg-' + sname, label: t('segPrefix') + sname, hint: '', items: items.map(function (x) { return { time: '', text: x } }), withTime: false, defaultOpen: sname === curSegName, period: sname })
|
|
383
441
|
}
|
|
384
442
|
// 外层:生活化问候
|
|
385
443
|
var totalCount = 0
|
|
@@ -404,33 +462,64 @@ window.__ModuleLoader__.load({
|
|
|
404
462
|
var sumCachePair = useState({})
|
|
405
463
|
var sumCache = sumCachePair[0]
|
|
406
464
|
var setSumCache = sumCachePair[1]
|
|
407
|
-
function requestSummary(key, period) {
|
|
408
|
-
if (sumCache[key] !== undefined) return
|
|
409
|
-
apiPost(API.summarize, { period: period }).then(function (d) {
|
|
410
|
-
if (d && d.
|
|
411
|
-
|
|
465
|
+
function requestSummary(key, period, force) {
|
|
466
|
+
if (!force && sumCache[key] !== undefined) return
|
|
467
|
+
apiPost(API.summarize, { period: period, force: !!force, ws: currentWs() }).then(function (d) {
|
|
468
|
+
if (d && (d.summary || (d.works && d.works.length))) {
|
|
469
|
+
var n = Object.assign({}, sumCache)
|
|
470
|
+
n[key] = { summary: d.summary || d.result || '', works: d.works || [], at: d.generatedAt || Date.now(), failed: false }
|
|
471
|
+
setSumCache(n)
|
|
472
|
+
}
|
|
473
|
+
}).catch(function () {
|
|
474
|
+
var n = Object.assign({}, sumCache)
|
|
475
|
+
n[key] = { summary: '', works: [], at: 0, failed: true }
|
|
476
|
+
setSumCache(n)
|
|
477
|
+
})
|
|
412
478
|
}
|
|
479
|
+
// 面板刷新键(nonce 变化):已缓存的展开抽屉 force 重新生成
|
|
480
|
+
useEffect(function () {
|
|
481
|
+
if (!props.nonce) return
|
|
482
|
+
for (var d = 0; d < drawers.length; d++) {
|
|
483
|
+
var dr = drawers[d]
|
|
484
|
+
var isOpen = openMap[dr.key] !== undefined ? openMap[dr.key] : dr.defaultOpen
|
|
485
|
+
if (isOpen && sumCache[dr.key] !== undefined) requestSummary(dr.key, dr.period, true)
|
|
486
|
+
}
|
|
487
|
+
}, [props.nonce])
|
|
413
488
|
for (var d = 0; d < drawers.length; d++) {
|
|
414
489
|
(function (dr) {
|
|
415
490
|
var isOpen = openMap[dr.key] !== undefined ? openMap[dr.key] : dr.defaultOpen
|
|
416
|
-
if (isOpen && sumCache[dr.key] === undefined)
|
|
417
|
-
|
|
418
|
-
|
|
491
|
+
if (isOpen && sumCache[dr.key] === undefined) requestSummary(dr.key, dr.period, false)
|
|
492
|
+
var cached = sumCache[dr.key]
|
|
493
|
+
// 大抽屉标题:有 AI 总结时用总结内容(用户要求),否则用时段名
|
|
494
|
+
var bigTitle = cached && cached.summary ? cached.summary : dr.label
|
|
419
495
|
rows.push(h('div', { key: dr.key, style: { marginTop: '8px' } },
|
|
420
496
|
h('button', {
|
|
421
497
|
'data-dam-btn': '',
|
|
422
498
|
onClick: function () { var n = Object.assign({}, openMap); n[dr.key] = !isOpen; setOpenMap(n) },
|
|
423
|
-
style: { width: '100%',
|
|
499
|
+
style: { width: '100%', textAlign: 'left', padding: '7px 9px', borderRadius: '8px', background: 'color-mix(in srgb, var(--dsw-alias-bg-layer-1, rgba(128,128,128,.08)) 45%, transparent)', border: '1px solid color-mix(in srgb, var(--dsw-alias-border-l1, rgba(128,128,128,.3)) 50%, transparent)' },
|
|
424
500
|
},
|
|
425
|
-
h('
|
|
426
|
-
h('
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
501
|
+
h('div', { style: { fontWeight: 600, fontSize: 'calc(12.5px * var(--dam-scale))', lineHeight: 1.5 } }, (isOpen ? '▼ ' : '▶ ') + bigTitle),
|
|
502
|
+
h('div', { 'data-dam-muted': '', style: { fontSize: 'calc(11px * var(--dam-scale))', marginTop: '2px' } },
|
|
503
|
+
dr.label + ' · ' + dr.items.length + t('logEntries') + (cached && cached.at ? ' · ' + t('generatedAt') + new Date(cached.at).toLocaleTimeString() : ''))),
|
|
504
|
+
isOpen ? h('div', { style: { padding: '4px 2px 2px 8px' } },
|
|
505
|
+
cached && cached.works && cached.works.length ? cached.works.map(function (w, wi) {
|
|
506
|
+
var sk = dr.key + ':w' + wi
|
|
507
|
+
var sOpen = subOpenMap[sk] !== undefined ? subOpenMap[sk] : false
|
|
508
|
+
return h('div', { key: sk, style: { marginTop: '5px' } },
|
|
509
|
+
h('button', {
|
|
510
|
+
'data-dam-btn': '',
|
|
511
|
+
onClick: function () { var n = Object.assign({}, subOpenMap); n[sk] = !sOpen; setSubOpenMap(n) },
|
|
512
|
+
style: { width: '100%', textAlign: 'left', padding: '4px 8px', borderRadius: '6px', background: 'color-mix(in srgb, var(--dsw-alias-bg-layer-1, rgba(128,128,128,.06)) 40%, transparent)', border: '1px solid color-mix(in srgb, var(--dsw-alias-border-l1, rgba(128,128,128,.22)) 45%, transparent)' },
|
|
513
|
+
},
|
|
514
|
+
h('span', { style: { fontWeight: 600, fontSize: 'calc(12px * var(--dam-scale))' } }, (sOpen ? '▾ ' : '▸ ') + w.title),
|
|
515
|
+
h('span', { 'data-dam-muted': '', style: { fontSize: 'calc(11px * var(--dam-scale))', marginLeft: '6px' } }, w.points.length + t('pointsCount'))),
|
|
516
|
+
sOpen ? h('div', { style: { padding: '4px 4px 2px 14px' } },
|
|
517
|
+
w.points.map(function (pt, pi) {
|
|
518
|
+
return h('div', { key: pi, style: { fontSize: 'calc(12px * var(--dam-scale))', lineHeight: 1.5, marginBottom: '2px' } }, '· ' + pt)
|
|
519
|
+
})) : null)
|
|
520
|
+
}) : cached && cached.failed ? h('div', { 'data-dam-hint': '', style: { padding: '4px 6px' } }, t('summaryFailed'))
|
|
521
|
+
: cached && cached.summary ? h('div', { 'data-dam-hint': '', style: { padding: '4px 6px' } }, cached.summary)
|
|
522
|
+
: h('div', { 'data-dam-hint': '', style: { padding: '4px 6px' } }, t('summarizing'))) : null))
|
|
434
523
|
})(drawers[d])
|
|
435
524
|
}
|
|
436
525
|
// 待反思提醒
|
|
@@ -440,7 +529,7 @@ window.__ModuleLoader__.load({
|
|
|
440
529
|
return h(Card, { title: (g.period || '') + ' · ' + segLabel }, rows)
|
|
441
530
|
}
|
|
442
531
|
|
|
443
|
-
function OverviewTab() {
|
|
532
|
+
function OverviewTab(props) {
|
|
444
533
|
var statePair = useState(null)
|
|
445
534
|
var state = statePair[0]
|
|
446
535
|
var setState = statePair[1]
|
|
@@ -453,10 +542,35 @@ window.__ModuleLoader__.load({
|
|
|
453
542
|
var actMsgPair = useState('')
|
|
454
543
|
var actMsg = actMsgPair[0]
|
|
455
544
|
var setActMsg = actMsgPair[1]
|
|
545
|
+
var wsPair = useState(null)
|
|
546
|
+
var wsData = wsPair[0]
|
|
547
|
+
var setWsData = wsPair[1]
|
|
548
|
+
// 每次进入面板 / 点刷新(nonce 变化)/ 面板打开期间每 30s 自动重拉,保证自动沉淀等数据新鲜
|
|
456
549
|
useEffect(function () {
|
|
457
550
|
var alive = true
|
|
458
|
-
|
|
551
|
+
// 跨工作区总结(概览页集成:所有工作区的小总结+细分;读缓存)
|
|
552
|
+
apiPost(API.workspaces, { force: false }).then(function (d) { if (d && alive) setWsData(d) }).catch(function () {})
|
|
553
|
+
apiGet(API.state, { ws: currentWs() }).then(function (s) {
|
|
554
|
+
if (alive) setState(s)
|
|
555
|
+
// 无 AI 问候 → 自动生成一次(host 按时段缓存,不会重复生成)
|
|
556
|
+
if (s && s.greeting && !s.greeting.greeting) {
|
|
557
|
+
apiPost(API.greet, { ws: currentWs() }).then(function (d) {
|
|
558
|
+
if (d && d.greeting && alive) {
|
|
559
|
+
setState(function (prev) {
|
|
560
|
+
var g0 = (prev && prev.greeting) || {}
|
|
561
|
+
return Object.assign({}, prev, { greeting: Object.assign({}, g0, { greeting: d.greeting, hasGreeting: true }) })
|
|
562
|
+
})
|
|
563
|
+
}
|
|
564
|
+
}).catch(function () {})
|
|
565
|
+
}
|
|
566
|
+
}).catch(function () {})
|
|
459
567
|
return function () { alive = false }
|
|
568
|
+
}, [props && props.nonce])
|
|
569
|
+
useEffect(function () {
|
|
570
|
+
var timer = setInterval(function () {
|
|
571
|
+
apiGet(API.state, { ws: currentWs() }).then(function (s) { setState(s) }).catch(function () {})
|
|
572
|
+
}, 30000)
|
|
573
|
+
return function () { clearInterval(timer) }
|
|
460
574
|
}, [])
|
|
461
575
|
useEffect(function () {
|
|
462
576
|
// 记录本次活动时间;下次打开若相隔>1小时,GreetingCard 显示"欢迎回来"
|
|
@@ -468,12 +582,25 @@ window.__ModuleLoader__.load({
|
|
|
468
582
|
setReflectBusy(true); setActMsg('')
|
|
469
583
|
apiPost(API.reflectAuto, {}).then(function (d) {
|
|
470
584
|
setActMsg(d.result || t('generated')); setReflectBusy(false)
|
|
471
|
-
apiGet(API.state).then(function (s) { if (s) setState(s) }).catch(function () {})
|
|
585
|
+
apiGet(API.state, { ws: currentWs() }).then(function (s) { if (s) setState(s) }).catch(function () {})
|
|
472
586
|
}).catch(function (e) { setActMsg(t('failed') + e.message); setReflectBusy(false) })
|
|
473
587
|
}
|
|
474
588
|
return h('div', null,
|
|
475
589
|
// 今日问候卡:问候语 + 昨天时间轴 + 提醒(纯 GUI 渲染,不干扰对话流)
|
|
476
|
-
h(GreetingCard, { greeting: state.greeting, periodSummary: state.periodSummary, t: t }),
|
|
590
|
+
h(GreetingCard, { greeting: state.greeting, periodSummary: state.periodSummary, t: t, nonce: props && props.nonce }),
|
|
591
|
+
// 跨工作区总结(所有工作区的小总结 + 区内细分)
|
|
592
|
+
h('div', { style: { marginTop: '10px' } },
|
|
593
|
+
h('div', { style: { fontWeight: 700, fontSize: 'calc(12.5px * var(--dam-scale))', opacity: 0.75, marginBottom: '6px' } }, t('wsOverview')),
|
|
594
|
+
wsData && wsData.workspaces && wsData.workspaces.length
|
|
595
|
+
? wsData.workspaces.map(function (ws) {
|
|
596
|
+
return h('div', { key: ws.path, style: { border: '1px solid color-mix(in srgb, var(--dsw-alias-border-l1, rgba(128,128,128,.22)) 60%, transparent)', borderRadius: '8px', padding: '7px 9px', marginBottom: '6px', background: 'color-mix(in srgb, var(--dsw-alias-bg-layer-1, rgba(128,128,128,.05)) 40%, transparent)' } },
|
|
597
|
+
h('div', { style: { fontWeight: 600, fontSize: 'calc(12px * var(--dam-scale))' } }, ws.name + (ws.dateRange ? ' · ' + ws.dateRange : '')),
|
|
598
|
+
ws.summary ? h('div', { style: { fontSize: 'calc(12px * var(--dam-scale))', lineHeight: 1.5, marginTop: '3px' } }, ws.summary) : h('div', { 'data-dam-hint': '' }, t('wsNoSummary')),
|
|
599
|
+
(ws.items && ws.items.length) ? ws.items.map(function (it, i) {
|
|
600
|
+
return h('div', { key: i, style: { fontSize: 'calc(11.5px * var(--dam-scale))', marginTop: '2px', opacity: 0.75 } }, '· ' + it)
|
|
601
|
+
}) : null)
|
|
602
|
+
})
|
|
603
|
+
: h('div', { 'data-dam-hint': '' }, t('wsGenerating'))),
|
|
477
604
|
state.pendingReflection
|
|
478
605
|
? h(Banner, null, t('pendingReflection') + state.pendingReflection + t('pendingReflectionHint'))
|
|
479
606
|
: null,
|
|
@@ -482,6 +609,12 @@ window.__ModuleLoader__.load({
|
|
|
482
609
|
h('b', null, t('todayWork')), h('span', null, state.todayEntries + t('logEntries')),
|
|
483
610
|
h('b', null, t('dailyReflection')), h('span', null, state.latestReflectionDate || t('notYet')),
|
|
484
611
|
h('b', null, t('workspace')), h('span', null, state.ws)),
|
|
612
|
+
// 自动沉淀即时反馈(本轮/今日沉淀了多少条、最近一次时间)
|
|
613
|
+
state.autoStats && state.autoStats.count > 0
|
|
614
|
+
? h('div', { 'data-dam-hint': '', style: { marginTop: '2px' } },
|
|
615
|
+
t('autoSettledToday') + state.autoStats.count + t('autoSettledSuffix') +
|
|
616
|
+
(state.autoStats.lastAt ? ' (' + t('autoSettledRecent') + new Date(state.autoStats.lastAt).toLocaleTimeString() + ')' : ''))
|
|
617
|
+
: h('div', { 'data-dam-hint': '', style: { marginTop: '2px' } }, t('autoSettledNone')),
|
|
485
618
|
// 快捷操作
|
|
486
619
|
h('div', { 'data-dam-row': '' },
|
|
487
620
|
h('button', { 'data-dam-btn': '', onClick: oneClickReflect, disabled: reflectBusy }, reflectBusy ? t('reflecting') : t('oneClickReflect')),
|
|
@@ -641,22 +774,69 @@ window.__ModuleLoader__.load({
|
|
|
641
774
|
var resultPair = useState(null)
|
|
642
775
|
var result = resultPair[0]
|
|
643
776
|
var setResult = resultPair[1]
|
|
777
|
+
var smartPair = useState(null)
|
|
778
|
+
var smart = smartPair[0]
|
|
779
|
+
var setSmart = smartPair[1]
|
|
644
780
|
var busyPair = useState(false)
|
|
645
781
|
var busy = busyPair[0]
|
|
646
782
|
var setBusy = busyPair[1]
|
|
647
783
|
function search() {
|
|
648
784
|
if (!q.trim() || busy) return
|
|
649
|
-
setBusy(true); setResult(null)
|
|
785
|
+
setBusy(true); setResult(null); setSmart(null)
|
|
650
786
|
apiPost(API.recall, { query: q.trim() }).then(function (d) { setResult(d.result); setBusy(false) })
|
|
651
787
|
.catch(function (e) { setResult(t('searchFailed') + e.message); setBusy(false) })
|
|
652
788
|
}
|
|
789
|
+
function smartSearch() {
|
|
790
|
+
if (!q.trim() || busy) return
|
|
791
|
+
setBusy(true); setResult(null); setSmart(null)
|
|
792
|
+
apiPost(API.smartRecall, { query: q.trim() }).then(function (d) { setSmart(d); setBusy(false) })
|
|
793
|
+
.catch(function (e) { setSmart({ answer: t('searchFailed') + e.message, keywords: [], hits: [] }); setBusy(false) })
|
|
794
|
+
}
|
|
653
795
|
return h('div', null,
|
|
654
796
|
h('div', { 'data-dam-row': '' },
|
|
655
797
|
h('input', { 'data-dam-input': '', placeholder: t('searchPlaceholder'), value: q, onChange: function (e) { setQ(e.target.value) }, onKeyDown: function (e) { if (e.key === 'Enter') search() } }),
|
|
656
|
-
h('button', { 'data-dam-btn': '', onClick: search, disabled: busy }, t('searchBtn'))
|
|
798
|
+
h('button', { 'data-dam-btn': '', onClick: search, disabled: busy }, t('searchBtn')),
|
|
799
|
+
h('button', { 'data-dam-btn': '', onClick: smartSearch, disabled: busy }, t('smartSearch'))),
|
|
800
|
+
smart ? h(Card, { title: t('smartAnswer') },
|
|
801
|
+
h('div', { 'data-dam-content': '' }, smart.answer || t('empty')),
|
|
802
|
+
smart.keywords && smart.keywords.length ? h('div', { 'data-dam-hint': '', style: { marginTop: '6px' } }, t('keywordsLabel') + smart.keywords.join(' / ')) : null,
|
|
803
|
+
smart.hits && smart.hits.length ? h('div', { 'data-dam-hint': '', style: { marginTop: '6px' } },
|
|
804
|
+
smart.hits.map(function (h, i) { return h('div', { key: i, style: { marginTop: '3px' } }, '· [' + h.where + '] ' + h.line) })) : null)
|
|
805
|
+
: null,
|
|
657
806
|
result ? h(Card, { title: t('resultTitle') }, h('div', { 'data-dam-content': '' }, result)) : null)
|
|
658
807
|
}
|
|
659
808
|
|
|
809
|
+
// ───────────────────────── 工作区总览页签(跨工作区全局总结) ─────────────────────────
|
|
810
|
+
function WorkspaceTab() {
|
|
811
|
+
var dataPair = useState(null)
|
|
812
|
+
var data = dataPair[0]
|
|
813
|
+
var setData = dataPair[1]
|
|
814
|
+
var busyPair = useState(false)
|
|
815
|
+
var busy = busyPair[0]
|
|
816
|
+
var setBusy = busyPair[1]
|
|
817
|
+
function load(force) {
|
|
818
|
+
if (busy) return
|
|
819
|
+
setBusy(true)
|
|
820
|
+
apiPost(API.workspaces, { force: !!force }).then(function (d) { if (d) setData(d); setBusy(false) })
|
|
821
|
+
.catch(function () { setBusy(false) })
|
|
822
|
+
}
|
|
823
|
+
useEffect(function () { load(false) }, [])
|
|
824
|
+
if (!data) return h('div', null, busy ? h('div', { 'data-dam-hint': '' }, t('wsGenerating')) : h(Loading))
|
|
825
|
+
return h('div', null,
|
|
826
|
+
h('div', { 'data-dam-row': '' },
|
|
827
|
+
h('button', { 'data-dam-btn': '', onClick: function () { load(true) }, disabled: busy }, busy ? t('refreshing') : t('refresh')),
|
|
828
|
+
h('span', { 'data-dam-hint': '' }, data.cached ? (t('generatedAt') + new Date(data.generatedAt).toLocaleTimeString()) : '')),
|
|
829
|
+
(data.workspaces && data.workspaces.length) ? data.workspaces.map(function (ws) {
|
|
830
|
+
return h(Card, { key: ws.path, title: ws.name + (ws.dateRange ? ' · ' + ws.dateRange : '') },
|
|
831
|
+
ws.summary ? h('div', { 'data-dam-content': '' }, ws.summary) : h('div', { 'data-dam-hint': '' }, t('wsNoSummary')),
|
|
832
|
+
(ws.items && ws.items.length) ? h('div', { style: { marginTop: '6px' } },
|
|
833
|
+
ws.items.map(function (it, i) {
|
|
834
|
+
return h('div', { key: i, style: { fontSize: 'calc(12px * var(--dam-scale))', marginTop: '3px', lineHeight: 1.5 } }, '· ' + it)
|
|
835
|
+
})) : null,
|
|
836
|
+
h('div', { 'data-dam-hint': '', style: { marginTop: '4px' } }, ws.path + ' · ' + (ws.logCount || 0) + t('logEntries')))
|
|
837
|
+
}) : h('div', { 'data-dam-hint': '' }, t('wsNone')))
|
|
838
|
+
}
|
|
839
|
+
|
|
660
840
|
// ───────────────────────── 日历页签 ─────────────────────────
|
|
661
841
|
var QUADRANT_STYLE = {
|
|
662
842
|
'重要紧急': { color: 'var(--dsw-alias-state-error-primary, #d64545)', label: t('qUrgentImportant') },
|
|
@@ -716,12 +896,12 @@ window.__ModuleLoader__.load({
|
|
|
716
896
|
// 图例
|
|
717
897
|
rows.push(h('div', { 'data-dam-row': '', style: { flexWrap: 'wrap' } },
|
|
718
898
|
Object.keys(QUADRANT_STYLE).map(function (q) {
|
|
719
|
-
return h('span', { key: q, style: { fontSize: '11px', opacity: 0.8, marginRight: '10px' } },
|
|
899
|
+
return h('span', { key: q, style: { fontSize: 'calc(11px * var(--dam-scale))', opacity: 0.8, marginRight: '10px' } },
|
|
720
900
|
h('span', { style: { display: 'inline-block', width: 8, height: 8, borderRadius: 2, background: QUADRANT_STYLE[q].color, marginRight: 4 } }), QUADRANT_STYLE[q].label)
|
|
721
901
|
})))
|
|
722
902
|
// 星期表头
|
|
723
903
|
rows.push(h('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: '3px', marginBottom: '4px' } },
|
|
724
|
-
dowLabels.map(function (dl) { return h('div', { key: dl, style: { textAlign: 'center', fontSize: '11px', opacity: 0.55 } }, dl) })))
|
|
904
|
+
dowLabels.map(function (dl) { return h('div', { key: dl, style: { textAlign: 'center', fontSize: 'calc(11px * var(--dam-scale))', opacity: 0.55 } }, dl) })))
|
|
725
905
|
// 日历格子
|
|
726
906
|
var gridRows = []
|
|
727
907
|
for (var ci = 0; ci < cells.length; ci += 7) {
|
|
@@ -742,7 +922,7 @@ window.__ModuleLoader__.load({
|
|
|
742
922
|
overflow: 'hidden',
|
|
743
923
|
},
|
|
744
924
|
},
|
|
745
|
-
h('div', { style: { fontSize: '11.5px', fontWeight: isToday ? 700 : 500, opacity: isToday ? 1 : 0.7, marginBottom: '3px' } }, dayNum),
|
|
925
|
+
h('div', { style: { fontSize: 'calc(11.5px * var(--dam-scale))', fontWeight: isToday ? 700 : 500, opacity: isToday ? 1 : 0.7, marginBottom: '3px' } }, dayNum),
|
|
746
926
|
es.slice(0, 3).map(function (en) {
|
|
747
927
|
var qs = QUADRANT_STYLE[en.quadrant] || QUADRANT_STYLE['未分类']
|
|
748
928
|
return h('div', {
|
|
@@ -750,14 +930,14 @@ window.__ModuleLoader__.load({
|
|
|
750
930
|
title: en.time + ' ' + en.title,
|
|
751
931
|
onClick: function (ev) { ev.stopPropagation(); toggleDone(en) },
|
|
752
932
|
style: {
|
|
753
|
-
fontSize: '10.5px', lineHeight: 1.35, padding: '1px 4px', borderRadius: 4, marginBottom: 2,
|
|
933
|
+
fontSize: 'calc(10.5px * var(--dam-scale))', lineHeight: 1.35, padding: '1px 4px', borderRadius: 4, marginBottom: 2,
|
|
754
934
|
background: 'color-mix(in srgb, ' + qs.color + ' 18%, transparent)',
|
|
755
935
|
color: qs.color, textDecoration: en.done ? 'line-through' : 'none',
|
|
756
936
|
opacity: en.done ? 0.5 : 1, cursor: 'pointer', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
|
|
757
937
|
},
|
|
758
938
|
}, (en.time && en.time !== '--:--' ? en.time + ' ' : '') + en.title)
|
|
759
939
|
}),
|
|
760
|
-
es.length > 3 ? h('div', { style: { fontSize: '10px', opacity: 0.5 } }, '+' + (es.length - 3)) : null))
|
|
940
|
+
es.length > 3 ? h('div', { style: { fontSize: 'calc(10px * var(--dam-scale))', opacity: 0.5 } }, '+' + (es.length - 3)) : null))
|
|
761
941
|
})(cells[ci + cj])
|
|
762
942
|
}
|
|
763
943
|
gridRows.push(h('div', { key: 'w' + ci, style: { display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: '3px' } }, week))
|
|
@@ -897,23 +1077,29 @@ window.__ModuleLoader__.load({
|
|
|
897
1077
|
var tabPair = useState('overview')
|
|
898
1078
|
var tab = tabPair[0]
|
|
899
1079
|
var setTab = tabPair[1]
|
|
1080
|
+
// 刷新 nonce:每次打开面板 / 点 ⟳ 时递增,驱动各页签重拉数据
|
|
1081
|
+
var noncePair = useState(0)
|
|
1082
|
+
var nonce = noncePair[0]
|
|
1083
|
+
var setNonce = noncePair[1]
|
|
900
1084
|
var g = controller.geom()
|
|
901
1085
|
useEffect(function () { return controller.subscribe(tick[1]) }, [])
|
|
902
1086
|
if (!panelOpen && !panelClosing) return null
|
|
903
1087
|
var body
|
|
904
|
-
if (tab === 'overview') body = h(OverviewTab)
|
|
1088
|
+
if (tab === 'overview') body = h(OverviewTab, { nonce: nonce })
|
|
905
1089
|
else if (tab === 'logs') body = h(LogsTab)
|
|
906
1090
|
else if (tab === 'notes') body = h(NotesTab)
|
|
907
1091
|
else if (tab === 'reflections') body = h(ReflectionsTab)
|
|
908
1092
|
else if (tab === 'connect') body = h(ConnectTab)
|
|
909
1093
|
else if (tab === 'calendar') body = h(CalendarTab)
|
|
1094
|
+
else if (tab === 'workspaces') body = h(WorkspaceTab)
|
|
910
1095
|
else body = h(SearchTab)
|
|
911
|
-
var tabs = [['overview', t('overview')], ['logs', t('logs')], ['notes', t('notes')], ['reflections', t('reflections')], ['connect', t('connect')], ['calendar', t('calendar')], ['search', t('search')]]
|
|
1096
|
+
var tabs = [['overview', t('overview')], ['logs', t('logs')], ['notes', t('notes')], ['reflections', t('reflections')], ['connect', t('connect')], ['calendar', t('calendar')], ['search', t('search')], ['workspaces', t('workspaces')]]
|
|
912
1097
|
var style = {
|
|
913
1098
|
left: g.left + 'px',
|
|
914
1099
|
top: g.top + 'px',
|
|
915
1100
|
width: g.width + 'px',
|
|
916
1101
|
height: g.height + 'px',
|
|
1102
|
+
'--dam-scale': FONT_SCALE_VALUES[fontScale] || '1',
|
|
917
1103
|
}
|
|
918
1104
|
var dragMove = startPointerDrag(function (dx, dy) {
|
|
919
1105
|
controller.setGeom({ left: g.left + dx, top: g.top + dy })
|
|
@@ -923,6 +1109,7 @@ window.__ModuleLoader__.load({
|
|
|
923
1109
|
})
|
|
924
1110
|
return h('div', {
|
|
925
1111
|
'data-dam-panel': '',
|
|
1112
|
+
'data-scale': fontScale in FONT_SCALES ? fontScale : 'md',
|
|
926
1113
|
style: style,
|
|
927
1114
|
'data-closing': panelClosing ? 'true' : undefined,
|
|
928
1115
|
'data-dragging': dragActive ? 'true' : undefined,
|
|
@@ -934,7 +1121,7 @@ window.__ModuleLoader__.load({
|
|
|
934
1121
|
h('strong', null, t('autoMemory')),
|
|
935
1122
|
h('span', { className: 'dam-spacer' }),
|
|
936
1123
|
h('button', { 'data-dam-btn': '', title: t('resetPos'), onClick: function () { controller.resetGeom() } }, '⤾'),
|
|
937
|
-
h('button', { 'data-dam-btn': '', title: t('refresh'), onClick: function () {
|
|
1124
|
+
h('button', { 'data-dam-btn': '', title: t('refresh'), onClick: function () { setNonce(nonce + 1) } }, '⟳'),
|
|
938
1125
|
h('button', { 'data-dam-btn': '', title: t('close'), onClick: function () { controller.close() } }, '✕')),
|
|
939
1126
|
h('div', { 'data-dam-tabs': '' }, tabs.map(function (t) {
|
|
940
1127
|
return h('button', { key: t[0], 'data-dam-tab': '', 'data-active': tab === t[0] ? 'true' : undefined, onClick: function () { setTab(t[0]) } }, t[1])
|
|
@@ -943,10 +1130,70 @@ window.__ModuleLoader__.load({
|
|
|
943
1130
|
h('div', { 'data-dam-resize': '', title: t('dragResize'), onPointerDown: resizeMove }))
|
|
944
1131
|
}
|
|
945
1132
|
|
|
1133
|
+
// ───────────────────────── 调试中心(为提 issue 提供诊断) ─────────────────────────
|
|
1134
|
+
function DebugCenter() {
|
|
1135
|
+
var dataPair = useState(null)
|
|
1136
|
+
var data = dataPair[0]
|
|
1137
|
+
var setData = dataPair[1]
|
|
1138
|
+
var probesPair = useState(null)
|
|
1139
|
+
var probes = probesPair[0]
|
|
1140
|
+
var setProbes = probesPair[1]
|
|
1141
|
+
var busyPair = useState(false)
|
|
1142
|
+
var busy = busyPair[0]
|
|
1143
|
+
var setBusy = busyPair[1]
|
|
1144
|
+
function refresh() {
|
|
1145
|
+
if (busy) return
|
|
1146
|
+
setBusy(true)
|
|
1147
|
+
var probesDone = {}
|
|
1148
|
+
var probeList = [
|
|
1149
|
+
['state', API.state, 'GET'], ['config', API.config, 'GET'], ['list', API.list, 'GET'],
|
|
1150
|
+
['file', API.file, 'GET'], ['calendar', API.calendar, 'GET'], ['debug', API.debug, 'GET'],
|
|
1151
|
+
['recall', API.recall, 'POST'], ['summarize', API.summarize, 'POST'], ['greet', API.greet, 'POST'],
|
|
1152
|
+
['workspaces', API.workspaces, 'POST'], ['reflectAuto', API.reflectAuto, 'POST'],
|
|
1153
|
+
]
|
|
1154
|
+
Promise.all(probeList.map(function (pr) {
|
|
1155
|
+
var t0 = Date.now()
|
|
1156
|
+
return fetch(pr[1], pr[2] === 'POST' ? { method: 'POST', headers: { 'content-type': 'application/json' }, body: '{}' } : undefined)
|
|
1157
|
+
.then(function (r) { probesDone[pr[0]] = { status: r.status, ms: Date.now() - t0 } })
|
|
1158
|
+
.catch(function (e) { probesDone[pr[0]] = { error: e.message } })
|
|
1159
|
+
})).then(function () {
|
|
1160
|
+
setProbes(probesDone)
|
|
1161
|
+
return apiGet(API.debug)
|
|
1162
|
+
}).then(function (d) { setData(d); setBusy(false) }).catch(function () { setBusy(false) })
|
|
1163
|
+
}
|
|
1164
|
+
useEffect(function () { refresh() }, [])
|
|
1165
|
+
if (!data) return h('div', { 'data-dam-hint': '' }, t('dbgLoading'))
|
|
1166
|
+
function kv(label, value, warn) {
|
|
1167
|
+
return h('div', { 'data-dam-row': '', style: { marginBottom: '3px' } },
|
|
1168
|
+
h('span', { style: { flex: '0 0 140px', opacity: .7, fontSize: 'calc(11.5px * var(--dam-scale))' } }, label),
|
|
1169
|
+
h('span', { style: { fontSize: 'calc(11.5px * var(--dam-scale))', wordBreak: 'break-all', color: warn ? 'var(--dsw-alias-state-warn-primary, #e6a23c)' : undefined } }, String(value)))
|
|
1170
|
+
}
|
|
1171
|
+
var hb = data.heartbeat || {}
|
|
1172
|
+
var hbAge = hb.exists && hb.heartbeatAt ? Math.round((Date.now() - hb.heartbeatAt) / 1000) : -1
|
|
1173
|
+
var apiBad = probes && Object.keys(probes).some(function (k) { return probes[k].status === 404 || probes[k].error })
|
|
1174
|
+
return h('div', null,
|
|
1175
|
+
h('div', { 'data-dam-row': '' },
|
|
1176
|
+
h('button', { 'data-dam-btn': '', onClick: refresh, disabled: busy }, busy ? t('dbgRefreshing') : t('dbgRefresh')),
|
|
1177
|
+
h('span', { 'data-dam-hint': '' }, data.host.indexPath || '')),
|
|
1178
|
+
kv('插件版本', data.host.version || '(读不到)', false),
|
|
1179
|
+
kv('PID / 启动', data.host.pid + ' / ' + (data.host.startTime ? new Date(data.host.startTime).toLocaleTimeString() : ''), false),
|
|
1180
|
+
kv('Host 需重启?', data.host.needsRestart ? '是(代码比进程新)' : '否', data.host.needsRestart),
|
|
1181
|
+
kv('轮询心跳', hb.exists ? (hbAge >= 0 ? '存活(上次 ' + hbAge + ' 秒前)' : '存活') : '无心跳文件', !hb.exists || hbAge > 360),
|
|
1182
|
+
kv('沉淀重试队列', data.autoConsolidate.pendingQueue + ' 条', data.autoConsolidate.pendingQueue > 0),
|
|
1183
|
+
kv('今日沉淀', data.autoConsolidate.stats.count + ' 条 / 最近 ' + (data.autoConsolidate.stats.lastAt ? new Date(data.autoConsolidate.stats.lastAt).toLocaleTimeString() : '无'), false),
|
|
1184
|
+
kv('正在沉淀中', data.autoConsolidate.consolidating ? '是' : '否', data.autoConsolidate.consolidating),
|
|
1185
|
+
kv('subagents', data.subagents.available ? (data.subagents.providers.join(', ') || '可用') : '不可用', !data.subagents.available),
|
|
1186
|
+
kv('项目笔记重复标题', data.duplicateHeadings + ' 个', data.duplicateHeadings > 0),
|
|
1187
|
+
kv('记忆文件', '用户 ' + (data.memoryFiles.user.exists ? fmtSize(data.memoryFiles.user.size) : '缺失') + ' · 笔记 ' + (data.memoryFiles.notes.exists ? fmtSize(data.memoryFiles.notes.size) : '缺失') + ' · 日志 ' + (data.memoryFiles.log.exists ? fmtSize(data.memoryFiles.log.size) : '缺失'), !data.memoryFiles.log.exists),
|
|
1188
|
+
kv('当前工作区', currentWs() || '(未取到)', false),
|
|
1189
|
+
kv('API 连通', probes ? Object.keys(probes).map(function (k) { return k + '=' + (probes[k].status !== undefined ? probes[k].status : probes[k].error) }).join(' ') : '…', apiBad))
|
|
1190
|
+
}
|
|
1191
|
+
|
|
946
1192
|
// ───────────────────────── 设置页 ─────────────────────────
|
|
947
1193
|
var STYLE_OPTIONS = [['auto', t('styleAuto')], ['life', t('styleLife')], ['professional', t('styleProfessional')]]
|
|
948
1194
|
var LOCALE_OPTIONS = [['zh', t('zh')], ['en', t('en')]]
|
|
949
1195
|
function SettingsPage() {
|
|
1196
|
+
var tickPair = useTick()
|
|
950
1197
|
var cfgPair = useState(null)
|
|
951
1198
|
var cfg = cfgPair[0]
|
|
952
1199
|
var setCfg = cfgPair[1]
|
|
@@ -959,17 +1206,87 @@ window.__ModuleLoader__.load({
|
|
|
959
1206
|
var errPair = useState('')
|
|
960
1207
|
var err = errPair[0]
|
|
961
1208
|
var setErr = errPair[1]
|
|
1209
|
+
var dbgOpenPair = useState(false)
|
|
1210
|
+
var dbgOpen = dbgOpenPair[0]
|
|
1211
|
+
var setDbgOpen = dbgOpenPair[1]
|
|
1212
|
+
var browseOpenPair = useState(false)
|
|
1213
|
+
var browseOpen = browseOpenPair[0]
|
|
1214
|
+
var setBrowseOpen = browseOpenPair[1]
|
|
1215
|
+
var browsePathPair = useState('')
|
|
1216
|
+
var browsePath = browsePathPair[0]
|
|
1217
|
+
var setBrowsePath = browsePathPair[1]
|
|
1218
|
+
var browseParentPair = useState('')
|
|
1219
|
+
var browseParent = browseParentPair[0]
|
|
1220
|
+
var setBrowseParent = browseParentPair[1]
|
|
1221
|
+
var browseDirsPair = useState(null)
|
|
1222
|
+
var browseDirs = browseDirsPair[0]
|
|
1223
|
+
var setBrowseDirs = browseDirsPair[1]
|
|
1224
|
+
function browseTo(p) {
|
|
1225
|
+
setBrowsePath(p)
|
|
1226
|
+
apiPost(API.browseDir, { path: p }).then(function (d) {
|
|
1227
|
+
if (d) { setBrowsePath(d.path); setBrowseParent(d.parent); setBrowseDirs(d.dirs || []) }
|
|
1228
|
+
}).catch(function () { setBrowseDirs([]) })
|
|
1229
|
+
}
|
|
1230
|
+
function openBrowser() {
|
|
1231
|
+
// 优先弹系统原生文件夹选择器(native 后端);不可用(远程/无显示)回退内嵌浏览
|
|
1232
|
+
apiPost(API.pickDir, {}).then(function (d) {
|
|
1233
|
+
if (d && d.native && d.dir) {
|
|
1234
|
+
set('memoryRoot', d.dir)
|
|
1235
|
+
setMsg(t('pickedDir') + ' ' + d.dir + ' ' + t('rememberSave'))
|
|
1236
|
+
} else if (d && d.native) {
|
|
1237
|
+
// 用户在系统对话框点了取消:保持原值,不动作
|
|
1238
|
+
} else {
|
|
1239
|
+
setMsg(t('pickerUnavailable'))
|
|
1240
|
+
setBrowseOpen(true)
|
|
1241
|
+
browseTo(cfg.memoryRoot || '')
|
|
1242
|
+
}
|
|
1243
|
+
}).catch(function () {
|
|
1244
|
+
setMsg(t('pickerUnavailable'))
|
|
1245
|
+
setBrowseOpen(true)
|
|
1246
|
+
browseTo(cfg.memoryRoot || '')
|
|
1247
|
+
})
|
|
1248
|
+
}
|
|
1249
|
+
useEffect(function () { return controller.subscribe(tickPair[1]) }, [])
|
|
962
1250
|
useEffect(function () {
|
|
963
1251
|
var alive = true
|
|
964
1252
|
apiGet(API.config).then(function (d) { if (alive) setCfg(d.config) }).catch(function (e) { setErr(e.message) })
|
|
1253
|
+
// 打开设置页自动检查更新(host 有 12h 缓存,不重复查网)
|
|
1254
|
+
apiGet(API.updateCheck).then(function (d) { if (alive) setVerInfo(d) }).catch(function () {})
|
|
965
1255
|
return function () { alive = false }
|
|
966
1256
|
}, [])
|
|
967
1257
|
if (!cfg) return err ? h('div', { 'data-dam-error': '' }, err) : h(Loading)
|
|
968
1258
|
function set(key, value) { var next = Object.assign({}, cfg); next[key] = value; setCfg(next) }
|
|
1259
|
+
var verPair = useState(null)
|
|
1260
|
+
var verInfo = verPair[0]
|
|
1261
|
+
var setVerInfo = verPair[1]
|
|
1262
|
+
var checkingPair = useState(false)
|
|
1263
|
+
var checkingUpdate = checkingPair[0]
|
|
1264
|
+
var setCheckingUpdate = checkingPair[1]
|
|
1265
|
+
function checkUpdate() {
|
|
1266
|
+
if (checkingUpdate) return
|
|
1267
|
+
setCheckingUpdate(true)
|
|
1268
|
+
apiGet(API.updateCheck + '?force=1').then(function (d) { setVerInfo(d); setCheckingUpdate(false) })
|
|
1269
|
+
.catch(function (e) { setVerInfo({ error: e.message }); setCheckingUpdate(false) })
|
|
1270
|
+
}
|
|
1271
|
+
var upBusyPair = useState(false)
|
|
1272
|
+
var upBusy = upBusyPair[0]
|
|
1273
|
+
var setUpBusy = upBusyPair[1]
|
|
1274
|
+
var upMsgPair = useState('')
|
|
1275
|
+
var upMsg = upMsgPair[0]
|
|
1276
|
+
var setUpMsg = upMsgPair[1]
|
|
1277
|
+
function doUpdate() {
|
|
1278
|
+
if (upBusy) return
|
|
1279
|
+
setUpBusy(true); setUpMsg('')
|
|
1280
|
+
apiPost(API.update, {}).then(function (d) {
|
|
1281
|
+
setUpBusy(false)
|
|
1282
|
+
if (d && d.ok) { setUpMsg(t('updateDone')); setVerInfo(null); checkUpdate() }
|
|
1283
|
+
else setUpMsg(t('updateFailed') + (d && d.message ? d.message : '(未知)'))
|
|
1284
|
+
}).catch(function (e) { setUpBusy(false); setUpMsg(t('updateFailed') + e.message) })
|
|
1285
|
+
}
|
|
969
1286
|
function save() {
|
|
970
1287
|
if (busy) return
|
|
971
1288
|
setBusy(true); setMsg(''); setErr('')
|
|
972
|
-
apiPost(API.config, cfg).then(function (d) { setCfg(d.config); setMsg(t('saved')); setBusy(false) })
|
|
1289
|
+
apiPost(API.config, cfg).then(function (d) { setCfg(d.config); setMsg(t('saved') + (d.migrated ? ' ' + d.migrated : '')); setBusy(false) })
|
|
973
1290
|
.catch(function (e) { setErr(e.message); setBusy(false) })
|
|
974
1291
|
}
|
|
975
1292
|
function field(label, control, hint) {
|
|
@@ -981,17 +1298,45 @@ window.__ModuleLoader__.load({
|
|
|
981
1298
|
h('div', { 'data-dam-hint': '' }, t('settingsHeader')),
|
|
982
1299
|
field(t('fLocale'), h('select', { 'data-dam-select': '', value: cfg.locale || 'zh', onChange: function (e) { set('locale', e.target.value); setLocale(e.target.value) } },
|
|
983
1300
|
LOCALE_OPTIONS.map(function (o) { return h('option', { key: o[0], value: o[0] }, o[1]) })), t('fLocaleHint')),
|
|
1301
|
+
field(t('fFontSize'), h('select', { 'data-dam-select': '', value: fontScale, onChange: function (e) { fontScale = e.target.value; try { localStorage.setItem('dsh-auto-memory.fontScale.v2', fontScale) } catch (ee) {}; try { var pp = document.querySelector('[data-dam-panel]'); if (pp) pp.style.setProperty('--dam-scale', FONT_SCALE_VALUES[fontScale] || '1') } catch (ee2) {}; emit() } },
|
|
1302
|
+
Object.keys(FONT_SCALES).map(function (k) { return h('option', { key: k, value: k }, t('fs' + k.charAt(0).toUpperCase() + k.slice(1))) })), t('fFontSizeHint')),
|
|
984
1303
|
field(t('fUserDir'), h('input', { 'data-dam-input': '', value: cfg.userMemoryDir, onChange: function (e) { set('userMemoryDir', e.target.value) } }), t('fUserDirHint')),
|
|
985
1304
|
field(t('fProjectDir'), h('input', { 'data-dam-input': '', value: cfg.projectMemoryDir, onChange: function (e) { set('projectMemoryDir', e.target.value) } }), t('fProjectDirHint')),
|
|
1305
|
+
field(t('fMemoryRoot'), h('div', { 'data-dam-row': '', style: { flex: 1 } },
|
|
1306
|
+
h('input', { 'data-dam-input': '', style: { flex: 1 }, value: cfg.memoryRoot || '', onChange: function (e) { set('memoryRoot', e.target.value) } }),
|
|
1307
|
+
h('button', { 'data-dam-btn': '', onClick: function () { openBrowser() } }, t('fBrowse'))), t('fMemoryRootHint')),
|
|
1308
|
+
browseOpen ? h('div', { style: { border: '1px solid color-mix(in srgb, var(--dsw-alias-border-l1, rgba(128,128,128,.25)) 60%, transparent)', borderRadius: '8px', padding: '8px', marginBottom: '8px', background: 'color-mix(in srgb, var(--dsw-alias-bg-layer-1, rgba(128,128,128,.06)) 40%, transparent)' } },
|
|
1309
|
+
h('div', { 'data-dam-row': '' },
|
|
1310
|
+
h('b', { style: { fontSize: 'calc(12px * var(--dam-scale))', wordBreak: 'break-all', flex: 1 } }, browsePath || '…'),
|
|
1311
|
+
h('button', { 'data-dam-btn': '', onClick: function () { browseTo(browseParent) }, disabled: browseParent === browsePath }, t('fUp'))),
|
|
1312
|
+
h('div', { style: { maxHeight: '160px', overflow: 'auto', marginTop: '4px' } },
|
|
1313
|
+
(browseDirs || []).map(function (d) {
|
|
1314
|
+
return h('button', { key: d.path, 'data-dam-btn': '', style: { display: 'block', width: '100%', textAlign: 'left', padding: '3px 6px' }, onClick: function () { browseTo(d.path) } }, '📁 ' + d.name)
|
|
1315
|
+
}).concat(browseDirs && !browseDirs.length ? [h('div', { key: 'e', 'data-dam-hint': '' }, t('empty'))] : [])),
|
|
1316
|
+
h('div', { 'data-dam-row': '', style: { marginTop: '6px' } },
|
|
1317
|
+
h('button', { 'data-dam-btn': '', onClick: function () { set('memoryRoot', browsePath); setBrowseOpen(false) } }, t('fSelectDir')),
|
|
1318
|
+
h('button', { 'data-dam-btn': '', onClick: function () { setBrowseOpen(false) } }, t('close'))))
|
|
1319
|
+
: null,
|
|
986
1320
|
field(t('fInject'), h('input', { type: 'checkbox', checked: !!cfg.injectEnabled, onChange: function (e) { set('injectEnabled', e.target.checked) } }), t('fInjectHint')),
|
|
987
1321
|
field(t('fBudget'), h('input', { 'data-dam-input': '', type: 'number', min: 400, value: cfg.injectBudgetChars, onChange: function (e) { set('injectBudgetChars', Number(e.target.value) || 2400) } }), t('fBudgetHint')),
|
|
988
1322
|
field(t('fDays'), h('input', { 'data-dam-input': '', type: 'number', min: 1, max: 14, value: cfg.recentDaysInjected, onChange: function (e) { set('recentDaysInjected', Number(e.target.value) || 3) } }), t('fDaysHint')),
|
|
1323
|
+
field(t('fDayBoundary'), h('input', { 'data-dam-input': '', type: 'number', min: 0, max: 1439, value: (cfg.dayBoundaryMinutes === undefined ? 450 : cfg.dayBoundaryMinutes), onChange: function (e) { set('dayBoundaryMinutes', parseInt(e.target.value || '0', 10)) } }), t('fDayBoundaryHint')),
|
|
989
1324
|
field(t('fReflect'), h('input', { type: 'checkbox', checked: !!cfg.reflectEnabled, onChange: function (e) { set('reflectEnabled', e.target.checked) } }), t('fReflectHint')),
|
|
990
1325
|
field(t('fStyle'), h('select', { 'data-dam-select': '', value: cfg.reflectStyle, onChange: function (e) { set('reflectStyle', e.target.value) } },
|
|
991
1326
|
STYLE_OPTIONS.map(function (o) { return h('option', { key: o[0], value: o[0] }, o[1]) })), t('fStyleHint')),
|
|
1327
|
+
field(t('fVersion'), h('div', { 'data-dam-row': '' },
|
|
1328
|
+
h('span', { style: { flex: 1 } }, verInfo ? (verInfo.current || '?') + (verInfo.latest ? ' → ' + verInfo.latest + (verInfo.upToDate ? ' ' + t('upToDate') : ' ' + t('hasUpdate')) : '') : (checkingUpdate ? t('checking') : '—')),
|
|
1329
|
+
h('button', { 'data-dam-btn': '', onClick: checkUpdate, disabled: checkingUpdate }, checkingUpdate ? t('checking') : t('checkUpdate')),
|
|
1330
|
+
(verInfo && verInfo.latest && !verInfo.upToDate && verInfo.installKind === 'registry') ? h('button', { 'data-dam-btn': '', onClick: doUpdate, disabled: upBusy, style: { marginLeft: '4px' } }, upBusy ? t('updating') : t('updateNow')) : null,
|
|
1331
|
+
upMsg ? h('span', { 'data-dam-hint': '' }, upMsg) : null),
|
|
1332
|
+
t('versionCmdHint') + (verInfo && verInfo.error ? ' ' + t('versionError') + verInfo.error : '') + (verInfo && verInfo.installKind === 'dev-link' ? ' ' + t('devLinkHint') : '') + (verInfo && !verInfo.installKind ? ' ' + t('noProfileHint') : '')),
|
|
992
1333
|
h('div', { 'data-dam-row': '' },
|
|
993
1334
|
h('button', { 'data-dam-btn': '', onClick: save, disabled: busy }, busy ? t('saving') : t('saveSettings')),
|
|
994
1335
|
msg ? h('span', null, msg) : null),
|
|
1336
|
+
// 调试中心(折叠):模块状态一览,方便排查问题/提 issue
|
|
1337
|
+
h('div', { style: { marginTop: '14px', borderTop: '1px solid color-mix(in srgb, var(--dsw-alias-border-l1, rgba(128,128,128,.2)) 55%, transparent)', paddingTop: '10px' } },
|
|
1338
|
+
h('button', { 'data-dam-btn': '', onClick: function () { setDbgOpen(!dbgOpen) } }, (dbgOpen ? '▴ ' : '▾ ') + t('debugCenter')),
|
|
1339
|
+
dbgOpen ? h('div', { style: { marginTop: '8px' } }, h(DebugCenter)) : null),
|
|
995
1340
|
err ? h('div', { 'data-dam-error': '' }, err) : null)
|
|
996
1341
|
}
|
|
997
1342
|
|
|
@@ -1008,7 +1353,13 @@ window.__ModuleLoader__.load({
|
|
|
1008
1353
|
|
|
1009
1354
|
var slots = ctx.slots
|
|
1010
1355
|
if (!slots) { console.warn('[dsh-auto-memory] slots service unavailable'); return }
|
|
1356
|
+
sessions = ctx.sessions
|
|
1011
1357
|
|
|
1358
|
+
// 初始化界面字号(本地偏好,localStorage 持久化)
|
|
1359
|
+
try {
|
|
1360
|
+
var savedScale = localStorage.getItem('dsh-auto-memory.fontScale.v2')
|
|
1361
|
+
if (savedScale in FONT_SCALES) fontScale = savedScale
|
|
1362
|
+
} catch (e3) {}
|
|
1012
1363
|
// 初始化界面语言(从 host 配置读取,持久化到 localStorage 以便即时生效)
|
|
1013
1364
|
try {
|
|
1014
1365
|
var savedLocale = localStorage.getItem('dsh-auto-memory.locale')
|
|
@@ -1039,7 +1390,7 @@ window.__ModuleLoader__.load({
|
|
|
1039
1390
|
console.log('[dsh-auto-memory] client ready: sidebar entry + panel + settings page')
|
|
1040
1391
|
}
|
|
1041
1392
|
|
|
1042
|
-
exports.inject = ['slots']
|
|
1393
|
+
exports.inject = ['slots', 'sessions']
|
|
1043
1394
|
exports.apply = apply
|
|
1044
1395
|
return module.exports
|
|
1045
1396
|
},
|