skillscript-runtime 0.9.9 → 0.13.2

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 (92) hide show
  1. package/README.md +39 -46
  2. package/dist/bootstrap.d.ts +57 -18
  3. package/dist/bootstrap.d.ts.map +1 -1
  4. package/dist/bootstrap.js +188 -54
  5. package/dist/bootstrap.js.map +1 -1
  6. package/dist/cli.js +5 -6
  7. package/dist/cli.js.map +1 -1
  8. package/dist/connectors/agent-noop.d.ts +2 -2
  9. package/dist/connectors/agent-noop.d.ts.map +1 -1
  10. package/dist/connectors/config.d.ts +46 -0
  11. package/dist/connectors/config.d.ts.map +1 -1
  12. package/dist/connectors/config.js +109 -1
  13. package/dist/connectors/config.js.map +1 -1
  14. package/dist/connectors/index.d.ts +3 -1
  15. package/dist/connectors/index.d.ts.map +1 -1
  16. package/dist/connectors/index.js +6 -3
  17. package/dist/connectors/index.js.map +1 -1
  18. package/dist/connectors/local-model-mcp.d.ts +3 -3
  19. package/dist/connectors/local-model-mcp.d.ts.map +1 -1
  20. package/dist/connectors/local-model.d.ts +30 -11
  21. package/dist/connectors/local-model.d.ts.map +1 -1
  22. package/dist/connectors/local-model.js +44 -12
  23. package/dist/connectors/local-model.js.map +1 -1
  24. package/dist/connectors/mcp-remote.d.ts +3 -3
  25. package/dist/connectors/mcp-remote.d.ts.map +1 -1
  26. package/dist/connectors/mcp.d.ts +3 -3
  27. package/dist/connectors/mcp.d.ts.map +1 -1
  28. package/dist/connectors/memory-store-mcp.d.ts +3 -3
  29. package/dist/connectors/memory-store-mcp.d.ts.map +1 -1
  30. package/dist/connectors/memory-store-mcp.js +3 -1
  31. package/dist/connectors/memory-store-mcp.js.map +1 -1
  32. package/dist/connectors/memory-store.d.ts +26 -6
  33. package/dist/connectors/memory-store.d.ts.map +1 -1
  34. package/dist/connectors/memory-store.js +84 -15
  35. package/dist/connectors/memory-store.js.map +1 -1
  36. package/dist/connectors/registry.d.ts +28 -5
  37. package/dist/connectors/registry.d.ts.map +1 -1
  38. package/dist/connectors/registry.js +34 -11
  39. package/dist/connectors/registry.js.map +1 -1
  40. package/dist/connectors/skill-store.d.ts +3 -3
  41. package/dist/connectors/skill-store.d.ts.map +1 -1
  42. package/dist/connectors/sqlite-skill-store.d.ts +89 -0
  43. package/dist/connectors/sqlite-skill-store.d.ts.map +1 -0
  44. package/dist/connectors/sqlite-skill-store.js +506 -0
  45. package/dist/connectors/sqlite-skill-store.js.map +1 -0
  46. package/dist/connectors/types.d.ts +86 -9
  47. package/dist/connectors/types.d.ts.map +1 -1
  48. package/dist/connectors/types.js.map +1 -1
  49. package/dist/errors.d.ts +15 -1
  50. package/dist/errors.d.ts.map +1 -1
  51. package/dist/errors.js +47 -6
  52. package/dist/errors.js.map +1 -1
  53. package/dist/help-content.d.ts.map +1 -1
  54. package/dist/help-content.js +18 -4
  55. package/dist/help-content.js.map +1 -1
  56. package/dist/index.d.ts +2 -0
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +1 -0
  59. package/dist/index.js.map +1 -1
  60. package/dist/runtime-config.d.ts +0 -2
  61. package/dist/runtime-config.d.ts.map +1 -1
  62. package/dist/runtime-config.js +1 -1
  63. package/dist/runtime-config.js.map +1 -1
  64. package/dist/runtime.d.ts.map +1 -1
  65. package/dist/runtime.js +29 -30
  66. package/dist/runtime.js.map +1 -1
  67. package/dist/testing/conformance.d.ts.map +1 -1
  68. package/dist/testing/conformance.js +12 -6
  69. package/dist/testing/conformance.js.map +1 -1
  70. package/examples/README.md +13 -13
  71. package/examples/connectors/LocalModelTemplate/LocalModelTemplate.ts +138 -0
  72. package/examples/connectors/LocalModelTemplate/README.md +134 -0
  73. package/examples/connectors/McpConnectorTemplate/McpConnectorTemplate.ts +200 -0
  74. package/examples/connectors/McpConnectorTemplate/README.md +153 -0
  75. package/examples/connectors/MemoryStoreTemplate/MemoryStoreTemplate.ts +155 -0
  76. package/examples/connectors/MemoryStoreTemplate/README.md +169 -0
  77. package/examples/connectors/README.md +47 -0
  78. package/examples/connectors/SkillStoreTemplate/README.md +143 -0
  79. package/examples/connectors/SkillStoreTemplate/SkillStoreTemplate.ts +199 -0
  80. package/examples/{hello.skill.provenance.json → skillscripts/hello.skill.provenance.json} +1 -1
  81. package/package.json +1 -1
  82. package/scaffold/config.toml +8 -12
  83. package/scaffold/connectors.json +31 -3
  84. /package/examples/{classify-support-ticket.skill.md → skillscripts/classify-support-ticket.skill.md} +0 -0
  85. /package/examples/{cut-release-tag.skill.md → skillscripts/cut-release-tag.skill.md} +0 -0
  86. /package/examples/{doc-qa-with-citations.skill.md → skillscripts/doc-qa-with-citations.skill.md} +0 -0
  87. /package/examples/{feedback-sentiment-scan.skill.md → skillscripts/feedback-sentiment-scan.skill.md} +0 -0
  88. /package/examples/{hello.skill.md → skillscripts/hello.skill.md} +0 -0
  89. /package/examples/{morning-brief.skill.md → skillscripts/morning-brief.skill.md} +0 -0
  90. /package/examples/{queue-length-monitor.skill.md → skillscripts/queue-length-monitor.skill.md} +0 -0
  91. /package/examples/{service-health-watch.skill.md → skillscripts/service-health-watch.skill.md} +0 -0
  92. /package/examples/{youtrack-morning-sweep.skill.md → skillscripts/youtrack-morning-sweep.skill.md} +0 -0
