@sentropic/h2a-cli 0.74.0 → 0.78.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 (346) hide show
  1. package/dist/index.d.ts +1 -36
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +2 -40
  4. package/dist/index.js.map +1 -1
  5. package/package.json +4 -15
  6. package/dist/bin.d.ts +0 -3
  7. package/dist/bin.d.ts.map +0 -1
  8. package/dist/bin.js +0 -83
  9. package/dist/bin.js.map +0 -1
  10. package/dist/cli-contract.d.ts +0 -62
  11. package/dist/cli-contract.d.ts.map +0 -1
  12. package/dist/cli-contract.js +0 -729
  13. package/dist/cli-contract.js.map +0 -1
  14. package/dist/cli.d.ts +0 -254
  15. package/dist/cli.d.ts.map +0 -1
  16. package/dist/cli.js +0 -4530
  17. package/dist/cli.js.map +0 -1
  18. package/dist/hosts/agy.d.ts +0 -14
  19. package/dist/hosts/agy.d.ts.map +0 -1
  20. package/dist/hosts/agy.js +0 -47
  21. package/dist/hosts/agy.js.map +0 -1
  22. package/dist/hosts/claude.d.ts +0 -12
  23. package/dist/hosts/claude.d.ts.map +0 -1
  24. package/dist/hosts/claude.js +0 -46
  25. package/dist/hosts/claude.js.map +0 -1
  26. package/dist/hosts/codex.d.ts +0 -65
  27. package/dist/hosts/codex.d.ts.map +0 -1
  28. package/dist/hosts/codex.js +0 -45
  29. package/dist/hosts/codex.js.map +0 -1
  30. package/dist/hosts/gemini.d.ts +0 -12
  31. package/dist/hosts/gemini.d.ts.map +0 -1
  32. package/dist/hosts/gemini.js +0 -46
  33. package/dist/hosts/gemini.js.map +0 -1
  34. package/dist/hosts/plugin.d.ts +0 -151
  35. package/dist/hosts/plugin.d.ts.map +0 -1
  36. package/dist/hosts/plugin.js +0 -188
  37. package/dist/hosts/plugin.js.map +0 -1
  38. package/dist/mcp.d.ts +0 -2
  39. package/dist/mcp.d.ts.map +0 -1
  40. package/dist/mcp.js +0 -32
  41. package/dist/mcp.js.map +0 -1
  42. package/dist/runtime/blockage/index.d.ts +0 -3
  43. package/dist/runtime/blockage/index.d.ts.map +0 -1
  44. package/dist/runtime/blockage/index.js +0 -3
  45. package/dist/runtime/blockage/index.js.map +0 -1
  46. package/dist/runtime/blockage/notifiers.d.ts +0 -52
  47. package/dist/runtime/blockage/notifiers.d.ts.map +0 -1
  48. package/dist/runtime/blockage/notifiers.js +0 -74
  49. package/dist/runtime/blockage/notifiers.js.map +0 -1
  50. package/dist/runtime/blockage/registry.d.ts +0 -30
  51. package/dist/runtime/blockage/registry.d.ts.map +0 -1
  52. package/dist/runtime/blockage/registry.js +0 -86
  53. package/dist/runtime/blockage/registry.js.map +0 -1
  54. package/dist/runtime/deploy/k8s-sidecar.d.ts +0 -92
  55. package/dist/runtime/deploy/k8s-sidecar.d.ts.map +0 -1
  56. package/dist/runtime/deploy/k8s-sidecar.js +0 -166
  57. package/dist/runtime/deploy/k8s-sidecar.js.map +0 -1
  58. package/dist/runtime/deploy/k8s-tenant.d.ts +0 -86
  59. package/dist/runtime/deploy/k8s-tenant.d.ts.map +0 -1
  60. package/dist/runtime/deploy/k8s-tenant.js +0 -255
  61. package/dist/runtime/deploy/k8s-tenant.js.map +0 -1
  62. package/dist/runtime/drive/inbox-wake.d.ts +0 -36
  63. package/dist/runtime/drive/inbox-wake.d.ts.map +0 -1
  64. package/dist/runtime/drive/inbox-wake.js +0 -50
  65. package/dist/runtime/drive/inbox-wake.js.map +0 -1
  66. package/dist/runtime/drive/index.d.ts +0 -173
  67. package/dist/runtime/drive/index.d.ts.map +0 -1
  68. package/dist/runtime/drive/index.js +0 -503
  69. package/dist/runtime/drive/index.js.map +0 -1
  70. package/dist/runtime/drumbeat/deciders.d.ts +0 -32
  71. package/dist/runtime/drumbeat/deciders.d.ts.map +0 -1
  72. package/dist/runtime/drumbeat/deciders.js +0 -65
  73. package/dist/runtime/drumbeat/deciders.js.map +0 -1
  74. package/dist/runtime/drumbeat/decisions.d.ts +0 -19
  75. package/dist/runtime/drumbeat/decisions.d.ts.map +0 -1
  76. package/dist/runtime/drumbeat/decisions.js +0 -34
  77. package/dist/runtime/drumbeat/decisions.js.map +0 -1
  78. package/dist/runtime/drumbeat/inbox-relance.d.ts +0 -29
  79. package/dist/runtime/drumbeat/inbox-relance.d.ts.map +0 -1
  80. package/dist/runtime/drumbeat/inbox-relance.js +0 -101
  81. package/dist/runtime/drumbeat/inbox-relance.js.map +0 -1
  82. package/dist/runtime/drumbeat/index.d.ts +0 -8
  83. package/dist/runtime/drumbeat/index.d.ts.map +0 -1
  84. package/dist/runtime/drumbeat/index.js +0 -8
  85. package/dist/runtime/drumbeat/index.js.map +0 -1
  86. package/dist/runtime/drumbeat/registry.d.ts +0 -60
  87. package/dist/runtime/drumbeat/registry.d.ts.map +0 -1
  88. package/dist/runtime/drumbeat/registry.js +0 -115
  89. package/dist/runtime/drumbeat/registry.js.map +0 -1
  90. package/dist/runtime/drumbeat/relaunchers.d.ts +0 -111
  91. package/dist/runtime/drumbeat/relaunchers.d.ts.map +0 -1
  92. package/dist/runtime/drumbeat/relaunchers.js +0 -242
  93. package/dist/runtime/drumbeat/relaunchers.js.map +0 -1
  94. package/dist/runtime/drumbeat/scan.d.ts +0 -36
  95. package/dist/runtime/drumbeat/scan.d.ts.map +0 -1
  96. package/dist/runtime/drumbeat/scan.js +0 -41
  97. package/dist/runtime/drumbeat/scan.js.map +0 -1
  98. package/dist/runtime/drumbeat/watch.d.ts +0 -74
  99. package/dist/runtime/drumbeat/watch.d.ts.map +0 -1
  100. package/dist/runtime/drumbeat/watch.js +0 -216
  101. package/dist/runtime/drumbeat/watch.js.map +0 -1
  102. package/dist/runtime/escalation/index.d.ts +0 -2
  103. package/dist/runtime/escalation/index.d.ts.map +0 -1
  104. package/dist/runtime/escalation/index.js +0 -2
  105. package/dist/runtime/escalation/index.js.map +0 -1
  106. package/dist/runtime/escalation/registry.d.ts +0 -44
  107. package/dist/runtime/escalation/registry.d.ts.map +0 -1
  108. package/dist/runtime/escalation/registry.js +0 -79
  109. package/dist/runtime/escalation/registry.js.map +0 -1
  110. package/dist/runtime/governance/claims.d.ts +0 -43
  111. package/dist/runtime/governance/claims.d.ts.map +0 -1
  112. package/dist/runtime/governance/claims.js +0 -93
  113. package/dist/runtime/governance/claims.js.map +0 -1
  114. package/dist/runtime/governance/conductor.d.ts +0 -79
  115. package/dist/runtime/governance/conductor.d.ts.map +0 -1
  116. package/dist/runtime/governance/conductor.js +0 -106
  117. package/dist/runtime/governance/conductor.js.map +0 -1
  118. package/dist/runtime/governance/index.d.ts +0 -5
  119. package/dist/runtime/governance/index.d.ts.map +0 -1
  120. package/dist/runtime/governance/index.js +0 -5
  121. package/dist/runtime/governance/index.js.map +0 -1
  122. package/dist/runtime/governance/launch-check.d.ts +0 -93
  123. package/dist/runtime/governance/launch-check.d.ts.map +0 -1
  124. package/dist/runtime/governance/launch-check.js +0 -113
  125. package/dist/runtime/governance/launch-check.js.map +0 -1
  126. package/dist/runtime/governance/spawns.d.ts +0 -50
  127. package/dist/runtime/governance/spawns.d.ts.map +0 -1
  128. package/dist/runtime/governance/spawns.js +0 -91
  129. package/dist/runtime/governance/spawns.js.map +0 -1
  130. package/dist/runtime/identity/bindings.d.ts +0 -84
  131. package/dist/runtime/identity/bindings.d.ts.map +0 -1
  132. package/dist/runtime/identity/bindings.js +0 -112
  133. package/dist/runtime/identity/bindings.js.map +0 -1
  134. package/dist/runtime/identity/index.d.ts +0 -11
  135. package/dist/runtime/identity/index.d.ts.map +0 -1
  136. package/dist/runtime/identity/index.js +0 -6
  137. package/dist/runtime/identity/index.js.map +0 -1
  138. package/dist/runtime/identity/live.d.ts +0 -26
  139. package/dist/runtime/identity/live.d.ts.map +0 -1
  140. package/dist/runtime/identity/live.js +0 -232
  141. package/dist/runtime/identity/live.js.map +0 -1
  142. package/dist/runtime/identity/migration.d.ts +0 -55
  143. package/dist/runtime/identity/migration.d.ts.map +0 -1
  144. package/dist/runtime/identity/migration.js +0 -100
  145. package/dist/runtime/identity/migration.js.map +0 -1
  146. package/dist/runtime/identity/readers.d.ts +0 -42
  147. package/dist/runtime/identity/readers.d.ts.map +0 -1
  148. package/dist/runtime/identity/readers.js +0 -248
  149. package/dist/runtime/identity/readers.js.map +0 -1
  150. package/dist/runtime/identity/resolver.d.ts +0 -50
  151. package/dist/runtime/identity/resolver.d.ts.map +0 -1
  152. package/dist/runtime/identity/resolver.js +0 -61
  153. package/dist/runtime/identity/resolver.js.map +0 -1
  154. package/dist/runtime/identity/workspace-id.d.ts +0 -43
  155. package/dist/runtime/identity/workspace-id.d.ts.map +0 -1
  156. package/dist/runtime/identity/workspace-id.js +0 -138
  157. package/dist/runtime/identity/workspace-id.js.map +0 -1
  158. package/dist/runtime/local-files/index.d.ts +0 -8
  159. package/dist/runtime/local-files/index.d.ts.map +0 -1
  160. package/dist/runtime/local-files/index.js +0 -8
  161. package/dist/runtime/local-files/index.js.map +0 -1
  162. package/dist/runtime/local-files/lease.d.ts +0 -62
  163. package/dist/runtime/local-files/lease.d.ts.map +0 -1
  164. package/dist/runtime/local-files/lease.js +0 -249
  165. package/dist/runtime/local-files/lease.js.map +0 -1
  166. package/dist/runtime/local-files/locks.d.ts +0 -43
  167. package/dist/runtime/local-files/locks.d.ts.map +0 -1
  168. package/dist/runtime/local-files/locks.js +0 -197
  169. package/dist/runtime/local-files/locks.js.map +0 -1
  170. package/dist/runtime/local-files/migrate.d.ts +0 -31
  171. package/dist/runtime/local-files/migrate.d.ts.map +0 -1
  172. package/dist/runtime/local-files/migrate.js +0 -104
  173. package/dist/runtime/local-files/migrate.js.map +0 -1
  174. package/dist/runtime/local-files/paths.d.ts +0 -146
  175. package/dist/runtime/local-files/paths.d.ts.map +0 -1
  176. package/dist/runtime/local-files/paths.js +0 -233
  177. package/dist/runtime/local-files/paths.js.map +0 -1
  178. package/dist/runtime/local-files/presence.d.ts +0 -80
  179. package/dist/runtime/local-files/presence.d.ts.map +0 -1
  180. package/dist/runtime/local-files/presence.js +0 -250
  181. package/dist/runtime/local-files/presence.js.map +0 -1
  182. package/dist/runtime/local-files/schema.d.ts +0 -47
  183. package/dist/runtime/local-files/schema.d.ts.map +0 -1
  184. package/dist/runtime/local-files/schema.js +0 -77
  185. package/dist/runtime/local-files/schema.js.map +0 -1
  186. package/dist/runtime/local-files/store.d.ts +0 -132
  187. package/dist/runtime/local-files/store.d.ts.map +0 -1
  188. package/dist/runtime/local-files/store.js +0 -997
  189. package/dist/runtime/local-files/store.js.map +0 -1
  190. package/dist/runtime/mcp/handlers.d.ts +0 -196
  191. package/dist/runtime/mcp/handlers.d.ts.map +0 -1
  192. package/dist/runtime/mcp/handlers.js +0 -1025
  193. package/dist/runtime/mcp/handlers.js.map +0 -1
  194. package/dist/runtime/mcp/index.d.ts +0 -7
  195. package/dist/runtime/mcp/index.d.ts.map +0 -1
  196. package/dist/runtime/mcp/index.js +0 -7
  197. package/dist/runtime/mcp/index.js.map +0 -1
  198. package/dist/runtime/mcp/notifications.d.ts +0 -47
  199. package/dist/runtime/mcp/notifications.d.ts.map +0 -1
  200. package/dist/runtime/mcp/notifications.js +0 -204
  201. package/dist/runtime/mcp/notifications.js.map +0 -1
  202. package/dist/runtime/mcp/server.d.ts +0 -45
  203. package/dist/runtime/mcp/server.d.ts.map +0 -1
  204. package/dist/runtime/mcp/server.js +0 -94
  205. package/dist/runtime/mcp/server.js.map +0 -1
  206. package/dist/runtime/mcp/sessions.d.ts +0 -68
  207. package/dist/runtime/mcp/sessions.d.ts.map +0 -1
  208. package/dist/runtime/mcp/sessions.js +0 -152
  209. package/dist/runtime/mcp/sessions.js.map +0 -1
  210. package/dist/runtime/mcp/stdio.d.ts +0 -72
  211. package/dist/runtime/mcp/stdio.d.ts.map +0 -1
  212. package/dist/runtime/mcp/stdio.js +0 -274
  213. package/dist/runtime/mcp/stdio.js.map +0 -1
  214. package/dist/runtime/mcp/tools.d.ts +0 -19
  215. package/dist/runtime/mcp/tools.d.ts.map +0 -1
  216. package/dist/runtime/mcp/tools.js +0 -525
  217. package/dist/runtime/mcp/tools.js.map +0 -1
  218. package/dist/runtime/mcp-http/app.d.ts +0 -33
  219. package/dist/runtime/mcp-http/app.d.ts.map +0 -1
  220. package/dist/runtime/mcp-http/app.js +0 -162
  221. package/dist/runtime/mcp-http/app.js.map +0 -1
  222. package/dist/runtime/mcp-http/hosted-mcp-server.d.ts +0 -14
  223. package/dist/runtime/mcp-http/hosted-mcp-server.d.ts.map +0 -1
  224. package/dist/runtime/mcp-http/hosted-mcp-server.js +0 -38
  225. package/dist/runtime/mcp-http/hosted-mcp-server.js.map +0 -1
  226. package/dist/runtime/mcp-http/index.d.ts +0 -18
  227. package/dist/runtime/mcp-http/index.d.ts.map +0 -1
  228. package/dist/runtime/mcp-http/index.js +0 -18
  229. package/dist/runtime/mcp-http/index.js.map +0 -1
  230. package/dist/runtime/mcp-http/main.d.ts +0 -2
  231. package/dist/runtime/mcp-http/main.d.ts.map +0 -1
  232. package/dist/runtime/mcp-http/main.js +0 -14
  233. package/dist/runtime/mcp-http/main.js.map +0 -1
  234. package/dist/runtime/mcp-http/oauth/broker-login.d.ts +0 -50
  235. package/dist/runtime/mcp-http/oauth/broker-login.d.ts.map +0 -1
  236. package/dist/runtime/mcp-http/oauth/broker-login.js +0 -41
  237. package/dist/runtime/mcp-http/oauth/broker-login.js.map +0 -1
  238. package/dist/runtime/mcp-http/oauth/broker-routes.d.ts +0 -45
  239. package/dist/runtime/mcp-http/oauth/broker-routes.d.ts.map +0 -1
  240. package/dist/runtime/mcp-http/oauth/broker-routes.js +0 -54
  241. package/dist/runtime/mcp-http/oauth/broker-routes.js.map +0 -1
  242. package/dist/runtime/mcp-http/oauth/config.d.ts +0 -49
  243. package/dist/runtime/mcp-http/oauth/config.d.ts.map +0 -1
  244. package/dist/runtime/mcp-http/oauth/config.js +0 -69
  245. package/dist/runtime/mcp-http/oauth/config.js.map +0 -1
  246. package/dist/runtime/mcp-http/oauth/crypto.d.ts +0 -14
  247. package/dist/runtime/mcp-http/oauth/crypto.d.ts.map +0 -1
  248. package/dist/runtime/mcp-http/oauth/crypto.js +0 -29
  249. package/dist/runtime/mcp-http/oauth/crypto.js.map +0 -1
  250. package/dist/runtime/mcp-http/oauth/file-store.d.ts +0 -48
  251. package/dist/runtime/mcp-http/oauth/file-store.d.ts.map +0 -1
  252. package/dist/runtime/mcp-http/oauth/file-store.js +0 -101
  253. package/dist/runtime/mcp-http/oauth/file-store.js.map +0 -1
  254. package/dist/runtime/mcp-http/oauth/hono-oauth-router.d.ts +0 -5
  255. package/dist/runtime/mcp-http/oauth/hono-oauth-router.d.ts.map +0 -1
  256. package/dist/runtime/mcp-http/oauth/hono-oauth-router.js +0 -92
  257. package/dist/runtime/mcp-http/oauth/hono-oauth-router.js.map +0 -1
  258. package/dist/runtime/mcp-http/oauth/oidc-rp.d.ts +0 -56
  259. package/dist/runtime/mcp-http/oauth/oidc-rp.d.ts.map +0 -1
  260. package/dist/runtime/mcp-http/oauth/oidc-rp.js +0 -63
  261. package/dist/runtime/mcp-http/oauth/oidc-rp.js.map +0 -1
  262. package/dist/runtime/mcp-http/oauth/redirect-uri.d.ts +0 -11
  263. package/dist/runtime/mcp-http/oauth/redirect-uri.d.ts.map +0 -1
  264. package/dist/runtime/mcp-http/oauth/redirect-uri.js +0 -29
  265. package/dist/runtime/mcp-http/oauth/redirect-uri.js.map +0 -1
  266. package/dist/runtime/mcp-http/oauth/single-tenant-provider.d.ts +0 -70
  267. package/dist/runtime/mcp-http/oauth/single-tenant-provider.d.ts.map +0 -1
  268. package/dist/runtime/mcp-http/oauth/single-tenant-provider.js +0 -247
  269. package/dist/runtime/mcp-http/oauth/single-tenant-provider.js.map +0 -1
  270. package/dist/runtime/mcp-http/oauth/tenancy.d.ts +0 -3
  271. package/dist/runtime/mcp-http/oauth/tenancy.d.ts.map +0 -1
  272. package/dist/runtime/mcp-http/oauth/tenancy.js +0 -18
  273. package/dist/runtime/mcp-http/oauth/tenancy.js.map +0 -1
  274. package/dist/runtime/mcp-http/readonly-allowlist.d.ts +0 -24
  275. package/dist/runtime/mcp-http/readonly-allowlist.d.ts.map +0 -1
  276. package/dist/runtime/mcp-http/readonly-allowlist.js +0 -43
  277. package/dist/runtime/mcp-http/readonly-allowlist.js.map +0 -1
  278. package/dist/runtime/mcp-http/serve.d.ts +0 -39
  279. package/dist/runtime/mcp-http/serve.d.ts.map +0 -1
  280. package/dist/runtime/mcp-http/serve.js +0 -100
  281. package/dist/runtime/mcp-http/serve.js.map +0 -1
  282. package/dist/runtime/mirror/accept.d.ts +0 -57
  283. package/dist/runtime/mirror/accept.d.ts.map +0 -1
  284. package/dist/runtime/mirror/accept.js +0 -70
  285. package/dist/runtime/mirror/accept.js.map +0 -1
  286. package/dist/runtime/mirror/build.d.ts +0 -44
  287. package/dist/runtime/mirror/build.d.ts.map +0 -1
  288. package/dist/runtime/mirror/build.js +0 -37
  289. package/dist/runtime/mirror/build.js.map +0 -1
  290. package/dist/runtime/mirror/index.d.ts +0 -9
  291. package/dist/runtime/mirror/index.d.ts.map +0 -1
  292. package/dist/runtime/mirror/index.js +0 -9
  293. package/dist/runtime/mirror/index.js.map +0 -1
  294. package/dist/runtime/mirror/serve.d.ts +0 -21
  295. package/dist/runtime/mirror/serve.d.ts.map +0 -1
  296. package/dist/runtime/mirror/serve.js +0 -141
  297. package/dist/runtime/mirror/serve.js.map +0 -1
  298. package/dist/runtime/nhi.d.ts +0 -15
  299. package/dist/runtime/nhi.d.ts.map +0 -1
  300. package/dist/runtime/nhi.js +0 -26
  301. package/dist/runtime/nhi.js.map +0 -1
  302. package/dist/runtime/remote/accept.d.ts +0 -50
  303. package/dist/runtime/remote/accept.d.ts.map +0 -1
  304. package/dist/runtime/remote/accept.js +0 -54
  305. package/dist/runtime/remote/accept.js.map +0 -1
  306. package/dist/runtime/remote/client.d.ts +0 -27
  307. package/dist/runtime/remote/client.d.ts.map +0 -1
  308. package/dist/runtime/remote/client.js +0 -34
  309. package/dist/runtime/remote/client.js.map +0 -1
  310. package/dist/runtime/remote/index.d.ts +0 -5
  311. package/dist/runtime/remote/index.d.ts.map +0 -1
  312. package/dist/runtime/remote/index.js +0 -5
  313. package/dist/runtime/remote/index.js.map +0 -1
  314. package/dist/runtime/remote/serve.d.ts +0 -27
  315. package/dist/runtime/remote/serve.d.ts.map +0 -1
  316. package/dist/runtime/remote/serve.js +0 -26
  317. package/dist/runtime/remote/serve.js.map +0 -1
  318. package/dist/runtime/remote/server.d.ts +0 -36
  319. package/dist/runtime/remote/server.d.ts.map +0 -1
  320. package/dist/runtime/remote/server.js +0 -100
  321. package/dist/runtime/remote/server.js.map +0 -1
  322. package/dist/runtime/sysml/client.d.ts +0 -44
  323. package/dist/runtime/sysml/client.d.ts.map +0 -1
  324. package/dist/runtime/sysml/client.js +0 -52
  325. package/dist/runtime/sysml/client.js.map +0 -1
  326. package/dist/runtime/sysml/disclosure.d.ts +0 -23
  327. package/dist/runtime/sysml/disclosure.d.ts.map +0 -1
  328. package/dist/runtime/sysml/disclosure.js +0 -53
  329. package/dist/runtime/sysml/disclosure.js.map +0 -1
  330. package/dist/runtime/sysml/index.d.ts +0 -4
  331. package/dist/runtime/sysml/index.d.ts.map +0 -1
  332. package/dist/runtime/sysml/index.js +0 -4
  333. package/dist/runtime/sysml/index.js.map +0 -1
  334. package/dist/runtime/sysml/verify.d.ts +0 -32
  335. package/dist/runtime/sysml/verify.d.ts.map +0 -1
  336. package/dist/runtime/sysml/verify.js +0 -67
  337. package/dist/runtime/sysml/verify.js.map +0 -1
  338. package/dist/runtime/upgrade/index.d.ts +0 -96
  339. package/dist/runtime/upgrade/index.d.ts.map +0 -1
  340. package/dist/runtime/upgrade/index.js +0 -185
  341. package/dist/runtime/upgrade/index.js.map +0 -1
  342. package/dist/runtime/version/agent-version.d.ts +0 -15
  343. package/dist/runtime/version/agent-version.d.ts.map +0 -1
  344. package/dist/runtime/version/agent-version.js +0 -53
  345. package/dist/runtime/version/agent-version.js.map +0 -1
  346. package/skills/h2a/SKILL.md +0 -345
