Skip to content

Commit ee50912

Browse files
authored
fix: extract sdkSessionId when reading from logs (#190)
1 parent 37262ba commit ee50912

File tree

6 files changed

+40
-7
lines changed

6 files changed

+40
-7
lines changed

apps/array/src/main/preload.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ contextBridge.exposeInMainWorld("electronAPI", {
183183
apiHost: string;
184184
projectId: number;
185185
logUrl?: string;
186+
sdkSessionId?: string;
186187
}): Promise<{ sessionId: string; channel: string } | null> =>
187188
ipcRenderer.invoke("agent-reconnect", params),
188189
onAgentEvent: (

apps/array/src/main/services/session-manager.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ export interface SessionConfig {
122122
repoPath: string;
123123
credentials: PostHogCredentials;
124124
logUrl?: string; // For reconnection from S3
125+
sdkSessionId?: string; // SDK session ID for resuming Claude Code context
125126
}
126127

127128
export interface ManagedSession {
@@ -171,7 +172,8 @@ export class SessionManager {
171172
config: SessionConfig,
172173
isReconnect: boolean,
173174
): Promise<ManagedSession | null> {
174-
const { taskId, taskRunId, repoPath, credentials, logUrl } = config;
175+
const { taskId, taskRunId, repoPath, credentials, logUrl, sdkSessionId } =
176+
config;
175177

176178
const existing = this.sessions.get(taskRunId);
177179
if (existing) {
@@ -214,9 +216,12 @@ export class SessionManager {
214216
sessionId: taskRunId,
215217
cwd: repoPath,
216218
mcpServers: [],
217-
_meta: logUrl
218-
? { persistence: { taskId, runId: taskRunId, logUrl } }
219-
: undefined,
219+
_meta: {
220+
...(logUrl && {
221+
persistence: { taskId, runId: taskRunId, logUrl },
222+
}),
223+
...(sdkSessionId && { sdkSessionId }),
224+
},
220225
});
221226
} else {
222227
await connection.newSession({
@@ -439,6 +444,7 @@ interface AgentSessionParams {
439444
apiHost: string;
440445
projectId: number;
441446
logUrl?: string;
447+
sdkSessionId?: string;
442448
}
443449

444450
type SessionResponse = { sessionId: string; channel: string };
@@ -467,6 +473,7 @@ function toSessionConfig(params: AgentSessionParams): SessionConfig {
467473
projectId: params.projectId,
468474
},
469475
logUrl: params.logUrl,
476+
sdkSessionId: params.sdkSessionId,
470477
};
471478
}
472479

apps/array/src/renderer/features/sessions/stores/sessionStore.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,12 @@ export const useSessionStore = create<SessionStore>((set, get) => ({
124124
latestRunId,
125125
logUrl: latestRunLogUrl,
126126
});
127-
const { notifications, rawEntries } =
127+
const { notifications, rawEntries, sdkSessionId } =
128128
await fetchSessionLogs(latestRunLogUrl);
129129
log.info("Loaded historical logs", {
130130
notifications: notifications.length,
131131
rawEntries: rawEntries.length,
132+
sdkSessionId,
132133
});
133134

134135
// 2. Convert to SessionEvent format - interleave raw and parsed by order
@@ -189,6 +190,7 @@ export const useSessionStore = create<SessionStore>((set, get) => ({
189190
apiHost,
190191
projectId,
191192
logUrl: latestRunLogUrl,
193+
sdkSessionId,
192194
});
193195

194196
if (result) {

apps/array/src/renderer/features/sessions/utils/parseSessionLogs.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export interface StoredLogEntry {
1616
export interface ParsedSessionLogs {
1717
notifications: SessionNotification[];
1818
rawEntries: StoredLogEntry[];
19+
sdkSessionId?: string;
1920
}
2021

2122
/**
@@ -36,6 +37,7 @@ export async function fetchSessionLogs(
3637

3738
const notifications: SessionNotification[] = [];
3839
const rawEntries: StoredLogEntry[] = [];
40+
let sdkSessionId: string | undefined;
3941

4042
for (const line of content.trim().split("\n")) {
4143
try {
@@ -71,12 +73,26 @@ export async function fetchSessionLogs(
7173
) {
7274
notifications.push(stored.notification.params as SessionNotification);
7375
}
76+
77+
// Extract SDK session ID from _posthog/sdk_session notification
78+
if (
79+
stored.type === "notification" &&
80+
stored.notification?.method?.endsWith("posthog/sdk_session") &&
81+
stored.notification?.params
82+
) {
83+
const params = stored.notification.params as {
84+
sdkSessionId?: string;
85+
};
86+
if (params.sdkSessionId) {
87+
sdkSessionId = params.sdkSessionId;
88+
}
89+
}
7490
} catch {
7591
// Skip malformed lines
7692
}
7793
}
7894

79-
return { notifications, rawEntries };
95+
return { notifications, rawEntries, sdkSessionId };
8096
} catch {
8197
// Network error or other failure
8298
return { notifications: [], rawEntries: [] };

apps/array/src/renderer/types/electron.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ declare global {
136136
apiHost: string;
137137
projectId: number;
138138
logUrl?: string;
139+
sdkSessionId?: string;
139140
}) => Promise<{ sessionId: string; channel: string } | null>;
140141
onAgentEvent: (
141142
channel: string,

packages/agent/src/adapters/claude/claude.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ export class ClaudeAcpAgent implements Agent {
171171
fileContentCache: { [key: string]: string };
172172
backgroundTerminals: { [key: string]: BackgroundTerminal } = {};
173173
clientCapabilities?: ClientCapabilities;
174-
logger: Logger = new Logger({ debug: false, prefix: "[ClaudeAcpAgent]" });
174+
logger: Logger = new Logger({ debug: true, prefix: "[ClaudeAcpAgent]" });
175175
sessionStore?: SessionStore;
176176

177177
constructor(client: AgentSideConnection, sessionStore?: SessionStore) {
@@ -934,6 +934,7 @@ export class ClaudeAcpAgent implements Agent {
934934
async resumeSession(
935935
params: LoadSessionRequest,
936936
): Promise<LoadSessionResponse> {
937+
this.logger.info("[RESUME] Resuming session", { params });
937938
const { sessionId } = params;
938939

939940
// Extract persistence config and SDK session ID from _meta
@@ -980,6 +981,11 @@ export class ClaudeAcpAgent implements Agent {
980981

981982
const permissionMode = "default";
982983

984+
this.logger.info("Resuming session", {
985+
cwd: params.cwd,
986+
sdkSessionId,
987+
persistence,
988+
});
983989
const options: Options = {
984990
cwd: params.cwd,
985991
includePartialMessages: true,

0 commit comments

Comments
 (0)