Skip to content

feat(condo): DOMA-12967 add streaming in chat with condo #7859

Open
tolmachev21 wants to merge 7 commits into
mainfrom
feat/condo/DOMA-12967/chat-with-condo-streaming
Open

feat(condo): DOMA-12967 add streaming in chat with condo #7859
tolmachev21 wants to merge 7 commits into
mainfrom
feat/condo/DOMA-12967/chat-with-condo-streaming

Conversation

@tolmachev21

@tolmachev21 tolmachev21 commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features
    • AI chat now renders with turn-aware scrolling, smoother incremental answer reveal, and animated follow-up suggestions.
    • AI chat can resume an in-progress assistant response after reopening.
  • Bug Fixes
    • Improved AI chat layout to better handle the fixed header/input chrome without clipped content.
    • Upgraded AI input notifications to clearer, accessible inline status panels.
    • Refined assistant output so tool-trace artifacts are removed from the displayed text.
    • Messaging gap replay now more reliably covers missed messages on re-subscribe.
  • Documentation
    • Clarified JetStream gap-replay startTime behavior.
  • Tests
    • Added Jest coverage for tool-trace stripping and display behavior.
  • Chores
    • Updated the pinned .helm submodule revision.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

AI assistant execution, streamed answer presentation, chat turns, scrolling, suggestions, notifications, consuming form state, messaging replay timestamps, and the Helm submodule pointer were updated.

AI assistant flows

