@stardustlc/dsh-dream 0.7.0 → 0.8.0

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/lib/config.d.ts CHANGED
@@ -12,6 +12,15 @@ export interface ResolvedDreamConfig {
12
12
  maxUserMessages: number;
13
13
  /** 梦原料入梦前是否做隐私脱敏(默认 true)。 */
14
14
  maskSecrets: boolean;
15
+ /** 默认开启;辅助模型调用受持久化预算限制。 */
16
+ autoCollect: boolean;
17
+ autoRetrieve: boolean;
18
+ autoMaxCallsPerDay: number;
19
+ autoCooldownMs: number;
20
+ autoMinToolCalls: number;
21
+ autoMaxInputChars: number;
22
+ autoMaxOutputTokens: number;
23
+ autoTimeoutMs: number;
15
24
  }
16
25
  /** 解析并校验插件配置。 */
17
26
  export declare function resolveConfig(raw?: Record<string, unknown> | null, env?: NodeJS.ProcessEnv): ResolvedDreamConfig;
package/lib/config.js CHANGED
@@ -24,5 +24,13 @@ export function resolveConfig(raw, env = process.env) {
24
24
  maxCharsPerSession: clamp(cfg.maxCharsPerSession, 6000, 500, 50000),
25
25
  maxUserMessages: clamp(cfg.maxUserMessages, 5, 1, 20),
26
26
  maskSecrets: cfg.maskSecrets !== false,
27
+ autoCollect: cfg.autoCollect !== false,
28
+ autoRetrieve: cfg.autoRetrieve !== false,
29
+ autoMaxCallsPerDay: clamp(cfg.autoMaxCallsPerDay, 4, 1, 20),
30
+ autoCooldownMs: clamp(cfg.autoCooldownMs, 600000, 1000, 3600000),
31
+ autoMinToolCalls: clamp(cfg.autoMinToolCalls, 2, 1, 50),
32
+ autoMaxInputChars: clamp(cfg.autoMaxInputChars, 12000, 1000, 20000),
33
+ autoMaxOutputTokens: clamp(cfg.autoMaxOutputTokens, 1200, 200, 2000),
34
+ autoTimeoutMs: clamp(cfg.autoTimeoutMs, 30000, 1000, 60000),
27
35
  };
28
36
  }
package/lib/index.d.ts CHANGED
@@ -36,3 +36,4 @@ export * from './bridge.js';
36
36
  export * from './knowledge.js';
37
37
  export * from './knowledge-store.js';
38
38
  export * from './retrieval.js';
39
+ export * from './automatic.js';
package/lib/index.js CHANGED
@@ -10,6 +10,7 @@ import { resolveConfig } from './config.js';
10
10
  import { buildDreamTools } from './tools.js';
11
11
  import { installDreamWeb } from './web.js';
12
12
  import { installDreamActions } from './web-actions.js';
13
+ import { installAutomaticDream } from './automatic.js';
13
14
  /** cordis 服务注入:要用 ctx.tools 与 ctx.skills。 */
14
15
  export const name = 'dream';
15
16
  export const inject = ['tools', 'skills'];
@@ -60,6 +61,7 @@ export function apply(ctx, config) {
60
61
  installDreamWeb(ctx, { journalDir: cfg.journalDir, config: cfg });
61
62
  installDreamActions(ctx, { config: cfg });
62
63
  }
