) => {
30 | const accessToken = mapboxAccessToken;
31 |
32 | if (!accessToken) {
33 | throw new Error('Please set the Mapbox Access Token in the plugin settings.');
34 | }
35 |
36 | let markers;
37 | let padding = "";
38 | let formatZoom = zoom?.toString() || (pois.length == 1 ? '9' : 'auto'); // Use provided zoom level or default
39 | if (pois.length > 1) {
40 | markers = pois.map((poi, index) => `pin-s-${index + 1}+FF2F48(${poi.longitude},${poi.latitude})`).join(',');
41 | padding = "&padding=50,50,50,50";
42 | formatZoom = formatZoom === 'auto' ? 'auto' : `${formatZoom},0`;
43 | } else {
44 | markers = `pin-s+FF2F48(${pois[0].longitude},${pois[0].latitude})`;
45 | formatZoom = `${formatZoom},0`;
46 | }
47 | let coordinates = pois.length == 1 ? `${pois[0].longitude},${pois[0].latitude},${formatZoom}` : 'auto';
48 | let url = `https://api.mapbox.com/styles/v1/mapbox/outdoors-v12/static/${markers}/${coordinates}/600x400@2x?access_token=${accessToken}${padding}`;
49 |
50 | return { imageURL: url };
51 | };
52 |
53 | return new Tool(paramsSchema, name, description, execute).tool;
54 | }
55 |
56 | export { createShowPoisOnMap };
57 |
--------------------------------------------------------------------------------
/tools/tool.ts:
--------------------------------------------------------------------------------
1 | import { z } from "zod";
2 | import { zodToJsonSchema } from "zod-to-json-schema";
3 |
4 | export type ToolInterface, R extends z.ZodType> = [
5 | (params: z.infer) => z.infer,
6 | {
7 | name: string;
8 | description: string;
9 | parameters: object;
10 | }
11 | ];
12 |
13 | class Tool, R extends z.ZodType> {
14 | paramsSchema: P;
15 | name: string;
16 | description: string;
17 | execute: (params: z.infer) => z.infer;
18 | tool: ToolInterface
19 |
20 | constructor(paramsSchema: P, name: string, description: string, execute: (params: z.infer
) => z.infer) {
21 | this.paramsSchema = paramsSchema;
22 | this.name = name;
23 | this.description = description;
24 | this.execute = execute;
25 |
26 | this.tool = [
27 | this.run.bind(this),
28 | {
29 | name: this.name,
30 | description: this.description,
31 | parameters: zodToJsonSchema(this.paramsSchema),
32 | }
33 | ];
34 | }
35 |
36 | run(params: z.infer): z.infer {
37 | try {
38 | const validatedParams = this.paramsSchema.parse(params);
39 | return this.execute(validatedParams);
40 | } catch (error) {
41 | return error.message as z.infer;
42 | }
43 | }
44 | }
45 |
46 | export { Tool };
47 |
--------------------------------------------------------------------------------
/tools/webbrowser.ts:
--------------------------------------------------------------------------------
1 | import { Tool } from './tool';
2 | import { z } from 'zod';
3 | import * as cheerio from "cheerio";
4 |
5 | const DEFAULT_HEADERS = {
6 | Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
7 | "Accept-Encoding": "gzip, deflate",
8 | "Accept-Language": "en-US,en;q=0.5",
9 | "Alt-Used": "LEAVE-THIS-KEY-SET-BY-TOOL",
10 | Connection: "keep-alive",
11 | // Host: "www.google.com",
12 | Referer: "https://www.google.com/",
13 | "Sec-Fetch-Dest": "document",
14 | "Sec-Fetch-Mode": "navigate",
15 | "Sec-Fetch-Site": "cross-site",
16 | "Upgrade-Insecure-Requests": "1",
17 | "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0",
18 | };
19 |
20 | function createWebBrowser() {
21 | const paramsSchema = z.object({
22 | url: z.string(),
23 | });
24 | const name = 'webbrowser';
25 | const description = 'useful for when you need to summarize a webpage. input should be a ONE valid http URL including protocol.';
26 |
27 | const execute = async ({ url }: z.infer) => {
28 | const config = {
29 | headers: DEFAULT_HEADERS,
30 | };
31 |
32 | try {
33 | const htmlResponse = await fetch(url, config);
34 | const allowedContentTypes = ["text/html", "application/json", "application/xml", "application/javascript", "text/plain"];
35 | const contentType = htmlResponse.headers.get("content-type");
36 | const contentTypeArray = contentType.split(";");
37 | if (contentTypeArray[0] && !allowedContentTypes.includes(contentTypeArray[0])) {
38 | return `Error in get content of web: returned page was not utf8`;
39 | }
40 | const html = await htmlResponse.text();
41 | const $ = cheerio.load(html, { scriptingEnabled: true });
42 | let text = "";
43 | const rootElement = "body";
44 |
45 | $(`${rootElement} *`).not('style, script, svg').each((_i: any, elem: any) => {
46 | let content = $(elem).clone().children().remove().end().text().trim();
47 | // 如果内容中还包含 script 标签,则跳过此元素
48 | if ($(elem).find("script").length > 0) {
49 | return;
50 | }
51 | const $el = $(elem);
52 | let href = $el.attr("href");
53 | if ($el.prop("tagName")?.toLowerCase() === "a" && href) {
54 | if (!href.startsWith("http")) {
55 | try {
56 | href = new URL(href, url).toString();
57 | } catch {
58 | href = "";
59 | }
60 | }
61 | const imgAlt = $el.find("img[alt]").attr("alt")?.trim();
62 | if (imgAlt) {
63 | content += ` ${imgAlt}`;
64 | }
65 | text += ` [${content}](${href})`;
66 | } else if (content !== "") {
67 | text += ` ${content}`;
68 | }
69 | });
70 |
71 | return text.trim().replace(/\n+/g, " ");
72 | } catch (error) {
73 | return `Error in getHtml: ${error}`;
74 | }
75 | };
76 |
77 | return new Tool, any>>(paramsSchema, name, description, execute).tool;
78 | }
79 |
80 | export { createWebBrowser };
81 |
--------------------------------------------------------------------------------
/tsconfig.cjs.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "outDir": "dist/cjs"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/tsconfig.esm.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "module": "esnext",
5 | "outDir": "dist/esm"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "declaration": true,
4 | "target": "es6",
5 | "noImplicitAny": true,
6 | "esModuleInterop": true,
7 | "rootDir": ".",
8 | "typeRoots": ["node_modules/@types"],
9 | "skipLibCheck": true,
10 | "moduleResolution": "node"
11 | },
12 | "exclude": ["dist", "node_modules"]
13 | }
14 |
--------------------------------------------------------------------------------
/utils/isNode.ts:
--------------------------------------------------------------------------------
1 | // Mark not-as-node if in Supabase Edge Function
2 | export const isNode = () => {
3 | return typeof process !== "undefined" &&
4 | typeof process.versions !== "undefined" &&
5 | typeof process.versions.node !== "undefined"
6 | }
7 |
--------------------------------------------------------------------------------