remote-codex 0.11.40 → 0.11.41

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.
@@ -11717,7 +11717,40 @@ import { pathToFileURL } from "url";
11717
11717
  import { promisify } from "util";
11718
11718
  var execFileAsync = promisify(execFile);
11719
11719
  var promptPhotoTokenPattern2 = /\[PHOTO\s+([^\]]+)\]/g;
11720
+ var claudeCompactSummaryPrefix = "This session is being continued from a previous conversation that ran out of context.";
11720
11721
  var activeTranscriptMatchWindowMs = 12e4;
11722
+ function isClaudeCompactBoundaryMessage(message) {
11723
+ if (message.type !== "system") {
11724
+ return false;
11725
+ }
11726
+ if (message.subtype === "compact_boundary" || message.compact_metadata) {
11727
+ return true;
11728
+ }
11729
+ return isRecord8(message.message) && (message.message.subtype === "compact_boundary" || isRecord8(message.message.compact_metadata));
11730
+ }
11731
+ function isClaudeCompactSummaryMessage(message) {
11732
+ if (message.type !== "user" || message.parent_tool_use_id) {
11733
+ return false;
11734
+ }
11735
+ const payload = isRecord8(message.message) ? message.message : null;
11736
+ if (message.isCompactSummary || message.is_compact_summary || payload?.isCompactSummary === true || payload?.is_compact_summary === true) {
11737
+ return true;
11738
+ }
11739
+ return messageContentText(message.message).trim().startsWith(claudeCompactSummaryPrefix);
11740
+ }
11741
+ function claudeContextCompactionItem(id, status, error = null) {
11742
+ const completed = status === "completed";
11743
+ const failed = status === "failed";
11744
+ const text2 = failed ? "Context compaction failed" : completed ? "Context compacted" : "Compacting context";
11745
+ return {
11746
+ id,
11747
+ kind: "contextCompaction",
11748
+ text: text2,
11749
+ previewText: text2,
11750
+ detailText: failed ? error : null,
11751
+ status
11752
+ };
11753
+ }
11721
11754
  function normalizePromptForTurnReconciliation(value) {
11722
11755
  return value.replace(/\[PHOTO\s+[^\]]+\]/g, " ").replace(/\s+/g, " ").trim();
11723
11756
  }
@@ -12923,7 +12956,8 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
12923
12956
  suppressedToolUseIds: /* @__PURE__ */ new Set(),
12924
12957
  assistantUsage: null,
12925
12958
  resultUsage: null,
12926
- modelContextWindow: null
12959
+ modelContextWindow: null,
12960
+ currentCompactionItemId: null
12927
12961
  };
12928
12962
  this.knownSessionIds.add(input.providerSessionId);
12929
12963
  let sessionPrompts = this.liveUserPrompts.get(input.providerSessionId);
@@ -13147,6 +13181,53 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
13147
13181
  }
13148
13182
  return;
13149
13183
  }
