feat(condo): DOMA-12967 add streaming in chat with condo #7859
feat(condo): DOMA-12967 add streaming in chat with condo #7859tolmachev21 wants to merge 7 commits into
Conversation
📝 WalkthroughWalkthroughChangesAI 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
Messaging subscription replay
Helm reference update
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested labels: Suggested reviewers: 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
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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
apps/condo/domains/ai/components/AIInputNotification.module.cssParsing 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. Comment |
There was a problem hiding this comment.
💡 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".
There was a problem hiding this comment.
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 winDo not persist messages until the new session has finished loading.
On an
aiSessionIdchange, the loading effect schedulessetMessages, but the persistence effect still runs with the previous render’s messages. Sincemessages.length >= 0is 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 winReplace the
anyref with the concrete input handle type.Only
.focus()is used here; typing the exposedAIChatInputhandle prevents incompatible ref assignments.As per coding guidelines, “In TypeScript files, avoid explicit
anyunless 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 winUse structured Pino logging for the new error paths.
Replace these
console.errorcalls 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
📒 Files selected for processing (24)
.helmapps/condo/domains/ai/components/AIChat/AIChat.module.cssapps/condo/domains/ai/components/AIChat/AIChat.tsxapps/condo/domains/ai/components/AIChat/AIChatInput.module.cssapps/condo/domains/ai/components/AIChat/AIChatMessage.module.cssapps/condo/domains/ai/components/AIChat/AIChatMessage.tsxapps/condo/domains/ai/components/AIChat/AIChatSuggestions.module.cssapps/condo/domains/ai/components/AIChat/AIChatSuggestions.tsxapps/condo/domains/ai/components/AIChat/AIChatThinkingStatus.module.cssapps/condo/domains/ai/components/AIChat/AIChatThinkingStatus.tsxapps/condo/domains/ai/components/AIInputNotification.module.cssapps/condo/domains/ai/components/AIInputNotification.tsxapps/condo/domains/ai/components/AIOverlay/AIOverlay.module.cssapps/condo/domains/ai/hooks/useAIFlow.tsxapps/condo/domains/ai/utils/aiAnswerPresenter.tsapps/condo/domains/ai/utils/answerDisplayBuffer.tsapps/condo/domains/common/components/Comments/CommentForm.tsxapps/condo/domains/common/components/Comments/index.tsxapps/condo/domains/news/components/NewsForm/InputStep/InputStepForm.tsxapps/condo/lang/en/en.jsonapps/condo/lang/es/es.jsonapps/condo/lang/ru/ru.jsonpackages/messaging/README.mdpackages/messaging/hooks/useMessagingSubscription.ts
toplenboren
left a comment
There was a problem hiding this comment.
Okay-ish, but please check code quality and naming of created utils
|
|
||
| if (!savedHistory || typeof savedHistory !== 'object') { | ||
| setMessages([]) | ||
| setActiveTurnUserMessageId(null) |
There was a problem hiding this comment.
Yes, it's need for pin user message in header
| })) | ||
| setMessages(historyWithDates) | ||
| setActiveTurnUserMessageId(null) | ||
| requestAnimationFrame(() => { |
There was a problem hiding this comment.
pls explain why do u have 2 request anmiation framce
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
Because it IIFE for async function. Rewrite it in async for clear
| const assistantMessage: Message = { | ||
| id: uuidV4(), | ||
| content: { text: loadingLabel }, | ||
| content: { text: '' }, |
There was a problem hiding this comment.
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. */ |
| return stripSuggestionsForDisplay(stripServiceToolCallLines(rawAnswer)).trimEnd() | ||
| } | ||
|
|
||
| export function parseAssistantAnswer (answer: string): ParsedAssistantAnswer { |
There was a problem hiding this comment.
please explain why do you need this utility and why do you create it in /utils
c26b9c4 to
9596b65
Compare
There was a problem hiding this comment.
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
📒 Files selected for processing (27)
.helmapps/condo/domains/ai/components/AIChat/AIChat.module.cssapps/condo/domains/ai/components/AIChat/AIChat.tsxapps/condo/domains/ai/components/AIChat/AIChatInput.module.cssapps/condo/domains/ai/components/AIChat/AIChatInput.tsxapps/condo/domains/ai/components/AIChat/AIChatMessage.module.cssapps/condo/domains/ai/components/AIChat/AIChatMessage.tsxapps/condo/domains/ai/components/AIChat/AIChatSuggestions.module.cssapps/condo/domains/ai/components/AIChat/AIChatSuggestions.tsxapps/condo/domains/ai/components/AIChat/AIChatThinkingStatus.module.cssapps/condo/domains/ai/components/AIChat/AIChatThinkingStatus.tsxapps/condo/domains/ai/components/AIInputNotification.module.cssapps/condo/domains/ai/components/AIInputNotification.tsxapps/condo/domains/ai/components/AIOverlay/AIOverlay.module.cssapps/condo/domains/ai/components/AIOverlay/AIOverlay.tsxapps/condo/domains/ai/hooks/useAIFlow.tsxapps/condo/domains/ai/utils/aiAnswerPresenter.spec.jsapps/condo/domains/ai/utils/aiAnswerPresenter.tsapps/condo/domains/ai/utils/answerDisplayBuffer.tsapps/condo/domains/common/components/Comments/CommentForm.tsxapps/condo/domains/common/components/Comments/index.tsxapps/condo/domains/news/components/NewsForm/InputStep/InputStepForm.tsxapps/condo/lang/en/en.jsonapps/condo/lang/es/es.jsonapps/condo/lang/ru/ru.jsonpackages/messaging/README.mdpackages/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
There was a problem hiding this comment.
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 winDo not enable suggestions without a click handler.
onSuggestionClickis optional, but these buttons are disabled only fromcanExecuteAIFlow.AIChat.tsxrenderswelcomeDisplayMessagewithoutonSuggestionClick, so suggestions on that message can be enabled while clicking them does nothing. Include!onSuggestionClickindisabled, 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 winHandle incomplete tool-call JSON spans before stripping only the last line
stripServiceToolCallLinesskips partial JSON payloads whenjsonEnd < 0, leaving the leadingCalling <tool> with input: {...text and any intermediate JSON lines inresultuntil the finalisPartialToolCallTrace(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 winUse structured logging for error paths.
These
console.errorcalls do not follow the TypeScript logging guideline. Replace them with the project’s structured logger, preserving exceptions inerrand contextual values indata.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
📒 Files selected for processing (5)
apps/condo/domains/ai/components/AIChat/AIChatMessage.tsxapps/condo/domains/ai/components/AIInputNotification.module.cssapps/condo/domains/ai/utils/aiAnswerPresenter.spec.jsapps/condo/domains/ai/utils/aiAnswerPresenter.tsapps/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
| // 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`) |
There was a problem hiding this comment.
🎯 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.
|



Summary by CodeRabbit
startTimebehavior..helmsubmodule revision.