Skip to content

Commit b6fd1b5

Browse files
authored
Recent decisions show a team tool's name next to its tool_ id (#313)
A decision on tool_find_order now reads "Find order tool_find_order: ..." from the event's policy.tool_label, which the platform fills in from the tool's definition. Tools without a name of their own show as before.
1 parent bb670f9 commit b6fd1b5

3 files changed

Lines changed: 29 additions & 3 deletions

File tree

‎dashboard/e2e/agent-permissions.spec.ts‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,10 @@ async function mockApi(page: Page, role = "admin", init: Partial<Backend> = {}):
190190
const a = db.approvals.find((x) => x.id === p.split("/").pop());
191191
return a ? json(route, { approval: a, can: { approve: true, always: true } }) : json(route, { error: "Not found" }, 404);
192192
}
193-
if (p === "/api/agents/activity") return json(route, { events: [{ id: "e1", at: new Date().toISOString(), actor: "agent:coder", actor_kind: "agent", action: "tool.queued_for_approval", tool: "linear__create_issue", result: "waiting", detail: "Changes ask by default.", policy: { decision: "ask" } }] });
193+
if (p === "/api/agents/activity") return json(route, { events: [
194+
{ id: "e1", at: new Date().toISOString(), actor: "agent:coder", actor_kind: "agent", action: "tool.queued_for_approval", tool: "linear__create_issue", result: "waiting", detail: "Changes ask by default.", policy: { decision: "ask" } },
195+
{ id: "e2", at: new Date().toISOString(), actor: "agent:planner", actor_kind: "agent", action: "tool.refused", tool: "tool_find_order", result: "refused", detail: "tool_find_order changed since it was approved, so it doesn't run. Approve the new version in Settings, Tools.", policy: { decision: "deny", rule: "unknown_tool", tool_label: "Find order" } },
196+
] });
194197
if (p === "/api/agents/sign-in/decline" && m === "POST") return json(route, { declined: true });
195198

196199
// The run page.
@@ -346,6 +349,17 @@ test("the page splits into Approvals, Agents and Advanced, and a switch can be u
346349
await expect.poll(() => db.calls.find((c) => c.path === "/api/agents/policy" && c.method === "PUT")?.body?.ask_timeout_secs).toBe(1800);
347350
});
348351

352+
test("recent decisions name a team tool for people, with the name agents call it", async ({ page }) => {
353+
await mockApi(page, "admin");
354+
await page.goto("/settings/agents");
355+
const log = page.getByTestId("agent-log");
356+
const row = log.getByRole("listitem").filter({ hasText: "Find order" });
357+
await expect(row).toContainText("Find order tool_find_order: tool_find_order changed since it was approved");
358+
await expect(row.getByTestId("agent-log-tool-id")).toHaveText("tool_find_order");
359+
// A tool with no name of its own shows as before.
360+
await expect(log.getByRole("listitem").filter({ hasText: "linear__create_issue: Changes ask by default." })).toBeVisible();
361+
});
362+
349363
test("pause all agents shows the banner, and resume lifts it", async ({ page }) => {
350364
const db = await mockApi(page, "admin");
351365
await page.goto("/settings/agents");

‎dashboard/src/app/settings/agents/sections.tsx‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,17 @@ export function SandboxSettings({ view, edit, repos, onChange }: { view: PolicyV
779779

780780
// ── Recent decisions ────────────────────────────────────────────────
781781

782+
/** A decision's tool: the name people know it by, with the name agents call it next to it. */
783+
function EventTool({ tool, label }: { tool: string; label?: string }) {
784+
if (!label) return <>{tool}: </>;
785+
return (
786+
<>
787+
<span className="font-medium">{label}</span>{" "}
788+
<code className="text-xs text-zinc-400" data-testid="agent-log-tool-id">{tool}</code>:{" "}
789+
</>
790+
);
791+
}
792+
782793
export function RecentDecisions({ reload }: { reload: number }) {
783794
const [events, setEvents] = useState<AgentEvent[] | null>(null);
784795
useEffect(() => {
@@ -799,7 +810,7 @@ export function RecentDecisions({ reload }: { reload: number }) {
799810
{e.policy?.decision && <StatusPill tone={DECISION_TONE[e.policy.decision as Decision] ?? "neutral"}>{e.policy.decision}</StatusPill>}
800811
</div>
801812
<p className="mt-1 text-sm text-zinc-200">
802-
{e.tool ? `${e.tool}: ` : ""}
813+
{e.tool && <EventTool tool={e.tool} label={e.policy?.tool_label} />}
803814
{e.detail || e.action}
804815
</p>
805816
</li>

‎dashboard/src/lib/agent-policy.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,8 @@ export interface AgentEvent {
177177
risk?: string;
178178
result: string;
179179
detail?: string;
180-
policy?: { agent?: string; repo?: string; decision?: string; rule?: string; thread_id?: string };
180+
/** `tool_label`: the name people know the tool by ("Find order" for `tool_find_order`), when its definition gives one. */
181+
policy?: { agent?: string; repo?: string; decision?: string; rule?: string; thread_id?: string; tool_label?: string };
181182
}
182183

183184
export const AGENT_LABELS: Record<AgentKey, string> = {

0 commit comments

Comments
 (0)