/** * * Design §6 orders the chain: 1 local browser → 2 lazy download → 3 MCP * fallback → 4 explicit error + install guidance. Orchestrator decision C3 is * binding on how tiers 3 and 4 are represented here: they are **not a branch * this process can take**. Whether `mcp__playwright__*` is available is harness * state — the CLI is a subprocess and cannot see the caller's tool list — so * the envelope carries BOTH the MCP fallback action and the install * instruction, and the calling LLM picks. Naming the MCP tool explicitly, and * saying where a screenshot taken through it lands, is what keeps the two * options distinguishable; a blob that reads as one undifferentiated warning * would defeat the purpose (C3's "consequence to keep"). * * `installHint` is derived from `installCommandLine()`'s pin so the guidance * and the command that is actually run cannot drift apart. */ import { type ResultEnvelope } from 'peaks-loop-shared/result'; import type { WebOp } from './web-protocol.js'; /** 3 = fall back to MCP and/or install locally; 4 = nothing available. */ export type DegradationTier = 3 | 4; /** * The MCP tool that replaces each op on the fallback path. * * `status` / `stop` / `whoami` have no browser path at all, so they have no MCP * equivalent and no degradation envelope: C2's matrix keeps them working * (`status` reports the disabled flag, `stop` stops a process). The empty * string is that "no fallback exists" answer, and `degradedEnvelope` — the only * caller — says so rather than naming a tool that cannot do the job. * * `login` is empty for the SAME reason, and it is the one browser op where that * is not obvious (S4 R3). No `mcp__playwright__*` tool persists a storage state, * so `browser_navigate` was a dead end for the only verb whose whole purpose is * persistence: an envelope that told a caller to call it would contradict its own * `nextActions`. The machine-readable field now agrees with the human-readable * one. */ export declare const MCP_TOOL_FOR_OP: Record; /** * Design §6 tier-3 wording. Two approved artifacts spell it two ways — the * design says 截图会落根目录, `qa/test-cases/peaks-web.md` §5 quotes * 截图会落项目根目录 as "原文" — so both are carried, rather than picking one and * failing the other's assertion. The second half says it in English for the * same reason. */ export declare const MCP_ROOT_DIR_WARNING = "MCP fallback screenshots land in the project root\uFF08\u622A\u56FE\u4F1A\u843D\u6839\u76EE\u5F55 / \u622A\u56FE\u4F1A\u843D\u9879\u76EE\u6839\u76EE\u5F55\uFF09"; /** The command a user or the LLM would run to get the local path back. */ export declare const INSTALL_HINT = "npx --yes --package playwright@1.63.0 -- playwright install chromium"; export interface DegradedData { readonly tier: DegradationTier; /** Empty when the op has no MCP equivalent (see `MCP_TOOL_FOR_OP`). */ readonly mcpTool: string; readonly installHint: string; /** * The op's own arguments, carried so the fallback is *actionable* (R9). * "Call `mcp__playwright__browser_navigate` instead" is not something a caller * can execute without the URL; `browser_evaluate` for `text`/`metrics` is not * something a caller can execute without the selector. Only string arguments * are carried — they are the op surface, and dropping the rest keeps a * `dispatchId`-shaped value from leaking into a fallback blob. */ readonly args: Readonly>; } /** * One envelope for the whole tier-3/4 branch (C3): `ok:false`, a code, the * fallback tool, the install command, the op's own arguments, and the two things * a caller must know — the local path was skipped and where the MCP path puts * its screenshots. */ export declare function degradedEnvelope(op: WebOp, reason: string, tier?: DegradationTier, opArgs?: Readonly>): ResultEnvelope;