Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review infoConfiguration used: Organization UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughAdds a standalone ToolOutput component and mcp-utils helpers; AiChat now appends compact tool-arg summaries to tool titles and conditionally renders a ConfigLink when an input has a string Changes
Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
5956534 to
2b8f5e7
Compare
2b8f5e7 to
8d66822
Compare
8d66822 to
96f882a
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
src/components/ai/AiChat.tsx (1)
331-356: Keep tool‑args summaries single‑line.Values can include newlines (e.g., multiline prompts), which may expand the header despite truncation. Normalizing whitespace keeps the title compact.
🧼 Optional tweak
- if (!result) return ""; - return result.length > maxLen - ? result.substring(0, maxLen - 1) + "…" - : result; + const normalized = result.replace(/\s+/g, " ").trim(); + if (!normalized) return ""; + return normalized.length > maxLen + ? normalized.substring(0, maxLen - 1) + "…" + : normalized;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/ai/AiChat.tsx` around lines 331 - 356, The tool-args summary may contain newlines which expand the header; inside formatToolArgsSummary normalize whitespace for all serialized values (replace sequences of whitespace including newlines with a single space and trim) before joining/truncating. Update the serialize function and the main mapping in formatToolArgsSummary so each String(v) is passed through a whitespace-collapse/trim step (e.g., replace(/\s+/g,' ') and .trim()) so entries like multiline prompts become single-line, then apply the existing maxLen truncation logic.src/components/ai-elements/tool.tsx (1)
205-211: Remove redundant string fallback afterresolvedhandling.After resolving, string outputs are already handled, so the final
else if (typeof output === "string")branch is unreachable and can be removed for clarity.🧹 Cleanup
- } else if (typeof output === "string") { - Output = <CodeBlock code={output} language="json" />; - }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/ai-elements/tool.tsx` around lines 205 - 211, The final else-if branch that checks typeof output === "string" is redundant because strings are already handled by the resolved branch; remove the unreachable branch that returns <CodeBlock code={output} language="json" />. Locate the conditional block using the identifiers resolved, isValidElement, Output and CodeBlock in the component (the branch that currently does: } else if (typeof resolved === "object" && !isValidElement(resolved)) { ... } else if (typeof output === "string") { ... }) and delete the trailing else-if so the control flow ends after the resolved/object handling, keeping all other branches intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/components/ai-elements/tool.tsx`:
- Around line 144-172: The MCP envelope parsing (unwrapMCPEnvelope) and JSON
helper (tryParseJSON) must be removed from src/components/ai-elements/tool.tsx
and relocated into a wrapper or extension module that sits outside the
ai-elements registry files; create a new local wrapper component or utility
(e.g., aiEnvelopeWrapper or mcpUtils) and move the logic for unwrapMCPEnvelope
and tryParseJSON there, update any callers to import from that wrapper, and
leave tool.tsx unchanged so registry files remain pristine.
- Around line 184-189: The truncation badge check uses the raw output instead of
the MCP-unwrapped text, so move the isTruncated call to use the resolved string:
compute mcpText = unwrapMCPEnvelope(output), resolved = mcpText ?? output, then
call isTruncated(resolved) (update the truncated constant) so the badge will
detect markers inside MCP content; adjust any downstream uses of truncated to
the new value.
---
Nitpick comments:
In `@src/components/ai-elements/tool.tsx`:
- Around line 205-211: The final else-if branch that checks typeof output ===
"string" is redundant because strings are already handled by the resolved
branch; remove the unreachable branch that returns <CodeBlock code={output}
language="json" />. Locate the conditional block using the identifiers resolved,
isValidElement, Output and CodeBlock in the component (the branch that currently
does: } else if (typeof resolved === "object" && !isValidElement(resolved)) {
... } else if (typeof output === "string") { ... }) and delete the trailing
else-if so the control flow ends after the resolved/object handling, keeping all
other branches intact.
In `@src/components/ai/AiChat.tsx`:
- Around line 331-356: The tool-args summary may contain newlines which expand
the header; inside formatToolArgsSummary normalize whitespace for all serialized
values (replace sequences of whitespace including newlines with a single space
and trim) before joining/truncating. Update the serialize function and the main
mapping in formatToolArgsSummary so each String(v) is passed through a
whitespace-collapse/trim step (e.g., replace(/\s+/g,' ') and .trim()) so entries
like multiline prompts become single-line, then apply the existing maxLen
truncation logic.
Keep ai-elements/tool.tsx free of local MCP parsing logic by introducing a local ToolOutput wrapper and mcp utilities. Also compute truncation badge state from MCP-unwrapped text so truncated markers inside content.text are detected.
96f882a to
4733574
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (1)
src/components/ai-elements/tool.tsx (1)
156-158: Registry file still modified — move the badge removal to the wrapper instead.Even though the MCP parsing has been correctly extracted to
mcp-utils.ts/ToolOutput.tsx, this file is still being touched. The truncation badge was removed directly from the registry'sToolOutputrather than being omitted only in the wrapper. Keepingtool.tsxpristine means the wrapper (src/components/ai/ToolOutput.tsx) should simply never use the registry'sToolOutputcomponent for rendering — which is already the case — so there's no need to alter this file at all.Based on learnings, do not edit components under
src/components/ai-elements/that come from the AI SDK registry (https://registry.ai-sdk.dev/); changes should be applied via extension/wrapper components that sit outside theai-elementsdirectory.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/ai-elements/tool.tsx` around lines 156 - 158, Revert any edits in the registry-sourced component src/components/ai-elements/tool.tsx (e.g., restore the original header/behavior around the {errorText ? "Error" : "Result"} line) and instead implement the truncation-badge removal in the wrapper component src/components/ai/ToolOutput.tsx so the wrapper never renders the registry's ToolOutput with the badge; ensure the wrapper filters/omits the truncation badge before passing props or rendering the registry ToolOutput component.
🧹 Nitpick comments (3)
src/components/ai/ToolOutput.tsx (1)
29-31:isError: truein the MCP envelope is silently ignored.
isError: truein the MCP spec signals to the client that the tool attempted execution but failed.unwrapMCPEnvelopeextracts the content text regardless of this flag, so an error response from an MCP tool will be labelled "Result" rather than "Error" (sincepart.errorTextfrom the AI SDK is unrelated to the envelope'sisErrorfield). Consider propagatingisErrorso the calling component can decide how to label and style the output. This is out of scope for the current PR but worth tracking as a follow-up.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/ai/ToolOutput.tsx` around lines 29 - 31, The MCP envelope's isError flag is being dropped by unwrapMCPEnvelope, so ToolOutput.tsx (variables mcpText and resolved) can't tell when an MCP tool failed; update unwrapMCPEnvelope to return both the extracted text and the envelope's isError (e.g., an object { text, isError }) and change callers in ToolOutput.tsx to use that result instead of just mcpText/resolved so the component can style/label output as an Error when isError is true; ensure isToolOutputTruncated continues to operate on the extracted text.src/components/ai/AiChat.tsx (1)
331-356: MoveformatToolArgsSummaryto module level.The function closes over nothing — no props, state, or refs — so defining it inside
AIChatcauses unnecessary recreation on every render. Hoisting it to module scope is a zero-risk improvement.♻️ Proposed refactor
- const formatToolArgsSummary = (input: unknown, maxLen = 90): string => { +// Module-level utility — no component dependencies +function formatToolArgsSummary(input: unknown, maxLen = 90): string { if (!input || typeof input !== "object" || Array.isArray(input)) { return ""; } ... - }; +}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/ai/AiChat.tsx` around lines 331 - 356, Hoist the formatToolArgsSummary function out of the AIChat component to module scope: cut the entire function (including its serialize helper) and paste it at top-level in the same file so it is defined once per module rather than on every render; keep the same signature (input: unknown, maxLen = 90): string and behavior, ensure it still references no component props/state, and update any internal references inside AIChat to use the now top-level formatToolArgsSummary identifier (no other API changes are required).src/components/ai/mcp-utils.ts (1)
32-46:tryParseJSONreturn typeunknown | nullsimplifies tounknown.In TypeScript,
nullis assignable tounknown, makingunknown | nullequivalent tounknown. Callers already narrow withif (parsed !== null)so the intent is clear, but the signature can be slightly more precise. This is a nitpick.♻️ Optional tightening
-export function tryParseJSON(text: string): unknown | null { +export function tryParseJSON(text: string): object | unknown[] | null {Or keep the
| nullas-is for documentation clarity — either is acceptable.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/ai/mcp-utils.ts` around lines 32 - 46, The return type of tryParseJSON is declared as "unknown | null" which is redundant because null is assignable to unknown; update the function signature "export function tryParseJSON(text: string): unknown | null" to "export function tryParseJSON(text: string): unknown" (keeping the implementation the same so it still returns null on parse failure) — this tightens the type while preserving behavior; the function to change is tryParseJSON.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/components/ai/AiChat.tsx`:
- Around line 347-354: The top-level kv-pair join in the AiChat result builder
uses a plain space which makes pairs run together; change the join separator
from " " to ", " so pairs render as "arg1: val, arg2: val". Also update the
nested serialize path to use ", " (comma plus space) instead of "," to keep
consistent spacing for nested lists/arrays; adjust nothing else except
preserving the truncation logic using maxLen and the ellipsis when result
exceeds maxLen. Ensure you modify the code that constructs result (the
Object.entries(...).map(...).join(...)) and the serialize(...) implementation so
both use ", " as the comma separator.
In `@src/components/ai/mcp-utils.ts`:
- Around line 1-9: The local TRUNCATION_MARKER constant in this file duplicates
the same literal used server-side and risks silent drift; extract the constant
into a shared client-safe module (e.g., create src/lib/ai-constants.ts exporting
TRUNCATION_MARKER) and update isToolOutputTruncated to import TRUNCATION_MARKER
from that shared module (also update app/api/chat/tools.ts to import the same
shared constant) so both client and server reference the single source of truth.
In `@src/components/ai/ToolOutput.tsx`:
- Around line 29-53: The code treats null as an object and ends up
JSON-stringifying null; update the rendering guard so the object branch only
runs when resolved is not null (e.g., check resolved !== null or resolved !=
null) before evaluating typeof resolved === "object" &&
!isValidElement(resolved); locate this logic around unwrapMCPEnvelope/output
handling and adjust the condition used to assign Output (in the block that
currently uses tryParseJSON, CodeBlock, and isValidElement) so null values fall
through to the intended empty/early-return behavior instead of rendering "null".
---
Duplicate comments:
In `@src/components/ai-elements/tool.tsx`:
- Around line 156-158: Revert any edits in the registry-sourced component
src/components/ai-elements/tool.tsx (e.g., restore the original header/behavior
around the {errorText ? "Error" : "Result"} line) and instead implement the
truncation-badge removal in the wrapper component
src/components/ai/ToolOutput.tsx so the wrapper never renders the registry's
ToolOutput with the badge; ensure the wrapper filters/omits the truncation badge
before passing props or rendering the registry ToolOutput component.
---
Nitpick comments:
In `@src/components/ai/AiChat.tsx`:
- Around line 331-356: Hoist the formatToolArgsSummary function out of the
AIChat component to module scope: cut the entire function (including its
serialize helper) and paste it at top-level in the same file so it is defined
once per module rather than on every render; keep the same signature (input:
unknown, maxLen = 90): string and behavior, ensure it still references no
component props/state, and update any internal references inside AIChat to use
the now top-level formatToolArgsSummary identifier (no other API changes are
required).
In `@src/components/ai/mcp-utils.ts`:
- Around line 32-46: The return type of tryParseJSON is declared as "unknown |
null" which is redundant because null is assignable to unknown; update the
function signature "export function tryParseJSON(text: string): unknown | null"
to "export function tryParseJSON(text: string): unknown" (keeping the
implementation the same so it still returns null on parse failure) — this
tightens the type while preserving behavior; the function to change is
tryParseJSON.
In `@src/components/ai/ToolOutput.tsx`:
- Around line 29-31: The MCP envelope's isError flag is being dropped by
unwrapMCPEnvelope, so ToolOutput.tsx (variables mcpText and resolved) can't tell
when an MCP tool failed; update unwrapMCPEnvelope to return both the extracted
text and the envelope's isError (e.g., an object { text, isError }) and change
callers in ToolOutput.tsx to use that result instead of just mcpText/resolved so
the component can style/label output as an Error when isError is true; ensure
isToolOutputTruncated continues to operate on the extracted text.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/components/ai-elements/tool.tsxsrc/components/ai/AiChat.tsxsrc/components/ai/ToolOutput.tsxsrc/components/ai/mcp-utils.ts
Closes #2880
Summary by CodeRabbit
New Features
Improvements
UI Changes