@a9i5k4/dsh-auto-memory 3.1.1 → 3.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/docs/CONTRIBUTORS.html +2 -2
- package/docs/HANDBOOK.md +5 -5
- package/lib/client.js +155 -26
- package/lib/index.js +368 -24
- package/lib/memory-mutation.js +7 -2
- package/lib/migrate-pack.js +114 -25
- package/lib/subagent-gc.js +5 -1
- package/lib/wb-sidecar.js +8 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -651,7 +651,7 @@ Full credits, including infrastructure sponsors: **[Contributors & Sponsors](htt
|
|
|
651
651
|
|
|
652
652
|
Development resources for this project are partly provided by:
|
|
653
653
|
|
|
654
|
-
- **[DSH API](https://api.dshapi.icu/)** — API relay station providing the model endpoints used for development, testing, and the semantic-engine research behind the M-series features. Thank you for keeping the lights on.
|
|
654
|
+
- **[DSH API](https://api.dshapi.icu/register?aff=HJU27P7JL39N)** — API relay station providing the model endpoints used for development, testing, and the semantic-engine research behind the M-series features. Thank you for keeping the lights on.
|
|
655
655
|
|
|
656
656
|
Infrastructure and API-quota sponsors are listed on the **[Contributors & Sponsors](https://htmlpreview.github.io/?https://github.com/Aik358/dsh-auto-memory/blob/main/docs/CONTRIBUTORS.html)** page. If you would like to support the project, open an issue or join the QQ group.
|
|
657
657
|
|
package/README.zh-CN.md
CHANGED
|
@@ -653,7 +653,7 @@ DeepSeek Harness (Node, 127.0.0.1:3080)
|
|
|
653
653
|
|
|
654
654
|
本项目部分开发资源由以下方提供:
|
|
655
655
|
|
|
656
|
-
- **[DSH API](https://api.dshapi.icu/)** — API 中转站,为本项目的开发、测试以及 M 系列语义引擎研究提供模型端点。感谢一路同行。
|
|
656
|
+
- **[DSH API](https://api.dshapi.icu/register?aff=HJU27P7JL39N)** — API 中转站,为本项目的开发、测试以及 M 系列语义引擎研究提供模型端点。感谢一路同行。
|
|
657
657
|
|
|
658
658
|
基础设施与 API 额度赞助方列在 **[贡献者与赞助](https://htmlpreview.github.io/?https://github.com/Aik358/dsh-auto-memory/blob/main/docs/CONTRIBUTORS.html)** 页面。如希望支持本项目,欢迎提 issue 或加入 QQ 交流群。
|
|
659
659
|
|
package/docs/CONTRIBUTORS.html
CHANGED
|
@@ -395,7 +395,7 @@
|
|
|
395
395
|
<div class="sponsor">
|
|
396
396
|
<div class="mark">DSH</div>
|
|
397
397
|
<div class="body">
|
|
398
|
-
<h3><a href="https://api.dshapi.icu/" target="_blank" rel="noopener">DSH API · api.dshapi.icu</a></h3>
|
|
398
|
+
<h3><a href="https://api.dshapi.icu/register?aff=HJU27P7JL39N" target="_blank" rel="noopener">DSH API · api.dshapi.icu</a></h3>
|
|
399
399
|
<p class="zh">API 中转站,为本项目的开发、回归测试,以及 M 系列语义引擎的选型与激活策略研究提供模型端点。没有这些额度,那些基准实验根本跑不起来。</p>
|
|
400
400
|
<p class="en">An API relay station providing the model endpoints used for development, regression testing, and the M-series semantic-engine selection / activation research. Without that quota, those benchmark runs simply would not have happened.</p>
|
|
401
401
|
<div class="tag"><span class="zh">API 额度赞助</span><span class="en">API quota sponsor</span></div>
|
|
@@ -442,7 +442,7 @@
|
|
|
442
442
|
<a href="https://github.com/Aik358/dsh-auto-memory">README</a> ·
|
|
443
443
|
<a href="https://github.com/Aik358/dsh-auto-memory/blob/main/docs/USER-GUIDE.zh-CN.md">用户文档</a> ·
|
|
444
444
|
<a href="https://github.com/Aik358/dsh-auto-memory" target="_blank" rel="noopener">GitHub</a> ·
|
|
445
|
-
<a href="https://api.dshapi.icu/" target="_blank" rel="noopener">DSH API</a>
|
|
445
|
+
<a href="https://api.dshapi.icu/register?aff=HJU27P7JL39N" target="_blank" rel="noopener">DSH API</a>
|
|
446
446
|
</p>
|
|
447
447
|
<p style="margin-top:10px;opacity:.6">dsh-auto-memory · BSD-3-Clause</p>
|
|
448
448
|
</footer>
|
package/docs/HANDBOOK.md
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
| **BM25** | 经典词法相关性算法 |
|
|
28
28
|
| **M8 / 记忆中枢** | 三层记忆存储(fact 事实/episodic 经历/procedure 技能)与编排器 memory-hub 的合称 |
|
|
29
29
|
| **evidence(证据)** | 记忆被使用情况的记录,六类:`seen`(曝光)/`read`(读到原文)/`cite`(回复引用)/`reuse`(跨会话复用)/`success`(任务成功)/`correction`(用户纠正) |
|
|
30
|
-
| **endpoint / 端点** | 后端 HTTP 接口,路径前缀统一为 `/api/dsh-auto-memory/`(pre 树为 `/api/dsh-auto-memory-pre/`),共
|
|
30
|
+
| **endpoint / 端点** | 后端 HTTP 接口,路径前缀统一为 `/api/dsh-auto-memory/`(pre 树为 `/api/dsh-auto-memory-pre/`),共 54 条 |
|
|
31
31
|
|
|
32
32
|
---
|
|
33
33
|
|
|
@@ -78,7 +78,7 @@ dsh web --no-open --port 0
|
|
|
78
78
|
│ HTTP /api/dsh-auto-memory/*(pre 树为 /api/dsh-auto-memory-pre/*)
|
|
79
79
|
┌───────────────▼───────────────────────────────────────────┐
|
|
80
80
|
│ 宿主侧(后端)lib/index.js + lib/*-pre.js │
|
|
81
|
-
│ · 端点路由(
|
|
81
|
+
│ · 端点路由(54 个) │
|
|
82
82
|
│ · 工具(18 个,供模型调用) │
|
|
83
83
|
│ · 存储:记忆文件、M8 三层 JSON、evidence 事件 JSONL │
|
|
84
84
|
│ · 检索:C1 词法 / C2 语义 / C3 Python 语义 │
|
|
@@ -169,7 +169,7 @@ dsh web --no-open --port 0
|
|
|
169
169
|
|
|
170
170
|
## 5. 后端状态来源(如何确认前端操作已生效)
|
|
171
171
|
|
|
172
|
-
### 5.1 主要端点(`lib/index.js` 注册,共 **
|
|
172
|
+
### 5.1 主要端点(`lib/index.js` 注册,共 **54** 条,前缀 `/api/dsh-auto-memory/`)
|
|
173
173
|
|
|
174
174
|
| 端点 | 用途 | 关键返回字段 |
|
|
175
175
|
|---|---|---|
|
|
@@ -195,7 +195,7 @@ dsh web --no-open --port 0
|
|
|
195
195
|
> node -e "const f=require('fs');const s=f.readFileSync('lib/index.js','utf8'),r=f.readFileSync('tools/release.mjs','utf8');const P=[...r.matchAll(/\['([^']+)',\s*'([^']+)'\]/g)].map(m=>[m[1],m[2]]);const c=x=>P.reduce((a,[b,d])=>a.split(b).join(d),x);const e=[...new Set([...s.matchAll(/'(\/api\/dsh-auto-memory[^']*)'/g)].map(m=>m[1]))];console.log('端点条数:',e.length);console.log('发布名前缀:',c(e[0]).split('/').slice(0,3).join('/')+'/')"
|
|
196
196
|
> ```
|
|
197
197
|
>
|
|
198
|
-
> 在工程根执行,输出应为 `端点条数:
|
|
198
|
+
> 在工程根执行,输出应为 `端点条数: 54` / `发布名前缀: /api/dsh-auto-memory/`。命令读的是**源码 + 发布转换表**,所以两条线的拼写都能对上。
|
|
199
199
|
|
|
200
200
|
### 5.2 日志
|
|
201
201
|
|
|
@@ -384,7 +384,7 @@ node tests/smoke/smoke-test-continue-chain-pre.mjs # 58
|
|
|
384
384
|
| 工程根 | `D:\dsh-auto-memory` |
|
|
385
385
|
| 宿主侧入口 | `lib/index.js` |
|
|
386
386
|
| 浏览器侧入口 | `lib/client.js` |
|
|
387
|
-
| 端点前缀 | `/api/dsh-auto-memory/`(
|
|
387
|
+
| 端点前缀 | `/api/dsh-auto-memory/`(54 条;pre 树 `/api/dsh-auto-memory-pre/`) |
|
|
388
388
|
| 工具 | 10 个,`memory_*_pre` |
|
|
389
389
|
| 记忆根 | `C:\Users\JH Z\.dsh\memory` |
|
|
390
390
|
| 证据事件 | `...\memory\evidence\events\YYYY-MM-DD.jsonl`(时间戳在 `event.ts`) |
|
package/lib/client.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
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 v3.1.
|
|
10
|
+
console.log('[dsh-auto-memory] client v3.1.4 fingerprint: ci-restore-and-migrate-safe-import')
|
|
11
11
|
window.__ModuleLoader__.load({
|
|
12
12
|
id: '@a9i5k4/dsh-auto-memory',
|
|
13
13
|
factory: (require) => {
|
|
@@ -234,7 +234,7 @@ window.__ModuleLoader__.load({
|
|
|
234
234
|
statsSegChars: '按字符数(谁最占预算)',
|
|
235
235
|
statsSegCount: '按出现次数',
|
|
236
236
|
statsSince: '开始记录于',
|
|
237
|
-
statsNever: '从未', logs: '日志', refineTab: '唤起回顾', notes: '笔记', reflections: '反思', connect: '接续', calendar: '日历', search: '检索', workspaces: '工作区', hubTab: '记忆中枢', storageTab: '存储管理', planTab: '白板', planTitle: '白板 · PLAN.md(项目全貌)', planEmpty: '(白板尚未建立——宿主会在该工作区第一次会话结束时自动落一版骨架,模型理解项目全貌后把它重写成真内容;也可在对话中让它用 memory_note(kind=plan) 写)', planVersions: '白板历史版本', planLedgers: '交接账本时间线', planDisabled: '交接白板未启用(设置 →
|
|
237
|
+
statsNever: '从未', logs: '日志', refineTab: '唤起回顾', notes: '笔记', reflections: '反思', connect: '接续', calendar: '日历', search: '检索', workspaces: '工作区', hubTab: '记忆中枢', storageTab: '存储管理', planTab: '白板', planTitle: '白板 · PLAN.md(项目全貌)', planEmpty: '(白板尚未建立——宿主会在该工作区第一次会话结束时自动落一版骨架,模型理解项目全貌后把它重写成真内容;也可在对话中让它用 memory_note(kind=plan) 写)', planVersions: '白板历史版本', planLedgers: '交接账本时间线', planDisabled: '交接白板未启用(设置 → 长会话接续)。', planWsUnbound: '当前会话未绑定工作区——白板与交接账本暂不可用(会话的工作区身份解析不出来;把会话开进项目文件夹或绑定工作区后自动恢复)。', planFileTitle: '查看',
|
|
238
238
|
hubSkills: '技能 (Procedural)', hubSkillsEmpty: '暂无已固化的技能。反复成功的流程会自动固化为技能并在相似场景召回。', hubFacts: '事实 (Semantic)', hubFactsEmpty: '暂无固化的事实。', hubConflicts: '待决冲突', hubEpisodic: '经历 (Episodic)', hubEpisodicEmpty: '暂无已巩固的经历。',
|
|
239
239
|
storageScanHint: '语料健康 = 逐源比对索引(sidecar)与正文的 digest。手动改动记忆文件后索引会失配,该记忆会退出检索直到重建索引。',
|
|
240
240
|
storageDeleteHint: '删除记忆 = 正文原子删除 + 在途唤起包清理 + 派生事实撤销(三联动)。已产生的 seen 证据不改写。',
|
|
@@ -281,7 +281,7 @@ window.__ModuleLoader__.load({
|
|
|
281
281
|
pickedDir: '已选择目录:', rememberSave: '(点击「保存设置」后生效)', pickerUnavailable: '系统文件夹选择器不可用,改用内嵌浏览。',
|
|
282
282
|
fDayBoundary: '日界(分钟)', fDayBoundaryHint: '从 0 点起算:凌晨在此之前的活儿归前一天。默认 450=早上 7:30 进入新一天;改 480=8:00;0=按午夜切日。',
|
|
283
283
|
fVersion: '插件版本', checkUpdate: '检查更新', checking: '检查中…', upToDate: '(已是最新)', hasUpdate: '(有新版本)', versionError: '版本检查失败: ', versionCmdHint: '更新命令: cd ~/.dsh/profiles/web && pnpm up @a9i5k4/dsh-auto-memory,然后重启 dsh web 生效。',
|
|
284
|
-
updateNow: '一键更新', updating: '更新中…', updateDone: '更新完成,请重启 dsh web 生效。', updateFailed: '更新失败: ', devLinkHint: '(
|
|
284
|
+
updateNow: '一键更新', updating: '更新中…', updateDone: '更新完成,请重启 dsh web 生效。', updateFailed: '更新失败: ', devLinkHint: '(当前为本地开发链接 link:,一键更新不适用。若上方显示「开发树 vX → 线上 vY」,说明 npm 上已有更新版,请同步开发源码后重新构建发布。)', noProfileHint: '(未找到 dsh profile,无法自动更新)',
|
|
285
285
|
kvVersion: '插件版本', kvUnreadable: '(读不到)', kvPid: 'PID / 启动', kvRestart: 'Host 需重启?', kvRestartYes: '是(代码比进程新)', kvRestartNo: '否',
|
|
286
286
|
kvHeartbeat: '轮询心跳', hbAliveAgo: '存活(上次 ', hbSecAgo: ' 秒前)', hbAlive: '存活', hbNone: '无心跳文件',
|
|
287
287
|
kvQueue: '沉淀重试队列', kvCountSuffix: ' 条', kvToday: '今日沉淀', kvRecentPrefix: ' 条 / 最近 ', kvBusy: '正在沉淀中', kvYes: '是', kvNo: '否',
|
|
@@ -289,9 +289,9 @@ window.__ModuleLoader__.load({
|
|
|
289
289
|
kvMem: '记忆文件', kvMemUser: '用户', kvMemNotes: '笔记', kvMemLog: '日志', kvMemMissing: '缺失',
|
|
290
290
|
kvWs: '当前工作区', kvWsUnknown: '(未取到)', kvApi: 'API 连通', unknown: '(未知)',
|
|
291
291
|
// ★P0-2/P0-3(2026-09-22):把后端早已算好、前端零消费者的两组可观测性接到界面上。
|
|
292
|
-
dbgHubIo: '三层记忆落盘', dbgPrune: '事实淘汰(保留上限)',
|
|
293
|
-
dbgLogs: '诊断日志',
|
|
294
|
-
dbgLogsNone: '尚未生成(本次运行还没有诊断输出)',
|
|
292
|
+
dbgHubIo: '三层记忆落盘', dbgPrune: '事实淘汰(保留上限)',
|
|
293
|
+
dbgLogs: '诊断日志',
|
|
294
|
+
dbgLogsNone: '尚未生成(本次运行还没有诊断输出)',
|
|
295
295
|
dbgLogsHint: '崩溃/异常时请把下面路径的文件附给维护者(只读展示,不含日志正文)',
|
|
296
296
|
kvPyTitle: 'Python 语义侧车', kvPyOff: '未启用(JS 端语义不受影响)', kvPyAlive: '运行中',
|
|
297
297
|
kvPyWatchdog: '看门狗击杀 / 重生', kvPyStderr: '最近 stderr 尾部', kvPyStderrTrunc: '(已截断)',
|
|
@@ -476,7 +476,7 @@ window.__ModuleLoader__.load({
|
|
|
476
476
|
statsSegChars: 'By characters (who eats the budget)',
|
|
477
477
|
statsSegCount: 'By occurrences',
|
|
478
478
|
statsSince: 'Recording since',
|
|
479
|
-
statsNever: 'never', logs: 'Logs', refineTab: 'Recall review', notes: 'Notes', reflections: 'Reflections', connect: 'Connect', calendar: 'Calendar', search: 'Search', workspaces: 'Workspaces', hubTab: 'Memory Hub', storageTab: 'Storage', planTab: 'Whiteboard', planTitle: 'Whiteboard · PLAN.md (project plan)', planEmpty: '(not created yet — the host seeds a skeleton board when a turn first ends in this workspace; the model rewrites it with real content once it grasps the picture, or ask it to write memory_note kind=plan)', planVersions: 'Plan versions', planLedgers: 'Handoff ledger timeline', planDisabled: 'Handoff whiteboard is disabled (Settings →
|
|
479
|
+
statsNever: 'never', logs: 'Logs', refineTab: 'Recall review', notes: 'Notes', reflections: 'Reflections', connect: 'Connect', calendar: 'Calendar', search: 'Search', workspaces: 'Workspaces', hubTab: 'Memory Hub', storageTab: 'Storage', planTab: 'Whiteboard', planTitle: 'Whiteboard · PLAN.md (project plan)', planEmpty: '(not created yet — the host seeds a skeleton board when a turn first ends in this workspace; the model rewrites it with real content once it grasps the picture, or ask it to write memory_note kind=plan)', planVersions: 'Plan versions', planLedgers: 'Handoff ledger timeline', planDisabled: 'Handoff whiteboard is disabled (Settings → Handoff).', planWsUnbound: 'This session has no bound workspace — whiteboard and handoff ledgers are unavailable (the session workspace could not be resolved; open the session inside a project folder or bind a workspace to restore).', planFileTitle: 'View',
|
|
480
480
|
hubSkills: 'Skills (Procedural)', hubSkillsEmpty: 'No solidified skills yet. Repeatedly-successful workflows become skills and are recalled in similar contexts.', hubFacts: 'Facts (Semantic)', hubFactsEmpty: 'No solidified facts yet.', hubConflicts: 'Pending conflicts', hubEpisodic: 'Episodes (Episodic)', hubEpisodicEmpty: 'No consolidated episodes yet.',
|
|
481
481
|
storageScanHint: 'Corpus health = compare each source\'s index (sidecar) against its body digest. After you hand-edit a memory file the index no longer matches, and that memory drops out of retrieval until the index is rebuilt.',
|
|
482
482
|
storageDeleteHint: 'Delete = atomic body removal + in-flight activation purge + derived-fact revocation (cascading). Evidence already recorded (seen) is never rewritten.',
|
|
@@ -522,16 +522,16 @@ window.__ModuleLoader__.load({
|
|
|
522
522
|
pickedDir: 'Selected folder:', rememberSave: '(click Save to apply)', pickerUnavailable: 'Native folder picker unavailable, falling back to in-app browser.',
|
|
523
523
|
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.',
|
|
524
524
|
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.',
|
|
525
|
-
updateNow: 'Update now', updating: 'Updating…', updateDone: 'Update finished, restart dsh web to apply.', updateFailed: 'Update failed: ', devLinkHint: '(local dev link, sync source
|
|
525
|
+
updateNow: 'Update now', updating: 'Updating…', updateDone: 'Update finished, restart dsh web to apply.', updateFailed: 'Update failed: ', devLinkHint: '(local dev link — one-click update does not apply. If "dev tree vX to registry vY" shows above, a newer version is on npm; sync the source and rebuild.)', noProfileHint: '(no dsh profile found, cannot auto-update)',
|
|
526
526
|
kvVersion: 'Plugin version', kvUnreadable: '(unreadable)', kvPid: 'PID / Started', kvRestart: 'Host restart needed?', kvRestartYes: 'yes (code newer than process)', kvRestartNo: 'no',
|
|
527
527
|
kvHeartbeat: 'Heartbeat', hbAliveAgo: 'alive (last ', hbSecAgo: ' s ago)', hbAlive: 'alive', hbNone: 'no heartbeat file',
|
|
528
528
|
kvQueue: 'Consolidation retry queue', kvCountSuffix: ' item(s)', kvToday: 'Consolidated today', kvRecentPrefix: ' item(s) / latest ', kvBusy: 'Consolidating now', kvYes: 'yes', kvNo: 'no',
|
|
529
529
|
kvAvail: 'available', kvUnavail: 'unavailable', kvDup: 'Duplicate note headings', kvDupCount: '',
|
|
530
530
|
kvMem: 'Memory files', kvMemUser: 'user', kvMemNotes: 'notes', kvMemLog: 'log', kvMemMissing: 'missing',
|
|
531
531
|
kvWs: 'Current workspace', kvWsUnknown: '(unknown)', kvApi: 'API probes', unknown: '(unknown)',
|
|
532
|
-
dbgHubIo: 'Layer-3 memory persistence', dbgPrune: 'Fact eviction (retention cap)',
|
|
533
|
-
dbgLogs: 'Diagnostic log',
|
|
534
|
-
dbgLogsNone: 'not created yet (no diagnostic output this run)',
|
|
532
|
+
dbgHubIo: 'Layer-3 memory persistence', dbgPrune: 'Fact eviction (retention cap)',
|
|
533
|
+
dbgLogs: 'Diagnostic log',
|
|
534
|
+
dbgLogsNone: 'not created yet (no diagnostic output this run)',
|
|
535
535
|
dbgLogsHint: 'On a crash/exception, attach the file at the path below (read-only; log body not shown)',
|
|
536
536
|
kvPyTitle: 'Python sidecar', kvPyOff: 'disabled (JS-side semantics unaffected)', kvPyAlive: 'running',
|
|
537
537
|
kvPyWatchdog: 'Watchdog kills / respawns', kvPyStderr: 'Last stderr tail', kvPyStderrTrunc: ' (truncated)',
|
|
@@ -806,7 +806,43 @@ window.__ModuleLoader__.load({
|
|
|
806
806
|
|
|
807
807
|
// ───────────────────────── 更新弹窗 / 首次指导 ─────────────────────────
|
|
808
808
|
var CHANGELOG = {
|
|
809
|
-
'3.1.
|
|
809
|
+
'3.1.4': { zh: [
|
|
810
|
+
'★ 修复:白板重写不再「每次都重试」。此前模型不知道锚点契约、注入快照又被截断,首轮必被拦一次;现在工具描述写明「先读磁盘原文抄回锚点」,被拦时还会把缺失卡片的原文块一并回吐,一轮即可补齐。',
|
|
811
|
+
'★ 变更:白板丢卡从「拒绝写入」改为「照写 + 显式警示」——放行但绝不静默,警示会说明丢了哪几张、从哪找回。用户手写备注区被覆盖、以及卡片 id 重复,仍然硬拒(这两类是真丢数据/结构错误)。',
|
|
812
|
+
'修复:补上白板重写时的「显式归档」入口(archivedIds)——此前报错里承诺的这条路根本没接通。',
|
|
813
|
+
'修复:引导末页的三个入口按钮此前是裸链接(只有属性没有样式),现在与页面风格统一:hover 有反馈、跟随主题色。',
|
|
814
|
+
'新增:引导末页新增「QQ 交流群」入口。',
|
|
815
|
+
], en: [
|
|
816
|
+
'★ Fix: rewriting the whiteboard no longer fails on the first try. The model was never told about the anchor contract, and the injected snapshot is truncated — so the first attempt was always rejected. The tool description now says "read the on-disk file first and copy every anchor back", and a rejection now returns the missing cards\' verbatim text so one retry suffices.',
|
|
817
|
+
'★ Change: a dropped whiteboard card is now written with an explicit warning instead of being rejected — never silent, and the warning names the cards lost and where to recover them. Overwriting your own notes region, and duplicate card ids, are still hard-rejected (real data loss / structural errors).',
|
|
818
|
+
'Fix: added the missing "explicit archive" entry (archivedIds) for whiteboard rewrites — the path promised by the error message was never actually wired.',
|
|
819
|
+
'Fix: the three entry buttons on the tour\'s last page were bare links (attribute without styles); they now match the page style, with hover feedback and theme colours.',
|
|
820
|
+
'New: a QQ community group entry on the tour\'s last page.',
|
|
821
|
+
] },
|
|
822
|
+
'3.1.3': { zh: [
|
|
823
|
+
'★ 修复:宿主下次改会话文件名时,五条功能链会集体静默降级 —— 已从根上拆掉;会话日志路径不再用固定候选表,改按结构识别(兼容未来 v4 命名)。',
|
|
824
|
+
'★ 修复:迁移搬包的范围扩到日历(CALENDAR.md);日历跨工作区共享,导入按合并不覆盖,本机已完成的条目不被打回,同包重导不重复。',
|
|
825
|
+
'★ 修复:「周期记忆快照」开关此前是死开关 —— 界面能翻面、能落盘,但记忆照旧每轮注入。现在关掉它真的会停注入(只关这一条通路,记忆写入与检索不受影响)。',
|
|
826
|
+
'修复:引导里「思维链监听」原写「默认关」,真值是开 —— 方向反了,会误导隐私判断;已改正。',
|
|
827
|
+
'修复:引导里「技能固化」原说晋升审批在记忆中枢页(实际在唤起回顾页),且该开关并不控晋升;两处指引已纠正。',
|
|
828
|
+
'修复:白板空态与索引提示指向的分区名已废弃(自动化/自动记忆引擎);改为实际分区名(长会话接续/语义记忆总开关)。',
|
|
829
|
+
'修复:设置页补上「机械流程切片」控件 —— 该键功能本来是通的,但此前只有向导里能改。',
|
|
830
|
+
'新增:引导末页新增「贡献者与赞助」「DSH API 中转站」两个入口。',
|
|
831
|
+
'新增:关闭新手引导后弹出的更新说明,从此跟随当前版本(此前恒为 2.1.0)。',
|
|
832
|
+
'新增:云盘/远端同步目录探测(判断目录是否可用并给出人话诊断;只当普通目录,不依赖任何网盘专有接口)。',
|
|
833
|
+
], en: [
|
|
834
|
+
'★ Fix: five feature chains would silently degrade the next time the host renamed its session-log file — root cause removed. Session paths are no longer a fixed candidate list; they are matched structurally, so future v4 names work.',
|
|
835
|
+
'★ Fix: pack-and-carry now includes your calendar (CALENDAR.md). The calendar is shared across workspaces, so import merges instead of overwriting: locally completed items are never reverted, and re-importing the same pack adds nothing.',
|
|
836
|
+
'★ Fix: the "periodic memory snapshot" switch used to be dead — it flipped and saved, but memories were injected every turn regardless. Turning it off now really stops injection (only that one path; memory writes and search are untouched).',
|
|
837
|
+
'Fix: the tour said the reasoning observer defaults OFF — it defaults ON. That reversal could mislead privacy decisions; corrected.',
|
|
838
|
+
'Fix: the tour said promotion review lives in the Memory Hub tab (it is the Recall review tab), and that switch does not control promotion at all; both pointers corrected.',
|
|
839
|
+
'Fix: the whiteboard empty state and index hints pointed at renamed/removed settings sections; now they name the real ones.',
|
|
840
|
+
'Fix: Settings now exposes the "mechanical flow slicing" control — the key worked, but previously only the tour could change it.',
|
|
841
|
+
'New: two entry points on the tour’s last page — Contributors & Sponsors, and the DSH API relay.',
|
|
842
|
+
'New: the release-notes card after the tour now follows the current version (it used to be pinned to 2.1.0).',
|
|
843
|
+
'New: cloud/remote sync-directory probe (reports whether a directory is usable, with a plain-language hint; treats it as an ordinary folder and depends on no vendor API).',
|
|
844
|
+
] },
|
|
845
|
+
'3.1.1': { zh: [
|
|
810
846
|
'新增:记忆搬包 —— 把某个工作区的记忆整体搬到另一台机器。「存储管理」页签新增入口:导出本工作区得到 .dam-pack,到新机器导入。',
|
|
811
847
|
'导入是三步向导:选包 → 预览差异(只读,不动任何文件) → 确认导入。预览会列出路径是否变化、新增/覆盖几个文件、内部引用要重写多少处。',
|
|
812
848
|
'换机器会自动重写内部路径:包内指向旧路径/旧 slug 的引用(含正文里的路径字样)按 4 种写法逐一替换成新机器真实路径;路径相同则一个字都不改。',
|
|
@@ -1347,6 +1383,8 @@ window.__ModuleLoader__.load({
|
|
|
1347
1383
|
pyStatus: ROUTE_PREFIX + '/python-setup/status',
|
|
1348
1384
|
handoffState: ROUTE_PREFIX + '/handoff-state',
|
|
1349
1385
|
kanbanBoard: ROUTE_PREFIX + '/kanban-board',
|
|
1386
|
+
// ★v3.1.2:卡片全文按需取(看板载荷不再内联 full)
|
|
1387
|
+
kanbanCard: ROUTE_PREFIX + '/kanban-card',
|
|
1350
1388
|
handoffContinue: ROUTE_PREFIX + '/handoff-continue',
|
|
1351
1389
|
handoffPermission: ROUTE_PREFIX + '/handoff-permission',
|
|
1352
1390
|
autoContState: ROUTE_PREFIX + '/auto-continue-state',
|
|
@@ -1826,6 +1864,20 @@ window.__ModuleLoader__.load({
|
|
|
1826
1864
|
'[data-dam-tour-sw][data-on="true"] { background: var(--dam-accent, #3a6df0); }',
|
|
1827
1865
|
'[data-dam-tour-sw][data-on="true"]::after { left: 19.5px; }',
|
|
1828
1866
|
'[data-dam-tour-chips] { display: flex; flex-wrap: wrap; gap: 7px; justify-content: center; margin-top: 12px; }',
|
|
1867
|
+
// ★v3.1.4 批 J(用户报「这个按钮实在是有点太难看了」):v3.1.3 只加了 data-dam-tour-links
|
|
1868
|
+
// 属性却没写 CSS ⇒ 浏览器按默认 a 渲染成蓝色下划线裸链接,与页面完全脱节。
|
|
1869
|
+
// 现补齐:与既有 chip 体系同源(--dam-accent 主题色 + 圆角胶囊 + hover + 深色底)。
|
|
1870
|
+
'[data-dam-tour-links] { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-top: 14px; }',
|
|
1871
|
+
'[data-dam-tour-link] { display: inline-flex; align-items: center; gap: 5px; padding: 6px 13px; border-radius: 99px;',
|
|
1872
|
+
' font-size: 12px; font-weight: 600; line-height: 1.4; text-decoration: none; cursor: pointer; white-space: nowrap;',
|
|
1873
|
+
' color: color-mix(in srgb, var(--dam-accent, #3a6df0) 78%, #fff);',
|
|
1874
|
+
' background: color-mix(in srgb, var(--dam-accent, #3a6df0) 12%, rgba(255,255,255,.05));',
|
|
1875
|
+
' border: 1px solid color-mix(in srgb, var(--dam-accent, #3a6df0) 34%, transparent);',
|
|
1876
|
+
' transition: background .18s ease, border-color .18s ease, transform .12s ease; }',
|
|
1877
|
+
'[data-dam-tour-link]:hover { background: color-mix(in srgb, var(--dam-accent, #3a6df0) 21%, rgba(255,255,255,.07));',
|
|
1878
|
+
' border-color: color-mix(in srgb, var(--dam-accent, #3a6df0) 52%, transparent); }',
|
|
1879
|
+
'[data-dam-tour-link]:active { transform: scale(.98); }',
|
|
1880
|
+
'[data-dam-tour-links-note] { flex-basis: 100%; text-align: center; font-size: 11px; opacity: .55; margin-top: 2px; line-height: 1.6; }',
|
|
1829
1881
|
'[data-dam-tour-where] { font-size: 11.5px; opacity: .72; line-height: 1.75; margin-top: 12px; text-align: left; max-width: 460px; margin-left: auto; margin-right: auto; }',
|
|
1830
1882
|
'[data-dam-tour-where] b { opacity: .96; font-weight: 650; }',
|
|
1831
1883
|
// ── CHANGELOG 开场序列:Logo 组装→展开→消散→内容浮现 ──
|
|
@@ -1965,7 +2017,9 @@ window.__ModuleLoader__.load({
|
|
|
1965
2017
|
* 正文 = 剩余行拼接(已清洗), 与标题不重复 —— 这正是「标题+正文分离」。
|
|
1966
2018
|
*/
|
|
1967
2019
|
function wbShape(c) {
|
|
1968
|
-
|
|
2020
|
+
// ★v3.1.2 性能:列表渲染(节点画布)用 preview 即可 —— 载荷已不内联 full,
|
|
2021
|
+
// 此处若仍读 c.full 会恒为空 ⇒ 标题/正文全丢。preview 是稳定来源。
|
|
2022
|
+
var rawFull = c.preview || c.full || ''
|
|
1969
2023
|
var ls = wbCleanLines(rawFull)
|
|
1970
2024
|
var head = ls.length ? ls[0] : ''
|
|
1971
2025
|
var title = head ? (head.length > 60 ? head.slice(0, 57) + '…' : head) : (c.title || c.short || '')
|
|
@@ -2005,6 +2059,54 @@ window.__ModuleLoader__.load({
|
|
|
2005
2059
|
return 'rgba(128,128,128,.75)'
|
|
2006
2060
|
}
|
|
2007
2061
|
|
|
2062
|
+
/**
|
|
2063
|
+
* ★v3.1.2 性能:卡片全文**按需取**。
|
|
2064
|
+
* 看板载荷不再内联 full(1178 卡 × ≤6000 字符、且 lanes+matrix 双份 ⇒ 约 1.7 MB 纯冗余),
|
|
2065
|
+
* 取而代之的是 fullLen;点「展开全文」/打开抽屉时才按 id 向 /kanban-card 单取一次并缓存。
|
|
2066
|
+
* 失败/未取到时**回退 preview**(绝不显示空白)。
|
|
2067
|
+
*/
|
|
2068
|
+
var wbFullCache = {} // id -> string(进程内缓存,避免反复取同一张)
|
|
2069
|
+
function useCardFull(card) {
|
|
2070
|
+
var p = useState(function () { return (card && wbFullCache[card.id]) || '' })
|
|
2071
|
+
var text = p[0], setText = p[1]
|
|
2072
|
+
useEffect(function () {
|
|
2073
|
+
var c = card || {}
|
|
2074
|
+
if (!c.id) return
|
|
2075
|
+
if (wbFullCache[c.id] !== undefined) { setText(wbFullCache[c.id]); return }
|
|
2076
|
+
// 载荷里若仍带 full(老版本/其它来源)直接用,不打请求
|
|
2077
|
+
if (typeof c.full === 'string') { wbFullCache[c.id] = c.full; setText(c.full); return }
|
|
2078
|
+
var alive = true
|
|
2079
|
+
apiGet(API.kanbanCard, { id: c.id, sessionId: currentSessionIdClient() }).then(function (r) {
|
|
2080
|
+
if (!alive) return
|
|
2081
|
+
var t = (r && r.ok && typeof r.full === 'string') ? r.full : ''
|
|
2082
|
+
wbFullCache[c.id] = t
|
|
2083
|
+
setText(t)
|
|
2084
|
+
}).catch(function () { if (alive) { wbFullCache[c.id] = ''; setText('') } })
|
|
2085
|
+
return function () { alive = false }
|
|
2086
|
+
}, [card && card.id])
|
|
2087
|
+
return text
|
|
2088
|
+
}
|
|
2089
|
+
|
|
2090
|
+
/**
|
|
2091
|
+
* ★v3.1.4 修复(用户报障「白板看板点进去就白屏」):抽屉正文**单独组件**。
|
|
2092
|
+
*
|
|
2093
|
+
* 根因(栈追踪直指): 此前正文写成 `h('pre', …, (useCardFull(drawer) || …))`,
|
|
2094
|
+
* 而该处位于 `drawer ? kxPortal(...) : null` 的**条件分支内部** ⇒
|
|
2095
|
+
* **未开抽屉时不调这个 hook、打开抽屉才调** ⇒ 同一组件两次渲染 hook 数量不同
|
|
2096
|
+
* ⇒ React error #310(Rendered more hooks than during the previous render)
|
|
2097
|
+
* ⇒ slot 'conversation.view' 整块崩溃 ⇒ 白屏。**「点击」这个动作本身**改变了 hook 数。
|
|
2098
|
+
* (同一 hook 在 KanbanCard 里写法是对的:`useCardFull(expanded ? c : null)` —— 无条件调用、参数可空。)
|
|
2099
|
+
*
|
|
2100
|
+
* 修法: 把 hook 收进本组件;它**只在 drawer 存在时才被挂载**,
|
|
2101
|
+
* 挂载期间 hook 数量恒定 ⇒ #310 消除。原 L2545 的兜底链
|
|
2102
|
+
* `|| drawer.full || drawer.preview || ''` 一并保留(绝不显示空白)。
|
|
2103
|
+
*/
|
|
2104
|
+
function KanbanDrawerBody(props) {
|
|
2105
|
+
var d = props.drawer || {}
|
|
2106
|
+
var text = useCardFull(d) || d.full || d.preview || ''
|
|
2107
|
+
return h('pre', { 'data-dam-kx-full': d.id, style: { whiteSpace: 'pre-wrap', wordBreak: 'break-word', fontFamily: 'inherit', margin: 0, fontSize: '12px' } }, text)
|
|
2108
|
+
}
|
|
2109
|
+
|
|
2008
2110
|
/** 单张卡片: 标题 + 判据徽章 + 预览/全文 + 小节徽章 + 标签 + 来源。可点击展开。 */
|
|
2009
2111
|
function KanbanCard(props) {
|
|
2010
2112
|
var c = props.card || {}
|
|
@@ -2012,8 +2114,10 @@ window.__ModuleLoader__.load({
|
|
|
2012
2114
|
var expanded = !!props.expanded
|
|
2013
2115
|
var onToggle = props.onToggle
|
|
2014
2116
|
var tone = KANBAN_TONES[(c.badge && c.badge.tone) || 'unknown'] || KANBAN_TONES.unknown
|
|
2015
|
-
|
|
2016
|
-
var
|
|
2117
|
+
// ★v3.1.2:全文按需取(展开时才请求;未取到回退 preview)
|
|
2118
|
+
var fullText = useCardFull(expanded ? c : null)
|
|
2119
|
+
var body = expanded ? (fullText || c.full || c.preview || '') : (c.preview || '')
|
|
2120
|
+
var canExpand = (typeof c.fullLen === 'number' ? c.fullLen : (c.full || '').length) > (c.preview || '').length
|
|
2017
2121
|
return h('div', {
|
|
2018
2122
|
'data-dam-kcard': '',
|
|
2019
2123
|
title: c.source + (c.section ? ' §' + c.section : '') + (c.anchored ? ' · 有锚点' : ''),
|
|
@@ -2038,7 +2142,7 @@ window.__ModuleLoader__.load({
|
|
|
2038
2142
|
maxHeight: expanded ? 'none' : (7.2 * zoom) + 'em', overflow: 'hidden',
|
|
2039
2143
|
},
|
|
2040
2144
|
}, body) : null,
|
|
2041
|
-
(canExpand || (c.full || '').length > 300) ? h('button', {
|
|
2145
|
+
(canExpand || (typeof c.fullLen === 'number' ? c.fullLen : (c.full || '').length) > 300) ? h('button', {
|
|
2042
2146
|
'data-dam-btn': '', onClick: function (e) { e.stopPropagation(); if (onToggle) onToggle(c.id) },
|
|
2043
2147
|
style: { marginTop: '3px', padding: '1px 6px', fontSize: (10 * zoom) + 'px', opacity: .7 },
|
|
2044
2148
|
}, expanded ? (locale === 'zh' ? '收起' : 'collapse') : (locale === 'zh' ? '展开全文' : 'expand')) : null,
|
|
@@ -2458,7 +2562,8 @@ window.__ModuleLoader__.load({
|
|
|
2458
2562
|
? h('div', { key: 'sg', style: { display: 'flex', gap: '4px', flexWrap: 'wrap', marginBottom: '8px' } },
|
|
2459
2563
|
drawer.sectionTags.map(function (tg, i) { return h('span', { key: i, 'data-dam-chip': '', style: { fontSize: '10px', padding: '1px 5px', borderRadius: '3px', background: 'rgba(76,141,255,.18)' } }, tg) }))
|
|
2460
2564
|
: null,
|
|
2461
|
-
|
|
2565
|
+
// ★v3.1.4:改为挂载子组件(hook 收进去)——原写法在条件分支里调 hook ⇒ React #310 白屏
|
|
2566
|
+
h(KanbanDrawerBody, { key: 'body', drawer: drawer }),
|
|
2462
2567
|
].map(function (node, i) {
|
|
2463
2568
|
// 头部固定、正文滚动: 把内容各自包一层; 正文那层给 flex:1 + overflow:auto
|
|
2464
2569
|
if (i === 0) return h('div', { key: 'headwrap', style: { padding: '12px 14px 8px', flexShrink: 0 } }, node)
|
|
@@ -3813,7 +3918,9 @@ window.__ModuleLoader__.load({
|
|
|
3813
3918
|
if (migBusy) return
|
|
3814
3919
|
opts = opts || {}
|
|
3815
3920
|
setMigBusy('export'); setMigErr(''); setMigNote('')
|
|
3816
|
-
|
|
3921
|
+
// ★v3.1.2 修:此前只发 outPath,宿主拿不到工作区 ⇒ 恒返回 missing-ws(用户实测)。
|
|
3922
|
+
// 本文件既有 currentWs()(跟随 GUI 切换工作区),导出必须显式带上。
|
|
3923
|
+
apiPost(API.migrateExport, { ws: currentWs() || undefined, outPath: migOut || undefined }).then(function (j) {
|
|
3817
3924
|
setMigBusy('')
|
|
3818
3925
|
if (!j || j.ok === false) { migFail(t('migExport'), j, null); return }
|
|
3819
3926
|
var s = j.stats || {}
|
|
@@ -3830,7 +3937,7 @@ window.__ModuleLoader__.load({
|
|
|
3830
3937
|
if (migBusy) return
|
|
3831
3938
|
if (!migPack) { setMigErr(t('migPickPack')); return }
|
|
3832
3939
|
setMigBusy('preview'); setMigErr(''); setMigNote(''); setMigPlan(null); setMigResult(null)
|
|
3833
|
-
apiPost(API.migrateInspect, { packPath: migPack }).then(function (j) {
|
|
3940
|
+
apiPost(API.migrateInspect, { packPath: migPack, targetWs: currentWs() || undefined }).then(function (j) {
|
|
3834
3941
|
setMigBusy('')
|
|
3835
3942
|
if (!j || j.ok === false) { migFail(t('migPreview'), j, null); return }
|
|
3836
3943
|
var p = j.plan || {}
|
|
@@ -3843,7 +3950,7 @@ window.__ModuleLoader__.load({
|
|
|
3843
3950
|
if (migBusy) return
|
|
3844
3951
|
if (!migPack) { setMigErr(t('migPickPack')); return }
|
|
3845
3952
|
setMigBusy('apply'); setMigErr(''); setMigNote('')
|
|
3846
|
-
apiPost(API.migrateImport, { packPath: migPack, onConflict: migConflict }).then(function (j) {
|
|
3953
|
+
apiPost(API.migrateImport, { packPath: migPack, targetWs: currentWs() || undefined, onConflict: migConflict }).then(function (j) {
|
|
3847
3954
|
setMigBusy('')
|
|
3848
3955
|
if (!j || j.ok === false) { migFail(t('migApply'), j, null); return }
|
|
3849
3956
|
setMigResult(j)
|
|
@@ -3866,7 +3973,7 @@ window.__ModuleLoader__.load({
|
|
|
3866
3973
|
.then(function (j) {
|
|
3867
3974
|
var reason = (j && (j.reason || (j.ok === false ? 'rejected' : 'ok'))) || 'done'
|
|
3868
3975
|
if (j && j.ok === false && j.reason === 'no-doc-store') {
|
|
3869
|
-
reason = locale === 'zh' ? '记忆锚定索引未启用:请在 设置 →
|
|
3976
|
+
reason = locale === 'zh' ? '记忆锚定索引未启用:请在 设置 → 语义记忆总开关 开启「记忆锚定索引」后重试;或忽略此提示(不影响记忆读写与检索)' : 'anchor index disabled: enable "Memory anchor index" under Settings → Semantic engine, or ignore (read/write/recall unaffected)'
|
|
3870
3977
|
}
|
|
3871
3978
|
setMsg(action + ': ' + reason)
|
|
3872
3979
|
if (onDone) onDone(j)
|
|
@@ -3882,7 +3989,7 @@ window.__ModuleLoader__.load({
|
|
|
3882
3989
|
var rows = []
|
|
3883
3990
|
if (data.indexEnabled === false) {
|
|
3884
3991
|
rows.push(h('div', { 'data-dam-hint': '', style: { marginTop: '6px', color: 'var(--dsw-alias-state-warn-primary, #e8c584)' } },
|
|
3885
|
-
locale === 'zh' ? '⚠ 记忆锚定索引未启用:语料健康不做 sidecar 比对(无 stale 可修)。如需「修复 stale / 删除记忆」,请到 设置 →
|
|
3992
|
+
locale === 'zh' ? '⚠ 记忆锚定索引未启用:语料健康不做 sidecar 比对(无 stale 可修)。如需「修复 stale / 删除记忆」,请到 设置 → 语义记忆总开关 开启「记忆锚定索引」。此提示不影响记忆读写与检索。' : '⚠ Memory anchor index disabled: corpus health performs no sidecar comparison (nothing stale). To use repair/delete, enable "Memory anchor index" under Settings → Semantic engine. Read/write/recall are unaffected.'))
|
|
3886
3993
|
}
|
|
3887
3994
|
rows.push(h('div', { 'data-dam-hint': '', style: { marginTop: '8px' } }, t('storageScanHint')))
|
|
3888
3995
|
rows.push(h(Card, { title: (locale === 'zh' ? '语料健康' : 'Corpus health') + ' (' + counts.ok + '/' + counts.total + ' ok)' },
|
|
@@ -5857,7 +5964,7 @@ function WorkspaceTab() {
|
|
|
5857
5964
|
text: locale === 'zh' ? '词法检索(0GB)永远可用作保底;内置语义引擎(约 130MB 量化模型)显著提升召回;进阶 Python 引擎(BGE-M3,约 563MB)面向深度用户。以下为自动检测结果,可在此直接安装。另有一个与隐私相关的检索信号开关:'
|
|
5858
5965
|
: 'Lexical search (0GB) is the always-on floor; the built-in engine (~130MB quantized model) boosts recall; the advanced Python engine (BGE-M3, ~563MB) is optional. Live detection below — install right here. One privacy-related retrieval switch:',
|
|
5859
5966
|
toggles: [
|
|
5860
|
-
{ key: 'reasoningObserverEnabled', name: locale === 'zh' ? '思维链监听' : 'Reasoning observer', sub: locale === 'zh' ? '
|
|
5967
|
+
{ key: 'reasoningObserverEnabled', name: locale === 'zh' ? '思维链监听' : 'Reasoning observer', sub: locale === 'zh' ? '监听模型思维链分段作为检索信号(默认开;内容比可见输出更敏感,不需要可在此关掉)' : 'Watch model CoT segments as a retrieval signal (default ON; more sensitive than visible output — turn off here if unwanted)', def: false, where: locale === 'zh' ? '自动记忆引擎' : 'Semantic engine' },
|
|
5861
5968
|
] },
|
|
5862
5969
|
{ art: 'radar', core: '', kicker: locale === 'zh' ? '唤起与固化' : 'ACTIVATION',
|
|
5863
5970
|
title: locale === 'zh' ? '该出手时才出手' : 'Interrupt only when it matters',
|
|
@@ -5868,7 +5975,7 @@ function WorkspaceTab() {
|
|
|
5868
5975
|
{ key: 'autoConsolidate', name: locale === 'zh' ? '记忆固化(自动沉淀)' : 'Memory consolidation', sub: locale === 'zh' ? '每轮对话结束自动把结论沉淀进每日日志与记忆店(推荐开)' : 'Consolidate conclusions into the log & stores each turn (recommended)', rec: true, where: locale === 'zh' ? '自动化' : 'Automation' },
|
|
5869
5976
|
// ★2026-09-22 改键(设置页缺口审计 P0-2):旧键 procedurePromotionEnabled 因 DEFAULT_CONFIG
|
|
5870
5977
|
// 恒供给布尔 procedureInjectEnabled 而**结构性不可达** ⇒ 该开关此前是摆设(会翻面、写盘成功、宿主读不到)。
|
|
5871
|
-
{ key: 'procedureInjectEnabled', name: locale === 'zh' ? '技能固化与注入' : 'Skill crystallization', sub: locale === 'zh' ? '重复流程固化为 checklist
|
|
5978
|
+
{ key: 'procedureInjectEnabled', name: locale === 'zh' ? '技能固化与注入' : 'Skill crystallization', sub: locale === 'zh' ? '重复流程固化为 checklist 自动附上(本开关只管「附不附」;晋升审批在「唤起回顾」页,与本开关无关)' : 'Turn repeated flows into auto-attached checklists (this switch only controls attaching; promotion review lives in the Recall review tab and is unrelated)', where: locale === 'zh' ? '记忆中枢' : 'Memory Hub' },
|
|
5872
5979
|
// ★T10(2026-09-20):机械 procedure 切片开关。
|
|
5873
5980
|
// 背景:`crossFeed()` 会把 episode 意图**机械截断**成技能名与步骤(无模型介入),
|
|
5874
5981
|
// 产出的观察行「既不像技能名也不像步骤」——用户报「审批里看不懂」的来源。
|
|
@@ -5957,8 +6064,9 @@ function WorkspaceTab() {
|
|
|
5957
6064
|
try {
|
|
5958
6065
|
apiGet(API.updateCheck).then(function (d) {
|
|
5959
6066
|
var cur = (d && d.current) || '2.1.0'
|
|
5960
|
-
//
|
|
5961
|
-
|
|
6067
|
+
// ★v3.1.3:**动态取最新版本**(此前硬编码 '2.1.0' ⇒ 关掉向导永远弹 2.1.0 的老卡)。
|
|
6068
|
+
// 与 :~7280 那处已正确的写法同源;兜底仍是 '2.1.0'(CHANGELOG 为空也不崩)。
|
|
6069
|
+
var latestKey = Object.keys(CHANGELOG).reduce(function (a, b) { return cmpVersion(b, a) > 0 ? b : a }, '2.1.0')
|
|
5962
6070
|
openDialog({ kind: 'update', versions: [{ version: latestKey, items: CHANGELOG[latestKey] || CHANGELOG['2.1.0'] }], currentVersion: cur })
|
|
5963
6071
|
try { localStorage.setItem('dsh-auto-memory.seenVersion', cur) } catch (e5) {}
|
|
5964
6072
|
}).catch(function () {
|
|
@@ -6058,6 +6166,19 @@ function WorkspaceTab() {
|
|
|
6058
6166
|
return h('div', { key: k }, '· ', h('b', null, k), ' —— ' + whereGroups[k].join(locale === 'zh' ? ' / ' : ' / '))
|
|
6059
6167
|
}),
|
|
6060
6168
|
h('div', null, '· ', h('b', null, locale === 'zh' ? '面板页签' : 'Panel tabs'), locale === 'zh' ? ' —— 唤起回顾(决策打分)/ 存储管理(扫描修复)' : ' — Recall review / Storage tools'))) : null),
|
|
6169
|
+
// ★v3.1.3:末页赞助/贡献入口(用户要求「两个小按钮 + 简短注释,不破坏原有结构」)。
|
|
6170
|
+
// 作为 where 的**兄弟节点追加**;文案走 inline locale(与 TOUR_STEPS 全体现有写法一致),
|
|
6171
|
+
// 不新增 i18n 键 ⇒ 零 i18n 表改动。
|
|
6172
|
+
step.final ? h('div', { 'data-dam-tour-links': '' },
|
|
6173
|
+
h('a', { href: 'https://htmlpreview.github.io/?https://github.com/Aik358/dsh-auto-memory/blob/main/docs/CONTRIBUTORS.html', target: '_blank', rel: 'noopener noreferrer', 'data-dam-tour-link': '' },
|
|
6174
|
+
locale === 'zh' ? '贡献者与赞助' : 'Contributors & Sponsors'),
|
|
6175
|
+
h('a', { href: 'https://api.dshapi.icu/register?aff=HJU27P7JL39N', target: '_blank', rel: 'noopener noreferrer', 'data-dam-tour-link': '' },
|
|
6176
|
+
locale === 'zh' ? 'DSH API 中转站' : 'DSH API relay'),
|
|
6177
|
+
// ★v3.1.4 批 J:第三个按钮 = QQ 交流群(链接与 README / CONTRIBUTORS 同源,不新造)
|
|
6178
|
+
h('a', { href: 'https://qm.qq.com/q/v7Asxn6vPa', target: '_blank', rel: 'noopener noreferrer', 'data-dam-tour-link': '' },
|
|
6179
|
+
locale === 'zh' ? 'QQ 交流群' : 'QQ group'),
|
|
6180
|
+
h('div', { 'data-dam-tour-links-note': '' },
|
|
6181
|
+
locale === 'zh' ? '感谢为本项目出力的贡献者与基础设施赞助方。' : 'Thanks to our contributors and infrastructure sponsors.')) : null,
|
|
6061
6182
|
h('div', { 'data-dam-tour-dots': '' },
|
|
6062
6183
|
TOUR_STEPS.map(function (s, si) {
|
|
6063
6184
|
return h('button', { key: si, 'data-dam-tour-dot': '', 'data-on': String(si === tourStep),
|
|
@@ -6930,6 +7051,9 @@ function WorkspaceTab() {
|
|
|
6930
7051
|
// 2026-09-22 补接线(设置页缺口审计 P0-1):procedureInjectEnabled 才是宿主真读的总闸
|
|
6931
7052
|
// (procedure-switch.js 先判它);此前设置页只有旧键 ⇒ 用户改了也无效(灰控件)。
|
|
6932
7053
|
field(t('fProcInject'), h('input', { type: 'checkbox', 'data-dam-key': 'procedureInjectEnabled', checked: cfg.procedureInjectEnabled !== false, onChange: function (e) { set('procedureInjectEnabled', e.target.checked) } }), t('fProcInjectHint')),
|
|
7054
|
+
// ★v3.1.3 补控件(引导审计 K-3):本键功能是通的(index.js 有 getter → memory-hub 消费),
|
|
7055
|
+
// 但此前**只有向导里有控件** ⇒ 用户在向导关掉后无处回改。与 procedureInjectEnabled 同节。
|
|
7056
|
+
field(locale === 'zh' ? '机械流程切片' : 'Mechanical flow slicing', h('input', { type: 'checkbox', 'data-dam-key': 'hubMechanicalProcedureFeedEnabled', checked: cfg.hubMechanicalProcedureFeedEnabled === true, onChange: function (e) { set('hubMechanicalProcedureFeedEnabled', e.target.checked) } }), locale === 'zh' ? '把情节意图机械截断成"技能"(无模型介入、可读性差)。关=只保留模型自己写的技能(推荐关)。' : 'Truncates episode intent into "skills" with no model involvement (poor readability). Off = only model-authored skills (recommended).'),
|
|
6933
7057
|
field(t('fProcLevel'), h('select', { 'data-dam-select': '', value: cfg.procedureActiveLevel || 'checklist', onChange: function (e) { set('procedureActiveLevel', e.target.value) } },
|
|
6934
7058
|
h('option', { value: 'checklist' }, locale === 'zh' ? 'checklist 完整步骤' : 'checklist (full steps)'),
|
|
6935
7059
|
h('option', { value: 'excerpt' }, locale === 'zh' ? 'excerpt 摘要' : 'excerpt (summary)'),
|
|
@@ -7060,6 +7184,11 @@ function WorkspaceTab() {
|
|
|
7060
7184
|
h('span', { style: { flex: 1 } }, verInfo ? (verInfo.current || '?') + (verInfo.latest ? ' → ' + verInfo.latest + (verInfo.upToDate ? ' ' + t('upToDate') : ' ' + t('hasUpdate')) : '') : (checkingUpdate ? t('checking') : '—')),
|
|
7061
7185
|
h('button', { 'data-dam-btn': '', onClick: checkUpdate, disabled: checkingUpdate }, checkingUpdate ? t('checking') : t('checkUpdate')),
|
|
7062
7186
|
(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,
|
|
7187
|
+
// ★v3.1.2:dev-link(开发树挂载)无法「一键更新」,但也必须让用户看见线上是否有新版 ——
|
|
7188
|
+
// 此前此处恒为 null,用户既看不到按钮也看不到「有新版」,反馈「按钮消失且不知道为什么」。
|
|
7189
|
+
(verInfo && verInfo.installKind === 'dev-link' && verInfo.latest && verInfo.devVersion && verInfo.latest !== verInfo.devVersion)
|
|
7190
|
+
? h('span', { 'data-dam-hint': '', style: { marginLeft: '6px' } }, (locale === 'zh' ? '开发树 v' : 'dev tree v') + verInfo.devVersion + ' → ' + (locale === 'zh' ? '线上 v' : 'registry v') + verInfo.latest + (locale === 'zh' ? ',请同步开发源码后重新构建' : ' — sync source and rebuild'))
|
|
7191
|
+
: null,
|
|
7063
7192
|
upMsg ? h('span', { 'data-dam-hint': '' }, upMsg) : null),
|
|
7064
7193
|
t('versionCmdHint') + (verInfo && verInfo.error ? ' ' + t('versionError') + verInfo.error : '') + (verInfo && verInfo.installKind === 'dev-link' ? ' ' + t('devLinkHint') : '') + (verInfo && !verInfo.installKind ? ' ' + t('noProfileHint') : '')),
|
|
7065
7194
|
field(locale === 'zh' ? '交流群' : 'Community', h('div', { 'data-dam-row': '' },
|