@astrosheep/keiyaku 4.5.29 → 4.6.2

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 (418) hide show
  1. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +0 -13
  2. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +47 -78
  3. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/references/automation.md +54 -41
  4. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-babysit/SKILL.md +10 -0
  5. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +27 -9
  6. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +68 -71
  7. package/build/src/akuma/akuma-call.d.ts +53 -0
  8. package/build/src/akuma/akuma-call.js +113 -0
  9. package/build/src/akuma/akuma-instance.d.ts +20 -18
  10. package/build/src/akuma/akuma-instance.js +65 -175
  11. package/build/src/akuma/akuma-observe.d.ts +3 -21
  12. package/build/src/akuma/akuma-observe.js +7 -24
  13. package/build/src/akuma/{akuma-handle.d.ts → akuma-owner.d.ts} +55 -27
  14. package/build/src/akuma/{akuma-handle.js → akuma-owner.js} +24 -23
  15. package/build/src/akuma/akuma-selection-execution.d.ts +51 -0
  16. package/build/src/akuma/akuma-selection-execution.js +134 -0
  17. package/build/src/akuma/{fleet-execution.d.ts → akuma-wait.d.ts} +24 -44
  18. package/build/src/akuma/akuma-wait.js +113 -0
  19. package/build/src/akuma/akuma.d.ts +35 -89
  20. package/build/src/akuma/akuma.js +148 -30
  21. package/build/src/akuma/archetype.d.ts +12 -0
  22. package/build/src/akuma/archetype.js +47 -19
  23. package/build/src/akuma/body.d.ts +76 -36
  24. package/build/src/akuma/body.js +84 -49
  25. package/build/src/akuma/call-initial-tell.d.ts +131 -22
  26. package/build/src/akuma/call-initial-tell.js +31 -1
  27. package/build/src/akuma/call-request.d.ts +237 -31
  28. package/build/src/akuma/call-request.js +67 -94
  29. package/build/src/akuma/coordinate.d.ts +15 -5
  30. package/build/src/akuma/coordinate.js +12 -22
  31. package/build/src/akuma/dispatch-association.d.ts +1 -1
  32. package/build/src/akuma/dispatch-association.js +1 -10
  33. package/build/src/akuma/heart/activity-schema.d.ts +325 -0
  34. package/build/src/akuma/heart/activity-schema.js +53 -0
  35. package/build/src/akuma/heart/facts.d.ts +1 -6
  36. package/build/src/akuma/heart/index.d.ts +3 -1
  37. package/build/src/akuma/heart/index.js +4 -1
  38. package/build/src/akuma/heart/rows.d.ts +49 -2
  39. package/build/src/akuma/heart/rows.js +16 -2
  40. package/build/src/akuma/heart/soul.d.ts +1 -0
  41. package/build/src/akuma/heart/soul.js +6 -4
  42. package/build/src/akuma/heart/tells.d.ts +1 -0
  43. package/build/src/akuma/heart/tells.js +18 -0
  44. package/build/src/akuma/identity.d.ts +10 -7
  45. package/build/src/akuma/identity.js +23 -0
  46. package/build/src/akuma/index.d.ts +10 -8
  47. package/build/src/akuma/index.js +2 -2
  48. package/build/src/akuma/nuke.d.ts +3 -0
  49. package/build/src/akuma/nuke.js +13 -7
  50. package/build/src/akuma/projection.d.ts +0 -5
  51. package/build/src/akuma/projection.js +22 -43
  52. package/build/src/akuma/provider-recipe.d.ts +58 -13
  53. package/build/src/akuma/provider-recipe.js +62 -80
  54. package/build/src/akuma/provider.d.ts +6 -76
  55. package/build/src/akuma/provider.js +11 -219
  56. package/build/src/akuma/providers/acp/config.d.ts +2 -0
  57. package/build/src/akuma/providers/acp/config.js +26 -1
  58. package/build/src/akuma/providers/acp/core.d.ts +7 -0
  59. package/build/src/akuma/providers/acp/core.js +49 -18
  60. package/build/src/akuma/providers/acp/index.js +14 -6
  61. package/build/src/akuma/providers/grok-build/index.js +44 -13
  62. package/build/src/akuma/providers/index.d.ts +3 -3
  63. package/build/src/akuma/providers/index.js +2 -13
  64. package/build/src/akuma/providers/opencode-sdk/event-stream.d.ts +28 -0
  65. package/build/src/akuma/providers/opencode-sdk/event-stream.js +92 -0
  66. package/build/src/akuma/providers/opencode-sdk/events.d.ts +0 -1
  67. package/build/src/akuma/providers/opencode-sdk/index.js +200 -64
  68. package/build/src/akuma/providers/opencode-sdk/session.d.ts +41 -1
  69. package/build/src/akuma/providers/opencode-sdk/session.js +69 -2
  70. package/build/src/akuma/providers/pi/events.js +5 -2
  71. package/build/src/akuma/providers/pi/index.d.ts +3 -4
  72. package/build/src/akuma/providers/pi/index.js +99 -45
  73. package/build/src/akuma/publication.d.ts +84 -3
  74. package/build/src/akuma/publication.js +145 -2
  75. package/build/src/akuma/read-pool.d.ts +2 -0
  76. package/build/src/akuma/read-pool.js +15 -0
  77. package/build/src/akuma/request-rendezvous.js +10 -0
  78. package/build/src/akuma/request-serve.js +7 -0
  79. package/build/src/akuma/request-wire.d.ts +14 -26
  80. package/build/src/akuma/request-wire.js +4 -0
  81. package/build/src/akuma/requests.d.ts +0 -2
  82. package/build/src/akuma/requests.js +0 -17
  83. package/build/src/akuma/{fleet-observation.d.ts → selection-observation.d.ts} +37 -36
  84. package/build/src/akuma/selection-observation.js +65 -0
  85. package/build/src/akuma/{fleet-owner-port.d.ts → selection-owner-port.d.ts} +3 -3
  86. package/build/src/akuma/{fleet-owner-port.js → selection-owner-port.js} +11 -17
  87. package/build/src/akuma/{fleet-request.d.ts → selection-request.d.ts} +42 -82
  88. package/build/src/akuma/{fleet-request.js → selection-request.js} +92 -136
  89. package/build/src/akuma/turn-drive.js +73 -14
  90. package/build/src/akuma-body.js +91 -56
  91. package/build/src/body/amend.d.ts +5 -0
  92. package/build/src/body/amend.js +26 -50
  93. package/build/src/body/arc.d.ts +4 -2
  94. package/build/src/body/arc.js +19 -26
  95. package/build/src/body/criteria.d.ts +6 -0
  96. package/build/src/body/criteria.js +37 -0
  97. package/build/src/body/decode.js +5 -42
  98. package/build/src/body/region.d.ts +5 -0
  99. package/build/src/body/region.js +45 -2
  100. package/build/src/body/render.js +2 -4
  101. package/build/src/cli/activity.d.ts +26 -0
  102. package/build/src/cli/activity.js +75 -0
  103. package/build/src/cli/actor.d.ts +3 -1
  104. package/build/src/cli/actor.js +15 -2
  105. package/build/src/cli/commands/akuma-grammar.d.ts +75 -0
  106. package/build/src/cli/commands/akuma-grammar.js +414 -0
  107. package/build/src/cli/commands/akuma.d.ts +5 -69
  108. package/build/src/cli/commands/akuma.js +352 -319
  109. package/build/src/cli/commands/amend.d.ts +4 -5
  110. package/build/src/cli/commands/amend.js +1 -2
  111. package/build/src/cli/commands/bind.d.ts +4 -5
  112. package/build/src/cli/commands/bind.js +7 -10
  113. package/build/src/cli/commands/contract-grammar.d.ts +112 -0
  114. package/build/src/cli/commands/contract-grammar.js +282 -0
  115. package/build/src/cli/commands/contract-help.d.ts +17 -22
  116. package/build/src/cli/commands/contract-help.js +37 -24
  117. package/build/src/cli/commands/contract.d.ts +18 -97
  118. package/build/src/cli/commands/contract.js +621 -233
  119. package/build/src/cli/commands/install.d.ts +1 -1
  120. package/build/src/cli/commands/install.js +2 -2
  121. package/build/src/cli/commands/task-grammar.d.ts +19 -0
  122. package/build/src/cli/commands/task-grammar.js +438 -0
  123. package/build/src/cli/commands/task-query.js +23 -104
  124. package/build/src/cli/commands/task.d.ts +5 -20
  125. package/build/src/cli/commands/task.js +414 -364
  126. package/build/src/cli/coordinates.d.ts +10 -0
  127. package/build/src/cli/coordinates.js +20 -0
  128. package/build/src/cli/draft.d.ts +7 -1
  129. package/build/src/cli/main.js +10 -1
  130. package/build/src/cli/parse.d.ts +8 -9
  131. package/build/src/cli/parse.js +62 -62
  132. package/build/src/cli/render/akuma-activity.d.ts +54 -36
  133. package/build/src/cli/render/akuma-activity.js +262 -242
  134. package/build/src/cli/render/akuma-tool.d.ts +8 -4
  135. package/build/src/cli/render/akuma-tool.js +6 -5
  136. package/build/src/cli/render/akuma.d.ts +36 -16
  137. package/build/src/cli/render/akuma.js +65 -132
  138. package/build/src/cli/render/audit.d.ts +6 -2
  139. package/build/src/cli/render/audit.js +59 -28
  140. package/build/src/cli/render/catalog.d.ts +11 -2
  141. package/build/src/cli/render/catalog.js +75 -95
  142. package/build/src/cli/render/contract-history.d.ts +3 -1
  143. package/build/src/cli/render/contract-history.js +215 -22
  144. package/build/src/cli/render/contract-observation.d.ts +10 -5
  145. package/build/src/cli/render/contract-observation.js +29 -46
  146. package/build/src/cli/render/contract.d.ts +10 -3
  147. package/build/src/cli/render/contract.js +252 -103
  148. package/build/src/cli/render/effects.d.ts +26 -0
  149. package/build/src/cli/render/effects.js +41 -0
  150. package/build/src/cli/render/execution-progress.d.ts +18 -6
  151. package/build/src/cli/render/execution-progress.js +34 -31
  152. package/build/src/cli/render/kanshi-akuma.d.ts +1 -2
  153. package/build/src/cli/render/kanshi-akuma.js +5 -26
  154. package/build/src/cli/render/kanshi.js +107 -128
  155. package/build/src/cli/render/marks.d.ts +13 -0
  156. package/build/src/cli/render/marks.js +74 -0
  157. package/build/src/cli/render/nuke.js +18 -7
  158. package/build/src/cli/render/receipt.d.ts +10 -4
  159. package/build/src/cli/render/receipt.js +124 -44
  160. package/build/src/cli/render/reconcile.d.ts +5 -0
  161. package/build/src/cli/render/reconcile.js +152 -0
  162. package/build/src/cli/render/refusal.d.ts +21 -4
  163. package/build/src/cli/render/refusal.js +60 -33
  164. package/build/src/cli/render/region.js +3 -2
  165. package/build/src/cli/render/settings.js +2 -12
  166. package/build/src/cli/render/task.d.ts +37 -6
  167. package/build/src/cli/render/task.js +161 -157
  168. package/build/src/cli/render/terminal.d.ts +20 -1
  169. package/build/src/cli/render/terminal.js +92 -18
  170. package/build/src/cli/runtime.d.ts +32 -8
  171. package/build/src/cli/runtime.js +157 -165
  172. package/build/src/cli/selectors.d.ts +5 -2
  173. package/build/src/cli/selectors.js +11 -3
  174. package/build/src/cli/streams.d.ts +11 -0
  175. package/build/src/cli/streams.js +32 -0
  176. package/build/src/cli/usage.d.ts +2 -0
  177. package/build/src/cli/usage.js +12 -8
  178. package/build/src/contract-guidance.js +3 -7
  179. package/build/src/contract-worktree.d.ts +20 -28
  180. package/build/src/contract-worktree.js +18 -70
  181. package/build/src/coordination/durable-file.d.ts +2 -2
  182. package/build/src/coordination/durable-file.js +0 -27
  183. package/build/src/core/facts/codec.d.ts +1 -2
  184. package/build/src/core/facts/codec.js +6 -7
  185. package/build/src/core/facts/gate.d.ts +0 -1
  186. package/build/src/core/facts/gate.js +0 -82
  187. package/build/src/core/facts/types.d.ts +1 -2
  188. package/build/src/core/verbs/abandon.d.ts +2 -6
  189. package/build/src/core/verbs/abandon.js +0 -16
  190. package/build/src/core/verbs/amend.d.ts +0 -1
  191. package/build/src/core/verbs/amend.js +0 -20
  192. package/build/src/core/verbs/arc.d.ts +7 -8
  193. package/build/src/core/verbs/arc.js +2 -19
  194. package/build/src/core/verbs/attestation.d.ts +2 -6
  195. package/build/src/core/verbs/attestation.js +0 -16
  196. package/build/src/core/verbs/bind.d.ts +0 -1
  197. package/build/src/core/verbs/bind.js +0 -16
  198. package/build/src/core/verbs/deliver.d.ts +0 -1
  199. package/build/src/core/verbs/deliver.js +0 -16
  200. package/build/src/core/verbs/placement.d.ts +2 -1
  201. package/build/src/core/verbs/placement.js +10 -59
  202. package/build/src/git/admission.d.ts +6 -4
  203. package/build/src/git/admission.js +4 -0
  204. package/build/src/git/hooks.d.ts +55 -30
  205. package/build/src/git/hooks.js +30 -3
  206. package/build/src/git/identity.d.ts +6 -0
  207. package/build/src/git/identity.js +47 -0
  208. package/build/src/git/integration.d.ts +31 -13
  209. package/build/src/git/integration.js +32 -1
  210. package/build/src/git/nuke.d.ts +10 -1
  211. package/build/src/git/nuke.js +31 -11
  212. package/build/src/git/observe.js +2 -15
  213. package/build/src/git/private-state-seat.d.ts +6 -7
  214. package/build/src/git/private-state-seat.js +8 -6
  215. package/build/src/git/read-observation.d.ts +6 -1
  216. package/build/src/git/read-observation.js +81 -46
  217. package/build/src/git/reconcile.d.ts +117 -40
  218. package/build/src/git/reconcile.js +169 -40
  219. package/build/src/git/scratch.d.ts +7 -4
  220. package/build/src/git/scratch.js +28 -6
  221. package/build/src/git/target-placement.d.ts +53 -38
  222. package/build/src/git/target-placement.js +69 -54
  223. package/build/src/git/tender.d.ts +37 -28
  224. package/build/src/git/tender.js +39 -0
  225. package/build/src/git/terminal-reconcile.js +21 -23
  226. package/build/src/git/terminal-seal.d.ts +8 -6
  227. package/build/src/git/terminal-seal.js +10 -0
  228. package/build/src/git/workspace.d.ts +29 -15
  229. package/build/src/git/workspace.js +28 -2
  230. package/build/src/identity/normalize.js +19 -6
  231. package/build/src/index.d.ts +78 -7
  232. package/build/src/index.js +52 -4
  233. package/build/src/kanshi/read.d.ts +3 -3
  234. package/build/src/kanshi/read.js +21 -21
  235. package/build/src/kanshi/report.d.ts +9 -8
  236. package/build/src/kanshi/roster.d.ts +2 -0
  237. package/build/src/kanshi/roster.js +2 -0
  238. package/build/src/kanshi/select.js +7 -3
  239. package/build/src/library/address.d.ts +3 -7
  240. package/build/src/library/address.js +7 -7
  241. package/build/src/library/akuma-creation.d.ts +21 -32
  242. package/build/src/library/akuma-creation.js +148 -165
  243. package/build/src/library/akumas.d.ts +20 -22
  244. package/build/src/library/akumas.js +43 -20
  245. package/build/src/library/bind.d.ts +107 -13
  246. package/build/src/library/bind.js +29 -23
  247. package/build/src/library/continuation.d.ts +556 -28
  248. package/build/src/library/continuation.js +29 -54
  249. package/build/src/library/contract-composition.d.ts +40 -0
  250. package/build/src/library/contract-composition.js +105 -0
  251. package/build/src/library/contract-creation.d.ts +7 -0
  252. package/build/src/library/contract-creation.js +192 -0
  253. package/build/src/library/contract-execution.d.ts +29 -40
  254. package/build/src/library/contract-execution.js +503 -128
  255. package/build/src/library/contract-operations.d.ts +275 -134
  256. package/build/src/library/contract-operations.js +83 -92
  257. package/build/src/library/contract-outcomes.d.ts +71 -0
  258. package/build/src/library/contract-outcomes.js +32 -0
  259. package/build/src/library/contract-settings.d.ts +25 -0
  260. package/build/src/library/contract-settings.js +135 -0
  261. package/build/src/library/contract-types.d.ts +17 -38
  262. package/build/src/library/delivery.d.ts +530 -10
  263. package/build/src/library/delivery.js +20 -45
  264. package/build/src/library/input.d.ts +3 -1
  265. package/build/src/library/input.js +11 -16
  266. package/build/src/library/invocation.d.ts +87 -0
  267. package/build/src/library/invocation.js +290 -0
  268. package/build/src/library/keiyaku.d.ts +45 -22
  269. package/build/src/library/keiyaku.js +134 -8
  270. package/build/src/library/nuke.d.ts +2 -11
  271. package/build/src/library/nuke.js +70 -57
  272. package/build/src/library/outcome.d.ts +13196 -0
  273. package/build/src/library/outcome.js +487 -0
  274. package/build/src/library/reconcile.d.ts +96 -24
  275. package/build/src/library/reconcile.js +102 -42
  276. package/build/src/library/refusal.d.ts +470 -42
  277. package/build/src/library/refusal.js +55 -143
  278. package/build/src/library/region.d.ts +15 -7
  279. package/build/src/library/region.js +23 -3
  280. package/build/src/library/repo.d.ts +2 -12
  281. package/build/src/library/repo.js +1 -22
  282. package/build/src/library/selection.d.ts +121 -0
  283. package/build/src/library/{fleet.js → selection.js} +169 -152
  284. package/build/src/plugin/public.d.ts +2 -0
  285. package/build/src/protocol/abandon.d.ts +2 -2
  286. package/build/src/protocol/abandon.js +1 -0
  287. package/build/src/protocol/amend.js +1 -0
  288. package/build/src/protocol/arc.d.ts +6 -4
  289. package/build/src/protocol/attempt.d.ts +4 -2
  290. package/build/src/protocol/attempt.js +10 -0
  291. package/build/src/protocol/audit.d.ts +255 -52
  292. package/build/src/protocol/audit.js +63 -5
  293. package/build/src/protocol/bind.d.ts +18 -17
  294. package/build/src/protocol/bind.js +9 -28
  295. package/build/src/protocol/completion.d.ts +256 -22
  296. package/build/src/protocol/completion.js +100 -12
  297. package/build/src/protocol/deliver.d.ts +34 -23
  298. package/build/src/protocol/deliver.js +39 -25
  299. package/build/src/protocol/execution-observation.d.ts +36 -37
  300. package/build/src/protocol/execution-observation.js +7 -9
  301. package/build/src/protocol/intent.d.ts +101 -30
  302. package/build/src/protocol/intent.js +74 -1
  303. package/build/src/protocol/operations.d.ts +570 -64
  304. package/build/src/protocol/operations.js +189 -9
  305. package/build/src/protocol/outcome.d.ts +2 -1
  306. package/build/src/protocol/placement.d.ts +2 -2
  307. package/build/src/protocol/placement.js +3 -1
  308. package/build/src/protocol/progress.d.ts +108 -65
  309. package/build/src/protocol/progress.js +82 -132
  310. package/build/src/protocol/read/status.d.ts +4 -3
  311. package/build/src/protocol/read/status.js +6 -5
  312. package/build/src/protocol/reconcile.d.ts +3 -3
  313. package/build/src/protocol/reconcile.js +4 -0
  314. package/build/src/protocol/reintegrate.d.ts +2 -2
  315. package/build/src/protocol/review.d.ts +30 -12
  316. package/build/src/protocol/review.js +15 -24
  317. package/build/src/protocol/run.d.ts +34 -5
  318. package/build/src/protocol/run.js +24 -12
  319. package/build/src/runtime/proc/windows-launch.exe +0 -0
  320. package/build/src/settings.d.ts +0 -10
  321. package/build/src/settings.js +0 -76
  322. package/build/src/settlement/holder.d.ts +1 -1
  323. package/build/src/settlement/settle.d.ts +25 -16
  324. package/build/src/settlement/settle.js +80 -20
  325. package/build/src/task/board.d.ts +3 -1
  326. package/build/src/task/board.js +13 -17
  327. package/build/src/task/catalog.d.ts +0 -4
  328. package/build/src/task/catalog.js +0 -15
  329. package/build/src/task/compose-language.d.ts +19 -9
  330. package/build/src/task/compose-language.js +30 -20
  331. package/build/src/task/compose.d.ts +7 -37
  332. package/build/src/task/compose.js +20 -2
  333. package/build/src/task/created-observation.d.ts +0 -1
  334. package/build/src/task/created-observation.js +1 -4
  335. package/build/src/task/document.d.ts +12 -2
  336. package/build/src/task/document.js +4 -0
  337. package/build/src/task/identity.d.ts +4 -1
  338. package/build/src/task/identity.js +21 -17
  339. package/build/src/task/index.d.ts +36 -16
  340. package/build/src/task/index.js +103 -96
  341. package/build/src/task/lifecycle-operations.d.ts +1 -1
  342. package/build/src/task/mutation-result.d.ts +647 -586
  343. package/build/src/task/mutation-result.js +79 -46
  344. package/build/src/task/mutation.d.ts +298 -270
  345. package/build/src/task/mutation.js +93 -110
  346. package/build/src/task/operation-types.d.ts +6 -49
  347. package/build/src/task/operations.d.ts +2 -1
  348. package/build/src/task/operations.js +35 -12
  349. package/build/src/task/query.d.ts +9 -3
  350. package/build/src/task/query.js +42 -16
  351. package/build/src/task/store.d.ts +2 -1
  352. package/build/src/task/store.js +10 -14
  353. package/build/src/verification/declaration.d.ts +0 -1
  354. package/build/src/verification/declaration.js +1 -18
  355. package/build/src/verification/execution.d.ts +6 -2
  356. package/build/src/verification/observation.d.ts +1 -1
  357. package/package.json +2 -18
  358. package/build/src/akuma/akuma-product.d.ts +0 -58
  359. package/build/src/akuma/akuma-product.js +0 -276
  360. package/build/src/akuma/fleet-execution.js +0 -234
  361. package/build/src/akuma/fleet-observation.js +0 -97
  362. package/build/src/cli/accepted.d.ts +0 -24
  363. package/build/src/cli/accepted.js +0 -167
  364. package/build/src/cli/catalog.d.ts +0 -45
  365. package/build/src/cli/catalog.js +0 -1
  366. package/build/src/cli/commands/akuma-invoke.d.ts +0 -114
  367. package/build/src/cli/commands/akuma-invoke.js +0 -375
  368. package/build/src/cli/commands/contract-invoke.d.ts +0 -34
  369. package/build/src/cli/commands/contract-invoke.js +0 -259
  370. package/build/src/cli/commands/nuke.d.ts +0 -10
  371. package/build/src/cli/commands/nuke.js +0 -20
  372. package/build/src/cli/commands/status-set.d.ts +0 -4
  373. package/build/src/cli/commands/status-set.js +0 -52
  374. package/build/src/cli/commands/task-invoke.d.ts +0 -49
  375. package/build/src/cli/commands/task-invoke.js +0 -306
  376. package/build/src/cli/invoke.d.ts +0 -27
  377. package/build/src/cli/invoke.js +0 -521
  378. package/build/src/cli/render/board.d.ts +0 -3
  379. package/build/src/cli/render/board.js +0 -25
  380. package/build/src/cli/render/status-set.d.ts +0 -5
  381. package/build/src/cli/render/status-set.js +0 -19
  382. package/build/src/cli/render/text.d.ts +0 -3
  383. package/build/src/cli/render/text.js +0 -33
  384. package/build/src/cli/result.d.ts +0 -240
  385. package/build/src/cli/result.js +0 -1
  386. package/build/src/git/result-codec.d.ts +0 -29
  387. package/build/src/git/result-codec.js +0 -309
  388. package/build/src/kanshi/fleet.d.ts +0 -6
  389. package/build/src/kanshi/fleet.js +0 -27
  390. package/build/src/library/audit.d.ts +0 -29
  391. package/build/src/library/audit.js +0 -41
  392. package/build/src/library/composition.d.ts +0 -15
  393. package/build/src/library/composition.js +0 -28
  394. package/build/src/library/configuration.d.ts +0 -4
  395. package/build/src/library/configuration.js +0 -2
  396. package/build/src/library/contract-bind.d.ts +0 -31
  397. package/build/src/library/contract-bind.js +0 -140
  398. package/build/src/library/contract-forwarding.d.ts +0 -55
  399. package/build/src/library/contract-forwarding.js +0 -67
  400. package/build/src/library/contract-handle.d.ts +0 -50
  401. package/build/src/library/contract-handle.js +0 -385
  402. package/build/src/library/contract.d.ts +0 -46
  403. package/build/src/library/contract.js +0 -73
  404. package/build/src/library/execution-result.d.ts +0 -243
  405. package/build/src/library/execution-result.js +0 -101
  406. package/build/src/library/execution.d.ts +0 -8
  407. package/build/src/library/execution.js +0 -102
  408. package/build/src/library/fleet.d.ts +0 -83
  409. package/build/src/library/mutation.d.ts +0 -501
  410. package/build/src/library/mutation.js +0 -248
  411. package/build/src/library/result-codec.d.ts +0 -2
  412. package/build/src/library/result-codec.js +0 -12
  413. package/build/src/protocol/result-codec.d.ts +0 -23
  414. package/build/src/protocol/result-codec.js +0 -488
  415. package/build/src/settlement/result-codec.d.ts +0 -2
  416. package/build/src/settlement/result-codec.js +0 -56
  417. package/build/src/task/public.d.ts +0 -2
  418. package/build/src/task/public.js +0 -1
