11 * Creates a tool for making HTTP requests to vals in a Val Town project
12 */
13export const makeFetchTool = (
14 { bearerToken, project, branch_id }: { bearerToken?: string; project?: any; branch_id?: string } = {},
15) =>
16 tool({
17 name: "fetch",
18 description: "Make an HTTP request to a Val Town val and return the response. Useful for testing HTTP vals.",
19 parameters: z.object({
68 return {
69 type: "error",
70 message: `Error fetching val at path '${valPath}': ${error.message}`,
71 };
72 }
83 return {
84 type: "error",
85 message: `The val at path '${valPath}' is not an HTTP val. Only HTTP vals can be called with fetch.`,
86 };
87 }
111 let response;
112 try {
113 response = await fetch(valEndpoint + urlPath, options);
114 } catch (error: any) {
115 // Return error information
239
240 // Inject data to avoid extra round-trips
241 const initialData = await fetchInitialData();
242 const dataScript = `<script>
243 window.__INITIAL_DATA__ = ${JSON.stringify(initialData)};
286
2875. **API Design:**
288 - `fetch` handler is the entry point for HTTP vals
289 - Run the Hono app with `export default app.fetch // This is the entry point for HTTP vals`
290
291
49 files={project.data?.files}
50 branchId={branchId}
51 refetch={project.refetch}
52 />
53 </ProjectContext>
59 files,
60 branchId,
61 refetch,
62}: {
63 project: any;
64 files: any[];
65 branchId: string;
66 refetch: () => void;
67}) {
68 const [images, setImages] = useState<(string|null)[]>([]);
94 if (!messages?.length) return;
95 let last = messages.at(-1);
96 if (shouldRefetch(last)) {
97 refetch();
98 }
99 }, [messages]);
194}
195
196function shouldRefetch (message) {
197 for (let i = 0; i < message?.parts?.length; i++) {
198 let part = message.parts[i];
32 return;
33 }
34 branches.refetch();
35 if (res?.branch?.id) {
36 navigate(`/chat/${projectId}/branch/${res.branch.id}`);
32});
33
34export default app.fetch;
21});
22
23// HTTP vals expect an exported "fetch handler"
24// This is how you "run the server" in Val Town with Hono
25export default app.fetch;
25 try {
26 // 2) 拉字幕
27 const transcript = await YoutubeTranscript.fetchTranscript(videoId, { lang });
28
29 if (!transcript.length) {
38 headers: {
39 "Content-Type": "text/plain; charset=utf-8",
40 "Access-Control-Allow-Origin": "*", // 跨域方便前端直接 fetch
41 },
42 });
54 console.error(err);
55 // youtube-transcript 会在抓不到自动字幕时抛错
56 return txt("Error fetching transcript", 500);
57 }
58}
138for (let i = 2; i <= pagesTotal; i++) {
139 console.log(`Processing page ${i}/${pagesTotal}...`);
140 const res = await fetch(url(i));
141 const text = await res.text();
142
8 const [error, setError] = useState(null);
9
10 const fetchData = async () => {
11 try {
12 const userEndpoint = new URL(USER_ENDPOINT, window.location.origin);
13
14 const res = await fetch(userEndpoint);
15 const data = await res.json();
16 if (!res.ok) {
33
34 useEffect(() => {
35 fetchData();
36 }, []);
37
38 return { data, loading, error, refetch: fetchData };
39}
40
9 const [error, setError] = useState(null);
10
11 const fetchData = async () => {
12 try {
13 const projectEndpoint = new URL(PROJECT_ENDPOINT, window.location.origin);
17 if (branchId) filesEndpoint.searchParams.append("branchId", branchId);
18
19 const { project } = await fetch(projectEndpoint).then((res) =>
20 res.json()
21 );
22 const { files } = await fetch(filesEndpoint).then((res) => res.json());
23
24 setData({ project, files });
34 useEffect(() => {
35 if (!projectId) return;
36 fetchData();
37 }, [projectId, branchId]);
38
39 return { data, loading, error, refetch: fetchData };
40}
41