feat(nodes): add v0 by Vercel tool node for UI generation#557
feat(nodes): add v0 by Vercel tool node for UI generation#557charliegillet wants to merge 6 commits intorocketride-org:developfrom
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds a new tool_v0 node: package init and requirements, a global state class holding a secure apikey with lifecycle methods, an instance exposing generate_ui and refine_ui that normalize input and call Vercel v0 chat API, and a services.json manifest registering the node and apikey config. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant Framework
participant IInstance
participant IGlobal
participant v0_API as "v0 API"
User->>Framework: invoke tool (generate_ui / refine_ui with args)
Framework->>IInstance: call tool method
IInstance->>IGlobal: read apikey
IGlobal-->>IInstance: return apikey
IInstance->>IInstance: normalize input & build messages
IInstance->>v0_API: POST /chat (Bearer apikey, JSON payload)
v0_API-->>IInstance: response (id, choices[0].message.content)
IInstance->>IInstance: extract code and message_id
alt extraction succeeds
IInstance-->>Framework: {success: true, code, message_id}
else extraction fails
IInstance-->>Framework: {success: false, error}
end
Framework-->>User: return result
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
Poem
🚥 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 |
asclearuc
left a comment
There was a problem hiding this comment.
Thanks @charliegillet for the clean implementation — the driver faithfully mirrors tool_firecrawl in structure and the IGlobal/IInstance wiring is correct.
See the inline comments for details.
- Format services.json with inline comments matching repo conventions - Return success:false when _extract_code yields empty code instead of success:true with empty string - Include prior_messages in refine_ui for stateless API fallback while keeping parent_message_id for stateful servers Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@nodes/src/nodes/tool_v0/IGlobal.py`:
- Line 52: Remove the extraneous parentheses around the cfg.get expression when
building the apikey string: change the apikey assignment to use
str(cfg.get('apikey') or '').strip() (i.e., drop the surrounding parentheses
around cfg.get('apikey') or ''), and apply the same fix to the other similar
apikey assignment further down in the file where cfg.get is used.
In `@nodes/src/nodes/tool_v0/v0_driver.py`:
- Around line 166-189: The _call_v0_api method currently assumes resp.json()
will succeed, so a malformed/non-JSON body will raise and bypass your warning
handling; wrap the response parsing (resp.json()) in its own try/except, catch
JSON decode errors (or ValueError/Exception), log a warning including
resp.status_code and resp.text, and re-raise a meaningful exception; update
_call_v0_api to parse safely and fall back to returning or raising with the raw
body when JSON parsing fails, referencing resp, resp.json(),
V0_GENERATE_ENDPOINT and the _build_headers() call to locate the code to change.
🪄 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: ASSERTIVE
Plan: Pro
Run ID: 22071bd7-9707-4076-a33e-c3325b828be3
📒 Files selected for processing (6)
nodes/src/nodes/tool_v0/IGlobal.pynodes/src/nodes/tool_v0/IInstance.pynodes/src/nodes/tool_v0/__init__.pynodes/src/nodes/tool_v0/requirements.txtnodes/src/nodes/tool_v0/services.jsonnodes/src/nodes/tool_v0/v0_driver.py
|
Addressed all review feedback:
Thanks for the thorough review! |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@nodes/src/nodes/tool_v0/services.json`:
- Around line 19-23: The tile metadata only lists "Tool: v0.generate_ui" but the
node exposes both generate_ui and refine_ui; update the "tile" entry in
services.json to reflect both tools (e.g., "Tool: v0.generate_ui / v0.refine_ui"
or a generic "Tool: v0 UI Generation") so the UI accurately represents available
operations; locate the "tile" array in the services.json entry for this node and
replace the existing single-tool string with the combined or generic label.
🪄 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: ASSERTIVE
Plan: Pro
Run ID: e8ca17c9-0dba-4ab3-b456-d0ca79d3687b
📒 Files selected for processing (1)
nodes/src/nodes/tool_v0/services.json
|
Thanks @charliegillet — the feature itself is exactly the right kind of addition and the v0 API integration logic is sound. However, since this was authored, PR #599 landed and replaced the tool node architecture that this PR was built on. The This PR needs to be rebuilt against the new pattern before it can merge. |
Adds a new tool_v0 pipeline node that integrates with Vercel's v0 API to generate React + Tailwind CSS components from natural-language prompts. Exposes generate_ui and refine_ui as agent-invocable tools. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Format services.json with inline comments matching repo conventions - Return success:false when _extract_code yields empty code instead of success:true with empty string - Include prior_messages in refine_ui for stateless API fallback while keeping parent_message_id for stateful servers Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ketride-org#599 Remove V0Driver(ToolsBase) and move generate_ui/refine_ui tool logic to @tool_function decorated methods on IInstance. Store apikey directly on IGlobal instead of through a driver object. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
cb5be5e to
65a5a4b
Compare
|
Rebased on develop and migrated to the @tool_function decorator pattern from PR #599. Removed the V0Driver(ToolsBase) approach and moved all tool logic to @tool_function methods on IInstance, following tool_firecrawl as reference. Ready for re-review. Thanks for the guidance! Addressing @asclearuc's inline feedback:
|
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
nodes/src/nodes/tool_v0/services.json (1)
23-23:⚠️ Potential issue | 🟡 MinorTile label is incomplete for the exposed toolset.
Line 23 advertises only
v0.generate_ui, but this node also exposesv0.refine_ui. Please update the tile text to reflect both (or use a generic label).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@nodes/src/nodes/tool_v0/services.json` at line 23, The tile label currently lists only "Tool: v0.generate_ui" but the node also exposes v0.refine_ui; update the "tile" array in services.json to include both exposed tools (e.g., "Tool: v0.generate_ui, v0.refine_ui" or a generic label like "Tool: v0 UI tools") so the tile accurately reflects the node's capabilities—modify the value for the "tile" key where it contains "Tool: v0.generate_ui".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@nodes/src/nodes/tool_v0/IInstance.py`:
- Around line 213-218: The except block that catches httpx.HTTPStatusError
currently logs e.response.text which may expose sensitive upstream content;
change the logging in that handler (the httpx.HTTPStatusError except where
warning(...) is called) to avoid printing the full response body—log only the
status code and either a fixed "response body redacted" message or a safely
truncated/redacted snippet (e.g., first 200 chars plus "... [TRUNCATED]") and/or
use a small helper like redact_response(response) to centralize redaction,
leaving the generic Exception handler unchanged.
- Around line 72-79: The output_schema dictionaries (the output_schema defined
in IInstance with properties 'success', 'code', 'message_id') are missing the
'error' field that the tools actually return on failures; update each
output_schema to include an 'error' property (e.g., 'error': {'type':
['object','null'], 'description': 'Error payload returned on failure',
'additionalProperties': True}) so schema-driven callers see the real contract
and allow null when no error is present; apply the same change to the other
output_schema occurrences noted in the review.
---
Duplicate comments:
In `@nodes/src/nodes/tool_v0/services.json`:
- Line 23: The tile label currently lists only "Tool: v0.generate_ui" but the
node also exposes v0.refine_ui; update the "tile" array in services.json to
include both exposed tools (e.g., "Tool: v0.generate_ui, v0.refine_ui" or a
generic label like "Tool: v0 UI tools") so the tile accurately reflects the
node's capabilities—modify the value for the "tile" key where it contains "Tool:
v0.generate_ui".
🪄 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: ASSERTIVE
Plan: Pro
Run ID: 86a541b2-7967-4dbc-a9df-9b6cc40abf51
📒 Files selected for processing (5)
nodes/src/nodes/tool_v0/IGlobal.pynodes/src/nodes/tool_v0/IInstance.pynodes/src/nodes/tool_v0/__init__.pynodes/src/nodes/tool_v0/requirements.txtnodes/src/nodes/tool_v0/services.json
| output_schema={ | ||
| 'type': 'object', | ||
| 'properties': { | ||
| 'success': {'type': 'boolean'}, | ||
| 'code': {'type': 'string', 'description': 'Generated React component code.'}, | ||
| 'message_id': {'type': 'string', 'description': 'v0 message ID for follow-up refinements.'}, | ||
| }, | ||
| }, |
There was a problem hiding this comment.
Keep output schemas aligned with actual error payloads.
Both tools return an error field on failure, but neither output schema declares it. This creates a contract mismatch for schema-driven callers.
♻️ Proposed fix
output_schema={
'type': 'object',
'properties': {
'success': {'type': 'boolean'},
'code': {'type': 'string', 'description': 'Generated React component code.'},
'message_id': {'type': 'string', 'description': 'v0 message ID for follow-up refinements.'},
+ 'error': {'type': 'string', 'description': 'Error message when generation fails.'},
},
},
@@
output_schema={
'type': 'object',
'properties': {
'success': {'type': 'boolean'},
'code': {'type': 'string', 'description': 'Refined React component code.'},
'message_id': {'type': 'string', 'description': 'Updated message ID for further refinements.'},
+ 'error': {'type': 'string', 'description': 'Error message when refinement fails.'},
},
},Also applies to: 99-103, 142-149, 179-182
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@nodes/src/nodes/tool_v0/IInstance.py` around lines 72 - 79, The output_schema
dictionaries (the output_schema defined in IInstance with properties 'success',
'code', 'message_id') are missing the 'error' field that the tools actually
return on failures; update each output_schema to include an 'error' property
(e.g., 'error': {'type': ['object','null'], 'description': 'Error payload
returned on failure', 'additionalProperties': True}) so schema-driven callers
see the real contract and allow null when no error is present; apply the same
change to the other output_schema occurrences noted in the review.
There was a problem hiding this comment.
Fixed — added 'error': {'type': 'string', 'description': 'Error message on failure.'} to both generate_ui and refine_ui output schemas.
There was a problem hiding this comment.
Rate Limit Exceeded
@charliegillet have exceeded the limit for the number of chat messages per hour. Please wait 1 minutes and 41 seconds before sending another message.
Senior Review — PR #557: feat(nodes): add v0 by Vercel tool node@charliegillet, good integration approach here. The remaining items are mostly cosmetic/polish and should be straightforward to knock out: Remaining items
None of these are architectural — just consistency and robustness. Should be a quick iteration to get this ready. |
🚀 Merge RequestGood Vercel v0 integration. Before merge (minor polish):
These are straightforward fixes. |
- Remove extraneous parentheses around cfg.get() in IGlobal.py - Add defensive JSON error handling for non-JSON API responses - Update tile label to generic "Tool: v0 UI Generation" - Add 'error' field to both tool output schemas - Remove raw response body from HTTP error logging Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
No description provided. |
|
@asclearuc Thanks for the thorough review! All three items you flagged were already addressed in previous commits:
I've also addressed all CodeRabbit feedback in the latest commit:
|
Latest fixes
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@nodes/src/nodes/tool_v0/IInstance.py`:
- Around line 97-104: Wrap calls to _call_v0_api and _extract_code in a
try/except and return the uniform failure shape on any exception: when invoking
_call_v0_api(...) and then _extract_code(...), catch all exceptions and return
{'success': False, 'error': <stringified error>} instead of letting them raise;
apply the same pattern to the second occurrence of this logic (the other block
that currently uses the same code path) so both transport/parse failure modes
return schema-shaped failures for downstream branching.
- Around line 259-261: The warning in IInstance.py currently logs the raw
malformed input via input_obj!r which can leak sensitive user data; update the
check around input_obj in the function containing this code to redact or replace
the payload before logging (e.g., call a small sanitizer like
sanitize_for_logging(input_obj) or log only a safe summary such as the type and
a fixed placeholder/truncated hash), and ensure the warning call uses that
redacted value instead of input_obj!r; reference the existing variables and call
site (input_obj and the warning(...) invocation) when making the change.
🪄 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: ASSERTIVE
Plan: Pro
Run ID: 58ad669e-c152-4692-bdb5-ada8b34104d9
📒 Files selected for processing (3)
nodes/src/nodes/tool_v0/IGlobal.pynodes/src/nodes/tool_v0/IInstance.pynodes/src/nodes/tool_v0/services.json
| response = self._call_v0_api(messages, model) | ||
| code, message_id = _extract_code(response) | ||
|
|
||
| if not code: | ||
| return { | ||
| 'success': False, | ||
| 'error': 'No code generated', | ||
| } |
There was a problem hiding this comment.
Return schema-shaped failures for all tool errors.
The new error output is only used when code is empty. If _call_v0_api() or _extract_code() fails before that branch, both tools still raise instead of returning {'success': False, 'error': ...}, so downstream nodes cannot branch on the main transport/parse failure modes.
Also applies to: 177-184
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@nodes/src/nodes/tool_v0/IInstance.py` around lines 97 - 104, Wrap calls to
_call_v0_api and _extract_code in a try/except and return the uniform failure
shape on any exception: when invoking _call_v0_api(...) and then
_extract_code(...), catch all exceptions and return {'success': False, 'error':
<stringified error>} instead of letting them raise; apply the same pattern to
the second occurrence of this logic (the other block that currently uses the
same code path) so both transport/parse failure modes return schema-shaped
failures for downstream branching.
| if not isinstance(input_obj, dict): | ||
| warning(f'v0: unexpected input type {type(input_obj).__name__}: {input_obj!r}') | ||
| return {} |
There was a problem hiding this comment.
Redact malformed tool input before logging.
Line 260 logs input_obj!r verbatim. For this node that can include prompts, prior messages, or generated code, so a bad invocation path still leaks user content into server logs.
🔒 Proposed fix
- warning(f'v0: unexpected input type {type(input_obj).__name__}: {input_obj!r}')
+ warning(f'v0: unexpected input type {type(input_obj).__name__} (content redacted)')🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@nodes/src/nodes/tool_v0/IInstance.py` around lines 259 - 261, The warning in
IInstance.py currently logs the raw malformed input via input_obj!r which can
leak sensitive user data; update the check around input_obj in the function
containing this code to redact or replace the payload before logging (e.g., call
a small sanitizer like sanitize_for_logging(input_obj) or log only a safe
summary such as the type and a fixed placeholder/truncated hash), and ensure the
warning call uses that redacted value instead of input_obj!r; reference the
existing variables and call site (input_obj and the warning(...) invocation)
when making the change.
Summary
tool_v0pipeline node that integrates with Vercel's v0 generative UI APIgenerate_ui(create React components from text prompts) andrefine_ui(iterate on prior generations)Type
Feature
Why this feature fits this codebase
RocketRide's node system already provides agents with tools for web scraping (Firecrawl), HTTP requests, and code execution (Python). Adding v0 UI generation fills a natural gap: agents can now generate frontend components on demand, enabling end-to-end workflows where an agent reasons about a UI requirement, generates production-ready React + Tailwind code via v0, and delivers it downstream through the pipeline. The node plugs directly into the existing ToolsBase interface, so any agent node (CrewAI, LangChain, RocketRide agent) can invoke it without additional wiring.
What changed
nodes/src/nodes/tool_v0/services.jsonnodes/src/nodes/tool_v0/__init__.pydepends()for requirements and public exportsnodes/src/nodes/tool_v0/IGlobal.pynodes/src/nodes/tool_v0/IInstance.pyinvoke()to the drivernodes/src/nodes/tool_v0/v0_driver.py_tool_query,_tool_validate,_tool_invokefor generate_ui and refine_ui tools via v0 chat APInodes/src/nodes/tool_v0/requirements.txthttpxValidation
ruff format --checkandruff checkHow this could be extended
stream: True) for real-time code generation feedbacklist_generationstool to browse previously generated componentsCloses #539
#Hack-with-bay-2
Summary by CodeRabbit
New Features
Configuration
Chores