@asermax/tachikoma 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (345) hide show
  1. package/README.md +64 -0
  2. package/dist/agent/adapter.d.ts +8 -0
  3. package/dist/agent/adapter.js +86 -0
  4. package/dist/agent/adapter.js.map +1 -0
  5. package/dist/agent/manager.d.ts +35 -0
  6. package/dist/agent/manager.js +76 -0
  7. package/dist/agent/manager.js.map +1 -0
  8. package/dist/agent/models.d.ts +46 -0
  9. package/dist/agent/models.js +96 -0
  10. package/dist/agent/models.js.map +1 -0
  11. package/dist/agent/side-run.d.ts +42 -0
  12. package/dist/agent/side-run.js +83 -0
  13. package/dist/agent/side-run.js.map +1 -0
  14. package/dist/app.d.ts +5 -0
  15. package/dist/app.js +79 -0
  16. package/dist/app.js.map +1 -0
  17. package/dist/channels/types.d.ts +37 -0
  18. package/dist/channels/types.js +5 -0
  19. package/dist/channels/types.js.map +1 -0
  20. package/dist/config/default-template.d.ts +1 -0
  21. package/dist/config/default-template.js +49 -0
  22. package/dist/config/default-template.js.map +1 -0
  23. package/dist/config/load.d.ts +8 -0
  24. package/dist/config/load.js +28 -0
  25. package/dist/config/load.js.map +1 -0
  26. package/dist/config/parse.d.ts +5 -0
  27. package/dist/config/parse.js +18 -0
  28. package/dist/config/parse.js.map +1 -0
  29. package/dist/config/schema.d.ts +29 -0
  30. package/dist/config/schema.js +35 -0
  31. package/dist/config/schema.js.map +1 -0
  32. package/dist/coordinator.d.ts +54 -0
  33. package/dist/coordinator.js +344 -0
  34. package/dist/coordinator.js.map +1 -0
  35. package/dist/db/core-schema.d.ts +250 -0
  36. package/dist/db/core-schema.js +19 -0
  37. package/dist/db/core-schema.js.map +1 -0
  38. package/dist/db/index.d.ts +8 -0
  39. package/dist/db/index.js +16 -0
  40. package/dist/db/index.js.map +1 -0
  41. package/dist/db/schema.d.ts +4 -0
  42. package/dist/db/schema.js +7 -0
  43. package/dist/db/schema.js.map +1 -0
  44. package/dist/db/state.d.ts +10 -0
  45. package/dist/db/state.js +36 -0
  46. package/dist/db/state.js.map +1 -0
  47. package/dist/domain/agent-events.d.ts +26 -0
  48. package/dist/domain/agent-events.js +2 -0
  49. package/dist/domain/agent-events.js.map +1 -0
  50. package/dist/domain/message.d.ts +25 -0
  51. package/dist/domain/message.js +17 -0
  52. package/dist/domain/message.js.map +1 -0
  53. package/dist/events.d.ts +9 -0
  54. package/dist/events.js +27 -0
  55. package/dist/events.js.map +1 -0
  56. package/dist/extensions/api.d.ts +118 -0
  57. package/dist/extensions/api.js +7 -0
  58. package/dist/extensions/api.js.map +1 -0
  59. package/dist/extensions/boundary/detector.d.ts +20 -0
  60. package/dist/extensions/boundary/detector.js +57 -0
  61. package/dist/extensions/boundary/detector.js.map +1 -0
  62. package/dist/extensions/boundary/idle.d.ts +10 -0
  63. package/dist/extensions/boundary/idle.js +28 -0
  64. package/dist/extensions/boundary/idle.js.map +1 -0
  65. package/dist/extensions/boundary/index.d.ts +12 -0
  66. package/dist/extensions/boundary/index.js +65 -0
  67. package/dist/extensions/boundary/index.js.map +1 -0
  68. package/dist/extensions/boundary/summary.d.ts +5 -0
  69. package/dist/extensions/boundary/summary.js +33 -0
  70. package/dist/extensions/boundary/summary.js.map +1 -0
  71. package/dist/extensions/commands/index.d.ts +7 -0
  72. package/dist/extensions/commands/index.js +21 -0
  73. package/dist/extensions/commands/index.js.map +1 -0
  74. package/dist/extensions/context/index.d.ts +7 -0
  75. package/dist/extensions/context/index.js +65 -0
  76. package/dist/extensions/context/index.js.map +1 -0
  77. package/dist/extensions/context/processor.d.ts +27 -0
  78. package/dist/extensions/context/processor.js +228 -0
  79. package/dist/extensions/context/processor.js.map +1 -0
  80. package/dist/extensions/detached-processes/index.d.ts +12 -0
  81. package/dist/extensions/detached-processes/index.js +51 -0
  82. package/dist/extensions/detached-processes/index.js.map +1 -0
  83. package/dist/extensions/detached-processes/limits.d.ts +27 -0
  84. package/dist/extensions/detached-processes/limits.js +55 -0
  85. package/dist/extensions/detached-processes/limits.js.map +1 -0
  86. package/dist/extensions/detached-processes/output.d.ts +2 -0
  87. package/dist/extensions/detached-processes/output.js +26 -0
  88. package/dist/extensions/detached-processes/output.js.map +1 -0
  89. package/dist/extensions/detached-processes/reconcile.d.ts +31 -0
  90. package/dist/extensions/detached-processes/reconcile.js +71 -0
  91. package/dist/extensions/detached-processes/reconcile.js.map +1 -0
  92. package/dist/extensions/detached-processes/repository.d.ts +33 -0
  93. package/dist/extensions/detached-processes/repository.js +62 -0
  94. package/dist/extensions/detached-processes/repository.js.map +1 -0
  95. package/dist/extensions/detached-processes/schema.d.ts +252 -0
  96. package/dist/extensions/detached-processes/schema.js +23 -0
  97. package/dist/extensions/detached-processes/schema.js.map +1 -0
  98. package/dist/extensions/detached-processes/spawn.d.ts +40 -0
  99. package/dist/extensions/detached-processes/spawn.js +137 -0
  100. package/dist/extensions/detached-processes/spawn.js.map +1 -0
  101. package/dist/extensions/detached-processes/tools.d.ts +41 -0
  102. package/dist/extensions/detached-processes/tools.js +243 -0
  103. package/dist/extensions/detached-processes/tools.js.map +1 -0
  104. package/dist/extensions/detached-processes/watcher.d.ts +7 -0
  105. package/dist/extensions/detached-processes/watcher.js +19 -0
  106. package/dist/extensions/detached-processes/watcher.js.map +1 -0
  107. package/dist/extensions/external/index.d.ts +11 -0
  108. package/dist/extensions/external/index.js +40 -0
  109. package/dist/extensions/external/index.js.map +1 -0
  110. package/dist/extensions/external/installs.d.ts +39 -0
  111. package/dist/extensions/external/installs.js +98 -0
  112. package/dist/extensions/external/installs.js.map +1 -0
  113. package/dist/extensions/external/loader.d.ts +19 -0
  114. package/dist/extensions/external/loader.js +70 -0
  115. package/dist/extensions/external/loader.js.map +1 -0
  116. package/dist/extensions/external/tools.d.ts +17 -0
  117. package/dist/extensions/external/tools.js +112 -0
  118. package/dist/extensions/external/tools.js.map +1 -0
  119. package/dist/extensions/git/commit.d.ts +19 -0
  120. package/dist/extensions/git/commit.js +44 -0
  121. package/dist/extensions/git/commit.js.map +1 -0
  122. package/dist/extensions/git/git.d.ts +11 -0
  123. package/dist/extensions/git/git.js +29 -0
  124. package/dist/extensions/git/git.js.map +1 -0
  125. package/dist/extensions/git/hooks.d.ts +10 -0
  126. package/dist/extensions/git/hooks.js +88 -0
  127. package/dist/extensions/git/hooks.js.map +1 -0
  128. package/dist/extensions/git/index.d.ts +11 -0
  129. package/dist/extensions/git/index.js +28 -0
  130. package/dist/extensions/git/index.js.map +1 -0
  131. package/dist/extensions/git/processor.d.ts +13 -0
  132. package/dist/extensions/git/processor.js +52 -0
  133. package/dist/extensions/git/processor.js.map +1 -0
  134. package/dist/extensions/git/sync.d.ts +44 -0
  135. package/dist/extensions/git/sync.js +189 -0
  136. package/dist/extensions/git/sync.js.map +1 -0
  137. package/dist/extensions/git/tools.d.ts +21 -0
  138. package/dist/extensions/git/tools.js +101 -0
  139. package/dist/extensions/git/tools.js.map +1 -0
  140. package/dist/extensions/host.d.ts +31 -0
  141. package/dist/extensions/host.js +75 -0
  142. package/dist/extensions/host.js.map +1 -0
  143. package/dist/extensions/index.d.ts +3 -0
  144. package/dist/extensions/index.js +32 -0
  145. package/dist/extensions/index.js.map +1 -0
  146. package/dist/extensions/memory/archive.d.ts +8 -0
  147. package/dist/extensions/memory/archive.js +46 -0
  148. package/dist/extensions/memory/archive.js.map +1 -0
  149. package/dist/extensions/memory/dates.d.ts +2 -0
  150. package/dist/extensions/memory/dates.js +7 -0
  151. package/dist/extensions/memory/dates.js.map +1 -0
  152. package/dist/extensions/memory/extraction.d.ts +17 -0
  153. package/dist/extensions/memory/extraction.js +218 -0
  154. package/dist/extensions/memory/extraction.js.map +1 -0
  155. package/dist/extensions/memory/index.d.ts +20 -0
  156. package/dist/extensions/memory/index.js +67 -0
  157. package/dist/extensions/memory/index.js.map +1 -0
  158. package/dist/extensions/memory/indexes.d.ts +14 -0
  159. package/dist/extensions/memory/indexes.js +64 -0
  160. package/dist/extensions/memory/indexes.js.map +1 -0
  161. package/dist/extensions/memory/layout.d.ts +20 -0
  162. package/dist/extensions/memory/layout.js +79 -0
  163. package/dist/extensions/memory/layout.js.map +1 -0
  164. package/dist/extensions/memory/maintenance.d.ts +21 -0
  165. package/dist/extensions/memory/maintenance.js +357 -0
  166. package/dist/extensions/memory/maintenance.js.map +1 -0
  167. package/dist/extensions/memory/prompts.d.ts +8 -0
  168. package/dist/extensions/memory/prompts.js +125 -0
  169. package/dist/extensions/memory/prompts.js.map +1 -0
  170. package/dist/extensions/memory/transcript.d.ts +18 -0
  171. package/dist/extensions/memory/transcript.js +79 -0
  172. package/dist/extensions/memory/transcript.js.map +1 -0
  173. package/dist/extensions/notifications/format.d.ts +5 -0
  174. package/dist/extensions/notifications/format.js +17 -0
  175. package/dist/extensions/notifications/format.js.map +1 -0
  176. package/dist/extensions/notifications/index.d.ts +13 -0
  177. package/dist/extensions/notifications/index.js +29 -0
  178. package/dist/extensions/notifications/index.js.map +1 -0
  179. package/dist/extensions/notifications/payload.d.ts +22 -0
  180. package/dist/extensions/notifications/payload.js +29 -0
  181. package/dist/extensions/notifications/payload.js.map +1 -0
  182. package/dist/extensions/notifications/router.d.ts +29 -0
  183. package/dist/extensions/notifications/router.js +55 -0
  184. package/dist/extensions/notifications/router.js.map +1 -0
  185. package/dist/extensions/notifications/tools.d.ts +12 -0
  186. package/dist/extensions/notifications/tools.js +41 -0
  187. package/dist/extensions/notifications/tools.js.map +1 -0
  188. package/dist/extensions/projects/context-provider.d.ts +9 -0
  189. package/dist/extensions/projects/context-provider.js +37 -0
  190. package/dist/extensions/projects/context-provider.js.map +1 -0
  191. package/dist/extensions/projects/git.d.ts +28 -0
  192. package/dist/extensions/projects/git.js +91 -0
  193. package/dist/extensions/projects/git.js.map +1 -0
  194. package/dist/extensions/projects/hooks.d.ts +7 -0
  195. package/dist/extensions/projects/hooks.js +42 -0
  196. package/dist/extensions/projects/hooks.js.map +1 -0
  197. package/dist/extensions/projects/index.d.ts +11 -0
  198. package/dist/extensions/projects/index.js +30 -0
  199. package/dist/extensions/projects/index.js.map +1 -0
  200. package/dist/extensions/projects/processor.d.ts +13 -0
  201. package/dist/extensions/projects/processor.js +63 -0
  202. package/dist/extensions/projects/processor.js.map +1 -0
  203. package/dist/extensions/projects/tools.d.ts +21 -0
  204. package/dist/extensions/projects/tools.js +118 -0
  205. package/dist/extensions/projects/tools.js.map +1 -0
  206. package/dist/extensions/registrations.d.ts +21 -0
  207. package/dist/extensions/registrations.js +12 -0
  208. package/dist/extensions/registrations.js.map +1 -0
  209. package/dist/extensions/repl/index.d.ts +2 -0
  210. package/dist/extensions/repl/index.js +85 -0
  211. package/dist/extensions/repl/index.js.map +1 -0
  212. package/dist/extensions/skills/agents.d.ts +17 -0
  213. package/dist/extensions/skills/agents.js +77 -0
  214. package/dist/extensions/skills/agents.js.map +1 -0
  215. package/dist/extensions/skills/delegate.d.ts +22 -0
  216. package/dist/extensions/skills/delegate.js +54 -0
  217. package/dist/extensions/skills/delegate.js.map +1 -0
  218. package/dist/extensions/skills/index.d.ts +11 -0
  219. package/dist/extensions/skills/index.js +43 -0
  220. package/dist/extensions/skills/index.js.map +1 -0
  221. package/dist/extensions/skills/reload.d.ts +8 -0
  222. package/dist/extensions/skills/reload.js +38 -0
  223. package/dist/extensions/skills/reload.js.map +1 -0
  224. package/dist/extensions/tasks/executor.d.ts +43 -0
  225. package/dist/extensions/tasks/executor.js +179 -0
  226. package/dist/extensions/tasks/executor.js.map +1 -0
  227. package/dist/extensions/tasks/expiration.d.ts +12 -0
  228. package/dist/extensions/tasks/expiration.js +17 -0
  229. package/dist/extensions/tasks/expiration.js.map +1 -0
  230. package/dist/extensions/tasks/generation.d.ts +14 -0
  231. package/dist/extensions/tasks/generation.js +70 -0
  232. package/dist/extensions/tasks/generation.js.map +1 -0
  233. package/dist/extensions/tasks/index.d.ts +14 -0
  234. package/dist/extensions/tasks/index.js +75 -0
  235. package/dist/extensions/tasks/index.js.map +1 -0
  236. package/dist/extensions/tasks/repository.d.ts +53 -0
  237. package/dist/extensions/tasks/repository.js +147 -0
  238. package/dist/extensions/tasks/repository.js.map +1 -0
  239. package/dist/extensions/tasks/schedule.d.ts +13 -0
  240. package/dist/extensions/tasks/schedule.js +32 -0
  241. package/dist/extensions/tasks/schedule.js.map +1 -0
  242. package/dist/extensions/tasks/schema.d.ts +423 -0
  243. package/dist/extensions/tasks/schema.js +45 -0
  244. package/dist/extensions/tasks/schema.js.map +1 -0
  245. package/dist/extensions/tasks/session-delivery.d.ts +18 -0
  246. package/dist/extensions/tasks/session-delivery.js +39 -0
  247. package/dist/extensions/tasks/session-delivery.js.map +1 -0
  248. package/dist/extensions/tasks/tools.d.ts +38 -0
  249. package/dist/extensions/tasks/tools.js +181 -0
  250. package/dist/extensions/tasks/tools.js.map +1 -0
  251. package/dist/extensions/telegram/buttons.d.ts +14 -0
  252. package/dist/extensions/telegram/buttons.js +49 -0
  253. package/dist/extensions/telegram/buttons.js.map +1 -0
  254. package/dist/extensions/telegram/channel.d.ts +39 -0
  255. package/dist/extensions/telegram/channel.js +201 -0
  256. package/dist/extensions/telegram/channel.js.map +1 -0
  257. package/dist/extensions/telegram/chunking.d.ts +7 -0
  258. package/dist/extensions/telegram/chunking.js +67 -0
  259. package/dist/extensions/telegram/chunking.js.map +1 -0
  260. package/dist/extensions/telegram/inbound.d.ts +7 -0
  261. package/dist/extensions/telegram/inbound.js +29 -0
  262. package/dist/extensions/telegram/inbound.js.map +1 -0
  263. package/dist/extensions/telegram/index.d.ts +13 -0
  264. package/dist/extensions/telegram/index.js +67 -0
  265. package/dist/extensions/telegram/index.js.map +1 -0
  266. package/dist/extensions/telegram/media.d.ts +39 -0
  267. package/dist/extensions/telegram/media.js +223 -0
  268. package/dist/extensions/telegram/media.js.map +1 -0
  269. package/dist/extensions/telegram/mutex.d.ts +9 -0
  270. package/dist/extensions/telegram/mutex.js +14 -0
  271. package/dist/extensions/telegram/mutex.js.map +1 -0
  272. package/dist/extensions/telegram/sending.d.ts +48 -0
  273. package/dist/extensions/telegram/sending.js +119 -0
  274. package/dist/extensions/telegram/sending.js.map +1 -0
  275. package/dist/extensions/telegram/streaming.d.ts +46 -0
  276. package/dist/extensions/telegram/streaming.js +140 -0
  277. package/dist/extensions/telegram/streaming.js.map +1 -0
  278. package/dist/extensions/telegram/tools.d.ts +80 -0
  279. package/dist/extensions/telegram/tools.js +232 -0
  280. package/dist/extensions/telegram/tools.js.map +1 -0
  281. package/dist/extensions/workflows/cleanup.d.ts +10 -0
  282. package/dist/extensions/workflows/cleanup.js +38 -0
  283. package/dist/extensions/workflows/cleanup.js.map +1 -0
  284. package/dist/extensions/workflows/index.d.ts +11 -0
  285. package/dist/extensions/workflows/index.js +42 -0
  286. package/dist/extensions/workflows/index.js.map +1 -0
  287. package/dist/extensions/workflows/loader.d.ts +27 -0
  288. package/dist/extensions/workflows/loader.js +90 -0
  289. package/dist/extensions/workflows/loader.js.map +1 -0
  290. package/dist/extensions/workflows/model.d.ts +19 -0
  291. package/dist/extensions/workflows/model.js +7 -0
  292. package/dist/extensions/workflows/model.js.map +1 -0
  293. package/dist/extensions/workflows/repository.d.ts +24 -0
  294. package/dist/extensions/workflows/repository.js +61 -0
  295. package/dist/extensions/workflows/repository.js.map +1 -0
  296. package/dist/extensions/workflows/schema.d.ts +193 -0
  297. package/dist/extensions/workflows/schema.js +20 -0
  298. package/dist/extensions/workflows/schema.js.map +1 -0
  299. package/dist/extensions/workflows/tools.d.ts +27 -0
  300. package/dist/extensions/workflows/tools.js +285 -0
  301. package/dist/extensions/workflows/tools.js.map +1 -0
  302. package/dist/log.d.ts +8 -0
  303. package/dist/log.js +15 -0
  304. package/dist/log.js.map +1 -0
  305. package/dist/main.d.ts +2 -0
  306. package/dist/main.js +27 -0
  307. package/dist/main.js.map +1 -0
  308. package/dist/migration/ask.d.ts +8 -0
  309. package/dist/migration/ask.js +24 -0
  310. package/dist/migration/ask.js.map +1 -0
  311. package/dist/migration/config.d.ts +10 -0
  312. package/dist/migration/config.js +122 -0
  313. package/dist/migration/config.js.map +1 -0
  314. package/dist/migration/context.d.ts +3 -0
  315. package/dist/migration/context.js +24 -0
  316. package/dist/migration/context.js.map +1 -0
  317. package/dist/migration/database.d.ts +8 -0
  318. package/dist/migration/database.js +51 -0
  319. package/dist/migration/database.js.map +1 -0
  320. package/dist/migration/fs.d.ts +1 -0
  321. package/dist/migration/fs.js +11 -0
  322. package/dist/migration/fs.js.map +1 -0
  323. package/dist/migration/index.d.ts +11 -0
  324. package/dist/migration/index.js +28 -0
  325. package/dist/migration/index.js.map +1 -0
  326. package/dist/migration/skills.d.ts +19 -0
  327. package/dist/migration/skills.js +77 -0
  328. package/dist/migration/skills.js.map +1 -0
  329. package/dist/scheduler.d.ts +17 -0
  330. package/dist/scheduler.js +53 -0
  331. package/dist/scheduler.js.map +1 -0
  332. package/dist/sessions/registry.d.ts +15 -0
  333. package/dist/sessions/registry.js +42 -0
  334. package/dist/sessions/registry.js.map +1 -0
  335. package/dist/workspace.d.ts +13 -0
  336. package/dist/workspace.js +32 -0
  337. package/dist/workspace.js.map +1 -0
  338. package/drizzle/0000_init.sql +19 -0
  339. package/drizzle/0001_extensions.sql +63 -0
  340. package/drizzle/meta/0000_snapshot.json +134 -0
  341. package/drizzle/meta/0001_snapshot.json +526 -0
  342. package/drizzle/meta/_journal.json +20 -0
  343. package/package.json +63 -0
  344. package/skills/skill-authoring/SKILL.md +168 -0
  345. package/skills/workflow-authoring/SKILL.md +251 -0
