@scotthuang/agent-knock-knock 0.13.15 → 0.13.16
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 +5 -0
- package/README.md +2 -1
- package/dist/src/cli-core.js +6 -3
- package/dist/src/cli-core.js.map +1 -1
- package/dist/src/codex-permission-surface.d.ts +23 -0
- package/dist/src/codex-permission-surface.js +211 -0
- package/dist/src/codex-permission-surface.js.map +1 -0
- package/dist/src/native-thread-lifecycle-cli-adapter.d.ts +5 -4
- package/dist/src/native-thread-lifecycle-cli-adapter.js +20 -0
- package/dist/src/native-thread-lifecycle-cli-adapter.js.map +1 -1
- package/dist/src/semantic-permission-control.d.ts +19 -0
- package/dist/src/semantic-permission-control.js +174 -0
- package/dist/src/semantic-permission-control.js.map +1 -0
- package/dist/src/semantic-tool-command-helpers.d.ts +7 -0
- package/dist/src/semantic-tool-command-helpers.js +29 -1
- package/dist/src/semantic-tool-command-helpers.js.map +1 -1
- package/dist/src/semantic-tool-list-projection.js +4 -0
- package/dist/src/semantic-tool-list-projection.js.map +1 -1
- package/dist/src/semantic-tool-presentation.js +5 -2
- package/dist/src/semantic-tool-presentation.js.map +1 -1
- package/dist/src/semantic-tool-runtime.js +7 -1
- package/dist/src/semantic-tool-runtime.js.map +1 -1
- package/dist/src/semantic-tool-schemas.d.ts +33 -0
- package/dist/src/semantic-tool-schemas.js +33 -0
- package/dist/src/semantic-tool-schemas.js.map +1 -1
- package/dist/src/terminal-action-projection.d.ts +1 -1
- package/dist/src/terminal-action-projection.js.map +1 -1
- package/dist/src/terminal-agent-bridge.d.ts +3 -0
- package/dist/src/terminal-agent-bridge.js +11 -0
- package/dist/src/terminal-agent-bridge.js.map +1 -1
- package/dist/src/terminal-composer-classifier.js +29 -3
- package/dist/src/terminal-composer-classifier.js.map +1 -1
- package/dist/src/terminal-list-cli-adapter.js +7 -12
- package/dist/src/terminal-list-cli-adapter.js.map +1 -1
- package/dist/src/terminal-list-renderer.d.ts +7 -0
- package/dist/src/terminal-list-renderer.js +53 -0
- package/dist/src/terminal-list-renderer.js.map +1 -1
- package/dist/src/terminal-monitor-decision-policy.d.ts +1 -1
- package/dist/src/terminal-native-control-cli-contract.d.ts +16 -0
- package/dist/src/terminal-native-control-cli-contract.js +2 -0
- package/dist/src/terminal-native-control-cli-contract.js.map +1 -0
- package/dist/src/terminal-permission-control-availability.d.ts +31 -0
- package/dist/src/terminal-permission-control-availability.js +50 -0
- package/dist/src/terminal-permission-control-availability.js.map +1 -0
- package/dist/src/terminal-permission-control-bridge.d.ts +16 -0
- package/dist/src/terminal-permission-control-bridge.js +93 -0
- package/dist/src/terminal-permission-control-bridge.js.map +1 -0
- package/dist/src/terminal-permission-control-cli-adapter.d.ts +31 -0
- package/dist/src/terminal-permission-control-cli-adapter.js +152 -0
- package/dist/src/terminal-permission-control-cli-adapter.js.map +1 -0
- package/dist/src/terminal-permission-control-list-projection.d.ts +23 -0
- package/dist/src/terminal-permission-control-list-projection.js +47 -0
- package/dist/src/terminal-permission-control-list-projection.js.map +1 -0
- package/dist/src/terminal-permission-control-runtime.d.ts +28 -0
- package/dist/src/terminal-permission-control-runtime.js +88 -0
- package/dist/src/terminal-permission-control-runtime.js.map +1 -0
- package/dist/src/terminal-permission-control.d.ts +69 -0
- package/dist/src/terminal-permission-control.js +217 -0
- package/dist/src/terminal-permission-control.js.map +1 -0
- package/docs/codex-permissions.md +95 -0
- package/openclaw.plugin.json +9 -1
- package/package.json +3 -2
- package/templates/openclaw-skills/agent-knock-knock/SKILL.md +6 -1
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { terminalPhysicalBindingToken } from "./terminal-control-ref.js";
|
|
3
|
+
/** Permission writes have their own reviewed UI contract, separate from reads/model control. */
|
|
4
|
+
export function terminalPermissionControlProfileFor(version) {
|
|
5
|
+
return ["0.159.2", "0.159.3"].includes(version)
|
|
6
|
+
? { agentVersion: version, behaviorProfile: "codex-permissions-fullscreen-v1", scope: "current_session" }
|
|
7
|
+
: undefined;
|
|
8
|
+
}
|
|
9
|
+
export function terminalPermissionControlBindingToken(value) {
|
|
10
|
+
const profile = terminalPermissionControlProfileFor(value.agentVersion);
|
|
11
|
+
if (!profile || profile.behaviorProfile !== value.behaviorProfile) {
|
|
12
|
+
throw new Error("unsupported native permission-control profile");
|
|
13
|
+
}
|
|
14
|
+
return digest({
|
|
15
|
+
authority: "terminal_permission_control", version: 1,
|
|
16
|
+
physical: terminalPhysicalBindingToken({ ...value, agent: "codex" }),
|
|
17
|
+
agentVersion: value.agentVersion, behaviorProfile: value.behaviorProfile
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/** A transport failure may have delivered input; no cleanup or retry follows it. */
|
|
21
|
+
export class TerminalPermissionInputUncertainError extends Error {
|
|
22
|
+
doNotRetry = true;
|
|
23
|
+
}
|
|
24
|
+
export function permissionModeFromStatus(value) {
|
|
25
|
+
if (value === "Full Access")
|
|
26
|
+
return "full_access";
|
|
27
|
+
if (value === "Workspace (Ask for approval)")
|
|
28
|
+
return "ask_for_approval";
|
|
29
|
+
if (value === "Workspace (Approve for me)")
|
|
30
|
+
return "approve_for_me";
|
|
31
|
+
if (value === "Read Only (Ask for approval)" || value === "Read Only")
|
|
32
|
+
return "read_only";
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
async function waitFor(ports, state) {
|
|
36
|
+
for (let attempt = 0; attempt < 35; attempt += 1) {
|
|
37
|
+
const captured = await ports.capture();
|
|
38
|
+
if (captured.state === state)
|
|
39
|
+
return captured;
|
|
40
|
+
await ports.sleep(100);
|
|
41
|
+
}
|
|
42
|
+
throw new Error(`Codex permission control did not prove its ${state} postcondition`);
|
|
43
|
+
}
|
|
44
|
+
async function openPicker(ports) {
|
|
45
|
+
const empty = await ports.capture();
|
|
46
|
+
if (empty.state !== "idle")
|
|
47
|
+
throw new Error("permission control requires an idle, exactly empty Codex Composer");
|
|
48
|
+
await ports.input("command", empty);
|
|
49
|
+
await ports.input("C-m", await waitFor(ports, "command"));
|
|
50
|
+
return await waitFor(ports, "picker");
|
|
51
|
+
}
|
|
52
|
+
async function dismiss(ports, picker) {
|
|
53
|
+
await ports.input("Escape", picker);
|
|
54
|
+
await waitFor(ports, "idle");
|
|
55
|
+
}
|
|
56
|
+
function catalog(profile, status, picker) {
|
|
57
|
+
const current = picker.rows.filter((row) => row.current);
|
|
58
|
+
if (current.length > 1 || current.length === 1 && current[0].id !== status.mode ||
|
|
59
|
+
current.length === 0 && picker.rows.some((row) => row.id === status.mode)) {
|
|
60
|
+
throw new Error("native permission menu and fresh /status disagree about current permissions");
|
|
61
|
+
}
|
|
62
|
+
const choices = picker.rows.map(({ id, label, description }) => ({
|
|
63
|
+
id, label, description
|
|
64
|
+
}));
|
|
65
|
+
return {
|
|
66
|
+
agent: "codex", ...profile, current: status.mode, choices,
|
|
67
|
+
catalogFingerprint: digest({ ...profile, threadId: status.threadId, current: status.mode, choices })
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/** Only clean up a freshly re-proven surface owned by this operation. */
|
|
71
|
+
async function cleanup(ports) {
|
|
72
|
+
const frame = await ports.capture();
|
|
73
|
+
if (frame.state === "picker")
|
|
74
|
+
return dismiss(ports, frame);
|
|
75
|
+
if (frame.state === "command") {
|
|
76
|
+
await ports.input("Escape", frame);
|
|
77
|
+
const bare = await waitFor(ports, "bare_command");
|
|
78
|
+
await ports.input("C-u", bare);
|
|
79
|
+
await waitFor(ports, "idle");
|
|
80
|
+
}
|
|
81
|
+
else if (frame.state === "bare_command") {
|
|
82
|
+
await ports.input("C-u", frame);
|
|
83
|
+
await waitFor(ports, "idle");
|
|
84
|
+
}
|
|
85
|
+
else if (frame.state !== "idle") {
|
|
86
|
+
throw new TerminalPermissionInputUncertainError("permission cleanup cannot prove an empty Composer; do not retry automatically");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export async function discoverTerminalPermissionOptions(profile, ports) {
|
|
90
|
+
// Fresh status binds the catalog to a native thread, including paginated sessions
|
|
91
|
+
// with no open rollout. No app-server write or persistent AKK Session is needed.
|
|
92
|
+
const status = await ports.inspectStatus();
|
|
93
|
+
try {
|
|
94
|
+
const picker = await openPicker(ports);
|
|
95
|
+
const result = catalog(profile, status, picker);
|
|
96
|
+
await dismiss(ports, picker);
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
if (!(error instanceof TerminalPermissionInputUncertainError)) {
|
|
101
|
+
try {
|
|
102
|
+
await cleanup(ports);
|
|
103
|
+
}
|
|
104
|
+
catch (cause) {
|
|
105
|
+
throw new TerminalPermissionInputUncertainError("native permission cleanup is uncertain; do not retry automatically", { cause });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export async function switchTerminalPermissions(profile, mode, expectedCatalogFingerprint, ports) {
|
|
112
|
+
if (!["ask_for_approval", "approve_for_me", "full_access", "read_only"].includes(mode)) {
|
|
113
|
+
throw new Error("permission mode must come from the current native permission catalog");
|
|
114
|
+
}
|
|
115
|
+
let status;
|
|
116
|
+
try {
|
|
117
|
+
status = await ports.inspectStatus();
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
if (error instanceof TerminalPermissionInputUncertainError)
|
|
121
|
+
return uncertain(mode);
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
let selectionAttempted = false;
|
|
125
|
+
try {
|
|
126
|
+
let picker = await openPicker(ports);
|
|
127
|
+
const offered = catalog(profile, status, picker);
|
|
128
|
+
if (offered.catalogFingerprint !== expectedCatalogFingerprint) {
|
|
129
|
+
throw new Error("native thread or permission catalog changed; refresh permission-options");
|
|
130
|
+
}
|
|
131
|
+
const target = picker.rows.find((row) => row.id === mode);
|
|
132
|
+
if (!target)
|
|
133
|
+
throw new Error("requested permission mode is not available in this native menu");
|
|
134
|
+
if (mode === offered.current) {
|
|
135
|
+
await dismiss(ports, picker);
|
|
136
|
+
return success("already_effective", mode);
|
|
137
|
+
}
|
|
138
|
+
picker = await selectPermissionRow(profile, status, picker, target.index, offered.catalogFingerprint, ports);
|
|
139
|
+
selectionAttempted = true;
|
|
140
|
+
await ports.input("C-m", picker);
|
|
141
|
+
if (mode === "full_access")
|
|
142
|
+
await confirmFullAccess(ports);
|
|
143
|
+
await verifyPermissionSelection(profile, status, mode, ports);
|
|
144
|
+
return success("changed", mode);
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
if (selectionAttempted || error instanceof TerminalPermissionInputUncertainError) {
|
|
148
|
+
return uncertain(mode);
|
|
149
|
+
}
|
|
150
|
+
try {
|
|
151
|
+
await cleanup(ports);
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
return uncertain(mode);
|
|
155
|
+
}
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async function selectPermissionRow(profile, status, initial, targetIndex, fingerprint, ports) {
|
|
160
|
+
let picker = initial;
|
|
161
|
+
for (let moves = 0; picker.selectedIndex !== targetIndex; moves += 1) {
|
|
162
|
+
if (moves >= picker.rows.length)
|
|
163
|
+
throw new Error("native permission selection did not converge");
|
|
164
|
+
const expectedIndex = picker.selectedIndex + (picker.selectedIndex < targetIndex ? 1 : -1);
|
|
165
|
+
await ports.input(picker.selectedIndex < targetIndex ? "Down" : "Up", picker);
|
|
166
|
+
picker = await waitForSelection(ports, "picker", expectedIndex);
|
|
167
|
+
if (catalog(profile, status, picker).catalogFingerprint !== fingerprint) {
|
|
168
|
+
throw new Error("native permission catalog changed during selection");
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return picker;
|
|
172
|
+
}
|
|
173
|
+
async function confirmFullAccess(ports) {
|
|
174
|
+
let confirmation = await waitFor(ports, "full_access_confirmation");
|
|
175
|
+
if (confirmation.state !== "full_access_confirmation")
|
|
176
|
+
throw new Error("full-access confirmation is unavailable");
|
|
177
|
+
if (confirmation.selectedIndex !== 0) {
|
|
178
|
+
await ports.input("Up", confirmation);
|
|
179
|
+
confirmation = await waitForSelection(ports, "full_access_confirmation", 0);
|
|
180
|
+
}
|
|
181
|
+
await ports.input("C-m", confirmation);
|
|
182
|
+
}
|
|
183
|
+
async function verifyPermissionSelection(profile, previous, mode, ports) {
|
|
184
|
+
await waitFor(ports, "idle");
|
|
185
|
+
// A request echo is not completion. Fresh /status plus a reopened current
|
|
186
|
+
// menu marker must independently agree about this same native thread.
|
|
187
|
+
const effective = await ports.inspectStatus();
|
|
188
|
+
if (effective.threadId !== previous.threadId || effective.mode !== mode) {
|
|
189
|
+
throw new Error("native permission update was not proven on the original thread");
|
|
190
|
+
}
|
|
191
|
+
const verified = await openPicker(ports);
|
|
192
|
+
if (catalog(profile, effective, verified).current !== mode ||
|
|
193
|
+
!verified.rows.some((row) => row.id === mode && row.current)) {
|
|
194
|
+
throw new Error("native permission menu did not confirm the requested current mode");
|
|
195
|
+
}
|
|
196
|
+
await dismiss(ports, verified);
|
|
197
|
+
}
|
|
198
|
+
async function waitForSelection(ports, state, index) {
|
|
199
|
+
for (let attempt = 0; attempt < 35; attempt += 1) {
|
|
200
|
+
const frame = await ports.capture();
|
|
201
|
+
if (frame.state === state && frame.selectedIndex === index)
|
|
202
|
+
return frame;
|
|
203
|
+
await ports.sleep(100);
|
|
204
|
+
}
|
|
205
|
+
throw new Error("Codex permission selection did not match its expected row");
|
|
206
|
+
}
|
|
207
|
+
function success(outcome, mode) {
|
|
208
|
+
return { outcome, requested: { mode }, effective: { mode }, scope: "current_session", defaultsChanged: false, doNotRetry: false };
|
|
209
|
+
}
|
|
210
|
+
function uncertain(mode) {
|
|
211
|
+
return { outcome: "uncertain", requested: { mode }, scope: "current_session", defaultsChanged: false,
|
|
212
|
+
doNotRetry: true, reason: "Native permission input or its postcondition is uncertain; inspect the terminal and refresh permissions before another deliberate action." };
|
|
213
|
+
}
|
|
214
|
+
function digest(value) {
|
|
215
|
+
return createHash("sha256").update(JSON.stringify(value)).digest("hex");
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=terminal-permission-control.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-permission-control.js","sourceRoot":"","sources":["../../src/terminal-permission-control.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Set Codex permissions before a task
|
|
2
|
+
|
|
3
|
+
AKK can inspect and change the built-in permissions of an existing, idle Codex
|
|
4
|
+
session through its native `/permissions` menu. The terminal must have an empty
|
|
5
|
+
Composer and no running task, approval, question, editor, or viewer. AKK verifies
|
|
6
|
+
the physical pane/process and native thread before acting.
|
|
7
|
+
|
|
8
|
+
In a controller conversation:
|
|
9
|
+
|
|
10
|
+
```text
|
|
11
|
+
/akk list
|
|
12
|
+
/akk permissions <exact-terminal-id>
|
|
13
|
+
/akk set-permissions <exact-terminal-id> <advertised-mode-id>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Use the permission action advertised by the current List row. The first command
|
|
17
|
+
opens and dismisses closed native UI inspection; it does not change permissions.
|
|
18
|
+
It returns the current mode and the modes this native picker actually offers.
|
|
19
|
+
Use the exact semantic ID for the requested or authorized permission mode.
|
|
20
|
+
For example, `ask_for_approval` may be available on a given Codex build. A mode
|
|
21
|
+
reported as current is not necessarily selectable: macOS can report `read_only`
|
|
22
|
+
while omitting it from its menu. Named/custom profiles are not supported.
|
|
23
|
+
|
|
24
|
+
The corresponding tools are:
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
agent_knock_knock_permission_options({terminal_id})
|
|
28
|
+
agent_knock_knock_set_permissions({terminal_id, mode})
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Both calls must use the same controller conversation. The private catalog is
|
|
32
|
+
valid for one attempt only; a refresh replaces it. Callers cannot provide raw
|
|
33
|
+
slash commands, keys, menu indexes, display labels, paths, fingerprints, or tokens.
|
|
34
|
+
|
|
35
|
+
Full Access is an ordinary selectable mode and needs no additional user
|
|
36
|
+
confirmation. AKK automatically handles its exact native confirmation inside
|
|
37
|
+
this permission transaction, without pausing for a second user reply or using
|
|
38
|
+
the generic approval tool. Ordinary Send does not change permissions.
|
|
39
|
+
|
|
40
|
+
A verified change returns `outcome=changed` or `already_effective`, the requested
|
|
41
|
+
and effective mode, `scope=current_session`, and `defaults_changed=false`.
|
|
42
|
+
Changes apply to this session/thread and may remain when the thread is resumed;
|
|
43
|
+
they do not change global defaults. Send the task only after the effective mode
|
|
44
|
+
matches the request. If the result is `uncertain`, inspect the terminal and do not
|
|
45
|
+
retry automatically. A running or blocked terminal must reach a safe idle state
|
|
46
|
+
before permission inspection; AKK does not interrupt its task to open the menu.
|
|
47
|
+
|
|
48
|
+
## Compatibility and verification
|
|
49
|
+
|
|
50
|
+
The permission-write profile currently covers Codex 0.159.2 and 0.159.3. It is
|
|
51
|
+
independent of native model selection, task observation, and interaction-write
|
|
52
|
+
profiles. Unsupported versions, named/custom profiles, disabled or incomplete
|
|
53
|
+
menus, and conflicting native status stop the operation before a permission
|
|
54
|
+
selection. A permission catalog never grants authority over another native
|
|
55
|
+
thread, even when its process and pane are unchanged.
|
|
56
|
+
|
|
57
|
+
On 2026-10-02, isolated macOS sessions running the locally installed Codex
|
|
58
|
+
0.159.3 were exercised through the built AKK CLI:
|
|
59
|
+
|
|
60
|
+
- **tmux:** discovered `read_only`, selected `ask_for_approval`, and proved
|
|
61
|
+
`Workspace (Ask for approval)` in a fresh native status plus the menu's current
|
|
62
|
+
marker. A subsequent AKK Send created a temporary file with exactly the
|
|
63
|
+
requested contents, and Codex returned `DONE`.
|
|
64
|
+
- **Herdr:** discovered `read_only`, selected `full_access` through the exact
|
|
65
|
+
native confirmation, then proved `Full Access` in a fresh status and the
|
|
66
|
+
reopened menu's current marker. The operation dismissed the menu afterward.
|
|
67
|
+
- Both sessions used a temporary workspace and private AKK Store. Existing user
|
|
68
|
+
sessions were untouched. Permission selection did not change global Codex
|
|
69
|
+
configuration; the test-only workspace trust entry was removed on cleanup.
|
|
70
|
+
|
|
71
|
+
`npm run test:fast` passed all 2,433 tests, including stale physical/thread
|
|
72
|
+
identity, stale catalogs, confirmation grammar, changed input frames, uncertain
|
|
73
|
+
transport, one-attempt authority, and ordinary Send/approval separation.
|
|
74
|
+
`npm run validate:architecture` and `npm run validate:refactor-evidence` passed.
|
|
75
|
+
Full/release suites were not run during development, per the repository's test policy.
|
|
76
|
+
|
|
77
|
+
Codex 0.159.2 has source-contract and regression coverage; it was not launched
|
|
78
|
+
for this live check. `approve_for_me` and a selectable `read_only` transition,
|
|
79
|
+
custom profiles, other platforms, and an external controller's complete
|
|
80
|
+
permission-to-callback conversation were not exercised live. Host/connector
|
|
81
|
+
tool registration and controller-scoped authority are covered by regression
|
|
82
|
+
checks; the live operations above used the CLI.
|
|
83
|
+
|
|
84
|
+
Scott subsequently tested the locally installed `0.13.16-local.permissions.20261002`
|
|
85
|
+
candidate successfully and authorized the npm and ClawHub `0.13.16` release.
|
|
86
|
+
|
|
87
|
+
The immediate pre-publication `npm run test:release` gate passed all 2,948
|
|
88
|
+
tests. Its isolated OpenClaw 2026.9.1 check loaded all 24 tools and passed
|
|
89
|
+
callback delivery, doctor, bundled Skill eligibility, update/reinstall, and
|
|
90
|
+
uninstall checks. ClawHub runtime validation passed with zero breakages or
|
|
91
|
+
warnings, and its publication dry run passed. The formal package's 248 runtime
|
|
92
|
+
JavaScript files and bundled Skill match the user-tested candidate; only release
|
|
93
|
+
metadata, verification documentation, and an older action-list test changed
|
|
94
|
+
after that candidate. The optional general native lifecycle smoke was not rerun;
|
|
95
|
+
the permission-specific live coverage and remaining limits are listed above.
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "agent-knock-knock",
|
|
3
3
|
"name": "Agent Knock Knock",
|
|
4
4
|
"categories": ["developer-tools"],
|
|
5
|
-
"description": "Control local Codex and Claude Code through shared tmux or Herdr terminals, with closed native status inspection
|
|
5
|
+
"description": "Control local Codex and Claude Code through shared tmux or Herdr terminals, with closed native status inspection, model switching, and Codex permission control, compatibility warnings for unverified versions, native-thread lifecycle controls, managed monitoring, durable Terminal Watch, approvals, and human takeover.",
|
|
6
6
|
"activation": {
|
|
7
7
|
"onStartup": true,
|
|
8
8
|
"onCommands": ["akk"]
|
|
@@ -23,6 +23,8 @@
|
|
|
23
23
|
"agent_knock_knock_model_options",
|
|
24
24
|
"agent_knock_knock_repair_model_control",
|
|
25
25
|
"agent_knock_knock_set_model",
|
|
26
|
+
"agent_knock_knock_permission_options",
|
|
27
|
+
"agent_knock_knock_set_permissions",
|
|
26
28
|
"agent_knock_knock_identify_foreground",
|
|
27
29
|
"agent_knock_knock_identify_and_send",
|
|
28
30
|
"agent_knock_knock_new_thread",
|
|
@@ -64,6 +66,12 @@
|
|
|
64
66
|
"agent_knock_knock_set_model": {
|
|
65
67
|
"optional": true
|
|
66
68
|
},
|
|
69
|
+
"agent_knock_knock_permission_options": {
|
|
70
|
+
"optional": true
|
|
71
|
+
},
|
|
72
|
+
"agent_knock_knock_set_permissions": {
|
|
73
|
+
"optional": true
|
|
74
|
+
},
|
|
67
75
|
"agent_knock_knock_identify_foreground": {
|
|
68
76
|
"optional": true
|
|
69
77
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scotthuang/agent-knock-knock",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.16",
|
|
4
4
|
"description": "Control local Codex and Claude Code from OpenClaw or compatible controller Hosts through shared terminals.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -91,7 +91,8 @@
|
|
|
91
91
|
"docs/codex-0.159.0-compatibility.md",
|
|
92
92
|
"docs/codex-0.159.2-compatibility.md",
|
|
93
93
|
"docs/claude-2.1.285-compatibility.md",
|
|
94
|
-
"docs/callback-compatibility.md"
|
|
94
|
+
"docs/callback-compatibility.md",
|
|
95
|
+
"docs/codex-permissions.md"
|
|
95
96
|
],
|
|
96
97
|
"publishConfig": {
|
|
97
98
|
"access": "public"
|
|
@@ -32,6 +32,8 @@ Core slash-command forms:
|
|
|
32
32
|
- `/akk models <exact-terminal-id>`: inspect the exact native model and reasoning-effort catalog for one verified idle terminal.
|
|
33
33
|
- `/akk repair-model-control <exact-terminal-id>`: dismiss only a currently advertised exact stale profiled Codex 0.154.0/0.155.1 `/model` Composer surface or open native model picker and prove an empty Composer.
|
|
34
34
|
- `/akk set-model <exact-terminal-id> <advertised-model-id> <advertised-reasoning-effort>`: consume that displayed catalog once and change only the advertised semantic tuple.
|
|
35
|
+
- `/akk permissions <exact-terminal-id>`: inspect the idle Codex pane’s current permission mode and native built-in choices.
|
|
36
|
+
- `/akk set-permissions <exact-terminal-id> <advertised-mode-id>`: apply the user-selected mode from that immediately preceding catalog.
|
|
35
37
|
- `/akk new-thread <exact-terminal-id>` or `/akk clear-thread <exact-terminal-id>`: switch that idle terminal to a verified clean native context without creating a Turn.
|
|
36
38
|
- `/akk resume-thread <exact-terminal-id> [uuid|previous|number|@short-id]`: list candidates when the selection is omitted, or resume one exact snapshot-bound choice without creating a Turn. `previous` also accepts the human phrase `刚才那个`.
|
|
37
39
|
- `/akk status [turn-selector|terminal-watch-id]`: inspect one live terminal, exact managed Turn, or exact Terminal Watch.
|
|
@@ -115,6 +117,8 @@ Approval attention is notification-only for every Watch: never call an approval
|
|
|
115
117
|
|
|
116
118
|
The current integrations register the complete capability-handshake-verified semantic AKK tool catalog and list action-contract v30. Structured OpenClaw, Pi, and DeepSeek Harness Lists use compact projection v1 and point here for the static contract; the CLI keeps the complete operator/debug action contract. Every structured model action carries semantic IDs only; opaque fences, Composer digests, and draft text are derived or retained privately. Watch uses `agent_knock_knock_watch({terminal_id})`, `agent_knock_knock_status({watch_id})`, and `agent_knock_knock_unwatch({watch_id})`; its internal CLI boundary is `watch-terminal`, `watch-status`, `unwatch-terminal`, and `reconcile-watches`.
|
|
117
119
|
|
|
120
|
+
For Codex permission changes, first call `agent_knock_knock_permission_options({terminal_id})` from the current row’s advertised action. This sends closed `/status` and `/permissions` inspection input but leaves permissions unchanged; the terminal must be idle, its Composer empty, and its physical and native thread identities verifiable. Use `current`, `scope`, and the returned choice descriptions to select the requested or authorized mode. Then call `agent_knock_knock_set_permissions({terminal_id,mode})` using its exact returned semantic ID in the same controller conversation. Full Access is an ordinary option and needs no additional user confirmation. AKK automatically handles its exact native confirmation inside this permission transaction; do not pause to ask the user to confirm Full Access or call generic `approve` for that dialog. Ordinary Send does not change permissions. Only currently displayed built-in modes are supported: do not invent `read_only` when the picker omits it, supply a named/custom profile, or pass commands, labels, menu indexes, keys, tokens, or scope overrides. Changes affect the current session/thread, may be retained on Resume, and leave global defaults unchanged. Send the intended task only after `outcome="changed"` or `"already_effective"` with matching `effective.mode`; `"uncertain"` means stop and do not retry automatically. Refresh the catalog after any change or consumed attempt.
|
|
121
|
+
|
|
118
122
|
For native model control, first call `agent_knock_knock_model_options({terminal_id})` only from the current terminal row's advertised action. This is explicit current-snapshot authority for one exact physical pane/process: Profiled Codex 0.154.0/0.155.1 may use either one exact current native Session or a verified-zero-rollout pane, where `identify_foreground` is diagnostic rather than a prerequisite; Claude Code still requires one exact current native Session. The pane must have no active Turn, approval, questionnaire/editor, or read-only viewer. It normally requires an idle empty Composer; when List advertises `model_options` for one exact stable profiled Codex 0.154.0/0.155.1 `/model` residual, AKK may continue only that residual into read-only catalog discovery. Show the returned `scope`, current selection, and semantic model/effort catalog to the user. Then call `agent_knock_knock_set_model({terminal_id,model,reasoning_effort})` with an exact required tuple from that same result in the same controller conversation. Codex scope is always `current_and_new_sessions`: a successful selection persists the model and an ordinary effort (including `max`) for future sessions, but `ultra` is current-session-only and Codex chooses a non-Ultra future fallback. Always read `effective` and `new_session_defaults` separately. Claude Code scope is always `current_session`. There is no caller-selectable scope. Never pass a display label, menu index, slash command, raw key, token, or fingerprint. A stale or consumed catalog must be refreshed, and `outcome="uncertain"` must never be retried automatically.
|
|
119
123
|
|
|
120
124
|
If the current List also advertises `repair_model_control`, it is the explicit
|
|
@@ -236,6 +240,7 @@ Action-name glossary:
|
|
|
236
240
|
- `list_resumable_threads`, `new_thread`, and `resume_thread`: inspect or change native thread context through their closed lifecycle protocols.
|
|
237
241
|
- `native_inspect`: run only an advertised closed native inspection such as `status`.
|
|
238
242
|
- `model_options`, `repair_model_control`, and `set_model`: discover the current native catalog, clear only a proven model-control residue, or consume one catalog offer.
|
|
243
|
+
- `permission_options` and `set_permissions`: inspect one idle Codex pane’s built-in permission modes, then consume one catalog for the requested or authorized change, including Full Access without an extra confirmation. Ordinary Send never increases permissions.
|
|
239
244
|
- `identify_foreground` / `identify_and_send`: diagnose Codex foreground identity, or keep that diagnosis and one Send atomic.
|
|
240
245
|
- `reconcile_binding`: detach only the exact listed stale/conflicting AKK binding after explicit user confirmation.
|
|
241
246
|
- `respond`: answer ordinary text inside the current managed Turn.
|
|
@@ -248,7 +253,7 @@ Action-name glossary:
|
|
|
248
253
|
|
|
249
254
|
The tool name is normally `agent_knock_knock_<action-name>`. The sole List alias is `retry_submission`, which invokes `agent_knock_knock_send` with its listed `turn_id` only after explicit confirmation. Nested `handoff_decision.choices.take_over_current.action` and `blocking_turns[].recovery_action` carry their explicit tool/action name and semantic arguments; the explanatory choice and recovery text is defined here rather than repeated in every List row.
|
|
250
255
|
|
|
251
|
-
`available_actions` is the authoritative current-action source for mutations after listing except for the explicitly modeled nested handoff decision and `blocking_turns[].recovery_action`; user-selected `watch({terminal_id})` deliberately honors an exact user-selected terminal even without advertisement. A native interaction response instead requires the current `interaction_state` returned by Status in the same controller conversation. Approval, native interaction response, handoff takeover, and `reconcile_binding` require explicit user intent and fresh source state. Model-facing shapes include `model_options({terminal_id})`, the separately advertised Codex-only `repair_model_control({terminal_id})`, and `set_model({terminal_id,model,reasoning_effort})`; `watch({terminal_id})`; `send({session_id|terminal_id,request})`, with the targets mutually exclusive; `identify_foreground({terminal_id})`; `identify_and_send({terminal_id,request})`; `respond_interaction({turn_id|watch_id,interaction_id,answers,delivery_mode?})`, with exactly one subject id, only projected question/option ids, and `delivery_mode` present only for `async_question`; managed `approve({turn_id,decision})` or approve-once-only terminal-scoped `approve({terminal_id})`; `native_inspect({terminal_id,inspection})`; `new_thread({terminal_id})`; `resume_thread({terminal_id,native_thread_id})`; and `reconcile_binding({terminal_id,conflicting_session_id})`. A top-level `previous` block, when present, is the only authority for a “previous/刚才那个” request; human-facing numbers and short IDs remain slash-navigation aids and are never structured tool arguments. The model never carries terminal, binding, catalog, candidate, composer, handoff, approval, interaction-fingerprint, revision, binding ID/generation, or handoff-only live-native-UUID fences; it never receives draft text or composer digests. `native_thread_id` remains the semantic resume identity. AKK derives those private fences and revalidates them before side effects. Orphan-close `expected_message_id` and `expected_transition_id` remain because they are entity IDs. Store format remains 1 and writer protocol is 9; Terminal Watch schema remains 3.
|
|
256
|
+
`available_actions` is the authoritative current-action source for mutations after listing except for the explicitly modeled nested handoff decision and `blocking_turns[].recovery_action`; user-selected `watch({terminal_id})` deliberately honors an exact user-selected terminal even without advertisement. A native interaction response instead requires the current `interaction_state` returned by Status in the same controller conversation. Approval, native interaction response, handoff takeover, and `reconcile_binding` require explicit user intent and fresh source state. Model-facing shapes include `permission_options({terminal_id})` and `set_permissions({terminal_id,mode})`; `model_options({terminal_id})`, the separately advertised Codex-only `repair_model_control({terminal_id})`, and `set_model({terminal_id,model,reasoning_effort})`; `watch({terminal_id})`; `send({session_id|terminal_id,request})`, with the targets mutually exclusive; `identify_foreground({terminal_id})`; `identify_and_send({terminal_id,request})`; `respond_interaction({turn_id|watch_id,interaction_id,answers,delivery_mode?})`, with exactly one subject id, only projected question/option ids, and `delivery_mode` present only for `async_question`; managed `approve({turn_id,decision})` or approve-once-only terminal-scoped `approve({terminal_id})`; `native_inspect({terminal_id,inspection})`; `new_thread({terminal_id})`; `resume_thread({terminal_id,native_thread_id})`; and `reconcile_binding({terminal_id,conflicting_session_id})`. A top-level `previous` block, when present, is the only authority for a “previous/刚才那个” request; human-facing numbers and short IDs remain slash-navigation aids and are never structured tool arguments. The model never carries terminal, binding, catalog, candidate, composer, handoff, approval, interaction-fingerprint, revision, binding ID/generation, or handoff-only live-native-UUID fences; it never receives draft text or composer digests. `native_thread_id` remains the semantic resume identity. AKK derives those private fences and revalidates them before side effects. Orphan-close `expected_message_id` and `expected_transition_id` remain because they are entity IDs. Store format remains 1 and writer protocol is 9; Terminal Watch schema remains 3.
|
|
252
257
|
|
|
253
258
|
Before every terminal operation, AKK revalidates the expected agent PID and provider-owned terminal identity. Native inspection and lifecycle input require an exactly empty Composer; managed Send may require exact empty before input. Codex and Claude Code `terminal_user_explicit` instead require a scanned non-blocked approval state and no proven input-owning questionnaire, editor, menu, or read-only viewer. Reviewed physical Send paths do not require ordinary main-Composer visibility, stability, or exactness. Unreviewed Codex frontends require a recognized styled Composer before clearing and a fresh empty styled Composer before task text. Existing drafts and parsed working activity do not themselves veto the user-priority path, and after text injection no Composer observation may veto Enter. Once clear or request input may have occurred, an uncertain result must not be retried automatically. Humans can attach to the same tmux or Herdr session and continue directly at any time.
|
|
254
259
|
|