@playdrop/playdrop-cli 0.12.1 → 0.12.2

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.
@@ -0,0 +1,215 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var instrument_evidence_exports = {};
19
+ __export(instrument_evidence_exports, {
20
+ ClaudeChromeScreenshotStreamParser: () => ClaudeChromeScreenshotStreamParser,
21
+ INSTRUMENT_EVIDENCE_NAMES: () => INSTRUMENT_EVIDENCE_NAMES
22
+ });
23
+ module.exports = __toCommonJS(instrument_evidence_exports);
24
+ const INSTRUMENT_EVIDENCE_NAMES = [
25
+ "first-frame",
26
+ "core",
27
+ "win",
28
+ "loss"
29
+ ];
30
+ const SCREENSHOT_ID_PATTERN = /^ss_[A-Za-z0-9_-]+$/;
31
+ const SCREENSHOT_ID_IN_TEXT_PATTERN = /\bID:\s*(ss_[A-Za-z0-9_-]+)\b/g;
32
+ const MAX_STREAM_LINE_LENGTH = 20 * 1024 * 1024;
33
+ function asRecord(value) {
34
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
35
+ }
36
+ function readPositiveInteger(value) {
37
+ const parsed = typeof value === "number" ? value : Number(value);
38
+ return Number.isInteger(parsed) && parsed > 0 ? parsed : null;
39
+ }
40
+ function collectScreenshotTabIds(toolName, input) {
41
+ if (toolName === "mcp__claude-in-chrome__computer") {
42
+ const tabId = input["action"] === "screenshot" ? readPositiveInteger(input["tabId"]) : null;
43
+ return tabId === null ? [] : [tabId];
44
+ }
45
+ if (toolName !== "mcp__claude-in-chrome__browser_batch" || !Array.isArray(input["actions"])) {
46
+ return [];
47
+ }
48
+ const tabIds = [];
49
+ for (const value of input["actions"]) {
50
+ const action = asRecord(value);
51
+ const actionInput = asRecord(action?.["input"]);
52
+ if (action?.["name"] !== "computer" || actionInput?.["action"] !== "screenshot") {
53
+ continue;
54
+ }
55
+ const tabId = readPositiveInteger(actionInput["tabId"]);
56
+ if (tabId !== null) {
57
+ tabIds.push(tabId);
58
+ }
59
+ }
60
+ return tabIds;
61
+ }
62
+ function readScreenshotDimensions(text) {
63
+ const match = text.match(/captured screenshot \((\d+)x(\d+),\s*(?:jpeg|png)\)/i);
64
+ if (!match) {
65
+ return { width: null, height: null };
66
+ }
67
+ return {
68
+ width: readPositiveInteger(match[1]),
69
+ height: readPositiveInteger(match[2])
70
+ };
71
+ }
72
+ class ClaudeChromeScreenshotStreamParser {
73
+ onScreenshot;
74
+ buffer = "";
75
+ screenshotTabsByToolUseId = /* @__PURE__ */ new Map();
76
+ emittedScreenshotIds = /* @__PURE__ */ new Set();
77
+ constructor(onScreenshot) {
78
+ this.onScreenshot = onScreenshot;
79
+ }
80
+ push(chunk) {
81
+ if (!chunk) {
82
+ return 0;
83
+ }
84
+ this.buffer += chunk;
85
+ if (this.buffer.length > MAX_STREAM_LINE_LENGTH && !this.buffer.includes("\n")) {
86
+ throw new Error("claude_stream_json_line_too_large");
87
+ }
88
+ let emitted = 0;
89
+ for (; ; ) {
90
+ const newlineIndex = this.buffer.indexOf("\n");
91
+ if (newlineIndex < 0) {
92
+ break;
93
+ }
94
+ const line = this.buffer.slice(0, newlineIndex);
95
+ this.buffer = this.buffer.slice(newlineIndex + 1);
96
+ emitted += this.processLine(line);
97
+ }
98
+ return emitted;
99
+ }
100
+ finish() {
101
+ const line = this.buffer;
102
+ this.buffer = "";
103
+ return line.trim() ? this.processLine(line) : 0;
104
+ }
105
+ processLine(line) {
106
+ const trimmed = line.trim();
107
+ if (!trimmed) {
108
+ return 0;
109
+ }
110
+ let payload;
111
+ try {
112
+ const parsed = JSON.parse(trimmed);
113
+ const record = asRecord(parsed);
114
+ if (!record) {
115
+ throw new Error("invalid_claude_stream_json");
116
+ }
117
+ payload = record;
118
+ } catch (error) {
119
+ throw new Error(`invalid_claude_stream_json:${error instanceof Error ? error.message : String(error)}`);
120
+ }
121
+ if (payload["type"] === "assistant") {
122
+ this.recordToolUse(payload);
123
+ return 0;
124
+ }
125
+ if (payload["type"] === "user") {
126
+ return this.recordToolResults(payload);
127
+ }
128
+ return 0;
129
+ }
130
+ recordToolUse(payload) {
131
+ const message = asRecord(payload["message"]);
132
+ const content = Array.isArray(message?.["content"]) ? message["content"] : [];
133
+ for (const value of content) {
134
+ const item = asRecord(value);
135
+ const id = typeof item?.["id"] === "string" ? item["id"].trim() : "";
136
+ const name = typeof item?.["name"] === "string" ? item["name"].trim() : "";
137
+ const input = asRecord(item?.["input"]);
138
+ if (item?.["type"] !== "tool_use" || !id || !name || !input) {
139
+ continue;
140
+ }
141
+ const tabIds = collectScreenshotTabIds(name, input);
142
+ if (tabIds.length > 0) {
143
+ this.screenshotTabsByToolUseId.set(id, tabIds);
144
+ }
145
+ }
146
+ }
147
+ recordToolResults(payload) {
148
+ const message = asRecord(payload["message"]);
149
+ const content = Array.isArray(message?.["content"]) ? message["content"] : [];
150
+ let emitted = 0;
151
+ for (const value of content) {
152
+ const toolResult = asRecord(value);
153
+ if (toolResult?.["type"] !== "tool_result") {
154
+ continue;
155
+ }
156
+ const toolUseId = typeof toolResult["tool_use_id"] === "string" ? toolResult["tool_use_id"].trim() : "";
157
+ const resultContent = Array.isArray(toolResult["content"]) ? toolResult["content"] : [];
158
+ const tabIds = this.screenshotTabsByToolUseId.get(toolUseId) ?? [];
159
+ const screenshotIds = [];
160
+ let dimensions = { width: null, height: null };
161
+ for (const resultValue of resultContent) {
162
+ const resultItem = asRecord(resultValue);
163
+ if (resultItem?.["type"] === "text" && typeof resultItem["text"] === "string") {
164
+ const text = resultItem["text"];
165
+ dimensions = readScreenshotDimensions(text);
166
+ for (const match of text.matchAll(SCREENSHOT_ID_IN_TEXT_PATTERN)) {
167
+ const screenshotId = match[1];
168
+ if (screenshotId && SCREENSHOT_ID_PATTERN.test(screenshotId)) {
169
+ screenshotIds.push(screenshotId);
170
+ }
171
+ }
172
+ }
173
+ }
174
+ const images = resultContent.map(asRecord).filter((item) => item?.["type"] === "image");
175
+ for (let imageIndex = 0; imageIndex < images.length; imageIndex += 1) {
176
+ const resultItem = images[imageIndex];
177
+ const screenshotId = screenshotIds[imageIndex];
178
+ if (!screenshotId) {
179
+ continue;
180
+ }
181
+ const source = asRecord(resultItem?.["source"]);
182
+ const mediaType = source?.["media_type"];
183
+ const dataBase64 = typeof source?.["data"] === "string" ? source["data"] : "";
184
+ const tabId = tabIds[imageIndex] ?? null;
185
+ if (mediaType !== "image/jpeg" && mediaType !== "image/png" || !dataBase64) {
186
+ throw new Error(`invalid_claude_screenshot_payload:${screenshotId}`);
187
+ }
188
+ if (tabId === null) {
189
+ throw new Error(`claude_screenshot_tab_attribution_missing:${screenshotId}`);
190
+ }
191
+ if (this.emittedScreenshotIds.has(screenshotId)) {
192
+ continue;
193
+ }
194
+ this.emittedScreenshotIds.add(screenshotId);
195
+ this.onScreenshot({
196
+ screenshotId,
197
+ tabId,
198
+ toolUseId,
199
+ mediaType,
200
+ dataBase64,
201
+ width: dimensions.width,
202
+ height: dimensions.height
203
+ });
204
+ emitted += 1;
205
+ }
206
+ this.screenshotTabsByToolUseId.delete(toolUseId);
207
+ }
208
+ return emitted;
209
+ }
210
+ }
211
+ // Annotate the CommonJS export names for ESM import in node:
212
+ 0 && (module.exports = {
213
+ ClaudeChromeScreenshotStreamParser,
214
+ INSTRUMENT_EVIDENCE_NAMES
215
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playdrop/playdrop-cli",
3
- "version": "0.12.1",
3
+ "version": "0.12.2",
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": {