Rewind chat or files from any user message (#1154)
* Add Pi extension-launch plumbing for in-process tree primitives
* Add Rewind controls for agent sessions
* Preserve SDK checkpoint env var so Claude file rewind works
The SDK injects CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING=true when file checkpointing is enabled. The earlier parent-env stripping from c4782ec71c was too broad and removed that child flag along with real parent-session markers.
Keep stripping parent markers, but preserve the checkpoint flag so the SDK rewind path can run directly. With that boundary fixed, the JSONL file-rewind fallback is no longer needed.
* Update OpenCode history replay tests for rewind state
* Show Rewind actions in an adaptive sheet
* Fix rewind semantics across providers
* Refactor Pi IDs through extension capture
* Restore user message to composer after rewind
* Fix Claude rewind tool result mapping
* Fix Claude rewind session switch roundtrip
* Fix rewind and optimistic message regressions
* Tighten rewind test discipline
* Fix OpenCode optimistic message reconciliation
* Reconcile optimistic user messages by marker
* Reorder user message actions
* Unify provider user message contract
* Add Claude rewind flow Playwright contract
* Add Codex rewind flow Playwright contract
* Add OpenCode rewind flow Playwright contract
* Add Pi rewind flow Playwright contract
* Remove real-provider rewind Playwright contracts
* Gate real-provider rewind specs from CI Playwright
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
import { useMemo } from "react";
|
||||
import type { AgentCapabilityFlags } from "@server/server/agent/agent-sdk-types";
|
||||
|
||||
export type RewindMode = "conversation" | "files" | "both";
|
||||
|
||||
export interface RewindMenuItem {
|
||||
mode: RewindMode;
|
||||
label: string;
|
||||
testID: string;
|
||||
}
|
||||
|
||||
export function resolveRewindMenuItems(
|
||||
capabilities:
|
||||
| Pick<
|
||||
AgentCapabilityFlags,
|
||||
"supportsRewindConversation" | "supportsRewindFiles" | "supportsRewindBoth"
|
||||
>
|
||||
| null
|
||||
| undefined,
|
||||
): RewindMenuItem[] {
|
||||
if (!capabilities) {
|
||||
return [];
|
||||
}
|
||||
const items: RewindMenuItem[] = [];
|
||||
if (capabilities.supportsRewindConversation) {
|
||||
items.push({
|
||||
mode: "conversation",
|
||||
label: "Rewind conversation",
|
||||
testID: "rewind-menu-conversation",
|
||||
});
|
||||
}
|
||||
if (capabilities.supportsRewindFiles) {
|
||||
items.push({
|
||||
mode: "files",
|
||||
label: "Rewind files",
|
||||
testID: "rewind-menu-files",
|
||||
});
|
||||
}
|
||||
if (capabilities.supportsRewindBoth) {
|
||||
items.push({
|
||||
mode: "both",
|
||||
label: "Rewind conversation and files",
|
||||
testID: "rewind-menu-both",
|
||||
});
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
export function useRewindCapabilities(
|
||||
capabilities: Parameters<typeof resolveRewindMenuItems>[0],
|
||||
): RewindMenuItem[] {
|
||||
return useMemo(() => resolveRewindMenuItems(capabilities), [capabilities]);
|
||||
}
|
||||
Reference in New Issue
Block a user