2023-10-30 07:29:50 +00:00
|
|
|
'use client'
|
|
|
|
|
|
|
|
|
|
import { buttonVariants } from '@/components/ui/button'
|
|
|
|
|
import {
|
|
|
|
|
Dialog,
|
|
|
|
|
DialogContent,
|
|
|
|
|
DialogDescription,
|
|
|
|
|
DialogFooter,
|
|
|
|
|
DialogHeader,
|
|
|
|
|
DialogTitle
|
|
|
|
|
} from '@/components/ui/dialog'
|
|
|
|
|
import { IconSlack } from '@/components/ui/icons'
|
|
|
|
|
import { Separator } from '@/components/ui/separator'
|
|
|
|
|
import { useHealth } from '@/lib/hooks/use-health'
|
|
|
|
|
import { PropsWithChildren, useEffect, useState } from 'react'
|
2023-10-31 05:11:01 +00:00
|
|
|
import WorkerCard from './components/worker-card'
|
2023-11-22 10:53:36 +00:00
|
|
|
import { useWorkers } from '@/lib/hooks/use-workers'
|
|
|
|
|
import { WorkerKind } from '@/lib/gql/generates/graphql'
|
2023-11-23 00:58:21 +00:00
|
|
|
import { useGraphQL } from '@/lib/hooks/use-graphql'
|
|
|
|
|
import { getRegistrationTokenDocument } from '@/lib/gql/request-documents'
|
|
|
|
|
import { CopyButton } from '@/components/copy-button'
|
2023-10-30 07:29:50 +00:00
|
|
|
|
|
|
|
|
const COMMUNITY_DIALOG_SHOWN_KEY = 'community-dialog-shown'
|
|
|
|
|
|
|
|
|
|
export default function Home() {
|
|
|
|
|
const [open, setOpen] = useState(false)
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (!localStorage.getItem(COMMUNITY_DIALOG_SHOWN_KEY)) {
|
|
|
|
|
setOpen(true)
|
|
|
|
|
localStorage.setItem(COMMUNITY_DIALOG_SHOWN_KEY, 'true')
|
|
|
|
|
}
|
|
|
|
|
}, [])
|
|
|
|
|
|
|
|
|
|
return (
|
2023-10-30 21:47:38 +00:00
|
|
|
<div className="p-4 lg:p-16">
|
2023-10-30 07:29:50 +00:00
|
|
|
<MainPanel />
|
|
|
|
|
<Dialog open={open} onOpenChange={setOpen}>
|
|
|
|
|
<DialogContent>
|
|
|
|
|
<DialogHeader className="gap-3">
|
|
|
|
|
<DialogTitle>Join the Tabby community</DialogTitle>
|
|
|
|
|
<DialogDescription>
|
|
|
|
|
Connect with other contributors building Tabby. Share knowledge,
|
|
|
|
|
get help, and contribute to the open-source project.
|
|
|
|
|
</DialogDescription>
|
|
|
|
|
</DialogHeader>
|
|
|
|
|
<DialogFooter className="sm:justify-start">
|
|
|
|
|
<a
|
|
|
|
|
target="_blank"
|
|
|
|
|
href="https://join.slack.com/t/tabbycommunity/shared_invite/zt-1xeiddizp-bciR2RtFTaJ37RBxr8VxpA"
|
|
|
|
|
className={buttonVariants()}
|
|
|
|
|
>
|
|
|
|
|
<IconSlack className="-ml-2 h-8 w-8" />
|
|
|
|
|
Join us on Slack
|
|
|
|
|
</a>
|
|
|
|
|
</DialogFooter>
|
|
|
|
|
</DialogContent>
|
|
|
|
|
</Dialog>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface LinkProps {
|
|
|
|
|
href: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function Link({ href, children }: PropsWithChildren<LinkProps>) {
|
|
|
|
|
return (
|
|
|
|
|
<a target="_blank" href={href} className="underline">
|
|
|
|
|
{children}
|
|
|
|
|
</a>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function toBadgeString(str: string) {
|
|
|
|
|
return encodeURIComponent(str.replaceAll('-', '--'))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function MainPanel() {
|
|
|
|
|
const { data: healthInfo } = useHealth()
|
2023-11-22 10:53:36 +00:00
|
|
|
const workers = useWorkers(healthInfo)
|
2023-11-23 00:58:21 +00:00
|
|
|
const { data: registrationTokenRes } = useGraphQL(
|
|
|
|
|
getRegistrationTokenDocument
|
|
|
|
|
)
|
2023-10-30 07:29:50 +00:00
|
|
|
|
|
|
|
|
if (!healthInfo) return
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="flex w-full flex-col gap-3">
|
|
|
|
|
<h1>
|
|
|
|
|
<span className="font-bold">Congratulations</span>, your tabby instance
|
2023-10-30 21:47:38 +00:00
|
|
|
is up!
|
2023-10-30 07:29:50 +00:00
|
|
|
</h1>
|
|
|
|
|
<span className="flex flex-wrap gap-1">
|
|
|
|
|
<a
|
|
|
|
|
target="_blank"
|
|
|
|
|
href={`https://github.com/TabbyML/tabby/releases/tag/${healthInfo.version.git_describe}`}
|
|
|
|
|
>
|
|
|
|
|
<img
|
|
|
|
|
src={`https://img.shields.io/badge/version-${toBadgeString(
|
|
|
|
|
healthInfo.version.git_describe
|
|
|
|
|
)}-green`}
|
|
|
|
|
/>
|
|
|
|
|
</a>
|
|
|
|
|
</span>
|
|
|
|
|
<Separator />
|
|
|
|
|
|
2023-10-30 21:47:38 +00:00
|
|
|
<div className="mt-4 rounded-lg bg-zinc-100 p-4 dark:bg-zinc-800">
|
2023-10-31 05:11:01 +00:00
|
|
|
<span className="font-bold">Workers</span>
|
2023-11-23 00:58:21 +00:00
|
|
|
|
|
|
|
|
{!!registrationTokenRes?.registrationToken && (
|
|
|
|
|
<div className="flex items-center gap-1">
|
2023-12-06 14:35:31 +00:00
|
|
|
Registeration token:{' '}
|
|
|
|
|
<span className="text-sm rounded-lg text-red-600">
|
2023-11-23 00:58:21 +00:00
|
|
|
{registrationTokenRes.registrationToken}
|
|
|
|
|
</span>
|
|
|
|
|
<CopyButton value={registrationTokenRes.registrationToken} />
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
2023-10-30 21:47:38 +00:00
|
|
|
<div className="mt-4 flex flex-col gap-4 lg:flex-row lg:flex-wrap">
|
2023-11-22 10:53:36 +00:00
|
|
|
{!!workers?.[WorkerKind.Completion] && (
|
|
|
|
|
<>
|
|
|
|
|
{workers[WorkerKind.Completion].map((worker, i) => {
|
|
|
|
|
return <WorkerCard key={i} {...worker} />
|
|
|
|
|
})}
|
|
|
|
|
</>
|
|
|
|
|
)}
|
|
|
|
|
{!!workers?.[WorkerKind.Chat] && (
|
|
|
|
|
<>
|
|
|
|
|
{workers[WorkerKind.Chat].map((worker, i) => {
|
|
|
|
|
return <WorkerCard key={i} {...worker} />
|
|
|
|
|
})}
|
|
|
|
|
</>
|
2023-10-30 21:47:38 +00:00
|
|
|
)}
|
2023-10-31 05:11:01 +00:00
|
|
|
<WorkerCard
|
2023-11-22 10:53:36 +00:00
|
|
|
addr="localhost"
|
2023-10-30 21:47:38 +00:00
|
|
|
name="Code Search Index"
|
2023-11-22 10:53:36 +00:00
|
|
|
kind="INDEX"
|
|
|
|
|
arch=""
|
|
|
|
|
device={healthInfo.device}
|
|
|
|
|
cudaDevices={healthInfo.cuda_devices}
|
|
|
|
|
cpuCount={healthInfo.cpu_count}
|
|
|
|
|
cpuInfo={healthInfo.cpu_info}
|
2023-10-30 21:47:38 +00:00
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-10-30 07:29:50 +00:00
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|