@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
@@ -0,0 +1,50 @@
1
+ // budget: `propose`, `stamp`, `decide`, `proposals`, `grants`.
2
+ import * as Budget from '../../../core/hub/usecases/budget.js';
3
+ import { fail, short, words } from '../../../lib/index.js';
4
+ import { attachments, dump, flag, list, opt, out, textOf } from '../args.js';
5
+ // --- decisions and budgets ---
6
+ export const propose = (a, o) => {
7
+ const decider = opt(o, 'decider') ?? fail('--decider <id> is required: who decides (operator, or someone with authority in the hub contract)');
8
+ const r = Budget.propose(a, {
9
+ text: textOf(o), decider, reviewers: words(opt(o, 'reviewers')), budget: opt(o, 'budget'), due: opt(o, 'due'),
10
+ supersedes: opt(o, 'supersedes'), files: list(o, 'attach').flatMap(attachments)
11
+ });
12
+ out(`proposed ${short(r.id)} to ${r.to.join(', ') || 'the room'}; decider ${decider}${r.budget ? `, budget ${Budget.budgetText(r.budget)}` : ''}`);
13
+ };
14
+ export const stamp_ = (a, o) => {
15
+ const s = o._[1] ?? '';
16
+ if (!Budget.STAMPS.includes(s))
17
+ fail(`usage: stamp <proposal> ${Budget.STAMPS.join('|')} -m <reason>`);
18
+ const r = Budget.stamp(a, o._[0] ?? fail('name the proposal'), s, textOf(o));
19
+ out(`stamped ${short(r.proposal.id)} ${s}: ${short(r.id)}`);
20
+ };
21
+ export const decide = (a, o) => {
22
+ const d = o._[1] ?? '';
23
+ if (!Budget.DECISIONS.includes(d))
24
+ fail(`usage: decide <proposal> ${Budget.DECISIONS.join('|')} -m <reason>`);
25
+ const r = Budget.decide(a, o._[0] ?? fail('name the proposal'), d, textOf(o));
26
+ out(`${d} ${short(r.proposal.id)}: ${short(r.id)}${r.budget ? `; grant ${short(r.id)} with ${Budget.budgetText(r.budget)}. Work spends it with --grant ${short(r.id)}` : ''}`);
27
+ };
28
+ export const proposals = (a, o) => {
29
+ const { proposals: ps, views } = Budget.proposals(a, { all: flag(o, 'all') });
30
+ if (flag(o, 'json'))
31
+ return dump(views);
32
+ if (!ps.length)
33
+ return out(flag(o, 'all') ? 'no proposals' : 'no open proposals (proposals --all for everything)');
34
+ for (const x of ps) {
35
+ const st = x.reviewers.map(r => `${r}:${x.stamps[r]?.stamp ?? '-'}`).join(' ');
36
+ out(`${short(x.proposal.id)} ${x.state.padEnd(10)} ${x.proposal.from} → ${x.decider}${x.budget ? ` [${Budget.budgetText(x.budget)}]` : ''}${st ? ` ${st}` : ''} ${x.proposal.subject}`);
37
+ }
38
+ };
39
+ export const grants = (a, o) => {
40
+ const gs = Budget.grants(a);
41
+ if (flag(o, 'json'))
42
+ return dump(gs);
43
+ if (!gs.length)
44
+ return out('no grants');
45
+ for (const g of gs) {
46
+ const u = g.usage;
47
+ out(`${short(g.grant)} ${g.revoked ? 'revoked ' : u.left ? 'active ' : 'spent '} runs ${u.runs}/${g.budget.runs}, open ${u.open}${u.uncertain ? `, uncertain ${u.uncertain}` : ''}, ${u.seconds}s used, ≤${g.budget['run-seconds']}s a run, concurrency ${g.budget.concurrency} ${g.subject}`);
48
+ }
49
+ };
50
+ //# sourceMappingURL=budget.js.map
@@ -0,0 +1,26 @@
1
+ // files: `cat` and `get`, a message's attached files.
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import * as Room from '../../../core/hub/usecases/room.js';
5
+ import { checkPath } from '../../../core/hub/usecases/room.js';
6
+ import { fail, short } from '../../../lib/index.js';
7
+ import { opt, out } from '../args.js';
8
+ export const cat = (a, o) => {
9
+ const ref = o._[0] ?? fail('usage: cat <msg> [<path>]');
10
+ const p = o._[1] ?? (() => {
11
+ const { m } = Room.files(a, ref);
12
+ return m.files.length === 1 ? m.files[0].path : fail(`${short(m.id)} has ${m.files.length} files; name one: ${m.files.map(f => f.path).join(', ')}`);
13
+ })();
14
+ process.stdout.write(Room.files(a, ref, p).files[0].content);
15
+ };
16
+ export const get = (a, o) => {
17
+ const { m, files } = Room.files(a, o._[0] ?? fail('usage: get <msg> [-o <dir>]'));
18
+ const dir = path.resolve(opt(o, 'out') ?? short(m.id));
19
+ for (const f of files) {
20
+ const dest = path.join(dir, checkPath(f.path));
21
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
22
+ fs.writeFileSync(dest, f.content);
23
+ out(dest);
24
+ }
25
+ };
26
+ //# sourceMappingURL=files.js.map
@@ -0,0 +1,10 @@
1
+ // shared: the commands both run: `ringi send` acts as the operator, `ringi agent send` as the agent its session is
2
+ // bound to; messages, files, work, signals, proposals and grants.
3
+ export { decide, grants, proposals, propose, stamp_ } from './budget.js';
4
+ export { cat, get } from './files.js';
5
+ export { add, read, reply, send, thread } from './messages.js';
6
+ export { profileCmd, who } from './profile.js';
7
+ export { scopeLine, waiting } from './session.js';
8
+ export { signals } from './signals.js';
9
+ export { log, taskLine, tasks } from './work.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,41 @@
1
+ // messages: `add` (staging), `send`, `reply`, `read`, `thread`.
2
+ import * as Room from '../../../core/hub/usecases/room.js';
3
+ import { withSizes } from '../../../core/hub/usecases/room.js';
4
+ import { asJson, render } from '../../../core/hub/usecases/view.js';
5
+ import { bytes, fail, short, words } from '../../../lib/index.js';
6
+ import { attachments, dump, flag, list, opt, out, textOf } from '../args.js';
7
+ const sendInput = (o) => ({
8
+ text: textOf(o), to: words(opt(o, 'to')), all: flag(o, 'all'), task: flag(o, 'task'),
9
+ state: opt(o, 'state'), assign: opt(o, 'assign') ? words(opt(o, 'assign')) : undefined, roles: opt(o, 'roles'), grant: opt(o, 'grant'),
10
+ files: list(o, 'attach').flatMap(attachments)
11
+ });
12
+ const sent = (r) => out(`sent ${short(r.id)} to ${r.to.join(', ')}${r.files ? ` with ${r.files} file(s)` : ''}`);
13
+ // Stages files for the actor's next message, like git add: their content is taken into the hub now. Without files it
14
+ // lists what is staged; --drop <path> and --clear take files back out.
15
+ export const add = (a, o) => {
16
+ if (flag(o, 'clear'))
17
+ Room.unstage(a, null);
18
+ else if (list(o, 'drop').length)
19
+ Room.unstage(a, list(o, 'drop'));
20
+ const staged = o._.length ? Room.stage(a, o._.flatMap(attachments)) : Room.staged(a);
21
+ out(staged.length ? `staged for your next message:\n${staged.map(s => ` ${s.path} (${bytes(s.size)})`).join('\n')}` : 'nothing staged');
22
+ };
23
+ export const send = (a, o) => sent(Room.send(a, { ...sendInput(o), re: opt(o, 're') }));
24
+ export const reply = (a, o) => sent(Room.send(a, { ...sendInput(o), re: o._[0] ?? fail('usage: reply <msg> -m <text> …'), reply: true }));
25
+ export const read = (a, o) => {
26
+ const { all, m, replies, marks } = Room.message(a, o._[0] ?? fail('usage: read <msg>'));
27
+ if (flag(o, 'json'))
28
+ return dump(asJson(m));
29
+ out(render(all, m, { files: () => withSizes(a.R, m) }));
30
+ if (replies.length)
31
+ out(`replies: ${replies.map(x => `${short(x.id)} (${x.from})`).join(', ')}`);
32
+ if (marks)
33
+ out(Object.entries(marks).map(([mark, who]) => `${mark} by: ${who.join(', ')}`).join('; '));
34
+ };
35
+ export const thread = (a, o) => {
36
+ const { all, msgs } = Room.thread(a, o._[0] ?? fail('usage: thread <msg>'));
37
+ if (flag(o, 'json'))
38
+ return dump(msgs.map(asJson));
39
+ out(msgs.map(m => render(all, m, { files: () => withSizes(a.R, m) })).join('\n\n'));
40
+ };
41
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1,17 @@
1
+ // profile: `profile` (what work is in the room) and `who` (its members and their cards).
2
+ import * as Room from '../../../core/hub/usecases/room.js';
3
+ import { dump, flag, out } from '../args.js';
4
+ export const profileCmd = ({ R }, o) => {
5
+ if (flag(o, 'json'))
6
+ return dump(R.profile);
7
+ const P = R.profile;
8
+ out(`room ${R.name} follows profile ${P.name}${P.description ? `: ${P.description}` : ''}`);
9
+ out(`opens with Kind: ${P.opens}; states: ${P.states.join(', ')}; initial ${P.initial}; terminal ${P.terminal.join(', ')}${P.waiting ? `; waiting ${P.waiting}` : ''}`);
10
+ for (const [k, v] of Object.entries(P.rules))
11
+ out(` ${k.padEnd(18)} ${(v ?? []).join(', ')}`);
12
+ };
13
+ export const who = (a) => {
14
+ for (const x of Room.members(a))
15
+ out(`${x.id.padEnd(12)} ${x.role.padEnd(7)} ${String(x.messages).padStart(4)} msg${x.card ? ` ${x.card}` : ''}`);
16
+ };
17
+ //# sourceMappingURL=profile.js.map
@@ -0,0 +1,8 @@
1
+ // session: how a session's scope and a room still waiting for its quorum are shown.
2
+ // What the session may do on its own: the recorded scope; without one, in a room with a quorum the room's work for it,
3
+ // in any other what the operator accepts when asked.
4
+ export const scopeLine = (s, quorum = false) => s.scope
5
+ ?? (quorum ? 'none recorded; the room\'s work for you, split with the other members' : 'none recorded; ask the operator what to accept');
6
+ // The line that keeps an agent of a room waiting for its quorum from doing anything yet.
7
+ export const waiting = (room, st) => `waiting: room ${room} waits for a quorum of ${st.quorum} agents and has ${st.agents}; nothing to do yet, end the turn. Its work starts by itself at the quorum`;
8
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1,21 @@
1
+ // signals: `signals`, the room's signals checked, and `--repair` for the actor's own.
2
+ import * as Room from '../../../core/hub/usecases/room.js';
3
+ import { note, short, when } from '../../../lib/index.js';
4
+ import { dump, flag, opt, out } from '../args.js';
5
+ export const signals = (a, o) => {
6
+ const res = Room.signals(a, { repair: flag(o, 'repair') });
7
+ if (res.repaired !== null)
8
+ out(`restored ${res.repaired} signal(s) of ${a.me}`);
9
+ for (const x of res.alarms)
10
+ note(`ALARM ${x}`);
11
+ if (flag(o, 'json'))
12
+ return dump(res.checked);
13
+ const at = (c) => res.all.get(c.target)?.time ?? 0;
14
+ const sorted = [...res.checked].sort((x, y) => at(x) - at(y));
15
+ const shown = flag(o, 'all') ? sorted : sorted.slice(-Number(opt(o, 'n') ?? 20));
16
+ if (!shown.length)
17
+ return out('no signals');
18
+ for (const c of shown)
19
+ out(`${short(c.target)} ${when(at(c)).slice(5)} ${c.actor.padEnd(10)} ${c.signal.padEnd(20)} ${c.ok ? res.all.get(c.target)?.subject ?? '' : `MISMATCH: ${c.why}`}`);
20
+ };
21
+ //# sourceMappingURL=signals.js.map
@@ -0,0 +1,26 @@
1
+ // work: `tasks` and `log`, and one line per piece of work.
2
+ import * as Room from '../../../core/hub/usecases/room.js';
3
+ import { asJson, oneLine } from '../../../core/hub/usecases/view.js';
4
+ import { short, when } from '../../../lib/index.js';
5
+ import { dump, flag, opt, out } from '../args.js';
6
+ export const taskLine = (t) => {
7
+ const roles = Object.keys(t.roles).length ? ` [${Object.entries(t.roles).map(([id, label]) => `${id}=${label}`).join(' ')}]` : '';
8
+ return `${short(t.id)} ${t.state.padEnd(14)} ${t.requester} → ${t.assignees.join(',') || '(open)'}${roles}${t.taken.length ? ` taken by ${t.taken.join(',')}` : ''}${t.grant ? ` grant ${short(t.grant)}` : ''} ${when(Date.parse(t.at) / 1000).slice(5)} by ${t.by} ${t.subject}`;
9
+ };
10
+ export const tasks = (a, o) => {
11
+ const { views } = Room.tasks(a, { all: flag(o, 'all') });
12
+ if (flag(o, 'json'))
13
+ return dump(views);
14
+ if (!views.length)
15
+ return out(flag(o, 'all') ? 'no work' : `no open work (profile ${a.R.profile.name}; tasks --all for everything)`);
16
+ for (const t of views)
17
+ out(taskLine(t));
18
+ };
19
+ export const log = (a, o) => {
20
+ const msgs = Room.log(a, { agent: opt(o, 'agent'), all: flag(o, 'all'), n: Number(opt(o, 'n') ?? 20) });
21
+ if (flag(o, 'json'))
22
+ return dump(msgs.map(asJson));
23
+ for (const m of msgs)
24
+ out(oneLine(m));
25
+ };
26
+ //# sourceMappingURL=work.js.map
@@ -0,0 +1,40 @@
1
+ // skill: the agents' manual for this same command line (src/main/resources/skill/), installed where each agent tool
2
+ // reads skills (targets.ts), checked and removed again.
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import { about } from '../../../core/hub/usecases/context.js';
6
+ import { sandboxHints } from '../../../core/agents/sessions/context.js';
7
+ import { fail } from '../../../lib/index.js';
8
+ import { flag, out } from '../args.js';
9
+ import { SKILL, sameSkill, skillTargets } from './targets.js';
10
+ export { SKILL, skillTargets } from './targets.js';
11
+ const install = (o) => {
12
+ for (const dir of skillTargets(flag(o, 'project'))) {
13
+ fs.mkdirSync(dir, { recursive: true });
14
+ fs.cpSync(SKILL, dir, { recursive: true });
15
+ out(`installed ${dir}`);
16
+ }
17
+ out([`ringi's home is ${about().home}. A sandboxed agent must be allowed to write it.`, ...sandboxHints(about().home).map(h => ` ${h}`),
18
+ 'Otherwise agents re-run ringi commands with sandbox escalation, which you approve.'].join('\n'));
19
+ };
20
+ const status = () => {
21
+ for (const dir of [...skillTargets(false), ...skillTargets(true)]) {
22
+ const state = sameSkill(dir) ? 'ok ' : fs.existsSync(dir) ? 'outdated' : 'missing ';
23
+ out(`${state} ${dir}`);
24
+ }
25
+ };
26
+ const uninstall = (o) => {
27
+ for (const dir of skillTargets(flag(o, 'project'))) {
28
+ if (!fs.existsSync(dir))
29
+ continue;
30
+ fs.rmSync(dir, { recursive: true });
31
+ out(`removed ${dir}`);
32
+ }
33
+ };
34
+ const show = () => { process.stdout.write(fs.readFileSync(path.join(SKILL, 'SKILL.md'), 'utf8')); };
35
+ const COMMANDS = new Map([['install', install], ['status', status], ['uninstall', uninstall], ['show', show]]);
36
+ export const skill = (o) => {
37
+ const run = COMMANDS.get(o._[0]) ?? fail('usage: ringi skill install [--project] | uninstall [--project] | status | show');
38
+ run(o);
39
+ };
40
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,20 @@
1
+ // targets: where the skill goes: each agent tool's skill directory under the user's home or the project.
2
+ import fs from 'node:fs';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { about } from '../../../core/hub/usecases/context.js';
6
+ import { skillDirs } from '../../../core/agents/sessions/context.js';
7
+ export const SKILL = path.join(about().resources, 'skill', 'ringi');
8
+ export const skillTargets = (project) => {
9
+ const base = project ? process.cwd() : os.homedir();
10
+ return skillDirs(base);
11
+ };
12
+ export const sameSkill = (dir) => {
13
+ try {
14
+ return fs.readFileSync(path.join(dir, 'SKILL.md'), 'utf8') === fs.readFileSync(path.join(SKILL, 'SKILL.md'), 'utf8');
15
+ }
16
+ catch {
17
+ return false;
18
+ }
19
+ };
20
+ //# sourceMappingURL=targets.js.map
@@ -0,0 +1,34 @@
1
+ // composition: the one place ringi is put together when a program starts: this build, the machine's state, the store
2
+ // types, the agent tools it knows, its processes and keys. Importing it wires them into the ports (core/hub/ports,
3
+ // core/agents/ports); nothing else imports an adapter.
4
+ import fs from 'node:fs';
5
+ import os from 'node:os';
6
+ import path from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
8
+ import { notesTo } from '../lib/index.js';
9
+ import { wireHub } from '../core/hub/ports/index.js';
10
+ import { wireAgents } from '../core/agents/ports/index.js';
11
+ import { stateFs } from '../adapters/state-fs/index.js';
12
+ import { claude } from '../adapters/tool-claude/index.js';
13
+ import { codex } from '../adapters/tool-codex/index.js';
14
+ import { cursor } from '../adapters/tool-cursor/index.js';
15
+ import { hostPosix } from '../adapters/host-posix/index.js';
16
+ import { keysFile } from '../adapters/keys-file/index.js';
17
+ import { gitTransport } from '../adapters/transport-git/transport.js';
18
+ import { kafka } from '../adapters/transport-kafka/index.js';
19
+ import { temporal } from '../adapters/transport-temporal/index.js';
20
+ // The package this file belongs to, run from its source (src/main/ts) or its build (target/esm).
21
+ const packageOf = (dir) => fs.existsSync(path.join(dir, 'package.json')) ? dir : packageOf(path.dirname(dir));
22
+ const PACKAGE = packageOf(path.dirname(fileURLToPath(import.meta.url)));
23
+ export const build = {
24
+ version: JSON.parse(fs.readFileSync(path.join(PACKAGE, 'package.json'), 'utf8')).version,
25
+ resources: path.join(PACKAGE, 'src', 'main', 'resources'),
26
+ };
27
+ const root = path.resolve(process.env.RINGI_HOME || path.join(os.homedir(), '.ringi'));
28
+ // The git store signs with keys kept as files under the home, made only for a signed hub.
29
+ const transports = { git: gitTransport(root, { signer: () => keysFile(root) }), kafka, temporal };
30
+ wireHub({ build, state: stateFs({ root, build }), transports, store: 'git' });
31
+ // In the order a session is recognised by.
32
+ wireAgents({ tools: [claude, codex, cursor], host: hostPosix() });
33
+ notesTo(line => { process.stderr.write(line); });
34
+ //# sourceMappingURL=index.js.map
@@ -1,18 +1,20 @@
1
1
  // heartbeat: whether an agent is alive, and working or waiting, judged from what its machine shows without asking the
