@astragenie/astramemory-local 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (493) hide show
  1. package/CHANGELOG.md +341 -0
  2. package/README.md +419 -0
  3. package/dist/backup/retention.d.ts +15 -0
  4. package/dist/backup/retention.js +62 -0
  5. package/dist/backup/retention.js.map +1 -0
  6. package/dist/backup/snapshot.d.ts +21 -0
  7. package/dist/backup/snapshot.js +55 -0
  8. package/dist/backup/snapshot.js.map +1 -0
  9. package/dist/backup/verify.d.ts +23 -0
  10. package/dist/backup/verify.js +77 -0
  11. package/dist/backup/verify.js.map +1 -0
  12. package/dist/budget/tracker.d.ts +58 -0
  13. package/dist/budget/tracker.js +102 -0
  14. package/dist/budget/tracker.js.map +1 -0
  15. package/dist/capture/codex.d.ts +63 -0
  16. package/dist/capture/codex.js +0 -0
  17. package/dist/capture/codex.js.map +1 -0
  18. package/dist/cli/backup.d.ts +1 -0
  19. package/dist/cli/backup.js +112 -0
  20. package/dist/cli/backup.js.map +1 -0
  21. package/dist/cli/budget.d.ts +7 -0
  22. package/dist/cli/budget.js +44 -0
  23. package/dist/cli/budget.js.map +1 -0
  24. package/dist/cli/capture.d.ts +10 -0
  25. package/dist/cli/capture.js +113 -0
  26. package/dist/cli/capture.js.map +1 -0
  27. package/dist/cli/consolidate.d.ts +16 -0
  28. package/dist/cli/consolidate.js +146 -0
  29. package/dist/cli/consolidate.js.map +1 -0
  30. package/dist/cli/doctor.d.ts +1 -0
  31. package/dist/cli/doctor.js +54 -0
  32. package/dist/cli/doctor.js.map +1 -0
  33. package/dist/cli/entity-backfill.d.ts +10 -0
  34. package/dist/cli/entity-backfill.js +46 -0
  35. package/dist/cli/entity-backfill.js.map +1 -0
  36. package/dist/cli/hook-install.d.ts +45 -0
  37. package/dist/cli/hook-install.js +77 -0
  38. package/dist/cli/hook-install.js.map +1 -0
  39. package/dist/cli/index.d.ts +2 -0
  40. package/dist/cli/index.js +312 -0
  41. package/dist/cli/index.js.map +1 -0
  42. package/dist/cli/init.d.ts +16 -0
  43. package/dist/cli/init.js +431 -0
  44. package/dist/cli/init.js.map +1 -0
  45. package/dist/cli/mcp-stdio.d.ts +18 -0
  46. package/dist/cli/mcp-stdio.js +67 -0
  47. package/dist/cli/mcp-stdio.js.map +1 -0
  48. package/dist/cli/memory.d.ts +15 -0
  49. package/dist/cli/memory.js +52 -0
  50. package/dist/cli/memory.js.map +1 -0
  51. package/dist/cli/open-runtime-db.d.ts +15 -0
  52. package/dist/cli/open-runtime-db.js +37 -0
  53. package/dist/cli/open-runtime-db.js.map +1 -0
  54. package/dist/cli/pair.d.ts +29 -0
  55. package/dist/cli/pair.js +64 -0
  56. package/dist/cli/pair.js.map +1 -0
  57. package/dist/cli/providers.d.ts +10 -0
  58. package/dist/cli/providers.js +97 -0
  59. package/dist/cli/providers.js.map +1 -0
  60. package/dist/cli/queue-purge.d.ts +5 -0
  61. package/dist/cli/queue-purge.js +92 -0
  62. package/dist/cli/queue-purge.js.map +1 -0
  63. package/dist/cli/queue.d.ts +29 -0
  64. package/dist/cli/queue.js +73 -0
  65. package/dist/cli/queue.js.map +1 -0
  66. package/dist/cli/rebuild.d.ts +15 -0
  67. package/dist/cli/rebuild.js +70 -0
  68. package/dist/cli/rebuild.js.map +1 -0
  69. package/dist/cli/reembed-dim.d.ts +21 -0
  70. package/dist/cli/reembed-dim.js +199 -0
  71. package/dist/cli/reembed-dim.js.map +1 -0
  72. package/dist/cli/reinstall.d.ts +1 -0
  73. package/dist/cli/reinstall.js +205 -0
  74. package/dist/cli/reinstall.js.map +1 -0
  75. package/dist/cli/restore.d.ts +1 -0
  76. package/dist/cli/restore.js +167 -0
  77. package/dist/cli/restore.js.map +1 -0
  78. package/dist/cli/retag.d.ts +14 -0
  79. package/dist/cli/retag.js +62 -0
  80. package/dist/cli/retag.js.map +1 -0
  81. package/dist/cli/search.d.ts +66 -0
  82. package/dist/cli/search.js +174 -0
  83. package/dist/cli/search.js.map +1 -0
  84. package/dist/cli/serve.d.ts +9 -0
  85. package/dist/cli/serve.js +364 -0
  86. package/dist/cli/serve.js.map +1 -0
  87. package/dist/cli/service.d.ts +1 -0
  88. package/dist/cli/service.js +121 -0
  89. package/dist/cli/service.js.map +1 -0
  90. package/dist/cli/sync.d.ts +15 -0
  91. package/dist/cli/sync.js +61 -0
  92. package/dist/cli/sync.js.map +1 -0
  93. package/dist/cli/token.d.ts +24 -0
  94. package/dist/cli/token.js +77 -0
  95. package/dist/cli/token.js.map +1 -0
  96. package/dist/cli/wait-health.d.ts +4 -0
  97. package/dist/cli/wait-health.js +23 -0
  98. package/dist/cli/wait-health.js.map +1 -0
  99. package/dist/config/config.d.ts +127 -0
  100. package/dist/config/config.js +38 -0
  101. package/dist/config/config.js.map +1 -0
  102. package/dist/config/datadir.d.ts +30 -0
  103. package/dist/config/datadir.js +65 -0
  104. package/dist/config/datadir.js.map +1 -0
  105. package/dist/config/loader.d.ts +23 -0
  106. package/dist/config/loader.js +102 -0
  107. package/dist/config/loader.js.map +1 -0
  108. package/dist/config/migrate-dirs.d.ts +36 -0
  109. package/dist/config/migrate-dirs.js +132 -0
  110. package/dist/config/migrate-dirs.js.map +1 -0
  111. package/dist/config/persist-envs.d.ts +23 -0
  112. package/dist/config/persist-envs.js +119 -0
  113. package/dist/config/persist-envs.js.map +1 -0
  114. package/dist/config/resolve-runtime.d.ts +19 -0
  115. package/dist/config/resolve-runtime.js +53 -0
  116. package/dist/config/resolve-runtime.js.map +1 -0
  117. package/dist/config/secrets.d.ts +28 -0
  118. package/dist/config/secrets.js +38 -0
  119. package/dist/config/secrets.js.map +1 -0
  120. package/dist/config/sync-settings.d.ts +16 -0
  121. package/dist/config/sync-settings.js +34 -0
  122. package/dist/config/sync-settings.js.map +1 -0
  123. package/dist/config/writer.d.ts +19 -0
  124. package/dist/config/writer.js +121 -0
  125. package/dist/config/writer.js.map +1 -0
  126. package/dist/consolidate/consolidate.d.ts +80 -0
  127. package/dist/consolidate/consolidate.js +0 -0
  128. package/dist/consolidate/consolidate.js.map +1 -0
  129. package/dist/consolidate/proposals.d.ts +35 -0
  130. package/dist/consolidate/proposals.js +66 -0
  131. package/dist/consolidate/proposals.js.map +1 -0
  132. package/dist/contracts/atom-wire.d.ts +48 -0
  133. package/dist/contracts/atom-wire.js +55 -0
  134. package/dist/contracts/atom-wire.js.map +1 -0
  135. package/dist/contracts/embed.d.ts +41 -0
  136. package/dist/contracts/embed.js +20 -0
  137. package/dist/contracts/embed.js.map +1 -0
  138. package/dist/contracts/index.d.ts +5 -0
  139. package/dist/contracts/index.js +6 -0
  140. package/dist/contracts/index.js.map +1 -0
  141. package/dist/contracts/job.d.ts +113 -0
  142. package/dist/contracts/job.js +32 -0
  143. package/dist/contracts/job.js.map +1 -0
  144. package/dist/contracts/llm.d.ts +30 -0
  145. package/dist/contracts/llm.js +2 -0
  146. package/dist/contracts/llm.js.map +1 -0
  147. package/dist/contracts/memory.d.ts +47 -0
  148. package/dist/contracts/memory.js +5 -0
  149. package/dist/contracts/memory.js.map +1 -0
  150. package/dist/contracts/vector.d.ts +29 -0
  151. package/dist/contracts/vector.js +2 -0
  152. package/dist/contracts/vector.js.map +1 -0
  153. package/dist/distill/flatten-turns.d.ts +1 -0
  154. package/dist/distill/flatten-turns.js +50 -0
  155. package/dist/distill/flatten-turns.js.map +1 -0
  156. package/dist/distill/pipeline.d.ts +45 -0
  157. package/dist/distill/pipeline.js +113 -0
  158. package/dist/distill/pipeline.js.map +1 -0
  159. package/dist/distill/prompts/extract.d.ts +122 -0
  160. package/dist/distill/prompts/extract.js +67 -0
  161. package/dist/distill/prompts/extract.js.map +1 -0
  162. package/dist/distill/stages/01-cleanup.d.ts +9 -0
  163. package/dist/distill/stages/01-cleanup.js +67 -0
  164. package/dist/distill/stages/01-cleanup.js.map +1 -0
  165. package/dist/distill/stages/02-normalize.d.ts +9 -0
  166. package/dist/distill/stages/02-normalize.js +76 -0
  167. package/dist/distill/stages/02-normalize.js.map +1 -0
  168. package/dist/distill/stages/03-chunk.d.ts +22 -0
  169. package/dist/distill/stages/03-chunk.js +138 -0
  170. package/dist/distill/stages/03-chunk.js.map +1 -0
  171. package/dist/distill/stages/04-compact.d.ts +28 -0
  172. package/dist/distill/stages/04-compact.js +69 -0
  173. package/dist/distill/stages/04-compact.js.map +1 -0
  174. package/dist/distill/stages/05-extract.d.ts +35 -0
  175. package/dist/distill/stages/05-extract.js +101 -0
  176. package/dist/distill/stages/05-extract.js.map +1 -0
  177. package/dist/distill/stages/06-reduce.d.ts +16 -0
  178. package/dist/distill/stages/06-reduce.js +30 -0
  179. package/dist/distill/stages/06-reduce.js.map +1 -0
  180. package/dist/distill/stages/07-memory-normalize.d.ts +27 -0
  181. package/dist/distill/stages/07-memory-normalize.js +65 -0
  182. package/dist/distill/stages/07-memory-normalize.js.map +1 -0
  183. package/dist/distill/stages/08-embed-index.d.ts +31 -0
  184. package/dist/distill/stages/08-embed-index.js +82 -0
  185. package/dist/distill/stages/08-embed-index.js.map +1 -0
  186. package/dist/doctor/checks.d.ts +77 -0
  187. package/dist/doctor/checks.js +626 -0
  188. package/dist/doctor/checks.js.map +1 -0
  189. package/dist/doctor/hardening-checks.d.ts +9 -0
  190. package/dist/doctor/hardening-checks.js +182 -0
  191. package/dist/doctor/hardening-checks.js.map +1 -0
  192. package/dist/doctor/probes/embed-probe.d.ts +19 -0
  193. package/dist/doctor/probes/embed-probe.js +47 -0
  194. package/dist/doctor/probes/embed-probe.js.map +1 -0
  195. package/dist/doctor/probes/llm-chat-probe.d.ts +11 -0
  196. package/dist/doctor/probes/llm-chat-probe.js +41 -0
  197. package/dist/doctor/probes/llm-chat-probe.js.map +1 -0
  198. package/dist/doctor/probes/plugin-coexistence.d.ts +14 -0
  199. package/dist/doctor/probes/plugin-coexistence.js +60 -0
  200. package/dist/doctor/probes/plugin-coexistence.js.map +1 -0
  201. package/dist/doctor/runner.d.ts +17 -0
  202. package/dist/doctor/runner.js +53 -0
  203. package/dist/doctor/runner.js.map +1 -0
  204. package/dist/doctor/types.d.ts +12 -0
  205. package/dist/doctor/types.js +2 -0
  206. package/dist/doctor/types.js.map +1 -0
  207. package/dist/entity/backfill.d.ts +30 -0
  208. package/dist/entity/backfill.js +55 -0
  209. package/dist/entity/backfill.js.map +1 -0
  210. package/dist/entity/extract-entities.d.ts +27 -0
  211. package/dist/entity/extract-entities.js +86 -0
  212. package/dist/entity/extract-entities.js.map +1 -0
  213. package/dist/entity/normalize.d.ts +17 -0
  214. package/dist/entity/normalize.js +20 -0
  215. package/dist/entity/normalize.js.map +1 -0
  216. package/dist/eval/harness.d.ts +96 -0
  217. package/dist/eval/harness.js +119 -0
  218. package/dist/eval/harness.js.map +1 -0
  219. package/dist/eval/metrics.d.ts +23 -0
  220. package/dist/eval/metrics.js +44 -0
  221. package/dist/eval/metrics.js.map +1 -0
  222. package/dist/log/correlation.d.ts +24 -0
  223. package/dist/log/correlation.js +33 -0
  224. package/dist/log/correlation.js.map +1 -0
  225. package/dist/log/logger.d.ts +38 -0
  226. package/dist/log/logger.js +129 -0
  227. package/dist/log/logger.js.map +1 -0
  228. package/dist/log/scrub.d.ts +33 -0
  229. package/dist/log/scrub.js +91 -0
  230. package/dist/log/scrub.js.map +1 -0
  231. package/dist/mcp/server.d.ts +36 -0
  232. package/dist/mcp/server.js +553 -0
  233. package/dist/mcp/server.js.map +1 -0
  234. package/dist/memory-tool/adapter.d.ts +73 -0
  235. package/dist/memory-tool/adapter.js +269 -0
  236. package/dist/memory-tool/adapter.js.map +1 -0
  237. package/dist/pipeline/errors.d.ts +21 -0
  238. package/dist/pipeline/errors.js +34 -0
  239. package/dist/pipeline/errors.js.map +1 -0
  240. package/dist/pipeline/failure-classifier.d.ts +13 -0
  241. package/dist/pipeline/failure-classifier.js +72 -0
  242. package/dist/pipeline/failure-classifier.js.map +1 -0
  243. package/dist/pipeline/handler-ctx-ext.d.ts +23 -0
  244. package/dist/pipeline/handler-ctx-ext.js +19 -0
  245. package/dist/pipeline/handler-ctx-ext.js.map +1 -0
  246. package/dist/pipeline/handler.d.ts +20 -0
  247. package/dist/pipeline/handler.js +2 -0
  248. package/dist/pipeline/handler.js.map +1 -0
  249. package/dist/pipeline/handlers/cleanup.d.ts +14 -0
  250. package/dist/pipeline/handlers/cleanup.js +47 -0
  251. package/dist/pipeline/handlers/cleanup.js.map +1 -0
  252. package/dist/pipeline/handlers/consolidate.d.ts +8 -0
  253. package/dist/pipeline/handlers/consolidate.js +23 -0
  254. package/dist/pipeline/handlers/consolidate.js.map +1 -0
  255. package/dist/pipeline/handlers/distill-events.d.ts +15 -0
  256. package/dist/pipeline/handlers/distill-events.js +134 -0
  257. package/dist/pipeline/handlers/distill-events.js.map +1 -0
  258. package/dist/pipeline/handlers/distill.d.ts +17 -0
  259. package/dist/pipeline/handlers/distill.js +110 -0
  260. package/dist/pipeline/handlers/distill.js.map +1 -0
  261. package/dist/pipeline/handlers/reembed.d.ts +10 -0
  262. package/dist/pipeline/handlers/reembed.js +34 -0
  263. package/dist/pipeline/handlers/reembed.js.map +1 -0
  264. package/dist/pipeline/job-repo.d.ts +86 -0
  265. package/dist/pipeline/job-repo.js +168 -0
  266. package/dist/pipeline/job-repo.js.map +1 -0
  267. package/dist/pipeline/mock-providers.d.ts +49 -0
  268. package/dist/pipeline/mock-providers.js +175 -0
  269. package/dist/pipeline/mock-providers.js.map +1 -0
  270. package/dist/pipeline/registry.d.ts +15 -0
  271. package/dist/pipeline/registry.js +20 -0
  272. package/dist/pipeline/registry.js.map +1 -0
  273. package/dist/pipeline/worker.d.ts +41 -0
  274. package/dist/pipeline/worker.js +167 -0
  275. package/dist/pipeline/worker.js.map +1 -0
  276. package/dist/providers/embed/azure-openai.d.ts +25 -0
  277. package/dist/providers/embed/azure-openai.js +138 -0
  278. package/dist/providers/embed/azure-openai.js.map +1 -0
  279. package/dist/providers/embed/ollama.d.ts +17 -0
  280. package/dist/providers/embed/ollama.js +106 -0
  281. package/dist/providers/embed/ollama.js.map +1 -0
  282. package/dist/providers/index.d.ts +19 -0
  283. package/dist/providers/index.js +72 -0
  284. package/dist/providers/index.js.map +1 -0
  285. package/dist/providers/llm/azure-openai.d.ts +20 -0
  286. package/dist/providers/llm/azure-openai.js +135 -0
  287. package/dist/providers/llm/azure-openai.js.map +1 -0
  288. package/dist/providers/llm/ollama.d.ts +13 -0
  289. package/dist/providers/llm/ollama.js +113 -0
  290. package/dist/providers/llm/ollama.js.map +1 -0
  291. package/dist/providers/llm/pricing.d.ts +21 -0
  292. package/dist/providers/llm/pricing.js +22 -0
  293. package/dist/providers/llm/pricing.js.map +1 -0
  294. package/dist/recall/pack.d.ts +32 -0
  295. package/dist/recall/pack.js +90 -0
  296. package/dist/recall/pack.js.map +1 -0
  297. package/dist/recall/policy.d.ts +39 -0
  298. package/dist/recall/policy.js +96 -0
  299. package/dist/recall/policy.js.map +1 -0
  300. package/dist/redact/detectors.d.ts +20 -0
  301. package/dist/redact/detectors.js +85 -0
  302. package/dist/redact/detectors.js.map +1 -0
  303. package/dist/redact/entropy.d.ts +24 -0
  304. package/dist/redact/entropy.js +77 -0
  305. package/dist/redact/entropy.js.map +1 -0
  306. package/dist/redact/index.d.ts +47 -0
  307. package/dist/redact/index.js +165 -0
  308. package/dist/redact/index.js.map +1 -0
  309. package/dist/search/fuse.d.ts +108 -0
  310. package/dist/search/fuse.js +135 -0
  311. package/dist/search/fuse.js.map +1 -0
  312. package/dist/search/query.d.ts +28 -0
  313. package/dist/search/query.js +70 -0
  314. package/dist/search/query.js.map +1 -0
  315. package/dist/search/search.d.ts +164 -0
  316. package/dist/search/search.js +310 -0
  317. package/dist/search/search.js.map +1 -0
  318. package/dist/server/app.d.ts +17 -0
  319. package/dist/server/app.js +133 -0
  320. package/dist/server/app.js.map +1 -0
  321. package/dist/server/health-state.d.ts +29 -0
  322. package/dist/server/health-state.js +28 -0
  323. package/dist/server/health-state.js.map +1 -0
  324. package/dist/server/lib/network.d.ts +12 -0
  325. package/dist/server/lib/network.js +16 -0
  326. package/dist/server/lib/network.js.map +1 -0
  327. package/dist/server/lib/score-contract.d.ts +36 -0
  328. package/dist/server/lib/score-contract.js +54 -0
  329. package/dist/server/lib/score-contract.js.map +1 -0
  330. package/dist/server/lib/stable-stringify.d.ts +10 -0
  331. package/dist/server/lib/stable-stringify.js +27 -0
  332. package/dist/server/lib/stable-stringify.js.map +1 -0
  333. package/dist/server/lib/wire-meta.d.ts +7 -0
  334. package/dist/server/lib/wire-meta.js +29 -0
  335. package/dist/server/lib/wire-meta.js.map +1 -0
  336. package/dist/server/queries/dashboard.d.ts +142 -0
  337. package/dist/server/queries/dashboard.js +166 -0
  338. package/dist/server/queries/dashboard.js.map +1 -0
  339. package/dist/server/routes/consolidation.d.ts +14 -0
  340. package/dist/server/routes/consolidation.js +67 -0
  341. package/dist/server/routes/consolidation.js.map +1 -0
  342. package/dist/server/routes/dashboard-api-html.d.ts +15 -0
  343. package/dist/server/routes/dashboard-api-html.js +144 -0
  344. package/dist/server/routes/dashboard-api-html.js.map +1 -0
  345. package/dist/server/routes/dashboard-consolidation-html.d.ts +26 -0
  346. package/dist/server/routes/dashboard-consolidation-html.js +202 -0
  347. package/dist/server/routes/dashboard-consolidation-html.js.map +1 -0
  348. package/dist/server/routes/dashboard-html.d.ts +15 -0
  349. package/dist/server/routes/dashboard-html.js +365 -0
  350. package/dist/server/routes/dashboard-html.js.map +1 -0
  351. package/dist/server/routes/dashboard-jobs-html.d.ts +18 -0
  352. package/dist/server/routes/dashboard-jobs-html.js +186 -0
  353. package/dist/server/routes/dashboard-jobs-html.js.map +1 -0
  354. package/dist/server/routes/dashboard-search-html.d.ts +18 -0
  355. package/dist/server/routes/dashboard-search-html.js +189 -0
  356. package/dist/server/routes/dashboard-search-html.js.map +1 -0
  357. package/dist/server/routes/dashboard.d.ts +19 -0
  358. package/dist/server/routes/dashboard.js +68 -0
  359. package/dist/server/routes/dashboard.js.map +1 -0
  360. package/dist/server/routes/digest.d.ts +9 -0
  361. package/dist/server/routes/digest.js +37 -0
  362. package/dist/server/routes/digest.js.map +1 -0
  363. package/dist/server/routes/entities.d.ts +12 -0
  364. package/dist/server/routes/entities.js +46 -0
  365. package/dist/server/routes/entities.js.map +1 -0
  366. package/dist/server/routes/health.d.ts +14 -0
  367. package/dist/server/routes/health.js +100 -0
  368. package/dist/server/routes/health.js.map +1 -0
  369. package/dist/server/routes/ingest.d.ts +209 -0
  370. package/dist/server/routes/ingest.js +454 -0
  371. package/dist/server/routes/ingest.js.map +1 -0
  372. package/dist/server/routes/lifecycle.d.ts +21 -0
  373. package/dist/server/routes/lifecycle.js +132 -0
  374. package/dist/server/routes/lifecycle.js.map +1 -0
  375. package/dist/server/routes/mcp.d.ts +15 -0
  376. package/dist/server/routes/mcp.js +36 -0
  377. package/dist/server/routes/mcp.js.map +1 -0
  378. package/dist/server/routes/memory-tool.d.ts +14 -0
  379. package/dist/server/routes/memory-tool.js +28 -0
  380. package/dist/server/routes/memory-tool.js.map +1 -0
  381. package/dist/server/routes/memory.d.ts +7 -0
  382. package/dist/server/routes/memory.js +19 -0
  383. package/dist/server/routes/memory.js.map +1 -0
  384. package/dist/server/routes/recall.d.ts +15 -0
  385. package/dist/server/routes/recall.js +74 -0
  386. package/dist/server/routes/recall.js.map +1 -0
  387. package/dist/server/routes/search.d.ts +12 -0
  388. package/dist/server/routes/search.js +203 -0
  389. package/dist/server/routes/search.js.map +1 -0
  390. package/dist/server/routes/version.d.ts +2 -0
  391. package/dist/server/routes/version.js +11 -0
  392. package/dist/server/routes/version.js.map +1 -0
  393. package/dist/server/routes/why.d.ts +9 -0
  394. package/dist/server/routes/why.js +38 -0
  395. package/dist/server/routes/why.js.map +1 -0
  396. package/dist/service/index.d.ts +10 -0
  397. package/dist/service/index.js +25 -0
  398. package/dist/service/index.js.map +1 -0
  399. package/dist/service/install-flow.d.ts +18 -0
  400. package/dist/service/install-flow.js +47 -0
  401. package/dist/service/install-flow.js.map +1 -0
  402. package/dist/service/instance-lock.d.ts +26 -0
  403. package/dist/service/instance-lock.js +150 -0
  404. package/dist/service/instance-lock.js.map +1 -0
  405. package/dist/service/launchd.d.ts +11 -0
  406. package/dist/service/launchd.js +196 -0
  407. package/dist/service/launchd.js.map +1 -0
  408. package/dist/service/schtasks.d.ts +31 -0
  409. package/dist/service/schtasks.js +274 -0
  410. package/dist/service/schtasks.js.map +1 -0
  411. package/dist/service/shim.d.ts +21 -0
  412. package/dist/service/shim.js +80 -0
  413. package/dist/service/shim.js.map +1 -0
  414. package/dist/service/systemd.d.ts +11 -0
  415. package/dist/service/systemd.js +150 -0
  416. package/dist/service/systemd.js.map +1 -0
  417. package/dist/service/task-xml.d.ts +36 -0
  418. package/dist/service/task-xml.js +91 -0
  419. package/dist/service/task-xml.js.map +1 -0
  420. package/dist/service/types.d.ts +47 -0
  421. package/dist/service/types.js +2 -0
  422. package/dist/service/types.js.map +1 -0
  423. package/dist/storage/archival.d.ts +29 -0
  424. package/dist/storage/archival.js +47 -0
  425. package/dist/storage/archival.js.map +1 -0
  426. package/dist/storage/bearer-keystore.d.ts +34 -0
  427. package/dist/storage/bearer-keystore.js +75 -0
  428. package/dist/storage/bearer-keystore.js.map +1 -0
  429. package/dist/storage/db.d.ts +37 -0
  430. package/dist/storage/db.js +92 -0
  431. package/dist/storage/db.js.map +1 -0
  432. package/dist/storage/entities.d.ts +71 -0
  433. package/dist/storage/entities.js +141 -0
  434. package/dist/storage/entities.js.map +1 -0
  435. package/dist/storage/ingest-idempotency.d.ts +26 -0
  436. package/dist/storage/ingest-idempotency.js +29 -0
  437. package/dist/storage/ingest-idempotency.js.map +1 -0
  438. package/dist/storage/keystore.d.ts +64 -0
  439. package/dist/storage/keystore.js +194 -0
  440. package/dist/storage/keystore.js.map +1 -0
  441. package/dist/storage/memories.d.ts +51 -0
  442. package/dist/storage/memories.js +67 -0
  443. package/dist/storage/memories.js.map +1 -0
  444. package/dist/storage/memory-events.d.ts +145 -0
  445. package/dist/storage/memory-events.js +287 -0
  446. package/dist/storage/memory-events.js.map +1 -0
  447. package/dist/storage/migrate-encrypt.d.ts +16 -0
  448. package/dist/storage/migrate-encrypt.js +121 -0
  449. package/dist/storage/migrate-encrypt.js.map +1 -0
  450. package/dist/storage/migrate.d.ts +27 -0
  451. package/dist/storage/migrate.js +105 -0
  452. package/dist/storage/migrate.js.map +1 -0
  453. package/dist/storage/redaction-log.d.ts +18 -0
  454. package/dist/storage/redaction-log.js +27 -0
  455. package/dist/storage/redaction-log.js.map +1 -0
  456. package/dist/storage/usefulness.d.ts +115 -0
  457. package/dist/storage/usefulness.js +203 -0
  458. package/dist/storage/usefulness.js.map +1 -0
  459. package/dist/sync/conflict-resolve.d.ts +26 -0
  460. package/dist/sync/conflict-resolve.js +139 -0
  461. package/dist/sync/conflict-resolve.js.map +1 -0
  462. package/dist/sync/puller.d.ts +115 -0
  463. package/dist/sync/puller.js +173 -0
  464. package/dist/sync/puller.js.map +1 -0
  465. package/dist/sync/shipper.d.ts +112 -0
  466. package/dist/sync/shipper.js +189 -0
  467. package/dist/sync/shipper.js.map +1 -0
  468. package/dist/tag-hygiene/backfill.d.ts +50 -0
  469. package/dist/tag-hygiene/backfill.js +117 -0
  470. package/dist/tag-hygiene/backfill.js.map +1 -0
  471. package/dist/tag-hygiene/derive-repo.d.ts +9 -0
  472. package/dist/tag-hygiene/derive-repo.js +19 -0
  473. package/dist/tag-hygiene/derive-repo.js.map +1 -0
  474. package/dist/tag-hygiene/tier2-infer.d.ts +28 -0
  475. package/dist/tag-hygiene/tier2-infer.js +72 -0
  476. package/dist/tag-hygiene/tier2-infer.js.map +1 -0
  477. package/dist/vector/sqlite-vec.d.ts +16 -0
  478. package/dist/vector/sqlite-vec.js +49 -0
  479. package/dist/vector/sqlite-vec.js.map +1 -0
  480. package/migrations/001-init.sql +117 -0
  481. package/migrations/002-wire-v1.sql +16 -0
  482. package/migrations/003-expand-memory-types.sql +81 -0
  483. package/migrations/004-provenance.sql +4 -0
  484. package/migrations/005-security.sql +12 -0
  485. package/migrations/006-atom-v3.sql +28 -0
  486. package/migrations/007-memory-events.sql +30 -0
  487. package/migrations/008-consolidation.sql +31 -0
  488. package/migrations/009-tag-hygiene.sql +13 -0
  489. package/migrations/010-sync-pull.sql +53 -0
  490. package/migrations/011-embed-dim-migration.sql +28 -0
  491. package/migrations/012-entities.sql +36 -0
  492. package/migrations/013-archival.sql +50 -0
  493. package/package.json +50 -0
