chromeflow 0.1.23 → 0.1.25
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.
- package/dist/setup.js +38 -5
- package/dist/tools/browser.js +38 -0
- package/package.json +1 -1
package/dist/setup.js
CHANGED
|
@@ -156,7 +156,16 @@ const CHROMEFLOW_TOOLS = [
|
|
|
156
156
|
"mark_step_done",
|
|
157
157
|
"find_and_highlight",
|
|
158
158
|
"highlight_region",
|
|
159
|
-
"show_guide_panel"
|
|
159
|
+
"show_guide_panel",
|
|
160
|
+
// v0.1.23+
|
|
161
|
+
"switch_to_tab",
|
|
162
|
+
"list_tabs",
|
|
163
|
+
"get_form_fields",
|
|
164
|
+
"scroll_to_element",
|
|
165
|
+
"save_page_state",
|
|
166
|
+
"restore_page_state",
|
|
167
|
+
// v0.1.25+
|
|
168
|
+
"take_and_copy_screenshot"
|
|
160
169
|
].map((t) => `mcp__chromeflow__${t}`);
|
|
161
170
|
function patchSettingsLocalJson(cwd) {
|
|
162
171
|
const claudeDir = join(cwd, ".claude");
|
|
@@ -311,16 +320,40 @@ async function runUninstall() {
|
|
|
311
320
|
}
|
|
312
321
|
console.log("\nDone. Restart Claude Code to complete removal.\n");
|
|
313
322
|
}
|
|
323
|
+
async function fetchLatestClaudeMd() {
|
|
324
|
+
try {
|
|
325
|
+
const res = await fetch("https://unpkg.com/chromeflow@latest/CLAUDE.md");
|
|
326
|
+
if (res.ok) return await res.text();
|
|
327
|
+
} catch {
|
|
328
|
+
}
|
|
329
|
+
return getClaudeMdContent();
|
|
330
|
+
}
|
|
314
331
|
async function runUpdate() {
|
|
315
332
|
const cwd = process.cwd();
|
|
316
333
|
console.log("\nChromeflow Update\n" + "\u2500".repeat(40));
|
|
317
|
-
const
|
|
334
|
+
const freshContent = await fetchLatestClaudeMd();
|
|
335
|
+
const claudeMdPath = join(cwd, "CLAUDE.md");
|
|
336
|
+
let mdResult;
|
|
337
|
+
if (existsSync(claudeMdPath)) {
|
|
338
|
+
const existing = readFileSync(claudeMdPath, "utf8");
|
|
339
|
+
if (existing.includes("# Chromeflow")) {
|
|
340
|
+
const before = existing.slice(0, existing.indexOf("# Chromeflow")).trimEnd();
|
|
341
|
+
writeFileSync(claudeMdPath, (before ? before + "\n\n" : "") + freshContent);
|
|
342
|
+
mdResult = "updated";
|
|
343
|
+
} else {
|
|
344
|
+
writeFileSync(claudeMdPath, existing.trimEnd() + "\n\n" + freshContent);
|
|
345
|
+
mdResult = "appended";
|
|
346
|
+
}
|
|
347
|
+
} else {
|
|
348
|
+
writeFileSync(claudeMdPath, freshContent);
|
|
349
|
+
mdResult = "created";
|
|
350
|
+
}
|
|
318
351
|
if (mdResult === "updated") {
|
|
319
|
-
console.log(`\u2713 Updated chromeflow instructions in ${
|
|
352
|
+
console.log(`\u2713 Updated chromeflow instructions in ${claudeMdPath}`);
|
|
320
353
|
} else if (mdResult === "appended") {
|
|
321
|
-
console.log(`\u2713 Appended chromeflow instructions to ${
|
|
354
|
+
console.log(`\u2713 Appended chromeflow instructions to ${claudeMdPath}`);
|
|
322
355
|
} else {
|
|
323
|
-
console.log(`\u2713 Created ${
|
|
356
|
+
console.log(`\u2713 Created ${claudeMdPath}`);
|
|
324
357
|
}
|
|
325
358
|
const settingsResult = patchSettingsLocalJson(cwd);
|
|
326
359
|
if (settingsResult === "already-present") {
|
package/dist/tools/browser.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { writeFileSync, copyFileSync } from "fs";
|
|
3
|
+
import { tmpdir, homedir } from "os";
|
|
4
|
+
import { join } from "path";
|
|
5
|
+
import { execSync } from "child_process";
|
|
2
6
|
function registerBrowserTools(server, bridge) {
|
|
3
7
|
server.tool(
|
|
4
8
|
"open_page",
|
|
@@ -68,6 +72,40 @@ ${lines.join("\n")}` }]
|
|
|
68
72
|
};
|
|
69
73
|
}
|
|
70
74
|
);
|
|
75
|
+
server.tool(
|
|
76
|
+
"take_and_copy_screenshot",
|
|
77
|
+
`Take a screenshot, copy it to the system clipboard, and save it as a PNG file.
|
|
78
|
+
Use this when you need to share, upload, or keep a screenshot outside of Claude.
|
|
79
|
+
The image is always copied to the clipboard so you can immediately paste it anywhere.
|
|
80
|
+
save_to controls where the file is saved: "downloads" (default) saves to ~/Downloads, "cwd" saves to Claude's current working directory.`,
|
|
81
|
+
{
|
|
82
|
+
save_to: z.enum(["downloads", "cwd"]).optional().describe(`Where to save the PNG file: "downloads" (~/Downloads, default) or "cwd" (Claude's current working directory)`)
|
|
83
|
+
},
|
|
84
|
+
async ({ save_to = "downloads" }) => {
|
|
85
|
+
const response = await bridge.request({ type: "screenshot" });
|
|
86
|
+
if (response.type !== "screenshot_response") throw new Error("Unexpected response from extension");
|
|
87
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
88
|
+
const filename = `chromeflow-${timestamp}.png`;
|
|
89
|
+
const imageBuffer = Buffer.from(response.image, "base64");
|
|
90
|
+
const tmpPath = join(tmpdir(), filename);
|
|
91
|
+
writeFileSync(tmpPath, imageBuffer);
|
|
92
|
+
const savePath = save_to === "cwd" ? join(process.cwd(), filename) : join(homedir(), "Downloads", filename);
|
|
93
|
+
copyFileSync(tmpPath, savePath);
|
|
94
|
+
let clipboardNote = "";
|
|
95
|
+
try {
|
|
96
|
+
execSync(`osascript -e 'set the clipboard to (read (POSIX file "${tmpPath}") as \xABclass PNGf\xBB)'`);
|
|
97
|
+
clipboardNote = "Copied to clipboard. ";
|
|
98
|
+
} catch {
|
|
99
|
+
clipboardNote = "";
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
content: [
|
|
103
|
+
{ type: "image", data: response.image, mimeType: "image/png" },
|
|
104
|
+
{ type: "text", text: `${clipboardNote}Saved to ${savePath}` }
|
|
105
|
+
]
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
);
|
|
71
109
|
server.tool(
|
|
72
110
|
"clear_overlays",
|
|
73
111
|
"Remove all highlights and callout annotations from the current page. Does NOT remove the guide panel \u2014 the guide panel persists until the next flow starts.",
|
package/package.json
CHANGED