pi-agent-browser-native 0.8.0 → 0.8.2
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 +16 -0
- package/README.md +1 -1
- package/dist/extensions/agent-browser/index.js +14 -10
- package/dist/extensions/agent-browser/lib/tool-surface.js +15 -0
- package/docs/ARCHITECTURE.md +4 -0
- package/docs/COMMAND_REFERENCE.md +2 -0
- package/docs/SUPPORT_MATRIX.md +1 -1
- package/docs/TOOL_CONTRACT.md +3 -1
- package/docs/platform-smoke.md +3 -3
- package/package.json +1 -1
- package/platform-smoke.config.mjs +2 -1
- package/scripts/platform-smoke/doctor.mjs +3 -4
- package/scripts/platform-smoke/platform-build-windows.ps1 +3 -4
- package/scripts/platform-smoke/targets.mjs +10 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.8.2 - 2026-09-27
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Supply extension-owned browser discovery metadata on capable Pi hosts, including conditional web search, without a user-maintained settings inventory. Official Pi retains its ordinary entry tools and lazy advanced loader.
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Prepare complete deferred browser instructions for generic prompts so same-run discovery reveals them before the first browser action.
|
|
12
|
+
|
|
13
|
+
## 0.8.1 - 2026-09-26
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- Enforce the complete Node 24.21.0 minimum in platform qualification instead of accepting any Node 24 release.
|
|
18
|
+
|
|
3
19
|
## 0.8.0 - 2026-09-26
|
|
4
20
|
|
|
5
21
|
### Breaking Changes
|
package/README.md
CHANGED
|
@@ -45,7 +45,7 @@ The agent gets a native tool, not a bash workaround:
|
|
|
45
45
|
{ "args": ["find", "text", "Learn React", "click"] }
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
Use native commands for individual actions, `batch --bail` for fixed sequences, and `agent_browser_code` for loops or branches. Specialized tools are available through `agent_browser_tools`; see [common calls](#common-agent-calls).
|
|
48
|
+
Use native commands for individual actions, `batch --bail` for fixed sequences, and `agent_browser_code` for loops or branches. Specialized tools are available through `agent_browser_tools`; see [common calls](#common-agent-calls). On hosts supporting extension-owned discovery, enable the `browser` group through `discover_tools` first. The extension supplies its own membership and instructions; no user-maintained tool inventory is needed. Official Pi keeps the ordinary direct/code/loader surface.
|
|
49
49
|
|
|
50
50
|
The result is optimized for agent work:
|
|
51
51
|
|
|
@@ -34,7 +34,7 @@ import { buildValidationFailureResult, resolveAgentBrowserInput } from "./lib/or
|
|
|
34
34
|
import { applyAgentBrowserOutputPath, canWriteAgentBrowserOutput, normalizeRequestedOutputPath } from "./lib/orchestration/output-file.js";
|
|
35
35
|
import { appendScriptSessionLease, createBrowserCodeOutput, getScriptSessionLeasesFromBranch } from "./lib/orchestration/script-mode.js";
|
|
36
36
|
import { resolveBrowserExecutionIdentity, withBrowserExecutionLock, withBrowserExecutionLocks } from "./lib/managed-session-policy-lock.js";
|
|
37
|
-
import { registerAgentBrowserToolSurface } from "./lib/tool-surface.js";
|
|
37
|
+
import { AGENT_BROWSER_DISCOVERY_GROUP, registerAgentBrowserToolSurface } from "./lib/tool-surface.js";
|
|
38
38
|
import { formatSessionArtifactRetentionSummary, getSessionArtifactManifestEntryKey, isPendingRecordingCommand, isSessionArtifactManifest, mergeSessionArtifactManifest, retirePendingRecordingManifestEntries } from "./lib/results/artifact-manifest.js";
|
|
39
39
|
import { appendUniqueAgentBrowserNextActions, applyNamespaceToNextActions, applySessionToNextActions, buildNextToolAction } from "./lib/results/next-actions.js";
|
|
40
40
|
import { canRegisterWebSearchTool, loadAgentBrowserConfigSync } from "./lib/config.js";
|
|
@@ -1229,14 +1229,17 @@ export default function agentBrowserExtension(pi, { beforeExecute } = {}) {
|
|
|
1229
1229
|
const registerWebSearchToolIfAvailable = (configState) => {
|
|
1230
1230
|
if (webSearchToolRegistered || !canRegisterWebSearchTool(configState))
|
|
1231
1231
|
return;
|
|
1232
|
-
pi.registerTool(
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1232
|
+
pi.registerTool({
|
|
1233
|
+
...{ discovery: { group: AGENT_BROWSER_DISCOVERY_GROUP, role: "entry" } },
|
|
1234
|
+
...createAgentBrowserWebSearchTool(configState, {
|
|
1235
|
+
loadConfigState(ctx) {
|
|
1236
|
+
return loadAgentBrowserConfigSync({
|
|
1237
|
+
cwd: ctx.cwd,
|
|
1238
|
+
includeProjectConfig: shouldIncludeProjectConfig(ctx),
|
|
1239
|
+
});
|
|
1240
|
+
},
|
|
1241
|
+
}),
|
|
1242
|
+
});
|
|
1240
1243
|
webSearchToolRegistered = true;
|
|
1241
1244
|
};
|
|
1242
1245
|
pi.on("session_start", async (_event, ctx) => {
|
|
@@ -1400,7 +1403,8 @@ export default function agentBrowserExtension(pi, { beforeExecute } = {}) {
|
|
|
1400
1403
|
await cleanupSecureTempArtifacts({ preservePaths: preservedElectronProfileDirs });
|
|
1401
1404
|
});
|
|
1402
1405
|
pi.on("before_agent_start", async (event, ctx) => {
|
|
1403
|
-
|
|
1406
|
+
const sectionTools = event.systemPromptOptions?.sectionTools;
|
|
1407
|
+
if (!Object.hasOwn(sectionTools ?? {}, "agent_browser") && !shouldAppendBrowserSystemPrompt(event.prompt)) {
|
|
1404
1408
|
return undefined;
|
|
1405
1409
|
}
|
|
1406
1410
|
const runtimeConfig = loadAgentBrowserConfigSync({
|
|
@@ -9,10 +9,18 @@ export const AGENT_BROWSER_TOOL_INVENTORY = {
|
|
|
9
9
|
source: { name: "agent_browser_source", description: "Find experimental DOM/React/local-source candidates with a bounded workspace scan." },
|
|
10
10
|
network: { name: "agent_browser_network_source", description: "Correlate failed requests with initiator and local-source candidates." },
|
|
11
11
|
};
|
|
12
|
+
export const AGENT_BROWSER_DISCOVERY_GROUP = {
|
|
13
|
+
name: "browser",
|
|
14
|
+
description: "Search the web, browse and interact with pages, verify browser UI, and inspect Electron apps.",
|
|
15
|
+
sections: ["agent_browser"],
|
|
16
|
+
};
|
|
17
|
+
const entryDiscovery = { discovery: { group: AGENT_BROWSER_DISCOVERY_GROUP, role: "entry" } };
|
|
18
|
+
const advancedDiscovery = { discovery: { group: AGENT_BROWSER_DISCOVERY_GROUP, role: "advanced" } };
|
|
12
19
|
const advancedNames = new Set(Object.values(AGENT_BROWSER_TOOL_INVENTORY).map(({ name }) => name));
|
|
13
20
|
/** Register once; advanced calls adapt only their input shape and reuse the ordinary executor. */
|
|
14
21
|
export function registerAgentBrowserToolSurface(pi, options) {
|
|
15
22
|
pi.registerTool({
|
|
23
|
+
...entryDiscovery,
|
|
16
24
|
name: "agent_browser",
|
|
17
25
|
label: "Agent Browser",
|
|
18
26
|
description: "Browse and interact through native agent-browser commands. One command in args; fixed sequences use batch --bail and JSON-array stdin. Use agent_browser_code for loops/branches and agent_browser_tools for advanced capabilities.",
|
|
@@ -25,6 +33,7 @@ export function registerAgentBrowserToolSurface(pi, options) {
|
|
|
25
33
|
executionMode: options.executionMode,
|
|
26
34
|
});
|
|
27
35
|
pi.registerTool({
|
|
36
|
+
...entryDiscovery,
|
|
28
37
|
name: "agent_browser_code",
|
|
29
38
|
label: "Agent Browser Code",
|
|
30
39
|
description: "Run fresh JavaScript against a persistent browser. await browser({args,stdin?,timeoutMs?}) returns success/data/error/nextActions and imageObservations; emit(selected JSON) and emitImage(image handle) explicitly choose output. No host APIs or imports. Use native batch for fixed sequences.",
|
|
@@ -40,6 +49,7 @@ export function registerAgentBrowserToolSurface(pi, options) {
|
|
|
40
49
|
renderResult: options.renderResult,
|
|
41
50
|
});
|
|
42
51
|
pi.registerTool({
|
|
52
|
+
...advancedDiscovery,
|
|
43
53
|
...AGENT_BROWSER_TOOL_INVENTORY.action,
|
|
44
54
|
label: "Browser Action",
|
|
45
55
|
promptGuidelines: [...ADVANCED_TOOL_PROMPT_GUIDELINES.action],
|
|
@@ -51,6 +61,7 @@ export function registerAgentBrowserToolSurface(pi, options) {
|
|
|
51
61
|
},
|
|
52
62
|
});
|
|
53
63
|
pi.registerTool({
|
|
64
|
+
...advancedDiscovery,
|
|
54
65
|
...AGENT_BROWSER_TOOL_INVENTORY.qa,
|
|
55
66
|
label: "Browser QA",
|
|
56
67
|
promptGuidelines: [...ADVANCED_TOOL_PROMPT_GUIDELINES.qa],
|
|
@@ -62,6 +73,7 @@ export function registerAgentBrowserToolSurface(pi, options) {
|
|
|
62
73
|
},
|
|
63
74
|
});
|
|
64
75
|
pi.registerTool({
|
|
76
|
+
...advancedDiscovery,
|
|
65
77
|
...AGENT_BROWSER_TOOL_INVENTORY.electron,
|
|
66
78
|
label: "Browser Electron",
|
|
67
79
|
promptGuidelines: [...ADVANCED_TOOL_PROMPT_GUIDELINES.electron],
|
|
@@ -73,6 +85,7 @@ export function registerAgentBrowserToolSurface(pi, options) {
|
|
|
73
85
|
},
|
|
74
86
|
});
|
|
75
87
|
pi.registerTool({
|
|
88
|
+
...advancedDiscovery,
|
|
76
89
|
...AGENT_BROWSER_TOOL_INVENTORY.source,
|
|
77
90
|
label: "Browser Source",
|
|
78
91
|
promptGuidelines: [...ADVANCED_TOOL_PROMPT_GUIDELINES.source],
|
|
@@ -84,6 +97,7 @@ export function registerAgentBrowserToolSurface(pi, options) {
|
|
|
84
97
|
},
|
|
85
98
|
});
|
|
86
99
|
pi.registerTool({
|
|
100
|
+
...advancedDiscovery,
|
|
87
101
|
...AGENT_BROWSER_TOOL_INVENTORY.network,
|
|
88
102
|
label: "Browser Network Source",
|
|
89
103
|
promptGuidelines: [...ADVANCED_TOOL_PROMPT_GUIDELINES.network],
|
|
@@ -95,6 +109,7 @@ export function registerAgentBrowserToolSurface(pi, options) {
|
|
|
95
109
|
},
|
|
96
110
|
});
|
|
97
111
|
pi.registerTool({
|
|
112
|
+
...entryDiscovery,
|
|
98
113
|
name: "agent_browser_tools",
|
|
99
114
|
label: "Browser Tools",
|
|
100
115
|
description: "List or enable advanced browser tools: action → agent_browser_action; qa → agent_browser_qa; electron → agent_browser_electron; source → agent_browser_source; network → agent_browser_network_source. Omit enable for inventory. Activation only adds tools; it preserves other active tools.",
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -23,6 +23,10 @@ The package install path is the primary product path. Local checkout development
|
|
|
23
23
|
|
|
24
24
|
Optional `agent_browser_web_search` remains separately credential/config gated and independent of browser state.
|
|
25
25
|
|
|
26
|
+
Registration-owned `discovery` metadata uses one `AGENT_BROWSER_DISCOVERY_GROUP` descriptor in `lib/tool-surface.ts` (`browser`, section `agent_browser`). Direct, code, loader, and conditional/late web search registrations are entry tools; the existing five specialized registrations are advanced tools. Capable hosts derive membership from the permitted registry, without another name catalog or user configuration. Official Pi ignores the metadata. The advanced loader and native selected-tool history remain unchanged.
|
|
27
|
+
|
|
28
|
+
`before_agent_start` prepares the complete browser section when `systemPromptOptions.sectionTools` has its own `agent_browser` key, including generic prompts. An empty map, another extension's key, or an inherited key does not trigger it. Without that ownership, the existing keyword gate applies. The host retains hidden section text and reveals it during same-run discovery; the extension never reruns the hook or replaces an opaque full system prompt. Project guidance and all execution guards retain their existing paths.
|
|
29
|
+
|
|
26
30
|
### Direct subprocess execution
|
|
27
31
|
|
|
28
32
|
The extension should:
|
|
@@ -230,6 +230,8 @@ Call `agent_browser_tools {}` for inventory, then enable required capabilities:
|
|
|
230
230
|
{ "enable": ["action", "qa", "electron", "source", "network"] }
|
|
231
231
|
```
|
|
232
232
|
|
|
233
|
+
On hosts supporting extension-owned discovery, first enable the `browser` group with `discover_tools`; its entry surface includes direct commands, code, this advanced loader, and web search when configured. The group is defined by registrations, not a user-maintained inventory. Official Pi exposes the ordinary entry tools without this host-level discovery step.
|
|
234
|
+
|
|
233
235
|
Activation is additive and uses native Pi selected-tool history. Omit CLI `--tools` for normal lazy activation, or include desired advanced tools in that explicit selection; excluded tools remain unavailable. The tools take flat input:
|
|
234
236
|
|
|
235
237
|
| Tool | Example |
|
package/docs/SUPPORT_MATRIX.md
CHANGED
|
@@ -40,7 +40,7 @@ The compact direct/code/loader surface replaces public multimode inputs while re
|
|
|
40
40
|
| RQ-0142 code | Fresh permissioned Node child over persistent parent-selected browser; explicit JSON/current-cell image output, visible failures/counts, ordinary auth/config/environment, ordered Pi intent/completion transitions, child cancellation/reaping, no legacy public execution. |
|
|
41
41
|
| Shared ordering | Actual socket/namespace/session lock spans helper/action or entire cell; sorted identity sets for replacement/cleanup and namespace barrier for direct close-all. Requires every participating Pi to run the updated package; no human/third-party/older-version guarantee or transaction. |
|
|
42
42
|
| Observation and geometry | Canonical bounded JSON/prose/code observations expose exact recovery and receipts; complete observation spills preserve large output. Image dimensions/CSS viewport/DPR/crop/scroll/frame evidence is measured or explicitly unknown; no viewport-coordinate assumptions for full-page/element images. |
|
|
43
|
-
| Pi integration | Native additive activation/history and prompt sections on independently qualified official Pi 0.87 and fork;
|
|
43
|
+
| Pi integration | Native additive activation/history and prompt sections on independently qualified official Pi 0.87 and fork; registration-owned `browser` discovery metadata on capable hosts, ordinary exposure on official hosts. Generic prompts prepare the deferred browser section before same-run activation; `test/agent-browser.discovery.test.ts` covers own-key gating and startup/late registration, with pipeline coverage in `test/agent-browser.pi-pipeline.test.ts`. Optional checkpoint hooks, no provider payload/image-detail overrides. |
|
|
44
44
|
|
|
45
45
|
See [migration](TOOL_CONTRACT.md#07-migration), [canonical observations](TOOL_CONTRACT.md#canonical-observation), and [release qualification/rollback](RELEASE.md#07-upgrade-and-rollback). Routine GitHub Actions runs official/fork Linux compatibility, a macOS packed-Pi smoke, and native Linux checkpoints on PRs to `main`; Windows CI is excluded. Release/platform evidence and review remain separate from these focused checks.
|
|
46
46
|
|
package/docs/TOOL_CONTRACT.md
CHANGED
|
@@ -10,7 +10,9 @@ Related docs:
|
|
|
10
10
|
|
|
11
11
|
## Browser tools
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Entry tools are `agent_browser` (native argv), `agent_browser_code` (fresh JavaScript over a persistent browser), and `agent_browser_tools` (advanced capability discovery/activation). Optional credential-backed `agent_browser_web_search` remains independent of browser state and joins the entry surface only when registered.
|
|
14
|
+
|
|
15
|
+
On hosts supporting extension-owned discovery, these registrations belong to the `browser` group: `discover_tools` enables the entry tools, and `agent_browser_tools` still enables the five advanced tools below. Tool selection, exclusions, and restored activation remain host-owned. No user-maintained group inventory is required. Discovery metadata is host-only, not a tool parameter or provider request field. Official Pi ignores the optional metadata and retains ordinary entry-tool exposure. The extension prepares its complete `agent_browser` prompt section even for a generic user prompt when the host identifies that section as deferred; the host reveals it on activation in the same run, before browser execution. Hosts without that section ownership retain keyword-triggered prompt guidance.
|
|
14
16
|
|
|
15
17
|
Pi 0.87.0 or newer is required; official and fork qualification is independent. Five specialized tools are registered but initially inactive: `agent_browser_action`, `agent_browser_qa`, `agent_browser_electron`, `agent_browser_source`, and `agent_browser_network_source`. Explicit CLI allowlists, filtered SDK catalogs, and restored Pi tool history are respected. Omit CLI `--tools` for lazy activation, or include every desired advanced tool in its allowlist; the loader reports excluded tools as unavailable rather than bypassing host selection. Pi 0.87 does not distinguish an SDK explicitly selecting the complete browser catalog from its default catalog; SDK hosts choosing activation for that complete catalog can call `session.setActiveToolsByName(...)` after `bindExtensions()`.
|
|
16
18
|
|
package/docs/platform-smoke.md
CHANGED
|
@@ -42,7 +42,7 @@ npm run verify -- platform-smoke run --target ubuntu --suite platform-build
|
|
|
42
42
|
|
|
43
43
|
With maintainer approval, local macOS execution can replace localhost SSH. Routine GitHub Actions has no Windows job; the separate Crabbox/Parallels release target remains as documented above. Record alternate native checks separately from Crabbox SSH or Parallels results. The default `release` and `prepublishOnly` commands still select the Crabbox matrix; record alternate suite evidence separately rather than reporting those commands as passed.
|
|
44
44
|
|
|
45
|
-
On macOS, run the unchanged commands returned by `buildPlatformBuildCommand('macos', 'pi-agent-browser-native', 24)` and `buildBrowserDogfoodCommand('macos', '0.38.1', true)` in [`scripts/platform-smoke/targets.mjs`](../scripts/platform-smoke/targets.mjs), serially in a clean private source copy. Use private HOME, npm and Pi settings, and headless browser profiles. No Remote Login or host security change is required.
|
|
45
|
+
On macOS, run the unchanged commands returned by `buildPlatformBuildCommand('macos', 'pi-agent-browser-native', '24.21.0')` and `buildBrowserDogfoodCommand('macos', '0.38.1', true)` in [`scripts/platform-smoke/targets.mjs`](../scripts/platform-smoke/targets.mjs), serially in a clean private source copy. Use private HOME, npm and Pi settings, and headless browser profiles. No Remote Login or host security change is required.
|
|
46
46
|
|
|
47
47
|
Retain the exact source head/tree, package and tool versions, native OS/architecture, generated commands, stdout/stderr, every `PLATFORM_*` exit marker, actual Pi registration output, dogfood JSON and verified screenshot. Check the suite assertions below and clean up only the run's processes and temporary files. These alternatives do not waive Ubuntu or any non-platform release check.
|
|
48
48
|
|
|
@@ -88,7 +88,7 @@ The configured upstream `agent-browser` baseline is imported from [`scripts/agen
|
|
|
88
88
|
|
|
89
89
|
Crabbox does not install project runtime tools. The macOS host, Ubuntu image, and Windows template must already provide:
|
|
90
90
|
|
|
91
|
-
- Node/npm at or above the
|
|
91
|
+
- Node/npm at or above the full Node version declared by `package.json` `engines.node` and used by [`platform-smoke.config.mjs`](../platform-smoke.config.mjs).
|
|
92
92
|
- Git and `tar`.
|
|
93
93
|
- Upstream `agent-browser` matching this wrapper’s capability baseline. The Ubuntu target gets it from [`scripts/platform-smoke/linux-image/Dockerfile`](../scripts/platform-smoke/linux-image/Dockerfile); the Windows template gets it from the shared `pi-extension-windows-template` snapshot named in [`platform-smoke.config.mjs`](../platform-smoke.config.mjs) (currently `crabbox-ready-ab-0.33.0`, a child of the shared `crabbox-ready` base used by other projects' linked clones).
|
|
94
94
|
- Browser/runtime dependencies needed by upstream `agent-browser`.
|
|
@@ -102,7 +102,7 @@ Each required target runs `platform-build` and `browser-dogfood-smoke` on one Cr
|
|
|
102
102
|
|
|
103
103
|
### `platform-build`
|
|
104
104
|
|
|
105
|
-
1. Verify the target Node
|
|
105
|
+
1. Verify the target's full Node version.
|
|
106
106
|
2. Run `npm ci` in the synced checkout.
|
|
107
107
|
3. Run `npm run verify -- platform-target`, a fast target-local gate covering generated docs, TypeScript, package/platform harness tests, and runtime planning. The full unit/fake suite still runs once in the host default gate before the release matrix starts; target-local smoke must not duplicate that full suite on every OS. Browser subprocess behavior is then exercised by the target-local `browser-dogfood-smoke` suite against the real upstream binary.
|
|
108
108
|
4. Run `npm pack`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Platform smoke configuration for pi-agent-browser-native.
|
|
2
2
|
// Crabbox owns the target lease/sync loop; this file is the project source of truth for release-blocking platform coverage.
|
|
3
3
|
|
|
4
|
+
import packageJson from "./package.json" with { type: "json" };
|
|
4
5
|
import { CAPABILITY_BASELINE } from "./scripts/agent-browser-capability-baseline.mjs";
|
|
5
6
|
|
|
6
7
|
const PLATFORM_SMOKE_AGENT_BROWSER_VERSION = CAPABILITY_BASELINE.targetVersion;
|
|
@@ -26,6 +27,6 @@ export default {
|
|
|
26
27
|
// Parent crabbox-ready remains for other projects' linked clones.
|
|
27
28
|
snapshot: "crabbox-ready-ab-0.34.0-d",
|
|
28
29
|
},
|
|
29
|
-
|
|
30
|
+
nodeValidationVersion: packageJson.engines.node.replace(/^>=/, ""),
|
|
30
31
|
agentBrowserVersion: PLATFORM_SMOKE_AGENT_BROWSER_VERSION,
|
|
31
32
|
};
|
|
@@ -234,7 +234,7 @@ export async function runDoctor(config) {
|
|
|
234
234
|
const failures = { count: 0 };
|
|
235
235
|
const packageName = config?.packageName ?? "pi-agent-browser-native";
|
|
236
236
|
const artifactRoot = config?.artifactRoot ?? ".artifacts/platform-smoke";
|
|
237
|
-
const
|
|
237
|
+
const nodeVersion = config?.nodeValidationVersion;
|
|
238
238
|
const agentBrowserVersion = config?.agentBrowserVersion;
|
|
239
239
|
|
|
240
240
|
console.log("\n── Platform smoke config ──");
|
|
@@ -280,9 +280,8 @@ export async function runDoctor(config) {
|
|
|
280
280
|
else ok(`${name}: ${output.split(/\r?\n/)[0]}`);
|
|
281
281
|
}
|
|
282
282
|
const localNode = shell("node --version");
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
else fail(`host Node major ${localNodeMajor || "unknown"} < ${nodeMajor}`, failures);
|
|
283
|
+
if (nodeVersion && localNode && versionAtLeast(localNode, nodeVersion)) ok(`host Node ${localNode} >= ${nodeVersion}`);
|
|
284
|
+
else fail(`host Node ${localNode || "unknown"} < ${nodeVersion ?? "configured minimum"}`, failures);
|
|
286
285
|
checkAgentBrowserVersion(agentBrowserVersion, failures);
|
|
287
286
|
|
|
288
287
|
console.log("\n── Crabbox providers ──");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
param(
|
|
2
2
|
[Parameter(Mandatory=$true)][string]$PackageName,
|
|
3
|
-
[Parameter(Mandatory=$true)][
|
|
3
|
+
[Parameter(Mandatory=$true)][string]$NodeValidationVersion
|
|
4
4
|
)
|
|
5
5
|
|
|
6
6
|
$ErrorActionPreference = "Continue"
|
|
@@ -20,10 +20,9 @@ Write-Output "Starting platform-build in $SourceRoot at $((Get-Date).ToUniversal
|
|
|
20
20
|
Write-Output "PLATFORM_RUN_ROOT=$RunRoot"
|
|
21
21
|
|
|
22
22
|
$NodeVersion = (& node --version 2>$null)
|
|
23
|
-
$NodeMajor = 0
|
|
24
|
-
if ($NodeVersion -match '^v?(\d+)\.') { $NodeMajor = [int]$Matches[1] }
|
|
25
23
|
Write-Output "PLATFORM_NODE_VERSION=$NodeVersion"
|
|
26
|
-
$NodeVersionExit =
|
|
24
|
+
$NodeVersionExit = 1
|
|
25
|
+
try { if ([version]$NodeVersion.TrimStart("v") -ge [version]$NodeValidationVersion) { $NodeVersionExit = 0 } } catch {}
|
|
27
26
|
Write-Output "PLATFORM_NODE_VERSION_EXIT=$NodeVersionExit"
|
|
28
27
|
|
|
29
28
|
& npm ci 2>&1
|
|
@@ -254,9 +254,13 @@ export function createLeaseWarmupFailureResult(config, targetName, warmupResult,
|
|
|
254
254
|
return { ok: false, suiteDir, assertions };
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
-
export function
|
|
257
|
+
export function nodeVersionAtLeast(actual, minimum) {
|
|
258
|
+
return /^v?\d+\.\d+\.\d+$/.test(actual) && actual.replace(/^v/, "").localeCompare(minimum, undefined, { numeric: true }) >= 0;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export function buildPlatformBuildCommand(targetName, packageName, nodeValidationVersion) {
|
|
258
262
|
if (platformFor(targetName) === "powershell") {
|
|
259
|
-
return `powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -File .\\scripts\\platform-smoke\\platform-build-windows.ps1 -PackageName ${psSingleQuote(packageName)} -
|
|
263
|
+
return `powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -File .\\scripts\\platform-smoke\\platform-build-windows.ps1 -PackageName ${psSingleQuote(packageName)} -NodeValidationVersion ${psSingleQuote(nodeValidationVersion)}`;
|
|
260
264
|
}
|
|
261
265
|
|
|
262
266
|
const lines = [];
|
|
@@ -268,10 +272,8 @@ export function buildPlatformBuildCommand(targetName, packageName = "pi-agent-br
|
|
|
268
272
|
lines.push(`mkdir -p "$PACK_DIR" "$PI_PROJECT"`);
|
|
269
273
|
lines.push(`echo "PLATFORM_RUN_ROOT=$RUN_ROOT"`);
|
|
270
274
|
lines.push(`NODE_VERSION=$(node --version)`);
|
|
271
|
-
lines.push(`NODE_MAJOR="${"${NODE_VERSION#v}"}"`);
|
|
272
|
-
lines.push(`NODE_MAJOR="${"${NODE_MAJOR%%.*}"}"`);
|
|
273
275
|
lines.push(`echo "PLATFORM_NODE_VERSION=$NODE_VERSION"`);
|
|
274
|
-
lines.push(`if [
|
|
276
|
+
lines.push(`if node -e 'process.exit(process.versions.node.localeCompare(process.argv[1], undefined, { numeric: true }) < 0 ? 1 : 0)' ${shellQuote(nodeValidationVersion)}; then NODE_VERSION_EXIT=0; else NODE_VERSION_EXIT=1; fi`);
|
|
275
277
|
lines.push(`echo "PLATFORM_NODE_VERSION_EXIT=$NODE_VERSION_EXIT"`);
|
|
276
278
|
lines.push(`npm ci 2>&1`);
|
|
277
279
|
lines.push(`NPM_CI_EXIT=$?`);
|
|
@@ -418,7 +420,7 @@ async function runPlatformBuildSuite(config, targetName, suiteName, leaseSession
|
|
|
418
420
|
const startedAt = Date.now();
|
|
419
421
|
const platform = platformFor(targetName);
|
|
420
422
|
const slug = `${config.packageName}-${targetName}`;
|
|
421
|
-
const command = buildPlatformBuildCommand(targetName, config.packageName, config.
|
|
423
|
+
const command = buildPlatformBuildCommand(targetName, config.packageName, config.nodeValidationVersion);
|
|
422
424
|
mkdirSync(dirname(suiteDir), { recursive: true });
|
|
423
425
|
writeFileSync(resolve(suiteDir, "target.json"), JSON.stringify(targetEvidence(config, targetName, runId, slug), null, 2));
|
|
424
426
|
writeFileSync(resolve(suiteDir, "suite.json"), JSON.stringify({ suiteName, modelCalls: 0 }, null, 2));
|
|
@@ -453,7 +455,7 @@ async function runPlatformBuildSuite(config, targetName, suiteName, leaseSession
|
|
|
453
455
|
|
|
454
456
|
const stdout = result.stdout;
|
|
455
457
|
const listOutput = section(stdout, "PI_LIST_STDOUT");
|
|
456
|
-
const
|
|
458
|
+
const nodeVersion = marker(stdout, "PLATFORM_NODE_VERSION");
|
|
457
459
|
const secretViolations = [
|
|
458
460
|
...scanForSecrets(`${result.stdout}\n${result.stderr}`, secretValues),
|
|
459
461
|
...scanArtifactTextFiles(suiteDir, secretValues).map((finding) => `${finding.file}: ${finding.violation}`),
|
|
@@ -461,7 +463,7 @@ async function runPlatformBuildSuite(config, targetName, suiteName, leaseSession
|
|
|
461
463
|
const checks = [
|
|
462
464
|
{ id: "command-exit-zero", fn: () => result.code === 0, error: `exit ${result.code}` },
|
|
463
465
|
{ id: "platform-marker", fn: () => stdout.includes("PLATFORM_BUILD_OK") },
|
|
464
|
-
{ id: "node-version", fn: () =>
|
|
466
|
+
{ id: "node-version", fn: () => nodeVersionAtLeast(nodeVersion, config.nodeValidationVersion), error: `Node ${nodeVersion || "unknown"} < ${config.nodeValidationVersion}` },
|
|
465
467
|
{ id: "npm-ci", fn: () => /PLATFORM_NPM_CI_EXIT=0/.test(stdout) },
|
|
466
468
|
{ id: "npm-run-verify", fn: () => /PLATFORM_VERIFY_EXIT=0/.test(stdout) },
|
|
467
469
|
{ id: "npm-pack", fn: () => /PLATFORM_NPM_PACK_EXIT=0/.test(stdout) && marker(stdout, "PLATFORM_PACKED_TARBALL").length > 0 },
|