@lmzhen/dsh-evolution-core 0.1.0-rc.50 → 0.1.0-rc.52
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 +6 -142
- package/lib/types/io.d.ts +3 -4
- package/lib/types/memory-store.d.ts +0 -3
- package/lib/types/state-store.d.ts +2 -22
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -2,14 +2,12 @@ import { basename, dirname, join } from "node:path";
|
|
|
2
2
|
import { cp, lstat, mkdir, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
3
3
|
import { createHash, randomBytes } from "node:crypto";
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
|
-
import { readFileSync } from "node:fs";
|
|
6
5
|
//#region lib/types/io.js
|
|
7
6
|
/**
|
|
8
|
-
* Structural IO seam for the
|
|
7
|
+
* Structural IO seam for the evolution plugin family.
|
|
9
8
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* (and the facade's own tests) can use `nodeEvolutionIo`.
|
|
9
|
+
* Every evolution package passes `ctx.evolutionIo.provider()`; standalone
|
|
10
|
+
* consumers (and the core's own tests) can use `nodeEvolutionIo`.
|
|
13
11
|
*/
|
|
14
12
|
/**
|
|
15
13
|
* Run `task` inside `io.transact` when the backend provides it; otherwise fall
|
|
@@ -1326,84 +1324,6 @@ var MemoryStore = class {
|
|
|
1326
1324
|
limit: this.limitFor(target)
|
|
1327
1325
|
};
|
|
1328
1326
|
}
|
|
1329
|
-
async replace(target, oldText, facts) {
|
|
1330
|
-
return this.mutate(target, oldText, "replace", facts);
|
|
1331
|
-
}
|
|
1332
|
-
async remove(target, oldText) {
|
|
1333
|
-
return this.mutate(target, oldText, "remove", void 0);
|
|
1334
|
-
}
|
|
1335
|
-
async mutate(target, oldText, action, facts) {
|
|
1336
|
-
const needle = oldText.trim();
|
|
1337
|
-
if (!needle) {
|
|
1338
|
-
const current = await this.read(target);
|
|
1339
|
-
return {
|
|
1340
|
-
ok: false,
|
|
1341
|
-
message: `old_text cannot be empty.${previewEntries(current)}`,
|
|
1342
|
-
entries: current,
|
|
1343
|
-
chars: current.join(ENTRY_DELIMITER).length,
|
|
1344
|
-
limit: this.limitFor(target)
|
|
1345
|
-
};
|
|
1346
|
-
}
|
|
1347
|
-
const refusal = await this.oversizedRefusal(target);
|
|
1348
|
-
if (refusal) return refusal;
|
|
1349
|
-
const content = action === "replace" ? (facts ?? "").trim() : "";
|
|
1350
|
-
if (action === "replace" && !content) return {
|
|
1351
|
-
ok: false,
|
|
1352
|
-
message: "facts is required for replace; use remove to delete.",
|
|
1353
|
-
entries: [],
|
|
1354
|
-
chars: 0,
|
|
1355
|
-
limit: this.limitFor(target)
|
|
1356
|
-
};
|
|
1357
|
-
if (action === "replace") {
|
|
1358
|
-
const threat = scanMemoryThreats(content);
|
|
1359
|
-
if (threat) return {
|
|
1360
|
-
ok: false,
|
|
1361
|
-
message: threat,
|
|
1362
|
-
entries: [],
|
|
1363
|
-
chars: 0,
|
|
1364
|
-
limit: this.limitFor(target)
|
|
1365
|
-
};
|
|
1366
|
-
}
|
|
1367
|
-
if (await this.detectDrift(target)) {
|
|
1368
|
-
const backup = await this.backupFile(target);
|
|
1369
|
-
return {
|
|
1370
|
-
ok: false,
|
|
1371
|
-
message: `External drift detected in memory file.${backup ? ` A backup was saved to ${basename(backup)}.` : ""} Resolve the drift before retrying.`,
|
|
1372
|
-
entries: [],
|
|
1373
|
-
chars: 0,
|
|
1374
|
-
limit: this.limitFor(target)
|
|
1375
|
-
};
|
|
1376
|
-
}
|
|
1377
|
-
const entries = await this.read(target);
|
|
1378
|
-
const matches = entries.map((entry, index) => ({
|
|
1379
|
-
entry,
|
|
1380
|
-
index
|
|
1381
|
-
})).filter(({ entry }) => entry.includes(needle));
|
|
1382
|
-
if (matches.length === 0) return this.failure(target, `No entry matching "${needle}" found.`, entries);
|
|
1383
|
-
if (new Set(matches.map((m) => m.entry)).size > 1) return {
|
|
1384
|
-
ok: false,
|
|
1385
|
-
message: `Multiple distinct entries matched "${needle}". Be more specific.`,
|
|
1386
|
-
entries,
|
|
1387
|
-
chars: entries.join(ENTRY_DELIMITER).length,
|
|
1388
|
-
limit: this.limitFor(target)
|
|
1389
|
-
};
|
|
1390
|
-
const index = matches[0]?.index ?? -1;
|
|
1391
|
-
const next = [...entries];
|
|
1392
|
-
if (action === "remove") next.splice(index, 1);
|
|
1393
|
-
else next[index] = content;
|
|
1394
|
-
const total = next.join(ENTRY_DELIMITER).length;
|
|
1395
|
-
const mutateLimit = this.limitFor(target);
|
|
1396
|
-
if (mutateLimit > 0 && total > mutateLimit) return this.failure(target, `Resulting memory would exceed the ${mutateLimit} char limit.`, entries);
|
|
1397
|
-
await this.write(target, next);
|
|
1398
|
-
this.resetFailures();
|
|
1399
|
-
return {
|
|
1400
|
-
ok: true,
|
|
1401
|
-
message: `Entry ${action === "remove" ? "removed" : "replaced"}.${this.storageHint(target, total)}`,
|
|
1402
|
-
entries: next,
|
|
1403
|
-
chars: total,
|
|
1404
|
-
limit: this.limitFor(target)
|
|
1405
|
-
};
|
|
1406
|
-
}
|
|
1407
1327
|
async applyBatch(target, operations) {
|
|
1408
1328
|
if (operations.length === 0) return {
|
|
1409
1329
|
ok: false,
|
|
@@ -2796,67 +2716,11 @@ var SkillLibrary = class {
|
|
|
2796
2716
|
//#endregion
|
|
2797
2717
|
//#region lib/types/state-store.js
|
|
2798
2718
|
/**
|
|
2799
|
-
*
|
|
2800
|
-
*
|
|
2719
|
+
* Evolution home path helper: `$DSH_HOME/evolution` for plugin-owned sidecar
|
|
2720
|
+
* state (reports, activity store, feedback file, state-domain data).
|
|
2801
2721
|
*/
|
|
2802
2722
|
function evolutionHome(env = process.env) {
|
|
2803
2723
|
return join(env.DSH_HOME ?? join(homedir(), ".dsh"), "evolution");
|
|
2804
2724
|
}
|
|
2805
|
-
var JsonState = class JsonState {
|
|
2806
|
-
initial;
|
|
2807
|
-
path;
|
|
2808
|
-
value;
|
|
2809
|
-
constructor(name, initial, env = process.env) {
|
|
2810
|
-
this.initial = initial;
|
|
2811
|
-
this.path = join(evolutionHome(env), name);
|
|
2812
|
-
this.value = this.loadSync();
|
|
2813
|
-
}
|
|
2814
|
-
/**
|
|
2815
|
-
* Deep-merge persisted state over the initial defaults. Nested plain
|
|
2816
|
-
* objects merge recursively (so a new default field added under an existing
|
|
2817
|
-
* object is preserved), while arrays and primitives take the on-disk value
|
|
2818
|
-
* wholesale. Keeps forward-compatible defaults across schema additions.
|
|
2819
|
-
*/
|
|
2820
|
-
static mergeDeep(initial, persisted) {
|
|
2821
|
-
const isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
2822
|
-
if (!isRecord(initial) || !isRecord(persisted)) return isRecord(persisted) ? persisted : persisted == null ? initial : persisted;
|
|
2823
|
-
const out = { ...initial };
|
|
2824
|
-
for (const [key, value] of Object.entries(persisted)) out[key] = key in initial ? JsonState.mergeDeep(initial[key], value) : value;
|
|
2825
|
-
return out;
|
|
2826
|
-
}
|
|
2827
|
-
loadSync() {
|
|
2828
|
-
try {
|
|
2829
|
-
const raw = readFileSync(this.path, "utf8");
|
|
2830
|
-
const parsed = JSON.parse(raw);
|
|
2831
|
-
return JsonState.mergeDeep(this.initial, parsed);
|
|
2832
|
-
} catch {
|
|
2833
|
-
return { ...this.initial };
|
|
2834
|
-
}
|
|
2835
|
-
}
|
|
2836
|
-
get() {
|
|
2837
|
-
return this.value;
|
|
2838
|
-
}
|
|
2839
|
-
set(value) {
|
|
2840
|
-
this.value = value;
|
|
2841
|
-
}
|
|
2842
|
-
update(mutator) {
|
|
2843
|
-
mutator(this.value);
|
|
2844
|
-
}
|
|
2845
|
-
async flush() {
|
|
2846
|
-
await mkdir(dirname(this.path), { recursive: true });
|
|
2847
|
-
const tmp = `${this.path}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`;
|
|
2848
|
-
await writeFile(tmp, JSON.stringify(this.value, null, 2), "utf8");
|
|
2849
|
-
await rename(tmp, this.path);
|
|
2850
|
-
}
|
|
2851
|
-
/** Merge-on-load helper for persisted maps/records. */
|
|
2852
|
-
async reload() {
|
|
2853
|
-
try {
|
|
2854
|
-
const raw = await readFile(this.path, "utf8");
|
|
2855
|
-
this.value = JsonState.mergeDeep(this.initial, JSON.parse(raw));
|
|
2856
|
-
} catch {
|
|
2857
|
-
this.value = { ...this.initial };
|
|
2858
|
-
}
|
|
2859
|
-
}
|
|
2860
|
-
};
|
|
2861
2725
|
//#endregion
|
|
2862
|
-
export { COMBINED_REVIEW_PROMPT, COMPLETION_SKILL_REVIEW_PROMPT, CURATOR_DRY_RUN_BANNER, CURATOR_PROMPT, DEFAULT_ARCHIVE_AFTER_DAYS, DEFAULT_CONSOLIDATION_FAILURES, DEFAULT_CURATOR_INTERVAL_HOURS, DEFAULT_MAX_OPS_PER_PLAN, DEFAULT_MEMORY_CHAR_LIMIT, DEFAULT_MIN_IDLE_HOURS, DEFAULT_MUTATION_CAP, DEFAULT_REVIEW_MEMORY_INTERVAL, DEFAULT_REVIEW_SKILL_INTERVAL, DEFAULT_SKILL_CONTENT_CHARS, DEFAULT_SKILL_LIMITS, DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS, DEFAULT_SKILL_REVIEW_TRIGGER, DEFAULT_STALE_AFTER_DAYS, DEFAULT_SUBSTANTIVE_MIN_AGENT_CHARS, DEFAULT_SUBSTANTIVE_MIN_TOOL_CALLS, DEFAULT_SUBSTANTIVE_MIN_USER_CHARS, DEFAULT_USER_CHAR_LIMIT, DSH_AUTHORING_STANDARDS, ENTRY_DELIMITER, EvolutionGateSet,
|
|
2726
|
+
export { COMBINED_REVIEW_PROMPT, COMPLETION_SKILL_REVIEW_PROMPT, CURATOR_DRY_RUN_BANNER, CURATOR_PROMPT, DEFAULT_ARCHIVE_AFTER_DAYS, DEFAULT_CONSOLIDATION_FAILURES, DEFAULT_CURATOR_INTERVAL_HOURS, DEFAULT_MAX_OPS_PER_PLAN, DEFAULT_MEMORY_CHAR_LIMIT, DEFAULT_MIN_IDLE_HOURS, DEFAULT_MUTATION_CAP, DEFAULT_REVIEW_MEMORY_INTERVAL, DEFAULT_REVIEW_SKILL_INTERVAL, DEFAULT_SKILL_CONTENT_CHARS, DEFAULT_SKILL_LIMITS, DEFAULT_SKILL_REVIEW_COMPLETION_MIN_TOOL_CALLS, DEFAULT_SKILL_REVIEW_TRIGGER, DEFAULT_STALE_AFTER_DAYS, DEFAULT_SUBSTANTIVE_MIN_AGENT_CHARS, DEFAULT_SUBSTANTIVE_MIN_TOOL_CALLS, DEFAULT_SUBSTANTIVE_MIN_USER_CHARS, DEFAULT_USER_CHAR_LIMIT, DSH_AUTHORING_STANDARDS, ENTRY_DELIMITER, EvolutionGateSet, LOW_QUALITY_THRESHOLD, MAX_DESCRIPTION_LENGTH, MAX_SKILL_CONTENT_CHARS, MAX_SKILL_FILE_BYTES, MAX_SKILL_NAME_LENGTH, MEMORY_REVIEW_PROMPT, MUTATIONS_FILE_VERSION, MemoryStore, PROMPT_BUNDLE, PROMPT_BUNDLE_ID, PROMPT_BUNDLE_VERSION, PROTECTED_BUILTIN_SKILLS, QUALITY_WEIGHTS, SKILL_NAME_RE, SKILL_REVIEW_PROMPT, SNAPSHOT_EXTRA_NAME_RE, SUPPORT_DIRS, SUPPRESSED_FILE_VERSION, SkillLibrary, advanceReview, buildCuratorRunReport, buildLearnPrompt, bumpPatch, bumpUse, bumpView, computeDedupGroups, computeLifecycleTransitions, computeQualityScores, computeScopeView, contentHash, createGateSet, emptyRecord, evaluateThreat, evolutionHome, evolutionIoAdapter, foldTurn, getRecord, latestActivityAt, lifecycleCandidate, loadMutations, loadSuppressedNames, loadUsage, markAgentCreated, memoryRoot, mutateUsage, mutationsFile, nodeEvolutionIo, normalizeUsageRecord, observeEvent, parseCuratorNominations, parseFrontmatter, recordMutation, relatedSkillNames, renderCuratorReportMarkdown, resolveOrigins, reviewPrompt, saveSuppressedNames, saveUsage, scanContentThreats, scanMemoryThreats, scanThreats, skillsRoot, suppressedFile, transactIo, updateSuppressedNames, usageFile, validateFrontmatter, verifyPromptBundle };
|
package/lib/types/io.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Structural IO seam for the
|
|
2
|
+
* Structural IO seam for the evolution plugin family.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* (and the facade's own tests) can use `nodeEvolutionIo`.
|
|
4
|
+
* Every evolution package passes `ctx.evolutionIo.provider()`; standalone
|
|
5
|
+
* consumers (and the core's own tests) can use `nodeEvolutionIo`.
|
|
7
6
|
*/
|
|
8
7
|
export interface EvolutionIoLike {
|
|
9
8
|
readText(path: string): Promise<string | null>;
|
|
@@ -72,9 +72,6 @@ export declare class MemoryStore {
|
|
|
72
72
|
*/
|
|
73
73
|
private oversizedRefusal;
|
|
74
74
|
add(target: MemoryTarget, facts: string): Promise<MemoryApplyResult>;
|
|
75
|
-
replace(target: MemoryTarget, oldText: string, facts: string): Promise<MemoryApplyResult>;
|
|
76
|
-
remove(target: MemoryTarget, oldText: string): Promise<MemoryApplyResult>;
|
|
77
|
-
private mutate;
|
|
78
75
|
applyBatch(target: MemoryTarget, operations: MemoryOperation[]): Promise<MemoryApplyResult>;
|
|
79
76
|
renderContext(): Promise<string>;
|
|
80
77
|
/**
|
|
@@ -1,26 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Evolution home path helper: `$DSH_HOME/evolution` for plugin-owned sidecar
|
|
3
|
+
* state (reports, activity store, feedback file, state-domain data).
|
|
4
4
|
*/
|
|
5
5
|
export declare function evolutionHome(env?: NodeJS.ProcessEnv): string;
|
|
6
|
-
export declare class JsonState<T> {
|
|
7
|
-
private readonly initial;
|
|
8
|
-
readonly path: string;
|
|
9
|
-
private value;
|
|
10
|
-
constructor(name: string, initial: T, env?: NodeJS.ProcessEnv);
|
|
11
|
-
/**
|
|
12
|
-
* Deep-merge persisted state over the initial defaults. Nested plain
|
|
13
|
-
* objects merge recursively (so a new default field added under an existing
|
|
14
|
-
* object is preserved), while arrays and primitives take the on-disk value
|
|
15
|
-
* wholesale. Keeps forward-compatible defaults across schema additions.
|
|
16
|
-
*/
|
|
17
|
-
private static mergeDeep;
|
|
18
|
-
private loadSync;
|
|
19
|
-
get(): T;
|
|
20
|
-
set(value: T): void;
|
|
21
|
-
update(mutator: (value: T) => void): void;
|
|
22
|
-
flush(): Promise<void>;
|
|
23
|
-
/** Merge-on-load helper for persisted maps/records. */
|
|
24
|
-
reload(): Promise<void>;
|
|
25
|
-
}
|
|
26
6
|
//# sourceMappingURL=state-store.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmzhen/dsh-evolution-core",
|
|
3
3
|
"description": "Shared stores, prompts, signals and lifecycle logic for the dsh-evolution plugin family (community build)",
|
|
4
|
-
"version": "0.1.0-rc.
|
|
4
|
+
"version": "0.1.0-rc.52",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|