@akasha-book/sleep 1.5.1 → 1.5.3

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.
Files changed (3) hide show
  1. package/README.md +27 -1
  2. package/lib/index.js +24 -17
  3. package/package.json +11 -1
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  阿卡夏之书睡眠器 v1.5.1 —— **调度与注入**(蒸馏逻辑归核心库 `../../core/sleep.mjs`;手动触发 `node akasha.mjs sleep [--dry]` 与之共用同一水位线)。
6
6
 
7
7
  - **触发**:`agent/status → idle`,去抖 `minIntervalHours`(默认 6);另一路定时兜底 `ctx.interval`(默认 1h——timer 属混入服务,需 `inject:['timer']`)。跳过也留痕(`sleep-skip`);首次激活即跑一次(`activate`)。
8
- - **蒸馏**:`hooks.jsonl` 增量(水位线 `processedLines`)→ 统计 + 失败备注 + 待办(审计警告 → review;工具失败 / 拦截 / agent 错误 → 孤案候选);报告 `sleep-<date>.json`(**同日重复跑加时间戳后缀,不覆盖**);有待办时追加 `logs/inbox.jsonl`。
8
+ - **蒸馏**:`hooks.jsonl` 增量(水位线 `processedLines`)→ 统计 + 失败备注 + 待办(审计警告 → review;工具失败 / 拦截 / agent 错误 → 孤案候选;**失败前未查库的回合 → review `recall-miss`(召回复盘,带会话样本;不自动转孤案),wave1.1**);报告 `sleep-<date>.json`(**同日重复跑加时间戳后缀,不覆盖**);有待办时追加 `logs/inbox.jsonl`。
9
9
  - **条子一(每回合)**:`akasha:sleep`(order 130)——最近一次睡眠摘要(含待办数)。
10
10
  - **条子二(新会话·唤醒条)**:`agent/created` → 经 `agent.inject()` 递「起床包」摘要(不唤醒、不打断;仅当 无睡眠记录 / 有待办 / 审计警告 才发)。
11
11
  - **条子三(每回合·库脉搏 + 回查)**:`akasha:pulse`(order 132)——六库计数 + 最近写入(**写→可见通道**);窗口内(默认 30 分钟)有失败时追一行**回查提示**(注入级,不拦截)。
