toolnet-memory 0.2.1 → 0.2.3

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 (342) hide show
  1. package/README.md +55 -28
  2. package/bin/toolnet-memory +55 -55
  3. package/bundle/agy.js +88 -0
  4. package/bundle/codex.js +92 -0
  5. package/bundle/context-runtime.js +56 -0
  6. package/bundle/context.js +62 -0
  7. package/bundle/doctor.js +3 -0
  8. package/bundle/full-index.js +8 -0
  9. package/bundle/learner.js +8 -0
  10. package/bundle/mcp.js +7 -0
  11. package/bundle/opencode.js +314 -0
  12. package/bundle/project-manual.js +54 -0
  13. package/bundle/setup.js +31 -0
  14. package/bundle/snapshot.js +4 -0
  15. package/bundle/work-continuity.js +12 -0
  16. package/package.json +9 -6
  17. package/dist/packages/cli/commands.js +0 -1
  18. package/dist/packages/cli/index.js +0 -1
  19. package/dist/packages/sdk/client.js +0 -78
  20. package/dist/packages/sdk/index.js +0 -1
  21. package/dist/packages/sdk/types.js +0 -1
  22. package/dist/src/api/index.js +0 -1
  23. package/dist/src/api/routes/health.js +0 -1
  24. package/dist/src/api/routes/index.js +0 -1
  25. package/dist/src/api/routes/memory.js +0 -1
  26. package/dist/src/api/routes/projects.js +0 -1
  27. package/dist/src/api/routes/search.js +0 -1
  28. package/dist/src/api/server.js +0 -1
  29. package/dist/src/capture/activity-capture.js +0 -21
  30. package/dist/src/capture/command-capture.js +0 -12
  31. package/dist/src/capture/error-capture.js +0 -14
  32. package/dist/src/capture/event-deduplicator.js +0 -28
  33. package/dist/src/capture/event-queue.js +0 -20
  34. package/dist/src/capture/file-capture.js +0 -23
  35. package/dist/src/capture/index.js +0 -8
  36. package/dist/src/capture/session-capture.js +0 -18
  37. package/dist/src/capture/tool-capture.js +0 -13
  38. package/dist/src/code-intelligence/analysis/analysis-engine.js +0 -26
  39. package/dist/src/code-intelligence/analysis/dead-code-analyzer.js +0 -127
  40. package/dist/src/code-intelligence/analysis/dependency-analyzer.js +0 -66
  41. package/dist/src/code-intelligence/analysis/index.js +0 -4
  42. package/dist/src/code-intelligence/analysis/types.js +0 -1
  43. package/dist/src/code-intelligence/architecture/architecture-engine.js +0 -48
  44. package/dist/src/code-intelligence/architecture/clusters.js +0 -322
  45. package/dist/src/code-intelligence/architecture/entry-points.js +0 -150
  46. package/dist/src/code-intelligence/architecture/hotspots.js +0 -136
  47. package/dist/src/code-intelligence/architecture/index.js +0 -6
  48. package/dist/src/code-intelligence/architecture/layers.js +0 -197
  49. package/dist/src/code-intelligence/architecture/types.js +0 -1
  50. package/dist/src/code-intelligence/chunks/index.js +0 -2
  51. package/dist/src/code-intelligence/chunks/smart-chunker.js +0 -125
  52. package/dist/src/code-intelligence/chunks/types.js +0 -1
  53. package/dist/src/code-intelligence/git/git-diff.js +0 -109
  54. package/dist/src/code-intelligence/git/index.js +0 -1
  55. package/dist/src/code-intelligence/graph/architecture.js +0 -26
  56. package/dist/src/code-intelligence/graph/graph-builder.js +0 -213
  57. package/dist/src/code-intelligence/graph/graph-store.js +0 -57
  58. package/dist/src/code-intelligence/graph/index.js +0 -1
  59. package/dist/src/code-intelligence/graph/relationships.js +0 -1
  60. package/dist/src/code-intelligence/graph/trace.js +0 -65
  61. package/dist/src/code-intelligence/impact/blast-radius.js +0 -160
  62. package/dist/src/code-intelligence/impact/change-mapper.js +0 -69
  63. package/dist/src/code-intelligence/impact/edit-tool-detector.js +0 -92
  64. package/dist/src/code-intelligence/impact/impact-analyzer.js +0 -60
  65. package/dist/src/code-intelligence/impact/impact-guard.js +0 -33
  66. package/dist/src/code-intelligence/impact/index.js +0 -5
  67. package/dist/src/code-intelligence/incremental/file-hash.js +0 -8
  68. package/dist/src/code-intelligence/incremental/incremental-indexer.js +0 -106
  69. package/dist/src/code-intelligence/incremental/manifest-builder.js +0 -19
  70. package/dist/src/code-intelligence/incremental/manifest.js +0 -31
  71. package/dist/src/code-intelligence/index.js +0 -23
  72. package/dist/src/code-intelligence/indexer/file-watcher.js +0 -1
  73. package/dist/src/code-intelligence/indexer/incremental-indexer.js +0 -1
  74. package/dist/src/code-intelligence/indexer/index.js +0 -1
  75. package/dist/src/code-intelligence/indexer/repository-indexer.js +0 -31
  76. package/dist/src/code-intelligence/indexer/repository-scanner.js +0 -50
  77. package/dist/src/code-intelligence/parsers/index.js +0 -1
  78. package/dist/src/code-intelligence/parsers/tree-sitter/index.js +0 -1
  79. package/dist/src/code-intelligence/parsers/tree-sitter/languages.js +0 -1
  80. package/dist/src/code-intelligence/parsers/tree-sitter/parser.js +0 -1
  81. package/dist/src/code-intelligence/parsers/typescript-parser.js +0 -190
  82. package/dist/src/code-intelligence/query/graph-query-engine.js +0 -275
  83. package/dist/src/code-intelligence/query/index.js +0 -2
  84. package/dist/src/code-intelligence/query/types.js +0 -1
  85. package/dist/src/code-intelligence/resolution/index.js +0 -2
  86. package/dist/src/code-intelligence/resolution/types.js +0 -1
  87. package/dist/src/code-intelligence/resolution/typescript-resolver.js +0 -316
  88. package/dist/src/code-intelligence/rich/index.js +0 -1
  89. package/dist/src/code-intelligence/rich/rich-graph-enricher.js +0 -463
  90. package/dist/src/code-intelligence/semantic/index.js +0 -2
  91. package/dist/src/code-intelligence/semantic/semantic-code-engine.js +0 -213
  92. package/dist/src/code-intelligence/semantic/source-priority.js +0 -22
  93. package/dist/src/code-intelligence/symbols/index.js +0 -1
  94. package/dist/src/code-intelligence/symbols/reference-resolver.js +0 -21
  95. package/dist/src/code-intelligence/symbols/symbol-extractor.js +0 -1
  96. package/dist/src/code-intelligence/test-analysis.js +0 -72
  97. package/dist/src/code-intelligence/test-architecture.js +0 -67
  98. package/dist/src/code-intelligence/test-impact.js +0 -47
  99. package/dist/src/code-intelligence/test-incremental.js +0 -24
  100. package/dist/src/code-intelligence/test-index.js +0 -39
  101. package/dist/src/code-intelligence/test-resolution.js +0 -54
  102. package/dist/src/code-intelligence/test-rich-graph.js +0 -48
  103. package/dist/src/code-intelligence/test-semantic.js +0 -57
  104. package/dist/src/code-intelligence/test-visualization.js +0 -36
  105. package/dist/src/code-intelligence/types.js +0 -1
  106. package/dist/src/code-intelligence/visualization/index.js +0 -2
  107. package/dist/src/code-intelligence/visualization/types.js +0 -1
  108. package/dist/src/code-intelligence/visualization/visualization-builder.js +0 -104
  109. package/dist/src/core/config.js +0 -66
  110. package/dist/src/core/global-env.js +0 -70
  111. package/dist/src/core/importance.js +0 -30
  112. package/dist/src/core/index.js +0 -5
  113. package/dist/src/core/memory-engine.js +0 -183
  114. package/dist/src/core/project-manager.js +0 -243
  115. package/dist/src/core/types.js +0 -1
  116. package/dist/src/embeddings/batch-embedder.js +0 -1
  117. package/dist/src/embeddings/cache.js +0 -1
  118. package/dist/src/embeddings/embedder.js +0 -51
  119. package/dist/src/embeddings/index.js +0 -4
  120. package/dist/src/embeddings/local.js +0 -37
  121. package/dist/src/embeddings/provider.js +0 -1
  122. package/dist/src/embeddings/remote.js +0 -76
  123. package/dist/src/embeddings/test-connection.js +0 -16
  124. package/dist/src/hooks/after-edit.js +0 -3
  125. package/dist/src/hooks/after-tool.js +0 -3
  126. package/dist/src/hooks/auto-context.js +0 -68
  127. package/dist/src/hooks/auto-impact-guard.js +0 -94
  128. package/dist/src/hooks/auto-retrieval.js +0 -27
  129. package/dist/src/hooks/before-agent.js +0 -18
  130. package/dist/src/hooks/before-compact.js +0 -3
  131. package/dist/src/hooks/before-edit.js +0 -20
  132. package/dist/src/hooks/index.js +0 -11
  133. package/dist/src/hooks/runtime.js +0 -110
  134. package/dist/src/hooks/session-end.js +0 -3
  135. package/dist/src/hooks/session-start.js +0 -3
  136. package/dist/src/index.js +0 -22
  137. package/dist/src/mcp/bootstrap.js +0 -68
  138. package/dist/src/mcp/context.js +0 -1
  139. package/dist/src/mcp/index.js +0 -3
  140. package/dist/src/mcp/server.js +0 -45
  141. package/dist/src/mcp/tools/analyze-impact.js +0 -41
  142. package/dist/src/mcp/tools/dead-code.js +0 -55
  143. package/dist/src/mcp/tools/find-callers.js +0 -24
  144. package/dist/src/mcp/tools/find-dependencies.js +0 -57
  145. package/dist/src/mcp/tools/find-symbol.js +0 -7
  146. package/dist/src/mcp/tools/get-architecture.js +0 -11
  147. package/dist/src/mcp/tools/graph-dependents.js +0 -24
  148. package/dist/src/mcp/tools/graph-neighborhood.js +0 -58
  149. package/dist/src/mcp/tools/graph-path.js +0 -43
  150. package/dist/src/mcp/tools/graph-query-utils.js +0 -32
  151. package/dist/src/mcp/tools/impact-guard.js +0 -34
  152. package/dist/src/mcp/tools/index-repository.js +0 -1
  153. package/dist/src/mcp/tools/index.js +0 -20
  154. package/dist/src/mcp/tools/memory-decisions.js +0 -1
  155. package/dist/src/mcp/tools/memory-forget.js +0 -14
  156. package/dist/src/mcp/tools/memory-recent.js +0 -1
  157. package/dist/src/mcp/tools/memory-remember.js +0 -33
  158. package/dist/src/mcp/tools/memory-rules.js +0 -1
  159. package/dist/src/mcp/tools/memory-search.js +0 -18
  160. package/dist/src/mcp/tools/memory-todos.js +0 -1
  161. package/dist/src/mcp/tools/project-context.js +0 -25
  162. package/dist/src/mcp/tools/search-code.js +0 -21
  163. package/dist/src/mcp/tools/semantic-code-search.js +0 -33
  164. package/dist/src/mcp/tools/snapshot-create.js +0 -13
  165. package/dist/src/mcp/tools/snapshot-list.js +0 -7
  166. package/dist/src/mcp/tools/snapshot-restore.js +0 -13
  167. package/dist/src/mcp/tools/trace-calls.js +0 -37
  168. package/dist/src/memory/activity.js +0 -5
  169. package/dist/src/memory/conflict-detector.js +0 -105
  170. package/dist/src/memory/consolidator.js +0 -104
  171. package/dist/src/memory/decay.js +0 -59
  172. package/dist/src/memory/decisions.js +0 -3
  173. package/dist/src/memory/deduplicate.js +0 -25
  174. package/dist/src/memory/index.js +0 -11
  175. package/dist/src/memory/maintenance.js +0 -16
  176. package/dist/src/memory/remember.js +0 -3
  177. package/dist/src/memory/rules.js +0 -3
  178. package/dist/src/memory/search.js +0 -3
  179. package/dist/src/memory/summaries.js +0 -1
  180. package/dist/src/memory/todos.js +0 -3
  181. package/dist/src/processor/decision-extractor.js +0 -13
  182. package/dist/src/processor/importance-scorer.js +0 -22
  183. package/dist/src/processor/index.js +0 -7
  184. package/dist/src/processor/memory-extractor.js +0 -59
  185. package/dist/src/processor/memory-processor.js +0 -105
  186. package/dist/src/processor/rule-extractor.js +0 -13
  187. package/dist/src/processor/summarizer.js +0 -71
  188. package/dist/src/processor/todo-extractor.js +0 -12
  189. package/dist/src/production/config-check.js +0 -34
  190. package/dist/src/production/doctor.js +0 -58
  191. package/dist/src/production/full-index.js +0 -114
  192. package/dist/src/production/health.js +0 -58
  193. package/dist/src/production/index-pipeline.js +0 -151
  194. package/dist/src/production/index.js +0 -4
  195. package/dist/src/production/project-lock.js +0 -95
  196. package/dist/src/production/project-status.js +0 -16
  197. package/dist/src/production/recovery.js +0 -15
  198. package/dist/src/production/setup.js +0 -219
  199. package/dist/src/production/snapshot-cli.js +0 -58
  200. package/dist/src/project-manual/cli.js +0 -77
  201. package/dist/src/project-manual/index.js +0 -2
  202. package/dist/src/project-manual/manager.js +0 -147
  203. package/dist/src/project-manual/types.js +0 -1
  204. package/dist/src/retrieval/bm25/index.js +0 -1
  205. package/dist/src/retrieval/bm25/search.js +0 -1
  206. package/dist/src/retrieval/bm25.js +0 -30
  207. package/dist/src/retrieval/context-budget.js +0 -1
  208. package/dist/src/retrieval/context-builder.js +0 -22
  209. package/dist/src/retrieval/graph/index.js +0 -1
  210. package/dist/src/retrieval/graph/search.js +0 -1
  211. package/dist/src/retrieval/hybrid/hybrid-search.js +0 -1
  212. package/dist/src/retrieval/hybrid/index.js +0 -1
  213. package/dist/src/retrieval/hybrid-search.js +0 -68
  214. package/dist/src/retrieval/importance.js +0 -16
  215. package/dist/src/retrieval/index.js +0 -12
  216. package/dist/src/retrieval/query-analyzer.js +0 -32
  217. package/dist/src/retrieval/query-classifier.js +0 -1
  218. package/dist/src/retrieval/query-expansion.js +0 -1
  219. package/dist/src/retrieval/recency.js +0 -12
  220. package/dist/src/retrieval/reranker/index.js +0 -1
  221. package/dist/src/retrieval/reranker/reranker.js +0 -1
  222. package/dist/src/retrieval/retrieval-engine.js +0 -17
  223. package/dist/src/retrieval/tokenizer.js +0 -9
  224. package/dist/src/retrieval/type-priority.js +0 -10
  225. package/dist/src/retrieval/types.js +0 -1
  226. package/dist/src/retrieval/vector/index.js +0 -4
  227. package/dist/src/retrieval/vector/metadata-filter.js +0 -1
  228. package/dist/src/retrieval/vector/persistence.js +0 -67
  229. package/dist/src/retrieval/vector/search.js +0 -12
  230. package/dist/src/retrieval/vector/test-persistence.js +0 -36
  231. package/dist/src/retrieval/vector/upsert.js +0 -40
  232. package/dist/src/retrieval/vector/vector-store.js +0 -89
  233. package/dist/src/retrieval/vector-hybrid-engine.js +0 -91
  234. package/dist/src/runtime/bootstrap.js +0 -28
  235. package/dist/src/runtime/graceful.js +0 -17
  236. package/dist/src/runtime/index.js +0 -3
  237. package/dist/src/runtime/toolnet-memory-runtime.js +0 -156
  238. package/dist/src/security/encryption.js +0 -1
  239. package/dist/src/security/file-filter.js +0 -30
  240. package/dist/src/security/index.js +0 -3
  241. package/dist/src/security/sanitizer.js +0 -49
  242. package/dist/src/security/secret-scanner.js +0 -56
  243. package/dist/src/session/agy/adapter.js +0 -159
  244. package/dist/src/session/agy/cli.js +0 -87
  245. package/dist/src/session/agy/hook-installer.js +0 -62
  246. package/dist/src/session/agy/hook.js +0 -167
  247. package/dist/src/session/agy/index.js +0 -5
  248. package/dist/src/session/agy/project-resolver.js +0 -27
  249. package/dist/src/session/agy/recovery.js +0 -112
  250. package/dist/src/session/agy/transcript.js +0 -191
  251. package/dist/src/session/codex/adapter.js +0 -138
  252. package/dist/src/session/codex/cli.js +0 -236
  253. package/dist/src/session/codex/context-hook-installer.js +0 -70
  254. package/dist/src/session/codex/context-hook.js +0 -69
  255. package/dist/src/session/codex/discovery.js +0 -138
  256. package/dist/src/session/codex/index.js +0 -6
  257. package/dist/src/session/codex/notify-installer.js +0 -135
  258. package/dist/src/session/codex/project-resolver.js +0 -25
  259. package/dist/src/session/codex/recovery.js +0 -27
  260. package/dist/src/session/codex/rollout.js +0 -186
  261. package/dist/src/session/core.js +0 -239
  262. package/dist/src/session/identity.js +0 -57
  263. package/dist/src/session/index.js +0 -9
  264. package/dist/src/session/learner/cli.js +0 -62
  265. package/dist/src/session/learner/extractor.js +0 -461
  266. package/dist/src/session/learner/index.js +0 -4
  267. package/dist/src/session/learner/journal.js +0 -159
  268. package/dist/src/session/learner/learner.js +0 -124
  269. package/dist/src/session/learner/types.js +0 -1
  270. package/dist/src/session/opencode/adapter.js +0 -553
  271. package/dist/src/session/opencode/cli.js +0 -121
  272. package/dist/src/session/opencode/index.js +0 -2
  273. package/dist/src/session/opencode/plugin-installer.js +0 -230
  274. package/dist/src/session/store.js +0 -242
  275. package/dist/src/session/types.js +0 -1
  276. package/dist/src/session/utils.js +0 -47
  277. package/dist/src/session/wal.js +0 -303
  278. package/dist/src/snapshot/index.js +0 -2
  279. package/dist/src/snapshot/manager.js +0 -130
  280. package/dist/src/snapshot/test-snapshot.js +0 -28
  281. package/dist/src/snapshot/types.js +0 -1
  282. package/dist/src/storage/architecture-store.js +0 -37
  283. package/dist/src/storage/cleanup-health.js +0 -20
  284. package/dist/src/storage/code-analysis-store.js +0 -35
  285. package/dist/src/storage/code-chunk-store.js +0 -25
  286. package/dist/src/storage/code-graph-store.js +0 -24
  287. package/dist/src/storage/code-manifest-store.js +0 -24
  288. package/dist/src/storage/code-vector-store.js +0 -25
  289. package/dist/src/storage/github/client.js +0 -1
  290. package/dist/src/storage/github/index.js +0 -1
  291. package/dist/src/storage/google-drive/client.js +0 -1
  292. package/dist/src/storage/google-drive/index.js +0 -1
  293. package/dist/src/storage/huggingface/client.js +0 -116
  294. package/dist/src/storage/huggingface/index.js +0 -1
  295. package/dist/src/storage/index.js +0 -16
  296. package/dist/src/storage/list-bucket-raw.js +0 -14
  297. package/dist/src/storage/list-bucket-tree.js +0 -38
  298. package/dist/src/storage/local/client.js +0 -99
  299. package/dist/src/storage/local/index.js +0 -1
  300. package/dist/src/storage/memory-store.js +0 -30
  301. package/dist/src/storage/project/cleanup-layout-v1.js +0 -72
  302. package/dist/src/storage/project/folder.js +0 -15
  303. package/dist/src/storage/project/index.js +0 -3
  304. package/dist/src/storage/project/layout.js +0 -74
  305. package/dist/src/storage/project/migrate-layout-v2.js +0 -101
  306. package/dist/src/storage/project/migrate.js +0 -73
  307. package/dist/src/storage/project/scoped-provider.js +0 -165
  308. package/dist/src/storage/provider.js +0 -26
  309. package/dist/src/storage/retrying-provider.js +0 -23
  310. package/dist/src/storage/test-connection.js +0 -32
  311. package/dist/src/storage/type-resolution-store.js +0 -26
  312. package/dist/src/storage/types.js +0 -1
  313. package/dist/src/storage/vector-store.js +0 -30
  314. package/dist/src/storage/visualization-store.js +0 -25
  315. package/dist/src/sync/compressor.js +0 -1
  316. package/dist/src/sync/conflict-resolver.js +0 -1
  317. package/dist/src/sync/downloader.js +0 -1
  318. package/dist/src/sync/index.js +0 -1
  319. package/dist/src/sync/sync-engine.js +0 -1
  320. package/dist/src/sync/upload-queue.js +0 -1
  321. package/dist/src/utils/retry.js +0 -29
  322. package/dist/src/visualization/server.js +0 -270
  323. package/dist/src/work-continuity/brief-cache.js +0 -107
  324. package/dist/src/work-continuity/brief.js +0 -349
  325. package/dist/src/work-continuity/cli.js +0 -96
  326. package/dist/src/work-continuity/context-cli.js +0 -106
  327. package/dist/src/work-continuity/context-runtime-cli.js +0 -88
  328. package/dist/src/work-continuity/extractor.js +0 -339
  329. package/dist/src/work-continuity/handoff.js +0 -185
  330. package/dist/src/work-continuity/index.js +0 -14
  331. package/dist/src/work-continuity/injection.js +0 -84
  332. package/dist/src/work-continuity/journal.js +0 -49
  333. package/dist/src/work-continuity/learner.js +0 -127
  334. package/dist/src/work-continuity/reducer.js +0 -316
  335. package/dist/src/work-continuity/semantic-extractor.js +0 -360
  336. package/dist/src/work-continuity/semantic-journal.js +0 -55
  337. package/dist/src/work-continuity/semantic-learner.js +0 -125
  338. package/dist/src/work-continuity/semantic-reducer.js +0 -268
  339. package/dist/src/work-continuity/semantic-types.js +0 -1
  340. package/dist/src/work-continuity/types.js +0 -1
  341. package/dist/visualization/public/index.html +0 -2896
  342. package/dist/visualization/public/vendor/3d-force-graph.min.js +0 -5
