@lmzhen/dsh-evolution-core 0.3.74 → 0.3.76
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/README.md +2 -0
- package/lib/index.js +1301 -640
- package/lib/types/constants.d.ts +5 -2
- package/lib/types/evolution-events.d.ts +12 -1
- package/lib/types/index.d.ts +7 -4
- package/lib/types/memory-store.d.ts +16 -0
- package/lib/types/probe.d.ts +38 -0
- package/lib/types/review-channel.d.ts +41 -0
- package/lib/types/scope.d.ts +27 -0
- package/lib/types/skill-store.d.ts +59 -25
- package/lib/types/tool-dispatch.d.ts +212 -0
- package/lib/types/usage.d.ts +7 -10
- package/package.json +3 -7
- package/lib/invariant.js +0 -8
- package/lib/types/invariant.d.ts +0 -5
package/lib/types/constants.d.ts
CHANGED
|
@@ -88,8 +88,11 @@ export declare const DEFAULT_CURATOR_BOOT_GRACE_SECONDS = 10;
|
|
|
88
88
|
export declare const DEFAULT_CURATOR_REVIEW_MAX_TOKENS = 2048;
|
|
89
89
|
/** 0.3.17 (S3.10, T-1): control-plane fields a model-facing write call may
|
|
90
90
|
* never carry — single source for plan-validator, evolution-policy and the
|
|
91
|
-
* threat scanner (they used to each hardcode the list).
|
|
92
|
-
|
|
91
|
+
* threat scanner (they used to each hardcode the list).
|
|
92
|
+
* P2-13 (v37): staged_from_sha256 joins the list — it is the replay's own
|
|
93
|
+
* staleness anchor, and the tool-arguments root is an OPEN object, so a model
|
|
94
|
+
* could otherwise choose the anchor that decides the write's outcome. */
|
|
95
|
+
export declare const FORBIDDEN_CONTROL_KEYS: readonly ["policy", "threshold", "prompt_hash", "model_route", "evolution_config", "staged_from_sha256"];
|
|
93
96
|
/** 0.3.17 (S3.10): the model-facing write tools the policy guard and threat
|
|
94
97
|
* scanner cover. */
|
|
95
98
|
export declare const EVOLUTION_WRITE_TOOLS: readonly ["memory", "skill_manage"];
|
|
@@ -49,6 +49,8 @@ export interface EvolutionEvent {
|
|
|
49
49
|
* count snapshot at the moment the observation window opened), and
|
|
50
50
|
* maintain scans (011: verdict + recommendation count + runId). */
|
|
51
51
|
type: 'feedback' | 'learn' | 'usage' | 'maintain';
|
|
52
|
+
/** Fold key for a `feedback` event: required and non-empty there (P2-10),
|
|
53
|
+
* optional on the other tags and on a record this version only reads. */
|
|
52
54
|
target?: string | undefined;
|
|
53
55
|
kind?: 'skill' | 'session' | undefined;
|
|
54
56
|
rating?: 'positive' | 'negative' | undefined;
|
|
@@ -70,6 +72,15 @@ export interface EvolutionEvent {
|
|
|
70
72
|
opened?: string;
|
|
71
73
|
} | undefined;
|
|
72
74
|
}
|
|
75
|
+
/** The durable-write shape of one event: `feedback` REQUIRES a `target` —
|
|
76
|
+
* the fold key the aggregate is keyed by (P2-10). The other tags keep every
|
|
77
|
+
* field optional, exactly as the runtime payload gate treats them. */
|
|
78
|
+
export type EvolutionEventInput = (Omit<EvolutionEvent, 'seq' | 'at' | 'target'> & {
|
|
79
|
+
type: 'feedback';
|
|
80
|
+
target: string;
|
|
81
|
+
}) | (Omit<EvolutionEvent, 'seq' | 'at'> & {
|
|
82
|
+
type: 'learn' | 'usage' | 'maintain';
|
|
83
|
+
});
|
|
73
84
|
export declare function eventsFile(home: string): string;
|
|
74
85
|
/** I-5 (v18): one lightweight description of the durable event payload
|
|
75
86
|
* contract. The log is a FILE boundary (a host, a script or an older version
|
|
@@ -108,7 +119,7 @@ export declare function listEventArchives(io: EvolutionIoLike, path: string): Pr
|
|
|
108
119
|
* — the active restarts AFTER the highest archived seq, never at 1, so a new
|
|
109
120
|
* event can never shadow an archived one in the seq-deduped timeline.
|
|
110
121
|
*/
|
|
111
|
-
export declare function appendEvolutionEvent(io: EvolutionIoLike, path: string, event:
|
|
122
|
+
export declare function appendEvolutionEvent(io: EvolutionIoLike, path: string, event: EvolutionEventInput, rotateAt?: number): Promise<number>;
|
|
112
123
|
/**
|
|
113
124
|
* Prune old event archives (rc.71): keep the newest `EVENT_LOG_RETAIN_ARCHIVES`.
|
|
114
125
|
* The name's numeric part is the last archived seq, so ordering is NUMERIC —
|
package/lib/types/index.d.ts
CHANGED
|
@@ -3,10 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Pure stores, prompts, signals, lifecycle logic, threat scanning, IO seam
|
|
5
5
|
* types, and session-event augmentations. This package ships no runtime
|
|
6
|
-
* plugin
|
|
7
|
-
* the
|
|
8
|
-
*
|
|
9
|
-
* bundles never depend on source subpaths.
|
|
6
|
+
* plugin and no `./invariant` companion (v37 S2.1); consumers import named
|
|
7
|
+
* exports from the package root so published npm bundles never depend on
|
|
8
|
+
* source subpaths.
|
|
10
9
|
*
|
|
11
10
|
* ## Layer map (OPT-28, 2026-09) — locate code by LAYER, not by directory
|
|
12
11
|
*
|
|
@@ -39,13 +38,17 @@ export * from './preset-composition.ts';
|
|
|
39
38
|
export * from './prompts.ts';
|
|
40
39
|
export * from './quality.ts';
|
|
41
40
|
export * from './redact.ts';
|
|
41
|
+
export * from './review-channel.ts';
|
|
42
42
|
export * from './serial.ts';
|
|
43
|
+
export * from './probe.ts';
|
|
44
|
+
export * from './scope.ts';
|
|
43
45
|
export * from './skill-health.ts';
|
|
44
46
|
export * from './signals.ts';
|
|
45
47
|
export * from './drift-signals.ts';
|
|
46
48
|
export * from './skill-store.ts';
|
|
47
49
|
export * from './state-store.ts';
|
|
48
50
|
export * from './threats.ts';
|
|
51
|
+
export * from './tool-dispatch.ts';
|
|
49
52
|
export * from './usage.ts';
|
|
50
53
|
export * from './constants.ts';
|
|
51
54
|
export * from './numeric.ts';
|
|
@@ -18,6 +18,22 @@ export interface MemoryApplyResult {
|
|
|
18
18
|
limit: number;
|
|
19
19
|
}
|
|
20
20
|
export declare function memoryRoot(env?: NodeJS.ProcessEnv): string;
|
|
21
|
+
/**
|
|
22
|
+
* Neutralize the platform's `{{name}}` prompt-variable syntax in text that is
|
|
23
|
+
* about to be registered as a `systemPrompt.context` contribution.
|
|
24
|
+
*
|
|
25
|
+
* The platform interpolates every context/section text once per model step and
|
|
26
|
+
* THROWS on an unknown or malformed reference — so one stored memory entry
|
|
27
|
+
* containing `{{...}}` (a CI expression, a Jinja/Helm/Vue template, a doc
|
|
28
|
+
* placeholder) used to fail `assemble()` on EVERY later pre-step of every
|
|
29
|
+
* session under this DSH_HOME, while a registered name such as `{{cwd}}` was
|
|
30
|
+
* silently substituted into the "memory" the model reads. Only the INJECTED
|
|
31
|
+
* text is neutralized: stored entries keep their original bytes.
|
|
32
|
+
*
|
|
33
|
+
* @param text - rendered context text about to leave for the prompt surface.
|
|
34
|
+
* @returns the same text with every `{{` split so it cannot start a reference.
|
|
35
|
+
*/
|
|
36
|
+
export declare function neutralizePromptVariables(text: string): string;
|
|
21
37
|
export interface MemoryStoreOptions {
|
|
22
38
|
memoryCharLimit?: number;
|
|
23
39
|
userCharLimit?: number;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V41 phase-1 follow-up: the read THREE-state (P2-25 sibling of N14).
|
|
3
|
+
*
|
|
4
|
+
* A read has three outcomes, not two: the value is there, it is genuinely not
|
|
5
|
+
* there, or we could not decide (IO error, unreadable store, missing
|
|
6
|
+
* provider). Collapsing the third into either of the others is how a broken
|
|
7
|
+
* store reads as "empty" and a guard silently passes — the class N14 registers.
|
|
8
|
+
* Migration target for the pre-existing two-state patches (protectionUnknown /
|
|
9
|
+
* unverifiable): constructors are prefixed so the type can never be confused
|
|
10
|
+
* with a value, and only `present` yields a value.
|
|
11
|
+
*/
|
|
12
|
+
export type Probe<T> = {
|
|
13
|
+
kind: 'present';
|
|
14
|
+
value: T;
|
|
15
|
+
} | {
|
|
16
|
+
kind: 'absent';
|
|
17
|
+
} | {
|
|
18
|
+
kind: 'unknown';
|
|
19
|
+
reason: string;
|
|
20
|
+
};
|
|
21
|
+
export declare function probePresent<T>(value: T): Probe<T>;
|
|
22
|
+
export declare function probeAbsent<T>(): Probe<T>;
|
|
23
|
+
export declare function probeUnknown<T>(reason: string): Probe<T>;
|
|
24
|
+
export declare function isPresent<T>(probe: Probe<T>): probe is {
|
|
25
|
+
kind: 'present';
|
|
26
|
+
value: T;
|
|
27
|
+
};
|
|
28
|
+
export declare function isAbsent<T>(probe: Probe<T>): probe is {
|
|
29
|
+
kind: 'absent';
|
|
30
|
+
};
|
|
31
|
+
export declare function isUnknown<T>(probe: Probe<T>): probe is {
|
|
32
|
+
kind: 'unknown';
|
|
33
|
+
reason: string;
|
|
34
|
+
};
|
|
35
|
+
/** Only a PRESENT probe yields a value; absent and unknown both fall back. */
|
|
36
|
+
export declare function valueOr<T>(probe: Probe<T>, fallback: T): T;
|
|
37
|
+
export declare function mapProbe<T, U>(probe: Probe<T>, transform: (value: T) => U): Probe<U>;
|
|
38
|
+
//# sourceMappingURL=probe.d.ts.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Family-internal mark for the review channel's INJECT delivery (v37 S2.2).
|
|
3
|
+
*
|
|
4
|
+
* With the default `reviewMode: 'inject'` the review prompt runs in the PARENT
|
|
5
|
+
* session, so the parent model's own `skill_manage` calls carry no origin the
|
|
6
|
+
* platform could attribute: `.pinned` and the `.hermes-managed` authorship mark
|
|
7
|
+
* were skipped for exactly the autonomous writes they exist for. The delivery
|
|
8
|
+
* marks the session here and the write path reads the mark.
|
|
9
|
+
*
|
|
10
|
+
* Window: after the review prompt, until the next REAL user message (a
|
|
11
|
+
* `user/message` with `source.kind === 'user'` clears it; plugin-sourced notices
|
|
12
|
+
* never do). Process-wide and keyed by session on purpose — the same
|
|
13
|
+
* "restart is a fresh conversation boundary" discipline as the review plugin's
|
|
14
|
+
* own per-session counters. This module is the ONE owner of the marker.
|
|
15
|
+
* @module @lmzhen/dsh-evolution-core/review-channel
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Mark one session as running the review channel's prompt; idempotent, and
|
|
19
|
+
* keyed by session so a mark can never leak into another session.
|
|
20
|
+
* @param sessionId - the session the review prompt was delivered to.
|
|
21
|
+
*/
|
|
22
|
+
export declare function markReviewChannel(sessionId: string): void;
|
|
23
|
+
/**
|
|
24
|
+
* Clear the mark: the session's next prompt is human input again.
|
|
25
|
+
* @param sessionId - the session whose mark is dropped.
|
|
26
|
+
*/
|
|
27
|
+
export declare function clearReviewChannel(sessionId: string): void;
|
|
28
|
+
/**
|
|
29
|
+
* Whether this session's current prompt came from the review channel. An
|
|
30
|
+
* execution without a session is never the review channel.
|
|
31
|
+
* @param sessionId - the executing session id, when the caller has one.
|
|
32
|
+
* @returns true only for a marked session.
|
|
33
|
+
*/
|
|
34
|
+
export declare function isReviewChannelSession(sessionId: string | undefined): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Drop marks whose session is gone — a dead session cannot execute a write.
|
|
37
|
+
* @param isAlive - liveness probe for one session id.
|
|
38
|
+
* @returns the number of removed marks.
|
|
39
|
+
*/
|
|
40
|
+
export declare function sweepReviewChannelSessions(isAlive: (sessionId: string) => boolean): number;
|
|
41
|
+
//# sourceMappingURL=review-channel.d.ts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V41 scope alignment: the ONE place that answers "in whose scope do we ask?".
|
|
3
|
+
*
|
|
4
|
+
* The platform's registry reads are scope-sensitive: `skills.list(options)`
|
|
5
|
+
* documents its `scope` as "the calling agent; OMITTED READS THE GLOBAL LAYER
|
|
6
|
+
* ALONE", and `tools.get(name, scope?)` resolves visibility the same way
|
|
7
|
+
* (packages/skill/skill/src/index.ts:113-120, packages/core/tools/src/index.ts:1194).
|
|
8
|
+
* A preset-mounted family row therefore lives in its PRESET'S STANDING SCOPE,
|
|
9
|
+
* so a scope-less read cannot see it — the asymmetry between "evolution mounted
|
|
10
|
+
* onto the original preset" and "the evolution variant preset".
|
|
11
|
+
*
|
|
12
|
+
* Resolution order (the single verdict; do not re-derive at call sites):
|
|
13
|
+
* 1. the scope the caller already holds (a tool invocation carrying one);
|
|
14
|
+
* 2. this plugin context's own scope — for a preset-mounted row that IS the
|
|
15
|
+
* preset's standing scope, i.e. exactly where the family's provider lives;
|
|
16
|
+
* 3. undefined, which callers must treat as an EXPLICIT global-layer read
|
|
17
|
+
* (registered per the arch guard's scope rule), never as a silent default.
|
|
18
|
+
*/
|
|
19
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
20
|
+
/** The platform's scope identity, kept structural so callers do not need the
|
|
21
|
+
* platform type (`ScopeKey` is `object`). */
|
|
22
|
+
export type OpaqueScopeKey = object;
|
|
23
|
+
export declare function callingScope(ctx: Context, held?: OpaqueScopeKey): OpaqueScopeKey | undefined;
|
|
24
|
+
/** True when a read is deliberately scope-less (global layer only). Callers
|
|
25
|
+
* pass this to the register so the choice is reviewed, not accidental. */
|
|
26
|
+
export declare function isGlobalRead(scope: OpaqueScopeKey | undefined): boolean;
|
|
27
|
+
//# sourceMappingURL=scope.d.ts.map
|
|
@@ -50,7 +50,12 @@ export interface SkillSummary {
|
|
|
50
50
|
protectedBy: string | null;
|
|
51
51
|
/** A1-17 (v18): the marker probe itself failed (EACCES/EIO), so "no marker"
|
|
52
52
|
* cannot be told apart from "directory unreadable". Consumers must treat this
|
|
53
|
-
* as protected, never as unprotected.
|
|
53
|
+
* as protected, never as unprotected.
|
|
54
|
+
* v41: this flag and `protectedBy` ARE the read three-state —
|
|
55
|
+
* (null, false) = no marker, (X, false) = present, (_, true) = unreadable.
|
|
56
|
+
* Read them together, never this flag alone; it is a published field, so the
|
|
57
|
+
* encoding stays (core's `Probe<T>` is for internal decisions, not for this
|
|
58
|
+
* contract). */
|
|
54
59
|
protectionUnknown: boolean;
|
|
55
60
|
managed: boolean;
|
|
56
61
|
/** E-11 (v18): the frontmatter `whenToUse` routing hint, published so the
|
|
@@ -221,20 +226,6 @@ export interface Frontmatter {
|
|
|
221
226
|
description?: string;
|
|
222
227
|
[key: string]: unknown;
|
|
223
228
|
}
|
|
224
|
-
/**
|
|
225
|
-
* Shared frontmatter block detection (P3-3 single owner): opening line `---`
|
|
226
|
-
* and closing line exactly `---`. Used by `parseFrontmatter`,
|
|
227
|
-
* `frontmatterCatalogInvalid` and `normalizeFrontmatter` so the three can
|
|
228
|
-
* never disagree about where the block ends (the loose `indexOf('\n---')`
|
|
229
|
-
* form matched `\n----` and was replaced by this strict line rule).
|
|
230
|
-
*
|
|
231
|
-
* V27 G2.1: both fence lines are matched EXACTLY, tolerating only a trailing
|
|
232
|
-
* `\r` — the same rule the upstream filesystem catalog uses
|
|
233
|
-
* (`skill-filesystem.parseFrontmatter`). The former `.trim()` comparison
|
|
234
|
-
* accepted ` --- `, so an indented fence loaded in the family while the
|
|
235
|
-
* platform ignored the file: family visibility split from platform visibility,
|
|
236
|
-
* which is exactly what a strict-YAML frontmatter is supposed to prevent.
|
|
237
|
-
*/
|
|
238
229
|
export declare function frontmatterBlock(content: string): {
|
|
239
230
|
block: string;
|
|
240
231
|
lines: string[];
|
|
@@ -260,9 +251,23 @@ export interface FrontmatterRead {
|
|
|
260
251
|
/** Whether the frontmatter is not valid AS WRITTEN for the strict platform
|
|
261
252
|
* catalog: the strict parser rejects the block, or an unquoted value would
|
|
262
253
|
* read as something other than its text (a dropped ` # ` comment, a
|
|
263
|
-
* number/bool shorthand the catalog refuses as a string field)
|
|
264
|
-
*
|
|
254
|
+
* number/bool shorthand the catalog refuses as a string field), or a
|
|
255
|
+
* platform string field carries a non-string value. The write path quotes
|
|
256
|
+
* such a value on its next edit. */
|
|
265
257
|
catalogInvalid: boolean;
|
|
258
|
+
/** Platform string fields (`name`/`description`/`whenToUse`) whose YAML value
|
|
259
|
+
* is not a string: the strict catalog reads such a field as ABSENT and, for an
|
|
260
|
+
* absent name/description, ignores the whole file (P2-9/v37). */
|
|
261
|
+
platformStringSplit: PlatformStringSplit[];
|
|
262
|
+
}
|
|
263
|
+
/** One `name`/`description`/`whenToUse` entry the strict catalog cannot read as
|
|
264
|
+
* a string, with the YAML kind the parser found. */
|
|
265
|
+
export interface PlatformStringSplit {
|
|
266
|
+
key: string;
|
|
267
|
+
/** The YAML type read for this field. `scalar` covers number/boolean (the
|
|
268
|
+
* E-47 auto-quote repair handles those); `sequence`/`mapping` are the shapes
|
|
269
|
+
* no rewrite can repair without inventing text — see `validateFrontmatter`. */
|
|
270
|
+
kind: 'sequence' | 'mapping' | 'scalar' | 'null';
|
|
266
271
|
}
|
|
267
272
|
/**
|
|
268
273
|
* Parse a SKILL.md: its frontmatter values and body, or `null` when the file
|
|
@@ -341,7 +346,9 @@ export declare function normalizeFrontmatter(content: string): FrontmatterNormal
|
|
|
341
346
|
* excluded. Pure and deduplicated.
|
|
342
347
|
*/
|
|
343
348
|
export declare function relatedSkillNames(content: string, exclude?: string): string[];
|
|
344
|
-
export declare function validateFrontmatter(content: string, expectedName?: string, limits?: SkillLimits
|
|
349
|
+
export declare function validateFrontmatter(content: string, expectedName?: string, limits?: SkillLimits,
|
|
350
|
+
/** On-disk bytes, so a NET SHRINK of an over-limit file is allowed (S1.2). */
|
|
351
|
+
current?: string | null): string | null;
|
|
345
352
|
/** Hermes authoring quality bar for descriptions — see constants.ts
|
|
346
353
|
* (0.3.16 T-4 moved the single source there; the public re-export sits behind
|
|
347
354
|
* the package root, which re-exports constants anyway). */
|
|
@@ -531,15 +538,16 @@ export declare class SkillLibrary {
|
|
|
531
538
|
* each support dir (write_file's lock sits next to its file). Residual:
|
|
532
539
|
* NESTED support-subdir locks and the probe→rename TOCTOU itself remain
|
|
533
540
|
* fail-safe (renameWithRetry rides the write out; the writer's locked
|
|
534
|
-
* re-read refuses on the moved-away file)
|
|
535
|
-
*
|
|
541
|
+
* re-read refuses on the moved-away file). v37 (P2-8): a residue `.lock` whose
|
|
542
|
+
* holder is GONE is not a writer — `decideTakeover` owns that verdict.
|
|
536
543
|
*/
|
|
537
544
|
private hasWriteLock;
|
|
538
|
-
/** P2 (v17): a file
|
|
539
|
-
* `pid:token
|
|
540
|
-
*
|
|
541
|
-
*
|
|
542
|
-
*
|
|
545
|
+
/** P2 (v17): a `*.lock` file counts as a writer lock only when its body
|
|
546
|
+
* carries the io layer's protocol — `pid:token`, a bare pid, or an empty body
|
|
547
|
+
* (a creator between create and body write); anything else is user content
|
|
548
|
+
* (suffix-only matching refused archiving and deleted user files on restore).
|
|
549
|
+
* v37 (P2-8): the verdict is `decideTakeover`'s, so the mover refuses exactly
|
|
550
|
+
* the lock the io layer refuses to reclaim, the 30s empty window included. */
|
|
543
551
|
private isWriterLock;
|
|
544
552
|
/** P2 (v16): best-effort removal of lock residue inside a RESTORED tree.
|
|
545
553
|
* A1-2/A1-7 (v18): the sweep now covers the marker locks the probe checks
|
|
@@ -684,4 +692,30 @@ export declare class SkillLibrary {
|
|
|
684
692
|
*/
|
|
685
693
|
private restoreSnapshotIntoRoot;
|
|
686
694
|
}
|
|
695
|
+
/** The emit surface the helper needs — structurally the platform context's
|
|
696
|
+
* `emit`, so core states the contract without importing the platform type. */
|
|
697
|
+
export interface SkillMutationSink {
|
|
698
|
+
emit: (type: 'evolution/skill-mutated', event: EvolutionSkillMutatedEvent) => unknown;
|
|
699
|
+
}
|
|
700
|
+
/** V41 P2-26 (0.3.75): the ONE SkillLibrary construction point.
|
|
701
|
+
*
|
|
702
|
+
* Eleven call sites used to re-derive the root and hand-roll the
|
|
703
|
+
* `evolution/skill-mutated` arrow (the catalog invalidates its cache on that
|
|
704
|
+
* exact string, so a second spelling is a silent divergence), and each one
|
|
705
|
+
* re-decided its own limits. `config` stays the RAW family config: resolving
|
|
706
|
+
* an empty `root` to the family default is `resolveSkillsRoot`'s policy, not
|
|
707
|
+
* a per-caller detail. */
|
|
708
|
+
export interface NewSkillLibraryOptions {
|
|
709
|
+
/** Raw family config; only `root` is read, through resolveSkillsRoot. */
|
|
710
|
+
config?: {
|
|
711
|
+
root?: string | undefined;
|
|
712
|
+
} | undefined;
|
|
713
|
+
io: EvolutionIoLike;
|
|
714
|
+
limits?: SkillLimits | undefined;
|
|
715
|
+
/** Supplying it wires the mutation event HERE — never at the call site. */
|
|
716
|
+
ctx?: SkillMutationSink | undefined;
|
|
717
|
+
transact?: typeof transactIo | undefined;
|
|
718
|
+
threatExemptLabels?: readonly string[] | undefined;
|
|
719
|
+
}
|
|
720
|
+
export declare function newSkillLibrary(options: NewSkillLibraryOptions): SkillLibrary;
|
|
687
721
|
//# sourceMappingURL=skill-store.d.ts.map
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The family's ONE reader of platform tool-dispatch events.
|
|
3
|
+
*
|
|
4
|
+
* The platform records a finished tool call under two different event
|
|
5
|
+
* vocabularies and only one of them is written per dispatch, chosen by the
|
|
6
|
+
* mounted tool runtime's mode:
|
|
7
|
+
*
|
|
8
|
+
* - native mode: \`tool/call\` (with \`callId\`) settled by \`tool/result\`, the
|
|
9
|
+
* write sites being core/agent-loop/src/tool-calls.ts:264 and :282.
|
|
10
|
+
* - PTC mode: \`tool/ptc-dispatch-start\` and \`tool/ptc-dispatch\` (with
|
|
11
|
+
* \`subCallId\`), the write sites being core/tools/src/ptc.ts:534 and :509.
|
|
12
|
+
*
|
|
13
|
+
* A consumer that matches a vocabulary directly therefore goes blind in the
|
|
14
|
+
* other mode while still appearing to work — the defect this module exists to
|
|
15
|
+
* make impossible. Every family consumer reads dispatches through
|
|
16
|
+
* \`ToolDispatchNormalizer\` (or the pure helpers below) and matches on
|
|
17
|
+
* \`ToolDispatchSignal\` fields only; \`verify-arch-guards\` rule N11 rejects a
|
|
18
|
+
* dispatch event-type comparison anywhere else.
|
|
19
|
+
*
|
|
20
|
+
* ## The one-dispatch invariant
|
|
21
|
+
*
|
|
22
|
+
* One dispatch produces exactly one \`ToolDispatchSignal\`, no matter how many
|
|
23
|
+
* events carry it: a start/settle pair for a PTC sub-dispatch, a call/result
|
|
24
|
+
* pair for a native call, or both vocabularies for the same call. Deduplication
|
|
25
|
+
* and outcome folding are keyed by the platform's own per-vocabulary call
|
|
26
|
+
* identity, which is stable across the pair (the platform's event JSDoc:
|
|
27
|
+
* "the pairing ids (matching the \`tool/ptc-dispatch-start\` with the same
|
|
28
|
+
* \`subCallId\`)").
|
|
29
|
+
*
|
|
30
|
+
* ## Layer
|
|
31
|
+
*
|
|
32
|
+
* Cross-cutting normalization: the reader half of the dispatch vocabulary,
|
|
33
|
+
* next to \`signals.ts\` (which folds the signals this module emits). Both are
|
|
34
|
+
* consumers; neither subscribes to the platform bus itself.
|
|
35
|
+
* @module
|
|
36
|
+
*/
|
|
37
|
+
/** How the platform delivered one dispatch. */
|
|
38
|
+
export type ToolDispatchKind =
|
|
39
|
+
/** A model-authored call, logged as \`tool/call\` and settled by \`tool/result\`. */
|
|
40
|
+
'native'
|
|
41
|
+
/** A sub-dispatch of a code program, logged as the PTC dispatch pair. */
|
|
42
|
+
| 'program'
|
|
43
|
+
/** A \`run_code\` call itself: a native call whose program dispatches sub-calls. */
|
|
44
|
+
| 'program-root';
|
|
45
|
+
/** The platform event type carrying a PTC sub-dispatch start. */
|
|
46
|
+
export declare const PTC_DISPATCH_START_EVENT = "tool/ptc-dispatch-start";
|
|
47
|
+
/** The platform event type carrying a PTC sub-dispatch settle. */
|
|
48
|
+
export declare const PTC_DISPATCH_EVENT = "tool/ptc-dispatch";
|
|
49
|
+
/** The platform event type carrying a native tool call. */
|
|
50
|
+
export declare const NATIVE_CALL_EVENT = "tool/call";
|
|
51
|
+
/** The platform event type carrying a native tool result. */
|
|
52
|
+
export declare const NATIVE_RESULT_EVENT = "tool/result";
|
|
53
|
+
/**
|
|
54
|
+
* The dispatch vocabulary this module owns. A consumer must never compare
|
|
55
|
+
* against these literals itself (rule N11); it compares \`kind\` instead.
|
|
56
|
+
*/
|
|
57
|
+
export declare const DISPATCH_EVENT_TYPES: readonly string[];
|
|
58
|
+
/**
|
|
59
|
+
* One normalized tool dispatch.
|
|
60
|
+
*
|
|
61
|
+
* Every field is derived from a platform event payload; the record is mutable
|
|
62
|
+
* and is updated in place when a later event of the same dispatch settles it,
|
|
63
|
+
* so a consumer that reacted at start already holds the outcome.
|
|
64
|
+
*/
|
|
65
|
+
export interface ToolDispatchSignal {
|
|
66
|
+
/** \`native\` | \`program\` (a code-program sub-dispatch) | \`program-root\` (the \`run_code\` call itself). */
|
|
67
|
+
readonly kind: ToolDispatchKind;
|
|
68
|
+
/** \`callId\` for a native call, \`subCallId\` for a PTC sub-dispatch — the platform's own identity. */
|
|
69
|
+
readonly callId: string;
|
|
70
|
+
/** The outer call: \`parentCallId\` for a PTC sub-dispatch, the call's own id for a native call. */
|
|
71
|
+
readonly rootCallId: string;
|
|
72
|
+
/** Dispatched tool name, always a non-empty string. */
|
|
73
|
+
readonly name: string;
|
|
74
|
+
/** Arguments as dispatched: a JSON string in native mode, the normalized object in PTC mode. */
|
|
75
|
+
readonly arguments: unknown;
|
|
76
|
+
/** Settled outcome: \`true\` succeeded, \`false\` failed, \`undefined\` still in flight. */
|
|
77
|
+
ok: boolean | undefined;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* \`TypeError\` thrown when a payload that claims to be a dispatch event
|
|
81
|
+
* violates the platform's event declaration. Named so a deployment can tell this
|
|
82
|
+
* refusal apart from a generic failure in a log line.
|
|
83
|
+
*/
|
|
84
|
+
export declare class ToolDispatchPayloadError extends TypeError {
|
|
85
|
+
name: string;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* The family's single dispatch ledger: absorbs platform events in log order,
|
|
89
|
+
* emits one \`ToolDispatchSignal\` per dispatch, and folds later events of the
|
|
90
|
+
* same dispatch into the record it already emitted.
|
|
91
|
+
*
|
|
92
|
+
* Consumers keep the \`ToolDispatchSignal\` object they received and re-read it
|
|
93
|
+
* later; no consumer needs to correlate events itself.
|
|
94
|
+
*/
|
|
95
|
+
export declare class ToolDispatchNormalizer {
|
|
96
|
+
private readonly records;
|
|
97
|
+
/** Call ids of \`run_code\`-class calls, i.e. of dispatches whose sub-dispatches are \`program\`. */
|
|
98
|
+
private readonly programRoots;
|
|
99
|
+
/**
|
|
100
|
+
* Absorb one session event.
|
|
101
|
+
* @param event - the event to absorb; any non-dispatch event is ignored.
|
|
102
|
+
* @returns the dispatch's signal when this event FIRST reveals the dispatch,
|
|
103
|
+
* otherwise \`null\` (the paired event of an already-emitted dispatch, or a
|
|
104
|
+
* non-dispatch event). A \`null\` return is never a dispatch to count again.
|
|
105
|
+
*/
|
|
106
|
+
advance(event: {
|
|
107
|
+
type: string;
|
|
108
|
+
data?: unknown;
|
|
109
|
+
}): ToolDispatchSignal | null;
|
|
110
|
+
/** Every emitted dispatch, in first-seen order. */
|
|
111
|
+
get signals(): readonly ToolDispatchSignal[];
|
|
112
|
+
/**
|
|
113
|
+
* Fold every event of a session log, in order.
|
|
114
|
+
* @param events - the log, oldest first.
|
|
115
|
+
* @returns one signal per dispatch, in first-seen order.
|
|
116
|
+
*/
|
|
117
|
+
foldAll(events: Iterable<{
|
|
118
|
+
type: string;
|
|
119
|
+
data?: unknown;
|
|
120
|
+
}>): ToolDispatchSignal[];
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Read one event into a dispatch record without a ledger (the pure half of the
|
|
124
|
+
* fold). Unlike the ledger it does NOT dedupe: a caller that walks a log and
|
|
125
|
+
* emits its own lines needs the call line on the event that opens the result.
|
|
126
|
+
* @param event - one session event; an absent event (an over-advanced index)
|
|
127
|
+
* answers \`null\` rather than throwing.
|
|
128
|
+
* @returns the dispatch this event opens, or \`null\` for any other event.
|
|
129
|
+
*/
|
|
130
|
+
export declare function readDispatchSignal(event: {
|
|
131
|
+
type?: string;
|
|
132
|
+
data?: unknown;
|
|
133
|
+
} | undefined): {
|
|
134
|
+
kind: ToolDispatchKind;
|
|
135
|
+
callId: string;
|
|
136
|
+
rootCallId: string;
|
|
137
|
+
name: string;
|
|
138
|
+
arguments: unknown;
|
|
139
|
+
} | null;
|
|
140
|
+
/**
|
|
141
|
+
* Is this dispatched tool name a single-skill read?
|
|
142
|
+
* @param name - the dispatched tool name.
|
|
143
|
+
* @returns \`true\` only for the read tool whose arguments name one skill.
|
|
144
|
+
*/
|
|
145
|
+
export declare function isSkillReadToolName(name: string): boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Does this signal read one skill, and did it not fail?
|
|
148
|
+
* @param signal - a normalized dispatch.
|
|
149
|
+
* @returns the skill name the dispatch read, or \`undefined\` when the dispatch
|
|
150
|
+
* is not a skill read or has failed. A dispatch whose outcome is still pending
|
|
151
|
+
* counts as a read: the platform settles every started sub-dispatch, so pending
|
|
152
|
+
* is a live-window state, not a failure.
|
|
153
|
+
*/
|
|
154
|
+
export declare function skillReadNameOf(signal: ToolDispatchSignal): string | undefined;
|
|
155
|
+
/**
|
|
156
|
+
* Fold one session log into its deduplicated dispatches.
|
|
157
|
+
* @param events - the log, oldest first. Pass an array, not a live snapshot
|
|
158
|
+
* iterator, when the log can grow while folding.
|
|
159
|
+
* @returns one signal per dispatch, in first-seen order.
|
|
160
|
+
*/
|
|
161
|
+
export declare function foldToolDispatches(events: Iterable<{
|
|
162
|
+
type: string;
|
|
163
|
+
data?: unknown;
|
|
164
|
+
}>): ToolDispatchSignal[];
|
|
165
|
+
/**
|
|
166
|
+
* Every skill name this log read through a dispatch, deduplicated by dispatch.
|
|
167
|
+
* @param events - the log, oldest first.
|
|
168
|
+
* @returns the names read by at least one non-failed skill dispatch.
|
|
169
|
+
*/
|
|
170
|
+
export declare function collectReadSkillNames(events: Iterable<{
|
|
171
|
+
type: string;
|
|
172
|
+
data?: unknown;
|
|
173
|
+
}>): Set<string>;
|
|
174
|
+
/**
|
|
175
|
+
* Does this dispatched tool name touch the skill library (read or mutate)?
|
|
176
|
+
* @param name - the dispatched tool name.
|
|
177
|
+
* @returns \`true\` for any skill-library tool. This is the review cadence's
|
|
178
|
+
* skill signal, which has always covered reads and writes alike.
|
|
179
|
+
*/
|
|
180
|
+
export declare function isSkillToolName(name: string): boolean;
|
|
181
|
+
/**
|
|
182
|
+
* Does this dispatched tool name open a code program?
|
|
183
|
+
* @param name - the dispatched tool name.
|
|
184
|
+
* @returns \`true\` for the tool whose sub-dispatches are \`program\` kind.
|
|
185
|
+
*/
|
|
186
|
+
export declare function isProgramToolName(name: string): boolean;
|
|
187
|
+
/**
|
|
188
|
+
* Assert that a payload really is the dispatch event it claims to be.
|
|
189
|
+
*
|
|
190
|
+
* The normalizer is deliberately lenient (it also folds persisted logs, where a
|
|
191
|
+
* payload may predate the current declaration); this is the loud gate for the
|
|
192
|
+
* live path, where a malformed payload means the producer is broken. It never
|
|
193
|
+
* silently downgrades: an unrecognized event type or a payload missing a
|
|
194
|
+
* declared field throws a named \`ToolDispatchPayloadError\`.
|
|
195
|
+
* @param event - the session event to check.
|
|
196
|
+
* @returns nothing; throws when the payload violates the platform declaration.
|
|
197
|
+
*/
|
|
198
|
+
export declare function assertDispatchPayload(event: {
|
|
199
|
+
type: string;
|
|
200
|
+
data?: unknown;
|
|
201
|
+
}): void;
|
|
202
|
+
/**
|
|
203
|
+
* Total dispatches in a log, deduplicated.
|
|
204
|
+
* @param events - the log, oldest first.
|
|
205
|
+
* @returns the number of distinct dispatches, one per dispatch regardless of
|
|
206
|
+
* how many events carried it.
|
|
207
|
+
*/
|
|
208
|
+
export declare function countDispatches(events: Iterable<{
|
|
209
|
+
type: string;
|
|
210
|
+
data?: unknown;
|
|
211
|
+
}>): number;
|
|
212
|
+
//# sourceMappingURL=tool-dispatch.d.ts.map
|
package/lib/types/usage.d.ts
CHANGED
|
@@ -59,18 +59,15 @@ export interface UsageMutateOptions {
|
|
|
59
59
|
onQuarantine?: ((message: string) => void) | undefined;
|
|
60
60
|
}
|
|
61
61
|
export declare function mutateUsage(root: string, io: EvolutionIoLike, task: (map: UsageMap) => void | Promise<void>, options?: UsageMutateOptions): Promise<void>;
|
|
62
|
-
/**
|
|
63
|
-
* Curator-owned usage fields (rc.67 K-2): the curator writes ONLY this set —
|
|
62
|
+
/** Curator-owned usage fields (rc.67 K-2): the curator writes ONLY this set —
|
|
64
63
|
* lifecycle state, archive stamp, the six-factor quality pair, and the
|
|
65
|
-
* marker-mirrored pin flag
|
|
66
|
-
* tool-telemetry side
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*/
|
|
71
|
-
export declare function applyCuratorFields(disk: UsageRecord, curated: UsageRecord): void;
|
|
64
|
+
* marker-mirrored pin flag; counters and activity stamps belong to the
|
|
65
|
+
* tool-telemetry side and are never copied by a fold. P2-12 (v39): the
|
|
66
|
+
* combined `applyCuratorFields` wrapper had no production caller (folds go
|
|
67
|
+
* through {@link foldCuratorFields}), so the two field copies below are the
|
|
68
|
+
* whole contract. */
|
|
72
69
|
/** Copy only the lifecycle pair (state/archived_at) — see the ownership split
|
|
73
|
-
* rationale
|
|
70
|
+
* rationale above. */
|
|
74
71
|
export declare function applyCuratorLifecycleFields(disk: UsageRecord, curated: UsageRecord): void;
|
|
75
72
|
/**
|
|
76
73
|
* Copy the recomputed meta pair (quality_score/quality_warn + the
|
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.3.
|
|
4
|
+
"version": "0.3.76",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -18,10 +18,6 @@
|
|
|
18
18
|
"types": "./lib/types/index.d.ts",
|
|
19
19
|
"default": "./lib/index.js"
|
|
20
20
|
},
|
|
21
|
-
"./invariant": {
|
|
22
|
-
"types": "./lib/types/invariant.d.ts",
|
|
23
|
-
"default": "./lib/invariant.js"
|
|
24
|
-
},
|
|
25
21
|
"./package.json": "./package.json"
|
|
26
22
|
},
|
|
27
23
|
"files": [
|
|
@@ -33,14 +29,14 @@
|
|
|
33
29
|
"js-yaml": "^4.2.0"
|
|
34
30
|
},
|
|
35
31
|
"peerDependencies": {
|
|
36
|
-
"@deepseek-ai/dsh-invariants": "^0.1.5-rc.2",
|
|
37
32
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
33
|
+
"@deepseek-ai/dsh-scope": "^0.1.5-rc.2",
|
|
38
34
|
"@deepseek-ai/dsh-session": "^0.1.5-rc.2"
|
|
39
35
|
},
|
|
40
36
|
"devDependencies": {
|
|
41
37
|
"@types/js-yaml": "^4.0.9",
|
|
42
|
-
"@deepseek-ai/dsh-invariants": "^0.1.5-rc.2",
|
|
43
38
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
39
|
+
"@deepseek-ai/dsh-scope": "^0.1.5-rc.2",
|
|
44
40
|
"@deepseek-ai/dsh-session": "^0.1.5-rc.2"
|
|
45
41
|
}
|
|
46
42
|
}
|
package/lib/invariant.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
//#region lib/types/invariant.js
|
|
2
|
-
const PACKAGE_NAME = "@lmzhen/dsh-evolution-core";
|
|
3
|
-
const name = "evolution-core-invariant";
|
|
4
|
-
const inject = ["invariants"];
|
|
5
|
-
const install = () => {};
|
|
6
|
-
const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
|
|
7
|
-
//#endregion
|
|
8
|
-
export { apply, inject, name };
|
package/lib/types/invariant.d.ts
DELETED