@lmzhen/dsh-evolution-activity 0.1.0-rc.9 → 0.2.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 +77 -42
- package/lib/types/index.d.ts +31 -23
- package/package.json +8 -6
package/lib/index.js
CHANGED
|
@@ -1,54 +1,89 @@
|
|
|
1
1
|
import z from "@deepseek-ai/schemastery";
|
|
2
|
-
import {
|
|
2
|
+
import { evolutionHome, evolutionIoAdapter, transactIo } from "@lmzhen/dsh-evolution-core";
|
|
3
|
+
import { join } from "node:path";
|
|
3
4
|
//#region lib/types/index.js
|
|
4
5
|
/**
|
|
5
|
-
*
|
|
6
|
+
* Durable activity store for self-evolution plan outcomes.
|
|
7
|
+
*
|
|
8
|
+
* Adjudication (rc.42, A-line P0-1): plan outcomes are process events on the
|
|
9
|
+
* cordis bus (a session log carrying `evolution/*` types is refused wholesale
|
|
10
|
+
* at resume), so the retired session projection is replaced by this driver:
|
|
11
|
+
* it subscribes to `evolution/plan-applied` (payload v2, with sessionId) and
|
|
12
|
+
* persists every outcome to `$DSH_HOME/evolution/activity.json` through the
|
|
13
|
+
* evolution IO seam — the same best-effort sidecar posture as
|
|
14
|
+
* `feedback.json` and the curator reports. A storage-domain table is deferred
|
|
15
|
+
* until a consumer needs domain routing (the domain spec version-gates its
|
|
16
|
+
* media, so adding a table is not a free schema addition).
|
|
17
|
+
*
|
|
18
|
+
* The sidecar is append-merge (load → fold → save under an in-process queue),
|
|
19
|
+
* so records survive host restarts and are readable without a session.
|
|
6
20
|
* @module @lmzhen/dsh-evolution-activity
|
|
7
21
|
*/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
/** Version of the `activity.json` shape; writers always emit the current one. */
|
|
23
|
+
const ACTIVITY_FILE_VERSION = 2;
|
|
24
|
+
function activityFile(root) {
|
|
25
|
+
return join(root, "activity.json");
|
|
26
|
+
}
|
|
27
|
+
/** Fold one plan-applied payload into a bounded record list (pure). */
|
|
28
|
+
function applyActivityEvent(items, event, maxItems, at = Date.now()) {
|
|
29
|
+
const record = {
|
|
30
|
+
sessionId: event.sessionId,
|
|
31
|
+
planId: event.planId,
|
|
32
|
+
policyFingerprint: event.policyFingerprint,
|
|
33
|
+
memoryApplied: event.memoryApplied,
|
|
34
|
+
skillApplied: event.skillApplied,
|
|
35
|
+
rejectedOps: event.rejectedOps,
|
|
36
|
+
evidenceQuotes: event.evidenceQuotes,
|
|
37
|
+
estimatedInputChars: event.estimatedInputChars,
|
|
38
|
+
at
|
|
39
|
+
};
|
|
40
|
+
const cap = Math.max(1, maxItems);
|
|
41
|
+
return [...items, record].slice(-cap);
|
|
42
|
+
}
|
|
43
|
+
/** Parse a raw sidecar into records; malformed content reads as empty (best-effort telemetry). */
|
|
44
|
+
function parseActivityContent(raw) {
|
|
45
|
+
if (raw === null) return [];
|
|
46
|
+
try {
|
|
47
|
+
const parsed = JSON.parse(raw);
|
|
48
|
+
return (typeof parsed === "object" && parsed !== null && Array.isArray(parsed.items) ? parsed.items : []).filter((item) => typeof item === "object" && item !== null && typeof item.planId === "string" && typeof item.sessionId === "string");
|
|
49
|
+
} catch {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function loadActivity(root, io) {
|
|
54
|
+
return parseActivityContent(await io.readText(activityFile(root)));
|
|
55
|
+
}
|
|
56
|
+
async function saveActivity(root, items, io) {
|
|
57
|
+
await io.writeText(activityFile(root), JSON.stringify({
|
|
58
|
+
version: 2,
|
|
59
|
+
items
|
|
60
|
+
}, null, 2));
|
|
28
61
|
}
|
|
29
62
|
const name = "evolution-activity";
|
|
30
|
-
const Config = z.object({ maxItems: z.number().default(
|
|
63
|
+
const Config = z.object({ maxItems: z.number().default(200) });
|
|
31
64
|
function apply(ctx, rawConfig = {}) {
|
|
32
|
-
const maxItems = rawConfig.maxItems ??
|
|
33
|
-
ctx.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
},
|
|
48
|
-
|
|
49
|
-
|
|
65
|
+
const maxItems = rawConfig.maxItems ?? 200;
|
|
66
|
+
const ioRegistry = ctx.get("evolutionIo");
|
|
67
|
+
if (!ioRegistry) {
|
|
68
|
+
ctx.logger.warn("evolution-activity: no evolution IO provider mounted; plan outcomes will not be persisted");
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const io = evolutionIoAdapter(() => ioRegistry.provider());
|
|
72
|
+
const root = evolutionHome();
|
|
73
|
+
let chain = Promise.resolve();
|
|
74
|
+
ctx.on("evolution/plan-applied", (event) => {
|
|
75
|
+
const run = chain.then(() => transactIo(io, activityFile(root), (current) => {
|
|
76
|
+
const items = applyActivityEvent(parseActivityContent(current), event, maxItems);
|
|
77
|
+
return Promise.resolve(JSON.stringify({
|
|
78
|
+
version: 2,
|
|
79
|
+
items
|
|
80
|
+
}, null, 2));
|
|
81
|
+
}));
|
|
82
|
+
chain = run.then(() => void 0, () => void 0);
|
|
83
|
+
run.catch((error) => {
|
|
84
|
+
ctx.logger.warn(error instanceof Error ? error : String(error));
|
|
50
85
|
});
|
|
51
86
|
});
|
|
52
87
|
}
|
|
53
88
|
//#endregion
|
|
54
|
-
export { Config, apply,
|
|
89
|
+
export { ACTIVITY_FILE_VERSION, Config, activityFile, apply, applyActivityEvent, loadActivity, name, parseActivityContent, saveActivity };
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1,41 +1,49 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Durable activity store for self-evolution plan outcomes.
|
|
3
|
+
*
|
|
4
|
+
* Adjudication (rc.42, A-line P0-1): plan outcomes are process events on the
|
|
5
|
+
* cordis bus (a session log carrying `evolution/*` types is refused wholesale
|
|
6
|
+
* at resume), so the retired session projection is replaced by this driver:
|
|
7
|
+
* it subscribes to `evolution/plan-applied` (payload v2, with sessionId) and
|
|
8
|
+
* persists every outcome to `$DSH_HOME/evolution/activity.json` through the
|
|
9
|
+
* evolution IO seam — the same best-effort sidecar posture as
|
|
10
|
+
* `feedback.json` and the curator reports. A storage-domain table is deferred
|
|
11
|
+
* until a consumer needs domain routing (the domain spec version-gates its
|
|
12
|
+
* media, so adding a table is not a free schema addition).
|
|
13
|
+
*
|
|
14
|
+
* The sidecar is append-merge (load → fold → save under an in-process queue),
|
|
15
|
+
* so records survive host restarts and are readable without a session.
|
|
3
16
|
* @module @deepseek-ai/dsh-evolution-activity
|
|
4
17
|
*/
|
|
5
18
|
import type { Context } from '@deepseek-ai/cordis';
|
|
6
19
|
import z from '@deepseek-ai/schemastery';
|
|
7
|
-
|
|
20
|
+
import type { EvolutionIoLike, EvolutionPlanAppliedEvent } from '@deepseek-ai/dsh-evolution-core';
|
|
21
|
+
/** One persisted plan outcome (payload v2 of `evolution/plan-applied`). */
|
|
22
|
+
export interface EvolutionActivityRecord {
|
|
23
|
+
sessionId: string;
|
|
8
24
|
planId: string;
|
|
9
|
-
|
|
25
|
+
policyFingerprint?: string | undefined;
|
|
10
26
|
memoryApplied: number;
|
|
11
27
|
skillApplied: number;
|
|
12
28
|
rejectedOps: number;
|
|
29
|
+
evidenceQuotes?: number | undefined;
|
|
30
|
+
estimatedInputChars?: number | undefined;
|
|
13
31
|
at: number;
|
|
14
32
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
planId: string;
|
|
25
|
-
memoryApplied: number;
|
|
26
|
-
skillApplied: number;
|
|
27
|
-
rejectedOps: number;
|
|
28
|
-
};
|
|
29
|
-
time: number;
|
|
30
|
-
} | {
|
|
31
|
-
type: string;
|
|
32
|
-
};
|
|
33
|
-
export declare function applyState(state: State, event: SessionEventLike, maxItems?: number): State;
|
|
33
|
+
/** Version of the `activity.json` shape; writers always emit the current one. */
|
|
34
|
+
export declare const ACTIVITY_FILE_VERSION = 2;
|
|
35
|
+
export declare function activityFile(root: string): string;
|
|
36
|
+
/** Fold one plan-applied payload into a bounded record list (pure). */
|
|
37
|
+
export declare function applyActivityEvent(items: EvolutionActivityRecord[], event: EvolutionPlanAppliedEvent, maxItems: number, at?: number): EvolutionActivityRecord[];
|
|
38
|
+
/** Parse a raw sidecar into records; malformed content reads as empty (best-effort telemetry). */
|
|
39
|
+
export declare function parseActivityContent(raw: string | null): EvolutionActivityRecord[];
|
|
40
|
+
export declare function loadActivity(root: string, io: EvolutionIoLike): Promise<EvolutionActivityRecord[]>;
|
|
41
|
+
export declare function saveActivity(root: string, items: EvolutionActivityRecord[], io: EvolutionIoLike): Promise<void>;
|
|
34
42
|
export declare const name = "evolution-activity";
|
|
35
43
|
export interface Config {
|
|
44
|
+
/** Bounded sidecar: how many recent outcomes are kept. */
|
|
36
45
|
maxItems?: number;
|
|
37
46
|
}
|
|
38
47
|
export declare const Config: z<Config>;
|
|
39
48
|
export declare function apply(ctx: Context, rawConfig?: Config): void;
|
|
40
|
-
export {};
|
|
41
49
|
//# sourceMappingURL=index.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmzhen/dsh-evolution-activity",
|
|
3
3
|
"description": "Session projection for self-evolution activity (community build)",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0-rc.1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -33,15 +33,17 @@
|
|
|
33
33
|
"license": "MIT",
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@deepseek-ai/schemastery": "^3.18.1",
|
|
36
|
-
"
|
|
36
|
+
"@lmzhen/dsh-evolution-core": "^0.2.0-rc.1"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"@deepseek-ai/dsh-invariants": "^0.1.0-rc.6",
|
|
40
39
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
41
|
-
"@deepseek-ai/dsh-
|
|
40
|
+
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.2"
|
|
42
41
|
},
|
|
43
42
|
"devDependencies": {
|
|
44
|
-
"@deepseek-ai/
|
|
45
|
-
"@deepseek-ai/dsh-
|
|
43
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
44
|
+
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
|
|
45
|
+
"@lmzhen/dsh-evolution-core": "^0.2.0-rc.1",
|
|
46
|
+
"@lmzhen/dsh-evolution-io": "^0.2.0-rc.1",
|
|
47
|
+
"@lmzhen/dsh-evolution-io-node": "^0.2.0-rc.1"
|
|
46
48
|
}
|
|
47
49
|
}
|