toolnet-memory 0.2.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 (329) hide show
  1. package/.env.example +28 -0
  2. package/README.md +147 -0
  3. package/bin/toolnet-memory +415 -0
  4. package/dist/packages/cli/commands.js +1 -0
  5. package/dist/packages/cli/index.js +1 -0
  6. package/dist/packages/sdk/client.js +78 -0
  7. package/dist/packages/sdk/index.js +1 -0
  8. package/dist/packages/sdk/types.js +1 -0
  9. package/dist/src/api/index.js +1 -0
  10. package/dist/src/api/routes/health.js +1 -0
  11. package/dist/src/api/routes/index.js +1 -0
  12. package/dist/src/api/routes/memory.js +1 -0
  13. package/dist/src/api/routes/projects.js +1 -0
  14. package/dist/src/api/routes/search.js +1 -0
  15. package/dist/src/api/server.js +1 -0
  16. package/dist/src/capture/activity-capture.js +21 -0
  17. package/dist/src/capture/command-capture.js +12 -0
  18. package/dist/src/capture/error-capture.js +14 -0
  19. package/dist/src/capture/event-deduplicator.js +28 -0
  20. package/dist/src/capture/event-queue.js +20 -0
  21. package/dist/src/capture/file-capture.js +23 -0
  22. package/dist/src/capture/index.js +8 -0
  23. package/dist/src/capture/session-capture.js +18 -0
  24. package/dist/src/capture/tool-capture.js +13 -0
  25. package/dist/src/code-intelligence/analysis/analysis-engine.js +26 -0
  26. package/dist/src/code-intelligence/analysis/dead-code-analyzer.js +127 -0
  27. package/dist/src/code-intelligence/analysis/dependency-analyzer.js +66 -0
  28. package/dist/src/code-intelligence/analysis/index.js +4 -0
  29. package/dist/src/code-intelligence/analysis/types.js +1 -0
  30. package/dist/src/code-intelligence/architecture/architecture-engine.js +48 -0
  31. package/dist/src/code-intelligence/architecture/clusters.js +322 -0
  32. package/dist/src/code-intelligence/architecture/entry-points.js +150 -0
  33. package/dist/src/code-intelligence/architecture/hotspots.js +136 -0
  34. package/dist/src/code-intelligence/architecture/index.js +6 -0
  35. package/dist/src/code-intelligence/architecture/layers.js +197 -0
  36. package/dist/src/code-intelligence/architecture/types.js +1 -0
  37. package/dist/src/code-intelligence/chunks/index.js +2 -0
  38. package/dist/src/code-intelligence/chunks/smart-chunker.js +125 -0
  39. package/dist/src/code-intelligence/chunks/types.js +1 -0
  40. package/dist/src/code-intelligence/git/git-diff.js +109 -0
  41. package/dist/src/code-intelligence/git/index.js +1 -0
  42. package/dist/src/code-intelligence/graph/architecture.js +26 -0
  43. package/dist/src/code-intelligence/graph/graph-builder.js +213 -0
  44. package/dist/src/code-intelligence/graph/graph-store.js +57 -0
  45. package/dist/src/code-intelligence/graph/index.js +1 -0
  46. package/dist/src/code-intelligence/graph/relationships.js +1 -0
  47. package/dist/src/code-intelligence/graph/trace.js +65 -0
  48. package/dist/src/code-intelligence/impact/blast-radius.js +160 -0
  49. package/dist/src/code-intelligence/impact/change-mapper.js +69 -0
  50. package/dist/src/code-intelligence/impact/edit-tool-detector.js +92 -0
  51. package/dist/src/code-intelligence/impact/impact-analyzer.js +60 -0
  52. package/dist/src/code-intelligence/impact/impact-guard.js +33 -0
  53. package/dist/src/code-intelligence/impact/index.js +5 -0
  54. package/dist/src/code-intelligence/incremental/file-hash.js +8 -0
  55. package/dist/src/code-intelligence/incremental/incremental-indexer.js +106 -0
  56. package/dist/src/code-intelligence/incremental/manifest-builder.js +19 -0
  57. package/dist/src/code-intelligence/incremental/manifest.js +31 -0
  58. package/dist/src/code-intelligence/index.js +23 -0
  59. package/dist/src/code-intelligence/indexer/file-watcher.js +1 -0
  60. package/dist/src/code-intelligence/indexer/incremental-indexer.js +1 -0
  61. package/dist/src/code-intelligence/indexer/index.js +1 -0
  62. package/dist/src/code-intelligence/indexer/repository-indexer.js +31 -0
  63. package/dist/src/code-intelligence/indexer/repository-scanner.js +50 -0
  64. package/dist/src/code-intelligence/parsers/index.js +1 -0
  65. package/dist/src/code-intelligence/parsers/tree-sitter/index.js +1 -0
  66. package/dist/src/code-intelligence/parsers/tree-sitter/languages.js +1 -0
  67. package/dist/src/code-intelligence/parsers/tree-sitter/parser.js +1 -0
  68. package/dist/src/code-intelligence/parsers/typescript-parser.js +190 -0
  69. package/dist/src/code-intelligence/query/graph-query-engine.js +275 -0
  70. package/dist/src/code-intelligence/query/index.js +2 -0
  71. package/dist/src/code-intelligence/query/types.js +1 -0
  72. package/dist/src/code-intelligence/resolution/index.js +2 -0
  73. package/dist/src/code-intelligence/resolution/types.js +1 -0
  74. package/dist/src/code-intelligence/resolution/typescript-resolver.js +316 -0
  75. package/dist/src/code-intelligence/rich/index.js +1 -0
  76. package/dist/src/code-intelligence/rich/rich-graph-enricher.js +463 -0
  77. package/dist/src/code-intelligence/semantic/index.js +2 -0
  78. package/dist/src/code-intelligence/semantic/semantic-code-engine.js +213 -0
  79. package/dist/src/code-intelligence/semantic/source-priority.js +22 -0
  80. package/dist/src/code-intelligence/symbols/index.js +1 -0
  81. package/dist/src/code-intelligence/symbols/reference-resolver.js +21 -0
  82. package/dist/src/code-intelligence/symbols/symbol-extractor.js +1 -0
  83. package/dist/src/code-intelligence/test-analysis.js +72 -0
  84. package/dist/src/code-intelligence/test-architecture.js +67 -0
  85. package/dist/src/code-intelligence/test-impact.js +47 -0
  86. package/dist/src/code-intelligence/test-incremental.js +24 -0
  87. package/dist/src/code-intelligence/test-index.js +39 -0
  88. package/dist/src/code-intelligence/test-resolution.js +54 -0
  89. package/dist/src/code-intelligence/test-rich-graph.js +48 -0
  90. package/dist/src/code-intelligence/test-semantic.js +57 -0
  91. package/dist/src/code-intelligence/test-visualization.js +36 -0
  92. package/dist/src/code-intelligence/types.js +1 -0
  93. package/dist/src/code-intelligence/visualization/index.js +2 -0
  94. package/dist/src/code-intelligence/visualization/types.js +1 -0
  95. package/dist/src/code-intelligence/visualization/visualization-builder.js +104 -0
  96. package/dist/src/core/config.js +66 -0
  97. package/dist/src/core/global-env.js +70 -0
  98. package/dist/src/core/importance.js +30 -0
  99. package/dist/src/core/index.js +5 -0
  100. package/dist/src/core/memory-engine.js +183 -0
  101. package/dist/src/core/project-manager.js +243 -0
  102. package/dist/src/core/types.js +1 -0
  103. package/dist/src/embeddings/batch-embedder.js +1 -0
  104. package/dist/src/embeddings/cache.js +1 -0
  105. package/dist/src/embeddings/embedder.js +51 -0
  106. package/dist/src/embeddings/index.js +4 -0
  107. package/dist/src/embeddings/local.js +37 -0
  108. package/dist/src/embeddings/provider.js +1 -0
  109. package/dist/src/embeddings/remote.js +76 -0
  110. package/dist/src/embeddings/test-connection.js +16 -0
  111. package/dist/src/hooks/after-edit.js +3 -0
  112. package/dist/src/hooks/after-tool.js +3 -0
  113. package/dist/src/hooks/auto-context.js +68 -0
  114. package/dist/src/hooks/auto-impact-guard.js +94 -0
  115. package/dist/src/hooks/auto-retrieval.js +27 -0
  116. package/dist/src/hooks/before-agent.js +18 -0
  117. package/dist/src/hooks/before-compact.js +3 -0
  118. package/dist/src/hooks/before-edit.js +20 -0
  119. package/dist/src/hooks/index.js +11 -0
  120. package/dist/src/hooks/runtime.js +110 -0
  121. package/dist/src/hooks/session-end.js +3 -0
  122. package/dist/src/hooks/session-start.js +3 -0
  123. package/dist/src/index.js +22 -0
  124. package/dist/src/mcp/bootstrap.js +68 -0
  125. package/dist/src/mcp/context.js +1 -0
  126. package/dist/src/mcp/index.js +3 -0
  127. package/dist/src/mcp/server.js +45 -0
  128. package/dist/src/mcp/tools/analyze-impact.js +41 -0
  129. package/dist/src/mcp/tools/dead-code.js +55 -0
  130. package/dist/src/mcp/tools/find-callers.js +24 -0
  131. package/dist/src/mcp/tools/find-dependencies.js +57 -0
  132. package/dist/src/mcp/tools/find-symbol.js +7 -0
  133. package/dist/src/mcp/tools/get-architecture.js +11 -0
  134. package/dist/src/mcp/tools/graph-dependents.js +24 -0
  135. package/dist/src/mcp/tools/graph-neighborhood.js +58 -0
  136. package/dist/src/mcp/tools/graph-path.js +43 -0
  137. package/dist/src/mcp/tools/graph-query-utils.js +32 -0
  138. package/dist/src/mcp/tools/impact-guard.js +34 -0
  139. package/dist/src/mcp/tools/index-repository.js +1 -0
  140. package/dist/src/mcp/tools/index.js +20 -0
  141. package/dist/src/mcp/tools/memory-decisions.js +1 -0
  142. package/dist/src/mcp/tools/memory-forget.js +14 -0
  143. package/dist/src/mcp/tools/memory-recent.js +1 -0
  144. package/dist/src/mcp/tools/memory-remember.js +33 -0
  145. package/dist/src/mcp/tools/memory-rules.js +1 -0
  146. package/dist/src/mcp/tools/memory-search.js +18 -0
  147. package/dist/src/mcp/tools/memory-todos.js +1 -0
  148. package/dist/src/mcp/tools/project-context.js +25 -0
  149. package/dist/src/mcp/tools/search-code.js +21 -0
  150. package/dist/src/mcp/tools/semantic-code-search.js +33 -0
  151. package/dist/src/mcp/tools/snapshot-create.js +13 -0
  152. package/dist/src/mcp/tools/snapshot-list.js +7 -0
  153. package/dist/src/mcp/tools/snapshot-restore.js +13 -0
  154. package/dist/src/mcp/tools/trace-calls.js +37 -0
  155. package/dist/src/memory/activity.js +5 -0
  156. package/dist/src/memory/conflict-detector.js +105 -0
  157. package/dist/src/memory/consolidator.js +104 -0
  158. package/dist/src/memory/decay.js +59 -0
  159. package/dist/src/memory/decisions.js +3 -0
  160. package/dist/src/memory/deduplicate.js +25 -0
  161. package/dist/src/memory/index.js +11 -0
  162. package/dist/src/memory/maintenance.js +16 -0
  163. package/dist/src/memory/remember.js +3 -0
  164. package/dist/src/memory/rules.js +3 -0
  165. package/dist/src/memory/search.js +3 -0
  166. package/dist/src/memory/summaries.js +1 -0
  167. package/dist/src/memory/todos.js +3 -0
  168. package/dist/src/processor/decision-extractor.js +13 -0
  169. package/dist/src/processor/importance-scorer.js +22 -0
  170. package/dist/src/processor/index.js +7 -0
  171. package/dist/src/processor/memory-extractor.js +59 -0
  172. package/dist/src/processor/memory-processor.js +105 -0
  173. package/dist/src/processor/rule-extractor.js +13 -0
  174. package/dist/src/processor/summarizer.js +71 -0
  175. package/dist/src/processor/todo-extractor.js +12 -0
  176. package/dist/src/production/config-check.js +34 -0
  177. package/dist/src/production/doctor.js +58 -0
  178. package/dist/src/production/full-index.js +114 -0
  179. package/dist/src/production/health.js +58 -0
  180. package/dist/src/production/index-pipeline.js +151 -0
  181. package/dist/src/production/index.js +4 -0
  182. package/dist/src/production/project-lock.js +95 -0
  183. package/dist/src/production/project-status.js +16 -0
  184. package/dist/src/production/recovery.js +15 -0
  185. package/dist/src/production/snapshot-cli.js +58 -0
  186. package/dist/src/project-manual/cli.js +77 -0
  187. package/dist/src/project-manual/index.js +2 -0
  188. package/dist/src/project-manual/manager.js +147 -0
  189. package/dist/src/project-manual/types.js +1 -0
  190. package/dist/src/retrieval/bm25/index.js +1 -0
  191. package/dist/src/retrieval/bm25/search.js +1 -0
  192. package/dist/src/retrieval/bm25.js +30 -0
  193. package/dist/src/retrieval/context-budget.js +1 -0
  194. package/dist/src/retrieval/context-builder.js +22 -0
  195. package/dist/src/retrieval/graph/index.js +1 -0
  196. package/dist/src/retrieval/graph/search.js +1 -0
  197. package/dist/src/retrieval/hybrid/hybrid-search.js +1 -0
  198. package/dist/src/retrieval/hybrid/index.js +1 -0
  199. package/dist/src/retrieval/hybrid-search.js +68 -0
  200. package/dist/src/retrieval/importance.js +16 -0
  201. package/dist/src/retrieval/index.js +12 -0
  202. package/dist/src/retrieval/query-analyzer.js +32 -0
  203. package/dist/src/retrieval/query-classifier.js +1 -0
  204. package/dist/src/retrieval/query-expansion.js +1 -0
  205. package/dist/src/retrieval/recency.js +12 -0
  206. package/dist/src/retrieval/reranker/index.js +1 -0
  207. package/dist/src/retrieval/reranker/reranker.js +1 -0
  208. package/dist/src/retrieval/retrieval-engine.js +17 -0
  209. package/dist/src/retrieval/tokenizer.js +9 -0
  210. package/dist/src/retrieval/type-priority.js +10 -0
  211. package/dist/src/retrieval/types.js +1 -0
  212. package/dist/src/retrieval/vector/index.js +4 -0
  213. package/dist/src/retrieval/vector/metadata-filter.js +1 -0
  214. package/dist/src/retrieval/vector/persistence.js +67 -0
  215. package/dist/src/retrieval/vector/search.js +12 -0
  216. package/dist/src/retrieval/vector/test-persistence.js +36 -0
  217. package/dist/src/retrieval/vector/upsert.js +40 -0
  218. package/dist/src/retrieval/vector/vector-store.js +89 -0
  219. package/dist/src/retrieval/vector-hybrid-engine.js +91 -0
  220. package/dist/src/runtime/bootstrap.js +28 -0
  221. package/dist/src/runtime/graceful.js +17 -0
  222. package/dist/src/runtime/index.js +3 -0
  223. package/dist/src/runtime/toolnet-memory-runtime.js +156 -0
  224. package/dist/src/security/encryption.js +1 -0
  225. package/dist/src/security/file-filter.js +30 -0
  226. package/dist/src/security/index.js +3 -0
  227. package/dist/src/security/sanitizer.js +49 -0
  228. package/dist/src/security/secret-scanner.js +56 -0
  229. package/dist/src/session/agy/adapter.js +159 -0
  230. package/dist/src/session/agy/cli.js +87 -0
  231. package/dist/src/session/agy/hook-installer.js +62 -0
  232. package/dist/src/session/agy/hook.js +167 -0
  233. package/dist/src/session/agy/index.js +5 -0
  234. package/dist/src/session/agy/project-resolver.js +27 -0
  235. package/dist/src/session/agy/recovery.js +112 -0
  236. package/dist/src/session/agy/transcript.js +191 -0
  237. package/dist/src/session/codex/adapter.js +138 -0
  238. package/dist/src/session/codex/cli.js +236 -0
  239. package/dist/src/session/codex/context-hook-installer.js +70 -0
  240. package/dist/src/session/codex/context-hook.js +69 -0
  241. package/dist/src/session/codex/discovery.js +138 -0
  242. package/dist/src/session/codex/index.js +6 -0
  243. package/dist/src/session/codex/notify-installer.js +135 -0
  244. package/dist/src/session/codex/project-resolver.js +25 -0
  245. package/dist/src/session/codex/recovery.js +27 -0
  246. package/dist/src/session/codex/rollout.js +186 -0
  247. package/dist/src/session/core.js +239 -0
  248. package/dist/src/session/identity.js +57 -0
  249. package/dist/src/session/index.js +9 -0
  250. package/dist/src/session/learner/cli.js +62 -0
  251. package/dist/src/session/learner/extractor.js +461 -0
  252. package/dist/src/session/learner/index.js +4 -0
  253. package/dist/src/session/learner/journal.js +159 -0
  254. package/dist/src/session/learner/learner.js +124 -0
  255. package/dist/src/session/learner/types.js +1 -0
  256. package/dist/src/session/opencode/adapter.js +553 -0
  257. package/dist/src/session/opencode/cli.js +121 -0
  258. package/dist/src/session/opencode/index.js +2 -0
  259. package/dist/src/session/opencode/plugin-installer.js +230 -0
  260. package/dist/src/session/store.js +242 -0
  261. package/dist/src/session/types.js +1 -0
  262. package/dist/src/session/utils.js +47 -0
  263. package/dist/src/session/wal.js +303 -0
  264. package/dist/src/snapshot/index.js +2 -0
  265. package/dist/src/snapshot/manager.js +130 -0
  266. package/dist/src/snapshot/test-snapshot.js +28 -0
  267. package/dist/src/snapshot/types.js +1 -0
  268. package/dist/src/storage/architecture-store.js +37 -0
  269. package/dist/src/storage/cleanup-health.js +20 -0
  270. package/dist/src/storage/code-analysis-store.js +35 -0
  271. package/dist/src/storage/code-chunk-store.js +25 -0
  272. package/dist/src/storage/code-graph-store.js +24 -0
  273. package/dist/src/storage/code-manifest-store.js +24 -0
  274. package/dist/src/storage/code-vector-store.js +25 -0
  275. package/dist/src/storage/github/client.js +1 -0
  276. package/dist/src/storage/github/index.js +1 -0
  277. package/dist/src/storage/google-drive/client.js +1 -0
  278. package/dist/src/storage/google-drive/index.js +1 -0
  279. package/dist/src/storage/huggingface/client.js +116 -0
  280. package/dist/src/storage/huggingface/index.js +1 -0
  281. package/dist/src/storage/index.js +16 -0
  282. package/dist/src/storage/list-bucket-raw.js +14 -0
  283. package/dist/src/storage/list-bucket-tree.js +38 -0
  284. package/dist/src/storage/local/client.js +99 -0
  285. package/dist/src/storage/local/index.js +1 -0
  286. package/dist/src/storage/memory-store.js +30 -0
  287. package/dist/src/storage/project/cleanup-layout-v1.js +72 -0
  288. package/dist/src/storage/project/folder.js +15 -0
  289. package/dist/src/storage/project/index.js +3 -0
  290. package/dist/src/storage/project/layout.js +74 -0
  291. package/dist/src/storage/project/migrate-layout-v2.js +101 -0
  292. package/dist/src/storage/project/migrate.js +73 -0
  293. package/dist/src/storage/project/scoped-provider.js +165 -0
  294. package/dist/src/storage/provider.js +26 -0
  295. package/dist/src/storage/retrying-provider.js +23 -0
  296. package/dist/src/storage/test-connection.js +32 -0
  297. package/dist/src/storage/type-resolution-store.js +26 -0
  298. package/dist/src/storage/types.js +1 -0
  299. package/dist/src/storage/vector-store.js +30 -0
  300. package/dist/src/storage/visualization-store.js +25 -0
  301. package/dist/src/sync/compressor.js +1 -0
  302. package/dist/src/sync/conflict-resolver.js +1 -0
  303. package/dist/src/sync/downloader.js +1 -0
  304. package/dist/src/sync/index.js +1 -0
  305. package/dist/src/sync/sync-engine.js +1 -0
  306. package/dist/src/sync/upload-queue.js +1 -0
  307. package/dist/src/utils/retry.js +29 -0
  308. package/dist/src/visualization/server.js +270 -0
  309. package/dist/src/work-continuity/brief-cache.js +107 -0
  310. package/dist/src/work-continuity/brief.js +349 -0
  311. package/dist/src/work-continuity/cli.js +96 -0
  312. package/dist/src/work-continuity/context-cli.js +106 -0
  313. package/dist/src/work-continuity/context-runtime-cli.js +88 -0
  314. package/dist/src/work-continuity/extractor.js +339 -0
  315. package/dist/src/work-continuity/handoff.js +185 -0
  316. package/dist/src/work-continuity/index.js +14 -0
  317. package/dist/src/work-continuity/injection.js +84 -0
  318. package/dist/src/work-continuity/journal.js +49 -0
  319. package/dist/src/work-continuity/learner.js +127 -0
  320. package/dist/src/work-continuity/reducer.js +316 -0
  321. package/dist/src/work-continuity/semantic-extractor.js +360 -0
  322. package/dist/src/work-continuity/semantic-journal.js +55 -0
  323. package/dist/src/work-continuity/semantic-learner.js +125 -0
  324. package/dist/src/work-continuity/semantic-reducer.js +268 -0
  325. package/dist/src/work-continuity/semantic-types.js +1 -0
  326. package/dist/src/work-continuity/types.js +1 -0
  327. package/dist/visualization/public/index.html +2896 -0
  328. package/dist/visualization/public/vendor/3d-force-graph.min.js +5 -0
  329. package/package.json +69 -0
