@avantf/dsh-mem 0.8.0 → 0.9.0

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.
Files changed (39) hide show
  1. package/lib/client.js +1088 -303
  2. package/lib/engine/graph-recall/index.d.ts +2 -2
  3. package/lib/engine/graph-recall/traverse.d.ts +2 -2
  4. package/lib/engine/graph-recall/types.d.ts +1 -1
  5. package/lib/engine/mem/config/config_files.d.ts +1 -1
  6. package/lib/engine/mem/defaults.d.ts +4 -1
  7. package/lib/engine/mem/entities/extract.d.ts +34 -14
  8. package/lib/engine/mem/index.d.ts +1 -0
  9. package/lib/engine/mem/modelBootstrap.d.ts +29 -0
  10. package/lib/engine/mem/store/graph_reader.d.ts +2 -2
  11. package/lib/engine/mem/store/memory.d.ts +53 -6
  12. package/lib/engine/mem/store/recall_policy.d.ts +10 -0
  13. package/lib/engine/mem-contract/config.d.ts +135 -0
  14. package/lib/engine/mem-contract/types.d.ts +11 -0
  15. package/lib/engine/mem-retrieval/adapters/auto_vstore.d.ts +10 -0
  16. package/lib/engine/mem-retrieval/adapters/hnswlib.d.ts +28 -0
  17. package/lib/engine/mem-retrieval/adapters/local_bge.d.ts +48 -6
  18. package/lib/engine/mem-retrieval/interfaces.d.ts +22 -2
  19. package/lib/engine/mem-retrieval/text_budget.d.ts +31 -0
  20. package/lib/index.js +1617 -114
  21. package/lib/interface-version.json +2 -2
  22. package/lib/types/client/index.d.ts.map +1 -1
  23. package/lib/types/client/paging.d.ts +58 -8
  24. package/lib/types/client/paging.d.ts.map +1 -1
  25. package/lib/types/client/time_filter.d.ts +54 -0
  26. package/lib/types/client/time_filter.d.ts.map +1 -0
  27. package/lib/types/deps_audit.d.ts +88 -0
  28. package/lib/types/deps_audit.d.ts.map +1 -0
  29. package/lib/types/envinit-bootstrap.d.ts +1 -1
  30. package/lib/types/envinit.d.ts +224 -4
  31. package/lib/types/envinit.d.ts.map +1 -1
  32. package/lib/types/hints.d.ts +58 -0
  33. package/lib/types/hints.d.ts.map +1 -1
  34. package/lib/types/index.d.ts.map +1 -1
  35. package/lib/types/render.d.ts.map +1 -1
  36. package/lib/types/runtime_deps_resource.d.ts +29 -0
  37. package/lib/types/runtime_deps_resource.d.ts.map +1 -0
  38. package/package.json +5 -4
  39. package/res/runtime-deps.yaml +99 -0