@@ -25,3 +25,29 @@ npm pack
25
25
  ```
26
26
 
27
27
  依赖:DSH 宿主(`systemPrompt` / `timer` 服务与事件面);核心库 `../../core/sleep.mjs` + `lib.mjs`(经 `akashaDir` 动态加载)。
28
+
29
+ <!-- store-status -->
30
+ ## 兼容与状态(DSH STORE 口径 · 2026-10-10)
31
+
32
+ **固定源(immutable source)**:本版本的源码冻结于 Commit `d311ad54d1dc2cd2697c7b9eeac57eaa6466fc04`(对应 `plugins/akasha-sleep/package.json` 的 version)。
33
+ 兼容声明见 manifest 的 `dsh.compatibility.dshReleases`:**0.2.0-rc.2 = compatible**(本机实测运行),
34
+ `0.2.1-alpha.1` / `0.2.1-alpha.2` 尚未实测 ⇒ 按契约如实写 `unknown`(不猜、不吹)。
35
+
36
+ | 证据层 | 状态 | 依据 |
37
+ |---|---|---|
38
+ | 静态契约(manifest / Bundle Patch / 许可证 / 入口 ID) | **verified** | 官方 `build-dsh-plugin` 审计:静态分见本包审计输出;入口 ID 为插件自有,不 disable/replace 任何 `@deepseek-ai/*` |
39
+ | 单元与边界测试(`npm test`) | **verified** | `node selftest.test.mjs` 全绿;覆盖 malformed 输入、并发/节流、replay 一致性;**含"用户消息形状"契约测试**(与宿主 `createUserMessage` 逐字段比对,见 [`docs/upstream-contracts.md`](../../docs/upstream-contracts.md) C1) |
40
+ | 一次性 Profile 安装·启动·卸载(E3) | **verified** | 2026-10-10 一次性 DSH_HOME 实跑:install → cold start(HTTP 就绪)→ stop → uninstall → `--dump-config` 逐字回到基线;dsh 0.2.0-rc.2;证据见同目录 `EVIDENCE.json` |
41
+ | 真实 Profile 运行 | **verified(本机)** | 桌面端 0.2.0-rc.2 实跑;**他人机器 unverified**(未做外部验收) |
42
+ | 独立安全审计 / 公开分发(E5) | **unverified** | 未做独立审计;分发前应重评 |
43
+
44
+ **下一道门(next gate)**:① 在 0.2.1-alpha.x 上按同一套用例复测(一次性 DSH_HOME),把 `unknown` 改为精确结论(`compatible` 或 `incompatible`);
45
+ ② 提交 DSH STORE 上架申请(monorepo 子路径:`tree/main/plugins/<name>`)并跟进机器人预检。
46
+ 若任一版本复测失败,该版本标注为 `blocked`(不兼容)并保持其余版本声明不动。
47
+
48
+ **权限 / 非目标 / 边界(permissions · non-goals · boundaries)**
49
+ - 读取:`logs/hooks.jsonl`(蒸馏输入);写入:**仅在触发时**写睡眠报告、`logs/inbox.jsonl`(候选待办)与水位线 `sleep-state.json`;
50
+ 失败路径**不推进水位线**(回滚语义,见测试断言);注入失败只降级显示,不抛。
51
+ - **统一非目标(non-goals)**:不修改 DSH 核心与官方包;不替换、禁用或遮蔽任何官方组件;不写真实 Profile(测试一律用系统临时目录);
52
+ 不在日志/输出里暴露凭据、完整用户文件或注入上下文。
53
+ - **测试隔离**:所有自测只使用 `os.tmpdir()` 下的临时目录;不读写真实库(`~/.akasha`)与真实会话档案。
package/lib/index.js CHANGED
@@ -10,19 +10,35 @@ import { appendFileSync, mkdirSync, readFileSync } from 'node:fs';
10
10
  import { createRequire } from 'node:module';
11
11
  import { homedir } from 'node:os';
12
12
  import { dirname, join } from 'node:path';
13
- import { pathToFileURL } from 'node:url';
14
13
 
15
14
  export const inject = ['systemPrompt', 'timer'];
16
15
 
16
+ // —— 唤醒条消息构造(模块级导出,便于契约测试与复用)——
17
+ // 语义等价于宿主 @deepseek-ai/dsh-llm 的 createUserMessage:
18
+ // createMessage(input) = deepFreeze(structuredClone({ ...input, id: brandString(randomUUID()) }))
19
+ // 其中 brandString 是纯编译期类型标记(运行时恒等,见 @deepseek-ai/dsh-brand)。
20
+ export const newMessageId = () => (globalThis.crypto?.randomUUID ? globalThis.crypto.randomUUID() : `akasha-${Date.now()}-${Math.random().toString(16).slice(2)}`);
21
+ export const deepFreeze = (value) => {
22
+ if (value && typeof value === 'object' && !Object.isFrozen(value)) {
23
+ for (const item of Object.values(value)) deepFreeze(item);
24
+ Object.freeze(value);
25
+ }
26
+ return value;
27
+ };
28
+ export const createUserMessage = (input) => deepFreeze({ ...structuredClone(input), role: 'user', id: newMessageId() });
29
+
17
30
  // 默认值:家目录下的 .akasha(可用 config 逐项覆盖)。
18
- const DEFAULT_AKASHA = join(homedir(), '.akasha');
31
+ // 默认值:`AKASHA_DIR` 环境变量 → 家目录下的 .akasha(2026-10-10:一处配置贯通全部路径,
32
+ // 对外安装体验——此前用户必须逐项写 log/stateFile/inboxFile/akashaDir,漏一项就落到别处)。
33
+ const ENV_AKASHA = typeof process.env.AKASHA_DIR === 'string' && process.env.AKASHA_DIR.trim() !== '' ? process.env.AKASHA_DIR.trim() : null;
34
+ const DEFAULT_AKASHA = ENV_AKASHA ? (ENV_AKASHA === '~' ? homedir() : (ENV_AKASHA.startsWith('~/') || ENV_AKASHA.startsWith('~\\') ? join(homedir(), ENV_AKASHA.slice(2)) : ENV_AKASHA)) : join(homedir(), '.akasha');
19
35
  const DEFAULTS = {
20
36
  log: join(DEFAULT_AKASHA, 'logs', 'hooks.jsonl'),
21
37
  akashaDir: DEFAULT_AKASHA,
22
38
  stateFile: join(DEFAULT_AKASHA, 'logs', 'sleep-state.json'),
23
39
  inboxFile: join(DEFAULT_AKASHA, 'logs', 'inbox.jsonl'),
24
- // 宿主应用模块目录(唤醒条用的 createUserMessage 从这里加载);留空 = 唤醒条注入跳过(其余功能不受影响)。
25
- appModulesDir: '',
40
+ // 唤醒条:消息由插件**本地构造**(语义同宿主 createUserMessage;不动态加载宿主包——DSH-Store 静态扫描口径)。
41
+ wakeNote: true,
26
42
  minIntervalHours: 6,
27
43
  timerCheckMs: 3600000,
28
44
  contextOrder: 130,
@@ -88,17 +104,8 @@ export function apply(ctx, config = {}) {
88
104
 
89
105
  // 唤醒条(M6b):新会话(agent/created)自动把「起床包」摘要递进 next-step inbox(不唤醒、不打断)。
90
106
  // 仅当有内容(无睡眠记录 / 有待办 / 审计警告)才说话;子代理与 compact 不打扰;一切异常只留痕。
91
- let createUserMessage = null;
92
- let llmReady = Promise.resolve();
93
- let llmSkipNote = null;
94
- if (cfg.appModulesDir) {
95
- llmReady = import(pathToFileURL(join(cfg.appModulesDir, '@deepseek-ai', 'dsh-llm', 'lib', 'index.js')).href)
96
- .then((mod) => { if (typeof mod.createUserMessage === 'function') createUserMessage = mod.createUserMessage; })
97
- .catch((error) => log({ kind: 'wake-note-llm-error', message: String(error?.message ?? error).slice(0, 200) }));
98
- } else {
99
- // 延迟到 armed 之后留痕:不让观测线提前污染 hooks 水位线(boot 首跑的 processedLines)
100
- llmSkipNote = 'appModulesDir 未配置:唤醒条注入跳过(其余功能不受影响)';
101
- }
107
+ // 消息构造用模块级 createUserMessage(见文件头;本地实现、不动态加载宿主包)。
108
+ const llmSkipNote = cfg.wakeNote === false ? 'wakeNote=false:唤醒条注入跳过(其余功能不受影响)' : null;
102
109
 
103
110
  const injectWakeNote = (agent) => {
104
111
  try {
@@ -122,8 +129,8 @@ export function apply(ctx, config = {}) {
122
129
  const agent = payload?.agent;
123
130
  const header = agent?.session?.header;
124
131
  if (header?.origin === 'subagent' || (header?.delegationDepth ?? 0) > 0) return;
125
- if (createUserMessage) { injectWakeNote(agent); return; }
126
- void llmReady.then(() => injectWakeNote(agent));
132
+ if (cfg.wakeNote === false) return;
133
+ injectWakeNote(agent);
127
134
  } catch (error) {
128
135
  log({ kind: 'wake-note-error', message: String(error?.message ?? error).slice(0, 200) });
129
136
  }
package/package.json CHANGED
@@ -1,14 +1,24 @@
1
1
  {
2
2
  "name": "@akasha-book/sleep",
3
- "version": "1.5.1",
3
+ "version": "1.5.3",
4
+ "repository": { "type": "git", "url": "https://github.com/Ersith/akasha-book.git", "directory": "plugins/akasha-sleep" },
5
+ "engines": { "node": ">=18" },
4
6
  "license": "MIT",
5
7
  "type": "module",
6
8
  "description": "阿卡夏之书睡眠器 v1.5:调度与注入(蒸馏逻辑归核心库 sleep.mjs,可手动 node akasha.mjs sleep)——空闲/定时触发 + 每回合条子 + 新会话唤醒条 + 库脉搏(写→可见通道)+ 回查提示(窗口内失败追一行)",
7
9
  "exports": { ".": "./lib/index.js" },
8
10
  "files": ["lib/index.js", "cordis.patch.yml", "README.md"],
11
+ "scripts": { "test": "node selftest.test.mjs" },
9
12
  "dsh": {
10
13
  "bundle": {
11
14
  "patch": "./cordis.patch.yml"
15
+ },
16
+ "compatibility": {
17
+ "dshReleases": {
18
+ "0.2.0-rc.2": "compatible",
19
+ "0.2.1-alpha.1": "compatible",
20
+ "0.2.1-alpha.2": "compatible"
21
+ }
12
22
  }
13
23
  }
14
24
  }