@kb-labs/adapters 0.5.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 (276) hide show
  1. package/.cursorrules +32 -0
  2. package/.github/workflows/ci.yml +13 -0
  3. package/.github/workflows/deploy.yml +28 -0
  4. package/.github/workflows/docker-build.yml +25 -0
  5. package/.github/workflows/drift-check.yml +10 -0
  6. package/.github/workflows/profiles-validate.yml +16 -0
  7. package/.github/workflows/release.yml +8 -0
  8. package/.kb/devkit/agents/devkit-maintainer/context.globs +15 -0
  9. package/.kb/devkit/agents/devkit-maintainer/permissions.yml +17 -0
  10. package/.kb/devkit/agents/devkit-maintainer/prompt.md +28 -0
  11. package/.kb/devkit/agents/devkit-maintainer/runbook.md +31 -0
  12. package/.kb/devkit/agents/docs-crafter/prompt.md +24 -0
  13. package/.kb/devkit/agents/docs-crafter/runbook.md +18 -0
  14. package/.kb/devkit/agents/release-manager/context.globs +7 -0
  15. package/.kb/devkit/agents/release-manager/prompt.md +27 -0
  16. package/.kb/devkit/agents/release-manager/runbook.md +17 -0
  17. package/.kb/devkit/agents/test-generator/context.globs +7 -0
  18. package/.kb/devkit/agents/test-generator/prompt.md +27 -0
  19. package/.kb/devkit/agents/test-generator/runbook.md +18 -0
  20. package/CONTRIBUTING.md +90 -0
  21. package/IMPLEMENTATION_COMPLETE.md +416 -0
  22. package/LICENSE +186 -0
  23. package/README-TEMPLATE.md +179 -0
  24. package/README.md +306 -0
  25. package/docs/DOCUMENTATION.md +74 -0
  26. package/docs/adr/0000-template.md +49 -0
  27. package/docs/adr/0001-architecture-and-repository-layout.md +33 -0
  28. package/docs/adr/0002-plugins-and-extensibility.md +46 -0
  29. package/docs/adr/0003-package-and-module-boundaries.md +37 -0
  30. package/docs/adr/0004-versioning-and-release-policy.md +38 -0
  31. package/docs/adr/0005-use-devkit-for-shared-tooling.md +48 -0
  32. package/docs/adr/0006-adopt-devkit-sync.md +47 -0
  33. package/docs/adr/0007-drift-kit-check.md +72 -0
  34. package/docs/adr/0008-devkit-sync-wrapper-strategy.md +67 -0
  35. package/docs/naming-convention.md +272 -0
  36. package/eslint.config.js +27 -0
  37. package/kb-labs.config.json +5 -0
  38. package/package.json +84 -0
  39. package/package.json.bin +25 -0
  40. package/package.json.lib +30 -0
  41. package/packages/adapters-analytics-duckdb/package.json +54 -0
  42. package/packages/adapters-analytics-duckdb/scripts/migrate-from-jsonl.mjs +253 -0
  43. package/packages/adapters-analytics-duckdb/src/index.ts +380 -0
  44. package/packages/adapters-analytics-duckdb/src/manifest.ts +36 -0
  45. package/packages/adapters-analytics-duckdb/src/schema.ts +161 -0
  46. package/packages/adapters-analytics-duckdb/tsconfig.build.json +15 -0
  47. package/packages/adapters-analytics-duckdb/tsconfig.json +9 -0
  48. package/packages/adapters-analytics-duckdb/tsup.config.ts +9 -0
  49. package/packages/adapters-analytics-file/README.md +32 -0
  50. package/packages/adapters-analytics-file/eslint.config.js +27 -0
  51. package/packages/adapters-analytics-file/package.json +50 -0
  52. package/packages/adapters-analytics-file/src/__tests__/daily-stats.spec.ts +287 -0
  53. package/packages/adapters-analytics-file/src/__tests__/scoped-analytics.test.ts +233 -0
  54. package/packages/adapters-analytics-file/src/index.test.ts +214 -0
  55. package/packages/adapters-analytics-file/src/index.ts +830 -0
  56. package/packages/adapters-analytics-file/src/manifest.ts +45 -0
  57. package/packages/adapters-analytics-file/tsconfig.build.json +15 -0
  58. package/packages/adapters-analytics-file/tsconfig.json +9 -0
  59. package/packages/adapters-analytics-file/tsup.config.ts +9 -0
  60. package/packages/adapters-analytics-sqlite/package.json +55 -0
  61. package/packages/adapters-analytics-sqlite/scripts/migrate-from-jsonl.mjs +194 -0
  62. package/packages/adapters-analytics-sqlite/src/index.ts +460 -0
  63. package/packages/adapters-analytics-sqlite/src/manifest.ts +41 -0
  64. package/packages/adapters-analytics-sqlite/tsconfig.build.json +15 -0
  65. package/packages/adapters-analytics-sqlite/tsconfig.json +9 -0
  66. package/packages/adapters-analytics-sqlite/tsup.config.ts +9 -0
  67. package/packages/adapters-environment-docker/README.md +28 -0
  68. package/packages/adapters-environment-docker/eslint.config.js +5 -0
  69. package/packages/adapters-environment-docker/package.json +49 -0
  70. package/packages/adapters-environment-docker/src/index.test.ts +138 -0
  71. package/packages/adapters-environment-docker/src/index.ts +439 -0
  72. package/packages/adapters-environment-docker/src/manifest.ts +65 -0
  73. package/packages/adapters-environment-docker/tsconfig.build.json +15 -0
  74. package/packages/adapters-environment-docker/tsconfig.json +16 -0
  75. package/packages/adapters-environment-docker/tsup.config.ts +9 -0
  76. package/packages/adapters-eventbus-cache/README.md +242 -0
  77. package/packages/adapters-eventbus-cache/eslint.config.js +27 -0
  78. package/packages/adapters-eventbus-cache/package.json +46 -0
  79. package/packages/adapters-eventbus-cache/src/index.test.ts +235 -0
  80. package/packages/adapters-eventbus-cache/src/index.ts +215 -0
  81. package/packages/adapters-eventbus-cache/src/manifest.ts +50 -0
  82. package/packages/adapters-eventbus-cache/src/types.ts +58 -0
  83. package/packages/adapters-eventbus-cache/tsconfig.build.json +15 -0
  84. package/packages/adapters-eventbus-cache/tsconfig.json +9 -0
  85. package/packages/adapters-eventbus-cache/tsup.config.ts +9 -0
  86. package/packages/adapters-fs/README.md +171 -0
  87. package/packages/adapters-fs/allowed.txt +1 -0
  88. package/packages/adapters-fs/conflict.txt +1 -0
  89. package/packages/adapters-fs/dest.txt +1 -0
  90. package/packages/adapters-fs/eslint.config.js +27 -0
  91. package/packages/adapters-fs/exists.txt +1 -0
  92. package/packages/adapters-fs/not-allowed.txt +1 -0
  93. package/packages/adapters-fs/other.txt +1 -0
  94. package/packages/adapters-fs/package.json +55 -0
  95. package/packages/adapters-fs/public/file1.txt +1 -0
  96. package/packages/adapters-fs/public/file2.txt +1 -0
  97. package/packages/adapters-fs/secret.txt +1 -0
  98. package/packages/adapters-fs/secrets/key.txt +1 -0
  99. package/packages/adapters-fs/src/index.test.ts +243 -0
  100. package/packages/adapters-fs/src/index.ts +258 -0
  101. package/packages/adapters-fs/src/manifest.ts +35 -0
  102. package/packages/adapters-fs/src/secure-storage.test.ts +380 -0
  103. package/packages/adapters-fs/src/secure-storage.ts +268 -0
  104. package/packages/adapters-fs/test.json +1 -0
  105. package/packages/adapters-fs/test.txt +1 -0
  106. package/packages/adapters-fs/test.xyz +1 -0
  107. package/packages/adapters-fs/test1.txt +1 -0
  108. package/packages/adapters-fs/test2.txt +1 -0
  109. package/packages/adapters-fs/tsconfig.build.json +15 -0
  110. package/packages/adapters-fs/tsconfig.json +9 -0
  111. package/packages/adapters-fs/tsup.config.ts +8 -0
  112. package/packages/adapters-fs/vitest.config.ts +19 -0
  113. package/packages/adapters-log-ringbuffer/README.md +228 -0
  114. package/packages/adapters-log-ringbuffer/eslint.config.js +27 -0
  115. package/packages/adapters-log-ringbuffer/package.json +47 -0
  116. package/packages/adapters-log-ringbuffer/src/__tests__/ring-buffer.test.ts +450 -0
  117. package/packages/adapters-log-ringbuffer/src/index.ts +212 -0
  118. package/packages/adapters-log-ringbuffer/src/manifest.ts +30 -0
  119. package/packages/adapters-log-ringbuffer/tsconfig.build.json +15 -0
  120. package/packages/adapters-log-ringbuffer/tsconfig.json +9 -0
  121. package/packages/adapters-log-ringbuffer/tsup.config.ts +9 -0
  122. package/packages/adapters-log-ringbuffer/vitest.config.ts +14 -0
  123. package/packages/adapters-log-sqlite/README.md +396 -0
  124. package/packages/adapters-log-sqlite/eslint.config.js +27 -0
  125. package/packages/adapters-log-sqlite/package.json +49 -0
  126. package/packages/adapters-log-sqlite/src/__tests__/log-persistence.test.ts +718 -0
  127. package/packages/adapters-log-sqlite/src/index.ts +1068 -0
  128. package/packages/adapters-log-sqlite/src/manifest.ts +36 -0
  129. package/packages/adapters-log-sqlite/src/schema.sql +46 -0
  130. package/packages/adapters-log-sqlite/tsconfig.build.json +15 -0
  131. package/packages/adapters-log-sqlite/tsconfig.json +9 -0
  132. package/packages/adapters-log-sqlite/tsup.config.ts +9 -0
  133. package/packages/adapters-log-sqlite/vitest.config.ts +15 -0
  134. package/packages/adapters-mongodb/README.md +147 -0
  135. package/packages/adapters-mongodb/eslint.config.js +27 -0
  136. package/packages/adapters-mongodb/package.json +53 -0
  137. package/packages/adapters-mongodb/src/index.ts +428 -0
  138. package/packages/adapters-mongodb/src/manifest.ts +45 -0
  139. package/packages/adapters-mongodb/src/secure-document.ts +231 -0
  140. package/packages/adapters-mongodb/tsconfig.build.json +15 -0
  141. package/packages/adapters-mongodb/tsconfig.json +9 -0
  142. package/packages/adapters-mongodb/tsup.config.ts +8 -0
  143. package/packages/adapters-openai/README.md +151 -0
  144. package/packages/adapters-openai/embeddings.ts +37 -0
  145. package/packages/adapters-openai/eslint.config.js +26 -0
  146. package/packages/adapters-openai/index.ts +22 -0
  147. package/packages/adapters-openai/package.json +57 -0
  148. package/packages/adapters-openai/src/embeddings-manifest.ts +45 -0
  149. package/packages/adapters-openai/src/embeddings.ts +104 -0
  150. package/packages/adapters-openai/src/index.ts +13 -0
  151. package/packages/adapters-openai/src/llm.ts +304 -0
  152. package/packages/adapters-openai/src/manifest.ts +47 -0
  153. package/packages/adapters-openai/tsconfig.build.json +15 -0
  154. package/packages/adapters-openai/tsconfig.json +9 -0
  155. package/packages/adapters-openai/tsup.config.ts +8 -0
  156. package/packages/adapters-pino/README.md +152 -0
  157. package/packages/adapters-pino/eslint.config.js +27 -0
  158. package/packages/adapters-pino/package.json +49 -0
  159. package/packages/adapters-pino/src/index.test.ts +44 -0
  160. package/packages/adapters-pino/src/index.ts +322 -0
  161. package/packages/adapters-pino/src/log-ring-buffer.ts +142 -0
  162. package/packages/adapters-pino/src/manifest.ts +49 -0
  163. package/packages/adapters-pino/tsconfig.build.json +15 -0
  164. package/packages/adapters-pino/tsconfig.json +9 -0
  165. package/packages/adapters-pino/tsup.config.ts +9 -0
  166. package/packages/adapters-pino-http/README.md +141 -0
  167. package/packages/adapters-pino-http/eslint.config.js +27 -0
  168. package/packages/adapters-pino-http/package.json +46 -0
  169. package/packages/adapters-pino-http/src/index.ts +229 -0
  170. package/packages/adapters-pino-http/tsconfig.build.json +15 -0
  171. package/packages/adapters-pino-http/tsconfig.json +9 -0
  172. package/packages/adapters-pino-http/tsup.config.ts +9 -0
  173. package/packages/adapters-qdrant/README.md +166 -0
  174. package/packages/adapters-qdrant/eslint.config.js +27 -0
  175. package/packages/adapters-qdrant/package.json +49 -0
  176. package/packages/adapters-qdrant/src/index.ts +490 -0
  177. package/packages/adapters-qdrant/src/manifest.ts +54 -0
  178. package/packages/adapters-qdrant/src/retry.ts +204 -0
  179. package/packages/adapters-qdrant/tsconfig.build.json +15 -0
  180. package/packages/adapters-qdrant/tsconfig.json +9 -0
  181. package/packages/adapters-qdrant/tsup.config.ts +9 -0
  182. package/packages/adapters-redis/README.md +159 -0
  183. package/packages/adapters-redis/eslint.config.js +27 -0
  184. package/packages/adapters-redis/package.json +49 -0
  185. package/packages/adapters-redis/src/index.ts +164 -0
  186. package/packages/adapters-redis/src/manifest.ts +49 -0
  187. package/packages/adapters-redis/tsconfig.build.json +15 -0
  188. package/packages/adapters-redis/tsconfig.json +9 -0
  189. package/packages/adapters-redis/tsup.config.ts +9 -0
  190. package/packages/adapters-snapshot-localfs/README.md +10 -0
  191. package/packages/adapters-snapshot-localfs/eslint.config.js +2 -0
  192. package/packages/adapters-snapshot-localfs/package.json +46 -0
  193. package/packages/adapters-snapshot-localfs/src/index.test.ts +40 -0
  194. package/packages/adapters-snapshot-localfs/src/index.ts +292 -0
  195. package/packages/adapters-snapshot-localfs/src/manifest.ts +32 -0
  196. package/packages/adapters-snapshot-localfs/tsconfig.build.json +15 -0
  197. package/packages/adapters-snapshot-localfs/tsconfig.json +16 -0
  198. package/packages/adapters-snapshot-localfs/tsup.config.ts +11 -0
  199. package/packages/adapters-sqlite/README.md +163 -0
  200. package/packages/adapters-sqlite/eslint.config.js +27 -0
  201. package/packages/adapters-sqlite/package.json +54 -0
  202. package/packages/adapters-sqlite/src/index.test.ts +245 -0
  203. package/packages/adapters-sqlite/src/index.ts +382 -0
  204. package/packages/adapters-sqlite/src/manifest.ts +47 -0
  205. package/packages/adapters-sqlite/src/secure-sql.test.ts +290 -0
  206. package/packages/adapters-sqlite/src/secure-sql.ts +281 -0
  207. package/packages/adapters-sqlite/tsconfig.build.json +15 -0
  208. package/packages/adapters-sqlite/tsconfig.json +9 -0
  209. package/packages/adapters-sqlite/tsup.config.ts +8 -0
  210. package/packages/adapters-sqlite/vitest.config.ts +19 -0
  211. package/packages/adapters-transport/README.md +170 -0
  212. package/packages/adapters-transport/eslint.config.js +27 -0
  213. package/packages/adapters-transport/package.json +49 -0
  214. package/packages/adapters-transport/src/__tests__/unix-socket-server.test.ts +550 -0
  215. package/packages/adapters-transport/src/index.ts +101 -0
  216. package/packages/adapters-transport/src/ipc-transport.ts +228 -0
  217. package/packages/adapters-transport/src/transport.ts +224 -0
  218. package/packages/adapters-transport/src/types.ts +92 -0
  219. package/packages/adapters-transport/src/unix-socket-server.ts +193 -0
  220. package/packages/adapters-transport/src/unix-socket-transport.ts +280 -0
  221. package/packages/adapters-transport/tsconfig.build.json +15 -0
  222. package/packages/adapters-transport/tsconfig.json +9 -0
  223. package/packages/adapters-transport/tsup.config.ts +9 -0
  224. package/packages/adapters-vibeproxy/README.md +159 -0
  225. package/packages/adapters-vibeproxy/eslint.config.js +27 -0
  226. package/packages/adapters-vibeproxy/package.json +51 -0
  227. package/packages/adapters-vibeproxy/src/index.ts +13 -0
  228. package/packages/adapters-vibeproxy/src/llm.ts +437 -0
  229. package/packages/adapters-vibeproxy/src/manifest.ts +51 -0
  230. package/packages/adapters-vibeproxy/tsconfig.build.json +15 -0
  231. package/packages/adapters-vibeproxy/tsconfig.json +9 -0
  232. package/packages/adapters-vibeproxy/tsup.config.ts +8 -0
  233. package/packages/adapters-workspace-agent/package.json +46 -0
  234. package/packages/adapters-workspace-agent/src/__tests__/adapter.test.ts +212 -0
  235. package/packages/adapters-workspace-agent/src/index.ts +220 -0
  236. package/packages/adapters-workspace-agent/src/manifest.ts +36 -0
  237. package/packages/adapters-workspace-agent/tsconfig.build.json +15 -0
  238. package/packages/adapters-workspace-agent/tsconfig.json +16 -0
  239. package/packages/adapters-workspace-agent/tsup.config.ts +11 -0
  240. package/packages/adapters-workspace-localfs/README.md +9 -0
  241. package/packages/adapters-workspace-localfs/eslint.config.js +2 -0
  242. package/packages/adapters-workspace-localfs/package.json +46 -0
  243. package/packages/adapters-workspace-localfs/src/index.test.ts +27 -0
  244. package/packages/adapters-workspace-localfs/src/index.ts +172 -0
  245. package/packages/adapters-workspace-localfs/src/manifest.ts +32 -0
  246. package/packages/adapters-workspace-localfs/tsconfig.build.json +15 -0
  247. package/packages/adapters-workspace-localfs/tsconfig.json +16 -0
  248. package/packages/adapters-workspace-localfs/tsup.config.ts +11 -0
  249. package/packages/adapters-workspace-worktree/README.md +9 -0
  250. package/packages/adapters-workspace-worktree/eslint.config.js +2 -0
  251. package/packages/adapters-workspace-worktree/package.json +46 -0
  252. package/packages/adapters-workspace-worktree/src/index.test.ts +38 -0
  253. package/packages/adapters-workspace-worktree/src/index.ts +245 -0
  254. package/packages/adapters-workspace-worktree/src/manifest.ts +38 -0
  255. package/packages/adapters-workspace-worktree/tsconfig.build.json +15 -0
  256. package/packages/adapters-workspace-worktree/tsconfig.json +16 -0
  257. package/packages/adapters-workspace-worktree/tsup.config.ts +11 -0
  258. package/pnpm-workspace.yaml +2800 -0
  259. package/prettierrc.json +1 -0
  260. package/scripts/devkit-sync.mjs +37 -0
  261. package/scripts/hooks/post-push +9 -0
  262. package/scripts/hooks/pre-commit +9 -0
  263. package/scripts/hooks/pre-push +9 -0
  264. package/test-integration.ts +242 -0
  265. package/test.txt +1 -0
  266. package/tsconfig.base.json +6 -0
  267. package/tsconfig.build.json +15 -0
  268. package/tsconfig.json +9 -0
  269. package/tsconfig.paths.json +26 -0
  270. package/tsconfig.tools.json +17 -0
  271. package/tsup.config.bin.ts +34 -0
  272. package/tsup.config.cli.ts +41 -0
  273. package/tsup.config.dual.ts +46 -0
  274. package/tsup.config.ts +36 -0
  275. package/tsup.external.json +103 -0
  276. package/vitest.config.ts +2 -0