@@ -0,0 +1,218 @@
1
+ import { localIsoDate } from "./dates.js";
2
+ import { storeDir, sweepEmptyMarkdown } from "./layout.js";
3
+ import { CLASSIFICATION_EXAMPLES_SECTION, CONTEXT_DEDUP_SECTION, INDEX_UPDATE_SECTION, STORE_PURPOSE_SECTION, scopeSection, WORKSPACE_VALIDATION_SECTION, } from "./prompts.js";
4
+ import { loadConversation } from "./transcript.js";
5
+ export const MEMORY_FILE_TOOLS = ["read", "grep", "find", "ls", "edit", "write"];
6
+ const EPISODIC_BASE_PROMPT = `You are a memory extraction agent. Your task is to analyze the conversation that just ended and create or update the episodic memory file for today.
7
+
8
+ Today's date is {date}.
9
+
10
+ ## Instructions
11
+
12
+ 1. **Read existing files** in \`$WORKSPACE/memories/episodic/\` to see what's there.
13
+
14
+ 2. Analyze the conversation for meaningful events, discussions, and activities.
15
+
16
+ 3. **Write to exactly one file per day: \`{date}.md\`.**
17
+ - The ONLY valid filename is the date itself. No suffixes, no variants. \`{date}.md\` is correct. \`{date}-consolidated.md\`, \`{date}-final.md\`, \`{date}-updated.md\` are ALL WRONG — never create files like these.
18
+ - If \`{date}.md\` already exists, READ it first, then EDIT it to merge the new information into the existing content. Do not create a second file.
19
+ - If it does not exist, create \`{date}.md\`.
20
+
21
+ 4. **Keep entries short and scannable:**
22
+ - One heading per session or topic, not per conversational turn
23
+ - 2-5 bullet points per heading capturing key outcomes
24
+ - Target: 30-80 lines per day, even for busy days with many sessions
25
+ - DO NOT include: verbatim quotes, step-by-step technical details, full lists of files changed, implementation specifics, or routine activity status
26
+
27
+ 5. **Cleanup duty**: If you see files that don't match the \`YYYY-MM-DD.md\` pattern (e.g., files with \`-consolidated\`, \`-final\`, \`-updated\` suffixes), merge any useful content into the correct \`YYYY-MM-DD.md\` file and empty the variant so it gets cleaned up. This corrects filename format violations — episodic entries are never deleted based on their content.
28
+
29
+ 6. **Important constraints**:
30
+ - Only create or modify files within \`$WORKSPACE/memories/episodic/\`
31
+ - If the conversation was trivial or contained no meaningful information, it is perfectly acceptable to create no files
32
+
33
+ Remember: These memories help the assistant maintain context across sessions. Focus on what would be useful to remember, not a transcript of what happened.`;
34
+ const FACTS_BASE_PROMPT = `You are a memory extraction agent. Your task is to analyze the conversation and extract or update factual information that would be useful to remember for future conversations.
35
+
36
+ ## Instructions
37
+
38
+ 1. **Read existing files** in \`$WORKSPACE/memories/facts/\` to see what facts are already stored.
39
+
40
+ 2. Analyze the conversation for STABLE REFERENCE INFORMATION — things that stay true across conversations:
41
+ - Personal details about the user (job, location, family, contacts)
42
+ - Important dates, deadlines, or upcoming events
43
+ - Stable routines or commitments (structure only, not daily logs)
44
+ - Key people and their roles/relationships
45
+ - Technical decisions or configurations that affect future work
46
+ - Account info, service subscriptions, tool setups
47
+
48
+ DO NOT store as facts:
49
+ - Daily activity logs or status updates (that's episodic memory)
50
+ - One-time events: bug fixes, security incidents, feature completions, outages, deployment events — these happened once on a specific date and belong in episodic memory, not here
51
+ - Full design documents, specs, or game mechanics (project files)
52
+ - Anything longer than ~40 lines — if it needs that much space, it's not a fact, it's a document
53
+
54
+ 3. **Before creating a new file**, search for existing overlap:
55
+ - Use the grep tool to search existing files for the key topic or keywords
56
+ - If an existing file covers the same topic, UPDATE that file instead of creating a new one
57
+ - If information is spread across multiple files about the same topic, MERGE them into one file and delete the others
58
+
59
+ 4. **File Consolidation at Write Time**:
60
+ Before creating any new file, follow this mandatory sequence:
61
+ - First, list the target directory \`$WORKSPACE/memories/facts/\` with the ls tool.
62
+ - Identify which existing file (if any) covers the broadest topic that encompasses the new information. Match by project name, system name, tool, or domain — not by incident, date, or specific event.
63
+ - If a broad-topic file exists, UPDATE that file. Do NOT create an incident- or date-specific sibling alongside it (e.g., if \`<project>.md\` exists, do not also create \`<project>-<bug-description>-<YYYY-MM-DD>.md\`).
64
+ - If multiple existing files cover overlapping aspects of the same topic, prefer the most specific existing file that still covers the new information broadly — and consider merging the narrower ones into it.
65
+ - Only create a new file when NO existing file covers the topic. When you do create one, choose a broad topic name that future related extracts can merge into — \`<project>.md\`, \`<system>.md\`, \`<tool>.md\`, \`<domain>.md\` — never a name scoped to one incident, bug, patch, or date.
66
+ - Positive examples (broad, future-mergeable): \`<project>.md\`, \`<system>.md\`, \`<tool>.md\`, \`<domain>.md\`, \`work-info.md\`, \`tech-stack.md\`.
67
+ - Negative examples (forbidden — too narrow): \`<project>-<bug-description>-<YYYY-MM-DD>.md\`, \`<project>-patch-<issue-id>.md\`, \`<system>-<incident>-<date>.md\`, \`<topic>-session-<date>.md\`.
68
+
69
+ 5. Manage the fact files:
70
+ - Create new files with descriptive names ONLY when no existing file covers the topic
71
+ - Update existing files when new information extends what's there
72
+ - **Merge** files that overlap in topic — combine into one, delete the rest
73
+ - **Delete** files that are outdated, redundant, or better covered elsewhere
74
+ - When updating a file, READ it first. If a section already covers what you're about to add, update that section rather than appending a duplicate
75
+
76
+ 6. **Prune stale and redundant entries**:
77
+ - After reading existing files, actively look for entries that may be outdated or no longer accurate based on the conversation:
78
+ - Information contradicted by new statements (e.g., file says "works at Company A" but conversation reveals a move to Company B)
79
+ - References to completed projects, past roles, or expired commitments that the conversation confirms are done
80
+ - Entries about tools, services, or setups the user no longer uses
81
+ - When you find stale entries: update them if new information replaces the old, or delete the file if the entire topic is no longer relevant
82
+ - **Do NOT prune based on**: vague hints ("I might switch..."), old dates alone (age is not staleness), or assumptions not backed by conversation evidence
83
+
84
+ 7. Each fact file should contain:
85
+ - Clear, factual statements
86
+ - Relevant context or details
87
+ - Keep files under 40 lines. If a topic needs more detail, the detail probably belongs in a project file, not in facts memory.
88
+
89
+ 8. **Important constraints**:
90
+ - Only create or modify files within \`$WORKSPACE/memories/facts/\`
91
+ - Use descriptive, topic-based filenames (not dates). Good names: \`work-info.md\`, \`key-people.md\`, \`tech-stack.md\`. Bad names that indicate the content belongs in episodic: \`2026-04-15-outage.md\`, \`bug-fix-session.md\`, \`security-incident-april.md\`. For per-incident fragmentation patterns to avoid, see step 4's negative examples.
92
+ - If no new factual information emerged from the conversation, it is perfectly acceptable to create no files
93
+ - Do not infer facts that weren't explicitly stated — only record what was actually shared or discussed
94
+ - Before writing a fact, ask: "Will this still be useful in a month?" If no — it describes something that happened once, has a specific date, or is a record of an event — it belongs in episodic memory, not here
95
+
96
+ Remember: These memories help the assistant maintain context across sessions. Focus on accurate, stable reference information — not activity logs or documents.`;
97
+ const PREFERENCES_BASE_PROMPT = `You are a memory extraction agent. Your task is to analyze the conversation and extract or update the user's expressed preferences.
98
+
99
+ ## Instructions
100
+
101
+ 1. **Read existing files** in \`$WORKSPACE/memories/preferences/\` to see what preferences are already stored. Also read \`$WORKSPACE/AGENTS.md\` if it exists — this file contains operational instructions and workflow preferences. If it doesn't exist or is empty, proceed normally — this check is purely to avoid duplication.
102
+
103
+ 2. Analyze the conversation for SUBJECTIVE CHOICES about how things should be done:
104
+ - How they like things done (communication style, workflows, formats)
105
+ - Approaches they prefer or want to avoid
106
+ - Tool, framework, or methodology preferences
107
+ - Scheduling or organizational preferences
108
+
109
+ A preference is NOT:
110
+ - A factual detail (job title, project architecture) → facts memory
111
+ - A design decision or spec (game mechanics, system rules) → project files
112
+ - A behavioral instruction for the assistant → AGENTS.md context file
113
+ - A detailed description of a system or project → too detailed for prefs
114
+ - An implementation detail or system behavior (how something works technically) → facts memory or project docs
115
+ - A bug report, resolved issue, or one-time fix → transient, not a lasting preference
116
+ - **Financial reference data** (payment structures, rates, fee schedules, reconciliation procedures) → facts memory
117
+ - **Technical specifications** (environment variables, SDK/API limitations, tool capabilities, system requirements) → facts memory
118
+ - **Procedural workflows** (cleanup steps, diagnostic procedures, deployment sequences) → facts memory
119
+ - **System configuration records** (what was configured, where, with what values) → facts memory
120
+
121
+ 2b. **Classification self-check**: Before writing any file, ask yourself: "Is this describing HOW SOMETHING WORKS (a fact) or HOW THE USER WANTS IT DONE (a preference)?"
122
+ - "How it works" → route to facts memory — do NOT create a preferences file
123
+ - "How the user wants it done" → valid preference, proceed
124
+ - When uncertain, prefer facts over preferences — objective information does not become a preference just because the user mentioned it
125
+
126
+ 3. **Before creating a new file**, search for existing overlap:
127
+ - Use the grep tool to search existing files for the key topic or keywords
128
+ - Also search \`$WORKSPACE/AGENTS.md\` for the same topic. If AGENTS.md already captures the preference (even in different words), skip creating a new file — the information is already stored where it belongs
129
+ - If an existing file covers the same topic, UPDATE that file instead of creating a new one
130
+ - If the same preference appears in multiple files, consolidate into the most specific file and remove it from the others
131
+
132
+ 4. **File Consolidation at Write Time**:
133
+ Before creating any new file, follow this mandatory sequence:
134
+ - First, list the target directory \`$WORKSPACE/memories/preferences/\` with the ls tool.
135
+ - Identify which existing file (if any) covers the broadest preference topic that encompasses the new information. Match by topic area (style, workflow, communication, tooling), project, system, or domain — not by a specific occasion, date, or one-off interaction.
136
+ - If a broad-topic file exists, UPDATE that file. Do NOT create an occasion- or date-specific sibling alongside it (e.g., if \`<topic-area>-style.md\` exists, do not also create \`<topic-area>-feedback-<YYYY-MM-DD>.md\`).
137
+ - If multiple existing files cover overlapping aspects of the same topic, prefer the most specific existing file that still covers the new information broadly — and consider merging the narrower ones into it.
138
+ - Only create a new file when NO existing file covers the topic. When you do create one, choose a broad topic name that future related extracts can merge into — \`<topic-area>-style.md\`, \`<topic-area>-workflow.md\`, \`<domain>.md\`, \`<project>.md\` — never a name scoped to one occasion, feedback moment, or date.
139
+ - Positive examples (broad, future-mergeable): \`<topic-area>-style.md\`, \`<topic-area>-workflow.md\`, \`<domain>.md\`, \`<project>.md\`, \`communication-style.md\`, \`code-formatting.md\`.
140
+ - Negative examples (forbidden — too narrow): \`<topic-area>-feedback-<YYYY-MM-DD>.md\`, \`<project>-preference-<issue-id>.md\`, \`<topic-area>-session-<date>.md\`, \`<one-off>-incident-<date>.md\`.
141
+
142
+ 5. Manage the preference files:
143
+ - Create new files with descriptive names ONLY when no existing file covers the topic
144
+ - When updating a file, READ it first. If it already says what you're about to add, do not add it again. If it says something similar in different words, REPLACE the old version — don't add a second version.
145
+ - Delete or merge files that overlap
146
+ - Each file should have ONE clear statement per preference, not multiple sections restating the same thing in different words
147
+
148
+ 6. **Prune stale and reversed preferences**:
149
+ - After reading existing files, actively look for preferences that may no longer reflect the user's current stance:
150
+ - Reversed preferences (e.g., file says "prefers dark mode" but user now says "I switched to light mode")
151
+ - Preferences about tools or workflows the user has explicitly moved away from
152
+ - Preferences that the conversation contradicts with clear, stated alternatives
153
+ - When you find stale preferences: update the file if the user expressed a new preference on the same topic, or delete the file if the preference topic is no longer relevant
154
+ - **Do NOT prune based on**: vague hints ("I might try..."), single exceptions to general rules, or assumptions not backed by conversation evidence
155
+
156
+ 7. Each preference file should contain:
157
+ - A clear statement of the preference
158
+ - Brief context or an example (1-2 sentences)
159
+ - When appropriate, how strongly the preference is held
160
+ - Keep files under 30 lines. A preference that takes more to express is probably a spec or design document, not a preference.
161
+
162
+ 8. **Important constraints**:
163
+ - Only create or modify files within \`$WORKSPACE/memories/preferences/\`
164
+ - Use descriptive, topic-based filenames (not dates). Good names: \`communication-style.md\`, \`code-formatting.md\`, \`<topic-area>-workflow.md\`. For per-occasion fragmentation patterns to avoid, see step 4's negative examples.
165
+ - If no preference-related information emerged from the conversation, it is perfectly acceptable to create no files
166
+ - Do not infer preferences from silence — only record what the user actually expressed
167
+
168
+ Remember: These memories help the assistant tailor its approach to the user's preferences. Focus on genuine, stated choices — not facts, specs, or instructions.`;
169
+ const STORE_PROMPTS = {
170
+ episodic: [EPISODIC_BASE_PROMPT, scopeSection("episodic")].join("\n\n"),
171
+ facts: [
172
+ FACTS_BASE_PROMPT,
173
+ CLASSIFICATION_EXAMPLES_SECTION,
174
+ STORE_PURPOSE_SECTION,
175
+ CONTEXT_DEDUP_SECTION,
176
+ WORKSPACE_VALIDATION_SECTION,
177
+ INDEX_UPDATE_SECTION,
178
+ scopeSection("facts"),
179
+ ].join("\n\n"),
180
+ preferences: [
181
+ PREFERENCES_BASE_PROMPT,
182
+ CLASSIFICATION_EXAMPLES_SECTION,
183
+ STORE_PURPOSE_SECTION,
184
+ CONTEXT_DEDUP_SECTION,
185
+ WORKSPACE_VALIDATION_SECTION,
186
+ INDEX_UPDATE_SECTION,
187
+ scopeSection("preferences"),
188
+ ].join("\n\n"),
189
+ };
190
+ export const extractionSystemPrompt = (store, workspaceRoot) => STORE_PROMPTS[store].replaceAll("$WORKSPACE", workspaceRoot).replaceAll("{date}", localIsoDate());
191
+ export const conversationPrompt = (conversation) => `The following conversation with the user just ended:\n\n<conversation>\n${conversation}\n</conversation>\n\nFollow your instructions and update the memory files accordingly.`;
192
+ /**
193
+ * Session-close extraction: re-reads the session transcript and runs a headless
194
+ * agent with file tools to fold the conversation into one memory store.
195
+ */
196
+ export const createExtractionProcessor = (store, { side, workspaceRoot, maxTranscriptChars }) => ({
197
+ name: `memory-${store}`,
198
+ phase: "main",
199
+ async process({ transcriptPath, log }) {
200
+ if (transcriptPath == null) {
201
+ log.debug({ store }, "no transcript — skipping memory extraction");
202
+ return;
203
+ }
204
+ const conversation = await loadConversation(transcriptPath, maxTranscriptChars);
205
+ if (conversation === "") {
206
+ log.debug({ store }, "empty conversation — skipping memory extraction");
207
+ return;
208
+ }
209
+ await side.run({
210
+ tools: MEMORY_FILE_TOOLS,
211
+ system: extractionSystemPrompt(store, workspaceRoot),
212
+ prompt: conversationPrompt(conversation),
213
+ tier: "processor",
214
+ });
215
+ await sweepEmptyMarkdown(storeDir(workspaceRoot, store), log);
216
+ },
217
+ });
218
+ //# sourceMappingURL=extraction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extraction.js","sourceRoot":"","sources":["../../../src/extensions/memory/extraction.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Long-term memory: a git-versioned markdown store under workspace `memories/`
3
+ * (episodic, facts, preferences, transcripts). Injects a static index of the
4
+ * store on every message, extracts memories at session close, archives the pi
5
+ * transcript, and consolidates the store on a nightly schedule.
6
+ */
7
+ declare const _default: import("../api.ts").TachikomaExtension<{
8
+ enabled: boolean;
9
+ maxTranscriptChars: number;
10
+ maintenance: {
11
+ enabled: boolean;
12
+ recentDays: number;
13
+ weeklyThresholdMonths: number;
14
+ monthlyThresholdMonths: number;
15
+ episodicSchedule: string;
16
+ factsSchedule: string;
17
+ preferencesSchedule: string;
18
+ };
19
+ }>;
20
+ export default _default;
@@ -0,0 +1,67 @@
1
+ import { Type } from "typebox";
2
+ import { defineExtension } from "../api.js";
3
+ import { createCoreContextProcessor } from "../context/processor.js";
4
+ import { createTranscriptArchiveProcessor } from "./archive.js";
5
+ import { createExtractionProcessor } from "./extraction.js";
6
+ import { createMemoryIndexProvider } from "./indexes.js";
7
+ import { ensureMemoryLayout, MEMORY_STORES } from "./layout.js";
8
+ import { runMaintenanceTick } from "./maintenance.js";
9
+ const MemoryConfigSchema = Type.Object({
10
+ enabled: Type.Boolean({ default: true }),
11
+ /** Cap on the rendered conversation injected into extraction prompts (tail-priority). */
12
+ maxTranscriptChars: Type.Number({ default: 24000 }),
13
+ maintenance: Type.Object({
14
+ enabled: Type.Boolean({ default: true }),
15
+ // Staggered so the three headless agent runs don't pile up at the same minute.
16
+ episodicSchedule: Type.String({ default: "0 3 * * *" }),
17
+ factsSchedule: Type.String({ default: "20 3 * * *" }),
18
+ preferencesSchedule: Type.String({ default: "40 3 * * *" }),
19
+ recentDays: Type.Number({ default: 15 }),
20
+ weeklyThresholdMonths: Type.Number({ default: 3 }),
21
+ monthlyThresholdMonths: Type.Number({ default: 12 }),
22
+ }, { default: {} }),
23
+ });
24
+ /**
25
+ * Long-term memory: a git-versioned markdown store under workspace `memories/`
26
+ * (episodic, facts, preferences, transcripts). Injects a static index of the
27
+ * store on every message, extracts memories at session close, archives the pi
28
+ * transcript, and consolidates the store on a nightly schedule.
29
+ */
30
+ export default defineExtension({
31
+ name: "memory",
32
+ configSchema: MemoryConfigSchema,
33
+ setup(app) {
34
+ if (!app.extensionConfig.enabled) {
35
+ app.log.info("memory extension disabled by configuration");
36
+ return;
37
+ }
38
+ const workspaceRoot = app.workspace.root;
39
+ app.bootstrap("init-memory-layout", () => ensureMemoryLayout(workspaceRoot, app.log));
40
+ app.agent.provideContext(createMemoryIndexProvider(workspaceRoot));
41
+ const extraction = {
42
+ side: app.agent.side,
43
+ workspaceRoot,
44
+ maxTranscriptChars: app.extensionConfig.maxTranscriptChars,
45
+ };
46
+ for (const store of MEMORY_STORES) {
47
+ app.sessions.registerProcessor(createExtractionProcessor(store, extraction));
48
+ }
49
+ // Registered here for now — once the context extension grows its own
50
+ // processor wiring this registration belongs in context/index.ts.
51
+ app.sessions.registerProcessor(createCoreContextProcessor({
52
+ side: app.agent.side,
53
+ workspaceRoot,
54
+ dataDir: app.workspace.dataDir,
55
+ maxTranscriptChars: app.extensionConfig.maxTranscriptChars,
56
+ }));
57
+ app.sessions.registerProcessor(createTranscriptArchiveProcessor(workspaceRoot));
58
+ const { maintenance } = app.extensionConfig;
59
+ if (maintenance.enabled) {
60
+ const deps = { side: app.agent.side, workspaceRoot, settings: maintenance, log: app.log };
61
+ app.scheduler.cron("memory-episodic-maintenance", maintenance.episodicSchedule, () => runMaintenanceTick("episodic", deps));
62
+ app.scheduler.cron("memory-facts-maintenance", maintenance.factsSchedule, () => runMaintenanceTick("facts", deps));
63
+ app.scheduler.cron("memory-preferences-maintenance", maintenance.preferencesSchedule, () => runMaintenanceTick("preferences", deps));
64
+ }
65
+ },
66
+ });
67
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/memory/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { ContextProvider } from "../api.ts";
2
+ import { type MemoryStore } from "./layout.ts";
3
+ /**
4
+ * Format a MEMORY.md file's raw content into an injectable section. Entries
5
+ * must match "[Name](./path.md): description"; malformed lines are skipped.
6
+ * Returns null when the file has no usable entries.
7
+ */
8
+ export declare const formatMemoryIndex: (store: MemoryStore, rawContent: string) => string | null;
9
+ /**
10
+ * Static memory index injection: the workspace layout plus the parsed facts and
11
+ * preferences MEMORY.md indexes, so the agent knows what exists and reads files
12
+ * on demand instead of getting everything inlined.
13
+ */
14
+ export declare const createMemoryIndexProvider: (workspaceRoot: string) => ContextProvider;
@@ -0,0 +1,64 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { fileExists, INDEXED_STORES, MEMORY_INDEX_FILENAME, memoriesRoot, storeDir, } from "./layout.js";
4
+ const INDEX_ENTRY_RE = /^\[([^\]]+)\]\(\.\/([^)]+\.md)\):\s*(.+)$/gm;
5
+ const STORE_DESCRIPTIONS = {
6
+ facts: "Stable reference information: personal details, key people, technical decisions.\nBrowse the entries below. When a file seems relevant to the current conversation,\nread it with the read tool to get the full content.",
7
+ preferences: "Subjective choices about how things should be done.\nBrowse the entries below. When a file seems relevant to the current conversation,\nread it with the read tool to get the full content.",
8
+ };
9
+ const LAYOUT_SECTION = `## Memory
10
+
11
+ The workspace keeps long-term memory as markdown files under \`memories/\`:
12
+
13
+ - \`memories/episodic/\` — date-stamped conversation summaries (\`YYYY-MM-DD.md\`, plus weekly \`YYYY-WNN.md\` and monthly \`YYYY-MM.md\` rollups)
14
+ - \`memories/facts/\` — stable reference information, one topic per file, indexed in \`MEMORY.md\`
15
+ - \`memories/preferences/\` — the user's expressed preferences, one topic per file, indexed in \`MEMORY.md\`
16
+
17
+ None of these files are loaded automatically. When the conversation touches a topic that might be covered there, grep or read the relevant memory files on demand.`;
18
+ const capitalize = (value) => value.charAt(0).toUpperCase() + value.slice(1);
19
+ /**
20
+ * Format a MEMORY.md file's raw content into an injectable section. Entries
21
+ * must match "[Name](./path.md): description"; malformed lines are skipped.
22
+ * Returns null when the file has no usable entries.
23
+ */
24
+ export const formatMemoryIndex = (store, rawContent) => {
25
+ const entries = [...rawContent.matchAll(INDEX_ENTRY_RE)].map((match) => match[0]);
26
+ if (entries.length === 0)
27
+ return null;
28
+ const description = STORE_DESCRIPTIONS[store] ??
29
+ "Browse the entries below. When a file seems relevant, read it with the read tool.";
30
+ return [
31
+ `## ${capitalize(store)} Index`,
32
+ "",
33
+ description,
34
+ "",
35
+ ...entries.map((entry) => `- ${entry}`),
36
+ ].join("\n");
37
+ };
38
+ /**
39
+ * Static memory index injection: the workspace layout plus the parsed facts and
40
+ * preferences MEMORY.md indexes, so the agent knows what exists and reads files
41
+ * on demand instead of getting everything inlined.
42
+ */
43
+ export const createMemoryIndexProvider = (workspaceRoot) => ({
44
+ name: "memory-index",
45
+ async provide() {
46
+ if (!(await fileExists(memoriesRoot(workspaceRoot))))
47
+ return null;
48
+ const sections = [LAYOUT_SECTION];
49
+ for (const store of INDEXED_STORES) {
50
+ let raw;
51
+ try {
52
+ raw = await readFile(join(storeDir(workspaceRoot, store), MEMORY_INDEX_FILENAME), "utf8");
53
+ }
54
+ catch {
55
+ continue;
56
+ }
57
+ const formatted = formatMemoryIndex(store, raw);
58
+ if (formatted != null)
59
+ sections.push(formatted);
60
+ }
61
+ return { tag: "memories", content: sections.join("\n\n") };
62
+ },
63
+ });
64
+ //# sourceMappingURL=indexes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexes.js","sourceRoot":"","sources":["../../../src/extensions/memory/indexes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EACL,UAAU,EACV,cAAc,EACd,qBAAqB,EAErB,YAAY,EACZ,QAAQ,GACT,MAAM,aAAa,CAAC;AAErB,MAAM,cAAc,GAAG,6CAA6C,CAAC;AAErE,MAAM,kBAAkB,GAAyC;IAC/D,KAAK,EACH,0NAA0N;IAC5N,WAAW,EACT,6LAA6L;CAChM,CAAC;AAEF,MAAM,cAAc,GAAG;;;;;;;;mKAQ4I,CAAC;AAEpK,MAAM,UAAU,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAE7F;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAAkB,EAAE,UAAkB,EAAiB,EAAE;IACzF,MAAM,OAAO,GAAG,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAElF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtC,MAAM,WAAW,GACf,kBAAkB,CAAC,KAAK,CAAC;QACzB,mFAAmF,CAAC;IAEtF,OAAO;QACL,MAAM,UAAU,CAAC,KAAK,CAAC,QAAQ;QAC/B,EAAE;QACF,WAAW;QACX,EAAE;QACF,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC;KACxC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,aAAqB,EAAmB,EAAE,CAAC,CAAC;IACpF,IAAI,EAAE,cAAc;IAEpB,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QAElE,MAAM,QAAQ,GAAG,CAAC,cAAc,CAAC,CAAC;QAElC,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;YACnC,IAAI,GAAW,CAAC;YAEhB,IAAI,CAAC;gBACH,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,qBAAqB,CAAC,EAAE,MAAM,CAAC,CAAC;YAC5F,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YAED,MAAM,SAAS,GAAG,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAChD,IAAI,SAAS,IAAI,IAAI;gBAAE,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAClD,CAAC;QAED,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;IAC7D,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { Logger } from "../../log.ts";
2
+ export declare const MEMORY_STORES: readonly ["episodic", "facts", "preferences"];
3
+ export type MemoryStore = (typeof MEMORY_STORES)[number];
4
+ export declare const INDEXED_STORES: readonly ["facts", "preferences"];
5
+ export declare const MEMORY_INDEX_FILENAME = "MEMORY.md";
6
+ export declare const memoriesRoot: (workspaceRoot: string) => string;
7
+ export declare const storeDir: (workspaceRoot: string, store: MemoryStore) => string;
8
+ export declare const transcriptsDir: (workspaceRoot: string) => string;
9
+ export declare const fileExists: (path: string) => Promise<boolean>;
10
+ /**
11
+ * Create the memory directory layout and seed MEMORY.md indexes (idempotent).
12
+ * Pre-existing memory files get placeholder index entries; the maintenance
13
+ * ticks regenerate proper descriptions later.
14
+ */
15
+ export declare const ensureMemoryLayout: (workspaceRoot: string, log: Logger) => Promise<void>;
16
+ /**
17
+ * The extraction/maintenance agents have no delete tool — they empty files
18
+ * instead, and the host removes those leftovers here after each run.
19
+ */
20
+ export declare const sweepEmptyMarkdown: (dir: string, log: Logger) => Promise<void>;
@@ -0,0 +1,79 @@
1
+ import { mkdir, readdir, readFile, stat, unlink, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ export const MEMORY_STORES = ["episodic", "facts", "preferences"];
4
+ export const INDEXED_STORES = ["facts", "preferences"];
5
+ export const MEMORY_INDEX_FILENAME = "MEMORY.md";
6
+ export const memoriesRoot = (workspaceRoot) => join(workspaceRoot, "memories");
7
+ export const storeDir = (workspaceRoot, store) => join(memoriesRoot(workspaceRoot), store);
8
+ export const transcriptsDir = (workspaceRoot) => join(memoriesRoot(workspaceRoot), "transcripts");
9
+ export const fileExists = async (path) => {
10
+ try {
11
+ await stat(path);
12
+ return true;
13
+ }
14
+ catch {
15
+ return false;
16
+ }
17
+ };
18
+ const titleFromFilename = (filename) => filename
19
+ .replace(/\.md$/, "")
20
+ .split(/[-_]/)
21
+ .filter((part) => part !== "")
22
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
23
+ .join(" ");
24
+ const listMarkdown = async (dir) => {
25
+ const names = await readdir(dir);
26
+ return names.filter((name) => name.endsWith(".md") && name !== MEMORY_INDEX_FILENAME).sort();
27
+ };
28
+ /**
29
+ * Create the memory directory layout and seed MEMORY.md indexes (idempotent).
30
+ * Pre-existing memory files get placeholder index entries; the maintenance
31
+ * ticks regenerate proper descriptions later.
32
+ */
33
+ export const ensureMemoryLayout = async (workspaceRoot, log) => {
34
+ const dirs = [
35
+ ...MEMORY_STORES.map((store) => storeDir(workspaceRoot, store)),
36
+ transcriptsDir(workspaceRoot),
37
+ ];
38
+ for (const dir of dirs)
39
+ await mkdir(dir, { recursive: true });
40
+ for (const store of INDEXED_STORES) {
41
+ const indexPath = join(storeDir(workspaceRoot, store), MEMORY_INDEX_FILENAME);
42
+ if (await fileExists(indexPath))
43
+ continue;
44
+ const entries = (await listMarkdown(storeDir(workspaceRoot, store))).map((name) => `[${titleFromFilename(name)}](./${name}): Description pending update`);
45
+ const content = `${["# Memory Index", "", ...entries].join("\n").trimEnd()}\n`;
46
+ await writeFile(indexPath, content, "utf8");
47
+ log.info({ store, entries: entries.length }, "memory index created");
48
+ }
49
+ };
50
+ /**
51
+ * The extraction/maintenance agents have no delete tool — they empty files
52
+ * instead, and the host removes those leftovers here after each run.
53
+ */
54
+ export const sweepEmptyMarkdown = async (dir, log) => {
55
+ let names;
56
+ try {
57
+ names = await readdir(dir);
58
+ }
59
+ catch {
60
+ return;
61
+ }
62
+ for (const name of names) {
63
+ if (!name.endsWith(".md"))
64
+ continue;
65
+ const path = join(dir, name);
66
+ try {
67
+ const info = await stat(path);
68
+ const blank = info.size === 0 || (info.size <= 64 && (await readFile(path, "utf8")).trim() === "");
69
+ if (!blank)
70
+ continue;
71
+ await unlink(path);
72
+ log.info({ path }, "removed emptied memory file");
73
+ }
74
+ catch (error) {
75
+ log.warn({ path, err: error }, "failed to sweep memory file");
76
+ }
77
+ }
78
+ };
79
+ //# sourceMappingURL=layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.js","sourceRoot":"","sources":["../../../src/extensions/memory/layout.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { Logger } from "../../log.ts";
2
+ import { type Runner } from "./extraction.ts";
3
+ import { type MemoryStore } from "./layout.ts";
4
+ export interface MaintenanceThresholds {
5
+ recentDays: number;
6
+ weeklyThresholdMonths: number;
7
+ monthlyThresholdMonths: number;
8
+ }
9
+ export interface MaintenanceDeps {
10
+ side: Runner;
11
+ workspaceRoot: string;
12
+ settings: MaintenanceThresholds;
13
+ log: Logger;
14
+ /** Injectable clock for tests — Sunday triggers the full index rebuild. */
15
+ now?: () => Date;
16
+ }
17
+ /** Names-only listing of the other stores so the maintenance agent can reconcile across them. */
18
+ export declare const buildCrossStoreManifest: (workspaceRoot: string, current: MemoryStore) => Promise<string | null>;
19
+ export declare const maintenanceSystemPrompt: (store: MemoryStore, { workspaceRoot, settings, now }: Pick<MaintenanceDeps, "workspaceRoot" | "settings" | "now">) => Promise<string>;
20
+ /** Daily maintenance pass over one memory store: consolidate, prune, keep indexes in sync. */
21
+ export declare const runMaintenanceTick: (store: MemoryStore, deps: MaintenanceDeps) => Promise<void>;