2
- // model, so no tokens are spent on it. The facts: its process and process tree (platform.ts), the trace its tool
3
- // writes (tools.ts) and ringi's own session record. What to do about a silent or stuck agent is the orchestrator's.
4
- import { SUPPORTED, alive, table, treeCpu } from './platform.js';
2
+ // model, so no tokens are spent on it. The facts: its process and process tree (ProcessHost, core/agents/ports/host.ts), the trace its tool
3
+ // writes (tools.ts, from the tools this machine knows) and ringi's own session record. What to do about a silent or stuck agent is the orchestrator's.
4
+ import { agentPorts } from '../ports/index.js';
5
5
  import { toolOf, traceTime } from './tools.js';
6
6
  // The facts of one session now; `rows` lets one `ps` call serve many sessions.
7
- export const probe = (s, waits = null, rows = SUPPORTED ? table() : null) => ({
8
- at: Date.now() / 1000,
9
- alive: s.pid && SUPPORTED ? alive(s.pid) : null,
10
- cpu: s.pid && s.product === 'watch' ? treeCpu(s.pid, rows) : null,
11
- trace: traceTime(s),
12
- seen: Date.parse(s.lastSeen) / 1000,
13
- stopped: s.state === 'stopped',
14
- waits,
15
- });
7
+ export const probe = (s, waits = null, rows = agentPorts().host.snapshot()) => {
8
+ const host = agentPorts().host, facts = s.pid ? host.inspect(s.pid, rows) : null;
9
+ return {
10
+ at: host.clock.wall() / 1000,
11
+ alive: facts?.alive ?? null,
12
+ cpu: s.product === 'watch' ? facts?.cpu ?? null : null,
13
+ trace: traceTime(s),
14
+ seen: Date.parse(s.lastSeen) / 1000,
15
+ stopped: s.state === 'stopped', waits,
16
+ };
17
+ };
16
18
  export const tracedBy = (s) => toolOf(s)?.tool ?? (s.product === 'watch' ? 'watch' : 'none');
