-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #86 from yello-xyz/v0.12
V0.12
- Loading branch information
Showing
109 changed files
with
2,345 additions
and
884 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import { ExtractPromptVariables, ExtractVariables } from '@/src/common/formatting' | ||
import { ChainItemWithInputs, PromptConfig, Prompts } from '@/types' | ||
import { DefaultConfig } from '@/src/common/defaultConfig' | ||
import { ExtractUnboundChainInputs } from '@/components/chains/chainNodeOutput' | ||
|
||
const testExtractVariables = (testDescription: string, expectedVariables: string[], content: string) => | ||
test(`Test ${testDescription}`, () => { | ||
expect(ExtractVariables(content)).toStrictEqual(expectedVariables) | ||
}) | ||
|
||
testExtractVariables('empty content', [], '') | ||
testExtractVariables('no variables', [], 'hello world') | ||
testExtractVariables('non variable', [], '}}hello{{') | ||
testExtractVariables('single variable', ['hello'], '{{hello}}') | ||
testExtractVariables('single variable start', ['hello'], '{{hello}} world') | ||
testExtractVariables('single variable end', ['world'], 'hello {{world}}') | ||
|
||
const configWithFunctionsSupport: PromptConfig = { ...DefaultConfig, model: 'gpt-4' } | ||
|
||
const buildPrompt = (main: string, system?: string, functions?: string): Prompts => ({ main, system, functions }) | ||
|
||
const testExtractPromptVariables = ( | ||
testDescription: string, | ||
expectedVariables: string[], | ||
prompts: Prompts, | ||
includingDynamic = true | ||
) => | ||
test(`Test ${testDescription}`, () => { | ||
expect(ExtractPromptVariables(prompts, configWithFunctionsSupport, includingDynamic)).toStrictEqual( | ||
expectedVariables | ||
) | ||
}) | ||
|
||
testExtractPromptVariables('empty prompts', [], buildPrompt('')) | ||
testExtractPromptVariables('main prompt', ['hello'], buildPrompt('{{hello}}')) | ||
testExtractPromptVariables('system prompt', ['hello', 'world'], buildPrompt('{{hello}}', '{{world}}')) | ||
testExtractPromptVariables('functions prompt', ['hello', 'world'], buildPrompt('{{hello}}', '', '{{world}}')) | ||
testExtractPromptVariables('include dynamic', ['hello_world'], buildPrompt('', '', '[{ "name": "hello_world" }]')) | ||
testExtractPromptVariables('exclude dynamic', [], buildPrompt('', '', '[{ "name": "hello_world" }]'), false) | ||
|
||
const buildChain = (inputs: string[], outputs: string[]): ChainItemWithInputs[] => | ||
inputs.map((input, index) => ({ | ||
code: '', | ||
inputs: input ? [input] : [], | ||
output: outputs[index], | ||
})) | ||
|
||
const testExtractChainVariables = ( | ||
testDescription: string, | ||
expectedVariables: string[], | ||
inputs: string[], | ||
outputs: string[] = [] | ||
) => | ||
test(`Test ${testDescription}`, () => { | ||
expect(ExtractUnboundChainInputs(buildChain(inputs, outputs), false)).toStrictEqual(expectedVariables) | ||
}) | ||
|
||
testExtractChainVariables('empty chain', [], [], []) | ||
testExtractChainVariables('single step single chain input', ['hello'], ['hello']) | ||
testExtractChainVariables('multi step single chain input', ['hello'], ['', 'hello']) | ||
testExtractChainVariables('multi step repeated chain input', ['hello'], ['hello', '', 'hello']) | ||
testExtractChainVariables('multi step multi chain input', ['hello', 'world'], ['hello', '', 'world']) | ||
testExtractChainVariables('mapped input', ['world'], ['', 'hello', 'world'], ['hello']) | ||
testExtractChainVariables('mapped too late', ['hello'], ['hello', ''], ['', 'hello']) | ||
testExtractChainVariables('mapped later too', ['hello', 'world'], ['hello', 'world', 'hello'], ['', 'hello']) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,4 +3,4 @@ env: flex | |
|
||
runtime_config: | ||
operating_system: "ubuntu22" | ||
runtime_version: 18 | ||
runtime_version: "18" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { ActiveUser, UserMetrics } from '@/types' | ||
import Label from '@/components/label' | ||
import UserAvatar from '@/components/users/userAvatar' | ||
import { FormatCost, FormatDate } from '@/src/common/formatting' | ||
import Icon from '../icon' | ||
import backIcon from '@/public/back.svg' | ||
import { LabelForProvider } from '@/src/common/providerMetadata' | ||
|
||
export default function ActiveUserMetrics({ | ||
user, | ||
metrics, | ||
onDismiss, | ||
}: { | ||
user: ActiveUser | ||
metrics: UserMetrics | ||
onDismiss: () => void | ||
}) { | ||
return ( | ||
<> | ||
<div className='flex flex-col items-start h-full gap-4 p-6 overflow-y-auto'> | ||
<Label onClick={onDismiss} className='flex items-center cursor-pointer'> | ||
<Icon icon={backIcon} /> | ||
Back to Active Users | ||
</Label> | ||
<div className='flex flex-col gap-4 p-4 bg-white border border-gray-200 rounded-lg'> | ||
<div className='flex items-center gap-2'> | ||
<UserAvatar user={user} /> | ||
<Label> | ||
{user.fullName} ({user.email}) | ||
</Label> | ||
</div> | ||
<Label>Last Active: {FormatDate(user.lastActive, true, true)}</Label> | ||
<div className='flex flex-col gap-1'> | ||
<Label>Number of additional workspaces created: {metrics.createdWorkspaceCount - 1}</Label> | ||
<Label> | ||
Number of additional workspaces shared with user:{' '} | ||
{metrics.workspaceAccessCount - metrics.createdWorkspaceCount} | ||
</Label> | ||
<Label>Number of additional projects shared with user: {metrics.projectAccessCount}</Label> | ||
</div> | ||
<div className='flex flex-col gap-1'> | ||
<Label>Total number of versions created: {metrics.createdVersionCount}</Label> | ||
<Label>Total number of comments made: {metrics.createdCommentCount}</Label> | ||
<Label>Total number of endpoints published: {metrics.createdEndpointCount}</Label> | ||
</div> | ||
<Label>Registered Providers:</Label> | ||
<div className='flex flex-col gap-1'> | ||
{metrics.providers.map((provider, index) => ( | ||
<Label key={index}> | ||
• {LabelForProvider(provider.provider)} ({FormatCost(provider.cost)}) | ||
</Label> | ||
))} | ||
</div> | ||
</div> | ||
</div> | ||
</> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { ReactNode } from 'react' | ||
import { ActiveUser } from '@/types' | ||
import Label from '@/components/label' | ||
import UserAvatar from '@/components/users/userAvatar' | ||
import { FormatDate } from '@/src/common/formatting' | ||
|
||
export default function ActiveUsers({ | ||
title = 'Active Users', | ||
activeUsers, | ||
onSelectUser, | ||
embedded, | ||
}: { | ||
title?: string | ||
activeUsers: ActiveUser[] | ||
onSelectUser: (userID: number) => void | ||
embedded?: boolean | ||
}) { | ||
const gridConfig = 'grid grid-cols-[100px_200px_minmax(0,1fr)_100px_100px_100px_100px_100px]' | ||
|
||
const startDate = Math.min(...activeUsers.map(user => user.startTimestamp)) | ||
|
||
return ( | ||
<> | ||
<div className={`flex flex-col items-start gap-4 ${embedded ? '' : 'p-6 overflow-y-auto'}`}> | ||
{activeUsers.length > 0 && ( | ||
<> | ||
<Label> | ||
{title} (data since {FormatDate(startDate)}) | ||
</Label> | ||
<div className={`${gridConfig} bg-white items-center border-gray-200 border rounded-lg p-2`}> | ||
<TableCell> | ||
<Label>Last Active</Label> | ||
</TableCell> | ||
<TableCell> | ||
<Label>Name</Label> | ||
</TableCell> | ||
<TableCell> | ||
<Label>Email</Label> | ||
</TableCell> | ||
<TableCell center> | ||
<Label># Comments</Label> | ||
</TableCell> | ||
<TableCell center> | ||
<Label># Versions</Label> | ||
</TableCell> | ||
<TableCell center> | ||
<Label># Prompts</Label> | ||
</TableCell> | ||
<TableCell center> | ||
<Label># Chains</Label> | ||
</TableCell> | ||
<TableCell center> | ||
<Label># Endpoints</Label> | ||
</TableCell> | ||
{activeUsers.map(user => ( | ||
<div key={user.id} className='cursor-pointer contents group' onClick={() => onSelectUser(user.id)}> | ||
<TableCell>{FormatDate(user.lastActive, false)}</TableCell> | ||
<TableCell> | ||
<UserAvatar user={user} /> {user.fullName} | ||
</TableCell> | ||
<TableCell>{user.email}</TableCell> | ||
<TableCell center>{user.commentCount}</TableCell> | ||
<TableCell center>{user.versionCount}</TableCell> | ||
<TableCell center>{user.promptCount}</TableCell> | ||
<TableCell center>{user.chainCount}</TableCell> | ||
<TableCell center>{user.endpointCount}</TableCell> | ||
</div> | ||
))} | ||
</div> | ||
</> | ||
)} | ||
</div> | ||
</> | ||
) | ||
} | ||
|
||
const TableCell = ({ children, center }: { children: ReactNode; center?: boolean }) => ( | ||
<div | ||
className={`flex items-center gap-2 px-2 h-10 overflow-hidden font-medium text-ellipsis group-hover:bg-gray-50 ${ | ||
center ? 'justify-center' : '' | ||
}`}> | ||
{children} | ||
</div> | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { AdminRoute } from '@/src/common/clientRoute' | ||
import { SidebarButton, SidebarSection } from '../sidebar' | ||
import linkIcon from '@/public/chain.svg' | ||
import userIcon from '@/public/user.svg' | ||
import fileIcon from '@/public/file.svg' | ||
|
||
export default function AdminSidebar({ | ||
onSelectWaitlist, | ||
onSelectActiveUsers, | ||
onSelectRecentProjects, | ||
}: { | ||
onSelectWaitlist: () => void | ||
onSelectActiveUsers: () => void | ||
onSelectRecentProjects: () => void | ||
}) { | ||
return ( | ||
<> | ||
<div className='flex flex-col gap-4 px-2 pt-3 pb-4 border-r border-gray-200 bg-gray-25'> | ||
<SidebarSection title='Manage Access'> | ||
<SidebarButton title='Waitlist' icon={userIcon} onClick={onSelectWaitlist} /> | ||
</SidebarSection> | ||
<SidebarSection title='Recent Activity'> | ||
<SidebarButton title='Active Users' icon={userIcon} onClick={onSelectActiveUsers} /> | ||
<SidebarButton title='Active Projects' icon={fileIcon} onClick={onSelectRecentProjects} /> | ||
</SidebarSection> | ||
<SidebarSection title='Google Analytics'> | ||
<SidebarButton title='Dashboards' icon={linkIcon} link={AdminRoute.AnalyticsDashboard} target='_blank' /> | ||
<SidebarButton title='Reports' icon={linkIcon} link={AdminRoute.AnalyticsReports} target='_blank' /> | ||
<SidebarButton title='Search Console' icon={linkIcon} link={AdminRoute.SearchConsole} target='_blank' /> | ||
</SidebarSection> | ||
<SidebarSection title='Debug'> | ||
<SidebarButton title='Server Logs' icon={linkIcon} link={AdminRoute.ServerLogs} target='_blank' /> | ||
</SidebarSection> | ||
</div> | ||
</> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { ProjectMetrics, RecentProject } from '@/types' | ||
import Label from '@/components/label' | ||
import Icon from '../icon' | ||
import backIcon from '@/public/back.svg' | ||
import AnalyticsDashboards from '../endpoints/analyticsDashboards' | ||
import { FormatDate } from '@/src/common/formatting' | ||
import ActiveUsers from './activeUsers' | ||
import fileIcon from '@/public/file.svg' | ||
import folderIcon from '@/public/folder.svg' | ||
|
||
export default function RecentProjectMetrics({ | ||
project, | ||
metrics, | ||
onSelectUser, | ||
onDismiss, | ||
}: { | ||
project: RecentProject | ||
metrics: ProjectMetrics | ||
onSelectUser: (userID: number) => void | ||
onDismiss: () => void | ||
}) { | ||
return ( | ||
<> | ||
<div className='flex flex-col items-start h-full gap-4 p-6 overflow-y-auto'> | ||
<Label onClick={onDismiss} className='flex items-center cursor-pointer'> | ||
<Icon icon={backIcon} /> | ||
Back to Active Projects | ||
</Label> | ||
<div className='flex flex-col gap-4 p-4 bg-white border border-gray-200 rounded-lg'> | ||
<div className='flex items-center'> | ||
<Icon icon={fileIcon} /> | ||
<Label>{project.name} • </Label> | ||
<Icon icon={folderIcon} /> | ||
<Label> | ||
{project.workspace} ({project.creator}) | ||
</Label> | ||
</div> | ||
<Label>Last Modified: {FormatDate(project.timestamp, true, true)}</Label> | ||
<div className='flex flex-col gap-1'> | ||
<Label>Number of prompts: {metrics.promptCount}</Label> | ||
<Label>Number of chains: {metrics.chainCount}</Label> | ||
<Label>Number of endpoints: {metrics.endpointCount}</Label> | ||
</div> | ||
</div> | ||
<div className='w-full '> | ||
<AnalyticsDashboards analytics={metrics.analytics} /> | ||
</div> | ||
<ActiveUsers title='Active Project Users' activeUsers={metrics.users} onSelectUser={onSelectUser} embedded /> | ||
{metrics.pendingUsers.length > 0 && ( | ||
<ActiveUsers | ||
title='Pending Invitations' | ||
activeUsers={metrics.pendingUsers} | ||
onSelectUser={onSelectUser} | ||
embedded | ||
/> | ||
)} | ||
</div> | ||
</> | ||
) | ||
} |
Oops, something went wrong.