@@ -0,0 +1,92 @@
1
+ /**
2
+ * A backoff sleep that resolves when the owned signal aborts and always clears
3
+ * its timer. Cancellation before the sleep starts completes immediately, and a
4
+ * simultaneous timeout and abort still settles once and drops the listener.
5
+ */
6
+ function cancellableSleep(signal) {
7
+ return (milliseconds) => new Promise((resolve) => {
8
+ if (signal.aborted) {
9
+ resolve();
10
+ return;
11
+ }
12
+ let timer;
13
+ const finish = () => {
14
+ if (timer !== undefined)
15
+ clearTimeout(timer);
16
+ signal.removeEventListener("abort", finish);
17
+ resolve();
18
+ };
19
+ timer = setTimeout(finish, milliseconds);
20
+ signal.addEventListener("abort", finish, { once: true });
21
+ });
22
+ }
23
+ export function ownEventStream(input) {
24
+ const controller = new AbortController();
25
+ const follow = () => {
26
+ if (!controller.signal.aborted)
27
+ controller.abort(input.signal.reason);
28
+ };
29
+ input.signal.addEventListener("abort", follow, { once: true });
30
+ if (input.signal.aborted)
31
+ follow();
32
+ let iterator;
33
+ let pending;
34
+ let settling;
35
+ let ready;
36
+ let subscribed;
37
+ // Retirement may be requested the moment custody owns this stream, so it
38
+ // waits for the one subscription call rather than reaching an unset value.
39
+ const subscribing = new Promise((resolve) => {
40
+ subscribed = resolve;
41
+ });
42
+ let settleClosed;
43
+ let rejectClosed;
44
+ const closed = new Promise((resolve, reject) => {
45
+ settleClosed = resolve;
46
+ rejectClosed = reject;
47
+ });
48
+ const retire = () => {
49
+ if (settling !== undefined)
50
+ return settling;
51
+ settling = (async () => {
52
+ // Abort first: it interrupts the SDK's fetch, reader, and backoff and
53
+ // settles a pending read, before iterator return can be waited on.
54
+ if (!controller.signal.aborted)
55
+ controller.abort(new Error("OpenCode event stream retired"));
56
+ input.signal.removeEventListener("abort", follow);
57
+ await subscribing;
58
+ await ready.catch(() => undefined);
59
+ const reading = pending;
60
+ if (reading !== undefined)
61
+ await reading.catch(() => undefined);
62
+ if (iterator?.return !== undefined)
63
+ await iterator.return(undefined);
64
+ })();
65
+ settling.then(settleClosed, rejectClosed);
66
+ return settling;
67
+ };
68
+ // The owner is registered before native subscription setup begins, so
69
+ // resources arriving after cancellation are still owned and retired.
70
+ input.custody?.own({ closed, abort: retire, forceDispose: retire });
71
+ ready = (async () => {
72
+ const subscription = await input.subscribe({
73
+ directory: input.directory,
74
+ signal: controller.signal,
75
+ sleep: cancellableSleep(controller.signal),
76
+ });
77
+ iterator = subscription.stream[Symbol.asyncIterator]();
78
+ })();
79
+ subscribed();
80
+ void ready.catch(() => undefined);
81
+ return {
82
+ ready,
83
+ next: () => {
84
+ const reading = ready.then(() => iterator.next());
85
+ pending = reading;
86
+ void reading.catch(() => undefined);
87
+ return reading;
88
+ },
89
+ retire,
90
+ closed,
91
+ };
92
+ }
@@ -49,6 +49,5 @@ export declare const OPENCODE_EVENT_DISPOSITIONS: {
49
49
  readonly "server.connected": "dropped";
50
50
  };
