charness 3.6.0 → 3.7.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 (582) hide show
  1. package/CHANGELOG.md +274 -0
  2. package/DEVELOPMENT.md +31 -5
  3. package/MIGRATION_RENAME_TO_CHARNESS.md +3 -2
  4. package/README.md +84 -782
  5. package/SETUP.md +37 -10
  6. package/agent-plugin/.claude-plugin/plugin.json +7 -0
  7. package/agent-plugin/README.md +35 -0
  8. package/agent-plugin/skills/charness-delegate-claude/SKILL.md +85 -0
  9. package/agent-plugin/skills/charness-delegate-claude/summarize-events.py +90 -0
  10. package/agent-plugin/skills/charness-delegate-opencode/SKILL.md +68 -0
  11. package/agent-plugin/skills/charness-manager/SKILL.md +152 -0
  12. package/dist/adapters/adapterNames.d.ts +6 -0
  13. package/dist/adapters/adapterNames.d.ts.map +1 -1
  14. package/dist/adapters/adapterNames.js +8 -2
  15. package/dist/adapters/adapterNames.js.map +1 -1
  16. package/dist/adapters/claudeCliAdapter.d.ts +8 -0
  17. package/dist/adapters/claudeCliAdapter.d.ts.map +1 -1
  18. package/dist/adapters/claudeCliAdapter.js +42 -5
  19. package/dist/adapters/claudeCliAdapter.js.map +1 -1
  20. package/dist/adapters/claudeJsonStreamAdapter.d.ts +10 -9
  21. package/dist/adapters/claudeJsonStreamAdapter.d.ts.map +1 -1
  22. package/dist/adapters/claudeJsonStreamAdapter.js +53 -55
  23. package/dist/adapters/claudeJsonStreamAdapter.js.map +1 -1
  24. package/dist/adapters/createAdapter.d.ts +8 -0
  25. package/dist/adapters/createAdapter.d.ts.map +1 -1
  26. package/dist/adapters/createAdapter.js +14 -2
  27. package/dist/adapters/createAdapter.js.map +1 -1
  28. package/dist/adapters/openCodeAdapter.d.ts +43 -6
  29. package/dist/adapters/openCodeAdapter.d.ts.map +1 -1
  30. package/dist/adapters/openCodeAdapter.js +95 -6
  31. package/dist/adapters/openCodeAdapter.js.map +1 -1
  32. package/dist/agentLogin/agentLogin.d.ts +1 -1
  33. package/dist/agentLogin/agentLogin.d.ts.map +1 -1
  34. package/dist/apiRetryKick.d.ts +4 -3
  35. package/dist/apiRetryKick.d.ts.map +1 -1
  36. package/dist/apiRetryKick.js +16 -9
  37. package/dist/apiRetryKick.js.map +1 -1
  38. package/dist/bot.d.ts.map +1 -1
  39. package/dist/bot.js +1313 -381
  40. package/dist/bot.js.map +1 -1
  41. package/dist/cli/claudeProfiles.d.ts +11 -6
  42. package/dist/cli/claudeProfiles.d.ts.map +1 -1
  43. package/dist/cli/claudeProfiles.js +50 -22
  44. package/dist/cli/claudeProfiles.js.map +1 -1
  45. package/dist/cli/hot.d.ts +5 -0
  46. package/dist/cli/hot.d.ts.map +1 -1
  47. package/dist/cli/hot.js +71 -25
  48. package/dist/cli/hot.js.map +1 -1
  49. package/dist/cli/tscWatchGuard.d.ts +95 -0
  50. package/dist/cli/tscWatchGuard.d.ts.map +1 -0
  51. package/dist/cli/tscWatchGuard.js +295 -0
  52. package/dist/cli/tscWatchGuard.js.map +1 -0
  53. package/dist/cli.js +12 -1
  54. package/dist/cli.js.map +1 -1
  55. package/dist/connectors/jira/answerSink.d.ts +10 -0
  56. package/dist/connectors/jira/answerSink.d.ts.map +1 -1
  57. package/dist/connectors/jira/answerSink.js +13 -0
  58. package/dist/connectors/jira/answerSink.js.map +1 -1
  59. package/dist/connectors/jira/config.d.ts +2 -0
  60. package/dist/connectors/jira/config.d.ts.map +1 -1
  61. package/dist/connectors/jira/config.js +9 -1
  62. package/dist/connectors/jira/config.js.map +1 -1
  63. package/dist/connectors/jira/connector.d.ts +11 -1
  64. package/dist/connectors/jira/connector.d.ts.map +1 -1
  65. package/dist/connectors/jira/connector.js +13 -1
  66. package/dist/connectors/jira/connector.js.map +1 -1
  67. package/dist/connectors/jira/inbound.d.ts +29 -4
  68. package/dist/connectors/jira/inbound.d.ts.map +1 -1
  69. package/dist/connectors/jira/inbound.js +71 -8
  70. package/dist/connectors/jira/inbound.js.map +1 -1
  71. package/dist/connectors/jira/issueBlocks.d.ts +5 -0
  72. package/dist/connectors/jira/issueBlocks.d.ts.map +1 -1
  73. package/dist/connectors/jira/issueBlocks.js +11 -0
  74. package/dist/connectors/jira/issueBlocks.js.map +1 -1
  75. package/dist/connectors/jira/prompt.d.ts +4 -0
  76. package/dist/connectors/jira/prompt.d.ts.map +1 -1
  77. package/dist/connectors/jira/prompt.js +11 -2
  78. package/dist/connectors/jira/prompt.js.map +1 -1
  79. package/dist/connectors/telegram/bindPicker.d.ts +5 -0
  80. package/dist/connectors/telegram/bindPicker.d.ts.map +1 -1
  81. package/dist/connectors/telegram/bindPicker.js +18 -1
  82. package/dist/connectors/telegram/bindPicker.js.map +1 -1
  83. package/dist/connectors/telegram/bindPickerClaims.d.ts +46 -0
  84. package/dist/connectors/telegram/bindPickerClaims.d.ts.map +1 -0
  85. package/dist/connectors/telegram/bindPickerClaims.js +83 -0
  86. package/dist/connectors/telegram/bindPickerClaims.js.map +1 -0
  87. package/dist/connectors/telegram/bindSweep.d.ts +32 -0
  88. package/dist/connectors/telegram/bindSweep.d.ts.map +1 -0
  89. package/dist/connectors/telegram/bindSweep.js +47 -0
  90. package/dist/connectors/telegram/bindSweep.js.map +1 -0
  91. package/dist/connectors/telegram/bindingWelcome.d.ts +23 -0
  92. package/dist/connectors/telegram/bindingWelcome.d.ts.map +1 -0
  93. package/dist/connectors/telegram/bindingWelcome.js +26 -0
  94. package/dist/connectors/telegram/bindingWelcome.js.map +1 -0
  95. package/dist/connectors/telegram/botApiConnection.d.ts +74 -0
  96. package/dist/connectors/telegram/botApiConnection.d.ts.map +1 -0
  97. package/dist/connectors/telegram/botApiConnection.js +201 -0
  98. package/dist/connectors/telegram/botApiConnection.js.map +1 -0
  99. package/dist/connectors/telegram/commands/botCore.d.ts +8 -2
  100. package/dist/connectors/telegram/commands/botCore.d.ts.map +1 -1
  101. package/dist/connectors/telegram/commands/botSkills.d.ts +21 -0
  102. package/dist/connectors/telegram/commands/botSkills.d.ts.map +1 -0
  103. package/dist/connectors/telegram/commands/botSkills.js +133 -0
  104. package/dist/connectors/telegram/commands/botSkills.js.map +1 -0
  105. package/dist/connectors/telegram/commands/callbackMessage.d.ts +5 -0
  106. package/dist/connectors/telegram/commands/callbackMessage.d.ts.map +1 -1
  107. package/dist/connectors/telegram/commands/callbackMessage.js +9 -0
  108. package/dist/connectors/telegram/commands/callbackMessage.js.map +1 -1
  109. package/dist/connectors/telegram/commands/compaction.d.ts +65 -3
  110. package/dist/connectors/telegram/commands/compaction.d.ts.map +1 -1
  111. package/dist/connectors/telegram/commands/compaction.js +512 -94
  112. package/dist/connectors/telegram/commands/compaction.js.map +1 -1
  113. package/dist/connectors/telegram/commands/displayModes.d.ts +1 -1
  114. package/dist/connectors/telegram/commands/displayModes.d.ts.map +1 -1
  115. package/dist/connectors/telegram/commands/displayModes.js +6 -18
  116. package/dist/connectors/telegram/commands/displayModes.js.map +1 -1
  117. package/dist/connectors/telegram/commands/fallbackChain.js +5 -5
  118. package/dist/connectors/telegram/commands/fallbackChain.js.map +1 -1
  119. package/dist/connectors/telegram/commands/reminders.d.ts +1 -1
  120. package/dist/connectors/telegram/commands/reminders.d.ts.map +1 -1
  121. package/dist/connectors/telegram/commands/reminders.js +4 -15
  122. package/dist/connectors/telegram/commands/reminders.js.map +1 -1
  123. package/dist/connectors/telegram/commands/selfUpdate.d.ts.map +1 -1
  124. package/dist/connectors/telegram/commands/selfUpdate.js +1 -11
  125. package/dist/connectors/telegram/commands/selfUpdate.js.map +1 -1
  126. package/dist/connectors/telegram/commands/taskAgents.d.ts +22 -0
  127. package/dist/connectors/telegram/commands/taskAgents.d.ts.map +1 -0
  128. package/dist/connectors/telegram/commands/taskAgents.js +104 -0
  129. package/dist/connectors/telegram/commands/taskAgents.js.map +1 -0
  130. package/dist/connectors/telegram/commands/todo.d.ts +82 -0
  131. package/dist/connectors/telegram/commands/todo.d.ts.map +1 -0
  132. package/dist/connectors/telegram/commands/todo.js +384 -0
  133. package/dist/connectors/telegram/commands/todo.js.map +1 -0
  134. package/dist/connectors/telegram/commands/topicCommand.d.ts +6 -2
  135. package/dist/connectors/telegram/commands/topicCommand.d.ts.map +1 -1
  136. package/dist/connectors/telegram/commands/topicCommand.js +6 -9
  137. package/dist/connectors/telegram/commands/topicCommand.js.map +1 -1
  138. package/dist/connectors/telegram/openBindMessages.d.ts +45 -0
  139. package/dist/connectors/telegram/openBindMessages.d.ts.map +1 -0
  140. package/dist/connectors/telegram/openBindMessages.js +67 -0
  141. package/dist/connectors/telegram/openBindMessages.js.map +1 -0
  142. package/dist/connectors/telegram/outputFlushPlan.d.ts +49 -0
  143. package/dist/connectors/telegram/outputFlushPlan.d.ts.map +1 -1
  144. package/dist/connectors/telegram/outputFlushPlan.js +46 -0
  145. package/dist/connectors/telegram/outputFlushPlan.js.map +1 -1
  146. package/dist/connectors/telegram/pendingTopicName.d.ts +26 -0
  147. package/dist/connectors/telegram/pendingTopicName.d.ts.map +1 -0
  148. package/dist/connectors/telegram/pendingTopicName.js +27 -0
  149. package/dist/connectors/telegram/pendingTopicName.js.map +1 -0
  150. package/dist/connectors/test/connector.d.ts.map +1 -1
  151. package/dist/connectors/test/connector.js +6 -1
  152. package/dist/connectors/test/connector.js.map +1 -1
  153. package/dist/i18n/de.d.ts.map +1 -1
  154. package/dist/i18n/de.js +90 -7
  155. package/dist/i18n/de.js.map +1 -1
  156. package/dist/i18n/en.d.ts.map +1 -1
  157. package/dist/i18n/en.js +90 -7
  158. package/dist/i18n/en.js.map +1 -1
  159. package/dist/i18n/es.d.ts.map +1 -1
  160. package/dist/i18n/es.js +90 -7
  161. package/dist/i18n/es.js.map +1 -1
  162. package/dist/i18n/fr.d.ts.map +1 -1
  163. package/dist/i18n/fr.js +90 -7
  164. package/dist/i18n/fr.js.map +1 -1
  165. package/dist/i18n/hi.d.ts.map +1 -1
  166. package/dist/i18n/hi.js +90 -7
  167. package/dist/i18n/hi.js.map +1 -1
  168. package/dist/i18n/ja.d.ts.map +1 -1
  169. package/dist/i18n/ja.js +90 -7
  170. package/dist/i18n/ja.js.map +1 -1
  171. package/dist/i18n/ka.d.ts.map +1 -1
  172. package/dist/i18n/ka.js +90 -7
  173. package/dist/i18n/ka.js.map +1 -1
  174. package/dist/i18n/pt.d.ts.map +1 -1
  175. package/dist/i18n/pt.js +90 -7
  176. package/dist/i18n/pt.js.map +1 -1
  177. package/dist/i18n/ru.d.ts.map +1 -1
  178. package/dist/i18n/ru.js +90 -7
  179. package/dist/i18n/ru.js.map +1 -1
  180. package/dist/i18n/uk.d.ts.map +1 -1
  181. package/dist/i18n/uk.js +90 -7
  182. package/dist/i18n/uk.js.map +1 -1
  183. package/dist/i18n/uz.d.ts.map +1 -1
  184. package/dist/i18n/uz.js +90 -7
  185. package/dist/i18n/uz.js.map +1 -1
  186. package/dist/i18n/zh.d.ts.map +1 -1
  187. package/dist/i18n/zh.js +90 -7
  188. package/dist/i18n/zh.js.map +1 -1
  189. package/dist/i18n.d.ts +1 -1
  190. package/dist/i18n.js +1 -1
  191. package/dist/installManager.d.ts +13 -0
  192. package/dist/installManager.d.ts.map +1 -1
  193. package/dist/installManager.js +38 -4
  194. package/dist/installManager.js.map +1 -1
  195. package/dist/instanceSettings.d.ts +40 -1
  196. package/dist/instanceSettings.d.ts.map +1 -1
  197. package/dist/instanceSettings.js +105 -26
  198. package/dist/instanceSettings.js.map +1 -1
  199. package/dist/openCodeQuestionFlow.d.ts +30 -0
  200. package/dist/openCodeQuestionFlow.d.ts.map +1 -1
  201. package/dist/openCodeQuestionFlow.js +43 -0
  202. package/dist/openCodeQuestionFlow.js.map +1 -1
  203. package/dist/postToSession.d.ts +20 -5
  204. package/dist/postToSession.d.ts.map +1 -1
  205. package/dist/postToSession.js +38 -7
  206. package/dist/postToSession.js.map +1 -1
  207. package/dist/remoteRun/cliArgs.d.ts +73 -0
  208. package/dist/remoteRun/cliArgs.d.ts.map +1 -0
  209. package/dist/remoteRun/cliArgs.js +197 -0
  210. package/dist/remoteRun/cliArgs.js.map +1 -0
  211. package/dist/remoteRun/commands.d.ts +56 -0
  212. package/dist/remoteRun/commands.d.ts.map +1 -0
  213. package/dist/remoteRun/commands.js +306 -0
  214. package/dist/remoteRun/commands.js.map +1 -0
  215. package/dist/remoteRun/depsPlan.d.ts +16 -0
  216. package/dist/remoteRun/depsPlan.d.ts.map +1 -0
  217. package/dist/remoteRun/depsPlan.js +82 -0
  218. package/dist/remoteRun/depsPlan.js.map +1 -0
  219. package/dist/remoteRun/exitCodes.d.ts +34 -0
  220. package/dist/remoteRun/exitCodes.d.ts.map +1 -0
  221. package/dist/remoteRun/exitCodes.js +38 -0
  222. package/dist/remoteRun/exitCodes.js.map +1 -0
  223. package/dist/remoteRun/foreground.d.ts +29 -0
  224. package/dist/remoteRun/foreground.d.ts.map +1 -0
  225. package/dist/remoteRun/foreground.js +159 -0
  226. package/dist/remoteRun/foreground.js.map +1 -0
  227. package/dist/remoteRun/interrupts.d.ts +17 -0
  228. package/dist/remoteRun/interrupts.d.ts.map +1 -0
  229. package/dist/remoteRun/interrupts.js +41 -0
  230. package/dist/remoteRun/interrupts.js.map +1 -0
  231. package/dist/remoteRun/jobFiles.d.ts +31 -0
  232. package/dist/remoteRun/jobFiles.d.ts.map +1 -0
  233. package/dist/remoteRun/jobFiles.js +84 -0
  234. package/dist/remoteRun/jobFiles.js.map +1 -0
  235. package/dist/remoteRun/jobFormat.d.ts +16 -0
  236. package/dist/remoteRun/jobFormat.d.ts.map +1 -0
  237. package/dist/remoteRun/jobFormat.js +130 -0
  238. package/dist/remoteRun/jobFormat.js.map +1 -0
  239. package/dist/remoteRun/jobId.d.ts +15 -0
  240. package/dist/remoteRun/jobId.d.ts.map +1 -0
  241. package/dist/remoteRun/jobId.js +85 -0
  242. package/dist/remoteRun/jobId.js.map +1 -0
  243. package/dist/remoteRun/jobMeta.d.ts +18 -0
  244. package/dist/remoteRun/jobMeta.d.ts.map +1 -0
  245. package/dist/remoteRun/jobMeta.js +33 -0
  246. package/dist/remoteRun/jobMeta.js.map +1 -0
  247. package/dist/remoteRun/jobQuery.d.ts +12 -0
  248. package/dist/remoteRun/jobQuery.d.ts.map +1 -0
  249. package/dist/remoteRun/jobQuery.js +22 -0
  250. package/dist/remoteRun/jobQuery.js.map +1 -0
  251. package/dist/remoteRun/jobRecords.d.ts +22 -0
  252. package/dist/remoteRun/jobRecords.d.ts.map +1 -0
  253. package/dist/remoteRun/jobRecords.js +145 -0
  254. package/dist/remoteRun/jobRecords.js.map +1 -0
  255. package/dist/remoteRun/jobState.d.ts +62 -0
  256. package/dist/remoteRun/jobState.d.ts.map +1 -0
  257. package/dist/remoteRun/jobState.js +132 -0
  258. package/dist/remoteRun/jobState.js.map +1 -0
  259. package/dist/remoteRun/leaseTiming.d.ts +18 -0
  260. package/dist/remoteRun/leaseTiming.d.ts.map +1 -0
  261. package/dist/remoteRun/leaseTiming.js +43 -0
  262. package/dist/remoteRun/leaseTiming.js.map +1 -0
  263. package/dist/remoteRun/output.d.ts +35 -0
  264. package/dist/remoteRun/output.d.ts.map +1 -0
  265. package/dist/remoteRun/output.js +82 -0
  266. package/dist/remoteRun/output.js.map +1 -0
  267. package/dist/remoteRun/pathPatterns.d.ts +33 -0
  268. package/dist/remoteRun/pathPatterns.d.ts.map +1 -0
  269. package/dist/remoteRun/pathPatterns.js +115 -0
  270. package/dist/remoteRun/pathPatterns.js.map +1 -0
  271. package/dist/remoteRun/probe.d.ts +56 -0
  272. package/dist/remoteRun/probe.d.ts.map +1 -0
  273. package/dist/remoteRun/probe.js +123 -0
  274. package/dist/remoteRun/probe.js.map +1 -0
  275. package/dist/remoteRun/project.d.ts +26 -0
  276. package/dist/remoteRun/project.d.ts.map +1 -0
  277. package/dist/remoteRun/project.js +159 -0
  278. package/dist/remoteRun/project.js.map +1 -0
  279. package/dist/remoteRun/projectConfig.d.ts +38 -0
  280. package/dist/remoteRun/projectConfig.d.ts.map +1 -0
  281. package/dist/remoteRun/projectConfig.js +87 -0
  282. package/dist/remoteRun/projectConfig.js.map +1 -0
  283. package/dist/remoteRun/remoteRunCli.d.ts +15 -0
  284. package/dist/remoteRun/remoteRunCli.d.ts.map +1 -0
  285. package/dist/remoteRun/remoteRunCli.js +144 -0
  286. package/dist/remoteRun/remoteRunCli.js.map +1 -0
  287. package/dist/remoteRun/remoteRunError.d.ts +14 -0
  288. package/dist/remoteRun/remoteRunError.d.ts.map +1 -0
  289. package/dist/remoteRun/remoteRunError.js +28 -0
  290. package/dist/remoteRun/remoteRunError.js.map +1 -0
  291. package/dist/remoteRun/rsync.d.ts +17 -0
  292. package/dist/remoteRun/rsync.d.ts.map +1 -0
  293. package/dist/remoteRun/rsync.js +39 -0
  294. package/dist/remoteRun/rsync.js.map +1 -0
  295. package/dist/remoteRun/runnerClient.d.ts +50 -0
  296. package/dist/remoteRun/runnerClient.d.ts.map +1 -0
  297. package/dist/remoteRun/runnerClient.js +139 -0
  298. package/dist/remoteRun/runnerClient.js.map +1 -0
  299. package/dist/remoteRun/runners.d.ts +57 -0
  300. package/dist/remoteRun/runners.d.ts.map +1 -0
  301. package/dist/remoteRun/runners.js +181 -0
  302. package/dist/remoteRun/runners.js.map +1 -0
  303. package/dist/remoteRun/runnersConfig.d.ts +44 -0
  304. package/dist/remoteRun/runnersConfig.d.ts.map +1 -0
  305. package/dist/remoteRun/runnersConfig.js +107 -0
  306. package/dist/remoteRun/runnersConfig.js.map +1 -0
  307. package/dist/remoteRun/safeCopy.d.ts +31 -0
  308. package/dist/remoteRun/safeCopy.d.ts.map +1 -0
  309. package/dist/remoteRun/safeCopy.js +137 -0
  310. package/dist/remoteRun/safeCopy.js.map +1 -0
  311. package/dist/remoteRun/sendPlan.d.ts +67 -0
  312. package/dist/remoteRun/sendPlan.d.ts.map +1 -0
  313. package/dist/remoteRun/sendPlan.js +139 -0
  314. package/dist/remoteRun/sendPlan.js.map +1 -0
  315. package/dist/remoteRun/ssh.d.ts +62 -0
  316. package/dist/remoteRun/ssh.d.ts.map +1 -0
  317. package/dist/remoteRun/ssh.js +202 -0
  318. package/dist/remoteRun/ssh.js.map +1 -0
  319. package/dist/remoteRun/submit.d.ts +29 -0
  320. package/dist/remoteRun/submit.d.ts.map +1 -0
  321. package/dist/remoteRun/submit.js +142 -0
  322. package/dist/remoteRun/submit.js.map +1 -0
  323. package/dist/requests/answerRequest.d.ts +5 -0
  324. package/dist/requests/answerRequest.d.ts.map +1 -1
  325. package/dist/requests/answerRequest.js +16 -1
  326. package/dist/requests/answerRequest.js.map +1 -1
  327. package/dist/requests/requestLedger.d.ts +13 -0
  328. package/dist/requests/requestLedger.d.ts.map +1 -1
  329. package/dist/requests/requestLedger.js +9 -0
  330. package/dist/requests/requestLedger.js.map +1 -1
  331. package/dist/requests/topicRequestSettle.d.ts +30 -0
  332. package/dist/requests/topicRequestSettle.d.ts.map +1 -0
  333. package/dist/requests/topicRequestSettle.js +23 -0
  334. package/dist/requests/topicRequestSettle.js.map +1 -0
  335. package/dist/requests/wakeUpEngine.d.ts +4 -0
  336. package/dist/requests/wakeUpEngine.d.ts.map +1 -1
  337. package/dist/requests/wakeUpEngine.js +5 -1
  338. package/dist/requests/wakeUpEngine.js.map +1 -1
  339. package/dist/scheduler/delivery.d.ts +2 -0
  340. package/dist/scheduler/delivery.d.ts.map +1 -1
  341. package/dist/scheduler/delivery.js +8 -4
  342. package/dist/scheduler/delivery.js.map +1 -1
  343. package/dist/scheduler/mcpSurface.d.ts +59 -10
  344. package/dist/scheduler/mcpSurface.d.ts.map +1 -1
  345. package/dist/scheduler/mcpSurface.js +276 -79
  346. package/dist/scheduler/mcpSurface.js.map +1 -1
  347. package/dist/scheduler/recurrence.d.ts +5 -0
  348. package/dist/scheduler/recurrence.d.ts.map +1 -1
  349. package/dist/scheduler/recurrence.js +12 -2
  350. package/dist/scheduler/recurrence.js.map +1 -1
  351. package/dist/scheduler/strictToolInput.d.ts +45 -0
  352. package/dist/scheduler/strictToolInput.d.ts.map +1 -0
  353. package/dist/scheduler/strictToolInput.js +155 -0
  354. package/dist/scheduler/strictToolInput.js.map +1 -0
  355. package/dist/scheduler/types.d.ts +5 -0
  356. package/dist/scheduler/types.d.ts.map +1 -1
  357. package/dist/scheduler/workerWatch.d.ts +23 -0
  358. package/dist/scheduler/workerWatch.d.ts.map +1 -0
  359. package/dist/scheduler/workerWatch.js +26 -0
  360. package/dist/scheduler/workerWatch.js.map +1 -0
  361. package/dist/selfUpdate/emittedSource.d.ts +11 -0
  362. package/dist/selfUpdate/emittedSource.d.ts.map +1 -0
  363. package/dist/selfUpdate/emittedSource.js +24 -0
  364. package/dist/selfUpdate/emittedSource.js.map +1 -0
  365. package/dist/selfUpdate/gitSource.d.ts +0 -6
  366. package/dist/selfUpdate/gitSource.d.ts.map +1 -1
  367. package/dist/selfUpdate/gitSource.js +2 -18
  368. package/dist/selfUpdate/gitSource.js.map +1 -1
  369. package/dist/selfUpdate/updatePending.d.ts +1 -1
  370. package/dist/sendErrorClassifier.d.ts +10 -0
  371. package/dist/sendErrorClassifier.d.ts.map +1 -1
  372. package/dist/sendErrorClassifier.js +22 -0
  373. package/dist/sendErrorClassifier.js.map +1 -1
  374. package/dist/state.d.ts +78 -7
  375. package/dist/state.d.ts.map +1 -1
  376. package/dist/state.js +125 -8
  377. package/dist/state.js.map +1 -1
  378. package/dist/stateFile.d.ts +9 -0
  379. package/dist/stateFile.d.ts.map +1 -0
  380. package/dist/stateFile.js +57 -0
  381. package/dist/stateFile.js.map +1 -0
  382. package/dist/stt/sttInstall.d.ts +7 -3
  383. package/dist/stt/sttInstall.d.ts.map +1 -1
  384. package/dist/stt/sttInstall.js +8 -4
  385. package/dist/stt/sttInstall.js.map +1 -1
  386. package/dist/stt/sttSettings.d.ts +2 -1
  387. package/dist/stt/sttSettings.d.ts.map +1 -1
  388. package/dist/stt/sttSettings.js +3 -2
  389. package/dist/stt/sttSettings.js.map +1 -1
  390. package/dist/stt/transcribeChain.js +2 -0
  391. package/dist/stt/transcribeChain.js.map +1 -1
  392. package/dist/testTimings.d.ts +13 -3
  393. package/dist/testTimings.d.ts.map +1 -1
  394. package/dist/testTimings.js +26 -2
  395. package/dist/testTimings.js.map +1 -1
  396. package/dist/todos/board.d.ts +83 -0
  397. package/dist/todos/board.d.ts.map +1 -0
  398. package/dist/todos/board.js +227 -0
  399. package/dist/todos/board.js.map +1 -0
  400. package/dist/todos/format.d.ts +33 -0
  401. package/dist/todos/format.d.ts.map +1 -0
  402. package/dist/todos/format.js +90 -0
  403. package/dist/todos/format.js.map +1 -0
  404. package/dist/todos/merge.d.ts +46 -0
  405. package/dist/todos/merge.d.ts.map +1 -0
  406. package/dist/todos/merge.js +137 -0
  407. package/dist/todos/merge.js.map +1 -0
  408. package/dist/todos/midTurn.d.ts +75 -0
  409. package/dist/todos/midTurn.d.ts.map +1 -0
  410. package/dist/todos/midTurn.js +214 -0
  411. package/dist/todos/midTurn.js.map +1 -0
  412. package/dist/todos/nag.d.ts +85 -0
  413. package/dist/todos/nag.d.ts.map +1 -0
  414. package/dist/todos/nag.js +103 -0
  415. package/dist/todos/nag.js.map +1 -0
  416. package/dist/todos/order.d.ts +25 -0
  417. package/dist/todos/order.d.ts.map +1 -0
  418. package/dist/todos/order.js +61 -0
  419. package/dist/todos/order.js.map +1 -0
  420. package/dist/todos/projects.d.ts +102 -0
  421. package/dist/todos/projects.d.ts.map +1 -0
  422. package/dist/todos/projects.js +342 -0
  423. package/dist/todos/projects.js.map +1 -0
  424. package/dist/todos/registry.d.ts +64 -0
  425. package/dist/todos/registry.d.ts.map +1 -0
  426. package/dist/todos/registry.js +116 -0
  427. package/dist/todos/registry.js.map +1 -0
  428. package/dist/todos/reminderEngine.d.ts +78 -0
  429. package/dist/todos/reminderEngine.d.ts.map +1 -0
  430. package/dist/todos/reminderEngine.js +162 -0
  431. package/dist/todos/reminderEngine.js.map +1 -0
  432. package/dist/todos/store.d.ts +34 -0
  433. package/dist/todos/store.d.ts.map +1 -0
  434. package/dist/todos/store.js +208 -0
  435. package/dist/todos/store.js.map +1 -0
  436. package/dist/todos/tools.d.ts +26 -0
  437. package/dist/todos/tools.d.ts.map +1 -0
  438. package/dist/todos/tools.js +25 -0
  439. package/dist/todos/tools.js.map +1 -0
  440. package/dist/todos/types.d.ts +85 -0
  441. package/dist/todos/types.d.ts.map +1 -0
  442. package/dist/todos/types.js +30 -0
  443. package/dist/todos/types.js.map +1 -0
  444. package/dist/trackers/taskAgentLimit.d.ts +58 -0
  445. package/dist/trackers/taskAgentLimit.d.ts.map +1 -0
  446. package/dist/trackers/taskAgentLimit.js +62 -0
  447. package/dist/trackers/taskAgentLimit.js.map +1 -0
  448. package/dist/trackers/taskAgentSlots.d.ts +109 -0
  449. package/dist/trackers/taskAgentSlots.d.ts.map +1 -0
  450. package/dist/trackers/taskAgentSlots.js +227 -0
  451. package/dist/trackers/taskAgentSlots.js.map +1 -0
  452. package/dist/trackers/types.d.ts +14 -0
  453. package/dist/trackers/types.d.ts.map +1 -0
  454. package/dist/trackers/types.js +3 -0
  455. package/dist/trackers/types.js.map +1 -0
  456. package/dist/types.d.ts +80 -4
  457. package/dist/types.d.ts.map +1 -1
  458. package/dist/utils/adoptReplayGate.d.ts +16 -0
  459. package/dist/utils/adoptReplayGate.d.ts.map +1 -0
  460. package/dist/utils/adoptReplayGate.js +35 -0
  461. package/dist/utils/adoptReplayGate.js.map +1 -0
  462. package/dist/utils/agentPlugin.d.ts +113 -0
  463. package/dist/utils/agentPlugin.d.ts.map +1 -0
  464. package/dist/utils/agentPlugin.js +192 -0
  465. package/dist/utils/agentPlugin.js.map +1 -0
  466. package/dist/utils/autoContinueOnLimit.d.ts +7 -4
  467. package/dist/utils/autoContinueOnLimit.d.ts.map +1 -1
  468. package/dist/utils/autoContinueOnLimit.js +8 -5
  469. package/dist/utils/autoContinueOnLimit.js.map +1 -1
  470. package/dist/utils/botSkills.d.ts +62 -0
  471. package/dist/utils/botSkills.d.ts.map +1 -0
  472. package/dist/utils/botSkills.js +53 -0
  473. package/dist/utils/botSkills.js.map +1 -0
  474. package/dist/utils/botSkillsSetting.d.ts +7 -0
  475. package/dist/utils/botSkillsSetting.d.ts.map +1 -0
  476. package/dist/utils/botSkillsSetting.js +9 -0
  477. package/dist/utils/botSkillsSetting.js.map +1 -0
  478. package/dist/utils/claudeCodeVersion.d.ts +7 -0
  479. package/dist/utils/claudeCodeVersion.d.ts.map +1 -1
  480. package/dist/utils/claudeCodeVersion.js +14 -1
  481. package/dist/utils/claudeCodeVersion.js.map +1 -1
  482. package/dist/utils/claudeCompactHook.d.ts +33 -15
  483. package/dist/utils/claudeCompactHook.d.ts.map +1 -1
  484. package/dist/utils/claudeCompactHook.js +36 -17
  485. package/dist/utils/claudeCompactHook.js.map +1 -1
  486. package/dist/utils/claudeCompactSummary.d.ts +15 -0
  487. package/dist/utils/claudeCompactSummary.d.ts.map +1 -0
  488. package/dist/utils/claudeCompactSummary.js +96 -0
  489. package/dist/utils/claudeCompactSummary.js.map +1 -0
  490. package/dist/utils/claudeLimitSwitch.d.ts +11 -9
  491. package/dist/utils/claudeLimitSwitch.d.ts.map +1 -1
  492. package/dist/utils/claudeLimitSwitch.js +18 -16
  493. package/dist/utils/claudeLimitSwitch.js.map +1 -1
  494. package/dist/utils/claudeProfiles.d.ts +5 -0
  495. package/dist/utils/claudeProfiles.d.ts.map +1 -1
  496. package/dist/utils/claudeProfiles.js +14 -0
  497. package/dist/utils/claudeProfiles.js.map +1 -1
  498. package/dist/utils/claudeSessionTitle.d.ts +2 -1
  499. package/dist/utils/claudeSessionTitle.d.ts.map +1 -1
  500. package/dist/utils/claudeSessionTitle.js +14 -14
  501. package/dist/utils/claudeSessionTitle.js.map +1 -1
  502. package/dist/utils/claudeUsage.d.ts +95 -15
  503. package/dist/utils/claudeUsage.d.ts.map +1 -1
  504. package/dist/utils/claudeUsage.js +241 -41
  505. package/dist/utils/claudeUsage.js.map +1 -1
  506. package/dist/utils/claudeUsageRefresher.d.ts +10 -0
  507. package/dist/utils/claudeUsageRefresher.d.ts.map +1 -1
  508. package/dist/utils/claudeUsageRefresher.js +11 -0
  509. package/dist/utils/claudeUsageRefresher.js.map +1 -1
  510. package/dist/utils/claudeUserEntry.d.ts +50 -0
  511. package/dist/utils/claudeUserEntry.d.ts.map +1 -0
  512. package/dist/utils/claudeUserEntry.js +120 -0
  513. package/dist/utils/claudeUserEntry.js.map +1 -0
  514. package/dist/utils/clearThreadOutputQueues.d.ts +4 -3
  515. package/dist/utils/clearThreadOutputQueues.d.ts.map +1 -1
  516. package/dist/utils/clearThreadOutputQueues.js +1 -1
  517. package/dist/utils/clearThreadOutputQueues.js.map +1 -1
  518. package/dist/utils/compactOnIdle.d.ts +33 -13
  519. package/dist/utils/compactOnIdle.d.ts.map +1 -1
  520. package/dist/utils/compactOnIdle.js +35 -15
  521. package/dist/utils/compactOnIdle.js.map +1 -1
  522. package/dist/utils/fallbackBridge.d.ts +5 -0
  523. package/dist/utils/fallbackBridge.d.ts.map +1 -1
  524. package/dist/utils/fallbackBridge.js +19 -3
  525. package/dist/utils/fallbackBridge.js.map +1 -1
  526. package/dist/utils/fallbackChain.d.ts +9 -3
  527. package/dist/utils/fallbackChain.d.ts.map +1 -1
  528. package/dist/utils/fallbackChain.js +21 -3
  529. package/dist/utils/fallbackChain.js.map +1 -1
  530. package/dist/utils/fileSendPlan.d.ts +6 -0
  531. package/dist/utils/fileSendPlan.d.ts.map +1 -1
  532. package/dist/utils/fileSendPlan.js +11 -0
  533. package/dist/utils/fileSendPlan.js.map +1 -1
  534. package/dist/utils/fileSendService.d.ts +7 -1
  535. package/dist/utils/fileSendService.d.ts.map +1 -1
  536. package/dist/utils/fileSendService.js +6 -2
  537. package/dist/utils/fileSendService.js.map +1 -1
  538. package/dist/utils/groupFinalizePlan.d.ts +8 -10
  539. package/dist/utils/groupFinalizePlan.d.ts.map +1 -1
  540. package/dist/utils/groupFinalizePlan.js +8 -12
  541. package/dist/utils/groupFinalizePlan.js.map +1 -1
  542. package/dist/utils/jsonStreamHost.d.ts +13 -0
  543. package/dist/utils/jsonStreamHost.d.ts.map +1 -1
  544. package/dist/utils/jsonStreamHost.js +13 -0
  545. package/dist/utils/jsonStreamHost.js.map +1 -1
  546. package/dist/utils/messageSendService.d.ts +5 -3
  547. package/dist/utils/messageSendService.d.ts.map +1 -1
  548. package/dist/utils/messageSendService.js +12 -5
  549. package/dist/utils/messageSendService.js.map +1 -1
  550. package/dist/utils/openCodeCompactPlugin.d.ts +39 -14
  551. package/dist/utils/openCodeCompactPlugin.d.ts.map +1 -1
  552. package/dist/utils/openCodeCompactPlugin.js +106 -38
  553. package/dist/utils/openCodeCompactPlugin.js.map +1 -1
  554. package/dist/utils/promptDelivery.d.ts +29 -12
  555. package/dist/utils/promptDelivery.d.ts.map +1 -1
  556. package/dist/utils/promptDelivery.js +13 -5
  557. package/dist/utils/promptDelivery.js.map +1 -1
  558. package/dist/utils/sentKindsSummary.d.ts +10 -0
  559. package/dist/utils/sentKindsSummary.d.ts.map +1 -0
  560. package/dist/utils/sentKindsSummary.js +18 -0
  561. package/dist/utils/sentKindsSummary.js.map +1 -0
  562. package/dist/utils/telegramError.d.ts +6 -0
  563. package/dist/utils/telegramError.d.ts.map +1 -1
  564. package/dist/utils/telegramError.js +12 -0
  565. package/dist/utils/telegramError.js.map +1 -1
  566. package/dist/utils/topicView.d.ts +1 -1
  567. package/dist/utils/topicView.js +1 -1
  568. package/dist/utils/transcribeAudio.d.ts +10 -0
  569. package/dist/utils/transcribeAudio.d.ts.map +1 -1
  570. package/dist/utils/transcribeAudio.js +22 -3
  571. package/dist/utils/transcribeAudio.js.map +1 -1
  572. package/dist/utils/transcriptErrorTime.d.ts +8 -0
  573. package/dist/utils/transcriptErrorTime.d.ts.map +1 -0
  574. package/dist/utils/transcriptErrorTime.js +56 -0
  575. package/dist/utils/transcriptErrorTime.js.map +1 -0
  576. package/dist/utils/wedgeRecovery.d.ts +2 -0
  577. package/dist/utils/wedgeRecovery.d.ts.map +1 -1
  578. package/dist/utils/wedgeRecovery.js +1 -1
  579. package/dist/utils/wedgeRecovery.js.map +1 -1
  580. package/package.json +11 -3
  581. package/remoteRun/runner.sh +1242 -0
  582. package/stt/gigaam_sidecar.py +555 -50
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.todoReadScopes = exports.todoHistoryMaxItems = void 0;
4
+ exports.createTodoRegistry = createTodoRegistry;
5
+ const sessionKey_1 = require("../sessionKey");
6
+ const format_1 = require("./format");
7
+ const merge_1 = require("./merge");
8
+ const nag_1 = require("./nag");
9
+ const order_1 = require("./order");
10
+ /**
11
+ * @description The todo registry's agent-facing service: what `todo_update` and `todo_read` do and answer, and the
12
+ * hint a `final` answer gets while the list still shows work in progress (D8). Platform-neutral — a Telegram topic
13
+ * and a Jira issue publish alike; the MCP surface only routes the conversation its token names here.
14
+ */
15
+ /** The most closed items `todo_read`'s history returns (D5). */
16
+ exports.todoHistoryMaxItems = 50;
17
+ /** What `todo_read` reads: the conversation's own list, or its project's whole board. */
18
+ exports.todoReadScopes = ['own', 'project'];
19
+ /** @description The opening line of a `todo_update` result: what the call did. */
20
+ function formatUpdateSummary(isChanged, createdIds) {
21
+ if (!isChanged)
22
+ return 'Noted: your list is still accurate.';
23
+ return createdIds.length === 0 ? 'Saved.' : `Saved. New ${createdIds.length === 1 ? 'item' : 'items'}: ${createdIds.join(', ')}.`;
24
+ }
25
+ function createTodoRegistry(deps) {
26
+ const { store, getNowMs } = deps;
27
+ /** Busy time polled since the conversation's last turn end, not stored yet (a write per poll would be wasted). */
28
+ const unsavedWorkMs = new Map();
29
+ /** The conversation's reminder bookkeeping with the unsaved work folded in. */
30
+ function getCurrentNag(key) {
31
+ const nag = store.getTopic(key).nag ?? (0, nag_1.createTodoNagState)();
32
+ return (0, nag_1.getTodoNagStateWithWork)(nag, unsavedWorkMs.get((0, sessionKey_1.keyToString)(key)) ?? 0);
33
+ }
34
+ /** Store `nag` (the unsaved work is in it now). */
35
+ function saveNag(key, nag) {
36
+ unsavedWorkMs.delete((0, sessionKey_1.keyToString)(key));
37
+ store.saveTopic(key, { ...store.getTopic(key), nag });
38
+ }
39
+ return {
40
+ updateTodos(key, args) {
41
+ const nowMs = getNowMs();
42
+ const result = (0, merge_1.applyTodoUpdate)(store.getTopic(key), args, nowMs);
43
+ if (!result.ok)
44
+ return { ok: false, error: `Nothing was saved:\n${result.errors.map((error) => `• ${error}`).join('\n')}` };
45
+ // Any call says the list is accurate: the reminder's clock waits for the next turn end (D10).
46
+ unsavedWorkMs.delete((0, sessionKey_1.keyToString)(key));
47
+ const saved = store.saveTopic(key, { ...result.file, nag: (0, nag_1.createTodoNagState)() });
48
+ return { ok: true, message: `${formatUpdateSummary(result.isChanged, result.createdIds)}\n\n${(0, format_1.formatOwnTodoList)(saved.items, nowMs)}` };
49
+ },
50
+ readTodos(key, args) {
51
+ const topic = store.getTopic(key);
52
+ const ownList = (0, format_1.formatOwnTodoList)(topic.items, getNowMs());
53
+ if (args.includeHistory !== true)
54
+ return { ok: true, message: ownList };
55
+ const liveClosed = (0, order_1.getClosedTodoItems)(topic.items);
56
+ const archived = liveClosed.length >= exports.todoHistoryMaxItems ? [] : store.readArchivedItems(key, exports.todoHistoryMaxItems - liveClosed.length);
57
+ return { ok: true, message: `${ownList}\n\n${(0, format_1.formatTodoHistory)([...liveClosed, ...archived].slice(0, exports.todoHistoryMaxItems))}` };
58
+ },
59
+ getFinalAnswerNote(key, requestCreatedAt) {
60
+ const topic = store.getTopic(key);
61
+ if ((topic.lastUpdateAt ?? 0) >= requestCreatedAt)
62
+ return null;
63
+ const inWork = (0, order_1.getInWorkTodoItems)(topic.items);
64
+ if (inWork.length === 0)
65
+ return null;
66
+ const titles = inWork.map((item) => `${item.id} «${item.title}»`).join(', ');
67
+ return `Your published todo list still shows in work: ${titles}. If that changed, record it with todo_update (done, dropped or queued) now.`;
68
+ },
69
+ getTopic: (key) => store.getTopic(key),
70
+ getStore: () => store,
71
+ addTurnWork(key, elapsedMs) {
72
+ // Before the clock starts nothing counts (the turn the update was made in included).
73
+ if (store.getTopic(key).nag?.clockStartedAt === undefined || elapsedMs <= 0)
74
+ return;
75
+ const conversationKey = (0, sessionKey_1.keyToString)(key);
76
+ unsavedWorkMs.set(conversationKey, (unsavedWorkMs.get(conversationKey) ?? 0) + elapsedMs);
77
+ },
78
+ noteTurnEnd(key, nowMs) {
79
+ const nag = (0, nag_1.getTodoNagStateAtTurnEnd)(getCurrentNag(key), nowMs);
80
+ unsavedWorkMs.delete((0, sessionKey_1.keyToString)(key));
81
+ store.saveTopic(key, { ...store.getTopic(key), nag, lastTurnEndAt: nowMs });
82
+ },
83
+ takePromptReminder(key, intervalMs, nowMs) {
84
+ const nag = getCurrentNag(key);
85
+ if (!(0, nag_1.decidePromptTodoReminder)(nag, intervalMs).shouldRemind)
86
+ return null;
87
+ saveNag(key, (0, nag_1.getTodoNagStateAfterReminder)(nag, nowMs));
88
+ return (0, nag_1.buildTodoReminderText)(store.getTopic(key).lastUpdateAt, nowMs);
89
+ },
90
+ decideStandaloneReminder(key, intervalMs, gate, nowMs) {
91
+ const nag = getCurrentNag(key);
92
+ return {
93
+ ...(0, nag_1.decideStandaloneTodoReminder)(nag, intervalMs, gate),
94
+ text: (0, nag_1.buildTodoReminderText)(store.getTopic(key).lastUpdateAt, nowMs),
95
+ isStale: (0, nag_1.checkIsTodoNagStale)(nag, intervalMs),
96
+ };
97
+ },
98
+ noteReminderDelivered(key, nowMs) {
99
+ saveNag(key, (0, nag_1.getTodoNagStateAfterReminder)(getCurrentNag(key), nowMs));
100
+ },
101
+ notePersonActivity(key) {
102
+ // On a person's message path, before the prompt is forwarded: a store that cannot be read or written is logged,
103
+ // never thrown — the message goes on.
104
+ try {
105
+ const stored = store.getTopic(key).nag;
106
+ if (stored === undefined || stored.ignoredCount === 0)
107
+ return;
108
+ saveNag(key, (0, nag_1.getTodoNagStateAfterPersonActivity)(getCurrentNag(key)));
109
+ }
110
+ catch (e) {
111
+ console.error(`[todos] ${(0, sessionKey_1.keyToString)(key)}: the reminder's silence could not be lifted:`, e instanceof Error ? e.message : e);
112
+ }
113
+ },
114
+ };
115
+ }
116
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/todos/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ import { type SessionKey } from '../sessionKey';
2
+ import type { SessionTurnProbe } from '../requests/wakeUpRules';
3
+ import type { TodoStandaloneGate } from './nag';
4
+ import type { TodoRegistry } from './registry';
5
+ /**
6
+ * @description The timer side of the staleness reminder (D10–D12). The conversations' sessions are POLLED like the
7
+ * wake-up engine's watched turns: each poll adds the WORKING time to the conversation's work — busy, and nothing
8
+ * holding the turn (a session waiting on a question is busy, but its agent does nothing) —, and a busy → idle edge is
9
+ * a turn end. The adapter's own turn end (`noteAdapterTurnEnd`, json-stream's `turnEnded`) is one too: the per-turn
10
+ * lifecycle stops the process right after it, before a poll could find it idle. A turn end starts the reminder's
11
+ * clock (the first one after an update) and, when the list is stale and every gate holds, posts the standalone
12
+ * reminder. Every decision is the
13
+ * registry's (`nag.ts`); this module only observes and acts. A failure in one conversation is logged and never stops
14
+ * the others. The same poll hands a busy session the project board's changes mid-turn (`midTurn.ts`) — it runs while
15
+ * the shared lists are on, the reminder off or not.
16
+ */
17
+ /** How often the sessions are polled — the wake-up engine's turn poll. */
18
+ export declare const todoReminderPollMs = 10000;
19
+ /**
20
+ * @name TodoReminderEngineDeps
21
+ * @description `listConversations` = the conversations whose sessions are polled; `getGate` adds what the turn probe
22
+ * does not know (an open request, the answer tail, a limit, an API-billed account); `getIntervalMs` = the reminder's
23
+ * interval now (`null` = off); `postReminder` writes the standalone reminder into the idle session and resolves
24
+ * whether it was written.
25
+ */
26
+ export interface TodoReminderEngineDeps {
27
+ registry: Pick<TodoRegistry, 'addTurnWork' | 'noteTurnEnd' | 'decideStandaloneReminder' | 'noteReminderDelivered'>;
28
+ listConversations: () => SessionKey[];
29
+ probeTurn: (key: SessionKey) => SessionTurnProbe;
30
+ getGate: (key: SessionKey) => Omit<TodoStandaloneGate, keyof SessionTurnProbe>;
31
+ getIntervalMs: () => number | null;
32
+ /** Whether the shared lists are on at all; off, the poll does nothing. */
33
+ checkIsEnabled: () => boolean;
34
+ postReminder: (key: SessionKey, text: string) => Promise<boolean>;
35
+ /**
36
+ * Mid-turn delivery (D22): reconcile what the hooks took, deliver to a working session what changed, and withdraw a
37
+ * waiting inbox when no tool call can take it (a turn's end, a turn held open).
38
+ */
39
+ midTurn?: {
40
+ reconcile(): void;
41
+ deliverIfPending(key: SessionKey): Promise<void>;
42
+ discardInbox(key: SessionKey): void;
43
+ };
44
+ now?: () => number;
45
+ pollIntervalMs?: number;
46
+ }
47
+ export declare class TodoReminderEngine {
48
+ private readonly deps;
49
+ private timer;
50
+ private lastPollAt;
51
+ /** Whether each conversation's session was busy at the previous poll. */
52
+ private readonly wasBusy;
53
+ /** Conversations whose reminder post is under way: never two at once. */
54
+ private readonly posting;
55
+ private readonly now;
56
+ private readonly pollIntervalMs;
57
+ constructor(deps: TodoReminderEngineDeps);
58
+ start(): void;
59
+ /** @description The conversation's agent produced output: a turn is under way, even one shorter than a poll. */
60
+ noteAgentOutput(key: SessionKey): void;
61
+ stop(): void;
62
+ /** @description One poll over every conversation (exposed for tests). */
63
+ poll(): Promise<void>;
64
+ private pollConversation;
65
+ /**
66
+ * @description The adapter reported a turn's end (json-stream `turnEnded`, every terminal `result`). A poll can miss
67
+ * it — the per-turn lifecycle stops the process right after, before the next poll finds it idle — so the event is a
68
+ * turn end of its own; a turn whose end is held (unread input, a compaction) is left to the poll.
69
+ */
70
+ noteAdapterTurnEnd(key: SessionKey): Promise<void>;
71
+ /**
72
+ * A waiting inbox is withdrawn: its changes stay unseen and ride the next prompt. So the inbox dir is empty between
73
+ * turns, and the hook starts no `node` for any other session's tool call meanwhile.
74
+ */
75
+ private discardInbox;
76
+ private handleTurnEnd;
77
+ }
78
+ //# sourceMappingURL=reminderEngine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reminderEngine.d.ts","sourceRoot":"","sources":["../../src/todos/reminderEngine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;;;;;;;;;;GAWG;AAEH,0EAA0E;AAC1E,eAAO,MAAM,kBAAkB,QAAS,CAAC;AAOzC;;;;;;GAMG;AACH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,aAAa,GAAG,aAAa,GAAG,0BAA0B,GAAG,uBAAuB,CAAC,CAAC;IACnH,iBAAiB,EAAE,MAAM,UAAU,EAAE,CAAC;IACtC,SAAS,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,gBAAgB,CAAC;IACjD,OAAO,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,IAAI,CAAC,kBAAkB,EAAE,MAAM,gBAAgB,CAAC,CAAC;IAC/E,aAAa,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IACnC,0EAA0E;IAC1E,cAAc,EAAE,MAAM,OAAO,CAAC;IAC9B,YAAY,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAClE;;;OAGG;IACH,OAAO,CAAC,EAAE;QAAE,SAAS,IAAI,IAAI,CAAC;QAAC,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAAC,YAAY,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CAAA;KAAE,CAAC;IACvH,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAOD,qBAAa,kBAAkB;IAUjB,OAAO,CAAC,QAAQ,CAAC,IAAI;IATjC,OAAO,CAAC,KAAK,CAA+B;IAC5C,OAAO,CAAC,UAAU,CAAuB;IACzC,yEAAyE;IACzE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8B;IACtD,yEAAyE;IACzE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAEX,IAAI,EAAE,sBAAsB;IAKzD,KAAK,IAAI,IAAI;IASb,gHAAgH;IAChH,eAAe,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI;IAItC,IAAI,IAAI,IAAI;IAKZ,yEAAyE;IACnE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAoBb,gBAAgB;IA2B9B;;;;OAIG;IACG,kBAAkB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAQxD;;;OAGG;IACH,OAAO,CAAC,YAAY;YAQN,aAAa;CAqB5B"}
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TodoReminderEngine = exports.todoReminderPollMs = void 0;
4
+ const sessionKey_1 = require("../sessionKey");
5
+ /**
6
+ * @description The timer side of the staleness reminder (D10–D12). The conversations' sessions are POLLED like the
7
+ * wake-up engine's watched turns: each poll adds the WORKING time to the conversation's work — busy, and nothing
8
+ * holding the turn (a session waiting on a question is busy, but its agent does nothing) —, and a busy → idle edge is
9
+ * a turn end. The adapter's own turn end (`noteAdapterTurnEnd`, json-stream's `turnEnded`) is one too: the per-turn
10
+ * lifecycle stops the process right after it, before a poll could find it idle. A turn end starts the reminder's
11
+ * clock (the first one after an update) and, when the list is stale and every gate holds, posts the standalone
12
+ * reminder. Every decision is the
13
+ * registry's (`nag.ts`); this module only observes and acts. A failure in one conversation is logged and never stops
14
+ * the others. The same poll hands a busy session the project board's changes mid-turn (`midTurn.ts`) — it runs while
15
+ * the shared lists are on, the reminder off or not.
16
+ */
17
+ /** How often the sessions are polled — the wake-up engine's turn poll. */
18
+ exports.todoReminderPollMs = 10_000;
19
+ /**
20
+ * A poll that comes much later than due (a suspended host, a blocked event loop) counts at most this many intervals
21
+ * of work: the gap was not observed as work.
22
+ */
23
+ const maxCountedPollIntervals = 3;
24
+ /** @description Whether the session stands at a settled turn end: live, idle, nothing holding the turn, nothing unread. */
25
+ function checkIsSettledTurnEnd(probe) {
26
+ return probe.isActive && !probe.isBusy && !probe.isTurnEndBlocked && probe.hasUnconsumedInput !== true;
27
+ }
28
+ class TodoReminderEngine {
29
+ deps;
30
+ timer = null;
31
+ lastPollAt = null;
32
+ /** Whether each conversation's session was busy at the previous poll. */
33
+ wasBusy = new Map();
34
+ /** Conversations whose reminder post is under way: never two at once. */
35
+ posting = new Set();
36
+ now;
37
+ pollIntervalMs;
38
+ constructor(deps) {
39
+ this.deps = deps;
40
+ this.now = deps.now ?? Date.now;
41
+ this.pollIntervalMs = deps.pollIntervalMs ?? exports.todoReminderPollMs;
42
+ }
43
+ start() {
44
+ if (this.timer)
45
+ return;
46
+ this.lastPollAt = this.now();
47
+ this.timer = setInterval(() => {
48
+ void this.poll().catch((e) => console.warn('[todos] reminder poll failed:', e instanceof Error ? e.message : e));
49
+ }, this.pollIntervalMs);
50
+ this.timer.unref();
51
+ }
52
+ /** @description The conversation's agent produced output: a turn is under way, even one shorter than a poll. */
53
+ noteAgentOutput(key) {
54
+ this.wasBusy.set((0, sessionKey_1.keyToString)(key), true);
55
+ }
56
+ stop() {
57
+ if (this.timer)
58
+ clearInterval(this.timer);
59
+ this.timer = null;
60
+ }
61
+ /** @description One poll over every conversation (exposed for tests). */
62
+ async poll() {
63
+ const nowMs = this.now();
64
+ const elapsedMs = Math.min(nowMs - (this.lastPollAt ?? nowMs), maxCountedPollIntervals * this.pollIntervalMs);
65
+ this.lastPollAt = nowMs;
66
+ // Off: nothing is counted, and a turn seen busy now is not an end later.
67
+ if (!this.deps.checkIsEnabled()) {
68
+ this.wasBusy.clear();
69
+ return;
70
+ }
71
+ const intervalMs = this.deps.getIntervalMs();
72
+ this.deps.midTurn?.reconcile();
73
+ for (const key of this.deps.listConversations()) {
74
+ try {
75
+ await this.pollConversation(key, nowMs, elapsedMs, intervalMs);
76
+ }
77
+ catch (e) {
78
+ console.warn(`[todos] reminder poll of ${(0, sessionKey_1.keyToString)(key)} failed:`, e instanceof Error ? e.message : e);
79
+ }
80
+ }
81
+ }
82
+ async pollConversation(key, nowMs, elapsedMs, intervalMs) {
83
+ const conversationKey = (0, sessionKey_1.keyToString)(key);
84
+ const probe = this.deps.probeTurn(key);
85
+ const wasBusy = this.wasBusy.get(conversationKey) === true;
86
+ this.wasBusy.set(conversationKey, probe.isBusy);
87
+ if (probe.isBusy) {
88
+ // A turn held open (a question waiting for the operator, a compaction) is no work of the agent's, and makes no
89
+ // tool call that could take an inbox: the changes wait for the turn to go on.
90
+ if (probe.isTurnEndBlocked) {
91
+ this.discardInbox(key);
92
+ return;
93
+ }
94
+ this.deps.registry.addTurnWork(key, elapsedMs);
95
+ await this.deps.midTurn?.deliverIfPending(key);
96
+ return;
97
+ }
98
+ const isTurnEnd = wasBusy && checkIsSettledTurnEnd(probe);
99
+ if (!isTurnEnd) {
100
+ // A turn whose end is held (a question, a compaction, unread input) ends at a later poll.
101
+ if (wasBusy && probe.isActive)
102
+ this.wasBusy.set(conversationKey, true);
103
+ // A session that ended mid-turn (a stop, a crash) makes no more tool calls.
104
+ if (wasBusy && !probe.isActive)
105
+ this.discardInbox(key);
106
+ return;
107
+ }
108
+ await this.handleTurnEnd(key, probe, nowMs, intervalMs);
109
+ }
110
+ /**
111
+ * @description The adapter reported a turn's end (json-stream `turnEnded`, every terminal `result`). A poll can miss
112
+ * it — the per-turn lifecycle stops the process right after, before the next poll finds it idle — so the event is a
113
+ * turn end of its own; a turn whose end is held (unread input, a compaction) is left to the poll.
114
+ */
115
+ async noteAdapterTurnEnd(key) {
116
+ if (!this.deps.checkIsEnabled())
117
+ return;
118
+ const probe = this.deps.probeTurn(key);
119
+ if (!checkIsSettledTurnEnd(probe))
120
+ return;
121
+ this.wasBusy.set((0, sessionKey_1.keyToString)(key), false);
122
+ await this.handleTurnEnd(key, probe, this.now(), this.deps.getIntervalMs());
123
+ }
124
+ /**
125
+ * A waiting inbox is withdrawn: its changes stay unseen and ride the next prompt. So the inbox dir is empty between
126
+ * turns, and the hook starts no `node` for any other session's tool call meanwhile.
127
+ */
128
+ discardInbox(key) {
129
+ try {
130
+ this.deps.midTurn?.discardInbox(key);
131
+ }
132
+ catch (e) {
133
+ console.warn(`[todos] ${(0, sessionKey_1.keyToString)(key)}: the mid-turn inbox could not be withdrawn:`, e instanceof Error ? e.message : e);
134
+ }
135
+ }
136
+ async handleTurnEnd(key, probe, nowMs, intervalMs) {
137
+ const conversationKey = (0, sessionKey_1.keyToString)(key);
138
+ this.discardInbox(key);
139
+ this.deps.registry.noteTurnEnd(key, nowMs);
140
+ if (this.posting.has(conversationKey))
141
+ return;
142
+ const decision = this.deps.registry.decideStandaloneReminder(key, intervalMs, { ...probe, ...this.deps.getGate(key) }, nowMs);
143
+ if (!decision.shouldRemind) {
144
+ // A due reminder that a gate holds back is worth one line per turn end; a list that is not due is not.
145
+ if (decision.isStale)
146
+ console.log(`[todos] ${conversationKey}: stale list, no reminder: ${decision.skipReasons.join(', ')}`);
147
+ return;
148
+ }
149
+ this.posting.add(conversationKey);
150
+ try {
151
+ if (await this.deps.postReminder(key, decision.text)) {
152
+ this.deps.registry.noteReminderDelivered(key, this.now());
153
+ console.log(`[todos] ${conversationKey}: stale list — reminded the agent`);
154
+ }
155
+ }
156
+ finally {
157
+ this.posting.delete(conversationKey);
158
+ }
159
+ }
160
+ }
161
+ exports.TodoReminderEngine = TodoReminderEngine;
162
+ //# sourceMappingURL=reminderEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reminderEngine.js","sourceRoot":"","sources":["../../src/todos/reminderEngine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import { type SessionKey } from '../sessionKey';
2
+ import { type TodoItem, type TodoTopicFile } from './types';
3
+ /** A closed item older than this leaves the live file for the archive. */
4
+ export declare const todoArchiveAfterMs: number;
5
+ /** @description `DATA_DIR/todos`: the lists, their archive, the mid-turn inboxes and the repositories' first commits. */
6
+ export declare function getTodosDir(dataDir: string): string;
7
+ /** @description The empty record of a conversation that never published anything. */
8
+ export declare function createEmptyTodoTopicFile(key: SessionKey): TodoTopicFile;
9
+ /**
10
+ * @description Split `file` into what stays live and the closed items old enough for the archive (closed before
11
+ * `nowMs - todoArchiveAfterMs`).
12
+ */
13
+ export declare function getTodoArchiveSplit(file: TodoTopicFile, nowMs: number): {
14
+ file: TodoTopicFile;
15
+ archived: TodoItem[];
16
+ };
17
+ /** @name TodoStore @description The file store over one data dir. */
18
+ export declare class TodoStore {
19
+ private readonly dataDir;
20
+ private readonly getNowMs;
21
+ private readonly files;
22
+ constructor(dataDir: string, getNowMs?: () => number);
23
+ private getDir;
24
+ private getFilePath;
25
+ private getArchivePath;
26
+ /** @description The conversation's record; the empty one when it never published (nothing is written for that). */
27
+ getTopic(key: SessionKey): TodoTopicFile;
28
+ private readTopicFile;
29
+ /** @description Store the conversation's record: old closed items go to the archive first. */
30
+ saveTopic(key: SessionKey, file: TodoTopicFile): TodoTopicFile;
31
+ /** @description The newest `limit` archived items of the conversation, the most recently closed first. */
32
+ readArchivedItems(key: SessionKey, limit: number): TodoItem[];
33
+ }
34
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/todos/store.ts"],"names":[],"mappings":"AAIA,OAAO,EAA0B,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAExE,OAAO,EAA6B,KAAK,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,SAAS,CAAC;AAqBvF,0EAA0E;AAC1E,eAAO,MAAM,kBAAkB,QAA2B,CAAC;AAmC3D,yHAAyH;AACzH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,qFAAqF;AACrF,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,UAAU,GAAG,aAAa,CAEvE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,EAAE,QAAQ,EAAE,CAAA;CAAE,CAMrH;AAED,qEAAqE;AACrE,qBAAa,SAAS;IAGR,OAAO,CAAC,QAAQ,CAAC,OAAO;IAAU,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAFvE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoC;gBAE7B,OAAO,EAAE,MAAM,EAAmB,QAAQ,GAAE,MAAM,MAAiB;IAEhG,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,cAAc;IAItB,mHAAmH;IACnH,QAAQ,CAAC,GAAG,EAAE,UAAU,GAAG,aAAa;IASxC,OAAO,CAAC,aAAa;IAqBrB,8FAA8F;IAC9F,SAAS,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,aAAa,GAAG,aAAa;IAa9D,0GAA0G;IAC1G,iBAAiB,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,QAAQ,EAAE;CAmB9D"}
@@ -0,0 +1,208 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.TodoStore = exports.todoArchiveAfterMs = void 0;
37
+ exports.getTodosDir = getTodosDir;
38
+ exports.createEmptyTodoTopicFile = createEmptyTodoTopicFile;
39
+ exports.getTodoArchiveSplit = getTodoArchiveSplit;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const zod_1 = require("zod");
43
+ const configDirFile_1 = require("../configDirFile");
44
+ const sessionKey_1 = require("../sessionKey");
45
+ const order_1 = require("./order");
46
+ const types_1 = require("./types");
47
+ /**
48
+ * @description The file store of the todo registry — the truth and the full history (D26). One JSON file per
49
+ * conversation, `DATA_DIR/todos/<conversation slug>.json`, written atomically (a temp file and a rename) and cached in
50
+ * memory: the bot is the only writer and every call is synchronous, so two writes can never interleave. A closed
51
+ * item older than {@link todoArchiveAfterMs} moves to `todos/archive/<slug>.jsonl` at the next save, one line per
52
+ * item, so the live file stays small and nothing is ever deleted.
53
+ *
54
+ * A file that cannot be read is set aside (`<name>.corrupt-<time>`) with one error line and the conversation starts
55
+ * from an empty list — a broken file must neither stop the bot nor be overwritten unseen.
56
+ */
57
+ /** The store's directory under `DATA_DIR`. */
58
+ const todosDirName = 'todos';
59
+ /** Where archived items go, under the store's directory. */
60
+ const archiveDirName = 'archive';
61
+ /** `:` is illegal in a file name on some filesystems; the slug uses this instead. */
62
+ const conversationSlugSeparator = '_';
63
+ const todoFileExtension = '.json';
64
+ const archiveFileExtension = '.jsonl';
65
+ /** A closed item older than this leaves the live file for the archive. */
66
+ exports.todoArchiveAfterMs = 30 * 24 * 60 * 60 * 1000;
67
+ /** Private content of the operator's work: readable by the bot's user only. */
68
+ const todoFileMode = 0o600;
69
+ const todoItemSchema = zod_1.z.object({
70
+ id: zod_1.z.string(),
71
+ title: zod_1.z.string(),
72
+ status: zod_1.z.enum(types_1.todoStatuses),
73
+ note: zod_1.z.string().optional(),
74
+ source: zod_1.z.enum(types_1.todoSources),
75
+ ref: zod_1.z.string().optional(),
76
+ createdAt: zod_1.z.number(),
77
+ updatedAt: zod_1.z.number(),
78
+ startedAt: zod_1.z.number().optional(),
79
+ closedAt: zod_1.z.number().optional(),
80
+ });
81
+ const todoTopicFileSchema = zod_1.z.object({
82
+ version: zod_1.z.literal(1),
83
+ conversationKey: zod_1.z.string(),
84
+ nextItemNumber: zod_1.z.number().int().positive(),
85
+ items: zod_1.z.array(todoItemSchema),
86
+ revision: zod_1.z.number().int().nonnegative(),
87
+ changedAt: zod_1.z.number().optional(),
88
+ lastUpdateAt: zod_1.z.number().optional(),
89
+ nag: zod_1.z.object({
90
+ clockStartedAt: zod_1.z.number().optional(),
91
+ workedMs: zod_1.z.number().nonnegative(),
92
+ ignoredCount: zod_1.z.number().int().nonnegative(),
93
+ lastRemindedAt: zod_1.z.number().optional(),
94
+ }).optional(),
95
+ lastTurnEndAt: zod_1.z.number().optional(),
96
+ boardSeen: zod_1.z.object({ revisions: zod_1.z.record(zod_1.z.string(), zod_1.z.number()), at: zod_1.z.number() }).optional(),
97
+ });
98
+ /** @description `DATA_DIR/todos`: the lists, their archive, the mid-turn inboxes and the repositories' first commits. */
99
+ function getTodosDir(dataDir) {
100
+ return path.join(dataDir, todosDirName);
101
+ }
102
+ /** @description The empty record of a conversation that never published anything. */
103
+ function createEmptyTodoTopicFile(key) {
104
+ return { version: 1, conversationKey: (0, sessionKey_1.keyToString)(key), nextItemNumber: 1, items: [], revision: 0 };
105
+ }
106
+ /**
107
+ * @description Split `file` into what stays live and the closed items old enough for the archive (closed before
108
+ * `nowMs - todoArchiveAfterMs`).
109
+ */
110
+ function getTodoArchiveSplit(file, nowMs) {
111
+ const archiveBefore = nowMs - exports.todoArchiveAfterMs;
112
+ const isArchived = (item) => !(0, order_1.checkIsOpenTodoItem)(item) && (item.closedAt ?? item.updatedAt) < archiveBefore;
113
+ const archived = file.items.filter(isArchived);
114
+ if (archived.length === 0)
115
+ return { file, archived };
116
+ return { file: { ...file, items: file.items.filter((item) => !isArchived(item)) }, archived };
117
+ }
118
+ /** @name TodoStore @description The file store over one data dir. */
119
+ class TodoStore {
120
+ dataDir;
121
+ getNowMs;
122
+ files = new Map();
123
+ constructor(dataDir, getNowMs = Date.now) {
124
+ this.dataDir = dataDir;
125
+ this.getNowMs = getNowMs;
126
+ }
127
+ getDir() {
128
+ return getTodosDir(this.dataDir);
129
+ }
130
+ getFilePath(key) {
131
+ return path.join(this.getDir(), `${(0, sessionKey_1.keyToSlug)(key, conversationSlugSeparator)}${todoFileExtension}`);
132
+ }
133
+ getArchivePath(key) {
134
+ return path.join(this.getDir(), archiveDirName, `${(0, sessionKey_1.keyToSlug)(key, conversationSlugSeparator)}${archiveFileExtension}`);
135
+ }
136
+ /** @description The conversation's record; the empty one when it never published (nothing is written for that). */
137
+ getTopic(key) {
138
+ const conversationKey = (0, sessionKey_1.keyToString)(key);
139
+ const cached = this.files.get(conversationKey);
140
+ if (cached)
141
+ return cached;
142
+ const loaded = this.readTopicFile(key);
143
+ this.files.set(conversationKey, loaded);
144
+ return loaded;
145
+ }
146
+ readTopicFile(key) {
147
+ const filePath = this.getFilePath(key);
148
+ let text;
149
+ try {
150
+ text = fs.readFileSync(filePath, 'utf8');
151
+ }
152
+ catch (e) {
153
+ if (e instanceof Error && 'code' in e && e.code === 'ENOENT')
154
+ return createEmptyTodoTopicFile(key);
155
+ throw e;
156
+ }
157
+ try {
158
+ const parsed = todoTopicFileSchema.parse(JSON.parse(text));
159
+ if (parsed.conversationKey !== (0, sessionKey_1.keyToString)(key))
160
+ throw new Error(`it belongs to ${parsed.conversationKey}`);
161
+ return parsed;
162
+ }
163
+ catch (e) {
164
+ const asidePath = `${filePath}.corrupt-${this.getNowMs()}`;
165
+ fs.renameSync(filePath, asidePath);
166
+ console.error(`[todos] ${filePath} is unreadable (${e instanceof Error ? e.message : String(e)}); set aside as ${asidePath}, the list starts empty`);
167
+ return createEmptyTodoTopicFile(key);
168
+ }
169
+ }
170
+ /** @description Store the conversation's record: old closed items go to the archive first. */
171
+ saveTopic(key, file) {
172
+ const split = getTodoArchiveSplit(file, this.getNowMs());
173
+ if (split.archived.length > 0) {
174
+ const archivePath = this.getArchivePath(key);
175
+ fs.mkdirSync(path.dirname(archivePath), { recursive: true, mode: 0o700 });
176
+ fs.appendFileSync(archivePath, split.archived.map((item) => `${JSON.stringify(item)}\n`).join(''), { mode: todoFileMode });
177
+ }
178
+ fs.mkdirSync(this.getDir(), { recursive: true, mode: 0o700 });
179
+ (0, configDirFile_1.writeJsonFileAtomically)(this.getFilePath(key), split.file, todoFileMode);
180
+ this.files.set((0, sessionKey_1.keyToString)(key), split.file);
181
+ return split.file;
182
+ }
183
+ /** @description The newest `limit` archived items of the conversation, the most recently closed first. */
184
+ readArchivedItems(key, limit) {
185
+ let text;
186
+ try {
187
+ text = fs.readFileSync(this.getArchivePath(key), 'utf8');
188
+ }
189
+ catch {
190
+ return [];
191
+ }
192
+ const items = text.split('\n').flatMap((line) => {
193
+ if (line.trim() === '')
194
+ return [];
195
+ try {
196
+ const parsed = todoItemSchema.safeParse(JSON.parse(line));
197
+ return parsed.success ? [parsed.data] : [];
198
+ }
199
+ catch {
200
+ // A torn last line (a crash mid-append) is skipped; the lines before it are whole.
201
+ return [];
202
+ }
203
+ });
204
+ return items.sort((left, right) => (right.closedAt ?? 0) - (left.closedAt ?? 0)).slice(0, limit);
205
+ }
206
+ }
207
+ exports.TodoStore = TodoStore;
208
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/todos/store.ts"],"names":[],"mappings":"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"}