@scotthuang/agent-knock-knock 0.12.11 → 0.12.13

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 (344) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +43 -30
  3. package/dist/src/approval-policy.d.ts +11 -2
  4. package/dist/src/approval-policy.js +33 -7
  5. package/dist/src/approval-policy.js.map +1 -1
  6. package/dist/src/callback-cli-adapter.d.ts +47 -0
  7. package/dist/src/callback-cli-adapter.js +156 -0
  8. package/dist/src/callback-cli-adapter.js.map +1 -0
  9. package/dist/src/callback-outbox-policy.d.ts +95 -0
  10. package/dist/src/callback-outbox-policy.js +149 -0
  11. package/dist/src/callback-outbox-policy.js.map +1 -0
  12. package/dist/src/callback-outbox-service.d.ts +247 -0
  13. package/dist/src/callback-outbox-service.js +1053 -0
  14. package/dist/src/callback-outbox-service.js.map +1 -0
  15. package/dist/src/callback-outbox-settlement.d.ts +54 -0
  16. package/dist/src/callback-outbox-settlement.js +241 -0
  17. package/dist/src/callback-outbox-settlement.js.map +1 -0
  18. package/dist/src/canonical-json.d.ts +1 -0
  19. package/dist/src/canonical-json.js +14 -0
  20. package/dist/src/canonical-json.js.map +1 -0
  21. package/dist/src/claude-lifecycle-compatibility.js +15 -0
  22. package/dist/src/claude-lifecycle-compatibility.js.map +1 -1
  23. package/dist/src/claude-local-transcript-provider.d.ts +82 -1
  24. package/dist/src/claude-local-transcript-provider.js +873 -23
  25. package/dist/src/claude-local-transcript-provider.js.map +1 -1
  26. package/dist/src/cli-command-runtime.d.ts +14 -0
  27. package/dist/src/cli-command-runtime.js +164 -0
  28. package/dist/src/cli-command-runtime.js.map +1 -0
  29. package/dist/src/cli-core.d.ts +4 -42
  30. package/dist/src/cli-core.js +958 -28684
  31. package/dist/src/cli-core.js.map +1 -1
  32. package/dist/src/cli-runtime-context.d.ts +57 -0
  33. package/dist/src/cli-runtime-context.js +118 -0
  34. package/dist/src/cli-runtime-context.js.map +1 -0
  35. package/dist/src/codex-lifecycle-compatibility.js +2 -1
  36. package/dist/src/codex-lifecycle-compatibility.js.map +1 -1
  37. package/dist/src/codex-local-session-provider.d.ts +18 -0
  38. package/dist/src/codex-local-session-provider.js +67 -0
  39. package/dist/src/codex-local-session-provider.js.map +1 -1
  40. package/dist/src/codex-session-provider.js +1 -3
  41. package/dist/src/codex-session-provider.js.map +1 -1
  42. package/dist/src/conversation-trace.d.ts +30 -0
  43. package/dist/src/conversation-trace.js +185 -0
  44. package/dist/src/conversation-trace.js.map +1 -0
  45. package/dist/src/deferred-foreground-application-service.d.ts +84 -0
  46. package/dist/src/deferred-foreground-application-service.js +742 -0
  47. package/dist/src/deferred-foreground-application-service.js.map +1 -0
  48. package/dist/src/deferred-foreground-authority-cli-adapter.d.ts +78 -0
  49. package/dist/src/deferred-foreground-authority-cli-adapter.js +795 -0
  50. package/dist/src/deferred-foreground-authority-cli-adapter.js.map +1 -0
  51. package/dist/src/deferred-foreground-boundary.d.ts +61 -0
  52. package/dist/src/deferred-foreground-boundary.js +2 -0
  53. package/dist/src/deferred-foreground-boundary.js.map +1 -0
  54. package/dist/src/deferred-foreground-capability.d.ts +4 -0
  55. package/dist/src/deferred-foreground-capability.js +184 -0
  56. package/dist/src/deferred-foreground-capability.js.map +1 -0
  57. package/dist/src/deferred-foreground-preparation-cli-adapter.d.ts +53 -0
  58. package/dist/src/deferred-foreground-preparation-cli-adapter.js +210 -0
  59. package/dist/src/deferred-foreground-preparation-cli-adapter.js.map +1 -0
  60. package/dist/src/deferred-foreground-preparation-service.d.ts +72 -0
  61. package/dist/src/deferred-foreground-preparation-service.js +179 -0
  62. package/dist/src/deferred-foreground-preparation-service.js.map +1 -0
  63. package/dist/src/deferred-foreground-recovery-cli-adapter.d.ts +139 -0
  64. package/dist/src/deferred-foreground-recovery-cli-adapter.js +1125 -0
  65. package/dist/src/deferred-foreground-recovery-cli-adapter.js.map +1 -0
  66. package/dist/src/deferred-foreground-recovery-service.d.ts +48 -0
  67. package/dist/src/deferred-foreground-recovery-service.js +91 -0
  68. package/dist/src/deferred-foreground-recovery-service.js.map +1 -0
  69. package/dist/src/deferred-foreground-transfer-policy.d.ts +2 -0
  70. package/dist/src/deferred-foreground-transfer-policy.js +10 -0
  71. package/dist/src/deferred-foreground-transfer-policy.js.map +1 -0
  72. package/dist/src/deferred-foreground-transfer.js +46 -105
  73. package/dist/src/deferred-foreground-transfer.js.map +1 -1
  74. package/dist/src/doctor-capabilities.d.ts +9 -0
  75. package/dist/src/doctor-capabilities.js +22 -0
  76. package/dist/src/doctor-capabilities.js.map +1 -1
  77. package/dist/src/durable-json-file.d.ts +22 -0
  78. package/dist/src/durable-json-file.js +127 -0
  79. package/dist/src/durable-json-file.js.map +1 -0
  80. package/dist/src/file-lock-cli-adapter.d.ts +43 -0
  81. package/dist/src/file-lock-cli-adapter.js +150 -0
  82. package/dist/src/file-lock-cli-adapter.js.map +1 -0
  83. package/dist/src/herdr-terminal-control-provider.js +1 -3
  84. package/dist/src/herdr-terminal-control-provider.js.map +1 -1
  85. package/dist/src/install-doctor-command-adapter.d.ts +17 -0
  86. package/dist/src/install-doctor-command-adapter.js +225 -0
  87. package/dist/src/install-doctor-command-adapter.js.map +1 -0
  88. package/dist/src/live-lifecycle-evidence.js +76 -46
  89. package/dist/src/live-lifecycle-evidence.js.map +1 -1
  90. package/dist/src/live-lifecycle-smoke.js +74 -50
  91. package/dist/src/live-lifecycle-smoke.js.map +1 -1
  92. package/dist/src/managed-session.d.ts +2 -0
  93. package/dist/src/managed-session.js +24 -0
  94. package/dist/src/managed-session.js.map +1 -1
  95. package/dist/src/managed-turn-recovery-service.d.ts +86 -0
  96. package/dist/src/managed-turn-recovery-service.js +145 -0
  97. package/dist/src/managed-turn-recovery-service.js.map +1 -0
  98. package/dist/src/mutation-transaction.d.ts +48 -0
  99. package/dist/src/mutation-transaction.js +73 -0
  100. package/dist/src/mutation-transaction.js.map +1 -0
  101. package/dist/src/native-thread-lifecycle-cli-adapter.d.ts +154 -0
  102. package/dist/src/native-thread-lifecycle-cli-adapter.js +786 -0
  103. package/dist/src/native-thread-lifecycle-cli-adapter.js.map +1 -0
  104. package/dist/src/native-thread-lifecycle-ledger-cli-adapter.d.ts +25 -0
  105. package/dist/src/native-thread-lifecycle-ledger-cli-adapter.js +50 -0
  106. package/dist/src/native-thread-lifecycle-ledger-cli-adapter.js.map +1 -0
  107. package/dist/src/native-thread-lifecycle-query-service.d.ts +75 -0
  108. package/dist/src/native-thread-lifecycle-query-service.js +297 -0
  109. package/dist/src/native-thread-lifecycle-query-service.js.map +1 -0
  110. package/dist/src/native-thread-lifecycle-recovery-adapter.d.ts +45 -0
  111. package/dist/src/native-thread-lifecycle-recovery-adapter.js +154 -0
  112. package/dist/src/native-thread-lifecycle-recovery-adapter.js.map +1 -0
  113. package/dist/src/native-thread-lifecycle-recovery-service.d.ts +211 -0
  114. package/dist/src/native-thread-lifecycle-recovery-service.js +1093 -0
  115. package/dist/src/native-thread-lifecycle-recovery-service.js.map +1 -0
  116. package/dist/src/native-thread-resume-snapshot-policy.d.ts +73 -0
  117. package/dist/src/native-thread-resume-snapshot-policy.js +218 -0
  118. package/dist/src/native-thread-resume-snapshot-policy.js.map +1 -0
  119. package/dist/src/native-thread-resume-snapshot.d.ts +3 -61
  120. package/dist/src/native-thread-resume-snapshot.js +2 -143
  121. package/dist/src/native-thread-resume-snapshot.js.map +1 -1
  122. package/dist/src/native-thread-transition-application.d.ts +147 -0
  123. package/dist/src/native-thread-transition-application.js +974 -0
  124. package/dist/src/native-thread-transition-application.js.map +1 -0
  125. package/dist/src/native-thread-transition-policy.d.ts +127 -0
  126. package/dist/src/native-thread-transition-policy.js +154 -0
  127. package/dist/src/native-thread-transition-policy.js.map +1 -0
  128. package/dist/src/native-thread-transition-resource-adapter.d.ts +12 -0
  129. package/dist/src/native-thread-transition-resource-adapter.js +44 -0
  130. package/dist/src/native-thread-transition-resource-adapter.js.map +1 -0
  131. package/dist/src/native-thread-transition-settlement-service.d.ts +94 -0
  132. package/dist/src/native-thread-transition-settlement-service.js +134 -0
  133. package/dist/src/native-thread-transition-settlement-service.js.map +1 -0
  134. package/dist/src/native-thread-transition-verification-adapter.d.ts +62 -0
  135. package/dist/src/native-thread-transition-verification-adapter.js +451 -0
  136. package/dist/src/native-thread-transition-verification-adapter.js.map +1 -0
  137. package/dist/src/openclaw-callback-transport.d.ts +69 -0
  138. package/dist/src/openclaw-callback-transport.js +583 -0
  139. package/dist/src/openclaw-callback-transport.js.map +1 -0
  140. package/dist/src/openclaw-plugin-callback-adapter.d.ts +1 -0
  141. package/dist/src/openclaw-plugin-callback-adapter.js +423 -0
  142. package/dist/src/openclaw-plugin-callback-adapter.js.map +1 -0
  143. package/dist/src/openclaw-plugin-command-adapter.d.ts +16 -0
  144. package/dist/src/openclaw-plugin-command-adapter.js +1868 -0
  145. package/dist/src/openclaw-plugin-command-adapter.js.map +1 -0
  146. package/dist/src/openclaw-plugin-helpers.d.ts +27 -4
  147. package/dist/src/openclaw-plugin-helpers.js +356 -81
  148. package/dist/src/openclaw-plugin-helpers.js.map +1 -1
  149. package/dist/src/openclaw-plugin-schemas.d.ts +358 -0
  150. package/dist/src/openclaw-plugin-schemas.js +366 -0
  151. package/dist/src/openclaw-plugin-schemas.js.map +1 -0
  152. package/dist/src/openclaw-plugin-supervisor.d.ts +6 -0
  153. package/dist/src/openclaw-plugin-supervisor.js +123 -0
  154. package/dist/src/openclaw-plugin-supervisor.js.map +1 -0
  155. package/dist/src/openclaw-plugin.js +7 -2212
  156. package/dist/src/openclaw-plugin.js.map +1 -1
  157. package/dist/src/openclaw-private-authority-offers.d.ts +22 -0
  158. package/dist/src/openclaw-private-authority-offers.js +177 -0
  159. package/dist/src/openclaw-private-authority-offers.js.map +1 -0
  160. package/dist/src/protocol.d.ts +5 -0
  161. package/dist/src/protocol.js +59 -3
  162. package/dist/src/protocol.js.map +1 -1
  163. package/dist/src/session-store.d.ts +1 -0
  164. package/dist/src/session-store.js +84 -106
  165. package/dist/src/session-store.js.map +1 -1
  166. package/dist/src/store.d.ts +1 -0
  167. package/dist/src/store.js +5 -2
  168. package/dist/src/store.js.map +1 -1
  169. package/dist/src/terminal-acceptance-application-service.d.ts +65 -0
  170. package/dist/src/terminal-acceptance-application-service.js +63 -0
  171. package/dist/src/terminal-acceptance-application-service.js.map +1 -0
  172. package/dist/src/terminal-acceptance-cli-adapter.d.ts +210 -0
  173. package/dist/src/terminal-acceptance-cli-adapter.js +957 -0
  174. package/dist/src/terminal-acceptance-cli-adapter.js.map +1 -0
  175. package/dist/src/terminal-action-projection.d.ts +309 -0
  176. package/dist/src/terminal-action-projection.js +376 -0
  177. package/dist/src/terminal-action-projection.js.map +1 -0
  178. package/dist/src/terminal-agent-bridge.d.ts +3 -0
  179. package/dist/src/terminal-agent-bridge.js +29 -8
  180. package/dist/src/terminal-agent-bridge.js.map +1 -1
  181. package/dist/src/terminal-authority-policy.d.ts +141 -0
  182. package/dist/src/terminal-authority-policy.js +367 -0
  183. package/dist/src/terminal-authority-policy.js.map +1 -0
  184. package/dist/src/terminal-binding-authority.d.ts +118 -0
  185. package/dist/src/terminal-binding-authority.js +245 -0
  186. package/dist/src/terminal-binding-authority.js.map +1 -0
  187. package/dist/src/terminal-binding-reconciliation-service.d.ts +75 -0
  188. package/dist/src/terminal-binding-reconciliation-service.js +73 -0
  189. package/dist/src/terminal-binding-reconciliation-service.js.map +1 -0
  190. package/dist/src/terminal-command-cli-adapter.d.ts +380 -0
  191. package/dist/src/terminal-command-cli-adapter.js +3288 -0
  192. package/dist/src/terminal-command-cli-adapter.js.map +1 -0
  193. package/dist/src/terminal-control-ref.d.ts +4 -0
  194. package/dist/src/terminal-control-ref.js +11 -8
  195. package/dist/src/terminal-control-ref.js.map +1 -1
  196. package/dist/src/terminal-delegate-cli-adapter.d.ts +41 -0
  197. package/dist/src/terminal-delegate-cli-adapter.js +242 -0
  198. package/dist/src/terminal-delegate-cli-adapter.js.map +1 -0
  199. package/dist/src/terminal-dispatch-abort.d.ts +22 -0
  200. package/dist/src/terminal-dispatch-abort.js +30 -0
  201. package/dist/src/terminal-dispatch-abort.js.map +1 -0
  202. package/dist/src/terminal-dispatch-application.d.ts +115 -0
  203. package/dist/src/terminal-dispatch-application.js +478 -0
  204. package/dist/src/terminal-dispatch-application.js.map +1 -0
  205. package/dist/src/terminal-dispatch-capability.d.ts +63 -0
  206. package/dist/src/terminal-dispatch-capability.js +133 -0
  207. package/dist/src/terminal-dispatch-capability.js.map +1 -0
  208. package/dist/src/terminal-dispatch-completion-cli-adapter.d.ts +22 -0
  209. package/dist/src/terminal-dispatch-completion-cli-adapter.js +96 -0
  210. package/dist/src/terminal-dispatch-completion-cli-adapter.js.map +1 -0
  211. package/dist/src/terminal-dispatch-composition.d.ts +79 -0
  212. package/dist/src/terminal-dispatch-composition.js +2 -0
  213. package/dist/src/terminal-dispatch-composition.js.map +1 -0
  214. package/dist/src/terminal-dispatch-execution.d.ts +290 -0
  215. package/dist/src/terminal-dispatch-execution.js +916 -0
  216. package/dist/src/terminal-dispatch-execution.js.map +1 -0
  217. package/dist/src/terminal-dispatch-ledger-codec.d.ts +110 -0
  218. package/dist/src/terminal-dispatch-ledger-codec.js +399 -0
  219. package/dist/src/terminal-dispatch-ledger-codec.js.map +1 -0
  220. package/dist/src/terminal-dispatch-policy.d.ts +93 -0
  221. package/dist/src/terminal-dispatch-policy.js +122 -0
  222. package/dist/src/terminal-dispatch-policy.js.map +1 -0
  223. package/dist/src/terminal-dispatch-presenter.d.ts +65 -0
  224. package/dist/src/terminal-dispatch-presenter.js +258 -0
  225. package/dist/src/terminal-dispatch-presenter.js.map +1 -0
  226. package/dist/src/terminal-dispatch-receipt.d.ts +79 -0
  227. package/dist/src/terminal-dispatch-receipt.js +314 -0
  228. package/dist/src/terminal-dispatch-receipt.js.map +1 -0
  229. package/dist/src/terminal-dispatch-recovery-cli-adapter.d.ts +132 -0
  230. package/dist/src/terminal-dispatch-recovery-cli-adapter.js +1330 -0
  231. package/dist/src/terminal-dispatch-recovery-cli-adapter.js.map +1 -0
  232. package/dist/src/terminal-dispatch-recovery-service.d.ts +271 -0
  233. package/dist/src/terminal-dispatch-recovery-service.js +374 -0
  234. package/dist/src/terminal-dispatch-recovery-service.js.map +1 -0
  235. package/dist/src/terminal-dispatch-repository-cli-adapter.d.ts +35 -0
  236. package/dist/src/terminal-dispatch-repository-cli-adapter.js +483 -0
  237. package/dist/src/terminal-dispatch-repository-cli-adapter.js.map +1 -0
  238. package/dist/src/terminal-handoff-application-service.d.ts +7 -0
  239. package/dist/src/terminal-handoff-application-service.js +18 -0
  240. package/dist/src/terminal-handoff-application-service.js.map +1 -0
  241. package/dist/src/terminal-handoff-cli-adapter.d.ts +229 -0
  242. package/dist/src/terminal-handoff-cli-adapter.js +1389 -0
  243. package/dist/src/terminal-handoff-cli-adapter.js.map +1 -0
  244. package/dist/src/terminal-handoff-facts.d.ts +12 -0
  245. package/dist/src/terminal-handoff-facts.js +16 -0
  246. package/dist/src/terminal-handoff-facts.js.map +1 -0
  247. package/dist/src/terminal-identity-authority-cli-adapter.d.ts +318 -0
  248. package/dist/src/terminal-identity-authority-cli-adapter.js +1072 -0
  249. package/dist/src/terminal-identity-authority-cli-adapter.js.map +1 -0
  250. package/dist/src/terminal-identity-authority-service.d.ts +48 -0
  251. package/dist/src/terminal-identity-authority-service.js +45 -0
  252. package/dist/src/terminal-identity-authority-service.js.map +1 -0
  253. package/dist/src/terminal-list-cli-adapter.d.ts +274 -0
  254. package/dist/src/terminal-list-cli-adapter.js +2444 -0
  255. package/dist/src/terminal-list-cli-adapter.js.map +1 -0
  256. package/dist/src/terminal-list-renderer.d.ts +34 -0
  257. package/dist/src/terminal-list-renderer.js +643 -0
  258. package/dist/src/terminal-list-renderer.js.map +1 -0
  259. package/dist/src/terminal-maintenance-cli-adapter.d.ts +102 -0
  260. package/dist/src/terminal-maintenance-cli-adapter.js +1059 -0
  261. package/dist/src/terminal-maintenance-cli-adapter.js.map +1 -0
  262. package/dist/src/terminal-monitor-application-service.d.ts +275 -0
  263. package/dist/src/terminal-monitor-application-service.js +982 -0
  264. package/dist/src/terminal-monitor-application-service.js.map +1 -0
  265. package/dist/src/terminal-monitor-cli-adapter.d.ts +130 -0
  266. package/dist/src/terminal-monitor-cli-adapter.js +442 -0
  267. package/dist/src/terminal-monitor-cli-adapter.js.map +1 -0
  268. package/dist/src/terminal-monitor-decision-policy.d.ts +98 -0
  269. package/dist/src/terminal-monitor-decision-policy.js +246 -0
  270. package/dist/src/terminal-monitor-decision-policy.js.map +1 -0
  271. package/dist/src/terminal-monitor-launch-plan.d.ts +45 -0
  272. package/dist/src/terminal-monitor-launch-plan.js +94 -0
  273. package/dist/src/terminal-monitor-launch-plan.js.map +1 -0
  274. package/dist/src/terminal-monitor-ownership-policy.d.ts +31 -0
  275. package/dist/src/terminal-monitor-ownership-policy.js +64 -0
  276. package/dist/src/terminal-monitor-ownership-policy.js.map +1 -0
  277. package/dist/src/terminal-monitor-poll-policy.d.ts +48 -0
  278. package/dist/src/terminal-monitor-poll-policy.js +67 -0
  279. package/dist/src/terminal-monitor-poll-policy.js.map +1 -0
  280. package/dist/src/terminal-monitor-reconciliation-eligibility.d.ts +53 -0
  281. package/dist/src/terminal-monitor-reconciliation-eligibility.js +114 -0
  282. package/dist/src/terminal-monitor-reconciliation-eligibility.js.map +1 -0
  283. package/dist/src/terminal-monitor-state-cli-adapter.d.ts +106 -0
  284. package/dist/src/terminal-monitor-state-cli-adapter.js +1492 -0
  285. package/dist/src/terminal-monitor-state-cli-adapter.js.map +1 -0
  286. package/dist/src/terminal-monitor-state-reconciliation-service.d.ts +87 -0
  287. package/dist/src/terminal-monitor-state-reconciliation-service.js +106 -0
  288. package/dist/src/terminal-monitor-state-reconciliation-service.js.map +1 -0
  289. package/dist/src/terminal-monitor-supervision-cli-adapter.d.ts +122 -0
  290. package/dist/src/terminal-monitor-supervision-cli-adapter.js +685 -0
  291. package/dist/src/terminal-monitor-supervision-cli-adapter.js.map +1 -0
  292. package/dist/src/terminal-process-facts.d.ts +2 -0
  293. package/dist/src/terminal-process-facts.js +19 -0
  294. package/dist/src/terminal-process-facts.js.map +1 -0
  295. package/dist/src/terminal-process-source.d.ts +6 -4
  296. package/dist/src/terminal-process-source.js +25 -20
  297. package/dist/src/terminal-process-source.js.map +1 -1
  298. package/dist/src/terminal-runtime-cli-adapter.d.ts +80 -0
  299. package/dist/src/terminal-runtime-cli-adapter.js +488 -0
  300. package/dist/src/terminal-runtime-cli-adapter.js.map +1 -0
  301. package/dist/src/terminal-scoped-approval-authority.d.ts +62 -0
  302. package/dist/src/terminal-scoped-approval-authority.js +281 -0
  303. package/dist/src/terminal-scoped-approval-authority.js.map +1 -0
  304. package/dist/src/terminal-selector-projection-service.d.ts +26 -0
  305. package/dist/src/terminal-selector-projection-service.js +81 -0
  306. package/dist/src/terminal-selector-projection-service.js.map +1 -0
  307. package/dist/src/terminal-status-cli-adapter.d.ts +126 -0
  308. package/dist/src/terminal-status-cli-adapter.js +577 -0
  309. package/dist/src/terminal-status-cli-adapter.js.map +1 -0
  310. package/dist/src/terminal-status-facts.d.ts +56 -0
  311. package/dist/src/terminal-status-facts.js +199 -0
  312. package/dist/src/terminal-status-facts.js.map +1 -0
  313. package/dist/src/terminal-submission-acceptance.d.ts +62 -145
  314. package/dist/src/terminal-submission-acceptance.js +555 -222
  315. package/dist/src/terminal-submission-acceptance.js.map +1 -1
  316. package/dist/src/terminal-submission-facts.d.ts +123 -0
  317. package/dist/src/terminal-submission-facts.js +205 -0
  318. package/dist/src/terminal-submission-facts.js.map +1 -0
  319. package/dist/src/terminal-turn-binding-authority-cli-adapter.d.ts +14 -0
  320. package/dist/src/terminal-turn-binding-authority-cli-adapter.js +90 -0
  321. package/dist/src/terminal-turn-binding-authority-cli-adapter.js.map +1 -0
  322. package/dist/src/terminal-watch-callback-cli-adapter.d.ts +20 -0
  323. package/dist/src/terminal-watch-callback-cli-adapter.js +55 -0
  324. package/dist/src/terminal-watch-callback-cli-adapter.js.map +1 -0
  325. package/dist/src/terminal-watch-cli-adapter.d.ts +64 -0
  326. package/dist/src/terminal-watch-cli-adapter.js +508 -0
  327. package/dist/src/terminal-watch-cli-adapter.js.map +1 -0
  328. package/dist/src/terminal-watch-service.d.ts +97 -0
  329. package/dist/src/terminal-watch-service.js +714 -0
  330. package/dist/src/terminal-watch-service.js.map +1 -0
  331. package/dist/src/terminal-watch-store.d.ts +149 -0
  332. package/dist/src/terminal-watch-store.js +861 -0
  333. package/dist/src/terminal-watch-store.js.map +1 -0
  334. package/dist/src/value-guards.d.ts +4 -0
  335. package/dist/src/value-guards.js +12 -0
  336. package/dist/src/value-guards.js.map +1 -0
  337. package/dist/src/verified-dead-agent-policy.d.ts +192 -0
  338. package/dist/src/verified-dead-agent-policy.js +262 -0
  339. package/dist/src/verified-dead-agent-policy.js.map +1 -0
  340. package/docs/quickstart-herdr.md +8 -0
  341. package/docs/quickstart-tmux.md +33 -6
  342. package/openclaw.plugin.json +11 -3
  343. package/package.json +3 -1
  344. package/templates/openclaw-skills/agent-knock-knock/SKILL.md +58 -40
@@ -0,0 +1,1053 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { applyMessageToConversation, createMessage, effectiveTurnStatus, executorForConversation, extractStructuredMessage, isTerminalBridgeCallbackSupersedeStatus, isTerminalDispatchOwnerReleasedStatus, isTurnPhaseStatus, isWaitingForAgentStatus, normalizeLegacyCallbackStatus, parseMessageJson, turnIdForConversation } from "./protocol.js";
3
+ import { beginCallbackRetryPolicy, reduceCallbackRetryPolicy } from "./callback-outbox-policy.js";
4
+ import { createCallbackOutboxSettlement } from "./callback-outbox-settlement.js";
5
+ import { canonicalJson } from "./canonical-json.js";
6
+ import { isRecord, nonBlankString as stringValue } from "./value-guards.js";
7
+ export function resolveCallbackGatewayRoute(...candidates) {
8
+ for (const candidate of candidates) {
9
+ const token = stringValue(candidate.token);
10
+ if (!token || token === "<token>") {
11
+ continue;
12
+ }
13
+ return {
14
+ gatewayUrl: stringValue(candidate.gatewayUrl),
15
+ token
16
+ };
17
+ }
18
+ return {
19
+ gatewayUrl: undefined,
20
+ token: undefined
21
+ };
22
+ }
23
+ export function createCallbackOutboxService(ports) {
24
+ const settlement = createCallbackOutboxSettlement({
25
+ state: {
26
+ withStateTransaction: ports.state.withTransaction,
27
+ load: ports.state.load,
28
+ save: ports.state.save,
29
+ append: ports.state.append
30
+ },
31
+ retryMonitor: {
32
+ start: ({ statePath }) => ports.retry.startMonitor({
33
+ statePath,
34
+ delayMs: ports.retry.delaysMs[0]
35
+ })
36
+ },
37
+ clock: { now: ports.runtime.now, nowMs: ports.runtime.nowMs },
38
+ attemptLeaseMs: ports.retry.attemptLeaseMs,
39
+ retryDelaysMs: ports.retry.delaysMs
40
+ });
41
+ function prepare({ options, logPath }) {
42
+ const messageInput = requiredMessageJson(options.messageJson);
43
+ const loadedConversation = isRecord(options.conversationOverride)
44
+ ? options.conversationOverride
45
+ : ports.state.load(options.statePath);
46
+ const conversation = normalizeLegacyCallbackStatus(loadedConversation);
47
+ const storeDir = ports.state.storeDirForStatePath(options.statePath);
48
+ ports.authority.assertNoDeferredTransfer({
49
+ storeDir,
50
+ conversation,
51
+ action: "prepare callback for"
52
+ });
53
+ const executor = executorForConversation(conversation);
54
+ const persistedGatewayRoute = resolveCallbackGatewayRoute({
55
+ gatewayUrl: options.gatewayUrl,
56
+ token: options.token
57
+ });
58
+ const message = options.retryPending === true ||
59
+ options.preserveMessageId === true
60
+ ? parseMessageJson(messageInput)
61
+ : extractStructuredMessage({
62
+ conversation,
63
+ input: messageInput,
64
+ defaultFrom: executor.actor,
65
+ defaultTo: "openclaw"
66
+ });
67
+ if (message.conversation_id !== conversation.conversation_id) {
68
+ throw new Error(`message.conversation_id ${message.conversation_id} does not match conversation ${conversation.conversation_id}`);
69
+ }
70
+ const existingEvents = ports.state.readEvents(logPath);
71
+ const callbackDelivery = isRecord(conversation.callback_delivery)
72
+ ? conversation.callback_delivery
73
+ : undefined;
74
+ const persistedDeliveryMessage = isRecord(callbackDelivery?.message)
75
+ ? callbackDelivery.message
76
+ : undefined;
77
+ const sameDeliveryMessageId = persistedDeliveryMessage?.id === message.id;
78
+ const sameDeliveryMessage = sameDeliveryMessageId &&
79
+ canonicalJson(persistedDeliveryMessage) === canonicalJson(message);
80
+ if (sameDeliveryMessageId && !sameDeliveryMessage) {
81
+ throw new Error(`callback message ${message.id} conflicts with its persisted immutable outbox payload`);
82
+ }
83
+ const inheritedDelivery = sameDeliveryMessage
84
+ ? callbackDelivery
85
+ : undefined;
86
+ const retryingPending = options.retryPending === true &&
87
+ sameDeliveryMessage &&
88
+ callbackRetryDisposition(ports, inheritedDelivery).state === "retryable";
89
+ if (options.retryPending === true &&
90
+ sameDeliveryMessage &&
91
+ !retryingPending) {
92
+ rejectNonRetryableDelivery(callbackRetryDisposition(ports, inheritedDelivery));
93
+ }
94
+ const duplicateMessage = isDuplicateMessage(existingEvents, message);
95
+ const recoveryMessageAlreadyLogged = options.recoverMissingOutbox === true
96
+ ? exactLoggedMessageForRecovery(existingEvents, message)
97
+ : false;
98
+ const recoveringMissingOutbox = options.recoverMissingOutbox === true &&
99
+ (!isRecord(callbackDelivery?.message) ||
100
+ callbackDelivery.message.id !== message.id);
101
+ if (!retryingPending &&
102
+ !recoveryMessageAlreadyLogged &&
103
+ !sameDeliveryMessage) {
104
+ ports.authority.assertBindingCurrent(conversation, "accept callback for");
105
+ }
106
+ if (isTerminalDispatchOwnerReleasedStatus(effectiveTurnStatus(conversation)) &&
107
+ !duplicateMessage) {
108
+ throw new Error(`refusing late callback ${message.id} for released Turn ` +
109
+ `${turnIdForConversation(conversation)} (${conversation.status})`);
110
+ }
111
+ const recoveringTerminalCompletion = options.recoverTerminalCompletion === true &&
112
+ duplicateMessage &&
113
+ (isWaitingForAgentStatus(conversation.status) ||
114
+ (options.allowTerminalCompletionRecoveryStatus === true &&
115
+ isTerminalBridgeCallbackSupersedeStatus(conversation.status)));
116
+ if (duplicateMessage &&
117
+ !retryingPending &&
118
+ !recoveringTerminalCompletion &&
119
+ !recoveringMissingOutbox) {
120
+ ports.runtime.log("info", "callback_duplicate", {
121
+ conversation_id: conversation.conversation_id,
122
+ agent: executor.kind,
123
+ executor_session: executor.session,
124
+ from: message.from,
125
+ type: message.type,
126
+ round: message.round,
127
+ state_path: options.statePath,
128
+ event_log_path: logPath
129
+ });
130
+ return {
131
+ outcome: "duplicate",
132
+ conversation,
133
+ message
134
+ };
135
+ }
136
+ function persistPreparation() {
137
+ const closeTerminalBridgeOnDone = message.type === "done" &&
138
+ options.closeTerminalBridgeOnDone === true;
139
+ const requiresDelivery = options.recordOnly !== true;
140
+ const deliveryAttempt = Number(inheritedDelivery?.attempts ?? 0) + 1;
141
+ const deliveryAttemptId = randomUUID();
142
+ let nextConversation = retryingPending
143
+ ? conversation
144
+ : applyMessageToConversation(conversation, message);
145
+ if (closeTerminalBridgeOnDone) {
146
+ const closedAt = ports.runtime.now().toISOString();
147
+ nextConversation = {
148
+ ...nextConversation,
149
+ status: "closed",
150
+ closed_at: nextConversation.closed_at ?? closedAt,
151
+ close_reason: nextConversation.close_reason ??
152
+ "terminal bridge task completed",
153
+ updated_at: closedAt
154
+ };
155
+ delete nextConversation.idle_since;
156
+ }
157
+ const storedFinalStatus = stringValue(inheritedDelivery?.final_status);
158
+ const finalStatus = storedFinalStatus &&
159
+ isTurnPhaseStatus(storedFinalStatus)
160
+ ? storedFinalStatus
161
+ : effectiveTurnStatus(nextConversation);
162
+ const retryDelayMs = ports.retry.delaysMs[Math.min(ports.retry.delaysMs.length - 1, Math.max(0, deliveryAttempt - 1))];
163
+ const callbackWatchdog = requiresDelivery &&
164
+ !retryingPending &&
165
+ options.disableCallbackRetry !== true &&
166
+ deliveryAttempt <= ports.retry.delaysMs.length
167
+ ? ports.retry.startMonitor({
168
+ statePath: options.statePath,
169
+ delayMs: retryDelayMs
170
+ })
171
+ : undefined;
172
+ if (!retryingPending &&
173
+ !recoveringTerminalCompletion &&
174
+ !(recoveringMissingOutbox && recoveryMessageAlreadyLogged)) {
175
+ ports.state.appendMessage(logPath, message);
176
+ }
177
+ if (requiresDelivery) {
178
+ const now = ports.runtime.now().toISOString();
179
+ nextConversation = {
180
+ ...nextConversation,
181
+ callback_delivery: {
182
+ status: "pending",
183
+ message,
184
+ attempts: deliveryAttempt,
185
+ attempt_id: deliveryAttemptId,
186
+ attempt_pid: ports.runtime.pid(),
187
+ attempt_lease_expires_at: new Date(ports.runtime.nowMs() + ports.retry.attemptLeaseMs).toISOString(),
188
+ created_at: stringValue(inheritedDelivery?.created_at) ?? now,
189
+ last_attempt_at: now,
190
+ updated_at: now,
191
+ gateway_method: options.gatewayMethod,
192
+ gateway_session: options.gatewaySession ??
193
+ options.openclawSession ?? conversation.openclaw_session,
194
+ gateway_url: persistedGatewayRoute.gatewayUrl,
195
+ openclaw_bin: options.openclawBin ?? conversation.openclaw_bin,
196
+ close_terminal_bridge_on_done: closeTerminalBridgeOnDone,
197
+ track_delivery: true,
198
+ final_status: finalStatus,
199
+ preserve_conversation_status: true,
200
+ kind: stringValue(options.callbackDeliveryKind) ??
201
+ stringValue(inheritedDelivery?.kind),
202
+ ...(callbackWatchdog
203
+ ? {
204
+ retry_monitor_pid: callbackWatchdog.pid ?? null,
205
+ next_attempt_at: new Date(ports.runtime.nowMs() + retryDelayMs).toISOString()
206
+ }
207
+ : {})
208
+ }
209
+ };
210
+ ports.state.append(logPath, {
211
+ ts: now,
212
+ conversation_id: conversation.conversation_id,
213
+ event: retryingPending
214
+ ? "callback_delivery_retry_started"
215
+ : "callback_delivery_pending",
216
+ message_id: message.id,
217
+ attempt: deliveryAttempt
218
+ });
219
+ if (callbackWatchdog) {
220
+ ports.state.append(logPath, {
221
+ ts: ports.runtime.now().toISOString(),
222
+ conversation_id: conversation.conversation_id,
223
+ event: "callback_retry_monitor_launched",
224
+ message_id: message.id,
225
+ pid: callbackWatchdog.pid ?? null,
226
+ next_attempt_at: isRecord(nextConversation.callback_delivery)
227
+ ? nextConversation.callback_delivery.next_attempt_at
228
+ : undefined
229
+ });
230
+ }
231
+ }
232
+ ports.state.save(options.statePath, nextConversation);
233
+ ports.runtime.log("info", "callback_received", {
234
+ conversation_id: conversation.conversation_id,
235
+ agent: executor.kind,
236
+ executor_session: executor.session,
237
+ from: message.from,
238
+ type: message.type,
239
+ round: message.round,
240
+ status: nextConversation.status,
241
+ requires_response: message.requires_response,
242
+ state_path: options.statePath,
243
+ event_log_path: logPath,
244
+ message: ports.runtime.textSummary(message.body)
245
+ });
246
+ if (options.recordOnly) {
247
+ ports.runtime.log("info", "callback_recorded_only", {
248
+ conversation_id: conversation.conversation_id,
249
+ status: nextConversation.status
250
+ });
251
+ return {
252
+ outcome: "record_only",
253
+ conversation: nextConversation,
254
+ message
255
+ };
256
+ }
257
+ return {
258
+ outcome: "deliver",
259
+ options,
260
+ statePath: options.statePath,
261
+ logPath,
262
+ conversation: nextConversation,
263
+ message,
264
+ deliveryAttempt,
265
+ deliveryAttemptId
266
+ };
267
+ }
268
+ return persistPreparation();
269
+ }
270
+ function runPrepared(prepared) {
271
+ if (prepared.outcome !== "deliver") {
272
+ return {
273
+ delivered: false,
274
+ duplicate: prepared.outcome === "duplicate",
275
+ conversation: prepared.conversation,
276
+ message: prepared.message
277
+ };
278
+ }
279
+ ports.state.assertWriterCompatible(ports.state.storeDirForStatePath(prepared.statePath));
280
+ let acceptedDelivery;
281
+ try {
282
+ const delivery = ports.delivery.deliver({
283
+ options: prepared.options,
284
+ statePath: prepared.statePath,
285
+ logPath: prepared.logPath,
286
+ conversation: prepared.conversation,
287
+ message: prepared.message,
288
+ onProgress: (progress) => {
289
+ settlement.persistDeliveryProgress(prepared, progress);
290
+ },
291
+ onAccepted: (accepted) => {
292
+ acceptedDelivery = accepted;
293
+ }
294
+ });
295
+ return {
296
+ delivered: true,
297
+ duplicate: false,
298
+ conversation: settlement.settleDelivery(prepared, {
299
+ delivered: true,
300
+ delivery
301
+ }),
302
+ message: prepared.message,
303
+ delivery: delivery.kind
304
+ };
305
+ }
306
+ catch (error) {
307
+ if (acceptedDelivery) {
308
+ const acceptedAfterError = {
309
+ ...acceptedDelivery,
310
+ run_observation: acceptedDelivery.run_observation ?? {
311
+ status: "unavailable",
312
+ source: "post_acceptance_error",
313
+ observed_at: ports.runtime.now().toISOString(),
314
+ error: error instanceof Error ? error.message : String(error)
315
+ }
316
+ };
317
+ return {
318
+ delivered: true,
319
+ duplicate: false,
320
+ conversation: settlement.settleDelivery(prepared, {
321
+ delivered: true,
322
+ delivery: acceptedAfterError
323
+ }),
324
+ message: prepared.message,
325
+ delivery: acceptedAfterError.kind
326
+ };
327
+ }
328
+ const settled = settlement.settleDelivery(prepared, {
329
+ delivered: false,
330
+ error
331
+ });
332
+ const settledDelivery = isRecord(settled.callback_delivery)
333
+ ? settled.callback_delivery
334
+ : undefined;
335
+ if (settledDelivery?.status === "delivered") {
336
+ return {
337
+ delivered: true,
338
+ duplicate: false,
339
+ conversation: settled,
340
+ message: prepared.message,
341
+ delivery: "accepted_before_observation_error"
342
+ };
343
+ }
344
+ throw error;
345
+ }
346
+ }
347
+ return {
348
+ prepare,
349
+ runPrepared,
350
+ reconcileDelivery: (input) => reconcileCallbackDelivery(ports, settlement, input),
351
+ runRetryMonitor: (input) => runCallbackRetryMonitor(ports, settlement, input),
352
+ retry: (input) => retryCallback(ports, settlement, input),
353
+ retryDisposition: (delivery) => callbackRetryDisposition(ports, delivery),
354
+ prepareApprovalNotification: (input) => prepareApprovalNotification(prepare, input),
355
+ prepareTerminalCompletion: (input) => prepareTerminalCompletion(ports, prepare, input)
356
+ };
357
+ }
358
+ function prepareApprovalNotification(prepare, input) {
359
+ const identity = terminalApprovalCallbackIdentity(input.conversation);
360
+ const callbackMessage = createMessage({
361
+ conversation: input.conversation,
362
+ id: identity.id,
363
+ from: input.actor,
364
+ to: "openclaw",
365
+ type: input.type,
366
+ requiresResponse: true,
367
+ body: input.body,
368
+ metadata: input.metadata,
369
+ now: identity.now
370
+ });
371
+ if (!input.conversation.gateway_method) {
372
+ return {
373
+ callbackMessage,
374
+ delivered: false
375
+ };
376
+ }
377
+ return {
378
+ callbackMessage,
379
+ prepared: prepare({
380
+ options: {
381
+ ...input.options,
382
+ statePath: input.statePath,
383
+ log: input.logPath,
384
+ messageJson: JSON.stringify(callbackMessage),
385
+ gatewayMethod: input.conversation.gateway_method,
386
+ gatewaySession: input.conversation.gateway_session,
387
+ openclawSession: input.conversation.openclaw_session,
388
+ openclawBin: input.conversation.openclaw_bin,
389
+ gatewayUrl: stringValue(input.conversation.gateway_token)
390
+ ? input.conversation.gateway_url
391
+ : undefined,
392
+ token: stringValue(input.conversation.gateway_token),
393
+ preserveMessageId: true,
394
+ callbackDeliveryKind: "approval_notification",
395
+ recoverMissingOutbox: input.recoverMissingOutbox === true,
396
+ conversationOverride: input.conversation
397
+ },
398
+ logPath: input.logPath
399
+ })
400
+ };
401
+ }
402
+ function terminalApprovalCallbackIdentity(conversation) {
403
+ const nativeTakeover = isRecord(conversation.native_session_takeover)
404
+ ? conversation.native_session_takeover
405
+ : undefined;
406
+ const approval = isRecord(nativeTakeover?.terminal_bridge_approval)
407
+ ? nativeTakeover.terminal_bridge_approval
408
+ : undefined;
409
+ const id = stringValue(approval?.callback_message_id);
410
+ const timestamp = stringValue(approval?.callback_message_ts);
411
+ const timestampMs = Date.parse(String(timestamp ?? ""));
412
+ if (!id || !Number.isFinite(timestampMs)) {
413
+ throw new Error("terminal approval notification has no stable callback identity");
414
+ }
415
+ return { id, now: new Date(timestampMs) };
416
+ }
417
+ export function deterministicTerminalCallbackMessageId(input) {
418
+ const digest = createHash("sha256")
419
+ .update(JSON.stringify({
420
+ conversation_id: input.conversationId,
421
+ terminal_message_id: input.terminalMessageId,
422
+ completion_fingerprint: input.completionFingerprint,
423
+ outcome: input.outcome
424
+ }))
425
+ .digest("hex")
426
+ .slice(0, 32);
427
+ return `msg-terminal-${digest}`;
428
+ }
429
+ export function terminalBridgeCompletionFingerprint(input) {
430
+ const metadata = isRecord(input.completion.metadata)
431
+ ? input.completion.metadata
432
+ : {};
433
+ const match = stringValue(metadata.match) ??
434
+ (input.completion.source === "screen"
435
+ ? "terminal_screen"
436
+ : "durable_completion");
437
+ return createHash("sha256")
438
+ .update(JSON.stringify({
439
+ text: input.completion.text,
440
+ timestamp: input.completion.timestamp,
441
+ match,
442
+ source: input.completion.source,
443
+ id: input.completion.id,
444
+ message_id: input.terminalMessageId
445
+ }))
446
+ .digest("hex");
447
+ }
448
+ function prepareTerminalCompletion(ports, prepare, input) {
449
+ const completionFingerprint = input.completionFingerprint ??
450
+ terminalBridgeCompletionFingerprint(input);
451
+ const completionMetadata = isRecord(input.completion.metadata)
452
+ ? input.completion.metadata
453
+ : {};
454
+ const completionMatch = stringValue(completionMetadata.match) ??
455
+ (input.completion.source === "screen"
456
+ ? "terminal_screen"
457
+ : "durable_completion");
458
+ const completionOutcome = input.completion.outcome === "failure"
459
+ ? "failure"
460
+ : "success";
461
+ const callbackMessageId = deterministicTerminalCallbackMessageId({
462
+ conversationId: input.conversationId,
463
+ terminalMessageId: input.terminalMessageId,
464
+ completionFingerprint,
465
+ outcome: completionOutcome
466
+ });
467
+ const transaction = ports.state.withTransaction(input.statePath, () => {
468
+ const claim = claimTerminalCompletion(ports, {
469
+ statePath: input.statePath,
470
+ logPath: input.logPath,
471
+ terminalMessageId: input.terminalMessageId,
472
+ completionFingerprint,
473
+ completionId: input.completion.id,
474
+ callbackMessageId,
475
+ outcome: completionOutcome,
476
+ allowSupersedeRecovery: input.allowSupersedeRecovery === true
477
+ });
478
+ if (!claim.claimed) {
479
+ return claim;
480
+ }
481
+ ports.state.append(input.logPath, {
482
+ ts: ports.runtime.now().toISOString(),
483
+ conversation_id: claim.conversation.conversation_id,
484
+ event: "terminal_bridge_completion_detected",
485
+ terminal_control: input.terminalControl,
486
+ match: completionMatch,
487
+ completion_source: input.completion.source,
488
+ completion_outcome: completionOutcome,
489
+ completion_id: input.completion.id,
490
+ terminal_session: completionMetadata.session,
491
+ context_match: completionMetadata.context_match,
492
+ assistant_timestamp: input.completion.timestamp,
493
+ rollout_turn_id: input.completion.source === "durable"
494
+ ? input.completion.id
495
+ : undefined,
496
+ terminal_bridge_message_id: input.terminalMessageId,
497
+ callback_message_id: callbackMessageId
498
+ });
499
+ const callbackMessage = {
500
+ ...createMessage({
501
+ conversation: claim.conversation,
502
+ from: input.actor,
503
+ to: "openclaw",
504
+ type: completionOutcome === "failure" ? "error" : "done",
505
+ requiresResponse: false,
506
+ body: input.completion.text,
507
+ metadata: {
508
+ source: "terminal_bridge",
509
+ terminal_control: input.terminalControl,
510
+ ...completionMetadata,
511
+ completion_source: input.completion.source,
512
+ completion_outcome: completionOutcome,
513
+ completion_id: input.completion.id,
514
+ terminal_session: completionMetadata.session,
515
+ confidence: input.completion.confidence,
516
+ match: completionMatch,
517
+ assistant_timestamp: input.completion.timestamp,
518
+ rollout_turn_id: input.completion.source === "durable"
519
+ ? input.completion.id
520
+ : undefined,
521
+ terminal_bridge_message_id: input.terminalMessageId
522
+ }
523
+ }),
524
+ id: callbackMessageId
525
+ };
526
+ const prepared = prepare({
527
+ options: {
528
+ ...input.options,
529
+ statePath: input.statePath,
530
+ log: input.logPath,
531
+ closeTerminalBridgeOnDone: false,
532
+ recoverTerminalCompletion: claim.resumed,
533
+ allowTerminalCompletionRecoveryStatus: input.allowSupersedeRecovery === true,
534
+ preserveMessageId: true,
535
+ messageJson: JSON.stringify(callbackMessage),
536
+ gatewayMethod: claim.conversation.gateway_method,
537
+ gatewaySession: claim.conversation.gateway_session,
538
+ openclawSession: claim.conversation.openclaw_session,
539
+ openclawBin: claim.conversation.openclaw_bin,
540
+ gatewayUrl: stringValue(claim.conversation.gateway_token)
541
+ ? claim.conversation.gateway_url
542
+ : undefined,
543
+ token: stringValue(claim.conversation.gateway_token),
544
+ recordOnly: !stringValue(claim.conversation.gateway_method)
545
+ },
546
+ logPath: input.logPath
547
+ });
548
+ if (prepared.outcome === "record_only") {
549
+ ports.runtime.crashCheckpoint("after_local_completion_state");
550
+ }
551
+ return {
552
+ claimed: true,
553
+ conversation: claim.conversation,
554
+ prepared,
555
+ callbackMessageId
556
+ };
557
+ });
558
+ if (!transaction.claimed) {
559
+ return transaction;
560
+ }
561
+ if (!ports.authority.resolveCompletionDispatch({
562
+ terminalControl: input.terminalControl,
563
+ conversation: transaction.conversation,
564
+ expectedMessageId: input.terminalMessageId,
565
+ reason: "terminal bridge task reached durable completion"
566
+ })) {
567
+ throw new Error(`terminal completion ${transaction.conversation.conversation_id} ` +
568
+ "changed before its dispatch ledger could be settled");
569
+ }
570
+ return transaction;
571
+ }
572
+ function claimTerminalCompletion(ports, input) {
573
+ const conversation = ports.state.load(input.statePath);
574
+ const nativeTakeover = isRecord(conversation.native_session_takeover)
575
+ ? conversation.native_session_takeover
576
+ : {};
577
+ if (!isWaitingForAgentStatus(conversation.status) &&
578
+ !(input.allowSupersedeRecovery &&
579
+ isTerminalBridgeCallbackSupersedeStatus(conversation.status))) {
580
+ return {
581
+ claimed: false,
582
+ conversation,
583
+ reason: "conversation_no_longer_waiting"
584
+ };
585
+ }
586
+ if (stringValue(nativeTakeover.terminal_bridge_message_id) !==
587
+ input.terminalMessageId) {
588
+ return {
589
+ claimed: false,
590
+ conversation,
591
+ reason: "terminal_bridge_task_replaced"
592
+ };
593
+ }
594
+ const existing = isRecord(nativeTakeover.terminal_bridge_completion_claim)
595
+ ? nativeTakeover.terminal_bridge_completion_claim
596
+ : undefined;
597
+ if (existing) {
598
+ if (existing.callback_message_id === input.callbackMessageId &&
599
+ existing.terminal_bridge_message_id === input.terminalMessageId &&
600
+ existing.completion_fingerprint === input.completionFingerprint &&
601
+ existing.outcome === input.outcome) {
602
+ ports.state.append(input.logPath, {
603
+ ts: ports.runtime.now().toISOString(),
604
+ conversation_id: conversation.conversation_id,
605
+ event: "terminal_bridge_completion_claim_resumed",
606
+ terminal_bridge_message_id: input.terminalMessageId,
607
+ completion_fingerprint: input.completionFingerprint,
608
+ callback_message_id: input.callbackMessageId,
609
+ outcome: input.outcome
610
+ });
611
+ return {
612
+ claimed: true,
613
+ resumed: true,
614
+ conversation
615
+ };
616
+ }
617
+ return {
618
+ claimed: false,
619
+ conversation,
620
+ reason: "terminal_bridge_completion_claim_conflict"
621
+ };
622
+ }
623
+ const claimedAt = ports.runtime.now().toISOString();
624
+ const claimedConversation = {
625
+ ...conversation,
626
+ native_session_takeover: {
627
+ ...nativeTakeover,
628
+ terminal_bridge_completion_claim: {
629
+ terminal_bridge_message_id: input.terminalMessageId,
630
+ completion_fingerprint: input.completionFingerprint,
631
+ completion_id: input.completionId,
632
+ callback_message_id: input.callbackMessageId,
633
+ outcome: input.outcome,
634
+ claimed_at: claimedAt
635
+ }
636
+ },
637
+ updated_at: claimedAt
638
+ };
639
+ ports.state.save(input.statePath, claimedConversation);
640
+ ports.state.append(input.logPath, {
641
+ ts: claimedAt,
642
+ conversation_id: conversation.conversation_id,
643
+ event: "terminal_bridge_completion_claimed",
644
+ terminal_bridge_message_id: input.terminalMessageId,
645
+ completion_fingerprint: input.completionFingerprint,
646
+ completion_id: input.completionId,
647
+ callback_message_id: input.callbackMessageId,
648
+ outcome: input.outcome
649
+ });
650
+ return {
651
+ claimed: true,
652
+ resumed: false,
653
+ conversation: claimedConversation
654
+ };
655
+ }
656
+ function retryCallback(ports, settlement, { options, conversation, statePath, logPath }) {
657
+ const callbackDelivery = isRecord(conversation.callback_delivery)
658
+ ? conversation.callback_delivery
659
+ : undefined;
660
+ const legacyStatusError = stringValue(conversation.legacy_callback_status_error);
661
+ if (legacyStatusError) {
662
+ throw new Error(`cannot retry callback for ${conversation.conversation_id}; ` +
663
+ `legacy Turn phase is ambiguous: ${legacyStatusError}`);
664
+ }
665
+ const disposition = callbackRetryDisposition(ports, callbackDelivery);
666
+ if (disposition.state === "accepted") {
667
+ const recovered = settlement.settleAccepted({
668
+ statePath,
669
+ logPath,
670
+ expectedMessageId: isRecord(callbackDelivery?.message)
671
+ ? stringValue(callbackDelivery.message.id)
672
+ : undefined,
673
+ reason: "manual_retry_observed_accepted_transport"
674
+ });
675
+ if (!recovered) {
676
+ throw new Error(`cannot retry callback for ${conversation.conversation_id}; ` +
677
+ "callback delivery changed while accepted transport was being recovered");
678
+ }
679
+ return {
680
+ kind: "recovered",
681
+ result: {
682
+ delivered: true,
683
+ duplicate: false,
684
+ conversation: recovered,
685
+ message: callbackDelivery?.message,
686
+ delivery: "accepted_transport_recovered"
687
+ }
688
+ };
689
+ }
690
+ rejectManualRetryDisposition(conversation, disposition);
691
+ if (!callbackDelivery || !isRecord(callbackDelivery.message)) {
692
+ throw new Error(`cannot retry callback for ${conversation.conversation_id}; pending callback is missing`);
693
+ }
694
+ const gatewayRoute = resolveCallbackGatewayRoute({ gatewayUrl: options.gatewayUrl, token: options.token }, {
695
+ gatewayUrl: callbackDelivery.gateway_url,
696
+ token: callbackDelivery.gateway_token
697
+ }, {
698
+ gatewayUrl: conversation.gateway_url,
699
+ token: conversation.gateway_token
700
+ });
701
+ return {
702
+ kind: "retried",
703
+ result: ports.delivery.runTransaction({
704
+ ...options,
705
+ statePath,
706
+ messageJson: JSON.stringify(callbackDelivery.message),
707
+ gatewayMethod: stringValue(callbackDelivery.gateway_method) ??
708
+ conversation.gateway_method,
709
+ gatewaySession: stringValue(callbackDelivery.gateway_session) ??
710
+ conversation.gateway_session,
711
+ openclawSession: conversation.openclaw_session,
712
+ openclawBin: stringValue(callbackDelivery.openclaw_bin) ??
713
+ conversation.openclaw_bin,
714
+ gatewayUrl: gatewayRoute.gatewayUrl,
715
+ token: gatewayRoute.token,
716
+ closeTerminalBridgeOnDone: callbackDelivery.close_terminal_bridge_on_done === true,
717
+ retryPending: true
718
+ })
719
+ };
720
+ }
721
+ function callbackRetryDisposition(ports, callbackDelivery) {
722
+ let policy = beginCallbackRetryPolicy(callbackDelivery, {
723
+ attemptLeaseMs: ports.retry.attemptLeaseMs,
724
+ retryDelayCount: ports.retry.delaysMs.length
725
+ });
726
+ if (policy.phase === "decided") {
727
+ return policy.disposition;
728
+ }
729
+ policy = reduceCallbackRetryPolicy(policy, {
730
+ kind: "process_alive",
731
+ alive: ports.retry.isProcessAlive(policy.attempt_pid)
732
+ });
733
+ if (policy.phase === "decided") {
734
+ return policy.disposition;
735
+ }
736
+ policy = reduceCallbackRetryPolicy(policy, {
737
+ kind: "clock",
738
+ now_ms: ports.runtime.nowMs()
739
+ });
740
+ if (policy.phase !== "decided") {
741
+ throw new Error("callback retry policy did not reach a decision");
742
+ }
743
+ return policy.disposition;
744
+ }
745
+ function rejectManualRetryDisposition(conversation, disposition) {
746
+ if (disposition.state === "in_flight") {
747
+ throw new Error(`cannot retry callback for ${conversation.conversation_id}; callback ` +
748
+ `attempt ${disposition.attempt} is in flight` +
749
+ (disposition.attempt_pid === undefined
750
+ ? ""
751
+ : ` (pid ${disposition.attempt_pid})`) +
752
+ (disposition.lease_expires_at
753
+ ? ` with lease until ${disposition.lease_expires_at}`
754
+ : "") +
755
+ (disposition.next_attempt_at
756
+ ? `; automatic retry is scheduled for ${disposition.next_attempt_at}`
757
+ : ""));
758
+ }
759
+ if (disposition.state === "exhausted") {
760
+ throw new Error(`cannot retry callback for ${conversation.conversation_id}; callback ` +
761
+ `delivery retries are exhausted after attempt ${disposition.attempt}`);
762
+ }
763
+ if (disposition.state !== "retryable") {
764
+ throw new Error(`cannot retry callback for ${conversation.conversation_id}; ` +
765
+ disposition.reason);
766
+ }
767
+ }
768
+ function reconcileCallbackDelivery(ports, settlement, { statePath, logPath, delayMs }) {
769
+ return ports.state.withTransaction(statePath, () => {
770
+ const conversation = ports.state.load(statePath);
771
+ const legacyStatusError = stringValue(conversation.legacy_callback_status_error);
772
+ if (legacyStatusError) {
773
+ return {
774
+ handled: true,
775
+ conversationId: conversation.conversation_id,
776
+ status: "skipped",
777
+ reason: "legacy_callback_status_ambiguous",
778
+ diagnostic: legacyStatusError
779
+ };
780
+ }
781
+ const callbackDelivery = isRecord(conversation.callback_delivery)
782
+ ? conversation.callback_delivery
783
+ : undefined;
784
+ if (!["pending", "failed"].includes(String(callbackDelivery?.status ?? ""))) {
785
+ return { handled: false };
786
+ }
787
+ ports.authority.assertNoDeferredTransfer({
788
+ storeDir: ports.state.storeDirForStatePath(statePath),
789
+ conversation,
790
+ action: "reconcile callback delivery for"
791
+ });
792
+ const conversationId = stringValue(conversation.conversation_id) ??
793
+ "unknown";
794
+ const attempts = Number(callbackDelivery?.attempts ?? 0);
795
+ if (!["pending", "failed"].includes(String(callbackDelivery?.status ?? "")) ||
796
+ !isRecord(callbackDelivery?.message)) {
797
+ return {
798
+ handled: true,
799
+ conversationId,
800
+ status: "skipped",
801
+ reason: "callback_delivery_metadata_missing"
802
+ };
803
+ }
804
+ const disposition = callbackRetryDisposition(ports, callbackDelivery);
805
+ if (disposition.state === "accepted") {
806
+ const settled = settlement.settleAcceptedWhileLocked({
807
+ conversation,
808
+ statePath,
809
+ logPath,
810
+ expectedMessageId: stringValue(callbackDelivery.message.id),
811
+ reason: "startup_reconciliation_observed_accepted_transport"
812
+ });
813
+ return {
814
+ handled: true,
815
+ conversationId,
816
+ status: settled ? "recovered" : "skipped",
817
+ reason: settled
818
+ ? "callback_delivery_accepted_recovered"
819
+ : "callback_delivery_changed_before_recovery"
820
+ };
821
+ }
822
+ if (disposition.state === "in_flight") {
823
+ return {
824
+ handled: true,
825
+ conversationId,
826
+ status: "already_running",
827
+ reason: "callback_delivery_attempt_in_flight",
828
+ attempt: disposition.attempt,
829
+ attemptPid: disposition.attempt_pid,
830
+ leaseExpiresAt: disposition.lease_expires_at,
831
+ nextAttemptAt: disposition.next_attempt_at
832
+ };
833
+ }
834
+ if (disposition.state === "exhausted") {
835
+ return {
836
+ handled: true,
837
+ conversationId,
838
+ status: "skipped",
839
+ reason: "callback_delivery_retries_exhausted"
840
+ };
841
+ }
842
+ if (disposition.state !== "retryable") {
843
+ return {
844
+ handled: true,
845
+ conversationId,
846
+ status: "skipped",
847
+ reason: disposition.reason
848
+ };
849
+ }
850
+ const configuredDelayMs = Number(delayMs);
851
+ const retryDelayMs = Number.isFinite(configuredDelayMs) &&
852
+ configuredDelayMs >= 0
853
+ ? configuredDelayMs
854
+ : ports.retry.delaysMs[Math.max(0, attempts - 1)];
855
+ const retryMonitor = ports.retry.startMonitor({ statePath, delayMs: retryDelayMs });
856
+ const launchedAt = ports.runtime.now().toISOString();
857
+ const nextAttemptAt = new Date(ports.runtime.nowMs() + retryDelayMs).toISOString();
858
+ ports.state.save(statePath, {
859
+ ...conversation,
860
+ callback_delivery: {
861
+ ...callbackDelivery,
862
+ retry_monitor_pid: retryMonitor.pid ?? null,
863
+ next_attempt_at: nextAttemptAt,
864
+ updated_at: launchedAt
865
+ }
866
+ });
867
+ ports.state.append(logPath, {
868
+ ts: launchedAt,
869
+ conversation_id: conversationId,
870
+ event: "callback_retry_monitor_launched",
871
+ message_id: callbackDelivery.message.id,
872
+ pid: retryMonitor.pid ?? null,
873
+ next_attempt_at: nextAttemptAt,
874
+ reason: "startup_reconciliation"
875
+ });
876
+ return {
877
+ handled: true,
878
+ conversationId,
879
+ status: "launched",
880
+ reason: "callback_delivery_reconciliation",
881
+ monitorPid: retryMonitor.pid
882
+ };
883
+ });
884
+ }
885
+ function runCallbackRetryMonitor(ports, settlement, { statePath, initialDelayMs }) {
886
+ const configuredDelayMs = Number(initialDelayMs);
887
+ ports.runtime.sleepSync(Math.max(0, Number.isFinite(configuredDelayMs)
888
+ ? configuredDelayMs
889
+ : ports.retry.delaysMs[0]));
890
+ while (true) {
891
+ const observed = observeCallbackRetryMonitor(ports, statePath);
892
+ if (observed.kind === "stop") {
893
+ return;
894
+ }
895
+ if (observed.kind === "accepted") {
896
+ settleRetryMonitorAcceptance(ports, settlement, statePath, observed.messageId);
897
+ return;
898
+ }
899
+ if (observed.kind === "in_flight") {
900
+ ports.runtime.sleepSync(1000);
901
+ continue;
902
+ }
903
+ try {
904
+ ports.delivery.runTransaction(retryMonitorDeliveryOptions(statePath, observed));
905
+ return;
906
+ }
907
+ catch {
908
+ // The failed attempt is persisted before the next bounded retry.
909
+ }
910
+ const latest = observeCallbackRetryMonitor(ports, statePath);
911
+ if (latest.kind === "accepted") {
912
+ settleRetryMonitorAcceptance(ports, settlement, statePath, latest.messageId);
913
+ return;
914
+ }
915
+ if (latest.kind !== "retryable" ||
916
+ latest.attempts > ports.retry.delaysMs.length ||
917
+ latest.attempts <= observed.attempts) {
918
+ return;
919
+ }
920
+ ports.runtime.sleepSync(ports.retry.delaysMs[Math.max(0, latest.attempts - 1)]);
921
+ }
922
+ }
923
+ function observeCallbackRetryMonitor(ports, statePath) {
924
+ const conversation = ports.state.load(statePath);
925
+ if (stringValue(conversation.legacy_callback_status_error)) {
926
+ return { kind: "stop" };
927
+ }
928
+ const delivery = isRecord(conversation.callback_delivery)
929
+ ? conversation.callback_delivery
930
+ : undefined;
931
+ if (!delivery ||
932
+ !isRecord(delivery.message) ||
933
+ !["pending", "failed"].includes(String(delivery.status ?? ""))) {
934
+ return { kind: "stop" };
935
+ }
936
+ const disposition = callbackRetryDisposition(ports, delivery);
937
+ if (disposition.state === "accepted") {
938
+ return {
939
+ kind: "accepted",
940
+ messageId: stringValue(delivery.message.id)
941
+ };
942
+ }
943
+ if (disposition.state === "in_flight") {
944
+ return { kind: "in_flight" };
945
+ }
946
+ if (disposition.state !== "retryable") {
947
+ return { kind: "stop" };
948
+ }
949
+ return {
950
+ kind: "retryable",
951
+ conversation,
952
+ delivery,
953
+ attempts: Number(delivery.attempts ?? 0)
954
+ };
955
+ }
956
+ function retryMonitorDeliveryOptions(statePath, observed) {
957
+ const { conversation, delivery } = observed;
958
+ const gatewayRoute = resolveCallbackGatewayRoute({
959
+ gatewayUrl: delivery.gateway_url,
960
+ token: delivery.gateway_token
961
+ }, {
962
+ gatewayUrl: conversation.gateway_url,
963
+ token: conversation.gateway_token
964
+ });
965
+ return {
966
+ statePath,
967
+ messageJson: JSON.stringify(delivery.message),
968
+ gatewayMethod: stringValue(delivery.gateway_method) ??
969
+ conversation.gateway_method,
970
+ gatewaySession: stringValue(delivery.gateway_session) ??
971
+ conversation.gateway_session,
972
+ openclawSession: conversation.openclaw_session,
973
+ openclawBin: stringValue(delivery.openclaw_bin) ?? conversation.openclaw_bin,
974
+ gatewayUrl: gatewayRoute.gatewayUrl,
975
+ token: gatewayRoute.token,
976
+ closeTerminalBridgeOnDone: delivery.close_terminal_bridge_on_done === true,
977
+ retryPending: true,
978
+ disableCallbackRetry: true
979
+ };
980
+ }
981
+ function settleRetryMonitorAcceptance(ports, settlement, statePath, expectedMessageId) {
982
+ settlement.settleAccepted({
983
+ statePath,
984
+ logPath: ports.state.logPathForStatePath(statePath),
985
+ expectedMessageId,
986
+ reason: "retry_monitor_observed_accepted_transport"
987
+ });
988
+ }
989
+ function requiredMessageJson(value) {
990
+ if (value === undefined || value === "") {
991
+ throw new Error("--message-json is required");
992
+ }
993
+ return value;
994
+ }
995
+ function rejectNonRetryableDelivery(disposition) {
996
+ if (disposition.state === "in_flight") {
997
+ throw new Error(`callback attempt ${disposition.attempt} is already in flight` +
998
+ (disposition.attempt_pid === undefined
999
+ ? ""
1000
+ : ` (pid ${disposition.attempt_pid})`) +
1001
+ (disposition.lease_expires_at
1002
+ ? ` with lease until ${disposition.lease_expires_at}`
1003
+ : ""));
1004
+ }
1005
+ if (disposition.state === "accepted") {
1006
+ throw new Error("callback transport was already accepted and must be settled, not retried");
1007
+ }
1008
+ if (disposition.state === "exhausted") {
1009
+ throw new Error(`callback retries are exhausted after attempt ${disposition.attempt}`);
1010
+ }
1011
+ throw new Error(disposition.state === "unavailable"
1012
+ ? disposition.reason
1013
+ : "callback delivery is not retryable");
1014
+ }
1015
+ function isDuplicateMessage(events, message) {
1016
+ return events.some((event) => {
1017
+ if (event.event !== "message") {
1018
+ return false;
1019
+ }
1020
+ const existing = (event.message ?? event);
1021
+ if (existing.id && existing.id === message.id) {
1022
+ return true;
1023
+ }
1024
+ return messageFingerprint(existing) === messageFingerprint(message);
1025
+ });
1026
+ }
1027
+ function exactLoggedMessageForRecovery(events, message) {
1028
+ const matchingId = events
1029
+ .filter((event) => event.event === "message")
1030
+ .map((event) => (event.message ?? event))
1031
+ .filter((existing) => existing.id === message.id);
1032
+ if (matchingId.length === 0) {
1033
+ return false;
1034
+ }
1035
+ if (matchingId.length !== 1 ||
1036
+ canonicalJson(matchingId[0]) !== canonicalJson(message)) {
1037
+ throw new Error(`callback recovery message ${message.id} conflicts with its logged payload`);
1038
+ }
1039
+ return true;
1040
+ }
1041
+ function messageFingerprint(message) {
1042
+ return JSON.stringify({
1043
+ session_id: message.session_id,
1044
+ turn_id: message.turn_id,
1045
+ conversation_id: message.conversation_id,
1046
+ from: message.from,
1047
+ to: message.to,
1048
+ type: message.type,
1049
+ requires_response: message.requires_response,
1050
+ body: message.body
1051
+ });
1052
+ }
1053
+ //# sourceMappingURL=callback-outbox-service.js.map