64
+ installAutomaticDream(ctx, cfg);
63
65
  if (typeof ctx.on === 'function') {
64
66
  ctx.on('dispose', () => {
65
67
  for (const dispose of disposers)
@@ -76,3 +78,4 @@ export * from './bridge.js';
76
78
  export * from './knowledge.js';
77
79
  export * from './knowledge-store.js';
78
80
  export * from './retrieval.js';
81
+ export * from './automatic.js';
@@ -1,5 +1,6 @@
1
1
  import { type ResolvedDreamConfig } from './config.js';
2
2
  export declare const DREAM_ACTION_ROUTE = "/api/dsh-dream/actions";
3
+ export declare const DREAM_AUTOMATIC_ROUTE = "/api/dsh-dream/automatic";
3
4
  type Options = {
4
5
  journalDir?: string;
5
6
  config?: Record<string, unknown> | ResolvedDreamConfig | null;
@@ -9,7 +9,9 @@ import { maskSecrets } from './mask.js';
9
9
  import { buildDreamTools, executeDreamReview } from './tools.js';
10
10
  import { rollbackBridge } from './bridge.js';
11
11
  import { maskDeep } from './web.js';
12
+ import { automaticRuntime } from './automatic.js';
12
13
  export const DREAM_ACTION_ROUTE = '/api/dsh-dream/actions';
14
+ export const DREAM_AUTOMATIC_ROUTE = '/api/dsh-dream/automatic';
13
15
  const BODY_LIMIT = 64 * 1024;
14
16
  const PREVIEW_LIFETIME = 10 * 60 * 1000;
15
17
  const MAX_PREVIEWS = 100;
@@ -102,6 +104,15 @@ export function createDreamActionHandler(options = {}) {
102
104
  if (request.signal.aborted)
103
105
  return fail(409, 'cancelled', '操作已取消');
104
106
  const operation = text(body, 'operation');
107
+ if (operation === 'automatic') {
108
+ if ((body.enabled !== undefined && typeof body.enabled !== 'boolean') || (body.retrievalEnabled !== undefined && typeof body.retrievalEnabled !== 'boolean') || (body.enabled === undefined && body.retrievalEnabled === undefined))
109
+ throw new KnowledgeError('invalid', '自动功能开关必须是布尔值');
110
+ const runtime = automaticRuntime(cfg);
111
+ if (!runtime)
112
+ return fail(503, 'unavailable', '自动功能尚未就绪,请刷新或重新启用插件');
113
+ runtime.control({ enabled: body.enabled, retrievalEnabled: body.retrievalEnabled });
114
+ return json(200, { ok: true, automatic: runtime.status() });
115
+ }
105
116
  if (operation === 'review') {
106
117
  if (!['accept', 'reject', 'reopen', 'mark-stale', 'resolve-conflict'].includes(String(body.action)))
107
118
  throw new KnowledgeError('invalid', '不支持此页面审阅动作');
@@ -171,5 +182,9 @@ export function installDreamActions(ctx, options = {}) {
171
182
  if (typeof host.connection?.fetch?.register !== 'function')
172
183
  return;
173
184
  host.connection.fetch.register({ path: DREAM_ACTION_ROUTE, methods: ['POST'], requestBody: 'buffered', fetch });
185
+ const cfg = { ...resolveConfig(options.config), ...(options.journalDir === undefined ? {} : { journalDir: options.journalDir }) };
186
+ host.connection.fetch.register({ path: DREAM_AUTOMATIC_ROUTE, methods: ['GET'], requestBody: 'buffered', fetch: async () => json(200, {
187
+ ok: true, automatic: automaticRuntime(cfg)?.status() ?? { available: false, enabled: false, retrievalEnabled: false, problem: 'unavailable' },
188
+ }) });
174
189
  });
175
190
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stardustlc/dsh-dream",
3
- "version": "0.7.0",
4
- "description": "DSH 做梦与经验记忆:核验来源、审阅经验,预览写入 AGENTS.md 并支持回滚;附梦境日记面板,默认隐私脱敏,零运行时依赖。",
3
+ "version": "0.8.0",
4
+ "description": "回顾会话、保存反思,并把经过核验和审阅的经验用于后续任务。",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "types": "lib/index.d.ts",
@@ -20,7 +20,8 @@
20
20
  "cordis.patch.yml",
21
21
  "README.md",
22
22
  "README.en.md",
23
- "CHANGELOG.md"
23
+ "CHANGELOG.md",
24
+ "docs"
24
25
  ],
25
26
  "scripts": {
26
27
  "build": "tsc -p tsconfig.json",
@@ -9,6 +9,8 @@ description: 做梦协议:任务开始取回适用经验,长任务收尾沉
9
9
 
10
10
  但「梦」和「经验」是两条流水线:**第一人称感悟**是主观的,进梦境日记;**技术经验**必须可执行、有条件、有证据,先进候选,再经审阅才可能被任务检索取用。
11
11
 
12
+ 插件会在符合条件的真人主会话完成后,按预算自动整理有来源的项目候选,并在相关新任务前回用已采纳经验。普通闲聊、子代理和失败轮次跳过;新输入取消整理。用户无需记住触发词或手工填写经验。自动候选从未采纳;日记写入、采纳与规则应用是不同操作。宿主缺少自动接口或用户关闭功能时,使用下述工具流程。
13
+
12
14
  ## 两条流水线(不要混)
13
15
 
14
16
  | | 第一人称感悟(梦) | 技术经验(lesson) |
@@ -20,7 +22,7 @@ description: 做梦协议:任务开始取回适用经验,长任务收尾沉
20
22
 
21
23
  ## 一、任务前:取回上下文(dream_context)
22
24
 
23
- - 任务涉及过往代码、用户偏好或踩过的坑时,先调 `dream_context`:给 `query`,能给就给 `projectId` / `workspaceRoot`,以及 `packageName` + `packageVersion`(`applicability.versions` 只在该包名被识别时参与判定)。审阅候选时显式传 `includeCandidates: true`。
25
+ - 已有 Dream reviewed memory 动态上下文时,先检查其中条件与当前请求,不必重复检索相同经验。需要版本条件、不同关键词或自动取回关闭时,调 `dream_context`:给 `query`、`projectId` / `workspaceRoot`,以及实际确认的 `packageName` + `packageVersion`。自动取回不知道依赖版本时会扣留所有版本限定经验。审阅候选时显式传 `includeCandidates: true`。
24
26
  - **预算:默认 5 条 / 3000 字符**(工具硬上限 20 条 / 20000 字符)。取回少量真正适用的即可;没有相关经验就接受空结果,不要为了「显得有记忆」硬塞。
25
27
  - `dream_context` 是只读的:不写盘,只返回标题、适用条件、行动建议、证据摘要与「为什么与当前任务相关」。
26
28
  - 未知当前项目时只会返回全局经验;不会跨项目扫描。候选(candidate)**可被检索到**(显式 `includeCandidates: true`,用于审阅候选),但**默认不注入任务建议**(`includeCandidates: false` 时记 `skipped: candidate-hold`;`independentSupportCount === 0` 且非 `usable` 的记 `no-evidence`),且排在可用经验之后——未经审阅不得当作已证实结论。
@@ -65,7 +67,7 @@ description: 做梦协议:任务开始取回适用经验,长任务收尾沉
65
67
  - 想查看/审阅候选、处理冲突 → `dream_review`;
66
68
  - attach-evidence 只补充核验后的证据,不自动采纳;resolve-conflict 必须给 resolution、affectedIds、note,整组原子更新;reopen 将驳回经验重新送审。
67
69
 
68
- - 面板查看:「设置 → 梦境日记」里有只读的梦境时间线与「经验」区块(状态、适用条件、证据摘要、最近核验时间),面板不提供任何写操作。
70
+ - 面板操作:「设置 → 梦境日记」可浏览时间线、查看来源、采纳或驳回候选、标记待复核、处理冲突与记录使用反馈。规则变更单独预览后应用,也可确认回滚;真实页面操作记录为 human,工具操作记录为 model。界面跟随宿主语言,日记和经验原文保留。
69
71
 
70
72
  ---
71
73
 
@@ -75,6 +77,8 @@ You are an agent that dreams. Dreams are not hallucinations — they are memory
75
77
 
76
78
  Dreams and **lessons** are two separate pipelines: a **first-person reflection** is subjective and goes to the dream journal; a **technical lesson** must be actionable, conditional and evidence-backed — it starts as a candidate and is only retrieved for tasks after review.
77
79
 
80
+ The plugin collects sourced project candidates after qualifying completed human root turns, within a persistent budget, and retrieves relevant accepted memories for later tasks. Ordinary chat, subagents and unsuccessful turns are skipped; new input cancels collection. Users need neither trigger phrases nor manual forms. Automatic candidates are never accepted automatically. Saving a journal, accepting a lesson and applying a rule are separate operations. Use the tool flow below when automatic interfaces are unavailable or switched off.
81
+
78
82
  ## Two pipelines (do not mix)
79
83
 
80
84
  | | First-person reflection (dream) | Technical lesson |
@@ -86,7 +90,7 @@ Dreams and **lessons** are two separate pipelines: a **first-person reflection**
86
90
 
87
91
  ## 1. Before the task: retrieve context (dream_context)
88
92
 
89
- - When a task touches past code, user preferences or known pitfalls, call `dream_context` first with `query`, plus `projectId` / `workspaceRoot` and `packageName` + `packageVersion` when available (`applicability.versions` only counts when that package is identified). Pass `includeCandidates: true` explicitly when reviewing candidates.
93
+ - If Dream reviewed memory is already present in dynamic context, check its conditions against the current request; do not retrieve the same items again. Use `dream_context` for version-bound lessons, different keywords, or when automatic retrieval is disabled. Supply `query`, scope and an actually verified `packageName` + `packageVersion`. Automatic retrieval holds all version-bound lessons when dependency versions are unknown. Pass `includeCandidates: true` explicitly when reviewing candidates.
90
94
  - **Budget: 5 items / 3000 characters by default** (hard caps 20 items / 20000 characters). Take only what is relevant; an empty result is acceptable — never stuff memories in to look useful.
91
95
  - `dream_context` is read-only: it writes nothing and returns title, applicability, action, evidence summary and why it is relevant.
92
96
  - With an unknown project it returns global lessons only and never scans across projects. Candidates **can be retrieved** (`includeCandidates: true`, for candidate review) but are **held out of default task advice** (`includeCandidates: false` reports `skipped: candidate-hold`; evidence-free non-usable items report `no-evidence`), and they rank after usable lessons — never treat one as a verified conclusion before review.
@@ -130,4 +134,4 @@ Dreams and **lessons** are two separate pipelines: a **first-person reflection**
130
134
  - Retrieving a few reusable lessons → `dream_context` (scoped, budgeted, read-only);
131
135
  - Browsing or reviewing candidates and conflicts → `dream_review`;
132
136
  - attach-evidence adds verified sources without promoting state. resolve-conflict requires resolution, affectedIds and note and updates the group atomically. reopen sends a rejected lesson back for review.
133
- - To browse: **Settings → Dream journal** shows the read-only dream timeline and a **Lessons** block (state, applicability, evidence summary, last validated time). The panel has no write actions.
137
+ - **Settings → Dream journal** lets users browse the timeline and sources, accept/reject candidates, request re-validation, resolve conflicts and record usage feedback. Rule changes require a separate preview and apply action and can be rolled back with confirmation. Page actions record human; tool actions record model. UI language follows the host; journal and lesson content remains original.