@@ -1,4 +1,4 @@
1
1
  {
2
- "baseVersion": "0.5.3",
3
- "interfaceVersion": 4
2
+ "baseVersion": "0.6.0",
3
+ "interfaceVersion": 6
4
4
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AA6DA,wDAAwD;AACxD,UAAU,aAAa;IACrB,KAAK,EAAE;QACL,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAA;QAChD,QAAQ,CACN,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,EAAE,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,MAAM,CAAA;SAAE,EACzE,SAAS,EAAE,MAAM,OAAO,GACvB,IAAI,CAAA;KACR,CAAA;IACD,MAAM,EAAE;QACN,wEAAwE;QACxE,MAAM,CAAC,YAAY,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;KAC5D,CAAA;IACD;;;;;OAKG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CAC3B;AAgqCD,2DAA2D;AAC3D,eAAO,MAAM,IAAI,sBAAsB,CAAA;AAEvC;;;;GAIG;AACH,eAAO,MAAM,MAAM,UAAsB,CAAA;AAEzC,8FAA8F;AAC9F,wBAAsB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA+B7D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAqFA,wDAAwD;AACxD,UAAU,aAAa;IACrB,KAAK,EAAE;QACL,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAA;QAChD,QAAQ,CACN,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,EAAE,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,MAAM,CAAA;SAAE,EACzE,SAAS,EAAE,MAAM,OAAO,GACvB,IAAI,CAAA;KACR,CAAA;IACD,MAAM,EAAE;QACN,wEAAwE;QACxE,MAAM,CAAC,YAAY,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;KAC5D,CAAA;IACD;;;;;OAKG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CAC3B;AA0sDD,2DAA2D;AAC3D,eAAO,MAAM,IAAI,sBAAsB,CAAA;AAEvC;;;;GAIG;AACH,eAAO,MAAM,MAAM,UAAsB,CAAA;AAEzC,8FAA8F;AAC9F,wBAAsB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA+B7D"}
@@ -1,21 +1,71 @@
1
1
  /**
2
- * Page merging for the fact list.
2
+ * Page merging for the tab's ONE list.
3
3
  *
4
4
  * Kept out of `client/index.ts` so it can be tested without a DOM (the same reason `summarize.ts`
5
5
  * lives on its own): this is where page drift is handled, and page drift is the kind of bug that
6
6
  * only shows up as a React key warning plus a row nobody can scroll to.
7
7
  *
8
+ * There used to be TWO helpers here — one keyed by `fact_id` for the admin list and one by `ref_id` for
9
+ * a time window's results — because the tab kept two lists. It keeps one now (`ListState`), so there is
10
+ * one merge: the row's React key is the identity, and both sources are appended through it.
11
+ *
8
12
  * @module client/paging
9
13
  */
10
14
  /**
11
- * Append one page of facts, dropping ids already present.
15
+ * Append one page of list rows, dropping keys already present.
16
+ *
17
+ * Both sources page by `OFFSET` over `created_at DESC`, and `created_at` has second precision: a fact
18
+ * written (or archived) between two requests shifts every later row by one, so the next page repeats a
19
+ * row that is already on screen. The duplicate is not cosmetic — it is a React key collision
20
+ * (`key={row.key}`) and a row that can never be scrolled to.
12
21
  *
13
- * `admin.list` pages by `OFFSET` over `created_at DESC`, and `created_at` has second precision: a
14
- * fact written (or archived) between two requests shifts every later row by one, so the next page
15
- * repeats a row that is already on screen. The duplicate is not cosmetic — it is a React key
16
- * collision (`key={fact_id}`) and a row that can never be scrolled to.
22
+ * A fact-shaped row's `key` is `fact:<id>`, so this stays exactly as strict as the two helpers it
23
+ * replaced; a relation path row is keyed by its position and cannot collide with one.
17
24
  */
18
- export declare function mergePage<T extends {
19
- fact_id: number;
25
+ export declare function mergeRows<T extends {
26
+ key: string;
20
27
  }>(previous: T[], page: T[]): T[];
28
+ /**
29
+ * Fold the pages of a WALKED window into the list's rows (REVIEW-2026-10-27 P1-1).
30
+ *
31
+ * The walk in `runTimeWindow` requests page after page from `offset` 0, and the drift the merge above
32
+ * guards against happens BETWEEN those requests just as it does between two scroll-triggered pages: a
33
+ * fact written while page 2 is in flight shifts the window, so page 3 repeats a row of page 2. Collecting
34
+ * the raw hits and mapping them once (what the walk did) therefore duplicated a row inside the FIRST
35
+ * render — a duplicate React key, a card that cannot be scrolled to, and a `total - rows.length` that
36
+ * under-reports. Folding through {@link mergeRows} makes the walk and the continuation the same rule.
37
+ *
38
+ * Note what this does NOT touch: the host-handed offsets (`nextOffset`) still advance by the page's own
39
+ * length, never by the de-duplicated row count — the cursor follows the HOST's paging, the rows follow
40
+ * what is actually on screen.
41
+ */
42
+ export declare function mergeRowPages<T extends {
43
+ key: string;
44
+ }>(pages: readonly (readonly T[])[]): T[];
45
+ /** The paging fields of the list state a page replaces (`ListState`'s subset, kept React-free here). */
46
+ export interface PagedRows<T> {
47
+ rows: T[];
48
+ nextOffset: number;
49
+ truncated: boolean;
50
+ }
51
+ /**
52
+ * Append ONE continuation page of a walked time window (`loadSearchPage`), and decide whether the window
53
+ * still has a page to fetch (REVIEW-2026-10-27 P1-2).
54
+ *
55
+ * `truncated` is the host's own rule — `offset + hits.length < total` — and NOT "did the row count grow".
56
+ * A page whose rows are all already on screen (extreme, but real: many facts inserted at the top between
57
+ * two requests shift every later row) adds nothing to `rows`, yet the anchor has moved, so claiming "no
58
+ * more rows" there stops the window for good while half of it is still unread.
59
+ *
60
+ * The one case that DOES stop is a page with no rows at all: the anchor cannot advance
61
+ * (`offset + 0 === offset`), so keeping `truncated` true would re-ask the same offset on every scroll.
62
+ * That is the empty page the host answers with when it has nothing more, not a repeated page.
63
+ */
64
+ export declare function appendWindowPage<T extends {
65
+ key: string;
66
+ }>(previous: PagedRows<T>, page: {
67
+ rows: T[];
68
+ offset: number;
69
+ total: number;
70
+ }): PagedRows<T>;
21
71
  //# sourceMappingURL=paging.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"paging.d.ts","sourceRoot":"","sources":["../../../src/client/paging.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAEtF"}
1
+ {"version":3,"file":"paging.d.ts","sourceRoot":"","sources":["../../../src/client/paging.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAIlF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,EAAE,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAE9F;AAED,wGAAwG;AACxG,MAAM,WAAW,SAAS,CAAC,CAAC;IAC1B,IAAI,EAAE,CAAC,EAAE,CAAA;IACT,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,EACxD,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,EACtB,IAAI,EAAE;IAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACjD,SAAS,CAAC,CAAC,CAAC,CAOd"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * The 记忆 tab's TIME window, built from the toolbar controls
3
+ * (docs/TIME_SEARCH_AND_CATEGORIES §3; contract `TimeFilter`).
4
+ *
5
+ * WHAT THIS IS. A pure mapping from "what the three controls say" to the `time` argument
6
+ * `recall.search` accepts, plus the one-line label the result panel prints. It lives in its own
7
+ * module — no React, no CSS module — so the shape it produces is covered by a real unit test
8
+ * instead of a source-text assertion: the host validates the argument with `TimeFilterSchema`
9
+ * (`field` required, `on` XOR `from`/`to`, at least one bound), and a shape that drifts there fails
10
+ * as an empty answer, not as an error the user can read.
11
+ *
12
+ * THE TWO FORMS. `on` is a whole local day. `range` is the half-open `[from, to)` window; ONE open
13
+ * end is legal and means "from then on" / "up to then" — the engine accepts a single bound, so this
14
+ * module does not invent a second one. Empty controls are `undefined`, which is what makes "no time
15
+ * condition" unambiguous in `runSearch` (an empty object would be a request the host rejects).
16
+ *
17
+ * THE AXES. `created`/`updated`/`event` are the contract's `TIME_FIELDS`, mirrored here as labels
18
+ * because the client bundle must not pull the whole contract as a VALUE (it imports only the
19
+ * `/remote` subpath and erased types): a runtime import of `TIME_FIELDS` would drag the tool unions
20
+ * into the browser artifact. `client_surface.spec.ts` pins this list against `TIME_FIELDS`, so the
21
+ * mirror cannot drift silently.
22
+ *
23
+ * @module client/time_filter
24
+ */
25
+ import type { TimeField, TimeFilter } from '../../engine/mem-contract/index.js';
26
+ /** Which bound form the user picked: one whole day, or a `from`~`to` window. */
27
+ export type TimeMode = 'on' | 'range';
28
+ /**
29
+ * The three time axes, with the labels the toolbar shows. The axis is REQUIRED by the contract (D1)
30
+ * and the three do not substitute for one another, so the control never defaults to "any time".
31
+ */
32
+ export declare const TIME_AXES: readonly {
33
+ value: TimeField;
34
+ label: string;
35
+ }[];
36
+ /**
37
+ * Build the `time` argument from the controls. `undefined` = no time condition at all.
38
+ *
39
+ * In `on` mode the range inputs are IGNORED (the contract refuses `on` together with `from`/`to`,
40
+ * so a stale value in the hidden inputs must never leak into a request). Values are the native
41
+ * `YYYY-MM-DD` a date input produces; they are passed through untouched — the engine owns the
42
+ * grammar, including the timezone reading of a date without an offset.
43
+ */
44
+ export declare function buildTimeFilter(field: TimeField, mode: TimeMode, on: string, from: string, to: string): TimeFilter | undefined;
45
+ /**
46
+ * The panel's one-line statement of the window the visible results were narrowed to.
47
+ *
48
+ * WHY THE PANEL NEEDS IT: a time-filtered answer is shorter than the list, and without a line naming
49
+ * the window, "fewer rows than expected" is indistinguishable from a broken query. It is rendered
50
+ * from the filter the RESULTS were fetched with (not from the live controls), so editing a date
51
+ * input cannot relabel results that were fetched with the previous window.
52
+ */
53
+ export declare function timeFilterLabel(time: TimeFilter): string;
54
+ //# sourceMappingURL=time_filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time_filter.d.ts","sourceRoot":"","sources":["../../../src/client/time_filter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAEjE,gFAAgF;AAChF,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG,OAAO,CAAA;AAErC;;;GAGG;AACH,eAAO,MAAM,SAAS,EAAE,SAAS;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAInE,CAAA;AAUD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,SAAS,EAChB,IAAI,EAAE,QAAQ,EACd,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT,UAAU,GAAG,SAAS,CAaxB;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAMxD"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * What the audit knows about one configured entry.
3
+ *
4
+ * `unknown` is a real state and NOT a synonym for `missing`: it means the question has not been
5
+ * answered yet (the audit has not run for it, or the probe itself failed). A notice conditioned on
6
+ * `missing` must stay silent for it — "cannot tell" never becomes a warning in a user's session.
7
+ *
8
+ * `pending` means a background install is in flight (runtime-deps only). It also matches nothing:
9
+ * reporting an install as a failure before it settles is exactly the false alarm this exists to
10
+ * prevent.
11
+ */
12
+ export type DependencyState = 'available' | 'failed' | 'missing' | 'skipped' | 'pending' | 'unknown';
13
+ /** The states a MODULE probe may answer with (an item probe additionally reports `pending`). */
14
+ export type ProbedState = Exclude<DependencyState, 'pending'>;
15
+ /**
16
+ * The read-only half: what a notice predicate is allowed to consult on the prompt path.
17
+ *
18
+ * Both members are synchronous and cheap by contract — `state()` is a map read and `vectors()` is the
19
+ * vector store's live count. `envinit.ts` calls them from inside a session-notice predicate on every
20
+ * step.
21
+ */
22
+ export interface DependencySnapshot {
23
+ /** The last recorded state of the entry with this id; `unknown` for an id nobody configured. */
24
+ state(id: string): DependencyState;
25
+ /** Live vector count in the index (what an entry's `min_vectors` is compared against). */
26
+ vectors(): number;
27
+ }
28
+ /** One configured entry's probe. */
29
+ export interface DependencyProbe {
30
+ /** The audit entry's id (from the shipped declaration); the key the state is recorded under. */
31
+ readonly id: string;
32
+ /** Run it and report the observation. Must not throw (a throw is caught and recorded as unknown). */
33
+ check(): Promise<DependencyState>;
34
+ }
35
+ /** What {@link createDependencyAudit} needs. */
36
+ export interface DependencyAuditOptions {
37
+ readonly probes: readonly DependencyProbe[];
38
+ /** Live vector count; see {@link DependencySnapshot.vectors}. */
39
+ vectors: () => number;
40
+ readonly logger?: {
41
+ info(message: string): void;
42
+ warn(message: string): void;
43
+ };
44
+ }
45
+ /** The audit handle: the snapshot plus the two refresh entry points. */
46
+ export interface DependencyAudit extends DependencySnapshot {
47
+ /** Audit every configured entry once. Never rejects (a failing probe is recorded, not thrown). */
48
+ run(): Promise<void>;
49
+ /** Re-audit ONE entry. Unknown ids are ignored. */
50
+ runId(id: string): Promise<void>;
51
+ }
52
+ /**
53
+ * Build the audit.
54
+ *
55
+ * Every configured entry starts `unknown`; nothing is assumed about an entry that has not been
56
+ * checked. The caller runs it once (fire-and-forget) and again for the entries a settlement could
57
+ * change — that ordering is what makes a session line appear only after there is an observation.
58
+ */
59
+ export declare function createDependencyAudit(options: DependencyAuditOptions): DependencyAudit;
60
+ /**
61
+ * Resolve and LOAD one specifier, from the first root that can serve it and then from this tree.
62
+ *
63
+ * The `createRequire(<root>/package.json)` anchor is the same rule the semantic adapter uses: a
64
+ * shared runtime-deps root's `package.json` is what makes `resolve` look in THAT root's
65
+ * `node_modules`, so the audit observes the copy the runtime would load. The import is by FILE URL
66
+ * because the resolved entry is inside the root, not a bare specifier this module could resolve.
67
+ *
68
+ * The three answers are deliberately distinct, because they lead to different repairs:
69
+ *
70
+ * - `available` — it loaded;
71
+ * - `failed` — something RESOLVED but loading it threw (the node-gyp build that exists and does not
72
+ * work: the case a bare `resolve()` check would report as healthy);
73
+ * - `missing` — nothing resolved anywhere.
74
+ *
75
+ * A root that cannot serve the specifier is not an error: the next candidate is tried, which is what
76
+ * makes a garbage-collected store no worse than no self-heal. Never throws.
77
+ */
78
+ export declare function moduleProbe(id: string, specifier: string, roots: () => readonly string[]): Promise<ProbedState>;
79
+ /**
80
+ * Observe one runtime-deps ITEM's state through the caller's own lookup.
81
+ *
82
+ * The caller owns the mapping (its provisioner's `resolve` plus the "declared but not settled" gate),
83
+ * so this probe adds nothing but a defensive boundary: a throwing lookup is `unknown`, not a failure
84
+ * claim. `pending` is passed through because it is a MEANINGFUL state — an install in flight — and the
85
+ * notice predicate treats it as "not reportable yet".
86
+ */
87
+ export declare function itemProbe(id: string, itemId: string, stateOf: (itemId: string) => DependencyState): DependencyProbe;
88
+ //# sourceMappingURL=deps_audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deps_audit.d.ts","sourceRoot":"","sources":["../../src/deps_audit.ts"],"names":[],"mappings":"AAqCA;;;;;;;;;;GAUG;AACH,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAA;AAKpG,gGAAgG;AAChG,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC,eAAe,EAAE,SAAS,CAAC,CAAA;AAE7D;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,gGAAgG;IAChG,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,CAAA;IAClC,0FAA0F;IAC1F,OAAO,IAAI,MAAM,CAAA;CAClB;AAED,oCAAoC;AACpC,MAAM,WAAW,eAAe;IAC9B,gGAAgG;IAChG,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,qGAAqG;IACrG,KAAK,IAAI,OAAO,CAAC,eAAe,CAAC,CAAA;CAClC;AAED,gDAAgD;AAChD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,CAAA;IAC3C,iEAAiE;IACjE,OAAO,EAAE,MAAM,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE;QAChB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;QAC3B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAC5B,CAAA;CACF;AAED,wEAAwE;AACxE,MAAM,WAAW,eAAgB,SAAQ,kBAAkB;IACzD,kGAAkG;IAClG,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACpB,mDAAmD;IACnD,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACjC;AAYD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,GAAG,eAAe,CAuEtF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,WAAW,CAC/B,EAAE,EAAE,MAAM,EACV,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,SAAS,MAAM,EAAE,GAC7B,OAAO,CAAC,WAAW,CAAC,CA4BtB;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,eAAe,GAAG,eAAe,CAWnH"}
@@ -3,7 +3,7 @@
3
3
  * @module bootstrap
4
4
  */
5
5
  /** The bootstrap version; the resolved framework must satisfy {@link supportedRange}. */
6
- export declare const VERSION = "0.5.3";
6
+ export declare const VERSION = "0.6.0";
7
7
  /**
8
8
  * The framework interval this bootstrap can launch.
9
9
  *
@@ -1,4 +1,6 @@
1
- import type { ProvisionReportEntry } from '@avantf/dsh-plugin-base';
1
+ import type { Config, RuntimeDepsResource } from '../engine/mem-contract/index.js';
2
+ import type { ProvisionReportEntry, RuntimeDepsHandle, RuntimeDepsSpec, SessionNoticeRegistry, SessionNoticeSpec } from '@avantf/dsh-plugin-base';
3
+ import { type RuntimeDepsResourceLoad } from './runtime_deps_resource.js';
2
4
  import { type CompatModule, type CompatRuntime } from './provision.js';
3
5
  /** The base's module shape; `import type` only — the value is always loaded dynamically. */
4
6
  type EnvinitModule = typeof import('@avantf/dsh-plugin-base');
@@ -7,6 +9,26 @@ type EnvinitModule = typeof import('@avantf/dsh-plugin-base');
7
9
  * names rather than re-spelling literals.
8
10
  */
9
11
  export declare const MODEL_ITEM = "mem:model";
12
+ /**
13
+ * The shared runtime-dependency item: `@huggingface/transformers` repaired through the base's
14
+ * content-addressed store when `semantic.self_heal.enabled` is on. Same root as every other family
15
+ * plugin's item for the same package set.
16
+ */
17
+ export declare const SEMANTIC_DEPS_ITEM = "mem:semantic-deps";
18
+ /**
19
+ * The NATIVE runtime-dependency item: `nodejieba` + `hnswlib-node`, repaired through the same base
20
+ * mechanism when `semantic.native_self_heal.enabled` is on.
21
+ *
22
+ * A SEPARATE item, not a third package in {@link SEMANTIC_DEPS_ITEM}, for two reasons that both
23
+ * matter:
24
+ *
25
+ * - the store is content-addressed, so this spec's package set (two node-gyp builds) keys a
26
+ * DIFFERENT immutable root under `<home>/deps/runtime/` — these packages are never installed into
27
+ * the transformers root, and vice versa;
28
+ * - the two have independent failure modes and independent consequences (semantic leg vs.
29
+ * entity/jaccard legs vs. ANN index), so one install failing must not report the other as broken.
30
+ */
31
+ export declare const NATIVE_DEPS_ITEM = "mem:native-deps";
10
32
  /** The logging surface this module needs — `AvantfLogger` satisfies it. */
11
33
  interface EnvinitLogger {
12
34
  info(message: string): void;
@@ -44,6 +66,77 @@ export interface ResourcePlan {
44
66
  readonly files: readonly string[];
45
67
  readonly endpoint: string;
46
68
  } | undefined;
69
+ /**
70
+ * The shared `runtime-deps` declaration for `@huggingface/transformers`: the spec the base's
71
+ * content-addressed store installs, or `undefined` when self-heal is off / not applicable (see
72
+ * {@link managedSemanticDepsSpec}). Declared only when the operator opted in: this item may run a
73
+ * package-manager install at startup. What a session is told about the package is a
74
+ * `audit` entry in `res/runtime-deps.yaml`, not part of this plan.
75
+ */
76
+ readonly semanticDeps?: SemanticDepsPlan | undefined;
77
+ /**
78
+ * The `runtime-deps` declaration for the NATIVE optional dependencies (`nodejieba`,
79
+ * `hnswlib-node`), or `undefined` when `semantic.native_self_heal.enabled` is off (see
80
+ * {@link managedNativeDepsSpec}). Independent of {@link semanticDeps}: a different package set, a
81
+ * different store root, a different failure.
82
+ */
83
+ readonly nativeDeps?: NativeDepsPlan | undefined;
84
+ /**
85
+ * The STARTUP DEPENDENCY AUDIT entries (see `audit:` in `res/runtime-deps.yaml`, the contract's
86
+ * `RuntimeDepsResourceSchema`, and `deps_audit.ts`): what to observe, how loud, under which
87
+ * condition, and the shipped text.
88
+ *
89
+ * Handed over with the plan because it is config, not wiring: `envinit` builds the generic probes
90
+ * from it, runs them at the end of the mount (`startDependencyAudit`) and again on every settle, and
91
+ * registers one session notice per entry. An empty/absent list means no notice at all — the plugin
92
+ * ships no sentence about any package.
93
+ */
94
+ readonly dependencyAudit?: readonly DependencyAuditNotice[] | undefined;
95
+ /**
96
+ * The live vector-index size, which a `min_vectors` threshold is compared against.
97
+ *
98
+ * A callback because the only cheap, always-current source is the runtime's own index (`MemoryStore`),
99
+ * which this module must not import: `envinit` is the bootstrap-side module and reaches the engine
100
+ * through the caller. Read synchronously on the prompt path, by contract.
101
+ */
102
+ readonly vectorCount?: (() => number) | undefined;
103
+ }
104
+ /**
105
+ * One shared `runtime-deps` item: the SPEC the base's store installs.
106
+ *
107
+ * What a session is told while it is not ready is NOT here: notices are `audit` entries in the shipped
108
+ * `res/runtime-deps.yaml` (`ResourcePlan.dependencyAudit`), judged on an observation rather than on an
109
+ * item, and one entry may describe a package no item installs. Two lifetimes, two places — a text edit
110
+ * must not look like a new dependency set.
111
+ */
112
+ export interface SemanticDepsPlan {
113
+ readonly spec: RuntimeDepsSpec;
114
+ }
115
+ /**
116
+ * One configured audit entry, resolved for execution: WHAT to probe (`probe`) plus the delivery fields
117
+ * the session-notice registry needs.
118
+ *
119
+ * The probe is a closed union of the two KINDS this build implements — a module load and a runtime-deps
120
+ * item state — and nothing here names a package: `specifier`/`item` come from the config verbatim.
121
+ */
122
+ export interface DependencyAuditNotice {
123
+ readonly id: string;
124
+ readonly severity: SessionNoticeSpec['severity'];
125
+ readonly when: SessionNoticeSpec['when'];
126
+ /** Corpus-size threshold: the line waits until the live index is at least this big (`0` = always). */
127
+ readonly minVectors: number;
128
+ readonly body: string;
129
+ readonly probe: {
130
+ readonly kind: 'module';
131
+ readonly specifier: string;
132
+ } | {
133
+ readonly kind: 'runtime-deps';
134
+ readonly item: string;
135
+ };
136
+ }
137
+ /** The native `runtime-deps` item: spec + the operator's notices for it. */
138
+ export interface NativeDepsPlan {
139
+ readonly spec: RuntimeDepsSpec;
47
140
  }
48
141
  /**
49
142
  * The model item the framework should own, or `undefined` when it should not.
@@ -69,6 +162,46 @@ export declare function managedModelSpec(semantic: {
69
162
  readonly cache_dir: string;
70
163
  readonly mirror: string;
71
164
  }, modelsRoot: string): ResourcePlan['model'];
165
+ /**
166
+ * The `runtime-deps` spec the base's shared store should own, or `undefined` when it should not.
167
+ *
168
+ * Refused when:
169
+ *
170
+ * 1. **self-heal is off** — the shipped default. Enabling it is a network decision the operator
171
+ * makes (`semantic.self_heal.enabled`), never a startup surprise.
172
+ * 2. **the backend is not `local_bge`** — this item repairs the module the local ONNX adapter
173
+ * loads; a third-party backend owns its own dependencies.
174
+ * 3. **no package was declared** — `spec.packages` must be non-empty (the base rejects an empty
175
+ * map); declaring nothing is cleaner than a guaranteed `invalid-option`.
176
+ *
177
+ * The config layers are copied field by field, not passed through: the schema's defaults include an
178
+ * empty `cache` placeholder that has to become the family root here (`<home>/cache/npm`), because
179
+ * the schema cannot know which family root the host will resolve. An explicitly configured cache is
180
+ * `~`-expanded, exactly like every other path in this plugin.
181
+ */
182
+ export declare function managedSemanticDepsSpec(semantic: Config['semantic'], declaration: RuntimeDepsResource['semantic'], home: string): RuntimeDepsSpec | undefined;
183
+ /**
184
+ * The `runtime-deps` spec for the NATIVE packages, or `undefined` when nothing should be declared.
185
+ *
186
+ * Refused only when `semantic.native_self_heal.enabled` is off or the package map is empty. There is
187
+ * no backend condition here (unlike the semantic spec): the tokenizer and the vector store are used
188
+ * by every backend, and a `vectorStore.backend: local_numpy` deployment still pays for `nodejieba`.
189
+ */
190
+ export declare function managedNativeDepsSpec(semantic: Config['semantic'], declaration: RuntimeDepsResource['native'], home: string): RuntimeDepsSpec | undefined;
191
+ /**
192
+ * The configured dependency-audit entries, copied field by field and resolved for execution.
193
+ *
194
+ * Why this is not part of a self-heal spec: the spec is what the base INSTALLS (and part of the shared
195
+ * root's content key, so it has to be exactly the provider's vocabulary), while an audit entry is a
196
+ * PROMPT line plus the observation behind it. Two consumers, two lifetimes — editing a sentence must
197
+ * not look like a new dependency set.
198
+ *
199
+ * The entries are returned VERBATIM (text, severity, condition) and no default is invented: the
200
+ * config's default is the empty array, so a profile that never wrote one gets no injection at all.
201
+ * `min_vectors` is defaulted to `0` here, and to nothing else — this section names no package, so it
202
+ * also invents no package-specific threshold.
203
+ */
204
+ export declare function managedDependencyAudit(audit: readonly RuntimeDepsResource['audit'][number][] | undefined): readonly DependencyAuditNotice[];
72
205
  /** The loaded framework + gate + the roots the runtime should use. */
73
206
  export interface EnvinitRuntime {
74
207
  /**
@@ -90,10 +223,67 @@ export interface EnvinitRuntime {
90
223
  * Declare the expensive resources and dispatch them in the BACKGROUND.
91
224
  *
92
225
  * Returns immediately; each item reaches `onSettled` when it settles (usually `present` right
93
- * away, or `installed`/`failed`/`skipped` later). A callback that throws is logged by the
94
- * framework, never fatal.
226
+ * away, or `installed`/`failed`/`skipped` later). The second argument is the resource's `dir` when
227
+ * the framework reports it ready — the shared `runtime-deps` root for `mem:semantic-deps`, and the
228
+ * model root for `mem:model`. A callback that throws is logged by the framework, never fatal.
229
+ *
230
+ * `onFailure` fires only when dispatching itself fails (a rejected `ensure`), not when an item
231
+ * settles as `failed`. The caller uses it to keep its own fallback warm instead of waiting for a
232
+ * settlement that will not arrive.
233
+ */
234
+ provisionResources(plan: ResourcePlan, onSettled: (entry: ProvisionReportEntry, handleDir?: string) => void, onFailure?: (error: unknown) => void): void;
235
+ /**
236
+ * The shared `mem:semantic-deps` handle the base built for this process, or `undefined`.
237
+ *
238
+ * `undefined` in every case where the item is not declared: self-heal off, not the local ONNX
239
+ * backend, or a loaded base without the v6 helper. Otherwise the handle exists from the moment
240
+ * `provisionResources` declared the item — BEFORE it settles, deliberately: the caller's pre-step
241
+ * consults {@link RuntimeDepsHandle.notices} on every step, and the registry's state predicate is
242
+ * what answers "is it broken right now", so nothing here has to be cached or invalidated.
243
+ *
244
+ * The whole handle is handed back rather than just its registry: `item` is what was declared,
245
+ * `resolve()` is the shared root (`undefined` until the item is ready) and `ensure()`/`load()` are
246
+ * the caller's sequencing surface. mem itself needs the first two plus the registry; `load()` is
247
+ * documented as unused by this plugin because the module import belongs to the base-free retrieval
248
+ * adapter (`packages/retrieval-core`), which resolves the same root with `createRequire`.
249
+ */
250
+ runtimeDeps(): RuntimeDepsHandle | undefined;
251
+ /**
252
+ * The shared `mem:native-deps` handle (nodejieba + hnswlib-node), or `undefined` when the item was
253
+ * not declared.
254
+ *
255
+ * Same lifecycle as {@link runtimeDeps}: the handle exists as soon as `provisionResources` declared
256
+ * the item, and `resolve()` answers the root once it is ready. The plugin needs `resolve()` for the
257
+ * module directories it hands to the tokenizer and the vector store, and `notices` for the session
258
+ * lines — a different registry from the semantic one, judged on a different item.
95
259
  */
96
- provisionResources(plan: ResourcePlan, onSettled: (entry: ProvisionReportEntry) => void): void;
260
+ nativeDeps(): RuntimeDepsHandle | undefined;
261
+ /**
262
+ * The session-notice registry the shipped audit entries were registered on, or
263
+ * `undefined` when there are none / the loaded base has no registry (interface v6).
264
+ *
265
+ * ONE registry for every entry, because an entry is not bound to an item: a `module` entry observes
266
+ * a package and a `runtime-deps` entry observes an item, and both are delivery decisions of the same
267
+ * session. The caller consumes it on the prompt path; its predicates read the audit's cached state.
268
+ */
269
+ notices(): SessionNoticeRegistry | undefined;
270
+ /**
271
+ * The plugin's OWN dependency declaration (`res/runtime-deps.yaml`), as the mount read it.
272
+ *
273
+ * `ok: false` means the file was missing/unreadable/malformed: the loader already logged an ERROR
274
+ * and the specs/audit were simply not declared, so the runtime keeps every optional dependency's own
275
+ * fallback. Exposed so a caller (and a test) can see WHICH state the mount is in instead of inferring
276
+ * it from an absent item.
277
+ */
278
+ depsResource(): RuntimeDepsResourceLoad;
279
+ /**
280
+ * Run the startup dependency audit — the LAST phase of the mount, called once by the caller.
281
+ *
282
+ * The caller does not await it: probing loads an optional package and, for a native addon,
283
+ * `dlopen`s it, which must not hold the host's boot. The promise is returned only so a test (and a
284
+ * future diagnostic) can await the observations; `agent/pre-step` still only CONSUMES the registry.
285
+ */
286
+ startDependencyAudit(): Promise<void>;
97
287
  /** Release every provisioner this runtime created (leases included). */
98
288
  dispose(): void;
99
289
  }
@@ -109,7 +299,37 @@ interface EnvinitLoadOptions {
109
299
  readonly framework?: EnvinitModule;
110
300
  /** Test seam: a partial module to derive the gate from, instead of `framework` itself. */
111
301
  readonly compatModule?: CompatModule;
302
+ /**
303
+ * Test seam: where the dependency declaration is read from. Production always uses
304
+ * `res/runtime-deps.yaml` next to the installed package (see `runtime_deps_resource.ts`).
305
+ */
306
+ readonly depsResourceUrl?: URL;
112
307
  }
308
+ /**
309
+ * Whether the loaded base can serve the shared `runtime-deps` item AND observe it.
310
+ *
311
+ * Three members are required, and all three are one capability here: `RUNTIME_DEPS_KIND` /
312
+ * `runtimeDepsProvider` (interface v5, base 0.6.0) install the root, and `createRuntimeDeps`
313
+ * (interface v6, base 0.7.0) is what DECLARES the item and binds the notices to its state. Since the
314
+ * item is now built by that helper, a base with the provider but not the helper cannot serve this
315
+ * plugin at all — so the predicate answers the caller's real question ("may I declare, wait for and
316
+ * translate this item?") instead of a narrower one that would let a half-wired declaration through.
317
+ *
318
+ * An OLDER generation does not normally reach this point — the interface gate withholds the whole
319
+ * base first (`gateOrDegrade`), so the plugin takes its legacy path. This guard covers the remaining
320
+ * shape: a module that reports a current generation but does not actually carry the members (a
321
+ * partial/hostile module, or a packaging mistake). Enabling self-heal must then degrade to the
322
+ * runtime's optional-dependency path, not throw from `declare`. It is also what lets the fake
323
+ * framework in the tests exercise that degradation instead of a TypeError.
324
+ *
325
+ * Exported because the startup caller asks the same question: a skipped item will never settle, so
326
+ * `startManagedResources` must not wait for it (see `packages/plugin/src/index.ts`). One predicate,
327
+ * two readers — the loader's skip and the caller's "do not wait" can never disagree.
328
+ *
329
+ * `undefined` (the test seam's partial framework, or no module at all) answers `false`: nothing is
330
+ * served, so nothing may be awaited.
331
+ */
332
+ export declare function supportsRuntimeDeps(framework: EnvinitModule | undefined): boolean;
113
333
  /**
114
334
  * Ensure the framework, then the compatibility base, then dispatch the expensive resources.
115
335
  *
@@ -1 +1 @@
1
- {"version":3,"file":"envinit.d.ts","sourceRoot":"","sources":["../../src/envinit.ts"],"names":[],"mappings":"AAiDA,OAAO,KAAK,EAAiB,oBAAoB,EAAe,MAAM,yBAAyB,CAAA;AAG/F,OAAO,EAKL,KAAK,YAAY,EACjB,KAAK,aAAa,EACnB,MAAM,gBAAgB,CAAA;AAKvB,4FAA4F;AAC5F,KAAK,aAAa,GAAG,cAAc,yBAAyB,CAAC,CAAA;AAK7D;;;GAGG;AACH,eAAO,MAAM,UAAU,cAAc,CAAA;AAmDrC,2EAA2E;AAC3E,UAAU,aAAa;IACrB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAC7B;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,8FAA8F;IAC9F,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAA;IAC1C;;;;;;;;OAQG;IACH,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAA;IACnC;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,EACV;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GACvF,SAAS,CAAA;CACd;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE;IACR,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB,EACD,UAAU,EAAE,MAAM,GACjB,YAAY,CAAC,OAAO,CAAC,CAQvB;AAOD,sEAAsE;AACtE,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,GAAG,EAAE,aAAa,GAAG,SAAS,CAAA;IACvC,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,2FAA2F;IAC3F,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,SAAS,CAAA;IAC1C,gEAAgE;IAChE,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IACnE;;;;;;OAMG;IACH,kBAAkB,CAAC,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,GAAG,IAAI,CAAA;IAC9F,wEAAwE;IACxE,OAAO,IAAI,IAAI,CAAA;CAChB;AAED,uCAAuC;AACvC,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,GAAG,CAAC,EAAE,aAAa,CAAA;IAC5B,6FAA6F;IAC7F,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,mHAAmH;IACnH,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAA;IAC/B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,yFAAyF;IACzF,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAA;IAClC,0FAA0F;IAC1F,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAA;CACrC;AA8GD;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAEjG"}
1
+ {"version":3,"file":"envinit.d.ts","sourceRoot":"","sources":["../../src/envinit.ts"],"names":[],"mappings":"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"}
@@ -16,6 +16,12 @@
16
16
  * `agent/pre-step` listener), and the harness shows such a message in the trace as coming from the
17
17
  * user. Without an author, a line like "记忆里有相关内容" reads as something the user said. The
18
18
  * `[avantf-mem]` prefix is what keeps the provenance honest.
19
+ *
20
+ * The step's injection is not only this hint: the plugin's DEPENDENCY NOTICES (the `audit` entries of
21
+ * the shipped `res/runtime-deps.yaml`) ride in the same message ({@link stepInjection}). They are a
22
+ * different producer of text with the same delivery rule — at most once per owner session, only on a
23
+ * step that already carried a user message — so merging them keeps ONE message per step instead of
24
+ * two competing ones.
19
25
  */
20
26
  export declare const RELEVANCE_HINT = "[avantf-mem] \u8BB0\u5FC6\u91CC\u6709\u4E0E\u4E0A\u6761\u7528\u6237\u6D88\u606F\u76F8\u5173\u7684\u5185\u5BB9\uFF1B\u9700\u8981\u65F6\u7528 `mem_recall` \u68C0\u7D22\u3002";
21
27
  /**
@@ -42,4 +48,56 @@ export declare function freshUserText(messages: readonly unknown[]): string;
42
48
  * with no text there is nothing for either the lexical or the semantic probe to judge.
43
49
  */
44
50
  export declare function messageText(message: unknown): string;
51
+ /**
52
+ * The text of the ONE message this step injects: the session notices, then the memory hint.
53
+ *
54
+ * `''` means "inject nothing" — the loop's turn-end guard is `decision.messages.length === 0`, so an
55
+ * empty injection has to stay empty rather than become an empty user message.
56
+ *
57
+ * Order: notices first. They report a capability that is not working (a repair the operator asked for
58
+ * did not finish), which is the louder statement; the hint is an invitation. Neither repeats within a
59
+ * session: the notice registry latches per session id, and the hint is one line by construction.
60
+ *
61
+ * Each body is used AS CONFIGURED, with one exception that is about YAML and not about editing: a
62
+ * block scalar (`body: |`) ends with a newline, and keeping it would insert a blank line between the
63
+ * notice and the hint. Trailing whitespace is therefore dropped; nothing else is rewritten, and a
64
+ * whitespace-only body is skipped rather than rendered as an empty paragraph.
65
+ */
66
+ export declare function stepInjection(hint: boolean, notices: readonly string[]): string;
67
+ /**
68
+ * The session-notice lines for this step, or `[]` when there are none to deliver.
69
+ *
70
+ * Three rules, all of them the caller's to make and this plugin's to keep:
71
+ *
72
+ * 1. **`ownerOnly` is a CLAIM, not a lookup.** The base registry cannot know which session owns the
73
+ * plugin, so it serves only a call that claims it ({@link isOwnerSession} decides), and a
74
+ * non-claiming call latches nothing — a worker/subagent session therefore never consumes the line
75
+ * out from under the owner session.
76
+ * 2. **Nothing is cached here.** `consume()` re-reads the item's real state on every step, so a
77
+ * dependency that healed stops matching and a NEW session simply sees nothing — "fixed ⇒ silent"
78
+ * needs no invalidation of its own.
79
+ * 3. **Never throws.** This runs on the prompt path of a live agent: a hostile/mismatched registry
80
+ * costs one skipped line, never the step.
81
+ */
82
+ export declare function noticeLines(registry: {
83
+ consume(sessionId: string, options?: {
84
+ ownerOnly?: boolean;
85
+ }): string[];
86
+ } | undefined, sessionId: string, owner: boolean): string[];
87
+ /**
88
+ * Whether `sessionId` is the OWNER session — a TOP-LEVEL agent, not a worker/subagent.
89
+ *
90
+ * Read STRUCTURALLY off the host's agent registry (`ctx.agents`), deliberately without a dependency
91
+ * on `@deepseek-ai/dsh-agent`: the only question is "is this id one of the roots", and the answer
92
+ * decides a claim the base registry would otherwise have to invent a role for. A subagent session is
93
+ * created under its parent's context, so it is never a root — and a mission executor is a subagent
94
+ * too. Those sessions keep working (memory tools, retrieval), they just do not receive the owner's
95
+ * repair notice.
96
+ *
97
+ * "Cannot tell" DELIVERS (`true`): a host with no agent registry, an older registry without `roots()`,
98
+ * a throwing read — none of those prove the session is a worker, and swallowing a real notice on a
99
+ * guess would be the worse failure. This mirrors the family rule that only a PROVEN condition may
100
+ * take a capability away.
101
+ */
102
+ export declare function isOwnerSession(agents: unknown, sessionId: string): boolean;
45
103
  //# sourceMappingURL=hints.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hints.d.ts","sourceRoot":"","sources":["../../src/hints.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,eAAO,MAAM,cAAc,gLAC4B,CAAA;AAEvD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAMlE;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAUpD"}
1
+ {"version":3,"file":"hints.d.ts","sourceRoot":"","sources":["../../src/hints.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,eAAO,MAAM,cAAc,gLAC4B,CAAA;AAEvD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAMlE;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAUpD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAU/E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE;IAAE,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,MAAM,EAAE,CAAA;CAAE,GAAG,SAAS,EACjG,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,OAAO,GACb,MAAM,EAAE,CASV;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAmB1E"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAQlD,OAAO,CAAC,MAAM,0BAA0B,CAAA;AACxC,OAAO,EAAqB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAE5E,OAAO,EAAE,mBAAmB,EAAU,MAAM,kCAAkC,CAAA;AAE9E,OAAO,EASL,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EACjB,MAAM,aAAa,CAAA;AACpB,OAAO,EAcL,KAAK,cAAc,EAIpB,MAAM,sBAAsB,CAAA;AAgB7B;;;;;;;GAOG;AACH,OAAO,QAAQ,sBAAsB,CAAC;IACpC,UAAU,gBAAgB;QACxB,UAAU,EAAE;YAAE,IAAI,EAAE,UAAU,CAAA;SAAE,GAAG,aAAa,CAAA;KACjD;CACF;AAED,eAAO,MAAM,IAAI,eAAe,CAAA;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAGpC,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAQnD,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,KAAK,eAAe,EACpB,KAAK,WAAW,GACjB,MAAM,aAAa,CAAA;AAEpB,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAA;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AACD,eAAO,MAAM,MAAM,EAAE,CAAC,CAAC,MAAM,CAO3B,CAAA;AA+BF,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAmBvC;;;;;;;;;;GAUG;AACH,qBAAa,gBAAiB,SAAQ,mBAAmB;IACvD,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAe;gBACtB,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa;IAK3C;;;;;;;;;OASG;YACW,IAAI;IAclB;;;;OAIG;IAEH,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC,WAAW,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC;IAMlF,MAAM,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC;IAMjE,KAAK,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC,WAAW,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;CAKjF;AAmGD,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAyZvE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAQlD,OAAO,CAAC,MAAM,0BAA0B,CAAA;AACxC,OAAO,EAAqB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAE5E,OAAO,EAAE,mBAAmB,EAAU,MAAM,kCAAkC,CAAA;AAE9E,OAAO,EAUL,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EACjB,MAAM,aAAa,CAAA;AACpB,OAAO,EAcL,KAAK,cAAc,EAIpB,MAAM,sBAAsB,CAAA;AAsB7B;;;;;;;GAOG;AACH,OAAO,QAAQ,sBAAsB,CAAC;IACpC,UAAU,gBAAgB;QACxB,UAAU,EAAE;YAAE,IAAI,EAAE,UAAU,CAAA;SAAE,GAAG,aAAa,CAAA;KACjD;CACF;AAED,eAAO,MAAM,IAAI,eAAe,CAAA;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAGpC,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAQnD,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,KAAK,eAAe,EACpB,KAAK,WAAW,GACjB,MAAM,aAAa,CAAA;AAEpB,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAA;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AACD,eAAO,MAAM,MAAM,EAAE,CAAC,CAAC,MAAM,CAO3B,CAAA;AA+BF,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAmBvC;;;;;;;;;;GAUG;AACH,qBAAa,gBAAiB,SAAQ,mBAAmB;IACvD,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAe;gBACtB,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa;IAK3C;;;;;;;;;OASG;YACW,IAAI;IAclB;;;;OAIG;IAEH,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC,WAAW,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC;IAMlF,MAAM,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC;IAMjE,KAAK,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC,WAAW,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;CAKjF;AA4ND,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0bvE"}