Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -263,3 +263,7 @@ development/generate-lavamoat-policies.js @MetaMask/extension-platfo
# Background Process
app/scripts/lib/createMetaRPCHandler.js @MetaMask/extension-platform
app/scripts/lib/metaRPCClientFactory.ts @MetaMask/extension-platform
app/scripts/lib/setup-initial-state-hooks.* @MetaMask/extension-platform

# UI Bootstrap
/ui/index.js @MetaMask/extension-platform
5 changes: 5 additions & 0 deletions .metamaskrc.dist
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ BLOCKAID_PUBLIC_KEY=
; Enables the Settings Page - Developer Options
; ENABLE_SETTINGS_PAGE_DEV_OPTIONS=true

; Enables agentic/CDP automation hooks on `globalThis.stateHooks` in debug builds.
; Requires `METAMASK_DEBUG=true`. Only set this when running the CDP automation
; harness — not needed for manual QA or general local development.
; METAMASK_AGENTIC_HOOKS=true

; SENTRY CONFIGURATION
; SENTRY_DSN - For production builds only (do NOT use in development)
; SENTRY_DSN_DEV - For local dev and one-off QA testing (sends to 'test-metamask' project)
Expand Down
4 changes: 4 additions & 0 deletions builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,10 @@ env:
# Modified in <root>/development/build/scripts.js:@setEnvironmentVariables
# Also see DEBUG and NODE_DEBUG
- METAMASK_DEBUG: false
# Enables agentic/CDP automation hooks on `globalThis.stateHooks`
# (see `ui/index.js`). Requires `METAMASK_DEBUG=true` to take effect.
# Off by default so manual QA debug builds do not expose the automation surface.
- METAMASK_AGENTIC_HOOKS: false
# Modified in <root>/development/build/scripts.js:@setEnvironmentVariables
- IN_TEST
# Modified in <root>/development/build/scripts.js:@setEnvironmentVariables
Expand Down
16 changes: 11 additions & 5 deletions types/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,15 +324,21 @@ type StateHooks = {
*/
resetWebVitalsMetrics?: () => void;

// Agentic dev hooks (METAMASK_DEBUG only) — expose internals for CDP automation.
// Typed as `unknown` because these are untyped debug-only entry points consumed
// by CDP automation scripts that perform their own runtime checks.
store?: unknown;
// Agentic dev hooks — curated surface for CDP automation.
// Present only when both METAMASK_DEBUG and METAMASK_AGENTIC_HOOKS are true
// at build time. Typed loosely because these are debug-only entry points
// consumed by CDP automation scripts that perform their own runtime checks.
store?: {
getState: () => unknown;
subscribe: (listener: () => void) => () => void;
};
submitRequestToBackground?: (
method: string,
args?: unknown[],
) => Promise<unknown>;
getPerpsStreamManager?: () => unknown;
services?: {
perps: unknown;
};
};

export declare global {
Expand Down
37 changes: 32 additions & 5 deletions ui/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -463,11 +463,38 @@ function setupStateHooks(store) {
exposeLongTaskMetricsForTesting();
}

// Agentic dev hooks — expose internals for CDP automation
if (process.env.METAMASK_DEBUG) {
globalThis.stateHooks.store = store;
globalThis.stateHooks.submitRequestToBackground = submitRequestToBackground;
globalThis.stateHooks.getPerpsStreamManager = getPerpsStreamManager;
// Agentic dev hooks — curated surface for CDP automation.
// Requires METAMASK_DEBUG AND METAMASK_AGENTIC_HOOKS. Both are compile-time
// constants; DefinePlugin dead-code-eliminates this block in release builds.
if (process.env.METAMASK_DEBUG && process.env.METAMASK_AGENTIC_HOOKS) {
// Background RPC methods allowlisted for agentic automation.
// Additions require PR review — each entry should document its use case.
const AGENTIC_BACKGROUND_METHODS = new Set([
// seed empty — harness team opens a follow-up PR to populate
]);

// Read-only store facade: getState + subscribe, no dispatch.
globalThis.stateHooks.store = {
getState: () => store.getState(),
subscribe: (listener) => store.subscribe(listener),
};

// Allowlisted background RPC — same signature as the real submitRequestToBackground.
globalThis.stateHooks.submitRequestToBackground = (method, args) => {
if (!AGENTIC_BACKGROUND_METHODS.has(method)) {
throw new Error(
`stateHooks.submitRequestToBackground: "${method}" is not in the ` +
`agentic allowlist. Add it to AGENTIC_BACKGROUND_METHODS in ` +
`ui/index.js via PR review.`,
);
}
return submitRequestToBackground(method, args);
};

// UI-side service singletons for agentic automation.
globalThis.stateHooks.services = {
perps: getPerpsStreamManager(),
};
}
}

Expand Down
Loading