refactor(session): clarify reference boundaries

This commit is contained in:
Xubin Ren
2026-08-04 12:14:51 +08:00
parent d8aeb0eb2c
commit d99f589a59
9 changed files with 108 additions and 43 deletions
+18 -9
View File
@@ -1325,14 +1325,23 @@ export function ThreadComposer({
logoUrl: preset.logo_url ?? null,
initials: mcpPresetInitials(preset),
}));
return [
...sessionCandidates.slice(0, 4),
...cliCandidates.slice(0, 2),
...mcpCandidates.slice(0, 2),
...sessionCandidates.slice(4),
...cliCandidates.slice(2),
...mcpCandidates.slice(2),
].slice(0, 8);
const groups = [
{ candidates: cliCandidates, reserved: 2 },
{ candidates: mcpCandidates, reserved: 2 },
{ candidates: sessionCandidates, reserved: 4 },
];
let remaining = 8;
const counts = groups.map(({ candidates, reserved }) => {
const count = Math.min(candidates.length, reserved);
remaining -= count;
return count;
});
for (const index of [2, 0, 1]) {
const extra = Math.min(remaining, groups[index].candidates.length - counts[index]);
counts[index] += extra;
remaining -= extra;
}
return groups.flatMap(({ candidates }, index) => candidates.slice(0, counts[index]));
}, [activeSessionMentions, availableSessionMentions, cliAppMention, cliApps, mcpPresets]);
const showCliAppMenu = filteredMentionCandidates.length > 0;
@@ -2660,7 +2669,7 @@ function CliAppMentionPalette({
layout.maxHeight - SLASH_PALETTE_CHROME_PX,
);
const listRef = useSelectedOptionScroll(selectedIndex);
const groupedCandidates = (["session", "cli", "mcp"] as const)
const groupedCandidates = (["cli", "mcp", "session"] as const)
.map((kind) => ({
kind,
label: kind === "session"
+5
View File
@@ -1596,6 +1596,7 @@ describe("ThreadComposer", () => {
onSend={vi.fn()}
placeholder="Type your message..."
cliApps={CLI_APPS}
mcpPresets={MCP_PRESETS}
sessions={[
...["a", "b"].map((chatId) => session(chatId, "Plan")),
session("blender-chat", "Blender", "3D notes"),
@@ -1606,6 +1607,10 @@ describe("ThreadComposer", () => {
const input = screen.getByLabelText("Message input");
fireEvent.change(input, { target: { value: "@", selectionStart: 1 } });
const palette = screen.getByRole("listbox", { name: "Mentions" });
expect(within(palette).getAllByRole("group").map((group) => (
group.getAttribute("aria-label")
))).toEqual(["CLI apps", "MCP services", "Nanobot conversations"]);
const options = screen.getAllByRole("option", { name: /Plan @Plan/i });
expect(options.map((option) => option.textContent)).toEqual([
expect.stringContaining("@Plan"),