| 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,6 +529,7 @@ export default function ChatView() { |
| 529 | threadRuntimeId: activeThreadRuntimeId, | 529 | threadRuntimeId: activeThreadRuntimeId, |
| 530 | fromTurnCount: target.fromTurnCount, | 530 | fromTurnCount: target.fromTurnCount, |
| 531 | toTurnCount: target.toTurnCount, | 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,12 +138,19 @@ export default function DiffPanel({ mode = "inline" }: DiffPanelProps) { |
| 138 | const activeCheckpointRange = selectedTurn | 138 | const activeCheckpointRange = selectedTurn |
| 139 | ? selectedCheckpointRange | 139 | ? selectedCheckpointRange |
| 140 | : conversationCheckpointRange; | 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 | const activeCheckpointDiffQuery = useQuery( | 147 | const activeCheckpointDiffQuery = useQuery( |
| 142 | checkpointDiffQueryOptions(api, { | 148 | checkpointDiffQueryOptions(api, { |
| 143 | sessionId: activeSessionId, | 149 | sessionId: activeSessionId, |
| 144 | threadRuntimeId: activeThreadRuntimeId, | 150 | threadRuntimeId: activeThreadRuntimeId, |
| 145 | fromTurnCount: activeCheckpointRange?.fromTurnCount ?? null, | 151 | fromTurnCount: activeCheckpointRange?.fromTurnCount ?? null, |
| 146 | toTurnCount: activeCheckpointRange?.toTurnCount ?? null, | 152 | toTurnCount: activeCheckpointRange?.toTurnCount ?? null, |
| 153 | cacheScope: selectedTurn ? `turn:${selectedTurn.turnId}` : conversationCacheScope, | ||
| 147 | }), | 154 | }), |
| 148 | ); | 155 | ); |
| 149 | const selectedTurnCheckpointDiff = selectedTurn | 156 | const selectedTurnCheckpointDiff = selectedTurn |
| ... | @@ -184,6 +191,7 @@ export default function DiffPanel({ mode = "inline" }: DiffPanelProps) { | ... | @@ -184,6 +191,7 @@ export default function DiffPanel({ mode = "inline" }: DiffPanelProps) { |
| 184 | threadRuntimeId: activeThreadRuntimeId, | 191 | threadRuntimeId: activeThreadRuntimeId, |
| 185 | fromTurnCount: Math.max(0, checkpointTurnCount - 1), | 192 | fromTurnCount: Math.max(0, checkpointTurnCount - 1), |
| 186 | toTurnCount: checkpointTurnCount, | 193 | toTurnCount: checkpointTurnCount, |
| 194 | cacheScope: `turn:${summary.turnId}`, | ||
| 187 | }), | 195 | }), |
| 188 | )?.diff; | 196 | )?.diff; |
| 189 | if (checkpointPatch) { | 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 +6,7 @@ export interface CheckpointDiffQueryInput { |
| 6 | threadRuntimeId: string | null; | 6 | threadRuntimeId: string | null; |
| 7 | fromTurnCount: number | null; | 7 | fromTurnCount: number | null; |
| 8 | toTurnCount: number | null; | 8 | toTurnCount: number | null; |
| 9 | cacheScope?: string | null; | ||
| 9 | } | 10 | } |
| 10 | 11 | ||
| 11 | export const providerQueryKeys = { | 12 | export const providerQueryKeys = { |
| ... | @@ -18,6 +19,7 @@ export const providerQueryKeys = { | ... | @@ -18,6 +19,7 @@ export const providerQueryKeys = { |
| 18 | input.threadRuntimeId, | 19 | input.threadRuntimeId, |
| 19 | input.fromTurnCount, | 20 | input.fromTurnCount, |
| 20 | input.toTurnCount, | 21 | input.toTurnCount, |
| 22 | input.cacheScope ?? null, | ||
| 21 | ] as const, | 23 | ] as const, |
| 22 | }; | 24 | }; |
| 23 | 25 |