@soleri/core 2.4.0 → 2.6.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 (328) hide show
  1. package/dist/brain/brain.d.ts +7 -0
  2. package/dist/brain/brain.d.ts.map +1 -1
  3. package/dist/brain/brain.js +56 -9
  4. package/dist/brain/brain.js.map +1 -1
  5. package/dist/brain/intelligence.d.ts +1 -0
  6. package/dist/brain/intelligence.d.ts.map +1 -1
  7. package/dist/brain/intelligence.js +164 -148
  8. package/dist/brain/intelligence.js.map +1 -1
  9. package/dist/brain/types.d.ts +2 -2
  10. package/dist/brain/types.d.ts.map +1 -1
  11. package/dist/cognee/client.d.ts +3 -0
  12. package/dist/cognee/client.d.ts.map +1 -1
  13. package/dist/cognee/client.js +17 -0
  14. package/dist/cognee/client.js.map +1 -1
  15. package/dist/cognee/sync-manager.d.ts +94 -0
  16. package/dist/cognee/sync-manager.d.ts.map +1 -0
  17. package/dist/cognee/sync-manager.js +293 -0
  18. package/dist/cognee/sync-manager.js.map +1 -0
  19. package/dist/control/identity-manager.d.ts +3 -1
  20. package/dist/control/identity-manager.d.ts.map +1 -1
  21. package/dist/control/identity-manager.js +49 -51
  22. package/dist/control/identity-manager.js.map +1 -1
  23. package/dist/control/intent-router.d.ts +1 -0
  24. package/dist/control/intent-router.d.ts.map +1 -1
  25. package/dist/control/intent-router.js +32 -32
  26. package/dist/control/intent-router.js.map +1 -1
  27. package/dist/curator/curator.d.ts +9 -1
  28. package/dist/curator/curator.d.ts.map +1 -1
  29. package/dist/curator/curator.js +104 -92
  30. package/dist/curator/curator.js.map +1 -1
  31. package/dist/errors/classify.d.ts +13 -0
  32. package/dist/errors/classify.d.ts.map +1 -0
  33. package/dist/errors/classify.js +97 -0
  34. package/dist/errors/classify.js.map +1 -0
  35. package/dist/errors/index.d.ts +6 -0
  36. package/dist/errors/index.d.ts.map +1 -0
  37. package/dist/errors/index.js +4 -0
  38. package/dist/errors/index.js.map +1 -0
  39. package/dist/errors/retry.d.ts +40 -0
  40. package/dist/errors/retry.d.ts.map +1 -0
  41. package/dist/errors/retry.js +97 -0
  42. package/dist/errors/retry.js.map +1 -0
  43. package/dist/errors/types.d.ts +48 -0
  44. package/dist/errors/types.d.ts.map +1 -0
  45. package/dist/errors/types.js +59 -0
  46. package/dist/errors/types.js.map +1 -0
  47. package/dist/governance/governance.d.ts +1 -0
  48. package/dist/governance/governance.d.ts.map +1 -1
  49. package/dist/governance/governance.js +51 -68
  50. package/dist/governance/governance.js.map +1 -1
  51. package/dist/index.d.ts +26 -5
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +22 -3
  54. package/dist/index.js.map +1 -1
  55. package/dist/intake/content-classifier.d.ts +14 -0
  56. package/dist/intake/content-classifier.d.ts.map +1 -0
  57. package/dist/intake/content-classifier.js +125 -0
  58. package/dist/intake/content-classifier.js.map +1 -0
  59. package/dist/intake/dedup-gate.d.ts +17 -0
  60. package/dist/intake/dedup-gate.d.ts.map +1 -0
  61. package/dist/intake/dedup-gate.js +66 -0
  62. package/dist/intake/dedup-gate.js.map +1 -0
  63. package/dist/intake/intake-pipeline.d.ts +63 -0
  64. package/dist/intake/intake-pipeline.d.ts.map +1 -0
  65. package/dist/intake/intake-pipeline.js +373 -0
  66. package/dist/intake/intake-pipeline.js.map +1 -0
  67. package/dist/intake/types.d.ts +65 -0
  68. package/dist/intake/types.d.ts.map +1 -0
  69. package/dist/intake/types.js +3 -0
  70. package/dist/intake/types.js.map +1 -0
  71. package/dist/intelligence/loader.js +1 -1
  72. package/dist/intelligence/loader.js.map +1 -1
  73. package/dist/intelligence/types.d.ts +3 -1
  74. package/dist/intelligence/types.d.ts.map +1 -1
  75. package/dist/loop/loop-manager.d.ts +58 -7
  76. package/dist/loop/loop-manager.d.ts.map +1 -1
  77. package/dist/loop/loop-manager.js +280 -6
  78. package/dist/loop/loop-manager.js.map +1 -1
  79. package/dist/loop/types.d.ts +69 -1
  80. package/dist/loop/types.d.ts.map +1 -1
  81. package/dist/loop/types.js +4 -1
  82. package/dist/loop/types.js.map +1 -1
  83. package/dist/persistence/index.d.ts +4 -0
  84. package/dist/persistence/index.d.ts.map +1 -0
  85. package/dist/persistence/index.js +3 -0
  86. package/dist/persistence/index.js.map +1 -0
  87. package/dist/persistence/postgres-provider.d.ts +46 -0
  88. package/dist/persistence/postgres-provider.d.ts.map +1 -0
  89. package/dist/persistence/postgres-provider.js +115 -0
  90. package/dist/persistence/postgres-provider.js.map +1 -0
  91. package/dist/persistence/sqlite-provider.d.ts +28 -0
  92. package/dist/persistence/sqlite-provider.d.ts.map +1 -0
  93. package/dist/persistence/sqlite-provider.js +97 -0
  94. package/dist/persistence/sqlite-provider.js.map +1 -0
  95. package/dist/persistence/types.d.ts +58 -0
  96. package/dist/persistence/types.d.ts.map +1 -0
  97. package/dist/persistence/types.js +8 -0
  98. package/dist/persistence/types.js.map +1 -0
  99. package/dist/planning/gap-analysis.d.ts +47 -4
  100. package/dist/planning/gap-analysis.d.ts.map +1 -1
  101. package/dist/planning/gap-analysis.js +190 -13
  102. package/dist/planning/gap-analysis.js.map +1 -1
  103. package/dist/planning/gap-types.d.ts +1 -1
  104. package/dist/planning/gap-types.d.ts.map +1 -1
  105. package/dist/planning/gap-types.js.map +1 -1
  106. package/dist/planning/planner.d.ts +277 -9
  107. package/dist/planning/planner.d.ts.map +1 -1
  108. package/dist/planning/planner.js +611 -46
  109. package/dist/planning/planner.js.map +1 -1
  110. package/dist/playbooks/generic/brainstorming.d.ts +9 -0
  111. package/dist/playbooks/generic/brainstorming.d.ts.map +1 -0
  112. package/dist/playbooks/generic/brainstorming.js +105 -0
  113. package/dist/playbooks/generic/brainstorming.js.map +1 -0
  114. package/dist/playbooks/generic/code-review.d.ts +11 -0
  115. package/dist/playbooks/generic/code-review.d.ts.map +1 -0
  116. package/dist/playbooks/generic/code-review.js +176 -0
  117. package/dist/playbooks/generic/code-review.js.map +1 -0
  118. package/dist/playbooks/generic/subagent-execution.d.ts +9 -0
  119. package/dist/playbooks/generic/subagent-execution.d.ts.map +1 -0
  120. package/dist/playbooks/generic/subagent-execution.js +68 -0
  121. package/dist/playbooks/generic/subagent-execution.js.map +1 -0
  122. package/dist/playbooks/generic/systematic-debugging.d.ts +9 -0
  123. package/dist/playbooks/generic/systematic-debugging.d.ts.map +1 -0
  124. package/dist/playbooks/generic/systematic-debugging.js +87 -0
  125. package/dist/playbooks/generic/systematic-debugging.js.map +1 -0
  126. package/dist/playbooks/generic/tdd.d.ts +9 -0
  127. package/dist/playbooks/generic/tdd.d.ts.map +1 -0
  128. package/dist/playbooks/generic/tdd.js +70 -0
  129. package/dist/playbooks/generic/tdd.js.map +1 -0
  130. package/dist/playbooks/generic/verification.d.ts +9 -0
  131. package/dist/playbooks/generic/verification.d.ts.map +1 -0
  132. package/dist/playbooks/generic/verification.js +74 -0
  133. package/dist/playbooks/generic/verification.js.map +1 -0
  134. package/dist/playbooks/index.d.ts +4 -0
  135. package/dist/playbooks/index.d.ts.map +1 -0
  136. package/dist/playbooks/index.js +5 -0
  137. package/dist/playbooks/index.js.map +1 -0
  138. package/dist/playbooks/playbook-registry.d.ts +42 -0
  139. package/dist/playbooks/playbook-registry.d.ts.map +1 -0
  140. package/dist/playbooks/playbook-registry.js +227 -0
  141. package/dist/playbooks/playbook-registry.js.map +1 -0
  142. package/dist/playbooks/playbook-seeder.d.ts +47 -0
  143. package/dist/playbooks/playbook-seeder.d.ts.map +1 -0
  144. package/dist/playbooks/playbook-seeder.js +104 -0
  145. package/dist/playbooks/playbook-seeder.js.map +1 -0
  146. package/dist/playbooks/playbook-types.d.ts +132 -0
  147. package/dist/playbooks/playbook-types.d.ts.map +1 -0
  148. package/dist/playbooks/playbook-types.js +12 -0
  149. package/dist/playbooks/playbook-types.js.map +1 -0
  150. package/dist/project/project-registry.d.ts +4 -4
  151. package/dist/project/project-registry.d.ts.map +1 -1
  152. package/dist/project/project-registry.js +30 -57
  153. package/dist/project/project-registry.js.map +1 -1
  154. package/dist/prompts/index.d.ts +4 -0
  155. package/dist/prompts/index.d.ts.map +1 -0
  156. package/dist/prompts/index.js +3 -0
  157. package/dist/prompts/index.js.map +1 -0
  158. package/dist/prompts/parser.d.ts +17 -0
  159. package/dist/prompts/parser.d.ts.map +1 -0
  160. package/dist/prompts/parser.js +47 -0
  161. package/dist/prompts/parser.js.map +1 -0
  162. package/dist/prompts/template-manager.d.ts +25 -0
  163. package/dist/prompts/template-manager.d.ts.map +1 -0
  164. package/dist/prompts/template-manager.js +71 -0
  165. package/dist/prompts/template-manager.js.map +1 -0
  166. package/dist/prompts/types.d.ts +26 -0
  167. package/dist/prompts/types.d.ts.map +1 -0
  168. package/dist/prompts/types.js +5 -0
  169. package/dist/prompts/types.js.map +1 -0
  170. package/dist/runtime/admin-extra-ops.d.ts +5 -3
  171. package/dist/runtime/admin-extra-ops.d.ts.map +1 -1
  172. package/dist/runtime/admin-extra-ops.js +348 -11
  173. package/dist/runtime/admin-extra-ops.js.map +1 -1
  174. package/dist/runtime/admin-ops.d.ts.map +1 -1
  175. package/dist/runtime/admin-ops.js +10 -3
  176. package/dist/runtime/admin-ops.js.map +1 -1
  177. package/dist/runtime/capture-ops.d.ts.map +1 -1
  178. package/dist/runtime/capture-ops.js +20 -2
  179. package/dist/runtime/capture-ops.js.map +1 -1
  180. package/dist/runtime/cognee-sync-ops.d.ts +12 -0
  181. package/dist/runtime/cognee-sync-ops.d.ts.map +1 -0
  182. package/dist/runtime/cognee-sync-ops.js +55 -0
  183. package/dist/runtime/cognee-sync-ops.js.map +1 -0
  184. package/dist/runtime/core-ops.d.ts +8 -6
  185. package/dist/runtime/core-ops.d.ts.map +1 -1
  186. package/dist/runtime/core-ops.js +226 -9
  187. package/dist/runtime/core-ops.js.map +1 -1
  188. package/dist/runtime/curator-extra-ops.d.ts +2 -2
  189. package/dist/runtime/curator-extra-ops.d.ts.map +1 -1
  190. package/dist/runtime/curator-extra-ops.js +15 -3
  191. package/dist/runtime/curator-extra-ops.js.map +1 -1
  192. package/dist/runtime/domain-ops.js +2 -2
  193. package/dist/runtime/domain-ops.js.map +1 -1
  194. package/dist/runtime/grading-ops.d.ts.map +1 -1
  195. package/dist/runtime/grading-ops.js.map +1 -1
  196. package/dist/runtime/intake-ops.d.ts +14 -0
  197. package/dist/runtime/intake-ops.d.ts.map +1 -0
  198. package/dist/runtime/intake-ops.js +110 -0
  199. package/dist/runtime/intake-ops.js.map +1 -0
  200. package/dist/runtime/loop-ops.d.ts +5 -4
  201. package/dist/runtime/loop-ops.d.ts.map +1 -1
  202. package/dist/runtime/loop-ops.js +84 -12
  203. package/dist/runtime/loop-ops.js.map +1 -1
  204. package/dist/runtime/memory-cross-project-ops.d.ts.map +1 -1
  205. package/dist/runtime/memory-cross-project-ops.js.map +1 -1
  206. package/dist/runtime/memory-extra-ops.js +5 -5
  207. package/dist/runtime/memory-extra-ops.js.map +1 -1
  208. package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
  209. package/dist/runtime/orchestrate-ops.js +8 -2
  210. package/dist/runtime/orchestrate-ops.js.map +1 -1
  211. package/dist/runtime/planning-extra-ops.d.ts +13 -5
  212. package/dist/runtime/planning-extra-ops.d.ts.map +1 -1
  213. package/dist/runtime/planning-extra-ops.js +381 -18
  214. package/dist/runtime/planning-extra-ops.js.map +1 -1
  215. package/dist/runtime/playbook-ops.d.ts +14 -0
  216. package/dist/runtime/playbook-ops.d.ts.map +1 -0
  217. package/dist/runtime/playbook-ops.js +141 -0
  218. package/dist/runtime/playbook-ops.js.map +1 -0
  219. package/dist/runtime/project-ops.d.ts.map +1 -1
  220. package/dist/runtime/project-ops.js +7 -2
  221. package/dist/runtime/project-ops.js.map +1 -1
  222. package/dist/runtime/runtime.d.ts.map +1 -1
  223. package/dist/runtime/runtime.js +28 -9
  224. package/dist/runtime/runtime.js.map +1 -1
  225. package/dist/runtime/types.d.ts +8 -0
  226. package/dist/runtime/types.d.ts.map +1 -1
  227. package/dist/runtime/vault-extra-ops.d.ts +4 -2
  228. package/dist/runtime/vault-extra-ops.d.ts.map +1 -1
  229. package/dist/runtime/vault-extra-ops.js +383 -4
  230. package/dist/runtime/vault-extra-ops.js.map +1 -1
  231. package/dist/vault/playbook.d.ts +34 -0
  232. package/dist/vault/playbook.d.ts.map +1 -0
  233. package/dist/vault/playbook.js +60 -0
  234. package/dist/vault/playbook.js.map +1 -0
  235. package/dist/vault/vault.d.ts +52 -32
  236. package/dist/vault/vault.d.ts.map +1 -1
  237. package/dist/vault/vault.js +300 -181
  238. package/dist/vault/vault.js.map +1 -1
  239. package/package.json +9 -3
  240. package/src/__tests__/admin-extra-ops.test.ts +62 -15
  241. package/src/__tests__/admin-ops.test.ts +2 -2
  242. package/src/__tests__/brain.test.ts +3 -3
  243. package/src/__tests__/cognee-integration.test.ts +80 -0
  244. package/src/__tests__/cognee-sync-manager.test.ts +103 -0
  245. package/src/__tests__/core-ops.test.ts +36 -4
  246. package/src/__tests__/curator-extra-ops.test.ts +24 -2
  247. package/src/__tests__/errors.test.ts +388 -0
  248. package/src/__tests__/grading-ops.test.ts +28 -7
  249. package/src/__tests__/intake-pipeline.test.ts +162 -0
  250. package/src/__tests__/loop-ops.test.ts +74 -3
  251. package/src/__tests__/memory-cross-project-ops.test.ts +3 -1
  252. package/src/__tests__/orchestrate-ops.test.ts +8 -3
  253. package/src/__tests__/persistence.test.ts +291 -0
  254. package/src/__tests__/planner.test.ts +99 -21
  255. package/src/__tests__/planning-extra-ops.test.ts +168 -10
  256. package/src/__tests__/playbook-registry.test.ts +326 -0
  257. package/src/__tests__/playbook-seeder.test.ts +163 -0
  258. package/src/__tests__/playbook.test.ts +389 -0
  259. package/src/__tests__/postgres-provider.test.ts +58 -0
  260. package/src/__tests__/project-ops.test.ts +18 -4
  261. package/src/__tests__/template-manager.test.ts +222 -0
  262. package/src/__tests__/vault-extra-ops.test.ts +82 -7
  263. package/src/__tests__/vault.test.ts +184 -0
  264. package/src/brain/brain.ts +71 -9
  265. package/src/brain/intelligence.ts +258 -307
  266. package/src/brain/types.ts +2 -2
  267. package/src/cognee/client.ts +18 -0
  268. package/src/cognee/sync-manager.ts +389 -0
  269. package/src/control/identity-manager.ts +77 -75
  270. package/src/control/intent-router.ts +55 -57
  271. package/src/curator/curator.ts +199 -139
  272. package/src/errors/classify.ts +102 -0
  273. package/src/errors/index.ts +5 -0
  274. package/src/errors/retry.ts +132 -0
  275. package/src/errors/types.ts +81 -0
  276. package/src/governance/governance.ts +90 -107
  277. package/src/index.ts +116 -3
  278. package/src/intake/content-classifier.ts +146 -0
  279. package/src/intake/dedup-gate.ts +92 -0
  280. package/src/intake/intake-pipeline.ts +503 -0
  281. package/src/intake/types.ts +69 -0
  282. package/src/intelligence/loader.ts +1 -1
  283. package/src/intelligence/types.ts +3 -1
  284. package/src/loop/loop-manager.ts +325 -7
  285. package/src/loop/types.ts +72 -1
  286. package/src/persistence/index.ts +9 -0
  287. package/src/persistence/postgres-provider.ts +157 -0
  288. package/src/persistence/sqlite-provider.ts +115 -0
  289. package/src/persistence/types.ts +74 -0
  290. package/src/planning/gap-analysis.ts +286 -17
  291. package/src/planning/gap-types.ts +4 -1
  292. package/src/planning/planner.ts +828 -55
  293. package/src/playbooks/generic/brainstorming.ts +110 -0
  294. package/src/playbooks/generic/code-review.ts +181 -0
  295. package/src/playbooks/generic/subagent-execution.ts +74 -0
  296. package/src/playbooks/generic/systematic-debugging.ts +92 -0
  297. package/src/playbooks/generic/tdd.ts +75 -0
  298. package/src/playbooks/generic/verification.ts +79 -0
  299. package/src/playbooks/index.ts +27 -0
  300. package/src/playbooks/playbook-registry.ts +284 -0
  301. package/src/playbooks/playbook-seeder.ts +119 -0
  302. package/src/playbooks/playbook-types.ts +162 -0
  303. package/src/project/project-registry.ts +81 -74
  304. package/src/prompts/index.ts +3 -0
  305. package/src/prompts/parser.ts +59 -0
  306. package/src/prompts/template-manager.ts +77 -0
  307. package/src/prompts/types.ts +28 -0
  308. package/src/runtime/admin-extra-ops.ts +391 -13
  309. package/src/runtime/admin-ops.ts +17 -6
  310. package/src/runtime/capture-ops.ts +25 -6
  311. package/src/runtime/cognee-sync-ops.ts +63 -0
  312. package/src/runtime/core-ops.ts +258 -8
  313. package/src/runtime/curator-extra-ops.ts +17 -3
  314. package/src/runtime/domain-ops.ts +2 -2
  315. package/src/runtime/grading-ops.ts +11 -2
  316. package/src/runtime/intake-ops.ts +126 -0
  317. package/src/runtime/loop-ops.ts +96 -13
  318. package/src/runtime/memory-cross-project-ops.ts +1 -2
  319. package/src/runtime/memory-extra-ops.ts +5 -5
  320. package/src/runtime/orchestrate-ops.ts +8 -2
  321. package/src/runtime/planning-extra-ops.ts +414 -23
  322. package/src/runtime/playbook-ops.ts +169 -0
  323. package/src/runtime/project-ops.ts +9 -3
  324. package/src/runtime/runtime.ts +36 -10
  325. package/src/runtime/types.ts +8 -0
  326. package/src/runtime/vault-extra-ops.ts +425 -4
  327. package/src/vault/playbook.ts +87 -0
  328. package/src/vault/vault.ts +419 -235
