@cydm/pie 2.6.11 → 2.7.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/README.md +68 -2
- package/dist/builtin/extensions/ask-user/index.js +3 -3
- package/dist/builtin/extensions/plan-mode/index.js +130 -21
- package/dist/builtin/extensions/subagent/index.js +4 -5
- package/dist/builtin/extensions/todo/index.js +3 -3
- package/dist/builtin/skills/computer-use-axi/SKILL.md +103 -0
- package/dist/builtin/skills/computer-use-axi/computer-use-axi-cli.js +37 -0
- package/dist/builtin/{extensions/computer-use/index.js → skills/computer-use-axi/computer-use-axi-runtime.js} +754 -642
- package/dist/builtin/skills/computer-use-axi/package.json +11 -0
- package/dist/chunks/{chunk-ZVM234WE.js → chunk-6RBSTII7.js} +669 -594
- package/dist/chunks/{chunk-MA4CHFN4.js → chunk-IPNAFMOJ.js} +172 -230
- package/dist/chunks/{chunk-7B4IIBVS.js → chunk-R5I2QLF2.js} +1269 -4
- package/dist/chunks/{chunk-PAC62XU4.js → chunk-TWILEFLD.js} +25 -3
- package/dist/chunks/{src-HPIBCE2I.js → src-E7NCXMU5.js} +2 -2
- package/dist/chunks/{test-stream-Y7WXELAJ.js → test-stream-BWBJTFNI.js} +1 -1
- package/dist/cli.js +1979 -384
- package/models.schema.json +52 -0
- package/package.json +3 -3
- package/dist/builtin/extensions/computer-use/package.json +0 -14
- package/dist/builtin/extensions/computer-use/scripts/build-native.mjs +0 -278
- package/dist/builtin/extensions/computer-use/scripts/test-native-retention.mjs +0 -204
- package/dist/chunks/chunk-5353DEEC.js +0 -130
- package/dist/chunks/webapi-MBCKO7ZV.js +0 -2481
- package/dist/code-intel-worker.cjs +0 -211227
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/linux/arm64/linux-bridge +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/linux/x64/linux-bridge +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/macos/arm64/pie-computer-use +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/macos/universal/pie-computer-use.app/Contents/Info.plist +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/macos/universal/pie-computer-use.app/Contents/MacOS/pie-computer-use +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/macos/universal/pie-computer-use.app/Contents/_CodeSignature/CodeResources +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/macos/x64/pie-computer-use +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/windows/windows-bridge.exe +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/scripts/helper-path.mjs +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/scripts/setup-helper.mjs +0 -0
package/models.schema.json
CHANGED
|
@@ -285,6 +285,15 @@
|
|
|
285
285
|
"type": "object",
|
|
286
286
|
"additionalProperties": false,
|
|
287
287
|
"properties": {
|
|
288
|
+
"store": {
|
|
289
|
+
"type": "boolean"
|
|
290
|
+
},
|
|
291
|
+
"supportsEncryptedReasoning": {
|
|
292
|
+
"type": "boolean"
|
|
293
|
+
},
|
|
294
|
+
"responsesContinuation": {
|
|
295
|
+
"type": "boolean"
|
|
296
|
+
},
|
|
288
297
|
"supportsStore": {
|
|
289
298
|
"type": "boolean"
|
|
290
299
|
},
|
|
@@ -347,10 +356,18 @@
|
|
|
347
356
|
"pattern": "^[^\\u0000-\\u0008\\u000A-\\u001F\\u007F]*$"
|
|
348
357
|
}
|
|
349
358
|
},
|
|
359
|
+
"api": {
|
|
360
|
+
"type": "string",
|
|
361
|
+
"enum": ["openai-completions", "openai-responses", "anthropic-messages"]
|
|
362
|
+
},
|
|
350
363
|
"model": {
|
|
351
364
|
"type": "object",
|
|
352
365
|
"additionalProperties": false,
|
|
353
366
|
"properties": {
|
|
367
|
+
"api": {
|
|
368
|
+
"$ref": "#/$defs/api",
|
|
369
|
+
"description": "Optional API selector; inherits profile api. A different API requires profile endpoints[api]."
|
|
370
|
+
},
|
|
354
371
|
"id": {
|
|
355
372
|
"type": "string",
|
|
356
373
|
"minLength": 1,
|
|
@@ -420,6 +437,14 @@
|
|
|
420
437
|
"attachmentPlatform": {
|
|
421
438
|
"type": "string",
|
|
422
439
|
"minLength": 1
|
|
440
|
+
},
|
|
441
|
+
"transport": {
|
|
442
|
+
"type": "string",
|
|
443
|
+
"enum": [
|
|
444
|
+
"sse",
|
|
445
|
+
"websocket",
|
|
446
|
+
"auto"
|
|
447
|
+
]
|
|
423
448
|
}
|
|
424
449
|
},
|
|
425
450
|
"required": [
|
|
@@ -434,6 +459,16 @@
|
|
|
434
459
|
"type": "object",
|
|
435
460
|
"additionalProperties": false,
|
|
436
461
|
"properties": {
|
|
462
|
+
"endpoints": {
|
|
463
|
+
"type": "object",
|
|
464
|
+
"description": "Optional API-specific roots; keys must be supported APIs. Routing relationships are validated by the runtime.",
|
|
465
|
+
"propertyNames": { "$ref": "#/$defs/api" },
|
|
466
|
+
"additionalProperties": {
|
|
467
|
+
"type": "string",
|
|
468
|
+
"format": "uri",
|
|
469
|
+
"pattern": "^https?://"
|
|
470
|
+
}
|
|
471
|
+
},
|
|
437
472
|
"baseUrl": {
|
|
438
473
|
"type": "string",
|
|
439
474
|
"format": "uri",
|
|
@@ -443,6 +478,7 @@
|
|
|
443
478
|
"type": "string",
|
|
444
479
|
"enum": [
|
|
445
480
|
"openai-completions",
|
|
481
|
+
"openai-responses",
|
|
446
482
|
"anthropic-messages"
|
|
447
483
|
]
|
|
448
484
|
},
|
|
@@ -487,6 +523,14 @@
|
|
|
487
523
|
"items": {
|
|
488
524
|
"$ref": "#/$defs/model"
|
|
489
525
|
}
|
|
526
|
+
},
|
|
527
|
+
"transport": {
|
|
528
|
+
"type": "string",
|
|
529
|
+
"enum": [
|
|
530
|
+
"sse",
|
|
531
|
+
"websocket",
|
|
532
|
+
"auto"
|
|
533
|
+
]
|
|
490
534
|
}
|
|
491
535
|
},
|
|
492
536
|
"required": [
|
|
@@ -576,6 +620,14 @@
|
|
|
576
620
|
"displayName": {
|
|
577
621
|
"type": "string",
|
|
578
622
|
"minLength": 1
|
|
623
|
+
},
|
|
624
|
+
"transport": {
|
|
625
|
+
"type": "string",
|
|
626
|
+
"enum": [
|
|
627
|
+
"sse",
|
|
628
|
+
"websocket",
|
|
629
|
+
"auto"
|
|
630
|
+
]
|
|
579
631
|
}
|
|
580
632
|
}
|
|
581
633
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cydm/pie",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"description": "Pie AI Agent CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
"validate:models": "tsx scripts/validate-models-config.ts",
|
|
18
18
|
"test": "npm run test:offline",
|
|
19
19
|
"pretest:offline": "npm run build --workspace @pie/agent-framework && npm run build --workspace @pie/shared-headless-capabilities && npm run build && npm run test:skill-regressions",
|
|
20
|
-
"test:skill-regressions": "node --test --import tsx test/bash-lifecycle.test.ts test/skill-creator-runner.test.ts test/tui-use-contract.test.ts test/tui-use-runtime.test.ts test/browser-runtime.test.ts test/axi-stop-semantics.test.ts test/computer-evidence.test.ts test/interactive-lifecycle.test.ts",
|
|
20
|
+
"test:skill-regressions": "node --test --import tsx test/bash-lifecycle.test.ts test/skill-creator-runner.test.ts test/tui-use-contract.test.ts test/tui-use-runtime.test.ts test/browser-runtime.test.ts test/axi-stop-semantics.test.ts test/computer-use-axi.test.ts test/computer-evidence.test.ts test/interactive-lifecycle.test.ts",
|
|
21
21
|
"posttest:offline": "node --test --import tsx test/remote-model-catalog.test.ts",
|
|
22
|
-
"test:offline": "node --test --test-concurrency=4 --import tsx test/cli-attention.test.ts test/builtin-extensions.test.ts test/core-services.test.ts test/cli.test.ts test/cli-auto-compaction.test.ts test/execution-state-manager.test.ts test/queued-steer-execution-state.test.ts test/architecture-boundaries.test.ts test/attachment-resolver.test.ts test/kimi-attachment-provider.test.ts test/document-attachment-extension.test.ts test/auto-compact-overflow.test.ts test/auto-compaction-ui.test.ts test/hierarchical-command-system.test.ts test/mcp-adapter.test.ts test/herdr-agent-state.test.ts test/extensions-enablement.test.ts test/extension-selector-shortcuts.test.ts test/skill-tool-enablement.test.ts test/message-queue-unit.test.ts test/evals-harness.test.ts test/session-trace.test.ts test/subagent-session-store.test.ts test/runtime-mode-context.test.ts test/tool-policy.test.ts test/retry-policy.test.ts test/yolo-command.test.ts test/footer-lifecycle.test.ts test/files-utils.test.ts test/source-size-guard.test.ts test/runtime-logger.test.ts test/release-readiness.test.ts test/package-artifacts.test.ts test/
|
|
22
|
+
"test:offline": "node --test --test-concurrency=4 --import tsx test/cli-attention.test.ts test/builtin-extensions.test.ts test/core-services.test.ts test/cli.test.ts test/cli-auto-compaction.test.ts test/execution-state-manager.test.ts test/queued-steer-execution-state.test.ts test/architecture-boundaries.test.ts test/attachment-resolver.test.ts test/kimi-attachment-provider.test.ts test/document-attachment-extension.test.ts test/auto-compact-overflow.test.ts test/auto-compaction-ui.test.ts test/hierarchical-command-system.test.ts test/mcp-adapter.test.ts test/herdr-agent-state.test.ts test/extensions-enablement.test.ts test/extension-selector-shortcuts.test.ts test/skill-tool-enablement.test.ts test/message-queue-unit.test.ts test/evals-harness.test.ts test/session-trace.test.ts test/subagent-session-store.test.ts test/runtime-mode-context.test.ts test/tool-policy.test.ts test/retry-policy.test.ts test/yolo-command.test.ts test/footer-lifecycle.test.ts test/files-utils.test.ts test/source-size-guard.test.ts test/runtime-logger.test.ts test/release-readiness.test.ts test/package-artifacts.test.ts test/init-extension-contract.test.ts test/skills-runtime.test.ts test/skills-agents-discovery.test.ts test/skills-symlink.test.ts test/model-overrides.test.ts test/auth-storage.test.ts test/extension-register-provider.test.ts test/extension-reload.test.ts test/extension-terminal-input.test.ts test/extension-session-before-events.test.ts test/extension-widgets.test.ts test/extension-render-hint.test.ts test/extension-oauth-restore.test.ts test/cross-host-parity.test.ts test/tool-name-rendering.test.ts test/session-selector.test.ts test/tree-selector-pagination.test.ts test/context-report.test.ts test/context-signals.test.ts test/plan-cache-stability.test.ts test/cache-invalidation-trace.test.ts test/cache-retention.test.ts test/trace-report.test.ts test/boot-report.test.ts test/compaction-diff.test.ts test/entry-body-and-usage.test.ts test/session-control.test.ts test/terminal-title.test.ts test/interactive-controller-title.test.ts test/todo-title.terminal.test.ts test/plan-mode-extension.test.ts test/rendered-page-reader.test.ts test/tools-registry.test.ts test/system-prompt-contract.test.ts test/bash-yolo.test.ts test/bash-confirm-pending.test.ts test/interaction-status-lifecycle.test.ts test/bash-process-group.test.ts test/bash-artifact-sink.test.ts test/direct-bash.test.ts test/terminal-bell.test.ts test/ctrl-d-exit.test.ts test/session-display-title.test.ts test/calm-mode.test.ts test/stream-render-throttle.test.ts test/message-display-resync.test.ts test/project-root.test.ts test/guard-advisory-context.test.ts test/clear-command-usage.test.ts test/daily-agent-smoke.terminal.test.ts test/slash-menu-toggles.terminal.test.ts test/cli-args.test.ts test/extensions-configured-paths.test.ts test/extensions-loader-path.test.ts test/file-picker.test.ts test/interrupt-recovery.test.ts test/mention-insert-regression.test.ts test/mention-picker-navigation.test.ts test/pie-unity-rpc-skill.test.ts test/skill-creator-scripts.test.ts",
|
|
23
23
|
"test:all": "npm run test:offline && npm run test:terminal:vitest",
|
|
24
24
|
"test:terminal:vitest": "vitest run test/mention-file-select.terminal.test.ts test/tool-partial-display.terminal.test.ts test/footer-plan-mode.test.ts test/viewport-position-final.test.ts test/resume-header.terminal.test.ts --no-file-parallelism",
|
|
25
25
|
"test:todo-tui": "node ../../scripts/run-with-env.mjs PIE_REAL_TODO_TUI=1 -- --test --import tsx test/todo-closure.terminal.test.ts",
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@pie/extension-computer-use",
|
|
3
|
-
"version": "0.5.1",
|
|
4
|
-
"description": "Desktop computer-use tools (observe/act) vendored from @injaneity/pi-computer-use",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"scripts": {
|
|
8
|
-
"test:native-retention": "node scripts/test-native-retention.mjs"
|
|
9
|
-
},
|
|
10
|
-
"pie": {
|
|
11
|
-
"name": "computer-use",
|
|
12
|
-
"main": "index.js"
|
|
13
|
-
}
|
|
14
|
-
}
|
|
@@ -1,278 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { spawn } from "node:child_process";
|
|
4
|
-
import fs from "node:fs/promises";
|
|
5
|
-
import os from "node:os";
|
|
6
|
-
import path from "node:path";
|
|
7
|
-
import { fileURLToPath } from "node:url";
|
|
8
|
-
|
|
9
|
-
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
10
|
-
const macosSourcePaths = [
|
|
11
|
-
"agent_cursor.swift",
|
|
12
|
-
"agent_cursor_motion.swift",
|
|
13
|
-
"bridge.swift",
|
|
14
|
-
"ref_store.swift",
|
|
15
|
-
].map((file) => path.join(rootDir, "native", "macos", file));
|
|
16
|
-
const windowsCrateDir = path.join(rootDir, "native", "windows", "bridge-rs");
|
|
17
|
-
const linuxCrateDir = path.join(rootDir, "native", "linux", "bridge-rs");
|
|
18
|
-
const linuxTargets = { x64: "x86_64-unknown-linux-gnu", arm64: "aarch64-unknown-linux-gnu" };
|
|
19
|
-
const archTriples = {
|
|
20
|
-
arm64: "arm64-apple-macosx",
|
|
21
|
-
x64: "x86_64-apple-macosx",
|
|
22
|
-
};
|
|
23
|
-
const deploymentTarget = "14.0";
|
|
24
|
-
const frameworks = ["ApplicationServices", "AppKit", "ScreenCaptureKit", "Foundation", "SwiftUI", "CryptoKit"];
|
|
25
|
-
const defaultCodeSignIdentifier = "com.pie.computer-use";
|
|
26
|
-
|
|
27
|
-
async function exists(filePath) {
|
|
28
|
-
try {
|
|
29
|
-
await fs.access(filePath);
|
|
30
|
-
return true;
|
|
31
|
-
} catch {
|
|
32
|
-
return false;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function getArg(name) {
|
|
37
|
-
const index = process.argv.indexOf(name);
|
|
38
|
-
if (index >= 0 && index + 1 < process.argv.length) {
|
|
39
|
-
return process.argv[index + 1];
|
|
40
|
-
}
|
|
41
|
-
return undefined;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function hasArg(name) {
|
|
45
|
-
return process.argv.includes(name);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function normalizeArch(arch) {
|
|
49
|
-
if (arch === "universal" || arch === "all") return arch;
|
|
50
|
-
if (arch === "arm64" || arch === "x64") return arch;
|
|
51
|
-
throw new Error(`Unsupported architecture '${arch}'. Supported: arm64, x64, universal, all.`);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
async function run(command, args) {
|
|
55
|
-
await new Promise((resolve, reject) => {
|
|
56
|
-
const child = spawn(command, args, { stdio: "inherit" });
|
|
57
|
-
child.on("error", reject);
|
|
58
|
-
child.on("close", (code) => {
|
|
59
|
-
if (code === 0) {
|
|
60
|
-
resolve();
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
reject(new Error(`Command failed (${code}): ${command} ${args.join(" ")}`));
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function defaultOutputPath(arch) {
|
|
69
|
-
return path.join(rootDir, "prebuilt", "macos", arch, "pie-computer-use");
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function moduleCachePath(arch) {
|
|
73
|
-
return path.join(os.tmpdir(), `pie-computer-use-swift-module-cache-${arch}`);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function swiftArgsForArch(arch, outputPath) {
|
|
77
|
-
const args = [
|
|
78
|
-
"swiftc",
|
|
79
|
-
"-target",
|
|
80
|
-
`${archTriples[arch]}${deploymentTarget}`,
|
|
81
|
-
"-module-cache-path",
|
|
82
|
-
moduleCachePath(arch),
|
|
83
|
-
"-O",
|
|
84
|
-
];
|
|
85
|
-
for (const framework of frameworks) args.push("-framework", framework);
|
|
86
|
-
args.push(...macosSourcePaths, "-o", outputPath);
|
|
87
|
-
return args;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async function signBinary(outputPath) {
|
|
91
|
-
if (hasArg("--no-sign") || process.env.PIE_COMPUTER_USE_NO_SIGN === "1") {
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const identity = getArg("--sign-identity") ?? process.env.PIE_COMPUTER_USE_CODESIGN_IDENTITY ?? "-";
|
|
96
|
-
const identifier = getArg("--sign-identifier") ?? process.env.PIE_COMPUTER_USE_CODESIGN_IDENTIFIER ?? defaultCodeSignIdentifier;
|
|
97
|
-
const args = ["--force", "-i", identifier];
|
|
98
|
-
if (hasArg("--hardened-runtime")) {
|
|
99
|
-
args.push("--options", "runtime");
|
|
100
|
-
}
|
|
101
|
-
if (hasArg("--timestamp")) {
|
|
102
|
-
args.push("--timestamp");
|
|
103
|
-
} else {
|
|
104
|
-
args.push("--timestamp=none");
|
|
105
|
-
}
|
|
106
|
-
args.push("--sign", identity, outputPath);
|
|
107
|
-
await run("codesign", args);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
async function buildForArch(arch, outputPath) {
|
|
111
|
-
await fs.mkdir(path.dirname(outputPath), { recursive: true });
|
|
112
|
-
console.log(`Building native helper for ${arch}...`);
|
|
113
|
-
await run("xcrun", swiftArgsForArch(arch, outputPath));
|
|
114
|
-
await fs.chmod(outputPath, 0o755);
|
|
115
|
-
await signBinary(outputPath);
|
|
116
|
-
console.log(`Built helper at ${outputPath}`);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
async function buildUniversal(outputPath) {
|
|
120
|
-
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "pie-computer-use-build-"));
|
|
121
|
-
const x64Output = path.join(tempDir, "pie-computer-use-x64");
|
|
122
|
-
const arm64Output = path.join(tempDir, "pie-computer-use-arm64");
|
|
123
|
-
await buildForArch("x64", x64Output);
|
|
124
|
-
await buildForArch("arm64", arm64Output);
|
|
125
|
-
await fs.mkdir(path.dirname(outputPath), { recursive: true });
|
|
126
|
-
await run("lipo", ["-create", "-output", outputPath, x64Output, arm64Output]);
|
|
127
|
-
await fs.chmod(outputPath, 0o755);
|
|
128
|
-
await signBinary(outputPath);
|
|
129
|
-
console.log(`Built universal helper at ${outputPath}`);
|
|
130
|
-
await fs.rm(tempDir, { recursive: true, force: true });
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Return the actual cargo binary path, handling platform suffix differences.
|
|
135
|
-
* On Windows, the binary is named "windows-bridge.exe"; on other platforms it's "windows-bridge".
|
|
136
|
-
*/
|
|
137
|
-
function windowsBinaryPath(crateDir, target) {
|
|
138
|
-
const releaseDir = target
|
|
139
|
-
? path.join(crateDir, "target", target, "release")
|
|
140
|
-
: path.join(crateDir, "target", "release");
|
|
141
|
-
return path.join(releaseDir, "windows-bridge.exe");
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
async function buildWindowsHelper(prebuiltOutput) {
|
|
145
|
-
const target = getArg("--target");
|
|
146
|
-
if (process.platform !== "win32" && !target?.includes("windows")) {
|
|
147
|
-
throw new Error("Refusing to label a host binary as Windows. Build on Windows or pass an explicit Windows --target triple.");
|
|
148
|
-
}
|
|
149
|
-
const prebuiltDir = prebuiltOutput
|
|
150
|
-
? path.resolve(process.cwd(), prebuiltOutput, "..")
|
|
151
|
-
: path.join(rootDir, "prebuilt", "windows");
|
|
152
|
-
const manifestPath = path.join(windowsCrateDir, "Cargo.toml");
|
|
153
|
-
|
|
154
|
-
console.log("Building Windows helper with cargo...");
|
|
155
|
-
const cargoArgs = [
|
|
156
|
-
"build",
|
|
157
|
-
"--release",
|
|
158
|
-
"--manifest-path",
|
|
159
|
-
manifestPath,
|
|
160
|
-
];
|
|
161
|
-
if (target) cargoArgs.push("--target", target);
|
|
162
|
-
await run("cargo", cargoArgs);
|
|
163
|
-
|
|
164
|
-
await fs.mkdir(prebuiltDir, { recursive: true });
|
|
165
|
-
|
|
166
|
-
const cargoOutput = windowsBinaryPath(windowsCrateDir, target);
|
|
167
|
-
const handle = await fs.open(cargoOutput, "r");
|
|
168
|
-
try {
|
|
169
|
-
const signature = Buffer.alloc(2);
|
|
170
|
-
await handle.read(signature, 0, 2, 0);
|
|
171
|
-
if (signature.toString("ascii") !== "MZ") {
|
|
172
|
-
throw new Error(`Cargo output is not a Windows PE executable: ${cargoOutput}`);
|
|
173
|
-
}
|
|
174
|
-
} finally {
|
|
175
|
-
await handle.close();
|
|
176
|
-
}
|
|
177
|
-
const prebuiltDest = path.join(prebuiltDir, "windows-bridge.exe");
|
|
178
|
-
await fs.copyFile(cargoOutput, prebuiltDest);
|
|
179
|
-
await fs.chmod(prebuiltDest, 0o755);
|
|
180
|
-
console.log(`Built Windows helper at ${prebuiltDest}`);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
function linuxBinaryPath(crateDir, target) {
|
|
184
|
-
const targetDir = target ? path.join("target", target) : "target";
|
|
185
|
-
return path.join(crateDir, targetDir, "release", "linux-bridge");
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
function defaultLinuxOutputPath(arch) {
|
|
189
|
-
return path.join(rootDir, "prebuilt", "linux", arch, "linux-bridge");
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
async function buildLinuxForArch(arch, outputPath) {
|
|
193
|
-
const explicitTarget = getArg("--target");
|
|
194
|
-
if (explicitTarget && !explicitTarget.includes("linux")) throw new Error(`Linux builds require a Linux --target triple, got ${explicitTarget}.`);
|
|
195
|
-
const target = explicitTarget ?? (process.platform === "linux" && process.arch === arch ? undefined : linuxTargets[arch]);
|
|
196
|
-
console.log(`Building Linux helper for ${arch} with cargo...`);
|
|
197
|
-
const cargoArgs = ["build", "--release", "--manifest-path", path.join(linuxCrateDir, "Cargo.toml")];
|
|
198
|
-
if (target) cargoArgs.push("--target", target);
|
|
199
|
-
await run("cargo", cargoArgs);
|
|
200
|
-
const cargoOutput = linuxBinaryPath(linuxCrateDir, target);
|
|
201
|
-
const header = await fs.readFile(cargoOutput).then((data) => data.subarray(0, 20));
|
|
202
|
-
if (header.length < 20 || !header.subarray(0, 4).equals(Buffer.from([0x7f, 0x45, 0x4c, 0x46]))) throw new Error(`Cargo output is not a Linux ELF executable: ${cargoOutput}`);
|
|
203
|
-
const machine = header.readUInt16LE(18);
|
|
204
|
-
const expectedMachine = arch === "x64" ? 0x3e : 0xb7;
|
|
205
|
-
if (machine !== expectedMachine) throw new Error(`Cargo output architecture does not match ${arch}: ${cargoOutput}`);
|
|
206
|
-
await fs.mkdir(path.dirname(outputPath), { recursive: true });
|
|
207
|
-
await fs.copyFile(cargoOutput, outputPath);
|
|
208
|
-
await fs.chmod(outputPath, 0o755);
|
|
209
|
-
console.log(`Built Linux helper at ${outputPath}`);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
async function buildLinuxHelper() {
|
|
213
|
-
const arch = normalizeArch(getArg("--arch") ?? process.arch);
|
|
214
|
-
if (arch === "universal") throw new Error("Linux does not support --arch universal. Use x64, arm64, or all.");
|
|
215
|
-
const outputArg = getArg("--output");
|
|
216
|
-
if (arch === "all") {
|
|
217
|
-
if (outputArg) throw new Error("--output is not supported with --arch all. Use a single architecture for one output.");
|
|
218
|
-
for (const nextArch of ["x64", "arm64"]) await buildLinuxForArch(nextArch, defaultLinuxOutputPath(nextArch));
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
await buildLinuxForArch(arch, outputArg ? path.resolve(process.cwd(), outputArg) : defaultLinuxOutputPath(arch));
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
async function main() {
|
|
225
|
-
const explicitPlatform = getArg("--platform");
|
|
226
|
-
|
|
227
|
-
if (explicitPlatform === "windows") {
|
|
228
|
-
await buildWindowsHelper(getArg("--output"));
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
if (explicitPlatform === "linux") {
|
|
233
|
-
await buildLinuxHelper();
|
|
234
|
-
return;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
if (explicitPlatform === "darwin") {
|
|
238
|
-
// Fall through to macOS build logic below.
|
|
239
|
-
} else if (process.platform === "win32") {
|
|
240
|
-
await buildWindowsHelper(getArg("--output"));
|
|
241
|
-
return;
|
|
242
|
-
} else if (process.platform === "linux") {
|
|
243
|
-
await buildLinuxHelper();
|
|
244
|
-
return;
|
|
245
|
-
} else if (process.platform !== "darwin") {
|
|
246
|
-
console.log(
|
|
247
|
-
`Skipping native build: unsupported platform "${process.platform}". ` +
|
|
248
|
-
"Use --platform windows or --platform linux to build a helper, or run on macOS for the macOS helper.",
|
|
249
|
-
);
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
const arch = normalizeArch(getArg("--arch") ?? process.arch);
|
|
254
|
-
const outputArg = getArg("--output");
|
|
255
|
-
|
|
256
|
-
if (arch === "all") {
|
|
257
|
-
if (outputArg) {
|
|
258
|
-
throw new Error("--output is not supported with --arch all. Use a single architecture for one output.");
|
|
259
|
-
}
|
|
260
|
-
for (const nextArch of ["x64", "arm64"]) {
|
|
261
|
-
await buildForArch(nextArch, defaultOutputPath(nextArch));
|
|
262
|
-
}
|
|
263
|
-
return;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
const outputPath = outputArg ? path.resolve(process.cwd(), outputArg) : defaultOutputPath(arch);
|
|
267
|
-
if (arch === "universal") {
|
|
268
|
-
await buildUniversal(outputPath);
|
|
269
|
-
return;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
await buildForArch(arch, outputPath);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
main().catch((error) => {
|
|
276
|
-
console.error(error instanceof Error ? error.message : String(error));
|
|
277
|
-
process.exit(1);
|
|
278
|
-
});
|
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// Compiles and runs the macOS native AXRefStore retention tests
|
|
4
|
-
// (native/macos/retention_tests.swift) from source, then compiles the full
|
|
5
|
-
// helper and drives its stdin JSON-lines transport with permission-free
|
|
6
|
-
// requests to assert the bridge-level stale-ref/stale-look integration.
|
|
7
|
-
//
|
|
8
|
-
// Nothing here needs Accessibility or Screen Recording permission or real UI
|
|
9
|
-
// interaction: the store tests use synthetic AXUIElement values, and the
|
|
10
|
-
// helper protocol probes only exercise failure paths (unknown look/element
|
|
11
|
-
// ids, missing windows). This script is macOS-only by design; on other
|
|
12
|
-
// platforms it skips with an explicit message (Linux/Windows helpers have
|
|
13
|
-
// their own native suites).
|
|
14
|
-
|
|
15
|
-
import { spawn } from "node:child_process";
|
|
16
|
-
import fs from "node:fs/promises";
|
|
17
|
-
import os from "node:os";
|
|
18
|
-
import path from "node:path";
|
|
19
|
-
import { fileURLToPath } from "node:url";
|
|
20
|
-
|
|
21
|
-
const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
22
|
-
const nativeDir = path.join(rootDir, "native", "macos");
|
|
23
|
-
const storeTestSources = ["ref_store.swift", "retention_tests.swift"].map((file) => path.join(nativeDir, file));
|
|
24
|
-
const helperSources = ["agent_cursor.swift", "agent_cursor_motion.swift", "bridge.swift", "ref_store.swift"].map((file) => path.join(nativeDir, file));
|
|
25
|
-
const deploymentTarget = "14.0";
|
|
26
|
-
const helperFrameworks = ["ApplicationServices", "AppKit", "ScreenCaptureKit", "Foundation", "SwiftUI", "CryptoKit"];
|
|
27
|
-
|
|
28
|
-
function run(command, args, options = {}) {
|
|
29
|
-
return new Promise((resolve, reject) => {
|
|
30
|
-
const child = spawn(command, args, { stdio: "inherit", ...options });
|
|
31
|
-
child.on("error", reject);
|
|
32
|
-
child.on("close", (code) => {
|
|
33
|
-
if (code === 0) {
|
|
34
|
-
resolve();
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
reject(new Error(`Command failed (${code}): ${command} ${args.join(" ")}`));
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function swiftcArgs(sources, output, moduleCache, frameworks) {
|
|
43
|
-
const args = [
|
|
44
|
-
"swiftc",
|
|
45
|
-
"-target",
|
|
46
|
-
`${process.arch === "arm64" ? "arm64" : "x86_64"}-apple-macosx${deploymentTarget}`,
|
|
47
|
-
"-module-cache-path",
|
|
48
|
-
moduleCache,
|
|
49
|
-
"-O",
|
|
50
|
-
];
|
|
51
|
-
for (const framework of frameworks) args.push("-framework", framework);
|
|
52
|
-
args.push(...sources, "-o", output);
|
|
53
|
-
return args;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/** Drives the helper over its stdin transport and resolves one response per request id. */
|
|
57
|
-
function helperResponses(executable, requests, timeoutMs = 15_000) {
|
|
58
|
-
return new Promise((resolve, reject) => {
|
|
59
|
-
const child = spawn(executable, [], { stdio: ["pipe", "pipe", "ignore"] });
|
|
60
|
-
const pending = new Map(requests.map((request) => [request.id, request]));
|
|
61
|
-
const settled = new Map();
|
|
62
|
-
const fail = (error) => {
|
|
63
|
-
child.kill();
|
|
64
|
-
reject(error);
|
|
65
|
-
};
|
|
66
|
-
const timer = setTimeout(() => fail(new Error(`Helper did not answer all requests within ${timeoutMs}ms`)), timeoutMs);
|
|
67
|
-
let buffer = "";
|
|
68
|
-
child.stdout.setEncoding("utf8");
|
|
69
|
-
child.stdout.on("data", (chunk) => {
|
|
70
|
-
buffer += chunk;
|
|
71
|
-
let newline;
|
|
72
|
-
while ((newline = buffer.indexOf("\n")) >= 0) {
|
|
73
|
-
const line = buffer.slice(0, newline);
|
|
74
|
-
buffer = buffer.slice(newline + 1);
|
|
75
|
-
if (!line.trim()) continue;
|
|
76
|
-
let response;
|
|
77
|
-
try {
|
|
78
|
-
response = JSON.parse(line);
|
|
79
|
-
} catch {
|
|
80
|
-
continue;
|
|
81
|
-
}
|
|
82
|
-
if (typeof response.id === "string" && pending.delete(response.id)) {
|
|
83
|
-
settled.set(response.id, response);
|
|
84
|
-
if (pending.size === 0) {
|
|
85
|
-
clearTimeout(timer);
|
|
86
|
-
child.stdin.end();
|
|
87
|
-
child.on("close", () => resolve(settled));
|
|
88
|
-
child.kill();
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
child.on("error", fail);
|
|
94
|
-
for (const request of requests) child.stdin.write(`${JSON.stringify(request)}\n`);
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/** Verifies the helper's true-exit path: shutdown answers, then the process exits zero on its own. */
|
|
99
|
-
function helperShutdownExits(executable, timeoutMs = 8_000) {
|
|
100
|
-
return new Promise((resolve, reject) => {
|
|
101
|
-
const child = spawn(executable, [], { stdio: ["pipe", "pipe", "ignore"] });
|
|
102
|
-
let buffer = "";
|
|
103
|
-
let sawResponse = false;
|
|
104
|
-
const fail = (error) => {
|
|
105
|
-
child.kill();
|
|
106
|
-
reject(error);
|
|
107
|
-
};
|
|
108
|
-
const timer = setTimeout(() => fail(new Error(`Helper did not shut down within ${timeoutMs}ms`)), timeoutMs);
|
|
109
|
-
child.stdout.setEncoding("utf8");
|
|
110
|
-
child.stdout.on("data", (chunk) => {
|
|
111
|
-
buffer += chunk;
|
|
112
|
-
let newline;
|
|
113
|
-
while ((newline = buffer.indexOf("\n")) >= 0) {
|
|
114
|
-
const line = buffer.slice(0, newline);
|
|
115
|
-
buffer = buffer.slice(newline + 1);
|
|
116
|
-
if (!line.trim()) continue;
|
|
117
|
-
let response;
|
|
118
|
-
try {
|
|
119
|
-
response = JSON.parse(line);
|
|
120
|
-
} catch {
|
|
121
|
-
continue;
|
|
122
|
-
}
|
|
123
|
-
if (response.id === "shutdown" && response.ok === true && response.result?.shuttingDown === true) sawResponse = true;
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
child.on("error", fail);
|
|
127
|
-
child.on("close", (code, signal) => {
|
|
128
|
-
clearTimeout(timer);
|
|
129
|
-
if (!sawResponse) {
|
|
130
|
-
reject(new Error("Helper did not acknowledge shutdown before exiting"));
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
if (code === 0) {
|
|
134
|
-
resolve();
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
reject(new Error(`Helper exited with ${code ?? "null"}${signal ? ` (signal ${signal})` : ""} instead of 0`));
|
|
138
|
-
});
|
|
139
|
-
child.stdin.write(`${JSON.stringify({ id: "shutdown", cmd: "shutdown" })}\n`);
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
function assert(condition, message) {
|
|
144
|
-
if (!condition) throw new Error(`[pie-computer-use] bridge integration assertion failed: ${message}`);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
async function runBridgeIntegration(helperPath) {
|
|
148
|
-
const responses = await helperResponses(helperPath, [
|
|
149
|
-
{ id: "diag", cmd: "diagnostics" },
|
|
150
|
-
{ id: "act-stale", cmd: "act", lookId: "look_999", pid: 123, action: "press", target: { ref: "e1" } },
|
|
151
|
-
{ id: "batch-stale", cmd: "actBatch", actions: [{ lookId: "look_999", pid: 123, action: "press", target: { ref: "e1" } }] },
|
|
152
|
-
{ id: "hit-stale", cmd: "hitTest", lookId: "look_999", x: 10, y: 10 },
|
|
153
|
-
{ id: "read-stale", cmd: "axReadText", elementRef: "e999999" },
|
|
154
|
-
{ id: "look-stale-base", cmd: "look", baseLookId: "look_999", windowId: 12345 },
|
|
155
|
-
]);
|
|
156
|
-
const diagnostics = responses.get("diag");
|
|
157
|
-
assert(diagnostics?.ok === true, "diagnostics must succeed");
|
|
158
|
-
assert(diagnostics.result?.protocolVersion === 6, "helper must keep protocol version 6");
|
|
159
|
-
assert(Array.isArray(diagnostics.result?.invariants) && diagnostics.result.invariants.includes("bounded-observation-history"), "helper must report the bounded-observation-history invariant");
|
|
160
|
-
for (const [id, expectedCode] of [
|
|
161
|
-
["act-stale", "stale_look"],
|
|
162
|
-
["batch-stale", "stale_look"],
|
|
163
|
-
["hit-stale", "stale_look"],
|
|
164
|
-
["read-stale", "element_ref_invalid"],
|
|
165
|
-
["look-stale-base", "stale_look"],
|
|
166
|
-
]) {
|
|
167
|
-
const response = responses.get(id);
|
|
168
|
-
assert(response?.ok === false, `${id} must fail`);
|
|
169
|
-
assert(response.error?.code === expectedCode, `${id} must fail with ${expectedCode}, got ${response.error?.code}`);
|
|
170
|
-
}
|
|
171
|
-
console.log("[pie-computer-use] bridge integration probes passed (stale look/ref failures, protocol v6).");
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
async function main() {
|
|
175
|
-
if (process.platform !== "darwin") {
|
|
176
|
-
console.log(`[pie-computer-use] skipping native retention tests: they are macOS-only and cannot run on ${process.platform}.`);
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
let tempDir;
|
|
180
|
-
try {
|
|
181
|
-
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "pie-computer-use-retention-"));
|
|
182
|
-
const moduleCache = path.join(tempDir, "module-cache");
|
|
183
|
-
const storeTestOutput = path.join(tempDir, "retention_tests");
|
|
184
|
-
console.log("[pie-computer-use] compiling native retention tests...");
|
|
185
|
-
await run("xcrun", swiftcArgs(storeTestSources, storeTestOutput, moduleCache, ["ApplicationServices", "CryptoKit"]));
|
|
186
|
-
console.log("[pie-computer-use] running native retention tests...");
|
|
187
|
-
await run(storeTestOutput, []);
|
|
188
|
-
|
|
189
|
-
const helperOutput = path.join(tempDir, "pie-computer-use");
|
|
190
|
-
console.log("[pie-computer-use] compiling native helper for bridge integration probes...");
|
|
191
|
-
await run("xcrun", swiftcArgs(helperSources, helperOutput, moduleCache, helperFrameworks));
|
|
192
|
-
await runBridgeIntegration(helperOutput);
|
|
193
|
-
await helperShutdownExits(helperOutput);
|
|
194
|
-
console.log("[pie-computer-use] helper shutdown exits cleanly with code 0.");
|
|
195
|
-
console.log("[pie-computer-use] native retention tests passed.");
|
|
196
|
-
} finally {
|
|
197
|
-
if (tempDir) await fs.rm(tempDir, { recursive: true, force: true }).catch(() => {});
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
main().catch((error) => {
|
|
202
|
-
console.error(error instanceof Error ? error.message : String(error));
|
|
203
|
-
process.exit(1);
|
|
204
|
-
});
|