@scotthuang/agent-knock-knock 0.13.10 → 0.13.12
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 +9 -2
- package/dist/src/codex-app-server-interaction-client.d.ts +72 -0
- package/dist/src/codex-app-server-interaction-client.js +310 -0
- package/dist/src/codex-app-server-interaction-client.js.map +1 -0
- package/dist/src/codex-app-server-questionnaire.d.ts +73 -0
- package/dist/src/codex-app-server-questionnaire.js +366 -0
- package/dist/src/codex-app-server-questionnaire.js.map +1 -0
- package/dist/src/codex-app-server-read-client.d.ts +118 -0
- package/dist/src/codex-app-server-read-client.js +300 -0
- package/dist/src/codex-app-server-read-client.js.map +1 -0
- package/dist/src/codex-app-server-transport.d.ts +11 -0
- package/dist/src/codex-app-server-transport.js +47 -0
- package/dist/src/codex-app-server-transport.js.map +1 -0
- package/dist/src/codex-async-question-adapter.d.ts +5 -0
- package/dist/src/codex-async-question-adapter.js +58 -17
- package/dist/src/codex-async-question-adapter.js.map +1 -1
- package/dist/src/codex-fullscreen-composer-proof.d.ts +23 -0
- package/dist/src/codex-fullscreen-composer-proof.js +124 -0
- package/dist/src/codex-fullscreen-composer-proof.js.map +1 -0
- package/dist/src/codex-lifecycle-compatibility.d.ts +10 -0
- package/dist/src/codex-lifecycle-compatibility.js +30 -3
- package/dist/src/codex-lifecycle-compatibility.js.map +1 -1
- package/dist/src/codex-paginated-answer-proof.d.ts +25 -0
- package/dist/src/codex-paginated-answer-proof.js +189 -0
- package/dist/src/codex-paginated-answer-proof.js.map +1 -0
- package/dist/src/codex-paginated-async-answer.d.ts +36 -0
- package/dist/src/codex-paginated-async-answer.js +321 -0
- package/dist/src/codex-paginated-async-answer.js.map +1 -0
- package/dist/src/codex-paginated-async-response.d.ts +21 -0
- package/dist/src/codex-paginated-async-response.js +116 -0
- package/dist/src/codex-paginated-async-response.js.map +1 -0
- package/dist/src/codex-paginated-observation.d.ts +30 -0
- package/dist/src/codex-paginated-observation.js +139 -0
- package/dist/src/codex-paginated-observation.js.map +1 -0
- package/dist/src/codex-paginated-questionnaire-runtime.d.ts +33 -0
- package/dist/src/codex-paginated-questionnaire-runtime.js +157 -0
- package/dist/src/codex-paginated-questionnaire-runtime.js.map +1 -0
- package/dist/src/codex-paginated-task.d.ts +77 -0
- package/dist/src/codex-paginated-task.js +440 -0
- package/dist/src/codex-paginated-task.js.map +1 -0
- package/dist/src/codex-paginated-thread-binding.d.ts +18 -0
- package/dist/src/codex-paginated-thread-binding.js +55 -0
- package/dist/src/codex-paginated-thread-binding.js.map +1 -0
- package/dist/src/codex-paginated-thread-facts.d.ts +10 -0
- package/dist/src/codex-paginated-thread-facts.js +2 -0
- package/dist/src/codex-paginated-thread-facts.js.map +1 -0
- package/dist/src/codex-paginated-watch.d.ts +29 -0
- package/dist/src/codex-paginated-watch.js +107 -0
- package/dist/src/codex-paginated-watch.js.map +1 -0
- package/dist/src/codex-session-provider.d.ts +6 -0
- package/dist/src/codex-session-provider.js +15 -2
- package/dist/src/codex-session-provider.js.map +1 -1
- package/dist/src/codex-store-adapter.d.ts +1 -0
- package/dist/src/codex-store-adapter.js +24 -6
- package/dist/src/codex-store-adapter.js.map +1 -1
- package/dist/src/codex-terminal-agent-adapter.js +53 -2
- package/dist/src/codex-terminal-agent-adapter.js.map +1 -1
- package/dist/src/doctor-capabilities.d.ts +2 -2
- package/dist/src/doctor-capabilities.js +7 -4
- package/dist/src/doctor-capabilities.js.map +1 -1
- package/dist/src/install-doctor-command-adapter.js +1 -1
- package/dist/src/install-doctor-command-adapter.js.map +1 -1
- package/dist/src/native-thread-lifecycle-cli-adapter.js +4 -1
- package/dist/src/native-thread-lifecycle-cli-adapter.js.map +1 -1
- package/dist/src/store.d.ts +1 -1
- package/dist/src/store.js +2 -2
- package/dist/src/store.js.map +1 -1
- package/dist/src/terminal-agent-adapter.d.ts +3 -0
- package/dist/src/terminal-agent-adapter.js.map +1 -1
- package/dist/src/terminal-agent-bridge.d.ts +13 -5
- package/dist/src/terminal-agent-bridge.js +27 -103
- package/dist/src/terminal-agent-bridge.js.map +1 -1
- package/dist/src/terminal-approval-fingerprint.d.ts +7 -0
- package/dist/src/terminal-approval-fingerprint.js +107 -0
- package/dist/src/terminal-approval-fingerprint.js.map +1 -0
- package/dist/src/terminal-command-cli-ports.d.ts +1 -0
- package/dist/src/terminal-command-dispatch-preparation.js +7 -0
- package/dist/src/terminal-command-dispatch-preparation.js.map +1 -1
- package/dist/src/terminal-composer-classifier.js +38 -1
- package/dist/src/terminal-composer-classifier.js.map +1 -1
- package/dist/src/terminal-control-provider.d.ts +6 -2
- package/dist/src/terminal-control-provider.js +4 -4
- package/dist/src/terminal-control-provider.js.map +1 -1
- package/dist/src/terminal-human-explicit-send-cli-adapter.js +22 -15
- package/dist/src/terminal-human-explicit-send-cli-adapter.js.map +1 -1
- package/dist/src/terminal-interaction-core.js +2 -1
- package/dist/src/terminal-interaction-core.js.map +1 -1
- package/dist/src/terminal-interaction-response-bridge.d.ts +21 -1
- package/dist/src/terminal-interaction-response-bridge.js +147 -3
- package/dist/src/terminal-interaction-response-bridge.js.map +1 -1
- package/dist/src/terminal-list-cli-adapter.js +4 -4
- package/dist/src/terminal-list-cli-adapter.js.map +1 -1
- package/dist/src/terminal-list-facts.d.ts +1 -1
- package/dist/src/terminal-list-facts.js +1 -1
- package/dist/src/terminal-list-facts.js.map +1 -1
- package/dist/src/terminal-list-renderer.js +1 -1
- package/dist/src/terminal-list-renderer.js.map +1 -1
- package/dist/src/terminal-managed-send-cli-adapter.d.ts +1 -1
- package/dist/src/terminal-managed-send-cli-adapter.js +27 -0
- package/dist/src/terminal-managed-send-cli-adapter.js.map +1 -1
- package/dist/src/terminal-model-control-bridge.d.ts +1 -1
- package/dist/src/terminal-model-control-bridge.js +1 -1
- package/dist/src/terminal-model-control-bridge.js.map +1 -1
- package/dist/src/terminal-model-control-profile.d.ts +2 -1
- package/dist/src/terminal-model-control-profile.js +24 -1
- package/dist/src/terminal-model-control-profile.js.map +1 -1
- package/dist/src/terminal-model-control.js +61 -21
- package/dist/src/terminal-model-control.js.map +1 -1
- package/dist/src/terminal-native-inspection-bridge.d.ts +6 -1
- package/dist/src/terminal-native-inspection-bridge.js +118 -81
- package/dist/src/terminal-native-inspection-bridge.js.map +1 -1
- package/dist/src/terminal-questionnaire-adapter.js +19 -16
- package/dist/src/terminal-questionnaire-adapter.js.map +1 -1
- package/dist/src/terminal-runtime-cli-adapter.js +16 -0
- package/dist/src/terminal-runtime-cli-adapter.js.map +1 -1
- package/dist/src/terminal-send-watch-policy.d.ts +38 -0
- package/dist/src/terminal-send-watch-policy.js +77 -0
- package/dist/src/terminal-send-watch-policy.js.map +1 -0
- package/dist/src/terminal-submission-acceptance.js +56 -10
- package/dist/src/terminal-submission-acceptance.js.map +1 -1
- package/dist/src/terminal-submission-facts.d.ts +1 -1
- package/dist/src/terminal-submission-facts.js +11 -9
- package/dist/src/terminal-submission-facts.js.map +1 -1
- package/dist/src/terminal-watch-cli-adapter.d.ts +9 -1
- package/dist/src/terminal-watch-cli-adapter.js +198 -210
- package/dist/src/terminal-watch-cli-adapter.js.map +1 -1
- package/dist/src/terminal-watch-codec.js +23 -1
- package/dist/src/terminal-watch-codec.js.map +1 -1
- package/dist/src/terminal-watch-interaction-runtime.js +27 -6
- package/dist/src/terminal-watch-interaction-runtime.js.map +1 -1
- package/dist/src/terminal-watch-presentation.d.ts +4 -0
- package/dist/src/terminal-watch-presentation.js +153 -0
- package/dist/src/terminal-watch-presentation.js.map +1 -0
- package/dist/src/terminal-watch-record.d.ts +4 -2
- package/dist/src/terminal-watch-record.js +15 -10
- package/dist/src/terminal-watch-record.js.map +1 -1
- package/dist/src/terminal-watch-service.js +13 -1
- package/dist/src/terminal-watch-service.js.map +1 -1
- package/docs/codex-0.157.1-compatibility.md +77 -0
- package/docs/codex-0.158.0-compatibility.md +129 -0
- package/docs/quickstart-herdr.md +3 -3
- package/docs/quickstart-tmux.md +4 -4
- package/package.json +7 -3
- package/templates/openclaw-skills/agent-knock-knock/SKILL.md +15 -13
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
import { respondCodexPaginatedAsyncQuestion } from "./codex-paginated-async-response.js";
|
|
2
|
+
import { publicTerminalWatch, terminalWatchCapturedAgentVersion } from "./terminal-watch-presentation.js";
|
|
1
3
|
import { createHash } from "node:crypto";
|
|
2
4
|
import path from "node:path";
|
|
5
|
+
import { CodexLegacyThreadHistoryError } from "./codex-paginated-observation.js";
|
|
6
|
+
import { capturePaginatedWatchAnchor as capturePaginatedAnchor, isPaginatedSendWatch, paginatedWatchProcessMatches, observePaginatedWatch, refreshPaginatedResponseForeground } from "./codex-paginated-watch.js";
|
|
7
|
+
import { observeCodexPaginatedBlockingQuestion, respondCodexPaginatedBlockingQuestion } from "./codex-paginated-questionnaire-runtime.js";
|
|
8
|
+
import { selectCodexUserExplicitSendWatchSource } from "./terminal-send-watch-policy.js";
|
|
3
9
|
import { callbackRouteFingerprint } from "./callback-route-authority.js";
|
|
4
10
|
import { createTerminalWatchOpenClawCallbackRoute, parseCallbackRoute } from "./callback-transport.js";
|
|
5
11
|
import { captureClaudeTranscriptAnchor, captureClaudeHumanStartedActiveTaskAnchor, observeClaudeUserExplicitFallbackTranscript, observeClaudeHumanStartedActiveTask } from "./claude-local-transcript-provider.js";
|
|
6
|
-
import { claudeRuntimeCompatibilityWarning } from "./claude-lifecycle-compatibility.js";
|
|
7
|
-
import { codexRuntimeCompatibilityProfile } from "./codex-lifecycle-compatibility.js";
|
|
8
12
|
import { codexAsyncQuestionMainComposerVisible } from "./codex-async-question-adapter.js";
|
|
9
13
|
import { hostProfileCallbackRouteMatchesRuntime } from "./host-profile-callback-transport.js";
|
|
10
14
|
import { captureTerminalInteractionRuntimeOffer, TerminalInteractionDispatchReservedError, TerminalInteractionInputNotStartedError } from "./terminal-agent-bridge.js";
|
|
@@ -120,46 +124,9 @@ export function createTerminalWatchCliAdapter(dependencies) {
|
|
|
120
124
|
const rawTerminal = observed.rawTerminal;
|
|
121
125
|
assertSameUserExplicitFallbackTerminal(input.terminal, rawTerminal);
|
|
122
126
|
const agentVersion = requiredString(rawTerminal.agent_version, "running coding-agent version");
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const acceptanceAnchor = isRecord(inventory)
|
|
127
|
-
? captureCodexCandidateSetRolloutAcceptanceAnchor({
|
|
128
|
-
inventory: inventory,
|
|
129
|
-
now: dependencies.now()
|
|
130
|
-
})
|
|
131
|
-
: captureCodexRolloutAcceptanceAnchor({
|
|
132
|
-
nativeThreadId: requiredString(rawTerminal.native_agent_session_id, "Codex native thread id"),
|
|
133
|
-
processUuid: requiredString(rawTerminal.native_agent_process_uuid, "Codex process UUID"),
|
|
134
|
-
processBirth: requiredString(rawTerminal.native_agent_process_birth, "Codex process birth"),
|
|
135
|
-
mode: "existing",
|
|
136
|
-
rollout: codexIdentity(rawTerminal).rollout,
|
|
137
|
-
now: dependencies.now()
|
|
138
|
-
});
|
|
139
|
-
anchor = createCodexUserExplicitFallbackWatchAnchor({
|
|
140
|
-
acceptanceAnchor,
|
|
141
|
-
requestHash: input.requestHash,
|
|
142
|
-
codexVersion: agentVersion
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
const transcriptAnchor = captureClaudeTranscriptAnchor({
|
|
147
|
-
sessionId: requiredString(rawTerminal.native_agent_session_id, "Claude native session id"),
|
|
148
|
-
cwd: terminalWorkspace(rawTerminal),
|
|
149
|
-
pid: positiveInteger(rawTerminal.pid, "Claude PID"),
|
|
150
|
-
claudeHome: stringValue(input.options.claudeHome),
|
|
151
|
-
agentRows: dependencies.loadClaudeAgentRows(input.options, { required: true }),
|
|
152
|
-
now: dependencies.now()
|
|
153
|
-
});
|
|
154
|
-
if (!transcriptAnchor) {
|
|
155
|
-
throw new Error("Claude transcript anchor is unavailable before terminal input");
|
|
156
|
-
}
|
|
157
|
-
anchor = createClaudeUserExplicitFallbackWatchAnchor({
|
|
158
|
-
transcriptAnchor,
|
|
159
|
-
requestHash: input.requestHash,
|
|
160
|
-
claudeVersion: agentVersion
|
|
161
|
-
});
|
|
162
|
-
}
|
|
127
|
+
const anchor = input.terminal.agent === "codex"
|
|
128
|
+
? await captureCodexFallbackWatchAnchor(input, rawTerminal, agentVersion, dependencies)
|
|
129
|
+
: captureClaudeFallbackWatchAnchor(input, rawTerminal, agentVersion, dependencies);
|
|
163
130
|
return {
|
|
164
131
|
watchId: terminalUserExplicitFallbackWatchId({
|
|
165
132
|
messageId: input.messageId,
|
|
@@ -217,7 +184,7 @@ export function createTerminalWatchCliAdapter(dependencies) {
|
|
|
217
184
|
catch (error) {
|
|
218
185
|
const existing = service.list().find((candidate) => candidate.watch_id === input.prepared.watchId);
|
|
219
186
|
if (!existing ||
|
|
220
|
-
!isUserExplicitFallbackWatch(existing) ||
|
|
187
|
+
!(isUserExplicitFallbackWatch(existing) || isPaginatedSendWatch(existing)) ||
|
|
221
188
|
existing.anchor.anchor_fingerprint !==
|
|
222
189
|
input.prepared.anchor.anchor_fingerprint) {
|
|
223
190
|
throw error;
|
|
@@ -227,7 +194,9 @@ export function createTerminalWatchCliAdapter(dependencies) {
|
|
|
227
194
|
return {
|
|
228
195
|
callback_expected: true,
|
|
229
196
|
callback_mode: "terminal_watch",
|
|
230
|
-
watch_id: watch.watch_id
|
|
197
|
+
watch_id: watch.watch_id,
|
|
198
|
+
watch_mode: "exact_task",
|
|
199
|
+
confidence: "exact"
|
|
231
200
|
};
|
|
232
201
|
}
|
|
233
202
|
async function bestEffortStabilizePriorFallbackWatch(options, terminalId, requestHash) {
|
|
@@ -254,13 +223,15 @@ export function createTerminalWatchCliAdapter(dependencies) {
|
|
|
254
223
|
function userExplicitFallbackWatchReceipt(input) {
|
|
255
224
|
try {
|
|
256
225
|
const watch = serviceFor(input.options).get(input.watchId);
|
|
257
|
-
if (!isUserExplicitFallbackWatch(watch) || !watch.callback_route) {
|
|
226
|
+
if (!(isUserExplicitFallbackWatch(watch) || isPaginatedSendWatch(watch)) || !watch.callback_route) {
|
|
258
227
|
return undefined;
|
|
259
228
|
}
|
|
260
229
|
return {
|
|
261
230
|
callback_expected: true,
|
|
262
231
|
callback_mode: "terminal_watch",
|
|
263
|
-
watch_id: watch.watch_id
|
|
232
|
+
watch_id: watch.watch_id,
|
|
233
|
+
watch_mode: "exact_task",
|
|
234
|
+
confidence: "exact"
|
|
264
235
|
};
|
|
265
236
|
}
|
|
266
237
|
catch {
|
|
@@ -285,7 +256,9 @@ export function createTerminalWatchCliAdapter(dependencies) {
|
|
|
285
256
|
const warnings = [];
|
|
286
257
|
let anchor;
|
|
287
258
|
try {
|
|
288
|
-
anchor =
|
|
259
|
+
anchor = agent === "codex" && rawTerminal.agent_version === "0.158.0"
|
|
260
|
+
? await capturePaginatedWatchAnchorWithLock(rawTerminal, options, dependencies)
|
|
261
|
+
: captureTerminalWatchAnchor(agent, rawTerminal, options, dependencies);
|
|
289
262
|
}
|
|
290
263
|
catch (error) {
|
|
291
264
|
warnings.push(`exact_task_anchor_unavailable: ${safeDiagnostic(error)}`);
|
|
@@ -481,20 +454,57 @@ function createTerminalWatchInteractionResponder(dependencies, serviceFor) {
|
|
|
481
454
|
if (!bridge) {
|
|
482
455
|
throw new Error("terminal interaction bridge is unavailable");
|
|
483
456
|
}
|
|
457
|
+
if (runtime.codexPaginatedThread && executableInteraction.projection.kind === "async_question") {
|
|
458
|
+
await refreshPaginatedResponseForeground(bridge, terminalControl, runtime, dependencies.now);
|
|
459
|
+
}
|
|
484
460
|
const attemptId = dependencies.randomUUID();
|
|
485
461
|
const responseHash = hashTerminalInteractionResponse(response);
|
|
486
462
|
const reservation = { attemptId, responseHash };
|
|
487
463
|
const result = await executeTerminalInteractionResponseTransaction({
|
|
488
464
|
reservationFailureFence: "confirmed",
|
|
489
|
-
dispatch: (hooks) =>
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
465
|
+
dispatch: (hooks) => "schema" in current.observation_checkpoint &&
|
|
466
|
+
current.observation_checkpoint.schema === "agent-knock-knock/codex-paginated-task-checkpoint" &&
|
|
467
|
+
executableInteraction.projection.kind === "questionnaire"
|
|
468
|
+
? respondCodexPaginatedBlockingQuestion({
|
|
469
|
+
watch: current, checkpoint: current.observation_checkpoint, terminalControl,
|
|
470
|
+
response, expectedFingerprint, now: dependencies.now,
|
|
471
|
+
authorize: hooks.authorize, beforeDispatch: hooks.beforeDispatch,
|
|
472
|
+
persistDraft: (draft) => {
|
|
473
|
+
current = repository.withWriterLease((scope) => scope.withWatchLock(watchId, () => {
|
|
474
|
+
const latest = scope.load(watchId);
|
|
475
|
+
const checkpoint = latest.observation_checkpoint;
|
|
476
|
+
if (!("schema" in checkpoint) || checkpoint.schema !== "agent-knock-knock/codex-paginated-task-checkpoint") {
|
|
477
|
+
throw new Error("Codex blocking question checkpoint changed");
|
|
478
|
+
}
|
|
479
|
+
const nextCheckpoint = { ...checkpoint };
|
|
480
|
+
if (draft)
|
|
481
|
+
nextCheckpoint.blocking_question_draft = draft;
|
|
482
|
+
else
|
|
483
|
+
delete nextCheckpoint.blocking_question_draft;
|
|
484
|
+
return scope.save({ ...latest,
|
|
485
|
+
observation_checkpoint: nextCheckpoint,
|
|
486
|
+
updated_at: dependencies.now().toISOString()
|
|
487
|
+
}, { expectedRevision: terminalWatchRevision(latest) });
|
|
488
|
+
}));
|
|
489
|
+
}
|
|
490
|
+
})
|
|
491
|
+
: runtime.codexPaginatedThread && executableInteraction.projection.kind === "async_question"
|
|
492
|
+
? respondCodexPaginatedAsyncQuestion({
|
|
493
|
+
bridge, terminalControl, terminalEvidence: current.terminal.terminal_endpoint,
|
|
494
|
+
runtime, response, now: dependencies.now,
|
|
495
|
+
options: { agentVersion: version, expectedFingerprint, expectedExpiresAt,
|
|
496
|
+
scrollbackLines: Number(options.scrollbackLines ?? 120), runtime,
|
|
497
|
+
authorize: hooks.authorize, beforeDispatch: hooks.beforeDispatch }
|
|
498
|
+
})
|
|
499
|
+
: bridge.respondInteraction(current.agent, terminalControl, response, {
|
|
500
|
+
agentVersion: version,
|
|
501
|
+
expectedFingerprint,
|
|
502
|
+
expectedExpiresAt,
|
|
503
|
+
scrollbackLines: Number(options.scrollbackLines ?? 120),
|
|
504
|
+
runtime,
|
|
505
|
+
authorize: hooks.authorize,
|
|
506
|
+
beforeDispatch: hooks.beforeDispatch
|
|
507
|
+
}),
|
|
498
508
|
authorize: ({ projection, fingerprint }) => {
|
|
499
509
|
const latest = repository.load(watchId);
|
|
500
510
|
const interaction = requiredExecutableWatchInteraction(latest, interactionId, expectedFingerprint);
|
|
@@ -743,6 +753,9 @@ function sameManualWatchTarget(watch, agent, terminal, anchor) {
|
|
|
743
753
|
function sameManualWatchAnchorTarget(left, right) {
|
|
744
754
|
if (left.schema !== right.schema)
|
|
745
755
|
return false;
|
|
756
|
+
if (left.schema === "agent-knock-knock/codex-paginated-task-anchor" && right.schema === left.schema) {
|
|
757
|
+
return samePaginatedWatchTask(left, right);
|
|
758
|
+
}
|
|
746
759
|
if (left.schema ===
|
|
747
760
|
"agent-knock-knock/codex-human-started-active-task-anchor" &&
|
|
748
761
|
right.schema === left.schema) {
|
|
@@ -755,11 +768,7 @@ function sameManualWatchAnchorTarget(left, right) {
|
|
|
755
768
|
if (left.schema ===
|
|
756
769
|
"agent-knock-knock/claude-human-started-active-task-anchor" &&
|
|
757
770
|
right.schema === left.schema) {
|
|
758
|
-
return left
|
|
759
|
-
left.pid === right.pid &&
|
|
760
|
-
left.agent_started_at_ms === right.agent_started_at_ms &&
|
|
761
|
-
left.device === right.device &&
|
|
762
|
-
left.inode === right.inode;
|
|
771
|
+
return sameClaudeWatchTask(left, right);
|
|
763
772
|
}
|
|
764
773
|
if (left.schema === "agent-knock-knock/terminal-activity-watch-anchor" &&
|
|
765
774
|
right.schema === left.schema) {
|
|
@@ -769,6 +778,18 @@ function sameManualWatchAnchorTarget(left, right) {
|
|
|
769
778
|
}
|
|
770
779
|
return left.anchor_fingerprint === right.anchor_fingerprint;
|
|
771
780
|
}
|
|
781
|
+
function sameClaudeWatchTask(left, right) {
|
|
782
|
+
return left.prompt_uuid === right.prompt_uuid &&
|
|
783
|
+
left.pid === right.pid &&
|
|
784
|
+
left.agent_started_at_ms === right.agent_started_at_ms &&
|
|
785
|
+
left.device === right.device &&
|
|
786
|
+
left.inode === right.inode;
|
|
787
|
+
}
|
|
788
|
+
function samePaginatedWatchTask(left, right) {
|
|
789
|
+
return left.native_thread_id === right.native_thread_id && left.turn_id === right.turn_id &&
|
|
790
|
+
left.process_uuid === right.process_uuid && left.process_birth === right.process_birth &&
|
|
791
|
+
left.origin === right.origin && left.codex_home === right.codex_home;
|
|
792
|
+
}
|
|
772
793
|
function optionalIdentityCompatible(left, right) {
|
|
773
794
|
return left === undefined || right === undefined || left === right;
|
|
774
795
|
}
|
|
@@ -794,6 +815,92 @@ function terminalControlForWatch(terminal) {
|
|
|
794
815
|
}
|
|
795
816
|
return terminal.terminal_control;
|
|
796
817
|
}
|
|
818
|
+
async function captureCodexFallbackWatchAnchor(input, rawTerminal, agentVersion, dependencies) {
|
|
819
|
+
let inventory = rawTerminal._codex_open_root_rollout_inventory;
|
|
820
|
+
let paginated;
|
|
821
|
+
if (agentVersion === "0.158.0") {
|
|
822
|
+
try {
|
|
823
|
+
paginated = await capturePaginatedWatchAnchor(rawTerminal, input.options, dependencies, input.requestText === undefined ? input.requestHash
|
|
824
|
+
: createHash("sha256").update(input.requestText.replace(/\r\n?/gu, "\n").trim()).digest("hex"));
|
|
825
|
+
}
|
|
826
|
+
catch (error) {
|
|
827
|
+
if (!(error instanceof CodexLegacyThreadHistoryError) || !isRecord(inventory) || !Array.isArray(inventory.roots))
|
|
828
|
+
throw error;
|
|
829
|
+
const roots = inventory.roots.filter((root) => root.sessionId === error.threadId);
|
|
830
|
+
if (roots.length !== 1)
|
|
831
|
+
throw error;
|
|
832
|
+
inventory = { ...inventory, roots };
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
const source = selectCodexUserExplicitSendWatchSource({
|
|
836
|
+
agentVersion,
|
|
837
|
+
legacyRootCount: isRecord(inventory) && Array.isArray(inventory.roots) ? inventory.roots.length : 0,
|
|
838
|
+
paginatedAnchorAvailable: paginated !== undefined
|
|
839
|
+
});
|
|
840
|
+
if (source.source === "none")
|
|
841
|
+
throw new Error(source.warning);
|
|
842
|
+
if (paginated) {
|
|
843
|
+
return paginated;
|
|
844
|
+
}
|
|
845
|
+
else {
|
|
846
|
+
const acceptanceAnchor = isRecord(inventory)
|
|
847
|
+
? captureCodexCandidateSetRolloutAcceptanceAnchor({
|
|
848
|
+
inventory: inventory,
|
|
849
|
+
now: dependencies.now()
|
|
850
|
+
})
|
|
851
|
+
: captureCodexRolloutAcceptanceAnchor({
|
|
852
|
+
nativeThreadId: requiredString(rawTerminal.native_agent_session_id, "Codex native thread id"),
|
|
853
|
+
processUuid: requiredString(rawTerminal.native_agent_process_uuid, "Codex process UUID"),
|
|
854
|
+
processBirth: requiredString(rawTerminal.native_agent_process_birth, "Codex process birth"),
|
|
855
|
+
mode: "existing",
|
|
856
|
+
rollout: codexIdentity(rawTerminal).rollout,
|
|
857
|
+
now: dependencies.now()
|
|
858
|
+
});
|
|
859
|
+
return createCodexUserExplicitFallbackWatchAnchor({
|
|
860
|
+
acceptanceAnchor,
|
|
861
|
+
requestHash: input.requestHash,
|
|
862
|
+
codexVersion: agentVersion
|
|
863
|
+
});
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
function captureClaudeFallbackWatchAnchor(input, rawTerminal, agentVersion, dependencies) {
|
|
867
|
+
const transcriptAnchor = captureClaudeTranscriptAnchor({
|
|
868
|
+
sessionId: requiredString(rawTerminal.native_agent_session_id, "Claude native session id"),
|
|
869
|
+
cwd: terminalWorkspace(rawTerminal),
|
|
870
|
+
pid: positiveInteger(rawTerminal.pid, "Claude PID"),
|
|
871
|
+
claudeHome: stringValue(input.options.claudeHome),
|
|
872
|
+
agentRows: dependencies.loadClaudeAgentRows(input.options, { required: true }),
|
|
873
|
+
now: dependencies.now()
|
|
874
|
+
});
|
|
875
|
+
if (!transcriptAnchor) {
|
|
876
|
+
throw new Error("Claude transcript anchor is unavailable before terminal input");
|
|
877
|
+
}
|
|
878
|
+
return createClaudeUserExplicitFallbackWatchAnchor({
|
|
879
|
+
transcriptAnchor,
|
|
880
|
+
requestHash: input.requestHash,
|
|
881
|
+
claudeVersion: agentVersion
|
|
882
|
+
});
|
|
883
|
+
}
|
|
884
|
+
async function capturePaginatedWatchAnchor(terminal, options, dependencies, requestHash) {
|
|
885
|
+
const bridge = dependencies.createBridge?.(options);
|
|
886
|
+
if (dependencies.capturePaginatedAnchor) {
|
|
887
|
+
return dependencies.capturePaginatedAnchor({ terminal, bridge: bridge, requestHash,
|
|
888
|
+
codexHome: stringValue(options.codexHome), now: dependencies.now });
|
|
889
|
+
}
|
|
890
|
+
if (!bridge)
|
|
891
|
+
throw new Error("Codex paginated terminal inspection is unavailable");
|
|
892
|
+
return capturePaginatedAnchor({ terminal, bridge, requestHash,
|
|
893
|
+
codexHome: stringValue(options.codexHome), now: dependencies.now });
|
|
894
|
+
}
|
|
895
|
+
async function capturePaginatedWatchAnchorWithLock(terminal, options, dependencies) {
|
|
896
|
+
const release = dependencies.acquireTerminalLock(dependencies.storeDirFromOptions(options), terminalControlForWatch(terminal));
|
|
897
|
+
try {
|
|
898
|
+
return await capturePaginatedWatchAnchor(terminal, options, dependencies);
|
|
899
|
+
}
|
|
900
|
+
finally {
|
|
901
|
+
release();
|
|
902
|
+
}
|
|
903
|
+
}
|
|
797
904
|
function captureTerminalWatchAnchor(agent, terminal, options, dependencies) {
|
|
798
905
|
if (agent === "codex") {
|
|
799
906
|
return captureCodexHumanStartedActiveTaskAnchor({
|
|
@@ -817,6 +924,23 @@ async function observeTerminalWatch(watch, options, dependencies) {
|
|
|
817
924
|
const rawTerminal = exactTerminal.state === "available"
|
|
818
925
|
? exactTerminal.rawTerminal
|
|
819
926
|
: undefined;
|
|
927
|
+
if (watch.anchor.schema === "agent-knock-knock/codex-paginated-task-anchor") {
|
|
928
|
+
const terminalMatches = Boolean(rawTerminal && terminalMatchesWatch(rawTerminal, watch) && paginatedWatchProcessMatches(rawTerminal, watch.anchor));
|
|
929
|
+
return observePaginatedWatch({ watch, observedAt, terminalMatches,
|
|
930
|
+
terminalAvailable: exactTerminal.state === "available",
|
|
931
|
+
readSnapshot: dependencies.readPaginatedSnapshot,
|
|
932
|
+
blockingQuestionnaire: (checkpoint) => observeCodexPaginatedBlockingQuestion({
|
|
933
|
+
watch, checkpoint, now: new Date(observedAt),
|
|
934
|
+
responseDecision: (surfaceId, fingerprint) => rawTerminal
|
|
935
|
+
? terminalWatchResponseDecision({ ...watch, observation_checkpoint: checkpoint }, rawTerminal, surfaceId, fingerprint, options, dependencies)
|
|
936
|
+
: { executable: false, suppress: false }
|
|
937
|
+
}),
|
|
938
|
+
questionnaire: (checkpoint, questions) => exactTerminal.state === "available"
|
|
939
|
+
? terminalWatchQuestionnaireObservation({ watch, observedAt, options, dependencies,
|
|
940
|
+
rawTerminal, projectedTerminal: exactTerminal.terminal, terminalMatches,
|
|
941
|
+
observationCheckpoint: checkpoint, codexAsyncQuestionEvidence: questions })
|
|
942
|
+
: undefined });
|
|
943
|
+
}
|
|
820
944
|
const projectedTerminal = exactTerminal.state === "available"
|
|
821
945
|
? exactTerminal.terminal
|
|
822
946
|
: undefined;
|
|
@@ -1331,7 +1455,8 @@ function terminalWatchQuestionnaireObservation(input, requireFallbackAttribution
|
|
|
1331
1455
|
}),
|
|
1332
1456
|
now: new Date(input.observedAt),
|
|
1333
1457
|
approvalBlocked: Boolean(approvalFingerprint(input.projectedTerminal)),
|
|
1334
|
-
trustedTerminalEvidence: input.watch.terminal.terminal_endpoint
|
|
1458
|
+
trustedTerminalEvidence: input.watch.terminal.terminal_endpoint,
|
|
1459
|
+
codexAsyncQuestionEvidence: input.codexAsyncQuestionEvidence
|
|
1335
1460
|
});
|
|
1336
1461
|
let offer = captureOffer("notify_only");
|
|
1337
1462
|
if (!offer)
|
|
@@ -1346,7 +1471,7 @@ function terminalWatchQuestionnaireObservation(input, requireFallbackAttribution
|
|
|
1346
1471
|
return undefined;
|
|
1347
1472
|
}
|
|
1348
1473
|
const responseDecision = terminalWatchResponseDecision(responseWatch, rawTerminal, offer.surfaceId, offer.promptFingerprint, input.options, input.dependencies);
|
|
1349
|
-
if (responseDecision.executable) {
|
|
1474
|
+
if (responseDecision.executable && !(responseWatch.anchor.schema === "agent-knock-knock/codex-paginated-task-anchor" && offer.projection.kind === "questionnaire")) {
|
|
1350
1475
|
const executableOffer = captureOffer("executable");
|
|
1351
1476
|
if (!executableOffer ||
|
|
1352
1477
|
executableOffer.surfaceId !== offer.surfaceId ||
|
|
@@ -1603,6 +1728,13 @@ function terminalWatchesShareExactTask(left, right) {
|
|
|
1603
1728
|
}
|
|
1604
1729
|
function terminalWatchExactTaskKey(watch) {
|
|
1605
1730
|
const anchor = watch.anchor;
|
|
1731
|
+
if (anchor.schema === "agent-knock-knock/codex-paginated-task-anchor") {
|
|
1732
|
+
const checkpoint = watch.observation_checkpoint;
|
|
1733
|
+
const turnId = "schema" in checkpoint && checkpoint.schema === "agent-knock-knock/codex-paginated-task-checkpoint"
|
|
1734
|
+
? checkpoint.acceptance_evidence?.acceptanceId ?? anchor.turn_id : anchor.turn_id;
|
|
1735
|
+
return turnId ? sha256({ source: "codex_paginated", thread: anchor.native_thread_id,
|
|
1736
|
+
task: turnId, home: anchor.codex_home, process: anchor.process_uuid }) : undefined;
|
|
1737
|
+
}
|
|
1606
1738
|
if (anchor.schema ===
|
|
1607
1739
|
"agent-knock-knock/codex-human-started-active-task-anchor") {
|
|
1608
1740
|
return codexWatchTaskKey({
|
|
@@ -1808,6 +1940,9 @@ function managedTerminalInteractionEvidence(turn, surfaceId, promptFingerprint,
|
|
|
1808
1940
|
function terminalWatchCandidateMatchesLiveContext(watch, terminal) {
|
|
1809
1941
|
if (!terminalMatchesWatch(terminal, watch))
|
|
1810
1942
|
return false;
|
|
1943
|
+
if (watch.anchor.schema === "agent-knock-knock/codex-paginated-task-anchor") {
|
|
1944
|
+
return paginatedWatchProcessMatches(terminal, watch.anchor);
|
|
1945
|
+
}
|
|
1811
1946
|
const sessionId = stringValue(terminal.native_agent_session_id);
|
|
1812
1947
|
if (watch.anchor.schema ===
|
|
1813
1948
|
"agent-knock-knock/codex-human-started-active-task-anchor") {
|
|
@@ -2160,125 +2295,6 @@ function codexIdentityForWatch(watch) {
|
|
|
2160
2295
|
rollout: watch.anchor.rollout
|
|
2161
2296
|
};
|
|
2162
2297
|
}
|
|
2163
|
-
function publicTerminalWatch(watch, additionalWarnings = [], exposeInteraction = false) {
|
|
2164
|
-
const pending = watch.notification_outbox.filter(({ status }) => status === "pending" || status === "delivering" || status === "failed").length;
|
|
2165
|
-
const capturedAgentVersion = terminalWatchCapturedAgentVersion(watch);
|
|
2166
|
-
const compatibilityWarning = capturedAgentVersion === undefined
|
|
2167
|
-
? undefined
|
|
2168
|
-
: watch.agent === "codex"
|
|
2169
|
-
? codexRuntimeCompatibilityProfile(capturedAgentVersion)
|
|
2170
|
-
?.compatibilityWarning
|
|
2171
|
-
: claudeRuntimeCompatibilityWarning(capturedAgentVersion);
|
|
2172
|
-
const userExplicitFallback = isUserExplicitFallbackWatch(watch);
|
|
2173
|
-
const terminalActivityFallback = isTerminalActivityWatch(watch);
|
|
2174
|
-
const warnings = [...new Set([
|
|
2175
|
-
...(watch.warnings ?? []),
|
|
2176
|
-
...additionalWarnings
|
|
2177
|
-
])];
|
|
2178
|
-
const latestFailedCallback = [...watch.notification_outbox]
|
|
2179
|
-
.reverse()
|
|
2180
|
-
.find(({ status }) => status === "failed");
|
|
2181
|
-
const currentInteraction = exposeInteraction && watch.status === "active" &&
|
|
2182
|
-
watch.current_interaction &&
|
|
2183
|
-
["pending", "reserved", "response_uncertain"].includes(watch.current_interaction.aggregate.state)
|
|
2184
|
-
? watch.current_interaction
|
|
2185
|
-
: undefined;
|
|
2186
|
-
const interactionProjection = currentInteraction?.aggregate.state ===
|
|
2187
|
-
"reserved"
|
|
2188
|
-
? {
|
|
2189
|
-
...currentInteraction.projection,
|
|
2190
|
-
state: "response_uncertain",
|
|
2191
|
-
capabilities: {
|
|
2192
|
-
...currentInteraction.projection.capabilities,
|
|
2193
|
-
respond: false
|
|
2194
|
-
}
|
|
2195
|
-
}
|
|
2196
|
-
: currentInteraction?.projection;
|
|
2197
|
-
return {
|
|
2198
|
-
watch_id: watch.watch_id,
|
|
2199
|
-
source: userExplicitFallback
|
|
2200
|
-
? "terminal_user_explicit_fallback_watch"
|
|
2201
|
-
: terminalActivityFallback
|
|
2202
|
-
? "terminal_activity_watch"
|
|
2203
|
-
: "user_selected_terminal_watch",
|
|
2204
|
-
watch_mode: terminalActivityFallback ? "terminal_activity" : "exact_task",
|
|
2205
|
-
confidence: terminalActivityFallback ? "best_effort" : "exact",
|
|
2206
|
-
interaction_policy: watch.interaction_policy,
|
|
2207
|
-
capabilities: {
|
|
2208
|
-
interaction_notify: true,
|
|
2209
|
-
interaction_respond: Boolean(interactionProjection?.state === "pending" &&
|
|
2210
|
-
interactionProjection.capabilities.respond)
|
|
2211
|
-
},
|
|
2212
|
-
agent: watch.agent,
|
|
2213
|
-
terminal_id: watch.terminal.terminal_id,
|
|
2214
|
-
native_thread_id: terminalWatchNativeThreadId(watch),
|
|
2215
|
-
workspace: watch.terminal.workspace,
|
|
2216
|
-
status: watch.status,
|
|
2217
|
-
activity_state: watch.status === "active" ? "watching" : "settled",
|
|
2218
|
-
created_at: watch.created_at,
|
|
2219
|
-
deadline_at: watch.deadline_at,
|
|
2220
|
-
updated_at: watch.updated_at,
|
|
2221
|
-
last_activity_at: watch.last_activity_at,
|
|
2222
|
-
...(compatibilityWarning
|
|
2223
|
-
? { compatibility_warning: compatibilityWarning }
|
|
2224
|
-
: {}),
|
|
2225
|
-
...(warnings.length > 0
|
|
2226
|
-
? { warnings }
|
|
2227
|
-
: {}),
|
|
2228
|
-
callback: {
|
|
2229
|
-
pending,
|
|
2230
|
-
delivered: watch.notification_outbox.filter(({ status }) => status === "delivered").length,
|
|
2231
|
-
failed: watch.notification_outbox.filter(({ status }) => status === "failed").length,
|
|
2232
|
-
superseded: watch.notification_outbox.filter(({ status }) => status === "superseded").length,
|
|
2233
|
-
...(latestFailedCallback?.last_error_code
|
|
2234
|
-
? { last_error_code: latestFailedCallback.last_error_code }
|
|
2235
|
-
: {})
|
|
2236
|
-
},
|
|
2237
|
-
...(interactionProjection
|
|
2238
|
-
? {
|
|
2239
|
-
interaction_state: interactionProjection,
|
|
2240
|
-
interaction_prompt_fingerprint: interactionProjection.prompt_fingerprint
|
|
2241
|
-
}
|
|
2242
|
-
: {}),
|
|
2243
|
-
...(watch.settlement
|
|
2244
|
-
? {
|
|
2245
|
-
settlement: {
|
|
2246
|
-
kind: watch.settlement.kind,
|
|
2247
|
-
observed_at: watch.settlement.observed_at,
|
|
2248
|
-
reason_code: watch.settlement.reason_code,
|
|
2249
|
-
completion_text: watch.settlement.completion_text,
|
|
2250
|
-
completion_id: watch.settlement.completion_id,
|
|
2251
|
-
completion_timestamp: watch.settlement.completion_timestamp
|
|
2252
|
-
}
|
|
2253
|
-
}
|
|
2254
|
-
: {}),
|
|
2255
|
-
available_actions: {
|
|
2256
|
-
status: {
|
|
2257
|
-
tool: "agent_knock_knock_status",
|
|
2258
|
-
arguments: { watch_id: watch.watch_id }
|
|
2259
|
-
},
|
|
2260
|
-
...(watch.status === "active"
|
|
2261
|
-
? {
|
|
2262
|
-
unwatch: {
|
|
2263
|
-
tool: "agent_knock_knock_unwatch",
|
|
2264
|
-
arguments: { watch_id: watch.watch_id },
|
|
2265
|
-
requires_user_intent: true
|
|
2266
|
-
}
|
|
2267
|
-
}
|
|
2268
|
-
: {}),
|
|
2269
|
-
...(interactionProjection?.state === "pending" &&
|
|
2270
|
-
interactionProjection.capabilities.respond
|
|
2271
|
-
? {
|
|
2272
|
-
respond_interaction: {
|
|
2273
|
-
tool: "agent_knock_knock_respond_interaction",
|
|
2274
|
-
arguments: { watch_id: watch.watch_id },
|
|
2275
|
-
requires_user_intent: true
|
|
2276
|
-
}
|
|
2277
|
-
}
|
|
2278
|
-
: {})
|
|
2279
|
-
}
|
|
2280
|
-
};
|
|
2281
|
-
}
|
|
2282
2298
|
function watchStatusInteractionAccess(watch, options) {
|
|
2283
2299
|
if (!Object.hasOwn(options, "openclawSession"))
|
|
2284
2300
|
return false;
|
|
@@ -2288,34 +2304,6 @@ function watchStatusInteractionAccess(watch, options) {
|
|
|
2288
2304
|
}
|
|
2289
2305
|
return true;
|
|
2290
2306
|
}
|
|
2291
|
-
function terminalWatchCapturedAgentVersion(watch) {
|
|
2292
|
-
switch (watch.anchor.schema) {
|
|
2293
|
-
case "agent-knock-knock/codex-human-started-active-task-anchor":
|
|
2294
|
-
case "agent-knock-knock/codex-user-explicit-fallback-watch-anchor":
|
|
2295
|
-
return watch.anchor.codex_version;
|
|
2296
|
-
case "agent-knock-knock/claude-human-started-active-task-anchor":
|
|
2297
|
-
case "agent-knock-knock/claude-user-explicit-fallback-watch-anchor":
|
|
2298
|
-
return watch.anchor.claude_version;
|
|
2299
|
-
case "agent-knock-knock/terminal-activity-watch-anchor":
|
|
2300
|
-
return watch.anchor.agent_version;
|
|
2301
|
-
}
|
|
2302
|
-
}
|
|
2303
|
-
function terminalWatchNativeThreadId(watch) {
|
|
2304
|
-
switch (watch.anchor.schema) {
|
|
2305
|
-
case "agent-knock-knock/codex-human-started-active-task-anchor":
|
|
2306
|
-
return watch.anchor.native_thread_id;
|
|
2307
|
-
case "agent-knock-knock/claude-human-started-active-task-anchor":
|
|
2308
|
-
return watch.anchor.session_id;
|
|
2309
|
-
case "agent-knock-knock/codex-user-explicit-fallback-watch-anchor":
|
|
2310
|
-
return watch.anchor.acceptance_anchor.version === 1
|
|
2311
|
-
? watch.anchor.acceptance_anchor.native_thread_id
|
|
2312
|
-
: undefined;
|
|
2313
|
-
case "agent-knock-knock/claude-user-explicit-fallback-watch-anchor":
|
|
2314
|
-
return watch.anchor.transcript_anchor.session_id;
|
|
2315
|
-
case "agent-knock-knock/terminal-activity-watch-anchor":
|
|
2316
|
-
return undefined;
|
|
2317
|
-
}
|
|
2318
|
-
}
|
|
2319
2307
|
function approvalFingerprint(terminal) {
|
|
2320
2308
|
if (terminal.activity_state !== "awaiting_approval")
|
|
2321
2309
|
return undefined;
|