Skip to content

Commit d5b472b

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

File tree

56 files changed

+4226
-1007
lines changed

Some content is hidden

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

56 files changed

+4226
-1007
lines changed

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,
@@ -470,6 +473,22 @@ export function SideMenu({
470473
)}
471474
onCollapseToggle={handleSectionToggle("ai")}
472475
>
476+
<SideMenuItem
477+
name="Agents"
478+
icon={CpuChipIcon}
479+
activeIconColor="text-indigo-500"
480+
inactiveIconColor="text-indigo-500"
481+
to={v3AgentsPath(organization, project, environment)}
482+
isCollapsed={isCollapsed}
483+
/>
484+
<SideMenuItem
485+
name="Playground"
486+
icon={BeakerIcon}
487+
activeIconColor="text-indigo-400"
488+
inactiveIconColor="text-indigo-400"
489+
to={v3PlaygroundPath(organization, project, environment)}
490+
isCollapsed={isCollapsed}
491+
/>
473492
<SideMenuItem
474493
name="Prompts"
475494
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,
@@ -182,6 +183,9 @@ export const TaskRunListSearchFilters = z.object({
182183
`Machine presets to filter by (${machines.join(", ")})`
183184
),
184185
errorId: z.string().optional().describe("Error ID to filter runs by (e.g. error_abc123)"),
186+
sources: StringOrStringArray.describe(
187+
"Task trigger sources to filter by (STANDARD, SCHEDULED, AGENT)"
188+
),
185189
});
186190

187191
export type TaskRunListSearchFilters = z.infer<typeof TaskRunListSearchFilters>;
@@ -223,6 +227,8 @@ export function filterTitle(filterKey: string) {
223227
return "Version";
224228
case "errorId":
225229
return "Error ID";
230+
case "sources":
231+
return "Source";
226232
default:
227233
return filterKey;
228234
}
@@ -263,6 +269,8 @@ export function filterIcon(filterKey: string): ReactNode | undefined {
263269
return <IconRotateClockwise2 className="size-4" />;
264270
case "errorId":
265271
return <IconBugFilled className="size-4" />;
272+
case "sources":
273+
return <CpuChipIcon className="size-4" />;
266274
default:
267275
return undefined;
268276
}
@@ -310,6 +318,10 @@ export function getRunFiltersFromSearchParams(
310318
? searchParams.getAll("versions")
311319
: undefined,
312320
errorId: searchParams.get("errorId") ?? undefined,
321+
sources:
322+
searchParams.getAll("sources").filter((v) => v.length > 0).length > 0
323+
? searchParams.getAll("sources")
324+
: undefined,
313325
};
314326

315327
const parsed = TaskRunListSearchFilters.safeParse(params);
@@ -351,7 +363,8 @@ export function RunsFilters(props: RunFiltersProps) {
351363
searchParams.has("queues") ||
352364
searchParams.has("machines") ||
353365
searchParams.has("versions") ||
354-
searchParams.has("errorId");
366+
searchParams.has("errorId") ||
367+
searchParams.has("sources");
355368

356369
return (
357370
<div className="flex flex-row flex-wrap items-center gap-1">
@@ -388,6 +401,7 @@ const filterTypes = [
388401
{ name: "schedule", title: "Schedule ID", icon: <ClockIcon className="size-4" /> },
389402
{ name: "bulk", title: "Bulk action", icon: <ListCheckedIcon className="size-4" /> },
390403
{ name: "error", title: "Error ID", icon: <IconBugFilled className="size-4" /> },
404+
{ name: "source", title: "Source", icon: <CpuChipIcon className="size-4" /> },
391405
] as const;
392406

393407
type FilterType = (typeof filterTypes)[number]["name"];
@@ -443,6 +457,7 @@ function AppliedFilters({ possibleTasks, bulkActions }: RunFiltersProps) {
443457
<AppliedScheduleIdFilter />
444458
<AppliedBulkActionsFilter bulkActions={bulkActions} />
445459
<AppliedErrorIdFilter />
460+
<AppliedSourceFilter />
446461
</>
447462
);
448463
}
@@ -481,6 +496,8 @@ function Menu(props: MenuProps) {
481496
return <VersionsDropdown onClose={() => props.setFilterType(undefined)} {...props} />;
482497
case "error":
483498
return <ErrorIdDropdown onClose={() => props.setFilterType(undefined)} {...props} />;
499+
case "source":
500+
return <SourceDropdown onClose={() => props.setFilterType(undefined)} {...props} />;
484501
}
485502
}
486503

