fix: default caption length to none#433
Conversation
…ly requested Captions were always generated with a default of "short", even when not requested or explicitly asked for "no captions". Now defaults to "none" across the full pipeline: API validation, Slack bot prompt parsing, and Trigger.dev task schema. When "none", caption generation is skipped entirely and the video renders without text overlay. Co-Authored-By: Paperclip <noreply@paperclip.ing>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 40 minutes and 59 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (3)
📝 WalkthroughWalkthroughA coordinated update across five files introduces Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ❌ 1❌ Failed checks (1 warning)
✏️ 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 |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
lib/content/validateCreateContentBody.ts (1)
94-94: Redundant nullish coalescing—Zod's.default("none")already handles this.Since the schema on line 19 has
.optional().default("none"),result.data.caption_lengthwill always be defined after parsing. The?? "none"fallback is unreachable and adds noise.♻️ Suggested fix
- captionLength: result.data.caption_length ?? "none", + captionLength: result.data.caption_length,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/content/validateCreateContentBody.ts` at line 94, In validateCreateContentBody, remove the redundant nullish coalescing on captionLength: the schema's .default("none") ensures result.data.caption_length is always defined, so replace the expression using result.data.caption_length ?? "none" with just result.data.caption_length (refer to the mapping that sets captionLength and the parsed result variable `result.data.caption_length` in the validateCreateContentBody logic).lib/trigger/triggerCreateContent.ts (1)
9-10: Consider usingCaptionLengthtype for consistency across the codebase.Similar to the suggestion for
validateCreateContentBody.ts, the hardcoded union could be replaced with theCaptionLengthtype. However, for cross-boundary contracts like Trigger.dev payloads, explicit typing can aid readability—so this is purely optional.♻️ Optional refactor
+import { CaptionLength } from "@/lib/content/captionLengths"; + export interface TriggerCreateContentPayload { accountId: string; artistSlug: string; template?: string; lipsync: boolean; - /** Controls caption length: "none" skips captions, "short", "medium", or "long". */ - captionLength: "none" | "short" | "medium" | "long"; + /** Controls caption length: "none" skips captions, "short", "medium", or "long". */ + captionLength: CaptionLength; /** Whether to upscale image and video for higher quality. */ upscale: boolean;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/trigger/triggerCreateContent.ts` around lines 9 - 10, Replace the hardcoded union type on the captionLength property with the shared CaptionLength type to ensure consistency: import CaptionLength into the module (if not already) and change the property declaration from captionLength: "none" | "short" | "medium" | "long"; to use captionLength: CaptionLength; and run type checks to confirm no other files rely on the explicit union; keep the property name captionLength to locate it easily.lib/content/caption/validateCreateCaptionBody.ts (1)
22-24: Minor: JSDoc@paramannotation could include type/description.The
@param requestannotation is sparse. Consider adding a brief description or removing it entirely if the type signature is self-documenting./** * Validates auth and request body for POST /api/content/caption. - * - * `@param` request */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/content/caption/validateCreateCaptionBody.ts` around lines 22 - 24, Update the JSDoc for the validateCreateCaptionBody function to either remove the bare "@param request" line or expand it with a short type/description (e.g., "@param request CreateCaptionRequest - payload for creating a caption, including fields X, Y") so the parameter is self-documenting; adjust the comment block above validateCreateCaptionBody to consistently describe the expected shape/fields of the request parameter.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@lib/content/caption/validateCreateCaptionBody.ts`:
- Line 13: The handler createTextHandler should skip caption generation when the
validated input length is "none"; add a guard at the start of createTextHandler
that checks if validated.length === "none" and immediately returns the same JSON
response shape currently expected (e.g., content: "", font: null, color:
"white", borderColor: "black", maxFontSize: 42) via NextResponse.json with
getCorsHeaders(), instead of calling composeCaptionPrompt and generateText; this
avoids invoking composeCaptionPrompt and generateText when length === "none".
In `@lib/content/validateCreateContentBody.ts`:
- Line 32: Replace the hardcoded union type for the captionLength property with
the existing exported type from captionLengths.ts: import and use CaptionLength
(or the exact exported symbol) in the validateCreateContentBody type definition
so the property reads captionLength: CaptionLength instead of "none" | "short" |
"medium" | "long"; update any related imports/exports so the
validateCreateContentBody module references the centralized CaptionLength type
to keep types DRY.
---
Nitpick comments:
In `@lib/content/caption/validateCreateCaptionBody.ts`:
- Around line 22-24: Update the JSDoc for the validateCreateCaptionBody function
to either remove the bare "@param request" line or expand it with a short
type/description (e.g., "@param request CreateCaptionRequest - payload for
creating a caption, including fields X, Y") so the parameter is
self-documenting; adjust the comment block above validateCreateCaptionBody to
consistently describe the expected shape/fields of the request parameter.
In `@lib/content/validateCreateContentBody.ts`:
- Line 94: In validateCreateContentBody, remove the redundant nullish coalescing
on captionLength: the schema's .default("none") ensures
result.data.caption_length is always defined, so replace the expression using
result.data.caption_length ?? "none" with just result.data.caption_length (refer
to the mapping that sets captionLength and the parsed result variable
`result.data.caption_length` in the validateCreateContentBody logic).
In `@lib/trigger/triggerCreateContent.ts`:
- Around line 9-10: Replace the hardcoded union type on the captionLength
property with the shared CaptionLength type to ensure consistency: import
CaptionLength into the module (if not already) and change the property
declaration from captionLength: "none" | "short" | "medium" | "long"; to use
captionLength: CaptionLength; and run type checks to confirm no other files rely
on the explicit union; keep the property name captionLength to locate it easily.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 8d03a9e2-8235-4894-8cd5-27c49594c16b
⛔ Files ignored due to path filters (4)
lib/agents/content/__tests__/parseContentPrompt.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/content/__tests__/captionLengths.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/content/__tests__/schemas.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**lib/content/__tests__/validateCreateContentBody.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**
📒 Files selected for processing (5)
lib/agents/content/createContentPromptAgent.tslib/content/caption/validateCreateCaptionBody.tslib/content/captionLengths.tslib/content/validateCreateContentBody.tslib/trigger/triggerCreateContent.ts
| template: z.enum(TEMPLATE_IDS).optional(), | ||
| topic: z.string().min(1), | ||
| length: z.enum(CAPTION_LENGTHS).optional().default("short"), | ||
| length: z.enum(CAPTION_LENGTHS).optional().default("none"), |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Check if createTextHandler has any guards for length === "none"
ast-grep --pattern $'async function createTextHandler($_) {
$$$
}'
# Also check for any conditional logic around length/captionLength
rg -n --type=ts -C3 'length.*none|none.*length' lib/content/caption/Repository: recoupable/api
Length of output: 682
🏁 Script executed:
# Find where createTextHandler is defined
rg -n "createTextHandler" --type=ts --type=tsx
# Also search for composeCaptionPrompt to understand the flow
rg -n "composeCaptionPrompt" --type=ts --type=tsxRepository: recoupable/api
Length of output: 113
🏁 Script executed:
# Search for createTextHandler and composeCaptionPrompt without type flags
rg "createTextHandler" -n -A 5 -B 1 lib/
# Search for composeCaptionPrompt
rg "composeCaptionPrompt" -n -A 3 -B 1 lib/Repository: recoupable/api
Length of output: 2018
🏁 Script executed:
# Get the full createTextHandler.ts file
cat lib/content/caption/createTextHandler.ts
# Find CAPTION_LENGTHS definition
rg "CAPTION_LENGTHS" -n -B 2 -A 5 lib/Repository: recoupable/api
Length of output: 6878
Add a guard in createTextHandler to skip caption generation when length === "none".
Based on the codebase, "none" is explicitly defined as "no captions" (see createContentPromptAgent.ts line 27). However, createTextHandler.ts (lines 22–23) unconditionally calls composeCaptionPrompt and generateText, passing "Length: none" to the LLM.
With the new default of "none", most requests will now incur an unnecessary LLM call. Consider adding a check around line 21:
if (validated.length === "none") {
return NextResponse.json(
{ content: "", font: null, color: "white", borderColor: "black", maxFontSize: 42 },
{ status: 200, headers: getCorsHeaders() },
);
}
This prevents wasting tokens and aligns the behavior with the semantic intent of the "none" option.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lib/content/caption/validateCreateCaptionBody.ts` at line 13, The handler
createTextHandler should skip caption generation when the validated input length
is "none"; add a guard at the start of createTextHandler that checks if
validated.length === "none" and immediately returns the same JSON response shape
currently expected (e.g., content: "", font: null, color: "white", borderColor:
"black", maxFontSize: 42) via NextResponse.json with getCorsHeaders(), instead
of calling composeCaptionPrompt and generateText; this avoids invoking
composeCaptionPrompt and generateText when length === "none".
| .enum(CAPTION_LENGTHS) | ||
| .describe( | ||
| "Caption length: 'short' (default), 'medium', or 'long'. Extract from phrases like 'long caption', 'detailed text', 'brief caption'.", | ||
| "Caption length: 'none' (default — no captions), 'short', 'medium', or 'long'. Only set to short/medium/long when the user explicitly requests captions. Extract from phrases like 'add a caption', 'with captions', 'long caption', 'detailed text'. If no captions are mentioned or the user says 'no captions', use 'none'.", |
There was a problem hiding this comment.
| "Caption length: 'none' (default — no captions), 'short', 'medium', or 'long'. Only set to short/medium/long when the user explicitly requests captions. Extract from phrases like 'add a caption', 'with captions', 'long caption', 'detailed text'. If no captions are mentioned or the user says 'no captions', use 'none'.", | |
| "Caption length: 'none' (default — no captions), 'short', 'medium', or 'long'. Only set to short/medium/long when captions are explicitly requested. Extract from phrases like 'add a caption', 'with captions', 'long caption', 'detailed text'. If no captions are mentioned or 'no captions', use 'none'.", |
Reflects API change in recoupable/api#433 — caption length now defaults to "none" (skip caption generation) instead of "short". Adds "none" to the enum for both POST /api/content/create (caption_length) and the caption endpoint (length). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
1 issue found across 9 files
Confidence score: 3/5
- There is a concrete regression risk:
lib/content/caption/validateCreateCaptionBody.tsnow defaultslengthto"none", but downstream handling does not appear to support that value. - In
createTextHandler.ts, the flow still unconditionally callscomposeCaptionPromptandgenerateText, so requests can send"Length: none"to the LLM and produce user-facing caption quality/behavior issues. - Given the high-severity/high-confidence mismatch between validation defaults and generation logic, this is moderate merge risk rather than a hard block if a follow-up fix is immediate.
- Pay close attention to
lib/content/caption/validateCreateCaptionBody.tsandcreateTextHandler.ts- default/value contract mismatch forlengthcan leak unsupported prompt input.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="lib/content/caption/validateCreateCaptionBody.ts">
<violation number="1" location="lib/content/caption/validateCreateCaptionBody.ts:13">
P1: The default `length` is now `"none"`, but `createTextHandler.ts` has no guard for this value — it unconditionally calls `composeCaptionPrompt` and `generateText`, passing `"Length: none"` to the LLM. This means most caption requests will still incur an LLM call and may return non-empty caption text even though the intent is "no captions". Add an early return in `createTextHandler` when `length === "none"` to skip the LLM call entirely.</violation>
</file>
Architecture diagram
sequenceDiagram
participant User as User (Slack/API)
participant Agent as Prompt Parsing Agent
participant Validator as Request Validator
participant Trigger as Trigger.dev (Worker)
participant Gen as Content Generator
Note over User,Gen: Content Creation Flow (Updated Defaults)
alt Interaction via Slack
User->>Agent: "Create a video about coffee"
Agent->>Agent: Parse natural language
Note right of Agent: NEW: If no caption specified,<br/>defaults to "none"
Agent-->>User: Confirming (captionLength: "none")
else Interaction via API
User->>Validator: POST /api/content/create {}
Validator->>Validator: Apply Zod Schema
Note right of Validator: CHANGED: Omitted field<br/>now defaults to "none"
end
Validator->>Trigger: triggerCreateContent(payload)
Note over Validator,Trigger: payload.captionLength = "none"
Trigger->>Gen: Execute Task
alt captionLength is "none"
Gen->>Gen: NEW: Skip caption generation
Gen->>Gen: Process Video + Audio only
else captionLength is "short" | "medium" | "long"
Gen->>Gen: Generate Script
Gen->>Gen: Generate Captions
Gen->>Gen: Overlay Captions on Video
end
Gen-->>User: Content Ready (No captions by default)
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.
* docs: add "none" to caption length enum and update default Reflects API change in recoupable/api#433 — caption length now defaults to "none" (skip caption generation) instead of "short". Adds "none" to the enum for both POST /api/content/create (caption_length) and the caption endpoint (length). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs: revert "none" from /content/caption length enum The /content/caption endpoint should only be called when captions are wanted — the orchestrator decides whether to invoke it. Keep "none" only on /content/create (caption_length). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove "none" from /content/caption length enum; default to "short". The caption endpoint is only invoked when a caption is wanted — "none" is a create-time opt-out, not a generation mode. Adds a local GENERATED_CAPTION_LENGTHS narrower than CAPTION_LENGTHS. (cubic P1 + coderabbit Major) - Use CaptionLength type on ValidatedCreateContentBody instead of hardcoded union (coderabbit DRY nit). - Drop redundant `?? "none"` fallback — Zod default already applies (coderabbit nit). - Refine captionLength prompt description per reviewer suggestion. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
1 issue found across 4 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="lib/content/caption/validateCreateCaptionBody.ts">
<violation number="1" location="lib/content/caption/validateCreateCaptionBody.ts:19">
P1: Custom agent: **Flag AI Slop and Fabricated Changes**
The PR description claims that `createCaptionBody` was updated to accept `"none"` and default to `"none"`. However, this line does the exact opposite: it rejects `"none"` (via `GENERATED_CAPTION_LENGTHS`) and changes the default from `"none"` to `"short"`.
Please update the PR description to accurately reflect that the caption generation endpoint intentionally rejects `"none"`, or update this code if the PR description's stated goal is correct.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.
Summary
"none"toCAPTION_LENGTHSenum across API and changes default from"short"to"none"createContentBody,createCaptionBody) and trigger payload typesTest plan
POST /api/content/createwithoutcaption_lengthdefaults to"none"🤖 Generated with Claude Code
Summary by cubic
Default caption length is now "none" so videos render without captions unless requested. The caption endpoint only runs when captions are requested and defaults to "short" there.
Bug Fixes
CAPTION_LENGTHS;createContentBodydefaults tonone;TriggerCreateContentPayloadaccepts"none"./content/captionnow uses localGENERATED_CAPTION_LENGTHS(short|medium|long) with default"short"and rejects"none".noneand only sets captions when requested; refined prompt description, appliedCaptionLengthtype, and removed redundant fallback; tests updated.Migration
caption_lengthyields no captions. Send"short" | "medium" | "long"to opt in.Written for commit 771d8ed. Summary will update on new commits.
Summary by CodeRabbit