pi-agent-browser-native 0.2.37 → 0.2.39
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 +22 -0
- package/README.md +19 -6
- package/docs/ARCHITECTURE.md +4 -4
- package/docs/COMMAND_REFERENCE.md +15 -12
- package/docs/RELEASE.md +21 -9
- package/docs/SUPPORT_MATRIX.md +10 -8
- package/docs/TOOL_CONTRACT.md +1 -1
- package/docs/platform-smoke.md +176 -0
- package/extensions/agent-browser/lib/playbook.ts +2 -2
- package/extensions/agent-browser/lib/process.ts +72 -13
- package/package.json +16 -4
- package/platform-smoke.config.mjs +18 -0
- package/scripts/agent-browser-capability-baseline.mjs +9 -6
- package/scripts/platform-smoke/artifacts.mjs +94 -0
- package/scripts/platform-smoke/browser-dogfood-windows.ps1 +110 -0
- package/scripts/platform-smoke/crabbox-runner.mjs +149 -0
- package/scripts/platform-smoke/doctor.mjs +307 -0
- package/scripts/platform-smoke/linux-image/Dockerfile +23 -0
- package/scripts/platform-smoke/platform-build-windows.ps1 +103 -0
- package/scripts/platform-smoke/targets.mjs +471 -0
- package/scripts/platform-smoke.mjs +161 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Purpose: Provide the Crabbox-backed platform smoke CLI for pi-agent-browser-native releases.
|
|
4
|
+
* Responsibilities: Load the project platform smoke config, validate target/suite names, run doctor, and fan out target suites.
|
|
5
|
+
* Scope: Maintainer release verification only; target command rendering and artifact assertions live under scripts/platform-smoke/.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { createRequire } from "node:module";
|
|
9
|
+
import { dirname, resolve } from "node:path";
|
|
10
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
11
|
+
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = dirname(__filename);
|
|
14
|
+
const repoRoot = resolve(__dirname, "..");
|
|
15
|
+
const require = createRequire(import.meta.url);
|
|
16
|
+
|
|
17
|
+
let config;
|
|
18
|
+
try {
|
|
19
|
+
config = require(resolve(repoRoot, "platform-smoke.config.mjs"));
|
|
20
|
+
if (config.default) config = config.default;
|
|
21
|
+
} catch {
|
|
22
|
+
config = null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function printHelp() {
|
|
26
|
+
console.log(`Usage: node scripts/platform-smoke.mjs <command> [options]
|
|
27
|
+
|
|
28
|
+
Commands:
|
|
29
|
+
doctor Validate Crabbox and platform prerequisites
|
|
30
|
+
run --target <names> Run one or more comma-separated targets concurrently
|
|
31
|
+
run --suite <name> Run one suite on all or specified targets
|
|
32
|
+
|
|
33
|
+
Package scripts:
|
|
34
|
+
check:platform-smoke Syntax-check harness scripts and run cheap harness invariant tests
|
|
35
|
+
smoke:platform:ubuntu-image Build the local Ubuntu image used by default
|
|
36
|
+
smoke:platform:all Runs doctor first, then the full macOS/Ubuntu/Windows matrix
|
|
37
|
+
|
|
38
|
+
Targets:
|
|
39
|
+
macos, ubuntu, windows-native
|
|
40
|
+
|
|
41
|
+
Suites:
|
|
42
|
+
platform-build npm ci, npm run verify -- platform-target, npm pack, packed pi install, pi list
|
|
43
|
+
browser-dogfood-smoke model-free native agent_browser smoke with real agent-browser/browser
|
|
44
|
+
|
|
45
|
+
Options:
|
|
46
|
+
--target <names> Comma-separated target names; defaults to configured required targets
|
|
47
|
+
--suite <name> Suite name; defaults to configured required suites
|
|
48
|
+
--help, -h Show this help
|
|
49
|
+
|
|
50
|
+
Examples:
|
|
51
|
+
npm run check:platform-smoke
|
|
52
|
+
npm run smoke:platform:doctor
|
|
53
|
+
npm run smoke:platform:all
|
|
54
|
+
node scripts/platform-smoke.mjs doctor
|
|
55
|
+
node scripts/platform-smoke.mjs run --target macos
|
|
56
|
+
node scripts/platform-smoke.mjs run --target ubuntu --suite platform-build
|
|
57
|
+
node scripts/platform-smoke.mjs run --target macos,ubuntu,windows-native
|
|
58
|
+
|
|
59
|
+
Environment:
|
|
60
|
+
PLATFORM_SMOKE_CRABBOX Optional Crabbox binary override; defaults to crabbox on PATH
|
|
61
|
+
PLATFORM_SMOKE_MAC_HOST macOS SSH host; default localhost
|
|
62
|
+
PLATFORM_SMOKE_MAC_USER macOS SSH user; default $USER
|
|
63
|
+
PLATFORM_SMOKE_MAC_WORK_ROOT macOS Crabbox work root
|
|
64
|
+
PLATFORM_SMOKE_UBUNTU_IMAGE Ubuntu local-container image; default pi-agent-browser-native-platform:node24-agent-browser0.27.1
|
|
65
|
+
PLATFORM_SMOKE_WINDOWS_VM Parallels Windows template VM
|
|
66
|
+
PLATFORM_SMOKE_WINDOWS_SNAPSHOT Parallels snapshot name
|
|
67
|
+
PLATFORM_SMOKE_WINDOWS_USER Windows SSH user
|
|
68
|
+
PLATFORM_SMOKE_WINDOWS_WORK_ROOT Windows work root, for example C:\\crabbox\\pi-agent-browser-native
|
|
69
|
+
PLATFORM_SMOKE_AUTH_ENV Optional comma-separated secret env names to redact/forward for future live suites
|
|
70
|
+
`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function parseArgs(argv = process.argv.slice(2)) {
|
|
74
|
+
const parsed = { command: null, target: null, suite: null };
|
|
75
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
76
|
+
const arg = argv[index];
|
|
77
|
+
if (arg === "--help" || arg === "-h") {
|
|
78
|
+
parsed.command = "help";
|
|
79
|
+
return parsed;
|
|
80
|
+
}
|
|
81
|
+
if (arg === "doctor" || arg === "run") {
|
|
82
|
+
if (parsed.command) throw new Error(`multiple commands provided: ${parsed.command}, ${arg}`);
|
|
83
|
+
parsed.command = arg;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (arg === "--target") {
|
|
87
|
+
const value = argv[index + 1];
|
|
88
|
+
if (!value || value.startsWith("-")) throw new Error("--target requires a value");
|
|
89
|
+
parsed.target = value;
|
|
90
|
+
index += 1;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
if (arg === "--suite") {
|
|
94
|
+
const value = argv[index + 1];
|
|
95
|
+
if (!value || value.startsWith("-")) throw new Error("--suite requires a value");
|
|
96
|
+
parsed.suite = value;
|
|
97
|
+
index += 1;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
throw new Error(`unknown argument: ${arg}`);
|
|
101
|
+
}
|
|
102
|
+
return parsed;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function validateNames(kind, names, allowed) {
|
|
106
|
+
const invalid = names.filter((name) => !allowed.includes(name));
|
|
107
|
+
if (invalid.length > 0) throw new Error(`unknown ${kind}: ${invalid.join(", ")}`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export async function main(argv = process.argv.slice(2)) {
|
|
111
|
+
const args = parseArgs(argv);
|
|
112
|
+
if (!args.command || args.command === "help") {
|
|
113
|
+
printHelp();
|
|
114
|
+
return args.command === "help" ? 0 : 2;
|
|
115
|
+
}
|
|
116
|
+
if (!config) throw new Error("platform-smoke.config.mjs not found or invalid");
|
|
117
|
+
|
|
118
|
+
if (args.command === "doctor") {
|
|
119
|
+
const { runDoctor } = await import("./platform-smoke/doctor.mjs");
|
|
120
|
+
await runDoctor(config);
|
|
121
|
+
return process.exitCode ?? 0;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (args.command === "run") {
|
|
125
|
+
const { runTargetSuite, runTargetSuites } = await import("./platform-smoke/targets.mjs");
|
|
126
|
+
const targets = args.target ? args.target.split(",").map((name) => name.trim()).filter(Boolean) : config.requiredTargets;
|
|
127
|
+
const suites = args.suite ? [args.suite] : config.requiredSuites;
|
|
128
|
+
const supportedTargets = config.supportedTargets ?? config.requiredTargets;
|
|
129
|
+
validateNames("target", targets, supportedTargets);
|
|
130
|
+
validateNames("suite", suites, config.requiredSuites);
|
|
131
|
+
const runs = targets.map(async (targetName) => {
|
|
132
|
+
console.log(`\n=== Target: ${targetName} ===`);
|
|
133
|
+
const result = args.suite
|
|
134
|
+
? await runTargetSuite(config, targetName, suites[0])
|
|
135
|
+
: await runTargetSuites(config, targetName, suites);
|
|
136
|
+
return { targetName, result };
|
|
137
|
+
});
|
|
138
|
+
const results = await Promise.all(runs);
|
|
139
|
+
const failed = results.filter(({ result }) => !result.ok);
|
|
140
|
+
if (failed.length > 0) {
|
|
141
|
+
console.error(`\nPlatform smoke failed for ${failed.map(({ targetName }) => targetName).join(", ")}. See ${config.artifactRoot}.`);
|
|
142
|
+
return 1;
|
|
143
|
+
}
|
|
144
|
+
console.log(`\nPlatform smoke passed for ${results.map(({ targetName }) => targetName).join(", ")}.`);
|
|
145
|
+
return 0;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
throw new Error(`unknown command: ${args.command}`);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
152
|
+
main().then(
|
|
153
|
+
(exitCode) => {
|
|
154
|
+
process.exitCode = exitCode;
|
|
155
|
+
},
|
|
156
|
+
(error) => {
|
|
157
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
158
|
+
process.exitCode = 1;
|
|
159
|
+
},
|
|
160
|
+
);
|
|
161
|
+
}
|