Skip to content

Conversation

@JounQin
Copy link
Member

@JounQin JounQin commented Aug 27, 2025

Summary by CodeRabbit

  • New Features

    • AI Assistant panel with chat, streaming answers, referenced docs, thinking indicator, and resizable input.
    • Login flow with region selection, captcha, encryption, auth management, and localized error alerts.
    • New reusable UI primitives: buttons, inputs, focus/captcha inputs, form items, radio group, translations (EN/ZH/RU).
  • Chores

    • Updated scripts to run pre-clean before build and simplified lint script.
    • Release metadata bumped for a minor version.
    • Dev proxy and package exports/styles exposed; dependency updates.

Copilot AI review requested due to automatic review settings August 27, 2025 04:46
@changeset-bot
Copy link

changeset-bot bot commented Aug 27, 2025

🦋 Changeset detected

Latest commit: 31df25e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@alauda/doom Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link

coderabbitai bot commented Aug 27, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds an AI Assistant feature: new UI components, streaming chat flow, auth (cloud regions, login with RSA/captcha), context and utilities, hooks, translations (en/zh/ru), styles, package/export updates, dev-proxy, and CI flag change. No existing public API removals.

Changes

Cohort / File(s) Summary
Release metadata
./.changeset/shaggy-garlics-divide.md
Adds a changeset indicating a minor release for @alauda/doom.
Repo root scripts & CI
package.json, .github/workflows/pkg-pr-new.yml
Run yarn clean && tsc -b for build; simplify lint script to eslint .; enable --compact in pkg-pr-new publish step.
Package manifest & exports
packages/doom/package.json
Adds ./assets/* and ./styles/* exports; updates and adds dependencies (ab64, jsencrypt, react-tooltip; bumps others).
Dev server proxy
packages/doom/src/cli/load-config.ts
Adds proxy routes forwarding /api/v1 → cloud.alauda.cn and /smart/api → docs-dev.alauda.cn.
AI Assistant core
packages/doom/src/global/Intelligence/AIAssistant/index.tsx, .../Chat/*, .../ResizableUserInput/*, .../Thinking.tsx, .../types.ts, .../utils.ts
Implements AIAssistant UI, chat rendering, streaming answer handling and parser, message/ref-doc types, resizable input, and thinking indicator.
Authentication / preamble & form primitives
.../Preamble/* (LoginForm, ApiErrorAlert, CaptchaInput, FocusInput, FormItem, Input, Button, Radio{,Group,context,index}.tsx, types, utils)
Adds pre-login UI, login flow with public-key encryption, captcha handling, form components, radio group context, and related types/utilities.
Intelligence feature gate & context
packages/doom/src/global/Intelligence/index.tsx, context.tsx, constants.ts, types.ts, utils.ts
Adds gating (host/lang/env), CloudAuth provider/hook, auth constants, JWT parsing and localStorage helpers.
Runtime hooks & translations
packages/doom/src/runtime/hooks/index.ts, useInterval.ts, useMemoizedFn.ts, packages/doom/src/runtime/translation.ts
Re-exports .ts hooks; adds useInterval and useMemoizedFn; expands translations (en/zh/ru) with AI/auth keys and punctuation tokens.
Styles
packages/doom/styles/*, packages/doom/styles/global.scss
Adds SCSS modules and styles for AI assistant, chat, ref-docs, preamble, inputs/forms, resizable input, intelligence entry; imports intelligence.scss into global styles.
Small import adjustments
packages/doom/src/global/VersionsNav/NavMenuSingleItem.tsx
Switches to TS import path and package styles alias; no logic changes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Widget as AI Assistant UI
  participant Auth as CloudAuthContext
  participant Server as /smart/api
  Note over Widget,Server: New chat and streaming answer flow
  User->>Widget: Type message + Send
  Widget->>Widget: Append user msg + placeholder assistant (Thinking)
  alt No session
    Widget->>Server: POST /new_session (username header)
    Server-->>Widget: { session_id }
  end
  Widget->>Server: POST /smart/api/smart_answer { input_text, session_id }
  loop Stream answer
    Server-->>Widget: streaming text chunks
    Widget->>Widget: parseStreamContent(chunk)
    Widget->>Widget: update assistant msg (content/refDocs/thinkingProcess)
  end
  Widget->>Widget: Auto-scroll chat
  Note over Widget: On error → set assistant content to translated NetworkError
Loading
sequenceDiagram
  autonumber
  actor User
  participant Preamble as Preamble/LoginForm
  participant Cloud as Origin (/api/v1)
  participant Auth as CloudAuthContext
  Note over Preamble,Cloud: Login with RSA, optional captcha, region selection
  User->>Preamble: Select region, enter tenant/username/password
  Preamble->>Cloud: GET /pubkey
  Cloud-->>Preamble: { pubkey, ts }
  Preamble->>Preamble: cryptoPassword(pubkey, password)
  Preamble->>Cloud: POST /login (encrypted payload, captchaId if present)
  alt Success
    Cloud-->>Preamble: { accessToken, ... }
    Preamble->>Auth: setAuthBasic({ origin, token })
  else PubkeyExpireError
    Cloud-->>Preamble: error(reason=PubkeyExpireError)
    Preamble->>Preamble: clear cached pubkey and retry
  else Error
    Cloud-->>Preamble: error(reason, message, captchaId?)
    Preamble->>Preamble: show ApiErrorAlert / CaptchaInput if needed
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Suggested labels

feature

Poem

I hop to the corner, a tiny assist,
I encrypt your password and fetch what you've missed.
I stream and I parse, I show docs with delight,
A nibble, a nudge — we’ll chat through the night.
Hooray for new helpers! 🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/intelligence

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Aug 27, 2025

Open in StackBlitz

yarn add https://pkg.pr.new/@alauda/doom@160.tgz
yarn add https://pkg.pr.new/@alauda/doom-export@160.tgz

commit: 31df25e

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements intelligence support by adding an AI assistant feature with complete login functionality and chat interface. It includes comprehensive UI components for user authentication against cloud portals, chat messaging with streaming responses, and multilingual support.

  • Adds AI assistant component with cloud authentication capabilities
  • Implements chat interface with streaming responses and document references
  • Extends translation support for AI assistant features across multiple languages

Reviewed Changes

Copilot reviewed 45 out of 54 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
packages/doom/styles/*.scss New SCSS modules for AI assistant, chat, preamble, and form styling
packages/doom/src/runtime/translation.ts Extended translations for AI assistant in English, Chinese, and Russian
packages/doom/src/runtime/hooks/* Added utility hooks for memoized functions and intervals
packages/doom/src/global/Intelligence/* Complete AI assistant implementation with authentication and chat
packages/doom/src/cli/load-config.ts Added proxy configuration for API endpoints
packages/doom/package.json Updated dependencies and exports for new features
Comments suppressed due to low confidence (2)

packages/doom/styles/intelligence.scss:1

  • Hard-coded red color values should use CSS custom properties like other colors in the design system.
.api-error-alert {

packages/doom/styles/intelligence.scss:1

  • Hard-coded red color values should use CSS custom properties like other colors in the design system.
.api-error-alert {

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@JounQin JounQin force-pushed the feat/intelligence branch from 8449cf6 to cdaea82 Compare August 27, 2025 04:57
@JounQin JounQin force-pushed the feat/intelligence branch from cdaea82 to 31df25e Compare August 27, 2025 05:01
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 29

♻️ Duplicate comments (7)
packages/doom/styles/chat-ref-docs.module.scss (1)

3-3: Replace hard-coded color with a design token

Use an existing CSS variable (e.g., var(--rp-c-bg-soft)) for theming consistency and dark-mode support.

-  background-color: #f2f8fe;
+  background-color: var(--rp-c-bg-soft);
packages/doom/styles/intelligence.scss (1)

25-29: Use a CSS variable instead of #fff for the primary button text

Align with tokens and ease theme switching.

   &--primary {
     background-color: var(--rp-c-brand-dark);
     border-radius: 4px;
-    color: #fff;
+    color: var(--rp-c-white);
   }
packages/doom/src/global/Intelligence/AIAssistant/Thinking.tsx (1)

19-19: Extract magic number to a named constant

Apply:

-  }, 250)
+  }, THINKING_ANIMATION_INTERVAL_MS)

Add at top:

+const THINKING_ANIMATION_INTERVAL_MS = 250
packages/doom/src/global/Intelligence/AIAssistant/utils.ts (2)

1-1: Extract regexes to named constants with docs.

Improves readability and testability; aligns with prior feedback.

+const DOCS_BLOCK_REGEX = /<docs>([\s\S]*?)<\/docs>/
+const THINK_BLOCK_REGEX = /<think>([\s\S]*?)<\/think>/g

Also applies to: 31-31


31-38: Correct think-block extraction and typing; current logic always strips the first match and may return a non-string.

  • Bug: matched defaults to firstMatched, then removes itself, yielding ''.
  • Type: thinkingProcess can become RegExpMatchArray | null, not string | null.
    Use a dedicated regex and take the last block’s inner text.

Apply:

-  const matchThinks = text.match(/<think>[\s\S]*?<\/think>|^[\s\S]*?<\/think>/g)
-  const firstMatched = matchThinks?.[0]
-  let matched = firstMatched || matchThinks?.[1]
-  if (matched) {
-    matched = removePrefix(firstMatched || '', matched)
-  }
-  const thinkingProcess = matchThinks && matched
+  const thinkMatches = [...text.matchAll(THINK_BLOCK_REGEX)]
+  const thinkingProcess: string | null =
+    thinkMatches.length ? thinkMatches[thinkMatches.length - 1][1] : null

And update content removal (below).

packages/doom/src/global/Intelligence/AIAssistant/ResizableUserInput/index.tsx (2)

37-37: Extract 2000 into a named constant.

-  const maxCharsExceeded = innerValue.length > 2000
+  const MAX_CHARS_LIMIT = 2000
+  const maxCharsExceeded = innerValue.length > MAX_CHARS_LIMIT

83-92: Extract 54 into a named constant and document basis.

54 = 27 CJK chars × 2 width units.

+  const FULLWIDTH_UNITS_PER_LINE = 54
@@
-        .map((line) =>
-          Math.ceil(stringWidth(line) / /* 27 Chinese characters */ 54),
-        )
+        .map((line) => Math.ceil(stringWidth(line) / FULLWIDTH_UNITS_PER_LINE))
🧹 Nitpick comments (54)
.github/workflows/pkg-pr-new.yml (1)