@@ -2,11 +2,11 @@
2
2
  * Project Registry — SQLite-backed registry for tracking projects,
3
3
  * rules, and cross-project links.
4
4
  *
5
- * Uses the Vault's underlying SQLite database via `vault.getDb()`.
5
+ * Uses the Vault's underlying database via PersistenceProvider.
6
6
  * Tables are created lazily on first access.
7
7
  */
8
8
 
9
- import type Database from 'better-sqlite3';
9
+ import type { PersistenceProvider } from '../persistence/types.js';
10
10
  import type { RegisteredProject, ProjectRule, ProjectLink, LinkType } from './types.js';
11
11
 
12
12
  /** Row shape for the projects table. */
@@ -42,7 +42,11 @@ interface LinkRow {
42
42
  * Generate a deterministic project ID from a filesystem path.
43
43
  */
44
44
  function pathToId(path: string): string {
45
- return path.replace(/[^a-z0-9]/gi, '-').toLowerCase().replace(/-+/g, '-').replace(/^-|-$/g, '');
45
+ return path
46
+ .replace(/[^a-z0-9]/gi, '-')
47
+ .toLowerCase()
48
+ .replace(/-+/g, '-')
49
+ .replace(/^-|-$/g, '');
46
50
  }
47
51
 
48
52
  function rowToProject(row: ProjectRow): RegisteredProject {
@@ -78,15 +82,15 @@ function rowToLink(row: LinkRow): ProjectLink {
78
82
  }
79
83
 
80
84
  export class ProjectRegistry {
81
- private db: Database.Database;
85
+ private provider: PersistenceProvider;
82
86
 
83
- constructor(db: Database.Database) {
84
- this.db = db;
87
+ constructor(provider: PersistenceProvider) {
88
+ this.provider = provider;
85
89
  this.initTables();
86
90
  }
87
91
 
88
92
  private initTables(): void {
89
- this.db.exec(`
93
+ this.provider.execSql(`
90
94
  CREATE TABLE IF NOT EXISTS registered_projects (
91
95
  id TEXT PRIMARY KEY,
92
96
  path TEXT UNIQUE NOT NULL,
@@ -124,17 +128,19 @@ export class ProjectRegistry {
124
128
  const id = pathToId(path);
125
129
  const now = Date.now();
126
130
 
127
- const existing = this.db
128
- .prepare('SELECT * FROM registered_projects WHERE id = ?')
129
- .get(id) as ProjectRow | undefined;
131
+ const existing = this.provider.get<ProjectRow>(
132
+ 'SELECT * FROM registered_projects WHERE id = ?',
133
+ [id],
134
+ );
130
135
 
131
136
  if (existing) {
132
137
  // Update lastAccessedAt, and optionally name/metadata if provided
133
138
  const newName = name ?? existing.name;
134
139
  const newMetadata = metadata ? JSON.stringify(metadata) : existing.metadata;
135
- this.db
136
- .prepare('UPDATE registered_projects SET last_accessed_at = ?, name = ?, metadata = ? WHERE id = ?')
137
- .run(now, newName, newMetadata, id);
140
+ this.provider.run(
141
+ 'UPDATE registered_projects SET last_accessed_at = ?, name = ?, metadata = ? WHERE id = ?',
142
+ [now, newName, newMetadata, id],
143
+ );
138
144
  return rowToProject({
139
145
  ...existing,
140
146
  last_accessed_at: now,
@@ -151,11 +157,10 @@ export class ProjectRegistry {
151
157
  last_accessed_at: now,
152
158
  metadata: JSON.stringify(metadata ?? {}),
153
159
  };
154
- this.db
155
- .prepare(
156
- 'INSERT INTO registered_projects (id, path, name, registered_at, last_accessed_at, metadata) VALUES (?, ?, ?, ?, ?, ?)',
157
- )
158
- .run(row.id, row.path, row.name, row.registered_at, row.last_accessed_at, row.metadata);
160
+ this.provider.run(
161
+ 'INSERT INTO registered_projects (id, path, name, registered_at, last_accessed_at, metadata) VALUES (?, ?, ?, ?, ?, ?)',
162
+ [row.id, row.path, row.name, row.registered_at, row.last_accessed_at, row.metadata],
163
+ );
159
164
 
160
165
  return rowToProject(row);
161
166
  }
@@ -164,9 +169,9 @@ export class ProjectRegistry {
164
169
  * Get a project by ID.
165
170
  */
166
171
  get(projectId: string): RegisteredProject | null {
167
- const row = this.db
168
- .prepare('SELECT * FROM registered_projects WHERE id = ?')
169
- .get(projectId) as ProjectRow | undefined;
172
+ const row = this.provider.get<ProjectRow>('SELECT * FROM registered_projects WHERE id = ?', [
173
+ projectId,
174
+ ]);
170
175
  return row ? rowToProject(row) : null;
171
176
  }
172
177
 
@@ -174,9 +179,9 @@ export class ProjectRegistry {
174
179
  * Get a project by its filesystem path.
175
180
  */
176
181
  getByPath(path: string): RegisteredProject | null {
177
- const row = this.db
178
- .prepare('SELECT * FROM registered_projects WHERE path = ?')
179
- .get(path) as ProjectRow | undefined;
182
+ const row = this.provider.get<ProjectRow>('SELECT * FROM registered_projects WHERE path = ?', [
183
+ path,
184
+ ]);
180
185
  return row ? rowToProject(row) : null;
181
186
  }
182
187
 
@@ -184,9 +189,9 @@ export class ProjectRegistry {
184
189
  * List all registered projects.
185
190
  */
186
191
  list(): RegisteredProject[] {
187
- const rows = this.db
188
- .prepare('SELECT * FROM registered_projects ORDER BY last_accessed_at DESC')
189
- .all() as ProjectRow[];
192
+ const rows = this.provider.all<ProjectRow>(
193
+ 'SELECT * FROM registered_projects ORDER BY last_accessed_at DESC',
194
+ );
190
195
  return rows.map(rowToProject);
191
196
  }
192
197
 
@@ -194,23 +199,26 @@ export class ProjectRegistry {
194
199
  * Unregister a project by ID. Also removes associated rules and links.
195
200
  */
196
201
  unregister(projectId: string): boolean {
197
- const result = this.db.transaction(() => {
198
- this.db.prepare('DELETE FROM project_rules WHERE project_id = ?').run(projectId);
199
- this.db
200
- .prepare('DELETE FROM project_links WHERE source_project_id = ? OR target_project_id = ?')
201
- .run(projectId, projectId);
202
- return this.db.prepare('DELETE FROM registered_projects WHERE id = ?').run(projectId).changes > 0;
203
- })();
204
- return result;
202
+ return this.provider.transaction(() => {
203
+ this.provider.run('DELETE FROM project_rules WHERE project_id = ?', [projectId]);
204
+ this.provider.run(
205
+ 'DELETE FROM project_links WHERE source_project_id = ? OR target_project_id = ?',
206
+ [projectId, projectId],
207
+ );
208
+ return (
209
+ this.provider.run('DELETE FROM registered_projects WHERE id = ?', [projectId]).changes > 0
210
+ );
211
+ });
205
212
  }
206
213
 
207
214
  /**
208
215
  * Update the lastAccessedAt timestamp for a project.
209
216
  */
210
217
  touch(projectId: string): void {
211
- this.db
212
- .prepare('UPDATE registered_projects SET last_accessed_at = ? WHERE id = ?')
213
- .run(Date.now(), projectId);
218
+ this.provider.run('UPDATE registered_projects SET last_accessed_at = ? WHERE id = ?', [
219
+ Date.now(),
220
+ projectId,
221
+ ]);
214
222
  }
215
223
 
216
224
  // ─── Rules ──────────────────────────────────────────────────────────
@@ -224,11 +232,10 @@ export class ProjectRegistry {
224
232
  ): ProjectRule {
225
233
  const id = `rule-${projectId}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
226
234
  const now = Date.now();
227
- this.db
228
- .prepare(
229
- 'INSERT INTO project_rules (id, project_id, category, text, priority, created_at) VALUES (?, ?, ?, ?, ?, ?)',
230
- )
231
- .run(id, projectId, rule.category, rule.text, rule.priority, now);
235
+ this.provider.run(
236
+ 'INSERT INTO project_rules (id, project_id, category, text, priority, created_at) VALUES (?, ?, ?, ?, ?, ?)',
237
+ [id, projectId, rule.category, rule.text, rule.priority, now],
238
+ );
232
239
 
233
240
  return {
234
241
  id,
@@ -244,9 +251,10 @@ export class ProjectRegistry {
244
251
  * Get all rules for a project.
245
252
  */
246
253
  getRules(projectId: string): ProjectRule[] {
247
- const rows = this.db
248
- .prepare('SELECT * FROM project_rules WHERE project_id = ? ORDER BY priority DESC, created_at ASC')
249
- .all(projectId) as RuleRow[];
254
+ const rows = this.provider.all<RuleRow>(
255
+ 'SELECT * FROM project_rules WHERE project_id = ? ORDER BY priority DESC, created_at ASC',
256
+ [projectId],
257
+ );
250
258
  return rows.map(rowToRule);
251
259
  }
252
260
 
@@ -254,7 +262,7 @@ export class ProjectRegistry {
254
262
  * Remove a rule by ID.
255
263
  */
256
264
  removeRule(ruleId: string): boolean {
257
- return this.db.prepare('DELETE FROM project_rules WHERE id = ?').run(ruleId).changes > 0;
265
+ return this.provider.run('DELETE FROM project_rules WHERE id = ?', [ruleId]).changes > 0;
258
266
  }
259
267
 
260
268
  /**
@@ -275,20 +283,18 @@ export class ProjectRegistry {
275
283
  */
276
284
  link(sourceId: string, targetId: string, linkType: LinkType): ProjectLink {
277
285
  const now = Date.now();
278
- const info = this.db
279
- .prepare(
280
- 'INSERT OR IGNORE INTO project_links (source_project_id, target_project_id, link_type, created_at) VALUES (?, ?, ?, ?)',
281
- )
282
- .run(sourceId, targetId, linkType, now);
286
+ const info = this.provider.run(
287
+ 'INSERT OR IGNORE INTO project_links (source_project_id, target_project_id, link_type, created_at) VALUES (?, ?, ?, ?)',
288
+ [sourceId, targetId, linkType, now],
289
+ );
283
290
 
284
291
  // If insert was ignored (duplicate), fetch existing
285
292
  if (info.changes === 0) {
286
- const existing = this.db
287
- .prepare(
288
- 'SELECT * FROM project_links WHERE source_project_id = ? AND target_project_id = ? AND link_type = ?',
289
- )
290
- .get(sourceId, targetId, linkType) as LinkRow;
291
- return rowToLink(existing);
293
+ const existing = this.provider.get<LinkRow>(
294
+ 'SELECT * FROM project_links WHERE source_project_id = ? AND target_project_id = ? AND link_type = ?',
295
+ [sourceId, targetId, linkType],
296
+ );
297
+ return rowToLink(existing!);
292
298
  }
293
299
 
294
300
  return {
@@ -306,28 +312,25 @@ export class ProjectRegistry {
306
312
  */
307
313
  unlink(sourceId: string, targetId: string, linkType?: LinkType): number {
308
314
  if (linkType) {
309
- return this.db
310
- .prepare(
311
- 'DELETE FROM project_links WHERE source_project_id = ? AND target_project_id = ? AND link_type = ?',
312
- )
313
- .run(sourceId, targetId, linkType).changes;
315
+ return this.provider.run(
316
+ 'DELETE FROM project_links WHERE source_project_id = ? AND target_project_id = ? AND link_type = ?',
317
+ [sourceId, targetId, linkType],
318
+ ).changes;
314
319
  }
315
- return this.db
316
- .prepare(
317
- 'DELETE FROM project_links WHERE source_project_id = ? AND target_project_id = ?',
318
- )
319
- .run(sourceId, targetId).changes;
320
+ return this.provider.run(
321
+ 'DELETE FROM project_links WHERE source_project_id = ? AND target_project_id = ?',
322
+ [sourceId, targetId],
323
+ ).changes;
320
324
  }
321
325
 
322
326
  /**
323
327
  * Get all links for a project (both outgoing and incoming).
324
328
  */
325
329
  getLinks(projectId: string): ProjectLink[] {
326
- const rows = this.db
327
- .prepare(
328
- 'SELECT * FROM project_links WHERE source_project_id = ? OR target_project_id = ? ORDER BY created_at DESC',
329
- )
330
- .all(projectId, projectId) as LinkRow[];
330
+ const rows = this.provider.all<LinkRow>(
331
+ 'SELECT * FROM project_links WHERE source_project_id = ? OR target_project_id = ? ORDER BY created_at DESC',
332
+ [projectId, projectId],
333
+ );
331
334
  return rows.map(rowToLink);
332
335
  }
333
336
 
@@ -338,7 +341,11 @@ export class ProjectRegistry {
338
341
  projectId: string,
339
342
  ): Array<{ project: RegisteredProject; linkType: LinkType; direction: 'outgoing' | 'incoming' }> {
340
343
  const links = this.getLinks(projectId);
341
- const results: Array<{ project: RegisteredProject; linkType: LinkType; direction: 'outgoing' | 'incoming' }> = [];
344
+ const results: Array<{
345
+ project: RegisteredProject;
346
+ linkType: LinkType;
347
+ direction: 'outgoing' | 'incoming';
348
+ }> = [];
342
349
 
343
350
  for (const link of links) {
344
351
  const isOutgoing = link.sourceProjectId === projectId;
@@ -0,0 +1,3 @@
1
+ export { TemplateManager } from './template-manager.js';
2
+ export { parseVariables, resolveIncludes } from './parser.js';
3
+ export type { PromptTemplate, TemplateVariable, RenderOptions } from './types.js';
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Template parser — extract variables and resolve includes.
3
+ */
4
+
5
+ import type { TemplateVariable } from './types.js';
6
+
7
+ const VAR_PATTERN = /\{\{(\w+)(?::([^}]*))?\}\}/g;
8
+ const INCLUDE_PATTERN = /@include\(([^)]+)\)/g;
9
+ const MAX_INCLUDE_DEPTH = 10;
10
+
11
+ /**
12
+ * Extract unique variables from template content.
13
+ * Supports {{name}} (required) and {{name:default}} (optional with default).
14
+ */
15
+ export function parseVariables(content: string): TemplateVariable[] {
16
+ const seen = new Map<string, TemplateVariable>();
17
+
18
+ for (const match of content.matchAll(VAR_PATTERN)) {
19
+ const name = match[1];
20
+ const defaultValue = match[2];
21
+ if (!seen.has(name)) {
22
+ seen.set(name, {
23
+ name,
24
+ required: defaultValue === undefined,
25
+ defaultValue,
26
+ });
27
+ }
28
+ }
29
+
30
+ return Array.from(seen.values());
31
+ }
32
+
33
+ /**
34
+ * Resolve @include(partial-name) directives.
35
+ *
36
+ * The loader function receives the partial name and returns its content.
37
+ * Cycle detection prevents infinite recursion.
38
+ */
39
+ export function resolveIncludes(
40
+ content: string,
41
+ loader: (name: string) => string,
42
+ _stack: Set<string> = new Set(),
43
+ _depth: number = 0,
44
+ ): string {
45
+ if (_depth > MAX_INCLUDE_DEPTH) {
46
+ throw new Error(`Include depth exceeded ${MAX_INCLUDE_DEPTH}. Possible circular include.`);
47
+ }
48
+
49
+ return content.replace(INCLUDE_PATTERN, (_match, partialName: string) => {
50
+ const trimmed = partialName.trim();
51
+ if (_stack.has(trimmed)) {
52
+ throw new Error(`Circular include detected: ${trimmed} (stack: ${[..._stack].join(' → ')})`);
53
+ }
54
+ const newStack = new Set(_stack);
55
+ newStack.add(trimmed);
56
+ const partialContent = loader(trimmed);
57
+ return resolveIncludes(partialContent, loader, newStack, _depth + 1);
58
+ });
59
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Template manager — load, render, and list .prompt templates.
3
+ */
4
+
5
+ import { readFileSync, readdirSync, existsSync } from 'node:fs';
6
+ import { join, basename } from 'node:path';
7
+ import type { PromptTemplate, RenderOptions } from './types.js';
8
+ import { parseVariables, resolveIncludes } from './parser.js';
9
+
10
+ const VAR_REGEX = /\{\{(\w+)(?::([^}]*))?\}\}/g;
11
+
12
+ export class TemplateManager {
13
+ private templates = new Map<string, PromptTemplate>();
14
+ private templatesDir: string;
15
+
16
+ constructor(templatesDir: string) {
17
+ this.templatesDir = templatesDir;
18
+ }
19
+
20
+ /** Load all .prompt files from templatesDir. */
21
+ load(): void {
22
+ if (!existsSync(this.templatesDir)) return;
23
+
24
+ const files = readdirSync(this.templatesDir).filter((f) => f.endsWith('.prompt'));
25
+ for (const file of files) {
26
+ const fullPath = join(this.templatesDir, file);
27
+ const content = readFileSync(fullPath, 'utf-8');
28
+ const name = basename(file, '.prompt');
29
+ this.templates.set(name, {
30
+ name,
31
+ content,
32
+ variables: parseVariables(content),
33
+ path: fullPath,
34
+ });
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Render a template by name with variable substitution.
40
+ *
41
+ * @param name - Template name (without .prompt extension)
42
+ * @param vars - Variable values to substitute
43
+ * @param options - Render options (strict mode)
44
+ * @throws If template not found, or strict mode and required variable missing
45
+ */
46
+ render(name: string, vars: Record<string, string> = {}, options?: RenderOptions): string {
47
+ const template = this.templates.get(name);
48
+ if (!template) throw new Error(`Template not found: ${name}`);
49
+
50
+ const strict = options?.strict ?? true;
51
+
52
+ // Resolve @include() directives
53
+ const resolved = resolveIncludes(template.content, (partialName) => {
54
+ const partial = this.templates.get(partialName);
55
+ if (!partial) throw new Error(`Include not found: ${partialName} (in template: ${name})`);
56
+ return partial.content;
57
+ });
58
+
59
+ // Replace {{var}} and {{var:default}}
60
+ return resolved.replace(VAR_REGEX, (_match, varName: string, defaultValue?: string) => {
61
+ if (vars[varName] !== undefined) return vars[varName];
62
+ if (defaultValue !== undefined) return defaultValue;
63
+ if (strict) throw new Error(`Missing required variable: ${varName} (in template: ${name})`);
64
+ return _match; // Leave placeholder as-is in non-strict mode
65
+ });
66
+ }
67
+
68
+ /** List all loaded template names. */
69
+ listTemplates(): string[] {
70
+ return Array.from(this.templates.keys());
71
+ }
72
+
73
+ /** Get a template by name (raw, unrendered). */
74
+ getTemplate(name: string): PromptTemplate | null {
75
+ return this.templates.get(name) ?? null;
76
+ }
77
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Prompt template types.
3
+ */
4
+
5
+ export interface TemplateVariable {
6
+ /** Variable name, e.g. 'agentName' */
7
+ name: string;
8
+ /** Whether the variable must be provided at render time. */
9
+ required: boolean;
10
+ /** Default value used when variable is not provided (makes required=false). */
11
+ defaultValue?: string;
12
+ }
13
+
14
+ export interface PromptTemplate {
15
+ /** Template name (filename without .prompt extension). */
16
+ name: string;
17
+ /** Raw template content before variable substitution. */
18
+ content: string;
19
+ /** Variables extracted from the template. */
20
+ variables: TemplateVariable[];
21
+ /** Absolute file path. */
22
+ path: string;
23
+ }
24
+
25
+ export interface RenderOptions {
26
+ /** If true (default), throw on missing required variables. */
27
+ strict?: boolean;
28
+ }