charness 3.6.1 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (578) hide show
  1. package/CHANGELOG.md +267 -0
  2. package/DEVELOPMENT.md +31 -5
  3. package/MIGRATION_RENAME_TO_CHARNESS.md +3 -2
  4. package/README.md +84 -782
  5. package/SETUP.md +37 -10
  6. package/agent-plugin/.claude-plugin/plugin.json +7 -0
  7. package/agent-plugin/README.md +35 -0
  8. package/agent-plugin/skills/charness-delegate-claude/SKILL.md +85 -0
  9. package/agent-plugin/skills/charness-delegate-claude/summarize-events.py +90 -0
  10. package/agent-plugin/skills/charness-delegate-opencode/SKILL.md +68 -0
  11. package/agent-plugin/skills/charness-manager/SKILL.md +152 -0
  12. package/dist/adapters/adapterNames.d.ts +6 -0
  13. package/dist/adapters/adapterNames.d.ts.map +1 -1
  14. package/dist/adapters/adapterNames.js +8 -2
  15. package/dist/adapters/adapterNames.js.map +1 -1
  16. package/dist/adapters/claudeCliAdapter.d.ts +8 -0
  17. package/dist/adapters/claudeCliAdapter.d.ts.map +1 -1
  18. package/dist/adapters/claudeCliAdapter.js +42 -5
  19. package/dist/adapters/claudeCliAdapter.js.map +1 -1
  20. package/dist/adapters/claudeJsonStreamAdapter.d.ts +10 -9
  21. package/dist/adapters/claudeJsonStreamAdapter.d.ts.map +1 -1
  22. package/dist/adapters/claudeJsonStreamAdapter.js +53 -55
  23. package/dist/adapters/claudeJsonStreamAdapter.js.map +1 -1
  24. package/dist/adapters/createAdapter.d.ts +8 -0
  25. package/dist/adapters/createAdapter.d.ts.map +1 -1
  26. package/dist/adapters/createAdapter.js +14 -2
  27. package/dist/adapters/createAdapter.js.map +1 -1
  28. package/dist/adapters/openCodeAdapter.d.ts +43 -6
  29. package/dist/adapters/openCodeAdapter.d.ts.map +1 -1
  30. package/dist/adapters/openCodeAdapter.js +95 -6
  31. package/dist/adapters/openCodeAdapter.js.map +1 -1
  32. package/dist/agentLogin/agentLogin.d.ts +1 -1
  33. package/dist/agentLogin/agentLogin.d.ts.map +1 -1
  34. package/dist/apiRetryKick.d.ts +4 -3
  35. package/dist/apiRetryKick.d.ts.map +1 -1
  36. package/dist/apiRetryKick.js +16 -9
  37. package/dist/apiRetryKick.js.map +1 -1
  38. package/dist/bot.d.ts.map +1 -1
  39. package/dist/bot.js +1313 -381
  40. package/dist/bot.js.map +1 -1
  41. package/dist/cli/claudeProfiles.d.ts +11 -6
  42. package/dist/cli/claudeProfiles.d.ts.map +1 -1
  43. package/dist/cli/claudeProfiles.js +50 -22
  44. package/dist/cli/claudeProfiles.js.map +1 -1
  45. package/dist/cli/hot.d.ts +5 -0
  46. package/dist/cli/hot.d.ts.map +1 -1
  47. package/dist/cli/hot.js +71 -25
  48. package/dist/cli/hot.js.map +1 -1
  49. package/dist/cli/tscWatchGuard.d.ts +95 -0
  50. package/dist/cli/tscWatchGuard.d.ts.map +1 -0
  51. package/dist/cli/tscWatchGuard.js +295 -0
  52. package/dist/cli/tscWatchGuard.js.map +1 -0
  53. package/dist/cli.js +12 -1
  54. package/dist/cli.js.map +1 -1
  55. package/dist/connectors/jira/answerSink.d.ts +10 -0
  56. package/dist/connectors/jira/answerSink.d.ts.map +1 -1
  57. package/dist/connectors/jira/answerSink.js +13 -0
  58. package/dist/connectors/jira/answerSink.js.map +1 -1
  59. package/dist/connectors/jira/config.d.ts +2 -0
  60. package/dist/connectors/jira/config.d.ts.map +1 -1
  61. package/dist/connectors/jira/config.js +9 -1
  62. package/dist/connectors/jira/config.js.map +1 -1
  63. package/dist/connectors/jira/connector.d.ts +11 -1
  64. package/dist/connectors/jira/connector.d.ts.map +1 -1
  65. package/dist/connectors/jira/connector.js +7 -0
  66. package/dist/connectors/jira/connector.js.map +1 -1
  67. package/dist/connectors/jira/inbound.d.ts +27 -4
  68. package/dist/connectors/jira/inbound.d.ts.map +1 -1
  69. package/dist/connectors/jira/inbound.js +69 -8
  70. package/dist/connectors/jira/inbound.js.map +1 -1
  71. package/dist/connectors/jira/issueBlocks.d.ts +5 -0
  72. package/dist/connectors/jira/issueBlocks.d.ts.map +1 -1
  73. package/dist/connectors/jira/issueBlocks.js +11 -0
  74. package/dist/connectors/jira/issueBlocks.js.map +1 -1
  75. package/dist/connectors/telegram/bindPicker.d.ts +5 -0
  76. package/dist/connectors/telegram/bindPicker.d.ts.map +1 -1
  77. package/dist/connectors/telegram/bindPicker.js +18 -1
  78. package/dist/connectors/telegram/bindPicker.js.map +1 -1
  79. package/dist/connectors/telegram/bindPickerClaims.d.ts +46 -0
  80. package/dist/connectors/telegram/bindPickerClaims.d.ts.map +1 -0
  81. package/dist/connectors/telegram/bindPickerClaims.js +83 -0
  82. package/dist/connectors/telegram/bindPickerClaims.js.map +1 -0
  83. package/dist/connectors/telegram/bindSweep.d.ts +32 -0
  84. package/dist/connectors/telegram/bindSweep.d.ts.map +1 -0
  85. package/dist/connectors/telegram/bindSweep.js +47 -0
  86. package/dist/connectors/telegram/bindSweep.js.map +1 -0
  87. package/dist/connectors/telegram/bindingWelcome.d.ts +23 -0
  88. package/dist/connectors/telegram/bindingWelcome.d.ts.map +1 -0
  89. package/dist/connectors/telegram/bindingWelcome.js +26 -0
  90. package/dist/connectors/telegram/bindingWelcome.js.map +1 -0
  91. package/dist/connectors/telegram/botApiConnection.d.ts +74 -0
  92. package/dist/connectors/telegram/botApiConnection.d.ts.map +1 -0
  93. package/dist/connectors/telegram/botApiConnection.js +201 -0
  94. package/dist/connectors/telegram/botApiConnection.js.map +1 -0
  95. package/dist/connectors/telegram/commands/botCore.d.ts +8 -2
  96. package/dist/connectors/telegram/commands/botCore.d.ts.map +1 -1
  97. package/dist/connectors/telegram/commands/botSkills.d.ts +21 -0
  98. package/dist/connectors/telegram/commands/botSkills.d.ts.map +1 -0
  99. package/dist/connectors/telegram/commands/botSkills.js +133 -0
  100. package/dist/connectors/telegram/commands/botSkills.js.map +1 -0
  101. package/dist/connectors/telegram/commands/callbackMessage.d.ts +5 -0
  102. package/dist/connectors/telegram/commands/callbackMessage.d.ts.map +1 -1
  103. package/dist/connectors/telegram/commands/callbackMessage.js +9 -0
  104. package/dist/connectors/telegram/commands/callbackMessage.js.map +1 -1
  105. package/dist/connectors/telegram/commands/compaction.d.ts +65 -3
  106. package/dist/connectors/telegram/commands/compaction.d.ts.map +1 -1
  107. package/dist/connectors/telegram/commands/compaction.js +512 -94
  108. package/dist/connectors/telegram/commands/compaction.js.map +1 -1
  109. package/dist/connectors/telegram/commands/displayModes.d.ts +1 -1
  110. package/dist/connectors/telegram/commands/displayModes.d.ts.map +1 -1
  111. package/dist/connectors/telegram/commands/displayModes.js +6 -18
  112. package/dist/connectors/telegram/commands/displayModes.js.map +1 -1
  113. package/dist/connectors/telegram/commands/fallbackChain.js +5 -5
  114. package/dist/connectors/telegram/commands/fallbackChain.js.map +1 -1
  115. package/dist/connectors/telegram/commands/reminders.d.ts +1 -1
  116. package/dist/connectors/telegram/commands/reminders.d.ts.map +1 -1
  117. package/dist/connectors/telegram/commands/reminders.js +4 -15
  118. package/dist/connectors/telegram/commands/reminders.js.map +1 -1
  119. package/dist/connectors/telegram/commands/selfUpdate.d.ts.map +1 -1
  120. package/dist/connectors/telegram/commands/selfUpdate.js +1 -11
  121. package/dist/connectors/telegram/commands/selfUpdate.js.map +1 -1
  122. package/dist/connectors/telegram/commands/taskAgents.d.ts +22 -0
  123. package/dist/connectors/telegram/commands/taskAgents.d.ts.map +1 -0
  124. package/dist/connectors/telegram/commands/taskAgents.js +104 -0
  125. package/dist/connectors/telegram/commands/taskAgents.js.map +1 -0
  126. package/dist/connectors/telegram/commands/todo.d.ts +82 -0
  127. package/dist/connectors/telegram/commands/todo.d.ts.map +1 -0
  128. package/dist/connectors/telegram/commands/todo.js +384 -0
  129. package/dist/connectors/telegram/commands/todo.js.map +1 -0
  130. package/dist/connectors/telegram/commands/topicCommand.d.ts +6 -2
  131. package/dist/connectors/telegram/commands/topicCommand.d.ts.map +1 -1
  132. package/dist/connectors/telegram/commands/topicCommand.js +6 -9
  133. package/dist/connectors/telegram/commands/topicCommand.js.map +1 -1
  134. package/dist/connectors/telegram/openBindMessages.d.ts +45 -0
  135. package/dist/connectors/telegram/openBindMessages.d.ts.map +1 -0
  136. package/dist/connectors/telegram/openBindMessages.js +67 -0
  137. package/dist/connectors/telegram/openBindMessages.js.map +1 -0
  138. package/dist/connectors/telegram/outputFlushPlan.d.ts +49 -0
  139. package/dist/connectors/telegram/outputFlushPlan.d.ts.map +1 -1
  140. package/dist/connectors/telegram/outputFlushPlan.js +46 -0
  141. package/dist/connectors/telegram/outputFlushPlan.js.map +1 -1
  142. package/dist/connectors/telegram/pendingTopicName.d.ts +26 -0
  143. package/dist/connectors/telegram/pendingTopicName.d.ts.map +1 -0
  144. package/dist/connectors/telegram/pendingTopicName.js +27 -0
  145. package/dist/connectors/telegram/pendingTopicName.js.map +1 -0
  146. package/dist/connectors/test/connector.d.ts.map +1 -1
  147. package/dist/connectors/test/connector.js +6 -1
  148. package/dist/connectors/test/connector.js.map +1 -1
  149. package/dist/i18n/de.d.ts.map +1 -1
  150. package/dist/i18n/de.js +90 -7
  151. package/dist/i18n/de.js.map +1 -1
  152. package/dist/i18n/en.d.ts.map +1 -1
  153. package/dist/i18n/en.js +90 -7
  154. package/dist/i18n/en.js.map +1 -1
  155. package/dist/i18n/es.d.ts.map +1 -1
  156. package/dist/i18n/es.js +90 -7
  157. package/dist/i18n/es.js.map +1 -1
  158. package/dist/i18n/fr.d.ts.map +1 -1
  159. package/dist/i18n/fr.js +90 -7
  160. package/dist/i18n/fr.js.map +1 -1
  161. package/dist/i18n/hi.d.ts.map +1 -1
  162. package/dist/i18n/hi.js +90 -7
  163. package/dist/i18n/hi.js.map +1 -1
  164. package/dist/i18n/ja.d.ts.map +1 -1
  165. package/dist/i18n/ja.js +90 -7
  166. package/dist/i18n/ja.js.map +1 -1
  167. package/dist/i18n/ka.d.ts.map +1 -1
  168. package/dist/i18n/ka.js +90 -7
  169. package/dist/i18n/ka.js.map +1 -1
  170. package/dist/i18n/pt.d.ts.map +1 -1
  171. package/dist/i18n/pt.js +90 -7
  172. package/dist/i18n/pt.js.map +1 -1
  173. package/dist/i18n/ru.d.ts.map +1 -1
  174. package/dist/i18n/ru.js +90 -7
  175. package/dist/i18n/ru.js.map +1 -1
  176. package/dist/i18n/uk.d.ts.map +1 -1
  177. package/dist/i18n/uk.js +90 -7
  178. package/dist/i18n/uk.js.map +1 -1
  179. package/dist/i18n/uz.d.ts.map +1 -1
  180. package/dist/i18n/uz.js +90 -7
  181. package/dist/i18n/uz.js.map +1 -1
  182. package/dist/i18n/zh.d.ts.map +1 -1
  183. package/dist/i18n/zh.js +90 -7
  184. package/dist/i18n/zh.js.map +1 -1
  185. package/dist/i18n.d.ts +1 -1
  186. package/dist/i18n.js +1 -1
  187. package/dist/installManager.d.ts +13 -0
  188. package/dist/installManager.d.ts.map +1 -1
  189. package/dist/installManager.js +38 -4
  190. package/dist/installManager.js.map +1 -1
  191. package/dist/instanceSettings.d.ts +40 -1
  192. package/dist/instanceSettings.d.ts.map +1 -1
  193. package/dist/instanceSettings.js +105 -26
  194. package/dist/instanceSettings.js.map +1 -1
  195. package/dist/openCodeQuestionFlow.d.ts +30 -0
  196. package/dist/openCodeQuestionFlow.d.ts.map +1 -1
  197. package/dist/openCodeQuestionFlow.js +43 -0
  198. package/dist/openCodeQuestionFlow.js.map +1 -1
  199. package/dist/postToSession.d.ts +20 -5
  200. package/dist/postToSession.d.ts.map +1 -1
  201. package/dist/postToSession.js +38 -7
  202. package/dist/postToSession.js.map +1 -1
  203. package/dist/remoteRun/cliArgs.d.ts +73 -0
  204. package/dist/remoteRun/cliArgs.d.ts.map +1 -0
  205. package/dist/remoteRun/cliArgs.js +197 -0
  206. package/dist/remoteRun/cliArgs.js.map +1 -0
  207. package/dist/remoteRun/commands.d.ts +56 -0
  208. package/dist/remoteRun/commands.d.ts.map +1 -0
  209. package/dist/remoteRun/commands.js +306 -0
  210. package/dist/remoteRun/commands.js.map +1 -0
  211. package/dist/remoteRun/depsPlan.d.ts +16 -0
  212. package/dist/remoteRun/depsPlan.d.ts.map +1 -0
  213. package/dist/remoteRun/depsPlan.js +82 -0
  214. package/dist/remoteRun/depsPlan.js.map +1 -0
  215. package/dist/remoteRun/exitCodes.d.ts +34 -0
  216. package/dist/remoteRun/exitCodes.d.ts.map +1 -0
  217. package/dist/remoteRun/exitCodes.js +38 -0
  218. package/dist/remoteRun/exitCodes.js.map +1 -0
  219. package/dist/remoteRun/foreground.d.ts +29 -0
  220. package/dist/remoteRun/foreground.d.ts.map +1 -0
  221. package/dist/remoteRun/foreground.js +159 -0
  222. package/dist/remoteRun/foreground.js.map +1 -0
  223. package/dist/remoteRun/interrupts.d.ts +17 -0
  224. package/dist/remoteRun/interrupts.d.ts.map +1 -0
  225. package/dist/remoteRun/interrupts.js +41 -0
  226. package/dist/remoteRun/interrupts.js.map +1 -0
  227. package/dist/remoteRun/jobFiles.d.ts +31 -0
  228. package/dist/remoteRun/jobFiles.d.ts.map +1 -0
  229. package/dist/remoteRun/jobFiles.js +84 -0
  230. package/dist/remoteRun/jobFiles.js.map +1 -0
  231. package/dist/remoteRun/jobFormat.d.ts +16 -0
  232. package/dist/remoteRun/jobFormat.d.ts.map +1 -0
  233. package/dist/remoteRun/jobFormat.js +130 -0
  234. package/dist/remoteRun/jobFormat.js.map +1 -0
  235. package/dist/remoteRun/jobId.d.ts +15 -0
  236. package/dist/remoteRun/jobId.d.ts.map +1 -0
  237. package/dist/remoteRun/jobId.js +85 -0
  238. package/dist/remoteRun/jobId.js.map +1 -0
  239. package/dist/remoteRun/jobMeta.d.ts +18 -0
  240. package/dist/remoteRun/jobMeta.d.ts.map +1 -0
  241. package/dist/remoteRun/jobMeta.js +33 -0
  242. package/dist/remoteRun/jobMeta.js.map +1 -0
  243. package/dist/remoteRun/jobQuery.d.ts +12 -0
  244. package/dist/remoteRun/jobQuery.d.ts.map +1 -0
  245. package/dist/remoteRun/jobQuery.js +22 -0
  246. package/dist/remoteRun/jobQuery.js.map +1 -0
  247. package/dist/remoteRun/jobRecords.d.ts +22 -0
  248. package/dist/remoteRun/jobRecords.d.ts.map +1 -0
  249. package/dist/remoteRun/jobRecords.js +145 -0
  250. package/dist/remoteRun/jobRecords.js.map +1 -0
  251. package/dist/remoteRun/jobState.d.ts +62 -0
  252. package/dist/remoteRun/jobState.d.ts.map +1 -0
  253. package/dist/remoteRun/jobState.js +132 -0
  254. package/dist/remoteRun/jobState.js.map +1 -0
  255. package/dist/remoteRun/leaseTiming.d.ts +18 -0
  256. package/dist/remoteRun/leaseTiming.d.ts.map +1 -0
  257. package/dist/remoteRun/leaseTiming.js +43 -0
  258. package/dist/remoteRun/leaseTiming.js.map +1 -0
  259. package/dist/remoteRun/output.d.ts +35 -0
  260. package/dist/remoteRun/output.d.ts.map +1 -0
  261. package/dist/remoteRun/output.js +82 -0
  262. package/dist/remoteRun/output.js.map +1 -0
  263. package/dist/remoteRun/pathPatterns.d.ts +33 -0
  264. package/dist/remoteRun/pathPatterns.d.ts.map +1 -0
  265. package/dist/remoteRun/pathPatterns.js +115 -0
  266. package/dist/remoteRun/pathPatterns.js.map +1 -0
  267. package/dist/remoteRun/probe.d.ts +56 -0
  268. package/dist/remoteRun/probe.d.ts.map +1 -0
  269. package/dist/remoteRun/probe.js +123 -0
  270. package/dist/remoteRun/probe.js.map +1 -0
  271. package/dist/remoteRun/project.d.ts +26 -0
  272. package/dist/remoteRun/project.d.ts.map +1 -0
  273. package/dist/remoteRun/project.js +159 -0
  274. package/dist/remoteRun/project.js.map +1 -0
  275. package/dist/remoteRun/projectConfig.d.ts +38 -0
  276. package/dist/remoteRun/projectConfig.d.ts.map +1 -0
  277. package/dist/remoteRun/projectConfig.js +87 -0
  278. package/dist/remoteRun/projectConfig.js.map +1 -0
  279. package/dist/remoteRun/remoteRunCli.d.ts +15 -0
  280. package/dist/remoteRun/remoteRunCli.d.ts.map +1 -0
  281. package/dist/remoteRun/remoteRunCli.js +144 -0
  282. package/dist/remoteRun/remoteRunCli.js.map +1 -0
  283. package/dist/remoteRun/remoteRunError.d.ts +14 -0
  284. package/dist/remoteRun/remoteRunError.d.ts.map +1 -0
  285. package/dist/remoteRun/remoteRunError.js +28 -0
  286. package/dist/remoteRun/remoteRunError.js.map +1 -0
  287. package/dist/remoteRun/rsync.d.ts +17 -0
  288. package/dist/remoteRun/rsync.d.ts.map +1 -0
  289. package/dist/remoteRun/rsync.js +39 -0
  290. package/dist/remoteRun/rsync.js.map +1 -0
  291. package/dist/remoteRun/runnerClient.d.ts +50 -0
  292. package/dist/remoteRun/runnerClient.d.ts.map +1 -0
  293. package/dist/remoteRun/runnerClient.js +139 -0
  294. package/dist/remoteRun/runnerClient.js.map +1 -0
  295. package/dist/remoteRun/runners.d.ts +57 -0
  296. package/dist/remoteRun/runners.d.ts.map +1 -0
  297. package/dist/remoteRun/runners.js +181 -0
  298. package/dist/remoteRun/runners.js.map +1 -0
  299. package/dist/remoteRun/runnersConfig.d.ts +44 -0
  300. package/dist/remoteRun/runnersConfig.d.ts.map +1 -0
  301. package/dist/remoteRun/runnersConfig.js +107 -0
  302. package/dist/remoteRun/runnersConfig.js.map +1 -0
  303. package/dist/remoteRun/safeCopy.d.ts +31 -0
  304. package/dist/remoteRun/safeCopy.d.ts.map +1 -0
  305. package/dist/remoteRun/safeCopy.js +137 -0
  306. package/dist/remoteRun/safeCopy.js.map +1 -0
  307. package/dist/remoteRun/sendPlan.d.ts +67 -0
  308. package/dist/remoteRun/sendPlan.d.ts.map +1 -0
  309. package/dist/remoteRun/sendPlan.js +139 -0
  310. package/dist/remoteRun/sendPlan.js.map +1 -0
  311. package/dist/remoteRun/ssh.d.ts +62 -0
  312. package/dist/remoteRun/ssh.d.ts.map +1 -0
  313. package/dist/remoteRun/ssh.js +202 -0
  314. package/dist/remoteRun/ssh.js.map +1 -0
  315. package/dist/remoteRun/submit.d.ts +29 -0
  316. package/dist/remoteRun/submit.d.ts.map +1 -0
  317. package/dist/remoteRun/submit.js +142 -0
  318. package/dist/remoteRun/submit.js.map +1 -0
  319. package/dist/requests/answerRequest.d.ts +5 -0
  320. package/dist/requests/answerRequest.d.ts.map +1 -1
  321. package/dist/requests/answerRequest.js +16 -1
  322. package/dist/requests/answerRequest.js.map +1 -1
  323. package/dist/requests/requestLedger.d.ts +13 -0
  324. package/dist/requests/requestLedger.d.ts.map +1 -1
  325. package/dist/requests/requestLedger.js +9 -0
  326. package/dist/requests/requestLedger.js.map +1 -1
  327. package/dist/requests/topicRequestSettle.d.ts +30 -0
  328. package/dist/requests/topicRequestSettle.d.ts.map +1 -0
  329. package/dist/requests/topicRequestSettle.js +23 -0
  330. package/dist/requests/topicRequestSettle.js.map +1 -0
  331. package/dist/requests/wakeUpEngine.d.ts +4 -0
  332. package/dist/requests/wakeUpEngine.d.ts.map +1 -1
  333. package/dist/requests/wakeUpEngine.js +5 -1
  334. package/dist/requests/wakeUpEngine.js.map +1 -1
  335. package/dist/scheduler/delivery.d.ts +2 -0
  336. package/dist/scheduler/delivery.d.ts.map +1 -1
  337. package/dist/scheduler/delivery.js +8 -4
  338. package/dist/scheduler/delivery.js.map +1 -1
  339. package/dist/scheduler/mcpSurface.d.ts +59 -10
  340. package/dist/scheduler/mcpSurface.d.ts.map +1 -1
  341. package/dist/scheduler/mcpSurface.js +276 -79
  342. package/dist/scheduler/mcpSurface.js.map +1 -1
  343. package/dist/scheduler/recurrence.d.ts +5 -0
  344. package/dist/scheduler/recurrence.d.ts.map +1 -1
  345. package/dist/scheduler/recurrence.js +12 -2
  346. package/dist/scheduler/recurrence.js.map +1 -1
  347. package/dist/scheduler/strictToolInput.d.ts +45 -0
  348. package/dist/scheduler/strictToolInput.d.ts.map +1 -0
  349. package/dist/scheduler/strictToolInput.js +155 -0
  350. package/dist/scheduler/strictToolInput.js.map +1 -0
  351. package/dist/scheduler/types.d.ts +5 -0
  352. package/dist/scheduler/types.d.ts.map +1 -1
  353. package/dist/scheduler/workerWatch.d.ts +23 -0
  354. package/dist/scheduler/workerWatch.d.ts.map +1 -0
  355. package/dist/scheduler/workerWatch.js +26 -0
  356. package/dist/scheduler/workerWatch.js.map +1 -0
  357. package/dist/selfUpdate/emittedSource.d.ts +11 -0
  358. package/dist/selfUpdate/emittedSource.d.ts.map +1 -0
  359. package/dist/selfUpdate/emittedSource.js +24 -0
  360. package/dist/selfUpdate/emittedSource.js.map +1 -0
  361. package/dist/selfUpdate/gitSource.d.ts +0 -6
  362. package/dist/selfUpdate/gitSource.d.ts.map +1 -1
  363. package/dist/selfUpdate/gitSource.js +2 -18
  364. package/dist/selfUpdate/gitSource.js.map +1 -1
  365. package/dist/selfUpdate/updatePending.d.ts +1 -1
  366. package/dist/sendErrorClassifier.d.ts +10 -0
  367. package/dist/sendErrorClassifier.d.ts.map +1 -1
  368. package/dist/sendErrorClassifier.js +22 -0
  369. package/dist/sendErrorClassifier.js.map +1 -1
  370. package/dist/state.d.ts +78 -7
  371. package/dist/state.d.ts.map +1 -1
  372. package/dist/state.js +125 -8
  373. package/dist/state.js.map +1 -1
  374. package/dist/stateFile.d.ts +9 -0
  375. package/dist/stateFile.d.ts.map +1 -0
  376. package/dist/stateFile.js +57 -0
  377. package/dist/stateFile.js.map +1 -0
  378. package/dist/stt/sttInstall.d.ts +7 -3
  379. package/dist/stt/sttInstall.d.ts.map +1 -1
  380. package/dist/stt/sttInstall.js +8 -4
  381. package/dist/stt/sttInstall.js.map +1 -1
  382. package/dist/stt/sttSettings.d.ts +2 -1
  383. package/dist/stt/sttSettings.d.ts.map +1 -1
  384. package/dist/stt/sttSettings.js +3 -2
  385. package/dist/stt/sttSettings.js.map +1 -1
  386. package/dist/stt/transcribeChain.js +2 -0
  387. package/dist/stt/transcribeChain.js.map +1 -1
  388. package/dist/testTimings.d.ts +13 -3
  389. package/dist/testTimings.d.ts.map +1 -1
  390. package/dist/testTimings.js +26 -2
  391. package/dist/testTimings.js.map +1 -1
  392. package/dist/todos/board.d.ts +83 -0
  393. package/dist/todos/board.d.ts.map +1 -0
  394. package/dist/todos/board.js +227 -0
  395. package/dist/todos/board.js.map +1 -0
  396. package/dist/todos/format.d.ts +33 -0
  397. package/dist/todos/format.d.ts.map +1 -0
  398. package/dist/todos/format.js +90 -0
  399. package/dist/todos/format.js.map +1 -0
  400. package/dist/todos/merge.d.ts +46 -0
  401. package/dist/todos/merge.d.ts.map +1 -0
  402. package/dist/todos/merge.js +137 -0
  403. package/dist/todos/merge.js.map +1 -0
  404. package/dist/todos/midTurn.d.ts +75 -0
  405. package/dist/todos/midTurn.d.ts.map +1 -0
  406. package/dist/todos/midTurn.js +214 -0
  407. package/dist/todos/midTurn.js.map +1 -0
  408. package/dist/todos/nag.d.ts +85 -0
  409. package/dist/todos/nag.d.ts.map +1 -0
  410. package/dist/todos/nag.js +103 -0
  411. package/dist/todos/nag.js.map +1 -0
  412. package/dist/todos/order.d.ts +25 -0
  413. package/dist/todos/order.d.ts.map +1 -0
  414. package/dist/todos/order.js +61 -0
  415. package/dist/todos/order.js.map +1 -0
  416. package/dist/todos/projects.d.ts +102 -0
  417. package/dist/todos/projects.d.ts.map +1 -0
  418. package/dist/todos/projects.js +342 -0
  419. package/dist/todos/projects.js.map +1 -0
  420. package/dist/todos/registry.d.ts +64 -0
  421. package/dist/todos/registry.d.ts.map +1 -0
  422. package/dist/todos/registry.js +116 -0
  423. package/dist/todos/registry.js.map +1 -0
  424. package/dist/todos/reminderEngine.d.ts +78 -0
  425. package/dist/todos/reminderEngine.d.ts.map +1 -0
  426. package/dist/todos/reminderEngine.js +162 -0
  427. package/dist/todos/reminderEngine.js.map +1 -0
  428. package/dist/todos/store.d.ts +34 -0
  429. package/dist/todos/store.d.ts.map +1 -0
  430. package/dist/todos/store.js +208 -0
  431. package/dist/todos/store.js.map +1 -0
  432. package/dist/todos/tools.d.ts +26 -0
  433. package/dist/todos/tools.d.ts.map +1 -0
  434. package/dist/todos/tools.js +25 -0
  435. package/dist/todos/tools.js.map +1 -0
  436. package/dist/todos/types.d.ts +85 -0
  437. package/dist/todos/types.d.ts.map +1 -0
  438. package/dist/todos/types.js +30 -0
  439. package/dist/todos/types.js.map +1 -0
  440. package/dist/trackers/taskAgentLimit.d.ts +58 -0
  441. package/dist/trackers/taskAgentLimit.d.ts.map +1 -0
  442. package/dist/trackers/taskAgentLimit.js +62 -0
  443. package/dist/trackers/taskAgentLimit.js.map +1 -0
  444. package/dist/trackers/taskAgentSlots.d.ts +109 -0
  445. package/dist/trackers/taskAgentSlots.d.ts.map +1 -0
  446. package/dist/trackers/taskAgentSlots.js +227 -0
  447. package/dist/trackers/taskAgentSlots.js.map +1 -0
  448. package/dist/trackers/types.d.ts +14 -0
  449. package/dist/trackers/types.d.ts.map +1 -0
  450. package/dist/trackers/types.js +3 -0
  451. package/dist/trackers/types.js.map +1 -0
  452. package/dist/types.d.ts +80 -4
  453. package/dist/types.d.ts.map +1 -1
  454. package/dist/utils/adoptReplayGate.d.ts +16 -0
  455. package/dist/utils/adoptReplayGate.d.ts.map +1 -0
  456. package/dist/utils/adoptReplayGate.js +35 -0
  457. package/dist/utils/adoptReplayGate.js.map +1 -0
  458. package/dist/utils/agentPlugin.d.ts +113 -0
  459. package/dist/utils/agentPlugin.d.ts.map +1 -0
  460. package/dist/utils/agentPlugin.js +192 -0
  461. package/dist/utils/agentPlugin.js.map +1 -0
  462. package/dist/utils/autoContinueOnLimit.d.ts +7 -4
  463. package/dist/utils/autoContinueOnLimit.d.ts.map +1 -1
  464. package/dist/utils/autoContinueOnLimit.js +8 -5
  465. package/dist/utils/autoContinueOnLimit.js.map +1 -1
  466. package/dist/utils/botSkills.d.ts +62 -0
  467. package/dist/utils/botSkills.d.ts.map +1 -0
  468. package/dist/utils/botSkills.js +53 -0
  469. package/dist/utils/botSkills.js.map +1 -0
  470. package/dist/utils/botSkillsSetting.d.ts +7 -0
  471. package/dist/utils/botSkillsSetting.d.ts.map +1 -0
  472. package/dist/utils/botSkillsSetting.js +9 -0
  473. package/dist/utils/botSkillsSetting.js.map +1 -0
  474. package/dist/utils/claudeCodeVersion.d.ts +7 -0
  475. package/dist/utils/claudeCodeVersion.d.ts.map +1 -1
  476. package/dist/utils/claudeCodeVersion.js +14 -1
  477. package/dist/utils/claudeCodeVersion.js.map +1 -1
  478. package/dist/utils/claudeCompactHook.d.ts +33 -15
  479. package/dist/utils/claudeCompactHook.d.ts.map +1 -1
  480. package/dist/utils/claudeCompactHook.js +36 -17
  481. package/dist/utils/claudeCompactHook.js.map +1 -1
  482. package/dist/utils/claudeCompactSummary.d.ts +15 -0
  483. package/dist/utils/claudeCompactSummary.d.ts.map +1 -0
  484. package/dist/utils/claudeCompactSummary.js +96 -0
  485. package/dist/utils/claudeCompactSummary.js.map +1 -0
  486. package/dist/utils/claudeLimitSwitch.d.ts +11 -9
  487. package/dist/utils/claudeLimitSwitch.d.ts.map +1 -1
  488. package/dist/utils/claudeLimitSwitch.js +18 -16
  489. package/dist/utils/claudeLimitSwitch.js.map +1 -1
  490. package/dist/utils/claudeProfiles.d.ts +5 -0
  491. package/dist/utils/claudeProfiles.d.ts.map +1 -1
  492. package/dist/utils/claudeProfiles.js +14 -0
  493. package/dist/utils/claudeProfiles.js.map +1 -1
  494. package/dist/utils/claudeSessionTitle.d.ts +2 -1
  495. package/dist/utils/claudeSessionTitle.d.ts.map +1 -1
  496. package/dist/utils/claudeSessionTitle.js +14 -14
  497. package/dist/utils/claudeSessionTitle.js.map +1 -1
  498. package/dist/utils/claudeUsage.d.ts +95 -15
  499. package/dist/utils/claudeUsage.d.ts.map +1 -1
  500. package/dist/utils/claudeUsage.js +241 -41
  501. package/dist/utils/claudeUsage.js.map +1 -1
  502. package/dist/utils/claudeUsageRefresher.d.ts +10 -0
  503. package/dist/utils/claudeUsageRefresher.d.ts.map +1 -1
  504. package/dist/utils/claudeUsageRefresher.js +11 -0
  505. package/dist/utils/claudeUsageRefresher.js.map +1 -1
  506. package/dist/utils/claudeUserEntry.d.ts +50 -0
  507. package/dist/utils/claudeUserEntry.d.ts.map +1 -0
  508. package/dist/utils/claudeUserEntry.js +120 -0
  509. package/dist/utils/claudeUserEntry.js.map +1 -0
  510. package/dist/utils/clearThreadOutputQueues.d.ts +4 -3
  511. package/dist/utils/clearThreadOutputQueues.d.ts.map +1 -1
  512. package/dist/utils/clearThreadOutputQueues.js +1 -1
  513. package/dist/utils/clearThreadOutputQueues.js.map +1 -1
  514. package/dist/utils/compactOnIdle.d.ts +33 -13
  515. package/dist/utils/compactOnIdle.d.ts.map +1 -1
  516. package/dist/utils/compactOnIdle.js +35 -15
  517. package/dist/utils/compactOnIdle.js.map +1 -1
  518. package/dist/utils/fallbackBridge.d.ts +5 -0
  519. package/dist/utils/fallbackBridge.d.ts.map +1 -1
  520. package/dist/utils/fallbackBridge.js +19 -3
  521. package/dist/utils/fallbackBridge.js.map +1 -1
  522. package/dist/utils/fallbackChain.d.ts +9 -3
  523. package/dist/utils/fallbackChain.d.ts.map +1 -1
  524. package/dist/utils/fallbackChain.js +21 -3
  525. package/dist/utils/fallbackChain.js.map +1 -1
  526. package/dist/utils/fileSendPlan.d.ts +6 -0
  527. package/dist/utils/fileSendPlan.d.ts.map +1 -1
  528. package/dist/utils/fileSendPlan.js +11 -0
  529. package/dist/utils/fileSendPlan.js.map +1 -1
  530. package/dist/utils/fileSendService.d.ts +7 -1
  531. package/dist/utils/fileSendService.d.ts.map +1 -1
  532. package/dist/utils/fileSendService.js +6 -2
  533. package/dist/utils/fileSendService.js.map +1 -1
  534. package/dist/utils/groupFinalizePlan.d.ts +8 -10
  535. package/dist/utils/groupFinalizePlan.d.ts.map +1 -1
  536. package/dist/utils/groupFinalizePlan.js +8 -12
  537. package/dist/utils/groupFinalizePlan.js.map +1 -1
  538. package/dist/utils/jsonStreamHost.d.ts +13 -0
  539. package/dist/utils/jsonStreamHost.d.ts.map +1 -1
  540. package/dist/utils/jsonStreamHost.js +13 -0
  541. package/dist/utils/jsonStreamHost.js.map +1 -1
  542. package/dist/utils/messageSendService.d.ts +5 -3
  543. package/dist/utils/messageSendService.d.ts.map +1 -1
  544. package/dist/utils/messageSendService.js +12 -5
  545. package/dist/utils/messageSendService.js.map +1 -1
  546. package/dist/utils/openCodeCompactPlugin.d.ts +39 -14
  547. package/dist/utils/openCodeCompactPlugin.d.ts.map +1 -1
  548. package/dist/utils/openCodeCompactPlugin.js +106 -38
  549. package/dist/utils/openCodeCompactPlugin.js.map +1 -1
  550. package/dist/utils/promptDelivery.d.ts +29 -12
  551. package/dist/utils/promptDelivery.d.ts.map +1 -1
  552. package/dist/utils/promptDelivery.js +13 -5
  553. package/dist/utils/promptDelivery.js.map +1 -1
  554. package/dist/utils/sentKindsSummary.d.ts +10 -0
  555. package/dist/utils/sentKindsSummary.d.ts.map +1 -0
  556. package/dist/utils/sentKindsSummary.js +18 -0
  557. package/dist/utils/sentKindsSummary.js.map +1 -0
  558. package/dist/utils/telegramError.d.ts +6 -0
  559. package/dist/utils/telegramError.d.ts.map +1 -1
  560. package/dist/utils/telegramError.js +12 -0
  561. package/dist/utils/telegramError.js.map +1 -1
  562. package/dist/utils/topicView.d.ts +1 -1
  563. package/dist/utils/topicView.js +1 -1
  564. package/dist/utils/transcribeAudio.d.ts +10 -0
  565. package/dist/utils/transcribeAudio.d.ts.map +1 -1
  566. package/dist/utils/transcribeAudio.js +22 -3
  567. package/dist/utils/transcribeAudio.js.map +1 -1
  568. package/dist/utils/transcriptErrorTime.d.ts +8 -0
  569. package/dist/utils/transcriptErrorTime.d.ts.map +1 -0
  570. package/dist/utils/transcriptErrorTime.js +56 -0
  571. package/dist/utils/transcriptErrorTime.js.map +1 -0
  572. package/dist/utils/wedgeRecovery.d.ts +2 -0
  573. package/dist/utils/wedgeRecovery.d.ts.map +1 -1
  574. package/dist/utils/wedgeRecovery.js +1 -1
  575. package/dist/utils/wedgeRecovery.js.map +1 -1
  576. package/package.json +11 -3
  577. package/remoteRun/runner.sh +1242 -0
  578. package/stt/gigaam_sidecar.py +555 -50
