diff --git a/.changeset/remove-agents-last-run-column.md b/.changeset/remove-agents-last-run-column.md
new file mode 100644
index 000000000..41dafc3b6
--- /dev/null
+++ b/.changeset/remove-agents-last-run-column.md
@@ -0,0 +1,5 @@
+---
+'@truefoundry/trueforge-ui': patch
+---
+
+Remove the Last run column from the agents library page.
diff --git a/packages/trueforge-ui/src/atoms/AgentLibraryUsage.tsx b/packages/trueforge-ui/src/atoms/AgentLibraryUsage.tsx
index d7bf21593..c1ae10cbd 100644
--- a/packages/trueforge-ui/src/atoms/AgentLibraryUsage.tsx
+++ b/packages/trueforge-ui/src/atoms/AgentLibraryUsage.tsx
@@ -2,7 +2,6 @@
import { useState, type MouseEvent as ReactMouseEvent, type ReactNode } from 'react';
-import { formatRelativeShort } from './lib/threadListMeta.js';
import {
AGENT_LIBRARY_METERS_WINDOW_DAYS,
AGENT_LIBRARY_SPARKLINE_DAYS,
@@ -30,13 +29,6 @@ function formatSparklineDay(iso: string): string {
return sparklineDayFormatter.format(new Date(ms));
}
-function formatLastRunLabel(iso: string | null): string {
- if (iso == null) return 'Never';
- const ms = Date.parse(iso);
- if (Number.isNaN(ms)) return '—';
- return `${formatRelativeShort(new Date(ms))} ago`;
-}
-
export const agentLibraryUsageLabels = {
sessions: `Sessions, ${String(AGENT_LIBRARY_METERS_WINDOW_DAYS)}d`,
spend: `Spend, ${String(AGENT_LIBRARY_METERS_WINDOW_DAYS)}d`,
@@ -238,34 +230,6 @@ export function AgentSpendCell({
);
}
-export function AgentLastRunCell({
- usage,
- loading,
- agentName,
-}: {
- usage: AgentLibraryUsageStats | undefined;
- loading: boolean;
- agentName: string;
-}) {
- if (loading) return ;
- if (usage?.lastRunAt === undefined) {
- return (
-
- —
-
- );
- }
- const label = formatLastRunLabel(usage.lastRunAt);
- return (
-
- {label}
-
- );
-}
-
function UsageField({ label, children }: { label: string; children: ReactNode }) {
return (
@@ -280,25 +244,11 @@ export type AgentLibraryUsageCellsProps = {
loading: boolean;
agentName: string;
showMetrics: boolean;
- showLastRun: boolean;
};
/** Mobile card usage block. Desktop rows place the same cells in table columns. */
-export function AgentLibraryUsageCells({
- usage,
- loading,
- agentName,
- showMetrics,
- showLastRun,
-}: AgentLibraryUsageCellsProps) {
- if (!showMetrics && !showLastRun) return null;
- if (!showMetrics) {
- return (
-
-
-
- );
- }
+export function AgentLibraryUsageCells({ usage, loading, agentName, showMetrics }: AgentLibraryUsageCellsProps) {
+ if (!showMetrics) return null;
return (
@@ -310,11 +260,6 @@ export function AgentLibraryUsageCells({
- {showLastRun ? (
-
-
-
- ) : null}
);
}
diff --git a/packages/trueforge-ui/src/atoms/AgentsLibrary.tsx b/packages/trueforge-ui/src/atoms/AgentsLibrary.tsx
index c68f09213..574d6d72b 100644
--- a/packages/trueforge-ui/src/atoms/AgentsLibrary.tsx
+++ b/packages/trueforge-ui/src/atoms/AgentsLibrary.tsx
@@ -16,7 +16,6 @@ import { useSlot } from '../theme/SlotsProvider.js';
import { readLibraryShareSearch, replaceLibraryShareSearch } from '../utils/libraryShareUrl.js';
import { replaceScheduleShareSearch } from '../utils/scheduleShareUrl.js';
import {
- AgentLastRunCell,
AgentLibrarySparklineCell,
AgentSessionsCell,
AgentSpendCell,
@@ -73,7 +72,6 @@ export type AgentLibraryRowProps = {
scheduleSummary?: AgentScheduleSummary | null;
usage?: AgentLibraryUsageStats;
showMetricsColumns?: boolean;
- showLastRunColumn?: boolean;
onOpenSchedules?: () => void;
onCreateSchedule?: () => void;
onOpen?: () => void;
@@ -369,7 +367,6 @@ export function AgentLibraryRow({
scheduleSummary,
usage,
showMetricsColumns = false,
- showLastRunColumn = false,
onOpenSchedules,
onCreateSchedule,
onOpen,
@@ -392,13 +389,12 @@ export function AgentLibraryRow({
const storedDescription = agent.description?.trim() || null;
// Create falls back to name when description is missing; don't echo it under the title.
const description = storedDescription != null && storedDescription !== agent.name ? storedDescription : null;
- const usageLoading = (showMetricsColumns || showLastRunColumn) && usage == null;
+ const usageLoading = showMetricsColumns && usage == null;
const usageCells = (
);
@@ -503,7 +499,6 @@ export function AgentLibraryRow({
) : null}
- {showLastRunColumn ?
: null}
{tryButton}
{overflowMenu}
@@ -628,11 +623,7 @@ export function AgentsLibrary({ onSelectAgent, headerStart }: AgentsLibraryProps
resourceIds: permissionAgentIds,
});
- const {
- usageByAgentId,
- metricsEnabled: showMetricsColumns,
- lastRunEnabled: showLastRunColumn,
- } = useAgentLibraryUsageStats({
+ const { usageByAgentId, metricsEnabled: showMetricsColumns } = useAgentLibraryUsageStats({
agentIds: permissionAgentIds,
refreshKey: agentsListEpoch,
});
@@ -721,7 +712,6 @@ export function AgentsLibrary({ onSelectAgent, headerStart }: AgentsLibraryProps
canDeleteAgent={allows(id, 'DELETE')}
canManageSchedules={canOpenAgentSchedules}
showMetricsColumns={showMetricsColumns}
- showLastRunColumn={showLastRunColumn}
variant={variant}
{...(usage !== undefined ? { usage } : {})}
{...(summary !== undefined ? { scheduleSummary: summary } : {})}
@@ -870,9 +860,7 @@ export function AgentsLibrary({ onSelectAgent, headerStart }: AgentsLibraryProps
>
) : null}
-
- {showLastRunColumn ? 'Last run' : 'Actions'}
-
+ Actions
diff --git a/packages/trueforge-ui/src/atoms/lib/useAgentLibraryUsageStats.ts b/packages/trueforge-ui/src/atoms/lib/useAgentLibraryUsageStats.ts
index 7790e0a49..14313ce56 100644
--- a/packages/trueforge-ui/src/atoms/lib/useAgentLibraryUsageStats.ts
+++ b/packages/trueforge-ui/src/atoms/lib/useAgentLibraryUsageStats.ts
@@ -2,13 +2,8 @@
import { useEffect, useRef, useState } from 'react';
-import { useOptionalAgentMetricsServer, useOptionalAgentSessionsServer } from '../../server/ServerContext.js';
-import type {
- AgentMetricMeter,
- AgentMetricPoint,
- AgentMetricsServer,
- AgentSessionsServer,
-} from '../../server/types.js';
+import { useOptionalAgentMetricsServer } from '../../server/ServerContext.js';
+import type { AgentMetricMeter, AgentMetricPoint, AgentMetricsServer } from '../../server/types.js';
import { DEFAULT_SESSION_TIME_WINDOW_MS } from '../../utils/sessionShareUrl.js';
const MS_PER_DAY = 24 * 60 * 60 * 1000;
@@ -29,11 +24,6 @@ export type AgentLibraryUsageStats = {
totalCostUsd: number | null;
costPerSessionUsd: number | null;
dailyPoints: AgentLibraryDailyPoint[] | null;
- /**
- * Present only after `listSessions` succeeds. `null` means the agent has no
- * sessions; omitted when the fetch failed (distinct from "never ran").
- */
- lastRunAt?: string | null;
};
function meterValue(meters: readonly AgentMetricMeter[], name: string): number | null {
@@ -61,59 +51,42 @@ function unavailableUsage(): AgentLibraryUsageStats {
async function loadUsageForAgent({
agentId,
metrics,
- sessions,
metersStart,
metersEnd,
sparklineStart,
sparklineEnd,
}: {
agentId: string;
- metrics: AgentMetricsServer | null;
- sessions: AgentSessionsServer | null;
+ metrics: AgentMetricsServer;
metersStart: string;
metersEnd: string;
sparklineStart: string;
sparklineEnd: string;
}): Promise {
- const metersPromise =
- metrics == null
- ? Promise.resolve({ ok: false as const })
- : metrics
- .getMeters({
- agentId,
- startTimestamp: metersStart,
- endTimestamp: metersEnd,
- })
- .then(
- meters => ({ ok: true as const, meters }),
- () => ({ ok: false as const }),
- );
-
- const chartPromise =
- metrics == null
- ? Promise.resolve({ ok: false as const })
- : metrics
- .getChartData({
- agentId,
- startTimestamp: sparklineStart,
- endTimestamp: sparklineEnd,
- chartName: CHART_NAME,
- })
- .then(
- data => ({ ok: true as const, data }),
- () => ({ ok: false as const }),
- );
-
- // `undefined` = sessions server absent or the call failed; `null` = no sessions.
- const lastRunPromise: Promise =
- sessions == null
- ? Promise.resolve(undefined)
- : sessions.listSessions({ agentId, limit: 1, order: 'desc' }).then(
- page => page.data[0]?.lastActivityAt ?? null,
- () => undefined,
- );
-
- const [metersResult, chartResult, lastRunAt] = await Promise.all([metersPromise, chartPromise, lastRunPromise]);
+ const metersPromise = metrics
+ .getMeters({
+ agentId,
+ startTimestamp: metersStart,
+ endTimestamp: metersEnd,
+ })
+ .then(
+ meters => ({ ok: true as const, meters }),
+ () => ({ ok: false as const }),
+ );
+
+ const chartPromise = metrics
+ .getChartData({
+ agentId,
+ startTimestamp: sparklineStart,
+ endTimestamp: sparklineEnd,
+ chartName: CHART_NAME,
+ })
+ .then(
+ data => ({ ok: true as const, data }),
+ () => ({ ok: false as const }),
+ );
+
+ const [metersResult, chartResult] = await Promise.all([metersPromise, chartPromise]);
const meters = metersResult.ok ? metersResult.meters : [];
const dailyPoints = chartResult.ok ? chartPoints(chartResult.data.graphs[0]?.graphLines[0]?.values) : null;
@@ -123,14 +96,13 @@ async function loadUsageForAgent({
totalCostUsd: metersResult.ok ? meterValue(meters, 'total_cost_in_usd') : null,
costPerSessionUsd: metersResult.ok ? meterValue(meters, 'cost_per_session_in_usd') : null,
dailyPoints,
- ...(lastRunAt === undefined ? {} : { lastRunAt }),
};
}
/**
- * Loads per-agent spend/session meters, a 14d cost sparkline, and last-run
- * for the visible library page. Each agent paints as its own requests finish.
- * ponytail: three requests per agent (N+1). Replace with one batched metrics
+ * Loads per-agent spend/session meters and a 14d cost sparkline for the
+ * visible library page. Each agent paints as its own requests finish.
+ * ponytail: two requests per agent (N+1). Replace with one batched metrics
* call if the library page grows past a few dozen rows.
*/
export function useAgentLibraryUsageStats({
@@ -142,19 +114,16 @@ export function useAgentLibraryUsageStats({
}): {
usageByAgentId: Map;
metricsEnabled: boolean;
- lastRunEnabled: boolean;
} {
const metrics = useOptionalAgentMetricsServer();
- const sessions = useOptionalAgentSessionsServer();
const metricsEnabled = metrics != null;
- const lastRunEnabled = sessions != null;
const [usageByAgentId, setUsageByAgentId] = useState