51
51
  export declare function mapEvent(value: unknown, events: Emitter, state: State): void;
52
- export type EventState = State;
53
52
  export declare function createEventState(sessionId?: string): State;
54
53
  export {};
@@ -1,7 +1,7 @@
1
- import { randomUUID } from "node:crypto";
2
1
  import { AgentEventChannel, createProviderAttempt, } from "../../provider.js";
2
+ import { ownEventStream } from "./event-stream.js";
3
3
  import { createEventState, mapEvent } from "./events.js";
4
- import { coordinate, loadOpencode, OPENCODE_SDK_PROVIDER, parseModel } from "./session.js";
4
+ import { coordinate, loadOpencode, messageId, OPENCODE_SDK_PROVIDER, parseModel, } from "./session.js";
5
5
  function object(value) {
6
6
  return value !== null && typeof value === "object" && !Array.isArray(value)
7
7
  ? value
@@ -70,7 +70,7 @@ function newest(rows) {
70
70
  return row;
71
71
  const at = Number(object(row.info.time)?.created ?? 0);
72
72
  const latestAt = Number(object(latest.info.time)?.created ?? 0);
73
- return at >= latestAt ? row : latest;
73
+ return at > latestAt || (at === latestAt && String(row.info.id) > String(latest.info.id)) ? row : latest;
74
74
  }, undefined);
75
75
  }
76
76
  async function readTurnResult(input) {
@@ -83,9 +83,9 @@ async function readTurnResult(input) {
83
83
  const rows = messageRows(response, input.sessionId);
84
84
  const user = rows.find((row) => row.info.role === "user" && row.info.id === input.messageID);
85
85
  if (user === undefined)
86
- return undefined;
87
- const userId = text(user?.info.id);
88
- const assistant = newest(rows.filter((row) => row.info.role === "assistant" && row.info.parentID === userId));
86
+ return { kind: "failed", diagnostic: "OpenCode completed without the admitted user message" };
87
+ const userId = text(user.info.id);
88
+ const assistant = newest(rows.filter((row) => row.info.role === "assistant" && row.info.parentID === userId && row.info.summary !== true));
89
89
  const historyId = text(assistant?.info.id);
90
90
  if (input.state.failure !== undefined)
91
91
  return { kind: "failed", diagnostic: input.state.failure };
@@ -119,10 +119,6 @@ function scopedProperties(value, sessionId) {
119
119
  const properties = object(object(value)?.properties);
120
120
  return nativeSessionId(value) === sessionId ? properties : undefined;
121
121
  }
122
- function stopIterator(iterator) {
123
- const stopped = iterator?.return?.(undefined);
124
- void stopped?.catch(() => undefined);
125
- }
126
122
  function nativeProgress(type, properties, busy) {
127
123
  if (type === "session.idle")
128
124
  return { busy, terminal: busy };
@@ -137,48 +133,122 @@ function startsTurn(value, sessionId, messageID) {
137
133
  const info = object(object(event?.properties)?.info);
138
134
  return (event?.type === "message.updated" && info?.sessionID === sessionId && info.role === "user" && info.id === messageID);
139
135
  }
136
+ function recognizeAdmission(value, sessionId, admission) {
137
+ const event = object(value);
138
+ const properties = object(event?.properties);
139
+ const info = object(properties?.info);
140
+ if (event?.type === "message.updated" &&
141
+ info?.sessionID === sessionId &&
142
+ info.role === "user" &&
143
+ typeof info.id === "string") {
144
+ admission.admit(info.id);
145
+ }
146
+ }
147
+ function observeEvent(input) {
148
+ const observedSessionId = nativeSessionId(input.value);
149
+ if (observedSessionId !== undefined && observedSessionId !== input.sessionId) {
150
+ return { active: input.active, busy: input.busy, terminal: false };
151
+ }
152
+ const event = object(input.value);
153
+ const properties = scopedProperties(input.value, input.sessionId);
154
+ if (properties === undefined) {
155
+ if (input.active)
156
+ mapEvent(input.value, input.events, input.state);
157
+ return { active: input.active, busy: input.busy, terminal: false };
158
+ }
159
+ const starts = !input.active && startsTurn(input.value, input.sessionId, input.messageID);
160
+ const active = input.active || starts;
161
+ const busy = starts ? false : input.busy;
162
+ recognizeAdmission(input.value, input.sessionId, input.admission);
163
+ const submittedError = event?.type === "session.error" && input.submissionState.started;
164
+ if (!active && !submittedError)
165
+ return { active, busy, terminal: false };
166
+ mapEvent(input.value, input.events, input.state);
167
+ if (event?.type === "session.error") {
168
+ input.admission.end();
169
+ return {
170
+ active,
171
+ busy,
172
+ terminal: true,
173
+ result: { kind: "failed", diagnostic: input.state.failure ?? diagnostic(properties.error) },
174
+ };
175
+ }
176
+ const progress = nativeProgress(event?.type, properties, busy);
177
+ return { active, busy: progress.busy, terminal: progress.terminal };
178
+ }
140
179
  async function observeTurn(input) {
141
180
  let active = false;
142
181
  let busy = false;
143
182
  try {
144
183
  for (;;) {
145
- const next = await input.iterator.next();
184
+ const next = await input.stream.next();
146
185
  if (next.done)
147
186
  return { kind: "failed", diagnostic: "OpenCode event stream ended before Turn completion" };
148
- const value = eventValue(next.value);
149
- const observedSessionId = nativeSessionId(value);
150
- if (observedSessionId !== undefined && observedSessionId !== input.sessionId)
151
- continue;
152
- const event = object(value);
153
- const properties = scopedProperties(value, input.sessionId);
154
- if (properties === undefined) {
155
- if (active)
156
- mapEvent(value, input.events, input.state);
157
- continue;
158
- }
159
- if (startsTurn(value, input.sessionId, input.messageID)) {
160
- active = true;
161
- busy = false;
162
- }
163
- const submittedError = event?.type === "session.error" && input.submissionState.started;
164
- if (!active && !submittedError)
165
- continue;
166
- mapEvent(value, input.events, input.state);
167
- if (event?.type === "session.error") {
168
- return { kind: "failed", diagnostic: input.state.failure ?? diagnostic(properties.error) };
169
- }
170
- const progress = nativeProgress(event?.type, properties, busy);
171
- busy = progress.busy;
172
- if (!progress.terminal)
187
+ const observed = observeEvent({
188
+ value: eventValue(next.value),
189
+ sessionId: input.sessionId,
190
+ messageID: input.messageID,
191
+ active,
192
+ busy,
193
+ admission: input.admission,
194
+ events: input.events,
195
+ state: input.state,
196
+ submissionState: input.submissionState,
197
+ });
198
+ active = observed.active;
199
+ busy = observed.busy;
200
+ if (observed.result !== undefined)
201
+ return observed.result;
202
+ if (!observed.terminal)
173
203
  continue;
174
- const result = await readTurnResult(input);
175
- if (result !== undefined)
176
- return result;
204
+ input.admission.end();
205
+ return await readTurnResult({ ...input, messageID: input.admission.latest() });
177
206
  }
178
207
  }
179
208
  catch (error) {
180
209
  return { kind: "failed", diagnostic: `OpenCode event stream failed: ${diagnostic(error)}` };
181
210
  }
211
+ finally {
212
+ input.admission.end();
213
+ }
214
+ }
215
+ function liveAdmission(initial) {
216
+ let latest = initial;
217
+ let ended = false;
218
+ const pending = new Map();
219
+ const wait = (id) => {
220
+ if (ended)
221
+ return Promise.resolve({ kind: "turn-ended" });
222
+ return new Promise((resolve, reject) => {
223
+ pending.set(id, { resolve, reject });
224
+ });
225
+ };
226
+ return {
227
+ initial: wait(initial),
228
+ latest: () => latest,
229
+ open: () => !ended,
230
+ wait,
231
+ admit(id) {
232
+ const waiter = pending.get(id);
233
+ if (waiter === undefined || ended)
234
+ return;
235
+ pending.delete(id);
236
+ latest = id;
237
+ waiter.resolve({ kind: "accepted", fence: id });
238
+ },
239
+ fail(id, error) {
240
+ pending.get(id)?.reject(error);
241
+ pending.delete(id);
242
+ },
243
+ end() {
244
+ if (ended)
245
+ return;
246
+ ended = true;
247
+ for (const waiter of pending.values())
248
+ waiter.resolve({ kind: "turn-ended" });
249
+ pending.clear();
250
+ },
251
+ };
182
252
  }
183
253
  function terminalSettlement(events, close) {
184
254
  let finish;
@@ -186,8 +256,14 @@ function terminalSettlement(events, close) {
186
256
  let settlement;
187
257
  finish = (result) => {
188
258
  settlement ??= (async () => {
189
- events.end();
259
+ // Whole closure is proved before narration ends. The driver therefore
260
+ // stays inside its Heart/control observation race while retirement is
261
+ // outstanding, so a rejected or unprovable closure still reaches attempt
262
+ // custody's bounded hung handling instead of parking on a pending
263
+ // completion. Ending narration first would move that await outside the
264
+ // driver's race and make the Body unresponsive to stop or Heart loss.
190
265
  await close();
266
+ events.end();
191
267
  resolve(result);
192
268
  })();
193
269
  return settlement;
@@ -195,6 +271,18 @@ function terminalSettlement(events, close) {
195
271
  });
196
272
  return { completion, finish };
197
273
  }
274
+ /**
275
+ * One memoized whole-close: stream retirement and existing server retirement
276
+ * start together on every terminal path, so a live socket can never outwait the
277
+ * server's death.
278
+ */
279
+ function wholeClosure(retireStream, closeServer) {
280
+ let closing;
281
+ return () => {
282
+ closing ??= Promise.all([retireStream(), closeServer()]).then(() => undefined);
283
+ return closing;
284
+ };
285
+ }
198
286
  async function forceDisposeOpencode(abortController, close, finish) {
199
287
  abortController.abort();
200
288
  await close();
@@ -245,6 +333,46 @@ async function openDriveSession(runtime, input, resumeSessionId, signal) {
245
333
  throw new Error("OpenCode did not return a session id");
246
334
  return { session, sessionId };
247
335
  }
336
+ function createLiveSession(input) {
337
+ let submissions = input.admission.initial.then(() => undefined);
338
+ const submit = (tell) => {
339
+ const submission = async () => {
340
+ if (!input.admission.open())
341
+ return { kind: "turn-ended" };
342
+ const receipt = input.admission.wait(tell.id);
343
+ void input.session
344
+ .promptAsync({
345
+ path: { id: input.sessionId },
346
+ query: { directory: input.cwd },
347
+ body: input.promptBody(tell.id, tell.text),
348
+ throwOnError: true,
349
+ })
350
+ .catch((error) => input.admission.fail(tell.id, error));
351
+ return await receipt;
352
+ };
353
+ const next = submissions.then(submission);
354
+ submissions = next.then(() => undefined, () => undefined);
355
+ return next;
356
+ };
357
+ return {
358
+ admission: { fence: input.sessionId },
359
+ events: input.events,
360
+ completion: input.completion,
361
+ tell: (tell) => submit({ ...tell, id: input.nextMessageId() }),
362
+ abort: async () => {
363
+ input.admission.end();
364
+ input.abortController.abort();
365
+ void input.session
366
+ .abort({ path: { id: input.sessionId }, query: { directory: input.cwd }, throwOnError: true })
367
+ .catch(() => undefined);
368
+ await input.finish({ kind: "failed", diagnostic: "OpenCode session interrupted" });
369
+ },
370
+ forceDispose: () => {
371
+ input.admission.end();
372
+ return forceDisposeOpencode(input.abortController, input.close, input.finish);
373
+ },
374
+ };
375
+ }
248
376
  async function drive(execution, input, loader, custody) {
249
377
  admit(input.options);
250
378
  const signal = input.signal ?? new AbortController().signal;
@@ -257,27 +385,34 @@ async function drive(execution, input, loader, custody) {
257
385
  const runtime = await loadDriveRuntime(execution, input, abortController.signal, loader, (ready) => {
258
386
  closeOnce = ownRuntime(custody, ready);
259
387
  });
260
- let iterator;
388
+ const stream = ownEventStream({
389
+ directory: input.cwd,
390
+ signal: abortController.signal,
391
+ ...(custody === undefined ? {} : { custody }),
392
+ subscribe: (request) => runtime.client.event.subscribe(request),
393
+ });
394
+ const wholeClose = wholeClosure(() => stream.retire(), () => closeOnce());
261
395
  try {
262
396
  const { session, sessionId } = await openDriveSession(runtime, input, resumeSessionId, abortController.signal);
263
397
  const events = new AgentEventChannel();
264
398
  const state = createEventState(sessionId);
265
- const messageID = `msg_${randomUUID().replaceAll("-", "")}`;
399
+ const messageSequence = { value: 0 };
400
+ const nextMessageId = () => messageId(messageSequence.value++);
401
+ const messageID = nextMessageId();
402
+ const admission = liveAdmission(messageID);
266
403
  const submissionState = { started: false };
267
404
  events.emit({ type: "session", coordinate: coordinate(sessionId) });
268
- const streamResult = await runtime.client.event.subscribe({ query: { directory: input.cwd } });
269
- if (abortController.signal.aborted) {
270
- await streamResult.stream[Symbol.asyncIterator]().return?.(undefined);
405
+ await stream.ready;
406
+ if (abortController.signal.aborted)
271
407
  abortController.signal.throwIfAborted();
272
- }
273
- iterator = streamResult.stream[Symbol.asyncIterator]();
274
- const { completion, finish } = terminalSettlement(events, closeOnce);
408
+ const { completion, finish } = terminalSettlement(events, wholeClose);
275
409
  const observation = observeTurn({
276
- iterator,
410
+ stream,
277
411
  session,
278
412
  sessionId,
279
413
  cwd: input.cwd,
280
414
  messageID,
415
+ admission,
281
416
  events,
282
417
  state,
283
418
  submissionState,
@@ -290,26 +425,27 @@ async function drive(execution, input, loader, custody) {
290
425
  throwOnError: true,
291
426
  });
292
427
  abortController.signal.throwIfAborted();
293
- void observation.then(finish);
294
- signal.removeEventListener("abort", abortSetup);
295
- return {
296
- admission: { fence: sessionId },
428
+ // The observer never awaits its own completion: finishing retires the whole
429
+ // stream, but the observer that invoked finish stays outside that wait. Its
430
+ // rejection is owned by attempt custody, not by an unobserved promise.
431
+ void observation.then(finish).catch(() => undefined);
432
+ return createLiveSession({
433
+ session,
434
+ sessionId,
435
+ cwd: input.cwd,
436
+ promptBody: (messageID, text) => promptBody({ ...input, body: text, launchTells: [] }, messageID),
437
+ admission,
438
+ nextMessageId,
297
439
  events,
298
440
  completion,
299
- abort: async () => {
300
- abortController.abort();
301
- void session
302
- .abort({ path: { id: sessionId }, query: { directory: input.cwd }, throwOnError: true })
303
- .catch(() => undefined);
304
- await finish({ kind: "failed", diagnostic: "OpenCode session interrupted" });
305
- },
306
- forceDispose: () => forceDisposeOpencode(abortController, closeOnce, finish),
307
- };
441
+ abortController,
442
+ close: wholeClose,
443
+ finish,
444
+ });
308
445
  }
309
446
  catch (error) {
310
447
  signal.removeEventListener("abort", abortSetup);
311
- stopIterator(iterator);
312
- await closeOnce();
448
+ await wholeClose();
313
449
  throw error;
314
450
  }
315
451
  }
@@ -2,7 +2,24 @@ import type { OpencodeClient } from "@opencode-ai/sdk";
2
2
  import type { ResumeCoordinate } from "../../heart/index.js";
3
3
  import type { ProviderExecution } from "../../provider-recipe.js";
4
4
  export type OpencodeSdkSession = Pick<OpencodeClient["session"], "create" | "get" | "fork" | "abort" | "promptAsync" | "messages">;
5
- export type OpencodeSdkEvent = Pick<OpencodeClient["event"], "subscribe">;
5
+ /**
6
+ * The adapter's own event subscription port. It carries the cancellation signal
7
+ * and the cancellable retry backoff the installed client honors at runtime,
8
+ * without naming the SDK's generated request type at the call site.
9
+ */
10
+ export type OpencodeEventSubscriptionRequest = Readonly<{
11
+ directory: string;
12
+ /** Cancels the subscription's fetch, reader, and retry waiting. */
13
+ signal: AbortSignal;
14
+ /** Resolves without rejecting when `signal` aborts, and always clears its timer. */
15
+ sleep(milliseconds: number): Promise<void>;
16
+ }>;
17
+ type OpencodeEventSubscription = Readonly<{
18
+ stream: AsyncIterable<unknown>;
19
+ }>;
20
+ export type OpencodeSdkEvent = Readonly<{
21
+ subscribe(request: OpencodeEventSubscriptionRequest): Promise<OpencodeEventSubscription>;
22
+ }>;
6
23
  export type OpencodeSdkLoader = (cwd: string, execution: ProviderExecution, signal: AbortSignal) => Promise<Readonly<{
7
24
  client: {
8
25
  session: OpencodeSdkSession;
@@ -12,10 +29,32 @@ export type OpencodeSdkLoader = (cwd: string, execution: ProviderExecution, sign
12
29
  ready?: Promise<void>;
13
30
  }>>;
14
31
  export declare const OPENCODE_SDK_PROVIDER: "opencode-sdk";
32
+ /**
33
+ * Adapt the installed client's generated event endpoint to the adapter's
34
+ * subscription port.
35
+ *
36
+ * The generated per-endpoint `Options` type omits the SDK's runtime
37
+ * `sseSleepFn` option even though the client forwards every per-request key
38
+ * into `createSseClient`, so a caller cannot express a cancellable backoff
39
+ * through the published type. Declaring the port here keeps that one typing gap
40
+ * and its single adaptation at the SDK seam: no other module repeats a cast,
41
+ * the SDK's own parser and retry policy stay untouched, and an injected loader
42
+ * supplies the same port shape.
43
+ */
44
+ export declare function opencodeEventPort(event: OpencodeClient["event"]): OpencodeSdkEvent;
45
+ export declare function messageId(sequence?: number): string;
15
46
  export declare function parseModel(model: string): Readonly<{
16
47
  providerID: string;
17
48
  modelID: string;
18
49
  }>;
50
+ /**
51
+ * Compose the config handed to a headless opencode server. The permission base
52
+ * layer fills only the classes the caller leaves unspecified: an explicit caller
53
+ * permission key wins per key and every non-permission key passes through
54
+ * untouched. A caller that supplies a non-object `permission` shorthand states
55
+ * the whole policy and keeps it.
56
+ */
57
+ export declare function composeHeadlessPermissionConfig(config?: Readonly<Record<string, unknown>>): Record<string, unknown>;
19
58
  export type OpencodeRuntime = Readonly<{
20
59
  client: {
21
60
  session: OpencodeSdkSession;
@@ -32,3 +71,4 @@ export declare function loadOpencode(input: Readonly<{
32
71
  requests?: string;
33
72
  }>): Promise<OpencodeRuntime>;
34
73
  export declare function coordinate(sessionId: string): ResumeCoordinate;
74
+ export {};
@@ -1,14 +1,81 @@
1
1
  import net from "node:net";
2
+ import { randomBytes } from "node:crypto";
2
3
  import { abortable } from "../../abort.js";
3
4
  import { akumaExecutionEnvironment } from "../execution-environment.js";
4
5
  import { spawnDetachedProcess } from "../../../runtime/proc/run.js";
5
6
  export const OPENCODE_SDK_PROVIDER = "opencode-sdk";
7
+ /**
8
+ * Adapt the installed client's generated event endpoint to the adapter's
9
+ * subscription port.
10
+ *
11
+ * The generated per-endpoint `Options` type omits the SDK's runtime
12
+ * `sseSleepFn` option even though the client forwards every per-request key
13
+ * into `createSseClient`, so a caller cannot express a cancellable backoff
14
+ * through the published type. Declaring the port here keeps that one typing gap
15
+ * and its single adaptation at the SDK seam: no other module repeats a cast,
16
+ * the SDK's own parser and retry policy stay untouched, and an injected loader
17
+ * supplies the same port shape.
18
+ */
19
+ export function opencodeEventPort(event) {
20
+ return {
21
+ subscribe: (request) => {
22
+ const adapted = {
23
+ query: { directory: request.directory },
24
+ signal: request.signal,
25
+ };
26
+ // Runtime-only key omitted from the generated Options type; the installed
27
+ // client forwards it to createSseClient unchanged.
28
+ adapted.sseSleepFn = request.sleep;
29
+ return event.subscribe(adapted);
30
+ },
31
+ };
32
+ }
33
+ export function messageId(sequence = 0) {
34
+ const timestamp = BigInt(new Date().getTime()) * 0x1000n + BigInt(sequence);
35
+ const bytes = Buffer.alloc(6);
36
+ bytes.writeUIntBE(Number(timestamp & 0xffffffffffffn), 0, 6);
37
+ const alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
38
+ const suffix = [...randomBytes(14)].map((byte) => alphabet[byte % alphabet.length]).join("");
39
+ return `msg_${bytes.toString("hex")}${suffix}`;
40
+ }
6
41
  export function parseModel(model) {
7
42
  const slash = model.indexOf("/");
8
43
  if (slash <= 0 || slash === model.length - 1)
9
44
  throw new Error("OpenCode model must be <provider>/<model>");
10
45
  return { providerID: model.slice(0, slash), modelID: model.slice(slash + 1) };
11
46
  }
47
+ /**
48
+ * Permission classes whose upstream defaults can await a human reply. A headless
49
+ * server has no reply channel, so such a pending ask never settles.
50
+ *
51
+ * Verified against the installed opencode 1.18.33 agent permission ruleset: the
52
+ * primary agents start from `{"*":"allow"}` with `external_directory` and
53
+ * `doom_loop` set to ask, `read` set to ask for `.env` files, and `question`
54
+ * allowed (the question tool awaits an answer by semantics). Every other class
55
+ * matches the allow-all rule and cannot await.
56
+ */
57
+ const HEADLESS_PERMISSION_BASE = Object.freeze({
58
+ external_directory: "allow",
59
+ doom_loop: "allow",
60
+ read: "allow",
61
+ question: "deny",
62
+ });
63
+ function isRecord(value) {
64
+ return value !== null && typeof value === "object" && !Array.isArray(value);
65
+ }
66
+ /**
67
+ * Compose the config handed to a headless opencode server. The permission base
68
+ * layer fills only the classes the caller leaves unspecified: an explicit caller
69
+ * permission key wins per key and every non-permission key passes through
70
+ * untouched. A caller that supplies a non-object `permission` shorthand states
71
+ * the whole policy and keeps it.
72
+ */
73
+ export function composeHeadlessPermissionConfig(config) {
74
+ const permission = config?.permission;
75
+ if (permission !== undefined && !isRecord(permission))
76
+ return { ...config };
77
+ return { ...config, permission: { ...HEADLESS_PERMISSION_BASE, ...permission } };
78
+ }
12
79
  async function waitReady(client, cwd, signal) {
13
80
  for (let attempt = 0; attempt < 100; attempt += 1) {
14
81
  if (signal.aborted)
@@ -67,7 +134,7 @@ export async function loadOpencode(input) {
67
134
  argv: [execution.executable ?? "opencode", "serve", "--hostname", "127.0.0.1", "--port", String(port)],
68
135
  cwd,
69
136
  env: akumaExecutionEnvironment(process.env, {
70
- ...(execution.config === undefined ? {} : { OPENCODE_CONFIG_CONTENT: JSON.stringify(execution.config) }),
137
+ OPENCODE_CONFIG_CONTENT: JSON.stringify(composeHeadlessPermissionConfig(execution.config)),
71
138
  ...execution.env,
72
139
  }, requests),
73
140
  log: `${cwd}/.opencode.log`,
@@ -76,7 +143,7 @@ export async function loadOpencode(input) {
76
143
  const client = createOpencodeClient({ baseUrl: `http://127.0.0.1:${port}`, directory: cwd });
77
144
  let closing;
78
145
  const runtime = {
79
- client,
146
+ client: { session: client.session, event: opencodeEventPort(client.event) },
80
147
  close: async () => {
81
148
  closing ??= owned.terminate();
82
149
  await closing;
@@ -146,7 +146,6 @@ function translateMessage(event, state) {
146
146
  const message = record(event.message);
147
147
  if (message?.role !== "assistant")
148
148
  return [];
149
- state.assistantSeen = true;
150
149
  const translated = [];
151
150
  if (Array.isArray(message.content)) {
152
151
  for (const block of message.content) {
@@ -160,7 +159,11 @@ function translateMessage(event, state) {
160
159
  }
161
160
  }
162
161
  const text = textContent(message.content);
163
- state.answer = text;
162
+ const terminal = message.stopReason !== "toolUse";
163
+ if (terminal) {
164
+ state.assistantSeen = true;
165
+ state.answer = text;
166
+ }
164
167
  // Gemini emits an empty text block alongside every tool-use message. It is
165
168
  // transport scaffolding, not narration; an ordinary terminal empty answer
166
169
  // remains public evidence.
@@ -1,12 +1,11 @@
1
- import type { createAgentSession, createBashToolDefinition, DefaultResourceLoader, getAgentDir, ModelRuntime, SessionManager, CreateAgentSessionOptions } from "@earendil-works/pi-coding-agent";
1
+ import type { createAgentSessionFromServices, createAgentSessionServices, createBashToolDefinition, getAgentDir, SessionManager } from "@earendil-works/pi-coding-agent";
2
2
  import type { ProviderExecution } from "../../provider-recipe.js";
3
3
  import { type ProviderAdapter } from "../../provider.js";
4
4
  export type PiSdk = Readonly<{
5
- createAgentSession(options?: CreateAgentSessionOptions): ReturnType<typeof createAgentSession>;
5
+ createAgentSessionFromServices: typeof createAgentSessionFromServices;
6
+ createAgentSessionServices: typeof createAgentSessionServices;
6
7
  createBashToolDefinition: typeof createBashToolDefinition;
7
- DefaultResourceLoader: typeof DefaultResourceLoader;
8
8
  getAgentDir: typeof getAgentDir;
9
- ModelRuntime: typeof ModelRuntime;
10
9
  SessionManager: typeof SessionManager;
11
10
  }>;
12
11
  export declare function createPiProvider(execution?: ProviderExecution, load?: () => Promise<PiSdk>): ProviderAdapter;