@@ -0,0 +1,77 @@
1
+ /**
2
+ * verify.ts — prove a snapshot restores (W2.1).
3
+ *
4
+ * A backup that can't be opened is discovered at the worst possible moment.
5
+ * Verification: reopen the snapshot read-only with the same key, run
6
+ * PRAGMA integrity_check, and compare memories/transcripts row counts against
7
+ * the live database the snapshot was taken from.
8
+ */
9
+ import Database from 'better-sqlite3-multiple-ciphers';
10
+ function countRows(db, table) {
11
+ try {
12
+ return db.prepare(`SELECT COUNT(*) AS n FROM ${table}`).get().n;
13
+ }
14
+ catch {
15
+ return -1; // table absent
16
+ }
17
+ }
18
+ /**
19
+ * Verify `snapshotPath` against the live `db` it was snapshotted from.
20
+ * Row-count tolerance: the live DB may have gained rows since the snapshot
21
+ * started (online backup), so snapshot counts must be <= live counts and
22
+ * within `tolerance` of them — never greater, never wildly behind.
23
+ */
24
+ export function verifySnapshot(liveDb, snapshotPath, key, tolerance = 10) {
25
+ const liveCounts = {
26
+ memories: countRows(liveDb, 'memories'),
27
+ transcripts: countRows(liveDb, 'transcripts'),
28
+ };
29
+ const result = {
30
+ ok: false,
31
+ integrity: '',
32
+ counts: {
33
+ memories: { live: liveCounts.memories, snapshot: -1 },
34
+ transcripts: { live: liveCounts.transcripts, snapshot: -1 },
35
+ },
36
+ };
37
+ let snap = null;
38
+ try {
39
+ snap = new Database(snapshotPath, { readonly: true });
40
+ if (key)
41
+ snap.pragma(`key='${key.replace(/'/g, "''")}'`);
42
+ const integrityRows = snap.pragma('integrity_check');
43
+ result.integrity = integrityRows.map(r => r.integrity_check).join('; ');
44
+ if (result.integrity !== 'ok') {
45
+ result.error = `integrity_check: ${result.integrity}`;
46
+ return result;
47
+ }
48
+ result.counts.memories.snapshot = countRows(snap, 'memories');
49
+ result.counts.transcripts.snapshot = countRows(snap, 'transcripts');
50
+ for (const table of ['memories', 'transcripts']) {
51
+ const { live, snapshot } = result.counts[table];
52
+ if (snapshot < 0) {
53
+ result.error = `snapshot missing ${table} table`;
54
+ return result;
55
+ }
56
+ // Snapshot may lag the live DB slightly (online backup) but must never
57
+ // exceed it or fall further behind than `tolerance` rows.
58
+ if (snapshot > live || live - snapshot > tolerance) {
59
+ result.error = `${table} count mismatch: live=${live} snapshot=${snapshot} (tolerance ${tolerance})`;
60
+ return result;
61
+ }
62
+ }
63
+ result.ok = true;
64
+ return result;
65
+ }
66
+ catch (err) {
67
+ result.error = err instanceof Error ? err.message : String(err);
68
+ return result;
69
+ }
70
+ finally {
71
+ try {
72
+ snap?.close();
73
+ }
74
+ catch { /* ignore */ }
75
+ }
76
+ }
77
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/backup/verify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Budget tracker — daily LLM spend enforcement.
3
+ *
4
+ * Backed by the budget_spend table (day TEXT PRIMARY KEY, usd_total REAL, calls INTEGER).
5
+ * All DB ops are synchronous (better-sqlite3).
6
+ */
7
+ import type { DB } from '../storage/db.js';
8
+ export declare class BudgetExceeded extends Error {
9
+ readonly dayTotal: number;
10
+ readonly cap: number;
11
+ readonly estimateUsd: number;
12
+ constructor(dayTotal: number, cap: number, estimateUsd: number);
13
+ }
14
+ export interface DaySpend {
15
+ day: string;
16
+ usd_total: number;
17
+ calls: number;
18
+ }
19
+ export declare class BudgetTracker {
20
+ private readonly db;
21
+ constructor(db: DB);
22
+ /** Return today's spend row (or a zeroed row if none exists yet). */
23
+ today(): DaySpend;
24
+ /**
25
+ * Add usd to today's running total and increment call count.
26
+ * Uses INSERT OR REPLACE so the first call creates the row.
27
+ */
28
+ record(usd: number): void;
29
+ /**
30
+ * Return true if today's spend + estimateUsd would remain within capUsd.
31
+ * Does NOT record spend — call record() after a successful LLM call.
32
+ */
33
+ canSpend(estimateUsd: number, capUsd: number): boolean;
34
+ /**
35
+ * Assert that we can spend estimateUsd against capUsd.
36
+ * Throws BudgetExceeded if over cap.
37
+ */
38
+ assertCanSpend(estimateUsd: number, capUsd: number): void;
39
+ /**
40
+ * Reset today's row to zero (user-initiated override).
41
+ * Logs to stdout for audit trail.
42
+ */
43
+ resetToday(): void;
44
+ /**
45
+ * Estimate LLM cost for a call given prompt character count.
46
+ * Uses: input_tokens ≈ chars/4, fixed 500 output tokens.
47
+ * Returns USD (0 if this is an Ollama call — caller should pass 0).
48
+ */
49
+ static estimateUsd(promptChars: number, costPerInputToken: number, costPerOutputToken: number): number;
50
+ /**
51
+ * Month totals: sum up all days in the current calendar month (YYYY-MM prefix).
52
+ */
53
+ monthTotal(): {
54
+ usd_total: number;
55
+ calls: number;
56
+ month: string;
57
+ };
58
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Budget tracker — daily LLM spend enforcement.
3
+ *
4
+ * Backed by the budget_spend table (day TEXT PRIMARY KEY, usd_total REAL, calls INTEGER).
5
+ * All DB ops are synchronous (better-sqlite3).
6
+ */
7
+ export class BudgetExceeded extends Error {
8
+ dayTotal;
9
+ cap;
10
+ estimateUsd;
11
+ constructor(dayTotal, cap, estimateUsd) {
12
+ super(`Budget cap exceeded: today=$${dayTotal.toFixed(4)} + estimate=$${estimateUsd.toFixed(4)} > cap=$${cap.toFixed(2)}`);
13
+ this.dayTotal = dayTotal;
14
+ this.cap = cap;
15
+ this.estimateUsd = estimateUsd;
16
+ this.name = 'BudgetExceeded';
17
+ }
18
+ }
19
+ export class BudgetTracker {
20
+ db;
21
+ constructor(db) {
22
+ this.db = db;
23
+ }
24
+ /** Return today's spend row (or a zeroed row if none exists yet). */
25
+ today() {
26
+ const day = todayKey();
27
+ const row = this.db
28
+ .prepare('SELECT day, usd_total, calls FROM budget_spend WHERE day = ?')
29
+ .get(day);
30
+ return row ?? { day, usd_total: 0, calls: 0 };
31
+ }
32
+ /**
33
+ * Add usd to today's running total and increment call count.
34
+ * Uses INSERT OR REPLACE so the first call creates the row.
35
+ */
36
+ record(usd) {
37
+ const day = todayKey();
38
+ this.db
39
+ .prepare(`
40
+ INSERT INTO budget_spend (day, usd_total, calls)
41
+ VALUES (?, ?, 1)
42
+ ON CONFLICT(day) DO UPDATE SET
43
+ usd_total = usd_total + excluded.usd_total,
44
+ calls = calls + 1
45
+ `)
46
+ .run(day, usd);
47
+ }
48
+ /**
49
+ * Return true if today's spend + estimateUsd would remain within capUsd.
50
+ * Does NOT record spend — call record() after a successful LLM call.
51
+ */
52
+ canSpend(estimateUsd, capUsd) {
53
+ const { usd_total } = this.today();
54
+ return usd_total + estimateUsd <= capUsd;
55
+ }
56
+ /**
57
+ * Assert that we can spend estimateUsd against capUsd.
58
+ * Throws BudgetExceeded if over cap.
59
+ */
60
+ assertCanSpend(estimateUsd, capUsd) {
61
+ const { usd_total } = this.today();
62
+ if (usd_total + estimateUsd > capUsd) {
63
+ throw new BudgetExceeded(usd_total, capUsd, estimateUsd);
64
+ }
65
+ }
66
+ /**
67
+ * Reset today's row to zero (user-initiated override).
68
+ * Logs to stdout for audit trail.
69
+ */
70
+ resetToday() {
71
+ const day = todayKey();
72
+ this.db
73
+ .prepare('INSERT INTO budget_spend (day, usd_total, calls) VALUES (?, 0, 0) ON CONFLICT(day) DO UPDATE SET usd_total=0, calls=0')
74
+ .run(day);
75
+ console.log(`[budget] reset: day=${day} usd_total reset to 0`);
76
+ }
77
+ /**
78
+ * Estimate LLM cost for a call given prompt character count.
79
+ * Uses: input_tokens ≈ chars/4, fixed 500 output tokens.
80
+ * Returns USD (0 if this is an Ollama call — caller should pass 0).
81
+ */
82
+ static estimateUsd(promptChars, costPerInputToken, costPerOutputToken) {
83
+ const inputTokens = Math.ceil(promptChars / 4);
84
+ const outputTokens = 500; // fixed max output estimate
85
+ return inputTokens * costPerInputToken + outputTokens * costPerOutputToken;
86
+ }
87
+ /**
88
+ * Month totals: sum up all days in the current calendar month (YYYY-MM prefix).
89
+ */
90
+ monthTotal() {
91
+ const month = todayKey().slice(0, 7); // YYYY-MM
92
+ const row = this.db
93
+ .prepare(`SELECT COALESCE(SUM(usd_total), 0) AS usd_total, COALESCE(SUM(calls), 0) AS calls
94
+ FROM budget_spend WHERE day LIKE ?`)
95
+ .get(`${month}-%`);
96
+ return { ...row, month };
97
+ }
98
+ }
99
+ function todayKey() {
100
+ return new Date().toISOString().slice(0, 10); // YYYY-MM-DD UTC
101
+ }
102
+ //# sourceMappingURL=tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracker.js","sourceRoot":"","sources":["../../src/budget/tracker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Codex CLI capture connector (Wave 4c, ADR-008).
3
+ *
4
+ * OpenAI Codex CLI persists every session as append-only JSONL under
5
+ * ~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl. This module turns those
6
+ * files into astramem-capture@1 transcript envelopes for POST
7
+ * /ingest/transcript — the daemon's stage-0 redaction and full distill
8
+ * pipeline take it from there, identical to Claude Code captures.
9
+ *
10
+ * The parser is deliberately tolerant: Codex has shipped several line
11
+ * shapes across versions (session_meta wrappers, response_item wrappers,
12
+ * bare message items). Unknown lines are skipped, never fatal — a session
13
+ * that yields zero usable turns is simply not captured.
14
+ *
15
+ * Decision (2026-07-02): Codex first, Cursor postponed — Codex's on-disk
16
+ * format is open and stable; Cursor stores chats in a proprietary SQLite
17
+ * blob that breaks on updates. Cursor users get the MCP-recall path.
18
+ */
19
+ export interface CodexTurn {
20
+ role: 'user' | 'assistant';
21
+ text: string;
22
+ }
23
+ export interface ParsedCodexSession {
24
+ sessionId: string;
25
+ cwd: string | null;
26
+ turns: CodexTurn[];
27
+ }
28
+ export interface CaptureEnvelope {
29
+ event: 'session_end';
30
+ session_id: string;
31
+ project_id: string;
32
+ agent_type: string;
33
+ cwd?: string;
34
+ captured_at: string;
35
+ kind: 'transcript';
36
+ tool: 'codex-cli';
37
+ turns: Array<{
38
+ role: 'user' | 'assistant';
39
+ text: string;
40
+ }>;
41
+ client_scrub_applied: boolean;
42
+ client_scrub_hits: number;
43
+ client_version: string;
44
+ client_scrub_version: string;
45
+ wire_version: 'v1.0';
46
+ }
47
+ export declare function defaultCodexSessionsDir(): string;
48
+ /** Recursively list *.jsonl session files under the Codex sessions dir. */
49
+ export declare function scanCodexSessionFiles(dir: string): string[];
50
+ export declare function parseCodexSession(jsonl: string, filePath: string): ParsedCodexSession;
51
+ export declare function buildCodexEnvelope(parsed: ParsedCodexSession, clientVersion: string, capturedAt?: string): CaptureEnvelope;
52
+ /** Stable idempotency key: same session content → same key → server-side replay. */
53
+ export declare function codexIdempotencyKey(parsed: ParsedCodexSession): string;
54
+ export type CaptureState = Record<string, {
55
+ size: number;
56
+ }>;
57
+ export interface CandidateSession {
58
+ filePath: string;
59
+ parsed: ParsedCodexSession;
60
+ size: number;
61
+ }
62
+ /** Files that are new or have grown since `state`, parsed to ≥ 2 usable turns. */
63
+ export declare function findNewSessions(sessionsDir: string, state: CaptureState): CandidateSession[];
Binary file
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/capture/codex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function backupCommand(args: string[]): Promise<void>;
@@ -0,0 +1,112 @@
1
+ /**
2
+ * backup.ts — `astramem-local backup` CLI command.
3
+ *
4
+ * Usage:
5
+ * astramem-local backup [--out PATH] [--keep N] [--json]
6
+ *
7
+ * Exit codes:
8
+ * 0 = success
9
+ * 1 = failure (write error, no space, DB locked, invalid args)
10
+ */
11
+ import { join } from 'node:path';
12
+ import { createSnapshot } from '../backup/snapshot.js';
13
+ import { verifySnapshot } from '../backup/verify.js';
14
+ import { pruneOldBackups } from '../backup/retention.js';
15
+ import { resolveRuntimeConfig } from '../config/resolve-runtime.js';
16
+ import { defaultConfigDir } from '../config/datadir.js';
17
+ import { openDb } from '../storage/db.js';
18
+ import { migrate } from '../storage/migrate.js';
19
+ import { getOrCreateKey } from '../storage/keystore.js';
20
+ function parseArg(args, flag) {
21
+ const i = args.indexOf(flag);
22
+ return i >= 0 ? args[i + 1] : undefined;
23
+ }
24
+ function hasFlag(args, flag) {
25
+ return args.includes(flag);
26
+ }
27
+ /**
28
+ * Generate a timestamped filename: `memory-YYYYMMDDTHHmmss.sqlite`
29
+ */
30
+ function defaultFilename() {
31
+ const now = new Date();
32
+ const pad = (n, w = 2) => String(n).padStart(w, '0');
33
+ const date = `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}` +
34
+ `T${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
35
+ return `memory-${date}.sqlite`;
36
+ }
37
+ export async function backupCommand(args) {
38
+ const outArg = parseArg(args, '--out');
39
+ const keepArg = parseArg(args, '--keep');
40
+ const jsonMode = hasFlag(args, '--json');
41
+ const keep = keepArg !== undefined ? Number(keepArg) : 7;
42
+ if (!Number.isInteger(keep) || keep < 1) {
43
+ console.error('backup: --keep must be a positive integer');
44
+ process.exit(1);
45
+ }
46
+ // Shared resolver — backup must snapshot the SAME dataDir the daemon
47
+ // serves from (config.yaml + ASTRA_MEMORY_DATADIR included), not the
48
+ // compile-time default.
49
+ const { cfg, dataDir } = resolveRuntimeConfig();
50
+ const backupDir = join(dataDir, 'backups');
51
+ const outPath = outArg ?? join(backupDir, defaultFilename());
52
+ // Open the live DB so we can use its backup API.
53
+ // Migrations run automatically when the DB is first opened.
54
+ const dbPath = join(dataDir, 'memory.sqlite');
55
+ let db;
56
+ try {
57
+ // SEC-8: an encrypted DB requires the key to open at all (even for a
58
+ // backup/VACUUM INTO copy) — fetch it the same way serve.ts does.
59
+ const key = cfg.security.encryption.enabled ? getOrCreateKey(defaultConfigDir()).key : undefined;
60
+ db = openDb(dbPath, { key });
61
+ migrate(db, cfg.embedding.dim);
62
+ }
63
+ catch (err) {
64
+ console.error(`backup: failed to open database at ${dbPath}: ${err}`);
65
+ process.exit(1);
66
+ }
67
+ let snapshotResult;
68
+ try {
69
+ snapshotResult = await createSnapshot(db, outPath);
70
+ }
71
+ catch (err) {
72
+ console.error(`backup: snapshot failed: ${err}`);
73
+ db.close();
74
+ process.exit(1);
75
+ }
76
+ // W2.1: prove the snapshot restores — integrity_check + row-count compare.
77
+ // Default ON; --no-verify skips (e.g. huge DBs on a tight timer window).
78
+ let verified;
79
+ if (!hasFlag(args, '--no-verify')) {
80
+ const key = cfg.security.encryption.enabled ? getOrCreateKey(defaultConfigDir()).key : undefined;
81
+ const v = verifySnapshot(db, snapshotResult.path, key);
82
+ verified = v.ok;
83
+ if (!v.ok) {
84
+ console.error(`backup: snapshot VERIFICATION FAILED: ${v.error}`);
85
+ console.error(` snapshot left at ${snapshotResult.path} for inspection — do NOT rely on it`);
86
+ db.close();
87
+ process.exit(1);
88
+ }
89
+ }
90
+ db.close();
91
+ // Apply retention policy
92
+ const retention = pruneOldBackups(backupDir, keep);
93
+ if (jsonMode) {
94
+ console.log(JSON.stringify({
95
+ path: snapshotResult.path,
96
+ size_bytes: snapshotResult.size_bytes,
97
+ duration_ms: snapshotResult.duration_ms,
98
+ verified: verified ?? null,
99
+ kept: retention.kept.length,
100
+ deleted: retention.deleted.length,
101
+ }));
102
+ }
103
+ else {
104
+ const kb = (snapshotResult.size_bytes / 1024).toFixed(1);
105
+ console.log(`Backup created: ${snapshotResult.path}`);
106
+ console.log(` Size: ${kb} KB`);
107
+ console.log(` Duration: ${snapshotResult.duration_ms}ms`);
108
+ console.log(` Verified: ${verified === undefined ? 'skipped (--no-verify)' : 'yes (integrity + counts)'}`);
109
+ console.log(` Retention: kept ${retention.kept.length}, deleted ${retention.deleted.length}`);
110
+ }
111
+ }
112
+ //# sourceMappingURL=backup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup.js","sourceRoot":"","sources":["../../src/cli/backup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * `astramem-local budget [--reset]`
3
+ *
4
+ * Shows today's LLM spend and month total versus the configured cap.
5
+ * --reset clears today's row (override, logged).
6
+ */
7
+ export declare function budgetCommand(args: string[]): Promise<void>;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * `astramem-local budget [--reset]`
3
+ *
4
+ * Shows today's LLM spend and month total versus the configured cap.
5
+ * --reset clears today's row (override, logged).
6
+ */
7
+ import { BudgetTracker } from '../budget/tracker.js';
8
+ import { openRuntimeDb } from './open-runtime-db.js';
9
+ export async function budgetCommand(args) {
10
+ const doReset = args.includes('--reset');
11
+ // Key-aware + config.yaml-aware open (same resolution as serve/doctor).
12
+ const { db, cfg } = openRuntimeDb();
13
+ const tracker = new BudgetTracker(db);
14
+ if (doReset) {
15
+ tracker.resetToday();
16
+ console.log('Today\'s budget has been reset to $0.00.');
17
+ }
18
+ const today = tracker.today();
19
+ const month = tracker.monthTotal();
20
+ const cap = cfg.budget.daily_usd;
21
+ const pct = cap > 0 ? ((today.usd_total / cap) * 100).toFixed(1) : '—';
22
+ console.log('');
23
+ console.log(' AstraMemory Budget');
24
+ console.log(' ──────────────────────────────');
25
+ console.log(` Today (${today.day})`);
26
+ console.log(` Spend: $${today.usd_total.toFixed(4)}`);
27
+ console.log(` Cap: $${cap.toFixed(2)}`);
28
+ console.log(` Usage: ${pct}%`);
29
+ console.log(` Calls: ${today.calls}`);
30
+ console.log('');
31
+ console.log(` Month (${month.month})`);
32
+ console.log(` Spend: $${month.usd_total.toFixed(4)}`);
33
+ console.log(` Calls: ${month.calls}`);
34
+ console.log('');
35
+ if (today.usd_total >= cap) {
36
+ console.log(' [!] Daily cap reached — distillation is paused until tomorrow.');
37
+ console.log(' Run: astramem-local budget --reset to override.');
38
+ }
39
+ else if (cap > 0 && today.usd_total / cap >= 0.8) {
40
+ console.log(' [!] 80% of daily cap used — approaching limit.');
41
+ }
42
+ db.close();
43
+ }
44
+ //# sourceMappingURL=budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget.js","sourceRoot":"","sources":["../../src/cli/budget.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAc;IAChD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IACzC,wEAAwE;IACxE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,aAAa,EAAE,CAAC;IAEpC,MAAM,OAAO,GAAG,IAAI,aAAa,CAAC,EAAE,CAAC,CAAC;IAEtC,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,UAAU,EAAE,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAC9B,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IACnC,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC;IAEjC,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAEvE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,gBAAgB,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAC,eAAe,GAAG,GAAG,CAAC,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,IAAI,KAAK,CAAC,SAAS,IAAI,GAAG,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC;QAChF,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;IACxE,CAAC;SAAM,IAAI,GAAG,GAAG,CAAC,IAAI,KAAK,CAAC,SAAS,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;IAClE,CAAC;IAED,EAAE,CAAC,KAAK,EAAE,CAAC;AACb,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * `astramem-local capture codex` — one-shot Codex CLI session capture
3
+ * (Wave 4c, ADR-008). Scans ~/.codex/sessions for new/grown session files,
4
+ * converts each to an astramem-capture@1 transcript envelope, POSTs to the
5
+ * daemon's /ingest/transcript with a content-stable Idempotency-Key, and
6
+ * records per-file sizes in <dataDir>/codex-capture-state.json so unchanged
7
+ * files are skipped next run. Designed to be cheap enough for a shell hook
8
+ * or scheduled task; re-runs are always safe (server-side idempotency).
9
+ */
10
+ export declare function captureCommand(args: string[]): Promise<void>;
@@ -0,0 +1,113 @@
1
+ /**
2
+ * `astramem-local capture codex` — one-shot Codex CLI session capture
3
+ * (Wave 4c, ADR-008). Scans ~/.codex/sessions for new/grown session files,
4
+ * converts each to an astramem-capture@1 transcript envelope, POSTs to the
5
+ * daemon's /ingest/transcript with a content-stable Idempotency-Key, and
6
+ * records per-file sizes in <dataDir>/codex-capture-state.json so unchanged
7
+ * files are skipped next run. Designed to be cheap enough for a shell hook
8
+ * or scheduled task; re-runs are always safe (server-side idempotency).
9
+ */
10
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
11
+ import { join, dirname } from 'node:path';
12
+ import { defaultDataDir } from '../config/datadir.js';
13
+ import { PKG_VERSION } from '../server/lib/wire-meta.js';
14
+ import { defaultCodexSessionsDir, findNewSessions, buildCodexEnvelope, codexIdempotencyKey, } from '../capture/codex.js';
15
+ function parseArg(args, flag) {
16
+ const i = args.indexOf(flag);
17
+ return i >= 0 ? args[i + 1] : undefined;
18
+ }
19
+ function statePath() {
20
+ return join(process.env.ASTRA_MEMORY_DATADIR ?? defaultDataDir(), 'codex-capture-state.json');
21
+ }
22
+ function loadState(path) {
23
+ try {
24
+ return JSON.parse(readFileSync(path, 'utf8'));
25
+ }
26
+ catch {
27
+ return {};
28
+ }
29
+ }
30
+ export async function captureCommand(args) {
31
+ const source = args[0];
32
+ if (source !== 'codex') {
33
+ console.error(`capture: unknown source '${source ?? ''}' — supported: codex`);
34
+ process.exit(1);
35
+ }
36
+ // --watch [seconds]: poll for new sessions on an interval (Codex has no
37
+ // session-end hook to latch onto). One-shot semantics per tick; ctrl-c to stop.
38
+ if (args.includes('--watch')) {
39
+ const idx = args.indexOf('--watch');
40
+ const next = args[idx + 1];
41
+ const intervalSec = next && /^\d+$/.test(next) ? Math.max(10, Number(next)) : 60;
42
+ const tickArgs = args.filter((a, i) => a !== '--watch' && !(i === idx + 1 && /^\d+$/.test(a)));
43
+ console.log(`capture codex: watching every ${intervalSec}s (ctrl-c to stop)`);
44
+ for (;;) {
45
+ await runCaptureOnce(tickArgs);
46
+ await new Promise(r => setTimeout(r, intervalSec * 1000));
47
+ }
48
+ }
49
+ await runCaptureOnce(args);
50
+ }
51
+ async function runCaptureOnce(args) {
52
+ const sessionsDir = parseArg(args, '--sessions-dir') ?? defaultCodexSessionsDir();
53
+ const dryRun = args.includes('--dry-run');
54
+ const asJson = args.includes('--json');
55
+ const baseUrl = process.env.ASTRA_MEMORY_URL ?? 'http://127.0.0.1:7777';
56
+ const token = process.env.ASTRA_MEMORY_TOKEN ?? 'devtok';
57
+ const stateFile = statePath();
58
+ const state = loadState(stateFile);
59
+ const candidates = findNewSessions(sessionsDir, state);
60
+ const results = [];
61
+ for (const c of candidates) {
62
+ const envelope = buildCodexEnvelope(c.parsed, PKG_VERSION);
63
+ if (dryRun) {
64
+ results.push({ file: c.filePath, session_id: envelope.session_id, turns: envelope.turns.length, status: 'dry-run' });
65
+ continue;
66
+ }
67
+ try {
68
+ const res = await fetch(`${baseUrl}/ingest/transcript`, {
69
+ method: 'POST',
70
+ headers: {
71
+ 'content-type': 'application/json',
72
+ 'authorization': `Bearer ${token}`,
73
+ 'idempotency-key': codexIdempotencyKey(c.parsed),
74
+ },
75
+ body: JSON.stringify(envelope),
76
+ });
77
+ if (!res.ok) {
78
+ results.push({ file: c.filePath, session_id: envelope.session_id, turns: envelope.turns.length, status: `HTTP ${res.status}` });
79
+ continue; // don't advance state — retry next run
80
+ }
81
+ const body = await res.json();
82
+ state[c.filePath] = { size: c.size };
83
+ results.push({
84
+ file: c.filePath,
85
+ session_id: envelope.session_id,
86
+ turns: envelope.turns.length,
87
+ status: body.idempotent ? 'replayed' : 'ingested',
88
+ });
89
+ }
90
+ catch (err) {
91
+ results.push({ file: c.filePath, session_id: envelope.session_id, turns: envelope.turns.length, status: `error: ${String(err)}` });
92
+ }
93
+ }
94
+ if (!dryRun && results.some(r => r.status === 'ingested' || r.status === 'replayed')) {
95
+ if (!existsSync(dirname(stateFile)))
96
+ mkdirSync(dirname(stateFile), { recursive: true });
97
+ writeFileSync(stateFile, JSON.stringify(state, null, 2));
98
+ }
99
+ if (asJson) {
100
+ console.log(JSON.stringify({ sessions_dir: sessionsDir, captured: results }, null, 2));
101
+ }
102
+ else if (results.length === 0) {
103
+ console.log(`No new Codex sessions found under ${sessionsDir}.`);
104
+ }
105
+ else {
106
+ for (const r of results)
107
+ console.log(`${r.status} ${r.session_id} (${r.turns} turns) ${r.file}`);
108
+ }
109
+ if (results.some(r => r.status.startsWith('HTTP') || r.status.startsWith('error'))) {
110
+ process.exitCode = 1;
111
+ }
112
+ }
113
+ //# sourceMappingURL=capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/cli/capture.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EACL,uBAAuB,EACvB,eAAe,EACf,kBAAkB,EAClB,mBAAmB,GAEpB,MAAM,qBAAqB,CAAC;AAE7B,SAAS,QAAQ,CAAC,IAAc,EAAE,IAAY;IAC5C,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1C,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,cAAc,EAAE,EAAE,0BAA0B,CAAC,CAAC;AAChG,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAiB,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAc;IACjD,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACvB,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CAAC,4BAA4B,MAAM,IAAI,EAAE,sBAAsB,CAAC,CAAC;QAC9E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,wEAAwE;IACxE,gFAAgF;IAChF,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACpC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;QAC3B,MAAM,WAAW,GAAG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACjF,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/F,OAAO,CAAC,GAAG,CAAC,iCAAiC,WAAW,oBAAoB,CAAC,CAAC;QAC9E,SAAS,CAAC;YACR,MAAM,cAAc,CAAC,QAAQ,CAAC,CAAC;YAC/B,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAED,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,IAAc;IAC1C,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC,IAAI,uBAAuB,EAAE,CAAC;IAClF,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,uBAAuB,CAAC;IACxE,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,QAAQ,CAAC;IAEzD,MAAM,SAAS,GAAG,SAAS,EAAE,CAAC;IAC9B,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;IACnC,MAAM,UAAU,GAAG,eAAe,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAEvD,MAAM,OAAO,GAA+E,EAAE,CAAC;IAE/F,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,kBAAkB,CAAC,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAC3D,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;YACrH,SAAS;QACX,CAAC;QACD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,oBAAoB,EAAE;gBACtD,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,eAAe,EAAE,UAAU,KAAK,EAAE;oBAClC,iBAAiB,EAAE,mBAAmB,CAAC,CAAC,CAAC,MAAM,CAAC;iBACjD;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;aAC/B,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;gBAChI,SAAS,CAAC,uCAAuC;YACnD,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAA8B,CAAC;YAC1D,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YACrC,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,CAAC,CAAC,QAAQ;gBAChB,UAAU,EAAE,QAAQ,CAAC,UAAU;gBAC/B,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,MAAM;gBAC5B,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU;aAClD,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QACrI,CAAC;IACH,CAAC;IAED,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,CAAC,MAAM,KAAK,UAAU,CAAC,EAAE,CAAC;QACrF,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAAE,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxF,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACzF,CAAC;SAAM,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,qCAAqC,WAAW,GAAG,CAAC,CAAC;IACnE,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,CAAC,IAAI,OAAO;YAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,UAAU,MAAM,CAAC,CAAC,KAAK,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACtG,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QACnF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC;AACH,CAAC"}