Skip to content

[Fix] stabilize conversation resolution flow#828

Merged
dingyi222666 merged 7 commits intov1-devfrom
fix/conversation-system
Apr 14, 2026
Merged

[Fix] stabilize conversation resolution flow#828
dingyi222666 merged 7 commits intov1-devfrom
fix/conversation-system

Conversation

@dingyi222666
Copy link
Copy Markdown
Member

description: |-

This pr consolidates conversation resolution into a single flow and fixes follow-up regressions in command routing, target lookup, and middleware state propagation.

New Features

None.

Bug fixes

  • restore explicit conversation target suggestions and ambiguous-target handling for chat and conversation commands
  • keep command routing on the resolved conversation object instead of duplicating stale conversationId state across middlewares
  • preserve active preset-lane behavior for untargeted commands and direct conversation-id switches
  • fix archived and cross-route target lookup behavior after the conversation resolution refactor
  • align stop, rollback, delay, and time-limit middleware with the unified resolution flow

Other Changes

  • simplify command option trimming for chat and conversation commands
  • introduce typed conversation resolution errors for route and ambiguity failures
  • expand conversation service and middleware coverage for the new resolution behavior

Use a single resolution path across chat and conversation middlewares so explicit targets, preset lanes, and archived lookups behave consistently. This restores target suggestions and keeps command routing stable for direct ids and active-lane commands.
Keep middleware and conversation management on the resolved conversation object instead of duplicating conversation ids in chain options. This tightens target resolution, typed error handling, and archived-target matching so command routing stays consistent after the resolution refactor.
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 14, 2026

Warning

Rate limit exceeded

@dingyi222666 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 29 minutes and 35 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 29 minutes and 35 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: e3ace945-b279-4789-a802-649966165650

📥 Commits

Reviewing files that changed from the base of the PR and between 85d50c7 and ab052df.

📒 Files selected for processing (1)
  • packages/core/src/middlewares/chat/rollback_chat.ts

Walkthrough

统一对话解析为单一的 resolveConversation API,新增 ConversationResolution/ConversationResolutionError 类型,删除旧的 resolveContext/resolveTargetConversation 等,所有中间件与命令改为通过 context.options.conversation 传递解析结果并调整中间件顺序以匹配新流程。

Changes

