mirror of
https://github.com/CopilotKit/CopilotKit.git
synced 2026-09-14 16:26:20 +08:00
fix(web-inspector): drop stale Try from here results
This commit is contained in:
@@ -625,6 +625,67 @@ test("Try from here copies a stored thread into Playground without changing the
|
||||
}
|
||||
});
|
||||
|
||||
test("Try from here discards a stale copy after leaving Threads", async () => {
|
||||
const context = await setup({
|
||||
agent: true,
|
||||
agentIds: ["default"],
|
||||
threads: [SAVED_THREAD],
|
||||
});
|
||||
try {
|
||||
await context.open();
|
||||
await context.selectLeaf("threads");
|
||||
await selectSavedThread(context.inspector);
|
||||
|
||||
const pendingFetch = globalThis.fetch;
|
||||
let releaseMessages!: () => void;
|
||||
let messagesResolved = false;
|
||||
const messagesGate = new Promise<void>((resolve) => {
|
||||
releaseMessages = resolve;
|
||||
});
|
||||
vi.stubGlobal(
|
||||
"fetch",
|
||||
async (input: RequestInfo | URL, init?: RequestInit) => {
|
||||
const url = input instanceof Request ? input.url : String(input);
|
||||
const isMessages = url.endsWith("/threads/thread-1/messages");
|
||||
if (isMessages) {
|
||||
await messagesGate;
|
||||
}
|
||||
const response = await pendingFetch(input, init);
|
||||
if (isMessages) {
|
||||
messagesResolved = true;
|
||||
}
|
||||
return response;
|
||||
},
|
||||
);
|
||||
|
||||
const root = requireElement(
|
||||
context.inspector.shadowRoot,
|
||||
"Web Inspector shadow root was not rendered",
|
||||
);
|
||||
const button = requireElement(
|
||||
tryFromHereButton(root),
|
||||
"Try from here was not rendered",
|
||||
);
|
||||
button.click();
|
||||
await context.selectLeaf("home");
|
||||
expectCurrentNavigation(root, "home", "home");
|
||||
|
||||
releaseMessages();
|
||||
await waitFor(() => messagesResolved, "stale Try from here load");
|
||||
await context.inspector.updateComplete;
|
||||
|
||||
expectCurrentNavigation(root, "home", "home");
|
||||
await context.selectLeaf("playground");
|
||||
expect(root.textContent).not.toContain("Earlier answer");
|
||||
expect(
|
||||
root.querySelector<HTMLSelectElement>("#cpk-playground-thread-source")
|
||||
?.value ?? "",
|
||||
).not.toBe("thread-1");
|
||||
} finally {
|
||||
context.teardown();
|
||||
}
|
||||
});
|
||||
|
||||
test("Try from here stays on Threads when messages fail", async () => {
|
||||
const context = await setup({
|
||||
agent: true,
|
||||
|
||||
@@ -14779,19 +14779,28 @@ export class WebInspectorElement extends LitElement {
|
||||
this.tryFromHereError = null;
|
||||
this.requestUpdate();
|
||||
|
||||
const isCurrentTryFromHereRequest = (): boolean =>
|
||||
this.selectedThreadId === threadId && this.selectedMenu === "threads";
|
||||
|
||||
try {
|
||||
const snapshot = await this.loadThreadSnapshot(thread);
|
||||
this.applyThreadSnapshotToPlayground(thread, snapshot);
|
||||
// A later thread or pane change owns the UI. Keep the fetch outcome
|
||||
// for telemetry, but do not replace Playground or leave Threads.
|
||||
if (isCurrentTryFromHereRequest()) {
|
||||
this.applyThreadSnapshotToPlayground(thread, snapshot);
|
||||
this.handleMenuSelect("playground");
|
||||
}
|
||||
if (!this.core?.telemetryDisabled) {
|
||||
trackThreadsTryFromHereClicked({
|
||||
...this.getThreadsTelemetryProps(),
|
||||
outcome: "success",
|
||||
});
|
||||
}
|
||||
this.handleMenuSelect("playground");
|
||||
} catch (error) {
|
||||
this.tryFromHereError =
|
||||
error instanceof Error ? error.message : "Failed to load thread.";
|
||||
if (isCurrentTryFromHereRequest()) {
|
||||
this.tryFromHereError =
|
||||
error instanceof Error ? error.message : "Failed to load thread.";
|
||||
}
|
||||
if (!this.core?.telemetryDisabled) {
|
||||
trackThreadsTryFromHereClicked({
|
||||
...this.getThreadsTelemetryProps(),
|
||||
|
||||
@@ -82,7 +82,7 @@ The button is hidden on example tour threads and when thread inspect cannot load
|
||||
- Map stored thread messages onto Playground agent messages (user, assistant, tool), then `clone()` the source agent, assign a new Playground thread id, `setMessages`, `setState`.
|
||||
- Fetch the snapshot first. Replace the scratch session only after a successful messages load. This is the control flow from the grill (not a demo):
|
||||
|
||||
```
|
||||
```text
|
||||
snapshot = loadThread(threadId)
|
||||
if snapshot.messagesFailed:
|
||||
showErrorOnThreads(error)
|
||||
|
||||
Reference in New Issue
Block a user