Skip to content

Commit d693942

Browse files
authored
Agents Page: Part 1 (#1783)
1 parent 66db158 commit d693942

File tree

26 files changed

+13332
-4282
lines changed

26 files changed

+13332
-4282
lines changed

apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/_components/Sidebar/ProjectSection/index.tsx

Lines changed: 48 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -83,58 +83,62 @@ export default function ProjectSection({
8383
limitedView?: boolean
8484
}) {
8585
const runs = useFeature('runs')
86+
const agentFeature = useFeature('newAgentPage')
8687

8788
const disableRunsNotifications = limitedView || !runs.isEnabled
8889
const { data: active } = useActiveRunsCount({
8990
project: project,
9091
realtime: !disableRunsNotifications,
9192
})
9293

93-
const PROJECT_ROUTES = useMemo(() => {
94-
const runsRoute = []
95-
96-
if (runs.isEnabled) {
97-
runsRoute.push({
98-
label: 'Runs',
99-
route: ROUTES.projects
100-
.detail({ id: project.id })
101-
.commits.detail({ uuid: commit.uuid }).runs.root,
102-
iconName: 'logs',
103-
notifications: {
104-
count: disableRunsNotifications ? 0 : active,
105-
label: (count: number) =>
106-
count <= 1
107-
? 'There is a run in progress'
108-
: `There are ${count} runs in progress`,
94+
const PROJECT_ROUTES = useMemo(
95+
() =>
96+
[
97+
agentFeature.isEnabled && {
98+
label: 'Agent',
99+
route: ROUTES.projects
100+
.detail({ id: project.id })
101+
.commits.detail({ uuid: commit.uuid }).agent.root,
102+
iconName: 'bot',
109103
},
110-
})
111-
}
112-
113-
return [
114-
{
115-
label: 'Preview',
116-
route: ROUTES.projects
117-
.detail({ id: project.id })
118-
.commits.detail({ uuid: commit.uuid }).preview.root,
119-
iconName: 'eye',
120-
},
121-
...runsRoute,
122-
{
123-
label: 'Analytics',
124-
route: ROUTES.projects
125-
.detail({ id: project.id })
126-
.commits.detail({ uuid: commit.uuid }).analytics.root,
127-
iconName: 'barChart4',
128-
},
129-
{
130-
label: 'History',
131-
route: ROUTES.projects
132-
.detail({ id: project.id })
133-
.commits.detail({ uuid: commit.uuid }).history.root,
134-
iconName: 'history',
135-
},
136-
] as ProjectRoute[]
137-
}, [project, commit, runs, active, disableRunsNotifications])
104+
{
105+
label: 'Preview',
106+
route: ROUTES.projects
107+
.detail({ id: project.id })
108+
.commits.detail({ uuid: commit.uuid }).preview.root,
109+
iconName: 'eye',
110+
},
111+
runs.isEnabled && {
112+
label: 'Runs',
113+
route: ROUTES.projects
114+
.detail({ id: project.id })
115+
.commits.detail({ uuid: commit.uuid }).runs.root,
116+
iconName: 'logs',
117+
notifications: {
118+
count: disableRunsNotifications ? 0 : active,
119+
label: (count: number) =>
120+
count <= 1
121+
? 'There is a run in progress'
122+
: `There are ${count} runs in progress`,
123+
},
124+
},
125+
{
126+
label: 'Analytics',
127+
route: ROUTES.projects
128+
.detail({ id: project.id })
129+
.commits.detail({ uuid: commit.uuid }).analytics.root,
130+
iconName: 'barChart4',
131+
},
132+
{
133+
label: 'History',
134+
route: ROUTES.projects
135+
.detail({ id: project.id })
136+
.commits.detail({ uuid: commit.uuid }).history.root,
137+
iconName: 'history',
138+
},
139+
].filter(Boolean) as ProjectRoute[],
140+
[project, commit, agentFeature, runs, active, disableRunsNotifications],
141+
)
138142

139143
return (
140144
<div className='flex flex-col gap-2'>
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
'use client'
2+
3+
import { useCurrentCommit } from '$/app/providers/CommitProvider'
4+
import { usePlaygroundChat } from '$/hooks/playgroundChat/usePlaygroundChat'
5+
import { useRunDocument } from '../../documents/[documentUuid]/_components/DocumentEditor/Editor/Playground/hooks/useRunDocument'
6+
import { useCallback, useState } from 'react'
7+
import { DocumentVersion } from '@latitude-data/core/schema/types'
8+
import { MainAgentSection } from './MainSection'
9+
import { AgentChatSection } from './ChatSection'
10+
import { cn } from '@latitude-data/web-ui/utils'
11+
12+
export function AgentPageWrapper() {
13+
const { commit } = useCurrentCommit()
14+
15+
const [parameters, setParameters] = useState<Record<string, unknown>>({})
16+
17+
const { runDocument, addMessages, abortCurrentStream, hasActiveStream } =
18+
useRunDocument({
19+
commit,
20+
})
21+
22+
const runPromptFn = useCallback(
23+
({
24+
document,
25+
userMessage,
26+
parameters = {},
27+
aiParameters = false,
28+
}: {
29+
document: DocumentVersion
30+
parameters: Record<string, unknown>
31+
userMessage: string | undefined
32+
aiParameters: boolean
33+
}) =>
34+
runDocument({
35+
document,
36+
parameters,
37+
userMessage,
38+
aiParameters,
39+
}),
40+
[runDocument],
41+
)
42+
43+
const playground = usePlaygroundChat({
44+
runPromptFn,
45+
addMessagesFn: addMessages,
46+
onPromptRan: (documentLogUuid, error) => {
47+
if (!documentLogUuid || error) return
48+
},
49+
})
50+
51+
const onRunPrompt = useCallback(
52+
({
53+
document,
54+
parameters,
55+
userMessage,
56+
aiParameters,
57+
}: {
58+
document: DocumentVersion
59+
parameters: Record<string, unknown>
60+
userMessage: string
61+
aiParameters: boolean
62+
}) => {
63+
setParameters(parameters)
64+
playground.start({ document, parameters, userMessage, aiParameters })
65+
},
66+
[playground, setParameters],
67+
)
68+
69+
return (
70+
<div className='relative w-full h-full overflow-hidden'>
71+
<div
72+
className={cn(
73+
'absolute h-[200%] w-full grid grid-rows-2',
74+
'transition-transform duration-500 ',
75+
{
76+
'-translate-y-1/2': playground.mode === 'chat',
77+
},
78+
)}
79+
>
80+
<div
81+
className={cn('h-full transition-opacity duration-500', {
82+
'opacity-100': playground.mode === 'preview',
83+
'opacity-0': playground.mode === 'chat',
84+
})}
85+
>
86+
<MainAgentSection runPromptFn={onRunPrompt} />
87+
</div>
88+
<div
89+
className={cn('h-full transition-opacity duration-500', {
90+
'opacity-100': playground.mode === 'chat',
91+
'opacity-0': playground.mode === 'preview',
92+
})}
93+
>
94+
<AgentChatSection
95+
playground={playground}
96+
parameters={parameters}
97+
onClose={() => playground.reset()}
98+
abortCurrentStream={abortCurrentStream}
99+
hasActiveStream={hasActiveStream}
100+
/>
101+
</div>
102+
</div>
103+
</div>
104+
)
105+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { PlaygroundChat } from '$/hooks/playgroundChat/usePlaygroundChat'
2+
import Chat from '../../../documents/[documentUuid]/_components/DocumentEditor/Editor/V2Playground/Chat'
3+
import { Button } from '@latitude-data/web-ui/atoms/Button'
4+
import { useRef, useState } from 'react'
5+
import { ChatInputBox } from '../../../documents/[documentUuid]/_components/DocumentEditor/Editor/ChatInputBox'
6+
import { useAutoScroll } from '@latitude-data/web-ui/hooks/useAutoScroll'
7+
8+
export function AgentChatSection({
9+
playground,
10+
parameters,
11+
hasActiveStream,
12+
abortCurrentStream,
13+
onClose,
14+
}: {
15+
playground: PlaygroundChat
16+
parameters: Record<string, unknown>
17+
hasActiveStream: () => boolean
18+
abortCurrentStream: () => void
19+
onClose: () => void
20+
}) {
21+
const [expandedParameters, setExpandedParameters] = useState(false)
22+
23+
const ref = useRef<HTMLDivElement | null>(null)
24+
25+
useAutoScroll(ref, { startAtBottom: true })
26+
27+
return (
28+
<div
29+
className='flex flex-col w-full h-full custom-scrollbar items-center'
30+
ref={ref}
31+
>
32+
<div className='sticky top-0 flex flex-row w-full items-center justify-center'>
33+
<Button
34+
variant='ghost'
35+
iconProps={{
36+
name: 'chevronUp',
37+
}}
38+
fullWidth
39+
onClick={onClose}
40+
>
41+
Back to agent
42+
</Button>
43+
</div>
44+
<div className='flex-1 flex flex-col w-full max-w-[800px] flex-grow min-h-0 justify-between'>
45+
<div className='flex-1 pb-20'>
46+
<Chat
47+
showHeader
48+
playground={playground}
49+
parameters={parameters}
50+
expandParameters={expandedParameters}
51+
setExpandParameters={setExpandedParameters}
52+
/>
53+
</div>
54+
<div className='sticky bottom-0 w-full bg-background pb-4'>
55+
<ChatInputBox
56+
resetChat={playground.reset}
57+
hasActiveStream={hasActiveStream}
58+
playground={playground}
59+
abortCurrentStream={abortCurrentStream}
60+
placeholder='Ask anything'
61+
onBack={playground.reset}
62+
onBackLabel='Back to triggers'
63+
isRunStream={false}
64+
/>
65+
</div>
66+
</div>
67+
</div>
68+
)
69+
}

0 commit comments

Comments
 (0)