@scotthuang/agent-knock-knock 0.12.11 → 0.12.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -0
- package/README.md +43 -30
- package/dist/src/approval-policy.d.ts +11 -2
- package/dist/src/approval-policy.js +33 -7
- package/dist/src/approval-policy.js.map +1 -1
- package/dist/src/callback-cli-adapter.d.ts +47 -0
- package/dist/src/callback-cli-adapter.js +156 -0
- package/dist/src/callback-cli-adapter.js.map +1 -0
- package/dist/src/callback-outbox-policy.d.ts +95 -0
- package/dist/src/callback-outbox-policy.js +149 -0
- package/dist/src/callback-outbox-policy.js.map +1 -0
- package/dist/src/callback-outbox-service.d.ts +247 -0
- package/dist/src/callback-outbox-service.js +1053 -0
- package/dist/src/callback-outbox-service.js.map +1 -0
- package/dist/src/callback-outbox-settlement.d.ts +54 -0
- package/dist/src/callback-outbox-settlement.js +241 -0
- package/dist/src/callback-outbox-settlement.js.map +1 -0
- package/dist/src/canonical-json.d.ts +1 -0
- package/dist/src/canonical-json.js +14 -0
- package/dist/src/canonical-json.js.map +1 -0
- package/dist/src/claude-lifecycle-compatibility.js +15 -0
- package/dist/src/claude-lifecycle-compatibility.js.map +1 -1
- package/dist/src/claude-local-transcript-provider.d.ts +82 -1
- package/dist/src/claude-local-transcript-provider.js +873 -23
- package/dist/src/claude-local-transcript-provider.js.map +1 -1
- package/dist/src/cli-command-runtime.d.ts +14 -0
- package/dist/src/cli-command-runtime.js +164 -0
- package/dist/src/cli-command-runtime.js.map +1 -0
- package/dist/src/cli-core.d.ts +4 -42
- package/dist/src/cli-core.js +958 -28684
- package/dist/src/cli-core.js.map +1 -1
- package/dist/src/cli-runtime-context.d.ts +57 -0
- package/dist/src/cli-runtime-context.js +118 -0
- package/dist/src/cli-runtime-context.js.map +1 -0
- package/dist/src/codex-lifecycle-compatibility.js +2 -1
- package/dist/src/codex-lifecycle-compatibility.js.map +1 -1
- package/dist/src/codex-local-session-provider.d.ts +18 -0
- package/dist/src/codex-local-session-provider.js +67 -0
- package/dist/src/codex-local-session-provider.js.map +1 -1
- package/dist/src/codex-session-provider.js +1 -3
- package/dist/src/codex-session-provider.js.map +1 -1
- package/dist/src/conversation-trace.d.ts +30 -0
- package/dist/src/conversation-trace.js +185 -0
- package/dist/src/conversation-trace.js.map +1 -0
- package/dist/src/deferred-foreground-application-service.d.ts +84 -0
- package/dist/src/deferred-foreground-application-service.js +742 -0
- package/dist/src/deferred-foreground-application-service.js.map +1 -0
- package/dist/src/deferred-foreground-authority-cli-adapter.d.ts +78 -0
- package/dist/src/deferred-foreground-authority-cli-adapter.js +795 -0
- package/dist/src/deferred-foreground-authority-cli-adapter.js.map +1 -0
- package/dist/src/deferred-foreground-boundary.d.ts +61 -0
- package/dist/src/deferred-foreground-boundary.js +2 -0
- package/dist/src/deferred-foreground-boundary.js.map +1 -0
- package/dist/src/deferred-foreground-capability.d.ts +4 -0
- package/dist/src/deferred-foreground-capability.js +184 -0
- package/dist/src/deferred-foreground-capability.js.map +1 -0
- package/dist/src/deferred-foreground-preparation-cli-adapter.d.ts +53 -0
- package/dist/src/deferred-foreground-preparation-cli-adapter.js +210 -0
- package/dist/src/deferred-foreground-preparation-cli-adapter.js.map +1 -0
- package/dist/src/deferred-foreground-preparation-service.d.ts +72 -0
- package/dist/src/deferred-foreground-preparation-service.js +179 -0
- package/dist/src/deferred-foreground-preparation-service.js.map +1 -0
- package/dist/src/deferred-foreground-recovery-cli-adapter.d.ts +139 -0
- package/dist/src/deferred-foreground-recovery-cli-adapter.js +1125 -0
- package/dist/src/deferred-foreground-recovery-cli-adapter.js.map +1 -0
- package/dist/src/deferred-foreground-recovery-service.d.ts +48 -0
- package/dist/src/deferred-foreground-recovery-service.js +91 -0
- package/dist/src/deferred-foreground-recovery-service.js.map +1 -0
- package/dist/src/deferred-foreground-transfer-policy.d.ts +2 -0
- package/dist/src/deferred-foreground-transfer-policy.js +10 -0
- package/dist/src/deferred-foreground-transfer-policy.js.map +1 -0
- package/dist/src/deferred-foreground-transfer.js +46 -105
- package/dist/src/deferred-foreground-transfer.js.map +1 -1
- package/dist/src/doctor-capabilities.d.ts +9 -0
- package/dist/src/doctor-capabilities.js +22 -0
- package/dist/src/doctor-capabilities.js.map +1 -1
- package/dist/src/durable-json-file.d.ts +22 -0
- package/dist/src/durable-json-file.js +127 -0
- package/dist/src/durable-json-file.js.map +1 -0
- package/dist/src/file-lock-cli-adapter.d.ts +43 -0
- package/dist/src/file-lock-cli-adapter.js +150 -0
- package/dist/src/file-lock-cli-adapter.js.map +1 -0
- package/dist/src/herdr-terminal-control-provider.js +1 -3
- package/dist/src/herdr-terminal-control-provider.js.map +1 -1
- package/dist/src/install-doctor-command-adapter.d.ts +17 -0
- package/dist/src/install-doctor-command-adapter.js +225 -0
- package/dist/src/install-doctor-command-adapter.js.map +1 -0
- package/dist/src/live-lifecycle-evidence.js +76 -46
- package/dist/src/live-lifecycle-evidence.js.map +1 -1
- package/dist/src/live-lifecycle-smoke.js +74 -50
- package/dist/src/live-lifecycle-smoke.js.map +1 -1
- package/dist/src/managed-session.d.ts +2 -0
- package/dist/src/managed-session.js +24 -0
- package/dist/src/managed-session.js.map +1 -1
- package/dist/src/managed-turn-recovery-service.d.ts +86 -0
- package/dist/src/managed-turn-recovery-service.js +145 -0
- package/dist/src/managed-turn-recovery-service.js.map +1 -0
- package/dist/src/mutation-transaction.d.ts +48 -0
- package/dist/src/mutation-transaction.js +73 -0
- package/dist/src/mutation-transaction.js.map +1 -0
- package/dist/src/native-thread-lifecycle-cli-adapter.d.ts +154 -0
- package/dist/src/native-thread-lifecycle-cli-adapter.js +786 -0
- package/dist/src/native-thread-lifecycle-cli-adapter.js.map +1 -0
- package/dist/src/native-thread-lifecycle-ledger-cli-adapter.d.ts +25 -0
- package/dist/src/native-thread-lifecycle-ledger-cli-adapter.js +50 -0
- package/dist/src/native-thread-lifecycle-ledger-cli-adapter.js.map +1 -0
- package/dist/src/native-thread-lifecycle-query-service.d.ts +75 -0
- package/dist/src/native-thread-lifecycle-query-service.js +297 -0
- package/dist/src/native-thread-lifecycle-query-service.js.map +1 -0
- package/dist/src/native-thread-lifecycle-recovery-adapter.d.ts +45 -0
- package/dist/src/native-thread-lifecycle-recovery-adapter.js +154 -0
- package/dist/src/native-thread-lifecycle-recovery-adapter.js.map +1 -0
- package/dist/src/native-thread-lifecycle-recovery-service.d.ts +211 -0
- package/dist/src/native-thread-lifecycle-recovery-service.js +1093 -0
- package/dist/src/native-thread-lifecycle-recovery-service.js.map +1 -0
- package/dist/src/native-thread-resume-snapshot-policy.d.ts +73 -0
- package/dist/src/native-thread-resume-snapshot-policy.js +218 -0
- package/dist/src/native-thread-resume-snapshot-policy.js.map +1 -0
- package/dist/src/native-thread-resume-snapshot.d.ts +3 -61
- package/dist/src/native-thread-resume-snapshot.js +2 -143
- package/dist/src/native-thread-resume-snapshot.js.map +1 -1
- package/dist/src/native-thread-transition-application.d.ts +147 -0
- package/dist/src/native-thread-transition-application.js +974 -0
- package/dist/src/native-thread-transition-application.js.map +1 -0
- package/dist/src/native-thread-transition-policy.d.ts +127 -0
- package/dist/src/native-thread-transition-policy.js +154 -0
- package/dist/src/native-thread-transition-policy.js.map +1 -0
- package/dist/src/native-thread-transition-resource-adapter.d.ts +12 -0
- package/dist/src/native-thread-transition-resource-adapter.js +44 -0
- package/dist/src/native-thread-transition-resource-adapter.js.map +1 -0
- package/dist/src/native-thread-transition-settlement-service.d.ts +94 -0
- package/dist/src/native-thread-transition-settlement-service.js +134 -0
- package/dist/src/native-thread-transition-settlement-service.js.map +1 -0
- package/dist/src/native-thread-transition-verification-adapter.d.ts +62 -0
- package/dist/src/native-thread-transition-verification-adapter.js +451 -0
- package/dist/src/native-thread-transition-verification-adapter.js.map +1 -0
- package/dist/src/openclaw-callback-transport.d.ts +69 -0
- package/dist/src/openclaw-callback-transport.js +583 -0
- package/dist/src/openclaw-callback-transport.js.map +1 -0
- package/dist/src/openclaw-plugin-callback-adapter.d.ts +1 -0
- package/dist/src/openclaw-plugin-callback-adapter.js +423 -0
- package/dist/src/openclaw-plugin-callback-adapter.js.map +1 -0
- package/dist/src/openclaw-plugin-command-adapter.d.ts +16 -0
- package/dist/src/openclaw-plugin-command-adapter.js +1868 -0
- package/dist/src/openclaw-plugin-command-adapter.js.map +1 -0
- package/dist/src/openclaw-plugin-helpers.d.ts +27 -4
- package/dist/src/openclaw-plugin-helpers.js +356 -81
- package/dist/src/openclaw-plugin-helpers.js.map +1 -1
- package/dist/src/openclaw-plugin-schemas.d.ts +358 -0
- package/dist/src/openclaw-plugin-schemas.js +366 -0
- package/dist/src/openclaw-plugin-schemas.js.map +1 -0
- package/dist/src/openclaw-plugin-supervisor.d.ts +6 -0
- package/dist/src/openclaw-plugin-supervisor.js +123 -0
- package/dist/src/openclaw-plugin-supervisor.js.map +1 -0
- package/dist/src/openclaw-plugin.js +7 -2212
- package/dist/src/openclaw-plugin.js.map +1 -1
- package/dist/src/openclaw-private-authority-offers.d.ts +22 -0
- package/dist/src/openclaw-private-authority-offers.js +177 -0
- package/dist/src/openclaw-private-authority-offers.js.map +1 -0
- package/dist/src/protocol.d.ts +5 -0
- package/dist/src/protocol.js +59 -3
- package/dist/src/protocol.js.map +1 -1
- package/dist/src/session-store.d.ts +1 -0
- package/dist/src/session-store.js +84 -106
- package/dist/src/session-store.js.map +1 -1
- package/dist/src/store.d.ts +1 -0
- package/dist/src/store.js +5 -2
- package/dist/src/store.js.map +1 -1
- package/dist/src/terminal-acceptance-application-service.d.ts +65 -0
- package/dist/src/terminal-acceptance-application-service.js +63 -0
- package/dist/src/terminal-acceptance-application-service.js.map +1 -0
- package/dist/src/terminal-acceptance-cli-adapter.d.ts +210 -0
- package/dist/src/terminal-acceptance-cli-adapter.js +957 -0
- package/dist/src/terminal-acceptance-cli-adapter.js.map +1 -0
- package/dist/src/terminal-action-projection.d.ts +309 -0
- package/dist/src/terminal-action-projection.js +376 -0
- package/dist/src/terminal-action-projection.js.map +1 -0
- package/dist/src/terminal-agent-bridge.d.ts +3 -0
- package/dist/src/terminal-agent-bridge.js +29 -8
- package/dist/src/terminal-agent-bridge.js.map +1 -1
- package/dist/src/terminal-authority-policy.d.ts +141 -0
- package/dist/src/terminal-authority-policy.js +367 -0
- package/dist/src/terminal-authority-policy.js.map +1 -0
- package/dist/src/terminal-binding-authority.d.ts +118 -0
- package/dist/src/terminal-binding-authority.js +245 -0
- package/dist/src/terminal-binding-authority.js.map +1 -0
- package/dist/src/terminal-binding-reconciliation-service.d.ts +75 -0
- package/dist/src/terminal-binding-reconciliation-service.js +73 -0
- package/dist/src/terminal-binding-reconciliation-service.js.map +1 -0
- package/dist/src/terminal-command-cli-adapter.d.ts +380 -0
- package/dist/src/terminal-command-cli-adapter.js +3288 -0
- package/dist/src/terminal-command-cli-adapter.js.map +1 -0
- package/dist/src/terminal-control-ref.d.ts +4 -0
- package/dist/src/terminal-control-ref.js +11 -8
- package/dist/src/terminal-control-ref.js.map +1 -1
- package/dist/src/terminal-delegate-cli-adapter.d.ts +41 -0
- package/dist/src/terminal-delegate-cli-adapter.js +242 -0
- package/dist/src/terminal-delegate-cli-adapter.js.map +1 -0
- package/dist/src/terminal-dispatch-abort.d.ts +22 -0
- package/dist/src/terminal-dispatch-abort.js +30 -0
- package/dist/src/terminal-dispatch-abort.js.map +1 -0
- package/dist/src/terminal-dispatch-application.d.ts +115 -0
- package/dist/src/terminal-dispatch-application.js +478 -0
- package/dist/src/terminal-dispatch-application.js.map +1 -0
- package/dist/src/terminal-dispatch-capability.d.ts +63 -0
- package/dist/src/terminal-dispatch-capability.js +133 -0
- package/dist/src/terminal-dispatch-capability.js.map +1 -0
- package/dist/src/terminal-dispatch-completion-cli-adapter.d.ts +22 -0
- package/dist/src/terminal-dispatch-completion-cli-adapter.js +96 -0
- package/dist/src/terminal-dispatch-completion-cli-adapter.js.map +1 -0
- package/dist/src/terminal-dispatch-composition.d.ts +79 -0
- package/dist/src/terminal-dispatch-composition.js +2 -0
- package/dist/src/terminal-dispatch-composition.js.map +1 -0
- package/dist/src/terminal-dispatch-execution.d.ts +290 -0
- package/dist/src/terminal-dispatch-execution.js +916 -0
- package/dist/src/terminal-dispatch-execution.js.map +1 -0
- package/dist/src/terminal-dispatch-ledger-codec.d.ts +110 -0
- package/dist/src/terminal-dispatch-ledger-codec.js +399 -0
- package/dist/src/terminal-dispatch-ledger-codec.js.map +1 -0
- package/dist/src/terminal-dispatch-policy.d.ts +93 -0
- package/dist/src/terminal-dispatch-policy.js +122 -0
- package/dist/src/terminal-dispatch-policy.js.map +1 -0
- package/dist/src/terminal-dispatch-presenter.d.ts +65 -0
- package/dist/src/terminal-dispatch-presenter.js +258 -0
- package/dist/src/terminal-dispatch-presenter.js.map +1 -0
- package/dist/src/terminal-dispatch-receipt.d.ts +79 -0
- package/dist/src/terminal-dispatch-receipt.js +314 -0
- package/dist/src/terminal-dispatch-receipt.js.map +1 -0
- package/dist/src/terminal-dispatch-recovery-cli-adapter.d.ts +132 -0
- package/dist/src/terminal-dispatch-recovery-cli-adapter.js +1330 -0
- package/dist/src/terminal-dispatch-recovery-cli-adapter.js.map +1 -0
- package/dist/src/terminal-dispatch-recovery-service.d.ts +271 -0
- package/dist/src/terminal-dispatch-recovery-service.js +374 -0
- package/dist/src/terminal-dispatch-recovery-service.js.map +1 -0
- package/dist/src/terminal-dispatch-repository-cli-adapter.d.ts +35 -0
- package/dist/src/terminal-dispatch-repository-cli-adapter.js +483 -0
- package/dist/src/terminal-dispatch-repository-cli-adapter.js.map +1 -0
- package/dist/src/terminal-handoff-application-service.d.ts +7 -0
- package/dist/src/terminal-handoff-application-service.js +18 -0
- package/dist/src/terminal-handoff-application-service.js.map +1 -0
- package/dist/src/terminal-handoff-cli-adapter.d.ts +229 -0
- package/dist/src/terminal-handoff-cli-adapter.js +1389 -0
- package/dist/src/terminal-handoff-cli-adapter.js.map +1 -0
- package/dist/src/terminal-handoff-facts.d.ts +12 -0
- package/dist/src/terminal-handoff-facts.js +16 -0
- package/dist/src/terminal-handoff-facts.js.map +1 -0
- package/dist/src/terminal-identity-authority-cli-adapter.d.ts +318 -0
- package/dist/src/terminal-identity-authority-cli-adapter.js +1072 -0
- package/dist/src/terminal-identity-authority-cli-adapter.js.map +1 -0
- package/dist/src/terminal-identity-authority-service.d.ts +48 -0
- package/dist/src/terminal-identity-authority-service.js +45 -0
- package/dist/src/terminal-identity-authority-service.js.map +1 -0
- package/dist/src/terminal-list-cli-adapter.d.ts +274 -0
- package/dist/src/terminal-list-cli-adapter.js +2444 -0
- package/dist/src/terminal-list-cli-adapter.js.map +1 -0
- package/dist/src/terminal-list-renderer.d.ts +34 -0
- package/dist/src/terminal-list-renderer.js +643 -0
- package/dist/src/terminal-list-renderer.js.map +1 -0
- package/dist/src/terminal-maintenance-cli-adapter.d.ts +102 -0
- package/dist/src/terminal-maintenance-cli-adapter.js +1059 -0
- package/dist/src/terminal-maintenance-cli-adapter.js.map +1 -0
- package/dist/src/terminal-monitor-application-service.d.ts +275 -0
- package/dist/src/terminal-monitor-application-service.js +982 -0
- package/dist/src/terminal-monitor-application-service.js.map +1 -0
- package/dist/src/terminal-monitor-cli-adapter.d.ts +130 -0
- package/dist/src/terminal-monitor-cli-adapter.js +442 -0
- package/dist/src/terminal-monitor-cli-adapter.js.map +1 -0
- package/dist/src/terminal-monitor-decision-policy.d.ts +98 -0
- package/dist/src/terminal-monitor-decision-policy.js +246 -0
- package/dist/src/terminal-monitor-decision-policy.js.map +1 -0
- package/dist/src/terminal-monitor-launch-plan.d.ts +45 -0
- package/dist/src/terminal-monitor-launch-plan.js +94 -0
- package/dist/src/terminal-monitor-launch-plan.js.map +1 -0
- package/dist/src/terminal-monitor-ownership-policy.d.ts +31 -0
- package/dist/src/terminal-monitor-ownership-policy.js +64 -0
- package/dist/src/terminal-monitor-ownership-policy.js.map +1 -0
- package/dist/src/terminal-monitor-poll-policy.d.ts +48 -0
- package/dist/src/terminal-monitor-poll-policy.js +67 -0
- package/dist/src/terminal-monitor-poll-policy.js.map +1 -0
- package/dist/src/terminal-monitor-reconciliation-eligibility.d.ts +53 -0
- package/dist/src/terminal-monitor-reconciliation-eligibility.js +114 -0
- package/dist/src/terminal-monitor-reconciliation-eligibility.js.map +1 -0
- package/dist/src/terminal-monitor-state-cli-adapter.d.ts +106 -0
- package/dist/src/terminal-monitor-state-cli-adapter.js +1492 -0
- package/dist/src/terminal-monitor-state-cli-adapter.js.map +1 -0
- package/dist/src/terminal-monitor-state-reconciliation-service.d.ts +87 -0
- package/dist/src/terminal-monitor-state-reconciliation-service.js +106 -0
- package/dist/src/terminal-monitor-state-reconciliation-service.js.map +1 -0
- package/dist/src/terminal-monitor-supervision-cli-adapter.d.ts +122 -0
- package/dist/src/terminal-monitor-supervision-cli-adapter.js +685 -0
- package/dist/src/terminal-monitor-supervision-cli-adapter.js.map +1 -0
- package/dist/src/terminal-process-facts.d.ts +2 -0
- package/dist/src/terminal-process-facts.js +19 -0
- package/dist/src/terminal-process-facts.js.map +1 -0
- package/dist/src/terminal-process-source.d.ts +6 -4
- package/dist/src/terminal-process-source.js +25 -20
- package/dist/src/terminal-process-source.js.map +1 -1
- package/dist/src/terminal-runtime-cli-adapter.d.ts +80 -0
- package/dist/src/terminal-runtime-cli-adapter.js +488 -0
- package/dist/src/terminal-runtime-cli-adapter.js.map +1 -0
- package/dist/src/terminal-scoped-approval-authority.d.ts +62 -0
- package/dist/src/terminal-scoped-approval-authority.js +281 -0
- package/dist/src/terminal-scoped-approval-authority.js.map +1 -0
- package/dist/src/terminal-selector-projection-service.d.ts +26 -0
- package/dist/src/terminal-selector-projection-service.js +81 -0
- package/dist/src/terminal-selector-projection-service.js.map +1 -0
- package/dist/src/terminal-status-cli-adapter.d.ts +126 -0
- package/dist/src/terminal-status-cli-adapter.js +577 -0
- package/dist/src/terminal-status-cli-adapter.js.map +1 -0
- package/dist/src/terminal-status-facts.d.ts +56 -0
- package/dist/src/terminal-status-facts.js +199 -0
- package/dist/src/terminal-status-facts.js.map +1 -0
- package/dist/src/terminal-submission-acceptance.d.ts +62 -145
- package/dist/src/terminal-submission-acceptance.js +555 -222
- package/dist/src/terminal-submission-acceptance.js.map +1 -1
- package/dist/src/terminal-submission-facts.d.ts +123 -0
- package/dist/src/terminal-submission-facts.js +205 -0
- package/dist/src/terminal-submission-facts.js.map +1 -0
- package/dist/src/terminal-turn-binding-authority-cli-adapter.d.ts +14 -0
- package/dist/src/terminal-turn-binding-authority-cli-adapter.js +90 -0
- package/dist/src/terminal-turn-binding-authority-cli-adapter.js.map +1 -0
- package/dist/src/terminal-watch-callback-cli-adapter.d.ts +20 -0
- package/dist/src/terminal-watch-callback-cli-adapter.js +55 -0
- package/dist/src/terminal-watch-callback-cli-adapter.js.map +1 -0
- package/dist/src/terminal-watch-cli-adapter.d.ts +64 -0
- package/dist/src/terminal-watch-cli-adapter.js +508 -0
- package/dist/src/terminal-watch-cli-adapter.js.map +1 -0
- package/dist/src/terminal-watch-service.d.ts +97 -0
- package/dist/src/terminal-watch-service.js +714 -0
- package/dist/src/terminal-watch-service.js.map +1 -0
- package/dist/src/terminal-watch-store.d.ts +149 -0
- package/dist/src/terminal-watch-store.js +861 -0
- package/dist/src/terminal-watch-store.js.map +1 -0
- package/dist/src/value-guards.d.ts +4 -0
- package/dist/src/value-guards.js +12 -0
- package/dist/src/value-guards.js.map +1 -0
- package/dist/src/verified-dead-agent-policy.d.ts +192 -0
- package/dist/src/verified-dead-agent-policy.js +262 -0
- package/dist/src/verified-dead-agent-policy.js.map +1 -0
- package/docs/quickstart-herdr.md +8 -0
- package/docs/quickstart-tmux.md +33 -6
- package/openclaw.plugin.json +11 -3
- package/package.json +3 -1
- package/templates/openclaw-skills/agent-knock-knock/SKILL.md +58 -40
|
@@ -0,0 +1,916 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { executorForConversation, isTerminalDispatchOwnerReleasedStatus, sessionIdForConversation, turnIdForConversation } from "./protocol.js";
|
|
3
|
+
import { parseTerminalConversationId } from "./terminal-agent-adapter.js";
|
|
4
|
+
import { decideTerminalBindingMatch, isCompleteNativeRollout, terminalNativeIdentityFence as codexIdentityFence, terminalNativeIdentityMatchesFence as nativeIdentityMatchesCodexPreMaterialization, terminalObservationFromResolvedIdentity } from "./terminal-binding-authority.js";
|
|
5
|
+
import { isCodexStatusCardEvidence, nativeAgentIdentityMatchesTurn, processIncarnationRelationship } from "./terminal-authority-policy.js";
|
|
6
|
+
import * as dispatch from "./terminal-dispatch-policy.js";
|
|
7
|
+
import { terminalAcceptanceEvidenceExpectation, terminalSubmissionReplayReceipt } from "./terminal-dispatch-receipt.js";
|
|
8
|
+
import { validateCodexRolloutAcceptanceAnchor } from "./terminal-submission-facts.js";
|
|
9
|
+
import { isRecord, nonBlankString } from "./value-guards.js";
|
|
10
|
+
export { managedSessionRevision, nativeThreadTransitionRevision } from "./managed-session.js";
|
|
11
|
+
export { nativeAgentIdentityMatchesTurn };
|
|
12
|
+
export { codexIdentityFence, isCompleteNativeRollout, nativeIdentityMatchesCodexPreMaterialization };
|
|
13
|
+
export function resolvedTerminalProcessIncarnation(input) {
|
|
14
|
+
if (input.terminal.agent !== "codex" ||
|
|
15
|
+
(input.identity?.processUuid && input.identity.processBirth)) {
|
|
16
|
+
return {
|
|
17
|
+
processUuid: input.identity?.processUuid,
|
|
18
|
+
processBirth: input.identity?.processBirth
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const incarnation = input.codexProcessIncarnation(input.terminal.pid);
|
|
23
|
+
return {
|
|
24
|
+
processUuid: input.identity?.processUuid ?? incarnation.processUuid,
|
|
25
|
+
processBirth: input.identity?.processBirth ?? incarnation.processBirth
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return {
|
|
30
|
+
processUuid: input.identity?.processUuid,
|
|
31
|
+
processBirth: input.identity?.processBirth
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export function managedSessionOwnerIsInactive(input) {
|
|
36
|
+
const binding = input.session.binding;
|
|
37
|
+
if (!binding) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
if (binding.native_process.pid !== input.terminal.pid) {
|
|
41
|
+
if (!input.isProcessAlive(binding.native_process.pid)) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
if (input.session.agent !== "codex") {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const owner = input.codexProcessIncarnation(binding.native_process.pid);
|
|
49
|
+
return processIncarnationRelationship({
|
|
50
|
+
binding,
|
|
51
|
+
livePid: binding.native_process.pid,
|
|
52
|
+
liveProcessUuid: owner.processUuid,
|
|
53
|
+
liveProcessBirth: owner.processBirth
|
|
54
|
+
}) === "different";
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const live = resolvedTerminalProcessIncarnation({
|
|
61
|
+
terminal: input.terminal,
|
|
62
|
+
identity: input.identity,
|
|
63
|
+
codexProcessIncarnation: input.codexProcessIncarnation
|
|
64
|
+
});
|
|
65
|
+
return processIncarnationRelationship({
|
|
66
|
+
binding,
|
|
67
|
+
livePid: input.terminal.pid,
|
|
68
|
+
liveProcessUuid: live.processUuid,
|
|
69
|
+
liveProcessBirth: live.processBirth
|
|
70
|
+
}) === "different";
|
|
71
|
+
}
|
|
72
|
+
export function managedBindingMatchesLiveTerminal(input) {
|
|
73
|
+
if (!input.claimMatches) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
const observation = terminalObservationFromResolvedIdentity({
|
|
77
|
+
agent: input.terminal.agent,
|
|
78
|
+
pid: input.terminal.pid,
|
|
79
|
+
identity: input.identity,
|
|
80
|
+
processIncarnation: input.processIncarnation
|
|
81
|
+
});
|
|
82
|
+
const evidence = { terminalAliasMatches: true, workspaceMatches: true };
|
|
83
|
+
let decision = decideTerminalBindingMatch(input.session, observation, evidence);
|
|
84
|
+
if (decision.state === "not_exact" &&
|
|
85
|
+
decision.reason === "native_identity_mismatch" &&
|
|
86
|
+
input.session.agent === "codex" && input.identity) {
|
|
87
|
+
decision = decideTerminalBindingMatch(input.session, observation, {
|
|
88
|
+
...evidence,
|
|
89
|
+
codexLingeringBeforeMatches: input.codexLingeringBeforeMatches()
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
return decision.state === "exact";
|
|
93
|
+
}
|
|
94
|
+
export function codexKnownBeforeIdentityForTransition(input) {
|
|
95
|
+
const { session, transition } = input;
|
|
96
|
+
const binding = session.binding;
|
|
97
|
+
const after = transition?.after_binding;
|
|
98
|
+
if (session.agent !== "codex" || session.status !== "bound" ||
|
|
99
|
+
!binding?.native_thread_id || !binding.native_process.process_uuid ||
|
|
100
|
+
!binding.native_process.process_birth || !session.last_transition_id ||
|
|
101
|
+
!transition || transition.status !== "committed" ||
|
|
102
|
+
(input.requireNewThread && ![
|
|
103
|
+
"new_thread",
|
|
104
|
+
"adopt_external_thread"
|
|
105
|
+
].includes(transition.operation)) ||
|
|
106
|
+
transition.target_session_id !== session.session_id || !after ||
|
|
107
|
+
after.binding_id !== binding.binding_id ||
|
|
108
|
+
after.generation !== binding.generation ||
|
|
109
|
+
after.native_thread_id !== binding.native_thread_id ||
|
|
110
|
+
!transition.before_native_thread_id ||
|
|
111
|
+
transition.before_native_thread_id === binding.native_thread_id ||
|
|
112
|
+
!transition.before_process_uuid || !transition.before_process_birth ||
|
|
113
|
+
!isCompleteNativeRollout(transition.before_process_rollout) ||
|
|
114
|
+
transition.before_process_uuid !== binding.native_process.process_uuid ||
|
|
115
|
+
transition.before_process_birth !== binding.native_process.process_birth) {
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
sessionId: transition.before_native_thread_id,
|
|
120
|
+
processUuid: transition.before_process_uuid,
|
|
121
|
+
processBirth: transition.before_process_birth,
|
|
122
|
+
rollout: transition.before_process_rollout,
|
|
123
|
+
evidence: transition.operation === "new_thread"
|
|
124
|
+
? "committed_new_thread_before_identity"
|
|
125
|
+
: "committed_resume_thread_before_identity"
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
export function codexLingeringIdentityMatches(input) {
|
|
129
|
+
const { session, identity, transition } = input;
|
|
130
|
+
const binding = session.binding;
|
|
131
|
+
const after = transition?.after_binding;
|
|
132
|
+
if (session.agent !== "codex" || session.status !== "bound" ||
|
|
133
|
+
!binding?.native_thread_id || binding.native_process.rollout ||
|
|
134
|
+
!isCodexStatusCardEvidence(binding.native_process.evidence) || !identity ||
|
|
135
|
+
!codexKnownBeforeIdentityForTransition({
|
|
136
|
+
session,
|
|
137
|
+
transition,
|
|
138
|
+
requireNewThread: true
|
|
139
|
+
}) ||
|
|
140
|
+
!transition || transition.status !== "committed" ||
|
|
141
|
+
!["new_thread", "adopt_external_thread"].includes(transition.operation) ||
|
|
142
|
+
transition.target_session_id !== session.session_id || !after ||
|
|
143
|
+
after.binding_id !== binding.binding_id ||
|
|
144
|
+
after.generation !== binding.generation ||
|
|
145
|
+
after.native_thread_id !== binding.native_thread_id ||
|
|
146
|
+
after.native_process.rollout) {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
return [input.companions.primary, ...input.companions.additional]
|
|
150
|
+
.some((candidate) => nativeIdentityMatchesCodexPreMaterialization(identity, candidate));
|
|
151
|
+
}
|
|
152
|
+
export function logicalManagedSessionIdentity(input) {
|
|
153
|
+
const binding = input.session.binding;
|
|
154
|
+
if (!binding?.native_thread_id) {
|
|
155
|
+
return input.observedIdentity;
|
|
156
|
+
}
|
|
157
|
+
const statusCardOnly = input.session.agent === "codex" &&
|
|
158
|
+
isCodexStatusCardEvidence(binding.native_process.evidence) &&
|
|
159
|
+
Boolean(binding.native_process.process_uuid) &&
|
|
160
|
+
Boolean(binding.native_process.process_birth) &&
|
|
161
|
+
(input.observedIdentity === undefined || input.lingeringBeforeMatches);
|
|
162
|
+
return statusCardOnly
|
|
163
|
+
? {
|
|
164
|
+
sessionId: binding.native_thread_id,
|
|
165
|
+
processUuid: binding.native_process.process_uuid,
|
|
166
|
+
processBirth: binding.native_process.process_birth,
|
|
167
|
+
rollout: binding.native_process.rollout,
|
|
168
|
+
evidence: binding.native_process.evidence
|
|
169
|
+
}
|
|
170
|
+
: input.observedIdentity;
|
|
171
|
+
}
|
|
172
|
+
export function terminalRuntimeForLiveIdentity(input) {
|
|
173
|
+
const { terminal, identity, physicalOnly = false } = input;
|
|
174
|
+
const expectedEmpty = input.expectedEmptyNativeSession ?? false;
|
|
175
|
+
const incarnation = !physicalOnly && expectedEmpty &&
|
|
176
|
+
terminal.agent === "codex"
|
|
177
|
+
? input.codexProcessIncarnation(terminal.pid)
|
|
178
|
+
: undefined;
|
|
179
|
+
return {
|
|
180
|
+
pid: terminal.pid,
|
|
181
|
+
nativeSessionId: physicalOnly ? undefined : identity?.sessionId,
|
|
182
|
+
nativeProcessUuid: physicalOnly
|
|
183
|
+
? undefined
|
|
184
|
+
: identity?.processUuid ?? incarnation?.processUuid,
|
|
185
|
+
nativeProcessBirth: physicalOnly
|
|
186
|
+
? undefined
|
|
187
|
+
: identity?.processBirth ?? incarnation?.processBirth,
|
|
188
|
+
nativeRollout: physicalOnly ? undefined : identity?.rollout,
|
|
189
|
+
requireNativeProcessUuid: !physicalOnly && terminal.agent === "claude" && !expectedEmpty,
|
|
190
|
+
requireNativeRolloutIdentity: !physicalOnly && terminal.agent === "codex" && !expectedEmpty,
|
|
191
|
+
expectedEmptyNativeSession: physicalOnly ? false : expectedEmpty,
|
|
192
|
+
cwd: terminal.terminalControl.currentPath,
|
|
193
|
+
terminalTarget: terminal.terminalControl.target
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
export function terminalRuntimeIdentityBase(conversation, terminalControl) {
|
|
197
|
+
const takeover = isRecord(conversation.native_session_takeover)
|
|
198
|
+
? conversation.native_session_takeover
|
|
199
|
+
: undefined;
|
|
200
|
+
const nativeSessionId = nonBlankString(takeover?.native_session_id);
|
|
201
|
+
const terminalIdentity = parseTerminalConversationId(nativeSessionId);
|
|
202
|
+
const explicitSessionId = nonBlankString(takeover?.terminal_agent_session_id) ??
|
|
203
|
+
(terminalIdentity ? undefined : nativeSessionId);
|
|
204
|
+
const rollout = isRecord(takeover?.terminal_agent_rollout)
|
|
205
|
+
? takeover.terminal_agent_rollout
|
|
206
|
+
: undefined;
|
|
207
|
+
const strict = Number(takeover?.terminal_agent_identity_protocol) === 1;
|
|
208
|
+
const expectedSessionId = nonBlankString(takeover?.terminal_agent_expected_session_id);
|
|
209
|
+
const agent = executorForConversation(conversation).kind;
|
|
210
|
+
return {
|
|
211
|
+
pid: Number.isInteger(Number(takeover?.terminal_agent_pid))
|
|
212
|
+
? Number(takeover?.terminal_agent_pid)
|
|
213
|
+
: terminalIdentity?.pid,
|
|
214
|
+
sessionId: explicitSessionId,
|
|
215
|
+
nativeSessionId: nonBlankString(takeover?.terminal_agent_session_id),
|
|
216
|
+
nativeProcessUuid: nonBlankString(takeover?.terminal_agent_process_uuid),
|
|
217
|
+
nativeProcessBirth: nonBlankString(takeover?.terminal_agent_process_birth),
|
|
218
|
+
requireNativeProcessUuid: strict && agent === "claude",
|
|
219
|
+
requireNativeRolloutIdentity: strict && agent === "codex",
|
|
220
|
+
...(rollout
|
|
221
|
+
? {
|
|
222
|
+
nativeRollout: {
|
|
223
|
+
fd: String(rollout.fd ?? ""),
|
|
224
|
+
device: String(rollout.device ?? ""),
|
|
225
|
+
inode: String(rollout.inode ?? ""),
|
|
226
|
+
path: String(rollout.path ?? "")
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
: {}),
|
|
230
|
+
expectedEmptyNativeSession: strict && !nonBlankString(takeover?.terminal_agent_session_id),
|
|
231
|
+
expectedNativeSessionId: strict && !nonBlankString(takeover?.terminal_agent_session_id)
|
|
232
|
+
? expectedSessionId
|
|
233
|
+
: undefined,
|
|
234
|
+
cwd: nonBlankString(takeover?.source_cwd) ?? terminalControl.currentPath,
|
|
235
|
+
conversationId: conversation.conversation_id,
|
|
236
|
+
messageId: nonBlankString(takeover?.terminal_bridge_message_id),
|
|
237
|
+
terminalTarget: terminalControl.target
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
export function migratedTerminalBindingMatches(input) {
|
|
241
|
+
const binding = input.session.binding;
|
|
242
|
+
if (input.session.status !== "bound" || !binding ||
|
|
243
|
+
!binding.native_thread_id || input.session.agent !== input.agent ||
|
|
244
|
+
!input.workspaceMatches || !input.terminalId ||
|
|
245
|
+
!input.terminalAliasMatches || !input.terminalIncarnationMatches ||
|
|
246
|
+
!Number.isSafeInteger(input.pid) ||
|
|
247
|
+
binding.native_process.pid !== input.pid ||
|
|
248
|
+
!input.nativeThreadId ||
|
|
249
|
+
binding.native_thread_id !== input.nativeThreadId) {
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
const bindingProcess = binding.native_process;
|
|
253
|
+
const uuidMatches = optionalValueMatches(input.processUuid, bindingProcess.process_uuid);
|
|
254
|
+
const birthMatches = optionalValueMatches(input.processBirth, bindingProcess.process_birth);
|
|
255
|
+
const rolloutMatches = input.rollout === undefined &&
|
|
256
|
+
bindingProcess.rollout === undefined ||
|
|
257
|
+
Boolean(input.rollout && bindingProcess.rollout &&
|
|
258
|
+
sameRollout(input.rollout, bindingProcess.rollout));
|
|
259
|
+
if (!uuidMatches || !birthMatches || !rolloutMatches) {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
return input.agent === "claude"
|
|
263
|
+
? Boolean(input.processUuid && bindingProcess.process_uuid)
|
|
264
|
+
: Boolean(input.processBirth && bindingProcess.process_birth &&
|
|
265
|
+
isCompleteNativeRollout(input.rollout) && bindingProcess.rollout);
|
|
266
|
+
}
|
|
267
|
+
export function selectBoundManagedSessionForTerminal(input) {
|
|
268
|
+
const unresolved = input.sessions.filter((session) => ["transitioning", "quarantined"].includes(session.status) &&
|
|
269
|
+
session.binding && session.agent === input.agent &&
|
|
270
|
+
input.aliasMatches(session));
|
|
271
|
+
if (unresolved[0]) {
|
|
272
|
+
const session = unresolved[0];
|
|
273
|
+
throw new Error("terminal " + input.terminalTarget + " is still claimed by " +
|
|
274
|
+
session.status + " managed Session " + session.session_id +
|
|
275
|
+
(session.last_transition_id
|
|
276
|
+
? " (" + session.last_transition_id + ")"
|
|
277
|
+
: "") +
|
|
278
|
+
"; complete lifecycle recovery before attaching or sending");
|
|
279
|
+
}
|
|
280
|
+
const exact = input.sessions.filter(input.exactMatches);
|
|
281
|
+
if (exact.length > 1) {
|
|
282
|
+
throw new Error("terminal " + input.terminalTarget +
|
|
283
|
+
" matches multiple managed Session bindings");
|
|
284
|
+
}
|
|
285
|
+
const conflicting = input.sessions.some((session) => session.status === "bound" && session.binding &&
|
|
286
|
+
session.agent === input.agent && input.sameIncarnation(session) &&
|
|
287
|
+
session.binding.native_process.pid === input.pid &&
|
|
288
|
+
!input.ownerIsInactive(session) && !exact.includes(session));
|
|
289
|
+
if (conflicting) {
|
|
290
|
+
throw new Error("terminal " + input.terminalTarget +
|
|
291
|
+
" changed native thread outside AKK; its managed binding must be " +
|
|
292
|
+
"reconciled explicitly before control");
|
|
293
|
+
}
|
|
294
|
+
return exact[0];
|
|
295
|
+
}
|
|
296
|
+
export function selectSoleBoundManagedSessionClaim(input) {
|
|
297
|
+
const claims = input.sessions.filter((session) => input.claims(session) && !input.ownerIsInactive(session));
|
|
298
|
+
if (claims.length > 1) {
|
|
299
|
+
throw new Error("terminal " + input.terminalTarget +
|
|
300
|
+
" has multiple bound managed Session claims");
|
|
301
|
+
}
|
|
302
|
+
return claims[0];
|
|
303
|
+
}
|
|
304
|
+
export function managedTurnMatchesTerminal(input) {
|
|
305
|
+
const takeover = isRecord(input.conversation.native_session_takeover)
|
|
306
|
+
? input.conversation.native_session_takeover
|
|
307
|
+
: undefined;
|
|
308
|
+
const storedTerminal = parseTerminalConversationId(nonBlankString(takeover?.native_session_id));
|
|
309
|
+
const currentTerminal = parseTerminalConversationId(input.terminal.conversationId);
|
|
310
|
+
return Boolean(input.storedControlExists && storedTerminal && currentTerminal &&
|
|
311
|
+
executorForConversation(input.conversation).kind === input.terminal.agent &&
|
|
312
|
+
storedTerminal.agent === currentTerminal.agent &&
|
|
313
|
+
storedTerminal.pid === currentTerminal.pid &&
|
|
314
|
+
Number(takeover?.terminal_agent_pid) === input.terminal.pid &&
|
|
315
|
+
nativeAgentIdentityMatchesTurn(input.conversation, input.currentIdentity) &&
|
|
316
|
+
input.terminalIncarnationMatches && input.workspaceMatches);
|
|
317
|
+
}
|
|
318
|
+
export function assertManagedSessionCanStartTurnPolicy(turns, isBlocking) {
|
|
319
|
+
const owner = turns.find(isBlocking);
|
|
320
|
+
if (!owner) {
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
throw new Error("session " + sessionIdForConversation(owner) +
|
|
324
|
+
" already has active turn " + turnIdForConversation(owner) +
|
|
325
|
+
" (" + owner.status + "); wait for its callback, respond to it if it is " +
|
|
326
|
+
"waiting for OpenClaw, cancel it, or close it before sending another turn");
|
|
327
|
+
}
|
|
328
|
+
export function terminalSubmissionPayload(payload) {
|
|
329
|
+
const firstLine = payload.split(/\r\n?|\n/u)
|
|
330
|
+
.find((line) => line.trim().length > 0)?.trimStart();
|
|
331
|
+
const reserved = /^\/([a-z][a-z0-9_-]*)(?=\s|$)/iu.exec(firstLine ?? "");
|
|
332
|
+
if (reserved) {
|
|
333
|
+
throw new Error("ordinary send/respond cannot invoke native slash command /" +
|
|
334
|
+
reserved[1].toLowerCase() +
|
|
335
|
+
"; use an advertised dedicated native action when one exists, or enter " +
|
|
336
|
+
"the unsupported native command manually in the terminal UI");
|
|
337
|
+
}
|
|
338
|
+
return payload.trimEnd();
|
|
339
|
+
}
|
|
340
|
+
export class TerminalDispatchExecutionService {
|
|
341
|
+
#syntheticAcceptanceOutcome;
|
|
342
|
+
#ports;
|
|
343
|
+
constructor(syntheticAcceptanceOutcome, ports) {
|
|
344
|
+
this.#syntheticAcceptanceOutcome = syntheticAcceptanceOutcome;
|
|
345
|
+
this.#ports = ports;
|
|
346
|
+
}
|
|
347
|
+
preflightRequiresOwner(ledger, lifecycle) {
|
|
348
|
+
return dispatch.terminalDispatchPreflightRequiresOwner({
|
|
349
|
+
status: nonBlankString(ledger?.status),
|
|
350
|
+
lifecycle
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
evaluatePreflight(input) {
|
|
354
|
+
const ledger = input.ledger;
|
|
355
|
+
const owner = input.owner;
|
|
356
|
+
const ownerReleased = Boolean(owner && isTerminalDispatchOwnerReleasedStatus(owner.status));
|
|
357
|
+
const continuingSameTurn = Boolean(owner && input.continuingTurnResponse &&
|
|
358
|
+
sessionIdForConversation(owner) ===
|
|
359
|
+
sessionIdForConversation(input.conversation) &&
|
|
360
|
+
turnIdForConversation(owner) ===
|
|
361
|
+
turnIdForConversation(input.conversation) &&
|
|
362
|
+
input.statePathMatches);
|
|
363
|
+
const exactReplay = Boolean(owner && !ownerReleased && !continuingSameTurn &&
|
|
364
|
+
nonBlankString(ledger?.request_hash) === input.requestHash &&
|
|
365
|
+
nonBlankString(ledger?.conversation_id) ===
|
|
366
|
+
input.conversation.conversation_id &&
|
|
367
|
+
nonBlankString(ledger?.message_id) === input.messageId &&
|
|
368
|
+
input.statePathMatches);
|
|
369
|
+
const decision = dispatch.decideTerminalDispatchPreflight({
|
|
370
|
+
ledger: {
|
|
371
|
+
status: nonBlankString(ledger?.status),
|
|
372
|
+
lifecycle: input.ledgerLifecycle,
|
|
373
|
+
transitionId: nonBlankString(ledger?.transition_id),
|
|
374
|
+
ownerConversationId: nonBlankString(ledger?.conversation_id)
|
|
375
|
+
},
|
|
376
|
+
owner: owner
|
|
377
|
+
? {
|
|
378
|
+
conversationId: owner.conversation_id,
|
|
379
|
+
status: owner.status,
|
|
380
|
+
released: ownerReleased,
|
|
381
|
+
continuingSameTurn,
|
|
382
|
+
exactReplay
|
|
383
|
+
}
|
|
384
|
+
: undefined
|
|
385
|
+
});
|
|
386
|
+
if (decision.action === "reject") {
|
|
387
|
+
throw terminalDispatchPreflightError(decision, input.terminalTarget);
|
|
388
|
+
}
|
|
389
|
+
if (decision.action !== "replay") {
|
|
390
|
+
return { action: "proceed" };
|
|
391
|
+
}
|
|
392
|
+
const replayOwner = owner;
|
|
393
|
+
const receipt = terminalSubmissionReplayReceipt({
|
|
394
|
+
proofLevel: decision.proofLevel,
|
|
395
|
+
evidence: ledger.acceptance_evidence,
|
|
396
|
+
expected: terminalAcceptanceEvidenceExpectation(replayOwner, input.requestText)
|
|
397
|
+
});
|
|
398
|
+
const replay = dispatch.decideTerminalDispatchReplayAcceptance({
|
|
399
|
+
delivered: receipt.delivered,
|
|
400
|
+
submissionOutcome: receipt.submission_outcome
|
|
401
|
+
});
|
|
402
|
+
return {
|
|
403
|
+
action: "replay",
|
|
404
|
+
owner: replayOwner,
|
|
405
|
+
receipt,
|
|
406
|
+
accepted: replay.accepted,
|
|
407
|
+
acceptanceInvalid: replay.invalid,
|
|
408
|
+
receiptConversationId: nonBlankString(ledger?.conversation_id) ??
|
|
409
|
+
replayOwner.conversation_id,
|
|
410
|
+
receiptMessageId: nonBlankString(ledger?.message_id) ?? input.messageId,
|
|
411
|
+
callbackExpected: !replay.invalid && Boolean(replayOwner.gateway_method ?? ledger?.callback_expected)
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
transportLifecycle(input) {
|
|
415
|
+
const selected = input.observedHandoff ??
|
|
416
|
+
input.verifiedEmptyHandoff ??
|
|
417
|
+
input.deferredBinding;
|
|
418
|
+
const verify = (requireEmptyComposer) => selected.verify(requireEmptyComposer);
|
|
419
|
+
return {
|
|
420
|
+
requireExactComposerBeforeEnter: selected !== undefined,
|
|
421
|
+
...(selected
|
|
422
|
+
? {
|
|
423
|
+
beforeText: async () => {
|
|
424
|
+
await verify(true);
|
|
425
|
+
if (input.deferredBinding === selected) {
|
|
426
|
+
input.deferredBinding.begin(this.#ports.clock.now().toISOString());
|
|
427
|
+
}
|
|
428
|
+
},
|
|
429
|
+
beforeEnter: async () => {
|
|
430
|
+
await verify(false);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
: {}),
|
|
434
|
+
onTransportStage: async ({ stage }) => {
|
|
435
|
+
const at = this.#ports.clock.now().toISOString();
|
|
436
|
+
await input.recordStage(stage, at, async () => {
|
|
437
|
+
input.deferredBinding?.advance(stage, at);
|
|
438
|
+
if (stage === "text_injected") {
|
|
439
|
+
await input.observedHandoff?.verify(false);
|
|
440
|
+
await input.verifiedEmptyHandoff?.verify(false);
|
|
441
|
+
await input.deferredBinding?.verify(false);
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
captureCodexAcceptanceAnchor(input) {
|
|
448
|
+
if (this.#syntheticEnabled()) {
|
|
449
|
+
return undefined;
|
|
450
|
+
}
|
|
451
|
+
if (input.candidateSetAnchor) {
|
|
452
|
+
return input.candidateSetAnchor;
|
|
453
|
+
}
|
|
454
|
+
const threadId = input.needsPostSendNativeBinding
|
|
455
|
+
? input.expectedNativeThreadId
|
|
456
|
+
: input.currentIdentity?.sessionId;
|
|
457
|
+
const processUuid = input.currentIdentity?.processUuid ??
|
|
458
|
+
input.allowedPreMaterializationIdentity?.processUuid ??
|
|
459
|
+
input.boundProcessUuid;
|
|
460
|
+
const processBirth = input.currentIdentity?.processBirth ??
|
|
461
|
+
input.allowedPreMaterializationIdentity?.processBirth ??
|
|
462
|
+
input.boundProcessBirth;
|
|
463
|
+
if (!processUuid || !processBirth) {
|
|
464
|
+
throw new Error("Codex native acceptance anchor requires an exact process incarnation");
|
|
465
|
+
}
|
|
466
|
+
if (!threadId && !input.needsPostSendNativeBinding) {
|
|
467
|
+
throw new Error("Codex native acceptance anchor requires an exact thread");
|
|
468
|
+
}
|
|
469
|
+
const now = this.#ports.clock.now();
|
|
470
|
+
if (!input.needsPostSendNativeBinding && input.currentIdentity?.rollout) {
|
|
471
|
+
return this.#ports.acceptance.captureCodex({
|
|
472
|
+
nativeThreadId: threadId,
|
|
473
|
+
processUuid,
|
|
474
|
+
processBirth,
|
|
475
|
+
now,
|
|
476
|
+
mode: "existing",
|
|
477
|
+
rollout: input.currentIdentity.rollout
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
const common = {
|
|
481
|
+
processUuid,
|
|
482
|
+
processBirth,
|
|
483
|
+
now,
|
|
484
|
+
mode: "pre_materialization",
|
|
485
|
+
expectedEmptyNativeSession: true
|
|
486
|
+
};
|
|
487
|
+
return this.#ports.acceptance.captureCodex(threadId ? { ...common, nativeThreadId: threadId } : common);
|
|
488
|
+
}
|
|
489
|
+
async resolveCurrentNativeIdentity(request) {
|
|
490
|
+
if (request.agent === "codex") {
|
|
491
|
+
const { agent: _agent, ...resolution } = request;
|
|
492
|
+
return this.#ports.native.resolveCodex(resolution);
|
|
493
|
+
}
|
|
494
|
+
return resolveClaudeIdentity(request.pid, this.#ports.native.claudeRows());
|
|
495
|
+
}
|
|
496
|
+
async observeCurrentNativeIdentity(request) {
|
|
497
|
+
try {
|
|
498
|
+
const identity = await this.resolveCurrentNativeIdentity(request);
|
|
499
|
+
return identity
|
|
500
|
+
? { status: "resolved", identity }
|
|
501
|
+
: {
|
|
502
|
+
status: "verified_absent",
|
|
503
|
+
evidence: "native_identity_resolver_verified_absent"
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
catch (error) {
|
|
507
|
+
return { status: "unavailable", reason: errorText(error) };
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
inspectCodexOpenRootInventory(pid, cwd) {
|
|
511
|
+
return this.#ports.native.inspectCodexOpenRoots(pid, cwd);
|
|
512
|
+
}
|
|
513
|
+
async detectAcceptance(request) {
|
|
514
|
+
const takeover = isRecord(request.conversation.native_session_takeover)
|
|
515
|
+
? request.conversation.native_session_takeover
|
|
516
|
+
: undefined;
|
|
517
|
+
const requestHash = nonBlankString(takeover?.terminal_bridge_request_hash);
|
|
518
|
+
if (!requestHash) {
|
|
519
|
+
throw new Error("terminal acceptance request hash is unavailable");
|
|
520
|
+
}
|
|
521
|
+
this.#ports.authority.assertTurnCurrent(request.conversation, "monitor");
|
|
522
|
+
const synthetic = this.#syntheticEvidence(request.executor, request.conversation, requestHash);
|
|
523
|
+
if (synthetic || this.#syntheticEnabled()) {
|
|
524
|
+
return synthetic;
|
|
525
|
+
}
|
|
526
|
+
if (request.executor === "claude") {
|
|
527
|
+
return this.#ports.acceptance.detectClaude(request.conversation, request.terminalControl);
|
|
528
|
+
}
|
|
529
|
+
const anchor = takeover?.codex_rollout_acceptance_anchor;
|
|
530
|
+
if (!isRecord(anchor)) {
|
|
531
|
+
throw new Error("Codex rollout acceptance anchor is unavailable");
|
|
532
|
+
}
|
|
533
|
+
const validated = validateCodexRolloutAcceptanceAnchor(anchor);
|
|
534
|
+
const pid = Number(takeover?.terminal_agent_pid);
|
|
535
|
+
if (validated.version === 3) {
|
|
536
|
+
const result = this.#ports.acceptance.detectCodexCandidates({
|
|
537
|
+
anchor: validated,
|
|
538
|
+
currentInventory: await this.inspectCodexOpenRootInventory(pid, request.terminalControl.currentPath),
|
|
539
|
+
requestHash
|
|
540
|
+
});
|
|
541
|
+
if (result.status === "uncertain") {
|
|
542
|
+
throw candidateAcceptanceError(result);
|
|
543
|
+
}
|
|
544
|
+
return result.status === "accepted" ? result.evidence : undefined;
|
|
545
|
+
}
|
|
546
|
+
const identity = await this.resolveCurrentNativeIdentity({
|
|
547
|
+
agent: "codex",
|
|
548
|
+
pid,
|
|
549
|
+
cwd: request.terminalControl.currentPath,
|
|
550
|
+
preferredSessionId: nonBlankString(validated.native_thread_id)
|
|
551
|
+
});
|
|
552
|
+
if (!identity) {
|
|
553
|
+
return undefined;
|
|
554
|
+
}
|
|
555
|
+
return this.#ports.acceptance.detectBoundCodex({
|
|
556
|
+
anchor: validated,
|
|
557
|
+
currentIdentity: identity,
|
|
558
|
+
requestHash
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
async pollAcceptance(request) {
|
|
562
|
+
const deadline = this.#ports.clock.nowMs() + request.timeoutMs;
|
|
563
|
+
while (true) {
|
|
564
|
+
try {
|
|
565
|
+
const evidence = await this.detectAcceptance(request);
|
|
566
|
+
if (evidence) {
|
|
567
|
+
return { outcome: "agent_accepted", evidence };
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
catch (error) {
|
|
571
|
+
return { outcome: "uncertain", reason: errorText(error) };
|
|
572
|
+
}
|
|
573
|
+
if (this.#ports.clock.nowMs() >= deadline) {
|
|
574
|
+
break;
|
|
575
|
+
}
|
|
576
|
+
await this.#ports.clock.sleep(request.pollIntervalMs);
|
|
577
|
+
}
|
|
578
|
+
if (this.#syntheticAcceptanceOutcome === "not_accepted") {
|
|
579
|
+
return draftNotAccepted();
|
|
580
|
+
}
|
|
581
|
+
try {
|
|
582
|
+
const takeover = isRecord(request.conversation.native_session_takeover)
|
|
583
|
+
? request.conversation.native_session_takeover
|
|
584
|
+
: undefined;
|
|
585
|
+
if (await this.#ports.terminal.proveExactDraftStillPresent({
|
|
586
|
+
executor: request.executor,
|
|
587
|
+
conversation: request.conversation,
|
|
588
|
+
terminalControl: request.terminalControl,
|
|
589
|
+
requestText: String(takeover?.terminal_bridge_request_text ?? ""),
|
|
590
|
+
scrollbackLines: request.scrollbackLines
|
|
591
|
+
})) {
|
|
592
|
+
return draftNotAccepted();
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
catch {
|
|
596
|
+
// Exact native acceptance remains authoritative when draft proof fails.
|
|
597
|
+
}
|
|
598
|
+
return { outcome: "pending_acceptance" };
|
|
599
|
+
}
|
|
600
|
+
assertRuntimeIdentity(input) {
|
|
601
|
+
if (input.runtime?.expectedEmptyNativeSession === true) {
|
|
602
|
+
this.#assertExpectedEmptyRuntime(input);
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
this.#assertBoundRuntime(input);
|
|
606
|
+
}
|
|
607
|
+
assertTurnIdentity(input) {
|
|
608
|
+
const { conversation, currentIdentity, operation } = input;
|
|
609
|
+
this.#ports.authority.assertTurnCurrent(conversation, operation);
|
|
610
|
+
if (nativeAgentIdentityMatchesTurn(conversation, currentIdentity)) {
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
const takeover = isRecord(conversation.native_session_takeover)
|
|
614
|
+
? conversation.native_session_takeover
|
|
615
|
+
: undefined;
|
|
616
|
+
const strictClaude = Number(takeover?.terminal_agent_identity_protocol) === 1 &&
|
|
617
|
+
executorForConversation(conversation).kind === "claude";
|
|
618
|
+
if (strictClaude &&
|
|
619
|
+
(!nonBlankString(takeover?.terminal_agent_process_uuid) ||
|
|
620
|
+
!currentIdentity?.processUuid)) {
|
|
621
|
+
throw new Error("cannot " + operation + " Turn " + turnIdForConversation(conversation) +
|
|
622
|
+
": native Claude process incarnation cannot be verified; this Claude " +
|
|
623
|
+
"CLI must report both sessionId and startedAt before AKK can control it");
|
|
624
|
+
}
|
|
625
|
+
const expected = nonBlankString(takeover?.terminal_agent_session_id) ??
|
|
626
|
+
"unavailable";
|
|
627
|
+
const observed = currentIdentity?.sessionId ?? "unverifiable";
|
|
628
|
+
throw new Error("cannot " + operation + " Turn " + turnIdForConversation(conversation) +
|
|
629
|
+
": native agent session identity changed or cannot be verified " +
|
|
630
|
+
"(expected " + expected + ", observed " + observed + ")");
|
|
631
|
+
}
|
|
632
|
+
withNativeIdentity(conversation, identity) {
|
|
633
|
+
const takeover = isRecord(conversation.native_session_takeover)
|
|
634
|
+
? conversation.native_session_takeover
|
|
635
|
+
: {};
|
|
636
|
+
return {
|
|
637
|
+
...conversation,
|
|
638
|
+
native_thread_id: identity.sessionId,
|
|
639
|
+
native_session_takeover: {
|
|
640
|
+
...takeover,
|
|
641
|
+
terminal_agent_identity_protocol: 1,
|
|
642
|
+
terminal_agent_session_id: identity.sessionId,
|
|
643
|
+
terminal_agent_process_uuid: identity.processUuid,
|
|
644
|
+
terminal_agent_process_birth: identity.processBirth,
|
|
645
|
+
terminal_agent_rollout: identity.rollout,
|
|
646
|
+
terminal_agent_identity_evidence: identity.evidence,
|
|
647
|
+
terminal_agent_identity_bound_at: this.#ports.clock.now().toISOString()
|
|
648
|
+
}
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
async pollNativeIdentity(request) {
|
|
652
|
+
const attempts = request.attempts ?? 40;
|
|
653
|
+
const delayMs = request.delayMs ?? 50;
|
|
654
|
+
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
655
|
+
const identity = await this.#pollNativeIdentityAttempt(request);
|
|
656
|
+
if (identity !== "pending") {
|
|
657
|
+
return identity;
|
|
658
|
+
}
|
|
659
|
+
if (attempt + 1 < attempts) {
|
|
660
|
+
await this.#ports.clock.sleep(delayMs);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
return undefined;
|
|
664
|
+
}
|
|
665
|
+
async #pollNativeIdentityAttempt(request) {
|
|
666
|
+
const required = request.requiredCodexAcceptance;
|
|
667
|
+
if (required?.anchor.version === 3) {
|
|
668
|
+
const result = this.#ports.acceptance.detectCodexCandidates({
|
|
669
|
+
anchor: required.anchor,
|
|
670
|
+
currentInventory: await this.inspectCodexOpenRootInventory(request.pid, request.terminalControl.currentPath),
|
|
671
|
+
requestHash: required.requestHash
|
|
672
|
+
});
|
|
673
|
+
if (result.status === "uncertain") {
|
|
674
|
+
throw candidateAcceptanceError(result);
|
|
675
|
+
}
|
|
676
|
+
return result.status === "accepted" ? result.identity : "pending";
|
|
677
|
+
}
|
|
678
|
+
const identity = await this.resolveCurrentNativeIdentity({
|
|
679
|
+
agent: request.executor,
|
|
680
|
+
pid: request.pid,
|
|
681
|
+
cwd: request.terminalControl.currentPath,
|
|
682
|
+
preferredSessionId: request.allowedPreMaterializationIdentity
|
|
683
|
+
? request.expectedSessionId
|
|
684
|
+
: undefined,
|
|
685
|
+
allowedCompanionIdentity: request.allowedPreMaterializationIdentity,
|
|
686
|
+
allowedAdditionalIdentities: request.allowedAdditionalIdentities
|
|
687
|
+
});
|
|
688
|
+
if (!identity) {
|
|
689
|
+
return "pending";
|
|
690
|
+
}
|
|
691
|
+
if (request.expectedSessionId &&
|
|
692
|
+
identity.sessionId !== request.expectedSessionId) {
|
|
693
|
+
if (nativeIdentityMatchesCodexPreMaterialization(identity, request.allowedPreMaterializationIdentity)) {
|
|
694
|
+
return "pending";
|
|
695
|
+
}
|
|
696
|
+
throw new Error("native agent materialized unexpected thread " + identity.sessionId +
|
|
697
|
+
"; expected " + request.expectedSessionId);
|
|
698
|
+
}
|
|
699
|
+
if (!required) {
|
|
700
|
+
return identity;
|
|
701
|
+
}
|
|
702
|
+
const acceptance = this.#ports.acceptance.detectBoundCodex({
|
|
703
|
+
anchor: required.anchor,
|
|
704
|
+
currentIdentity: identity,
|
|
705
|
+
requestHash: required.requestHash
|
|
706
|
+
});
|
|
707
|
+
return acceptance ? identity : "pending";
|
|
708
|
+
}
|
|
709
|
+
#syntheticEnabled() {
|
|
710
|
+
return this.#syntheticAcceptanceOutcome !== undefined;
|
|
711
|
+
}
|
|
712
|
+
#syntheticEvidence(executor, conversation, requestHash) {
|
|
713
|
+
const outcome = this.#syntheticAcceptanceOutcome;
|
|
714
|
+
if (outcome === undefined || outcome === "pending" ||
|
|
715
|
+
outcome === "not_accepted") {
|
|
716
|
+
return undefined;
|
|
717
|
+
}
|
|
718
|
+
if (outcome === "identity_drift" || outcome === "uncertain") {
|
|
719
|
+
throw new Error("injected terminal acceptance identity drift");
|
|
720
|
+
}
|
|
721
|
+
if (outcome !== "accepted") {
|
|
722
|
+
throw new Error("unsupported injected terminal acceptance outcome " + outcome);
|
|
723
|
+
}
|
|
724
|
+
const takeover = isRecord(conversation.native_session_takeover)
|
|
725
|
+
? conversation.native_session_takeover
|
|
726
|
+
: undefined;
|
|
727
|
+
const nativeThreadId = nonBlankString(takeover?.terminal_agent_session_id) ??
|
|
728
|
+
nonBlankString(takeover?.terminal_agent_expected_session_id) ??
|
|
729
|
+
sessionIdForConversation(conversation);
|
|
730
|
+
const base = {
|
|
731
|
+
source: executor === "codex"
|
|
732
|
+
? "codex_rollout"
|
|
733
|
+
: "claude_transcript",
|
|
734
|
+
kind: "native_user_turn",
|
|
735
|
+
nativeThreadId,
|
|
736
|
+
requestHash,
|
|
737
|
+
acceptanceId: "test-" + turnIdForConversation(conversation),
|
|
738
|
+
anchorFingerprint: sha256("test-anchor:" + nativeThreadId + ":" + requestHash)
|
|
739
|
+
};
|
|
740
|
+
return { ...base, evidenceFingerprint: sha256(JSON.stringify(base)) };
|
|
741
|
+
}
|
|
742
|
+
#assertExpectedEmptyRuntime(input) {
|
|
743
|
+
const runtime = input.runtime;
|
|
744
|
+
if (input.agent === "codex" &&
|
|
745
|
+
(runtime.expectedNativeSessionId || runtime.nativeProcessUuid ||
|
|
746
|
+
runtime.nativeProcessBirth)) {
|
|
747
|
+
this.#assertCodexProcessIncarnation(runtime, input.pid, input.agent);
|
|
748
|
+
}
|
|
749
|
+
if (!input.currentIdentity ||
|
|
750
|
+
runtimeMatchesIdentity(runtime, input.currentIdentity, runtime.expectedNativeSessionId)) {
|
|
751
|
+
return;
|
|
752
|
+
}
|
|
753
|
+
const exactCompanion = [
|
|
754
|
+
runtime.allowedPreMaterializationNativeIdentity,
|
|
755
|
+
...(runtime.allowedAdditionalNativeIdentities ?? [])
|
|
756
|
+
].find((candidate) => candidate?.sessionId !== runtime.expectedNativeSessionId &&
|
|
757
|
+
candidate?.processUuid === runtime.nativeProcessUuid &&
|
|
758
|
+
candidate?.processBirth === runtime.nativeProcessBirth &&
|
|
759
|
+
nativeIdentityMatchesCodexPreMaterialization(input.currentIdentity, candidate));
|
|
760
|
+
if (input.agent === "codex" &&
|
|
761
|
+
runtime.expectedNativeSessionId &&
|
|
762
|
+
exactCompanion) {
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
throw new Error("native " + input.agent + " session appeared for process " + input.pid +
|
|
766
|
+
" during terminal control");
|
|
767
|
+
}
|
|
768
|
+
#assertCodexProcessIncarnation(runtime, pid, agent) {
|
|
769
|
+
if (!runtime.nativeProcessUuid || !runtime.nativeProcessBirth) {
|
|
770
|
+
throw nativeIdentityRefreshError(agent, pid, "cannot be verified");
|
|
771
|
+
}
|
|
772
|
+
let incarnation;
|
|
773
|
+
try {
|
|
774
|
+
incarnation = this.#ports.native.codexProcessIncarnation(pid);
|
|
775
|
+
}
|
|
776
|
+
catch (error) {
|
|
777
|
+
throw new Error("native " + agent +
|
|
778
|
+
" process incarnation cannot be verified for process " + pid + "; " +
|
|
779
|
+
errorText(error));
|
|
780
|
+
}
|
|
781
|
+
if (incarnation.processUuid !== runtime.nativeProcessUuid ||
|
|
782
|
+
incarnation.processBirth !== runtime.nativeProcessBirth) {
|
|
783
|
+
throw nativeIdentityRefreshError(agent, pid, "changed");
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
#assertBoundRuntime(input) {
|
|
787
|
+
const { runtime, currentIdentity, agent, pid } = input;
|
|
788
|
+
if (runtime?.requireNativeRolloutIdentity === true &&
|
|
789
|
+
(!runtime.nativeSessionId || !runtime.nativeProcessUuid ||
|
|
790
|
+
!runtime.nativeProcessBirth ||
|
|
791
|
+
!isCompleteNativeRollout(runtime.nativeRollout) ||
|
|
792
|
+
!currentIdentity?.sessionId || !currentIdentity.processUuid ||
|
|
793
|
+
!currentIdentity.processBirth ||
|
|
794
|
+
!isCompleteNativeRollout(currentIdentity.rollout))) {
|
|
795
|
+
throw new Error("native " + agent +
|
|
796
|
+
" rollout incarnation cannot be verified for process " + pid +
|
|
797
|
+
"; refresh list before controlling the terminal");
|
|
798
|
+
}
|
|
799
|
+
if (runtime?.requireNativeProcessUuid === true &&
|
|
800
|
+
(!runtime.nativeProcessUuid ||
|
|
801
|
+
currentIdentity?.processUuid !== runtime.nativeProcessUuid)) {
|
|
802
|
+
throw nativeIdentityRefreshError(agent, pid, "cannot be verified");
|
|
803
|
+
}
|
|
804
|
+
if (runtime?.nativeProcessStartedAt !== undefined &&
|
|
805
|
+
(!Number.isSafeInteger(runtime.nativeProcessStartedAt) ||
|
|
806
|
+
Number(runtime.nativeProcessStartedAt) <= 0 ||
|
|
807
|
+
currentIdentity?.processStartedAt !== runtime.nativeProcessStartedAt)) {
|
|
808
|
+
throw new Error("native " + agent + " process start changed for process " + pid +
|
|
809
|
+
"; refresh list before controlling the terminal");
|
|
810
|
+
}
|
|
811
|
+
if (runtime?.nativeSessionId &&
|
|
812
|
+
!runtimeMatchesIdentity(runtime, currentIdentity)) {
|
|
813
|
+
throw new Error("native " + agent + " session identity changed for process " + pid +
|
|
814
|
+
"; refresh list before controlling the terminal");
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
function resolveClaudeIdentity(pid, rows) {
|
|
819
|
+
const matching = rows.filter((row) => row.pid === pid);
|
|
820
|
+
if (matching.length === 0) {
|
|
821
|
+
return undefined;
|
|
822
|
+
}
|
|
823
|
+
const sessionIds = unique(matching.map((row) => nonBlankString(row.sessionId)));
|
|
824
|
+
if (sessionIds.length > 1) {
|
|
825
|
+
throw new Error("Claude process " + pid + " has conflicting exact session identities");
|
|
826
|
+
}
|
|
827
|
+
if (!sessionIds[0]) {
|
|
828
|
+
throw new Error("Claude process " + pid +
|
|
829
|
+
" is visible but its exact sessionId is unavailable");
|
|
830
|
+
}
|
|
831
|
+
const startedAtValues = [...new Set(matching.map((row) => Number(row.startedAt))
|
|
832
|
+
.filter((value) => Number.isSafeInteger(value) && value > 0))];
|
|
833
|
+
if (startedAtValues.length > 1) {
|
|
834
|
+
throw new Error("Claude process " + pid +
|
|
835
|
+
" has conflicting process-incarnation timestamps");
|
|
836
|
+
}
|
|
837
|
+
const startedAt = startedAtValues[0];
|
|
838
|
+
if (!startedAt) {
|
|
839
|
+
throw new Error("Claude process " + pid +
|
|
840
|
+
" is visible but its process-incarnation startedAt is unavailable");
|
|
841
|
+
}
|
|
842
|
+
return {
|
|
843
|
+
sessionId: sessionIds[0],
|
|
844
|
+
processStartedAt: startedAt,
|
|
845
|
+
processUuid: "claude-pid:" + pid + ":started:" + startedAt,
|
|
846
|
+
evidence: "claude_agents_exact_pid"
|
|
847
|
+
};
|
|
848
|
+
}
|
|
849
|
+
function runtimeMatchesIdentity(runtime, identity, expectedSession = runtime.nativeSessionId) {
|
|
850
|
+
return Boolean(identity && expectedSession &&
|
|
851
|
+
identity.sessionId === expectedSession &&
|
|
852
|
+
(!runtime.nativeProcessUuid ||
|
|
853
|
+
identity.processUuid === runtime.nativeProcessUuid) &&
|
|
854
|
+
(!runtime.nativeProcessBirth ||
|
|
855
|
+
identity.processBirth === runtime.nativeProcessBirth) &&
|
|
856
|
+
(!runtime.nativeRollout ||
|
|
857
|
+
sameRollout(identity.rollout, runtime.nativeRollout)));
|
|
858
|
+
}
|
|
859
|
+
function sameRollout(left, right) {
|
|
860
|
+
return isRecord(left) && isRecord(right) &&
|
|
861
|
+
nonBlankString(left.fd) === nonBlankString(right.fd) &&
|
|
862
|
+
nonBlankString(left.device) === nonBlankString(right.device) &&
|
|
863
|
+
nonBlankString(left.inode) === nonBlankString(right.inode) &&
|
|
864
|
+
nonBlankString(left.path) === nonBlankString(right.path);
|
|
865
|
+
}
|
|
866
|
+
function optionalValueMatches(left, right) {
|
|
867
|
+
return left === undefined && right === undefined ||
|
|
868
|
+
Boolean(left && right && left === right);
|
|
869
|
+
}
|
|
870
|
+
function candidateAcceptanceError(result) {
|
|
871
|
+
return new Error("Codex candidate-set acceptance is uncertain (" + result.code + "): " +
|
|
872
|
+
result.reason);
|
|
873
|
+
}
|
|
874
|
+
function terminalDispatchPreflightError(decision, target) {
|
|
875
|
+
if (decision.reason === "unresolved_lifecycle") {
|
|
876
|
+
return new Error("terminal " + target + " has unresolved lifecycle transition " +
|
|
877
|
+
(decision.transitionId ?? "with invalid identity") +
|
|
878
|
+
"; refresh AKK list and use its exact recovery action");
|
|
879
|
+
}
|
|
880
|
+
if (decision.reason === "terminal_level_dispatch") {
|
|
881
|
+
return new Error("terminal " + target + " has a terminal-level " +
|
|
882
|
+
String(decision.status) + " dispatch owned by " +
|
|
883
|
+
(decision.ownerConversationId ?? "an unknown conversation") +
|
|
884
|
+
"; inspect the shared terminal pane and explicitly close that AKK " +
|
|
885
|
+
"conversation before retrying");
|
|
886
|
+
}
|
|
887
|
+
if (decision.reason === "owner_unavailable") {
|
|
888
|
+
return new Error("terminal " + target + " has a submitted dispatch whose owner state is " +
|
|
889
|
+
"unavailable; inspect the shared terminal pane and repair or explicitly " +
|
|
890
|
+
"resolve that conversation before sending another task");
|
|
891
|
+
}
|
|
892
|
+
return new Error("terminal " + target + " is still owned by active AKK conversation " +
|
|
893
|
+
decision.ownerConversationId + " (" + decision.ownerStatus +
|
|
894
|
+
"); wait for its callback, cancel it, or explicitly close it before " +
|
|
895
|
+
"sending a different task");
|
|
896
|
+
}
|
|
897
|
+
function draftNotAccepted() {
|
|
898
|
+
return {
|
|
899
|
+
outcome: "not_accepted",
|
|
900
|
+
reason: "the exact managed draft remains in the terminal composer"
|
|
901
|
+
};
|
|
902
|
+
}
|
|
903
|
+
function nativeIdentityRefreshError(agent, pid, state) {
|
|
904
|
+
return new Error("native " + agent + " process incarnation " + state + " for process " +
|
|
905
|
+
pid + "; refresh list before controlling the terminal");
|
|
906
|
+
}
|
|
907
|
+
function unique(values) {
|
|
908
|
+
return [...new Set(values.filter((value) => value !== undefined))];
|
|
909
|
+
}
|
|
910
|
+
function sha256(value) {
|
|
911
|
+
return createHash("sha256").update(value).digest("hex");
|
|
912
|
+
}
|
|
913
|
+
function errorText(error) {
|
|
914
|
+
return error instanceof Error ? error.message : String(error);
|
|
915
|
+
}
|
|
916
|
+
//# sourceMappingURL=terminal-dispatch-execution.js.map
|