@idleware/ringi 0.5.0 → 0.6.1

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 (378) hide show
  1. package/package.json +1 -1
  2. package/target/dts/adapters/fs/index.d.ts +2 -0
  3. package/target/dts/adapters/fs/lock.d.ts +1 -0
  4. package/target/dts/adapters/fs/write.d.ts +5 -0
  5. package/target/dts/adapters/host-posix/group-state.d.ts +7 -0
  6. package/target/dts/adapters/host-posix/groups.d.ts +1 -0
  7. package/target/dts/adapters/host-posix/index.d.ts +2 -0
  8. package/target/dts/adapters/host-posix/launch.d.ts +7 -0
  9. package/target/dts/adapters/host-posix/probes.d.ts +5 -0
  10. package/target/dts/adapters/host-posix/stats.d.ts +9 -0
  11. package/target/dts/adapters/keys-file/index.d.ts +2 -0
  12. package/target/dts/adapters/state-fs/index.d.ts +5 -0
  13. package/target/dts/adapters/tool-claude/index.d.ts +2 -0
  14. package/target/dts/adapters/tool-codex/index.d.ts +2 -0
  15. package/target/dts/adapters/tool-cursor/index.d.ts +2 -0
  16. package/target/dts/adapters/tool-traces/index.d.ts +3 -0
  17. package/target/dts/adapters/transport-git/branches.d.ts +43 -0
  18. package/target/dts/adapters/transport-git/files.d.ts +2 -0
  19. package/target/dts/adapters/transport-git/index.d.ts +32 -0
  20. package/target/dts/adapters/transport-git/marks.d.ts +20 -0
  21. package/target/dts/adapters/transport-git/remote/admit.d.ts +7 -0
  22. package/target/dts/adapters/transport-git/remote/alarms.d.ts +3 -0
  23. package/target/dts/adapters/transport-git/remote/bootstrap.d.ts +7 -0
  24. package/target/dts/adapters/transport-git/remote/branch-commit.d.ts +3 -0
  25. package/target/dts/adapters/transport-git/remote/branch-control.d.ts +15 -0
  26. package/target/dts/adapters/transport-git/remote/branch-scan.d.ts +2 -0
  27. package/target/dts/adapters/transport-git/remote/branch.d.ts +5 -0
  28. package/target/dts/adapters/transport-git/remote/cache.d.ts +3 -0
  29. package/target/dts/adapters/transport-git/remote/commits.d.ts +2 -0
  30. package/target/dts/adapters/transport-git/remote/forget.d.ts +2 -0
  31. package/target/dts/adapters/transport-git/remote/git.d.ts +26 -0
  32. package/target/dts/adapters/transport-git/remote/heartbeat-facts.d.ts +1 -0
  33. package/target/dts/adapters/transport-git/remote/heartbeat-name.d.ts +6 -0
  34. package/target/dts/adapters/transport-git/remote/heartbeat-object.d.ts +10 -0
  35. package/target/dts/adapters/transport-git/remote/heartbeat-push.d.ts +2 -0
  36. package/target/dts/adapters/transport-git/remote/heartbeat.d.ts +7 -0
  37. package/target/dts/adapters/transport-git/remote/keys.d.ts +13 -0
  38. package/target/dts/adapters/transport-git/remote/main.d.ts +11 -0
  39. package/target/dts/adapters/transport-git/remote/process.d.ts +20 -0
  40. package/target/dts/adapters/transport-git/remote/push-retry.d.ts +2 -0
  41. package/target/dts/adapters/transport-git/remote/push-validate.d.ts +2 -0
  42. package/target/dts/adapters/transport-git/remote/push.d.ts +16 -0
  43. package/target/dts/adapters/transport-git/remote/roster.d.ts +7 -0
  44. package/target/dts/adapters/transport-git/remote/signals.d.ts +15 -0
  45. package/target/dts/adapters/transport-git/remote/signature.d.ts +5 -0
  46. package/target/dts/adapters/transport-git/remote/sync-heartbeat.d.ts +2 -0
  47. package/target/dts/adapters/transport-git/remote/sync-rooms.d.ts +6 -0
  48. package/target/dts/adapters/transport-git/remote/sync-tags.d.ts +8 -0
  49. package/target/dts/adapters/transport-git/remote/sync.d.ts +2 -0
  50. package/target/dts/adapters/transport-git/remote/types.d.ts +64 -0
  51. package/target/dts/adapters/transport-git/remote.d.ts +17 -0
  52. package/target/dts/adapters/transport-git/repo.d.ts +31 -0
  53. package/target/dts/adapters/transport-git/run.d.ts +21 -0
  54. package/target/dts/adapters/transport-git/signing.d.ts +4 -0
  55. package/target/dts/adapters/transport-git/tags.d.ts +15 -0
  56. package/target/dts/adapters/transport-git/transport.d.ts +7 -0
  57. package/target/dts/adapters/transport-kafka/index.d.ts +2 -0
  58. package/target/dts/adapters/transport-temporal/index.d.ts +2 -0
  59. package/target/dts/cli.d.ts +2 -1
  60. package/target/dts/{cli/agent.d.ts → clients/cli/agent/index.d.ts} +3 -3
  61. package/target/dts/{cli → clients/cli/agent}/session.d.ts +2 -2
  62. package/target/dts/clients/cli/arg-parse.d.ts +2 -0
  63. package/target/dts/{cli → clients/cli}/args.d.ts +2 -2
  64. package/target/dts/clients/cli/commands.d.ts +2 -0
  65. package/target/dts/clients/cli/context.d.ts +4 -0
  66. package/target/dts/{cli/index.d.ts → clients/cli/help.d.ts} +1 -3
  67. package/target/dts/clients/cli/index.d.ts +4 -0
  68. package/target/dts/clients/cli/operator/heartbeat-format.d.ts +5 -0
  69. package/target/dts/clients/cli/operator/heartbeat.d.ts +3 -0
  70. package/target/dts/clients/cli/operator/hub-commands.d.ts +6 -0
  71. package/target/dts/clients/cli/operator/hub.d.ts +2 -0
  72. package/target/dts/clients/cli/operator/index.d.ts +5 -0
  73. package/target/dts/clients/cli/operator/room-lifecycle.d.ts +5 -0
  74. package/target/dts/clients/cli/operator/room-list.d.ts +5 -0
  75. package/target/dts/clients/cli/operator/room-members.d.ts +4 -0
  76. package/target/dts/clients/cli/operator/room.d.ts +2 -0
  77. package/target/dts/clients/cli/operator/sessions.d.ts +5 -0
  78. package/target/dts/clients/cli/operator/watch.d.ts +2 -0
  79. package/target/dts/clients/cli/operator/where-format.d.ts +7 -0
  80. package/target/dts/clients/cli/operator/where.d.ts +2 -0
  81. package/target/dts/clients/cli/shared/budget.d.ts +7 -0
  82. package/target/dts/clients/cli/shared/files.d.ts +4 -0
  83. package/target/dts/clients/cli/shared/index.d.ts +7 -0
  84. package/target/dts/clients/cli/shared/messages.d.ts +7 -0
  85. package/target/dts/clients/cli/shared/profile.d.ts +4 -0
  86. package/target/dts/clients/cli/shared/session.d.ts +6 -0
  87. package/target/dts/clients/cli/shared/signals.d.ts +3 -0
  88. package/target/dts/clients/cli/shared/work.d.ts +6 -0
  89. package/target/dts/clients/cli/skill/index.d.ts +3 -0
  90. package/target/dts/{cli/skill.d.ts → clients/cli/skill/targets.d.ts} +1 -2
  91. package/target/dts/composition/index.d.ts +2 -0
  92. package/target/dts/{heartbeat → core/agents/heartbeat}/index.d.ts +2 -4
  93. package/target/dts/{app/heartbeat.d.ts → core/agents/heartbeat/pulse.d.ts} +5 -6
  94. package/target/dts/core/agents/heartbeat/singleton.d.ts +3 -0
  95. package/target/dts/core/agents/heartbeat/tools.d.ts +6 -0
  96. package/target/dts/{app → core/agents}/overview.d.ts +12 -6
  97. package/target/dts/core/agents/ports/host.d.ts +47 -0
  98. package/target/dts/core/agents/ports/index.d.ts +9 -0
  99. package/target/dts/core/agents/ports/tools.d.ts +18 -0
  100. package/target/dts/core/agents/sessions/agent.d.ts +70 -0
  101. package/target/dts/core/agents/sessions/binding.d.ts +9 -0
  102. package/target/dts/core/agents/sessions/context.d.ts +8 -0
  103. package/target/dts/{runtime/session.d.ts → core/agents/sessions/index.d.ts} +2 -9
  104. package/target/dts/core/agents/sessions/join.d.ts +20 -0
  105. package/target/dts/core/agents/sessions/resume.d.ts +2 -0
  106. package/target/dts/core/agents/sessions/session.d.ts +46 -0
  107. package/target/dts/core/agents/sessions/wait.d.ts +38 -0
  108. package/target/dts/core/agents/turns/budgets.d.ts +5 -0
  109. package/target/dts/core/agents/turns/dispatch.d.ts +9 -0
  110. package/target/dts/core/agents/turns/exhaustion.d.ts +11 -0
  111. package/target/dts/core/agents/turns/grants.d.ts +4 -0
  112. package/target/dts/core/agents/turns/index.d.ts +4 -0
  113. package/target/dts/core/agents/turns/limits.d.ts +2 -0
  114. package/target/dts/core/agents/turns/messages.d.ts +10 -0
  115. package/target/dts/core/agents/turns/pings.d.ts +5 -0
  116. package/target/dts/core/agents/turns/plan.d.ts +3 -0
  117. package/target/dts/core/agents/turns/poll.d.ts +8 -0
  118. package/target/dts/core/agents/turns/results.d.ts +3 -0
  119. package/target/dts/core/agents/turns/seat.d.ts +2 -0
  120. package/target/dts/core/agents/turns/types.d.ts +59 -0
  121. package/target/dts/core/hub/decisions/budget.d.ts +15 -0
  122. package/target/dts/core/hub/decisions/check.d.ts +6 -0
  123. package/target/dts/core/hub/decisions/index.d.ts +5 -0
  124. package/target/dts/core/hub/decisions/proposal.d.ts +38 -0
  125. package/target/dts/core/hub/decisions/usage.d.ts +12 -0
  126. package/target/dts/{runtime/reader.d.ts → core/hub/history/index.d.ts} +12 -6
  127. package/target/dts/core/hub/ports/index.d.ts +16 -0
  128. package/target/dts/core/hub/ports/state.d.ts +12 -0
  129. package/target/dts/{store/index.d.ts → core/hub/ports/store.d.ts} +48 -18
  130. package/target/dts/core/hub/protocol/index.d.ts +5 -0
  131. package/target/dts/{protocol/index.d.ts → core/hub/protocol/model.d.ts} +0 -25
  132. package/target/dts/core/hub/protocol/order.d.ts +2 -0
  133. package/target/dts/core/hub/protocol/reading.d.ts +8 -0
  134. package/target/dts/core/hub/protocol/text.d.ts +11 -0
  135. package/target/dts/core/hub/protocol/threads.d.ts +5 -0
  136. package/target/dts/core/hub/rooms/compat.d.ts +5 -0
  137. package/target/dts/core/hub/rooms/hubs.d.ts +14 -0
  138. package/target/dts/core/hub/rooms/index.d.ts +53 -0
  139. package/target/dts/core/hub/rooms/messages.d.ts +8 -0
  140. package/target/dts/core/hub/rooms/rooms.d.ts +10 -0
  141. package/target/dts/core/hub/signals/check.d.ts +3 -0
  142. package/target/dts/core/hub/signals/effective.d.ts +3 -0
  143. package/target/dts/core/hub/signals/index.d.ts +5 -0
  144. package/target/dts/core/hub/signals/marks.d.ts +4 -0
  145. package/target/dts/core/hub/signals/model.d.ts +28 -0
  146. package/target/dts/core/hub/signals/pins.d.ts +5 -0
  147. package/target/dts/{hub/signals.d.ts → core/hub/signals/write.d.ts} +1 -1
  148. package/target/dts/core/hub/usecases/actor.d.ts +6 -0
  149. package/target/dts/{app → core/hub/usecases}/budget.d.ts +5 -18
  150. package/target/dts/core/hub/usecases/config.d.ts +6 -0
  151. package/target/dts/{app → core/hub/usecases}/context.d.ts +3 -8
  152. package/target/dts/{app → core/hub/usecases}/hubs.d.ts +1 -1
  153. package/target/dts/core/hub/usecases/propose.d.ts +17 -0
  154. package/target/dts/{app → core/hub/usecases}/room.d.ts +8 -34
  155. package/target/dts/{app → core/hub/usecases}/rooms.d.ts +2 -6
  156. package/target/dts/core/hub/usecases/roster.d.ts +5 -0
  157. package/target/dts/core/hub/usecases/send.d.ts +21 -0
  158. package/target/dts/core/hub/usecases/staging.d.ts +8 -0
  159. package/target/dts/{app → core/hub/usecases}/view.d.ts +4 -4
  160. package/target/dts/{domain/profiles.d.ts → core/hub/work/index.d.ts} +3 -7
  161. package/target/dts/core/hub/work/parse.d.ts +2 -0
  162. package/target/dts/core/hub/work/task.d.ts +6 -0
  163. package/target/dts/core/signing/index.d.ts +35 -0
  164. package/target/dts/index.d.ts +8 -8
  165. package/target/dts/lib/fail.d.ts +8 -0
  166. package/target/dts/lib/index.d.ts +3 -11
  167. package/target/dts/lib/json.d.ts +1 -0
  168. package/target/esm/adapters/fs/index.js +5 -0
  169. package/target/esm/adapters/fs/lock.js +83 -0
  170. package/target/esm/adapters/fs/write.js +25 -0
  171. package/target/esm/adapters/host-posix/group-state.js +24 -0
  172. package/target/esm/adapters/host-posix/groups.js +43 -0
  173. package/target/esm/adapters/host-posix/index.js +35 -0
  174. package/target/esm/adapters/host-posix/launch.js +80 -0
  175. package/target/esm/adapters/host-posix/probes.js +66 -0
  176. package/target/esm/adapters/host-posix/stats.js +27 -0
  177. package/target/esm/adapters/keys-file/index.js +68 -0
  178. package/target/esm/adapters/state-fs/index.js +79 -0
  179. package/target/esm/adapters/tool-claude/index.js +32 -0
  180. package/target/esm/adapters/tool-codex/index.js +38 -0
  181. package/target/esm/adapters/tool-cursor/index.js +8 -0
  182. package/target/esm/adapters/tool-traces/index.js +18 -0
  183. package/target/esm/adapters/transport-git/branches.js +155 -0
  184. package/target/esm/adapters/transport-git/files.js +48 -0
  185. package/target/esm/adapters/transport-git/index.js +128 -0
  186. package/target/esm/adapters/transport-git/marks.js +88 -0
  187. package/target/esm/adapters/transport-git/remote/admit.js +71 -0
  188. package/target/esm/adapters/transport-git/remote/alarms.js +30 -0
  189. package/target/esm/adapters/transport-git/remote/bootstrap.js +47 -0
  190. package/target/esm/adapters/transport-git/remote/branch-commit.js +36 -0
  191. package/target/esm/adapters/transport-git/remote/branch-control.js +37 -0
  192. package/target/esm/adapters/transport-git/remote/branch-scan.js +28 -0
  193. package/target/esm/adapters/transport-git/remote/branch.js +37 -0
  194. package/target/esm/adapters/transport-git/remote/cache.js +23 -0
  195. package/target/esm/adapters/transport-git/remote/commits.js +25 -0
  196. package/target/esm/adapters/transport-git/remote/forget.js +35 -0
  197. package/target/esm/adapters/transport-git/remote/git.js +58 -0
  198. package/target/esm/adapters/transport-git/remote/heartbeat-facts.js +35 -0
  199. package/target/esm/adapters/transport-git/remote/heartbeat-name.js +19 -0
  200. package/target/esm/adapters/transport-git/remote/heartbeat-object.js +40 -0
  201. package/target/esm/adapters/transport-git/remote/heartbeat-push.js +44 -0
  202. package/target/esm/adapters/transport-git/remote/heartbeat.js +44 -0
  203. package/target/esm/adapters/transport-git/remote/keys.js +75 -0
  204. package/target/esm/adapters/transport-git/remote/main.js +41 -0
  205. package/target/esm/adapters/transport-git/remote/process.js +37 -0
  206. package/target/esm/adapters/transport-git/remote/push-retry.js +46 -0
  207. package/target/esm/adapters/transport-git/remote/push-validate.js +39 -0
  208. package/target/esm/adapters/transport-git/remote/push.js +62 -0
  209. package/target/esm/adapters/transport-git/remote/roster.js +48 -0
  210. package/target/esm/adapters/transport-git/remote/signals.js +63 -0
  211. package/target/esm/adapters/transport-git/remote/signature.js +56 -0
  212. package/target/esm/adapters/transport-git/remote/sync-heartbeat.js +26 -0
  213. package/target/esm/adapters/transport-git/remote/sync-rooms.js +38 -0
  214. package/target/esm/adapters/transport-git/remote/sync-tags.js +48 -0
  215. package/target/esm/adapters/transport-git/remote/sync.js +38 -0
  216. package/target/esm/adapters/transport-git/remote/types.js +10 -0
  217. package/target/esm/adapters/transport-git/remote.js +17 -0
  218. package/target/esm/adapters/transport-git/repo.js +115 -0
  219. package/target/esm/adapters/transport-git/run.js +57 -0
  220. package/target/esm/adapters/transport-git/signing.js +44 -0
  221. package/target/esm/adapters/transport-git/tags.js +21 -0
  222. package/target/esm/adapters/transport-git/transport.js +29 -0
  223. package/target/esm/adapters/transport-kafka/index.js +4 -0
  224. package/target/esm/adapters/transport-temporal/index.js +4 -0
  225. package/target/esm/cli.js +5 -4
  226. package/target/esm/{cli/agent.js → clients/cli/agent/index.js} +8 -7
  227. package/target/esm/{cli → clients/cli/agent}/session.js +7 -7
  228. package/target/esm/clients/cli/arg-parse.js +41 -0
  229. package/target/esm/{cli → clients/cli}/args.js +3 -36
  230. package/target/esm/clients/cli/commands.js +45 -0
  231. package/target/esm/clients/cli/context.js +6 -0
  232. package/target/esm/{cli/index.js → clients/cli/help.js} +4 -77
  233. package/target/esm/clients/cli/index.js +27 -0
  234. package/target/esm/clients/cli/operator/heartbeat-format.js +8 -0
  235. package/target/esm/clients/cli/operator/heartbeat.js +35 -0
  236. package/target/esm/clients/cli/operator/hub-commands.js +37 -0
  237. package/target/esm/clients/cli/operator/hub.js +10 -0
  238. package/target/esm/clients/cli/operator/index.js +8 -0
  239. package/target/esm/clients/cli/operator/room-lifecycle.js +23 -0
  240. package/target/esm/clients/cli/operator/room-list.js +27 -0
  241. package/target/esm/clients/cli/operator/room-members.js +15 -0
  242. package/target/esm/clients/cli/operator/room.js +15 -0
  243. package/target/esm/clients/cli/operator/sessions.js +32 -0
  244. package/target/esm/clients/cli/operator/watch.js +15 -0
  245. package/target/esm/clients/cli/operator/where-format.js +24 -0
  246. package/target/esm/clients/cli/operator/where.js +32 -0
  247. package/target/esm/clients/cli/shared/budget.js +50 -0
  248. package/target/esm/clients/cli/shared/files.js +26 -0
  249. package/target/esm/clients/cli/shared/index.js +10 -0
  250. package/target/esm/clients/cli/shared/messages.js +41 -0
  251. package/target/esm/clients/cli/shared/profile.js +17 -0
  252. package/target/esm/clients/cli/shared/session.js +8 -0
  253. package/target/esm/clients/cli/shared/signals.js +21 -0
  254. package/target/esm/clients/cli/shared/work.js +26 -0
  255. package/target/esm/clients/cli/skill/index.js +40 -0
  256. package/target/esm/clients/cli/skill/targets.js +20 -0
  257. package/target/esm/composition/index.js +34 -0
  258. package/target/esm/{heartbeat → core/agents/heartbeat}/index.js +14 -12
  259. package/target/esm/{app/heartbeat.js → core/agents/heartbeat/pulse.js} +31 -55
  260. package/target/esm/core/agents/heartbeat/singleton.js +38 -0
  261. package/target/esm/core/agents/heartbeat/tools.js +24 -0
  262. package/target/esm/{app → core/agents}/overview.js +15 -9
  263. package/target/esm/core/agents/ports/host.js +4 -0
  264. package/target/esm/core/agents/ports/index.js +7 -0
  265. package/target/esm/core/agents/ports/tools.js +5 -0
  266. package/target/esm/{app → core/agents/sessions}/agent.js +11 -43
  267. package/target/esm/core/agents/sessions/binding.js +43 -0
  268. package/target/esm/core/agents/sessions/context.js +11 -0
  269. package/target/esm/core/agents/sessions/index.js +59 -0
  270. package/target/esm/core/agents/sessions/join.js +55 -0
  271. package/target/esm/core/agents/sessions/resume.js +54 -0
  272. package/target/esm/core/agents/sessions/session.js +28 -0
  273. package/target/esm/core/agents/sessions/wait.js +47 -0
  274. package/target/esm/core/agents/turns/budgets.js +48 -0
  275. package/target/esm/core/agents/turns/dispatch.js +40 -0
  276. package/target/esm/core/agents/turns/exhaustion.js +16 -0
  277. package/target/esm/core/agents/turns/grants.js +36 -0
  278. package/target/esm/core/agents/turns/index.js +33 -0
  279. package/target/esm/core/agents/turns/limits.js +11 -0
  280. package/target/esm/core/agents/turns/messages.js +32 -0
  281. package/target/esm/core/agents/turns/pings.js +30 -0
  282. package/target/esm/core/agents/turns/plan.js +29 -0
  283. package/target/esm/core/agents/turns/poll.js +48 -0
  284. package/target/esm/core/agents/turns/results.js +40 -0
  285. package/target/esm/core/agents/turns/seat.js +44 -0
  286. package/target/esm/core/agents/turns/types.js +3 -0
  287. package/target/esm/{domain/index.js → core/hub/capabilities.js} +3 -3
  288. package/target/esm/core/hub/decisions/budget.js +40 -0
  289. package/target/esm/core/hub/decisions/check.js +43 -0
  290. package/target/esm/core/hub/decisions/index.js +10 -0
  291. package/target/esm/core/hub/decisions/proposal.js +73 -0
  292. package/target/esm/core/hub/decisions/usage.js +39 -0
  293. package/target/esm/core/hub/history/index.js +90 -0
  294. package/target/esm/core/hub/ports/index.js +10 -0
  295. package/target/esm/core/hub/ports/state.js +5 -0
  296. package/target/esm/core/hub/ports/store.js +10 -0
  297. package/target/esm/{protocol → core/hub/protocol}/files.js +4 -2
  298. package/target/esm/core/hub/protocol/index.js +9 -0
  299. package/target/esm/core/hub/protocol/model.js +15 -0
  300. package/target/esm/core/hub/protocol/order.js +39 -0
  301. package/target/esm/core/hub/protocol/reading.js +29 -0
  302. package/target/esm/core/hub/protocol/text.js +95 -0
  303. package/target/esm/core/hub/protocol/threads.js +52 -0
  304. package/target/esm/core/hub/rooms/compat.js +51 -0
  305. package/target/esm/core/hub/rooms/hubs.js +92 -0
  306. package/target/esm/core/hub/rooms/index.js +23 -0
  307. package/target/esm/core/hub/rooms/messages.js +47 -0
  308. package/target/esm/core/hub/rooms/rooms.js +84 -0
  309. package/target/esm/core/hub/signals/check.js +33 -0
  310. package/target/esm/core/hub/signals/effective.js +31 -0
  311. package/target/esm/core/hub/signals/index.js +23 -0
  312. package/target/esm/core/hub/signals/marks.js +30 -0
  313. package/target/esm/core/hub/signals/model.js +5 -0
  314. package/target/esm/core/hub/signals/pins.js +21 -0
  315. package/target/esm/{hub/signals.js → core/hub/signals/write.js} +4 -4
  316. package/target/esm/core/hub/usecases/actor.js +3 -0
  317. package/target/esm/core/hub/usecases/budget.js +78 -0
  318. package/target/esm/core/hub/usecases/config.js +5 -0
  319. package/target/esm/core/hub/usecases/context.js +13 -0
  320. package/target/esm/core/hub/usecases/hubs.js +95 -0
  321. package/target/esm/core/hub/usecases/propose.js +39 -0
  322. package/target/esm/core/hub/usecases/room.js +82 -0
  323. package/target/esm/{app → core/hub/usecases}/rooms.js +11 -63
  324. package/target/esm/core/hub/usecases/roster.js +47 -0
  325. package/target/esm/core/hub/usecases/send.js +78 -0
  326. package/target/esm/core/hub/usecases/staging.js +60 -0
  327. package/target/esm/{app → core/hub/usecases}/view.js +33 -33
  328. package/target/esm/core/hub/work/index.js +13 -0
  329. package/target/esm/core/hub/work/parse.js +37 -0
  330. package/target/esm/core/hub/work/task.js +68 -0
  331. package/target/esm/core/signing/index.js +4 -0
  332. package/target/esm/index.js +7 -6
  333. package/target/esm/lib/fail.js +18 -0
  334. package/target/esm/lib/index.js +20 -195
  335. package/target/esm/lib/json.js +81 -0
  336. package/target/dts/app/agent.d.ts +0 -109
  337. package/target/dts/app/session.d.ts +0 -65
  338. package/target/dts/cli/context.d.ts +0 -6
  339. package/target/dts/cli/operator.d.ts +0 -10
  340. package/target/dts/cli/shared.d.ts +0 -27
  341. package/target/dts/domain/decisions.d.ts +0 -65
  342. package/target/dts/domain/signals.d.ts +0 -37
  343. package/target/dts/heartbeat/platform.d.ts +0 -15
  344. package/target/dts/heartbeat/tools.d.ts +0 -11
  345. package/target/dts/home/index.d.ts +0 -21
  346. package/target/dts/hub/index.d.ts +0 -72
  347. package/target/dts/runtime/watch.d.ts +0 -17
  348. package/target/dts/store/git/index.d.ts +0 -92
  349. package/target/dts/store/git/remote.d.ts +0 -95
  350. package/target/dts/store/kafka/index.d.ts +0 -2
  351. package/target/dts/store/temporal/index.d.ts +0 -2
  352. package/target/esm/app/budget.js +0 -95
  353. package/target/esm/app/context.js +0 -16
  354. package/target/esm/app/hubs.js +0 -76
  355. package/target/esm/app/room.js +0 -181
  356. package/target/esm/app/session.js +0 -99
  357. package/target/esm/cli/context.js +0 -8
  358. package/target/esm/cli/operator.js +0 -185
  359. package/target/esm/cli/shared.js +0 -159
  360. package/target/esm/cli/skill.js +0 -54
  361. package/target/esm/domain/decisions.js +0 -178
  362. package/target/esm/domain/profiles.js +0 -96
  363. package/target/esm/domain/signals.js +0 -134
  364. package/target/esm/heartbeat/platform.js +0 -83
  365. package/target/esm/heartbeat/tools.js +0 -68
  366. package/target/esm/home/index.js +0 -88
  367. package/target/esm/hub/index.js +0 -224
  368. package/target/esm/protocol/index.js +0 -219
  369. package/target/esm/runtime/reader.js +0 -65
  370. package/target/esm/runtime/session.js +0 -116
  371. package/target/esm/runtime/watch.js +0 -321
  372. package/target/esm/store/git/index.js +0 -719
  373. package/target/esm/store/git/remote.js +0 -928
  374. package/target/esm/store/index.js +0 -15
  375. package/target/esm/store/kafka/index.js +0 -3
  376. package/target/esm/store/temporal/index.js +0 -3
  377. /package/target/dts/{domain/index.d.ts → core/hub/capabilities.d.ts} +0 -0
  378. /package/target/dts/{protocol → core/hub/protocol}/files.d.ts +0 -0
