Review of #156 (Request changes) flagged the new CLIENT logic as untested. Extract the decision logic from chat-thread.tsx into pure, unit-testable helpers and cover both branches the reviewer called out: - `roleLaunchMessage(role, default)` — the three-way handleRolePick behavior: autoStart=false -> null (send nothing); autoStart=true + custom -> trimmed message; autoStart=true + empty/null/whitespace -> default fallback. - `shouldResetRolePicked(chatId, roleId, flag)` — the #149 render-phase reset; the regression test asserts the stuck-flag case (New chat after an autoStart=false pick -> cards return) that the pre-fix code never handled, and that a still-bound role keeps the cards hidden. chat-thread.tsx now calls these helpers (behavior unchanged). 9 new pure tests. Also folded the review's cosmetic suggestion: `x ? x : null` -> `x || null` in ai-agent-roles.repo.ts (identical for string|null|undefined). Client tsc clean; role-launch + role-cards green; repo spec green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
35 lines
1.4 KiB
TypeScript
35 lines
1.4 KiB
TypeScript
import type { IAiRole } from "@/features/ai-chat/types/ai-chat.types.ts";
|
|
|
|
/**
|
|
* Decide what (if anything) to auto-send when an agent role card is picked
|
|
* (issue #149). Extracted as a pure function so the three-way behavior is
|
|
* unit-testable without mounting the chat-thread component:
|
|
* - autoStart=false -> null (bind the role only, send nothing)
|
|
* - autoStart=true + message -> the trimmed custom launchMessage
|
|
* - autoStart=true + empty/null -> the default fallback text
|
|
*/
|
|
export function roleLaunchMessage(
|
|
role: Pick<IAiRole, "autoStart" | "launchMessage">,
|
|
defaultText: string,
|
|
): string | null {
|
|
if (!role.autoStart) return null;
|
|
return role.launchMessage?.trim() || defaultText;
|
|
}
|
|
|
|
/**
|
|
* Whether the "role picked but nothing sent yet" flag (`rolePickedNoSend`)
|
|
* should reset to false. After an autoStart=false pick the thread shows the
|
|
* composer with chatId still null; when the user then starts a fresh chat the
|
|
* parent clears the bound role (roleId -> null) but chatId stays null, so the
|
|
* thread never remounts and the flag would otherwise stay set — hiding the role
|
|
* cards forever. Reset exactly in that state; a still-bound role (roleId set)
|
|
* keeps the cards hidden. (Regression guard for #149.)
|
|
*/
|
|
export function shouldResetRolePicked(
|
|
chatId: string | null,
|
|
roleId: string | null | undefined,
|
|
rolePickedNoSend: boolean,
|
|
): boolean {
|
|
return chatId === null && roleId == null && rolePickedNoSend;
|
|
}
|