Cohort / File(s) Summary
服务与类型
packages/core/src/services/conversation.ts, packages/core/src/services/conversation_types.ts, packages/core/src/services/types.ts
新增 resolveConversation 公共方法与 ResolveConversationOptions/ConversationResolution 类型,移除旧的 resolveContext/resolveCommandConversation/相关 API,新增 ConversationResolutionError 与模式枚举,更新多个服务签名。
中间件:会话解析与请求
packages/core/src/middlewares/conversation/resolve_conversation.ts, packages/core/src/middlewares/conversation/request_conversation.ts
resolve_conversation 调用新服务 API、统一存储解析结果为 context.options.conversation、新增错误映射与提示;request_conversation 改为直接读取 context.options.conversation 并传入 ensureActiveConversation
中间件:聊天流水线
packages/core/src/middlewares/chat/read_chat_message.ts, packages/core/src/middlewares/chat/message_delay.ts, packages/core/src/middlewares/chat/chat_time_limit_check.ts, packages/core/src/middlewares/chat/chat_time_limit_save.ts
拆分出 transform_chat_message 中间件,消息转换/校验从解析逻辑分离;多个中间件改为读取 context.options.conversation,调整执行顺序(如改为在 transform_chat_message 之后/之前运行)。
中间件:停止与回滚
packages/core/src/middlewares/chat/stop_chat.ts, packages/core/src/middlewares/chat/rollback_chat.ts
停止/回滚中间件改为优先使用已解析的 context.options.conversation,并在需要时调用 resolveConversation;移除对 context.options.conversationId 的写入副作用,调整函数签名以传递 resolved 对象。
系统会话管理
packages/core/src/middlewares/system/conversation_manage.ts
会话管理命令改为依赖 context.options.conversation,删除重复解析逻辑,添加 ConversationResolutionError 对应消息映射与更严格的缺失早停行为。
命令构建器与工具
packages/core/src/commands/chat.ts, packages/core/src/commands/conversation.ts, packages/core/src/utils/conversation.ts, packages/core/src/chains/chain.ts
移除 completeConversationTarget 工具与调用,命令直接使用 `options.conversation?.trim()
预设与其他辅助
packages/core/src/preset.ts, packages/extension-long-memory/src/utils/conversation.ts
watchPreset 过滤扩展名及改进 ENOENT 处理;扩展插件改为使用 resolveConversation 替代旧解析 API。
测试
packages/core/tests/*
大量测试更新:改为模拟/断言 resolveConversation,新增 ConversationResolutionError 场景与解析优先级测试,删除与 completeConversationTarget 相关测试文件并调整多处断言与中间件集成测试。

Sequence Diagram(s)

sequenceDiagram
  participant Cmd as Command (用户/CLI)
  participant Chain as Middleware Chain
  participant ConvSvc as Conversation Service
  participant Store as Conversation Store/DB

  Cmd->>Chain: 发起命令/消息(含 options.targetConversation)
  Chain->>Chain: resolve_conversation 读取 options.targetConversation / options.conversation
  Chain->>ConvSvc: resolveConversation(session, ResolveConversationOptions)
  ConvSvc->>Store: 查询/匹配会话 (id/seq/title/archived)
  Store-->>ConvSvc: 返回 conversation / ambiguous / not found
  ConvSvc-->>Chain: 返回 ConversationResolution (mode, conversationId, conversation, constraint...)
  Chain->>Chain: transform_chat_message 使用 context.options.conversation 和消息进行转换
  Chain->>Chain: 继续后续中间件(message_delay / handlers)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Poem

🐰 旧路散乱今合一,解析有序展新姿,
Middleware 按步行,Conversation 分明记,
我在胡萝卜旁轻跳跃,赞这变更真欢喜! 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed PR标题明确概括了主要变更:稳定对话解析流程,与changeset中的核心改动相符。
Description check ✅ Passed PR描述详细说明了问题修复和改进内容,与changeset中的多个文件更改相关联,包括对话解析流程、命令路由和中间件状态传播。

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/conversation-system

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 and usage tips.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the conversation resolution logic by introducing a unified resolveConversation method, replacing legacy methods and simplifying command option parsing. Middlewares and commands are updated to use this centralized flow, which supports multiple resolution modes and improves error handling. Feedback highlights a type discrepancy where the conversation option is typed as ConversationResolution but sometimes used as a partial object, suggesting stricter typing or a partial type definition to improve safety.

Comment thread packages/core/src/chains/chain.ts
Run the repository lint autofixes on the conversation resolution changes. This keeps formatting and import ordering aligned with the project rules without changing behavior.
Copy link
Copy Markdown
Contributor

@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: 3

🧹 Nitpick comments (7)
packages/core/src/services/types.ts (1)

3-14: 导入排序问题

静态分析提示 ConstraintRecord 应按字母顺序排列。建议修复以保持代码风格一致性。

🔧 建议的导入排序
 import {
     ACLRecord,
     ArchiveRecord,
     BindingRecord,
+    ConstraintRecord,
     ConversationResolution,
     ConversationResolveMode,
-    ConstraintRecord,
     ConversationRecord,
     MessageRecord,
     MetaRecord,
     ResolveConversationOptions
 } from './conversation_types'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/services/types.ts` around lines 3 - 14, Reorder the named
imports in the import statement so they are alphabetized to satisfy the linter;
specifically place ConstraintRecord in its correct alphabetical position among
ACLRecord, ArchiveRecord, BindingRecord, ConversationRecord,
ConversationResolution, ConversationResolveMode, MessageRecord, MetaRecord, and
ResolveConversationOptions (ensure the entire import list is sorted and keep the
import from './conversation_types' intact).
packages/core/src/middlewares/chat/chat_time_limit_save.ts (1)

23-25: 访问模式可以简化

根据 ConversationResolution 类型定义,conversationId 字段已经是 string | null,其值在 resolveConversation 中被设置为 resolved.conversation?.id ?? null。因此 context.options.conversation?.conversation?.id 的回退是冗余的。

可以简化为:

