pi-agent-browser-native 0.2.42 → 0.2.44

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.
Files changed (39) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +14 -9
  3. package/docs/COMMAND_REFERENCE.md +9 -10
  4. package/docs/RELEASE.md +10 -4
  5. package/docs/SUPPORT_MATRIX.md +7 -6
  6. package/docs/TOOL_CONTRACT.md +27 -24
  7. package/docs/platform-smoke.md +13 -8
  8. package/extensions/agent-browser/index.ts +71 -2
  9. package/extensions/agent-browser/lib/input-modes/params.ts +1 -1
  10. package/extensions/agent-browser/lib/input-modes/types.ts +1 -1
  11. package/extensions/agent-browser/lib/navigation-policy.ts +95 -0
  12. package/extensions/agent-browser/lib/orchestration/browser-run/diagnostics.ts +2 -7
  13. package/extensions/agent-browser/lib/orchestration/browser-run/final-result.ts +1 -0
  14. package/extensions/agent-browser/lib/orchestration/browser-run/prepare.ts +2 -2
  15. package/extensions/agent-browser/lib/orchestration/browser-run/process-output.ts +103 -12
  16. package/extensions/agent-browser/lib/orchestration/browser-run/session-state.ts +20 -3
  17. package/extensions/agent-browser/lib/orchestration/browser-run/types.ts +6 -1
  18. package/extensions/agent-browser/lib/playbook.ts +4 -4
  19. package/extensions/agent-browser/lib/results/action-recommendations.ts +15 -0
  20. package/extensions/agent-browser/lib/results/contracts.ts +17 -0
  21. package/extensions/agent-browser/lib/results/network-routes.ts +80 -0
  22. package/extensions/agent-browser/lib/results/network.ts +10 -2
  23. package/extensions/agent-browser/lib/results/presentation/artifacts.ts +14 -0
  24. package/extensions/agent-browser/lib/results/presentation/batch.ts +36 -13
  25. package/extensions/agent-browser/lib/results/presentation/diagnostics.ts +154 -16
  26. package/extensions/agent-browser/lib/results/presentation/errors.ts +62 -2
  27. package/extensions/agent-browser/lib/results/presentation/semantic-action.ts +2 -4
  28. package/extensions/agent-browser/lib/results/presentation.ts +31 -1
  29. package/extensions/agent-browser/lib/results/selector-recovery.ts +11 -3
  30. package/extensions/agent-browser/lib/results/shared.ts +1 -0
  31. package/extensions/agent-browser/lib/results.ts +3 -0
  32. package/extensions/agent-browser/lib/runtime.ts +6 -0
  33. package/package.json +4 -4
  34. package/platform-smoke.config.mjs +10 -1
  35. package/scripts/doctor.mjs +70 -1
  36. package/scripts/platform-smoke/crabbox-runner.mjs +57 -29
  37. package/scripts/platform-smoke/doctor.mjs +22 -9
  38. package/scripts/platform-smoke/targets.mjs +58 -21
  39. package/scripts/platform-smoke.mjs +1 -0
@@ -1,5 +1,6 @@
1
1
  /** Target/suite runner for pi-agent-browser-native platform smoke. */
2
2
 
3
+ import { execFileSync } from "node:child_process";
3
4
  import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
4
5
  import { dirname, resolve } from "node:path";
5
6
 
@@ -14,7 +15,7 @@ import {
14
15
  writeManifest,
15
16
  writeSummary,
16
17
  } from "./artifacts.mjs";
17
- import { cleanupStaleTargetState, runOnLease, stopLease, warmupLease } from "./crabbox-runner.mjs";
18
+ import { cleanupStaleTargetState, crabboxBin, describeTarget, runOnLease, stopLease, warmupLease } from "./crabbox-runner.mjs";
18
19
 
