@deeeed/metamask-harness 0.79.0 → 0.81.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/CHANGELOG.md +73 -0
- package/README.md +1 -1
- package/adapters/extension/ensure-browser.sh +2 -2
- package/adapters/extension/inject.mjs +0 -1
- package/adapters/extension/launch-browser.cjs +39 -613
- package/adapters/extension/readiness.mjs +2 -5
- package/adapters/extension/reattach.sh +2 -2
- package/adapters/extension/stamp-runtime-title.cjs +1 -1
- package/adapters/manifest.json +16 -64
- package/adapters/mobile/bridge-runtime/cdp-bridge.cjs +57 -1358
- package/adapters/mobile/bridge-runtime/teaching.cjs +20 -0
- package/adapters/mobile/inject.sh +16 -0
- package/adapters/mobile/launch-console-forwarder.cjs +1 -2
- package/adapters/mobile/open-device.sh +2 -2
- package/adapters/mobile/reload-app.mjs +4 -4
- package/adapters/mobile/reset-app-data.sh +1 -1
- package/adapters/mobile/start-console-forwarder.sh +3 -2
- package/adapters/mobile/start-metro.sh +17 -12
- package/adapters/mobile/wait-for-bridge.cjs +2 -2
- package/adapters/shared/harness-source-fingerprint.mjs +13 -8
- package/adapters/shared/open-debug.mjs +2 -2
- package/adapters/shared/sync-wallet-fixture.sh +8 -5
- package/adapters/terminal/cleanup.mjs +2 -1
- package/adapters/terminal/inject.mjs +2 -1
- package/adapters/terminal/launch.mjs +17 -13
- package/adapters/terminal/lib/mainnet-guard.mjs +9 -0
- package/adapters/terminal/lib/readiness.mjs +20 -12
- package/adapters/terminal/policy.mjs +35 -0
- package/adapters/terminal/verify.mjs +10 -3
- package/adapters/terminal/wallet-host.mjs +43 -225
- package/bin/mm-harness +9 -28
- package/dist/adapters/checkout-files.js +16 -0
- package/dist/adapters/console-capture.js +14 -1
- package/dist/adapters/core/actions.js +8 -4
- package/dist/adapters/core/overlay.js +1 -1
- package/dist/adapters/core/readiness.js +28 -1
- package/dist/adapters/core/run.js +2 -2
- package/dist/adapters/core/surface.js +16 -1
- package/dist/adapters/extension/actions.js +6 -2
- package/dist/adapters/extension/browser-pid.js +56 -0
- package/dist/adapters/extension/console-capture.js +1 -1
- package/dist/adapters/extension/doctor-checks.js +1 -1
- package/dist/adapters/extension/ensure-ready.js +5 -4
- package/dist/adapters/extension/extension-id.js +1 -1
- package/dist/adapters/extension/feature-flags.js +1 -1
- package/dist/adapters/extension/fixtures.js +1 -2
- package/dist/adapters/extension/launch.js +4 -5
- package/dist/adapters/extension/launched-browser.js +1 -2
- package/dist/adapters/extension/network-observer.js +14 -1
- package/dist/adapters/extension/overlay.js +1 -1
- package/dist/adapters/extension/product-config.js +1 -1
- package/dist/adapters/extension/readiness.js +1 -1
- package/dist/adapters/extension/reload.js +1 -1
- package/dist/adapters/extension/run.js +135 -14
- package/dist/adapters/extension/runtime-decision.js +2 -1
- package/dist/adapters/extension/runtime.js +9 -5
- package/dist/adapters/extension/surface.js +15 -2
- package/dist/adapters/extension/verify.js +2 -2
- package/dist/adapters/harness-freshness.js +2 -1
- package/dist/adapters/mobile/actions.js +4 -1
- package/dist/adapters/mobile/android-gfxinfo-performance.js +1 -3
- package/dist/adapters/mobile/app-identity.js +10 -0
- package/dist/adapters/mobile/doctor-checks.js +1 -1
- package/dist/adapters/mobile/fixtures.js +1 -1
- package/dist/adapters/mobile/launch.js +27 -28
- package/dist/adapters/mobile/lifecycle.js +1 -1
- package/dist/adapters/mobile/metro-env.js +9 -59
- package/dist/adapters/mobile/network-observer.js +68 -0
- package/dist/adapters/mobile/performance-observer.js +2 -4
- package/dist/adapters/mobile/prepare-target.js +1 -1
- package/dist/adapters/mobile/prepare.js +3 -4
- package/dist/adapters/mobile/provision.js +1 -1
- package/dist/adapters/mobile/readiness.js +1 -1
- package/dist/adapters/mobile/recording-target.js +15 -0
- package/dist/adapters/mobile/release-artifact-state.js +1 -1
- package/dist/adapters/mobile/reload.js +1 -1
- package/dist/adapters/mobile/run.js +39 -15
- package/dist/adapters/mobile/runtime-decision.js +2 -4
- package/dist/adapters/mobile/source-freshness.js +22 -126
- package/dist/adapters/mobile/surface.js +26 -3
- package/dist/adapters/mobile/ui.js +16 -5
- package/dist/adapters/mobile/verify.js +2 -3
- package/dist/adapters/performance/cdp-trace.js +1 -1
- package/dist/adapters/performance/device-platform.js +1 -1
- package/dist/adapters/perps-order-inputs.js +36 -0
- package/dist/adapters/proof-failure.js +11 -0
- package/dist/adapters/slot-ports.js +1 -1
- package/dist/adapters/surface.js +1 -0
- package/dist/adapters/terminal/actions.js +4 -1
- package/dist/adapters/terminal/console-capture.js +1 -1
- package/dist/adapters/terminal/doctor-checks.js +2 -0
- package/dist/adapters/terminal/launch.js +4 -1
- package/dist/adapters/terminal/overlay.js +8 -1
- package/dist/adapters/terminal/run.js +33 -5
- package/dist/adapters/terminal/surface.js +9 -1
- package/dist/adapters.js +27 -7
- package/dist/advisor-policy.js +1 -1
- package/dist/checkout-view.js +1 -2
- package/dist/cli.js +59 -21
- package/dist/command-contract.js +1 -26
- package/dist/commands/check.js +33 -10
- package/dist/commands/checklist.js +1 -1
- package/dist/commands/completion-candidates.js +6 -14
- package/dist/commands/config.js +2 -2
- package/dist/commands/core-readiness.js +12 -7
- package/dist/commands/debug.js +3 -3
- package/dist/commands/device-target.js +5 -5
- package/dist/commands/doctor.js +2 -14
- package/dist/commands/domain.js +2 -2
- package/dist/commands/ensure-ready.js +1 -7
- package/dist/commands/fixtures.js +5 -6
- package/dist/commands/help.js +3 -4
- package/dist/commands/launch/device.js +10 -17
- package/dist/commands/launch/extension.js +2 -8
- package/dist/commands/launch/mobile.js +1 -1
- package/dist/commands/logs.js +3 -3
- package/dist/commands/mobile-device-view.js +4 -2
- package/dist/commands/overlay.js +110 -0
- package/dist/commands/pin.js +1 -1
- package/dist/commands/pr-body.js +2 -2
- package/dist/commands/prepare.js +4 -9
- package/dist/commands/provision.js +3 -12
- package/dist/commands/recipe-advice.js +1 -2
- package/dist/commands/recipe-quality.js +2 -3
- package/dist/commands/resolve-extension.js +1 -7
- package/dist/commands/review.js +4 -4
- package/dist/commands/runtime-decision.js +1 -6
- package/dist/commands/runtime-health.js +1 -7
- package/dist/commands/runtime-launch.js +1 -13
- package/dist/commands/self-test.js +5 -8
- package/dist/commands/status-watch.js +1 -2
- package/dist/commands/status.js +2 -5
- package/dist/commands/task-init.js +2 -3
- package/dist/commands/tutorial.js +2 -2
- package/dist/commands/update.js +1 -1
- package/dist/completions-cache.js +1 -1
- package/dist/console-classifier.js +19 -0
- package/dist/doctor.js +2 -3
- package/dist/engine.js +57 -0
- package/dist/funding-execution-context.js +96 -1
- package/dist/host.js +32 -0
- package/dist/index.js +1 -6
- package/dist/live-tsx.js +49 -0
- package/dist/mm-harness-cli.js +4 -6
- package/dist/paths.js +34 -64
- package/dist/performance-observation.js +3 -5
- package/dist/progress.js +1 -1
- package/dist/recipe-assistance-context.js +6 -9
- package/dist/recipe-security.js +2 -59
- package/dist/review/knowledge.js +2 -2
- package/dist/runner.js +7 -4
- package/dist/runtime-context.js +1 -1
- package/dist/task-view.js +2 -3
- package/docs/CONTRIBUTING.md +5 -3
- package/docs/RECIPES.md +31 -3
- package/docs/cli-contract.md +2 -2
- package/docs/feature-guard.md +90 -0
- package/library/README.md +3 -1
- package/library/actions/core/perps/_controller.mjs +153 -134
- package/library/actions/core/perps/_rewards.mjs +186 -0
- package/library/actions/core/perps/close_positions.mjs +1 -1
- package/library/actions/core/perps/place_order.mjs +167 -45
- package/library/actions/core/perps/quote_fees.mjs +61 -0
- package/library/actions/core/wallet/list_accounts.mjs +14 -57
- package/library/actions/extension/feature_flags/state.mjs +1 -1
- package/library/actions/extension/perps/close_visible_position.mjs +5 -0
- package/library/actions/extension/perps/edit_margin.mjs +4 -0
- package/library/actions/extension/perps/mutation-receipt.mjs +95 -3
- package/library/actions/extension/perps/perps.mjs +320 -3
- package/library/actions/extension/perps/place_order.mjs +3 -1
- package/library/actions/extension/perps/update_position_tpsl.mjs +4 -0
- package/library/actions/extension/platform/cdp.mjs +73 -11
- package/library/actions/harness-exports.mjs +1 -6
- package/library/actions/mobile/app/network-control.mjs +6 -8
- package/library/actions/mobile/perps/perps.mjs +216 -11
- package/library/actions/mobile/perps/place_order.mjs +3 -1
- package/library/actions/mobile/perps/prepare_local_snapshot_endpoint.mjs +1 -1
- package/library/actions/mobile/platform/bridge.mjs +8 -8
- package/library/actions/mobile/platform/native-session-name.mjs +21 -1
- package/library/actions/mobile/platform/native-session.mjs +3 -4
- package/library/actions/mobile/platform/observe-ui.mjs +12 -6
- package/library/actions/mobile/ui/native-navigation.mjs +4 -3
- package/library/actions/mobile/wallet/native-ui.mjs +3 -2
- package/library/actions/shared/analytics/_adapter.mjs +1 -1
- package/library/actions/shared/console-findings.mjs +1 -1
- package/library/actions/shared/perps/order-policy.mjs +177 -0
- package/library/actions/shared/wallet/fixture-accounts.mjs +84 -0
- package/library/actions/terminal/app/launch.mjs +3 -2
- package/library/actions/terminal/platform/hud.mjs +2 -1
- package/library/actions/terminal/platform/page.mjs +2 -1
- package/library/actions/terminal/platform/runtime.mjs +2 -1
- package/library/actions/terminal/wallet/_signature-log.mjs +40 -161
- package/library/actions/terminal/wallet/assert_signatures.mjs +6 -12
- package/library/actions/terminal/wallet/read_signatures.mjs +10 -9
- package/library/manifests/core.action-manifest.json +87 -13
- package/library/manifests/extension.action-manifest.json +4 -0
- package/library/manifests/mobile.action-manifest.json +12 -0
- package/package.json +8 -9
- package/site/assets/help-recipes.json +1 -0
- package/adapters/extension/lib/slot-title.cjs +0 -292
- package/adapters/mobile/bridge-runtime/console-forwarder.cjs +0 -472
- package/adapters/mobile/bridge-runtime/lib/bridge-errors.cjs +0 -125
- package/adapters/mobile/bridge-runtime/lib/cdp-broker.cjs +0 -1055
- package/adapters/mobile/bridge-runtime/lib/cdp-eval.cjs +0 -110
- package/adapters/mobile/bridge-runtime/lib/config.cjs +0 -61
- package/adapters/mobile/bridge-runtime/lib/console-format.cjs +0 -53
- package/adapters/mobile/bridge-runtime/lib/devtools-proxy.cjs +0 -177
- package/adapters/mobile/bridge-runtime/lib/issue-capture.cjs +0 -446
- package/adapters/mobile/bridge-runtime/lib/match-bridge-target.cjs +0 -84
- package/adapters/mobile/bridge-runtime/lib/target-discovery.cjs +0 -403
- package/adapters/mobile/bridge-runtime/lib/ws-client.cjs +0 -116
- package/adapters/mobile/coalesce-metro-log.cjs +0 -24
- package/adapters/mobile/launch-metro.cjs +0 -77
- package/adapters/mobile/metro-config.cjs +0 -98
- package/adapters/mobile/metro-log-generation.cjs +0 -106
- package/adapters/terminal/lib/origin.mjs +0 -30
- package/adapters/terminal/lib/page-script.mjs +0 -246
- package/adapters/terminal/lib/strict-wallet.mjs +0 -138
- package/dist/adapters/mobile/frame-metrics.js +0 -118
- package/dist/adapters/mobile/video-recorder.js +0 -289
- package/dist/artifact-files.js +0 -92
- package/dist/checkout-lock.js +0 -149
- package/dist/cli-color.js +0 -98
- package/dist/command-journal.js +0 -308
- package/dist/commands/call.js +0 -685
- package/dist/commands/last.js +0 -60
- package/dist/commands/launch/index.js +0 -109
- package/dist/commands/list-executables.js +0 -247
- package/dist/commands/manifest.js +0 -488
- package/dist/commands/parse-args.js +0 -279
- package/dist/commands/reload.js +0 -41
- package/dist/commands/run-engine.js +0 -1340
- package/dist/commands/run-report.js +0 -241
- package/dist/commands/run.js +0 -751
- package/dist/commands/shared.js +0 -323
- package/dist/commands/stop.js +0 -60
- package/dist/devices.js +0 -100
- package/dist/discovery.js +0 -15
- package/dist/execution-provenance.js +0 -332
- package/dist/harness.js +0 -451
- package/dist/heal-bounds.js +0 -137
- package/dist/json-stream.js +0 -60
- package/dist/leaf-invoke.js +0 -19
- package/dist/library-provenance.js +0 -33
- package/dist/live-adapter-contract.js +0 -380
- package/dist/metamask-action-validation.js +0 -68
- package/dist/network-observation.js +0 -290
- package/dist/recording-target.js +0 -120
- package/dist/run-diagnostics.js +0 -364
- package/dist/run-recording.js +0 -481
- package/dist/runtime-proof.js +0 -90
- package/library/actions/mobile/platform/tool-paths.mjs +0 -123
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { execFileSync } from "node:child_process";
|
|
4
|
-
import { getAdapterSurface } from "../adapters/surface.js";
|
|
5
|
-
import { isRecord } from "./parse-args.js";
|
|
6
|
-
function writeRunReport(result) {
|
|
7
|
-
const summaryPath = String(result.summaryPath);
|
|
8
|
-
const tracePath = String(result.tracePath);
|
|
9
|
-
const artifactManifestPath = String(result.artifactManifestPath);
|
|
10
|
-
const artifactsDir = path.dirname(summaryPath);
|
|
11
|
-
const summary = JSON.parse(fs.readFileSync(summaryPath, "utf8"));
|
|
12
|
-
const trace = JSON.parse(fs.readFileSync(tracePath, "utf8"));
|
|
13
|
-
const entries = Array.isArray(trace.entries) ? trace.entries : [];
|
|
14
|
-
const lines = renderRunReport(summary, entries);
|
|
15
|
-
const reportPath = path.join(artifactsDir, "report.md");
|
|
16
|
-
fs.writeFileSync(reportPath, `${lines.join("\n")}
|
|
17
|
-
`);
|
|
18
|
-
indexRunReportArtifact(artifactManifestPath);
|
|
19
|
-
return {
|
|
20
|
-
path: reportPath,
|
|
21
|
-
preview: lines.filter((line) => line.startsWith("- ")).slice(0, 6).map((line) => line.slice(2))
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
function indexProductProvenanceArtifact(artifactManifestPath, target, adapter, browser = null) {
|
|
25
|
-
const artifactsDir = path.dirname(artifactManifestPath);
|
|
26
|
-
let gitRef = "unknown";
|
|
27
|
-
let branch = "unknown";
|
|
28
|
-
let dirty = true;
|
|
29
|
-
try {
|
|
30
|
-
gitRef = execFileSync("git", ["rev-parse", "HEAD"], {
|
|
31
|
-
cwd: target,
|
|
32
|
-
encoding: "utf8",
|
|
33
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
34
|
-
}).trim();
|
|
35
|
-
branch = execFileSync("git", ["branch", "--show-current"], {
|
|
36
|
-
cwd: target,
|
|
37
|
-
encoding: "utf8",
|
|
38
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
39
|
-
}).trim() || "detached";
|
|
40
|
-
dirty = execFileSync(
|
|
41
|
-
"git",
|
|
42
|
-
["status", "--porcelain", "--untracked-files=normal"],
|
|
43
|
-
{
|
|
44
|
-
cwd: target,
|
|
45
|
-
encoding: "utf8",
|
|
46
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
47
|
-
}
|
|
48
|
-
).trim().length > 0;
|
|
49
|
-
} catch {
|
|
50
|
-
}
|
|
51
|
-
const provenance = {
|
|
52
|
-
schemaVersion: 1,
|
|
53
|
-
adapter,
|
|
54
|
-
repository: path.basename(path.resolve(target)),
|
|
55
|
-
git_ref: gitRef,
|
|
56
|
-
branch,
|
|
57
|
-
dirty,
|
|
58
|
-
...browser ? { browser } : {}
|
|
59
|
-
};
|
|
60
|
-
fs.writeFileSync(
|
|
61
|
-
path.join(artifactsDir, "product-provenance.json"),
|
|
62
|
-
`${JSON.stringify(provenance, null, 2)}
|
|
63
|
-
`
|
|
64
|
-
);
|
|
65
|
-
let manifest;
|
|
66
|
-
try {
|
|
67
|
-
manifest = JSON.parse(fs.readFileSync(artifactManifestPath, "utf8"));
|
|
68
|
-
} catch {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
if (!isRecord(manifest)) return;
|
|
72
|
-
const artifacts = Array.isArray(manifest.artifacts) ? manifest.artifacts : [];
|
|
73
|
-
manifest.artifacts = [
|
|
74
|
-
...artifacts.filter(
|
|
75
|
-
(artifact) => !isRecord(artifact) || artifact.path !== "product-provenance.json"
|
|
76
|
-
),
|
|
77
|
-
{
|
|
78
|
-
path: "product-provenance.json",
|
|
79
|
-
type: "json",
|
|
80
|
-
label: "Product checkout provenance",
|
|
81
|
-
category: "system",
|
|
82
|
-
metadata: {
|
|
83
|
-
adapter,
|
|
84
|
-
git_ref: gitRef,
|
|
85
|
-
branch,
|
|
86
|
-
dirty,
|
|
87
|
-
...browser?.boundTo && browser.boundTo !== "none" ? { browser: browser.browser, browser_version: browser.version, browser_source: browser.source, extension_loading: browser.extensionLoading } : {}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
];
|
|
91
|
-
fs.writeFileSync(
|
|
92
|
-
artifactManifestPath,
|
|
93
|
-
`${JSON.stringify(manifest, null, 2)}
|
|
94
|
-
`
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
function resolveTemplatedPort(value, params, recipe) {
|
|
98
|
-
let resolved = value;
|
|
99
|
-
const template = /^\{\{\s*params\.([\w-]+)\s*\}\}$/u.exec(String(value).trim());
|
|
100
|
-
if (template) {
|
|
101
|
-
const name = template[1];
|
|
102
|
-
const schema = isRecord(recipe) && isRecord(recipe.paramsSchema) && isRecord(recipe.paramsSchema.properties) ? recipe.paramsSchema.properties[name] : void 0;
|
|
103
|
-
resolved = isRecord(params) && params[name] !== void 0 ? params[name] : isRecord(schema) ? schema.default : void 0;
|
|
104
|
-
}
|
|
105
|
-
const text = String(resolved ?? "").trim();
|
|
106
|
-
return /^\d+$/u.test(text) ? text : null;
|
|
107
|
-
}
|
|
108
|
-
function recipeCdpPorts(request) {
|
|
109
|
-
const ports = /* @__PURE__ */ new Set();
|
|
110
|
-
const envPort = request.env?.CDP_PORT || request.env?.RECIPE_CDP_PORT;
|
|
111
|
-
if (envPort) ports.add(String(envPort));
|
|
112
|
-
let recipe = request.recipeDocument;
|
|
113
|
-
if (recipe === void 0 && request.recipePath) {
|
|
114
|
-
try {
|
|
115
|
-
recipe = JSON.parse(fs.readFileSync(request.recipePath, "utf8"));
|
|
116
|
-
} catch {
|
|
117
|
-
recipe = void 0;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
const workflow = isRecord(recipe) && isRecord(recipe.workflow) ? recipe.workflow : null;
|
|
121
|
-
const nodes = workflow && isRecord(workflow.nodes) ? Object.values(workflow.nodes) : [];
|
|
122
|
-
for (const node of nodes) {
|
|
123
|
-
if (!isRecord(node) || node.cdp_port === void 0 || node.cdp_port === null) continue;
|
|
124
|
-
const port = resolveTemplatedPort(node.cdp_port, request.params, recipe);
|
|
125
|
-
ports.add(port ?? `unresolved ${String(node.cdp_port)}`);
|
|
126
|
-
}
|
|
127
|
-
return [...ports];
|
|
128
|
-
}
|
|
129
|
-
function executedBrowser(adapter, target, artifactManifestPath, ports) {
|
|
130
|
-
const launched = getAdapterSurface(adapter).run?.launchedBrowser;
|
|
131
|
-
if (!launched) return null;
|
|
132
|
-
if (ports.length === 0) return { boundTo: "none", reason: "the run had no known CDP port" };
|
|
133
|
-
if (ports.length > 1) return { boundTo: "none", reason: `the run drove several CDP ports (${ports.join(", ")})` };
|
|
134
|
-
return launched(target, path.dirname(artifactManifestPath), ports[0]);
|
|
135
|
-
}
|
|
136
|
-
function renderRunReport(summary, entries) {
|
|
137
|
-
const lines = [
|
|
138
|
-
"# MetaMask Recipe Run",
|
|
139
|
-
"",
|
|
140
|
-
`Status: ${String(summary.status ?? "unknown")}`,
|
|
141
|
-
`Duration: ${formatDuration(Number(summary.durationMs ?? 0))}`,
|
|
142
|
-
`Nodes: ${Number(summary.passed ?? 0)}/${Number(summary.total ?? entries.length)} passed`
|
|
143
|
-
];
|
|
144
|
-
const sideFindings = isRecord(summary.sideFindings) ? summary.sideFindings : void 0;
|
|
145
|
-
const sideFindingCounts = sideFindings && isRecord(sideFindings.counts) ? sideFindings.counts : void 0;
|
|
146
|
-
const sideFindingTotal = Number(sideFindingCounts?.total ?? 0);
|
|
147
|
-
if (sideFindingTotal > 0) {
|
|
148
|
-
lines.push(
|
|
149
|
-
"",
|
|
150
|
-
"## Side findings",
|
|
151
|
-
`- REVIEW ${sideFindingTotal} distinct application warning/error event(s) (non-blocking; expanded below and stored in diagnostics.json)`
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
lines.push("", "## Steps");
|
|
155
|
-
for (const entry of entries) {
|
|
156
|
-
if (!isRecord(entry)) continue;
|
|
157
|
-
const mark = entry.ok === false ? "FAIL" : "PASS";
|
|
158
|
-
const nodeId = String(entry.nodeId ?? "(node)");
|
|
159
|
-
const action = String(entry.action ?? "(action)");
|
|
160
|
-
const duration = formatDuration(Number(entry.durationMs ?? 0));
|
|
161
|
-
const detail = summarizeNodeOutput(entry.output);
|
|
162
|
-
lines.push(`- ${mark} ${nodeId} (${action}, ${duration})${detail ? `: ${detail}` : ""}`);
|
|
163
|
-
}
|
|
164
|
-
return lines;
|
|
165
|
-
}
|
|
166
|
-
function summarizeNodeOutput(output) {
|
|
167
|
-
if (!isRecord(output)) return "";
|
|
168
|
-
const parts = [];
|
|
169
|
-
const preferredKeys = [
|
|
170
|
-
"platform",
|
|
171
|
-
"screen",
|
|
172
|
-
"route",
|
|
173
|
-
"page",
|
|
174
|
-
"network",
|
|
175
|
-
"account",
|
|
176
|
-
"count",
|
|
177
|
-
"matchingCount",
|
|
178
|
-
"proofPath",
|
|
179
|
-
"screenshot",
|
|
180
|
-
"path"
|
|
181
|
-
];
|
|
182
|
-
for (const key of preferredKeys) addPart(parts, labelFor(key), summarizeValue(output[key]));
|
|
183
|
-
const accountState = isRecord(output.accountState) ? output.accountState : void 0;
|
|
184
|
-
if (accountState) {
|
|
185
|
-
addPart(parts, "totalBalance", accountState.totalBalance);
|
|
186
|
-
addPart(parts, "spendable", accountState.spendableBalance);
|
|
187
|
-
addPart(parts, "marginUsed", accountState.marginUsed);
|
|
188
|
-
addPart(parts, "unrealizedPnl", accountState.unrealizedPnl);
|
|
189
|
-
}
|
|
190
|
-
if (parts.length === 0) {
|
|
191
|
-
for (const [key, value] of Object.entries(output)) {
|
|
192
|
-
if (parts.length >= 5) break;
|
|
193
|
-
if (key === "liveAdapter" || key === "artifacts") continue;
|
|
194
|
-
addPart(parts, key, summarizeValue(value));
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
return parts.join(", ");
|
|
198
|
-
}
|
|
199
|
-
function labelFor(key) {
|
|
200
|
-
return key === "matchingCount" ? "matching" : key === "proofPath" ? "proof" : key;
|
|
201
|
-
}
|
|
202
|
-
function summarizeValue(value) {
|
|
203
|
-
if (typeof value === "string") return shortenAddress(value);
|
|
204
|
-
if (typeof value === "number" || typeof value === "boolean") return value;
|
|
205
|
-
if (Array.isArray(value)) return `${value.length} item${value.length === 1 ? "" : "s"}`;
|
|
206
|
-
return void 0;
|
|
207
|
-
}
|
|
208
|
-
function addPart(parts, label, value) {
|
|
209
|
-
if (value === void 0 || value === null || value === "") return;
|
|
210
|
-
parts.push(`${label}=${String(value)}`);
|
|
211
|
-
}
|
|
212
|
-
function shortenAddress(value) {
|
|
213
|
-
return /^0x[a-fA-F0-9]{40}$/u.test(value) ? `${value.slice(0, 6)}...${value.slice(-4)}` : value;
|
|
214
|
-
}
|
|
215
|
-
function formatDuration(ms) {
|
|
216
|
-
if (!Number.isFinite(ms) || ms <= 0) return "0ms";
|
|
217
|
-
if (ms < 1e3) return `${Math.round(ms)}ms`;
|
|
218
|
-
return `${(ms / 1e3).toFixed(ms < 1e4 ? 1 : 0)}s`;
|
|
219
|
-
}
|
|
220
|
-
function indexRunReportArtifact(artifactManifestPath) {
|
|
221
|
-
let manifest;
|
|
222
|
-
try {
|
|
223
|
-
manifest = JSON.parse(fs.readFileSync(artifactManifestPath, "utf8"));
|
|
224
|
-
} catch {
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
if (!isRecord(manifest)) return;
|
|
228
|
-
const artifacts = Array.isArray(manifest.artifacts) ? manifest.artifacts : [];
|
|
229
|
-
manifest.artifacts = [
|
|
230
|
-
...artifacts.filter((artifact) => !isRecord(artifact) || artifact.path !== "report.md"),
|
|
231
|
-
{ path: "report.md", type: "report", label: "Human run report", category: "system" }
|
|
232
|
-
];
|
|
233
|
-
fs.writeFileSync(artifactManifestPath, `${JSON.stringify(manifest, null, 2)}
|
|
234
|
-
`);
|
|
235
|
-
}
|
|
236
|
-
export {
|
|
237
|
-
executedBrowser,
|
|
238
|
-
indexProductProvenanceArtifact,
|
|
239
|
-
recipeCdpPorts,
|
|
240
|
-
writeRunReport
|
|
241
|
-
};
|