@idleware/ringi 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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 +42 -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,78 @@
1
+ // budget: proposals, reviewers' stamps, the decider's decision, and the grants it makes (decisions/1). Each operation
2
+ // takes who acts and typed input, and returns data; interfaces print it.
3
+ import * as D from '../decisions/index.js';
4
+ import { locked } from '../ports/index.js';
5
+ import { OPERATOR, append } from '../rooms/index.js';
6
+ import { fail, note, short } from '../../../lib/index.js';
7
+ import { checkOutgoing, compose, lookup } from '../protocol/index.js';
8
+ import { linked } from '../history/index.js';
9
+ import { isRef } from './actor.js';
10
+ import { grantView, proposalView } from './view.js';
11
+ const proposalAt = (all, ref) => {
12
+ const p = lookup(all, ref);
13
+ if (p.kind !== 'proposal' || p.bad)
14
+ fail(`${short(p.id)} is not a proposal`);
15
+ return p;
16
+ };
17
+ export const stamp = ({ R, me }, ref, s, text) => {
18
+ const { all } = linked(R, me);
19
+ const p = proposalAt(all, ref);
20
+ if (!D.STAMPS.includes(s))
21
+ fail(`usage: stamp <proposal> ${D.STAMPS.join('|')} -m <reason>`);
22
+ const info = D.proposalOf(all, p, R.authorityAt);
23
+ if (!info.reviewers.includes(me))
24
+ fail(`you are not a named reviewer of ${short(p.id)} (reviewers: ${info.reviewers.join(', ') || 'none'})`);
25
+ if (info.decision)
26
+ fail(`${short(p.id)} is already ${info.decision.decision}`);
27
+ const out = compose(text, [['To', [...new Set([p.from, info.decider])].filter(x => x !== me).join(', ') || p.from], ['Re', p.id], ['Kind', 'stamp'], ['Stamp', s], ['Hop', String(p.hopEff + 1)]]);
28
+ checkOutgoing(out, isRef(R));
29
+ return { proposal: p, id: append(R, me, out) };
30
+ };
31
+ // Why the actor may not revoke the proposal's approval: only its decider or the operator revokes, and only an approval.
32
+ const revokeProblem = (info, p, me) => {
33
+ if (info.state !== 'approved')
34
+ return `${short(p.id)} is ${info.state}; only an approval can be revoked`;
35
+ return me !== info.decider && me !== OPERATOR ? `only ${info.decider} or the operator revokes it` : null;
36
+ };
37
+ // Why the actor may not decide the proposal: only its named decider with authority, once, on its latest revision.
38
+ const decideProblem = ({ R, me }, info, p) => {
39
+ if (me !== info.decider)
40
+ return `only the named decider, ${info.decider}, decides ${short(p.id)}`;
41
+ if (!D.mayDecide(R.contract.authority, me, p.from, info.budget))
42
+ return `${me} has no authority to decide this${info.budget ? ` budget (${D.budgetText(info.budget)})` : ''} in hub ${R.hub.name}, or it is your own proposal`;
43
+ if (info.decision)
44
+ return `${short(p.id)} is already ${info.decision.decision}`;
45
+ return info.superseded ? `${short(p.id)} was superseded by ${short(info.superseded.id)}; decide that revision` : null;
46
+ };
47
+ // The decision names the control entry, and so the authority, it was made under (decisions/1).
48
+ export const decide = ({ R, me }, ref, d, text) => locked(`grant-${R.hub.name}`, () => {
49
+ const { all } = linked(R, me);
50
+ const p = proposalAt(all, ref);
51
+ if (!D.DECISIONS.includes(d))
52
+ fail(`usage: decide <proposal> ${D.DECISIONS.join('|')} -m <reason>`);
53
+ const info = D.proposalOf(all, p, R.authorityAt);
54
+ const why = d === 'revoked' ? revokeProblem(info, p, me) : decideProblem({ R, me }, info, p);
55
+ if (why)
56
+ fail(why);
57
+ const to = [...new Set([p.from, ...info.reviewers])].filter(x => x !== me);
58
+ const out = compose(text, [['To', to.join(', ') || '*'], ['Re', p.id], ['Kind', 'decision'], ['Decision', d], ['Control', R.head], ['Hop', String(p.hopEff + 1)]]);
59
+ checkOutgoing(out, isRef(R));
60
+ const id = append(R, me, out);
61
+ const approved = d === 'approved';
62
+ if (approved && info.missing.length)
63
+ note(`decided without stamps from ${info.missing.join(', ')}`);
64
+ return { proposal: p, id, budget: approved ? info.budget : null };
65
+ });
66
+ // Open proposals (with `all`, every one).
67
+ export const proposals = ({ R, me }, { all: everything = false } = {}) => {
68
+ const { all } = linked(R, me);
69
+ const ps = D.proposals(all, R.authorityAt).filter(x => everything || ['open', 'overdue'].includes(x.state));
70
+ return { proposals: ps, views: ps.map(proposalView) };
71
+ };
72
+ export const grants = ({ R, me }) => {
73
+ const { all } = linked(R, me);
74
+ return D.proposals(all, R.authorityAt).filter(x => x.grant).map(x => grantView(x, D.usageOf(all, x.grant)));
75
+ };
76
+ export { propose } from './propose.js';
77
+ export { DECISIONS, STAMPS, budgetText } from '../decisions/index.js';
78
+ //# sourceMappingURL=budget.js.map
@@ -0,0 +1,5 @@
1
+ // config: the operator's terminal context on this machine: the hub and the room a command means when it names none.
2
+ import { hubPorts } from '../ports/index.js';
3
+ export const config = () => ({ hub: 'local', room: null, ...hubPorts().state.read(['config'], {}) });
4
+ export const setConfig = (patch) => hubPorts().state.write(['config'], { ...config(), ...patch });
5
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1,13 @@
1
+ // context: who acts as the operator and where (its terminal context, unless a command names a hub or a room), and what
2
+ // this build is. An agent acts through its session (core/agents/sessions/context.ts).
3
+ import { hubPorts } from '../ports/index.js';
4
+ import { CAPS, HUB_MAJOR, OPERATOR, config, openHub, room as roomOf } from '../rooms/index.js';
5
+ // The operator, in the named hub and room, else in the terminal's current ones.
6
+ export const operator = ({ hub, room } = {}) => {
7
+ const H = openHub(hub ?? config().hub);
8
+ const name = room ?? (hub && hub !== config().hub ? null : config().room);
9
+ return { R: roomOf(H, name), me: OPERATOR };
10
+ };
11
+ export const about = () => ({ version: hubPorts().build.version, home: hubPorts().state.root, resources: hubPorts().build.resources, contract: `${HUB_MAJOR}.x`, capabilities: [...CAPS] });
12
+ export { config };
13
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1,95 @@
1
+ // hubs: the operator's hubs on this machine: list, create, switch, add a signed replica, amend the shared contract.
2
+ import fs from 'node:fs';
3
+ import { DEFAULT_PROFILE, PROFILES_CAPABILITY, parseProfile } from '../work/index.js';
4
+ import { OPERATOR, config, createHub, hubNames, openHub, roomNames, setConfig, transportOf } from '../rooms/index.js';
5
+ import { hubPorts } from '../ports/index.js';
6
+ import { fail, strictJson, words } from '../../../lib/index.js';
7
+ import { ID_RE, compose } from '../protocol/index.js';
8
+ // The operator's terminal context picks the hub unless one is named.
9
+ export const hubOf = (name) => openHub(name ?? config().hub);
10
+ export const hubs = () => {
11
+ hubPorts().state.ensure();
12
+ if (!hubNames().length)
13
+ openHub('local');
14
+ const cur = config().hub;
15
+ return hubNames().map(n => {
16
+ const H = openHub(n);
17
+ return { name: H.name, current: H.name === cur, store: H.d.store.type, trust: H.contract.trust, contract: H.contract.version,
18
+ rooms: roomNames(H).length, remote: H.d.store.remote ?? null, dir: H.dir };
19
+ });
20
+ };
21
+ // A new hub; a signed one makes its root key here and returns what other machines need to pin it.
22
+ export const create = (name, { signed = false, url } = {}) => {
23
+ if (!ID_RE.test(name))
24
+ fail('usage: ringi hub create <name> [--signed [--url <git url>]]');
25
+ const { custody } = createHub(name, { signed, url });
26
+ const H = openHub(name);
27
+ return { H, rootKey: custody,
28
+ add: H.signed ? `ringi hub add ${name} ${H.d.store.remote ?? '<url>'} --root '${H.d.root}' --genesis ${H.d.genesis}` : null };
29
+ };
30
+ export const use = (name) => {
31
+ openHub(name);
32
+ setConfig({ hub: name, room: null });
33
+ };
34
+ // A replica of a signed hub. The root key comes from the operator, out of band: a key the hub advertises proves nothing.
35
+ export const add = (name, url, { root, genesis }) => {
36
+ if (!ID_RE.test(name) || !url)
37
+ fail('usage: ringi hub add <name> <git url> --root <public key|file> [--genesis <sha>]');
38
+ hubPorts().state.ensure();
39
+ const t = transportOf(name, hubPorts().store);
40
+ if (!t.attach)
41
+ return fail(`a ${hubPorts().store} store cannot replicate a published hub`);
42
+ t.attach(name, url, { root, genesis });
43
+ return openHub(name);
44
+ };
45
+ const SETTABLE = ['version', 'capabilities', 'protocol', 'profile'];
46
+ const json = (x) => JSON.stringify(x, null, 2) + '\n';
47
+ // `key=value` pairs on the contract: capabilities are words, protocol a number, the rest strings.
48
+ const setKeys = (contract, set) => {
49
+ for (const kv of set) {
50
+ const [k, v] = kv.split(/=(.*)/s);
51
+ if (!SETTABLE.includes(k))
52
+ fail(`contract keys that can be set: ${SETTABLE.join(', ')} (not ${k})`);
53
+ contract[k] = k === 'capabilities' ? words(v) : k === 'protocol' ? Number(v) : v;
54
+ }
55
+ };
56
+ // The files the amendment brings besides the contract; a profile is checked before it reaches the contract.
57
+ const extraFiles = (x) => {
58
+ const files = {};
59
+ if (x.authority)
60
+ files['authority.json'] = json(strictJson(fs.readFileSync(x.authority, 'utf8'), x.authority));
61
+ for (const f of x.files ?? []) {
62
+ if (/^profiles\/[^/]+\.json$/.test(f.path))
63
+ parseProfile(f.content.toString('utf8'), f.path);
64
+ files[f.path] = f.content;
65
+ }
66
+ return files;
67
+ };
68
+ // The default profile must be built in, or in the hub after this amendment.
69
+ const checkDefault = (H, contract, files) => {
70
+ const p = contract.profile;
71
+ if (typeof p !== 'string' || p === DEFAULT_PROFILE || files[`profiles/${p}.json`])
72
+ return;
73
+ if (H.store.contractFile(H.main, `profiles/${p}.json`) === null)
74
+ fail(`the default profile ${p} is not in the hub; attach it: --attach <file>:profiles/${p}.json`);
75
+ };
76
+ // Profiles other than the built-in A2A rules need clients that read them: the contract says so.
77
+ const needsProfiles = (contract, files, set) => {
78
+ if (!Object.keys(files).some(f => f.startsWith('profiles/')) && !set.some(kv => kv.startsWith('profile=')))
79
+ return;
80
+ const caps = Array.isArray(contract.capabilities) ? contract.capabilities : [];
81
+ if (!caps.includes(PROFILES_CAPABILITY))
82
+ contract.capabilities = [...caps, PROFILES_CAPABILITY];
83
+ };
84
+ // A new version of the shared contract on `main`. Rooms keep their base until moved (rooms.rebase).
85
+ export const amend = (H, x) => {
86
+ const name = 'contract.json';
87
+ const contract = strictJson(H.store.contractFile(H.main, name), name);
88
+ setKeys(contract, x.set ?? []);
89
+ const files = extraFiles(x);
90
+ checkDefault(H, contract, files);
91
+ needsProfiles(contract, files, x.set ?? []);
92
+ H.store.amendContract(OPERATOR, compose(x.text, [['To', '*'], ['Kind', 'hub']]), { [name]: json(contract), ...files });
93
+ return { version: String(contract.version) };
94
+ };
95
+ //# sourceMappingURL=hubs.js.map
@@ -0,0 +1,39 @@
1
+ // propose: a proposal for the decider and its reviewers, its budget and revision checked before it is written
2
+ // (decisions/1).
3
+ import * as D from '../decisions/index.js';
4
+ import { OPERATOR, append } from '../rooms/index.js';
5
+ import { fail, note, short } from '../../../lib/index.js';
6
+ import { ID_RE, checkOutgoing, compose, lookup } from '../protocol/index.js';
7
+ import { linked } from '../history/index.js';
8
+ import { isRef } from './actor.js';
9
+ // Named reviewers, the proposer never among them.
10
+ const reviewersOf = (me, x) => {
11
+ if (!ID_RE.test(x.decider))
12
+ fail(`bad decider ${x.decider}`);
13
+ const reviewers = [...new Set(x.reviewers ?? [])].filter(r => r !== me);
14
+ for (const r of reviewers)
15
+ if (!ID_RE.test(r))
16
+ fail(`bad reviewer ${r}`);
17
+ return reviewers;
18
+ };
19
+ const budgetOf = (x) => x.budget ? D.parseBudget(x.budget) ?? fail('--budget takes runs=<n>[, run-seconds=<n>][, concurrency=<n>]') : null;
20
+ // A revision supersedes the actor's own proposal; the operator may revise anyone's.
21
+ const supersededOf = (all, me, ref) => {
22
+ const sup = ref ? lookup(all, ref) : null;
23
+ const mine = sup?.kind === 'proposal' && (sup.from === me || me === OPERATOR);
24
+ return !sup || mine ? sup : fail(`${short(sup.id)} is not your proposal`);
25
+ };
26
+ export const propose = ({ R, me }, x) => {
27
+ const { all } = linked(R, me);
28
+ const reviewers = reviewersOf(me, x), budget = budgetOf(x), sup = supersededOf(all, me, x.supersedes);
29
+ if (budget && !D.mayDecide(R.contract.authority, x.decider, me, budget))
30
+ note(`${x.decider} has no authority for this budget in hub ${R.hub.name}; only operator could approve it`);
31
+ const to = [...new Set([...reviewers, x.decider])].filter(t => t !== me);
32
+ const text = compose(x.text, [['To', to.join(', ') || '*'], ['Kind', 'proposal'], ['Decider', x.decider], ['Reviewers', reviewers.join(', ')],
33
+ ['Due', x.due && D.parseDue(x.due)], ['Budget', budget && D.budgetText(budget)], ['Supersedes', sup?.id]]);
34
+ const bad = D.check(checkOutgoing(text, isRef(R)), isRef(R));
35
+ if (bad)
36
+ fail(`refusing to send: ${bad}`);
37
+ return { id: append(R, me, text, x.files ?? []), to, budget };
38
+ };
39
+ //# sourceMappingURL=propose.js.map
@@ -0,0 +1,82 @@
1
+ // room: what any participant (the operator or an agent) does in a room: write messages and read them, follow work,
2
+ // check signals. Each operation takes who acts and typed input, and returns data; interfaces print it.
3
+ import * as Signals from '../signals/index.js';
4
+ import { isOpen, tasksIn } from '../work/index.js';
5
+ import { HIDDEN, OPERATOR } from '../rooms/index.js';
6
+ import * as HubSignals from '../signals/write.js';
7
+ import { fail, short } from '../../../lib/index.js';
8
+ import { link, lookup, ordered, rootOf, under } from '../protocol/index.js';
9
+ import { linked, loadRoomUnlocked, loadState, readerLock, saveState } from '../history/index.js';
10
+ import { taskView } from './view.js';
11
+ export * from './actor.js';
12
+ export * from './staging.js';
13
+ export * from './send.js';
14
+ // --- reading ---
15
+ // Who marked a message how (read, taken), from the marks that pass their check.
16
+ export const marks = (R, all) => Signals.marksOn(Signals.check(R, all, R.hub.store.signals(R.s)));
17
+ export const message = ({ R, me }, ref) => {
18
+ const { all } = linked(R, me);
19
+ const m = lookup(all, ref);
20
+ return { all, m, replies: [...all.values()].filter(x => x.reId === m.id), marks: marks(R, all).get(m.id) };
21
+ };
22
+ export const thread = ({ R, me }, ref) => {
23
+ const { all } = linked(R, me);
24
+ return { all, msgs: under(all, rootOf(all, lookup(all, ref))) };
25
+ };
26
+ // Work concerns the operator, its requester and assignees, and, while nobody is assigned, whom its root names.
27
+ const concerns = (t, me) => {
28
+ if (me === OPERATOR || t.requester === me || t.assignees.includes(me))
29
+ return true;
30
+ return !t.assignees.length && (t.root.to.includes(me) || t.root.to.includes('*'));
31
+ };
32
+ // Open work that concerns the actor (the operator: all open work); with `all`, every piece of work.
33
+ export const tasks = ({ R, me }, { all: everything = false } = {}) => {
34
+ const P = R.profile;
35
+ const { all } = linked(R, me);
36
+ let ts = tasksIn(all, P);
37
+ if (!everything)
38
+ ts = ts.filter(t => isOpen(t, P) && concerns(t, me));
39
+ ts.sort((a, b) => a.at - b.at);
40
+ const m = marks(R, all);
41
+ return { tasks: ts, views: ts.map(t => taskView(t, m.get(t.root.id)?.taken ?? [])) };
42
+ };
43
+ export const log = ({ R, me }, { agent, all: everything = false, n = 20 } = {}) => {
44
+ const { all } = linked(R, me);
45
+ return ordered([...all.values()].filter(m => (!agent || m.from === agent) && (everything || !(m.kind && HIDDEN.has(m.kind))))).slice(-n);
46
+ };
47
+ // The files of a message: one named path, or all of them.
48
+ export const files = ({ R, me }, ref, path) => {
49
+ const { all } = linked(R, me);
50
+ const m = lookup(all, ref);
51
+ if (path && !m.files.some(f => f.path === path))
52
+ fail(`no ${path} in ${short(m.id)}`);
53
+ return { m, files: m.files.filter(f => !path || f.path === path).map(f => ({ path: f.path, content: R.hub.store.file(m.id, f.path) })) };
54
+ };
55
+ export const members = ({ R, me }) => {
56
+ const { logs, all } = linked(R, me);
57
+ const cards = new Map(ordered([...all.values()].filter(m => m.kind === 'card' && !m.bad)).map(m => [m.from, m]));
58
+ return Object.entries(R.members).map(([id, info]) => ({ id, role: info.role ?? 'member',
59
+ messages: (logs.get(id) ?? []).filter(m => !(m.kind && HIDDEN.has(m.kind))).length, card: cards.get(id)?.subject ?? null }));
60
+ };
61
+ // --- signals ---
62
+ // The room's signals, each checked against its message and against what this reader accepted before; `repair` first
63
+ // restores the missing signals of the actor's own messages.
64
+ export const signals = ({ R, me }, { repair = false } = {}) => readerLock(R, me, () => {
65
+ const { logs, st } = loadRoomUnlocked(R, me);
66
+ const all = link(logs);
67
+ let repaired = null;
68
+ if (repair) {
69
+ repaired = 0;
70
+ for (const m of logs.get(me) ?? [])
71
+ repaired += HubSignals.emit(R, me, all, m);
72
+ }
73
+ const records = R.hub.store.signals(R.s);
74
+ const checked = Signals.check(R, all, records);
75
+ const p = Signals.pins(records, checked, st.signals);
76
+ saveState(R, me, { ...loadState(R, me), signals: p.accepted });
77
+ return { all, checked, alarms: [...p.alarms, ...checked.filter(c => !c.ok).map(c => `signal ${c.ref}: ${c.why}`)], repaired };
78
+ });
79
+ // What interfaces need to show and store a message's files: their sizes, and a path safe to write under.
80
+ export { withSizes } from '../rooms/index.js';
81
+ export { checkPath } from '../protocol/files.js';
82
+ //# sourceMappingURL=room.js.map
@@ -1,15 +1,13 @@
1
1
  // rooms: the operator's rooms in a hub: list, create, switch, admit and remove members, archive, delete, move to a