17
19
  // working: its process tree used CPU since the previous look, or its trace or a ringi command is younger than
18
20
  // `active` seconds; waiting: alive but neither, or kept waiting by the operator or its room; gone: its process is
@@ -1,14 +1,13 @@
1
1
  // heartbeat: the pulse of every session this machine holds, judged from its process and its tool's trace without the
2
- // model (heartbeat/). It reads session records only: it never binds a session, renews its lease or marks anything read.
3
- import { spawn } from 'node:child_process';
4
- import fs from 'node:fs';
5
- import path from 'node:path';
6
- import * as HB from '../heartbeat/index.js';
7
- import { alive, table } from '../heartbeat/platform.js';
8
- import { HOME, locked } from '../home/index.js';
9
- import { openHub, openRoom, start } from '../hub/index.js';
10
- import { sleep } from '../lib/index.js';
11
- import { allSessions } from '../runtime/session.js';
2
+ // model (index.ts). It reads session records only: it never binds a session, renews its lease or marks anything read.
3
+ import * as HB from './index.js';
4
+ import { agentPorts } from '../ports/index.js';
5
+ import { hubPorts } from '../../hub/ports/index.js';
6
+ import { claim, release } from './singleton.js';
7
+ export { ensurePulse } from './singleton.js';
8
+ import { openHub, openRoom, start } from '../../hub/rooms/index.js';
9
+ import { sleep } from '../../../lib/index.js';
10
+ import { allSessions } from '../sessions/index.js';
12
11
  // What the room keeps the session waiting for, if anything; a hub that cannot be read says nothing.
