charness 0.0.0-stage → 3.1.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 (1044) hide show
  1. package/.env.example +88 -0
  2. package/DEVELOPMENT.md +110 -0
  3. package/LICENSE +21 -0
  4. package/MIGRATION_1_TO_2.md +24 -0
  5. package/README.md +1196 -2
  6. package/dist/accessControl.d.ts +71 -0
  7. package/dist/accessControl.d.ts.map +1 -0
  8. package/dist/accessControl.js +108 -0
  9. package/dist/accessControl.js.map +1 -0
  10. package/dist/adapters/adapterEventRouting.d.ts +51 -0
  11. package/dist/adapters/adapterEventRouting.d.ts.map +1 -0
  12. package/dist/adapters/adapterEventRouting.js +74 -0
  13. package/dist/adapters/adapterEventRouting.js.map +1 -0
  14. package/dist/adapters/adapterNames.d.ts +19 -0
  15. package/dist/adapters/adapterNames.d.ts.map +1 -0
  16. package/dist/adapters/adapterNames.js +25 -0
  17. package/dist/adapters/adapterNames.js.map +1 -0
  18. package/dist/adapters/claudeCliAdapter.d.ts +1351 -0
  19. package/dist/adapters/claudeCliAdapter.d.ts.map +1 -0
  20. package/dist/adapters/claudeCliAdapter.js +4239 -0
  21. package/dist/adapters/claudeCliAdapter.js.map +1 -0
  22. package/dist/adapters/claudeConfigDir.d.ts +40 -0
  23. package/dist/adapters/claudeConfigDir.d.ts.map +1 -0
  24. package/dist/adapters/claudeConfigDir.js +3 -0
  25. package/dist/adapters/claudeConfigDir.js.map +1 -0
  26. package/dist/adapters/claudeJsonStreamAdapter.d.ts +580 -0
  27. package/dist/adapters/claudeJsonStreamAdapter.d.ts.map +1 -0
  28. package/dist/adapters/claudeJsonStreamAdapter.js +1891 -0
  29. package/dist/adapters/claudeJsonStreamAdapter.js.map +1 -0
  30. package/dist/adapters/claudePlatformFlags.d.ts +35 -0
  31. package/dist/adapters/claudePlatformFlags.d.ts.map +1 -0
  32. package/dist/adapters/claudePlatformFlags.js +46 -0
  33. package/dist/adapters/claudePlatformFlags.js.map +1 -0
  34. package/dist/adapters/createAdapter.d.ts +260 -0
  35. package/dist/adapters/createAdapter.d.ts.map +1 -0
  36. package/dist/adapters/createAdapter.js +512 -0
  37. package/dist/adapters/createAdapter.js.map +1 -0
  38. package/dist/adapters/openCodeAdapter.d.ts +1469 -0
  39. package/dist/adapters/openCodeAdapter.d.ts.map +1 -0
  40. package/dist/adapters/openCodeAdapter.js +4623 -0
  41. package/dist/adapters/openCodeAdapter.js.map +1 -0
  42. package/dist/adapters/sessionLaunchDefaults.d.ts +28 -0
  43. package/dist/adapters/sessionLaunchDefaults.d.ts.map +1 -0
  44. package/dist/adapters/sessionLaunchDefaults.js +15 -0
  45. package/dist/adapters/sessionLaunchDefaults.js.map +1 -0
  46. package/dist/adapters/terminalAdapter.d.ts +68 -0
  47. package/dist/adapters/terminalAdapter.d.ts.map +1 -0
  48. package/dist/adapters/terminalAdapter.js +371 -0
  49. package/dist/adapters/terminalAdapter.js.map +1 -0
  50. package/dist/agentLogin/agentLogin.d.ts +44 -0
  51. package/dist/agentLogin/agentLogin.d.ts.map +1 -0
  52. package/dist/agentLogin/agentLogin.js +530 -0
  53. package/dist/agentLogin/agentLogin.js.map +1 -0
  54. package/dist/agentTrigger.d.ts +28 -0
  55. package/dist/agentTrigger.d.ts.map +1 -0
  56. package/dist/agentTrigger.js +53 -0
  57. package/dist/agentTrigger.js.map +1 -0
  58. package/dist/apiErrorRetry.d.ts +214 -0
  59. package/dist/apiErrorRetry.d.ts.map +1 -0
  60. package/dist/apiErrorRetry.js +382 -0
  61. package/dist/apiErrorRetry.js.map +1 -0
  62. package/dist/apiRetryKick.d.ts +157 -0
  63. package/dist/apiRetryKick.d.ts.map +1 -0
  64. package/dist/apiRetryKick.js +174 -0
  65. package/dist/apiRetryKick.js.map +1 -0
  66. package/dist/bootClassifier.d.ts +46 -0
  67. package/dist/bootClassifier.d.ts.map +1 -0
  68. package/dist/bootClassifier.js +43 -0
  69. package/dist/bootClassifier.js.map +1 -0
  70. package/dist/bot.d.ts +207 -0
  71. package/dist/bot.d.ts.map +1 -0
  72. package/dist/bot.js +11226 -0
  73. package/dist/bot.js.map +1 -0
  74. package/dist/botFileStorage.d.ts +60 -0
  75. package/dist/botFileStorage.d.ts.map +1 -0
  76. package/dist/botFileStorage.js +205 -0
  77. package/dist/botFileStorage.js.map +1 -0
  78. package/dist/cli/applyDnsFix.d.ts +7 -0
  79. package/dist/cli/applyDnsFix.d.ts.map +1 -0
  80. package/dist/cli/applyDnsFix.js +46 -0
  81. package/dist/cli/applyDnsFix.js.map +1 -0
  82. package/dist/cli/bot.d.ts +27 -0
  83. package/dist/cli/bot.d.ts.map +1 -0
  84. package/dist/cli/bot.js +98 -0
  85. package/dist/cli/bot.js.map +1 -0
  86. package/dist/cli/botEntry.d.ts +3 -0
  87. package/dist/cli/botEntry.d.ts.map +1 -0
  88. package/dist/cli/botEntry.js +11 -0
  89. package/dist/cli/botEntry.js.map +1 -0
  90. package/dist/cli/claudeProfiles.d.ts +42 -0
  91. package/dist/cli/claudeProfiles.d.ts.map +1 -0
  92. package/dist/cli/claudeProfiles.js +106 -0
  93. package/dist/cli/claudeProfiles.js.map +1 -0
  94. package/dist/cli/connectorGuards.d.ts +31 -0
  95. package/dist/cli/connectorGuards.d.ts.map +1 -0
  96. package/dist/cli/connectorGuards.js +159 -0
  97. package/dist/cli/connectorGuards.js.map +1 -0
  98. package/dist/cli/envLoader.d.ts +34 -0
  99. package/dist/cli/envLoader.d.ts.map +1 -0
  100. package/dist/cli/envLoader.js +132 -0
  101. package/dist/cli/envLoader.js.map +1 -0
  102. package/dist/cli/hot.d.ts +82 -0
  103. package/dist/cli/hot.d.ts.map +1 -0
  104. package/dist/cli/hot.js +323 -0
  105. package/dist/cli/hot.js.map +1 -0
  106. package/dist/cli.d.ts +3 -0
  107. package/dist/cli.d.ts.map +1 -0
  108. package/dist/cli.js +140 -0
  109. package/dist/cli.js.map +1 -0
  110. package/dist/connectors/jira/adf.d.ts +74 -0
  111. package/dist/connectors/jira/adf.d.ts.map +1 -0
  112. package/dist/connectors/jira/adf.js +412 -0
  113. package/dist/connectors/jira/adf.js.map +1 -0
  114. package/dist/connectors/jira/agentBinaries.d.ts +14 -0
  115. package/dist/connectors/jira/agentBinaries.d.ts.map +1 -0
  116. package/dist/connectors/jira/agentBinaries.js +75 -0
  117. package/dist/connectors/jira/agentBinaries.js.map +1 -0
  118. package/dist/connectors/jira/answerSink.d.ts +59 -0
  119. package/dist/connectors/jira/answerSink.d.ts.map +1 -0
  120. package/dist/connectors/jira/answerSink.js +234 -0
  121. package/dist/connectors/jira/answerSink.js.map +1 -0
  122. package/dist/connectors/jira/attachmentDownload.d.ts +41 -0
  123. package/dist/connectors/jira/attachmentDownload.d.ts.map +1 -0
  124. package/dist/connectors/jira/attachmentDownload.js +92 -0
  125. package/dist/connectors/jira/attachmentDownload.js.map +1 -0
  126. package/dist/connectors/jira/attachmentTool.d.ts +50 -0
  127. package/dist/connectors/jira/attachmentTool.d.ts.map +1 -0
  128. package/dist/connectors/jira/attachmentTool.js +166 -0
  129. package/dist/connectors/jira/attachmentTool.js.map +1 -0
  130. package/dist/connectors/jira/client.d.ts +522 -0
  131. package/dist/connectors/jira/client.d.ts.map +1 -0
  132. package/dist/connectors/jira/client.js +491 -0
  133. package/dist/connectors/jira/client.js.map +1 -0
  134. package/dist/connectors/jira/config.d.ts +104 -0
  135. package/dist/connectors/jira/config.d.ts.map +1 -0
  136. package/dist/connectors/jira/config.js +323 -0
  137. package/dist/connectors/jira/config.js.map +1 -0
  138. package/dist/connectors/jira/configFile.d.ts +10 -0
  139. package/dist/connectors/jira/configFile.d.ts.map +1 -0
  140. package/dist/connectors/jira/configFile.js +50 -0
  141. package/dist/connectors/jira/configFile.js.map +1 -0
  142. package/dist/connectors/jira/connector.d.ts +71 -0
  143. package/dist/connectors/jira/connector.d.ts.map +1 -0
  144. package/dist/connectors/jira/connector.js +312 -0
  145. package/dist/connectors/jira/connector.js.map +1 -0
  146. package/dist/connectors/jira/contextLedger.d.ts +60 -0
  147. package/dist/connectors/jira/contextLedger.d.ts.map +1 -0
  148. package/dist/connectors/jira/contextLedger.js +196 -0
  149. package/dist/connectors/jira/contextLedger.js.map +1 -0
  150. package/dist/connectors/jira/contextPreamble.d.ts +18 -0
  151. package/dist/connectors/jira/contextPreamble.d.ts.map +1 -0
  152. package/dist/connectors/jira/contextPreamble.js +31 -0
  153. package/dist/connectors/jira/contextPreamble.js.map +1 -0
  154. package/dist/connectors/jira/inbound.d.ts +141 -0
  155. package/dist/connectors/jira/inbound.d.ts.map +1 -0
  156. package/dist/connectors/jira/inbound.js +331 -0
  157. package/dist/connectors/jira/inbound.js.map +1 -0
  158. package/dist/connectors/jira/issueBlocks.d.ts +74 -0
  159. package/dist/connectors/jira/issueBlocks.d.ts.map +1 -0
  160. package/dist/connectors/jira/issueBlocks.js +257 -0
  161. package/dist/connectors/jira/issueBlocks.js.map +1 -0
  162. package/dist/connectors/jira/issueContext.d.ts +31 -0
  163. package/dist/connectors/jira/issueContext.d.ts.map +1 -0
  164. package/dist/connectors/jira/issueContext.js +70 -0
  165. package/dist/connectors/jira/issueContext.js.map +1 -0
  166. package/dist/connectors/jira/issueDelta.d.ts +38 -0
  167. package/dist/connectors/jira/issueDelta.d.ts.map +1 -0
  168. package/dist/connectors/jira/issueDelta.js +59 -0
  169. package/dist/connectors/jira/issueDelta.js.map +1 -0
  170. package/dist/connectors/jira/mediaPlaceholders.d.ts +22 -0
  171. package/dist/connectors/jira/mediaPlaceholders.d.ts.map +1 -0
  172. package/dist/connectors/jira/mediaPlaceholders.js +105 -0
  173. package/dist/connectors/jira/mediaPlaceholders.js.map +1 -0
  174. package/dist/connectors/jira/outbound.d.ts +6 -0
  175. package/dist/connectors/jira/outbound.d.ts.map +1 -0
  176. package/dist/connectors/jira/outbound.js +38 -0
  177. package/dist/connectors/jira/outbound.js.map +1 -0
  178. package/dist/connectors/jira/prompt.d.ts +39 -0
  179. package/dist/connectors/jira/prompt.d.ts.map +1 -0
  180. package/dist/connectors/jira/prompt.js +102 -0
  181. package/dist/connectors/jira/prompt.js.map +1 -0
  182. package/dist/connectors/jira/promptSpill.d.ts +50 -0
  183. package/dist/connectors/jira/promptSpill.d.ts.map +1 -0
  184. package/dist/connectors/jira/promptSpill.js +157 -0
  185. package/dist/connectors/jira/promptSpill.js.map +1 -0
  186. package/dist/connectors/jira/promptText.d.ts +7 -0
  187. package/dist/connectors/jira/promptText.d.ts.map +1 -0
  188. package/dist/connectors/jira/promptText.js +26 -0
  189. package/dist/connectors/jira/promptText.js.map +1 -0
  190. package/dist/connectors/jira/sessionKeyCodec.d.ts +18 -0
  191. package/dist/connectors/jira/sessionKeyCodec.d.ts.map +1 -0
  192. package/dist/connectors/jira/sessionKeyCodec.js +106 -0
  193. package/dist/connectors/jira/sessionKeyCodec.js.map +1 -0
  194. package/dist/connectors/jira/trigger.d.ts +54 -0
  195. package/dist/connectors/jira/trigger.d.ts.map +1 -0
  196. package/dist/connectors/jira/trigger.js +101 -0
  197. package/dist/connectors/jira/trigger.js.map +1 -0
  198. package/dist/connectors/jira/triggerLog.d.ts +53 -0
  199. package/dist/connectors/jira/triggerLog.d.ts.map +1 -0
  200. package/dist/connectors/jira/triggerLog.js +78 -0
  201. package/dist/connectors/jira/triggerLog.js.map +1 -0
  202. package/dist/connectors/jira/trustedGroup.d.ts +54 -0
  203. package/dist/connectors/jira/trustedGroup.d.ts.map +1 -0
  204. package/dist/connectors/jira/trustedGroup.js +98 -0
  205. package/dist/connectors/jira/trustedGroup.js.map +1 -0
  206. package/dist/connectors/jira/unconfirmedPosts.d.ts +58 -0
  207. package/dist/connectors/jira/unconfirmedPosts.d.ts.map +1 -0
  208. package/dist/connectors/jira/unconfirmedPosts.js +105 -0
  209. package/dist/connectors/jira/unconfirmedPosts.js.map +1 -0
  210. package/dist/connectors/telegram/answerSink.d.ts +46 -0
  211. package/dist/connectors/telegram/answerSink.d.ts.map +1 -0
  212. package/dist/connectors/telegram/answerSink.js +71 -0
  213. package/dist/connectors/telegram/answerSink.js.map +1 -0
  214. package/dist/connectors/telegram/commands/autoContinueLimits.d.ts +34 -0
  215. package/dist/connectors/telegram/commands/autoContinueLimits.d.ts.map +1 -0
  216. package/dist/connectors/telegram/commands/autoContinueLimits.js +112 -0
  217. package/dist/connectors/telegram/commands/autoContinueLimits.js.map +1 -0
  218. package/dist/connectors/telegram/commands/botCore.d.ts +46 -0
  219. package/dist/connectors/telegram/commands/botCore.d.ts.map +1 -0
  220. package/dist/connectors/telegram/commands/botCore.js +3 -0
  221. package/dist/connectors/telegram/commands/botCore.js.map +1 -0
  222. package/dist/connectors/telegram/commands/callbackMessage.d.ts +12 -0
  223. package/dist/connectors/telegram/commands/callbackMessage.d.ts.map +1 -0
  224. package/dist/connectors/telegram/commands/callbackMessage.js +13 -0
  225. package/dist/connectors/telegram/commands/callbackMessage.js.map +1 -0
  226. package/dist/connectors/telegram/commands/claudeAccounts.d.ts +58 -0
  227. package/dist/connectors/telegram/commands/claudeAccounts.d.ts.map +1 -0
  228. package/dist/connectors/telegram/commands/claudeAccounts.js +591 -0
  229. package/dist/connectors/telegram/commands/claudeAccounts.js.map +1 -0
  230. package/dist/connectors/telegram/commands/compaction.d.ts +47 -0
  231. package/dist/connectors/telegram/commands/compaction.d.ts.map +1 -0
  232. package/dist/connectors/telegram/commands/compaction.js +868 -0
  233. package/dist/connectors/telegram/commands/compaction.js.map +1 -0
  234. package/dist/connectors/telegram/commands/displayModes.d.ts +13 -0
  235. package/dist/connectors/telegram/commands/displayModes.d.ts.map +1 -0
  236. package/dist/connectors/telegram/commands/displayModes.js +335 -0
  237. package/dist/connectors/telegram/commands/displayModes.js.map +1 -0
  238. package/dist/connectors/telegram/commands/fallbackChain.d.ts +49 -0
  239. package/dist/connectors/telegram/commands/fallbackChain.d.ts.map +1 -0
  240. package/dist/connectors/telegram/commands/fallbackChain.js +624 -0
  241. package/dist/connectors/telegram/commands/fallbackChain.js.map +1 -0
  242. package/dist/connectors/telegram/commands/modelProviders.d.ts +117 -0
  243. package/dist/connectors/telegram/commands/modelProviders.d.ts.map +1 -0
  244. package/dist/connectors/telegram/commands/modelProviders.js +966 -0
  245. package/dist/connectors/telegram/commands/modelProviders.js.map +1 -0
  246. package/dist/connectors/telegram/commands/reminders.d.ts +54 -0
  247. package/dist/connectors/telegram/commands/reminders.d.ts.map +1 -0
  248. package/dist/connectors/telegram/commands/reminders.js +624 -0
  249. package/dist/connectors/telegram/commands/reminders.js.map +1 -0
  250. package/dist/connectors/telegram/fileIntake.d.ts +166 -0
  251. package/dist/connectors/telegram/fileIntake.d.ts.map +1 -0
  252. package/dist/connectors/telegram/fileIntake.js +304 -0
  253. package/dist/connectors/telegram/fileIntake.js.map +1 -0
  254. package/dist/connectors/telegram/fileSendGateway.d.ts +57 -0
  255. package/dist/connectors/telegram/fileSendGateway.d.ts.map +1 -0
  256. package/dist/connectors/telegram/fileSendGateway.js +221 -0
  257. package/dist/connectors/telegram/fileSendGateway.js.map +1 -0
  258. package/dist/connectors/telegram/foreignKeyFallbacks.d.ts +52 -0
  259. package/dist/connectors/telegram/foreignKeyFallbacks.d.ts.map +1 -0
  260. package/dist/connectors/telegram/foreignKeyFallbacks.js +71 -0
  261. package/dist/connectors/telegram/foreignKeyFallbacks.js.map +1 -0
  262. package/dist/connectors/telegram/inbound.d.ts +131 -0
  263. package/dist/connectors/telegram/inbound.d.ts.map +1 -0
  264. package/dist/connectors/telegram/inbound.js +278 -0
  265. package/dist/connectors/telegram/inbound.js.map +1 -0
  266. package/dist/connectors/telegram/languagePicker.d.ts +32 -0
  267. package/dist/connectors/telegram/languagePicker.d.ts.map +1 -0
  268. package/dist/connectors/telegram/languagePicker.js +55 -0
  269. package/dist/connectors/telegram/languagePicker.js.map +1 -0
  270. package/dist/connectors/telegram/messageSplit.d.ts +62 -0
  271. package/dist/connectors/telegram/messageSplit.d.ts.map +1 -0
  272. package/dist/connectors/telegram/messageSplit.js +119 -0
  273. package/dist/connectors/telegram/messageSplit.js.map +1 -0
  274. package/dist/connectors/telegram/outbound.d.ts +62 -0
  275. package/dist/connectors/telegram/outbound.d.ts.map +1 -0
  276. package/dist/connectors/telegram/outbound.js +116 -0
  277. package/dist/connectors/telegram/outbound.js.map +1 -0
  278. package/dist/connectors/telegram/output/createOutputTransport.d.ts +34 -0
  279. package/dist/connectors/telegram/output/createOutputTransport.d.ts.map +1 -0
  280. package/dist/connectors/telegram/output/createOutputTransport.js +77 -0
  281. package/dist/connectors/telegram/output/createOutputTransport.js.map +1 -0
  282. package/dist/connectors/telegram/output/dmOutputTransport.d.ts +47 -0
  283. package/dist/connectors/telegram/output/dmOutputTransport.d.ts.map +1 -0
  284. package/dist/connectors/telegram/output/dmOutputTransport.js +412 -0
  285. package/dist/connectors/telegram/output/dmOutputTransport.js.map +1 -0
  286. package/dist/connectors/telegram/outputBacklogGlue.d.ts +38 -0
  287. package/dist/connectors/telegram/outputBacklogGlue.d.ts.map +1 -0
  288. package/dist/connectors/telegram/outputBacklogGlue.js +49 -0
  289. package/dist/connectors/telegram/outputBacklogGlue.js.map +1 -0
  290. package/dist/connectors/telegram/outputFlushPlan.d.ts +93 -0
  291. package/dist/connectors/telegram/outputFlushPlan.d.ts.map +1 -0
  292. package/dist/connectors/telegram/outputFlushPlan.js +120 -0
  293. package/dist/connectors/telegram/outputFlushPlan.js.map +1 -0
  294. package/dist/connectors/telegram/questionKeyboards.d.ts +30 -0
  295. package/dist/connectors/telegram/questionKeyboards.d.ts.map +1 -0
  296. package/dist/connectors/telegram/questionKeyboards.js +37 -0
  297. package/dist/connectors/telegram/questionKeyboards.js.map +1 -0
  298. package/dist/connectors/telegram/renderAgentHtml.d.ts +27 -0
  299. package/dist/connectors/telegram/renderAgentHtml.d.ts.map +1 -0
  300. package/dist/connectors/telegram/renderAgentHtml.js +97 -0
  301. package/dist/connectors/telegram/renderAgentHtml.js.map +1 -0
  302. package/dist/connectors/telegram/sessionKeyCodec.d.ts +28 -0
  303. package/dist/connectors/telegram/sessionKeyCodec.d.ts.map +1 -0
  304. package/dist/connectors/telegram/sessionKeyCodec.js +107 -0
  305. package/dist/connectors/telegram/sessionKeyCodec.js.map +1 -0
  306. package/dist/connectors/telegram/telegramCallGuard.d.ts +19 -0
  307. package/dist/connectors/telegram/telegramCallGuard.d.ts.map +1 -0
  308. package/dist/connectors/telegram/telegramCallGuard.js +35 -0
  309. package/dist/connectors/telegram/telegramCallGuard.js.map +1 -0
  310. package/dist/connectors/telegram/timezonePicker.d.ts +85 -0
  311. package/dist/connectors/telegram/timezonePicker.d.ts.map +1 -0
  312. package/dist/connectors/telegram/timezonePicker.js +142 -0
  313. package/dist/connectors/telegram/timezonePicker.js.map +1 -0
  314. package/dist/connectors/telegram/updateDispatcher.d.ts +85 -0
  315. package/dist/connectors/telegram/updateDispatcher.d.ts.map +1 -0
  316. package/dist/connectors/telegram/updateDispatcher.js +159 -0
  317. package/dist/connectors/telegram/updateDispatcher.js.map +1 -0
  318. package/dist/connectors/test/connector.d.ts +52 -0
  319. package/dist/connectors/test/connector.d.ts.map +1 -0
  320. package/dist/connectors/test/connector.js +143 -0
  321. package/dist/connectors/test/connector.js.map +1 -0
  322. package/dist/connectors/test/sessionKeyCodec.d.ts +25 -0
  323. package/dist/connectors/test/sessionKeyCodec.d.ts.map +1 -0
  324. package/dist/connectors/test/sessionKeyCodec.js +50 -0
  325. package/dist/connectors/test/sessionKeyCodec.js.map +1 -0
  326. package/dist/diagLog.d.ts +6 -0
  327. package/dist/diagLog.d.ts.map +1 -0
  328. package/dist/diagLog.js +58 -0
  329. package/dist/diagLog.js.map +1 -0
  330. package/dist/effortLevels.d.ts +68 -0
  331. package/dist/effortLevels.d.ts.map +1 -0
  332. package/dist/effortLevels.js +114 -0
  333. package/dist/effortLevels.js.map +1 -0
  334. package/dist/folderName.d.ts +42 -0
  335. package/dist/folderName.d.ts.map +1 -0
  336. package/dist/folderName.js +51 -0
  337. package/dist/folderName.js.map +1 -0
  338. package/dist/i18n/de.d.ts +2 -0
  339. package/dist/i18n/de.d.ts.map +1 -0
  340. package/dist/i18n/de.js +665 -0
  341. package/dist/i18n/de.js.map +1 -0
  342. package/dist/i18n/en.d.ts +7 -0
  343. package/dist/i18n/en.d.ts.map +1 -0
  344. package/dist/i18n/en.js +694 -0
  345. package/dist/i18n/en.js.map +1 -0
  346. package/dist/i18n/es.d.ts +2 -0
  347. package/dist/i18n/es.d.ts.map +1 -0
  348. package/dist/i18n/es.js +665 -0
  349. package/dist/i18n/es.js.map +1 -0
  350. package/dist/i18n/fr.d.ts +2 -0
  351. package/dist/i18n/fr.d.ts.map +1 -0
  352. package/dist/i18n/fr.js +665 -0
  353. package/dist/i18n/fr.js.map +1 -0
  354. package/dist/i18n/hi.d.ts +2 -0
  355. package/dist/i18n/hi.d.ts.map +1 -0
  356. package/dist/i18n/hi.js +665 -0
  357. package/dist/i18n/hi.js.map +1 -0
  358. package/dist/i18n/ja.d.ts +2 -0
  359. package/dist/i18n/ja.d.ts.map +1 -0
  360. package/dist/i18n/ja.js +665 -0
  361. package/dist/i18n/ja.js.map +1 -0
  362. package/dist/i18n/ka.d.ts +2 -0
  363. package/dist/i18n/ka.d.ts.map +1 -0
  364. package/dist/i18n/ka.js +665 -0
  365. package/dist/i18n/ka.js.map +1 -0
  366. package/dist/i18n/pt.d.ts +2 -0
  367. package/dist/i18n/pt.d.ts.map +1 -0
  368. package/dist/i18n/pt.js +665 -0
  369. package/dist/i18n/pt.js.map +1 -0
  370. package/dist/i18n/ru.d.ts +6 -0
  371. package/dist/i18n/ru.d.ts.map +1 -0
  372. package/dist/i18n/ru.js +668 -0
  373. package/dist/i18n/ru.js.map +1 -0
  374. package/dist/i18n/uk.d.ts +8 -0
  375. package/dist/i18n/uk.d.ts.map +1 -0
  376. package/dist/i18n/uk.js +670 -0
  377. package/dist/i18n/uk.js.map +1 -0
  378. package/dist/i18n/uz.d.ts +2 -0
  379. package/dist/i18n/uz.d.ts.map +1 -0
  380. package/dist/i18n/uz.js +665 -0
  381. package/dist/i18n/uz.js.map +1 -0
  382. package/dist/i18n/zh.d.ts +2 -0
  383. package/dist/i18n/zh.d.ts.map +1 -0
  384. package/dist/i18n/zh.js +665 -0
  385. package/dist/i18n/zh.js.map +1 -0
  386. package/dist/i18n.d.ts +115 -0
  387. package/dist/i18n.d.ts.map +1 -0
  388. package/dist/i18n.js +233 -0
  389. package/dist/i18n.js.map +1 -0
  390. package/dist/index.d.ts +3 -0
  391. package/dist/index.d.ts.map +1 -0
  392. package/dist/index.js +10 -0
  393. package/dist/index.js.map +1 -0
  394. package/dist/installManager.d.ts +99 -0
  395. package/dist/installManager.d.ts.map +1 -0
  396. package/dist/installManager.js +943 -0
  397. package/dist/installManager.js.map +1 -0
  398. package/dist/instanceLock.d.ts +161 -0
  399. package/dist/instanceLock.d.ts.map +1 -0
  400. package/dist/instanceLock.js +388 -0
  401. package/dist/instanceLock.js.map +1 -0
  402. package/dist/mcpConfig.d.ts +76 -0
  403. package/dist/mcpConfig.d.ts.map +1 -0
  404. package/dist/mcpConfig.js +270 -0
  405. package/dist/mcpConfig.js.map +1 -0
  406. package/dist/openCodeOpenQuestion.d.ts +44 -0
  407. package/dist/openCodeOpenQuestion.d.ts.map +1 -0
  408. package/dist/openCodeOpenQuestion.js +64 -0
  409. package/dist/openCodeOpenQuestion.js.map +1 -0
  410. package/dist/openCodeQuestionFlow.d.ts +105 -0
  411. package/dist/openCodeQuestionFlow.d.ts.map +1 -0
  412. package/dist/openCodeQuestionFlow.js +143 -0
  413. package/dist/openCodeQuestionFlow.js.map +1 -0
  414. package/dist/openCodeSessionRouting.d.ts +133 -0
  415. package/dist/openCodeSessionRouting.d.ts.map +1 -0
  416. package/dist/openCodeSessionRouting.js +253 -0
  417. package/dist/openCodeSessionRouting.js.map +1 -0
  418. package/dist/openCodeSessionTitle.d.ts +50 -0
  419. package/dist/openCodeSessionTitle.d.ts.map +1 -0
  420. package/dist/openCodeSessionTitle.js +84 -0
  421. package/dist/openCodeSessionTitle.js.map +1 -0
  422. package/dist/outputTrace.d.ts +108 -0
  423. package/dist/outputTrace.d.ts.map +1 -0
  424. package/dist/outputTrace.js +430 -0
  425. package/dist/outputTrace.js.map +1 -0
  426. package/dist/pendingQuestionRepost.d.ts +47 -0
  427. package/dist/pendingQuestionRepost.d.ts.map +1 -0
  428. package/dist/pendingQuestionRepost.js +29 -0
  429. package/dist/pendingQuestionRepost.js.map +1 -0
  430. package/dist/pinnedStatus.d.ts +52 -0
  431. package/dist/pinnedStatus.d.ts.map +1 -0
  432. package/dist/pinnedStatus.js +36 -0
  433. package/dist/pinnedStatus.js.map +1 -0
  434. package/dist/platform/answerSink.d.ts +93 -0
  435. package/dist/platform/answerSink.d.ts.map +1 -0
  436. package/dist/platform/answerSink.js +31 -0
  437. package/dist/platform/answerSink.js.map +1 -0
  438. package/dist/platform/capabilityFallback.d.ts +39 -0
  439. package/dist/platform/capabilityFallback.d.ts.map +1 -0
  440. package/dist/platform/capabilityFallback.js +55 -0
  441. package/dist/platform/capabilityFallback.js.map +1 -0
  442. package/dist/platform/commandRouter.d.ts +51 -0
  443. package/dist/platform/commandRouter.d.ts.map +1 -0
  444. package/dist/platform/commandRouter.js +53 -0
  445. package/dist/platform/commandRouter.js.map +1 -0
  446. package/dist/platform/connectorSet.d.ts +39 -0
  447. package/dist/platform/connectorSet.d.ts.map +1 -0
  448. package/dist/platform/connectorSet.js +55 -0
  449. package/dist/platform/connectorSet.js.map +1 -0
  450. package/dist/platform/inbound.d.ts +147 -0
  451. package/dist/platform/inbound.d.ts.map +1 -0
  452. package/dist/platform/inbound.js +18 -0
  453. package/dist/platform/inbound.js.map +1 -0
  454. package/dist/platform/outbound.d.ts +225 -0
  455. package/dist/platform/outbound.d.ts.map +1 -0
  456. package/dist/platform/outbound.js +30 -0
  457. package/dist/platform/outbound.js.map +1 -0
  458. package/dist/platform/unservedStateGuard.d.ts +27 -0
  459. package/dist/platform/unservedStateGuard.d.ts.map +1 -0
  460. package/dist/platform/unservedStateGuard.js +42 -0
  461. package/dist/platform/unservedStateGuard.js.map +1 -0
  462. package/dist/postToSession.d.ts +94 -0
  463. package/dist/postToSession.d.ts.map +1 -0
  464. package/dist/postToSession.js +56 -0
  465. package/dist/postToSession.js.map +1 -0
  466. package/dist/progressLine.d.ts +180 -0
  467. package/dist/progressLine.d.ts.map +1 -0
  468. package/dist/progressLine.js +293 -0
  469. package/dist/progressLine.js.map +1 -0
  470. package/dist/rateLimiter.d.ts +246 -0
  471. package/dist/rateLimiter.d.ts.map +1 -0
  472. package/dist/rateLimiter.js +555 -0
  473. package/dist/rateLimiter.js.map +1 -0
  474. package/dist/requests/answerRequest.d.ts +57 -0
  475. package/dist/requests/answerRequest.d.ts.map +1 -0
  476. package/dist/requests/answerRequest.js +96 -0
  477. package/dist/requests/answerRequest.js.map +1 -0
  478. package/dist/requests/answerTail.d.ts +83 -0
  479. package/dist/requests/answerTail.d.ts.map +1 -0
  480. package/dist/requests/answerTail.js +102 -0
  481. package/dist/requests/answerTail.js.map +1 -0
  482. package/dist/requests/limitWaitAnswer.d.ts +87 -0
  483. package/dist/requests/limitWaitAnswer.d.ts.map +1 -0
  484. package/dist/requests/limitWaitAnswer.js +83 -0
  485. package/dist/requests/limitWaitAnswer.js.map +1 -0
  486. package/dist/requests/requestGroup.d.ts +44 -0
  487. package/dist/requests/requestGroup.d.ts.map +1 -0
  488. package/dist/requests/requestGroup.js +63 -0
  489. package/dist/requests/requestGroup.js.map +1 -0
  490. package/dist/requests/requestHeader.d.ts +70 -0
  491. package/dist/requests/requestHeader.d.ts.map +1 -0
  492. package/dist/requests/requestHeader.js +83 -0
  493. package/dist/requests/requestHeader.js.map +1 -0
  494. package/dist/requests/requestLedger.d.ts +217 -0
  495. package/dist/requests/requestLedger.d.ts.map +1 -0
  496. package/dist/requests/requestLedger.js +468 -0
  497. package/dist/requests/requestLedger.js.map +1 -0
  498. package/dist/requests/sessionTurnProbe.d.ts +52 -0
  499. package/dist/requests/sessionTurnProbe.d.ts.map +1 -0
  500. package/dist/requests/sessionTurnProbe.js +29 -0
  501. package/dist/requests/sessionTurnProbe.js.map +1 -0
  502. package/dist/requests/types.d.ts +181 -0
  503. package/dist/requests/types.d.ts.map +1 -0
  504. package/dist/requests/types.js +9 -0
  505. package/dist/requests/types.js.map +1 -0
  506. package/dist/requests/wakeUpEngine.d.ts +160 -0
  507. package/dist/requests/wakeUpEngine.d.ts.map +1 -0
  508. package/dist/requests/wakeUpEngine.js +399 -0
  509. package/dist/requests/wakeUpEngine.js.map +1 -0
  510. package/dist/requests/wakeUpRules.d.ts +151 -0
  511. package/dist/requests/wakeUpRules.d.ts.map +1 -0
  512. package/dist/requests/wakeUpRules.js +167 -0
  513. package/dist/requests/wakeUpRules.js.map +1 -0
  514. package/dist/resumeContext.d.ts +87 -0
  515. package/dist/resumeContext.d.ts.map +1 -0
  516. package/dist/resumeContext.js +114 -0
  517. package/dist/resumeContext.js.map +1 -0
  518. package/dist/scheduler/checkRun.d.ts +95 -0
  519. package/dist/scheduler/checkRun.d.ts.map +1 -0
  520. package/dist/scheduler/checkRun.js +172 -0
  521. package/dist/scheduler/checkRun.js.map +1 -0
  522. package/dist/scheduler/delivery.d.ts +99 -0
  523. package/dist/scheduler/delivery.d.ts.map +1 -0
  524. package/dist/scheduler/delivery.js +212 -0
  525. package/dist/scheduler/delivery.js.map +1 -0
  526. package/dist/scheduler/deliveryKind.d.ts +29 -0
  527. package/dist/scheduler/deliveryKind.d.ts.map +1 -0
  528. package/dist/scheduler/deliveryKind.js +39 -0
  529. package/dist/scheduler/deliveryKind.js.map +1 -0
  530. package/dist/scheduler/directoryThreads.d.ts +19 -0
  531. package/dist/scheduler/directoryThreads.d.ts.map +1 -0
  532. package/dist/scheduler/directoryThreads.js +28 -0
  533. package/dist/scheduler/directoryThreads.js.map +1 -0
  534. package/dist/scheduler/engine.d.ts +77 -0
  535. package/dist/scheduler/engine.d.ts.map +1 -0
  536. package/dist/scheduler/engine.js +337 -0
  537. package/dist/scheduler/engine.js.map +1 -0
  538. package/dist/scheduler/injection.d.ts +102 -0
  539. package/dist/scheduler/injection.d.ts.map +1 -0
  540. package/dist/scheduler/injection.js +122 -0
  541. package/dist/scheduler/injection.js.map +1 -0
  542. package/dist/scheduler/mcpBoot.d.ts +65 -0
  543. package/dist/scheduler/mcpBoot.d.ts.map +1 -0
  544. package/dist/scheduler/mcpBoot.js +60 -0
  545. package/dist/scheduler/mcpBoot.js.map +1 -0
  546. package/dist/scheduler/mcpSurface.d.ts +363 -0
  547. package/dist/scheduler/mcpSurface.d.ts.map +1 -0
  548. package/dist/scheduler/mcpSurface.js +1297 -0
  549. package/dist/scheduler/mcpSurface.js.map +1 -0
  550. package/dist/scheduler/rebindResume.d.ts +27 -0
  551. package/dist/scheduler/rebindResume.d.ts.map +1 -0
  552. package/dist/scheduler/rebindResume.js +17 -0
  553. package/dist/scheduler/rebindResume.js.map +1 -0
  554. package/dist/scheduler/recurrence.d.ts +58 -0
  555. package/dist/scheduler/recurrence.d.ts.map +1 -0
  556. package/dist/scheduler/recurrence.js +210 -0
  557. package/dist/scheduler/recurrence.js.map +1 -0
  558. package/dist/scheduler/runLedger.d.ts +59 -0
  559. package/dist/scheduler/runLedger.d.ts.map +1 -0
  560. package/dist/scheduler/runLedger.js +54 -0
  561. package/dist/scheduler/runLedger.js.map +1 -0
  562. package/dist/scheduler/store.d.ts +97 -0
  563. package/dist/scheduler/store.d.ts.map +1 -0
  564. package/dist/scheduler/store.js +124 -0
  565. package/dist/scheduler/store.js.map +1 -0
  566. package/dist/scheduler/timezoneRecompute.d.ts +61 -0
  567. package/dist/scheduler/timezoneRecompute.d.ts.map +1 -0
  568. package/dist/scheduler/timezoneRecompute.js +46 -0
  569. package/dist/scheduler/timezoneRecompute.js.map +1 -0
  570. package/dist/scheduler/types.d.ts +139 -0
  571. package/dist/scheduler/types.d.ts.map +1 -0
  572. package/dist/scheduler/types.js +8 -0
  573. package/dist/scheduler/types.js.map +1 -0
  574. package/dist/sendErrorClassifier.d.ts +45 -0
  575. package/dist/sendErrorClassifier.d.ts.map +1 -0
  576. package/dist/sendErrorClassifier.js +65 -0
  577. package/dist/sendErrorClassifier.js.map +1 -0
  578. package/dist/sessionKey.d.ts +136 -0
  579. package/dist/sessionKey.d.ts.map +1 -0
  580. package/dist/sessionKey.js +153 -0
  581. package/dist/sessionKey.js.map +1 -0
  582. package/dist/sessionPick.d.ts +42 -0
  583. package/dist/sessionPick.d.ts.map +1 -0
  584. package/dist/sessionPick.js +39 -0
  585. package/dist/sessionPick.js.map +1 -0
  586. package/dist/shutdown.d.ts +126 -0
  587. package/dist/shutdown.d.ts.map +1 -0
  588. package/dist/shutdown.js +164 -0
  589. package/dist/shutdown.js.map +1 -0
  590. package/dist/startupPromptBuffer.d.ts +85 -0
  591. package/dist/startupPromptBuffer.d.ts.map +1 -0
  592. package/dist/startupPromptBuffer.js +123 -0
  593. package/dist/startupPromptBuffer.js.map +1 -0
  594. package/dist/state.d.ts +1416 -0
  595. package/dist/state.d.ts.map +1 -0
  596. package/dist/state.js +2128 -0
  597. package/dist/state.js.map +1 -0
  598. package/dist/threadContextPreamble.d.ts +89 -0
  599. package/dist/threadContextPreamble.d.ts.map +1 -0
  600. package/dist/threadContextPreamble.js +102 -0
  601. package/dist/threadContextPreamble.js.map +1 -0
  602. package/dist/threadRouting.d.ts +164 -0
  603. package/dist/threadRouting.d.ts.map +1 -0
  604. package/dist/threadRouting.js +182 -0
  605. package/dist/threadRouting.js.map +1 -0
  606. package/dist/types.d.ts +1022 -0
  607. package/dist/types.d.ts.map +1 -0
  608. package/dist/types.js +3 -0
  609. package/dist/types.js.map +1 -0
  610. package/dist/utils/abortableFifo.d.ts +10 -0
  611. package/dist/utils/abortableFifo.d.ts.map +1 -0
  612. package/dist/utils/abortableFifo.js +55 -0
  613. package/dist/utils/abortableFifo.js.map +1 -0
  614. package/dist/utils/adoptedToolList.d.ts +27 -0
  615. package/dist/utils/adoptedToolList.d.ts.map +1 -0
  616. package/dist/utils/adoptedToolList.js +22 -0
  617. package/dist/utils/adoptedToolList.js.map +1 -0
  618. package/dist/utils/agentEnvironment.d.ts +42 -0
  619. package/dist/utils/agentEnvironment.d.ts.map +1 -0
  620. package/dist/utils/agentEnvironment.js +122 -0
  621. package/dist/utils/agentEnvironment.js.map +1 -0
  622. package/dist/utils/ansiClean.d.ts +11 -0
  623. package/dist/utils/ansiClean.d.ts.map +1 -0
  624. package/dist/utils/ansiClean.js +139 -0
  625. package/dist/utils/ansiClean.js.map +1 -0
  626. package/dist/utils/autoContinueOnLimit.d.ts +56 -0
  627. package/dist/utils/autoContinueOnLimit.d.ts.map +1 -0
  628. package/dist/utils/autoContinueOnLimit.js +79 -0
  629. package/dist/utils/autoContinueOnLimit.js.map +1 -0
  630. package/dist/utils/canonicalPathContainment.d.ts +7 -0
  631. package/dist/utils/canonicalPathContainment.d.ts.map +1 -0
  632. package/dist/utils/canonicalPathContainment.js +48 -0
  633. package/dist/utils/canonicalPathContainment.js.map +1 -0
  634. package/dist/utils/claudeAccountPickerPlan.d.ts +85 -0
  635. package/dist/utils/claudeAccountPickerPlan.d.ts.map +1 -0
  636. package/dist/utils/claudeAccountPickerPlan.js +123 -0
  637. package/dist/utils/claudeAccountPickerPlan.js.map +1 -0
  638. package/dist/utils/claudeAuthLogin.d.ts +71 -0
  639. package/dist/utils/claudeAuthLogin.d.ts.map +1 -0
  640. package/dist/utils/claudeAuthLogin.js +93 -0
  641. package/dist/utils/claudeAuthLogin.js.map +1 -0
  642. package/dist/utils/claudeChunkClassifier.d.ts +97 -0
  643. package/dist/utils/claudeChunkClassifier.d.ts.map +1 -0
  644. package/dist/utils/claudeChunkClassifier.js +254 -0
  645. package/dist/utils/claudeChunkClassifier.js.map +1 -0
  646. package/dist/utils/claudeCodeVersion.d.ts +31 -0
  647. package/dist/utils/claudeCodeVersion.d.ts.map +1 -0
  648. package/dist/utils/claudeCodeVersion.js +62 -0
  649. package/dist/utils/claudeCodeVersion.js.map +1 -0
  650. package/dist/utils/claudeCompactHook.d.ts +64 -0
  651. package/dist/utils/claudeCompactHook.d.ts.map +1 -0
  652. package/dist/utils/claudeCompactHook.js +98 -0
  653. package/dist/utils/claudeCompactHook.js.map +1 -0
  654. package/dist/utils/claudeLimitSwitch.d.ts +40 -0
  655. package/dist/utils/claudeLimitSwitch.d.ts.map +1 -0
  656. package/dist/utils/claudeLimitSwitch.js +54 -0
  657. package/dist/utils/claudeLimitSwitch.js.map +1 -0
  658. package/dist/utils/claudeLivenessAction.d.ts +208 -0
  659. package/dist/utils/claudeLivenessAction.d.ts.map +1 -0
  660. package/dist/utils/claudeLivenessAction.js +135 -0
  661. package/dist/utils/claudeLivenessAction.js.map +1 -0
  662. package/dist/utils/claudeMcpHeal.d.ts +92 -0
  663. package/dist/utils/claudeMcpHeal.d.ts.map +1 -0
  664. package/dist/utils/claudeMcpHeal.js +91 -0
  665. package/dist/utils/claudeMcpHeal.js.map +1 -0
  666. package/dist/utils/claudeProfileUsageLines.d.ts +15 -0
  667. package/dist/utils/claudeProfileUsageLines.d.ts.map +1 -0
  668. package/dist/utils/claudeProfileUsageLines.js +42 -0
  669. package/dist/utils/claudeProfileUsageLines.js.map +1 -0
  670. package/dist/utils/claudeProfiles.d.ts +117 -0
  671. package/dist/utils/claudeProfiles.d.ts.map +1 -0
  672. package/dist/utils/claudeProfiles.js +285 -0
  673. package/dist/utils/claudeProfiles.js.map +1 -0
  674. package/dist/utils/claudeRelayRouting.d.ts +86 -0
  675. package/dist/utils/claudeRelayRouting.d.ts.map +1 -0
  676. package/dist/utils/claudeRelayRouting.js +159 -0
  677. package/dist/utils/claudeRelayRouting.js.map +1 -0
  678. package/dist/utils/claudeRuntimeInfo.d.ts +26 -0
  679. package/dist/utils/claudeRuntimeInfo.d.ts.map +1 -0
  680. package/dist/utils/claudeRuntimeInfo.js +151 -0
  681. package/dist/utils/claudeRuntimeInfo.js.map +1 -0
  682. package/dist/utils/claudeScrapeShapes.d.ts +256 -0
  683. package/dist/utils/claudeScrapeShapes.d.ts.map +1 -0
  684. package/dist/utils/claudeScrapeShapes.js +290 -0
  685. package/dist/utils/claudeScrapeShapes.js.map +1 -0
  686. package/dist/utils/claudeSessionTitle.d.ts +27 -0
  687. package/dist/utils/claudeSessionTitle.d.ts.map +1 -0
  688. package/dist/utils/claudeSessionTitle.js +90 -0
  689. package/dist/utils/claudeSessionTitle.js.map +1 -0
  690. package/dist/utils/claudeStreamJson.d.ts +214 -0
  691. package/dist/utils/claudeStreamJson.d.ts.map +1 -0
  692. package/dist/utils/claudeStreamJson.js +364 -0
  693. package/dist/utils/claudeStreamJson.js.map +1 -0
  694. package/dist/utils/claudeSubagentTail.d.ts +93 -0
  695. package/dist/utils/claudeSubagentTail.d.ts.map +1 -0
  696. package/dist/utils/claudeSubagentTail.js +136 -0
  697. package/dist/utils/claudeSubagentTail.js.map +1 -0
  698. package/dist/utils/claudeUsage.d.ts +209 -0
  699. package/dist/utils/claudeUsage.d.ts.map +1 -0
  700. package/dist/utils/claudeUsage.js +413 -0
  701. package/dist/utils/claudeUsage.js.map +1 -0
  702. package/dist/utils/claudeUsageRefresher.d.ts +44 -0
  703. package/dist/utils/claudeUsageRefresher.d.ts.map +1 -0
  704. package/dist/utils/claudeUsageRefresher.js +95 -0
  705. package/dist/utils/claudeUsageRefresher.js.map +1 -0
  706. package/dist/utils/clearThreadOutputQueues.d.ts +43 -0
  707. package/dist/utils/clearThreadOutputQueues.d.ts.map +1 -0
  708. package/dist/utils/clearThreadOutputQueues.js +39 -0
  709. package/dist/utils/clearThreadOutputQueues.js.map +1 -0
  710. package/dist/utils/compactCommandRoute.d.ts +45 -0
  711. package/dist/utils/compactCommandRoute.d.ts.map +1 -0
  712. package/dist/utils/compactCommandRoute.js +36 -0
  713. package/dist/utils/compactCommandRoute.js.map +1 -0
  714. package/dist/utils/compactOnIdle.d.ts +329 -0
  715. package/dist/utils/compactOnIdle.d.ts.map +1 -0
  716. package/dist/utils/compactOnIdle.js +379 -0
  717. package/dist/utils/compactOnIdle.js.map +1 -0
  718. package/dist/utils/consoleFileTap.d.ts +51 -0
  719. package/dist/utils/consoleFileTap.d.ts.map +1 -0
  720. package/dist/utils/consoleFileTap.js +86 -0
  721. package/dist/utils/consoleFileTap.js.map +1 -0
  722. package/dist/utils/displayVerbosity.d.ts +44 -0
  723. package/dist/utils/displayVerbosity.d.ts.map +1 -0
  724. package/dist/utils/displayVerbosity.js +75 -0
  725. package/dist/utils/displayVerbosity.js.map +1 -0
  726. package/dist/utils/download.d.ts +72 -0
  727. package/dist/utils/download.d.ts.map +1 -0
  728. package/dist/utils/download.js +216 -0
  729. package/dist/utils/download.js.map +1 -0
  730. package/dist/utils/draftFinalize.d.ts +110 -0
  731. package/dist/utils/draftFinalize.d.ts.map +1 -0
  732. package/dist/utils/draftFinalize.js +100 -0
  733. package/dist/utils/draftFinalize.js.map +1 -0
  734. package/dist/utils/draftId.d.ts +36 -0
  735. package/dist/utils/draftId.d.ts.map +1 -0
  736. package/dist/utils/draftId.js +46 -0
  737. package/dist/utils/draftId.js.map +1 -0
  738. package/dist/utils/draftPacer.d.ts +72 -0
  739. package/dist/utils/draftPacer.d.ts.map +1 -0
  740. package/dist/utils/draftPacer.js +53 -0
  741. package/dist/utils/draftPacer.js.map +1 -0
  742. package/dist/utils/effortStartupKeystroke.d.ts +20 -0
  743. package/dist/utils/effortStartupKeystroke.d.ts.map +1 -0
  744. package/dist/utils/effortStartupKeystroke.js +28 -0
  745. package/dist/utils/effortStartupKeystroke.js.map +1 -0
  746. package/dist/utils/ensureSessionPlan.d.ts +70 -0
  747. package/dist/utils/ensureSessionPlan.d.ts.map +1 -0
  748. package/dist/utils/ensureSessionPlan.js +54 -0
  749. package/dist/utils/ensureSessionPlan.js.map +1 -0
  750. package/dist/utils/fallbackBridge.d.ts +32 -0
  751. package/dist/utils/fallbackBridge.d.ts.map +1 -0
  752. package/dist/utils/fallbackBridge.js +62 -0
  753. package/dist/utils/fallbackBridge.js.map +1 -0
  754. package/dist/utils/fallbackChain.d.ts +299 -0
  755. package/dist/utils/fallbackChain.d.ts.map +1 -0
  756. package/dist/utils/fallbackChain.js +542 -0
  757. package/dist/utils/fallbackChain.js.map +1 -0
  758. package/dist/utils/fileSendPlan.d.ts +217 -0
  759. package/dist/utils/fileSendPlan.d.ts.map +1 -0
  760. package/dist/utils/fileSendPlan.js +291 -0
  761. package/dist/utils/fileSendPlan.js.map +1 -0
  762. package/dist/utils/fileSendService.d.ts +94 -0
  763. package/dist/utils/fileSendService.d.ts.map +1 -0
  764. package/dist/utils/fileSendService.js +387 -0
  765. package/dist/utils/fileSendService.js.map +1 -0
  766. package/dist/utils/groupFinalizePlan.d.ts +38 -0
  767. package/dist/utils/groupFinalizePlan.d.ts.map +1 -0
  768. package/dist/utils/groupFinalizePlan.js +35 -0
  769. package/dist/utils/groupFinalizePlan.js.map +1 -0
  770. package/dist/utils/identicalOutputGuard.d.ts +83 -0
  771. package/dist/utils/identicalOutputGuard.d.ts.map +1 -0
  772. package/dist/utils/identicalOutputGuard.js +99 -0
  773. package/dist/utils/identicalOutputGuard.js.map +1 -0
  774. package/dist/utils/isoTimestamp.d.ts +16 -0
  775. package/dist/utils/isoTimestamp.d.ts.map +1 -0
  776. package/dist/utils/isoTimestamp.js +34 -0
  777. package/dist/utils/isoTimestamp.js.map +1 -0
  778. package/dist/utils/jsonStreamBusyWatchdog.d.ts +130 -0
  779. package/dist/utils/jsonStreamBusyWatchdog.d.ts.map +1 -0
  780. package/dist/utils/jsonStreamBusyWatchdog.js +122 -0
  781. package/dist/utils/jsonStreamBusyWatchdog.js.map +1 -0
  782. package/dist/utils/jsonStreamHost.d.ts +238 -0
  783. package/dist/utils/jsonStreamHost.d.ts.map +1 -0
  784. package/dist/utils/jsonStreamHost.js +438 -0
  785. package/dist/utils/jsonStreamHost.js.map +1 -0
  786. package/dist/utils/keyedTransitionQueue.d.ts +18 -0
  787. package/dist/utils/keyedTransitionQueue.d.ts.map +1 -0
  788. package/dist/utils/keyedTransitionQueue.js +34 -0
  789. package/dist/utils/keyedTransitionQueue.js.map +1 -0
  790. package/dist/utils/limitEpisodeRecovery.d.ts +92 -0
  791. package/dist/utils/limitEpisodeRecovery.d.ts.map +1 -0
  792. package/dist/utils/limitEpisodeRecovery.js +133 -0
  793. package/dist/utils/limitEpisodeRecovery.js.map +1 -0
  794. package/dist/utils/limitHeldPromptQueue.d.ts +48 -0
  795. package/dist/utils/limitHeldPromptQueue.d.ts.map +1 -0
  796. package/dist/utils/limitHeldPromptQueue.js +59 -0
  797. package/dist/utils/limitHeldPromptQueue.js.map +1 -0
  798. package/dist/utils/limitHeldPrompts.d.ts +58 -0
  799. package/dist/utils/limitHeldPrompts.d.ts.map +1 -0
  800. package/dist/utils/limitHeldPrompts.js +65 -0
  801. package/dist/utils/limitHeldPrompts.js.map +1 -0
  802. package/dist/utils/linkPreviewSuppression.d.ts +18 -0
  803. package/dist/utils/linkPreviewSuppression.d.ts.map +1 -0
  804. package/dist/utils/linkPreviewSuppression.js +37 -0
  805. package/dist/utils/linkPreviewSuppression.js.map +1 -0
  806. package/dist/utils/localClock.d.ts +15 -0
  807. package/dist/utils/localClock.d.ts.map +1 -0
  808. package/dist/utils/localClock.js +29 -0
  809. package/dist/utils/localClock.js.map +1 -0
  810. package/dist/utils/markdownTableRender.d.ts +83 -0
  811. package/dist/utils/markdownTableRender.d.ts.map +1 -0
  812. package/dist/utils/markdownTableRender.js +298 -0
  813. package/dist/utils/markdownTableRender.js.map +1 -0
  814. package/dist/utils/mediaGroupCollector.d.ts +51 -0
  815. package/dist/utils/mediaGroupCollector.d.ts.map +1 -0
  816. package/dist/utils/mediaGroupCollector.js +90 -0
  817. package/dist/utils/mediaGroupCollector.js.map +1 -0
  818. package/dist/utils/messageSendService.d.ts +136 -0
  819. package/dist/utils/messageSendService.d.ts.map +1 -0
  820. package/dist/utils/messageSendService.js +165 -0
  821. package/dist/utils/messageSendService.js.map +1 -0
  822. package/dist/utils/minutesOverride.d.ts +7 -0
  823. package/dist/utils/minutesOverride.d.ts.map +1 -0
  824. package/dist/utils/minutesOverride.js +16 -0
  825. package/dist/utils/minutesOverride.js.map +1 -0
  826. package/dist/utils/modelPickerPlan.d.ts +119 -0
  827. package/dist/utils/modelPickerPlan.d.ts.map +1 -0
  828. package/dist/utils/modelPickerPlan.js +171 -0
  829. package/dist/utils/modelPickerPlan.js.map +1 -0
  830. package/dist/utils/modelRecentPlan.d.ts +56 -0
  831. package/dist/utils/modelRecentPlan.d.ts.map +1 -0
  832. package/dist/utils/modelRecentPlan.js +107 -0
  833. package/dist/utils/modelRecentPlan.js.map +1 -0
  834. package/dist/utils/modelSetReplyDecision.d.ts +67 -0
  835. package/dist/utils/modelSetReplyDecision.d.ts.map +1 -0
  836. package/dist/utils/modelSetReplyDecision.js +27 -0
  837. package/dist/utils/modelSetReplyDecision.js.map +1 -0
  838. package/dist/utils/openCodeAuthLogin.d.ts +181 -0
  839. package/dist/utils/openCodeAuthLogin.d.ts.map +1 -0
  840. package/dist/utils/openCodeAuthLogin.js +393 -0
  841. package/dist/utils/openCodeAuthLogin.js.map +1 -0
  842. package/dist/utils/openCodeCompactPlugin.d.ts +81 -0
  843. package/dist/utils/openCodeCompactPlugin.d.ts.map +1 -0
  844. package/dist/utils/openCodeCompactPlugin.js +146 -0
  845. package/dist/utils/openCodeCompactPlugin.js.map +1 -0
  846. package/dist/utils/openCodeTurnActivity.d.ts +67 -0
  847. package/dist/utils/openCodeTurnActivity.d.ts.map +1 -0
  848. package/dist/utils/openCodeTurnActivity.js +27 -0
  849. package/dist/utils/openCodeTurnActivity.js.map +1 -0
  850. package/dist/utils/outputDebounce.d.ts +24 -0
  851. package/dist/utils/outputDebounce.d.ts.map +1 -0
  852. package/dist/utils/outputDebounce.js +30 -0
  853. package/dist/utils/outputDebounce.js.map +1 -0
  854. package/dist/utils/outputFlushTiming.d.ts +54 -0
  855. package/dist/utils/outputFlushTiming.d.ts.map +1 -0
  856. package/dist/utils/outputFlushTiming.js +48 -0
  857. package/dist/utils/outputFlushTiming.js.map +1 -0
  858. package/dist/utils/paginateList.d.ts +25 -0
  859. package/dist/utils/paginateList.d.ts.map +1 -0
  860. package/dist/utils/paginateList.js +32 -0
  861. package/dist/utils/paginateList.js.map +1 -0
  862. package/dist/utils/paneDiff.d.ts +55 -0
  863. package/dist/utils/paneDiff.d.ts.map +1 -0
  864. package/dist/utils/paneDiff.js +88 -0
  865. package/dist/utils/paneDiff.js.map +1 -0
  866. package/dist/utils/paneResizeGuard.d.ts +69 -0
  867. package/dist/utils/paneResizeGuard.d.ts.map +1 -0
  868. package/dist/utils/paneResizeGuard.js +91 -0
  869. package/dist/utils/paneResizeGuard.js.map +1 -0
  870. package/dist/utils/persistAdapterSessionIds.d.ts +39 -0
  871. package/dist/utils/persistAdapterSessionIds.d.ts.map +1 -0
  872. package/dist/utils/persistAdapterSessionIds.js +28 -0
  873. package/dist/utils/persistAdapterSessionIds.js.map +1 -0
  874. package/dist/utils/pinnedBannerSkipDecision.d.ts +44 -0
  875. package/dist/utils/pinnedBannerSkipDecision.d.ts.map +1 -0
  876. package/dist/utils/pinnedBannerSkipDecision.js +20 -0
  877. package/dist/utils/pinnedBannerSkipDecision.js.map +1 -0
  878. package/dist/utils/pollBackoff.d.ts +45 -0
  879. package/dist/utils/pollBackoff.d.ts.map +1 -0
  880. package/dist/utils/pollBackoff.js +44 -0
  881. package/dist/utils/pollBackoff.js.map +1 -0
  882. package/dist/utils/promptDelivery.d.ts +46 -0
  883. package/dist/utils/promptDelivery.d.ts.map +1 -0
  884. package/dist/utils/promptDelivery.js +49 -0
  885. package/dist/utils/promptDelivery.js.map +1 -0
  886. package/dist/utils/providerDisconnectPlan.d.ts +82 -0
  887. package/dist/utils/providerDisconnectPlan.d.ts.map +1 -0
  888. package/dist/utils/providerDisconnectPlan.js +110 -0
  889. package/dist/utils/providerDisconnectPlan.js.map +1 -0
  890. package/dist/utils/rateLimitLog.d.ts +48 -0
  891. package/dist/utils/rateLimitLog.d.ts.map +1 -0
  892. package/dist/utils/rateLimitLog.js +43 -0
  893. package/dist/utils/rateLimitLog.js.map +1 -0
  894. package/dist/utils/recentRelayWindow.d.ts +165 -0
  895. package/dist/utils/recentRelayWindow.d.ts.map +1 -0
  896. package/dist/utils/recentRelayWindow.js +284 -0
  897. package/dist/utils/recentRelayWindow.js.map +1 -0
  898. package/dist/utils/recvPreviewRedaction.d.ts +23 -0
  899. package/dist/utils/recvPreviewRedaction.d.ts.map +1 -0
  900. package/dist/utils/recvPreviewRedaction.js +39 -0
  901. package/dist/utils/recvPreviewRedaction.js.map +1 -0
  902. package/dist/utils/reminderFlow.d.ts +148 -0
  903. package/dist/utils/reminderFlow.d.ts.map +1 -0
  904. package/dist/utils/reminderFlow.js +122 -0
  905. package/dist/utils/reminderFlow.js.map +1 -0
  906. package/dist/utils/reminderScheduleText.d.ts +87 -0
  907. package/dist/utils/reminderScheduleText.d.ts.map +1 -0
  908. package/dist/utils/reminderScheduleText.js +135 -0
  909. package/dist/utils/reminderScheduleText.js.map +1 -0
  910. package/dist/utils/reminderWizard.d.ts +710 -0
  911. package/dist/utils/reminderWizard.d.ts.map +1 -0
  912. package/dist/utils/reminderWizard.js +1164 -0
  913. package/dist/utils/reminderWizard.js.map +1 -0
  914. package/dist/utils/replyQuote.d.ts +111 -0
  915. package/dist/utils/replyQuote.d.ts.map +1 -0
  916. package/dist/utils/replyQuote.js +122 -0
  917. package/dist/utils/replyQuote.js.map +1 -0
  918. package/dist/utils/resolveBinary.d.ts +25 -0
  919. package/dist/utils/resolveBinary.d.ts.map +1 -0
  920. package/dist/utils/resolveBinary.js +99 -0
  921. package/dist/utils/resolveBinary.js.map +1 -0
  922. package/dist/utils/retryAfterHeader.d.ts +7 -0
  923. package/dist/utils/retryAfterHeader.d.ts.map +1 -0
  924. package/dist/utils/retryAfterHeader.js +17 -0
  925. package/dist/utils/retryAfterHeader.js.map +1 -0
  926. package/dist/utils/rotatingJsonlFile.d.ts +40 -0
  927. package/dist/utils/rotatingJsonlFile.d.ts.map +1 -0
  928. package/dist/utils/rotatingJsonlFile.js +106 -0
  929. package/dist/utils/rotatingJsonlFile.js.map +1 -0
  930. package/dist/utils/rotatingLogFile.d.ts +25 -0
  931. package/dist/utils/rotatingLogFile.d.ts.map +1 -0
  932. package/dist/utils/rotatingLogFile.js +74 -0
  933. package/dist/utils/rotatingLogFile.js.map +1 -0
  934. package/dist/utils/sendRateTracker.d.ts +59 -0
  935. package/dist/utils/sendRateTracker.d.ts.map +1 -0
  936. package/dist/utils/sendRateTracker.js +144 -0
  937. package/dist/utils/sendRateTracker.js.map +1 -0
  938. package/dist/utils/serialQueue.d.ts +5 -0
  939. package/dist/utils/serialQueue.d.ts.map +1 -0
  940. package/dist/utils/serialQueue.js +14 -0
  941. package/dist/utils/serialQueue.js.map +1 -0
  942. package/dist/utils/sseStreamLifecycle.d.ts +32 -0
  943. package/dist/utils/sseStreamLifecycle.d.ts.map +1 -0
  944. package/dist/utils/sseStreamLifecycle.js +41 -0
  945. package/dist/utils/sseStreamLifecycle.js.map +1 -0
  946. package/dist/utils/startupReadiness.d.ts +119 -0
  947. package/dist/utils/startupReadiness.d.ts.map +1 -0
  948. package/dist/utils/startupReadiness.js +148 -0
  949. package/dist/utils/startupReadiness.js.map +1 -0
  950. package/dist/utils/statusFlushDecision.d.ts +18 -0
  951. package/dist/utils/statusFlushDecision.d.ts.map +1 -0
  952. package/dist/utils/statusFlushDecision.js +53 -0
  953. package/dist/utils/statusFlushDecision.js.map +1 -0
  954. package/dist/utils/subagentRender.d.ts +52 -0
  955. package/dist/utils/subagentRender.d.ts.map +1 -0
  956. package/dist/utils/subagentRender.js +66 -0
  957. package/dist/utils/subagentRender.js.map +1 -0
  958. package/dist/utils/subagentStatusRender.d.ts +90 -0
  959. package/dist/utils/subagentStatusRender.d.ts.map +1 -0
  960. package/dist/utils/subagentStatusRender.js +124 -0
  961. package/dist/utils/subagentStatusRender.js.map +1 -0
  962. package/dist/utils/telegramError.d.ts +2 -0
  963. package/dist/utils/telegramError.d.ts.map +1 -0
  964. package/dist/utils/telegramError.js +16 -0
  965. package/dist/utils/telegramError.js.map +1 -0
  966. package/dist/utils/terminalEmitPlan.d.ts +74 -0
  967. package/dist/utils/terminalEmitPlan.d.ts.map +1 -0
  968. package/dist/utils/terminalEmitPlan.js +86 -0
  969. package/dist/utils/terminalEmitPlan.js.map +1 -0
  970. package/dist/utils/thinkingRender.d.ts +74 -0
  971. package/dist/utils/thinkingRender.d.ts.map +1 -0
  972. package/dist/utils/thinkingRender.js +85 -0
  973. package/dist/utils/thinkingRender.js.map +1 -0
  974. package/dist/utils/threadStatusReport.d.ts +79 -0
  975. package/dist/utils/threadStatusReport.d.ts.map +1 -0
  976. package/dist/utils/threadStatusReport.js +88 -0
  977. package/dist/utils/threadStatusReport.js.map +1 -0
  978. package/dist/utils/threadToggle.d.ts +29 -0
  979. package/dist/utils/threadToggle.d.ts.map +1 -0
  980. package/dist/utils/threadToggle.js +39 -0
  981. package/dist/utils/threadToggle.js.map +1 -0
  982. package/dist/utils/timezone.d.ts +125 -0
  983. package/dist/utils/timezone.d.ts.map +1 -0
  984. package/dist/utils/timezone.js +278 -0
  985. package/dist/utils/timezone.js.map +1 -0
  986. package/dist/utils/tmuxExec.d.ts +61 -0
  987. package/dist/utils/tmuxExec.d.ts.map +1 -0
  988. package/dist/utils/tmuxExec.js +109 -0
  989. package/dist/utils/tmuxExec.js.map +1 -0
  990. package/dist/utils/tmuxSessionName.d.ts +34 -0
  991. package/dist/utils/tmuxSessionName.d.ts.map +1 -0
  992. package/dist/utils/tmuxSessionName.js +51 -0
  993. package/dist/utils/tmuxSessionName.js.map +1 -0
  994. package/dist/utils/toolResultRender.d.ts +61 -0
  995. package/dist/utils/toolResultRender.d.ts.map +1 -0
  996. package/dist/utils/toolResultRender.js +62 -0
  997. package/dist/utils/toolResultRender.js.map +1 -0
  998. package/dist/utils/topicRequest.d.ts +61 -0
  999. package/dist/utils/topicRequest.d.ts.map +1 -0
  1000. package/dist/utils/topicRequest.js +68 -0
  1001. package/dist/utils/topicRequest.js.map +1 -0
  1002. package/dist/utils/topicView.d.ts +55 -0
  1003. package/dist/utils/topicView.d.ts.map +1 -0
  1004. package/dist/utils/topicView.js +56 -0
  1005. package/dist/utils/topicView.js.map +1 -0
  1006. package/dist/utils/transcribeAudio.d.ts +89 -0
  1007. package/dist/utils/transcribeAudio.d.ts.map +1 -0
  1008. package/dist/utils/transcribeAudio.js +249 -0
  1009. package/dist/utils/transcribeAudio.js.map +1 -0
  1010. package/dist/utils/transientFrames.d.ts +52 -0
  1011. package/dist/utils/transientFrames.d.ts.map +1 -0
  1012. package/dist/utils/transientFrames.js +41 -0
  1013. package/dist/utils/transientFrames.js.map +1 -0
  1014. package/dist/utils/typingActive.d.ts +35 -0
  1015. package/dist/utils/typingActive.d.ts.map +1 -0
  1016. package/dist/utils/typingActive.js +22 -0
  1017. package/dist/utils/typingActive.js.map +1 -0
  1018. package/dist/utils/typingLoopBackstop.d.ts +64 -0
  1019. package/dist/utils/typingLoopBackstop.d.ts.map +1 -0
  1020. package/dist/utils/typingLoopBackstop.js +68 -0
  1021. package/dist/utils/typingLoopBackstop.js.map +1 -0
  1022. package/dist/utils/verbosityRender.d.ts +18 -0
  1023. package/dist/utils/verbosityRender.d.ts.map +1 -0
  1024. package/dist/utils/verbosityRender.js +17 -0
  1025. package/dist/utils/verbosityRender.js.map +1 -0
  1026. package/dist/utils/wedgeRecovery.d.ts +57 -0
  1027. package/dist/utils/wedgeRecovery.d.ts.map +1 -0
  1028. package/dist/utils/wedgeRecovery.js +24 -0
  1029. package/dist/utils/wedgeRecovery.js.map +1 -0
  1030. package/dist/utils.d.ts +30 -0
  1031. package/dist/utils.d.ts.map +1 -0
  1032. package/dist/utils.js +61 -0
  1033. package/dist/utils.js.map +1 -0
  1034. package/dist/validation.d.ts +113 -0
  1035. package/dist/validation.d.ts.map +1 -0
  1036. package/dist/validation.js +226 -0
  1037. package/dist/validation.js.map +1 -0
  1038. package/dist/voiceQueue.d.ts +7 -0
  1039. package/dist/voiceQueue.d.ts.map +1 -0
  1040. package/dist/voiceQueue.js +33 -0
  1041. package/dist/voiceQueue.js.map +1 -0
  1042. package/examples/.env.example +17 -0
  1043. package/examples/docker-compose.yml +36 -0
  1044. package/package.json +83 -4
