@scotthuang/agent-knock-knock 0.13.2 → 0.13.4

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 (278) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +27 -6
  3. package/dist/src/callback-outbox-policy.js +27 -6
  4. package/dist/src/callback-outbox-policy.js.map +1 -1
  5. package/dist/src/callback-outbox-service.d.ts +4 -30
  6. package/dist/src/callback-outbox-service.js +21 -154
  7. package/dist/src/callback-outbox-service.js.map +1 -1
  8. package/dist/src/callback-outbox-settlement.js +13 -8
  9. package/dist/src/callback-outbox-settlement.js.map +1 -1
  10. package/dist/src/callback-route-service.d.ts +46 -0
  11. package/dist/src/callback-route-service.js +155 -0
  12. package/dist/src/callback-route-service.js.map +1 -0
  13. package/dist/src/claude-terminal-agent-adapter.js +4 -0
  14. package/dist/src/claude-terminal-agent-adapter.js.map +1 -1
  15. package/dist/src/cli-core.js +9 -1
  16. package/dist/src/cli-core.js.map +1 -1
  17. package/dist/src/codex-process-incarnation.d.ts +8 -0
  18. package/dist/src/codex-process-incarnation.js +36 -0
  19. package/dist/src/codex-process-incarnation.js.map +1 -0
  20. package/dist/src/codex-terminal-agent-adapter.js +4 -0
  21. package/dist/src/codex-terminal-agent-adapter.js.map +1 -1
  22. package/dist/src/deferred-foreground-conflict-policy.d.ts +22 -0
  23. package/dist/src/deferred-foreground-conflict-policy.js +52 -0
  24. package/dist/src/deferred-foreground-conflict-policy.js.map +1 -0
  25. package/dist/src/durable-notification-kernel.d.ts +94 -0
  26. package/dist/src/durable-notification-kernel.js +68 -0
  27. package/dist/src/durable-notification-kernel.js.map +1 -0
  28. package/dist/src/herdr-socket-transport.d.ts +43 -0
  29. package/dist/src/herdr-socket-transport.js +170 -0
  30. package/dist/src/herdr-socket-transport.js.map +1 -0
  31. package/dist/src/herdr-terminal-control-provider.d.ts +2 -45
  32. package/dist/src/herdr-terminal-control-provider.js +8 -173
  33. package/dist/src/herdr-terminal-control-provider.js.map +1 -1
  34. package/dist/src/host-adapter-capabilities.d.ts +35 -0
  35. package/dist/src/host-adapter-capabilities.js +146 -0
  36. package/dist/src/host-adapter-capabilities.js.map +1 -0
  37. package/dist/src/host-adapter.d.ts +9 -3
  38. package/dist/src/host-adapter.js +33 -9
  39. package/dist/src/host-adapter.js.map +1 -1
  40. package/dist/src/host-bridge-tools.d.ts +3 -4
  41. package/dist/src/host-bridge-tools.js +49 -92
  42. package/dist/src/host-bridge-tools.js.map +1 -1
  43. package/dist/src/host-bridge.js +5 -5
  44. package/dist/src/host-bridge.js.map +1 -1
  45. package/dist/src/host-monitor-reconciliation.d.ts +6 -0
  46. package/dist/src/host-monitor-reconciliation.js +96 -0
  47. package/dist/src/host-monitor-reconciliation.js.map +1 -0
  48. package/dist/src/managed-session.js +2 -18
  49. package/dist/src/managed-session.js.map +1 -1
  50. package/dist/src/native-thread-lifecycle-cli-adapter.d.ts +13 -0
  51. package/dist/src/native-thread-lifecycle-cli-adapter.js +635 -3
  52. package/dist/src/native-thread-lifecycle-cli-adapter.js.map +1 -1
  53. package/dist/src/openclaw-list-projection.d.ts +2 -0
  54. package/dist/src/openclaw-list-projection.js +3 -0
  55. package/dist/src/openclaw-list-projection.js.map +1 -0
  56. package/dist/src/openclaw-model-facing-field-policy.d.ts +2 -0
  57. package/dist/src/openclaw-model-facing-field-policy.js +3 -0
  58. package/dist/src/openclaw-model-facing-field-policy.js.map +1 -0
  59. package/dist/src/openclaw-plugin-command-adapter.d.ts +6 -29
  60. package/dist/src/openclaw-plugin-command-adapter.js +7 -2370
  61. package/dist/src/openclaw-plugin-command-adapter.js.map +1 -1
  62. package/dist/src/openclaw-plugin-helpers.d.ts +2 -121
  63. package/dist/src/openclaw-plugin-helpers.js +2 -1164
  64. package/dist/src/openclaw-plugin-helpers.js.map +1 -1
  65. package/dist/src/openclaw-plugin-schemas.d.ts +2 -510
  66. package/dist/src/openclaw-plugin-schemas.js +2 -519
  67. package/dist/src/openclaw-plugin-schemas.js.map +1 -1
  68. package/dist/src/openclaw-plugin-supervisor.d.ts +4 -5
  69. package/dist/src/openclaw-plugin-supervisor.js +5 -94
  70. package/dist/src/openclaw-plugin-supervisor.js.map +1 -1
  71. package/dist/src/openclaw-plugin-value-helpers.d.ts +2 -0
  72. package/dist/src/openclaw-plugin-value-helpers.js +3 -0
  73. package/dist/src/openclaw-plugin-value-helpers.js.map +1 -0
  74. package/dist/src/openclaw-private-authority-offers.d.ts +4 -39
  75. package/dist/src/openclaw-private-authority-offers.js +3 -258
  76. package/dist/src/openclaw-private-authority-offers.js.map +1 -1
  77. package/dist/src/semantic-private-authority-offers.d.ts +41 -0
  78. package/dist/src/semantic-private-authority-offers.js +261 -0
  79. package/dist/src/semantic-private-authority-offers.js.map +1 -0
  80. package/dist/src/semantic-tool-arguments.d.ts +9 -0
  81. package/dist/src/semantic-tool-arguments.js +64 -0
  82. package/dist/src/semantic-tool-arguments.js.map +1 -0
  83. package/dist/src/semantic-tool-catalog.d.ts +48 -0
  84. package/dist/src/semantic-tool-catalog.js +105 -0
  85. package/dist/src/semantic-tool-catalog.js.map +1 -0
  86. package/dist/src/semantic-tool-command-helpers.d.ts +145 -0
  87. package/dist/src/semantic-tool-command-helpers.js +1272 -0
  88. package/dist/src/semantic-tool-command-helpers.js.map +1 -0
  89. package/dist/src/semantic-tool-list-projection.d.ts +10 -0
  90. package/dist/src/semantic-tool-list-projection.js +497 -0
  91. package/dist/src/semantic-tool-list-projection.js.map +1 -0
  92. package/dist/src/semantic-tool-model-facing-field-policy.d.ts +3 -0
  93. package/dist/src/semantic-tool-model-facing-field-policy.js +66 -0
  94. package/dist/src/semantic-tool-model-facing-field-policy.js.map +1 -0
  95. package/dist/src/semantic-tool-presentation.d.ts +37 -0
  96. package/dist/src/semantic-tool-presentation.js +680 -0
  97. package/dist/src/semantic-tool-presentation.js.map +1 -0
  98. package/dist/src/semantic-tool-private-authority.d.ts +39 -0
  99. package/dist/src/semantic-tool-private-authority.js +602 -0
  100. package/dist/src/semantic-tool-private-authority.js.map +1 -0
  101. package/dist/src/semantic-tool-relay.d.ts +16 -0
  102. package/dist/src/semantic-tool-relay.js +175 -0
  103. package/dist/src/semantic-tool-relay.js.map +1 -0
  104. package/dist/src/semantic-tool-runtime.d.ts +10 -0
  105. package/dist/src/semantic-tool-runtime.js +1157 -0
  106. package/dist/src/semantic-tool-runtime.js.map +1 -0
  107. package/dist/src/semantic-tool-schemas.d.ts +563 -0
  108. package/dist/src/semantic-tool-schemas.js +573 -0
  109. package/dist/src/semantic-tool-schemas.js.map +1 -0
  110. package/dist/src/semantic-tool-value-helpers.d.ts +5 -0
  111. package/dist/src/semantic-tool-value-helpers.js +27 -0
  112. package/dist/src/semantic-tool-value-helpers.js.map +1 -0
  113. package/dist/src/store-event-presentation.d.ts +17 -0
  114. package/dist/src/store-event-presentation.js +33 -0
  115. package/dist/src/store-event-presentation.js.map +1 -0
  116. package/dist/src/store.d.ts +3 -16
  117. package/dist/src/store.js +2 -30
  118. package/dist/src/store.js.map +1 -1
  119. package/dist/src/terminal-action-projection.d.ts +3 -17
  120. package/dist/src/terminal-action-projection.js +13 -41
  121. package/dist/src/terminal-action-projection.js.map +1 -1
  122. package/dist/src/terminal-agent-adapter.d.ts +7 -0
  123. package/dist/src/terminal-agent-adapter.js +8 -0
  124. package/dist/src/terminal-agent-adapter.js.map +1 -1
  125. package/dist/src/terminal-agent-bridge.d.ts +35 -332
  126. package/dist/src/terminal-agent-bridge.js +293 -2798
  127. package/dist/src/terminal-agent-bridge.js.map +1 -1
  128. package/dist/src/terminal-approval-cli-adapter.d.ts +17 -0
  129. package/dist/src/terminal-approval-cli-adapter.js +921 -0
  130. package/dist/src/terminal-approval-cli-adapter.js.map +1 -0
  131. package/dist/src/terminal-command-cli-adapter.d.ts +2 -429
  132. package/dist/src/terminal-command-cli-adapter.js +344 -6061
  133. package/dist/src/terminal-command-cli-adapter.js.map +1 -1
  134. package/dist/src/terminal-command-cli-ports.d.ts +443 -0
  135. package/dist/src/terminal-command-cli-ports.js +2 -0
  136. package/dist/src/terminal-command-cli-ports.js.map +1 -0
  137. package/dist/src/terminal-command-dispatch-preparation.d.ts +81 -0
  138. package/dist/src/terminal-command-dispatch-preparation.js +209 -0
  139. package/dist/src/terminal-command-dispatch-preparation.js.map +1 -0
  140. package/dist/src/terminal-command-dispatch-transport.d.ts +35 -0
  141. package/dist/src/terminal-command-dispatch-transport.js +859 -0
  142. package/dist/src/terminal-command-dispatch-transport.js.map +1 -0
  143. package/dist/src/terminal-command-foreground-proof.d.ts +32 -0
  144. package/dist/src/terminal-command-foreground-proof.js +72 -0
  145. package/dist/src/terminal-command-foreground-proof.js.map +1 -0
  146. package/dist/src/terminal-command-send-preflight.d.ts +41 -0
  147. package/dist/src/terminal-command-send-preflight.js +86 -0
  148. package/dist/src/terminal-command-send-preflight.js.map +1 -0
  149. package/dist/src/terminal-composer-classifier.d.ts +55 -0
  150. package/dist/src/terminal-composer-classifier.js +638 -0
  151. package/dist/src/terminal-composer-classifier.js.map +1 -0
  152. package/dist/src/terminal-control-ref.d.ts +23 -0
  153. package/dist/src/terminal-control-ref.js +32 -0
  154. package/dist/src/terminal-control-ref.js.map +1 -1
  155. package/dist/src/terminal-dispatch-recovery-authority.d.ts +56 -0
  156. package/dist/src/terminal-dispatch-recovery-authority.js +251 -0
  157. package/dist/src/terminal-dispatch-recovery-authority.js.map +1 -0
  158. package/dist/src/terminal-dispatch-recovery-cli-adapter.d.ts +1 -9
  159. package/dist/src/terminal-dispatch-recovery-cli-adapter.js +5 -240
  160. package/dist/src/terminal-dispatch-recovery-cli-adapter.js.map +1 -1
  161. package/dist/src/terminal-handoff-cli-adapter.d.ts +1 -11
  162. package/dist/src/terminal-handoff-cli-adapter.js +2 -39
  163. package/dist/src/terminal-handoff-cli-adapter.js.map +1 -1
  164. package/dist/src/terminal-human-explicit-send-cli-adapter.d.ts +25 -0
  165. package/dist/src/terminal-human-explicit-send-cli-adapter.js +903 -0
  166. package/dist/src/terminal-human-explicit-send-cli-adapter.js.map +1 -0
  167. package/dist/src/terminal-identity-authority-cli-adapter.d.ts +1 -6
  168. package/dist/src/terminal-identity-authority-cli-adapter.js +3 -33
  169. package/dist/src/terminal-identity-authority-cli-adapter.js.map +1 -1
  170. package/dist/src/terminal-interaction-cli-adapter.js +209 -210
  171. package/dist/src/terminal-interaction-cli-adapter.js.map +1 -1
  172. package/dist/src/terminal-interaction-core.d.ts +0 -2
  173. package/dist/src/terminal-interaction-core.js +4 -3
  174. package/dist/src/terminal-interaction-core.js.map +1 -1
  175. package/dist/src/terminal-interaction-protocol.d.ts +21 -0
  176. package/dist/src/terminal-interaction-protocol.js +74 -0
  177. package/dist/src/terminal-interaction-protocol.js.map +1 -1
  178. package/dist/src/terminal-interaction-response-bridge.d.ts +126 -0
  179. package/dist/src/terminal-interaction-response-bridge.js +579 -0
  180. package/dist/src/terminal-interaction-response-bridge.js.map +1 -0
  181. package/dist/src/terminal-interaction-response-transaction.d.ts +44 -0
  182. package/dist/src/terminal-interaction-response-transaction.js +56 -0
  183. package/dist/src/terminal-interaction-response-transaction.js.map +1 -0
  184. package/dist/src/terminal-list-action-policy.d.ts +43 -0
  185. package/dist/src/terminal-list-action-policy.js +164 -0
  186. package/dist/src/terminal-list-action-policy.js.map +1 -0
  187. package/dist/src/terminal-list-cli-adapter.d.ts +6 -36
  188. package/dist/src/terminal-list-cli-adapter.js +314 -1711
  189. package/dist/src/terminal-list-cli-adapter.js.map +1 -1
  190. package/dist/src/terminal-list-facts.d.ts +129 -0
  191. package/dist/src/terminal-list-facts.js +179 -0
  192. package/dist/src/terminal-list-facts.js.map +1 -0
  193. package/dist/src/terminal-list-inventory.d.ts +59 -0
  194. package/dist/src/terminal-list-inventory.js +194 -0
  195. package/dist/src/terminal-list-inventory.js.map +1 -0
  196. package/dist/src/terminal-list-ownership-service.d.ts +118 -0
  197. package/dist/src/terminal-list-ownership-service.js +1003 -0
  198. package/dist/src/terminal-list-ownership-service.js.map +1 -0
  199. package/dist/src/terminal-list-projection-service.d.ts +49 -0
  200. package/dist/src/terminal-list-projection-service.js +407 -0
  201. package/dist/src/terminal-list-projection-service.js.map +1 -0
  202. package/dist/src/terminal-list-renderer.d.ts +12 -11
  203. package/dist/src/terminal-list-renderer.js +237 -104
  204. package/dist/src/terminal-list-renderer.js.map +1 -1
  205. package/dist/src/terminal-managed-send-cli-adapter.d.ts +33 -0
  206. package/dist/src/terminal-managed-send-cli-adapter.js +994 -0
  207. package/dist/src/terminal-managed-send-cli-adapter.js.map +1 -0
  208. package/dist/src/terminal-managed-turn-list-action-policy.d.ts +47 -0
  209. package/dist/src/terminal-managed-turn-list-action-policy.js +64 -0
  210. package/dist/src/terminal-managed-turn-list-action-policy.js.map +1 -0
  211. package/dist/src/terminal-model-control-action-policy.d.ts +60 -0
  212. package/dist/src/terminal-model-control-action-policy.js +96 -0
  213. package/dist/src/terminal-model-control-action-policy.js.map +1 -0
  214. package/dist/src/terminal-model-control-availability.d.ts +68 -0
  215. package/dist/src/terminal-model-control-availability.js +157 -0
  216. package/dist/src/terminal-model-control-availability.js.map +1 -0
  217. package/dist/src/terminal-model-control-bridge.d.ts +48 -0
  218. package/dist/src/terminal-model-control-bridge.js +259 -0
  219. package/dist/src/terminal-model-control-bridge.js.map +1 -0
  220. package/dist/src/terminal-model-control-profile.d.ts +55 -0
  221. package/dist/src/terminal-model-control-profile.js +137 -0
  222. package/dist/src/terminal-model-control-profile.js.map +1 -0
  223. package/dist/src/terminal-model-control-subject.d.ts +34 -0
  224. package/dist/src/terminal-model-control-subject.js +58 -0
  225. package/dist/src/terminal-model-control-subject.js.map +1 -0
  226. package/dist/src/terminal-model-control-transaction.d.ts +19 -0
  227. package/dist/src/terminal-model-control-transaction.js +39 -0
  228. package/dist/src/terminal-model-control-transaction.js.map +1 -0
  229. package/dist/src/terminal-model-control.d.ts +331 -0
  230. package/dist/src/terminal-model-control.js +1686 -0
  231. package/dist/src/terminal-model-control.js.map +1 -0
  232. package/dist/src/terminal-monitor-application-service.js +50 -17
  233. package/dist/src/terminal-monitor-application-service.js.map +1 -1
  234. package/dist/src/terminal-native-inspection-bridge.d.ts +211 -0
  235. package/dist/src/terminal-native-inspection-bridge.js +1127 -0
  236. package/dist/src/terminal-native-inspection-bridge.js.map +1 -0
  237. package/dist/src/terminal-runtime-cli-adapter.d.ts +2 -0
  238. package/dist/src/terminal-runtime-cli-adapter.js +59 -17
  239. package/dist/src/terminal-runtime-cli-adapter.js.map +1 -1
  240. package/dist/src/terminal-submission-retry-application.d.ts +24 -0
  241. package/dist/src/terminal-submission-retry-application.js +402 -0
  242. package/dist/src/terminal-submission-retry-application.js.map +1 -0
  243. package/dist/src/terminal-submission-retry-ports.d.ts +30 -0
  244. package/dist/src/terminal-submission-retry-ports.js +2 -0
  245. package/dist/src/terminal-submission-retry-ports.js.map +1 -0
  246. package/dist/src/terminal-submission-retry-reconciliation.d.ts +236 -0
  247. package/dist/src/terminal-submission-retry-reconciliation.js +1130 -0
  248. package/dist/src/terminal-submission-retry-reconciliation.js.map +1 -0
  249. package/dist/src/terminal-submission-retry-transport.d.ts +58 -0
  250. package/dist/src/terminal-submission-retry-transport.js +675 -0
  251. package/dist/src/terminal-submission-retry-transport.js.map +1 -0
  252. package/dist/src/terminal-text-submission-bridge.d.ts +200 -0
  253. package/dist/src/terminal-text-submission-bridge.js +632 -0
  254. package/dist/src/terminal-text-submission-bridge.js.map +1 -0
  255. package/dist/src/terminal-user-explicit-send-policy.d.ts +29 -0
  256. package/dist/src/terminal-user-explicit-send-policy.js +46 -0
  257. package/dist/src/terminal-user-explicit-send-policy.js.map +1 -0
  258. package/dist/src/terminal-watch-cli-adapter.js +91 -143
  259. package/dist/src/terminal-watch-cli-adapter.js.map +1 -1
  260. package/dist/src/terminal-watch-codec.d.ts +9 -0
  261. package/dist/src/terminal-watch-codec.js +1051 -0
  262. package/dist/src/terminal-watch-codec.js.map +1 -0
  263. package/dist/src/terminal-watch-interaction-response-store.d.ts +19 -0
  264. package/dist/src/terminal-watch-interaction-response-store.js +87 -0
  265. package/dist/src/terminal-watch-interaction-response-store.js.map +1 -0
  266. package/dist/src/terminal-watch-record.d.ts +319 -0
  267. package/dist/src/terminal-watch-record.js +742 -0
  268. package/dist/src/terminal-watch-record.js.map +1 -0
  269. package/dist/src/terminal-watch-service.js +48 -27
  270. package/dist/src/terminal-watch-service.js.map +1 -1
  271. package/dist/src/terminal-watch-store.d.ts +3 -279
  272. package/dist/src/terminal-watch-store.js +5 -1779
  273. package/dist/src/terminal-watch-store.js.map +1 -1
  274. package/docs/quickstart-herdr.md +1 -1
  275. package/docs/quickstart-tmux.md +27 -2
  276. package/openclaw.plugin.json +13 -1
  277. package/package.json +7 -2
  278. package/templates/openclaw-skills/agent-knock-knock/SKILL.md +54 -11