-        const conversationId =
-            context.options.conversation?.conversationId ??
-            context.options.conversation?.conversation?.id
+        const conversationId = context.options.conversation?.conversationId

不过当前写法也是安全的,可以作为可选优化。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/middlewares/chat/chat_time_limit_save.ts` around lines 23 -
25, The conversationId resolution is redundant: use the ConversationResolution
field directly instead of falling back to
context.options.conversation?.conversation?.id; update the assignment of
conversationId (the variable in chat_time_limit_save.ts) to read from
context.options.conversation?.conversationId (or default to null) and remove the
extra fallback expression so the code becomes simpler and relies on the resolved
conversationId provided by resolveConversation.
packages/core/src/middlewares/system/conversation_manage.ts (1)

705-712: 格式问题需要修复。

静态分析工具指出此处存在 prettier 格式问题。建议调整缩进以符合项目格式规范。

🔧 建议修复
             const current =
-                await ctx.chatluna.conversation.updateManagedConstraint(session, {
-                    routeMode
-                })
+                await ctx.chatluna.conversation.updateManagedConstraint(
+                    session,
+                    { routeMode }
+                )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/middlewares/system/conversation_manage.ts` around lines 705
- 712, 该段代码因缩进/格式不符合 prettier 导致静态检查失败;请调整 updateManagedConstraint
调用及接续赋值表达式的换行与缩进使其符合项目格式规范:定位到 conversation.updateManagedConstraint 和
conversation.resolveConstraint 使用的表达式(变量 current 和 nextRouteMode),将三元表达式与 await
对齐、适当拆行并确保对象字面量 { routeMode } 与后续链式调用缩进一致,保存并运行 prettier/项目格式化验证通过后提交。
packages/core/src/middlewares/chat/rollback_chat.ts (2)

20-25: 考虑内联 getTargetConversation 函数。

根据编码规范,函数体为 1-5 行的函数应在调用处内联。该函数仅在一处使用(第 36 行),可直接内联以减少抽象层。

♻️ 建议修复
-function getTargetConversation(context: ChainMiddlewareContext) {
-    return (
-        context.options.conversation_manage?.targetConversation ??
-        context.options.targetConversation
-    )
-}
-
 // 在第 36 行直接内联:
-            const targetConversation = getTargetConversation(context)
+            const targetConversation =
+                context.options.conversation_manage?.targetConversation ??
+                context.options.targetConversation

Based on learnings: "Do NOT create extra functions for short logic; if a function body would be 1-5 lines, inline it at the call site instead"

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/middlewares/chat/rollback_chat.ts` around lines 20 - 25,
The helper function getTargetConversation is a 1-5 line helper that is only used
once; inline its logic at the call site instead of keeping a separate function.
Replace the call to getTargetConversation(context) with the inline expression
context.options.conversation_manage?.targetConversation ??
context.options.targetConversation (preserving the same nullish/coalescing
behavior), and remove the getTargetConversation function declaration (the
function and its reference to ChainMiddlewareContext can be deleted).

9-12: 按字母顺序排列导入成员。

静态分析工具指出 ConversationResolution 应按字母顺序排在 MessageRecord 之后。

🔧 建议修复
 import {
-    MessageRecord,
-    type ConversationResolution
+    type ConversationResolution,
+    MessageRecord
 } from '../../services/conversation_types'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/middlewares/chat/rollback_chat.ts` around lines 9 - 12, 在
rollback_chat.ts 的导入列表中按字母顺序调整导入成员,把 MessageRecord 和 ConversationResolution
的顺序互换以满足静态分析要求;具体在 import {...} from '../../services/conversation_types' 语句中确保
ConversationResolution 位于 MessageRecord 之后(调整 "MessageRecord" 和
"ConversationResolution" 的顺序),保存并让 linter 通过。
packages/core/src/services/conversation.ts (2)

525-527: 格式问题建议修复。

静态分析指出此处存在 prettier 格式问题,建议调整换行。

🔧 建议修复
         conversation =
