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