@modusensus/dsh-mneme 0.8.8 → 0.8.9

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/continuity.js CHANGED
@@ -205,7 +205,7 @@ export function createContinuityRescue(ctx, store) {
205
205
  ...decision,
206
206
  messages: [
207
207
  ...messages,
208
- createUserMessage({ content: [{ type: "text", text }], source: { kind: "plugin", plugin: "dsh-mneme" } })
208
+ createUserMessage({ content: [{ type: "text", text }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } })
209
209
  ]
210
210
  };
211
211
  });
@@ -334,8 +334,8 @@ async function phaseConflicts(ctx, service, config, logger, runId, semantic = nu
334
334
  maxTokens: config.sleepMaxTokens ?? 2048,
335
335
  ...(withEffort && sleepEffort ? { reasoningEffort: sleepEffort } : {}),
336
336
  messages: [
337
- { role: "system", content: [{ type: "text", text: conflictPrompt }], source: { kind: "plugin", plugin: "dsh-mneme" } },
338
- { role: "user", content: [{ type: "text", text: listText }], source: { kind: "plugin", plugin: "dsh-mneme" } }
337
+ { role: "system", content: [{ type: "text", text: conflictPrompt }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } },
338
+ { role: "user", content: [{ type: "text", text: listText }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } }
339
339
  ]
340
340
  }, reportUsage, (reason) => { conflictStreamFailure = describeStreamFailure(reason); }));
341
341
  };
@@ -496,8 +496,8 @@ async function phasePatterns(ctx, service, config, logger, runId, signal = null)
496
496
  maxTokens: config.sleepMaxTokens ?? 2048,
497
497
  ...(withEffort && sleepEffort ? { reasoningEffort: sleepEffort } : {}),
498
498
  messages: [
499
- { role: "system", content: [{ type: "text", text: STR.prompts.pattern[language].replace("N", String(maxPatterns)) }], source: { kind: "plugin", plugin: "dsh-mneme" } },
500
- { role: "user", content: [{ type: "text", text: listText }], source: { kind: "plugin", plugin: "dsh-mneme" } }
499
+ { role: "system", content: [{ type: "text", text: STR.prompts.pattern[language].replace("N", String(maxPatterns)) }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } },
500
+ { role: "user", content: [{ type: "text", text: listText }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } }
501
501
  ]
502
502
  }, reportUsage, (reason) => { patternStreamFailure = describeStreamFailure(reason); }));
503
503
  };
package/lib/dream.js CHANGED
@@ -422,8 +422,8 @@ async function generateNarratives({ ctx, service, config, route, language, effor
422
422
  maxTokens: config.dreamMaxTokens ?? 2048,
423
423
  ...(withEffort && effort ? { reasoningEffort: effort } : {}),
424
424
  messages: [
425
- { role: "system", content: [{ type: "text", text: STR.prompts.narrative[language] }], source: { kind: "plugin", plugin: "dsh-mneme" } },
426
- { role: "user", content: [{ type: "text", text: listing }], source: { kind: "plugin", plugin: "dsh-mneme" } }
425
+ { role: "system", content: [{ type: "text", text: STR.prompts.narrative[language] }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } },
426
+ { role: "user", content: [{ type: "text", text: listing }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } }
427
427
  ]
428
428
  }, reportUsage, (reason) => { streamFailure = describeStreamFailure(reason); }));
429
429
  };
@@ -1100,8 +1100,8 @@ export function createDreamScheduler({ onRun, thresholdCount = 10, thresholdChar
1100
1100
  maxTokens: config.dreamMaxTokens ?? 4096,
1101
1101
  ...(withEffort && effort ? { reasoningEffort: effort } : {}),
1102
1102
  messages: [
1103
- { role: "system", content: [{ type: "text", text: consolidationPrompt }], source: { kind: "plugin", plugin: "dsh-mneme" } },
1104
- { role: "user", content: [{ type: "text", text: listText }], source: { kind: "plugin", plugin: "dsh-mneme" } }
1103
+ { role: "system", content: [{ type: "text", text: consolidationPrompt }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } },
1104
+ { role: "user", content: [{ type: "text", text: listText }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } }
1105
1105
  ]
1106
1106
  }, reportUsage, (reason) => { streamFailure = describeStreamFailure(reason); }));