@@ -0,0 +1,89 @@
1
+ export class VectorStore {
2
+ records = new Map();
3
+ upsert(record) {
4
+ this.records.set(record.id, record);
5
+ }
6
+ get(id) {
7
+ return this.records.get(id);
8
+ }
9
+ has(id) {
10
+ return this.records.has(id);
11
+ }
12
+ remove(id) {
13
+ return this.records.delete(id);
14
+ }
15
+ clearProject(projectId) {
16
+ let deleted = 0;
17
+ for (const [id, record] of this.records) {
18
+ if (record.projectId ===
19
+ projectId) {
20
+ this.records.delete(id);
21
+ deleted++;
22
+ }
23
+ }
24
+ return deleted;
25
+ }
26
+ exportProject(projectId) {
27
+ return [...this.records.values()]
28
+ .filter((record) => record.projectId ===
29
+ projectId);
30
+ }
31
+ importRecords(records) {
32
+ let imported = 0;
33
+ for (const record of records) {
34
+ if (!record?.id ||
35
+ !record?.projectId ||
36
+ !Array.isArray(record.vector)) {
37
+ continue;
38
+ }
39
+ this.records.set(record.id, record);
40
+ imported++;
41
+ }
42
+ return imported;
43
+ }
44
+ search(projectId, queryVector, limit = 10) {
45
+ const results = [];
46
+ for (const record of this.records.values()) {
47
+ if (record.projectId !==
48
+ projectId) {
49
+ continue;
50
+ }
51
+ const score = cosineSimilarity(queryVector, record.vector);
52
+ results.push({
53
+ id: record.id,
54
+ score,
55
+ metadata: record.metadata,
56
+ });
57
+ }
58
+ return results
59
+ .sort((a, b) => b.score - a.score)
60
+ .slice(0, limit);
61
+ }
62
+ size() {
63
+ return this.records.size;
64
+ }
65
+ }
66
+ export function cosineSimilarity(a, b) {
67
+ if (a.length === 0 ||
68
+ b.length === 0 ||
69
+ a.length !== b.length) {
70
+ return 0;
71
+ }
72
+ let dot = 0;
73
+ let normA = 0;
74
+ let normB = 0;
75
+ for (let i = 0; i < a.length; i++) {
76
+ const av = a[i] ?? 0;
77
+ const bv = b[i] ?? 0;
78
+ dot += av * bv;
79
+ normA += av * av;
80
+ normB += bv * bv;
81
+ }
82
+ if (normA === 0 ||
83
+ normB === 0) {
84
+ return 0;
85
+ }
86
+ return (dot /
87
+ (Math.sqrt(normA) *
88
+ Math.sqrt(normB)));
89
+ }
@@ -0,0 +1,91 @@
1
+ import { HybridSearch, } from "./hybrid-search.js";
2
+ import { ContextBuilder, } from "./context-builder.js";
3
+ import { VectorIndexer, } from "./vector/upsert.js";
4
+ import { VectorSearch, } from "./vector/search.js";
5
+ import { VectorStore, } from "./vector/vector-store.js";
6
+ export class VectorHybridEngine {
7
+ memory;
8
+ lexical = new HybridSearch();
9
+ contextBuilder = new ContextBuilder();
10
+ store;
11
+ indexer;
12
+ vectorSearch;
13
+ constructor(memory, embeddings, store = new VectorStore()) {
14
+ this.memory = memory;
15
+ this.store =
16
+ store;
17
+ this.indexer =
18
+ new VectorIndexer(embeddings, this.store);
19
+ this.vectorSearch =
20
+ new VectorSearch(embeddings, this.store);
21
+ }
22
+ async rebuild(projectId) {
23
+ this.store.clearProject(projectId);
24
+ return this.indexer.index(this.memory.list(projectId));
25
+ }
26
+ async search(projectId, query, topK = 8) {
27
+ const memories = this.memory.list(projectId);
28
+ const byId = new Map(memories.map((memory) => [
29
+ memory.id,
30
+ memory,
31
+ ]));
32
+ const lexicalResults = this.lexical.search(query, memories, {
33
+ topK: Math.max(topK * 3, 20),
34
+ });
35
+ const vectorResults = await this.vectorSearch.search(projectId, query, Math.max(topK * 3, 20));
36
+ const merged = new Map();
37
+ for (const result of lexicalResults) {
38
+ merged.set(result.memory.id, {
39
+ lexicalScore: result.score,
40
+ vectorScore: 0,
41
+ });
42
+ }
43
+ for (const result of vectorResults) {
44
+ const current = merged.get(result.id) ?? {
45
+ lexicalScore: 0,
46
+ vectorScore: 0,
47
+ };
48
+ current.vectorScore =
49
+ Math.max(0, result.score);
50
+ merged.set(result.id, current);
51
+ }
52
+ const results = [];
53
+ for (const [id, scores] of merged) {
54
+ const memory = byId.get(id);
55
+ if (!memory) {
56
+ continue;
57
+ }
58
+ /*
59
+ * Hybrid:
60
+ * lexical/relevance 55%
61
+ * vector semantic 45%
62
+ */
63
+ const score = scores.lexicalScore *
64
+ 0.55 +
65
+ scores.vectorScore *
66
+ 0.45;
67
+ results.push({
68
+ memory,
69
+ score,
70
+ lexicalScore: scores.lexicalScore,
71
+ vectorScore: scores.vectorScore,
72
+ });
73
+ }
74
+ return results
75
+ .sort((a, b) => b.score - a.score)
76
+ .slice(0, topK);
77
+ }
78
+ async context(projectId, query, topK = 5) {
79
+ const results = await this.search(projectId, query, topK);
80
+ return this.contextBuilder.build(results.map((result) => ({
81
+ memory: result.memory,
82
+ score: result.score,
83
+ scores: {
84
+ keyword: result.lexicalScore,
85
+ recency: 0,
86
+ importance: 0,
87
+ type: result.vectorScore,
88
+ },
89
+ })));
90
+ }
91
+ }
@@ -0,0 +1,28 @@
1
+ import "dotenv/config";
2
+ import { loadConfig, ProjectManager, } from "../core/index.js";
3
+ import { createStorageProvider, withStorageRetry, ProjectScopedStorageProvider, } from "../storage/index.js";
4
+ import { ToolNetMemoryRuntime, } from "./toolnet-memory-runtime.js";
5
+ export function createToolNetMemoryRuntime(rootPath = process.cwd()) {
6
+ const config = loadConfig();
7
+ const project = new ProjectManager()
8
+ .detect(rootPath);
9
+ const rawStorage = createStorageProvider({
10
+ provider: config.storage.provider,
11
+ huggingface: config.storage.huggingface,
12
+ localRoot: config.storage.localRoot,
13
+ });
14
+ const retryStorage = withStorageRetry(rawStorage, {
15
+ attempts: Number(process.env
16
+ .TOOLNET_STORAGE_RETRIES ??
17
+ 3),
18
+ });
19
+ const storage = new ProjectScopedStorageProvider(retryStorage, project.id, project.name, project.remote ?? project.name);
20
+ const embeddingModel = process.env
21
+ .HF_EMBEDDING_MODEL ??
22
+ "sentence-transformers/all-MiniLM-L6-v2";
23
+ return new ToolNetMemoryRuntime({
24
+ project,
25
+ storage,
26
+ embeddingModel,
27
+ });
28
+ }
@@ -0,0 +1,17 @@
1
+ export function registerGracefulShutdown(runtime) {
2
+ let stopping = false;
3
+ const stop = async () => {
4
+ if (stopping) {
5
+ return;
6
+ }
7
+ stopping = true;
8
+ try {
9
+ await runtime.stop();
10
+ }
11
+ finally {
12
+ process.exit(0);
13
+ }
14
+ };
15
+ process.once("SIGINT", stop);
16
+ process.once("SIGTERM", stop);
17
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./toolnet-memory-runtime.js";
2
+ export * from "./bootstrap.js";
3
+ export * from "./graceful.js";
@@ -0,0 +1,156 @@
1
+ import { MemoryEngine, } from "../core/memory-engine.js";
2
+ import { MemoryMaintenance, } from "../memory/maintenance.js";
3
+ import { MemoryConsolidator, } from "../memory/consolidator.js";
4
+ import { RetrievalEngine, } from "../retrieval/retrieval-engine.js";
5
+ import { createEmbeddingProvider, } from "../embeddings/index.js";
6
+ import { CodeGraphStore, ReferenceResolver, } from "../code-intelligence/index.js";
7
+ import { IncrementalRepositoryIndexer, } from "../code-intelligence/incremental/incremental-indexer.js";
8
+ import { ImpactGuard, } from "../code-intelligence/impact/impact-guard.js";
9
+ import { VectorStore, VectorPersistenceManager, } from "../retrieval/vector/index.js";
10
+ import { HookRuntime, AutoContextBuilder, AutoRetrieval, AutoImpactGuard, } from "../hooks/index.js";
11
+ import { MemoryStore, PersistentCodeGraphStore, PersistentVectorStore, } from "../storage/index.js";
12
+ import { reconcileSessionMemoryJournal, } from "../session/learner/index.js";
13
+ import { SnapshotManager, } from "../snapshot/index.js";
14
+ import { ProjectLock, } from "../production/project-lock.js";
15
+ export class ToolNetMemoryRuntime {
16
+ options;
17
+ memory = new MemoryEngine();
18
+ graph = new CodeGraphStore();
19
+ vectors = new VectorStore();
20
+ retrieval;
21
+ references;
22
+ hooks;
23
+ autoRetrieval;
24
+ impactGuard;
25
+ autoImpactGuard;
26
+ memoryStore;
27
+ graphStore;
28
+ vectorStore;
29
+ processLock;
30
+ constructor(options) {
31
+ this.options = options;
32
+ this.memoryStore =
33
+ new MemoryStore(options.storage);
34
+ this.graphStore =
35
+ new PersistentCodeGraphStore(options.storage);
36
+ this.vectorStore =
37
+ new PersistentVectorStore(options.storage);
38
+ this.processLock =
39
+ new ProjectLock(options.project.id);
40
+ this.retrieval =
41
+ new RetrievalEngine(this.memory);
42
+ this.references =
43
+ new ReferenceResolver(this.graph);
44
+ this.hooks =
45
+ new HookRuntime({
46
+ projectId: options.project.id,
47
+ memory: this.memory,
48
+ memoryStore: this.memoryStore,
49
+ maxEventsBeforeFlush: 100,
50
+ });
51
+ const contextBuilder = new AutoContextBuilder(this.memory, this.retrieval, this.graph);
52
+ this.autoRetrieval =
53
+ new AutoRetrieval(this.hooks, contextBuilder, options.project.id);
54
+ this.impactGuard =
55
+ new ImpactGuard(this.graph);
56
+ this.autoImpactGuard =
57
+ new AutoImpactGuard(this.impactGuard, options.project.id);
58
+ }
59
+ async start() {
60
+ const { project, } = this.options;
61
+ await this.processLock
62
+ .acquire();
63
+ /*
64
+ * Session learners write immutable claims only.
65
+ * Reconcile them into current memory before runtime load.
66
+ */
67
+ await reconcileSessionMemoryJournal(project, this.options.storage);
68
+ // Load persistent memory.
69
+ const memories = await this.memoryStore.load(project.id);
70
+ this.memory.importRecords(memories);
71
+ const maintenance = new MemoryMaintenance(this.memory);
72
+ const maintenanceStats = maintenance.run(project.id);
73
+ if (maintenanceStats.expiredRemoved > 0 ||
74
+ maintenanceStats.supersededRemoved > 0) {
75
+ await this.memoryStore.save(project.id, this.memory.exportProject(project.id));
76
+ }
77
+ // Load code graph.
78
+ const graphSnapshot = await this.graphStore.load(project.id);
79
+ if (graphSnapshot) {
80
+ this.graph.import(graphSnapshot.symbols, graphSnapshot.edges);
81
+ }
82
+ // Load / update vectors.
83
+ const embeddings = createEmbeddingProvider();
84
+ const vectorManager = new VectorPersistenceManager(project.id, this.options.embeddingModel, embeddings, this.vectors, this.vectorStore);
85
+ const vectorStats = await vectorManager.initialize(this.memory.list(project.id));
86
+ await this.hooks
87
+ .sessionStart();
88
+ return {
89
+ memories: memories.length,
90
+ graphSymbols: this.graph
91
+ .allSymbols(project.id)
92
+ .length,
93
+ graphEdges: this.graph
94
+ .allEdges(project.id)
95
+ .length,
96
+ vectors: vectorStats.total,
97
+ vectorsIndexed: vectorStats.indexed,
98
+ };
99
+ }
100
+ async preparePrompt(prompt) {
101
+ return this.autoRetrieval
102
+ .prepare(prompt);
103
+ }
104
+ /*
105
+ * PHẢI gọi trước khi tool thật sự chạy.
106
+ * Edit/write/patch sẽ tự chạy Blast Radius.
107
+ */
108
+ async beforeTool(tool, input) {
109
+ const impact = await this.autoImpactGuard
110
+ .beforeTool(tool, input);
111
+ await this.hooks
112
+ .beforeTool(tool, input);
113
+ return impact;
114
+ }
115
+ async afterTool(tool, output) {
116
+ return this.hooks
117
+ .afterTool(tool, output);
118
+ }
119
+ async stop() {
120
+ const { project, storage, embeddingModel, } = this.options;
121
+ // Snapshot persistent state before changing it.
122
+ const snapshotManager = new SnapshotManager(storage);
123
+ const snapshot = await snapshotManager.create(project.id, "session-end-auto");
124
+ await snapshotManager.prune(project.id, 10);
125
+ // Flush pending memory events.
126
+ await this.hooks
127
+ .sessionEnd();
128
+ // Consolidate small activity memories.
129
+ const consolidation = new MemoryConsolidator(this.memory).consolidate(project.id);
130
+ if (consolidation.summaryCreated) {
131
+ await this.memoryStore.save(project.id, this.memory.exportProject(project.id));
132
+ }
133
+ // Incrementally update code graph.
134
+ const codeStats = await new IncrementalRepositoryIndexer(storage).index(project.id, project.rootPath);
135
+ // Reload latest graph snapshot.
136
+ const graphSnapshot = await this.graphStore.load(project.id);
137
+ if (graphSnapshot) {
138
+ this.graph.clearProject(project.id);
139
+ this.graph.import(graphSnapshot.symbols, graphSnapshot.edges);
140
+ }
141
+ // Persist only missing/new memory vectors.
142
+ const embeddings = createEmbeddingProvider();
143
+ const vectorManager = new VectorPersistenceManager(project.id, embeddingModel, embeddings, this.vectors, this.vectorStore);
144
+ const vectorStats = await vectorManager.initialize(this.memory.list(project.id));
145
+ const result = {
146
+ code: codeStats,
147
+ vectors: vectorStats,
148
+ consolidation,
149
+ snapshot: snapshot?.id,
150
+ memories: this.memory.list(project.id).length,
151
+ };
152
+ await this.processLock
153
+ .release();
154
+ return result;
155
+ }
156
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,30 @@
1
+ import { basename, } from "node:path";
2
+ const BLOCKED_NAMES = new Set([
3
+ ".env",
4
+ ".env.local",
5
+ ".env.production",
6
+ ".env.development",
7
+ "id_rsa",
8
+ "id_ed25519",
9
+ "credentials",
10
+ "credentials.json",
11
+ "service-account.json",
12
+ ]);
13
+ const BLOCKED_EXTENSIONS = new Set([
14
+ ".pem",
15
+ ".key",
16
+ ".p12",
17
+ ".pfx",
18
+ ]);
19
+ export function isSensitiveFile(filePath) {
20
+ const name = basename(filePath).toLowerCase();
21
+ if (BLOCKED_NAMES.has(name)) {
22
+ return true;
23
+ }
24
+ for (const extension of BLOCKED_EXTENSIONS) {
25
+ if (name.endsWith(extension)) {
26
+ return true;
27
+ }
28
+ }
29
+ return false;
30
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./secret-scanner.js";
2
+ export * from "./sanitizer.js";
3
+ export * from "./file-filter.js";
@@ -0,0 +1,49 @@
1
+ import { SecretScanner } from "./secret-scanner.js";
2
+ export class Sanitizer {
3
+ scanner = new SecretScanner();
4
+ sanitize(text) {
5
+ let output = text;
6
+ const matches = this.scanner.scan(text);
7
+ const secretTypes = new Set();
8
+ for (const match of matches) {
9
+ secretTypes.add(match.type);
10
+ output = output
11
+ .split(match.value)
12
+ .join(`[REDACTED:${match.type}]`);
13
+ }
14
+ return {
15
+ text: output,
16
+ redacted: matches.length,
17
+ secretTypes: [...secretTypes],
18
+ };
19
+ }
20
+ sanitizeValue(value) {
21
+ if (typeof value === "string") {
22
+ return this.sanitize(value).text;
23
+ }
24
+ if (Array.isArray(value)) {
25
+ return value.map((item) => this.sanitizeValue(item));
26
+ }
27
+ if (value &&
28
+ typeof value === "object") {
29
+ const output = {};
30
+ for (const [key, item] of Object.entries(value)) {
31
+ const normalized = key.toLowerCase();
32
+ if (normalized.includes("password") ||
33
+ normalized.includes("secret") ||
34
+ normalized.includes("token") ||
35
+ normalized.includes("cookie") ||
36
+ normalized.includes("authorization")) {
37
+ output[key] =
38
+ "[REDACTED]";
39
+ }
40
+ else {
41
+ output[key] =
42
+ this.sanitizeValue(item);
43
+ }
44
+ }
45
+ return output;
46
+ }
47
+ return value;
48
+ }
49
+ }
@@ -0,0 +1,56 @@
1
+ const PATTERNS = [
2
+ {
3
+ type: "openai_key",
4
+ regex: /\bsk-[A-Za-z0-9_\-]{20,}\b/g,
5
+ },
6
+ {
7
+ type: "huggingface_token",
8
+ regex: /\bhf_[A-Za-z0-9]{20,}\b/g,
9
+ },
10
+ {
11
+ type: "hf_s3_access_key",
12
+ regex: /\bHFAK[A-Za-z0-9]{8,}\b/g,
13
+ },
14
+ {
15
+ type: "bearer_token",
16
+ regex: /\bBearer\s+[A-Za-z0-9._\-]{16,}\b/gi,
17
+ },
18
+ {
19
+ type: "jwt",
20
+ regex: /\beyJ[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\b/g,
21
+ },
22
+ {
23
+ type: "private_key",
24
+ regex: /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/g,
25
+ },
26
+ {
27
+ type: "password_assignment",
28
+ regex: /\b(password|passwd|pwd)\s*[:=]\s*["']?[^"'\s]{6,}["']?/gi,
29
+ },
30
+ {
31
+ type: "secret_assignment",
32
+ regex: /\b(secret|api[_-]?key|access[_-]?token|refresh[_-]?token)\s*[:=]\s*["']?[^"'\s]{8,}["']?/gi,
33
+ },
34
+ {
35
+ type: "cookie",
36
+ regex: /\b(cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi,
37
+ },
38
+ ];
39
+ export class SecretScanner {
40
+ scan(text) {
41
+ const matches = [];
42
+ for (const pattern of PATTERNS) {
43
+ const regex = new RegExp(pattern.regex.source, pattern.regex.flags);
44
+ for (const match of text.matchAll(regex)) {
45
+ matches.push({
46
+ type: pattern.type,
47
+ value: match[0],
48
+ });
49
+ }
50
+ }
51
+ return matches;
52
+ }
53
+ hasSecrets(text) {
54
+ return this.scan(text).length > 0;
55
+ }
56
+ }
@@ -0,0 +1,159 @@
1
+ import { existsSync, } from "node:fs";
2
+ import { homedir, } from "node:os";
3
+ import { join, resolve, } from "node:path";
4
+ import { SessionCore, } from "../core.js";
5
+ import { readAgyTranscript, } from "./transcript.js";
6
+ function expandHome(value) {
7
+ if (value === "~") {
8
+ return homedir();
9
+ }
10
+ if (value.startsWith("~/")) {
11
+ return join(homedir(), value.slice(2));
12
+ }
13
+ return value;
14
+ }
15
+ export async function syncAgySession(options) {
16
+ const conversationId = options
17
+ .conversationId
18
+ .trim();
19
+ if (!conversationId) {
20
+ throw new Error("Agy conversationId is required");
21
+ }
22
+ const transcriptPath = resolve(expandHome(options
23
+ .transcriptPath));
24
+ const core = new SessionCore({
25
+ project: options.project,
26
+ storage: options.storage,
27
+ agent: "agy",
28
+ nativeSessionId: conversationId,
29
+ metadata: {
30
+ source: "antigravity-hook",
31
+ transcriptPath,
32
+ workspacePaths: options
33
+ .workspacePaths ??
34
+ [],
35
+ artifactDirectoryPath: options
36
+ .artifactDirectoryPath,
37
+ modelName: options.modelName,
38
+ },
39
+ });
40
+ const state = core.status();
41
+ const rawCursor = state
42
+ .sourceCursors["agy.transcript.offset"];
43
+ const offset = rawCursor
44
+ ? Number(rawCursor)
45
+ : 0;
46
+ const transcript = readAgyTranscript(transcriptPath, {
47
+ offset: Number.isFinite(offset)
48
+ ? offset
49
+ : 0,
50
+ });
51
+ const events = [];
52
+ if (state.lastSequence ===
53
+ 0) {
54
+ events.push({
55
+ type: "session_start",
56
+ sourceEventId: `agy:${conversationId}:start`,
57
+ data: {
58
+ workspacePaths: options
59
+ .workspacePaths ??
60
+ [],
61
+ transcriptPath,
62
+ modelName: options.modelName,
63
+ },
64
+ provenance: {
65
+ source: "antigravity-hook",
66
+ sourcePath: transcriptPath,
67
+ },
68
+ });
69
+ }
70
+ if (transcript.reset) {
71
+ events.push({
72
+ type: "custom",
73
+ sourceEventId: `agy:${conversationId}:transcript-reset:${transcript.nextOffset}`,
74
+ data: {
75
+ event: "transcript_reset",
76
+ transcriptPath,
77
+ },
78
+ provenance: {
79
+ source: "agy-transcript",
80
+ sourcePath: transcriptPath,
81
+ },
82
+ });
83
+ }
84
+ events.push(...transcript.events);
85
+ if (options.phase ===
86
+ "stop") {
87
+ if (options.error) {
88
+ events.push({
89
+ type: "error",
90
+ sourceEventId: [
91
+ "agy",
92
+ conversationId,
93
+ "stop-error",
94
+ options
95
+ .terminationReason ??
96
+ "",
97
+ transcript
98
+ .nextOffset,
99
+ ].join(":"),
100
+ data: {
101
+ error: options.error,
102
+ terminationReason: options
103
+ .terminationReason,
104
+ fullyIdle: options
105
+ .fullyIdle,
106
+ },
107
+ provenance: {
108
+ source: "antigravity-stop-hook",
109
+ },
110
+ });
111
+ }
112
+ /*
113
+ * Stop is NOT permanent SessionEnd.
114
+ * The same conversation UUID may be resumed later.
115
+ */
116
+ if (options.fullyIdle) {
117
+ events.push({
118
+ type: "session_idle",
119
+ sourceEventId: [
120
+ "agy",
121
+ conversationId,
122
+ "idle",
123
+ transcript
124
+ .nextOffset,
125
+ ].join(":"),
126
+ data: {
127
+ terminationReason: options
128
+ .terminationReason,
129
+ fullyIdle: true,
130
+ },
131
+ provenance: {
132
+ source: "antigravity-stop-hook",
133
+ },
134
+ });
135
+ }
136
+ }
137
+ const recorded = core.recordMany(events);
138
+ core.setSourceCursor("agy.transcript.offset", transcript.nextOffset);
139
+ if (options.phase) {
140
+ core.setSourceCursor("agy.last.phase", options.phase);
141
+ }
142
+ const flushed = await core.flush();
143
+ return {
144
+ conversationId,
145
+ imported: recorded.length,
146
+ eventCount: flushed.eventCount,
147
+ chunkCount: flushed.chunkCount,
148
+ status: flushed.status,
149
+ transcriptOffset: transcript
150
+ .nextOffset,
151
+ reset: transcript.reset,
152
+ };
153
+ }
154
+ export function defaultAgyTranscript(conversationId) {
155
+ return join(homedir(), ".gemini", "antigravity-cli", "brain", conversationId, ".system_generated", "logs", "transcript.jsonl");
156
+ }
157
+ export function agyTranscriptExists(conversationId) {
158
+ return existsSync(defaultAgyTranscript(conversationId));
159
+ }