forked from farhoodlabs/paperclip
d4c3899ca4
## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Operators rely on issue, inbox, and routine views to understand what the company is doing in real time > - Those views need to stay fast and readable even when issue lists, markdown comments, and run metadata get large > - The current branch had a coherent set of UI and live-update improvements spread across issue search, issue detail rendering, routine affordances, and workspace lookups > - This pull request groups those board-facing changes into one standalone branch that can merge independently of the heartbeat/runtime work > - The benefit is a faster, clearer issue and routine workflow without changing the underlying task model ## What Changed - Show routine execution issues by default and rename the filter to `Hide routine runs` so the default state no longer looks like an active filter. - Show the routine name in the run dialog and tighten the issue properties pane with a workspace link, copy-on-click behavior, and an inline parent arrow. - Reduce issue detail rerenders, keep queued issue chat mounted, improve issues page search responsiveness, and speed up issues first paint. - Add inbox "other search results", refresh visible issue runs after status updates, and optimize workspace lookups through summary-mode execution workspace queries. - Improve markdown wrapping and scrolling behavior for long strings and self-comment code blocks. - Relax the markdown sanitizer assertion so the test still validates safety after the new wrap-friendly inline styles. ## Verification - `pnpm vitest run ui/src/components/IssuesList.test.tsx ui/src/lib/inbox.test.ts ui/src/pages/Issues.test.tsx ui/src/context/BreadcrumbContext.test.tsx ui/src/context/LiveUpdatesProvider.test.ts ui/src/components/MarkdownBody.test.tsx ui/src/api/execution-workspaces.test.ts server/src/__tests__/execution-workspaces-routes.test.ts` ## Risks - This touches several issue-facing UI surfaces at once, so regressions would most likely show up as stale rendering, search result mismatches, or small markdown presentation differences. - The workspace lookup optimization depends on the summary-mode route shape staying aligned between server and UI. ## Model Used - OpenAI Codex, GPT-5-based coding agent in the Codex CLI environment. Exact backend model deployment ID was not exposed in-session. Tool-assisted editing and shell execution were used. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
114 lines
3.3 KiB
TypeScript
114 lines
3.3 KiB
TypeScript
// @vitest-environment node
|
|
|
|
import { describe, expect, it } from "vitest";
|
|
import { renderToStaticMarkup } from "react-dom/server";
|
|
import type { TranscriptEntry } from "../../adapters";
|
|
import { ThemeProvider } from "../../context/ThemeContext";
|
|
import { RunTranscriptView, normalizeTranscript } from "./RunTranscriptView";
|
|
|
|
describe("RunTranscriptView", () => {
|
|
it("keeps running command stdout inside the command fold instead of a standalone stdout block", () => {
|
|
const entries: TranscriptEntry[] = [
|
|
{
|
|
kind: "tool_call",
|
|
ts: "2026-03-12T00:00:00.000Z",
|
|
name: "command_execution",
|
|
toolUseId: "cmd_1",
|
|
input: { command: "ls -la" },
|
|
},
|
|
{
|
|
kind: "stdout",
|
|
ts: "2026-03-12T00:00:01.000Z",
|
|
text: "file-a\nfile-b",
|
|
},
|
|
];
|
|
|
|
const blocks = normalizeTranscript(entries, false);
|
|
|
|
expect(blocks).toHaveLength(1);
|
|
expect(blocks[0]).toMatchObject({
|
|
type: "command_group",
|
|
items: [{ result: "file-a\nfile-b", status: "running" }],
|
|
});
|
|
});
|
|
|
|
it("renders assistant and thinking content as markdown in compact mode", () => {
|
|
const html = renderToStaticMarkup(
|
|
<ThemeProvider>
|
|
<RunTranscriptView
|
|
density="compact"
|
|
entries={[
|
|
{
|
|
kind: "assistant",
|
|
ts: "2026-03-12T00:00:00.000Z",
|
|
text: "Hello **world**",
|
|
},
|
|
{
|
|
kind: "thinking",
|
|
ts: "2026-03-12T00:00:01.000Z",
|
|
text: "- first\n- second",
|
|
},
|
|
]}
|
|
/>
|
|
</ThemeProvider>,
|
|
);
|
|
|
|
expect(html).toContain("<strong>world</strong>");
|
|
expect(html).toMatch(/<li[^>]*>first<\/li>/);
|
|
expect(html).toMatch(/<li[^>]*>second<\/li>/);
|
|
});
|
|
|
|
it("hides saved-session resume skip stderr from nice mode normalization", () => {
|
|
const entries: TranscriptEntry[] = [
|
|
{
|
|
kind: "stderr",
|
|
ts: "2026-03-12T00:00:00.000Z",
|
|
text: "[paperclip] Skipping saved session resume for task \"PAP-485\" because wake reason is issue_assigned.",
|
|
},
|
|
{
|
|
kind: "assistant",
|
|
ts: "2026-03-12T00:00:01.000Z",
|
|
text: "Working on the task.",
|
|
},
|
|
];
|
|
|
|
const blocks = normalizeTranscript(entries, false);
|
|
|
|
expect(blocks).toHaveLength(1);
|
|
expect(blocks[0]).toMatchObject({
|
|
type: "message",
|
|
role: "assistant",
|
|
text: "Working on the task.",
|
|
});
|
|
});
|
|
|
|
it("renders successful result summaries as markdown in nice mode", () => {
|
|
const html = renderToStaticMarkup(
|
|
<ThemeProvider>
|
|
<RunTranscriptView
|
|
density="compact"
|
|
entries={[
|
|
{
|
|
kind: "result",
|
|
ts: "2026-03-12T00:00:02.000Z",
|
|
text: "## Summary\n\n- fixed deploy config\n- posted issue update",
|
|
inputTokens: 10,
|
|
outputTokens: 20,
|
|
cachedTokens: 0,
|
|
costUsd: 0,
|
|
subtype: "success",
|
|
isError: false,
|
|
errors: [],
|
|
},
|
|
]}
|
|
/>
|
|
</ThemeProvider>,
|
|
);
|
|
|
|
expect(html).toContain("<h2>Summary</h2>");
|
|
expect(html).toMatch(/<li[^>]*>fixed deploy config<\/li>/);
|
|
expect(html).toMatch(/<li[^>]*>posted issue update<\/li>/);
|
|
expect(html).not.toContain("result");
|
|
});
|
|
});
|