dna-sdk 0.1.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.
- package/LICENSE +21 -0
- package/README.md +58 -0
- package/dist/adapters/embedding/onnx.d.ts +32 -0
- package/dist/adapters/embedding/onnx.js +51 -0
- package/dist/adapters/filesystem/cache.d.ts +16 -0
- package/dist/adapters/filesystem/cache.js +113 -0
- package/dist/adapters/filesystem/index.d.ts +2 -0
- package/dist/adapters/filesystem/index.js +2 -0
- package/dist/adapters/filesystem/source.d.ts +82 -0
- package/dist/adapters/filesystem/source.js +357 -0
- package/dist/adapters/postgres/index.d.ts +2 -0
- package/dist/adapters/postgres/index.js +2 -0
- package/dist/adapters/postgres/migrations.d.ts +14 -0
- package/dist/adapters/postgres/migrations.js +88 -0
- package/dist/adapters/postgres/source.d.ts +172 -0
- package/dist/adapters/postgres/source.js +569 -0
- package/dist/adapters/resolvers/github.d.ts +12 -0
- package/dist/adapters/resolvers/github.js +47 -0
- package/dist/adapters/resolvers/http.d.ts +22 -0
- package/dist/adapters/resolvers/http.js +145 -0
- package/dist/adapters/resolvers/index.d.ts +3 -0
- package/dist/adapters/resolvers/index.js +3 -0
- package/dist/adapters/resolvers/local.d.ts +24 -0
- package/dist/adapters/resolvers/local.js +132 -0
- package/dist/adapters/search/driver.d.ts +45 -0
- package/dist/adapters/search/driver.js +138 -0
- package/dist/adapters/search/migrations.d.ts +26 -0
- package/dist/adapters/search/migrations.js +58 -0
- package/dist/adapters/search/rrf.d.ts +23 -0
- package/dist/adapters/search/rrf.js +42 -0
- package/dist/adapters/search/sqlite-vec.d.ts +66 -0
- package/dist/adapters/search/sqlite-vec.js +294 -0
- package/dist/bootstrap.d.ts +45 -0
- package/dist/bootstrap.js +134 -0
- package/dist/extensions/agentskills/DOCS.md +18 -0
- package/dist/extensions/agentskills.d.ts +28 -0
- package/dist/extensions/agentskills.js +252 -0
- package/dist/extensions/agentsmd/DOCS.md +18 -0
- package/dist/extensions/agentsmd.d.ts +22 -0
- package/dist/extensions/agentsmd.js +170 -0
- package/dist/extensions/audit/kinds/audit-log.kind.yaml +148 -0
- package/dist/extensions/audit.d.ts +25 -0
- package/dist/extensions/audit.js +62 -0
- package/dist/extensions/automation/kinds/automation.kind.yaml +296 -0
- package/dist/extensions/automation/query.d.ts +49 -0
- package/dist/extensions/automation/query.js +77 -0
- package/dist/extensions/automation/write-guards.d.ts +59 -0
- package/dist/extensions/automation/write-guards.js +153 -0
- package/dist/extensions/automation.d.ts +41 -0
- package/dist/extensions/automation.js +54 -0
- package/dist/extensions/collab.d.ts +16 -0
- package/dist/extensions/collab.js +79 -0
- package/dist/extensions/doc/kinds/doc.kind.yaml +118 -0
- package/dist/extensions/doc.d.ts +25 -0
- package/dist/extensions/doc.js +10 -0
- package/dist/extensions/eval/kinds/eval-baseline.kind.yaml +65 -0
- package/dist/extensions/eval/kinds/eval-case.kind.yaml +140 -0
- package/dist/extensions/eval/kinds/eval-run.kind.yaml +134 -0
- package/dist/extensions/eval/kinds/eval-suite.kind.yaml +87 -0
- package/dist/extensions/eval.d.ts +24 -0
- package/dist/extensions/eval.js +31 -0
- package/dist/extensions/evidence/kinds/evidence.kind.yaml +92 -0
- package/dist/extensions/evidence.d.ts +17 -0
- package/dist/extensions/evidence.js +94 -0
- package/dist/extensions/federation.d.ts +22 -0
- package/dist/extensions/federation.js +173 -0
- package/dist/extensions/guardrails/DOCS.md +20 -0
- package/dist/extensions/guardrails.d.ts +31 -0
- package/dist/extensions/guardrails.js +228 -0
- package/dist/extensions/helix/DOCS-Actor.md +20 -0
- package/dist/extensions/helix/DOCS-Agent.md +20 -0
- package/dist/extensions/helix/DOCS-UseCase.md +20 -0
- package/dist/extensions/helix/layers.d.ts +12 -0
- package/dist/extensions/helix/layers.js +18 -0
- package/dist/extensions/helix/write-guards.d.ts +70 -0
- package/dist/extensions/helix/write-guards.js +172 -0
- package/dist/extensions/helix.d.ts +29 -0
- package/dist/extensions/helix.js +963 -0
- package/dist/extensions/helix_extras.d.ts +124 -0
- package/dist/extensions/helix_extras.js +328 -0
- package/dist/extensions/hooks.d.ts +31 -0
- package/dist/extensions/hooks.js +247 -0
- package/dist/extensions/kinddef/DOCS.md +24 -0
- package/dist/extensions/kinddef.d.ts +40 -0
- package/dist/extensions/kinddef.js +171 -0
- package/dist/extensions/lesson.d.ts +6 -0
- package/dist/extensions/lesson.js +194 -0
- package/dist/extensions/modelreg/kinds/model-profile.kind.yaml +155 -0
- package/dist/extensions/modelreg.d.ts +30 -0
- package/dist/extensions/modelreg.js +38 -0
- package/dist/extensions/recognizer.d.ts +34 -0
- package/dist/extensions/recognizer.js +272 -0
- package/dist/extensions/research.d.ts +32 -0
- package/dist/extensions/research.js +292 -0
- package/dist/extensions/safety.d.ts +33 -0
- package/dist/extensions/safety.js +230 -0
- package/dist/extensions/sdlc/kinds/adr.kind.yaml +136 -0
- package/dist/extensions/sdlc/kinds/archive-proposal.kind.yaml +107 -0
- package/dist/extensions/sdlc/kinds/changelog.kind.yaml +108 -0
- package/dist/extensions/sdlc/kinds/cognitive-policy.kind.yaml +470 -0
- package/dist/extensions/sdlc/kinds/forecast.kind.yaml +125 -0
- package/dist/extensions/sdlc/kinds/insight.kind.yaml +87 -0
- package/dist/extensions/sdlc/kinds/kaizen.kind.yaml +106 -0
- package/dist/extensions/sdlc/kinds/lesson-learned.kind.yaml +270 -0
- package/dist/extensions/sdlc/kinds/narrative.kind.yaml +189 -0
- package/dist/extensions/sdlc/kinds/pattern-insight.kind.yaml +204 -0
- package/dist/extensions/sdlc/kinds/postmortem.kind.yaml +168 -0
- package/dist/extensions/sdlc/kinds/pre-mortem.kind.yaml +145 -0
- package/dist/extensions/sdlc/kinds/prompt-template.kind.yaml +109 -0
- package/dist/extensions/sdlc/kinds/retrospective.kind.yaml +186 -0
- package/dist/extensions/sdlc/kinds/risk-register.kind.yaml +178 -0
- package/dist/extensions/sdlc/kinds/saved-view.kind.yaml +127 -0
- package/dist/extensions/sdlc/kinds/status-report.kind.yaml +129 -0
- package/dist/extensions/sdlc/kinds/synthesis-run.kind.yaml +279 -0
- package/dist/extensions/sdlc/kinds/synthesizer-state.kind.yaml +196 -0
- package/dist/extensions/sdlc/kinds/workflow-event.kind.yaml +195 -0
- package/dist/extensions/sdlc.d.ts +32 -0
- package/dist/extensions/sdlc.js +1318 -0
- package/dist/extensions/soulspec/DOCS.md +19 -0
- package/dist/extensions/soulspec.d.ts +22 -0
- package/dist/extensions/soulspec.js +287 -0
- package/dist/extensions/tenant.d.ts +6 -0
- package/dist/extensions/tenant.js +291 -0
- package/dist/extensions/testkit.d.ts +24 -0
- package/dist/extensions/testkit.js +211 -0
- package/dist/index.d.ts +80 -0
- package/dist/index.js +102 -0
- package/dist/kernel/_text.d.ts +28 -0
- package/dist/kernel/_text.js +42 -0
- package/dist/kernel/bundle-handle.d.ts +83 -0
- package/dist/kernel/bundle-handle.js +184 -0
- package/dist/kernel/capabilities.d.ts +157 -0
- package/dist/kernel/capabilities.js +109 -0
- package/dist/kernel/collaborator-ports.d.ts +91 -0
- package/dist/kernel/collaborator-ports.js +1 -0
- package/dist/kernel/composition-resolver.d.ts +215 -0
- package/dist/kernel/composition-resolver.js +558 -0
- package/dist/kernel/composition.d.ts +10 -0
- package/dist/kernel/composition.js +1 -0
- package/dist/kernel/descriptor-loader.d.ts +13 -0
- package/dist/kernel/descriptor-loader.js +48 -0
- package/dist/kernel/document.d.ts +43 -0
- package/dist/kernel/document.js +71 -0
- package/dist/kernel/embedding.d.ts +28 -0
- package/dist/kernel/embedding.js +78 -0
- package/dist/kernel/errors.d.ts +62 -0
- package/dist/kernel/errors.js +82 -0
- package/dist/kernel/events.d.ts +6 -0
- package/dist/kernel/events.js +21 -0
- package/dist/kernel/evidence-capture.d.ts +69 -0
- package/dist/kernel/evidence-capture.js +138 -0
- package/dist/kernel/fs.d.ts +20 -0
- package/dist/kernel/fs.js +128 -0
- package/dist/kernel/generic-rw.d.ts +33 -0
- package/dist/kernel/generic-rw.js +235 -0
- package/dist/kernel/hooks.d.ts +172 -0
- package/dist/kernel/hooks.js +256 -0
- package/dist/kernel/index.d.ts +624 -0
- package/dist/kernel/index.js +1638 -0
- package/dist/kernel/instance.d.ts +211 -0
- package/dist/kernel/instance.js +487 -0
- package/dist/kernel/kind-registry.d.ts +183 -0
- package/dist/kernel/kind-registry.js +710 -0
- package/dist/kernel/kind_base.d.ts +106 -0
- package/dist/kernel/kind_base.js +244 -0
- package/dist/kernel/layer-resolver.d.ts +48 -0
- package/dist/kernel/layer-resolver.js +284 -0
- package/dist/kernel/lock-manager.d.ts +21 -0
- package/dist/kernel/lock-manager.js +43 -0
- package/dist/kernel/lock.d.ts +38 -0
- package/dist/kernel/lock.js +115 -0
- package/dist/kernel/meta.d.ts +135 -0
- package/dist/kernel/meta.js +817 -0
- package/dist/kernel/models.d.ts +3089 -0
- package/dist/kernel/models.js +764 -0
- package/dist/kernel/navigator.d.ts +36 -0
- package/dist/kernel/navigator.js +132 -0
- package/dist/kernel/port-surface.d.ts +33 -0
- package/dist/kernel/port-surface.js +180 -0
- package/dist/kernel/preview.d.ts +60 -0
- package/dist/kernel/preview.js +54 -0
- package/dist/kernel/prompt-budget.d.ts +39 -0
- package/dist/kernel/prompt-budget.js +43 -0
- package/dist/kernel/prompt-builder.d.ts +25 -0
- package/dist/kernel/prompt-builder.js +237 -0
- package/dist/kernel/protocols.d.ts +751 -0
- package/dist/kernel/protocols.js +493 -0
- package/dist/kernel/reports.d.ts +26 -0
- package/dist/kernel/reports.js +215 -0
- package/dist/kernel/resolver.d.ts +146 -0
- package/dist/kernel/resolver.js +232 -0
- package/dist/kernel/resource.d.ts +57 -0
- package/dist/kernel/resource.js +97 -0
- package/dist/kernel/runtime.d.ts +16 -0
- package/dist/kernel/runtime.js +18 -0
- package/dist/kernel/safety-scanner.d.ts +38 -0
- package/dist/kernel/safety-scanner.js +228 -0
- package/dist/kernel/serialize-to-files.d.ts +29 -0
- package/dist/kernel/serialize-to-files.js +23 -0
- package/dist/kernel/spec-access.d.ts +23 -0
- package/dist/kernel/spec-access.js +40 -0
- package/dist/kernel/studio_ui.d.ts +88 -0
- package/dist/kernel/studio_ui.js +135 -0
- package/dist/kernel/templates.d.ts +77 -0
- package/dist/kernel/templates.js +116 -0
- package/dist/kernel/tool-registry.d.ts +52 -0
- package/dist/kernel/tool-registry.js +89 -0
- package/dist/kernel/write-pipeline.d.ts +65 -0
- package/dist/kernel/write-pipeline.js +271 -0
- package/dist/kernel/writer-helpers.d.ts +24 -0
- package/dist/kernel/writer-helpers.js +42 -0
- package/dist/memory/decay.d.ts +31 -0
- package/dist/memory/decay.js +97 -0
- package/dist/memory/ecphory.d.ts +25 -0
- package/dist/memory/ecphory.js +178 -0
- package/dist/memory/encodingContext.d.ts +21 -0
- package/dist/memory/encodingContext.js +62 -0
- package/dist/memory/index.d.ts +23 -0
- package/dist/memory/index.js +23 -0
- package/dist/memory/memoryType.d.ts +7 -0
- package/dist/memory/memoryType.js +24 -0
- package/dist/memory/policy.d.ts +35 -0
- package/dist/memory/policy.js +35 -0
- package/dist/memory/retrieval.d.ts +21 -0
- package/dist/memory/retrieval.js +145 -0
- package/dist/testing/index.d.ts +8 -0
- package/dist/testing/index.js +8 -0
- package/dist/testing/recordSearchConformance.d.ts +43 -0
- package/dist/testing/recordSearchConformance.js +147 -0
- package/dist/viz/ascii.d.ts +7 -0
- package/dist/viz/ascii.js +60 -0
- package/dist/viz/health.d.ts +8 -0
- package/dist/viz/health.js +161 -0
- package/dist/viz/index.d.ts +10 -0
- package/dist/viz/index.js +10 -0
- package/dist/viz/matrix.d.ts +8 -0
- package/dist/viz/matrix.js +84 -0
- package/dist/viz/mermaid.d.ts +38 -0
- package/dist/viz/mermaid.js +706 -0
- package/package.json +82 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ManifestInstance v3 — public API for querying manifest documents.
|
|
3
|
+
*
|
|
4
|
+
* Provides query (all/one/root), navigation (get/describe/listKinds/summary),
|
|
5
|
+
* prompt building (buildPrompt with template cascade), and layer resolution.
|
|
6
|
+
*
|
|
7
|
+
* Method bodies delegate to namespace classes (PromptBuilder, CompositionEngine,
|
|
8
|
+
* Navigator, LockManager) and viz/ functions. The old API surface is preserved
|
|
9
|
+
* as one-line delegates for backwards compatibility.
|
|
10
|
+
*
|
|
11
|
+
* 1:1 parity with Python dna.v3.kernel.instance.
|
|
12
|
+
*/
|
|
13
|
+
import { Document } from "./document.js";
|
|
14
|
+
import type { Lockfile } from "./lock.js";
|
|
15
|
+
import type { CompositionResult, KindPort, SourcePort } from "./protocols.js";
|
|
16
|
+
import type { CompositionProfile } from "./composition-resolver.js";
|
|
17
|
+
import type { PreviewBlock } from "./preview.js";
|
|
18
|
+
import { PromptBuilder } from "./prompt-builder.js";
|
|
19
|
+
import { CompositionEngine } from "./composition-resolver.js";
|
|
20
|
+
import { Navigator } from "./navigator.js";
|
|
21
|
+
import { LockManager } from "./lock-manager.js";
|
|
22
|
+
import { ReportBuilder } from "./reports.js";
|
|
23
|
+
export type { PreviewBlock };
|
|
24
|
+
/** @internal Test hook — reset the once-per-process deprecation state. */
|
|
25
|
+
export declare function _resetDeprecationWarnings(): void;
|
|
26
|
+
export interface ManifestInstanceOpts {
|
|
27
|
+
scope: string;
|
|
28
|
+
documents: Document[];
|
|
29
|
+
kinds: Map<string, KindPort>;
|
|
30
|
+
source?: SourcePort | null;
|
|
31
|
+
resolveErrors?: string[];
|
|
32
|
+
kernel?: unknown;
|
|
33
|
+
profiles?: CompositionProfile[];
|
|
34
|
+
}
|
|
35
|
+
export interface BuildPromptOpts {
|
|
36
|
+
agent?: string;
|
|
37
|
+
context?: Record<string, unknown>;
|
|
38
|
+
/** Generic slot filtering: keys are slot names from the CompositionProfile,
|
|
39
|
+
* values are arrays of doc names to keep. */
|
|
40
|
+
enabledSlots?: Record<string, string[]>;
|
|
41
|
+
/** @deprecated Use enabledSlots.skills instead. Kept for backwards compat. */
|
|
42
|
+
enabledSkills?: string[];
|
|
43
|
+
/** @deprecated Use enabledSlots.guardrails instead. */
|
|
44
|
+
enabledGuardrails?: string[];
|
|
45
|
+
}
|
|
46
|
+
export declare class ManifestInstance {
|
|
47
|
+
readonly scope: string;
|
|
48
|
+
readonly documents: Document[];
|
|
49
|
+
readonly resolveErrors: string[];
|
|
50
|
+
private _kinds;
|
|
51
|
+
private _source;
|
|
52
|
+
private _kernel;
|
|
53
|
+
private _root;
|
|
54
|
+
private _compositionResult;
|
|
55
|
+
/** Composition profiles registered by extensions. */
|
|
56
|
+
readonly _profiles: readonly CompositionProfile[];
|
|
57
|
+
private _promptBuilder;
|
|
58
|
+
private _compositionEngine;
|
|
59
|
+
private _navigator;
|
|
60
|
+
private _lockManager;
|
|
61
|
+
private _reportBuilder;
|
|
62
|
+
constructor(opts: ManifestInstanceOpts);
|
|
63
|
+
get prompt(): PromptBuilder;
|
|
64
|
+
get composition(): CompositionEngine;
|
|
65
|
+
get nav(): Navigator;
|
|
66
|
+
get lock(): LockManager;
|
|
67
|
+
get reports(): ReportBuilder;
|
|
68
|
+
/**
|
|
69
|
+
* Find the CompositionProfile for a document's kind (via its alias).
|
|
70
|
+
* Returns null if no profile covers this kind.
|
|
71
|
+
*/
|
|
72
|
+
profileFor(doc: Document): CompositionProfile | null;
|
|
73
|
+
/**
|
|
74
|
+
* Return all docs of `kind`.
|
|
75
|
+
*
|
|
76
|
+
* @deprecated Will be removed in 1.0 — filter `mi.documents`
|
|
77
|
+
* (e.g. `mi.documents.filter((d) => d.kind === kind)`) or use
|
|
78
|
+
* `kernel.query(scope, kind)` for indexed/record-plane reads.
|
|
79
|
+
* (s-blessed-query-surface)
|
|
80
|
+
*/
|
|
81
|
+
all(kind: string): Document[];
|
|
82
|
+
/** @internal Non-warning twin of `all()` — used by the SDK's own
|
|
83
|
+
* collaborators (`applyHooks`, `ReportBuilder`, viz). External
|
|
84
|
+
* callers use the blessed surface (`mi.documents` / `kernel.query`). */
|
|
85
|
+
_all(kind: string): Document[];
|
|
86
|
+
/**
|
|
87
|
+
* Lookup a single doc by (kind, name).
|
|
88
|
+
*
|
|
89
|
+
* @deprecated Will be removed in 1.0 — search `mi.documents`
|
|
90
|
+
* (e.g. `mi.documents.find((d) => d.kind === kind && d.name === name) ??
|
|
91
|
+
* null`) or use `kernel.query(scope, kind)` with a filter for
|
|
92
|
+
* indexed/record-plane reads. (s-blessed-query-surface)
|
|
93
|
+
*/
|
|
94
|
+
one(kind: string, name: string): Document | null;
|
|
95
|
+
/** @internal Non-warning twin of `one()` — used by the SDK's own
|
|
96
|
+
* collaborators (`readSpec*`, `readMetadata`). External callers use
|
|
97
|
+
* the blessed surface (`mi.documents` / `kernel.query`). */
|
|
98
|
+
_one(kind: string, name: string): Document | null;
|
|
99
|
+
/**
|
|
100
|
+
* Return the KindPort registered for `kind` (by kind name), or null.
|
|
101
|
+
*/
|
|
102
|
+
kindFor(kind: string): KindPort | null;
|
|
103
|
+
/**
|
|
104
|
+
* True when the document's KindPort is marked as the manifest root.
|
|
105
|
+
*/
|
|
106
|
+
isRootDoc(doc: Document): boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Return all documents whose registered KindPort satisfies a predicate.
|
|
109
|
+
*/
|
|
110
|
+
allWhere(predicate: (kp: KindPort) => boolean): Document[];
|
|
111
|
+
/**
|
|
112
|
+
* Return the KindPort whose `alias` matches, or null.
|
|
113
|
+
*/
|
|
114
|
+
kindForAlias(alias: string): KindPort | null;
|
|
115
|
+
/**
|
|
116
|
+
* Iterate a document's declared dep_filters dynamically.
|
|
117
|
+
* Delegates to CompositionEngine.
|
|
118
|
+
*/
|
|
119
|
+
iterDocDeps(doc: Document): {
|
|
120
|
+
label: string;
|
|
121
|
+
targetKind: string;
|
|
122
|
+
names: string[];
|
|
123
|
+
}[];
|
|
124
|
+
get root(): Document | null;
|
|
125
|
+
readSpec(kind: string, name: string, field: string): unknown;
|
|
126
|
+
readSpecString(kind: string, name: string, field: string): string | undefined;
|
|
127
|
+
readSpecStringArray(kind: string, name: string, field: string): string[];
|
|
128
|
+
readMetadata(kind: string, name: string, field: string): unknown;
|
|
129
|
+
defaultAgent(): Document | null;
|
|
130
|
+
get compositionResult(): CompositionResult;
|
|
131
|
+
listKinds(): string[];
|
|
132
|
+
/**
|
|
133
|
+
* Return every kind REGISTERED in this manifest (not just those that have
|
|
134
|
+
* documents on disk).
|
|
135
|
+
*/
|
|
136
|
+
allKinds(): Array<{
|
|
137
|
+
kind: string;
|
|
138
|
+
alias: string;
|
|
139
|
+
apiVersion: string;
|
|
140
|
+
origin: string | null;
|
|
141
|
+
}>;
|
|
142
|
+
renderDoc(kind: string, name: string): PreviewBlock[];
|
|
143
|
+
consumersOf(kind: string, name: string): Array<{
|
|
144
|
+
kind: string;
|
|
145
|
+
name: string;
|
|
146
|
+
}>;
|
|
147
|
+
get(kind?: string): Array<{
|
|
148
|
+
kind: string;
|
|
149
|
+
name: string;
|
|
150
|
+
apiVersion: string;
|
|
151
|
+
}>;
|
|
152
|
+
describe(kind: string, name: string): string;
|
|
153
|
+
summary(): string;
|
|
154
|
+
inventory(): Record<string, unknown>;
|
|
155
|
+
dependencyTree(): Record<string, unknown>;
|
|
156
|
+
erModel(): {
|
|
157
|
+
entities: {
|
|
158
|
+
id: string;
|
|
159
|
+
kind: string;
|
|
160
|
+
name: string;
|
|
161
|
+
attrs: {
|
|
162
|
+
key: string;
|
|
163
|
+
type: string;
|
|
164
|
+
value: string;
|
|
165
|
+
}[];
|
|
166
|
+
}[];
|
|
167
|
+
relationships: {
|
|
168
|
+
sourceId: string;
|
|
169
|
+
targetId: string;
|
|
170
|
+
label: string;
|
|
171
|
+
isMany: boolean;
|
|
172
|
+
}[];
|
|
173
|
+
};
|
|
174
|
+
dependencyTreeMermaid(): string;
|
|
175
|
+
compositionFlowchartMermaid(): string;
|
|
176
|
+
c4ComponentMermaid(): string;
|
|
177
|
+
erDiagramMermaid(): string;
|
|
178
|
+
mindmapMermaid(): string;
|
|
179
|
+
pieChartMermaid(): string;
|
|
180
|
+
quadrantMermaid(): string;
|
|
181
|
+
timelineMermaid(): string;
|
|
182
|
+
sankeyMermaid(): string;
|
|
183
|
+
kindCatalogMermaid(): string;
|
|
184
|
+
exportDiagramsMd(path?: string): Record<string, string>;
|
|
185
|
+
matrix(): Record<string, unknown>;
|
|
186
|
+
matrixMarkdown(): string;
|
|
187
|
+
health(): Record<string, unknown>;
|
|
188
|
+
impact(kind: string, name: string): Record<string, unknown>;
|
|
189
|
+
asciiTree(): string;
|
|
190
|
+
/**
|
|
191
|
+
* Resolve a ref-like value (path or markdown/yaml/txt filename).
|
|
192
|
+
*
|
|
193
|
+
* v1.0 async refactor: SourcePort.resolveRef is async, so this is
|
|
194
|
+
* async too. Cascades to PromptBuilder.build() and
|
|
195
|
+
* ManifestInstance.buildPrompt() — every prompt build is async.
|
|
196
|
+
* That's the honest contract — the alternative (cache-based sync
|
|
197
|
+
* ref) requires knowing every ref at scope load time, which doesn't
|
|
198
|
+
* hold for dynamic context fields.
|
|
199
|
+
*/
|
|
200
|
+
ref(value: string): Promise<string>;
|
|
201
|
+
buildPrompt(opts?: BuildPromptOpts): Promise<string>;
|
|
202
|
+
resolve(layers?: Record<string, string>): ManifestInstance;
|
|
203
|
+
generateLock(): Lockfile;
|
|
204
|
+
/** Auto-register Hook documents on the kernel's HookRegistry. */
|
|
205
|
+
applyHooks(): void;
|
|
206
|
+
/** Find the best prompt-target document matching `name`.
|
|
207
|
+
* Considers promptTargetPriority when multiple kinds match. */
|
|
208
|
+
findAgent(name: string): Document | null;
|
|
209
|
+
/** @internal */
|
|
210
|
+
_findAgent(name: string): Document | null;
|
|
211
|
+
}
|
|
@@ -0,0 +1,487 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ManifestInstance v3 — public API for querying manifest documents.
|
|
3
|
+
*
|
|
4
|
+
* Provides query (all/one/root), navigation (get/describe/listKinds/summary),
|
|
5
|
+
* prompt building (buildPrompt with template cascade), and layer resolution.
|
|
6
|
+
*
|
|
7
|
+
* Method bodies delegate to namespace classes (PromptBuilder, CompositionEngine,
|
|
8
|
+
* Navigator, LockManager) and viz/ functions. The old API surface is preserved
|
|
9
|
+
* as one-line delegates for backwards compatibility.
|
|
10
|
+
*
|
|
11
|
+
* 1:1 parity with Python dna.v3.kernel.instance.
|
|
12
|
+
*/
|
|
13
|
+
import { readSpecString, readSpecStringArray } from "./spec-access.js";
|
|
14
|
+
import { ScannerPipeline } from "./safety-scanner.js";
|
|
15
|
+
import { profileForOrchestrator } from "./composition-resolver.js";
|
|
16
|
+
import { PromptBuilder } from "./prompt-builder.js";
|
|
17
|
+
import { CompositionEngine } from "./composition-resolver.js";
|
|
18
|
+
import { Navigator } from "./navigator.js";
|
|
19
|
+
import { LockManager } from "./lock-manager.js";
|
|
20
|
+
import { ReportBuilder } from "./reports.js";
|
|
21
|
+
// Viz imports — all use `import type { ManifestInstance }` so no circular issue at runtime.
|
|
22
|
+
import { dependencyTreeMermaid as vizDependencyTreeMermaid, compositionFlowchartMermaid as vizCompositionFlowchartMermaid, c4ComponentMermaid as vizC4ComponentMermaid, erDiagramMermaid as vizErDiagramMermaid, erModel as vizErModel, mindmapMermaid as vizMindmapMermaid, pieChartMermaid as vizPieChartMermaid, quadrantMermaid as vizQuadrantMermaid, timelineMermaid as vizTimelineMermaid, sankeyMermaid as vizSankeyMermaid, kindCatalogMermaid as vizKindCatalogMermaid, exportDiagramsMd as vizExportDiagramsMd, } from "../viz/mermaid.js";
|
|
23
|
+
import { healthReport as vizHealthReport, impact as vizImpact } from "../viz/health.js";
|
|
24
|
+
import { matrix as vizMatrix, matrixMarkdown as vizMatrixMarkdown } from "../viz/matrix.js";
|
|
25
|
+
import { asciiTree as vizAsciiTree } from "../viz/ascii.js";
|
|
26
|
+
/**
|
|
27
|
+
* s-kernel-sandbox-hook-exec — whether a Hook's `action: "script"` may run
|
|
28
|
+
* arbitrary code from `spec.body` via `new Function(...)`. OFF by default: a
|
|
29
|
+
* Hook doc is reachable via the normal doc-write path, so executing its body is
|
|
30
|
+
* an unauthenticated RCE in the host process. Opt in with
|
|
31
|
+
* `DNA_ALLOW_HOOK_SCRIPT_EXEC=1` only in trusted single-tenant deployments.
|
|
32
|
+
* 1:1 with the Python twin (dna.operations._hook_script_exec_allowed).
|
|
33
|
+
*/
|
|
34
|
+
function hookScriptExecAllowed() {
|
|
35
|
+
return (typeof process !== "undefined" &&
|
|
36
|
+
process.env?.DNA_ALLOW_HOOK_SCRIPT_EXEC === "1");
|
|
37
|
+
}
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// Deprecation plumbing (s-blessed-query-surface)
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
/** Methods that already fired their once-per-process deprecation warning. */
|
|
42
|
+
const _deprecationWarned = new Set();
|
|
43
|
+
/** `console.warn` a deprecation message once per method per process —
|
|
44
|
+
* mirror of the Python `DeprecationWarning` on the same members. */
|
|
45
|
+
function warnDeprecatedOnce(method, message) {
|
|
46
|
+
if (_deprecationWarned.has(method))
|
|
47
|
+
return;
|
|
48
|
+
_deprecationWarned.add(method);
|
|
49
|
+
console.warn(message);
|
|
50
|
+
}
|
|
51
|
+
/** @internal Test hook — reset the once-per-process deprecation state. */
|
|
52
|
+
export function _resetDeprecationWarnings() {
|
|
53
|
+
_deprecationWarned.clear();
|
|
54
|
+
}
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// ManifestInstance
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
export class ManifestInstance {
|
|
59
|
+
scope;
|
|
60
|
+
documents;
|
|
61
|
+
resolveErrors;
|
|
62
|
+
_kinds;
|
|
63
|
+
_source;
|
|
64
|
+
_kernel;
|
|
65
|
+
_root = undefined; // undefined = not computed
|
|
66
|
+
_compositionResult = undefined;
|
|
67
|
+
/** Composition profiles registered by extensions. */
|
|
68
|
+
_profiles;
|
|
69
|
+
// -- Namespace instances (lazy) --------------------------------------------
|
|
70
|
+
_promptBuilder = null;
|
|
71
|
+
_compositionEngine = null;
|
|
72
|
+
_navigator = null;
|
|
73
|
+
_lockManager = null;
|
|
74
|
+
_reportBuilder = null;
|
|
75
|
+
constructor(opts) {
|
|
76
|
+
this.scope = opts.scope;
|
|
77
|
+
this.documents = opts.documents;
|
|
78
|
+
this._kinds = opts.kinds;
|
|
79
|
+
this._source = opts.source ?? null;
|
|
80
|
+
this._kernel = opts.kernel ?? null;
|
|
81
|
+
this.resolveErrors = opts.resolveErrors ?? [];
|
|
82
|
+
this._profiles = opts.profiles ?? [];
|
|
83
|
+
}
|
|
84
|
+
// -- Namespace getters (lazy, memoized) ------------------------------------
|
|
85
|
+
get prompt() {
|
|
86
|
+
return this._promptBuilder ??= new PromptBuilder(this);
|
|
87
|
+
}
|
|
88
|
+
get composition() {
|
|
89
|
+
return this._compositionEngine ??= new CompositionEngine(this);
|
|
90
|
+
}
|
|
91
|
+
get nav() {
|
|
92
|
+
return this._navigator ??= new Navigator(this);
|
|
93
|
+
}
|
|
94
|
+
get lock() {
|
|
95
|
+
return this._lockManager ??= new LockManager(this);
|
|
96
|
+
}
|
|
97
|
+
get reports() {
|
|
98
|
+
return this._reportBuilder ??= new ReportBuilder(this);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Find the CompositionProfile for a document's kind (via its alias).
|
|
102
|
+
* Returns null if no profile covers this kind.
|
|
103
|
+
*/
|
|
104
|
+
profileFor(doc) {
|
|
105
|
+
const kp = this._kinds.get(`${doc.apiVersion}\0${doc.kind}`);
|
|
106
|
+
if (!kp)
|
|
107
|
+
return null;
|
|
108
|
+
return profileForOrchestrator(this._profiles, kp.alias);
|
|
109
|
+
}
|
|
110
|
+
// -- Query ----------------------------------------------------------------
|
|
111
|
+
/**
|
|
112
|
+
* Return all docs of `kind`.
|
|
113
|
+
*
|
|
114
|
+
* @deprecated Will be removed in 1.0 — filter `mi.documents`
|
|
115
|
+
* (e.g. `mi.documents.filter((d) => d.kind === kind)`) or use
|
|
116
|
+
* `kernel.query(scope, kind)` for indexed/record-plane reads.
|
|
117
|
+
* (s-blessed-query-surface)
|
|
118
|
+
*/
|
|
119
|
+
all(kind) {
|
|
120
|
+
warnDeprecatedOnce("all", "ManifestInstance.all() is deprecated and will be removed in 1.0 — " +
|
|
121
|
+
"filter mi.documents (e.g. `mi.documents.filter((d) => d.kind === " +
|
|
122
|
+
"kind)`) or use `kernel.query(scope, kind)` for " +
|
|
123
|
+
"indexed/record-plane reads.");
|
|
124
|
+
return this._all(kind);
|
|
125
|
+
}
|
|
126
|
+
/** @internal Non-warning twin of `all()` — used by the SDK's own
|
|
127
|
+
* collaborators (`applyHooks`, `ReportBuilder`, viz). External
|
|
128
|
+
* callers use the blessed surface (`mi.documents` / `kernel.query`). */
|
|
129
|
+
_all(kind) {
|
|
130
|
+
return this.documents.filter((d) => d.kind === kind);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Lookup a single doc by (kind, name).
|
|
134
|
+
*
|
|
135
|
+
* @deprecated Will be removed in 1.0 — search `mi.documents`
|
|
136
|
+
* (e.g. `mi.documents.find((d) => d.kind === kind && d.name === name) ??
|
|
137
|
+
* null`) or use `kernel.query(scope, kind)` with a filter for
|
|
138
|
+
* indexed/record-plane reads. (s-blessed-query-surface)
|
|
139
|
+
*/
|
|
140
|
+
one(kind, name) {
|
|
141
|
+
warnDeprecatedOnce("one", "ManifestInstance.one() is deprecated and will be removed in 1.0 — " +
|
|
142
|
+
"search mi.documents (e.g. `mi.documents.find((d) => d.kind === " +
|
|
143
|
+
"kind && d.name === name) ?? null`) or use `kernel.query(scope, " +
|
|
144
|
+
"kind)` with a filter for indexed/record-plane reads.");
|
|
145
|
+
return this._one(kind, name);
|
|
146
|
+
}
|
|
147
|
+
/** @internal Non-warning twin of `one()` — used by the SDK's own
|
|
148
|
+
* collaborators (`readSpec*`, `readMetadata`). External callers use
|
|
149
|
+
* the blessed surface (`mi.documents` / `kernel.query`). */
|
|
150
|
+
_one(kind, name) {
|
|
151
|
+
return (this.documents.find((d) => d.kind === kind && d.name === name) ?? null);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Return the KindPort registered for `kind` (by kind name), or null.
|
|
155
|
+
*/
|
|
156
|
+
kindFor(kind) {
|
|
157
|
+
for (const [key, kp] of this._kinds) {
|
|
158
|
+
const kn = key.split("\0")[1] ?? "";
|
|
159
|
+
if (kn === kind)
|
|
160
|
+
return kp;
|
|
161
|
+
}
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* True when the document's KindPort is marked as the manifest root.
|
|
166
|
+
*/
|
|
167
|
+
isRootDoc(doc) {
|
|
168
|
+
const kp = this._kinds.get(`${doc.apiVersion}\0${doc.kind}`);
|
|
169
|
+
return kp?.isRoot === true;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Return all documents whose registered KindPort satisfies a predicate.
|
|
173
|
+
*/
|
|
174
|
+
allWhere(predicate) {
|
|
175
|
+
return this.documents.filter((d) => {
|
|
176
|
+
const kp = this._kinds.get(`${d.apiVersion}\0${d.kind}`);
|
|
177
|
+
return kp ? predicate(kp) : false;
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Return the KindPort whose `alias` matches, or null.
|
|
182
|
+
*/
|
|
183
|
+
kindForAlias(alias) {
|
|
184
|
+
for (const kp of this._kinds.values()) {
|
|
185
|
+
if (kp.alias === alias)
|
|
186
|
+
return kp;
|
|
187
|
+
}
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Iterate a document's declared dep_filters dynamically.
|
|
192
|
+
* Delegates to CompositionEngine.
|
|
193
|
+
*/
|
|
194
|
+
iterDocDeps(doc) {
|
|
195
|
+
return this.composition.iterDocDeps(doc);
|
|
196
|
+
}
|
|
197
|
+
get root() {
|
|
198
|
+
if (this._root !== undefined)
|
|
199
|
+
return this._root;
|
|
200
|
+
// Phase 16 — Genome is the canonical root Kind. ModuleKind class
|
|
201
|
+
// is gone; legacy ``kind: Module`` docs no longer parse.
|
|
202
|
+
for (const d of this.documents) {
|
|
203
|
+
const kp = this._kinds.get(`${d.apiVersion}\0${d.kind}`);
|
|
204
|
+
if (kp?.isRoot) {
|
|
205
|
+
this._root = d;
|
|
206
|
+
return d;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
this._root = null;
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
// -- Spec-access sugar (mirrors Python mi.read_spec) ---------------------
|
|
213
|
+
readSpec(kind, name, field) {
|
|
214
|
+
const doc = this._one(kind, name);
|
|
215
|
+
if (!doc) {
|
|
216
|
+
throw new Error(`${kind}/${name}: document not found in manifest`);
|
|
217
|
+
}
|
|
218
|
+
return doc.spec[field];
|
|
219
|
+
}
|
|
220
|
+
readSpecString(kind, name, field) {
|
|
221
|
+
const doc = this._one(kind, name);
|
|
222
|
+
if (!doc)
|
|
223
|
+
throw new Error(`${kind}/${name}: document not found in manifest`);
|
|
224
|
+
return readSpecString(doc, field);
|
|
225
|
+
}
|
|
226
|
+
readSpecStringArray(kind, name, field) {
|
|
227
|
+
const doc = this._one(kind, name);
|
|
228
|
+
if (!doc)
|
|
229
|
+
throw new Error(`${kind}/${name}: document not found in manifest`);
|
|
230
|
+
return readSpecStringArray(doc, field);
|
|
231
|
+
}
|
|
232
|
+
readMetadata(kind, name, field) {
|
|
233
|
+
const doc = this._one(kind, name);
|
|
234
|
+
if (!doc)
|
|
235
|
+
throw new Error(`${kind}/${name}: document not found in manifest`);
|
|
236
|
+
return doc.metadata[field];
|
|
237
|
+
}
|
|
238
|
+
defaultAgent() {
|
|
239
|
+
const root = this.root;
|
|
240
|
+
if (!root)
|
|
241
|
+
return null;
|
|
242
|
+
const kp = this._kinds.get(`${root.apiVersion}\0${root.kind}`);
|
|
243
|
+
if (!kp)
|
|
244
|
+
return null;
|
|
245
|
+
const agentName = kp.getDefaultAgentName(root);
|
|
246
|
+
if (!agentName)
|
|
247
|
+
return null;
|
|
248
|
+
return this._findAgent(agentName);
|
|
249
|
+
}
|
|
250
|
+
// -- Composition validation → CompositionEngine ---------------------------
|
|
251
|
+
get compositionResult() {
|
|
252
|
+
if (this._compositionResult !== undefined)
|
|
253
|
+
return this._compositionResult;
|
|
254
|
+
this._compositionResult = this.composition.validate();
|
|
255
|
+
return this._compositionResult;
|
|
256
|
+
}
|
|
257
|
+
// -- Navigation → Navigator -----------------------------------------------
|
|
258
|
+
listKinds() {
|
|
259
|
+
return [...new Set(this.documents.map((d) => d.kind))].sort();
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Return every kind REGISTERED in this manifest (not just those that have
|
|
263
|
+
* documents on disk).
|
|
264
|
+
*/
|
|
265
|
+
allKinds() {
|
|
266
|
+
const out = [];
|
|
267
|
+
for (const kp of this._kinds.values()) {
|
|
268
|
+
out.push({
|
|
269
|
+
kind: kp.kind,
|
|
270
|
+
alias: kp.alias,
|
|
271
|
+
apiVersion: kp.apiVersion,
|
|
272
|
+
origin: kp.origin ?? null,
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
out.sort((a, b) => a.kind.localeCompare(b.kind));
|
|
276
|
+
return out;
|
|
277
|
+
}
|
|
278
|
+
renderDoc(kind, name) {
|
|
279
|
+
return this.nav.renderDoc(kind, name);
|
|
280
|
+
}
|
|
281
|
+
consumersOf(kind, name) {
|
|
282
|
+
return this.composition.consumersOf(kind, name);
|
|
283
|
+
}
|
|
284
|
+
get(kind) {
|
|
285
|
+
const docs = kind != null ? this._all(kind) : this.documents;
|
|
286
|
+
return docs.map((d) => ({
|
|
287
|
+
kind: d.kind,
|
|
288
|
+
name: d.name,
|
|
289
|
+
apiVersion: d.apiVersion,
|
|
290
|
+
}));
|
|
291
|
+
}
|
|
292
|
+
describe(kind, name) {
|
|
293
|
+
return this.nav.describe(kind, name);
|
|
294
|
+
}
|
|
295
|
+
summary() {
|
|
296
|
+
return this.nav.summary();
|
|
297
|
+
}
|
|
298
|
+
inventory() {
|
|
299
|
+
return this.nav.inventory();
|
|
300
|
+
}
|
|
301
|
+
dependencyTree() {
|
|
302
|
+
return this.composition.dependencyTree();
|
|
303
|
+
}
|
|
304
|
+
// -- ER Model → viz -------------------------------------------------------
|
|
305
|
+
erModel() {
|
|
306
|
+
return vizErModel(this);
|
|
307
|
+
}
|
|
308
|
+
// -- Mermaid diagrams → viz ------------------------------------------------
|
|
309
|
+
dependencyTreeMermaid() { return vizDependencyTreeMermaid(this); }
|
|
310
|
+
compositionFlowchartMermaid() { return vizCompositionFlowchartMermaid(this); }
|
|
311
|
+
c4ComponentMermaid() { return vizC4ComponentMermaid(this); }
|
|
312
|
+
erDiagramMermaid() { return vizErDiagramMermaid(this); }
|
|
313
|
+
mindmapMermaid() { return vizMindmapMermaid(this); }
|
|
314
|
+
pieChartMermaid() { return vizPieChartMermaid(this); }
|
|
315
|
+
quadrantMermaid() { return vizQuadrantMermaid(this); }
|
|
316
|
+
timelineMermaid() { return vizTimelineMermaid(this); }
|
|
317
|
+
sankeyMermaid() { return vizSankeyMermaid(this); }
|
|
318
|
+
kindCatalogMermaid() { return vizKindCatalogMermaid(this); }
|
|
319
|
+
exportDiagramsMd(path) { return vizExportDiagramsMd(this, path); }
|
|
320
|
+
// -- Matrix → viz ----------------------------------------------------------
|
|
321
|
+
matrix() { return vizMatrix(this); }
|
|
322
|
+
matrixMarkdown() { return vizMatrixMarkdown(this); }
|
|
323
|
+
// -- Health / Impact → viz -------------------------------------------------
|
|
324
|
+
health() { return vizHealthReport(this); }
|
|
325
|
+
impact(kind, name) { return vizImpact(this, kind, name); }
|
|
326
|
+
// -- ASCII tree → viz ------------------------------------------------------
|
|
327
|
+
asciiTree() { return vizAsciiTree(this); }
|
|
328
|
+
// -- Ref resolution -------------------------------------------------------
|
|
329
|
+
/**
|
|
330
|
+
* Resolve a ref-like value (path or markdown/yaml/txt filename).
|
|
331
|
+
*
|
|
332
|
+
* v1.0 async refactor: SourcePort.resolveRef is async, so this is
|
|
333
|
+
* async too. Cascades to PromptBuilder.build() and
|
|
334
|
+
* ManifestInstance.buildPrompt() — every prompt build is async.
|
|
335
|
+
* That's the honest contract — the alternative (cache-based sync
|
|
336
|
+
* ref) requires knowing every ref at scope load time, which doesn't
|
|
337
|
+
* hold for dynamic context fields.
|
|
338
|
+
*/
|
|
339
|
+
async ref(value) {
|
|
340
|
+
if (!value)
|
|
341
|
+
return "";
|
|
342
|
+
if (this._source &&
|
|
343
|
+
(value.includes("/") || /\.(md|txt|yaml)$/.test(value))) {
|
|
344
|
+
const resolved = await this._source.resolveRef(this.scope, value);
|
|
345
|
+
if (resolved)
|
|
346
|
+
return resolved;
|
|
347
|
+
}
|
|
348
|
+
return value;
|
|
349
|
+
}
|
|
350
|
+
// -- Prompt → PromptBuilder ------------------------------------------------
|
|
351
|
+
async buildPrompt(opts) {
|
|
352
|
+
return this.prompt.build(opts);
|
|
353
|
+
}
|
|
354
|
+
// -- Layers ---------------------------------------------------------------
|
|
355
|
+
resolve(layers) {
|
|
356
|
+
if (!layers)
|
|
357
|
+
return this;
|
|
358
|
+
const kernel = this._kernel;
|
|
359
|
+
if (kernel?.resolveLayers) {
|
|
360
|
+
return kernel.resolveLayers(this, layers);
|
|
361
|
+
}
|
|
362
|
+
// Fallback if no kernel ref (e.g., constructed directly in tests)
|
|
363
|
+
return this;
|
|
364
|
+
}
|
|
365
|
+
// -- Lock → LockManager ---------------------------------------------------
|
|
366
|
+
generateLock() {
|
|
367
|
+
return this.lock.generate();
|
|
368
|
+
}
|
|
369
|
+
// -- Hook auto-registration ------------------------------------------------
|
|
370
|
+
/** Auto-register Hook documents on the kernel's HookRegistry. */
|
|
371
|
+
applyHooks() {
|
|
372
|
+
const kernel = this._kernel;
|
|
373
|
+
if (!kernel?.hooks)
|
|
374
|
+
return;
|
|
375
|
+
const hooks = this._all("Hook");
|
|
376
|
+
for (const doc of hooks) {
|
|
377
|
+
const spec = doc.spec;
|
|
378
|
+
const target = spec.target;
|
|
379
|
+
const type = spec.type;
|
|
380
|
+
const action = spec.action;
|
|
381
|
+
if (type === "middleware" && target) {
|
|
382
|
+
if (action === "inject_fields") {
|
|
383
|
+
const fields = (spec.fields ?? {});
|
|
384
|
+
kernel.hooks.use(target, (ctx) => {
|
|
385
|
+
const context = (ctx.data?.context ?? {});
|
|
386
|
+
for (const [k, v] of Object.entries(fields)) {
|
|
387
|
+
context[k] = v;
|
|
388
|
+
}
|
|
389
|
+
return { ...ctx, data: { ...ctx.data, context } };
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
else if (action === "script") {
|
|
393
|
+
const body = spec.body ?? "";
|
|
394
|
+
if (body.trim() && !hookScriptExecAllowed()) {
|
|
395
|
+
console.warn(`Hook ${doc.name}: action='script' skipped — exec of Hook spec.body ` +
|
|
396
|
+
`is disabled (RCE surface). Use a declarative action, or set ` +
|
|
397
|
+
`DNA_ALLOW_HOOK_SCRIPT_EXEC=1 in a trusted deployment. (s-kernel-sandbox-hook-exec)`);
|
|
398
|
+
}
|
|
399
|
+
else if (body.trim()) {
|
|
400
|
+
try {
|
|
401
|
+
const fn = new Function("ctx", `return (${body.trim()})(ctx);`);
|
|
402
|
+
kernel.hooks.use(target, (ctx) => fn(ctx));
|
|
403
|
+
}
|
|
404
|
+
catch (e) {
|
|
405
|
+
console.warn(`Hook ${doc.name}: script compilation failed: ${e}`);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
else if (type === "event" && target) {
|
|
411
|
+
if (action === "log") {
|
|
412
|
+
kernel.hooks.on(target, (ctx) => {
|
|
413
|
+
console.log(`[Hook:${doc.name}] ${target}`, {
|
|
414
|
+
agent: ctx.agent,
|
|
415
|
+
scope: ctx.scope,
|
|
416
|
+
promptLength: ctx.prompt?.length,
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
else if (action === "script") {
|
|
421
|
+
const body = spec.body ?? "";
|
|
422
|
+
if (body.trim() && !hookScriptExecAllowed()) {
|
|
423
|
+
console.warn(`Hook ${doc.name}: event action='script' skipped — exec of Hook ` +
|
|
424
|
+
`spec.body is disabled (RCE surface). Use action='log', or set ` +
|
|
425
|
+
`DNA_ALLOW_HOOK_SCRIPT_EXEC=1 in a trusted deployment. (s-kernel-sandbox-hook-exec)`);
|
|
426
|
+
}
|
|
427
|
+
else if (body.trim()) {
|
|
428
|
+
try {
|
|
429
|
+
const fn = new Function("ctx", `(${body.trim()})(ctx);`);
|
|
430
|
+
kernel.hooks.on(target, (ctx) => fn(ctx));
|
|
431
|
+
}
|
|
432
|
+
catch (e) {
|
|
433
|
+
console.warn(`Hook ${doc.name}: script compilation failed: ${e}`);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
// -- SafetyPolicy input enforcement ----------------------------------------
|
|
440
|
+
const policies = this._all("SafetyPolicy");
|
|
441
|
+
for (const doc of policies) {
|
|
442
|
+
const spec = doc.spec;
|
|
443
|
+
const scope = spec.scope;
|
|
444
|
+
const action = spec.action;
|
|
445
|
+
const rules = (spec.rules ?? []);
|
|
446
|
+
if ((scope === "input" || scope === "both") && rules.length > 0) {
|
|
447
|
+
kernel.hooks.use("pre_build_prompt", (ctx) => {
|
|
448
|
+
const pipeline = new ScannerPipeline(rules);
|
|
449
|
+
const context = (ctx.data?.context ?? {});
|
|
450
|
+
for (const [key, val] of Object.entries(context)) {
|
|
451
|
+
if (typeof val === "string") {
|
|
452
|
+
try {
|
|
453
|
+
context[key] = pipeline.apply(val, action);
|
|
454
|
+
}
|
|
455
|
+
catch {
|
|
456
|
+
/* block action throws — skip field */
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
return { ...ctx, data: { ...ctx.data, context } };
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
// -- Agent lookup -----------------------------------------------------------
|
|
466
|
+
/** Find the best prompt-target document matching `name`.
|
|
467
|
+
* Considers promptTargetPriority when multiple kinds match. */
|
|
468
|
+
findAgent(name) {
|
|
469
|
+
return this._findAgent(name);
|
|
470
|
+
}
|
|
471
|
+
/** @internal */
|
|
472
|
+
_findAgent(name) {
|
|
473
|
+
let best = null;
|
|
474
|
+
let bestPriority = -1;
|
|
475
|
+
for (const d of this.documents) {
|
|
476
|
+
const kp = this._kinds.get(`${d.apiVersion}\0${d.kind}`);
|
|
477
|
+
if (kp?.isPromptTarget && d.name === name) {
|
|
478
|
+
const priority = kp.promptTargetPriority ?? 0;
|
|
479
|
+
if (priority > bestPriority) {
|
|
480
|
+
best = d;
|
|
481
|
+
bestPriority = priority;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
return best;
|
|
486
|
+
}
|
|
487
|
+
}
|