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
|
|
13596
|
-
const userStartedAt = isoFromUuidV7(
|
|
13704
|
+
const userMessageUuid = message.uuid ?? randomUUID2();
|
|
13705
|
+
const userStartedAt = isoFromUuidV7(userMessageUuid);
|
|
13597
13706
|
const userItem = await this.userMessageToHistoryItem(
|
|
13598
|
-
|
|
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-${
|
|
13713
|
+
providerTurnId: `claude-turn-${userMessageUuid}`,
|
|
13605
13714
|
startedAt: userStartedAt,
|
|
13606
13715
|
items: [stampedUserItem],
|
|
13607
|
-
itemsById: /* @__PURE__ */ new Map([[
|
|
13716
|
+
itemsById: /* @__PURE__ */ new Map([[userMessageUuid, stampedUserItem]])
|
|
13608
13717
|
};
|
|
13609
13718
|
continue;
|
|
13610
13719
|
}
|
package/package.json
CHANGED
|
@@ -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
|
|
2510
|
-
const userStartedAt = isoFromUuidV7(
|
|
2660
|
+
const userMessageUuid = message.uuid ?? randomUUID();
|
|
2661
|
+
const userStartedAt = isoFromUuidV7(userMessageUuid);
|
|
2511
2662
|
const userItem = await this.userMessageToHistoryItem(
|
|
2512
|
-
|
|
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-${
|
|
2669
|
+
providerTurnId: `claude-turn-${userMessageUuid}`,
|
|
2519
2670
|
startedAt: userStartedAt,
|
|
2520
2671
|
items: [stampedUserItem],
|
|
2521
|
-
itemsById: new Map([[
|
|
2672
|
+
itemsById: new Map([[userMessageUuid, stampedUserItem]]),
|
|
2522
2673
|
};
|
|
2523
2674
|
continue;
|
|
2524
2675
|
}
|