Sync main-xavier with upstream main#2645
Conversation
…py' into main-xavier # Conflicts: # apps/web/src/components/ChatView.browser.tsx # apps/web/src/components/settings/SettingsPanels.tsx
…in-xavier # Conflicts: # apps/web/src/components/chat/MessagesTimeline.test.tsx # apps/web/src/components/chat/MessagesTimeline.tsx
# Conflicts: # apps/server/integration/OrchestrationEngineHarness.integration.ts # apps/server/src/checkpointing/Layers/CheckpointDiffQuery.test.ts # apps/server/src/orchestration/Layers/OrchestrationReactor.ts # apps/server/src/orchestration/Layers/ProjectionPipeline.ts # apps/server/src/persistence/Migrations.ts # apps/server/src/serverLayers.ts # apps/server/src/wsServer.test.ts # apps/server/src/wsServer.ts # apps/web/src/components/ChatView.browser.tsx # apps/web/src/components/ChatView.logic.test.ts # apps/web/src/components/ChatView.logic.ts # apps/web/src/components/ChatView.tsx # apps/web/src/components/chat/MessagesTimeline.tsx # apps/web/src/components/settings/SettingsPanels.tsx # apps/web/src/store.ts # packages/contracts/src/settings.test.ts # packages/shared/package.json
# Conflicts: # apps/server/integration/OrchestrationEngineHarness.integration.ts # apps/web/src/components/ChatView.logic.test.ts # apps/web/src/components/ChatView.tsx # apps/web/src/components/chat/MessagesTimeline.logic.ts # apps/web/src/components/chat/MessagesTimeline.tsx # apps/web/src/components/chat/ProposedPlanCard.tsx # apps/web/src/components/timelineHeight.test.ts # apps/web/src/components/timelineHeight.ts # packages/contracts/src/orchestration.test.ts
# Conflicts: # apps/web/src/components/chat/MessagesTimeline.tsx # apps/web/src/session-logic.ts
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. 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 |
| @@ -0,0 +1,42 @@ | |||
| const FENCED_CODE_BLOCK_REGEX = /(^|\n)(`{3,}|~{3,})[^\n]*\n([\s\S]*?)\n\2(?=\n|$)/g; | |||
There was a problem hiding this comment.
🟢 Low lib/markdownPlainText.ts:1
The FENCED_CODE_BLOCK_REGEX requires a newline before the closing fence, so empty fenced code blocks like "```\n```" fail to match and leave the fence markers in the output. Consider using (?:[\s\S]*?\n)? to make the content line optional.
| const FENCED_CODE_BLOCK_REGEX = /(^|\n)(`{3,}|~{3,})[^\n]*\n([\s\S]*?)\n\2(?=\n|$)/g; | |
| +const FENCED_CODE_BLOCK_REGEX = /(^|\n)(`{3,}|~{3,})[^\n]*\n((?:[\s\S]*?\n)?)\2(?=\n|$)/g; |
🤖 Copy this AI Prompt to have your agent fix this:
In file apps/web/src/lib/markdownPlainText.ts around line 1:
The `FENCED_CODE_BLOCK_REGEX` requires a newline before the closing fence, so empty fenced code blocks like `"[code fence]\n[code fence]"` fail to match and leave the fence markers in the output. Consider using `(?:[\s\S]*?\n)?` to make the content line optional.
Evidence trail:
apps/web/src/lib/markdownPlainText.ts line 1 (REVIEWED_COMMIT): regex `/(^|\n)(`{3,}|~{3,})[^\n]*\n([\s\S]*?)\n\2(?=\n|$)/g` — the literal `\n` between group 3 and `\2` mandates a newline before the closing fence. For input `"[code fence]\n[code fence]"`, after consuming the opening fence and the newline, the remaining text is just `` [code fence] `` with no preceding newline, so the regex cannot match.
| const BLOCKQUOTE_PREFIX_REGEX = /^\s{0,3}>\s?/gm; | ||
| const LIST_PREFIX_REGEX = /^\s{0,3}(?:[-+*]|\d+[.)])\s+/gm; | ||
| const THEMATIC_BREAK_REGEX = /^\s{0,3}(?:[-*_]\s*){3,}$/gm; | ||
| const EMPHASIS_REGEXES = [/(\*\*\*|___)(.*?)\1/gs, /(\*\*|__)(.*?)\1/gs, /(~~)(.*?)\1/gs] as const; |
There was a problem hiding this comment.
🟡 Medium lib/markdownPlainText.ts:14
The EMPHASIS_REGEXES array handles **, __, ***, ___, and ~~, but omits single emphasis markers *text* and _text_ for italic. When italic text like *important* appears in the markdown, the asterisks are preserved in the output instead of being stripped, so plain text derived from search indexing contains incorrect characters.
-const EMPHASIS_REGEXES = [/(\*\*\*|___)(.*?)\1/gs, /(\*\*|__)(.*?)\1/gs, /(~~)(.*?)\1/gs] as const;🤖 Copy this AI Prompt to have your agent fix this:
In file apps/web/src/lib/markdownPlainText.ts around line 14:
The `EMPHASIS_REGEXES` array handles `**`, `__`, `***`, `___`, and `~~`, but omits single emphasis markers `*text*` and `_text_` for italic. When italic text like `*important*` appears in the markdown, the asterisks are preserved in the output instead of being stripped, so plain text derived from search indexing contains incorrect characters.
Evidence trail:
apps/web/src/lib/markdownPlainText.ts line 14: `const EMPHASIS_REGEXES = [/(\*\*\*|___)(.*?)\1/gs, /(\*\*|__)(.*?)\1/gs, /(~~)(.*?)\1/gs] as const;` — only matches `***`, `___`, `**`, `__`, `~~` but not `*` or `_` as delimiters. Lines 31-33 show the for-loop applying these regexes. Single-emphasis italic markdown like `*text*` or `_text_` would not be matched by any regex, leaving markers in the plain text output.
Summary
Merge upstream main from pingdotgg/t3code into main-xavier.
Preserve fork features while resolving upstream structural changes, including assistant copy formatting, thread search, queued follow-ups, and related compatibility updates.
Validation
Note
Add queued follow-ups to threads with background reactor, search highlighting, and markdown copy format
queuedFollowUpsfeature on threads: new contracts schemas, commands, and events for enqueue/update/remove/reorder/send-failed/send-error-cleared lifecycle; decider, projector, and projection pipeline all updated to persist and project follow-up state into a newprojection_thread_queued_follow_upsDB table (migration 031).QueuedFollowUpReactor, a background service that reads the orchestration read model, dispatchesthread.turn.startfor eligible queued follow-ups, records pending dispatches, and emitsthread.queued-follow-up.send-failedon errors.buildThreadSearchIndexandfindThreadSearchLookupStateindex timeline rows (messages, plans, work entries) and find matches;ThreadSearchBarprovides keyboard-navigable UI;createThreadSearchHighlightRehypePluginandrenderHighlightedTexthighlight matches in rendered markdown and plain text.assistantResponseCopyFormatsetting ('markdown'|'plain-text') with a full AST-basedmarkdownToPlainTextrenderer (LRU-cached) so users can copy assistant responses as plain text.ComposerQueuedFollowUpsPanelcomponent with drag-and-drop reordering of queued follow-up items.projection_threads; existing orchestration read model consumers must handle the newqueuedFollowUpsarray field on threads.📊 Macroscope summarized 01a42b9. 40 files reviewed, 7 issues evaluated, 1 issue filtered, 2 comments posted
🗂️ Filtered Issues
apps/server/src/persistence/Layers/ProjectionThreadQueuedFollowUps.ts — 0 comments posted, 1 evaluated, 1 filtered
replaceByThreadIdfunction at lines 139-159 performs a delete followed by multiple inserts without transaction wrapping. If the delete succeeds but any subsequentinsertQueuedFollowUpRowcall fails, the database will be left in an inconsistent state: the original follow-ups are deleted, but only a partial set of new follow-ups exist. This violates the atomicity semantics implied by "replace" - the operation should either fully succeed or leave the data unchanged. Consider wrapping the delete and inserts in a SQL transaction usingSqlClient.withTransactionor similar. [ Failed validation ]