-            matchTargetConversation(target, normalized, conversations, entries) ??
-            null
+            matchTargetConversation(
+                target,
+                normalized,
+                conversations,
+                entries
+            ) ?? null
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/services/conversation.ts` around lines 525 - 527, Prettier
reports a formatting issue on the assignment to the variable conversation;
reformat the statement using the matchTargetConversation call so it conforms to
project prettier rules (e.g., place the whole assignment on one line or wrap the
call with parentheses and break lines consistently). Update the expression
involving matchTargetConversation(target, normalized, conversations, entries)
and the nullish coalescing (?? null) so the assignment to conversation is
properly indented and line-broken according to the code style.

38-52: 按字母顺序排列导入成员。

静态分析指出 ConstraintPermission(第 39 行)应按字母顺序排列。

🔧 建议修复
 import {
     ACLRecord,
     applyPresetLane,
     ArchiveRecord,
     BindingRecord,
     computeBaseBindingKey,
     ConversationResolution,
-    ConstraintPermission,
     ConstraintRecord,
+    ConstraintPermission,
     ConversationCompressionRecord,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/services/conversation.ts` around lines 38 - 52, Imports
from './conversation_types' are not alphabetized; specifically move
ConstraintPermission so the import list is sorted alphabetically; update the
import statement that includes ConversationResolution, ConstraintPermission,
ConstraintRecord, ConversationCompressionRecord, ConversationListEntry,
ConversationRecord, ConversationResolutionError, getBaseBindingKey,
getPresetLane, MessageRecord, ResolveConversationOptions, ResolvedConstraint,
ResolvedConversationContext, RouteMode to be in strict alphabetical order (use
the symbol names as sorting keys) so ConstraintPermission appears in its correct
alphabetic position among the imported identifiers.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/core/src/commands/conversation.ts`:
- Around line 53-56: The property assignment for
conversation_manage.targetConversation uses a multi-line expression that breaks
Prettier; change it to a single-line property assignment (e.g.,
conversation_manage: { targetConversation: conversation?.trim() || undefined })
and apply the same single-line fix to the other occurrences (same pattern under
archive/restore/export/compress/delete and the blocks referenced at the other
locations) so all targetConversation assignments use the compact single-line
form to satisfy the formatter.

In `@packages/core/src/middlewares/chat/stop_chat.ts`:
- Around line 25-42: The code currently skips an ACL re-check by reusing current
when it appears resolved; always re-run conversation resolution with permission:
'manage' to enforce the intended ACL check instead of allowing the early-return
path. Replace the conditional that assigns resolved using current (the variable
named current and type ConversationResolution) with an unconditional await call
to ctx.chatluna.conversation.resolveConversation(session, { targetConversation,
presetLane: context.options.presetLane, allPresetLanes:
context.options.allPresetLanes, permission: 'manage', useRoutePresetLane:
context.options.presetLane == null && targetConversation == null, mode: 'target'
}) so getTargetConversation/context.options flow is preserved but the manage
permission is always enforced; remove the branch that bypasses
resolveConversation to prevent view-only sessions from being allowed to stop
conversations.

In `@packages/core/src/middlewares/conversation/resolve_conversation.ts`:
- Around line 30-44: The call to ctx.chatluna.conversation.resolveConversation
in resolve_conversation.ts is misformatted and breaks the linter; reflow the
await ctx.chatluna.conversation.resolveConversation(session, { ... }) invocation
and the subsequent if block to match the repository's Prettier style
(single-line or consistent object property alignment), ensuring consistent
indentation and line breaks for the parameters mode, conversationId,
targetConversation, presetLane, includeArchived, allPresetLanes, and
useRoutePresetLane; run Prettier/ESLint and adjust the surrounding if/return
block (the following if that checks the resolved value) so both the call and the
conditional follow the same formatting pattern used elsewhere in this file.

---

Nitpick comments:
In `@packages/core/src/middlewares/chat/chat_time_limit_save.ts`:
- Around line 23-25: The conversationId resolution is redundant: use the
ConversationResolution field directly instead of falling back to
context.options.conversation?.conversation?.id; update the assignment of
conversationId (the variable in chat_time_limit_save.ts) to read from
context.options.conversation?.conversationId (or default to null) and remove the
extra fallback expression so the code becomes simpler and relies on the resolved
conversationId provided by resolveConversation.

In `@packages/core/src/middlewares/chat/rollback_chat.ts`:
- Around line 20-25: The helper function getTargetConversation is a 1-5 line
helper that is only used once; inline its logic at the call site instead of
keeping a separate function. Replace the call to getTargetConversation(context)
with the inline expression
context.options.conversation_manage?.targetConversation ??
context.options.targetConversation (preserving the same nullish/coalescing
behavior), and remove the getTargetConversation function declaration (the
function and its reference to ChainMiddlewareContext can be deleted).
- Around line 9-12: 在 rollback_chat.ts 的导入列表中按字母顺序调整导入成员,把 MessageRecord 和
ConversationResolution 的顺序互换以满足静态分析要求;具体在 import {...} from
'../../services/conversation_types' 语句中确保 ConversationResolution 位于
MessageRecord 之后(调整 "MessageRecord" 和 "ConversationResolution" 的顺序),保存并让 linter
通过。

In `@packages/core/src/middlewares/system/conversation_manage.ts`:
- Around line 705-712: 该段代码因缩进/格式不符合 prettier 导致静态检查失败;请调整
updateManagedConstraint 调用及接续赋值表达式的换行与缩进使其符合项目格式规范:定位到
conversation.updateManagedConstraint 和 conversation.resolveConstraint 使用的表达式(变量
current 和 nextRouteMode),将三元表达式与 await 对齐、适当拆行并确保对象字面量 { routeMode }
与后续链式调用缩进一致,保存并运行 prettier/项目格式化验证通过后提交。

In `@packages/core/src/services/conversation.ts`:
- Around line 525-527: Prettier reports a formatting issue on the assignment to
the variable conversation; reformat the statement using the
matchTargetConversation call so it conforms to project prettier rules (e.g.,
place the whole assignment on one line or wrap the call with parentheses and
break lines consistently). Update the expression involving
matchTargetConversation(target, normalized, conversations, entries) and the
nullish coalescing (?? null) so the assignment to conversation is properly
indented and line-broken according to the code style.
- Around line 38-52: Imports from './conversation_types' are not alphabetized;
specifically move ConstraintPermission so the import list is sorted
alphabetically; update the import statement that includes
ConversationResolution, ConstraintPermission, ConstraintRecord,
ConversationCompressionRecord, ConversationListEntry, ConversationRecord,
ConversationResolutionError, getBaseBindingKey, getPresetLane, MessageRecord,
ResolveConversationOptions, ResolvedConstraint, ResolvedConversationContext,
RouteMode to be in strict alphabetical order (use the symbol names as sorting
keys) so ConstraintPermission appears in its correct alphabetic position among
the imported identifiers.

In `@packages/core/src/services/types.ts`:
- Around line 3-14: Reorder the named imports in the import statement so they
are alphabetized to satisfy the linter; specifically place ConstraintRecord in
its correct alphabetical position among ACLRecord, ArchiveRecord, BindingRecord,
ConversationRecord, ConversationResolution, ConversationResolveMode,
MessageRecord, MetaRecord, and ResolveConversationOptions (ensure the entire
import list is sorted and keep the import from './conversation_types' intact).
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: b28116a8-cce2-41b8-a136-a85dcf4c6f96

📥 Commits

Reviewing files that changed from the base of the PR and between fe99839 and e95f127.

📒 Files selected for processing (22)
  • packages/core/src/chains/chain.ts
  • packages/core/src/commands/chat.ts
  • packages/core/src/commands/conversation.ts
  • packages/core/src/middlewares/chat/chat_time_limit_check.ts
  • packages/core/src/middlewares/chat/chat_time_limit_save.ts
  • packages/core/src/middlewares/chat/message_delay.ts
  • packages/core/src/middlewares/chat/read_chat_message.ts
  • packages/core/src/middlewares/chat/rollback_chat.ts
  • packages/core/src/middlewares/chat/stop_chat.ts
  • packages/core/src/middlewares/conversation/request_conversation.ts
  • packages/core/src/middlewares/conversation/resolve_conversation.ts
  • packages/core/src/middlewares/model/resolve_model.ts
  • packages/core/src/middlewares/system/conversation_manage.ts
  • packages/core/src/services/conversation.ts
  • packages/core/src/services/conversation_types.ts
  • packages/core/src/services/types.ts
  • packages/core/src/utils/conversation.ts
  • packages/core/tests/conversation-resolve.spec.ts
  • packages/core/tests/conversation-service.spec.ts
  • packages/core/tests/conversation-target.spec.ts
  • packages/core/tests/rollback-chat.spec.ts
  • packages/extension-long-memory/src/utils/conversation.ts
💤 Files with no reviewable changes (1)
  • packages/core/tests/conversation-target.spec.ts

Comment thread packages/core/src/commands/conversation.ts Outdated
Comment thread packages/core/src/middlewares/chat/stop_chat.ts Outdated
Comment thread packages/core/src/middlewares/conversation/resolve_conversation.ts Outdated
Always resolve the stop-chat target from the command options instead of reusing the current resolved conversation state. This keeps stop requests pointed at the intended conversation after the conversation resolution refactor.
Run the repository lint autofix on stop_chat after the explicit target resolution change. This only updates formatting to match the project's ESLint and prettier rules.
@dingyi222666
Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 14, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Ignore non-preset files in the preset watcher and treat missing files on rename as removals instead of logging spurious errors. This keeps preset schema updates stable when preset files are deleted or unrelated files change.
Copy link
Copy Markdown
Contributor

@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: 2

Caution

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

⚠️ Outside diff range comments (1)
packages/core/src/services/conversation.ts (1)

1499-1547: ⚠️ Potential issue | 🔴 Critical

这里把“当前路由约束”当成了“目标会话约束”。

options.conversationId != null 时,下面真正被修改的会话是通过一次新的 mode: 'target' 解析拿到的,但后续 assertManageAllowedfixedModel / fixedPreset / fixedChatModelockConversation 仍然读的是前面 mode: 'context'resolved.constraint。跨路由或跨 lane 更新时,这会按当前路由而不是目标会话所属路由执行限制,允许绕过目标路由的管理/固定项/锁定约束。这里应直接复用 target 解析结果里的 constraint

🔒 参考改法
-        const resolved = await this.resolveConversation(session, {
+        const currentResolved = await this.resolveConversation(session, {
             ...options,
             mode: 'context'
         })
-        await assertManageAllowed(session, resolved.constraint)
-
-        const conversation =
-            options.conversationId == null
-                ? (
-                      await this.resolveConversation(session, {
-                          ...options,
-                          mode: 'active'
-                      })
-                  ).conversation
-                : (
-                      await this.resolveConversation(session, {
-                          ...options,
-                          permission: 'manage',
-                          mode: 'target'
-                      })
-                  ).conversation
+        await assertManageAllowed(session, currentResolved.constraint)
+
+        const targetResolved =
+            options.conversationId == null
+                ? await this.resolveConversation(session, {
+                      ...options,
+                      mode: 'active'
+                  })
+                : await this.resolveConversation(session, {
+                      ...options,
+                      permission: 'manage',
+                      mode: 'target'
+                  })
+        const conversation = targetResolved.conversation
 
         if (conversation == null) {
             throw new Error('Conversation not found.')
         }
 
-        const target = await this.getManagedConstraintByBindingKey(
+        await assertManageAllowed(session, targetResolved.constraint)
+
+        const managed = await this.getManagedConstraintByBindingKey(
             conversation.bindingKey
         )
 
-        if (target != null) {
-            await assertManageAllowed(session, target)
+        if (managed != null) {
+            await assertManageAllowed(session, managed)
         }
 
         for (const [key, fixedKey, label] of [
             ['model', 'fixedModel', 'Model'],
             ['preset', 'fixedPreset', 'Preset'],
             ['chatMode', 'fixedChatMode', 'Chat mode']
         ] as const) {
-            const fixed = target?.[fixedKey] ?? resolved.constraint[fixedKey]
+            const fixed =
+                managed?.[fixedKey] ??
+                targetResolved.constraint[fixedKey]
 
             if (options[key] != null && fixed != null) {
                 throw new Error(`${label} is fixed to ${fixed}.`)
             }
         }
 
-        if (target?.lockConversation ?? resolved.constraint.lockConversation) {
+        if (
+            managed?.lockConversation ??
+            targetResolved.constraint.lockConversation
+        ) {
             throw new Error('Conversation update is locked by constraint.')
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/services/conversation.ts` around lines 1499 - 1547, The
code is using the initial context resolution (resolved.constraint) for
permission/ fixed-value/lock checks even when a target conversation was
resolved; change the logic to reuse the target resolution's constraint when
present: after obtaining target via getManagedConstraintByBindingKey and the
conversation from resolveConversation (with mode: 'target' when
options.conversationId != null), call assertManageAllowed(session,
target.constraint) instead of resolved.constraint when target exists, and for
the fixedModel/fixedPreset/fixedChatMode checks and the lockConversation check
read from target.constraint (falling back to resolved.constraint only if target
is null). Update references to resolved.constraint in those checks to use
target.constraint where applicable so constraints are enforced for the actual
target conversation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/core/src/middlewares/chat/rollback_chat.ts`:
- Around line 35-52: 当前逻辑在遇到 context.options.conversation 满足 constraint 和
bindingKey 时直接复用上游对象 (current / ConversationResolution) 导致跳过本应以 permission:
'manage' 重新解析的流程,允许仅有查看权限的会话被回滚;应始终调用
ctx.chatluna.conversation.resolveConversation(session, {..., permission:
'manage', mode: 'target'}) 来重新解析目标会话(可将上游 conversation 的 conversationId
或相关标识作为输入),不要直接返回 context.options.conversation;在 getTargetConversation
使用到的分支中、以及处理 resolved 的变量(resolved)处改为强制走 resolveConversation,以确保使用 manage 权限校验。

In `@packages/core/src/services/types.ts`:
- Around line 141-144: Prettier flags the current multiline declaration of
ListConversationsOptions; fix it by reformatting the export of
ListConversationsOptions that uses Omit<ResolveConversationOptions, 'mode' |
'targetConversation' | 'permission'> to match the project's Prettier rules
(e.g., collapse into a single line or run the repo Prettier/formatter) so the
declaration for ListConversationsOptions/ResolveConversationOptions/Omit no
longer triggers prettier/prettier in CI.

---

Outside diff comments:
In `@packages/core/src/services/conversation.ts`:
- Around line 1499-1547: The code is using the initial context resolution
(resolved.constraint) for permission/ fixed-value/lock checks even when a target
conversation was resolved; change the logic to reuse the target resolution's
constraint when present: after obtaining target via
getManagedConstraintByBindingKey and the conversation from resolveConversation
(with mode: 'target' when options.conversationId != null), call
assertManageAllowed(session, target.constraint) instead of resolved.constraint
when target exists, and for the fixedModel/fixedPreset/fixedChatMode checks and
the lockConversation check read from target.constraint (falling back to
resolved.constraint only if target is null). Update references to
resolved.constraint in those checks to use target.constraint where applicable so
constraints are enforced for the actual target conversation.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 5fbb646b-370f-43c8-93b4-ca1a4ea2b129

📥 Commits

Reviewing files that changed from the base of the PR and between e95f127 and 85d50c7.

📒 Files selected for processing (9)
  • packages/core/src/commands/conversation.ts
  • packages/core/src/middlewares/chat/rollback_chat.ts
  • packages/core/src/middlewares/chat/stop_chat.ts
  • packages/core/src/middlewares/conversation/resolve_conversation.ts
  • packages/core/src/middlewares/system/conversation_manage.ts
  • packages/core/src/preset.ts
  • packages/core/src/services/conversation.ts
  • packages/core/src/services/conversation_types.ts
  • packages/core/src/services/types.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/core/src/services/conversation_types.ts

Comment thread packages/core/src/middlewares/chat/rollback_chat.ts Outdated
Comment thread packages/core/src/services/types.ts
Always resolve rollback commands through the conversation service using either the explicit target or the current conversation id. This keeps rollback requests pointed at the intended conversation after the conversation resolution refactor.
@dingyi222666 dingyi222666 merged commit 5215ecc into v1-dev Apr 14, 2026
3 of 5 checks passed
@dingyi222666 dingyi222666 deleted the fix/conversation-system branch April 14, 2026 15:10
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.

1 participant