@@ -18,6 +18,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.getSessionTitleLine = getSessionTitleLine;
19
19
  exports.getSessionTitleCandidate = getSessionTitleCandidate;
20
20
  const threadContextPreamble_1 = require("../threadContextPreamble");
21
+ const claudeUserEntry_1 = require("./claudeUserEntry");
21
22
  /**
22
23
  * @description Leading `[Scheduled run "<name>"]` marker a scheduled run glues
23
24
  * ahead of its prompt (see `scheduler/delivery.ts`). Anchored + single `\n`,
@@ -25,22 +26,14 @@ const threadContextPreamble_1 = require("../threadContextPreamble");
25
26
  */
26
27
  const scheduledRunMarkerRe = /^\[Scheduled run "[^"]*"\]\n/;
27
28
  /**
28
- * @description Prompt prefixes that mark a stored user turn as bot/tooling
29
- * plumbing rather than a real topic — never a session title. Matched after the
30
- * preamble/marker is stripped and whitespace collapsed.
29
+ * @description Prompt prefixes that mark a stored user turn as bot-generated rather than a real topic — never a
30
+ * session title, though the turn is a real message. Matched after the preamble/marker is stripped and whitespace
31
+ * collapsed. (What the CLI itself injects is told apart by `classifyClaudeUserEntry`.)
31
32
  */
