-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhandler.js
More file actions
124 lines (108 loc) · 4.04 KB
/
Copy pathhandler.js
File metadata and controls
124 lines (108 loc) · 4.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// ============================================================
// Generic Website — Tool Handlers
// Fetch-based tools for any website
// ============================================================
/**
* Search the website content.
* @param {object} input
* @param {string} input.query - Search query
* @param {number} [input.limit=10] - Maximum number of results
* @param {object} context
* @param {string} context.baseUrl - Website base URL
* @param {function} context.fetch - Fetch function
*/
export async function search(input, context) {
const { baseUrl, fetch } = context;
const url = new URL('/api/search', baseUrl);
url.searchParams.set('q', input.query);
url.searchParams.set('limit', String(input.limit || 10));
const res = await fetch(url.toString());
if (!res.ok) throw new Error(`Search API error: ${res.status}`);
const data = await res.json();
return (data.results || data).map((r) => ({
title: r.title,
url: r.url || r.path,
excerpt: r.excerpt || r.snippet || r.description,
score: r.score,
}));
}
/**
* Get structured information about a specific page.
* @param {object} input
* @param {string} input.path - Page path relative to the site root
* @param {object} context
*/
export async function get_page_info(input, context) {
const { baseUrl, fetch } = context;
const pagePath = input.path.startsWith('/') ? input.path : `/${input.path}`;
const res = await fetch(new URL(pagePath, baseUrl).toString());
if (!res.ok) throw new Error(`Page not found: ${res.status}`);
const html = await res.text();
// Extract basic info from HTML
const title = html.match(/<title[^>]*>([^<]+)<\/title>/i)?.[1]?.trim() || '';
const metaDesc = html.match(/<meta[^>]+name=["']description["'][^>]+content=["']([^"']+)["']/i)?.[1] || '';
const h1 = html.match(/<h1[^>]*>([^<]+)<\/h1>/i)?.[1]?.trim() || '';
// Extract headings
const headings = [];
const headingRegex = /<(h[1-6])[^>]*>(.*?)<\/\1>/gi;
let match;
while ((match = headingRegex.exec(html)) !== null) {
headings.push({
level: parseInt(match[1][1]),
text: match[2].replace(/<[^>]+>/g, '').trim(),
});
}
return {
title: title || h1,
description: metaDesc,
headings: headings.slice(0, 20),
url: new URL(pagePath, baseUrl).toString(),
};
}
/**
* Submit a form on the website.
* @param {object} input
* @param {string} input.formId - Identifier of the form (e.g. 'contact', 'newsletter')
* @param {object} input.fields - Key-value pairs of form fields
* @param {object} context
*/
export async function submit_form(input, context) {
const { baseUrl, fetch } = context;
const url = new URL(`/api/forms/${input.formId}`, baseUrl);
const res = await fetch(url.toString(), {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(input.fields),
});
if (!res.ok) {
const err = await res.json().catch(() => ({}));
throw new Error(err.message || `Form submission failed: ${res.status}`);
}
const data = await res.json();
return {
success: true,
message: data.message || 'Form submitted successfully',
id: data.id || data.submission_id,
};
}
/**
* List all available pages and their descriptions.
* @param {object} input
* @param {string} [input.section] - Optional section filter
* @param {object} context
*/
export async function list_pages(input, context) {
const { baseUrl, fetch } = context;
const url = new URL('/api/pages', baseUrl);
if (input.section) url.searchParams.set('section', input.section);
const res = await fetch(url.toString());
if (!res.ok) throw new Error(`Pages API error: ${res.status}`);
const data = await res.json();
return (data.pages || data).map((p) => ({
title: p.title,
path: p.path || p.url,
description: p.description,
section: p.section || p.category,
lastModified: p.last_modified || p.updated_at,
}));
}