11import * as Ariakit from "@ariakit/react" ;
2- import { ArrowPathIcon , SparklesIcon } from "@heroicons/react/20/solid" ;
2+ import { ArrowPathIcon } from "@heroicons/react/20/solid" ;
3+ import { DialogClose } from "@radix-ui/react-dialog" ;
34import { type MetaFunction , useFetcher } from "@remix-run/react" ;
45import {
56 type ActionFunctionArgs ,
67 json ,
78 type LoaderFunctionArgs ,
89 redirect ,
910} from "@remix-run/server-runtime" ;
10- import { DialogClose } from "@radix-ui/react-dialog" ;
1111
1212import { useCallback , useEffect , useRef , useState } from "react" ;
1313import { typedjson , useTypedLoaderData } from "remix-typedjson" ;
1414import { CodeBlock } from "~/components/code/CodeBlock" ;
1515import { TextEditor } from "~/components/code/TextEditor" ;
1616import { PageBody , PageContainer } from "~/components/layout/AppLayout" ;
17+ import { ModelsFilter } from "~/components/metrics/ModelsFilter" ;
18+ import { OperationsFilter } from "~/components/metrics/OperationsFilter" ;
19+ import { ProvidersFilter } from "~/components/metrics/ProvidersFilter" ;
20+ import { AppliedFilter } from "~/components/primitives/AppliedFilter" ;
1721import { Badge } from "~/components/primitives/Badge" ;
18- import { DateTime } from "~/components/primitives/DateTime" ;
1922import { Button } from "~/components/primitives/Buttons" ;
20- import { Header2 , Header3 } from "~/components/primitives/Headers" ;
23+ import { CopyButton } from "~/components/primitives/CopyButton" ;
24+ import { CopyableText } from "~/components/primitives/CopyableText" ;
25+ import { DateTime } from "~/components/primitives/DateTime" ;
2126import { Dialog , DialogContent , DialogHeader } from "~/components/primitives/Dialog" ;
27+ import { Header3 } from "~/components/primitives/Headers" ;
2228import { Hint } from "~/components/primitives/Hint" ;
2329import { Input } from "~/components/primitives/Input" ;
2430import { InputGroup } from "~/components/primitives/InputGroup" ;
2531import { Label } from "~/components/primitives/Label" ;
2632import { NavBar , PageAccessories , PageTitle } from "~/components/primitives/PageHeader" ;
2733import { Paragraph } from "~/components/primitives/Paragraph" ;
28- import { Spinner } from "~/components/primitives/Spinner" ;
2934import * as Property from "~/components/primitives/PropertyTable" ;
3035import {
3136 ResizableHandle ,
3237 ResizablePanel ,
3338 ResizablePanelGroup ,
3439 type ResizableSnapshot ,
3540} from "~/components/primitives/Resizable" ;
36- import { TabButton , TabContainer } from "~/components/primitives/Tabs" ;
37- import { CopyButton } from "~/components/primitives/CopyButton" ;
38- import { CopyableText } from "~/components/primitives/CopyableText" ;
3941import {
4042 SelectItem ,
4143 SelectList ,
4244 SelectPopover ,
4345 SelectProvider ,
4446 SelectTrigger ,
4547} from "~/components/primitives/Select" ;
48+ import { Spinner } from "~/components/primitives/Spinner" ;
49+ import { TabButton , TabContainer } from "~/components/primitives/Tabs" ;
4650import { TextArea } from "~/components/primitives/TextArea" ;
47- import { ModelsFilter } from "~/components/metrics/ModelsFilter" ;
48- import { OperationsFilter } from "~/components/metrics/OperationsFilter" ;
49- import { ProvidersFilter } from "~/components/metrics/ProvidersFilter" ;
50- import { AppliedFilter } from "~/components/primitives/AppliedFilter" ;
5151import tablerSpritePath from "~/components/primitives/tabler-sprite.svg" ;
5252import { TimeFilter } from "~/components/runs/v3/SharedFilters" ;
53- import { SpanView } from "~/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route " ;
53+ import { prisma } from "~/db.server " ;
5454import { useEnvironment } from "~/hooks/useEnvironment" ;
55+ import { useInterval } from "~/hooks/useInterval" ;
5556import { useOrganization } from "~/hooks/useOrganizations" ;
5657import { useProject } from "~/hooks/useProject" ;
57- import { prisma } from "~/db.server" ;
58- import { clickhouseClient } from "~/services/clickhouseInstance.server" ;
59- import { useInterval } from "~/hooks/useInterval" ;
6058import { useSearchParams } from "~/hooks/useSearchParam" ;
6159import { findProjectBySlug } from "~/models/project.server" ;
6260import { findEnvironmentBySlug } from "~/models/runtimeEnvironment.server" ;
63- import { PromptPresenter , type GenerationRow } from "~/presenters/v3/PromptPresenter.server" ;
61+ import { type GenerationRow , PromptPresenter } from "~/presenters/v3/PromptPresenter.server" ;
62+ import { SpanView } from "~/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route" ;
63+ import { clickhouseClient } from "~/services/clickhouseInstance.server" ;
6464import { getResizableSnapshot } from "~/services/resizablePanel.server" ;
6565import { requireUserId } from "~/services/session.server" ;
6666import { PromptService } from "~/v3/services/promptService.server" ;
6767
68- import { MetricWidget } from "~/routes/resources.metric " ;
69- import { InfoPanel } from "~/components/primitives/InfoPanel " ;
68+ import { z } from "zod " ;
69+ import { AIPromptsIcon } from "~/assets/icons/AIPromptsIcon " ;
7070import { InlineCode } from "~/components/code/InlineCode" ;
71+ import { InfoPanel } from "~/components/primitives/InfoPanel" ;
7172import { TextLink } from "~/components/primitives/TextLink" ;
73+ import { MetricWidget } from "~/routes/resources.metric" ;
7274import { EnvironmentParamSchema , v3PromptsPath , v3RunSpanPath } from "~/utils/pathBuilder" ;
7375import { parsePeriodToMs } from "~/utils/periods" ;
74- import { z } from "zod" ;
7576
7677const ParamSchema = EnvironmentParamSchema . extend ( {
7778 promptSlug : z . string ( ) ,
@@ -233,7 +234,11 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => {
233234 let generations : Awaited < ReturnType < typeof presenter . listGenerations > > [ "generations" ] = [ ] ;
234235 let generationsPagination : { next ?: string } = { } ;
235236 try {
236- const urlVersions = url . searchParams . getAll ( "versions" ) . filter ( Boolean ) . map ( Number ) . filter ( ( n ) => ! isNaN ( n ) ) ;
237+ const urlVersions = url . searchParams
238+ . getAll ( "versions" )
239+ . filter ( Boolean )
240+ . map ( Number )
241+ . filter ( ( n ) => ! isNaN ( n ) ) ;
237242 const urlModels = url . searchParams . getAll ( "models" ) . filter ( Boolean ) ;
238243 const urlOperations = url . searchParams . getAll ( "operations" ) . filter ( Boolean ) ;
239244 const urlProviders = url . searchParams . getAll ( "providers" ) . filter ( Boolean ) ;
@@ -284,7 +289,11 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => {
284289 const possibleProviders = provsErr ? [ ] : provsRows . map ( ( r ) => r . val ) ;
285290
286291 return typedjson ( {
287- resizable : { outer : resizableOuter , vertical : resizableVertical , generations : resizableGenerations } ,
292+ resizable : {
293+ outer : resizableOuter ,
294+ vertical : resizableVertical ,
295+ generations : resizableGenerations ,
296+ } ,
288297 prompt : {
289298 id : prompt . id ,
290299 friendlyId : prompt . friendlyId ,
@@ -520,20 +529,16 @@ export default function PromptDetailPage() {
520529 { overrideVersion && (
521530 < div className = "flex items-center justify-between bg-amber-500/10 px-4 py-2" >
522531 < span className = "text-xs text-amber-300" >
523- Override v{ overrideVersion . version } is active. API calls resolve this version instead of the deployed prompt.
532+ Override v{ overrideVersion . version } is active. API calls resolve this version instead of
533+ the deployed prompt.
524534 </ span >
525535 < div className = "flex items-center gap-2" >
526- < Button
527- variant = "tertiary/small"
528- onClick = { ( ) => setOverrideDialogOpen ( true ) }
529- >
536+ < Button variant = "tertiary/small" onClick = { ( ) => setOverrideDialogOpen ( true ) } >
530537 Edit
531538 </ Button >
532539 < Button
533540 variant = "tertiary/small"
534- onClick = { ( ) =>
535- fetcher . submit ( { intent : "removeOverride" } , { method : "POST" } )
536- }
541+ onClick = { ( ) => fetcher . submit ( { intent : "removeOverride" } , { method : "POST" } ) }
537542 disabled = { fetcher . state !== "idle" }
538543 >
539544 Remove
@@ -679,7 +684,13 @@ export default function PromptDetailPage() {
679684 < ResizableHandle id = "prompt-sidebar-handle" />
680685
681686 { /* Sidebar */ }
682- < ResizablePanel id = "prompt-sidebar" default = "380px" min = "280px" max = "500px" isStaticAtRest >
687+ < ResizablePanel
688+ id = "prompt-sidebar"
689+ default = "380px"
690+ min = "280px"
691+ max = "500px"
692+ isStaticAtRest
693+ >
683694 < div className = "grid h-full max-h-full grid-rows-[2rem_1fr] overflow-hidden bg-background-bright" >
684695 { /* Tabs */ }
685696 < div className = "overflow-x-auto px-3 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-charcoal-600" >
@@ -713,7 +724,9 @@ export default function PromptDetailPage() {
713724
714725 { /* Tab content */ }
715726 < div className = "overflow-y-auto px-3 py-3 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-charcoal-600" >
716- { tab === "details" && < DetailsTab prompt = { prompt } selectedVersion = { selectedVersion } /> }
727+ { tab === "details" && (
728+ < DetailsTab prompt = { prompt } selectedVersion = { selectedVersion } />
729+ ) }
717730 { tab === "preview" && < PreviewTab prompt = { prompt } content = { content } /> }
718731 { tab === "versions" && (
719732 < VersionsTab
@@ -731,9 +744,17 @@ export default function PromptDetailPage() {
731744 open = { overrideDialogOpen }
732745 onOpenChange = { setOverrideDialogOpen }
733746 prompt = { prompt }
734- content = { overrideVersion ? getVersionContent ( versions . find ( ( v ) => v . id === overrideVersion . id ) ?? { textContent : null } ) : content }
747+ content = {
748+ overrideVersion
749+ ? getVersionContent (
750+ versions . find ( ( v ) => v . id === overrideVersion . id ) ?? { textContent : null }
751+ )
752+ : content
753+ }
735754 isEditingOverride = { ! ! overrideVersion }
736- currentOverrideModel = { overrideVersion ? versions . find ( ( v ) => v . id === overrideVersion . id ) ?. model ?? null : null }
755+ currentOverrideModel = {
756+ overrideVersion ? versions . find ( ( v ) => v . id === overrideVersion . id ) ?. model ?? null : null
757+ }
737758 onSave = { ( textContent , commitMessage , model ) => {
738759 const intent = overrideVersion ? "updateOverride" : "saveVersion" ;
739760 fetcher . submit ( { intent, textContent, commitMessage, model } , { method : "POST" } ) ;
@@ -1230,7 +1251,11 @@ function GenerationsTab({
12301251 // Check poll results for new generations — only react to new poll data, not generation list changes
12311252 const lastPollDataRef = useRef ( pollFetcher . data ) ;
12321253 useEffect ( ( ) => {
1233- if ( pollFetcher . data && pollFetcher . state === "idle" && pollFetcher . data !== lastPollDataRef . current ) {
1254+ if (
1255+ pollFetcher . data &&
1256+ pollFetcher . state === "idle" &&
1257+ pollFetcher . data !== lastPollDataRef . current
1258+ ) {
12341259 lastPollDataRef . current = pollFetcher . data ;
12351260 const existingIds = new Set ( generations . map ( ( g ) => g . span_id ) ) ;
12361261 const newCount = pollFetcher . data . generations . filter (
@@ -1245,9 +1270,7 @@ function GenerationsTab({
12451270 if ( pollFetcher . data ) {
12461271 setGenerations ( ( prev ) => {
12471272 const existingIds = new Set ( prev . map ( ( g ) => g . span_id ) ) ;
1248- const newRows = pollFetcher . data ! . generations . filter (
1249- ( g ) => ! existingIds . has ( g . span_id )
1250- ) ;
1273+ const newRows = pollFetcher . data ! . generations . filter ( ( g ) => ! existingIds . has ( g . span_id ) ) ;
12511274 return newRows . length > 0 ? [ ...newRows , ...prev ] : prev ;
12521275 } ) ;
12531276 }
@@ -1359,8 +1382,8 @@ function GenerationsTab({
13591382 < div className = "flex h-full items-center justify-center" >
13601383 < InfoPanel
13611384 title = "No generations yet"
1362- icon = { SparklesIcon }
1363- iconClassName = "text-purple-500 "
1385+ icon = { AIPromptsIcon }
1386+ iconClassName = "text-aiPrompts "
13641387 panelClassName = "max-w-md"
13651388 >
13661389 < Paragraph variant = "small" >
@@ -1376,7 +1399,11 @@ function GenerationsTab({
13761399 }
13771400
13781401 return (
1379- < ResizablePanelGroup autosaveId = "prompt-generations" snapshot = { generationsSnapshot } className = "h-full" >
1402+ < ResizablePanelGroup
1403+ autosaveId = "prompt-generations"
1404+ snapshot = { generationsSnapshot }
1405+ className = "h-full"
1406+ >
13801407 { /* Span list */ }
13811408 < ResizablePanel id = "prompt-gen-list" min = "200px" >
13821409 < div
@@ -1452,10 +1479,7 @@ function GenerationsTab({
14521479 { /* Span inspector */ }
14531480 < ResizablePanel id = "prompt-gen-inspector" default = "40%" min = "200px" isStaticAtRest >
14541481 { selectedSpan ? (
1455- < SpanView
1456- runParam = { selectedSpan . runId }
1457- spanId = { selectedSpan . spanId }
1458- />
1482+ < SpanView runParam = { selectedSpan . runId } spanId = { selectedSpan . spanId } />
14591483 ) : (
14601484 < div className = "flex h-full items-center justify-center bg-background-bright" >
14611485 < Paragraph variant = "small" className = "text-text-dimmed" >
@@ -1810,10 +1834,7 @@ function PromptVersionsFilter({ versions }: { versions: VersionData[] }) {
18101834 ) ;
18111835 }
18121836
1813- const summary =
1814- selected . length === 1
1815- ? `v${ selected [ 0 ] } `
1816- : `${ selected . length } versions` ;
1837+ const summary = selected . length === 1 ? `v${ selected [ 0 ] } ` : `${ selected . length } versions` ;
18171838
18181839 return (
18191840 < SelectProvider value = { selected } setValue = { handleChange } virtualFocus = { true } >
0 commit comments