trellis 3.1.35 → 3.2.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 (287) hide show
  1. package/CHANGELOG.md +23 -5
  2. package/README.md +63 -156
  3. package/bin/trellis.mjs +2 -75
  4. package/dist/{better-sqlite-backend-ahx5p0br.js → better-sqlite-backend-2P4F6AOJ.js} +91 -29
  5. package/dist/boot-middleware-MHLHFCUC.js +9 -0
  6. package/dist/browser/index.d.ts +18 -0
  7. package/dist/browser/index.d.ts.map +1 -0
  8. package/dist/browser/index.js +95 -0
  9. package/dist/{index-53f3b8p8.js → chunk-2W3MHTMG.js} +552 -213
  10. package/dist/chunk-44FFQKQX.js +142 -0
  11. package/dist/chunk-4HYPLFJD.js +150 -0
  12. package/dist/chunk-4XIVMVHC.js +361 -0
  13. package/dist/{index-yp88he8n.js → chunk-6CTA6MCE.js} +88 -64
  14. package/dist/chunk-6GEZ6DN5.js +394 -0
  15. package/dist/chunk-7ZFRVCUE.js +211 -0
  16. package/dist/chunk-CAG4FULI.js +121 -0
  17. package/dist/chunk-FF36CQHZ.js +61 -0
  18. package/dist/{index-h32txmxe.js → chunk-FKQO5A3H.js} +6 -13
  19. package/dist/{index-nq520y6k.js → chunk-FWRS4CSC.js} +46 -32
  20. package/dist/chunk-GFZCJ4EH.js +108 -0
  21. package/dist/chunk-GLM4HGN4.js +55 -0
  22. package/dist/{index-4cdr7x2x.js → chunk-GU374KWZ.js} +182 -111
  23. package/dist/chunk-H6JB3PZ3.js +45 -0
  24. package/dist/chunk-IZX2PLIB.js +1240 -0
  25. package/dist/chunk-J2TXUFCZ.js +289 -0
  26. package/dist/chunk-J3WYZO3Q.js +211 -0
  27. package/dist/{index-xzym9w0m.js → chunk-JA7AIHRK.js} +12 -7
  28. package/dist/chunk-JHHEXEDM.js +162 -0
  29. package/dist/chunk-JUEMDWLU.js +233 -0
  30. package/dist/chunk-KFQGP6VL.js +33 -0
  31. package/dist/chunk-KIJITUZB.js +419 -0
  32. package/dist/{index-4wxa8xz4.js → chunk-KQ4A2D2P.js} +162 -23
  33. package/dist/chunk-KSU2GW22.js +958 -0
  34. package/dist/{index-rv1p47gp.js → chunk-L5N5PR2S.js} +3015 -2480
  35. package/dist/{index-h9e2efx4.js → chunk-LNUIGRDZ.js} +71 -55
  36. package/dist/{index-skhn0agf.js → chunk-MLC5BUYO.js} +19 -20
  37. package/dist/chunk-MPXUVGT3.js +104 -0
  38. package/dist/chunk-N6MYZT4O.js +68 -0
  39. package/dist/chunk-O2AV5WMN.js +48 -0
  40. package/dist/chunk-PZ4XYZ4J.js +143 -0
  41. package/dist/chunk-QB5ISE47.js +419 -0
  42. package/dist/chunk-RSWUFTO2.js +857 -0
  43. package/dist/chunk-S3XLFZ27.js +1095 -0
  44. package/dist/{index-w5wccer3.js → chunk-S6GBJ2ZB.js} +28 -12
  45. package/dist/{index-7pjz3tsy.js → chunk-SGMDTWJJ.js} +57 -15
  46. package/dist/chunk-SPSPV5BC.js +390 -0
  47. package/dist/chunk-TCKXSOBP.js +123 -0
  48. package/dist/chunk-UBGUDMUV.js +59 -0
  49. package/dist/{index-wt8rz4gn.js → chunk-UQISRW6T.js} +97 -26
  50. package/dist/chunk-USEINYUL.js +12 -0
  51. package/dist/{index-bmyt7k8n.js → chunk-UZRUP7QW.js} +12 -4
  52. package/dist/{index-xhcp6xrn.js → chunk-VBYUTRXX.js} +695 -514
  53. package/dist/{index-vkpkfwhq.js → chunk-VDAKEOML.js} +234 -194
  54. package/dist/chunk-WXSWA3MV.js +0 -0
  55. package/dist/{index-n9f2qyh5.js → chunk-X5FLTRUB.js} +55 -33
  56. package/dist/{index-h7zxhhhh.js → chunk-XMQ7G77X.js} +46 -38
  57. package/dist/{index-w7ng765c.js → chunk-YCM7ZYEZ.js} +102 -49
  58. package/dist/cli/deploy-cli.d.ts +18 -0
  59. package/dist/cli/deploy-cli.d.ts.map +1 -0
  60. package/dist/cli/errors.d.ts +6 -0
  61. package/dist/cli/errors.d.ts.map +1 -0
  62. package/dist/cli/examples.d.ts +23 -0
  63. package/dist/cli/examples.d.ts.map +1 -0
  64. package/dist/cli/index.d.ts +1 -1
  65. package/dist/cli/index.d.ts.map +1 -1
  66. package/dist/cli/index.js +2426 -6225
  67. package/dist/client/index.browser.d.ts +29 -0
  68. package/dist/client/index.browser.d.ts.map +1 -0
  69. package/dist/client/index.browser.js +64 -0
  70. package/dist/client/index.d.ts +6 -1
  71. package/dist/client/index.d.ts.map +1 -1
  72. package/dist/client/index.js +41 -21
  73. package/dist/client/live.d.ts +67 -0
  74. package/dist/client/live.d.ts.map +1 -0
  75. package/dist/client/reactive.d.ts +31 -0
  76. package/dist/client/reactive.d.ts.map +1 -0
  77. package/dist/client/sdk.browser.d.ts +104 -0
  78. package/dist/client/sdk.browser.d.ts.map +1 -0
  79. package/dist/client/sdk.browser.js +9 -0
  80. package/dist/client/sdk.d.ts +26 -2
  81. package/dist/client/sdk.d.ts.map +1 -1
  82. package/dist/client/sdk.js +9 -0
  83. package/dist/client/vcs-client.d.ts +129 -0
  84. package/dist/client/vcs-client.d.ts.map +1 -0
  85. package/dist/cms/index.js +171 -163
  86. package/dist/{config-8hczw0rs.js → config-PFTP67TR.js} +8 -9
  87. package/dist/core/computation/index.d.ts +5 -0
  88. package/dist/core/computation/index.d.ts.map +1 -0
  89. package/dist/core/computation/rollup.d.ts +18 -0
  90. package/dist/core/computation/rollup.d.ts.map +1 -0
  91. package/dist/core/index.d.ts +5 -0
  92. package/dist/core/index.d.ts.map +1 -1
  93. package/dist/core/index.js +171 -104
  94. package/dist/core/kernel/boot-middleware.d.ts +10 -0
  95. package/dist/core/kernel/boot-middleware.d.ts.map +1 -0
  96. package/dist/core/kernel/logic-middleware.d.ts +7 -1
  97. package/dist/core/kernel/logic-middleware.d.ts.map +1 -1
  98. package/dist/core/kernel/trellis-kernel.d.ts.map +1 -1
  99. package/dist/core/ontology/types.d.ts +5 -0
  100. package/dist/core/ontology/types.d.ts.map +1 -1
  101. package/dist/core/persist/better-sqlite-backend.d.ts +9 -2
  102. package/dist/core/persist/better-sqlite-backend.d.ts.map +1 -1
  103. package/dist/core/persist/factory.d.ts +6 -7
  104. package/dist/core/persist/factory.d.ts.map +1 -1
  105. package/dist/core/persist/factory.js +2 -3
  106. package/dist/core/persist/sqljs-backend.js +2 -3
  107. package/dist/db/index.d.ts +4 -1
  108. package/dist/db/index.d.ts.map +1 -1
  109. package/dist/db/index.js +67 -54
  110. package/dist/db/inspector.js +11 -19
  111. package/dist/db/trellis.css +1 -1
  112. package/dist/decisions/index.js +9 -10
  113. package/dist/deploy-LQ7GUGJ5.js +9 -0
  114. package/dist/deploy-YNVG5E4E.js +9 -0
  115. package/dist/deploy-cli-24BCHAXY.js +67 -0
  116. package/dist/deploy-cli-C35HTITO.js +67 -0
  117. package/dist/embeddings/auto-embed.d.ts +2 -2
  118. package/dist/embeddings/auto-embed.d.ts.map +1 -1
  119. package/dist/embeddings/index.js +20 -22
  120. package/dist/embeddings/search.d.ts +2 -1
  121. package/dist/embeddings/search.d.ts.map +1 -1
  122. package/dist/embeddings/store.d.ts +25 -4
  123. package/dist/embeddings/store.d.ts.map +1 -1
  124. package/dist/engine.d.ts +59 -19
  125. package/dist/engine.d.ts.map +1 -1
  126. package/dist/import-UZEKXU3B.js +10 -0
  127. package/dist/index.js +102 -93
  128. package/dist/launch-explorer-HZ4ZJA4X.js +95 -0
  129. package/dist/links/index.js +24 -26
  130. package/dist/mcp/server.d.ts.map +1 -1
  131. package/dist/plugins/agent-memory/index.js +316 -0
  132. package/dist/plugins/idea-garden/index.js +165 -0
  133. package/dist/plugins/plan-approval/index.js +579 -0
  134. package/dist/plugins/proactive-watcher/index.js +194 -0
  135. package/dist/{index-2r4jxwnb.js → query-XYLTJYSA.js} +14 -15
  136. package/dist/react/index.js +39 -70
  137. package/dist/react/realtime.js +11 -0
  138. package/dist/react/schema-hooks.js +87 -0
  139. package/dist/realtime/broadcast-channel-transport.d.ts +43 -0
  140. package/dist/realtime/broadcast-channel-transport.d.ts.map +1 -0
  141. package/dist/realtime/durable-object-relay-transport.d.ts +96 -0
  142. package/dist/realtime/durable-object-relay-transport.d.ts.map +1 -0
  143. package/dist/realtime/index.d.ts +44 -0
  144. package/dist/realtime/index.d.ts.map +1 -0
  145. package/dist/realtime/index.js +40 -0
  146. package/dist/realtime/memory-hub.d.ts +32 -0
  147. package/dist/realtime/memory-hub.d.ts.map +1 -0
  148. package/dist/realtime/persistent-channel.d.ts +105 -0
  149. package/dist/realtime/persistent-channel.d.ts.map +1 -0
  150. package/dist/realtime/presence.d.ts +73 -0
  151. package/dist/realtime/presence.d.ts.map +1 -0
  152. package/dist/realtime/relay-persistence.d.ts +37 -0
  153. package/dist/realtime/relay-persistence.d.ts.map +1 -0
  154. package/dist/realtime/relay-persistence.js +107 -0
  155. package/dist/realtime/relay-server.d.ts +103 -0
  156. package/dist/realtime/relay-server.d.ts.map +1 -0
  157. package/dist/realtime/room.d.ts +98 -0
  158. package/dist/realtime/room.d.ts.map +1 -0
  159. package/dist/realtime/text.d.ts +73 -0
  160. package/dist/realtime/text.d.ts.map +1 -0
  161. package/dist/realtime/types.d.ts +89 -0
  162. package/dist/realtime/types.d.ts.map +1 -0
  163. package/dist/realtime/websocket-relay-transport.d.ts +28 -0
  164. package/dist/realtime/websocket-relay-transport.d.ts.map +1 -0
  165. package/dist/realtime.bundle.js +1100 -0
  166. package/dist/{remote-manager-xvbg4230.js → remote-manager-ODE3T2KR.js} +25 -15
  167. package/dist/scaffold/seed.d.ts.map +1 -1
  168. package/dist/scaffold/write.d.ts +1 -1
  169. package/dist/scaffold/write.d.ts.map +1 -1
  170. package/dist/schema/define.d.ts +137 -0
  171. package/dist/schema/define.d.ts.map +1 -0
  172. package/dist/schema/entity-projection.d.ts +34 -0
  173. package/dist/schema/entity-projection.d.ts.map +1 -0
  174. package/dist/schema/eql.d.ts +46 -0
  175. package/dist/schema/eql.d.ts.map +1 -0
  176. package/dist/schema/index.d.ts +21 -0
  177. package/dist/schema/index.d.ts.map +1 -0
  178. package/dist/schema/index.js +46 -0
  179. package/dist/schema/kernel-resolve.d.ts +21 -0
  180. package/dist/schema/kernel-resolve.d.ts.map +1 -0
  181. package/dist/schema/mutations.d.ts +20 -0
  182. package/dist/schema/mutations.d.ts.map +1 -0
  183. package/dist/schema/resolve.d.ts +21 -0
  184. package/dist/schema/resolve.d.ts.map +1 -0
  185. package/dist/server/deploy-meta.d.ts +25 -0
  186. package/dist/server/deploy-meta.d.ts.map +1 -0
  187. package/dist/server/deploy.d.ts +7 -2
  188. package/dist/server/deploy.d.ts.map +1 -1
  189. package/dist/server/index.d.ts +7 -2
  190. package/dist/server/index.d.ts.map +1 -1
  191. package/dist/server/index.js +100 -58
  192. package/dist/server/node-adapter.js +5 -104
  193. package/dist/server/realtime.d.ts +14 -3
  194. package/dist/server/realtime.d.ts.map +1 -1
  195. package/dist/server/server.d.ts +8 -16
  196. package/dist/server/server.d.ts.map +1 -1
  197. package/dist/server/sprites.d.ts +18 -1
  198. package/dist/server/sprites.d.ts.map +1 -1
  199. package/dist/server/tenancy.d.ts +4 -0
  200. package/dist/server/tenancy.d.ts.map +1 -1
  201. package/dist/server/usage-meter.d.ts +53 -0
  202. package/dist/server/usage-meter.d.ts.map +1 -0
  203. package/dist/server-MB3OPSPI.js +18 -0
  204. package/dist/server-ZVWGLLRF.js +18 -0
  205. package/dist/sprites-KQGTGM6W.js +27 -0
  206. package/dist/{sprites-vc4qbrp1.js → sprites-RU3E4XQN.js} +6 -7
  207. package/dist/svelte/index.d.ts +17 -0
  208. package/dist/svelte/index.d.ts.map +1 -0
  209. package/dist/svelte/index.js +51 -0
  210. package/dist/svelte/schema-hooks.d.ts +45 -0
  211. package/dist/svelte/schema-hooks.d.ts.map +1 -0
  212. package/dist/svelte/schema-hooks.js +71 -0
  213. package/dist/svelte/stores.d.ts +78 -0
  214. package/dist/svelte/stores.d.ts.map +1 -0
  215. package/dist/sync/http-transport.d.ts +3 -3
  216. package/dist/sync/http-transport.d.ts.map +1 -1
  217. package/dist/sync/index.d.ts +15 -1
  218. package/dist/sync/index.d.ts.map +1 -1
  219. package/dist/sync/index.js +617 -0
  220. package/dist/sync/memory-room.d.ts +37 -0
  221. package/dist/sync/memory-room.d.ts.map +1 -0
  222. package/dist/sync/memory-transport.d.ts +3 -3
  223. package/dist/sync/memory-transport.d.ts.map +1 -1
  224. package/dist/sync/partykit-room.d.ts +40 -0
  225. package/dist/sync/partykit-room.d.ts.map +1 -0
  226. package/dist/sync/partykit-transport.d.ts +84 -0
  227. package/dist/sync/partykit-transport.d.ts.map +1 -0
  228. package/dist/sync/room-core.d.ts +53 -0
  229. package/dist/sync/room-core.d.ts.map +1 -0
  230. package/dist/sync/sync-engine.d.ts +40 -2
  231. package/dist/sync/sync-engine.d.ts.map +1 -1
  232. package/dist/sync/sync-room-server.d.ts +39 -0
  233. package/dist/sync/sync-room-server.d.ts.map +1 -0
  234. package/dist/sync/types.d.ts +70 -3
  235. package/dist/sync/types.d.ts.map +1 -1
  236. package/dist/sync/vcs-sync-peer.d.ts +63 -0
  237. package/dist/sync/vcs-sync-peer.d.ts.map +1 -0
  238. package/dist/sync/ws-transport.d.ts +2 -2
  239. package/dist/sync/ws-transport.d.ts.map +1 -1
  240. package/dist/tenancy-NBLLGCNJ.js +14 -0
  241. package/dist/tenancy-POMWQP6M.js +16 -0
  242. package/dist/ui/client.html +355 -67
  243. package/dist/ui/launch-explorer.d.ts +22 -0
  244. package/dist/ui/launch-explorer.d.ts.map +1 -0
  245. package/dist/ui/server.d.ts +1 -1
  246. package/dist/ui/server.d.ts.map +1 -1
  247. package/dist/vcs/blob-store.d.ts.map +1 -1
  248. package/dist/vcs/idb-op-log.d.ts +67 -0
  249. package/dist/vcs/idb-op-log.d.ts.map +1 -0
  250. package/dist/vcs/index.d.ts +1 -0
  251. package/dist/vcs/index.d.ts.map +1 -1
  252. package/dist/vcs/index.js +81 -72
  253. package/dist/vcs/issue.d.ts +22 -5
  254. package/dist/vcs/issue.d.ts.map +1 -1
  255. package/dist/vcs/lane-materialize.d.ts +5 -0
  256. package/dist/vcs/lane-materialize.d.ts.map +1 -1
  257. package/dist/vcs/op-log.d.ts +28 -2
  258. package/dist/vcs/op-log.d.ts.map +1 -1
  259. package/dist/vcs/ops.d.ts +10 -0
  260. package/dist/vcs/ops.d.ts.map +1 -1
  261. package/dist/vcs/types.d.ts +2 -0
  262. package/dist/vcs/types.d.ts.map +1 -1
  263. package/dist/{vm-config-6xhsj6b3.js → vm-config-JI4OXKDQ.js} +9 -10
  264. package/dist/vue/hooks.d.ts +64 -0
  265. package/dist/vue/hooks.d.ts.map +1 -0
  266. package/dist/vue/index.d.ts +19 -0
  267. package/dist/vue/index.d.ts.map +1 -0
  268. package/dist/vue/index.js +59 -0
  269. package/dist/vue/schema-hooks.d.ts +41 -0
  270. package/dist/vue/schema-hooks.d.ts.map +1 -0
  271. package/dist/vue/schema-hooks.js +64 -0
  272. package/package.json +130 -17
  273. package/dist/deploy-999q207z.js +0 -10
  274. package/dist/engine-y0724kjq.js +0 -8
  275. package/dist/import-s2b8e0ft.js +0 -11
  276. package/dist/index-a76rekgs.js +0 -67
  277. package/dist/index-c9h37r6h.js +0 -1
  278. package/dist/index-hr9qvv77.js +0 -860
  279. package/dist/index-k5b0xskw.js +0 -1
  280. package/dist/index-nzb3am4f.js +0 -80
  281. package/dist/index-wncptktd.js +0 -292
  282. package/dist/index-y6a4kj0p.js +0 -43
  283. package/dist/index-yhwjgfvj.js +0 -342
  284. package/dist/sdk-bepky0xs.js +0 -16
  285. package/dist/server-szdjx0nt.js +0 -13
  286. package/dist/sqlite-backend-0vsmc6qj.js +0 -8
  287. package/dist/tenancy-pjm32b4v.js +0 -14
