fix: image gen log content + shared LogCard - #1974
Conversation
Google provider image generation responses that contain only images (no text) left content as null, causing the UI to show "No response content available." Now sets content to "Image generated"/"Image edited" label like other providers (xAI, alibaba, bytedance, zai). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract the activity log card component into @llmgateway/shared so both apps/ui and ee/admin use a single implementation. Variant-specific behavior (links, copy buttons, wording) is controlled via props. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
✅ Files skipped from review due to trivial changes (1)
WalkthroughConsolidates LogCard UI into a new shared component and updates gateway provider parsing: Google-family image-generation responses now set Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 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 |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
packages/shared/src/components/log-card.tsx (2)
261-261: Replaceanywithunknownin cast.Proposed fix
- const params = log.params as Record<string, any> | undefined; + const params = log.params as Record<string, unknown> | undefined;As per coding guidelines: "Never use
anyoras anyin TypeScript unless absolutely necessary".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/shared/src/components/log-card.tsx` at line 261, The cast "const params = log.params as Record<string, any> | undefined" uses `any`; change it to `unknown` by casting to `Record<string, unknown> | undefined` (i.e., update the declaration for `params`), and then update any downstream uses of `params` in this component (e.g., property access, mapping, or JSON stringify) to use proper type narrowing or explicit conversions (type guards, checks, or localized casts) so you don't reintroduce `any` while keeping runtime behavior unchanged.
198-198: Avoidanyin favor ofunknown.Per coding guidelines,
anyshould not be used. TherenderParamsfunction already handles unknown value types viatypeofchecks.Proposed fix
-function renderParams(obj: Record<string, any>, depth = 0): React.ReactNode { +function renderParams(obj: Record<string, unknown>, depth = 0): React.ReactNode {As per coding guidelines: "Never use
anyoras anyin TypeScript unless absolutely necessary".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/shared/src/components/log-card.tsx` at line 198, The parameter type of renderParams uses Record<string, any>; change it to Record<string, unknown> and then update local usages inside renderParams to properly narrow values via typeof checks (e.g., assign const val = obj[key] and treat val as unknown before branching), replacing any other local "any" declarations with unknown and refining checks for object/array/string/number/boolean/null to satisfy the compiler; ensure function signature and all internal type assumptions (in renderParams) are adjusted so no "any" remains.ee/admin/src/components/log-card.tsx (1)
12-14: Use type-level assertion to validate shape compatibility instead of double cast.The
log as unknown as LogCardDatapattern bypasses TypeScript's structural type checking. WhileProjectLogEntryfrom the OpenAPI schema has all required fields (id,createdAt) and compatible types, a type assertion likesatisfies LogCardDatawould validate the shape at compile time and make the intent clearer:const logData = log satisfies LogCardData; return <SharedLogCard log={logData} showCopyButtons showLogId />;Alternatively, create a type helper to explicitly narrow the types or document why the cast is necessary.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ee/admin/src/components/log-card.tsx` around lines 12 - 14, Replace the unsafe double-cast of log in the SharedLogCard props with a type-level shape validation using TypeScript's satisfies operator (or a dedicated type-narrowing helper): ensure the value passed to SharedLogCard's log prop is declared as satisfying LogCardData (or explicitly convert ProjectLogEntry -> LogCardData via a small mapper/validator) so the compiler checks structural compatibility; update the usage around SharedLogCard (the log prop) to use that validated variable and keep showCopyButtons and showLogId props as before.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/gateway/src/chat/tools/parse-provider-response.ts`:
- Around line 264-267: The current code sets content = imageLabel when no text
is present, which causes the downstream token estimation (using
candidatesTokenCount fallback) to count the synthetic label; instead, preserve
content for display but ensure token estimation uses the real extracted text
(textContent) or empty string, not content. Change the logic around the block
that assigns imageLabel to content (variables: content, images, imageLabel) so
you only set a displayValue or responseLabel for UI/logs while leaving content
unchanged, and update the token estimation path that references
candidatesTokenCount to fall back to textContent (or "") when
candidatesTokenCount is missing (symbols to update: content assignment,
textContent, candidatesTokenCount, and the token estimation call/site around
line ~393).
---
Nitpick comments:
In `@ee/admin/src/components/log-card.tsx`:
- Around line 12-14: Replace the unsafe double-cast of log in the SharedLogCard
props with a type-level shape validation using TypeScript's satisfies operator
(or a dedicated type-narrowing helper): ensure the value passed to
SharedLogCard's log prop is declared as satisfying LogCardData (or explicitly
convert ProjectLogEntry -> LogCardData via a small mapper/validator) so the
compiler checks structural compatibility; update the usage around SharedLogCard
(the log prop) to use that validated variable and keep showCopyButtons and
showLogId props as before.
In `@packages/shared/src/components/log-card.tsx`:
- Line 261: The cast "const params = log.params as Record<string, any> |
undefined" uses `any`; change it to `unknown` by casting to `Record<string,
unknown> | undefined` (i.e., update the declaration for `params`), and then
update any downstream uses of `params` in this component (e.g., property access,
mapping, or JSON stringify) to use proper type narrowing or explicit conversions
(type guards, checks, or localized casts) so you don't reintroduce `any` while
keeping runtime behavior unchanged.
- Line 198: The parameter type of renderParams uses Record<string, any>; change
it to Record<string, unknown> and then update local usages inside renderParams
to properly narrow values via typeof checks (e.g., assign const val = obj[key]
and treat val as unknown before branching), replacing any other local "any"
declarations with unknown and refining checks for
object/array/string/number/boolean/null to satisfy the compiler; ensure function
signature and all internal type assumptions (in renderParams) are adjusted so no
"any" remains.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 8d868af1-d651-4ae0-8907-1e64c2c56f00
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (6)
apps/gateway/src/chat/tools/parse-provider-response.tsapps/ui/src/components/dashboard/log-card.tsxee/admin/src/components/log-card.tsxpackages/shared/package.jsonpackages/shared/src/components/index.tsxpackages/shared/src/components/log-card.tsx
When Google candidatesTokenCount is missing and content is the synthetic "Image generated" label, the fallback was estimating ~2-3 tokens from the label string. Now skips estimation when images are present (images.length > 0) and sets rawCandidates to 0 instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
contentasnullin logs, causing "No response content available." in the UI. Now setscontentto "Image generated"/"Image edited" label — matching xAI, alibaba, bytedance, and zai providers.@llmgateway/shared/componentsso bothapps/uiandee/adminuse a single implementation. Variant-specific behavior (Next.js links, copy buttons, wording) is controlled via props.Test plan
apps/ui(with detail links, "your balance" wording)ee/admin(with copy buttons, log ID row, neutral wording)🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
New Features