2
2
  // newer contract, and accept a new baseline for a log after reviewing an alarm.
3
3
  import crypto from 'node:crypto';
4
- import fs from 'node:fs';
5
- import path from 'node:path';
6
- import { DEFAULT_PROFILE, parseProfile } from '../domain/profiles.js';
7
- import { HOME, OPERATOR, config, guard, locked, setConfig } from '../home/index.js';
8
- import { RESERVED_ROOMS, ROOM_MD, controlChange, profileText, room as roomOf, roomNames } from '../hub/index.js';
9
- import { Fail, fail, note } from '../lib/index.js';
10
- import { AGENT_RE, ID_RE, compose } from '../protocol/index.js';
11
- import { loadState, readerLock, saveState } from '../runtime/reader.js';
12
- import { allSessions, liveness } from '../runtime/session.js';
4
+ import { DEFAULT_PROFILE, parseProfile } from '../work/index.js';
5
+ import { hubPorts, locked } from '../ports/index.js';
6
+ import { OPERATOR, RESERVED_ROOMS, ROOM_MD, config, controlChange, profileText, room as roomOf, roomNames, setConfig } from '../rooms/index.js';
7
+ import { Fail, fail, note } from '../../../lib/index.js';
8
+ import { ID_RE, compose } from '../protocol/index.js';
9
+ import { notSigned } from './roster.js';
10
+ export { admit, forgetLog, remove } from './roster.js';
13
11
  // The operator's terminal context picks the room unless one is named.