1107
1107
  };
@@ -1335,8 +1335,8 @@ export function createDreamScheduler({ onRun, thresholdCount = 10, thresholdChar
1335
1335
  maxTokens: config.dreamMaxTokens ?? 2048,
1336
1336
  ...(withEffort && effort ? { reasoningEffort: effort } : {}),
1337
1337
  messages: [
1338
- { role: "system", content: [{ type: "text", text: STR.prompts.dreamSummary[language] }], source: { kind: "plugin", plugin: "dsh-mneme" } },
1339
- { role: "user", content: [{ type: "text", text: summaryInputs.map((m) => `- ${m.title}: ${m.content}`).join("\n") }], source: { kind: "plugin", plugin: "dsh-mneme" } }
1338
+ { role: "system", content: [{ type: "text", text: STR.prompts.dreamSummary[language] }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } },
1339
+ { role: "user", content: [{ type: "text", text: summaryInputs.map((m) => `- ${m.title}: ${m.content}`).join("\n") }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } }
1340
1340
  ]
1341
1341
  }, reportUsage, (reason) => { summaryStreamFailure = describeStreamFailure(reason); }));
1342
1342
  };
@@ -150,8 +150,8 @@ export async function extractEntities(memory, { store, config, callLLM, logger }
150
150
  const userText = buildUserMessage(memory.content);
151
151
 
152
152
  const messages = [
153
- { role: "system", content: [{ type: "text", text: systemPrompt }], source: { kind: "plugin", plugin: "dsh-mneme" } },
154
- { role: "user", content: [{ type: "text", text: userText }], source: { kind: "plugin", plugin: "dsh-mneme" } }
153
+ { role: "system", content: [{ type: "text", text: systemPrompt }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } },
154
+ { role: "user", content: [{ type: "text", text: userText }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } }
155
155
  ];
156
156
 
157
157
  // Issue #109: optional provider/model override + reasoning effort are
package/lib/peak-hours.js CHANGED
@@ -1,117 +1,117 @@
1
- // 高峰时段(peak hours)解析与判定——纯函数模块,零依赖。
2
- //
3
- // 从 summarize.js 抽出(PR #320 review):#316 之后 summarize.js 反向依赖
4
- // dream.js(withEffortFallback 复用),dream 镜像错峰时再 import summarize
5
- // 会成真循环。时段调度本来就不是蒸馏的私有语义,独立成模块后两侧都从这里
6
- // import,循环消失。re-export 兼容留在 summarize.js,调用方零改动。
7
- //
8
- // Issue #239(第 4 项,错峰队列):高峰时段解析与判定。纯函数、可单测——排程
9
- // 判断不绑死真实时钟,测试才能确定性地覆盖跨零点、多段、星期过滤与非法写法。
10
- // spec 语法:`[<星期> ]<时段>[,<时段>...]`,星期前缀可省(省 = 每天):
11
- // "09:00-18:00" 每天 09:00-18:00
12
- // "mon-fri 08:00-12:00,14:00-18:00" 工作日两段(ISO 1=周一…7=周日,也认 mon..sun)
13
- // "sat,sun 23:00-06:00" 周末跨零点段
14
- // 时间取宿主本地时区。任一写法非法 → 整串视为未配置(返回 null):排程是省钱手段,
15
- // 绝不该因为写错格式把蒸馏/巩固停掉。
16
- const DAY_NAMES = { mon: 1, tue: 2, wed: 3, thu: 4, fri: 5, sat: 6, sun: 7 };
17
-
18
- function parseDayToken(token) {
19
- const days = new Set();
20
- const normalize = (value) => (/^\d$/.test(value) ? Number(value) : DAY_NAMES[value] ?? null);
21
- for (const piece of token.split(",")) {
22
- const matched = /^([a-z]{3}|\d)(?:-([a-z]{3}|\d))?$/.exec(piece.trim().toLowerCase());
23
- if (!matched) return null;
24
- const from = normalize(matched[1]);
25
- const to = matched[2] === undefined ? from : normalize(matched[2]);
26
- if (from === null || to === null || from < 1 || from > 7 || to < 1 || to > 7) return null;
27
- // 支持跨周环绕(fri-mon):从 from 起逐天推进到 to,最多绕一圈。
28
- for (let day = from; ; day = (day % 7) + 1) {
29
- days.add(day);
30
- if (day === to) break;
31
- }
32
- }
33
- return days.size > 0 ? [...days].sort((a, b) => a - b) : null;
34
- }
35
-
36
- /** JS 的 getDay() 是 0=周日…6=周六;这里统一成 ISO(1=周一…7=周日)。 */
37
- function isoDay(date) {
38
- const day = date.getDay();
39
- return day === 0 ? 7 : day;
40
- }
41
-
42
- export function parsePeakSpec(spec) {
43
- if (typeof spec !== "string" || spec.trim() === "") return null;
44
- let rest = spec.trim();
45
- let days = null;
46
- // 星期前缀 = 第一个空白之前的部分,但**头段含冒号就不是前缀**(那是时段本身,
47
- // 例如 "09:00-12:00, 14:00-18:00" 里的逗号空格)。前缀解析失败一律按未配置处理,
48
- // 不做猜测——宁可不省,也不能误停。
49
- const sep = rest.search(/\s/);
50
- if (sep > 0) {
51
- const head = rest.slice(0, sep);
52
- if (!head.includes(":")) {
53
- days = parseDayToken(head);
54
- if (days === null) return null;
55
- rest = rest.slice(sep).trim();
56
- }
57
- }
58
- const windows = [];
59
- for (const part of rest.split(",")) {
60
- const matched = /^\s*(\d{1,2}):(\d{2})\s*-\s*(\d{1,2}):(\d{2})\s*$/.exec(part);
61
- if (!matched) return null;
62
- const [sh, sm, eh, em] = [Number(matched[1]), Number(matched[2]), Number(matched[3]), Number(matched[4])];
63
- if (sh > 23 || eh > 23 || sm > 59 || em > 59) return null;
64
- const start = sh * 60 + sm;
65
- const end = eh * 60 + em;
66
- if (start === end) return null;
67
- windows.push({ start, end });
68
- }
69
- return windows.length > 0 ? { days, windows } : null;
70
- }
71
-
72
- /**
73
- * 该时刻是否落在高峰内。跨零点段(start > end)按「窗口所属的那一天」认星期:
74
- * `mon-fri 23:00-06:00` 的周六 02:00 属于周五开的那个窗口,仍算高峰。
75
- */
76
- export function isInPeakWindow(date, spec) {
77
- const parsed = parsePeakSpec(spec);
78
- if (!parsed) return false;
79
- const minutes = date.getHours() * 60 + date.getMinutes();
80
- const today = isoDay(date);
81
- const yesterday = today === 1 ? 7 : today - 1;
82
- const allowed = (day) => !parsed.days || parsed.days.includes(day);
83
- return parsed.windows.some(({ start, end }) => {
84
- if (start < end) return minutes >= start && minutes < end && allowed(today);
85
- return (minutes >= start && allowed(today)) || (minutes < end && allowed(yesterday));
86
- });
87
- }
88
-
89
- /**
90
- * 高峰内则返回「距当前最近的一个高峰结束时刻」(择时补跑用),否则 null。
91
- * 落在多个时段重叠处时取最早结束的那个——早跑不亏,晚跑才亏。
92
- */
93
- export function nextOffPeakAt(date, spec) {
94
- const parsed = parsePeakSpec(spec);
95
- if (!parsed) return null;
96
- const minutes = date.getHours() * 60 + date.getMinutes();
97
- const today = isoDay(date);
98
- const yesterday = today === 1 ? 7 : today - 1;
99
- const allowed = (day) => !parsed.days || parsed.days.includes(day);
100
- let bestDelta = null;
101
- const consider = (delta) => {
102
- if (bestDelta === null || delta < bestDelta) bestDelta = delta;
103
- };
104
- for (const { start, end } of parsed.windows) {
105
- if (start < end) {
106
- if (minutes >= start && minutes < end && allowed(today)) consider(end - minutes);
107
- continue;
108
- }
109
- if (minutes >= start && allowed(today)) consider((1440 - minutes) + end);
110
- else if (minutes < end && allowed(yesterday)) consider(end - minutes);
111
- }
112
- if (bestDelta === null) return null;
113
- const at = new Date(date.getTime());
114
- at.setSeconds(0, 0);
115
- at.setMinutes(at.getMinutes() + bestDelta);
116
- return at;
117
- }
1
+ // 高峰时段(peak hours)解析与判定——纯函数模块,零依赖。
2
+ //
3
+ // 从 summarize.js 抽出(PR #320 review):#316 之后 summarize.js 反向依赖
4
+ // dream.js(withEffortFallback 复用),dream 镜像错峰时再 import summarize
5
+ // 会成真循环。时段调度本来就不是蒸馏的私有语义,独立成模块后两侧都从这里
6
+ // import,循环消失。re-export 兼容留在 summarize.js,调用方零改动。
7
+ //
8
+ // Issue #239(第 4 项,错峰队列):高峰时段解析与判定。纯函数、可单测——排程
9
+ // 判断不绑死真实时钟,测试才能确定性地覆盖跨零点、多段、星期过滤与非法写法。
10
+ // spec 语法:`[<星期> ]<时段>[,<时段>...]`,星期前缀可省(省 = 每天):
11
+ // "09:00-18:00" 每天 09:00-18:00
12
+ // "mon-fri 08:00-12:00,14:00-18:00" 工作日两段(ISO 1=周一…7=周日,也认 mon..sun)
13
+ // "sat,sun 23:00-06:00" 周末跨零点段
14
+ // 时间取宿主本地时区。任一写法非法 → 整串视为未配置(返回 null):排程是省钱手段,
15
+ // 绝不该因为写错格式把蒸馏/巩固停掉。
16
+ const DAY_NAMES = { mon: 1, tue: 2, wed: 3, thu: 4, fri: 5, sat: 6, sun: 7 };
17
+
18
+ function parseDayToken(token) {
19
+ const days = new Set();
20
+ const normalize = (value) => (/^\d$/.test(value) ? Number(value) : DAY_NAMES[value] ?? null);
21
+ for (const piece of token.split(",")) {
22
+ const matched = /^([a-z]{3}|\d)(?:-([a-z]{3}|\d))?$/.exec(piece.trim().toLowerCase());
23
+ if (!matched) return null;
24
+ const from = normalize(matched[1]);
25
+ const to = matched[2] === undefined ? from : normalize(matched[2]);
26
+ if (from === null || to === null || from < 1 || from > 7 || to < 1 || to > 7) return null;
27
+ // 支持跨周环绕(fri-mon):从 from 起逐天推进到 to,最多绕一圈。
28
+ for (let day = from; ; day = (day % 7) + 1) {
29
+ days.add(day);
30
+ if (day === to) break;
31
+ }
32
+ }
33
+ return days.size > 0 ? [...days].sort((a, b) => a - b) : null;
34
+ }
35
+
36
+ /** JS 的 getDay() 是 0=周日…6=周六;这里统一成 ISO(1=周一…7=周日)。 */
37
+ function isoDay(date) {
38
+ const day = date.getDay();
39
+ return day === 0 ? 7 : day;
40
+ }
41
+
42
+ export function parsePeakSpec(spec) {
43
+ if (typeof spec !== "string" || spec.trim() === "") return null;
44
+ let rest = spec.trim();
45
+ let days = null;
46
+ // 星期前缀 = 第一个空白之前的部分,但**头段含冒号就不是前缀**(那是时段本身,
47
+ // 例如 "09:00-12:00, 14:00-18:00" 里的逗号空格)。前缀解析失败一律按未配置处理,
48
+ // 不做猜测——宁可不省,也不能误停。
49
+ const sep = rest.search(/\s/);
50
+ if (sep > 0) {
51
+ const head = rest.slice(0, sep);
52
+ if (!head.includes(":")) {
53
+ days = parseDayToken(head);
54
+ if (days === null) return null;
55
+ rest = rest.slice(sep).trim();
56
+ }
57
+ }
58
+ const windows = [];
59
+ for (const part of rest.split(",")) {
60
+ const matched = /^\s*(\d{1,2}):(\d{2})\s*-\s*(\d{1,2}):(\d{2})\s*$/.exec(part);
61
+ if (!matched) return null;
62
+ const [sh, sm, eh, em] = [Number(matched[1]), Number(matched[2]), Number(matched[3]), Number(matched[4])];
63
+ if (sh > 23 || eh > 23 || sm > 59 || em > 59) return null;
64
+ const start = sh * 60 + sm;
65
+ const end = eh * 60 + em;
66
+ if (start === end) return null;
67
+ windows.push({ start, end });
68
+ }
69
+ return windows.length > 0 ? { days, windows } : null;
70
+ }
71
+
72
+ /**
73
+ * 该时刻是否落在高峰内。跨零点段(start > end)按「窗口所属的那一天」认星期:
74
+ * `mon-fri 23:00-06:00` 的周六 02:00 属于周五开的那个窗口,仍算高峰。
75
+ */
76
+ export function isInPeakWindow(date, spec) {
77
+ const parsed = parsePeakSpec(spec);
78
+ if (!parsed) return false;
79
+ const minutes = date.getHours() * 60 + date.getMinutes();
80
+ const today = isoDay(date);
81
+ const yesterday = today === 1 ? 7 : today - 1;
82
+ const allowed = (day) => !parsed.days || parsed.days.includes(day);
83
+ return parsed.windows.some(({ start, end }) => {
84
+ if (start < end) return minutes >= start && minutes < end && allowed(today);
85
+ return (minutes >= start && allowed(today)) || (minutes < end && allowed(yesterday));
86
+ });
87
+ }
88
+
89
+ /**
90
+ * 高峰内则返回「距当前最近的一个高峰结束时刻」(择时补跑用),否则 null。
91
+ * 落在多个时段重叠处时取最早结束的那个——早跑不亏,晚跑才亏。
92
+ */
93
+ export function nextOffPeakAt(date, spec) {
94
+ const parsed = parsePeakSpec(spec);
95
+ if (!parsed) return null;
96
+ const minutes = date.getHours() * 60 + date.getMinutes();
97
+ const today = isoDay(date);
98
+ const yesterday = today === 1 ? 7 : today - 1;
99
+ const allowed = (day) => !parsed.days || parsed.days.includes(day);
100
+ let bestDelta = null;
101
+ const consider = (delta) => {
102
+ if (bestDelta === null || delta < bestDelta) bestDelta = delta;
103
+ };
104
+ for (const { start, end } of parsed.windows) {
105
+ if (start < end) {
106
+ if (minutes >= start && minutes < end && allowed(today)) consider(end - minutes);
107
+ continue;
108
+ }
109
+ if (minutes >= start && allowed(today)) consider((1440 - minutes) + end);
110
+ else if (minutes < end && allowed(yesterday)) consider(end - minutes);
111
+ }
112
+ if (bestDelta === null) return null;
113
+ const at = new Date(date.getTime());
114
+ at.setSeconds(0, 0);
115
+ at.setMinutes(at.getMinutes() + bestDelta);
116
+ return at;
117
+ }
package/lib/summarize.js CHANGED
@@ -220,7 +220,7 @@ function collectMessages(session, maxChars = 8000, language = "zh", afterSeq, th
220
220
  }, undefined);
