Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 1 | import { |
| 2 | ArrowUpRight, | |
| 3 | Bot, | |
| 4 | CircleAlert, | |
| 5 | CircleCheck, | |
| 6 | CircleDot, | |
| 7 | CircleDotDashed, | |
| Merge branch 'worktree-agent-a1398e81ad1a64c5f' | 8 | Forward, |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 9 | GitPullRequest, |
| 10 | ListChecks, | |
| 11 | Rocket, | |
| 12 | ShieldCheck, | |
| 13 | Sparkles, | |
| 14 | X, | |
| 15 | } from "lucide-react"; | |
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 16 | import { type ReactNode, useEffect, useId, useRef, useState, useSyncExternalStore } from "react"; |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 17 | import { Link } from "react-router"; |
| 18 | ||
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 19 | import type { CardAction, MessageCard } from "@g1t/contracts"; |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 20 | |
| 21 | import { Markdown } from "../markdown"; | |
| 22 | import { Badge, type BadgeTone } from "../ui/badge"; | |
| The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after. | 23 | import { ButtonLink } from "../ui"; |
| 24 | import { Button, type ButtonVariant } from "../ui/button"; | |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 25 | import { cn } from "../../lib/cn"; |
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 26 | import { type CardChip, cardChip, foldsBody, shownActions } from "../../lib/card-actions"; |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 27 | import { repoAt } from "../../lib/markdown-plugins"; |
| 28 | import { sessionChip } from "../../lib/session-card"; | |
| 29 | import { codeAccessPath } from "../../lib/workspace-nav"; | |
| 30 | ||
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 31 | // A card g1t posts in chat (or an agent did, on old messages): what it is |
| 32 | // about, its state, a preview, a few facts, and links to where it goes. | |
| 33 | // The card changes in place when the service that posted it updates it | |
| 34 | // (`message.updated`). Buttons that ran something on an old agent's card | |
| 35 | // are not shown: nothing answers them any more. | |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 36 | |
| 37 | const CARD_ICONS: Record<string, ReactNode> = { | |
| 38 | pull: <GitPullRequest size={16} />, | |
| 39 | issue: <CircleDot size={16} />, | |
| 40 | draft_issue: <CircleDotDashed size={16} />, | |
| 41 | task: <ListChecks size={16} />, | |
| 42 | deploy: <Rocket size={16} />, | |
| 43 | approval: <ShieldCheck size={16} />, | |
| 44 | session: <Bot size={16} />, | |
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 45 | // Where an agent handed the work, on old messages: the group message it went to. |
| Merge branch 'worktree-agent-a1398e81ad1a64c5f' | 46 | handoff: <Forward size={16} />, |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 47 | }; |
| 48 | ||
| 49 | /** Where a card's link goes for this viewer: a member without Code goes to the workspace's own view of it. */ | |
| 50 | export function cardHref(href: string | null | undefined, slug: string, code: boolean): string | null { | |
| 51 | if (!href) return null; | |
| 52 | if (code || !/^\/[^/]+\/(?!-\/)[^/]+/.test(href)) return href; | |
| 53 | return codeAccessPath(slug, href); | |
| 54 | } | |
| 55 | ||
| 56 | /** How loud a card's state reads, from what it says, for kinds without chips of their own. */ | |
| 57 | function stateTone(state: string): BadgeTone { | |
| 58 | const s = state.toLowerCase(); | |
| 59 | if (/merged/.test(s)) return "merged"; | |
| 60 | if (/fail|error|blocked|over budget|rejected/.test(s)) return "danger"; | |
| 61 | if (/approval|waiting|review|queued|needs/.test(s)) return "warn"; | |
| 62 | if (/pass|done|deployed|ready|approved|live|success/.test(s)) return "success"; | |
| 63 | if (/working|running|in progress|open/.test(s)) return "info"; | |
| 64 | return "neutral"; | |
| 65 | } | |
| 66 | ||
| 67 | function chipOf(card: MessageCard): CardChip | null { | |
| 68 | if (!card.state) return null; | |
| 69 | if (card.kind === "session") return sessionChip(card.state); | |
| 70 | return cardChip(card) ?? { tone: stateTone(card.state), live: false }; | |
| 71 | } | |
| 72 | ||
| 73 | /** | |
| 74 | * A card's state, as a chip: a session's Working pulses softly in lavender, | |
| 75 | * Needs approval is amber, Done green; a draft issue is outlined lavender | |
| 76 | * until it is filed (green) or discarded (quiet). | |
| 77 | */ | |
| 78 | function StateChip({ state, chip }: { state: string; chip: CardChip }) { | |
| 79 | return ( | |
| 80 | <Badge tone={chip.tone} className={cn("mt-0.5", chip.outline && "bg-transparent")}> | |
| 81 | {chip.live && ( | |
| 82 | <span aria-hidden="true" className="relative flex size-1.5"> | |
| 83 | <span className="absolute inline-flex size-full animate-ping rounded-full bg-current opacity-60 motion-reduce:animate-none" /> | |
| 84 | <span className="relative inline-flex size-1.5 rounded-full bg-current" /> | |
| 85 | </span> | |
| 86 | )} | |
| 87 | {state} | |
| 88 | </Badge> | |
| 89 | ); | |
| 90 | } | |
| 91 | ||
| 92 | // ── What pressing an action said, as a toast above the composer. | |
| 93 | ||
| 94 | type CardToast = { id: number; ok: boolean; message: string }; | |
| 95 | ||
| 96 | const TOAST_MS = 4_500; | |
| 97 | const NO_TOASTS: CardToast[] = []; | |
| 98 | let toasts: CardToast[] = NO_TOASTS; | |
| 99 | let toastSeq = 0; | |
| 100 | const toastListeners = new Set<() => void>(); | |
| 101 | ||
| 102 | function setToasts(next: CardToast[]) { | |
| 103 | toasts = next; | |
| 104 | for (const listener of toastListeners) listener(); | |
| 105 | } | |
| 106 | ||
| 107 | function dismissToast(id: number) { | |
| 108 | setToasts(toasts.filter((t) => t.id !== id)); | |
| 109 | } | |
| 110 | ||
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 111 | /** Says something in the conversation's toasts: that a link was copied, say. */ |
| Write a thread up in Docs from chat; cards' buttons in notifications; a session's card stays at the top of its thread | 112 | export function showToast(ok: boolean, message: string) { |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 113 | const id = ++toastSeq; |
| 114 | // Three at most; a fourth pushes the oldest out. | |
| 115 | setToasts([...toasts.slice(-2), { id, ok, message }]); | |
| 116 | setTimeout(() => dismissToast(id), ok ? TOAST_MS : TOAST_MS * 1.5); | |
| 117 | } | |
| 118 | ||
| 119 | function subscribeToasts(listener: () => void) { | |
| 120 | toastListeners.add(listener); | |
| 121 | return () => toastListeners.delete(listener); | |
| 122 | } | |
| 123 | ||
| 124 | /** | |
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 125 | * The conversation's toasts (a link copied, or not). Put once in a conversation; |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 126 | * along the top on a phone, above the composer on a computer, clear of the |
| 127 | * notification toasts in the corner. | |
| 128 | */ | |
| 129 | export function CardToasts() { | |
| 130 | const list = useSyncExternalStore( | |
| 131 | subscribeToasts, | |
| 132 | () => toasts, | |
| 133 | () => NO_TOASTS, | |
| 134 | ); | |
| 135 | return ( | |
| 136 | <section | |
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 137 | aria-label="Notices" |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 138 | aria-live="polite" |
| 139 | className="pointer-events-none fixed z-[66] flex flex-col items-center gap-2 max-sm:inset-x-3 max-sm:top-[calc(env(safe-area-inset-top)+0.75rem)] sm:bottom-28 sm:left-1/2 sm:w-[min(26rem,calc(100vw-2rem))] sm:-translate-x-1/2" | |
| 140 | > | |
| 141 | {list.map((toast) => ( | |
| 142 | <div | |
| 143 | key={toast.id} | |
| 144 | role={toast.ok ? "status" : "alert"} | |
| 145 | className={cn( | |
| You choose how g1t looks: Auto follows your system, Light and Dark stay put, set from the account menu, the phone's You and help sheet, Settings → Account or the command palette; the page is drawn in your choice from the first byte, every colour has a light value that reads at 4.5:1 or better, code and diffs are highlighted for both, diagrams and the document editor follow along, the product tour and the g1t mark's avatar stay dark, and Dark is what you see until you choose; the workspaces guide says how. | 146 | "pointer-events-auto flex w-full animate-pop-in items-start gap-2.5 rounded-xl bg-surface py-2.5 pr-2 pl-3 text-[0.8125rem] leading-snug text-fg shadow-[0_0_0_6px_var(--color-bg),0_20px_48px_-12px_rgba(0,0,0,0.9)] ring-1 motion-reduce:animate-none", |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 147 | toast.ok ? "ring-success/35" : "ring-danger/45", |
| 148 | )} | |
| 149 | > | |
| 150 | <span className={cn("mt-px shrink-0", toast.ok ? "text-success" : "text-danger")} aria-hidden="true"> | |
| 151 | {toast.ok ? <CircleCheck size={16} /> : <CircleAlert size={16} />} | |
| 152 | </span> | |
| 153 | <p className="min-w-0 grow">{toast.message}</p> | |
| The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after. | 154 | <Button |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 155 | type="button" |
| 156 | aria-label="Dismiss" | |
| 157 | onClick={() => dismissToast(toast.id)} | |
| The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after. | 158 | variant="ghost" size="icon" |
| 159 | className="size-6 text-faint" | |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 160 | > |
| 161 | <X size={14} /> | |
| The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after. | 162 | </Button> |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 163 | </div> |
| 164 | ))} | |
| 165 | </section> | |
| 166 | ); | |
| 167 | } | |
| 168 | ||
| 169 | // ── The card. | |
| 170 | ||
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 171 | /** A card's links are small buttons, a finger tall on a phone; the action's style names the variant. */ |
| The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after. | 172 | const ACTION_VARIANT: Record<NonNullable<CardAction["style"]>, ButtonVariant> = { primary: "accent", danger: "destructive", default: "outline" }; |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 173 | |
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 174 | function actionProps(action: Pick<CardAction, "style">) { |
| 175 | return { variant: ACTION_VARIANT[action.style ?? "default"], size: "sm" as const, className: "max-md:h-10 max-md:px-3.5" }; | |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 176 | } |
| 177 | ||
| 178 | /** | |
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 179 | * A card g1t (or, on old messages, an agent) posted: its title (a link |
| 180 | * when it goes somewhere), its state, a line of detail, a preview, its | |
| 181 | * facts, and its links. | |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 182 | */ |
| 183 | export function CardBox({ | |
| 184 | card, | |
| 185 | slug, | |
| 186 | code, | |
| 187 | }: { | |
| 188 | card: MessageCard; | |
| 189 | slug: string; | |
| 190 | /** Whether the viewer uses Code, for where links go. */ | |
| 191 | code: boolean; | |
| 192 | }) { | |
| 193 | const href = cardHref(card.href, slug, code); | |
| 194 | const chip = chipOf(card); | |
| 195 | const live = card.kind === "session" && !!chip?.live; | |
| 196 | const actions = shownActions(card); | |
| 197 | const head = ( | |
| 198 | <> | |
| 199 | <span | |
| 200 | className={cn( | |
| 201 | "mt-0.5 flex size-8 shrink-0 items-center justify-center rounded-lg transition-colors", | |
| 202 | live ? "bg-accent/10 text-accent" : "bg-raised text-muted group-hover/card:text-fg", | |
| 203 | )} | |
| 204 | > | |
| 205 | {CARD_ICONS[card.kind] ?? <Sparkles size={16} />} | |
| 206 | </span> | |
| 207 | <span className="min-w-0 grow"> | |
| 208 | <span className={cn("line-clamp-2 text-sm font-medium text-fg", href && "group-hover/head:underline group-hover/head:decoration-line-strong group-hover/head:underline-offset-2")}> | |
| 209 | {card.title} | |
| 210 | </span> | |
| 211 | {card.detail && <span className="mt-0.5 block truncate font-mono text-xs text-muted tabular-nums">{card.detail}</span>} | |
| 212 | </span> | |
| 213 | {card.state && chip && <StateChip state={card.state} chip={chip} />} | |
| 214 | </> | |
| 215 | ); | |
| 216 | ||
| 217 | const repository = card.fields?.find((f) => f.label.toLowerCase() === "repository")?.value; | |
| 218 | ||
| 219 | return ( | |
| 220 | <div | |
| 221 | className={cn( | |
| 222 | "group/card mt-1.5 w-full max-w-xl rounded-xl border bg-surface px-3.5 py-3 transition-[transform,box-shadow,border-color] duration-150", | |
| 223 | "hover:-translate-y-px hover:border-line-strong hover:shadow-lg hover:shadow-black/25 motion-reduce:transition-none motion-reduce:hover:translate-y-0", | |
| 224 | live ? "border-accent/25" : "border-line", | |
| 225 | )} | |
| 226 | > | |
| 227 | {href ? ( | |
| 228 | <Link to={href} className="group/head -m-1 flex items-start gap-3 rounded-lg p-1 outline-none focus-visible:ring-2 focus-visible:ring-accent/50"> | |
| 229 | {head} | |
| 230 | </Link> | |
| 231 | ) : ( | |
| 232 | <div className="flex items-start gap-3">{head}</div> | |
| 233 | )} | |
| 234 | ||
| 235 | {card.body && <CardBody body={card.body} repo={repository} />} | |
| 236 | ||
| 237 | {card.fields && card.fields.length > 0 && ( | |
| 238 | <dl className="mt-2.5 grid grid-cols-2 gap-x-4 gap-y-2 sm:pl-11"> | |
| 239 | {card.fields.map((field) => ( | |
| 240 | <div key={field.label} className="min-w-0"> | |
| 241 | <dt className="text-[0.6875rem] font-medium text-faint">{field.label}</dt> | |
| 242 | <dd className="line-clamp-2 text-xs break-words text-fg-soft"> | |
| 243 | {field.value} | |
| 244 | </dd> | |
| 245 | </div> | |
| 246 | ))} | |
| 247 | </dl> | |
| 248 | )} | |
| 249 | ||
| 250 | {actions.length > 0 && ( | |
| 251 | <div | |
| 252 | role="group" | |
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 253 | aria-label={`${card.title}: links`} |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 254 | className="mt-3 flex flex-wrap items-center gap-2 sm:pl-11" |
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 255 | // A press here is for the link, not the message's long-press sheet. |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 256 | onTouchStart={(event) => event.stopPropagation()} |
| 257 | > | |
| 258 | {actions.map((action) => { | |
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 259 | const target = cardHref(action.href, slug, code); |
| 260 | return target ? ( | |
| 261 | <ButtonLink key={action.id} to={target} {...actionProps(action)}> | |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 262 | {action.label} |
| The site no longer has g1t's own agents. g1t is where the coding agents you already use do their work, so the Agents mode is gone from the rail, with every page under /<workspace>/-/agents: personas, faces, skills, abilities, routines, computers, sessions and agent spend. Customize (skills, connectors, plugins, marketplaces), the context hub, model providers, the AI Gateway page, the Spend page and pill, Ask g1t, and the repository's Agents, Plans and agent settings pages go too, and their addresses now answer 404. | 263 | <ArrowUpRight size={14} aria-hidden="true" className="-mr-0.5 text-faint" /> |
| 264 | </ButtonLink> | |
| 265 | ) : null; | |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 266 | })} |
| 267 | </div> | |
| 268 | )} | |
| 269 | </div> | |
| 270 | ); | |
| 271 | } | |
| 272 | ||
| 273 | /** A card's Markdown preview: about eight lines, then "Show more". */ | |
| 274 | function CardBody({ body, repo }: { body: string; repo?: string }) { | |
| 275 | const [open, setOpen] = useState(false); | |
| 276 | // Folded by its length at first (the same on the server), then by whether it really overflows. | |
| 277 | const [folds, setFolds] = useState(() => foldsBody(body)); | |
| 278 | const box = useRef<HTMLDivElement>(null); | |
| 279 | const id = useId(); | |
| 280 | useEffect(() => { | |
| 281 | const element = box.current; | |
| 282 | if (!element || open) return; | |
| 283 | const measure = () => setFolds(element.scrollHeight > element.clientHeight + 2); | |
| 284 | measure(); | |
| 285 | const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(measure); | |
| 286 | observer?.observe(element); | |
| 287 | return () => observer?.disconnect(); | |
| 288 | }, [body, open]); | |
| 289 | const folded = folds && !open; | |
| 290 | return ( | |
| 291 | <div className="mt-2.5 sm:pl-11"> | |
| 292 | <div | |
| 293 | ref={box} | |
| 294 | id={id} | |
| 295 | className={cn("card-md relative rounded-lg border border-line/70 bg-bg/40 px-3 py-2", !open && "max-h-[11.5rem] overflow-hidden")} | |
| 296 | > | |
| 297 | <Markdown source={body} repo={repoAt(repo)} /> | |
| 298 | {folded && ( | |
| 299 | <span aria-hidden="true" className="pointer-events-none absolute inset-x-0 bottom-0 h-12 rounded-b-lg bg-gradient-to-t from-surface to-transparent" /> | |
| 300 | )} | |
| 301 | </div> | |
| 302 | {(folded || open) && ( | |
| The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after. | 303 | <Button |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 304 | type="button" |
| 305 | aria-expanded={open} | |
| 306 | aria-controls={id} | |
| 307 | onClick={() => setOpen((now) => !now)} | |
| The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after. | 308 | variant="ghost" |
| 309 | size="inline" | |
| 310 | className="mt-1 rounded px-1 py-0.5 text-xs text-accent focus-visible:ring-accent/50 max-md:min-h-9" | |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 311 | > |
| 312 | {open ? "Show less" : "Show more"} | |
| The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after. | 313 | </Button> |
| Cards you act on in chat; agents comment and review as themselves; names shown cleanly; commits on the calendar | 314 | )} |
| 315 | </div> | |
| 316 | ); | |
| 317 | } |
This file's history is long; its oldest lines are credited to the oldest commit read.