@@ -1,1025 +0,0 @@
1
- import { readFileSync, realpathSync } from "node:fs";
2
- import { hostname } from "node:os";
3
- import { H2A_ACTIVITY_WINDOW_DEFAULT_MS, H2A_ATTESTER_COMPREHENSION_RIGHT, H2A_COMPREHENSION_ATTESTATION_BODY_KIND, H2A_ROLES, H2A_DECLARATION_INTERET_BODY_KIND, H2A_SESSION_NOTIFICATION_TOPICS, H2A_SESSION_STATES, auditNhiPosture, deriveConnectionConfidence, buildComprehensionAttestation, canAttestComprehension, computeHash, createEnvelope, deriveWorkspaceId, effectiveOrgInstances, isComprehensionAttestation, nhiAttestationEnvelope, nhiInventory, nhiTrustBundle, signCanonical, signEnvelope } from "@sentropic/h2a";
4
- function mcpReadMachineId() {
5
- for (const p of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
6
- try {
7
- const id = readFileSync(p, "utf8").trim();
8
- if (id.length > 0)
9
- return id;
10
- }
11
- catch { /* try next */ }
12
- }
13
- return hostname() || "unknown-machine";
14
- }
15
- import { listBlockages, raiseBlockage, resolveBlockage } from "../blockage/registry.js";
16
- import { conductorFor } from "../governance/conductor.js";
17
- import { appendConductorClaim } from "../governance/claims.js";
18
- import { conductorLaunchCheck } from "../governance/launch-check.js";
19
- import { canonicalAddress, isHostQualifiedAddress, listPresence, resolveRecipient, writePresence } from "../local-files/index.js";
20
- import { createLocalStore } from "../local-files/store.js";
21
- import { lastSpawnRequestAt, recordSpawnRequest, spawnAllowed } from "../governance/spawns.js";
22
- import { gatherNhiSnapshot } from "../nhi.js";
23
- import { agentVersion } from "../version/agent-version.js";
24
- const ESCALATION_CHANNELS = new Set(["advise", "decide", "alert"]);
25
- function safeError(reason) {
26
- if (reason instanceof Error)
27
- return { error: reason.message };
28
- return { error: String(reason) };
29
- }
30
- function nowIso() {
31
- return new Date().toISOString();
32
- }
33
- export function handleRegisterInstance(store, args) {
34
- if (!args || typeof args.registration !== "object" || args.registration === null) {
35
- return { error: "h2a_register_instance: missing 'registration' object" };
36
- }
37
- try {
38
- store.registerInstance(args.registration);
39
- return { ok: true, instance: args.registration.id };
40
- }
41
- catch (err) {
42
- return safeError(err);
43
- }
44
- }
45
- // ---------------------------------------------------------------------------
46
- // WP-F (presence-honesty): connection-confidence helpers — ADVISORY surfacing
47
- // only; nothing here gates routing (that change is parked).
48
- // ---------------------------------------------------------------------------
49
- /** Clock-skew margin (ms) for a mirrored session's cross-machine timestamp. */
50
- const ACTIVITY_SKEW_MARGIN_MS = 120_000;
51
- /** Activity window (ms): `H2A_ACTIVITY_WINDOW_MS` env override, else the default. */
52
- function activityWindowMs() {
53
- const raw = process.env.H2A_ACTIVITY_WINDOW_MS;
54
- if (raw !== undefined) {
55
- const n = Number.parseInt(raw, 10);
56
- if (Number.isFinite(n) && n > 0)
57
- return n;
58
- }
59
- return H2A_ACTIVITY_WINDOW_DEFAULT_MS;
60
- }
61
- /** Confidence of one session, adding a skew margin for mirrored records. */
62
- function confidenceOf(session, now) {
63
- return deriveConnectionConfidence(session, {
64
- now,
65
- activityWindowMs: activityWindowMs(),
66
- ...(session.mirroredAt ? { skewMarginMs: ACTIVITY_SKEW_MARGIN_MS } : {})
67
- });
68
- }
69
- /** Best confidence across sessions: active > idle-uncertain > unknown. */
70
- function bestConfidence(sessions, now) {
71
- if (sessions.length === 0)
72
- return undefined;
73
- const set = new Set(sessions.map((s) => confidenceOf(s, now)));
74
- if (set.has("active"))
75
- return "active";
76
- if (set.has("idle-uncertain"))
77
- return "idle-uncertain";
78
- return "unknown";
79
- }
80
- export function handleDiscoverInstances(store, args) {
81
- try {
82
- let instances = store.listInstances();
83
- // DEC-110: gate discovery on the effective org view (registration ∪
84
- // provisioned membership grants), matching the CLI `discover` verb.
85
- const effective = effectiveOrgInstances(instances, store.listOrgMembership());
86
- const effByInstance = new Map(effective.map((e) => [e.instance, e]));
87
- if (args?.role) {
88
- const wanted = args.role;
89
- instances = instances.filter((reg) => effByInstance.get(reg.instance)?.roles.includes(wanted));
90
- }
91
- if (args?.scope) {
92
- const wanted = args.scope;
93
- instances = instances.filter((reg) => effByInstance.get(reg.instance)?.scopes.includes(wanted));
94
- }
95
- return { instances };
96
- }
97
- catch (err) {
98
- return safeError(err);
99
- }
100
- }
101
- export function handleInbox(store, args) {
102
- if (!args || typeof args.instance !== "string" || args.instance.length === 0) {
103
- return { error: "h2a_inbox: missing 'instance'" };
104
- }
105
- // Narrowed once here so the type survives into the filter closures below.
106
- const instance = args.instance;
107
- try {
108
- switch (args.action) {
109
- case "read":
110
- return { envelopes: store.readInbox(args.instance) };
111
- case "put": {
112
- if (!args.envelope)
113
- return { error: "h2a_inbox put: missing 'envelope'" };
114
- if (!isHostQualifiedAddress(args.instance)) {
115
- return {
116
- error: `h2a: recipient "${args.instance}" is not host-qualified — address it as <host>:<label> (e.g. claude:${String(args.instance).replace(/^:+/, "") || "agent"}). A bare label is ambiguous (the same label can exist on several hosts) and routes to an orphan inbox nobody reads. Resolve the exact peer via discover.`
117
- };
118
- }
119
- // WP-2: resolve-before-send legibility gate (does NOT change destination).
120
- {
121
- const liveSessions = listPresence(store.paths.root).map((s) => s.instance);
122
- const registeredIds = store.listInstances().map((i) => i.instance ?? i.id);
123
- const resolution = resolveRecipient({
124
- target: args.instance,
125
- liveInstances: liveSessions,
126
- registeredInstances: registeredIds
127
- });
128
- if (resolution.kind === "refuse") {
129
- return {
130
- error: resolution.reason,
131
- ...(resolution.candidates ? { candidates: resolution.candidates } : {})
132
- };
133
- }
134
- // deliver / deliver-dormant / deliver-hint → proceed with put.
135
- }
136
- store.putInboxMessage(args.instance, args.envelope);
137
- // Bug-2 backstop: report whether the recipient actually has a fresh
138
- // session. The write always succeeds (a dormant deposit-for-wake is
139
- // legitimate), but the caller must know live vs dormant rather than
140
- // assuming delivery. Exact-instance match — a live agent is addressed by
141
- // its full perennial id; the bare channel/alias form reads as dormant.
142
- const allFresh = listPresence(store.paths.root);
143
- const matchingFresh = allFresh.filter((s) => canonicalAddress(s.instance) === canonicalAddress(instance));
144
- const freshSessions = matchingFresh.length;
145
- // WP-F: honest at-send connection confidence for the recipient —
146
- // recipientLive is heartbeat-based (which the keepalive prober can also
147
- // refresh); recipientConfidence reflects ACTUAL MCP-channel traffic, so
148
- // an "idle-uncertain" recipient may be silently disconnected even while
149
- // recipientLive is true. Advisory — the put still delivers (dormant
150
- // deposit-for-wake stays legitimate).
151
- const recipientConfidence = bestConfidence(matchingFresh, Date.now());
152
- // WP-2: enrich return with resolution metadata.
153
- const liveSessions2 = allFresh.map((s) => s.instance);
154
- const registeredIds2 = store.listInstances().map((i) => i.instance ?? i.id);
155
- const resolution2 = resolveRecipient({
156
- target: args.instance,
157
- liveInstances: liveSessions2,
158
- registeredInstances: registeredIds2
159
- });
160
- return {
161
- ok: true,
162
- envelopeId: args.envelope.id,
163
- recipientLive: freshSessions > 0,
164
- freshSessions,
165
- ...(recipientConfidence ? { recipientConfidence } : {}),
166
- resolution: resolution2.kind,
167
- ...(resolution2.kind === "deliver-hint" ? { liveCandidate: resolution2.liveCandidate, reason: resolution2.reason } : {}),
168
- ...(resolution2.kind === "deliver-dormant" ? { reason: resolution2.reason, dormant: true } : {})
169
- };
170
- }
171
- case "pop": {
172
- if (typeof args.envelopeId !== "string" || args.envelopeId.length === 0) {
173
- return { error: "h2a_inbox pop: missing 'envelopeId'" };
174
- }
175
- const envelope = store.popInboxMessage(args.instance, args.envelopeId);
176
- if (!envelope) {
177
- return { error: `h2a_inbox pop: no envelope ${args.envelopeId} for ${args.instance}` };
178
- }
179
- return { envelope };
180
- }
181
- default:
182
- return {
183
- error: `h2a_inbox: unknown action '${String(args.action)}', expected read|put|pop`
184
- };
185
- }
186
- }
187
- catch (err) {
188
- return safeError(err);
189
- }
190
- }
191
- export function handleAppendJournal(store, args) {
192
- if (!args || typeof args.negotiationId !== "string" || args.negotiationId.length === 0) {
193
- return { error: "h2a_append_journal: missing 'negotiationId'" };
194
- }
195
- if (!args.payload || typeof args.payload !== "object") {
196
- return { error: "h2a_append_journal: missing 'payload'" };
197
- }
198
- try {
199
- const entry = store.appendNegotiationEvent(args.negotiationId, args.payload);
200
- return { entry };
201
- }
202
- catch (err) {
203
- return safeError(err);
204
- }
205
- }
206
- export function handleOpenNegotiation(store, args) {
207
- if (!args || typeof args.record !== "object" || args.record === null) {
208
- return { error: "h2a_open_negotiation: missing 'record' object" };
209
- }
210
- try {
211
- const persisted = store.openNegotiation(args.record);
212
- return { record: persisted };
213
- }
214
- catch (err) {
215
- return safeError(err);
216
- }
217
- }
218
- /**
219
- * Resolve causation/correlation for an MCP-driven journal append, mirroring
220
- * the CLI semantics (DEC-033): explicit args always win, otherwise inherit
221
- * from the previous journal entry — `causationId` defaults to the previous
222
- * entry's `id`, `correlationId` is propagated as-is.
223
- */
224
- function resolveChain(store, negotiationId, explicit) {
225
- const entries = store.readNegotiationJournal(negotiationId);
226
- const previous = entries[entries.length - 1];
227
- const out = {};
228
- if (explicit.causationId) {
229
- out.causationId = explicit.causationId;
230
- }
231
- else if (previous) {
232
- out.causationId = previous.id;
233
- }
234
- if (explicit.correlationId) {
235
- out.correlationId = explicit.correlationId;
236
- }
237
- else if (previous && previous.correlationId !== undefined) {
238
- out.correlationId = previous.correlationId;
239
- }
240
- return out;
241
- }
242
- function handleOfferLike(store, toolName, args) {
243
- if (!args || typeof args.negotiationId !== "string" || args.negotiationId.length === 0) {
244
- return { error: `${toolName}: missing 'negotiationId'` };
245
- }
246
- if (typeof args.instance !== "string" || args.instance.length === 0) {
247
- return { error: `${toolName}: missing 'instance'` };
248
- }
249
- if (args.artifact === undefined) {
250
- return { error: `${toolName}: missing 'artifact'` };
251
- }
252
- const record = store.readNegotiation(args.negotiationId);
253
- if (!record) {
254
- return { error: `${toolName}: negotiation ${args.negotiationId} not found` };
255
- }
256
- const type = toolName === "h2a_offer" ? "propose" : "counter";
257
- const chain = resolveChain(store, args.negotiationId, {
258
- causationId: args.causationId,
259
- correlationId: args.correlationId
260
- });
261
- const payload = {
262
- id: args.eventId ?? `evt-${type}-${Date.now().toString(36)}`,
263
- type,
264
- actor: { instance: args.instance, role: "CONDUCTOR", scope: record.scope },
265
- body: { artifact: args.artifact },
266
- createdAt: nowIso(),
267
- ...chain
268
- };
269
- try {
270
- const entry = store.appendNegotiationEvent(args.negotiationId, payload);
271
- return { entry };
272
- }
273
- catch (err) {
274
- return safeError(err);
275
- }
276
- }
277
- export function handleOffer(store, args) {
278
- return handleOfferLike(store, "h2a_offer", args);
279
- }
280
- export function handleCounteroffer(store, args) {
281
- return handleOfferLike(store, "h2a_counteroffer", args);
282
- }
283
- export function handleSign(store, args) {
284
- if (!args || typeof args.negotiationId !== "string" || args.negotiationId.length === 0) {
285
- return { error: "h2a_sign: missing 'negotiationId'" };
286
- }
287
- if (typeof args.instance !== "string" || args.instance.length === 0) {
288
- return { error: "h2a_sign: missing 'instance'" };
289
- }
290
- if (args.artifact === undefined) {
291
- return { error: "h2a_sign: missing 'artifact'" };
292
- }
293
- if (typeof args.privateKeyPem !== "string" || args.privateKeyPem.length === 0) {
294
- return { error: "h2a_sign: missing 'privateKeyPem'" };
295
- }
296
- const record = store.readNegotiation(args.negotiationId);
297
- if (!record) {
298
- return { error: `h2a_sign: negotiation ${args.negotiationId} not found` };
299
- }
300
- try {
301
- const artifactHash = computeHash(args.artifact);
302
- const signature = signCanonical({ artifactHash }, { by: args.instance, privateKeyPem: args.privateKeyPem });
303
- const chain = resolveChain(store, args.negotiationId, {
304
- causationId: args.causationId,
305
- correlationId: args.correlationId
306
- });
307
- const payload = {
308
- id: args.eventId ?? `evt-sign-${Date.now().toString(36)}`,
309
- type: "event",
310
- actor: { instance: args.instance, role: "CONDUCTOR", scope: record.scope },
311
- body: { kind: "signature", artifactHash, signature },
312
- createdAt: nowIso(),
313
- ...chain
314
- };
315
- const entry = store.appendNegotiationEvent(args.negotiationId, payload);
316
- return { entry };
317
- }
318
- catch (err) {
319
- return safeError(err);
320
- }
321
- }
322
- export function handleStabilize(store, args) {
323
- if (!args || typeof args.negotiationId !== "string" || args.negotiationId.length === 0) {
324
- return { error: "h2a_stabilize: missing 'negotiationId'" };
325
- }
326
- try {
327
- const result = store.stabilizeNegotiation(args.negotiationId, { eventId: args.eventId });
328
- return {
329
- record: result.record,
330
- artifactHash: result.artifactHash,
331
- signers: result.signers,
332
- artifactPath: result.artifactPath,
333
- advisoryEvents: result.advisoryEvents.map((entry) => ({
334
- id: entry.id,
335
- sequence: entry.sequence
336
- })),
337
- finalEvent: { id: result.finalEvent.id, sequence: result.finalEvent.sequence }
338
- };
339
- }
340
- catch (err) {
341
- return safeError(err);
342
- }
343
- }
344
- function findRegisteredInstance(store, instance) {
345
- return store.findInstance(instance) ?? store.listInstances().find((entry) => entry.instance === instance);
346
- }
347
- function roleFromArg(value) {
348
- if (typeof value !== "string")
349
- return undefined;
350
- return H2A_ROLES.includes(value) ? value : undefined;
351
- }
352
- export function handleAttestComprehension(store, args) {
353
- if (!args || typeof args.instance !== "string" || args.instance.length === 0) {
354
- return { error: "h2a_attest_comprehension: missing 'instance'" };
355
- }
356
- if (typeof args.privateKeyPem !== "string" || args.privateKeyPem.length === 0) {
357
- return { error: "h2a_attest_comprehension: missing 'privateKeyPem'" };
358
- }
359
- if (args.dossierHash === undefined && args.dossier === undefined) {
360
- return { error: "h2a_attest_comprehension: missing 'dossierHash' or 'dossier'" };
361
- }
362
- const registration = findRegisteredInstance(store, args.instance);
363
- if (!registration) {
364
- return { error: `h2a_attest_comprehension: instance ${args.instance} not registered` };
365
- }
366
- const record = args.negotiationId ? store.readNegotiation(args.negotiationId) : undefined;
367
- if (args.negotiationId && !record) {
368
- return { error: `h2a_attest_comprehension: negotiation ${args.negotiationId} not found` };
369
- }
370
- const role = args.role === undefined ? registration.roles[0] : roleFromArg(args.role);
371
- if (!role) {
372
- return { error: `h2a_attest_comprehension: unknown or missing role ${String(args.role ?? "")}` };
373
- }
374
- const scope = args.scope ?? record?.scope ?? registration.scopes[0];
375
- if (!scope) {
376
- return { error: `h2a_attest_comprehension: ${args.instance} has no scope` };
377
- }
378
- if (!canAttestComprehension(role, registration.capabilities)) {
379
- return {
380
- error: `h2a_attest_comprehension: role ${role} for ${args.instance} cannot attest comprehension; AGENTS require ${H2A_ATTESTER_COMPREHENSION_RIGHT}`
381
- };
382
- }
383
- try {
384
- const body = buildComprehensionAttestation({
385
- subject: args.instance,
386
- dossierHash: args.dossierHash ?? computeHash(args.dossier),
387
- ...(args.at ? { at: args.at } : {})
388
- });
389
- if (body.kind !== H2A_COMPREHENSION_ATTESTATION_BODY_KIND ||
390
- !isComprehensionAttestation(body)) {
391
- return { error: "h2a_attest_comprehension: invalid comprehension-attestation body" };
392
- }
393
- const actor = { instance: args.instance, role, scope };
394
- const signature = signCanonical(body, { by: args.instance, privateKeyPem: args.privateKeyPem });
395
- if (args.negotiationId) {
396
- const chain = resolveChain(store, args.negotiationId, {
397
- causationId: args.causationId,
398
- correlationId: args.correlationId
399
- });
400
- const payload = {
401
- id: args.eventId ?? `evt-comprehension-${Date.now().toString(36)}`,
402
- type: "event",
403
- actor,
404
- body,
405
- signatures: [signature],
406
- createdAt: body.at,
407
- ...chain
408
- };
409
- const entry = store.appendNegotiationEvent(args.negotiationId, payload);
410
- return { entry };
411
- }
412
- const envelope = createEnvelope({
413
- id: args.eventId ?? `env-comprehension-${Date.now().toString(36)}`,
414
- type: "event",
415
- actor,
416
- body,
417
- signatures: [signature],
418
- createdAt: body.at
419
- });
420
- return { envelope };
421
- }
422
- catch (err) {
423
- return safeError(err);
424
- }
425
- }
426
- function stringList(value) {
427
- if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) {
428
- return undefined;
429
- }
430
- return value.map((item) => item.trim()).filter((item) => item.length > 0);
431
- }
432
- export function handleDeclareConflitInteret(store, args) {
433
- if (!args || typeof args.negotiationId !== "string" || args.negotiationId.length === 0) {
434
- return { error: "h2a_declare_conflit_interet: missing 'negotiationId'" };
435
- }
436
- if (typeof args.instance !== "string" || args.instance.length === 0) {
437
- return { error: "h2a_declare_conflit_interet: missing 'instance'" };
438
- }
439
- const interets = stringList(args.interets);
440
- if (!interets || interets.length === 0) {
441
- return { error: "h2a_declare_conflit_interet: 'interets' must be a non-empty string array" };
442
- }
443
- const bindings = args.bindings === undefined ? [] : stringList(args.bindings);
444
- if (bindings === undefined) {
445
- return { error: "h2a_declare_conflit_interet: 'bindings' must be a string array when provided" };
446
- }
447
- try {
448
- const entry = store.declareConflitInteret(args.negotiationId, {
449
- kind: H2A_DECLARATION_INTERET_BODY_KIND,
450
- subject: args.instance,
451
- interets,
452
- ...(bindings.length > 0 ? { bindings } : {}),
453
- ...(args.masqueImpactCollectif === true ? { masqueImpactCollectif: true } : {}),
454
- at: args.at ?? nowIso()
455
- }, { eventId: args.eventId });
456
- return { entry };
457
- }
458
- catch (err) {
459
- return safeError(err);
460
- }
461
- }
462
- export function handleConflictPosture(store, args) {
463
- if (!args || typeof args.negotiationId !== "string" || args.negotiationId.length === 0) {
464
- return { error: "h2a_conflict_posture: missing 'negotiationId'" };
465
- }
466
- try {
467
- return {
468
- negotiationId: args.negotiationId,
469
- postures: store.derivePosturesConflit(args.negotiationId)
470
- };
471
- }
472
- catch (err) {
473
- return safeError(err);
474
- }
475
- }
476
- export function handleEscalate(store, args) {
477
- if (!args || typeof args.negotiationId !== "string" || args.negotiationId.length === 0) {
478
- return { error: "h2a_escalate: missing 'negotiationId'" };
479
- }
480
- if (typeof args.instance !== "string" || args.instance.length === 0) {
481
- return { error: "h2a_escalate: missing 'instance'" };
482
- }
483
- if (typeof args.channel !== "string" || !ESCALATION_CHANNELS.has(args.channel)) {
484
- return { error: "h2a_escalate: channel must be advise|decide|alert" };
485
- }
486
- const record = store.readNegotiation(args.negotiationId);
487
- if (!record) {
488
- return { error: `h2a_escalate: negotiation ${args.negotiationId} not found` };
489
- }
490
- const channel = args.channel;
491
- const chain = resolveChain(store, args.negotiationId, {
492
- causationId: args.causationId,
493
- correlationId: args.correlationId
494
- });
495
- const payload = {
496
- id: `evt-escalate-${Date.now().toString(36)}`,
497
- type: "escalate",
498
- actor: { instance: args.instance, role: "MANDATAIRE", scope: record.scope },
499
- body: { kind: "escalation", channel, payload: args.payload ?? null },
500
- createdAt: nowIso(),
501
- ...chain
502
- };
503
- try {
504
- const entry = store.appendNegotiationEvent(args.negotiationId, payload);
505
- return { entry };
506
- }
507
- catch (err) {
508
- return safeError(err);
509
- }
510
- }
511
- export function handleSessionOpen(sessions, args) {
512
- if (!args || typeof args.instance !== "string" || args.instance.length === 0) {
513
- return { error: "h2a_session_open: missing 'instance'" };
514
- }
515
- if (args.subscribedTopics !== undefined &&
516
- (!Array.isArray(args.subscribedTopics) ||
517
- args.subscribedTopics.some((topic) => typeof topic !== "string" ||
518
- !H2A_SESSION_NOTIFICATION_TOPICS.includes(topic)))) {
519
- return {
520
- error: "h2a_session_open: 'subscribedTopics' must be a subset of the canonical topic list"
521
- };
522
- }
523
- try {
524
- const session = sessions.open({
525
- instance: args.instance,
526
- ...(args.host !== undefined ? { host: args.host } : {}),
527
- ...(args.workspace !== undefined ? { workspace: args.workspace } : {}),
528
- ...(args.name !== undefined ? { name: args.name } : {}),
529
- version: agentVersion(typeof args.host === "string" ? args.host : undefined),
530
- ...(args.pid !== undefined ? { pid: args.pid } : {}),
531
- ...(args.interests !== undefined ? { interests: args.interests } : {}),
532
- ...(args.subscribedTopics !== undefined
533
- ? {
534
- subscribedTopics: args.subscribedTopics
535
- }
536
- : {}),
537
- ...(args.sessionId !== undefined ? { sessionId: args.sessionId } : {})
538
- });
539
- const peers = sessions
540
- .scanFresh()
541
- .filter((peer) => peer.sessionId !== session.sessionId);
542
- return { session, peers };
543
- }
544
- catch (err) {
545
- return safeError(err);
546
- }
547
- }
548
- export function handleSessionClose(sessions, args) {
549
- if (!args || typeof args.sessionId !== "string" || args.sessionId.length === 0) {
550
- return { error: "h2a_session_close: missing 'sessionId'" };
551
- }
552
- if (args.state !== undefined &&
553
- !H2A_SESSION_STATES.includes(args.state)) {
554
- return {
555
- error: `h2a_session_close: unknown state '${String(args.state)}'`
556
- };
557
- }
558
- try {
559
- const closed = sessions.close(args.sessionId, args.state ?? "closed");
560
- return { ok: true, sessionId: args.sessionId, session: closed };
561
- }
562
- catch (err) {
563
- return safeError(err);
564
- }
565
- }
566
- export function handleDiscoverSessions(sessions, args) {
567
- try {
568
- let fresh = sessions.scanFresh();
569
- if (args?.scope) {
570
- const wanted = args.scope;
571
- fresh = fresh.filter((session) => session.interests.scopes.includes(wanted));
572
- }
573
- if (args?.instance) {
574
- const wanted = args.instance;
575
- fresh = fresh.filter((session) => session.instance === wanted);
576
- }
577
- if (args?.name && typeof args.name === "string" && args.name.length > 0) {
578
- const needle = args.name.toLowerCase();
579
- fresh = fresh.filter((session) => typeof session.name === "string" &&
580
- session.name.toLowerCase().includes(needle));
581
- }
582
- // WP-F: surface connection-confidence per session (advisory). "active" =
583
- // the MCP channel carried traffic within the window; "idle-uncertain" =
584
- // process alive but channel silent (idle OR silently disconnected);
585
- // "unknown" = legacy/mirrored record with no activity stamp.
586
- const now = Date.now();
587
- const enriched = fresh.map((session) => ({
588
- ...session,
589
- connectionConfidence: confidenceOf(session, now)
590
- }));
591
- return { sessions: enriched };
592
- }
593
- catch (err) {
594
- return safeError(err);
595
- }
596
- }
597
- // DEC-087: NHI posture over the registry. Mirrors `h2a nhi report` — same
598
- // snapshot gatherer + core `auditNhiPosture`, so CLI and MCP agree.
599
- export function handleNhiReport(store, args) {
600
- try {
601
- const { instances, subagents, keyEvents } = gatherNhiSnapshot(store);
602
- const report = auditNhiPosture({
603
- instances,
604
- subagents,
605
- keyEvents,
606
- ...(typeof args?.longLivedKeyMaxDays === "number"
607
- ? { longLivedKeyMaxDays: args.longLivedKeyMaxDays }
608
- : {})
609
- });
610
- return { report };
611
- }
612
- catch (err) {
613
- return safeError(err);
614
- }
615
- }
616
- // DEC-090 (P2): per-identity inventory of the estate. Same snapshot gatherer.
617
- export function handleNhiInventory(store, args) {
618
- try {
619
- const { instances, subagents, keyEvents, offboards } = gatherNhiSnapshot(store);
620
- const inventory = nhiInventory({
621
- instances,
622
- subagents,
623
- keyEvents,
624
- offboards,
625
- ...(typeof args?.longLivedKeyMaxDays === "number"
626
- ? { longLivedKeyMaxDays: args.longLivedKeyMaxDays }
627
- : {})
628
- });
629
- return { inventory };
630
- }
631
- catch (err) {
632
- return safeError(err);
633
- }
634
- }
635
- // DEC-087 (P1b): sign the current posture into an attestation envelope. Same
636
- // snapshot + classifier + envelope builder as `h2a nhi attest`.
637
- export function handleNhiAttest(store, args) {
638
- if (!args || typeof args.instance !== "string" || args.instance.length === 0) {
639
- return { error: "h2a_nhi_attest: missing 'instance'" };
640
- }
641
- if (typeof args.privateKeyPem !== "string" || args.privateKeyPem.length === 0) {
642
- return { error: "h2a_nhi_attest: missing 'privateKeyPem'" };
643
- }
644
- try {
645
- const registration = store.findInstance(args.instance);
646
- const role = args.role ?? registration?.roles?.[0];
647
- const scope = args.scope ?? registration?.scopes?.[0];
648
- if (!role || !scope) {
649
- return {
650
- error: `h2a_nhi_attest: cannot resolve actor for "${args.instance}" — register it first, or pass role and scope`
651
- };
652
- }
653
- if (!H2A_ROLES.includes(role)) {
654
- return { error: `h2a_nhi_attest: invalid role "${role}"` };
655
- }
656
- const { instances, subagents, keyEvents } = gatherNhiSnapshot(store);
657
- const report = auditNhiPosture({
658
- instances,
659
- subagents,
660
- keyEvents,
661
- ...(typeof args.longLivedKeyMaxDays === "number"
662
- ? { longLivedKeyMaxDays: args.longLivedKeyMaxDays }
663
- : {})
664
- });
665
- const envelope = nhiAttestationEnvelope({
666
- report,
667
- actor: { instance: args.instance, role: role, scope }
668
- });
669
- const attestation = signEnvelope(envelope, {
670
- by: args.instance,
671
- privateKeyPem: args.privateKeyPem
672
- });
673
- return { attestation };
674
- }
675
- catch (err) {
676
- return safeError(err);
677
- }
678
- }
679
- // DEC-089 (P1c): coordinated decommission — revoke keys + subagents + tombstone.
680
- export function handleNhiOffboard(store, args) {
681
- if (!args || typeof args.instance !== "string" || args.instance.length === 0) {
682
- return { error: "h2a_nhi_offboard: missing 'instance'" };
683
- }
684
- try {
685
- const tombstone = store.offboardInstance(args.instance, args.reason);
686
- return { tombstone };
687
- }
688
- catch (err) {
689
- return safeError(err);
690
- }
691
- }
692
- // DEC-094 (NHI P3): SPIFFE-trust-bundle export of an instance's active keys.
693
- export function handleNhiExport(store, args) {
694
- if (!args || typeof args.instance !== "string" || args.instance.length === 0) {
695
- return { error: "h2a_nhi_export: missing 'instance'" };
696
- }
697
- if (typeof args.trustDomain !== "string" || args.trustDomain.length === 0) {
698
- return { error: "h2a_nhi_export: missing 'trustDomain'" };
699
- }
700
- try {
701
- const bundle = nhiTrustBundle({
702
- instance: args.instance,
703
- trustDomain: args.trustDomain,
704
- activeKeys: store.listInstanceKeys(args.instance)
705
- });
706
- return { bundle };
707
- }
708
- catch (err) {
709
- return safeError(err);
710
- }
711
- }
712
- // DEC-092 (EVO-3): blockage feedback loop. The dispatcher turns the registry
713
- // changes these write into peer.blocked/peer.unblocked pushes.
714
- export function handleBlockageRaise(store, args) {
715
- if (!args || typeof args.instance !== "string" || args.instance.length === 0) {
716
- return { error: "h2a_blockage_raise: missing 'instance'" };
717
- }
718
- if (typeof args.reason !== "string" || args.reason.length === 0) {
719
- return { error: "h2a_blockage_raise: missing 'reason'" };
720
- }
721
- try {
722
- const blockage = raiseBlockage(store.paths.root, {
723
- instance: args.instance,
724
- scope: typeof args.scope === "string" ? args.scope : "",
725
- reason: args.reason,
726
- ...(typeof args.needs === "string" ? { needs: args.needs } : {})
727
- });
728
- return { blockage };
729
- }
730
- catch (err) {
731
- return safeError(err);
732
- }
733
- }
734
- export function handleBlockageList(store, args) {
735
- try {
736
- let blockages = listBlockages(store.paths.root);
737
- if (typeof args?.scope === "string")
738
- blockages = blockages.filter((b) => b.scope === args.scope);
739
- if (args?.active === true)
740
- blockages = blockages.filter((b) => b.resolvedAt === undefined);
741
- return { blockages };
742
- }
743
- catch (err) {
744
- return safeError(err);
745
- }
746
- }
747
- export function handleBlockageResolve(store, args) {
748
- if (!args || typeof args.instance !== "string" || args.instance.length === 0) {
749
- return { error: "h2a_blockage_resolve: missing 'instance'" };
750
- }
751
- try {
752
- const resolved = resolveBlockage(store.paths.root, args.instance, typeof args.by === "string" ? { by: args.by } : {});
753
- if (!resolved) {
754
- return { error: `h2a_blockage_resolve: no blockage recorded for "${args.instance}"` };
755
- }
756
- return { blockage: resolved };
757
- }
758
- catch (err) {
759
- return safeError(err);
760
- }
761
- }
762
- /**
763
- * h2a_conductor — resolve the live conductor/owner of a workspace (WP-G1).
764
- * Mirrors `h2a conductor` CLI. Read-only.
765
- */
766
- export function handleConductor(root, args) {
767
- let workspaceId;
768
- if (typeof args?.workspaceId === "string" && args.workspaceId.length > 0) {
769
- workspaceId = args.workspaceId;
770
- }
771
- else if (typeof args?.workspacePath === "string" && args.workspacePath.length > 0) {
772
- let realPath = args.workspacePath;
773
- try {
774
- realPath = realpathSync(realPath);
775
- }
776
- catch { /* use as-is */ }
777
- workspaceId = deriveWorkspaceId({ machineId: mcpReadMachineId(), path: realPath });
778
- }
779
- if (!workspaceId) {
780
- return { error: "h2a_conductor: provide workspaceId or workspacePath" };
781
- }
782
- try {
783
- const result = conductorFor({ root, workspaceId });
784
- return result;
785
- }
786
- catch (err) {
787
- return safeError(err);
788
- }
789
- }
790
- /**
791
- * h2a_conductor_claim — append a conductor claim for (workspaceId, instance)
792
- * and return the post-claim conductorFor resolution (WP-G1b).
793
- */
794
- export function handleConductorClaim(root, args) {
795
- if (!args || typeof args.instance !== "string" || args.instance.length === 0) {
796
- return { error: "h2a_conductor_claim: missing 'instance'" };
797
- }
798
- let workspaceId;
799
- if (typeof args.workspaceId === "string" && args.workspaceId.length > 0) {
800
- workspaceId = args.workspaceId;
801
- }
802
- else if (typeof args.workspacePath === "string" && args.workspacePath.length > 0) {
803
- let realPath = args.workspacePath;
804
- try {
805
- realPath = realpathSync(realPath);
806
- }
807
- catch { /* use as-is */ }
808
- workspaceId = deriveWorkspaceId({ machineId: mcpReadMachineId(), path: realPath });
809
- }
810
- if (!workspaceId) {
811
- return { error: "h2a_conductor_claim: provide workspaceId or workspacePath" };
812
- }
813
- try {
814
- appendConductorClaim(root, {
815
- type: "claim",
816
- workspaceId,
817
- instance: args.instance,
818
- at: new Date().toISOString()
819
- });
820
- const result = conductorFor({ root, workspaceId });
821
- return result;
822
- }
823
- catch (err) {
824
- return safeError(err);
825
- }
826
- }
827
- /**
828
- * h2a_conductor_release — append a conductor release for (workspaceId, instance)
829
- * and return the post-release conductorFor resolution (WP-G1b).
830
- */
831
- export function handleConductorRelease(root, args) {
832
- if (!args || typeof args.instance !== "string" || args.instance.length === 0) {
833
- return { error: "h2a_conductor_release: missing 'instance'" };
834
- }
835
- let workspaceId;
836
- if (typeof args.workspaceId === "string" && args.workspaceId.length > 0) {
837
- workspaceId = args.workspaceId;
838
- }
839
- else if (typeof args.workspacePath === "string" && args.workspacePath.length > 0) {
840
- let realPath = args.workspacePath;
841
- try {
842
- realPath = realpathSync(realPath);
843
- }
844
- catch { /* use as-is */ }
845
- workspaceId = deriveWorkspaceId({ machineId: mcpReadMachineId(), path: realPath });
846
- }
847
- if (!workspaceId) {
848
- return { error: "h2a_conductor_release: provide workspaceId or workspacePath" };
849
- }
850
- try {
851
- appendConductorClaim(root, {
852
- type: "release",
853
- workspaceId,
854
- instance: args.instance,
855
- at: new Date().toISOString()
856
- });
857
- const result = conductorFor({ root, workspaceId });
858
- return result;
859
- }
860
- catch (err) {
861
- return safeError(err);
862
- }
863
- }
864
- /**
865
- * h2a_conductor_launch_check — DRY-RUN conductor launch recommendation (D3).
866
- *
867
- * Polls `track workspace-activity` and returns a recommendation to launch a
868
- * conductor if work is durably stalled and no conductor is live.
869
- * h2a does NOT spawn anything. This is advisory only; the launch is parked
870
- * pending a spawn policy and remote-trigger support.
871
- */
872
- export function handleConductorLaunchCheck(root, args) {
873
- let workspaceId;
874
- if (typeof args?.workspaceId === "string" && args.workspaceId.length > 0) {
875
- workspaceId = args.workspaceId;
876
- }
877
- else if (typeof args?.workspacePath === "string" && args.workspacePath.length > 0) {
878
- let realPath = args.workspacePath;
879
- try {
880
- realPath = realpathSync(realPath);
881
- }
882
- catch { /* use as-is */ }
883
- workspaceId = deriveWorkspaceId({ machineId: mcpReadMachineId(), path: realPath });
884
- }
885
- if (!workspaceId) {
886
- return { error: "h2a_conductor_launch_check: provide workspaceId or workspacePath" };
887
- }
888
- let idleMs;
889
- if (args?.idleMs !== undefined) {
890
- const parsed = Number(args.idleMs);
891
- if (!Number.isFinite(parsed) || parsed <= 0) {
892
- return { error: `h2a_conductor_launch_check: idleMs must be a positive number (got ${args.idleMs})` };
893
- }
894
- idleMs = parsed;
895
- }
896
- try {
897
- const result = conductorLaunchCheck({ root, workspaceId, ...(idleMs !== undefined ? { idleMs } : {}) });
898
- return result;
899
- }
900
- catch (err) {
901
- return safeError(err);
902
- }
903
- }
904
- /**
905
- * h2a_conductor_launch — D3 EMISSION: emit a conductor-launch-request envelope
906
- * to a live remote agent when work is stalled and no conductor is live.
907
- *
908
- * Gated by --confirm (boolean) and a 1/30min/workspace cap.
909
- * h2a NEVER spawns a process — it only puts a request envelope to remote.
910
- */
911
- export function handleConductorLaunch(root, args) {
912
- // Resolve workspace id (mirrors handleConductorLaunchCheck)
913
- let workspaceId;
914
- if (typeof args?.workspaceId === "string" && args.workspaceId.length > 0) {
915
- workspaceId = args.workspaceId;
916
- }
917
- else if (typeof args?.workspacePath === "string" && args.workspacePath.length > 0) {
918
- let realPath = args.workspacePath;
919
- try {
920
- realPath = realpathSync(realPath);
921
- }
922
- catch { /* use as-is */ }
923
- workspaceId = deriveWorkspaceId({ machineId: mcpReadMachineId(), path: realPath });
924
- }
925
- if (!workspaceId) {
926
- return { error: "h2a_conductor_launch: provide workspaceId or workspacePath" };
927
- }
928
- let idleMs;
929
- if (args?.idleMs !== undefined) {
930
- const parsed = Number(args.idleMs);
931
- if (!Number.isFinite(parsed) || parsed <= 0) {
932
- return { error: `h2a_conductor_launch: idleMs must be a positive number (got ${args.idleMs})` };
933
- }
934
- idleMs = parsed;
935
- }
936
- // 1. Compute the launch recommendation.
937
- const check = conductorLaunchCheck({
938
- root,
939
- workspaceId,
940
- ...(idleMs !== undefined ? { idleMs } : {})
941
- });
942
- if (check.recommendation !== "launch") {
943
- return { action: "none", ...check };
944
- }
945
- // 2. Cooldown gate.
946
- const last = lastSpawnRequestAt(root, workspaceId);
947
- if (!spawnAllowed({ lastSpawnAt: last, now: Date.now() })) {
948
- return {
949
- action: "cooldown",
950
- reason: "a launch request was emitted < 30min ago for this workspace",
951
- lastSpawnAt: last
952
- };
953
- }
954
- // 3. Build request object.
955
- const request = {
956
- kind: "conductor-launch-request",
957
- workspaceId,
958
- hostPref: ["claude", "codex", "agy"],
959
- stalled: check.stalled,
960
- reason: check.reason
961
- };
962
- // 4. Without confirm → preview only.
963
- if (!args?.confirm) {
964
- return {
965
- action: "would-emit",
966
- request,
967
- note: "DRY-RUN — pass confirm:true to emit this launch request to remote (h2a never spawns; remote does)"
968
- };
969
- }
970
- // 5. confirm=true: instance required.
971
- if (typeof args?.instance !== "string" || args.instance.length === 0) {
972
- return { error: "h2a_conductor_launch: 'instance' (self/sender) is required when confirm=true" };
973
- }
974
- const selfInstance = args.instance;
975
- // 6. Resolve remote instance.
976
- let remoteInstance;
977
- if (typeof args.remote === "string" && args.remote.length > 0) {
978
- remoteInstance = args.remote;
979
- }
980
- else {
981
- const sessions = listPresence(root);
982
- const remoteSessions = sessions.filter((s) => s.host === "remote" || (s.instance && s.instance.startsWith("remote:")));
983
- if (remoteSessions.length === 0) {
984
- return {
985
- action: "no-remote",
986
- reason: "no live remote agent to receive the launch request"
987
- };
988
- }
989
- const withPane = remoteSessions.filter((s) => s.launchContext?.tmux?.pane);
990
- const chosen = withPane.length > 0 ? withPane[0] : remoteSessions[0];
991
- remoteInstance = chosen.instance;
992
- }
993
- // 7. Compose envelope and deliver.
994
- const store = createLocalStore({ root });
995
- const envelope = createEnvelope({
996
- id: `env-conductor-launch-${Date.now().toString(36)}`,
997
- type: "event",
998
- actor: { instance: selfInstance, role: "CONDUCTOR", scope: "scope:default" },
999
- target: { instance: remoteInstance },
1000
- body: {
1001
- kind: "message",
1002
- topic: "conductor-launch-request",
1003
- text: `Conductor-launch request for workspace ${workspaceId}: ${check.reason}`,
1004
- request
1005
- },
1006
- createdAt: nowIso()
1007
- });
1008
- try {
1009
- store.putInboxMessage(remoteInstance, envelope);
1010
- }
1011
- catch (err) {
1012
- return safeError(err);
1013
- }
1014
- // 8. Record spawn marker.
1015
- recordSpawnRequest(root, {
1016
- workspaceId,
1017
- at: nowIso(),
1018
- to: remoteInstance
1019
- });
1020
- return { action: "emitted", to: remoteInstance, request };
1021
- }
1022
- export function notImplemented(toolName) {
1023
- return { error: `${toolName}: not implemented in this slice` };
1024
- }
1025
- //# sourceMappingURL=handlers.js.map