221
221
  return {
222
222
  messages: lines.length
223
- ? [createUserMessage({ content: [{ type: "text", text: trimTranscript(lines.join("\n"), maxChars) }], source: { kind: "plugin", plugin: "dsh-mneme" } })]
223
+ ? [createUserMessage({ content: [{ type: "text", text: trimTranscript(lines.join("\n"), maxChars) }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } })]
224
224
  : [],
225
225
  hasEvents: events.length > 0,
226
226
  lastSeq
@@ -495,7 +495,7 @@ export function createSummarizer(ctx, service, config, deps = {}) {
495
495
  model: route.model,
496
496
  purpose: "summarization",
497
497
  messages: [
498
- { role: "system", content: [{ type: "text", text: config.codingRetrospect ? STR.prompts.codingSummary[langOf(config)] : STR.prompts.summary[langOf(config)] }], source: { kind: "plugin", plugin: "dsh-mneme" } },
498
+ { role: "system", content: [{ type: "text", text: config.codingRetrospect ? STR.prompts.codingSummary[langOf(config)] : STR.prompts.summary[langOf(config)] }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } },
499
499
  ...messages
500
500
  ],
501
501
  signal: controller.signal
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@modusensus/dsh-mneme",
3
3
  "description": "Cross-session memory plugin for DeepSeek Harness with autoDream consolidation: SQLite store, Markdown mirrors, 9 model tools, automatic injection, session summarization, user profile/rules, custom slash commands, vector (semantic) search, and a Web GUI panel",
4
- "version": "0.8.8",
4
+ "version": "0.8.9",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
package/src/api.js CHANGED
@@ -380,7 +380,7 @@ export function createApi(ctx, service, settings, commands, embedder, semantic =
380
380
  {
381
381
  role: "user",
382
382
  content: [{ type: "text", text: "Reply with exactly one word: ok" }],
383
- source: { kind: "plugin", plugin: "dsh-mneme" }
383
+ source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" }
384
384
  }
385
385
  ]
386
386
  })) {
package/src/continuity.js CHANGED
@@ -205,7 +205,7 @@ export function createContinuityRescue(ctx, store) {
205
205
  ...decision,
206
206
  messages: [
207
207
  ...messages,
208
- createUserMessage({ content: [{ type: "text", text }], source: { kind: "plugin", plugin: "dsh-mneme" } })
208
+ createUserMessage({ content: [{ type: "text", text }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } })
209
209
  ]
210
210
  };
211
211
  });
