@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,488 +0,0 @@
|
|
|
1
|
-
import { resolveActionManifest } from "../manifest.js";
|
|
2
|
-
import { color } from "../cli-color.js";
|
|
3
|
-
import { EXIT } from "./shared.js";
|
|
4
|
-
import {
|
|
5
|
-
isRecord,
|
|
6
|
-
optionFlag,
|
|
7
|
-
optionString,
|
|
8
|
-
optionStrings,
|
|
9
|
-
resolveAdapter,
|
|
10
|
-
shellQuoteArg
|
|
11
|
-
} from "./parse-args.js";
|
|
12
|
-
import { resolveMetaMaskLibrarySources } from "./run-engine.js";
|
|
13
|
-
import { isSensitiveKey, redactStructuredValue } from "../command-journal.js";
|
|
14
|
-
import {
|
|
15
|
-
OFFICIAL_RECIPE_ACTIONS,
|
|
16
|
-
officialRecipeActionCapabilities
|
|
17
|
-
} from "@farmslot/protocol";
|
|
18
|
-
import { metaMaskActionExecutionCapabilities } from "../recipe-security.js";
|
|
19
|
-
import { closest } from "../command-contract.js";
|
|
20
|
-
import {
|
|
21
|
-
actionCapabilityMatrix,
|
|
22
|
-
actionCategory,
|
|
23
|
-
findRelatedActions,
|
|
24
|
-
fuzzyResolveActions,
|
|
25
|
-
resolveActionCapabilityRefusal,
|
|
26
|
-
searchActions,
|
|
27
|
-
summarizeActionCategories
|
|
28
|
-
} from "@farmslot/recipe-cli";
|
|
29
|
-
const OFFICIAL_ACTIONS = new Set(OFFICIAL_RECIPE_ACTIONS);
|
|
30
|
-
const ACTION_MATRIX_ADAPTERS = ["mobile", "extension", "core", "terminal"];
|
|
31
|
-
function actionLibraryContextArgs(librarySources) {
|
|
32
|
-
return (librarySources ?? []).filter((source) => source.name !== "metamask").map((source) => {
|
|
33
|
-
const entry = source.name ? `${source.name}=${source.root}` : source.root;
|
|
34
|
-
return ` --library ${shellQuoteArg(entry)}`;
|
|
35
|
-
}).join("");
|
|
36
|
-
}
|
|
37
|
-
async function handleActions({ options, positional }) {
|
|
38
|
-
const librarySources = await resolveMetaMaskLibrarySources(optionStrings(options, "library"));
|
|
39
|
-
const json = optionFlag(options, "json");
|
|
40
|
-
const action = optionString(options, "action");
|
|
41
|
-
const query = positional[0]?.trim();
|
|
42
|
-
const category = optionString(options, "category")?.toLowerCase();
|
|
43
|
-
if (optionFlag(options, "matrix")) {
|
|
44
|
-
return handleActionMatrix(options, { json, action, query, category, librarySources });
|
|
45
|
-
}
|
|
46
|
-
const { adapter, target } = resolveAdapter(options);
|
|
47
|
-
const actionManifestOverride = optionString(options, "actionManifest");
|
|
48
|
-
const { manifest, actionSources } = await resolveActionManifest(
|
|
49
|
-
adapter,
|
|
50
|
-
actionManifestOverride,
|
|
51
|
-
librarySources
|
|
52
|
-
);
|
|
53
|
-
if (optionFlag(options, "raw")) {
|
|
54
|
-
console.log(JSON.stringify(manifest, null, 2));
|
|
55
|
-
return EXIT.ok;
|
|
56
|
-
}
|
|
57
|
-
const categoriesOnly = optionFlag(options, "categories");
|
|
58
|
-
const all = describeManifestActions(manifest, actionSources);
|
|
59
|
-
const categories = summarizeActionCategories(all);
|
|
60
|
-
if (categoriesOnly && (action || category)) {
|
|
61
|
-
const message = "--categories cannot be combined with --action or --category.";
|
|
62
|
-
const userAction = `mm-harness actions --adapter ${adapter} --categories`;
|
|
63
|
-
if (json) {
|
|
64
|
-
console.log(JSON.stringify({ schemaVersion: 1, command: "actions", adapter, error: { code: "ACTION_FILTER_CONFLICT", message, userAction } }, null, 2));
|
|
65
|
-
} else {
|
|
66
|
-
console.error(`\u2717 mm-harness actions: ${message}
|
|
67
|
-
Next: ${userAction}`);
|
|
68
|
-
}
|
|
69
|
-
return EXIT.usage;
|
|
70
|
-
}
|
|
71
|
-
if (categoriesOnly) {
|
|
72
|
-
if (json) console.log(JSON.stringify({ schemaVersion: 1, command: "actions", adapter, categories }, null, 2));
|
|
73
|
-
else for (const entry of categories) console.log(`${entry.name} (${entry.count})`);
|
|
74
|
-
return EXIT.ok;
|
|
75
|
-
}
|
|
76
|
-
const categoryActions = category ? all.filter((entry) => entry.category === category) : all;
|
|
77
|
-
if (category && categoryActions.length === 0) {
|
|
78
|
-
const message = `no action category matches "${category}" for the ${adapter} adapter.`;
|
|
79
|
-
const userAction = `mm-harness actions --adapter ${adapter} --categories`;
|
|
80
|
-
if (json) {
|
|
81
|
-
console.log(JSON.stringify({ schemaVersion: 1, command: "actions", adapter, category, availableCategories: categories, error: { code: "ACTION_CATEGORY_UNKNOWN", message, userAction } }, null, 2));
|
|
82
|
-
} else {
|
|
83
|
-
console.error(`\u2717 mm-harness actions: ${message}
|
|
84
|
-
Next: ${userAction}`);
|
|
85
|
-
}
|
|
86
|
-
return EXIT.usage;
|
|
87
|
-
}
|
|
88
|
-
const actions = action ? fuzzyResolveActions(categoryActions, action) : query ? searchActions(categoryActions, query) : categoryActions;
|
|
89
|
-
if (action && actions.length === 0) {
|
|
90
|
-
const refusal = actionManifestOverride ? void 0 : resolveActionCapabilityRefusal(
|
|
91
|
-
action,
|
|
92
|
-
adapter,
|
|
93
|
-
await resolveActionCapabilityMatrix(librarySources)
|
|
94
|
-
);
|
|
95
|
-
if (refusal) {
|
|
96
|
-
const satisfying = refusal.satisfyingAdapters.join(", ");
|
|
97
|
-
const message2 = `missing action capability "${refusal.capability}" for the ${adapter} adapter.`;
|
|
98
|
-
const userAction2 = `Satisfying adapters for "${refusal.capability}": ${satisfying}. Inspect: mm-harness actions --matrix --action ${shellQuoteArg(refusal.capability)}${actionLibraryContextArgs(librarySources)} --json`;
|
|
99
|
-
if (json) {
|
|
100
|
-
console.log(JSON.stringify({
|
|
101
|
-
schemaVersion: 1,
|
|
102
|
-
command: "actions",
|
|
103
|
-
adapter,
|
|
104
|
-
action,
|
|
105
|
-
category,
|
|
106
|
-
error: {
|
|
107
|
-
code: "ACTION_CAPABILITY_UNAVAILABLE",
|
|
108
|
-
message: message2,
|
|
109
|
-
capability: refusal.capability,
|
|
110
|
-
satisfyingAdapters: refusal.satisfyingAdapters,
|
|
111
|
-
userAction: userAction2
|
|
112
|
-
}
|
|
113
|
-
}, null, 2));
|
|
114
|
-
} else {
|
|
115
|
-
console.error(`\u2717 mm-harness actions: ${message2}
|
|
116
|
-
Next: ${userAction2}`);
|
|
117
|
-
}
|
|
118
|
-
return EXIT.usage;
|
|
119
|
-
}
|
|
120
|
-
const message = `no action matches "${action}" for the ${adapter} adapter.`;
|
|
121
|
-
const userAction = `mm-harness actions --adapter ${adapter}`;
|
|
122
|
-
if (json) {
|
|
123
|
-
console.log(JSON.stringify({ schemaVersion: 1, command: "actions", adapter, action, category, error: { code: "ACTION_UNKNOWN", message, userAction } }, null, 2));
|
|
124
|
-
} else {
|
|
125
|
-
console.error(`\u2717 mm-harness actions: ${message}
|
|
126
|
-
Next: ${userAction}`);
|
|
127
|
-
}
|
|
128
|
-
return EXIT.usage;
|
|
129
|
-
}
|
|
130
|
-
if (query && actions.length === 0) {
|
|
131
|
-
const message = `no action matches search "${query}" for the ${adapter} adapter.`;
|
|
132
|
-
const userAction = `mm-harness actions --adapter ${adapter} --categories`;
|
|
133
|
-
if (json) {
|
|
134
|
-
console.log(JSON.stringify({
|
|
135
|
-
schemaVersion: 1,
|
|
136
|
-
command: "actions",
|
|
137
|
-
adapter,
|
|
138
|
-
query,
|
|
139
|
-
category,
|
|
140
|
-
error: { code: "ACTION_SEARCH_EMPTY", message, userAction }
|
|
141
|
-
}, null, 2));
|
|
142
|
-
} else {
|
|
143
|
-
console.error(`\u2717 mm-harness actions: ${message}
|
|
144
|
-
Next: ${userAction}`);
|
|
145
|
-
}
|
|
146
|
-
return EXIT.usage;
|
|
147
|
-
}
|
|
148
|
-
const relatedActions = action && actions.length === 1 ? findRelatedActions(all, actions[0]) : void 0;
|
|
149
|
-
if (json) {
|
|
150
|
-
const detailed = Boolean(action && actions.length === 1);
|
|
151
|
-
console.log(JSON.stringify({
|
|
152
|
-
schemaVersion: 1,
|
|
153
|
-
command: "actions",
|
|
154
|
-
adapter,
|
|
155
|
-
...query ? { query } : {},
|
|
156
|
-
category,
|
|
157
|
-
detail: detailed ? "full" : "summary",
|
|
158
|
-
actions: detailed ? actions : actions.map(summarizeDescribedAction),
|
|
159
|
-
...relatedActions?.length ? { relatedActions } : {}
|
|
160
|
-
}, null, 2));
|
|
161
|
-
} else {
|
|
162
|
-
console.log(renderHumanActionCatalog(actions, {
|
|
163
|
-
title: `actions (${adapter})`,
|
|
164
|
-
guidance: "Inspect: mm-harness actions --action <name> \xB7 Run: mm-harness call <name>"
|
|
165
|
-
}));
|
|
166
|
-
const example = action && actions.length === 1 ? renderHumanActionExample(
|
|
167
|
-
actions[0],
|
|
168
|
-
adapter,
|
|
169
|
-
target,
|
|
170
|
-
process.env.MM_HARNESS_INVOKED_AS ?? process.env.MM_HARNESS_EXECUTABLE ?? "mm-harness"
|
|
171
|
-
) : void 0;
|
|
172
|
-
if (example) console.log(`
|
|
173
|
-
${example}`);
|
|
174
|
-
if (relatedActions?.length) console.log(`
|
|
175
|
-
${color("label", "Related:", { stream: process.stdout })} ${relatedActions.join(", ")}`);
|
|
176
|
-
}
|
|
177
|
-
return 0;
|
|
178
|
-
}
|
|
179
|
-
async function resolveActionCapabilityMatrix(librarySources) {
|
|
180
|
-
const catalogs = await Promise.all(
|
|
181
|
-
ACTION_MATRIX_ADAPTERS.map(async (adapter) => {
|
|
182
|
-
const { manifest, actionSources } = await resolveActionManifest(
|
|
183
|
-
adapter,
|
|
184
|
-
void 0,
|
|
185
|
-
librarySources
|
|
186
|
-
);
|
|
187
|
-
return { adapter, actions: describeManifestActions(manifest, actionSources) };
|
|
188
|
-
})
|
|
189
|
-
);
|
|
190
|
-
return actionCapabilityMatrix(catalogs);
|
|
191
|
-
}
|
|
192
|
-
function handleActionMatrixError(json, code, message, userAction, details = {}) {
|
|
193
|
-
if (json) {
|
|
194
|
-
console.log(JSON.stringify({
|
|
195
|
-
schemaVersion: 1,
|
|
196
|
-
command: "actions",
|
|
197
|
-
view: "matrix",
|
|
198
|
-
...details,
|
|
199
|
-
error: { code, message, userAction }
|
|
200
|
-
}, null, 2));
|
|
201
|
-
} else {
|
|
202
|
-
console.error(`\u2717 mm-harness actions: ${message}
|
|
203
|
-
Next: ${userAction}`);
|
|
204
|
-
}
|
|
205
|
-
return EXIT.usage;
|
|
206
|
-
}
|
|
207
|
-
async function handleActionMatrix(options, input) {
|
|
208
|
-
const inspectCommand = `mm-harness actions --matrix${actionLibraryContextArgs(input.librarySources)} --json`;
|
|
209
|
-
const conflicts = [
|
|
210
|
-
optionFlag(options, "raw") ? "--raw" : void 0,
|
|
211
|
-
optionFlag(options, "categories") ? "--categories" : void 0,
|
|
212
|
-
optionString(options, "adapter") ? "--adapter" : void 0,
|
|
213
|
-
optionString(options, "platform") ? "--platform" : void 0,
|
|
214
|
-
optionString(options, "actionManifest") ? "--action-manifest" : void 0
|
|
215
|
-
].filter((value) => Boolean(value));
|
|
216
|
-
if (conflicts.length > 0) {
|
|
217
|
-
return handleActionMatrixError(
|
|
218
|
-
input.json,
|
|
219
|
-
"ACTION_MATRIX_CONFLICT",
|
|
220
|
-
`--matrix cannot be combined with ${conflicts.join(", ")}.`,
|
|
221
|
-
inspectCommand
|
|
222
|
-
);
|
|
223
|
-
}
|
|
224
|
-
const matrix = await resolveActionCapabilityMatrix(input.librarySources);
|
|
225
|
-
const categories = summarizeActionCategories(matrix);
|
|
226
|
-
const categoryActions = input.category ? matrix.filter((entry) => entry.category === input.category) : matrix;
|
|
227
|
-
if (input.category && categoryActions.length === 0) {
|
|
228
|
-
return handleActionMatrixError(
|
|
229
|
-
input.json,
|
|
230
|
-
"ACTION_CATEGORY_UNKNOWN",
|
|
231
|
-
`no action category matches "${input.category}" across the adapter matrix.`,
|
|
232
|
-
inspectCommand,
|
|
233
|
-
{ category: input.category, availableCategories: categories }
|
|
234
|
-
);
|
|
235
|
-
}
|
|
236
|
-
const actions = input.action ? fuzzyResolveActions(categoryActions, input.action) : input.query ? searchActions(categoryActions, input.query) : categoryActions;
|
|
237
|
-
if (input.action && actions.length === 0) {
|
|
238
|
-
return handleActionMatrixError(
|
|
239
|
-
input.json,
|
|
240
|
-
"ACTION_UNKNOWN",
|
|
241
|
-
`no action capability matches "${input.action}" across Mobile, Extension, or Core.`,
|
|
242
|
-
inspectCommand,
|
|
243
|
-
{ action: input.action, category: input.category }
|
|
244
|
-
);
|
|
245
|
-
}
|
|
246
|
-
if (input.query && actions.length === 0) {
|
|
247
|
-
return handleActionMatrixError(
|
|
248
|
-
input.json,
|
|
249
|
-
"ACTION_SEARCH_EMPTY",
|
|
250
|
-
`no action capability matches search "${input.query}" across Mobile, Extension, or Core.`,
|
|
251
|
-
inspectCommand,
|
|
252
|
-
{ query: input.query, category: input.category }
|
|
253
|
-
);
|
|
254
|
-
}
|
|
255
|
-
if (input.json) {
|
|
256
|
-
console.log(JSON.stringify({
|
|
257
|
-
schemaVersion: 1,
|
|
258
|
-
command: "actions",
|
|
259
|
-
view: "matrix",
|
|
260
|
-
adapters: ACTION_MATRIX_ADAPTERS,
|
|
261
|
-
...input.query ? { query: input.query } : {},
|
|
262
|
-
...input.category ? { category: input.category } : {},
|
|
263
|
-
actions
|
|
264
|
-
}, null, 2));
|
|
265
|
-
} else {
|
|
266
|
-
console.log(renderHumanActionMatrix(actions));
|
|
267
|
-
}
|
|
268
|
-
return EXIT.ok;
|
|
269
|
-
}
|
|
270
|
-
function renderHumanActionMatrix(actions) {
|
|
271
|
-
const out = (style, text) => color(style, text, { stream: process.stdout });
|
|
272
|
-
const width = Math.max("action capability".length, ...actions.map((action) => action.name.length));
|
|
273
|
-
const cell = (status, width2) => status === "available" ? out("accent", "yes".padEnd(width2)) : out("dim", "\u2014".padEnd(width2));
|
|
274
|
-
return [
|
|
275
|
-
out("bold", "action capability matrix"),
|
|
276
|
-
out("comment", "Inspect one: mm-harness actions --matrix --action <name> --json"),
|
|
277
|
-
`${"action capability".padEnd(width)} mobile extension core terminal`,
|
|
278
|
-
...actions.map(
|
|
279
|
-
(action) => `${action.name.padEnd(width)} ${cell(action.support.mobile, 6)} ${cell(action.support.extension, 9)} ${cell(action.support.core, 4)} ${cell(action.support.terminal, 8)}`
|
|
280
|
-
)
|
|
281
|
-
].join("\n");
|
|
282
|
-
}
|
|
283
|
-
function summarizeDescribedAction(entry) {
|
|
284
|
-
const { schema: _schema, examples: _examples, ...summary } = entry;
|
|
285
|
-
return summary;
|
|
286
|
-
}
|
|
287
|
-
function actionDomain(entry) {
|
|
288
|
-
return entry.category.replaceAll("_", "-");
|
|
289
|
-
}
|
|
290
|
-
function renderHumanActionCatalog(actions, options) {
|
|
291
|
-
const out = (style, text) => color(style, text, { stream: process.stdout });
|
|
292
|
-
const groups = /* @__PURE__ */ new Map();
|
|
293
|
-
for (const entry of actions) {
|
|
294
|
-
const group = options.sort === "name" ? "" : options.sort === "library" ? `Library: ${entry.source}` : options.sort === "domain" ? actionDomain(entry) : actionDomainGroup(entry);
|
|
295
|
-
groups.set(group, [...groups.get(group) ?? [], entry]);
|
|
296
|
-
}
|
|
297
|
-
const lines = [out("bold", options.title), ...options.contextLines ?? [], out("comment", options.guidance)];
|
|
298
|
-
if (actions.length === 0) lines.push("No callable actions match.");
|
|
299
|
-
for (const [group, entries] of groups) {
|
|
300
|
-
const groupStyle = options.sort === "domain" ? options.domainStyles?.get(group) ?? "accent" : group === "official" ? "label" : "accent";
|
|
301
|
-
if (group) lines.push("", `${out(groupStyle, group)} ${out("dim", `(${entries.length})`)}`);
|
|
302
|
-
for (const entry of entries) {
|
|
303
|
-
const fieldNames = humanFieldNames(entry);
|
|
304
|
-
const fields = fieldNames.length ? ` ${out("dim", `fields=${fieldNames.join(",")}`)}` : "";
|
|
305
|
-
const cases = entry.result_cases?.length ? ` ${out("dim", `cases=${entry.result_cases.join(",")}`)}` : "";
|
|
306
|
-
const description = entry.description ? ` ${out("comment", `\u2014 ${entry.description}`)}` : "";
|
|
307
|
-
const source = ` ${out("dim", `[${entry.source}]`)}`;
|
|
308
|
-
const risk = entry.capabilities.length ? ` ${out("dim", `risk=${entry.capabilities.join(",")}`)}` : "";
|
|
309
|
-
const nameStyle = options.domainStyles?.get(actionDomain(entry)) ?? "cmd";
|
|
310
|
-
lines.push(` ${out(nameStyle, options.displayName?.(entry) ?? entry.name)}${source}${fields}${cases}${risk}${description}`);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
return lines.join("\n");
|
|
314
|
-
}
|
|
315
|
-
function renderHumanActionExample(entry, adapter, target, executable) {
|
|
316
|
-
const node = authoredExampleNode(entry.examples, void 0, entry.schema);
|
|
317
|
-
if (!node) return void 0;
|
|
318
|
-
const out = (style, text) => color(style, text, { stream: process.stdout });
|
|
319
|
-
const command = actionExampleCommand(entry, adapter, target, executable);
|
|
320
|
-
if (!command) return void 0;
|
|
321
|
-
const lines = [
|
|
322
|
-
out("label", "Example call:"),
|
|
323
|
-
` ${out("cmd", command)}`,
|
|
324
|
-
out("label", "Recipe node:"),
|
|
325
|
-
...JSON.stringify(node, null, 2).split("\n").map((line) => ` ${line}`)
|
|
326
|
-
];
|
|
327
|
-
return lines.join("\n");
|
|
328
|
-
}
|
|
329
|
-
function actionExampleCommand(entry, adapter, target, executable, preferredValues) {
|
|
330
|
-
const node = authoredExampleNode(entry.examples, preferredValues, entry.schema);
|
|
331
|
-
if (!node) return void 0;
|
|
332
|
-
const commandName = executable.endsWith("/mm-harness") ? "mm-harness" : executable;
|
|
333
|
-
const args = entry.fields.flatMap(
|
|
334
|
-
(field) => Object.hasOwn(node, field) ? [shellQuoteArg(`${field}=${safeActionCallValue(field, node[field])}`)] : []
|
|
335
|
-
);
|
|
336
|
-
return [
|
|
337
|
-
shellQuoteArg(commandName),
|
|
338
|
-
"call",
|
|
339
|
-
shellQuoteArg(entry.name),
|
|
340
|
-
...args,
|
|
341
|
-
"--adapter",
|
|
342
|
-
adapter,
|
|
343
|
-
"--target",
|
|
344
|
-
shellQuoteArg(target)
|
|
345
|
-
].join(" ");
|
|
346
|
-
}
|
|
347
|
-
function authoredExampleNode(examples, preferredValues, schema) {
|
|
348
|
-
if (!Array.isArray(examples)) return void 0;
|
|
349
|
-
if (preferredValues && Object.keys(preferredValues).length > 0) {
|
|
350
|
-
const normalizedValues = normalizePreferredValues(preferredValues, schema);
|
|
351
|
-
const nodes = examples.filter(isRecord);
|
|
352
|
-
if (nodes.length === 0) return void 0;
|
|
353
|
-
const ranked = nodes.map((node) => ({
|
|
354
|
-
node,
|
|
355
|
-
completeness: Object.keys(node).filter((name) => !["action", "intent", "next"].includes(name)).length,
|
|
356
|
-
score: Object.entries(normalizedValues).reduce((score, [name, value]) => {
|
|
357
|
-
if (!Object.hasOwn(node, name)) return score;
|
|
358
|
-
return score + (sameActionValue(name, node[name], value) ? 3 : -1);
|
|
359
|
-
}, 0)
|
|
360
|
-
})).sort(
|
|
361
|
-
(left, right) => right.score - left.score || right.completeness - left.completeness
|
|
362
|
-
);
|
|
363
|
-
return { ...ranked[0].node, ...normalizedValues };
|
|
364
|
-
}
|
|
365
|
-
for (const example of examples) {
|
|
366
|
-
if (isRecord(example)) return example;
|
|
367
|
-
}
|
|
368
|
-
return void 0;
|
|
369
|
-
}
|
|
370
|
-
function normalizePreferredValues(preferredValues, schema) {
|
|
371
|
-
const properties = isRecord(schema) && isRecord(schema.properties) ? schema.properties : {};
|
|
372
|
-
return Object.fromEntries(
|
|
373
|
-
Object.entries(preferredValues).flatMap(([name, value]) => {
|
|
374
|
-
const property = isRecord(properties[name]) ? properties[name] : void 0;
|
|
375
|
-
if (property && !matchesSchemaType(property.type, value)) return [];
|
|
376
|
-
const values = property && Array.isArray(property.enum) ? property.enum : void 0;
|
|
377
|
-
if (!values) {
|
|
378
|
-
return [[name, value]];
|
|
379
|
-
}
|
|
380
|
-
const compatibleValue = values.find(
|
|
381
|
-
(candidate) => sameActionValue(name, candidate, value)
|
|
382
|
-
);
|
|
383
|
-
if (compatibleValue !== void 0) return [[name, compatibleValue]];
|
|
384
|
-
const strings = values.filter((candidate) => typeof candidate === "string");
|
|
385
|
-
const suggestion = typeof value === "string" ? closest(value, strings) : void 0;
|
|
386
|
-
return suggestion === void 0 ? [] : [[name, suggestion]];
|
|
387
|
-
})
|
|
388
|
-
);
|
|
389
|
-
}
|
|
390
|
-
function matchesSchemaType(type, value) {
|
|
391
|
-
const types = Array.isArray(type) ? type : [type];
|
|
392
|
-
if (types.every((candidate) => typeof candidate !== "string")) return true;
|
|
393
|
-
return types.some((candidate) => {
|
|
394
|
-
if (candidate === "null") return value === null;
|
|
395
|
-
if (candidate === "array") return Array.isArray(value);
|
|
396
|
-
if (candidate === "object") return isRecord(value);
|
|
397
|
-
if (candidate === "integer") return typeof value === "number" && Number.isInteger(value);
|
|
398
|
-
return typeof value === candidate;
|
|
399
|
-
});
|
|
400
|
-
}
|
|
401
|
-
function sameActionValue(name, left, right) {
|
|
402
|
-
if (name === "state") {
|
|
403
|
-
const canonicalState = (value) => {
|
|
404
|
-
if (value === "present") return "open";
|
|
405
|
-
if (value === "absent") return "none";
|
|
406
|
-
return value;
|
|
407
|
-
};
|
|
408
|
-
left = canonicalState(left);
|
|
409
|
-
right = canonicalState(right);
|
|
410
|
-
}
|
|
411
|
-
const scalar = (value) => typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
412
|
-
if (scalar(left) && scalar(right)) return String(left) === String(right);
|
|
413
|
-
return JSON.stringify(left) === JSON.stringify(right);
|
|
414
|
-
}
|
|
415
|
-
function actionCallValue(value) {
|
|
416
|
-
return typeof value === "string" ? value : JSON.stringify(value);
|
|
417
|
-
}
|
|
418
|
-
function safeActionCallValue(field, value) {
|
|
419
|
-
if (isSensitiveKey(field)) return `<${field}>`;
|
|
420
|
-
return actionCallValue(redactStructuredValue(value));
|
|
421
|
-
}
|
|
422
|
-
function humanFieldNames(entry) {
|
|
423
|
-
const schema = isRecord(entry.schema) ? entry.schema : void 0;
|
|
424
|
-
const properties = schema && isRecord(schema.properties) ? schema.properties : void 0;
|
|
425
|
-
if (!properties) return entry.fields;
|
|
426
|
-
return entry.fields.map((field) => {
|
|
427
|
-
const property = properties[field];
|
|
428
|
-
if (!isRecord(property) || !Array.isArray(property.enum)) return field;
|
|
429
|
-
const values = property.enum.filter((value) => typeof value === "string" || typeof value === "number" || typeof value === "boolean");
|
|
430
|
-
return values.length > 0 ? `${field}=${values.join("|")}` : field;
|
|
431
|
-
});
|
|
432
|
-
}
|
|
433
|
-
function actionDomainGroup(entry) {
|
|
434
|
-
if (entry.kind === "official") return "official";
|
|
435
|
-
const match = /^metamask[.]([^.]+)[.]/u.exec(entry.name);
|
|
436
|
-
return match ? `metamask \xB7 ${match[1]}` : "custom";
|
|
437
|
-
}
|
|
438
|
-
function describeManifestActions(manifest, actionSources = /* @__PURE__ */ new Map()) {
|
|
439
|
-
const manifestRecord = isRecord(manifest) ? manifest : {};
|
|
440
|
-
const actions = isRecord(manifestRecord.actions) ? manifestRecord.actions : {};
|
|
441
|
-
return Object.entries(actions).map(
|
|
442
|
-
([name, metadata]) => describeManifestAction(
|
|
443
|
-
name,
|
|
444
|
-
OFFICIAL_ACTIONS.has(name) ? "official" : "custom",
|
|
445
|
-
metadata,
|
|
446
|
-
actionSources.get(name)
|
|
447
|
-
)
|
|
448
|
-
);
|
|
449
|
-
}
|
|
450
|
-
function describeManifestAction(name, kind, metadata, source) {
|
|
451
|
-
const record = isRecord(metadata) ? metadata : {};
|
|
452
|
-
const schema = record.schema;
|
|
453
|
-
const schemaRecord = isRecord(schema) ? schema : {};
|
|
454
|
-
const properties = isRecord(schemaRecord.properties) ? Object.keys(schemaRecord.properties).filter((field) => field !== "action" && field !== "next").sort() : [];
|
|
455
|
-
return {
|
|
456
|
-
name,
|
|
457
|
-
kind,
|
|
458
|
-
category: actionCategory(name, ["metamask"]),
|
|
459
|
-
description: typeof record.description === "string" ? record.description : "",
|
|
460
|
-
fields: properties,
|
|
461
|
-
schema,
|
|
462
|
-
examples: record.examples,
|
|
463
|
-
...Array.isArray(record.result_cases) ? { result_cases: record.result_cases.filter((value) => typeof value === "string") } : {},
|
|
464
|
-
source: source?.name ?? (kind === "official" ? "official" : "metamask"),
|
|
465
|
-
sourceTier: source?.tier ?? (kind === "official" ? "official" : "canonical"),
|
|
466
|
-
sourceManifest: source?.manifestPath ?? "",
|
|
467
|
-
shadows: source?.shadows ?? [],
|
|
468
|
-
capabilities: [.../* @__PURE__ */ new Set([
|
|
469
|
-
...Array.isArray(record.execution_capabilities) ? record.execution_capabilities.filter(
|
|
470
|
-
(value) => typeof value === "string"
|
|
471
|
-
) : [],
|
|
472
|
-
...kind === "official" ? officialRecipeActionCapabilities(name) : metaMaskActionExecutionCapabilities(name)
|
|
473
|
-
])]
|
|
474
|
-
};
|
|
475
|
-
}
|
|
476
|
-
export {
|
|
477
|
-
ACTION_MATRIX_ADAPTERS,
|
|
478
|
-
actionDomain,
|
|
479
|
-
actionExampleCommand,
|
|
480
|
-
actionLibraryContextArgs,
|
|
481
|
-
describeManifestActions,
|
|
482
|
-
handleActions,
|
|
483
|
-
renderHumanActionCatalog,
|
|
484
|
-
renderHumanActionExample,
|
|
485
|
-
renderHumanActionMatrix,
|
|
486
|
-
resolveActionCapabilityMatrix,
|
|
487
|
-
summarizeDescribedAction
|
|
488
|
-
};
|