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,66 @@
|
|
|
1
|
+
/** The slice of the kernel this provider needs (embedding surface). */
|
|
2
|
+
export interface EmbeddingKernel {
|
|
3
|
+
embed(texts: string[]): Promise<number[][]>;
|
|
4
|
+
readonly embeddingDims: number;
|
|
5
|
+
readonly embeddingModelId: string;
|
|
6
|
+
}
|
|
7
|
+
/** A record to index. `text` is used verbatim if present; otherwise derived
|
|
8
|
+
* from `raw` via {@link documentText}. */
|
|
9
|
+
export interface SearchRecord {
|
|
10
|
+
scope: string;
|
|
11
|
+
kind: string;
|
|
12
|
+
name: string;
|
|
13
|
+
tenant?: string;
|
|
14
|
+
text?: string;
|
|
15
|
+
raw?: Record<string, unknown>;
|
|
16
|
+
title?: string;
|
|
17
|
+
snippet?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface SearchHit extends Record<string, unknown> {
|
|
20
|
+
scope: string;
|
|
21
|
+
kind: string;
|
|
22
|
+
name: string;
|
|
23
|
+
score: number;
|
|
24
|
+
}
|
|
25
|
+
/** An id to delete: `{ scope, kind, name, tenant? }`. */
|
|
26
|
+
export interface RecordId {
|
|
27
|
+
scope: string;
|
|
28
|
+
kind: string;
|
|
29
|
+
name: string;
|
|
30
|
+
tenant?: string;
|
|
31
|
+
}
|
|
32
|
+
/** Derive the searchable text blob for a raw document — every string value in
|
|
33
|
+
* `spec` plus `metadata.name`, in document order (parity with the Python
|
|
34
|
+
* `document_text`). */
|
|
35
|
+
export declare function documentText(raw: Record<string, unknown>): string;
|
|
36
|
+
export declare class SqliteVecRecordSearchProvider {
|
|
37
|
+
private readonly kernel;
|
|
38
|
+
private readonly dbDir;
|
|
39
|
+
private readonly singlePath;
|
|
40
|
+
private readonly rrfK;
|
|
41
|
+
private readonly conns;
|
|
42
|
+
constructor(kernel: EmbeddingKernel, opts?: {
|
|
43
|
+
dbDir?: string;
|
|
44
|
+
dbPath?: string;
|
|
45
|
+
rrfK?: number;
|
|
46
|
+
});
|
|
47
|
+
private pathFor;
|
|
48
|
+
private connFor;
|
|
49
|
+
private pinIdentity;
|
|
50
|
+
/** Index (upsert) records into their scope's store. Idempotent by text hash
|
|
51
|
+
* (re-indexing unchanged text is skipped). Returns the count actually
|
|
52
|
+
* (re)embedded. */
|
|
53
|
+
index(records: SearchRecord[]): Promise<number>;
|
|
54
|
+
private upsert;
|
|
55
|
+
/** Delete indexed records. Returns the number of rows removed. */
|
|
56
|
+
delete(ids: RecordId[]): Promise<number>;
|
|
57
|
+
search(opts: {
|
|
58
|
+
scope: string;
|
|
59
|
+
queryText: string;
|
|
60
|
+
kind?: string | null;
|
|
61
|
+
k?: number;
|
|
62
|
+
tenant?: string;
|
|
63
|
+
}): Promise<SearchHit[]>;
|
|
64
|
+
private resolveMeta;
|
|
65
|
+
close(): void;
|
|
66
|
+
}
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SqliteVecRecordSearchProvider — the embeddable default RecordSearchProvider
|
|
3
|
+
* (TS twin of `dna/adapters/search/sqlite_vec.py`).
|
|
4
|
+
*
|
|
5
|
+
* The FIRST real implementation of the `RecordSearchProvider` port on the TS
|
|
6
|
+
* side. Hybrid search inside one SQLite file per scope, offline, no server:
|
|
7
|
+
*
|
|
8
|
+
* - dense — sqlite-vec `vec0` KNN over `kernel.embed()` vectors (the
|
|
9
|
+
* deterministic `FakeEmbeddingProvider` floor by default).
|
|
10
|
+
* - lexical — FTS5 BM25 over the same text.
|
|
11
|
+
* - fusion — Reciprocal Rank Fusion (`reciprocalRankFusion`, the pure
|
|
12
|
+
* function shared with the Python twin).
|
|
13
|
+
*
|
|
14
|
+
* The store schema is OWNED by a numbered migration (`migrations.ts`), closing
|
|
15
|
+
* f-embeddings-ddl-debt. Overlay/tenant-aware: `tenant` is a column ('' = base);
|
|
16
|
+
* a tenant search reads base ∪ overlay and the overlay row shadows the base row
|
|
17
|
+
* for the same `(kind, name)`.
|
|
18
|
+
*
|
|
19
|
+
* SQLite access goes through {@link openSearchDb} (bun:sqlite or node:sqlite);
|
|
20
|
+
* sqlite-vec is an OPTIONAL peer dep (`sqlite-vec`), never in the default graph.
|
|
21
|
+
* Both are exercised by the shared record-search conformance kit with the fake
|
|
22
|
+
* embedder, offline.
|
|
23
|
+
*/
|
|
24
|
+
import { sha256 } from "js-sha256";
|
|
25
|
+
import { DEFAULT_RRF_K, reciprocalRankFusion } from "./rrf.js";
|
|
26
|
+
import { buildMigrations, runSearchMigrations } from "./migrations.js";
|
|
27
|
+
import { openSearchDb, serializeF32 } from "./driver.js";
|
|
28
|
+
const OVERFETCH = 4;
|
|
29
|
+
const MIN_CANDIDATES = 40;
|
|
30
|
+
/** Derive the searchable text blob for a raw document — every string value in
|
|
31
|
+
* `spec` plus `metadata.name`, in document order (parity with the Python
|
|
32
|
+
* `document_text`). */
|
|
33
|
+
export function documentText(raw) {
|
|
34
|
+
const parts = [];
|
|
35
|
+
const meta = raw.metadata ?? {};
|
|
36
|
+
const name = meta.name ?? raw.name;
|
|
37
|
+
if (typeof name === "string")
|
|
38
|
+
parts.push(name);
|
|
39
|
+
const walk = (node) => {
|
|
40
|
+
if (typeof node === "string")
|
|
41
|
+
parts.push(node);
|
|
42
|
+
else if (Array.isArray(node))
|
|
43
|
+
node.forEach(walk);
|
|
44
|
+
else if (node && typeof node === "object")
|
|
45
|
+
Object.values(node).forEach(walk);
|
|
46
|
+
};
|
|
47
|
+
walk(raw.spec ?? {});
|
|
48
|
+
return parts.filter((p) => p).join("\n");
|
|
49
|
+
}
|
|
50
|
+
export class SqliteVecRecordSearchProvider {
|
|
51
|
+
kernel;
|
|
52
|
+
dbDir;
|
|
53
|
+
singlePath;
|
|
54
|
+
rrfK;
|
|
55
|
+
conns = new Map();
|
|
56
|
+
constructor(kernel, opts = {}) {
|
|
57
|
+
this.kernel = kernel;
|
|
58
|
+
let dbDir = opts.dbDir ?? null;
|
|
59
|
+
if (dbDir === null && !opts.dbPath) {
|
|
60
|
+
const env = globalThis
|
|
61
|
+
.process?.env;
|
|
62
|
+
dbDir = env?.DNA_SEARCH_DIR ?? ".dna-search";
|
|
63
|
+
}
|
|
64
|
+
this.dbDir = opts.dbPath ? null : dbDir;
|
|
65
|
+
this.singlePath = opts.dbPath ?? null;
|
|
66
|
+
this.rrfK = opts.rrfK ?? DEFAULT_RRF_K;
|
|
67
|
+
}
|
|
68
|
+
// ------------------------------------------------------------------
|
|
69
|
+
// store / schema (migration-owned)
|
|
70
|
+
// ------------------------------------------------------------------
|
|
71
|
+
pathFor(scope) {
|
|
72
|
+
if (this.singlePath)
|
|
73
|
+
return this.singlePath;
|
|
74
|
+
const safe = scope.replace(/[/\\]/g, "_");
|
|
75
|
+
return `${this.dbDir}/${safe}.db`;
|
|
76
|
+
}
|
|
77
|
+
async connFor(scope) {
|
|
78
|
+
const path = this.pathFor(scope);
|
|
79
|
+
const existing = this.conns.get(path);
|
|
80
|
+
if (existing)
|
|
81
|
+
return existing;
|
|
82
|
+
if (this.dbDir && !this.singlePath)
|
|
83
|
+
await ensureDir(this.dbDir);
|
|
84
|
+
const db = await openSearchDb(path);
|
|
85
|
+
runSearchMigrations(db, buildMigrations(this.kernel.embeddingDims));
|
|
86
|
+
this.pinIdentity(db);
|
|
87
|
+
this.conns.set(path, db);
|
|
88
|
+
return db;
|
|
89
|
+
}
|
|
90
|
+
pinIdentity(db) {
|
|
91
|
+
const dims = String(this.kernel.embeddingDims);
|
|
92
|
+
const modelId = this.kernel.embeddingModelId;
|
|
93
|
+
const rows = db.all("SELECT key, value FROM search_meta");
|
|
94
|
+
if (rows.length === 0) {
|
|
95
|
+
db.run("INSERT INTO search_meta (key, value) VALUES (?, ?)", ["embedding_dims", dims]);
|
|
96
|
+
db.run("INSERT INTO search_meta (key, value) VALUES (?, ?)", ["embedding_model_id", modelId]);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const meta = Object.fromEntries(rows.map((r) => [r.key, r.value]));
|
|
100
|
+
if (meta.embedding_dims !== dims || meta.embedding_model_id !== modelId) {
|
|
101
|
+
throw new Error(`search store was built for embedding space (${meta.embedding_model_id}, `
|
|
102
|
+
+ `dims=${meta.embedding_dims}) but the active provider is (${modelId}, `
|
|
103
|
+
+ `dims=${dims}) — the vectors are incomparable. Use a fresh store dir `
|
|
104
|
+
+ "or re-index.");
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// ------------------------------------------------------------------
|
|
108
|
+
// index / delete
|
|
109
|
+
// ------------------------------------------------------------------
|
|
110
|
+
/** Index (upsert) records into their scope's store. Idempotent by text hash
|
|
111
|
+
* (re-indexing unchanged text is skipped). Returns the count actually
|
|
112
|
+
* (re)embedded. */
|
|
113
|
+
async index(records) {
|
|
114
|
+
if (records.length === 0)
|
|
115
|
+
return 0;
|
|
116
|
+
const pending = records.map((rec) => {
|
|
117
|
+
const text = rec.text ?? documentText(rec.raw ?? {});
|
|
118
|
+
return { rec, text, hash: sha256(text) };
|
|
119
|
+
});
|
|
120
|
+
const toEmbed = [];
|
|
121
|
+
for (const item of pending) {
|
|
122
|
+
const db = await this.connFor(item.rec.scope);
|
|
123
|
+
const existing = db.get("SELECT text_hash FROM search_docs WHERE scope=? AND kind=? AND name=? AND tenant=?", [item.rec.scope, item.rec.kind, item.rec.name, item.rec.tenant ?? ""]);
|
|
124
|
+
if (existing && existing.text_hash === item.hash)
|
|
125
|
+
continue;
|
|
126
|
+
toEmbed.push(item);
|
|
127
|
+
}
|
|
128
|
+
if (toEmbed.length === 0)
|
|
129
|
+
return 0;
|
|
130
|
+
const vectors = await this.kernel.embed(toEmbed.map((i) => i.text));
|
|
131
|
+
toEmbed.forEach((item, i) => this.upsert(item.rec, item.text, item.hash, vectors[i]));
|
|
132
|
+
return toEmbed.length;
|
|
133
|
+
}
|
|
134
|
+
upsert(rec, text, textHash, vector) {
|
|
135
|
+
const db = this.conns.get(this.pathFor(rec.scope));
|
|
136
|
+
const tenant = rec.tenant ?? "";
|
|
137
|
+
const title = rec.title ?? null;
|
|
138
|
+
const snippet = rec.snippet ?? snippetOf(text);
|
|
139
|
+
const row = db.get("SELECT rowid FROM search_docs WHERE scope=? AND kind=? AND name=? AND tenant=?", [rec.scope, rec.kind, rec.name, tenant]);
|
|
140
|
+
let rowid;
|
|
141
|
+
if (!row) {
|
|
142
|
+
const info = db.run("INSERT INTO search_docs (scope, kind, name, tenant, text_hash, title, snippet, text) "
|
|
143
|
+
+ "VALUES (?,?,?,?,?,?,?,?)", [rec.scope, rec.kind, rec.name, tenant, textHash, title, snippet, text]);
|
|
144
|
+
rowid = info.lastInsertRowid;
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
rowid = row.rowid;
|
|
148
|
+
db.run("UPDATE search_docs SET text_hash=?, title=?, snippet=?, text=? WHERE rowid=?", [
|
|
149
|
+
textHash, title, snippet, text, rowid,
|
|
150
|
+
]);
|
|
151
|
+
db.run("DELETE FROM search_vec WHERE doc_rowid=?", [BigInt(rowid)]);
|
|
152
|
+
db.run("DELETE FROM search_fts WHERE rowid=?", [BigInt(rowid)]);
|
|
153
|
+
}
|
|
154
|
+
// vec0 (and fts5) require an INTEGER rowid binding — node:sqlite binds a JS
|
|
155
|
+
// number as a double and vec0 rejects it, so pass BigInt (both drivers OK).
|
|
156
|
+
db.run("INSERT INTO search_vec (doc_rowid, embedding) VALUES (?, ?)", [
|
|
157
|
+
BigInt(rowid), serializeF32(vector),
|
|
158
|
+
]);
|
|
159
|
+
db.run("INSERT INTO search_fts (rowid, text) VALUES (?, ?)", [BigInt(rowid), text]);
|
|
160
|
+
}
|
|
161
|
+
/** Delete indexed records. Returns the number of rows removed. */
|
|
162
|
+
async delete(ids) {
|
|
163
|
+
let removed = 0;
|
|
164
|
+
for (const id of ids) {
|
|
165
|
+
const db = await this.connFor(id.scope);
|
|
166
|
+
const row = db.get("SELECT rowid FROM search_docs WHERE scope=? AND kind=? AND name=? AND tenant=?", [id.scope, id.kind, id.name, id.tenant ?? ""]);
|
|
167
|
+
if (!row)
|
|
168
|
+
continue;
|
|
169
|
+
const rowid = BigInt(row.rowid);
|
|
170
|
+
db.run("DELETE FROM search_vec WHERE doc_rowid=?", [rowid]);
|
|
171
|
+
db.run("DELETE FROM search_fts WHERE rowid=?", [rowid]);
|
|
172
|
+
db.run("DELETE FROM search_docs WHERE rowid=?", [rowid]);
|
|
173
|
+
removed += 1;
|
|
174
|
+
}
|
|
175
|
+
return removed;
|
|
176
|
+
}
|
|
177
|
+
// ------------------------------------------------------------------
|
|
178
|
+
// search (RecordSearchProvider)
|
|
179
|
+
// ------------------------------------------------------------------
|
|
180
|
+
async search(opts) {
|
|
181
|
+
const { scope, queryText } = opts;
|
|
182
|
+
const kind = opts.kind ?? null;
|
|
183
|
+
const k = opts.k ?? 10;
|
|
184
|
+
const tenant = opts.tenant ?? "";
|
|
185
|
+
if (!queryText.trim() || k <= 0)
|
|
186
|
+
return [];
|
|
187
|
+
const db = await this.connFor(scope);
|
|
188
|
+
const overfetch = Math.max(MIN_CANDIDATES, k * OVERFETCH);
|
|
189
|
+
const queryVec = (await this.kernel.embed([queryText]))[0];
|
|
190
|
+
let denseRanked = [];
|
|
191
|
+
if (queryVec.some((x) => x !== 0)) {
|
|
192
|
+
denseRanked = db
|
|
193
|
+
.all("SELECT doc_rowid FROM search_vec WHERE embedding MATCH ? ORDER BY distance LIMIT ?", [serializeF32(queryVec), overfetch])
|
|
194
|
+
.map((r) => r.doc_rowid);
|
|
195
|
+
}
|
|
196
|
+
let lexicalRanked = [];
|
|
197
|
+
const ftsQuery = ftsQueryOf(queryText);
|
|
198
|
+
if (ftsQuery) {
|
|
199
|
+
try {
|
|
200
|
+
lexicalRanked = db
|
|
201
|
+
.all("SELECT rowid FROM search_fts WHERE search_fts MATCH ? ORDER BY bm25(search_fts) LIMIT ?", [ftsQuery, overfetch])
|
|
202
|
+
.map((r) => r.rowid);
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
lexicalRanked = [];
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (denseRanked.length === 0 && lexicalRanked.length === 0)
|
|
209
|
+
return [];
|
|
210
|
+
const fused = reciprocalRankFusion([denseRanked.map(String), lexicalRanked.map(String)], this.rrfK);
|
|
211
|
+
const densePos = new Map(denseRanked.map((r, i) => [r, i + 1]));
|
|
212
|
+
const lexicalPos = new Map(lexicalRanked.map((r, i) => [r, i + 1]));
|
|
213
|
+
const rowids = fused.map(([rid]) => Number(rid));
|
|
214
|
+
const meta = this.resolveMeta(db, rowids);
|
|
215
|
+
const best = new Map();
|
|
216
|
+
for (const [rid, score] of fused) {
|
|
217
|
+
const rowid = Number(rid);
|
|
218
|
+
const m = meta.get(rowid);
|
|
219
|
+
if (!m)
|
|
220
|
+
continue;
|
|
221
|
+
if (kind !== null && m.kind !== kind)
|
|
222
|
+
continue;
|
|
223
|
+
const rowTenant = m.tenant ?? "";
|
|
224
|
+
if (rowTenant !== "" && rowTenant !== (tenant || ""))
|
|
225
|
+
continue; // other tenant — never leaks
|
|
226
|
+
const key = `${m.kind}${m.name}`;
|
|
227
|
+
const prev = best.get(key);
|
|
228
|
+
const hit = makeHit(scope, m, score, densePos.get(rowid), lexicalPos.get(rowid));
|
|
229
|
+
if (!prev) {
|
|
230
|
+
best.set(key, hit);
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
const thisIsOverlay = rowTenant !== "" && rowTenant === (tenant || "");
|
|
234
|
+
if (thisIsOverlay && prev._tenant === "")
|
|
235
|
+
best.set(key, hit);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
const hits = [...best.values()].sort((a, b) => b.score - a.score);
|
|
239
|
+
for (const h of hits)
|
|
240
|
+
delete h._tenant;
|
|
241
|
+
return hits.slice(0, k);
|
|
242
|
+
}
|
|
243
|
+
resolveMeta(db, rowids) {
|
|
244
|
+
if (rowids.length === 0)
|
|
245
|
+
return new Map();
|
|
246
|
+
const placeholders = rowids.map(() => "?").join(",");
|
|
247
|
+
const rows = db.all(`SELECT rowid, scope, kind, name, tenant, title, snippet FROM search_docs `
|
|
248
|
+
+ `WHERE rowid IN (${placeholders})`, rowids);
|
|
249
|
+
return new Map(rows.map((r) => [r.rowid, r]));
|
|
250
|
+
}
|
|
251
|
+
close() {
|
|
252
|
+
for (const db of this.conns.values()) {
|
|
253
|
+
try {
|
|
254
|
+
db.close();
|
|
255
|
+
}
|
|
256
|
+
catch {
|
|
257
|
+
/* ignore */
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
this.conns.clear();
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
function makeHit(scope, m, score, rankDense, rankLexical) {
|
|
264
|
+
const hit = {
|
|
265
|
+
scope, kind: m.kind, name: m.name, score, _tenant: m.tenant ?? "",
|
|
266
|
+
};
|
|
267
|
+
if (m.title)
|
|
268
|
+
hit.title = m.title;
|
|
269
|
+
if (m.snippet)
|
|
270
|
+
hit.snippet = m.snippet;
|
|
271
|
+
if (rankDense !== undefined)
|
|
272
|
+
hit.rank_dense = rankDense;
|
|
273
|
+
if (rankLexical !== undefined)
|
|
274
|
+
hit.rank_lexical = rankLexical;
|
|
275
|
+
return hit;
|
|
276
|
+
}
|
|
277
|
+
function snippetOf(text, maxLen = 200) {
|
|
278
|
+
const flat = text.split(/\s+/).filter(Boolean).join(" ");
|
|
279
|
+
return flat.length > maxLen ? flat.slice(0, maxLen) + "…" : flat;
|
|
280
|
+
}
|
|
281
|
+
/** OR of quoted alphanumeric tokens — parity with the Python `_fts_query`. */
|
|
282
|
+
function ftsQueryOf(queryText) {
|
|
283
|
+
const tokens = queryText.toLowerCase().match(/[a-z0-9]+/g) ?? [];
|
|
284
|
+
return tokens.map((t) => `"${t}"`).join(" OR ");
|
|
285
|
+
}
|
|
286
|
+
async function ensureDir(dir) {
|
|
287
|
+
try {
|
|
288
|
+
const fs = (await import("node:fs"));
|
|
289
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
/* best effort — open will surface a real failure */
|
|
293
|
+
}
|
|
294
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opinionated SDK bootstrap.
|
|
3
|
+
*
|
|
4
|
+
* The kernel itself (src/kernel/*) is extension-agnostic by design — it
|
|
5
|
+
* knows about the 5-port architecture and nothing else. This module is
|
|
6
|
+
* where the SDK ships its default wiring: the six built-in extensions,
|
|
7
|
+
* the default resolvers, and the quick-start helpers used by examples
|
|
8
|
+
* and tests.
|
|
9
|
+
*
|
|
10
|
+
* Callers that want a minimal kernel can `import { Kernel }` directly
|
|
11
|
+
* and register exactly the extensions they need. Callers that want the
|
|
12
|
+
* batteries-included experience use `createKernelWithBuiltins()` or
|
|
13
|
+
* `quickInstance()`.
|
|
14
|
+
*/
|
|
15
|
+
import { Kernel } from "./kernel/index.js";
|
|
16
|
+
import { Runtime } from "./kernel/runtime.js";
|
|
17
|
+
import type { ManifestInstance } from "./kernel/instance.js";
|
|
18
|
+
/**
|
|
19
|
+
* Return a fresh Kernel with all six built-in extensions registered.
|
|
20
|
+
* No source, cache, or resolvers wired — callers are responsible for
|
|
21
|
+
* that. Use `quickInstance()` if you want the full batteries-included
|
|
22
|
+
* shortcut.
|
|
23
|
+
*/
|
|
24
|
+
export declare function createKernelWithBuiltins(): Kernel;
|
|
25
|
+
/**
|
|
26
|
+
* Batteries-included shortcut: kernel + all built-in extensions +
|
|
27
|
+
* default filesystem source / cache / resolvers, then returns a
|
|
28
|
+
* `ManifestInstance` for the given scope. Equivalent to the old
|
|
29
|
+
* `Kernel.quick(scope, baseDir)` static method that used to live on
|
|
30
|
+
* the kernel class itself.
|
|
31
|
+
*/
|
|
32
|
+
export declare function quickInstance(scope: string, baseDir?: string): Promise<ManifestInstance>;
|
|
33
|
+
/**
|
|
34
|
+
* Return a fresh Runtime with all six built-in extensions registered.
|
|
35
|
+
* No source, cache, or resolvers wired — callers are responsible for
|
|
36
|
+
* that. Use `quickManifest()` if you want the full batteries-included
|
|
37
|
+
* shortcut.
|
|
38
|
+
*/
|
|
39
|
+
export declare function createRuntimeWithBuiltins(): Runtime;
|
|
40
|
+
/**
|
|
41
|
+
* Batteries-included shortcut using Runtime: all built-in extensions +
|
|
42
|
+
* default filesystem source / cache / resolvers, then returns a
|
|
43
|
+
* `ManifestInstance` for the given scope.
|
|
44
|
+
*/
|
|
45
|
+
export declare function quickManifest(scope: string, baseDir?: string): Promise<ManifestInstance>;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opinionated SDK bootstrap.
|
|
3
|
+
*
|
|
4
|
+
* The kernel itself (src/kernel/*) is extension-agnostic by design — it
|
|
5
|
+
* knows about the 5-port architecture and nothing else. This module is
|
|
6
|
+
* where the SDK ships its default wiring: the six built-in extensions,
|
|
7
|
+
* the default resolvers, and the quick-start helpers used by examples
|
|
8
|
+
* and tests.
|
|
9
|
+
*
|
|
10
|
+
* Callers that want a minimal kernel can `import { Kernel }` directly
|
|
11
|
+
* and register exactly the extensions they need. Callers that want the
|
|
12
|
+
* batteries-included experience use `createKernelWithBuiltins()` or
|
|
13
|
+
* `quickInstance()`.
|
|
14
|
+
*/
|
|
15
|
+
import { Kernel } from "./kernel/index.js";
|
|
16
|
+
import { Runtime } from "./kernel/runtime.js";
|
|
17
|
+
import { FilesystemSource } from "./adapters/filesystem/source.js";
|
|
18
|
+
import { FilesystemCache } from "./adapters/filesystem/cache.js";
|
|
19
|
+
import { LocalResolver } from "./adapters/resolvers/local.js";
|
|
20
|
+
import { HttpResolver } from "./adapters/resolvers/http.js";
|
|
21
|
+
import { GitHubResolver } from "./adapters/resolvers/github.js";
|
|
22
|
+
import { HelixExtension } from "./extensions/helix.js";
|
|
23
|
+
import { AgentSkillsExtension } from "./extensions/agentskills.js";
|
|
24
|
+
import { SoulSpecExtension } from "./extensions/soulspec.js";
|
|
25
|
+
import { AgentsMdExtension } from "./extensions/agentsmd.js";
|
|
26
|
+
import { GuardrailExtension } from "./extensions/guardrails.js";
|
|
27
|
+
import { HookExtension } from "./extensions/hooks.js";
|
|
28
|
+
import { KindDefinitionExtension } from "./extensions/kinddef.js";
|
|
29
|
+
import { SafetyPolicyExtension } from "./extensions/safety.js";
|
|
30
|
+
import { RecognizerExtension } from "./extensions/recognizer.js";
|
|
31
|
+
import { FederationExtension } from "./extensions/federation.js";
|
|
32
|
+
import { SdlcExtension } from "./extensions/sdlc.js";
|
|
33
|
+
import { AuditExtension } from "./extensions/audit.js";
|
|
34
|
+
import { LessonExtension } from "./extensions/lesson.js";
|
|
35
|
+
import { TenantExtension } from "./extensions/tenant.js";
|
|
36
|
+
import { EvidenceExtension } from "./extensions/evidence.js";
|
|
37
|
+
import { DocExtension } from "./extensions/doc.js";
|
|
38
|
+
import { ResearchExtension } from "./extensions/research.js";
|
|
39
|
+
import { TestkitExtension } from "./extensions/testkit.js";
|
|
40
|
+
import { ModelRegExtension } from "./extensions/modelreg.js";
|
|
41
|
+
import { AutomationExtension } from "./extensions/automation.js";
|
|
42
|
+
import { EvalExtension } from "./extensions/eval.js";
|
|
43
|
+
/**
|
|
44
|
+
* The canonical built-in extension set. Loaded into BOTH a Kernel and a
|
|
45
|
+
* Runtime through this SINGLE list so the two bootstraps can never drift
|
|
46
|
+
* (s-export-unwired-ts-extensions — they had, and Community/Research/Sdlc were
|
|
47
|
+
* loaded by neither). Add a built-in here once and both paths get it.
|
|
48
|
+
*/
|
|
49
|
+
function loadBuiltins(target) {
|
|
50
|
+
for (const ext of [
|
|
51
|
+
new HelixExtension(),
|
|
52
|
+
new AgentSkillsExtension(),
|
|
53
|
+
new SoulSpecExtension(),
|
|
54
|
+
new AgentsMdExtension(),
|
|
55
|
+
new GuardrailExtension(),
|
|
56
|
+
new HookExtension(),
|
|
57
|
+
new KindDefinitionExtension(),
|
|
58
|
+
new SafetyPolicyExtension(),
|
|
59
|
+
new RecognizerExtension(),
|
|
60
|
+
new FederationExtension(),
|
|
61
|
+
new SdlcExtension(),
|
|
62
|
+
new AuditExtension(),
|
|
63
|
+
new LessonExtension(),
|
|
64
|
+
new TenantExtension(),
|
|
65
|
+
new EvidenceExtension(),
|
|
66
|
+
new DocExtension(),
|
|
67
|
+
new ResearchExtension(),
|
|
68
|
+
new TestkitExtension(),
|
|
69
|
+
new ModelRegExtension(),
|
|
70
|
+
new AutomationExtension(),
|
|
71
|
+
new EvalExtension(),
|
|
72
|
+
]) {
|
|
73
|
+
target.load(ext);
|
|
74
|
+
}
|
|
75
|
+
// s-alias-generated-not-typed — com TODAS as extensions carregadas, todo
|
|
76
|
+
// dep_filter builtin deve resolver pra um alias registrado. Antes: alias
|
|
77
|
+
// com typo degradava o prompt silenciosamente (warning enterrado); agora
|
|
78
|
+
// o boot falha apontando o Kind + campo + alias. Runtime herda de Kernel,
|
|
79
|
+
// então AMBOS os caminhos (createKernelWithBuiltins/createRuntimeWithBuiltins)
|
|
80
|
+
// passam por aqui — o twin TS do gate no fim de Kernel.auto() (Python).
|
|
81
|
+
target
|
|
82
|
+
.validateDepFilters?.();
|
|
83
|
+
return target;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Return a fresh Kernel with all six built-in extensions registered.
|
|
87
|
+
* No source, cache, or resolvers wired — callers are responsible for
|
|
88
|
+
* that. Use `quickInstance()` if you want the full batteries-included
|
|
89
|
+
* shortcut.
|
|
90
|
+
*/
|
|
91
|
+
export function createKernelWithBuiltins() {
|
|
92
|
+
return loadBuiltins(new Kernel());
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Batteries-included shortcut: kernel + all built-in extensions +
|
|
96
|
+
* default filesystem source / cache / resolvers, then returns a
|
|
97
|
+
* `ManifestInstance` for the given scope. Equivalent to the old
|
|
98
|
+
* `Kernel.quick(scope, baseDir)` static method that used to live on
|
|
99
|
+
* the kernel class itself.
|
|
100
|
+
*/
|
|
101
|
+
export async function quickInstance(scope, baseDir = ".dna") {
|
|
102
|
+
const k = createKernelWithBuiltins();
|
|
103
|
+
k.source(new FilesystemSource(baseDir));
|
|
104
|
+
k.cache(new FilesystemCache(baseDir));
|
|
105
|
+
k.resolver("local", new LocalResolver(baseDir));
|
|
106
|
+
k.resolver("http", new HttpResolver());
|
|
107
|
+
k.resolver("https", new HttpResolver());
|
|
108
|
+
k.resolver("github", new GitHubResolver());
|
|
109
|
+
return k.instance(scope);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Return a fresh Runtime with all six built-in extensions registered.
|
|
113
|
+
* No source, cache, or resolvers wired — callers are responsible for
|
|
114
|
+
* that. Use `quickManifest()` if you want the full batteries-included
|
|
115
|
+
* shortcut.
|
|
116
|
+
*/
|
|
117
|
+
export function createRuntimeWithBuiltins() {
|
|
118
|
+
return loadBuiltins(new Runtime());
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Batteries-included shortcut using Runtime: all built-in extensions +
|
|
122
|
+
* default filesystem source / cache / resolvers, then returns a
|
|
123
|
+
* `ManifestInstance` for the given scope.
|
|
124
|
+
*/
|
|
125
|
+
export async function quickManifest(scope, baseDir = ".dna") {
|
|
126
|
+
const rt = createRuntimeWithBuiltins();
|
|
127
|
+
rt.storage(new FilesystemSource(baseDir));
|
|
128
|
+
rt.cache(new FilesystemCache(baseDir));
|
|
129
|
+
rt.resolver("local", new LocalResolver(baseDir));
|
|
130
|
+
rt.resolver("http", new HttpResolver());
|
|
131
|
+
rt.resolver("https", new HttpResolver());
|
|
132
|
+
rt.resolver("github", new GitHubResolver());
|
|
133
|
+
return rt.manifest(scope);
|
|
134
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Skill
|
|
2
|
+
|
|
3
|
+
A Skill is a modular, progressively-disclosed unit of know-how. It is stored
|
|
4
|
+
as a bundle rooted on a `SKILL.md` marker file plus optional `scripts/`,
|
|
5
|
+
`references/`, and `assets/` directories. The shape is compatible with
|
|
6
|
+
Anthropic's Agent Skills format
|
|
7
|
+
(https://docs.anthropic.com/en/docs/agents/skills).
|
|
8
|
+
|
|
9
|
+
Skills are NOT flattened into the agent's system prompt. Instead, the harness
|
|
10
|
+
(e.g. DeepAgents' `SkillsMiddleware`) exposes a short catalogue of
|
|
11
|
+
`{name, description}` entries in the system prompt; the agent decides when to
|
|
12
|
+
read the full `SKILL.md` on demand via the `read` tool. This keeps the context
|
|
13
|
+
window lean while still giving the agent access to deep procedural knowledge.
|
|
14
|
+
|
|
15
|
+
**Composition:** Agents reference Skills via their `dep_filters.skills`
|
|
16
|
+
(alias `agentskills-skill`). A single Skill can be shared across many agents
|
|
17
|
+
or modules, resolved either locally or from remote dependencies via the
|
|
18
|
+
resolver ports.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentSkillsExtension — Skill kind + SkillReader.
|
|
3
|
+
*
|
|
4
|
+
* 1:1 parity with Python dna.v3.extensions.agentskills.
|
|
5
|
+
*/
|
|
6
|
+
import type { BundleHandle } from "../kernel/bundle-handle.js";
|
|
7
|
+
import type { ExtensionHost, Extension, ReaderPort, SerializedFile, WriterPort } from "../kernel/protocols.js";
|
|
8
|
+
import type { FSLike } from "../kernel/fs.js";
|
|
9
|
+
export declare class SkillReader implements ReaderPort {
|
|
10
|
+
private fs;
|
|
11
|
+
constructor(fs: FSLike);
|
|
12
|
+
detect(bundle: BundleHandle): boolean;
|
|
13
|
+
read(bundle: BundleHandle): Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
export declare class SkillWriter implements WriterPort {
|
|
16
|
+
private fs;
|
|
17
|
+
constructor(fs: FSLike);
|
|
18
|
+
canWrite(raw: Record<string, unknown>): boolean;
|
|
19
|
+
write(bundle: BundleHandle, raw: Record<string, unknown>): void;
|
|
20
|
+
serialize(raw: Record<string, unknown>): SerializedFile[];
|
|
21
|
+
}
|
|
22
|
+
export declare class AgentSkillsExtension implements Extension {
|
|
23
|
+
private fs;
|
|
24
|
+
readonly name = "agentskills";
|
|
25
|
+
readonly version = "1.0.0";
|
|
26
|
+
constructor(fs?: FSLike);
|
|
27
|
+
register(kernel: ExtensionHost): void;
|
|
28
|
+
}
|