codex-computer-use-mcp 0.1.0
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/CONTRIBUTING.md +26 -0
- package/LICENSE +21 -0
- package/PROOF.md +81 -0
- package/README.md +195 -0
- package/SECURITY.md +38 -0
- package/dist/audit.d.ts +25 -0
- package/dist/audit.js +42 -0
- package/dist/audit.js.map +1 -0
- package/dist/config.d.ts +12 -0
- package/dist/config.js +105 -0
- package/dist/config.js.map +1 -0
- package/dist/lock.d.ts +16 -0
- package/dist/lock.js +108 -0
- package/dist/lock.js.map +1 -0
- package/dist/mcp-server.d.ts +2 -0
- package/dist/mcp-server.js +134 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/policy.d.ts +42 -0
- package/dist/policy.js +428 -0
- package/dist/policy.js.map +1 -0
- package/dist/prompt.d.ts +62 -0
- package/dist/prompt.js +119 -0
- package/dist/prompt.js.map +1 -0
- package/dist/runner.d.ts +55 -0
- package/dist/runner.js +494 -0
- package/dist/runner.js.map +1 -0
- package/dist/service.d.ts +17 -0
- package/dist/service.js +382 -0
- package/dist/service.js.map +1 -0
- package/dist/system.d.ts +17 -0
- package/dist/system.js +228 -0
- package/dist/system.js.map +1 -0
- package/integrations/pi/README.md +50 -0
- package/integrations/pi/index.ts +135 -0
- package/integrations/pi/mcp.json.example +15 -0
- package/npm-shrinkwrap.json +1600 -0
- package/package.json +65 -0
package/dist/service.js
ADDED
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { appendAudit } from "./audit.js";
|
|
5
|
+
import { loadConfig } from "./config.js";
|
|
6
|
+
import { acquireAppLock } from "./lock.js";
|
|
7
|
+
import { COMPUTER_USE_TOOLS, MODEL, PolicyError, allowedToolsForRequest, createDictionaryArgumentValidator, validateObservedMethods, validateResolvedAppIdentity, validateRequest, } from "./policy.js";
|
|
8
|
+
import { buildPrompt } from "./prompt.js";
|
|
9
|
+
import { runOfficialCodex, verifyOfficialBroker } from "./runner.js";
|
|
10
|
+
import { ensureAppRunningInBackground, frontmostBundleId, frontmostBundleIdAsync, resolveAppIdentity, watchTargetFrontmost, } from "./system.js";
|
|
11
|
+
export function defaultStateRoot() {
|
|
12
|
+
return process.env.CODEX_COMPUTER_USE_HOME || path.join(homedir(), ".codex-computer-use-mcp");
|
|
13
|
+
}
|
|
14
|
+
function usageText(result) {
|
|
15
|
+
const usage = result.usage;
|
|
16
|
+
return `Codex usage: ${usage.input} input (${usage.cachedInput} cached), ${usage.output} output tokens`;
|
|
17
|
+
}
|
|
18
|
+
function safeDisplay(value, maxLength) {
|
|
19
|
+
return value.replace(/[\u0000-\u001f\u007f]+/g, " ").replace(/\s+/g, " ").trim().slice(0, maxLength);
|
|
20
|
+
}
|
|
21
|
+
function auditAppIdentifier(app, canonicalBundleId) {
|
|
22
|
+
if (!app)
|
|
23
|
+
return null;
|
|
24
|
+
if (canonicalBundleId)
|
|
25
|
+
return canonicalBundleId;
|
|
26
|
+
return `target-sha256:${crypto.createHash("sha256").update(app).digest("hex").slice(0, 16)}`;
|
|
27
|
+
}
|
|
28
|
+
function rejectedInputMetadata(raw) {
|
|
29
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
30
|
+
return { operation: "invalid_request", app: null, mutating: false, cleanup: false, inputBytes: 0 };
|
|
31
|
+
}
|
|
32
|
+
const value = raw;
|
|
33
|
+
const operation = typeof value.mode === "string" && ["list", "inspect", "act", "dictionary_lookup", "configure"].includes(value.mode)
|
|
34
|
+
? value.mode
|
|
35
|
+
: "invalid_request";
|
|
36
|
+
const app = typeof value.app === "string" ? auditAppIdentifier(value.app, undefined) : null;
|
|
37
|
+
const input = [value.task, value.query, value.cleanup_instructions]
|
|
38
|
+
.filter((item) => typeof item === "string")
|
|
39
|
+
.join("");
|
|
40
|
+
return {
|
|
41
|
+
operation,
|
|
42
|
+
app,
|
|
43
|
+
mutating: operation === "act" || operation === "dictionary_lookup" || operation === "configure",
|
|
44
|
+
cleanup: value.cleanup === true,
|
|
45
|
+
inputBytes: Buffer.byteLength(input, "utf8"),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function interruptionMessage(kind, app, methods) {
|
|
49
|
+
const prior = methods.length
|
|
50
|
+
? ` Earlier successful calls (${methods.join(", ")}) may already have changed state; cleanup is unverified.`
|
|
51
|
+
: " No successful Computer Use call was observed before the interruption.";
|
|
52
|
+
switch (kind) {
|
|
53
|
+
case "app_approval":
|
|
54
|
+
return `Official Computer Use app approval is required for ${app}. Complete or deny that first-party app approval in an official interactive session, then retry only if approved.${prior}`;
|
|
55
|
+
case "sensitive_action":
|
|
56
|
+
return `Official Computer Use sensitive-action confirmation interrupted work in ${app}. Review that specific first-party action prompt; wrapper full-permissions does not bypass it.${prior}`;
|
|
57
|
+
case "os_permission":
|
|
58
|
+
return `A macOS privacy permission interrupted Computer Use for ${app}. Review the relevant macOS permission directly; the wrapper does not alter OS privacy controls.${prior}`;
|
|
59
|
+
case "unknown_elicitation":
|
|
60
|
+
return `An unclassified first-party Computer Use elicitation interrupted work in ${app}. Review it in an official interactive session rather than assuming it is app approval.${prior}`;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export async function executeOperation(raw, deps = {}) {
|
|
64
|
+
const stateDir = deps.stateRoot || defaultStateRoot();
|
|
65
|
+
const runId = crypto.randomUUID();
|
|
66
|
+
const startedAt = Date.now();
|
|
67
|
+
const config = await loadConfig(stateDir);
|
|
68
|
+
const permissionMode = config.permissionMode;
|
|
69
|
+
let request;
|
|
70
|
+
try {
|
|
71
|
+
request = validateRequest(raw, permissionMode);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
const rejected = rejectedInputMetadata(raw);
|
|
75
|
+
const audit = {
|
|
76
|
+
timestamp: new Date().toISOString(),
|
|
77
|
+
runId,
|
|
78
|
+
operation: rejected.operation,
|
|
79
|
+
permissionMode,
|
|
80
|
+
app: rejected.app,
|
|
81
|
+
mutating: rejected.mutating,
|
|
82
|
+
cleanupRequested: rejected.cleanup,
|
|
83
|
+
userConfirmed: false,
|
|
84
|
+
authorization: permissionMode === "full-permissions" ? "full_permissions_config" : "none",
|
|
85
|
+
inputBytes: rejected.inputBytes,
|
|
86
|
+
outcome: "policy_rejected",
|
|
87
|
+
durationMs: Date.now() - startedAt,
|
|
88
|
+
model: MODEL,
|
|
89
|
+
usage: { input: 0, cachedInput: 0, output: 0 },
|
|
90
|
+
computerUseCalls: 0,
|
|
91
|
+
computerUseMethods: [],
|
|
92
|
+
backgroundPreserved: null,
|
|
93
|
+
cleanupVerified: null,
|
|
94
|
+
};
|
|
95
|
+
try {
|
|
96
|
+
await appendAudit(stateDir, audit, "background-computer-use.jsonl");
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
throw new Error("Computer Use request was rejected, but secure audit logging failed");
|
|
100
|
+
}
|
|
101
|
+
if (error instanceof PolicyError)
|
|
102
|
+
throw error;
|
|
103
|
+
throw new PolicyError("Request did not pass the Computer Use policy");
|
|
104
|
+
}
|
|
105
|
+
let userConfirmed = false;
|
|
106
|
+
let authorization = permissionMode === "full-permissions" ? "full_permissions_config" : "none";
|
|
107
|
+
const locks = [];
|
|
108
|
+
let runner;
|
|
109
|
+
let outcome = "failed";
|
|
110
|
+
let backgroundPreserved = null;
|
|
111
|
+
let cleanupVerified = null;
|
|
112
|
+
const app = request.app;
|
|
113
|
+
let targetIdentity = app ? resolveAppIdentity(app) : undefined;
|
|
114
|
+
const initialTargetLeaseId = targetIdentity?.leaseId;
|
|
115
|
+
let targetLeaseId = initialTargetLeaseId;
|
|
116
|
+
let canonicalTargetApp = targetIdentity?.bundleId;
|
|
117
|
+
let frontBefore;
|
|
118
|
+
let targetBecameFrontmost = false;
|
|
119
|
+
let unrelatedFocusChanges = false;
|
|
120
|
+
let focusWatcher;
|
|
121
|
+
let focusWatcherFailed = false;
|
|
122
|
+
try {
|
|
123
|
+
validateResolvedAppIdentity(request, targetIdentity?.bundleId, targetIdentity?.verifiedSystemDictionary === true);
|
|
124
|
+
if (initialTargetLeaseId)
|
|
125
|
+
locks.push(await acquireAppLock(stateDir, initialTargetLeaseId, runId));
|
|
126
|
+
frontBefore = frontmostBundleId();
|
|
127
|
+
if (!frontBefore)
|
|
128
|
+
throw new PolicyError("Could not observe the frontmost app; refusing to spend Codex quota without background verification");
|
|
129
|
+
let focusSamplePromise;
|
|
130
|
+
const sampleFocus = () => {
|
|
131
|
+
if (focusSamplePromise)
|
|
132
|
+
return focusSamplePromise;
|
|
133
|
+
focusSamplePromise = (async () => {
|
|
134
|
+
const current = await frontmostBundleIdAsync();
|
|
135
|
+
if (!current)
|
|
136
|
+
return;
|
|
137
|
+
if (canonicalTargetApp && current.toLowerCase() === canonicalTargetApp.toLowerCase())
|
|
138
|
+
targetBecameFrontmost = true;
|
|
139
|
+
else if (current !== frontBefore)
|
|
140
|
+
unrelatedFocusChanges = true;
|
|
141
|
+
})().finally(() => {
|
|
142
|
+
focusSamplePromise = undefined;
|
|
143
|
+
});
|
|
144
|
+
return focusSamplePromise;
|
|
145
|
+
};
|
|
146
|
+
if (app)
|
|
147
|
+
focusWatcher = await watchTargetFrontmost();
|
|
148
|
+
const focusMonitor = setInterval(() => void sampleFocus(), 250);
|
|
149
|
+
focusMonitor.unref();
|
|
150
|
+
try {
|
|
151
|
+
if (app) {
|
|
152
|
+
targetIdentity = await ensureAppRunningInBackground(app, targetIdentity);
|
|
153
|
+
canonicalTargetApp = targetIdentity.bundleId;
|
|
154
|
+
if (!canonicalTargetApp)
|
|
155
|
+
throw new PolicyError("Could not resolve the background-launched app to a canonical bundle ID");
|
|
156
|
+
targetLeaseId = canonicalTargetApp.toLowerCase();
|
|
157
|
+
validateResolvedAppIdentity(request, targetIdentity.bundleId, targetIdentity.verifiedSystemDictionary);
|
|
158
|
+
if (targetLeaseId !== initialTargetLeaseId)
|
|
159
|
+
locks.push(await acquireAppLock(stateDir, targetLeaseId, runId));
|
|
160
|
+
await sampleFocus();
|
|
161
|
+
if (frontmostBundleId()?.toLowerCase() === targetLeaseId)
|
|
162
|
+
targetBecameFrontmost = true;
|
|
163
|
+
if (targetBecameFrontmost)
|
|
164
|
+
throw new PolicyError("The target app became frontmost during background launch; background-only guarantee failed");
|
|
165
|
+
}
|
|
166
|
+
await deps.onProgress?.(`${permissionMode === "full-permissions" ? "FULL PERMISSIONS; " : ""}Leased ${app ?? "app inventory"}; starting signed Codex Computer Use worker…`);
|
|
167
|
+
runner = await (deps.runCodex ?? runOfficialCodex)(buildPrompt(request, canonicalTargetApp), {
|
|
168
|
+
signal: deps.signal,
|
|
169
|
+
timeoutMs: 300_000,
|
|
170
|
+
allowedTools: allowedToolsForRequest(request),
|
|
171
|
+
targetApp: request.app,
|
|
172
|
+
targetAppAliases: [canonicalTargetApp, targetLeaseId, initialTargetLeaseId].filter((value) => Boolean(value)),
|
|
173
|
+
reasoningEffort: request.reasoningEffort,
|
|
174
|
+
maxToolCalls: request.maxComputerUseCalls,
|
|
175
|
+
validateCallArguments: request.mode === "dictionary_lookup" ? createDictionaryArgumentValidator(request.query) : undefined,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
finally {
|
|
179
|
+
clearInterval(focusMonitor);
|
|
180
|
+
await sampleFocus();
|
|
181
|
+
if (focusWatcher) {
|
|
182
|
+
focusWatcherFailed = !focusWatcher.healthy();
|
|
183
|
+
await focusWatcher.stop();
|
|
184
|
+
if (canonicalTargetApp)
|
|
185
|
+
targetBecameFrontmost ||= focusWatcher.becameFrontmost(canonicalTargetApp);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (focusWatcherFailed)
|
|
189
|
+
throw new PolicyError("Target focus-event monitor exited before the Computer Use worker");
|
|
190
|
+
if (runner.policyViolation) {
|
|
191
|
+
outcome = "policy_violation";
|
|
192
|
+
throw new PolicyError(`${runner.policyViolation}${request.mutating ? "; target cleanup is not verified—inspect and restore the app before retrying" : ""}`);
|
|
193
|
+
}
|
|
194
|
+
if (runner.firstPartyInterruption) {
|
|
195
|
+
outcome = `first_party_${runner.firstPartyInterruption}`;
|
|
196
|
+
return {
|
|
197
|
+
ok: false,
|
|
198
|
+
isError: true,
|
|
199
|
+
text: `[${permissionMode}] ${interruptionMessage(runner.firstPartyInterruption, app ?? "the target app", runner.computerUseMethods)} Do not retry automatically. ${usageText(runner)}`,
|
|
200
|
+
details: {
|
|
201
|
+
runId,
|
|
202
|
+
mode: request.mode,
|
|
203
|
+
permissionMode,
|
|
204
|
+
app,
|
|
205
|
+
outcome,
|
|
206
|
+
approvalRequired: runner.firstPartyInterruption === "app_approval",
|
|
207
|
+
firstPartyInterruption: runner.firstPartyInterruption,
|
|
208
|
+
usedCapabilities: runner.computerUseMethods,
|
|
209
|
+
usage: runner.usage,
|
|
210
|
+
model: MODEL,
|
|
211
|
+
durationMs: runner.durationMs,
|
|
212
|
+
retryAllowed: false,
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
if (runner.errorKind === "cancelled") {
|
|
217
|
+
outcome = "cancelled";
|
|
218
|
+
cleanupVerified = false;
|
|
219
|
+
return {
|
|
220
|
+
ok: false,
|
|
221
|
+
isError: true,
|
|
222
|
+
text: `Computer Use was cancelled. ${runner.computerUseMethods.length ? `Earlier successful calls (${runner.computerUseMethods.join(", ")}) may already have changed state; cleanup is unverified. ` : "No successful Computer Use call was observed. "}Do not retry automatically.`,
|
|
223
|
+
details: {
|
|
224
|
+
runId,
|
|
225
|
+
mode: request.mode,
|
|
226
|
+
permissionMode,
|
|
227
|
+
app,
|
|
228
|
+
outcome,
|
|
229
|
+
usedCapabilities: runner.computerUseMethods,
|
|
230
|
+
usage: runner.usage,
|
|
231
|
+
model: MODEL,
|
|
232
|
+
durationMs: runner.durationMs,
|
|
233
|
+
cleanupVerified: false,
|
|
234
|
+
retryAllowed: false,
|
|
235
|
+
},
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
if (runner.exitCode !== 0 || !runner.result) {
|
|
239
|
+
outcome = runner.errorKind ?? "broker_failed";
|
|
240
|
+
throw new Error(`Official Codex broker failed (${runner.errorKind ?? "unknown"})${request.mutating ? "; target cleanup is not verified—inspect and restore the app before retrying" : ""}`);
|
|
241
|
+
}
|
|
242
|
+
const result = runner.result;
|
|
243
|
+
if (result.mode !== request.mode)
|
|
244
|
+
throw new PolicyError("Codex returned a mismatched mode");
|
|
245
|
+
if (app &&
|
|
246
|
+
![app, canonicalTargetApp, targetLeaseId]
|
|
247
|
+
.filter((value) => Boolean(value))
|
|
248
|
+
.some((value) => value.toLowerCase() === result.app.toLowerCase())) {
|
|
249
|
+
throw new PolicyError("Codex returned a mismatched target app");
|
|
250
|
+
}
|
|
251
|
+
if (result.status === "approval_required" || result.approvalRequired) {
|
|
252
|
+
outcome = "unverified_approval_claim";
|
|
253
|
+
throw new Error("Codex claimed app approval was required without an observed official approval event; no task completion is trusted");
|
|
254
|
+
}
|
|
255
|
+
if (result.status !== "ok") {
|
|
256
|
+
outcome = `computer_use_${result.status}`;
|
|
257
|
+
throw new Error(`Computer Use returned ${result.status}${request.mutating ? "; target cleanup is not verified—inspect and restore the app before retrying" : ""}`);
|
|
258
|
+
}
|
|
259
|
+
validateObservedMethods(request, runner.computerUseMethods);
|
|
260
|
+
const frontAfter = frontmostBundleId();
|
|
261
|
+
if (!frontAfter)
|
|
262
|
+
throw new PolicyError("Could not verify the final frontmost app state");
|
|
263
|
+
if (targetLeaseId && frontAfter.toLowerCase() === targetLeaseId)
|
|
264
|
+
targetBecameFrontmost = true;
|
|
265
|
+
else if (frontAfter !== frontBefore)
|
|
266
|
+
unrelatedFocusChanges = true;
|
|
267
|
+
backgroundPreserved = !targetBecameFrontmost;
|
|
268
|
+
if (!backgroundPreserved)
|
|
269
|
+
throw new PolicyError("The confirmed target app became frontmost; background-only guarantee failed");
|
|
270
|
+
cleanupVerified = request.mutating ? (request.cleanup ? result.cleaned : null) : true;
|
|
271
|
+
if (request.mutating && request.cleanup && result.cleaned !== true)
|
|
272
|
+
throw new PolicyError("Requested cleanup was not verified");
|
|
273
|
+
outcome = "ok";
|
|
274
|
+
if (request.mode === "list") {
|
|
275
|
+
const safeApps = result.apps.map((item) => ({ name: safeDisplay(item.name, 120), bundleId: safeDisplay(item.bundleId, 160) }));
|
|
276
|
+
const lines = safeApps.map((item) => `${item.name} (${item.bundleId})`);
|
|
277
|
+
return {
|
|
278
|
+
ok: true,
|
|
279
|
+
isError: false,
|
|
280
|
+
text: `[${permissionMode}] Discovered ${safeApps.length} apps through signed Codex Computer Use:\n${lines.join("\n")}\n\n${usageText(runner)}.`,
|
|
281
|
+
details: {
|
|
282
|
+
runId,
|
|
283
|
+
mode: request.mode,
|
|
284
|
+
permissionMode,
|
|
285
|
+
outcome,
|
|
286
|
+
apps: safeApps,
|
|
287
|
+
cleaned: true,
|
|
288
|
+
backgroundPreserved,
|
|
289
|
+
unrelatedFocusChanges,
|
|
290
|
+
usedCapabilities: runner.computerUseMethods,
|
|
291
|
+
usage: runner.usage,
|
|
292
|
+
model: MODEL,
|
|
293
|
+
durationMs: runner.durationMs,
|
|
294
|
+
},
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
return {
|
|
298
|
+
ok: true,
|
|
299
|
+
isError: false,
|
|
300
|
+
text: `[${permissionMode}] ${app} ${request.mode} completed through signed Codex Computer Use. ${safeDisplay(result.summary, 1000)} Background preserved: yes. ${request.cleanup ? "Cleanup verified: yes. " : "Cleanup not requested. "}Capabilities used: ${runner.computerUseMethods.join(", ")}. ${usageText(runner)}.`,
|
|
301
|
+
details: {
|
|
302
|
+
runId,
|
|
303
|
+
mode: request.mode,
|
|
304
|
+
permissionMode,
|
|
305
|
+
app,
|
|
306
|
+
outcome,
|
|
307
|
+
summary: safeDisplay(result.summary, 1000),
|
|
308
|
+
cleaned: result.cleaned,
|
|
309
|
+
backgroundPreserved,
|
|
310
|
+
unrelatedFocusChanges,
|
|
311
|
+
approvalRequired: false,
|
|
312
|
+
usedCapabilities: runner.computerUseMethods,
|
|
313
|
+
usage: runner.usage,
|
|
314
|
+
model: MODEL,
|
|
315
|
+
durationMs: runner.durationMs,
|
|
316
|
+
},
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
finally {
|
|
320
|
+
let releaseFailure = false;
|
|
321
|
+
for (const held of locks.reverse()) {
|
|
322
|
+
try {
|
|
323
|
+
await held.release();
|
|
324
|
+
}
|
|
325
|
+
catch {
|
|
326
|
+
releaseFailure = true;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
const audit = {
|
|
330
|
+
timestamp: new Date().toISOString(),
|
|
331
|
+
runId,
|
|
332
|
+
operation: request.mode,
|
|
333
|
+
permissionMode,
|
|
334
|
+
app: auditAppIdentifier(app, canonicalTargetApp),
|
|
335
|
+
mutating: request.mutating,
|
|
336
|
+
cleanupRequested: request.cleanup,
|
|
337
|
+
userConfirmed,
|
|
338
|
+
authorization,
|
|
339
|
+
inputBytes: Buffer.byteLength(`${request.task ?? request.query ?? ""}${request.cleanupInstructions ?? ""}`, "utf8"),
|
|
340
|
+
outcome,
|
|
341
|
+
durationMs: Date.now() - startedAt,
|
|
342
|
+
model: MODEL,
|
|
343
|
+
usage: runner?.usage ?? { input: 0, cachedInput: 0, output: 0 },
|
|
344
|
+
computerUseCalls: runner?.computerUseMethods.length ?? 0,
|
|
345
|
+
computerUseMethods: runner?.computerUseMethods ?? [],
|
|
346
|
+
backgroundPreserved,
|
|
347
|
+
cleanupVerified,
|
|
348
|
+
};
|
|
349
|
+
try {
|
|
350
|
+
await appendAudit(stateDir, audit, "background-computer-use.jsonl");
|
|
351
|
+
}
|
|
352
|
+
catch {
|
|
353
|
+
throw new Error(`Computer Use ended with outcome ${outcome}, but secure audit logging failed${request.mutating ? "; prior mutations and cleanup state may require manual inspection" : ""}`);
|
|
354
|
+
}
|
|
355
|
+
if (releaseFailure) {
|
|
356
|
+
throw new Error(`Computer Use ended with outcome ${outcome}, but one or more app leases did not release cleanly`);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
export async function getStatus(stateRoot = defaultStateRoot()) {
|
|
361
|
+
const config = await loadConfig(stateRoot);
|
|
362
|
+
let brokerVerified = false;
|
|
363
|
+
let brokerVersion;
|
|
364
|
+
try {
|
|
365
|
+
brokerVersion = verifyOfficialBroker();
|
|
366
|
+
brokerVerified = true;
|
|
367
|
+
}
|
|
368
|
+
catch {
|
|
369
|
+
// Status remains readable on incompatible hosts without exposing local verification details.
|
|
370
|
+
}
|
|
371
|
+
return {
|
|
372
|
+
stateRoot,
|
|
373
|
+
permissionMode: config.permissionMode,
|
|
374
|
+
model: MODEL,
|
|
375
|
+
brokerVerified,
|
|
376
|
+
...(brokerVersion ? { brokerVersion } : {}),
|
|
377
|
+
officialApprovalAuthoritative: true,
|
|
378
|
+
supportedMethods: [...COMPUTER_USE_TOOLS],
|
|
379
|
+
auditPath: path.join(stateRoot, "audit", "background-computer-use.jsonl"),
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
|
package/dist/system.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare function frontmostApplicationToken(): string | undefined;
|
|
2
|
+
export declare function frontmostBundleId(): string | undefined;
|
|
3
|
+
export declare function frontmostBundleIdAsync(): Promise<string | undefined>;
|
|
4
|
+
export interface ResolvedAppIdentity {
|
|
5
|
+
bundleId?: string;
|
|
6
|
+
leaseId: string;
|
|
7
|
+
verifiedSystemDictionary: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function resolveAppIdentity(app: string): ResolvedAppIdentity;
|
|
10
|
+
export declare function resolveAppLeaseId(app: string): string;
|
|
11
|
+
export declare function ensureAppRunningInBackground(app: string, identity?: ResolvedAppIdentity): Promise<ResolvedAppIdentity>;
|
|
12
|
+
export interface TargetFrontmostWatcher {
|
|
13
|
+
becameFrontmost(bundleId: string): boolean;
|
|
14
|
+
healthy(): boolean;
|
|
15
|
+
stop(): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
export declare function watchTargetFrontmost(listenerPath?: string, infoPath?: string): Promise<TargetFrontmostWatcher>;
|
package/dist/system.js
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { execFile, spawn, spawnSync } from "node:child_process";
|
|
2
|
+
import { realpathSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { promisify } from "node:util";
|
|
5
|
+
const execFileAsync = promisify(execFile);
|
|
6
|
+
export function frontmostApplicationToken() {
|
|
7
|
+
const front = spawnSync("/usr/bin/lsappinfo", ["front"], { encoding: "utf8", timeout: 3000 });
|
|
8
|
+
const asn = (front.stdout ?? "").trim();
|
|
9
|
+
return front.status === 0 && asn.startsWith("ASN:") ? asn : undefined;
|
|
10
|
+
}
|
|
11
|
+
export function frontmostBundleId() {
|
|
12
|
+
const asn = frontmostApplicationToken();
|
|
13
|
+
if (!asn)
|
|
14
|
+
return undefined;
|
|
15
|
+
const info = spawnSync("/usr/bin/lsappinfo", ["info", "-only", "bundleID", asn], {
|
|
16
|
+
encoding: "utf8",
|
|
17
|
+
timeout: 3000,
|
|
18
|
+
});
|
|
19
|
+
if (info.status !== 0)
|
|
20
|
+
return undefined;
|
|
21
|
+
const match = (info.stdout ?? "").match(/"CFBundleIdentifier"="([^"]+)"/);
|
|
22
|
+
return match?.[1];
|
|
23
|
+
}
|
|
24
|
+
export async function frontmostBundleIdAsync() {
|
|
25
|
+
try {
|
|
26
|
+
const front = await execFileAsync("/usr/bin/lsappinfo", ["front"], { encoding: "utf8", timeout: 3000 });
|
|
27
|
+
const asn = front.stdout.trim();
|
|
28
|
+
if (!asn.startsWith("ASN:"))
|
|
29
|
+
return undefined;
|
|
30
|
+
const info = await execFileAsync("/usr/bin/lsappinfo", ["info", "-only", "bundleID", asn], {
|
|
31
|
+
encoding: "utf8",
|
|
32
|
+
timeout: 3000,
|
|
33
|
+
});
|
|
34
|
+
return info.stdout.match(/"CFBundleIdentifier"="([^"]+)"/)?.[1];
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const DICTIONARY_BUNDLE_ID = "com.apple.Dictionary";
|
|
41
|
+
const DICTIONARY_PATH = "/System/Applications/Dictionary.app";
|
|
42
|
+
function verifySystemDictionaryBundle(bundleId) {
|
|
43
|
+
if (bundleId !== DICTIONARY_BUNDLE_ID)
|
|
44
|
+
return false;
|
|
45
|
+
const verify = spawnSync("/usr/bin/codesign", ["--verify", "--strict", DICTIONARY_PATH], {
|
|
46
|
+
encoding: "utf8",
|
|
47
|
+
timeout: 10_000,
|
|
48
|
+
});
|
|
49
|
+
if (verify.status !== 0)
|
|
50
|
+
return false;
|
|
51
|
+
const requirement = spawnSync("/usr/bin/codesign", ["-dr", "-", DICTIONARY_PATH], {
|
|
52
|
+
encoding: "utf8",
|
|
53
|
+
timeout: 10_000,
|
|
54
|
+
});
|
|
55
|
+
const output = `${requirement.stdout ?? ""}\n${requirement.stderr ?? ""}`;
|
|
56
|
+
return requirement.status === 0 && output.includes(`identifier "${DICTIONARY_BUNDLE_ID}"`) && output.includes("anchor apple");
|
|
57
|
+
}
|
|
58
|
+
export function resolveAppIdentity(app) {
|
|
59
|
+
const trimmed = app.trim();
|
|
60
|
+
if (path.isAbsolute(trimmed)) {
|
|
61
|
+
try {
|
|
62
|
+
const resolvedPath = realpathSync(trimmed);
|
|
63
|
+
const plist = path.join(resolvedPath, "Contents", "Info.plist");
|
|
64
|
+
const metadata = spawnSync("/usr/bin/plutil", ["-extract", "CFBundleIdentifier", "raw", plist], {
|
|
65
|
+
encoding: "utf8",
|
|
66
|
+
timeout: 3000,
|
|
67
|
+
});
|
|
68
|
+
const bundleId = (metadata.stdout ?? "").trim();
|
|
69
|
+
if (metadata.status === 0 && /^[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)+$/.test(bundleId)) {
|
|
70
|
+
return {
|
|
71
|
+
bundleId,
|
|
72
|
+
leaseId: bundleId.toLowerCase(),
|
|
73
|
+
verifiedSystemDictionary: verifySystemDictionaryBundle(bundleId),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return { leaseId: `path:${resolvedPath.toLowerCase()}`, verifiedSystemDictionary: false };
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return { leaseId: `path:${trimmed.toLowerCase()}`, verifiedSystemDictionary: false };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const isBundleId = /^[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)+$/.test(trimmed);
|
|
83
|
+
const script = [
|
|
84
|
+
"on run argv",
|
|
85
|
+
isBundleId ? "id of application id (item 1 of argv)" : "id of application (item 1 of argv)",
|
|
86
|
+
"end run",
|
|
87
|
+
];
|
|
88
|
+
const result = spawnSync("/usr/bin/osascript", ["-e", script[0], "-e", script[1], "-e", script[2], "--", trimmed], {
|
|
89
|
+
encoding: "utf8",
|
|
90
|
+
timeout: 3000,
|
|
91
|
+
});
|
|
92
|
+
const resolvedBundleId = (result.stdout ?? "").trim();
|
|
93
|
+
if (result.status === 0 && /^[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)+$/.test(resolvedBundleId)) {
|
|
94
|
+
return {
|
|
95
|
+
bundleId: resolvedBundleId,
|
|
96
|
+
leaseId: resolvedBundleId.toLowerCase(),
|
|
97
|
+
verifiedSystemDictionary: verifySystemDictionaryBundle(resolvedBundleId),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
if (isBundleId)
|
|
101
|
+
return { leaseId: trimmed.toLowerCase(), verifiedSystemDictionary: false };
|
|
102
|
+
return { leaseId: `name:${trimmed.toLowerCase()}`, verifiedSystemDictionary: false };
|
|
103
|
+
}
|
|
104
|
+
export function resolveAppLeaseId(app) {
|
|
105
|
+
return resolveAppIdentity(app).leaseId;
|
|
106
|
+
}
|
|
107
|
+
export async function ensureAppRunningInBackground(app, identity = resolveAppIdentity(app)) {
|
|
108
|
+
if (identity.bundleId) {
|
|
109
|
+
const found = spawnSync("/usr/bin/lsappinfo", ["find", `bundleID=${identity.bundleId}`], {
|
|
110
|
+
encoding: "utf8",
|
|
111
|
+
timeout: 3000,
|
|
112
|
+
});
|
|
113
|
+
if (found.status === 0 && (found.stdout ?? "").trim().startsWith("ASN:"))
|
|
114
|
+
return identity;
|
|
115
|
+
}
|
|
116
|
+
const selectorIsBundleId = /^[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)+$/.test(app.trim());
|
|
117
|
+
const launchArgs = path.isAbsolute(app)
|
|
118
|
+
? ["-g", app]
|
|
119
|
+
: identity.bundleId || selectorIsBundleId
|
|
120
|
+
? ["-g", "-b", identity.bundleId ?? app.trim()]
|
|
121
|
+
: ["-g", "-a", app];
|
|
122
|
+
const launched = spawnSync("/usr/bin/open", launchArgs, { encoding: "utf8", timeout: 10_000 });
|
|
123
|
+
if (launched.status !== 0)
|
|
124
|
+
throw new Error("Could not launch the target app in the background");
|
|
125
|
+
for (let attempt = 0; attempt < 100; attempt++) {
|
|
126
|
+
const resolved = resolveAppIdentity(identity.bundleId ?? app);
|
|
127
|
+
if (resolved.bundleId) {
|
|
128
|
+
const found = spawnSync("/usr/bin/lsappinfo", ["find", `bundleID=${resolved.bundleId}`], {
|
|
129
|
+
encoding: "utf8",
|
|
130
|
+
timeout: 3000,
|
|
131
|
+
});
|
|
132
|
+
if (found.status === 0 && (found.stdout ?? "").trim().startsWith("ASN:"))
|
|
133
|
+
return resolved;
|
|
134
|
+
}
|
|
135
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
136
|
+
}
|
|
137
|
+
throw new Error("Target app did not become available after background launch");
|
|
138
|
+
}
|
|
139
|
+
function bundleIdForAsn(asn, infoPath = "/usr/bin/lsappinfo") {
|
|
140
|
+
const info = spawnSync(infoPath, ["info", "-only", "bundleID", asn], {
|
|
141
|
+
encoding: "utf8",
|
|
142
|
+
timeout: 3000,
|
|
143
|
+
});
|
|
144
|
+
if (info.status !== 0)
|
|
145
|
+
return undefined;
|
|
146
|
+
return (info.stdout ?? "").match(/"CFBundleIdentifier"="([^"]+)"/)?.[1];
|
|
147
|
+
}
|
|
148
|
+
export async function watchTargetFrontmost(listenerPath = "/usr/bin/lsappinfo", infoPath = "/usr/bin/lsappinfo") {
|
|
149
|
+
// Listen globally so a stopped/display-name target is covered before background launch and canonical resolution.
|
|
150
|
+
const proc = spawn(listenerPath, ["listen", "+becameFrontmost", "forever"], {
|
|
151
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
152
|
+
});
|
|
153
|
+
const observedBundles = new Set();
|
|
154
|
+
const observedAsns = new Set();
|
|
155
|
+
const unresolvedAsns = new Set();
|
|
156
|
+
let running = true;
|
|
157
|
+
let buffer = "";
|
|
158
|
+
const resolvePending = () => {
|
|
159
|
+
for (const asn of unresolvedAsns) {
|
|
160
|
+
const bundleId = bundleIdForAsn(asn, infoPath);
|
|
161
|
+
if (!bundleId)
|
|
162
|
+
continue;
|
|
163
|
+
observedBundles.add(bundleId.toLowerCase());
|
|
164
|
+
observedAsns.add(asn);
|
|
165
|
+
unresolvedAsns.delete(asn);
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
const retryTimer = setInterval(resolvePending, 50);
|
|
169
|
+
retryTimer.unref();
|
|
170
|
+
const markStopped = () => {
|
|
171
|
+
running = false;
|
|
172
|
+
clearInterval(retryTimer);
|
|
173
|
+
};
|
|
174
|
+
proc.stdout.setEncoding("utf8");
|
|
175
|
+
proc.stdout.on("data", (chunk) => {
|
|
176
|
+
buffer = `${buffer}${chunk}`.slice(-16_384);
|
|
177
|
+
for (const match of buffer.matchAll(/ASN:0x[0-9a-f]+-0x[0-9a-f]+/gi)) {
|
|
178
|
+
const asn = match[0];
|
|
179
|
+
if (!observedAsns.has(asn))
|
|
180
|
+
unresolvedAsns.add(asn);
|
|
181
|
+
}
|
|
182
|
+
resolvePending();
|
|
183
|
+
});
|
|
184
|
+
proc.once("error", markStopped);
|
|
185
|
+
proc.once("close", markStopped);
|
|
186
|
+
await new Promise((resolve) => setTimeout(resolve, 75));
|
|
187
|
+
if (!running || proc.exitCode !== null)
|
|
188
|
+
throw new Error("Target focus-event monitor failed to start");
|
|
189
|
+
return {
|
|
190
|
+
becameFrontmost: (bundleId) => {
|
|
191
|
+
resolvePending();
|
|
192
|
+
return observedBundles.has(bundleId.toLowerCase());
|
|
193
|
+
},
|
|
194
|
+
healthy: () => running && proc.exitCode === null,
|
|
195
|
+
stop: async () => {
|
|
196
|
+
if (proc.exitCode === null) {
|
|
197
|
+
proc.kill("SIGTERM");
|
|
198
|
+
await new Promise((resolve) => {
|
|
199
|
+
const timeout = setTimeout(resolve, 1000);
|
|
200
|
+
proc.once("close", () => {
|
|
201
|
+
clearTimeout(timeout);
|
|
202
|
+
resolve();
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
if (proc.exitCode === null) {
|
|
206
|
+
proc.kill("SIGKILL");
|
|
207
|
+
await new Promise((resolve) => {
|
|
208
|
+
const timeout = setTimeout(resolve, 500);
|
|
209
|
+
proc.once("close", () => {
|
|
210
|
+
clearTimeout(timeout);
|
|
211
|
+
resolve();
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
clearInterval(retryTimer);
|
|
217
|
+
// Events may arrive only while SIGTERM is draining stdout. Resolve every queued ASN before returning.
|
|
218
|
+
for (let attempt = 0; unresolvedAsns.size > 0 && attempt < 10; attempt += 1) {
|
|
219
|
+
resolvePending();
|
|
220
|
+
if (unresolvedAsns.size > 0)
|
|
221
|
+
await new Promise((resolve) => setTimeout(resolve, 25));
|
|
222
|
+
}
|
|
223
|
+
if (unresolvedAsns.size > 0)
|
|
224
|
+
throw new Error("Could not resolve all queued focus-event identities");
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=system.js.map
|