32
33
  const noisePromptPrefixes = [
33
34
  '[Telegram thread context]', // a preamble with no prompt after it (strip failed)
34
35
  '[Telegram file]',
35
36
  '[Telegram album]',
36
- '[Request interrupted',
37
- '<local-command-', // stdout / stderr / caveat wrappers around a slash command
38
- '<command-',
39
- '<task-notification>',
40
- '<system-reminder>',
41
- '<tool-use-',
42
- 'Base directory for this skill:',
43
- 'Caveat: The messages below',
44
37
  ];
45
38
  /**
46
39
  * @description Whole-prompt values that are follow-up chatter, never a topic:
@@ -51,7 +44,10 @@ const noiseExactPrompts = new Set([
51
44
  'да', 'нет', 'ага', 'угу', 'давай', 'да, давай', 'да, давай.',
52
45
  'commit', 'commit.', 'push', 'пуш', 'коммить', 'коммит', 'обнови my',
53
46
  ]);
54
- /** Effort / model slash-command stdout that lost its `<local-command-*>` wrapper. */
47
+ /**
48
+ * Effort / model slash-command stdout that lost its `<local-command-*>` wrapper. Not a topic, but a message somebody
49
+ * may type ("Set model to … in the config"), so only the titles skip it.
50
+ */
55
51
  const commandEchoRe = /^set (effort level|model) /i;
