shennian 0.2.88 → 0.2.90

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.
Files changed (143) hide show
  1. package/dist/assets/wechat-channel/macos/manifest.json +22 -0
  2. package/dist/assets/wechat-channel/macos/shennian-wechat-channel-helper +0 -0
  3. package/dist/bin/shennian.js +1 -1
  4. package/dist/publish-build-manifest.json +548 -0
  5. package/dist/scripts/wechat-rpa-confirmation.mjs +5 -97
  6. package/dist/src/agent-env.js +4 -105
  7. package/dist/src/agents/adapter.d.ts +6 -0
  8. package/dist/src/agents/adapter.js +1 -19
  9. package/dist/src/agents/claude.js +8 -305
  10. package/dist/src/agents/codex-control.d.ts +35 -0
  11. package/dist/src/agents/codex-control.js +2 -0
  12. package/dist/src/agents/codex-utils.js +7 -200
  13. package/dist/src/agents/codex.d.ts +8 -0
  14. package/dist/src/agents/codex.js +15 -863
  15. package/dist/src/agents/command-spec.js +2 -413
  16. package/dist/src/agents/config-status.js +1 -226
  17. package/dist/src/agents/cursor.js +1 -249
  18. package/dist/src/agents/custom.js +4 -271
  19. package/dist/src/agents/detect.js +1 -56
  20. package/dist/src/agents/external-channel-instructions.js +10 -94
  21. package/dist/src/agents/gemini.js +1 -173
  22. package/dist/src/agents/manager.js +13 -157
  23. package/dist/src/agents/model-registry/cache.js +1 -37
  24. package/dist/src/agents/model-registry/discovery.js +2 -187
  25. package/dist/src/agents/model-registry/parsers.js +4 -447
  26. package/dist/src/agents/model-registry/runner.js +1 -30
  27. package/dist/src/agents/model-registry/service.js +1 -78
  28. package/dist/src/agents/model-registry/types.js +1 -8
  29. package/dist/src/agents/model-registry.js +1 -18
  30. package/dist/src/agents/openclaw.js +2 -275
  31. package/dist/src/agents/opencode.js +1 -231
  32. package/dist/src/agents/pi-context.js +12 -217
  33. package/dist/src/agents/pi.js +14 -723
  34. package/dist/src/agents/platform-instructions.js +9 -54
  35. package/dist/src/channels/base.d.ts +4 -1
  36. package/dist/src/channels/base.js +1 -3
  37. package/dist/src/channels/registry.js +1 -30
  38. package/dist/src/channels/reply-split.js +10 -89
  39. package/dist/src/channels/runtime.d.ts +1 -0
  40. package/dist/src/channels/runtime.js +5 -533
  41. package/dist/src/channels/secret-registry.d.ts +1 -0
  42. package/dist/src/channels/secret-registry.js +1 -46
  43. package/dist/src/channels/websocket.js +8 -378
  44. package/dist/src/channels/wechat-channel/anchor.d.ts +10 -0
  45. package/dist/src/channels/wechat-channel/anchor.js +1 -0
  46. package/dist/src/channels/wechat-channel/client.d.ts +74 -0
  47. package/dist/src/channels/wechat-channel/client.js +1 -0
  48. package/dist/src/channels/wechat-channel/cooldown.d.ts +15 -0
  49. package/dist/src/channels/wechat-channel/cooldown.js +1 -0
  50. package/dist/src/channels/wechat-channel/fingerprint.d.ts +28 -0
  51. package/dist/src/channels/wechat-channel/fingerprint.js +1 -0
  52. package/dist/src/channels/wechat-channel/helper-assets.d.ts +37 -0
  53. package/dist/src/channels/wechat-channel/helper-assets.js +1 -0
  54. package/dist/src/channels/wechat-channel/helper-client.d.ts +25 -0
  55. package/dist/src/channels/wechat-channel/helper-client.js +3 -0
  56. package/dist/src/channels/wechat-channel/helper-protocol.d.ts +84 -0
  57. package/dist/src/channels/wechat-channel/helper-protocol.js +1 -0
  58. package/dist/src/channels/wechat-channel/index.d.ts +17 -0
  59. package/dist/src/channels/wechat-channel/index.js +1 -0
  60. package/dist/src/channels/wechat-channel/ledger.d.ts +33 -0
  61. package/dist/src/channels/wechat-channel/ledger.js +1 -0
  62. package/dist/src/channels/wechat-channel/media-resolver.d.ts +32 -0
  63. package/dist/src/channels/wechat-channel/media-resolver.js +1 -0
  64. package/dist/src/channels/wechat-channel/message-key.d.ts +19 -0
  65. package/dist/src/channels/wechat-channel/message-key.js +1 -0
  66. package/dist/src/channels/wechat-channel/observer.d.ts +64 -0
  67. package/dist/src/channels/wechat-channel/observer.js +1 -0
  68. package/dist/src/channels/wechat-channel/outbound-ledger.d.ts +69 -0
  69. package/dist/src/channels/wechat-channel/outbound-ledger.js +2 -0
  70. package/dist/src/channels/wechat-channel/outbound-sender.d.ts +26 -0
  71. package/dist/src/channels/wechat-channel/outbound-sender.js +1 -0
  72. package/dist/src/channels/wechat-channel/preflight.d.ts +37 -0
  73. package/dist/src/channels/wechat-channel/preflight.js +1 -0
  74. package/dist/src/channels/wechat-channel/runner.d.ts +34 -0
  75. package/dist/src/channels/wechat-channel/runner.js +1 -0
  76. package/dist/src/channels/wechat-channel/runtime.d.ts +45 -0
  77. package/dist/src/channels/wechat-channel/runtime.js +1 -0
  78. package/dist/src/channels/wechat-channel/scheduler.d.ts +35 -0
  79. package/dist/src/channels/wechat-channel/scheduler.js +1 -0
  80. package/dist/src/channels/wechat-rpa/macos-flow.js +1 -96
  81. package/dist/src/channels/wechat-rpa/macos.js +6 -48
  82. package/dist/src/channels/wechat-rpa/normalizer.js +7 -127
  83. package/dist/src/channels/wechat-rpa.d.ts +21 -0
  84. package/dist/src/channels/wechat-rpa.js +6 -1022
  85. package/dist/src/channels/wecom.js +4 -357
  86. package/dist/src/commands/agent.js +6 -131
  87. package/dist/src/commands/daemon-windows.js +8 -48
  88. package/dist/src/commands/daemon.js +19 -1013
  89. package/dist/src/commands/external-attachments.js +1 -51
  90. package/dist/src/commands/external.js +1 -137
  91. package/dist/src/commands/manager.js +2 -389
  92. package/dist/src/commands/pair-qr.js +1 -6
  93. package/dist/src/commands/pair.js +9 -287
  94. package/dist/src/commands/tools.js +1 -34
  95. package/dist/src/commands/upgrade.js +1 -198
  96. package/dist/src/config/index.js +1 -35
  97. package/dist/src/daemon-log.js +6 -58
  98. package/dist/src/env-path.js +1 -64
  99. package/dist/src/fs/boundary.js +1 -126
  100. package/dist/src/fs/handler.js +1 -130
  101. package/dist/src/fs/security.js +1 -32
  102. package/dist/src/fs/text-decoder.d.ts +10 -0
  103. package/dist/src/fs/text-decoder.js +1 -0
  104. package/dist/src/index.js +2 -404
  105. package/dist/src/log-reporter.js +1 -16
  106. package/dist/src/manager/prompt.js +29 -34
  107. package/dist/src/manager/registry.js +2 -269
  108. package/dist/src/manager/runtime.js +19 -1003
  109. package/dist/src/native-fusion/config.js +1 -5
  110. package/dist/src/native-fusion/opencode-parser.js +3 -123
  111. package/dist/src/native-fusion/parser-common.js +8 -264
  112. package/dist/src/native-fusion/parsers.js +8 -729
  113. package/dist/src/native-fusion/service.d.ts +10 -0
  114. package/dist/src/native-fusion/service.js +2 -198
  115. package/dist/src/native-fusion/state.js +1 -22
  116. package/dist/src/native-fusion/types.js +1 -1
  117. package/dist/src/region.js +1 -88
  118. package/dist/src/relay/client.js +1 -343
  119. package/dist/src/session/archive-zip.js +1 -220
  120. package/dist/src/session/handlers/agent-config.js +1 -150
  121. package/dist/src/session/handlers/agents.js +1 -55
  122. package/dist/src/session/handlers/chat.js +2 -733
  123. package/dist/src/session/handlers/control.js +1 -55
  124. package/dist/src/session/handlers/fs.js +1 -747
  125. package/dist/src/session/handlers/session-refresh.js +1 -35
  126. package/dist/src/session/handlers/skills.js +1 -121
  127. package/dist/src/session/handlers/title.js +1 -60
  128. package/dist/src/session/handlers/tool-detail.d.ts +3 -0
  129. package/dist/src/session/handlers/tool-detail.js +1 -0
  130. package/dist/src/session/manager.d.ts +3 -0
  131. package/dist/src/session/manager.js +1 -261
  132. package/dist/src/session/projection.js +1 -54
  133. package/dist/src/session/queue.js +4 -317
  134. package/dist/src/session/remote-attachments.js +1 -72
  135. package/dist/src/session/store.js +3 -109
  136. package/dist/src/session/types.d.ts +4 -0
  137. package/dist/src/session/types.js +1 -4
  138. package/dist/src/skills/registry.js +15 -148
  139. package/dist/src/skills/setup.js +1 -101
  140. package/dist/src/tools/markdown-to-pdf.js +10 -346
  141. package/dist/src/upgrade/engine.js +3 -347
  142. package/package.json +3 -2
  143. package/dist/scripts/wechat-rpa-download-candidates.mjs +0 -105