@@ -0,0 +1,1095 @@
1
+ import {
2
+ __esm,
3
+ __export,
4
+ __require
5
+ } from "./chunk-KFQGP6VL.js";
6
+
7
+ // src/embeddings/types.ts
8
+ var DEFAULT_MODEL_CONFIG;
9
+ var init_types = __esm({
10
+ "src/embeddings/types.ts"() {
11
+ "use strict";
12
+ DEFAULT_MODEL_CONFIG = {
13
+ modelName: "Xenova/all-MiniLM-L6-v2",
14
+ dimension: 384
15
+ };
16
+ }
17
+ });
18
+
19
+ // src/embeddings/model.ts
20
+ async function importTransformers() {
21
+ try {
22
+ return await import("@huggingface/transformers");
23
+ } catch {
24
+ try {
25
+ return await import("@xenova/transformers");
26
+ } catch {
27
+ throw new Error(
28
+ "No transformers library found. Install @huggingface/transformers (recommended) or @xenova/transformers."
29
+ );
30
+ }
31
+ }
32
+ }
33
+ async function loadModel(config = DEFAULT_MODEL_CONFIG) {
34
+ if (pipeline) return pipeline;
35
+ if (!loadPromise) {
36
+ loadPromise = (async () => {
37
+ const { pipeline: createPipeline } = await importTransformers();
38
+ const opts = {};
39
+ if (config.cacheDir) {
40
+ opts.cache_dir = config.cacheDir;
41
+ }
42
+ pipeline = await createPipeline(
43
+ "feature-extraction",
44
+ config.modelName,
45
+ opts
46
+ );
47
+ return pipeline;
48
+ })();
49
+ }
50
+ return loadPromise;
51
+ }
52
+ async function embed(text, config = DEFAULT_MODEL_CONFIG) {
53
+ const pipe = await loadModel(config);
54
+ const output = await pipe(text, { pooling: "mean", normalize: true });
55
+ return new Float32Array(output.data);
56
+ }
57
+ async function embedBatch(texts, config = DEFAULT_MODEL_CONFIG) {
58
+ if (texts.length === 0) return [];
59
+ const pipe = await loadModel(config);
60
+ const results = [];
61
+ const batchSize = 32;
62
+ for (let i = 0; i < texts.length; i += batchSize) {
63
+ const batch = texts.slice(i, i + batchSize);
64
+ for (const text of batch) {
65
+ const output = await pipe(text, { pooling: "mean", normalize: true });
66
+ results.push(new Float32Array(output.data));
67
+ }
68
+ }
69
+ return results;
70
+ }
71
+ function resetModel() {
72
+ pipeline = null;
73
+ loadPromise = null;
74
+ }
75
+ var pipeline, loadPromise;
76
+ var init_model = __esm({
77
+ "src/embeddings/model.ts"() {
78
+ "use strict";
79
+ init_types();
80
+ pipeline = null;
81
+ loadPromise = null;
82
+ }
83
+ });
84
+
85
+ // src/embeddings/store.ts
86
+ function rowToChunkMeta(row) {
87
+ return {
88
+ id: row.id,
89
+ entityId: row.entity_id,
90
+ content: row.content,
91
+ chunkType: row.chunk_type,
92
+ filePath: row.file_path ?? void 0,
93
+ updatedAt: row.updated_at
94
+ };
95
+ }
96
+ function cosineSimilarity(a, b) {
97
+ if (a.length !== b.length) return 0;
98
+ let dot = 0;
99
+ let normA = 0;
100
+ let normB = 0;
101
+ for (let i = 0; i < a.length; i++) {
102
+ dot += a[i] * b[i];
103
+ normA += a[i] * a[i];
104
+ normB += b[i] * b[i];
105
+ }
106
+ const denom = Math.sqrt(normA) * Math.sqrt(normB);
107
+ return denom === 0 ? 0 : dot / denom;
108
+ }
109
+ var SCHEMA_SQL, VectorStore;
110
+ var init_store = __esm({
111
+ "src/embeddings/store.ts"() {
112
+ "use strict";
113
+ SCHEMA_SQL = `
114
+ CREATE TABLE IF NOT EXISTS chunks (
115
+ id TEXT PRIMARY KEY,
116
+ entity_id TEXT NOT NULL,
117
+ content TEXT NOT NULL,
118
+ chunk_type TEXT NOT NULL,
119
+ file_path TEXT,
120
+ updated_at TEXT NOT NULL
121
+ );
122
+
123
+ CREATE TABLE IF NOT EXISTS vectors (
124
+ id TEXT PRIMARY KEY,
125
+ embedding BLOB NOT NULL,
126
+ FOREIGN KEY (id) REFERENCES chunks(id) ON DELETE CASCADE
127
+ );
128
+
129
+ CREATE INDEX IF NOT EXISTS idx_chunks_entity ON chunks(entity_id);
130
+ CREATE INDEX IF NOT EXISTS idx_chunks_type ON chunks(chunk_type);
131
+ CREATE INDEX IF NOT EXISTS idx_chunks_file ON chunks(file_path);
132
+ `;
133
+ VectorStore = class _VectorStore {
134
+ constructor(dbPath) {
135
+ this.dbPath = dbPath;
136
+ }
137
+ db;
138
+ stmts;
139
+ writes = 0;
140
+ /**
141
+ * Async factory — sql.js WASM init is async, but after bootstrap the store
142
+ * exposes a synchronous-style public API.
143
+ */
144
+ static async create(dbPath) {
145
+ const store = new _VectorStore(dbPath);
146
+ await store.bootstrap();
147
+ return store;
148
+ }
149
+ async bootstrap() {
150
+ let initSqlJs;
151
+ try {
152
+ const mod = await import("sql.js");
153
+ initSqlJs = mod.default ?? mod;
154
+ } catch {
155
+ throw new Error(
156
+ 'VectorStore requires the optional dependency "sql.js". Install it: npm install sql.js'
157
+ );
158
+ }
159
+ let sqljsDistDir = null;
160
+ if (typeof window === "undefined") {
161
+ try {
162
+ const moduleMod = await import("module");
163
+ const pathMod = await import("path");
164
+ const req = moduleMod.createRequire(import.meta.url);
165
+ const sqlJsEntry = req.resolve("sql.js");
166
+ sqljsDistDir = pathMod.dirname(sqlJsEntry);
167
+ } catch {
168
+ sqljsDistDir = null;
169
+ }
170
+ }
171
+ const SQL = await initSqlJs({
172
+ locateFile: (file) => {
173
+ if (typeof window !== "undefined") return `/sql-wasm/${file}`;
174
+ if (sqljsDistDir) return `${sqljsDistDir}/${file}`;
175
+ return file;
176
+ }
177
+ });
178
+ const existing = this.loadFromDisk();
179
+ this.db = existing ? new SQL.Database(existing) : new SQL.Database();
180
+ this.db.run("PRAGMA foreign_keys = ON;");
181
+ this.db.run(SCHEMA_SQL);
182
+ this.prepareStatements();
183
+ }
184
+ loadFromDisk() {
185
+ if (this.dbPath === ":memory:") return null;
186
+ try {
187
+ const fs = __require("fs");
188
+ if (!fs.existsSync(this.dbPath)) return null;
189
+ return new Uint8Array(fs.readFileSync(this.dbPath));
190
+ } catch {
191
+ return null;
192
+ }
193
+ }
194
+ flushToDisk() {
195
+ if (this.dbPath === ":memory:") return;
196
+ try {
197
+ const fs = __require("fs");
198
+ const path = __require("path");
199
+ const data = this.db.export();
200
+ this.prepareStatements();
201
+ fs.mkdirSync(path.dirname(this.dbPath), { recursive: true });
202
+ const tmp = `${this.dbPath}.tmp`;
203
+ fs.writeFileSync(tmp, Buffer.from(data));
204
+ fs.renameSync(tmp, this.dbPath);
205
+ } catch {
206
+ }
207
+ }
208
+ prepareStatements() {
209
+ this.stmts = {
210
+ upsertChunk: this.db.prepare(`
211
+ INSERT OR REPLACE INTO chunks (id, entity_id, content, chunk_type, file_path, updated_at)
212
+ VALUES ($id, $entityId, $content, $chunkType, $filePath, $updatedAt)
213
+ `),
214
+ upsertVector: this.db.prepare(`
215
+ INSERT OR REPLACE INTO vectors (id, embedding)
216
+ VALUES ($id, $embedding)
217
+ `),
218
+ deleteVector: this.db.prepare("DELETE FROM vectors WHERE id = $id"),
219
+ deleteChunk: this.db.prepare("DELETE FROM chunks WHERE id = $id"),
220
+ getChunkById: this.db.prepare("SELECT * FROM chunks WHERE id = $id"),
221
+ getChunkIdsByEntity: this.db.prepare(
222
+ "SELECT id FROM chunks WHERE entity_id = $entityId"
223
+ ),
224
+ getChunkIdsByFile: this.db.prepare(
225
+ "SELECT id FROM chunks WHERE file_path = $filePath"
226
+ ),
227
+ count: this.db.prepare("SELECT COUNT(*) AS cnt FROM chunks"),
228
+ countByType: this.db.prepare(
229
+ "SELECT chunk_type, COUNT(*) AS cnt FROM chunks GROUP BY chunk_type"
230
+ )
231
+ };
232
+ }
233
+ /**
234
+ * Insert or update a chunk with its embedding vector.
235
+ */
236
+ upsert(record) {
237
+ const embeddingBlob = new Uint8Array(record.embedding.buffer);
238
+ this.db.run("BEGIN");
239
+ try {
240
+ this.stmts.upsertChunk.run({
241
+ $id: record.id,
242
+ $entityId: record.entityId,
243
+ $content: record.content,
244
+ $chunkType: record.chunkType,
245
+ $filePath: record.filePath ?? null,
246
+ $updatedAt: record.updatedAt
247
+ });
248
+ this.stmts.upsertChunk.reset();
249
+ this.stmts.upsertVector.run({
250
+ $id: record.id,
251
+ $embedding: embeddingBlob
252
+ });
253
+ this.stmts.upsertVector.reset();
254
+ this.db.run("COMMIT");
255
+ } catch (e) {
256
+ this.db.run("ROLLBACK");
257
+ throw e;
258
+ }
259
+ this.tickFlush();
260
+ }
261
+ /**
262
+ * Batch upsert multiple records.
263
+ */
264
+ upsertBatch(records) {
265
+ if (records.length === 0) return;
266
+ this.db.run("BEGIN");
267
+ try {
268
+ for (const record of records) {
269
+ const embeddingBlob = new Uint8Array(record.embedding.buffer);
270
+ this.stmts.upsertChunk.run({
271
+ $id: record.id,
272
+ $entityId: record.entityId,
273
+ $content: record.content,
274
+ $chunkType: record.chunkType,
275
+ $filePath: record.filePath ?? null,
276
+ $updatedAt: record.updatedAt
277
+ });
278
+ this.stmts.upsertChunk.reset();
279
+ this.stmts.upsertVector.run({
280
+ $id: record.id,
281
+ $embedding: embeddingBlob
282
+ });
283
+ this.stmts.upsertVector.reset();
284
+ }
285
+ this.db.run("COMMIT");
286
+ } catch (e) {
287
+ this.db.run("ROLLBACK");
288
+ throw e;
289
+ }
290
+ this.tickFlush();
291
+ }
292
+ /**
293
+ * Delete a chunk and its vector by ID.
294
+ */
295
+ delete(id) {
296
+ this.stmts.deleteVector.run({ $id: id });
297
+ this.stmts.deleteVector.reset();
298
+ this.stmts.deleteChunk.run({ $id: id });
299
+ this.stmts.deleteChunk.reset();
300
+ this.tickFlush();
301
+ }
302
+ /**
303
+ * Delete all chunks for an entity.
304
+ */
305
+ deleteByEntity(entityId) {
306
+ const ids = this.runAll(this.stmts.getChunkIdsByEntity, {
307
+ $entityId: entityId
308
+ }).map((r) => r.id);
309
+ if (ids.length === 0) return;
310
+ this.db.run("BEGIN");
311
+ try {
312
+ for (const id of ids) {
313
+ this.stmts.deleteVector.run({ $id: id });
314
+ this.stmts.deleteVector.reset();
315
+ this.stmts.deleteChunk.run({ $id: id });
316
+ this.stmts.deleteChunk.reset();
317
+ }
318
+ this.db.run("COMMIT");
319
+ } catch (e) {
320
+ this.db.run("ROLLBACK");
321
+ throw e;
322
+ }
323
+ this.tickFlush();
324
+ }
325
+ /**
326
+ * Delete all chunks associated with a file path.
327
+ */
328
+ deleteByFile(filePath) {
329
+ const ids = this.runAll(this.stmts.getChunkIdsByFile, {
330
+ $filePath: filePath
331
+ }).map((r) => r.id);
332
+ if (ids.length === 0) return;
333
+ this.db.run("BEGIN");
334
+ try {
335
+ for (const id of ids) {
336
+ this.stmts.deleteVector.run({ $id: id });
337
+ this.stmts.deleteVector.reset();
338
+ this.stmts.deleteChunk.run({ $id: id });
339
+ this.stmts.deleteChunk.reset();
340
+ }
341
+ this.db.run("COMMIT");
342
+ } catch (e) {
343
+ this.db.run("ROLLBACK");
344
+ throw e;
345
+ }
346
+ this.tickFlush();
347
+ }
348
+ /**
349
+ * Get a chunk by ID (without vector).
350
+ */
351
+ getChunk(id) {
352
+ const row = this.runOne(this.stmts.getChunkById, { $id: id });
353
+ return row ? rowToChunkMeta(row) : null;
354
+ }
355
+ /**
356
+ * Search for chunks similar to the query vector.
357
+ * Uses brute-force cosine similarity scan.
358
+ */
359
+ search(queryVector, opts = {}) {
360
+ const limit = opts.limit ?? 10;
361
+ const minScore = opts.minScore ?? 0;
362
+ const conditions = [];
363
+ const params = {};
364
+ if (opts.types && opts.types.length > 0) {
365
+ const placeholders = opts.types.map((_, i) => `$type${i}`).join(", ");
366
+ conditions.push(`c.chunk_type IN (${placeholders})`);
367
+ opts.types.forEach((t, i) => {
368
+ params[`$type${i}`] = t;
369
+ });
370
+ }
371
+ if (opts.filePrefix) {
372
+ conditions.push("c.file_path LIKE $filePrefix");
373
+ params.$filePrefix = `${opts.filePrefix}%`;
374
+ }
375
+ const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
376
+ const sql = `
377
+ SELECT c.id, c.entity_id, c.content, c.chunk_type, c.file_path, c.updated_at,
378
+ v.embedding
379
+ FROM chunks c
380
+ JOIN vectors v ON c.id = v.id
381
+ ${where}
382
+ `;
383
+ const stmt = this.db.prepare(sql);
384
+ const rows = this.runAll(stmt, params);
385
+ stmt.free();
386
+ const scored = [];
387
+ for (const row of rows) {
388
+ const embeddingBytes = row.embedding;
389
+ const ownedBuf = embeddingBytes.buffer.slice(
390
+ embeddingBytes.byteOffset,
391
+ embeddingBytes.byteOffset + embeddingBytes.byteLength
392
+ );
393
+ const storedVec = new Float32Array(ownedBuf);
394
+ const score = cosineSimilarity(queryVector, storedVec);
395
+ if (score >= minScore) {
396
+ scored.push({ chunk: rowToChunkMeta(row), score });
397
+ }
398
+ }
399
+ scored.sort((a, b) => b.score - a.score);
400
+ return scored.slice(0, limit);
401
+ }
402
+ /**
403
+ * Get total count of chunks in the store.
404
+ */
405
+ count() {
406
+ const row = this.runOne(this.stmts.count);
407
+ return Number(row?.cnt ?? 0);
408
+ }
409
+ /**
410
+ * Get count by chunk type.
411
+ */
412
+ countByType() {
413
+ const rows = this.runAll(this.stmts.countByType);
414
+ const result = {};
415
+ for (const row of rows) {
416
+ result[row.chunk_type] = row.cnt;
417
+ }
418
+ return result;
419
+ }
420
+ /**
421
+ * Clear all data from the store.
422
+ */
423
+ clear() {
424
+ this.db.run("DELETE FROM vectors");
425
+ this.db.run("DELETE FROM chunks");
426
+ this.tickFlush();
427
+ }
428
+ /**
429
+ * Force a write of the in-memory DB image to disk.
430
+ */
431
+ flush() {
432
+ this.flushToDisk();
433
+ }
434
+ /**
435
+ * Close the database connection.
436
+ */
437
+ close() {
438
+ try {
439
+ this.flushToDisk();
440
+ } finally {
441
+ for (const s of Object.values(this.stmts ?? {})) s?.free?.();
442
+ this.db?.close?.();
443
+ }
444
+ }
445
+ // ---------------------------------------------------------------------------
446
+ // Helpers
447
+ // ---------------------------------------------------------------------------
448
+ runAll(stmt, params = {}) {
449
+ stmt.bind(params);
450
+ const rows = [];
451
+ while (stmt.step()) rows.push(stmt.getAsObject());
452
+ stmt.reset();
453
+ return rows;
454
+ }
455
+ runOne(stmt, params = {}) {
456
+ stmt.bind(params);
457
+ const has = stmt.step();
458
+ const row = has ? stmt.getAsObject() : void 0;
459
+ stmt.reset();
460
+ return row;
461
+ }
462
+ tickFlush() {
463
+ if (++this.writes % 50 === 0) this.flushToDisk();
464
+ }
465
+ };
466
+ }
467
+ });
468
+
469
+ // src/embeddings/chunker.ts
470
+ function chunkIssue(issue) {
471
+ const now = (/* @__PURE__ */ new Date()).toISOString();
472
+ const chunks = [];
473
+ if (issue.title) {
474
+ chunks.push({
475
+ id: `issue:${issue.id}:title`,
476
+ entityId: `issue:${issue.id}`,
477
+ content: issue.title,
478
+ chunkType: "issue_title",
479
+ updatedAt: now
480
+ });
481
+ }
482
+ if (issue.description) {
483
+ chunks.push({
484
+ id: `issue:${issue.id}:desc`,
485
+ entityId: `issue:${issue.id}`,
486
+ content: issue.description,
487
+ chunkType: "issue_desc",
488
+ updatedAt: now
489
+ });
490
+ }
491
+ return chunks;
492
+ }
493
+ function chunkDecision(decision) {
494
+ const parts = [];
495
+ parts.push(`Decision ${decision.id}: ${decision.toolName}`);
496
+ if (decision.rationale) parts.push(`Rationale: ${decision.rationale}`);
497
+ if (decision.context) parts.push(`Context: ${decision.context}`);
498
+ if (decision.outputSummary) parts.push(`Output: ${decision.outputSummary}`);
499
+ const content = parts.join("\n");
500
+ if (!content.trim()) return [];
501
+ return [
502
+ {
503
+ id: `decision:${decision.id}:rationale`,
504
+ entityId: `decision:${decision.id}`,
505
+ content,
506
+ chunkType: "decision_rationale",
507
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
508
+ }
509
+ ];
510
+ }
511
+ function chunkMilestone(milestone) {
512
+ if (!milestone.message) return [];
513
+ return [
514
+ {
515
+ id: `milestone:${milestone.id}:msg`,
516
+ entityId: `milestone:${milestone.id}`,
517
+ content: milestone.message,
518
+ chunkType: "milestone_msg",
519
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
520
+ }
521
+ ];
522
+ }
523
+ function chunkMarkdown(filePath, content) {
524
+ if (!content.trim()) return [];
525
+ const entityId = `file:${filePath}`;
526
+ const now = (/* @__PURE__ */ new Date()).toISOString();
527
+ const sections = splitByHeadings(content);
528
+ const chunks = [];
529
+ for (let i = 0; i < sections.length; i++) {
530
+ const section = sections[i];
531
+ if (!section.text.trim()) continue;
532
+ if (section.text.length <= MAX_CHUNK_CHARS) {
533
+ chunks.push({
534
+ id: `${entityId}:section:${i}`,
535
+ entityId,
536
+ content: section.text,
537
+ chunkType: "markdown",
538
+ filePath,
539
+ updatedAt: now
540
+ });
541
+ } else {
542
+ const windows = slidingWindow(section.text);
543
+ for (let w = 0; w < windows.length; w++) {
544
+ chunks.push({
545
+ id: `${entityId}:section:${i}:w${w}`,
546
+ entityId,
547
+ content: windows[w],
548
+ chunkType: "markdown",
549
+ filePath,
550
+ updatedAt: now
551
+ });
552
+ }
553
+ }
554
+ }
555
+ return chunks;
556
+ }
557
+ function chunkCodeEntities(filePath, declarations) {
558
+ const now = (/* @__PURE__ */ new Date()).toISOString();
559
+ const chunks = [];
560
+ for (const decl of declarations) {
561
+ const parts = [];
562
+ if (decl.docComment) parts.push(decl.docComment);
563
+ parts.push(`${decl.kind} ${decl.name}`);
564
+ parts.push(decl.signature);
565
+ const content = parts.join("\n").slice(0, MAX_CHUNK_CHARS);
566
+ chunks.push({
567
+ id: `symbol:${filePath}#${decl.name}`,
568
+ entityId: `symbol:${filePath}#${decl.name}`,
569
+ content,
570
+ chunkType: "code_entity",
571
+ filePath,
572
+ updatedAt: now
573
+ });
574
+ }
575
+ return chunks;
576
+ }
577
+ function chunkDocComments(filePath, comments) {
578
+ if (comments.length === 0) return [];
579
+ const entityId = `file:${filePath}`;
580
+ const now = (/* @__PURE__ */ new Date()).toISOString();
581
+ const chunks = [];
582
+ for (let i = 0; i < comments.length; i++) {
583
+ const comment = comments[i];
584
+ if (!comment.text.trim()) continue;
585
+ chunks.push({
586
+ id: `${entityId}:doc:${i}`,
587
+ entityId,
588
+ content: comment.text.slice(0, MAX_CHUNK_CHARS),
589
+ chunkType: "doc_comment",
590
+ filePath,
591
+ updatedAt: now
592
+ });
593
+ }
594
+ return chunks;
595
+ }
596
+ function chunkSummary(filePath, content) {
597
+ if (!content.trim()) return [];
598
+ const entityId = `file:${filePath}`;
599
+ const now = (/* @__PURE__ */ new Date()).toISOString();
600
+ if (content.length <= MAX_CHUNK_CHARS) {
601
+ return [
602
+ {
603
+ id: `${entityId}:summary`,
604
+ entityId,
605
+ content,
606
+ chunkType: "summary_md",
607
+ filePath,
608
+ updatedAt: now
609
+ }
610
+ ];
611
+ }
612
+ return chunkMarkdown(filePath, content).map((c) => ({
613
+ ...c,
614
+ chunkType: "summary_md"
615
+ }));
616
+ }
617
+ function chunkFile(filePath, content) {
618
+ if (!content.trim()) return [];
619
+ const ext = filePath.split(".").pop()?.toLowerCase() ?? "";
620
+ if (filePath.endsWith("summary.md")) {
621
+ return chunkSummary(filePath, content);
622
+ }
623
+ if (ext === "md") {
624
+ return chunkMarkdown(filePath, content);
625
+ }
626
+ return [];
627
+ }
628
+ function splitByHeadings(content) {
629
+ const lines = content.split("\n");
630
+ const sections = [];
631
+ let currentSection = { text: "" };
632
+ for (const line of lines) {
633
+ if (/^#{1,3}\s/.test(line)) {
634
+ if (currentSection.text.trim()) {
635
+ sections.push(currentSection);
636
+ }
637
+ currentSection = { heading: line, text: line + "\n" };
638
+ } else {
639
+ currentSection.text += line + "\n";
640
+ }
641
+ }
642
+ if (currentSection.text.trim()) {
643
+ sections.push(currentSection);
644
+ }
645
+ return sections;
646
+ }
647
+ function slidingWindow(text) {
648
+ const windows = [];
649
+ let start = 0;
650
+ while (start < text.length) {
651
+ const end = Math.min(start + MAX_CHUNK_CHARS, text.length);
652
+ windows.push(text.slice(start, end));
653
+ if (end >= text.length) break;
654
+ start += MAX_CHUNK_CHARS - OVERLAP_CHARS;
655
+ }
656
+ return windows;
657
+ }
658
+ var MAX_CHUNK_CHARS, OVERLAP_CHARS;
659
+ var init_chunker = __esm({
660
+ "src/embeddings/chunker.ts"() {
661
+ "use strict";
662
+ MAX_CHUNK_CHARS = 512;
663
+ OVERLAP_CHARS = 64;
664
+ }
665
+ });
666
+
667
+ // src/embeddings/search.ts
668
+ import { join } from "path";
669
+ import { readFileSync, existsSync } from "fs";
670
+ var EmbeddingManager;
671
+ var init_search = __esm({
672
+ "src/embeddings/search.ts"() {
673
+ "use strict";
674
+ init_store();
675
+ init_model();
676
+ init_chunker();
677
+ EmbeddingManager = class _EmbeddingManager {
678
+ store;
679
+ embedFn;
680
+ constructor(store, embedFn) {
681
+ this.store = store;
682
+ this.embedFn = embedFn;
683
+ }
684
+ static async create(dbPath, embedFn) {
685
+ const store = await VectorStore.create(dbPath);
686
+ return new _EmbeddingManager(store, embedFn ?? embed);
687
+ }
688
+ /**
689
+ * Full reindex: clear store, re-chunk all entities, embed, and insert.
690
+ */
691
+ async reindex(engine) {
692
+ this.store.clear();
693
+ const allChunks = [];
694
+ const issues = engine.listIssues();
695
+ for (const issue of issues) {
696
+ allChunks.push(...chunkIssue(issue));
697
+ }
698
+ const milestones = engine.listMilestones();
699
+ for (const ms of milestones) {
700
+ allChunks.push(...chunkMilestone(ms));
701
+ }
702
+ if (engine.queryDecisions) {
703
+ const decisions = engine.queryDecisions();
704
+ for (const dec of decisions) {
705
+ allChunks.push(...chunkDecision(dec));
706
+ }
707
+ }
708
+ const rootPath = engine.getRootPath();
709
+ const trackedFiles = engine.trackedFiles();
710
+ for (const tf of trackedFiles) {
711
+ try {
712
+ const absPath = join(rootPath, tf.path);
713
+ if (!existsSync(absPath)) continue;
714
+ const content = readFileSync(absPath, "utf-8");
715
+ allChunks.push(...chunkFile(tf.path, content));
716
+ } catch {
717
+ }
718
+ }
719
+ if (engine.parseFile) {
720
+ for (const tf of trackedFiles) {
721
+ const ext = tf.path.split(".").pop()?.toLowerCase() ?? "";
722
+ if (![
723
+ "ts",
724
+ "js",
725
+ "tsx",
726
+ "jsx",
727
+ "py",
728
+ "go",
729
+ "rs",
730
+ "rb",
731
+ "java",
732
+ "cs"
733
+ ].includes(ext)) {
734
+ continue;
735
+ }
736
+ try {
737
+ const parsed = engine.parseFile(tf.path);
738
+ if (parsed && Array.isArray(parsed.entities)) {
739
+ const declarations = parsed.entities.map((e) => ({
740
+ id: e.id ?? e.name,
741
+ name: e.name,
742
+ kind: e.kind,
743
+ signature: e.signature ?? e.rawText?.split("\n")[0] ?? "",
744
+ docComment: e.docComment
745
+ }));
746
+ allChunks.push(...chunkCodeEntities(tf.path, declarations));
747
+ }
748
+ } catch {
749
+ }
750
+ }
751
+ }
752
+ const records = [];
753
+ for (const chunk of allChunks) {
754
+ try {
755
+ const vector = await this.embedFn(chunk.content);
756
+ records.push({ ...chunk, embedding: vector });
757
+ } catch {
758
+ }
759
+ }
760
+ this.store.upsertBatch(records);
761
+ return { chunks: records.length };
762
+ }
763
+ /**
764
+ * Incrementally index a single file (on file change).
765
+ */
766
+ async indexFile(filePath, content, engine) {
767
+ this.store.deleteByFile(filePath);
768
+ const chunks = chunkFile(filePath, content);
769
+ if (engine?.parseFile) {
770
+ const ext = filePath.split(".").pop()?.toLowerCase() ?? "";
771
+ if ([
772
+ "ts",
773
+ "js",
774
+ "tsx",
775
+ "jsx",
776
+ "py",
777
+ "go",
778
+ "rs",
779
+ "rb",
780
+ "java",
781
+ "cs"
782
+ ].includes(ext)) {
783
+ try {
784
+ const parsed = engine.parseFile(filePath);
785
+ if (parsed && Array.isArray(parsed.entities)) {
786
+ const declarations = parsed.entities.map((e) => ({
787
+ id: e.id ?? e.name,
788
+ name: e.name,
789
+ kind: e.kind,
790
+ signature: e.signature ?? e.rawText?.split("\n")[0] ?? "",
791
+ docComment: e.docComment
792
+ }));
793
+ chunks.push(...chunkCodeEntities(filePath, declarations));
794
+ }
795
+ } catch {
796
+ }
797
+ }
798
+ }
799
+ const records = [];
800
+ for (const chunk of chunks) {
801
+ try {
802
+ const vector = await this.embedFn(chunk.content);
803
+ records.push({ ...chunk, embedding: vector });
804
+ } catch {
805
+ }
806
+ }
807
+ if (records.length > 0) {
808
+ this.store.upsertBatch(records);
809
+ }
810
+ return records.length;
811
+ }
812
+ /**
813
+ * Index an issue (on create/update).
814
+ */
815
+ async indexIssue(issue) {
816
+ this.store.deleteByEntity(`issue:${issue.id}`);
817
+ const chunks = chunkIssue(issue);
818
+ const records = [];
819
+ for (const chunk of chunks) {
820
+ try {
821
+ const vector = await this.embedFn(chunk.content);
822
+ records.push({ ...chunk, embedding: vector });
823
+ } catch {
824
+ }
825
+ }
826
+ if (records.length > 0) {
827
+ this.store.upsertBatch(records);
828
+ }
829
+ return records.length;
830
+ }
831
+ /**
832
+ * Index a milestone (on create).
833
+ */
834
+ async indexMilestone(milestone) {
835
+ this.store.deleteByEntity(`milestone:${milestone.id}`);
836
+ const chunks = chunkMilestone(milestone);
837
+ const records = [];
838
+ for (const chunk of chunks) {
839
+ try {
840
+ const vector = await this.embedFn(chunk.content);
841
+ records.push({ ...chunk, embedding: vector });
842
+ } catch {
843
+ }
844
+ }
845
+ if (records.length > 0) {
846
+ this.store.upsertBatch(records);
847
+ }
848
+ return records.length;
849
+ }
850
+ /**
851
+ * Semantic search: embed query → vector search → ranked results.
852
+ */
853
+ async search(query, opts) {
854
+ const queryVector = await this.embedFn(query);
855
+ return this.store.search(queryVector, opts);
856
+ }
857
+ /**
858
+ * Remove all data for a file.
859
+ */
860
+ removeFile(filePath) {
861
+ this.store.deleteByFile(filePath);
862
+ }
863
+ /**
864
+ * Get store statistics.
865
+ */
866
+ stats() {
867
+ return {
868
+ total: this.store.count(),
869
+ byType: this.store.countByType()
870
+ };
871
+ }
872
+ /**
873
+ * Close the store.
874
+ */
875
+ close() {
876
+ this.store.close();
877
+ }
878
+ };
879
+ }
880
+ });
881
+
882
+ // src/embeddings/auto-embed.ts
883
+ function entitySummaryText(entityId, facts, links) {
884
+ const type = facts.find((f) => f.a === "type")?.v ?? "Entity";
885
+ const name = facts.find((f) => f.a === "name" || f.a === "title")?.v ?? entityId;
886
+ const parts = [`${type}: ${name} (${entityId})`];
887
+ const attrs = facts.filter(
888
+ (f) => !["type", "name", "title", "createdAt", "updatedAt"].includes(f.a)
889
+ );
890
+ if (attrs.length > 0) {
891
+ parts.push(attrs.map((f) => ` ${f.a} = ${f.v}`).join("\n"));
892
+ }
893
+ if (links.length > 0) {
894
+ parts.push("Relations:");
895
+ parts.push(links.map((l) => ` ${l.a} \u2192 ${l.e2}`).join("\n"));
896
+ }
897
+ return parts.join("\n");
898
+ }
899
+ async function createAutoEmbedMiddleware(options) {
900
+ const store = await VectorStore.create(options.dbPath);
901
+ const embedFn = options.embedFn ?? embed;
902
+ const embedIndividual = options.embedIndividualFacts ?? false;
903
+ return {
904
+ name: "auto-embed",
905
+ handleOp: async (op, ctx, next) => {
906
+ await next(op, ctx);
907
+ try {
908
+ await _processOp(op, store, embedFn, embedIndividual);
909
+ } catch {
910
+ }
911
+ },
912
+ close: () => {
913
+ store.close();
914
+ }
915
+ };
916
+ }
917
+ async function _processOp(op, store, embedFn, embedIndividual) {
918
+ const now = (/* @__PURE__ */ new Date()).toISOString();
919
+ const entityIds = /* @__PURE__ */ new Set();
920
+ if (op.facts) for (const f of op.facts) entityIds.add(f.e);
921
+ if (op.links)
922
+ for (const l of op.links) {
923
+ entityIds.add(l.e1);
924
+ entityIds.add(l.e2);
925
+ }
926
+ if (op.deleteFacts) for (const f of op.deleteFacts) entityIds.add(f.e);
927
+ if (op.deleteLinks)
928
+ for (const l of op.deleteLinks) {
929
+ entityIds.add(l.e1);
930
+ entityIds.add(l.e2);
931
+ }
932
+ let mutated = false;
933
+ if (op.deleteFacts || op.deleteLinks) {
934
+ for (const eid of entityIds) {
935
+ store.deleteByEntity(eid);
936
+ }
937
+ mutated = true;
938
+ }
939
+ if (op.facts && op.facts.length > 0) {
940
+ const factsByEntity = /* @__PURE__ */ new Map();
941
+ for (const f of op.facts) {
942
+ const existing = factsByEntity.get(f.e) ?? [];
943
+ existing.push(f);
944
+ factsByEntity.set(f.e, existing);
945
+ }
946
+ const linksByEntity = /* @__PURE__ */ new Map();
947
+ if (op.links) {
948
+ for (const l of op.links) {
949
+ const existing = linksByEntity.get(l.e1) ?? [];
950
+ existing.push(l);
951
+ linksByEntity.set(l.e1, existing);
952
+ }
953
+ }
954
+ const records = [];
955
+ for (const [eid, facts] of factsByEntity) {
956
+ const links = linksByEntity.get(eid) ?? [];
957
+ const summaryText = entitySummaryText(eid, facts, links);
958
+ if (summaryText.trim()) {
959
+ try {
960
+ const vector = await embedFn(summaryText);
961
+ records.push({
962
+ id: `entity:${eid}:summary`,
963
+ entityId: eid,
964
+ content: summaryText,
965
+ chunkType: "summary_md",
966
+ updatedAt: now,
967
+ embedding: vector
968
+ });
969
+ } catch {
970
+ }
971
+ }
972
+ if (embedIndividual) {
973
+ for (const fact of facts) {
974
+ if (["type", "createdAt", "updatedAt"].includes(fact.a)) continue;
975
+ const text = `${fact.a}: ${fact.v}`;
976
+ try {
977
+ const vector = await embedFn(text);
978
+ records.push({
979
+ id: `entity:${eid}:fact:${fact.a}`,
980
+ entityId: eid,
981
+ content: text,
982
+ chunkType: "doc_comment",
983
+ updatedAt: now,
984
+ embedding: vector
985
+ });
986
+ } catch {
987
+ }
988
+ }
989
+ }
990
+ }
991
+ if (records.length > 0) {
992
+ store.upsertBatch(records);
993
+ mutated = true;
994
+ }
995
+ }
996
+ if (mutated) {
997
+ store.flush();
998
+ }
999
+ }
1000
+ async function buildRAGContext(query, vectorStore, embedFn = embed, options) {
1001
+ const maxChunks = options?.maxChunks ?? 10;
1002
+ const maxTokens = options?.maxTokens ?? 4e3;
1003
+ const minScore = options?.minScore ?? 0.1;
1004
+ const queryVector = await embedFn(query);
1005
+ const results = vectorStore.search(queryVector, {
1006
+ limit: maxChunks * 2,
1007
+ minScore
1008
+ });
1009
+ const chunks = [];
1010
+ let totalChars = 0;
1011
+ for (const r of results) {
1012
+ if (chunks.length >= maxChunks) break;
1013
+ if (totalChars + r.chunk.content.length > maxTokens * 4) break;
1014
+ chunks.push({
1015
+ content: r.chunk.content,
1016
+ entityId: r.chunk.entityId,
1017
+ score: r.score,
1018
+ chunkType: r.chunk.chunkType
1019
+ });
1020
+ totalChars += r.chunk.content.length;
1021
+ }
1022
+ return {
1023
+ query,
1024
+ chunks,
1025
+ estimatedTokens: Math.ceil(totalChars / 4)
1026
+ };
1027
+ }
1028
+ var init_auto_embed = __esm({
1029
+ "src/embeddings/auto-embed.ts"() {
1030
+ "use strict";
1031
+ init_store();
1032
+ init_model();
1033
+ }
1034
+ });
1035
+
1036
+ // src/embeddings/index.ts
1037
+ var embeddings_exports = {};
1038
+ __export(embeddings_exports, {
1039
+ DEFAULT_MODEL_CONFIG: () => DEFAULT_MODEL_CONFIG,
1040
+ EmbeddingManager: () => EmbeddingManager,
1041
+ VectorStore: () => VectorStore,
1042
+ buildRAGContext: () => buildRAGContext,
1043
+ chunkCodeEntities: () => chunkCodeEntities,
1044
+ chunkDecision: () => chunkDecision,
1045
+ chunkDocComments: () => chunkDocComments,
1046
+ chunkFile: () => chunkFile,
1047
+ chunkIssue: () => chunkIssue,
1048
+ chunkMarkdown: () => chunkMarkdown,
1049
+ chunkMilestone: () => chunkMilestone,
1050
+ chunkSummary: () => chunkSummary,
1051
+ cosineSimilarity: () => cosineSimilarity,
1052
+ createAutoEmbedMiddleware: () => createAutoEmbedMiddleware,
1053
+ embed: () => embed,
1054
+ embedBatch: () => embedBatch,
1055
+ loadModel: () => loadModel,
1056
+ resetModel: () => resetModel,
1057
+ slidingWindow: () => slidingWindow
1058
+ });
1059
+ var init_embeddings = __esm({
1060
+ "src/embeddings/index.ts"() {
1061
+ init_types();
1062
+ init_model();
1063
+ init_store();
1064
+ init_search();
1065
+ init_auto_embed();
1066
+ init_chunker();
1067
+ }
1068
+ });
1069
+
1070
+ export {
1071
+ DEFAULT_MODEL_CONFIG,
1072
+ loadModel,
1073
+ embed,
1074
+ embedBatch,
1075
+ resetModel,
1076
+ init_model,
1077
+ VectorStore,
1078
+ cosineSimilarity,
1079
+ init_store,
1080
+ chunkIssue,
1081
+ chunkDecision,
1082
+ chunkMilestone,
1083
+ chunkMarkdown,
1084
+ chunkCodeEntities,
1085
+ chunkDocComments,
1086
+ chunkSummary,
1087
+ chunkFile,
1088
+ slidingWindow,
1089
+ EmbeddingManager,
1090
+ createAutoEmbedMiddleware,
1091
+ buildRAGContext,
1092
+ init_auto_embed,
1093
+ embeddings_exports,
1094
+ init_embeddings
1095
+ };