@scotthuang/agent-knock-knock 0.2.0 → 0.2.2
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 +11 -2
- package/README.md +45 -163
- package/dist/src/cli.js +399 -50
- package/dist/src/cli.js.map +1 -1
- package/dist/src/codex-session-provider.d.ts +12 -0
- package/dist/src/codex-session-provider.js.map +1 -1
- package/dist/src/executors.d.ts +0 -6
- package/dist/src/executors.js +0 -6
- package/dist/src/executors.js.map +1 -1
- package/dist/src/openclaw-plugin.js +43 -19
- package/dist/src/openclaw-plugin.js.map +1 -1
- package/dist/src/terminal-control-provider.d.ts +56 -0
- package/dist/src/terminal-control-provider.js +154 -0
- package/dist/src/terminal-control-provider.js.map +1 -0
- package/openclaw.plugin.json +1 -5
- package/package.json +1 -1
- package/templates/openclaw-skills/agent-knock-knock/SKILL.md +12 -8
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
export class TmuxTerminalControlProvider {
|
|
3
|
+
runCommand;
|
|
4
|
+
constructor(options = {}) {
|
|
5
|
+
this.runCommand = options.runCommand ?? runCommand;
|
|
6
|
+
}
|
|
7
|
+
async listPanes() {
|
|
8
|
+
const result = this.runCommand("tmux", [
|
|
9
|
+
"list-panes",
|
|
10
|
+
"-a",
|
|
11
|
+
"-F",
|
|
12
|
+
"#{session_name}\t#{window_index}\t#{pane_index}\t#{pane_pid}\t#{pane_current_command}\t#{pane_current_path}"
|
|
13
|
+
]);
|
|
14
|
+
if (result.status !== 0) {
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
return parseTmuxListPanes(result.stdout);
|
|
18
|
+
}
|
|
19
|
+
async capture(target, options = {}) {
|
|
20
|
+
const scrollbackLines = Math.max(0, Math.floor(options.scrollbackLines ?? 200));
|
|
21
|
+
const result = this.runCommand("tmux", [
|
|
22
|
+
"capture-pane",
|
|
23
|
+
"-t",
|
|
24
|
+
target,
|
|
25
|
+
"-p",
|
|
26
|
+
"-S",
|
|
27
|
+
`-${scrollbackLines}`
|
|
28
|
+
]);
|
|
29
|
+
if (result.status !== 0) {
|
|
30
|
+
throw new Error(result.stderr || result.error?.message || `tmux capture-pane failed for ${target}`);
|
|
31
|
+
}
|
|
32
|
+
return result.stdout;
|
|
33
|
+
}
|
|
34
|
+
async sendKeys(target, keys) {
|
|
35
|
+
const result = this.runCommand("tmux", ["send-keys", "-t", target, ...keys]);
|
|
36
|
+
if (result.status !== 0) {
|
|
37
|
+
throw new Error(result.stderr || result.error?.message || `tmux send-keys failed for ${target}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async sendText(target, text) {
|
|
41
|
+
const result = this.runCommand("tmux", ["send-keys", "-t", target, "-l", text]);
|
|
42
|
+
if (result.status !== 0) {
|
|
43
|
+
throw new Error(result.stderr || result.error?.message || `tmux send-keys failed for ${target}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export class StaticTerminalControlProvider {
|
|
48
|
+
panes;
|
|
49
|
+
screens;
|
|
50
|
+
sentKeys = [];
|
|
51
|
+
constructor(options = {}) {
|
|
52
|
+
this.panes = options.panes ?? [];
|
|
53
|
+
this.screens = new Map(Object.entries(options.screens ?? {}));
|
|
54
|
+
}
|
|
55
|
+
async listPanes() {
|
|
56
|
+
return this.panes;
|
|
57
|
+
}
|
|
58
|
+
async capture(target) {
|
|
59
|
+
return this.screens.get(target) ?? "";
|
|
60
|
+
}
|
|
61
|
+
async sendText(target, text) {
|
|
62
|
+
this.sentKeys.push({ target, keys: ["-l", text] });
|
|
63
|
+
}
|
|
64
|
+
async sendKeys(target, keys) {
|
|
65
|
+
this.sentKeys.push({ target, keys });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export function parseTmuxListPanes(output) {
|
|
69
|
+
const panes = [];
|
|
70
|
+
for (const line of output.split(/\r?\n/)) {
|
|
71
|
+
if (line.trim().length === 0) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const [session, windowIndex, paneIndex, panePid, currentCommand, currentPath] = line.split("\t");
|
|
75
|
+
const window = Number(windowIndex);
|
|
76
|
+
const pane = Number(paneIndex);
|
|
77
|
+
const parsedPanePid = Number(panePid);
|
|
78
|
+
if (!session || !Number.isInteger(window) || !Number.isInteger(pane) || !Number.isInteger(parsedPanePid)) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
panes.push({
|
|
82
|
+
kind: "tmux",
|
|
83
|
+
target: `${session}:${window}.${pane}`,
|
|
84
|
+
session,
|
|
85
|
+
window,
|
|
86
|
+
pane,
|
|
87
|
+
panePid: parsedPanePid,
|
|
88
|
+
currentCommand: currentCommand || undefined,
|
|
89
|
+
currentPath: currentPath || undefined
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
return panes;
|
|
93
|
+
}
|
|
94
|
+
export async function enrichActiveProcessesWithTerminalControl(processes, provider) {
|
|
95
|
+
const panes = await provider.listPanes();
|
|
96
|
+
if (panes.length === 0) {
|
|
97
|
+
return processes;
|
|
98
|
+
}
|
|
99
|
+
return processes.map((process) => {
|
|
100
|
+
const pane = panes.find((candidate) => processBelongsToPane(process, candidate, processes));
|
|
101
|
+
if (!pane) {
|
|
102
|
+
return process;
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
...process,
|
|
106
|
+
terminalControl: terminalRefFromPane(pane)
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
export function terminalRefFromPane(pane) {
|
|
111
|
+
return {
|
|
112
|
+
kind: "tmux",
|
|
113
|
+
target: pane.target,
|
|
114
|
+
session: pane.session,
|
|
115
|
+
window: pane.window,
|
|
116
|
+
pane: pane.pane,
|
|
117
|
+
panePid: pane.panePid,
|
|
118
|
+
currentCommand: pane.currentCommand,
|
|
119
|
+
currentPath: pane.currentPath,
|
|
120
|
+
capabilities: ["capture_screen", "send_keys", "terminal_approval"]
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function processBelongsToPane(process, pane, processes) {
|
|
124
|
+
if (process.pid === pane.panePid || process.ppid === pane.panePid) {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
let current = process;
|
|
128
|
+
const seen = new Set();
|
|
129
|
+
while (current.ppid && !seen.has(current.pid)) {
|
|
130
|
+
seen.add(current.pid);
|
|
131
|
+
if (current.ppid === pane.panePid) {
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
const parent = processes.find((candidate) => candidate.pid === current.ppid);
|
|
135
|
+
if (!parent) {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
current = parent;
|
|
139
|
+
}
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
function runCommand(command, args) {
|
|
143
|
+
const result = spawnSync(command, args, {
|
|
144
|
+
encoding: "utf8",
|
|
145
|
+
maxBuffer: 1024 * 1024 * 10
|
|
146
|
+
});
|
|
147
|
+
return {
|
|
148
|
+
status: result.status,
|
|
149
|
+
stdout: result.stdout,
|
|
150
|
+
stderr: result.stderr,
|
|
151
|
+
error: result.error
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=terminal-control-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-control-provider.js","sourceRoot":"","sources":["../../src/terminal-control-provider.ts"],"names":[],"mappings":"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"}
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "agent-knock-knock",
|
|
3
3
|
"name": "Agent Knock Knock",
|
|
4
|
-
"description": "Agent Knock Knock (AKK/akk) delegates OpenClaw coding work to local Codex, Claude, or Cursor agents. Use this plugin when the user says AKK, akk, Agent Knock Knock, asks to hand work to Codex, Claude, or Cursor, asks what agent tasks are running, sends a follow-up to an agent task, recovers
|
|
4
|
+
"description": "Agent Knock Knock (AKK/akk) delegates OpenClaw coding work to local Codex, Claude, or Cursor agents. Use this plugin when the user says AKK, akk, Agent Knock Knock, asks to hand work to Codex, Claude, or Cursor, asks what agent tasks are running, sends a follow-up to an agent task, recovers an unavailable agent session, cancels a running agent task, or closes an agent task. Default delegation target comes from plugin config defaultAgent and falls back to Codex when unset; explicit user agent requests override it.",
|
|
5
5
|
"activation": {
|
|
6
6
|
"onStartup": true
|
|
7
7
|
},
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
"agent_knock_knock_send",
|
|
17
17
|
"agent_knock_knock_cancel",
|
|
18
18
|
"agent_knock_knock_recover",
|
|
19
|
-
"agent_knock_knock_restart",
|
|
20
19
|
"agent_knock_knock_close"
|
|
21
20
|
]
|
|
22
21
|
},
|
|
@@ -39,9 +38,6 @@
|
|
|
39
38
|
"agent_knock_knock_recover": {
|
|
40
39
|
"optional": true
|
|
41
40
|
},
|
|
42
|
-
"agent_knock_knock_restart": {
|
|
43
|
-
"optional": true
|
|
44
|
-
},
|
|
45
41
|
"agent_knock_knock_close": {
|
|
46
42
|
"optional": true
|
|
47
43
|
}
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@ description: Delegate OpenClaw tasks to local Codex, Claude Code, and Cursor age
|
|
|
5
5
|
|
|
6
6
|
# Agent Knock Knock
|
|
7
7
|
|
|
8
|
-
Use this skill when the user says `AKK`, `akk`, `Agent Knock Knock`, asks OpenClaw to delegate coding work to Codex, Claude, or Cursor, asks what agent tasks are running, sends a follow-up to an agent task, discovers existing local coding-agent sessions, takes over an existing native Codex session, recovers
|
|
8
|
+
Use this skill when the user says `AKK`, `akk`, `Agent Knock Knock`, asks OpenClaw to delegate coding work to Codex, Claude, or Cursor, asks what agent tasks are running, sends a follow-up to an agent task, discovers existing local coding-agent sessions, takes over an existing native Codex session, recovers an unavailable agent session, cancels a running agent task, or closes an agent task.
|
|
9
9
|
|
|
10
10
|
Treat `AKK` and `akk` the same way.
|
|
11
11
|
|
|
@@ -38,7 +38,6 @@ Slash command forms:
|
|
|
38
38
|
- `/akk send <conversation-id> <message>`: send a follow-up to one open AKK session.
|
|
39
39
|
- `/akk cancel <conversation-id>`: request cooperative cancellation of the current in-flight prompt for one AKK session without closing it.
|
|
40
40
|
- `/akk recover <conversation-id>`: recover a session that is waiting for a recovery decision by starting a new agent session with AKK's saved protocol history summary.
|
|
41
|
-
- `/akk restart <conversation-id>`: restart a session that is waiting for a recovery decision by starting a new agent session with only the pending message.
|
|
42
41
|
- `/akk close <conversation-id> [reason]`: close one AKK session.
|
|
43
42
|
|
|
44
43
|
Natural-language forms:
|
|
@@ -52,12 +51,13 @@ Natural-language forms:
|
|
|
52
51
|
- `AKK send <conversation-id>: <message>` or follow-up requests for an existing open agent session: call `agent_knock_knock_send`.
|
|
53
52
|
- `AKK cancel <conversation-id>` or requests to stop the current running work without closing the session: call `agent_knock_knock_cancel`.
|
|
54
53
|
- `AKK recover <conversation-id>`: call `agent_knock_knock_recover`.
|
|
55
|
-
- `AKK restart <conversation-id>`: call `agent_knock_knock_restart`.
|
|
56
54
|
- `AKK close <conversation-id>`: call `agent_knock_knock_close`.
|
|
57
55
|
- `AKK Codex sessions`, `AKK Codex history`, or requests to list existing native Codex sessions outside AKK: call `agent_knock_knock_agent_discover` with `agent="codex"` and `scope="sessions"`.
|
|
58
56
|
- `AKK Codex active` or requests to list currently running local Codex CLI processes: call `agent_knock_knock_agent_discover` with `agent="codex"` and `scope="active"`.
|
|
59
57
|
- `AKK Codex capabilities` or requests to inspect Codex takeover support: call `agent_knock_knock_agent_discover` with `agent="codex"` and `scope="capabilities"`.
|
|
60
58
|
- `AKK takeover Codex <session-id>` or requests to take over an active Codex CLI session: call `agent_knock_knock_agent_takeover` with `agent="codex"` and `strategy="terminate_then_resume"`.
|
|
59
|
+
- `AKK terminal takeover Codex <session-id>`, `AKK tmux takeover Codex <session-id>`, or requests to take over a Codex CLI that is running inside tmux without stopping it: call `agent_knock_knock_agent_takeover` with `agent="codex"` and `strategy="terminal_control"`.
|
|
60
|
+
- `AKK approve <conversation-id>` or requests to approve the current visible Codex permission/command prompt for a terminal-controlled session: first call `agent_knock_knock_status` for that conversation and show the terminal screen excerpt to the user. Only after the user explicitly approves that prompt, call `agent_knock_knock_approve`.
|
|
61
61
|
- `AKK safe resume Codex <session-id>` or requests to resume only after the original Codex CLI has already exited: call `agent_knock_knock_agent_takeover` with `agent="codex"` and `strategy="safe_resume"`.
|
|
62
62
|
- `AKK takeover Codex <session-id> with fork`, `AKK fork takeover Codex <session-id>`, or requests to take over without stopping the original Codex CLI: call `agent_knock_knock_agent_takeover` with `agent="codex"` and `strategy="fork"`.
|
|
63
63
|
|
|
@@ -66,7 +66,7 @@ Session reuse rule:
|
|
|
66
66
|
- If the user asks to continue, add, follow up, "send another task", "let it also", "tell it", "ask Codex/Claude/Cursor to also", "再让它", "继续让它", "给刚才那个", or otherwise refers to an existing AKK agent, reuse the most recent matching open AKK session instead of creating a new delegation.
|
|
67
67
|
- When the user gives a follow-up without a `conversation_id`, first call `agent_knock_knock_list`, choose the most recent open session that matches the requested agent if one is named, and then call `agent_knock_knock_send` with that `conversation_id`.
|
|
68
68
|
- `idle` means the agent completed the previous round but the AKK session is still open and should be reused for follow-ups.
|
|
69
|
-
- `
|
|
69
|
+
- `send` automatically falls back to AKK replay recovery when the previous coding-agent session is unavailable. If AKK still reports `needs_recovery`, ask the user to choose `AKK recover <conversation-id>`, `AKK close <conversation-id>`, or starting a new independent AKK delegation.
|
|
70
70
|
- Call `agent_knock_knock_delegate` only when the user clearly asks for a new independent AKK task/session, names a different agent that does not already have a suitable open session, or there is no matching open session to reuse.
|
|
71
71
|
|
|
72
72
|
Useful examples:
|
|
@@ -81,11 +81,12 @@ akk send task-20260618T010203Z-abcdef12: continue with the smaller implementatio
|
|
|
81
81
|
再让刚才那个 Codex 分析 ~/chrome-debug 为什么占空间
|
|
82
82
|
akk cancel task-20260618T010203Z-abcdef12
|
|
83
83
|
akk recover task-20260618T010203Z-abcdef12
|
|
84
|
-
akk restart task-20260618T010203Z-abcdef12
|
|
85
84
|
akk close task-20260618T010203Z-abcdef12
|
|
86
85
|
akk codex sessions
|
|
87
86
|
akk codex active
|
|
88
87
|
akk takeover codex 019ee559-7bb8-7fd1-970c-0f7b6978c44e
|
|
88
|
+
akk terminal takeover codex 019ee559-7bb8-7fd1-970c-0f7b6978c44e
|
|
89
|
+
akk approve task-20260618T010203Z-abcdef12
|
|
89
90
|
```
|
|
90
91
|
|
|
91
92
|
## Start A Conversation
|
|
@@ -127,15 +128,17 @@ If the plugin tool and delegation script are unavailable, stop and report that A
|
|
|
127
128
|
|
|
128
129
|
## Recovery Decisions
|
|
129
130
|
|
|
130
|
-
|
|
131
|
+
`AKK send <conversation-id>: <message>` automatically falls back to AKK replay recovery when the previous ACPX session is unavailable. This starts a fresh ACPX session, gives the coding agent AKK's saved protocol history summary, and includes the pending message.
|
|
132
|
+
|
|
133
|
+
When AKK still reports that a conversation is `needs_recovery`, do not automatically recover, start a replacement task, or close it. Explain the options and let the user choose:
|
|
131
134
|
|
|
132
135
|
- `AKK recover <conversation-id>`: use `agent_knock_knock_recover` to start a new coding-agent session with AKK's saved protocol history summary plus the pending message.
|
|
133
|
-
- `AKK restart <conversation-id>`: use `agent_knock_knock_restart` to start a new coding-agent session with only the pending message.
|
|
134
136
|
- `AKK close <conversation-id>`: use `agent_knock_knock_close` to close the task.
|
|
137
|
+
- Start a new independent `AKK <task>` delegation if the old task should not be recovered.
|
|
135
138
|
|
|
136
139
|
Make clear that `recover` is AKK replay recovery, not guaranteed native coding-agent session resume.
|
|
137
140
|
|
|
138
|
-
|
|
141
|
+
Do not start a replacement task without the user's explicit choice.
|
|
139
142
|
|
|
140
143
|
## Native Session Takeover
|
|
141
144
|
|
|
@@ -151,6 +154,7 @@ Use `agent_knock_knock_agent_takeover` when the user wants AKK to take over an e
|
|
|
151
154
|
|
|
152
155
|
- `safe_resume`: allowed only when no active Codex CLI matches the session. If the result is `ready`, explain that this is safe to resume because AKK did not find an active conflicting CLI. If the user confirms attaching it to AKK, call again with `createConversation=true`, then use the returned `conversation_id` for `AKK send`, `AKK status`, and `AKK close`.
|
|
153
156
|
- `terminate_then_resume`: use when the user wants to take over an active native Codex CLI. The first call is side-effect-free. If the result is `requires_confirmation`, explain the exact pid, cwd, and session that would be stopped. Only after explicit user confirmation, call `agent_knock_knock_agent_takeover` again with `strategy="terminate_then_resume"`, `createConversation=true`, `confirmTerminate=true`, and `expectedPid=<confirmed pid>`. AKK will re-scan before terminating and will only stop an exact session match. If Codex does not expose a session id and the user still explicitly confirms a specific pid in the target cwd, you may add `allowCwdOnly=true`; explain that this is higher risk because it relies on pid and cwd rather than a visible session id.
|
|
157
|
+
- `terminal_control`: use when the target Codex CLI is running inside tmux and the user wants AKK to operate the existing TUI without stopping or resuming it. The first call is side-effect-free. If the result is `requires_confirmation`, show the exact tmux target, pid, cwd, and current terminal-control metadata. Only after explicit user confirmation, call again with `strategy="terminal_control"`, `createConversation=true`, `confirmTerminal=true`, and `terminalTarget=<confirmed target>`. Follow-up `AKK send` messages will be typed into the tmux pane. Before `agent_knock_knock_approve`, call `agent_knock_knock_status`, show the terminal screen excerpt, and ask for explicit approval.
|
|
154
158
|
- `fork`: use when the user wants to avoid stopping the original Codex CLI. First call returns a bounded context package plus `summaryPrompt` and `nextAction`; use that prompt to summarize as OpenClaw, ask the user to confirm, and do not inject raw full rollout history directly. After the user confirms the summary, call `agent_knock_knock_agent_takeover` again with `strategy="fork"`, `createConversation=true`, and `forkSummary=<approved summary>` to create the forked AKK-managed session. Then use the returned `conversation_id` with `AKK send` for follow-up work.
|
|
155
159
|
|
|
156
160
|
Do not present `fork` as a standalone command or standalone feature. It is a takeover strategy.
|