13184
+ if (message.type === "system" && message.subtype === "status") {
13185
+ if (message.status === "compacting") {
13186
+ const existing = state.currentCompactionItemId ? state.items.get(state.currentCompactionItemId) : null;
13187
+ const itemId = existing?.status === "running" ? existing.id : `claude-compaction-${messageUuid(message, randomUUID2())}`;
13188
+ state.currentCompactionItemId = itemId;
13189
+ const item = withHistoryItemCreatedAt(
13190
+ claudeContextCompactionItem(itemId, "running"),
13191
+ messageCreatedAt
13192
+ );
13193
+ addOrUpdateItem(state, item);
13194
+ this.emitItem(state, item, "item.started", { force: Boolean(existing) });
13195
+ return;
13196
+ }
13197
+ if (message.compact_result) {
13198
+ const itemId = state.currentCompactionItemId ?? `claude-compaction-${messageUuid(message, randomUUID2())}`;
13199
+ const status = message.compact_result === "success" ? "completed" : "failed";
13200
+ const item = withHistoryItemCreatedAt(
13201
+ claudeContextCompactionItem(itemId, status, message.compact_error ?? null),
13202
+ messageCreatedAt
13203
+ );
13204
+ addOrUpdateItem(state, item);
13205
+ this.emitItem(state, item, "item.completed");
13206
+ state.currentCompactionItemId = status === "failed" ? null : itemId;
13207
+ return;
13208
+ }
13209
+ return;
13210
+ }
13211
+ if (isClaudeCompactBoundaryMessage(message)) {
13212
+ const itemId = state.currentCompactionItemId ?? `claude-compaction-${messageUuid(message, randomUUID2())}`;
13213
+ const previous = state.items.get(itemId);
13214
+ const item = withHistoryItemCreatedAt(
13215
+ claudeContextCompactionItem(itemId, "completed"),
13216
+ previous?.createdAt ?? messageCreatedAt
13217
+ );
13218
+ addOrUpdateItem(state, item);
13219
+ if (!previous) {
13220
+ this.emitItem(state, item, "item.started");
13221
+ }
13222
+ if (previous?.status !== "completed") {
13223
+ this.emitItem(state, item, "item.completed");
13224
+ }
13225
+ state.currentCompactionItemId = null;
13226
+ return;
13227
+ }
13228
+ if (isClaudeCompactSummaryMessage(message)) {
13229
+ return;
13230
+ }
13150
13231
  if (message.type === "stream_event") {
13151
13232
  const nextStreamMessageId = streamMessageId(message.event);
13152
13233
  if (nextStreamMessageId) {
@@ -13498,6 +13579,8 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
13498
13579
  const turns = [];
13499
13580
  let current = null;
13500
13581
  let skippingHiddenInit = false;
13582
+ let pendingCompactSummaryItemId = null;
13583
+ let pendingCompactBoundaryItemId = null;
13501
13584
  const suppressedToolUseIds = /* @__PURE__ */ new Set();
13502
13585
  const upsertCurrentItem = (item) => {
13503
13586
  if (!current) {
@@ -13529,6 +13612,18 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
13529
13612
  current.itemsById.set(item.id, item);
13530
13613
  };
13531
13614
  for (const message of messages) {
13615
+ if (isClaudeCompactBoundaryMessage(message)) {
13616
+ const itemId = pendingCompactSummaryItemId ?? `claude-compaction-${messageUuid(message, randomUUID2())}`;
13617
+ pendingCompactSummaryItemId = null;
13618
+ pendingCompactBoundaryItemId = itemId;
13619
+ upsertCurrentItem(
13620
+ withHistoryItemCreatedAt(
13621
+ claudeContextCompactionItem(itemId, "completed"),
13622
+ sessionMessageTimestamp(message) ?? current?.startedAt
13623
+ )
13624
+ );
13625
+ continue;
13626
+ }
13532
13627
  if (message.type === "user") {
13533
13628
  const taskNotification = taskNotificationToolResult(message.message);
13534
13629
  if (taskNotification) {
@@ -13573,6 +13668,20 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
13573
13668
  }
13574
13669
  }
13575
13670
  if (message.type === "user" && !message.parent_tool_use_id) {
13671
+ if (isClaudeCompactSummaryMessage(message)) {
13672
+ const itemId = pendingCompactBoundaryItemId ?? `claude-compaction-${messageUuid(message, randomUUID2())}`;
13673
+ if (!pendingCompactBoundaryItemId) {
13674
+ pendingCompactSummaryItemId = itemId;
13675
+ }
13676
+ pendingCompactBoundaryItemId = null;
13677
+ upsertCurrentItem(
13678
+ withHistoryItemCreatedAt(
13679
+ claudeContextCompactionItem(itemId, "completed"),
13680
+ sessionMessageTimestamp(message) ?? current?.startedAt
13681
+ )
13682
+ );
13683
+ continue;
13684
+ }
13576
13685
  if (isHiddenInitMessage(message.message)) {
13577
13686
  skippingHiddenInit = true;
13578
13687
  current = null;
@@ -13592,19 +13701,19 @@ var ClaudeRuntimeAdapter = class extends EventEmitter5 {
13592
13701
  items: current.items
13593
13702
  }));
13594
13703
  }
13595
- const messageUuid2 = message.uuid ?? randomUUID2();
13596
- const userStartedAt = isoFromUuidV7(messageUuid2);
13704
+ const userMessageUuid = message.uuid ?? randomUUID2();
13705
+ const userStartedAt = isoFromUuidV7(userMessageUuid);
13597
13706
  const userItem = await this.userMessageToHistoryItem(
13598
- messageUuid2,
13707
+ userMessageUuid,
13599
13708
  message.message,
13600
13709
  context
13601
13710
  );
13602
13711
  const stampedUserItem = withHistoryItemCreatedAt(userItem, userStartedAt);
13603
13712
  current = {
13604
- providerTurnId: `claude-turn-${messageUuid2}`,
13713
+ providerTurnId: `claude-turn-${userMessageUuid}`,
13605
13714
  startedAt: userStartedAt,
13606
13715
  items: [stampedUserItem],
13607
- itemsById: /* @__PURE__ */ new Map([[messageUuid2, stampedUserItem]])
13716
+ itemsById: /* @__PURE__ */ new Map([[userMessageUuid, stampedUserItem]])
13608
13717
  };
13609
13718
  continue;
13610
13719
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remote-codex",
3
- "version": "0.11.40",
3
+ "version": "0.11.41",
4
4
  "description": "Local web supervisor for Codex workspaces and threads.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -2983,4 +2983,139 @@ describe('ClaudeRuntimeAdapter', () => {
2983
2983
  ]),
2984
2984
  );
