|
1 | 1 | import { env } from "cloudflare:workers"; |
2 | 2 | import { createMCPClient } from "@ai-sdk/mcp"; |
| 3 | +import { createOpenRouter } from "@openrouter/ai-sdk-provider"; |
3 | 4 | import { createClient } from "@sanity/client"; |
4 | 5 | import { isStepCount, jsonSchema, streamText, tool } from "ai"; |
5 | 6 | import type { APIRoute } from "astro"; |
6 | | -import { createOpenRouter } from "@openrouter/ai-sdk-provider"; |
7 | 7 | import { createWorkersAI } from "workers-ai-provider"; |
8 | 8 | import { |
9 | 9 | semanticSearchQuery, |
@@ -179,15 +179,21 @@ export const POST: APIRoute = async ({ request }) => { |
179 | 179 | results = res; |
180 | 180 | } |
181 | 181 | } catch (semanticErr) { |
182 | | - console.warn("[search_content semantic error, falling back]", semanticErr); |
| 182 | + console.warn( |
| 183 | + "[search_content semantic error, falling back]", |
| 184 | + semanticErr, |
| 185 | + ); |
183 | 186 | } |
184 | 187 |
|
185 | 188 | if (!results.length) { |
186 | 189 | try { |
187 | | - const fallback = await sanityClient.fetch(textSearchFallbackQuery, { |
188 | | - searchTerm: query, |
189 | | - type: filterType, |
190 | | - }); |
| 190 | + const fallback = await sanityClient.fetch( |
| 191 | + textSearchFallbackQuery, |
| 192 | + { |
| 193 | + searchTerm: query, |
| 194 | + type: filterType, |
| 195 | + }, |
| 196 | + ); |
191 | 197 | if (Array.isArray(fallback)) { |
192 | 198 | results = fallback; |
193 | 199 | } |
@@ -271,9 +277,7 @@ export const POST: APIRoute = async ({ request }) => { |
271 | 277 | {} as any, |
272 | 278 | ); |
273 | 279 | const parsed = |
274 | | - typeof mcpResult === "string" |
275 | | - ? JSON.parse(mcpResult) |
276 | | - : mcpResult; |
| 280 | + typeof mcpResult === "string" ? JSON.parse(mcpResult) : mcpResult; |
277 | 281 | const results = |
278 | 282 | parsed?.result || |
279 | 283 | (Array.isArray(parsed?.content) && parsed.content[0]?.text |
@@ -307,16 +311,26 @@ export const POST: APIRoute = async ({ request }) => { |
307 | 311 | } |
308 | 312 |
|
309 | 313 | // If still empty and query was a search for a keyword, extract keyword and run semantic search |
310 | | - const matchTerm = query.match(/match\s+["']\*?([a-zA-Z0-9_-]+)\*?["']/); |
| 314 | + const matchTerm = query.match( |
| 315 | + /match\s+["']\*?([a-zA-Z0-9_-]+)\*?["']/, |
| 316 | + ); |
311 | 317 | if (matchTerm?.[1]) { |
312 | 318 | const keyword = matchTerm[1]; |
313 | | - const typeMatch = query.match(/_type\s*==\s*["']([a-zA-Z0-9_-]+)["']/); |
| 319 | + const typeMatch = query.match( |
| 320 | + /_type\s*==\s*["']([a-zA-Z0-9_-]+)["']/, |
| 321 | + ); |
314 | 322 | const filterType = typeMatch?.[1] || null; |
315 | | - const semanticResults = await sanityClient.fetch(semanticSearchQuery, { |
316 | | - searchTerm: keyword, |
317 | | - type: filterType, |
318 | | - }); |
319 | | - if (Array.isArray(semanticResults) && semanticResults.length > 0) { |
| 323 | + const semanticResults = await sanityClient.fetch( |
| 324 | + semanticSearchQuery, |
| 325 | + { |
| 326 | + searchTerm: keyword, |
| 327 | + type: filterType, |
| 328 | + }, |
| 329 | + ); |
| 330 | + if ( |
| 331 | + Array.isArray(semanticResults) && |
| 332 | + semanticResults.length > 0 |
| 333 | + ) { |
320 | 334 | return semanticResults.slice(0, 10).map((item: any) => ({ |
321 | 335 | title: item.title, |
322 | 336 | type: item._type, |
@@ -384,7 +398,7 @@ export const POST: APIRoute = async ({ request }) => { |
384 | 398 | "- When asked for 'top videos' or popular video podcasts, search for high-profile episodes with video recordings (e.g. episodes featuring Guillermo Rauch, Rich Harris, Lee Robinson, or recent GenAI/MCP video podcasts) and provide their YouTube links alongside CodingCat.dev episode links.\n" + |
385 | 399 | "- Use `groq_query` for precise lookups when searching for specific author profiles (e.g. *[_type == 'author' && title match '*Alex*']).\n" + |
386 | 400 | "- CRITICAL: ALWAYS execute tools by invoking them via function calls. NEVER output raw JSON or code blocks in your text describing tool calls instead of executing them.\n" + |
387 | | - "- Once you receive results from your tool calls, synthesize them into an engaging, helpful response. List the relevant episode or article titles, brief descriptions, and markdown links using relative paths (e.g. [Episode Title](/podcast/slug) or [Post Title](/post/slug)). When YouTube links are available, always include them directly on their own line (e.g. https://www.youtube.com/watch?v=VIDEO_ID or https://youtu.be/VIDEO_ID). NEVER output localhost URLs, internal IP addresses, or malformed URL brackets like [\"/slug\"](http://localhost:3000/slug).", |
| 401 | + '- Once you receive results from your tool calls, synthesize them into an engaging, helpful response. List the relevant episode or article titles, brief descriptions, and markdown links using relative paths (e.g. [Episode Title](/podcast/slug) or [Post Title](/post/slug)). When YouTube links are available, always include them directly on their own line (e.g. https://www.youtube.com/watch?v=VIDEO_ID or https://youtu.be/VIDEO_ID). NEVER output localhost URLs, internal IP addresses, or malformed URL brackets like ["/slug"](http://localhost:3000/slug).', |
388 | 402 | messages: coreMessages, |
389 | 403 | tools, |
390 | 404 | stopWhen: isStepCount(5), |
|
0 commit comments