Layer / File(s) Summary
Answer presentation and buffering
apps/condo/domains/ai/utils/*
Assistant tool traces and suggestion markers are removed from display text, completed answers expose parsed suggestions, and streamed output is progressively revealed.
Run-guarded AI flow completion
apps/condo/domains/ai/hooks/useAIFlow.tsx
Streaming and polling share typed completion, cancellation, timeout, resume, and run-invalidation handling.
Chat turns and scrollport execution
apps/condo/domains/ai/components/AIChat/*, apps/condo/domains/ai/components/AIOverlay/*
Chat execution creates user/assistant turns, resumes saved tasks, and uses active-turn scrollport sizing.
Message and suggestion presentation
apps/condo/domains/ai/components/AIChat/AIChatMessage*, apps/condo/domains/ai/components/AIChat/AIChatSuggestions*, apps/condo/domains/ai/components/AIChat/AIChatThinkingStatus*, apps/condo/lang/*
Messages use dedicated styling, animated thinking status, reusable suggestions, and updated loading translations.
AI notification consumers
apps/condo/domains/ai/components/AIInputNotification*, apps/condo/domains/common/components/Comments/*, apps/condo/domains/news/components/NewsForm/InputStep/InputStepForm.tsx
Notifications render accessible result panels and consuming forms synchronize loading, results, errors, and close behavior.

Messaging subscription replay

Layer / File(s) Summary
JetStream replay cursor handling
packages/messaging/hooks/useMessagingSubscription.ts, packages/messaging/README.md
Subscriptions always send startTime, reset cursors when topics change, include resubscribeDelay in dependencies, and document replay behavior.

Helm reference update

Layer / File(s) Summary
Helm submodule pointer
.helm
The pinned Helm submodule commit was advanced.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Suggested labels: ✋🙂 Review please, 🐘 BIG

Suggested reviewers: toplenboren, alllex202, nomerdvadcatpyat

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant AIChat
  participant useAIFlow
  participant AnswerDisplayBuffer
  participant AIChatMessage
  User->>AIChat: Send message or select suggestion
  AIChat->>useAIFlow: Execute or resume AI task
  useAIFlow->>AnswerDisplayBuffer: Append streamed answer chunks
  useAIFlow-->>AIChat: Return live and final results
  AIChat->>AIChatMessage: Update assistant turn
  AIChatMessage-->>AIChat: Render suggestions
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: adding streaming behavior to the Condo AI chat flow.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/condo/DOMA-12967/chat-with-condo-streaming

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

apps/condo/domains/ai/components/AIInputNotification.module.css

Parsing error: Declaration or statement expected.


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

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 59ae7913e4

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread apps/condo/domains/news/components/NewsForm/InputStep/InputStepForm.tsx Outdated
Comment thread apps/condo/domains/ai/utils/aiAnswerPresenter.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/condo/domains/ai/components/AIChat/AIChat.tsx (1)

186-217: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Do not persist messages until the new session has finished loading.

On an aiSessionId change, the loading effect schedules setMessages, but the persistence effect still runs with the previous render’s messages. Since messages.length >= 0 is always true, it can write the previous session’s history under the new session ID.

Track the hydrated session ID and only save when it matches the current aiSessionId.

Also applies to: 278-282

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/condo/domains/ai/components/AIChat/AIChat.tsx` around lines 186 - 217,
Track the session ID successfully hydrated by the loading effect around the
aiSessionId change, and update it only after the appropriate history has been
loaded or cleared. In the persistence effect, require the hydrated session ID to
match the current aiSessionId before saving, rather than relying on
messages.length, so previous-session messages are never written under the new
session.
🧹 Nitpick comments (2)
apps/condo/domains/ai/components/AIChat/AIChat.tsx (2)

94-99: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace the any ref with the concrete input handle type.

Only .focus() is used here; typing the exposed AIChatInput handle prevents incompatible ref assignments.

As per coding guidelines, “In TypeScript files, avoid explicit any unless necessary.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/condo/domains/ai/components/AIChat/AIChat.tsx` around lines 94 - 99,
Replace the any type on inputRef in the AIChat component with the concrete
AIChatInput handle type, preserving the existing ref behavior and focus usage.
Import or reuse the existing AIChatInput type exposed by the input component so
incompatible ref assignments are rejected.

Source: Coding guidelines


234-234: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use structured Pino logging for the new error paths.

Replace these console.error calls with the project logger and fields such as { msg, err }.

As per coding guidelines, “Use structured Pino logging with { msg, entityId, entity, count, status, err, data }.”

Also applies to: 274-274, 527-527

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/condo/domains/ai/components/AIChat/AIChat.tsx` at line 234, Replace the
console.error calls in the AIChat error paths, including the handlers around
resuming the AI flow and the locations at the referenced lines, with the
project’s structured Pino logger. Preserve each existing error context in a
descriptive msg field and pass the caught error through the err field.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/condo/domains/ai/components/AIChat/AIChat.tsx`:
- Around line 112-140: Throttle chat-history persistence triggered by streaming
updates in the AIChat message persistence logic, including the related block
around the task-ID handling. Debounce or otherwise batch full-history
serialization and local-storage writes so chunks do not synchronously persist
every update, while retaining an immediate write for the task ID required to
resume the task.
- Around line 161-163: Update the assistant answer fallback in the
parseAssistantAnswer call within the AIChat flow so empty or whitespace-only
answer values use the localized noResponseMessage, not only nullish values.
Preserve the existing parsing and suggestion handling for non-empty answers.

In `@apps/condo/domains/ai/components/AIInputNotification.module.css`:
- Around line 7-19: Update the .panel notification overlay to prevent it from
extending beyond the viewport: use collision-aware positioning where supported,
or add a viewport-constrained maximum height with vertical scrolling while
preserving its upward placement and existing styling.

In `@apps/condo/domains/ai/components/AIInputNotification.tsx`:
- Around line 103-110: Add a localized accessible name to the icon-only Button
in AIInputNotification, using the component’s existing i18n/localization
mechanism and preserving the current onClick and Close icon behavior.

In `@apps/condo/domains/ai/hooks/useAIFlow.tsx`:
- Around line 294-311: Update the AI flow around startPollingForResult and its
streaming-to-polling fallback to use a single run-level timeout deadline.
Preserve the original deadline when polling begins, calculate the remaining
budget, and pass that remaining duration to polling so it cannot wait beyond the
overall timeout, including the initial polling delay.
- Around line 216-221: Update failFlow to dispose or cancel the active
display/reveal buffer before calling setError, ensuring any pending onFlush
callback cannot restore partial PROCESSING data after the terminal error. Keep
the existing state resets and error publication behavior unchanged.
- Around line 167-180: The invalidateActiveWork callback only settles the
streaming completion waiter; update the polling flow around
startPollingForResult to track and resolve its pending completion when
invalidation occurs. Ensure both execute and resume promises settle with the
cancellation result, including when an in-flight poll observes an inactive run,
while preserving the existing timer cleanup and run-id behavior.

In `@apps/condo/domains/ai/utils/aiAnswerPresenter.ts`:
- Line 9: Replace CALLING_SERVICE_REGEX with a pattern that matches only the
exact structured tool-trace grammar, using its required delimiters or metadata
as the boundary rather than Cyrillic-character exclusion. Preserve legitimate
English and Spanish sentences beginning with capitalized “Calling,” while
continuing to remove valid tool traces.

In `@packages/messaging/hooks/useMessagingSubscription.ts`:
- Around line 128-131: Refactor the subscription replay flow in
useMessagingSubscription so initial replay uses a server-calculated relative
replaySkewMs instead of a client-generated Date.now timestamp. Update the
backend relay contract to accept that skew and forward each message’s
authoritative JetStream sequence, then track the sequence client-side and
reconnect with startSequence set to the last received sequence plus one. Remove
reliance on lastMessageTimeRef for replay cursors to avoid clock-drift gaps and
inclusive-timestamp duplicates.

---

Outside diff comments:
In `@apps/condo/domains/ai/components/AIChat/AIChat.tsx`:
- Around line 186-217: Track the session ID successfully hydrated by the loading
effect around the aiSessionId change, and update it only after the appropriate
history has been loaded or cleared. In the persistence effect, require the
hydrated session ID to match the current aiSessionId before saving, rather than
relying on messages.length, so previous-session messages are never written under
the new session.

---

Nitpick comments:
In `@apps/condo/domains/ai/components/AIChat/AIChat.tsx`:
- Around line 94-99: Replace the any type on inputRef in the AIChat component
with the concrete AIChatInput handle type, preserving the existing ref behavior
and focus usage. Import or reuse the existing AIChatInput type exposed by the
input component so incompatible ref assignments are rejected.
- Line 234: Replace the console.error calls in the AIChat error paths, including
the handlers around resuming the AI flow and the locations at the referenced
lines, with the project’s structured Pino logger. Preserve each existing error
context in a descriptive msg field and pass the caught error through the err
field.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: ebc44f00-302e-483b-8274-297f767fd20f

📥 Commits

Reviewing files that changed from the base of the PR and between 3a4f6c5 and 59ae791.

📒 Files selected for processing (24)
  • .helm
  • apps/condo/domains/ai/components/AIChat/AIChat.module.css
  • apps/condo/domains/ai/components/AIChat/AIChat.tsx
  • apps/condo/domains/ai/components/AIChat/AIChatInput.module.css
  • apps/condo/domains/ai/components/AIChat/AIChatMessage.module.css
  • apps/condo/domains/ai/components/AIChat/AIChatMessage.tsx
  • apps/condo/domains/ai/components/AIChat/AIChatSuggestions.module.css
  • apps/condo/domains/ai/components/AIChat/AIChatSuggestions.tsx
  • apps/condo/domains/ai/components/AIChat/AIChatThinkingStatus.module.css
  • apps/condo/domains/ai/components/AIChat/AIChatThinkingStatus.tsx
  • apps/condo/domains/ai/components/AIInputNotification.module.css
  • apps/condo/domains/ai/components/AIInputNotification.tsx
  • apps/condo/domains/ai/components/AIOverlay/AIOverlay.module.css
  • apps/condo/domains/ai/hooks/useAIFlow.tsx
  • apps/condo/domains/ai/utils/aiAnswerPresenter.ts
  • apps/condo/domains/ai/utils/answerDisplayBuffer.ts
  • apps/condo/domains/common/components/Comments/CommentForm.tsx
  • apps/condo/domains/common/components/Comments/index.tsx
  • apps/condo/domains/news/components/NewsForm/InputStep/InputStepForm.tsx
  • apps/condo/lang/en/en.json
  • apps/condo/lang/es/es.json
  • apps/condo/lang/ru/ru.json
  • packages/messaging/README.md
  • packages/messaging/hooks/useMessagingSubscription.ts

Comment thread apps/condo/domains/ai/components/AIChat/AIChat.tsx Outdated
Comment thread apps/condo/domains/ai/components/AIChat/AIChat.tsx
Comment thread apps/condo/domains/ai/components/AIInputNotification.module.css
Comment thread apps/condo/domains/ai/components/AIInputNotification.tsx
Comment thread apps/condo/domains/ai/hooks/useAIFlow.tsx
Comment thread apps/condo/domains/ai/hooks/useAIFlow.tsx
Comment thread apps/condo/domains/ai/hooks/useAIFlow.tsx Outdated
Comment thread apps/condo/domains/ai/utils/aiAnswerPresenter.ts Outdated
Comment thread packages/messaging/hooks/useMessagingSubscription.ts

@toplenboren toplenboren left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Okay-ish, but please check code quality and naming of created utils


if (!savedHistory || typeof savedHistory !== 'object') {
setMessages([])
setActiveTurnUserMessageId(null)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

ActiveTurn?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, it's need for pin user message in header

}))
setMessages(historyWithDates)
setActiveTurnUserMessageId(null)
requestAnimationFrame(() => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

pls explain why do u have 2 request anmiation framce

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

First rAF need for scroll to bottom when we restore history. Second - for pin active message in header.

I add commets for both

if (lastMessage?.status === 'sending' && lastMessage?.executionAIFlowTaskId) {
resume(lastMessage.executionAIFlowTaskId)
void (async () => {
try {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why in a function?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Because it IIFE for async function. Rewrite it in async for clear

const assistantMessage: Message = {
id: uuidV4(),
content: { text: loadingLabel },
content: { text: '' },

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

is it not ... ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

All logic for sending status now in AIChatThinkingStatus

const SUGGESTIONS_BLOCK_REGEX = /\[\[SUGGESTIONS\]\]([\s\S]*?)\[\[\/SUGGESTIONS\]\]/m

const CALLING_PREFIX = 'Calling'
/** Stop before Cyrillic so "Calling ….За текущий месяц" still strips the tool line. */

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

