mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-23 09:07:46 +02:00
fix(ui): remove the provider trace run button (#17211)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The agent header provides actions to assign work and start runs. > - A second run button starts a run with raw provider tracing. > - Agent configuration already has a switch for raw tracing on future runs. > - This pull request removes the extra run button and its unused code. > - The header keeps one normal run action and the saved tracing status. ## Linked Issues or Issue Description **What existing behavior does this improve?** The action buttons in the agent detail header. **Current behavior** Administrators see Run now and Run with provider trace next to each other. **Proposed behavior** Remove Run with provider trace from the header. Use Capture raw provider traces in the configuration Debugging section to enable tracing for future runs. **Reason and benefit** Keep the normal run action clear. Put the tracing setting with the other agent settings. **Breaking changes** The separate trace button is removed. The tracing configuration, trace API, and run inspector actions stay available. ## What Changed - Remove the trace button, its property, and its mutation. - Remove the property from the agent detail page. - Update tests for normal runs with saved tracing on and off. - Check normal actions for Codex, Dot, and Muse. - Document the tracing setting in the feature map. ## Verification - Passed: 178 focused UI tests across AgentActionButtons, AgentDetail.accounting, RunnerInspector, AgentConfigForm, and AgentConfigForm.render. - Passed: pnpm check:token-gates. - Passed: node scripts/check-maps.mjs. - Passed: git diff --check. - Passed: [PR CI workflow](https://github.com/paperclipai/paperclip/actions/runs/39796866659), including the required verify and e2e gates. - Passed: Greptile 5/5 with no open review threads. - Two optional job badges still say running. Their test, cleanup, and final job steps passed. The parent workflow completed with success. - The broad local checks could not complete with the installed dependencies. The full typecheck and build require smol-toml. The UI checks also require @spekoai/client and the plugin SDK UI build. The full test run was stopped after many suites could not load. The PR workflow and both required gates passed for the current head. - To inspect the UI, open an agent. Confirm there is one Run now action. Enable Capture raw provider traces under configuration, Debugging. Save the change. Confirm the header shows Raw tracing on and still has one run action. ## Risks - Low risk. This removes one UI action and its unused code. - Administrators use the saved Debugging setting for tracing future runs. - No API, database, or permission changes. ## Model Used OpenAI GPT-6 through Codex, with reasoning, tool use, and code execution. The exact serving model ID and context window are not exposed in this run. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge Co-authored-by: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
043f2514e6
commit
25f2d05282
5 files changed
+21
-56
No files matched your search
@@ -28,6 +28,9 @@ Open an agent’s model/adapter configuration or the instance adapter settings p
|
||||
### `run-history`
|
||||
|
||||
Open an agent run at `/agents/:agentId/runs/:runId` from the agent or task activity.
|
||||
The agent header has one Run now action. Administrators can enable
|
||||
Capture raw provider traces under the agent configuration’s Debugging section
|
||||
for future runs. The header shows Raw tracing on while that setting is enabled.
|
||||
|
||||
For latency diagnosis with an operator OTLP endpoint, search the hashed run ID
|
||||
without restricting the root span name. Compare workspace preparation with its
|
||||
|
||||
@@ -212,23 +212,20 @@ describe("AgentActionButtons", () => {
|
||||
expect(container.textContent).not.toContain("Clear error");
|
||||
});
|
||||
|
||||
it("starts an administrator-selected run with raw provider tracing", async () => {
|
||||
render(makeAgent(), { canRunWithProviderTrace: true });
|
||||
it.each([false, true])("keeps the normal run action when persistent tracing is %s", async tracingEnabled => {
|
||||
render(makeAgent({ runtimeConfig: tracingEnabled ? { debug: { providerTrace: "raw" } } : {} }));
|
||||
await flushReact();
|
||||
|
||||
const traceButton = Array.from(container.querySelectorAll("button")).find(
|
||||
(button) => button.textContent?.includes("Run with provider trace"),
|
||||
);
|
||||
expect(traceButton).toBeTruthy();
|
||||
const buttons = Array.from(container.querySelectorAll("button"));
|
||||
expect(buttons.some(button => button.textContent?.includes("Run with provider trace"))).toBe(false);
|
||||
expect(container.textContent?.includes("Raw tracing on")).toBe(tracingEnabled);
|
||||
|
||||
await act(async () => {
|
||||
traceButton?.click();
|
||||
buttons.find(button => button.textContent === "Run Heartbeat")!.click();
|
||||
});
|
||||
await flushReact();
|
||||
|
||||
expect(mockAgentsApi.invoke).toHaveBeenCalledWith("agent-1", "company-1", {
|
||||
debug: { providerTrace: "raw" },
|
||||
});
|
||||
expect(mockAgentsApi.invoke).toHaveBeenCalledExactlyOnceWith("agent-1", "company-1");
|
||||
expect(mockNavigate).toHaveBeenCalledWith("/agents/alpha/runs/run-1");
|
||||
});
|
||||
|
||||
|
||||
@@ -167,7 +167,6 @@ export function AgentActionButtons({
|
||||
workActionsDisabled = false,
|
||||
workActionsDisabledReason,
|
||||
navigateToRunOnInvoke = true,
|
||||
canRunWithProviderTrace = false,
|
||||
hasPendingNavigationChanges = false,
|
||||
onBeforeNavigate,
|
||||
onActionError,
|
||||
@@ -188,8 +187,6 @@ export function AgentActionButtons({
|
||||
workActionsDisabled?: boolean;
|
||||
workActionsDisabledReason?: string;
|
||||
navigateToRunOnInvoke?: boolean;
|
||||
/** Instance administrators may opt one manual run into short-lived raw provider capture. */
|
||||
canRunWithProviderTrace?: boolean;
|
||||
/** Whether the caller currently has an unsaved draft that navigation would discard. */
|
||||
hasPendingNavigationChanges?: boolean;
|
||||
/** Return false to stop an action whose success would navigate away. */
|
||||
@@ -297,24 +294,6 @@ export function AgentActionButtons({
|
||||
},
|
||||
});
|
||||
|
||||
const providerTraceAction = useMutation({
|
||||
mutationFn: () =>
|
||||
agentsApi.invoke(agent.id, resolvedCompanyId ?? undefined, {
|
||||
debug: { providerTrace: "raw" },
|
||||
}),
|
||||
onSuccess: (run) => {
|
||||
onActionError?.(null);
|
||||
invalidateAgent();
|
||||
if (navigateToRunOnInvoke) {
|
||||
if (!confirmLateNavigationChanges(agentActionStartedDirtyRef)) return;
|
||||
navigate(`/agents/${canonicalAgentRef}/runs/${run.id}`);
|
||||
}
|
||||
},
|
||||
onError: (err) => {
|
||||
reportError(err instanceof Error ? err.message : "Failed to start traced run");
|
||||
},
|
||||
});
|
||||
|
||||
const duplicateAgent = useMutation({
|
||||
mutationFn: async () => {
|
||||
if (!resolvedCompanyId) {
|
||||
@@ -370,7 +349,7 @@ export function AgentActionButtons({
|
||||
});
|
||||
|
||||
const isPendingApproval = agent.status === "pending_approval";
|
||||
const disabled = actionsDisabled || agentAction.isPending || providerTraceAction.isPending;
|
||||
const disabled = actionsDisabled || agentAction.isPending;
|
||||
const assignAndRunDisabled = disabled || isPendingApproval || workActionsDisabled || agent.status === "terminated";
|
||||
const pauseResumeDisabled = disabled || isPendingApproval || (isPaused && workActionsDisabled)
|
||||
|| Boolean(agent.lifecycleState && ["pausing", "terminating", "cleaning_up", "terminated", "rejected"].includes(agent.lifecycleState));
|
||||
@@ -412,21 +391,6 @@ export function AgentActionButtons({
|
||||
label={runLabel}
|
||||
size={size}
|
||||
/>}
|
||||
{canRunWithProviderTrace && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size={size}
|
||||
onClick={() => {
|
||||
if (navigateToRunOnInvoke && !confirmNavigationStart(agentActionStartedDirtyRef)) return;
|
||||
providerTraceAction.mutate();
|
||||
}}
|
||||
disabled={assignAndRunDisabled}
|
||||
title="Capture exact provider traffic for this run (expires after 24 hours)"
|
||||
>
|
||||
<Bug className="h-3.5 w-3.5 sm:mr-1" />
|
||||
<span className="hidden sm:inline">Run with provider trace</span>
|
||||
</Button>
|
||||
)}
|
||||
{isError ? (
|
||||
<ClearErrorButton
|
||||
onClick={() => agentAction.mutate("clear_error")}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { AgentActionButtons } from "../components/AgentActionButtons";
|
||||
import type { Agent, HeartbeatRun } from "@paperclipai/shared";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { RunAccountingMetrics } from "./AgentDetail";
|
||||
import { hasUnavailableProviderAccounting, supportsRawProviderTrace } from "../lib/utils";
|
||||
import { hasUnavailableProviderAccounting } from "../lib/utils";
|
||||
|
||||
vi.mock("@/lib/router", () => ({ useNavigate: () => vi.fn() }));
|
||||
vi.mock("../context/DialogContext", () => ({ useDialogActions: () => ({ openNewIssue: vi.fn() }) }));
|
||||
@@ -41,7 +41,7 @@ describe("run accounting provenance", () => {
|
||||
|
||||
|
||||
describe("provider trace support", () => {
|
||||
const renderActions = (provider: string, isAdmin: boolean) => {
|
||||
const renderActions = (provider: string) => {
|
||||
const agent: Agent = {
|
||||
id: "agent-1", companyId: "company-1", name: "Researcher", urlKey: "researcher", role: "researcher",
|
||||
title: null, icon: null, status: "active", reportsTo: null, capabilities: null,
|
||||
@@ -52,22 +52,24 @@ describe("provider trace support", () => {
|
||||
};
|
||||
return renderToStaticMarkup(
|
||||
<QueryClientProvider client={new QueryClient()}>
|
||||
<AgentActionButtons agent={agent} canRunWithProviderTrace={isAdmin && supportsRawProviderTrace(agent.adapterType, agent.adapterConfig)} />
|
||||
<AgentActionButtons agent={agent} />
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
};
|
||||
|
||||
it("keeps normal Muse actions but removes the unsupported raw traffic promise", () => {
|
||||
const markup = renderActions("muse", true);
|
||||
const markup = renderActions("muse");
|
||||
expect(markup).toContain("Run now");
|
||||
expect(markup).toContain("Pause");
|
||||
expect(markup).not.toContain("Run with provider trace");
|
||||
expect(markup).not.toContain("Capture exact provider traffic");
|
||||
});
|
||||
|
||||
it("retains other provider tracing only for authorized administrators", () => {
|
||||
expect(renderActions("codex", true)).toContain("Run with provider trace");
|
||||
expect(renderActions("openai_dot", true)).toContain("Run with provider trace");
|
||||
expect(renderActions("codex", false)).not.toContain("Run with provider trace");
|
||||
it.each(["codex", "openai_dot"])("keeps normal %s actions without a separate trace button", provider => {
|
||||
const markup = renderActions(provider);
|
||||
expect(markup).toContain("Run now");
|
||||
expect(markup).toContain("Pause");
|
||||
expect(markup).not.toContain("Run with provider trace");
|
||||
expect(markup).not.toContain("Capture exact provider traffic");
|
||||
});
|
||||
});
|
||||
@@ -1294,7 +1294,6 @@ export function AgentDetail() {
|
||||
companyId={resolvedCompanyId}
|
||||
assignLabel="Assign Task"
|
||||
showStatus={false}
|
||||
canRunWithProviderTrace={canUseProviderTrace && supportsRawProviderTrace(currentAgent.adapterType, currentAgent.adapterConfig)}
|
||||
actionsDisabled={agentAction.isPending}
|
||||
workActionsDisabled={hasInvalidOrgChain}
|
||||
workActionsDisabledReason="Repair this agent's reporting chain before assigning tasks or starting runs"
|
||||
|
||||
Reference in new issue
Block a user