@scotthuang/agent-knock-knock 0.2.44 → 0.2.46
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 +21 -0
- package/README.md +135 -244
- package/dist/src/cli.js +638 -729
- package/dist/src/cli.js.map +1 -1
- package/dist/src/codex-session-provider.d.ts +6 -32
- package/dist/src/codex-session-provider.js +2 -1
- package/dist/src/codex-session-provider.js.map +1 -1
- package/dist/src/codex-store-adapter.d.ts +3 -9
- package/dist/src/codex-store-adapter.js +5 -55
- package/dist/src/codex-store-adapter.js.map +1 -1
- package/dist/src/codex-terminal-agent-adapter.d.ts +34 -0
- package/dist/src/codex-terminal-agent-adapter.js +386 -0
- package/dist/src/codex-terminal-agent-adapter.js.map +1 -0
- package/dist/src/openclaw-plugin.js +54 -5
- package/dist/src/openclaw-plugin.js.map +1 -1
- package/dist/src/protocol.d.ts +1 -1
- package/dist/src/terminal-agent-adapter.d.ts +124 -0
- package/dist/src/terminal-agent-adapter.js +109 -0
- package/dist/src/terminal-agent-adapter.js.map +1 -0
- package/dist/src/terminal-agent-bridge.d.ts +97 -0
- package/dist/src/terminal-agent-bridge.js +362 -0
- package/dist/src/terminal-agent-bridge.js.map +1 -0
- package/dist/src/terminal-agent-registry.d.ts +7 -0
- package/dist/src/terminal-agent-registry.js +22 -0
- package/dist/src/terminal-agent-registry.js.map +1 -0
- package/dist/src/terminal-control-provider.d.ts +8 -6
- package/dist/src/terminal-control-provider.js +5 -5
- package/dist/src/terminal-control-provider.js.map +1 -1
- package/dist/src/terminal-process-source.d.ts +25 -0
- package/dist/src/terminal-process-source.js +77 -0
- package/dist/src/terminal-process-source.js.map +1 -0
- package/openclaw.plugin.json +4 -0
- package/package.json +1 -1
- package/templates/openclaw-skills/agent-knock-knock/SKILL.md +4 -4
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { classifyCodexProcess } from "./codex-session-provider.js";
|
|
3
|
+
import { redactString } from "./runtime-log.js";
|
|
4
|
+
export function createCodexTerminalAgentAdapter(options = {}) {
|
|
5
|
+
return {
|
|
6
|
+
agent: "codex",
|
|
7
|
+
displayName: "Codex",
|
|
8
|
+
capabilities: {
|
|
9
|
+
processDiscovery: true,
|
|
10
|
+
screenStatus: true,
|
|
11
|
+
terminalApproval: true,
|
|
12
|
+
screenCompletion: true,
|
|
13
|
+
durableCompletion: true,
|
|
14
|
+
cancellation: true
|
|
15
|
+
},
|
|
16
|
+
cancelKeys: ["C-c"],
|
|
17
|
+
classifyProcess(snapshot) {
|
|
18
|
+
const process = classifyCodexProcess(snapshot);
|
|
19
|
+
return process?.kind === "codex_cli" ? process : undefined;
|
|
20
|
+
},
|
|
21
|
+
inspectScreen: inspectCodexScreen,
|
|
22
|
+
detectDurableCompletion: options.detectDurableCompletion ?? (async (request) => detectCodexDurableCompletion(request))
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export const codexTerminalAgentAdapter = createCodexTerminalAgentAdapter();
|
|
26
|
+
export function inspectCodexScreen(options) {
|
|
27
|
+
const detectedApproval = detectCodexApprovalPrompt(options.screen);
|
|
28
|
+
const blocked = isCodexApprovalPromptVisible(options.screen);
|
|
29
|
+
const approval = detectedApproval.approvable
|
|
30
|
+
? {
|
|
31
|
+
blocked: true,
|
|
32
|
+
approvable: true,
|
|
33
|
+
promptKind: detectedApproval.promptKind,
|
|
34
|
+
command: detectedApproval.command,
|
|
35
|
+
action: {
|
|
36
|
+
keys: detectedApproval.keys,
|
|
37
|
+
label: detectedApproval.label
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
: {
|
|
41
|
+
blocked,
|
|
42
|
+
approvable: false,
|
|
43
|
+
reason: detectedApproval.reason,
|
|
44
|
+
promptKind: detectedApproval.promptKind,
|
|
45
|
+
command: detectedApproval.command
|
|
46
|
+
};
|
|
47
|
+
const activity = detectCodexActivityState(options.screen, detectedApproval);
|
|
48
|
+
const screenExcerpt = codexScreenExcerpt(options.screen, options.maxExcerptLength ?? 4000);
|
|
49
|
+
const completion = activity.state === "idle"
|
|
50
|
+
? detectCodexScreenCompletion({
|
|
51
|
+
screen: screenExcerpt,
|
|
52
|
+
requestText: options.requestText,
|
|
53
|
+
screenChangedSinceSend: options.screenChangedSinceSend
|
|
54
|
+
})
|
|
55
|
+
: undefined;
|
|
56
|
+
return {
|
|
57
|
+
activity,
|
|
58
|
+
approval,
|
|
59
|
+
screenExcerpt,
|
|
60
|
+
completion
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export function detectCodexApprovalPrompt(screen) {
|
|
64
|
+
const prompt = codexApprovalPromptRegion(screen);
|
|
65
|
+
if (!prompt.visible) {
|
|
66
|
+
return {
|
|
67
|
+
approvable: false,
|
|
68
|
+
reason: prompt.reason
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
for (const line of prompt.region.split(/\r?\n/)) {
|
|
72
|
+
const match = /^[\s›]*1\.\s+(Yes,[^(]+)\(([^)]+)\)/u.exec(line.trim());
|
|
73
|
+
if (!match) {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
const key = match[2].trim();
|
|
77
|
+
if (key !== "y") {
|
|
78
|
+
return {
|
|
79
|
+
approvable: false,
|
|
80
|
+
reason: `primary approval shortcut is ${key}, not y`,
|
|
81
|
+
...approvalCandidateFromPrompt(prompt.marker, prompt.region)
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
approvable: true,
|
|
86
|
+
key,
|
|
87
|
+
keys: [key],
|
|
88
|
+
label: match[1].trim(),
|
|
89
|
+
...approvalCandidateFromPrompt(prompt.marker, prompt.region)
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
approvable: false,
|
|
94
|
+
reason: "no primary approve option with a shortcut was detected",
|
|
95
|
+
...approvalCandidateFromPrompt(prompt.marker, prompt.region)
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
export function isCodexApprovalPromptVisible(screen) {
|
|
99
|
+
return codexApprovalPromptRegion(screen).visible;
|
|
100
|
+
}
|
|
101
|
+
export function detectCodexActivityState(screen, approval = detectCodexApprovalPrompt(screen)) {
|
|
102
|
+
if (approval.approvable || isCodexApprovalPromptVisible(screen)) {
|
|
103
|
+
return {
|
|
104
|
+
state: "awaiting_approval",
|
|
105
|
+
reason: "current Codex approval prompt is visible"
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
const tailLines = screen.trimEnd().split(/\r?\n/).slice(-30);
|
|
109
|
+
const workingLine = tailLines.find((line) => isCodexWorkingLine(line));
|
|
110
|
+
if (workingLine) {
|
|
111
|
+
return {
|
|
112
|
+
state: "working",
|
|
113
|
+
reason: `Codex working marker detected: ${workingLine.trim()}`
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
const idleLine = tailLines
|
|
117
|
+
.slice(-6)
|
|
118
|
+
.map((line) => line.trim())
|
|
119
|
+
.find((line) => isCodexIdlePromptLine(line));
|
|
120
|
+
if (idleLine) {
|
|
121
|
+
return {
|
|
122
|
+
state: "idle",
|
|
123
|
+
reason: `Codex input prompt detected: ${idleLine}`
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
state: "unknown",
|
|
128
|
+
reason: "no current Codex working, idle, or approval marker was detected in the terminal screen"
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
export function codexScreenExcerpt(screen, maxLength = 4000) {
|
|
132
|
+
const lines = screen.trimEnd().split(/\r?\n/);
|
|
133
|
+
const excerpt = lines.slice(Math.max(0, lines.length - 80)).join("\n");
|
|
134
|
+
return redactString(excerpt).slice(-maxLength);
|
|
135
|
+
}
|
|
136
|
+
export function detectCodexScreenCompletion({ screen, requestText, screenChangedSinceSend }) {
|
|
137
|
+
const request = requestText?.trim() ?? "";
|
|
138
|
+
const promptEnd = request ? whitespaceInsensitiveMatchEnd(screen, request) : undefined;
|
|
139
|
+
const afterPrompt = promptEnd === undefined ? undefined : screen.slice(promptEnd);
|
|
140
|
+
const completionBoundary = afterPrompt === undefined
|
|
141
|
+
? undefined
|
|
142
|
+
: codexCompletionBoundary(afterPrompt);
|
|
143
|
+
const completionText = afterPrompt === undefined
|
|
144
|
+
? screenChangedSinceSend
|
|
145
|
+
? latestCompletedCodexSegment(screen)
|
|
146
|
+
: undefined
|
|
147
|
+
: completionBoundary === undefined
|
|
148
|
+
? afterPrompt
|
|
149
|
+
: afterPrompt.slice(0, completionBoundary);
|
|
150
|
+
if (completionText === undefined) {
|
|
151
|
+
return undefined;
|
|
152
|
+
}
|
|
153
|
+
const cleaned = cleanCodexTerminalScreenText(completionText);
|
|
154
|
+
const hasCompletionEvidence = promptEnd === undefined || completionBoundary !== undefined || /[•└]/u.test(cleaned ?? "");
|
|
155
|
+
if (!cleaned || cleaned.length < 40 || !hasCompletionEvidence) {
|
|
156
|
+
return undefined;
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
source: "screen",
|
|
160
|
+
text: truncateText(redactString(cleaned), 4000),
|
|
161
|
+
confidence: "screen_only"
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
export function detectCodexDurableCompletion(request) {
|
|
165
|
+
const context = asForkContextPackage(request.context);
|
|
166
|
+
const threshold = validTimestampMs(request.startedAt);
|
|
167
|
+
const expectedRequestHash = request.requestHash ?? requestFingerprint(request.requestText);
|
|
168
|
+
if (!context || threshold === undefined || !expectedRequestHash) {
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
const turn = [...context.turns]
|
|
172
|
+
.reverse()
|
|
173
|
+
.find((candidate) => {
|
|
174
|
+
const userTimestamp = validTimestampMs(candidate.userTimestamp);
|
|
175
|
+
const completedAt = validTimestampMs(candidate.completedAt);
|
|
176
|
+
return candidate.userTextHash === expectedRequestHash &&
|
|
177
|
+
userTimestamp !== undefined &&
|
|
178
|
+
completedAt !== undefined &&
|
|
179
|
+
userTimestamp >= threshold &&
|
|
180
|
+
completedAt >= userTimestamp &&
|
|
181
|
+
Boolean(candidate.lastAssistantMessage);
|
|
182
|
+
});
|
|
183
|
+
if (!turn?.lastAssistantMessage) {
|
|
184
|
+
return undefined;
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
source: "durable",
|
|
188
|
+
text: turn.lastAssistantMessage,
|
|
189
|
+
timestamp: turn.completedAt,
|
|
190
|
+
id: turn.turnId,
|
|
191
|
+
confidence: "high",
|
|
192
|
+
metadata: {
|
|
193
|
+
match: "rollout_task_complete",
|
|
194
|
+
userTimestamp: turn.userTimestamp,
|
|
195
|
+
session: context.source
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function codexApprovalPromptRegion(screen) {
|
|
200
|
+
const approvalMarkers = [
|
|
201
|
+
"Would you like to run the following command?",
|
|
202
|
+
"Would you like to make the following edits?",
|
|
203
|
+
"Would you like to grant these permissions?",
|
|
204
|
+
"needs your approval."
|
|
205
|
+
];
|
|
206
|
+
const lines = screen.split(/\r?\n/);
|
|
207
|
+
let markerIndex = -1;
|
|
208
|
+
let matchedMarker = "";
|
|
209
|
+
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
210
|
+
const marker = approvalMarkers.find((candidate) => lines[index].includes(candidate));
|
|
211
|
+
if (marker) {
|
|
212
|
+
markerIndex = index;
|
|
213
|
+
matchedMarker = marker;
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (markerIndex < 0) {
|
|
218
|
+
return {
|
|
219
|
+
visible: false,
|
|
220
|
+
reason: "no Codex approval prompt was detected in the terminal screen"
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
const regionLines = lines.slice(markerIndex);
|
|
224
|
+
const staleLine = regionLines.slice(1).find((line) => isPostApprovalActivityLine(line));
|
|
225
|
+
if (staleLine) {
|
|
226
|
+
return {
|
|
227
|
+
visible: false,
|
|
228
|
+
reason: `Codex approval prompt appears stale after later terminal activity: ${staleLine.trim()}`
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
return {
|
|
232
|
+
visible: true,
|
|
233
|
+
region: regionLines.join("\n"),
|
|
234
|
+
marker: matchedMarker
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
function approvalCandidateFromPrompt(marker, region) {
|
|
238
|
+
const promptKind = marker === "Would you like to run the following command?"
|
|
239
|
+
? "run_command"
|
|
240
|
+
: marker === "Would you like to make the following edits?"
|
|
241
|
+
? "file_edit"
|
|
242
|
+
: marker === "Would you like to grant these permissions?"
|
|
243
|
+
? "grant_permissions"
|
|
244
|
+
: "unknown";
|
|
245
|
+
return {
|
|
246
|
+
promptKind,
|
|
247
|
+
command: promptKind === "run_command" ? commandFromApprovalRegion(region) : undefined
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
function commandFromApprovalRegion(region) {
|
|
251
|
+
const lines = region.split(/\r?\n/);
|
|
252
|
+
const commandStart = lines.findIndex((line) => /^\s*\$\s+/u.test(line));
|
|
253
|
+
if (commandStart < 0) {
|
|
254
|
+
return undefined;
|
|
255
|
+
}
|
|
256
|
+
const parts = [];
|
|
257
|
+
for (let index = commandStart; index < lines.length; index += 1) {
|
|
258
|
+
const line = lines[index];
|
|
259
|
+
if (index > commandStart && (!line.trim() || /^[\s›]*\d+\.\s+/u.test(line) || /Press enter to confirm/u.test(line))) {
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
262
|
+
parts.push(index === commandStart ? line.replace(/^\s*\$\s+/u, "").trim() : line.trim());
|
|
263
|
+
}
|
|
264
|
+
const command = parts.filter(Boolean).join(" ").trim();
|
|
265
|
+
return command ? redactString(command) : undefined;
|
|
266
|
+
}
|
|
267
|
+
function isPostApprovalActivityLine(line) {
|
|
268
|
+
const trimmed = line.trim();
|
|
269
|
+
if (!trimmed) {
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
if (/^✔\s+You approved\b/u.test(trimmed)) {
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
if (/^›\s+(?!1\.)\S/u.test(trimmed)) {
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
if (/^•\s+(Working|Ran|Explored|Edited|Read|Called|Searching|Planning|Updated|Added|Deleted|Modified|Running|Thinking)\b/u.test(trimmed)) {
|
|
279
|
+
return true;
|
|
280
|
+
}
|
|
281
|
+
return /^─\s*Worked for\b/u.test(trimmed);
|
|
282
|
+
}
|
|
283
|
+
function isCodexWorkingLine(line) {
|
|
284
|
+
const trimmed = line.trim();
|
|
285
|
+
if (!trimmed) {
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
if (/^•\s+Working\b/u.test(trimmed) && (/\besc to interrupt\b/u.test(trimmed) || trimmed === "• Working")) {
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
291
|
+
if (/^•\s+Waiting for background terminals?\b(?:\s*·|$)/u.test(trimmed)) {
|
|
292
|
+
return true;
|
|
293
|
+
}
|
|
294
|
+
return /^\d+\s+background terminals? running\b/u.test(trimmed) && /\/(?:ps|stop)\b/u.test(trimmed);
|
|
295
|
+
}
|
|
296
|
+
function isCodexIdlePromptLine(line) {
|
|
297
|
+
const trimmed = line.trim();
|
|
298
|
+
return /^›(?:\s|$)/u.test(trimmed) && !/^›\s*1\./u.test(trimmed);
|
|
299
|
+
}
|
|
300
|
+
function whitespaceInsensitiveMatchEnd(text, expected) {
|
|
301
|
+
const normalizedExpected = expected.replace(/\s/gu, "");
|
|
302
|
+
if (!normalizedExpected) {
|
|
303
|
+
return undefined;
|
|
304
|
+
}
|
|
305
|
+
let normalizedText = "";
|
|
306
|
+
const sourceEnds = [];
|
|
307
|
+
for (let index = 0; index < text.length;) {
|
|
308
|
+
const codePoint = text.codePointAt(index);
|
|
309
|
+
if (codePoint === undefined) {
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
const character = String.fromCodePoint(codePoint);
|
|
313
|
+
if (!/\s/u.test(character)) {
|
|
314
|
+
normalizedText += character;
|
|
315
|
+
for (let codeUnit = 0; codeUnit < character.length; codeUnit += 1) {
|
|
316
|
+
sourceEnds.push(index + character.length);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
index += character.length;
|
|
320
|
+
}
|
|
321
|
+
const matchIndex = normalizedText.lastIndexOf(normalizedExpected);
|
|
322
|
+
if (matchIndex < 0) {
|
|
323
|
+
return undefined;
|
|
324
|
+
}
|
|
325
|
+
return sourceEnds[matchIndex + normalizedExpected.length - 1];
|
|
326
|
+
}
|
|
327
|
+
function latestCompletedCodexSegment(text) {
|
|
328
|
+
const matches = [...text.matchAll(/^[ \t]*[─━-]+\s+Worked for\b.*$/gmu)];
|
|
329
|
+
const completion = matches.at(-1);
|
|
330
|
+
if (completion?.index === undefined) {
|
|
331
|
+
return undefined;
|
|
332
|
+
}
|
|
333
|
+
const previousCompletion = matches.at(-2);
|
|
334
|
+
let start = previousCompletion?.index === undefined
|
|
335
|
+
? 0
|
|
336
|
+
: previousCompletion.index + previousCompletion[0].length;
|
|
337
|
+
const beforeCompletion = text.slice(0, completion.index);
|
|
338
|
+
const prompts = [...beforeCompletion.matchAll(/^[ \t]*›(?:\s|$).*$/gmu)];
|
|
339
|
+
const latestPrompt = prompts.at(-1);
|
|
340
|
+
if (latestPrompt?.index !== undefined && latestPrompt.index >= start) {
|
|
341
|
+
start = latestPrompt.index + latestPrompt[0].length;
|
|
342
|
+
}
|
|
343
|
+
return text.slice(start, completion.index);
|
|
344
|
+
}
|
|
345
|
+
function codexCompletionBoundary(text) {
|
|
346
|
+
const matches = [...text.matchAll(/^[ \t]*[─━-]+\s+Worked for\b.*$/gmu)];
|
|
347
|
+
return matches.at(-1)?.index;
|
|
348
|
+
}
|
|
349
|
+
function cleanCodexTerminalScreenText(text) {
|
|
350
|
+
const lines = text
|
|
351
|
+
.split(/\r?\n/)
|
|
352
|
+
.map((line) => line.replace(/\s+$/u, ""))
|
|
353
|
+
.filter((line) => {
|
|
354
|
+
const trimmed = line.trim();
|
|
355
|
+
return trimmed &&
|
|
356
|
+
!trimmed.startsWith("› Use /skills") &&
|
|
357
|
+
!/^gpt-[\w.-]+/u.test(trimmed) &&
|
|
358
|
+
!/^[-\w.]+ default ·/u.test(trimmed);
|
|
359
|
+
});
|
|
360
|
+
const cleaned = lines.join("\n").trim();
|
|
361
|
+
return cleaned || undefined;
|
|
362
|
+
}
|
|
363
|
+
function asForkContextPackage(value) {
|
|
364
|
+
if (!value || typeof value !== "object") {
|
|
365
|
+
return undefined;
|
|
366
|
+
}
|
|
367
|
+
const context = value;
|
|
368
|
+
return context.source && Array.isArray(context.turns)
|
|
369
|
+
? context
|
|
370
|
+
: undefined;
|
|
371
|
+
}
|
|
372
|
+
function validTimestampMs(value) {
|
|
373
|
+
const parsed = Date.parse(String(value ?? ""));
|
|
374
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
375
|
+
}
|
|
376
|
+
function requestFingerprint(value) {
|
|
377
|
+
const text = String(value ?? "").replace(/\s+/gu, " ").trim();
|
|
378
|
+
return text ? createHash("sha256").update(text).digest("hex") : undefined;
|
|
379
|
+
}
|
|
380
|
+
function truncateText(text, maxLength) {
|
|
381
|
+
if (text.length <= maxLength) {
|
|
382
|
+
return text;
|
|
383
|
+
}
|
|
384
|
+
return `${text.slice(0, Math.max(0, maxLength - 15)).trimEnd()}... [truncated]`;
|
|
385
|
+
}
|
|
386
|
+
//# sourceMappingURL=codex-terminal-agent-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-terminal-agent-adapter.js","sourceRoot":"","sources":["../../src/codex-terminal-agent-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -144,6 +144,20 @@ const renewParameters = {
|
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
146
|
};
|
|
147
|
+
const retryCallbackParameters = {
|
|
148
|
+
type: "object",
|
|
149
|
+
additionalProperties: false,
|
|
150
|
+
required: ["conversation_id"],
|
|
151
|
+
properties: {
|
|
152
|
+
conversation_id: {
|
|
153
|
+
type: "string",
|
|
154
|
+
description: "AKK-managed conversation whose persisted callback delivery is pending or failed."
|
|
155
|
+
},
|
|
156
|
+
storeDir: {
|
|
157
|
+
type: "string"
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
};
|
|
147
161
|
const statusParameters = {
|
|
148
162
|
type: "object",
|
|
149
163
|
additionalProperties: false,
|
|
@@ -151,7 +165,7 @@ const statusParameters = {
|
|
|
151
165
|
properties: {
|
|
152
166
|
conversation_id: {
|
|
153
167
|
type: "string",
|
|
154
|
-
description: "AKK-managed conversation id, or a terminal-controlled id from AKK list such as terminal:tmux:codex-work:0.1:33389."
|
|
168
|
+
description: "AKK-managed conversation id, or a terminal-controlled id from AKK list such as terminal:v2:tmux:codex:codex-work:0.1:33389."
|
|
155
169
|
},
|
|
156
170
|
storeDir: {
|
|
157
171
|
type: "string"
|
|
@@ -201,7 +215,7 @@ const sendParameters = {
|
|
|
201
215
|
properties: {
|
|
202
216
|
conversation_id: {
|
|
203
217
|
type: "string",
|
|
204
|
-
description: "AKK-managed conversation id, or a terminal-controlled id from AKK list such as terminal:tmux:codex-work:0.1:33389. When the user refers to a listed tmux target like my-work:0.1, resolve it to the terminal-controlled id from AKK list before sending."
|
|
218
|
+
description: "AKK-managed conversation id, or a terminal-controlled id from AKK list such as terminal:v2:tmux:codex:codex-work:0.1:33389. When the user refers to a listed tmux target like my-work:0.1, resolve it to the terminal-controlled id from AKK list before sending."
|
|
205
219
|
},
|
|
206
220
|
message: {
|
|
207
221
|
type: "string"
|
|
@@ -240,7 +254,7 @@ const cancelParameters = {
|
|
|
240
254
|
properties: {
|
|
241
255
|
conversation_id: {
|
|
242
256
|
type: "string",
|
|
243
|
-
description: "AKK-managed conversation id, or a terminal-controlled id from AKK list such as terminal:tmux:codex-work:0.1:33389."
|
|
257
|
+
description: "AKK-managed conversation id, or a terminal-controlled id from AKK list such as terminal:v2:tmux:codex:codex-work:0.1:33389."
|
|
244
258
|
},
|
|
245
259
|
allProxy: {
|
|
246
260
|
type: "string"
|
|
@@ -374,11 +388,15 @@ const agentTakeoverParameters = {
|
|
|
374
388
|
const approveParameters = {
|
|
375
389
|
type: "object",
|
|
376
390
|
additionalProperties: false,
|
|
377
|
-
required: ["conversation_id"],
|
|
391
|
+
required: ["conversation_id", "expected_approval_fingerprint"],
|
|
378
392
|
properties: {
|
|
379
393
|
conversation_id: {
|
|
380
394
|
type: "string",
|
|
381
|
-
description: "AKK-managed conversation id, or a terminal-controlled id from AKK list such as terminal:tmux:codex-work:0.1:33389."
|
|
395
|
+
description: "AKK-managed conversation id, or a terminal-controlled id from AKK list such as terminal:v2:tmux:codex:codex-work:0.1:33389."
|
|
396
|
+
},
|
|
397
|
+
expected_approval_fingerprint: {
|
|
398
|
+
type: "string",
|
|
399
|
+
description: "Exact approval fingerprint returned by the latest status or approval-required callback. The prompt is captured again and must still match before keys are sent."
|
|
382
400
|
},
|
|
383
401
|
storeDir: {
|
|
384
402
|
type: "string"
|
|
@@ -528,6 +546,7 @@ export default definePluginEntry({
|
|
|
528
546
|
parameters: approveParameters,
|
|
529
547
|
buildArgs: (params) => {
|
|
530
548
|
const args = ["approve", "--conversation", requiredString(params.conversation_id, "conversation_id")];
|
|
549
|
+
pushOptional(args, "--expected-approval-fingerprint", requiredString(params.expected_approval_fingerprint, "expected_approval_fingerprint"));
|
|
531
550
|
pushOptional(args, "--store-dir", stringValue(params.storeDir) ?? stringValue(api.pluginConfig?.storeDir));
|
|
532
551
|
return args;
|
|
533
552
|
}
|
|
@@ -544,6 +563,17 @@ export default definePluginEntry({
|
|
|
544
563
|
return args;
|
|
545
564
|
}
|
|
546
565
|
});
|
|
566
|
+
registerCliTool(api, {
|
|
567
|
+
name: "agent_knock_knock_retry_callback",
|
|
568
|
+
description: "Retry a persisted AKK callback that failed before reaching OpenClaw. The original callback message id is reused for idempotent delivery, and the task closes only after delivery succeeds.",
|
|
569
|
+
parameters: retryCallbackParameters,
|
|
570
|
+
buildArgs: (params) => {
|
|
571
|
+
const config = isRecord(api.pluginConfig) ? api.pluginConfig : {};
|
|
572
|
+
const args = ["retry-callback", "--conversation", requiredString(params.conversation_id, "conversation_id")];
|
|
573
|
+
pushOptional(args, "--store-dir", stringValue(params.storeDir) ?? stringValue(config.storeDir));
|
|
574
|
+
return args;
|
|
575
|
+
}
|
|
576
|
+
});
|
|
547
577
|
registerCliTool(api, {
|
|
548
578
|
name: "agent_knock_knock_cancel",
|
|
549
579
|
description: "Request cancellation for an existing Agent Knock Knock Codex, Claude, or Cursor session. Delegated sessions use cooperative ACPX cancellation. Terminal-controlled sessions send Control-C to the controlled terminal pane. This does not close the AKK session; use close when the session should no longer be reused.",
|
|
@@ -682,6 +712,13 @@ async function handleAkkCommand(api, ctx) {
|
|
|
682
712
|
const result = runCli(api, args);
|
|
683
713
|
return { text: formatRenewCommandResult(result) };
|
|
684
714
|
}
|
|
715
|
+
if (parsed.action === "retry-callback" || parsed.action === "retry") {
|
|
716
|
+
const config = isRecord(api.pluginConfig) ? api.pluginConfig : {};
|
|
717
|
+
const args = ["retry-callback", "--conversation", parsed.conversationId];
|
|
718
|
+
pushOptional(args, "--store-dir", stringValue(config.storeDir));
|
|
719
|
+
const result = runCli(api, args);
|
|
720
|
+
return { text: formatRetryCallbackCommandResult(result) };
|
|
721
|
+
}
|
|
685
722
|
if (parsed.action === "cancel") {
|
|
686
723
|
const args = [
|
|
687
724
|
"cancel",
|
|
@@ -766,6 +803,10 @@ function parseAkkCommand(args) {
|
|
|
766
803
|
}
|
|
767
804
|
return { action: "renew", conversationId, minutes: minutes || undefined };
|
|
768
805
|
}
|
|
806
|
+
if (action === "retry-callback" || action === "retry") {
|
|
807
|
+
const { token: conversationId } = takeRequiredToken(rest, "Usage: /akk retry-callback <conversation-id>");
|
|
808
|
+
return { action: "retry-callback", conversationId };
|
|
809
|
+
}
|
|
769
810
|
if (action === "recover") {
|
|
770
811
|
const { token: conversationId } = takeRequiredToken(rest, "Usage: /akk recover <conversation-id>");
|
|
771
812
|
return { action: "recover", conversationId };
|
|
@@ -814,6 +855,7 @@ function akkUsageText() {
|
|
|
814
855
|
"/akk send <conversation-id> <message>",
|
|
815
856
|
"/akk cancel <conversation-id>",
|
|
816
857
|
"/akk renew <conversation-id> [minutes]",
|
|
858
|
+
"/akk retry-callback <conversation-id>",
|
|
817
859
|
"/akk recover <conversation-id>",
|
|
818
860
|
"/akk close <conversation-id> [reason]"
|
|
819
861
|
].join("\n");
|
|
@@ -867,6 +909,13 @@ function formatRenewCommandResult(result) {
|
|
|
867
909
|
"No message or key was sent to the coding agent."
|
|
868
910
|
].join("\n");
|
|
869
911
|
}
|
|
912
|
+
function formatRetryCallbackCommandResult(result) {
|
|
913
|
+
return [
|
|
914
|
+
`AKK callback delivered: ${result.conversation?.conversation_id ?? "unknown"}`,
|
|
915
|
+
`status: ${result.conversation?.status ?? "unknown"}`,
|
|
916
|
+
`attempts: ${result.conversation?.callback_delivery?.attempts ?? "unknown"}`
|
|
917
|
+
].join("\n");
|
|
918
|
+
}
|
|
870
919
|
function formatDescribeCommandResult(result) {
|
|
871
920
|
const lines = [
|
|
872
921
|
`AKK description: ${result.conversation_id ?? "unknown"}`,
|