feat(emulate): add mobile device emulation via CDP Emulation domain (#60)

* feat(emulate): add mobile device emulation via CDP Emulation domain

Add `bsk emulate` so agents can debug mobile page behaviour by
emulating a device environment on a session tab:

- Viewport metrics (Emulation.setDeviceMetricsOverride), User-Agent
  (Emulation.setUserAgentOverride, optional accept-language and UA
  client-hints metadata), and touch (Emulation.setTouchEmulationEnabled
  with maxTouchPoints).
- Seven CLI-side device presets (iphone-14, iphone-14-pro-max,
  iphone-se, pixel-7, galaxy-s23, ipad-mini, galaxy-tab-s8) via
  --device; manual flags (--width/--height/--dpr/--mobile/--ua/
  --accept-language/--touch/--max-touch-points) work standalone or
  override individual preset fields.
- `bsk emulate --off` clears every override (clearDeviceMetricsOverride
  + touch disabled + empty UA override) and restores the real
  environment.
- Overrides are per-tab (CDP per-target) and not inherited by new tabs;
  the result JSON carries a note reminding agents to re-apply.

Wire: new tool.emulate method end-to-end (bsk-protocol types + JSON
schemas + Method::ToolEmulate classified BrowserMutation, daemon
forwarding, CLI subcommand, extension tool handler + ChromiumCdp
Emulation wrappers, dispatcher registration), docs in both SKILL.md
copies, and unit tests on every layer.

* refine(emulate): merge per-tab state and align preset override semantics

- extension: remember the applied emulation state per tab and merge each new request onto it field by field before applying, so a later --width/--height no longer resets an earlier preset's dpr/mobile; --off clears the stored state along with the CDP overrides
- extension: cdp_failed errors now note that already-applied overrides were not rolled back and can be reset with --off
- cli: validate width/height pairing and metric requirements on the merged preset+flags result, so --device iphone-14 --width 500 keeps the preset height
- cli: add --no-mobile/--no-touch (conflicting with --mobile/--touch) to turn preset mobile/touch fields back off
- docs: describe the merge behaviour, --no-mobile/--no-touch and --off state clearing in both SKILL.md copies
This commit is contained in:
BB-fat
2026-08-05 18:10:39 +08:00
committed by GitHub
parent 49378d70de
commit 0f264c5df1
21 changed files with 2579 additions and 1 deletions
+57
View File
@@ -565,6 +565,63 @@ export interface RequestHelpResult {
resolved_targets?: ResolvedTarget[];
}
// --------------------------------------------------------------------------
// Device-emulation payloads — tool.emulate (mirror bsk-protocol emulate.rs)
// --------------------------------------------------------------------------
export interface UserAgentBrandVersion {
brand: string;
version: string;
}
/** Mirror of CDP `Emulation.UserAgentMetadata`; all fields optional. */
export interface UserAgentMetadata {
brands?: UserAgentBrandVersion[];
full_version?: string;
platform?: string;
platform_version?: string;
architecture?: string;
model?: string;
mobile?: boolean;
}
/**
* Concrete emulation overrides for one tab. The extension merges each
* request field by field onto the tab's remembered emulation state:
* fields present here overwrite the stored value, absent fields keep
* it, and the merged state is applied as a whole.
*/
export interface EmulateOverrides {
width?: number;
height?: number;
device_scale_factor?: number;
mobile?: boolean;
user_agent?: string;
accept_language?: string;
user_agent_metadata?: UserAgentMetadata;
touch?: boolean;
max_touch_points?: number;
}
export interface EmulateParams {
session_id: string;
tab_id?: number;
/** Clear every emulation override on the tab. Exclusive with `overrides`. */
off?: boolean;
/** Overrides to apply. Required unless `off` is set. */
overrides?: EmulateOverrides;
}
export interface EmulateResult {
tab_id: number;
/** True when overrides were cleared (`off`); false when applied. */
cleared: boolean;
/** Echo of the overrides that were applied. Absent when cleared. */
applied?: EmulateOverrides;
/** Scope note: overrides are per-tab (CDP target), not inherited by new tabs. */
note?: string;
}
// --------------------------------------------------------------------------
// Semantic record payloads — mirror bsk-protocol record.rs (Trace v2)
// --------------------------------------------------------------------------