diff --git a/app/(playground)/p/[agentId]/beta-proto/components/icons/circle-check.tsx b/app/(playground)/p/[agentId]/beta-proto/components/icons/circle-check.tsx index efd3fca9..9fa3f345 100644 --- a/app/(playground)/p/[agentId]/beta-proto/components/icons/circle-check.tsx +++ b/app/(playground)/p/[agentId]/beta-proto/components/icons/circle-check.tsx @@ -8,6 +8,7 @@ export const CircleCheckIcon: FC> = (props) => ( xmlns="http://www.w3.org/2000/svg" {...props} > + Circle Check Icon diff --git a/app/(playground)/p/[agentId]/beta-proto/components/icons/circle-x.tsx b/app/(playground)/p/[agentId]/beta-proto/components/icons/circle-x.tsx new file mode 100644 index 00000000..b1453c0d --- /dev/null +++ b/app/(playground)/p/[agentId]/beta-proto/components/icons/circle-x.tsx @@ -0,0 +1,21 @@ +import type { FC, SVGProps } from "react"; + +export const CircleXIcon: FC> = (props) => ( + + Circle X Icon + + + + + + + + + +); diff --git a/app/(playground)/p/[agentId]/beta-proto/web-search/server-action.ts b/app/(playground)/p/[agentId]/beta-proto/web-search/server-action.ts index 9e43b52e..efba5275 100644 --- a/app/(playground)/p/[agentId]/beta-proto/web-search/server-action.ts +++ b/app/(playground)/p/[agentId]/beta-proto/web-search/server-action.ts @@ -13,6 +13,7 @@ import type { GiselleNode } from "../giselle-node/types"; import { webSearchSchema } from "./schema"; import { search } from "./tavily"; import { + type FailedWebSearchItemReference, type WebSearch, type WebSearchItemReference, webSearchItemStatus, @@ -119,26 +120,45 @@ export async function generateWebSearchStream( await Promise.all( chunkedArray.map(async (webSearchItems) => { for (const webSearchItem of webSearchItems) { - const scrapeResponse = await app.scrapeUrl(webSearchItem.url, { - formats: ["markdown"], - }); - if (scrapeResponse.success) { - const blob = await put( - `webSearch/${webSearchItem.id}.md`, - scrapeResponse.markdown ?? "", - { - access: "public", - contentType: "text/markdown", - }, - ); + try { + const scrapeResponse = await app.scrapeUrl(webSearchItem.url, { + formats: ["markdown"], + }); + if (scrapeResponse.success) { + const blob = await put( + `webSearch/${webSearchItem.id}.md`, + scrapeResponse.markdown ?? "", + { + access: "public", + contentType: "text/markdown", + }, + ); + mutableItems = mutableItems.map((item) => { + if (item.id !== webSearchItem.id) { + return item; + } + return { + ...webSearchItem, + contentBlobUrl: blob.url, + status: webSearchItemStatus.completed, + }; + }); + stream.update({ + ...result, + webSearch: { + ...webSearch, + items: mutableItems, + }, + }); + } + } catch { mutableItems = mutableItems.map((item) => { if (item.id !== webSearchItem.id) { return item; } return { ...webSearchItem, - contentBlobUrl: blob.url, - status: webSearchItemStatus.completed, + status: webSearchItemStatus.failed, }; }); stream.update({ diff --git a/app/(playground)/p/[agentId]/beta-proto/web-search/types.ts b/app/(playground)/p/[agentId]/beta-proto/web-search/types.ts index e0fd797a..b91cd2c6 100644 --- a/app/(playground)/p/[agentId]/beta-proto/web-search/types.ts +++ b/app/(playground)/p/[agentId]/beta-proto/web-search/types.ts @@ -28,6 +28,7 @@ export const webSearchItemStatus = { pending: "pending", processing: "processing", completed: "completed", + failed: "failed", } as const; type WebSearchItemStatus = @@ -44,7 +45,7 @@ export interface WebSearchItem { interface PendingWebSearchItemReference { id: WebSearchContentId; object: "webSearch.item.reference"; - status: Extract; + status: Extract; title: string; url: string; relevance: number; @@ -52,15 +53,24 @@ interface PendingWebSearchItemReference { interface CompletedWebSearchItemReference { id: WebSearchContentId; object: "webSearch.item.reference"; - status: Extract; + status: Extract; title: string; contentBlobUrl: string; url: string; relevance: number; } +export interface FailedWebSearchItemReference { + id: WebSearchContentId; + object: "webSearch.item.reference"; + status: Extract; + title: string; + url: string; + relevance: number; +} export type WebSearchItemReference = | PendingWebSearchItemReference - | CompletedWebSearchItemReference; + | CompletedWebSearchItemReference + | FailedWebSearchItemReference; export interface GeneratedObject { plan: string; webSearch: WebSearch; diff --git a/app/(playground)/p/[agentId]/beta-proto/web-search/websearch-block.tsx b/app/(playground)/p/[agentId]/beta-proto/web-search/websearch-block.tsx index 7c1e41c2..2d60ed0b 100644 --- a/app/(playground)/p/[agentId]/beta-proto/web-search/websearch-block.tsx +++ b/app/(playground)/p/[agentId]/beta-proto/web-search/websearch-block.tsx @@ -1,6 +1,7 @@ import { CopyIcon } from "lucide-react"; import { Dialog, DialogContent, DialogTrigger } from "../components/dialog"; import { CircleCheckIcon } from "../components/icons/circle-check"; +import { CircleXIcon } from "../components/icons/circle-x"; import { DocumentIcon } from "../components/icons/document"; import { SpinnerIcon } from "../components/icons/spinner"; import { Block } from "../giselle-node/components/panel/block"; @@ -62,6 +63,8 @@ export function WebSearchBlock(props: WebSearchBlockProps) { {item.status === webSearchItemStatus.completed ? ( + ) : item.status === webSearchItemStatus.failed ? ( + ) : ( "" )}