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.
Files changed (240) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +58 -0
  3. package/dist/adapters/embedding/onnx.d.ts +32 -0
  4. package/dist/adapters/embedding/onnx.js +51 -0
  5. package/dist/adapters/filesystem/cache.d.ts +16 -0
  6. package/dist/adapters/filesystem/cache.js +113 -0
  7. package/dist/adapters/filesystem/index.d.ts +2 -0
  8. package/dist/adapters/filesystem/index.js +2 -0
  9. package/dist/adapters/filesystem/source.d.ts +82 -0
  10. package/dist/adapters/filesystem/source.js +357 -0
  11. package/dist/adapters/postgres/index.d.ts +2 -0
  12. package/dist/adapters/postgres/index.js +2 -0
  13. package/dist/adapters/postgres/migrations.d.ts +14 -0
  14. package/dist/adapters/postgres/migrations.js +88 -0
  15. package/dist/adapters/postgres/source.d.ts +172 -0
  16. package/dist/adapters/postgres/source.js +569 -0
  17. package/dist/adapters/resolvers/github.d.ts +12 -0
  18. package/dist/adapters/resolvers/github.js +47 -0
  19. package/dist/adapters/resolvers/http.d.ts +22 -0
  20. package/dist/adapters/resolvers/http.js +145 -0
  21. package/dist/adapters/resolvers/index.d.ts +3 -0
  22. package/dist/adapters/resolvers/index.js +3 -0
  23. package/dist/adapters/resolvers/local.d.ts +24 -0
  24. package/dist/adapters/resolvers/local.js +132 -0
  25. package/dist/adapters/search/driver.d.ts +45 -0
  26. package/dist/adapters/search/driver.js +138 -0
  27. package/dist/adapters/search/migrations.d.ts +26 -0
  28. package/dist/adapters/search/migrations.js +58 -0
  29. package/dist/adapters/search/rrf.d.ts +23 -0
  30. package/dist/adapters/search/rrf.js +42 -0
  31. package/dist/adapters/search/sqlite-vec.d.ts +66 -0
  32. package/dist/adapters/search/sqlite-vec.js +294 -0
  33. package/dist/bootstrap.d.ts +45 -0
  34. package/dist/bootstrap.js +134 -0
  35. package/dist/extensions/agentskills/DOCS.md +18 -0
  36. package/dist/extensions/agentskills.d.ts +28 -0
  37. package/dist/extensions/agentskills.js +252 -0
  38. package/dist/extensions/agentsmd/DOCS.md +18 -0
  39. package/dist/extensions/agentsmd.d.ts +22 -0
  40. package/dist/extensions/agentsmd.js +170 -0
  41. package/dist/extensions/audit/kinds/audit-log.kind.yaml +148 -0
  42. package/dist/extensions/audit.d.ts +25 -0
  43. package/dist/extensions/audit.js +62 -0
  44. package/dist/extensions/automation/kinds/automation.kind.yaml +296 -0
  45. package/dist/extensions/automation/query.d.ts +49 -0
  46. package/dist/extensions/automation/query.js +77 -0
  47. package/dist/extensions/automation/write-guards.d.ts +59 -0
  48. package/dist/extensions/automation/write-guards.js +153 -0
  49. package/dist/extensions/automation.d.ts +41 -0
  50. package/dist/extensions/automation.js +54 -0
  51. package/dist/extensions/collab.d.ts +16 -0
  52. package/dist/extensions/collab.js +79 -0
  53. package/dist/extensions/doc/kinds/doc.kind.yaml +118 -0
  54. package/dist/extensions/doc.d.ts +25 -0
  55. package/dist/extensions/doc.js +10 -0
  56. package/dist/extensions/eval/kinds/eval-baseline.kind.yaml +65 -0
  57. package/dist/extensions/eval/kinds/eval-case.kind.yaml +140 -0
  58. package/dist/extensions/eval/kinds/eval-run.kind.yaml +134 -0
  59. package/dist/extensions/eval/kinds/eval-suite.kind.yaml +87 -0
  60. package/dist/extensions/eval.d.ts +24 -0
  61. package/dist/extensions/eval.js +31 -0
  62. package/dist/extensions/evidence/kinds/evidence.kind.yaml +92 -0
  63. package/dist/extensions/evidence.d.ts +17 -0
  64. package/dist/extensions/evidence.js +94 -0
  65. package/dist/extensions/federation.d.ts +22 -0
  66. package/dist/extensions/federation.js +173 -0
  67. package/dist/extensions/guardrails/DOCS.md +20 -0
  68. package/dist/extensions/guardrails.d.ts +31 -0
  69. package/dist/extensions/guardrails.js +228 -0
  70. package/dist/extensions/helix/DOCS-Actor.md +20 -0
  71. package/dist/extensions/helix/DOCS-Agent.md +20 -0
  72. package/dist/extensions/helix/DOCS-UseCase.md +20 -0
  73. package/dist/extensions/helix/layers.d.ts +12 -0
  74. package/dist/extensions/helix/layers.js +18 -0
  75. package/dist/extensions/helix/write-guards.d.ts +70 -0
  76. package/dist/extensions/helix/write-guards.js +172 -0
  77. package/dist/extensions/helix.d.ts +29 -0
  78. package/dist/extensions/helix.js +963 -0
  79. package/dist/extensions/helix_extras.d.ts +124 -0
  80. package/dist/extensions/helix_extras.js +328 -0
  81. package/dist/extensions/hooks.d.ts +31 -0
  82. package/dist/extensions/hooks.js +247 -0
  83. package/dist/extensions/kinddef/DOCS.md +24 -0
  84. package/dist/extensions/kinddef.d.ts +40 -0
  85. package/dist/extensions/kinddef.js +171 -0
  86. package/dist/extensions/lesson.d.ts +6 -0
  87. package/dist/extensions/lesson.js +194 -0
  88. package/dist/extensions/modelreg/kinds/model-profile.kind.yaml +155 -0
  89. package/dist/extensions/modelreg.d.ts +30 -0
  90. package/dist/extensions/modelreg.js +38 -0
  91. package/dist/extensions/recognizer.d.ts +34 -0
  92. package/dist/extensions/recognizer.js +272 -0
  93. package/dist/extensions/research.d.ts +32 -0
  94. package/dist/extensions/research.js +292 -0
  95. package/dist/extensions/safety.d.ts +33 -0
  96. package/dist/extensions/safety.js +230 -0
  97. package/dist/extensions/sdlc/kinds/adr.kind.yaml +136 -0
  98. package/dist/extensions/sdlc/kinds/archive-proposal.kind.yaml +107 -0
  99. package/dist/extensions/sdlc/kinds/changelog.kind.yaml +108 -0
  100. package/dist/extensions/sdlc/kinds/cognitive-policy.kind.yaml +470 -0
  101. package/dist/extensions/sdlc/kinds/forecast.kind.yaml +125 -0
  102. package/dist/extensions/sdlc/kinds/insight.kind.yaml +87 -0
  103. package/dist/extensions/sdlc/kinds/kaizen.kind.yaml +106 -0
  104. package/dist/extensions/sdlc/kinds/lesson-learned.kind.yaml +270 -0
  105. package/dist/extensions/sdlc/kinds/narrative.kind.yaml +189 -0
  106. package/dist/extensions/sdlc/kinds/pattern-insight.kind.yaml +204 -0
  107. package/dist/extensions/sdlc/kinds/postmortem.kind.yaml +168 -0
  108. package/dist/extensions/sdlc/kinds/pre-mortem.kind.yaml +145 -0
  109. package/dist/extensions/sdlc/kinds/prompt-template.kind.yaml +109 -0
  110. package/dist/extensions/sdlc/kinds/retrospective.kind.yaml +186 -0
  111. package/dist/extensions/sdlc/kinds/risk-register.kind.yaml +178 -0
  112. package/dist/extensions/sdlc/kinds/saved-view.kind.yaml +127 -0
  113. package/dist/extensions/sdlc/kinds/status-report.kind.yaml +129 -0
  114. package/dist/extensions/sdlc/kinds/synthesis-run.kind.yaml +279 -0
  115. package/dist/extensions/sdlc/kinds/synthesizer-state.kind.yaml +196 -0
  116. package/dist/extensions/sdlc/kinds/workflow-event.kind.yaml +195 -0
  117. package/dist/extensions/sdlc.d.ts +32 -0
  118. package/dist/extensions/sdlc.js +1318 -0
  119. package/dist/extensions/soulspec/DOCS.md +19 -0
  120. package/dist/extensions/soulspec.d.ts +22 -0
  121. package/dist/extensions/soulspec.js +287 -0
  122. package/dist/extensions/tenant.d.ts +6 -0
  123. package/dist/extensions/tenant.js +291 -0
  124. package/dist/extensions/testkit.d.ts +24 -0
  125. package/dist/extensions/testkit.js +211 -0
  126. package/dist/index.d.ts +80 -0
  127. package/dist/index.js +102 -0
  128. package/dist/kernel/_text.d.ts +28 -0
  129. package/dist/kernel/_text.js +42 -0
  130. package/dist/kernel/bundle-handle.d.ts +83 -0
  131. package/dist/kernel/bundle-handle.js +184 -0
  132. package/dist/kernel/capabilities.d.ts +157 -0
  133. package/dist/kernel/capabilities.js +109 -0
  134. package/dist/kernel/collaborator-ports.d.ts +91 -0
  135. package/dist/kernel/collaborator-ports.js +1 -0
  136. package/dist/kernel/composition-resolver.d.ts +215 -0
  137. package/dist/kernel/composition-resolver.js +558 -0
  138. package/dist/kernel/composition.d.ts +10 -0
  139. package/dist/kernel/composition.js +1 -0
  140. package/dist/kernel/descriptor-loader.d.ts +13 -0
  141. package/dist/kernel/descriptor-loader.js +48 -0
  142. package/dist/kernel/document.d.ts +43 -0
  143. package/dist/kernel/document.js +71 -0
  144. package/dist/kernel/embedding.d.ts +28 -0
  145. package/dist/kernel/embedding.js +78 -0
  146. package/dist/kernel/errors.d.ts +62 -0
  147. package/dist/kernel/errors.js +82 -0
  148. package/dist/kernel/events.d.ts +6 -0
  149. package/dist/kernel/events.js +21 -0
  150. package/dist/kernel/evidence-capture.d.ts +69 -0
  151. package/dist/kernel/evidence-capture.js +138 -0
  152. package/dist/kernel/fs.d.ts +20 -0
  153. package/dist/kernel/fs.js +128 -0
  154. package/dist/kernel/generic-rw.d.ts +33 -0
  155. package/dist/kernel/generic-rw.js +235 -0
  156. package/dist/kernel/hooks.d.ts +172 -0
  157. package/dist/kernel/hooks.js +256 -0
  158. package/dist/kernel/index.d.ts +624 -0
  159. package/dist/kernel/index.js +1638 -0
  160. package/dist/kernel/instance.d.ts +211 -0
  161. package/dist/kernel/instance.js +487 -0
  162. package/dist/kernel/kind-registry.d.ts +183 -0
  163. package/dist/kernel/kind-registry.js +710 -0
  164. package/dist/kernel/kind_base.d.ts +106 -0
  165. package/dist/kernel/kind_base.js +244 -0
  166. package/dist/kernel/layer-resolver.d.ts +48 -0
  167. package/dist/kernel/layer-resolver.js +284 -0
  168. package/dist/kernel/lock-manager.d.ts +21 -0
  169. package/dist/kernel/lock-manager.js +43 -0
  170. package/dist/kernel/lock.d.ts +38 -0
  171. package/dist/kernel/lock.js +115 -0
  172. package/dist/kernel/meta.d.ts +135 -0
  173. package/dist/kernel/meta.js +817 -0
  174. package/dist/kernel/models.d.ts +3089 -0
  175. package/dist/kernel/models.js +764 -0
  176. package/dist/kernel/navigator.d.ts +36 -0
  177. package/dist/kernel/navigator.js +132 -0
  178. package/dist/kernel/port-surface.d.ts +33 -0
  179. package/dist/kernel/port-surface.js +180 -0
  180. package/dist/kernel/preview.d.ts +60 -0
  181. package/dist/kernel/preview.js +54 -0
  182. package/dist/kernel/prompt-budget.d.ts +39 -0
  183. package/dist/kernel/prompt-budget.js +43 -0
  184. package/dist/kernel/prompt-builder.d.ts +25 -0
  185. package/dist/kernel/prompt-builder.js +237 -0
  186. package/dist/kernel/protocols.d.ts +751 -0
  187. package/dist/kernel/protocols.js +493 -0
  188. package/dist/kernel/reports.d.ts +26 -0
  189. package/dist/kernel/reports.js +215 -0
  190. package/dist/kernel/resolver.d.ts +146 -0
  191. package/dist/kernel/resolver.js +232 -0
  192. package/dist/kernel/resource.d.ts +57 -0
  193. package/dist/kernel/resource.js +97 -0
  194. package/dist/kernel/runtime.d.ts +16 -0
  195. package/dist/kernel/runtime.js +18 -0
  196. package/dist/kernel/safety-scanner.d.ts +38 -0
  197. package/dist/kernel/safety-scanner.js +228 -0
  198. package/dist/kernel/serialize-to-files.d.ts +29 -0
  199. package/dist/kernel/serialize-to-files.js +23 -0
  200. package/dist/kernel/spec-access.d.ts +23 -0
  201. package/dist/kernel/spec-access.js +40 -0
  202. package/dist/kernel/studio_ui.d.ts +88 -0
  203. package/dist/kernel/studio_ui.js +135 -0
  204. package/dist/kernel/templates.d.ts +77 -0
  205. package/dist/kernel/templates.js +116 -0
  206. package/dist/kernel/tool-registry.d.ts +52 -0
  207. package/dist/kernel/tool-registry.js +89 -0
  208. package/dist/kernel/write-pipeline.d.ts +65 -0
  209. package/dist/kernel/write-pipeline.js +271 -0
  210. package/dist/kernel/writer-helpers.d.ts +24 -0
  211. package/dist/kernel/writer-helpers.js +42 -0
  212. package/dist/memory/decay.d.ts +31 -0
  213. package/dist/memory/decay.js +97 -0
  214. package/dist/memory/ecphory.d.ts +25 -0
  215. package/dist/memory/ecphory.js +178 -0
  216. package/dist/memory/encodingContext.d.ts +21 -0
  217. package/dist/memory/encodingContext.js +62 -0
  218. package/dist/memory/index.d.ts +23 -0
  219. package/dist/memory/index.js +23 -0
  220. package/dist/memory/memoryType.d.ts +7 -0
  221. package/dist/memory/memoryType.js +24 -0
  222. package/dist/memory/policy.d.ts +35 -0
  223. package/dist/memory/policy.js +35 -0
  224. package/dist/memory/retrieval.d.ts +21 -0
  225. package/dist/memory/retrieval.js +145 -0
  226. package/dist/testing/index.d.ts +8 -0
  227. package/dist/testing/index.js +8 -0
  228. package/dist/testing/recordSearchConformance.d.ts +43 -0
  229. package/dist/testing/recordSearchConformance.js +147 -0
  230. package/dist/viz/ascii.d.ts +7 -0
  231. package/dist/viz/ascii.js +60 -0
  232. package/dist/viz/health.d.ts +8 -0
  233. package/dist/viz/health.js +161 -0
  234. package/dist/viz/index.d.ts +10 -0
  235. package/dist/viz/index.js +10 -0
  236. package/dist/viz/matrix.d.ts +8 -0
  237. package/dist/viz/matrix.js +84 -0
  238. package/dist/viz/mermaid.d.ts +38 -0
  239. package/dist/viz/mermaid.js +706 -0
  240. package/package.json +82 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 DNA contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # dna-sdk (TypeScript)
