@akasha-book/sleep 0.0.0-stage → 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.
- package/README.md +52 -2
- package/cordis.patch.yml +8 -0
- package/lib/index.js +197 -0
- package/package.json +22 -4
package/README.md
CHANGED
|
@@ -1,3 +1,53 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @akasha-book/sleep
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> 阿卡夏之书(Akasha Book)· 睡眠器插件
|
|
4
|
+
|
|
5
|
+
阿卡夏之书睡眠器 v1.5.1 —— **调度与注入**(蒸馏逻辑归核心库 `../../core/sleep.mjs`;手动触发 `node akasha.mjs sleep [--dry]` 与之共用同一水位线)。
|
|
6
|
+
|
|
7
|
+
- **触发**:`agent/status → idle`,去抖 `minIntervalHours`(默认 6);另一路定时兜底 `ctx.interval`(默认 1h——timer 属混入服务,需 `inject:['timer']`)。跳过也留痕(`sleep-skip`);首次激活即跑一次(`activate`)。
|
|
8
|
+
- **蒸馏**:`hooks.jsonl` 增量(水位线 `processedLines`)→ 统计 + 失败备注 + 待办(审计警告 → review;工具失败 / 拦截 / agent 错误 → 孤案候选;**失败前未查库的回合 → review `recall-miss`(召回复盘,带会话样本;不自动转孤案),wave1.1**);报告 `sleep-<date>.json`(**同日重复跑加时间戳后缀,不覆盖**);有待办时追加 `logs/inbox.jsonl`。
|
|
9
|
+
- **条子一(每回合)**:`akasha:sleep`(order 130)——最近一次睡眠摘要(含待办数)。
|
|
10
|
+
- **条子二(新会话·唤醒条)**:`agent/created` → 经 `agent.inject()` 递「起床包」摘要(不唤醒、不打断;仅当 无睡眠记录 / 有待办 / 审计警告 才发)。
|
|
11
|
+
- **条子三(每回合·库脉搏 + 回查)**:`akasha:pulse`(order 132)——六库计数 + 最近写入(**写→可见通道**);窗口内(默认 30 分钟)有失败时追一行**回查提示**(注入级,不拦截)。
|
|
12
|
+
- **配置**:`akashaDir` / `log` / `stateFile` / `inboxFile` / `appModulesDir`(唤醒条用的宿主模块目录;**留空则跳过并留痕 `wake-note-llm-skip`**)/ `minIntervalHours` / `timerCheckMs` / `contextOrder` / `pulseOrder`。
|
|
13
|
+
- 观测线:`sleep-armed` / `sleep-done` / `sleep-skip` / `sleep-error` / `wake-note` / `wake-note-error` / `wake-note-llm-error` / `wake-note-llm-skip` / `sleep-report-error` / `sleep-state-error` / `sleep-inbox-error`。
|
|
14
|
+
- 自测:`node selftest.mjs`(纯函数 + 桩 ctx 端到端 + 写失败线 + 无核心降级;不碰真实水位线)。
|
|
15
|
+
|
|
16
|
+
## ⚠️ 版本纪律
|
|
17
|
+
|
|
18
|
+
替换已安装包的 JS **无法进程内热更**(模块代缓存)——升级后需重启宿主载入。
|
|
19
|
+
|
|
20
|
+
## 打包 / 安装(DSH 宿主)
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm pack
|
|
24
|
+
# 然后:plugin_manager install_bundle <tgz 绝对路径>(新 bundle 热生效;替换已装包需重启宿主)
|
|
25
|
+
```
|
|
26
|
+
|
|
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/cordis.patch.yml
ADDED
package/lib/index.js
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
// 阿卡夏之书睡眠器 v1.5.1 —— 调度与注入(蒸馏逻辑归核心库 sleep.mjs)。
|
|
2
|
+
// · 触发:agent/status → idle(去抖 minIntervalHours)+ 定时兜底 ctx.interval(默认 1h)
|
|
3
|
+
// · 蒸馏/复核/待办/报告/水位线:核心库 sleepRun —— 手动 `node akasha.mjs sleep` 与之共用同一水位线
|
|
4
|
+
// · 条子一:systemPrompt.context(akasha:sleep)——每回合带最近一次睡眠摘要
|
|
5
|
+
// · 条子二(唤醒条):agent/created → agent.inject 起床包摘要(不唤醒、不打断)
|
|
6
|
+
// · 条子三(库脉搏 + 回查,v1.5):systemPrompt.context(akasha:pulse)——六库计数 + 最近写入;
|
|
7
|
+
// 窗口内(默认 30 分钟)有失败时追一行「回查提示」(错误钩子的注入级动作,不拦截)
|
|
8
|
+
// · 降级:核心库不可用 → sleep-error 观测线 + 条子提示文案,不炸、不失活。
|
|
9
|
+
import { appendFileSync, mkdirSync, readFileSync } from 'node:fs';
|
|
10
|
+
import { createRequire } from 'node:module';
|
|
11
|
+
import { homedir } from 'node:os';
|
|
12
|
+
import { dirname, join } from 'node:path';
|
|
13
|
+
|
|
14
|
+
export const inject = ['systemPrompt', 'timer'];
|
|
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
|
+
|
|
30
|
+
// 默认值:家目录下的 .akasha(可用 config 逐项覆盖)。
|
|
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');
|
|
35
|
+
const DEFAULTS = {
|
|
36
|
+
log: join(DEFAULT_AKASHA, 'logs', 'hooks.jsonl'),
|
|
37
|
+
akashaDir: DEFAULT_AKASHA,
|
|
38
|
+
stateFile: join(DEFAULT_AKASHA, 'logs', 'sleep-state.json'),
|
|
39
|
+
inboxFile: join(DEFAULT_AKASHA, 'logs', 'inbox.jsonl'),
|
|
40
|
+
// 唤醒条:消息由插件**本地构造**(语义同宿主 createUserMessage;不动态加载宿主包——DSH-Store 静态扫描口径)。
|
|
41
|
+
wakeNote: true,
|
|
42
|
+
minIntervalHours: 6,
|
|
43
|
+
timerCheckMs: 3600000,
|
|
44
|
+
contextOrder: 130,
|
|
45
|
+
pulseOrder: 132
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/** 唤醒条是否值得推(有内容才说话):无睡眠记录 / 有待办 / 审计有警告。 */
|
|
49
|
+
export function isWakeNoteworthy(k) {
|
|
50
|
+
return !k.sleep || (k.inbox?.totalItems ?? 0) > 0 || (k.review?.findings ?? []).some((f) => f.level === 'warn');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** 组装「唤醒条」文本(纯函数)。 */
|
|
54
|
+
export function buildWakeNote(k) {
|
|
55
|
+
const lines = ['【阿卡夏·起床包】'];
|
|
56
|
+
lines.push(`库况:canon ${k.library.canon} / mirror ${k.library.mirror} / orphan ${k.library.orphan} / pricing ${k.library.pricing} / lexicon ${k.library.lexicon} / frontier ${k.library.frontier}`);
|
|
57
|
+
lines.push(k.sleep ? `睡眠:${k.sleep.lastRunAt}(${k.sleep.trigger})待办 ${k.sleep.todo}` : '睡眠:无记录(等待首个空闲)');
|
|
58
|
+
if ((k.inbox?.totalItems ?? 0) > 0) lines.push(`待办 inbox:${k.inbox.totalItems} 条(akasha_promote 可转正)`);
|
|
59
|
+
const warns = (k.review?.findings ?? []).filter((f) => f.level === 'warn');
|
|
60
|
+
if (warns.length) lines.push(`审计:${warns.map((f) => f.code + '×' + f.count).join(',')}`);
|
|
61
|
+
lines.push('详情:akasha_kit');
|
|
62
|
+
return lines.join('\n');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function apply(ctx, config = {}) {
|
|
66
|
+
const cfg = { ...DEFAULTS, ...config };
|
|
67
|
+
const require_ = createRequire(import.meta.url);
|
|
68
|
+
const reportDir = join(cfg.akashaDir, 'logs');
|
|
69
|
+
const stateFile = cfg.stateFile || join(reportDir, 'sleep-state.json');
|
|
70
|
+
const inboxFile = cfg.inboxFile || join(reportDir, 'inbox.jsonl');
|
|
71
|
+
|
|
72
|
+
const log = (record) => {
|
|
73
|
+
try {
|
|
74
|
+
mkdirSync(dirname(cfg.log), { recursive: true });
|
|
75
|
+
appendFileSync(cfg.log, JSON.stringify({ ts: new Date().toISOString(), ...record }) + '\n', 'utf8');
|
|
76
|
+
} catch { /* 静默:观测线写不了不拖垮宿主 */ }
|
|
77
|
+
};
|
|
78
|
+
const readState = () => { try { return JSON.parse(readFileSync(stateFile, 'utf8')); } catch { return {}; } };
|
|
79
|
+
|
|
80
|
+
// 核心库(蒸馏逻辑)动态加载:插件只做调度与注入;缺文件时降级留痕(不失活)。
|
|
81
|
+
const core = () => require_(join(cfg.akashaDir, 'sleep.mjs'));
|
|
82
|
+
|
|
83
|
+
const runSleep = (trigger) => {
|
|
84
|
+
try {
|
|
85
|
+
const r = core().sleepRun({ trigger, log: cfg.log, stateFile, inboxFile, reportDir });
|
|
86
|
+
if (!r.ok) { log({ kind: 'sleep-error', trigger, message: String(r.error).slice(0, 300) }); return false; }
|
|
87
|
+
log({ kind: 'sleep-done', trigger, report: r.reportFile, todo: r.todo, counters: r.state?.lastCounters, audit: r.state?.lastAudit });
|
|
88
|
+
return true;
|
|
89
|
+
} catch (error) {
|
|
90
|
+
log({ kind: 'sleep-error', trigger, message: String(error?.message ?? error).slice(0, 300) });
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const maybeSleep = (trigger) => {
|
|
96
|
+
try {
|
|
97
|
+
const verdict = core().shouldSleep(readState(), Date.now(), cfg.minIntervalHours);
|
|
98
|
+
if (!verdict.due) { log({ kind: 'sleep-skip', trigger, sinceHours: verdict.hoursSince }); return; }
|
|
99
|
+
runSleep(trigger);
|
|
100
|
+
} catch (error) {
|
|
101
|
+
log({ kind: 'sleep-error', trigger, message: String(error?.message ?? error).slice(0, 300) });
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// 唤醒条(M6b):新会话(agent/created)自动把「起床包」摘要递进 next-step inbox(不唤醒、不打断)。
|
|
106
|
+
// 仅当有内容(无睡眠记录 / 有待办 / 审计警告)才说话;子代理与 compact 不打扰;一切异常只留痕。
|
|
107
|
+
// 消息构造用模块级 createUserMessage(见文件头;本地实现、不动态加载宿主包)。
|
|
108
|
+
const llmSkipNote = cfg.wakeNote === false ? 'wakeNote=false:唤醒条注入跳过(其余功能不受影响)' : null;
|
|
109
|
+
|
|
110
|
+
const injectWakeNote = (agent) => {
|
|
111
|
+
try {
|
|
112
|
+
if (!agent || typeof agent.inject !== 'function' || !createUserMessage) return;
|
|
113
|
+
const k = require_(join(cfg.akashaDir, 'lib.mjs')).kit();
|
|
114
|
+
if (!isWakeNoteworthy(k)) return;
|
|
115
|
+
const message = createUserMessage({
|
|
116
|
+
content: [{ type: 'text', text: buildWakeNote(k) }],
|
|
117
|
+
source: { kind: 'akasha-wake' }
|
|
118
|
+
});
|
|
119
|
+
agent.inject(message);
|
|
120
|
+
log({ kind: 'wake-note', session: String(agent.id ?? ''), todo: k.inbox?.totalItems ?? 0, auditOk: k.review?.ok ?? null });
|
|
121
|
+
} catch (error) {
|
|
122
|
+
log({ kind: 'wake-note-error', message: String(error?.message ?? error).slice(0, 200) });
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
ctx.on('agent/created', (payload) => {
|
|
127
|
+
try {
|
|
128
|
+
// 2026-10-07 复查:官方 agent/created 的 source 只有 startup/resume;子代理守卫沿用 header.origin / delegationDepth。
|
|
129
|
+
const agent = payload?.agent;
|
|
130
|
+
const header = agent?.session?.header;
|
|
131
|
+
if (header?.origin === 'subagent' || (header?.delegationDepth ?? 0) > 0) return;
|
|
132
|
+
if (cfg.wakeNote === false) return;
|
|
133
|
+
injectWakeNote(agent);
|
|
134
|
+
} catch (error) {
|
|
135
|
+
log({ kind: 'wake-note-error', message: String(error?.message ?? error).slice(0, 200) });
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// 条子:每个新回合的 runtime context 自动带上最近一次睡眠摘要(渲染自核心库,失败安全)。
|
|
140
|
+
ctx.systemPrompt.context({
|
|
141
|
+
name: 'akasha:sleep',
|
|
142
|
+
order: cfg.contextOrder,
|
|
143
|
+
text: () => {
|
|
144
|
+
try { return core().renderContextLine(readState()); }
|
|
145
|
+
catch { return '阿卡夏·睡眠:核心库不可用(akasha\\sleep.mjs 缺失或损坏)。'; }
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// 回查提示(v1.5,错误钩子的注入级动作):进程内记录近期失败(工具 / agent),窗口内幂等渲染。
|
|
150
|
+
const recentFailures = [];
|
|
151
|
+
const noteFailure = (tool) => {
|
|
152
|
+
try {
|
|
153
|
+
recentFailures.push({ ts: Date.now(), tool: String(tool ?? '?') });
|
|
154
|
+
if (recentFailures.length > 20) recentFailures.splice(0, recentFailures.length - 20);
|
|
155
|
+
} catch { /* 静默 */ }
|
|
156
|
+
};
|
|
157
|
+
ctx.on('tools/result', (exec, result) => { if (result?.isError === true) noteFailure(exec?.name); });
|
|
158
|
+
ctx.on('agent/error', () => noteFailure('agent'));
|
|
159
|
+
|
|
160
|
+
// 库脉搏(v1.3;v1.5 起附加回查行):写→可见通道——并行会话 / 脚本写入库后,下一回合即可见并命名新内容。
|
|
161
|
+
ctx.systemPrompt.context({
|
|
162
|
+
name: 'akasha:pulse',
|
|
163
|
+
order: cfg.pulseOrder,
|
|
164
|
+
text: () => {
|
|
165
|
+
try {
|
|
166
|
+
const lib = require_(join(cfg.akashaDir, 'lib.mjs'));
|
|
167
|
+
const lines = [core().renderPulseLine(lib.pulse())];
|
|
168
|
+
const recall = core().renderRecallLine(recentFailures, Date.now());
|
|
169
|
+
if (recall) lines.push(recall);
|
|
170
|
+
return lines.filter(Boolean).join('\n') || null;
|
|
171
|
+
} catch { return null; }
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// 空闲触发(事件失败开放)。
|
|
176
|
+
ctx.on('agent/status', (payload) => {
|
|
177
|
+
try { if (payload?.status === 'idle') maybeSleep('idle'); } catch { /* 静默 */ }
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// 定时兜底:宿主长期不空闲也能按节奏睡。
|
|
181
|
+
// ⚠️ timer 是「混入服务」:访问 ctx.interval 需要 inject:['timer'],否则属性访问本身抛出
|
|
182
|
+
// "cannot get property \"timer\" without inject"——v1.1.0 事故:整个 apply 失败、插件静默失活。
|
|
183
|
+
// ctx.interval 返回的停止函数再挂到本插件自己的 effect 上,卸载即停。
|
|
184
|
+
if (typeof ctx.interval === 'function') {
|
|
185
|
+
try {
|
|
186
|
+
const stop = ctx.interval(() => { try { maybeSleep('timer'); } catch { /* 静默 */ } }, cfg.timerCheckMs);
|
|
187
|
+
ctx.effect(() => () => { try { stop(); } catch { /* 静默 */ } });
|
|
188
|
+
} catch { /* 静默 */ }
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// 首次激活即跑一次,此后按去抖节奏。
|
|
192
|
+
const boot = readState();
|
|
193
|
+
if (!boot.lastRunAt) runSleep('activate');
|
|
194
|
+
|
|
195
|
+
log({ kind: 'sleep-armed', pid: process.pid, minIntervalHours: cfg.minIntervalHours, timerCheckMs: cfg.timerCheckMs });
|
|
196
|
+
if (llmSkipNote) log({ kind: 'wake-note-llm-skip', message: llmSkipNote });
|
|
197
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akasha-book/sleep",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
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" },
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"description": "阿卡夏之书睡眠器 v1.5:调度与注入(蒸馏逻辑归核心库 sleep.mjs,可手动 node akasha.mjs sleep)——空闲/定时触发 + 每回合条子 + 新会话唤醒条 + 库脉搏(写→可见通道)+ 回查提示(窗口内失败追一行)",
|
|
9
|
+
"exports": { ".": "./lib/index.js" },
|
|
10
|
+
"files": ["lib/index.js", "cordis.patch.yml", "README.md"],
|
|
11
|
+
"scripts": { "test": "node selftest.test.mjs" },
|
|
12
|
+
"dsh": {
|
|
13
|
+
"bundle": {
|
|
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
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|