@scotthuang/agent-knock-knock 0.13.3 → 0.13.5
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 +25 -0
- package/README.md +13 -5
- 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/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.d.ts +1 -1
- package/dist/src/codex-terminal-agent-adapter.js +56 -4
- 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 +2 -172
- 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/native-thread-lifecycle-cli-adapter.js +116 -60
- 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 -2660
- package/dist/src/openclaw-plugin-command-adapter.js.map +1 -1
- package/dist/src/openclaw-plugin-helpers.d.ts +2 -148
- package/dist/src/openclaw-plugin-helpers.js +2 -1844
- package/dist/src/openclaw-plugin-helpers.js.map +1 -1
- package/dist/src/openclaw-plugin-schemas.d.ts +2 -563
- package/dist/src/openclaw-plugin-schemas.js +2 -572
- 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 +2 -98
- package/dist/src/terminal-action-projection.js +13 -215
- package/dist/src/terminal-action-projection.js.map +1 -1
- package/dist/src/terminal-agent-bridge.d.ts +14 -340
- package/dist/src/terminal-agent-bridge.js +155 -3226
- 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-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 +165 -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 +241 -1946
- 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 +11 -11
- package/dist/src/terminal-list-renderer.js +168 -119
- 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 +37 -18
- package/dist/src/terminal-model-control.js +285 -194
- package/dist/src/terminal-model-control.js.map +1 -1
- 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 -2
- 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/package.json +7 -2
- package/templates/openclaw-skills/agent-knock-knock/SKILL.md +1 -1
|
@@ -0,0 +1,859 @@
|
|
|
1
|
+
// Ordinary terminal dispatch transaction and transport orchestration.
|
|
2
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import * as dispatchApplication from "./terminal-dispatch-application.js";
|
|
5
|
+
import * as dispatchReceipt from "./terminal-dispatch-receipt.js";
|
|
6
|
+
import * as deferredRecoveryAdapter from "./deferred-foreground-recovery-cli-adapter.js";
|
|
7
|
+
import * as monitorOwner from "./terminal-monitor-ownership-policy.js";
|
|
8
|
+
import { bindDeferredForegroundApplicationScope } from "./deferred-foreground-capability.js";
|
|
9
|
+
import { deferredForegroundBoundaryProjection } from "./deferred-foreground-preparation-cli-adapter.js";
|
|
10
|
+
import { executorForConversation, sessionIdForConversation } from "./protocol.js";
|
|
11
|
+
import { messageEvent } from "./store.js";
|
|
12
|
+
import { TerminalEnterDispatchNotAttemptedError, TerminalInputNotStartedError } from "./terminal-agent-bridge.js";
|
|
13
|
+
import { isCompleteNativeRollout } from "./terminal-authority-policy.js";
|
|
14
|
+
import { bindTerminalDispatchCapabilities, withExactTerminalDispatchRoute } from "./terminal-dispatch-capability.js";
|
|
15
|
+
import { sameCanonicalStatePath } from "./terminal-dispatch-ledger-codec.js";
|
|
16
|
+
import { presentTerminalCompleted, presentTerminalIdentityFailure, presentTerminalUncertain, presentTerminalZeroInputAbort as renderTerminalZeroInputAbort } from "./terminal-dispatch-presenter.js";
|
|
17
|
+
import { positiveMilliseconds } from "./cli-command-runtime.js";
|
|
18
|
+
import { isRecord, nonBlankString as stringValue } from "./value-guards.js";
|
|
19
|
+
const dispatchTransportContext = new AsyncLocalStorage();
|
|
20
|
+
function dispatchTransportRuntime() {
|
|
21
|
+
const runtime = dispatchTransportContext.getStore();
|
|
22
|
+
if (!runtime) {
|
|
23
|
+
throw new Error("Terminal dispatch transport runtime is unavailable");
|
|
24
|
+
}
|
|
25
|
+
return runtime;
|
|
26
|
+
}
|
|
27
|
+
function rawPort(name) {
|
|
28
|
+
return ((...arguments_) => {
|
|
29
|
+
const operation = dispatchTransportRuntime().ports[name];
|
|
30
|
+
return operation(...arguments_);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
const assertDeferredCodexForegroundBindingBoundary = rawPort("assertDeferredCodexForegroundBindingBoundary");
|
|
34
|
+
const assertNativeThreadHasExclusiveOwnership = rawPort("assertNativeThreadHasExclusiveOwnership");
|
|
35
|
+
const assertObservedHandoffTransportBoundary = rawPort("assertObservedHandoffTransportBoundary");
|
|
36
|
+
const assertVerifiedEmptyCodexTransportBoundary = rawPort("assertVerifiedEmptyCodexTransportBoundary");
|
|
37
|
+
const deferredForegroundApplication = rawPort("deferredForegroundApplication");
|
|
38
|
+
const deferredForegroundRecoveryAdapterPorts = rawPort("deferredForegroundRecoveryAdapterPorts");
|
|
39
|
+
const managedSessionStoreDirForConversation = rawPort("managedSessionStoreDirForConversation");
|
|
40
|
+
const persistManagedSessionNativeIdentity = rawPort("persistManagedSessionNativeIdentity");
|
|
41
|
+
const quarantineManagedSessionBinding = rawPort("quarantineManagedSessionBinding");
|
|
42
|
+
const required = rawPort("required");
|
|
43
|
+
const stallOtherTerminalBridgeConversationsForUncertainDispatch = rawPort("stallOtherTerminalBridgeConversationsForUncertainDispatch");
|
|
44
|
+
const startTerminalBridgeMonitorForConversation = rawPort("startTerminalBridgeMonitorForConversation");
|
|
45
|
+
const terminalBindingLedgerFields = rawPort("terminalBindingLedgerFields");
|
|
46
|
+
const terminalBridgeRuntimeKey = rawPort("terminalBridgeRuntimeKey");
|
|
47
|
+
const terminalControlFromTakeover = rawPort("terminalControlFromTakeover");
|
|
48
|
+
const terminalDispatchCapabilityRepositories = rawPort("terminalDispatchCapabilityRepositories");
|
|
49
|
+
const terminalRuntimeIdentityForConversation = rawPort("terminalRuntimeIdentityForConversation");
|
|
50
|
+
const withTerminalBridgeSubmission = rawPort("withTerminalBridgeSubmission");
|
|
51
|
+
const foregroundIdentificationAuthority = new Proxy({}, {
|
|
52
|
+
get: (_target, property) => dispatchTransportRuntime().foregroundProofs[property]
|
|
53
|
+
});
|
|
54
|
+
const cliEnv = () => dispatchTransportRuntime().runtime.env();
|
|
55
|
+
const cliExit = (code) => dispatchTransportRuntime().runtime.exit(code);
|
|
56
|
+
const cliNow = () => dispatchTransportRuntime().runtime.now();
|
|
57
|
+
const cliPid = () => dispatchTransportRuntime().runtime.pid();
|
|
58
|
+
const runtimeLog = (level, event, fields) => dispatchTransportRuntime().runtime.log(level, event, fields);
|
|
59
|
+
async function resolveTerminalDispatchSubmissionOwner(prepared, request, application, stagedConversation) {
|
|
60
|
+
const { transaction, options, executor, allowedPreMaterializationIdentity, allowedAdditionalIdentities = [], deferredCodexForegroundBinding: deferredBinding } = request;
|
|
61
|
+
const { execution, needsPostSendNativeBinding, codexRolloutAcceptanceAnchor: acceptanceAnchor, terminalControl, terminalAgentPid, sendTakeover, terminalRequestHash, route } = prepared;
|
|
62
|
+
const deferredForegroundScope = deferredBinding
|
|
63
|
+
? bindDeferredForegroundApplicationScope(transaction.scopes, transaction.resources)
|
|
64
|
+
: undefined;
|
|
65
|
+
const ready = (conversation, pending = false) => ({
|
|
66
|
+
conversation, deferredCandidateBindingPending: pending
|
|
67
|
+
});
|
|
68
|
+
if (!needsPostSendNativeBinding) {
|
|
69
|
+
return ready(stagedConversation);
|
|
70
|
+
}
|
|
71
|
+
let boundIdentity;
|
|
72
|
+
let boundConversation;
|
|
73
|
+
let bindingError;
|
|
74
|
+
try {
|
|
75
|
+
if (deferredBinding &&
|
|
76
|
+
cliEnv().AKK_TEST_ALLOW_SYNTHETIC_TERMINAL_ACCEPTANCE !== "1" &&
|
|
77
|
+
![2, 3].includes(Number(acceptanceAnchor?.version))) {
|
|
78
|
+
throw new Error("deferred Codex foreground binding requires a virgin rollout acceptance anchor");
|
|
79
|
+
}
|
|
80
|
+
boundIdentity = await execution.pollNativeIdentity({
|
|
81
|
+
executor: executor.kind,
|
|
82
|
+
terminalControl,
|
|
83
|
+
pid: terminalAgentPid,
|
|
84
|
+
expectedSessionId: stringValue(sendTakeover?.terminal_agent_expected_session_id),
|
|
85
|
+
allowedPreMaterializationIdentity,
|
|
86
|
+
allowedAdditionalIdentities,
|
|
87
|
+
...(acceptanceAnchor &&
|
|
88
|
+
[2, 3].includes(acceptanceAnchor.version)
|
|
89
|
+
? {
|
|
90
|
+
requiredCodexAcceptance: {
|
|
91
|
+
anchor: acceptanceAnchor,
|
|
92
|
+
requestHash: terminalRequestHash
|
|
93
|
+
},
|
|
94
|
+
attempts: Math.max(1, Math.ceil(dispatchTransportRuntime().defaults.acceptanceTimeoutMs /
|
|
95
|
+
dispatchTransportRuntime().defaults.acceptancePollIntervalMs)),
|
|
96
|
+
delayMs: dispatchTransportRuntime().defaults.acceptancePollIntervalMs
|
|
97
|
+
}
|
|
98
|
+
: {})
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
bindingError = error instanceof Error ? error.message : String(error);
|
|
103
|
+
}
|
|
104
|
+
if (boundIdentity) {
|
|
105
|
+
try {
|
|
106
|
+
if (acceptanceAnchor &&
|
|
107
|
+
(boundIdentity.processUuid !==
|
|
108
|
+
acceptanceAnchor.process_uuid ||
|
|
109
|
+
boundIdentity.processBirth !==
|
|
110
|
+
acceptanceAnchor.process_birth)) {
|
|
111
|
+
throw new Error("Codex process incarnation changed while its native thread materialized");
|
|
112
|
+
}
|
|
113
|
+
const expectedNativeThreadId = stringValue(sendTakeover?.terminal_agent_expected_session_id);
|
|
114
|
+
if (expectedNativeThreadId &&
|
|
115
|
+
boundIdentity.sessionId !== expectedNativeThreadId) {
|
|
116
|
+
throw new Error(`native agent created thread ${boundIdentity.sessionId}, expected ` +
|
|
117
|
+
`${expectedNativeThreadId}`);
|
|
118
|
+
}
|
|
119
|
+
const resolvedBoundConversation = execution.withNativeIdentity(stagedConversation, boundIdentity);
|
|
120
|
+
boundConversation = resolvedBoundConversation;
|
|
121
|
+
const bindingStoreDir = managedSessionStoreDirForConversation(resolvedBoundConversation);
|
|
122
|
+
const bindingStatePath = stringValue(resolvedBoundConversation.state_path);
|
|
123
|
+
if (!bindingStoreDir || !bindingStatePath) {
|
|
124
|
+
throw new Error("managed Session Store is unavailable before native identity commit");
|
|
125
|
+
}
|
|
126
|
+
const identityRoute = withExactTerminalDispatchRoute(route, {
|
|
127
|
+
terminalControl,
|
|
128
|
+
terminalKey: terminalBridgeRuntimeKey(terminalControl),
|
|
129
|
+
storeDir: bindingStoreDir,
|
|
130
|
+
statePath: bindingStatePath,
|
|
131
|
+
logPath: path.join(path.dirname(bindingStatePath), "events.ndjson")
|
|
132
|
+
}, (exactRoute) => exactRoute);
|
|
133
|
+
if (deferredBinding) {
|
|
134
|
+
await deferredForegroundApplication(options, deferredBinding.terminal).commit({
|
|
135
|
+
scope: required(deferredForegroundScope, "deferred foreground mutation scope is unavailable"),
|
|
136
|
+
boundary: deferredForegroundBoundaryProjection(deferredBinding),
|
|
137
|
+
identity: boundIdentity,
|
|
138
|
+
acceptedAt: cliNow().toISOString()
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
if (executor.kind === "codex") {
|
|
143
|
+
await rawPort("prepareManagedSessionNativeIdentityClaim")({
|
|
144
|
+
options,
|
|
145
|
+
conversation: boundConversation,
|
|
146
|
+
identity: boundIdentity,
|
|
147
|
+
storeDir: identityRoute.storeDir,
|
|
148
|
+
terminalControl
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
await assertNativeThreadHasExclusiveOwnership({
|
|
153
|
+
options,
|
|
154
|
+
agent: executor.kind,
|
|
155
|
+
currentPid: terminalAgentPid,
|
|
156
|
+
nativeThreadId: boundIdentity.sessionId,
|
|
157
|
+
storeDir: identityRoute.storeDir,
|
|
158
|
+
terminalControl,
|
|
159
|
+
excludedManagedSessionId: sessionIdForConversation(boundConversation)
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
persistManagedSessionNativeIdentity({
|
|
163
|
+
conversation: boundConversation,
|
|
164
|
+
terminalControl,
|
|
165
|
+
identity: boundIdentity,
|
|
166
|
+
storeDir: identityRoute.storeDir
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
if (acceptanceAnchor &&
|
|
170
|
+
[2, 3].includes(acceptanceAnchor.version) &&
|
|
171
|
+
cliEnv().AKK_TEST_EXIT_AFTER_VIRGIN_SESSION_BINDING === "1") {
|
|
172
|
+
cliExit(86);
|
|
173
|
+
}
|
|
174
|
+
// Persist the observed identity before the full Turn-vs-Session check:
|
|
175
|
+
// the provisional Turn and Session initially share only a binding id.
|
|
176
|
+
execution.assertTurnIdentity({
|
|
177
|
+
conversation: boundConversation,
|
|
178
|
+
currentIdentity: boundIdentity,
|
|
179
|
+
operation: "bind"
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
bindingError = error instanceof Error ? error.message : String(error);
|
|
184
|
+
boundIdentity = undefined;
|
|
185
|
+
boundConversation = undefined;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (!boundIdentity && deferredBinding) {
|
|
189
|
+
try {
|
|
190
|
+
const deferredScope = required(deferredForegroundScope, "deferred foreground mutation scope is unavailable");
|
|
191
|
+
const transfer = deferredScope.loadTransfer(deferredBinding.transferId);
|
|
192
|
+
if (["committed", "resolved"].includes(transfer.status)) {
|
|
193
|
+
const recoveredTarget = await deferredForegroundApplication(options, deferredBinding.terminal).resolve({
|
|
194
|
+
scope: deferredScope,
|
|
195
|
+
boundary: deferredForegroundBoundaryProjection(deferredBinding)
|
|
196
|
+
});
|
|
197
|
+
const binding = recoveredTarget.binding;
|
|
198
|
+
if (!binding?.native_thread_id ||
|
|
199
|
+
!binding.native_process.process_uuid ||
|
|
200
|
+
!binding.native_process.process_birth ||
|
|
201
|
+
!isCompleteNativeRollout(binding.native_process.rollout)) {
|
|
202
|
+
throw new Error("resolved deferred target lacks exact native identity");
|
|
203
|
+
}
|
|
204
|
+
const recoveredIdentity = {
|
|
205
|
+
sessionId: binding.native_thread_id,
|
|
206
|
+
processUuid: binding.native_process.process_uuid,
|
|
207
|
+
processBirth: binding.native_process.process_birth,
|
|
208
|
+
rollout: binding.native_process.rollout,
|
|
209
|
+
evidence: binding.native_process.evidence
|
|
210
|
+
};
|
|
211
|
+
const recoveredConversation = execution.withNativeIdentity(stagedConversation, recoveredIdentity);
|
|
212
|
+
execution.assertTurnIdentity({
|
|
213
|
+
conversation: recoveredConversation,
|
|
214
|
+
currentIdentity: recoveredIdentity,
|
|
215
|
+
operation: "recover deferred foreground binding for"
|
|
216
|
+
});
|
|
217
|
+
boundIdentity = recoveredIdentity;
|
|
218
|
+
boundConversation = recoveredConversation;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
bindingError = error instanceof Error ? error.message : String(error);
|
|
223
|
+
boundIdentity = undefined;
|
|
224
|
+
boundConversation = undefined;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
if (boundIdentity && boundConversation) {
|
|
228
|
+
return ready(boundConversation);
|
|
229
|
+
}
|
|
230
|
+
if (acceptanceAnchor?.version === 3 &&
|
|
231
|
+
bindingError === undefined) {
|
|
232
|
+
return ready(stagedConversation, true);
|
|
233
|
+
}
|
|
234
|
+
const bindingReason = bindingError
|
|
235
|
+
? `AKK dispatched terminal input but could not verify the new native agent session: ${bindingError}`
|
|
236
|
+
: "AKK dispatched terminal input but no exact native agent session appeared within the binding window";
|
|
237
|
+
if (deferredBinding) {
|
|
238
|
+
try {
|
|
239
|
+
deferredForegroundApplication(options, deferredBinding.terminal).markUncertain({
|
|
240
|
+
scope: required(deferredForegroundScope, "deferred foreground mutation scope is unavailable"),
|
|
241
|
+
boundary: deferredForegroundBoundaryProjection(deferredBinding),
|
|
242
|
+
reason: bindingReason
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
runtimeLog("error", "deferred_codex_foreground_uncertain_persist_failed", {
|
|
247
|
+
transfer_id: deferredBinding.transferId,
|
|
248
|
+
error: error instanceof Error ? error.message : String(error)
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return {
|
|
253
|
+
conversation: application.applyIdentityFailure(cliNow().toISOString(), bindingReason, deferredBinding
|
|
254
|
+
? undefined
|
|
255
|
+
: (current) => quarantineManagedSessionBinding({
|
|
256
|
+
conversation: current,
|
|
257
|
+
reason: bindingReason,
|
|
258
|
+
storeDir: route.storeDir
|
|
259
|
+
})),
|
|
260
|
+
failureReason: bindingReason
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
function deferredTerminalInputNotStartedAt(transfer, terminalInputNotStartedAt) {
|
|
264
|
+
if (terminalInputNotStartedAt === undefined ||
|
|
265
|
+
transfer.input_stage === "none") {
|
|
266
|
+
return undefined;
|
|
267
|
+
}
|
|
268
|
+
if (transfer.status === "dispatch_started" &&
|
|
269
|
+
transfer.input_stage === "dispatch_started") {
|
|
270
|
+
return terminalInputNotStartedAt;
|
|
271
|
+
}
|
|
272
|
+
throw new Error(`deferred foreground transfer ${transfer.transfer_id} has ` +
|
|
273
|
+
`${transfer.input_stage} input evidence and cannot accept a ` +
|
|
274
|
+
"terminal-input-not-started result");
|
|
275
|
+
}
|
|
276
|
+
function terminalDispatchRollbackRepositories({ request, prepared, deferredForegroundScope, preTransportRollback }) {
|
|
277
|
+
const { options, conversation, deferredCodexForegroundBinding } = request;
|
|
278
|
+
let rollbackPreTransportAttach = preTransportRollback;
|
|
279
|
+
const rollbackBeforeInput = (route) => {
|
|
280
|
+
if (!rollbackPreTransportAttach) {
|
|
281
|
+
return true;
|
|
282
|
+
}
|
|
283
|
+
const rollback = rollbackPreTransportAttach;
|
|
284
|
+
rollbackPreTransportAttach = undefined;
|
|
285
|
+
try {
|
|
286
|
+
rollback(route);
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
catch (error) {
|
|
290
|
+
runtimeLog("error", "raw_attach_pre_transport_rollback_failed", {
|
|
291
|
+
conversation_id: conversation.conversation_id,
|
|
292
|
+
terminal_target: route.terminalControl.target,
|
|
293
|
+
error: error instanceof Error ? error.message : String(error)
|
|
294
|
+
});
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
const restoreDeferred = (route, terminalInputNotStartedAt) => {
|
|
299
|
+
if (!deferredCodexForegroundBinding) {
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
const deferredScope = required(deferredForegroundScope, "deferred foreground mutation scope is unavailable");
|
|
303
|
+
const transfer = deferredScope.loadTransfer(deferredCodexForegroundBinding.transferId);
|
|
304
|
+
if (terminalBridgeRuntimeKey(route.terminalControl) !==
|
|
305
|
+
terminalBridgeRuntimeKey(deferredCodexForegroundBinding.terminal.terminalControl) ||
|
|
306
|
+
(transfer.state_path !== undefined &&
|
|
307
|
+
!sameCanonicalStatePath(transfer.state_path, route.statePath))) {
|
|
308
|
+
throw new Error("deferred Codex pre-input abort escaped its exact mutation resources");
|
|
309
|
+
}
|
|
310
|
+
const durableTerminalInputNotStartedAt = deferredTerminalInputNotStartedAt(transfer, terminalInputNotStartedAt);
|
|
311
|
+
deferredRecoveryAdapter.abortPreparedDeferredForegroundTurn(deferredForegroundRecoveryAdapterPorts(), {
|
|
312
|
+
options,
|
|
313
|
+
scope: deferredScope,
|
|
314
|
+
storeDir: route.storeDir,
|
|
315
|
+
terminal: {
|
|
316
|
+
...deferredCodexForegroundBinding.terminal,
|
|
317
|
+
terminalControl: route.terminalControl
|
|
318
|
+
},
|
|
319
|
+
transfer,
|
|
320
|
+
boundary: deferredCodexForegroundBinding,
|
|
321
|
+
terminalInputNotStartedAt: durableTerminalInputNotStartedAt
|
|
322
|
+
});
|
|
323
|
+
// The dedicated abort already durably restores the Turn, ledger,
|
|
324
|
+
// transfer, and Sessions. Never invoke the attach rollback twice.
|
|
325
|
+
rollbackPreTransportAttach = undefined;
|
|
326
|
+
return true;
|
|
327
|
+
};
|
|
328
|
+
return { rollbackBeforeInput, restoreDeferred };
|
|
329
|
+
}
|
|
330
|
+
function createTerminalDispatchRuntime(request, prepared, rollback) {
|
|
331
|
+
const { transaction, conversation, nextConversation, executor, message, recordRawAttachmentAfterSend = false, postSendCodexDetachedSessionClaims } = request;
|
|
332
|
+
const { bridge, terminalControl, lockedStoreDir, statePath, logPath, bridgeStartedAt, submissionPreparedAt, agentTimeoutMinutes, agentHardTimeoutMinutes, terminalPayload, terminalRequestHash, previousDispatchLedger, preSendScreenFingerprint, codexRolloutAcceptanceAnchor, claudeTranscriptAnchor, claudeHome } = prepared;
|
|
333
|
+
const terminalMessage = message;
|
|
334
|
+
const bridgeConversation = bridge
|
|
335
|
+
? dispatchReceipt.withTerminalBridgeState({
|
|
336
|
+
conversation: nextConversation,
|
|
337
|
+
message: terminalMessage,
|
|
338
|
+
requestText: terminalPayload,
|
|
339
|
+
startedAt: bridgeStartedAt,
|
|
340
|
+
agentTimeoutMinutes,
|
|
341
|
+
agentHardTimeoutMinutes,
|
|
342
|
+
monitorLockVersion: monitorOwner.LOCK_VERSION,
|
|
343
|
+
preSendScreenFingerprint,
|
|
344
|
+
codexRolloutAcceptanceAnchor,
|
|
345
|
+
codexDetachedCandidateSessionClaims: postSendCodexDetachedSessionClaims,
|
|
346
|
+
claudeTranscriptAnchor,
|
|
347
|
+
claudeHome
|
|
348
|
+
})
|
|
349
|
+
: nextConversation;
|
|
350
|
+
const preparedSubmissionConversation = withTerminalBridgeSubmission({
|
|
351
|
+
conversation: bridgeConversation,
|
|
352
|
+
messageId: message.id,
|
|
353
|
+
messageType: terminalMessage.type,
|
|
354
|
+
messageBody: String(message.body),
|
|
355
|
+
requestText: terminalPayload,
|
|
356
|
+
status: "prepared",
|
|
357
|
+
preparedAt: submissionPreparedAt
|
|
358
|
+
});
|
|
359
|
+
// A deferred generation's receipt authority begins when its transfer is
|
|
360
|
+
// prepared. Keep the newer bridge lifecycle timestamp at the Turn level so
|
|
361
|
+
// creating the provisional Turn never moves its visible update time back.
|
|
362
|
+
const preparedConversation = submissionPreparedAt === bridgeStartedAt
|
|
363
|
+
? preparedSubmissionConversation
|
|
364
|
+
: { ...preparedSubmissionConversation, updated_at: bridgeStartedAt };
|
|
365
|
+
const previousGenerationId = stringValue(previousDispatchLedger?.generation_id) ??
|
|
366
|
+
stringValue(previousDispatchLedger?.message_id);
|
|
367
|
+
const progress = {
|
|
368
|
+
stagedConversation: preparedConversation
|
|
369
|
+
};
|
|
370
|
+
let preparedMessageEvent;
|
|
371
|
+
const recordPostTransportBookkeepingFailure = (phase, error) => {
|
|
372
|
+
const warning = error instanceof Error ? error.message : String(error);
|
|
373
|
+
progress.bookkeepingWarning ??= warning;
|
|
374
|
+
runtimeLog("warn", "terminal_message_post_transport_bookkeeping_failed", {
|
|
375
|
+
conversation_id: conversation.conversation_id,
|
|
376
|
+
terminal_target: terminalControl.target,
|
|
377
|
+
phase,
|
|
378
|
+
error: warning
|
|
379
|
+
});
|
|
380
|
+
};
|
|
381
|
+
const { applicationPorts } = bindTerminalDispatchCapabilities({
|
|
382
|
+
scopes: transaction.scopes,
|
|
383
|
+
resources: transaction.resources,
|
|
384
|
+
repositories: terminalDispatchCapabilityRepositories({
|
|
385
|
+
previousLedger: previousDispatchLedger,
|
|
386
|
+
preparedMessageEvent: () => {
|
|
387
|
+
if (!preparedMessageEvent) {
|
|
388
|
+
throw new Error("prepared message event was not validated");
|
|
389
|
+
}
|
|
390
|
+
return preparedMessageEvent;
|
|
391
|
+
},
|
|
392
|
+
restoreDeferred: rollback.restoreDeferred,
|
|
393
|
+
rollbackBeforeInput: rollback.rollbackBeforeInput
|
|
394
|
+
}),
|
|
395
|
+
local: {
|
|
396
|
+
synchronizeStageProgress: (current, stage, at) => {
|
|
397
|
+
progress.stagedConversation = current;
|
|
398
|
+
progress.textInjectedAt = stage === "text_injected"
|
|
399
|
+
? at
|
|
400
|
+
: progress.textInjectedAt;
|
|
401
|
+
progress.enterDispatchedAt = stage === "enter_dispatched"
|
|
402
|
+
? at
|
|
403
|
+
: progress.enterDispatchedAt;
|
|
404
|
+
},
|
|
405
|
+
audit: {
|
|
406
|
+
log: runtimeLog,
|
|
407
|
+
recordBookkeepingFailure: recordPostTransportBookkeepingFailure,
|
|
408
|
+
recordPersistenceFailure: (phase, error, current) => {
|
|
409
|
+
runtimeLog("error", phase, {
|
|
410
|
+
conversation_id: current.conversation_id,
|
|
411
|
+
terminal_target: terminalControl.target,
|
|
412
|
+
error: error instanceof Error ? error.message : String(error)
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
const application = new dispatchApplication.TerminalDispatchApplication({
|
|
419
|
+
originalConversation: conversation,
|
|
420
|
+
preparedConversation,
|
|
421
|
+
message: terminalMessage,
|
|
422
|
+
executor,
|
|
423
|
+
terminalControl,
|
|
424
|
+
receiptTerminalControl: terminalControlFromTakeover(isRecord(preparedConversation.native_session_takeover)
|
|
425
|
+
? preparedConversation.native_session_takeover
|
|
426
|
+
: undefined),
|
|
427
|
+
requestText: terminalPayload,
|
|
428
|
+
requestHash: terminalRequestHash,
|
|
429
|
+
preparedAt: submissionPreparedAt,
|
|
430
|
+
statePath,
|
|
431
|
+
eventLogPath: logPath,
|
|
432
|
+
previousGenerationId,
|
|
433
|
+
dispatcherPid: cliPid(),
|
|
434
|
+
storeDir: lockedStoreDir,
|
|
435
|
+
recordRawAttachmentAfterSend,
|
|
436
|
+
ledgerBindingFields: terminalBindingLedgerFields
|
|
437
|
+
}, applicationPorts);
|
|
438
|
+
application.persistPrepared();
|
|
439
|
+
return {
|
|
440
|
+
application,
|
|
441
|
+
terminalMessage,
|
|
442
|
+
progress,
|
|
443
|
+
recordPostTransportBookkeepingFailure,
|
|
444
|
+
validatePreparedMessageEvent: () => {
|
|
445
|
+
preparedMessageEvent = messageEvent(terminalMessage);
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
function terminalDispatchTransportLifecycle({ request, prepared, application, deferredForegroundScope }) {
|
|
450
|
+
const { options, observedHandoff, verifiedEmptyCodexHandoff, deferredCodexForegroundBinding } = request;
|
|
451
|
+
const lifecycle = prepared.execution.transportLifecycle({
|
|
452
|
+
...(observedHandoff
|
|
453
|
+
? {
|
|
454
|
+
observedHandoff: {
|
|
455
|
+
verify: (requireEmptyComposer) => assertObservedHandoffTransportBoundary({
|
|
456
|
+
options,
|
|
457
|
+
terminal: observedHandoff.terminal,
|
|
458
|
+
transition: observedHandoff.transition,
|
|
459
|
+
requireEmptyComposer
|
|
460
|
+
})
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
: {}),
|
|
464
|
+
...(verifiedEmptyCodexHandoff
|
|
465
|
+
? {
|
|
466
|
+
verifiedEmptyHandoff: {
|
|
467
|
+
verify: (requireEmptyComposer) => assertVerifiedEmptyCodexTransportBoundary({
|
|
468
|
+
options,
|
|
469
|
+
boundary: verifiedEmptyCodexHandoff,
|
|
470
|
+
requireEmptyComposer
|
|
471
|
+
})
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
: {}),
|
|
475
|
+
...(deferredCodexForegroundBinding
|
|
476
|
+
? {
|
|
477
|
+
deferredBinding: {
|
|
478
|
+
verify: (requireEmptyComposer) => assertDeferredCodexForegroundBindingBoundary({
|
|
479
|
+
options,
|
|
480
|
+
scope: required(deferredForegroundScope, "deferred foreground mutation scope is unavailable"),
|
|
481
|
+
boundary: deferredCodexForegroundBinding,
|
|
482
|
+
expectedSourceStatus: "transitioning",
|
|
483
|
+
requireNoDispatch: false,
|
|
484
|
+
requireEmptyComposer
|
|
485
|
+
}),
|
|
486
|
+
begin: (at) => deferredForegroundApplication(options, deferredCodexForegroundBinding.terminal).begin({
|
|
487
|
+
scope: required(deferredForegroundScope, "deferred foreground mutation scope is unavailable"),
|
|
488
|
+
boundary: deferredForegroundBoundaryProjection(deferredCodexForegroundBinding),
|
|
489
|
+
at
|
|
490
|
+
}),
|
|
491
|
+
advance: (stage, at) => deferredForegroundApplication(options, deferredCodexForegroundBinding.terminal).advance({
|
|
492
|
+
scope: required(deferredForegroundScope, "deferred foreground mutation scope is unavailable"),
|
|
493
|
+
boundary: deferredForegroundBoundaryProjection(deferredCodexForegroundBinding),
|
|
494
|
+
stage,
|
|
495
|
+
at
|
|
496
|
+
})
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
: {}),
|
|
500
|
+
recordStage: (stage, at, afterDurable) => application.recordTransportStage(stage, at, afterDurable)
|
|
501
|
+
});
|
|
502
|
+
const lifecycleBeforeText = lifecycle.beforeText;
|
|
503
|
+
const guardedLifecycle = options.identifyForeground === true
|
|
504
|
+
? {
|
|
505
|
+
...lifecycle,
|
|
506
|
+
beforeText: async () => {
|
|
507
|
+
await lifecycleBeforeText?.();
|
|
508
|
+
const proof = foregroundIdentificationAuthority.current(options);
|
|
509
|
+
const status = await prepared.terminalBridge.status(request.executor.kind, prepared.terminalControl, {
|
|
510
|
+
runtime: prepared.preSendRuntime,
|
|
511
|
+
scrollbackLines: proof?.observationScrollbackLines ??
|
|
512
|
+
dispatchTransportRuntime().defaults.foregroundScrollbackLines
|
|
513
|
+
});
|
|
514
|
+
foregroundIdentificationAuthority.assertCurrent({
|
|
515
|
+
options,
|
|
516
|
+
executor: request.executor,
|
|
517
|
+
terminalControl: prepared.terminalControl,
|
|
518
|
+
terminalAgentPid: prepared.terminalAgentPid,
|
|
519
|
+
status
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
: lifecycle;
|
|
524
|
+
const userExplicitTerminalSend = Boolean(stringValue(options.expectedUserExplicitTerminalToken));
|
|
525
|
+
return userExplicitTerminalSend
|
|
526
|
+
? {
|
|
527
|
+
...guardedLifecycle,
|
|
528
|
+
requireExactEmptyComposerBeforeText: true,
|
|
529
|
+
...(request.executor.kind === "codex"
|
|
530
|
+
? { userExplicitEnterAfterTextWithoutComposerVeto: true }
|
|
531
|
+
: {})
|
|
532
|
+
}
|
|
533
|
+
: guardedLifecycle;
|
|
534
|
+
}
|
|
535
|
+
async function terminalDispatchAcceptance({ request, prepared, conversation }) {
|
|
536
|
+
const { options, executor } = request;
|
|
537
|
+
const { execution, terminalControl } = prepared;
|
|
538
|
+
const timeoutMs = positiveMilliseconds(options.terminalAcceptanceTimeoutMs ??
|
|
539
|
+
dispatchTransportRuntime().defaults.acceptanceTimeoutMs, "--terminal-acceptance-timeout-ms");
|
|
540
|
+
return execution.pollAcceptance({
|
|
541
|
+
executor: executor.kind,
|
|
542
|
+
conversation,
|
|
543
|
+
terminalControl,
|
|
544
|
+
...terminalAcceptanceCompanionFences(conversation, terminalControl),
|
|
545
|
+
timeoutMs,
|
|
546
|
+
pollIntervalMs: Math.max(10, Math.min(timeoutMs, Number(options.terminalAcceptancePollIntervalMs ??
|
|
547
|
+
dispatchTransportRuntime().defaults.acceptancePollIntervalMs))),
|
|
548
|
+
scrollbackLines: Number(options.scrollbackLines ?? 240)
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
function terminalAcceptanceCompanionFences(conversation, terminalControl) {
|
|
552
|
+
if (executorForConversation(conversation).kind !== "codex") {
|
|
553
|
+
return {};
|
|
554
|
+
}
|
|
555
|
+
const runtime = terminalRuntimeIdentityForConversation(conversation, terminalControl);
|
|
556
|
+
return {
|
|
557
|
+
allowedCompanionIdentity: runtime.allowedPreMaterializationNativeIdentity,
|
|
558
|
+
allowedAdditionalIdentities: runtime.allowedAdditionalNativeIdentities
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
function launchAcceptedTerminalMonitor({ request, prepared, conversation, acceptance, recordFailure }) {
|
|
562
|
+
const { options } = request;
|
|
563
|
+
const { bridge, statePath, logPath, terminalControl, agentTimeoutMinutes, agentHardTimeoutMinutes } = prepared;
|
|
564
|
+
if (!bridge ||
|
|
565
|
+
!(acceptance.outcome === "agent_accepted" ||
|
|
566
|
+
acceptance.outcome === "pending_acceptance")) {
|
|
567
|
+
return undefined;
|
|
568
|
+
}
|
|
569
|
+
try {
|
|
570
|
+
const monitor = startTerminalBridgeMonitorForConversation({
|
|
571
|
+
conversation,
|
|
572
|
+
statePath,
|
|
573
|
+
logPath,
|
|
574
|
+
options
|
|
575
|
+
});
|
|
576
|
+
if (monitor) {
|
|
577
|
+
dispatchTransportRuntime().runtime.appendEvent(logPath, {
|
|
578
|
+
ts: cliNow().toISOString(),
|
|
579
|
+
conversation_id: conversation.conversation_id,
|
|
580
|
+
event: "terminal_bridge_monitor_launch",
|
|
581
|
+
pid: monitor.pid ?? null,
|
|
582
|
+
terminal_control: terminalControl,
|
|
583
|
+
phase: acceptance.outcome,
|
|
584
|
+
agent_timeout_minutes: agentTimeoutMinutes,
|
|
585
|
+
agent_hard_timeout_minutes: agentHardTimeoutMinutes
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
return monitor;
|
|
589
|
+
}
|
|
590
|
+
catch (error) {
|
|
591
|
+
recordFailure("monitor_launch", error);
|
|
592
|
+
return undefined;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
function presentTerminalDispatchTransportFailure({ error, request, prepared, application, progress, deferredForegroundScope, bridgeMonitor, deferZeroInputFailurePresentation }) {
|
|
596
|
+
const { options, executor, message, deferredCodexForegroundBinding } = request;
|
|
597
|
+
const { lockedStoreDir, terminalControl, presentationContext, presentationPorts } = prepared;
|
|
598
|
+
if (!progress.textInjectedAt &&
|
|
599
|
+
error instanceof TerminalInputNotStartedError) {
|
|
600
|
+
let aborted;
|
|
601
|
+
try {
|
|
602
|
+
aborted = application.recordZeroInputAbort({
|
|
603
|
+
failureKind: "transport",
|
|
604
|
+
error,
|
|
605
|
+
abortedAt: cliNow().toISOString()
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
catch (persistenceError) {
|
|
609
|
+
if (!deferZeroInputFailurePresentation)
|
|
610
|
+
throw persistenceError;
|
|
611
|
+
runtimeLog("warn", "terminal_user_explicit_zero_input_abort_unavailable", {
|
|
612
|
+
terminal_target: prepared.terminalControl.target,
|
|
613
|
+
error: persistenceError instanceof Error
|
|
614
|
+
? persistenceError.message
|
|
615
|
+
: String(persistenceError)
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
if (!deferZeroInputFailurePresentation && aborted) {
|
|
619
|
+
renderTerminalZeroInputAbort(aborted, presentationContext, presentationPorts, bridgeMonitor?.pid);
|
|
620
|
+
}
|
|
621
|
+
return "zero_input";
|
|
622
|
+
}
|
|
623
|
+
const uncertainAt = cliNow().toISOString();
|
|
624
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
625
|
+
if (deferredCodexForegroundBinding) {
|
|
626
|
+
try {
|
|
627
|
+
deferredForegroundApplication(options, deferredCodexForegroundBinding.terminal).markUncertain({
|
|
628
|
+
scope: required(deferredForegroundScope, "deferred foreground mutation scope is unavailable"),
|
|
629
|
+
boundary: deferredForegroundBoundaryProjection(deferredCodexForegroundBinding),
|
|
630
|
+
reason: errorMessage
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
catch (transferError) {
|
|
634
|
+
runtimeLog("error", "deferred_codex_foreground_uncertain_persist_failed", {
|
|
635
|
+
transfer_id: deferredCodexForegroundBinding.transferId,
|
|
636
|
+
error: transferError instanceof Error
|
|
637
|
+
? transferError.message
|
|
638
|
+
: String(transferError)
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
const uncertainConversation = application.applyUncertain(uncertainAt, error, progress.textInjectedAt && !progress.enterDispatchedAt &&
|
|
643
|
+
error instanceof TerminalEnterDispatchNotAttemptedError
|
|
644
|
+
? {
|
|
645
|
+
enterNotAttemptedAt: uncertainAt,
|
|
646
|
+
enterNotAttemptedReason: "pre_key_failure"
|
|
647
|
+
}
|
|
648
|
+
: {});
|
|
649
|
+
const stalledConversationIds = stallOtherTerminalBridgeConversationsForUncertainDispatch({
|
|
650
|
+
storeDir: lockedStoreDir,
|
|
651
|
+
terminalControl,
|
|
652
|
+
currentConversationId: uncertainConversation.conversation_id,
|
|
653
|
+
uncertainMessageId: message.id
|
|
654
|
+
});
|
|
655
|
+
runtimeLog("error", "terminal_message_submit_uncertain", {
|
|
656
|
+
conversation_id: uncertainConversation.conversation_id,
|
|
657
|
+
agent: executor.kind,
|
|
658
|
+
terminal_target: terminalControl.target,
|
|
659
|
+
error: errorMessage,
|
|
660
|
+
do_not_retry: true,
|
|
661
|
+
stalled_conversation_ids: stalledConversationIds
|
|
662
|
+
});
|
|
663
|
+
presentTerminalUncertain({
|
|
664
|
+
conversation: uncertainConversation,
|
|
665
|
+
stalledConversationIds,
|
|
666
|
+
textInjected: progress.textInjectedAt !== undefined,
|
|
667
|
+
enterDispatched: progress.enterDispatchedAt !== undefined,
|
|
668
|
+
monitorPid: bridgeMonitor?.pid
|
|
669
|
+
}, presentationContext, presentationPorts);
|
|
670
|
+
return "input_started";
|
|
671
|
+
}
|
|
672
|
+
async function runTerminalDispatchTransport({ request, prepared, application, progress, recordPostTransportBookkeepingFailure, deferredForegroundScope, deferZeroInputFailurePresentation }) {
|
|
673
|
+
const { executor } = request;
|
|
674
|
+
const { terminalBridge, terminalControl, terminalPayload, preSendRuntime, codexRolloutAcceptanceAnchor, presentationContext, presentationPorts } = prepared;
|
|
675
|
+
let bridgeMonitor;
|
|
676
|
+
try {
|
|
677
|
+
const transportLifecycle = terminalDispatchTransportLifecycle({
|
|
678
|
+
request,
|
|
679
|
+
prepared,
|
|
680
|
+
application,
|
|
681
|
+
deferredForegroundScope
|
|
682
|
+
});
|
|
683
|
+
await terminalBridge.send(executor.kind, terminalControl, terminalPayload, { runtime: preSendRuntime, ...transportLifecycle });
|
|
684
|
+
if (!progress.enterDispatchedAt) {
|
|
685
|
+
throw new Error("terminal bridge returned without an enter_dispatched receipt");
|
|
686
|
+
}
|
|
687
|
+
if (codexRolloutAcceptanceAnchor &&
|
|
688
|
+
[2, 3].includes(codexRolloutAcceptanceAnchor.version) &&
|
|
689
|
+
cliEnv().AKK_TEST_EXIT_AFTER_VIRGIN_ENTER_DISPATCHED === "1") {
|
|
690
|
+
cliExit(86);
|
|
691
|
+
}
|
|
692
|
+
const submissionOwner = await resolveTerminalDispatchSubmissionOwner(prepared, request, application, progress.stagedConversation);
|
|
693
|
+
if ("failureReason" in submissionOwner) {
|
|
694
|
+
presentTerminalIdentityFailure(submissionOwner.conversation, submissionOwner.failureReason, presentationContext, presentationPorts, bridgeMonitor?.pid);
|
|
695
|
+
return {
|
|
696
|
+
outcome: "handled",
|
|
697
|
+
terminalInput: "input_started",
|
|
698
|
+
enterDispatched: true
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
const acceptance = submissionOwner.deferredCandidateBindingPending
|
|
702
|
+
? { outcome: "pending_acceptance" }
|
|
703
|
+
: await terminalDispatchAcceptance({
|
|
704
|
+
request,
|
|
705
|
+
prepared,
|
|
706
|
+
conversation: submissionOwner.conversation
|
|
707
|
+
});
|
|
708
|
+
const deliveredConversation = application.applyAcceptance(submissionOwner.conversation, acceptance, cliNow().toISOString()).conversation;
|
|
709
|
+
bridgeMonitor = launchAcceptedTerminalMonitor({
|
|
710
|
+
request,
|
|
711
|
+
prepared,
|
|
712
|
+
conversation: deliveredConversation,
|
|
713
|
+
acceptance,
|
|
714
|
+
recordFailure: recordPostTransportBookkeepingFailure
|
|
715
|
+
});
|
|
716
|
+
return {
|
|
717
|
+
outcome: "completed",
|
|
718
|
+
conversation: deliveredConversation,
|
|
719
|
+
acceptance,
|
|
720
|
+
bridgeMonitor
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
catch (error) {
|
|
724
|
+
const terminalInput = presentTerminalDispatchTransportFailure({
|
|
725
|
+
error,
|
|
726
|
+
request,
|
|
727
|
+
prepared,
|
|
728
|
+
application,
|
|
729
|
+
progress,
|
|
730
|
+
deferredForegroundScope,
|
|
731
|
+
bridgeMonitor,
|
|
732
|
+
deferZeroInputFailurePresentation
|
|
733
|
+
});
|
|
734
|
+
return {
|
|
735
|
+
outcome: "handled",
|
|
736
|
+
terminalInput,
|
|
737
|
+
enterDispatched: progress.enterDispatchedAt !== undefined,
|
|
738
|
+
failure: error
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
async function runTerminalControlSendWithinContext(request) {
|
|
743
|
+
const { transaction, recordMessageAfterSend = false, onTerminalPreflightVerified, deferredCodexForegroundBinding, deferZeroInputFailurePresentation = false } = request;
|
|
744
|
+
let prepared;
|
|
745
|
+
try {
|
|
746
|
+
prepared = await dispatchTransportRuntime().prepare(request, dispatchTransportRuntime().preparationPorts, dispatchTransportRuntime().defaults);
|
|
747
|
+
}
|
|
748
|
+
catch (error) {
|
|
749
|
+
if (deferZeroInputFailurePresentation) {
|
|
750
|
+
return { outcome: "zero_input", failure: error };
|
|
751
|
+
}
|
|
752
|
+
throw error;
|
|
753
|
+
}
|
|
754
|
+
if (!prepared) {
|
|
755
|
+
return { outcome: "replayed" };
|
|
756
|
+
}
|
|
757
|
+
const { route, presentationContext, presentationPorts } = prepared;
|
|
758
|
+
let deferredForegroundScope;
|
|
759
|
+
// A newly discovered raw terminal may not have an authoritative Session
|
|
760
|
+
// yet. Commit that Session only after every pre-input terminal and native
|
|
761
|
+
// acceptance check has passed, but before the Turn or dispatch ledger can
|
|
762
|
+
// become durable. This prevents a failed virgin attach from leaving a
|
|
763
|
+
// zero-identity `bound` Session that fences every later control action.
|
|
764
|
+
let dispatch;
|
|
765
|
+
try {
|
|
766
|
+
deferredForegroundScope = deferredCodexForegroundBinding
|
|
767
|
+
? bindDeferredForegroundApplicationScope(transaction.scopes, transaction.resources)
|
|
768
|
+
: undefined;
|
|
769
|
+
if (deferredCodexForegroundBinding) {
|
|
770
|
+
deferredForegroundScope?.assertBoundary(deferredForegroundBoundaryProjection(deferredCodexForegroundBinding));
|
|
771
|
+
}
|
|
772
|
+
const preTransportRollback = await onTerminalPreflightVerified?.(route);
|
|
773
|
+
const rollback = terminalDispatchRollbackRepositories({
|
|
774
|
+
request,
|
|
775
|
+
prepared,
|
|
776
|
+
deferredForegroundScope,
|
|
777
|
+
preTransportRollback: typeof preTransportRollback === "function"
|
|
778
|
+
? preTransportRollback
|
|
779
|
+
: undefined
|
|
780
|
+
});
|
|
781
|
+
dispatch = createTerminalDispatchRuntime(request, prepared, rollback);
|
|
782
|
+
}
|
|
783
|
+
catch (error) {
|
|
784
|
+
if (deferZeroInputFailurePresentation) {
|
|
785
|
+
return { outcome: "zero_input", failure: error };
|
|
786
|
+
}
|
|
787
|
+
throw error;
|
|
788
|
+
}
|
|
789
|
+
const { application, progress, recordPostTransportBookkeepingFailure, validatePreparedMessageEvent } = dispatch;
|
|
790
|
+
try {
|
|
791
|
+
// Preserve legacy argument-evaluation priority inside the setup catch:
|
|
792
|
+
// validate once before raw-attach bookkeeping, then let the gated
|
|
793
|
+
// repository consume only this cached immutable event.
|
|
794
|
+
application.recordPreparedBookkeeping(recordMessageAfterSend, cliEnv().AKK_TEST_TERMINAL_SETUP_FAILURE === "1", recordMessageAfterSend
|
|
795
|
+
? validatePreparedMessageEvent
|
|
796
|
+
: undefined);
|
|
797
|
+
}
|
|
798
|
+
catch (error) {
|
|
799
|
+
let aborted;
|
|
800
|
+
try {
|
|
801
|
+
aborted = application.recordZeroInputAbort({
|
|
802
|
+
failureKind: "setup",
|
|
803
|
+
error,
|
|
804
|
+
abortedAt: cliNow().toISOString(),
|
|
805
|
+
injectStatePersistenceFailure: cliEnv().AKK_TEST_ABORTED_STATE_PERSISTENCE_FAILURE === "1"
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
catch (persistenceError) {
|
|
809
|
+
if (!deferZeroInputFailurePresentation)
|
|
810
|
+
throw persistenceError;
|
|
811
|
+
runtimeLog("warn", "terminal_user_explicit_zero_input_abort_unavailable", {
|
|
812
|
+
terminal_target: route.terminalControl.target,
|
|
813
|
+
error: persistenceError instanceof Error
|
|
814
|
+
? persistenceError.message
|
|
815
|
+
: String(persistenceError)
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
if (!deferZeroInputFailurePresentation && aborted) {
|
|
819
|
+
renderTerminalZeroInputAbort(aborted, presentationContext, presentationPorts, undefined);
|
|
820
|
+
}
|
|
821
|
+
return { outcome: "zero_input", failure: error };
|
|
822
|
+
}
|
|
823
|
+
const transport = await runTerminalDispatchTransport({
|
|
824
|
+
request,
|
|
825
|
+
prepared,
|
|
826
|
+
application,
|
|
827
|
+
progress,
|
|
828
|
+
recordPostTransportBookkeepingFailure,
|
|
829
|
+
deferredForegroundScope,
|
|
830
|
+
deferZeroInputFailurePresentation
|
|
831
|
+
});
|
|
832
|
+
if (transport.outcome === "handled") {
|
|
833
|
+
return transport.terminalInput === "zero_input"
|
|
834
|
+
? { outcome: "zero_input", failure: transport.failure }
|
|
835
|
+
: {
|
|
836
|
+
outcome: "input_started",
|
|
837
|
+
enterDispatched: transport.enterDispatched
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
const deliveredConversation = transport.conversation;
|
|
841
|
+
const acceptanceResult = transport.acceptance;
|
|
842
|
+
const bridgeMonitor = transport.bridgeMonitor;
|
|
843
|
+
const nativeAccepted = acceptanceResult?.outcome === "agent_accepted";
|
|
844
|
+
const postSubmissionWarning = application.recordPostSubmissionBookkeeping(deliveredConversation, nativeAccepted, () => cliNow().toISOString());
|
|
845
|
+
if (postSubmissionWarning !== undefined) {
|
|
846
|
+
progress.bookkeepingWarning = postSubmissionWarning;
|
|
847
|
+
}
|
|
848
|
+
presentTerminalCompleted({
|
|
849
|
+
conversation: deliveredConversation,
|
|
850
|
+
acceptance: acceptanceResult,
|
|
851
|
+
monitorPid: bridgeMonitor?.pid,
|
|
852
|
+
bookkeepingWarning: progress.bookkeepingWarning
|
|
853
|
+
}, presentationContext, presentationPorts);
|
|
854
|
+
return { outcome: "input_started", enterDispatched: true };
|
|
855
|
+
}
|
|
856
|
+
export async function runTerminalControlSend(request, dependencies) {
|
|
857
|
+
return dispatchTransportContext.run(dependencies, () => runTerminalControlSendWithinContext(request));
|
|
858
|
+
}
|
|
859
|
+
//# sourceMappingURL=terminal-command-dispatch-transport.js.map
|