@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,786 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { createClaudeThreadLifecycleCandidateProvider } from "./claude-local-transcript-provider.js";
|
|
4
|
+
import { codexLifecycleBehaviorProfile } from "./codex-lifecycle-compatibility.js";
|
|
5
|
+
import { expandHome } from "./cli-command-runtime.js";
|
|
6
|
+
import { isExactNativeThreadId, legacyManagedSessionBindingToken, legacyUnmanagedTerminalBindingToken, managedSessionBindingToken, unmanagedTerminalBindingToken } from "./managed-session.js";
|
|
7
|
+
import { assertNativeThreadHasExclusiveOwnership as assertExclusiveFromQuery, previousCommittedResumeCandidate, resumableNativeThreadCandidates } from "./native-thread-lifecycle-query-service.js";
|
|
8
|
+
import { codexComposerEmpty } from "./native-thread-lifecycle-recovery-adapter.js";
|
|
9
|
+
import { createNativeThreadResumeSnapshot, saveNativeThreadResumeSnapshot } from "./native-thread-resume-snapshot.js";
|
|
10
|
+
import { terminalActionFingerprint } from "./native-thread-resume-snapshot-policy.js";
|
|
11
|
+
import { isSessionSendBlockingStatus, turnIdForConversation } from "./protocol.js";
|
|
12
|
+
import { listManagedSessions, loadNativeThreadTransition } from "./session-store.js";
|
|
13
|
+
import { isExactClaudeNativeInspectionIdleComposer, NativeInspectionSubmissionError } from "./terminal-agent-bridge.js";
|
|
14
|
+
import { terminalControlAliasMatches, selectRootTerminalProcesses, withCodexCompanionFences } from "./terminal-authority-policy.js";
|
|
15
|
+
import { nonBlankString } from "./value-guards.js";
|
|
16
|
+
export function createNativeThreadLifecycleCliAdapter(ports) {
|
|
17
|
+
const app = new NativeThreadLifecycleCliApplication(ports);
|
|
18
|
+
return Object.freeze({
|
|
19
|
+
resolveLifecycleTerminal: (options) => app.resolveLifecycleTerminal(options),
|
|
20
|
+
queryPorts: (options) => app.queryPorts(options),
|
|
21
|
+
assertExclusive: (input) => app.assertExclusive(input),
|
|
22
|
+
currentSnapshot: (options, terminal, settings) => app.currentSnapshot(options, terminal, settings),
|
|
23
|
+
lifecycleBindingTokens: (input) => app.lifecycleBindingTokens(input),
|
|
24
|
+
agentAdapter: (options, agent) => app.agentAdapter(options, agent),
|
|
25
|
+
runList: (options) => app.runList(options),
|
|
26
|
+
runInspect: (options) => app.runInspect(options),
|
|
27
|
+
assertSameInspectionTerminal: (expected, actual, stage) => app.assertSameInspectionTerminal(expected, actual, stage),
|
|
28
|
+
codexLatentClearResumeObservation,
|
|
29
|
+
nativeInspectionComposerEmpty
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
class NativeThreadLifecycleCliApplication {
|
|
33
|
+
ports;
|
|
34
|
+
constructor(ports) {
|
|
35
|
+
this.ports = ports;
|
|
36
|
+
}
|
|
37
|
+
agentAdapter(options, agent) {
|
|
38
|
+
return this.ports.runtime.forOptions(options).createAgentRegistry().require(agent);
|
|
39
|
+
}
|
|
40
|
+
async resolveLifecycleTerminal(options) {
|
|
41
|
+
const terminalId = required(nonBlankString(options.terminal ?? options.conversation ?? options.conversationId), "--terminal is required");
|
|
42
|
+
const terminal = await this.ports.runtime.forOptions(options)
|
|
43
|
+
.createBridge().resolveConversationId(terminalId);
|
|
44
|
+
if (!terminal || terminal.conversationId !== terminalId) {
|
|
45
|
+
throw new Error("native thread lifecycle requires the exact terminal_id returned by AKK list");
|
|
46
|
+
}
|
|
47
|
+
return terminal;
|
|
48
|
+
}
|
|
49
|
+
lifecycleBindingTokens(input) {
|
|
50
|
+
const { session, terminal, identity } = input;
|
|
51
|
+
const current = this.lifecycleBindingToken(input);
|
|
52
|
+
const incarnation = terminal.agent === "codex" && !identity
|
|
53
|
+
? this.ports.identity.processIncarnation(terminal.pid)
|
|
54
|
+
: undefined;
|
|
55
|
+
const tokenInput = {
|
|
56
|
+
terminalId: terminal.conversationId,
|
|
57
|
+
terminalControl: terminal.terminalControl,
|
|
58
|
+
agent: terminal.agent,
|
|
59
|
+
pid: terminal.pid,
|
|
60
|
+
workspace: terminal.terminalControl.currentPath ?? this.ports.output.cwd(),
|
|
61
|
+
nativeThreadId: identity?.sessionId,
|
|
62
|
+
processUuid: identity?.processUuid ?? incarnation?.processUuid,
|
|
63
|
+
processBirth: identity?.processBirth ?? incarnation?.processBirth,
|
|
64
|
+
rollout: identity?.rollout
|
|
65
|
+
};
|
|
66
|
+
const legacy = session
|
|
67
|
+
? legacyManagedSessionBindingToken(session)
|
|
68
|
+
: legacyUnmanagedTerminalBindingToken(tokenInput);
|
|
69
|
+
return [...new Set([current, legacy])];
|
|
70
|
+
}
|
|
71
|
+
lifecycleBindingToken(input) {
|
|
72
|
+
if (input.session)
|
|
73
|
+
return managedSessionBindingToken(input.session);
|
|
74
|
+
const incarnation = input.terminal.agent === "codex" && !input.identity
|
|
75
|
+
? this.ports.identity.processIncarnation(input.terminal.pid)
|
|
76
|
+
: undefined;
|
|
77
|
+
return unmanagedTerminalBindingToken({
|
|
78
|
+
terminalId: input.terminal.conversationId,
|
|
79
|
+
terminalControl: input.terminal.terminalControl,
|
|
80
|
+
agent: input.terminal.agent,
|
|
81
|
+
pid: input.terminal.pid,
|
|
82
|
+
workspace: input.terminal.terminalControl.currentPath ??
|
|
83
|
+
this.ports.output.cwd(),
|
|
84
|
+
nativeThreadId: input.identity?.sessionId,
|
|
85
|
+
processUuid: input.identity?.processUuid ?? incarnation?.processUuid,
|
|
86
|
+
processBirth: input.identity?.processBirth ?? incarnation?.processBirth,
|
|
87
|
+
rollout: input.identity?.rollout
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
queryPorts(options) {
|
|
91
|
+
let resolvedStoreDir;
|
|
92
|
+
const storeDir = () => resolvedStoreDir ??=
|
|
93
|
+
this.ports.state.storeDir(options);
|
|
94
|
+
return Object.freeze({
|
|
95
|
+
cwd: this.ports.output.cwd,
|
|
96
|
+
listManagedSessions: () => listManagedSessions(storeDir()),
|
|
97
|
+
loadNativeThreadTransition: (id) => loadNativeThreadTransition(storeDir(), id),
|
|
98
|
+
blockingTurns: (sessionId) => this.ports.state
|
|
99
|
+
.managedTurns(storeDir(), sessionId)
|
|
100
|
+
.filter((turn) => isSessionSendBlockingStatus(turn.status))
|
|
101
|
+
.map((turn) => ({ turnId: turnIdForConversation(turn), status: turn.status })),
|
|
102
|
+
assertStoreAuthority: (terminalControl, nativeThreadId) => this.ports.state.assertNativeThreadStoreAuthority({
|
|
103
|
+
terminalControl, nativeThreadId, storeDir: storeDir()
|
|
104
|
+
}),
|
|
105
|
+
runningVersion: (terminal) => this.ports.runtime.forOptions(options)
|
|
106
|
+
.agentVersionForRunningProcess(terminal.agent, terminal.pid),
|
|
107
|
+
candidateProvider: (agent) => agent === "codex"
|
|
108
|
+
? this.ports.runtime.forOptions(options)
|
|
109
|
+
.createThreadLifecycleCandidateProvider(agent)
|
|
110
|
+
: createClaudeThreadLifecycleCandidateProvider({
|
|
111
|
+
claudeHome: expandHome(nonBlankString(options.claudeHome))
|
|
112
|
+
}),
|
|
113
|
+
sessionOwnerIsConclusivelyInactive: (session, terminal, identity) => this.ports.identity.ownerIsInactive({ session, terminal, identity }),
|
|
114
|
+
rootActiveProcesses: (agent) => this.rootActiveProcesses(options, agent),
|
|
115
|
+
resolveProcessIdentity: (agent, pid, cwd) => this.ports.identity.resolveCurrent({ options, agent, pid, cwd }),
|
|
116
|
+
loadClaudeAgentRows: () => this.ports.runtime.forOptions(options)
|
|
117
|
+
.loadClaudeAgentRows({ required: true }),
|
|
118
|
+
workspaceRelationship: verifiedWorkspaceRelationship
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
async rootActiveProcesses(options, agent) {
|
|
122
|
+
const runtime = this.ports.runtime.forOptions(options);
|
|
123
|
+
const adapter = runtime.createAgentRegistry().require(agent);
|
|
124
|
+
const snapshots = await runtime.createProcessSource().listProcessSnapshots((snapshot) => adapter.classifyProcess(snapshot) !== undefined, { includeCwd: true, includeAncestors: true });
|
|
125
|
+
const processes = snapshots.flatMap((snapshot) => {
|
|
126
|
+
const classified = adapter.classifyProcess(snapshot);
|
|
127
|
+
return classified ? [{ ...classified, agent }] : [];
|
|
128
|
+
});
|
|
129
|
+
return selectRootTerminalProcesses(processes);
|
|
130
|
+
}
|
|
131
|
+
async assertExclusive(input) {
|
|
132
|
+
await assertExclusiveFromQuery({
|
|
133
|
+
terminalControl: input.terminalControl,
|
|
134
|
+
agent: input.agent,
|
|
135
|
+
currentPid: input.currentPid,
|
|
136
|
+
nativeThreadId: input.nativeThreadId,
|
|
137
|
+
excludedManagedSessionId: input.excludedManagedSessionId,
|
|
138
|
+
allowedManagedSessionIds: input.allowedManagedSessionIds
|
|
139
|
+
}, this.queryPorts({ ...input.options, storeDir: input.storeDir }));
|
|
140
|
+
}
|
|
141
|
+
async currentSnapshot(options, terminal, { materialize = false } = {}) {
|
|
142
|
+
const storeDir = this.ports.state.storeDir(options);
|
|
143
|
+
const context = terminal.agent === "codex"
|
|
144
|
+
? this.ports.identity.managedContext({ storeDir, terminal })
|
|
145
|
+
: undefined;
|
|
146
|
+
const claimedCompanions = context?.companions ?? { additional: [] };
|
|
147
|
+
const observedIdentity = await this.ports.identity.resolveCurrent({
|
|
148
|
+
options, agent: terminal.agent, pid: terminal.pid,
|
|
149
|
+
cwd: terminal.terminalControl.currentPath,
|
|
150
|
+
preferredSessionId: context?.preferredSessionId,
|
|
151
|
+
allowedCompanionIdentity: claimedCompanions.primary,
|
|
152
|
+
allowedAdditionalIdentities: claimedCompanions.additional
|
|
153
|
+
});
|
|
154
|
+
const initialSession = materialize
|
|
155
|
+
? this.ports.identity.materializeSession({ options, terminal,
|
|
156
|
+
identity: observedIdentity })
|
|
157
|
+
: this.ports.identity.boundSession({ storeDir, terminal,
|
|
158
|
+
identity: observedIdentity });
|
|
159
|
+
const resolved = this.resolveSnapshotIdentity({
|
|
160
|
+
storeDir, terminal, observedIdentity, session: initialSession, materialize
|
|
161
|
+
});
|
|
162
|
+
const codexCompanions = terminal.agent === "codex" && resolved.session
|
|
163
|
+
? this.ports.identity.companionSet({
|
|
164
|
+
storeDir, session: resolved.session
|
|
165
|
+
})
|
|
166
|
+
: claimedCompanions;
|
|
167
|
+
if (materialize && resolved.identity?.sessionId) {
|
|
168
|
+
await this.assertExclusive({
|
|
169
|
+
options, agent: terminal.agent, currentPid: terminal.pid,
|
|
170
|
+
nativeThreadId: resolved.identity.sessionId, storeDir,
|
|
171
|
+
terminalControl: terminal.terminalControl,
|
|
172
|
+
excludedManagedSessionId: resolved.session?.session_id
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
return this.snapshotFacts({
|
|
176
|
+
options, terminal, observedIdentity, session: resolved.session,
|
|
177
|
+
identity: resolved.identity, codexCompanions
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
resolveSnapshotIdentity(input) {
|
|
181
|
+
let session = input.session;
|
|
182
|
+
let identity = session ? this.ports.identity.logicalIdentity({
|
|
183
|
+
storeDir: input.storeDir, session, observedIdentity: input.observedIdentity
|
|
184
|
+
}) : input.observedIdentity;
|
|
185
|
+
if (input.materialize && session) {
|
|
186
|
+
session = this.ports.identity.refineSession({
|
|
187
|
+
storeDir: input.storeDir, session,
|
|
188
|
+
terminalControl: input.terminal.terminalControl, identity
|
|
189
|
+
});
|
|
190
|
+
identity = this.ports.identity.logicalIdentity({
|
|
191
|
+
storeDir: input.storeDir, session, observedIdentity: input.observedIdentity
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
return { session, identity };
|
|
195
|
+
}
|
|
196
|
+
snapshotFacts(input) {
|
|
197
|
+
const version = this.ports.runtime.forOptions(input.options)
|
|
198
|
+
.agentVersionForRunningProcess(input.terminal.agent, input.terminal.pid);
|
|
199
|
+
const adapter = this.agentAdapter(input.options, input.terminal.agent);
|
|
200
|
+
const capabilities = adapter.probeThreadLifecycle?.(version) ?? {
|
|
201
|
+
status: "unsupported", agentVersion: version, newThread: false,
|
|
202
|
+
resumeExact: false,
|
|
203
|
+
reason: `${adapter.displayName} has no native-thread lifecycle adapter`
|
|
204
|
+
};
|
|
205
|
+
const bindingTokens = this.lifecycleBindingTokens({
|
|
206
|
+
session: input.session, terminal: input.terminal, identity: input.identity
|
|
207
|
+
});
|
|
208
|
+
return Object.freeze({
|
|
209
|
+
identity: input.identity, runtimeIdentity: input.observedIdentity,
|
|
210
|
+
codexCompanions: input.codexCompanions,
|
|
211
|
+
session: input.session, version, capabilities,
|
|
212
|
+
bindingToken: bindingTokens[0], bindingTokens
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
async runList(options) {
|
|
216
|
+
const terminal = await this.resolveLifecycleTerminal(options);
|
|
217
|
+
const snapshot = await this.currentSnapshot(options, terminal);
|
|
218
|
+
if (snapshot.capabilities.status !== "supported" ||
|
|
219
|
+
snapshot.capabilities.resumeExact !== true) {
|
|
220
|
+
throw new Error(snapshot.capabilities.reason);
|
|
221
|
+
}
|
|
222
|
+
const queryPorts = this.queryPorts(options);
|
|
223
|
+
const candidates = await resumableNativeThreadCandidates({
|
|
224
|
+
terminal, currentIdentity: snapshot.identity
|
|
225
|
+
}, queryPorts);
|
|
226
|
+
const storeDir = this.ports.state.storeDir(options);
|
|
227
|
+
const workspace = path.resolve(terminal.terminalControl.currentPath ?? this.ports.output.cwd());
|
|
228
|
+
const resumeSnapshot = createNativeThreadResumeSnapshot({
|
|
229
|
+
storeDir,
|
|
230
|
+
selectionScope: nonBlankString(options.selectionScope) ?? "cli:unscoped",
|
|
231
|
+
terminalId: terminal.conversationId,
|
|
232
|
+
agent: terminal.agent,
|
|
233
|
+
workspace,
|
|
234
|
+
terminalControl: terminal.terminalControl,
|
|
235
|
+
currentSessionId: snapshot.session?.session_id,
|
|
236
|
+
currentNativeThreadId: snapshot.identity?.sessionId ??
|
|
237
|
+
snapshot.session?.binding?.native_thread_id,
|
|
238
|
+
expectedBindingToken: snapshot.bindingToken,
|
|
239
|
+
terminalActionFingerprint: terminalActionFingerprint(this.ports.state.loadLedger(terminal.terminalControl)),
|
|
240
|
+
candidates
|
|
241
|
+
});
|
|
242
|
+
saveNativeThreadResumeSnapshot(this.ports.state.runtimeDir(), storeDir, resumeSnapshot);
|
|
243
|
+
const previous = previousCommittedResumeCandidate({
|
|
244
|
+
terminal, currentSession: snapshot.session, candidates
|
|
245
|
+
}, this.queryPorts({ ...options, storeDir }));
|
|
246
|
+
this.ports.output.print(this.listResult({
|
|
247
|
+
terminal, snapshot, candidates, resumeSnapshot, previous, workspace
|
|
248
|
+
}));
|
|
249
|
+
}
|
|
250
|
+
listResult(input) {
|
|
251
|
+
const rows = new Map(input.resumeSnapshot.rows.map((row) => [row.native_thread_id, row]));
|
|
252
|
+
const action = (candidate) => ({
|
|
253
|
+
tool: "agent_knock_knock_resume_thread",
|
|
254
|
+
arguments: {
|
|
255
|
+
terminal_id: input.terminal.conversationId,
|
|
256
|
+
native_thread_id: candidate.native_thread_id,
|
|
257
|
+
expected_binding_token: input.snapshot.bindingToken,
|
|
258
|
+
...(candidate.candidate_token
|
|
259
|
+
? { candidate_token: candidate.candidate_token }
|
|
260
|
+
: {})
|
|
261
|
+
},
|
|
262
|
+
requires_user_intent: true
|
|
263
|
+
});
|
|
264
|
+
const previousRow = input.previous
|
|
265
|
+
? rows.get(input.previous.native_thread_id)
|
|
266
|
+
: undefined;
|
|
267
|
+
return {
|
|
268
|
+
terminal_id: input.terminal.conversationId,
|
|
269
|
+
agent: input.terminal.agent,
|
|
270
|
+
workspace: input.workspace,
|
|
271
|
+
current_session_id: input.snapshot.session?.session_id ?? null,
|
|
272
|
+
current_native_thread_id: input.snapshot.identity?.sessionId ??
|
|
273
|
+
input.snapshot.session?.binding?.native_thread_id ?? null,
|
|
274
|
+
expected_binding_token: input.snapshot.bindingToken,
|
|
275
|
+
capability: input.snapshot.capabilities,
|
|
276
|
+
selection_snapshot: {
|
|
277
|
+
schema: input.resumeSnapshot.schema,
|
|
278
|
+
version: input.resumeSnapshot.version,
|
|
279
|
+
snapshot_id: input.resumeSnapshot.snapshot_id,
|
|
280
|
+
created_at: input.resumeSnapshot.created_at,
|
|
281
|
+
expires_at: input.resumeSnapshot.expires_at,
|
|
282
|
+
scope: "exact selection snapshot, scope, and terminal",
|
|
283
|
+
display_only: true
|
|
284
|
+
},
|
|
285
|
+
...(input.previous && previousRow ? { previous: {
|
|
286
|
+
keyword: "previous",
|
|
287
|
+
native_thread_id: input.previous.native_thread_id,
|
|
288
|
+
selection_number: previousRow.selection_number,
|
|
289
|
+
short_id: previousRow.short_id,
|
|
290
|
+
selection_handle: previousRow.selection_handle,
|
|
291
|
+
available_actions: { resume_thread: action(input.previous) }
|
|
292
|
+
} } : {}),
|
|
293
|
+
threads: input.candidates.map((candidate) => ({
|
|
294
|
+
...candidate,
|
|
295
|
+
selection_number: rows.get(candidate.native_thread_id)?.selection_number,
|
|
296
|
+
short_id: rows.get(candidate.native_thread_id)?.short_id,
|
|
297
|
+
selection_handle: rows.get(candidate.native_thread_id)?.selection_handle,
|
|
298
|
+
selection_scope: "current_snapshot",
|
|
299
|
+
available_actions: candidate.resumable
|
|
300
|
+
? { resume_thread: action(candidate) }
|
|
301
|
+
: {}
|
|
302
|
+
}))
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
assertSameInspectionTerminal(expected, actual, stage) {
|
|
306
|
+
const expectedPath = expected.terminalControl.currentPath;
|
|
307
|
+
const actualPath = actual.terminalControl.currentPath;
|
|
308
|
+
if (actual.agent !== expected.agent || actual.pid !== expected.pid ||
|
|
309
|
+
!terminalControlAliasMatches(expected.conversationId, expected.terminalControl, actual.conversationId, actual.terminalControl) || !expectedPath || !actualPath ||
|
|
310
|
+
path.resolve(actualPath) !== path.resolve(expectedPath)) {
|
|
311
|
+
throw new Error(`terminal identity, pane, or cwd changed ${stage}; refresh AKK list`);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
assertInspectionReady(input) {
|
|
315
|
+
const { options, terminal, terminalStatus, session } = input;
|
|
316
|
+
if (terminalStatus && (terminalStatus.reachable !== true ||
|
|
317
|
+
terminalStatus.activity_state !== "idle" ||
|
|
318
|
+
terminalStatus.approval_state.blocked === true)) {
|
|
319
|
+
throw new Error(`terminal ${terminal.terminalControl.target} is not at a verified idle prompt ` +
|
|
320
|
+
`(${terminalStatus.activity_state}: ${terminalStatus.activity_reason})`);
|
|
321
|
+
}
|
|
322
|
+
const storeDir = this.ports.state.storeDir(options);
|
|
323
|
+
const blocker = this.ports.state.terminalBlockingTurns(storeDir, terminal.terminalControl)[0];
|
|
324
|
+
if (blocker) {
|
|
325
|
+
throw new Error(`terminal ${terminal.terminalControl.target} still has unresolved Turn ` +
|
|
326
|
+
`${turnIdForConversation(blocker)} (${blocker.status})`);
|
|
327
|
+
}
|
|
328
|
+
if (session && this.ports.state.hasUnresolvedTransition(storeDir, session)) {
|
|
329
|
+
throw new Error(`managed Session ${session.session_id} has an unresolved native-thread transition`);
|
|
330
|
+
}
|
|
331
|
+
if (this.ports.state.dispatchOwnership(terminal.terminalControl).state !== "none") {
|
|
332
|
+
throw new Error(`terminal ${terminal.terminalControl.target} has unresolved dispatch ` +
|
|
333
|
+
"ownership; resolve it before native inspection");
|
|
334
|
+
}
|
|
335
|
+
const orphaned = this.ports.state.orphanedForRecovery(terminal.terminalControl);
|
|
336
|
+
if (orphaned) {
|
|
337
|
+
throw new Error(`terminal ${terminal.terminalControl.target} has unresolved ` +
|
|
338
|
+
`${String(orphaned.kind ?? "terminal")} input ` +
|
|
339
|
+
`(${String(orphaned.status ?? "unknown")})`);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
inspectionRuntime(terminal, snapshot) {
|
|
343
|
+
if (terminal.agent === "claude") {
|
|
344
|
+
const identity = snapshot.runtimeIdentity;
|
|
345
|
+
if (!identity?.sessionId || !identity.processUuid ||
|
|
346
|
+
identity.sessionId !== snapshot.identity?.sessionId) {
|
|
347
|
+
throw new Error("Claude native status inspection requires one exact claude agents Session and process incarnation");
|
|
348
|
+
}
|
|
349
|
+
return {
|
|
350
|
+
...this.ports.identity.runtimeForLiveIdentity({ terminal, identity }),
|
|
351
|
+
requireExactClaudeAgentRow: true,
|
|
352
|
+
nativeProcessStartedAt: identity.processStartedAt,
|
|
353
|
+
exactClaudeAgentState: "idle"
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
const exactIdentity = snapshot.runtimeIdentity?.sessionId ===
|
|
357
|
+
snapshot.identity?.sessionId ? snapshot.runtimeIdentity : undefined;
|
|
358
|
+
const runtime = exactIdentity
|
|
359
|
+
? this.ports.identity.runtimeForLiveIdentity({ terminal,
|
|
360
|
+
identity: exactIdentity })
|
|
361
|
+
: {
|
|
362
|
+
...this.ports.identity.runtimeForLiveIdentity({
|
|
363
|
+
terminal, expectedEmptyNativeSession: true
|
|
364
|
+
}),
|
|
365
|
+
...(snapshot.identity?.processUuid
|
|
366
|
+
? { nativeProcessUuid: snapshot.identity.processUuid } : {}),
|
|
367
|
+
...(snapshot.identity?.processBirth
|
|
368
|
+
? { nativeProcessBirth: snapshot.identity.processBirth } : {}),
|
|
369
|
+
...(snapshot.identity?.sessionId
|
|
370
|
+
? { expectedNativeSessionId: snapshot.identity.sessionId } : {})
|
|
371
|
+
};
|
|
372
|
+
return withCodexCompanionFences(runtime, snapshot.codexCompanions);
|
|
373
|
+
}
|
|
374
|
+
assertInspectionAgentIdentity(input) {
|
|
375
|
+
const { options, terminal, snapshot, stage } = input;
|
|
376
|
+
if (terminal.agent !== "claude")
|
|
377
|
+
return;
|
|
378
|
+
const identity = snapshot.runtimeIdentity;
|
|
379
|
+
if (!identity?.sessionId || !identity.processUuid ||
|
|
380
|
+
!Number.isSafeInteger(identity.processStartedAt) ||
|
|
381
|
+
Number(identity.processStartedAt) <= 0) {
|
|
382
|
+
throw new Error(`Claude process identity is incomplete ${stage}; refresh AKK list`);
|
|
383
|
+
}
|
|
384
|
+
const runtime = this.ports.runtime.forOptions(options);
|
|
385
|
+
const agentRows = runtime.loadClaudeAgentRows({ required: true });
|
|
386
|
+
const observation = runtime.createAgentRegistry().require("claude")
|
|
387
|
+
.observeThreadLifecycle?.({
|
|
388
|
+
operation: { kind: "new_thread" }, phase: "before", pid: terminal.pid,
|
|
389
|
+
processStartedAt: identity.processStartedAt,
|
|
390
|
+
cwd: terminal.terminalControl.currentPath, agentRows
|
|
391
|
+
});
|
|
392
|
+
const exactRows = agentRows.filter((row) => row.pid === terminal.pid);
|
|
393
|
+
const stateMatches = (input.expectedClaudeState ?? "idle") === "idle"
|
|
394
|
+
? observation?.idle === true
|
|
395
|
+
: observation?.idle === false && exactRows.length === 1 &&
|
|
396
|
+
exactRows[0].status === "waiting" &&
|
|
397
|
+
exactRows[0].waitingFor === "dialog open";
|
|
398
|
+
if (observation?.status !== "observed" || !stateMatches ||
|
|
399
|
+
observation.nativeThreadId !== identity.sessionId) {
|
|
400
|
+
throw new Error(`Claude agents identity, cwd, or idle state changed ${stage}; refresh AKK list`);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
assertInspectionSnapshotUnchanged(input) {
|
|
404
|
+
this.assertSameInspectionTerminal(input.expectedTerminal, input.actualTerminal, input.stage);
|
|
405
|
+
if (!input.actualSnapshot.bindingTokens.includes(input.expectedBindingToken)) {
|
|
406
|
+
throw new Error(`terminal binding changed ${input.stage}; refresh AKK list`);
|
|
407
|
+
}
|
|
408
|
+
if (input.actualSnapshot.version !== input.expectedVersion) {
|
|
409
|
+
throw new Error(`coding-agent version changed ${input.stage}; refresh AKK list`);
|
|
410
|
+
}
|
|
411
|
+
const capability = this.agentAdapter(input.options, input.actualTerminal.agent).probeNativeInspection?.(input.actualSnapshot.version);
|
|
412
|
+
if (capability?.status !== "supported" ||
|
|
413
|
+
capability.statusInspection !== true) {
|
|
414
|
+
throw new Error(capability?.reason ??
|
|
415
|
+
"native status inspection became unsupported; refresh AKK list");
|
|
416
|
+
}
|
|
417
|
+
this.assertInspectionAgentIdentity({
|
|
418
|
+
options: input.options, terminal: input.actualTerminal,
|
|
419
|
+
snapshot: input.actualSnapshot, stage: input.stage,
|
|
420
|
+
expectedClaudeState: input.expectedClaudeState
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
async assertInspectionExclusive(input) {
|
|
424
|
+
if (input.terminal.agent !== "claude")
|
|
425
|
+
return;
|
|
426
|
+
const nativeThreadId = input.snapshot.identity?.sessionId ??
|
|
427
|
+
input.snapshot.session?.binding?.native_thread_id;
|
|
428
|
+
if (!isExactNativeThreadId(nativeThreadId)) {
|
|
429
|
+
throw new Error("native status inspection requires one exact current native Session identity");
|
|
430
|
+
}
|
|
431
|
+
await this.assertExclusive({
|
|
432
|
+
options: input.options, agent: input.terminal.agent,
|
|
433
|
+
currentPid: input.terminal.pid, nativeThreadId,
|
|
434
|
+
storeDir: this.ports.state.storeDir(input.options),
|
|
435
|
+
terminalControl: input.terminal.terminalControl,
|
|
436
|
+
excludedManagedSessionId: input.snapshot.session?.session_id
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
async assertInspectionComposerReady(input) {
|
|
440
|
+
if (input.terminal.agent === "codex") {
|
|
441
|
+
await this.ports.identity.assertCodexComposerReady({
|
|
442
|
+
options: input.options,
|
|
443
|
+
terminalControl: input.terminal.terminalControl
|
|
444
|
+
});
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
const provider = this.ports.runtime.forOptions(input.options)
|
|
448
|
+
.createControlProvider();
|
|
449
|
+
const resolved = await provider.resolve(provider.endpoint(input.terminal.terminalControl));
|
|
450
|
+
const screen = await provider.capture(resolved, { scrollbackLines: 40 });
|
|
451
|
+
if (!isExactClaudeNativeInspectionIdleComposer(screen)) {
|
|
452
|
+
throw new Error("Claude composer contains input or is not at the exact idle frame; refusing automated terminal input");
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
validateInspectionOptions(options) {
|
|
456
|
+
const inspection = required(nonBlankString(options.inspection), "--inspection is required");
|
|
457
|
+
if (inspection !== "status") {
|
|
458
|
+
throw new Error("--inspection must be the closed value status; arbitrary native slash commands are not accepted");
|
|
459
|
+
}
|
|
460
|
+
if (options.command !== undefined || options.message !== undefined) {
|
|
461
|
+
throw new Error("native inspection does not accept a command or message payload");
|
|
462
|
+
}
|
|
463
|
+
return required(nonBlankString(options.expectedBindingToken), "--expected-binding-token is required");
|
|
464
|
+
}
|
|
465
|
+
async runInspect(options) {
|
|
466
|
+
const expectedBindingToken = this.validateInspectionOptions(options);
|
|
467
|
+
const storeDir = this.ports.state.storeDir(options);
|
|
468
|
+
if (this.ports.state.inspectStore(storeDir).writable !== true) {
|
|
469
|
+
throw new Error("native inspection requires a compatible AKK Store so binding authority can be verified");
|
|
470
|
+
}
|
|
471
|
+
const initiallyResolved = await this.resolveLifecycleTerminal(options);
|
|
472
|
+
const bridge = this.ports.runtime.forOptions(options).createBridge();
|
|
473
|
+
const release = this.ports.state.acquireTerminal(storeDir, initiallyResolved.terminalControl, { timeoutMs: 30000 });
|
|
474
|
+
try {
|
|
475
|
+
const context = await this.prepareInspection({
|
|
476
|
+
options, initiallyResolved, expectedBindingToken, bridge
|
|
477
|
+
});
|
|
478
|
+
const submission = await this.submitInspection(context);
|
|
479
|
+
try {
|
|
480
|
+
const observed = await this.observeStableInspection(context, submission);
|
|
481
|
+
const dismissal = await this.dismissInspection(context, observed);
|
|
482
|
+
await this.finalizeInspection(context, observed, submission, dismissal);
|
|
483
|
+
}
|
|
484
|
+
catch (error) {
|
|
485
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
486
|
+
if (/do not retry automatically/iu.test(detail))
|
|
487
|
+
throw error;
|
|
488
|
+
throw new Error("native status inspection Enter was dispatched exactly once, but its " +
|
|
489
|
+
`postcondition became uncertain; do not retry automatically: ${detail}`);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
finally {
|
|
493
|
+
release();
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
async prepareInspection(input) {
|
|
497
|
+
const runtimeFacade = this.ports.runtime.forOptions(input.options);
|
|
498
|
+
const bridge = input.bridge;
|
|
499
|
+
const initial = input.initiallyResolved;
|
|
500
|
+
const terminal = await bridge.resolveStoredTerminal(initial.agent, initial.pid, initial.terminalControl, { pid: initial.pid });
|
|
501
|
+
this.assertSameInspectionTerminal(initial, terminal, "while waiting for native-inspection control");
|
|
502
|
+
const snapshot = await this.currentSnapshot(input.options, terminal);
|
|
503
|
+
if (!snapshot.bindingTokens.includes(input.expectedBindingToken)) {
|
|
504
|
+
throw new Error("terminal binding changed after it was listed; refresh AKK list and retry");
|
|
505
|
+
}
|
|
506
|
+
const adapter = runtimeFacade.createAgentRegistry().require(terminal.agent);
|
|
507
|
+
const capability = adapter.probeNativeInspection?.(snapshot.version);
|
|
508
|
+
if (capability?.status !== "supported" ||
|
|
509
|
+
capability.statusInspection !== true) {
|
|
510
|
+
throw new Error(capability?.reason ??
|
|
511
|
+
"native status inspection is unavailable for this agent version");
|
|
512
|
+
}
|
|
513
|
+
const plan = adapter.planNativeInspection?.({ kind: "status" }, capability);
|
|
514
|
+
if (!plan || plan.operation.kind !== "status" || plan.command !== "/status" ||
|
|
515
|
+
plan.effect !== "read_only") {
|
|
516
|
+
throw new Error("the agent adapter did not produce the closed native status inspection plan");
|
|
517
|
+
}
|
|
518
|
+
const inspectionRuntime = await this.assertInitialInspectionReady(input.options, terminal, snapshot, bridge);
|
|
519
|
+
return {
|
|
520
|
+
options: input.options, terminal, snapshot, bridge, plan,
|
|
521
|
+
runtime: inspectionRuntime,
|
|
522
|
+
expectedBindingToken: input.expectedBindingToken
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
async assertInitialInspectionReady(options, terminal, snapshot, bridge) {
|
|
526
|
+
this.assertInspectionAgentIdentity({
|
|
527
|
+
options, terminal, snapshot, stage: "before native status inspection"
|
|
528
|
+
});
|
|
529
|
+
await this.assertInspectionExclusive({ options, terminal, snapshot });
|
|
530
|
+
const runtime = this.inspectionRuntime(terminal, snapshot);
|
|
531
|
+
const status = await bridge.status(terminal.agent, terminal.terminalControl, { runtime });
|
|
532
|
+
this.assertInspectionReady({
|
|
533
|
+
options, terminal, terminalStatus: status, session: snapshot.session
|
|
534
|
+
});
|
|
535
|
+
await this.assertInspectionComposerReady({ options, terminal });
|
|
536
|
+
return runtime;
|
|
537
|
+
}
|
|
538
|
+
async submitInspection(context) {
|
|
539
|
+
try {
|
|
540
|
+
return await context.bridge.submitNativeInspection(context.terminal.agent, context.terminal.terminalControl, context.plan, {
|
|
541
|
+
runtime: context.runtime,
|
|
542
|
+
beforeEnter: async () => {
|
|
543
|
+
const terminal = await context.bridge.resolveStoredTerminal(context.terminal.agent, context.terminal.pid, context.terminal.terminalControl, context.runtime);
|
|
544
|
+
await this.assertFreshInspectionBoundary({
|
|
545
|
+
context, terminal,
|
|
546
|
+
stage: "immediately before native status submission"
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
catch (error) {
|
|
552
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
553
|
+
if (error instanceof NativeInspectionSubmissionError &&
|
|
554
|
+
error.doNotRetry !== true) {
|
|
555
|
+
throw new Error(`native status inspection did not start; refresh AKK list and retry if still desired: ${detail}`);
|
|
556
|
+
}
|
|
557
|
+
throw new Error("native status inspection did not cross a proven completion boundary; " +
|
|
558
|
+
`do not retry automatically: ${detail}`);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
async assertFreshInspectionBoundary(input) {
|
|
562
|
+
const snapshot = await this.currentSnapshot(input.context.options, input.terminal);
|
|
563
|
+
this.assertInspectionSnapshotUnchanged({
|
|
564
|
+
options: input.context.options,
|
|
565
|
+
expectedTerminal: input.context.terminal,
|
|
566
|
+
actualTerminal: input.terminal,
|
|
567
|
+
expectedBindingToken: input.context.expectedBindingToken,
|
|
568
|
+
expectedVersion: input.context.snapshot.version,
|
|
569
|
+
actualSnapshot: snapshot,
|
|
570
|
+
stage: input.stage,
|
|
571
|
+
expectedClaudeState: input.expectedClaudeState
|
|
572
|
+
});
|
|
573
|
+
await this.assertInspectionExclusive({
|
|
574
|
+
options: input.context.options,
|
|
575
|
+
terminal: input.terminal,
|
|
576
|
+
snapshot
|
|
577
|
+
});
|
|
578
|
+
if (input.assertReady !== false) {
|
|
579
|
+
this.assertInspectionReady({
|
|
580
|
+
options: input.context.options,
|
|
581
|
+
terminal: input.terminal,
|
|
582
|
+
session: snapshot.session
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
return snapshot;
|
|
586
|
+
}
|
|
587
|
+
async observeStableInspection(context, submission) {
|
|
588
|
+
const expectedNativeThreadId = context.snapshot.session?.binding?.native_thread_id ??
|
|
589
|
+
context.snapshot.identity?.sessionId;
|
|
590
|
+
const request = {
|
|
591
|
+
operation: context.plan.operation,
|
|
592
|
+
previousScreenFingerprint: submission.preEnterScreenDigest,
|
|
593
|
+
preEnterEvidenceInventory: submission.preEnterEvidenceInventory,
|
|
594
|
+
expectedNativeThreadId,
|
|
595
|
+
expectedAgentVersion: context.snapshot.version,
|
|
596
|
+
expectedCwd: context.terminal.terminalControl.currentPath
|
|
597
|
+
};
|
|
598
|
+
const postEnterRuntime = context.plan.expectedResult.presentation === "modal"
|
|
599
|
+
? { ...context.runtime, exactClaudeAgentState: "status_dialog" }
|
|
600
|
+
: context.runtime;
|
|
601
|
+
let fingerprint;
|
|
602
|
+
let stable;
|
|
603
|
+
let count = 0;
|
|
604
|
+
for (let attempt = 0; attempt < 50; attempt += 1) {
|
|
605
|
+
const observed = await context.bridge.observeNativeInspection(context.terminal.agent, context.terminal.terminalControl, request, { runtime: postEnterRuntime, scrollbackLines: 240 });
|
|
606
|
+
if (freshInspectionObservation(context.plan, submission.preEnterScreenDigest, observed)) {
|
|
607
|
+
if (fingerprint === observed.observation.evidenceFingerprint)
|
|
608
|
+
count += 1;
|
|
609
|
+
else {
|
|
610
|
+
fingerprint = observed.observation.evidenceFingerprint;
|
|
611
|
+
count = 1;
|
|
612
|
+
}
|
|
613
|
+
stable = observed.observation;
|
|
614
|
+
if (count >= 2)
|
|
615
|
+
break;
|
|
616
|
+
}
|
|
617
|
+
else {
|
|
618
|
+
fingerprint = undefined;
|
|
619
|
+
stable = undefined;
|
|
620
|
+
count = 0;
|
|
621
|
+
}
|
|
622
|
+
await this.ports.runtime.sleep(100);
|
|
623
|
+
}
|
|
624
|
+
if (!stable || count < 2) {
|
|
625
|
+
throw new Error("native status inspection Enter was dispatched exactly once, but a fresh exact status result was not proven; do not retry automatically");
|
|
626
|
+
}
|
|
627
|
+
return { observation: stable, request, postEnterRuntime };
|
|
628
|
+
}
|
|
629
|
+
async dismissInspection(context, observed) {
|
|
630
|
+
if (context.plan.expectedResult.presentation !== "modal")
|
|
631
|
+
return undefined;
|
|
632
|
+
const fingerprint = observed.observation.evidenceFingerprint;
|
|
633
|
+
if (!fingerprint) {
|
|
634
|
+
throw new Error("native status modal lacks exact dismissal evidence; do not retry automatically");
|
|
635
|
+
}
|
|
636
|
+
let dismissal;
|
|
637
|
+
try {
|
|
638
|
+
dismissal = await context.bridge.dismissNativeInspection(context.terminal.agent, context.terminal.terminalControl, context.plan, observed.request, fingerprint, {
|
|
639
|
+
runtime: observed.postEnterRuntime,
|
|
640
|
+
scrollbackLines: 240,
|
|
641
|
+
beforeDismiss: async () => {
|
|
642
|
+
const terminal = await context.bridge.resolveStoredTerminal(context.terminal.agent, context.terminal.pid, context.terminal.terminalControl, observed.postEnterRuntime);
|
|
643
|
+
await this.assertFreshInspectionBoundary({
|
|
644
|
+
context, terminal,
|
|
645
|
+
stage: "immediately before native status dismissal",
|
|
646
|
+
expectedClaudeState: "status_dialog"
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
catch (error) {
|
|
652
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
653
|
+
throw new Error("native status panel was proven but safe dismissal failed; " +
|
|
654
|
+
`do not retry automatically and dismiss it manually if still visible: ${detail}`);
|
|
655
|
+
}
|
|
656
|
+
await this.assertInspectionRestoredIdle(context);
|
|
657
|
+
return dismissal;
|
|
658
|
+
}
|
|
659
|
+
async assertInspectionRestoredIdle(context) {
|
|
660
|
+
for (let attempt = 0; attempt < 50; attempt += 1) {
|
|
661
|
+
const status = await context.bridge.status(context.terminal.agent, context.terminal.terminalControl, { runtime: context.runtime });
|
|
662
|
+
if (status.reachable === true && status.activity_state === "idle" &&
|
|
663
|
+
status.approval_state.blocked !== true &&
|
|
664
|
+
nativeInspectionComposerEmpty(context.terminal.agent, status.screen.excerpt))
|
|
665
|
+
return;
|
|
666
|
+
await this.ports.runtime.sleep(100);
|
|
667
|
+
}
|
|
668
|
+
throw new Error("Claude Status panel dismissal was dispatched exactly once, but the original idle composer was not restored; do not retry automatically");
|
|
669
|
+
}
|
|
670
|
+
async finalizeInspection(context, observed, submission, dismissal) {
|
|
671
|
+
const terminal = await context.bridge.resolveStoredTerminal(context.terminal.agent, context.terminal.pid, context.terminal.terminalControl, context.runtime);
|
|
672
|
+
const snapshot = await this.assertFreshInspectionBoundary({
|
|
673
|
+
context, terminal, stage: "after native status inspection",
|
|
674
|
+
assertReady: false
|
|
675
|
+
});
|
|
676
|
+
const status = await context.bridge.status(terminal.agent, terminal.terminalControl, { runtime: context.runtime });
|
|
677
|
+
this.assertInspectionReady({
|
|
678
|
+
options: context.options, terminal, terminalStatus: status,
|
|
679
|
+
session: snapshot.session
|
|
680
|
+
});
|
|
681
|
+
await this.assertInspectionComposerReady({
|
|
682
|
+
options: context.options, terminal
|
|
683
|
+
});
|
|
684
|
+
this.ports.output.print({
|
|
685
|
+
status: "observed",
|
|
686
|
+
inspection: "status",
|
|
687
|
+
terminal_id: context.terminal.conversationId,
|
|
688
|
+
agent: context.terminal.agent,
|
|
689
|
+
agent_version: context.snapshot.version,
|
|
690
|
+
behavior_profile: context.plan.behaviorProfile,
|
|
691
|
+
native_thread_id: observed.observation.nativeThreadId,
|
|
692
|
+
native_status: observed.observation.result,
|
|
693
|
+
terminal_submission: {
|
|
694
|
+
command: context.plan.command,
|
|
695
|
+
enter_count: submission.enterCount,
|
|
696
|
+
materialization: submission.materialization
|
|
697
|
+
},
|
|
698
|
+
...(dismissal ? { terminal_dismissal: {
|
|
699
|
+
keys: dismissal.keys,
|
|
700
|
+
dismiss_count: dismissal.dismissCount,
|
|
701
|
+
restored_idle: true
|
|
702
|
+
} } : {}),
|
|
703
|
+
store_mutation: false,
|
|
704
|
+
session_created: false,
|
|
705
|
+
turn_created: false,
|
|
706
|
+
receipt_created: false,
|
|
707
|
+
monitor_created: false,
|
|
708
|
+
callback_created: false
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
function freshInspectionObservation(plan, preEnterScreenDigest, observed) {
|
|
713
|
+
return observed.status.reachable === true &&
|
|
714
|
+
(plan.expectedResult.presentation === "inline"
|
|
715
|
+
? observed.status.activity_state === "idle"
|
|
716
|
+
: !["working", "awaiting_approval"].includes(observed.status.activity_state)) &&
|
|
717
|
+
observed.status.approval_state.blocked !== true &&
|
|
718
|
+
observed.screenDigest !== preEnterScreenDigest &&
|
|
719
|
+
observed.observation.status === "observed" &&
|
|
720
|
+
observed.observation.result?.kind === "native_status" &&
|
|
721
|
+
isExactNativeThreadId(observed.observation.nativeThreadId) &&
|
|
722
|
+
Boolean(observed.observation.evidenceFingerprint);
|
|
723
|
+
}
|
|
724
|
+
function verifiedWorkspaceRelationship(targetWorkspace, candidateWorkspace) {
|
|
725
|
+
const target = nonBlankString(targetWorkspace);
|
|
726
|
+
const candidate = nonBlankString(candidateWorkspace);
|
|
727
|
+
if (!target || !candidate || !path.isAbsolute(target) ||
|
|
728
|
+
!path.isAbsolute(candidate))
|
|
729
|
+
return "unknown";
|
|
730
|
+
try {
|
|
731
|
+
const targetReal = fs.realpathSync(target);
|
|
732
|
+
const candidateReal = fs.realpathSync(candidate);
|
|
733
|
+
if (!fs.statSync(targetReal).isDirectory() ||
|
|
734
|
+
!fs.statSync(candidateReal).isDirectory())
|
|
735
|
+
return "unknown";
|
|
736
|
+
return targetReal === candidateReal ? "same" : "different";
|
|
737
|
+
}
|
|
738
|
+
catch {
|
|
739
|
+
return "unknown";
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
function codexLatentClearResumeObservation(input) {
|
|
743
|
+
const behaviorProfile = codexLifecycleBehaviorProfile(input.agentVersion);
|
|
744
|
+
if (!behaviorProfile)
|
|
745
|
+
return undefined;
|
|
746
|
+
const clean = (line) => line.replace(/\x1B(?:\[[0-?]*[ -/]*[@-~]|\][^\x07]*(?:\x07|\x1B\\))/gu, "");
|
|
747
|
+
const prefix = /^\s*To continue this session, run codex resume\s+(.+?)\s*$/iu;
|
|
748
|
+
const uuid = /^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/iu;
|
|
749
|
+
const lines = String(input.screen ?? "").split(/\r?\n/u).slice(-24).map(clean);
|
|
750
|
+
const ids = [];
|
|
751
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
752
|
+
const match = prefix.exec(lines[index]);
|
|
753
|
+
if (!match)
|
|
754
|
+
continue;
|
|
755
|
+
const first = match[1].replace(/\s+/gu, "");
|
|
756
|
+
const fragments = [first, ...(first.endsWith("-")
|
|
757
|
+
? [`${match[1]}${lines[index + 1] ?? ""}`.replace(/\s+/gu, "")]
|
|
758
|
+
: [])];
|
|
759
|
+
const id = fragments.flatMap((candidate) => {
|
|
760
|
+
const exact = uuid.exec(candidate);
|
|
761
|
+
return exact ? [exact[1].toLowerCase()] : [];
|
|
762
|
+
})[0];
|
|
763
|
+
if (id)
|
|
764
|
+
ids.push(id);
|
|
765
|
+
}
|
|
766
|
+
const sourceNativeThreadId = ids.at(-1);
|
|
767
|
+
return sourceNativeThreadId ? {
|
|
768
|
+
sourceNativeThreadId,
|
|
769
|
+
fingerprint: terminalActionFingerprint({
|
|
770
|
+
kind: "codex_latent_clear_resume_hint",
|
|
771
|
+
behavior_profile: behaviorProfile,
|
|
772
|
+
source_native_thread_id: sourceNativeThreadId
|
|
773
|
+
})
|
|
774
|
+
} : undefined;
|
|
775
|
+
}
|
|
776
|
+
function nativeInspectionComposerEmpty(agent, screen) {
|
|
777
|
+
return agent === "codex"
|
|
778
|
+
? codexComposerEmpty(screen)
|
|
779
|
+
: isExactClaudeNativeInspectionIdleComposer(String(screen ?? ""));
|
|
780
|
+
}
|
|
781
|
+
function required(value, message) {
|
|
782
|
+
if (value === undefined || value === "")
|
|
783
|
+
throw new Error(message);
|
|
784
|
+
return value;
|
|
785
|
+
}
|
|
786
|
+
//# sourceMappingURL=native-thread-lifecycle-cli-adapter.js.map
|