2985
2985
  });
2986
+
2987
+ it('keeps live Claude compaction in the active turn and hides its summary', async () => {
2988
+ const adapter = makeAdapter((prompt) => prompt === hiddenInitPrompt()
2989
+ ? [systemInit(), result()]
2990
+ : [
2991
+ systemInit(),
2992
+ {
2993
+ type: 'assistant',
2994
+ uuid: 'assistant-before-compact',
2995
+ session_id: 'claude-session-1',
2996
+ message: { role: 'assistant', content: [{ type: 'text', text: 'Before.' }] },
2997
+ parent_tool_use_id: null,
2998
+ },
2999
+ {
3000
+ type: 'system',
3001
+ subtype: 'status',
3002
+ status: 'compacting',
3003
+ uuid: 'compact-status',
3004
+ session_id: 'claude-session-1',
3005
+ },
3006
+ {
3007
+ type: 'user',
3008
+ uuid: 'compact-summary',
3009
+ session_id: 'claude-session-1',
3010
+ isCompactSummary: true,
3011
+ message: { role: 'user', content: 'HIDDEN LIVE SUMMARY' },
3012
+ parent_tool_use_id: null,
3013
+ },
3014
+ {
3015
+ type: 'system',
3016
+ subtype: 'compact_boundary',
3017
+ compact_metadata: { trigger: 'auto', pre_tokens: 180_000 },
3018
+ uuid: 'compact-boundary',
3019
+ session_id: 'claude-session-1',
3020
+ },
3021
+ {
3022
+ type: 'assistant',
3023
+ uuid: 'assistant-after-compact',
3024
+ session_id: 'claude-session-1',
3025
+ message: { role: 'assistant', content: [{ type: 'text', text: 'After.' }] },
3026
+ parent_tool_use_id: null,
3027
+ },
3028
+ result(),
3029
+ ]);
3030
+ const events: AgentRuntimeEvent[] = [];
3031
+ adapter.on('event', (event) => events.push(event));
3032
+
3033
+ await adapter.startTurn({
3034
+ providerSessionId: 'claude-session-1',
3035
+ displayTurnId: 'turn-compact',
3036
+ prompt: 'Continue working',
3037
+ } as any);
3038
+ await wait();
3039
+
3040
+ const completed = events.findLast((event) => event.type === 'turn.completed');
3041
+ const items = completed?.type === 'turn.completed' ? completed.turn.items : [];
3042
+ expect(completed).toMatchObject({
3043
+ type: 'turn.completed',
3044
+ turn: { providerTurnId: 'turn-compact', status: 'completed' },
3045
+ });
3046
+ expect(items.filter((item) => item.kind === 'contextCompaction')).toEqual([
3047
+ expect.objectContaining({
3048
+ text: 'Context compacted',
3049
+ detailText: null,
3050
+ status: 'completed',
3051
+ }),
3052
+ ]);
3053
+ expect(items).toEqual(expect.arrayContaining([
3054
+ expect.objectContaining({ kind: 'agentMessage', text: 'Before.' }),
3055
+ expect.objectContaining({ kind: 'agentMessage', text: 'After.' }),
3056
+ ]));
3057
+ expect(JSON.stringify(items)).not.toContain('HIDDEN LIVE SUMMARY');
3058
+ });
3059
+
3060
+ it('does not create a historical turn for Claude compact summaries', async () => {
3061
+ const adapter = new ClaudeRuntimeAdapter({
3062
+ home: '/tmp/claude-home',
3063
+ query: (() => new FakeQuery([])) as any,
3064
+ getSessionInfo: (async () => ({
3065
+ sessionId: 'claude-session-1',
3066
+ summary: 'Existing session',
3067
+ lastModified: 1_772_000_000_000,
3068
+ createdAt: 1_771_000_000_000,
3069
+ cwd: '/tmp/workspace',
3070
+ firstPrompt: 'Check training',
3071
+ })) as any,
3072
+ getSessionMessages: (async () => [
3073
+ {
3074
+ type: 'user',
3075
+ uuid: uuidV7At(1_771_000_000_000),
3076
+ session_id: 'claude-session-1',
3077
+ message: { role: 'user', content: 'Check training' },
3078
+ parent_tool_use_id: null,
3079
+ },
3080
+ {
3081
+ type: 'assistant',
3082
+ uuid: 'assistant-before-compact',
3083
+ session_id: 'claude-session-1',
3084
+ message: { role: 'assistant', content: [{ type: 'text', text: 'Before.' }] },
3085
+ parent_tool_use_id: null,
3086
+ },
3087
+ {
3088
+ type: 'user',
3089
+ uuid: 'compact-summary',
3090
+ session_id: 'claude-session-1',
3091
+ message: {
3092
+ role: 'user',
3093
+ content: 'This session is being continued from a previous conversation that ran out of context. HIDDEN HISTORICAL SUMMARY',
3094
+ },
3095
+ parent_tool_use_id: null,
3096
+ },
3097
+ {
3098
+ type: 'assistant',
3099
+ uuid: 'assistant-after-compact',
3100
+ session_id: 'claude-session-1',
3101
+ message: { role: 'assistant', content: [{ type: 'text', text: 'After.' }] },
3102
+ parent_tool_use_id: null,
3103
+ },
3104
+ ] satisfies SessionMessage[]) as any,
3105
+ });
3106
+
3107
+ const session = await adapter.readSession('claude-session-1');
3108
+ expect(session.turns).toHaveLength(1);
3109
+ expect(session.turns[0]?.items).toEqual(expect.arrayContaining([
3110
+ expect.objectContaining({ kind: 'userMessage', text: 'Check training' }),
3111
+ expect.objectContaining({ kind: 'agentMessage', text: 'Before.' }),
3112
+ expect.objectContaining({
3113
+ kind: 'contextCompaction',
3114
+ text: 'Context compacted',
3115
+ detailText: null,
3116
+ }),
3117
+ expect.objectContaining({ kind: 'agentMessage', text: 'After.' }),
3118
+ ]));
3119
+ expect(JSON.stringify(session.turns)).not.toContain('HIDDEN HISTORICAL SUMMARY');
3120
+ });
2986
3121
  });
