| author | |
| committer | |
| log | ec44bc56f598be16ffbc22ed0e4e095447043844 |
| tree | e125223869b0e3345d20bc620b3ba6b9b33fa5f2 |
| parent | 922bd692251bc803c12a3fab159efe83c957bb70 |
| signature | Signed by PGP key B5690EEEBB952194 |
Co-authored-by: maria-rcks <254055478+maria-rcks@users.noreply.github.com>8 files changed, 54 insertions(+), 37 deletions(-)
apps/mobile/src/lib/threadActivity.test.ts+8-6| ... | @@ -868,7 +868,7 @@ describe("buildThreadFeed", () => { | ... | @@ -868,7 +868,7 @@ describe("buildThreadFeed", () => { |
| 868 | title: "Call MCP tool", | 868 | title: "Call MCP tool", |
| 869 | item: { server: "t3-code", tool: "preview_click" }, | 869 | item: { server: "t3-code", tool: "preview_click" }, |
| 870 | status: undefined, | 870 | status: undefined, |
| 871 | displayName: "Click in the preview browser", | 871 | displayName: "Clicking in the preview browser", |
| 872 | liveDisplayName: "Clicking in the preview browser", | 872 | liveDisplayName: "Clicking in the preview browser", |
| 873 | settledDisplayName: "Clicked in the preview browser", | 873 | settledDisplayName: "Clicked in the preview browser", |
| 874 | icon: "browser", | 874 | icon: "browser", |
| ... | @@ -879,7 +879,7 @@ describe("buildThreadFeed", () => { | ... | @@ -879,7 +879,7 @@ describe("buildThreadFeed", () => { |
| 879 | title: "Call MCP tool", | 879 | title: "Call MCP tool", |
| 880 | item: { server: "t3-code", tool: "task_status" }, | 880 | item: { server: "t3-code", tool: "task_status" }, |
| 881 | status: undefined, | 881 | status: undefined, |
| 882 | displayName: "Get delegated task status", | 882 | displayName: "Getting delegated task status", |
| 883 | liveDisplayName: "Getting delegated task status", | 883 | liveDisplayName: "Getting delegated task status", |
| 884 | settledDisplayName: "Got delegated task status", | 884 | settledDisplayName: "Got delegated task status", |
| 885 | icon: "t3-code", | 885 | icon: "t3-code", |
| ... | @@ -1039,7 +1039,7 @@ describe("buildThreadFeed", () => { | ... | @@ -1039,7 +1039,7 @@ describe("buildThreadFeed", () => { |
| 1039 | ).toMatchObject([ | 1039 | ).toMatchObject([ |
| 1040 | { | 1040 | { |
| 1041 | type: "work-toggle", | 1041 | type: "work-toggle", |
| 1042 | summary: "Clicked in the preview browser", | 1042 | summary: "Clicking in the preview browser", |
| 1043 | summaryToolIcon: "browser", | 1043 | summaryToolIcon: "browser", |
| 1044 | live: true, | 1044 | live: true, |
| 1045 | }, | 1045 | }, |
| ... | @@ -1050,18 +1050,20 @@ describe("buildThreadFeed", () => { | ... | @@ -1050,18 +1050,20 @@ describe("buildThreadFeed", () => { |
| 1050 | { | 1050 | { |
| 1051 | status: "completed", | 1051 | status: "completed", |
| 1052 | displayName: "Clicked in the preview browser", | 1052 | displayName: "Clicked in the preview browser", |
| 1053 | liveDisplayName: "Clicking in the preview browser", | ||
| 1053 | detail: "Clicked Continue", | 1054 | detail: "Clicked Continue", |
| 1054 | hasFailure: false, | 1055 | hasFailure: false, |
| 1055 | }, | 1056 | }, |
| 1056 | { | 1057 | { |
| 1057 | status: "failed", | 1058 | status: "failed", |
| 1058 | displayName: "Failed to click in the preview browser", | 1059 | displayName: "Failed to click in the preview browser", |
| 1060 | liveDisplayName: "Failed to click in the preview browser", | ||
| 1059 | detail: "Timed out waiting for Continue", | 1061 | detail: "Timed out waiting for Continue", |
| 1060 | hasFailure: true, | 1062 | hasFailure: true, |
| 1061 | }, | 1063 | }, |
| 1062 | ])( | 1064 | ])( |
| 1063 | "uses the browser call label once its action settles as $status", | 1065 | "uses the browser call label once its action settles as $status", |
| 1064 | ({ status, displayName, detail, hasFailure }) => { | 1066 | ({ status, displayName, liveDisplayName, detail, hasFailure }) => { |
| 1065 | const turnId = TurnId.make("turn-preview-lifecycle"); | 1067 | const turnId = TurnId.make("turn-preview-lifecycle"); |
| 1066 | const toolCallId = "preview-click"; | 1068 | const toolCallId = "preview-click"; |
| 1067 | const groupId = `work-group:tool:${turnId}:${toolCallId}`; | 1069 | const groupId = `work-group:tool:${turnId}:${toolCallId}`; |
| ... | @@ -1156,7 +1158,7 @@ describe("buildThreadFeed", () => { | ... | @@ -1156,7 +1158,7 @@ describe("buildThreadFeed", () => { |
| 1156 | groupId, | 1158 | groupId, |
| 1157 | hiddenCount: 1, | 1159 | hiddenCount: 1, |
| 1158 | expanded: true, | 1160 | expanded: true, |
| 1159 | summary: displayName, | 1161 | summary: liveDisplayName, |
| 1160 | summaryToolIcon: "browser", | 1162 | summaryToolIcon: "browser", |
| 1161 | hasFailure, | 1163 | hasFailure, |
| 1162 | live: true, | 1164 | live: true, |
| ... | @@ -1677,7 +1679,7 @@ describe("buildThreadFeed", () => { | ... | @@ -1677,7 +1679,7 @@ describe("buildThreadFeed", () => { |
| 1677 | ( | 1679 | ( |
| 1678 | [ | 1680 | [ |
| 1679 | { lifecycleStatus: "inProgress", summary: "Running pnpm", shimmer: true }, | 1681 | { lifecycleStatus: "inProgress", summary: "Running pnpm", shimmer: true }, |
| 1680 | { lifecycleStatus: "completed", summary: "Ran pnpm", shimmer: false }, | 1682 | { lifecycleStatus: "completed", summary: "Running pnpm", shimmer: false }, |
| 1681 | { lifecycleStatus: "failed", summary: "Failed pnpm", shimmer: false }, | 1683 | { lifecycleStatus: "failed", summary: "Failed pnpm", shimmer: false }, |
| 1682 | { lifecycleStatus: "declined", summary: "Declined pnpm", shimmer: false }, | 1684 | { lifecycleStatus: "declined", summary: "Declined pnpm", shimmer: false }, |
| 1683 | { lifecycleStatus: "stopped", summary: "Stopped pnpm", shimmer: false }, | 1685 | { lifecycleStatus: "stopped", summary: "Stopped pnpm", shimmer: false }, |
apps/mobile/src/lib/threadActivity.ts+8-7| ... | @@ -17,6 +17,7 @@ import { | ... | @@ -17,6 +17,7 @@ import { |
| 17 | commandDetailRepeatsCommand, | 17 | commandDetailRepeatsCommand, |
| 18 | extractCommandOutputText, | 18 | extractCommandOutputText, |
| 19 | isWorktreeSetupActivity, | 19 | isWorktreeSetupActivity, |
| 20 | liveActivityToolStatus, | ||
| 20 | normalizeCompactToolLabel, | 21 | normalizeCompactToolLabel, |
| 21 | omitSupersededLifecycleMarkers, | 22 | omitSupersededLifecycleMarkers, |
| 22 | resolveWorkEntryToolPresentation, | 23 | resolveWorkEntryToolPresentation, |
| ... | @@ -1528,7 +1529,7 @@ function appendToolGroupRows( | ... | @@ -1528,7 +1529,7 @@ function appendToolGroupRows( |
| 1528 | const latestActivity = latestActiveActivity ?? activities.at(-1)!; | 1529 | const latestActivity = latestActiveActivity ?? activities.at(-1)!; |
| 1529 | const singleActivity = activities.length === 1 ? latestActivity : null; | 1530 | const singleActivity = activities.length === 1 ? latestActivity : null; |
| 1530 | const summary = live | 1531 | const summary = live |
| 1531 | ? liveToolActivitySummary(latestActivity, active) | 1532 | ? liveToolActivitySummary(latestActivity, live) |
| 1532 | : singleActivity !== null && | 1533 | : singleActivity !== null && |
| 1533 | singleActivity.toolLike && | 1534 | singleActivity.toolLike && |
| 1534 | toolGroupAction(singleActivity.workEntry) !== "edit" | 1535 | toolGroupAction(singleActivity.workEntry) !== "edit" |
| ... | @@ -1580,16 +1581,16 @@ function appendToolGroupRows( | ... | @@ -1580,16 +1581,16 @@ function appendToolGroupRows( |
| 1580 | }); | 1581 | }); |
| 1581 | } | 1582 | } |
| 1582 | 1583 | ||
| 1583 | function liveToolActivitySummary(activity: ThreadFeedActivity, active: boolean): string { | 1584 | function liveToolActivitySummary(activity: ThreadFeedActivity, presentTense: boolean): string { |
| 1584 | const presentation = resolveWorkEntryToolPresentation( | 1585 | const status = liveActivityToolStatus(activity.lifecycleStatus, presentTense); |
| 1585 | activity.workEntry, | 1586 | const presentation = resolveWorkEntryToolPresentation({ |
| 1586 | active ? "inProgress" : "completed", | 1587 | ...activity.workEntry, |
| 1587 | ); | 1588 | toolLifecycleStatus: status, |
| 1589 | }); | ||
| 1588 | if (presentation) return presentation.displayName; | 1590 | if (presentation) return presentation.displayName; |
| 1589 | const command = activity.workEntry.command?.trim(); | 1591 | const command = activity.workEntry.command?.trim(); |
| 1590 | if (command) { | 1592 | if (command) { |
| 1591 | const program = commandProgramName(command); | 1593 | const program = commandProgramName(command); |
| 1592 | const status = activity.lifecycleStatus ?? (active ? "inProgress" : "completed"); | ||
| 1593 | const verb = | 1594 | const verb = |
| 1594 | status === "inProgress" | 1595 | status === "inProgress" |
| 1595 | ? "Running" | 1596 | ? "Running" |
apps/web/src/components/chat/MessagesTimeline.logic.test.ts+13-10| ... | @@ -99,13 +99,16 @@ describe("work entry labels", () => { | ... | @@ -99,13 +99,16 @@ describe("work entry labels", () => { |
| 99 | ); | 99 | ); |
| 100 | }); | 100 | }); |
| 101 | 101 | ||
| 102 | it("does not describe a finished call as still running while the turn continues", () => { | 102 | it("keeps the latest live activity in the present tense after the call completes", () => { |
| 103 | const browserEntry = { | 103 | const browserEntry = { |
| 104 | ...entry, | 104 | ...entry, |
| 105 | toolTitle: "T3-code.preview_click", | 105 | toolTitle: "T3-code.preview_click", |
| 106 | toolLifecycleStatus: "completed" as const, | 106 | toolLifecycleStatus: "completed" as const, |
| 107 | }; | 107 | }; |
| 108 | expect(liveWorkEntryLabel(browserEntry, undefined, true)).toBe( | 108 | expect(liveWorkEntryLabel(browserEntry, undefined, true)).toBe( |
| 109 | "Clicking in the preview browser", | ||
| 110 | ); | ||
| 111 | expect(liveWorkEntryLabel(browserEntry, undefined, false)).toBe( | ||
| 109 | "Clicked in the preview browser", | 112 | "Clicked in the preview browser", |
| 110 | ); | 113 | ); |
| 111 | }); | 114 | }); |
| ... | @@ -134,21 +137,21 @@ describe("work entry labels", () => { | ... | @@ -134,21 +137,21 @@ describe("work entry labels", () => { |
| 134 | }); | 137 | }); |
| 135 | 138 | ||
| 136 | it.each([ | 139 | it.each([ |
| 137 | ["inProgress", "Running vp"], | 140 | ["inProgress", "Running vp", "Running vp"], |
| 138 | ["completed", "Ran vp"], | 141 | ["completed", "Running vp", "Ran vp"], |
| 139 | ["failed", "Failed vp"], | 142 | ["failed", "Failed vp", "Failed vp"], |
| 140 | ["declined", "Declined vp"], | 143 | ["declined", "Declined vp", "Declined vp"], |
| 141 | ["stopped", "Stopped vp"], | 144 | ["stopped", "Stopped vp", "Stopped vp"], |
| 142 | ] as const)( | 145 | ] as const)( |
| 143 | "uses the command's %s outcome even while the turn continues", | 146 | "uses present tense for a live %s command and the outcome once it is no longer live", |
| 144 | (toolLifecycleStatus, label) => { | 147 | (toolLifecycleStatus, liveLabel, settledLabel) => { |
| 145 | const commandEntry = { | 148 | const commandEntry = { |
| 146 | ...entry, | 149 | ...entry, |
| 147 | command: "/bin/bash -lc 'vp test run'", | 150 | command: "/bin/bash -lc 'vp test run'", |
| 148 | toolLifecycleStatus, | 151 | toolLifecycleStatus, |
| 149 | }; | 152 | }; |
| 150 | expect(liveWorkEntryLabel(commandEntry, undefined, true)).toBe(label); | 153 | expect(liveWorkEntryLabel(commandEntry, undefined, true)).toBe(liveLabel); |
| 151 | expect(liveWorkEntryLabel(commandEntry, undefined, false)).toBe(label); | 154 | expect(liveWorkEntryLabel(commandEntry, undefined, false)).toBe(settledLabel); |
| 152 | }, | 155 | }, |
| 153 | ); | 156 | ); |
| 154 | 157 |
apps/web/src/components/chat/MessagesTimeline.logic.ts+6-5| ... | @@ -2,6 +2,7 @@ import * as Equal from "effect/Equal"; | ... | @@ -2,6 +2,7 @@ import * as Equal from "effect/Equal"; |
| 2 | import { renderCodexDirectivesForCopy } from "@t3tools/client-runtime/codex-markdown-directives"; | 2 | import { renderCodexDirectivesForCopy } from "@t3tools/client-runtime/codex-markdown-directives"; |
| 3 | import { commandProgramName } from "@t3tools/client-runtime/work-log/command-label"; | 3 | import { commandProgramName } from "@t3tools/client-runtime/work-log/command-label"; |
| 4 | import { | 4 | import { |
| 5 | liveActivityToolStatus, | ||
| 5 | normalizeCompactToolLabel, | 6 | normalizeCompactToolLabel, |
| 6 | omitSupersededLifecycleMarkers, | 7 | omitSupersededLifecycleMarkers, |
| 7 | resolveWorkEntryToolPresentation, | 8 | resolveWorkEntryToolPresentation, |
| ... | @@ -65,14 +66,14 @@ export function liveWorkEntryLabel( | ... | @@ -65,14 +66,14 @@ export function liveWorkEntryLabel( |
| 65 | workspaceRoot: string | undefined, | 66 | workspaceRoot: string | undefined, |
| 66 | active: boolean, | 67 | active: boolean, |
| 67 | ) { | 68 | ) { |
| 68 | const toolPresentation = resolveWorkEntryToolPresentation( | 69 | const status = liveActivityToolStatus(entry.toolLifecycleStatus, active); |
| 69 | entry, | 70 | const toolPresentation = resolveWorkEntryToolPresentation({ |
| 70 | active ? "inProgress" : "completed", | 71 | ...entry, |
| 71 | ); | 72 | toolLifecycleStatus: status, |
| 73 | }); | ||
| 72 | if (toolPresentation) return toolPresentation.displayName; | 74 | if (toolPresentation) return toolPresentation.displayName; |
| 73 | const command = entry.command?.trim(); | 75 | const command = entry.command?.trim(); |
| 74 | if (command) { | 76 | if (command) { |
| 75 | const status = entry.toolLifecycleStatus ?? (active ? "inProgress" : "completed"); | ||
| 76 | const verb = | 77 | const verb = |
| 77 | status === "inProgress" | 78 | status === "inProgress" |
| 78 | ? "Running" | 79 | ? "Running" |
apps/web/src/components/chat/MessagesTimeline.test.tsx+3-3| ... | @@ -1224,7 +1224,7 @@ describe("MessagesTimeline", () => { | ... | @@ -1224,7 +1224,7 @@ describe("MessagesTimeline", () => { |
| 1224 | expect(markup).toContain('data-timeline-row-id="live-activity-row"'); | 1224 | expect(markup).toContain('data-timeline-row-id="live-activity-row"'); |
| 1225 | }); | 1225 | }); |
| 1226 | 1226 | ||
| 1227 | it("keeps the completed command in the shared activity row with a past-tense label", () => { | 1227 | it("keeps the completed command in the shared activity row with a present-tense label", () => { |
| 1228 | const turnId = TurnId.make("turn-live"); | 1228 | const turnId = TurnId.make("turn-live"); |
| 1229 | const markup = renderToStaticMarkup( | 1229 | const markup = renderToStaticMarkup( |
| 1230 | <MessagesTimeline | 1230 | <MessagesTimeline |
| ... | @@ -1259,10 +1259,10 @@ describe("MessagesTimeline", () => { | ... | @@ -1259,10 +1259,10 @@ describe("MessagesTimeline", () => { |
| 1259 | />, | 1259 | />, |
| 1260 | ); | 1260 | ); |
| 1261 | 1261 | ||
| 1262 | expect(markup).toContain("Ran pnpm"); | 1262 | expect(markup).toContain("Running pnpm"); |
| 1263 | expect(markup).toContain("lucide-terminal"); | 1263 | expect(markup).toContain("lucide-terminal"); |
| 1264 | expect(markup).toContain("live-activity-focus"); | 1264 | expect(markup).toContain("live-activity-focus"); |
| 1265 | expect(markup).not.toContain("Running pnpm"); | 1265 | expect(markup).not.toContain("Ran pnpm"); |
| 1266 | expect(markup).not.toContain("Thinking"); | 1266 | expect(markup).not.toContain("Thinking"); |
| 1267 | expect(markup).not.toContain('data-timeline-row-kind="thinking"'); | 1267 | expect(markup).not.toContain('data-timeline-row-kind="thinking"'); |
| 1268 | }); | 1268 | }); |
docs/user/tool-activity.md+4-1| ... | @@ -8,7 +8,10 @@ indicate more calls above or below. Short groups use only the space they need. | ... | @@ -8,7 +8,10 @@ indicate more calls above or below. Short groups use only the space they need. |
| 8 | Collapsing and reopening a group preserves your reading position and any open call details. | 8 | Collapsing and reopening a group preserves your reading position and any open call details. |
| 9 | 9 | ||
| 10 | Recognized T3 tools use descriptive labels in both the running summary and individual rows. | 10 | Recognized T3 tools use descriptive labels in both the running summary and individual rows. |
| 11 | Labels follow the call's state, such as "Clicking" while running and "Clicked" after success. | 11 | The latest live activity stays in the present tense while the turn continues, such as |
| 12 | "Running vp" or "Clicking in the preview browser", even after that call has completed. | ||
| 13 | Expanded rows follow the call's own state, such as "Clicked" after success. | ||
| 14 | When a call has not reported a state yet, the label stays in the present tense. | ||
| 12 | Failed, declined, and stopped calls say what happened without implying success. | 15 | Failed, declined, and stopped calls say what happened without implying success. |
| 13 | Preview browser actions use a globe icon. Other T3 tools keep the T3 mark. | 16 | Preview browser actions use a globe icon. Other T3 tools keep the T3 mark. |
| 14 | Group summaries count browser actions separately, such as "Used browser 18 times" or | 17 | Group summaries count browser actions separately, such as "Used browser 18 times" or |
packages/client-runtime/src/work-log/presentation.test.ts+4-4| ... | @@ -25,7 +25,7 @@ describe("resolveWorkEntryToolPresentation", () => { | ... | @@ -25,7 +25,7 @@ describe("resolveWorkEntryToolPresentation", () => { |
| 25 | "preview_click", | 25 | "preview_click", |
| 26 | ])("recognizes browser tool names across providers: %s", (label) => { | 26 | ])("recognizes browser tool names across providers: %s", (label) => { |
| 27 | expect(resolveWorkEntryToolPresentation({ label })).toEqual({ | 27 | expect(resolveWorkEntryToolPresentation({ label })).toEqual({ |
| 28 | displayName: "Click in the preview browser", | 28 | displayName: "Clicking in the preview browser", |
| 29 | icon: "browser", | 29 | icon: "browser", |
| 30 | }); | 30 | }); |
| 31 | }); | 31 | }); |
| ... | @@ -37,7 +37,7 @@ describe("resolveWorkEntryToolPresentation", () => { | ... | @@ -37,7 +37,7 @@ describe("resolveWorkEntryToolPresentation", () => { |
| 37 | toolTitle: "Inspect the current page", | 37 | toolTitle: "Inspect the current page", |
| 38 | toolData: { server: "t3-code", tool: "preview_snapshot", result: { title: "Example" } }, | 38 | toolData: { server: "t3-code", tool: "preview_snapshot", result: { title: "Example" } }, |
| 39 | }), | 39 | }), |
| 40 | ).toEqual({ displayName: "Take a snapshot of the preview page", icon: "browser" }); | 40 | ).toEqual({ displayName: "Taking a snapshot of the preview page", icon: "browser" }); |
| 41 | }); | 41 | }); |
| 42 | 42 | ||
| 43 | it.each([ | 43 | it.each([ |
| ... | @@ -46,7 +46,7 @@ describe("resolveWorkEntryToolPresentation", () => { | ... | @@ -46,7 +46,7 @@ describe("resolveWorkEntryToolPresentation", () => { |
| 46 | ["failed", "Failed to click in the preview browser"], | 46 | ["failed", "Failed to click in the preview browser"], |
| 47 | ["declined", "Declined to click in the preview browser"], | 47 | ["declined", "Declined to click in the preview browser"], |
| 48 | ["stopped", "Stopped clicking in the preview browser"], | 48 | ["stopped", "Stopped clicking in the preview browser"], |
| 49 | ["unknown", "Click in the preview browser"], | 49 | ["unknown", "Clicking in the preview browser"], |
| 50 | ])("describes the tool's own %s state", (toolLifecycleStatus, displayName) => { | 50 | ])("describes the tool's own %s state", (toolLifecycleStatus, displayName) => { |
| 51 | expect( | 51 | expect( |
| 52 | resolveWorkEntryToolPresentation({ | 52 | resolveWorkEntryToolPresentation({ |
| ... | @@ -115,7 +115,7 @@ describe("resolveWorkEntryToolPresentation", () => { | ... | @@ -115,7 +115,7 @@ describe("resolveWorkEntryToolPresentation", () => { |
| 115 | label: "mcp__t3_code__task_status", | 115 | label: "mcp__t3_code__task_status", |
| 116 | toolTitle: "Check the child task", | 116 | toolTitle: "Check the child task", |
| 117 | }), | 117 | }), |
| 118 | ).toEqual({ displayName: "Get delegated task status", icon: "t3-code" }); | 118 | ).toEqual({ displayName: "Getting delegated task status", icon: "t3-code" }); |
| 119 | }); | 119 | }); |
| 120 | 120 | ||
| 121 | it("does not brand unknown tools or another server's matching tool name", () => { | 121 | it("does not brand unknown tools or another server's matching tool name", () => { |
packages/client-runtime/src/work-log/presentation.ts+8-1| ... | @@ -113,7 +113,7 @@ function resolveT3McpToolPresentation(value: string | undefined, status: string | ... | @@ -113,7 +113,7 @@ function resolveT3McpToolPresentation(value: string | undefined, status: string |
| 113 | ? `Declined to ${action.toLowerCase()}` | 113 | ? `Declined to ${action.toLowerCase()}` |
| 114 | : status === "stopped" | 114 | : status === "stopped" |
| 115 | ? `Stopped ${running.toLowerCase()}` | 115 | ? `Stopped ${running.toLowerCase()}` |
| 116 | : action; | 116 | : running; |
| 117 | 117 | ||
| 118 | return { | 118 | return { |
| 119 | displayName: `${verb} ${detail}`, | 119 | displayName: `${verb} ${detail}`, |
| ... | @@ -121,6 +121,13 @@ function resolveT3McpToolPresentation(value: string | undefined, status: string | ... | @@ -121,6 +121,13 @@ function resolveT3McpToolPresentation(value: string | undefined, status: string |
| 121 | }; | 121 | }; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | /** Latest live activity stays present-tense unless the call itself failed, declined, or stopped. */ | ||
| 125 | export function liveActivityToolStatus(status: string | undefined, presentTense: boolean) { | ||
| 126 | if (status === "failed" || status === "declined" || status === "stopped") return status; | ||
| 127 | if (presentTense || status === "inProgress") return "inProgress"; | ||
| 128 | return "completed"; | ||
| 129 | } | ||
| 130 | |||
| 124 | /** Resolves tool identity before choosing labels or icons in either client. */ | 131 | /** Resolves tool identity before choosing labels or icons in either client. */ |
| 125 | export function resolveWorkEntryToolPresentation( | 132 | export function resolveWorkEntryToolPresentation( |
| 126 | entry: Pick<WorkLogPresentationEntry, "label" | "toolTitle" | "toolData" | "toolLifecycleStatus">, | 133 | entry: Pick<WorkLogPresentationEntry, "label" | "toolTitle" | "toolData" | "toolLifecycleStatus">, |