@@ -0,0 +1,506 @@
1
+ import { createRequire } from "node:module";
2
+ import { dirname } from "node:path";
3
+ import { mkdirSync, existsSync } from "node:fs";
4
+ import { createHash } from "node:crypto";
5
+ import { SkillNotFoundError, VersionNotFoundError, StorageConflictError, } from "../errors.js";
6
+ import { extractStatusFromBody, stampApprovalToken } from "../approval.js";
7
+ const CONTRACT_VERSION = "1.0.0";
8
+ // Lazy-load `node:sqlite` at instance construction time, not module load.
9
+ // Vite (vitest dev pipeline) strips the `node:` prefix and fails to resolve
10
+ // plain `sqlite`; createRequire bypasses Vite entirely. Matches the pattern
11
+ // in src/connectors/memory-store.ts.
12
+ const requireNode = createRequire(import.meta.url);
13
+ function loadDatabaseSync() {
14
+ return requireNode("node:sqlite").DatabaseSync;
15
+ }
16
+ /**
17
+ * SQLite-backed SkillStore. Two-table schema:
18
+ *
19
+ * skills(name PRIMARY KEY, current_version, content_hash, status, source,
20
+ * description, metadata_json, created_at, updated_at,
21
+ * status_changed_at)
22
+ * skill_versions(name, version, content_hash, source, status,
23
+ * previous_status, changed_at, PRIMARY KEY (name, version))
24
+ *
25
+ * `skills` is the fast-path read for `load()` / `metadata()` / `query()`.
26
+ * `skill_versions` is the append-only history for `versions()`.
27
+ *
28
+ * `update_status()` wraps the UPDATE + INSERT in a transaction so the audit
29
+ * trail never logs a transition that didn't take effect. `delete()` hard-
30
+ * cascades — both tables purged. If you need recovery, back up adopter-side
31
+ * BEFORE calling delete (skill names can be reused after delete; no orphan
32
+ * history left behind).
33
+ *
34
+ * WAL is enabled at bootstrap so concurrent readers don't block a writer.
35
+ * Tag filtering uses `json_extract(metadata_json, '$.tags')` — O(n) table
36
+ * scan documented in `manifest()` features.
37
+ *
38
+ * `version` string format: first 12 chars of `content_hash`. Consumers MUST
39
+ * treat `version` as opaque (equality only) — same convention as
40
+ * FilesystemSkillStore.
41
+ *
42
+ * **Bundled default — one of three legs of the SkillStore connector model.**
43
+ * Adopters wire which leg via `connectors.json` substrate config:
44
+ * - `"filesystem"` (default) — uses FilesystemSkillStore
45
+ * - `"sqlite"` — uses this class
46
+ * - `{ type: "custom", module, export, config }` — adopter's own impl
47
+ *
48
+ * Runtime hosts (MCP server, web dashboard) honor the configured leg
49
+ * automatically. The bundled CLI authoring commands (`skillfile compile`,
50
+ * `skillfile lint`, `skillfile audit`, `skillfile list`) stay
51
+ * filesystem-pinned — they're the FS-authoring loop regardless of substrate
52
+ * config. Sqlite-backed skills are authored via the dashboard or the
53
+ * `skill_write` MCP tool.
54
+ *
55
+ * See `docs/sqlite-skill-store.md` for the forking checklist (writing your
56
+ * own adopter SkillStore impl).
57
+ */
58
+ export class SqliteSkillStore {
59
+ static staticCapabilities() {
60
+ return {
61
+ connector_type: "skill_store",
62
+ implementation: "SqliteSkillStore",
63
+ contract_version: CONTRACT_VERSION,
64
+ features: {
65
+ supports_writes: true,
66
+ supports_versioning: true,
67
+ supports_tag_filter: true,
68
+ supports_audit_trail: true,
69
+ supports_atomic_status_transitions: true,
70
+ },
71
+ };
72
+ }
73
+ db;
74
+ /**
75
+ * v0.13.0 — REGEXP support probed once at construction. `node:sqlite`
76
+ * doesn't include REGEXP by default. When unsupported, `query()` with
77
+ * `name_pattern` falls back to a JS-side filter over a full-table scan
78
+ * (no index help). Surfaced in `manifest()` so adopters notice the
79
+ * degradation; was a silent fallback before.
80
+ */
81
+ regexpSupported;
82
+ constructor(config) {
83
+ if (config.dbPath !== ":memory:") {
84
+ const dir = dirname(config.dbPath);
85
+ if (!existsSync(dir))
86
+ mkdirSync(dir, { recursive: true });
87
+ }
88
+ const DatabaseSync = loadDatabaseSync();
89
+ this.db = new DatabaseSync(config.dbPath);
90
+ this.bootstrap();
91
+ this.regexpSupported = this.probeRegexpSupport();
92
+ if (!this.regexpSupported) {
93
+ process.stderr.write(`[SqliteSkillStore] REGEXP not supported by node:sqlite build at ${config.dbPath}; ` +
94
+ `\`query({name_pattern: ...})\` will fall back to a JS-side filter over a full-table scan ` +
95
+ `(no index help). Use \`status\` / \`tag\` / \`since\` filters instead where possible.\n`);
96
+ }
97
+ }
98
+ probeRegexpSupport() {
99
+ try {
100
+ this.db.prepare(`SELECT 1 WHERE 'a' REGEXP 'a'`).get();
101
+ return true;
102
+ }
103
+ catch {
104
+ return false;
105
+ }
106
+ }
107
+ /**
108
+ * v0.13.0 — transaction helper. Wraps a synchronous block in
109
+ * BEGIN/COMMIT/ROLLBACK with the "ROLLBACK after COMMIT may itself fail"
110
+ * edge case absorbed once. Three callers (`store()`, `delete()`,
111
+ * `update_status()`) consolidate here.
112
+ */
113
+ withTransaction(fn) {
114
+ this.db.exec("BEGIN");
115
+ try {
116
+ const result = fn();
117
+ this.db.exec("COMMIT");
118
+ return result;
119
+ }
120
+ catch (err) {
121
+ // ROLLBACK after a successful COMMIT throws ("cannot rollback - no
122
+ // transaction is active") — that's a no-op for our purposes. Swallow
123
+ // the ROLLBACK error; always re-raise the original.
124
+ try {
125
+ this.db.exec("ROLLBACK");
126
+ }
127
+ catch { /* no-op */ }
128
+ throw err;
129
+ }
130
+ }
131
+ bootstrap() {
132
+ this.db.exec(`PRAGMA journal_mode = WAL;`);
133
+ this.db.exec(`
134
+ CREATE TABLE IF NOT EXISTS skills (
135
+ name TEXT PRIMARY KEY,
136
+ current_version TEXT NOT NULL,
137
+ content_hash TEXT NOT NULL,
138
+ status TEXT NOT NULL,
139
+ source TEXT NOT NULL,
140
+ description TEXT,
141
+ metadata_json TEXT,
142
+ created_at INTEGER NOT NULL,
143
+ updated_at INTEGER NOT NULL,
144
+ status_changed_at INTEGER
145
+ );
146
+ CREATE TABLE IF NOT EXISTS skill_versions (
147
+ name TEXT NOT NULL,
148
+ version TEXT NOT NULL,
149
+ content_hash TEXT NOT NULL,
150
+ source TEXT NOT NULL,
151
+ status TEXT NOT NULL,
152
+ previous_status TEXT,
153
+ changed_at INTEGER NOT NULL,
154
+ changed_by TEXT,
155
+ PRIMARY KEY (name, version)
156
+ );
157
+ CREATE INDEX IF NOT EXISTS skills_status_idx ON skills(status);
158
+ CREATE INDEX IF NOT EXISTS skills_updated_at_idx ON skills(updated_at);
159
+ CREATE INDEX IF NOT EXISTS skill_versions_name_idx ON skill_versions(name);
160
+ `);
161
+ }
162
+ async manifest() {
163
+ return {
164
+ capabilities_version: "1",
165
+ manifest: {
166
+ kind: "sqlite",
167
+ // v0.13.0 — capability flags moved to StaticCapabilities.features only.
168
+ // Manifest is substrate metadata (kind, paths, runtime context),
169
+ // NOT a duplicate capability surface.
170
+ tag_filter_note: "json_extract on metadata.tags; O(n) table scan",
171
+ // v0.13.0 — surfaces when REGEXP isn't compiled into node:sqlite
172
+ // so adopters can see the index-bypass at runtime_capabilities.
173
+ regexp_fallback_active: !this.regexpSupported,
174
+ },
175
+ };
176
+ }
177
+ async load(name, version) {
178
+ if (version !== undefined) {
179
+ const row = this.db.prepare(`SELECT name, version, content_hash, source, status FROM skill_versions
180
+ WHERE name = $name AND version = $version`).get({ $name: name, $version: version });
181
+ if (row === undefined) {
182
+ // Check if the skill exists at all to disambiguate the error.
183
+ const exists = this.db.prepare(`SELECT 1 FROM skills WHERE name = $name`).get({ $name: name });
184
+ if (exists === undefined)
185
+ throw new SkillNotFoundError(name, "SqliteSkillStore");
186
+ throw new VersionNotFoundError(name, version, "SqliteSkillStore");
187
+ }
188
+ const meta = this.metadataRowToMeta(name, this.skillRow(name));
189
+ return {
190
+ name,
191
+ version: row["version"],
192
+ content_hash: row["content_hash"],
193
+ source: row["source"],
194
+ metadata: meta,
195
+ };
196
+ }
197
+ const row = this.skillRow(name);
198
+ return {
199
+ name,
200
+ version: row["current_version"],
201
+ content_hash: row["content_hash"],
202
+ source: row["source"],
203
+ metadata: this.metadataRowToMeta(name, row),
204
+ };
205
+ }
206
+ async query(filter) {
207
+ const where = [];
208
+ const params = {};
209
+ if (filter?.status !== undefined) {
210
+ const wanted = Array.isArray(filter.status) ? filter.status : [filter.status];
211
+ const placeholders = wanted.map((_, i) => `$status${i}`).join(",");
212
+ where.push(`status IN (${placeholders})`);
213
+ wanted.forEach((s, i) => { params[`$status${i}`] = s; });
214
+ }
215
+ if (filter?.name_pattern !== undefined && this.regexpSupported) {
216
+ where.push(`name REGEXP $name_pattern`);
217
+ params["$name_pattern"] = filter.name_pattern;
218
+ }
219
+ // v0.13.0 — JS-side `name_pattern` filter applied post-query when
220
+ // REGEXP is unsupported. Proactive instead of catch-and-retry.
221
+ if (filter?.since !== undefined) {
222
+ where.push(`updated_at >= $since`);
223
+ params["$since"] = filter.since;
224
+ }
225
+ if (filter?.tag !== undefined) {
226
+ const tags = Array.isArray(filter.tag) ? filter.tag : [filter.tag];
227
+ tags.forEach((t, i) => {
228
+ // AND semantics: skill must contain every requested tag.
229
+ where.push(`EXISTS (SELECT 1 FROM json_each(json_extract(metadata_json, '$.tags')) WHERE value = $tag${i})`);
230
+ params[`$tag${i}`] = t;
231
+ });
232
+ }
233
+ if (filter?.author !== undefined) {
234
+ where.push(`json_extract(metadata_json, '$.author') = $author`);
235
+ params["$author"] = filter.author;
236
+ }
237
+ const whereSql = where.length > 0 ? `WHERE ${where.join(" AND ")}` : "";
238
+ let sql = `SELECT name, current_version, content_hash, status, source, description,
239
+ metadata_json, created_at, updated_at, status_changed_at
240
+ FROM skills ${whereSql}
241
+ ORDER BY name`;
242
+ if (filter?.limit !== undefined)
243
+ sql += ` LIMIT $limit`;
244
+ if (filter?.offset !== undefined)
245
+ sql += ` OFFSET $offset`;
246
+ if (filter?.limit !== undefined)
247
+ params["$limit"] = filter.limit;
248
+ if (filter?.offset !== undefined)
249
+ params["$offset"] = filter.offset;
250
+ let rows = this.db.prepare(sql).all(params);
251
+ // v0.13.0 — apply JS-side `name_pattern` filter when REGEXP unsupported.
252
+ // Operator was warned at construction; manifest.regexp_fallback_active
253
+ // reflects this at runtime_capabilities.
254
+ if (filter?.name_pattern !== undefined && !this.regexpSupported) {
255
+ const pat = new RegExp(filter.name_pattern);
256
+ rows = rows.filter((r) => pat.test(r["name"]));
257
+ if (filter?.offset !== undefined)
258
+ rows = rows.slice(filter.offset);
259
+ if (filter?.limit !== undefined)
260
+ rows = rows.slice(0, filter.limit);
261
+ }
262
+ return rows.map((r) => this.metadataRowToMeta(r["name"], r));
263
+ }
264
+ async metadata(name) {
265
+ const row = this.skillRow(name);
266
+ return this.metadataRowToMeta(name, row);
267
+ }
268
+ async versions(name) {
269
+ // Verify the skill exists at all so we throw rather than return [].
270
+ this.skillRow(name);
271
+ const rows = this.db.prepare(`SELECT name, version, content_hash, status, previous_status, changed_at, changed_by
272
+ FROM skill_versions WHERE name = $name ORDER BY changed_at`).all({ $name: name });
273
+ return rows.map((r) => {
274
+ const info = {
275
+ name: r["name"],
276
+ version: r["version"],
277
+ content_hash: r["content_hash"],
278
+ status: r["status"],
279
+ changed_at: r["changed_at"],
280
+ };
281
+ if (typeof r["previous_status"] === "string")
282
+ info.previous_status = r["previous_status"];
283
+ if (typeof r["changed_by"] === "string")
284
+ info.changed_by = r["changed_by"];
285
+ return info;
286
+ });
287
+ }
288
+ async store(name, source, metadata) {
289
+ if (name.length === 0) {
290
+ throw new StorageConflictError(name, "name must not be empty", "SqliteSkillStore");
291
+ }
292
+ // Auto-stamp approval token if body declares Approved without a valid
293
+ // token. Matches FilesystemSkillStore behavior so headless adopters get
294
+ // a runnable Approved state without a dashboard round-trip.
295
+ let bodyToWrite = source;
296
+ const extracted = extractStatusFromBody(source);
297
+ if (extracted !== null && extracted.status === "Approved") {
298
+ bodyToWrite = stampApprovalToken(source);
299
+ }
300
+ const content_hash = hashSource(bodyToWrite);
301
+ const version = shortHash(content_hash);
302
+ const status = metadata?.status ?? extracted?.status ?? "Draft";
303
+ const description = metadata?.description ?? extractHeader(bodyToWrite, "Description");
304
+ const nowSec = Math.floor(Date.now() / 1000);
305
+ const metaJson = serializeMetadata(metadata);
306
+ this.db.exec("BEGIN");
307
+ try {
308
+ const existing = this.db.prepare(`SELECT created_at FROM skills WHERE name = $name`).get({ $name: name });
309
+ const createdAt = existing?.created_at ?? nowSec;
310
+ this.db.prepare(`INSERT INTO skills (name, current_version, content_hash, status, source, description,
311
+ metadata_json, created_at, updated_at, status_changed_at)
312
+ VALUES ($name, $version, $hash, $status, $source, $description,
313
+ $meta, $createdAt, $updatedAt, $statusChangedAt)
314
+ ON CONFLICT(name) DO UPDATE SET
315
+ current_version = $version,
316
+ content_hash = $hash,
317
+ status = $status,
318
+ source = $source,
319
+ description = $description,
320
+ metadata_json = $meta,
321
+ updated_at = $updatedAt,
322
+ status_changed_at = $statusChangedAt`).run({
323
+ $name: name,
324
+ $version: version,
325
+ $hash: content_hash,
326
+ $status: status,
327
+ $source: bodyToWrite,
328
+ $description: description ?? null,
329
+ $meta: metaJson,
330
+ $createdAt: createdAt,
331
+ $updatedAt: nowSec,
332
+ $statusChangedAt: nowSec,
333
+ });
334
+ this.db.prepare(`INSERT INTO skill_versions (name, version, content_hash, source, status, changed_at, changed_by)
335
+ VALUES ($name, $version, $hash, $source, $status, $changedAt, $changedBy)
336
+ ON CONFLICT(name, version) DO UPDATE SET
337
+ source = $source, status = $status, changed_at = $changedAt, changed_by = $changedBy`).run({
338
+ $name: name,
339
+ $version: version,
340
+ $hash: content_hash,
341
+ $source: bodyToWrite,
342
+ $status: status,
343
+ $changedAt: nowSec,
344
+ $changedBy: metadata?.author ?? null,
345
+ });
346
+ this.db.exec("COMMIT");
347
+ }
348
+ catch (err) {
349
+ this.db.exec("ROLLBACK");
350
+ throw err;
351
+ }
352
+ const info = {
353
+ name,
354
+ version,
355
+ content_hash,
356
+ status,
357
+ changed_at: nowSec,
358
+ };
359
+ if (metadata?.author !== undefined)
360
+ info.changed_by = metadata.author;
361
+ return info;
362
+ }
363
+ async delete(name) {
364
+ const result = this.withTransaction(() => {
365
+ const r = this.db.prepare(`DELETE FROM skills WHERE name = $name`).run({ $name: name });
366
+ this.db.prepare(`DELETE FROM skill_versions WHERE name = $name`).run({ $name: name });
367
+ return r;
368
+ });
369
+ // Post-commit no-rows check — the transaction completed cleanly, but
370
+ // there was nothing to delete. Same shape as the other "not found" misses.
371
+ if (result.changes === 0)
372
+ throw new SkillNotFoundError(name, "SqliteSkillStore");
373
+ }
374
+ async update_status(name, status) {
375
+ const row = this.skillRow(name);
376
+ const previous_status = row["status"];
377
+ const source = row["source"];
378
+ // Transitions to Approved stamp the token; transitions away strip it.
379
+ const updated = status === "Approved"
380
+ ? stampApprovalToken(rewriteStatusHeader(source, "Approved"))
381
+ : rewriteStatusHeader(source, status);
382
+ const content_hash = hashSource(updated);
383
+ const version = shortHash(content_hash);
384
+ const nowSec = Math.floor(Date.now() / 1000);
385
+ this.withTransaction(() => {
386
+ this.db.prepare(`UPDATE skills SET
387
+ current_version = $version,
388
+ content_hash = $hash,
389
+ status = $status,
390
+ source = $source,
391
+ updated_at = $updatedAt,
392
+ status_changed_at = $statusChangedAt
393
+ WHERE name = $name`).run({
394
+ $name: name,
395
+ $version: version,
396
+ $hash: content_hash,
397
+ $status: status,
398
+ $source: updated,
399
+ $updatedAt: nowSec,
400
+ $statusChangedAt: nowSec,
401
+ });
402
+ this.db.prepare(`INSERT INTO skill_versions (name, version, content_hash, source, status, previous_status, changed_at)
403
+ VALUES ($name, $version, $hash, $source, $status, $previous, $changedAt)
404
+ ON CONFLICT(name, version) DO UPDATE SET
405
+ status = $status, previous_status = $previous, changed_at = $changedAt`).run({
406
+ $name: name,
407
+ $version: version,
408
+ $hash: content_hash,
409
+ $source: updated,
410
+ $status: status,
411
+ $previous: previous_status,
412
+ $changedAt: nowSec,
413
+ });
414
+ });
415
+ return {
416
+ name,
417
+ version,
418
+ content_hash,
419
+ status,
420
+ previous_status,
421
+ changed_at: nowSec,
422
+ };
423
+ }
424
+ close() {
425
+ this.db.close();
426
+ }
427
+ /**
428
+ * v0.13.0 — Throws `SkillNotFoundError` on miss. Cannot distinguish
429
+ * "never existed" from "deleted between calls" — hard-cascade `delete()`
430
+ * removes the skill row + all skill_versions, so the substrate has no
431
+ * evidence either way. Callers needing that distinction must track
432
+ * delete events themselves (e.g., watch their own `delete()` calls) or
433
+ * switch to soft-delete (tombstone via `update_status("Disabled")`).
434
+ */
435
+ skillRow(name) {
436
+ const row = this.db.prepare(`SELECT name, current_version, content_hash, status, source, description,
437
+ metadata_json, created_at, updated_at, status_changed_at
438
+ FROM skills WHERE name = $name`).get({ $name: name });
439
+ if (row === undefined)
440
+ throw new SkillNotFoundError(name, "SqliteSkillStore");
441
+ return row;
442
+ }
443
+ metadataRowToMeta(name, row) {
444
+ const meta = {
445
+ name,
446
+ version: row["current_version"],
447
+ content_hash: row["content_hash"],
448
+ status: row["status"],
449
+ created_at: row["created_at"],
450
+ updated_at: row["updated_at"],
451
+ };
452
+ if (typeof row["description"] === "string")
453
+ meta.description = row["description"];
454
+ if (typeof row["status_changed_at"] === "number")
455
+ meta.status_changed_at = row["status_changed_at"];
456
+ if (typeof row["metadata_json"] === "string") {
457
+ const parsed = safeParseJson(row["metadata_json"]);
458
+ if (parsed !== null && typeof parsed === "object") {
459
+ const bag = parsed;
460
+ if (typeof bag["author"] === "string")
461
+ meta.author = bag["author"];
462
+ if (Object.keys(bag).length > 0)
463
+ meta.metadata_bag = bag;
464
+ }
465
+ }
466
+ return meta;
467
+ }
468
+ }
469
+ function hashSource(source) {
470
+ return createHash("sha256").update(source, "utf8").digest("hex");
471
+ }
472
+ function shortHash(content_hash) {
473
+ return content_hash.slice(0, 12);
474
+ }
475
+ function extractHeader(body, key) {
476
+ const re = new RegExp(`^#\\s*${key}\\s*:\\s*(.+?)\\s*$`, "m");
477
+ const m = re.exec(body);
478
+ return m ? m[1] : null;
479
+ }
480
+ function rewriteStatusHeader(source, status) {
481
+ const line = `# Status: ${status}`;
482
+ const re = /^#\s*Status\s*:\s*.+?\s*$/m;
483
+ if (re.test(source))
484
+ return source.replace(re, line);
485
+ const skillLineRe = /^(#\s*Skill\s*:\s*.+?)\s*$/m;
486
+ if (skillLineRe.test(source))
487
+ return source.replace(skillLineRe, `$1\n${line}`);
488
+ return `${line}\n${source}`;
489
+ }
490
+ function serializeMetadata(metadata) {
491
+ if (metadata === undefined)
492
+ return null;
493
+ const bag = { ...(metadata.metadata_bag ?? {}) };
494
+ if (metadata.author !== undefined)
495
+ bag["author"] = metadata.author;
496
+ return Object.keys(bag).length > 0 ? JSON.stringify(bag) : null;
497
+ }
498
+ function safeParseJson(s) {
499
+ try {
500
+ return JSON.parse(s);
501
+ }
502
+ catch {
503
+ return null;
504
+ }
505
+ }
506
+ //# sourceMappingURL=sqlite-skill-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-skill-store.js","sourceRoot":"","sources":["../../src/connectors/sqlite-skill-store.ts"],"names":[],"mappings":"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"}
@@ -1,26 +1,102 @@
1
1
  /** The five connector kinds. */
2
2
  export type ConnectorType = "skill_store" | "memory_store" | "local_model" | "mcp_connector" | "agent_connector";
3
+ export type SkillStoreFeature = "supports_writes" | "supports_versioning" | "supports_tag_filter" | "supports_audit_trail" | "supports_atomic_status_transitions";
4
+ export type MemoryStoreFeature = "supports_writes" | "supports_tag_filter" | "supports_semantic" | "supports_rerank" | "supports_thread_status_filter" | "supports_pinning" | "supports_decay_model";
5
+ export type LocalModelFeature = "supports_max_tokens" | "supports_timeout" | "supports_streaming" | "supports_embedding";
6
+ export type McpConnectorFeature = "supports_identity_propagation" | "supports_streaming_responses" | "supports_batch";
7
+ /** AgentConnector flags are method-presence shape (one per contract method). */
8
+ export type AgentConnectorFeature = "deliver" | "wake" | "list_agents" | "agent_status" | "health_check" | "request_response";
3
9
  /**
4
10
  * Static capabilities — declared by the connector class, consumed by the
5
- * linter offline. `features` is a string→boolean map of feature flags;
6
- * skill `# Requires:` clauses match against the names. See per-contract
7
- * feature-flag namespaces below.
11
+ * linter offline. Discriminated union per `connector_type`; per-kind
12
+ * feature unions enforce closed-set flag names at compile time. `# Requires:`
13
+ * lint clauses match against `<connector_type>.<flag>`.
8
14
  */
9
- export interface StaticCapabilities {
10
- connector_type: ConnectorType;
15
+ interface BaseStaticCapabilities {
11
16
  /** Implementation class name; appears in conformance test output + dashboard. */
12
17
  implementation: string;
13
18
  /** Contract version this implementation targets (e.g. "1.0.0"). Lets the runtime refuse incompatible impls. */
14
19
  contract_version: string;
15
- features: Record<string, boolean>;
16
20
  }
21
+ export interface SkillStoreCapabilities extends BaseStaticCapabilities {
22
+ connector_type: "skill_store";
23
+ features: Partial<Record<SkillStoreFeature, boolean>>;
24
+ }
25
+ export interface MemoryStoreCapabilities extends BaseStaticCapabilities {
26
+ connector_type: "memory_store";
27
+ features: Partial<Record<MemoryStoreFeature, boolean>>;
28
+ }
29
+ export interface LocalModelCapabilities extends BaseStaticCapabilities {
30
+ connector_type: "local_model";
31
+ features: Partial<Record<LocalModelFeature, boolean>>;
32
+ }
33
+ export interface McpConnectorCapabilities extends BaseStaticCapabilities {
34
+ connector_type: "mcp_connector";
35
+ features: Partial<Record<McpConnectorFeature, boolean>>;
36
+ }
37
+ export interface AgentConnectorCapabilities extends BaseStaticCapabilities {
38
+ connector_type: "agent_connector";
39
+ features: Partial<Record<AgentConnectorFeature, boolean>>;
40
+ }
41
+ export type StaticCapabilities = SkillStoreCapabilities | MemoryStoreCapabilities | LocalModelCapabilities | McpConnectorCapabilities | AgentConnectorCapabilities;
42
+ export interface SkillStoreManifest {
43
+ kind: string;
44
+ /** Filesystem-backed impls — root directory for `.skill.md` files. */
45
+ root_dir?: string;
46
+ /** SQLite-backed impls — db file path. */
47
+ db_path?: string;
48
+ /** Adopter-extension catch-all. */
49
+ [key: string]: unknown;
50
+ }
51
+ export interface MemoryStoreManifest {
52
+ kind: string;
53
+ /** Query modes the substrate supports — e.g., ["fts"], ["semantic", "rerank"]. */
54
+ supported_modes?: string[];
55
+ /** Filter fields the substrate honors in `query()`. */
56
+ supported_filters?: string[];
57
+ /** Score range hint — e.g., "unbounded", "0..1". */
58
+ score_range?: string;
59
+ [key: string]: unknown;
60
+ }
61
+ export interface LocalModelManifest {
62
+ kind: string;
63
+ /** Default model tag (e.g., "gemma2:9b"). */
64
+ default_model?: string;
65
+ /** Endpoint URL the impl connects to. */
66
+ endpoint?: string;
67
+ /** Available model list. Populated when the impl can introspect the substrate (e.g., `/api/tags` for Ollama). Absent on impls that don't enumerate. */
68
+ models_available?: string[];
69
+ /**
70
+ * Set when the substrate query that would populate `models_available`
71
+ * failed (network error, auth failure, parse error, etc.). Cold authors
72
+ * + adopters see this and know why the model list is empty, rather than
73
+ * silently getting `models_available: []` and assuming no models are
74
+ * installed. v0.13.0.
75
+ */
76
+ fetch_error?: string;
77
+ [key: string]: unknown;
78
+ }
79
+ export interface McpConnectorManifest {
80
+ kind: string;
81
+ /** Spawned command for child-process bridges. */
82
+ command?: string;
83
+ /** Stdio framing convention for child-process bridges. */
84
+ framing?: string;
85
+ /** Tools available — populated for bridges that introspect upstream MCPs at startup. */
86
+ tools_available?: string[];
87
+ /** For bridge connectors that wrap an underlying contract — the inner manifest. */
88
+ wraps?: Record<string, unknown>;
89
+ [key: string]: unknown;
90
+ }
91
+ type ManifestPayload<K extends ConnectorType> = K extends "skill_store" ? SkillStoreManifest : K extends "memory_store" ? MemoryStoreManifest : K extends "local_model" ? LocalModelManifest : K extends "mcp_connector" ? McpConnectorManifest : never;
17
92
  /**
18
93
  * Dynamic manifest — instance state. Runtime caches per `capabilities_version`;
19
- * connectors bump version on schema/structural changes only.
94
+ * connectors bump version on schema/structural changes only. Parameterized
95
+ * by connector kind; default is the open union for code that doesn't care.
20
96
  */
21
- export interface ManifestInfo {
97
+ export interface ManifestInfo<K extends Exclude<ConnectorType, "agent_connector"> = Exclude<ConnectorType, "agent_connector">> {
22
98
  capabilities_version: string;
23
- manifest: Record<string, unknown>;
99
+ manifest: ManifestPayload<K>;
24
100
  }
25
101
  export type SkillStatus = "Draft" | "Approved" | "Disabled";
26
102
  /**
@@ -307,4 +383,5 @@ export interface McpConnectorClass {
307
383
  /** Eleven curated substrate fields. Connectors route equivalents here at top level; everything else flows into metadata. */
308
384
  export declare const CURATED_MEMORY_FIELDS: readonly ["thread_status", "pinned", "confidence", "domain_tags", "payload_type", "knowledge_type", "recipients", "expires_at", "created_at", "agent_id", "vault"];
309
385
  export type CuratedMemoryField = (typeof CURATED_MEMORY_FIELDS)[number];
386
+ export {};
310
387
  //# sourceMappingURL=types.d.ts.map