codex-computer-use-mcp 0.3.1 → 0.3.3
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/ARCHITECTURE.md +48 -36
- package/CHANGELOG.md +13 -0
- package/CONTRIBUTING.md +5 -4
- package/MIGRATION.md +22 -2
- package/PROOF.md +8 -5
- package/README.md +18 -18
- package/SECURITY.md +17 -9
- package/dist/direct-broker.d.ts +11 -1
- package/dist/direct-broker.js +159 -109
- package/dist/direct-broker.js.map +1 -1
- package/dist/mcp-server.js +1 -1
- package/dist/system.d.ts +11 -0
- package/dist/system.js +16 -4
- package/dist/system.js.map +1 -1
- package/integrations/pi/README.md +8 -9
- package/integrations/pi/index.ts +95 -12
- package/integrations/pi/mcp.json.example +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +2 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Pi integration
|
|
2
2
|
|
|
3
|
-
The native Pi adapter is the primary 0.3 path. It registers ten namespaced typed tools so Pi itself chooses each official Computer Use method and argument.
|
|
3
|
+
The native Pi adapter is the primary 0.3 path. It registers and activates ten namespaced typed tools together so Pi itself chooses each official Computer Use method and argument.
|
|
4
4
|
|
|
5
5
|
## Source checkout acceptance
|
|
6
6
|
|
|
@@ -13,23 +13,20 @@ CODEX_COMPUTER_USE_HOME="$(mktemp -d)" \
|
|
|
13
13
|
|
|
14
14
|
`-ne` prevents an installed 0.1 adapter from loading at the same time. This source workflow does not install or switch live Pi configuration.
|
|
15
15
|
|
|
16
|
-
For normal installation, use the exact version 0.3.
|
|
16
|
+
For normal installation, use the exact version 0.3.3 npm package:
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
pi install npm:codex-computer-use-mcp@0.3.
|
|
19
|
+
pi install npm:codex-computer-use-mcp@0.3.3
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
Use the source workflow only when you need to test an exact reviewed commit. Follow the rollback procedure in `MIGRATION.md` when replacing version 0.1.
|
|
23
23
|
|
|
24
24
|
## Registered surface
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
All ten tools are registered and active from session start:
|
|
27
27
|
|
|
28
28
|
- `computer_use_list_apps`
|
|
29
29
|
- `computer_use_get_app_state`
|
|
30
|
-
|
|
31
|
-
Registered and activated after a successful `get_app_state` call:
|
|
32
|
-
|
|
33
30
|
- `computer_use_click`
|
|
34
31
|
- `computer_use_perform_secondary_action`
|
|
35
32
|
- `computer_use_set_value`
|
|
@@ -43,13 +40,15 @@ Command:
|
|
|
43
40
|
|
|
44
41
|
- `/computer-use-status`
|
|
45
42
|
|
|
46
|
-
|
|
43
|
+
Session-start activation is purely additive and preserves every active tool owned by Pi or another extension. The interaction definitions rely on their official descriptions and omit extra prompt metadata.
|
|
44
|
+
|
|
45
|
+
A successful `get_app_state` retains its verified app-server runtime, thread, and signed Computer Use client. The following direct interaction uses that same client and official active-app lease, then closes the retained process tree with strict cleanup verification. A new inspection replaces and closes any earlier retained session; Pi `session_shutdown` also closes it.
|
|
47
46
|
|
|
48
47
|
No-permissions is the only policy: all ten tools are registered and available through this lifecycle with no wrapper permission prompts, mode selector, or app/intent/action gate. The signed host runs with Codex Full access (`approvalPolicy: "never"`, `sandbox: "danger-full-access"`), so normal empty-schema Computer Use app approvals are accepted by Codex before they reach Pi. Pi renders any form, OpenAI-form, or URL elicitation app-server does emit. The user's `accept`, `decline`, or `cancel` response is returned unchanged; the adapter never fabricates one.
|
|
49
48
|
|
|
50
49
|
## Generic MCP gateway
|
|
51
50
|
|
|
52
|
-
Merge `mcp.json.example` only for the exact 0.3.
|
|
51
|
+
Merge `mcp.json.example` only for the exact 0.3.3 package or after building an exact reviewed source commit. `directTools: false` is intentional; it keeps this powerful generic MCP surface behind Pi's gateway.
|
|
53
52
|
|
|
54
53
|
For a source checkout:
|
|
55
54
|
|
package/integrations/pi/index.ts
CHANGED
|
@@ -4,9 +4,11 @@ import { getAgentDir, truncateHead, type ExtensionAPI } from "@earendil-works/pi
|
|
|
4
4
|
import { Text } from "@earendil-works/pi-tui";
|
|
5
5
|
import { Type, type TSchema } from "typebox";
|
|
6
6
|
import { executeDirectTool, getDirectStatus } from "../../dist/direct-service.js";
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
import {
|
|
8
|
+
createOfficialDirectToolSession,
|
|
9
|
+
type DirectBrokerElicitationRequest,
|
|
10
|
+
type DirectBrokerElicitationResponse,
|
|
11
|
+
type OfficialDirectToolSession,
|
|
10
12
|
} from "../../dist/direct-broker.js";
|
|
11
13
|
import { OFFICIAL_TOOL_METADATA, type DirectMethod } from "../../dist/tools.js";
|
|
12
14
|
|
|
@@ -82,15 +84,94 @@ export const INTERACTION_TOOL_NAMES = [
|
|
|
82
84
|
"computer_use_type_text",
|
|
83
85
|
] as const;
|
|
84
86
|
|
|
87
|
+
export const COMPUTER_USE_TOOL_NAMES = [
|
|
88
|
+
...INSPECTION_TOOL_NAMES,
|
|
89
|
+
...INTERACTION_TOOL_NAMES,
|
|
90
|
+
] as const;
|
|
91
|
+
|
|
85
92
|
export function setInitialComputerUseTools(pi: Pick<ExtensionAPI, "getActiveTools" | "setActiveTools">): void {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
93
|
+
pi.setActiveTools([...new Set([...pi.getActiveTools(), ...COMPUTER_USE_TOOL_NAMES])]);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
interface SessionExecutorDependencies {
|
|
97
|
+
createSession?: typeof createOfficialDirectToolSession;
|
|
98
|
+
executeTool?: typeof executeDirectTool;
|
|
89
99
|
}
|
|
90
100
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
101
|
+
/** Keep the signed app-server/client alive across the required state -> action pair. */
|
|
102
|
+
export class PiDirectSessionExecutor {
|
|
103
|
+
private session: OfficialDirectToolSession | undefined;
|
|
104
|
+
private queue: Promise<void> = Promise.resolve();
|
|
105
|
+
private readonly dependencies: SessionExecutorDependencies;
|
|
106
|
+
|
|
107
|
+
constructor(dependencies: SessionExecutorDependencies = {}) {
|
|
108
|
+
this.dependencies = dependencies;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private async closeSession(): Promise<void> {
|
|
112
|
+
const session = this.session;
|
|
113
|
+
this.session = undefined;
|
|
114
|
+
await session?.close();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async execute(
|
|
118
|
+
method: DirectMethod,
|
|
119
|
+
params: Record<string, unknown>,
|
|
120
|
+
dependencies: Parameters<typeof executeDirectTool>[1],
|
|
121
|
+
): Promise<Awaited<ReturnType<typeof executeDirectTool>>> {
|
|
122
|
+
const previous = this.queue;
|
|
123
|
+
let release!: () => void;
|
|
124
|
+
this.queue = new Promise<void>((resolve) => { release = resolve; });
|
|
125
|
+
await previous;
|
|
126
|
+
try {
|
|
127
|
+
const executeTool = this.dependencies.executeTool ?? executeDirectTool;
|
|
128
|
+
if (method === "list_apps") return await executeTool({ method, arguments: params }, dependencies);
|
|
129
|
+
if (method === "get_app_state") {
|
|
130
|
+
await this.closeSession();
|
|
131
|
+
const createSession = this.dependencies.createSession ?? createOfficialDirectToolSession;
|
|
132
|
+
try {
|
|
133
|
+
const response = await executeTool(
|
|
134
|
+
{ method, arguments: params },
|
|
135
|
+
{
|
|
136
|
+
...dependencies,
|
|
137
|
+
callTool: async (directMethod, args, options) => {
|
|
138
|
+
this.session = await createSession({ supportsOpenAiFormElicitation: true });
|
|
139
|
+
return this.session.call(directMethod, args, options);
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
);
|
|
143
|
+
if (response.isError) await this.closeSession();
|
|
144
|
+
return response;
|
|
145
|
+
} catch (error) {
|
|
146
|
+
await this.closeSession();
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const session = this.session;
|
|
151
|
+
try {
|
|
152
|
+
return await executeTool(
|
|
153
|
+
{ method, arguments: params },
|
|
154
|
+
session ? {
|
|
155
|
+
...dependencies,
|
|
156
|
+
callTool: async (directMethod, args, options) => {
|
|
157
|
+
const result = await session.call(directMethod, args, options);
|
|
158
|
+
await this.closeSession();
|
|
159
|
+
return { ...result, brokerCleanupVerified: true };
|
|
160
|
+
},
|
|
161
|
+
} : dependencies,
|
|
162
|
+
);
|
|
163
|
+
} finally {
|
|
164
|
+
await this.closeSession();
|
|
165
|
+
}
|
|
166
|
+
} finally {
|
|
167
|
+
release();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async close(): Promise<void> {
|
|
172
|
+
await this.queue;
|
|
173
|
+
await this.closeSession();
|
|
174
|
+
}
|
|
94
175
|
}
|
|
95
176
|
|
|
96
177
|
function toPiContent(content: Array<Record<string, unknown>>): Array<{ type: "text"; text: string } | { type: "image"; data: string; mimeType: string }> {
|
|
@@ -188,6 +269,7 @@ export async function handleOfficialElicitation(
|
|
|
188
269
|
|
|
189
270
|
export default function directComputerUse(pi: ExtensionAPI) {
|
|
190
271
|
const stateRoot = process.env.CODEX_COMPUTER_USE_HOME || path.join(getAgentDir(), "direct-computer-use");
|
|
272
|
+
const sessionExecutor = new PiDirectSessionExecutor();
|
|
191
273
|
|
|
192
274
|
pi.registerCommand("computer-use-status", {
|
|
193
275
|
description: "Show the direct-call architecture, durable no-permissions policy, signed broker, and private audit path",
|
|
@@ -214,8 +296,9 @@ export default function directComputerUse(pi: ExtensionAPI) {
|
|
|
214
296
|
...inspectionPromptMetadata,
|
|
215
297
|
parameters: ToolParameters[method] as any,
|
|
216
298
|
async execute(_toolCallId, params, signal, onUpdate, ctx) {
|
|
217
|
-
const response = await
|
|
218
|
-
|
|
299
|
+
const response = await sessionExecutor.execute(
|
|
300
|
+
method,
|
|
301
|
+
params as Record<string, unknown>,
|
|
219
302
|
{
|
|
220
303
|
stateRoot,
|
|
221
304
|
signal,
|
|
@@ -232,7 +315,6 @@ export default function directComputerUse(pi: ExtensionAPI) {
|
|
|
232
315
|
},
|
|
233
316
|
);
|
|
234
317
|
if (response.isError) throw new Error(errorText(response.content));
|
|
235
|
-
if (method === "get_app_state") activateInteractionTools(pi);
|
|
236
318
|
return { content: toPiContent(response.content), details: response.details };
|
|
237
319
|
},
|
|
238
320
|
renderCall(args, theme) {
|
|
@@ -244,4 +326,5 @@ export default function directComputerUse(pi: ExtensionAPI) {
|
|
|
244
326
|
}
|
|
245
327
|
|
|
246
328
|
pi.on("session_start", () => setInitialComputerUseTools(pi));
|
|
329
|
+
pi.on("session_shutdown", () => sessionExecutor.close());
|
|
247
330
|
}
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codex-computer-use-mcp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "codex-computer-use-mcp",
|
|
9
|
-
"version": "0.3.
|
|
9
|
+
"version": "0.3.3",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"os": [
|
|
12
12
|
"darwin"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codex-computer-use-mcp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "Expose the official macOS Computer Use tools directly to Pi and MCP clients without a nested model.",
|
|
5
5
|
"author": "Thomas Mustier",
|
|
6
6
|
"license": "MIT",
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"integrations/pi",
|
|
32
32
|
"npm-shrinkwrap.json",
|
|
33
33
|
"README.md",
|
|
34
|
+
"CHANGELOG.md",
|
|
34
35
|
"PROOF.md",
|
|
35
36
|
"ARCHITECTURE.md",
|
|
36
37
|
"MIGRATION.md",
|