fix: update project structure and rename dashboard to chat#58
Conversation
|
Warning Rate limit exceeded
⌛ 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. 📝 WalkthroughWalkthroughThe PR replaces the "dashboard" web app with a new "chat" app: renames scripts and ports, consolidates Biome config to the monorepo root, removes the old dashboard implementation, and adds a full Vue 3 chat UI with components, styles, tests, and gateway configuration handling. Changes
Sequence DiagramsequenceDiagram
actor User
participant Browser as Client / Browser
participant App as Chat App
participant Backend as Gateway API
User->>Browser: Fill baseUrl & secrets
User->>Browser: Click "Save Configuration"
Browser->>App: saveGatewayConfig()
App->>App: Build payload (baseUrl + secrets)
App->>App: Create AbortController (timeout)
App->>Backend: POST /web/chat/config (payload, signal)
activate Backend
Backend-->>App: Response (success / error)
deactivate Backend
alt success
App->>App: clear secrets, increment nonce, show success
App->>Browser: display success
else abort (timeout)
App->>Browser: display timeout error
else error
App->>App: log error
App->>Browser: display save error
end
App->>App: reset to idle
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 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 |
✅ Contributor ReportUser: @yacosta738
Contributor Report evaluates based on public GitHub activity. Analysis period: 2025-02-20 to 2026-02-20 |
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
clients/web/build.gradle.kts (1)
18-26:⚠️ Potential issue | 🟠 MajorReplace the overly broad
catch (e: Exception)— Detekt pipeline failure.
Files.createSymbolicLinkthrowsIOException(andSecurityException/UnsupportedOperationExceptionfor non-I/O failures). Catching the rootExceptionswallows programming errors silently.🛠️ Proposed fix
- } catch (e: Exception) { - logger.warn("⚠️ No se pudo crear symlink de docs: ${e.message}") - // Fallback: crear directorio vacío o copiar contenido - logger.lifecycle("📁 Creando directorio docs como fallback...") - docsSymlink.toFile().mkdirs() + } catch (e: java.io.IOException) { + logger.warn("⚠️ No se pudo crear symlink de docs: ${e.message}") + // Fallback: crear directorio vacío o copiar contenido + logger.lifecycle("📁 Creando directorio docs como fallback...") + docsSymlink.toFile().mkdirs() }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@clients/web/build.gradle.kts` around lines 18 - 26, The current catch-all on Files.createSymbolicLink hides programming errors; replace catch (e: Exception) with targeted catches for the expected failure modes: catch java.io.IOException to handle I/O failures, catch SecurityException for permission issues, and catch UnsupportedOperationException for platforms that don't support symlinks; in each handler reference docsSymlink and docsTarget and include the caught exception (e) in the logger.warn message, then run the same fallback (logger.lifecycle "creating docs" and docsSymlink.toFile().mkdirs()) so only non-recoverable, unexpected exceptions escape.clients/web/README.md (1)
43-44:⚠️ Potential issue | 🟡 MinorNode.js version requirement is inconsistent across configuration files.
The README states "Node.js 20.19+ (recomendado 22+)" on line 43, but
clients/web/package.jsonenforces"node": ">=22.0.0"(line 29). Additionally,clients/web/apps/chat/package.jsonspecifies"node": ">=20.19.0"(line 8), creating a three-way mismatch. Update the README to reflect that the root workspace requires Node 22.0.0 as a strict minimum.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@clients/web/README.md` around lines 43 - 44, The README currently advertises "Node.js 20.19+ (recomendado 22+)" which conflicts with the workspace engines; change the README Node version to a strict minimum of "Node.js 22.0.0+" to match the root package.json engines.node value and remove the 20.19 reference; ensure the README text mirrors the exact engines.node constraint used in package.json (the "engines.node" entries) so all three references are consistent.clients/web/apps/chat/package.json (1)
14-15:⚠️ Potential issue | 🟡 MinorRemove unused dependencies and verify
biomehoisting in CI.
@biomejs/biomeis called in theformatandcheckscripts but only listed in the workspace rootpackage.json. This relies on pnpm hoisting—verify this works in your CI environment.Additionally,
class-variance-authorityis unused and can be removed.clsxandtailwind-mergeare imported insrc/lib/utils.tsto create acn()utility function, but this utility is never called anywhere in the application, making it dead code. Consider removing all three dependencies or refactor to use thecn()utility if it's needed for future components.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@clients/web/apps/chat/package.json` around lines 14 - 15, Remove unused deps and ensure biome is available in CI: delete "class-variance-authority" and decide whether to keep "clsx" and "tailwind-merge"—either remove them from clients/web/apps/chat/package.json or refactor code to actually use the cn() utility in src/lib/utils.ts (search for the cn function) so those imports are justified; additionally update the package.json scripts if you want to avoid relying on workspace hoisting by adding a devDependency on `@biomejs/biome` here or confirm CI's pnpm hoisting behavior to ensure the existing "format" and "check" scripts that invoke biome will run reliably.
🧹 Nitpick comments (7)
clients/web/apps/chat/src/components/ui/input/Input.vue (1)
9-11:_emitunderscore prefix is misleading — the variable is actively used in the template.The
_convention signals "intentionally unused," but_emitis called in@input. Rename it toemitfor clarity.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@clients/web/apps/chat/src/components/ui/input/Input.vue` around lines 9 - 11, Rename the defineEmits binding from _emit to emit so the template usage is clear: update the const declaration using defineEmits<{ "update:modelValue": [value: string]; }>() to export/assign as emit instead of _emit, and update any template references (e.g., the `@input` handler) to call emit(...) accordingly to remove the misleading underscore that implies “unused.”clients/web/apps/chat/src/components/chat/ChatMessage.vue (1)
102-111: Redundant@keyframes fade-in— already defined globally instyle.css.Vue's
<style scoped>does not scope@keyframes— they are always injected as global CSS. The identicalfade-inkeyframes instyle.css(lines 90–99) cover the.message-rowanimation at line 42. This local copy can be removed.♻️ Proposed fix
-.@keyframes fade-in { - from { - opacity: 0; - transform: translateY(8px); - } - to { - opacity: 1; - transform: translateY(0); - } -}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@clients/web/apps/chat/src/components/chat/ChatMessage.vue` around lines 102 - 111, Remove the redundant global keyframes definition from ChatMessage.vue: delete the local `@keyframes` fade-in block (the one used by .message-row animation) since `@keyframes` are not scoped and the identical fade-in is already defined in style.css; keep .message-row animation usage intact and ensure no other local references to fade-in remain in ChatMessage.vue.clients/web/apps/chat/src/style.css (2)
1-2: Consider self-hosting the Inter font instead of loading from Google Fonts.Loading fonts from
fonts.googleapis.commakes an external network request on every page load, which can be a GDPR/privacy concern (the user's IP is sent to Google's servers) and a performance dependency.A common alternative is to bundle the font via
fontsource:-@import url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap"); +@import "@fontsource-variable/inter";Install with:
pnpm add@fontsource-variable/inter``🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@clients/web/apps/chat/src/style.css` around lines 1 - 2, Replace the external Google Fonts import in clients/web/apps/chat/src/style.css (the line with `@import` url("https://fonts.googleapis.com/css2?family=Inter...")) by self-hosting Inter: install the package (e.g., pnpm add `@fontsource-variable/inter` or `@fontsource/inter`), remove the `@import` url(...) line, import the font from the installed package in your app entry or global stylesheet (where style.css is consumed), and update the CSS font-family declarations to use the locally bundled font with suitable fallbacks so the build serves font files from your own CDN/server rather than fonts.googleapis.com.
90-99:@keyframes fade-inis duplicated acrossstyle.cssandChatMessage.vue.
ChatMessage.vue(lines 102–111) defines an identicalfade-inkeyframe inside its<style scoped>block. Vue's scoped CSS does not scope@keyframes— they are always global, so both definitions resolve to the same name. The one inChatMessage.vueis redundant and can be removed.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@clients/web/apps/chat/src/style.css` around lines 90 - 99, The duplicate global `@keyframes` fade-in is defined in both style.css and ChatMessage.vue; because `@keyframes` are not scoped, remove the redundant definition from ChatMessage.vue's <style scoped> block (or alternatively rename the animation in ChatMessage.vue and update its usage in the component to a unique name) so only one global `@keyframes` fade-in remains and there are no conflicts.clients/web/apps/chat/src/components/ui/button/Button.vue (1)
116-118: Scoped.w-fullutility may be better placed in a shared stylesheet.This utility class is defined in scoped CSS but is passed from the parent (
App.vueLine 309:class="w-full"). While this works because the<button>element carries the scoped attribute, a utility class likew-fullis a general-purpose pattern that would be more discoverable and reusable in a shared/global stylesheet or via Tailwind'sw-full.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@clients/web/apps/chat/src/components/ui/button/Button.vue` around lines 116 - 118, The scoped utility class `.w-full` in Button.vue is a general-purpose width utility used by the parent (App.vue uses class="w-full")—move this rule out of the component's scoped CSS into a shared/global stylesheet (or replace usage with Tailwind's `w-full`) and remove the `.w-full` entry from the scoped block in Button.vue so the utility is discoverable and reusable across components.clients/web/apps/chat/src/App.vue (2)
189-193: Duplicated inline SVGs — consider extracting icon components.The settings gear SVG is duplicated 3 times (sidebar, mobile header, config header) and the logo SVG is duplicated 3 times as well. Extracting these into small icon components (e.g.,
IconLogo.vue,IconGear.vue) would reduce template size and improve maintainability.Also applies to: 218-221, 233-237, 246-249, 258-261, 338-342
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@clients/web/apps/chat/src/App.vue` around lines 189 - 193, The template contains repeated inline SVG markup (logo and gear) in App.vue; extract them into two small single-file components (e.g., IconLogo.vue and IconGear.vue) that render the SVG, export default with a simple name, then replace each inline SVG occurrence in App.vue (sidebar, mobile header, config header and other duplicates) with the new components and import/register them in the App.vue script block (use the component names like IconLogo and IconGear). Ensure the new components accept passthrough props for size/class if needed so existing attributes (width/height/class) can be preserved when used.
152-174:sendMessagedoes not make an API call — appears to be a stub.The function appends a canned "processing" template message as the assistant response instead of actually calling the configured gateway. If this is intentional for an initial iteration, consider adding a
// TODOcomment so it's not overlooked. Otherwise, this should be wired to the backend.Would you like me to open an issue to track wiring
sendMessageto the gateway API?🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@clients/web/apps/chat/src/App.vue` around lines 152 - 174, sendMessage currently only appends a canned "processing" assistant message instead of calling the gateway; replace the stub with a real API call: build a request payload using normalizedText and modelName and POST it to the configured gateway (baseUrl.value), send the request after pushing the user message, create a temporary assistant message via nextMessageId() to show loading, then replace or update that assistant message with the gateway response when the call resolves (or replace it with an error message on failure), keep prompt.value clearing, await nextTick() and call scrollChatToBottom() as before, and add a // TODO if you intend to keep the stub behavior temporarily. Use messages, nextMessageId, MAX_PROMPT_LENGTH, modelName, baseUrl, t(...) for error text, and ensure errors are caught and logged/ surfaced to the user.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@clients/web/apps/chat/src/App.vue`:
- Around line 96-113: The code posts sensitive fields (pairingCodeInput,
bearerTokenInput, webhookSecretInput) to gatewayBaseUrl without validating
protocol; update the submit logic that builds payload and calls fetch to parse
gatewayBaseUrl (using the URL constructor) and reject or prompt the user if the
protocol is "http:" and the hostname is not "localhost" or "127.0.0.1" (or
otherwise not explicitly allowed); implement this check before creating
payload/issuing fetch, and surface a clear UI error/warning or disable
submission when the unsafe URL is detected so secrets are not sent over plain
HTTP to remote hosts.
- Around line 365-369: The chat input currently uses only a placeholder
(v-model="prompt" on the element with class "chat-input") which is not
accessible; add an accessible label by either adding an aria-label that reuses
the translation (e.g. :aria-label="t('chat.inputPlaceholder')") or render a
visually-hidden <label> element tied to the input via an id (set :id on the
input and for on the label) so screen readers announce the field; keep the
existing v-model="prompt" and placeholder intact for visual UX and ensure you
use the same i18n key t('chat.inputPlaceholder') for the label text.
In `@clients/web/apps/chat/src/components/chat/ChatMessage.vue`:
- Around line 15-21: The decorative SVGs in ChatMessage.vue are being announced
by assistive tech; add aria-hidden="true" to each presentational SVG to prevent
screen readers from announcing them. Specifically update the <svg> inside the
div rendered when role === 'assistant' (class "avatar avatar--assistant") and
the counterpart SVG used for the other role (the avatar div around lines 29-34)
to include aria-hidden="true" on the <svg> elements so they are treated as
purely decorative.
In `@clients/web/apps/chat/src/components/ui/button/Button.vue`:
- Around line 13-18: The class collision comes from using the same prefix for
variant and size in the :class array in Button.vue (the `btn--${props.variant ??
'default'}` and `btn--${props.size ?? 'default'}` entries); change the size
class to use a distinct prefix (for example `btn-size--${props.size ??
'default'}`) in the :class array so variant and size generate different tokens,
then rename the corresponding CSS selectors (e.g., change `.btn--default-size`
and other `.btn--{size}` rules to the new `btn-size--{size}` names and update
any rules that currently rely on `.btn--default`) so the ghost variant is not
overridden by the default size rule.
In `@clients/web/apps/chat/src/components/ui/input/Input.vue`:
- Around line 1-22: The component currently declares a prop named "class" and
also relies on Vue's default inheritAttrs behavior, causing duplicate/confusing
class application; update the component by calling defineOptions({ inheritAttrs:
false }) at the top, remove or stop using the "class" prop in defineProps (or
rename it to avoid colliding with fallthrough attrs), and adjust the template to
read classes from $attrs.class or a renamed prop as appropriate; also consider
renaming _emit to emit via const emit = defineEmits(...) for clearer emit usage
in the `@input` handler (i.e., use emit('update:modelValue', ...)).
In `@clients/web/apps/chat/src/style.css`:
- Line 2: Replace the current `@import` url(...) line with the string form `@import`
"..." to satisfy stylelint's import-notation rule and Tailwind/Lightning CSS
expectations; locate the `@import` line in style.css and change the url(...)
wrapper to the plain string syntax using the same Google Fonts URL.
---
Outside diff comments:
In `@clients/web/apps/chat/package.json`:
- Around line 14-15: Remove unused deps and ensure biome is available in CI:
delete "class-variance-authority" and decide whether to keep "clsx" and
"tailwind-merge"—either remove them from clients/web/apps/chat/package.json or
refactor code to actually use the cn() utility in src/lib/utils.ts (search for
the cn function) so those imports are justified; additionally update the
package.json scripts if you want to avoid relying on workspace hoisting by
adding a devDependency on `@biomejs/biome` here or confirm CI's pnpm hoisting
behavior to ensure the existing "format" and "check" scripts that invoke biome
will run reliably.
In `@clients/web/build.gradle.kts`:
- Around line 18-26: The current catch-all on Files.createSymbolicLink hides
programming errors; replace catch (e: Exception) with targeted catches for the
expected failure modes: catch java.io.IOException to handle I/O failures, catch
SecurityException for permission issues, and catch UnsupportedOperationException
for platforms that don't support symlinks; in each handler reference docsSymlink
and docsTarget and include the caught exception (e) in the logger.warn message,
then run the same fallback (logger.lifecycle "creating docs" and
docsSymlink.toFile().mkdirs()) so only non-recoverable, unexpected exceptions
escape.
In `@clients/web/README.md`:
- Around line 43-44: The README currently advertises "Node.js 20.19+
(recomendado 22+)" which conflicts with the workspace engines; change the README
Node version to a strict minimum of "Node.js 22.0.0+" to match the root
package.json engines.node value and remove the 20.19 reference; ensure the
README text mirrors the exact engines.node constraint used in package.json (the
"engines.node" entries) so all three references are consistent.
---
Nitpick comments:
In `@clients/web/apps/chat/src/App.vue`:
- Around line 189-193: The template contains repeated inline SVG markup (logo
and gear) in App.vue; extract them into two small single-file components (e.g.,
IconLogo.vue and IconGear.vue) that render the SVG, export default with a simple
name, then replace each inline SVG occurrence in App.vue (sidebar, mobile
header, config header and other duplicates) with the new components and
import/register them in the App.vue script block (use the component names like
IconLogo and IconGear). Ensure the new components accept passthrough props for
size/class if needed so existing attributes (width/height/class) can be
preserved when used.
- Around line 152-174: sendMessage currently only appends a canned "processing"
assistant message instead of calling the gateway; replace the stub with a real
API call: build a request payload using normalizedText and modelName and POST it
to the configured gateway (baseUrl.value), send the request after pushing the
user message, create a temporary assistant message via nextMessageId() to show
loading, then replace or update that assistant message with the gateway response
when the call resolves (or replace it with an error message on failure), keep
prompt.value clearing, await nextTick() and call scrollChatToBottom() as before,
and add a // TODO if you intend to keep the stub behavior temporarily. Use
messages, nextMessageId, MAX_PROMPT_LENGTH, modelName, baseUrl, t(...) for error
text, and ensure errors are caught and logged/ surfaced to the user.
In `@clients/web/apps/chat/src/components/chat/ChatMessage.vue`:
- Around line 102-111: Remove the redundant global keyframes definition from
ChatMessage.vue: delete the local `@keyframes` fade-in block (the one used by
.message-row animation) since `@keyframes` are not scoped and the identical
fade-in is already defined in style.css; keep .message-row animation usage
intact and ensure no other local references to fade-in remain in
ChatMessage.vue.
In `@clients/web/apps/chat/src/components/ui/button/Button.vue`:
- Around line 116-118: The scoped utility class `.w-full` in Button.vue is a
general-purpose width utility used by the parent (App.vue uses
class="w-full")—move this rule out of the component's scoped CSS into a
shared/global stylesheet (or replace usage with Tailwind's `w-full`) and remove
the `.w-full` entry from the scoped block in Button.vue so the utility is
discoverable and reusable across components.
In `@clients/web/apps/chat/src/components/ui/input/Input.vue`:
- Around line 9-11: Rename the defineEmits binding from _emit to emit so the
template usage is clear: update the const declaration using defineEmits<{
"update:modelValue": [value: string]; }>() to export/assign as emit instead of
_emit, and update any template references (e.g., the `@input` handler) to call
emit(...) accordingly to remove the misleading underscore that implies “unused.”
In `@clients/web/apps/chat/src/style.css`:
- Around line 1-2: Replace the external Google Fonts import in
clients/web/apps/chat/src/style.css (the line with `@import`
url("https://fonts.googleapis.com/css2?family=Inter...")) by self-hosting Inter:
install the package (e.g., pnpm add `@fontsource-variable/inter` or
`@fontsource/inter`), remove the `@import` url(...) line, import the font from the
installed package in your app entry or global stylesheet (where style.css is
consumed), and update the CSS font-family declarations to use the locally
bundled font with suitable fallbacks so the build serves font files from your
own CDN/server rather than fonts.googleapis.com.
- Around line 90-99: The duplicate global `@keyframes` fade-in is defined in both
style.css and ChatMessage.vue; because `@keyframes` are not scoped, remove the
redundant definition from ChatMessage.vue's <style scoped> block (or
alternatively rename the animation in ChatMessage.vue and update its usage in
the component to a unique name) so only one global `@keyframes` fade-in remains
and there are no conflicts.
Deploying corvus with
|
| Latest commit: |
7720c3e
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://46534cc0.corvus-42x.pages.dev |
| Branch Preview URL: | https://fix-pnpm-lockfile-gradle.corvus-42x.pages.dev |
… update UI components with new icons
This pull request renames the
dashboardapp tochatthroughout the Corvus web monorepo and introduces a new, modern conversational AI chat interface. It updates all related documentation, configuration, and code references, and adds new UI components and styling for the chat experience. The most important changes are grouped below:App Renaming and Documentation Updates:
dashboardapp is renamed tochateverywhere, including folder names, documentation (README.md), and package metadata, to reflect its new purpose as a conversational AI interface. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12]New and Improved Chat UI:
ChatMessage.vue, a reusableButton.vue, and anInput.vuecomponent, providing a modern, ChatGPT-style conversational workspace. [1] [2] [3]Styling and Design Tokens:
style.csswith design tokens, dark mode support, custom fonts, and animations for a polished, modern look and feel.Localization and UX Improvements:
Testing Adjustments:
These changes collectively modernize the Corvus web frontend, shifting its focus from a dashboard to a user-friendly conversational AI chat experience.
Summary by CodeRabbit
New Features
Refactor
Documentation