19
20
  export function platformFor(targetName) {
20
21
  return targetName === "windows-native" ? "powershell" : "posix";
@@ -38,6 +39,45 @@ function authEnvAllowList(config = {}) {
38
39
  return names.map((name) => String(name).trim()).filter(Boolean);
39
40
  }
40
41
 
42
+ function packageVersion() {
43
+ try {
44
+ return JSON.parse(readFileSync("package.json", "utf8")).version ?? null;
45
+ } catch {
46
+ return null;
47
+ }
48
+ }
49
+
50
+ function crabboxVersion() {
51
+ try {
52
+ return execFileSync(crabboxBin(), ["--version"], { encoding: "utf8", stdio: "pipe", timeout: 10_000 }).trim().split(/\r?\n/)[0] ?? null;
53
+ } catch {
54
+ return null;
55
+ }
56
+ }
57
+
58
+ function targetEvidence(config, targetName, runId, slug) {
59
+ const target = describeTarget(targetName, config);
60
+ return {
61
+ targetName,
62
+ platform: platformFor(targetName),
63
+ runId,
64
+ slug,
65
+ packageName: config.packageName,
66
+ packageVersion: packageVersion(),
67
+ crabbox: {
68
+ binary: crabboxBin(),
69
+ version: crabboxVersion(),
70
+ provider: target.provider,
71
+ target: target.crabboxTarget,
72
+ workRoot: target.workRoot,
73
+ image: target.image,
74
+ windowsMode: target.windowsMode,
75
+ sourceVm: target.sourceVm,
76
+ snapshot: target.snapshot,
77
+ },
78
+ };
79
+ }
80
+
41
81
  function writeRedacted(path, text, secretValues) {
42
82
  writeFileSync(path, redactSecrets(text ?? "", secretValues));
43
83
  }
@@ -141,12 +181,11 @@ function finalizeSuite(suiteDir, checks, summary, expectedFiles) {
141
181
  return { assertions: finalAssertions, manifest: writeManifest(suiteDir, [...expectedFiles, "failures.md"]) };
142
182
  }
143
183
 
144
- export function createLeaseCleanupResult(config, targetName, leaseId, stopResult, staleCleanupResult = null) {
184
+ export function createLeaseCleanupResult(config, targetName, leaseId, stopResult, staleCleanupResult = null, runId = makeRunId()) {
145
185
  const suiteName = "lease-cleanup";
146
- const runId = makeRunId();
147
186
  const suiteDir = createSuiteDir(config.artifactRoot, runId, targetName, suiteName);
148
187
  const secretValues = collectSecretValues(authEnvAllowList(config));
149
- writeFileSync(resolve(suiteDir, "target.json"), JSON.stringify({ targetName, platform: platformFor(targetName), runId, slug: `${config.packageName}-${targetName}` }, null, 2));
188
+ writeFileSync(resolve(suiteDir, "target.json"), JSON.stringify(targetEvidence(config, targetName, runId, `${config.packageName}-${targetName}`), null, 2));
150
189
  writeFileSync(resolve(suiteDir, "suite.json"), JSON.stringify({ suiteName, leaseId, modelCalls: 0 }, null, 2));
151
190
  writeCommand(suiteDir, `crabbox stop ${targetName} --id ${leaseId}`);
152
191
  writeExitCode(suiteDir, stopResult.code, stopResult.signal);
@@ -180,16 +219,15 @@ export function createLeaseCleanupResult(config, targetName, leaseId, stopResult
180
219
  return { ok: assertions.ok, suiteDir, assertions };
181
220
  }
182
221
 
183
- export function createLeaseCleanupFailureResult(config, targetName, leaseId, stopResult) {
184
- return createLeaseCleanupResult(config, targetName, leaseId, stopResult);
222
+ export function createLeaseCleanupFailureResult(config, targetName, leaseId, stopResult, runId) {
223
+ return createLeaseCleanupResult(config, targetName, leaseId, stopResult, null, runId);
185
224
  }
186
225
 
187
- export function createLeaseWarmupFailureResult(config, targetName, warmupResult) {
226
+ export function createLeaseWarmupFailureResult(config, targetName, warmupResult, runId = makeRunId()) {
188
227
  const suiteName = "lease-warmup";
189
- const runId = makeRunId();
190
228
  const suiteDir = createSuiteDir(config.artifactRoot, runId, targetName, suiteName);
191
229
  const secretValues = collectSecretValues(authEnvAllowList(config));
192
- writeFileSync(resolve(suiteDir, "target.json"), JSON.stringify({ targetName, platform: platformFor(targetName), runId, slug: `${config.packageName}-${targetName}` }, null, 2));
230
+ writeFileSync(resolve(suiteDir, "target.json"), JSON.stringify(targetEvidence(config, targetName, runId, `${config.packageName}-${targetName}`), null, 2));
193
231
  writeFileSync(resolve(suiteDir, "suite.json"), JSON.stringify({ suiteName, modelCalls: 0 }, null, 2));
194
232
  writeCommand(suiteDir, `crabbox warmup ${targetName}`);
195
233
  writeExitCode(suiteDir, warmupResult.code, warmupResult.signal);
@@ -301,14 +339,13 @@ export function buildBrowserDogfoodCommand(targetName, agentBrowserVersion = "0.
301
339
  return lines.join("\n");
302
340
  }
303
341
 
304
- async function runBrowserDogfoodSuite(config, targetName, suiteName, leaseSession) {
305
- const runId = makeRunId();
342
+ async function runBrowserDogfoodSuite(config, targetName, suiteName, leaseSession, runId = makeRunId()) {
306
343
  const suiteDir = createSuiteDir(config.artifactRoot, runId, targetName, suiteName);
307
344
  const startedAt = Date.now();
308
345
  const platform = platformFor(targetName);
309
346
  const slug = `${config.packageName}-${targetName}`;
310
347
  const command = buildBrowserDogfoodCommand(targetName, config.agentBrowserVersion);
311
- writeFileSync(resolve(suiteDir, "target.json"), JSON.stringify({ targetName, platform, runId, slug }, null, 2));
348
+ writeFileSync(resolve(suiteDir, "target.json"), JSON.stringify(targetEvidence(config, targetName, runId, slug), null, 2));
312
349
  writeFileSync(resolve(suiteDir, "suite.json"), JSON.stringify({ suiteName, modelCalls: 0, realBrowser: true }, null, 2));
313
350
  writeCommand(suiteDir, command);
314
351
 
@@ -367,15 +404,14 @@ async function runBrowserDogfoodSuite(config, targetName, suiteName, leaseSessio
367
404
  return { ok: assertions.ok, suiteDir, assertions };
368
405
  }
369
406
 
370
- async function runPlatformBuildSuite(config, targetName, suiteName, leaseSession) {
371
- const runId = makeRunId();
407
+ async function runPlatformBuildSuite(config, targetName, suiteName, leaseSession, runId = makeRunId()) {
372
408
  const suiteDir = createSuiteDir(config.artifactRoot, runId, targetName, suiteName);
373
409
  const startedAt = Date.now();
374
410
  const platform = platformFor(targetName);
375
411
  const slug = `${config.packageName}-${targetName}`;
376
412
  const command = buildPlatformBuildCommand(targetName, config.packageName, config.nodeValidationMajor);
377
413
  mkdirSync(dirname(suiteDir), { recursive: true });
378
- writeFileSync(resolve(suiteDir, "target.json"), JSON.stringify({ targetName, platform, runId, slug }, null, 2));
414
+ writeFileSync(resolve(suiteDir, "target.json"), JSON.stringify(targetEvidence(config, targetName, runId, slug), null, 2));
379
415
  writeFileSync(resolve(suiteDir, "suite.json"), JSON.stringify({ suiteName, modelCalls: 0 }, null, 2));
380
416
  writeCommand(suiteDir, command);
381
417
 
@@ -436,17 +472,18 @@ async function runPlatformBuildSuite(config, targetName, suiteName, leaseSession
436
472
  return { ok: assertions.ok, suiteDir, assertions };
437
473
  }
438
474
 
439
- export async function runTargetSuite(config, targetName, suiteName, leaseSession) {
440
- if (suiteName === "platform-build") return await runPlatformBuildSuite(config, targetName, suiteName, leaseSession);
441
- if (suiteName === "browser-dogfood-smoke") return await runBrowserDogfoodSuite(config, targetName, suiteName, leaseSession);
475
+ export async function runTargetSuite(config, targetName, suiteName, leaseSession, runId) {
476
+ if (suiteName === "platform-build") return await runPlatformBuildSuite(config, targetName, suiteName, leaseSession, runId);
477
+ if (suiteName === "browser-dogfood-smoke") return await runBrowserDogfoodSuite(config, targetName, suiteName, leaseSession, runId);
442
478
  throw new Error(`unknown suite: ${suiteName}`);
443
479
  }
444
480
 
445
481
  export async function runTargetSuites(config, targetName, suiteNames) {
446
482
  const slug = `${config.packageName}-${targetName}`;
483
+ const runId = makeRunId();
447
484
  const lease = await warmupLease(targetName, slug, config);
448
485
  if (!lease.ok) {
449
- const warmupFailure = createLeaseWarmupFailureResult(config, targetName, lease);
486
+ const warmupFailure = createLeaseWarmupFailureResult(config, targetName, lease, runId);
450
487
  return { ok: false, results: [warmupFailure] };
451
488
  }
452
489
  const results = [];
@@ -455,7 +492,7 @@ export async function runTargetSuites(config, targetName, suiteNames) {
455
492
  try {
456
493
  let sync = true;
457
494
  for (const suiteName of suiteNames) {
458
- const result = await runTargetSuite(config, targetName, suiteName, { ...lease, sync });
495
+ const result = await runTargetSuite(config, targetName, suiteName, { ...lease, sync }, runId);
459
496
  results.push(result);
460
497
  sync = false;
461
498
  if (!result.ok) break;
@@ -465,7 +502,7 @@ export async function runTargetSuites(config, targetName, suiteNames) {
465
502
  staleCleanupResult = await cleanupStaleTargetState(targetName, config);
466
503
  }
467
504
  if (stopResult) {
468
- results.push(createLeaseCleanupResult(config, targetName, lease.leaseId, stopResult, staleCleanupResult));
505
+ results.push(createLeaseCleanupResult(config, targetName, lease.leaseId, stopResult, staleCleanupResult, runId));
469
506
  }
470
507
  return { ok: results.every((result) => result.ok), results };
471
508
  }
@@ -61,6 +61,7 @@ Environment:
61
61
  PLATFORM_SMOKE_MAC_HOST macOS SSH host; default localhost
62
62
  PLATFORM_SMOKE_MAC_USER macOS SSH user; default $USER
63
63
  PLATFORM_SMOKE_MAC_WORK_ROOT macOS Crabbox work root
64
+ PLATFORM_SMOKE_MAC_PORT macOS SSH port; default 22
64
65
  PLATFORM_SMOKE_UBUNTU_IMAGE Ubuntu local-container image; default pi-agent-browser-native-platform:node24-agent-browser0.27.1
65
66
  PLATFORM_SMOKE_WINDOWS_VM Parallels Windows template VM
66
67
  PLATFORM_SMOKE_WINDOWS_SNAPSHOT Parallels snapshot name