Merge PR #7740: fix(session): isolate rewind reports by checkpoint cycle (@roboomp)
This commit is contained in:
@@ -37,6 +37,7 @@
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed resumed or rebuilt sessions auto-applying a new checkpoint with a stale rewind report from an earlier completed checkpoint cycle ([#7739](https://github.com/can1357/oh-my-pi/issues/7739)).
|
||||
- Retried concurrent-request caps with a short backoff without deleting valid Copilot credentials or rotating through sibling accounts.
|
||||
- Fixed the default `textVerbosity` setting being forwarded to OpenAI Codex requests unless the user explicitly configures it, preserving Codex's native response-control defaults. ([#4949](https://github.com/can1357/oh-my-pi/issues/4949))
|
||||
- Reduced streaming CPU usage by coalescing the cumulative `message_update` deltas of a turn at the event-controller dispatch boundary: at most one streaming-state rebuild runs per ~33ms window instead of one per token, cutting the per-token handler work that dominated the CPU profile of streaming sessions (especially at high token rates) while preserving per-delta speech output. Subscriber dispatch is serialized so a rapid stream tail (`message_update` → `message_end` → `agent_end`) cannot overtake the coalesced flush. ([#7443](https://github.com/can1357/oh-my-pi/issues/7443))
|
||||
|
||||
@@ -6681,9 +6681,10 @@ export class AgentSession {
|
||||
}
|
||||
|
||||
#extractRewindReport(messages: AgentMessage[]): string | undefined {
|
||||
if (!this.#checkpointState) return undefined;
|
||||
const checkpointState = this.#checkpointState;
|
||||
if (!checkpointState) return undefined;
|
||||
if (this.#pendingRewindReport) return this.#pendingRewindReport;
|
||||
for (let i = messages.length - 1; i >= 0; i--) {
|
||||
for (let i = messages.length - 1; i >= checkpointState.checkpointMessageCount; i--) {
|
||||
const message = messages[i];
|
||||
if (message?.role !== "toolResult" || message.isError) continue;
|
||||
const semanticResult = semanticToolResult(message.toolName, message);
|
||||
|
||||
@@ -267,6 +267,50 @@ describe("AgentSession checkpoint rewind branch context", () => {
|
||||
expect(finalThinking?.thinkingSignature).toBe("sig_after_rewind");
|
||||
});
|
||||
|
||||
it("ignores a completed cycle's rewind result after rebuilding context", async () => {
|
||||
const staleReport = "findings from the previous checkpoint";
|
||||
const currentReport = "findings from the current checkpoint";
|
||||
const { session, mock } = await createHarness([
|
||||
{
|
||||
content: [
|
||||
{ type: "toolCall", id: "call_checkpoint_a", name: "checkpoint", arguments: { goal: "inspect A" } },
|
||||
],
|
||||
stopReason: "toolUse",
|
||||
},
|
||||
{
|
||||
content: [{ type: "toolCall", id: "call_rewind_a", name: "rewind", arguments: { report: staleReport } }],
|
||||
stopReason: "toolUse",
|
||||
},
|
||||
{ content: ["DONE"], stopReason: "stop" },
|
||||
]);
|
||||
await session.prompt("investigate the first checkpoint");
|
||||
|
||||
session.sessionManager.appendMessage({
|
||||
role: "toolResult",
|
||||
toolCallId: "call_rewind_a_late",
|
||||
toolName: "rewind",
|
||||
content: [{ type: "text", text: "rewind requested" }],
|
||||
details: { report: staleReport, rewound: true },
|
||||
isError: false,
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
session.agent.replaceMessages(session.buildDisplaySessionContext().messages);
|
||||
|
||||
mock.push({
|
||||
content: [{ type: "toolCall", id: "call_checkpoint_b", name: "checkpoint", arguments: { goal: "inspect B" } }],
|
||||
stopReason: "toolUse",
|
||||
});
|
||||
mock.push({
|
||||
content: [{ type: "toolCall", id: "call_rewind_b", name: "rewind", arguments: { report: currentReport } }],
|
||||
stopReason: "toolUse",
|
||||
});
|
||||
mock.push({ content: ["DONE"], stopReason: "stop" });
|
||||
|
||||
await session.prompt("investigate the second checkpoint");
|
||||
|
||||
expect(session.getLastCompletedRewind()?.report).toBe(currentReport);
|
||||
});
|
||||
|
||||
it("does not start checkpoint tracking for xdev help envelopes", async () => {
|
||||
const { session } = await createHarness(
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user