56
52
  /**
57
53
  * @description Strip the bot's service wrappers (thread-context preamble first —
@@ -77,10 +73,14 @@ function checkIsNoisePrompt(line) {
77
73
  }
78
74
  /**
79
75
  * @description A session-title candidate from ONE stored prompt: the stripped
80
- * single-line topic, or `null` when the prompt is empty or tooling noise.
76
+ * single-line topic, or `null` when the prompt is empty, a slash command run in
77
+ * the CLI, text the CLI injected, or other tooling noise.
81
78
  */
82
79
  function getSessionTitleCandidate(rawPrompt) {
83
- const line = getSessionTitleLine(rawPrompt);
80
+ const entry = (0, claudeUserEntry_1.classifyClaudeUserEntry)(rawPrompt);
81
+ if (entry.kind !== 'message')
82
+ return null;
83
+ const line = getSessionTitleLine(entry.text);
84
84
  if (!line)
85
85
  return null;
86
86
  if (checkIsNoisePrompt(line))
@@ -1 +1 @@
1
- {"version":3,"file":"claudeSessionTitle.js","sourceRoot":"","sources":["../../src/utils/claudeSessionTitle.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;AAgDH,kDAKC;AAeD,4DAKC;AAvED,oEAAsE;AAEtE;;;;GAIG;AACH,MAAM,oBAAoB,GAAG,8BAA8B,CAAC;AAE5D;;;;GAIG;AACH,MAAM,mBAAmB,GAAG;IAC1B,2BAA2B,EAAE,oDAAoD;IACjF,iBAAiB;IACjB,kBAAkB;IAClB,sBAAsB;IACtB,iBAAiB,EAAE,2DAA2D;IAC9E,WAAW;IACX,qBAAqB;IACrB,mBAAmB;IACnB,YAAY;IACZ,gCAAgC;IAChC,4BAA4B;CAC7B,CAAC;AAEF;;;GAGG;AACH,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IAChC,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU;IACvE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY;IAC7D,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW;CACrE,CAAC,CAAC;AAEH,qFAAqF;AACrF,MAAM,aAAa,GAAG,6BAA6B,CAAC;AAEpD;;;;GAIG;AACH,SAAgB,mBAAmB,CAAC,SAAiB;IACnD,IAAI,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,GAAG,IAAA,kDAA0B,EAAC,IAAI,CAAC,CAAC;IACxC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AAC1C,CAAC;AAED,wFAAwF;AACxF,SAAS,kBAAkB,CAAC,IAAY;IACtC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,IAAI,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9C,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,CAAC,gCAAgC;IACrE,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1C,OAAO,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AACrE,CAAC;AAED;;;GAGG;AACH,SAAgB,wBAAwB,CAAC,SAAiB;IACxD,MAAM,IAAI,GAAG,mBAAmB,CAAC,SAAS,CAAC,CAAC;IAC5C,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,IAAI,kBAAkB,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1C,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"claudeSessionTitle.js","sourceRoot":"","sources":["../../src/utils/claudeSessionTitle.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;AA4CH,kDAKC;AAgBD,4DAOC;AAtED,oEAAsE;AACtE,uDAA4D;AAE5D;;;;GAIG;AACH,MAAM,oBAAoB,GAAG,8BAA8B,CAAC;AAE5D;;;;GAIG;AACH,MAAM,mBAAmB,GAAG;IAC1B,2BAA2B,EAAE,oDAAoD;IACjF,iBAAiB;IACjB,kBAAkB;CACnB,CAAC;AAEF;;;GAGG;AACH,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IAChC,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU;IACvE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY;IAC7D,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW;CACrE,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,aAAa,GAAG,6BAA6B,CAAC;AAEpD;;;;GAIG;AACH,SAAgB,mBAAmB,CAAC,SAAiB;IACnD,IAAI,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,GAAG,IAAA,kDAA0B,EAAC,IAAI,CAAC,CAAC;IACxC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AAC1C,CAAC;AAED,wFAAwF;AACxF,SAAS,kBAAkB,CAAC,IAAY;IACtC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,IAAI,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9C,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,CAAC,gCAAgC;IACrE,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1C,OAAO,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AACrE,CAAC;AAED;;;;GAIG;AACH,SAAgB,wBAAwB,CAAC,SAAiB;IACxD,MAAM,KAAK,GAAG,IAAA,yCAAuB,EAAC,SAAS,CAAC,CAAC;IACjD,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC1C,MAAM,IAAI,GAAG,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7C,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,IAAI,kBAAkB,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1C,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * @description Per-profile Claude USAGE — how much of each subscription window an account profile
3
- * (`utils/claudeProfiles.ts`) has used, and which profile a new process should run on.
3
+ * (`utils/claudeProfiles.ts`) has used, and which profile a process should run on: a NEW agent goes to the
4
+ * account whose weekly window resets soonest (spend first what burns soonest), a WARM session stays on the
5
+ * account it worked on ({@link getClaudeLaunchPick}).
4
6
  *
5
7
  * Two sources feed one snapshot per profile (`ClaudeProfileRecord.usage`):
6
8
  * - the OAuth usage endpoint (`GET https://api.anthropic.com/api/oauth/usage`, the profile's own access
@@ -184,7 +186,8 @@ export interface ClaudeProfileReportEntry {
184
186
  subscriptionType: string | null;
185
187
  /**
186
188
  * `api`: billed per request to a Claude Console organization's API credits — no windows, so no headroom figure, and
187
- * NEVER `isRecommended` (it would look inexhaustible and spend money). `null`: a subscription not recorded as such.
189
+ * NEVER picked for a NEW agent (it would look inexhaustible and spend money); only a warm session already on it stays.
190
+ * `null`: a subscription not recorded as such.
188
191
  */
189
192
  billing: ClaudeProfileBilling | null;
190
193
  /** `null` when never probed. */
@@ -195,29 +198,106 @@ export interface ClaudeProfileReportEntry {
195
198
  limitedUntil: string | null;
196
199
  /** When its prepaid API credits were found used up (`null`: not marked). */
197
200
  creditExhaustedAt: string | null;
198
- /** Signed in, not limited, its API credits not used up, and not at 100 % on a window the model drains. */
201
+ /** Signed in, not limited, its API credits not used up, and not at 100 % on a window the model drains — by the figures AS RECORDED. */
199
202
  isEligible: boolean;
200
- /** `100 − max(relevant percent)`; `null` when the usage is unknown. */
203
+ /** `100 − max(relevant percent)`; `null` when the usage is unknown. Informational: the pick ranks by reset, not by headroom. */
201
204
  headroomPercent: number | null;
205
+ /** The profile {@link getClaudeLaunchPick} chose (the figures read as of now). */
202
206
  isRecommended: boolean;
203
207
  }
204
208
  export interface ClaudeProfilesReport {
205
209
  model: string | null;
206
- /** The windows the ranking looked at for `model`. */
210
+ /** The windows the pick looked at for `model`. */
207
211
  relevantBuckets: ClaudeUsageBucketKind[];
208
- /** The SUBSCRIPTION profile a new process of `model` should run on; `null` when none is eligible. */
212
+ /** The profile a process of `model` should run on (see {@link getClaudeLaunchPick}); `null` when none is usable. */
209
213
  recommended: string | null;
214
+ /** Why `recommended` is what it is. */
215
+ pickReason: ClaudeLaunchPickReason;
216
+ /** With nothing usable: the account and instant that frees up first, so a resume can be scheduled for it. */
217
+ nextAvailable: ClaudeNextAvailable | null;
210
218
  profiles: ClaudeProfileReportEntry[];
211
219
  }
220
+ /** A new agent never starts on an account whose five-hour window is already this full: it would hit the limit within minutes. */
221
+ export declare const claudeLaunchSessionCeilingPercent = 90;
222
+ /** Two weekly resets closer than this count as the same moment (the endpoint's instants carry sub-second jitter); the five-hour percent then decides. */
223
+ export declare const claudeLaunchResetTieMs = 60000;
224
+ export declare const claudeWeeklyWindowMs: number;
225
+ export declare const claudeSessionWindowMs: number;
212
226
  /**
213
- * @description Rank the profiles for a launch of `model`: a profile that is signed out, marked limited
214
- * (`limitedUntil` in the future), out of API credits or at 100 % on a relevant window is out; the rest are ordered by
215
- * headroom on the relevant windows (most first; unknown usage ranks after any known one; a tie goes to the lower
216
- * total of the relevant percentages). The first SUBSCRIPTION in that order is `recommended`: an account billed to API
217
- * credits has no windows — it would rank as unknown headroom forever — and a child launched on it spends money, so
218
- * it is listed (eligible or not) but never recommended. The entries keep the input order.
227
+ * `warm`: the session stays on its account; `movedFromLimited`: it was stopped by a limit and goes elsewhere;
228
+ * `movedFromUnavailable`: its account can no longer run (signed out, marked limited, out of credits, a window full) and it
229
+ * goes elsewhere; `soonestWeeklyReset`: a new agent; `none`: nothing is usable.
219
230
  */
220
- export declare function buildClaudeProfilesReport(profiles: readonly ClaudeProfileUsageView[], model: string | null, nowMs: number): ClaudeProfilesReport;
231
+ export type ClaudeLaunchPickReason = 'warm' | 'movedFromLimited' | 'movedFromUnavailable' | 'soonestWeeklyReset' | 'none';
232
+ /** The account that frees up first and the ISO instant it does. */
233
+ export interface ClaudeNextAvailable {
234
+ profile: string;
235
+ at: string;
236
+ }
237
+ export interface ClaudeLaunchPick {
238
+ pick: string | null;
239
+ reason: ClaudeLaunchPickReason;
240
+ nextAvailable: ClaudeNextAvailable | null;
241
+ }
242
+ /** What the pick needs besides the profiles, the model and the clock. */
243
+ export interface ClaudeLaunchPickOptions {
244
+ /** The account a WARM session last ran on; absent for a new agent (an unknown name counts as absent). */
245
+ currentProfile?: string | null;
246
+ /** The session broke off on a usage limit of `currentProfile`: it is left out of this answer whatever the figures say. */
247
+ isStoppedByLimit?: boolean;
248
+ /** Accounts the operator switched off in the `/limits` list (every rung disabled): never picked for a new agent. */
249
+ excludedNames?: ReadonlySet<string>;
250
+ }
251
+ /**
252
+ * @description Whether a NEW agent of `model` may start on the profile now: a subscription account that is eligible by the
253
+ * figures as of `nowMs` and whose five-hour window is below {@link claudeLaunchSessionCeilingPercent}. Switching it off
254
+ * in the `/limits` list is the caller's filter.
255
+ */
256
+ export declare function checkIsClaudeProfileLaunchable(profile: ClaudeProfileUsageView, model: string | null, nowMs: number): boolean;
257
+ /**
258
+ * @description The profiles in the order a launch of `model` prefers them: the soonest weekly reset first (the figures as of
259
+ * `nowMs`: a passed reset rolled forward), an unknown reset after every known one, no snapshot last. Resets within
260
+ * {@link claudeLaunchResetTieMs} of the group's first count as one moment, ordered by the lower five-hour percent, then by
261
+ * input order. Pure ordering: the caller filters who may be picked at all. Shared by the report's pick and the bot's
262
+ * own topic switch (`claudeLimitSwitch.ts`) — ONE ranking.
263
+ */
264
+ export declare function sortClaudeProfilesByLaunchRank<T extends ClaudeProfileUsageView>(profiles: readonly T[], model: string | null, nowMs: number): T[];
265
+ /**
266
+ * @description The account a process of `model` should run on.
267
+ *
268
+ * NEW agent (no `currentProfile`): of the USABLE accounts — subscription, signed in, not marked limited, not out of API
269
+ * credits, not switched off (`excludedNames`), every weekly window the model drains below 100 % and the five-hour window
270
+ * below {@link claudeLaunchSessionCeilingPercent} — the one whose weekly window resets soonest
271
+ * ({@link sortClaudeProfilesByLaunchRank}): spend first what burns first, and move to a farther reset only when the
272
+ * five-hour window is exhausted. Fable's own window at 100 % takes only Fable out.
273
+ *
274
+ * WARM session (`currentProfile` known): it stays on that account unless the account is signed out, marked limited, out
275
+ * of API credits or at 100 % on a window the model drains — the ceiling does not apply, and an API-billed account the
276
+ * session already works on is kept (the spend was approved). `isStoppedByLimit` takes `currentProfile` out of the answer
277
+ * whatever the figures say (they may lag the limit); the rest follows the new-agent rule, and the reason says the
278
+ * session moved (`movedFromLimited`, or `movedFromUnavailable` when the account could no longer run by its own figures).
279
+ *
280
+ * Nothing usable → `pick: null` and {@link ClaudeLaunchPick.nextAvailable}.
281
+ */
282
+ export declare function getClaudeLaunchPick(input: ClaudeLaunchPickOptions & {
283
+ profiles: readonly ClaudeProfileUsageView[];
284
+ model: string | null;
285
+ nowMs: number;
286
+ }): ClaudeLaunchPick;
287
+ /**
288
+ * @description The pick in words, for the first line of the `claude_profiles` answer and the CLI: why the account was chosen
289
+ * (`stays on the warm account`, `moved: <name> stopped on a limit` / `can no longer run`, `soonest weekly reset`), or that nothing is usable
290
+ * and which account frees up when. `currentProfile` is the account the caller passed for a resumed session.
291
+ */
292
+ export declare function describeClaudeLaunchOutcome(report: Pick<ClaudeProfilesReport, 'pickReason' | 'nextAvailable'>, currentProfile: string | null): string;
293
+ /**
294
+ * @description The report of every profile for a launch of `model`, with the pick of {@link getClaudeLaunchPick}
295
+ * (`options`: the warm account, the limit stop, the switched-off accounts). `isEligible` is the strict reading — signed in,
296
+ * not marked limited, its API credits not used up, not at 100 % on a relevant window as recorded — which the explicit
297
+ * fallback chain's availability reads; `recommended` is the pick, an account billed to API credits only when a warm
298
+ * session already runs on it. The entries keep the input order.
299
+ */
300
+ export declare function buildClaudeProfilesReport(profiles: readonly ClaudeProfileUsageView[], model: string | null, nowMs: number, options?: ClaudeLaunchPickOptions): ClaudeProfilesReport;
221
301
  /**
222
302
  * @description The ranking's view of every profile off the registry: `default` (its hidden record, when the
223
303
  * bot has written one) first, then the added profiles in creation order. Shared by the bot (live state) and
@@ -228,8 +308,8 @@ export declare function buildClaudeProfileUsageViews(input: {
228
308
  /** Every record, the hidden `default` one included (`StateStore.getClaudeProfileInfo` / the raw file). */
229
309
  records: Readonly<Record<string, ClaudeProfileRecord>>;
230
310
  }): ClaudeProfileUsageView[];
231
- /** The profile registry as `state.json` holds it — the CLI's read, no `StateStore` (which would migrate and lock). */
232
- export declare function readClaudeProfileRecordsFromStateFile(dataDir: string): Readonly<Record<string, ClaudeProfileRecord>>;
311
+ /** The profile registry out of a `state.json` already read (`stateFile.ts`): entries without a creation time are dropped. */
312
+ export declare function getClaudeProfileRecordsFromState(stateFile: Readonly<Record<string, unknown>>): Readonly<Record<string, ClaudeProfileRecord>>;
233
313
  /**
234
314
  * @description A reset instant for a human, in the instance zone: `16:00` when it is today there, `Sat 00:00`
235
315
  * within the week, `17.10 00:00` beyond. The weekday is English on purpose (a three-letter token every locale
@@ -1 +1 @@
1
- {"version":3,"file":"claudeUsage.d.ts","sourceRoot":"","sources":["../../src/utils/claudeUsage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"claudeUsage.d.ts","sourceRoot":"","sources":["../../src/utils/claudeUsage.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  /**
3
3
  * @description Per-profile Claude USAGE — how much of each subscription window an account profile
4
- * (`utils/claudeProfiles.ts`) has used, and which profile a new process should run on.
4
+ * (`utils/claudeProfiles.ts`) has used, and which profile a process should run on: a NEW agent goes to the
5
+ * account whose weekly window resets soonest (spend first what burns soonest), a WARM session stays on the
6
+ * account it worked on ({@link getClaudeLaunchPick}).
5
7
  *
6
8
  * Two sources feed one snapshot per profile (`ClaudeProfileRecord.usage`):
7
9
  * - the OAuth usage endpoint (`GET https://api.anthropic.com/api/oauth/usage`, the profile's own access
@@ -52,7 +54,7 @@ var __importStar = (this && this.__importStar) || (function () {
52
54
  };
53
55
  })();
54
56
  Object.defineProperty(exports, "__esModule", { value: true });
55
- exports.englishRelativeResetWords = exports.claudeUsageBucketKinds = exports.claudeUsageFetchTimeoutMs = exports.claudeUsageEndpoint = void 0;
57
+ exports.englishRelativeResetWords = exports.claudeSessionWindowMs = exports.claudeWeeklyWindowMs = exports.claudeLaunchResetTieMs = exports.claudeLaunchSessionCeilingPercent = exports.claudeUsageBucketKinds = exports.claudeUsageFetchTimeoutMs = exports.claudeUsageEndpoint = void 0;
56
58
  exports.readClaudeOAuthToken = readClaudeOAuthToken;
57
59
  exports.checkIsClaudeTokenExpired = checkIsClaudeTokenExpired;
58
60
  exports.fetchUsageBuckets = fetchUsageBuckets;
@@ -68,9 +70,13 @@ exports.getRelevantClaudeUsageKinds = getRelevantClaudeUsageKinds;
68
70
  exports.checkHasHeadroomForClaudeModel = checkHasHeadroomForClaudeModel;
69
71
  exports.checkIsClaudeUsageExhausted = checkIsClaudeUsageExhausted;
70
72
  exports.checkIsClaudeModelClearOfLimit = checkIsClaudeModelClearOfLimit;
73
+ exports.checkIsClaudeProfileLaunchable = checkIsClaudeProfileLaunchable;
74
+ exports.sortClaudeProfilesByLaunchRank = sortClaudeProfilesByLaunchRank;
75
+ exports.getClaudeLaunchPick = getClaudeLaunchPick;
76
+ exports.describeClaudeLaunchOutcome = describeClaudeLaunchOutcome;
71
77
  exports.buildClaudeProfilesReport = buildClaudeProfilesReport;
72
78
  exports.buildClaudeProfileUsageViews = buildClaudeProfileUsageViews;
73
- exports.readClaudeProfileRecordsFromStateFile = readClaudeProfileRecordsFromStateFile;
79
+ exports.getClaudeProfileRecordsFromState = getClaudeProfileRecordsFromState;
74
80
  exports.formatClaudeUsageResetAt = formatClaudeUsageResetAt;
75
81
  exports.formatClaudeUsageRelativeReset = formatClaudeUsageRelativeReset;
76
82
  exports.formatClaudeUsageBucket = formatClaudeUsageBucket;
@@ -299,23 +305,235 @@ function checkIsClaudeModelClearOfLimit(usage, limitedModel, pickedModel) {
299
305
  }
300
306
  return checkHasHeadroomForClaudeModel(usage, pickedModel);
301
307
  }
308
+ // ── the launch pick ──
309
+ /** A new agent never starts on an account whose five-hour window is already this full: it would hit the limit within minutes. */
310
+ exports.claudeLaunchSessionCeilingPercent = 90;
311
+ /** Two weekly resets closer than this count as the same moment (the endpoint's instants carry sub-second jitter); the five-hour percent then decides. */
312
+ exports.claudeLaunchResetTieMs = 60_000;
313
+ exports.claudeWeeklyWindowMs = 7 * 24 * 3_600_000;
314
+ exports.claudeSessionWindowMs = 5 * 3_600_000;
302
315
  /**
303
- * @description Rank the profiles for a launch of `model`: a profile that is signed out, marked limited
304
- * (`limitedUntil` in the future), out of API credits or at 100 % on a relevant window is out; the rest are ordered by
305
- * headroom on the relevant windows (most first; unknown usage ranks after any known one; a tie goes to the lower
306
- * total of the relevant percentages). The first SUBSCRIPTION in that order is `recommended`: an account billed to API
307
- * credits has no windows — it would rank as unknown headroom forever — and a child launched on it spends money, so
308
- * it is listed (eligible or not) but never recommended. The entries keep the input order.
316
+ * The account itself can run: signed in, not marked limited, its API credits not used up, and none of the windows
317
+ * the model drains (`relevantBuckets`, read by the caller) at 100 %. The one hard-eligibility rule of the report's
318
+ * `isEligible` (figures as recorded) and of the launch pick (figures as of now).
309
319
  */
310
- function buildClaudeProfilesReport(profiles, model, nowMs) {
320
+ function checkIsClaudeProfileEligible(profile, relevantBuckets, nowMs) {
321
+ const isLimited = profile.limitedUntil !== null && Date.parse(profile.limitedUntil) > nowMs;
322
+ return profile.loggedIn !== false && !isLimited && profile.creditExhaustedAt === null && relevantBuckets.every((bucket) => bucket.percent < 100);
323
+ }
324
+ /** The reset instant in epoch ms; `NaN` when the bucket names none. */
325
+ function getBucketResetMs(bucket) {
326
+ return bucket.resetsAt === null ? Number.NaN : Date.parse(bucket.resetsAt);
327
+ }
328
+ function getRelevantClaudeUsageBuckets(usage, model) {
329
+ return getRelevantClaudeUsageKinds(model)
330
+ .map((kind) => getClaudeUsageBucket(usage, kind))
331
+ .filter((bucket) => bucket !== null);
332
+ }
333
+ /**
334
+ * A bucket as it stands at `nowMs`: a window whose reset instant has passed since the figure was read is empty again
335
+ * (0 %) and resets one window length per elapsed period later. A bucket without a usable reset stays as read.
336
+ */
337
+ function readClaudeBucketAsOf(bucket, nowMs) {
338
+ const resetMs = getBucketResetMs(bucket);
339
+ if (!Number.isFinite(resetMs) || resetMs > nowMs)
340
+ return bucket;
341
+ const windowMs = bucket.kind === 'session' ? exports.claudeSessionWindowMs : exports.claudeWeeklyWindowMs;
342
+ const rolledMs = resetMs + (Math.floor((nowMs - resetMs) / windowMs) + 1) * windowMs;
343
+ return { ...bucket, percent: 0, resetsAt: new Date(rolledMs).toISOString() };
344
+ }
345
+ function getRelevantClaudeBucketsAsOf(profile, model, nowMs) {
346
+ return getRelevantClaudeUsageBuckets(profile.usage, model).map((bucket) => readClaudeBucketAsOf(bucket, nowMs));
347
+ }
348
+ /**
349
+ * @description Whether a NEW agent of `model` may start on the profile now: a subscription account that is eligible by the
350
+ * figures as of `nowMs` and whose five-hour window is below {@link claudeLaunchSessionCeilingPercent}. Switching it off
351
+ * in the `/limits` list is the caller's filter.
352
+ */
353
+ function checkIsClaudeProfileLaunchable(profile, model, nowMs) {
354
+ if (profile.billing === 'api')
355
+ return false;
356
+ const buckets = getRelevantClaudeBucketsAsOf(profile, model, nowMs);
357
+ if (!checkIsClaudeProfileEligible(profile, buckets, nowMs))
358
+ return false;
359
+ const session = buckets.find((bucket) => bucket.kind === 'session');
360
+ return session === undefined || session.percent < exports.claudeLaunchSessionCeilingPercent;
361
+ }
362
+ /** 0: a known weekly reset; 1: a snapshot without one; 2: no snapshot at all. */
363
+ function getRankTier(key) {
364
+ if (key.weeklyResetMs !== null)
365
+ return 0;
366
+ return key.hasUsage ? 1 : 2;
367
+ }
368
+ function compareRankKeysBySession(a, b) {
369
+ const aSession = a.sessionPercent ?? Number.POSITIVE_INFINITY;
370
+ const bSession = b.sessionPercent ?? Number.POSITIVE_INFINITY;
371
+ if (aSession !== bSession)
372
+ return aSession < bSession ? -1 : 1;
373
+ return a.index - b.index;
374
+ }
375
+ /**
376
+ * @description The profiles in the order a launch of `model` prefers them: the soonest weekly reset first (the figures as of
377
+ * `nowMs`: a passed reset rolled forward), an unknown reset after every known one, no snapshot last. Resets within
378
+ * {@link claudeLaunchResetTieMs} of the group's first count as one moment, ordered by the lower five-hour percent, then by
379
+ * input order. Pure ordering: the caller filters who may be picked at all. Shared by the report's pick and the bot's
380
+ * own topic switch (`claudeLimitSwitch.ts`) — ONE ranking.
381
+ */
382
+ function sortClaudeProfilesByLaunchRank(profiles, model, nowMs) {
383
+ const keys = profiles.map((profile, index) => {
384
+ const buckets = getRelevantClaudeBucketsAsOf(profile, model, nowMs);
385
+ const resets = buckets
386
+ .filter((bucket) => bucket.kind !== 'session')
387
+ .map(getBucketResetMs)
388
+ .filter((resetMs) => Number.isFinite(resetMs));
389
+ return {
390
+ profile,
391
+ index,
392
+ weeklyResetMs: resets.length === 0 ? null : Math.min(...resets),
393
+ sessionPercent: buckets.find((bucket) => bucket.kind === 'session')?.percent ?? null,
394
+ hasUsage: (profile.usage?.buckets.length ?? 0) > 0,
395
+ };
396
+ });
397
+ keys.sort((a, b) => getRankTier(a) - getRankTier(b) || (a.weeklyResetMs ?? 0) - (b.weeklyResetMs ?? 0) || a.index - b.index);
398
+ // A tie group is anchored at its first member, so the rule is a partition, not a comparator that could contradict itself.
399
+ const ordered = [];
400
+ let group = [];
401
+ const flushGroup = () => {
402
+ ordered.push(...group.sort(compareRankKeysBySession).map((key) => key.profile));
403
+ group = [];
404
+ };
405
+ for (const key of keys) {
406
+ const anchor = group[0];
407
+ const isTied = anchor !== undefined
408
+ && getRankTier(anchor) === getRankTier(key)
409
+ && (key.weeklyResetMs === null || anchor.weeklyResetMs === null || key.weeklyResetMs - anchor.weeklyResetMs <= exports.claudeLaunchResetTieMs);
410
+ if (anchor !== undefined && !isTied)
411
+ flushGroup();
412
+ group.push(key);
413
+ }
414
+ flushGroup();
415
+ return ordered;
416
+ }
417
+ /**
418
+ * The instant the profile becomes usable for a new agent once every blocker clears: its limited mark, a weekly window the
419
+ * model drains at 100 %, a five-hour window at the launch ceiling (each at its reset, figures as of now). `nowMs` when
420
+ * nothing blocks it; `null` when a blocker names no reset (nobody can tell when it frees up).
421
+ */
422
+ function getClaudeProfileFreeAtMs(profile, model, nowMs) {
423
+ let freeAtMs = nowMs;
424
+ const limitedUntilMs = profile.limitedUntil === null ? Number.NaN : Date.parse(profile.limitedUntil);
425
+ if (Number.isFinite(limitedUntilMs) && limitedUntilMs > nowMs)
426
+ freeAtMs = limitedUntilMs;
427
+ for (const bucket of getRelevantClaudeBucketsAsOf(profile, model, nowMs)) {
428
+ const ceilingPercent = bucket.kind === 'session' ? exports.claudeLaunchSessionCeilingPercent : 100;
429
+ if (bucket.percent < ceilingPercent)
430
+ continue;
431
+ const resetMs = getBucketResetMs(bucket);
432
+ if (!Number.isFinite(resetMs))
433
+ return null;
434
+ freeAtMs = Math.max(freeAtMs, resetMs);
435
+ }
436
+ return freeAtMs;
437
+ }
438
+ /** When the profile's five-hour window resets (as of `nowMs`); `null` when the snapshot has none or names no reset. */
439
+ function getSessionResetMs(profile, nowMs) {
440
+ const session = getClaudeUsageBucket(profile.usage, 'session');
441
+ const resetMs = session === null ? Number.NaN : getBucketResetMs(readClaudeBucketAsOf(session, nowMs));
442
+ return Number.isFinite(resetMs) ? resetMs : null;
443
+ }
444
+ /**
445
+ * The subscription account that frees up first, when nothing is usable now; `null` when no account names a time. The
446
+ * account a limit just stopped (`stoppedName`) may show no blocker at all — its figures lag the limit — and is then
447
+ * taken to free up when its five-hour window resets, so a single account is never left without a time to come back.
448
+ */
449
+ function getClaudeNextAvailable(profiles, model, nowMs, excludedNames, stoppedName) {
450
+ let next = null;
451
+ for (const profile of profiles) {
452
+ // These never come back at a known time: switched off, signed out, API-billed, out of credits.
453
+ if (excludedNames.has(profile.name) || profile.loggedIn === false || profile.billing === 'api' || profile.creditExhaustedAt !== null)
454
+ continue;
455
+ let freeAtMs = getClaudeProfileFreeAtMs(profile, model, nowMs);
456
+ // The limit stopped this account, yet its figures show no blocker, so nothing says WHICH limit it was (a weekly window
457
+ // the usage endpoint has not caught up with, or the five-hour one). The five-hour reset is a guess — the earliest it
458
+ // could be free. A wrong guess just hits the limit again on the resume and asks again: at most about one try per five hours.
459
+ if (profile.name === stoppedName && freeAtMs !== null && freeAtMs <= nowMs)
460
+ freeAtMs = getSessionResetMs(profile, nowMs);
461
+ if (freeAtMs === null || freeAtMs <= nowMs)
462
+ continue;
463
+ if (next === null || freeAtMs < next.atMs)
464
+ next = { profile: profile.name, atMs: freeAtMs };
465
+ }
466
+ return next === null ? null : { profile: next.profile, at: new Date(next.atMs).toISOString() };
467
+ }
468
+ /**
469
+ * @description The account a process of `model` should run on.
470
+ *
471
+ * NEW agent (no `currentProfile`): of the USABLE accounts — subscription, signed in, not marked limited, not out of API
472
+ * credits, not switched off (`excludedNames`), every weekly window the model drains below 100 % and the five-hour window
473
+ * below {@link claudeLaunchSessionCeilingPercent} — the one whose weekly window resets soonest
474
+ * ({@link sortClaudeProfilesByLaunchRank}): spend first what burns first, and move to a farther reset only when the
475
+ * five-hour window is exhausted. Fable's own window at 100 % takes only Fable out.
476
+ *
477
+ * WARM session (`currentProfile` known): it stays on that account unless the account is signed out, marked limited, out
478
+ * of API credits or at 100 % on a window the model drains — the ceiling does not apply, and an API-billed account the
479
+ * session already works on is kept (the spend was approved). `isStoppedByLimit` takes `currentProfile` out of the answer
480
+ * whatever the figures say (they may lag the limit); the rest follows the new-agent rule, and the reason says the
481
+ * session moved (`movedFromLimited`, or `movedFromUnavailable` when the account could no longer run by its own figures).
482
+ *
483
+ * Nothing usable → `pick: null` and {@link ClaudeLaunchPick.nextAvailable}.
484
+ */
485
+ function getClaudeLaunchPick(input) {
486
+ const excludedNames = input.excludedNames ?? new Set();
487
+ const current = input.currentProfile ? input.profiles.find((profile) => profile.name === input.currentProfile) : undefined;
488
+ const isStopped = current !== undefined && input.isStoppedByLimit === true;
489
+ if (current && !isStopped
490
+ && checkIsClaudeProfileEligible(current, getRelevantClaudeBucketsAsOf(current, input.model, input.nowMs), input.nowMs)) {
491
+ return { pick: current.name, reason: 'warm', nextAvailable: null };
492
+ }
493
+ const movedFrom = current?.name ?? null;
494
+ const usable = input.profiles.filter((profile) => profile.name !== movedFrom
495
+ && !excludedNames.has(profile.name)
496
+ && checkIsClaudeProfileLaunchable(profile, input.model, input.nowMs));
497
+ const [first] = sortClaudeProfilesByLaunchRank(usable, input.model, input.nowMs);
498
+ if (first) {
499
+ const reason = movedFrom === null ? 'soonestWeeklyReset' : isStopped ? 'movedFromLimited' : 'movedFromUnavailable';
500
+ return { pick: first.name, reason, nextAvailable: null };
501
+ }
502
+ return { pick: null, reason: 'none', nextAvailable: getClaudeNextAvailable(input.profiles, input.model, input.nowMs, excludedNames, isStopped ? movedFrom : null) };
503
+ }
504
+ /**
505
+ * @description The pick in words, for the first line of the `claude_profiles` answer and the CLI: why the account was chosen
506
+ * (`stays on the warm account`, `moved: <name> stopped on a limit` / `can no longer run`, `soonest weekly reset`), or that nothing is usable
507
+ * and which account frees up when. `currentProfile` is the account the caller passed for a resumed session.
508
+ */
509
+ function describeClaudeLaunchOutcome(report, currentProfile) {
510
+ switch (report.pickReason) {
511
+ case 'warm':
512
+ return 'stays on the warm account';
513
+ case 'movedFromLimited':
514
+ return `moved: ${currentProfile ?? 'the warm account'} stopped on a limit`;
515
+ case 'movedFromUnavailable':
516
+ return `moved: ${currentProfile ?? 'the warm account'} can no longer run`;
517
+ case 'soonestWeeklyReset':
518
+ return 'soonest weekly reset';
519
+ case 'none':
520
+ return report.nextAvailable === null
521
+ ? 'none usable — no account names a time it frees up'
522
+ : `none usable — next: ${report.nextAvailable.profile} at ${report.nextAvailable.at}`;
523
+ }
524
+ }
525
+ /**
526
+ * @description The report of every profile for a launch of `model`, with the pick of {@link getClaudeLaunchPick}
527
+ * (`options`: the warm account, the limit stop, the switched-off accounts). `isEligible` is the strict reading — signed in,
528
+ * not marked limited, its API credits not used up, not at 100 % on a relevant window as recorded — which the explicit
529
+ * fallback chain's availability reads; `recommended` is the pick, an account billed to API credits only when a warm
530
+ * session already runs on it. The entries keep the input order.
531
+ */
532
+ function buildClaudeProfilesReport(profiles, model, nowMs, options = {}) {
311
533
  const relevantBuckets = getRelevantClaudeUsageKinds(model);
312
534
  const entries = profiles.map((profile) => {
313
- const relevant = relevantBuckets
314
- .map((kind) => getClaudeUsageBucket(profile.usage, kind))
315
- .filter((bucket) => bucket !== null);
535
+ const relevant = getRelevantClaudeUsageBuckets(profile.usage, model);
316
536
  const maxPercent = relevant.length === 0 ? null : Math.max(...relevant.map((bucket) => bucket.percent));
317
- const isLimited = profile.limitedUntil !== null && Date.parse(profile.limitedUntil) > nowMs;
318
- const isEligible = profile.loggedIn !== false && !isLimited && profile.creditExhaustedAt === null && (maxPercent === null || maxPercent < 100);
319
537
  return {
320
538
  name: profile.name,
321
539
  configDir: profile.configDir,
@@ -329,28 +547,16 @@ function buildClaudeProfilesReport(profiles, model, nowMs) {
329
547
  isUsageStale: profile.usage?.isStale === true,
330
548
  limitedUntil: profile.limitedUntil,
331
549
  creditExhaustedAt: profile.creditExhaustedAt,
332
- isEligible,
550
+ isEligible: checkIsClaudeProfileEligible(profile, relevant, nowMs),
333
551
  headroomPercent: maxPercent === null ? null : 100 - maxPercent,
334
552
  isRecommended: false,
335
553
  };
336
554
  });
337
- const ranked = entries
338
- .filter((entry) => entry.isEligible && entry.billing !== 'api')
339
- .sort((a, b) => {
340
- if (a.headroomPercent === null || b.headroomPercent === null) {
341
- return (a.headroomPercent === null ? 1 : 0) - (b.headroomPercent === null ? 1 : 0);
342
- }
343
- if (a.headroomPercent !== b.headroomPercent)
344
- return b.headroomPercent - a.headroomPercent;
345
- return sumRelevantPercent(a, relevantBuckets) - sumRelevantPercent(b, relevantBuckets);
346
- });
347
- const recommended = ranked[0] ?? null;
555
+ const launch = getClaudeLaunchPick({ ...options, profiles, model, nowMs });
556
+ const recommended = entries.find((entry) => entry.name === launch.pick);
348
557
  if (recommended)
349
558
  recommended.isRecommended = true;
350
- return { model, relevantBuckets, recommended: recommended?.name ?? null, profiles: entries };
351
- }
352
- function sumRelevantPercent(entry, kinds) {
353
- return entry.buckets.filter((bucket) => kinds.includes(bucket.kind)).reduce((sum, bucket) => sum + bucket.percent, 0);
559
+ return { model, relevantBuckets, recommended: launch.pick, pickReason: launch.reason, nextAvailable: launch.nextAvailable, profiles: entries };
354
560
  }
355
561
  /**
356
562
  * @description The ranking's view of every profile off the registry: `default` (its hidden record, when the
@@ -377,16 +583,10 @@ function buildClaudeProfileUsageViews(input) {
377
583
  .sort(([, a], [, b]) => a.createdAt.localeCompare(b.createdAt));
378
584
  return [...(isDefaultRemoved ? [] : [toView('default', input.records.default)]), ...added.map(([name, record]) => toView(name, record))];
379
585
  }
380
- /** The profile registry as `state.json` holds it — the CLI's read, no `StateStore` (which would migrate and lock). */
381
- function readClaudeProfileRecordsFromStateFile(dataDir) {
382
- let parsed;
383
- try {
384
- parsed = JSON.parse(fs.readFileSync(path.join(dataDir, 'state.json'), 'utf8'));
385
- }
386
- catch {
387
- return {};
388
- }
389
- const records = checkIsRecord(parsed) && checkIsRecord(parsed.claudeProfiles) ? parsed.claudeProfiles : {};
586
+ /** The profile registry out of a `state.json` already read (`stateFile.ts`): entries without a creation time are dropped. */
587
+ function getClaudeProfileRecordsFromState(stateFile) {
588
+ const registry = stateFile.claudeProfiles;
589
+ const records = checkIsRecord(registry) ? registry : {};
390
590
  const result = {};
391
591
  for (const [name, record] of Object.entries(records)) {
392
592
  if (checkIsRecord(record) && typeof record.createdAt === 'string')