| author | |
| committer | |
| log | 6aea858ed85fc3e8e4b41d6164b428a80895dcc7 |
| tree | 5b874cdb67a5f7bb0aabdb7f5a996115d94126b0 |
| parent | f07b6ac8e6d17efde13fe3135bb52159962b5bdc |
- Include `cacheScope` in checkpoint diff query keys
- Pass turn/conversation-specific scopes from `ChatView` and `DiffPanel`
- Add tests for key separation and API argument forwarding4 files changed, 64 insertions(+), 0 deletions(-)
apps/web/src/components/ChatView.tsx+1| ... | ... | @@ -529,6 +529,7 @@ export default function ChatView() { |
| 529 | 529 | threadRuntimeId: activeThreadRuntimeId, |
| 530 | 530 | fromTurnCount: target.fromTurnCount, |
| 531 | 531 | toTurnCount: target.toTurnCount, |
| 532 | cacheScope: `turn:${target.turnId}`, | |
| 532 | 533 | }), |
| 533 | 534 | ), |
| 534 | 535 | }); |
apps/web/src/components/DiffPanel.tsx+8| ... | ... | @@ -138,12 +138,19 @@ export default function DiffPanel({ mode = "inline" }: DiffPanelProps) { |
| 138 | 138 | const activeCheckpointRange = selectedTurn |
| 139 | 139 | ? selectedCheckpointRange |
| 140 | 140 | : conversationCheckpointRange; |
| 141 | const conversationCacheScope = useMemo(() => { | |
| 142 | if (selectedTurn || turnDiffSummaries.length === 0) { | |
| 143 | return null; | |
| 144 | } | |
| 145 | return `conversation:${turnDiffSummaries.map((summary) => summary.turnId).join(",")}`; | |
| 146 | }, [selectedTurn, turnDiffSummaries]); | |
| 141 | 147 | const activeCheckpointDiffQuery = useQuery( |
| 142 | 148 | checkpointDiffQueryOptions(api, { |
| 143 | 149 | sessionId: activeSessionId, |
| 144 | 150 | threadRuntimeId: activeThreadRuntimeId, |
| 145 | 151 | fromTurnCount: activeCheckpointRange?.fromTurnCount ?? null, |
| 146 | 152 | toTurnCount: activeCheckpointRange?.toTurnCount ?? null, |
| 153 | cacheScope: selectedTurn ? `turn:${selectedTurn.turnId}` : conversationCacheScope, | |
| 147 | 154 | }), |
| 148 | 155 | ); |
| 149 | 156 | const selectedTurnCheckpointDiff = selectedTurn |
| ... | ... | @@ -184,6 +191,7 @@ export default function DiffPanel({ mode = "inline" }: DiffPanelProps) { |
| 184 | 191 | threadRuntimeId: activeThreadRuntimeId, |
| 185 | 192 | fromTurnCount: Math.max(0, checkpointTurnCount - 1), |
| 186 | 193 | toTurnCount: checkpointTurnCount, |
| 194 | cacheScope: `turn:${summary.turnId}`, | |
| 187 | 195 | }), |
| 188 | 196 | )?.diff; |
| 189 | 197 | if (checkpointPatch) { |
apps/web/src/lib/providerReactQuery.test.ts created+53| ... | ... | @@ -0,0 +1,53 @@ |
| 1 | import type { NativeApi } from "@t3tools/contracts"; | |
| 2 | import { describe, expect, it, vi } from "vitest"; | |
| 3 | import { checkpointDiffQueryOptions, providerQueryKeys } from "./providerReactQuery"; | |
| 4 | ||
| 5 | describe("providerQueryKeys.checkpointDiff", () => { | |
| 6 | it("includes cacheScope so reused turn counts do not collide", () => { | |
| 7 | const baseInput = { | |
| 8 | sessionId: "session-id", | |
| 9 | threadRuntimeId: "thread-id", | |
| 10 | fromTurnCount: 1, | |
| 11 | toTurnCount: 2, | |
| 12 | } as const; | |
| 13 | ||
| 14 | expect( | |
| 15 | providerQueryKeys.checkpointDiff({ | |
| 16 | ...baseInput, | |
| 17 | cacheScope: "turn:old-turn", | |
| 18 | }), | |
| 19 | ).not.toEqual( | |
| 20 | providerQueryKeys.checkpointDiff({ | |
| 21 | ...baseInput, | |
| 22 | cacheScope: "turn:new-turn", | |
| 23 | }), | |
| 24 | ); | |
| 25 | }); | |
| 26 | }); | |
| 27 | ||
| 28 | describe("checkpointDiffQueryOptions", () => { | |
| 29 | it("forwards checkpoint range to the provider API", async () => { | |
| 30 | const getCheckpointDiff = vi.fn().mockResolvedValue({ diff: "patch" }); | |
| 31 | const api = { | |
| 32 | providers: { | |
| 33 | getCheckpointDiff, | |
| 34 | }, | |
| 35 | } as unknown as NativeApi; | |
| 36 | ||
| 37 | const options = checkpointDiffQueryOptions(api, { | |
| 38 | sessionId: "session-id", | |
| 39 | threadRuntimeId: "thread-id", | |
| 40 | fromTurnCount: 3, | |
| 41 | toTurnCount: 4, | |
| 42 | cacheScope: "turn:abc", | |
| 43 | }); | |
| 44 | ||
| 45 | await options.queryFn(); | |
| 46 | ||
| 47 | expect(getCheckpointDiff).toHaveBeenCalledWith({ | |
| 48 | sessionId: "session-id", | |
| 49 | fromTurnCount: 3, | |
| 50 | toTurnCount: 4, | |
| 51 | }); | |
| 52 | }); | |
| 53 | }); |
apps/web/src/lib/providerReactQuery.ts+2| ... | ... | @@ -6,6 +6,7 @@ export interface CheckpointDiffQueryInput { |
| 6 | 6 | threadRuntimeId: string | null; |
| 7 | 7 | fromTurnCount: number | null; |
| 8 | 8 | toTurnCount: number | null; |
| 9 | cacheScope?: string | null; | |
| 9 | 10 | } |
| 10 | 11 | |
| 11 | 12 | export const providerQueryKeys = { |
| ... | ... | @@ -18,6 +19,7 @@ export const providerQueryKeys = { |
| 18 | 19 | input.threadRuntimeId, |
| 19 | 20 | input.fromTurnCount, |
| 20 | 21 | input.toTurnCount, |
| 22 | input.cacheScope ?? null, | |
| 21 | 23 | ] as const, |
| 22 | 24 | }; |
| 23 | 25 |