14
12
  export const roomIn = (H, name) => roomOf(H, name ?? config().room);
15
13
  // A room the store offers but that does not open (a history under another name) is an alarm, not a row.
@@ -26,11 +24,8 @@ const opens = (H, n) => {
26
24
  };
27
25
  export const rooms = (H, { archived = false } = {}) => {
28
26
  const cur = config().room;
29
- const view = (n, R) => {
30
- const ss = allSessions().filter(s => s.hub === H.name && s.genesis === R.genesis);
31
- return { name: n, current: n === cur && !R.archived, archived: R.archived, members: Object.keys(R.members).length,
32
- active: ss.filter(s => liveness(s) === 'active').length, profile: R.profile.name, genesis: R.genesis };
33
- };
27
+ const view = (n, R) => ({ name: n, current: n === cur && !R.archived, archived: R.archived,
28
+ members: Object.keys(R.members).length, profile: R.profile.name, genesis: R.genesis });
34
29
  const live = roomNames(H).flatMap(n => { const R = opens(H, n); return R ? [view(n, R)] : []; });
35
30
  const gone = archived ? roomNames(H, true).flatMap(n => { const R = opens(H, n); return R ? [view(n, R)] : []; }) : [];
36
31
  return [...live, ...gone];
@@ -62,29 +57,6 @@ export const use = (H, name) => {
62
57
  setConfig({ hub: H.name, room: R.name });
63
58
  return R;
64
59
  };
65
- export const migrate = (H, name) => {
66
- if (!H.store.migrateRoom)
67
- fail(`store ${H.store.type} cannot migrate rooms`);
68
- return locked(`hub-${H.name}`, () => H.store.migrateRoom(name));
69
- };
70
- // Removing, archiving or deleting in a signed hub needs revocation published to every replica: not in this version.
71
- const notSigned = (H, what) => { if (H.signed)
72
- fail(`room ${what} is not supported on signed hubs yet: a local change would come back with the next fetch`); };
73
- export const admit = (H, R, who, key) => {
74
- if (!H.signed || !H.store.admit)
75
- fail('room admit is for signed hubs; on a local hub the operator\'s join adds members');
76
- if (!AGENT_RE.test(who))
77
- fail(`bad agent id ${who}: lowercase letters, digits, - and _, no dot`);
78
- locked(`hub-${H.name}`, () => H.store.admit(R.s, who, key));
79
- };
80
- export const remove = (H, R, who) => {
81
- notSigned(H, 'remove');
82
- if (!R.members[who])
83
- fail(`${who} is not a member of ${R.name}`);
84
- if (who === OPERATOR)
85
- fail('the operator stays in every room');
86
- controlChange(R, OPERATOR, `remove ${who}`, m => { delete m[who]; });
87
- };
88
60
  export const archive = (H, R) => {
89
61
  notSigned(H, 'archive');
90
62
  if (R.archived)
@@ -96,38 +68,14 @@ export const archive = (H, R) => {
96
68
  return name;
97
69
  };
98
70
  // The room and everything kept for it: in the store (deleteRoom) and its readers' state. The sessions bound to it,
99
- // on this machine or another, leave it on their own when they find its branch gone (runtime/session.ts).
71
+ // on this machine or another, leave it on their own when they find its branch gone (core/agents/sessions).
100
72
  export const erase = (H, R) => {
101
73
  notSigned(H, 'delete');
102
74
  locked(`hub-${H.name}`, () => H.store.deleteRoom(R.s));
103
- guard(() => fs.rmSync(path.join(HOME, 'readers', H.name, R.genesis), { recursive: true, force: true }));
75
+ hubPorts().state.remove(['readers', H.name, R.genesis]);
104
76
  if (config().room === R.name)
105
77
  setConfig({ room: null });
106
78
  };
107
79
  // The room follows the hub's current contract from now on; nothing written before is reinterpreted.
108
80
  export const rebase = (H, R) => controlChange(R, OPERATOR, `contract ${H.contract.version}`, () => { }, [['Contract', H.main]]);
109
- // The operator accepts a new baseline for one log, for every reader of the room, after reviewing an alarm. A signed
110
- // store resets its transport pin too, keeping the displaced head as evidence; signatures are never waived.
111
- export const forgetLog = (H, R, id) => {
112
- if (!ID_RE.test(id))
113
- fail('usage: ringi forget <room>/<log>');
114
- if (H.signed)
115
- H.store.forgetLog?.(R.s, id);
116
- const dir = path.join(HOME, 'readers', H.name, R.genesis);
117
- let n = 0;
118
- for (const f of fs.existsSync(dir) ? fs.readdirSync(dir).filter(f => f.endsWith('.json')) : []) {
119
- const reader = f.slice(0, -5);
120
- readerLock(R, reader, () => {
121
- const st = loadState(R, reader);
122
- if (st.heads?.[id]) {
123
- delete st.heads[id];
124
- st.alarms = (st.alarms ?? []).filter(a => !a.startsWith(`log ${id} `) && !a.startsWith(`log ${id}:`));
125
- saveState(R, reader, st);
126
- n++;
127
- }
128
- H.store.unpin(R.s, reader, id);
129
- });
130
- }
131
- return n;
132
- };
133
81
  //# sourceMappingURL=rooms.js.map
@@ -0,0 +1,47 @@
1
+ // roster: who belongs to a room and whose history its readers accept: admit a signed member, remove one, and accept a
2
+ // new baseline for a log after an alarm.
3
+ import { hubPorts, locked } from '../ports/index.js';
4
+ import { OPERATOR, controlChange } from '../rooms/index.js';
5
+ import { fail } from '../../../lib/index.js';
6
+ import { AGENT_RE, ID_RE } from '../protocol/index.js';
7
+ import { loadState, readerLock, saveState } from '../history/index.js';
8
+ // Removing, archiving or deleting in a signed hub needs revocation published to every replica: not in this version.
9
+ export const notSigned = (H, what) => { if (H.signed)
10
+ fail(`room ${what} is not supported on signed hubs yet: a local change would come back with the next fetch`); };
11
+ export const admit = (H, R, who, key) => {
12
+ if (!H.signed || !H.store.admit)
13
+ fail('room admit is for signed hubs; on a local hub the operator\'s join adds members');
14
+ if (!AGENT_RE.test(who))
15
+ fail(`bad agent id ${who}: lowercase letters, digits, - and _, no dot`);
16
+ locked(`hub-${H.name}`, () => H.store.admit(R.s, who, key));
17
+ };
18
+ export const remove = (H, R, who) => {
19
+ notSigned(H, 'remove');
20
+ if (!R.members[who])
21
+ fail(`${who} is not a member of ${R.name}`);
22
+ if (who === OPERATOR)
23
+ fail('the operator stays in every room');
24
+ controlChange(R, OPERATOR, `remove ${who}`, m => { delete m[who]; });
25
+ };
26
+ // One reader forgets the log's accepted head and the alarms about it; whether it had accepted any.
27
+ const forgetIn = (R, reader, id) => readerLock(R, reader, () => {
28
+ const st = loadState(R, reader);
29
+ const heads = st.heads ?? {}, had = !!heads[id];
30
+ if (had) {
31
+ delete heads[id];
32
+ st.alarms = (st.alarms ?? []).filter(a => !a.startsWith(`log ${id} `) && !a.startsWith(`log ${id}:`));
33
+ saveState(R, reader, st);
34
+ }
35
+ R.hub.store.unpin(R.s, reader, id);
36
+ return had;
37
+ });
38
+ // The operator accepts a new baseline for one log, for every reader of the room, after reviewing an alarm. A signed
39
+ // store resets its transport pin too, keeping the displaced head as evidence; signatures are never waived.
40
+ export const forgetLog = (H, R, id) => {
41
+ if (!ID_RE.test(id))
42
+ fail('usage: ringi forget <room>/<log>');
43
+ if (H.signed)
44
+ H.store.forgetLog?.(R.s, id);
45
+ return hubPorts().state.list(['readers', H.name, R.genesis]).filter(reader => forgetIn(R, reader, id)).length;
46
+ };
47
+ //# sourceMappingURL=roster.js.map
@@ -0,0 +1,78 @@
1
+ // send: a message from the actor, its recipients, trailers and files checked before it is written.
2
+ import * as D from '../decisions/index.js';
3
+ import { OPERATOR, append } from '../rooms/index.js';
4
+ import { fail, note, short } from '../../../lib/index.js';
5
+ import { ID_RE, TOKEN_RE, checkOutgoing, compose, lookup } from '../protocol/index.js';
6
+ import { linked, readerLock } from '../history/index.js';
7
+ import { isRef } from './actor.js';
8
+ import { outgoing, shrink, staged } from './staging.js';
9
+ // A reply without `to` goes back to the sender (with `all`, to everyone the message named); one's own, to its recipients.
10
+ const replyTo = (me, x, re) => {
11
+ if (!x.reply || !re)
12
+ return [];
13
+ if (re.from === me)
14
+ return re.to;
15
+ return [re.from, ...(x.all ? re.to.filter(t => t !== me) : [])];
16
+ };
17
+ // Without `to`: a reply goes back, an assignment to the assignees, the operator's message to the room.
18
+ const recipients = (me, x, re, assign) => {
19
+ const to = [...new Set(x.to ?? [])];
20
+ if (to.length)
21
+ return to;
22
+ const back = replyTo(me, x, re);
23
+ if (back.length)
24
+ return back;
25
+ if (assign)
26
+ return assign;
27
+ return me === OPERATOR ? ['*'] : fail('--to is required: agent ids, comma-separated, or *');
28
+ };
29
+ const role = (r) => {
30
+ const parts = r.split('=').map(v => v.trim());
31
+ return parts.length === 2 && ID_RE.test(parts[0]) && TOKEN_RE.test(parts[1]);
32
+ };
33
+ const checkTrailers = (P, x, to, assign, re) => {
34
+ for (const t of to)
35
+ if (t !== '*' && !ID_RE.test(t))
36
+ fail(`bad recipient ${t}`);
37
+ if (x.state && !P.states.includes(x.state))
38
+ fail(`--state must be one of profile ${P.name}: ${P.states.join(', ')}`);
39
+ if (x.state && !re)
40
+ fail('--state belongs to a reply inside a piece of work; pass --re <message>');
41
+ for (const a of assign ?? [])
42
+ if (!ID_RE.test(a))
43
+ fail(`bad assignee ${a}`);
44
+ if (x.roles && !x.roles.split(',').every(role))
45
+ fail('--roles takes "<id>=<label>, …"; labels mean what the room profile says');
46
+ };
47
+ // The grant a piece of work spends: an approved decision with a budget, not revoked.
48
+ const grantOf = (R, all, ref) => {
49
+ if (!ref)
50
+ return null;
51
+ const d = lookup(all, ref);
52
+ const g = D.grantOf(all, R.authorityAt, d.id) ?? fail(`${short(d.id)} is not an approved decision with a budget`);
53
+ return g.revoked ? fail(`grant ${short(g.id)} was revoked`) : g.id;
54
+ };
55
+ // A message from the actor. The operator may omit `to`: the room, or the assignees when there are any.
56
+ export const send = ({ R, me }, x) => {
57
+ const P = R.profile;
58
+ const { all } = linked(R, me);
59
+ const re = x.re ? lookup(all, x.re) : null;
60
+ const assign = x.assign ? [...new Set(x.assign)] : null;
61
+ const to = recipients(me, x, re, assign);
62
+ checkTrailers(P, x, to, assign, re);
63
+ const grant = grantOf(R, all, x.grant);
64
+ const stagedNow = staged({ R, me });
65
+ const entries = outgoing(stagedNow, x.files ?? []);
66
+ const text = compose(x.text, [
67
+ ['To', to.join(', ')], ['Re', re?.id], ['Kind', x.task && P.opens], ['State', x.state], ['Assign', assign?.join(', ')],
68
+ ['Roles', x.roles], ['Grant', grant], ['Hop', re && String(re.hopEff + 1)],
69
+ ]);
70
+ checkOutgoing(text, isRef(R));
71
+ const id = append(R, me, text, entries);
72
+ if (stagedNow.length)
73
+ readerLock(R, me, () => shrink({ R, me }, s => !stagedNow.some(t => t.path === s.path && t.blob === s.blob)));
74
+ if (to.length === 1 && to[0] === '*')
75
+ note(`addressed to the whole room: this ${x.task ? P.opens : 'message'} wakes nobody; name recipients (--to or --assign) to start work`);
76
+ return { id, to, files: entries.length };
77
+ };
78
+ //# sourceMappingURL=send.js.map
@@ -0,0 +1,60 @@
1
+ // staging, like git's index: add takes a file's content into the store now, and the actor's next message carries it,
2
+ // whatever happens to the file meanwhile. Results and state travel only so, never through a shared directory. The store
3
+ // keeps staged contents reachable (`retain`); it grows before the list does and shrinks after, so a crash in between
4
+ // leaks an object rather than loses one.
5
+ import fs from 'node:fs';
6
+ import { fail } from '../../../lib/index.js';
7
+ import { checkCollisions } from '../protocol/files.js';
8
+ import { loadState, readerLock, saveState } from '../history/index.js';
9
+ const FILE_MAX = 64 << 20;
10
+ const tooBig = (path, size) => size > FILE_MAX && fail(`${path} is ${Math.ceil(size / (1 << 20))} MiB; an attachment is at most ${FILE_MAX >> 20} MiB`);
11
+ // What retain keeps: each staged content once, named by its id, so two snapshots of one path both stay.
12
+ const kept = (all) => [...new Set(all.map(s => s.blob))].map(blob => ({ path: blob, blob, mode: '100644' }));
13
+ export const staged = ({ R, me }) => loadState(R, me).staged ?? [];
14
+ export const stage = ({ R, me }, files) => {
15
+ const taken = files.map(e => {
16
+ if (!e.file)
17
+ fail(`${e.path}: add takes files`);
18
+ tooBig(e.path, fs.statSync(e.file).size);
19
+ const b = R.hub.store.blob(e.file);
20
+ tooBig(e.path, b.size);
21
+ return { path: e.path, blob: b.id, mode: e.mode, size: b.size };
22
+ });
23
+ return readerLock(R, me, () => {
24
+ const st = loadState(R, me);
25
+ const next = new Map((st.staged ?? []).map(s => [s.path, s]));
26
+ for (const s of taken)
27
+ next.set(s.path, s);
28
+ const all = [...next.values()];
29
+ checkCollisions(all.map(s => s.path));
30
+ R.hub.store.retain(R.s, me, kept([...all, ...st.staged ?? []]));
31
+ saveState(R, me, { ...st, staged: all });
32
+ R.hub.store.retain(R.s, me, kept(all));
33
+ return all;
34
+ });
35
+ };
36
+ export const shrink = ({ R, me }, keep) => {
37
+ const st = loadState(R, me);
38
+ const left = (st.staged ?? []).filter(keep);
39
+ saveState(R, me, { ...st, staged: left });
40
+ R.hub.store.retain(R.s, me, kept(left));
41
+ return left;
42
+ };
43
+ // Unstages the given paths, or everything.
44
+ export const unstage = (a, paths) => readerLock(a.R, a.me, () => {
45
+ const missing = (paths ?? []).filter(p => !staged(a).some(s => s.path === p));
46
+ if (missing.length)
47
+ fail(`not staged: ${missing.join(', ')}`);
48
+ return shrink(a, s => paths !== null && !paths.includes(s.path));
49
+ });
50
+ // What the actor staged goes along, an explicit attachment of the same path in its place.
51
+ export const outgoing = (stagedNow, explicit) => {
52
+ for (const e of explicit)
53
+ if (e.file)
54
+ tooBig(e.path, fs.statSync(e.file).size);
55
+ const named = new Set(explicit.map(e => e.path));
56
+ const entries = [...stagedNow.filter(s => !named.has(s.path)).map(s => ({ path: s.path, blob: s.blob, mode: s.mode })), ...explicit];
57
+ checkCollisions(entries.map(e => e.path));
58
+ return entries;
59
+ };
60
+ //# sourceMappingURL=staging.js.map