@@ -46,6 +46,7 @@ import {
46
46
  isHiddenContinuationMessage,
47
47
  isHiddenInitMessage,
48
48
  limitErrorFromHistoryItems,
49
+ messageContentText,
49
50
  partialReasoningDelta,
50
51
  partialTextDelta,
51
52
  resultForToolUse,
@@ -133,6 +134,16 @@ interface SDKMessage {
133
134
  errors?: string[];
134
135
  stop_reason?: string;
135
136
  rate_limit_info?: SDKRateLimitInfo;
137
+ compact_metadata?: {
138
+ trigger?: 'manual' | 'auto';
139
+ pre_tokens?: number;
140
+ post_tokens?: number;
141
+ };
142
+ compact_result?: 'success' | 'failed';
143
+ compact_error?: string;
144
+ status?: 'compacting' | 'requesting' | null;
145
+ isCompactSummary?: boolean;
146
+ is_compact_summary?: boolean;
136
147
  }
137
148
  interface SDKRateLimitInfo {
138
149
  status: 'allowed' | 'allowed_warning' | 'rejected';
@@ -244,11 +255,63 @@ interface ActiveClaudeTurn {
244
255
  assistantUsage: ClaudeTokenUsageBreakdown | null;
245
256
  resultUsage: ClaudeTokenUsageBreakdown | null;
246
257
  modelContextWindow: number | null;
258
+ currentCompactionItemId: string | null;
247
259
  }
248
260
 
249
261
  const promptPhotoTokenPattern = /\[PHOTO\s+([^\]]+)\]/g;
262
+ const claudeCompactSummaryPrefix =
263
+ 'This session is being continued from a previous conversation that ran out of context.';
250
264
  const activeTranscriptMatchWindowMs = 120_000;
251
265
 
266
+ function isClaudeCompactBoundaryMessage(message: SDKMessage | SessionMessage) {
267
+ if (message.type !== 'system') {
268
+ return false;
269
+ }
270
+ if (message.subtype === 'compact_boundary' || message.compact_metadata) {
271
+ return true;
272
+ }
273
+ return isRecord(message.message)
274
+ && (message.message.subtype === 'compact_boundary' || isRecord(message.message.compact_metadata));
275
+ }
276
+
277
+ function isClaudeCompactSummaryMessage(message: SDKMessage | SessionMessage) {
278
+ if (message.type !== 'user' || message.parent_tool_use_id) {
279
+ return false;
280
+ }
281
+ const payload = isRecord(message.message) ? message.message : null;
282
+ if (
283
+ message.isCompactSummary
284
+ || message.is_compact_summary
285
+ || payload?.isCompactSummary === true
286
+ || payload?.is_compact_summary === true
287
+ ) {
288
+ return true;
289
+ }
290
+ return messageContentText(message.message).trim().startsWith(claudeCompactSummaryPrefix);
291
+ }
292
+
293
+ function claudeContextCompactionItem(
294
+ id: string,
295
+ status: 'running' | 'completed' | 'failed',
296
+ error: string | null = null,
297
+ ): AgentHistoryItem {
298
+ const completed = status === 'completed';
299
+ const failed = status === 'failed';
300
+ const text = failed
301
+ ? 'Context compaction failed'
302
+ : completed
303
+ ? 'Context compacted'
304
+ : 'Compacting context';
305
+ return {
306
+ id,
307
+ kind: 'contextCompaction',
308
+ text,
309
+ previewText: text,
310
+ detailText: failed ? error : null,
311
+ status,
312
+ };
313
+ }
314
+
252
315
  function normalizePromptForTurnReconciliation(value: string) {
253
316
  return value
254
317
  // Claude history can rewrite or omit an image marker. The surrounding
@@ -1690,6 +1753,7 @@ export class ClaudeRuntimeAdapter extends EventEmitter implements AgentRuntime {
1690
1753
  assistantUsage: null,
1691
1754
  resultUsage: null,
1692
1755
  modelContextWindow: null,
1756
+ currentCompactionItemId: null,
1693
1757
  };
1694
1758
  this.knownSessionIds.add(input.providerSessionId);
1695
1759
  let sessionPrompts = this.liveUserPrompts.get(input.providerSessionId);
@@ -1976,6 +2040,62 @@ export class ClaudeRuntimeAdapter extends EventEmitter implements AgentRuntime {
1976
2040
  return;
1977
2041
  }
1978
2042
 
2043
+ if (message.type === 'system' && message.subtype === 'status') {
2044
+ if (message.status === 'compacting') {
2045
+ const existing = state.currentCompactionItemId
2046
+ ? state.items.get(state.currentCompactionItemId)
2047
+ : null;
2048
+ const itemId = existing?.status === 'running'
2049
+ ? existing.id
2050
+ : `claude-compaction-${messageUuid(message, randomUUID())}`;
2051
+ state.currentCompactionItemId = itemId;
2052
+ const item = withHistoryItemCreatedAt(
2053
+ claudeContextCompactionItem(itemId, 'running'),
2054
+ messageCreatedAt,
2055
+ );
2056
+ addOrUpdateItem(state, item);
2057
+ this.emitItem(state, item, 'item.started', { force: Boolean(existing) });
2058
+ return;
2059
+ }
2060
+ if (message.compact_result) {
2061
+ const itemId = state.currentCompactionItemId
2062
+ ?? `claude-compaction-${messageUuid(message, randomUUID())}`;
2063
+ const status = message.compact_result === 'success' ? 'completed' : 'failed';
2064
+ const item = withHistoryItemCreatedAt(
2065
+ claudeContextCompactionItem(itemId, status, message.compact_error ?? null),
2066
+ messageCreatedAt,
2067
+ );
2068
+ addOrUpdateItem(state, item);
2069
+ this.emitItem(state, item, 'item.completed');
2070
+ state.currentCompactionItemId = status === 'failed' ? null : itemId;
2071
+ return;
2072
+ }
2073
+ return;
2074
+ }
2075
+
2076
+ if (isClaudeCompactBoundaryMessage(message)) {
2077
+ const itemId = state.currentCompactionItemId
2078
+ ?? `claude-compaction-${messageUuid(message, randomUUID())}`;
2079
+ const previous = state.items.get(itemId);
2080
+ const item = withHistoryItemCreatedAt(
2081
+ claudeContextCompactionItem(itemId, 'completed'),
2082
+ previous?.createdAt ?? messageCreatedAt,
2083
+ );
2084
+ addOrUpdateItem(state, item);
2085
+ if (!previous) {
2086
+ this.emitItem(state, item, 'item.started');
2087
+ }
2088
+ if (previous?.status !== 'completed') {
2089
+ this.emitItem(state, item, 'item.completed');
2090
+ }
2091
+ state.currentCompactionItemId = null;
2092
+ return;
2093
+ }
2094
+
2095
+ if (isClaudeCompactSummaryMessage(message)) {
2096
+ return;
2097
+ }
2098
+
1979
2099
  if (message.type === 'stream_event') {
1980
2100
  const nextStreamMessageId = streamMessageId(message.event);
1981
2101
  if (nextStreamMessageId) {
@@ -2408,6 +2528,8 @@ export class ClaudeRuntimeAdapter extends EventEmitter implements AgentRuntime {
2408
2528
  itemsById: Map<string, AgentHistoryItem>;
2409
2529
  } | null = null;
2410
2530
  let skippingHiddenInit = false;
2531
+ let pendingCompactSummaryItemId: string | null = null;
2532
+ let pendingCompactBoundaryItemId: string | null = null;
2411
2533
  const suppressedToolUseIds = new Set<string>();
2412
2534
 
2413
2535
  const upsertCurrentItem = (item: AgentHistoryItem) => {
@@ -2441,6 +2563,20 @@ export class ClaudeRuntimeAdapter extends EventEmitter implements AgentRuntime {
2441
2563
  };
2442
2564
 
2443
2565
  for (const message of messages) {
2566
+ if (isClaudeCompactBoundaryMessage(message)) {
2567
+ const itemId: string = pendingCompactSummaryItemId
2568
+ ?? `claude-compaction-${messageUuid(message, randomUUID())}`;
2569
+ pendingCompactSummaryItemId = null;
2570
+ pendingCompactBoundaryItemId = itemId;
2571
+ upsertCurrentItem(
2572
+ withHistoryItemCreatedAt(
2573
+ claudeContextCompactionItem(itemId, 'completed'),
2574
+ sessionMessageTimestamp(message) ?? current?.startedAt,
2575
+ ),
2576
+ );
2577
+ continue;
2578
+ }
2579
+
2444
2580
  if (message.type === 'user') {
2445
2581
  const taskNotification = taskNotificationToolResult(message.message);
2446
2582
  if (taskNotification) {
@@ -2487,6 +2623,21 @@ export class ClaudeRuntimeAdapter extends EventEmitter implements AgentRuntime {
2487
2623
  }
2488
2624
 
2489
2625
  if (message.type === 'user' && !message.parent_tool_use_id) {
2626
+ if (isClaudeCompactSummaryMessage(message)) {
2627
+ const itemId: string = pendingCompactBoundaryItemId
2628
+ ?? `claude-compaction-${messageUuid(message, randomUUID())}`;
2629
+ if (!pendingCompactBoundaryItemId) {
2630
+ pendingCompactSummaryItemId = itemId;
2631
+ }
2632
+ pendingCompactBoundaryItemId = null;
2633
+ upsertCurrentItem(
2634
+ withHistoryItemCreatedAt(
2635
+ claudeContextCompactionItem(itemId, 'completed'),
2636
+ sessionMessageTimestamp(message) ?? current?.startedAt,
2637
+ ),
2638
+ );
2639
+ continue;
2640
+ }
2490
2641
  if (isHiddenInitMessage(message.message)) {
2491
2642
  skippingHiddenInit = true;
2492
2643
  current = null;
@@ -2506,19 +2657,19 @@ export class ClaudeRuntimeAdapter extends EventEmitter implements AgentRuntime {
2506
2657
  items: current.items,
2507
2658
  }));
2508
2659
  }
2509
- const messageUuid = message.uuid ?? randomUUID();
2510
- const userStartedAt = isoFromUuidV7(messageUuid);
2660
+ const userMessageUuid = message.uuid ?? randomUUID();
2661
+ const userStartedAt = isoFromUuidV7(userMessageUuid);
2511
2662
  const userItem = await this.userMessageToHistoryItem(
2512
- messageUuid,
2663
+ userMessageUuid,
2513
2664
  message.message,
2514
2665
  context,
2515
2666
  );
2516
2667
  const stampedUserItem = withHistoryItemCreatedAt(userItem, userStartedAt);
2517
2668
  current = {
2518
- providerTurnId: `claude-turn-${messageUuid}`,
2669
+ providerTurnId: `claude-turn-${userMessageUuid}`,
2519
2670
  startedAt: userStartedAt,
2520
2671
  items: [stampedUserItem],
2521
- itemsById: new Map([[messageUuid, stampedUserItem]]),
2672
+ itemsById: new Map([[userMessageUuid, stampedUserItem]]),
2522
2673
  };
2523
2674
  continue;
2524
2675
  }