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,62 @@
1
+ import { loadConfig, ProjectManager, } from "../../core/index.js";
2
+ import { createStorageProvider, ProjectScopedStorageProvider, withStorageRetry, } from "../../storage/index.js";
3
+ import { ProjectLock, } from "../../production/project-lock.js";
4
+ import { reconcileSessionMemoryJournal, } from "./journal.js";
5
+ function after(args, flag) {
6
+ const index = args.indexOf(flag);
7
+ return index >=
8
+ 0
9
+ ? args[index + 1]
10
+ : undefined;
11
+ }
12
+ async function main() {
13
+ const [command = "help", ...args] = process.argv.slice(2);
14
+ if (command !==
15
+ "reconcile") {
16
+ console.log(`Session Memory Learner
17
+
18
+ Commands:
19
+ reconcile [--project PATH]
20
+ `);
21
+ return;
22
+ }
23
+ const projectPath = after(args, "--project") ??
24
+ process.cwd();
25
+ const project = new ProjectManager()
26
+ .detect(projectPath);
27
+ const config = loadConfig();
28
+ const raw = withStorageRetry(createStorageProvider({
29
+ provider: config.storage
30
+ .provider,
31
+ huggingface: config.storage
32
+ .huggingface,
33
+ localRoot: config.storage
34
+ .localRoot,
35
+ }), {
36
+ attempts: 3,
37
+ });
38
+ const storage = new ProjectScopedStorageProvider(raw, project.id, project.name, project.remote ??
39
+ project.name);
40
+ /*
41
+ * Reconcile writes current.json.
42
+ * Serialize against ToolNet runtime.
43
+ */
44
+ const lock = new ProjectLock(project.id);
45
+ await lock.acquire();
46
+ try {
47
+ const result = await reconcileSessionMemoryJournal(project, storage);
48
+ console.log(JSON.stringify({
49
+ project: project.name,
50
+ ...result,
51
+ }, null, 2));
52
+ }
53
+ finally {
54
+ await lock.release();
55
+ }
56
+ }
57
+ main().catch(error => {
58
+ console.error(error instanceof Error
59
+ ? error.message
60
+ : error);
61
+ process.exit(1);
62
+ });
@@ -0,0 +1,461 @@
1
+ import { scoreImportance, } from "../../processor/importance-scorer.js";
2
+ import { sha256, } from "../utils.js";
3
+ const RULE_CRITICAL = [
4
+ /không được/iu,
5
+ /tuyệt đối/iu,
6
+ /bắt buộc/iu,
7
+ /đừng\s+/iu,
8
+ /must not/iu,
9
+ /do not/iu,
10
+ /don't/iu,
11
+ /\bnever\b/iu,
12
+ ];
13
+ const RULE_PERSISTENT = [
14
+ /từ giờ/iu,
15
+ /về sau/iu,
16
+ /mỗi lần/iu,
17
+ /luôn luôn/iu,
18
+ /\bluôn\b/iu,
19
+ /quy tắc/iu,
20
+ /workflow/iu,
21
+ /\balways\b/iu,
22
+ /\brequired\b/iu,
23
+ /\bmust\b/iu,
24
+ /from now on/iu,
25
+ ];
26
+ const DECISION = [
27
+ /\bchốt\b/iu,
28
+ /quyết định/iu,
29
+ /sẽ dùng/iu,
30
+ /chọn .+ thay/iu,
31
+ /đổi sang/iu,
32
+ /chuyển sang/iu,
33
+ /\bdecided\b/iu,
34
+ /\bchosen\b/iu,
35
+ /we will use/iu,
36
+ /use .+ instead/iu,
37
+ /switch(?:ed)? to/iu,
38
+ ];
39
+ const TODO = [
40
+ /\btodo\b/iu,
41
+ /cần làm/iu,
42
+ /cần thêm/iu,
43
+ /cần sửa/iu,
44
+ /cần kiểm tra/iu,
45
+ /tiếp theo/iu,
46
+ /bước tiếp theo/iu,
47
+ /còn phải/iu,
48
+ /còn cần/iu,
49
+ /next step/iu,
50
+ /\bneed to\b/iu,
51
+ /\bremaining\b/iu,
52
+ /follow[- ]?up/iu,
53
+ ];
54
+ const FIX = [
55
+ /đã sửa/iu,
56
+ /đã fix/iu,
57
+ /đã khắc phục/iu,
58
+ /đã xử lý/iu,
59
+ /hoàn tất/iu,
60
+ /hoàn thành/iu,
61
+ /\bfixed\b/iu,
62
+ /\bresolved\b/iu,
63
+ /\bimplemented\b/iu,
64
+ /\bcompleted\b/iu,
65
+ /\bpasses?\b/iu,
66
+ ];
67
+ const ARCHITECTURE = [
68
+ /kiến trúc/iu,
69
+ /pipeline/iu,
70
+ /adapter/iu,
71
+ /schema/iu,
72
+ /runtime/iu,
73
+ /namespace/iu,
74
+ /storage/iu,
75
+ /lưu trữ/iu,
76
+ /workflow/iu,
77
+ /session core/iu,
78
+ /memory engine/iu,
79
+ /retrieval/iu,
80
+ ];
81
+ const ARCH_ACTION = [
82
+ /\bdùng\b/iu,
83
+ /\btách\b/iu,
84
+ /\bthay\b/iu,
85
+ /\bchuyển\b/iu,
86
+ /\blưu\b/iu,
87
+ /\bmap\b/iu,
88
+ /\buse\b/iu,
89
+ /\bsplit\b/iu,
90
+ /\bstore\b/iu,
91
+ /\breplace\b/iu,
92
+ /\bmove\b/iu,
93
+ ];
94
+ const CONTEXT = [
95
+ /đường dẫn/iu,
96
+ /\bpath\b/iu,
97
+ /\bport\b/iu,
98
+ /\bendpoint\b/iu,
99
+ /\bdomain\b/iu,
100
+ /\bbucket\b/iu,
101
+ /\brepository\b/iu,
102
+ /\brepo\b/iu,
103
+ /\bbranch\b/iu,
104
+ /\/[A-Za-z0-9._/-]{4,}/u,
105
+ ];
106
+ const CONTEXT_ASSIGNMENT = [
107
+ /\blà\b/iu,
108
+ /\bở\b/iu,
109
+ /\bdùng\b/iu,
110
+ /\bnằm\b/iu,
111
+ /\bis\b/iu,
112
+ /\buse\b/iu,
113
+ /located/iu,
114
+ /runs on/iu,
115
+ ];
116
+ const TEXT_KEYS = new Set([
117
+ "content",
118
+ "text",
119
+ "message",
120
+ "prompt",
121
+ "summary",
122
+ "description",
123
+ "reason",
124
+ "title",
125
+ "last_assistant_message",
126
+ "lastAssistantMessage",
127
+ "input_messages",
128
+ "inputMessages",
129
+ ]);
130
+ const CONTAINER_KEYS = new Set([
131
+ "payload",
132
+ "data",
133
+ "content",
134
+ "message",
135
+ "messages",
136
+ "parts",
137
+ "summary",
138
+ ]);
139
+ function matches(value, patterns) {
140
+ return patterns.some(pattern => pattern.test(value));
141
+ }
142
+ function normalizeText(value) {
143
+ return value
144
+ .normalize("NFKC")
145
+ .replace(/\r/g, "")
146
+ .replace(/^[\s>*#\-•]+/u, "")
147
+ .replace(/\s+/g, " ")
148
+ .trim();
149
+ }
150
+ function fingerprintText(value) {
151
+ return normalizeText(value)
152
+ .toLowerCase()
153
+ .replace(/[^\p{L}\p{N}:/._-]+/gu, " ")
154
+ .replace(/\s+/g, " ")
155
+ .trim();
156
+ }
157
+ function useful(value) {
158
+ if (value.length <
159
+ 12 ||
160
+ value.length >
161
+ 1000) {
162
+ return false;
163
+ }
164
+ const letters = (value.match(/\p{L}/gu) ??
165
+ []).length;
166
+ if (letters <
167
+ 6) {
168
+ return false;
169
+ }
170
+ if (/^(?:https?:\/\/\S+|[A-Za-z0-9+/=]{80,})$/u
171
+ .test(value)) {
172
+ return false;
173
+ }
174
+ return true;
175
+ }
176
+ function collectText(value, key, output, depth = 0) {
177
+ if (depth >
178
+ 6) {
179
+ return;
180
+ }
181
+ if (typeof value ===
182
+ "string") {
183
+ if (!key ||
184
+ TEXT_KEYS.has(key)) {
185
+ output.push(value);
186
+ }
187
+ return;
188
+ }
189
+ if (Array.isArray(value)) {
190
+ for (const item of value.slice(0, 50)) {
191
+ collectText(item, key, output, depth + 1);
192
+ }
193
+ return;
194
+ }
195
+ if (!value ||
196
+ typeof value !==
197
+ "object") {
198
+ return;
199
+ }
200
+ for (const [childKey, childValue,] of Object.entries(value)) {
201
+ if (TEXT_KEYS.has(childKey) ||
202
+ CONTAINER_KEYS.has(childKey)) {
203
+ collectText(childValue, childKey, output, depth + 1);
204
+ }
205
+ }
206
+ }
207
+ function fragments(event) {
208
+ const raw = [];
209
+ collectText(event.data, undefined, raw);
210
+ const result = [];
211
+ const seen = new Set();
212
+ for (const block of raw) {
213
+ for (const piece of block.split(/\n+|(?<=[.!?])\s+/u)) {
214
+ const text = normalizeText(piece);
215
+ if (!useful(text)) {
216
+ continue;
217
+ }
218
+ if (seen.has(text)) {
219
+ continue;
220
+ }
221
+ seen.add(text);
222
+ result.push(text);
223
+ if (result.length >=
224
+ 50) {
225
+ return result;
226
+ }
227
+ }
228
+ }
229
+ return result;
230
+ }
231
+ function roleOf(event) {
232
+ return (event.role ??
233
+ (typeof event.data.role ===
234
+ "string"
235
+ ? event.data.role
236
+ : ""))
237
+ .toLowerCase();
238
+ }
239
+ function classify(text, role, event) {
240
+ if (event.type ===
241
+ "decision") {
242
+ return {
243
+ kind: "decision",
244
+ confidence: 1,
245
+ };
246
+ }
247
+ if (event.type ===
248
+ "todo") {
249
+ return {
250
+ kind: "todo",
251
+ confidence: 1,
252
+ };
253
+ }
254
+ const isUser = role ===
255
+ "user" ||
256
+ event.type ===
257
+ "user_prompt";
258
+ const isAssistant = role ===
259
+ "assistant" ||
260
+ event.type ===
261
+ "assistant_message";
262
+ if (isUser &&
263
+ matches(text, RULE_CRITICAL)) {
264
+ return {
265
+ kind: "rule",
266
+ confidence: 0.98,
267
+ };
268
+ }
269
+ if (isUser &&
270
+ matches(text, RULE_PERSISTENT)) {
271
+ return {
272
+ kind: "rule",
273
+ confidence: 0.92,
274
+ };
275
+ }
276
+ if (matches(text, DECISION)) {
277
+ return {
278
+ kind: matches(text, ARCHITECTURE)
279
+ ? "architecture"
280
+ : "decision",
281
+ confidence: isUser
282
+ ? 0.93
283
+ : 0.86,
284
+ };
285
+ }
286
+ if (isUser &&
287
+ matches(text, TODO)) {
288
+ return {
289
+ kind: "todo",
290
+ confidence: 0.87,
291
+ };
292
+ }
293
+ if (matches(text, ARCHITECTURE) &&
294
+ matches(text, ARCH_ACTION)) {
295
+ return {
296
+ kind: "architecture",
297
+ confidence: isUser
298
+ ? 0.88
299
+ : 0.82,
300
+ };
301
+ }
302
+ if (isAssistant &&
303
+ matches(text, FIX)) {
304
+ return {
305
+ kind: "fix",
306
+ confidence: 0.8,
307
+ };
308
+ }
309
+ if (isUser &&
310
+ matches(text, CONTEXT) &&
311
+ matches(text, CONTEXT_ASSIGNMENT)) {
312
+ return {
313
+ kind: "context",
314
+ confidence: 0.79,
315
+ };
316
+ }
317
+ return null;
318
+ }
319
+ function memoryType(kind) {
320
+ switch (kind) {
321
+ case "rule":
322
+ return "rule";
323
+ case "decision":
324
+ case "architecture":
325
+ return "decision";
326
+ case "todo":
327
+ return "todo";
328
+ case "fix":
329
+ case "context":
330
+ return "code";
331
+ }
332
+ }
333
+ function importance(kind, type, content) {
334
+ if (kind ===
335
+ "rule" &&
336
+ matches(content, RULE_CRITICAL)) {
337
+ return "critical";
338
+ }
339
+ if (kind ===
340
+ "architecture" ||
341
+ kind ===
342
+ "decision" ||
343
+ kind ===
344
+ "rule") {
345
+ return "high";
346
+ }
347
+ if (kind ===
348
+ "fix" ||
349
+ kind ===
350
+ "context") {
351
+ return "normal";
352
+ }
353
+ return scoreImportance(type, content);
354
+ }
355
+ export function extractLearnedMemories(identity, events) {
356
+ const output = [];
357
+ const fingerprints = new Set();
358
+ const messageRoles = new Map();
359
+ for (const event of events) {
360
+ const messageId = typeof event.data
361
+ .messageId ===
362
+ "string"
363
+ ? event.data
364
+ .messageId
365
+ : undefined;
366
+ const role = roleOf(event);
367
+ if (messageId &&
368
+ role) {
369
+ messageRoles.set(messageId, role);
370
+ }
371
+ }
372
+ for (const event of events) {
373
+ let role = roleOf(event);
374
+ const messageId = typeof event.data
375
+ .messageId ===
376
+ "string"
377
+ ? event.data
378
+ .messageId
379
+ : undefined;
380
+ if (!role &&
381
+ messageId) {
382
+ role =
383
+ messageRoles.get(messageId) ??
384
+ "";
385
+ }
386
+ for (const text of fragments(event)) {
387
+ const classified = classify(text, role, event);
388
+ if (!classified ||
389
+ classified
390
+ .confidence <
391
+ 0.75) {
392
+ continue;
393
+ }
394
+ const type = memoryType(classified.kind);
395
+ const normalized = fingerprintText(text);
396
+ const fingerprint = sha256([
397
+ identity
398
+ .projectId,
399
+ classified
400
+ .kind,
401
+ normalized,
402
+ ].join("|"));
403
+ if (fingerprints.has(fingerprint)) {
404
+ continue;
405
+ }
406
+ fingerprints.add(fingerprint);
407
+ const sourcePaths = event.provenance
408
+ .sourcePath
409
+ ? [
410
+ event.provenance
411
+ .sourcePath,
412
+ ]
413
+ : [];
414
+ const sourceEventIds = event.sourceEventId
415
+ ? [
416
+ event.sourceEventId,
417
+ ]
418
+ : [];
419
+ output.push({
420
+ version: 1,
421
+ fingerprint,
422
+ projectId: identity
423
+ .projectId,
424
+ agent: identity.agent,
425
+ nativeSessionId: identity
426
+ .nativeSessionId,
427
+ sessionKey: identity
428
+ .sessionKey,
429
+ kind: classified.kind,
430
+ type,
431
+ content: text,
432
+ confidence: classified
433
+ .confidence,
434
+ importance: importance(classified.kind, type, text),
435
+ /*
436
+ * Keep decision/rule tags generic.
437
+ * ConflictDetector uses non-generic tags as topic hints.
438
+ */
439
+ tags: [
440
+ type,
441
+ ],
442
+ provenance: {
443
+ agent: identity.agent,
444
+ nativeSessionId: identity
445
+ .nativeSessionId,
446
+ sessionKey: identity
447
+ .sessionKey,
448
+ eventIds: [
449
+ event.id,
450
+ ],
451
+ sourceEventIds,
452
+ sourcePaths,
453
+ firstSequence: event.sequence,
454
+ lastSequence: event.sequence,
455
+ },
456
+ createdAt: event.timestamp,
457
+ });
458
+ }
459
+ }
460
+ return output;
461
+ }
@@ -0,0 +1,4 @@
1
+ export * from "./types.js";
2
+ export * from "./extractor.js";
3
+ export * from "./journal.js";
4
+ export * from "./learner.js";
@@ -0,0 +1,159 @@
1
+ import { MemoryEngine, } from "../../core/memory-engine.js";
2
+ import { MemoryStore, } from "../../storage/memory-store.js";
3
+ import { sha256, } from "../utils.js";
4
+ function pad(value) {
5
+ return String(value).padStart(12, "0");
6
+ }
7
+ function journalPrefix(identity) {
8
+ return identity
9
+ .remotePrefix
10
+ .replace("/sessions/", "/memory/learned/");
11
+ }
12
+ export class SessionMemoryJournal {
13
+ storage;
14
+ constructor(storage) {
15
+ this.storage = storage;
16
+ }
17
+ async write(identity, events, candidates) {
18
+ if (candidates.length ===
19
+ 0 ||
20
+ events.length ===
21
+ 0) {
22
+ return null;
23
+ }
24
+ const firstSequence = Math.min(...events.map(item => item.sequence));
25
+ const lastSequence = Math.max(...events.map(item => item.sequence));
26
+ const batch = {
27
+ version: 1,
28
+ projectId: identity.projectId,
29
+ agent: identity.agent,
30
+ nativeSessionId: identity
31
+ .nativeSessionId,
32
+ sessionKey: identity.sessionKey,
33
+ createdAt: new Date()
34
+ .toISOString(),
35
+ firstSequence,
36
+ lastSequence,
37
+ candidateCount: candidates.length,
38
+ candidates,
39
+ };
40
+ const payload = JSON.stringify(batch, null, 2) +
41
+ "\n";
42
+ const digest = sha256(candidates
43
+ .map(item => item.fingerprint)
44
+ .sort()
45
+ .join("|")).slice(0, 16);
46
+ const key = [
47
+ journalPrefix(identity),
48
+ "batches",
49
+ `${pad(firstSequence)}-${pad(lastSequence)}-${digest}.json`,
50
+ ].join("/");
51
+ if (!await this.storage
52
+ .exists(key)) {
53
+ await this.storage.put(key, payload, "application/json");
54
+ }
55
+ return key;
56
+ }
57
+ }
58
+ function candidateFingerprint(memory) {
59
+ const value = memory.metadata
60
+ ?.learningFingerprint;
61
+ return typeof value ===
62
+ "string"
63
+ ? value
64
+ : undefined;
65
+ }
66
+ async function loadBatches(project, storage) {
67
+ const prefix = `projects/${project.id}/memory/learned/`;
68
+ const objects = await storage.list(prefix);
69
+ const batches = [];
70
+ for (const object of objects
71
+ .filter(item => item.key.includes("/batches/") &&
72
+ item.key.endsWith(".json"))
73
+ .sort((left, right) => left.key.localeCompare(right.key))) {
74
+ const text = await storage.getText(object.key);
75
+ if (!text) {
76
+ continue;
77
+ }
78
+ try {
79
+ const parsed = JSON.parse(text);
80
+ if (parsed.version !==
81
+ 1 ||
82
+ !Array.isArray(parsed.candidates)) {
83
+ continue;
84
+ }
85
+ batches.push(parsed);
86
+ }
87
+ catch {
88
+ // Ignore incomplete/corrupt optional learning batch.
89
+ }
90
+ }
91
+ return batches;
92
+ }
93
+ export async function reconcileSessionMemoryJournal(project, storage) {
94
+ const batches = await loadBatches(project, storage);
95
+ const store = new MemoryStore(storage);
96
+ const existing = await store.load(project.id);
97
+ const engine = new MemoryEngine();
98
+ engine.importRecords(existing);
99
+ const fingerprints = new Set(existing
100
+ .map(memory => candidateFingerprint(memory))
101
+ .filter((value) => Boolean(value)));
102
+ let candidates = 0;
103
+ let added = 0;
104
+ let duplicates = 0;
105
+ for (const batch of batches) {
106
+ for (const candidate of batch.candidates) {
107
+ candidates +=
108
+ 1;
109
+ if (fingerprints.has(candidate
110
+ .fingerprint)) {
111
+ duplicates +=
112
+ 1;
113
+ continue;
114
+ }
115
+ engine.remember({
116
+ projectId: project.id,
117
+ type: candidate.type,
118
+ content: candidate.content,
119
+ importance: candidate
120
+ .importance,
121
+ tags: candidate.tags,
122
+ source: "session-memory-learner",
123
+ metadata: {
124
+ learningFingerprint: candidate
125
+ .fingerprint,
126
+ learningKind: candidate.kind,
127
+ confidence: candidate
128
+ .confidence,
129
+ provenance: candidate
130
+ .provenance,
131
+ sourceCreatedAt: candidate
132
+ .createdAt,
133
+ sessionKey: candidate
134
+ .sessionKey,
135
+ agent: candidate.agent,
136
+ nativeSessionId: candidate
137
+ .nativeSessionId,
138
+ },
139
+ });
140
+ fingerprints.add(candidate
141
+ .fingerprint);
142
+ added +=
143
+ 1;
144
+ }
145
+ }
146
+ if (added >
147
+ 0) {
148
+ await store.save(project.id, engine.exportProject(project.id));
149
+ }
150
+ return {
151
+ batches: batches.length,
152
+ candidates,
153
+ added,
154
+ duplicates,
155
+ memories: engine
156
+ .exportProject(project.id)
157
+ .length,
158
+ };
159
+ }