@scotthuang/agent-knock-knock 0.13.14 → 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 +12 -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-app-server-read-client.d.ts +17 -1
- package/dist/src/codex-app-server-read-client.js +81 -37
- package/dist/src/codex-app-server-read-client.js.map +1 -1
- package/dist/src/codex-fullscreen-composer-proof.d.ts +3 -1
- package/dist/src/codex-fullscreen-composer-proof.js +11 -3
- package/dist/src/codex-fullscreen-composer-proof.js.map +1 -1
- package/dist/src/codex-lifecycle-compatibility.d.ts +9 -0
- package/dist/src/codex-lifecycle-compatibility.js +27 -0
- package/dist/src/codex-lifecycle-compatibility.js.map +1 -1
- package/dist/src/codex-paginated-observation.d.ts +1 -0
- package/dist/src/codex-paginated-observation.js +13 -4
- package/dist/src/codex-paginated-observation.js.map +1 -1
- package/dist/src/codex-paginated-task.d.ts +7 -5
- package/dist/src/codex-paginated-task.js +41 -17
- package/dist/src/codex-paginated-task.js.map +1 -1
- package/dist/src/codex-paginated-thread-binding.d.ts +5 -0
- package/dist/src/codex-paginated-thread-binding.js +52 -35
- package/dist/src/codex-paginated-thread-binding.js.map +1 -1
- package/dist/src/codex-paginated-thread-facts.d.ts +2 -3
- package/dist/src/codex-paginated-watch.d.ts +1 -1
- package/dist/src/codex-paginated-watch.js +19 -2
- package/dist/src/codex-paginated-watch.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/codex-status-history-navigation.js +4 -3
- package/dist/src/codex-status-history-navigation.js.map +1 -1
- package/dist/src/codex-terminal-agent-adapter.js +28 -12
- package/dist/src/codex-terminal-agent-adapter.js.map +1 -1
- 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/store.d.ts +1 -1
- package/dist/src/store.js +2 -2
- package/dist/src/store.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 +45 -6
- package/dist/src/terminal-agent-bridge.js.map +1 -1
- package/dist/src/terminal-composer-classifier.js +31 -5
- package/dist/src/terminal-composer-classifier.js.map +1 -1
- package/dist/src/terminal-human-explicit-send-cli-adapter.js +11 -0
- package/dist/src/terminal-human-explicit-send-cli-adapter.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-native-inspection-bridge.js +34 -25
- package/dist/src/terminal-native-inspection-bridge.js.map +1 -1
- 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/dist/src/terminal-send-watch-policy.js +9 -12
- package/dist/src/terminal-send-watch-policy.js.map +1 -1
- package/dist/src/terminal-watch-cli-adapter.d.ts +5 -10
- package/dist/src/terminal-watch-cli-adapter.js +51 -32
- package/dist/src/terminal-watch-cli-adapter.js.map +1 -1
- package/dist/src/terminal-watch-codec.js +11 -2
- package/dist/src/terminal-watch-codec.js.map +1 -1
- package/dist/src/terminal-watch-record.d.ts +8 -1
- package/dist/src/terminal-watch-record.js +16 -2
- package/dist/src/terminal-watch-record.js.map +1 -1
- package/dist/src/terminal-watch-send-activity.d.ts +28 -0
- package/dist/src/terminal-watch-send-activity.js +65 -0
- package/dist/src/terminal-watch-send-activity.js.map +1 -0
- package/dist/src/terminal-watch-service.d.ts +5 -0
- package/dist/src/terminal-watch-service.js +53 -6
- package/dist/src/terminal-watch-service.js.map +1 -1
- package/docs/callback-compatibility.md +84 -0
- package/docs/codex-permissions.md +95 -0
- package/openclaw.plugin.json +9 -1
- package/package.json +4 -2
- package/templates/openclaw-skills/agent-knock-knock/SKILL.md +21 -16
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { observeCodexPermissionSurface } from "./codex-permission-surface.js";
|
|
3
|
+
import { exactCodexFullscreenBareCommandCapture, exactCodexFullscreenSlashComposerCapture } from "./codex-fullscreen-composer-proof.js";
|
|
4
|
+
import { exactCodexReadyStyledComposerCapture, stripTerminalEscapeSequences } from "./terminal-native-inspection-bridge.js";
|
|
5
|
+
import { codexActiveWriterViewerVisible, codexBlockingModalVisible, inspectCodexAsyncQuestionInputMode } from "./terminal-composer-classifier.js";
|
|
6
|
+
import { inspectNativeQuestionnaire } from "./terminal-questionnaire-adapter.js";
|
|
7
|
+
import { TerminalPermissionInputUncertainError, terminalPermissionControlProfileFor } from "./terminal-permission-control.js";
|
|
8
|
+
/** The caller holds the terminal lock; every input consumes a fresh exact frame. */
|
|
9
|
+
export function createTerminalPermissionControlPorts(ports) {
|
|
10
|
+
if (ports.adapter.agent !== "codex" ||
|
|
11
|
+
!terminalPermissionControlProfileFor(ports.agentVersion) ||
|
|
12
|
+
ports.runtime.agentVersion !== ports.agentVersion) {
|
|
13
|
+
throw new Error("permission control requires an exact matching Codex behavior profile");
|
|
14
|
+
}
|
|
15
|
+
let inputPermit;
|
|
16
|
+
const captureFrame = async () => {
|
|
17
|
+
await ports.verifyIdentity();
|
|
18
|
+
const styled = await ports.captureStyled();
|
|
19
|
+
await ports.verifyIdentity();
|
|
20
|
+
const owned = observeCodexPermissionSurface(styled);
|
|
21
|
+
if (owned.state === "picker" || owned.state === "full_access_confirmation")
|
|
22
|
+
return owned;
|
|
23
|
+
const fingerprint = createHash("sha256").update(styled).digest("hex");
|
|
24
|
+
if (owned.state === "ambiguous")
|
|
25
|
+
return { state: "blocked", fingerprint };
|
|
26
|
+
const plain = stripTerminalEscapeSequences(styled);
|
|
27
|
+
const inspected = ports.adapter.inspectScreen({ screen: plain, runtime: ports.runtime });
|
|
28
|
+
const question = inspectNativeQuestionnaire({ agent: "codex", version: ports.agentVersion, screen: styled });
|
|
29
|
+
const asyncMode = inspectCodexAsyncQuestionInputMode(styled);
|
|
30
|
+
if (inspected.approval.blocked || inspected.activity.state === "working" ||
|
|
31
|
+
inspected.activity.state === "awaiting_approval" || codexBlockingModalVisible(styled) ||
|
|
32
|
+
question.status !== "none" || codexActiveWriterViewerVisible(styled) ||
|
|
33
|
+
asyncMode !== "absent")
|
|
34
|
+
return { state: "blocked", fingerprint };
|
|
35
|
+
// Native slash completions intentionally replace the idle shortcut footer,
|
|
36
|
+
// so the general activity classifier reports unknown. Their exact styled
|
|
37
|
+
// command grammar is the input proof; positive activity still blocks above.
|
|
38
|
+
const command = exactCodexFullscreenSlashComposerCapture(styled, "/permissions", ["› /permissions choose what Codex is allowed to do"], true, ports.agentVersion);
|
|
39
|
+
if (command)
|
|
40
|
+
return { state: "command", fingerprint: command.digest };
|
|
41
|
+
const bare = exactCodexFullscreenBareCommandCapture(styled, "/permissions", ports.agentVersion);
|
|
42
|
+
if (bare)
|
|
43
|
+
return { state: "bare_command", fingerprint: bare.digest };
|
|
44
|
+
const empty = exactCodexReadyStyledComposerCapture(styled, ports.agentVersion);
|
|
45
|
+
return empty && inspected.activity.state === "idle"
|
|
46
|
+
? { state: "idle", fingerprint: empty.digest } : { state: "blocked", fingerprint };
|
|
47
|
+
};
|
|
48
|
+
const capture = async () => {
|
|
49
|
+
inputPermit = undefined;
|
|
50
|
+
const observed = await captureFrame();
|
|
51
|
+
inputPermit = observed;
|
|
52
|
+
return observed;
|
|
53
|
+
};
|
|
54
|
+
return {
|
|
55
|
+
capture, inspectStatus: ports.inspectStatus, sleep: ports.sleep,
|
|
56
|
+
input: async (action, expected) => {
|
|
57
|
+
const permitted = inputPermit === expected;
|
|
58
|
+
inputPermit = undefined;
|
|
59
|
+
if (!permitted)
|
|
60
|
+
throw new Error("permission input requires one fresh operation-local surface permit");
|
|
61
|
+
if (!inputAllowed(action, expected))
|
|
62
|
+
throw new Error("permission input is not authorized by the observed native surface");
|
|
63
|
+
await ports.beforeInput();
|
|
64
|
+
const fresh = await captureFrame();
|
|
65
|
+
if (fresh.state !== expected.state || fresh.fingerprint !== expected.fingerprint ||
|
|
66
|
+
!inputAllowed(action, fresh)) {
|
|
67
|
+
throw new Error("native permission surface changed immediately before terminal input");
|
|
68
|
+
}
|
|
69
|
+
await ports.verifyIdentity();
|
|
70
|
+
try {
|
|
71
|
+
if (action === "command")
|
|
72
|
+
await ports.sendText("/permissions");
|
|
73
|
+
else
|
|
74
|
+
await ports.sendKeys([action]);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
throw new TerminalPermissionInputUncertainError("native permission input outcome is uncertain; do not retry automatically", { cause: error });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function inputAllowed(action, frame) {
|
|
83
|
+
switch (action) {
|
|
84
|
+
case "command": return frame.state === "idle";
|
|
85
|
+
case "Up":
|
|
86
|
+
case "Down": return frame.state === "picker" || frame.state === "full_access_confirmation";
|
|
87
|
+
case "Escape": return frame.state === "picker" || frame.state === "command";
|
|
88
|
+
case "C-u": return frame.state === "bare_command";
|
|
89
|
+
case "C-m": return frame.state === "command" || frame.state === "picker" ||
|
|
90
|
+
frame.state === "full_access_confirmation" && frame.selectedIndex === 0;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=terminal-permission-control-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-permission-control-bridge.js","sourceRoot":"","sources":["../../src/terminal-permission-control-bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { FileLockAcquisitionOptions } from "./file-lock-cli-adapter.js";
|
|
2
|
+
import type { TerminalNativeControlCliOptions as NativeLifecycleCliOptions, TerminalNativeControlCliBoundary } from "./terminal-native-control-cli-contract.js";
|
|
3
|
+
import type { ResolvedTerminalConversation } from "./terminal-agent-bridge.js";
|
|
4
|
+
import type { TerminalControlRef, TerminalRuntimeIdentity } from "./terminal-agent-adapter.js";
|
|
5
|
+
import type { TerminalRuntimeCliAdapter } from "./terminal-runtime-cli-adapter.js";
|
|
6
|
+
export interface TerminalPermissionControlCliPorts {
|
|
7
|
+
readonly runtime: {
|
|
8
|
+
forOptions(options: NativeLifecycleCliOptions): TerminalRuntimeCliAdapter;
|
|
9
|
+
physicalProcessIncarnation(pid: number): {
|
|
10
|
+
processUuid: string;
|
|
11
|
+
processBirth: string;
|
|
12
|
+
};
|
|
13
|
+
physicalRuntime(terminal: ResolvedTerminalConversation): TerminalRuntimeIdentity;
|
|
14
|
+
};
|
|
15
|
+
readonly lifecycle: TerminalNativeControlCliBoundary;
|
|
16
|
+
readonly state: {
|
|
17
|
+
storeDir(options: NativeLifecycleCliOptions): string;
|
|
18
|
+
inspectStore(storeDir: string): {
|
|
19
|
+
writable: boolean;
|
|
20
|
+
};
|
|
21
|
+
acquireTerminal(storeDir: string, terminalControl: TerminalControlRef, options?: FileLockAcquisitionOptions): () => void;
|
|
22
|
+
};
|
|
23
|
+
readonly output: {
|
|
24
|
+
print(value: unknown): void;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** Closed native permission operations; no task, Session, or Watch is created. */
|
|
28
|
+
export declare function createTerminalPermissionControlCliAdapter(ports: TerminalPermissionControlCliPorts): {
|
|
29
|
+
runPermissionOptions(options: NativeLifecycleCliOptions): Promise<void>;
|
|
30
|
+
runSetPermissions(options: NativeLifecycleCliOptions): Promise<void>;
|
|
31
|
+
};
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { terminalPermissionControlBindingToken, terminalPermissionControlProfileFor } from "./terminal-permission-control.js";
|
|
2
|
+
import { nonBlankString } from "./value-guards.js";
|
|
3
|
+
/** Closed native permission operations; no task, Session, or Watch is created. */
|
|
4
|
+
export function createTerminalPermissionControlCliAdapter(ports) {
|
|
5
|
+
const app = new TerminalPermissionControlCliApplication(ports);
|
|
6
|
+
return Object.freeze({
|
|
7
|
+
runPermissionOptions: (options) => app.runPermissionOptions(options),
|
|
8
|
+
runSetPermissions: (options) => app.runSetPermissions(options)
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
class TerminalPermissionControlCliApplication {
|
|
12
|
+
ports;
|
|
13
|
+
constructor(ports) {
|
|
14
|
+
this.ports = ports;
|
|
15
|
+
}
|
|
16
|
+
async runPermissionOptions(options) {
|
|
17
|
+
const token = validateOptions(options, false);
|
|
18
|
+
const result = await this.withPrepared(options, token, async (context) => {
|
|
19
|
+
const catalog = await context.bridge.permissionOptions(context.terminal.terminalControl, context.profile.agentVersion, {
|
|
20
|
+
runtime: context.runtime,
|
|
21
|
+
beforeInput: () => this.assertFreshBoundary(context)
|
|
22
|
+
});
|
|
23
|
+
await this.assertFreshBoundary(context);
|
|
24
|
+
return {
|
|
25
|
+
terminal_id: context.terminal.conversationId,
|
|
26
|
+
agent: catalog.agent,
|
|
27
|
+
agent_version: catalog.agentVersion,
|
|
28
|
+
behavior_profile: catalog.behaviorProfile,
|
|
29
|
+
scope: catalog.scope,
|
|
30
|
+
current: catalog.current,
|
|
31
|
+
choices: catalog.choices.map((choice) => ({
|
|
32
|
+
id: choice.id,
|
|
33
|
+
label: choice.label,
|
|
34
|
+
description: choice.description
|
|
35
|
+
})),
|
|
36
|
+
catalog_fingerprint: catalog.catalogFingerprint,
|
|
37
|
+
available_actions: {
|
|
38
|
+
set_permissions: {
|
|
39
|
+
tool: "agent_knock_knock_set_permissions",
|
|
40
|
+
arguments: {
|
|
41
|
+
terminal_id: context.terminal.conversationId,
|
|
42
|
+
expected_binding_token: context.expectedBindingToken,
|
|
43
|
+
expected_catalog_fingerprint: catalog.catalogFingerprint
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
this.ports.output.print(result);
|
|
50
|
+
}
|
|
51
|
+
async runSetPermissions(options) {
|
|
52
|
+
const token = validateOptions(options, true);
|
|
53
|
+
const mode = required(options.mode, "--mode is required");
|
|
54
|
+
if (!/^[a-z][a-z0-9_-]{0,63}$/u.test(mode)) {
|
|
55
|
+
throw new Error("--mode must be one semantic id from permission-options");
|
|
56
|
+
}
|
|
57
|
+
const fingerprint = required(options.expectedCatalogFingerprint, "--expected-catalog-fingerprint is required");
|
|
58
|
+
if (!/^[0-9a-f]{64}$/u.test(fingerprint)) {
|
|
59
|
+
throw new Error("--expected-catalog-fingerprint must come from permission-options");
|
|
60
|
+
}
|
|
61
|
+
const result = await this.withPrepared(options, token, async (context) => {
|
|
62
|
+
const switched = await context.bridge.setPermissions(context.terminal.terminalControl, context.profile.agentVersion, mode, fingerprint, {
|
|
63
|
+
runtime: context.runtime,
|
|
64
|
+
beforeInput: () => this.assertFreshBoundary(context)
|
|
65
|
+
});
|
|
66
|
+
return {
|
|
67
|
+
terminal_id: context.terminal.conversationId,
|
|
68
|
+
agent: "codex",
|
|
69
|
+
agent_version: context.profile.agentVersion,
|
|
70
|
+
behavior_profile: context.profile.behaviorProfile,
|
|
71
|
+
outcome: switched.outcome,
|
|
72
|
+
requested: switched.requested,
|
|
73
|
+
scope: switched.scope,
|
|
74
|
+
defaults_changed: switched.defaultsChanged,
|
|
75
|
+
...(switched.effective ? { effective: switched.effective } : {}),
|
|
76
|
+
do_not_retry: switched.doNotRetry,
|
|
77
|
+
...(switched.reason ? { reason: switched.reason } : {})
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
this.ports.output.print(result);
|
|
81
|
+
}
|
|
82
|
+
async withPrepared(options, expectedBindingToken, operation) {
|
|
83
|
+
const storeDir = this.ports.state.storeDir(options);
|
|
84
|
+
if (!this.ports.state.inspectStore(storeDir).writable) {
|
|
85
|
+
throw new Error("permission control requires a compatible AKK Store");
|
|
86
|
+
}
|
|
87
|
+
const initial = await this.ports.lifecycle.resolveLifecycleTerminal(options);
|
|
88
|
+
if (initial.agent !== "codex") {
|
|
89
|
+
throw new Error("native permission control is supported only for Codex");
|
|
90
|
+
}
|
|
91
|
+
const release = this.ports.state.acquireTerminal(storeDir, initial.terminalControl, { timeoutMs: 30_000 });
|
|
92
|
+
try {
|
|
93
|
+
const facade = this.ports.runtime.forOptions(options);
|
|
94
|
+
const bridge = facade.createBridge();
|
|
95
|
+
const terminal = await bridge.resolveStoredTerminal("codex", initial.pid, initial.terminalControl, this.ports.runtime.physicalRuntime(initial));
|
|
96
|
+
this.ports.lifecycle.assertSameInspectionTerminal(initial, terminal, "while waiting for permission-control ownership");
|
|
97
|
+
const version = facade.agentVersionForRunningProcess("codex", terminal.pid);
|
|
98
|
+
const profile = version ? terminalPermissionControlProfileFor(version) : undefined;
|
|
99
|
+
if (!profile)
|
|
100
|
+
throw new Error("Codex has no verified native permission-control profile");
|
|
101
|
+
const runtime = { ...this.ports.runtime.physicalRuntime(terminal), agentVersion: version };
|
|
102
|
+
const context = { options, terminal, bridge, runtime, profile, expectedBindingToken };
|
|
103
|
+
await this.assertFreshBoundary(context);
|
|
104
|
+
const status = await bridge.status("codex", terminal.terminalControl, { runtime });
|
|
105
|
+
if (status.approval_state.scanned !== true) {
|
|
106
|
+
throw new Error("permission control requires a fresh approval scan");
|
|
107
|
+
}
|
|
108
|
+
this.ports.lifecycle.assertInspectionReady({ options, terminal, terminalStatus: status });
|
|
109
|
+
return await operation(context);
|
|
110
|
+
}
|
|
111
|
+
finally {
|
|
112
|
+
release();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async assertFreshBoundary(context) {
|
|
116
|
+
const terminal = await context.bridge.resolveStoredTerminal("codex", context.terminal.pid, context.terminal.terminalControl, context.runtime);
|
|
117
|
+
this.ports.lifecycle.assertSameInspectionTerminal(context.terminal, terminal, "before permission-control input");
|
|
118
|
+
const version = this.ports.runtime.forOptions(context.options)
|
|
119
|
+
.agentVersionForRunningProcess("codex", terminal.pid);
|
|
120
|
+
const incarnation = this.ports.runtime.physicalProcessIncarnation(terminal.pid);
|
|
121
|
+
if (version !== context.profile.agentVersion ||
|
|
122
|
+
terminalPermissionControlBindingToken({
|
|
123
|
+
terminalId: terminal.conversationId,
|
|
124
|
+
terminalControl: terminal.terminalControl,
|
|
125
|
+
pid: terminal.pid,
|
|
126
|
+
workspace: required(terminal.terminalControl.currentPath, "terminal cwd is unavailable"),
|
|
127
|
+
...incarnation,
|
|
128
|
+
agentVersion: context.profile.agentVersion,
|
|
129
|
+
behaviorProfile: context.profile.behaviorProfile
|
|
130
|
+
}) !== context.expectedBindingToken) {
|
|
131
|
+
throw new Error("permission-control terminal binding or version changed; refresh AKK list");
|
|
132
|
+
}
|
|
133
|
+
this.ports.lifecycle.assertInspectionReady({ options: context.options, terminal });
|
|
134
|
+
this.ports.lifecycle.assertForegroundHasNoLifecycleTransition(context.options, terminal);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function validateOptions(options, set) {
|
|
138
|
+
const forbidden = ["command", "message", "request", "scope", "keys", "index", "model", "reasoningEffort"];
|
|
139
|
+
if (!set)
|
|
140
|
+
forbidden.push("mode", "expectedCatalogFingerprint");
|
|
141
|
+
if (forbidden.some((name) => options[name] !== undefined)) {
|
|
142
|
+
throw new Error("permission control accepts only typed permission fields, never raw commands, keys, indexes, or scope");
|
|
143
|
+
}
|
|
144
|
+
return required(options.expectedBindingToken, "--expected-binding-token is required");
|
|
145
|
+
}
|
|
146
|
+
function required(value, message) {
|
|
147
|
+
const text = nonBlankString(value);
|
|
148
|
+
if (!text)
|
|
149
|
+
throw new Error(message);
|
|
150
|
+
return text;
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=terminal-permission-control-cli-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-permission-control-cli-adapter.js","sourceRoot":"","sources":["../../src/terminal-permission-control-cli-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ExecutorKind } from "./executors.js";
|
|
2
|
+
import type { ActiveTerminalProcess, TerminalControlRef } from "./terminal-agent-adapter.js";
|
|
3
|
+
import type { TerminalListTerminalFacts } from "./terminal-list-facts.js";
|
|
4
|
+
export declare function permissionControlCapability(agent: ExecutorKind, version?: string): {
|
|
5
|
+
status: string;
|
|
6
|
+
agentVersion: string;
|
|
7
|
+
behaviorProfile: string;
|
|
8
|
+
scope: "current_session";
|
|
9
|
+
reason?: undefined;
|
|
10
|
+
} | {
|
|
11
|
+
agentVersion?: undefined;
|
|
12
|
+
behaviorProfile?: undefined;
|
|
13
|
+
scope?: undefined;
|
|
14
|
+
status: string;
|
|
15
|
+
reason: string;
|
|
16
|
+
};
|
|
17
|
+
/** Project existing fresh List facts without another terminal read or identity guess. */
|
|
18
|
+
export declare function renderPermissionControlListActions(input: {
|
|
19
|
+
session: ActiveTerminalProcess;
|
|
20
|
+
terminalControl: TerminalControlRef;
|
|
21
|
+
facts: TerminalListTerminalFacts;
|
|
22
|
+
renderedActions: Record<string, unknown>;
|
|
23
|
+
}): Record<string, unknown>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { renderTerminalPermissionControlActions } from "./terminal-list-renderer.js";
|
|
2
|
+
import { terminalPermissionControlAvailability } from "./terminal-permission-control-availability.js";
|
|
3
|
+
import { terminalPermissionControlProfileFor } from "./terminal-permission-control.js";
|
|
4
|
+
export function permissionControlCapability(agent, version) {
|
|
5
|
+
const profile = agent === "codex" && version
|
|
6
|
+
? terminalPermissionControlProfileFor(version)
|
|
7
|
+
: undefined;
|
|
8
|
+
return profile
|
|
9
|
+
? {
|
|
10
|
+
status: "supported",
|
|
11
|
+
agentVersion: profile.agentVersion,
|
|
12
|
+
behaviorProfile: profile.behaviorProfile,
|
|
13
|
+
scope: profile.scope
|
|
14
|
+
}
|
|
15
|
+
: {
|
|
16
|
+
status: "unsupported",
|
|
17
|
+
reason: "No verified native permission-control profile for this agent version."
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/** Project existing fresh List facts without another terminal read or identity guess. */
|
|
21
|
+
export function renderPermissionControlListActions(input) {
|
|
22
|
+
const { facts, session } = input;
|
|
23
|
+
return renderTerminalPermissionControlActions({
|
|
24
|
+
renderedActions: input.renderedActions,
|
|
25
|
+
availability: terminalPermissionControlAvailability({
|
|
26
|
+
exactTerminalRow: true,
|
|
27
|
+
terminalId: facts.physical.terminalId,
|
|
28
|
+
processState: "active",
|
|
29
|
+
agent: session.agent,
|
|
30
|
+
pid: session.pid,
|
|
31
|
+
terminalControl: input.terminalControl,
|
|
32
|
+
processUuid: facts.physical.processIncarnation?.processUuid,
|
|
33
|
+
processBirth: facts.physical.processIncarnation?.processBirth,
|
|
34
|
+
agentVersion: facts.runtime.agentVersion,
|
|
35
|
+
approvalScanned: facts.status.projected.approval_state.scanned === true,
|
|
36
|
+
approvalBlocked: facts.status.projected.approval_state.blocked === true,
|
|
37
|
+
terminalHasInteraction: facts.status.hasInteraction,
|
|
38
|
+
terminalHasBlockingTurn: facts.store.terminalHasBlockingTurn,
|
|
39
|
+
hasOrphanedDispatch: facts.store.hasOrphanedDispatch,
|
|
40
|
+
inputOwnerBlocked: facts.composer.inputOwnerBlocked,
|
|
41
|
+
exactEmptyComposer: facts.composer.automatedInputComposerReady,
|
|
42
|
+
screenState: facts.status.projected.screen_state,
|
|
43
|
+
activityState: facts.status.projected.activity_state
|
|
44
|
+
})
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=terminal-permission-control-list-projection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-permission-control-list-projection.js","sourceRoot":"","sources":["../../src/terminal-permission-control-list-projection.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,sCAAsC,EAAE,MAAM,6BAA6B,CAAC;AACrF,OAAO,EAAE,qCAAqC,EAAE,MAC9C,+CAA+C,CAAC;AAClD,OAAO,EAAE,mCAAmC,EAAE,MAC5C,kCAAkC,CAAC;AAErC,MAAM,UAAU,2BAA2B,CAAC,KAAmB,EAAE,OAAgB;IAC/E,MAAM,OAAO,GAAG,KAAK,KAAK,OAAO,IAAI,OAAO;QAC1C,CAAC,CAAC,mCAAmC,CAAC,OAAO,CAAC;QAC9C,CAAC,CAAC,SAAS,CAAC;IACd,OAAO,OAAO;QACZ,CAAC,CAAC;YACE,MAAM,EAAE,WAAW;YACnB,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,eAAe,EAAE,OAAO,CAAC,eAAe;YACxC,KAAK,EAAE,OAAO,CAAC,KAAK;SACrB;QACH,CAAC,CAAC;YACE,MAAM,EAAE,aAAa;YACrB,MAAM,EAAE,uEAAuE;SAChF,CAAC;AACR,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,kCAAkC,CAAC,KAKlD;IACC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IACjC,OAAO,sCAAsC,CAAC;QAC5C,eAAe,EAAE,KAAK,CAAC,eAAe;QACtC,YAAY,EAAE,qCAAqC,CAAC;YAClD,gBAAgB,EAAE,IAAI;YACtB,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,UAAU;YACrC,YAAY,EAAE,QAAQ;YACtB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,eAAe,EAAE,KAAK,CAAC,eAAe;YACtC,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,kBAAkB,EAAE,WAAW;YAC3D,YAAY,EAAE,KAAK,CAAC,QAAQ,CAAC,kBAAkB,EAAE,YAAY;YAC7D,YAAY,EAAE,KAAK,CAAC,OAAO,CAAC,YAAY;YACxC,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,OAAO,KAAK,IAAI;YACvE,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,OAAO,KAAK,IAAI;YACvE,sBAAsB,EAAE,KAAK,CAAC,MAAM,CAAC,cAAc;YACnD,uBAAuB,EAAE,KAAK,CAAC,KAAK,CAAC,uBAAuB;YAC5D,mBAAmB,EAAE,KAAK,CAAC,KAAK,CAAC,mBAAmB;YACpD,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,iBAAiB;YACnD,kBAAkB,EAAE,KAAK,CAAC,QAAQ,CAAC,2BAA2B;YAC9D,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,YAAY;YAChD,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc;SACrD,CAAC;KACH,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { TerminalAgentAdapter, TerminalRuntimeIdentity, TerminalControlRef } from "./terminal-agent-adapter.js";
|
|
2
|
+
import type { TerminalControlProvider } from "./terminal-control-provider.js";
|
|
3
|
+
import { type TerminalCodexStatusProbeResult, type TerminalNativeInspectionOptions } from "./terminal-native-inspection-bridge.js";
|
|
4
|
+
import { type TerminalPermissionCatalog, type TerminalPermissionSwitchResult } from "./terminal-permission-control.js";
|
|
5
|
+
export interface TerminalPermissionControlBridgeOptions {
|
|
6
|
+
runtime?: TerminalRuntimeIdentity;
|
|
7
|
+
beforeInput?: () => void | Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
interface PermissionRuntimePorts {
|
|
10
|
+
provider: TerminalControlProvider;
|
|
11
|
+
adapter: TerminalAgentAdapter;
|
|
12
|
+
verifyIdentity(control: TerminalControlRef, runtime: TerminalRuntimeIdentity): Promise<TerminalControlRef>;
|
|
13
|
+
submitStatus(control: TerminalControlRef, version: string, options: TerminalNativeInspectionOptions): Promise<TerminalCodexStatusProbeResult>;
|
|
14
|
+
captureStatus(control: TerminalControlRef, runtime: TerminalRuntimeIdentity, submission: TerminalCodexStatusProbeResult): Promise<{
|
|
15
|
+
screen: string;
|
|
16
|
+
emptyComposer: boolean;
|
|
17
|
+
}>;
|
|
18
|
+
sleep(milliseconds: number): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
/** Native permission UI composition, isolated from task execution and app-server writes. */
|
|
21
|
+
export declare class TerminalPermissionControlRuntime {
|
|
22
|
+
private readonly ports;
|
|
23
|
+
constructor(ports: PermissionRuntimePorts);
|
|
24
|
+
permissionOptions: (control: TerminalControlRef, version: string, options: TerminalPermissionControlBridgeOptions) => Promise<TerminalPermissionCatalog>;
|
|
25
|
+
setPermissions: (control: TerminalControlRef, version: string, mode: string, fingerprint: string, options: TerminalPermissionControlBridgeOptions) => Promise<TerminalPermissionSwitchResult>;
|
|
26
|
+
private permissionControlPorts;
|
|
27
|
+
}
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { sameTerminalControlIncarnation } from "./terminal-control-ref.js";
|
|
3
|
+
import { assertTerminalMutationCapabilities, stripTerminalEscapeSequences, NativeInspectionSubmissionError } from "./terminal-native-inspection-bridge.js";
|
|
4
|
+
import { createTerminalPermissionControlPorts } from "./terminal-permission-control-bridge.js";
|
|
5
|
+
import { discoverTerminalPermissionOptions, switchTerminalPermissions, terminalPermissionControlProfileFor, permissionModeFromStatus, TerminalPermissionInputUncertainError } from "./terminal-permission-control.js";
|
|
6
|
+
/** Native permission UI composition, isolated from task execution and app-server writes. */
|
|
7
|
+
export class TerminalPermissionControlRuntime {
|
|
8
|
+
ports;
|
|
9
|
+
constructor(ports) {
|
|
10
|
+
this.ports = ports;
|
|
11
|
+
}
|
|
12
|
+
permissionOptions = async (control, version, options) => {
|
|
13
|
+
const profile = terminalPermissionControlProfileFor(version);
|
|
14
|
+
if (!profile)
|
|
15
|
+
throw new Error("Codex has no verified permission-control profile");
|
|
16
|
+
return discoverTerminalPermissionOptions(profile, this.permissionControlPorts(control, version, options));
|
|
17
|
+
};
|
|
18
|
+
setPermissions = async (control, version, mode, fingerprint, options) => {
|
|
19
|
+
const profile = terminalPermissionControlProfileFor(version);
|
|
20
|
+
if (!profile)
|
|
21
|
+
throw new Error("Codex has no verified permission-control profile");
|
|
22
|
+
return switchTerminalPermissions(profile, mode, fingerprint, this.permissionControlPorts(control, version, options));
|
|
23
|
+
};
|
|
24
|
+
permissionControlPorts(control, version, options) {
|
|
25
|
+
if (!options.beforeInput || !options.runtime?.pid) {
|
|
26
|
+
throw new Error("permission control requires exact physical identity and an in-lock input fence");
|
|
27
|
+
}
|
|
28
|
+
assertTerminalMutationCapabilities({
|
|
29
|
+
provider: this.ports.provider, terminal: this.ports.provider.endpoint(control),
|
|
30
|
+
semantic: ["send_keys", "screen_status"],
|
|
31
|
+
transport: ["stable_resource_resolution", "screen_capture", "ansi_capture", "text_delivery", "key_delivery"]
|
|
32
|
+
});
|
|
33
|
+
const beforeInput = options.beforeInput;
|
|
34
|
+
const runtime = { ...options.runtime, agentVersion: version };
|
|
35
|
+
const adapter = this.ports.adapter;
|
|
36
|
+
const verifyIdentity = async () => {
|
|
37
|
+
const verified = await this.ports.verifyIdentity(control, runtime);
|
|
38
|
+
if (!sameTerminalControlIncarnation(control, verified)) {
|
|
39
|
+
throw new Error("permission-control terminal incarnation changed");
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
return createTerminalPermissionControlPorts({
|
|
43
|
+
agentVersion: version, runtime, adapter, verifyIdentity, beforeInput,
|
|
44
|
+
captureStyled: () => this.ports.provider.capture(this.ports.provider.endpoint(control), {
|
|
45
|
+
scrollbackLines: 160, preserveEscapes: true
|
|
46
|
+
}),
|
|
47
|
+
sendText: (text) => this.ports.provider.sendText(this.ports.provider.endpoint(control), text),
|
|
48
|
+
sendKeys: (keys) => this.ports.provider.sendKeys(this.ports.provider.endpoint(control), keys),
|
|
49
|
+
sleep: this.ports.sleep,
|
|
50
|
+
inspectStatus: async () => {
|
|
51
|
+
await beforeInput();
|
|
52
|
+
let submitted = false;
|
|
53
|
+
try {
|
|
54
|
+
const submission = await this.ports.submitStatus(control, version, {
|
|
55
|
+
runtime, beforeEnter: beforeInput
|
|
56
|
+
});
|
|
57
|
+
submitted = true;
|
|
58
|
+
for (let attempt = 0; attempt < 40; attempt += 1) {
|
|
59
|
+
const frame = await this.ports.captureStatus(control, runtime, submission);
|
|
60
|
+
const observed = adapter.observeNativeInspection?.({
|
|
61
|
+
operation: { kind: "status" }, expectedAgentVersion: version,
|
|
62
|
+
screen: stripTerminalEscapeSequences(frame.screen),
|
|
63
|
+
previousScreenFingerprint: submission.preEnterScreenDigest
|
|
64
|
+
});
|
|
65
|
+
if (frame.emptyComposer && observed?.status === "observed" && observed.nativeThreadId &&
|
|
66
|
+
createHash("sha256").update(frame.screen).digest("hex") !== submission.observationBaselineDigest) {
|
|
67
|
+
const permission = observed.result?.fields.filter((field) => field.name === "Permissions");
|
|
68
|
+
const mode = permission?.length === 1 ? permissionModeFromStatus(permission[0].value) : undefined;
|
|
69
|
+
if (!mode)
|
|
70
|
+
throw new Error("Codex /status does not expose a supported exact permission mode");
|
|
71
|
+
await verifyIdentity();
|
|
72
|
+
return { threadId: observed.nativeThreadId, mode };
|
|
73
|
+
}
|
|
74
|
+
await this.ports.sleep(100);
|
|
75
|
+
}
|
|
76
|
+
throw new Error("Codex permission control could not prove a fresh native /status result; do not retry automatically");
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
if (submitted || error instanceof NativeInspectionSubmissionError && error.doNotRetry) {
|
|
80
|
+
throw new TerminalPermissionInputUncertainError("native permission status probe is uncertain; inspect the terminal and do not retry automatically", { cause: error });
|
|
81
|
+
}
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=terminal-permission-control-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-permission-control-runtime.js","sourceRoot":"","sources":["../../src/terminal-permission-control-runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { type TerminalControlRef } from "./terminal-control-ref.js";
|
|
2
|
+
import type { CodexPermissionSurface } from "./codex-permission-surface.js";
|
|
3
|
+
export interface TerminalPermissionControlProfile {
|
|
4
|
+
readonly agentVersion: string;
|
|
5
|
+
readonly behaviorProfile: string;
|
|
6
|
+
readonly scope: "current_session";
|
|
7
|
+
}
|
|
8
|
+
/** Permission writes have their own reviewed UI contract, separate from reads/model control. */
|
|
9
|
+
export declare function terminalPermissionControlProfileFor(version: string): TerminalPermissionControlProfile | undefined;
|
|
10
|
+
export declare function terminalPermissionControlBindingToken(value: {
|
|
11
|
+
terminalId: string;
|
|
12
|
+
terminalControl: TerminalControlRef;
|
|
13
|
+
pid: number;
|
|
14
|
+
workspace: string;
|
|
15
|
+
processUuid: string;
|
|
16
|
+
processBirth: string;
|
|
17
|
+
agentVersion: string;
|
|
18
|
+
behaviorProfile: string;
|
|
19
|
+
}): string;
|
|
20
|
+
export interface TerminalPermissionChoice {
|
|
21
|
+
readonly id: string;
|
|
22
|
+
readonly label: string;
|
|
23
|
+
readonly description: string;
|
|
24
|
+
}
|
|
25
|
+
export interface TerminalPermissionCatalog {
|
|
26
|
+
readonly agent: "codex";
|
|
27
|
+
readonly agentVersion: string;
|
|
28
|
+
readonly behaviorProfile: string;
|
|
29
|
+
readonly scope: "current_session";
|
|
30
|
+
readonly current: string;
|
|
31
|
+
readonly choices: readonly TerminalPermissionChoice[];
|
|
32
|
+
readonly catalogFingerprint: string;
|
|
33
|
+
}
|
|
34
|
+
export interface TerminalPermissionSwitchResult {
|
|
35
|
+
readonly outcome: "changed" | "already_effective" | "uncertain";
|
|
36
|
+
readonly requested: {
|
|
37
|
+
readonly mode: string;
|
|
38
|
+
};
|
|
39
|
+
readonly effective?: {
|
|
40
|
+
readonly mode: string;
|
|
41
|
+
};
|
|
42
|
+
readonly scope: "current_session";
|
|
43
|
+
readonly defaultsChanged: false;
|
|
44
|
+
readonly doNotRetry: boolean;
|
|
45
|
+
readonly reason?: string;
|
|
46
|
+
}
|
|
47
|
+
export interface TerminalPermissionStatus {
|
|
48
|
+
readonly threadId: string;
|
|
49
|
+
readonly mode: string;
|
|
50
|
+
}
|
|
51
|
+
export type PermissionCapture = {
|
|
52
|
+
readonly state: "idle" | "command" | "bare_command" | "blocked";
|
|
53
|
+
readonly fingerprint: string;
|
|
54
|
+
} | Extract<CodexPermissionSurface, {
|
|
55
|
+
state: "picker" | "full_access_confirmation";
|
|
56
|
+
}>;
|
|
57
|
+
export interface TerminalPermissionControlPorts {
|
|
58
|
+
capture(): Promise<PermissionCapture>;
|
|
59
|
+
inspectStatus(): Promise<TerminalPermissionStatus>;
|
|
60
|
+
input(action: "command" | "Up" | "Down" | "C-m" | "Escape" | "C-u", expected: PermissionCapture): Promise<void>;
|
|
61
|
+
sleep(milliseconds: number): Promise<void>;
|
|
62
|
+
}
|
|
63
|
+
/** A transport failure may have delivered input; no cleanup or retry follows it. */
|
|
64
|
+
export declare class TerminalPermissionInputUncertainError extends Error {
|
|
65
|
+
readonly doNotRetry = true;
|
|
66
|
+
}
|
|
67
|
+
export declare function permissionModeFromStatus(value: string): string | undefined;
|
|
68
|
+
export declare function discoverTerminalPermissionOptions(profile: TerminalPermissionControlProfile, ports: TerminalPermissionControlPorts): Promise<TerminalPermissionCatalog>;
|
|
69
|
+
export declare function switchTerminalPermissions(profile: TerminalPermissionControlProfile, mode: string, expectedCatalogFingerprint: string, ports: TerminalPermissionControlPorts): Promise<TerminalPermissionSwitchResult>;
|