@getpaseo/server 0.1.80 → 0.1.82
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server/client/daemon-client.d.ts +6 -2
- package/dist/server/client/daemon-client.d.ts.map +1 -1
- package/dist/server/client/daemon-client.js +36 -1
- package/dist/server/client/daemon-client.js.map +1 -1
- package/dist/server/client/terminal-stream-router.d.ts +4 -0
- package/dist/server/client/terminal-stream-router.d.ts.map +1 -1
- package/dist/server/client/terminal-stream-router.js +8 -0
- package/dist/server/client/terminal-stream-router.js.map +1 -1
- package/dist/server/server/agent/agent-manager.d.ts +9 -7
- package/dist/server/server/agent/agent-manager.d.ts.map +1 -1
- package/dist/server/server/agent/agent-manager.js +78 -92
- package/dist/server/server/agent/agent-manager.js.map +1 -1
- package/dist/server/server/agent/agent-metadata-generator.d.ts.map +1 -1
- package/dist/server/server/agent/agent-metadata-generator.js +6 -7
- package/dist/server/server/agent/agent-metadata-generator.js.map +1 -1
- package/dist/server/server/agent/agent-projections.d.ts.map +1 -1
- package/dist/server/server/agent/agent-projections.js +4 -4
- package/dist/server/server/agent/agent-projections.js.map +1 -1
- package/dist/server/server/agent/agent-prompt.d.ts +2 -9
- package/dist/server/server/agent/agent-prompt.d.ts.map +1 -1
- package/dist/server/server/agent/agent-prompt.js +7 -18
- package/dist/server/server/agent/agent-prompt.js.map +1 -1
- package/dist/server/server/agent/agent-response-loop.d.ts +5 -0
- package/dist/server/server/agent/agent-response-loop.d.ts.map +1 -1
- package/dist/server/server/agent/agent-response-loop.js +12 -1
- package/dist/server/server/agent/agent-response-loop.js.map +1 -1
- package/dist/server/server/agent/agent-sdk-types.d.ts +13 -0
- package/dist/server/server/agent/agent-sdk-types.d.ts.map +1 -1
- package/dist/server/server/agent/agent-sdk-types.js.map +1 -1
- package/dist/server/server/agent/agent-storage.d.ts +2 -7
- package/dist/server/server/agent/agent-storage.d.ts.map +1 -1
- package/dist/server/server/agent/agent-storage.js +2 -16
- package/dist/server/server/agent/agent-storage.js.map +1 -1
- package/dist/server/server/agent/agent-timeline-store-types.d.ts +0 -4
- package/dist/server/server/agent/agent-timeline-store-types.d.ts.map +1 -1
- package/dist/server/server/agent/agent-timeline-store.d.ts +0 -5
- package/dist/server/server/agent/agent-timeline-store.d.ts.map +1 -1
- package/dist/server/server/agent/agent-timeline-store.js +0 -33
- package/dist/server/server/agent/agent-timeline-store.js.map +1 -1
- package/dist/server/server/agent/import-sessions.d.ts.map +1 -1
- package/dist/server/server/agent/import-sessions.js +6 -0
- package/dist/server/server/agent/import-sessions.js.map +1 -1
- package/dist/server/server/agent/mcp-server.d.ts.map +1 -1
- package/dist/server/server/agent/mcp-server.js +0 -9
- package/dist/server/server/agent/mcp-server.js.map +1 -1
- package/dist/server/server/agent/provider-launch-config.d.ts.map +1 -1
- package/dist/server/server/agent/provider-launch-config.js +0 -1
- package/dist/server/server/agent/provider-launch-config.js.map +1 -1
- package/dist/server/server/agent/provider-manifest.d.ts +1 -1
- package/dist/server/server/agent/provider-manifest.d.ts.map +1 -1
- package/dist/server/server/agent/provider-registry.d.ts +2 -1
- package/dist/server/server/agent/provider-registry.d.ts.map +1 -1
- package/dist/server/server/agent/provider-registry.js +5 -1
- package/dist/server/server/agent/provider-registry.js.map +1 -1
- package/dist/server/server/agent/provider-snapshot-manager.d.ts +2 -2
- package/dist/server/server/agent/provider-snapshot-manager.d.ts.map +1 -1
- package/dist/server/server/agent/provider-snapshot-manager.js +60 -26
- package/dist/server/server/agent/provider-snapshot-manager.js.map +1 -1
- package/dist/server/server/agent/providers/acp-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/acp-agent.js +3 -0
- package/dist/server/server/agent/providers/acp-agent.js.map +1 -1
- package/dist/server/server/agent/providers/claude/agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/claude/agent.js +275 -85
- package/dist/server/server/agent/providers/claude/agent.js.map +1 -1
- package/dist/server/server/agent/providers/claude/rewind.d.ts +30 -0
- package/dist/server/server/agent/providers/claude/rewind.d.ts.map +1 -0
- package/dist/server/server/agent/providers/claude/rewind.js +30 -0
- package/dist/server/server/agent/providers/claude/rewind.js.map +1 -0
- package/dist/server/server/agent/providers/claude/test-rewind-claude-sdk.d.ts +24 -0
- package/dist/server/server/agent/providers/claude/test-rewind-claude-sdk.d.ts.map +1 -0
- package/dist/server/server/agent/providers/claude/test-rewind-claude-sdk.js +23 -0
- package/dist/server/server/agent/providers/claude/test-rewind-claude-sdk.js.map +1 -0
- package/dist/server/server/agent/providers/codex/app-server-transport.d.ts +168 -0
- package/dist/server/server/agent/providers/codex/app-server-transport.d.ts.map +1 -1
- package/dist/server/server/agent/providers/codex/app-server-transport.js +48 -0
- package/dist/server/server/agent/providers/codex/app-server-transport.js.map +1 -1
- package/dist/server/server/agent/providers/codex/rewind.d.ts +21 -0
- package/dist/server/server/agent/providers/codex/rewind.d.ts.map +1 -0
- package/dist/server/server/agent/providers/codex/rewind.js +46 -0
- package/dist/server/server/agent/providers/codex/rewind.js.map +1 -0
- package/dist/server/server/agent/providers/codex/test-utils/fake-app-server.d.ts +5 -0
- package/dist/server/server/agent/providers/codex/test-utils/fake-app-server.d.ts.map +1 -1
- package/dist/server/server/agent/providers/codex/test-utils/fake-app-server.js +45 -0
- package/dist/server/server/agent/providers/codex/test-utils/fake-app-server.js.map +1 -1
- package/dist/server/server/agent/providers/codex/tool-call-mapper.d.ts +1 -1
- package/dist/server/server/agent/providers/codex/tool-call-mapper.d.ts.map +1 -1
- package/dist/server/server/agent/providers/codex/tool-call-mapper.js +11 -11
- package/dist/server/server/agent/providers/codex/tool-call-mapper.js.map +1 -1
- package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +32 -34
- package/dist/server/server/agent/providers/codex-app-server-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/codex-app-server-agent.js +206 -60
- package/dist/server/server/agent/providers/codex-app-server-agent.js.map +1 -1
- package/dist/server/server/agent/providers/copilot-acp-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/copilot-acp-agent.js +3 -0
- package/dist/server/server/agent/providers/copilot-acp-agent.js.map +1 -1
- package/dist/server/server/agent/providers/mock-load-test-agent.d.ts +13 -0
- package/dist/server/server/agent/providers/mock-load-test-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/mock-load-test-agent.js +55 -1
- package/dist/server/server/agent/providers/mock-load-test-agent.js.map +1 -1
- package/dist/server/server/agent/providers/opencode/rewind.d.ts +18 -0
- package/dist/server/server/agent/providers/opencode/rewind.d.ts.map +1 -0
- package/dist/server/server/agent/providers/opencode/rewind.js +14 -0
- package/dist/server/server/agent/providers/opencode/rewind.js.map +1 -0
- package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-runtime.d.ts +4 -0
- package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-runtime.d.ts.map +1 -1
- package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-runtime.js +12 -2
- package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-runtime.js.map +1 -1
- package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.d.ts.map +1 -1
- package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js +110 -2
- package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js.map +1 -1
- package/dist/server/server/agent/providers/opencode-agent.d.ts +18 -0
- package/dist/server/server/agent/providers/opencode-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/opencode-agent.js +265 -42
- package/dist/server/server/agent/providers/opencode-agent.js.map +1 -1
- package/dist/server/server/agent/providers/pi/agent.d.ts +23 -1
- package/dist/server/server/agent/providers/pi/agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/pi/agent.js +470 -17
- package/dist/server/server/agent/providers/pi/agent.js.map +1 -1
- package/dist/server/server/agent/providers/pi/cli-runtime.js +4 -1
- package/dist/server/server/agent/providers/pi/cli-runtime.js.map +1 -1
- package/dist/server/server/agent/providers/pi/history-mapper.d.ts +5 -1
- package/dist/server/server/agent/providers/pi/history-mapper.d.ts.map +1 -1
- package/dist/server/server/agent/providers/pi/history-mapper.js +3 -2
- package/dist/server/server/agent/providers/pi/history-mapper.js.map +1 -1
- package/dist/server/server/agent/providers/pi/rewind.d.ts +8 -0
- package/dist/server/server/agent/providers/pi/rewind.d.ts.map +1 -0
- package/dist/server/server/agent/providers/pi/rewind.js +8 -0
- package/dist/server/server/agent/providers/pi/rewind.js.map +1 -0
- package/dist/server/server/agent/providers/pi/rpc-types.d.ts +10 -0
- package/dist/server/server/agent/providers/pi/rpc-types.d.ts.map +1 -1
- package/dist/server/server/agent/providers/pi/runtime.d.ts +7 -0
- package/dist/server/server/agent/providers/pi/runtime.d.ts.map +1 -1
- package/dist/server/server/agent/providers/pi/runtime.js +4 -0
- package/dist/server/server/agent/providers/pi/runtime.js.map +1 -1
- package/dist/server/server/agent/providers/pi/test-utils/fake-pi.d.ts +23 -0
- package/dist/server/server/agent/providers/pi/test-utils/fake-pi.d.ts.map +1 -1
- package/dist/server/server/agent/providers/pi/test-utils/fake-pi.js +54 -1
- package/dist/server/server/agent/providers/pi/test-utils/fake-pi.js.map +1 -1
- package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts +4 -1
- package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts.map +1 -1
- package/dist/server/server/agent/providers/tool-call-detail-primitives.js +57 -1
- package/dist/server/server/agent/providers/tool-call-detail-primitives.js.map +1 -1
- package/dist/server/server/agent/rewind/rewind.d.ts +10 -0
- package/dist/server/server/agent/rewind/rewind.d.ts.map +1 -0
- package/dist/server/server/agent/rewind/rewind.js +29 -0
- package/dist/server/server/agent/rewind/rewind.js.map +1 -0
- package/dist/server/server/agent/rewind/test-rewind-session.d.ts +48 -0
- package/dist/server/server/agent/rewind/test-rewind-session.d.ts.map +1 -0
- package/dist/server/server/agent/rewind/test-rewind-session.js +88 -0
- package/dist/server/server/agent/rewind/test-rewind-session.js.map +1 -0
- package/dist/server/server/persistence-hooks.d.ts.map +1 -1
- package/dist/server/server/persistence-hooks.js +0 -2
- package/dist/server/server/persistence-hooks.js.map +1 -1
- package/dist/server/server/session.d.ts +2 -0
- package/dist/server/server/session.d.ts.map +1 -1
- package/dist/server/server/session.js +39 -9
- package/dist/server/server/session.js.map +1 -1
- package/dist/server/server/websocket-server.d.ts.map +1 -1
- package/dist/server/server/websocket-server.js +4 -0
- package/dist/server/server/websocket-server.js.map +1 -1
- package/dist/server/server/worktree-branch-name-generator.d.ts +1 -0
- package/dist/server/server/worktree-branch-name-generator.d.ts.map +1 -1
- package/dist/server/server/worktree-branch-name-generator.js +5 -6
- package/dist/server/server/worktree-branch-name-generator.js.map +1 -1
- package/dist/server/shared/binary-frames/terminal.d.ts +1 -0
- package/dist/server/shared/binary-frames/terminal.d.ts.map +1 -1
- package/dist/server/shared/binary-frames/terminal.js +3 -1
- package/dist/server/shared/binary-frames/terminal.js.map +1 -1
- package/dist/server/shared/messages.d.ts +502 -0
- package/dist/server/shared/messages.d.ts.map +1 -1
- package/dist/server/shared/messages.js +43 -0
- package/dist/server/shared/messages.js.map +1 -1
- package/dist/server/shared/terminal-snapshot.d.ts +3 -0
- package/dist/server/shared/terminal-snapshot.d.ts.map +1 -0
- package/dist/server/shared/terminal-snapshot.js +165 -0
- package/dist/server/shared/terminal-snapshot.js.map +1 -0
- package/dist/server/terminal/terminal-manager.d.ts +2 -2
- package/dist/server/terminal/terminal-manager.d.ts.map +1 -1
- package/dist/server/terminal/terminal-manager.js +3 -3
- package/dist/server/terminal/terminal-manager.js.map +1 -1
- package/dist/server/terminal/terminal-restore.d.ts +17 -0
- package/dist/server/terminal/terminal-restore.d.ts.map +1 -0
- package/dist/server/terminal/terminal-restore.js +46 -0
- package/dist/server/terminal/terminal-restore.js.map +1 -0
- package/dist/server/terminal/terminal-session-controller.d.ts +3 -0
- package/dist/server/terminal/terminal-session-controller.d.ts.map +1 -1
- package/dist/server/terminal/terminal-session-controller.js +88 -27
- package/dist/server/terminal/terminal-session-controller.js.map +1 -1
- package/dist/server/terminal/terminal-worker-process.js +1 -1
- package/dist/server/terminal/terminal-worker-process.js.map +1 -1
- package/dist/server/terminal/terminal-worker-protocol.d.ts +2 -1
- package/dist/server/terminal/terminal-worker-protocol.d.ts.map +1 -1
- package/dist/server/terminal/terminal.d.ts +11 -2
- package/dist/server/terminal/terminal.d.ts.map +1 -1
- package/dist/server/terminal/terminal.js +33 -8
- package/dist/server/terminal/terminal.js.map +1 -1
- package/dist/server/terminal/worker-terminal-manager.d.ts.map +1 -1
- package/dist/server/terminal/worker-terminal-manager.js +16 -4
- package/dist/server/terminal/worker-terminal-manager.js.map +1 -1
- package/dist/server/utils/checkout-git.d.ts.map +1 -1
- package/dist/server/utils/checkout-git.js +7 -7
- package/dist/server/utils/checkout-git.js.map +1 -1
- package/dist/src/server/agent/agent-sdk-types.js.map +1 -1
- package/dist/src/server/agent/provider-launch-config.js +0 -1
- package/dist/src/server/agent/provider-launch-config.js.map +1 -1
- package/dist/src/shared/messages.js +43 -0
- package/dist/src/shared/messages.js.map +1 -1
- package/package.json +3 -3
- package/dist/server/server/agent/providers/codex-rollout-timeline.d.ts +0 -9
- package/dist/server/server/agent/providers/codex-rollout-timeline.d.ts.map +0 -1
- package/dist/server/server/agent/providers/codex-rollout-timeline.js +0 -555
- package/dist/server/server/agent/providers/codex-rollout-timeline.js.map +0 -1
- package/dist/server/server/agent/providers/pi/session-descriptor.d.ts +0 -10
- package/dist/server/server/agent/providers/pi/session-descriptor.d.ts.map +0 -1
- package/dist/server/server/agent/providers/pi/session-descriptor.js +0 -300
- package/dist/server/server/agent/providers/pi/session-descriptor.js.map +0 -1
|
@@ -12,6 +12,7 @@ import { formatDiagnosticStatus, formatProviderDiagnostic, formatProviderDiagnos
|
|
|
12
12
|
import { appendOrReplaceGrowingAssistantMessage, runProviderTurn } from "../provider-runner.js";
|
|
13
13
|
import { renderPromptAttachmentAsText } from "../../prompt-attachments.js";
|
|
14
14
|
import { claudeQuery } from "./query.js";
|
|
15
|
+
import { realClaudeRewindSdk, revertClaudeConversation, revertClaudeFiles } from "./rewind.js";
|
|
15
16
|
import { normalizeProviderReplayTimestamp } from "../../provider-history-timestamps.js";
|
|
16
17
|
import { getAgentStreamEventTurnId, } from "../../agent-sdk-types.js";
|
|
17
18
|
import { createProviderEnv, createProviderEnvSpec, } from "../../provider-launch-config.js";
|
|
@@ -89,6 +90,9 @@ const CLAUDE_CAPABILITIES = {
|
|
|
89
90
|
supportsMcpServers: true,
|
|
90
91
|
supportsReasoningStream: true,
|
|
91
92
|
supportsToolInvocations: true,
|
|
93
|
+
supportsRewindConversation: true,
|
|
94
|
+
supportsRewindFiles: true,
|
|
95
|
+
supportsRewindBoth: true,
|
|
92
96
|
};
|
|
93
97
|
const DEFAULT_MODES = [
|
|
94
98
|
{
|
|
@@ -742,7 +746,7 @@ class TimelineAssembler {
|
|
|
742
746
|
nextAssistantText !== INTERRUPT_TOOL_USE_PLACEHOLDER &&
|
|
743
747
|
!isClaudeTranscriptNoiseText(nextAssistantText)) {
|
|
744
748
|
state.emittedAssistantLength = state.assistantText.length;
|
|
745
|
-
items.push({ type: "assistant_message", text: nextAssistantText });
|
|
749
|
+
items.push({ type: "assistant_message", text: nextAssistantText, messageId: state.id });
|
|
746
750
|
}
|
|
747
751
|
const nextReasoningText = state.reasoningText.slice(state.emittedReasoningLength);
|
|
748
752
|
if (nextReasoningText.length > 0) {
|
|
@@ -834,7 +838,19 @@ function isSyntheticUserEntry(entry) {
|
|
|
834
838
|
if (!candidate) {
|
|
835
839
|
return false;
|
|
836
840
|
}
|
|
837
|
-
return candidate.isSynthetic === true || candidate.isMeta === true;
|
|
841
|
+
return (candidate.isSynthetic === true || candidate.isMeta === true || Boolean(candidate.toolUseResult));
|
|
842
|
+
}
|
|
843
|
+
function isToolResultUserEntry(entry) {
|
|
844
|
+
const candidate = toObjectRecord(entry);
|
|
845
|
+
if (!candidate) {
|
|
846
|
+
return false;
|
|
847
|
+
}
|
|
848
|
+
const message = toObjectRecord(candidate.message);
|
|
849
|
+
const content = message?.content;
|
|
850
|
+
return (Array.isArray(content) && content.some((block) => toObjectRecord(block)?.type === "tool_result"));
|
|
851
|
+
}
|
|
852
|
+
function isSyntheticHistoryUserEntry(entry) {
|
|
853
|
+
return isSyntheticUserEntry(entry) && !isToolResultUserEntry(entry);
|
|
838
854
|
}
|
|
839
855
|
function firstTrimmedString(sources) {
|
|
840
856
|
for (const source of sources) {
|
|
@@ -845,13 +861,23 @@ function firstTrimmedString(sources) {
|
|
|
845
861
|
}
|
|
846
862
|
return null;
|
|
847
863
|
}
|
|
864
|
+
function readTranscriptUuid(message) {
|
|
865
|
+
const root = toObjectRecord(message) ?? {};
|
|
866
|
+
const messageType = readTrimmedString(root.type);
|
|
867
|
+
if (messageType !== "user" && messageType !== "assistant") {
|
|
868
|
+
return null;
|
|
869
|
+
}
|
|
870
|
+
return firstTrimmedString([root.uuid]);
|
|
871
|
+
}
|
|
848
872
|
export function readEventIdentifiers(message) {
|
|
849
873
|
const root = toObjectRecord(message) ?? {};
|
|
850
874
|
const messageType = readTrimmedString(root.type);
|
|
851
875
|
const streamEvent = toObjectRecord(root.event);
|
|
852
876
|
const streamEventMessage = toObjectRecord(streamEvent?.message);
|
|
853
877
|
const messageContainer = toObjectRecord(root.message);
|
|
854
|
-
const messageIdFromUuid = messageType === "user"
|
|
878
|
+
const messageIdFromUuid = messageType === "user" || messageType === "assistant" || messageType === "system"
|
|
879
|
+
? root.uuid
|
|
880
|
+
: undefined;
|
|
855
881
|
return {
|
|
856
882
|
taskId: firstTrimmedString([
|
|
857
883
|
root.task_id,
|
|
@@ -1165,10 +1191,12 @@ class ClaudeAgentSession {
|
|
|
1165
1191
|
this.queryPumpPromise = null;
|
|
1166
1192
|
this.queryRestartNeeded = false;
|
|
1167
1193
|
this.pendingInterruptAbort = false;
|
|
1168
|
-
this.lastForegroundPromptText = null;
|
|
1169
1194
|
this.foregroundHasVisibleActivity = false;
|
|
1170
1195
|
this.activeTurnHasAssistantText = false;
|
|
1171
1196
|
this.userMessageIds = [];
|
|
1197
|
+
this.emittedUserMessageIds = new Set();
|
|
1198
|
+
this.rewindTurnAnchors = [];
|
|
1199
|
+
this.pendingFreshSessionId = null;
|
|
1172
1200
|
this.recentStderr = "";
|
|
1173
1201
|
this.closed = false;
|
|
1174
1202
|
this.handlePermissionRequest = async (toolName, input, options) => {
|
|
@@ -1335,7 +1363,8 @@ class ClaudeAgentSession {
|
|
|
1335
1363
|
this.completeAutonomousTurn();
|
|
1336
1364
|
}
|
|
1337
1365
|
const sdkMessage = this.toSdkUserMessage(prompt);
|
|
1338
|
-
|
|
1366
|
+
const sdkUserMessageId = typeof sdkMessage.uuid === "string" && sdkMessage.uuid.length > 0 ? sdkMessage.uuid : null;
|
|
1367
|
+
this.rememberRewindUserAnchor(sdkUserMessageId);
|
|
1339
1368
|
const turnId = this.createTurnId("foreground");
|
|
1340
1369
|
this.activeForegroundTurnId = turnId;
|
|
1341
1370
|
this.foregroundHasVisibleActivity = false;
|
|
@@ -1370,6 +1399,11 @@ class ClaudeAgentSession {
|
|
|
1370
1399
|
}
|
|
1371
1400
|
this.startQueryPump();
|
|
1372
1401
|
this.input.push(sdkMessage);
|
|
1402
|
+
setTimeout(() => {
|
|
1403
|
+
if (this.activeForegroundTurnId === turnId) {
|
|
1404
|
+
this.emitSubmittedUserMessage(sdkMessage, turnId);
|
|
1405
|
+
}
|
|
1406
|
+
}, 0);
|
|
1373
1407
|
}
|
|
1374
1408
|
catch (error) {
|
|
1375
1409
|
this.finishForegroundTurn(this.buildTurnFailedEvent(error instanceof Error ? error.message : "Claude stream failed"));
|
|
@@ -1607,6 +1641,33 @@ class ClaudeAgentSession {
|
|
|
1607
1641
|
}
|
|
1608
1642
|
return Array.from(commandMap.values()).sort((a, b) => a.name.localeCompare(b.name));
|
|
1609
1643
|
}
|
|
1644
|
+
async revertConversation(input) {
|
|
1645
|
+
const target = this.resolveConversationRewindTarget(input.messageId);
|
|
1646
|
+
if (target.kind === "fresh-session") {
|
|
1647
|
+
this.startFreshConversationSession();
|
|
1648
|
+
return;
|
|
1649
|
+
}
|
|
1650
|
+
await revertClaudeConversation({
|
|
1651
|
+
sdk: realClaudeRewindSdk,
|
|
1652
|
+
sessionId: this.claudeSessionId,
|
|
1653
|
+
messageId: target.messageId,
|
|
1654
|
+
resolveMessageId: (messageId) => this.resolveClaudeMessageId(messageId),
|
|
1655
|
+
setSessionId: (sessionId) => {
|
|
1656
|
+
this.rebindConversationSession(sessionId);
|
|
1657
|
+
},
|
|
1658
|
+
});
|
|
1659
|
+
}
|
|
1660
|
+
async revertFiles(input) {
|
|
1661
|
+
const messageId = await this.resolveClaudeMessageId(input.messageId);
|
|
1662
|
+
await revertClaudeFiles({
|
|
1663
|
+
query: await this.ensureQuery(),
|
|
1664
|
+
messageId,
|
|
1665
|
+
});
|
|
1666
|
+
}
|
|
1667
|
+
async revertBoth(input) {
|
|
1668
|
+
await this.revertFiles(input);
|
|
1669
|
+
await this.revertConversation(input);
|
|
1670
|
+
}
|
|
1610
1671
|
resolveSlashCommandInvocation(prompt) {
|
|
1611
1672
|
if (typeof prompt !== "string") {
|
|
1612
1673
|
return null;
|
|
@@ -1722,10 +1783,6 @@ class ClaudeAgentSession {
|
|
|
1722
1783
|
candidates.push(value);
|
|
1723
1784
|
}
|
|
1724
1785
|
};
|
|
1725
|
-
const historyIds = this.readUserMessageIdsFromHistoryFile();
|
|
1726
|
-
for (let idx = historyIds.length - 1; idx >= 0; idx -= 1) {
|
|
1727
|
-
pushUnique(historyIds[idx]);
|
|
1728
|
-
}
|
|
1729
1786
|
for (let idx = this.persistedHistory.length - 1; idx >= 0; idx -= 1) {
|
|
1730
1787
|
const entry = this.persistedHistory[idx];
|
|
1731
1788
|
if (entry?.item.type === "user_message") {
|
|
@@ -1737,37 +1794,47 @@ class ClaudeAgentSession {
|
|
|
1737
1794
|
}
|
|
1738
1795
|
return candidates;
|
|
1739
1796
|
}
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
}
|
|
1767
|
-
catch {
|
|
1768
|
-
return [];
|
|
1797
|
+
rebindConversationSession(sessionId) {
|
|
1798
|
+
const oldSessionId = this.claudeSessionId;
|
|
1799
|
+
this.claudeSessionId = sessionId;
|
|
1800
|
+
this.pendingFreshSessionId = null;
|
|
1801
|
+
this.persistence = null;
|
|
1802
|
+
this.cachedRuntimeInfo = null;
|
|
1803
|
+
this.queryRestartNeeded = true;
|
|
1804
|
+
this.persistedHistory = [];
|
|
1805
|
+
this.historyPending = false;
|
|
1806
|
+
this.userMessageIds = [];
|
|
1807
|
+
this.emittedUserMessageIds.clear();
|
|
1808
|
+
this.rewindTurnAnchors.length = 0;
|
|
1809
|
+
this.loadPersistedHistory(sessionId);
|
|
1810
|
+
if (oldSessionId && oldSessionId !== sessionId) {
|
|
1811
|
+
this.dispatchEvents([
|
|
1812
|
+
{
|
|
1813
|
+
type: "timeline",
|
|
1814
|
+
provider: "claude",
|
|
1815
|
+
item: this.createClaudeSessionChangedNotice(oldSessionId, sessionId),
|
|
1816
|
+
},
|
|
1817
|
+
{
|
|
1818
|
+
type: "thread_started",
|
|
1819
|
+
provider: "claude",
|
|
1820
|
+
sessionId,
|
|
1821
|
+
},
|
|
1822
|
+
]);
|
|
1769
1823
|
}
|
|
1770
1824
|
}
|
|
1825
|
+
startFreshConversationSession() {
|
|
1826
|
+
const sessionId = randomUUID();
|
|
1827
|
+
this.claudeSessionId = sessionId;
|
|
1828
|
+
this.pendingFreshSessionId = sessionId;
|
|
1829
|
+
this.persistence = null;
|
|
1830
|
+
this.cachedRuntimeInfo = null;
|
|
1831
|
+
this.queryRestartNeeded = true;
|
|
1832
|
+
this.persistedHistory = [];
|
|
1833
|
+
this.historyPending = false;
|
|
1834
|
+
this.userMessageIds = [];
|
|
1835
|
+
this.emittedUserMessageIds.clear();
|
|
1836
|
+
this.rewindTurnAnchors.length = 0;
|
|
1837
|
+
}
|
|
1771
1838
|
rememberUserMessageId(messageId) {
|
|
1772
1839
|
if (typeof messageId !== "string" || messageId.length === 0) {
|
|
1773
1840
|
return;
|
|
@@ -1778,6 +1845,78 @@ class ClaudeAgentSession {
|
|
|
1778
1845
|
}
|
|
1779
1846
|
this.userMessageIds.push(messageId);
|
|
1780
1847
|
}
|
|
1848
|
+
rememberEmittedUserMessageId(messageId) {
|
|
1849
|
+
if (typeof messageId !== "string" || messageId.length === 0) {
|
|
1850
|
+
return;
|
|
1851
|
+
}
|
|
1852
|
+
this.emittedUserMessageIds.add(messageId);
|
|
1853
|
+
}
|
|
1854
|
+
rememberRewindUserAnchor(userMessageId) {
|
|
1855
|
+
if (typeof userMessageId !== "string" || userMessageId.length === 0) {
|
|
1856
|
+
return;
|
|
1857
|
+
}
|
|
1858
|
+
if (this.rewindTurnAnchors.some((anchor) => anchor.userMessageId === userMessageId)) {
|
|
1859
|
+
return;
|
|
1860
|
+
}
|
|
1861
|
+
this.rewindTurnAnchors.push({
|
|
1862
|
+
userMessageId,
|
|
1863
|
+
assistantMessageId: null,
|
|
1864
|
+
});
|
|
1865
|
+
}
|
|
1866
|
+
rememberRewindAssistantAnchor(assistantMessageId) {
|
|
1867
|
+
if (typeof assistantMessageId !== "string" || assistantMessageId.length === 0) {
|
|
1868
|
+
return;
|
|
1869
|
+
}
|
|
1870
|
+
for (let index = this.rewindTurnAnchors.length - 1; index >= 0; index -= 1) {
|
|
1871
|
+
const anchor = this.rewindTurnAnchors[index];
|
|
1872
|
+
if (!anchor) {
|
|
1873
|
+
continue;
|
|
1874
|
+
}
|
|
1875
|
+
anchor.assistantMessageId = assistantMessageId;
|
|
1876
|
+
return;
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
rememberTranscriptProgress(message, messageId) {
|
|
1880
|
+
if (!messageId) {
|
|
1881
|
+
return;
|
|
1882
|
+
}
|
|
1883
|
+
if (message.type === "user" &&
|
|
1884
|
+
!isSyntheticUserEntry(message) &&
|
|
1885
|
+
!isToolResultUserEntry(message)) {
|
|
1886
|
+
this.rememberRewindUserAnchor(messageId);
|
|
1887
|
+
return;
|
|
1888
|
+
}
|
|
1889
|
+
if (message.type === "assistant") {
|
|
1890
|
+
this.rememberRewindAssistantAnchor(messageId);
|
|
1891
|
+
return;
|
|
1892
|
+
}
|
|
1893
|
+
if (message.type === "stream_event") {
|
|
1894
|
+
const event = toObjectRecord(message.event) ?? {};
|
|
1895
|
+
const eventType = readTrimmedString(event.type);
|
|
1896
|
+
if (eventType === "message_start") {
|
|
1897
|
+
this.rememberRewindAssistantAnchor(messageId);
|
|
1898
|
+
}
|
|
1899
|
+
return;
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
resolveClaudeMessageId(messageId) {
|
|
1903
|
+
return messageId;
|
|
1904
|
+
}
|
|
1905
|
+
resolveConversationRewindTarget(messageId) {
|
|
1906
|
+
const targetUserMessageId = this.resolveClaudeMessageId(messageId);
|
|
1907
|
+
const index = this.rewindTurnAnchors.findIndex((anchor) => anchor.userMessageId === targetUserMessageId);
|
|
1908
|
+
if (index < 0) {
|
|
1909
|
+
throw new Error(`Claude rewind target ${messageId} is not in the tracked conversation`);
|
|
1910
|
+
}
|
|
1911
|
+
if (index === 0) {
|
|
1912
|
+
return { kind: "fresh-session" };
|
|
1913
|
+
}
|
|
1914
|
+
const previousTurn = this.rewindTurnAnchors[index - 1];
|
|
1915
|
+
if (!previousTurn?.assistantMessageId) {
|
|
1916
|
+
throw new Error(`Claude rewind cannot preserve turn ${index} because its assistant response id was not observed`);
|
|
1917
|
+
}
|
|
1918
|
+
return { kind: "fork", messageId: previousTurn.assistantMessageId };
|
|
1919
|
+
}
|
|
1781
1920
|
async ensureQuery() {
|
|
1782
1921
|
if (this.query && !this.queryRestartNeeded) {
|
|
1783
1922
|
return this.query;
|
|
@@ -1893,6 +2032,13 @@ class ClaudeAgentSession {
|
|
|
1893
2032
|
.toLowerCase()
|
|
1894
2033
|
.includes("\\.local\\bin"),
|
|
1895
2034
|
}, "Resolved Claude executable");
|
|
2035
|
+
const sessionBinding = {};
|
|
2036
|
+
if (this.pendingFreshSessionId) {
|
|
2037
|
+
sessionBinding.sessionId = this.pendingFreshSessionId;
|
|
2038
|
+
}
|
|
2039
|
+
else if (this.claudeSessionId) {
|
|
2040
|
+
sessionBinding.resume = this.claudeSessionId;
|
|
2041
|
+
}
|
|
1896
2042
|
const base = {
|
|
1897
2043
|
cwd: this.config.cwd,
|
|
1898
2044
|
includePartialMessages: true,
|
|
@@ -1920,7 +2066,7 @@ class ClaudeAgentSession {
|
|
|
1920
2066
|
enableFileCheckpointing: true,
|
|
1921
2067
|
// If we have a session ID from a previous query (e.g., after interrupt),
|
|
1922
2068
|
// resume that session to continue the conversation history.
|
|
1923
|
-
...
|
|
2069
|
+
...sessionBinding,
|
|
1924
2070
|
...(thinking ? { thinking } : {}),
|
|
1925
2071
|
...(effort ? { effort } : {}),
|
|
1926
2072
|
...extraClaudeOptions,
|
|
@@ -1934,7 +2080,7 @@ class ClaudeAgentSession {
|
|
|
1934
2080
|
base.model = this.config.model;
|
|
1935
2081
|
}
|
|
1936
2082
|
this.lastOptionsModel = base.model ?? null;
|
|
1937
|
-
if (this.claudeSessionId) {
|
|
2083
|
+
if (this.claudeSessionId && !this.pendingFreshSessionId) {
|
|
1938
2084
|
base.resume = this.claudeSessionId;
|
|
1939
2085
|
}
|
|
1940
2086
|
if (this.runtimeSettings?.disallowedTools?.length) {
|
|
@@ -2066,15 +2212,6 @@ class ClaudeAgentSession {
|
|
|
2066
2212
|
event.type === "turn_failed" ||
|
|
2067
2213
|
event.type === "turn_canceled");
|
|
2068
2214
|
}
|
|
2069
|
-
extractPromptText(prompt) {
|
|
2070
|
-
if (typeof prompt === "string") {
|
|
2071
|
-
return prompt;
|
|
2072
|
-
}
|
|
2073
|
-
const textParts = prompt
|
|
2074
|
-
.filter((block) => block.type === "text")
|
|
2075
|
-
.map((block) => block.text);
|
|
2076
|
-
return textParts.length > 0 ? textParts.join("\n") : null;
|
|
2077
|
-
}
|
|
2078
2215
|
async executeRewindTurn(_turnId, invocation) {
|
|
2079
2216
|
this.notifySubscribers({ type: "turn_started", provider: "claude" });
|
|
2080
2217
|
try {
|
|
@@ -2128,7 +2265,6 @@ class ClaudeAgentSession {
|
|
|
2128
2265
|
}
|
|
2129
2266
|
this.notifySubscribers(event);
|
|
2130
2267
|
this.activeForegroundTurnId = null;
|
|
2131
|
-
this.lastForegroundPromptText = null;
|
|
2132
2268
|
this.cancelCurrentTurn = null;
|
|
2133
2269
|
this.activeTurnHasAssistantText = false;
|
|
2134
2270
|
this.syncTurnState("foreground turn terminal");
|
|
@@ -2142,7 +2278,6 @@ class ClaudeAgentSession {
|
|
|
2142
2278
|
if (terminalSeen) {
|
|
2143
2279
|
if (this.activeForegroundTurnId) {
|
|
2144
2280
|
this.activeForegroundTurnId = null;
|
|
2145
|
-
this.lastForegroundPromptText = null;
|
|
2146
2281
|
this.cancelCurrentTurn = null;
|
|
2147
2282
|
this.activeTurnHasAssistantText = false;
|
|
2148
2283
|
this.syncTurnState("foreground turn terminal");
|
|
@@ -2285,15 +2420,6 @@ class ClaudeAgentSession {
|
|
|
2285
2420
|
}
|
|
2286
2421
|
}
|
|
2287
2422
|
}
|
|
2288
|
-
isEchoedForegroundUserMessage(event) {
|
|
2289
|
-
if (event.type !== "timeline" ||
|
|
2290
|
-
event.item.type !== "user_message" ||
|
|
2291
|
-
!this.activeForegroundTurnId ||
|
|
2292
|
-
!this.lastForegroundPromptText) {
|
|
2293
|
-
return false;
|
|
2294
|
-
}
|
|
2295
|
-
return event.item.text.trim() === this.lastForegroundPromptText.trim();
|
|
2296
|
-
}
|
|
2297
2423
|
shouldSuppressStaleResult(message) {
|
|
2298
2424
|
// Suppress stale results from interrupted requests. The cancel path already
|
|
2299
2425
|
// emitted the terminal event; this result is leftover from the killed API
|
|
@@ -2330,6 +2456,7 @@ class ClaudeAgentSession {
|
|
|
2330
2456
|
}
|
|
2331
2457
|
const turnId = this.activeForegroundTurnId ?? this.autonomousTurn?.id ?? null;
|
|
2332
2458
|
const identifiers = readEventIdentifiers(message);
|
|
2459
|
+
this.rememberTranscriptProgress(message, readTranscriptUuid(message));
|
|
2333
2460
|
this.logger.trace({
|
|
2334
2461
|
agentId: this.agentId,
|
|
2335
2462
|
provider: "claude",
|
|
@@ -2354,9 +2481,7 @@ class ClaudeAgentSession {
|
|
|
2354
2481
|
item,
|
|
2355
2482
|
provider: "claude",
|
|
2356
2483
|
}));
|
|
2357
|
-
|
|
2358
|
-
const filteredMessageEvents = messageEvents.filter((event) => !this.isEchoedForegroundUserMessage(event));
|
|
2359
|
-
const events = [...filteredMessageEvents, ...assistantTimelineEvents];
|
|
2484
|
+
const events = [...messageEvents, ...assistantTimelineEvents];
|
|
2360
2485
|
if (events.length === 0) {
|
|
2361
2486
|
return;
|
|
2362
2487
|
}
|
|
@@ -2431,20 +2556,22 @@ class ClaudeAgentSession {
|
|
|
2431
2556
|
return this.sidechainTracker.handleMessage(message, parentToolUseId);
|
|
2432
2557
|
}
|
|
2433
2558
|
const events = [];
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2559
|
+
if (message.type !== "system") {
|
|
2560
|
+
const sessionCapture = this.captureSessionIdFromMessage(message);
|
|
2561
|
+
if (sessionCapture.notice) {
|
|
2562
|
+
events.push({
|
|
2563
|
+
type: "timeline",
|
|
2564
|
+
provider: "claude",
|
|
2565
|
+
item: sessionCapture.notice,
|
|
2566
|
+
});
|
|
2567
|
+
}
|
|
2568
|
+
if (sessionCapture.threadStartedSessionId) {
|
|
2569
|
+
events.push({
|
|
2570
|
+
type: "thread_started",
|
|
2571
|
+
provider: "claude",
|
|
2572
|
+
sessionId: sessionCapture.threadStartedSessionId,
|
|
2573
|
+
});
|
|
2574
|
+
}
|
|
2448
2575
|
}
|
|
2449
2576
|
switch (message.type) {
|
|
2450
2577
|
case "system":
|
|
@@ -2474,6 +2601,22 @@ class ClaudeAgentSession {
|
|
|
2474
2601
|
}
|
|
2475
2602
|
return events;
|
|
2476
2603
|
}
|
|
2604
|
+
emitSubmittedUserMessage(message, turnId) {
|
|
2605
|
+
const events = [];
|
|
2606
|
+
this.appendUserMessageEvents(message, events);
|
|
2607
|
+
if (events.length === 0) {
|
|
2608
|
+
return;
|
|
2609
|
+
}
|
|
2610
|
+
this.foregroundHasVisibleActivity = true;
|
|
2611
|
+
for (const event of events) {
|
|
2612
|
+
if (event.type === "timeline") {
|
|
2613
|
+
this.notifySubscribers({ ...event, turnId });
|
|
2614
|
+
}
|
|
2615
|
+
else {
|
|
2616
|
+
this.notifySubscribers(event);
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
}
|
|
2477
2620
|
appendSystemMessageEvents(message, events) {
|
|
2478
2621
|
if (message.subtype === "init") {
|
|
2479
2622
|
const sessionUpdate = this.handleSystemMessage(message);
|
|
@@ -2565,7 +2708,11 @@ class ClaudeAgentSession {
|
|
|
2565
2708
|
return;
|
|
2566
2709
|
}
|
|
2567
2710
|
const messageId = typeof message.uuid === "string" && message.uuid.length > 0 ? message.uuid : undefined;
|
|
2711
|
+
if (messageId && this.emittedUserMessageIds.has(messageId)) {
|
|
2712
|
+
return;
|
|
2713
|
+
}
|
|
2568
2714
|
this.rememberUserMessageId(messageId);
|
|
2715
|
+
this.rememberEmittedUserMessageId(messageId);
|
|
2569
2716
|
const content = message.message?.content;
|
|
2570
2717
|
const taskNotificationItem = mapTaskNotificationUserContentToToolCall({
|
|
2571
2718
|
content,
|
|
@@ -2673,10 +2820,12 @@ class ClaudeAgentSession {
|
|
|
2673
2820
|
}
|
|
2674
2821
|
if (this.claudeSessionId === null) {
|
|
2675
2822
|
this.claudeSessionId = sessionId;
|
|
2823
|
+
this.pendingFreshSessionId = null;
|
|
2676
2824
|
this.persistence = null;
|
|
2677
2825
|
return { threadStartedSessionId: sessionId, notice: null };
|
|
2678
2826
|
}
|
|
2679
2827
|
if (this.claudeSessionId === sessionId) {
|
|
2828
|
+
this.pendingFreshSessionId = null;
|
|
2680
2829
|
return { threadStartedSessionId: null, notice: null };
|
|
2681
2830
|
}
|
|
2682
2831
|
const oldSessionId = this.claudeSessionId;
|
|
@@ -2685,6 +2834,7 @@ class ClaudeAgentSession {
|
|
|
2685
2834
|
// not be failed just because the underlying subprocess cycled.
|
|
2686
2835
|
this.logger.warn({ existingSessionId: this.claudeSessionId, newSessionId: sessionId }, "Claude session ID changed in message; accepting new session");
|
|
2687
2836
|
this.claudeSessionId = sessionId;
|
|
2837
|
+
this.pendingFreshSessionId = null;
|
|
2688
2838
|
this.persistence = null;
|
|
2689
2839
|
return {
|
|
2690
2840
|
threadStartedSessionId: sessionId,
|
|
@@ -2709,10 +2859,12 @@ class ClaudeAgentSession {
|
|
|
2709
2859
|
let notice = null;
|
|
2710
2860
|
if (existingSessionId === null) {
|
|
2711
2861
|
this.claudeSessionId = newSessionId;
|
|
2862
|
+
this.pendingFreshSessionId = null;
|
|
2712
2863
|
threadStartedSessionId = newSessionId;
|
|
2713
2864
|
this.logger.debug({ sessionId: newSessionId }, "Claude session ID set for the first time");
|
|
2714
2865
|
}
|
|
2715
2866
|
else if (existingSessionId === newSessionId) {
|
|
2867
|
+
this.pendingFreshSessionId = null;
|
|
2716
2868
|
this.logger.debug({ sessionId: newSessionId }, "Claude session ID unchanged (same value)");
|
|
2717
2869
|
}
|
|
2718
2870
|
else {
|
|
@@ -2720,6 +2872,7 @@ class ClaudeAgentSession {
|
|
|
2720
2872
|
// with a new session mid-turn). Accept the new ID and continue.
|
|
2721
2873
|
this.logger.warn({ existingSessionId, newSessionId }, "Claude session ID changed in init message; accepting new session");
|
|
2722
2874
|
this.claudeSessionId = newSessionId;
|
|
2875
|
+
this.pendingFreshSessionId = null;
|
|
2723
2876
|
threadStartedSessionId = newSessionId;
|
|
2724
2877
|
notice = this.createClaudeSessionChangedNotice(existingSessionId, newSessionId);
|
|
2725
2878
|
}
|
|
@@ -2960,11 +3113,19 @@ class ClaudeAgentSession {
|
|
|
2960
3113
|
if (entry.isSidechain) {
|
|
2961
3114
|
return;
|
|
2962
3115
|
}
|
|
2963
|
-
if (entry.type === "user" && typeof entry.uuid === "string") {
|
|
2964
|
-
this.rememberUserMessageId(entry.uuid);
|
|
2965
|
-
}
|
|
2966
3116
|
const historyTimestamp = normalizeProviderReplayTimestamp(entry.timestamp);
|
|
2967
3117
|
const items = this.convertHistoryEntry(entry);
|
|
3118
|
+
const isVisibleUserEntry = entry.type === "user" &&
|
|
3119
|
+
typeof entry.uuid === "string" &&
|
|
3120
|
+
!isSyntheticHistoryUserEntry(entry) &&
|
|
3121
|
+
!isToolResultUserEntry(entry);
|
|
3122
|
+
if (isVisibleUserEntry && typeof entry.uuid === "string") {
|
|
3123
|
+
this.rememberUserMessageId(entry.uuid);
|
|
3124
|
+
this.rememberRewindUserAnchor(entry.uuid);
|
|
3125
|
+
}
|
|
3126
|
+
if (entry.type === "assistant" && typeof entry.uuid === "string") {
|
|
3127
|
+
this.rememberRewindAssistantAnchor(entry.uuid);
|
|
3128
|
+
}
|
|
2968
3129
|
if (items.length > 0) {
|
|
2969
3130
|
timeline.push(...items.map((item) => ({
|
|
2970
3131
|
item,
|
|
@@ -2976,10 +3137,26 @@ class ClaudeAgentSession {
|
|
|
2976
3137
|
const cwd = this.config.cwd;
|
|
2977
3138
|
if (!cwd)
|
|
2978
3139
|
return null;
|
|
2979
|
-
const sanitized = sanitizeClaudeProjectPath(cwd);
|
|
2980
3140
|
const configDir = process.env.CLAUDE_CONFIG_DIR ?? path.join(os.homedir(), ".claude");
|
|
2981
|
-
const
|
|
2982
|
-
|
|
3141
|
+
const candidates = [cwd];
|
|
3142
|
+
try {
|
|
3143
|
+
const realCwd = fs.realpathSync(cwd);
|
|
3144
|
+
if (realCwd !== cwd) {
|
|
3145
|
+
candidates.push(realCwd);
|
|
3146
|
+
}
|
|
3147
|
+
}
|
|
3148
|
+
catch {
|
|
3149
|
+
// Fall back to the configured cwd when the path has already disappeared.
|
|
3150
|
+
}
|
|
3151
|
+
for (const candidate of candidates) {
|
|
3152
|
+
const sanitized = sanitizeClaudeProjectPath(candidate);
|
|
3153
|
+
const historyPath = path.join(configDir, "projects", sanitized, `${sessionId}.jsonl`);
|
|
3154
|
+
if (fs.existsSync(historyPath)) {
|
|
3155
|
+
return historyPath;
|
|
3156
|
+
}
|
|
3157
|
+
}
|
|
3158
|
+
const sanitized = sanitizeClaudeProjectPath(cwd);
|
|
3159
|
+
return path.join(configDir, "projects", sanitized, `${sessionId}.jsonl`);
|
|
2983
3160
|
}
|
|
2984
3161
|
convertHistoryEntry(entry) {
|
|
2985
3162
|
return convertClaudeHistoryEntry(entry, (content) => this.mapBlocksToTimeline(content));
|
|
@@ -3528,6 +3705,19 @@ function normalizeHistoryBlocks(content) {
|
|
|
3528
3705
|
}
|
|
3529
3706
|
return null;
|
|
3530
3707
|
}
|
|
3708
|
+
function mapAssistantHistoryBlocksWithMessageId(entry, content, mapBlocks) {
|
|
3709
|
+
const items = mapBlocks(content);
|
|
3710
|
+
const assistantMessageId = typeof entry.uuid === "string" && entry.uuid.length > 0 ? entry.uuid : null;
|
|
3711
|
+
if (!assistantMessageId) {
|
|
3712
|
+
return items;
|
|
3713
|
+
}
|
|
3714
|
+
for (const item of items) {
|
|
3715
|
+
if (item.type === "assistant_message" && !item.messageId) {
|
|
3716
|
+
item.messageId = assistantMessageId;
|
|
3717
|
+
}
|
|
3718
|
+
}
|
|
3719
|
+
return items;
|
|
3720
|
+
}
|
|
3531
3721
|
function convertClaudeHistoryEntryPreamble(entry) {
|
|
3532
3722
|
if (entry.type === "system" && entry.subtype === "compact_boundary") {
|
|
3533
3723
|
const compactMetadata = readCompactionMetadata(entry);
|
|
@@ -3549,7 +3739,7 @@ function convertClaudeHistoryEntryPreamble(entry) {
|
|
|
3549
3739
|
if (entry.isCompactSummary) {
|
|
3550
3740
|
return { shortCircuit: [] };
|
|
3551
3741
|
}
|
|
3552
|
-
if (entry.type === "user" &&
|
|
3742
|
+
if (entry.type === "user" && isSyntheticHistoryUserEntry(entry)) {
|
|
3553
3743
|
return { shortCircuit: [] };
|
|
3554
3744
|
}
|
|
3555
3745
|
const message = entry?.message;
|
|
@@ -3604,7 +3794,7 @@ export function convertClaudeHistoryEntry(entry, mapBlocks) {
|
|
|
3604
3794
|
return mapped;
|
|
3605
3795
|
}
|
|
3606
3796
|
if (entry.type === "assistant" && contentValue) {
|
|
3607
|
-
return
|
|
3797
|
+
return mapAssistantHistoryBlocksWithMessageId(entry, contentValue, mapBlocks);
|
|
3608
3798
|
}
|
|
3609
3799
|
return timeline;
|
|
3610
3800
|
}
|