13
12
  const roomWaits = (s) => {
14
13
  try {
@@ -23,31 +22,14 @@ const roomWaits = (s) => {
23
22
  export const heartbeats = async ({ sample = 1 } = {}) => {
24
23
  const ss = allSessions();
25
24
  const waits = ss.map(roomWaits);
26
- const first = ss.map((s, i) => HB.probe(s, waits[i], table()));
25
+ const first = ss.map((s, i) => HB.probe(s, waits[i], agentPorts().host.snapshot()));
27
26
  if (ss.some(s => s.product === 'watch'))
28
27
  await sleep(sample * 1000);
29
- const rows = table();
28
+ const rows = agentPorts().host.snapshot();
30
29
  return ss.map((s, i) => ({ session: s, tool: HB.tracedBy(s), beat: HB.judge(HB.probe(s, waits[i], rows), first[i]) }));
31
30
  };
32
- // --- pulse: the process that beats for every session here, with no model in it ---
33
- const PIDFILE = () => path.join(HOME, 'pulse.pid');
34
- const running = () => {
35
- try {
36
- const pid = Number(fs.readFileSync(PIDFILE(), 'utf8'));
37
- return pid && pid !== process.pid && alive(pid) ? pid : null;
38
- }
39
- catch {
40
- return null;
41
- }
42
- };
43
- // Starts the pulse in the background unless one runs (or RINGI_PULSE=off): join and continue call it.
44
- export const ensurePulse = (cli) => {
45
- if (process.env.RINGI_PULSE === 'off' || running())
46
- return;
47
- spawn(process.execPath, [cli, 'pulse'], { detached: true, stdio: 'ignore', env: process.env }).unref();
48
- };
49
- export const beatAll = (prev, next) => {
50
- const rows = table();
31
+ const beatAll = (prev, next) => {
32
+ const rows = agentPorts().host.snapshot();
51
33
  return allSessions().flatMap((s) => {
52
34
  try {
53
35
  const H = openHub(s.hub);
@@ -66,38 +48,32 @@ export const beatAll = (prev, next) => {
66
48
  }
67
49
  });
68
50
  };
51
+ // Beats until no session is left twice in a row, or the home is gone; `once`: one round.
52
+ const beatLoop = async (every, once, log) => {
53
+ const prev = new Map();
54
+ for (let idle = 0; idle < 2;) {
55
+ const beats = beatAll(prev, every);
56
+ for (const b of beats)
57
+ if (b.error)
58
+ log(`pulse: ${b.session.agent} in ${b.session.hub}/${b.session.room}: ${b.error}`);
59
+ idle = beats.length ? 0 : idle + 1;
60
+ if (once || !hubPorts().state.present())
61
+ return;
62
+ await sleep(every * 1000);
63
+ }
64
+ };
69
65
  // The loop: one pulse per home, beating every `every` seconds until no session is left or the home is gone.
70
66
  export const pulse = async ({ every = 30, once = false, log }) => {
71
- // Claimed under the home's lock, so two starts at once leave one pulse.
72
- const other = locked('pulse', () => {
73
- const pid = running();
74
- if (!pid)
75
- fs.writeFileSync(PIDFILE(), String(process.pid));
76
- return pid;
77
- });
67
+ const other = claim();
78
68
  if (other) {
79
69
  log(`pulse: already running (pid ${other})`);
80
70
  return 0;
81
71
  }
82
- const prev = new Map();
83
72
  try {
84
- for (let idle = 0; idle < 2;) {
85
- const beats = beatAll(prev, every);
86
- for (const b of beats)
87
- if (b.error)
88
- log(`pulse: ${b.session.agent} in ${b.session.hub}/${b.session.room}: ${b.error}`);
89
- idle = beats.length ? 0 : idle + 1;
90
- if (once || !fs.existsSync(HOME))
91
- break;
92
- await sleep(every * 1000);
93
- }
73
+ await beatLoop(every, once, log);
94
74
  }
95
75
  finally {
96
- try {
97
- if (Number(fs.readFileSync(PIDFILE(), 'utf8')) === process.pid)
98
- fs.rmSync(PIDFILE());
99
- }
100
- catch { }
76
+ release();
101
77
  }
102
78
  return 0;
103
79
  };
@@ -107,4 +83,4 @@ export const published = (R) => (R.hub.store.heartbeats?.(R.s) ?? []).map(h => {
107
83
  const age = Math.max(0, Math.round(Date.now() / 1000 - h.time));
108
84
  return { ...h, state: /^State: (\w+)$/m.exec(h.text)?.[1] ?? '?', waits: /^Waits: (.+)$/m.exec(h.text)?.[1] ?? null, age, overdue: Number.isFinite(next) && age > next * 2 };
109
85
  });
110
- //# sourceMappingURL=heartbeat.js.map
86
+ //# sourceMappingURL=pulse.js.map
@@ -0,0 +1,38 @@
1
+ // singleton: one pulse for this machine, its process id kept in the state as `pulse`. Process facts and the detached
2
+ // launch belong to ProcessHost; a corrupt record never invents an owner.
3
+ import { agentPorts } from '../ports/index.js';
4
+ import { hubPorts, locked } from '../../hub/ports/index.js';
5
+ const PULSE = ['pulse'];
6
+ const recorded = () => {
7
+ let v;
8
+ try {
9
+ v = hubPorts().state.read(PULSE, 0);
10
+ }
11
+ catch {
12
+ return 0;
13
+ }
14
+ return Number.isSafeInteger(v) && v > 0 ? v : 0;
15
+ };
16
+ const running = () => {
17
+ const pid = recorded();
18
+ return pid && pid !== process.pid && agentPorts().host.alive(pid) ? pid : null;
19
+ };
20
+ export const ensurePulse = (cli) => {
21
+ if (process.env.RINGI_PULSE === 'off' || running())
22
+ return;
23
+ agentPorts().host.start({ file: process.execPath, args: [cli, 'pulse'], env: process.env });
24
+ };
25
+ export const claim = () => locked('pulse', () => {
26
+ const pid = running();
27
+ if (!pid)
28
+ hubPorts().state.write(PULSE, process.pid);
29
+ return pid;
30
+ });
31
+ export const release = () => {
32
+ try {
33
+ if (recorded() === process.pid)
34
+ hubPorts().state.remove(PULSE);
35
+ }
36
+ catch { }
37
+ };
38
+ //# sourceMappingURL=singleton.js.map
@@ -0,0 +1,24 @@
1
+ // tools: which agent tool a session runs in, and when that tool last wrote the session's trace, asked of the tools
2
+ // this machine knows (core/agents/ports/tools.ts). Its modification time is the session's own activity, unlike the CPU of an app
3
+ // process that hosts many sessions. A ringi watcher writes no trace of its own: the CPU of its process tree speaks for
4
+ // its turn (index.ts).
5
+ import { agentPorts } from '../ports/index.js';
6
+ const traced = (s) => {
7
+ for (const tool of agentPorts().tools) {
8
+ const id = tool.traceId?.(s);
9
+ if (id)
10
+ return { tool, id };
11
+ }
12
+ return null;
13
+ };
14
+ // The tool the session runs in and the id its trace is named by.
15
+ export const toolOf = (s) => {
16
+ const t = traced(s);
17
+ return t && { tool: t.tool.id, id: t.id };
18
+ };
19
+ // When the session's tool last wrote its trace (unix seconds), or null: no tool known, or no trace found.
20
+ export const traceTime = (s) => {
21
+ const t = traced(s);
22
+ return t?.tool.traceTime?.(t.id) ?? null;
23
+ };
24
+ //# sourceMappingURL=tools.js.map
@@ -1,13 +1,14 @@
1
1
  // overview: where things stand for the operator: the hub, the room, who is in, open work and proposals, the latest
2
2
  // messages, and new ones as they land; and the sessions of this machine.
3
- import * as D from '../domain/decisions.js';
4
- import { OPERATOR, ensureHome, locked } from '../home/index.js';
5
- import { HIDDEN, openHub, room as roomOf } from '../hub/index.js';
6
- import { fail } from '../lib/index.js';
7
- import { ordered } from '../protocol/index.js';
8
- import { linked } from '../runtime/reader.js';
9
- import { allSessions, dropSession, liveness, readSession } from '../runtime/session.js';
10
- import { tasks } from './room.js';
3
+ import * as D from '../hub/decisions/index.js';
4
+ import { hubPorts, locked } from '../hub/ports/index.js';
5
+ import { HIDDEN, OPERATOR, openHub, room as roomOf } from '../hub/rooms/index.js';
6
+ import { fail } from '../../lib/index.js';
7
+ import { ordered } from '../hub/protocol/index.js';
8
+ import { linked } from '../hub/history/index.js';
9
+ import { allSessions, dropSession, liveness, readSession } from './sessions/index.js';
10
+ import { tasks } from '../hub/usecases/room.js';
11
+ import { rooms } from '../hub/usecases/rooms.js';
11
12
  const sessionView = (s) => ({ ...s, liveness: liveness(s) });
12
13
  export const where = (H, name) => {
13
14
  if (!name)
@@ -26,8 +27,13 @@ export const arrived = (H, R, seen) => {
26
27
  seen.add(m.id);
27
28
  return { all, messages };
28
29
  };
30
+ // The hub's rooms, each with how many of its sessions on this machine are active.
31
+ export const roomsActive = (H, o = {}) => {
32
+ const ss = allSessions().filter(s => s.hub === H.name && liveness(s) === 'active');
33
+ return rooms(H, o).map(v => ({ ...v, active: ss.filter(s => s.genesis === v.genesis).length }));
34
+ };
29
35
  export const sessions = () => {
30
- ensureHome();
36
+ hubPorts().state.ensure();
31
37
  return allSessions().map(sessionView);
32
38
  };
33
39
  // The seat a session held becomes free.
@@ -0,0 +1,4 @@
1
+ // host: process facts and isolated launches, apart from any operating system or agent tool. A launch is held by an
2
+ // opaque handle; only its host may stop it. A deadline uses the host's monotonic clock, dates its wall clock.
3
+ export {};
4
+ //# sourceMappingURL=host.js.map
@@ -0,0 +1,7 @@
1
+ // ports (agents): what running agents on this machine needs from it — the agent tools it knows — and where an
2
+ // implementation plugs in. Code asks `agentPorts()`; composition/ wires them in when a program starts.
3
+ import { fail } from '../../../lib/fail.js';
4
+ let wired = null;
5
+ export const wireAgents = (p) => { wired = p; };
6
+ export const agentPorts = () => wired ?? fail('ringi is not wired: a program starts it through composition/');
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,5 @@
1
+ // tools: the agent tools ringi works with (Claude Code, Codex, …), as a port. Each says what it can: recognise that
2
+ // this process runs in one of its sessions, name that session, find the trace it writes while it works, where it reads
3
+ // skills, and what lets its sandbox write a path. A tool leaves out what it cannot do.
4
+ export {};
5
+ //# sourceMappingURL=tools.js.map