@clinebot/core 0.0.34 → 0.0.36

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 (546) hide show
  1. package/README.md +13 -10
  2. package/dist/ClineCore.d.ts +96 -63
  3. package/dist/ClineCore.d.ts.map +1 -1
  4. package/dist/account/index.d.ts +1 -1
  5. package/dist/account/index.d.ts.map +1 -1
  6. package/dist/account/rpc.d.ts +6 -6
  7. package/dist/account/rpc.d.ts.map +1 -1
  8. package/dist/cron/index.d.ts +6 -0
  9. package/dist/cron/index.d.ts.map +1 -0
  10. package/dist/cron/resource-limiter.d.ts +9 -0
  11. package/dist/cron/resource-limiter.d.ts.map +1 -0
  12. package/dist/cron/schedule-command-service.d.ts +10 -0
  13. package/dist/cron/schedule-command-service.d.ts.map +1 -0
  14. package/dist/cron/schedule-service.d.ts +100 -0
  15. package/dist/cron/schedule-service.d.ts.map +1 -0
  16. package/dist/cron/scheduler.d.ts +66 -0
  17. package/dist/cron/scheduler.d.ts.map +1 -0
  18. package/dist/cron/sqlite-schedule-store.d.ts +52 -0
  19. package/dist/cron/sqlite-schedule-store.d.ts.map +1 -0
  20. package/dist/extensions/config/agent-config-loader.d.ts +6 -5
  21. package/dist/extensions/config/agent-config-loader.d.ts.map +1 -1
  22. package/dist/extensions/config/agent-config-parser.d.ts +1 -1
  23. package/dist/extensions/config/agent-config-parser.d.ts.map +1 -1
  24. package/dist/extensions/config/hooks-config-loader.d.ts +2 -2
  25. package/dist/extensions/config/hooks-config-loader.d.ts.map +1 -1
  26. package/dist/extensions/config/index.d.ts +3 -3
  27. package/dist/extensions/config/index.d.ts.map +1 -1
  28. package/dist/extensions/config/runtime-commands.d.ts +1 -0
  29. package/dist/extensions/config/runtime-commands.d.ts.map +1 -1
  30. package/dist/extensions/config/user-instruction-config-loader.d.ts +3 -2
  31. package/dist/extensions/config/user-instruction-config-loader.d.ts.map +1 -1
  32. package/dist/extensions/context/agentic-compaction.d.ts +2 -2
  33. package/dist/extensions/context/agentic-compaction.d.ts.map +1 -1
  34. package/dist/extensions/context/compaction-shared.d.ts +5 -4
  35. package/dist/extensions/context/compaction-shared.d.ts.map +1 -1
  36. package/dist/extensions/context/compaction.d.ts.map +1 -1
  37. package/dist/extensions/plugin/plugin-config-loader.d.ts +9 -2
  38. package/dist/extensions/plugin/plugin-config-loader.d.ts.map +1 -1
  39. package/dist/extensions/plugin/plugin-loader.d.ts +5 -3
  40. package/dist/extensions/plugin/plugin-loader.d.ts.map +1 -1
  41. package/dist/extensions/plugin/plugin-module-import.d.ts.map +1 -1
  42. package/dist/extensions/plugin/plugin-sandbox.d.ts +15 -2
  43. package/dist/extensions/plugin/plugin-sandbox.d.ts.map +1 -1
  44. package/dist/extensions/plugin/plugin-targeting.d.ts +7 -0
  45. package/dist/extensions/plugin/plugin-targeting.d.ts.map +1 -0
  46. package/dist/extensions/plugin-sandbox-bootstrap.js +253 -253
  47. package/dist/extensions/tools/constants.d.ts.map +1 -0
  48. package/dist/{tools → extensions/tools}/definitions.d.ts +1 -1
  49. package/dist/extensions/tools/definitions.d.ts.map +1 -0
  50. package/dist/extensions/tools/executors/apply-patch-parser.d.ts.map +1 -0
  51. package/dist/{tools → extensions/tools}/executors/apply-patch.d.ts +3 -1
  52. package/dist/extensions/tools/executors/apply-patch.d.ts.map +1 -0
  53. package/dist/extensions/tools/executors/bash.d.ts.map +1 -0
  54. package/dist/extensions/tools/executors/editor.d.ts.map +1 -0
  55. package/dist/extensions/tools/executors/file-read.d.ts.map +1 -0
  56. package/dist/extensions/tools/executors/index.d.ts.map +1 -0
  57. package/dist/{tools → extensions/tools}/executors/search.d.ts +1 -1
  58. package/dist/extensions/tools/executors/search.d.ts.map +1 -0
  59. package/dist/extensions/tools/executors/web-fetch.d.ts.map +1 -0
  60. package/dist/extensions/tools/helpers.d.ts.map +1 -0
  61. package/dist/{tools → extensions/tools}/index.d.ts +2 -0
  62. package/dist/extensions/tools/index.d.ts.map +1 -0
  63. package/dist/{tools → extensions/tools}/model-tool-routing.d.ts +1 -1
  64. package/dist/extensions/tools/model-tool-routing.d.ts.map +1 -0
  65. package/dist/{tools → extensions/tools}/presets.d.ts +26 -44
  66. package/dist/extensions/tools/presets.d.ts.map +1 -0
  67. package/dist/extensions/tools/runtime.d.ts +25 -0
  68. package/dist/extensions/tools/runtime.d.ts.map +1 -0
  69. package/dist/extensions/tools/schemas.d.ts.map +1 -0
  70. package/dist/extensions/tools/team/delegated-agent.d.ts.map +1 -0
  71. package/dist/extensions/tools/team/index.d.ts.map +1 -0
  72. package/dist/{team → extensions/tools/team}/multi-agent.d.ts +1 -3
  73. package/dist/extensions/tools/team/multi-agent.d.ts.map +1 -0
  74. package/dist/extensions/tools/team/projections.d.ts.map +1 -0
  75. package/dist/extensions/tools/team/runtime.d.ts.map +1 -0
  76. package/dist/{team → extensions/tools/team}/spawn-agent-tool.d.ts +0 -1
  77. package/dist/extensions/tools/team/spawn-agent-tool.d.ts.map +1 -0
  78. package/dist/extensions/tools/team/subagent-prompts.d.ts.map +1 -0
  79. package/dist/{team → extensions/tools/team}/team-tools.d.ts +1 -0
  80. package/dist/extensions/tools/team/team-tools.d.ts.map +1 -0
  81. package/dist/{tools → extensions/tools}/types.d.ts +4 -3
  82. package/dist/extensions/tools/types.d.ts.map +1 -0
  83. package/dist/{runtime → hooks}/checkpoint-hooks.d.ts +7 -0
  84. package/dist/hooks/checkpoint-hooks.d.ts.map +1 -0
  85. package/dist/{runtime → hooks}/hook-file-hooks.d.ts +4 -3
  86. package/dist/hooks/hook-file-hooks.d.ts.map +1 -0
  87. package/dist/hooks/index.d.ts +0 -1
  88. package/dist/hooks/index.d.ts.map +1 -1
  89. package/dist/hooks/subprocess.d.ts +10 -130
  90. package/dist/hooks/subprocess.d.ts.map +1 -1
  91. package/dist/hub/browser-websocket.d.ts +18 -0
  92. package/dist/hub/browser-websocket.d.ts.map +1 -0
  93. package/dist/hub/client.d.ts +45 -0
  94. package/dist/hub/client.d.ts.map +1 -0
  95. package/dist/hub/connect.d.ts +15 -0
  96. package/dist/hub/connect.d.ts.map +1 -0
  97. package/dist/hub/daemon-entry.d.ts +2 -0
  98. package/dist/hub/daemon-entry.d.ts.map +1 -0
  99. package/dist/hub/daemon-entry.js +1045 -0
  100. package/dist/hub/daemon.d.ts +5 -0
  101. package/dist/hub/daemon.d.ts.map +1 -0
  102. package/dist/hub/defaults.d.ts +13 -0
  103. package/dist/hub/defaults.d.ts.map +1 -0
  104. package/dist/hub/discovery.d.ts +29 -0
  105. package/dist/hub/discovery.d.ts.map +1 -0
  106. package/dist/hub/index.d.ts +15 -0
  107. package/dist/hub/index.d.ts.map +1 -0
  108. package/dist/hub/index.js +1044 -0
  109. package/dist/hub/native-transport.d.ts +17 -0
  110. package/dist/hub/native-transport.d.ts.map +1 -0
  111. package/dist/hub/runtime-handlers.d.ts +11 -0
  112. package/dist/hub/runtime-handlers.d.ts.map +1 -0
  113. package/dist/hub/server.d.ts +86 -0
  114. package/dist/hub/server.d.ts.map +1 -0
  115. package/dist/hub/session-client.d.ts +87 -0
  116. package/dist/hub/session-client.d.ts.map +1 -0
  117. package/dist/hub/start-shared-server.d.ts +19 -0
  118. package/dist/hub/start-shared-server.d.ts.map +1 -0
  119. package/dist/hub/transport.d.ts +8 -0
  120. package/dist/hub/transport.d.ts.map +1 -0
  121. package/dist/hub/ui-client.d.ts +44 -0
  122. package/dist/hub/ui-client.d.ts.map +1 -0
  123. package/dist/hub/workspace.d.ts +4 -0
  124. package/dist/hub/workspace.d.ts.map +1 -0
  125. package/dist/index.d.ts +52 -39
  126. package/dist/index.d.ts.map +1 -1
  127. package/dist/index.js +557 -533
  128. package/dist/llms/configured-provider-registry.d.ts +28 -0
  129. package/dist/llms/configured-provider-registry.d.ts.map +1 -0
  130. package/dist/llms/provider-defaults.d.ts +27 -0
  131. package/dist/llms/provider-defaults.d.ts.map +1 -0
  132. package/dist/llms/provider-settings.d.ts +202 -0
  133. package/dist/llms/provider-settings.d.ts.map +1 -0
  134. package/dist/llms/runtime-config.d.ts +4 -0
  135. package/dist/llms/runtime-config.d.ts.map +1 -0
  136. package/dist/llms/runtime-registry.d.ts +20 -0
  137. package/dist/llms/runtime-registry.d.ts.map +1 -0
  138. package/dist/llms/runtime-types.d.ts +85 -0
  139. package/dist/llms/runtime-types.d.ts.map +1 -0
  140. package/dist/runtime/history.d.ts +4 -0
  141. package/dist/runtime/history.d.ts.map +1 -0
  142. package/dist/runtime/host.d.ts +8 -0
  143. package/dist/runtime/host.d.ts.map +1 -0
  144. package/dist/runtime/rules.d.ts +1 -0
  145. package/dist/runtime/rules.d.ts.map +1 -1
  146. package/dist/runtime/runtime-builder.d.ts.map +1 -1
  147. package/dist/runtime/runtime-host.d.ts +103 -0
  148. package/dist/runtime/runtime-host.d.ts.map +1 -0
  149. package/dist/{session → runtime}/runtime-oauth-token-manager.d.ts +1 -1
  150. package/dist/{session → runtime}/runtime-oauth-token-manager.d.ts.map +1 -1
  151. package/dist/runtime/session-runtime.d.ts +3 -21
  152. package/dist/runtime/session-runtime.d.ts.map +1 -1
  153. package/dist/{session/session-agent-events.d.ts → services/agent-events.d.ts} +4 -4
  154. package/dist/services/agent-events.d.ts.map +1 -0
  155. package/dist/services/config.d.ts +3 -0
  156. package/dist/services/config.d.ts.map +1 -0
  157. package/dist/services/global-settings.d.ts +12 -0
  158. package/dist/services/global-settings.d.ts.map +1 -0
  159. package/dist/services/local-runtime-bootstrap.d.ts +47 -0
  160. package/dist/services/local-runtime-bootstrap.d.ts.map +1 -0
  161. package/dist/services/plugin-tools.d.ts +16 -0
  162. package/dist/services/plugin-tools.d.ts.map +1 -0
  163. package/dist/{providers → services/providers}/local-provider-registry.d.ts +4 -4
  164. package/dist/services/providers/local-provider-registry.d.ts.map +1 -0
  165. package/dist/{providers → services/providers}/local-provider-service.d.ts +13 -13
  166. package/dist/services/providers/local-provider-service.d.ts.map +1 -0
  167. package/dist/{session → services}/session-artifacts.d.ts +0 -4
  168. package/dist/services/session-artifacts.d.ts.map +1 -0
  169. package/dist/{session/utils/helpers.d.ts → services/session-data.d.ts} +19 -27
  170. package/dist/services/session-data.d.ts.map +1 -0
  171. package/dist/{session → services}/session-telemetry.d.ts +2 -2
  172. package/dist/services/session-telemetry.d.ts.map +1 -0
  173. package/dist/{storage → services/storage}/file-team-store.d.ts +2 -2
  174. package/dist/services/storage/file-team-store.d.ts.map +1 -0
  175. package/dist/{storage → services/storage}/provider-settings-legacy-migration.d.ts +1 -1
  176. package/dist/services/storage/provider-settings-legacy-migration.d.ts.map +1 -0
  177. package/dist/{storage → services/storage}/provider-settings-manager.d.ts +1 -1
  178. package/dist/services/storage/provider-settings-manager.d.ts.map +1 -0
  179. package/dist/{storage → services/storage}/sqlite-session-store.d.ts +3 -3
  180. package/dist/services/storage/sqlite-session-store.d.ts.map +1 -0
  181. package/dist/{storage → services/storage}/sqlite-team-store.d.ts +2 -2
  182. package/dist/services/storage/sqlite-team-store.d.ts.map +1 -0
  183. package/dist/{storage → services/storage}/team-store.d.ts +1 -1
  184. package/dist/services/storage/team-store.d.ts.map +1 -0
  185. package/dist/services/telemetry/ITelemetryAdapter.d.ts.map +1 -0
  186. package/dist/services/telemetry/OpenTelemetryAdapter.d.ts.map +1 -0
  187. package/dist/services/telemetry/OpenTelemetryProvider.d.ts.map +1 -0
  188. package/dist/services/telemetry/TelemetryLoggerSink.d.ts.map +1 -0
  189. package/dist/services/telemetry/TelemetryService.d.ts.map +1 -0
  190. package/dist/services/telemetry/core-events.d.ts.map +1 -0
  191. package/dist/services/telemetry/distinct-id.d.ts.map +1 -0
  192. package/dist/services/telemetry/index.d.ts.map +1 -0
  193. package/dist/services/telemetry/index.js +28 -0
  194. package/dist/{session/utils → services}/usage.d.ts +1 -1
  195. package/dist/services/usage.d.ts.map +1 -0
  196. package/dist/services/workspace/file-indexer.d.ts.map +1 -0
  197. package/dist/services/workspace/index.d.ts.map +1 -0
  198. package/dist/services/workspace/mention-enricher.d.ts.map +1 -0
  199. package/dist/services/workspace-manifest.d.ts +16 -0
  200. package/dist/services/workspace-manifest.d.ts.map +1 -0
  201. package/dist/session/file-session-service.d.ts +4 -1
  202. package/dist/session/file-session-service.d.ts.map +1 -1
  203. package/dist/session/persistence-service.d.ts +15 -25
  204. package/dist/session/persistence-service.d.ts.map +1 -1
  205. package/dist/session/session-manifest-store.d.ts +22 -0
  206. package/dist/session/session-manifest-store.d.ts.map +1 -0
  207. package/dist/session/session-row.d.ts +93 -0
  208. package/dist/session/session-row.d.ts.map +1 -0
  209. package/dist/session/session-service.d.ts +8 -109
  210. package/dist/session/session-service.d.ts.map +1 -1
  211. package/dist/session/session-team-coordination.d.ts +4 -4
  212. package/dist/session/session-team-coordination.d.ts.map +1 -1
  213. package/dist/session/subagent-session-manager.d.ts +36 -0
  214. package/dist/session/subagent-session-manager.d.ts.map +1 -0
  215. package/dist/session/team-persistence-store.d.ts +24 -0
  216. package/dist/session/team-persistence-store.d.ts.map +1 -0
  217. package/dist/transports/hub.d.ts +47 -0
  218. package/dist/transports/hub.d.ts.map +1 -0
  219. package/dist/{session/default-session-manager.d.ts → transports/local.d.ts} +30 -16
  220. package/dist/transports/local.d.ts.map +1 -0
  221. package/dist/transports/remote.d.ts +10 -0
  222. package/dist/transports/remote.d.ts.map +1 -0
  223. package/dist/transports/runtime-host-support.d.ts +22 -0
  224. package/dist/transports/runtime-host-support.d.ts.map +1 -0
  225. package/dist/{chat → types}/chat-schema.d.ts +10 -12
  226. package/dist/types/chat-schema.d.ts.map +1 -0
  227. package/dist/types/config.d.ts +10 -9
  228. package/dist/types/config.d.ts.map +1 -1
  229. package/dist/types/provider-settings.d.ts +4 -5
  230. package/dist/types/provider-settings.d.ts.map +1 -1
  231. package/dist/{session/utils/types.d.ts → types/session.d.ts} +16 -6
  232. package/dist/types/session.d.ts.map +1 -0
  233. package/dist/types/sessions.d.ts +19 -0
  234. package/dist/types/sessions.d.ts.map +1 -1
  235. package/dist/types/storage.d.ts +1 -3
  236. package/dist/types/storage.d.ts.map +1 -1
  237. package/dist/types.d.ts +14 -6
  238. package/dist/types.d.ts.map +1 -1
  239. package/package.json +22 -13
  240. package/src/ClineCore.ts +183 -85
  241. package/src/account/index.ts +3 -3
  242. package/src/account/rpc.ts +12 -12
  243. package/src/auth/cline.ts +1 -1
  244. package/src/auth/codex.ts +1 -1
  245. package/src/auth/oca.ts +1 -1
  246. package/src/cron/index.ts +5 -0
  247. package/src/cron/resource-limiter.ts +46 -0
  248. package/src/cron/schedule-command-service.ts +193 -0
  249. package/src/cron/schedule-service.ts +703 -0
  250. package/src/cron/scheduler.ts +637 -0
  251. package/src/cron/sqlite-schedule-store.ts +708 -0
  252. package/src/extensions/config/agent-config-loader.ts +18 -12
  253. package/src/extensions/config/agent-config-parser.ts +1 -1
  254. package/src/extensions/config/hooks-config-loader.ts +1 -2
  255. package/src/extensions/config/index.ts +0 -4
  256. package/src/extensions/config/runtime-commands.ts +6 -0
  257. package/src/extensions/config/user-instruction-config-loader.ts +1 -4
  258. package/src/extensions/context/agentic-compaction.ts +3 -3
  259. package/src/extensions/context/basic-compaction.ts +2 -2
  260. package/src/extensions/context/compaction-shared.ts +5 -4
  261. package/src/extensions/context/compaction.ts +3 -3
  262. package/src/extensions/plugin/plugin-config-loader.ts +17 -2
  263. package/src/extensions/plugin/plugin-loader.ts +48 -4
  264. package/src/extensions/plugin/plugin-module-import.ts +0 -2
  265. package/src/extensions/plugin/plugin-sandbox-bootstrap.ts +93 -39
  266. package/src/extensions/plugin/plugin-sandbox.ts +47 -27
  267. package/src/extensions/plugin/plugin-targeting.ts +32 -0
  268. package/src/{tools → extensions/tools}/definitions.ts +31 -50
  269. package/src/{tools → extensions/tools}/executors/apply-patch.ts +69 -80
  270. package/src/{tools → extensions/tools}/executors/file-read.ts +29 -4
  271. package/src/{tools → extensions/tools}/executors/search.ts +196 -4
  272. package/src/{tools → extensions/tools}/index.ts +10 -0
  273. package/src/{tools → extensions/tools}/model-tool-routing.ts +1 -1
  274. package/src/{tools → extensions/tools}/presets.ts +31 -47
  275. package/src/extensions/tools/runtime.ts +261 -0
  276. package/src/{tools → extensions/tools}/schemas.ts +4 -2
  277. package/src/{team → extensions/tools/team}/multi-agent.ts +80 -17
  278. package/src/{team → extensions/tools/team}/spawn-agent-tool.ts +1 -7
  279. package/src/{team → extensions/tools/team}/subagent-prompts.ts +2 -2
  280. package/src/{team → extensions/tools/team}/team-tools.ts +84 -53
  281. package/src/{tools → extensions/tools}/types.ts +5 -3
  282. package/src/{runtime → hooks}/checkpoint-hooks.ts +27 -0
  283. package/src/{runtime → hooks}/hook-file-hooks.ts +14 -13
  284. package/src/hooks/index.ts +0 -7
  285. package/src/hooks/subprocess-runner.ts +1 -1
  286. package/src/hooks/subprocess.ts +57 -257
  287. package/src/hub/browser-websocket.ts +137 -0
  288. package/src/hub/client.ts +574 -0
  289. package/src/hub/connect.ts +156 -0
  290. package/src/hub/daemon-entry.ts +87 -0
  291. package/src/hub/daemon.ts +181 -0
  292. package/src/hub/defaults.ts +43 -0
  293. package/src/hub/discovery.ts +247 -0
  294. package/src/hub/index.ts +14 -0
  295. package/src/hub/native-transport.ts +31 -0
  296. package/src/hub/runtime-handlers.ts +140 -0
  297. package/src/hub/server.ts +1888 -0
  298. package/src/hub/session-client.ts +460 -0
  299. package/src/hub/start-shared-server.ts +58 -0
  300. package/src/hub/transport.ts +14 -0
  301. package/src/hub/ui-client.ts +122 -0
  302. package/src/hub/workspace.ts +19 -0
  303. package/src/index.ts +264 -199
  304. package/src/llms/configured-provider-registry.ts +193 -0
  305. package/src/llms/provider-defaults.ts +637 -0
  306. package/src/llms/provider-settings.ts +263 -0
  307. package/src/llms/runtime-config.ts +43 -0
  308. package/src/llms/runtime-registry.ts +171 -0
  309. package/src/llms/runtime-types.ts +121 -0
  310. package/src/runtime/history.ts +237 -0
  311. package/src/runtime/host.ts +200 -0
  312. package/src/runtime/index.ts +1 -0
  313. package/src/runtime/rules.ts +12 -0
  314. package/src/runtime/runtime-builder.ts +37 -29
  315. package/src/runtime/runtime-host.ts +206 -0
  316. package/src/{session → runtime}/runtime-oauth-token-manager.ts +12 -16
  317. package/src/runtime/session-runtime.ts +2 -26
  318. package/src/{session/session-agent-events.ts → services/agent-events.ts} +7 -7
  319. package/src/services/config.ts +5 -0
  320. package/src/services/global-settings.ts +122 -0
  321. package/src/services/local-runtime-bootstrap.ts +318 -0
  322. package/src/services/plugin-tools.ts +85 -0
  323. package/src/{providers → services/providers}/local-provider-registry.ts +6 -6
  324. package/src/{providers → services/providers}/local-provider-service.ts +46 -41
  325. package/src/{session → services}/session-artifacts.ts +7 -19
  326. package/src/{session/utils/helpers.ts → services/session-data.ts} +90 -80
  327. package/src/{session → services}/session-telemetry.ts +7 -9
  328. package/src/services/storage/artifact-store.ts +1 -0
  329. package/src/{storage → services/storage}/file-team-store.ts +2 -2
  330. package/src/{storage → services/storage}/provider-settings-legacy-migration.ts +6 -4
  331. package/src/{storage → services/storage}/provider-settings-manager.ts +3 -3
  332. package/src/services/storage/session-store.ts +1 -0
  333. package/src/{storage → services/storage}/sqlite-session-store.ts +7 -12
  334. package/src/{storage → services/storage}/sqlite-team-store.ts +4 -4
  335. package/src/{storage → services/storage}/team-store.ts +1 -1
  336. package/src/{session/utils → services}/usage.ts +1 -1
  337. package/src/{input → services/workspace}/file-indexer.ts +26 -2
  338. package/src/{input → services/workspace}/mention-enricher.ts +1 -1
  339. package/src/{session → services}/workspace-manifest.ts +18 -0
  340. package/src/session/file-session-service.ts +10 -8
  341. package/src/session/index.ts +10 -23
  342. package/src/session/persistence-service.ts +144 -528
  343. package/src/session/session-manifest-store.ts +158 -0
  344. package/src/session/session-row.ts +199 -0
  345. package/src/session/session-service.ts +43 -389
  346. package/src/session/session-team-coordination.ts +14 -7
  347. package/src/session/subagent-session-manager.ts +397 -0
  348. package/src/session/team-persistence-store.ts +176 -0
  349. package/src/session/workspace-manager.ts +1 -1
  350. package/src/transports/hub.ts +656 -0
  351. package/src/{session/default-session-manager.ts → transports/local.ts} +263 -200
  352. package/src/transports/remote.ts +26 -0
  353. package/src/transports/runtime-host-support.ts +140 -0
  354. package/src/{chat → types}/chat-schema.ts +4 -5
  355. package/src/types/config.ts +10 -9
  356. package/src/types/provider-settings.ts +11 -7
  357. package/src/{session/utils/types.ts → types/session.ts} +16 -5
  358. package/src/types/sessions.ts +21 -0
  359. package/src/types/storage.ts +1 -6
  360. package/src/types.ts +52 -19
  361. package/dist/chat/chat-schema.d.ts.map +0 -1
  362. package/dist/hooks/persistent.d.ts +0 -64
  363. package/dist/hooks/persistent.d.ts.map +0 -1
  364. package/dist/input/file-indexer.d.ts.map +0 -1
  365. package/dist/input/index.d.ts.map +0 -1
  366. package/dist/input/mention-enricher.d.ts.map +0 -1
  367. package/dist/prompt/default-system.d.ts +0 -2
  368. package/dist/prompt/default-system.d.ts.map +0 -1
  369. package/dist/providers/local-provider-registry.d.ts.map +0 -1
  370. package/dist/providers/local-provider-service.d.ts.map +0 -1
  371. package/dist/runtime/checkpoint-hooks.d.ts.map +0 -1
  372. package/dist/runtime/hook-file-hooks.d.ts.map +0 -1
  373. package/dist/session/default-session-manager.d.ts.map +0 -1
  374. package/dist/session/rpc-runtime-ensure.d.ts +0 -53
  375. package/dist/session/rpc-runtime-ensure.d.ts.map +0 -1
  376. package/dist/session/rpc-session-service.d.ts +0 -13
  377. package/dist/session/rpc-session-service.d.ts.map +0 -1
  378. package/dist/session/rpc-spawn-lease.d.ts +0 -8
  379. package/dist/session/rpc-spawn-lease.d.ts.map +0 -1
  380. package/dist/session/session-agent-events.d.ts.map +0 -1
  381. package/dist/session/session-artifacts.d.ts.map +0 -1
  382. package/dist/session/session-config-builder.d.ts +0 -16
  383. package/dist/session/session-config-builder.d.ts.map +0 -1
  384. package/dist/session/session-host.d.ts +0 -15
  385. package/dist/session/session-host.d.ts.map +0 -1
  386. package/dist/session/session-manager.d.ts +0 -62
  387. package/dist/session/session-manager.d.ts.map +0 -1
  388. package/dist/session/session-telemetry.d.ts.map +0 -1
  389. package/dist/session/sqlite-rpc-session-backend.d.ts +0 -31
  390. package/dist/session/sqlite-rpc-session-backend.d.ts.map +0 -1
  391. package/dist/session/utils/helpers.d.ts.map +0 -1
  392. package/dist/session/utils/types.d.ts.map +0 -1
  393. package/dist/session/utils/usage.d.ts.map +0 -1
  394. package/dist/session/workspace-manifest.d.ts +0 -5
  395. package/dist/session/workspace-manifest.d.ts.map +0 -1
  396. package/dist/storage/file-team-store.d.ts.map +0 -1
  397. package/dist/storage/provider-settings-legacy-migration.d.ts.map +0 -1
  398. package/dist/storage/provider-settings-manager.d.ts.map +0 -1
  399. package/dist/storage/sqlite-session-store.d.ts.map +0 -1
  400. package/dist/storage/sqlite-team-store.d.ts.map +0 -1
  401. package/dist/storage/team-store.d.ts.map +0 -1
  402. package/dist/team/delegated-agent.d.ts.map +0 -1
  403. package/dist/team/index.d.ts.map +0 -1
  404. package/dist/team/multi-agent.d.ts.map +0 -1
  405. package/dist/team/projections.d.ts.map +0 -1
  406. package/dist/team/runtime.d.ts.map +0 -1
  407. package/dist/team/spawn-agent-tool.d.ts.map +0 -1
  408. package/dist/team/subagent-prompts.d.ts.map +0 -1
  409. package/dist/team/team-tools.d.ts.map +0 -1
  410. package/dist/telemetry/ITelemetryAdapter.d.ts.map +0 -1
  411. package/dist/telemetry/OpenTelemetryAdapter.d.ts.map +0 -1
  412. package/dist/telemetry/OpenTelemetryProvider.d.ts.map +0 -1
  413. package/dist/telemetry/TelemetryLoggerSink.d.ts.map +0 -1
  414. package/dist/telemetry/TelemetryService.d.ts.map +0 -1
  415. package/dist/telemetry/core-events.d.ts.map +0 -1
  416. package/dist/telemetry/distinct-id.d.ts.map +0 -1
  417. package/dist/telemetry/index.d.ts.map +0 -1
  418. package/dist/telemetry/index.js +0 -15
  419. package/dist/tools/constants.d.ts.map +0 -1
  420. package/dist/tools/definitions.d.ts.map +0 -1
  421. package/dist/tools/executors/apply-patch-parser.d.ts.map +0 -1
  422. package/dist/tools/executors/apply-patch.d.ts.map +0 -1
  423. package/dist/tools/executors/bash.d.ts.map +0 -1
  424. package/dist/tools/executors/editor.d.ts.map +0 -1
  425. package/dist/tools/executors/file-read.d.ts.map +0 -1
  426. package/dist/tools/executors/index.d.ts.map +0 -1
  427. package/dist/tools/executors/search.d.ts.map +0 -1
  428. package/dist/tools/executors/web-fetch.d.ts.map +0 -1
  429. package/dist/tools/helpers.d.ts.map +0 -1
  430. package/dist/tools/index.d.ts.map +0 -1
  431. package/dist/tools/model-tool-routing.d.ts.map +0 -1
  432. package/dist/tools/presets.d.ts.map +0 -1
  433. package/dist/tools/schemas.d.ts.map +0 -1
  434. package/dist/tools/types.d.ts.map +0 -1
  435. package/src/ClineCore.test.ts +0 -150
  436. package/src/account/cline-account-service.test.ts +0 -185
  437. package/src/account/featurebase-token.test.ts +0 -175
  438. package/src/account/rpc.test.ts +0 -63
  439. package/src/auth/bounded-ttl-cache.test.ts +0 -38
  440. package/src/auth/client.test.ts +0 -69
  441. package/src/auth/cline.test.ts +0 -267
  442. package/src/auth/codex.test.ts +0 -170
  443. package/src/auth/oca.test.ts +0 -340
  444. package/src/auth/server.test.ts +0 -287
  445. package/src/auth/utils.test.ts +0 -128
  446. package/src/extensions/config/agent-config-loader.test.ts +0 -236
  447. package/src/extensions/config/hooks-config-loader.test.ts +0 -20
  448. package/src/extensions/config/runtime-commands.test.ts +0 -115
  449. package/src/extensions/config/unified-config-file-watcher.test.ts +0 -196
  450. package/src/extensions/config/user-instruction-config-loader.test.ts +0 -246
  451. package/src/extensions/context/compaction.test.ts +0 -483
  452. package/src/extensions/mcp/config-loader.test.ts +0 -238
  453. package/src/extensions/mcp/manager.test.ts +0 -105
  454. package/src/extensions/plugin/plugin-config-loader.test.ts +0 -182
  455. package/src/extensions/plugin/plugin-loader.test.ts +0 -292
  456. package/src/extensions/plugin/plugin-sandbox.test.ts +0 -423
  457. package/src/hooks/persistent.ts +0 -661
  458. package/src/input/file-indexer.d.ts +0 -11
  459. package/src/input/file-indexer.test.ts +0 -127
  460. package/src/input/mention-enricher.test.ts +0 -85
  461. package/src/prompt/default-system.ts +0 -21
  462. package/src/providers/local-provider-service.test.ts +0 -1062
  463. package/src/runtime/checkpoint-hooks.test.ts +0 -168
  464. package/src/runtime/hook-file-hooks.test.ts +0 -311
  465. package/src/runtime/runtime-builder.team-persistence.test.ts +0 -242
  466. package/src/runtime/runtime-builder.test.ts +0 -616
  467. package/src/runtime/runtime-parity.test.ts +0 -143
  468. package/src/session/default-session-manager.e2e.test.ts +0 -384
  469. package/src/session/default-session-manager.test.ts +0 -2473
  470. package/src/session/persistence-service.test.ts +0 -241
  471. package/src/session/rpc-runtime-ensure.ts +0 -521
  472. package/src/session/rpc-session-service.ts +0 -107
  473. package/src/session/rpc-spawn-lease.test.ts +0 -49
  474. package/src/session/rpc-spawn-lease.ts +0 -122
  475. package/src/session/runtime-oauth-token-manager.test.ts +0 -137
  476. package/src/session/session-config-builder.ts +0 -172
  477. package/src/session/session-host.test.ts +0 -89
  478. package/src/session/session-host.ts +0 -213
  479. package/src/session/session-manager.ts +0 -74
  480. package/src/session/session-service.team-persistence.test.ts +0 -48
  481. package/src/session/sqlite-rpc-session-backend.ts +0 -303
  482. package/src/session/utils/helpers.test.ts +0 -160
  483. package/src/storage/artifact-store.ts +0 -1
  484. package/src/storage/provider-settings-legacy-migration.test.ts +0 -424
  485. package/src/storage/provider-settings-manager.test.ts +0 -191
  486. package/src/storage/session-store.ts +0 -1
  487. package/src/team/multi-agent.lifecycle.test.ts +0 -201
  488. package/src/team/spawn-agent-tool.test.ts +0 -387
  489. package/src/team/team-tools.test.ts +0 -906
  490. package/src/telemetry/OpenTelemetryAdapter.test.ts +0 -157
  491. package/src/telemetry/OpenTelemetryProvider.test.ts +0 -326
  492. package/src/telemetry/TelemetryLoggerSink.test.ts +0 -42
  493. package/src/telemetry/TelemetryService.test.ts +0 -134
  494. package/src/telemetry/distinct-id.test.ts +0 -57
  495. package/src/tools/definitions.test.ts +0 -780
  496. package/src/tools/executors/bash.test.ts +0 -87
  497. package/src/tools/executors/editor.test.ts +0 -35
  498. package/src/tools/executors/file-read.test.ts +0 -49
  499. package/src/tools/model-tool-routing.test.ts +0 -86
  500. package/src/tools/presets.test.ts +0 -70
  501. /package/dist/{tools → extensions/tools}/constants.d.ts +0 -0
  502. /package/dist/{tools → extensions/tools}/executors/apply-patch-parser.d.ts +0 -0
  503. /package/dist/{tools → extensions/tools}/executors/bash.d.ts +0 -0
  504. /package/dist/{tools → extensions/tools}/executors/editor.d.ts +0 -0
  505. /package/dist/{tools → extensions/tools}/executors/file-read.d.ts +0 -0
  506. /package/dist/{tools → extensions/tools}/executors/index.d.ts +0 -0
  507. /package/dist/{tools → extensions/tools}/executors/web-fetch.d.ts +0 -0
  508. /package/dist/{tools → extensions/tools}/helpers.d.ts +0 -0
  509. /package/dist/{tools → extensions/tools}/schemas.d.ts +0 -0
  510. /package/dist/{team → extensions/tools/team}/delegated-agent.d.ts +0 -0
  511. /package/dist/{team → extensions/tools/team}/index.d.ts +0 -0
  512. /package/dist/{team → extensions/tools/team}/projections.d.ts +0 -0
  513. /package/dist/{team → extensions/tools/team}/runtime.d.ts +0 -0
  514. /package/dist/{team → extensions/tools/team}/subagent-prompts.d.ts +0 -0
  515. /package/dist/{telemetry → services/telemetry}/ITelemetryAdapter.d.ts +0 -0
  516. /package/dist/{telemetry → services/telemetry}/OpenTelemetryAdapter.d.ts +0 -0
  517. /package/dist/{telemetry → services/telemetry}/OpenTelemetryProvider.d.ts +0 -0
  518. /package/dist/{telemetry → services/telemetry}/TelemetryLoggerSink.d.ts +0 -0
  519. /package/dist/{telemetry → services/telemetry}/TelemetryService.d.ts +0 -0
  520. /package/dist/{telemetry → services/telemetry}/core-events.d.ts +0 -0
  521. /package/dist/{telemetry → services/telemetry}/distinct-id.d.ts +0 -0
  522. /package/dist/{telemetry → services/telemetry}/index.d.ts +0 -0
  523. /package/dist/{input → services/workspace}/file-indexer.d.ts +0 -0
  524. /package/dist/{input → services/workspace}/index.d.ts +0 -0
  525. /package/dist/{input → services/workspace}/mention-enricher.d.ts +0 -0
  526. /package/src/{tools → extensions/tools}/constants.ts +0 -0
  527. /package/src/{tools → extensions/tools}/executors/apply-patch-parser.ts +0 -0
  528. /package/src/{tools → extensions/tools}/executors/bash.ts +0 -0
  529. /package/src/{tools → extensions/tools}/executors/editor.ts +0 -0
  530. /package/src/{tools → extensions/tools}/executors/index.ts +0 -0
  531. /package/src/{tools → extensions/tools}/executors/web-fetch.ts +0 -0
  532. /package/src/{tools → extensions/tools}/helpers.ts +0 -0
  533. /package/src/{team → extensions/tools/team}/delegated-agent.ts +0 -0
  534. /package/src/{team → extensions/tools/team}/index.ts +0 -0
  535. /package/src/{team → extensions/tools/team}/projections.ts +0 -0
  536. /package/src/{team → extensions/tools/team}/runtime.ts +0 -0
  537. /package/src/{storage → services/storage}/index.ts +0 -0
  538. /package/src/{telemetry → services/telemetry}/ITelemetryAdapter.ts +0 -0
  539. /package/src/{telemetry → services/telemetry}/OpenTelemetryAdapter.ts +0 -0
  540. /package/src/{telemetry → services/telemetry}/OpenTelemetryProvider.ts +0 -0
  541. /package/src/{telemetry → services/telemetry}/TelemetryLoggerSink.ts +0 -0
  542. /package/src/{telemetry → services/telemetry}/TelemetryService.ts +0 -0
  543. /package/src/{telemetry → services/telemetry}/core-events.ts +0 -0
  544. /package/src/{telemetry → services/telemetry}/distinct-id.ts +0 -0
  545. /package/src/{telemetry → services/telemetry}/index.ts +0 -0
  546. /package/src/{input → services/workspace}/index.ts +0 -0