@@ -334,8 +334,8 @@ async function phaseConflicts(ctx, service, config, logger, runId, semantic = nu
334
334
  maxTokens: config.sleepMaxTokens ?? 2048,
335
335
  ...(withEffort && sleepEffort ? { reasoningEffort: sleepEffort } : {}),
336
336
  messages: [
337
- { role: "system", content: [{ type: "text", text: conflictPrompt }], source: { kind: "plugin", plugin: "dsh-mneme" } },
338
- { role: "user", content: [{ type: "text", text: listText }], source: { kind: "plugin", plugin: "dsh-mneme" } }
337
+ { role: "system", content: [{ type: "text", text: conflictPrompt }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } },
338
+ { role: "user", content: [{ type: "text", text: listText }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } }
339
339
  ]
340
340
  }, reportUsage, (reason) => { conflictStreamFailure = describeStreamFailure(reason); }));
341
341
  };
@@ -496,8 +496,8 @@ async function phasePatterns(ctx, service, config, logger, runId, signal = null)
496
496
  maxTokens: config.sleepMaxTokens ?? 2048,
497
497
  ...(withEffort && sleepEffort ? { reasoningEffort: sleepEffort } : {}),
498
498
  messages: [
499
- { role: "system", content: [{ type: "text", text: STR.prompts.pattern[language].replace("N", String(maxPatterns)) }], source: { kind: "plugin", plugin: "dsh-mneme" } },
500
- { role: "user", content: [{ type: "text", text: listText }], source: { kind: "plugin", plugin: "dsh-mneme" } }
499
+ { role: "system", content: [{ type: "text", text: STR.prompts.pattern[language].replace("N", String(maxPatterns)) }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } },
500
+ { role: "user", content: [{ type: "text", text: listText }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } }
501
501
  ]
502
502
  }, reportUsage, (reason) => { patternStreamFailure = describeStreamFailure(reason); }));
503
503
  };
package/src/dream.js CHANGED
@@ -422,8 +422,8 @@ async function generateNarratives({ ctx, service, config, route, language, effor
422
422
  maxTokens: config.dreamMaxTokens ?? 2048,
423
423
  ...(withEffort && effort ? { reasoningEffort: effort } : {}),
424
424
  messages: [
425
- { role: "system", content: [{ type: "text", text: STR.prompts.narrative[language] }], source: { kind: "plugin", plugin: "dsh-mneme" } },
426
- { role: "user", content: [{ type: "text", text: listing }], source: { kind: "plugin", plugin: "dsh-mneme" } }
425
+ { role: "system", content: [{ type: "text", text: STR.prompts.narrative[language] }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } },
426
+ { role: "user", content: [{ type: "text", text: listing }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } }
427
427
  ]
428
428
  }, reportUsage, (reason) => { streamFailure = describeStreamFailure(reason); }));
429
429
  };
@@ -1100,8 +1100,8 @@ export function createDreamScheduler({ onRun, thresholdCount = 10, thresholdChar
1100
1100
  maxTokens: config.dreamMaxTokens ?? 4096,
1101
1101
  ...(withEffort && effort ? { reasoningEffort: effort } : {}),
1102
1102
  messages: [
1103
- { role: "system", content: [{ type: "text", text: consolidationPrompt }], source: { kind: "plugin", plugin: "dsh-mneme" } },
1104
- { role: "user", content: [{ type: "text", text: listText }], source: { kind: "plugin", plugin: "dsh-mneme" } }
1103
+ { role: "system", content: [{ type: "text", text: consolidationPrompt }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } },
1104
+ { role: "user", content: [{ type: "text", text: listText }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } }
1105
1105
  ]
1106
1106
  }, reportUsage, (reason) => { streamFailure = describeStreamFailure(reason); }));