3-9: Consider restricting triggers or adding path filters to save CI minutes.

If desired, add on.push.paths/paths-ignore so publish runs only when package files change.

Apply this diff if you want minimal noise:

 on:
-  - push
-  - pull_request
+  push:
+    paths:
+      - "packages/**"
+      - ".github/workflows/pkg-pr-new.yml"
+      - "package.json"
+      - "yarn.lock"
+  pull_request:
+    paths:
+      - "packages/**"
+      - ".github/workflows/pkg-pr-new.yml"
+      - "package.json"
+      - "yarn.lock"
packages/doom/src/cli/load-config.ts (2)

331-334: Defaulting dev proxies to internal domains may surprise external users; gate behind env.

As-is, any consumer of doom gets these proxies by default. Consider enabling them only when explicitly requested and optionally make targets configurable via env.

Apply this diff:

       server: {
         open,
-        proxy: {
-          '/api/v1': 'https://cloud.alauda.cn',
-          '/smart/api': 'https://docs-dev.alauda.cn',
-        },
+        proxy:
+          process.env.ALAUDA_INTERNAL_PROXY === '1'
+            ? {
+                '/api/v1':
+                  process.env.ALAUDA_CLOUD_PROXY_TARGET ??
+                  'https://cloud.alauda.cn',
+                '/smart/api':
+                  process.env.ALAUDA_SMART_API_PROXY_TARGET ??
+                  'https://docs-dev.alauda.cn',
+              }
+            : undefined,
       },

345-355: Avoid DefinePlugin values resolving to undefined.

When algoliaOptions is falsy, JSON.stringify(undefined) yields undefined, which can produce missing replacements. Coalesce to empty strings (or 'null') to be safe.

Apply this diff:

               new rspack.DefinePlugin({
-                'process.env.ALGOLIA_APP_ID': JSON.stringify(
-                  algoliaOptions?.appId,
-                ),
-                'process.env.ALGOLIA_API_KEY': JSON.stringify(
-                  algoliaOptions?.apiKey,
-                ),
-                'process.env.ALGOLIA_INDEX_NAME': JSON.stringify(
-                  algoliaOptions?.indexName,
-                ),
+                'process.env.ALGOLIA_APP_ID': JSON.stringify(
+                  algoliaOptions?.appId ?? '',
+                ),
+                'process.env.ALGOLIA_API_KEY': JSON.stringify(
+                  algoliaOptions?.apiKey ?? '',
+                ),
+                'process.env.ALGOLIA_INDEX_NAME': JSON.stringify(
+                  algoliaOptions?.indexName ?? '',
+                ),
               }),
packages/doom/package.json (1)

42-114: Optional tidy: drop unused deps.

If html-tag-names is no longer used after the UI migration, consider removing it.

package.json (1)

24-24: Single eslint entry-point — fine; consider keeping a type-check script in CI.

Since lint:tsc was removed, ensure CI still runs tsc --noEmit for PRs (build may be skipped on docs-only changes).

