@voila.dev/cliche 0.1.0
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/LICENSE +21 -0
- package/README.md +218 -0
- package/apps/album/src/app.ts +107 -0
- package/apps/album/src/index.html +38 -0
- package/apps/album/src/index.ts +12 -0
- package/apps/album/src/shots.ts +85 -0
- package/apps/album/src/styles.css +66 -0
- package/dist/capture.d.ts +28 -0
- package/dist/capture.d.ts.map +1 -0
- package/dist/capture.js +115 -0
- package/dist/capture.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +107 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/keys.d.ts +10 -0
- package/dist/keys.d.ts.map +1 -0
- package/dist/keys.js +21 -0
- package/dist/keys.js.map +1 -0
- package/dist/mcp.d.ts +19 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +193 -0
- package/dist/mcp.js.map +1 -0
- package/dist/options.d.ts +38 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +91 -0
- package/dist/options.js.map +1 -0
- package/dist/setup.d.ts +11 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +85 -0
- package/dist/setup.js.map +1 -0
- package/dist/skill.d.ts +8 -0
- package/dist/skill.d.ts.map +1 -0
- package/dist/skill.js +13 -0
- package/dist/skill.js.map +1 -0
- package/dist/upload.d.ts +27 -0
- package/dist/upload.d.ts.map +1 -0
- package/dist/upload.js +51 -0
- package/dist/upload.js.map +1 -0
- package/package.json +57 -0
- package/skill/SKILL.md +65 -0
- package/src/capture.ts +85 -0
- package/src/cli.ts +101 -0
- package/src/index.ts +7 -0
- package/src/keys.ts +24 -0
- package/src/mcp.ts +220 -0
- package/src/options.ts +141 -0
- package/src/setup.ts +104 -0
- package/src/skill.ts +14 -0
- package/src/upload.ts +72 -0
package/dist/capture.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
|
|
2
|
+
if (value !== null && value !== void 0) {
|
|
3
|
+
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
4
|
+
var dispose, inner;
|
|
5
|
+
if (async) {
|
|
6
|
+
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
7
|
+
dispose = value[Symbol.asyncDispose];
|
|
8
|
+
}
|
|
9
|
+
if (dispose === void 0) {
|
|
10
|
+
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
11
|
+
dispose = value[Symbol.dispose];
|
|
12
|
+
if (async) inner = dispose;
|
|
13
|
+
}
|
|
14
|
+
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
15
|
+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
|
|
16
|
+
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
17
|
+
}
|
|
18
|
+
else if (async) {
|
|
19
|
+
env.stack.push({ async: true });
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
};
|
|
23
|
+
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
24
|
+
return function (env) {
|
|
25
|
+
function fail(e) {
|
|
26
|
+
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
27
|
+
env.hasError = true;
|
|
28
|
+
}
|
|
29
|
+
var r, s = 0;
|
|
30
|
+
function next() {
|
|
31
|
+
while (r = env.stack.pop()) {
|
|
32
|
+
try {
|
|
33
|
+
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
34
|
+
if (r.dispose) {
|
|
35
|
+
var result = r.dispose.call(r.value);
|
|
36
|
+
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
37
|
+
}
|
|
38
|
+
else s |= 1;
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
fail(e);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
45
|
+
if (env.hasError) throw env.error;
|
|
46
|
+
}
|
|
47
|
+
return next();
|
|
48
|
+
};
|
|
49
|
+
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
50
|
+
var e = new Error(message);
|
|
51
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
|
+
});
|
|
53
|
+
const WAIT_FOR_TIMEOUT_MILLISECONDS = 15_000;
|
|
54
|
+
const WAIT_FOR_POLL_MILLISECONDS = 250;
|
|
55
|
+
// Bun.WebView rejects viewport dimensions above 16384 pixels.
|
|
56
|
+
const MAXIMUM_VIEWPORT_HEIGHT = 16_384;
|
|
57
|
+
function sleep(milliseconds) {
|
|
58
|
+
return new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
59
|
+
}
|
|
60
|
+
async function waitForSelector(view, selector) {
|
|
61
|
+
const deadline = Date.now() + WAIT_FOR_TIMEOUT_MILLISECONDS;
|
|
62
|
+
const probe = `!!document.querySelector(${JSON.stringify(selector)})`;
|
|
63
|
+
while (!(await view.evaluate(probe))) {
|
|
64
|
+
if (Date.now() > deadline) {
|
|
65
|
+
throw new Error(`Timed out after ${WAIT_FOR_TIMEOUT_MILLISECONDS}ms waiting for ${selector}`);
|
|
66
|
+
}
|
|
67
|
+
await sleep(WAIT_FOR_POLL_MILLISECONDS);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/** Screenshot a page with Bun.WebView and write it to `options.out` as PNG. */
|
|
71
|
+
export async function capture(options) {
|
|
72
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
73
|
+
try {
|
|
74
|
+
const viewport = options.viewport ?? { width: 1440, height: 900 };
|
|
75
|
+
const view = __addDisposableResource(env_1, new Bun.WebView(viewport), true);
|
|
76
|
+
const localStorageEntries = Object.entries(options.localStorage ?? {});
|
|
77
|
+
if (localStorageEntries.length > 0) {
|
|
78
|
+
// localStorage is origin-scoped, so land on the origin (any page, a login
|
|
79
|
+
// redirect is fine) to seed the entries before loading the target.
|
|
80
|
+
await view.navigate(new URL(options.url).origin);
|
|
81
|
+
for (const [key, value] of localStorageEntries) {
|
|
82
|
+
await view.evaluate(`localStorage.setItem(${JSON.stringify(key)}, ${JSON.stringify(value)})`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
await view.navigate(options.url);
|
|
86
|
+
if (options.waitFor !== undefined) {
|
|
87
|
+
await waitForSelector(view, options.waitFor);
|
|
88
|
+
}
|
|
89
|
+
// A fixed delay for fonts, images and entrance animations: dev servers keep
|
|
90
|
+
// an HMR socket open, so there is no network-idle moment to wait for.
|
|
91
|
+
await sleep(options.settleMilliseconds ?? 1500);
|
|
92
|
+
if (options.fullPage === true) {
|
|
93
|
+
const pageHeight = await view.evaluate("Math.max(document.documentElement.scrollHeight, document.body.scrollHeight)");
|
|
94
|
+
if (pageHeight > viewport.height) {
|
|
95
|
+
await view.resize(viewport.width, Math.min(pageHeight, MAXIMUM_VIEWPORT_HEIGHT));
|
|
96
|
+
await sleep(400);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (options.scrollTo !== undefined) {
|
|
100
|
+
await view.scrollTo(options.scrollTo);
|
|
101
|
+
await sleep(300);
|
|
102
|
+
}
|
|
103
|
+
await Bun.write(options.out, await view.screenshot());
|
|
104
|
+
}
|
|
105
|
+
catch (e_1) {
|
|
106
|
+
env_1.error = e_1;
|
|
107
|
+
env_1.hasError = true;
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
const result_1 = __disposeResources(env_1);
|
|
111
|
+
if (result_1)
|
|
112
|
+
await result_1;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=capture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture.js","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
3
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
4
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
5
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
6
|
+
});
|
|
7
|
+
}
|
|
8
|
+
return path;
|
|
9
|
+
};
|
|
10
|
+
import { capture } from "./capture.js";
|
|
11
|
+
import { runMcpServer } from "./mcp.js";
|
|
12
|
+
import { parseCommand } from "./options.js";
|
|
13
|
+
import { setup } from "./setup.js";
|
|
14
|
+
import { installSkill } from "./skill.js";
|
|
15
|
+
import { upload } from "./upload.js";
|
|
16
|
+
const HELP = `cliche — take a cliché of any page and get a shareable URL.
|
|
17
|
+
|
|
18
|
+
Usage:
|
|
19
|
+
cliche <url> <out.png> [options] Screenshot a page.
|
|
20
|
+
cliche <url> <out.png> --upload …and upload it, printing its URL.
|
|
21
|
+
cliche upload [--prefix pr-123] <files> Upload images, printing their URLs.
|
|
22
|
+
cliche mcp Serve the tools over MCP (stdio).
|
|
23
|
+
cliche setup [--bucket name] Create an R2 bucket via wrangler and
|
|
24
|
+
write the S3 config to .env.
|
|
25
|
+
cliche album [--port 4949] Browse the bucket as a photo album.
|
|
26
|
+
cliche skill Install the PR-screenshots skill into
|
|
27
|
+
.claude/skills/ (Claude Code).
|
|
28
|
+
|
|
29
|
+
Capture options:
|
|
30
|
+
--viewport <WxH> Viewport, default 1440x900 (390x844 for mobile).
|
|
31
|
+
--wait-for <css> Wait for a selector before shooting (15s max).
|
|
32
|
+
--scroll-to <css> Scroll a selector into view before shooting.
|
|
33
|
+
--settle <ms> Let the page settle after load, default 1500.
|
|
34
|
+
--full-page Grow the viewport to the full page height.
|
|
35
|
+
--local-storage key=value Seed localStorage on the target origin
|
|
36
|
+
(repeatable; e.g. a session token).
|
|
37
|
+
|
|
38
|
+
Upload options:
|
|
39
|
+
--prefix <name> Object key prefix, e.g. pr-123.
|
|
40
|
+
--markdown Print  lines instead of URLs.
|
|
41
|
+
|
|
42
|
+
Upload configuration (standard Bun.S3Client environment variables):
|
|
43
|
+
S3_BUCKET, S3_ENDPOINT, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY (or AWS_*)
|
|
44
|
+
CLICHE_PUBLIC_URL Public base URL of the bucket (custom domain).
|
|
45
|
+
|
|
46
|
+
URLs go to stdout, progress to stderr. Ouistiti !`;
|
|
47
|
+
function printUploads(uploaded, markdown) {
|
|
48
|
+
console.log(uploaded.map((entry) => (markdown ? entry.markdown : entry.url)).join("\n"));
|
|
49
|
+
}
|
|
50
|
+
async function main() {
|
|
51
|
+
const command = parseCommand(Bun.argv.slice(2));
|
|
52
|
+
switch (command.kind) {
|
|
53
|
+
case "help":
|
|
54
|
+
console.log(HELP);
|
|
55
|
+
return;
|
|
56
|
+
case "mcp":
|
|
57
|
+
await runMcpServer();
|
|
58
|
+
return;
|
|
59
|
+
case "skill": {
|
|
60
|
+
const target = await installSkill();
|
|
61
|
+
console.error(`Installed the PR-screenshots skill at ${target}`);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
case "setup":
|
|
65
|
+
await setup(command.bucket);
|
|
66
|
+
return;
|
|
67
|
+
case "album": {
|
|
68
|
+
if (command.port !== undefined)
|
|
69
|
+
process.env.PORT = String(command.port);
|
|
70
|
+
// Dynamic with a computed specifier so tsc ships it untouched: the album
|
|
71
|
+
// is TS + HTML imports that Bun resolves at runtime from the package.
|
|
72
|
+
const albumEntry = "../apps/album/src/index.ts";
|
|
73
|
+
await import(__rewriteRelativeImportExtension(albumEntry));
|
|
74
|
+
const url = `http://localhost:${process.env.PORT ?? 4949}`;
|
|
75
|
+
const opener = process.platform === "darwin" ? "open" : "xdg-open";
|
|
76
|
+
Bun.spawn([opener, url], { stdout: "ignore", stderr: "ignore" });
|
|
77
|
+
// Keep the process alive for the server.
|
|
78
|
+
await new Promise(() => { });
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
case "upload": {
|
|
82
|
+
const uploaded = await upload({
|
|
83
|
+
files: command.files,
|
|
84
|
+
...(command.prefix === undefined ? {} : { prefix: command.prefix }),
|
|
85
|
+
});
|
|
86
|
+
printUploads(uploaded, command.markdown);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
case "capture": {
|
|
90
|
+
await capture(command.capture);
|
|
91
|
+
console.error(`Captured ${command.capture.url} -> ${command.capture.out}`);
|
|
92
|
+
if (command.upload) {
|
|
93
|
+
const uploaded = await upload({
|
|
94
|
+
files: [command.capture.out],
|
|
95
|
+
...(command.prefix === undefined ? {} : { prefix: command.prefix }),
|
|
96
|
+
});
|
|
97
|
+
printUploads(uploaded, command.markdown);
|
|
98
|
+
}
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
main().catch((error) => {
|
|
104
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
105
|
+
process.exit(1);
|
|
106
|
+
});
|
|
107
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { capture } from "./capture.ts";
|
|
2
|
+
export type { CaptureOptions, Viewport } from "./capture.ts";
|
|
3
|
+
export { upload } from "./upload.ts";
|
|
4
|
+
export type { ObjectWriter, UploadedFile, UploadOptions } from "./upload.ts";
|
|
5
|
+
export { captionOf, objectKeyOf, slugOf } from "./keys.ts";
|
|
6
|
+
export { handleMessage, runMcpServer } from "./mcp.ts";
|
|
7
|
+
export type { McpDependencies } from "./mcp.ts";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACvD,YAAY,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/keys.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** S3 object keys only tolerate a narrow character set. */
|
|
2
|
+
export declare function slugOf(rawPrefix: string): string;
|
|
3
|
+
/** The image's caption in the generated markdown. */
|
|
4
|
+
export declare function captionOf(file: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* `<prefix>/<yyyy-mm-dd>-<basename>-<content-hash>.<ext>`: the hash makes
|
|
7
|
+
* re-uploads cache-safe, the date keeps the bucket browsable.
|
|
8
|
+
*/
|
|
9
|
+
export declare function objectKeyOf(prefix: string, file: string, bytes: Uint8Array, date: string): string;
|
|
10
|
+
//# sourceMappingURL=keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAEA,2DAA2D;AAC3D,wBAAgB,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,qDAAqD;AACrD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAMD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAGjG"}
|
package/dist/keys.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { basename, extname } from "node:path";
|
|
2
|
+
/** S3 object keys only tolerate a narrow character set. */
|
|
3
|
+
export function slugOf(rawPrefix) {
|
|
4
|
+
return rawPrefix.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
5
|
+
}
|
|
6
|
+
/** The image's caption in the generated markdown. */
|
|
7
|
+
export function captionOf(file) {
|
|
8
|
+
return basename(file, extname(file)).replace(/[-_]+/g, " ");
|
|
9
|
+
}
|
|
10
|
+
function contentHash(bytes) {
|
|
11
|
+
return new Bun.CryptoHasher("sha256").update(bytes).digest("hex").slice(0, 8);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* `<prefix>/<yyyy-mm-dd>-<basename>-<content-hash>.<ext>`: the hash makes
|
|
15
|
+
* re-uploads cache-safe, the date keeps the bucket browsable.
|
|
16
|
+
*/
|
|
17
|
+
export function objectKeyOf(prefix, file, bytes, date) {
|
|
18
|
+
const extension = extname(file);
|
|
19
|
+
return `${slugOf(prefix)}/${date}-${basename(file, extension)}-${contentHash(bytes)}${extension.toLowerCase()}`;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=keys.js.map
|
package/dist/keys.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE9C,2DAA2D;AAC3D,MAAM,UAAU,MAAM,CAAC,SAAiB;IACtC,OAAO,SAAS,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;AACnD,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,WAAW,CAAC,KAAiB;IACpC,OAAO,IAAI,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAChF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,MAAc,EAAE,IAAY,EAAE,KAAiB,EAAE,IAAY;IACvF,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,WAAW,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC;AAClH,CAAC"}
|
package/dist/mcp.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type CaptureOptions } from "./capture.ts";
|
|
2
|
+
import { type UploadedFile, type UploadOptions } from "./upload.ts";
|
|
3
|
+
interface JsonRpcMessage {
|
|
4
|
+
readonly jsonrpc: "2.0";
|
|
5
|
+
readonly id?: number | string;
|
|
6
|
+
readonly method?: string;
|
|
7
|
+
readonly params?: Record<string, unknown>;
|
|
8
|
+
}
|
|
9
|
+
/** The implementations, injectable for tests. */
|
|
10
|
+
export interface McpDependencies {
|
|
11
|
+
readonly capture: (options: CaptureOptions) => Promise<void>;
|
|
12
|
+
readonly upload: (options: UploadOptions) => Promise<Array<UploadedFile>>;
|
|
13
|
+
}
|
|
14
|
+
/** Handle one JSON-RPC message; null means nothing to send back. */
|
|
15
|
+
export declare function handleMessage(message: JsonRpcMessage, dependencies: McpDependencies): Promise<Record<string, unknown> | null>;
|
|
16
|
+
/** Serve MCP over stdio until stdin closes. */
|
|
17
|
+
export declare function runMcpServer(): Promise<void>;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=mcp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAEA,OAAO,EAAoC,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAErF,OAAO,EAAkC,KAAK,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAUpG,UAAU,cAAc;IACtB,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC3C;AAED,iDAAiD;AACjD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;CAC3E;AAqID,oEAAoE;AACpE,wBAAsB,aAAa,CACjC,OAAO,EAAE,cAAc,EACvB,YAAY,EAAE,eAAe,GAC5B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAsCzC;AAED,+CAA+C;AAC/C,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAgBlD"}
|
package/dist/mcp.js
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { tmpdir } from "node:os";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { capture as captureImplementation } from "./capture.js";
|
|
4
|
+
import { parseLocalStorage, parseViewport } from "./options.js";
|
|
5
|
+
import { upload as uploadImplementation } from "./upload.js";
|
|
6
|
+
/**
|
|
7
|
+
* A hand-rolled MCP server: the stdio transport is newline-delimited JSON-RPC
|
|
8
|
+
* 2.0, and this server only needs initialize + tools, so the protocol fits in
|
|
9
|
+
* this file and the package stays zero-dependency.
|
|
10
|
+
*/
|
|
11
|
+
const PROTOCOL_VERSION = "2025-06-18";
|
|
12
|
+
const TOOLS = [
|
|
13
|
+
{
|
|
14
|
+
name: "screenshot",
|
|
15
|
+
description: "Screenshot a web page locally with Bun.WebView (no browser install). Optionally upload it to the configured S3-compatible bucket and return its public URL.",
|
|
16
|
+
inputSchema: {
|
|
17
|
+
type: "object",
|
|
18
|
+
properties: {
|
|
19
|
+
url: { type: "string", description: "The page to screenshot." },
|
|
20
|
+
out: {
|
|
21
|
+
type: "string",
|
|
22
|
+
description: "Where to write the PNG. Defaults to a temporary file.",
|
|
23
|
+
},
|
|
24
|
+
viewport: {
|
|
25
|
+
type: "string",
|
|
26
|
+
description: "Viewport as <width>x<height>. Defaults to 1440x900 (use 390x844 for mobile).",
|
|
27
|
+
},
|
|
28
|
+
wait_for: {
|
|
29
|
+
type: "string",
|
|
30
|
+
description: "CSS selector to wait for before shooting (15s timeout).",
|
|
31
|
+
},
|
|
32
|
+
scroll_to: {
|
|
33
|
+
type: "string",
|
|
34
|
+
description: "CSS selector scrolled into view before shooting.",
|
|
35
|
+
},
|
|
36
|
+
settle_ms: {
|
|
37
|
+
type: "number",
|
|
38
|
+
description: "Milliseconds to let the page settle after load. Defaults to 1500.",
|
|
39
|
+
},
|
|
40
|
+
full_page: {
|
|
41
|
+
type: "boolean",
|
|
42
|
+
description: "Grow the viewport to the full page height before shooting.",
|
|
43
|
+
},
|
|
44
|
+
local_storage: {
|
|
45
|
+
type: "object",
|
|
46
|
+
additionalProperties: { type: "string" },
|
|
47
|
+
description: "Entries seeded into the target origin's localStorage before the page loads (e.g. a session token for authenticated screens).",
|
|
48
|
+
},
|
|
49
|
+
upload: {
|
|
50
|
+
type: "boolean",
|
|
51
|
+
description: "Upload the shot and return its public URL.",
|
|
52
|
+
},
|
|
53
|
+
prefix: {
|
|
54
|
+
type: "string",
|
|
55
|
+
description: "Object key prefix for the upload, e.g. pr-123.",
|
|
56
|
+
},
|
|
57
|
+
markdown: {
|
|
58
|
+
type: "boolean",
|
|
59
|
+
description: "Return a  markdown line instead of the bare URL.",
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
required: ["url"],
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: "upload",
|
|
67
|
+
description: "Upload local images to the configured S3-compatible bucket and return their public URLs (content-hashed keys, safe to re-upload).",
|
|
68
|
+
inputSchema: {
|
|
69
|
+
type: "object",
|
|
70
|
+
properties: {
|
|
71
|
+
files: {
|
|
72
|
+
type: "array",
|
|
73
|
+
items: { type: "string" },
|
|
74
|
+
description: "Paths of the images to upload.",
|
|
75
|
+
},
|
|
76
|
+
prefix: {
|
|
77
|
+
type: "string",
|
|
78
|
+
description: "Object key prefix, e.g. pr-123.",
|
|
79
|
+
},
|
|
80
|
+
markdown: {
|
|
81
|
+
type: "boolean",
|
|
82
|
+
description: "Return  markdown lines instead of the bare URLs.",
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
required: ["files"],
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
];
|
|
89
|
+
function textResult(text, isError = false) {
|
|
90
|
+
return { content: [{ type: "text", text }], ...(isError ? { isError: true } : {}) };
|
|
91
|
+
}
|
|
92
|
+
function renderUploads(uploaded, markdown) {
|
|
93
|
+
return uploaded.map((entry) => (markdown ? entry.markdown : entry.url)).join("\n");
|
|
94
|
+
}
|
|
95
|
+
function temporaryOut() {
|
|
96
|
+
return join(tmpdir(), `cliche-${Date.now().toString(36)}.png`);
|
|
97
|
+
}
|
|
98
|
+
async function callTool(name, input, dependencies) {
|
|
99
|
+
if (name === "screenshot") {
|
|
100
|
+
const out = typeof input.out === "string" ? input.out : temporaryOut();
|
|
101
|
+
await dependencies.capture({
|
|
102
|
+
url: String(input.url),
|
|
103
|
+
out,
|
|
104
|
+
...(typeof input.viewport === "string" ? { viewport: parseViewport(input.viewport) } : {}),
|
|
105
|
+
...(typeof input.wait_for === "string" ? { waitFor: input.wait_for } : {}),
|
|
106
|
+
...(typeof input.scroll_to === "string" ? { scrollTo: input.scroll_to } : {}),
|
|
107
|
+
...(typeof input.settle_ms === "number" ? { settleMilliseconds: input.settle_ms } : {}),
|
|
108
|
+
...(input.full_page === true ? { fullPage: true } : {}),
|
|
109
|
+
...(input.local_storage !== undefined && typeof input.local_storage === "object"
|
|
110
|
+
? { localStorage: input.local_storage }
|
|
111
|
+
: {}),
|
|
112
|
+
});
|
|
113
|
+
if (input.upload !== true) {
|
|
114
|
+
return textResult(`Captured ${String(input.url)} -> ${out}`);
|
|
115
|
+
}
|
|
116
|
+
const uploaded = await dependencies.upload({
|
|
117
|
+
files: [out],
|
|
118
|
+
...(typeof input.prefix === "string" ? { prefix: input.prefix } : {}),
|
|
119
|
+
});
|
|
120
|
+
return textResult(renderUploads(uploaded, input.markdown === true));
|
|
121
|
+
}
|
|
122
|
+
if (name === "upload") {
|
|
123
|
+
const uploaded = await dependencies.upload({
|
|
124
|
+
files: input.files ?? [],
|
|
125
|
+
...(typeof input.prefix === "string" ? { prefix: input.prefix } : {}),
|
|
126
|
+
});
|
|
127
|
+
return textResult(renderUploads(uploaded, input.markdown === true));
|
|
128
|
+
}
|
|
129
|
+
return textResult(`Unknown tool: ${name}`, true);
|
|
130
|
+
}
|
|
131
|
+
/** Handle one JSON-RPC message; null means nothing to send back. */
|
|
132
|
+
export async function handleMessage(message, dependencies) {
|
|
133
|
+
// Notifications carry no id and expect no response.
|
|
134
|
+
if (message.id === undefined)
|
|
135
|
+
return null;
|
|
136
|
+
const reply = (result) => ({
|
|
137
|
+
jsonrpc: "2.0",
|
|
138
|
+
id: message.id,
|
|
139
|
+
result,
|
|
140
|
+
});
|
|
141
|
+
switch (message.method) {
|
|
142
|
+
case "initialize":
|
|
143
|
+
return reply({
|
|
144
|
+
protocolVersion: typeof message.params?.protocolVersion === "string"
|
|
145
|
+
? message.params.protocolVersion
|
|
146
|
+
: PROTOCOL_VERSION,
|
|
147
|
+
capabilities: { tools: {} },
|
|
148
|
+
serverInfo: { name: "cliche", version: "0.1.0" },
|
|
149
|
+
});
|
|
150
|
+
case "ping":
|
|
151
|
+
return reply({});
|
|
152
|
+
case "tools/list":
|
|
153
|
+
return reply({ tools: TOOLS });
|
|
154
|
+
case "tools/call": {
|
|
155
|
+
const name = String(message.params?.name);
|
|
156
|
+
const input = (message.params?.arguments ?? {});
|
|
157
|
+
try {
|
|
158
|
+
return reply(await callTool(name, input, dependencies));
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
return reply(textResult(error instanceof Error ? error.message : String(error), true));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
default:
|
|
165
|
+
return {
|
|
166
|
+
jsonrpc: "2.0",
|
|
167
|
+
id: message.id,
|
|
168
|
+
error: { code: -32601, message: `Method not found: ${message.method}` },
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/** Serve MCP over stdio until stdin closes. */
|
|
173
|
+
export async function runMcpServer() {
|
|
174
|
+
const dependencies = {
|
|
175
|
+
capture: captureImplementation,
|
|
176
|
+
upload: uploadImplementation,
|
|
177
|
+
};
|
|
178
|
+
for await (const line of console) {
|
|
179
|
+
if (line.trim() === "")
|
|
180
|
+
continue;
|
|
181
|
+
let message;
|
|
182
|
+
try {
|
|
183
|
+
message = JSON.parse(line);
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
const response = await handleMessage(message, dependencies);
|
|
189
|
+
if (response !== null)
|
|
190
|
+
console.log(JSON.stringify(response));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=mcp.js.map
|
package/dist/mcp.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { CaptureOptions, Viewport } from "./capture.ts";
|
|
2
|
+
export interface CaptureCommand {
|
|
3
|
+
readonly kind: "capture";
|
|
4
|
+
readonly capture: CaptureOptions;
|
|
5
|
+
/** Upload the shot right after capturing it. */
|
|
6
|
+
readonly upload: boolean;
|
|
7
|
+
readonly prefix: string | undefined;
|
|
8
|
+
/** Print `` lines instead of the bare URLs. */
|
|
9
|
+
readonly markdown: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface UploadCommand {
|
|
12
|
+
readonly kind: "upload";
|
|
13
|
+
readonly files: ReadonlyArray<string>;
|
|
14
|
+
readonly prefix: string | undefined;
|
|
15
|
+
readonly markdown: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface McpCommand {
|
|
18
|
+
readonly kind: "mcp";
|
|
19
|
+
}
|
|
20
|
+
export interface SkillCommand {
|
|
21
|
+
readonly kind: "skill";
|
|
22
|
+
}
|
|
23
|
+
export interface SetupCommand {
|
|
24
|
+
readonly kind: "setup";
|
|
25
|
+
readonly bucket: string;
|
|
26
|
+
}
|
|
27
|
+
export interface AlbumCommand {
|
|
28
|
+
readonly kind: "album";
|
|
29
|
+
readonly port: number | undefined;
|
|
30
|
+
}
|
|
31
|
+
export interface HelpCommand {
|
|
32
|
+
readonly kind: "help";
|
|
33
|
+
}
|
|
34
|
+
export type Command = CaptureCommand | UploadCommand | McpCommand | SkillCommand | SetupCommand | AlbumCommand | HelpCommand;
|
|
35
|
+
export declare function parseViewport(value: string): Viewport;
|
|
36
|
+
export declare function parseLocalStorage(entries: ReadonlyArray<string>): Record<string, string>;
|
|
37
|
+
export declare function parseCommand(argv: ReadonlyArray<string>): Command;
|
|
38
|
+
//# sourceMappingURL=options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,gDAAgD;IAChD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,8DAA8D;IAC9D,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,OAAO,GACf,cAAc,GACd,aAAa,GACb,UAAU,GACV,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,WAAW,CAAC;AAEhB,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAMrD;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUxF;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,OAAO,CAqEjE"}
|