langchain-snaprender 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/README.md +69 -0
- package/dist/index.cjs +161 -0
- package/dist/index.d.cts +97 -0
- package/dist/index.d.ts +97 -0
- package/dist/index.js +124 -0
- package/package.json +64 -0
package/README.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# langchain-snaprender
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/langchain-snaprender)
|
|
4
|
+
[](../LICENSE)
|
|
5
|
+
|
|
6
|
+
LangChain.js tools for [SnapRender Screenshot API](https://snap-render.com). Lets your LangChain agents capture website screenshots as PNG, JPEG, WebP, or PDF.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install langchain-snaprender @langchain/core
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Setup
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
export SNAPRENDER_API_KEY="sk_live_your_key_here"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Get a free key at [app.snap-render.com](https://app.snap-render.com/auth/signup) — 50 screenshots/month, no credit card.
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { SnapRenderScreenshot, SnapRenderCacheCheck, SnapRenderUsage } from "langchain-snaprender";
|
|
26
|
+
|
|
27
|
+
// Pass API key explicitly or use SNAPRENDER_API_KEY env var
|
|
28
|
+
const screenshotTool = new SnapRenderScreenshot();
|
|
29
|
+
const cacheTool = new SnapRenderCacheCheck();
|
|
30
|
+
const usageTool = new SnapRenderUsage();
|
|
31
|
+
|
|
32
|
+
// Use standalone
|
|
33
|
+
const result = await screenshotTool.invoke({ url: "https://example.com" });
|
|
34
|
+
console.log(result);
|
|
35
|
+
|
|
36
|
+
// Or bind to a LangChain agent
|
|
37
|
+
import { ChatOpenAI } from "@langchain/openai";
|
|
38
|
+
import { createReactAgent } from "@langchain/langgraph/prebuilt";
|
|
39
|
+
|
|
40
|
+
const llm = new ChatOpenAI({ model: "gpt-4o" });
|
|
41
|
+
const tools = [screenshotTool, cacheTool, usageTool];
|
|
42
|
+
const agent = createReactAgent({ llm, tools });
|
|
43
|
+
|
|
44
|
+
const response = await agent.invoke({
|
|
45
|
+
messages: [{ role: "user", content: "Take a screenshot of stripe.com" }],
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Tools
|
|
50
|
+
|
|
51
|
+
### `SnapRenderScreenshot` (name: `take_screenshot`)
|
|
52
|
+
|
|
53
|
+
Capture any website as PNG, JPEG, WebP, or PDF.
|
|
54
|
+
|
|
55
|
+
Parameters: `url`, `format`, `full_page`, `dark_mode`, `block_ads`, `block_cookie_banners`, `device`, `width`, `height`
|
|
56
|
+
|
|
57
|
+
### `SnapRenderCacheCheck` (name: `check_screenshot_cache`)
|
|
58
|
+
|
|
59
|
+
Check if a screenshot is cached (free, doesn't count against quota).
|
|
60
|
+
|
|
61
|
+
Parameters: `url`, `format`
|
|
62
|
+
|
|
63
|
+
### `SnapRenderUsage` (name: `get_screenshot_usage`)
|
|
64
|
+
|
|
65
|
+
Get current month's usage stats.
|
|
66
|
+
|
|
67
|
+
## License
|
|
68
|
+
|
|
69
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
SnapRenderCacheCheck: () => SnapRenderCacheCheck,
|
|
34
|
+
SnapRenderScreenshot: () => SnapRenderScreenshot,
|
|
35
|
+
SnapRenderUsage: () => SnapRenderUsage
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(index_exports);
|
|
38
|
+
var import_tools = require("@langchain/core/tools");
|
|
39
|
+
var import_zod = require("zod");
|
|
40
|
+
var import_snaprender = __toESM(require("snaprender"), 1);
|
|
41
|
+
function getClient(apiKey) {
|
|
42
|
+
const key = apiKey ?? process.env.SNAPRENDER_API_KEY;
|
|
43
|
+
if (!key) {
|
|
44
|
+
throw new Error(
|
|
45
|
+
"SNAPRENDER_API_KEY environment variable is required. Get a free key at https://app.snap-render.com/auth/signup"
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
return new import_snaprender.default({ apiKey: key });
|
|
49
|
+
}
|
|
50
|
+
var screenshotSchema = import_zod.z.object({
|
|
51
|
+
url: import_zod.z.string().describe("URL to capture (must start with http:// or https://)"),
|
|
52
|
+
format: import_zod.z.enum(["png", "jpeg", "webp", "pdf"]).optional().default("png").describe("Output format"),
|
|
53
|
+
full_page: import_zod.z.boolean().optional().default(false).describe("Capture entire scrollable page"),
|
|
54
|
+
dark_mode: import_zod.z.boolean().optional().default(false).describe("Enable dark mode CSS emulation"),
|
|
55
|
+
block_ads: import_zod.z.boolean().optional().default(true).describe("Block advertisements"),
|
|
56
|
+
block_cookie_banners: import_zod.z.boolean().optional().default(true).describe("Remove cookie consent banners"),
|
|
57
|
+
device: import_zod.z.enum(["iphone_14", "iphone_15_pro", "pixel_7", "ipad_pro", "macbook_pro"]).optional().describe("Device preset for viewport emulation"),
|
|
58
|
+
width: import_zod.z.number().optional().describe("Viewport width in pixels (320-3840)"),
|
|
59
|
+
height: import_zod.z.number().optional().describe("Viewport height in pixels (200-10000)")
|
|
60
|
+
});
|
|
61
|
+
var SnapRenderScreenshot = class extends import_tools.StructuredTool {
|
|
62
|
+
static lc_name() {
|
|
63
|
+
return "SnapRenderScreenshot";
|
|
64
|
+
}
|
|
65
|
+
name = "take_screenshot";
|
|
66
|
+
description = "Capture a screenshot of any website as PNG, JPEG, WebP, or PDF. Supports device emulation, dark mode, ad blocking, and full-page capture.";
|
|
67
|
+
schema = screenshotSchema;
|
|
68
|
+
apiKey;
|
|
69
|
+
constructor(params = {}) {
|
|
70
|
+
super();
|
|
71
|
+
this.apiKey = params.apiKey;
|
|
72
|
+
}
|
|
73
|
+
async _call(input, _runManager) {
|
|
74
|
+
const client = getClient(this.apiKey);
|
|
75
|
+
const result = await client.capture({
|
|
76
|
+
url: input.url,
|
|
77
|
+
format: input.format,
|
|
78
|
+
fullPage: input.full_page,
|
|
79
|
+
darkMode: input.dark_mode,
|
|
80
|
+
blockAds: input.block_ads,
|
|
81
|
+
blockCookieBanners: input.block_cookie_banners,
|
|
82
|
+
device: input.device,
|
|
83
|
+
width: input.width,
|
|
84
|
+
height: input.height,
|
|
85
|
+
responseType: "json"
|
|
86
|
+
});
|
|
87
|
+
return [
|
|
88
|
+
`URL: ${result.url}`,
|
|
89
|
+
`Format: ${result.format}`,
|
|
90
|
+
`Size: ${result.size.toLocaleString()} bytes`,
|
|
91
|
+
`Dimensions: ${result.width}x${result.height}`,
|
|
92
|
+
`Cache: ${result.cache}`,
|
|
93
|
+
`Response time: ${result.responseTime}`,
|
|
94
|
+
`Remaining credits: ${result.remainingCredits}`,
|
|
95
|
+
`Image: data:image/${result.format};base64,${result.image.split(",").pop()}`
|
|
96
|
+
].join("\n");
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
var cacheSchema = import_zod.z.object({
|
|
100
|
+
url: import_zod.z.string().describe("URL to check"),
|
|
101
|
+
format: import_zod.z.enum(["png", "jpeg", "webp", "pdf"]).optional().default("png").describe("Output format")
|
|
102
|
+
});
|
|
103
|
+
var SnapRenderCacheCheck = class extends import_tools.StructuredTool {
|
|
104
|
+
static lc_name() {
|
|
105
|
+
return "SnapRenderCacheCheck";
|
|
106
|
+
}
|
|
107
|
+
name = "check_screenshot_cache";
|
|
108
|
+
description = "Check if a screenshot is already cached without capturing a new one. Free, does not count against quota.";
|
|
109
|
+
schema = cacheSchema;
|
|
110
|
+
apiKey;
|
|
111
|
+
constructor(params = {}) {
|
|
112
|
+
super();
|
|
113
|
+
this.apiKey = params.apiKey;
|
|
114
|
+
}
|
|
115
|
+
async _call(input, _runManager) {
|
|
116
|
+
const client = getClient(this.apiKey);
|
|
117
|
+
const info = await client.info({ url: input.url, format: input.format });
|
|
118
|
+
if (info.cached) {
|
|
119
|
+
return [
|
|
120
|
+
`Cached: YES`,
|
|
121
|
+
`URL: ${info.url}`,
|
|
122
|
+
`Cached at: ${info.cachedAt ?? "unknown"}`,
|
|
123
|
+
`Expires at: ${info.expiresAt ?? "unknown"}`,
|
|
124
|
+
`Content type: ${info.contentType ?? "unknown"}`
|
|
125
|
+
].join("\n");
|
|
126
|
+
}
|
|
127
|
+
return `Cached: NO
|
|
128
|
+
URL: ${info.url}`;
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
var usageSchema = import_zod.z.object({});
|
|
132
|
+
var SnapRenderUsage = class extends import_tools.StructuredTool {
|
|
133
|
+
static lc_name() {
|
|
134
|
+
return "SnapRenderUsage";
|
|
135
|
+
}
|
|
136
|
+
name = "get_screenshot_usage";
|
|
137
|
+
description = "Get current month's screenshot usage statistics including plan, used, limit, and remaining credits.";
|
|
138
|
+
schema = usageSchema;
|
|
139
|
+
apiKey;
|
|
140
|
+
constructor(params = {}) {
|
|
141
|
+
super();
|
|
142
|
+
this.apiKey = params.apiKey;
|
|
143
|
+
}
|
|
144
|
+
async _call(_input, _runManager) {
|
|
145
|
+
const client = getClient(this.apiKey);
|
|
146
|
+
const usage = await client.usage();
|
|
147
|
+
return [
|
|
148
|
+
`Plan: ${usage.plan}`,
|
|
149
|
+
`Used: ${usage.used}`,
|
|
150
|
+
`Limit: ${usage.limit}`,
|
|
151
|
+
`Remaining: ${usage.remaining}`,
|
|
152
|
+
`Period: ${usage.period.start} to ${usage.period.end}`
|
|
153
|
+
].join("\n");
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
157
|
+
0 && (module.exports = {
|
|
158
|
+
SnapRenderCacheCheck,
|
|
159
|
+
SnapRenderScreenshot,
|
|
160
|
+
SnapRenderUsage
|
|
161
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { StructuredTool } from '@langchain/core/tools';
|
|
2
|
+
import { CallbackManagerForToolRun } from '@langchain/core/callbacks/manager';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
|
|
5
|
+
declare const screenshotSchema: z.ZodObject<{
|
|
6
|
+
url: z.ZodString;
|
|
7
|
+
format: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
8
|
+
png: "png";
|
|
9
|
+
jpeg: "jpeg";
|
|
10
|
+
webp: "webp";
|
|
11
|
+
pdf: "pdf";
|
|
12
|
+
}>>>;
|
|
13
|
+
full_page: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
14
|
+
dark_mode: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
15
|
+
block_ads: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
16
|
+
block_cookie_banners: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
17
|
+
device: z.ZodOptional<z.ZodEnum<{
|
|
18
|
+
iphone_14: "iphone_14";
|
|
19
|
+
iphone_15_pro: "iphone_15_pro";
|
|
20
|
+
pixel_7: "pixel_7";
|
|
21
|
+
ipad_pro: "ipad_pro";
|
|
22
|
+
macbook_pro: "macbook_pro";
|
|
23
|
+
}>>;
|
|
24
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
25
|
+
height: z.ZodOptional<z.ZodNumber>;
|
|
26
|
+
}, z.core.$strip>;
|
|
27
|
+
interface SnapRenderToolParams {
|
|
28
|
+
apiKey?: string;
|
|
29
|
+
}
|
|
30
|
+
declare class SnapRenderScreenshot extends StructuredTool {
|
|
31
|
+
static lc_name(): string;
|
|
32
|
+
name: string;
|
|
33
|
+
description: string;
|
|
34
|
+
schema: z.ZodObject<{
|
|
35
|
+
url: z.ZodString;
|
|
36
|
+
format: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
37
|
+
png: "png";
|
|
38
|
+
jpeg: "jpeg";
|
|
39
|
+
webp: "webp";
|
|
40
|
+
pdf: "pdf";
|
|
41
|
+
}>>>;
|
|
42
|
+
full_page: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
43
|
+
dark_mode: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
44
|
+
block_ads: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
45
|
+
block_cookie_banners: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
46
|
+
device: z.ZodOptional<z.ZodEnum<{
|
|
47
|
+
iphone_14: "iphone_14";
|
|
48
|
+
iphone_15_pro: "iphone_15_pro";
|
|
49
|
+
pixel_7: "pixel_7";
|
|
50
|
+
ipad_pro: "ipad_pro";
|
|
51
|
+
macbook_pro: "macbook_pro";
|
|
52
|
+
}>>;
|
|
53
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
54
|
+
height: z.ZodOptional<z.ZodNumber>;
|
|
55
|
+
}, z.core.$strip>;
|
|
56
|
+
private apiKey?;
|
|
57
|
+
constructor(params?: SnapRenderToolParams);
|
|
58
|
+
_call(input: z.output<typeof screenshotSchema>, _runManager?: CallbackManagerForToolRun): Promise<string>;
|
|
59
|
+
}
|
|
60
|
+
declare const cacheSchema: z.ZodObject<{
|
|
61
|
+
url: z.ZodString;
|
|
62
|
+
format: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
63
|
+
png: "png";
|
|
64
|
+
jpeg: "jpeg";
|
|
65
|
+
webp: "webp";
|
|
66
|
+
pdf: "pdf";
|
|
67
|
+
}>>>;
|
|
68
|
+
}, z.core.$strip>;
|
|
69
|
+
declare class SnapRenderCacheCheck extends StructuredTool {
|
|
70
|
+
static lc_name(): string;
|
|
71
|
+
name: string;
|
|
72
|
+
description: string;
|
|
73
|
+
schema: z.ZodObject<{
|
|
74
|
+
url: z.ZodString;
|
|
75
|
+
format: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
76
|
+
png: "png";
|
|
77
|
+
jpeg: "jpeg";
|
|
78
|
+
webp: "webp";
|
|
79
|
+
pdf: "pdf";
|
|
80
|
+
}>>>;
|
|
81
|
+
}, z.core.$strip>;
|
|
82
|
+
private apiKey?;
|
|
83
|
+
constructor(params?: SnapRenderToolParams);
|
|
84
|
+
_call(input: z.output<typeof cacheSchema>, _runManager?: CallbackManagerForToolRun): Promise<string>;
|
|
85
|
+
}
|
|
86
|
+
declare const usageSchema: z.ZodObject<{}, z.core.$strip>;
|
|
87
|
+
declare class SnapRenderUsage extends StructuredTool {
|
|
88
|
+
static lc_name(): string;
|
|
89
|
+
name: string;
|
|
90
|
+
description: string;
|
|
91
|
+
schema: z.ZodObject<{}, z.core.$strip>;
|
|
92
|
+
private apiKey?;
|
|
93
|
+
constructor(params?: SnapRenderToolParams);
|
|
94
|
+
_call(_input: z.output<typeof usageSchema>, _runManager?: CallbackManagerForToolRun): Promise<string>;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export { SnapRenderCacheCheck, SnapRenderScreenshot, type SnapRenderToolParams, SnapRenderUsage };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { StructuredTool } from '@langchain/core/tools';
|
|
2
|
+
import { CallbackManagerForToolRun } from '@langchain/core/callbacks/manager';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
|
|
5
|
+
declare const screenshotSchema: z.ZodObject<{
|
|
6
|
+
url: z.ZodString;
|
|
7
|
+
format: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
8
|
+
png: "png";
|
|
9
|
+
jpeg: "jpeg";
|
|
10
|
+
webp: "webp";
|
|
11
|
+
pdf: "pdf";
|
|
12
|
+
}>>>;
|
|
13
|
+
full_page: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
14
|
+
dark_mode: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
15
|
+
block_ads: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
16
|
+
block_cookie_banners: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
17
|
+
device: z.ZodOptional<z.ZodEnum<{
|
|
18
|
+
iphone_14: "iphone_14";
|
|
19
|
+
iphone_15_pro: "iphone_15_pro";
|
|
20
|
+
pixel_7: "pixel_7";
|
|
21
|
+
ipad_pro: "ipad_pro";
|
|
22
|
+
macbook_pro: "macbook_pro";
|
|
23
|
+
}>>;
|
|
24
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
25
|
+
height: z.ZodOptional<z.ZodNumber>;
|
|
26
|
+
}, z.core.$strip>;
|
|
27
|
+
interface SnapRenderToolParams {
|
|
28
|
+
apiKey?: string;
|
|
29
|
+
}
|
|
30
|
+
declare class SnapRenderScreenshot extends StructuredTool {
|
|
31
|
+
static lc_name(): string;
|
|
32
|
+
name: string;
|
|
33
|
+
description: string;
|
|
34
|
+
schema: z.ZodObject<{
|
|
35
|
+
url: z.ZodString;
|
|
36
|
+
format: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
37
|
+
png: "png";
|
|
38
|
+
jpeg: "jpeg";
|
|
39
|
+
webp: "webp";
|
|
40
|
+
pdf: "pdf";
|
|
41
|
+
}>>>;
|
|
42
|
+
full_page: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
43
|
+
dark_mode: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
44
|
+
block_ads: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
45
|
+
block_cookie_banners: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
46
|
+
device: z.ZodOptional<z.ZodEnum<{
|
|
47
|
+
iphone_14: "iphone_14";
|
|
48
|
+
iphone_15_pro: "iphone_15_pro";
|
|
49
|
+
pixel_7: "pixel_7";
|
|
50
|
+
ipad_pro: "ipad_pro";
|
|
51
|
+
macbook_pro: "macbook_pro";
|
|
52
|
+
}>>;
|
|
53
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
54
|
+
height: z.ZodOptional<z.ZodNumber>;
|
|
55
|
+
}, z.core.$strip>;
|
|
56
|
+
private apiKey?;
|
|
57
|
+
constructor(params?: SnapRenderToolParams);
|
|
58
|
+
_call(input: z.output<typeof screenshotSchema>, _runManager?: CallbackManagerForToolRun): Promise<string>;
|
|
59
|
+
}
|
|
60
|
+
declare const cacheSchema: z.ZodObject<{
|
|
61
|
+
url: z.ZodString;
|
|
62
|
+
format: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
63
|
+
png: "png";
|
|
64
|
+
jpeg: "jpeg";
|
|
65
|
+
webp: "webp";
|
|
66
|
+
pdf: "pdf";
|
|
67
|
+
}>>>;
|
|
68
|
+
}, z.core.$strip>;
|
|
69
|
+
declare class SnapRenderCacheCheck extends StructuredTool {
|
|
70
|
+
static lc_name(): string;
|
|
71
|
+
name: string;
|
|
72
|
+
description: string;
|
|
73
|
+
schema: z.ZodObject<{
|
|
74
|
+
url: z.ZodString;
|
|
75
|
+
format: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
76
|
+
png: "png";
|
|
77
|
+
jpeg: "jpeg";
|
|
78
|
+
webp: "webp";
|
|
79
|
+
pdf: "pdf";
|
|
80
|
+
}>>>;
|
|
81
|
+
}, z.core.$strip>;
|
|
82
|
+
private apiKey?;
|
|
83
|
+
constructor(params?: SnapRenderToolParams);
|
|
84
|
+
_call(input: z.output<typeof cacheSchema>, _runManager?: CallbackManagerForToolRun): Promise<string>;
|
|
85
|
+
}
|
|
86
|
+
declare const usageSchema: z.ZodObject<{}, z.core.$strip>;
|
|
87
|
+
declare class SnapRenderUsage extends StructuredTool {
|
|
88
|
+
static lc_name(): string;
|
|
89
|
+
name: string;
|
|
90
|
+
description: string;
|
|
91
|
+
schema: z.ZodObject<{}, z.core.$strip>;
|
|
92
|
+
private apiKey?;
|
|
93
|
+
constructor(params?: SnapRenderToolParams);
|
|
94
|
+
_call(_input: z.output<typeof usageSchema>, _runManager?: CallbackManagerForToolRun): Promise<string>;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export { SnapRenderCacheCheck, SnapRenderScreenshot, type SnapRenderToolParams, SnapRenderUsage };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { StructuredTool } from "@langchain/core/tools";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import SnapRender from "snaprender";
|
|
5
|
+
function getClient(apiKey) {
|
|
6
|
+
const key = apiKey ?? process.env.SNAPRENDER_API_KEY;
|
|
7
|
+
if (!key) {
|
|
8
|
+
throw new Error(
|
|
9
|
+
"SNAPRENDER_API_KEY environment variable is required. Get a free key at https://app.snap-render.com/auth/signup"
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
return new SnapRender({ apiKey: key });
|
|
13
|
+
}
|
|
14
|
+
var screenshotSchema = z.object({
|
|
15
|
+
url: z.string().describe("URL to capture (must start with http:// or https://)"),
|
|
16
|
+
format: z.enum(["png", "jpeg", "webp", "pdf"]).optional().default("png").describe("Output format"),
|
|
17
|
+
full_page: z.boolean().optional().default(false).describe("Capture entire scrollable page"),
|
|
18
|
+
dark_mode: z.boolean().optional().default(false).describe("Enable dark mode CSS emulation"),
|
|
19
|
+
block_ads: z.boolean().optional().default(true).describe("Block advertisements"),
|
|
20
|
+
block_cookie_banners: z.boolean().optional().default(true).describe("Remove cookie consent banners"),
|
|
21
|
+
device: z.enum(["iphone_14", "iphone_15_pro", "pixel_7", "ipad_pro", "macbook_pro"]).optional().describe("Device preset for viewport emulation"),
|
|
22
|
+
width: z.number().optional().describe("Viewport width in pixels (320-3840)"),
|
|
23
|
+
height: z.number().optional().describe("Viewport height in pixels (200-10000)")
|
|
24
|
+
});
|
|
25
|
+
var SnapRenderScreenshot = class extends StructuredTool {
|
|
26
|
+
static lc_name() {
|
|
27
|
+
return "SnapRenderScreenshot";
|
|
28
|
+
}
|
|
29
|
+
name = "take_screenshot";
|
|
30
|
+
description = "Capture a screenshot of any website as PNG, JPEG, WebP, or PDF. Supports device emulation, dark mode, ad blocking, and full-page capture.";
|
|
31
|
+
schema = screenshotSchema;
|
|
32
|
+
apiKey;
|
|
33
|
+
constructor(params = {}) {
|
|
34
|
+
super();
|
|
35
|
+
this.apiKey = params.apiKey;
|
|
36
|
+
}
|
|
37
|
+
async _call(input, _runManager) {
|
|
38
|
+
const client = getClient(this.apiKey);
|
|
39
|
+
const result = await client.capture({
|
|
40
|
+
url: input.url,
|
|
41
|
+
format: input.format,
|
|
42
|
+
fullPage: input.full_page,
|
|
43
|
+
darkMode: input.dark_mode,
|
|
44
|
+
blockAds: input.block_ads,
|
|
45
|
+
blockCookieBanners: input.block_cookie_banners,
|
|
46
|
+
device: input.device,
|
|
47
|
+
width: input.width,
|
|
48
|
+
height: input.height,
|
|
49
|
+
responseType: "json"
|
|
50
|
+
});
|
|
51
|
+
return [
|
|
52
|
+
`URL: ${result.url}`,
|
|
53
|
+
`Format: ${result.format}`,
|
|
54
|
+
`Size: ${result.size.toLocaleString()} bytes`,
|
|
55
|
+
`Dimensions: ${result.width}x${result.height}`,
|
|
56
|
+
`Cache: ${result.cache}`,
|
|
57
|
+
`Response time: ${result.responseTime}`,
|
|
58
|
+
`Remaining credits: ${result.remainingCredits}`,
|
|
59
|
+
`Image: data:image/${result.format};base64,${result.image.split(",").pop()}`
|
|
60
|
+
].join("\n");
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
var cacheSchema = z.object({
|
|
64
|
+
url: z.string().describe("URL to check"),
|
|
65
|
+
format: z.enum(["png", "jpeg", "webp", "pdf"]).optional().default("png").describe("Output format")
|
|
66
|
+
});
|
|
67
|
+
var SnapRenderCacheCheck = class extends StructuredTool {
|
|
68
|
+
static lc_name() {
|
|
69
|
+
return "SnapRenderCacheCheck";
|
|
70
|
+
}
|
|
71
|
+
name = "check_screenshot_cache";
|
|
72
|
+
description = "Check if a screenshot is already cached without capturing a new one. Free, does not count against quota.";
|
|
73
|
+
schema = cacheSchema;
|
|
74
|
+
apiKey;
|
|
75
|
+
constructor(params = {}) {
|
|
76
|
+
super();
|
|
77
|
+
this.apiKey = params.apiKey;
|
|
78
|
+
}
|
|
79
|
+
async _call(input, _runManager) {
|
|
80
|
+
const client = getClient(this.apiKey);
|
|
81
|
+
const info = await client.info({ url: input.url, format: input.format });
|
|
82
|
+
if (info.cached) {
|
|
83
|
+
return [
|
|
84
|
+
`Cached: YES`,
|
|
85
|
+
`URL: ${info.url}`,
|
|
86
|
+
`Cached at: ${info.cachedAt ?? "unknown"}`,
|
|
87
|
+
`Expires at: ${info.expiresAt ?? "unknown"}`,
|
|
88
|
+
`Content type: ${info.contentType ?? "unknown"}`
|
|
89
|
+
].join("\n");
|
|
90
|
+
}
|
|
91
|
+
return `Cached: NO
|
|
92
|
+
URL: ${info.url}`;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
var usageSchema = z.object({});
|
|
96
|
+
var SnapRenderUsage = class extends StructuredTool {
|
|
97
|
+
static lc_name() {
|
|
98
|
+
return "SnapRenderUsage";
|
|
99
|
+
}
|
|
100
|
+
name = "get_screenshot_usage";
|
|
101
|
+
description = "Get current month's screenshot usage statistics including plan, used, limit, and remaining credits.";
|
|
102
|
+
schema = usageSchema;
|
|
103
|
+
apiKey;
|
|
104
|
+
constructor(params = {}) {
|
|
105
|
+
super();
|
|
106
|
+
this.apiKey = params.apiKey;
|
|
107
|
+
}
|
|
108
|
+
async _call(_input, _runManager) {
|
|
109
|
+
const client = getClient(this.apiKey);
|
|
110
|
+
const usage = await client.usage();
|
|
111
|
+
return [
|
|
112
|
+
`Plan: ${usage.plan}`,
|
|
113
|
+
`Used: ${usage.used}`,
|
|
114
|
+
`Limit: ${usage.limit}`,
|
|
115
|
+
`Remaining: ${usage.remaining}`,
|
|
116
|
+
`Period: ${usage.period.start} to ${usage.period.end}`
|
|
117
|
+
].join("\n");
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
export {
|
|
121
|
+
SnapRenderCacheCheck,
|
|
122
|
+
SnapRenderScreenshot,
|
|
123
|
+
SnapRenderUsage
|
|
124
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "langchain-snaprender",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "LangChain.js tools for SnapRender Screenshot API — capture websites as PNG, JPEG, WebP, or PDF",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"require": {
|
|
13
|
+
"types": "./dist/index.d.cts",
|
|
14
|
+
"default": "./dist/index.cjs"
|
|
15
|
+
},
|
|
16
|
+
"import": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"default": "./dist/index.js"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"keywords": [
|
|
26
|
+
"langchain",
|
|
27
|
+
"langchain-tool",
|
|
28
|
+
"screenshot",
|
|
29
|
+
"web-capture",
|
|
30
|
+
"snaprender",
|
|
31
|
+
"ai-agent",
|
|
32
|
+
"llm-tool"
|
|
33
|
+
],
|
|
34
|
+
"author": {
|
|
35
|
+
"name": "SnapRender",
|
|
36
|
+
"email": "support@snap-render.com"
|
|
37
|
+
},
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "https://github.com/User0856/snaprender-integrations.git",
|
|
41
|
+
"directory": "langchain-js"
|
|
42
|
+
},
|
|
43
|
+
"homepage": "https://snap-render.com",
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=20"
|
|
46
|
+
},
|
|
47
|
+
"scripts": {
|
|
48
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
49
|
+
"prepublishOnly": "npm run build"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"snaprender": "^0.2.0",
|
|
53
|
+
"zod": "^3.25.76 || ^4"
|
|
54
|
+
},
|
|
55
|
+
"peerDependencies": {
|
|
56
|
+
"@langchain/core": ">=0.3.0"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@langchain/core": "^1.1.0",
|
|
60
|
+
"@types/node": "^25.3.0",
|
|
61
|
+
"tsup": "^8.0.0",
|
|
62
|
+
"typescript": "^5.8.0"
|
|
63
|
+
}
|
|
64
|
+
}
|