Example addition:

   "scripts": {
     "build": "yarn clean && tsc -b",
+    "typecheck": "tsc -b --noEmit",
     "clean": "tsc -b --clean",
packages/doom/src/global/Intelligence/AIAssistant/types.ts (1)

3-8: Use camelCase for field names to match TS conventions.

Aligns with existing code style and avoids mixed_case.

 export interface RefDoc {
   content: string
-  cos_sim: number
+  cosSim: number
   id: number
   path: string
 }
packages/doom/src/runtime/hooks/useMemoizedFn.ts (1)

10-14: Optional: preserve this typing if needed.

If consumers rely on this, add an explicit this: unknown to T to avoid accidental this leakage.

-  <T extends (...args: any[]) => any>(fn: T): T => {
+  <T extends (this: unknown, ...args: any[]) => any>(fn: T): T => {
packages/doom/styles/intelligence.scss (1)

15-30: Add disabled and focus-visible styles for accessibility

Improve keyboard visibility and clarify disabled state; matches the Button component behavior.

 .button {
   display: inline-flex;
   align-items: center;
   justify-content: center;
   height: 40px;
+
+  &:disabled {
+    opacity: 0.6;
+    cursor: not-allowed;
+  }
+
+  &:focus-visible {
+    outline: 2px solid var(--rp-c-brand-dark);
+    outline-offset: 2px;
+  }
packages/doom/styles/global.scss (1)

166-166: Consider migrating @import to @use to avoid Sass deprecation warnings

Optional, but future-proof. Using @use will include the CSS once and avoid global name collisions.

-@import 'intelligence.scss';
+@use './intelligence.scss';
packages/doom/src/global/Intelligence/types.ts (2)

3-11: Avoid value/type name shadowing for TenantType

Having both a value and a type named TenantType is legal but confusing. Rename the constant to reduce cognitive load.

-export const TenantType = {
+export const TenantTypes = {
   Alauda: 'alauda',
   NONE: 'none',
   Tencent: 'tencent',
   Huawei: 'huawei',
 } as const

-export type TenantType = ValueOf<typeof TenantType>
+export type TenantType = ValueOf<typeof TenantTypes>

3-8: Normalize enum-like keys for consistency

Mixed casing (Alauda/Tencent/Huawei vs NONE) is inconsistent. Consider using a single convention (e.g., PascalCase or SCREAMING_CASE) across all keys.

packages/doom/src/runtime/translation.ts (1)

57-57: Parameterize the “2000 characters” limit instead of hardcoding

Hardcoding the limit in i18n strings makes future changes noisy and error-prone across locales.

Apply this diff to switch to a placeholder that callers can replace (e.g., with .replace('{max}', String(max))):

-  max_chars_exceeded_tip: 'Maximum 2000 characters allowed.',
+  max_chars_exceeded_tip: 'Maximum {max} characters allowed.',
-  max_chars_exceeded_tip: '最多允许 2000 个字符。',
+  max_chars_exceeded_tip: '最多允许 {max} 个字符。',
-  max_chars_exceeded_tip: 'Максимум 2000 символов.',
+  max_chars_exceeded_tip: 'Максимум {max} символов.',

Also applies to: 118-118, 185-185

packages/doom/src/global/Intelligence/AIAssistant/Preamble/Input/index.tsx (1)

6-7: Prefix/suffix should accept ReactNode, not just string

Icons and formatted fragments are common here; widening to ReactNode improves flexibility. Also mark decorative wrappers aria-hidden to avoid noisy screen reader output.

(Handled in the diff above.)

Also applies to: 19-21

packages/doom/src/runtime/hooks/useInterval.ts (2)

12-21: Type the interval ID for cross-env TS (DOM/Node) compatibility

Explicitly typing the id avoids friction when both DOM and Node types are present.

Apply:

-      const id = setInterval(
+      const id: ReturnType<typeof setInterval> = setInterval(
         () => {
           cbRef.current()
         },
         delay,
       )

6-8: Minor: move callback ref update into an effect

Functionally fine, but placing cbRef.current = cb inside a useEffect with [cb] reduces accidental mutations during render.

-  // Remember the latest callback.
-  cbRef.current = cb
+  // Remember the latest callback.
+  useEffect(() => {
+    cbRef.current = cb
+  }, [cb])
packages/doom/src/global/Intelligence/AIAssistant/Thinking.tsx (1)

21-21: Improve accessibility: announce status updates

Wrap in a live region so screen readers get non-intrusive updates.

-  return `${t('thinking')}${CHUNKS[index]}`
+  return (
+    <span aria-live="polite" aria-atomic="true">
+      {t('thinking')}
+      {CHUNKS[index]}
+    </span>
+  )
packages/doom/styles/chat.module.scss (1)

26-29: Nit: simplify line-height to a numeric constant.

calc(20 / 14) is fine, but a plain number is clearer and avoids any calc parsing edge cases.

-  line-height: calc(20 / 14);
+  line-height: 1.4286;
packages/doom/src/global/Intelligence/AIAssistant/Preamble/LoginForm/utils.ts (1)

11-14: Propagate encryption failures from cryptoPassword.

If crypto throws (or you switch to a nullable return), ensure caller handles it to present a clear login error.

Want me to wire this through the Login form submit path with user-friendly messages?

packages/doom/src/global/Intelligence/AIAssistant/Preamble/types.ts (1)

3-18: Prefer Record over object for stronger typing and fewer pitfalls.

object is broad (includes arrays). Record<string, unknown> is safer for structured extras and aligns with JSON payloads.

-export interface ApiErrorOptions<
-  R extends string = string,
-  E extends object = object,
-  T = unknown,
-> {
+export interface ApiErrorOptions<
+  R extends string = string,
+  E extends Record<string, unknown> = Record<string, unknown>,
+  T = unknown,
+> {
   code: number
   reason: R
   message: string
   extra?: E
   details?: T[]
 }
 
 export type ApiError<
-  T extends string = string,
-  E extends object = object,
-> = ResponseError<ApiErrorOptions<T, E>>
+  T extends string = string,
+  E extends Record<string, unknown> = Record<string, unknown>,
+> = ResponseError<ApiErrorOptions<T, E>>
packages/doom/src/global/Intelligence/constants.ts (2)

8-24: Avoid mutating exported arrays; compute per-env and freeze for safety.

unshift mutates the shared instance. Build a per-env array and expose read-only views to prevent accidental downstream mutation.

-const CLOUD_AUTH_ORIGINS: CloudAuthRegion[] = [
-  {
-    name: 'global',
-    value: 'https://cloud.alauda.io',
-  },
-  {
-    name: 'china',
-    value: 'https://cloud.alauda.cn',
-  },
-]
-
-if (!isProduction()) {
-  CLOUD_AUTH_ORIGINS.unshift({
-    name: 'local',
-    value: '',
-  })
-}
+const BASE_ORIGINS = Object.freeze([
+  Object.freeze<CloudAuthRegion>({ name: 'global', value: 'https://cloud.alauda.io' }),
+  Object.freeze<CloudAuthRegion>({ name: 'china', value: 'https://cloud.alauda.cn' }),
+])
+
+const ORIGINS = isProduction()
+  ? BASE_ORIGINS
+  : Object.freeze([
+      Object.freeze<CloudAuthRegion>({ name: 'local', value: '' }),
+      ...BASE_ORIGINS,
+    ])

26-31: Expose read-only views to discourage mutation by consumers.

Mark the exports as readonly.

-export const CLOUD_AUTH_ORIGIN_VALUES = CLOUD_AUTH_ORIGINS.map(
-  ({ value }) => value,
-)
-
-export { CLOUD_AUTH_ORIGINS }
+export const CLOUD_AUTH_ORIGINS: ReadonlyArray<Readonly<CloudAuthRegion>> = ORIGINS
+export const CLOUD_AUTH_ORIGIN_VALUES = Object.freeze(
+  CLOUD_AUTH_ORIGINS.map(({ value }) => value) as readonly string[],
+)
packages/doom/styles/intelligence.module.scss (1)

13-26: Ensure the floating entry button stays on top and is keyboard-visible

Add a z-index and a clear focus-visible outline for accessibility.

 .entry {
   position: fixed;
   bottom: 15%;
   right: 0;
   display: inline-flex;
   align-items: center;
   background-color: var(--rp-c-bg);
   height: 40px;
   border-top-left-radius: 100px;
   border-bottom-left-radius: 100px;
   box-shadow: 0px 0px 12px 0px var(--rp-c-divider);
   padding-left: 10px;
   padding-right: 8px;
+  z-index: 1000;
+
+  &:focus-visible {
+    outline: 2px solid var(--rp-c-brand);
+    outline-offset: 2px;
+  }
 }
packages/doom/src/global/Intelligence/utils.ts (2)

13-27: Harden JWT payload parsing against malformed tokens

Avoid decoding when the token lacks a payload segment; return early without logging noisy errors.

 export const getAuthInfoFromToken = (
   token?: string | null,
 ): AuthInfo | undefined => {
   if (!token) {
     return
   }
 
-  let authTokenInfo: AuthTokenInfo
+  let authTokenInfo: AuthTokenInfo
+  const [, payload] = token.split('.') as [string, string?, ...string[]]
+  if (!payload) {
+    return
+  }
 
   try {
-    authTokenInfo = JSON.parse(decodeUrl(token.split('.')[1])) as AuthTokenInfo
+    authTokenInfo = JSON.parse(decodeUrl(payload)) as AuthTokenInfo
   } catch (err) {
     console.error('jwt decode failed:', err)
     return
   }

23-27: Consider softening logging

console.error can be noisy in user consoles. Prefer console.debug or a project logger with sampling.

packages/doom/styles/resizable-user-input.module.scss (1)

23-31: Add :focus-within fallback for browsers without :has support

:has is not universally reliable in older environments. Provide a focus-within fallback to keep borders and send color consistent.

   &:has(textarea:focus) {
     &:not(.error) {
       border-color: var(--rp-c-brand-dark);
     }
 
     .send:not(.disabled) {
       color: var(--rp-c-brand);
     }
   }
+
+  /* Fallback for older browsers */
+  &:focus-within:not(.error) {
+    border-color: var(--rp-c-brand-dark);
+  }
+  &:focus-within .send:not(.disabled) {
+    color: var(--rp-c-brand);
+  }
packages/doom/src/global/Intelligence/AIAssistant/Preamble/ApiErrorAlert/index.tsx (2)

28-33: Simplify translation lookup; remove try/catch

t() shouldn’t throw. Use a typed key with a nullish-coalesce fallback to message.

-    try {
-      return reason ? t(reason) || reason : message
-    } catch {
-      return message
-    }
+    const reasonKey = reason as Parameters<typeof t>[0] | undefined
+    return reasonKey ? (t(reasonKey) ?? message) : message

35-38: Add ARIA semantics for status messages

Make the alert announced by screen readers; hide the icon from accessibility tree.

-    <div className="api-error-alert">
-      <AlertIcon className="api-error-alert__icon" />
+    <div className="api-error-alert" role="alert" aria-live="polite">
+      <AlertIcon className="api-error-alert__icon" aria-hidden="true" />
       {message}
     </div>
packages/doom/src/global/Intelligence/index.tsx (3)

49-52: Config-driven domain allowlist

Hardcoding domains means code changes for each new host. Consider reading an allowlist from virtual config/env and falling back to the current defaults.


53-54: Return null instead of undefined for clarity

React treats both as “render nothing,” but null is idiomatic.

-    return
+    return null

31-33: Security note: avoid trusting client-sent username

AIAssistant sends username from a locally decoded token in the new_session header. Ensure the backend authenticates via cookies/Authorization and treats this header as informational only.

packages/doom/src/global/Intelligence/AIAssistant/Chat/ChatRefDocs/index.tsx (3)

32-38: Make the expander control accessible

Use a button with aria-expanded and keyboard support instead of a clickable span.

-        {refDocs.length > 3 && (
-          <span className={classes.action} onClick={toggleExpand}>
+        {refDocs.length > 3 && (
+          <button
+            type="button"
+            className={classes.action}
+            onClick={toggleExpand}
+            aria-expanded={expand}
+            aria-controls="chat-ref-docs-list"
+          >
             {t(expand ? 'view_less_related_docs' : 'view_more_related_docs')} (
             {refDocs.length})
             <AngleDownIcon
               className={clsx(classes.icon, expand && classes.expanded)}
             />
-          </span>
+          </button>
         )}

41-42: Wire aria-controls to the list

Give the docs list an id referenced by the button.

-      <ul className={classes.docs}>
+      <ul id="chat-ref-docs-list" className={classes.docs}>

29-30: Prefer a single i18n key instead of string concatenation

Using two keys for “label + colon” can break locale-specific punctuation. Consider a single key (e.g., referenced_doc_links_label).

-          {t('referenced_doc_links') + t('colon')}
+          {t('referenced_doc_links_label')}

Note: add the new translation key in all locales.

packages/doom/src/global/Intelligence/AIAssistant/Preamble/index.tsx (2)

25-25: Use explicit conditional for readability

Avoid relying on falsy rendering semantics.

-      {loggedIn || <LoginForm className={classes.form} />}
+      {!loggedIn && <LoginForm className={classes.form} />}

18-19: Mark decorative SVG as hidden from assistive tech

If the assistant icon conveys no extra meaning, hide it from screen readers.

-      <AssistantIcon width={48} height={40} />
+      <AssistantIcon width={48} height={40} aria-hidden="true" focusable="false" />
packages/doom/src/global/Intelligence/AIAssistant/Preamble/LoginForm/index.tsx (1)

37-44: Optional: guard localStorage for SSR

If this renders server-side, localStorage access will throw. A simple typeof window check avoids that.

-  const [origin, setOrigin] = useState(() => {
-    let origin = localStorage.getItem(CLOUD_AUTH_ORIGIN_KEY)
+  const [origin, setOrigin] = useState(() => {
+    if (typeof window === 'undefined') return CLOUD_AUTH_ORIGIN_VALUES[0]
+    let origin = window.localStorage.getItem(CLOUD_AUTH_ORIGIN_KEY)
     if (origin == null || !CLOUD_AUTH_ORIGIN_VALUES.includes(origin)) {
       origin = CLOUD_AUTH_ORIGIN_VALUES[0]
-      localStorage.setItem(CLOUD_AUTH_ORIGIN_KEY, origin)
+      window.localStorage.setItem(CLOUD_AUTH_ORIGIN_KEY, origin)
     }
     return origin
   })
packages/doom/src/global/Intelligence/AIAssistant/Preamble/CaptchaInput/index.tsx (1)

40-45: Make captcha image refresh keyboard-accessible

Clickable img is not reachable by keyboard. Add role, tabIndex, and key handler.

           <img
             className="captcha-input__captcha"
             src={captcha}
-            onClick={onRefresh}
+            onClick={onRefresh}
+            role="button"
+            tabIndex={0}
+            onKeyDown={(e) => {
+              if (e.key === 'Enter' || e.key === ' ') onRefresh()
+            }}
             alt={t('captcha')}
           />
packages/doom/src/global/Intelligence/AIAssistant/utils.ts (2)

17-17: Annotate return type for stronger contracts.

-export function parseStreamContent(text: string) {
+export function parseStreamContent(
+  text: string,
+): { refDocs: RefDoc[]; thinkingProcess: string | null; content: string } {

7-10: Unicode decoding is OK; consider surrogate-pair safety and optional broader escapes.

Current approach is fine for \uXXXX; if needed, extend to handle escaped UTF-16 surrogate pairs explicitly.

packages/doom/src/global/Intelligence/AIAssistant/ResizableUserInput/index.tsx (3)

94-104: Name layout constants and clarify row math.

-  const inputHeight = useMemo(
-    () => Math.min(Math.max(textLines, 3), 8) * 20,
-    [textLines],
-  )
+  const MIN_ROWS = 3
+  const MAX_ROWS = 8
+  const LINE_HEIGHT_PX = 20
+  const inputHeight = useMemo(
+    () => Math.min(Math.max(textLines, MIN_ROWS), MAX_ROWS) * LINE_HEIGHT_PX,
+    [textLines],
+  )

106-114: Honor placeholder prop; add basic a11y.

Prefer provided placeholder; expose aria-invalid and maxLength to assist UX.

-      <textarea
-        placeholder={t('ai_assistant_placeholder')}
+      <textarea
+        placeholder={placeholder ?? t('ai_assistant_placeholder')}
         value={innerValue}
         onChange={handleChange}
         onKeyDown={onKeyDown}
         style={inputStyle}
+        aria-invalid={maxCharsExceeded || undefined}
+        maxLength={MAX_CHARS_LIMIT}
       />

115-119: Make send icon accessible and non-interactive when disabled.

Expose button semantics and prevent clicks when disabled.

-        <SendIcon
-          className={clsx(classes.send, isSendDisabled && classes.disabled)}
-          onClick={handleSend}
-        />
+        <SendIcon
+          role="button"
+          aria-disabled={isSendDisabled}
+          tabIndex={isSendDisabled ? -1 : 0}
+          className={clsx(classes.send, isSendDisabled && classes.disabled)}
+          onClick={isSendDisabled ? undefined : handleSend}
+          onKeyDown={(e) => !isSendDisabled && e.key === 'Enter' && handleSend()}
+        />
packages/doom/src/global/Intelligence/AIAssistant/Preamble/FocusInput/index.tsx (2)

20-21: Sync ‘active’ with external value changes.

If value is controlled and changed programmatically, active may desync.

   const [active, setActive] = useState(!!value)
   const [focus, setFocus] = useState(false)
+  useEffect(() => {
+    setActive(!!value)
+  }, [value])

47-49: Add accessibility label to the underlying input.

Overlay placeholders aren’t read by screen readers. Provide aria-label.

-      <Component onFocus={handleFocus} onBlur={handleBlur} {...props} />
+      <Component
+        aria-label={placeholder}
+        onFocus={handleFocus}
+        onBlur={handleBlur}
+        {...props}
+      />
packages/doom/styles/ai-assistant.module.scss (1)

9-10: Drop unnecessary calc(); use min() directly.

Pure min() is simpler and equivalent here.

-  width: calc(min(100vw, 440px));
-  height: calc(min(100vh, 700px));
+  width: min(100vw, 440px);
+  height: min(100vh, 700px);
packages/doom/src/global/Intelligence/AIAssistant/Preamble/Radio/RadioGroup.tsx (1)

35-35: Don’t mutate prop variables

Avoid name ??= id. Use a derived const and pass groupName to context.

Also applies to: 56-60

packages/doom/src/global/Intelligence/AIAssistant/Preamble/LoginForm/types.ts (1)

8-13: Confirm numeric fields’ types

If the API returns seconds as numbers, prefer number for expiresIn/refreshExpiresIn to avoid downstream parsing.

packages/doom/src/global/Intelligence/AIAssistant/Preamble/FormItem/index.tsx (1)

73-75: Minor i18n spacing

Add a separator between label and required tip to avoid concatenation.

Apply:

-          {label || t('current_field')}
-          {t('field_required')}
+          {(label || t('current_field')) + ' '}
+          {t('field_required')}
packages/doom/src/global/Intelligence/context.tsx (2)

19-19: Prefer useContext over experimental use

Unless you’re on a React build that supports use(Context) on the client, switch to useContext(CloudAuthContext) for compatibility.

Apply:

-import { type ReactNode, createContext, use, useMemo, useState } from 'react'
+import { type ReactNode, createContext, useContext, useMemo, useState } from 'react'
@@
-export const useCloudAuth = () => use(CloudAuthContext)
+export const useCloudAuth = () => useContext(CloudAuthContext)

21-34: Guard localStorage for SSR

If this module can be imported server-side, add a window check to avoid ReferenceErrors.

Apply:

 const getCloudAuth = (): CloudAuth | null => {
-  const origin = localStorage.getItem(CLOUD_AUTH_ORIGIN_KEY)
-  const token = localStorage.getItem(CLOUD_AUTH_TOKEN_KEY)
+  if (typeof window === 'undefined') return null
+  const origin = localStorage.getItem(CLOUD_AUTH_ORIGIN_KEY)
+  const token = localStorage.getItem(CLOUD_AUTH_TOKEN_KEY)
packages/doom/src/global/Intelligence/AIAssistant/index.tsx (4)

96-100: Guard header username and session creation with loggedIn

Avoid non-null assertions; if usage changes, this prevents runtime errors.

Apply:

-          headers: { username: authInfo!.detail!.user.name },
+          headers: { username: authInfo?.detail?.user.name ?? '' },

And early-return in onSend_ if not loggedIn.


61-71: Optional: avoid dangling timeouts

Store and clear the timeout on unmount to prevent leaks in long sessions.

Apply:

   const flushMessages = useMemoizedFn(
     (setMessagesAction: (messages: ChatMessage[]) => ChatMessage[]) => {
       setMessages(setMessagesAction)
-      setTimeout(() => {
+      const tid = setTimeout(() => {
         const chatEl = chatRef.current
         if (!chatEl) {
           return
         }
         chatEl.scrollTop = chatEl.scrollHeight
       }, 200)
     },
   )
+  useEffect(() => () => clearTimeout?.(tid as any), [])

22-26: onCleanup is unused

Either remove it from props or invoke it on close/unmount.

Apply (unmount cleanup):

+  useEffect(() => () => { onCleanup?.() }, [onCleanup])

Also applies to: 168-207


104-117: Defensive stream handling

res.body may be null/non-iterable in some environments. Add a guard.

Apply:

-    const res = await xfetch('/smart/api/smart_answer', {
+    const res = await xfetch('/smart/api/smart_answer', {
       type: null,
       method: ApiMethod.POST,
       body: {
         input_text: content,
         session_id: sessionId,
       },
     })
-
-    textDecoder ??= new TextDecoder()
-
-    let text = ''
-
-    for await (const chunk_ of res.body! as unknown as AsyncIterable<Uint8Array>) {
+    const body = res.body as unknown as AsyncIterable<Uint8Array> | null
+    if (!body) throw new Error('Empty stream body')
+    textDecoder ??= new TextDecoder()
+    let text = ''
+    for await (const chunk_ of body) {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 63c2b51 and 31df25e.

⛔ Files ignored due to path filters (9)
  • packages/doom/assets/alert.svg is excluded by !**/*.svg
  • packages/doom/assets/angle-down.svg is excluded by !**/*.svg
  • packages/doom/assets/assistant.svg is excluded by !**/*.svg
  • packages/doom/assets/close.svg is excluded by !**/*.svg
  • packages/doom/assets/logout.svg is excluded by !**/*.svg
  • packages/doom/assets/new-chat.svg is excluded by !**/*.svg
  • packages/doom/assets/question-circle.svg is excluded by !**/*.svg
  • packages/doom/assets/send.svg is excluded by !**/*.svg
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (46)
  • .changeset/shaggy-garlics-divide.md (1 hunks)
  • .github/workflows/pkg-pr-new.yml (1 hunks)
  • package.json (2 hunks)
  • packages/doom/package.json (4 hunks)
  • packages/doom/src/cli/load-config.ts (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/Chat/ChatRefDocs/index.tsx (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/Chat/ThinkingProcess/index.tsx (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/Chat/index.tsx (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/Preamble/ApiErrorAlert/index.tsx (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/Preamble/Button/index.tsx (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/Preamble/CaptchaInput/index.tsx (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/Preamble/FocusInput/index.tsx (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/Preamble/FormItem/index.tsx (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/Preamble/Input/index.tsx (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/Preamble/LoginForm/index.tsx (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/Preamble/LoginForm/types.ts (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/Preamble/LoginForm/utils.ts (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/Preamble/Radio/Radio.tsx (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/Preamble/Radio/RadioGroup.tsx (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/Preamble/Radio/context.ts (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/Preamble/Radio/index.ts (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/Preamble/index.tsx (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/Preamble/types.ts (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/ResizableUserInput/index.tsx (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/Thinking.tsx (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/index.tsx (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/types.ts (1 hunks)
  • packages/doom/src/global/Intelligence/AIAssistant/utils.ts (1 hunks)
  • packages/doom/src/global/Intelligence/constants.ts (1 hunks)
  • packages/doom/src/global/Intelligence/context.tsx (1 hunks)
  • packages/doom/src/global/Intelligence/index.tsx (1 hunks)
  • packages/doom/src/global/Intelligence/types.ts (1 hunks)
  • packages/doom/src/global/Intelligence/utils.ts (1 hunks)
  • packages/doom/src/global/VersionsNav/NavMenuSingleItem.tsx (1 hunks)
  • packages/doom/src/runtime/hooks/index.ts (1 hunks)
  • packages/doom/src/runtime/hooks/useInterval.ts (1 hunks)
  • packages/doom/src/runtime/hooks/useMemoizedFn.ts (1 hunks)
  • packages/doom/src/runtime/translation.ts (3 hunks)
  • packages/doom/styles/ai-assistant.module.scss (1 hunks)
  • packages/doom/styles/chat-ref-docs.module.scss (1 hunks)
  • packages/doom/styles/chat.module.scss (1 hunks)
  • packages/doom/styles/global.scss (1 hunks)
  • packages/doom/styles/intelligence.module.scss (1 hunks)
  • packages/doom/styles/intelligence.scss (1 hunks)
  • packages/doom/styles/preamble.module.scss (1 hunks)
  • packages/doom/styles/resizable-user-input.module.scss (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-05-26T09:09:21.339Z
Learnt from: JounQin
PR: alauda/doom#30
File: src/runtime/components/K8sCrd.tsx:5-5
Timestamp: 2025-05-26T09:09:21.339Z
Learning: The alauda/doom project uses yarn v4 for dependency management, which handles package exports and module resolution correctly, so imports like `rspress/core/theme` work without any ESLint errors.

Applied to files:

  • packages/doom/src/global/VersionsNav/NavMenuSingleItem.tsx
  • package.json
  • packages/doom/package.json
📚 Learning: 2025-06-09T03:10:41.010Z
Learnt from: JounQin
PR: alauda/doom#75
File: src/cli/load-config.ts:4-7
Timestamp: 2025-06-09T03:10:41.010Z
Learning: The alauda/doom project uses yarn v4 as the package manager, not npm. Always reference yarn commands when suggesting package management operations.

Applied to files:

  • package.json
📚 Learning: 2025-05-29T16:25:28.086Z
Learnt from: JounQin
PR: alauda/doom#40
File: src/plugins/sitemap/index.ts:7-7
Timestamp: 2025-05-29T16:25:28.086Z
Learning: In rspress/shared v2.0.0-beta.8, the '/logger' export is available in the package exports field, so imports like `import { logger } from 'rspress/shared/logger'` are valid even if ESLint shows resolution errors. This is used throughout the codebase in files like src/cli/translate.ts, src/cli/load-config.ts, src/utils/git.ts, and src/plugins/sitemap/index.ts.

Applied to files:

  • packages/doom/src/runtime/hooks/index.ts
🧬 Code graph analysis (21)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/LoginForm/types.ts (1)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/types.ts (1)
  • ApiError (15-18)
packages/doom/src/global/Intelligence/AIAssistant/Thinking.tsx (2)
packages/doom/src/runtime/hooks/useTranslation.ts (1)
  • useTranslation (9-16)
packages/doom/src/runtime/hooks/useInterval.ts (1)
  • useInterval (3-24)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/LoginForm/utils.ts (1)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/LoginForm/types.ts (1)
  • PasswordPubKey (3-6)
packages/doom/src/global/Intelligence/AIAssistant/Chat/ChatRefDocs/index.tsx (3)
packages/doom/src/global/Intelligence/AIAssistant/types.ts (1)
  • RefDoc (3-8)
packages/doom/src/runtime/hooks/useTranslation.ts (1)
  • useTranslation (9-16)
packages/doom/src/runtime/components/_X.tsx (1)
  • X (3-3)
packages/doom/src/global/Intelligence/constants.ts (1)
packages/doom/src/global/Intelligence/types.ts (1)
  • CloudAuthRegion (36-39)
packages/doom/src/global/Intelligence/AIAssistant/index.tsx (10)
packages/doom/src/global/Intelligence/context.tsx (2)
  • CloudAuth (7-10)
  • useCloudAuth (19-19)
packages/doom/src/global/Intelligence/types.ts (1)
  • AuthInfo (30-34)
packages/doom/src/runtime/hooks/useTranslation.ts (1)
  • useTranslation (9-16)
packages/doom/src/global/Intelligence/AIAssistant/types.ts (1)
  • ChatMessage (10-16)
packages/doom/src/runtime/hooks/useMemoizedFn.ts (1)
  • useMemoizedFn (3-15)
packages/doom/src/global/Intelligence/AIAssistant/Thinking.tsx (1)
  • Thinking (9-22)
packages/doom/src/global/Intelligence/AIAssistant/utils.ts (1)
  • parseStreamContent (17-46)
packages/doom/src/global/Intelligence/AIAssistant/Chat/index.tsx (1)
  • Chat (18-37)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/index.tsx (1)
  • Preamble (13-28)
packages/doom/src/global/Intelligence/AIAssistant/ResizableUserInput/index.tsx (1)
  • ResizableUserInput (23-128)
packages/doom/src/global/Intelligence/utils.ts (1)
packages/doom/src/global/Intelligence/types.ts (2)
  • AuthInfo (30-34)
  • AuthTokenInfo (14-21)
packages/doom/src/global/Intelligence/AIAssistant/Chat/ThinkingProcess/index.tsx (2)
packages/doom/src/runtime/hooks/useTranslation.ts (1)
  • useTranslation (9-16)
packages/doom/src/runtime/components/Markdown.tsx (1)
  • Markdown (12-21)
packages/doom/src/global/Intelligence/AIAssistant/ResizableUserInput/index.tsx (2)
packages/doom/src/runtime/hooks/useTranslation.ts (1)
  • useTranslation (9-16)
packages/doom/src/runtime/hooks/useMemoizedFn.ts (1)
  • useMemoizedFn (3-15)
packages/doom/src/global/Intelligence/AIAssistant/Chat/index.tsx (4)
packages/doom/src/global/Intelligence/AIAssistant/types.ts (1)
  • ChatMessage (10-16)
packages/doom/src/global/Intelligence/AIAssistant/Chat/ThinkingProcess/index.tsx (1)
  • ThinkingProcess (7-15)
packages/doom/src/global/Intelligence/AIAssistant/Chat/ChatRefDocs/index.tsx (1)
  • ChatRefDocs (15-57)
packages/doom/src/runtime/components/Markdown.tsx (1)
  • Markdown (12-21)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/ApiErrorAlert/index.tsx (2)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/types.ts (1)
  • ApiError (15-18)
packages/doom/src/runtime/hooks/useTranslation.ts (1)
  • useTranslation (9-16)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/FormItem/index.tsx (1)
packages/doom/src/runtime/hooks/useTranslation.ts (1)
  • useTranslation (9-16)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/LoginForm/index.tsx (13)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/LoginForm/types.ts (3)
  • LoginError (29-30)
  • PasswordPubKey (3-6)
  • LoginResponse (8-13)
packages/doom/src/runtime/hooks/useTranslation.ts (1)
  • useTranslation (9-16)
packages/doom/src/global/Intelligence/constants.ts (3)
  • CLOUD_AUTH_ORIGIN_KEY (5-5)
  • CLOUD_AUTH_ORIGIN_VALUES (26-28)
  • CLOUD_AUTH_ORIGINS (30-30)
packages/doom/src/runtime/hooks/useMemoizedFn.ts (1)
  • useMemoizedFn (3-15)
packages/doom/src/global/Intelligence/context.tsx (1)
  • useCloudAuth (19-19)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/LoginForm/utils.ts (1)
  • cryptoPassword (11-14)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/FormItem/index.tsx (1)
  • FormItem (26-79)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/Radio/RadioGroup.tsx (1)
  • RadioGroup (22-69)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/Radio/Radio.tsx (1)
  • Radio (11-38)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/ApiErrorAlert/index.tsx (1)
  • ApiErrorAlert (12-40)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/FocusInput/index.tsx (1)
  • FocusInput (10-51)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/CaptchaInput/index.tsx (1)
  • CaptchaInput (17-52)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/Button/index.tsx (1)
  • Button (12-34)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/Radio/Radio.tsx (1)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/Radio/context.ts (2)
  • RadioGroupContext (3-7)
  • RadioGroupContext (9-9)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/Radio/RadioGroup.tsx (1)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/Radio/context.ts (2)
  • RadioGroupContext (3-7)
  • RadioGroupContext (9-9)
packages/doom/src/global/Intelligence/index.tsx (5)
packages/doom/src/runtime/hooks/useTranslation.ts (2)
  • useTranslation (9-16)
  • useLang (7-7)
packages/doom/src/runtime/hooks/useMemoizedFn.ts (1)
  • useMemoizedFn (3-15)
packages/doom/src/global/Intelligence/context.tsx (1)
  • CloudAuthProvider (36-58)
packages/doom/src/global/Intelligence/AIAssistant/index.tsx (1)
  • AIAssistant (34-208)
packages/doom/src/shared/constants.ts (1)
  • ACP_BASE (1-1)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/index.tsx (2)
packages/doom/src/runtime/hooks/useTranslation.ts (1)
  • useTranslation (9-16)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/LoginForm/index.tsx (1)
  • LoginForm (34-189)
packages/doom/src/global/Intelligence/AIAssistant/utils.ts (1)
packages/doom/src/global/Intelligence/AIAssistant/types.ts (1)
  • RefDoc (3-8)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/CaptchaInput/index.tsx (3)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/Input/index.tsx (2)
  • InputProps (4-8)
  • Input (10-24)
packages/doom/src/runtime/hooks/useTranslation.ts (1)
  • useTranslation (9-16)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/FormItem/index.tsx (1)
  • FormItem (26-79)
packages/doom/src/global/Intelligence/context.tsx (3)
packages/doom/src/global/Intelligence/types.ts (1)
  • AuthInfo (30-34)
packages/doom/src/global/Intelligence/constants.ts (2)
  • CLOUD_AUTH_ORIGIN_KEY (5-5)
  • CLOUD_AUTH_TOKEN_KEY (6-6)
packages/doom/src/global/Intelligence/utils.ts (2)
  • getAuthInfoFromToken (13-39)
  • setLocalStorage (5-11)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/FocusInput/index.tsx (1)
packages/doom/src/global/Intelligence/AIAssistant/Preamble/Input/index.tsx (2)
  • InputProps (4-8)
  • Input (10-24)
🔇 Additional comments (28)
packages/doom/src/global/VersionsNav/NavMenuSingleItem.tsx (1)

6-7: Ignore .ts-extension removal suggestion

Your repository is using NodeNext resolution with

"compilerOptions": {
  "module": "NodeNext",
  "moduleResolution": "NodeNext",
  "rewriteRelativeImportExtensions": true,
  "verbatimModuleSyntax": true,
  
}

Under these settings, retaining .ts in import paths is intentional: TypeScript rewrites import "./foo.ts"import "./foo.js" in the emitted ESM, ensuring Node can resolve the files. Swapping to extensionless imports would leave them unmodified and break runtime loading.

A scan confirms dozens of .ts imports across both packages/doom and packages/export, indicating a consistent, project-wide pattern:

  • doom/src/global/VersionsNav/NavMenuSingleItem.tsx: import from '../../shared/index.ts'
  • doom/src/shared/helpers.ts: import from './constants.ts', './types.ts'
  • …and many more.

Because this is by design and necessary for correct bundling and Node ESM support, you can safely disregard the recommendation to drop .ts extensions here.

Likely an incorrect or invalid review comment.

.changeset/shaggy-garlics-divide.md (1)

1-5: Changeset looks good; scope and bump match the feature size.

Minor bump for @alauda/doom with a concise summary is appropriate.

.github/workflows/pkg-pr-new.yml (1)

35-35: Enable compact output — LGTM.

The added --compact flag should reduce CI noise without changing behavior.

packages/doom/src/cli/load-config.ts (1)

104-114: Confirm Algolia keys are search-only and intended to be public.

If these are search-only keys, embedding is fine; otherwise move to env/secret injection.

packages/doom/package.json (2)

18-24: Adding assets/styles exports — good call.

This enables clean imports like @alauda/doom/styles/… and asset resolution; files already whitelisted.


50-51: Sanity-check new runtime deps for size and compatibility

react-tooltip@^5.29.1
• Peer-requires React ≤18 by default. The Doom plugin itself doesn’t declare React, so the host app (via @rspress/core or consumer) must supply a compatible version.
• Import sites in this package:
• packages/doom/src/global/Intelligence/index.tsx
• packages/doom/src/global/Intelligence/AIAssistant/index.tsx
• packages/doom/src/global/Intelligence/AIAssistant/Preamble/LoginForm/index.tsx
→ Confirm that the application’s React version is ≤18. If you’re on React 19, either pin react-tooltip to a 6.x prerelease or document the mismatch.

openai@^5.16.0
• Only imported in the CLI (packages/doom/src/cli/translate.ts). ESM payload size isn’t tree-shaken in Node, but you can defer loading to reduce CLI startup cost.
→ Consider switching the top-level import to a dynamic await import('openai') inside the translate command handler.

jsencrypt@^3.5.4 & ab64@^0.1.6
• Pulled into the browser bundle via:
• packages/doom/src/global/Intelligence/AIAssistant/Preamble/LoginForm/utils.ts (JSEncrypt)
• packages/doom/src/global/Intelligence/utils.ts (ab64)
→ These crypto utilities can add ~20–40 KB gzipped each. Lazy-load them in the auth/login flow or isolate into a separate chunk so they don’t bloat your initial UI bundle.

package.json (1)

15-16: Pre-clean build is a good hardening.

yarn clean && tsc -b reduces stale artifacts in multi-project builds.

packages/doom/src/global/Intelligence/AIAssistant/types.ts (1)

10-14: Consider future-proofing roles and serializability.

  • If tools/system messages may appear later, widen role to include 'system' | 'tool'.
  • ReactNode content can’t be serialized; if messages will be persisted, keep a parallel string field.

Would you like a follow-up patch adding role: 'user' | 'assistant' | 'system' | 'tool' and contentText?: string?

packages/doom/styles/preamble.module.scss (2)

8-10: Verify CSS Modules usage of the state class.

Selector compiles as .preamble.logged-in{...}; you must apply both classes. Ensure TSX uses styles.preamble plus styles['logged-in'] (bracket access required due to hyphen).


1-11: LGTM: clean, minimal layout rules.

Flex column, centered alignment, and state override read well.

packages/doom/src/runtime/hooks/useMemoizedFn.ts (1)

3-15: Solid implementation; stable identity with latest ref.

Pattern matches industry-standard approach; lint disables are appropriate.

packages/doom/src/runtime/hooks/index.ts (1)

1-5: All .ts extension imports are intentional and supported by your TypeScript configuration

– A repository-wide search confirms numerous import/export statements ending in .ts across both packages/doom and packages/export, including your runtime/hooks/index.ts file.
tsconfig.base.json is set to "module": "NodeNext", "moduleResolution": "NodeNext", and "rewriteRelativeImportExtensions": true, ensuring these .ts extensions are accepted in source and rewritten to .js in the emitted ESM output.

No modifications are necessary.

packages/doom/src/runtime/translation.ts (2)

66-66: Strong typing for i18n shape—nice

Deriving Translation from typeof en and typing other locales against it + exporting a stable TRANSLATIONS map is solid. This prevents missing keys at compile time.

Also applies to: 193-193


22-25: Refactor punctuation translations to remove embedded spaces

We discovered that the only call site relying on the trailing space in t('colon') is here:

  • packages/doom/src/global/Intelligence/AIAssistant/Chat/ChatRefDocs/index.tsx:29
    {t('referenced_doc_links') + t('colon')}

Removing the space from the translation entries (exclamation: '!', semicolon: ';', period: '.', colon: ':') will break this line (it will render "Referenced doc links:" without a space).

Options:

  • Refactor translations: strip trailing spaces and update call sites to add spaces explicitly, for example:
    {`${t('referenced_doc_links')}: `}
  • Or document/guard in translation.ts that these four keys include a trailing space and should not be used in JSX expressions without trimming.

Please verify all usage of these punctuation keys before removing their spaces to avoid layout regressions.

packages/doom/styles/chat.module.scss (1)

15-19: Verify layout math for assistant vs. user bubbles.

width: calc(100% - 36px) plus .assistant .content { margin-left: 12px; } could produce asymmetric gutters depending on icon width. Please confirm visuals across breakpoints.

Also applies to: 58-61

packages/doom/src/global/Intelligence/AIAssistant/Preamble/LoginForm/utils.ts (1)

1-1: No changes required: import { JSEncrypt } is valid
The jsencrypt package’s ESM entrypoint (lib/index.js) both re-exports JSEncrypt as a named export and as the default export, so the existing

import { JSEncrypt } from 'jsencrypt'

is correct and will work as expected.

• Location needing no change:

  • packages/doom/src/global/Intelligence/AIAssistant/Preamble/LoginForm/utils.ts:1
packages/doom/src/global/Intelligence/AIAssistant/Chat/ThinkingProcess/index.tsx (1)

7-15: LGTM — simple, clear component.

Label + Markdown is straightforward; translation key usage looks correct.

packages/doom/styles/intelligence.module.scss (1)

1-11: Global react-tooltip theming: confirm intended global scope

You’re overriding react-tooltip CSS variables at :root for the entire site. Confirm no other tooltips rely on different colors. If scoping is needed later, consider toggling via a host class rather than permanent globals.

packages/doom/src/global/Intelligence/utils.ts (2)

5-11: LocalStorage helper is clean

Nullish -> remove, otherwise set. Reads well.


29-38: Mapping looks correct

tenant_type/id and user fields are mapped as expected; sensible username fallback.

packages/doom/src/global/Intelligence/AIAssistant/Preamble/ApiErrorAlert/index.tsx (1)

3-3: Import extension consistency

You import from '../types.js' here, but other files (e.g., index.tsx) import '.ts'. Ensure your bundler/tsconfig supports mixed extensions; otherwise align to one style.

packages/doom/src/global/Intelligence/index.tsx (2)

48-54: Gating to English only: confirm intent

You have translations for zh/ru in this PR, but the gate is lang === 'en'. Is this intentional for a phased rollout?

If not intentional, a simple relaxation:

-  if (
-    lang !== 'en' ||
+  if (
+    !['en', 'zh', 'ru'].includes(lang) ||
     !ALLOWED_DOMAINS.has(location.hostname) ||
     virtual.userBase !== ACP_BASE
   ) {
-    return
+    return null
   }

59-63: Client-only rendering LGTM

Wrapping with NoSSR avoids SSR access to window/location and localStorage.

packages/doom/src/global/Intelligence/AIAssistant/Preamble/Radio/Radio.tsx (1)

11-16: Confirm React version for use(Context)

This relies on React’s use() for context. Ensure the app runs on a React version where this API is stable across your targets (including SSR).

Would you like me to scan package.json/lockfiles to confirm the React version used across packages?

packages/doom/src/global/Intelligence/AIAssistant/Preamble/CaptchaInput/index.tsx (1)

4-6: Import path extensions: ensure resolver compatibility

Mixed usage of .tsx and .js extensions across the preamble components can bite certain TS/ESM setups. Consider extensionless imports for local files (preferred) or verify tsconfig moduleSuffixes/allowImportingTsExtensions handle this.

Want me to scan tsconfig(es) to confirm the resolver settings and propose a repo-wide codemod?

packages/doom/src/global/Intelligence/AIAssistant/Chat/index.tsx (1)

28-31: Sanitization Confirmed – No Changes Required

The Markdown component in packages/doom/src/runtime/components/Markdown.tsx already imports and applies rehype-sanitize in its rehypePlugins array, ensuring that any untrusted strings are properly sanitized before rendering.

• File: packages/doom/src/runtime/components/Markdown.tsx
import rehypeSanitize from 'rehype-sanitize'
const rehypePlugins = [rehypeRaw, rehypeSanitize]

packages/doom/src/global/Intelligence/AIAssistant/Preamble/FocusInput/index.tsx (1)

6-8: Consider forwardRef if refs must reach the actual input.

InputProps includes ref, but without forwardRef on both Component and FocusInput, consumer refs won’t work.

Would you like a follow-up patch to convert Input and FocusInput to forwardRef and update call sites?

Also applies to: 10-19

packages/doom/src/global/Intelligence/AIAssistant/Preamble/LoginForm/types.ts (1)

8-13: Types look good

Type-only surface is clean and import is type-only. LGTM.

@JounQin JounQin merged commit 1163f0b into main Aug 27, 2025
16 checks passed
@JounQin JounQin deleted the feat/intelligence branch August 27, 2025 05:22
github-actions bot pushed a commit that referenced this pull request Aug 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants