Skip to content

Commit 8231c95

Browse files
committed
fix(web): restore work-log turn scoping and widen URL extraction
Address three Cursor reviewer comments on 7875a07: - ChatView: pass `activeLatestTurn?.turnId` into `deriveWorkLogEntries` again. The `undefined` slipped in during rebase resolution and broadened the chat work log across every turn instead of the active one. - session-logic: run `extractToolCommandActivity` for non-command tools so the timeline picks up localhost URLs and `outputPreview` from Monitor/tail tools, matching what `deriveSidebarAgentCommandStatus` already does. `commandPreview` stays narrow (via `extractToolCommand`) for non-command tools so details like `/tmp/app.ts` aren't inferred as commands. - toolActivity: normalize `127.0.0.1` and `[::1]` (along with `0.0.0.0`) to `localhost` for href-based dedup so the same server printed under multiple loopback hosts collapses to a single chip. The visible `url` preserves the original spelling.
1 parent 7875a07 commit 8231c95

4 files changed

Lines changed: 44 additions & 8 deletions

File tree

apps/web/src/components/ChatView.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,8 +1055,8 @@ export default function ChatView(props: ChatViewProps) {
10551055
const phase = derivePhase(activeThread?.session ?? null);
10561056
const threadActivities = activeThread?.activities ?? EMPTY_ACTIVITIES;
10571057
const workLogEntries = useMemo(
1058-
() => deriveWorkLogEntries(threadActivities, undefined),
1059-
[threadActivities],
1058+
() => deriveWorkLogEntries(threadActivities, activeLatestTurn?.turnId ?? undefined),
1059+
[activeLatestTurn?.turnId, threadActivities],
10601060
);
10611061
const latestTurnHasToolActivity = useMemo(
10621062
() => hasToolActivityForTurn(threadActivities, activeLatestTurn?.turnId),

apps/web/src/session-logic.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -580,11 +580,18 @@ function toDerivedWorkLogEntry(activity: OrchestrationThreadActivity): DerivedWo
580580
: null;
581581
const title = extractToolTitle(payload);
582582
const itemType = extractWorkLogItemType(payload);
583-
const commandActivity =
584-
itemType === "command_execution"
585-
? extractToolCommandActivity({ payload, title, itemType })
586-
: null;
587-
const commandPreview = commandActivity ?? extractToolCommand(payload);
583+
// Run URL/output extraction for every tool kind so Monitor/tail and other
584+
// log-style tools can surface localhost URLs in the timeline — matching the
585+
// sidebar's `deriveSidebarAgentCommandStatus`, which already widens beyond
586+
// command_execution. Keep `commandPreview` narrow for non-command tools so
587+
// details like `/tmp/app.ts` aren't inferred as commands.
588+
const commandActivity = extractToolCommandActivity({
589+
payload,
590+
title,
591+
itemType: itemType ?? "command_execution",
592+
});
593+
const commandPreview =
594+
itemType === "command_execution" ? commandActivity : extractToolCommand(payload);
588595
const changedFiles = extractChangedFiles(payload);
589596
const isTaskActivity = activity.kind === "task.progress" || activity.kind === "task.completed";
590597
const taskSummary =

packages/shared/src/toolActivity.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,29 @@ describe("toolActivity", () => {
9999
).toEqual(["http://localhost:3000"]);
100100
});
101101

102+
it("treats 127.0.0.1 and [::1] as localhost equivalents for dedup", () => {
103+
const urls = extractLocalhostUrlsFromText(
104+
"Local: http://localhost:3000 Loopback: http://127.0.0.1:3000 IPv6: http://[::1]:3000",
105+
"output",
106+
);
107+
expect(urls).toHaveLength(1);
108+
expect(urls[0]?.href).toBe("http://localhost:3000");
109+
expect(urls[0]?.url).toBe("http://localhost:3000");
110+
});
111+
112+
it("normalizes 127.0.0.1 href but preserves the original visible url", () => {
113+
const urls = extractLocalhostUrlsFromText("http://127.0.0.1:5173/", "detail");
114+
expect(urls).toEqual([
115+
{
116+
url: "http://127.0.0.1:5173/",
117+
href: "http://localhost:5173/",
118+
host: "127.0.0.1",
119+
port: 5173,
120+
source: "detail",
121+
},
122+
]);
123+
});
124+
102125
it("normalizes command tools to a stable ran-command label", () => {
103126
expect(
104127
deriveToolActivityPresentation({

packages/shared/src/toolActivity.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,13 @@ function stripTrailingUrlPunctuation(value: string): string {
5757
}
5858

5959
function hrefForLocalhostUrl(url: string, host: string): string {
60-
return host === "0.0.0.0" ? url.replace("://0.0.0.0:", "://localhost:") : url;
60+
if (host === "localhost") {
61+
return url;
62+
}
63+
// Treat all loopback hosts as equivalent for dedup so an agent that prints
64+
// both "http://localhost:5173" and "http://127.0.0.1:5173" yields a single
65+
// chip. The visible `url` field preserves the original spelling.
66+
return url.replace(`://${host}:`, "://localhost:");
6167
}
6268

6369
export function extractLocalhostUrlsFromText(

0 commit comments

Comments
 (0)