Files
Hayden Bleasel 30cbcfec97 Migrate to Oxlint (#357)
* Migrate to oxlint / oxfmt

* Initial fixes

* Misc fixes

* Temporary fixes

* Update Ultracite

* Update .oxlintrc.json

* Update .oxlintrc.json

* Start running manual fixes

* Update .oxlintrc.json

* AI Fixes Part 2

* AI Fixes Part 3

* AI Fixes Part 4

* AI Fixes Part 5

* AI Fixes Part 6

* AI Fixes Part 7

* AI Fixes Part 8

* AI Fixes Part 9

* AI Fixes Part 10

* AI Fixes Part 11

* AI Fixes Part 12

* Fix tests

* Lint / test fixes

* Update chat.tsx

* Fix AI SDK React version

* Misc fixes

* Build fixes
2026-02-04 08:00:41 -08:00

75 lines
1.9 KiB
TypeScript

import { Shimmer } from "@repo/elements/shimmer";
import {
Source,
Sources,
SourcesContent,
SourcesTrigger,
} from "@repo/elements/sources";
import { isToolUIPart } from "ai";
import { BookmarkIcon } from "lucide-react";
import type { MyUIMessage } from "@/app/api/chat/types";
interface MessageMetadataProps {
parts: MyUIMessage["parts"];
inProgress: boolean;
}
export const MessageMetadata = ({
parts,
inProgress,
}: MessageMetadataProps) => {
// Pull out last part that is either text or tool call
const lastPart = parts
.filter((part) => part.type === "text" || isToolUIPart(part))
.at(-1);
if (!lastPart) {
return <Shimmer className="text-xs">Thinking...</Shimmer>;
}
const tool = isToolUIPart(lastPart) ? lastPart : null;
const hasTextPart = parts.some((part) => part.type === "text");
const sources = [
...new Map(
parts
.filter((part) => part.type === "source-url")
.map((part) => [part.url, part])
).values(),
];
// Show loading state when sources exist but text hasn't arrived yet
if (sources.length > 0 && !hasTextPart && inProgress) {
return <Shimmer className="text-xs">Searching sources...</Shimmer>;
}
if (sources.length > 0 && !(tool && inProgress)) {
return (
<Sources>
<SourcesTrigger count={sources.length}>
<BookmarkIcon className="size-4" />
<p>Used {sources.length} sources</p>
</SourcesTrigger>
<SourcesContent>
<ul className="flex flex-col gap-2">
{sources.map((source) => (
<li className="ml-4.5 list-disc pl-1" key={source.url}>
<Source href={source.url} title={source.url}>
{source.title}
</Source>
</li>
))}
</ul>
</SourcesContent>
</Sources>
);
}
if (!tool && sources.length === 0) {
return null;
}
return <div className="h-12" />;
};