1107
1107
  };
@@ -1335,8 +1335,8 @@ export function createDreamScheduler({ onRun, thresholdCount = 10, thresholdChar
1335
1335
  maxTokens: config.dreamMaxTokens ?? 2048,
1336
1336
  ...(withEffort && effort ? { reasoningEffort: effort } : {}),
1337
1337
  messages: [
1338
- { role: "system", content: [{ type: "text", text: STR.prompts.dreamSummary[language] }], source: { kind: "plugin", plugin: "dsh-mneme" } },
1339
- { role: "user", content: [{ type: "text", text: summaryInputs.map((m) => `- ${m.title}: ${m.content}`).join("\n") }], source: { kind: "plugin", plugin: "dsh-mneme" } }
1338
+ { role: "system", content: [{ type: "text", text: STR.prompts.dreamSummary[language] }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } },
1339
+ { role: "user", content: [{ type: "text", text: summaryInputs.map((m) => `- ${m.title}: ${m.content}`).join("\n") }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } }
1340
1340
  ]
1341
1341
  }, reportUsage, (reason) => { summaryStreamFailure = describeStreamFailure(reason); }));
1342
1342
  };
@@ -150,8 +150,8 @@ export async function extractEntities(memory, { store, config, callLLM, logger }
150
150
  const userText = buildUserMessage(memory.content);
151
151
 
152
152
  const messages = [
153
- { role: "system", content: [{ type: "text", text: systemPrompt }], source: { kind: "plugin", plugin: "dsh-mneme" } },
154
- { role: "user", content: [{ type: "text", text: userText }], source: { kind: "plugin", plugin: "dsh-mneme" } }
153
+ { role: "system", content: [{ type: "text", text: systemPrompt }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } },
154
+ { role: "user", content: [{ type: "text", text: userText }], source: { kind: "plugin:dsh-mneme", plugin: "dsh-mneme" } }
155
155
  ];
156
156
 
157
157
  // Issue #109: optional provider/model override + reasoning effort are