@lmzhen/dsh-evolution-curator 0.16.0 → 0.17.0-rc.1
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/index.js +142 -105
- package/lib/types/index.d.ts +131 -39
- package/package.json +11 -11
package/lib/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { randomUUID } from "node:crypto";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { BlockAssembler, createUserMessage } from "@deepseek-ai/dsh-llm";
|
|
5
5
|
import z from "@deepseek-ai/schemastery";
|
|
6
|
-
import { CURATOR_DRY_RUN_BANNER, CURATOR_PROMPT, DEFAULT_ARCHIVE_AFTER_DAYS, DEFAULT_CURATOR_BOOT_GRACE_SECONDS, DEFAULT_CURATOR_INTERVAL_HOURS, DEFAULT_CURATOR_MODEL, DEFAULT_CURATOR_REVIEW_MAX_TOKENS, DEFAULT_HEALTH_THRESHOLDS, DEFAULT_MIN_IDLE_HOURS, DEFAULT_SKILL_LIMITS, DEFAULT_STALE_AFTER_DAYS, EvolutionGateSet, INSTANCE_KEYS, MAX_TIMER_DELAY_MS, SKILL_NAME_RE, buildCuratorRunReport, claimInstance, clampedNumber, computeDedupGroups, computeLifecycleTransitions, computePrefixClusters, computeQualityScores, computeScopeView, contentHash, emptyRecord, entryTarget, evolutionHome, evolutionIoAdapter, foldCuratorFields,
|
|
6
|
+
import { CURATOR_DRY_RUN_BANNER, CURATOR_PROMPT, DEFAULT_ARCHIVE_AFTER_DAYS, DEFAULT_CURATOR_BOOT_GRACE_SECONDS, DEFAULT_CURATOR_INTERVAL_HOURS, DEFAULT_CURATOR_MODEL, DEFAULT_CURATOR_REVIEW_MAX_TOKENS, DEFAULT_HEALTH_THRESHOLDS, DEFAULT_MIN_IDLE_HOURS, DEFAULT_SKILL_LIMITS, DEFAULT_STALE_AFTER_DAYS, EvolutionGateSet, INSTANCE_KEYS, MAX_TIMER_DELAY_MS, SKILL_NAME_RE, buildCuratorRunReport, claimInstance, clampedNumber, computeDedupGroups, computeLifecycleTransitions, computePrefixClusters, computeQualityScores, computeScopeView, contentHash, emptyRecord, entryTarget, evolutionHome, evolutionIoAdapter, foldCuratorFields, isPresent, isUnknown, loadSuppressedNames, loadUsage, markerEntryName, mutateUsage, newSkillLibrary, paramRowId, parseCuratorNominations, parseFrontmatter, policyStageLimits, probeList, probeMtime, readNumberParam, relatedSkillNames, releaseInstance, renderCuratorReportMarkdown, sessionLastEventTime, transactIo, updateSuppressedNames, usageObserved } from "@lmzhen/dsh-evolution-core";
|
|
7
7
|
//#region lib/types/index.js
|
|
8
8
|
/**
|
|
9
9
|
* Deterministic skill lifecycle curator with interval gate and archive.
|
|
@@ -17,23 +17,6 @@ const DEFAULT_QUALITY_WARN_STALE_AFTER_DAYS = 7;
|
|
|
17
17
|
* 120s matches the review subagent default; the 32-bit ceiling is Node's
|
|
18
18
|
* timer-delay limit (`AbortSignal.timeout` throws above it). */
|
|
19
19
|
const DEFAULT_CURATOR_REVIEW_TIMEOUT_MS = 12e4;
|
|
20
|
-
/** Schema the platform validates the user layer against; defaults mirror the core
|
|
21
|
-
* constants and the bounds mirror the row schema, so an empty document resolves to
|
|
22
|
-
* today's behaviour and an out-of-range value is refused instead of clamped. */
|
|
23
|
-
const CURATOR_SETTINGS_SCHEMA = z.object({
|
|
24
|
-
curatorIntervalHours: z.number().min(1).default(DEFAULT_CURATOR_INTERVAL_HOURS),
|
|
25
|
-
staleAfterDays: z.number().min(1).default(DEFAULT_STALE_AFTER_DAYS),
|
|
26
|
-
archiveAfterDays: z.number().min(1).default(DEFAULT_ARCHIVE_AFTER_DAYS),
|
|
27
|
-
qualityWarnStaleAfterDays: z.number().min(1).default(DEFAULT_QUALITY_WARN_STALE_AFTER_DAYS),
|
|
28
|
-
minIdleHours: z.number().min(0).default(DEFAULT_MIN_IDLE_HOURS),
|
|
29
|
-
minIdleFailOpen: z.boolean().default(true),
|
|
30
|
-
llmReview: z.boolean().default(false),
|
|
31
|
-
curatorReviewMaxTokens: z.number().min(1).default(DEFAULT_CURATOR_REVIEW_MAX_TOKENS),
|
|
32
|
-
curatorReviewTimeoutMs: z.number().min(1).max(MAX_TIMER_DELAY_MS).default(DEFAULT_CURATOR_REVIEW_TIMEOUT_MS),
|
|
33
|
-
healthSoftBodyChars: z.number().min(1).default(DEFAULT_HEALTH_THRESHOLDS.softBodyChars),
|
|
34
|
-
healthStampDensityPerKb: z.number().min(1).default(DEFAULT_HEALTH_THRESHOLDS.stampDensityPerKb),
|
|
35
|
-
healthChurnMinPatches: z.number().min(1).default(DEFAULT_HEALTH_THRESHOLDS.churnMinPatches)
|
|
36
|
-
});
|
|
37
20
|
/**
|
|
38
21
|
* The cross-field rule the schema cannot express (A2-17): an archive threshold
|
|
39
22
|
* below the stale threshold makes the engine reactivate stale records instead of
|
|
@@ -60,54 +43,43 @@ var EvolutionCurator = class extends Service {
|
|
|
60
43
|
static Config = z.object({
|
|
61
44
|
root: z.string().default(""),
|
|
62
45
|
enabled: z.boolean().default(true),
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
46
|
+
curatorIntervalHours: z.number().min(1).volatile(),
|
|
47
|
+
intervalHours: z.number().min(1),
|
|
48
|
+
staleAfterDays: z.number().min(1).default(DEFAULT_STALE_AFTER_DAYS).volatile(),
|
|
49
|
+
archiveAfterDays: z.number().min(1).default(DEFAULT_ARCHIVE_AFTER_DAYS).volatile(),
|
|
50
|
+
llmReview: z.boolean().default(false).volatile(),
|
|
67
51
|
curatorProvider: z.string().default("deepseek-official"),
|
|
68
|
-
qualityWarnStaleAfterDays: z.number().min(1).default(DEFAULT_QUALITY_WARN_STALE_AFTER_DAYS),
|
|
69
|
-
minIdleHours: z.number().min(0).default(DEFAULT_MIN_IDLE_HOURS),
|
|
70
|
-
minIdleFailOpen: z.boolean().default(true),
|
|
52
|
+
qualityWarnStaleAfterDays: z.number().min(1).default(DEFAULT_QUALITY_WARN_STALE_AFTER_DAYS).volatile(),
|
|
53
|
+
minIdleHours: z.number().min(0).default(DEFAULT_MIN_IDLE_HOURS).volatile(),
|
|
54
|
+
minIdleFailOpen: z.boolean().default(true).volatile(),
|
|
71
55
|
excludeSkillNames: z.array(z.string()).default([]),
|
|
72
56
|
manageUnmanaged: z.boolean().default(false),
|
|
73
57
|
pruneBuiltins: z.boolean().default(false),
|
|
74
58
|
referencedSkillNames: z.array(z.string()).default([]),
|
|
75
59
|
autoStart: z.boolean().default(true),
|
|
76
60
|
bootGraceSeconds: z.number().min(0).default(DEFAULT_CURATOR_BOOT_GRACE_SECONDS),
|
|
77
|
-
curatorReviewMaxTokens: z.number().min(1).default(DEFAULT_CURATOR_REVIEW_MAX_TOKENS),
|
|
78
|
-
curatorReviewTimeoutMs: z.number().min(1).max(MAX_TIMER_DELAY_MS).default(DEFAULT_CURATOR_REVIEW_TIMEOUT_MS),
|
|
79
|
-
healthSoftBodyChars: z.number().min(1).default(DEFAULT_HEALTH_THRESHOLDS.softBodyChars),
|
|
80
|
-
healthStampDensityPerKb: z.number().min(1).default(DEFAULT_HEALTH_THRESHOLDS.stampDensityPerKb),
|
|
81
|
-
healthChurnMinPatches: z.number().min(1).default(DEFAULT_HEALTH_THRESHOLDS.churnMinPatches)
|
|
61
|
+
curatorReviewMaxTokens: z.number().min(1).default(DEFAULT_CURATOR_REVIEW_MAX_TOKENS).volatile(),
|
|
62
|
+
curatorReviewTimeoutMs: z.number().min(1).max(MAX_TIMER_DELAY_MS).default(DEFAULT_CURATOR_REVIEW_TIMEOUT_MS).volatile(),
|
|
63
|
+
healthSoftBodyChars: z.number().min(1).default(DEFAULT_HEALTH_THRESHOLDS.softBodyChars).volatile(),
|
|
64
|
+
healthStampDensityPerKb: z.number().min(1).default(DEFAULT_HEALTH_THRESHOLDS.stampDensityPerKb).volatile(),
|
|
65
|
+
healthChurnMinPatches: z.number().min(1).default(DEFAULT_HEALTH_THRESHOLDS.churnMinPatches).volatile()
|
|
82
66
|
});
|
|
83
67
|
skills;
|
|
84
68
|
io;
|
|
85
69
|
enabled;
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
archiveAfterDays;
|
|
89
|
-
llmReview;
|
|
70
|
+
/** This row's live config (G1 §8.3): its volatile fields are resolved at USE time. */
|
|
71
|
+
config;
|
|
90
72
|
/** S1-C3: one warn per instance when `llmReview` is on but the llm service
|
|
91
73
|
* is absent — the channel silently degrading must be visible at least once. */
|
|
92
74
|
llmAbsentWarned = false;
|
|
93
75
|
curatorProvider;
|
|
94
|
-
qualityWarnStaleAfterDays;
|
|
95
|
-
minIdleHours;
|
|
96
|
-
minIdleFailOpen;
|
|
97
76
|
excludeSkillNames;
|
|
98
77
|
manageUnmanaged;
|
|
99
78
|
pruneBuiltins;
|
|
100
79
|
referencedSkillNames;
|
|
101
80
|
bootGraceSeconds;
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
healthSoftBodyChars;
|
|
105
|
-
healthStampDensityPerKb;
|
|
106
|
-
healthChurnMinPatches;
|
|
107
|
-
/** G3/S3.3: this row's resolved values — the base layer of the settings section. */
|
|
108
|
-
settingsBase;
|
|
109
|
-
/** The user layer for this row's namespace (absent provider = deployment values). */
|
|
110
|
-
overrides;
|
|
81
|
+
/** Keys whose supplied value had to be corrected; each warns once (G3.1). */
|
|
82
|
+
clampedKeys = /* @__PURE__ */ new Set();
|
|
111
83
|
lastRun = 0;
|
|
112
84
|
timer;
|
|
113
85
|
/** B-8 (v18): set by the fiber disposer; a triggered autoCheck must not
|
|
@@ -138,6 +110,12 @@ var EvolutionCurator = class extends Service {
|
|
|
138
110
|
instanceOwner = `evolution-curator[${process.pid}:${randomUUID().slice(0, 8)}]`;
|
|
139
111
|
constructor(ctx, config = {}) {
|
|
140
112
|
super(ctx, "evolutionCurator");
|
|
113
|
+
ctx.inject(["settings"], (injected) => {
|
|
114
|
+
const settings = injected.settings;
|
|
115
|
+
if (typeof settings?.configure !== "function") return;
|
|
116
|
+
const disposer = settings.configure({ auto: false });
|
|
117
|
+
if (typeof disposer === "function") ctx.effect(() => disposer, "evolution-curator: settings presentation");
|
|
118
|
+
});
|
|
141
119
|
this.io = evolutionIoAdapter(() => ctx.evolutionIo.provider());
|
|
142
120
|
this.skills = newSkillLibrary({
|
|
143
121
|
config,
|
|
@@ -148,62 +126,31 @@ var EvolutionCurator = class extends Service {
|
|
|
148
126
|
...policyStageLimits(this.ctx.get("evolutionPolicy")?.get?.())
|
|
149
127
|
}
|
|
150
128
|
});
|
|
129
|
+
this.config = config;
|
|
151
130
|
this.enabled = config.enabled ?? true;
|
|
152
131
|
this.instanceHome = evolutionHome();
|
|
153
132
|
const claim = claimInstance(this.instanceHome, INSTANCE_KEYS.curator, this.instanceOwner);
|
|
154
133
|
this.holdsInstance = claim.granted;
|
|
155
134
|
if (!claim.granted) this.ctx.logger.warn(`evolution-curator: this instance YIELDS — ${claim.key} is already held by ${claim.holder} IN THIS PROCESS (the claim is a module-scope Map, so it does not exclude another process); a second curator ROW over one home would run a second gate set and a second lifecycle pass over the same tree. It schedules nothing and every run() returns skipped "instance-held"; the report sweep itself is cross-process locked (v43 FLOW2-1).`);
|
|
156
|
-
const clamped = [];
|
|
157
|
-
const field = (name, value, fallback, min, max) => {
|
|
158
|
-
const result = clampedNumber(value, fallback, max === void 0 ? { min } : {
|
|
159
|
-
min,
|
|
160
|
-
max
|
|
161
|
-
});
|
|
162
|
-
if (value !== void 0 && result !== value) clamped.push(name);
|
|
163
|
-
return result;
|
|
164
|
-
};
|
|
165
|
-
this.intervalHours = field("intervalHours", readNumberParam(config, "curatorIntervalHours"), DEFAULT_CURATOR_INTERVAL_HOURS, 1);
|
|
166
|
-
this.staleAfterDays = field("staleAfterDays", config.staleAfterDays, DEFAULT_STALE_AFTER_DAYS, 1);
|
|
167
|
-
this.archiveAfterDays = field("archiveAfterDays", config.archiveAfterDays, DEFAULT_ARCHIVE_AFTER_DAYS, 1);
|
|
168
|
-
if (this.archiveAfterDays < this.staleAfterDays) {
|
|
169
|
-
this.ctx.logger.warn(`evolution-curator: archiveAfterDays (${this.archiveAfterDays}) < staleAfterDays (${this.staleAfterDays}); using staleAfterDays as the archive threshold`);
|
|
170
|
-
this.archiveAfterDays = this.staleAfterDays;
|
|
171
|
-
}
|
|
172
|
-
this.llmReview = config.llmReview ?? false;
|
|
173
135
|
this.curatorProvider = config.curatorProvider ?? "deepseek-official";
|
|
174
|
-
this.qualityWarnStaleAfterDays = field("qualityWarnStaleAfterDays", config.qualityWarnStaleAfterDays, DEFAULT_QUALITY_WARN_STALE_AFTER_DAYS, 1);
|
|
175
|
-
this.minIdleHours = field("minIdleHours", config.minIdleHours, DEFAULT_MIN_IDLE_HOURS, 0);
|
|
176
|
-
this.minIdleFailOpen = config.minIdleFailOpen ?? true;
|
|
177
136
|
this.excludeSkillNames = new Set(config.excludeSkillNames ?? []);
|
|
178
137
|
this.manageUnmanaged = config.manageUnmanaged ?? false;
|
|
179
138
|
this.pruneBuiltins = config.pruneBuiltins ?? false;
|
|
180
139
|
this.referencedSkillNames = new Set(config.referencedSkillNames ?? []);
|
|
181
|
-
this.bootGraceSeconds =
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
this.
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
llmReview: this.llmReview,
|
|
196
|
-
curatorReviewMaxTokens: this.curatorReviewMaxTokens,
|
|
197
|
-
curatorReviewTimeoutMs: this.curatorReviewTimeoutMs,
|
|
198
|
-
healthSoftBodyChars: this.healthSoftBodyChars,
|
|
199
|
-
healthStampDensityPerKb: this.healthStampDensityPerKb,
|
|
200
|
-
healthChurnMinPatches: this.healthChurnMinPatches
|
|
201
|
-
};
|
|
202
|
-
this.overrides = installParamSection(ctx, paramNamespace("evolution-curator"), CURATOR_SETTINGS_SCHEMA, this.settingsBase, {
|
|
203
|
-
warn: (message) => {
|
|
204
|
-
this.ctx.logger.warn("dsh-evolution-curator: " + message);
|
|
205
|
-
},
|
|
206
|
-
validate: validateCuratorSettings
|
|
140
|
+
this.bootGraceSeconds = this.clampOnce("bootGraceSeconds", config.bootGraceSeconds, DEFAULT_CURATOR_BOOT_GRACE_SECONDS, 0, 3600);
|
|
141
|
+
const archiveAtBoot = this.rowNumber("archiveAfterDays", DEFAULT_ARCHIVE_AFTER_DAYS, 1);
|
|
142
|
+
const staleAtBoot = this.rowNumber("staleAfterDays", DEFAULT_STALE_AFTER_DAYS, 1);
|
|
143
|
+
if (archiveAtBoot < staleAtBoot) this.ctx.logger.warn(`evolution-curator: archiveAfterDays (${archiveAtBoot}) < staleAfterDays (${staleAtBoot}); using staleAfterDays as the archive threshold`);
|
|
144
|
+
ctx.on("internal/config", function(_previous, next) {
|
|
145
|
+
const value = next();
|
|
146
|
+
if (this !== ctx.fiber) return value;
|
|
147
|
+
const archive = readNumberParam(value, "archiveAfterDays");
|
|
148
|
+
const stale = readNumberParam(value, "staleAfterDays");
|
|
149
|
+
if (typeof archive === "number" && typeof stale === "number") validateCuratorSettings({
|
|
150
|
+
archiveAfterDays: archive,
|
|
151
|
+
staleAfterDays: stale
|
|
152
|
+
});
|
|
153
|
+
return value;
|
|
207
154
|
});
|
|
208
155
|
this.lastRun = Date.now();
|
|
209
156
|
this.ctx.effect(() => {
|
|
@@ -215,24 +162,112 @@ var EvolutionCurator = class extends Service {
|
|
|
215
162
|
}, "evolution-curator.stop");
|
|
216
163
|
if (config.autoStart ?? true) this.start();
|
|
217
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Clamp one supplied numeric value, warning once per key (G3.1).
|
|
167
|
+
* @param key - the config key, for the warning.
|
|
168
|
+
* @param value - the value as supplied by the deployment or the user.
|
|
169
|
+
* @param fallback - the package default a corrected value falls back to.
|
|
170
|
+
* @param min - the smallest value the engine can act on.
|
|
171
|
+
* @param max - the largest value the carrier can hold, when bounded.
|
|
172
|
+
* @returns the value the engine may use.
|
|
173
|
+
*/
|
|
174
|
+
clampOnce(key, value, fallback, min, max) {
|
|
175
|
+
const result = clampedNumber(value, fallback, max === void 0 ? { min } : {
|
|
176
|
+
min,
|
|
177
|
+
max
|
|
178
|
+
});
|
|
179
|
+
if (value !== void 0 && result !== value && !this.clampedKeys.has(key)) {
|
|
180
|
+
this.clampedKeys.add(key);
|
|
181
|
+
this.ctx.logger.warn(`evolution-curator: ${key} provided an invalid value; falling back to the default`);
|
|
182
|
+
}
|
|
183
|
+
return result;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* One live numeric row field at USE time (G1 §8.3): the row config carries the
|
|
187
|
+
* platform-resolved layers (schema default < bundle row < profile override) and the
|
|
188
|
+
* field stays a live reference, so a committed edit applies without a watcher.
|
|
189
|
+
* @param key - the canonical registry id of the field.
|
|
190
|
+
* @returns the current plain value, or undefined when nothing supplied one.
|
|
191
|
+
*/
|
|
192
|
+
liveNumber(key) {
|
|
193
|
+
if (key === "curatorIntervalHours") return this.config.curatorIntervalHours?.get() ?? this.config.intervalHours;
|
|
194
|
+
return this.config[key]?.get();
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* One live numeric row field, clamped and warned once (G3.1).
|
|
198
|
+
* @param key - the canonical registry id of the field.
|
|
199
|
+
* @param fallback - the package default a corrected value falls back to.
|
|
200
|
+
* @param min - the smallest value the engine can act on.
|
|
201
|
+
* @param max - the largest value the carrier can hold, when bounded.
|
|
202
|
+
* @returns the value the engine may use.
|
|
203
|
+
*/
|
|
204
|
+
rowNumber(key, fallback, min, max) {
|
|
205
|
+
return this.clampOnce(key, this.liveNumber(key), fallback, min, max);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* One live boolean row field at USE time.
|
|
209
|
+
* @param key - the canonical registry id of the field.
|
|
210
|
+
* @param fallback - the value used when the deployment supplied none.
|
|
211
|
+
* @returns the current value.
|
|
212
|
+
*/
|
|
213
|
+
rowBoolean(key, fallback) {
|
|
214
|
+
return this.config[key]?.get() ?? fallback;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* This row's resolved values — the base layer of the precedence chain (G1 §8.3).
|
|
218
|
+
* Resolved per call so a user edit is live; every numeric field is clamped.
|
|
219
|
+
* @returns the row layer of the curator's behaviour knobs.
|
|
220
|
+
*/
|
|
221
|
+
rowSettings() {
|
|
222
|
+
const number = (key, fallback, min, max) => this.rowNumber(key, fallback, min, max);
|
|
223
|
+
return {
|
|
224
|
+
curatorIntervalHours: number("curatorIntervalHours", DEFAULT_CURATOR_INTERVAL_HOURS, 1),
|
|
225
|
+
staleAfterDays: number("staleAfterDays", DEFAULT_STALE_AFTER_DAYS, 1),
|
|
226
|
+
archiveAfterDays: number("archiveAfterDays", DEFAULT_ARCHIVE_AFTER_DAYS, 1),
|
|
227
|
+
qualityWarnStaleAfterDays: number("qualityWarnStaleAfterDays", DEFAULT_QUALITY_WARN_STALE_AFTER_DAYS, 1),
|
|
228
|
+
minIdleHours: number("minIdleHours", DEFAULT_MIN_IDLE_HOURS, 0),
|
|
229
|
+
minIdleFailOpen: this.rowBoolean("minIdleFailOpen", true),
|
|
230
|
+
llmReview: this.rowBoolean("llmReview", false),
|
|
231
|
+
curatorReviewMaxTokens: number("curatorReviewMaxTokens", DEFAULT_CURATOR_REVIEW_MAX_TOKENS, 1),
|
|
232
|
+
curatorReviewTimeoutMs: number("curatorReviewTimeoutMs", DEFAULT_CURATOR_REVIEW_TIMEOUT_MS, 1, MAX_TIMER_DELAY_MS),
|
|
233
|
+
healthSoftBodyChars: number("healthSoftBodyChars", DEFAULT_HEALTH_THRESHOLDS.softBodyChars, 1),
|
|
234
|
+
healthStampDensityPerKb: number("healthStampDensityPerKb", DEFAULT_HEALTH_THRESHOLDS.stampDensityPerKb, 1),
|
|
235
|
+
healthChurnMinPatches: number("healthChurnMinPatches", DEFAULT_HEALTH_THRESHOLDS.churnMinPatches, 1)
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* The keys the user set in this row's namespace (G1 §8.4-A).
|
|
240
|
+
*
|
|
241
|
+
* This is the ONLY remaining read of the settings user layer, and it reads KEY
|
|
242
|
+
* NAMES, never values: the platform resolves the user layer into the row config,
|
|
243
|
+
* so a value is needed from `config` — but the precedence rule (user > policy)
|
|
244
|
+
* needs to know WHICH keys the user set, or a deployment policy would silently
|
|
245
|
+
* override the user.
|
|
246
|
+
* @returns the keys present in this row's user layer.
|
|
247
|
+
*/
|
|
248
|
+
userSetKeys() {
|
|
249
|
+
const entry = this.ctx.get("settings")?.describe?.({ redactSecrets: false }).find((item) => item.ns === paramRowId("evolution-curator"));
|
|
250
|
+
return new Set(Object.keys(entry?.user ?? {}));
|
|
251
|
+
}
|
|
218
252
|
/** The policy-snapshot carrier for this group (unmounted service = no policy). */
|
|
219
253
|
policyFields() {
|
|
220
254
|
return this.ctx.get("evolutionPolicy")?.get() ?? {};
|
|
221
255
|
}
|
|
222
256
|
/**
|
|
223
|
-
* G3/S3.3: the ONE reader of the curator's behaviour knobs. Precedence is
|
|
224
|
-
* user > policy snapshot > this row
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
*
|
|
257
|
+
* G3/S3.3 + G1: the ONE reader of the curator's behaviour knobs. Precedence is
|
|
258
|
+
* user > policy snapshot > this row: the row layer already carries the user value
|
|
259
|
+
* (a live field), and {@link userSetKeys} answers whether the user set the key —
|
|
260
|
+
* so an untouched key keeps following the deployment carriers exactly as before.
|
|
261
|
+
* Read at USE time: a committed settings change is live without a restart and
|
|
262
|
+
* without a watcher.
|
|
228
263
|
* @returns the resolved section, every numeric field sanitized.
|
|
229
264
|
*/
|
|
230
265
|
settings() {
|
|
231
266
|
const snapshot = this.policyFields();
|
|
232
|
-
const row = this.
|
|
267
|
+
const row = this.rowSettings();
|
|
268
|
+
const userSet = this.userSetKeys();
|
|
233
269
|
const pick = (key) => {
|
|
234
|
-
|
|
235
|
-
if (user !== void 0) return user;
|
|
270
|
+
if (userSet.has(key)) return row[key];
|
|
236
271
|
return snapshot[key] ?? row[key];
|
|
237
272
|
};
|
|
238
273
|
const number = (key, min, max) => {
|
|
@@ -412,8 +447,7 @@ var EvolutionCurator = class extends Service {
|
|
|
412
447
|
text: prompt
|
|
413
448
|
}],
|
|
414
449
|
source: {
|
|
415
|
-
kind: "
|
|
416
|
-
plugin: "dsh-evolution-curator",
|
|
450
|
+
kind: "evolution-curator",
|
|
417
451
|
form: "notice",
|
|
418
452
|
summary: "curator review"
|
|
419
453
|
}
|
|
@@ -1049,11 +1083,14 @@ var EvolutionCurator = class extends Service {
|
|
|
1049
1083
|
const agents = this.ctx.get("agents");
|
|
1050
1084
|
if (!agents) return !settings.minIdleFailOpen;
|
|
1051
1085
|
let latest = 0;
|
|
1086
|
+
let measured = 0;
|
|
1052
1087
|
for (const agent of agents.list()) {
|
|
1053
|
-
const
|
|
1054
|
-
|
|
1088
|
+
const last = sessionLastEventTime(this.ctx, agent.session);
|
|
1089
|
+
if (last === void 0) continue;
|
|
1090
|
+
measured += 1;
|
|
1055
1091
|
latest = Math.max(latest, last);
|
|
1056
1092
|
}
|
|
1093
|
+
if (measured === 0) return !settings.minIdleFailOpen;
|
|
1057
1094
|
return latest > 0 && Date.now() - latest < settings.minIdleHours * 36e5;
|
|
1058
1095
|
}
|
|
1059
1096
|
/**
|
|
@@ -1435,4 +1472,4 @@ function reportsSweepLockTarget() {
|
|
|
1435
1472
|
return join(evolutionHome(), "reports", ".retention");
|
|
1436
1473
|
}
|
|
1437
1474
|
//#endregion
|
|
1438
|
-
export {
|
|
1475
|
+
export { EvolutionCurator, EvolutionCurator as default, gateConsolidations, validateCuratorSettings };
|
package/lib/types/index.d.ts
CHANGED
|
@@ -3,8 +3,16 @@
|
|
|
3
3
|
* @module @lmzhen/dsh-evolution-curator
|
|
4
4
|
*/
|
|
5
5
|
import { Context, Service } from '@deepseek-ai/cordis';
|
|
6
|
+
import type { Volatile } from '@deepseek-ai/cordis';
|
|
7
|
+
import type { ContextFormed } from '@deepseek-ai/dsh-llm';
|
|
8
|
+
declare module '@deepseek-ai/dsh-llm' {
|
|
9
|
+
interface MessageSourceMap {
|
|
10
|
+
'evolution-curator': {
|
|
11
|
+
kind: 'evolution-curator';
|
|
12
|
+
} & ContextFormed;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
6
15
|
import z from '@deepseek-ai/schemastery';
|
|
7
|
-
import type Schema from '@deepseek-ai/schemastery';
|
|
8
16
|
import { EvolutionGateSet, type SkillLibrary } from '@lmzhen/dsh-evolution-core';
|
|
9
17
|
import { type CuratorConsolidation, type CuratorNominations, type CuratorRunReport, type ScopeView, type SkillActionResult, type SkillHealthVerdict } from '@lmzhen/dsh-evolution-core';
|
|
10
18
|
import type { SkillVersion } from '@lmzhen/dsh-evolution-core';
|
|
@@ -16,29 +24,31 @@ declare module '@deepseek-ai/cordis' {
|
|
|
16
24
|
}
|
|
17
25
|
export interface Config {
|
|
18
26
|
enabled?: boolean;
|
|
27
|
+
/** Canonical registry id for the due-ness interval (see PARAM_ALIASES). */
|
|
28
|
+
curatorIntervalHours?: Volatile<number | undefined>;
|
|
19
29
|
/** The due-ness interval. The policy snapshot shadows it in every shipped
|
|
20
30
|
* composition — configure `curatorIntervalHours` there; that name is the
|
|
21
31
|
* canonical id. Deprecated alias (G0/S0.3): still readable, refused by
|
|
22
32
|
* writes; removed 0.7.0. */
|
|
23
33
|
intervalHours?: number;
|
|
24
|
-
staleAfterDays?: number
|
|
25
|
-
archiveAfterDays?: number
|
|
34
|
+
staleAfterDays?: Volatile<number>;
|
|
35
|
+
archiveAfterDays?: Volatile<number>;
|
|
26
36
|
/** Skill-tree root for curator scope/snapshot/archive (D2, v11) — a custom
|
|
27
37
|
* root deployment (review/tool-skill-manage write another tree) must point
|
|
28
38
|
* the curator at the SAME tree or lifecycle decisions land on the default
|
|
29
39
|
* tree and never see the deployed skills. Empty uses skillsRoot(). */
|
|
30
40
|
root?: string;
|
|
31
41
|
/** Spend one LLM review pass on stale candidates before the deterministic archive step. */
|
|
32
|
-
llmReview?: boolean
|
|
42
|
+
llmReview?: Volatile<boolean>;
|
|
33
43
|
curatorProvider?: string;
|
|
34
44
|
/** Quality-warned skills may turn stale after this many idle days. */
|
|
35
|
-
qualityWarnStaleAfterDays?: number
|
|
45
|
+
qualityWarnStaleAfterDays?: Volatile<number>;
|
|
36
46
|
/** Skip automatic runs while any session was active within this many hours (0 disables). */
|
|
37
|
-
minIdleHours?: number
|
|
47
|
+
minIdleHours?: Volatile<number>;
|
|
38
48
|
/** When true (default), a missing `agents` service is treated as "no active
|
|
39
49
|
* session" (fail-open — the idle gate lets the run proceed); when false the
|
|
40
50
|
* gate fails closed and defers the run until activity can be measured. */
|
|
41
|
-
minIdleFailOpen?: boolean
|
|
51
|
+
minIdleFailOpen?: Volatile<boolean>;
|
|
42
52
|
/** Skill names excluded from the automated lifecycle. */
|
|
43
53
|
excludeSkillNames?: string[];
|
|
44
54
|
/** Include usage records whose created_by is not 'agent' in lifecycle decisions. */
|
|
@@ -52,15 +62,15 @@ export interface Config {
|
|
|
52
62
|
/** Seconds between host boot and the first automatic schedule check (restart catch-up). */
|
|
53
63
|
bootGraceSeconds?: number;
|
|
54
64
|
/** Max tokens for the optional LLM nomination pass. */
|
|
55
|
-
curatorReviewMaxTokens?: number
|
|
65
|
+
curatorReviewMaxTokens?: Volatile<number>;
|
|
56
66
|
/** Timeout (ms) for the optional LLM nomination pass (B-10, v18). */
|
|
57
|
-
curatorReviewTimeoutMs?: number
|
|
67
|
+
curatorReviewTimeoutMs?: Volatile<number>;
|
|
58
68
|
/** Structure-health soft body limit (chars) — see DEFAULT_HEALTH_THRESHOLDS (rc.73 A1). */
|
|
59
|
-
healthSoftBodyChars?: number
|
|
69
|
+
healthSoftBodyChars?: Volatile<number>;
|
|
60
70
|
/** Structure-health stamp-density ceiling per KB — see DEFAULT_HEALTH_THRESHOLDS. */
|
|
61
|
-
healthStampDensityPerKb?: number
|
|
71
|
+
healthStampDensityPerKb?: Volatile<number>;
|
|
62
72
|
/** Structure-health write-ghost floor: patches at/above with zero reads (A2). */
|
|
63
|
-
healthChurnMinPatches?: number
|
|
73
|
+
healthChurnMinPatches?: Volatile<number>;
|
|
64
74
|
}
|
|
65
75
|
/** Curator behaviour a user may change (G3/S3.3). Field names are the CANONICAL
|
|
66
76
|
* parameter ids from the registry, so the settings document, the params output,
|
|
@@ -91,10 +101,6 @@ export interface CuratorSettings {
|
|
|
91
101
|
/** Patches without a read that flag a write-ghost skill. */
|
|
92
102
|
healthChurnMinPatches: number;
|
|
93
103
|
}
|
|
94
|
-
/** Schema the platform validates the user layer against; defaults mirror the core
|
|
95
|
-
* constants and the bounds mirror the row schema, so an empty document resolves to
|
|
96
|
-
* today's behaviour and an out-of-range value is refused instead of clamped. */
|
|
97
|
-
export declare const CURATOR_SETTINGS_SCHEMA: z<CuratorSettings>;
|
|
98
104
|
/**
|
|
99
105
|
* The cross-field rule the schema cannot express (A2-17): an archive threshold
|
|
100
106
|
* below the stale threshold makes the engine reactivate stale records instead of
|
|
@@ -103,7 +109,7 @@ export declare const CURATOR_SETTINGS_SCHEMA: z<CuratorSettings>;
|
|
|
103
109
|
* snapshot and the plugin row).
|
|
104
110
|
* @param value - the resolved section the platform hands the owner.
|
|
105
111
|
*/
|
|
106
|
-
export declare function validateCuratorSettings(value: CuratorSettings): void;
|
|
112
|
+
export declare function validateCuratorSettings(value: Pick<CuratorSettings, 'archiveAfterDays' | 'staleAfterDays'>): void;
|
|
107
113
|
/** Outcome of one curator run pass. */
|
|
108
114
|
export interface CuratorRunOutcome {
|
|
109
115
|
stale: string[];
|
|
@@ -136,35 +142,69 @@ export declare function gateConsolidations(consolidations: CuratorConsolidation[
|
|
|
136
142
|
}): CuratorConsolidation[];
|
|
137
143
|
export declare class EvolutionCurator extends Service {
|
|
138
144
|
static inject: string[];
|
|
139
|
-
static Config:
|
|
145
|
+
static Config: z<Schemastery.ObjectS<NoInfer<{
|
|
146
|
+
root: z<string, string, "defined">;
|
|
147
|
+
enabled: z<boolean, boolean, "defined">;
|
|
148
|
+
curatorIntervalHours: z<number, number, "volatile">;
|
|
149
|
+
intervalHours: z<number, number, "plain">;
|
|
150
|
+
staleAfterDays: z<number, number, "volatile-defined">;
|
|
151
|
+
archiveAfterDays: z<number, number, "volatile-defined">;
|
|
152
|
+
llmReview: z<boolean, boolean, "volatile-defined">;
|
|
153
|
+
curatorProvider: z<string, string, "defined">;
|
|
154
|
+
qualityWarnStaleAfterDays: z<number, number, "volatile-defined">;
|
|
155
|
+
minIdleHours: z<number, number, "volatile-defined">;
|
|
156
|
+
minIdleFailOpen: z<boolean, boolean, "volatile-defined">;
|
|
157
|
+
excludeSkillNames: z<string[], string[], "defined">;
|
|
158
|
+
manageUnmanaged: z<boolean, boolean, "defined">;
|
|
159
|
+
pruneBuiltins: z<boolean, boolean, "defined">;
|
|
160
|
+
referencedSkillNames: z<string[], string[], "defined">;
|
|
161
|
+
autoStart: z<boolean, boolean, "defined">;
|
|
162
|
+
bootGraceSeconds: z<number, number, "defined">;
|
|
163
|
+
curatorReviewMaxTokens: z<number, number, "volatile-defined">;
|
|
164
|
+
curatorReviewTimeoutMs: z<number, number, "volatile-defined">;
|
|
165
|
+
healthSoftBodyChars: z<number, number, "volatile-defined">;
|
|
166
|
+
healthStampDensityPerKb: z<number, number, "volatile-defined">;
|
|
167
|
+
healthChurnMinPatches: z<number, number, "volatile-defined">;
|
|
168
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
169
|
+
root: z<string, string, "defined">;
|
|
170
|
+
enabled: z<boolean, boolean, "defined">;
|
|
171
|
+
curatorIntervalHours: z<number, number, "volatile">;
|
|
172
|
+
intervalHours: z<number, number, "plain">;
|
|
173
|
+
staleAfterDays: z<number, number, "volatile-defined">;
|
|
174
|
+
archiveAfterDays: z<number, number, "volatile-defined">;
|
|
175
|
+
llmReview: z<boolean, boolean, "volatile-defined">;
|
|
176
|
+
curatorProvider: z<string, string, "defined">;
|
|
177
|
+
qualityWarnStaleAfterDays: z<number, number, "volatile-defined">;
|
|
178
|
+
minIdleHours: z<number, number, "volatile-defined">;
|
|
179
|
+
minIdleFailOpen: z<boolean, boolean, "volatile-defined">;
|
|
180
|
+
excludeSkillNames: z<string[], string[], "defined">;
|
|
181
|
+
manageUnmanaged: z<boolean, boolean, "defined">;
|
|
182
|
+
pruneBuiltins: z<boolean, boolean, "defined">;
|
|
183
|
+
referencedSkillNames: z<string[], string[], "defined">;
|
|
184
|
+
autoStart: z<boolean, boolean, "defined">;
|
|
185
|
+
bootGraceSeconds: z<number, number, "defined">;
|
|
186
|
+
curatorReviewMaxTokens: z<number, number, "volatile-defined">;
|
|
187
|
+
curatorReviewTimeoutMs: z<number, number, "volatile-defined">;
|
|
188
|
+
healthSoftBodyChars: z<number, number, "volatile-defined">;
|
|
189
|
+
healthStampDensityPerKb: z<number, number, "volatile-defined">;
|
|
190
|
+
healthChurnMinPatches: z<number, number, "volatile-defined">;
|
|
191
|
+
}>>, "plain">;
|
|
140
192
|
readonly skills: SkillLibrary;
|
|
141
193
|
private readonly io;
|
|
142
194
|
private readonly enabled;
|
|
143
|
-
|
|
144
|
-
private readonly
|
|
145
|
-
private readonly archiveAfterDays;
|
|
146
|
-
private readonly llmReview;
|
|
195
|
+
/** This row's live config (G1 §8.3): its volatile fields are resolved at USE time. */
|
|
196
|
+
private readonly config;
|
|
147
197
|
/** S1-C3: one warn per instance when `llmReview` is on but the llm service
|
|
148
198
|
* is absent — the channel silently degrading must be visible at least once. */
|
|
149
199
|
private llmAbsentWarned;
|
|
150
200
|
private readonly curatorProvider;
|
|
151
|
-
private readonly qualityWarnStaleAfterDays;
|
|
152
|
-
private readonly minIdleHours;
|
|
153
|
-
private readonly minIdleFailOpen;
|
|
154
201
|
private readonly excludeSkillNames;
|
|
155
202
|
private readonly manageUnmanaged;
|
|
156
203
|
private readonly pruneBuiltins;
|
|
157
204
|
private readonly referencedSkillNames;
|
|
158
205
|
private readonly bootGraceSeconds;
|
|
159
|
-
|
|
160
|
-
private readonly
|
|
161
|
-
private readonly healthSoftBodyChars;
|
|
162
|
-
private readonly healthStampDensityPerKb;
|
|
163
|
-
private readonly healthChurnMinPatches;
|
|
164
|
-
/** G3/S3.3: this row's resolved values — the base layer of the settings section. */
|
|
165
|
-
private readonly settingsBase;
|
|
166
|
-
/** The user layer for this row's namespace (absent provider = deployment values). */
|
|
167
|
-
private readonly overrides;
|
|
206
|
+
/** Keys whose supplied value had to be corrected; each warns once (G3.1). */
|
|
207
|
+
private readonly clampedKeys;
|
|
168
208
|
private lastRun;
|
|
169
209
|
private timer;
|
|
170
210
|
/** B-8 (v18): set by the fiber disposer; a triggered autoCheck must not
|
|
@@ -192,14 +232,66 @@ export declare class EvolutionCurator extends Service {
|
|
|
192
232
|
* yielding instance's log line names a concrete holder. */
|
|
193
233
|
private readonly instanceOwner;
|
|
194
234
|
constructor(ctx: Context, config?: Config);
|
|
235
|
+
/**
|
|
236
|
+
* Clamp one supplied numeric value, warning once per key (G3.1).
|
|
237
|
+
* @param key - the config key, for the warning.
|
|
238
|
+
* @param value - the value as supplied by the deployment or the user.
|
|
239
|
+
* @param fallback - the package default a corrected value falls back to.
|
|
240
|
+
* @param min - the smallest value the engine can act on.
|
|
241
|
+
* @param max - the largest value the carrier can hold, when bounded.
|
|
242
|
+
* @returns the value the engine may use.
|
|
243
|
+
*/
|
|
244
|
+
private clampOnce;
|
|
245
|
+
/**
|
|
246
|
+
* One live numeric row field at USE time (G1 §8.3): the row config carries the
|
|
247
|
+
* platform-resolved layers (schema default < bundle row < profile override) and the
|
|
248
|
+
* field stays a live reference, so a committed edit applies without a watcher.
|
|
249
|
+
* @param key - the canonical registry id of the field.
|
|
250
|
+
* @returns the current plain value, or undefined when nothing supplied one.
|
|
251
|
+
*/
|
|
252
|
+
private liveNumber;
|
|
253
|
+
/**
|
|
254
|
+
* One live numeric row field, clamped and warned once (G3.1).
|
|
255
|
+
* @param key - the canonical registry id of the field.
|
|
256
|
+
* @param fallback - the package default a corrected value falls back to.
|
|
257
|
+
* @param min - the smallest value the engine can act on.
|
|
258
|
+
* @param max - the largest value the carrier can hold, when bounded.
|
|
259
|
+
* @returns the value the engine may use.
|
|
260
|
+
*/
|
|
261
|
+
private rowNumber;
|
|
262
|
+
/**
|
|
263
|
+
* One live boolean row field at USE time.
|
|
264
|
+
* @param key - the canonical registry id of the field.
|
|
265
|
+
* @param fallback - the value used when the deployment supplied none.
|
|
266
|
+
* @returns the current value.
|
|
267
|
+
*/
|
|
268
|
+
private rowBoolean;
|
|
269
|
+
/**
|
|
270
|
+
* This row's resolved values — the base layer of the precedence chain (G1 §8.3).
|
|
271
|
+
* Resolved per call so a user edit is live; every numeric field is clamped.
|
|
272
|
+
* @returns the row layer of the curator's behaviour knobs.
|
|
273
|
+
*/
|
|
274
|
+
private rowSettings;
|
|
275
|
+
/**
|
|
276
|
+
* The keys the user set in this row's namespace (G1 §8.4-A).
|
|
277
|
+
*
|
|
278
|
+
* This is the ONLY remaining read of the settings user layer, and it reads KEY
|
|
279
|
+
* NAMES, never values: the platform resolves the user layer into the row config,
|
|
280
|
+
* so a value is needed from `config` — but the precedence rule (user > policy)
|
|
281
|
+
* needs to know WHICH keys the user set, or a deployment policy would silently
|
|
282
|
+
* override the user.
|
|
283
|
+
* @returns the keys present in this row's user layer.
|
|
284
|
+
*/
|
|
285
|
+
private userSetKeys;
|
|
195
286
|
/** The policy-snapshot carrier for this group (unmounted service = no policy). */
|
|
196
287
|
private policyFields;
|
|
197
288
|
/**
|
|
198
|
-
* G3/S3.3: the ONE reader of the curator's behaviour knobs. Precedence is
|
|
199
|
-
* user > policy snapshot > this row
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
289
|
+
* G3/S3.3 + G1: the ONE reader of the curator's behaviour knobs. Precedence is
|
|
290
|
+
* user > policy snapshot > this row: the row layer already carries the user value
|
|
291
|
+
* (a live field), and {@link userSetKeys} answers whether the user set the key —
|
|
292
|
+
* so an untouched key keeps following the deployment carriers exactly as before.
|
|
293
|
+
* Read at USE time: a committed settings change is live without a restart and
|
|
294
|
+
* without a watcher.
|
|
203
295
|
* @returns the resolved section, every numeric field sanitized.
|
|
204
296
|
*/
|
|
205
297
|
private settings;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmzhen/dsh-evolution-curator",
|
|
3
3
|
"description": "Deterministic skill lifecycle and recovery (community build)",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.17.0-rc.1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -27,20 +27,20 @@
|
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@deepseek-ai/schemastery": "^3.18.1",
|
|
30
|
-
"@lmzhen/dsh-evolution-core": "^0.
|
|
30
|
+
"@lmzhen/dsh-evolution-core": "^0.17.0-rc.1"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
34
|
-
"@deepseek-ai/dsh-llm": "^0.
|
|
35
|
-
"@deepseek-ai/dsh-session": "^0.
|
|
36
|
-
"@lmzhen/dsh-evolution-io": "^0.
|
|
37
|
-
"@lmzhen/dsh-evolution-state": "^0.
|
|
34
|
+
"@deepseek-ai/dsh-llm": "^0.2.0-rc.1",
|
|
35
|
+
"@deepseek-ai/dsh-session": "^0.2.0-rc.1",
|
|
36
|
+
"@lmzhen/dsh-evolution-io": "^0.17.0-rc.1",
|
|
37
|
+
"@lmzhen/dsh-evolution-state": "^0.17.0-rc.1"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@deepseek-ai/dsh-llm": "^0.
|
|
41
|
-
"@deepseek-ai/dsh-session": "^0.
|
|
42
|
-
"@lmzhen/dsh-evolution-core": "^0.
|
|
43
|
-
"@lmzhen/dsh-evolution-io": "^0.
|
|
44
|
-
"@lmzhen/dsh-evolution-state": "^0.
|
|
40
|
+
"@deepseek-ai/dsh-llm": "^0.2.0-rc.1",
|
|
41
|
+
"@deepseek-ai/dsh-session": "^0.2.0-rc.1",
|
|
42
|
+
"@lmzhen/dsh-evolution-core": "^0.17.0-rc.1",
|
|
43
|
+
"@lmzhen/dsh-evolution-io": "^0.17.0-rc.1",
|
|
44
|
+
"@lmzhen/dsh-evolution-state": "^0.17.0-rc.1"
|
|
45
45
|
}
|
|
46
46
|
}
|