@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,1272 @@
1
+ import path from "node:path";
2
+ import { recordValue } from "./value-guards.js";
3
+ import { isTerminalApprovalDecision } from "./terminal-agent-adapter.js";
4
+ import { arrayValue, finiteNumber, nonEmptyString, stringArrayValue, truncateText } from "./semantic-tool-value-helpers.js";
5
+ export { isAkkModelFacingDiagnosticField, isAkkModelFacingPrivateAuthorityField, normalizeAkkModelFacingFieldName } from "./semantic-tool-model-facing-field-policy.js";
6
+ const MODEL_FACING_PRIVATE_AUTHORITY_PARTS = [
7
+ ["expected", "terminal", "token"],
8
+ ["expected", "binding", "token"],
9
+ ["expected", "handoff", "token"],
10
+ ["candidate", "token"],
11
+ ["expected", "approval", "fingerprint"],
12
+ ["approval", "fingerprint"],
13
+ ["expected", "interaction", "fingerprint"],
14
+ ["interaction", "prompt", "fingerprint"],
15
+ ["interaction", "fingerprint"],
16
+ ["interaction", "authority"],
17
+ ["owner", "session"],
18
+ ["process", "incarnation"],
19
+ ["source", "file", "identity"],
20
+ ["prompt", "evidence"],
21
+ ["action", "plan"],
22
+ ["expected", "session", "revision"],
23
+ ["lifecycle", "binding", "token"],
24
+ ["binding", "token"],
25
+ ["binding", "id"],
26
+ ["binding", "generation"],
27
+ ["terminal", "binding", "id"],
28
+ ["terminal", "binding", "generation"],
29
+ ["selection", "handle"],
30
+ ["selection", "snapshot"],
31
+ ["selection", "scope"],
32
+ ["expected", "callback", "conversation", "id"],
33
+ ["expected", "callback", "session", "id"],
34
+ ["expected", "callback", "turn", "id"],
35
+ ["expected", "callback", "message", "id"],
36
+ ["expected", "callback", "openclaw", "session"]
37
+ ];
38
+ // The optional separator accepts the three spellings that can be emitted by
39
+ // old CLI/JSON diagnostics: snake_case, kebab-case, and camelCase. These are
40
+ // exact AKK authority names rather than generic words such as "token" or
41
+ // "revision", so ordinary user and agent text remains intact.
42
+ const MODEL_FACING_PRIVATE_AUTHORITY_NAME = `(?:${MODEL_FACING_PRIVATE_AUTHORITY_PARTS
43
+ .map((parts) => parts.join("[_-]?"))
44
+ .join("|")})`;
45
+ const MODEL_FACING_SCALAR = `(?:"(?:\\\\.|[^"\\\\])*"|'(?:\\\\.|[^'\\\\])*'|` +
46
+ "`(?:\\\\.|[^`\\\\])*`|true|false|null|" +
47
+ `-?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?|[^\\s,;}\\]]+)`;
48
+ const MODEL_FACING_PRIVATE_AUTHORITY_JSON = new RegExp(`"${MODEL_FACING_PRIVATE_AUTHORITY_NAME}"\\s*:\\s*${MODEL_FACING_SCALAR}`, "giu");
49
+ const MODEL_FACING_PRIVATE_AUTHORITY_CLI = new RegExp(`--${MODEL_FACING_PRIVATE_AUTHORITY_NAME}(?:=|\\s+)${MODEL_FACING_SCALAR}`, "giu");
50
+ const MODEL_FACING_PRIVATE_AUTHORITY_ASSIGNMENT = new RegExp(`(^|[^A-Za-z0-9])${MODEL_FACING_PRIVATE_AUTHORITY_NAME}` +
51
+ `\\s*(?:=|:)\\s*${MODEL_FACING_SCALAR}`, "gimu");
52
+ const MODEL_FACING_PRIVATE_AUTHORITY_LINE = new RegExp(`^\\s*(?:[-*]\\s*)?(?:` +
53
+ `(?:["']?${MODEL_FACING_PRIVATE_AUTHORITY_NAME}["']?\\s*(?:=|:))|` +
54
+ `(?:--${MODEL_FACING_PRIVATE_AUTHORITY_NAME}(?:=|\\s+)))`, "iu");
55
+ const LEGACY_APPROVAL_TAIL_MARKER = "If the user approves, call `agent_knock_knock_approve`";
56
+ const LEGACY_APPROVAL_TERMINAL_INSTRUCTION = "Do not use raw tmux, shell, or manual key presses for this approval. Do not approve without explicit user confirmation.";
57
+ function sanitizeAkkModelFacingEmbeddedAuthorityText(value) {
58
+ return value
59
+ .replace(MODEL_FACING_PRIVATE_AUTHORITY_JSON, '"internal_authority":"[retained by AKK]"')
60
+ .replace(MODEL_FACING_PRIVATE_AUTHORITY_CLI, "[AKK internal authority omitted]")
61
+ .replace(MODEL_FACING_PRIVATE_AUTHORITY_ASSIGNMENT, (_match, prefix) => `${prefix}[AKK internal authority omitted]`);
62
+ }
63
+ /**
64
+ * Remove only AKK-generated pre-v18 authority instructions from callback/event
65
+ * text. Exact authority-looking text outside one of these fixed machine-owned
66
+ * forms is business content and must remain byte-for-byte visible.
67
+ */
68
+ export function sanitizeAkkModelFacingLegacyAuthorityInstructionText(value) {
69
+ const reviewOnly = stripAkkLegacyApprovalInstructionTail(value);
70
+ let machineAuthorityBlock = false;
71
+ return reviewOnly.split("\n").map((line) => {
72
+ const text = line.endsWith("\r") ? line.slice(0, -1) : line;
73
+ const carriageReturn = line.endsWith("\r") ? "\r" : "";
74
+ if (/^\s*(?:\[?AKK\]?\s+)?(?:approval|internal) authority\s*:?\s*$/iu
75
+ .test(text)) {
76
+ machineAuthorityBlock = true;
77
+ return line;
78
+ }
79
+ if (text.trim().length === 0) {
80
+ machineAuthorityBlock = false;
81
+ return line;
82
+ }
83
+ const fixedCommand = /^\s*(?:equivalent (?:user )?command|AKK (?:approval )?command)\s*:/iu
84
+ .test(text) && containsEmbeddedPrivateAuthority(text);
85
+ const blockAuthority = machineAuthorityBlock &&
86
+ containsEmbeddedPrivateAuthority(text);
87
+ if (fixedCommand || blockAuthority) {
88
+ return `${text.match(/^\s*/u)?.[0] ?? ""}` +
89
+ `[AKK internal authority omitted]${carriageReturn}`;
90
+ }
91
+ if (machineAuthorityBlock)
92
+ machineAuthorityBlock = false;
93
+ return line;
94
+ }).join("\n");
95
+ }
96
+ /** Remove only the exact legacy approval instruction appended by AKK. */
97
+ export function stripAkkLegacyApprovalInstructionTail(value) {
98
+ const markerIndex = value.lastIndexOf(LEGACY_APPROVAL_TAIL_MARKER);
99
+ const markerSuffix = markerIndex === -1 ? "" : value.slice(markerIndex);
100
+ const fixedTail = markerIndex !== -1 && (markerSuffix.trimEnd().endsWith(LEGACY_APPROVAL_TERMINAL_INSTRUCTION) ||
101
+ markerSuffix.split(/\r?\n/u).some(isLegacyMachineAuthorityLine));
102
+ return fixedTail ? value.slice(0, markerIndex) : value;
103
+ }
104
+ function isLegacyMachineAuthorityLine(line) {
105
+ return containsEmbeddedPrivateAuthority(line) && (MODEL_FACING_PRIVATE_AUTHORITY_LINE.test(line) ||
106
+ /^\s*(?:equivalent (?:user )?command|AKK (?:approval )?command)\s*:/iu
107
+ .test(line));
108
+ }
109
+ function containsEmbeddedPrivateAuthority(value) {
110
+ return sanitizeAkkModelFacingEmbeddedAuthorityText(value) !== value;
111
+ }
112
+ export function sanitizeAkkModelFacingDiagnosticText(message) {
113
+ const sanitized = sanitizeAkkModelFacingEmbeddedAuthorityText(message);
114
+ if (sanitized !== message ||
115
+ /(?:\bexpected\s+(?:session\s+)?revision\b|\bactual\s+(?:session\s+)?revision\b|\b(?:terminal|binding|handoff|candidate)\s+token\b|\b(?:approval|interaction(?:\s+prompt)?)\s+fingerprint\b|\bbinding\s+(?:id|generation)\b|\bcompare-and-swap\b|\bCAS\b)/iu.test(message)) {
116
+ return "AKK's private authority changed or could not be verified. Refresh AKK list/status and retry only the currently advertised semantic action.";
117
+ }
118
+ return sanitized;
119
+ }
120
+ export const AKK_CALLBACK_METHOD = "agent-knock-knock.callback";
121
+ export function parseAkkCommand(args) {
122
+ const input = String(args ?? "").trim();
123
+ if (!input || input === "help" || input === "-h" || input === "--help") {
124
+ return { action: "help" };
125
+ }
126
+ const selectorMessage = parseSelectorMessage(input);
127
+ if (selectorMessage) {
128
+ return {
129
+ action: "send",
130
+ selector: selectorMessage.selector,
131
+ message: selectorMessage.message
132
+ };
133
+ }
134
+ const { token, rest } = takeToken(input);
135
+ const action = token.toLowerCase();
136
+ const lifecycleCommand = parseAkkLifecycleCommand(action, rest);
137
+ if (lifecycleCommand) {
138
+ return lifecycleCommand;
139
+ }
140
+ const turnCommand = parseAkkTurnCommand(action, rest);
141
+ return turnCommand ?? { action: "delegate", request: input };
142
+ }
143
+ function parseAkkLifecycleCommand(action, rest) {
144
+ if (action === "list" || action === "ls" || action === "tasks") {
145
+ return { action: "list" };
146
+ }
147
+ if (action === "doctor" || action === "check") {
148
+ if (rest.trim()) {
149
+ throw new Error("Usage: /akk doctor");
150
+ }
151
+ return { action: "doctor" };
152
+ }
153
+ if (action === "watch") {
154
+ const usage = "Usage: /akk watch <exact-terminal-id>";
155
+ const { token: terminalId, rest: extra } = takeRequiredToken(rest, usage);
156
+ assertExactTerminalId(terminalId, usage);
157
+ if (extra.trim()) {
158
+ throw new Error(usage);
159
+ }
160
+ return { action: "watch", terminalId };
161
+ }
162
+ if (action === "unwatch") {
163
+ const usage = "Usage: /akk unwatch <watch-id>";
164
+ const { token: watchId, rest: extra } = takeRequiredToken(rest, usage);
165
+ if (extra.trim() || !isTerminalWatchId(watchId)) {
166
+ throw new Error(usage);
167
+ }
168
+ return { action: "unwatch", watchId };
169
+ }
170
+ if (action === "threads" || action === "list-resumable-threads") {
171
+ const usage = "Usage: /akk threads <exact-terminal-id>";
172
+ const { token: terminalId, rest: extra } = takeRequiredToken(rest, usage);
173
+ assertExactTerminalId(terminalId, usage);
174
+ if (extra.trim()) {
175
+ throw new Error(usage);
176
+ }
177
+ return { action: "list-resumable-threads", terminalId };
178
+ }
179
+ if (action === "models" || action === "model-options") {
180
+ const usage = "Usage: /akk models <exact-terminal-id>";
181
+ const { token: terminalId, rest: extra } = takeRequiredToken(rest, usage);
182
+ assertExactTerminalId(terminalId, usage);
183
+ if (extra.trim()) {
184
+ throw new Error(usage);
185
+ }
186
+ return { action: "model-options", terminalId };
187
+ }
188
+ if (action === "repair-model-control") {
189
+ const usage = "Usage: /akk repair-model-control <exact-terminal-id>";
190
+ const { token: terminalId, rest: extra } = takeRequiredToken(rest, usage);
191
+ assertExactTerminalId(terminalId, usage);
192
+ if (extra.trim()) {
193
+ throw new Error(usage);
194
+ }
195
+ return { action: "repair-model-control", terminalId };
196
+ }
197
+ if (action === "set-model") {
198
+ const usage = "Usage: /akk set-model <exact-terminal-id> <advertised-model-id> " +
199
+ "<advertised-reasoning-effort>";
200
+ const { token: terminalId, rest: modelInput } = takeRequiredToken(rest, usage);
201
+ assertExactTerminalId(terminalId, usage);
202
+ const { token: model, rest: effortInput } = takeRequiredToken(modelInput, usage);
203
+ const { token: reasoningEffort, rest: extra } = takeRequiredToken(effortInput, usage);
204
+ if (extra.trim() ||
205
+ !isAkkModelSemanticIdentifier(model, 160) ||
206
+ !/^[a-z][a-z0-9_-]{0,63}$/u.test(reasoningEffort)) {
207
+ throw new Error(usage);
208
+ }
209
+ return {
210
+ action: "set-model",
211
+ terminalId,
212
+ model,
213
+ reasoningEffort
214
+ };
215
+ }
216
+ if (action === "new-thread" || action === "clear-thread") {
217
+ const usage = `Usage: /akk ${action} <exact-terminal-id>`;
218
+ const { token: terminalId, rest: extra } = takeRequiredToken(rest, usage);
219
+ assertExactTerminalId(terminalId, usage);
220
+ if (extra.trim()) {
221
+ throw new Error(usage);
222
+ }
223
+ return { action: "new-thread", terminalId };
224
+ }
225
+ if (action === "resume-thread") {
226
+ const usage = "Usage: /akk resume-thread <exact-terminal-id> " +
227
+ "[native-thread-uuid|previous|刚才那个|number|@short-id]";
228
+ const { token: terminalId, rest: nativeInput } = takeRequiredToken(rest, usage);
229
+ assertExactTerminalId(terminalId, usage);
230
+ const { token: selectionInput, rest: extra } = takeToken(nativeInput);
231
+ if (extra.trim()) {
232
+ throw new Error(usage);
233
+ }
234
+ const selection = selectionInput
235
+ ? parseAkkResumeSelection(selectionInput, usage)
236
+ : undefined;
237
+ return {
238
+ action: "resume-thread",
239
+ terminalId,
240
+ ...(selection
241
+ ? { selection }
242
+ : {})
243
+ };
244
+ }
245
+ return undefined;
246
+ }
247
+ function parseAkkTurnCommand(action, rest) {
248
+ if (action === "status" || action === "show") {
249
+ const { token: turnId, rest: extra } = takeToken(rest);
250
+ if (extra.trim()) {
251
+ throw new Error("Usage: /akk status [turn-selector|terminal-watch-id]");
252
+ }
253
+ return turnId && isTerminalWatchId(turnId)
254
+ ? { action: "status", watchId: turnId }
255
+ : { action: "status", turnId: turnId || undefined };
256
+ }
257
+ if (action === "describe" || action === "summary" || action === "about") {
258
+ throw new Error("AKK describe was removed; use /akk status [turn-selector]");
259
+ }
260
+ if (action === "respond") {
261
+ const response = parseTurnResponse(rest);
262
+ return {
263
+ action: "respond",
264
+ turnId: response.selector,
265
+ message: response.message
266
+ };
267
+ }
268
+ if (action === "send") {
269
+ throw new Error("AKK send syntax changed; use /akk <session-selector>: <message>");
270
+ }
271
+ if (action === "reply") {
272
+ throw new Error("AKK reply syntax changed; use /akk respond <turn-selector>: <answer>");
273
+ }
274
+ if (action === "approve") {
275
+ const { token: turnId, rest: approvalInput } = takeRequiredToken(rest, "Usage: /akk approve <turn-selector> [approve_once|reject]");
276
+ const decisionInput = approvalInput.trim();
277
+ if (decisionInput && !isTerminalApprovalDecision(decisionInput)) {
278
+ throw new Error("Usage: /akk approve <turn-selector> [approve_once|reject]");
279
+ }
280
+ const decision = isTerminalApprovalDecision(decisionInput)
281
+ ? decisionInput
282
+ : undefined;
283
+ return {
284
+ action: "approve",
285
+ turnId,
286
+ ...(decision ? { decision } : {})
287
+ };
288
+ }
289
+ if (action === "cancel" || action === "stop") {
290
+ const { token: turnId } = takeRequiredToken(rest, "Usage: /akk cancel <turn-selector>");
291
+ return { action: "cancel", turnId };
292
+ }
293
+ if (action === "renew") {
294
+ const { token: turnId, rest: minutesInput } = takeRequiredToken(rest, "Usage: /akk renew <turn-selector> [minutes]");
295
+ const minutes = minutesInput.trim();
296
+ if (minutes && (!Number.isFinite(Number(minutes)) || Number(minutes) <= 0)) {
297
+ throw new Error("Usage: /akk renew <turn-selector> [positive-minutes]");
298
+ }
299
+ return { action: "renew", turnId, minutes: minutes || undefined };
300
+ }
301
+ if (action === "retry-callback" || action === "retry") {
302
+ const { token: turnId } = takeRequiredToken(rest, "Usage: /akk retry-callback <turn-selector>");
303
+ return { action: "retry-callback", turnId };
304
+ }
305
+ if (action === "close" || action === "done") {
306
+ return parseAkkCloseCommand(rest);
307
+ }
308
+ return undefined;
309
+ }
310
+ function parseAkkCloseCommand(rest) {
311
+ const usage = "Usage: /akk close <turn-selector> " +
312
+ "[(--expected-message-id <id> | --expected-transition-id <id>)] [reason]";
313
+ const { token: turnId, rest: reasonInput } = takeRequiredToken(rest, usage);
314
+ const recoveryInput = reasonInput.trim();
315
+ const recoveryFlags = recoveryInput.match(/(?:^|\s)--expected-(?:message|transition)-id(?=\s|$)/gu) ?? [];
316
+ if (recoveryFlags.length > 1) {
317
+ throw new Error(`${usage}; expected-message-id and expected-transition-id are mutually exclusive`);
318
+ }
319
+ const recovery = /^--expected-(message|transition)-id\s+(\S+)(?:\s+([\s\S]*))?$/u.exec(recoveryInput);
320
+ if (recoveryFlags.length === 1 && !recovery) {
321
+ throw new Error(usage);
322
+ }
323
+ const recoveryKind = recovery?.[1];
324
+ const recoveryId = recovery?.[2];
325
+ const recoveryReason = recovery?.[3]?.trim();
326
+ const defaultRecoveryReason = recoveryKind === "transition"
327
+ ? "Native-thread lifecycle transition recovered from /akk command"
328
+ : "Orphaned terminal dispatch resolved from /akk command";
329
+ return {
330
+ action: "close",
331
+ turnId,
332
+ reason: recoveryReason ||
333
+ (recovery
334
+ ? defaultRecoveryReason
335
+ : recoveryInput || "Closed from /akk command"),
336
+ ...(recoveryKind === "message" && recoveryId
337
+ ? { expectedMessageId: recoveryId }
338
+ : {}),
339
+ ...(recoveryKind === "transition" && recoveryId
340
+ ? { expectedTransitionId: recoveryId }
341
+ : {})
342
+ };
343
+ }
344
+ export function akkUsageText() {
345
+ return [
346
+ "AKK usage:",
347
+ "/akk <request>",
348
+ "/akk codex: <request>",
349
+ "/akk claude: <request>",
350
+ "/akk <session-selector>: <message>",
351
+ "/akk list",
352
+ "/akk watch <exact-terminal-id>",
353
+ "/akk unwatch <watch-id>",
354
+ "/akk threads <exact-terminal-id>",
355
+ "/akk models <exact-terminal-id>",
356
+ "/akk repair-model-control <exact-terminal-id>",
357
+ "/akk set-model <exact-terminal-id> <advertised-model-id> <advertised-reasoning-effort>",
358
+ "/akk new-thread <exact-terminal-id>",
359
+ "/akk clear-thread <exact-terminal-id>",
360
+ "/akk resume-thread <exact-terminal-id> [uuid|previous|number|@short-id]",
361
+ "/akk doctor",
362
+ "/akk status [turn-selector|terminal-watch-id]",
363
+ "/akk respond <turn-selector>: <answer>",
364
+ "/akk approve <turn-selector> [approve_once|reject]",
365
+ "/akk cancel <turn-selector>",
366
+ "Model control targets one exact physical pane; Codex rollout attribution and identify-foreground are not prerequisites.",
367
+ "Repair-model-control is advertised only for an exact stale Codex /model Composer surface or open native picker; it clears no other draft, never presses Enter, and never submits or selects anything.",
368
+ "Models normally requires an idle, empty, prompt-free UI with no active Turn; for an exactly advertised Codex 0.154 /model residue it may continue that residue into read-only catalog discovery. Successful discovery consumes any residual-entry authority, restores the exact empty UI, and issues a fresh ordinary one-shot set-model offer; set-model accepts only that offer. If the result is uncertain, inspect the pane and do not retry automatically."
369
+ ].join("\n");
370
+ }
371
+ export function formatAkkListCommandResult(result) {
372
+ const terminals = arrayValue(result.terminals);
373
+ const terminalWatches = arrayValue(result.terminal_watches);
374
+ const unavailableManagedTurns = arrayValue(result.unavailable_managed_turns);
375
+ if (terminals.length === 0 &&
376
+ terminalWatches.length === 0 &&
377
+ unavailableManagedTurns.length === 0) {
378
+ return "AKK found no live terminals or unavailable managed turns.";
379
+ }
380
+ const terminalLines = terminals.slice(0, 20).flatMap((terminal) => {
381
+ const managed = recordValue(terminal.managed) ?? {};
382
+ const managementConflict = recordValue(terminal.management_conflict);
383
+ const currentTurn = recordValue(managed.current_turn);
384
+ const recentTurn = recordValue(managed.recent_turn);
385
+ const history = arrayValue(managed.history);
386
+ const sessionId = nonEmptyString(managed.session_id);
387
+ const sessionShortRef = nonEmptyString(managed.session_short_ref);
388
+ const hiddenTurnCount = finiteNumber(managed.hidden_turn_count) ?? 0;
389
+ const recovery = orphanedTerminalDispatchRecovery(terminal);
390
+ const terminalId = nonEmptyString(terminal.id);
391
+ const availableActions = recordValue(terminal.available_actions) ?? {};
392
+ const hasLifecycleAction = [
393
+ "list_resumable_threads",
394
+ "new_thread",
395
+ "resume_thread"
396
+ ].some((name) => Object.hasOwn(availableActions, name));
397
+ const hasWatchAction = Object.hasOwn(availableActions, "watch");
398
+ return [
399
+ `- ${formatTerminalLine(terminal)}`,
400
+ ...compatibilityWarningLines(terminal),
401
+ ...(hasLifecycleAction && terminalId
402
+ ? [` lifecycle terminal_id: ${terminalId}`]
403
+ : []),
404
+ ...(hasWatchAction && terminalId
405
+ ? [` AKK Watch available: /akk watch ${terminalId} — observe this exact terminal without input; exact task evidence is preferred and terminal-activity fallback is best-effort.`]
406
+ : []),
407
+ ...(sessionId || sessionShortRef
408
+ ? [` AKK session: ${sessionShortRef ?? sessionId}`]
409
+ : []),
410
+ ...formatAvailableActions("terminal actions", terminal),
411
+ ...(currentTurn
412
+ ? [
413
+ ` current turn: ${formatManagedTurnLine(currentTurn)}`,
414
+ ...formatAvailableActions("current turn actions", currentTurn)
415
+ ]
416
+ : []),
417
+ ...(recentTurn
418
+ ? [
419
+ ` recent turn: ${formatManagedTurnLine(recentTurn)}`,
420
+ ...formatAvailableActions("recent turn actions", recentTurn)
421
+ ]
422
+ : []),
423
+ ...history.slice(0, 20).flatMap((turn) => [
424
+ ` history: ${formatManagedTurnLine(turn)}`,
425
+ ...formatAvailableActions("history actions", turn)
426
+ ]),
427
+ ...(hiddenTurnCount > 0 && history.length === 0
428
+ ? [` older managed turns: ${hiddenTurnCount} (use all=true to include)`]
429
+ : []),
430
+ ...(managementConflict
431
+ ? [
432
+ ` management conflict: ${nonEmptyString(managementConflict.reason) ?? "current terminal ownership is unresolved"}`,
433
+ ...(nonEmptyString(managementConflict.recovery)
434
+ ? [` recovery: ${nonEmptyString(managementConflict.recovery)}`]
435
+ : [])
436
+ ]
437
+ : []),
438
+ ...(recovery ? [` recovery: ${recovery}`] : [])
439
+ ];
440
+ });
441
+ const watchLines = terminalWatches.slice(0, 20).flatMap((watch) => [
442
+ `- ${formatTerminalWatchLine(watch)}`,
443
+ ...compatibilityWarningLines(watch),
444
+ ...formatAvailableActions(" actions", watch)
445
+ ]);
446
+ const heading = terminalWatches.length > 0
447
+ ? `AKK terminals (${terminals.length} live, ${terminalWatches.length} terminal watches, ${unavailableManagedTurns.length} unavailable managed turns):`
448
+ : `AKK terminals (${terminals.length} live, ${unavailableManagedTurns.length} unavailable managed turns):`;
449
+ return [
450
+ heading,
451
+ ...(terminalLines.length > 0
452
+ ? ["live terminals:", ...terminalLines]
453
+ : []),
454
+ ...(watchLines.length > 0
455
+ ? ["terminal watches:", ...watchLines]
456
+ : []),
457
+ ...(unavailableManagedTurns.length > 0
458
+ ? [
459
+ "unavailable managed turns:",
460
+ ...unavailableManagedTurns.slice(0, 20).flatMap((turn) => [
461
+ `- ${formatManagedTurnLine(turn)}`,
462
+ ...formatAvailableActions(" actions", turn)
463
+ ])
464
+ ]
465
+ : [])
466
+ ].join("\n");
467
+ }
468
+ /**
469
+ * Keep every structured controller-Host List result below its model-output
470
+ * budget without weakening the private action-authority path.
471
+ *
472
+ * The CLI remains the complete operator/debug contract. The controller receives a
473
+ * terminal-first projection: current resource identities and state, action
474
+ * names, and only the dynamic semantic inputs needed to invoke those actions.
475
+ * Static explanations live in the bundled agent-knock-knock skill.
476
+ */
477
+ export { compactAkkListModelProjection } from "./semantic-tool-list-projection.js";
478
+ export function formatAkkWatchCommandResult(result) {
479
+ const watch = terminalWatchRecord(result);
480
+ return [
481
+ "AKK Terminal Watch started:",
482
+ `watch: ${nonEmptyString(watch.watch_id) ?? "unknown"}`,
483
+ `terminal: ${nonEmptyString(watch.terminal_id) ?? "unknown"}`,
484
+ `agent: ${nonEmptyString(watch.agent) ?? "unknown"}`,
485
+ `status: ${nonEmptyString(watch.status) ?? "watching"}`,
486
+ `mode: ${nonEmptyString(watch.watch_mode) ?? "exact_task"}`,
487
+ `confidence: ${nonEmptyString(watch.confidence) ?? "exact"}`,
488
+ ...compatibilityWarningLines(watch),
489
+ ...(stringArrayValue(watch.warnings).map((warning) => `warning: ${warning}`)),
490
+ watch.watch_mode === "terminal_activity"
491
+ ? "AKK is observing terminal activity only. Stable idle is best-effort and is not proof that one exact task completed."
492
+ : "This Watch is observing an exact task anchor without sending input, adopting the task, or changing any managed ownership."
493
+ ].join("\n");
494
+ }
495
+ export function formatAkkUnwatchCommandResult(result) {
496
+ const watch = terminalWatchRecord(result);
497
+ return [
498
+ "AKK Terminal Watch stopped:",
499
+ `watch: ${nonEmptyString(watch.watch_id) ?? "unknown"}`,
500
+ `status: ${nonEmptyString(watch.status) ?? "cancelled"}`,
501
+ "The terminal and its task were not interrupted."
502
+ ].join("\n");
503
+ }
504
+ export function formatAkkWatchStatusCommandResult(result) {
505
+ const watch = terminalWatchRecord(result);
506
+ const userExplicitFallback = watch.source ===
507
+ "terminal_user_explicit_fallback_watch";
508
+ const settlement = recordValue(watch.settlement) ?? {};
509
+ const reason = nonEmptyString(settlement.reason_code) ??
510
+ nonEmptyString(watch.reason);
511
+ const completionText = nonEmptyString(settlement.completion_text);
512
+ const callback = recordValue(watch.callback);
513
+ const callbackFailed = Number(callback?.failed ?? 0);
514
+ const callbackDelivered = Number(callback?.delivered ?? 0);
515
+ const callbackPending = Number(callback?.pending ?? 0);
516
+ const callbackError = nonEmptyString(callback?.last_error_code);
517
+ const callbackLines = callbackFailed > 0
518
+ ? [
519
+ `callback: failed (${callbackFailed})`,
520
+ ...(callbackError ? [`callback error: ${callbackError}`] : []),
521
+ "The terminal task status and callback delivery status are separate. Watch status only reports delivery; wait for the supervisor or run reconcile-watches to attempt recovery."
522
+ ]
523
+ : callbackDelivered > 0
524
+ ? [`callback: delivered (${callbackDelivered})`]
525
+ : callbackPending > 0
526
+ ? [`callback: pending (${callbackPending})`]
527
+ : [];
528
+ return [
529
+ "AKK Terminal Watch status:",
530
+ `watch: ${nonEmptyString(watch.watch_id) ?? "unknown"}`,
531
+ `terminal: ${nonEmptyString(watch.terminal_id) ?? "unknown"}`,
532
+ `agent: ${nonEmptyString(watch.agent) ?? "unknown"}`,
533
+ `status: ${nonEmptyString(watch.status) ?? "unknown"}`,
534
+ `mode: ${nonEmptyString(watch.watch_mode) ?? "exact_task"}`,
535
+ `confidence: ${nonEmptyString(watch.confidence) ?? "exact"}`,
536
+ ...compatibilityWarningLines(watch),
537
+ ...(stringArrayValue(watch.warnings).map((warning) => `warning: ${warning}`)),
538
+ ...(reason
539
+ ? [`reason: ${reason}`]
540
+ : []),
541
+ ...(completionText
542
+ ? [`completion: ${truncateText(completionText, 500)}`]
543
+ : []),
544
+ ...callbackLines,
545
+ userExplicitFallback
546
+ ? "AKK sent this exact request through user-explicit unmanaged fallback and attached Watch for its callback; no managed Turn was created."
547
+ : watch.watch_mode === "terminal_activity"
548
+ ? "This is a best-effort read-only terminal-activity Watch; stable idle is not exact task-completion proof."
549
+ : "This is a user-selected read-only exact-task observation; Watch itself did not send, adopt, or mutate the task."
550
+ ].join("\n");
551
+ }
552
+ export function formatAkkTerminalWatchHint(result) {
553
+ const hint = recordValue(result.terminal_watch_hint);
554
+ if (hint?.kind !== "terminal_watch_discovery" ||
555
+ hint.available_action_required !== false) {
556
+ return [];
557
+ }
558
+ const command = nonEmptyString(hint.command);
559
+ const instruction = nonEmptyString(hint.instruction);
560
+ if (!command || !instruction) {
561
+ return [];
562
+ }
563
+ return [
564
+ `AKK Watch available: ${command}`,
565
+ `next: ${instruction}`
566
+ ];
567
+ }
568
+ export function formatAkkRespondCommandResult(result) {
569
+ const conversation = recordValue(result.conversation) ?? {};
570
+ const compatibilityId = nonEmptyString(conversation.conversation_id) ??
571
+ nonEmptyString(result.conversation_id) ??
572
+ "unknown";
573
+ const sessionId = nonEmptyString(conversation.session_id) ??
574
+ nonEmptyString(result.session_id) ??
575
+ compatibilityId;
576
+ const turnId = nonEmptyString(conversation.turn_id) ??
577
+ nonEmptyString(result.turn_id) ??
578
+ compatibilityId;
579
+ const status = nonEmptyString(conversation.status) ??
580
+ nonEmptyString(result.status) ??
581
+ "unknown";
582
+ const identityLines = [
583
+ `session: ${sessionId}`,
584
+ `turn: ${turnId}`,
585
+ `status: ${status}`
586
+ ];
587
+ if (isAkkNativeSubmissionAccepted(result)) {
588
+ return {
589
+ text: ["AKK response sent.", ...identityLines].join("\n"),
590
+ isError: false
591
+ };
592
+ }
593
+ if (result.submission_outcome === "uncertain") {
594
+ return {
595
+ text: [
596
+ "AKK may have delivered the response, but its submission outcome is uncertain.",
597
+ ...identityLines,
598
+ "next: do not retry automatically; inspect this Turn and the shared terminal pane."
599
+ ].join("\n"),
600
+ isError: true
601
+ };
602
+ }
603
+ if (result.submission_outcome === "aborted") {
604
+ const safeToRetry = result.safe_to_retry === true && result.do_not_retry !== true;
605
+ return {
606
+ text: [
607
+ "AKK response was not sent.",
608
+ ...identityLines,
609
+ safeToRetry
610
+ ? "next: the aborted receipt is durable, so it is safe to retry this response."
611
+ : "next: do not retry automatically; a durable safe abort was not proven, so inspect this Turn and its terminal dispatch ledger."
612
+ ].join("\n"),
613
+ isError: true
614
+ };
615
+ }
616
+ if (result.submission_outcome === "pending_acceptance") {
617
+ return {
618
+ text: [
619
+ "AKK dispatched the response, but native acceptance is still pending.",
620
+ ...identityLines,
621
+ "next: do not retry automatically; wait for native acceptance or inspect the shared terminal pane."
622
+ ].join("\n"),
623
+ isError: true
624
+ };
625
+ }
626
+ if (result.submission_outcome === "not_accepted") {
627
+ return {
628
+ text: [
629
+ "AKK proved that the coding agent did not accept the response draft.",
630
+ ...identityLines,
631
+ "next: do not retry automatically; inspect the exact composer draft."
632
+ ].join("\n"),
633
+ isError: true
634
+ };
635
+ }
636
+ return {
637
+ text: [
638
+ "AKK could not confirm the response submission outcome.",
639
+ ...identityLines,
640
+ "next: do not retry automatically; inspect this Turn and the shared terminal pane."
641
+ ].join("\n"),
642
+ isError: true
643
+ };
644
+ }
645
+ export function isAkkNativeSubmissionAccepted(result) {
646
+ return result.submission_outcome === "agent_accepted" &&
647
+ result.delivery_receipt === "agent_accepted" &&
648
+ result.delivered === true;
649
+ }
650
+ export function formatAkkThreadsCommandResult(result) {
651
+ const terminalId = nonEmptyString(result.terminal_id) ?? "unknown";
652
+ const currentSessionId = nonEmptyString(result.current_session_id);
653
+ const currentNativeThreadId = nonEmptyString(result.current_native_thread_id);
654
+ const threads = arrayValue(result.threads);
655
+ const resumableCount = threads.filter((thread) => thread.resumable === true).length;
656
+ const previous = recordValue(result.previous);
657
+ const previousNativeThreadId = nonEmptyString(previous?.native_thread_id);
658
+ const selectionSnapshot = recordValue(result.selection_snapshot);
659
+ const threadLines = threads.slice(0, 30).flatMap((thread) => {
660
+ const nativeThreadId = nonEmptyString(thread.native_thread_id) ?? "unknown";
661
+ const selectionNumber = finiteNumber(thread.selection_number);
662
+ const shortId = nonEmptyString(thread.short_id);
663
+ const status = thread.resumable === true
664
+ ? "resumable"
665
+ : nonEmptyString(thread.unavailable_reason) ?? "unavailable";
666
+ const context = [
667
+ nonEmptyString(thread.title),
668
+ nonEmptyString(thread.preview)
669
+ ].filter((value) => Boolean(value)).join(" · ");
670
+ const selector = selectionNumber !== undefined || shortId
671
+ ? [
672
+ selectionNumber !== undefined ? `${selectionNumber}.` : undefined,
673
+ shortId
674
+ ].filter(Boolean).join(" ")
675
+ : `- ${nativeThreadId}`;
676
+ const previousMarker = nativeThreadId === previousNativeThreadId
677
+ ? " | previous / 刚才那个"
678
+ : "";
679
+ return [
680
+ `${selector} | ${status}${previousMarker}`,
681
+ ` full UUID: ${nativeThreadId}`,
682
+ ...(nonEmptyString(thread.updated_at)
683
+ ? [` updated: ${nonEmptyString(thread.updated_at)}`]
684
+ : []),
685
+ ...(context ? [` context: ${truncateText(context, 180)}`] : [])
686
+ ];
687
+ });
688
+ return [
689
+ `AKK native threads (${threads.length} found, ${resumableCount} resumable):`,
690
+ `terminal: ${terminalId}`,
691
+ `current session: ${currentSessionId ?? "none"}`,
692
+ `current native thread: ${currentNativeThreadId ?? "none"}`,
693
+ ...(nonEmptyString(selectionSnapshot?.expires_at)
694
+ ? [`selection expires: ${nonEmptyString(selectionSnapshot?.expires_at)}`]
695
+ : []),
696
+ ...compatibilityWarningLines(result),
697
+ ...(threadLines.length > 0
698
+ ? ["threads:", ...threadLines]
699
+ : ["threads: none"]),
700
+ ...(resumableCount > 0
701
+ ? [
702
+ `next: /akk resume-thread ${terminalId} <native-thread-uuid>`,
703
+ `shortcuts: /akk resume-thread ${terminalId} <number|@short-id>`,
704
+ ...(previousNativeThreadId
705
+ ? [`previous: /akk resume-thread ${terminalId} previous`]
706
+ : []),
707
+ "Numbers and short IDs refer only to this displayed snapshot; relist after expiry or any terminal change."
708
+ ]
709
+ : []),
710
+ "Listing or switching native threads does not create an AKK Turn."
711
+ ].join("\n");
712
+ }
713
+ export function formatAkkModelOptionsCommandResult(result) {
714
+ const terminalId = nonEmptyString(result.terminal_id) ?? "unknown";
715
+ const scope = nonEmptyString(result.scope) ?? "unknown";
716
+ const current = recordValue(result.current) ?? {};
717
+ const models = arrayValue(result.models);
718
+ const modelLines = models.slice(0, 50).map((entry) => {
719
+ const id = nonEmptyString(entry.id) ?? "unknown";
720
+ const label = nonEmptyString(entry.label);
721
+ const efforts = stringArrayValue(entry.reasoning_efforts);
722
+ return `- ${id}${label && label !== id ? ` (${label})` : ""}` +
723
+ `${efforts.length > 0 ? ` | reasoning: ${efforts.join(", ")}` : ""}`;
724
+ });
725
+ return [
726
+ `AKK model options (${models.length} models):`,
727
+ `terminal: ${terminalId}`,
728
+ `agent: ${nonEmptyString(result.agent) ?? "unknown"}`,
729
+ `scope: ${scope}`,
730
+ `current model: ${nonEmptyString(current.model) ?? "unknown"}`,
731
+ `current reasoning: ${nonEmptyString(current.reasoning_effort) ?? "unobserved"}`,
732
+ ...compatibilityWarningLines(result),
733
+ ...(modelLines.length > 0 ? ["models:", ...modelLines] : ["models: none"]),
734
+ scope === "current_and_new_sessions"
735
+ ? "Codex applies this selection to the current session and persists the selected model and ordinary efforts (including max) for new sessions; ultra applies only now and uses a native non-ultra future fallback."
736
+ : "Claude Code applies this selection only to the current session; new-session defaults are unchanged.",
737
+ `next: /akk set-model ${terminalId} <advertised-model-id> <advertised-reasoning-effort>`,
738
+ "This successful catalog result has restored an exact empty Composer and carries a fresh ordinary private offer for one set-model attempt in the current controller. Residual-entry authority was consumed by model-options and is never reusable by set-model. A Codex rollout and identify-foreground are not prerequisites. Refresh /akk models after any terminal change or failed attempt."
739
+ ].join("\n");
740
+ }
741
+ export function formatAkkSetModelCommandResult(result) {
742
+ const outcome = nonEmptyString(result.outcome) ?? "uncertain";
743
+ const requested = recordValue(result.requested) ?? {};
744
+ const effective = recordValue(result.effective) ?? {};
745
+ const newSessionDefaults = recordValue(result.new_session_defaults) ?? {};
746
+ const uncertain = outcome === "uncertain" || result.do_not_retry === true;
747
+ const defaultsChanged = typeof result.defaults_changed === "boolean"
748
+ ? result.defaults_changed ? "yes" : "no"
749
+ : "unknown";
750
+ const requestedUltra = requested.reasoning_effort === "ultra";
751
+ return [
752
+ outcome === "changed"
753
+ ? "AKK changed and verified the coding-agent model."
754
+ : outcome === "already_effective"
755
+ ? "AKK verified that the requested model was already effective."
756
+ : "AKK could not prove the complete model-change postcondition.",
757
+ `terminal: ${nonEmptyString(result.terminal_id) ?? "unknown"}`,
758
+ `scope: ${nonEmptyString(result.scope) ?? "unknown"}`,
759
+ `requested model: ${nonEmptyString(requested.model) ?? "unknown"}`,
760
+ `requested reasoning: ${nonEmptyString(requested.reasoning_effort) ?? "unchanged/default"}`,
761
+ `effective model: ${nonEmptyString(effective.model) ?? "unproven"}`,
762
+ `effective reasoning: ${nonEmptyString(effective.reasoning_effort) ?? "unproven"}`,
763
+ `new-session default changed: ${defaultsChanged}`,
764
+ ...(nonEmptyString(newSessionDefaults.model)
765
+ ? [`new-session default model: ${nonEmptyString(newSessionDefaults.model)}`]
766
+ : []),
767
+ ...(nonEmptyString(newSessionDefaults.reasoning_effort)
768
+ ? [`new-session default reasoning: ${nonEmptyString(newSessionDefaults.reasoning_effort)}`]
769
+ : requestedUltra && result.scope === "current_and_new_sessions" && outcome === "changed"
770
+ ? ["new-session default reasoning: native non-ultra fallback (exact value is not exposed by this Codex TUI)"]
771
+ : []),
772
+ ...compatibilityWarningLines(result),
773
+ ...(nonEmptyString(result.reason)
774
+ ? [
775
+ `reason: ${sanitizeAkkModelFacingDiagnosticText(nonEmptyString(result.reason) ?? "")}`
776
+ ]
777
+ : []),
778
+ uncertain
779
+ ? "Next: do not retry automatically; inspect the shared pane, then refresh /akk models before any deliberate new attempt."
780
+ : "No task, approval, questionnaire response, or AKK Turn was created."
781
+ ].join("\n");
782
+ }
783
+ export function formatAkkRepairModelControlCommandResult(result) {
784
+ const outcome = nonEmptyString(result.outcome) ?? "uncertain";
785
+ const repaired = outcome === "repaired";
786
+ const uncertain = outcome === "uncertain" || result.do_not_retry === true;
787
+ return [
788
+ repaired
789
+ ? "AKK cleared and verified the exact stale Codex /model surface."
790
+ : "AKK could not prove the model-control repair postcondition.",
791
+ `terminal: ${nonEmptyString(result.terminal_id) ?? "unknown"}`,
792
+ `composer postcondition: ${nonEmptyString(result.composer_postcondition) ?? "unproven"}`,
793
+ `terminal input attempted: ${result.terminal_input_attempted === true ? "yes" : "no"}`,
794
+ ...compatibilityWarningLines(result),
795
+ ...(nonEmptyString(result.reason)
796
+ ? [
797
+ `reason: ${sanitizeAkkModelFacingDiagnosticText(nonEmptyString(result.reason) ?? "")}`
798
+ ]
799
+ : []),
800
+ uncertain
801
+ ? "Next: do not retry automatically; inspect the shared pane and refresh /akk list."
802
+ : "Next: refresh /akk list, then run /akk models before any deliberate set-model attempt.",
803
+ "This repair never submits a task, chooses a model, approves a prompt, or creates an AKK Turn."
804
+ ].join("\n");
805
+ }
806
+ export function isAkkRepairModelControlSuccess(result) {
807
+ const record = recordValue(result);
808
+ return record?.outcome === "repaired" || record?.outcome === "already_empty";
809
+ }
810
+ export function isAkkSetModelSuccess(result) {
811
+ const record = recordValue(result);
812
+ return record?.outcome === "changed" ||
813
+ record?.outcome === "already_effective";
814
+ }
815
+ export function formatAkkThreadTransitionCommandResult(result) {
816
+ if (!isAkkThreadTransitionSuccess(result)) {
817
+ const status = nonEmptyString(result.status) ?? "unknown";
818
+ const heading = status === "verified_recovery_required"
819
+ ? "AKK verified the native thread transition, but its Session commit requires recovery."
820
+ : "AKK could not verify the native thread transition outcome.";
821
+ return [
822
+ heading,
823
+ `status: ${status}`,
824
+ `terminal: ${nonEmptyString(result.terminal_id) ?? "unknown"}`,
825
+ ...(nonEmptyString(result.transition_id)
826
+ ? [`transition: ${nonEmptyString(result.transition_id)}`]
827
+ : []),
828
+ ...(nonEmptyString(result.reason)
829
+ ? [
830
+ `reason: ${sanitizeAkkModelFacingDiagnosticText(nonEmptyString(result.reason) ?? "")}`
831
+ ]
832
+ : []),
833
+ ...compatibilityWarningLines(result),
834
+ "No AKK Turn was created.",
835
+ "Next: do not retry automatically; refresh /akk list and use only its exact lifecycle recovery action."
836
+ ].join("\n");
837
+ }
838
+ const alreadyActive = result.status === "already_active";
839
+ const operation = nonEmptyString(result.operation) ?? "resume_thread";
840
+ const heading = alreadyActive
841
+ ? "AKK native thread was already active; no switch was needed."
842
+ : operation === "new_thread"
843
+ ? "AKK started and verified a new native thread."
844
+ : "AKK resumed and verified the selected native thread.";
845
+ return [
846
+ heading,
847
+ `terminal: ${nonEmptyString(result.terminal_id) ?? "unknown"}`,
848
+ ...(nonEmptyString(result.previous_session_id)
849
+ ? [`previous session: ${nonEmptyString(result.previous_session_id)}`]
850
+ : []),
851
+ `session: ${nonEmptyString(result.session_id) ?? "none"}`,
852
+ ...(nonEmptyString(result.previous_native_thread_id)
853
+ ? [
854
+ `previous native thread: ${nonEmptyString(result.previous_native_thread_id)}`
855
+ ]
856
+ : []),
857
+ `native thread: ${nonEmptyString(result.native_thread_id) ?? "unknown"}`,
858
+ ...compatibilityWarningLines(result),
859
+ "No AKK Turn was created. The next ordinary send creates the first Turn in this native context."
860
+ ].join("\n");
861
+ }
862
+ export function isAkkThreadTransitionSuccess(result) {
863
+ const record = recordValue(result);
864
+ return record?.status === "committed" || record?.status === "already_active";
865
+ }
866
+ export function buildAkkCommandCliArgs(command, config, context = {}) {
867
+ switch (command.action) {
868
+ case "help":
869
+ case "delegate":
870
+ return undefined;
871
+ case "doctor":
872
+ return withOptionalArgs(["doctor"], ["--openclaw-bin", nonEmptyString(config.openclawBin)]);
873
+ }
874
+ const storeDir = resolvePluginStoreDir(config);
875
+ const codexHome = nonEmptyString(config.codexHome);
876
+ const idleTimeoutMinutes = finiteNumberString(config.idleTimeoutMinutes);
877
+ switch (command.action) {
878
+ case "list":
879
+ return withOptionalArgs(["list", "--reconcile"], ["--store-dir", storeDir], ["--idle-timeout-minutes", idleTimeoutMinutes]);
880
+ case "watch": {
881
+ const openclawSession = nonEmptyString(context.sessionKey) ??
882
+ "agent:main:main";
883
+ return withOptionalArgs([
884
+ "watch-terminal",
885
+ "--terminal",
886
+ command.terminalId
887
+ ], ["--store-dir", storeDir], [
888
+ "--hard-timeout-minutes",
889
+ finiteNumberString(config.agentHardTimeoutMinutes)
890
+ ], ["--openclaw-session", openclawSession], ["--openclaw-bin", nonEmptyString(config.openclawBin)]);
891
+ }
892
+ case "unwatch":
893
+ return withOptionalArgs(["unwatch-terminal", "--watch", command.watchId], ["--store-dir", storeDir]);
894
+ case "list-resumable-threads":
895
+ return withOptionalArgs([
896
+ "list-resumable-threads",
897
+ "--terminal",
898
+ command.terminalId
899
+ ], ["--store-dir", storeDir], ["--codex-home", codexHome], ["--selection-scope", nonEmptyString(context.selectionScope)]);
900
+ case "model-options":
901
+ return withOptionalArgs([
902
+ "model-options",
903
+ "--terminal",
904
+ command.terminalId,
905
+ "--expected-binding-token",
906
+ requiredExpectedBindingToken(context.expectedBindingToken)
907
+ ], ["--store-dir", storeDir], ["--codex-home", codexHome]);
908
+ case "repair-model-control":
909
+ return withOptionalArgs([
910
+ "repair-model-control",
911
+ "--terminal",
912
+ command.terminalId,
913
+ "--expected-binding-token",
914
+ requiredExpectedBindingToken(context.expectedBindingToken)
915
+ ], ["--store-dir", storeDir], ["--codex-home", codexHome]);
916
+ case "set-model":
917
+ return withOptionalArgs([
918
+ "set-model",
919
+ "--terminal",
920
+ command.terminalId,
921
+ "--expected-binding-token",
922
+ requiredExpectedBindingToken(context.expectedBindingToken),
923
+ "--expected-catalog-fingerprint",
924
+ requiredExpectedCatalogFingerprint(context.expectedCatalogFingerprint),
925
+ "--model",
926
+ command.model
927
+ ], ["--reasoning-effort", command.reasoningEffort], ["--store-dir", storeDir], ["--codex-home", codexHome]);
928
+ case "new-thread":
929
+ return withOptionalArgs([
930
+ "new-thread",
931
+ "--terminal",
932
+ command.terminalId,
933
+ "--expected-binding-token",
934
+ requiredExpectedBindingToken(context.expectedBindingToken)
935
+ ], ["--store-dir", storeDir], ["--codex-home", codexHome]);
936
+ case "resume-thread":
937
+ if (!command.selection || command.selection.kind === "previous") {
938
+ return withOptionalArgs([
939
+ "list-resumable-threads",
940
+ "--terminal",
941
+ command.terminalId
942
+ ], ["--store-dir", storeDir], ["--codex-home", codexHome], ["--selection-scope", nonEmptyString(context.selectionScope)]);
943
+ }
944
+ if (command.selection.kind === "number") {
945
+ return withOptionalArgs([
946
+ "resume-thread",
947
+ "--terminal",
948
+ command.terminalId,
949
+ "--selection-snapshot",
950
+ requiredSelectionSnapshotId(context.selectionSnapshotId),
951
+ "--selection-number",
952
+ String(command.selection.selectionNumber),
953
+ "--selection-scope",
954
+ requiredSelectionScope(context.selectionScope)
955
+ ], ["--store-dir", storeDir], ["--codex-home", codexHome]);
956
+ }
957
+ if (command.selection.kind === "short-id") {
958
+ return withOptionalArgs([
959
+ "resume-thread",
960
+ "--terminal",
961
+ command.terminalId,
962
+ "--selection-snapshot",
963
+ requiredSelectionSnapshotId(context.selectionSnapshotId),
964
+ "--selection-short-id",
965
+ command.selection.shortId,
966
+ "--selection-scope",
967
+ requiredSelectionScope(context.selectionScope)
968
+ ], ["--store-dir", storeDir], ["--codex-home", codexHome]);
969
+ }
970
+ return withOptionalArgs([
971
+ "resume-thread",
972
+ "--terminal",
973
+ command.terminalId,
974
+ "--native-thread",
975
+ command.selection.nativeThreadId,
976
+ "--expected-binding-token",
977
+ requiredExpectedBindingToken(context.expectedBindingToken),
978
+ "--candidate-token",
979
+ requiredCandidateToken(context.candidateToken)
980
+ ], ["--store-dir", storeDir], ["--codex-home", codexHome]);
981
+ case "status":
982
+ if (command.watchId) {
983
+ return withOptionalArgs(["watch-status", "--watch", command.watchId], ["--store-dir", storeDir]);
984
+ }
985
+ return withOptionalArgs([
986
+ "status",
987
+ "--reconcile",
988
+ ...(command.turnId
989
+ ? ["--turn", command.turnId]
990
+ : [])
991
+ ], ["--store-dir", storeDir], ["--idle-timeout-minutes", idleTimeoutMinutes]);
992
+ case "send": {
993
+ const openclawSession = nonEmptyString(context.sessionKey) ??
994
+ "agent:main:main";
995
+ return withOptionalArgs([
996
+ "send",
997
+ "--session",
998
+ command.selector,
999
+ "--message",
1000
+ command.message,
1001
+ "--background"
1002
+ ], ["--store-dir", storeDir], ["--idle-timeout-minutes", idleTimeoutMinutes], ["--agent-timeout-minutes", finiteNumberString(config.agentTimeoutMinutes)], ["--agent-hard-timeout-minutes", finiteNumberString(config.agentHardTimeoutMinutes)], ["--message-id", nonEmptyString(context.messageId)], ["--openclaw-session", openclawSession], ["--gateway-method", AKK_CALLBACK_METHOD], ["--gateway-session", openclawSession], ["--openclaw-bin", nonEmptyString(config.openclawBin)]);
1003
+ }
1004
+ case "respond":
1005
+ return withOptionalArgs([
1006
+ "respond",
1007
+ "--turn",
1008
+ command.turnId,
1009
+ "--message",
1010
+ command.message
1011
+ ], ["--store-dir", storeDir]);
1012
+ case "approve":
1013
+ // The Host adapter resolves the current private approval
1014
+ // authority immediately before invoking the CLI.
1015
+ return undefined;
1016
+ case "renew":
1017
+ return withOptionalArgs(["renew", "--turn", command.turnId], [
1018
+ "--minutes",
1019
+ command.minutes ?? finiteNumberString(config.agentTimeoutMinutes)
1020
+ ], ["--store-dir", storeDir]);
1021
+ case "retry-callback":
1022
+ return withOptionalArgs(["retry-callback", "--turn", command.turnId], ["--store-dir", storeDir]);
1023
+ case "cancel": {
1024
+ return withOptionalArgs(["cancel", "--turn", command.turnId], ["--store-dir", storeDir], ["--idle-timeout-minutes", idleTimeoutMinutes]);
1025
+ }
1026
+ case "close":
1027
+ return withOptionalArgs([
1028
+ "close",
1029
+ "--turn",
1030
+ command.turnId,
1031
+ "--reason",
1032
+ command.reason
1033
+ ], ["--expected-message-id", command.expectedMessageId], ["--expected-transition-id", command.expectedTransitionId], ["--store-dir", storeDir]);
1034
+ }
1035
+ }
1036
+ function isTerminalWatchId(value) {
1037
+ return /^terminal-watch-[A-Za-z0-9._:-]+$/u.test(value);
1038
+ }
1039
+ function parseSelectorMessage(input) {
1040
+ const match = /^((?:(?:codex|claude):latest|only|latest|codex|claude|@[0-9a-f]+))\s*:\s*([\s\S]*)$/iu.exec(input);
1041
+ const message = match?.[2]?.trim();
1042
+ if (!match) {
1043
+ return undefined;
1044
+ }
1045
+ if (!message) {
1046
+ throw new Error("Usage: /akk <session-selector>: <message>");
1047
+ }
1048
+ return {
1049
+ selector: match[1].toLowerCase(),
1050
+ message
1051
+ };
1052
+ }
1053
+ function parseTurnResponse(input) {
1054
+ const match = /^(\S+)\s*:\s*([\s\S]*)$/u.exec(input.trim());
1055
+ const selector = match?.[1]?.trim();
1056
+ const message = match?.[2]?.trim();
1057
+ if (!selector || !message) {
1058
+ throw new Error("Usage: /akk respond <turn-selector>: <answer>");
1059
+ }
1060
+ return { selector, message };
1061
+ }
1062
+ function assertExactTerminalId(value, usage) {
1063
+ if (!/^terminal:v\d+:[^\s]+$/u.test(value)) {
1064
+ throw new Error(`${usage}; use the exact terminal_id returned by /akk list`);
1065
+ }
1066
+ }
1067
+ function isAkkModelSemanticIdentifier(value, maxLength) {
1068
+ return value.length <= maxLength &&
1069
+ /^[A-Za-z0-9][A-Za-z0-9._:/+\-]*$/u.test(value);
1070
+ }
1071
+ function isExactNativeThreadId(value) {
1072
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu.test(value);
1073
+ }
1074
+ function parseAkkResumeSelection(value, usage) {
1075
+ const normalized = value.toLowerCase();
1076
+ if (normalized === "previous" || normalized === "prev" || value === "刚才那个") {
1077
+ return { kind: "previous" };
1078
+ }
1079
+ if (isExactNativeThreadId(value)) {
1080
+ return { kind: "exact", nativeThreadId: normalized };
1081
+ }
1082
+ if (/^[1-9][0-9]*$/u.test(value)) {
1083
+ const selectionNumber = Number(value);
1084
+ if (Number.isSafeInteger(selectionNumber)) {
1085
+ return { kind: "number", selectionNumber };
1086
+ }
1087
+ }
1088
+ if (/^@[a-f0-9]{8,32}$/u.test(normalized)) {
1089
+ return { kind: "short-id", shortId: normalized };
1090
+ }
1091
+ throw new Error(`${usage}; use a complete UUID or a selection exactly returned by /akk threads`);
1092
+ }
1093
+ function requiredExpectedBindingToken(value) {
1094
+ const token = nonEmptyString(value);
1095
+ if (!token) {
1096
+ throw new Error("expected binding token is required; refresh the lifecycle snapshot before switching native threads");
1097
+ }
1098
+ return token;
1099
+ }
1100
+ function requiredCandidateToken(value) {
1101
+ const token = nonEmptyString(value);
1102
+ if (!token) {
1103
+ throw new Error("candidate token is required; select an exact resumable row from the current lifecycle snapshot");
1104
+ }
1105
+ return token;
1106
+ }
1107
+ function requiredExpectedCatalogFingerprint(value) {
1108
+ const fingerprint = nonEmptyString(value);
1109
+ if (!fingerprint) {
1110
+ throw new Error("expected catalog fingerprint is required; refresh model options before switching the model");
1111
+ }
1112
+ return fingerprint;
1113
+ }
1114
+ function requiredSelectionScope(value) {
1115
+ const scope = nonEmptyString(value);
1116
+ if (!scope) {
1117
+ throw new Error("snapshot-bound resume requires the current controller session scope; run /akk threads again");
1118
+ }
1119
+ return scope;
1120
+ }
1121
+ function requiredSelectionSnapshotId(value) {
1122
+ const snapshotId = nonEmptyString(value);
1123
+ if (!snapshotId) {
1124
+ throw new Error("snapshot-bound resume requires the last displayed snapshot; run /akk threads again");
1125
+ }
1126
+ return snapshotId;
1127
+ }
1128
+ export function resolvePluginStoreDir(config, gatewayCwd = process.cwd()) {
1129
+ const configured = nonEmptyString(config.storeDir);
1130
+ if (!configured) {
1131
+ return undefined;
1132
+ }
1133
+ if (path.isAbsolute(configured)) {
1134
+ return path.normalize(configured);
1135
+ }
1136
+ return path.resolve(gatewayCwd, configured);
1137
+ }
1138
+ function takeRequiredToken(input, usage) {
1139
+ const parsed = takeToken(input);
1140
+ if (!parsed.token) {
1141
+ throw new Error(usage);
1142
+ }
1143
+ return parsed;
1144
+ }
1145
+ function takeToken(input) {
1146
+ const value = String(input ?? "").trimStart();
1147
+ const match = value.match(/^(\S+)(?:\s+([\s\S]*))?$/);
1148
+ if (!match) {
1149
+ return { token: "", rest: "" };
1150
+ }
1151
+ return {
1152
+ token: match[1],
1153
+ rest: match[2] ?? ""
1154
+ };
1155
+ }
1156
+ function finiteNumberString(value) {
1157
+ return typeof value === "number" && Number.isFinite(value)
1158
+ ? String(value)
1159
+ : undefined;
1160
+ }
1161
+ function withOptionalArgs(args, ...optionalArgs) {
1162
+ for (const [flag, value] of optionalArgs) {
1163
+ if (value !== undefined && value !== "") {
1164
+ args.push(flag, value);
1165
+ }
1166
+ }
1167
+ return args;
1168
+ }
1169
+ function terminalWatchRecord(result) {
1170
+ return recordValue(result.watch) ??
1171
+ recordValue(result.terminal_watch) ??
1172
+ result;
1173
+ }
1174
+ function formatTerminalLine(terminal) {
1175
+ const terminalControl = recordValue(terminal.terminal_control) ?? {};
1176
+ const context = [
1177
+ nonEmptyString(terminalControl.target)
1178
+ ? `${nonEmptyString(terminalControl.kind) ?? "tmux"} ${nonEmptyString(terminalControl.target)}`
1179
+ : undefined,
1180
+ nonEmptyString(terminal.command),
1181
+ nonEmptyString(terminal.workspace) ?? nonEmptyString(terminal.cwd)
1182
+ ].filter((value) => Boolean(value)).join(" · ");
1183
+ return [
1184
+ nonEmptyString(terminal.short_ref) ??
1185
+ nonEmptyString(terminal.id) ??
1186
+ "unknown",
1187
+ nonEmptyString(terminal.agent) ?? "agent",
1188
+ nonEmptyString(terminal.process_state) ?? "unknown",
1189
+ nonEmptyString(terminal.activity_state),
1190
+ truncateText(context, 90)
1191
+ ].filter(Boolean).join(" | ");
1192
+ }
1193
+ function formatManagedTurnLine(turn) {
1194
+ const executor = recordValue(turn.executor) ?? {};
1195
+ const context = nonEmptyString(turn.request) ??
1196
+ [
1197
+ nonEmptyString(turn.workspace),
1198
+ nonEmptyString(turn.callback_state)
1199
+ ].filter((value) => Boolean(value)).join(" · ");
1200
+ return [
1201
+ nonEmptyString(turn.short_ref) ??
1202
+ nonEmptyString(turn.turn_id) ??
1203
+ nonEmptyString(turn.conversation_id) ??
1204
+ nonEmptyString(turn.id) ??
1205
+ "unknown",
1206
+ nonEmptyString(turn.agent) ?? nonEmptyString(executor.kind) ?? "agent",
1207
+ nonEmptyString(turn.lifecycle_state) ?? nonEmptyString(turn.status) ?? "unknown",
1208
+ truncateText(context, 90)
1209
+ ].filter(Boolean).join(" | ");
1210
+ }
1211
+ function formatTerminalWatchLine(watch) {
1212
+ return [
1213
+ nonEmptyString(watch.short_ref) ??
1214
+ nonEmptyString(watch.watch_id) ??
1215
+ "unknown",
1216
+ nonEmptyString(watch.agent) ?? "agent",
1217
+ nonEmptyString(watch.status) ?? "unknown",
1218
+ nonEmptyString(watch.terminal_id)
1219
+ ].filter(Boolean).join(" | ");
1220
+ }
1221
+ function formatAvailableActions(label, resource) {
1222
+ const actions = recordValue(resource.available_actions);
1223
+ if (!actions) {
1224
+ return [];
1225
+ }
1226
+ const displayedActions = new Set([
1227
+ "send",
1228
+ "watch",
1229
+ "unwatch",
1230
+ "respond",
1231
+ "status",
1232
+ "approve",
1233
+ "cancel",
1234
+ "renew",
1235
+ "retry_callback",
1236
+ "close",
1237
+ "list_resumable_threads",
1238
+ "new_thread",
1239
+ "resume_thread",
1240
+ "native_inspect",
1241
+ "model_options",
1242
+ "repair_model_control"
1243
+ ]);
1244
+ const names = Object.keys(actions)
1245
+ .filter((name) => displayedActions.has(name))
1246
+ .sort();
1247
+ return names.length > 0 ? [` ${label}: ${names.join(", ")}`] : [];
1248
+ }
1249
+ function compatibilityWarningLines(resource) {
1250
+ const capability = recordValue(resource.capability);
1251
+ const warnings = [
1252
+ nonEmptyString(resource.compatibility_warning),
1253
+ nonEmptyString(capability?.compatibilityWarning),
1254
+ ...(Array.isArray(resource.compatibility_warnings)
1255
+ ? resource.compatibility_warnings
1256
+ .map(nonEmptyString)
1257
+ .filter((value) => Boolean(value))
1258
+ : [])
1259
+ ].filter((value) => Boolean(value));
1260
+ return [...new Set(warnings)].map((warning) => `compatibility warning: ${truncateText(sanitizeAkkModelFacingDiagnosticText(warning), 300)}`);
1261
+ }
1262
+ function orphanedTerminalDispatchRecovery(task) {
1263
+ const orphaned = task.orphaned_terminal_dispatch !== null &&
1264
+ typeof task.orphaned_terminal_dispatch === "object" &&
1265
+ !Array.isArray(task.orphaned_terminal_dispatch)
1266
+ ? task.orphaned_terminal_dispatch
1267
+ : undefined;
1268
+ return orphaned
1269
+ ? nonEmptyString(orphaned.recovery)
1270
+ : undefined;
1271
+ }
1272
+ //# sourceMappingURL=semantic-tool-command-helpers.js.map