@@ -0,0 +1,703 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import type {
3
+ BasicLogger,
4
+ ChatRunTurnRequest,
5
+ ChatStartSessionArtifacts,
6
+ ChatStartSessionRequest,
7
+ HubScheduleCreateInput,
8
+ HubScheduleUpdateInput,
9
+ ScheduleExecutionRecord,
10
+ ScheduleExecutionStatus,
11
+ ScheduleRecord,
12
+ } from "@clinebot/shared";
13
+ import { nowIso } from "@clinebot/shared/db";
14
+ import { ResourceLimiter } from "./resource-limiter";
15
+ import { validateCronPattern } from "./scheduler";
16
+ import {
17
+ type ListScheduleExecutionsOptions,
18
+ type ListSchedulesOptions,
19
+ type ScheduleClaimRecord,
20
+ type ScheduleExecutionStats,
21
+ SqliteHubScheduleStore,
22
+ } from "./sqlite-schedule-store";
23
+
24
+ function toErrorMessage(error: unknown): string {
25
+ return error instanceof Error ? error.message : String(error);
26
+ }
27
+
28
+ type HubScheduleTurnResult = {
29
+ text: string;
30
+ usage?: {
31
+ inputTokens?: number;
32
+ outputTokens?: number;
33
+ cacheReadTokens?: number;
34
+ cacheWriteTokens?: number;
35
+ totalCost?: number;
36
+ };
37
+ inputTokens?: number;
38
+ outputTokens?: number;
39
+ iterations?: number;
40
+ finishReason?: string;
41
+ messages?: unknown[];
42
+ toolCalls?: Array<{
43
+ name: string;
44
+ input?: unknown;
45
+ output?: unknown;
46
+ error?: string;
47
+ durationMs?: number;
48
+ }>;
49
+ };
50
+
51
+ function parseTurnMetrics(result: HubScheduleTurnResult): {
52
+ iterations?: number;
53
+ tokensUsed?: number;
54
+ costUsd?: number;
55
+ } {
56
+ const inputTokens =
57
+ typeof result.inputTokens === "number" ? result.inputTokens : undefined;
58
+ const outputTokens =
59
+ typeof result.outputTokens === "number" ? result.outputTokens : undefined;
60
+ return {
61
+ iterations:
62
+ typeof result.iterations === "number" ? result.iterations : undefined,
63
+ tokensUsed:
64
+ inputTokens !== undefined && outputTokens !== undefined
65
+ ? inputTokens + outputTokens
66
+ : undefined,
67
+ costUsd:
68
+ typeof result.usage?.totalCost === "number"
69
+ ? result.usage.totalCost
70
+ : undefined,
71
+ };
72
+ }
73
+
74
+ interface AggregatedTurnMetrics {
75
+ iterations?: number;
76
+ tokensUsed?: number;
77
+ costUsd?: number;
78
+ }
79
+
80
+ function addTurnMetrics(
81
+ current: AggregatedTurnMetrics,
82
+ result: HubScheduleTurnResult,
83
+ ): AggregatedTurnMetrics {
84
+ const next = { ...current };
85
+ const metrics = parseTurnMetrics(result);
86
+ if (typeof metrics.iterations === "number") {
87
+ next.iterations = (next.iterations ?? 0) + metrics.iterations;
88
+ }
89
+ if (typeof metrics.tokensUsed === "number") {
90
+ next.tokensUsed = (next.tokensUsed ?? 0) + metrics.tokensUsed;
91
+ }
92
+ if (typeof metrics.costUsd === "number") {
93
+ next.costUsd = (next.costUsd ?? 0) + metrics.costUsd;
94
+ }
95
+ return next;
96
+ }
97
+
98
+ function optionsOrDefault(value: number | undefined, fallback: number): number {
99
+ return typeof value === "number" && Number.isFinite(value) ? value : fallback;
100
+ }
101
+
102
+ function asPositiveSeconds(value: unknown, fallback: number): number {
103
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
104
+ return fallback;
105
+ }
106
+ return Math.max(1, Math.floor(value));
107
+ }
108
+
109
+ const DEFAULT_AUTONOMOUS_IDLE_TIMEOUT_SECONDS = 60;
110
+ const DEFAULT_AUTONOMOUS_POLL_INTERVAL_SECONDS = 5;
111
+ const AUTONOMOUS_IDLE_NOOP_TOKEN = "<idle-noop/>";
112
+
113
+ export interface ScheduleAutonomousOptions {
114
+ enabled?: boolean;
115
+ idleTimeoutSeconds?: number;
116
+ pollIntervalSeconds?: number;
117
+ }
118
+
119
+ function getAutonomousOptions(
120
+ schedule: ScheduleRecord,
121
+ ): ScheduleAutonomousOptions | undefined {
122
+ const metadata = schedule.metadata;
123
+ if (!metadata || typeof metadata !== "object") {
124
+ return undefined;
125
+ }
126
+ const raw =
127
+ metadata.autonomous &&
128
+ typeof metadata.autonomous === "object" &&
129
+ !Array.isArray(metadata.autonomous)
130
+ ? (metadata.autonomous as Record<string, unknown>)
131
+ : undefined;
132
+ if (!raw || raw.enabled !== true) {
133
+ return undefined;
134
+ }
135
+ return {
136
+ enabled: true,
137
+ idleTimeoutSeconds: asPositiveSeconds(
138
+ raw.idleTimeoutSeconds,
139
+ DEFAULT_AUTONOMOUS_IDLE_TIMEOUT_SECONDS,
140
+ ),
141
+ pollIntervalSeconds: asPositiveSeconds(
142
+ raw.pollIntervalSeconds,
143
+ DEFAULT_AUTONOMOUS_POLL_INTERVAL_SECONDS,
144
+ ),
145
+ };
146
+ }
147
+
148
+ function buildSchedulePrompt(
149
+ schedule: ScheduleRecord,
150
+ autonomous: ScheduleAutonomousOptions | undefined,
151
+ ): string {
152
+ if (!autonomous?.enabled) {
153
+ return schedule.prompt;
154
+ }
155
+ return `${schedule.prompt}
156
+
157
+ When you finish the immediate scheduled work, remain available for autonomous follow-up. During idle polling, inspect team mailbox and team tasks. Use team_task with action="list" to find ready unassigned work, claim it with team_task and action="claim", and resume execution when work exists. Reply exactly ${AUTONOMOUS_IDLE_NOOP_TOKEN} only when the poll finds no actionable work.`;
158
+ }
159
+
160
+ function buildAutonomousPollPrompt(
161
+ autonomous: ScheduleAutonomousOptions,
162
+ ): string {
163
+ return `Autonomous idle poll. Check team_read_mailbox for unread messages and use team_task with action="list" to find ready unassigned tasks. Claim and execute one task if actionable work exists. If there is nothing to do right now, reply exactly ${AUTONOMOUS_IDLE_NOOP_TOKEN} and nothing else. Poll cadence is ${autonomous.pollIntervalSeconds}s and the idle shutdown window is ${autonomous.idleTimeoutSeconds}s.`;
164
+ }
165
+
166
+ function isAutonomousNoop(result: HubScheduleTurnResult): boolean {
167
+ return result.text?.trim() === AUTONOMOUS_IDLE_NOOP_TOKEN;
168
+ }
169
+
170
+ function sleep(ms: number): Promise<void> {
171
+ return new Promise((resolve) => setTimeout(resolve, ms));
172
+ }
173
+
174
+ class TimeoutError extends Error {
175
+ constructor(message: string) {
176
+ super(message);
177
+ this.name = "TimeoutError";
178
+ }
179
+ }
180
+
181
+ async function withTimeout<T>(
182
+ promise: Promise<T>,
183
+ timeoutMs: number,
184
+ ): Promise<T> {
185
+ if (timeoutMs <= 0) {
186
+ return await promise;
187
+ }
188
+ let timeoutHandle: ReturnType<typeof setTimeout> | undefined;
189
+ const timeoutPromise = new Promise<never>((_, reject) => {
190
+ timeoutHandle = setTimeout(() => {
191
+ reject(new TimeoutError("scheduled execution timed out"));
192
+ }, timeoutMs);
193
+ });
194
+ try {
195
+ return await Promise.race([promise, timeoutPromise]);
196
+ } finally {
197
+ if (timeoutHandle) {
198
+ clearTimeout(timeoutHandle);
199
+ }
200
+ }
201
+ }
202
+
203
+ export interface HubScheduleRuntimeHandlers {
204
+ startSession(request: ChatStartSessionRequest): Promise<{
205
+ sessionId: string;
206
+ startResult?: ChatStartSessionArtifacts;
207
+ }>;
208
+ sendSession(
209
+ sessionId: string,
210
+ request: ChatRunTurnRequest,
211
+ ): Promise<{
212
+ result: HubScheduleTurnResult;
213
+ }>;
214
+ abortSession(sessionId: string): Promise<{ applied: boolean }>;
215
+ stopSession(sessionId: string): Promise<{ applied: boolean }>;
216
+ }
217
+
218
+ export interface ActiveScheduledExecution {
219
+ executionId: string;
220
+ scheduleId: string;
221
+ sessionId: string;
222
+ startedAt: string;
223
+ timeoutAt?: string;
224
+ }
225
+
226
+ export interface HubScheduleServiceOptions {
227
+ runtimeHandlers: HubScheduleRuntimeHandlers;
228
+ eventPublisher?: (eventType: string, payload: unknown) => void;
229
+ logger?: BasicLogger;
230
+ sessionsDbPath?: string;
231
+ pollIntervalMs?: number;
232
+ globalMaxConcurrency?: number;
233
+ claimLeaseSeconds?: number;
234
+ }
235
+
236
+ export class HubScheduleService {
237
+ private readonly store: SqliteHubScheduleStore;
238
+ private readonly resourceLimiter: ResourceLimiter;
239
+ private readonly options: HubScheduleServiceOptions;
240
+ private readonly claimLeaseMs: number;
241
+ private readonly activeExecutions = new Map<
242
+ string,
243
+ ActiveScheduledExecution
244
+ >();
245
+ private timer: ReturnType<typeof setInterval> | undefined;
246
+ private started = false;
247
+ private ticking = false;
248
+ private disposed = false;
249
+
250
+ constructor(options: HubScheduleServiceOptions) {
251
+ this.options = options;
252
+ this.store = new SqliteHubScheduleStore({
253
+ sessionsDbPath: options.sessionsDbPath,
254
+ });
255
+ this.resourceLimiter = new ResourceLimiter(
256
+ options.globalMaxConcurrency ?? 10,
257
+ );
258
+ this.claimLeaseMs = Math.max(
259
+ 5_000,
260
+ optionsOrDefault(options.claimLeaseSeconds, 90) * 1000,
261
+ );
262
+ }
263
+
264
+ public async start(): Promise<void> {
265
+ if (this.disposed) {
266
+ throw new Error("HubScheduleService has been disposed");
267
+ }
268
+ if (this.started) {
269
+ return;
270
+ }
271
+ this.started = true;
272
+ const intervalMs = Math.max(
273
+ 5_000,
274
+ optionsOrDefault(this.options.pollIntervalMs, 30_000),
275
+ );
276
+ this.options.logger?.log("hub.schedule.started", {
277
+ pollIntervalMs: intervalMs,
278
+ });
279
+ await this.tick();
280
+ this.timer = setInterval(() => {
281
+ void this.tick();
282
+ }, intervalMs);
283
+ }
284
+
285
+ public async stop(): Promise<void> {
286
+ const wasStarted = this.started;
287
+ this.started = false;
288
+ if (this.timer) {
289
+ clearInterval(this.timer);
290
+ this.timer = undefined;
291
+ }
292
+ if (wasStarted) {
293
+ this.options.logger?.log("hub.schedule.stopped", {});
294
+ }
295
+ const active = Array.from(this.activeExecutions.values());
296
+ await Promise.all(
297
+ active.map(async (execution) => {
298
+ try {
299
+ await this.options.runtimeHandlers.abortSession(execution.sessionId);
300
+ } catch {
301
+ // best effort
302
+ }
303
+ }),
304
+ );
305
+ }
306
+
307
+ public async dispose(): Promise<void> {
308
+ if (this.disposed) {
309
+ return;
310
+ }
311
+ this.disposed = true;
312
+ await this.stop();
313
+ this.store.close();
314
+ }
315
+
316
+ public createSchedule(input: HubScheduleCreateInput): ScheduleRecord {
317
+ validateCronPattern(input.cronPattern);
318
+ if (!input.workspaceRoot?.trim()) {
319
+ throw new Error("workspaceRoot is required for schedules");
320
+ }
321
+ return this.store.createSchedule(input);
322
+ }
323
+
324
+ public getSchedule(scheduleId: string): ScheduleRecord | undefined {
325
+ return this.store.getSchedule(scheduleId);
326
+ }
327
+
328
+ public listSchedules(options: ListSchedulesOptions = {}): ScheduleRecord[] {
329
+ return this.store.listSchedules(options);
330
+ }
331
+
332
+ public updateSchedule(
333
+ scheduleId: string,
334
+ updates: HubScheduleUpdateInput,
335
+ ): ScheduleRecord | undefined {
336
+ if (updates.cronPattern !== undefined) {
337
+ validateCronPattern(updates.cronPattern);
338
+ }
339
+ const current = this.store.getSchedule(scheduleId);
340
+ if (!current) {
341
+ return undefined;
342
+ }
343
+ const nextWorkspaceRoot =
344
+ updates.workspaceRoot !== undefined
345
+ ? updates.workspaceRoot.trim()
346
+ : current.workspaceRoot;
347
+ const nextEnabled = updates.enabled ?? current.enabled;
348
+ if (nextEnabled && !nextWorkspaceRoot) {
349
+ throw new Error("workspaceRoot is required for enabled schedules");
350
+ }
351
+ return this.store.updateSchedule(scheduleId, {
352
+ ...updates,
353
+ scheduleId,
354
+ });
355
+ }
356
+
357
+ public deleteSchedule(scheduleId: string): boolean {
358
+ return this.store.deleteSchedule(scheduleId);
359
+ }
360
+
361
+ public pauseSchedule(scheduleId: string): ScheduleRecord | undefined {
362
+ return this.updateSchedule(scheduleId, { scheduleId, enabled: false });
363
+ }
364
+
365
+ public resumeSchedule(scheduleId: string): ScheduleRecord | undefined {
366
+ return this.updateSchedule(scheduleId, { scheduleId, enabled: true });
367
+ }
368
+
369
+ public async triggerScheduleNow(
370
+ scheduleId: string,
371
+ ): Promise<ScheduleExecutionRecord | undefined> {
372
+ const schedule = this.store.getSchedule(scheduleId);
373
+ if (!schedule) {
374
+ return undefined;
375
+ }
376
+ return await this.executeSchedule(schedule, nowIso(), "manual");
377
+ }
378
+
379
+ public listScheduleExecutions(
380
+ options: ListScheduleExecutionsOptions,
381
+ ): ScheduleExecutionRecord[] {
382
+ return this.store.listExecutions(options);
383
+ }
384
+
385
+ public getScheduleStats(scheduleId: string): ScheduleExecutionStats {
386
+ return this.store.getExecutionStats(scheduleId);
387
+ }
388
+
389
+ public getActiveExecutions(): ActiveScheduledExecution[] {
390
+ return Array.from(this.activeExecutions.values());
391
+ }
392
+
393
+ public getUpcomingRuns(limit = 20): Array<{
394
+ scheduleId: string;
395
+ name: string;
396
+ nextRunAt: string;
397
+ }> {
398
+ return this.store.listUpcomingRuns(limit);
399
+ }
400
+
401
+ private async tick(): Promise<void> {
402
+ if (this.ticking) {
403
+ return;
404
+ }
405
+ this.ticking = true;
406
+ try {
407
+ const claims = this.store.claimDueSchedules(nowIso(), this.claimLeaseMs);
408
+ await Promise.allSettled(
409
+ claims.map((claim) => this.executeClaimedSchedule(claim)),
410
+ );
411
+ } catch (error) {
412
+ const logger = this.options.logger;
413
+ if (logger) {
414
+ if (logger.error) {
415
+ logger.error("hub.schedule.tick.failed", { error });
416
+ } else {
417
+ logger.log("hub.schedule.tick.failed", {
418
+ error,
419
+ severity: "error",
420
+ });
421
+ }
422
+ }
423
+ } finally {
424
+ this.ticking = false;
425
+ }
426
+ }
427
+
428
+ private async executeClaimedSchedule(
429
+ claim: ScheduleClaimRecord,
430
+ ): Promise<void> {
431
+ const releaseLeaseHeartbeat = this.startClaimLeaseHeartbeat(claim);
432
+ try {
433
+ const result = await this.executeSchedule(
434
+ claim.schedule,
435
+ new Date(claim.triggeredAt).toISOString(),
436
+ "scheduled",
437
+ );
438
+ const completedAt = result.startedAt ?? claim.triggeredAt;
439
+ this.store.completeScheduleClaim(
440
+ claim.schedule.scheduleId,
441
+ claim.claimToken,
442
+ new Date(completedAt).toISOString(),
443
+ );
444
+ } finally {
445
+ releaseLeaseHeartbeat();
446
+ }
447
+ }
448
+
449
+ private startClaimLeaseHeartbeat(claim: ScheduleClaimRecord): () => void {
450
+ const heartbeatMs = Math.max(1_000, Math.floor(this.claimLeaseMs / 2));
451
+ const interval = setInterval(() => {
452
+ const leaseUntilAt = new Date(
453
+ Date.now() + this.claimLeaseMs,
454
+ ).toISOString();
455
+ const renewed = this.store.renewScheduleClaim(
456
+ claim.schedule.scheduleId,
457
+ claim.claimToken,
458
+ leaseUntilAt,
459
+ );
460
+ if (!renewed) {
461
+ clearInterval(interval);
462
+ }
463
+ }, heartbeatMs);
464
+ return () => clearInterval(interval);
465
+ }
466
+
467
+ private buildStartRequest(schedule: ScheduleRecord): ChatStartSessionRequest {
468
+ const workspaceRoot = schedule.workspaceRoot.trim();
469
+ const provider = schedule.modelSelection?.providerId?.trim();
470
+ const model = schedule.modelSelection?.modelId?.trim();
471
+ if (!workspaceRoot) {
472
+ throw new Error("schedule requires workspaceRoot");
473
+ }
474
+ if (!provider || !model) {
475
+ throw new Error(
476
+ "schedule requires modelSelection.providerId and modelSelection.modelId",
477
+ );
478
+ }
479
+ return {
480
+ workspaceRoot,
481
+ cwd: schedule.cwd?.trim() || workspaceRoot,
482
+ provider,
483
+ model,
484
+ mode:
485
+ schedule.mode === "plan"
486
+ ? "plan"
487
+ : schedule.mode === "yolo"
488
+ ? "yolo"
489
+ : "act",
490
+ systemPrompt: schedule.systemPrompt,
491
+ maxIterations: schedule.maxIterations,
492
+ enableTools: schedule.runtimeOptions?.enableTools ?? true,
493
+ enableSpawn: schedule.runtimeOptions?.enableSpawn ?? true,
494
+ enableTeams: schedule.runtimeOptions?.enableTeams ?? true,
495
+ autoApproveTools: schedule.runtimeOptions?.autoApproveTools ?? true,
496
+ };
497
+ }
498
+
499
+ private async executeSchedule(
500
+ schedule: ScheduleRecord,
501
+ triggeredAt: string,
502
+ trigger: "scheduled" | "manual",
503
+ ): Promise<ScheduleExecutionRecord> {
504
+ const executionId = `exec_${randomUUID()}`;
505
+ const triggeredAtMs = new Date(triggeredAt).getTime();
506
+ const pending: ScheduleExecutionRecord = {
507
+ executionId,
508
+ scheduleId: schedule.scheduleId,
509
+ triggeredAt: triggeredAtMs,
510
+ status: "pending",
511
+ };
512
+ this.store.recordExecution(pending);
513
+
514
+ const acquired = this.resourceLimiter.acquire(
515
+ schedule.scheduleId,
516
+ executionId,
517
+ schedule.maxParallel ?? 1,
518
+ );
519
+ if (!acquired) {
520
+ const skipped: ScheduleExecutionRecord = {
521
+ ...pending,
522
+ status: "failed",
523
+ endedAt: Date.now(),
524
+ errorMessage: "concurrency limit reached",
525
+ };
526
+ this.store.recordExecution(skipped);
527
+ return skipped;
528
+ }
529
+
530
+ let sessionId: string | undefined;
531
+ let startedAt: number | undefined;
532
+ let timeoutAt: string | undefined;
533
+ let executionDeadlineMs: number | undefined;
534
+
535
+ try {
536
+ const startRequest = this.buildStartRequest(schedule);
537
+ const startResponse =
538
+ await this.options.runtimeHandlers.startSession(startRequest);
539
+ sessionId = startResponse.sessionId.trim();
540
+ if (!sessionId) {
541
+ throw new Error("runtime start returned empty sessionId");
542
+ }
543
+
544
+ startedAt = Date.now();
545
+ timeoutAt =
546
+ typeof schedule.timeoutSeconds === "number" &&
547
+ schedule.timeoutSeconds > 0
548
+ ? new Date(startedAt + schedule.timeoutSeconds * 1000).toISOString()
549
+ : undefined;
550
+ executionDeadlineMs = timeoutAt
551
+ ? new Date(timeoutAt).getTime()
552
+ : undefined;
553
+
554
+ const runningState: ScheduleExecutionRecord = {
555
+ ...pending,
556
+ sessionId,
557
+ startedAt,
558
+ status: "running",
559
+ };
560
+ this.store.recordExecution(runningState);
561
+ this.activeExecutions.set(executionId, {
562
+ executionId,
563
+ scheduleId: schedule.scheduleId,
564
+ sessionId,
565
+ startedAt: new Date(startedAt).toISOString(),
566
+ timeoutAt,
567
+ });
568
+ this.publishEvent("schedule.execution.started", {
569
+ scheduleId: schedule.scheduleId,
570
+ executionId,
571
+ sessionId,
572
+ trigger,
573
+ triggeredAt,
574
+ });
575
+
576
+ const turnRequest: ChatRunTurnRequest = {
577
+ config: startRequest,
578
+ prompt: buildSchedulePrompt(schedule, getAutonomousOptions(schedule)),
579
+ };
580
+ const sendTurn = async (
581
+ request: ChatRunTurnRequest,
582
+ ): Promise<HubScheduleTurnResult> => {
583
+ const sendPromise = this.options.runtimeHandlers.sendSession(
584
+ sessionId!,
585
+ request,
586
+ );
587
+ const timeoutMs = executionDeadlineMs
588
+ ? Math.max(1, executionDeadlineMs - Date.now())
589
+ : 0;
590
+ const sendResult = await withTimeout(sendPromise, timeoutMs);
591
+ return sendResult.result;
592
+ };
593
+
594
+ let metrics = addTurnMetrics({}, await sendTurn(turnRequest));
595
+ const autonomous = getAutonomousOptions(schedule);
596
+ if (autonomous?.enabled) {
597
+ metrics = await this.runAutonomousIdleLoop({
598
+ sessionId,
599
+ startRequest,
600
+ autonomous,
601
+ metrics,
602
+ sendTurn,
603
+ executionDeadlineMs,
604
+ });
605
+ }
606
+
607
+ const completed: ScheduleExecutionRecord = {
608
+ ...runningState,
609
+ status: "success",
610
+ endedAt: Date.now(),
611
+ iterations: metrics.iterations,
612
+ tokensUsed: metrics.tokensUsed,
613
+ costUsd: metrics.costUsd,
614
+ };
615
+ this.store.recordExecution(completed);
616
+ this.publishEvent("schedule.execution.completed", {
617
+ scheduleId: schedule.scheduleId,
618
+ executionId,
619
+ sessionId,
620
+ status: completed.status,
621
+ durationMs:
622
+ completed.startedAt && completed.endedAt
623
+ ? completed.endedAt - completed.startedAt
624
+ : undefined,
625
+ });
626
+ return completed;
627
+ } catch (error) {
628
+ const status: ScheduleExecutionStatus =
629
+ error instanceof TimeoutError ? "timeout" : "failed";
630
+ if (sessionId && status === "timeout") {
631
+ try {
632
+ await this.options.runtimeHandlers.abortSession(sessionId);
633
+ } catch {
634
+ // best effort
635
+ }
636
+ }
637
+ const failed: ScheduleExecutionRecord = {
638
+ executionId,
639
+ scheduleId: schedule.scheduleId,
640
+ sessionId,
641
+ triggeredAt: triggeredAtMs,
642
+ startedAt,
643
+ endedAt: Date.now(),
644
+ status,
645
+ errorMessage: toErrorMessage(error),
646
+ };
647
+ this.store.recordExecution(failed);
648
+ this.publishEvent("schedule.execution.completed", {
649
+ scheduleId: schedule.scheduleId,
650
+ executionId,
651
+ sessionId,
652
+ status: failed.status,
653
+ errorMessage: failed.errorMessage,
654
+ });
655
+ return failed;
656
+ } finally {
657
+ if (sessionId) {
658
+ try {
659
+ await this.options.runtimeHandlers.stopSession(sessionId);
660
+ } catch {
661
+ // best effort
662
+ }
663
+ }
664
+ this.activeExecutions.delete(executionId);
665
+ this.resourceLimiter.release(schedule.scheduleId, executionId);
666
+ }
667
+ }
668
+
669
+ private publishEvent(eventType: string, payload: unknown): void {
670
+ this.options.eventPublisher?.(eventType, payload);
671
+ }
672
+
673
+ private async runAutonomousIdleLoop(options: {
674
+ sessionId: string;
675
+ startRequest: ChatStartSessionRequest;
676
+ autonomous: ScheduleAutonomousOptions;
677
+ metrics: AggregatedTurnMetrics;
678
+ sendTurn: (request: ChatRunTurnRequest) => Promise<HubScheduleTurnResult>;
679
+ executionDeadlineMs?: number;
680
+ }): Promise<AggregatedTurnMetrics> {
681
+ let metrics = options.metrics;
682
+ const idleDeadline =
683
+ Date.now() + options.autonomous.idleTimeoutSeconds! * 1000;
684
+ while (Date.now() < idleDeadline) {
685
+ if (
686
+ options.executionDeadlineMs !== undefined &&
687
+ Date.now() >= options.executionDeadlineMs
688
+ ) {
689
+ throw new TimeoutError("scheduled execution timed out");
690
+ }
691
+ await sleep(options.autonomous.pollIntervalSeconds! * 1000);
692
+ const result = await options.sendTurn({
693
+ config: options.startRequest,
694
+ prompt: buildAutonomousPollPrompt(options.autonomous),
695
+ });
696
+ metrics = addTurnMetrics(metrics, result);
697
+ if (isAutonomousNoop(result)) {
698
+ break;
699
+ }
700
+ }
701
+ return metrics;
702
+ }
703
+ }