@@ -1,13 +1,14 @@
1
- // Agent operations return data; the runtime owns readers, seats and headless turns.
2
- import { HIDDEN, append, pongText, start, withSizes } from '../hub/index.js';
3
- import * as Signals from '../hub/signals.js';
4
- import { fail, sleep } from '../lib/index.js';
5
- import { ID_RE, checkOutgoing, compose, link, lookup, unread } from '../protocol/index.js';
6
- import { linked, loadRoom, loadRoomUnlocked, loadState, readerLock, saveState } from '../runtime/reader.js';
7
- import { bound } from '../runtime/session.js';
8
- import { isRef } from './room.js';
9
- export { bound } from '../runtime/session.js';
10
- export { watch } from '../runtime/watch.js';
1
+ // agent: what an agent does in its room as itself: read its inbox (marking what it read), take a piece of work, show
2
+ // who it is, leave its card, wait and ping; the headless watcher is turns/.
3
+ import { HIDDEN, append, start, withSizes } from '../../hub/rooms/index.js';
4
+ import * as Signals from '../../hub/signals/write.js';
5
+ import { fail } from '../../../lib/index.js';
6
+ import { ID_RE, checkOutgoing, compose, link, lookup, unread } from '../../hub/protocol/index.js';
7
+ import { linked, loadRoomUnlocked, loadState, readerLock, saveState } from '../../hub/history/index.js';
8
+ import { isRef } from '../../hub/usecases/room.js';
9
+ export { wait } from './wait.js';
10
+ export { bound } from './index.js';
11
+ export { watch } from '../turns/index.js';
11
12
  // Whether the agent's room has its quorum and started its work; a room that has not is not read.
