@playdrop/playdrop-cli 0.12.14 → 0.12.15

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "0.12.8",
3
- "build": 6,
3
+ "build": 7,
4
4
  "runtimeSdkVersion": "0.12.5",
5
5
  "runtimeSdkBuild": 2,
6
6
  "clients": {
@@ -66,7 +66,7 @@ function extensionForMediaType(mediaType) {
66
66
  }
67
67
  function createWorkerInstrumentScreenshotCollector(workspaceDir) {
68
68
  const resolvedWorkspace = node_path_1.default.resolve(workspaceDir);
69
- const parser = new types_1.ClaudeChromeScreenshotStreamParser((screenshot) => {
69
+ const store = (screenshot) => {
70
70
  const buffer = Buffer.from(screenshot.dataBase64, 'base64');
71
71
  if (buffer.length <= 0) {
72
72
  throw new Error(`invalid_claude_screenshot_payload:${screenshot.screenshotId}`);
@@ -89,10 +89,14 @@ function createWorkerInstrumentScreenshotCollector(workspaceDir) {
89
89
  height: screenshot.height,
90
90
  };
91
91
  writeJsonAtomic(screenshotIndexPath(resolvedWorkspace), index);
92
- });
92
+ };
93
+ // Both parsers watch the same stream: their tool names and id namespaces are disjoint, so a
94
+ // session only ever populates the store through the browser integration it actually used.
95
+ const chromeParser = new types_1.ClaudeChromeScreenshotStreamParser(store);
96
+ const playwrightParser = new types_1.PlaywrightMcpScreenshotStreamParser(store);
93
97
  return {
94
- push: (chunk) => parser.push(chunk),
95
- finish: () => parser.finish(),
98
+ push: (chunk) => chromeParser.push(chunk) + playwrightParser.push(chunk),
99
+ finish: () => chromeParser.finish() + playwrightParser.finish(),
96
100
  };
97
101
  }
98
102
  function normalizeEvidenceName(value) {
@@ -68,10 +68,13 @@ export declare function buildClaudeExecArgs(input: {
68
68
  model: string;
69
69
  effort?: string | null;
70
70
  chrome?: boolean;
71
+ playwrightMcp?: boolean;
71
72
  workspaceDir?: string | null;
72
73
  denyReadRoots?: string[] | null;
73
74
  pluginDir?: string | null;
74
75
  }): string[];
76
+ export declare const PLAYWRIGHT_MCP_VERSION = "0.0.78";
77
+ export declare function buildPlaywrightMcpServerConfig(): Record<string, unknown>;
75
78
  export declare function buildClaudePermissionSettings(input?: {
76
79
  workspaceDir?: string | null;
77
80
  denyReadRoots?: string[];
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.DEFAULT_TRANSCRIPT_FLUSH_INTERVAL_MS = exports.DEFAULT_CODEX_LOG_TAIL_CHARS = exports.DEFAULT_WORKER_TOKEN_CAP = exports.DEFAULT_CODEX_TIMEOUT_MS = void 0;
6
+ exports.PLAYWRIGHT_MCP_VERSION = exports.DEFAULT_TRANSCRIPT_FLUSH_INTERVAL_MS = exports.DEFAULT_CODEX_LOG_TAIL_CHARS = exports.DEFAULT_WORKER_TOKEN_CAP = exports.DEFAULT_CODEX_TIMEOUT_MS = void 0;
7
7
  exports.readPositiveEnvInt = readPositiveEnvInt;
8
8
  exports.readEnvBoolean = readEnvBoolean;
9
9
  exports.extractAgentTokenUsage = extractAgentTokenUsage;
@@ -16,6 +16,7 @@ exports.runLoggedProcess = runLoggedProcess;
16
16
  exports.buildCodexExecArgs = buildCodexExecArgs;
17
17
  exports.readCodexSandboxMode = readCodexSandboxMode;
18
18
  exports.buildClaudeExecArgs = buildClaudeExecArgs;
19
+ exports.buildPlaywrightMcpServerConfig = buildPlaywrightMcpServerConfig;
19
20
  exports.buildClaudePermissionSettings = buildClaudePermissionSettings;
20
21
  exports.buildClaudeDeniedPermissionRules = buildClaudeDeniedPermissionRules;
21
22
  exports.buildWorkerChildEnv = buildWorkerChildEnv;
@@ -488,18 +489,23 @@ function buildClaudeExecArgs(input) {
488
489
  if (!model) {
489
490
  throw new Error('agent_task_assignment_model_missing');
490
491
  }
492
+ if (input.chrome && input.playwrightMcp) {
493
+ throw new Error('claude_exec_browser_mode_conflict');
494
+ }
491
495
  const permissionSettings = buildClaudePermissionSettings({
492
496
  workspaceDir: input.workspaceDir,
493
497
  denyReadRoots: input.denyReadRoots ?? [],
494
498
  });
495
- const permissionMode = input.chrome ? 'bypassPermissions' : 'acceptEdits';
499
+ const permissionMode = input.chrome || input.playwrightMcp ? 'bypassPermissions' : 'acceptEdits';
496
500
  const tools = input.chrome
497
501
  ? [...CLAUDE_BASE_TOOL_NAMES, ...CLAUDE_CHROME_TOOL_NAMES].join(',')
498
502
  : CLAUDE_BASE_TOOL_NAMES.join(',');
499
503
  const allowedPermissionRules = buildClaudeAllowedPermissionRules(input.workspaceDir);
500
504
  const allowedTools = input.chrome
501
505
  ? [...allowedPermissionRules, ...CLAUDE_CHROME_TOOL_NAMES]
502
- : allowedPermissionRules;
506
+ : input.playwrightMcp
507
+ ? [...allowedPermissionRules, PLAYWRIGHT_MCP_ALLOWED_TOOL_RULE]
508
+ : allowedPermissionRules;
503
509
  const args = [
504
510
  '-p',
505
511
  '--safe-mode',
@@ -525,6 +531,9 @@ function buildClaudeExecArgs(input) {
525
531
  if (input.chrome) {
526
532
  args.unshift('--chrome');
527
533
  }
534
+ if (input.playwrightMcp) {
535
+ args.push('--mcp-config', JSON.stringify(buildPlaywrightMcpServerConfig()));
536
+ }
528
537
  const pluginDir = typeof input.pluginDir === 'string' ? input.pluginDir.trim() : '';
529
538
  if (pluginDir) {
530
539
  args.push('--plugin-dir', pluginDir);
@@ -543,6 +552,20 @@ const CLAUDE_BASE_TOOL_NAMES = [
543
552
  'Glob',
544
553
  'Grep',
545
554
  ];
555
+ // Pinned deliberately: agent-CLI and MCP versions on workers only change through releases,
556
+ // never through @latest drift (see the 2026-07-13 auto-update incident).
557
+ exports.PLAYWRIGHT_MCP_VERSION = '0.0.78';
558
+ const PLAYWRIGHT_MCP_ALLOWED_TOOL_RULE = 'mcp__playwright';
559
+ function buildPlaywrightMcpServerConfig() {
560
+ return {
561
+ mcpServers: {
562
+ playwright: {
563
+ command: 'npx',
564
+ args: ['-y', `@playwright/mcp@${exports.PLAYWRIGHT_MCP_VERSION}`, '--browser', 'chrome', '--isolated'],
565
+ },
566
+ },
567
+ };
568
+ }
546
569
  const CLAUDE_CHROME_TOOL_NAMES = [
547
570
  'mcp__claude-in-chrome__browser_batch',
548
571
  'mcp__claude-in-chrome__computer',
@@ -2102,7 +2102,7 @@ async function runClaude(input) {
2102
2102
  envName: input.envName,
2103
2103
  });
2104
2104
  const denyReadRoots = resolveClaudeDenyReadRoots(input.workspaceDir);
2105
- const screenshotCollector = input.enableChrome
2105
+ const screenshotCollector = input.enableChrome || input.enablePlaywrightMcp
2106
2106
  ? (0, instrument_evidence_1.createWorkerInstrumentScreenshotCollector)(input.workspaceDir)
2107
2107
  : null;
2108
2108
  const result = await (0, runtime_1.runLoggedProcess)({
@@ -2113,6 +2113,7 @@ async function runClaude(input) {
2113
2113
  denyReadRoots,
2114
2114
  pluginDir: input.taskPluginRoot,
2115
2115
  chrome: input.enableChrome,
2116
+ playwrightMcp: input.enablePlaywrightMcp,
2116
2117
  }),
2117
2118
  cwd: input.workspaceDir,
2118
2119
  env: (0, runtime_1.buildWorkerChildEnv)({
@@ -4090,7 +4091,8 @@ async function startWorker(options = {}) {
4090
4091
  binDir,
4091
4092
  eventDir,
4092
4093
  prompt,
4093
- enableChrome: task.kind === 'GAME_REVIEW' || task.kind === 'GAME_EVAL',
4094
+ enableChrome: false,
4095
+ enablePlaywrightMcp: task.kind === 'GAME_REVIEW' || task.kind === 'GAME_EVAL',
4094
4096
  envName: env,
4095
4097
  workerUsername: username,
4096
4098
  taskId: task.id,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "0.12.8",
3
- "build": 6,
3
+ "build": 7,
4
4
  "runtimeSdkVersion": "0.12.5",
5
5
  "runtimeSdkBuild": 2,
6
6
  "clients": {
@@ -26,6 +26,9 @@ export type InstrumentEvidenceManifest = {
26
26
  controlledTabId: number;
27
27
  captures: Partial<Record<InstrumentEvidenceName, InstrumentEvidenceCapture>>;
28
28
  };
29
+ export declare const PLAYWRIGHT_MCP_SCREENSHOT_TOOL = "mcp__playwright__browser_take_screenshot";
30
+ export declare const PLAYWRIGHT_MCP_CONTROLLED_TAB_ID = 1;
31
+ export declare function isInstrumentScreenshotId(value: string): boolean;
29
32
  export declare class ClaudeChromeScreenshotStreamParser {
30
33
  private readonly onScreenshot;
31
34
  private buffer;
@@ -38,4 +41,17 @@ export declare class ClaudeChromeScreenshotStreamParser {
38
41
  private recordToolUse;
39
42
  private recordToolResults;
40
43
  }
44
+ export declare class PlaywrightMcpScreenshotStreamParser {
45
+ private readonly onScreenshot;
46
+ private buffer;
47
+ private readonly pendingScreenshotToolUseIds;
48
+ private readonly handledToolUseIds;
49
+ private sequence;
50
+ constructor(onScreenshot: (screenshot: ClaudeChromeScreenshot) => void);
51
+ push(chunk: string): number;
52
+ finish(): number;
53
+ private processLine;
54
+ private recordToolUse;
55
+ private recordToolResults;
56
+ }
41
57
  //# sourceMappingURL=instrument-evidence.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"instrument-evidence.d.ts","sourceRoot":"","sources":["../src/instrument-evidence.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,yBAAyB,iDAK5B,CAAC;AAEX,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhF,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,YAAY,GAAG,WAAW,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,IAAI,EAAE,sBAAsB,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,YAAY,GAAG,WAAW,CAAC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,sBAAsB,EAAE,yBAAyB,CAAC,CAAC,CAAC;CAC9E,CAAC;AAmDF,qBAAa,kCAAkC;IAKjC,OAAO,CAAC,QAAQ,CAAC,YAAY;IAJzC,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAA+B;IACzE,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAqB;gBAE7B,YAAY,EAAE,CAAC,UAAU,EAAE,sBAAsB,KAAK,IAAI;IAEvF,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAqB3B,MAAM,IAAI,MAAM;IAMhB,OAAO,CAAC,WAAW;IA0BnB,OAAO,CAAC,aAAa;IAkBrB,OAAO,CAAC,iBAAiB;CAiE1B"}
1
+ {"version":3,"file":"instrument-evidence.d.ts","sourceRoot":"","sources":["../src/instrument-evidence.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,yBAAyB,iDAK5B,CAAC;AAEX,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhF,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,YAAY,GAAG,WAAW,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,IAAI,EAAE,sBAAsB,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,YAAY,GAAG,WAAW,CAAC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,sBAAsB,EAAE,yBAAyB,CAAC,CAAC,CAAC;CAC9E,CAAC;AAMF,eAAO,MAAM,8BAA8B,6CAA6C,CAAC;AACzF,eAAO,MAAM,gCAAgC,IAAI,CAAC;AAGlD,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE/D;AA+CD,qBAAa,kCAAkC;IAKjC,OAAO,CAAC,QAAQ,CAAC,YAAY;IAJzC,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAA+B;IACzE,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAqB;gBAE7B,YAAY,EAAE,CAAC,UAAU,EAAE,sBAAsB,KAAK,IAAI;IAEvF,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAqB3B,MAAM,IAAI,MAAM;IAMhB,OAAO,CAAC,WAAW;IA0BnB,OAAO,CAAC,aAAa;IAkBrB,OAAO,CAAC,iBAAiB;CAiE1B;AAMD,qBAAa,mCAAmC;IAMlC,OAAO,CAAC,QAAQ,CAAC,YAAY;IALzC,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,QAAQ,CAAC,2BAA2B,CAAqB;IACjE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAqB;IACvD,OAAO,CAAC,QAAQ,CAAK;gBAEQ,YAAY,EAAE,CAAC,UAAU,EAAE,sBAAsB,KAAK,IAAI;IAEvF,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAqB3B,MAAM,IAAI,MAAM;IAMhB,OAAO,CAAC,WAAW;IA0BnB,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,iBAAiB;CA8C1B"}
@@ -18,7 +18,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
18
18
  var instrument_evidence_exports = {};
19
19
  __export(instrument_evidence_exports, {
20
20
  ClaudeChromeScreenshotStreamParser: () => ClaudeChromeScreenshotStreamParser,
21
- INSTRUMENT_EVIDENCE_NAMES: () => INSTRUMENT_EVIDENCE_NAMES
21
+ INSTRUMENT_EVIDENCE_NAMES: () => INSTRUMENT_EVIDENCE_NAMES,
22
+ PLAYWRIGHT_MCP_CONTROLLED_TAB_ID: () => PLAYWRIGHT_MCP_CONTROLLED_TAB_ID,
23
+ PLAYWRIGHT_MCP_SCREENSHOT_TOOL: () => PLAYWRIGHT_MCP_SCREENSHOT_TOOL,
24
+ PlaywrightMcpScreenshotStreamParser: () => PlaywrightMcpScreenshotStreamParser,
25
+ isInstrumentScreenshotId: () => isInstrumentScreenshotId
22
26
  });
23
27
  module.exports = __toCommonJS(instrument_evidence_exports);
24
28
  const INSTRUMENT_EVIDENCE_NAMES = [
@@ -30,6 +34,12 @@ const INSTRUMENT_EVIDENCE_NAMES = [
30
34
  const SCREENSHOT_ID_PATTERN = /^ss_[A-Za-z0-9_-]+$/;
31
35
  const SCREENSHOT_ID_IN_TEXT_PATTERN = /\bID:\s*(ss_[A-Za-z0-9_-]+)\b/g;
32
36
  const MAX_STREAM_LINE_LENGTH = 20 * 1024 * 1024;
37
+ const PLAYWRIGHT_MCP_SCREENSHOT_TOOL = "mcp__playwright__browser_take_screenshot";
38
+ const PLAYWRIGHT_MCP_CONTROLLED_TAB_ID = 1;
39
+ const PLAYWRIGHT_SCREENSHOT_ID_PATTERN = /^pw-[1-9][0-9]*$/;
40
+ function isInstrumentScreenshotId(value) {
41
+ return SCREENSHOT_ID_PATTERN.test(value) || PLAYWRIGHT_SCREENSHOT_ID_PATTERN.test(value);
42
+ }
33
43
  function asRecord(value) {
34
44
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
35
45
  }
@@ -208,8 +218,128 @@ class ClaudeChromeScreenshotStreamParser {
208
218
  return emitted;
209
219
  }
210
220
  }
221
+ class PlaywrightMcpScreenshotStreamParser {
222
+ onScreenshot;
223
+ buffer = "";
224
+ pendingScreenshotToolUseIds = /* @__PURE__ */ new Set();
225
+ handledToolUseIds = /* @__PURE__ */ new Set();
226
+ sequence = 0;
227
+ constructor(onScreenshot) {
228
+ this.onScreenshot = onScreenshot;
229
+ }
230
+ push(chunk) {
231
+ if (!chunk) {
232
+ return 0;
233
+ }
234
+ this.buffer += chunk;
235
+ if (this.buffer.length > MAX_STREAM_LINE_LENGTH && !this.buffer.includes("\n")) {
236
+ throw new Error("claude_stream_json_line_too_large");
237
+ }
238
+ let emitted = 0;
239
+ for (; ; ) {
240
+ const newlineIndex = this.buffer.indexOf("\n");
241
+ if (newlineIndex < 0) {
242
+ break;
243
+ }
244
+ const line = this.buffer.slice(0, newlineIndex);
245
+ this.buffer = this.buffer.slice(newlineIndex + 1);
246
+ emitted += this.processLine(line);
247
+ }
248
+ return emitted;
249
+ }
250
+ finish() {
251
+ const line = this.buffer;
252
+ this.buffer = "";
253
+ return line.trim() ? this.processLine(line) : 0;
254
+ }
255
+ processLine(line) {
256
+ const trimmed = line.trim();
257
+ if (!trimmed) {
258
+ return 0;
259
+ }
260
+ let payload;
261
+ try {
262
+ const parsed = JSON.parse(trimmed);
263
+ const record = asRecord(parsed);
264
+ if (!record) {
265
+ throw new Error("invalid_claude_stream_json");
266
+ }
267
+ payload = record;
268
+ } catch (error) {
269
+ throw new Error(`invalid_claude_stream_json:${error instanceof Error ? error.message : String(error)}`);
270
+ }
271
+ if (payload["type"] === "assistant") {
272
+ this.recordToolUse(payload);
273
+ return 0;
274
+ }
275
+ if (payload["type"] === "user") {
276
+ return this.recordToolResults(payload);
277
+ }
278
+ return 0;
279
+ }
280
+ recordToolUse(payload) {
281
+ const message = asRecord(payload["message"]);
282
+ const content = Array.isArray(message?.["content"]) ? message["content"] : [];
283
+ for (const value of content) {
284
+ const item = asRecord(value);
285
+ const id = typeof item?.["id"] === "string" ? item["id"].trim() : "";
286
+ const name = typeof item?.["name"] === "string" ? item["name"].trim() : "";
287
+ if (item?.["type"] !== "tool_use" || !id || name !== PLAYWRIGHT_MCP_SCREENSHOT_TOOL) {
288
+ continue;
289
+ }
290
+ this.pendingScreenshotToolUseIds.add(id);
291
+ }
292
+ }
293
+ recordToolResults(payload) {
294
+ const message = asRecord(payload["message"]);
295
+ const content = Array.isArray(message?.["content"]) ? message["content"] : [];
296
+ let emitted = 0;
297
+ for (const value of content) {
298
+ const toolResult = asRecord(value);
299
+ if (toolResult?.["type"] !== "tool_result") {
300
+ continue;
301
+ }
302
+ const toolUseId = typeof toolResult["tool_use_id"] === "string" ? toolResult["tool_use_id"].trim() : "";
303
+ if (!this.pendingScreenshotToolUseIds.has(toolUseId) || this.handledToolUseIds.has(toolUseId)) {
304
+ continue;
305
+ }
306
+ this.handledToolUseIds.add(toolUseId);
307
+ this.pendingScreenshotToolUseIds.delete(toolUseId);
308
+ const resultContent = Array.isArray(toolResult["content"]) ? toolResult["content"] : [];
309
+ const images = resultContent.map(asRecord).filter((item) => item?.["type"] === "image");
310
+ if (images.length === 0) {
311
+ continue;
312
+ }
313
+ if (images.length > 1) {
314
+ throw new Error(`playwright_screenshot_multiple_images:${toolUseId}`);
315
+ }
316
+ const source = asRecord(images[0]?.["source"]);
317
+ const mediaType = source?.["media_type"];
318
+ const dataBase64 = typeof source?.["data"] === "string" ? source["data"] : "";
319
+ if (mediaType !== "image/jpeg" && mediaType !== "image/png" || !dataBase64) {
320
+ throw new Error(`invalid_playwright_screenshot_payload:${toolUseId}`);
321
+ }
322
+ this.sequence += 1;
323
+ this.onScreenshot({
324
+ screenshotId: `pw-${this.sequence}`,
325
+ tabId: PLAYWRIGHT_MCP_CONTROLLED_TAB_ID,
326
+ toolUseId,
327
+ mediaType,
328
+ dataBase64,
329
+ width: null,
330
+ height: null
331
+ });
332
+ emitted += 1;
333
+ }
334
+ return emitted;
335
+ }
336
+ }
211
337
  // Annotate the CommonJS export names for ESM import in node:
212
338
  0 && (module.exports = {
213
339
  ClaudeChromeScreenshotStreamParser,
214
- INSTRUMENT_EVIDENCE_NAMES
340
+ INSTRUMENT_EVIDENCE_NAMES,
341
+ PLAYWRIGHT_MCP_CONTROLLED_TAB_ID,
342
+ PLAYWRIGHT_MCP_SCREENSHOT_TOOL,
343
+ PlaywrightMcpScreenshotStreamParser,
344
+ isInstrumentScreenshotId
215
345
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playdrop/playdrop-cli",
3
- "version": "0.12.14",
3
+ "version": "0.12.15",
4
4
  "description": "Official Playdrop CLI for publishing browser games, creator apps, and AI-generated game assets on playdrop.ai",
5
5
  "homepage": "https://www.playdrop.ai",
6
6
  "repository": {