2
+
3
+ TypeScript SDK for **DNA — Domain Notation of Anything**: a microkernel +
4
+ extensions runtime for declarative agent notation. 1:1 behavioral twin of
5
+ the Python SDK (`packages/sdk-py`) — same ports, same composition rules,
6
+ same outputs, parity-enforced by tests. See the
7
+ [repository README](https://github.com/ruinosus/dna#readme) for the thesis and the Kind catalog.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ npm install dna-sdk # or: bun add dna-sdk
13
+ ```
14
+
15
+ Pre-release / exact-pin alternative — consume straight from the repo:
16
+
17
+ ```bash
18
+ cd packages/sdk-ts
19
+ bun install
20
+ ```
21
+
22
+ ESM-only, Node >= 20 or Bun. The published package ships compiled JS +
23
+ type declarations (`dist/`); inside the repo, dev and tests run the
24
+ TypeScript sources directly under Bun (no build step needed). The
25
+ publication build is `bun run build` (tsc emit + runtime-asset copy).
26
+
27
+ ## Minimal example
28
+
29
+ ```typescript
30
+ import { quickInstance } from "dna-sdk";
31
+
32
+ // Scan a scope (directory of YAML/Markdown manifests under .dna/)
33
+ const mi = await quickInstance("hello-genome", "examples/hello-genome/.dna");
34
+
35
+ // Every document is identified by (apiVersion, kind, name)
36
+ for (const d of mi.documents) {
37
+ console.log(d.apiVersion, d.kind, d.name);
38
+ }
39
+
40
+ // Compose agent + soul + skills + guardrails into one system prompt
41
+ console.log(await mi.buildPrompt({ agent: "greeter" }));
42
+ ```
43
+
44
+ Runnable version: [`examples/hello-genome/run.ts`](https://github.com/ruinosus/dna/blob/main/examples/hello-genome/run.ts).
45
+
46
+ Prefer `createKernelWithBuiltins()` (from the same entrypoint) when you
47
+ want to wire sources, caches and resolvers yourself.
48
+
49
+ ## Tests
50
+
51
+ ```bash
52
+ bun test # full suite
53
+ bun run typecheck # tsc --noEmit
54
+ ```
55
+
56
+ The suite includes the market-fidelity conformance tests
57
+ (`tests/market-conformance.test.ts`) and the Py↔TS parity fixtures shared
58
+ with the Python twin.
@@ -0,0 +1,32 @@
1
+ /**
2
+ * ONNX all-MiniLM-L6-v2 embedding provider (optional `@huggingface/transformers`
3
+ * peer dep).
4
+ *
5
+ * The REAL embedder (rec-embedding-port): the same
6
+ * `sentence-transformers/all-MiniLM-L6-v2` ONNX artifact run by
7
+ * `@huggingface/transformers` (transformers.js, TS) and `fastembed` (Py) —
8
+ * parity by artifact, not reimplementation. Cosine ≈ 1 across the two runtimes.
9
+ *
10
+ * Lazy-download + cache, the Chroma pattern: the model is a downloaded artifact,
11
+ * never a bundled dependency. `@huggingface/transformers` is dynamically
12
+ * imported on the FIRST `embed` call and the pipeline fetches + caches the ONNX
13
+ * then — so this module never pulls transformers.js into a process that does
14
+ * not embed, and it is not in the default dependency graph.
15
+ */
16
+ import type { EmbeddingPort } from "../../kernel/protocols.js";
17
+ export declare const ONNX_MODEL_ID = "Xenova/all-MiniLM-L6-v2";
18
+ export declare const ONNX_DIMS = 384;
19
+ /**
20
+ * `EmbeddingPort` backed by transformers.js feature-extraction. The heavy
21
+ * dynamic import (`@huggingface/transformers`) is deferred to first use so
22
+ * merely importing this module never pulls ML deps into a process that does not
23
+ * embed.
24
+ */
25
+ export declare class OnnxEmbeddingProvider implements EmbeddingPort {
26
+ readonly modelId: string;
27
+ readonly dims: number;
28
+ private _pipe;
29
+ constructor(modelId?: string, dims?: number);
30
+ private ensurePipe;
31
+ embed(texts: string[]): Promise<number[][]>;
32
+ }
@@ -0,0 +1,51 @@
1
+ // Same model + vector width as the Py twin (adapters/embedding/onnx.py) and the
2
+ // fake floor (FAKE_EMBEDDING_DIMS) so providers are swap-compatible.
3
+ export const ONNX_MODEL_ID = "Xenova/all-MiniLM-L6-v2";
4
+ export const ONNX_DIMS = 384;
5
+ /**
6
+ * `EmbeddingPort` backed by transformers.js feature-extraction. The heavy
7
+ * dynamic import (`@huggingface/transformers`) is deferred to first use so
8
+ * merely importing this module never pulls ML deps into a process that does not
9
+ * embed.
10
+ */
11
+ export class OnnxEmbeddingProvider {
12
+ modelId;
13
+ dims;
14
+ // The transformers.js pipeline, lazily constructed on first embed().
15
+ _pipe = null;
16
+ constructor(modelId = ONNX_MODEL_ID, dims = ONNX_DIMS) {
17
+ this.modelId = modelId;
18
+ this.dims = dims;
19
+ }
20
+ async ensurePipe() {
21
+ if (this._pipe === null) {
22
+ let mod;
23
+ // NON-LITERAL specifier on purpose: the peer dep is OPTIONAL and its
24
+ // type declarations are NOT installed by default, so a literal
25
+ // `import("@huggingface/transformers")` would fail `tsc --noEmit` in CI
26
+ // with TS2307. A string variable makes the dynamic import resolve to
27
+ // `Promise<any>` at type-check time (still the same module at runtime).
28
+ const spec = "@huggingface/transformers";
29
+ try {
30
+ // Dynamic import so the dep is optional and never bundled by default.
31
+ mod = (await import(/* @vite-ignore */ spec));
32
+ }
33
+ catch (err) {
34
+ throw new Error("OnnxEmbeddingProvider needs the '@huggingface/transformers' peer dep: "
35
+ + "npm install @huggingface/transformers", { cause: err });
36
+ }
37
+ // Downloads + caches the ONNX artifact on first construction.
38
+ this._pipe = await mod.pipeline("feature-extraction", this.modelId);
39
+ }
40
+ return this._pipe;
41
+ }
42
+ async embed(texts) {
43
+ if (texts.length === 0)
44
+ return [];
45
+ const pipe = await this.ensurePipe();
46
+ // Mean-pooled + L2-normalized sentence vectors — same recipe fastembed
47
+ // uses by default, matching sentence-transformers.
48
+ const out = await pipe(texts, { pooling: "mean", normalize: true });
49
+ return out.tolist();
50
+ }
51
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * FilesystemCache — CachePort backed by .dna-cache/ directories.
3
+ *
4
+ * 1:1 parity with Python dna.v3.adapters.filesystem.cache.
5
+ */
6
+ import type { CacheItem, CachePort, ReaderPort } from "../../kernel/protocols.js";
7
+ export declare class FilesystemCache implements CachePort {
8
+ readonly baseDir: string;
9
+ private readonly _cacheDir;
10
+ constructor(baseDir: string);
11
+ has(scope: string, key: string): Promise<boolean>;
12
+ store(scope: string, key: string, items: CacheItem[]): Promise<void>;
13
+ loadKey(scope: string, key: string, readers?: ReaderPort[]): Promise<Record<string, unknown>[]>;
14
+ loadAll(scope: string, readers?: ReaderPort[]): Promise<Record<string, unknown>[]>;
15
+ private _readTree;
16
+ }
@@ -0,0 +1,113 @@
1
+ /**
2
+ * FilesystemCache — CachePort backed by .dna-cache/ directories.
3
+ *
4
+ * 1:1 parity with Python dna.v3.adapters.filesystem.cache.
5
+ */
6
+ import { access, cp, mkdir, readFile, readdir, rm, stat } from "node:fs/promises";
7
+ import { resolve, join, dirname } from "node:path";
8
+ async function pathExists(p) {
9
+ try {
10
+ await access(p);
11
+ return true;
12
+ }
13
+ catch {
14
+ return false;
15
+ }
16
+ }
17
+ import yaml from "js-yaml";
18
+ import { FilesystemBundleHandle } from "../../kernel/bundle-handle.js";
19
+ export class FilesystemCache {
20
+ baseDir;
21
+ _cacheDir;
22
+ constructor(baseDir) {
23
+ this.baseDir = resolve(baseDir);
24
+ this._cacheDir = join(dirname(this.baseDir), ".dna-cache");
25
+ }
26
+ async has(scope, key) {
27
+ return pathExists(join(this._cacheDir, scope, key));
28
+ }
29
+ async store(scope, key, items) {
30
+ const destBase = join(this._cacheDir, scope, key);
31
+ await mkdir(destBase, { recursive: true });
32
+ for (const item of items) {
33
+ const subDir = item.kind
34
+ ? join(destBase, item.kind.toLowerCase() + "s")
35
+ : destBase;
36
+ const dest = join(subDir, item.name);
37
+ if (await pathExists(dest)) {
38
+ await rm(dest, { recursive: true, force: true });
39
+ }
40
+ await mkdir(dirname(dest), { recursive: true });
41
+ await cp(item.contentPath, dest, { recursive: true });
42
+ }
43
+ }
44
+ async loadKey(scope, key, readers) {
45
+ const keyDir = join(this._cacheDir, scope, key);
46
+ if (!(await pathExists(keyDir)))
47
+ return [];
48
+ const documents = [];
49
+ await this._readTree(keyDir, readers ?? [], documents);
50
+ return documents;
51
+ }
52
+ async loadAll(scope, readers) {
53
+ const scopeDir = join(this._cacheDir, scope);
54
+ if (!(await pathExists(scopeDir)))
55
+ return [];
56
+ const documents = [];
57
+ await this._readTree(scopeDir, readers ?? [], documents);
58
+ return documents;
59
+ }
60
+ async _readTree(directory, readers, documents) {
61
+ const entries = (await readdir(directory)).sort();
62
+ for (const entry of entries) {
63
+ const full = join(directory, entry);
64
+ if (!(await stat(full)).isDirectory())
65
+ continue;
66
+ let matched = false;
67
+ const handle = new FilesystemBundleHandle(full);
68
+ for (const reader of readers) {
69
+ try {
70
+ if (await reader.detect(handle)) {
71
+ const doc = await reader.read(handle);
72
+ if (doc != null &&
73
+ typeof doc === "object" &&
74
+ "kind" in doc) {
75
+ documents.push(doc);
76
+ }
77
+ matched = true;
78
+ break;
79
+ }
80
+ }
81
+ catch {
82
+ // Skip reader errors
83
+ }
84
+ }
85
+ if (matched)
86
+ continue;
87
+ let hasYaml = false;
88
+ const subEntries = (await readdir(full)).sort();
89
+ for (const sub of subEntries) {
90
+ if (!sub.endsWith(".yaml") && !sub.endsWith(".yml"))
91
+ continue;
92
+ const yf = join(full, sub);
93
+ if (!(await stat(yf)).isFile())
94
+ continue;
95
+ try {
96
+ const content = yaml.load(await readFile(yf, "utf-8"));
97
+ if (content != null &&
98
+ typeof content === "object" &&
99
+ "kind" in content) {
100
+ documents.push(content);
101
+ hasYaml = true;
102
+ }
103
+ }
104
+ catch {
105
+ // Skip unparseable YAML
106
+ }
107
+ }
108
+ if (!hasYaml) {
109
+ await this._readTree(full, readers, documents);
110
+ }
111
+ }
112
+ }
113
+ }
@@ -0,0 +1,2 @@
1
+ export { FilesystemSource } from "./source.js";
2
+ export { FilesystemCache } from "./cache.js";
@@ -0,0 +1,2 @@
1
+ export { FilesystemSource } from "./source.js";
2
+ export { FilesystemCache } from "./cache.js";
@@ -0,0 +1,82 @@
1
+ /**
2
+ * FilesystemSource — SourcePort backed by local .dna/ directories.
3
+ *
4
+ * 1:1 parity with Python dna.v3.adapters.filesystem.source.
5
+ */
6
+ import type { CountResult, ReaderPort, SourceCountOpts, SourcePort, SourceQueryOpts } from "../../kernel/protocols.js";
7
+ import type { SourceCapabilities } from "../../kernel/capabilities.js";
8
+ export declare class FilesystemSource implements SourcePort {
9
+ readonly baseDir: string;
10
+ readonly supportsReaders = true;
11
+ constructor(baseDir: string);
12
+ loadBootstrapDocs(scope: string, opts?: {
13
+ tenant?: string;
14
+ }): Promise<Record<string, unknown>[]>;
15
+ loadAll(scope: string, readers?: ReaderPort[]): Promise<Record<string, unknown>[]>;
16
+ /**
17
+ * Two-planes F2 — record-plane query over `loadAll` + the shared pure
18
+ * helpers (mirror of the Py `SourcePort.query` protocol-default). FS
19
+ * is dev-mode with small scopes; native push-down is the purview of
20
+ * the SQL adapters.
21
+ *
22
+ * `opts.tenant` is a documented NO-OP here: the FS TS adapter has no
23
+ * tenant-aware overlay merge in `loadAll` (divergence from the Py FS
24
+ * source, which unions base + tenant layer with shadowing) — overlay
25
+ * support is an F2.5 candidate alongside the writable FS source.
26
+ *
27
+ * Bundle-format kinds are not visible to this query (no kernel reader
28
+ * back-ref on the TS source) — record-plane docs are plain YAML.
29
+ */
30
+ query(scope: string, kind: string, opts?: SourceQueryOpts): AsyncIterable<Record<string, unknown>>;
31
+ /**
32
+ * Two-planes F2 — record-plane count over `loadAll` + `countDocs`
33
+ * (mirror of the Py protocol-default). Same `opts.tenant` NO-OP
34
+ * caveat as `query`.
35
+ */
36
+ count(scope: string, kind: string, opts?: SourceCountOpts): Promise<CountResult>;
37
+ /**
38
+ * Explicit contract declaration (s-sourceport-contract-cleanup) — kept
39
+ * honest by the adapter conformance test (declaration == structural
40
+ * derivation). Read-only FS source: in-memory query/count + the L1
41
+ * granular reads (loadOne + listDocRefs, s-dna-port-surface-parity);
42
+ * no bundle/write surface on the TS twin yet.
43
+ */
44
+ capabilities(): SourceCapabilities;
45
+ /**
46
+ * Documented NO-OP — the FS source holds no pooled resources (each read
47
+ * opens/closes its own file handles via fs/promises). The member exists
48
+ * for SourcePort surface parity with Python, where `close` is a
49
+ * SOURCE_PORT_CORE_MEMBERS boot-gate entry.
50
+ */
51
+ close(): Promise<void>;
52
+ /**
53
+ * L1 granular access — FS impl projects from `loadAll` (mirror of the
54
+ * Py `FilesystemSource.list_doc_refs`): `[kind, name]` refs only, no
55
+ * bundle rehydration. No perf gain over `loadAll` on FS, but keeps the
56
+ * SourcePort contract consistent across adapters (PG is where the gain
57
+ * lives). Tenant: union of base + overlay with the overlay shadowing
58
+ * base, same as the Py twin. Result sorted by (kind, name).
59
+ */
60
+ listDocRefs(scope: string, opts?: {
61
+ kind?: string | null;
62
+ tenant?: string | null;
63
+ }): Promise<Array<[string, string]>>;
64
+ resolveRef(scope: string, ref: string): Promise<string>;
65
+ /**
66
+ * L1 granular access — FS impl projects from `loadAll` (mirror of the
67
+ * Py `FilesystemSource.load_one`). No perf gain over `loadAll` on FS
68
+ * (cheap in-process disk reads) but keeps the SourcePort contract
69
+ * consistent across adapters. Tenant overlay shadows base: when
70
+ * `opts.tenant` is set the tenant layer is consulted first and the
71
+ * BASE layer is the fallback (same as Python — a tenant read of a doc
72
+ * with no overlay still returns the base doc).
73
+ */
74
+ loadOne(scope: string, kind: string, name: string, opts?: {
75
+ readers?: ReaderPort[];
76
+ tenant?: string | null;
77
+ }): Promise<Record<string, unknown> | null>;
78
+ loadLayer(scope: string, layerId: string, layerValue: string, readers?: ReaderPort[]): Promise<Record<string, unknown>[]>;
79
+ private _loadDir;
80
+ private _collectYaml;
81
+ private _readRecursive;
82
+ }