12
13
  export const started = ({ R }) => start(R);
13
14
  export const inbox = ({ R, me }, { peek = false, limit = 20 } = {}) => {
@@ -50,37 +51,4 @@ export const ping = ({ R, me }, { to, text = 'ping: still working', next = 600,
50
51
  checkOutgoing(message, isRef(R));
51
52
  return { id: append(R, me, message), to, previous: mine ? { id: mine.id, answeredAt: pong?.time ?? null } : null };
52
53
  };
53
- export const wait = async (a, { max = 120, ...options } = {}) => {
54
- if (!Number.isFinite(max) || max < 0)
55
- fail('wait max must be nonnegative seconds');
56
- const start = Date.now(), ponged = new Set();
57
- let last = start, silence = Math.min(max, 110);
58
- for (;;) {
59
- // Each poll renews the lease and checks stop, takeover, membership and the room's identity.
60
- const current = bound();
61
- if (current.R.genesis !== a.R.genesis || current.me !== a.me)
62
- fail('the waiting session changed its binding');
63
- const { R, me } = current;
64
- const { logs, st } = loadRoom(R, me);
65
- if (unread(logs, me, st.seen ?? {}, Infinity, HIDDEN).msgs.length)
66
- return { inbox: inbox(current, options), seconds: (Date.now() - start) / 1000 };
67
- link(logs);
68
- for (const m of logs.get(me) ?? [])
69
- if (m.kind === 'pong' && m.reId)
70
- ponged.add(m.reId);
71
- for (const msgs of logs.values())
72
- for (const m of msgs) {
73
- if (m.kind !== 'ping' || m.bad || !m.to.includes(me) || ponged.has(m.id))
74
- continue;
75
- ponged.add(m.id);
76
- last = Date.now();
77
- silence = Math.max(silence, Number(m.trailers.next?.[0]) || 600);
78
- append(R, me, pongText(me, m, 'is waiting'));
79
- }
80
- const now = Date.now();
81
- if (now - last >= silence * 1000 || now - start >= max * 1000)
82
- return { inbox: null, seconds: (now - start) / 1000 };
83
- await sleep(Math.min(1000, max * 1000 - (now - start)));
84
- }
85
- };
86
54
  //# sourceMappingURL=agent.js.map
@@ -0,0 +1,43 @@
1
+ // binding: the seat a chat holds, checked on every agent command: joined, not stopped, its room alive and the same
2
+ // room, still a member; a chat whose room is gone leaves it on its own.
3
+ import { locked } from '../../hub/ports/index.js';
4
+ import { openHub, openRoom, roomNames } from '../../hub/rooms/index.js';
5
+ import { fail, stamp } from '../../../lib/index.js';
6
+ import { dropSession, readSession, saveSession, whoAmI } from './index.js';
7
+ // The binding, checked on every agent command: joined, not stopped, room alive and the same room, still a member.
8
+ export const bound = () => {
9
+ const me = whoAmI();
10
+ const s = readSession(me.handle) ?? fail(`this session is not in a room. Take part only when the operator says so in this chat:
11
+ "join <room> as <id>" runs ringi join local <room> --as <id> --scope "<what they delegate>";
12
+ after a restart, "continue" runs ringi continue.`);
13
+ if (s.state === 'stopped')
14
+ fail('this session is stopped: the operator paused it. It reacts to nothing until the operator says "continue" (ringi continue)');
15
+ const H = openHub(s.hub);
16
+ const R = openRoom(H, s.room, { quiet: true });
17
+ checkRoomIdentity(me, s, H, R);
18
+ if (!R.members[s.agent])
19
+ fail(`${s.agent} was removed from room ${s.room}; returning needs a fresh join by the operator`);
20
+ renewSession(me, s);
21
+ return { s, H, R: R, me: s.agent };
22
+ };
23
+ const checkRoomIdentity = (me, s, H, R) => {
24
+ if (!R || R.genesis !== s.genesis) {
25
+ // The room's branch is gone (deleted, archived, or deleted and made anew): the session leaves it on its own. A hub
26
+ // that cannot be reached fails above and leaves nothing.
27
+ locked('sessions', () => { if (readSession(me.handle)?.genesis === s.genesis)
28
+ dropSession(me.handle); });
29
+ const gone = roomNames(H, true).find(a => a === `${s.room}@${s.genesis.slice(0, 8)}`);
30
+ fail(gone ? `room ${s.room} was archived as ${gone}; this session left it`
31
+ : R ? `room ${s.room} was deleted and created again; this session left the old room. The operator joins it anew`
32
+ : `room ${s.room} is gone from hub ${s.hub}; this session left it`);
33
+ }
34
+ };
35
+ const renewSession = (me, s) => {
36
+ locked('sessions', () => {
37
+ const cur = readSession(me.handle) ?? fail('this session lost its seat');
38
+ if (cur.state !== 'active' || cur.genesis !== s.genesis || cur.agent !== s.agent)
39
+ fail('this session was stopped or its seat changed');
40
+ saveSession({ ...cur, lastSeen: stamp(), pid: me.pid ?? cur.pid });
41
+ });
42
+ };
43
+ //# sourceMappingURL=binding.js.map
@@ -0,0 +1,11 @@
1
+ // context: who acts as an agent — the agent this session is bound to — and what the agent tools this machine
2
+ // knows need from an interface: where they read skills, and what lets their sandboxes write.
3
+ import { agentPorts } from '../ports/index.js';
4
+ import { bound } from './index.js';
5
+ // The agent this session is bound to; refuses when it is not joined, is stopped, or its room is gone.
6
+ export const agent = () => bound();
7
+ // Where the agent tools this machine knows read skills, under a base directory (the user's home or a project).
8
+ export const skillDirs = (base) => agentPorts().tools.flatMap(t => t.skillDirs?.(base) ?? []);
9
+ // What lets each tool's sandbox write a path.
10
+ export const sandboxHints = (where) => agentPorts().tools.flatMap(t => t.sandboxHint ? [t.sandboxHint(where)] : []);
11
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1,59 @@
1
+ // sessions: the chats on this machine that hold a seat in a room: who this chat is (its handle, from the agent tool
2
+ // it runs in), the session records, and whether each is active, stopped or gone.
3
+ import crypto from 'node:crypto';
4
+ import { hubPorts } from '../../hub/ports/index.js';
5
+ import { agentPorts } from '../ports/index.js';
6
+ import { fail } from '../../../lib/index.js';
7
+ export { bound } from './binding.js';
8
+ const LEASE = 60 * 60 * 1000;
9
+ // The tool this process runs in, by its environment (core/agents/ports/tools.ts).
10
+ const detectProduct = () => agentPorts().tools.find(t => t.detect(process.env))?.id ?? null;
11
+ // The tool's process among this process's ancestors, by its name.
12
+ const ancestry = () => {
13
+ for (const { pid, name } of agentPorts().host.ancestors(process.ppid)) {
14
+ const tool = agentPorts().tools.find(t => t.processes?.includes(name));
15
+ if (tool)
16
+ return { pid, product: tool.id };
17
+ }
18
+ return null;
19
+ };
20
+ // A chat is known by a stable handle: RINGI_SESSION, else the session id its tool exposes, else the tool's process as
21
+ // a last resort (ps may be denied in a sandbox; then RINGI_SESSION is required).
22
+ export const whoAmI = () => {
23
+ const env = process.env;
24
+ const product = detectProduct();
25
+ if (env.RINGI_SESSION)
26
+ return { handle: `env:${env.RINGI_SESSION}`, product, pid: null };
27
+ for (const t of agentPorts().tools) {
28
+ const s = t.session?.(env);
29
+ if (s)
30
+ return { ...s, product: t.id };
31
+ }
32
+ const a = ancestry() ?? fail('cannot tell which session this is: set RINGI_SESSION to a stable id of this chat (for Codex: its thread id) on every ringi command');
33
+ return { handle: `pid:${a.pid}`, product: product ?? a.product, pid: a.pid };
34
+ };
35
+ // Each session is a record of the machine's state under `sessions`, named after its handle.
36
+ const sessionKey = (handle) => ['sessions', `${handle.replace(/[^A-Za-z0-9._-]/g, '_').slice(0, 100)}-${crypto.createHash('sha256').update(handle).digest('hex').slice(0, 10)}`];
37
+ export const allSessions = () => hubPorts().state.list(['sessions']).map(n => hubPorts().state.read(['sessions', n], null)).filter((s) => !!s?.handle);
38
+ export const readSession = (handle) => {
39
+ const s = hubPorts().state.read(sessionKey(handle), null);
40
+ return s?.handle === handle ? s : null;
41
+ };
42
+ export const saveSession = (s) => hubPorts().state.write(sessionKey(s.handle), s);
43
+ export const dropSession = (handle) => hubPorts().state.remove(sessionKey(handle));
44
+ export const pidAlive = (pid) => agentPorts().host.alive(pid);
45
+ // active: in use within the lease by a living process; stopped: paused by the operator; gone: neither. A gone or
46
+ // stopped binding keeps its seat and scope. A watcher is alive exactly while its process is: a run may outlast any
47
+ // lease.
48
+ export const liveness = (s) => s.state === 'stopped' ? 'stopped'
49
+ : s.product === 'watch' ? (s.pid && pidAlive(s.pid) ? 'active' : 'gone')
50
+ : Date.now() - Date.parse(s.lastSeen) < LEASE && (!s.pid || pidAlive(s.pid)) ? 'active' : 'gone';
51
+ export const seatHolder = (hub, genesis, agent, except) => allSessions().find(s => s.hub === hub && s.genesis === genesis && s.agent === agent && s.handle !== except);
52
+ // An explicit chat-to-watch handoff remembers only that chat; it never selects another chat's seat.
53
+ export const ownSession = (handle) => readSession(handle)
54
+ ?? allSessions().find(s => s.product === 'watch' && s.takenFrom === handle) ?? null;
55
+ export const parseSelector = (sel) => {
56
+ const m = /^(?:([a-z0-9._-]+):)?([^/]+)\/([^/]+)$/.exec(sel ?? '');
57
+ return m ? { hub: m[1] ?? null, room: m[2], agent: m[3] } : fail('a session is named <room>/<agent> or <hub>:<room>/<agent>');
58
+ };
59
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,55 @@
1
+ // join: a chat takes a seat in a room as an agent, one room per chat; on a signed hub its key must be admitted first.
2
+ import { locked } from '../../hub/ports/index.js';
3
+ import { OPERATOR, controlChange, openHub, room as roomOf } from '../../hub/rooms/index.js';
4
+ import { fail, note, stamp } from '../../../lib/index.js';
5
+ import { AGENT_RE } from '../../hub/protocol/index.js';
6
+ import { dropSession, liveness, ownSession, pidAlive, readSession, saveSession, seatHolder, whoAmI } from './index.js';
7
+ export const join = ({ hub, room, agent: id, scope }) => {
8
+ const me = whoAmI();
9
+ const agent = id ?? me.product ?? fail('--as <id> is required: this session\'s product is unknown');
10
+ if (!AGENT_RE.test(agent) || agent === OPERATOR)
11
+ fail(`bad agent id ${agent}: lowercase letters, digits, - and _, no dot`);
12
+ const H = openHub(hub), R = roomOf(H, room);
13
+ if (R.archived)
14
+ fail(`${room} is archived`);
15
+ if (H.signed) {
16
+ if (!H.store.joinKey)
17
+ fail(`hub ${H.name}: its store cannot make keys`);
18
+ const key = H.store.joinKey(R.s, agent);
19
+ if (!key.admitted)
20
+ return { agent, hub: H.name, room: R.name, session: null, key };
21
+ }
22
+ locked('sessions', () => claimSession({ me, H, R, agent, room, scope }));
23
+ return { agent, hub: H.name, room: R.name, session: readSession(me.handle), key: null };
24
+ };
25
+ const claimSession = (c) => {
26
+ const { me, H, R, agent, scope } = c;
27
+ const mine = previousSession(c);
28
+ const same = !!mine && mine.hub === H.name && mine.genesis === R.genesis && mine.agent === agent;
29
+ ensureMember(c);
30
+ if (mine && !same)
31
+ note(`left ${mine.hub}/${mine.room} as ${mine.agent}: one room per session`);
32
+ saveSession({
33
+ handle: me.handle, product: me.product, hub: H.name, room: R.name, genesis: R.genesis, agent,
34
+ scope: scope ?? (same ? mine.scope : null), state: 'active', since: same ? mine.since : stamp(), lastSeen: stamp(), pid: me.pid
35
+ });
36
+ };
37
+ const previousSession = ({ me, H, R, agent, room }) => {
38
+ const holder = seatHolder(H.name, R.genesis, agent, me.handle);
39
+ if (holder)
40
+ fail(`${room}/${agent} is held by another session (${holder.handle}, ${liveness(holder)}). A seat ends only with leave, or the operator's takeover: "continue ${room}/${agent}" in this chat`);
41
+ const mine = ownSession(me.handle);
42
+ if (mine?.product === 'watch' && mine.pid && pidAlive(mine.pid))
43
+ fail('this chat handed its seat to a live watcher; stop or leave it before joining another room');
44
+ if (mine && mine.handle !== me.handle)
45
+ dropSession(mine.handle);
46
+ return mine;
47
+ };
48
+ const ensureMember = ({ H, R, agent, room }) => {
49
+ if (!R.members[agent]) {
50
+ if (H.signed)
51
+ fail(`${agent} is not in the roster of ${room}; the root admits its key first`);
52
+ controlChange(R, OPERATOR, `join ${agent}`, m => { m[agent] = { role: 'member', since: stamp() }; });
53
+ }
54
+ };
55
+ //# sourceMappingURL=join.js.map
@@ -0,0 +1,54 @@
1
+ // resume: a chat continues its own seat after a restart, or takes over one the operator names.
2
+ import { hubPorts, locked } from '../../hub/ports/index.js';
3
+ import { fail, note, stamp } from '../../../lib/index.js';
4
+ import { allSessions, dropSession, liveness, ownSession, parseSelector, pidAlive, saveSession, whoAmI } from './index.js';
5
+ export const resume = (selector) => {
6
+ const me = whoAmI();
7
+ hubPorts().state.ensure();
8
+ return locked('sessions', () => {
9
+ const target = selectTarget(me, selector);
10
+ takeOver(me, target);
11
+ const session = resumed(me, target);
12
+ saveSession(session);
13
+ return session;
14
+ });
15
+ };
16
+ const selectTarget = (me, selector) => {
17
+ if (!selector) {
18
+ return ownTarget(me);
19
+ }
20
+ else {
21
+ const sel = parseSelector(selector);
22
+ const hits = allSessions().filter(s => s.room === sel.room && s.agent === sel.agent && (!sel.hub || s.hub === sel.hub));
23
+ if (hits.length > 1)
24
+ fail(`several hubs have ${sel.room}/${sel.agent}; name one: <hub>:${sel.room}/${sel.agent}`);
25
+ return hits[0] ?? fail(`no session holds ${selector}; the operator joins this chat with ringi join`);
26
+ }
27
+ };
28
+ const ownTarget = (me) => {
29
+ const mine = ownSession(me.handle);
30
+ if (!mine) {
31
+ const cands = allSessions().filter(s => liveness(s) !== 'active').sort((a, b) => Number(b.product === me.product) - Number(a.product === me.product));
32
+ if (!cands.length)
33
+ fail('nothing to continue: this chat was never joined, and no paused or gone session waits. The operator says "join <room> as <id>"');
34
+ fail(`this chat has no binding of its own. Say which one to take over:\n${cands.map(s => ` ringi continue ${s.hub}:${s.room}/${s.agent} (${liveness(s)}, ${s.product ?? '?'}, ${s.handle}${s.scope ? `, scope: ${s.scope}` : ''})`).join('\n')}`);
35
+ }
36
+ return mine;
37
+ };
38
+ const takeOver = (me, target) => {
39
+ if (target.handle !== me.handle) {
40
+ if (liveness(target) === 'active' || (target.product === 'watch' && target.pid && pidAlive(target.pid)))
41
+ fail(`${target.room}/${target.agent} is held by a live session (${target.handle}); it is not taken over`);
42
+ dropSession(target.handle);
43
+ note(`took over ${target.hub}/${target.room}/${target.agent} from ${target.handle}`);
44
+ }
45
+ };
46
+ const resumed = (me, target) => {
47
+ const session = {
48
+ ...target, handle: me.handle, product: target.handle === me.handle ? target.product : me.product, state: 'active',
49
+ since: target.handle === me.handle ? target.since : stamp(), lastSeen: stamp(), pid: me.pid ?? (target.handle === me.handle ? target.pid : null),
50
+ takenFrom: target.handle === me.handle ? target.takenFrom : undefined
51
+ };
52
+ return session;
53
+ };
54
+ //# sourceMappingURL=resume.js.map
@@ -0,0 +1,28 @@
1
+ // session: what the operator says in an agent's chat: join, continue (with a briefing of the room), stop, leave.
2
+ import { locked } from '../../hub/ports/index.js';
3
+ import { start } from '../../hub/rooms/index.js';
4
+ import { fail, stamp } from '../../../lib/index.js';
5
+ import { bound, dropSession, ownSession, saveSession, whoAmI } from './index.js';
6
+ import { inbox } from './agent.js';
7
+ import { tasks } from '../../hub/usecases/room.js';
8
+ export { resume } from './resume.js';
9
+ export { join } from './join.js';
10
+ export { bound } from './index.js';
11
+ // A room still waiting for its agents is not read: nothing is marked seen before its work starts.
12
+ export const briefing = (s) => {
13
+ const actor = bound();
14
+ const st = start(actor.R);
15
+ return { session: s, actor, start: st, tasks: st.started ? tasks(actor).views : [], inbox: st.started ? inbox(actor) : null };
16
+ };
17
+ export const stop = () => locked('sessions', () => {
18
+ const s = ownSession(whoAmI().handle) ?? fail('this session is in no room');
19
+ const stopped = { ...s, state: 'stopped', lastSeen: stamp() };
20
+ saveSession(stopped);
21
+ return stopped;
22
+ });
23
+ export const leave = () => locked('sessions', () => {
24
+ const s = ownSession(whoAmI().handle) ?? fail('this session is in no room');
25
+ dropSession(s.handle);
26
+ return s;
27
+ });
28
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1,47 @@
1
+ // wait: an agent holds the line until something new arrives for it or the room falls silent, answering pings.
2
+ import { HIDDEN, append, pongText } from '../../hub/rooms/index.js';
3
+ import { fail, sleep } from '../../../lib/index.js';
4
+ import { link, unread } from '../../hub/protocol/index.js';
5
+ import { loadRoom } from '../../hub/history/index.js';
6
+ import { bound } from './index.js';
7
+ import { inbox } from './agent.js';
8
+ export const wait = async (a, { max = 120, ...options } = {}) => {
9
+ if (!Number.isFinite(max) || max < 0)
10
+ fail('wait max must be nonnegative seconds');
11
+ const start = Date.now(), ponged = new Set();
12
+ let last = start, silence = Math.min(max, 110);
13
+ for (;;) {
14
+ // Each poll renews the lease and checks stop, takeover, membership and the room's identity.
15
+ const current = bound();
16
+ if (current.R.genesis !== a.R.genesis || current.me !== a.me)
17
+ fail('the waiting session changed its binding');
18
+ const { R, me } = current;
19
+ const { logs, st } = loadRoom(R, me);
20
+ if (unread(logs, me, st.seen ?? {}, Infinity, HIDDEN).msgs.length)
21
+ return { inbox: inbox(current, options), seconds: (Date.now() - start) / 1000 };
22
+ link(logs);
23
+ const state = { last, silence, ponged };
24
+ answerPings(current, logs, state);
25
+ last = state.last;
26
+ silence = state.silence;
27
+ const now = Date.now();
28
+ if (now - last >= silence * 1000 || now - start >= max * 1000)
29
+ return { inbox: null, seconds: (now - start) / 1000 };
30
+ await sleep(Math.min(1000, max * 1000 - (now - start)));
31
+ }
32
+ };
33
+ const answerPings = (a, logs, state) => {
34
+ for (const m of logs.get(a.me) ?? [])
35
+ if (m.kind === 'pong' && m.reId)
36
+ state.ponged.add(m.reId);
37
+ for (const msgs of logs.values())
38
+ for (const m of msgs) {
39
+ if (m.kind !== 'ping' || m.bad || !m.to.includes(a.me) || state.ponged.has(m.id))
40
+ continue;
41
+ state.ponged.add(m.id);
42
+ state.last = Date.now();
43
+ state.silence = Math.max(state.silence, Number(m.trailers.next?.[0]) || 600);
44
+ append(a.R, a.me, pongText(a.me, m, 'is waiting'));
45
+ }
46
+ };
47
+ //# sourceMappingURL=wait.js.map
@@ -0,0 +1,48 @@
1
+ // budgets: which groups of messages may start a turn now: within a grant's budget, or within the watcher's own run
2
+ // limit when no grant covers them.
3
+ import { note, short } from '../../../lib/index.js';
4
+ import { reportExhausted } from './exhaustion.js';
5
+ import { reserveGrant } from './grants.js';
6
+ const ownRun = (c, grp, p, now) => {
7
+ if (c.w.requireGrant) {
8
+ for (const m of grp.msgs)
9
+ note(`watch: ${short(m.id)} is outside any grant; --require-grant: not starting a turn`);
10
+ return;
11
+ }
12
+ if (p.ownRuns.length >= c.maxRuns) {
13
+ p.hold = true;
14
+ note(`watch: own run budget spent (${c.maxRuns} per ${c.span}s); ${grp.msgs.length} message(s) wait`);
15
+ return;
16
+ }
17
+ p.ownRuns = [...p.ownRuns, now];
18
+ p.runs.push({ ...grp, timeout: null });
19
+ };
20
+ const grantedRun = ({ c, R, all, grp, r, p }) => {
21
+ if (r.wait) {
22
+ p.hold = true;
23
+ note(`watch: ${r.why}; waiting`);
24
+ return;
25
+ }
26
+ if (r.why) {
27
+ note(`watch: ${r.why}`);
28
+ reportExhausted({ c, R, all, grp, r, p });
29
+ return;
30
+ }
31
+ p.runs.push({ ...grp, run: r.run, timeout: r.gr.budget['run-seconds'] });
32
+ };
33
+ export const reserveGroups = (c, R, all, groups, st) => {
34
+ const now = Date.now() / 1000;
35
+ const p = { runs: [], hold: false, lost: false, ownRuns: (st.runs ?? []).filter(t => t > now - c.span), exhausted: { ...st.exhausted } };
36
+ for (const grp of groups.values()) {
37
+ if (!grp.grant) {
38
+ ownRun(c, grp, p, now);
39
+ continue;
40
+ }
41
+ const r = reserveGrant(c, R, all, grp);
42
+ if (r.lost)
43
+ return { ...p, runs: [], hold: true, lost: true };
44
+ grantedRun({ c, R, all, grp, r, p });
45
+ }
46
+ return p;
47
+ };
48
+ //# sourceMappingURL=budgets.js.map
@@ -0,0 +1,40 @@
1
+ // dispatch: a planned turn is started through the process host, still holding the seat and a valid grant.
2
+ import * as D from '../../hub/decisions/index.js';
3
+ import { hubPorts, locked } from '../../hub/ports/index.js';
4
+ import { fail, note, short } from '../../../lib/index.js';
5
+ import { link } from '../../hub/protocol/index.js';
6
+ import { loadRoomUnlocked, loadState, readerLock, saveState } from '../../hub/history/index.js';
7
+ import { readSession } from '../sessions/index.js';
8
+ import { agentPorts } from '../ports/index.js';
9
+ const grantProblem = (c, R, run) => {
10
+ if (!run.grant)
11
+ return undefined;
12
+ const { logs } = readerLock(R, c.me, () => loadRoomUnlocked(R, c.me));
13
+ const gr = D.grantOf(link(logs), R.authorityAt, run.grant);
14
+ return !gr ? 'its grant is no longer valid' : gr.revoked ? 'its grant was revoked' : undefined;
15
+ };
16
+ const spawnTurn = (c, run) => locked('sessions', () => {
17
+ const cur = readSession(c.handle);
18
+ if (!cur || cur.pid !== process.pid)
19
+ return { why: 'the seat was taken over' };
20
+ if (cur.state !== 'active')
21
+ return { why: 'the watcher was stopped' };
22
+ note(`watch: ${run.msgs.length} new${run.grant ? ` under grant ${short(run.grant)}` : ''}: ${c.cmd}`);
23
+ return {
24
+ done: agentPorts().host.awaitQuiescence(agentPorts().host.start({ shell: c.cmd, timeout: run.timeout, env: {
25
+ ...process.env, RINGI_HOME: hubPorts().state.root, RINGI_SESSION: c.raw,
26
+ RINGI_MSGS: run.msgs.map(m => m.id).join('\n'), RINGI_GRANT: run.grant ?? ''
27
+ } })).then(result => result ?? fail('the process host did not settle the turn'))
28
+ };
29
+ });
30
+ export const dispatch = (c, R, run) => locked(`grant-${R.hub.name}`, () => {
31
+ const why = grantProblem(c, R, run);
32
+ if (why)
33
+ return { why };
34
+ readerLock(R, c.me, () => {
35
+ const st = loadState(R, c.me);
36
+ saveState(R, c.me, { ...st, inflight: { seen: st.seen ?? {} } });
37
+ });
38
+ return spawnTurn(c, run);
39
+ });
40
+ //# sourceMappingURL=dispatch.js.map
@@ -0,0 +1,16 @@
1
+ // exhaustion: a piece of work whose grant is spent or revoked waits for a new grant, said once in its thread.
2
+ import { isOpen, taskOf } from '../../hub/work/index.js';
3
+ import { OPERATOR, append } from '../../hub/rooms/index.js';
4
+ import { compose } from '../../hub/protocol/index.js';
5
+ export const reportExhausted = ({ c, R, all, grp, r, p }) => {
6
+ const key = `${grp.task?.id}/${grp.grant}`;
7
+ if (!r.exhausted || !grp.task || p.exhausted[key])
8
+ return;
9
+ p.exhausted[key] = true;
10
+ const t = taskOf(all, grp.task, R.profile), last = grp.msgs.at(-1);
11
+ if (isOpen(t, R.profile))
12
+ append(R, c.me, compose(`${r.why}; waiting for a new grant`, [
13
+ ['To', [...new Set([t.requester, OPERATOR])].join(', ')], ['Re', last.id], ['State', R.profile.waiting], ['Hop', String(last.hopEff + 1)]
14
+ ]));
15
+ };
16
+ //# sourceMappingURL=exhaustion.js.map
@@ -0,0 +1,36 @@
1
+ // grants: a run reserved under a grant: approved, not revoked, not spent, within its concurrency.
2
+ import * as D from '../../hub/decisions/index.js';
3
+ import { OPERATOR, append } from '../../hub/rooms/index.js';
4
+ import { short } from '../../../lib/index.js';
5
+ import { compose } from '../../hub/protocol/index.js';
6
+ import { readSession } from '../sessions/index.js';
7
+ const grantStatus = (gr) => {
8
+ if (gr.revoked)
9
+ return { why: `grant ${short(gr.id)} was revoked`, exhausted: true, gr };
10
+ return { gr };
11
+ };
12
+ const remaining = (all, gr) => {
13
+ const u = D.usageOf(all, gr);
14
+ if (u.left <= 0)
15
+ return { why: `grant ${short(gr.id)} is spent: ${u.runs}/${gr.budget.runs} runs`, exhausted: true, gr };
16
+ if (u.open >= gr.budget.concurrency)
17
+ return { why: `grant ${short(gr.id)} has ${u.open} run(s) open, concurrency ${gr.budget.concurrency}`, wait: true };
18
+ return { gr };
19
+ };
20
+ export const reserveGrant = (c, R, all, grp) => {
21
+ if (readSession(c.handle)?.pid !== process.pid)
22
+ return { why: 'this watcher no longer holds the seat', lost: true };
23
+ const gr = D.grantOf(all, R.authorityAt, grp.grant);
24
+ if (!gr)
25
+ return { why: `grant ${short(grp.grant)} is not an approved decision with a budget` };
26
+ const status = grantStatus(gr);
27
+ if (status.why)
28
+ return status;
29
+ const balance = remaining(all, gr);
30
+ if (balance.why)
31
+ return balance;
32
+ const run = `${c.raw}.${process.pid}.${Date.now().toString(36)}.${c.runSeq++}`;
33
+ append(R, c.me, compose(`usage: reserve a run of ${c.me}`, [['To', OPERATOR], ['Kind', 'usage'], ['Grant', gr.id], ['Usage', 'reserve'], ['Run', run]]));
34
+ return { gr, run };
35
+ };
36
+ //# sourceMappingURL=grants.js.map
@@ -0,0 +1,33 @@
1
+ // turns: the headless watcher: it holds one agent's seat, wakes a command for what arrives, and charges only its own
2
+ // reservations and receipts.
3
+ import { note, sleep } from '../../../lib/index.js';
4
+ import { planTurns } from './plan.js';
5
+ import { pollWatcher } from './poll.js';
6
+ import { runTurns } from './results.js';
7
+ import { createWatcher } from './seat.js';
8
+ export const watch = async (w, log = note) => {
9
+ const c = createWatcher(w, log);
10
+ for (;;) {
11
+ const done = await watchTick(c);
12
+ if (done !== undefined)
13
+ return done;
14
+ await sleep(c.interval);
15
+ }
16
+ };
17
+ const watchTick = async (c) => {
18
+ const poll = pollWatcher(c);
19
+ if (poll.done)
20
+ return 0;
21
+ if (poll.R) {
22
+ const plan = planTurns(c, poll.R);
23
+ if (plan.lost) {
24
+ c.log(`watch: the seat of ${c.me} was taken over; stopping`);
25
+ return 0;
26
+ }
27
+ const exitCode = await runTurns(c, poll.R, plan.runs);
28
+ if (c.w.once)
29
+ return exitCode || (plan.hold ? 4 : 0);
30
+ }
31
+ return undefined;
32
+ };
33
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,11 @@
1
+ // limits: the watcher's options checked before it starts.
2
+ import { fail } from '../../../lib/index.js';
3
+ export const validateWatch = (w) => {
4
+ for (const [name, value] of [['interval', w.interval], ['window', w.window]])
5
+ if (value !== undefined && (!Number.isFinite(value) || value <= 0))
6
+ fail(`watch ${name} must be positive seconds`);
7
+ for (const [name, value] of [['max-runs', w.maxRuns], ['max-hop', w.maxHop]])
8
+ if (value !== undefined && (!Number.isSafeInteger(value) || value < 0))
9
+ fail(`watch ${name} must be a nonnegative integer`);
10
+ };
11
+ //# sourceMappingURL=limits.js.map
@@ -0,0 +1,32 @@
1
+ // messages: what wakes the watcher: new messages for its agent and retries of failed turns, grouped by grant and work.
2
+ import { isOpen, taskFor, taskOf } from '../../hub/work/index.js';
3
+ import { HIDDEN } from '../../hub/rooms/index.js';
4
+ import { note, short } from '../../../lib/index.js';
5
+ import { unread, wakes } from '../../hub/protocol/index.js';
6
+ export const collectMessages = (c, R, logs, st, all) => {
7
+ const { msgs: fresh, cursors } = unread(logs, c.me, st.watched ?? st.seen ?? {}, Infinity, HIDDEN);
8
+ const retry = (st.pending ?? []).flatMap(id => {
9
+ const m = all.get(id);
10
+ if (!m)
11
+ return [];
12
+ const task = taskFor(all, m, R.profile);
13
+ return !task || isOpen(taskOf(all, task, R.profile), R.profile) ? [m] : [];
14
+ });
15
+ const msgs = [...new Map([...retry, ...fresh].map(m => [m.id, m])).values()];
16
+ const go = msgs.filter(m => wakes(m, c.me, HIDDEN) && m.hopEff < c.maxHop && (!c.allow || c.allow.has(m.from)));
17
+ for (const m of msgs)
18
+ if (!go.includes(m))
19
+ note(`watch: not waking for ${short(m.id)} from ${m.from} (to ${m.to.join(',')}, hop ${m.hopEff})`);
20
+ return { retry, cursors, go };
21
+ };
22
+ export const groupMessages = (R, all, go) => {
23
+ const groups = new Map();
24
+ for (const m of go) {
25
+ const task = taskFor(all, m, R.profile), g = task ? taskOf(all, task, R.profile).grant : null;
26
+ if (!groups.has(g))
27
+ groups.set(g, { grant: g, msgs: [], task });
28
+ groups.get(g).msgs.push(m);
29
+ }
30
+ return groups;
31
+ };
32
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1,30 @@
1
+ // pings: the watcher answers pings for its agent without waking a model.
2
+ import { append, pongText } from '../../hub/rooms/index.js';
3
+ import { note, short } from '../../../lib/index.js';
4
+ const allowed = (c, m, answered) => {
5
+ const ping = !m.bad && m.kind === 'ping' && m.to.includes(c.me);
6
+ const wake = m.hopEff < c.maxHop && (!c.allow || c.allow.has(m.from));
7
+ return ping && !answered.has(m.id) && wake;
8
+ };
9
+ const answerAuthor = (c, R, msgs, last, answered) => {
10
+ const at = msgs.findIndex(m => m.id === last);
11
+ for (const m of msgs.slice(at + 1)) {
12
+ if (!allowed(c, m, answered))
13
+ continue;
14
+ append(R, c.me, pongText(c.me, m, 'has a watcher'));
15
+ note(`watch: answered heartbeat ${short(m.id)} from ${m.from}`);
16
+ }
17
+ };
18
+ export const answerWatchPings = (c, R, logs, st) => {
19
+ const heartbeatSeen = { ...st.heartbeatSeen };
20
+ const answered = new Set((logs.get(c.me) ?? []).filter(m => m.kind === 'pong').map(m => m.reId));
21
+ for (const [id, msgs] of logs) {
22
+ if (id === c.me)
23
+ continue;
24
+ answerAuthor(c, R, msgs, heartbeatSeen[id], answered);
25
+ if (msgs.length)
26
+ heartbeatSeen[id] = msgs.at(-1).id;
27
+ }
28
+ return heartbeatSeen;
29
+ };
30
+ //# sourceMappingURL=pings.js.map