@@ -1,729 +1,8 @@
1
- // @arch docs/architecture/cli/native-session-fusion.md
2
- // @test src/__tests__/native-fusion-parsers.test.ts
3
- import fs from 'node:fs';
4
- import os from 'node:os';
5
- import path from 'node:path';
6
- import { buildApprovalPendingPayload, buildUserMessagePayload, isSystemControlPayload, isToolPayload } from '@shennian/wire';
7
- export { listOpenCodeSessionFiles, parseOpenCodeSessionFile, parseOpenCodeSessionSnapshot, } from './opencode-parser.js';
8
- import { buildImagePayload, buildToolPayload, inferMimeType, makeCursor, makeEventKey, normalizeText, parseStructuredString, readClaudeEventCwd, readJsonlLines, readTimestamp, safeParse, isClaudeSubagentTranscript, shouldIgnoreClaudeProjectDir, shouldIgnoreClaudeTranscriptPath, shouldIgnoreNativeScanPath, } from './parser-common.js';
9
- function parseCodexLocalImageAttachment(value) {
10
- if (typeof value === 'string') {
11
- const imagePath = value.trim();
12
- if (!imagePath)
13
- return null;
14
- return {
15
- path: imagePath,
16
- name: path.basename(imagePath) || 'image.png',
17
- mimeType: inferMimeType(imagePath),
18
- kind: 'image',
19
- };
20
- }
21
- if (typeof value !== 'object' || value === null)
22
- return null;
23
- const entry = value;
24
- const imagePath = typeof entry.path === 'string' ? entry.path
25
- : typeof entry.file_path === 'string' ? entry.file_path
26
- : typeof entry.saved_path === 'string' ? entry.saved_path
27
- : '';
28
- if (!imagePath.trim())
29
- return null;
30
- const name = typeof entry.name === 'string' && entry.name.trim()
31
- ? entry.name
32
- : path.basename(imagePath) || 'image.png';
33
- const mimeType = typeof entry.mimeType === 'string' && entry.mimeType.trim()
34
- ? entry.mimeType
35
- : inferMimeType(imagePath);
36
- return {
37
- path: imagePath,
38
- name,
39
- mimeType,
40
- kind: 'image',
41
- };
42
- }
43
- function parseCodexTextElements(value) {
44
- if (!Array.isArray(value))
45
- return '';
46
- const parts = value
47
- .map((item) => {
48
- if (typeof item === 'string')
49
- return item;
50
- if (typeof item === 'object' && item !== null) {
51
- const record = item;
52
- return typeof record.text === 'string' ? record.text : '';
53
- }
54
- return '';
55
- })
56
- .map((text) => normalizeText(text))
57
- .filter(Boolean);
58
- return parts.join('\n\n');
59
- }
60
- function stripCodexUserMessageWrapper(text) {
61
- const normalized = normalizeText(text);
62
- if (!normalized)
63
- return { text: '', strippedWrapper: false };
64
- const requestMatch = normalized.match(/My request for Codex:\s*([\s\S]*)$/i);
65
- if (requestMatch && requestMatch[1]) {
66
- return { text: stripCodexImagePlaceholders(requestMatch[1]), strippedWrapper: true };
67
- }
68
- return { text: normalized, strippedWrapper: false };
69
- }
70
- function stripCodexImagePlaceholders(text) {
71
- return normalizeText(text.replace(/<image>\s*<\/image>/gi, ''));
72
- }
73
- function isCodexInjectedContextText(text) {
74
- const normalized = normalizeText(text);
75
- if (!normalized)
76
- return false;
77
- const hasProjectInstructions = normalized.startsWith('# AGENTS.md instructions for ') &&
78
- normalized.includes('<INSTRUCTIONS>') &&
79
- normalized.includes('</INSTRUCTIONS>');
80
- const hasEnvironmentContext = normalized.includes('<environment_context>') &&
81
- normalized.includes('</environment_context>');
82
- return hasProjectInstructions && hasEnvironmentContext;
83
- }
84
- function parseCodexUserMessage(payload) {
85
- const textFromElements = parseCodexTextElements(payload.text_elements);
86
- const textFromInput = Array.isArray(payload.input)
87
- ? parseCodexTextElements(payload.input)
88
- : '';
89
- const strippedMessage = typeof payload.message === 'string'
90
- ? stripCodexUserMessageWrapper(payload.message)
91
- : { text: '', strippedWrapper: false };
92
- const textFromMessage = strippedMessage.text;
93
- const text = textFromElements || textFromInput || textFromMessage;
94
- const repairHint = strippedMessage.strippedWrapper ? 'codex_app_context_wrapper' : undefined;
95
- const attachments = Array.isArray(payload.local_images)
96
- ? payload.local_images
97
- .map(parseCodexLocalImageAttachment)
98
- .filter((item) => item != null)
99
- : [];
100
- if (!text && attachments.length === 0)
101
- return null;
102
- if (isSystemControlPayload(text) && attachments.length === 0)
103
- return null;
104
- if (isCodexInjectedContextText(text) && attachments.length === 0)
105
- return null;
106
- if (attachments.length > 0) {
107
- return {
108
- payload: buildUserMessagePayload(text, attachments),
109
- titleText: text,
110
- repairHint,
111
- };
112
- }
113
- return { payload: text, titleText: text, repairHint };
114
- }
115
- function isCodexTerminalEventType(eventType) {
116
- return eventType === 'turn_completed' || eventType === 'turn_complete' || eventType === 'task_complete';
117
- }
118
- function isCodexApprovalEventType(eventType) {
119
- return /approval|permission|confirm|user[_-]?input|input[_-]?required/i.test(eventType);
120
- }
121
- function buildCodexApprovalPayload(payload) {
122
- const command = typeof payload.command === 'string'
123
- ? payload.command
124
- : Array.isArray(payload.command)
125
- ? payload.command.join(' ')
126
- : '';
127
- const content = typeof payload.prompt === 'string' ? payload.prompt
128
- : typeof payload.reason === 'string' ? payload.reason
129
- : typeof payload.message === 'string' ? payload.message
130
- : command ? `Codex 请求执行命令:${command}`
131
- : 'Codex 正在等待用户确认后继续。';
132
- return buildApprovalPendingPayload({
133
- title: '需要用户确认',
134
- content,
135
- source: 'codex',
136
- actionHint: '当前神念暂不支持远程确认,请回到运行 Codex 的电脑/终端完成确认。',
137
- });
138
- }
139
- function codexMessageContentText(content, textType) {
140
- if (!Array.isArray(content))
141
- return '';
142
- return normalizeText(content
143
- .map((part) => {
144
- if (typeof part === 'string')
145
- return part;
146
- if (typeof part !== 'object' || part === null)
147
- return '';
148
- const record = part;
149
- if (record.type !== textType)
150
- return '';
151
- return typeof record.text === 'string' ? record.text : '';
152
- })
153
- .filter(Boolean)
154
- .join('\n\n'));
155
- }
156
- function codexMessageInputImageAttachments(content) {
157
- if (!Array.isArray(content))
158
- return [];
159
- const attachments = [];
160
- for (const part of content) {
161
- if (typeof part !== 'object' || part === null)
162
- continue;
163
- const record = part;
164
- if (record.type !== 'input_image')
165
- continue;
166
- const imagePath = typeof record.path === 'string' ? record.path
167
- : typeof record.file_path === 'string' ? record.file_path
168
- : typeof record.saved_path === 'string' ? record.saved_path
169
- : typeof record.image_path === 'string' ? record.image_path
170
- : '';
171
- if (!imagePath.trim())
172
- continue;
173
- attachments.push({
174
- path: imagePath,
175
- name: path.basename(imagePath) || 'image.png',
176
- mimeType: inferMimeType(imagePath),
177
- kind: 'image',
178
- });
179
- }
180
- return attachments;
181
- }
182
- function parseCodexResponseMessage(payload) {
183
- if (payload.type !== 'message')
184
- return null;
185
- const role = payload.role === 'assistant' ? 'agent' : payload.role === 'user' ? 'user' : null;
186
- if (!role)
187
- return null;
188
- if (role === 'agent') {
189
- const text = codexMessageContentText(payload.content, 'output_text');
190
- if (isSystemControlPayload(text))
191
- return null;
192
- return text ? { role, payload: text, titleText: text } : null;
193
- }
194
- const stripped = stripCodexUserMessageWrapper(codexMessageContentText(payload.content, 'input_text'));
195
- const text = stripped.text;
196
- const attachments = codexMessageInputImageAttachments(payload.content);
197
- if (!text && attachments.length === 0)
198
- return null;
199
- if (isSystemControlPayload(text) && attachments.length === 0)
200
- return null;
201
- if (isCodexInjectedContextText(text) && attachments.length === 0)
202
- return null;
203
- return {
204
- role,
205
- payload: attachments.length > 0 ? buildUserMessagePayload(text, attachments) : text,
206
- titleText: text,
207
- repairHint: stripped.strippedWrapper ? 'codex_app_context_wrapper' : undefined,
208
- };
209
- }
210
- function codexDedupeText(payload) {
211
- if (!payload)
212
- return '';
213
- try {
214
- const parsed = JSON.parse(payload);
215
- if (typeof parsed === 'object' && parsed !== null) {
216
- const record = parsed;
217
- if (record.type === 'user' && typeof record.content === 'string')
218
- return normalizeText(record.content);
219
- }
220
- }
221
- catch {
222
- /* plain text payload */
223
- }
224
- return normalizeText(payload);
225
- }
226
- function isDuplicateCodexChatEvent(event, role, payload, ts) {
227
- if (event.agentType !== 'codex')
228
- return false;
229
- if (event.role !== role)
230
- return false;
231
- if (isToolPayload(event.payload))
232
- return false;
233
- if (Math.abs(event.ts - ts) > 5 * 60 * 1000)
234
- return false;
235
- return codexDedupeText(event.payload) === codexDedupeText(payload);
236
- }
237
- function findDuplicateCodexChatEventIndex(events, role, payload, ts) {
238
- for (let i = events.length - 1; i >= 0; i -= 1) {
239
- const event = events[i];
240
- if (!event)
241
- continue;
242
- if (isDuplicateCodexChatEvent(event, role, payload, ts))
243
- return i;
244
- if (event.agentType === 'codex' && Math.abs(event.ts - ts) > 5 * 60 * 1000)
245
- break;
246
- }
247
- return -1;
248
- }
249
- function pushCodexEvent(events, filePath, lineOffset, kind, sourceSessionKey, ts, payload, title, modelId, workDir, role = 'agent', terminal = false, repairHint) {
250
- if (!payload)
251
- return;
252
- events.push({
253
- agentType: 'codex',
254
- sourceMode: 'codex_rollout_import',
255
- sourceSessionKey,
256
- sourceEventKey: makeEventKey(filePath, lineOffset, kind),
257
- cursor: makeCursor(filePath, lineOffset),
258
- role,
259
- ts,
260
- payload,
261
- title,
262
- modelId,
263
- workDir,
264
- terminal,
265
- repairHint,
266
- });
267
- }
268
- function pushCodexToolEvent(events, filePath, lineOffset, kind, sourceSessionKey, ts, toolName, title, modelId, workDir, args, result) {
269
- pushCodexEvent(events, filePath, lineOffset, kind, sourceSessionKey, ts, buildToolPayload(toolName, args, result), title, modelId, workDir);
270
- }
271
- function parseCodexResponseItem(events, filePath, lineOffset, payload, sourceSessionKey, ts, title, modelId, workDir) {
272
- const itemType = typeof payload.type === 'string' ? payload.type : '';
273
- if (!itemType)
274
- return;
275
- if (itemType === 'message') {
276
- const parsedMessage = parseCodexResponseMessage(payload);
277
- if (!parsedMessage)
278
- return;
279
- const duplicateIndex = findDuplicateCodexChatEventIndex(events, parsedMessage.role, parsedMessage.payload, ts);
280
- if (duplicateIndex >= 0)
281
- return;
282
- pushCodexEvent(events, filePath, lineOffset, `${itemType}:${parsedMessage.role}`, sourceSessionKey, ts, parsedMessage.payload, title, modelId, workDir, parsedMessage.role, false, parsedMessage.repairHint);
283
- return;
284
- }
285
- if (itemType === 'function_call') {
286
- const name = typeof payload.name === 'string' ? payload.name : 'function_call';
287
- pushCodexToolEvent(events, filePath, lineOffset, itemType, sourceSessionKey, ts, name, title, modelId, workDir, parseStructuredString(payload.arguments));
288
- return;
289
- }
290
- if (itemType === 'function_call_output') {
291
- pushCodexToolEvent(events, filePath, lineOffset, itemType, sourceSessionKey, ts, 'function_call_output', title, modelId, workDir, payload.call_id, payload.output);
292
- return;
293
- }
294
- if (itemType === 'custom_tool_call') {
295
- const name = typeof payload.name === 'string' ? payload.name : 'custom_tool_call';
296
- const args = payload.input !== undefined ? { input: payload.input } : undefined;
297
- pushCodexToolEvent(events, filePath, lineOffset, itemType, sourceSessionKey, ts, name, title, modelId, workDir, args);
298
- return;
299
- }
300
- if (itemType === 'custom_tool_call_output') {
301
- const name = typeof payload.name === 'string' ? payload.name : 'custom_tool_call_output';
302
- const result = payload.output ?? payload.result ?? payload.content;
303
- pushCodexToolEvent(events, filePath, lineOffset, itemType, sourceSessionKey, ts, name, title, modelId, workDir, payload.call_id, result);
304
- return;
305
- }
306
- if (itemType === 'web_search_call') {
307
- const action = typeof payload.action === 'object' && payload.action !== null
308
- ? payload.action
309
- : null;
310
- pushCodexToolEvent(events, filePath, lineOffset, itemType, sourceSessionKey, ts, 'web_search', title, modelId, workDir, action ?? payload.query);
311
- return;
312
- }
313
- }
314
- function parseCodexEventMessage(events, filePath, lineOffset, payload, sourceSessionKey, ts, title, modelId, workDir) {
315
- const eventType = typeof payload.type === 'string' ? payload.type : '';
316
- if (!eventType)
317
- return;
318
- if (eventType === 'user_message') {
319
- const parsedUser = parseCodexUserMessage(payload);
320
- if (!parsedUser)
321
- return;
322
- pushCodexEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, parsedUser.payload, title, modelId, workDir, 'user', false, parsedUser.repairHint);
323
- return;
324
- }
325
- if (eventType === 'agent_message') {
326
- const text = typeof payload.message === 'string' ? normalizeText(payload.message) : '';
327
- if (!text || isSystemControlPayload(text))
328
- return;
329
- pushCodexEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, text, title, modelId, workDir);
330
- return;
331
- }
332
- if (eventType === 'turn_aborted' || eventType === 'error') {
333
- const text = typeof payload.message === 'string'
334
- ? normalizeText(payload.message)
335
- : typeof payload.error === 'string'
336
- ? normalizeText(payload.error)
337
- : '';
338
- if (!text)
339
- return;
340
- pushCodexEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, text, title, modelId, workDir, 'agent', true);
341
- return;
342
- }
343
- if (isCodexApprovalEventType(eventType)) {
344
- pushCodexEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, buildCodexApprovalPayload(payload), title, modelId, workDir, 'agent');
345
- return;
346
- }
347
- if (eventType === 'exec_command_end') {
348
- const command = Array.isArray(payload.command) ? payload.command : payload.parsed_cmd ?? payload.command;
349
- const exitCode = payload.exit_code ?? payload.exitCode;
350
- const output = [
351
- typeof payload.aggregated_output === 'string' ? payload.aggregated_output : '',
352
- exitCode != null ? `\n(exit ${String(exitCode)})` : '',
353
- ].join('');
354
- pushCodexToolEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, 'command_execution', title, modelId, workDir, { command }, output);
355
- return;
356
- }
357
- if (eventType === 'patch_apply_end') {
358
- pushCodexToolEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, 'apply_patch', title, modelId, workDir, payload.changes, {
359
- success: payload.success,
360
- stdout: payload.stdout,
361
- stderr: payload.stderr,
362
- });
363
- return;
364
- }
365
- if (eventType === 'mcp_tool_call_end') {
366
- const invocation = typeof payload.invocation === 'object' && payload.invocation !== null
367
- ? payload.invocation
368
- : null;
369
- const tool = typeof invocation?.tool === 'string' ? invocation.tool : 'mcp_tool_call';
370
- const args = {
371
- server: invocation?.server,
372
- ...(typeof invocation?.arguments === 'object' && invocation.arguments !== null
373
- ? invocation.arguments
374
- : {}),
375
- };
376
- pushCodexToolEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, tool, title, modelId, workDir, args, payload.result);
377
- return;
378
- }
379
- if (eventType === 'dynamic_tool_call_request') {
380
- const tool = typeof payload.tool === 'string' ? payload.tool : 'dynamic_tool_call';
381
- pushCodexToolEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, tool, title, modelId, workDir, payload.arguments);
382
- return;
383
- }
384
- if (eventType === 'dynamic_tool_call_response') {
385
- const tool = typeof payload.tool === 'string' ? payload.tool : 'dynamic_tool_call';
386
- pushCodexToolEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, tool, title, modelId, workDir, payload.callId ?? payload.call_id, payload.result ?? payload.output);
387
- return;
388
- }
389
- if (eventType === 'web_search_end') {
390
- const action = typeof payload.action === 'object' && payload.action !== null
391
- ? payload.action
392
- : null;
393
- pushCodexToolEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, 'web_search', title, modelId, workDir, action ?? payload.query, payload.query);
394
- return;
395
- }
396
- if (eventType === 'image_generation_end') {
397
- const savedPath = typeof payload.saved_path === 'string' ? payload.saved_path.trim() : '';
398
- if (!savedPath)
399
- return;
400
- pushCodexEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, buildImagePayload(savedPath), title, modelId, workDir);
401
- return;
402
- }
403
- if (eventType === 'view_image_tool_call') {
404
- pushCodexToolEvent(events, filePath, lineOffset, eventType, sourceSessionKey, ts, 'view_image', title, modelId, workDir, payload.path ?? payload.image_path ?? payload);
405
- }
406
- }
407
- function relativeProjectDir(cwd) {
408
- const home = os.homedir();
409
- if (cwd.startsWith(home))
410
- return cwd.slice(home.length).replace(/^\//, '') || '~';
411
- return cwd.replace(/\//g, '-');
412
- }
413
- function readCodexSessionMeta(filePath) {
414
- const fd = fs.openSync(filePath, 'r');
415
- try {
416
- const chunks = [];
417
- let position = 0;
418
- let firstLine = '';
419
- while (position < 1024 * 1024) {
420
- const buffer = Buffer.alloc(16 * 1024);
421
- const bytesRead = fs.readSync(fd, buffer, 0, buffer.length, position);
422
- if (bytesRead <= 0)
423
- break;
424
- const chunk = buffer.subarray(0, bytesRead);
425
- chunks.push(chunk);
426
- position += bytesRead;
427
- const combined = Buffer.concat(chunks);
428
- const newlineIndex = combined.indexOf(0x0a);
429
- if (newlineIndex >= 0) {
430
- firstLine = combined.subarray(0, newlineIndex).toString('utf8');
431
- break;
432
- }
433
- }
434
- if (!firstLine && chunks.length > 0) {
435
- firstLine = Buffer.concat(chunks).toString('utf8');
436
- }
437
- const parsed = safeParse(firstLine);
438
- if (!parsed || parsed.type !== 'session_meta') {
439
- return {
440
- sourceSessionKey: '',
441
- workDir: '',
442
- modelId: null,
443
- title: '',
444
- };
445
- }
446
- const payload = typeof parsed.payload === 'object' && parsed.payload !== null
447
- ? parsed.payload
448
- : null;
449
- if (!payload) {
450
- return {
451
- sourceSessionKey: '',
452
- workDir: '',
453
- modelId: null,
454
- title: '',
455
- };
456
- }
457
- const sourceSessionKey = typeof payload.id === 'string' ? payload.id : '';
458
- return {
459
- sourceSessionKey,
460
- workDir: typeof payload.cwd === 'string' ? payload.cwd : '',
461
- modelId: readCodexModelId(payload),
462
- title: lookupCodexThreadName(sourceSessionKey) ?? '',
463
- };
464
- }
465
- finally {
466
- fs.closeSync(fd);
467
- }
468
- return {
469
- sourceSessionKey: '',
470
- workDir: '',
471
- modelId: null,
472
- title: '',
473
- };
474
- }
475
- function readCodexModelId(payload) {
476
- const model = typeof payload.model === 'string' ? payload.model.trim() : '';
477
- return model || null;
478
- }
479
- function readCodexIndexTitle(parsed, sourceSessionKey) {
480
- const id = typeof parsed.id === 'string'
481
- ? parsed.id
482
- : typeof parsed.thread_id === 'string'
483
- ? parsed.thread_id
484
- : typeof parsed.session_id === 'string'
485
- ? parsed.session_id
486
- : '';
487
- if (id !== sourceSessionKey)
488
- return null;
489
- const title = typeof parsed.thread_name === 'string'
490
- ? parsed.thread_name
491
- : typeof parsed.title === 'string'
492
- ? parsed.title
493
- : '';
494
- const trimmed = title.trim();
495
- return trimmed ? trimmed.slice(0, 120) : null;
496
- }
497
- function lookupCodexThreadName(sourceSessionKey) {
498
- if (!sourceSessionKey)
499
- return null;
500
- const indexPath = path.join(os.homedir(), '.codex', 'session_index.jsonl');
501
- if (!fs.existsSync(indexPath))
502
- return null;
503
- let latestTitle = null;
504
- readJsonlLines(indexPath, 0, (line) => {
505
- if (!line.trim())
506
- return;
507
- const parsed = safeParse(line);
508
- if (!parsed)
509
- return;
510
- const title = readCodexIndexTitle(parsed, sourceSessionKey);
511
- if (title)
512
- latestTitle = title;
513
- });
514
- return latestTitle;
515
- }
516
- export function listCodexRolloutFiles() {
517
- const roots = [
518
- path.join(os.homedir(), '.codex', 'sessions'),
519
- path.join(os.homedir(), '.codex', 'archived_sessions'),
520
- ];
521
- const files = [];
522
- const walk = (dir) => {
523
- for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
524
- const full = path.join(dir, entry.name);
525
- if (entry.isDirectory())
526
- walk(full);
527
- else if (entry.isFile() && entry.name.endsWith('.jsonl'))
528
- files.push(full);
529
- }
530
- };
531
- for (const root of roots) {
532
- if (fs.existsSync(root))
533
- walk(root);
534
- }
535
- return [...new Set(files)].sort();
536
- }
537
- export function listClaudeTranscriptFiles() {
538
- const root = path.join(os.homedir(), '.claude', 'projects');
539
- if (!fs.existsSync(root))
540
- return [];
541
- const files = [];
542
- const walk = (dir) => {
543
- for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
544
- const full = path.join(dir, entry.name);
545
- if (entry.isDirectory()) {
546
- if (dir === root && shouldIgnoreClaudeProjectDir(entry.name))
547
- continue;
548
- walk(full);
549
- }
550
- else if (entry.isFile() && entry.name.endsWith('.jsonl'))
551
- files.push(full);
552
- }
553
- };
554
- walk(root);
555
- return files.sort();
556
- }
557
- export function lookupClaudeTranscriptCwd(sourceSessionKey) {
558
- if (!sourceSessionKey)
559
- return null;
560
- const match = listClaudeTranscriptFiles().find((filePath) => path.basename(filePath, '.jsonl') === sourceSessionKey);
561
- if (!match)
562
- return null;
563
- let found = null;
564
- readJsonlLines(match, 0, (line) => {
565
- if (found || !line.trim())
566
- return;
567
- const parsed = safeParse(line);
568
- if (!parsed)
569
- return;
570
- const cwd = readClaudeEventCwd(parsed);
571
- if (cwd)
572
- found = cwd;
573
- });
574
- return found;
575
- }
576
- export function parseCodexRolloutChunk(filePath, startOffset) {
577
- const events = [];
578
- let { sourceSessionKey, workDir, modelId, title } = readCodexSessionMeta(filePath);
579
- let pendingTerminal = false;
580
- const nextOffset = readJsonlLines(filePath, startOffset, (line, lineOffset) => {
581
- const parsed = safeParse(line);
582
- if (!parsed)
583
- return;
584
- const type = typeof parsed.type === 'string' ? parsed.type : '';
585
- const payload = typeof parsed.payload === 'object' && parsed.payload !== null
586
- ? parsed.payload
587
- : null;
588
- const ts = readTimestamp(parsed.timestamp);
589
- if (!payload || !ts)
590
- return;
591
- if (type === 'session_meta') {
592
- sourceSessionKey = typeof payload.id === 'string' ? payload.id : sourceSessionKey;
593
- workDir = typeof payload.cwd === 'string' ? payload.cwd : workDir;
594
- modelId = readCodexModelId(payload) ?? modelId;
595
- if (!title)
596
- title = lookupCodexThreadName(sourceSessionKey) ?? '';
597
- return;
598
- }
599
- if (!sourceSessionKey)
600
- return;
601
- if (type === 'response_item') {
602
- const parsedMessage = parseCodexResponseMessage(payload);
603
- if (parsedMessage?.role === 'user' && parsedMessage.titleText && !title) {
604
- title = parsedMessage.titleText.slice(0, 80);
605
- }
606
- parseCodexResponseItem(events, filePath, lineOffset, payload, sourceSessionKey, ts, title, modelId, workDir);
607
- return;
608
- }
609
- if (type === 'event_msg') {
610
- const eventType = typeof payload.type === 'string' ? payload.type : '';
611
- if (isCodexTerminalEventType(eventType)) {
612
- for (let i = events.length - 1; i >= 0; i -= 1) {
613
- const event = events[i];
614
- if (event?.agentType !== 'codex')
615
- continue;
616
- if (event.role !== 'agent')
617
- continue;
618
- if (isToolPayload(event.payload))
619
- continue;
620
- event.terminal = true;
621
- pendingTerminal = false;
622
- break;
623
- }
624
- return;
625
- }
626
- if (eventType === 'user_message') {
627
- const parsedUser = parseCodexUserMessage(payload);
628
- if (parsedUser?.titleText && !title)
629
- title = parsedUser.titleText.slice(0, 80);
630
- if (parsedUser) {
631
- const duplicateIndex = findDuplicateCodexChatEventIndex(events, 'user', parsedUser.payload, ts);
632
- if (duplicateIndex >= 0)
633
- events.splice(duplicateIndex, 1);
634
- }
635
- }
636
- else if (eventType === 'agent_message') {
637
- const text = typeof payload.message === 'string' ? normalizeText(payload.message) : '';
638
- if (text && !isSystemControlPayload(text)) {
639
- const duplicateIndex = findDuplicateCodexChatEventIndex(events, 'agent', text, ts);
640
- if (duplicateIndex >= 0)
641
- events.splice(duplicateIndex, 1);
642
- }
643
- }
644
- const beforeCount = events.length;
645
- parseCodexEventMessage(events, filePath, lineOffset, payload, sourceSessionKey, ts, title, modelId, workDir);
646
- if (pendingTerminal && events.length > beforeCount) {
647
- events[events.length - 1].terminal = true;
648
- pendingTerminal = false;
649
- }
650
- }
651
- });
652
- return { nextOffset, events };
653
- }
654
- export function parseClaudeTranscriptChunk(filePath, startOffset) {
655
- const fileSize = fs.statSync(filePath).size;
656
- if (isClaudeSubagentTranscript(filePath) || shouldIgnoreClaudeTranscriptPath(filePath)) {
657
- return { nextOffset: fileSize, events: [] };
658
- }
659
- const events = [];
660
- const sourceSessionKey = path.basename(filePath, '.jsonl');
661
- const fallbackWorkDir = relativeProjectDir(path.dirname(filePath).replace(path.join(os.homedir(), '.claude', 'projects') + path.sep, ''));
662
- if (shouldIgnoreNativeScanPath(fallbackWorkDir)) {
663
- return { nextOffset: fileSize, events: [] };
664
- }
665
- let title = '';
666
- const nextOffset = readJsonlLines(filePath, startOffset, (line, lineOffset) => {
667
- const parsed = safeParse(line);
668
- if (!parsed)
669
- return;
670
- const ts = readTimestamp(parsed.timestamp);
671
- const type = typeof parsed.type === 'string' ? parsed.type : '';
672
- if (!ts || !type)
673
- return;
674
- const eventCwd = readClaudeEventCwd(parsed);
675
- if (eventCwd && shouldIgnoreNativeScanPath(eventCwd))
676
- return;
677
- if (type === 'user') {
678
- const message = typeof parsed.message === 'object' && parsed.message !== null
679
- ? parsed.message
680
- : null;
681
- const text = typeof message?.content === 'string' ? normalizeText(message.content) : '';
682
- if (!text)
683
- return;
684
- if (!title)
685
- title = text.slice(0, 80);
686
- events.push({
687
- agentType: 'claude',
688
- sourceMode: 'claude_transcript_import',
689
- sourceSessionKey,
690
- sourceEventKey: makeEventKey(filePath, lineOffset, 'user'),
691
- cursor: makeCursor(filePath, lineOffset),
692
- role: 'user',
693
- ts,
694
- payload: text,
695
- title,
696
- workDir: eventCwd ?? fallbackWorkDir,
697
- });
698
- }
699
- else if (type === 'assistant') {
700
- const message = typeof parsed.message === 'object' && parsed.message !== null
701
- ? parsed.message
702
- : null;
703
- const content = Array.isArray(message?.content) ? message.content : [];
704
- const text = normalizeText(content
705
- .map((part) => typeof part === 'object' && part !== null && typeof part.text === 'string'
706
- ? part.text
707
- : '')
708
- .filter(Boolean)
709
- .join('\n\n'));
710
- if (!text)
711
- return;
712
- const modelId = typeof message?.model === 'string' ? message.model : null;
713
- events.push({
714
- agentType: 'claude',
715
- sourceMode: 'claude_transcript_import',
716
- sourceSessionKey,
717
- sourceEventKey: makeEventKey(filePath, lineOffset, 'assistant'),
718
- cursor: makeCursor(filePath, lineOffset),
719
- role: 'agent',
720
- ts,
721
- payload: text,
722
- title,
723
- modelId,
724
- workDir: eventCwd ?? fallbackWorkDir,
725
- });
726
- }
727
- });
728
- return { nextOffset, events };
729
- }
1
+ import T from"node:fs";import j from"node:os";import x from"node:path";import{buildApprovalPendingPayload as V,buildUserMessagePayload as k,isSystemControlPayload as A,isToolPayload as F}from"@shennian/wire";import{listOpenCodeSessionFiles as jt,parseOpenCodeSessionFile as At,parseOpenCodeSessionSnapshot as Mt}from"./opencode-parser.js";import{buildImagePayload as X,buildToolPayload as Y,inferMimeType as E,makeCursor as I,makeEventKey as w,normalizeText as h,parseStructuredString as Z,readClaudeEventCwd as N,readJsonlLines as v,readTimestamp as q,safeParse as M,isClaudeSubagentTranscript as D,shouldIgnoreClaudeProjectDir as K,shouldIgnoreClaudeTranscriptPath as O,shouldIgnoreNativeScanPath as R}from"./parser-common.js";function P(e){if(typeof e=="string"){const s=e.trim();return s?{path:s,name:x.basename(s)||"image.png",mimeType:E(s),kind:"image"}:null}if(typeof e!="object"||e===null)return null;const r=e,n=typeof r.path=="string"?r.path:typeof r.file_path=="string"?r.file_path:typeof r.saved_path=="string"?r.saved_path:"";if(!n.trim())return null;const t=typeof r.name=="string"&&r.name.trim()?r.name:x.basename(n)||"image.png",o=typeof r.mimeType=="string"&&r.mimeType.trim()?r.mimeType:E(n);return{path:n,name:t,mimeType:o,kind:"image"}}function U(e){return Array.isArray(e)?e.map(n=>{if(typeof n=="string")return n;if(typeof n=="object"&&n!==null){const t=n;return typeof t.text=="string"?t.text:""}return""}).map(n=>h(n)).filter(Boolean).join(`
2
+
3
+ `):""}function B(e){const r=h(e);if(!r)return{text:"",strippedWrapper:!1};const n=r.match(/My request for Codex:\s*([\s\S]*)$/i);return n&&n[1]?{text:tt(n[1]),strippedWrapper:!0}:{text:r,strippedWrapper:!1}}function tt(e){return h(e.replace(/<image>\s*<\/image>/gi,""))}function z(e){const r=h(e);if(!r)return!1;const n=r.startsWith("# AGENTS.md instructions for ")&&r.includes("<INSTRUCTIONS>")&&r.includes("</INSTRUCTIONS>"),t=r.includes("<environment_context>")&&r.includes("</environment_context>");return n&&t}function H(e){const r=U(e.text_elements),n=Array.isArray(e.input)?U(e.input):"",t=typeof e.message=="string"?B(e.message):{text:"",strippedWrapper:!1},o=t.text,s=r||n||o,u=t.strippedWrapper?"codex_app_context_wrapper":void 0,a=Array.isArray(e.local_images)?e.local_images.map(P).filter(l=>l!=null):[];return!s&&a.length===0||A(s)&&a.length===0||z(s)&&a.length===0?null:a.length>0?{payload:k(s,a),titleText:s,repairHint:u}:{payload:s,titleText:s,repairHint:u}}function et(e){return e==="turn_completed"||e==="turn_complete"||e==="task_complete"}function nt(e){return/approval|permission|confirm|user[_-]?input|input[_-]?required/i.test(e)}function rt(e){const r=typeof e.command=="string"?e.command:Array.isArray(e.command)?e.command.join(" "):"",n=typeof e.prompt=="string"?e.prompt:typeof e.reason=="string"?e.reason:typeof e.message=="string"?e.message:r?`Codex \u8BF7\u6C42\u6267\u884C\u547D\u4EE4\uFF1A${r}`:"Codex \u6B63\u5728\u7B49\u5F85\u7528\u6237\u786E\u8BA4\u540E\u7EE7\u7EED\u3002";return V({title:"\u9700\u8981\u7528\u6237\u786E\u8BA4",content:n,source:"codex",actionHint:"\u5F53\u524D\u795E\u5FF5\u6682\u4E0D\u652F\u6301\u8FDC\u7A0B\u786E\u8BA4\uFF0C\u8BF7\u56DE\u5230\u8FD0\u884C Codex \u7684\u7535\u8111/\u7EC8\u7AEF\u5B8C\u6210\u786E\u8BA4\u3002"})}function $(e,r){return Array.isArray(e)?h(e.map(n=>{if(typeof n=="string")return n;if(typeof n!="object"||n===null)return"";const t=n;return t.type!==r?"":typeof t.text=="string"?t.text:""}).filter(Boolean).join(`
4
+
5
+ `)):""}function ot(e){if(!Array.isArray(e))return[];const r=[];for(const n of e){if(typeof n!="object"||n===null)continue;const t=n;if(t.type!=="input_image")continue;const o=typeof t.path=="string"?t.path:typeof t.file_path=="string"?t.file_path:typeof t.saved_path=="string"?t.saved_path:typeof t.image_path=="string"?t.image_path:"";o.trim()&&r.push({path:o,name:x.basename(o)||"image.png",mimeType:E(o),kind:"image"})}return r}function L(e){if(e.type!=="message")return null;const r=e.role==="assistant"?"agent":e.role==="user"?"user":null;if(!r)return null;if(r==="agent"){const s=$(e.content,"output_text");return A(s)?null:s?{role:r,payload:s,titleText:s}:null}const n=B($(e.content,"input_text")),t=n.text,o=ot(e.content);return!t&&o.length===0||A(t)&&o.length===0||z(t)&&o.length===0?null:{role:r,payload:o.length>0?k(t,o):t,titleText:t,repairHint:n.strippedWrapper?"codex_app_context_wrapper":void 0}}function J(e){if(!e)return"";try{const r=JSON.parse(e);if(typeof r=="object"&&r!==null){const n=r;if(n.type==="user"&&typeof n.content=="string")return h(n.content)}}catch{}return h(e)}function st(e,r,n,t){return e.agentType!=="codex"||e.role!==r||F(e.payload)||Math.abs(e.ts-t)>300*1e3?!1:J(e.payload)===J(n)}function W(e,r,n,t){for(let o=e.length-1;o>=0;o-=1){const s=e[o];if(s){if(st(s,r,n,t))return o;if(s.agentType==="codex"&&Math.abs(s.ts-t)>300*1e3)break}}return-1}function b(e,r,n,t,o,s,u,a,l,c,i="agent",f=!1,m){u&&e.push({agentType:"codex",sourceMode:"codex_rollout_import",sourceSessionKey:o,sourceEventKey:w(r,n,t),cursor:I(r,n),role:i,ts:s,payload:u,title:a,modelId:l,workDir:c,terminal:f,repairHint:m})}function C(e,r,n,t,o,s,u,a,l,c,i,f){b(e,r,n,t,o,s,Y(u,i,f),a,l,c)}function it(e,r,n,t,o,s,u,a,l){const c=typeof t.type=="string"?t.type:"";if(c){if(c==="message"){const i=L(t);if(!i||W(e,i.role,i.payload,s)>=0)return;b(e,r,n,`${c}:${i.role}`,o,s,i.payload,u,a,l,i.role,!1,i.repairHint);return}if(c==="function_call"){const i=typeof t.name=="string"?t.name:"function_call";C(e,r,n,c,o,s,i,u,a,l,Z(t.arguments));return}if(c==="function_call_output"){C(e,r,n,c,o,s,"function_call_output",u,a,l,t.call_id,t.output);return}if(c==="custom_tool_call"){const i=typeof t.name=="string"?t.name:"custom_tool_call",f=t.input!==void 0?{input:t.input}:void 0;C(e,r,n,c,o,s,i,u,a,l,f);return}if(c==="custom_tool_call_output"){const i=typeof t.name=="string"?t.name:"custom_tool_call_output",f=t.output??t.result??t.content;C(e,r,n,c,o,s,i,u,a,l,t.call_id,f);return}if(c==="web_search_call"){const i=typeof t.action=="object"&&t.action!==null?t.action:null;C(e,r,n,c,o,s,"web_search",u,a,l,i??t.query);return}}}function ct(e,r,n,t,o,s,u,a,l){const c=typeof t.type=="string"?t.type:"";if(c){if(c==="user_message"){const i=H(t);if(!i)return;b(e,r,n,c,o,s,i.payload,u,a,l,"user",!1,i.repairHint);return}if(c==="agent_message"){const i=typeof t.message=="string"?h(t.message):"";if(!i||A(i))return;b(e,r,n,c,o,s,i,u,a,l);return}if(c==="turn_aborted"||c==="error"){const i=typeof t.message=="string"?h(t.message):typeof t.error=="string"?h(t.error):"";if(!i)return;b(e,r,n,c,o,s,i,u,a,l,"agent",!0);return}if(nt(c)){b(e,r,n,c,o,s,rt(t),u,a,l,"agent");return}if(c==="exec_command_end"){const i=Array.isArray(t.command)?t.command:t.parsed_cmd??t.command,f=t.exit_code??t.exitCode,m=[typeof t.aggregated_output=="string"?t.aggregated_output:"",f!=null?`
6
+ (exit ${String(f)})`:""].join("");C(e,r,n,c,o,s,"command_execution",u,a,l,{command:i},m);return}if(c==="patch_apply_end"){C(e,r,n,c,o,s,"apply_patch",u,a,l,t.changes,{success:t.success,stdout:t.stdout,stderr:t.stderr});return}if(c==="mcp_tool_call_end"){const i=typeof t.invocation=="object"&&t.invocation!==null?t.invocation:null,f=typeof i?.tool=="string"?i.tool:"mcp_tool_call",m={server:i?.server,...typeof i?.arguments=="object"&&i.arguments!==null?i.arguments:{}};C(e,r,n,c,o,s,f,u,a,l,m,t.result);return}if(c==="dynamic_tool_call_request"){const i=typeof t.tool=="string"?t.tool:"dynamic_tool_call";C(e,r,n,c,o,s,i,u,a,l,t.arguments);return}if(c==="dynamic_tool_call_response"){const i=typeof t.tool=="string"?t.tool:"dynamic_tool_call";C(e,r,n,c,o,s,i,u,a,l,t.callId??t.call_id,t.result??t.output);return}if(c==="web_search_end"){const i=typeof t.action=="object"&&t.action!==null?t.action:null;C(e,r,n,c,o,s,"web_search",u,a,l,i??t.query,t.query);return}if(c==="image_generation_end"){const i=typeof t.saved_path=="string"?t.saved_path.trim():"";if(!i)return;b(e,r,n,c,o,s,X(i),u,a,l);return}c==="view_image_tool_call"&&C(e,r,n,c,o,s,"view_image",u,a,l,t.path??t.image_path??t)}}function ut(e){const r=j.homedir();return e.startsWith(r)?e.slice(r.length).replace(/^\//,"")||"~":e.replace(/\//g,"-")}function at(e){const r=T.openSync(e,"r");try{const n=[];let t=0,o="";for(;t<1024*1024;){const l=Buffer.alloc(16384),c=T.readSync(r,l,0,l.length,t);if(c<=0)break;const i=l.subarray(0,c);n.push(i),t+=c;const f=Buffer.concat(n),m=f.indexOf(10);if(m>=0){o=f.subarray(0,m).toString("utf8");break}}!o&&n.length>0&&(o=Buffer.concat(n).toString("utf8"));const s=M(o);if(!s||s.type!=="session_meta")return{sourceSessionKey:"",workDir:"",modelId:null,title:""};const u=typeof s.payload=="object"&&s.payload!==null?s.payload:null;if(!u)return{sourceSessionKey:"",workDir:"",modelId:null,title:""};const a=typeof u.id=="string"?u.id:"";return{sourceSessionKey:a,workDir:typeof u.cwd=="string"?u.cwd:"",modelId:G(u),title:Q(a)??""}}finally{T.closeSync(r)}return{sourceSessionKey:"",workDir:"",modelId:null,title:""}}function G(e){return(typeof e.model=="string"?e.model.trim():"")||null}function lt(e,r){if((typeof e.id=="string"?e.id:typeof e.thread_id=="string"?e.thread_id:typeof e.session_id=="string"?e.session_id:"")!==r)return null;const o=(typeof e.thread_name=="string"?e.thread_name:typeof e.title=="string"?e.title:"").trim();return o?o.slice(0,120):null}function Q(e){if(!e)return null;const r=x.join(j.homedir(),".codex","session_index.jsonl");if(!T.existsSync(r))return null;let n=null;return v(r,0,t=>{if(!t.trim())return;const o=M(t);if(!o)return;const s=lt(o,e);s&&(n=s)}),n}function _t(){const e=[x.join(j.homedir(),".codex","sessions"),x.join(j.homedir(),".codex","archived_sessions")],r=[],n=t=>{for(const o of T.readdirSync(t,{withFileTypes:!0})){const s=x.join(t,o.name);o.isDirectory()?n(s):o.isFile()&&o.name.endsWith(".jsonl")&&r.push(s)}};for(const t of e)T.existsSync(t)&&n(t);return[...new Set(r)].sort()}function ft(){const e=x.join(j.homedir(),".claude","projects");if(!T.existsSync(e))return[];const r=[],n=t=>{for(const o of T.readdirSync(t,{withFileTypes:!0})){const s=x.join(t,o.name);if(o.isDirectory()){if(t===e&&K(o.name))continue;n(s)}else o.isFile()&&o.name.endsWith(".jsonl")&&r.push(s)}};return n(e),r.sort()}function yt(e){if(!e)return null;const r=ft().find(t=>x.basename(t,".jsonl")===e);if(!r)return null;let n=null;return v(r,0,t=>{if(n||!t.trim())return;const o=M(t);if(!o)return;const s=N(o);s&&(n=s)}),n}function ht(e,r){const n=[];let{sourceSessionKey:t,workDir:o,modelId:s,title:u}=at(e),a=!1;return{nextOffset:v(e,r,(c,i)=>{const f=M(c);if(!f)return;const m=typeof f.type=="string"?f.type:"",p=typeof f.payload=="object"&&f.payload!==null?f.payload:null,_=q(f.timestamp);if(!(!p||!_)){if(m==="session_meta"){t=typeof p.id=="string"?p.id:t,o=typeof p.cwd=="string"?p.cwd:o,s=G(p)??s,u||(u=Q(t)??"");return}if(t){if(m==="response_item"){const y=L(p);y?.role==="user"&&y.titleText&&!u&&(u=y.titleText.slice(0,80)),it(n,e,i,p,t,_,u,s,o);return}if(m==="event_msg"){const y=typeof p.type=="string"?p.type:"";if(et(y)){for(let d=n.length-1;d>=0;d-=1){const g=n[d];if(g?.agentType==="codex"&&g.role==="agent"&&!F(g.payload)){g.terminal=!0,a=!1;break}}return}if(y==="user_message"){const d=H(p);if(d?.titleText&&!u&&(u=d.titleText.slice(0,80)),d){const g=W(n,"user",d.payload,_);g>=0&&n.splice(g,1)}}else if(y==="agent_message"){const d=typeof p.message=="string"?h(p.message):"";if(d&&!A(d)){const g=W(n,"agent",d,_);g>=0&&n.splice(g,1)}}const S=n.length;ct(n,e,i,p,t,_,u,s,o),a&&n.length>S&&(n[n.length-1].terminal=!0,a=!1)}}}}),events:n}}function Ct(e,r){const n=T.statSync(e).size;if(D(e)||O(e))return{nextOffset:n,events:[]};const t=[],o=x.basename(e,".jsonl"),s=ut(x.dirname(e).replace(x.join(j.homedir(),".claude","projects")+x.sep,""));if(R(s))return{nextOffset:n,events:[]};let u="";return{nextOffset:v(e,r,(l,c)=>{const i=M(l);if(!i)return;const f=q(i.timestamp),m=typeof i.type=="string"?i.type:"";if(!f||!m)return;const p=N(i);if(!(p&&R(p))){if(m==="user"){const _=typeof i.message=="object"&&i.message!==null?i.message:null,y=typeof _?.content=="string"?h(_.content):"";if(!y)return;u||(u=y.slice(0,80)),t.push({agentType:"claude",sourceMode:"claude_transcript_import",sourceSessionKey:o,sourceEventKey:w(e,c,"user"),cursor:I(e,c),role:"user",ts:f,payload:y,title:u,workDir:p??s})}else if(m==="assistant"){const _=typeof i.message=="object"&&i.message!==null?i.message:null,y=Array.isArray(_?.content)?_.content:[],S=h(y.map(g=>typeof g=="object"&&g!==null&&typeof g.text=="string"?g.text:"").filter(Boolean).join(`
7
+
8
+ `));if(!S)return;const d=typeof _?.model=="string"?_.model:null;t.push({agentType:"claude",sourceMode:"claude_transcript_import",sourceSessionKey:o,sourceEventKey:w(e,c,"assistant"),cursor:I(e,c),role:"agent",ts:f,payload:S,title:u,modelId:d,workDir:p??s})}}}),events:t}}export{ft as listClaudeTranscriptFiles,_t as listCodexRolloutFiles,jt as listOpenCodeSessionFiles,yt as lookupClaudeTranscriptCwd,Ct as parseClaudeTranscriptChunk,ht as parseCodexRolloutChunk,At as parseOpenCodeSessionFile,Mt as parseOpenCodeSessionSnapshot};