@a9i5k4/dsh-auto-memory 0.1.7 → 0.1.9
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 +160 -17
- package/README.zh-CN.md +158 -15
- package/lib/client.js +367 -43
- package/lib/index.js +1266 -58
- 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,22 @@ 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
|
+
refresh: '刷新', refreshing: '刷新中…', close: '关闭', dragMove: '拖动移动', dragResize: '拖动调整大小', resetPos: '恢复默认位置',
|
|
102
109
|
generated: '已生成', failed: '失败: ',
|
|
110
|
+
generatedAt: '生成于 ',
|
|
111
|
+
pointsCount: ' 项', summarizing: 'AI 总结生成中…', summaryFailed: 'AI 总结生成失败,点 ⟳ 重试',
|
|
103
112
|
pendingReflection: '待生成反思: ',
|
|
104
113
|
pendingReflectionHint: ' —— 可点下方「一键反思」立即生成。',
|
|
105
114
|
todayWork: '今日工作', logEntries: ' 条日志',
|
|
115
|
+
autoSettledToday: '今日已自动沉淀 ', autoSettledSuffix: ' 条要点',
|
|
116
|
+
autoSettledRecent: '最近: ', autoSettledNone: '本轮对话暂无自动沉淀',
|
|
106
117
|
dailyReflection: '每日反思', notYet: '(还没有)',
|
|
107
118
|
workspace: '工作区',
|
|
108
119
|
reflecting: '反思生成中…', oneClickReflect: '一键反思',
|
|
@@ -121,6 +132,7 @@ window.__ModuleLoader__.load({
|
|
|
121
132
|
reflectAutoHint: '自动用最近日志生成反思草稿(便于测试)',
|
|
122
133
|
noReflection: '还没有反思。每天第一次会话时,agent 会主动呈现前一天的工作反思。',
|
|
123
134
|
searchFailed: '检索失败: ', searchPlaceholder: '搜记忆:关键词或自包含描述…', searchBtn: '检索', resultTitle: '结果',
|
|
135
|
+
smartSearch: '智能检索', smartAnswer: '智能回答', keywordsLabel: '关键词: ',
|
|
124
136
|
projectFiles: '项目文件', aiAssistant: 'AI 助手',
|
|
125
137
|
imported: '接入完成', importing: '正在接入 ', importingSuffix: ' 个源…', allImported: '全部接入完成',
|
|
126
138
|
noExternal: '未检测到其他 AI 工具的记忆文件(CodeBuddy/Claude Code/Codex 等)。',
|
|
@@ -134,6 +146,7 @@ window.__ModuleLoader__.load({
|
|
|
134
146
|
yesterdayTimeline: '昨天(', pendingReflectionShort: '昨天的工作还没复盘(',
|
|
135
147
|
saved: '已保存',
|
|
136
148
|
settingsHeader: '记忆存储与行为设置(保存到 DSH 主目录 dsh-auto-memory.json):',
|
|
149
|
+
fFontSize: '界面字号', fFontSizeHint: '记忆面板文字大小(立即生效,仅本机)', fsSm: '小', fsMd: '标准', fsLg: '大', fsXl: '特大',
|
|
137
150
|
fUserDir: '用户记忆目录', fUserDirHint: '跨项目规则存放处,支持 ~ 开头;需有文件写权限。',
|
|
138
151
|
fProjectDir: '项目记忆目录', fProjectDirHint: '相对各工作区的目录名(默认 .dsh-memory)。',
|
|
139
152
|
fInject: '注入记忆上下文', fInjectHint: '每次组装提示词时自动注入 <memory_system> 块。',
|
|
@@ -158,12 +171,22 @@ window.__ModuleLoader__.load({
|
|
|
158
171
|
memoryPanel: 'Memory Panel',
|
|
159
172
|
memory: 'Memory',
|
|
160
173
|
autoMemory: 'Auto Memory',
|
|
161
|
-
overview: 'Overview', logs: 'Logs', notes: 'Notes', reflections: 'Reflections', connect: 'Connect', search: 'Search',
|
|
162
|
-
|
|
174
|
+
overview: 'Overview', logs: 'Logs', notes: 'Notes', reflections: 'Reflections', connect: 'Connect', calendar: 'Calendar', search: 'Search', workspaces: 'Workspaces',
|
|
175
|
+
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)',
|
|
176
|
+
debugCenter: 'Debug Center', dbgLoading: 'Loading diagnostics…', dbgRefresh: 'Refresh', dbgRefreshing: 'Refreshing…',
|
|
177
|
+
fMemoryRoot: 'Memory root', fMemoryRootHint: 'Centralized storage: all workspace memories live here (one subdir per workspace); legacy memories are auto-migrated.',
|
|
178
|
+
fBrowse: 'Browse…', browseTitle: 'Choose memory root', fUp: 'Up', fSelectDir: 'Select this folder',
|
|
179
|
+
pickedDir: 'Selected folder:', rememberSave: '(click Save to apply)', pickerUnavailable: 'Native folder picker unavailable, falling back to in-app browser.',
|
|
180
|
+
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.',
|
|
181
|
+
refresh: 'Refresh', refreshing: 'Refreshing…', close: 'Close', dragMove: 'Drag to move', dragResize: 'Drag to resize', resetPos: 'Reset position',
|
|
163
182
|
generated: 'Generated', failed: 'Failed: ',
|
|
183
|
+
generatedAt: 'Generated ',
|
|
184
|
+
pointsCount: ' items', summarizing: 'AI summary generating…', summaryFailed: 'Summary failed, press refresh to retry',
|
|
164
185
|
pendingReflection: 'Pending reflection: ',
|
|
165
186
|
pendingReflectionHint: ' — click "One-click Reflect" below to generate now.',
|
|
166
187
|
todayWork: 'Today', logEntries: ' log entries',
|
|
188
|
+
autoSettledToday: 'Auto-consolidated ', autoSettledSuffix: ' points today',
|
|
189
|
+
autoSettledRecent: 'Latest: ', autoSettledNone: 'Nothing auto-consolidated this turn',
|
|
167
190
|
dailyReflection: 'Daily reflection', notYet: '(none yet)',
|
|
168
191
|
workspace: 'Workspace',
|
|
169
192
|
reflecting: 'Generating…', oneClickReflect: 'One-click Reflect',
|
|
@@ -182,6 +205,7 @@ window.__ModuleLoader__.load({
|
|
|
182
205
|
reflectAutoHint: 'Auto-generate a reflection draft from recent logs (for testing)',
|
|
183
206
|
noReflection: "No reflections yet. On the first session each day, the agent presents the previous day's reflection.",
|
|
184
207
|
searchFailed: 'Search failed: ', searchPlaceholder: 'Search memory: keyword or self-contained description…', searchBtn: 'Search', resultTitle: 'Results',
|
|
208
|
+
smartSearch: 'Smart search', smartAnswer: 'AI Answer', keywordsLabel: 'Keywords: ',
|
|
185
209
|
projectFiles: 'Project files', aiAssistant: 'AI Assistant',
|
|
186
210
|
imported: 'Imported', importing: 'Importing ', importingSuffix: ' sources…', allImported: 'All imported',
|
|
187
211
|
noExternal: 'No memory files found from other AI tools (CodeBuddy/Claude Code/Codex etc.).',
|
|
@@ -195,6 +219,7 @@ window.__ModuleLoader__.load({
|
|
|
195
219
|
yesterdayTimeline: 'Yesterday (', pendingReflectionShort: 'Yesterday\'s work not reviewed (',
|
|
196
220
|
saved: 'Saved',
|
|
197
221
|
settingsHeader: 'Memory storage & behavior (saved to ~/.dsh/dsh-auto-memory.json):',
|
|
222
|
+
fFontSize: 'Panel font size', fFontSizeHint: 'Memory panel text size (applies immediately, this device only)', fsSm: 'Small', fsMd: 'Normal', fsLg: 'Large', fsXl: 'Extra large',
|
|
198
223
|
fUserDir: 'User memory dir', fUserDirHint: 'Cross-project rules; supports ~ prefix; needs write permission.',
|
|
199
224
|
fProjectDir: 'Project memory dir', fProjectDirHint: 'Directory name relative to each workspace (default .dsh-memory).',
|
|
200
225
|
fInject: 'Inject memory context', fInjectHint: 'Auto-inject <memory_system> block into every prompt.',
|
|
@@ -216,6 +241,21 @@ window.__ModuleLoader__.load({
|
|
|
216
241
|
}
|
|
217
242
|
}
|
|
218
243
|
var locale = 'zh'
|
|
244
|
+
var sessions = null
|
|
245
|
+
// 当前会话工作区(跟随 GUI 切换工作区):从 sessions 服务拿,供 state/summarize/greet 请求使用
|
|
246
|
+
function currentWs() {
|
|
247
|
+
try {
|
|
248
|
+
var snap = sessions && sessions.list && sessions.list.getSnapshot()
|
|
249
|
+
if (!snap) return ''
|
|
250
|
+
var id = snap.current
|
|
251
|
+
if (id === undefined || id === null) return ''
|
|
252
|
+
var s = snap.byId && snap.byId[id]
|
|
253
|
+
return (s && typeof s.cwd === 'string') ? s.cwd : ''
|
|
254
|
+
} catch (e) { return '' }
|
|
255
|
+
}
|
|
256
|
+
var fontScale = 'lg'
|
|
257
|
+
var FONT_SCALES = { sm: '小', md: '标准', lg: '大', xl: '特大' }
|
|
258
|
+
var FONT_SCALE_VALUES = { sm: '0.9', md: '1', lg: '1.15', xl: '1.3' }
|
|
219
259
|
var localeListeners = new Set()
|
|
220
260
|
function t(key) { return (I18N[locale] && I18N[locale][key]) || I18N.zh[key] || key }
|
|
221
261
|
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,12 +267,19 @@ window.__ModuleLoader__.load({
|
|
|
227
267
|
list: '/api/dsh-auto-memory/list',
|
|
228
268
|
file: '/api/dsh-auto-memory/file',
|
|
229
269
|
recall: '/api/dsh-auto-memory/recall',
|
|
270
|
+
smartRecall: '/api/dsh-auto-memory/smart-recall',
|
|
271
|
+
workspaces: '/api/dsh-auto-memory/workspaces',
|
|
272
|
+
debug: '/api/dsh-auto-memory/debug',
|
|
273
|
+
browseDir: '/api/dsh-auto-memory/browse-dir',
|
|
274
|
+
pickDir: '/api/dsh-auto-memory/pick-dir',
|
|
230
275
|
config: '/api/dsh-auto-memory/config',
|
|
231
276
|
reflect: '/api/dsh-auto-memory/reflect',
|
|
232
277
|
reflectAuto: '/api/dsh-auto-memory/reflect-auto',
|
|
233
278
|
note: '/api/dsh-auto-memory/note',
|
|
234
279
|
external: '/api/dsh-auto-memory/external',
|
|
235
280
|
externalImport: '/api/dsh-auto-memory/external-import',
|
|
281
|
+
summarize: '/api/dsh-auto-memory/summarize',
|
|
282
|
+
greet: '/api/dsh-auto-memory/greet',
|
|
236
283
|
}
|
|
237
284
|
function query(params) {
|
|
238
285
|
var search = new URLSearchParams()
|
|
@@ -257,7 +304,7 @@ window.__ModuleLoader__.load({
|
|
|
257
304
|
// 视觉:液态玻璃(毛玻璃)—— backdrop-filter + DSH 主题令牌(--dsw-alias-*),
|
|
258
305
|
// 跟随亮/暗主题与页面背景自适应;位置/尺寸由 JS 几何状态驱动(可拖动、可缩放)。
|
|
259
306
|
var CSS = [
|
|
260
|
-
'[data-dam-panel] { position: fixed; left: 16px; width: 440px; height: 560px;',
|
|
307
|
+
'[data-dam-panel] { position: fixed; left: 16px; width: 440px; height: 560px; --dam-scale: 1;',
|
|
261
308
|
' max-width: calc(100vw - 32px); max-height: calc(100vh - 32px);',
|
|
262
309
|
' display: flex; flex-direction: column; overflow: hidden; z-index: 3000; pointer-events: auto;',
|
|
263
310
|
' border-radius: 16px; font: 13px/1.55 system-ui, "Segoe UI", sans-serif;',
|
|
@@ -270,36 +317,39 @@ window.__ModuleLoader__.load({
|
|
|
270
317
|
'@keyframes dam-in { from { opacity: 0; transform: scale(.92) translateY(10px); } to { opacity: 1; transform: none; } }',
|
|
271
318
|
'@keyframes dam-out { from { opacity: 1; transform: none; } to { opacity: 0; transform: scale(.95) translateY(6px); } }',
|
|
272
319
|
'[data-dam-panel][data-closing="true"] { animation: dam-out .16s ease-in both; }',
|
|
320
|
+
'[data-dam-panel][data-scale="sm"] { --dam-scale: .9; }',
|
|
321
|
+
'[data-dam-panel][data-scale="lg"] { --dam-scale: 1.15; }',
|
|
322
|
+
'[data-dam-panel][data-scale="xl"] { --dam-scale: 1.3; }',
|
|
273
323
|
'[data-dam-panel]::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 64%; pointer-events: none;',
|
|
274
324
|
' background: linear-gradient(180deg, rgba(255,255,255,.13), rgba(255,255,255,0) 70%); border-radius: 16px 16px 0 0; }',
|
|
275
325
|
'[data-dam-panel][data-dragging="true"] { user-select: none; }',
|
|
276
326
|
'[data-dam-panel] header { display: flex; align-items: center; gap: 8px; padding: 10px 14px; cursor: grab;',
|
|
277
327
|
' border-bottom: 1px solid color-mix(in srgb, var(--dsw-alias-border-l1, rgba(128,128,128,.25)) 55%, transparent); }',
|
|
278
328
|
'[data-dam-panel][data-dragging="true"] header { cursor: grabbing; }',
|
|
279
|
-
'[data-dam-panel] header strong { font-size: 14px; }',
|
|
329
|
+
'[data-dam-panel] header strong { font-size: calc(14px * var(--dam-scale)); }',
|
|
280
330
|
'[data-dam-panel] header .dam-spacer { flex: 1; }',
|
|
281
331
|
'[data-dam-resize] { position: absolute; right: 0; bottom: 0; width: 22px; height: 22px; cursor: nwse-resize;',
|
|
282
332
|
' opacity: .55; z-index: 2; border-radius: 0 0 16px 0;',
|
|
283
333
|
' background: linear-gradient(135deg, transparent 50%, color-mix(in srgb, var(--dsw-alias-label-secondary, #666) 45%, transparent) 50%); }',
|
|
284
334
|
'[data-dam-resize]:hover { opacity: 1; }',
|
|
285
|
-
'[data-dam-btn] { border: none; background: transparent; cursor: pointer; color: inherit; opacity: .75; font-size: 13px; padding: 4px 8px; border-radius: 6px; }',
|
|
335
|
+
'[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; }',
|
|
286
336
|
'[data-dam-btn]:hover { opacity: 1; background: color-mix(in srgb, var(--dsw-alias-label-secondary, #666) 16%, transparent); }',
|
|
287
337
|
'[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); }',
|
|
288
|
-
'[data-dam-tab] { border: none; background: transparent; cursor: pointer; color: inherit; opacity: .6; padding: 5px 10px; border-radius: 7px; font-size: 12.5px; }',
|
|
338
|
+
'[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)); }',
|
|
289
339
|
'[data-dam-tab][data-active="true"] { opacity: 1; background: color-mix(in srgb, var(--dsw-alias-label-secondary, #666) 18%, transparent); font-weight: 600; }',
|
|
290
340
|
'[data-dam-body] { flex: 1; overflow: auto; padding: 12px 14px; }',
|
|
291
|
-
'[data-dam-kv] { display: grid; grid-template-columns: auto 1fr; gap: 4px 12px; font-size: 12.5px; }',
|
|
341
|
+
'[data-dam-kv] { display: grid; grid-template-columns: auto 1fr; gap: 4px 12px; font-size: calc(12.5px * var(--dam-scale)); }',
|
|
292
342
|
'[data-dam-kv] b { opacity: .55; font-weight: 500; }',
|
|
293
|
-
'[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;',
|
|
343
|
+
'[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));',
|
|
294
344
|
' background: color-mix(in srgb, var(--dsw-alias-bg-layer-1, rgba(128,128,128,.06)) 40%, transparent); }',
|
|
295
345
|
'[data-dam-card] .dam-date { font-weight: 600; margin-bottom: 4px; }',
|
|
296
346
|
'[data-dam-card] .dam-content { white-space: pre-wrap; word-break: break-word; max-height: 220px; overflow: auto; }',
|
|
297
347
|
'[data-dam-banner] { border: 1px solid color-mix(in srgb, var(--dsw-alias-state-warn-primary, #e6a23c) 55%, transparent);',
|
|
298
|
-
' 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; }',
|
|
348
|
+
' 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)); }',
|
|
299
349
|
'[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; }',
|
|
300
350
|
'[data-dam-row] { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }',
|
|
301
|
-
'[data-dam-row] label { flex: 0 0 110px; opacity: .8; font-size: 12.5px; }',
|
|
302
|
-
'[data-dam-hint] { opacity: .5; font-size: 11.5px; margin-top: 2px; }',
|
|
351
|
+
'[data-dam-row] label { flex: 0 0 110px; opacity: .8; font-size: calc(12.5px * var(--dam-scale)); }',
|
|
352
|
+
'[data-dam-hint] { opacity: .5; font-size: calc(11.5px * var(--dam-scale)); margin-top: 2px; }',
|
|
303
353
|
'[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; }',
|
|
304
354
|
'[data-dam-sidebar-btn]:hover { background: color-mix(in srgb, var(--dsw-alias-label-secondary, #666) 14%, transparent); opacity: 1; }',
|
|
305
355
|
'[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); }',
|
|
@@ -313,7 +363,7 @@ window.__ModuleLoader__.load({
|
|
|
313
363
|
if (document.getElementById(STYLE_ID)) return
|
|
314
364
|
var tag = document.createElement('style')
|
|
315
365
|
tag.id = STYLE_ID
|
|
316
|
-
tag.dataset.plugin = '@
|
|
366
|
+
tag.dataset.plugin = '@deepseek-ai/dsh-auto-memory'
|
|
317
367
|
tag.textContent = CSS
|
|
318
368
|
document.head.appendChild(tag)
|
|
319
369
|
}
|
|
@@ -359,6 +409,9 @@ window.__ModuleLoader__.load({
|
|
|
359
409
|
var openPair = useState({})
|
|
360
410
|
var openMap = openPair[0]
|
|
361
411
|
var setOpenMap = openPair[1]
|
|
412
|
+
var subOpenPair = useState({})
|
|
413
|
+
var subOpenMap = subOpenPair[0]
|
|
414
|
+
var setSubOpenMap = subOpenPair[1]
|
|
362
415
|
// 智能时段判定
|
|
363
416
|
var hour = new Date().getHours()
|
|
364
417
|
var seg = hour < 9 ? 'morning' : hour < 12 ? 'forenoon' : hour < 14 ? 'noon' : hour < 18 ? 'afternoon' : 'evening'
|
|
@@ -368,7 +421,7 @@ window.__ModuleLoader__.load({
|
|
|
368
421
|
var curSegName = { morning: '早晨', forenoon: '上午', noon: '中午', afternoon: '下午', evening: '晚上' }[seg]
|
|
369
422
|
// 昨天抽屉(早晨显示)
|
|
370
423
|
if (seg === 'morning' && g.entries.length) {
|
|
371
|
-
drawers.push({ key: 'yesterday', label: t('yesterdayDrawer') + (g.yesterdayDate || ''), hint: '', items: g.entries, withTime: true, defaultOpen: true })
|
|
424
|
+
drawers.push({ key: 'yesterday', label: t('yesterdayDrawer') + (g.yesterdayDate || ''), hint: '', items: g.entries, withTime: true, defaultOpen: true, period: '昨天' })
|
|
372
425
|
}
|
|
373
426
|
// 今天各时段抽屉(已过的时段)
|
|
374
427
|
var seenSeg = { '早晨': seg !== 'morning', '上午': (seg === 'forenoon' || seg === 'noon' || seg === 'afternoon' || seg === 'evening'), '中午': (seg === 'noon' || seg === 'afternoon' || seg === 'evening'), '下午': (seg === 'afternoon' || seg === 'evening'), '晚上': seg === 'evening' }
|
|
@@ -378,7 +431,7 @@ window.__ModuleLoader__.load({
|
|
|
378
431
|
if (!seenSeg[sname]) continue
|
|
379
432
|
var items = (ps && ps.groups && ps.groups[sname]) || []
|
|
380
433
|
if (!items.length) continue
|
|
381
|
-
drawers.push({ key: 'seg-' + sname, label: t('segPrefix') + sname, hint: '', items: items.map(function (x) { return { time: '', text: x } }), withTime: false, defaultOpen: sname === curSegName })
|
|
434
|
+
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 })
|
|
382
435
|
}
|
|
383
436
|
// 外层:生活化问候
|
|
384
437
|
var totalCount = 0
|
|
@@ -399,24 +452,68 @@ window.__ModuleLoader__.load({
|
|
|
399
452
|
}
|
|
400
453
|
var rows = []
|
|
401
454
|
rows.push(h('div', { 'data-dam-content': '' }, greetLine))
|
|
402
|
-
// 抽屉列表
|
|
455
|
+
// 抽屉列表(AI 生活化总结缓存)
|
|
456
|
+
var sumCachePair = useState({})
|
|
457
|
+
var sumCache = sumCachePair[0]
|
|
458
|
+
var setSumCache = sumCachePair[1]
|
|
459
|
+
function requestSummary(key, period, force) {
|
|
460
|
+
if (!force && sumCache[key] !== undefined) return
|
|
461
|
+
apiPost(API.summarize, { period: period, force: !!force, ws: currentWs() }).then(function (d) {
|
|
462
|
+
if (d && (d.summary || (d.works && d.works.length))) {
|
|
463
|
+
var n = Object.assign({}, sumCache)
|
|
464
|
+
n[key] = { summary: d.summary || d.result || '', works: d.works || [], at: d.generatedAt || Date.now(), failed: false }
|
|
465
|
+
setSumCache(n)
|
|
466
|
+
}
|
|
467
|
+
}).catch(function () {
|
|
468
|
+
var n = Object.assign({}, sumCache)
|
|
469
|
+
n[key] = { summary: '', works: [], at: 0, failed: true }
|
|
470
|
+
setSumCache(n)
|
|
471
|
+
})
|
|
472
|
+
}
|
|
473
|
+
// 面板刷新键(nonce 变化):已缓存的展开抽屉 force 重新生成
|
|
474
|
+
useEffect(function () {
|
|
475
|
+
if (!props.nonce) return
|
|
476
|
+
for (var d = 0; d < drawers.length; d++) {
|
|
477
|
+
var dr = drawers[d]
|
|
478
|
+
var isOpen = openMap[dr.key] !== undefined ? openMap[dr.key] : dr.defaultOpen
|
|
479
|
+
if (isOpen && sumCache[dr.key] !== undefined) requestSummary(dr.key, dr.period, true)
|
|
480
|
+
}
|
|
481
|
+
}, [props.nonce])
|
|
403
482
|
for (var d = 0; d < drawers.length; d++) {
|
|
404
483
|
(function (dr) {
|
|
405
484
|
var isOpen = openMap[dr.key] !== undefined ? openMap[dr.key] : dr.defaultOpen
|
|
485
|
+
if (isOpen && sumCache[dr.key] === undefined) requestSummary(dr.key, dr.period, false)
|
|
486
|
+
var cached = sumCache[dr.key]
|
|
487
|
+
// 大抽屉标题:有 AI 总结时用总结内容(用户要求),否则用时段名
|
|
488
|
+
var bigTitle = cached && cached.summary ? cached.summary : dr.label
|
|
406
489
|
rows.push(h('div', { key: dr.key, style: { marginTop: '8px' } },
|
|
407
490
|
h('button', {
|
|
408
491
|
'data-dam-btn': '',
|
|
409
492
|
onClick: function () { var n = Object.assign({}, openMap); n[dr.key] = !isOpen; setOpenMap(n) },
|
|
410
|
-
style: { width: '100%',
|
|
493
|
+
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)' },
|
|
411
494
|
},
|
|
412
|
-
h('
|
|
413
|
-
h('
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
495
|
+
h('div', { style: { fontWeight: 600, fontSize: 'calc(12.5px * var(--dam-scale))', lineHeight: 1.5 } }, (isOpen ? '▼ ' : '▶ ') + bigTitle),
|
|
496
|
+
h('div', { 'data-dam-muted': '', style: { fontSize: 'calc(11px * var(--dam-scale))', marginTop: '2px' } },
|
|
497
|
+
dr.label + ' · ' + dr.items.length + t('logEntries') + (cached && cached.at ? ' · ' + t('generatedAt') + new Date(cached.at).toLocaleTimeString() : ''))),
|
|
498
|
+
isOpen ? h('div', { style: { padding: '4px 2px 2px 8px' } },
|
|
499
|
+
cached && cached.works && cached.works.length ? cached.works.map(function (w, wi) {
|
|
500
|
+
var sk = dr.key + ':w' + wi
|
|
501
|
+
var sOpen = subOpenMap[sk] !== undefined ? subOpenMap[sk] : false
|
|
502
|
+
return h('div', { key: sk, style: { marginTop: '5px' } },
|
|
503
|
+
h('button', {
|
|
504
|
+
'data-dam-btn': '',
|
|
505
|
+
onClick: function () { var n = Object.assign({}, subOpenMap); n[sk] = !sOpen; setSubOpenMap(n) },
|
|
506
|
+
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)' },
|
|
507
|
+
},
|
|
508
|
+
h('span', { style: { fontWeight: 600, fontSize: 'calc(12px * var(--dam-scale))' } }, (sOpen ? '▾ ' : '▸ ') + w.title),
|
|
509
|
+
h('span', { 'data-dam-muted': '', style: { fontSize: 'calc(11px * var(--dam-scale))', marginLeft: '6px' } }, w.points.length + t('pointsCount'))),
|
|
510
|
+
sOpen ? h('div', { style: { padding: '4px 4px 2px 14px' } },
|
|
511
|
+
w.points.map(function (pt, pi) {
|
|
512
|
+
return h('div', { key: pi, style: { fontSize: 'calc(12px * var(--dam-scale))', lineHeight: 1.5, marginBottom: '2px' } }, '· ' + pt)
|
|
513
|
+
})) : null)
|
|
514
|
+
}) : cached && cached.failed ? h('div', { 'data-dam-hint': '', style: { padding: '4px 6px' } }, t('summaryFailed'))
|
|
515
|
+
: cached && cached.summary ? h('div', { 'data-dam-hint': '', style: { padding: '4px 6px' } }, cached.summary)
|
|
516
|
+
: h('div', { 'data-dam-hint': '', style: { padding: '4px 6px' } }, t('summarizing'))) : null))
|
|
420
517
|
})(drawers[d])
|
|
421
518
|
}
|
|
422
519
|
// 待反思提醒
|
|
@@ -426,7 +523,7 @@ window.__ModuleLoader__.load({
|
|
|
426
523
|
return h(Card, { title: (g.period || '') + ' · ' + segLabel }, rows)
|
|
427
524
|
}
|
|
428
525
|
|
|
429
|
-
function OverviewTab() {
|
|
526
|
+
function OverviewTab(props) {
|
|
430
527
|
var statePair = useState(null)
|
|
431
528
|
var state = statePair[0]
|
|
432
529
|
var setState = statePair[1]
|
|
@@ -439,10 +536,35 @@ window.__ModuleLoader__.load({
|
|
|
439
536
|
var actMsgPair = useState('')
|
|
440
537
|
var actMsg = actMsgPair[0]
|
|
441
538
|
var setActMsg = actMsgPair[1]
|
|
539
|
+
var wsPair = useState(null)
|
|
540
|
+
var wsData = wsPair[0]
|
|
541
|
+
var setWsData = wsPair[1]
|
|
542
|
+
// 每次进入面板 / 点刷新(nonce 变化)/ 面板打开期间每 30s 自动重拉,保证自动沉淀等数据新鲜
|
|
442
543
|
useEffect(function () {
|
|
443
544
|
var alive = true
|
|
444
|
-
|
|
545
|
+
// 跨工作区总结(概览页集成:所有工作区的小总结+细分;读缓存)
|
|
546
|
+
apiPost(API.workspaces, { force: false }).then(function (d) { if (d && alive) setWsData(d) }).catch(function () {})
|
|
547
|
+
apiGet(API.state, { ws: currentWs() }).then(function (s) {
|
|
548
|
+
if (alive) setState(s)
|
|
549
|
+
// 无 AI 问候 → 自动生成一次(host 按时段缓存,不会重复生成)
|
|
550
|
+
if (s && s.greeting && !s.greeting.greeting) {
|
|
551
|
+
apiPost(API.greet, { ws: currentWs() }).then(function (d) {
|
|
552
|
+
if (d && d.greeting && alive) {
|
|
553
|
+
setState(function (prev) {
|
|
554
|
+
var g0 = (prev && prev.greeting) || {}
|
|
555
|
+
return Object.assign({}, prev, { greeting: Object.assign({}, g0, { greeting: d.greeting, hasGreeting: true }) })
|
|
556
|
+
})
|
|
557
|
+
}
|
|
558
|
+
}).catch(function () {})
|
|
559
|
+
}
|
|
560
|
+
}).catch(function () {})
|
|
445
561
|
return function () { alive = false }
|
|
562
|
+
}, [props && props.nonce])
|
|
563
|
+
useEffect(function () {
|
|
564
|
+
var timer = setInterval(function () {
|
|
565
|
+
apiGet(API.state, { ws: currentWs() }).then(function (s) { setState(s) }).catch(function () {})
|
|
566
|
+
}, 30000)
|
|
567
|
+
return function () { clearInterval(timer) }
|
|
446
568
|
}, [])
|
|
447
569
|
useEffect(function () {
|
|
448
570
|
// 记录本次活动时间;下次打开若相隔>1小时,GreetingCard 显示"欢迎回来"
|
|
@@ -454,12 +576,25 @@ window.__ModuleLoader__.load({
|
|
|
454
576
|
setReflectBusy(true); setActMsg('')
|
|
455
577
|
apiPost(API.reflectAuto, {}).then(function (d) {
|
|
456
578
|
setActMsg(d.result || t('generated')); setReflectBusy(false)
|
|
457
|
-
apiGet(API.state).then(function (s) { if (s) setState(s) }).catch(function () {})
|
|
579
|
+
apiGet(API.state, { ws: currentWs() }).then(function (s) { if (s) setState(s) }).catch(function () {})
|
|
458
580
|
}).catch(function (e) { setActMsg(t('failed') + e.message); setReflectBusy(false) })
|
|
459
581
|
}
|
|
460
582
|
return h('div', null,
|
|
461
583
|
// 今日问候卡:问候语 + 昨天时间轴 + 提醒(纯 GUI 渲染,不干扰对话流)
|
|
462
|
-
h(GreetingCard, { greeting: state.greeting, periodSummary: state.periodSummary, t: t }),
|
|
584
|
+
h(GreetingCard, { greeting: state.greeting, periodSummary: state.periodSummary, t: t, nonce: props && props.nonce }),
|
|
585
|
+
// 跨工作区总结(所有工作区的小总结 + 区内细分)
|
|
586
|
+
h('div', { style: { marginTop: '10px' } },
|
|
587
|
+
h('div', { style: { fontWeight: 700, fontSize: 'calc(12.5px * var(--dam-scale))', opacity: 0.75, marginBottom: '6px' } }, t('wsOverview')),
|
|
588
|
+
wsData && wsData.workspaces && wsData.workspaces.length
|
|
589
|
+
? wsData.workspaces.map(function (ws) {
|
|
590
|
+
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)' } },
|
|
591
|
+
h('div', { style: { fontWeight: 600, fontSize: 'calc(12px * var(--dam-scale))' } }, ws.name + (ws.dateRange ? ' · ' + ws.dateRange : '')),
|
|
592
|
+
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')),
|
|
593
|
+
(ws.items && ws.items.length) ? ws.items.map(function (it, i) {
|
|
594
|
+
return h('div', { key: i, style: { fontSize: 'calc(11.5px * var(--dam-scale))', marginTop: '2px', opacity: 0.75 } }, '· ' + it)
|
|
595
|
+
}) : null)
|
|
596
|
+
})
|
|
597
|
+
: h('div', { 'data-dam-hint': '' }, t('wsGenerating'))),
|
|
463
598
|
state.pendingReflection
|
|
464
599
|
? h(Banner, null, t('pendingReflection') + state.pendingReflection + t('pendingReflectionHint'))
|
|
465
600
|
: null,
|
|
@@ -468,6 +603,12 @@ window.__ModuleLoader__.load({
|
|
|
468
603
|
h('b', null, t('todayWork')), h('span', null, state.todayEntries + t('logEntries')),
|
|
469
604
|
h('b', null, t('dailyReflection')), h('span', null, state.latestReflectionDate || t('notYet')),
|
|
470
605
|
h('b', null, t('workspace')), h('span', null, state.ws)),
|
|
606
|
+
// 自动沉淀即时反馈(本轮/今日沉淀了多少条、最近一次时间)
|
|
607
|
+
state.autoStats && state.autoStats.count > 0
|
|
608
|
+
? h('div', { 'data-dam-hint': '', style: { marginTop: '2px' } },
|
|
609
|
+
t('autoSettledToday') + state.autoStats.count + t('autoSettledSuffix') +
|
|
610
|
+
(state.autoStats.lastAt ? ' (' + t('autoSettledRecent') + new Date(state.autoStats.lastAt).toLocaleTimeString() + ')' : ''))
|
|
611
|
+
: h('div', { 'data-dam-hint': '', style: { marginTop: '2px' } }, t('autoSettledNone')),
|
|
471
612
|
// 快捷操作
|
|
472
613
|
h('div', { 'data-dam-row': '' },
|
|
473
614
|
h('button', { 'data-dam-btn': '', onClick: oneClickReflect, disabled: reflectBusy }, reflectBusy ? t('reflecting') : t('oneClickReflect')),
|
|
@@ -627,22 +768,69 @@ window.__ModuleLoader__.load({
|
|
|
627
768
|
var resultPair = useState(null)
|
|
628
769
|
var result = resultPair[0]
|
|
629
770
|
var setResult = resultPair[1]
|
|
771
|
+
var smartPair = useState(null)
|
|
772
|
+
var smart = smartPair[0]
|
|
773
|
+
var setSmart = smartPair[1]
|
|
630
774
|
var busyPair = useState(false)
|
|
631
775
|
var busy = busyPair[0]
|
|
632
776
|
var setBusy = busyPair[1]
|
|
633
777
|
function search() {
|
|
634
778
|
if (!q.trim() || busy) return
|
|
635
|
-
setBusy(true); setResult(null)
|
|
779
|
+
setBusy(true); setResult(null); setSmart(null)
|
|
636
780
|
apiPost(API.recall, { query: q.trim() }).then(function (d) { setResult(d.result); setBusy(false) })
|
|
637
781
|
.catch(function (e) { setResult(t('searchFailed') + e.message); setBusy(false) })
|
|
638
782
|
}
|
|
783
|
+
function smartSearch() {
|
|
784
|
+
if (!q.trim() || busy) return
|
|
785
|
+
setBusy(true); setResult(null); setSmart(null)
|
|
786
|
+
apiPost(API.smartRecall, { query: q.trim() }).then(function (d) { setSmart(d); setBusy(false) })
|
|
787
|
+
.catch(function (e) { setSmart({ answer: t('searchFailed') + e.message, keywords: [], hits: [] }); setBusy(false) })
|
|
788
|
+
}
|
|
639
789
|
return h('div', null,
|
|
640
790
|
h('div', { 'data-dam-row': '' },
|
|
641
791
|
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() } }),
|
|
642
|
-
h('button', { 'data-dam-btn': '', onClick: search, disabled: busy }, t('searchBtn'))
|
|
792
|
+
h('button', { 'data-dam-btn': '', onClick: search, disabled: busy }, t('searchBtn')),
|
|
793
|
+
h('button', { 'data-dam-btn': '', onClick: smartSearch, disabled: busy }, t('smartSearch'))),
|
|
794
|
+
smart ? h(Card, { title: t('smartAnswer') },
|
|
795
|
+
h('div', { 'data-dam-content': '' }, smart.answer || t('empty')),
|
|
796
|
+
smart.keywords && smart.keywords.length ? h('div', { 'data-dam-hint': '', style: { marginTop: '6px' } }, t('keywordsLabel') + smart.keywords.join(' / ')) : null,
|
|
797
|
+
smart.hits && smart.hits.length ? h('div', { 'data-dam-hint': '', style: { marginTop: '6px' } },
|
|
798
|
+
smart.hits.map(function (h, i) { return h('div', { key: i, style: { marginTop: '3px' } }, '· [' + h.where + '] ' + h.line) })) : null)
|
|
799
|
+
: null,
|
|
643
800
|
result ? h(Card, { title: t('resultTitle') }, h('div', { 'data-dam-content': '' }, result)) : null)
|
|
644
801
|
}
|
|
645
802
|
|
|
803
|
+
// ───────────────────────── 工作区总览页签(跨工作区全局总结) ─────────────────────────
|
|
804
|
+
function WorkspaceTab() {
|
|
805
|
+
var dataPair = useState(null)
|
|
806
|
+
var data = dataPair[0]
|
|
807
|
+
var setData = dataPair[1]
|
|
808
|
+
var busyPair = useState(false)
|
|
809
|
+
var busy = busyPair[0]
|
|
810
|
+
var setBusy = busyPair[1]
|
|
811
|
+
function load(force) {
|
|
812
|
+
if (busy) return
|
|
813
|
+
setBusy(true)
|
|
814
|
+
apiPost(API.workspaces, { force: !!force }).then(function (d) { if (d) setData(d); setBusy(false) })
|
|
815
|
+
.catch(function () { setBusy(false) })
|
|
816
|
+
}
|
|
817
|
+
useEffect(function () { load(false) }, [])
|
|
818
|
+
if (!data) return h('div', null, busy ? h('div', { 'data-dam-hint': '' }, t('wsGenerating')) : h(Loading))
|
|
819
|
+
return h('div', null,
|
|
820
|
+
h('div', { 'data-dam-row': '' },
|
|
821
|
+
h('button', { 'data-dam-btn': '', onClick: function () { load(true) }, disabled: busy }, busy ? t('refreshing') : t('refresh')),
|
|
822
|
+
h('span', { 'data-dam-hint': '' }, data.cached ? (t('generatedAt') + new Date(data.generatedAt).toLocaleTimeString()) : '')),
|
|
823
|
+
(data.workspaces && data.workspaces.length) ? data.workspaces.map(function (ws) {
|
|
824
|
+
return h(Card, { key: ws.path, title: ws.name + (ws.dateRange ? ' · ' + ws.dateRange : '') },
|
|
825
|
+
ws.summary ? h('div', { 'data-dam-content': '' }, ws.summary) : h('div', { 'data-dam-hint': '' }, t('wsNoSummary')),
|
|
826
|
+
(ws.items && ws.items.length) ? h('div', { style: { marginTop: '6px' } },
|
|
827
|
+
ws.items.map(function (it, i) {
|
|
828
|
+
return h('div', { key: i, style: { fontSize: 'calc(12px * var(--dam-scale))', marginTop: '3px', lineHeight: 1.5 } }, '· ' + it)
|
|
829
|
+
})) : null,
|
|
830
|
+
h('div', { 'data-dam-hint': '', style: { marginTop: '4px' } }, ws.path + ' · ' + (ws.logCount || 0) + t('logEntries')))
|
|
831
|
+
}) : h('div', { 'data-dam-hint': '' }, t('wsNone')))
|
|
832
|
+
}
|
|
833
|
+
|
|
646
834
|
// ───────────────────────── 日历页签 ─────────────────────────
|
|
647
835
|
var QUADRANT_STYLE = {
|
|
648
836
|
'重要紧急': { color: 'var(--dsw-alias-state-error-primary, #d64545)', label: t('qUrgentImportant') },
|
|
@@ -702,12 +890,12 @@ window.__ModuleLoader__.load({
|
|
|
702
890
|
// 图例
|
|
703
891
|
rows.push(h('div', { 'data-dam-row': '', style: { flexWrap: 'wrap' } },
|
|
704
892
|
Object.keys(QUADRANT_STYLE).map(function (q) {
|
|
705
|
-
return h('span', { key: q, style: { fontSize: '11px', opacity: 0.8, marginRight: '10px' } },
|
|
893
|
+
return h('span', { key: q, style: { fontSize: 'calc(11px * var(--dam-scale))', opacity: 0.8, marginRight: '10px' } },
|
|
706
894
|
h('span', { style: { display: 'inline-block', width: 8, height: 8, borderRadius: 2, background: QUADRANT_STYLE[q].color, marginRight: 4 } }), QUADRANT_STYLE[q].label)
|
|
707
895
|
})))
|
|
708
896
|
// 星期表头
|
|
709
897
|
rows.push(h('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: '3px', marginBottom: '4px' } },
|
|
710
|
-
dowLabels.map(function (dl) { return h('div', { key: dl, style: { textAlign: 'center', fontSize: '11px', opacity: 0.55 } }, dl) })))
|
|
898
|
+
dowLabels.map(function (dl) { return h('div', { key: dl, style: { textAlign: 'center', fontSize: 'calc(11px * var(--dam-scale))', opacity: 0.55 } }, dl) })))
|
|
711
899
|
// 日历格子
|
|
712
900
|
var gridRows = []
|
|
713
901
|
for (var ci = 0; ci < cells.length; ci += 7) {
|
|
@@ -728,7 +916,7 @@ window.__ModuleLoader__.load({
|
|
|
728
916
|
overflow: 'hidden',
|
|
729
917
|
},
|
|
730
918
|
},
|
|
731
|
-
h('div', { style: { fontSize: '11.5px', fontWeight: isToday ? 700 : 500, opacity: isToday ? 1 : 0.7, marginBottom: '3px' } }, dayNum),
|
|
919
|
+
h('div', { style: { fontSize: 'calc(11.5px * var(--dam-scale))', fontWeight: isToday ? 700 : 500, opacity: isToday ? 1 : 0.7, marginBottom: '3px' } }, dayNum),
|
|
732
920
|
es.slice(0, 3).map(function (en) {
|
|
733
921
|
var qs = QUADRANT_STYLE[en.quadrant] || QUADRANT_STYLE['未分类']
|
|
734
922
|
return h('div', {
|
|
@@ -736,14 +924,14 @@ window.__ModuleLoader__.load({
|
|
|
736
924
|
title: en.time + ' ' + en.title,
|
|
737
925
|
onClick: function (ev) { ev.stopPropagation(); toggleDone(en) },
|
|
738
926
|
style: {
|
|
739
|
-
fontSize: '10.5px', lineHeight: 1.35, padding: '1px 4px', borderRadius: 4, marginBottom: 2,
|
|
927
|
+
fontSize: 'calc(10.5px * var(--dam-scale))', lineHeight: 1.35, padding: '1px 4px', borderRadius: 4, marginBottom: 2,
|
|
740
928
|
background: 'color-mix(in srgb, ' + qs.color + ' 18%, transparent)',
|
|
741
929
|
color: qs.color, textDecoration: en.done ? 'line-through' : 'none',
|
|
742
930
|
opacity: en.done ? 0.5 : 1, cursor: 'pointer', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
|
|
743
931
|
},
|
|
744
932
|
}, (en.time && en.time !== '--:--' ? en.time + ' ' : '') + en.title)
|
|
745
933
|
}),
|
|
746
|
-
es.length > 3 ? h('div', { style: { fontSize: '10px', opacity: 0.5 } }, '+' + (es.length - 3)) : null))
|
|
934
|
+
es.length > 3 ? h('div', { style: { fontSize: 'calc(10px * var(--dam-scale))', opacity: 0.5 } }, '+' + (es.length - 3)) : null))
|
|
747
935
|
})(cells[ci + cj])
|
|
748
936
|
}
|
|
749
937
|
gridRows.push(h('div', { key: 'w' + ci, style: { display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: '3px' } }, week))
|
|
@@ -883,23 +1071,29 @@ window.__ModuleLoader__.load({
|
|
|
883
1071
|
var tabPair = useState('overview')
|
|
884
1072
|
var tab = tabPair[0]
|
|
885
1073
|
var setTab = tabPair[1]
|
|
1074
|
+
// 刷新 nonce:每次打开面板 / 点 ⟳ 时递增,驱动各页签重拉数据
|
|
1075
|
+
var noncePair = useState(0)
|
|
1076
|
+
var nonce = noncePair[0]
|
|
1077
|
+
var setNonce = noncePair[1]
|
|
886
1078
|
var g = controller.geom()
|
|
887
1079
|
useEffect(function () { return controller.subscribe(tick[1]) }, [])
|
|
888
1080
|
if (!panelOpen && !panelClosing) return null
|
|
889
1081
|
var body
|
|
890
|
-
if (tab === 'overview') body = h(OverviewTab)
|
|
1082
|
+
if (tab === 'overview') body = h(OverviewTab, { nonce: nonce })
|
|
891
1083
|
else if (tab === 'logs') body = h(LogsTab)
|
|
892
1084
|
else if (tab === 'notes') body = h(NotesTab)
|
|
893
1085
|
else if (tab === 'reflections') body = h(ReflectionsTab)
|
|
894
1086
|
else if (tab === 'connect') body = h(ConnectTab)
|
|
895
1087
|
else if (tab === 'calendar') body = h(CalendarTab)
|
|
1088
|
+
else if (tab === 'workspaces') body = h(WorkspaceTab)
|
|
896
1089
|
else body = h(SearchTab)
|
|
897
|
-
var tabs = [['overview', t('overview')], ['logs', t('logs')], ['notes', t('notes')], ['reflections', t('reflections')], ['connect', t('connect')], ['calendar', t('calendar')], ['search', t('search')]]
|
|
1090
|
+
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')]]
|
|
898
1091
|
var style = {
|
|
899
1092
|
left: g.left + 'px',
|
|
900
1093
|
top: g.top + 'px',
|
|
901
1094
|
width: g.width + 'px',
|
|
902
1095
|
height: g.height + 'px',
|
|
1096
|
+
'--dam-scale': FONT_SCALE_VALUES[fontScale] || '1',
|
|
903
1097
|
}
|
|
904
1098
|
var dragMove = startPointerDrag(function (dx, dy) {
|
|
905
1099
|
controller.setGeom({ left: g.left + dx, top: g.top + dy })
|
|
@@ -909,6 +1103,7 @@ window.__ModuleLoader__.load({
|
|
|
909
1103
|
})
|
|
910
1104
|
return h('div', {
|
|
911
1105
|
'data-dam-panel': '',
|
|
1106
|
+
'data-scale': fontScale in FONT_SCALES ? fontScale : 'md',
|
|
912
1107
|
style: style,
|
|
913
1108
|
'data-closing': panelClosing ? 'true' : undefined,
|
|
914
1109
|
'data-dragging': dragActive ? 'true' : undefined,
|
|
@@ -920,7 +1115,7 @@ window.__ModuleLoader__.load({
|
|
|
920
1115
|
h('strong', null, t('autoMemory')),
|
|
921
1116
|
h('span', { className: 'dam-spacer' }),
|
|
922
1117
|
h('button', { 'data-dam-btn': '', title: t('resetPos'), onClick: function () { controller.resetGeom() } }, '⤾'),
|
|
923
|
-
h('button', { 'data-dam-btn': '', title: t('refresh'), onClick: function () {
|
|
1118
|
+
h('button', { 'data-dam-btn': '', title: t('refresh'), onClick: function () { setNonce(nonce + 1) } }, '⟳'),
|
|
924
1119
|
h('button', { 'data-dam-btn': '', title: t('close'), onClick: function () { controller.close() } }, '✕')),
|
|
925
1120
|
h('div', { 'data-dam-tabs': '' }, tabs.map(function (t) {
|
|
926
1121
|
return h('button', { key: t[0], 'data-dam-tab': '', 'data-active': tab === t[0] ? 'true' : undefined, onClick: function () { setTab(t[0]) } }, t[1])
|
|
@@ -929,10 +1124,70 @@ window.__ModuleLoader__.load({
|
|
|
929
1124
|
h('div', { 'data-dam-resize': '', title: t('dragResize'), onPointerDown: resizeMove }))
|
|
930
1125
|
}
|
|
931
1126
|
|
|
1127
|
+
// ───────────────────────── 调试中心(为提 issue 提供诊断) ─────────────────────────
|
|
1128
|
+
function DebugCenter() {
|
|
1129
|
+
var dataPair = useState(null)
|
|
1130
|
+
var data = dataPair[0]
|
|
1131
|
+
var setData = dataPair[1]
|
|
1132
|
+
var probesPair = useState(null)
|
|
1133
|
+
var probes = probesPair[0]
|
|
1134
|
+
var setProbes = probesPair[1]
|
|
1135
|
+
var busyPair = useState(false)
|
|
1136
|
+
var busy = busyPair[0]
|
|
1137
|
+
var setBusy = busyPair[1]
|
|
1138
|
+
function refresh() {
|
|
1139
|
+
if (busy) return
|
|
1140
|
+
setBusy(true)
|
|
1141
|
+
var probesDone = {}
|
|
1142
|
+
var probeList = [
|
|
1143
|
+
['state', API.state, 'GET'], ['config', API.config, 'GET'], ['list', API.list, 'GET'],
|
|
1144
|
+
['file', API.file, 'GET'], ['calendar', API.calendar, 'GET'], ['debug', API.debug, 'GET'],
|
|
1145
|
+
['recall', API.recall, 'POST'], ['summarize', API.summarize, 'POST'], ['greet', API.greet, 'POST'],
|
|
1146
|
+
['workspaces', API.workspaces, 'POST'], ['reflectAuto', API.reflectAuto, 'POST'],
|
|
1147
|
+
]
|
|
1148
|
+
Promise.all(probeList.map(function (pr) {
|
|
1149
|
+
var t0 = Date.now()
|
|
1150
|
+
return fetch(pr[1], pr[2] === 'POST' ? { method: 'POST', headers: { 'content-type': 'application/json' }, body: '{}' } : undefined)
|
|
1151
|
+
.then(function (r) { probesDone[pr[0]] = { status: r.status, ms: Date.now() - t0 } })
|
|
1152
|
+
.catch(function (e) { probesDone[pr[0]] = { error: e.message } })
|
|
1153
|
+
})).then(function () {
|
|
1154
|
+
setProbes(probesDone)
|
|
1155
|
+
return apiGet(API.debug)
|
|
1156
|
+
}).then(function (d) { setData(d); setBusy(false) }).catch(function () { setBusy(false) })
|
|
1157
|
+
}
|
|
1158
|
+
useEffect(function () { refresh() }, [])
|
|
1159
|
+
if (!data) return h('div', { 'data-dam-hint': '' }, t('dbgLoading'))
|
|
1160
|
+
function kv(label, value, warn) {
|
|
1161
|
+
return h('div', { 'data-dam-row': '', style: { marginBottom: '3px' } },
|
|
1162
|
+
h('span', { style: { flex: '0 0 140px', opacity: .7, fontSize: 'calc(11.5px * var(--dam-scale))' } }, label),
|
|
1163
|
+
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)))
|
|
1164
|
+
}
|
|
1165
|
+
var hb = data.heartbeat || {}
|
|
1166
|
+
var hbAge = hb.exists && hb.heartbeatAt ? Math.round((Date.now() - hb.heartbeatAt) / 1000) : -1
|
|
1167
|
+
var apiBad = probes && Object.keys(probes).some(function (k) { return probes[k].status === 404 || probes[k].error })
|
|
1168
|
+
return h('div', null,
|
|
1169
|
+
h('div', { 'data-dam-row': '' },
|
|
1170
|
+
h('button', { 'data-dam-btn': '', onClick: refresh, disabled: busy }, busy ? t('dbgRefreshing') : t('dbgRefresh')),
|
|
1171
|
+
h('span', { 'data-dam-hint': '' }, data.host.indexPath || '')),
|
|
1172
|
+
kv('插件版本', data.host.version || '(读不到)', false),
|
|
1173
|
+
kv('PID / 启动', data.host.pid + ' / ' + (data.host.startTime ? new Date(data.host.startTime).toLocaleTimeString() : ''), false),
|
|
1174
|
+
kv('Host 需重启?', data.host.needsRestart ? '是(代码比进程新)' : '否', data.host.needsRestart),
|
|
1175
|
+
kv('轮询心跳', hb.exists ? (hbAge >= 0 ? '存活(上次 ' + hbAge + ' 秒前)' : '存活') : '无心跳文件', !hb.exists || hbAge > 360),
|
|
1176
|
+
kv('沉淀重试队列', data.autoConsolidate.pendingQueue + ' 条', data.autoConsolidate.pendingQueue > 0),
|
|
1177
|
+
kv('今日沉淀', data.autoConsolidate.stats.count + ' 条 / 最近 ' + (data.autoConsolidate.stats.lastAt ? new Date(data.autoConsolidate.stats.lastAt).toLocaleTimeString() : '无'), false),
|
|
1178
|
+
kv('正在沉淀中', data.autoConsolidate.consolidating ? '是' : '否', data.autoConsolidate.consolidating),
|
|
1179
|
+
kv('subagents', data.subagents.available ? (data.subagents.providers.join(', ') || '可用') : '不可用', !data.subagents.available),
|
|
1180
|
+
kv('项目笔记重复标题', data.duplicateHeadings + ' 个', data.duplicateHeadings > 0),
|
|
1181
|
+
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),
|
|
1182
|
+
kv('当前工作区', currentWs() || '(未取到)', false),
|
|
1183
|
+
kv('API 连通', probes ? Object.keys(probes).map(function (k) { return k + '=' + (probes[k].status !== undefined ? probes[k].status : probes[k].error) }).join(' ') : '…', apiBad))
|
|
1184
|
+
}
|
|
1185
|
+
|
|
932
1186
|
// ───────────────────────── 设置页 ─────────────────────────
|
|
933
1187
|
var STYLE_OPTIONS = [['auto', t('styleAuto')], ['life', t('styleLife')], ['professional', t('styleProfessional')]]
|
|
934
1188
|
var LOCALE_OPTIONS = [['zh', t('zh')], ['en', t('en')]]
|
|
935
1189
|
function SettingsPage() {
|
|
1190
|
+
var tickPair = useTick()
|
|
936
1191
|
var cfgPair = useState(null)
|
|
937
1192
|
var cfg = cfgPair[0]
|
|
938
1193
|
var setCfg = cfgPair[1]
|
|
@@ -945,6 +1200,47 @@ window.__ModuleLoader__.load({
|
|
|
945
1200
|
var errPair = useState('')
|
|
946
1201
|
var err = errPair[0]
|
|
947
1202
|
var setErr = errPair[1]
|
|
1203
|
+
var dbgOpenPair = useState(false)
|
|
1204
|
+
var dbgOpen = dbgOpenPair[0]
|
|
1205
|
+
var setDbgOpen = dbgOpenPair[1]
|
|
1206
|
+
var browseOpenPair = useState(false)
|
|
1207
|
+
var browseOpen = browseOpenPair[0]
|
|
1208
|
+
var setBrowseOpen = browseOpenPair[1]
|
|
1209
|
+
var browsePathPair = useState('')
|
|
1210
|
+
var browsePath = browsePathPair[0]
|
|
1211
|
+
var setBrowsePath = browsePathPair[1]
|
|
1212
|
+
var browseParentPair = useState('')
|
|
1213
|
+
var browseParent = browseParentPair[0]
|
|
1214
|
+
var setBrowseParent = browseParentPair[1]
|
|
1215
|
+
var browseDirsPair = useState(null)
|
|
1216
|
+
var browseDirs = browseDirsPair[0]
|
|
1217
|
+
var setBrowseDirs = browseDirsPair[1]
|
|
1218
|
+
function browseTo(p) {
|
|
1219
|
+
setBrowsePath(p)
|
|
1220
|
+
apiPost(API.browseDir, { path: p }).then(function (d) {
|
|
1221
|
+
if (d) { setBrowsePath(d.path); setBrowseParent(d.parent); setBrowseDirs(d.dirs || []) }
|
|
1222
|
+
}).catch(function () { setBrowseDirs([]) })
|
|
1223
|
+
}
|
|
1224
|
+
function openBrowser() {
|
|
1225
|
+
// 优先弹系统原生文件夹选择器(native 后端);不可用(远程/无显示)回退内嵌浏览
|
|
1226
|
+
apiPost(API.pickDir, {}).then(function (d) {
|
|
1227
|
+
if (d && d.native && d.dir) {
|
|
1228
|
+
set('memoryRoot', d.dir)
|
|
1229
|
+
setMsg(t('pickedDir') + ' ' + d.dir + ' ' + t('rememberSave'))
|
|
1230
|
+
} else if (d && d.native) {
|
|
1231
|
+
// 用户在系统对话框点了取消:保持原值,不动作
|
|
1232
|
+
} else {
|
|
1233
|
+
setMsg(t('pickerUnavailable'))
|
|
1234
|
+
setBrowseOpen(true)
|
|
1235
|
+
browseTo(cfg.memoryRoot || '')
|
|
1236
|
+
}
|
|
1237
|
+
}).catch(function () {
|
|
1238
|
+
setMsg(t('pickerUnavailable'))
|
|
1239
|
+
setBrowseOpen(true)
|
|
1240
|
+
browseTo(cfg.memoryRoot || '')
|
|
1241
|
+
})
|
|
1242
|
+
}
|
|
1243
|
+
useEffect(function () { return controller.subscribe(tickPair[1]) }, [])
|
|
948
1244
|
useEffect(function () {
|
|
949
1245
|
var alive = true
|
|
950
1246
|
apiGet(API.config).then(function (d) { if (alive) setCfg(d.config) }).catch(function (e) { setErr(e.message) })
|
|
@@ -955,7 +1251,7 @@ window.__ModuleLoader__.load({
|
|
|
955
1251
|
function save() {
|
|
956
1252
|
if (busy) return
|
|
957
1253
|
setBusy(true); setMsg(''); setErr('')
|
|
958
|
-
apiPost(API.config, cfg).then(function (d) { setCfg(d.config); setMsg(t('saved')); setBusy(false) })
|
|
1254
|
+
apiPost(API.config, cfg).then(function (d) { setCfg(d.config); setMsg(t('saved') + (d.migrated ? ' ' + d.migrated : '')); setBusy(false) })
|
|
959
1255
|
.catch(function (e) { setErr(e.message); setBusy(false) })
|
|
960
1256
|
}
|
|
961
1257
|
function field(label, control, hint) {
|
|
@@ -967,17 +1263,39 @@ window.__ModuleLoader__.load({
|
|
|
967
1263
|
h('div', { 'data-dam-hint': '' }, t('settingsHeader')),
|
|
968
1264
|
field(t('fLocale'), h('select', { 'data-dam-select': '', value: cfg.locale || 'zh', onChange: function (e) { set('locale', e.target.value); setLocale(e.target.value) } },
|
|
969
1265
|
LOCALE_OPTIONS.map(function (o) { return h('option', { key: o[0], value: o[0] }, o[1]) })), t('fLocaleHint')),
|
|
1266
|
+
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() } },
|
|
1267
|
+
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')),
|
|
970
1268
|
field(t('fUserDir'), h('input', { 'data-dam-input': '', value: cfg.userMemoryDir, onChange: function (e) { set('userMemoryDir', e.target.value) } }), t('fUserDirHint')),
|
|
971
1269
|
field(t('fProjectDir'), h('input', { 'data-dam-input': '', value: cfg.projectMemoryDir, onChange: function (e) { set('projectMemoryDir', e.target.value) } }), t('fProjectDirHint')),
|
|
1270
|
+
field(t('fMemoryRoot'), h('div', { 'data-dam-row': '', style: { flex: 1 } },
|
|
1271
|
+
h('input', { 'data-dam-input': '', style: { flex: 1 }, value: cfg.memoryRoot || '', onChange: function (e) { set('memoryRoot', e.target.value) } }),
|
|
1272
|
+
h('button', { 'data-dam-btn': '', onClick: function () { openBrowser() } }, t('fBrowse'))), t('fMemoryRootHint')),
|
|
1273
|
+
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)' } },
|
|
1274
|
+
h('div', { 'data-dam-row': '' },
|
|
1275
|
+
h('b', { style: { fontSize: 'calc(12px * var(--dam-scale))', wordBreak: 'break-all', flex: 1 } }, browsePath || '…'),
|
|
1276
|
+
h('button', { 'data-dam-btn': '', onClick: function () { browseTo(browseParent) }, disabled: browseParent === browsePath }, t('fUp'))),
|
|
1277
|
+
h('div', { style: { maxHeight: '160px', overflow: 'auto', marginTop: '4px' } },
|
|
1278
|
+
(browseDirs || []).map(function (d) {
|
|
1279
|
+
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)
|
|
1280
|
+
}).concat(browseDirs && !browseDirs.length ? [h('div', { key: 'e', 'data-dam-hint': '' }, t('empty'))] : [])),
|
|
1281
|
+
h('div', { 'data-dam-row': '', style: { marginTop: '6px' } },
|
|
1282
|
+
h('button', { 'data-dam-btn': '', onClick: function () { set('memoryRoot', browsePath); setBrowseOpen(false) } }, t('fSelectDir')),
|
|
1283
|
+
h('button', { 'data-dam-btn': '', onClick: function () { setBrowseOpen(false) } }, t('close'))))
|
|
1284
|
+
: null,
|
|
972
1285
|
field(t('fInject'), h('input', { type: 'checkbox', checked: !!cfg.injectEnabled, onChange: function (e) { set('injectEnabled', e.target.checked) } }), t('fInjectHint')),
|
|
973
1286
|
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')),
|
|
974
1287
|
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')),
|
|
1288
|
+
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')),
|
|
975
1289
|
field(t('fReflect'), h('input', { type: 'checkbox', checked: !!cfg.reflectEnabled, onChange: function (e) { set('reflectEnabled', e.target.checked) } }), t('fReflectHint')),
|
|
976
1290
|
field(t('fStyle'), h('select', { 'data-dam-select': '', value: cfg.reflectStyle, onChange: function (e) { set('reflectStyle', e.target.value) } },
|
|
977
1291
|
STYLE_OPTIONS.map(function (o) { return h('option', { key: o[0], value: o[0] }, o[1]) })), t('fStyleHint')),
|
|
978
1292
|
h('div', { 'data-dam-row': '' },
|
|
979
1293
|
h('button', { 'data-dam-btn': '', onClick: save, disabled: busy }, busy ? t('saving') : t('saveSettings')),
|
|
980
1294
|
msg ? h('span', null, msg) : null),
|
|
1295
|
+
// 调试中心(折叠):模块状态一览,方便排查问题/提 issue
|
|
1296
|
+
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' } },
|
|
1297
|
+
h('button', { 'data-dam-btn': '', onClick: function () { setDbgOpen(!dbgOpen) } }, (dbgOpen ? '▴ ' : '▾ ') + t('debugCenter')),
|
|
1298
|
+
dbgOpen ? h('div', { style: { marginTop: '8px' } }, h(DebugCenter)) : null),
|
|
981
1299
|
err ? h('div', { 'data-dam-error': '' }, err) : null)
|
|
982
1300
|
}
|
|
983
1301
|
|
|
@@ -994,7 +1312,13 @@ window.__ModuleLoader__.load({
|
|
|
994
1312
|
|
|
995
1313
|
var slots = ctx.slots
|
|
996
1314
|
if (!slots) { console.warn('[dsh-auto-memory] slots service unavailable'); return }
|
|
1315
|
+
sessions = ctx.sessions
|
|
997
1316
|
|
|
1317
|
+
// 初始化界面字号(本地偏好,localStorage 持久化)
|
|
1318
|
+
try {
|
|
1319
|
+
var savedScale = localStorage.getItem('dsh-auto-memory.fontScale.v2')
|
|
1320
|
+
if (savedScale in FONT_SCALES) fontScale = savedScale
|
|
1321
|
+
} catch (e3) {}
|
|
998
1322
|
// 初始化界面语言(从 host 配置读取,持久化到 localStorage 以便即时生效)
|
|
999
1323
|
try {
|
|
1000
1324
|
var savedLocale = localStorage.getItem('dsh-auto-memory.locale')
|
|
@@ -1025,7 +1349,7 @@ window.__ModuleLoader__.load({
|
|
|
1025
1349
|
console.log('[dsh-auto-memory] client ready: sidebar entry + panel + settings page')
|
|
1026
1350
|
}
|
|
1027
1351
|
|
|
1028
|
-
exports.inject = ['slots']
|
|
1352
|
+
exports.inject = ['slots', 'sessions']
|
|
1029
1353
|
exports.apply = apply
|
|
1030
1354
|
return module.exports
|
|
1031
1355
|
},
|