@@ -0,0 +1,9 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "extends": "@kb-labs/devkit/tsconfig/node.json",
4
+ "compilerOptions": {
5
+ "rootDir": "src",
6
+ "outDir": "dist"
7
+ },
8
+ "include": ["src"]
9
+ }
@@ -0,0 +1,9 @@
1
+ import { defineConfig } from 'tsup';
2
+ import nodePreset from '@kb-labs/devkit/tsup/node';
3
+
4
+ export default defineConfig({
5
+ ...nodePreset,
6
+ tsconfig: 'tsconfig.build.json',
7
+ entry: ['src/index.ts', 'src/manifest.ts'],
8
+ dts: true,
9
+ });
@@ -0,0 +1,10 @@
1
+ # @kb-labs/adapters-snapshot-localfs
2
+
3
+ Local filesystem implementation of `ISnapshotProvider`.
4
+
5
+ ## Features
6
+
7
+ - Capture snapshot by copying source directory into snapshot store
8
+ - Restore snapshot to target directory
9
+ - Status/delete/garbage-collect lifecycle
10
+ - Can resolve workspace root from workspace registry
@@ -0,0 +1,2 @@
1
+ import cfg from '@kb-labs/devkit/eslint/node.js';
2
+ export default cfg;
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@kb-labs/adapters-snapshot-localfs",
3
+ "version": "0.5.0",
4
+ "description": "Local filesystem adapter implementing ISnapshotProvider",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md"
17
+ ],
18
+ "sideEffects": false,
19
+ "scripts": {
20
+ "clean": "rimraf dist",
21
+ "build": "tsup",
22
+ "dev": "tsup --watch",
23
+ "type-check": "tsc --noEmit",
24
+ "test": "vitest run --passWithNoTests",
25
+ "test:watch": "vitest",
26
+ "lint": "eslint src --ext .ts",
27
+ "lint:fix": "eslint . --fix"
28
+ },
29
+ "peerDependencies": {
30
+ "@kb-labs/core-platform": "*"
31
+ },
32
+ "devDependencies": {
33
+ "@kb-labs/core-platform": "link:../../../../platform/kb-labs-core/packages/core-platform",
34
+ "@types/node": "^24.3.3",
35
+ "eslint": "^9",
36
+ "tsup": "^8.5.0",
37
+ "typescript": "^5.6.3",
38
+ "vitest": "^3.2.4",
39
+ "@kb-labs/devkit": "link:../../../kb-labs-devkit",
40
+ "rimraf": "^6.0.1"
41
+ },
42
+ "engines": {
43
+ "node": ">=20.0.0",
44
+ "pnpm": ">=9.0.0"
45
+ }
46
+ }
@@ -0,0 +1,40 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { mkdtemp, rm, writeFile, readFile, mkdir } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import os from 'node:os';
5
+ import { LocalFsSnapshotAdapter } from './index.js';
6
+
7
+ describe('LocalFsSnapshotAdapter', () => {
8
+ it('captures and restores workspace snapshot', async () => {
9
+ const tmp = await mkdtemp(path.join(os.tmpdir(), 'kb-snapshot-'));
10
+ try {
11
+ const workspaceId = 'ws_1';
12
+ const workspaceRoot = path.join(tmp, 'demo');
13
+ await mkdir(path.join(tmp, '.kb/runtime/workspace-registry'), { recursive: true });
14
+ await mkdir(workspaceRoot, { recursive: true });
15
+ await writeFile(
16
+ path.join(tmp, '.kb/runtime/workspace-registry', `${workspaceId}.json`),
17
+ JSON.stringify({ workspaceId, rootPath: workspaceRoot }, null, 2),
18
+ 'utf8'
19
+ );
20
+
21
+ const filePath = path.join(workspaceRoot, 'hello.txt');
22
+ await writeFile(filePath, 'v1', 'utf8');
23
+
24
+ const snapshot = new LocalFsSnapshotAdapter({ workspace: { cwd: tmp } });
25
+ const snap = await snapshot.capture({ workspaceId, namespace: 'demo' });
26
+
27
+ await writeFile(filePath, 'v2', 'utf8');
28
+ await snapshot.restore({
29
+ snapshotId: snap.snapshotId,
30
+ workspaceId,
31
+ overwrite: true,
32
+ });
33
+
34
+ const restored = await readFile(filePath, 'utf8');
35
+ expect(restored).toBe('v1');
36
+ } finally {
37
+ await rm(tmp, { recursive: true, force: true });
38
+ }
39
+ });
40
+ });
@@ -0,0 +1,292 @@
1
+ import { mkdir, readFile, rm, writeFile, access, cp, readdir, stat } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { randomUUID } from 'node:crypto';
4
+ import type {
5
+ ISnapshotProvider,
6
+ CaptureSnapshotRequest,
7
+ SnapshotDescriptor,
8
+ RestoreSnapshotRequest,
9
+ RestoreSnapshotResult,
10
+ SnapshotStatusResult,
11
+ SnapshotGarbageCollectRequest,
12
+ SnapshotGarbageCollectResult,
13
+ SnapshotProviderCapabilities,
14
+ SnapshotStatus,
15
+ } from '@kb-labs/core-platform';
16
+
17
+ export { manifest } from './manifest.js';
18
+
19
+ interface WorkspaceContext {
20
+ cwd?: string;
21
+ }
22
+
23
+ export interface LocalFsSnapshotAdapterConfig {
24
+ storageDir?: string;
25
+ workspaceRegistryDir?: string;
26
+ workspace?: WorkspaceContext;
27
+ }
28
+
29
+ interface SnapshotRecord {
30
+ snapshotId: string;
31
+ status: SnapshotStatus;
32
+ createdAt: string;
33
+ updatedAt: string;
34
+ workspaceId?: string;
35
+ environmentId?: string;
36
+ sourcePath: string;
37
+ payloadPath: string;
38
+ namespace?: string;
39
+ }
40
+
41
+ interface WorkspaceRecord {
42
+ workspaceId: string;
43
+ rootPath?: string;
44
+ }
45
+
46
+ export class LocalFsSnapshotAdapter implements ISnapshotProvider {
47
+ private readonly cwd: string;
48
+ private readonly storageDir: string;
49
+ private readonly workspaceRegistryDir: string;
50
+ private readonly records = new Map<string, SnapshotRecord>();
51
+
52
+ constructor(private readonly config: LocalFsSnapshotAdapterConfig = {}) {
53
+ this.cwd = path.resolve(config.workspace?.cwd ?? process.cwd());
54
+ this.storageDir = path.resolve(this.cwd, config.storageDir ?? '.kb/runtime/snapshots');
55
+ this.workspaceRegistryDir = path.resolve(
56
+ this.cwd,
57
+ config.workspaceRegistryDir ?? '.kb/runtime/workspace-registry'
58
+ );
59
+ }
60
+
61
+ async capture(request: CaptureSnapshotRequest): Promise<SnapshotDescriptor> {
62
+ const snapshotId = request.snapshotId ?? `snap_${randomUUID()}`;
63
+ const now = new Date().toISOString();
64
+ const sourcePath = await this.resolveSourcePath(request);
65
+ const namespace = request.namespace ?? 'default';
66
+ const payloadPath = path.join(this.storageDir, namespace, snapshotId);
67
+
68
+ await mkdir(path.dirname(payloadPath), { recursive: true });
69
+ await rm(payloadPath, { recursive: true, force: true });
70
+ await cp(sourcePath, payloadPath, { recursive: true, force: true });
71
+
72
+ const record: SnapshotRecord = {
73
+ snapshotId,
74
+ status: 'ready',
75
+ createdAt: now,
76
+ updatedAt: now,
77
+ workspaceId: request.workspaceId,
78
+ environmentId: request.environmentId,
79
+ sourcePath,
80
+ payloadPath,
81
+ namespace,
82
+ };
83
+
84
+ await this.persistRecord(record);
85
+
86
+ return {
87
+ snapshotId,
88
+ provider: 'snapshot-localfs',
89
+ status: 'ready',
90
+ createdAt: now,
91
+ updatedAt: now,
92
+ workspaceId: request.workspaceId,
93
+ environmentId: request.environmentId,
94
+ metadata: {
95
+ namespace,
96
+ payloadPath,
97
+ },
98
+ };
99
+ }
100
+
101
+ async restore(request: RestoreSnapshotRequest): Promise<RestoreSnapshotResult> {
102
+ const record = await this.getRecordOrThrow(request.snapshotId);
103
+ const now = new Date().toISOString();
104
+
105
+ const targetPath = request.targetPath
106
+ ? path.resolve(this.cwd, request.targetPath)
107
+ : await this.resolveRestoreTargetPath(request.workspaceId, record.workspaceId);
108
+
109
+ if (!request.overwrite) {
110
+ try {
111
+ await access(targetPath);
112
+ throw new Error(`Restore target already exists: ${targetPath}. Use overwrite=true.`);
113
+ } catch (error) {
114
+ if (error instanceof Error && error.message.startsWith('Restore target already exists')) {
115
+ throw error;
116
+ }
117
+ // path missing, continue
118
+ }
119
+ }
120
+
121
+ if (request.overwrite) {
122
+ await rm(targetPath, { recursive: true, force: true });
123
+ }
124
+
125
+ await mkdir(path.dirname(targetPath), { recursive: true });
126
+ await cp(record.payloadPath, targetPath, { recursive: true, force: true });
127
+
128
+ record.status = 'ready';
129
+ record.updatedAt = now;
130
+ await this.persistRecord(record);
131
+
132
+ return {
133
+ snapshotId: request.snapshotId,
134
+ restoredAt: now,
135
+ workspaceId: request.workspaceId,
136
+ environmentId: request.environmentId,
137
+ targetPath,
138
+ };
139
+ }
140
+
141
+ async getStatus(snapshotId: string): Promise<SnapshotStatusResult> {
142
+ const record = await this.getRecordOrThrow(snapshotId);
143
+ return {
144
+ snapshotId,
145
+ status: record.status,
146
+ updatedAt: record.updatedAt,
147
+ };
148
+ }
149
+
150
+ async delete(snapshotId: string): Promise<void> {
151
+ const record = await this.getRecordOrThrow(snapshotId);
152
+ await rm(record.payloadPath, { recursive: true, force: true });
153
+ this.records.delete(snapshotId);
154
+ await rm(this.getRecordPath(snapshotId), { force: true });
155
+ }
156
+
157
+ async garbageCollect(
158
+ request: SnapshotGarbageCollectRequest = {}
159
+ ): Promise<SnapshotGarbageCollectResult> {
160
+ const beforeTs = request.before ? new Date(request.before).getTime() : Number.POSITIVE_INFINITY;
161
+ const limit = request.limit ?? Number.POSITIVE_INFINITY;
162
+ const dryRun = request.dryRun ?? false;
163
+ let scanned = 0;
164
+ let deleted = 0;
165
+
166
+ for (const record of await this.loadAllRecords()) {
167
+ scanned += 1;
168
+ const createdTs = new Date(record.createdAt).getTime();
169
+ if (createdTs >= beforeTs) {
170
+ continue;
171
+ }
172
+ if (request.namespace && record.namespace !== request.namespace) {
173
+ continue;
174
+ }
175
+ if (deleted >= limit) {
176
+ break;
177
+ }
178
+
179
+ if (!dryRun) {
180
+ await this.delete(record.snapshotId);
181
+ }
182
+ deleted += 1;
183
+ }
184
+
185
+ return { scanned, deleted, dryRun };
186
+ }
187
+
188
+ getCapabilities(): SnapshotProviderCapabilities {
189
+ return {
190
+ supportsWorkspaceSnapshots: true,
191
+ supportsEnvironmentSnapshots: false,
192
+ supportsGarbageCollection: true,
193
+ supportsIncrementalSnapshots: false,
194
+ custom: {
195
+ provider: 'localfs',
196
+ },
197
+ };
198
+ }
199
+
200
+ private async resolveSourcePath(request: CaptureSnapshotRequest): Promise<string> {
201
+ if (request.sourcePath) {
202
+ return path.resolve(this.cwd, request.sourcePath);
203
+ }
204
+
205
+ if (request.workspaceId) {
206
+ const workspace = await this.readWorkspaceRecord(request.workspaceId);
207
+ if (workspace.rootPath) {
208
+ return workspace.rootPath;
209
+ }
210
+ }
211
+
212
+ throw new Error('Snapshot capture requires sourcePath or resolvable workspaceId');
213
+ }
214
+
215
+ private async resolveRestoreTargetPath(
216
+ requestedWorkspaceId?: string,
217
+ recordWorkspaceId?: string
218
+ ): Promise<string> {
219
+ const workspaceId = requestedWorkspaceId ?? recordWorkspaceId;
220
+ if (!workspaceId) {
221
+ throw new Error('Snapshot restore requires targetPath or workspaceId');
222
+ }
223
+ const workspace = await this.readWorkspaceRecord(workspaceId);
224
+ if (!workspace.rootPath) {
225
+ throw new Error(`Workspace rootPath not found for workspaceId=${workspaceId}`);
226
+ }
227
+ return workspace.rootPath;
228
+ }
229
+
230
+ private getRecordPath(snapshotId: string): string {
231
+ return path.join(this.storageDir, '.records', `${snapshotId}.json`);
232
+ }
233
+
234
+ private async persistRecord(record: SnapshotRecord): Promise<void> {
235
+ this.records.set(record.snapshotId, record);
236
+ const recordPath = this.getRecordPath(record.snapshotId);
237
+ await mkdir(path.dirname(recordPath), { recursive: true });
238
+ await writeFile(recordPath, JSON.stringify(record, null, 2), 'utf8');
239
+ }
240
+
241
+ private async getRecordOrThrow(snapshotId: string): Promise<SnapshotRecord> {
242
+ const inMemory = this.records.get(snapshotId);
243
+ if (inMemory) {
244
+ return inMemory;
245
+ }
246
+
247
+ const recordPath = this.getRecordPath(snapshotId);
248
+ try {
249
+ const raw = await readFile(recordPath, 'utf8');
250
+ const parsed = JSON.parse(raw) as SnapshotRecord;
251
+ this.records.set(snapshotId, parsed);
252
+ return parsed;
253
+ } catch {
254
+ throw new Error(`Snapshot not found: ${snapshotId}`);
255
+ }
256
+ }
257
+
258
+ private async readWorkspaceRecord(workspaceId: string): Promise<WorkspaceRecord> {
259
+ const filePath = path.join(this.workspaceRegistryDir, `${workspaceId}.json`);
260
+ const raw = await readFile(filePath, 'utf8');
261
+ return JSON.parse(raw) as WorkspaceRecord;
262
+ }
263
+
264
+ private async loadAllRecords(): Promise<SnapshotRecord[]> {
265
+ const recordsDir = path.join(this.storageDir, '.records');
266
+ try {
267
+ const entries = await readdir(recordsDir);
268
+ const loaded: SnapshotRecord[] = [];
269
+ for (const entry of entries) {
270
+ if (!entry.endsWith('.json')) {
271
+ continue;
272
+ }
273
+ const filePath = path.join(recordsDir, entry);
274
+ const fileStat = await stat(filePath);
275
+ if (!fileStat.isFile()) {
276
+ continue;
277
+ }
278
+ const raw = await readFile(filePath, 'utf8');
279
+ loaded.push(JSON.parse(raw) as SnapshotRecord);
280
+ }
281
+ return loaded;
282
+ } catch {
283
+ return [];
284
+ }
285
+ }
286
+ }
287
+
288
+ export function createAdapter(config?: LocalFsSnapshotAdapterConfig): LocalFsSnapshotAdapter {
289
+ return new LocalFsSnapshotAdapter(config);
290
+ }
291
+
292
+ export default createAdapter;
@@ -0,0 +1,32 @@
1
+ import type { AdapterManifest } from '@kb-labs/core-platform';
2
+
3
+ export const manifest: AdapterManifest = {
4
+ manifestVersion: '1.0.0',
5
+ id: 'localfs-snapshot-provider',
6
+ name: 'LocalFS Snapshot Provider',
7
+ version: '0.1.0',
8
+ description: 'Snapshot provider on local filesystem',
9
+ author: 'KB Labs Team',
10
+ license: 'KBPL-1.1',
11
+ type: 'core',
12
+ implements: 'ISnapshotProvider',
13
+ contexts: ['workspace'],
14
+ capabilities: {
15
+ custom: {
16
+ provider: 'localfs',
17
+ workspaceRegistry: true,
18
+ },
19
+ },
20
+ configSchema: {
21
+ storageDir: {
22
+ type: 'string',
23
+ default: '.kb/runtime/snapshots',
24
+ description: 'Root directory where snapshots are stored',
25
+ },
26
+ workspaceRegistryDir: {
27
+ type: 'string',
28
+ default: '.kb/runtime/workspace-registry',
29
+ description: 'Directory with workspace metadata for source path resolution',
30
+ },
31
+ },
32
+ };
@@ -0,0 +1,15 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist",
5
+ "baseUrl": ".",
6
+ "paths": {}
7
+ },
8
+ "include": [
9
+ "src/**/*"
10
+ ],
11
+ "exclude": [
12
+ "dist",
13
+ "node_modules"
14
+ ]
15
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "extends": "@kb-labs/devkit/tsconfig/node.json",
4
+ "compilerOptions": {
5
+ "baseUrl": ".",
6
+ "paths": {
7
+ "@kb-labs/core-platform": [
8
+ "../../../kb-labs-core/packages/core-platform/src/index.ts"
9
+ ],
10
+ "@kb-labs/core-platform/*": [
11
+ "../../../kb-labs-core/packages/core-platform/src/*"
12
+ ]
13
+ }
14
+ },
15
+ "include": ["src"]
16
+ }
@@ -0,0 +1,11 @@
1
+ import { defineConfig } from 'tsup';
2
+
3
+ export default defineConfig({
4
+ entry: ['src/index.ts', 'src/manifest.ts'],
5
+ format: ['esm'],
6
+ dts: true,
7
+ sourcemap: true,
8
+ clean: true,
9
+ target: 'es2022',
10
+ external: [/^@kb-labs\/.*/],
11
+ });
@@ -0,0 +1,163 @@
1
+ # @kb-labs/adapters-sqlite
2
+
3
+ > Part of [KB Labs](https://github.com/KirillBaranov/kb-labs) ecosystem. Works exclusively within KB Labs platform.
4
+
5
+ Lightweight embedded SQL database adapter using better-sqlite3 with FTS, JSON, and transaction support.
6
+
7
+ ## Overview
8
+
9
+ | Property | Value |
10
+ |----------|-------|
11
+ | **Implements** | `ISQLDatabase` |
12
+ | **Type** | `core` |
13
+ | **Requires** | None |
14
+ | **Category** | Database |
15
+
16
+ ## Features
17
+
18
+ - **Embedded Database** - No external server required
19
+ - **Full-Text Search** - FTS5 for fast text search
20
+ - **JSON Support** - Store and query JSON fields
21
+ - **Prepared Statements** - Optimized query execution
22
+ - **Transaction Support** - ACID-compliant operations
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ pnpm add @kb-labs/adapters-sqlite
28
+ ```
29
+
30
+ ## Configuration
31
+
32
+ Add to your `kb.config.json`:
33
+
34
+ ```json
35
+ {
36
+ "platform": {
37
+ "adapters": {
38
+ "db": "@kb-labs/adapters-sqlite"
39
+ },
40
+ "adapterOptions": {
41
+ "db": {
42
+ "filename": ".kb/data/kb.db",
43
+ "readonly": false,
44
+ "timeout": 5000
45
+ }
46
+ }
47
+ }
48
+ }
49
+ ```
50
+
51
+ ### Options
52
+
53
+ | Option | Type | Default | Description |
54
+ |--------|------|---------|-------------|
55
+ | `filename` | `string` | - | Database file path (`:memory:` for in-memory) |
56
+ | `readonly` | `boolean` | `false` | Open in readonly mode |
57
+ | `timeout` | `number` | `5000` | Busy timeout in milliseconds |
58
+
59
+ ## Usage
60
+
61
+ ### Via Platform (Recommended)
62
+
63
+ ```typescript
64
+ import { usePlatform } from '@kb-labs/sdk';
65
+
66
+ const platform = usePlatform();
67
+
68
+ // Execute query
69
+ const users = platform.db.query<User>('SELECT * FROM users WHERE active = ?', [true]);
70
+
71
+ // Insert
72
+ platform.db.run('INSERT INTO users (name, email) VALUES (?, ?)', ['John', 'john@example.com']);
73
+
74
+ // Transaction
75
+ platform.db.transaction(() => {
76
+ platform.db.run('UPDATE accounts SET balance = balance - 100 WHERE id = ?', [1]);
77
+ platform.db.run('UPDATE accounts SET balance = balance + 100 WHERE id = ?', [2]);
78
+ });
79
+ ```
80
+
81
+ ### Standalone (Testing/Development)
82
+
83
+ ```typescript
84
+ import { createAdapter } from '@kb-labs/adapters-sqlite';
85
+
86
+ const db = createAdapter({ filename: ':memory:' });
87
+
88
+ db.run('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)');
89
+ db.run('INSERT INTO users (name) VALUES (?)', ['John']);
90
+
91
+ const users = db.query('SELECT * FROM users');
92
+ ```
93
+
94
+ ## Adapter Manifest
95
+
96
+ ```typescript
97
+ {
98
+ id: 'sqlite-database',
99
+ name: 'SQLite Database',
100
+ version: '1.0.0',
101
+ implements: 'ISQLDatabase',
102
+ capabilities: {
103
+ transactions: true,
104
+ search: true,
105
+ custom: {
106
+ prepared: true,
107
+ fts: true,
108
+ json: true,
109
+ },
110
+ },
111
+ }
112
+ ```
113
+
114
+ ## FAQ
115
+
116
+ <details>
117
+ <summary><strong>Q: How do I use in-memory database?</strong></summary>
118
+
119
+ Set filename to `:memory:`:
120
+
121
+ ```json
122
+ {
123
+ "adapterOptions": {
124
+ "db": {
125
+ "filename": ":memory:"
126
+ }
127
+ }
128
+ }
129
+ ```
130
+ </details>
131
+
132
+ <details>
133
+ <summary><strong>Q: How do I enable WAL mode for better concurrency?</strong></summary>
134
+
135
+ Run pragma after initialization:
136
+
137
+ ```typescript
138
+ db.run('PRAGMA journal_mode = WAL');
139
+ ```
140
+ </details>
141
+
142
+ <details>
143
+ <summary><strong>Q: How do I use full-text search?</strong></summary>
144
+
145
+ Create FTS5 virtual table:
146
+
147
+ ```typescript
148
+ db.run('CREATE VIRTUAL TABLE docs_fts USING fts5(content)');
149
+ db.run("INSERT INTO docs_fts VALUES ('hello world')");
150
+ const results = db.query("SELECT * FROM docs_fts WHERE docs_fts MATCH 'hello'");
151
+ ```
152
+ </details>
153
+
154
+ ## Related Adapters
155
+
156
+ | Adapter | Use Case |
157
+ |---------|----------|
158
+ | `@kb-labs/adapters-log-sqlite` | Log persistence using SQLite |
159
+ | `@kb-labs/adapters-mongodb` | Document database for complex data |
160
+
161
+ ## License
162
+
163
+ [KB Public License v1.1](../../LICENSE) - KB Labs Team
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Standard ESLint configuration template
3
+ *
4
+ * This is the canonical template for all @kb-labs packages.
5
+ * DO NOT modify this file locally - it is synced from @kb-labs/devkit
6
+ *
7
+ * Customization guidelines:
8
+ * - DevKit preset already includes all standard ignores
9
+ * - Only add project-specific ignores if absolutely necessary
10
+ * - Document why custom ignores are needed
11
+ *
12
+ * @see https://github.com/kb-labs/devkit#eslint-configuration
13
+ */
14
+ import nodePreset from '@kb-labs/devkit/eslint/node.js';
15
+
16
+ export default [
17
+ ...nodePreset,
18
+
19
+ // OPTIONAL: Add project-specific ignores only if needed
20
+ // DevKit preset already ignores: dist/, coverage/, node_modules/, *.d.ts, scripts/, etc.
21
+ // {
22
+ // ignores: [
23
+ // // Add ONLY project-specific patterns here
24
+ // // Example: '**/*.generated.ts',
25
+ // ]
26
+ // }
27
+ ];