@@ -0,0 +1,1297 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.schedulerMcpPendingCancellationMax = exports.schedulerMcpPendingCancellationTtlMs = exports.schedulerMcpBindRetryDelayMs = exports.schedulerMcpBindRetryCount = exports.schedulerMcpClientIdHeader = exports.schedulerMcpPath = exports.defaultSchedulerMcpPort = void 0;
4
+ exports.buildMcpServerInstructions = buildMcpServerInstructions;
5
+ exports.getSchedulerMcpPort = getSchedulerMcpPort;
6
+ exports.resolveSchedulerMcpPort = resolveSchedulerMcpPort;
7
+ exports.getSchedulerScopePlatform = getSchedulerScopePlatform;
8
+ exports.serializeSchedulerScope = serializeSchedulerScope;
9
+ exports.parseSchedulerScope = parseSchedulerScope;
10
+ exports.buildSchedulerMcpToken = buildSchedulerMcpToken;
11
+ exports.verifySchedulerMcpToken = verifySchedulerMcpToken;
12
+ exports.extractBearerToken = extractBearerToken;
13
+ exports.buildBotMcpToolDigest = buildBotMcpToolDigest;
14
+ exports.getBotMcpToolDigest = getBotMcpToolDigest;
15
+ exports.resolveTargetThreadKey = resolveTargetThreadKey;
16
+ exports.buildSpecFromCreateArgs = buildSpecFromCreateArgs;
17
+ exports.checkIsConversationInScope = checkIsConversationInScope;
18
+ exports.createSchedulerMcpCancellationLifecycle = createSchedulerMcpCancellationLifecycle;
19
+ exports.createSchedulerMcpServer = createSchedulerMcpServer;
20
+ const node_crypto_1 = require("node:crypto");
21
+ const node_http_1 = require("node:http");
22
+ const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
23
+ const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
24
+ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
25
+ const zod_1 = require("zod");
26
+ const sessionKey_1 = require("../sessionKey");
27
+ const isoTimestamp_1 = require("../utils/isoTimestamp");
28
+ const messageSendService_1 = require("../utils/messageSendService");
29
+ const utils_1 = require("../utils");
30
+ const checkRun_1 = require("./checkRun");
31
+ const deliveryKind_1 = require("./deliveryKind");
32
+ const recurrence_1 = require("./recurrence");
33
+ const store_1 = require("./store");
34
+ const answerRequest_1 = require("../requests/answerRequest");
35
+ /**
36
+ * @description The bot-owned MCP server exposes the agent-facing tools —
37
+ * `schedule_create`, `schedule_list`, `schedule_cancel`, `send_file_to_user`,
38
+ * `send_messages_to_user`, `compact_conversation` and `answer_request` — over
39
+ * streamable HTTP on a loopback port. The server is
40
+ * INERT until `bot.ts` wires {@link createSchedulerMcpServer}; this module
41
+ * imports nothing from `bot.ts` (every side effect is injected via
42
+ * {@link SchedulerMcpDeps}).
43
+ *
44
+ * Transport: STATELESS streamable HTTP (`sessionIdGenerator: undefined`) — a
45
+ * research-locked choice (plan S5) that dodges the SDK's session-loss bugs and
46
+ * suits a single local host. The SDK binds one `McpServer` to one transport per
47
+ * connection, so every request builds a FRESH `McpServer` + transport (see
48
+ * {@link buildRequestServer}) that registers the same handlers, and they
49
+ * are closed when the response finishes. MCP cancellation arrives as a separate
50
+ * HTTP notification, so {@link createSchedulerMcpServer} keeps only the active
51
+ * request abort controllers plus one bounded, expiring lifecycle-tombstone cache
52
+ * across those otherwise-stateless transports. A pending-cancellation tombstone
53
+ * handles a cancellation that genuinely leads first registration; a
54
+ * recently-completed tombstone suppresses an unmatched late cancellation only
55
+ * while that key is inactive. An active request always takes precedence so its
56
+ * own legitimate cancellation can abort it even after typed JSON-RPC id reuse.
57
+ *
58
+ * Auth/scoping: a request carries `Authorization: Bearer <token>`. The token is
59
+ * self-describing — `<scopeB64url>.<hmacHex>` — so the bot need not know every
60
+ * valid scope up front (an OpenCode directory scope is any bound folder). The
61
+ * scope rides in cleartext (base64url) next to an HMAC-SHA256 signature over the
62
+ * decoded scope string; {@link verifySchedulerMcpToken} recomputes the HMAC and
63
+ * compares it timing-safely. A scope is one of:
64
+ * - `thread:<threadKey>` — a Claude session, pinned to its exact thread.
65
+ * - `dir:<directory>` — an OpenCode instance, granular to a bound folder.
66
+ * Every tool call resolves a single target thread from the scope (see
67
+ * {@link resolveTargetThreadKey}) and can only touch that thread's jobs —
68
+ * except `answer_request`, whose request id already names the conversation: it
69
+ * only checks that conversation is inside the scope
70
+ * ({@link checkIsConversationInScope}).
71
+ */
72
+ /**
73
+ * Default loopback port for the scheduler MCP server. Zero asks the OS for a
74
+ * free ephemeral port, so independent bot instances never compete for 4097.
75
+ */
76
+ exports.defaultSchedulerMcpPort = 0;
77
+ /** HTTP path the streamable transport is served on (matches the injected `--mcp-config` url, S6). */
78
+ exports.schedulerMcpPath = '/mcp';
79
+ /** Per-registration identity used to isolate equal JSON-RPC request IDs. */
80
+ exports.schedulerMcpClientIdHeader = 'x-telegramcode-mcp-client-id';
81
+ /**
82
+ * A port that is in use at the start is retried this many times, this far apart,
83
+ * before the bot binds another one. Another port orphans every Claude session
84
+ * launched before (it keeps the MCP address of its launch), and the holder may
85
+ * let go soon: the previous process still exiting, or a short connection of
86
+ * another process that was handed the port as its local one while the bot was
87
+ * down. Together they span the shutdown watchdog's bound (`DEFAULT_WATCHDOG_MS`),
88
+ * the longest the previous generation can take to exit.
89
+ */
90
+ exports.schedulerMcpBindRetryCount = 20;
91
+ exports.schedulerMcpBindRetryDelayMs = 500;
92
+ /** Pending cancellations and recent completions remain correlatable for this window. */
93
+ exports.schedulerMcpPendingCancellationTtlMs = 30_000;
94
+ /** Global memory bound shared by pending-cancellation and recent-completion tombstones. */
95
+ exports.schedulerMcpPendingCancellationMax = 1_000;
96
+ const schedulerMcpClientIdMaxLength = 128;
97
+ const schedulerMcpClientIdPattern = /^[A-Za-z0-9._:-]+$/;
98
+ /** Server identity reported in the MCP `initialize` handshake. */
99
+ const mcpServerName = 'telegram-bot-scheduler';
100
+ const mcpServerVersion = '1.0.0';
101
+ /** The instruction bullets that hold on every platform (the two platform-neutral tools). */
102
+ const compactConversationInstruction = '• The user EXPLICITLY asks to compact/shrink/summarize this conversation\'s context → compact_conversation. Only on an explicit request, never on your own judgement.';
103
+ const answerRequestInstruction = '• A message carries a "[Request <id> · from: …]" header → answer it through answer_request with that id: kind "final" with the full result at the end of your turn, "question" when you need the requester before you can go on (their reply arrives as a new request), "progress" for an interim note. You may call it several times; only question/final close the request.';
104
+ const claudeProfilesInstruction = '• Before you start a child `claude` process (a detached worker, reviewer, planner) → claude_profiles with the model you will launch: it lists the signed-in Claude accounts with their usage windows and names the one with the most headroom (`recommended`). Launch the child with `CLAUDE_CONFIG_DIR=<its configDir>` in its environment (nothing when configDir is null); without it the child inherits YOUR account and drains the same limits.';
105
+ const telegramInstructions = `This MCP lets the agent act on its own Telegram topic.
106
+
107
+ When to use it:
108
+ • The user asks to run/finish a plan or task LATER ("in 2h", "tomorrow 9am", "every weekday") → schedule_create. Put the work in \`prompt\`; the future run is a fresh session with no memory of this chat.
109
+ • You produced a file/chart/screenshot/video to deliver → send_file_to_user. Videos MUST be H.264 .mp4 sent as video (never as_file/document, never .webm/.mov — those render as GIFs or don't play); transcode first if needed (the tool description has the ffmpeg recipe).
110
+ • You want to deliver SEVERAL discrete messages (each as its own Telegram message, e.g. a per-item news digest) → send_messages_to_user. Each item can optionally attach ONE file/photo/video (text becomes its caption).
111
+ ${compactConversationInstruction}
112
+ • You need to review or remove scheduled jobs → schedule_list / schedule_cancel.
113
+ • You need a watchdog — keep an eye on a service, process, build, deploy, disk, URL… → schedule_create with \`checkCommand\` (cron). The bot runs the command in this folder on schedule, stays silent while it exits 0, and on the first failure pins an alert and wakes you with \`prompt\` + the exit code and output tail. Checks survive bot restarts and crashes. NEVER build your own watcher (a background loop, nohup, a sleep loop, a tmux pane, a shell crontab): it dies with your session or a restart and then fails silently.
114
+ ${answerRequestInstruction} The requester may not see your plain text, so anything they must read goes through answer_request. Your plain text is relayed into the topic too, so after answer_request end the turn WITHOUT a plain-text recap of what you answered — it would show up twice.
115
+ ${claudeProfilesInstruction}
116
+
117
+ Each tool's own description has the exact argument recipe (one-shot vs cron vs N-times, checks).`;
118
+ /** What a Jira session's instructions add: the tool that reaches the issue's original files (C10). */
119
+ const jiraAttachmentInstruction = '• The issue lists a file (an attachment id in the attachments list, or in a placeholder such as "[image: shot.png — attachment 10234]") you need to look at → jira_get_attachment with that id; it saves the original file and returns its path.';
120
+ /** For a conversation on a tracker: the requester sees nothing but the answers; `extraInstructions` name the platform's own tools. */
121
+ function buildTrackerInstructions(extraInstructions) {
122
+ return `This MCP connects the agent to the conversation that asked for its work.
123
+
124
+ When to use it:
125
+ ${[
126
+ `${answerRequestInstruction} The requester never sees your plain text or tool output: anything they must read goes through answer_request.`,
127
+ ...extraInstructions,
128
+ compactConversationInstruction,
129
+ claudeProfilesInstruction,
130
+ ].join('\n')}
131
+
132
+ Each tool's own description has the exact argument recipe.`;
133
+ }
134
+ const neutralInstructions = buildTrackerInstructions([]);
135
+ const jiraInstructions = buildTrackerInstructions([jiraAttachmentInstruction]);
136
+ /**
137
+ * Connect-time `instructions` returned in the MCP `initialize` handshake — a
138
+ * short, high-level pointer the client surfaces to the agent BEFORE any call.
139
+ * Deliberately use-case oriented (when to reach for this server, what it can do)
140
+ * and does NOT repeat the per-tool argument recipes: each tool's own description
141
+ * already carries those in full. Kept terse on purpose.
142
+ *
143
+ * @description The connect-time instructions for a session of `platform`: only
144
+ * a Telegram session has the scheduling and send-to-topic tools, so only its
145
+ * instructions name them (Jira connector plan J2, D18).
146
+ */
147
+ function buildMcpServerInstructions(platform, isJiraAttachmentToolOffered = false) {
148
+ if (platform === 'telegram')
149
+ return telegramInstructions;
150
+ return platform === 'jira' && isJiraAttachmentToolOffered ? jiraInstructions : neutralInstructions;
151
+ }
152
+ /** Max characters of a free-text job name / prompt accepted by a tool (defensive bound). */
153
+ const maxNameLength = 200;
154
+ const maxPromptLength = 8000;
155
+ /** Read the configured scheduler MCP port once, mirroring the OPENCODE_URL env read. */
156
+ function getSchedulerMcpPort() {
157
+ const raw = process.env.SCHEDULER_MCP_PORT;
158
+ if (!raw)
159
+ return exports.defaultSchedulerMcpPort;
160
+ const parsed = Number(raw);
161
+ return Number.isInteger(parsed) && parsed >= 0 && parsed <= 65535
162
+ ? parsed
163
+ : exports.defaultSchedulerMcpPort;
164
+ }
165
+ /**
166
+ * @description Resolve the scheduler MCP listen port with a fixed precedence:
167
+ * an explicit env port (`SCHEDULER_MCP_PORT`, a non-zero {@link getSchedulerMcpPort})
168
+ * WINS; else the port persisted from a prior boot (so an ephemeral port, once
169
+ * chosen, is reused — the registrations injected into agent sessions point at
170
+ * it, and an ephemeral port changing every restart would orphan them); else `0`
171
+ * (ask the OS for a fresh ephemeral port). A persisted `0` / non-positive value
172
+ * is ignored (nothing worth reusing).
173
+ */
174
+ function resolveSchedulerMcpPort(envPort, persistedPort) {
175
+ if (envPort !== exports.defaultSchedulerMcpPort)
176
+ return envPort;
177
+ if (persistedPort !== undefined && persistedPort > 0)
178
+ return persistedPort;
179
+ return exports.defaultSchedulerMcpPort;
180
+ }
181
+ /**
182
+ * @description The platform of the conversations a scope reaches. A `dir:`
183
+ * scope is an OpenCode registration, which only Telegram topics use today. A
184
+ * thread key no codec reads gets the narrower, platform-neutral tool set.
185
+ */
186
+ function getSchedulerScopePlatform(scope) {
187
+ if (scope.kind === 'dir')
188
+ return 'telegram';
189
+ return (0, sessionKey_1.tryKeyFromString)(scope.threadKey)?.platform ?? null;
190
+ }
191
+ /** Serialise a scope to its canonical cleartext form (the string the HMAC signs). */
192
+ function serializeSchedulerScope(scope) {
193
+ return scope.kind === 'thread' ? `thread:${scope.threadKey}` : `dir:${scope.directory}`;
194
+ }
195
+ /** Parse the canonical cleartext scope string back into a {@link SchedulerScope}, or `null`. */
196
+ function parseSchedulerScope(serialized) {
197
+ const sep = serialized.indexOf(':');
198
+ if (sep <= 0)
199
+ return null;
200
+ const kind = serialized.slice(0, sep);
201
+ const rest = serialized.slice(sep + 1);
202
+ if (rest.length === 0)
203
+ return null;
204
+ if (kind === 'thread')
205
+ return { kind: 'thread', threadKey: rest };
206
+ if (kind === 'dir')
207
+ return { kind: 'dir', directory: rest };
208
+ return null;
209
+ }
210
+ /** HMAC-SHA256(secret, message) as lowercase hex. */
211
+ function computeHmacHex(secret, message) {
212
+ return (0, node_crypto_1.createHmac)('sha256', secret).update(message).digest('hex');
213
+ }
214
+ /**
215
+ * @description Mint a bearer token for a scope: `<scopeB64url>.<hmacHex>`. The
216
+ * scope rides in cleartext (base64url of the canonical scope string) so the
217
+ * verifier can recover it without a lookup table; the HMAC over the DECODED
218
+ * scope string is the unforgeable part. Document/keep in sync with
219
+ * {@link verifySchedulerMcpToken}.
220
+ */
221
+ function buildSchedulerMcpToken(secret, scope) {
222
+ const serialized = serializeSchedulerScope(scope);
223
+ const scopeB64 = Buffer.from(serialized, 'utf8').toString('base64url');
224
+ const signature = computeHmacHex(secret, serialized);
225
+ return `${scopeB64}.${signature}`;
226
+ }
227
+ /**
228
+ * @description Verify a bearer token and recover its scope. Splits on the single
229
+ * `.`, base64url-decodes the scope half, recomputes the HMAC over the decoded
230
+ * scope string, and compares it to the token's signature with a constant-time
231
+ * {@link timingSafeEqual} (equal-length hex buffers). Returns the parsed scope on
232
+ * success, or `null` for any malformed / tampered token. A tampered scope half
233
+ * changes the HMAC input so the recomputed signature won't match; a tampered
234
+ * signature half fails the compare directly.
235
+ */
236
+ function verifySchedulerMcpToken(secret, token) {
237
+ const dot = token.indexOf('.');
238
+ if (dot <= 0 || dot === token.length - 1)
239
+ return null;
240
+ const scopeB64 = token.slice(0, dot);
241
+ const providedSignature = token.slice(dot + 1);
242
+ let serialized;
243
+ try {
244
+ serialized = Buffer.from(scopeB64, 'base64url').toString('utf8');
245
+ }
246
+ catch {
247
+ return null;
248
+ }
249
+ const scope = parseSchedulerScope(serialized);
250
+ if (!scope)
251
+ return null;
252
+ const expectedSignature = computeHmacHex(secret, serialized);
253
+ // timingSafeEqual throws on length mismatch, so length-gate first (hex of a
254
+ // SHA-256 is always 64 chars, but a tampered token could be any length).
255
+ const expectedBuffer = Buffer.from(expectedSignature, 'utf8');
256
+ const providedBuffer = Buffer.from(providedSignature, 'utf8');
257
+ if (expectedBuffer.length !== providedBuffer.length)
258
+ return null;
259
+ if (!(0, node_crypto_1.timingSafeEqual)(expectedBuffer, providedBuffer))
260
+ return null;
261
+ return scope;
262
+ }
263
+ /** Pull the bearer token out of an `Authorization` header value, or `null`. */
264
+ function extractBearerToken(authorizationHeader) {
265
+ if (!authorizationHeader)
266
+ return null;
267
+ const match = authorizationHeader.match(/^Bearer\s+(.+)$/i);
268
+ return match ? match[1].trim() : null;
269
+ }
270
+ /**
271
+ * @description Hash what a client caches when it connects — the server
272
+ * instructions and the tool definitions it would list — into a stable id of
273
+ * "what this bot build offers a session of one platform". Lifecycle plan L4:
274
+ * persisted when a json-stream process starts and compared when the process is
275
+ * adopted after a bot restart, since the stateless server cannot tell a running
276
+ * client that any of it changed.
277
+ */
278
+ function buildBotMcpToolDigest(instructions, definitions) {
279
+ const canonical = [...definitions]
280
+ .sort((left, right) => left.name.localeCompare(right.name))
281
+ .map(({ name, title, description, inputKeys }) => ({ name, title: title ?? '', description: description ?? '', inputKeys }));
282
+ return (0, node_crypto_1.createHash)('sha256').update(JSON.stringify({ instructions, tools: canonical })).digest('hex');
283
+ }
284
+ /** A scope of no conversation: only the digest registers against it, and the digest never runs a handler. */
285
+ const digestScope = { kind: 'dir', directory: '' };
286
+ /**
287
+ * @description The digest of the tools a session of `platform` gets — built by
288
+ * the SAME registration the request path runs, recorded instead of served, so
289
+ * a tool added, renamed, re-described or re-shaped changes it and nothing else
290
+ * has to be kept in step by hand.
291
+ */
292
+ function getBotMcpToolDigest(deps, platform) {
293
+ const definitions = [];
294
+ const recorder = {
295
+ registerTool: (name, config) => {
296
+ definitions.push({ name, title: config.title, description: config.description, inputKeys: Object.keys(config.inputSchema ?? {}).sort() });
297
+ },
298
+ };
299
+ registerBotTools(recorder, deps, digestScope, platform, undefined);
300
+ return buildBotMcpToolDigest(buildMcpServerInstructions(platform, deps.fetchJiraAttachment !== undefined), definitions);
301
+ }
302
+ /**
303
+ * @description Resolve the single thread a tool call targets, from its scope and
304
+ * an optional caller-supplied `threadKey`:
305
+ * - `thread` scope → that exact thread; a supplied `threadKey` must match it.
306
+ * - `dir` scope → the threads bound to the directory: exactly 1 → implicit;
307
+ * >1 → `threadKey` REQUIRED and must be one of them; 0 → error.
308
+ * Pure given the injected `getThreadsForDirectory`.
309
+ */
310
+ function resolveTargetThreadKey(scope, suppliedThreadKey, getThreadsForDirectory) {
311
+ if (scope.kind === 'thread') {
312
+ if (suppliedThreadKey && suppliedThreadKey !== scope.threadKey) {
313
+ return {
314
+ ok: false,
315
+ error: `threadKey "${suppliedThreadKey}" does not match this session's thread (${scope.threadKey})`,
316
+ };
317
+ }
318
+ return { ok: true, threadKey: scope.threadKey };
319
+ }
320
+ const bound = getThreadsForDirectory(scope.directory);
321
+ if (bound.length === 0) {
322
+ return { ok: false, error: `no thread is bound to directory "${scope.directory}"` };
323
+ }
324
+ if (bound.length === 1) {
325
+ if (suppliedThreadKey && suppliedThreadKey !== bound[0]) {
326
+ return {
327
+ ok: false,
328
+ error: `threadKey "${suppliedThreadKey}" is not bound to directory "${scope.directory}"`,
329
+ };
330
+ }
331
+ return { ok: true, threadKey: bound[0] };
332
+ }
333
+ // >1 bound thread → an explicit, valid threadKey is mandatory.
334
+ if (!suppliedThreadKey) {
335
+ return {
336
+ ok: false,
337
+ error: `directory "${scope.directory}" has ${bound.length} bound threads; ` +
338
+ `pass threadKey (one of: ${bound.join(', ')})`,
339
+ };
340
+ }
341
+ if (!bound.includes(suppliedThreadKey)) {
342
+ return {
343
+ ok: false,
344
+ error: `threadKey "${suppliedThreadKey}" is not bound to directory "${scope.directory}"`,
345
+ };
346
+ }
347
+ return { ok: true, threadKey: suppliedThreadKey };
348
+ }
349
+ // ─── tool input schemas + spec building ──────────────────────────────
350
+ const scheduleCreateShape = {
351
+ name: zod_1.z.string().min(1).max(maxNameLength).describe('Short human name for the job (shown in announcements/lists).'),
352
+ cron: zod_1.z
353
+ .string()
354
+ .optional()
355
+ .describe('5-field host-local cron expression for a RECURRING job (e.g. "0 9 * * 1-5"). ' +
356
+ 'For a single future run use onceAt instead, NOT a cron (a cron has no year and would ' +
357
+ 'fire on the same date every year). Omit onceAt when you pass cron.'),
358
+ onceAt: zod_1.z
359
+ .string()
360
+ .optional()
361
+ .describe('ISO 8601 instant for a ONE-SHOT run (e.g. "2026-06-07T09:00:00"). This is the right field for ' +
362
+ '"run it once at <time>". Omit cron AND repeatCount when you pass onceAt — a one-shot always runs ' +
363
+ 'exactly once.'),
364
+ repeatCount: zod_1.z
365
+ .number()
366
+ .int()
367
+ .positive()
368
+ .optional()
369
+ .describe('Number of CRON fires before the job auto-deletes (N-times recurring). ONLY for cron jobs. ' +
370
+ 'Do NOT set it for a one-shot (onceAt) — a one-shot already runs exactly once, so repeatCount ' +
371
+ 'is ignored there.'),
372
+ prompt: zod_1.z
373
+ .string()
374
+ .min(1)
375
+ .max(maxPromptLength)
376
+ .describe('The prompt forwarded to the agent at fire time (for a check: only when the check fails, after ' +
377
+ 'the failure details). Make it SELF-CONTAINED — the future run starts ' +
378
+ 'with no memory of this conversation. Bake in everything it needs: the plan file path + scope, ' +
379
+ 'whether to delegate to a sub-agent, and any constraints. Put the WORK in the prompt; do the ' +
380
+ 'investigation later, when it fires.'),
381
+ checkCommand: zod_1.z
382
+ .string()
383
+ .max(checkRun_1.maxCheckCommandLength)
384
+ .optional()
385
+ .describe('Makes the job a WATCHDOG CHECK: a shell command (run with /bin/sh -c in the bound folder) the bot ' +
386
+ 'executes at every fire instead of waking you. Exit 0 = healthy, nothing is posted. The first ' +
387
+ 'non-zero exit or timeout pins an alert in the topic and wakes you with `prompt` plus the exit ' +
388
+ 'code and output tail; later failures stay silent until a run passes again (the topic is told). ' +
389
+ 'Keep it a quick probe, e.g. `systemctl --user is-active myapp`, `curl -fsS -m 10 http://127.0.0.1:8080/health`, ' +
390
+ '`test $(df --output=pcent / | tail -1 | tr -dc 0-9) -lt 90`.'),
391
+ checkTimeoutSeconds: zod_1.z
392
+ .number()
393
+ .int()
394
+ .positive()
395
+ .max(checkRun_1.maxCheckTimeoutSec)
396
+ .optional()
397
+ .describe(`Seconds a check run may take before it is stopped and counted as a failure (default ${checkRun_1.defaultCheckTimeoutSec}). ` +
398
+ 'Only with checkCommand.'),
399
+ isPinSilent: zod_1.z
400
+ .boolean()
401
+ .optional()
402
+ .describe('Pin the fire announcement silently (no member notification). Default false = notify all.'),
403
+ threadKey: zod_1.z
404
+ .string()
405
+ .optional()
406
+ .describe('Target thread "<chatId>:<threadId>". Required when a directory scope has more than one bound thread.'),
407
+ };
408
+ const scheduleListShape = {
409
+ threadKey: zod_1.z
410
+ .string()
411
+ .optional()
412
+ .describe('Target thread "<chatId>:<threadId>". Required when a directory scope has more than one bound thread.'),
413
+ };
414
+ const scheduleCancelShape = {
415
+ id: zod_1.z.string().min(1).describe('The schedule id to cancel (from schedule_list).'),
416
+ threadKey: zod_1.z
417
+ .string()
418
+ .optional()
419
+ .describe('Target thread "<chatId>:<threadId>". Required when a directory scope has more than one bound thread.'),
420
+ };
421
+ /**
422
+ * Coerces an ARRAY tool argument into an actual array before validation. Some
423
+ * MCP bridges (observed: Claude-agent harnesses AND OpenCode) serialize an array
424
+ * argument as a raw JSON STRING (`'["a","b"]'`, or a mixed
425
+ * `'[{"path":"p"},"txt"]'`) instead of a JSON array, which a plain `z.array()`
426
+ * rejects. Accept: a real array (pass-through), a JSON-array string (parsed —
427
+ * per-element validation still runs on the union afterward), or a single plain
428
+ * string (wrapped into a one-element array). Shared by `paths` and `messages`.
429
+ */
430
+ const coerceJsonArrayArg = (value) => {
431
+ if (typeof value !== 'string')
432
+ return value;
433
+ const trimmed = value.trim();
434
+ if (trimmed.startsWith('[')) {
435
+ try {
436
+ return JSON.parse(trimmed);
437
+ }
438
+ catch {
439
+ return value;
440
+ }
441
+ }
442
+ return [value];
443
+ };
444
+ const sendFileShape = {
445
+ paths: zod_1.z.preprocess(coerceJsonArrayArg, zod_1.z
446
+ .array(zod_1.z.string().min(1))
447
+ .min(1)
448
+ .max(10))
449
+ .describe('Files to send, as 1..10 paths RELATIVE to this topic\'s bound folder (absolute paths are accepted ' +
450
+ 'only if they resolve inside it). A path outside the folder is rejected and nothing is sent. ' +
451
+ '2..10 paths are delivered as ONE album.'),
452
+ caption: zod_1.z
453
+ .string()
454
+ .optional()
455
+ .describe('Optional caption (Telegram caps it at 1024 chars; longer is trimmed). For an album it rides the first file.'),
456
+ as_file: zod_1.z
457
+ .boolean()
458
+ .optional()
459
+ .describe('Explicitly force sendDocument (original quality, no inline preview), including for MP4s that use sendVideo by default.'),
460
+ threadKey: zod_1.z
461
+ .string()
462
+ .optional()
463
+ .describe('Target thread "<chatId>:<threadId>". Required when a directory scope has more than one bound thread.'),
464
+ };
465
+ /**
466
+ * One batch item: EITHER a plain non-empty string (text-only message,
467
+ * backward-compatible with the original string-array tool) OR an object that may
468
+ * carry a text body, an attachment `path`, or both. The `.refine` rejects an
469
+ * all-empty object so a stray `{}` never posts nothing.
470
+ */
471
+ const sendMessageItemObjectSchema = zod_1.z
472
+ .object({
473
+ text: zod_1.z
474
+ .string()
475
+ .optional()
476
+ .describe('Message body. On an ATTACHMENT item (path set) it is the media caption, trimmed to 1024 chars — put long ' +
477
+ 'prose in its OWN text-only item instead of an attachment caption.'),
478
+ path: zod_1.z
479
+ .string()
480
+ .optional()
481
+ .describe("Optional attachment, RELATIVE to this topic's bound folder (an absolute path is accepted only if it " +
482
+ 'resolves inside it; a path outside is rejected). Supported photos and MP4 videos are sent as native ' +
483
+ 'media, GIFs as animations, and everything else as a document.'),
484
+ as_file: zod_1.z
485
+ .boolean()
486
+ .optional()
487
+ .describe('Force sendDocument for THIS attachment (original quality, no inline preview), including for MP4s.'),
488
+ })
489
+ .refine((item) => (item.text?.trim().length ?? 0) > 0 || (item.path?.trim().length ?? 0) > 0, { message: 'each message object must set a non-empty text or path' });
490
+ const sendMessageShape = {
491
+ messages: zod_1.z
492
+ .preprocess(coerceJsonArrayArg, zod_1.z
493
+ .array(zod_1.z.union([zod_1.z.string().min(1), sendMessageItemObjectSchema]))
494
+ .min(1)
495
+ .max(messageSendService_1.maxDiscreteMessages))
496
+ .describe(`1..${messageSendService_1.maxDiscreteMessages} items; EACH item is posted as its OWN separate Telegram message, in order (never ` +
497
+ 'merged). An item is EITHER a plain string (a text message) OR an object {text?, path?, as_file?}. When ' +
498
+ 'path is set the item is delivered as an ATTACHMENT: supported photos render inline, .gif uses ' +
499
+ 'sendAnimation, and .mp4 uses sendVideo (other video containers like .mov/.webm render as a GIF, so remux ' +
500
+ 'to .mp4 first); everything else is a document, and text becomes the media caption (trimmed to 1024 chars ' +
501
+ '— send long prose as its OWN ' +
502
+ "text-only item). path is RELATIVE to this topic's bound folder; as_file forces the document override. " +
503
+ 'Use this when you deliberately want several distinct messages (e.g. a per-item news digest: one message ' +
504
+ 'per headline). Do NOT also print the same content as your normal reply, or it posts twice. Text supports ' +
505
+ 'the usual markdown (links, bold); an over-long text item is split automatically.'),
506
+ threadKey: zod_1.z
507
+ .string()
508
+ .optional()
509
+ .describe('Target thread "<chatId>:<threadId>". Required when a directory scope has more than one bound thread.'),
510
+ };
511
+ /**
512
+ * The three valid call shapes, appended to structural errors so a bad first call
513
+ * teaches the corrected next call (the model spirals when an error says only what
514
+ * is wrong, not what shape to use instead — observed in the live transcript).
515
+ */
516
+ const scheduleRecipes = 'Recipes — one-shot: pass onceAt (ISO), omit cron and repeatCount. ' +
517
+ 'Recurring: pass cron, omit onceAt. ' +
518
+ 'Recurring N times: pass cron and repeatCount, omit onceAt.';
519
+ /**
520
+ * @description Collapse an optional free-text field to `undefined` when it is
521
+ * absent OR blank (empty / whitespace-only). MCP bridges can render an omitted
522
+ * optional as an empty string (`cron=""` on a one-shot, `onceAt=""` on a cron),
523
+ * and an empty string must NOT count as a supplied value for the exactly-one-of
524
+ * check. Trimming also tolerates accidental surrounding whitespace.
525
+ */
526
+ function normalizeOptionalArg(value) {
527
+ if (value === undefined)
528
+ return undefined;
529
+ const trimmed = value.trim();
530
+ return trimmed.length > 0 ? trimmed : undefined;
531
+ }
532
+ /**
533
+ * @description Validate the create args and build a {@link ScheduleSpec}: exactly
534
+ * one of `cron`/`onceAt` (empty/whitespace fields normalised away first); then run
535
+ * the shared {@link validateScheduleSpec} (cron parse + min-interval + past-one-shot).
536
+ * `nowMs` is injected so the past-one-shot check is deterministic.
537
+ *
538
+ * A `repeatCount` supplied alongside `onceAt` is IGNORED (not rejected): a one-shot
539
+ * is by definition a single run, so the count is meaningless there. The model
540
+ * naturally reaches for `repeatCount: 1` to express "run once" and, when that was
541
+ * a hard error, spiralled into absurd counts / a wrong-year cron workaround
542
+ * (live transcript). Accepting the natural call removes that failure mode; the
543
+ * returned `note` teaches the agent the field was redundant.
544
+ */
545
+ function buildSpecFromCreateArgs(args, nowMs) {
546
+ const cron = normalizeOptionalArg(args.cron);
547
+ const onceAt = normalizeOptionalArg(args.onceAt);
548
+ const { repeatCount } = args;
549
+ if (cron && onceAt) {
550
+ return { ok: false, error: `Pass either cron OR onceAt, not both. ${scheduleRecipes}` };
551
+ }
552
+ if (!cron && !onceAt) {
553
+ return { ok: false, error: `Pass exactly one of cron or onceAt. ${scheduleRecipes}` };
554
+ }
555
+ let note;
556
+ if (onceAt && repeatCount !== undefined) {
557
+ note = 'repeatCount was ignored — a one-shot (onceAt) always runs exactly once.';
558
+ }
559
+ const spec = cron
560
+ ? { kind: 'cron', cronExpr: cron, ...(repeatCount !== undefined ? { remainingRuns: repeatCount } : {}) }
561
+ : { kind: 'once', onceAtIso: onceAt };
562
+ const validationError = (0, recurrence_1.validateScheduleSpec)(spec, nowMs);
563
+ if (validationError)
564
+ return { ok: false, error: validationError };
565
+ return { ok: true, spec, note };
566
+ }
567
+ // ─── tool result helpers ─────────────────────────────────────────────
568
+ /** Wrap text as a successful MCP tool result (plain text content block). */
569
+ function textResult(text) {
570
+ return { content: [{ type: 'text', text }] };
571
+ }
572
+ /** Wrap a readable message as an MCP tool ERROR result the agent relays to the user. */
573
+ function errorResult(message) {
574
+ return { content: [{ type: 'text', text: message }], isError: true };
575
+ }
576
+ /** Report an ambiguous delivery without inviting MCP clients to retry it. */
577
+ function deliveryUnknownResult(message) {
578
+ return {
579
+ content: [{ type: 'text', text: message }],
580
+ structuredContent: { kind: 'deliveryUnknown', retryable: false },
581
+ };
582
+ }
583
+ /** One-line human summary of a record for `schedule_list` / create confirmations. */
584
+ function summarizeRecord(record) {
585
+ // Local-offset ISO, never `toISOString()`'s UTC `Z`: the operator declared a
586
+ // timezone and the agent reads this back to them, so a next-run stamp in some
587
+ // other zone than the one the job actually fires in is actively misleading.
588
+ const next = record.nextRunAt !== null ? (0, isoTimestamp_1.formatIsoLocalOffset)(record.nextRunAt) : 'none';
589
+ const pausedNote = record.isPaused ? ' [paused]' : '';
590
+ const checkNote = (0, deliveryKind_1.checkIsCheckSchedule)(record)
591
+ ? `; check: \`${record.checkCommand ?? ''}\` (${record.isCheckFailing ? 'FAILING' : 'passing'})`
592
+ : '';
593
+ return `${record.name} (id: ${record.id}) — ${(0, recurrence_1.describeSchedule)(record.spec)}${checkNote}; next run: ${next}${pausedNote}`;
594
+ }
595
+ // ─── tool handlers (scope-bound) ─────────────────────────────────────
596
+ /**
597
+ * @description Register the three scoped tools onto a fresh {@link McpServer}.
598
+ * Every handler resolves the target thread from `scope` first (scope isolation),
599
+ * then operates only on that thread's jobs. Bound to `deps` + the request's
600
+ * verified `scope`.
601
+ */
602
+ function registerSchedulerTools(server, deps, scope) {
603
+ server.registerTool('schedule_create', {
604
+ title: 'Create a scheduled prompt',
605
+ description: 'Schedule a prompt to be delivered to this topic later. The bot announces, pins, and ' +
606
+ 'forwards the prompt to the agent at fire time.\n\n' +
607
+ 'Pick exactly ONE mode:\n' +
608
+ '• one-shot (run once at a time): pass onceAt (ISO 8601); omit cron and repeatCount.\n' +
609
+ '• recurring: pass cron (5-field); omit onceAt.\n' +
610
+ '• recurring N times: pass cron AND repeatCount; omit onceAt.\n' +
611
+ 'For a single future run ALWAYS use onceAt — never a cron with repeatCount:1 ' +
612
+ '(a cron has no year, so it would fire on that date every year). repeatCount counts CRON ' +
613
+ 'fires only and is ignored for a one-shot.\n\n' +
614
+ 'USE THIS whenever the user asks to schedule execution of a plan or task for later ' +
615
+ "(e.g. \"schedule finishing plan X in 2h\", \"run this plan tomorrow morning\"). " +
616
+ 'Schedule IMMEDIATELY: write the request straight into `prompt` and create the job FIRST — ' +
617
+ 'do NOT read code, explore the repo, or deliberate before scheduling. Plan now, figure out the ' +
618
+ 'details at fire time. The future run does the investigation, not this call.\n\n' +
619
+ 'WATCHDOG: to monitor something (a service, process, build, deploy, disk, URL), pass checkCommand ' +
620
+ 'with a cron — the bot runs it in this folder and wakes you only when it starts failing. This is ' +
621
+ 'the ONLY reliable watcher: it survives bot restarts and crashes. Never build your own (a ' +
622
+ 'background loop, nohup, a sleep loop, a tmux pane, a shell crontab) — it dies with your session ' +
623
+ 'or a restart and then fails silently.',
624
+ inputSchema: scheduleCreateShape,
625
+ }, async (args) => {
626
+ const resolved = resolveTargetThreadKey(scope, args.threadKey, deps.getThreadsForDirectory);
627
+ if (!resolved.ok)
628
+ return errorResult(resolved.error);
629
+ const nowMs = Date.now();
630
+ const built = buildSpecFromCreateArgs(args, nowMs);
631
+ if (!built.ok)
632
+ return errorResult(built.error);
633
+ let threadKey;
634
+ try {
635
+ threadKey = (0, sessionKey_1.keyFromString)(resolved.threadKey);
636
+ }
637
+ catch {
638
+ return errorResult(`invalid threadKey "${resolved.threadKey}"`);
639
+ }
640
+ const checkCommand = normalizeOptionalArg(args.checkCommand);
641
+ const notes = built.note ? [built.note] : [];
642
+ if (!checkCommand && args.checkTimeoutSeconds !== undefined) {
643
+ notes.push('checkTimeoutSeconds was ignored — it only applies with checkCommand.');
644
+ }
645
+ const created = await (0, store_1.createScheduleForThread)(deps.store, {
646
+ threadKey,
647
+ name: args.name,
648
+ spec: built.spec,
649
+ prompt: args.prompt,
650
+ createdBy: 'agent',
651
+ nowMs,
652
+ lastAdapterName: deps.getThreadAdapterName(resolved.threadKey),
653
+ isPinSilent: args.isPinSilent,
654
+ ...(checkCommand
655
+ ? { deliveryKind: 'check', checkCommand, checkTimeoutSec: args.checkTimeoutSeconds }
656
+ : {}),
657
+ });
658
+ if (!created.ok) {
659
+ // The cap counts only the agent-prompt jobs `schedule_list` shows, so the
660
+ // plain sentence is the whole truth: every slot it names is one this agent
661
+ // can see and cancel itself.
662
+ return errorResult(`cannot create: thread already has the maximum of ${created.limit} schedules`);
663
+ }
664
+ const record = created.record;
665
+ deps.armJob(record);
666
+ const noteSuffix = notes.map((note) => `\n\nℹ️ ${note}`).join('');
667
+ return textResult(`Scheduled "${record.name}".\n${summarizeRecord(record)}${noteSuffix}`);
668
+ });
669
+ server.registerTool('schedule_list', {
670
+ title: 'List scheduled prompts',
671
+ description: 'List the scheduled prompts for this topic (id, name, schedule, next run, paused flag).',
672
+ inputSchema: scheduleListShape,
673
+ }, async (args) => {
674
+ const resolved = resolveTargetThreadKey(scope, args.threadKey, deps.getThreadsForDirectory);
675
+ if (!resolved.ok)
676
+ return errorResult(resolved.error);
677
+ let threadKey;
678
+ try {
679
+ threadKey = (0, sessionKey_1.keyFromString)(resolved.threadKey);
680
+ }
681
+ catch {
682
+ return errorResult(`invalid threadKey "${resolved.threadKey}"`);
683
+ }
684
+ // Reminders are invisible to the agent BY DESIGN: a `/reminders` job is
685
+ // bot-local (posted + pinned, no session touched), so listing one here
686
+ // would describe it to the agent as a "scheduled prompt" it could act on —
687
+ // and `schedule_cancel` below would let it delete something the operator
688
+ // created with buttons and never handed to any agent.
689
+ const records = deps.store
690
+ .getThreadSchedules(threadKey)
691
+ .filter((record) => !(0, deliveryKind_1.checkIsReminderSchedule)(record));
692
+ if (records.length === 0) {
693
+ return textResult('No schedules for this topic.');
694
+ }
695
+ const lines = records.map((record, index) => `${index + 1}. ${summarizeRecord(record)}`);
696
+ return textResult(lines.join('\n'));
697
+ });
698
+ server.registerTool('schedule_cancel', {
699
+ title: 'Cancel a scheduled prompt',
700
+ description: 'Cancel (delete) a scheduled prompt by its id. Only schedules owned by this topic can be cancelled.',
701
+ inputSchema: scheduleCancelShape,
702
+ }, async (args) => {
703
+ const resolved = resolveTargetThreadKey(scope, args.threadKey, deps.getThreadsForDirectory);
704
+ if (!resolved.ok)
705
+ return errorResult(resolved.error);
706
+ const record = deps.store.getSchedules()[args.id];
707
+ // Scope isolation: the record must exist AND belong to the resolved thread.
708
+ // A reminder answers the SAME "not found" as a missing id rather than a new
709
+ // error kind: `schedule_list` never showed it, so from the agent's side it
710
+ // genuinely does not exist, and a distinct refusal would only tell it there
711
+ // is an id here worth retrying.
712
+ if (!record || record.threadKey !== resolved.threadKey || (0, deliveryKind_1.checkIsReminderSchedule)(record)) {
713
+ return errorResult(`no schedule with id "${args.id}" in this topic`);
714
+ }
715
+ await deps.store.removeSchedule(args.id);
716
+ deps.disarmJob(args.id);
717
+ return textResult(`Cancelled "${record.name}" (id: ${record.id}).`);
718
+ });
719
+ }
720
+ /**
721
+ * @description Register the agent→Telegram `send_file_to_user` tool onto a fresh
722
+ * {@link McpServer}. Kept separate from {@link registerSchedulerTools} so the
723
+ * scheduler tools stay cohesive. Like every tool here it resolves the target
724
+ * thread from `scope` first (scope isolation — the agent can never name another
725
+ * topic); the actual path-safety + Telegraf send live in `deps.sendFilesToThread`.
726
+ */
727
+ function registerFileSendTool(server, deps, scope, requestSignal) {
728
+ server.registerTool('send_file_to_user', {
729
+ title: 'Send a file or image to this topic',
730
+ description: 'Send one or more files/images from THIS topic\'s bound folder back to the user in the topic. ' +
731
+ 'Use it to deliver a generated chart, screenshot, report, etc. Paths are relative to the bound ' +
732
+ 'folder; a path outside it is rejected and nothing is sent. Images (.png/.jpg/.jpeg/.webp) preview ' +
733
+ 'inline, .gif autoplays, and a single .mp4 uses sendVideo by default. as_file:true is the explicit sendDocument ' +
734
+ 'override for previewable media; no fake audio track is needed for a silent MP4. Everything else arrives ' +
735
+ 'as a document. VIDEO RULE: to deliver a playable video, pass a .mp4 path and do NOT set as_file — any other ' +
736
+ 'container (.mov/.webm/.mkv) or a document fallback makes Telegram render it as a GIF instead; remux to .mp4 first ' +
737
+ '(e.g. `ffmpeg -i in.webm -c:v libx264 -pix_fmt yuv420p -movflags +faststart out.mp4`; if no full ffmpeg is ' +
738
+ 'installed, `npm i ffmpeg-static` provides one — Playwright\'s bundled ffmpeg has no H.264 encoder). ' +
739
+ '2..10 paths use sendMediaGroup: eligible photos and MP4 videos stay native in ' +
740
+ 'all-video and mixed photo/video groups; as_file:true, any animation/document, or an over-cap photo makes ' +
741
+ 'the whole album documents — which turns its MP4s into GIFs, so send videos in their own call. ' +
742
+ 'Secure outbound traversal currently requires Linux; other platforms fail closed. ' +
743
+ 'Caption is optional (trimmed to 1024 chars; on the first album item).',
744
+ inputSchema: sendFileShape,
745
+ }, async (args, extra) => {
746
+ const signal = requestSignal
747
+ ? AbortSignal.any([extra.signal, requestSignal])
748
+ : extra.signal;
749
+ const resolved = resolveTargetThreadKey(scope, args.threadKey, deps.getThreadsForDirectory);
750
+ if (!resolved.ok)
751
+ return errorResult(resolved.error);
752
+ if (signal.aborted)
753
+ throw (0, utils_1.getAbortError)(signal);
754
+ const result = await deps.sendFilesToThread(resolved.threadKey, {
755
+ paths: args.paths,
756
+ caption: args.caption,
757
+ asFile: args.as_file,
758
+ ...(scope.kind === 'dir' ? { authorizedWorkDir: scope.directory } : {}),
759
+ signal,
760
+ });
761
+ if (result.ok)
762
+ return textResult(result.summary);
763
+ return 'kind' in result && result.kind === 'deliveryUnknown'
764
+ ? deliveryUnknownResult(result.error)
765
+ : errorResult(result.error);
766
+ });
767
+ }
768
+ /**
769
+ * @description Register the agent→Telegram `send_messages_to_user` tool onto a
770
+ * fresh {@link McpServer}. The discrete-message sibling of `send_file_to_user`:
771
+ * each array element is delivered as its OWN Telegram message (never merged),
772
+ * for a per-item digest and similar. Like every tool here it resolves the target
773
+ * thread from `scope` first (scope isolation); the paced send lives in
774
+ * `deps.sendMessagesToThread`.
775
+ */
776
+ function registerMessageSendTool(server, deps, scope, requestSignal) {
777
+ server.registerTool('send_messages_to_user', {
778
+ title: 'Send several separate messages to this topic',
779
+ description: 'Deliver a batch of DISCRETE messages into THIS topic — each item of `messages` is posted as its own ' +
780
+ 'separate Telegram message, in order (never merged). Use it when you deliberately want several messages ' +
781
+ 'instead of one, e.g. a per-item news digest (header, a date separator, then one message per headline). ' +
782
+ 'An item is EITHER a plain string (text message) OR an object {text?, path?, as_file?} — set `path` to ' +
783
+ "attach ONE file (RELATIVE to this topic's bound folder): supported photos render inline, .gif uses " +
784
+ 'sendAnimation, and .mp4 uses sendVideo (.mov/.webm render as a GIF, so remux to .mp4 first); everything ' +
785
+ 'else is a document, and `text` ' +
786
+ 'becomes the media caption (trimmed to 1024 chars — send long prose as its OWN text-only item). ' +
787
+ '`as_file:true` forces the document override for that attachment. Markdown (links, bold) works on text ' +
788
+ 'items; an over-long text item is split automatically. Note: this does NOT replace your normal single ' +
789
+ 'reply — only reach for it when multiple discrete messages are wanted, and do not also print the same ' +
790
+ 'content as your reply text (that would post it twice).',
791
+ inputSchema: sendMessageShape,
792
+ }, async (args, extra) => {
793
+ const signal = requestSignal
794
+ ? AbortSignal.any([extra.signal, requestSignal])
795
+ : extra.signal;
796
+ const resolved = resolveTargetThreadKey(scope, args.threadKey, deps.getThreadsForDirectory);
797
+ if (!resolved.ok)
798
+ return errorResult(resolved.error);
799
+ if (signal.aborted)
800
+ throw (0, utils_1.getAbortError)(signal);
801
+ // Map the wire shape (snake-case `as_file`) to the service's item type.
802
+ const items = args.messages.map((item) => typeof item === 'string'
803
+ ? item
804
+ : {
805
+ ...(item.text !== undefined ? { text: item.text } : {}),
806
+ ...(item.path !== undefined ? { path: item.path } : {}),
807
+ ...(item.as_file !== undefined ? { asFile: item.as_file } : {}),
808
+ });
809
+ const result = await deps.sendMessagesToThread(resolved.threadKey, {
810
+ messages: items,
811
+ ...(scope.kind === 'dir' ? { authorizedWorkDir: scope.directory } : {}),
812
+ signal,
813
+ });
814
+ if (result.ok)
815
+ return textResult(result.summary);
816
+ return 'kind' in result && result.kind === 'deliveryUnknown'
817
+ ? deliveryUnknownResult(result.error)
818
+ : errorResult(result.error);
819
+ });
820
+ }
821
+ /**
822
+ * @description Register the agent→bot `compact_conversation` tool (F1). Like
823
+ * every tool here it resolves the target thread from `scope` first (scope
824
+ * isolation — the agent can only compact ITS OWN topic's session). The actual
825
+ * arm + deferred compaction lives in `deps.compactConversation`; this surface
826
+ * only routes the resolved thread and relays the status text.
827
+ */
828
+ function registerCompactConversationTool(server, deps, scope) {
829
+ server.registerTool('compact_conversation', {
830
+ title: 'Compact this conversation',
831
+ description: 'Compact (summarize) THIS topic\'s own session context so the conversation can continue in a ' +
832
+ 'smaller window. Call this ONLY when the user EXPLICITLY asks to compact / shrink / summarize the ' +
833
+ 'context (e.g. "compact our conversation", "сожми контекст") — never on your own judgement, and ' +
834
+ 'never to "clean up". It does NOT compact mid-turn: it arms compaction and returns immediately; the ' +
835
+ 'bot runs the real compaction the moment this turn finishes. There is nothing for you to do ' +
836
+ 'afterwards — do not call it again for the same request.',
837
+ inputSchema: {
838
+ reason: zod_1.z
839
+ .string()
840
+ .optional()
841
+ .describe('Optional short note on why the user asked to compact (for the bot log only).'),
842
+ },
843
+ }, async (args) => {
844
+ // A surviving session may call this before boot re-attached it.
845
+ await deps.whenSessionsRestored();
846
+ const resolved = resolveTargetThreadKey(scope, undefined, deps.getThreadsForDirectory);
847
+ if (!resolved.ok)
848
+ return errorResult(resolved.error);
849
+ if (args.reason)
850
+ console.log(`[compact_conversation] ${resolved.threadKey}: ${args.reason}`);
851
+ const outcome = deps.compactConversation(resolved.threadKey);
852
+ return outcome.ok ? textResult(outcome.message) : errorResult(outcome.message);
853
+ });
854
+ }
855
+ /**
856
+ * `jira_get_attachment`: the issue is the conversation this session's token names — never an argument —
857
+ * so a file of any other issue cannot be asked for, however the id got into the agent's head.
858
+ */
859
+ function registerJiraAttachmentTool(server, deps, fetchJiraAttachment, scope) {
860
+ server.registerTool('jira_get_attachment', {
861
+ title: 'Get a Jira attachment',
862
+ description: 'Download the ORIGINAL of one attachment of THIS issue and get the local path it was saved at. The ' +
863
+ 'attachment ids are in the issue\'s attachments list and in placeholders like ' +
864
+ '"[image: shot.png — attachment 10234]". There is no size limit. What you do with the file is up to ' +
865
+ 'you: view an image with your file-reading tool, take frames or the audio of a video with ffmpeg ' +
866
+ '(when it is on your PATH). Only this issue\'s own attachments can be fetched.',
867
+ inputSchema: {
868
+ attachmentId: zod_1.z.string().min(1).describe('The attachment id, e.g. "10234" from "[image: shot.png — attachment 10234]".'),
869
+ },
870
+ }, async (args) => {
871
+ await deps.whenSessionsRestored();
872
+ const resolved = resolveTargetThreadKey(scope, undefined, deps.getThreadsForDirectory);
873
+ if (!resolved.ok)
874
+ return errorResult(resolved.error);
875
+ const outcome = await fetchJiraAttachment(resolved.threadKey, args.attachmentId);
876
+ return outcome.ok ? textResult(outcome.message) : errorResult(outcome.error);
877
+ });
878
+ }
879
+ /**
880
+ * @description Whether a token's scope covers a conversation (serialized key): a
881
+ * `thread:` token covers exactly its thread, a `dir:` token every thread bound to
882
+ * its directory. Unlike {@link resolveTargetThreadKey} it never picks a target —
883
+ * the request id already names the conversation, this only checks the caller may
884
+ * act on it.
885
+ */
886
+ function checkIsConversationInScope(scope, conversationKey, getThreadsForDirectory) {
887
+ if (scope.kind === 'thread')
888
+ return scope.threadKey === conversationKey;
889
+ return getThreadsForDirectory(scope.directory).includes(conversationKey);
890
+ }
891
+ const answerRequestShape = {
892
+ requestId: zod_1.z
893
+ .string()
894
+ .trim()
895
+ .min(1)
896
+ .describe('The id from the "[Request <id> · from: …]" header of the message you are answering.'),
897
+ kind: zod_1.z
898
+ .enum(['progress', 'question', 'final'])
899
+ .describe('"final" — the full result, at the end of your turn (closes the request); "question" — you need the ' +
900
+ 'requester before you can go on (closes the request; their reply is a new request); "progress" — an ' +
901
+ 'interim note (the request stays open).'),
902
+ body: zod_1.z
903
+ .string()
904
+ .trim()
905
+ .min(1)
906
+ .max(answerRequest_1.answerBodyMaxLength)
907
+ .describe('The answer itself, in Markdown. Write it for the requester: they do not see your other output.'),
908
+ };
909
+ /**
910
+ * @description Register `answer_request` (request/answer core S3): the agent's
911
+ * answer to a request, delivered to the surface the request came from. The
912
+ * scope check is passed in so a session can only answer requests of the
913
+ * conversations its token covers; an id outside it reads as unknown.
914
+ */
915
+ function registerAnswerRequestTool(server, deps, scope) {
916
+ server.registerTool('answer_request', {
917
+ title: 'Answer a request',
918
+ description: 'Send your answer to a request — a message that carries a "[Request <id> · from: …]" header — to ' +
919
+ 'the person who made it, on the surface it came from. The requester may not see your plain text, so ' +
920
+ 'anything they must read goes through this tool. Call it with kind "final" and the full result at the ' +
921
+ 'end of your turn; "question" when you need them before you can continue; "progress" for an interim ' +
922
+ 'note. You may call it several times for one request; only "question" and "final" close it. Do not ' +
923
+ 'restate the answer in plain text afterwards: where your plain text is relayed as well, a recap shows twice.',
924
+ inputSchema: answerRequestShape,
925
+ }, async (args) => {
926
+ const outcome = await deps.answerRequest({
927
+ requestId: args.requestId,
928
+ kind: args.kind,
929
+ body: args.body,
930
+ checkIsConversationInScope: (conversationKey) => checkIsConversationInScope(scope, conversationKey, deps.getThreadsForDirectory),
931
+ });
932
+ return outcome.ok ? textResult(outcome.message) : errorResult(outcome.error);
933
+ });
934
+ }
935
+ /**
936
+ * @description Correlate stateless MCP requests with cancellation notifications.
937
+ * Active controllers are isolated by verified token + validated client identity
938
+ * + typed JSON-RPC id. One bounded TTL cache stores mutually-exclusive terminal
939
+ * states for inactive keys:
940
+ *
941
+ * - `pendingCancellation` aborts the first matching registration, then is consumed.
942
+ * - `recentlyCompleted` ignores only an unmatched late cancellation while no
943
+ * matching request is active, preventing it from becoming pending poison.
944
+ *
945
+ * Active controllers always take precedence over tombstones because generations
946
+ * that reuse one client identity and request id are otherwise indistinguishable.
947
+ *
948
+ * The clock and cache limit are injectable only at construction so expiry and
949
+ * oldest-entry eviction stay deterministic in tests; production uses the fixed
950
+ * exported defaults.
951
+ */
952
+ function createSchedulerMcpCancellationLifecycle(options = {}) {
953
+ const getNowMs = options.getNowMs ?? Date.now;
954
+ const maxTombstones = options.maxTombstones ?? exports.schedulerMcpPendingCancellationMax;
955
+ if (!Number.isSafeInteger(maxTombstones) || maxTombstones <= 0) {
956
+ throw new RangeError('maxTombstones must be a positive safe integer');
957
+ }
958
+ const requestAbortControllers = new Map();
959
+ const tombstones = new Map();
960
+ function getRequestCorrelationKey(clientIdentity, requestId) {
961
+ return JSON.stringify([clientIdentity, typeof requestId, requestId]);
962
+ }
963
+ function pruneTombstones(now) {
964
+ for (const [correlationKey, tombstone] of tombstones) {
965
+ if (tombstone.expiresAt <= now)
966
+ tombstones.delete(correlationKey);
967
+ }
968
+ }
969
+ function setTombstone(correlationKey, tombstone, now) {
970
+ pruneTombstones(now);
971
+ tombstones.delete(correlationKey);
972
+ while (tombstones.size >= maxTombstones) {
973
+ const oldestKey = tombstones.keys().next().value;
974
+ if (oldestKey === undefined)
975
+ break;
976
+ tombstones.delete(oldestKey);
977
+ }
978
+ tombstones.set(correlationKey, tombstone);
979
+ }
980
+ function registerRequest(clientIdentity, requestId) {
981
+ const correlationKey = getRequestCorrelationKey(clientIdentity, requestId);
982
+ const controller = new AbortController();
983
+ const controllers = requestAbortControllers.get(correlationKey) ?? new Set();
984
+ controllers.add(controller);
985
+ requestAbortControllers.set(correlationKey, controllers);
986
+ const now = getNowMs();
987
+ pruneTombstones(now);
988
+ const tombstone = tombstones.get(correlationKey);
989
+ if (tombstone?.kind === 'pendingCancellation') {
990
+ tombstones.delete(correlationKey);
991
+ controller.abort(tombstone.reason);
992
+ }
993
+ let isTerminal = false;
994
+ return {
995
+ controller,
996
+ markTerminal: () => {
997
+ if (isTerminal)
998
+ return;
999
+ isTerminal = true;
1000
+ const completedAt = getNowMs();
1001
+ setTombstone(correlationKey, {
1002
+ kind: 'recentlyCompleted',
1003
+ expiresAt: completedAt + exports.schedulerMcpPendingCancellationTtlMs,
1004
+ }, completedAt);
1005
+ },
1006
+ unregister: () => {
1007
+ controllers.delete(controller);
1008
+ if (controllers.size === 0)
1009
+ requestAbortControllers.delete(correlationKey);
1010
+ },
1011
+ };
1012
+ }
1013
+ function cancelRequest(clientIdentity, requestId, reason) {
1014
+ const correlationKey = getRequestCorrelationKey(clientIdentity, requestId);
1015
+ const now = getNowMs();
1016
+ pruneTombstones(now);
1017
+ const controllers = requestAbortControllers.get(correlationKey);
1018
+ if (controllers && controllers.size > 0) {
1019
+ for (const controller of controllers)
1020
+ controller.abort(reason);
1021
+ return;
1022
+ }
1023
+ if (tombstones.get(correlationKey)?.kind === 'recentlyCompleted')
1024
+ return;
1025
+ setTombstone(correlationKey, {
1026
+ kind: 'pendingCancellation',
1027
+ expiresAt: now + exports.schedulerMcpPendingCancellationTtlMs,
1028
+ ...(reason !== undefined ? { reason } : {}),
1029
+ }, now);
1030
+ }
1031
+ return { registerRequest, cancelRequest };
1032
+ }
1033
+ /**
1034
+ * @description Build a fresh {@link McpServer} for one request, registering the
1035
+ * scope-bound scheduler tools plus the `send_file_to_user` tool. The SDK binds one server
1036
+ * per transport per connection, so a new instance is built (and closed) per
1037
+ * request in the stateless flow.
1038
+ */
1039
+ function buildRequestServer(deps, scope, requestSignal) {
1040
+ const platform = getSchedulerScopePlatform(scope);
1041
+ const server = new mcp_js_1.McpServer({ name: mcpServerName, version: mcpServerVersion }, { instructions: buildMcpServerInstructions(platform, deps.fetchJiraAttachment !== undefined) });
1042
+ registerBotTools(server, deps, scope, platform, requestSignal);
1043
+ return server;
1044
+ }
1045
+ /** The tools a session of `platform` gets — the one list the request path serves and the digest records. */
1046
+ function registerBotTools(server, deps, scope, platform, requestSignal) {
1047
+ // These deliver into a Telegram topic; for another platform's key they would throw (D18).
1048
+ if (platform === 'telegram') {
1049
+ registerSchedulerTools(server, deps, scope);
1050
+ registerFileSendTool(server, deps, scope, requestSignal);
1051
+ registerMessageSendTool(server, deps, scope, requestSignal);
1052
+ }
1053
+ // The original files of the conversation's own issue: only a Jira session, and only with the connector loaded.
1054
+ if (platform === 'jira' && deps.fetchJiraAttachment)
1055
+ registerJiraAttachmentTool(server, deps, deps.fetchJiraAttachment, scope);
1056
+ registerCompactConversationTool(server, deps, scope);
1057
+ registerAnswerRequestTool(server, deps, scope);
1058
+ if (deps.listClaudeProfiles)
1059
+ registerClaudeProfilesTool(server, deps.listClaudeProfiles);
1060
+ }
1061
+ /**
1062
+ * `claude_profiles`: which Claude account a child process should run on. Reads the bot's per-profile usage
1063
+ * cache (refreshed on demand by the port); touches no conversation, so it needs no scope resolution. The
1064
+ * answer is the report as JSON with a one-line verdict first, so an agent can act on it without parsing.
1065
+ */
1066
+ function registerClaudeProfilesTool(server, listClaudeProfiles) {
1067
+ server.registerTool('claude_profiles', {
1068
+ title: 'Claude accounts and their usage',
1069
+ description: 'The Claude account profiles signed in on this host, each with its usage windows — session (5 h), weekly ' +
1070
+ '(all models) and weekly Fable — as percent used + reset instant, and `recommended`: the profile with the most ' +
1071
+ 'headroom for the model you pass (Fable → its own weekly window + the session window; any other model → the ' +
1072
+ 'shared weekly window + the session window; signed-out and limited profiles are skipped). Call it BEFORE ' +
1073
+ 'launching a child `claude` and start the child with CLAUDE_CONFIG_DIR=<configDir> in its environment — ' +
1074
+ 'configDir null means the default profile: set nothing. Without the variable the child inherits the account ' +
1075
+ 'of this very session.',
1076
+ inputSchema: {
1077
+ model: zod_1.z
1078
+ .string()
1079
+ .max(64)
1080
+ .optional()
1081
+ .describe('The model the child will run (e.g. "fable", "opus", "sonnet"); decides which weekly window counts. Omit for the shared windows.'),
1082
+ },
1083
+ }, async (args) => {
1084
+ const report = await listClaudeProfiles(args.model?.trim() || null);
1085
+ const verdict = report.recommended === null
1086
+ ? 'No eligible profile: every signed-in account is limited or at 100 % on a relevant window.'
1087
+ : (() => {
1088
+ const entry = report.profiles.find((profile) => profile.name === report.recommended);
1089
+ const dir = entry?.configDir ?? null;
1090
+ return `recommended: ${report.recommended} → ${dir === null ? 'default profile, set no CLAUDE_CONFIG_DIR' : `CLAUDE_CONFIG_DIR=${dir}`}`;
1091
+ })();
1092
+ return textResult(`${verdict}\n${JSON.stringify(report, null, 1)}`);
1093
+ });
1094
+ }
1095
+ /** Read the whole request body into a string (the SDK wants the parsed JSON body). */
1096
+ function readRequestBody(req) {
1097
+ return new Promise((resolve, reject) => {
1098
+ const chunks = [];
1099
+ req.on('data', (chunk) => chunks.push(chunk));
1100
+ req.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
1101
+ req.on('error', reject);
1102
+ });
1103
+ }
1104
+ /** Write a JSON-RPC error response (used for the 401 / not-found paths the SDK doesn't reach). */
1105
+ function writeJsonRpcError(res, httpStatus, code, message) {
1106
+ res.writeHead(httpStatus, { 'Content-Type': 'application/json' });
1107
+ res.end(JSON.stringify({ jsonrpc: '2.0', error: { code, message }, id: null }));
1108
+ }
1109
+ /**
1110
+ * @description Create the bot-owned scheduler MCP server. Returns a handle with
1111
+ * `start`/`stop` and the bound `port`. The HTTP listener is plain `node:http`
1112
+ * (no web framework) on `127.0.0.1`; each request verifies the bearer token,
1113
+ * builds a fresh stateless transport + `McpServer`, and tears them down when the
1114
+ * response finishes. Invalid/missing tokens get a JSON-RPC 401 without touching
1115
+ * any tool.
1116
+ */
1117
+ function createSchedulerMcpServer(deps) {
1118
+ const requestedPort = deps.port ?? getSchedulerMcpPort();
1119
+ let boundPort = requestedPort;
1120
+ let httpServer = null;
1121
+ const sockets = new Set();
1122
+ const cancellationLifecycle = createSchedulerMcpCancellationLifecycle();
1123
+ function getClientIdentity(req, verifiedToken) {
1124
+ const clientId = req.headers[exports.schedulerMcpClientIdHeader];
1125
+ if (typeof clientId === 'string' &&
1126
+ clientId.length > 0 &&
1127
+ clientId.length <= schedulerMcpClientIdMaxLength &&
1128
+ schedulerMcpClientIdPattern.test(clientId)) {
1129
+ return `token:${verifiedToken}:client:${clientId}`;
1130
+ }
1131
+ return `token:${verifiedToken}`;
1132
+ }
1133
+ async function handleMcpRequest(req, res) {
1134
+ const secret = await deps.getSecret();
1135
+ const token = extractBearerToken(req.headers.authorization);
1136
+ const scope = token ? verifySchedulerMcpToken(secret, token) : null;
1137
+ if (!scope || token === null) {
1138
+ // -32001 (SDK's "unauthorized" convention) + HTTP 401, no tool touched.
1139
+ writeJsonRpcError(res, 401, -32001, 'Unauthorized: missing or invalid scheduler token');
1140
+ return;
1141
+ }
1142
+ if (req.method === 'GET') {
1143
+ // This server NEVER initiates a message: it is stateless, has no event
1144
+ // store, and every transport is built and closed around ONE request. The
1145
+ // spec's answer for exactly that case is 405, and the SDK client treats it
1146
+ // as expected and simply does not open a stream.
1147
+ //
1148
+ // Answering the SDK's way instead (200 + `text/event-stream`) hands the
1149
+ // client a standalone SSE stream that carries nothing and only ever ends
1150
+ // one way: the bot restarts, the socket dies, and the client burns its
1151
+ // reconnect budget against a port that is not listening yet. Hot mode
1152
+ // rebuilds on every code change, so that is a frequent event — and a
1153
+ // client that gives up latches the whole server `failed`, stranding the
1154
+ // bot's own tools in a session that was deliberately built to survive the
1155
+ // restart. Refusing the GET removes the thing that breaks.
1156
+ res.writeHead(405, { Allow: 'POST', 'Content-Type': 'application/json' });
1157
+ res.end(JSON.stringify({
1158
+ jsonrpc: '2.0',
1159
+ error: { code: -32000, message: 'Method Not Allowed: this endpoint does not offer an SSE stream' },
1160
+ id: null,
1161
+ }));
1162
+ return;
1163
+ }
1164
+ const clientIdentity = getClientIdentity(req, token);
1165
+ const bodyText = await readRequestBody(req);
1166
+ let parsedBody;
1167
+ try {
1168
+ parsedBody = bodyText.length > 0 ? JSON.parse(bodyText) : undefined;
1169
+ }
1170
+ catch {
1171
+ writeJsonRpcError(res, 400, -32700, 'Parse error: request body is not valid JSON');
1172
+ return;
1173
+ }
1174
+ const cancellation = types_js_1.CancelledNotificationSchema.safeParse(parsedBody);
1175
+ if (cancellation.success && cancellation.data.params.requestId !== undefined) {
1176
+ cancellationLifecycle.cancelRequest(clientIdentity, cancellation.data.params.requestId, cancellation.data.params.reason);
1177
+ }
1178
+ const request = types_js_1.JSONRPCRequestSchema.safeParse(parsedBody);
1179
+ const registeredRequest = request.success
1180
+ ? cancellationLifecycle.registerRequest(clientIdentity, request.data.id)
1181
+ : undefined;
1182
+ const transport = new streamableHttp_js_1.StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
1183
+ const server = buildRequestServer(deps, scope, registeredRequest?.controller.signal);
1184
+ // Stateless: the transport + server live only for this request; close both
1185
+ // when the response finishes so no connection state lingers.
1186
+ const markRequestTerminal = () => registeredRequest?.markTerminal();
1187
+ res.once('finish', markRequestTerminal);
1188
+ res.once('close', () => {
1189
+ res.off('finish', markRequestTerminal);
1190
+ registeredRequest?.markTerminal();
1191
+ registeredRequest?.controller.abort();
1192
+ registeredRequest?.unregister();
1193
+ void transport.close();
1194
+ void server.close();
1195
+ });
1196
+ await server.connect(transport);
1197
+ await transport.handleRequest(req, res, parsedBody);
1198
+ }
1199
+ function start() {
1200
+ return new Promise((resolve, reject) => {
1201
+ const server = (0, node_http_1.createServer)((req, res) => {
1202
+ if (req.url && req.url.split('?')[0] === exports.schedulerMcpPath) {
1203
+ handleMcpRequest(req, res).catch((error) => {
1204
+ console.error('[scheduler-mcp] request handling failed:', error);
1205
+ if (!res.headersSent) {
1206
+ writeJsonRpcError(res, 500, -32603, 'Internal error');
1207
+ }
1208
+ else {
1209
+ res.end();
1210
+ }
1211
+ });
1212
+ return;
1213
+ }
1214
+ writeJsonRpcError(res, 404, -32601, 'Not found');
1215
+ });
1216
+ server.on('connection', (socket) => {
1217
+ sockets.add(socket);
1218
+ socket.once('close', () => sockets.delete(socket));
1219
+ });
1220
+ const portBindRetry = deps.portBindRetry ?? { count: exports.schedulerMcpBindRetryCount, delayMs: exports.schedulerMcpBindRetryDelayMs };
1221
+ let retryCount = 0;
1222
+ let isFallenBack = false;
1223
+ const handleListening = () => {
1224
+ const address = server.address();
1225
+ if (address && typeof address === 'object')
1226
+ boundPort = address.port;
1227
+ httpServer = server;
1228
+ server.off('error', handleError);
1229
+ resolve();
1230
+ };
1231
+ const handleError = (error) => {
1232
+ // A non-zero requested port already in use (a persisted port a prior
1233
+ // generation still holds, or a sibling instance) must not wedge boot: it
1234
+ // is retried (`portBindRetry`), then bound on an ephemeral port ONCE.
1235
+ // Port 0 can never hit EADDRINUSE.
1236
+ if (error.code === 'EADDRINUSE' && requestedPort !== 0 && !isFallenBack) {
1237
+ // Track the server before the retry so a stop() in the retry window
1238
+ // still closes the eventually-bound listener (no orphan).
1239
+ httpServer = server;
1240
+ if (retryCount < portBindRetry.count) {
1241
+ if (retryCount === 0) {
1242
+ console.warn(`[scheduler-mcp] requested port ${requestedPort} is in use; retrying for up to ${portBindRetry.count * portBindRetry.delayMs} ms`);
1243
+ }
1244
+ retryCount += 1;
1245
+ setTimeout(() => {
1246
+ // A stop() during the wait already settled this server: binding now
1247
+ // would leave a listener nobody closes.
1248
+ if (httpServer !== server) {
1249
+ server.off('listening', handleListening);
1250
+ reject(new Error(`stopped while waiting for port ${requestedPort}`));
1251
+ return;
1252
+ }
1253
+ server.listen(requestedPort, '127.0.0.1');
1254
+ }, portBindRetry.delayMs);
1255
+ return;
1256
+ }
1257
+ isFallenBack = true;
1258
+ console.error(`[scheduler-mcp] requested port ${requestedPort} is still in use after ${portBindRetry.count * portBindRetry.delayMs} ms; ` +
1259
+ `falling back to an ephemeral port. A Claude session that was already running keeps the MCP address of its launch ` +
1260
+ `(127.0.0.1:${requestedPort}) and loses the bot's tools until it is restarted.`);
1261
+ server.listen(0, '127.0.0.1');
1262
+ return;
1263
+ }
1264
+ server.off('listening', handleListening);
1265
+ reject(error);
1266
+ };
1267
+ server.on('listening', handleListening);
1268
+ server.on('error', handleError);
1269
+ server.listen(requestedPort, '127.0.0.1');
1270
+ });
1271
+ }
1272
+ function stop() {
1273
+ return new Promise((resolve) => {
1274
+ if (!httpServer) {
1275
+ resolve();
1276
+ return;
1277
+ }
1278
+ httpServer.close(() => {
1279
+ httpServer = null;
1280
+ resolve();
1281
+ });
1282
+ // Streamable HTTP clients may retain an idle keep-alive connection after
1283
+ // their request completes; server.close() otherwise waits for it forever.
1284
+ for (const socket of sockets)
1285
+ socket.destroy();
1286
+ });
1287
+ }
1288
+ return {
1289
+ start,
1290
+ stop,
1291
+ getToolDigest: (platform) => getBotMcpToolDigest(deps, platform),
1292
+ get port() {
1293
+ return boundPort;
1294
+ },
1295
+ };
1296
+ }
1297
+ //# sourceMappingURL=mcpSurface.js.map