@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.
- package/CHANGELOG.md +36 -0
- package/README.md +27 -6
- package/dist/src/callback-outbox-policy.js +27 -6
- package/dist/src/callback-outbox-policy.js.map +1 -1
- package/dist/src/callback-outbox-service.d.ts +4 -30
- package/dist/src/callback-outbox-service.js +21 -154
- package/dist/src/callback-outbox-service.js.map +1 -1
- package/dist/src/callback-outbox-settlement.js +13 -8
- package/dist/src/callback-outbox-settlement.js.map +1 -1
- package/dist/src/callback-route-service.d.ts +46 -0
- package/dist/src/callback-route-service.js +155 -0
- package/dist/src/callback-route-service.js.map +1 -0
- package/dist/src/claude-terminal-agent-adapter.js +4 -0
- package/dist/src/claude-terminal-agent-adapter.js.map +1 -1
- package/dist/src/cli-core.js +9 -1
- package/dist/src/cli-core.js.map +1 -1
- package/dist/src/codex-process-incarnation.d.ts +8 -0
- package/dist/src/codex-process-incarnation.js +36 -0
- package/dist/src/codex-process-incarnation.js.map +1 -0
- package/dist/src/codex-terminal-agent-adapter.js +4 -0
- package/dist/src/codex-terminal-agent-adapter.js.map +1 -1
- package/dist/src/deferred-foreground-conflict-policy.d.ts +22 -0
- package/dist/src/deferred-foreground-conflict-policy.js +52 -0
- package/dist/src/deferred-foreground-conflict-policy.js.map +1 -0
- package/dist/src/durable-notification-kernel.d.ts +94 -0
- package/dist/src/durable-notification-kernel.js +68 -0
- package/dist/src/durable-notification-kernel.js.map +1 -0
- package/dist/src/herdr-socket-transport.d.ts +43 -0
- package/dist/src/herdr-socket-transport.js +170 -0
- package/dist/src/herdr-socket-transport.js.map +1 -0
- package/dist/src/herdr-terminal-control-provider.d.ts +2 -45
- package/dist/src/herdr-terminal-control-provider.js +8 -173
- package/dist/src/herdr-terminal-control-provider.js.map +1 -1
- package/dist/src/host-adapter-capabilities.d.ts +35 -0
- package/dist/src/host-adapter-capabilities.js +146 -0
- package/dist/src/host-adapter-capabilities.js.map +1 -0
- package/dist/src/host-adapter.d.ts +9 -3
- package/dist/src/host-adapter.js +33 -9
- package/dist/src/host-adapter.js.map +1 -1
- package/dist/src/host-bridge-tools.d.ts +3 -4
- package/dist/src/host-bridge-tools.js +49 -92
- package/dist/src/host-bridge-tools.js.map +1 -1
- package/dist/src/host-bridge.js +5 -5
- package/dist/src/host-bridge.js.map +1 -1
- package/dist/src/host-monitor-reconciliation.d.ts +6 -0
- package/dist/src/host-monitor-reconciliation.js +96 -0
- package/dist/src/host-monitor-reconciliation.js.map +1 -0
- package/dist/src/managed-session.js +2 -18
- package/dist/src/managed-session.js.map +1 -1
- package/dist/src/native-thread-lifecycle-cli-adapter.d.ts +13 -0
- package/dist/src/native-thread-lifecycle-cli-adapter.js +635 -3
- package/dist/src/native-thread-lifecycle-cli-adapter.js.map +1 -1
- package/dist/src/openclaw-list-projection.d.ts +2 -0
- package/dist/src/openclaw-list-projection.js +3 -0
- package/dist/src/openclaw-list-projection.js.map +1 -0
- package/dist/src/openclaw-model-facing-field-policy.d.ts +2 -0
- package/dist/src/openclaw-model-facing-field-policy.js +3 -0
- package/dist/src/openclaw-model-facing-field-policy.js.map +1 -0
- package/dist/src/openclaw-plugin-command-adapter.d.ts +6 -29
- package/dist/src/openclaw-plugin-command-adapter.js +7 -2370
- package/dist/src/openclaw-plugin-command-adapter.js.map +1 -1
- package/dist/src/openclaw-plugin-helpers.d.ts +2 -121
- package/dist/src/openclaw-plugin-helpers.js +2 -1164
- package/dist/src/openclaw-plugin-helpers.js.map +1 -1
- package/dist/src/openclaw-plugin-schemas.d.ts +2 -510
- package/dist/src/openclaw-plugin-schemas.js +2 -519
- package/dist/src/openclaw-plugin-schemas.js.map +1 -1
- package/dist/src/openclaw-plugin-supervisor.d.ts +4 -5
- package/dist/src/openclaw-plugin-supervisor.js +5 -94
- package/dist/src/openclaw-plugin-supervisor.js.map +1 -1
- package/dist/src/openclaw-plugin-value-helpers.d.ts +2 -0
- package/dist/src/openclaw-plugin-value-helpers.js +3 -0
- package/dist/src/openclaw-plugin-value-helpers.js.map +1 -0
- package/dist/src/openclaw-private-authority-offers.d.ts +4 -39
- package/dist/src/openclaw-private-authority-offers.js +3 -258
- package/dist/src/openclaw-private-authority-offers.js.map +1 -1
- package/dist/src/semantic-private-authority-offers.d.ts +41 -0
- package/dist/src/semantic-private-authority-offers.js +261 -0
- package/dist/src/semantic-private-authority-offers.js.map +1 -0
- package/dist/src/semantic-tool-arguments.d.ts +9 -0
- package/dist/src/semantic-tool-arguments.js +64 -0
- package/dist/src/semantic-tool-arguments.js.map +1 -0
- package/dist/src/semantic-tool-catalog.d.ts +48 -0
- package/dist/src/semantic-tool-catalog.js +105 -0
- package/dist/src/semantic-tool-catalog.js.map +1 -0
- package/dist/src/semantic-tool-command-helpers.d.ts +145 -0
- package/dist/src/semantic-tool-command-helpers.js +1272 -0
- package/dist/src/semantic-tool-command-helpers.js.map +1 -0
- package/dist/src/semantic-tool-list-projection.d.ts +10 -0
- package/dist/src/semantic-tool-list-projection.js +497 -0
- package/dist/src/semantic-tool-list-projection.js.map +1 -0
- package/dist/src/semantic-tool-model-facing-field-policy.d.ts +3 -0
- package/dist/src/semantic-tool-model-facing-field-policy.js +66 -0
- package/dist/src/semantic-tool-model-facing-field-policy.js.map +1 -0
- package/dist/src/semantic-tool-presentation.d.ts +37 -0
- package/dist/src/semantic-tool-presentation.js +680 -0
- package/dist/src/semantic-tool-presentation.js.map +1 -0
- package/dist/src/semantic-tool-private-authority.d.ts +39 -0
- package/dist/src/semantic-tool-private-authority.js +602 -0
- package/dist/src/semantic-tool-private-authority.js.map +1 -0
- package/dist/src/semantic-tool-relay.d.ts +16 -0
- package/dist/src/semantic-tool-relay.js +175 -0
- package/dist/src/semantic-tool-relay.js.map +1 -0
- package/dist/src/semantic-tool-runtime.d.ts +10 -0
- package/dist/src/semantic-tool-runtime.js +1157 -0
- package/dist/src/semantic-tool-runtime.js.map +1 -0
- package/dist/src/semantic-tool-schemas.d.ts +563 -0
- package/dist/src/semantic-tool-schemas.js +573 -0
- package/dist/src/semantic-tool-schemas.js.map +1 -0
- package/dist/src/semantic-tool-value-helpers.d.ts +5 -0
- package/dist/src/semantic-tool-value-helpers.js +27 -0
- package/dist/src/semantic-tool-value-helpers.js.map +1 -0
- package/dist/src/store-event-presentation.d.ts +17 -0
- package/dist/src/store-event-presentation.js +33 -0
- package/dist/src/store-event-presentation.js.map +1 -0
- package/dist/src/store.d.ts +3 -16
- package/dist/src/store.js +2 -30
- package/dist/src/store.js.map +1 -1
- package/dist/src/terminal-action-projection.d.ts +3 -17
- package/dist/src/terminal-action-projection.js +13 -41
- package/dist/src/terminal-action-projection.js.map +1 -1
- package/dist/src/terminal-agent-adapter.d.ts +7 -0
- package/dist/src/terminal-agent-adapter.js +8 -0
- package/dist/src/terminal-agent-adapter.js.map +1 -1
- package/dist/src/terminal-agent-bridge.d.ts +35 -332
- package/dist/src/terminal-agent-bridge.js +293 -2798
- package/dist/src/terminal-agent-bridge.js.map +1 -1
- package/dist/src/terminal-approval-cli-adapter.d.ts +17 -0
- package/dist/src/terminal-approval-cli-adapter.js +921 -0
- package/dist/src/terminal-approval-cli-adapter.js.map +1 -0
- package/dist/src/terminal-command-cli-adapter.d.ts +2 -429
- package/dist/src/terminal-command-cli-adapter.js +344 -6061
- package/dist/src/terminal-command-cli-adapter.js.map +1 -1
- package/dist/src/terminal-command-cli-ports.d.ts +443 -0
- package/dist/src/terminal-command-cli-ports.js +2 -0
- package/dist/src/terminal-command-cli-ports.js.map +1 -0
- package/dist/src/terminal-command-dispatch-preparation.d.ts +81 -0
- package/dist/src/terminal-command-dispatch-preparation.js +209 -0
- package/dist/src/terminal-command-dispatch-preparation.js.map +1 -0
- package/dist/src/terminal-command-dispatch-transport.d.ts +35 -0
- package/dist/src/terminal-command-dispatch-transport.js +859 -0
- package/dist/src/terminal-command-dispatch-transport.js.map +1 -0
- package/dist/src/terminal-command-foreground-proof.d.ts +32 -0
- package/dist/src/terminal-command-foreground-proof.js +72 -0
- package/dist/src/terminal-command-foreground-proof.js.map +1 -0
- package/dist/src/terminal-command-send-preflight.d.ts +41 -0
- package/dist/src/terminal-command-send-preflight.js +86 -0
- package/dist/src/terminal-command-send-preflight.js.map +1 -0
- package/dist/src/terminal-composer-classifier.d.ts +55 -0
- package/dist/src/terminal-composer-classifier.js +638 -0
- package/dist/src/terminal-composer-classifier.js.map +1 -0
- package/dist/src/terminal-control-ref.d.ts +23 -0
- package/dist/src/terminal-control-ref.js +32 -0
- package/dist/src/terminal-control-ref.js.map +1 -1
- package/dist/src/terminal-dispatch-recovery-authority.d.ts +56 -0
- package/dist/src/terminal-dispatch-recovery-authority.js +251 -0
- package/dist/src/terminal-dispatch-recovery-authority.js.map +1 -0
- package/dist/src/terminal-dispatch-recovery-cli-adapter.d.ts +1 -9
- package/dist/src/terminal-dispatch-recovery-cli-adapter.js +5 -240
- package/dist/src/terminal-dispatch-recovery-cli-adapter.js.map +1 -1
- package/dist/src/terminal-handoff-cli-adapter.d.ts +1 -11
- package/dist/src/terminal-handoff-cli-adapter.js +2 -39
- package/dist/src/terminal-handoff-cli-adapter.js.map +1 -1
- package/dist/src/terminal-human-explicit-send-cli-adapter.d.ts +25 -0
- package/dist/src/terminal-human-explicit-send-cli-adapter.js +903 -0
- package/dist/src/terminal-human-explicit-send-cli-adapter.js.map +1 -0
- package/dist/src/terminal-identity-authority-cli-adapter.d.ts +1 -6
- package/dist/src/terminal-identity-authority-cli-adapter.js +3 -33
- package/dist/src/terminal-identity-authority-cli-adapter.js.map +1 -1
- package/dist/src/terminal-interaction-cli-adapter.js +209 -210
- package/dist/src/terminal-interaction-cli-adapter.js.map +1 -1
- package/dist/src/terminal-interaction-core.d.ts +0 -2
- package/dist/src/terminal-interaction-core.js +4 -3
- package/dist/src/terminal-interaction-core.js.map +1 -1
- package/dist/src/terminal-interaction-protocol.d.ts +21 -0
- package/dist/src/terminal-interaction-protocol.js +74 -0
- package/dist/src/terminal-interaction-protocol.js.map +1 -1
- package/dist/src/terminal-interaction-response-bridge.d.ts +126 -0
- package/dist/src/terminal-interaction-response-bridge.js +579 -0
- package/dist/src/terminal-interaction-response-bridge.js.map +1 -0
- package/dist/src/terminal-interaction-response-transaction.d.ts +44 -0
- package/dist/src/terminal-interaction-response-transaction.js +56 -0
- package/dist/src/terminal-interaction-response-transaction.js.map +1 -0
- package/dist/src/terminal-list-action-policy.d.ts +43 -0
- package/dist/src/terminal-list-action-policy.js +164 -0
- package/dist/src/terminal-list-action-policy.js.map +1 -0
- package/dist/src/terminal-list-cli-adapter.d.ts +6 -36
- package/dist/src/terminal-list-cli-adapter.js +314 -1711
- package/dist/src/terminal-list-cli-adapter.js.map +1 -1
- package/dist/src/terminal-list-facts.d.ts +129 -0
- package/dist/src/terminal-list-facts.js +179 -0
- package/dist/src/terminal-list-facts.js.map +1 -0
- package/dist/src/terminal-list-inventory.d.ts +59 -0
- package/dist/src/terminal-list-inventory.js +194 -0
- package/dist/src/terminal-list-inventory.js.map +1 -0
- package/dist/src/terminal-list-ownership-service.d.ts +118 -0
- package/dist/src/terminal-list-ownership-service.js +1003 -0
- package/dist/src/terminal-list-ownership-service.js.map +1 -0
- package/dist/src/terminal-list-projection-service.d.ts +49 -0
- package/dist/src/terminal-list-projection-service.js +407 -0
- package/dist/src/terminal-list-projection-service.js.map +1 -0
- package/dist/src/terminal-list-renderer.d.ts +12 -11
- package/dist/src/terminal-list-renderer.js +237 -104
- package/dist/src/terminal-list-renderer.js.map +1 -1
- package/dist/src/terminal-managed-send-cli-adapter.d.ts +33 -0
- package/dist/src/terminal-managed-send-cli-adapter.js +994 -0
- package/dist/src/terminal-managed-send-cli-adapter.js.map +1 -0
- package/dist/src/terminal-managed-turn-list-action-policy.d.ts +47 -0
- package/dist/src/terminal-managed-turn-list-action-policy.js +64 -0
- package/dist/src/terminal-managed-turn-list-action-policy.js.map +1 -0
- package/dist/src/terminal-model-control-action-policy.d.ts +60 -0
- package/dist/src/terminal-model-control-action-policy.js +96 -0
- package/dist/src/terminal-model-control-action-policy.js.map +1 -0
- package/dist/src/terminal-model-control-availability.d.ts +68 -0
- package/dist/src/terminal-model-control-availability.js +157 -0
- package/dist/src/terminal-model-control-availability.js.map +1 -0
- package/dist/src/terminal-model-control-bridge.d.ts +48 -0
- package/dist/src/terminal-model-control-bridge.js +259 -0
- package/dist/src/terminal-model-control-bridge.js.map +1 -0
- package/dist/src/terminal-model-control-profile.d.ts +55 -0
- package/dist/src/terminal-model-control-profile.js +137 -0
- package/dist/src/terminal-model-control-profile.js.map +1 -0
- package/dist/src/terminal-model-control-subject.d.ts +34 -0
- package/dist/src/terminal-model-control-subject.js +58 -0
- package/dist/src/terminal-model-control-subject.js.map +1 -0
- package/dist/src/terminal-model-control-transaction.d.ts +19 -0
- package/dist/src/terminal-model-control-transaction.js +39 -0
- package/dist/src/terminal-model-control-transaction.js.map +1 -0
- package/dist/src/terminal-model-control.d.ts +331 -0
- package/dist/src/terminal-model-control.js +1686 -0
- package/dist/src/terminal-model-control.js.map +1 -0
- package/dist/src/terminal-monitor-application-service.js +50 -17
- package/dist/src/terminal-monitor-application-service.js.map +1 -1
- package/dist/src/terminal-native-inspection-bridge.d.ts +211 -0
- package/dist/src/terminal-native-inspection-bridge.js +1127 -0
- package/dist/src/terminal-native-inspection-bridge.js.map +1 -0
- package/dist/src/terminal-runtime-cli-adapter.d.ts +2 -0
- package/dist/src/terminal-runtime-cli-adapter.js +59 -17
- package/dist/src/terminal-runtime-cli-adapter.js.map +1 -1
- package/dist/src/terminal-submission-retry-application.d.ts +24 -0
- package/dist/src/terminal-submission-retry-application.js +402 -0
- package/dist/src/terminal-submission-retry-application.js.map +1 -0
- package/dist/src/terminal-submission-retry-ports.d.ts +30 -0
- package/dist/src/terminal-submission-retry-ports.js +2 -0
- package/dist/src/terminal-submission-retry-ports.js.map +1 -0
- package/dist/src/terminal-submission-retry-reconciliation.d.ts +236 -0
- package/dist/src/terminal-submission-retry-reconciliation.js +1130 -0
- package/dist/src/terminal-submission-retry-reconciliation.js.map +1 -0
- package/dist/src/terminal-submission-retry-transport.d.ts +58 -0
- package/dist/src/terminal-submission-retry-transport.js +675 -0
- package/dist/src/terminal-submission-retry-transport.js.map +1 -0
- package/dist/src/terminal-text-submission-bridge.d.ts +200 -0
- package/dist/src/terminal-text-submission-bridge.js +632 -0
- package/dist/src/terminal-text-submission-bridge.js.map +1 -0
- package/dist/src/terminal-user-explicit-send-policy.d.ts +29 -0
- package/dist/src/terminal-user-explicit-send-policy.js +46 -0
- package/dist/src/terminal-user-explicit-send-policy.js.map +1 -0
- package/dist/src/terminal-watch-cli-adapter.js +91 -143
- package/dist/src/terminal-watch-cli-adapter.js.map +1 -1
- package/dist/src/terminal-watch-codec.d.ts +9 -0
- package/dist/src/terminal-watch-codec.js +1051 -0
- package/dist/src/terminal-watch-codec.js.map +1 -0
- package/dist/src/terminal-watch-interaction-response-store.d.ts +19 -0
- package/dist/src/terminal-watch-interaction-response-store.js +87 -0
- package/dist/src/terminal-watch-interaction-response-store.js.map +1 -0
- package/dist/src/terminal-watch-record.d.ts +319 -0
- package/dist/src/terminal-watch-record.js +742 -0
- package/dist/src/terminal-watch-record.js.map +1 -0
- package/dist/src/terminal-watch-service.js +48 -27
- package/dist/src/terminal-watch-service.js.map +1 -1
- package/dist/src/terminal-watch-store.d.ts +3 -279
- package/dist/src/terminal-watch-store.js +5 -1779
- package/dist/src/terminal-watch-store.js.map +1 -1
- package/docs/quickstart-herdr.md +1 -1
- package/docs/quickstart-tmux.md +27 -2
- package/openclaw.plugin.json +13 -1
- package/package.json +7 -2
- 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
|