@a9i5k4/dsh-auto-memory 0.1.6 → 0.1.7
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 +36 -9
- package/README.zh-CN.md +35 -8
- package/lib/client.js +64 -43
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# dsh-auto-memory — DSH Auto Memory Plugin / DSH 自动记忆插件
|
|
2
2
|
|
|
3
|
-
An auto-memory plugin for the DeepSeek Harness Web GUI: three-layer memory (user-level / project notes / daily logs) with automatic injection and retrieval, daily reflections, a
|
|
3
|
+
An auto-memory plugin for the DeepSeek Harness Web GUI: three-layer memory (user-level / project notes / daily logs) with automatic injection and retrieval, daily reflections, smart period greetings, a calendar view and settings page, and inheritance of memories from other AI tools.
|
|
4
4
|
|
|
5
|
-
DSH Web GUI
|
|
5
|
+
DSH Web GUI 的记忆插件:三层记忆自动注入与检索、每日反思、智能时段问候、日历视图与设置页,支持继承其他 AI 工具的历史记忆。
|
|
6
6
|
|
|
7
7
|
[**English**](README.md) | [中文版](README.zh-CN.md)
|
|
8
8
|
|
|
@@ -10,18 +10,45 @@ DSH Web GUI 的记忆插件:三层记忆(用户级 / 项目笔记 / 每日
|
|
|
10
10
|
|
|
11
11
|
## Features
|
|
12
12
|
|
|
13
|
+
### Three-layer Memory
|
|
14
|
+
|
|
13
15
|
| Layer | Location | Description |
|
|
14
16
|
|---|---|---|
|
|
15
17
|
| User-level memory | `~/.dsh/memory/MEMORY.md` | Cross-project rules & preferences |
|
|
16
18
|
| Project notes | `{workspace}/.dsh-memory/MEMORY.md` | Project conventions & decisions |
|
|
17
19
|
| Daily logs | `{workspace}/.dsh-memory/YYYY-MM-DD.md` | Append-only work log |
|
|
18
|
-
| Reflections | `{workspace}/.dsh-memory/reflections/YYYY-MM-DD.md` | Daily reflection,
|
|
20
|
+
| Reflections | `{workspace}/.dsh-memory/reflections/YYYY-MM-DD.md` | Daily reflection (structured, kept in background) |
|
|
21
|
+
|
|
22
|
+
- **Auto injection**: injects a `<memory_system>` block into every system prompt (user rules + project notes + recent reflections + recent N days of log tails + pending calendar items + writing discipline)
|
|
23
|
+
- **Visible memory ops**: when the AI updates or searches memory, it says so in plain text in the chat reply (e.g. "Logged X to today's journal", "I checked memory and found..."), not hidden inside tool calls
|
|
24
|
+
|
|
25
|
+
### Smart Period Greetings (Overview page)
|
|
26
|
+
|
|
27
|
+
The first thing you see when opening the memory panel is a friendly period greeting, not technical info:
|
|
28
|
+
|
|
29
|
+
- **Multiple times a day**: morning shows "yesterday summary + early morning", forenoon shows the morning's work, noon/afternoon/evening follow suit
|
|
30
|
+
- **Smart timing**: if you were away for more than 1 hour (off work / stepped away) and come back, it automatically shows "Welcome back" with what was finished meanwhile
|
|
31
|
+
- **Drawer layout**: the outer layer stays casual and greeting-like; each period is a drawer — tap to expand the professional details
|
|
32
|
+
- **Daily reflection stays in background**: structured reflections (results / lessons / next steps) are kept, while the front page only shows a light greeting
|
|
33
|
+
|
|
34
|
+
### Calendar View (Four Quadrants)
|
|
35
|
+
|
|
36
|
+
New 「Calendar」tab (liquid-glass monthly view):
|
|
37
|
+
|
|
38
|
+
- Monthly grid, today highlighted, click any date to add an item
|
|
39
|
+
- **Four-quadrant colors**: Urgent & Important (red) / Important (blue) / Urgent (orange) / Neither (gray)
|
|
40
|
+
- Click an item to toggle done, click again to delete; legend + weekday header
|
|
41
|
+
- **Cross-conversation persistence**: data lives at user level `~/.dsh/memory/CALENDAR.md`, shared across workspaces, survives DSH reinstall
|
|
42
|
+
- **AI-maintained**: the AI extracts deadlines and appointments from conversations and writes them to the calendar automatically (`calendar_add` / `calendar_list` / `calendar_done` / `calendar_remove`), restating it in plain text; pending items are injected into every session's system prompt
|
|
43
|
+
|
|
44
|
+
### Agent Tools
|
|
45
|
+
|
|
46
|
+
`memory_log` / `memory_note` / `memory_user` / `memory_recall` / `memory_external` / `memory_maintain` / `memory_status` / `memory_reflect` / `calendar_add` / `calendar_list` / `calendar_done` / `calendar_remove`
|
|
47
|
+
|
|
48
|
+
### UI
|
|
19
49
|
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
- **Agent tools**: `memory_log` / `memory_note` / `memory_user` / `memory_recall` / `memory_external` / `memory_maintain` / `memory_status` / `memory_reflect`
|
|
23
|
-
- **GUI**: sidebar 「Memory」entry → floating panel (Overview / Logs / Notes / Reflections / Connect / Search); Settings page (Settings → Auto Memory)
|
|
24
|
-
- **UI language**: switch between 中文 / English in Settings → Auto Memory → UI language
|
|
50
|
+
- Sidebar 「Memory」entry → floating panel (Overview / Logs / Notes / Reflections / Connect / Calendar / Search)
|
|
51
|
+
- Settings page (Settings → Auto Memory): storage paths, injection budget, reflection style, **UI language (中文 / English)**
|
|
25
52
|
- **External memory inheritance**: import memories accumulated by other AI tools (CodeBuddy / Claude Code / Codex / project convention files)
|
|
26
53
|
|
|
27
54
|
---
|
|
@@ -86,7 +113,7 @@ Adjustable in the GUI (Settings → Auto Memory), including the UI language (zh
|
|
|
86
113
|
## Structure
|
|
87
114
|
|
|
88
115
|
- `lib/index.js` — Host half: engine, injection, tools, routes (zero runtime deps, Node built-ins only)
|
|
89
|
-
- `lib/client.js` — Browser half: memory panel + settings page (built-in zh/en i18n)
|
|
116
|
+
- `lib/client.js` — Browser half: memory panel (with calendar view) + settings page (built-in zh/en i18n)
|
|
90
117
|
- `cordis.patch.yml` — Plugin row (`auto-memory`)
|
|
91
118
|
|
|
92
119
|
---
|
package/README.zh-CN.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# dsh-auto-memory — DSH 自动记忆插件
|
|
2
2
|
|
|
3
|
-
DSH Web GUI 的记忆插件:三层记忆(用户级 / 项目笔记 /
|
|
3
|
+
DSH Web GUI 的记忆插件:三层记忆(用户级 / 项目笔记 / 每日日志)自动注入与检索、每日反思、智能时段问候、日历视图与设置页,支持继承其他 AI 工具的历史记忆。
|
|
4
4
|
|
|
5
5
|
[English](README.md) | [中文版](README.zh-CN.md)
|
|
6
6
|
|
|
@@ -8,18 +8,45 @@ DSH Web GUI 的记忆插件:三层记忆(用户级 / 项目笔记 / 每日
|
|
|
8
8
|
|
|
9
9
|
## 功能
|
|
10
10
|
|
|
11
|
+
### 三层记忆
|
|
12
|
+
|
|
11
13
|
| 层 | 位置 | 说明 |
|
|
12
14
|
|---|---|---|
|
|
13
15
|
| 用户级记忆 | `~/.dsh/memory/MEMORY.md` | 跨项目规则/偏好(用户明确要求时写) |
|
|
14
16
|
| 项目笔记 | `{工作区}/.dsh-memory/MEMORY.md` | 项目长期约定、决策、架构要点 |
|
|
15
17
|
| 每日日志 | `{工作区}/.dsh-memory/YYYY-MM-DD.md` | append-only 工作日志 |
|
|
16
|
-
| 反思 | `{工作区}/.dsh-memory/reflections/YYYY-MM-DD.md` |
|
|
18
|
+
| 反思 | `{工作区}/.dsh-memory/reflections/YYYY-MM-DD.md` | 每日反思(后台结构化积累) |
|
|
19
|
+
|
|
20
|
+
- **自动注入**:每次组装系统提示词时注入 `<memory_system>` 块(用户规则 + 项目笔记 + 最近反思 + 最近 N 天日志尾部 + 未完成日历事项 + 写入纪律)
|
|
21
|
+
- **记忆操作可见**:更新/检索记忆时,AI 会在对话正文中明文说明(如"已把 X 记入今日日志""我查了记忆,发现…"),不藏在工具调用里
|
|
22
|
+
|
|
23
|
+
### 智能时段问候(概览页)
|
|
24
|
+
|
|
25
|
+
打开记忆面板第一眼看到的是生活化的时段问候,而不是严肃的技术信息:
|
|
26
|
+
|
|
27
|
+
- **一天多次**:早晨显示"昨天摘要 + 今天早晨"、上午显示上午的工作、中午/下午/晚上依次类推
|
|
28
|
+
- **智能时机**:离开超过 1 小时(下班/暂离)再打开,自动显示"欢迎回来"并列出期间的完成事项
|
|
29
|
+
- **抽屉式展开**:外层保持生活化问候风格;每个时段做成抽屉,点开才显示专业的工作明细
|
|
30
|
+
- **每日反思**:后台保留结构化反思(成果/教训/要点),前台只有轻松问候
|
|
31
|
+
|
|
32
|
+
### 日历视图(四象限)
|
|
33
|
+
|
|
34
|
+
新增「日历」页签(液态玻璃风格月视图):
|
|
35
|
+
|
|
36
|
+
- 月视图网格,今日高亮,点击任意日期添加事项
|
|
37
|
+
- **四象限色标**:重要紧急(红)/ 重要不紧急(蓝)/ 紧急不重要(橙)/ 不重要不紧急(灰)
|
|
38
|
+
- 点条目切换完成状态,再点删除;图例 + 星期头
|
|
39
|
+
- **跨对话持久**:数据存用户级 `~/.dsh/memory/CALENDAR.md`,所有工作区共享,重装 DSH 不丢
|
|
40
|
+
- **AI 主动维护**:AI 会从对话中提取 deadline、约定时间等自动写入日历(`calendar_add` / `calendar_list` / `calendar_done` / `calendar_remove`),并在正文转述;未完成事项注入每次会话的系统提示词
|
|
41
|
+
|
|
42
|
+
### Agent 工具
|
|
43
|
+
|
|
44
|
+
`memory_log` / `memory_note` / `memory_user` / `memory_recall` / `memory_external` / `memory_maintain` / `memory_status` / `memory_reflect` / `calendar_add` / `calendar_list` / `calendar_done` / `calendar_remove`
|
|
45
|
+
|
|
46
|
+
### 界面
|
|
17
47
|
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
- **Agent 工具**:`memory_log` / `memory_note` / `memory_user` / `memory_recall` / `memory_external` / `memory_maintain` / `memory_status` / `memory_reflect`
|
|
21
|
-
- **GUI**:侧边栏「记忆」入口 → 浮层面板(概览/日志/笔记/反思/接续/检索);设置页(设置 → 自动记忆)
|
|
22
|
-
- **界面语言**:中文 / English 可切换(设置 → 自动记忆 → 界面语言)
|
|
48
|
+
- 侧边栏「记忆」入口 → 浮层面板(概览/日志/笔记/反思/接续/日历/检索)
|
|
49
|
+
- 设置页(设置 → 自动记忆):存储位置、注入预算、反思风格、**界面语言(中文 / English)**
|
|
23
50
|
- **外部记忆继承**:接入其他 AI 工具(CodeBuddy / Claude Code / Codex / 项目约定文件)积累的记忆
|
|
24
51
|
|
|
25
52
|
---
|
|
@@ -84,7 +111,7 @@ pnpm add @a9i5k4/dsh-auto-memory
|
|
|
84
111
|
## 结构
|
|
85
112
|
|
|
86
113
|
- `lib/index.js` — Host 半:引擎、注入、工具、路由(零运行时依赖,仅 node 内置模块)
|
|
87
|
-
- `lib/client.js` —
|
|
114
|
+
- `lib/client.js` — 浏览器半:记忆面板(含日历视图)+ 设置页(内置中英双语)
|
|
88
115
|
- `cordis.patch.yml` — 插件行(`auto-memory`)
|
|
89
116
|
|
|
90
117
|
---
|
package/lib/client.js
CHANGED
|
@@ -148,6 +148,9 @@ window.__ModuleLoader__.load({
|
|
|
148
148
|
segMorning: '早晨', segForenoon: '上午', segNoon: '中午', segAfternoon: '下午', segEvening: '晚上',
|
|
149
149
|
segPrefix: '今日', segMorningHint: '(昨日摘要)',
|
|
150
150
|
welcomeBack: '欢迎回来!这段时间你完成了这些工作:',
|
|
151
|
+
yesterdayDrawer: '昨天',
|
|
152
|
+
greetMorning: '新的一天开始啦,先看看昨天做了什么。', greetForenoon: '上午好,今天也在稳步推进。', greetNoon: '中午好,歇口气再继续。', greetAfternoon: '下午好,下午也要元气满满。', greetEvening: '晚上好,辛苦一天了。',
|
|
153
|
+
greetSummary: '今天已经完成了 ', greetThings: ' 件工作,点开看看:',
|
|
151
154
|
qUrgentImportant: '重要紧急', qImportant: '重要不紧急', qUrgent: '紧急不重要', qNone: '不重要不紧急', qUncategorized: '未分类',
|
|
152
155
|
},
|
|
153
156
|
en: {
|
|
@@ -206,6 +209,9 @@ window.__ModuleLoader__.load({
|
|
|
206
209
|
segMorning: 'Morning', segForenoon: 'Forenoon', segNoon: 'Noon', segAfternoon: 'Afternoon', segEvening: 'Evening',
|
|
207
210
|
segPrefix: 'Today ', segMorningHint: ' (yesterday summary)',
|
|
208
211
|
welcomeBack: 'Welcome back! While you were away, you finished:',
|
|
212
|
+
yesterdayDrawer: 'Yesterday',
|
|
213
|
+
greetMorning: 'A fresh day! Let us look back at yesterday first.', greetForenoon: 'Good morning, steady progress today.', greetNoon: 'Good noon, take a break and keep going.', greetAfternoon: 'Good afternoon, keep up the good energy.', greetEvening: 'Good evening, well done today.',
|
|
214
|
+
greetSummary: 'You have completed ', greetThings: ' things today. Tap to expand:',
|
|
209
215
|
qUrgentImportant: 'Urgent & Important', qImportant: 'Important', qUrgent: 'Urgent', qNone: 'Neither', qUncategorized: 'Uncategorized',
|
|
210
216
|
}
|
|
211
217
|
}
|
|
@@ -350,59 +356,74 @@ window.__ModuleLoader__.load({
|
|
|
350
356
|
var g = props.greeting
|
|
351
357
|
var ps = props.periodSummary
|
|
352
358
|
if (!g) return null
|
|
359
|
+
var openPair = useState({})
|
|
360
|
+
var openMap = openPair[0]
|
|
361
|
+
var setOpenMap = openPair[1]
|
|
353
362
|
// 智能时段判定
|
|
354
363
|
var hour = new Date().getHours()
|
|
355
364
|
var seg = hour < 9 ? 'morning' : hour < 12 ? 'forenoon' : hour < 14 ? 'noon' : hour < 18 ? 'afternoon' : 'evening'
|
|
356
365
|
var segLabel = { morning: t('segMorning'), forenoon: t('segForenoon'), noon: t('segNoon'), afternoon: t('segAfternoon'), evening: t('segEvening') }[seg]
|
|
357
|
-
|
|
358
|
-
var
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
var away = lastSeen > 0 && (now - lastSeen) > 3600000
|
|
364
|
-
if (away) {
|
|
365
|
-
rows.push(h('div', { 'data-dam-content': '' }, t('welcomeBack')))
|
|
366
|
+
// 收集抽屉: {key, label, hint, items, withTime}
|
|
367
|
+
var drawers = []
|
|
368
|
+
var curSegName = { morning: '早晨', forenoon: '上午', noon: '中午', afternoon: '下午', evening: '晚上' }[seg]
|
|
369
|
+
// 昨天抽屉(早晨显示)
|
|
370
|
+
if (seg === 'morning' && g.entries.length) {
|
|
371
|
+
drawers.push({ key: 'yesterday', label: t('yesterdayDrawer') + (g.yesterdayDate || ''), hint: '', items: g.entries, withTime: true, defaultOpen: true })
|
|
366
372
|
}
|
|
367
|
-
//
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
var
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
if (!items.length) continue
|
|
377
|
-
if (segRows.length) segRows.push(h('div', { 'data-dam-hint': '' }, ''))
|
|
378
|
-
segRows.push(h('div', { 'data-dam-hint': '' }, t('segPrefix') + sname + (sname === '早晨' ? t('segMorningHint') : '') + ':'))
|
|
379
|
-
for (var ii = 0; ii < items.length; ii++) {
|
|
380
|
-
(function (txt) {
|
|
381
|
-
segRows.push(h('div', { 'data-dam-row': '', style: { marginBottom: '3px', alignItems: 'flex-start' } },
|
|
382
|
-
h('span', { 'data-dam-muted': '', style: { flex: '0 0 10px', marginTop: '2px' } }, '·'),
|
|
383
|
-
h('span', { style: { flex: '1', wordBreak: 'break-word' } }, txt)))
|
|
384
|
-
})(items[ii])
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
if (segRows.length) rows.push(h('div', null, segRows))
|
|
373
|
+
// 今天各时段抽屉(已过的时段)
|
|
374
|
+
var seenSeg = { '早晨': seg !== 'morning', '上午': (seg === 'forenoon' || seg === 'noon' || seg === 'afternoon' || seg === 'evening'), '中午': (seg === 'noon' || seg === 'afternoon' || seg === 'evening'), '下午': (seg === 'afternoon' || seg === 'evening'), '晚上': seg === 'evening' }
|
|
375
|
+
var segOrder = ['早晨', '上午', '中午', '下午', '晚上']
|
|
376
|
+
for (var si = 0; si < segOrder.length; si++) {
|
|
377
|
+
var sname = segOrder[si]
|
|
378
|
+
if (!seenSeg[sname]) continue
|
|
379
|
+
var items = (ps && ps.groups && ps.groups[sname]) || []
|
|
380
|
+
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 })
|
|
388
382
|
}
|
|
389
|
-
//
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
383
|
+
// 外层:生活化问候
|
|
384
|
+
var totalCount = 0
|
|
385
|
+
for (var d0 = 0; d0 < drawers.length; d0++) totalCount += drawers[d0].items.length
|
|
386
|
+
var greetLine = g.greeting && String(g.greeting).trim()
|
|
387
|
+
? String(g.greeting).trim()
|
|
388
|
+
: (function () {
|
|
389
|
+
if (away()) return t('welcomeBack')
|
|
390
|
+
var base = { morning: t('greetMorning'), forenoon: t('greetForenoon'), noon: t('greetNoon'), afternoon: t('greetAfternoon'), evening: t('greetEvening') }[seg]
|
|
391
|
+
if (totalCount > 0) base += t('greetSummary') + totalCount + t('greetThings')
|
|
392
|
+
return base
|
|
393
|
+
})()
|
|
394
|
+
// 离开>1小时后回来
|
|
395
|
+
function away() {
|
|
396
|
+
var lastSeen = 0
|
|
397
|
+
try { lastSeen = Number(localStorage.getItem('dsh-auto-memory.lastActive') || 0) } catch (e) {}
|
|
398
|
+
return lastSeen > 0 && (Date.now() - lastSeen) > 3600000
|
|
399
|
+
}
|
|
400
|
+
var rows = []
|
|
401
|
+
rows.push(h('div', { 'data-dam-content': '' }, greetLine))
|
|
402
|
+
// 抽屉列表
|
|
403
|
+
for (var d = 0; d < drawers.length; d++) {
|
|
404
|
+
(function (dr) {
|
|
405
|
+
var isOpen = openMap[dr.key] !== undefined ? openMap[dr.key] : dr.defaultOpen
|
|
406
|
+
rows.push(h('div', { key: dr.key, style: { marginTop: '8px' } },
|
|
407
|
+
h('button', {
|
|
408
|
+
'data-dam-btn': '',
|
|
409
|
+
onClick: function () { var n = Object.assign({}, openMap); n[dr.key] = !isOpen; setOpenMap(n) },
|
|
410
|
+
style: { width: '100%', display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '5px 8px', borderRadius: '7px', 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
|
+
},
|
|
412
|
+
h('span', { style: { fontWeight: 600, fontSize: '12.5px' } }, (isOpen ? '▼ ' : '▶ ') + dr.label),
|
|
413
|
+
h('span', { 'data-dam-muted': '', style: { fontSize: '11.5px' } }, dr.items.length + t('logEntries'))),
|
|
414
|
+
isOpen ? h('div', { style: { padding: '6px 4px 2px 10px' } },
|
|
415
|
+
dr.items.map(function (en) {
|
|
416
|
+
return h('div', { key: (en.time || '') + en.text, style: { marginBottom: '3px', fontSize: '12.5px', lineHeight: 1.5 } },
|
|
417
|
+
dr.withTime && en.time ? h('span', { 'data-dam-muted': '', style: { fontFamily: 'monospace', fontSize: '11px', marginRight: '6px' } }, en.time) : null,
|
|
418
|
+
h('span', { style: { wordBreak: 'break-word' } }, en.text))
|
|
419
|
+
})) : null))
|
|
420
|
+
})(drawers[d])
|
|
399
421
|
}
|
|
400
422
|
// 待反思提醒
|
|
401
423
|
if (g.pendingReflectionDate) {
|
|
402
|
-
rows.push(h('div', { 'data-dam-hint': '' }, t('pendingReflectionShort') + g.pendingReflectionDate))
|
|
424
|
+
rows.push(h('div', { 'data-dam-hint': '', style: { marginTop: '8px' } }, t('pendingReflectionShort') + g.pendingReflectionDate))
|
|
403
425
|
}
|
|
404
|
-
|
|
405
|
-
return h(Card, { title: title }, rows)
|
|
426
|
+
return h(Card, { title: (g.period || '') + ' · ' + segLabel }, rows)
|
|
406
427
|
}
|
|
407
428
|
|
|
408
429
|
function OverviewTab() {
|