shennian 0.2.71 → 0.2.72
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.
|
@@ -60,11 +60,12 @@ function parseCodexTextElements(value) {
|
|
|
60
60
|
function stripCodexUserMessageWrapper(text) {
|
|
61
61
|
const normalized = normalizeText(text);
|
|
62
62
|
if (!normalized)
|
|
63
|
-
return '';
|
|
63
|
+
return { text: '', strippedWrapper: false };
|
|
64
64
|
const requestMatch = normalized.match(/My request for Codex:\s*([\s\S]*)$/i);
|
|
65
|
-
if (requestMatch && requestMatch[1])
|
|
66
|
-
return stripCodexImagePlaceholders(requestMatch[1]);
|
|
67
|
-
|
|
65
|
+
if (requestMatch && requestMatch[1]) {
|
|
66
|
+
return { text: stripCodexImagePlaceholders(requestMatch[1]), strippedWrapper: true };
|
|
67
|
+
}
|
|
68
|
+
return { text: normalized, strippedWrapper: false };
|
|
68
69
|
}
|
|
69
70
|
function stripCodexImagePlaceholders(text) {
|
|
70
71
|
return normalizeText(text.replace(/<image>\s*<\/image>/gi, ''));
|
|
@@ -74,10 +75,12 @@ function parseCodexUserMessage(payload) {
|
|
|
74
75
|
const textFromInput = Array.isArray(payload.input)
|
|
75
76
|
? parseCodexTextElements(payload.input)
|
|
76
77
|
: '';
|
|
77
|
-
const
|
|
78
|
+
const strippedMessage = typeof payload.message === 'string'
|
|
78
79
|
? stripCodexUserMessageWrapper(payload.message)
|
|
79
|
-
: '';
|
|
80
|
+
: { text: '', strippedWrapper: false };
|
|
81
|
+
const textFromMessage = strippedMessage.text;
|
|
80
82
|
const text = textFromElements || textFromInput || textFromMessage;
|
|
83
|
+
const repairHint = strippedMessage.strippedWrapper ? 'codex_app_context_wrapper' : undefined;
|
|
81
84
|
const attachments = Array.isArray(payload.local_images)
|
|
82
85
|
? payload.local_images
|
|
83
86
|
.map(parseCodexLocalImageAttachment)
|
|
@@ -91,9 +94,10 @@ function parseCodexUserMessage(payload) {
|
|
|
91
94
|
return {
|
|
92
95
|
payload: buildUserMessagePayload(text, attachments),
|
|
93
96
|
titleText: text,
|
|
97
|
+
repairHint,
|
|
94
98
|
};
|
|
95
99
|
}
|
|
96
|
-
return { payload: text, titleText: text };
|
|
100
|
+
return { payload: text, titleText: text, repairHint };
|
|
97
101
|
}
|
|
98
102
|
function isCodexTerminalEventType(eventType) {
|
|
99
103
|
return eventType === 'turn_completed' || eventType === 'turn_complete' || eventType === 'task_complete';
|
|
@@ -174,7 +178,8 @@ function parseCodexResponseMessage(payload) {
|
|
|
174
178
|
return null;
|
|
175
179
|
return text ? { role, payload: text, titleText: text } : null;
|
|
176
180
|
}
|
|
177
|
-
const
|
|
181
|
+
const stripped = stripCodexUserMessageWrapper(codexMessageContentText(payload.content, 'input_text'));
|
|
182
|
+
const text = stripped.text;
|
|
178
183
|
const attachments = codexMessageInputImageAttachments(payload.content);
|
|
179
184
|
if (!text && attachments.length === 0)
|
|
180
185
|
return null;
|
|
@@ -184,6 +189,7 @@ function parseCodexResponseMessage(payload) {
|
|
|
184
189
|
role,
|
|
185
190
|
payload: attachments.length > 0 ? buildUserMessagePayload(text, attachments) : text,
|
|
186
191
|
titleText: text,
|
|
192
|
+
repairHint: stripped.strippedWrapper ? 'codex_app_context_wrapper' : undefined,
|
|
187
193
|
};
|
|
188
194
|
}
|
|
189
195
|
function codexDedupeText(payload) {
|
|
@@ -225,7 +231,7 @@ function findDuplicateCodexChatEventIndex(events, role, payload, ts) {
|
|
|
225
231
|
}
|
|
226
232
|
return -1;
|
|
227
233
|
}
|
|
228
|
-
function pushCodexEvent(events, filePath, lineOffset, kind, sourceSessionKey, ts, payload, title, modelId, workDir, role = 'agent', terminal = false) {
|
|
234
|
+
function pushCodexEvent(events, filePath, lineOffset, kind, sourceSessionKey, ts, payload, title, modelId, workDir, role = 'agent', terminal = false, repairHint) {
|
|
229
235
|
if (!payload)
|
|
230
236
|
return;
|
|
231
237
|
events.push({
|
|
@@ -241,6 +247,7 @@ function pushCodexEvent(events, filePath, lineOffset, kind, sourceSessionKey, ts
|
|
|
241
247
|
modelId,
|
|
242
248
|
workDir,
|
|
243
249
|
terminal,
|
|
250
|
+
repairHint,
|
|
244
251
|
});
|
|
245
252
|
}
|
|
246
253
|
function pushCodexToolEvent(events, filePath, lineOffset, kind, sourceSessionKey, ts, toolName, title, modelId, workDir, args, result) {
|
|
@@ -257,7 +264,7 @@ function parseCodexResponseItem(events, filePath, lineOffset, payload, sourceSes
|
|
|
257
264
|
const duplicateIndex = findDuplicateCodexChatEventIndex(events, parsedMessage.role, parsedMessage.payload, ts);
|
|
258
265
|
if (duplicateIndex >= 0)
|
|
259
266
|
return;
|
|
260
|
-
pushCodexEvent(events, filePath, lineOffset, `${itemType}:${parsedMessage.role}`, sourceSessionKey, ts, parsedMessage.payload, title, modelId, workDir, parsedMessage.role);
|
|
267
|
+
pushCodexEvent(events, filePath, lineOffset, `${itemType}:${parsedMessage.role}`, sourceSessionKey, ts, parsedMessage.payload, title, modelId, workDir, parsedMessage.role, false, parsedMessage.repairHint);
|
|
261
268
|
return;
|
|
262
269
|
}
|
|
263
270
|
if (itemType === 'function_call') {
|
|
@@ -297,7 +304,7 @@ function parseCodexEventMessage(events, filePath, lineOffset, payload, sourceSes
|
|
|
297
304
|
const parsedUser = parseCodexUserMessage(payload);
|
|
298
305
|
if (!parsedUser)
|
|
299
306
|
return;
|
|
300
|
-
pushCodexEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, parsedUser.payload, title, modelId, workDir, 'user');
|
|
307
|
+
pushCodexEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, parsedUser.payload, title, modelId, workDir, 'user', false, parsedUser.repairHint);
|
|
301
308
|
return;
|
|
302
309
|
}
|
|
303
310
|
if (eventType === 'agent_message') {
|
|
@@ -108,9 +108,10 @@ export class NativeSessionFusionService {
|
|
|
108
108
|
const current = state.files[filePath];
|
|
109
109
|
const isCodex = isCodexRolloutPath(filePath);
|
|
110
110
|
const isOpenCode = filePath.endsWith('.opencode-session.json');
|
|
111
|
+
const isCodexRepairBackfillFile = backfillCodexAppContextWrapper && isCodex && current != null;
|
|
111
112
|
const startOffset = isOpenCode && current?.mtimeMs !== stat.mtimeMs
|
|
112
113
|
? 0
|
|
113
|
-
: (backfillWindowsCodex ||
|
|
114
|
+
: (backfillWindowsCodex || isCodexRepairBackfillFile) && isCodex
|
|
114
115
|
? 0
|
|
115
116
|
: current?.offset ?? 0;
|
|
116
117
|
const parsed = isOpenCode
|
|
@@ -122,7 +123,10 @@ export class NativeSessionFusionService {
|
|
|
122
123
|
offset: parsed.nextOffset,
|
|
123
124
|
mtimeMs: stat.mtimeMs,
|
|
124
125
|
};
|
|
125
|
-
|
|
126
|
+
const parsedEvents = isCodexRepairBackfillFile && startOffset === 0
|
|
127
|
+
? parsed.events.filter((event) => event.repairHint === 'codex_app_context_wrapper')
|
|
128
|
+
: parsed.events;
|
|
129
|
+
for (const event of parsedEvents) {
|
|
126
130
|
const claimed = this.tryClaimManagedEcho(event);
|
|
127
131
|
if (claimed) {
|
|
128
132
|
batches.push(claimed);
|
|
@@ -137,11 +141,12 @@ export class NativeSessionFusionService {
|
|
|
137
141
|
const chunk = batches.slice(index, index + MAX_BATCH_SIZE);
|
|
138
142
|
if (chunk.length === 0)
|
|
139
143
|
continue;
|
|
144
|
+
const wireEvents = chunk.map(({ repairHint: _repairHint, ...event }) => event);
|
|
140
145
|
await this.client.sendBufferedEvent({
|
|
141
146
|
type: 'event',
|
|
142
147
|
event: 'native.session.events',
|
|
143
148
|
id: `native-fusion-${randomUUID()}`,
|
|
144
|
-
payload: { events:
|
|
149
|
+
payload: { events: wireEvents },
|
|
145
150
|
}, 60_000);
|
|
146
151
|
}
|
|
147
152
|
state.files = nextFilesState;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { NativeSessionEventPayload } from '@shennian/wire';
|
|
2
|
+
export type NativeRepairHint = 'codex_app_context_wrapper';
|
|
2
3
|
export type NativeScannerState = {
|
|
3
4
|
files: Record<string, {
|
|
4
5
|
offset: number;
|
|
@@ -7,7 +8,9 @@ export type NativeScannerState = {
|
|
|
7
8
|
codexWindowsPathParserFixed?: boolean;
|
|
8
9
|
codexAppContextWrapperFixed?: boolean;
|
|
9
10
|
};
|
|
10
|
-
export type ParsedNativeEvent = NativeSessionEventPayload
|
|
11
|
+
export type ParsedNativeEvent = NativeSessionEventPayload & {
|
|
12
|
+
repairHint?: NativeRepairHint;
|
|
13
|
+
};
|
|
11
14
|
export type PendingManagedClaim = {
|
|
12
15
|
sessionId: string;
|
|
13
16
|
agentType: string;
|