?

return stripSuggestionsForDisplay(stripServiceToolCallLines(rawAnswer)).trimEnd()
}

export function parseAssistantAnswer (answer: string): ParsedAssistantAnswer {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

please explain why do you need this utility and why do you create it in /utils

Comment thread apps/condo/domains/ai/components/AIChat/AIChatMessage.module.css Outdated
Comment thread apps/condo/domains/ai/components/AIChat/AIChatMessage.module.css Outdated
Comment thread apps/condo/domains/ai/components/AIChat/AIChatMessage.tsx Outdated
Comment thread apps/condo/domains/ai/components/AIChat/AIChatSuggestions.module.css Outdated
Comment thread apps/condo/domains/ai/components/AIInputNotification.module.css Outdated
Comment thread apps/condo/domains/ai/components/AIInputNotification.module.css Outdated
Comment thread apps/condo/domains/ai/utils/aiAnswerPresenter.ts Outdated
Comment thread apps/condo/domains/ai/utils/aiAnswerPresenter.ts
@tolmachev21
tolmachev21 force-pushed the feat/condo/DOMA-12967/chat-with-condo-streaming branch from c26b9c4 to 9596b65 Compare July 24, 2026 08:01

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/condo/domains/ai/components/AIChat/AIChatMessage.tsx`:
- Around line 204-214: Update the suggestion key generation in AIChatMessage’s
AIChatSuggestions items mapping to include the array index alongside message.id
and suggestion, ensuring duplicate suggestion text within the same message
receives a unique key while preserving the existing animationDelayMs behavior.

In `@apps/condo/domains/ai/utils/aiAnswerPresenter.ts`:
- Around line 93-124: Refine the single-token heuristic in
isPartialToolCallTrace so a completed final-answer line such as “Calling
support.” is not classified as a partial tool call and removed by
stripServiceToolCallLines. Require the existing /^Calling\s+\S*$/ path to
exclude sentence-ending punctuation while preserving detection of genuinely
incomplete tool-call prefixes.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 91b93d14-4084-4d46-a758-0e70a4e0feb6

📥 Commits

Reviewing files that changed from the base of the PR and between 231d454 and 9596b65.

📒 Files selected for processing (27)
  • .helm
  • apps/condo/domains/ai/components/AIChat/AIChat.module.css
  • apps/condo/domains/ai/components/AIChat/AIChat.tsx
  • apps/condo/domains/ai/components/AIChat/AIChatInput.module.css
  • apps/condo/domains/ai/components/AIChat/AIChatInput.tsx
  • apps/condo/domains/ai/components/AIChat/AIChatMessage.module.css
  • apps/condo/domains/ai/components/AIChat/AIChatMessage.tsx
  • apps/condo/domains/ai/components/AIChat/AIChatSuggestions.module.css
  • apps/condo/domains/ai/components/AIChat/AIChatSuggestions.tsx
  • apps/condo/domains/ai/components/AIChat/AIChatThinkingStatus.module.css
  • apps/condo/domains/ai/components/AIChat/AIChatThinkingStatus.tsx
  • apps/condo/domains/ai/components/AIInputNotification.module.css
  • apps/condo/domains/ai/components/AIInputNotification.tsx
  • apps/condo/domains/ai/components/AIOverlay/AIOverlay.module.css
  • apps/condo/domains/ai/components/AIOverlay/AIOverlay.tsx
  • apps/condo/domains/ai/hooks/useAIFlow.tsx
  • apps/condo/domains/ai/utils/aiAnswerPresenter.spec.js
  • apps/condo/domains/ai/utils/aiAnswerPresenter.ts
  • apps/condo/domains/ai/utils/answerDisplayBuffer.ts
  • apps/condo/domains/common/components/Comments/CommentForm.tsx
  • apps/condo/domains/common/components/Comments/index.tsx
  • apps/condo/domains/news/components/NewsForm/InputStep/InputStepForm.tsx
  • apps/condo/lang/en/en.json
  • apps/condo/lang/es/es.json
  • apps/condo/lang/ru/ru.json
  • packages/messaging/README.md
  • packages/messaging/hooks/useMessagingSubscription.ts
💤 Files with no reviewable changes (1)
  • apps/condo/domains/ai/components/AIOverlay/AIOverlay.tsx
🚧 Files skipped from review as they are similar to previous changes (21)
  • apps/condo/domains/ai/components/AIChat/AIChatThinkingStatus.module.css
  • .helm
  • apps/condo/domains/ai/components/AIChat/AIChatThinkingStatus.tsx
  • apps/condo/domains/ai/components/AIChat/AIChatSuggestions.module.css
  • apps/condo/lang/en/en.json
  • apps/condo/domains/ai/components/AIChat/AIChatInput.module.css
  • apps/condo/domains/common/components/Comments/CommentForm.tsx
  • apps/condo/lang/es/es.json
  • apps/condo/domains/common/components/Comments/index.tsx
  • apps/condo/domains/ai/components/AIChat/AIChatSuggestions.tsx
  • apps/condo/domains/ai/components/AIChat/AIChat.module.css
  • apps/condo/domains/ai/components/AIChat/AIChatMessage.module.css
  • packages/messaging/hooks/useMessagingSubscription.ts
  • apps/condo/domains/news/components/NewsForm/InputStep/InputStepForm.tsx
  • packages/messaging/README.md
  • apps/condo/domains/ai/components/AIInputNotification.tsx
  • apps/condo/domains/ai/components/AIOverlay/AIOverlay.module.css
  • apps/condo/domains/ai/components/AIInputNotification.module.css
  • apps/condo/domains/ai/utils/answerDisplayBuffer.ts
  • apps/condo/domains/ai/hooks/useAIFlow.tsx
  • apps/condo/domains/ai/components/AIChat/AIChat.tsx

Comment thread apps/condo/domains/ai/components/AIChat/AIChatMessage.tsx
Comment thread apps/condo/domains/ai/utils/aiAnswerPresenter.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/condo/domains/ai/components/AIChat/AIChatMessage.tsx (1)

204-212: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not enable suggestions without a click handler.

onSuggestionClick is optional, but these buttons are disabled only from canExecuteAIFlow. AIChat.tsx renders welcomeDisplayMessage without onSuggestionClick, so suggestions on that message can be enabled while clicking them does nothing. Include !onSuggestionClick in disabled, or skip rendering suggestions when no handler exists.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/condo/domains/ai/components/AIChat/AIChatMessage.tsx` around lines 204 -
212, Update the suggestion item mapping in AIChatMessage so each suggestion is
disabled when either canExecuteAIFlow is false or onSuggestionClick is
unavailable. Preserve the existing click behavior for messages that provide a
handler.
apps/condo/domains/ai/utils/aiAnswerPresenter.ts (1)

133-162: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Handle incomplete tool-call JSON spans before stripping only the last line

stripServiceToolCallLines skips partial JSON payloads when jsonEnd < 0, leaving the leading Calling <tool> with input: {... text and any intermediate JSON lines in result until the final isPartialToolCallTrace(lastLine) check. If the streaming source emits a multi-line JSON payload, the header and unfinished JSON lines are not the last line and can appear in the displayed answer instead of being removed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/condo/domains/ai/utils/aiAnswerPresenter.ts` around lines 133 - 162,
Update stripServiceToolCallLines to remove an incomplete tool-call span when
findEndOfBalancedJsonObject returns a negative result, including the header and
all following partial JSON lines rather than continuing the search. Preserve
subsequent non-tool-call text and the existing final-line cleanup for partial
traces.
🧹 Nitpick comments (1)
apps/condo/domains/ai/components/AIChat/AIChatMessage.tsx (1)

46-48: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use structured logging for error paths.

These console.error calls do not follow the TypeScript logging guideline. Replace them with the project’s structured logger, preserving exceptions in err and contextual values in data.

Also applies to: 141-142, 149-150

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/condo/domains/ai/components/AIChat/AIChatMessage.tsx` around lines 46 -
48, Replace the console.error calls in AIChatMessage, including the handlers
around the clipboard copy and the locations near the additional referenced
ranges, with the project’s structured logger. Preserve each caught exception in
the logger’s err field and pass relevant contextual values through data, while
retaining the existing error messages and control flow.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/condo/domains/ai/utils/aiAnswerPresenter.ts`:
- Around line 11-17: Replace the Cyrillic-specific trailing boundary in
NARRATIVE_TOOL_CALL_REGEX with a context-aware termination rule that removes
only an actual narrative tool-call phrase, not arbitrary text following an
English camelCase word such as “iPhone.” Keep TOOL_NAME_PATTERN and
PARTIAL_NARRATIVE_TOOL_CALL_REGEX behavior aligned, and preserve legitimate
same-line sentence content after non-tool words.

---

Outside diff comments:
In `@apps/condo/domains/ai/components/AIChat/AIChatMessage.tsx`:
- Around line 204-212: Update the suggestion item mapping in AIChatMessage so
each suggestion is disabled when either canExecuteAIFlow is false or
onSuggestionClick is unavailable. Preserve the existing click behavior for
messages that provide a handler.

In `@apps/condo/domains/ai/utils/aiAnswerPresenter.ts`:
- Around line 133-162: Update stripServiceToolCallLines to remove an incomplete
tool-call span when findEndOfBalancedJsonObject returns a negative result,
including the header and all following partial JSON lines rather than continuing
the search. Preserve subsequent non-tool-call text and the existing final-line
cleanup for partial traces.

---

Nitpick comments:
In `@apps/condo/domains/ai/components/AIChat/AIChatMessage.tsx`:
- Around line 46-48: Replace the console.error calls in AIChatMessage, including
the handlers around the clipboard copy and the locations near the additional
referenced ranges, with the project’s structured logger. Preserve each caught
exception in the logger’s err field and pass relevant contextual values through
data, while retaining the existing error messages and control flow.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a60c88e1-6dbd-46af-9965-07463998d2f1

📥 Commits

Reviewing files that changed from the base of the PR and between 9596b65 and 266fea4.

📒 Files selected for processing (5)
  • apps/condo/domains/ai/components/AIChat/AIChatMessage.tsx
  • apps/condo/domains/ai/components/AIInputNotification.module.css
  • apps/condo/domains/ai/utils/aiAnswerPresenter.spec.js
  • apps/condo/domains/ai/utils/aiAnswerPresenter.ts
  • apps/condo/domains/ai/utils/answerDisplayBuffer.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/condo/domains/ai/utils/aiAnswerPresenter.spec.js
  • apps/condo/domains/ai/components/AIInputNotification.module.css

Comment on lines +11 to +17
// Narrative status without JSON: "Calling getProperties to find the house by address."
// Stop before newline or Cyrillic so glued RU text stays.
const NARRATIVE_TOOL_CALL_REGEX = new RegExp(
`Calling\\s+(?:${TOOL_NAME_PATTERN})\\b[^\\n\\u0400-\\u04FF]*`,
'g',
)
const PARTIAL_NARRATIVE_TOOL_CALL_REGEX = new RegExp(`^Calling\\s+(?:${TOOL_NAME_PATTERN})\\b`)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Cyrillic-boundary heuristic in NARRATIVE_TOOL_CALL_REGEX still relies on the same hardcoded delimiter previously flagged.

[^\n\u0400-\u04FF]* still stops only at a newline or Cyrillic character, so anything else on the same line after a Calling <camelCaseToken> match gets deleted. This is narrower now (gated by TOOL_NAME_PATTERN), but TOOL_NAME_PATTERN's [a-z]+[A-Z][A-Za-z0-9_]* alternative still matches ordinary English words like "iPhone", so a legitimate sentence such as "Calling iPhone users about the update. This part matters too." would still be silently truncated from "iPhone" to end-of-line. This is the same architectural concern raised in the earlier review round ("why only Cyrillic? Little strange, like hardcode") that was marked "Fixed," but the boundary logic is unchanged.

🐛 Suggested direction
-const NARRATIVE_TOOL_CALL_REGEX = new RegExp(
-    `Calling\\s+(?:${TOOL_NAME_PATTERN})\\b[^\\n\\u0400-\\u04FF]*`,
-    'g',
-)
+// Only strip up to the first sentence boundary / punctuation, not to end-of-line,
+// so legitimate trailing prose is preserved even when it starts right after a
+// camelCase-looking token.
+const NARRATIVE_TOOL_CALL_REGEX = new RegExp(
+    `Calling\\s+(?:${TOOL_NAME_PATTERN})\\b[^\\n.!?]*[.!?]?`,
+    'g',
+)
🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 12-15: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(
Calling\\s+(?:${TOOL_NAME_PATTERN})\\b[^\\n\\u0400-\\u04FF]*,
'g',
)
Note: [CWE-1333] Inefficient Regular Expression Complexity

(regexp-from-variable)


[warning] 16-16: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(^Calling\\s+(?:${TOOL_NAME_PATTERN})\\b)
Note: [CWE-1333] Inefficient Regular Expression Complexity

(regexp-from-variable)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/condo/domains/ai/utils/aiAnswerPresenter.ts` around lines 11 - 17,
Replace the Cyrillic-specific trailing boundary in NARRATIVE_TOOL_CALL_REGEX
with a context-aware termination rule that removes only an actual narrative
tool-call phrase, not arbitrary text following an English camelCase word such as
“iPhone.” Keep TOOL_NAME_PATTERN and PARTIAL_NARRATIVE_TOOL_CALL_REGEX behavior
aligned, and preserve legitimate same-line sentence content after non-tool
words.

@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants