@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,982 @@
1
+ import { executorForConversation } from "./protocol.js";
2
+ import { terminalBridgeCompletionFingerprint } from "./callback-outbox-service.js";
3
+ import { claudeTranscriptApprovalIdentity, decideTerminalMonitorAfterEffectsTimeout, decideTerminalMonitorApproval, reduceTerminalMonitorDecision, terminalMonitorActivityFingerprint, terminalMonitorApprovalEffectOrder, terminalMonitorApprovalFingerprint, terminalMonitorScreenFingerprint, validTerminalMonitorTimestampMs } from "./terminal-monitor-decision-policy.js";
4
+ import { isRecord, nonBlankString as stringValue } from "./value-guards.js";
5
+ /** Retry Store contention without releasing the singleton monitor owner. */
6
+ export async function runTerminalMonitorWithStoreDeferral(input) {
7
+ let attempts = 0;
8
+ let firstDeferredAt;
9
+ while (true) {
10
+ try {
11
+ if (attempts > 0) {
12
+ const resumed = resumeDeferredStoreOperation(input, {
13
+ attempts,
14
+ firstDeferredAt
15
+ });
16
+ if (!resumed) {
17
+ return;
18
+ }
19
+ attempts = 0;
20
+ firstDeferredAt = undefined;
21
+ }
22
+ await input.run();
23
+ return;
24
+ }
25
+ catch (error) {
26
+ const superseded = input.ports.authority.bindingSuperseded(error);
27
+ if (superseded) {
28
+ presentBindingSuperseded(input, superseded);
29
+ return;
30
+ }
31
+ const timeout = input.ports.authority.storeOperationTimeout(error);
32
+ if (!timeout) {
33
+ throw error;
34
+ }
35
+ attempts += 1;
36
+ firstDeferredAt ??= input.ports.runtime.now().toISOString();
37
+ const retryInMs = Math.min(5_000, 250 * (2 ** Math.min(5, attempts - 1)));
38
+ input.ports.runtime.log("warn", "terminal_bridge_monitor_store_operation_deferred", {
39
+ conversation_id: input.initialConversation.conversation_id,
40
+ terminal_bridge_message_id: input.terminalMessageId,
41
+ error_code: timeout.code,
42
+ lock_kind: timeout.lockKind,
43
+ attempt: attempts,
44
+ retry_in_ms: retryInMs
45
+ });
46
+ input.ports.runtime.sleep(retryInMs);
47
+ }
48
+ }
49
+ }
50
+ function resumeDeferredStoreOperation(input, deferral) {
51
+ const resumedAt = input.ports.runtime.now().toISOString();
52
+ const conversation = input.ports.state.load();
53
+ const takeover = takeoverFor(conversation);
54
+ if (stringValue(takeover?.terminal_bridge_message_id) !== input.terminalMessageId) {
55
+ input.ports.runtime.log("info", "terminal_bridge_monitor_finished", {
56
+ conversation_id: conversation.conversation_id,
57
+ terminal_bridge_message_id: input.terminalMessageId,
58
+ reason: "terminal_bridge_generation_replaced_during_store_deferral"
59
+ });
60
+ input.ports.presentation.emit({ kind: "generation_replaced", conversation });
61
+ return false;
62
+ }
63
+ input.ports.state.appendEvent({
64
+ ts: resumedAt,
65
+ conversation_id: conversation.conversation_id,
66
+ event: "terminal_bridge_monitor_store_operation_deferred",
67
+ terminal_bridge_message_id: input.terminalMessageId,
68
+ error_code: "AKK_STORE_LOCK_TIMEOUT",
69
+ first_deferred_at: deferral.firstDeferredAt,
70
+ resumed_at: resumedAt,
71
+ attempts: deferral.attempts,
72
+ outcome: "resumed"
73
+ });
74
+ input.ports.runtime.log("info", "terminal_bridge_monitor_store_operation_resumed", {
75
+ conversation_id: conversation.conversation_id,
76
+ terminal_bridge_message_id: input.terminalMessageId,
77
+ attempts: deferral.attempts,
78
+ first_deferred_at: deferral.firstDeferredAt
79
+ });
80
+ return true;
81
+ }
82
+ function presentBindingSuperseded(input, error) {
83
+ const control = input.ports.authority.terminalControl(input.initialConversation);
84
+ input.ports.runtime.log("warn", "terminal_bridge_monitor_binding_superseded", {
85
+ conversation_id: input.initialConversation.conversation_id,
86
+ terminal_target: control?.target,
87
+ reason: error.message
88
+ });
89
+ try {
90
+ input.ports.state.appendEvent({
91
+ ts: input.ports.runtime.now().toISOString(),
92
+ conversation_id: input.initialConversation.conversation_id,
93
+ event: "terminal_bridge_monitor_binding_superseded",
94
+ terminal_control: control,
95
+ error_code: error.code,
96
+ reason: error.message
97
+ });
98
+ }
99
+ catch (diagnosticError) {
100
+ input.ports.runtime.log("warn", "terminal_bridge_monitor_diagnostic_write_failed", {
101
+ conversation_id: input.initialConversation.conversation_id,
102
+ terminal_target: control?.target,
103
+ diagnostic_event: "terminal_bridge_monitor_binding_superseded",
104
+ reason: diagnosticError instanceof Error
105
+ ? diagnosticError.message
106
+ : String(diagnosticError)
107
+ });
108
+ }
109
+ input.ports.presentation.emit({
110
+ kind: "binding_superseded",
111
+ conversation: input.initialConversation,
112
+ detail: error.message
113
+ });
114
+ }
115
+ /**
116
+ * Run one exact terminal-monitor generation after the composition root has
117
+ * acquired the singleton owner lock. All terminal, Store, state-lock, process,
118
+ * callback and presentation effects remain behind typed ports.
119
+ */
120
+ export async function runTerminalMonitor(input) {
121
+ const initialized = initializeMonitor(input);
122
+ if (initialized.kind === "finished") {
123
+ input.ports.presentation.emit(initialized.presentation);
124
+ return { startedRecorded: input.lifecycle.startedRecorded };
125
+ }
126
+ const { configuration, state } = initialized;
127
+ input.ports.authority.initialize();
128
+ if (!input.lifecycle.startedRecorded) {
129
+ recordMonitorStarted(state, configuration, input.ports);
130
+ input.lifecycle.startedRecorded = true;
131
+ }
132
+ while (true) {
133
+ const iteration = await runMonitorIteration(state, configuration, input.ports);
134
+ if (iteration === "finished") {
135
+ return { startedRecorded: input.lifecycle.startedRecorded };
136
+ }
137
+ }
138
+ }
139
+ function initializeMonitor(input) {
140
+ const conversation = input.initialConversation;
141
+ const takeover = takeoverFor(conversation);
142
+ if (stringValue(takeover?.terminal_bridge_message_id) !==
143
+ input.expectedTerminalMessageId) {
144
+ input.ports.runtime.log("info", "terminal_bridge_monitor_finished", {
145
+ conversation_id: conversation.conversation_id,
146
+ terminal_bridge_message_id: input.expectedTerminalMessageId,
147
+ reason: "terminal_bridge_generation_replaced_before_monitor_restart"
148
+ });
149
+ return {
150
+ kind: "finished",
151
+ presentation: { kind: "generation_replaced", conversation }
152
+ };
153
+ }
154
+ const configuration = input.configuration();
155
+ const nowMs = input.ports.runtime.nowMs();
156
+ const taskStartedAtMs = validTerminalMonitorTimestampMs(takeover?.terminal_bridge_started_at) ?? nowMs;
157
+ const lastActivityAtMs = validTerminalMonitorTimestampMs(takeover?.terminal_bridge_last_activity_at) ??
158
+ taskStartedAtMs;
159
+ const initialDiagnostic = isRecord(takeover?.terminal_bridge_detector_diagnostic)
160
+ ? takeover.terminal_bridge_detector_diagnostic
161
+ : undefined;
162
+ const preSendScreenFingerprint = stringValue(takeover?.terminal_bridge_pre_send_screen_fingerprint);
163
+ return {
164
+ kind: "ready",
165
+ configuration,
166
+ state: {
167
+ conversation,
168
+ executor: executorForConversation(conversation),
169
+ monitorMessageId: input.expectedTerminalMessageId,
170
+ taskStartedAtMs,
171
+ lastActivityAtMs,
172
+ lastPersistedActivityAtMs: lastActivityAtMs,
173
+ persistedActivityReason: stringValue(takeover?.terminal_bridge_last_activity_reason),
174
+ persistedDetectorDiagnosticFingerprint: stringValue(initialDiagnostic?.fingerprint),
175
+ persistedDetectorDiagnosticStatus: stringValue(initialDiagnostic?.status),
176
+ preSendScreenFingerprint,
177
+ pollPolicyState: { previousScreenFingerprint: preSendScreenFingerprint },
178
+ bindingCheckDeferredAttempts: 0
179
+ }
180
+ };
181
+ }
182
+ function recordMonitorStarted(state, configuration, ports) {
183
+ const now = ports.runtime.now().toISOString();
184
+ ports.state.appendEvent({
185
+ ts: now,
186
+ conversation_id: state.conversation.conversation_id,
187
+ event: "terminal_bridge_monitor_started",
188
+ monitor_pid: ports.runtime.pid(),
189
+ executor: state.executor,
190
+ agent_timeout_minutes: configuration.timeoutMinutes,
191
+ agent_hard_timeout_minutes: configuration.hardTimeoutMinutes,
192
+ poll_interval_ms: configuration.pollIntervalMs,
193
+ task_started_at: new Date(state.taskStartedAtMs).toISOString(),
194
+ last_activity_at: new Date(state.lastActivityAtMs).toISOString(),
195
+ inactivity_deadline_at: configuration.timeoutMinutes > 0
196
+ ? new Date(state.lastActivityAtMs + configuration.timeoutMinutes * 60 * 1000).toISOString()
197
+ : null,
198
+ hard_deadline_at: configuration.hardTimeoutMinutes > 0
199
+ ? new Date(state.taskStartedAtMs + configuration.hardTimeoutMinutes * 60 * 1000).toISOString()
200
+ : null
201
+ });
202
+ ports.runtime.log("info", "terminal_bridge_monitor_started", {
203
+ conversation_id: state.conversation.conversation_id,
204
+ monitor_pid: ports.runtime.pid(),
205
+ agent: state.executor.kind,
206
+ executor_session: state.executor.session,
207
+ agent_timeout_minutes: configuration.timeoutMinutes,
208
+ agent_hard_timeout_minutes: configuration.hardTimeoutMinutes
209
+ });
210
+ }
211
+ async function runMonitorIteration(state, configuration, ports) {
212
+ state.conversation = ports.state.load();
213
+ if (!ports.authority.isWaitingForAgent(state.conversation.status)) {
214
+ ports.runtime.log("info", "terminal_bridge_monitor_finished", {
215
+ conversation_id: state.conversation.conversation_id,
216
+ status: state.conversation.status,
217
+ reason: "conversation_no_longer_waiting"
218
+ });
219
+ ports.presentation.emit({
220
+ kind: "conversation_no_longer_waiting",
221
+ conversation: state.conversation
222
+ });
223
+ return "finished";
224
+ }
225
+ let takeover = takeoverFor(state.conversation);
226
+ const currentMessageId = stringValue(takeover?.terminal_bridge_message_id);
227
+ if (currentMessageId !== state.monitorMessageId) {
228
+ ports.state.appendEvent({
229
+ ts: ports.runtime.now().toISOString(),
230
+ conversation_id: state.conversation.conversation_id,
231
+ event: "terminal_bridge_monitor_superseded",
232
+ monitor_message_id: state.monitorMessageId,
233
+ current_message_id: currentMessageId
234
+ });
235
+ ports.presentation.emit({ kind: "task_replaced", conversation: state.conversation });
236
+ return "finished";
237
+ }
238
+ const terminalControl = ports.authority.terminalControl(state.conversation);
239
+ if (!terminalControl || takeover?.terminal_bridge !== true) {
240
+ const stalled = ports.state.markStalled("terminal bridge monitor could not find terminal bridge metadata", { terminal_bridge: true });
241
+ ports.presentation.emit({
242
+ kind: "stalled",
243
+ conversation: stalled,
244
+ reason: stringValue(stalled.stalled_reason)
245
+ });
246
+ return "finished";
247
+ }
248
+ const submissionResult = await reconcileSubmissionPhase({
249
+ state,
250
+ configuration,
251
+ ports,
252
+ terminalControl,
253
+ currentMessageId
254
+ });
255
+ if (submissionResult !== "proceed") {
256
+ return submissionResult;
257
+ }
258
+ const observed = await observeMonitorPoll({
259
+ state,
260
+ configuration,
261
+ ports,
262
+ terminalControl,
263
+ currentMessageId
264
+ });
265
+ if (observed.kind !== "observed") {
266
+ return observed.kind;
267
+ }
268
+ takeover = takeoverFor(state.conversation);
269
+ return handleObservedPoll({
270
+ state,
271
+ configuration,
272
+ ports,
273
+ terminalControl,
274
+ currentMessageId,
275
+ takeover,
276
+ poll: observed.poll
277
+ });
278
+ }
279
+ function takeoverFor(conversation) {
280
+ return isRecord(conversation.native_session_takeover)
281
+ ? conversation.native_session_takeover
282
+ : undefined;
283
+ }
284
+ async function reconcileSubmissionPhase({ state, configuration, ports, terminalControl, currentMessageId }) {
285
+ const submission = ports.authority.submission(state.conversation);
286
+ if (!currentMessageId ||
287
+ !submission ||
288
+ stringValue(submission.message_id) !== currentMessageId) {
289
+ return "proceed";
290
+ }
291
+ const status = stringValue(submission.status);
292
+ if (status === "text_injected" || status === "enter_dispatched") {
293
+ return reconcileDispatchedSubmission({
294
+ state,
295
+ configuration,
296
+ ports,
297
+ terminalControl,
298
+ currentMessageId,
299
+ submission,
300
+ status
301
+ });
302
+ }
303
+ if (status === "prepared") {
304
+ return recoverPreparedSubmission({
305
+ state,
306
+ configuration,
307
+ ports,
308
+ terminalControl,
309
+ currentMessageId,
310
+ submission
311
+ });
312
+ }
313
+ if (status === "not_accepted" || status === "uncertain" || status === "aborted") {
314
+ const safeToRetry = status === "aborted" && submission.safe_to_retry === true;
315
+ ports.presentation.emit({
316
+ kind: "submission_terminal",
317
+ conversation: state.conversation,
318
+ status,
319
+ safeToRetry
320
+ });
321
+ return "finished";
322
+ }
323
+ if (status !== "submitted" && status !== "agent_accepted") {
324
+ ports.presentation.emit({
325
+ kind: "submission_status_invalid",
326
+ conversation: state.conversation
327
+ });
328
+ return "finished";
329
+ }
330
+ return "proceed";
331
+ }
332
+ async function reconcileDispatchedSubmission({ state, configuration, ports, terminalControl, currentMessageId, submission, status }) {
333
+ const dispatcherPid = Number(submission.dispatcher_pid);
334
+ if (Number.isSafeInteger(dispatcherPid) &&
335
+ dispatcherPid > 1 &&
336
+ ports.authority.isProcessAlive(dispatcherPid)) {
337
+ ports.runtime.sleep(configuration.pollIntervalMs);
338
+ return "continue";
339
+ }
340
+ if (status === "text_injected") {
341
+ state.conversation = ports.authority.markAcceptanceUncertain({
342
+ conversation: state.conversation,
343
+ terminalControl,
344
+ reason: "terminal dispatcher exited after text injection but before Enter dispatch was durably proven"
345
+ });
346
+ ports.presentation.emit({
347
+ kind: "submission_uncertain",
348
+ conversation: state.conversation,
349
+ deliveryReceipt: "text_injected",
350
+ reason: "text was injected but native submission was not proven; inspect the composer"
351
+ });
352
+ return "finished";
353
+ }
354
+ const result = await ports.authority.reconcileAcceptance({
355
+ conversation: state.conversation,
356
+ terminalControl,
357
+ executor: state.executor,
358
+ apply: (reconciliation) => {
359
+ if (reconciliation.outcome === "accepted") {
360
+ state.conversation = reconciliation.conversation;
361
+ return "continue";
362
+ }
363
+ if (reconciliation.outcome === "not_accepted") {
364
+ ports.presentation.emit({
365
+ kind: "submission_not_accepted",
366
+ conversation: reconciliation.conversation
367
+ });
368
+ return "finished";
369
+ }
370
+ return "pending";
371
+ },
372
+ recover: (error) => {
373
+ if (ports.authority.storeOperationTimeout(error)) {
374
+ throw error;
375
+ }
376
+ const reason = error instanceof Error ? error.message : String(error);
377
+ state.conversation = ports.authority.markAcceptanceUncertain({
378
+ conversation: state.conversation,
379
+ terminalControl,
380
+ reason
381
+ });
382
+ ports.presentation.emit({
383
+ kind: "submission_uncertain",
384
+ conversation: state.conversation,
385
+ deliveryReceipt: "enter_dispatched",
386
+ reason
387
+ });
388
+ return "finished";
389
+ }
390
+ });
391
+ if (result === "pending") {
392
+ ports.runtime.sleep(configuration.pollIntervalMs);
393
+ return "continue";
394
+ }
395
+ return result;
396
+ }
397
+ async function recoverPreparedSubmission({ state, configuration, ports, terminalControl, currentMessageId, submission }) {
398
+ const dispatcherPid = Number(submission.dispatcher_pid);
399
+ if (Number.isSafeInteger(dispatcherPid) &&
400
+ dispatcherPid > 1 &&
401
+ ports.authority.isProcessAlive(dispatcherPid)) {
402
+ ports.runtime.sleep(configuration.pollIntervalMs);
403
+ return "continue";
404
+ }
405
+ state.conversation = await ports.authority.recoverPreparedSubmission({
406
+ conversation: state.conversation,
407
+ terminalControl,
408
+ currentMessageId,
409
+ dispatcherPid
410
+ });
411
+ const recovered = ports.authority.submission(state.conversation);
412
+ const recoveredStatus = stringValue(recovered?.status) ?? "uncertain";
413
+ if (stringValue(recovered?.message_id) === currentMessageId &&
414
+ (recoveredStatus === "submitted" || recoveredStatus === "agent_accepted")) {
415
+ return "continue";
416
+ }
417
+ ports.presentation.emit({
418
+ kind: "submission_unproven",
419
+ conversation: state.conversation,
420
+ status: recoveredStatus
421
+ });
422
+ return "finished";
423
+ }
424
+ async function observeMonitorPoll({ state, configuration, ports, terminalControl, currentMessageId }) {
425
+ try {
426
+ ports.authority.assertBindingCurrent(state.conversation);
427
+ }
428
+ catch (error) {
429
+ const lockTimeout = ports.authority.storeLeaseTimeout(error);
430
+ if (!lockTimeout) {
431
+ if (!ports.authority.bindingSuperseded(error)) {
432
+ ports.runtime.log("error", "terminal_bridge_monitor_binding_check_failed", {
433
+ conversation_id: state.conversation.conversation_id,
434
+ terminal_target: terminalControl.target,
435
+ error_code: isRecord(error) ? stringValue(error.code) : undefined,
436
+ reason: error instanceof Error ? error.message : String(error)
437
+ });
438
+ }
439
+ throw error;
440
+ }
441
+ state.bindingCheckDeferredAttempts += 1;
442
+ state.bindingCheckFirstDeferredAt ??= ports.runtime.now().toISOString();
443
+ const backoffMs = Math.min(5_000, 250 * (2 ** Math.min(5, state.bindingCheckDeferredAttempts - 1)));
444
+ ports.runtime.log("warn", "terminal_bridge_monitor_binding_check_deferred", {
445
+ conversation_id: state.conversation.conversation_id,
446
+ terminal_target: terminalControl.target,
447
+ error_code: lockTimeout.code,
448
+ lock_kind: lockTimeout.lockKind,
449
+ attempt: state.bindingCheckDeferredAttempts,
450
+ retry_in_ms: backoffMs
451
+ });
452
+ ports.runtime.sleep(backoffMs);
453
+ return { kind: "continue" };
454
+ }
455
+ if (!recordBindingCheckResumed(state, configuration, ports, terminalControl)) {
456
+ return { kind: "continue" };
457
+ }
458
+ const screenChangedSinceSend = state.preSendScreenFingerprint !== undefined &&
459
+ state.pollPolicyState.previousScreenFingerprint !== undefined &&
460
+ state.pollPolicyState.previousScreenFingerprint !==
461
+ state.preSendScreenFingerprint;
462
+ const result = await ports.authority.poll({
463
+ conversation: state.conversation,
464
+ terminalControl,
465
+ currentMessageId,
466
+ executor: state.executor,
467
+ screenChangedSinceSend,
468
+ onFenced: (ledgerStatus) => ports.presentation.emit({
469
+ kind: "dispatch_fenced",
470
+ conversation: state.conversation,
471
+ ledgerStatus
472
+ })
473
+ });
474
+ if (result.kind === "retry") {
475
+ state.conversation = result.conversation;
476
+ return { kind: "continue" };
477
+ }
478
+ if (result.kind === "fenced") {
479
+ return { kind: "finished" };
480
+ }
481
+ return result;
482
+ }
483
+ function recordBindingCheckResumed(state, configuration, ports, terminalControl) {
484
+ if (state.bindingCheckDeferredAttempts === 0) {
485
+ return true;
486
+ }
487
+ const resumedAt = ports.runtime.now().toISOString();
488
+ try {
489
+ ports.state.appendEvent({
490
+ ts: resumedAt,
491
+ conversation_id: state.conversation.conversation_id,
492
+ event: "terminal_bridge_monitor_binding_check_deferred",
493
+ terminal_control: terminalControl,
494
+ error_code: "AKK_STORE_LOCK_TIMEOUT",
495
+ lock_kind: "writer",
496
+ first_deferred_at: state.bindingCheckFirstDeferredAt,
497
+ resumed_at: resumedAt,
498
+ attempts: state.bindingCheckDeferredAttempts,
499
+ outcome: "resumed"
500
+ });
501
+ ports.runtime.log("info", "terminal_bridge_monitor_binding_check_resumed", {
502
+ conversation_id: state.conversation.conversation_id,
503
+ terminal_target: terminalControl.target,
504
+ attempts: state.bindingCheckDeferredAttempts,
505
+ first_deferred_at: state.bindingCheckFirstDeferredAt
506
+ });
507
+ state.bindingCheckDeferredAttempts = 0;
508
+ state.bindingCheckFirstDeferredAt = undefined;
509
+ return true;
510
+ }
511
+ catch (error) {
512
+ const lockTimeout = ports.authority.storeLeaseTimeout(error);
513
+ if (!lockTimeout) {
514
+ throw error;
515
+ }
516
+ ports.runtime.log("warn", "terminal_bridge_monitor_diagnostic_write_deferred", {
517
+ conversation_id: state.conversation.conversation_id,
518
+ terminal_target: terminalControl.target,
519
+ error_code: lockTimeout.code,
520
+ lock_kind: lockTimeout.lockKind
521
+ });
522
+ ports.runtime.sleep(Math.max(250, configuration.pollIntervalMs));
523
+ return false;
524
+ }
525
+ }
526
+ async function handleObservedPoll(input) {
527
+ const terminalStatus = input.poll.status;
528
+ const sampledStatus = { ...input, terminalStatus };
529
+ const diagnostic = persistDetectorDiagnostic(sampledStatus);
530
+ if (!diagnostic.proceed) {
531
+ return "continue";
532
+ }
533
+ const currentScreenFingerprint = terminalScreenFingerprint(terminalStatus);
534
+ const sampledApproval = {
535
+ ...sampledStatus,
536
+ currentScreenFingerprint
537
+ };
538
+ const approval = handleApprovalObservation({
539
+ ...sampledApproval,
540
+ takeover: diagnostic.takeover
541
+ });
542
+ if (approval !== "proceed") {
543
+ return approval;
544
+ }
545
+ const durable = input.poll.durableCompletion;
546
+ const durableFingerprint = durable
547
+ ? terminalMonitorActivityFingerprint(JSON.stringify({
548
+ text: durable.text,
549
+ timestamp: durable.timestamp,
550
+ id: durable.id,
551
+ metadata: durable.metadata
552
+ }))
553
+ : undefined;
554
+ const completion = input.poll.completion;
555
+ const completionMetadata = isRecord(completion?.metadata)
556
+ ? completion.metadata
557
+ : {};
558
+ const completionFingerprint = completion
559
+ ? terminalBridgeCompletionFingerprint({
560
+ completion,
561
+ terminalMessageId: input.currentMessageId
562
+ })
563
+ : undefined;
564
+ return handleCompletionAndTimeout({
565
+ ...sampledApproval,
566
+ durableFingerprint,
567
+ completion,
568
+ completionMetadata,
569
+ completionFingerprint
570
+ });
571
+ }
572
+ function persistDetectorDiagnostic(input) {
573
+ const { state, configuration, ports, terminalControl, currentMessageId, terminalStatus } = input;
574
+ const limitation = stringValue(terminalStatus.capability_limitation);
575
+ const fingerprint = limitation
576
+ ? terminalMonitorActivityFingerprint(limitation)
577
+ : undefined;
578
+ const changed = limitation
579
+ ? fingerprint !== state.persistedDetectorDiagnosticFingerprint ||
580
+ state.persistedDetectorDiagnosticStatus !== "limited"
581
+ : state.persistedDetectorDiagnosticStatus === "limited";
582
+ if (!changed) {
583
+ return { proceed: true, takeover: input.takeover };
584
+ }
585
+ try {
586
+ const persisted = ports.state.persistDetectorDiagnostic({
587
+ expectedConversationId: state.conversation.conversation_id,
588
+ expectedMessageId: currentMessageId,
589
+ limitation,
590
+ fingerprint
591
+ });
592
+ if (persisted.diagnostic) {
593
+ state.conversation = persisted.conversation;
594
+ const takeover = takeoverFor(state.conversation);
595
+ state.persistedDetectorDiagnosticFingerprint = stringValue(persisted.diagnostic.fingerprint);
596
+ state.persistedDetectorDiagnosticStatus = stringValue(persisted.diagnostic.status);
597
+ return { proceed: true, takeover };
598
+ }
599
+ return { proceed: true, takeover: input.takeover };
600
+ }
601
+ catch (error) {
602
+ const lockTimeout = ports.authority.storeLeaseTimeout(error);
603
+ if (!lockTimeout) {
604
+ throw error;
605
+ }
606
+ ports.runtime.log("warn", "terminal_bridge_detector_diagnostic_deferred", {
607
+ conversation_id: state.conversation.conversation_id,
608
+ terminal_target: terminalControl.target,
609
+ error_code: lockTimeout.code,
610
+ lock_kind: lockTimeout.lockKind
611
+ });
612
+ ports.runtime.sleep(Math.max(250, configuration.pollIntervalMs));
613
+ return { proceed: false, takeover: input.takeover };
614
+ }
615
+ }
616
+ function handleApprovalObservation(input) {
617
+ const { state, configuration, ports, terminalControl, terminalStatus, currentMessageId, currentScreenFingerprint } = input;
618
+ const approval = terminalStatus.approval_state;
619
+ const currentScreenChangedSinceSend = state.preSendScreenFingerprint !== undefined &&
620
+ currentScreenFingerprint !== undefined &&
621
+ currentScreenFingerprint !== state.preSendScreenFingerprint;
622
+ const claudePermissionVisible = state.executor.kind === "claude" &&
623
+ approval.blocked === true &&
624
+ approval.prompt_kind === "claude_permission";
625
+ const observedFingerprint = claudePermissionVisible
626
+ ? terminalMonitorApprovalFingerprint({ terminalControl, terminalStatus })
627
+ : undefined;
628
+ const decision = decideTerminalMonitorApproval({
629
+ executorKind: state.executor.kind,
630
+ executorDisplayName: state.executor.display_name,
631
+ terminalReachable: terminalStatus.reachable,
632
+ approval,
633
+ nativeTakeover: input.takeover,
634
+ currentMessageId,
635
+ currentScreenFingerprint,
636
+ currentScreenChangedSinceSend,
637
+ observedFingerprint,
638
+ transcriptIdentity: claudePermissionVisible
639
+ ? claudeTranscriptApprovalIdentity(approval)
640
+ : undefined
641
+ });
642
+ if (decision.markPromptCleared) {
643
+ const cleared = ports.state.markApprovalPromptCleared({
644
+ expectedConversationId: state.conversation.conversation_id,
645
+ expectedMessageId: currentMessageId
646
+ });
647
+ if (cleared.marked) {
648
+ state.conversation = cleared.conversation;
649
+ }
650
+ }
651
+ for (const suppression of decision.suppressions) {
652
+ state.pollPolicyState = {
653
+ ...state.pollPolicyState,
654
+ previousScreenFingerprint: currentScreenFingerprint
655
+ };
656
+ logApprovalSuppression(input, suppression);
657
+ }
658
+ if (decision.notification.kind === "none") {
659
+ return "proceed";
660
+ }
661
+ return deliverApprovalNotification({
662
+ state,
663
+ configuration,
664
+ ports,
665
+ terminalControl,
666
+ terminalStatus,
667
+ currentMessageId,
668
+ currentScreenFingerprint,
669
+ notification: decision.notification.kind === "question"
670
+ ? { kind: "question" }
671
+ : {
672
+ kind: "error",
673
+ reason: decision.notification.reason ??
674
+ "Claude Code permission state cannot be safely resolved through AKK"
675
+ }
676
+ });
677
+ }
678
+ function logApprovalSuppression(input, suppression) {
679
+ const detail = {
680
+ conversation_id: input.state.conversation.conversation_id,
681
+ terminal_target: input.terminalControl.target
682
+ };
683
+ if (suppression.kind === "screen_not_new") {
684
+ input.ports.runtime.log("warn", "claude_screen_approval_not_new", {
685
+ ...detail,
686
+ reason: "permission screen is not proven to have changed since the managed send"
687
+ });
688
+ return;
689
+ }
690
+ input.ports.runtime.log("info", "claude_consumed_approval_screen_still_visible", {
691
+ ...detail,
692
+ fingerprint: suppression.fingerprint,
693
+ screen_digest: suppression.screenDigest,
694
+ reason: suppression.reason
695
+ });
696
+ }
697
+ function deliverApprovalNotification(input) {
698
+ const { state, configuration, ports, terminalControl, terminalStatus, currentMessageId, currentScreenFingerprint } = input;
699
+ const question = input.notification.kind === "question";
700
+ const reason = input.notification.kind === "error"
701
+ ? input.notification.reason
702
+ : undefined;
703
+ const order = terminalMonitorApprovalEffectOrder(question ? "question" : "error");
704
+ let fingerprint = order[0] === "fingerprint"
705
+ ? terminalMonitorApprovalFingerprint({ terminalControl, terminalStatus })
706
+ : undefined;
707
+ appendApprovalEvent(input, question, fingerprint, reason);
708
+ if (order[1] === "fingerprint") {
709
+ fingerprint = terminalMonitorApprovalFingerprint({
710
+ terminalControl,
711
+ terminalStatus
712
+ });
713
+ }
714
+ const notification = ports.state.recordApprovalNotification({
715
+ conversation: state.conversation,
716
+ executor: state.executor,
717
+ terminalControl,
718
+ terminalStatus,
719
+ currentMessageId,
720
+ fingerprint,
721
+ kind: question ? "question" : "error",
722
+ reason
723
+ });
724
+ if (notification.stale) {
725
+ state.pollPolicyState = {
726
+ ...state.pollPolicyState,
727
+ previousScreenFingerprint: currentScreenFingerprint
728
+ };
729
+ ports.runtime.sleep(configuration.pollIntervalMs);
730
+ return "continue";
731
+ }
732
+ if (notification.duplicate) {
733
+ ports.presentation.emit({
734
+ kind: "approval_duplicate",
735
+ conversation: notification.conversation,
736
+ terminalControl,
737
+ terminalStatus,
738
+ approvable: question,
739
+ ...(!question ? { reason } : {})
740
+ });
741
+ return "finished";
742
+ }
743
+ const prepared = notification.recorded?.prepared;
744
+ if (!prepared) {
745
+ ports.presentation.emit({
746
+ kind: "approval_gateway_missing",
747
+ conversation: notification.conversation,
748
+ callbackMessage: notification.recorded?.callbackMessage,
749
+ terminalControl,
750
+ terminalStatus,
751
+ approvable: question
752
+ });
753
+ return "finished";
754
+ }
755
+ if (!question) {
756
+ ports.callbacks.run(prepared);
757
+ return "finished";
758
+ }
759
+ return runApprovableCallback({
760
+ ...input,
761
+ fingerprint,
762
+ prepared
763
+ });
764
+ }
765
+ function appendApprovalEvent(input, question, fingerprint, reason) {
766
+ input.ports.state.appendEvent(question
767
+ ? {
768
+ ts: input.ports.runtime.now().toISOString(),
769
+ conversation_id: input.state.conversation.conversation_id,
770
+ event: "terminal_bridge_approval_detected",
771
+ terminal_control: input.terminalControl,
772
+ activity_state: input.terminalStatus.activity_state,
773
+ activity_reason: input.terminalStatus.activity_reason,
774
+ fingerprint
775
+ }
776
+ : {
777
+ ts: input.ports.runtime.now().toISOString(),
778
+ conversation_id: input.state.conversation.conversation_id,
779
+ event: "terminal_bridge_approval_not_approvable",
780
+ terminal_control: input.terminalControl,
781
+ activity_state: input.terminalStatus.activity_state,
782
+ reason
783
+ });
784
+ }
785
+ function runApprovableCallback(input) {
786
+ const { state, configuration, ports, terminalControl, currentMessageId, currentScreenFingerprint, fingerprint, prepared } = input;
787
+ const result = ports.callbacks.run(prepared, { emit: false });
788
+ if (result.delivered && ports.runtime.exitAfterApprovalCallback()) {
789
+ ports.state.appendEvent({
790
+ ts: ports.runtime.now().toISOString(),
791
+ conversation_id: state.conversation.conversation_id,
792
+ event: "terminal_bridge_test_exit_after_approval_callback_delivered",
793
+ terminal_control: terminalControl,
794
+ fingerprint
795
+ });
796
+ ports.runtime.exit(86);
797
+ }
798
+ const afterCallback = ports.state.load();
799
+ const takeover = takeoverFor(afterCallback);
800
+ const consumed = ports.authority.isWaitingForAgent(afterCallback.status) &&
801
+ takeover?.terminal_bridge_approval === undefined &&
802
+ stringValue(takeover?.terminal_bridge_message_id) === currentMessageId &&
803
+ stringValue(takeover?.terminal_bridge_last_approval_message_id) ===
804
+ currentMessageId &&
805
+ stringValue(takeover?.terminal_bridge_last_approval_fingerprint) ===
806
+ fingerprint;
807
+ if (!consumed) {
808
+ ports.callbacks.emit(result);
809
+ return "finished";
810
+ }
811
+ state.conversation = afterCallback;
812
+ state.pollPolicyState = {
813
+ previousScreenFingerprint: currentScreenFingerprint
814
+ };
815
+ state.lastActivityAtMs =
816
+ validTerminalMonitorTimestampMs(takeover?.terminal_bridge_last_activity_at) ??
817
+ ports.runtime.nowMs();
818
+ state.lastPersistedActivityAtMs = state.lastActivityAtMs;
819
+ state.persistedActivityReason = stringValue(takeover?.terminal_bridge_last_activity_reason);
820
+ ports.state.appendEvent({
821
+ ts: ports.runtime.now().toISOString(),
822
+ conversation_id: afterCallback.conversation_id,
823
+ event: "terminal_bridge_monitor_continued_after_approval",
824
+ terminal_control: terminalControl,
825
+ fingerprint
826
+ });
827
+ ports.runtime.sleep(configuration.pollIntervalMs);
828
+ return "continue";
829
+ }
830
+ async function handleCompletionAndTimeout(input) {
831
+ const { state, configuration, ports, terminalStatus, currentScreenFingerprint, durableFingerprint, completion, completionFingerprint } = input;
832
+ const decision = reduceTerminalMonitorDecision({
833
+ state: state.pollPolicyState,
834
+ activityState: terminalStatus.activity_state,
835
+ activityReason: terminalStatus.activity_reason,
836
+ screenFingerprint: currentScreenFingerprint,
837
+ durableFingerprint,
838
+ completionPresent: Boolean(completion),
839
+ completionFingerprint
840
+ });
841
+ state.pollPolicyState = decision.state;
842
+ if (decision.activity.activityReason !== undefined) {
843
+ const observedAtMs = ports.runtime.nowMs();
844
+ state.lastActivityAtMs = observedAtMs;
845
+ if (state.persistedActivityReason === undefined ||
846
+ observedAtMs - state.lastPersistedActivityAtMs >=
847
+ configuration.activityPersistIntervalMs) {
848
+ state.conversation = ports.state.persistActivity({
849
+ conversation: state.conversation,
850
+ observedAtMs,
851
+ reason: decision.activity.activityReason,
852
+ activityState: terminalStatus.activity_state,
853
+ timeoutMinutes: configuration.timeoutMinutes,
854
+ hardTimeoutMinutes: configuration.hardTimeoutMinutes
855
+ });
856
+ state.lastPersistedActivityAtMs = observedAtMs;
857
+ state.persistedActivityReason = decision.activity.activityReason;
858
+ if (!ports.authority.isWaitingForAgent(state.conversation.status)) {
859
+ return "continue";
860
+ }
861
+ }
862
+ }
863
+ return applyMonitorNextAction({
864
+ ...input,
865
+ completion,
866
+ nextAction: decision.next
867
+ });
868
+ }
869
+ async function applyMonitorNextAction(input) {
870
+ const { state, ports, terminalControl, currentMessageId } = input;
871
+ if (input.completion && input.nextAction.kind === "complete") {
872
+ const prepared = ports.callbacks.prepareCompletion({
873
+ conversation: state.conversation,
874
+ executor: state.executor,
875
+ terminalControl,
876
+ terminalMessageId: currentMessageId ?? state.monitorMessageId,
877
+ completion: input.completion,
878
+ completionFingerprint: input.nextAction.completionFingerprint
879
+ });
880
+ if (!prepared.claimed) {
881
+ ports.presentation.emit({
882
+ kind: "completion_duplicate",
883
+ conversation: prepared.conversation,
884
+ reason: prepared.reason
885
+ });
886
+ return "finished";
887
+ }
888
+ ports.callbacks.run(prepared.prepared);
889
+ return "finished";
890
+ }
891
+ if (input.nextAction.kind === "verify_dead") {
892
+ const dead = await ports.callbacks.verifiedDead({
893
+ conversationId: state.conversation.conversation_id,
894
+ messageId: currentMessageId
895
+ });
896
+ if (dead.completionPreparation) {
897
+ const preparation = dead.completionPreparation;
898
+ if (!preparation.claimed) {
899
+ ports.presentation.emit({
900
+ kind: "completion_duplicate",
901
+ conversation: preparation.conversation,
902
+ reason: preparation.reason
903
+ });
904
+ return "finished";
905
+ }
906
+ ports.callbacks.run(preparation.prepared);
907
+ return "finished";
908
+ }
909
+ if (dead.stalled) {
910
+ ports.presentation.emit({
911
+ kind: "stalled",
912
+ conversation: dead.conversation,
913
+ reason: dead.reason
914
+ });
915
+ return "finished";
916
+ }
917
+ }
918
+ return handleTimeout(input);
919
+ }
920
+ function handleTimeout(input) {
921
+ const { state, configuration, ports, terminalControl, terminalStatus, completionMetadata } = input;
922
+ const nowMs = ports.runtime.nowMs();
923
+ const decision = decideTerminalMonitorAfterEffectsTimeout({
924
+ nowMs,
925
+ taskStartedAtMs: state.taskStartedAtMs,
926
+ lastActivityAtMs: state.lastActivityAtMs,
927
+ hardTimeoutMinutes: configuration.hardTimeoutMinutes,
928
+ inactivityTimeoutMinutes: configuration.timeoutMinutes
929
+ });
930
+ if (decision.kind === "poll") {
931
+ ports.runtime.sleep(configuration.pollIntervalMs);
932
+ return "continue";
933
+ }
934
+ if (decision.kind === "hard_timeout") {
935
+ ports.state.appendEvent({
936
+ ts: new Date(nowMs).toISOString(),
937
+ conversation_id: state.conversation.conversation_id,
938
+ event: "terminal_bridge_hard_timeout_reached",
939
+ terminal_control: terminalControl,
940
+ task_started_at: new Date(state.taskStartedAtMs).toISOString(),
941
+ hard_deadline_at: new Date(decision.deadlineAtMs).toISOString(),
942
+ agent_hard_timeout_minutes: configuration.hardTimeoutMinutes,
943
+ last_activity_at: new Date(state.lastActivityAtMs).toISOString(),
944
+ terminal_activity_state: terminalStatus.activity_state
945
+ });
946
+ const stalled = ports.state.markStalled(`terminal bridge reached its hard lifetime of ${configuration.hardTimeoutMinutes} minutes`, {
947
+ terminal_bridge: true,
948
+ terminal_control: terminalControl,
949
+ task_started_at: new Date(state.taskStartedAtMs).toISOString(),
950
+ last_activity_at: new Date(state.lastActivityAtMs).toISOString(),
951
+ agent_hard_timeout_minutes: configuration.hardTimeoutMinutes,
952
+ terminal_activity_state: terminalStatus.activity_state
953
+ });
954
+ ports.presentation.emit({
955
+ kind: "stalled",
956
+ conversation: stalled,
957
+ hardTimeout: true,
958
+ reason: stringValue(stalled.stalled_reason)
959
+ });
960
+ return "finished";
961
+ }
962
+ const stalled = ports.state.markStalled(`terminal bridge observed no activity for ${configuration.timeoutMinutes} minutes`, {
963
+ terminal_bridge: true,
964
+ terminal_control: terminalControl,
965
+ match: completionMetadata.context_match,
966
+ terminal_activity_state: terminalStatus.activity_state,
967
+ last_activity_at: new Date(state.lastActivityAtMs).toISOString(),
968
+ inactivity_deadline_at: new Date(decision.deadlineAtMs).toISOString(),
969
+ agent_timeout_minutes: configuration.timeoutMinutes
970
+ });
971
+ ports.presentation.emit({
972
+ kind: "stalled",
973
+ conversation: stalled,
974
+ reason: stringValue(stalled.stalled_reason)
975
+ });
976
+ return "finished";
977
+ }
978
+ function terminalScreenFingerprint(status) {
979
+ return stringValue(status.screen.digest) ??
980
+ terminalMonitorScreenFingerprint(status.screen.excerpt);
981
+ }
982
+ //# sourceMappingURL=terminal-monitor-application-service.js.map