@@ -0,0 +1,632 @@
1
+ import { createHash } from "node:crypto";
2
+ import { claudeInjectedPasteProofEligible, revalidateClaudeComposerProof, settleClaudeInjectedPasteComposer } from "./claude-injected-paste-proof.js";
3
+ import { TerminalControlInputNotSentError } from "./terminal-control-provider.js";
4
+ // Verified Codex profiles through 0.154.0 keep Enter in paste/newline mode for
5
+ // 120ms after burst input. Cross that boundary rather than landing on it, and
6
+ // also require observable composer stability instead of treating this delay
7
+ // alone as acceptance.
8
+ export const CODEX_PASTE_ENTER_SETTLE_MS = 121;
9
+ export const CODEX_MULTILINE_SETTLE_POLL_MS = 30;
10
+ // A capture can itself take longer than the old two-second deadline on a busy
11
+ // tmux server. Give repaint discovery a bounded five-second window and, once
12
+ // an exact frame has been observed, always allow the required stable/final
13
+ // captures to complete instead of letting the first I/O consume their budget.
14
+ const CODEX_MULTILINE_SETTLE_TIMEOUT_MS = 5_000;
15
+ export const CODEX_MULTILINE_STABLE_CAPTURES = 2;
16
+ export const CODEX_EXACT_CANDIDATE_GRACE_CAPTURES = 8;
17
+ export const CODEX_MULTILINE_SETTLE_SCROLLBACK_LINES = 240;
18
+ /** A terminal send failed at a boundary that proves input never started. */
19
+ export class TerminalInputNotStartedError extends Error {
20
+ code = "AKK_TERMINAL_INPUT_NOT_STARTED";
21
+ constructor(message, options = {}) {
22
+ super(message, options);
23
+ this.name = "TerminalInputNotStartedError";
24
+ }
25
+ }
26
+ /**
27
+ * Text is already in the terminal composer, but this bridge invocation proved
28
+ * that it never called the Enter transport boundary.
29
+ *
30
+ * Callers may persist this as narrow recovery evidence. It says nothing about
31
+ * whether the draft remains exact or whether a later human action submitted
32
+ * it; those facts must be re-observed under the terminal lock.
33
+ */
34
+ export class TerminalEnterDispatchNotAttemptedError extends Error {
35
+ code = "AKK_TERMINAL_ENTER_DISPATCH_NOT_ATTEMPTED";
36
+ stage = "enter_not_attempted";
37
+ constructor(message, options = {}) {
38
+ super(message, options);
39
+ this.name = "TerminalEnterDispatchNotAttemptedError";
40
+ }
41
+ }
42
+ /**
43
+ * The caller's one-shot Enter reservation was invoked, so this recovery
44
+ * attempt is permanently consumed even though C-m was not proven dispatched.
45
+ */
46
+ export class TerminalEnterDispatchReservedError extends Error {
47
+ code = "AKK_TERMINAL_ENTER_DISPATCH_RESERVED";
48
+ stage = "enter_reserved";
49
+ doNotRetry = true;
50
+ constructor(message, options = {}) {
51
+ super(message, options);
52
+ this.name = "TerminalEnterDispatchReservedError";
53
+ }
54
+ }
55
+ function terminalSendComposerRequirements(agent, multiline, options) {
56
+ const exactEmptyRetryAuthority = options.requireExactEmptyComposerAfterBeforeText;
57
+ const requireExactEmptyComposerBeforeText = options.requireExactEmptyComposerBeforeText === true;
58
+ const userExplicitEnterAfterTextWithoutComposerVeto = options.userExplicitEnterAfterTextWithoutComposerVeto === true;
59
+ if (userExplicitEnterAfterTextWithoutComposerVeto &&
60
+ (agent !== "codex" || !requireExactEmptyComposerBeforeText)) {
61
+ throw new TerminalInputNotStartedError("composer-veto-free Enter requires Codex and an exact-empty pre-text user-explicit boundary");
62
+ }
63
+ const requireExactComposer = !userExplicitEnterAfterTextWithoutComposerVeto &&
64
+ ((agent === "codex" && multiline) ||
65
+ options.requireExactComposerBeforeEnter === true ||
66
+ requireExactEmptyComposerBeforeText ||
67
+ exactEmptyRetryAuthority !== undefined);
68
+ if (exactEmptyRetryAuthority !== undefined &&
69
+ (agent !== "codex" ||
70
+ options.beforeText === undefined ||
71
+ !/^[0-9a-f]{64}$/u.test(exactEmptyRetryAuthority.preliminaryComposerDigest))) {
72
+ throw new TerminalInputNotStartedError("exact-empty replacement requires Codex, a reservation hook, and a preliminary composer digest");
73
+ }
74
+ return {
75
+ exactEmptyRetryAuthority,
76
+ requireExactEmptyComposerBeforeText,
77
+ requireExactComposer
78
+ };
79
+ }
80
+ async function recordTerminalSendStage(options, event, preserveUserInput, previousError) {
81
+ try {
82
+ await options.onTransportStage?.(event);
83
+ return previousError;
84
+ }
85
+ catch (error) {
86
+ if (!preserveUserInput)
87
+ throw error;
88
+ return previousError ?? error;
89
+ }
90
+ }
91
+ async function runTerminalSendBeforeEnter(options, context, preserveUserInput, previousError) {
92
+ try {
93
+ await options.beforeEnter?.(context);
94
+ return previousError;
95
+ }
96
+ catch (error) {
97
+ if (!preserveUserInput)
98
+ throw error;
99
+ return previousError ?? error;
100
+ }
101
+ }
102
+ async function waitForUserExplicitCodexEnter(input) {
103
+ if (!input.enabled)
104
+ return;
105
+ await input.sleep(Math.max(0, CODEX_PASTE_ENTER_SETTLE_MS -
106
+ (input.nowMs() - input.textInjectedAt)));
107
+ }
108
+ function throwPostTextHookFailureAfterUserEnter(enabled, error) {
109
+ if (!enabled || error === undefined)
110
+ return;
111
+ throw new TerminalEnterDispatchReservedError("user-explicit Codex Enter was dispatched but post-text bookkeeping failed; do not retry", { cause: error });
112
+ }
113
+ export class TerminalTextSubmissionBridge {
114
+ runtime;
115
+ classifiers;
116
+ constructor(input) {
117
+ this.runtime = input.runtime;
118
+ this.classifiers = input.classifiers;
119
+ }
120
+ async send(adapter, terminalControl, text, options = {}) {
121
+ const multiline = /[\r\n]/u.test(text.trimEnd());
122
+ const { exactEmptyRetryAuthority, requireExactEmptyComposerBeforeText, requireExactComposer } = terminalSendComposerRequirements(adapter.agent, multiline, options);
123
+ try {
124
+ this.runtime.preflight(terminalControl, requireExactComposer || exactEmptyRetryAuthority
125
+ ? "send_with_composer"
126
+ : "send");
127
+ }
128
+ catch (error) {
129
+ throw new TerminalInputNotStartedError(error instanceof Error ? error.message : String(error), { cause: error });
130
+ }
131
+ const normalized = text.trimEnd();
132
+ if (!normalized) {
133
+ throw new TerminalInputNotStartedError("terminal message is empty");
134
+ }
135
+ let verifiedForText;
136
+ try {
137
+ verifiedForText = await this.runtime.verifyIdentity(adapter.agent, terminalControl, options.runtime);
138
+ }
139
+ catch (error) {
140
+ throw new TerminalInputNotStartedError(error instanceof Error ? error.message : String(error), { cause: error });
141
+ }
142
+ if (!verifiedForText.capabilities.includes("send_keys")) {
143
+ throw new TerminalInputNotStartedError(`${adapter.displayName} terminal input capability changed before injection`);
144
+ }
145
+ let composerVerifiedImmediatelyBeforeText = false;
146
+ if (exactEmptyRetryAuthority) {
147
+ try {
148
+ await options.beforeText?.({
149
+ agent: adapter.agent,
150
+ terminalControl: verifiedForText,
151
+ multiline,
152
+ text: normalized
153
+ });
154
+ const finalEmpty = await this.captureCodexComposerSnapshot(adapter, verifiedForText, normalized, options.runtime);
155
+ if (finalEmpty.state !== "exact_empty" ||
156
+ finalEmpty.digest !==
157
+ exactEmptyRetryAuthority.preliminaryComposerDigest ||
158
+ !this.classifiers.sameIdentity(verifiedForText, finalEmpty.terminalControl)) {
159
+ const reason = "reason" in finalEmpty
160
+ ? finalEmpty.reason
161
+ : `Codex composer is ${finalEmpty.state}`;
162
+ throw new Error(`reserved Codex replacement lost its exact-empty composer: ${reason}`);
163
+ }
164
+ verifiedForText = finalEmpty.terminalControl;
165
+ }
166
+ catch (error) {
167
+ throw new TerminalEnterDispatchReservedError(error instanceof Error ? error.message : String(error), { cause: error });
168
+ }
169
+ }
170
+ else {
171
+ try {
172
+ await options.beforeText?.({
173
+ agent: adapter.agent,
174
+ terminalControl: verifiedForText,
175
+ multiline,
176
+ text: normalized
177
+ });
178
+ }
179
+ catch (error) {
180
+ throw new TerminalInputNotStartedError(error instanceof Error ? error.message : String(error), { cause: error });
181
+ }
182
+ if (requireExactEmptyComposerBeforeText) {
183
+ try {
184
+ verifiedForText = await this.verifyExactEmptyComposerBeforeText(adapter, verifiedForText, normalized, options.runtime, options.allowWorkingComposerForUserExplicit === true);
185
+ composerVerifiedImmediatelyBeforeText = true;
186
+ }
187
+ catch (error) {
188
+ throw new TerminalInputNotStartedError(error instanceof Error ? error.message : String(error), { cause: error });
189
+ }
190
+ }
191
+ }
192
+ if (!composerVerifiedImmediatelyBeforeText) {
193
+ try {
194
+ const reverifiedForText = await this.runtime.verifyIdentity(adapter.agent, verifiedForText, options.runtime);
195
+ if (!this.classifiers.sameIdentity(verifiedForText, reverifiedForText)) {
196
+ throw new Error("terminal identity changed after the final pre-text check");
197
+ }
198
+ verifiedForText = reverifiedForText;
199
+ }
200
+ catch (error) {
201
+ const message = error instanceof Error ? error.message : String(error);
202
+ if (exactEmptyRetryAuthority) {
203
+ throw new TerminalEnterDispatchReservedError(message, {
204
+ cause: error
205
+ });
206
+ }
207
+ throw new TerminalInputNotStartedError(message, { cause: error });
208
+ }
209
+ }
210
+ try {
211
+ await this.runtime.deliverText(verifiedForText, normalized);
212
+ }
213
+ catch (error) {
214
+ if (exactEmptyRetryAuthority) {
215
+ throw new TerminalEnterDispatchReservedError("reserved Codex replacement text delivery outcome is uncertain; do not retry", { cause: error });
216
+ }
217
+ if (error instanceof TerminalControlInputNotSentError) {
218
+ throw new TerminalInputNotStartedError(error.message, {
219
+ cause: error
220
+ });
221
+ }
222
+ throw error;
223
+ }
224
+ const textInjectedAt = this.runtime.nowMs();
225
+ const preserveUserInput = options.userExplicitEnterAfterTextWithoutComposerVeto === true;
226
+ const allowClaudeInjectedPastePlaceholder = claudeInjectedPasteProofEligible({
227
+ agent: adapter.agent,
228
+ multiline,
229
+ composerVerifiedImmediatelyBeforeText,
230
+ terminalControl: verifiedForText
231
+ });
232
+ let postTextHookError;
233
+ let verifiedForEnter;
234
+ let claudeComposerProof;
235
+ try {
236
+ postTextHookError = await recordTerminalSendStage(options, {
237
+ stage: "text_injected",
238
+ agent: adapter.agent,
239
+ terminalControl: verifiedForText,
240
+ multiline
241
+ }, preserveUserInput);
242
+ if (adapter.agent === "codex" && requireExactComposer) {
243
+ verifiedForEnter = await this.settleCodexMultilineComposer(adapter, terminalControl, normalized, options.runtime, {
244
+ allowOpaqueLargePastePlaceholder: exactEmptyRetryAuthority === undefined,
245
+ allowWorkingComposer: options.allowWorkingComposerForUserExplicit === true
246
+ });
247
+ }
248
+ else if (allowClaudeInjectedPastePlaceholder) {
249
+ claudeComposerProof = await settleClaudeInjectedPasteComposer({
250
+ terminalControl: verifiedForText,
251
+ expectedText: normalized,
252
+ runtime: options.runtime,
253
+ allowWorkingComposer: options.allowWorkingComposerForUserExplicit === true,
254
+ ports: this.claudeInjectedPasteProofPorts(adapter)
255
+ });
256
+ verifiedForEnter = claudeComposerProof.terminalControl;
257
+ }
258
+ else if (requireExactComposer) {
259
+ verifiedForEnter = await this.verifyExactComposerBeforeEnter(adapter, terminalControl, normalized, options.runtime, options.allowWorkingComposerForUserExplicit === true);
260
+ }
261
+ else {
262
+ await waitForUserExplicitCodexEnter({
263
+ enabled: preserveUserInput,
264
+ textInjectedAt,
265
+ nowMs: this.runtime.nowMs,
266
+ sleep: this.runtime.sleep
267
+ });
268
+ verifiedForEnter = await this.runtime.verifyIdentity(adapter.agent, terminalControl, options.runtime);
269
+ }
270
+ postTextHookError = await runTerminalSendBeforeEnter(options, {
271
+ agent: adapter.agent,
272
+ terminalControl: verifiedForEnter,
273
+ multiline,
274
+ text: normalized
275
+ }, preserveUserInput, postTextHookError);
276
+ if (requireExactComposer) {
277
+ if (adapter.agent === "codex") {
278
+ verifiedForEnter = await this.settleCodexMultilineComposer(adapter, terminalControl, normalized, options.runtime, {
279
+ allowOpaqueLargePastePlaceholder: exactEmptyRetryAuthority === undefined,
280
+ allowWorkingComposer: options.allowWorkingComposerForUserExplicit === true
281
+ });
282
+ }
283
+ else if (allowClaudeInjectedPastePlaceholder && claudeComposerProof) {
284
+ verifiedForEnter = await revalidateClaudeComposerProof({
285
+ proof: claudeComposerProof,
286
+ expectedText: normalized,
287
+ runtime: options.runtime,
288
+ allowWorkingComposer: options.allowWorkingComposerForUserExplicit === true,
289
+ ports: this.claudeInjectedPasteProofPorts(adapter)
290
+ });
291
+ }
292
+ else {
293
+ verifiedForEnter = await this.verifyExactComposerBeforeEnter(adapter, terminalControl, normalized, options.runtime, options.allowWorkingComposerForUserExplicit === true);
294
+ }
295
+ }
296
+ else if (options.beforeEnter) {
297
+ verifiedForEnter = await this.runtime.verifyIdentity(adapter.agent, terminalControl, options.runtime);
298
+ }
299
+ }
300
+ catch (error) {
301
+ if (exactEmptyRetryAuthority) {
302
+ if (error instanceof TerminalEnterDispatchReservedError) {
303
+ throw error;
304
+ }
305
+ throw new TerminalEnterDispatchReservedError(error instanceof Error ? error.message : String(error), { cause: error });
306
+ }
307
+ if (error instanceof TerminalEnterDispatchNotAttemptedError) {
308
+ throw error;
309
+ }
310
+ throw new TerminalEnterDispatchNotAttemptedError(error instanceof Error ? error.message : String(error), { cause: error });
311
+ }
312
+ try {
313
+ await this.runtime.dispatchEnter(verifiedForEnter);
314
+ postTextHookError = await recordTerminalSendStage(options, {
315
+ stage: "enter_dispatched",
316
+ agent: adapter.agent,
317
+ terminalControl: verifiedForEnter,
318
+ multiline
319
+ }, preserveUserInput, postTextHookError);
320
+ throwPostTextHookFailureAfterUserEnter(preserveUserInput, postTextHookError);
321
+ }
322
+ catch (error) {
323
+ if (exactEmptyRetryAuthority) {
324
+ throw new TerminalEnterDispatchReservedError("reserved Codex Enter dispatch outcome is uncertain; do not retry", { cause: error });
325
+ }
326
+ throw error;
327
+ }
328
+ return {
329
+ stage: "enter_dispatched",
330
+ agent: adapter.agent,
331
+ terminalControl: verifiedForEnter,
332
+ multiline
333
+ };
334
+ }
335
+ async observeCodexComposer(adapter, terminalControl, expectedText, runtime) {
336
+ const normalized = expectedText.trimEnd();
337
+ if (!normalized) {
338
+ return {
339
+ state: "unavailable",
340
+ reason: "expected Codex draft is empty"
341
+ };
342
+ }
343
+ try {
344
+ this.runtime.preflight(terminalControl, "observe_composer");
345
+ }
346
+ catch (error) {
347
+ return {
348
+ state: "unavailable",
349
+ reason: error instanceof Error ? error.message : String(error)
350
+ };
351
+ }
352
+ return this.settleCodexComposerObservation(adapter, terminalControl, normalized, runtime, { minimumStableMs: CODEX_MULTILINE_SETTLE_POLL_MS });
353
+ }
354
+ async settleCodexComposerObservation(adapter, terminalControl, expectedText, runtime, options) {
355
+ const startedAt = this.runtime.nowMs();
356
+ let candidate;
357
+ let stableSince;
358
+ let stableCaptures = 0;
359
+ let finishObservedExactCandidate = false;
360
+ let capturesBeyondDeadline = 0;
361
+ let control = terminalControl;
362
+ while (true) {
363
+ const snapshot = await this.captureCodexComposerSnapshot(adapter, control, expectedText, runtime, {
364
+ allowOpaqueLargePastePlaceholder: options.allowOpaqueLargePastePlaceholder === true,
365
+ classifyOpaqueLargePasteAsDifferent: options.classifyOpaqueLargePasteAsDifferent === true,
366
+ allowWorkingComposer: options.allowWorkingComposer === true
367
+ });
368
+ if (snapshot.state === "identity_drift" ||
369
+ (snapshot.state === "unavailable" && snapshot.retryable !== true)) {
370
+ return snapshot;
371
+ }
372
+ if (this.runtime.nowMs() - startedAt >
373
+ CODEX_MULTILINE_SETTLE_TIMEOUT_MS) {
374
+ capturesBeyondDeadline += 1;
375
+ if (capturesBeyondDeadline > CODEX_EXACT_CANDIDATE_GRACE_CAPTURES) {
376
+ return {
377
+ state: "unavailable",
378
+ reason: "Codex exact composer did not stabilize within its bounded capture grace"
379
+ };
380
+ }
381
+ }
382
+ control = snapshot.terminalControl;
383
+ const sameCandidate = candidate !== undefined &&
384
+ candidate.state === snapshot.state &&
385
+ candidate.digest === snapshot.digest &&
386
+ this.classifiers.sameIdentity(candidate.terminalControl, snapshot.terminalControl);
387
+ if (sameCandidate) {
388
+ stableCaptures += 1;
389
+ }
390
+ else {
391
+ candidate = snapshot;
392
+ stableSince = this.runtime.nowMs();
393
+ stableCaptures = 1;
394
+ finishObservedExactCandidate = snapshot.state === "exact_draft";
395
+ }
396
+ const stableForMs = stableSince === undefined
397
+ ? 0
398
+ : this.runtime.nowMs() - stableSince;
399
+ if (stableCaptures >= CODEX_MULTILINE_STABLE_CAPTURES &&
400
+ stableForMs >= options.minimumStableMs &&
401
+ snapshot.state !== "unavailable" &&
402
+ (options.requiredState === undefined ||
403
+ snapshot.state === options.requiredState ||
404
+ snapshot.state === "working" ||
405
+ snapshot.state === "approval_or_modal")) {
406
+ const finalSnapshot = await this.captureCodexComposerSnapshot(adapter, snapshot.terminalControl, expectedText, runtime, {
407
+ allowOpaqueLargePastePlaceholder: options.allowOpaqueLargePastePlaceholder === true,
408
+ classifyOpaqueLargePasteAsDifferent: options.classifyOpaqueLargePasteAsDifferent === true,
409
+ allowWorkingComposer: options.allowWorkingComposer === true
410
+ });
411
+ if (finalSnapshot.state === snapshot.state &&
412
+ "digest" in finalSnapshot &&
413
+ finalSnapshot.digest === snapshot.digest &&
414
+ this.classifiers.sameIdentity(snapshot.terminalControl, finalSnapshot.terminalControl)) {
415
+ return {
416
+ ...finalSnapshot,
417
+ stableCaptures: stableCaptures + 1
418
+ };
419
+ }
420
+ if (finalSnapshot.state === "identity_drift" ||
421
+ (finalSnapshot.state === "unavailable" &&
422
+ finalSnapshot.retryable !== true)) {
423
+ return finalSnapshot;
424
+ }
425
+ if (options.requiredState !== undefined &&
426
+ snapshot.state === options.requiredState) {
427
+ return {
428
+ state: "unavailable",
429
+ reason: "Codex composer changed after its stable final recapture"
430
+ };
431
+ }
432
+ candidate = finalSnapshot;
433
+ control = finalSnapshot.terminalControl;
434
+ stableSince = this.runtime.nowMs();
435
+ stableCaptures = 1;
436
+ finishObservedExactCandidate = finalSnapshot.state === "exact_draft";
437
+ }
438
+ const elapsed = this.runtime.nowMs() - startedAt;
439
+ if (elapsed > CODEX_MULTILINE_SETTLE_TIMEOUT_MS &&
440
+ !finishObservedExactCandidate) {
441
+ return {
442
+ state: "unavailable",
443
+ reason: options.requiredState
444
+ ? `Codex composer did not become ${options.requiredState} before the bounded observation deadline`
445
+ : "Codex composer did not become stable before the bounded observation deadline"
446
+ };
447
+ }
448
+ if (elapsed > CODEX_MULTILINE_SETTLE_TIMEOUT_MS &&
449
+ options.requiredState !== undefined &&
450
+ snapshot.state !== options.requiredState) {
451
+ if (snapshot.state !== "unavailable") {
452
+ return {
453
+ ...snapshot,
454
+ stableCaptures
455
+ };
456
+ }
457
+ return {
458
+ state: "unavailable",
459
+ reason: snapshot.reason
460
+ };
461
+ }
462
+ const remainingStableMs = options.minimumStableMs - stableForMs;
463
+ await this.runtime.sleep(Math.max(1, Math.min(CODEX_MULTILINE_SETTLE_POLL_MS, remainingStableMs > 0
464
+ ? remainingStableMs
465
+ : CODEX_MULTILINE_SETTLE_POLL_MS)));
466
+ }
467
+ }
468
+ async captureCodexComposerSnapshot(adapter, terminalControl, expectedText, runtime, options = {}) {
469
+ let verifiedBefore;
470
+ try {
471
+ verifiedBefore = await this.runtime.verifyIdentity(adapter.agent, terminalControl, runtime);
472
+ }
473
+ catch (error) {
474
+ return {
475
+ state: "identity_drift",
476
+ reason: error instanceof Error ? error.message : String(error)
477
+ };
478
+ }
479
+ let styledScreen;
480
+ try {
481
+ styledScreen = await this.runtime.captureStyled(verifiedBefore);
482
+ }
483
+ catch (error) {
484
+ return {
485
+ state: "unavailable",
486
+ reason: error instanceof Error ? error.message : String(error)
487
+ };
488
+ }
489
+ const screen = this.classifiers.stripEscapes(styledScreen);
490
+ let inspection;
491
+ try {
492
+ inspection = adapter.inspectScreen({ screen, runtime });
493
+ }
494
+ catch (error) {
495
+ return {
496
+ state: "unavailable",
497
+ reason: error instanceof Error ? error.message : String(error)
498
+ };
499
+ }
500
+ let verifiedAfter;
501
+ try {
502
+ verifiedAfter = await this.runtime.verifyIdentity(adapter.agent, verifiedBefore, runtime);
503
+ }
504
+ catch (error) {
505
+ return {
506
+ state: "identity_drift",
507
+ reason: error instanceof Error ? error.message : String(error)
508
+ };
509
+ }
510
+ if (!this.classifiers.sameIdentity(verifiedBefore, verifiedAfter)) {
511
+ return {
512
+ state: "identity_drift",
513
+ reason: "terminal control identity changed across the Codex composer capture"
514
+ };
515
+ }
516
+ const screenDigest = createHash("sha256")
517
+ .update(styledScreen)
518
+ .digest("hex");
519
+ if (inspection.approval.blocked ||
520
+ inspection.activity.state === "awaiting_approval" ||
521
+ this.classifiers.codexBlockingModalVisible(screen)) {
522
+ return {
523
+ state: "approval_or_modal",
524
+ terminalControl: verifiedAfter,
525
+ digest: screenDigest
526
+ };
527
+ }
528
+ if (inspection.activity.state === "working" &&
529
+ options.allowWorkingComposer !== true) {
530
+ return {
531
+ state: "working",
532
+ terminalControl: verifiedAfter,
533
+ digest: screenDigest
534
+ };
535
+ }
536
+ const composer = this.classifiers.currentCodexComposer(styledScreen, expectedText, options.allowOpaqueLargePastePlaceholder === true, options.classifyOpaqueLargePasteAsDifferent === true);
537
+ if (!composer) {
538
+ return {
539
+ state: "unavailable",
540
+ reason: "the current live Codex composer could not be proven",
541
+ retryable: true,
542
+ terminalControl: verifiedAfter,
543
+ digest: screenDigest
544
+ };
545
+ }
546
+ return {
547
+ state: composer.state,
548
+ terminalControl: verifiedAfter,
549
+ digest: composer.digest
550
+ };
551
+ }
552
+ async settleCodexMultilineComposer(adapter, terminalControl, expectedText, runtime, options = {}) {
553
+ const observation = await this.settleCodexComposerObservation(adapter, terminalControl, expectedText, runtime, {
554
+ minimumStableMs: CODEX_PASTE_ENTER_SETTLE_MS,
555
+ requiredState: "exact_draft",
556
+ allowOpaqueLargePastePlaceholder: options.allowOpaqueLargePastePlaceholder === true,
557
+ allowWorkingComposer: options.allowWorkingComposer === true
558
+ });
559
+ if (observation.state === "exact_draft") {
560
+ return observation.terminalControl;
561
+ }
562
+ if (observation.state === "working" ||
563
+ observation.state === "approval_or_modal") {
564
+ throw new Error("Codex became busy or blocked while its multiline composer was settling");
565
+ }
566
+ if (observation.state === "identity_drift") {
567
+ throw new Error(observation.reason);
568
+ }
569
+ throw new Error("Codex multiline composer did not become exact, idle, and stable before the bounded submit deadline");
570
+ }
571
+ async verifyExactComposerBeforeEnter(adapter, terminalControl, expectedText, runtime, allowWorkingComposer = false) {
572
+ const captured = await this.runtime.captureInspection(adapter, terminalControl, {
573
+ runtime,
574
+ scrollbackLines: CODEX_MULTILINE_SETTLE_SCROLLBACK_LINES
575
+ });
576
+ const exactComposer = this.classifiers.exactTerminalComposer(adapter.agent, captured.screen, expectedText);
577
+ if (captured.inspection.approval.blocked ||
578
+ !(["idle", "unknown"].includes(captured.inspection.activity.state) ||
579
+ (allowWorkingComposer &&
580
+ captured.inspection.activity.state === "working")) ||
581
+ !exactComposer) {
582
+ throw new Error(`${adapter.displayName} composer was not exact and idle immediately before Enter`);
583
+ }
584
+ const verifiedImmediatelyBeforeEnter = await this.runtime.verifyIdentity(adapter.agent, captured.terminalControl, runtime);
585
+ if (!this.classifiers.sameIdentity(captured.terminalControl, verifiedImmediatelyBeforeEnter)) {
586
+ throw new Error("terminal control identity changed after the final exact composer capture");
587
+ }
588
+ return verifiedImmediatelyBeforeEnter;
589
+ }
590
+ claudeInjectedPasteProofPorts(adapter) {
591
+ return {
592
+ nowMs: this.runtime.nowMs,
593
+ sleep: this.runtime.sleep,
594
+ capture: (terminalControl, runtime) => this.runtime.captureInspection(adapter, terminalControl, {
595
+ runtime,
596
+ scrollbackLines: CODEX_MULTILINE_SETTLE_SCROLLBACK_LINES
597
+ }),
598
+ verifyIdentity: (terminalControl, runtime) => this.runtime.verifyIdentity(adapter.agent, terminalControl, runtime),
599
+ exactDraft: this.classifiers.exactClaudeComposer,
600
+ exactInjectedPastePlaceholder: this.classifiers.exactClaudeInjectedPastePlaceholder
601
+ };
602
+ }
603
+ async verifyExactEmptyComposerBeforeText(adapter, terminalControl, expectedText, runtime, allowWorkingComposer = false) {
604
+ if (adapter.agent === "codex") {
605
+ const snapshot = await this.captureCodexComposerSnapshot(adapter, terminalControl, expectedText, runtime);
606
+ if (snapshot.state !== "exact_empty") {
607
+ const reason = "reason" in snapshot
608
+ ? snapshot.reason
609
+ : `Codex composer is ${snapshot.state}`;
610
+ throw new Error(`Codex composer was not exactly empty immediately before text: ${reason}`);
611
+ }
612
+ return snapshot.terminalControl;
613
+ }
614
+ const captured = await this.runtime.captureInspection(adapter, terminalControl, {
615
+ runtime,
616
+ scrollbackLines: CODEX_MULTILINE_SETTLE_SCROLLBACK_LINES
617
+ });
618
+ if (captured.inspection.approval.blocked ||
619
+ !(["idle", "unknown"].includes(captured.inspection.activity.state) ||
620
+ (allowWorkingComposer &&
621
+ captured.inspection.activity.state === "working")) ||
622
+ !this.classifiers.exactTerminalComposer(adapter.agent, captured.screen, "")) {
623
+ throw new Error(`${adapter.displayName} composer was not exactly empty immediately before text`);
624
+ }
625
+ const verified = await this.runtime.verifyIdentity(adapter.agent, captured.terminalControl, runtime);
626
+ if (!this.classifiers.sameIdentity(captured.terminalControl, verified)) {
627
+ throw new Error("terminal control identity changed after the final empty composer capture");
628
+ }
629
+ return verified;
630
+ }
631
+ }
632
+ //# sourceMappingURL=terminal-text-submission-bridge.js.map