Skip to content

Commit f0b5791

Browse files
committed
chat.task -> chat.agent
plus playground support, including playground conversations, and a new agent list
1 parent af8728f commit f0b5791

55 files changed

Lines changed: 4263 additions & 1072 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/webapp/app/components/BulkActionFilterSummary.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,19 @@ export function BulkActionFilterSummary({
240240
/>
241241
);
242242
}
243+
case "sources": {
244+
const values = Array.isArray(value) ? value : [`${value}`];
245+
return (
246+
<AppliedFilter
247+
variant="minimal/medium"
248+
key={key}
249+
label={filterTitle(key)}
250+
icon={filterIcon(key)}
251+
value={appliedSummary(values)}
252+
removable={false}
253+
/>
254+
);
255+
}
243256
default: {
244257
assertNever(typedKey);
245258
}

apps/webapp/app/components/navigation/SideMenu.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
ClockIcon,
1111
Cog8ToothIcon,
1212
CogIcon,
13+
CpuChipIcon,
1314
CubeIcon,
1415
ExclamationTriangleIcon,
1516
FolderIcon,
@@ -69,7 +70,9 @@ import {
6970
organizationTeamPath,
7071
queryPath,
7172
regionsPath,
73+
v3AgentsPath,
7274
v3ApiKeysPath,
75+
v3PlaygroundPath,
7376
v3BatchesPath,
7477
v3BillingPath,
7578
v3BuiltInDashboardPath,
@@ -467,6 +470,22 @@ export function SideMenu({
467470
initialCollapsed={getSectionCollapsed(user.dashboardPreferences.sideMenu, "ai")}
468471
onCollapseToggle={handleSectionToggle("ai")}
469472
>
473+
<SideMenuItem
474+
name="Agents"
475+
icon={CpuChipIcon}
476+
activeIconColor="text-indigo-500"
477+
inactiveIconColor="text-indigo-500"
478+
to={v3AgentsPath(organization, project, environment)}
479+
isCollapsed={isCollapsed}
480+
/>
481+
<SideMenuItem
482+
name="Playground"
483+
icon={BeakerIcon}
484+
activeIconColor="text-indigo-400"
485+
inactiveIconColor="text-indigo-400"
486+
to={v3PlaygroundPath(organization, project, environment)}
487+
isCollapsed={isCollapsed}
488+
/>
470489
<SideMenuItem
471490
name="Prompts"
472491
icon={AIPromptsIcon}

apps/webapp/app/components/runs/v3/RunFilters.tsx

Lines changed: 116 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as Ariakit from "@ariakit/react";
22
import {
33
CalendarIcon,
44
ClockIcon,
5+
CpuChipIcon,
56
FingerPrintIcon,
67
RectangleStackIcon,
78
Squares2X2Icon,
@@ -184,6 +185,9 @@ export const TaskRunListSearchFilters = z.object({
184185
`Machine presets to filter by (${machines.join(", ")})`
185186
),
186187
errorId: z.string().optional().describe("Error ID to filter runs by (e.g. error_abc123)"),
188+
sources: StringOrStringArray.describe(
189+
"Task trigger sources to filter by (STANDARD, SCHEDULED, AGENT)"
190+
),
187191
});
188192

189193
export type TaskRunListSearchFilters = z.infer<typeof TaskRunListSearchFilters>;
@@ -225,6 +229,8 @@ export function filterTitle(filterKey: string) {
225229
return "Version";
226230
case "errorId":
227231
return "Error ID";
232+
case "sources":
233+
return "Source";
228234
default:
229235
return filterKey;
230236
}
@@ -265,6 +271,8 @@ export function filterIcon(filterKey: string): ReactNode | undefined {
265271
return <IconRotateClockwise2 className="size-4" />;
266272
case "errorId":
267273
return <IconBugFilled className="size-4" />;
274+
case "sources":
275+
return <CpuChipIcon className="size-4" />;
268276
default:
269277
return undefined;
270278
}
@@ -312,6 +320,10 @@ export function getRunFiltersFromSearchParams(
312320
? searchParams.getAll("versions")
313321
: undefined,
314322
errorId: searchParams.get("errorId") ?? undefined,
323+
sources:
324+
searchParams.getAll("sources").filter((v) => v.length > 0).length > 0
325+
? searchParams.getAll("sources")
326+
: undefined,
315327
};
316328

317329
const parsed = TaskRunListSearchFilters.safeParse(params);
@@ -353,7 +365,8 @@ export function RunsFilters(props: RunFiltersProps) {
353365
searchParams.has("queues") ||
354366
searchParams.has("machines") ||
355367
searchParams.has("versions") ||
356-
searchParams.has("errorId");
368+
searchParams.has("errorId") ||
369+
searchParams.has("sources");
357370

358371
return (
359372
<div className="flex flex-row flex-wrap items-center gap-1">
@@ -390,6 +403,7 @@ const filterTypes = [
390403
{ name: "schedule", title: "Schedule ID", icon: <ClockIcon className="size-4" /> },
391404
{ name: "bulk", title: "Bulk action", icon: <ListCheckedIcon className="size-4" /> },
392405
{ name: "error", title: "Error ID", icon: <IconBugFilled className="size-4" /> },
406+
{ name: "source", title: "Source", icon: <CpuChipIcon className="size-4" /> },
393407
] as const;
394408

395409
type FilterType = (typeof filterTypes)[number]["name"];
@@ -445,6 +459,7 @@ function AppliedFilters({ possibleTasks, bulkActions }: RunFiltersProps) {
445459
<AppliedScheduleIdFilter />
446460
<AppliedBulkActionsFilter bulkActions={bulkActions} />
447461
<AppliedErrorIdFilter />
462+
<AppliedSourceFilter />
448463
</>
449464
);
450465
}
@@ -483,6 +498,8 @@ function Menu(props: MenuProps) {
483498
return <VersionsDropdown onClose={() => props.setFilterType(undefined)} {...props} />;
484499
case "error":
485500
return <ErrorIdDropdown onClose={() => props.setFilterType(undefined)} {...props} />;
501+
case "source":
502+
return <SourceDropdown onClose={() => props.setFilterType(undefined)} {...props} />;
486503
}
487504
}
488505

@@ -1896,3 +1913,101 @@ function AppliedErrorIdFilter() {
18961913
</FilterMenuProvider>
18971914
);
18981915
}
1916+
1917+
const sourceOptions: { value: TaskTriggerSource; title: string }[] = [
1918+
{ value: "STANDARD", title: "Standard" },
1919+
{ value: "SCHEDULED", title: "Scheduled" },
1920+
{ value: "AGENT", title: "Agent" },
1921+
];
1922+
1923+
function SourceDropdown({
1924+
trigger,
1925+
clearSearchValue,
1926+
searchValue,
1927+
onClose,
1928+
}: {
1929+
trigger: ReactNode;
1930+
clearSearchValue: () => void;
1931+
searchValue: string;
1932+
onClose?: () => void;
1933+
}) {
1934+
const { values, replace } = useSearchParams();
1935+
1936+
const handleChange = (values: string[]) => {
1937+
clearSearchValue();
1938+
replace({ sources: values, cursor: undefined, direction: undefined });
1939+
};
1940+
1941+
const filtered = useMemo(() => {
1942+
return sourceOptions.filter((item) =>
1943+
item.title.toLowerCase().includes(searchValue.toLowerCase())
1944+
);
1945+
}, [searchValue]);
1946+
1947+
return (
1948+
<SelectProvider value={values("sources")} setValue={handleChange} virtualFocus={true}>
1949+
{trigger}
1950+
<SelectPopover
1951+
className="min-w-0 max-w-[min(240px,var(--popover-available-width))]"
1952+
hideOnEscape={() => {
1953+
if (onClose) {
1954+
onClose();
1955+
return false;
1956+
}
1957+
return true;
1958+
}}
1959+
>
1960+
<ComboBox placeholder={"Filter by source..."} value={searchValue} />
1961+
<SelectList>
1962+
{filtered.map((item, index) => (
1963+
<SelectItem
1964+
key={item.value}
1965+
value={item.value}
1966+
icon={
1967+
<TaskTriggerSourceIcon source={item.value} className="size-4 flex-none" />
1968+
}
1969+
shortcut={shortcutFromIndex(index, { shortcutsEnabled: true })}
1970+
>
1971+
{item.title}
1972+
</SelectItem>
1973+
))}
1974+
</SelectList>
1975+
</SelectPopover>
1976+
</SelectProvider>
1977+
);
1978+
}
1979+
1980+
function AppliedSourceFilter() {
1981+
const { values, del } = useSearchParams();
1982+
const sources = values("sources");
1983+
1984+
if (sources.length === 0 || sources.every((v) => v === "")) {
1985+
return null;
1986+
}
1987+
1988+
return (
1989+
<FilterMenuProvider>
1990+
{(search, setSearch) => (
1991+
<SourceDropdown
1992+
trigger={
1993+
<Ariakit.Select render={<div className="group cursor-pointer focus-custom" />}>
1994+
<AppliedFilter
1995+
label="Source"
1996+
icon={<CpuChipIcon className="size-4" />}
1997+
value={appliedSummary(
1998+
sources.map(
1999+
(v) => sourceOptions.find((o) => o.value === v)?.title ?? v
2000+
)
2001+
)}
2002+
onRemove={() => del(["sources", "cursor", "direction"])}
2003+
variant="secondary/small"
2004+
/>
2005+
</Ariakit.Select>
2006+
}
2007+
searchValue={search}
2008+
clearSearchValue={() => setSearch("")}
2009+
/>
2010+
)}
2011+
</FilterMenuProvider>
2012+
);
2013+
}

apps/webapp/app/components/runs/v3/TaskRunsTable.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,10 @@ import {
5555
filterableTaskRunStatuses,
5656
TaskRunStatusCombo,
5757
} from "./TaskRunStatus";
58+
import { TaskTriggerSourceIcon } from "./TaskTriggerSource";
5859
import { useOptimisticLocation } from "~/hooks/useOptimisticLocation";
5960
import { useSearchParams } from "~/hooks/useSearchParam";
61+
import type { TaskTriggerSource } from "@trigger.dev/database";
6062

6163
type RunsTableProps = {
6264
total: number;
@@ -343,6 +345,10 @@ export function TaskRunsTable({
343345
</TableCell>
344346
<TableCell to={path}>
345347
<span className="flex items-center gap-x-1">
348+
<TaskTriggerSourceIcon
349+
source={run.taskKind as TaskTriggerSource}
350+
className="size-3.5 flex-none"
351+
/>
346352
{run.taskIdentifier}
347353
{run.rootTaskRunId === null ? <Badge variant="extra-small">Root</Badge> : null}
348354
</span>

apps/webapp/app/components/runs/v3/TaskTriggerSource.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ClockIcon } from "@heroicons/react/20/solid";
1+
import { ClockIcon, CpuChipIcon } from "@heroicons/react/20/solid";
22
import type { TaskTriggerSource } from "@trigger.dev/database";
33
import { TaskIconSmall } from "~/assets/icons/TaskIcon";
44
import { cn } from "~/utils/cn";
@@ -19,6 +19,11 @@ export function TaskTriggerSourceIcon({
1919
<ClockIcon className={cn("size-[1.125rem] min-w-[1.125rem] text-schedules", className)} />
2020
);
2121
}
22+
case "AGENT": {
23+
return (
24+
<CpuChipIcon className={cn("size-[1.125rem] min-w-[1.125rem] text-indigo-500", className)} />
25+
);
26+
}
2227
}
2328
}
2429

@@ -30,5 +35,8 @@ export function taskTriggerSourceDescription(source: TaskTriggerSource) {
3035
case "SCHEDULED": {
3136
return "Scheduled task";
3237
}
38+
case "AGENT": {
39+
return "Agent";
40+
}
3341
}
3442
}

apps/webapp/app/components/runs/v3/ai/AIChatMessages.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ function ToolUseSection({ tools }: { tools: ToolUse[] }) {
259259

260260
type ToolTab = "input" | "output" | "details";
261261

262-
function ToolUseRow({ tool }: { tool: ToolUse }) {
262+
export function ToolUseRow({ tool }: { tool: ToolUse }) {
263263
const hasInput = tool.inputJson !== "{}";
264264
const hasResult = !!tool.resultOutput;
265265
const hasDetails = !!tool.description || !!tool.parametersJson;

apps/webapp/app/presenters/RunFilters.server.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export async function getRunFiltersFromRequest(request: Request): Promise<Filter
3636
queues,
3737
machines,
3838
errorId,
39+
sources,
3940
} = TaskRunListSearchFilters.parse(s);
4041

4142
return {
@@ -56,5 +57,6 @@ export async function getRunFiltersFromRequest(request: Request): Promise<Filter
5657
queues,
5758
machines,
5859
errorId,
60+
sources,
5961
};
6062
}

0 commit comments

Comments
 (0)