@@ -1869,3 +1886,101 @@ function AppliedErrorIdFilter() {
18691886
</FilterMenuProvider>
18701887
);
18711888
}
1889+
1890+
const sourceOptions: { value: TaskTriggerSource; title: string }[] = [
1891+
{ value: "STANDARD", title: "Standard" },
1892+
{ value: "SCHEDULED", title: "Scheduled" },
1893+
{ value: "AGENT", title: "Agent" },
1894+
];
1895+
1896+
function SourceDropdown({
1897+
trigger,
1898+
clearSearchValue,
1899+
searchValue,
1900+
onClose,
1901+
}: {
1902+
trigger: ReactNode;
1903+
clearSearchValue: () => void;
1904+
searchValue: string;
1905+
onClose?: () => void;
1906+
}) {
1907+
const { values, replace } = useSearchParams();
1908+
1909+
const handleChange = (values: string[]) => {
1910+
clearSearchValue();
1911+
replace({ sources: values, cursor: undefined, direction: undefined });
1912+
};
1913+
1914+
const filtered = useMemo(() => {
1915+
return sourceOptions.filter((item) =>
1916+
item.title.toLowerCase().includes(searchValue.toLowerCase())
1917+
);
1918+
}, [searchValue]);
1919+
1920+
return (
1921+
<SelectProvider value={values("sources")} setValue={handleChange} virtualFocus={true}>
1922+
{trigger}
1923+
<SelectPopover
1924+
className="min-w-0 max-w-[min(240px,var(--popover-available-width))]"
1925+
hideOnEscape={() => {
1926+
if (onClose) {
1927+
onClose();
1928+
return false;
1929+
}
1930+
return true;
1931+
}}
1932+
>
1933+
<ComboBox placeholder={"Filter by source..."} value={searchValue} />
1934+
<SelectList>
1935+
{filtered.map((item, index) => (
1936+
<SelectItem
1937+
key={item.value}
1938+
value={item.value}
1939+
icon={
1940+
<TaskTriggerSourceIcon source={item.value} className="size-4 flex-none" />
1941+
}
1942+
shortcut={shortcutFromIndex(index, { shortcutsEnabled: true })}
1943+
>
1944+
{item.title}
1945+
</SelectItem>
1946+
))}
1947+
</SelectList>
1948+
</SelectPopover>
1949+
</SelectProvider>
1950+
);
1951+
}
1952+
1953+
function AppliedSourceFilter() {
1954+
const { values, del } = useSearchParams();
1955+
const sources = values("sources");
1956+
1957+
if (sources.length === 0 || sources.every((v) => v === "")) {
1958+
return null;
1959+
}
1960+
1961+
return (
1962+
<FilterMenuProvider>
1963+
{(search, setSearch) => (
1964+
<SourceDropdown
1965+
trigger={
1966+
<Ariakit.Select render={<div className="group cursor-pointer focus-custom" />}>
1967+
<AppliedFilter
1968+
label="Source"
1969+
icon={<CpuChipIcon className="size-4" />}
1970+
value={appliedSummary(
1971+
sources.map(
1972+
(v) => sourceOptions.find((o) => o.value === v)?.title ?? v
1973+
)
1974+
)}
1975+
onRemove={() => del(["sources", "cursor", "direction"])}
1976+
variant="secondary/small"
1977+
/>
1978+
</Ariakit.Select>
1979+
}
1980+
searchValue={search}
1981+
clearSearchValue={() => setSearch("")}
1982+
/>
1983+
)}
1984+
</FilterMenuProvider>
1985+
);
1986+
}

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)