package/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  # TOOLNET MEMORY
4
4
 
5
- ### Persistent memory & code intelligence for AI coding agents
5
+ ### Persistent project memory & code intelligence for AI coding agents
6
6
 
7
- **Keep project knowledge, work continuity and agent handoffs across sessions.**
7
+ **Continue the same project across OpenCode, Agy and Codex without losing context.**
8
8
 
9
9
  [![npm](https://img.shields.io/npm/v/toolnet-memory?style=flat-square)](https://www.npmjs.com/package/toolnet-memory)
10
10
  [![Node.js](https://img.shields.io/badge/Node.js-22%2B-339933?style=flat-square&logo=node.js&logoColor=white)](https://nodejs.org/)
@@ -14,19 +14,63 @@
14
14
 
15
15
  ---
16
16
 
17
- ## What is ToolNet Memory?
17
+ ## What does ToolNet Memory do?
18
18
 
19
- ToolNet Memory is a lightweight persistent memory layer for AI coding agents.
19
+ ToolNet Memory is a persistent memory layer for AI coding agents.
20
20
 
21
- It keeps project state alive when you:
21
+ Its job is simple: **help the next AI understand the project before it continues the work.**
22
22
 
23
- - stop a session and continue tomorrow,
24
- - move from OpenCode to Agy or Codex,
25
- - hit token limits,
26
- - resume a partially completed plan,
27
- - need the next agent to understand not only **what to do next**, but also **why**.
23
+ A coding agent normally loses important context when a session ends, tokens run out, you change tools, move to another VPS, or return to the project days later. The new agent may be able to read the source code, but it often does not know the original goal, why an architecture was chosen, what has already been completed, what is still in progress, or which project rules must not be violated.
28
24
 
29
- Instead of blindly telling the next agent “continue Phase 4”, ToolNet can preserve the project mission, current objective, rationale, completed work, active phase, blockers, rules and next actions.
25
+ ToolNet Memory preserves that project knowledge separately from any single AI agent.
26
+
27
+ ```text
28
+ OpenCode stops at Phase 3
29
+
30
+ ToolNet Memory
31
+
32
+ Agy opens the same project
33
+
34
+ Understands the mission, rationale,
35
+ completed work, current objective,
36
+ constraints and next actions
37
+
38
+ Continues Phase 4
39
+
40
+ Agy later stops at Phase 6
41
+
42
+ ToolNet Memory
43
+
44
+ Codex continues Phase 7
45
+ ```
46
+
47
+ It is **not just chat history**. ToolNet extracts and preserves durable working context such as:
48
+
49
+ - what the project is building,
50
+ - the current objective,
51
+ - why the work matters,
52
+ - why a specific implementation direction was chosen,
53
+ - completed and active phases/tasks,
54
+ - deliverables and Definition of Done,
55
+ - architecture decisions,
56
+ - dependencies and blockers,
57
+ - project operating rules,
58
+ - important warnings,
59
+ - next actions.
60
+
61
+ The result is a shared technical memory layer between your project and your AI coding agents:
62
+
63
+ ```text
64
+ OpenCode / Agy / Codex
65
+
66
+ ToolNet Memory
67
+
68
+ Project Memory + Work State
69
+ + Semantic Context + Code Intelligence
70
+
71
+ The next agent continues with context
72
+ instead of restarting from zero
73
+ ```
30
74
 
31
75
  ---
32
76
 
@@ -129,23 +173,6 @@ Warnings
129
173
  Next Actions
130
174
  ```
131
175
 
132
- Example:
133
-
134
- ```text
135
- OpenCode
136
-
137
- Completes Phase 1–3
138
-
139
- ToolNet Memory
140
-
141
- Agy starts
142
-
143
- Understands mission, rationale,
144
- completed work and current objective
145
-
146
- Continues Phase 4
147
- ```
148
-
149
176
  ### Semantic Work Context
150
177
 
151
178
  ToolNet can preserve:
@@ -36,8 +36,8 @@ run() {
36
36
 
37
37
  case "$COMMAND" in
38
38
  setup)
39
- if [ -f "$ROOT/dist/src/production/setup.js" ]; then
40
- exec node "$ROOT/dist/src/production/setup.js" "$@"
39
+ if [ -f "$ROOT/bundle/setup.js" ]; then
40
+ exec node "$ROOT/bundle/setup.js" "$@"
41
41
  elif [ -f "$ROOT/src/production/setup.ts" ]; then
42
42
  exec npx --yes tsx "$ROOT/src/production/setup.ts" "$@"
43
43
  else
@@ -48,7 +48,7 @@ case "$COMMAND" in
48
48
 
49
49
 
50
50
  doctor)
51
- run dist/src/production/doctor.js src/production/doctor.ts
51
+ run bundle/doctor.js src/production/doctor.ts
52
52
  ;;
53
53
 
54
54
  run)
@@ -56,11 +56,11 @@ case "$COMMAND" in
56
56
  ;;
57
57
 
58
58
  mcp)
59
- run dist/src/mcp/bootstrap.js src/mcp/bootstrap.ts
59
+ run bundle/mcp.js src/mcp/bootstrap.ts
60
60
  ;;
61
61
 
62
62
  index)
63
- run dist/src/production/full-index.js src/production/full-index.ts
63
+ run bundle/full-index.js src/production/full-index.ts
64
64
  ;;
65
65
 
66
66
  index:graph)
@@ -82,28 +82,28 @@ case "$COMMAND" in
82
82
  ;;
83
83
 
84
84
  snapshot:list)
85
- run dist/src/production/snapshot-cli.js src/production/snapshot-cli.ts list
85
+ run bundle/snapshot.js src/production/snapshot-cli.ts list
86
86
  ;;
87
87
 
88
88
  snapshot:create)
89
89
  shift
90
- run dist/src/production/snapshot-cli.js src/production/snapshot-cli.ts create "$@"
90
+ run bundle/snapshot.js src/production/snapshot-cli.ts create "$@"
91
91
  ;;
92
92
 
93
93
  snapshot:restore)
94
94
  shift
95
- run dist/src/production/snapshot-cli.js src/production/snapshot-cli.ts restore "$@"
95
+ run bundle/snapshot.js src/production/snapshot-cli.ts restore "$@"
96
96
  ;;
97
97
 
98
98
  recover)
99
- run dist/src/production/snapshot-cli.js src/production/snapshot-cli.ts recover-latest
99
+ run bundle/snapshot.js src/production/snapshot-cli.ts recover-latest
100
100
  ;;
101
101
 
102
102
  session:opencode-sync)
103
103
  shift
104
104
 
105
- if [ -f "$ROOT/dist/src/session/opencode/cli.js" ]; then
106
- exec node "$ROOT/dist/src/session/opencode/cli.js" sync "$@"
105
+ if [ -f "$ROOT/bundle/opencode.js" ]; then
106
+ exec node "$ROOT/bundle/opencode.js" sync "$@"
107
107
  fi
108
108
 
109
109
  if [ -n "${TSX:-}" ] && [ -x "${TSX:-}" ]; then
@@ -117,8 +117,8 @@ case "$COMMAND" in
117
117
  session:opencode-recover)
118
118
  shift
119
119
 
120
- if [ -f "$ROOT/dist/src/session/opencode/cli.js" ]; then
121
- exec node "$ROOT/dist/src/session/opencode/cli.js" recover "$@"
120
+ if [ -f "$ROOT/bundle/opencode.js" ]; then
121
+ exec node "$ROOT/bundle/opencode.js" recover "$@"
122
122
  fi
123
123
 
124
124
  if [ -n "${TSX:-}" ] && [ -x "${TSX:-}" ]; then
@@ -132,8 +132,8 @@ case "$COMMAND" in
132
132
  integrate:opencode)
133
133
  shift
134
134
 
135
- if [ -f "$ROOT/dist/src/session/opencode/cli.js" ]; then
136
- exec node "$ROOT/dist/src/session/opencode/cli.js" install-plugin "$@"
135
+ if [ -f "$ROOT/bundle/opencode.js" ]; then
136
+ exec node "$ROOT/bundle/opencode.js" install-plugin "$@"
137
137
  fi
138
138
 
139
139
  if [ -n "${TSX:-}" ] && [ -x "${TSX:-}" ]; then
@@ -161,8 +161,8 @@ case "$COMMAND" in
161
161
  session:agy-sync)
162
162
  shift
163
163
 
164
- if [ -f "$ROOT/dist/src/session/agy/cli.js" ]; then
165
- exec node "$ROOT/dist/src/session/agy/cli.js" sync "$@"
164
+ if [ -f "$ROOT/bundle/agy.js" ]; then
165
+ exec node "$ROOT/bundle/agy.js" sync "$@"
166
166
  fi
167
167
 
168
168
  exec "$TSX" "$ROOT/src/session/agy/cli.ts" sync "$@"
@@ -171,8 +171,8 @@ case "$COMMAND" in
171
171
  session:agy-recover)
172
172
  shift
173
173
 
174
- if [ -f "$ROOT/dist/src/session/agy/cli.js" ]; then
175
- exec node "$ROOT/dist/src/session/agy/cli.js" recover "$@"
174
+ if [ -f "$ROOT/bundle/agy.js" ]; then
175
+ exec node "$ROOT/bundle/agy.js" recover "$@"
176
176
  fi
177
177
 
178
178
  exec "$TSX" "$ROOT/src/session/agy/cli.ts" recover "$@"
@@ -181,8 +181,8 @@ case "$COMMAND" in
181
181
  integrate:agy)
182
182
  shift
183
183
 
184
- if [ -f "$ROOT/dist/src/session/agy/cli.js" ]; then
185
- exec node "$ROOT/dist/src/session/agy/cli.js" install-hooks "$@"
184
+ if [ -f "$ROOT/bundle/agy.js" ]; then
185
+ exec node "$ROOT/bundle/agy.js" install-hooks "$@"
186
186
  fi
187
187
 
188
188
  exec "$TSX" "$ROOT/src/session/agy/cli.ts" install-hooks "$@"
@@ -191,8 +191,8 @@ case "$COMMAND" in
191
191
  session:codex-notify)
192
192
  shift
193
193
 
194
- if [ -f "$ROOT/dist/src/session/codex/cli.js" ]; then
195
- exec node "$ROOT/dist/src/session/codex/cli.js" notify "$@"
194
+ if [ -f "$ROOT/bundle/codex.js" ]; then
195
+ exec node "$ROOT/bundle/codex.js" notify "$@"
196
196
  fi
197
197
 
198
198
  if [ -x "${TSX:-}" ]; then
@@ -205,8 +205,8 @@ case "$COMMAND" in
205
205
  session:codex-sync)
206
206
  shift
207
207
 
208
- if [ -f "$ROOT/dist/src/session/codex/cli.js" ]; then
209
- exec node "$ROOT/dist/src/session/codex/cli.js" sync "$@"
208
+ if [ -f "$ROOT/bundle/codex.js" ]; then
209
+ exec node "$ROOT/bundle/codex.js" sync "$@"
210
210
  fi
211
211
 
212
212
  exec "$TSX" "$ROOT/src/session/codex/cli.ts" sync "$@"
@@ -215,8 +215,8 @@ case "$COMMAND" in
215
215
  session:codex-recover)
216
216
  shift
217
217
 
218
- if [ -f "$ROOT/dist/src/session/codex/cli.js" ]; then
219
- exec node "$ROOT/dist/src/session/codex/cli.js" recover "$@"
218
+ if [ -f "$ROOT/bundle/codex.js" ]; then
219
+ exec node "$ROOT/bundle/codex.js" recover "$@"
220
220
  fi
221
221
 
222
222
  exec "$TSX" "$ROOT/src/session/codex/cli.ts" recover "$@"
@@ -225,8 +225,8 @@ case "$COMMAND" in
225
225
  integrate:codex)
226
226
  shift
227
227
 
228
- if [ -f "$ROOT/dist/src/session/codex/cli.js" ]; then
229
- exec node "$ROOT/dist/src/session/codex/cli.js" install-notify "$@"
228
+ if [ -f "$ROOT/bundle/codex.js" ]; then
229
+ exec node "$ROOT/bundle/codex.js" install-notify "$@"
230
230
  fi
231
231
 
232
232
  exec "$TSX" "$ROOT/src/session/codex/cli.ts" install-notify "$@"
@@ -235,8 +235,8 @@ case "$COMMAND" in
235
235
  memory:reconcile)
236
236
  shift
237
237
 
238
- if [ -f "$ROOT/dist/src/session/learner/cli.js" ]; then
239
- exec node "$ROOT/dist/src/session/learner/cli.js" reconcile "$@"
238
+ if [ -f "$ROOT/bundle/learner.js" ]; then
239
+ exec node "$ROOT/bundle/learner.js" reconcile "$@"
240
240
  fi
241
241
 
242
242
  if [ -x "${TSX:-}" ]; then
@@ -250,8 +250,8 @@ case "$COMMAND" in
250
250
  project:manual-init)
251
251
  shift
252
252
 
253
- if [ -f "$ROOT/dist/src/project-manual/cli.js" ]; then
254
- exec node "$ROOT/dist/src/project-manual/cli.js" init "$@"
253
+ if [ -f "$ROOT/bundle/project-manual.js" ]; then
254
+ exec node "$ROOT/bundle/project-manual.js" init "$@"
255
255
  fi
256
256
 
257
257
  exec "$TSX" "$ROOT/src/project-manual/cli.ts" init "$@"
@@ -260,8 +260,8 @@ case "$COMMAND" in
260
260
  project:manual-show)
261
261
  shift
262
262
 
263
- if [ -f "$ROOT/dist/src/project-manual/cli.js" ]; then
264
- exec node "$ROOT/dist/src/project-manual/cli.js" show "$@"
263
+ if [ -f "$ROOT/bundle/project-manual.js" ]; then
264
+ exec node "$ROOT/bundle/project-manual.js" show "$@"
265
265
  fi
266
266
 
267
267
  exec "$TSX" "$ROOT/src/project-manual/cli.ts" show "$@"
@@ -270,8 +270,8 @@ case "$COMMAND" in
270
270
  project:manual-sync)
271
271
  shift
272
272
 
273
- if [ -f "$ROOT/dist/src/project-manual/cli.js" ]; then
274
- exec node "$ROOT/dist/src/project-manual/cli.js" sync "$@"
273
+ if [ -f "$ROOT/bundle/project-manual.js" ]; then
274
+ exec node "$ROOT/bundle/project-manual.js" sync "$@"
275
275
  fi
276
276
 
277
277
  exec "$TSX" "$ROOT/src/project-manual/cli.ts" sync "$@"
@@ -280,8 +280,8 @@ case "$COMMAND" in
280
280
  work:status)
281
281
  shift
282
282
 
283
- if [ -f "$ROOT/dist/src/work-continuity/cli.js" ]; then
284
- exec node "$ROOT/dist/src/work-continuity/cli.js" status "$@"
283
+ if [ -f "$ROOT/bundle/work-continuity.js" ]; then
284
+ exec node "$ROOT/bundle/work-continuity.js" status "$@"
285
285
  fi
286
286
 
287
287
  exec "$TSX" "$ROOT/src/work-continuity/cli.ts" status "$@"
@@ -290,8 +290,8 @@ case "$COMMAND" in
290
290
  work:json)
291
291
  shift
292
292
 
293
- if [ -f "$ROOT/dist/src/work-continuity/cli.js" ]; then
294
- exec node "$ROOT/dist/src/work-continuity/cli.js" json "$@"
293
+ if [ -f "$ROOT/bundle/work-continuity.js" ]; then
294
+ exec node "$ROOT/bundle/work-continuity.js" json "$@"
295
295
  fi
296
296
 
297
297
  exec "$TSX" "$ROOT/src/work-continuity/cli.ts" json "$@"
@@ -300,8 +300,8 @@ case "$COMMAND" in
300
300
  work:reconcile)
301
301
  shift
302
302
 
303
- if [ -f "$ROOT/dist/src/work-continuity/cli.js" ]; then
304
- exec node "$ROOT/dist/src/work-continuity/cli.js" reconcile "$@"
303
+ if [ -f "$ROOT/bundle/work-continuity.js" ]; then
304
+ exec node "$ROOT/bundle/work-continuity.js" reconcile "$@"
305
305
  fi
306
306
 
307
307
  exec "$TSX" "$ROOT/src/work-continuity/cli.ts" reconcile "$@"
@@ -310,8 +310,8 @@ case "$COMMAND" in
310
310
  brief)
311
311
  shift
312
312
 
313
- if [ -f "$ROOT/dist/src/work-continuity/context-cli.js" ]; then
314
- exec node "$ROOT/dist/src/work-continuity/context-cli.js" brief "$@"
313
+ if [ -f "$ROOT/bundle/context.js" ]; then
314
+ exec node "$ROOT/bundle/context.js" brief "$@"
315
315
  fi
316
316
 
317
317
  exec "$TSX" "$ROOT/src/work-continuity/context-cli.ts" brief "$@"
@@ -320,8 +320,8 @@ case "$COMMAND" in
320
320
  brief:json)
321
321
  shift
322
322
 
323
- if [ -f "$ROOT/dist/src/work-continuity/context-cli.js" ]; then
324
- exec node "$ROOT/dist/src/work-continuity/context-cli.js" brief-json "$@"
323
+ if [ -f "$ROOT/bundle/context.js" ]; then
324
+ exec node "$ROOT/bundle/context.js" brief-json "$@"
325
325
  fi
326
326
 
327
327
  exec "$TSX" "$ROOT/src/work-continuity/context-cli.ts" brief-json "$@"
@@ -330,8 +330,8 @@ case "$COMMAND" in
330
330
  handoff:latest)
331
331
  shift
332
332
 
333
- if [ -f "$ROOT/dist/src/work-continuity/context-cli.js" ]; then
334
- exec node "$ROOT/dist/src/work-continuity/context-cli.js" handoff-latest "$@"
333
+ if [ -f "$ROOT/bundle/context.js" ]; then
334
+ exec node "$ROOT/bundle/context.js" handoff-latest "$@"
335
335
  fi
336
336
 
337
337
  exec "$TSX" "$ROOT/src/work-continuity/context-cli.ts" handoff-latest "$@"
@@ -340,8 +340,8 @@ case "$COMMAND" in
340
340
  context:sync)
341
341
  shift
342
342
 
343
- if [ -f "$ROOT/dist/src/work-continuity/context-runtime-cli.js" ]; then
344
- exec node "$ROOT/dist/src/work-continuity/context-runtime-cli.js" sync "$@"
343
+ if [ -f "$ROOT/bundle/context-runtime.js" ]; then
344
+ exec node "$ROOT/bundle/context-runtime.js" sync "$@"
345
345
  fi
346
346
 
347
347
  exec "$TSX" "$ROOT/src/work-continuity/context-runtime-cli.ts" sync "$@"
@@ -350,8 +350,8 @@ case "$COMMAND" in
350
350
  context:print)
351
351
  shift
352
352
 
353
- if [ -f "$ROOT/dist/src/work-continuity/context-runtime-cli.js" ]; then
354
- exec node "$ROOT/dist/src/work-continuity/context-runtime-cli.js" print "$@"
353
+ if [ -f "$ROOT/bundle/context-runtime.js" ]; then
354
+ exec node "$ROOT/bundle/context-runtime.js" print "$@"
355
355
  fi
356
356
 
357
357
  exec "$TSX" "$ROOT/src/work-continuity/context-runtime-cli.ts" print "$@"
@@ -360,8 +360,8 @@ case "$COMMAND" in
360
360
  context:refresh)
361
361
  shift
362
362
 
363
- if [ -f "$ROOT/dist/src/work-continuity/context-runtime-cli.js" ]; then
364
- exec node "$ROOT/dist/src/work-continuity/context-runtime-cli.js" refresh "$@"
363
+ if [ -f "$ROOT/bundle/context-runtime.js" ]; then
364
+ exec node "$ROOT/bundle/context-runtime.js" refresh "$@"
365
365
  fi
366
366
 
367
367
  exec "$TSX" "$ROOT/src/work-continuity/context-runtime-cli.ts" refresh "$@"
package/bundle/agy.js ADDED
@@ -0,0 +1,88 @@
1
+ import{existsSync as St,readFileSync as vt}from"node:fs";import{homedir as bt}from"node:os";import{join as wt}from"node:path";function jt(t){let e=t.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
2
+ `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function kt(){let t=process.env.TOOLNET_GLOBAL_ENV??wt(bt(),".config","toolnet-memory",".env");if(!St(t))return;let e=vt(t,"utf8");for(let n of e.split(/\r?\n/)){let r=n.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let s=r.indexOf("=");if(s<=0)continue;let o=r.slice(0,s).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(o)&&process.env[o]===void 0&&(process.env[o]=jt(r.slice(s+1)))}}kt();function K(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function L(t,e){if(!t)return e;let n=Number(t);return Number.isFinite(n)?n:e}function be(){return{memory:{autoCapture:K(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:K(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:K(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:K(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:L(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:L(process.env.MEMORY_RERANK_TOP,10),finalContext:L(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:L(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:L(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as xt}from"node:crypto";import{existsSync as ce,mkdirSync as It,readFileSync as Pt,renameSync as Ot,writeFileSync as At}from"node:fs";import{basename as Et,dirname as q,join as D,parse as ke,resolve as z}from"node:path";var xe=".toolnet",Mt="project.json";function Rt(t){return xt("sha256").update(t).digest("hex").slice(0,16)}function ue(t){return D(t,xe,Mt)}function Nt(t){return ce(ue(t))}function Tt(t,e){let n=z(t),r=ke(n).root;for(;;){if(Nt(n))return n;if(n===r||e&&n===z(e))break;let s=q(n);if(s===n)break;n=s}return null}function Ct(t){let e=z(t),n=ke(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>ce(D(e,o))))return e;if(e===n)break;let s=q(e);if(s===e)break;e=s}return z(t)}function _t(t){let e;try{e=JSON.parse(Pt(t,"utf8"))}catch(s){throw new Error(`Invalid ToolNet project manifest: ${t}: ${s instanceof Error?s.message:String(s)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${t}`);let n=e;if(typeof n.id!="string"||!n.id.trim())throw new Error(`ToolNet project manifest is missing id: ${t}`);if(typeof n.name!="string"||!n.name.trim())throw new Error(`ToolNet project manifest is missing name: ${t}`);let r=new Date().toISOString();return{version:1,id:n.id,name:n.name,remote:typeof n.remote=="string"&&n.remote.trim()?n.remote:n.name,rootPath:typeof n.rootPath=="string"?n.rootPath:q(q(t)),createdAt:typeof n.createdAt=="string"?n.createdAt:r,updatedAt:typeof n.updatedAt=="string"?n.updatedAt:r,graphVersion:typeof n.graphVersion=="number"?n.graphVersion:0,memoryVersion:typeof n.memoryVersion=="number"?n.memoryVersion:0,metadata:n.metadata&&typeof n.metadata=="object"?n.metadata:void 0}}function we(t,e){let n=D(t,xe);It(n,{recursive:!0});let r=ue(t),s=`${r}.tmp-${process.pid}`;At(s,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),Ot(s,r)}function je(t,e){return{id:t.id,name:t.name,remote:t.remote,rootPath:e,createdAt:t.createdAt,updatedAt:t.updatedAt,graphVersion:t.graphVersion,memoryVersion:t.memoryVersion,metadata:t.metadata}}var B=class{detect(e=process.cwd()){let n=z(e),r=Ct(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>ce(D(r,d))),i=Tt(n,o?r:void 0);if(i){let d=ue(i),p=_t(d);return p.rootPath!==i&&(p.rootPath=i,p.updatedAt=new Date().toISOString(),we(i,p)),je(p,i)}let c=new Date().toISOString(),u=Et(r),a={version:1,id:Rt(r),name:u,remote:u,rootPath:r,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return we(r,a),je(a,r)}};var $t=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_\-]{20,}\b/g},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._\-]{16,}\b/gi},{type:"jwt",regex:/\beyJ[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\b/g},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/g},{type:"password_assignment",regex:/\b(password|passwd|pwd)\s*[:=]\s*["']?[^"'\s]{6,}["']?/gi},{type:"secret_assignment",regex:/\b(secret|api[_-]?key|access[_-]?token|refresh[_-]?token)\s*[:=]\s*["']?[^"'\s]{8,}["']?/gi},{type:"cookie",regex:/\b(cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi}],J=class{scan(e){let n=[];for(let r of $t){let s=new RegExp(r.regex.source,r.regex.flags);for(let o of e.matchAll(s))n.push({type:r.type,value:o[0]})}return n}hasSecrets(e){return this.scan(e).length>0}};var W=class{scanner=new J;sanitize(e){let n=e,r=this.scanner.scan(e),s=new Set;for(let o of r)s.add(o.type),n=n.split(o.value).join(`[REDACTED:${o.type}]`);return{text:n,redacted:r.length,secretTypes:[...s]}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(n=>this.sanitizeValue(n));if(e&&typeof e=="object"){let n={};for(let[r,s]of Object.entries(e)){let o=r.toLowerCase();o.includes("password")||o.includes("secret")||o.includes("token")||o.includes("cookie")||o.includes("authorization")?n[r]="[REDACTED]":n[r]=this.sanitizeValue(s)}return n}return e}};import{homedir as Zt}from"node:os";import{join as Qt}from"node:path";import{DeleteObjectCommand as Lt,GetObjectCommand as zt,HeadObjectCommand as Wt,ListObjectsV2Command as Ft,PutObjectCommand as Kt,S3Client as qt}from"@aws-sdk/client-s3";import{getSignedUrl as Bt}from"@aws-sdk/s3-request-presigner";var V=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new qt({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,n,r="application/octet-stream"){let s=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new Kt({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await Bt(this.client,new zt({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(n,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`HF download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await this.client.send(new Wt({Bucket:this.bucket,Key:e})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(e){await this.client.send(new Lt({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new Ft({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&n.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return n}};import{access as Ie,mkdir as Dt,readFile as Jt,readdir as Vt,rm as Ut,stat as Pe,writeFile as Ht}from"node:fs/promises";import{dirname as Yt,join as Gt,relative as Oe,resolve as Xt}from"node:path";var F=class{constructor(e){this.root=e}root;name="local";path(e){let n=e.replace(/^\/+/,"");return Xt(this.root,n)}async put(e,n){let r=this.path(e);await Dt(Yt(r),{recursive:!0}),await Ht(r,n)}async get(e){try{return await Jt(this.path(e))}catch(n){if(typeof n=="object"&&n!==null&&"code"in n&&n.code==="ENOENT")return null;throw n}}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await Ie(this.path(e)),!0}catch{return!1}}async delete(e){await Ut(this.path(e),{force:!0})}async list(e=""){let n=this.path(e),r=[];try{await Ie(n)}catch{return r}let s=async i=>{let c=await Vt(i,{withFileTypes:!0});for(let u of c){let a=Gt(i,u.name);if(u.isDirectory()){await s(a);continue}let d=await Pe(a);r.push({key:Oe(this.root,a),size:d.size,updatedAt:d.mtime.toISOString()})}},o=await Pe(n);return o.isDirectory()?await s(n):r.push({key:Oe(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};function Ae(t){let e=t.localRoot??Qt(Zt(),".toolnet-memory","storage");if(t.provider==="huggingface"){let n=t.huggingface;return n?.namespace&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new V({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):(console.warn("[storage] Hugging Face credentials missing. Using local fallback."),new F(e))}return new F(e)}function en(t){return new Promise(e=>setTimeout(e,t))}async function Ee(t,e={}){let n=Math.max(1,e.attempts??3),r=e.baseDelayMs??150,s=e.maxDelayMs??2e3,o;for(let i=1;i<=n;i++)try{return await t()}catch(c){if(o=c,i>=n)break;let u=Math.min(s,r*2**(i-1)),a=Math.floor(Math.random()*Math.max(1,u*.2));await en(u+a)}throw o}var tn=new Set(["put","get","getText","delete","list"]);function Me(t,e={}){return new Proxy(t,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:tn.has(r)?(...o)=>Ee(()=>Promise.resolve(s.apply(n,o)),e):s.bind(n)}})}function Re(t){let e=t.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function Ne(t){let e=t.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let n=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let s=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return s?`${s[1]}memory/records/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),s?`${s[1]}memory/vectors/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),s?`${s[1]}code/graph/${s[2]}`:e))}var U=class{constructor(e,n,r,s){this.provider=e;this.name=e.name,this.projectId=n,this.projectName=r,this.folder=Re(s??r),this.sourcePrefix=`projects/${n}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,n=new Date().toISOString(),r=n,s=await this.provider.getText(e);if(s){let i;try{i=JSON.parse(s)}catch(c){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${c instanceof Error?c.message:String(c)}`)}if(typeof i.id=="string"&&i.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${i.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof i.createdAt=="string"&&(r=i.createdAt)}let o={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:n};await this.provider.put(e,JSON.stringify(o,null,2)+`
4
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=Ne(e),e===this.sourcePrefix)return this.targetPrefix;if(e.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+e.slice(this.sourcePrefix.length);if(e===this.targetPrefix||e.startsWith(`${this.targetPrefix}/`))return e;if(e.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${e}`].join(" "));return e}async put(e,n,r){return await this.ensureRegistered(),this.provider.put(this.key(e),n,r)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{homedir as he}from"node:os";import{join as lt,resolve as Rr}from"node:path";import{join as un}from"node:path";import{createHash as nn}from"node:crypto";import{dirname as rn}from"node:path";import{mkdirSync as sn,readFileSync as on,renameSync as an,writeFileSync as cn}from"node:fs";function v(t){return nn("sha256").update(t).digest("hex")}function pe(t){if(Array.isArray(t))return t.map(pe);if(t&&typeof t=="object"){let e=t,n={};for(let r of Object.keys(e).sort())n[r]=pe(e[r]);return n}return t}function Te(t){return JSON.stringify(pe(t))}function Ce(t){try{return JSON.parse(on(t,"utf8"))}catch{return null}}function O(t,e){sn(rn(t),{recursive:!0});let n=`${t}.${process.pid}.tmp`;cn(n,JSON.stringify(e,null,2)+`
5
+ `,{encoding:"utf8",mode:384}),an(n,t)}function _e(t,e){let n=t.trim(),r=n.replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,""),s=v(n).slice(0,12);if(!r||r==="."||r==="..")return`${e}--${s}`;let o=r.slice(0,100);return o===n&&n.length<=100?o:`${o.slice(0,85)}--${s}`}function $e(t,e,n){let r=e.trim(),s=n.trim();if(!r)throw new Error("Session agent is required");if(!s)throw new Error("Native session ID is required");let o=_e(r.toLowerCase(),"agent"),i=_e(s,"session");return{projectId:t.id,projectName:t.name,projectRoot:t.rootPath,agent:r,nativeSessionId:s,sessionKey:`${r}:${s}`,remotePrefix:["projects",t.id,"sessions",o,i].join("/"),localDirectory:un(t.rootPath,".toolnet","sessions",o,i)}}function Le(t){return String(t).padStart(12,"0")}var H=class{constructor(e,n=100,r=512*1024){this.storage=e;this.maxEventsPerChunk=n;this.maxChunkBytes=r;if(n<1)throw new Error("maxEventsPerChunk must be positive");if(r<1024)throw new Error("maxChunkBytes is too small")}storage;maxEventsPerChunk;maxChunkBytes;async getJson(e){let n=await this.storage.getText(e);return n?JSON.parse(n):null}async putJson(e,n){await this.storage.put(e,JSON.stringify(n,null,2)+`
6
+ `,"application/json")}async scan(e){let n=`${e.remotePrefix}/events/`,r=await this.storage.list(n),s=[],o=0;for(let i of r){let c=i.key.match(/\/events\/(\d+)-(\d+)-[a-f0-9]+\.jsonl$/);if(!c)continue;let u=Number(c[1]),a=Number(c[2]);!Number.isFinite(u)||!Number.isFinite(a)||(s.push({key:i.key,start:u,end:a}),o=Math.max(o,a))}return s.sort((i,c)=>i.start-c.start),{chunks:s,maxSequence:o}}split(e){let n=[],r=[],s=0;for(let o of e){let i=Buffer.byteLength(JSON.stringify(o)+`
7
+ `,"utf8");r.length>0&&(r.length>=this.maxEventsPerChunk||s+i>this.maxChunkBytes)&&(n.push(r),r=[],s=0),r.push(o),s+=i}return r.length>0&&n.push(r),n}async loadManifest(e){return this.getJson(`${e.remotePrefix}/session.json`)}async loadCursor(e){return this.getJson(`${e.remotePrefix}/cursor.json`)}async recover(e){let n=await this.scan(e);return{maxSequence:n.maxSequence,chunkCount:n.chunks.length}}async append(e,n,r,s={}){let o=await this.loadManifest(e),i=await this.scan(e),c=n.filter(m=>m.sequence>i.maxSequence),u=0;for(let m of this.split(c)){let y=m[0],b=m[m.length-1],M=m.map(R=>JSON.stringify(R)).join(`
8
+ `)+`
9
+ `,N=v(M).slice(0,16),P=[e.remotePrefix,"events",`${Le(y.sequence)}-${Le(b.sequence)}-${N}.jsonl`].join("/");await this.storage.exists(P)||await this.storage.put(P,M,"application/x-ndjson"),u+=m.length}let a=await this.scan(e),d=n[n.length-1],p=o?.status??"active";d?.type==="session_end"||d?.type==="session_idle"?p="idle":d?.type==="error"?p="error":n.length>0&&(p="active");let f=new Date().toISOString(),h=n[0],S={version:1,projectId:e.projectId,projectName:e.projectName,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,status:p,createdAt:o?.createdAt??h?.timestamp??f,updatedAt:d?.timestamp??f,firstEventAt:o?.firstEventAt??h?.timestamp,lastEventAt:d?.timestamp??o?.lastEventAt,eventCount:a.maxSequence,chunkCount:a.chunks.length,metadata:{...o?.metadata,...s.metadata}};(s.title??o?.title)&&(S.title=s.title??o?.title);let g={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,lastLocalSequence:n.length>0?n[n.length-1].sequence:a.maxSequence,lastRemoteSequence:a.maxSequence,sourceCursors:r,updatedAt:f};return await this.putJson(`${e.remotePrefix}/cursor.json`,g),await this.putJson(`${e.remotePrefix}/session.json`,S),{uploadedEvents:u,lastRemoteSequence:a.maxSequence,eventCount:S.eventCount,chunkCount:S.chunkCount,status:p}}};import{closeSync as le,existsSync as pn,fsyncSync as ln,mkdirSync as dn,openSync as de,readSync as mn,rmSync as ze,statSync as We,writeSync as fn}from"node:fs";import{join as me}from"node:path";var gn=12e4,yn=80,hn=2e3;function Sn(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var Y=class{constructor(e){this.identity=e;dn(e.localDirectory,{recursive:!0}),this.eventsFile=me(e.localDirectory,"events.jsonl"),this.stateFile=me(e.localDirectory,"state.json"),this.lockFile=me(e.localDirectory,"journal.lock")}identity;eventsFile;stateFile;lockFile;initialState(){let e=new Date().toISOString();return{version:1,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,status:"idle",createdAt:e,updatedAt:e,lastSequence:0,lastRemoteSequence:0,remoteByteOffset:0,sourceCursors:{},recentEventIds:[]}}loadStateUnsafe(){return Ce(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){O(this.stateFile,e)}acquireLock(){for(let e=0;e<yn;e+=1)try{return de(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-We(this.lockFile).mtimeMs>gn){ze(this.lockFile,{force:!0});continue}}catch{}Sn(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let n=this.acquireLock();try{return e()}finally{le(n),ze(this.lockFile,{force:!0})}}append(e){return e.length===0?[]:this.withLock(()=>{let n=this.loadStateUnsafe(),r=new Set(n.recentEventIds),s=n.lastSequence,o=[];for(let p of e){let f=p.timestamp??new Date().toISOString(),h=p.data??{},S=p.provenance?.rawDigest??v(Te(h)),g=p.sourceEventId?[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,p.sourceEventId].join("|"):[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,s+1,p.type,f,S].join("|"),m=v(g).slice(0,32);if(r.has(m))continue;s+=1;let y={version:1,id:m,sequence:s,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,type:p.type,timestamp:f,data:h,provenance:{...p.provenance,rawDigest:S}};p.role!==void 0&&(y.role=p.role),p.sourceEventId!==void 0&&(y.sourceEventId=p.sourceEventId),p.sourceSequence!==void 0&&(y.sourceSequence=p.sourceSequence),o.push(y),r.add(m)}if(o.length===0)return[];let i=o.map(p=>JSON.stringify(p)).join(`
10
+ `)+`
11
+ `,c=de(this.eventsFile,"a",384);try{fn(c,i,null,"utf8"),ln(c)}finally{le(c)}let u=o[o.length-1],a="active";u.type==="session_end"||u.type==="session_idle"?a="idle":u.type==="error"&&(a="error");let d=Array.from(r).slice(-hn);return this.saveStateUnsafe({...n,status:a,updatedAt:u.timestamp,lastSequence:u.sequence,recentEventIds:d}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!pn(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let n=We(this.eventsFile).size,r=Math.min(e.remoteByteOffset,n);if(n<=r)return{events:[],startOffset:r,endOffset:n};let s=n-r,o=Buffer.alloc(s),i=de(this.eventsFile,"r");try{mn(i,o,0,s,r)}finally{le(i)}return{events:o.toString("utf8").split(`
12
+ `).filter(Boolean).map(a=>JSON.parse(a)),startOffset:r,endOffset:n}})}markRemote(e,n){this.withLock(()=>{let r=this.loadStateUnsafe();this.saveStateUnsafe({...r,lastRemoteSequence:Math.max(r.lastRemoteSequence,e),remoteByteOffset:Math.max(r.remoteByteOffset,n),updatedAt:new Date().toISOString()})})}setSourceCursor(e,n){this.withLock(()=>{let r=this.loadStateUnsafe();this.saveStateUnsafe({...r,sourceCursors:{...r.sourceCursors,[e]:String(n)},updatedAt:new Date().toISOString()})})}};import{closeSync as Cn,existsSync as _n,openSync as $n,readSync as Ln,statSync as zn}from"node:fs";function Fe(t,e){let n=e.toLowerCase();return n.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||n.includes("tuy\u1EC7t \u0111\u1ED1i")||n.includes("must not")||n.includes("never ")?"critical":t==="rule"||t==="decision"?"high":t==="todo"||n.includes("error")||n.includes("failed")||n.includes("exception")?"normal":"temporary"}var De=[/không được/iu,/tuyệt đối/iu,/bắt buộc/iu,/đừng\s+/iu,/must not/iu,/do not/iu,/don't/iu,/\bnever\b/iu],vn=[/từ giờ/iu,/về sau/iu,/mỗi lần/iu,/luôn luôn/iu,/\bluôn\b/iu,/quy tắc/iu,/workflow/iu,/\balways\b/iu,/\brequired\b/iu,/\bmust\b/iu,/from now on/iu],bn=[/\bchốt\b/iu,/quyết định/iu,/sẽ dùng/iu,/chọn .+ thay/iu,/đổi sang/iu,/chuyển sang/iu,/\bdecided\b/iu,/\bchosen\b/iu,/we will use/iu,/use .+ instead/iu,/switch(?:ed)? to/iu],wn=[/\btodo\b/iu,/cần làm/iu,/cần thêm/iu,/cần sửa/iu,/cần kiểm tra/iu,/tiếp theo/iu,/bước tiếp theo/iu,/còn phải/iu,/còn cần/iu,/next step/iu,/\bneed to\b/iu,/\bremaining\b/iu,/follow[- ]?up/iu],jn=[/đã sửa/iu,/đã fix/iu,/đã khắc phục/iu,/đã xử lý/iu,/hoàn tất/iu,/hoàn thành/iu,/\bfixed\b/iu,/\bresolved\b/iu,/\bimplemented\b/iu,/\bcompleted\b/iu,/\bpasses?\b/iu],Ke=[/kiến trúc/iu,/pipeline/iu,/adapter/iu,/schema/iu,/runtime/iu,/namespace/iu,/storage/iu,/lưu trữ/iu,/workflow/iu,/session core/iu,/memory engine/iu,/retrieval/iu],kn=[/\bdùng\b/iu,/\btách\b/iu,/\bthay\b/iu,/\bchuyển\b/iu,/\blưu\b/iu,/\bmap\b/iu,/\buse\b/iu,/\bsplit\b/iu,/\bstore\b/iu,/\breplace\b/iu,/\bmove\b/iu],xn=[/đường dẫn/iu,/\bpath\b/iu,/\bport\b/iu,/\bendpoint\b/iu,/\bdomain\b/iu,/\bbucket\b/iu,/\brepository\b/iu,/\brepo\b/iu,/\bbranch\b/iu,/\/[A-Za-z0-9._/-]{4,}/u],In=[/\blà\b/iu,/\bở\b/iu,/\bdùng\b/iu,/\bnằm\b/iu,/\bis\b/iu,/\buse\b/iu,/located/iu,/runs on/iu],qe=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),Pn=new Set(["payload","data","content","message","messages","parts","summary"]);function k(t,e){return e.some(n=>n.test(t))}function Je(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function On(t){return Je(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function An(t){return!(t.length<12||t.length>1e3||(t.match(new RegExp("\\p{L}","gu"))??[]).length<6||/^(?:https?:\/\/\S+|[A-Za-z0-9+/=]{80,})$/u.test(t))}function fe(t,e,n,r=0){if(!(r>6)){if(typeof t=="string"){(!e||qe.has(e))&&n.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))fe(s,e,n,r+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(qe.has(s)||Pn.has(s))&&fe(o,s,n,r+1)}}function En(t){let e=[];fe(t.data,void 0,e);let n=[],r=new Set;for(let s of e)for(let o of s.split(/\n+|(?<=[.!?])\s+/u)){let i=Je(o);if(An(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function Be(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function Mn(t,e,n){if(n.type==="decision")return{kind:"decision",confidence:1};if(n.type==="todo")return{kind:"todo",confidence:1};let r=e==="user"||n.type==="user_prompt",s=e==="assistant"||n.type==="assistant_message";return r&&k(t,De)?{kind:"rule",confidence:.98}:r&&k(t,vn)?{kind:"rule",confidence:.92}:k(t,bn)?{kind:k(t,Ke)?"architecture":"decision",confidence:r?.93:.86}:r&&k(t,wn)?{kind:"todo",confidence:.87}:k(t,Ke)&&k(t,kn)?{kind:"architecture",confidence:r?.88:.82}:s&&k(t,jn)?{kind:"fix",confidence:.8}:r&&k(t,xn)&&k(t,In)?{kind:"context",confidence:.79}:null}function Rn(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function Nn(t,e,n){return t==="rule"&&k(n,De)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":Fe(e,n)}function Ve(t,e){let n=[],r=new Set,s=new Map;for(let o of e){let i=typeof o.data.messageId=="string"?o.data.messageId:void 0,c=Be(o);i&&c&&s.set(i,c)}for(let o of e){let i=Be(o),c=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&c&&(i=s.get(c)??"");for(let u of En(o)){let a=Mn(u,i,o);if(!a||a.confidence<.75)continue;let d=Rn(a.kind),p=On(u),f=v([t.projectId,a.kind,p].join("|"));if(r.has(f))continue;r.add(f);let h=o.provenance.sourcePath?[o.provenance.sourcePath]:[],S=o.sourceEventId?[o.sourceEventId]:[];n.push({version:1,fingerprint:f,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,kind:a.kind,type:d,content:u,confidence:a.confidence,importance:Nn(a.kind,d,u),tags:[d],provenance:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventIds:[o.id],sourceEventIds:S,sourcePaths:h,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return n}function Ue(t){return String(t).padStart(12,"0")}function Tn(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var G=class{constructor(e){this.storage=e}storage;async write(e,n,r){if(r.length===0||n.length===0)return null;let s=Math.min(...n.map(d=>d.sequence)),o=Math.max(...n.map(d=>d.sequence)),i={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:s,lastSequence:o,candidateCount:r.length,candidates:r},c=JSON.stringify(i,null,2)+`
13
+ `,u=v(r.map(d=>d.fingerprint).sort().join("|")).slice(0,16),a=[Tn(e),"batches",`${Ue(s)}-${Ue(o)}-${u}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,c,"application/json"),a}};function Wn(t,e){if(!_n(t))return{events:[],nextOffset:e};let n=zn(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=n-r,o=Buffer.alloc(s),i=$n(t,"r");try{Ln(i,o,0,s,r)}finally{Cn(i)}let c=o.toString("utf8"),u=c.lastIndexOf(`
14
+ `);if(u<0)return{events:[],nextOffset:r};let a=c.slice(0,u+1);return{events:a.split(`
15
+ `).filter(Boolean).flatMap(p=>{try{return[JSON.parse(p)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var X=class{constructor(e){this.options=e;this.journal=new G(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["memory.learner.offset"]??0),r=Number.isFinite(n)?n:0,s=Wn(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=Ve(this.options.identity,s.events),i=!1;return o.length>0&&(i=!!await this.journal.write(this.options.identity,s.events,o)),this.options.wal.setSourceCursor("memory.learner.offset",s.nextOffset),{scannedEvents:s.events.length,candidates:o.length,journalWritten:i,nextOffset:s.nextOffset}}};import{closeSync as Vn,existsSync as Un,openSync as Hn,readSync as Yn,statSync as Gn}from"node:fs";var Fn=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function C(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Ye(t){return C(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function T(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))T(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Fn.has(r)||["data","payload","parts","messages"].includes(r))&&T(s,e,n+1)}}function Z(t){return/\b(cancelled|canceled)\b|đã hủy|bỏ qua/iu.test(t)?"cancelled":/\b(blocked|blocker)\b|đang vướng|bị vướng|đang kẹt|chưa thể/iu.test(t)?"blocked":/\b(completed|complete|done|finished|passed)\b|hoàn thành|hoàn tất|đã xong|đã làm xong|\bxong\b/iu.test(t)?"completed":/\bin[\s_-]*progress\b|working on|đang làm|đang thực hiện|đang xử lý|đang triển khai/iu.test(t)?"in_progress":"pending"}function He(t){let e=C(t);return/^(?:đang\s+làm|đang\s+thực\s+hiện|đang\s+xử\s+lý|đang\s+triển\s+khai|hoàn\s+thành|hoàn\s+tất|đã\s+xong|đã\s+làm\s+xong|xong|pending|in[\s_-]*progress|completed|complete|done|finished|blocked|cancelled|canceled)[.!]*$/iu.test(e)}function w(t,e,n,r,s={}){let o=C(r),i=s.key??Ye(o);return{version:1,id:v([t.projectId,n,i,e.id,o,s.status??"",s.order??""].join("|")).slice(0,32),projectId:t.projectId,kind:n,key:i,text:o,status:s.status,order:s.order,confidence:s.confidence??.85,occurredAt:e.timestamp,sequence:e.sequence,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId}}function Kn(t,e,n){let r=C(n);if(r.length<5||r.length>1200)return[];let s=[],o=/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r),i=r.match(/^(?:mục tiêu|goal|objective)\s*(?::|-)\s*(.+)$/iu);i?.[1]&&s.push(w(t,e,"goal",i[1],{confidence:.97}));let c=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);c?.[1]&&s.push(w(t,e,"plan",c[1],{confidence:.95}));let u=/\b(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?([^.;\n]{0,220})/giu,a;for(;!o&&(a=u.exec(r));){let f=Number(a[1]),h=C(a[2]??""),S=h&&!He(h)?`Phase ${f} - ${h}`:`Phase ${f}`;s.push(w(t,e,"phase",S,{key:`phase:${f}`,order:f,status:Z(r),confidence:.93}))}let d=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);d?.[2]&&s.push(w(t,e,"task",d[2],{status:d[1].trim()?"completed":Z(d[2]),confidence:.96}));let p=r.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(p?.[2]){let f=p[1]?Number(p[1]):void 0,h=C(p[2]),S=He(h);s.push(w(t,e,"task",S&&f!==void 0?`TODO ${f}`:h,{key:f!==void 0?`task:${f}`:Ye(h),order:f,status:Z(r),confidence:.93}))}if(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r)){let f=r.replace(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\s*(?::|-)?\s*/iu,"");f&&s.push(w(t,e,"next_action",f,{confidence:.9}))}return/\b(blocker|blocked)\b|đang vướng|bị vướng|đang kẹt/iu.test(r)&&s.push(w(t,e,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&s.push(w(t,e,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&s.push(w(t,e,"decision",r,{confidence:.9})),s}function Ge(t,e){if(e.length===0)return[];let n=[],r=new Set;function s(i){r.has(i.id)||(r.add(i.id),n.push(i))}for(let i of e){if(i.type==="decision"){let u=[];T(i.data,u);for(let a of u)s(w(t,i,"decision",a,{confidence:1}))}if(i.type==="todo"){let u=[];T(i.data,u);for(let a of u)s(w(t,i,"task",a,{status:Z(a),confidence:1}))}if(["file_write","file_edit"].includes(i.type))for(let u of["filePath","path","file"]){let a=i.data[u];typeof a=="string"&&a&&s(w(t,i,"file",a,{confidence:1}))}if(i.type==="test"){let u=[];T(i.data,u);for(let a of u)s(w(t,i,"test",a,{confidence:1}))}let c=[];T(i.data,c);for(let u of c)for(let a of u.split(/\n+/u))for(let d of Kn(t,i,a))s(d)}let o=e[e.length-1];return s(w(t,o,"session",`${t.agent}:${t.nativeSessionId}`,{key:t.sessionKey,confidence:1})),n}function Xe(t){return String(t).padStart(12,"0")}var Q=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(a=>a.sequence)),s=Math.max(...n.map(a=>a.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:r,lastSequence:s,observations:n},i=JSON.stringify(o,null,2)+`
16
+ `,c=v(n.map(a=>a.id).sort().join("|")).slice(0,16),u=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${Xe(r)}-${Xe(s)}-${c}.json`].join("/");return await this.storage.exists(u)||await this.storage.put(u,i,"application/json"),u}};import{join as Ze}from"node:path";import{mkdirSync as qn}from"node:fs";function Bn(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function _(t,e=20){let n=[],r=new Set;for(let s of t.slice().reverse()){let o=Bn(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=e))break}return n.reverse()}function Dn(t){return t.kind==="phase"?/^Phase\s+\d+$/iu.test(t.text):t.kind==="task"?/^(?:TODO|Task|Việc)\s+\d+$/iu.test(t.text):!1}function Qe(t,e){let n=e.status??t?.status??"pending",r=n;t&&(t.status==="completed"&&n!=="completed"?r="completed":n==="pending"&&(t.status==="in_progress"||t.status==="blocked")&&(r=t.status));let s=t&&Dn(e)?t.title:e.text;return{id:t?.id??v(e.key).slice(0,24),title:s,status:r,order:e.order??t?.order,confidence:Math.max(e.confidence,t?.confidence??0),updatedAt:e.occurredAt,updatedBy:{agent:e.agent,nativeSessionId:e.nativeSessionId,eventId:e.eventId}}}async function Jn(t,e){let n=`projects/${t.id}/work/observations/`,r=await e.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,c)=>i.key.localeCompare(c.key))){let i=await e.getText(o.key);if(i)try{let c=JSON.parse(i);c.version===1&&Array.isArray(c.observations)&&s.push(c)}catch{}}return s}async function ee(t,e){let r=(await Jn(t,e)).flatMap(l=>l.observations).sort((l,j)=>{let Se=l.occurredAt.localeCompare(j.occurredAt);if(Se!==0)return Se;let ve=l.sequence-j.sequence;return ve!==0?ve:l.id.localeCompare(j.id)}),s=new Map,o=new Map,i,c,u,a=[],d=[],p=[],f=[],h=[],S=[];for(let l of r)switch(l.kind){case"goal":i=l.text;break;case"plan":c=l.text;break;case"phase":s.set(l.key,Qe(s.get(l.key),l));break;case"task":o.set(l.key,Qe(o.get(l.key),l));break;case"decision":a.push(l.text);break;case"blocker":d.push(l.text);break;case"warning":p.push(l.text);break;case"next_action":f.push(l.text);break;case"file":h.push(l.text);break;case"test":S.push(l.text);break;case"session":u={agent:l.agent,nativeSessionId:l.nativeSessionId,sessionKey:l.sessionKey,updatedAt:l.occurredAt};break}let g=Array.from(s.values()).sort((l,j)=>(l.order??Number.MAX_SAFE_INTEGER)-(j.order??Number.MAX_SAFE_INTEGER)),m=Array.from(o.values()).sort((l,j)=>(l.order??Number.MAX_SAFE_INTEGER)-(j.order??Number.MAX_SAFE_INTEGER)),y=g.find(l=>l.status==="in_progress")??g.find(l=>l.status==="blocked")??g.find(l=>l.status==="pending"),b=m.find(l=>l.status==="in_progress")??m.find(l=>l.status==="blocked")??m.find(l=>l.status==="pending"),M=_([...f,...b?[b.title]:[],...!b&&y?[y.title]:[],...m.filter(l=>l.status==="pending").slice(0,5).map(l=>l.title)],8),N=_([...d,...g.filter(l=>l.status==="blocked").map(l=>l.title),...m.filter(l=>l.status==="blocked").map(l=>l.title)],20),P={version:1,projectId:t.id,projectName:t.name,goal:i,plan:c,phases:g,tasks:m,decisions:_(a,20),blockers:N,warnings:_(p,20),nextActions:M,filesTouched:_(h,30),tests:_(S,20),currentPhase:y,currentTask:b,progress:{phasesTotal:g.length,phasesCompleted:g.filter(l=>l.status==="completed").length,tasksTotal:m.length,tasksCompleted:m.filter(l=>l.status==="completed").length,blocked:g.filter(l=>l.status==="blocked").length+m.filter(l=>l.status==="blocked").length},lastSession:u,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},R=Ze(t.rootPath,".toolnet","work");return qn(R,{recursive:!0}),O(Ze(R,"current.json"),P),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(P,null,2)+`
17
+ `,"application/json"),P}async function et(t,e){let n=await e.getText(`projects/${t.id}/work/current.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}function Xn(t,e){if(!Un(t))return{events:[],nextOffset:e};let n=Gn(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=n-r,o=Buffer.alloc(s),i=Hn(t,"r");try{Yn(i,o,0,s,r)}finally{Vn(i)}let c=o.toString("utf8"),u=c.lastIndexOf(`
18
+ `);if(u<0)return{events:[],nextOffset:r};let a=c.slice(0,u+1);return{events:a.split(`
19
+ `).filter(Boolean).flatMap(p=>{try{return[JSON.parse(p)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var te=class{constructor(e){this.options=e;this.journal=new Q(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.continuity.offset"]??0),r=Xn(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let s=Ge(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await ee(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.continuity.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{closeSync as ir,existsSync as ar,openSync as cr,readSync as ur,statSync as pr}from"node:fs";var Zn=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function $(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function ge(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))ge(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Zn.has(r)||["data","payload","parts","messages"].includes(r))&&ge(s,e,n+1)}}function x(t,e,n,r,s,o=.95){let i=$(r);return{version:1,id:v([t.projectId,n,s.type,s.key??"",i.toLowerCase(),e.id].join("|")).slice(0,32),projectId:t.projectId,kind:n,value:i,scope:s.type,scopeKey:s.key,scopeOrder:s.order,confidence:o,evidence:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId,sequence:e.sequence,occurredAt:e.timestamp}}}function I(t,e){let n=t.toLowerCase();for(let r of e){let s=r.toLowerCase();if(n.startsWith(`${s}:`)||n.startsWith(`${s} -`)||n.startsWith(`${s} \u2014`))return $(t.slice(r.length+1))}return null}function Qn(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function er(t){return $(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function tt(t,e){let n=[],r=new Set;function s(o){!o.value||o.value.length<3||r.has(o.id)||(r.add(o.id),n.push(o))}for(let o of e){let i=[];ge(o.data,i);for(let c of i){let u={type:"project"},a=null;for(let d of c.split(/\r?\n/u)){let p=$(d);if(!p){a=null;continue}let f=p.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(f){let j=Number(f[1]);u={type:"phase",key:`phase:${j}`,order:j,title:$(f[2]??"")},a=null;continue}let h=p.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(h){let j=Number(h[1]);u={type:"task",key:`task:${j}`,order:j,title:$(h[2]??"")},a=null;continue}let S=I(p,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(S){s(x(t,o,"mission",S,{type:"project"},.99)),a=null;continue}let g=I(p,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(g){s(x(t,o,u.type==="phase"?"phase_objective":"objective",g,u,.98)),a=null;continue}let m=I(p,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(m){s(x(t,o,u.type==="phase"?"phase_why":"why",m,u,.98)),a=null;continue}let y=I(p,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(y){s(x(t,o,"desired_outcome",y,{type:"project"},.98)),a=null;continue}let b=I(p,["plan rationale","approach rationale","why this approach","t\u1EA1i sao ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn ki\u1EBFn tr\xFAc"]);if(b){s(x(t,o,"plan_rationale",b,{type:"project"},.98)),a=null;continue}let M=I(p,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(M){s(x(t,o,"phase_deliverable",M,u,.97)),a=null;continue}let N=I(p,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if(N){s(x(t,o,"acceptance_criterion",N,u,.98)),a="acceptance_criterion";continue}let P=I(p,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(P){s(x(t,o,"dependency",P,u,.97)),a="dependency";continue}let R=I(p,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(R){s(x(t,o,"open_question",R,u,.95)),a="open_question";continue}let l=I(p,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(l){s(x(t,o,"constraint",l,u,.97)),a="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(p)){a="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(p)){a="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(p)){a="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(p)){a="constraint";continue}if(a&&Qn(d)){s(x(t,o,a,er(d),u,.96));continue}a=null}}}return n}function nt(t){return String(t).padStart(12,"0")}var ne=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(u=>u.evidence.sequence)),s=Math.max(...n.map(u=>u.evidence.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,firstSequence:r,lastSequence:s,createdAt:new Date().toISOString(),observations:n},i=v(n.map(u=>u.id).sort().join("|")).slice(0,16),c=[`projects/${e.projectId}`,"work","semantic","observations",e.agent,e.nativeSessionId,`${nt(r)}-${nt(s)}-${i}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,JSON.stringify(o,null,2)+`
20
+ `,"application/json"),c}};import{mkdirSync as tr}from"node:fs";import{join as rt}from"node:path";function nr(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function rr(t,e){if(!e)return!0;let n=t.evidence.occurredAt.localeCompare(e.evidence.occurredAt);return n!==0?n>0:t.evidence.sessionKey===e.evidence.sessionKey?t.evidence.sequence>=e.evidence.sequence:t.confidence>=e.confidence}function A(t,e){return rr(e,t)?e:t}function E(t,e=30){let n=new Set,r=[];for(let s of t){let o=s.value.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim();!o||n.has(o)||(n.add(o),r.push(s))}return r.slice(-e)}async function sr(t,e){let n=`projects/${t.id}/work/semantic/observations/`,r=await e.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,c)=>i.key.localeCompare(c.key))){let i=await e.getText(o.key);if(i)try{let c=JSON.parse(i);c.version===1&&Array.isArray(c.observations)&&s.push(c)}catch{}}return s}function or(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function st(t,e){let r=(await sr(t,e)).flatMap(g=>g.observations).sort((g,m)=>{let y=g.evidence.occurredAt.localeCompare(m.evidence.occurredAt);return y!==0?y:g.evidence.sessionKey===m.evidence.sessionKey?g.evidence.sequence-m.evidence.sequence:g.id.localeCompare(m.id)}),s,o,i,c,u,a=new Map,d=[],p=[],f=[];for(let g of r){let m=nr(g);if(g.scope==="phase"&&g.scopeKey){let y=a.get(g.scopeKey)??or(g);switch(g.kind){case"phase_objective":y.objective=A(y.objective,m);break;case"phase_why":y.why=A(y.why,m);break;case"phase_deliverable":y.deliverable=A(y.deliverable,m);break;case"acceptance_criterion":y.acceptanceCriteria.push(m);break;case"dependency":y.dependencies.push(m);break;case"open_question":y.openQuestions.push(m);break;case"constraint":y.constraints.push(m);break;case"note":y.notes.push(m);break}a.set(y.key,y);continue}switch(g.kind){case"mission":s=A(s,m);break;case"objective":o=A(o,m);break;case"why":i=A(i,m);break;case"desired_outcome":c=A(c,m);break;case"plan_rationale":u=A(u,m);break;case"open_question":d.push(m);break;case"constraint":p.push(m);break;case"note":f.push(m);break}}for(let g of a.values())g.acceptanceCriteria=E(g.acceptanceCriteria,20),g.dependencies=E(g.dependencies,15),g.openQuestions=E(g.openQuestions,15),g.constraints=E(g.constraints,15),g.notes=E(g.notes,20);let h={version:1,projectId:t.id,projectName:t.name,mission:s,activeObjective:o,why:i,desiredOutcome:c,planRationale:u,phases:Array.from(a.values()).sort((g,m)=>g.order-m.order),openQuestions:E(d,20),constraints:E(p,20),notes:E(f,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},S=rt(t.rootPath,".toolnet","work");return tr(S,{recursive:!0}),O(rt(S,"semantic-current.json"),h),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(h,null,2)+`
21
+ `,"application/json"),h}function lr(t,e){if(!ar(t))return{events:[],nextOffset:e};let n=pr(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=Buffer.alloc(n-r),o=cr(t,"r");try{ur(o,s,0,s.length,r)}finally{ir(o)}let i=s.toString("utf8"),c=i.lastIndexOf(`
22
+ `);if(c<0)return{events:[],nextOffset:r};let u=i.slice(0,c+1);return{events:u.split(`
23
+ `).filter(Boolean).flatMap(a=>{try{return[JSON.parse(a)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(u,"utf8")}}var re=class{constructor(e){this.options=e;this.journal=new ne(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.semantic.offset"]??0),r=lr(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let s=tt(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await st(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.semantic.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{mkdirSync as wr}from"node:fs";import{join as ye}from"node:path";import{existsSync as at,mkdirSync as dr,readFileSync as mr,statSync as ot,writeFileSync as fr}from"node:fs";import{dirname as gr,join as yr}from"node:path";var it=64*1024,hr=`# ToolNet Project Operating Manual
24
+
25
+ This file contains persistent instructions for AI agents working on this project.
26
+
27
+ ## Critical Rules
28
+
29
+ <!--
30
+ Examples:
31
+
32
+ - [enforce] Never edit production files directly.
33
+ - [enforce] Edit source only in /path/to/source.
34
+ - [enforce] Deploy only with ./deploy.sh --apply
35
+ -->
36
+
37
+ ## Workflow
38
+
39
+ <!--
40
+ Describe the correct working process.
41
+ -->
42
+
43
+ ## Architecture
44
+
45
+ <!--
46
+ Important architecture conventions.
47
+ -->
48
+
49
+ ## Verification
50
+
51
+ <!--
52
+ Tests / QA required after changes.
53
+ -->
54
+
55
+ ## Known Gotchas
56
+
57
+ <!--
58
+ Things an AI agent should always remember.
59
+ -->
60
+
61
+ ## Preferences
62
+
63
+ <!--
64
+ - [advisory] Prefer small focused files.
65
+ -->
66
+ `;function ct(t){return yr(t.rootPath,".toolnet","PROJECT.md")}function Sr(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function vr(t){let e=[],n=new Set,r=/^\s*[-*]\s+\[(enforce|advisory)\]\s+(.+?)\s*$/gimu,s;for(;s=r.exec(t);){let o=s[1].toLowerCase(),i=Sr(s[2]);if(!i)continue;let c=`${o}:${i.toLowerCase()}`;n.has(c)||(n.add(c),e.push({id:v(c).slice(0,24),mode:o,text:i,source:"manual"}))}return e}function br(t){let e=ct(t);return at(e)||(dr(gr(e),{recursive:!0}),fr(e,hr,{encoding:"utf8",mode:384})),e}function ut(t,e=!1){let n=e?br(t):ct(t);if(!at(n))return null;if(ot(n).size>it)throw new Error(`PROJECT.md exceeds ${it} bytes`);let s=mr(n,"utf8");return{path:n,content:s,digest:v(s),rules:vr(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(ot(n).mtimeMs).toISOString()}}function jr(t){return{goal:t.goal,plan:t.plan,phases:t.phases.map(e=>({id:e.id,title:e.title,status:e.status,order:e.order})),tasks:t.tasks.map(e=>({id:e.id,title:e.title,status:e.status,order:e.order})),decisions:t.decisions,blockers:t.blockers,warnings:t.warnings,nextActions:t.nextActions,filesTouched:t.filesTouched,tests:t.tests}}function kr(t){return t.phases.some(e=>e.status==="pending"||e.status==="in_progress"||e.status==="blocked")||t.tasks.some(e=>e.status==="pending"||e.status==="in_progress"||e.status==="blocked")||t.nextActions.length>0||t.blockers.length>0}var se=class{constructor(e){this.options=e}options;async capture(e,n){let r=await et(this.options.project,this.options.storage);if(r||(r=await ee(this.options.project,this.options.storage)),!kr(r))return null;let s=ut(this.options.project,!1),o=s?s.rules.filter(f=>f.mode==="enforce").map(f=>f.text):[],i=v(JSON.stringify(jr(r))),c=v([this.options.project.id,this.options.identity.sessionKey,i].join("|")).slice(0,24),u=new Date().toISOString(),a={version:1,id:c,projectId:this.options.project.id,projectName:this.options.project.name,createdAt:u,reason:e,sourceSession:{agent:this.options.identity.agent,nativeSessionId:this.options.identity.nativeSessionId,sessionKey:this.options.identity.sessionKey,sequence:n},goal:r.goal,plan:r.plan,progress:r.progress,currentPhase:r.currentPhase,currentTask:r.currentTask,incompletePhases:r.phases.filter(f=>f.status!=="completed"&&f.status!=="cancelled"),incompleteTasks:r.tasks.filter(f=>f.status!=="completed"&&f.status!=="cancelled"),nextActions:r.nextActions.slice(0,10),blockers:r.blockers.slice(0,10),decisions:r.decisions.slice(-10),warnings:r.warnings.slice(-10),attention:[...o,...r.warnings].slice(0,20),filesTouched:r.filesTouched.slice(-20),tests:r.tests.slice(-15),stateDigest:i},d=`projects/${this.options.project.id}/work/handoffs/${c}.json`;await this.options.storage.exists(d)||await this.options.storage.put(d,JSON.stringify(a,null,2)+`
67
+ `,"application/json"),await this.options.storage.put(`projects/${this.options.project.id}/work/handoff-latest.json`,JSON.stringify(a,null,2)+`
68
+ `,"application/json");let p=ye(this.options.project.rootPath,".toolnet","work","handoffs");return wr(p,{recursive:!0}),O(ye(p,`${c}.json`),a),O(ye(this.options.project.rootPath,".toolnet","work","handoff-latest.json"),a),a}};var oe=class{identity;wal;remote;sanitizer=new W;learner;continuity;semantic;handoff;title;metadata;constructor(e){this.identity=$e(e.project,e.agent,e.nativeSessionId),this.title=e.title,this.metadata=this.sanitizer.sanitizeValue(e.metadata??{}),this.wal=new Y(this.identity),this.remote=new H(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new X({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new te({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.semantic=new re({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.handoff=new se({project:e.project,storage:e.storage,identity:this.identity})}sanitizeEvent(e){let n=e.provenance?{...e.provenance,metadata:this.sanitizer.sanitizeValue(e.provenance.metadata)}:void 0;return{...e,data:this.sanitizer.sanitizeValue(e.data??{}),provenance:n}}start(e={}){let n=this.wal.loadState();return this.record({type:n.lastSequence===0?"session_start":"session_resume",data:e,provenance:{source:this.identity.agent}})}record(e){return this.wal.append([this.sanitizeEvent(e)])[0]}recordMany(e){return this.wal.append(e.map(n=>this.sanitizeEvent(n)))}setSourceCursor(e,n){this.wal.setSourceCursor(e,n)}async flush(){let e=this.wal.readPending(),n=this.wal.loadState(),r=await this.remote.append(this.identity,e.events,n.sourceCursors,{title:this.title,metadata:this.metadata});if(e.events.length>0){let s=e.events[e.events.length-1];this.wal.markRemote(s.sequence,e.endOffset)}if(process.env.TOOLNET_SESSION_LEARNING!=="0")try{await this.learner.learnNew()}catch{}if(process.env.TOOLNET_WORK_CONTINUITY!=="0")try{await this.continuity.learnNew()}catch{}if(process.env.TOOLNET_SEMANTIC_CONTINUITY!=="0")try{await this.semantic.learnNew()}catch{}if(process.env.TOOLNET_SMART_HANDOFF!=="0"&&e.events.length>0)try{let s=e.events[e.events.length-1],o=["session_idle","session_end","session_compact"].includes(s.type)?s.type:"checkpoint";await this.handoff.capture(o,s.sequence)}catch{}return r}async idle(e={}){return this.record({type:"session_idle",data:e,provenance:{source:this.identity.agent}}),this.flush()}async end(e={}){return this.record({type:"session_end",data:e,provenance:{source:this.identity.agent}}),this.flush()}status(){return this.wal.loadState()}recoverRemote(){return this.remote.recover(this.identity)}};import{existsSync as xr,openSync as Ir,closeSync as Pr,readSync as Or,statSync as Ar}from"node:fs";function Er(t){let e=typeof t.role=="string"?t.role:"",n=typeof t.type=="string"?t.type.toLowerCase():"";return e==="user"||n.includes("user")?"user_prompt":e==="assistant"||n.includes("assistant")||n.includes("model")?"assistant_message":n.includes("tool")||"toolCall"in t||"tool_call"in t?"tool_call":n.includes("error")?"error":"message"}function Mr(t){let e=[t.timestamp,t.createdAt,t.time,t.created_at];for(let n of e){if(typeof n=="string"){let r=new Date(n);if(!Number.isNaN(r.getTime()))return r.toISOString()}if(typeof n=="number"){let r=n;r<1e11&&(r*=1e3);let s=new Date(r);if(!Number.isNaN(s.getTime()))return s.toISOString()}}return new Date().toISOString()}function pt(t,e={offset:0}){if(!xr(t))return{events:[],nextOffset:e.offset,reset:!1};let n=Ar(t).size,r=e.offset>n,s=r?0:e.offset;if(s===n)return{events:[],nextOffset:n,reset:r};let o=n-s,i=Buffer.alloc(o),c=Ir(t,"r");try{Or(c,i,0,o,s)}finally{Pr(c)}let u=i.toString("utf8"),a=u.lastIndexOf(`
69
+ `);if(a<0)return{events:[],nextOffset:s,reset:r};let d=u.slice(0,a+1),p=Buffer.byteLength(d,"utf8"),f=[],h=0;for(let S of d.split(`
70
+ `)){if(!S)continue;let g=Buffer.byteLength(S+`
71
+ `,"utf8"),m=s+h;h+=g;let y;try{y=JSON.parse(S)}catch{f.push({type:"custom",sourceEventId:`transcript:${m}`,sourceSequence:m,data:{format:"raw-line",content:S},provenance:{source:"agy-transcript",sourcePath:t,sourceOffset:m}});continue}let b=y&&typeof y=="object"&&!Array.isArray(y)?y:{value:y};f.push({type:Er(b),timestamp:Mr(b),role:typeof b.role=="string"?b.role:void 0,sourceEventId:`transcript:${m}`,sourceSequence:m,data:b,provenance:{source:"agy-transcript",sourcePath:t,sourceOffset:m}})}return{events:f,nextOffset:s+p,reset:r}}function Nr(t){return t==="~"?he():t.startsWith("~/")?lt(he(),t.slice(2)):t}async function ie(t){let e=t.conversationId.trim();if(!e)throw new Error("Agy conversationId is required");let n=Rr(Nr(t.transcriptPath)),r=new oe({project:t.project,storage:t.storage,agent:"agy",nativeSessionId:e,metadata:{source:"antigravity-hook",transcriptPath:n,workspacePaths:t.workspacePaths??[],artifactDirectoryPath:t.artifactDirectoryPath,modelName:t.modelName}}),s=r.status(),o=s.sourceCursors["agy.transcript.offset"],i=o?Number(o):0,c=pt(n,{offset:Number.isFinite(i)?i:0}),u=[];s.lastSequence===0&&u.push({type:"session_start",sourceEventId:`agy:${e}:start`,data:{workspacePaths:t.workspacePaths??[],transcriptPath:n,modelName:t.modelName},provenance:{source:"antigravity-hook",sourcePath:n}}),c.reset&&u.push({type:"custom",sourceEventId:`agy:${e}:transcript-reset:${c.nextOffset}`,data:{event:"transcript_reset",transcriptPath:n},provenance:{source:"agy-transcript",sourcePath:n}}),u.push(...c.events),t.phase==="stop"&&(t.error&&u.push({type:"error",sourceEventId:["agy",e,"stop-error",t.terminationReason??"",c.nextOffset].join(":"),data:{error:t.error,terminationReason:t.terminationReason,fullyIdle:t.fullyIdle},provenance:{source:"antigravity-stop-hook"}}),t.fullyIdle&&u.push({type:"session_idle",sourceEventId:["agy",e,"idle",c.nextOffset].join(":"),data:{terminationReason:t.terminationReason,fullyIdle:!0},provenance:{source:"antigravity-stop-hook"}}));let a=r.recordMany(u);r.setSourceCursor("agy.transcript.offset",c.nextOffset),t.phase&&r.setSourceCursor("agy.last.phase",t.phase);let d=await r.flush();return{conversationId:e,imported:a.length,eventCount:d.eventCount,chunkCount:d.chunkCount,status:d.status,transcriptOffset:c.nextOffset,reset:c.reset}}function dt(t){return lt(he(),".gemini","antigravity-cli","brain",t,".system_generated","logs","transcript.jsonl")}import{existsSync as Tr,mkdirSync as Cr,readFileSync as _r,writeFileSync as $r}from"node:fs";import{homedir as Lr}from"node:os";import{dirname as zr,join as Wr}from"node:path";function Fr(t){return`'${t.replace(/'/g,"'\\''")}'`}function mt(t={}){let e=t.hooksFile??Wr(Lr(),".gemini","config","hooks.json");Cr(zr(e),{recursive:!0});let n={};if(Tr(e))try{n=JSON.parse(_r(e,"utf8"))}catch(o){throw new Error(`Invalid existing Agy hooks.json: ${o instanceof Error?o.message:String(o)}`)}let r=t.binary??"toolnet-memory",s=`${Fr(r)} session:agy-hook`;return n["toolnet-memory"]={enabled:!0,PreInvocation:[{type:"command",command:`${s} pre`,timeout:15}],PostInvocation:[{type:"command",command:`${s} post`,timeout:15}],Stop:[{type:"command",command:`${s} stop`,timeout:30}]},$r(e,JSON.stringify(n,null,2)+`
72
+ `,{encoding:"utf8",mode:384}),e}import{existsSync as ft}from"node:fs";import{homedir as Kr}from"node:os";import{join as qr,resolve as gt}from"node:path";import{DatabaseSync as Br}from"node:sqlite";function yt(t){if(t.startsWith("file://"))try{return decodeURIComponent(new URL(t).pathname)}catch{return t}return t}function Dr(t){if(typeof t!="string"||!t)return[];try{let e=JSON.parse(t);if(Array.isArray(e))return e.filter(n=>typeof n=="string").map(yt)}catch{}return[yt(t)]}function Jr(t,e){let n=gt(t.rootPath);return e.some(r=>{let s=gt(r);return s===n||s.startsWith(n+"/")||n.startsWith(s+"/")})}async function ht(t,e,n=100){let r=process.env.AGY_SUMMARY_DB??qr(Kr(),".gemini","antigravity-cli","conversation_summaries.db");if(!ft(r))throw new Error(`Agy summary database not found: ${r}`);let s=new Br(r,{readOnly:!0});s.exec("PRAGMA query_only = ON");let o=s.prepare(`
73
+ SELECT
74
+ conversation_id,
75
+ title,
76
+ workspace_uris,
77
+ agent_name,
78
+ last_user_input_time
79
+ FROM conversation_summaries
80
+ ORDER BY
81
+ last_user_input_time DESC
82
+ `).all();s.close();let i=[];for(let c of o){let u=typeof c.conversation_id=="string"?c.conversation_id:"";if(!u)continue;let a=Dr(c.workspace_uris);if(!Jr(t,a))continue;let d=dt(u);if(ft(d)&&(i.push(await ie({project:t,storage:e,conversationId:u,transcriptPath:d,workspacePaths:a,modelName:typeof c.agent_name=="string"?c.agent_name:void 0,phase:"recover"})),i.length>=n))break}return i}function ae(t,e){let n=t.indexOf(e);return n>=0?t[n+1]:void 0}function Vr(t){let e=be(),n=Me(Ae({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3});return new U(n,t.id,t.name,t.remote??t.name)}async function Ur(){let[t="help",...e]=process.argv.slice(2);if(t==="install-hooks"){let o=mt({binary:ae(e,"--bin")});console.log(`\u2705 Agy hooks installed: ${o}`);return}let n=ae(e,"--project")??process.cwd(),r=new B().detect(n),s=Vr(r);if(t==="sync"){let o=e[0],i=ae(e,"--transcript");if(!o||!i)throw new Error("Usage: sync <conversation-id> --transcript <path>");let c=await ie({project:r,storage:s,conversationId:o,transcriptPath:i,phase:"recover"});console.log(JSON.stringify(c,null,2));return}if(t==="recover"){let o=Number(ae(e,"--limit")??100),i=await ht(r,s,Number.isFinite(o)?o:100);console.log(JSON.stringify({project:r.name,sessions:i.length,imported:i.reduce((c,u)=>c+u.imported,0)},null,2));return}console.log(`Agy Session Adapter
83
+
84
+ Commands:
85
+ install-hooks
86
+ sync <conversation-id> --transcript <path>
87
+ recover [--project PATH] [--limit N]
88
+ `)}Ur().catch(t=>{console.error(t instanceof Error?t.message:t),process.exit(1)});